summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMojca Miklavec <mojca.miklavec@gmail.com>2012-05-14 17:38:55 +0000
committerMojca Miklavec <mojca.miklavec@gmail.com>2012-05-14 17:38:55 +0000
commit15995e10bfc68edf79970c4ea4fbb6678566c46e (patch)
tree2de7ca2a83f2d37ef043ad7429a5cb945bb79ddb
parentc9a39f716f1e5ec820ed3aab2c9aef25c5a9d730 (diff)
ConTeXt 2012.05.14 16:00
git-svn-id: svn://tug.org/texlive/trunk@26371 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Build/source/texk/texlive/context/Makefile.am1
-rw-r--r--Build/source/texk/texlive/context/Makefile.in3
-rwxr-xr-xBuild/source/texk/texlive/context/mtxrun3992
-rwxr-xr-xBuild/source/texk/texlive/context/rlxtools2
-rwxr-xr-xMaster/bin/alpha-linux/mtxrun3992
-rwxr-xr-xMaster/bin/amd64-freebsd/mtxrun3992
-rwxr-xr-xMaster/bin/amd64-kfreebsd/mtxrun3992
-rwxr-xr-xMaster/bin/i386-cygwin/mtxrun3992
-rwxr-xr-xMaster/bin/i386-freebsd/mtxrun3992
-rwxr-xr-xMaster/bin/i386-kfreebsd/mtxrun3992
-rwxr-xr-xMaster/bin/i386-linux/mtxrun3992
-rwxr-xr-xMaster/bin/i386-netbsd/mtxrun3992
-rwxr-xr-xMaster/bin/i386-solaris/mtxrun3992
-rwxr-xr-xMaster/bin/mips-irix/mtxrun3992
-rwxr-xr-xMaster/bin/powerpc-aix/mtxrun3992
-rwxr-xr-xMaster/bin/powerpc-linux/mtxrun3992
-rwxr-xr-xMaster/bin/sparc-linux/mtxrun3992
-rwxr-xr-xMaster/bin/sparc-solaris/mtxrun3992
-rwxr-xr-xMaster/bin/universal-darwin/mtxrun3992
-rw-r--r--[-rwxr-xr-x]Master/bin/win32/mtxrun.dllbin9216 -> 9216 bytes
-rw-r--r--[-rwxr-xr-x]Master/bin/win32/mtxrun.lua3992
-rwxr-xr-xMaster/bin/x86_64-darwin/mtxrun3992
-rwxr-xr-xMaster/bin/x86_64-linux/mtxrun3992
-rwxr-xr-xMaster/bin/x86_64-solaris/mtxrun3992
-rw-r--r--Master/texmf-dist/context/data/scite/cont-cs-scite.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/cont-cz-scite.properties76
-rw-r--r--Master/texmf-dist/context/data/scite/cont-de-scite.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/cont-en-scite.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/cont-fr-scite.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/cont-it-scite.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/cont-nl-scite.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/cont-pe-scite.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/cont-ro-scite.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/cont-xx-scite.properties178
-rw-r--r--Master/texmf-dist/context/data/scite/cscite.rme50
-rw-r--r--Master/texmf-dist/context/data/scite/latex-scite.properties2
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-context.lua4
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-interfaces.lua10
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metafun.lua4
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metapost.lua7
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-tex.lua9
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-cld.lua23
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua-longstring.lua22
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua.lua264
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-mps.lua142
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf-object.lua117
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf-xref.lua51
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf.lua80
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-tex.lua464
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-txt.lua86
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-cdata.lua30
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-comment.lua39
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml.lua334
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/scite-context-lexer.lua825
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme-keep.lua233
-rw-r--r--Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme.lua224
-rw-r--r--Master/texmf-dist/context/data/scite/metafun-scite.properties19
-rw-r--r--Master/texmf-dist/context/data/scite/metapost.properties1
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-data-context.properties129
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-data-interfaces.properties1276
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-data-metafun.properties53
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-data-metapost.properties96
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-data-tex.properties238
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-external.properties85
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-internal.properties82
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-readme.pdfbin0 -> 205340 bytes
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-readme.tex858
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-user.properties15
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-visual.pdf1364
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-visual.pngbin0 -> 77849 bytes
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context-visual.tex52
-rw-r--r--Master/texmf-dist/context/data/scite/scite-context.properties (renamed from Master/texmf-dist/context/data/scite/context.properties)471
-rw-r--r--Master/texmf-dist/context/data/scite/scite-ctx-context.properties49
-rw-r--r--Master/texmf-dist/context/data/scite/scite-ctx-example.properties23
-rw-r--r--Master/texmf-dist/context/data/scite/scite-ctx.lua28
-rw-r--r--Master/texmf-dist/context/data/scite/scite-ctx.properties5
-rw-r--r--Master/texmf-dist/context/data/scite/scite-ctx.readme19
-rw-r--r--Master/texmf-dist/context/data/scite/scite-metapost.properties76
-rw-r--r--Master/texmf-dist/context/data/scite/scite-pragma.properties38
-rw-r--r--Master/texmf-dist/context/data/scite/scite-tex.properties116
-rw-r--r--Master/texmf-dist/context/data/scite/tex.properties1
-rw-r--r--Master/texmf-dist/context/data/textadept/context.lua710
-rw-r--r--Master/texmf-dist/context/data/textpad/textpad-context-template.txt54
-rw-r--r--Master/texmf-dist/fonts/map/pdftex/context/original-base.map3
-rw-r--r--Master/texmf-dist/metapost/context/base/metafun.mp75
-rw-r--r--Master/texmf-dist/metapost/context/base/metafun.mpii65
-rw-r--r--Master/texmf-dist/metapost/context/base/metafun.mpiv52
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-abck.mpiv269
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-apos.mpiv102
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-asnc.mpiv177
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-back.mp3
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-base.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-base.mp)0
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-base.mpiv867
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-butt.mp75
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-butt.mpii77
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-butt.mpiv77
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-char.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-char.mp)67
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-char.mpiv1116
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-chem.mpiv (renamed from Master/texmf-dist/metapost/context/base/mp-chem.mp)93
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-core.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-core.mp)8
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-core.mpiv1558
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-crop.mpiv194
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-figs.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-figs.mp)31
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-figs.mpiv47
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-fobg.mp3
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-form.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-form.mp)30
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-form.mpiv30
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-func.mp59
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-func.mpii58
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-func.mpiv78
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-grid.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-grid.mp)5
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-grid.mpiv142
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-grph.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-grph.mp)68
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-grph.mpiv259
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-idea.mpiv30
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-mlib.mp533
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-mlib.mpiv616
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-page.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-page.mp)187
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-page.mpiv322
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-shap.mp307
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-shap.mpii206
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-shap.mpiv218
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-spec.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-spec.mp)6
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-step.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-step.mp)53
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-step.mpiv376
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-text.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-text.mp)3
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-text.mpiv163
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-tool.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-tool.mp)75
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-tool.mpiv2183
-rw-r--r--Master/texmf-dist/metapost/context/base/mp-txts.mpii (renamed from Master/texmf-dist/metapost/context/base/mp-txts.mp)3
-rw-r--r--Master/texmf-dist/scripts/context/lua/luatools.rme3
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-chars.lua87
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-check.lua180
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-context.lua53
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-convert.lua87
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-epub.lua166
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-fonts.lua20
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-grep.lua125
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-interface.lua280
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-modules.lua72
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-pdf.lua117
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-rsync.lua168
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-scite.lua337
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua1
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-server.lua60
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-tools.lua2
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-update.lua111
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtx-watch.lua29
-rwxr-xr-xMaster/texmf-dist/scripts/context/lua/mtxrun.lua3992
-rw-r--r--Master/texmf-dist/scripts/context/lua/mtxrun.rme18
-rw-r--r--Master/texmf-dist/scripts/context/ruby/ctxtools.rb8
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/mswin/metatex.exe (renamed from Master/texmf-dist/scripts/context/stubs/mswin/pstopdf.exe)bin6144 -> 6144 bytes
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/mswin/mptopdf.exe (renamed from Master/texmf-dist/scripts/context/stubs/mswin/rlxtools.exe)bin6144 -> 6144 bytes
-rw-r--r--[-rwxr-xr-x]Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dllbin9216 -> 9216 bytes
-rw-r--r--[-rwxr-xr-x]Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua3992
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/mswin/mtxworks.exe (renamed from Master/texmf-dist/scripts/context/stubs/mswin/ctxtools.exe)bin6144 -> 6144 bytes
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/unix/ctxtools2
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/unix/metatex2
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/unix/mptopdf2
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/unix/mtxrun3992
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/unix/mtxworks2
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/unix/pstopdf2
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/unix/rlxtools2
-rw-r--r--Master/texmf-dist/tex/context/base/anch-bar.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/anch-bar.mkiv104
-rw-r--r--Master/texmf-dist/tex/context/base/anch-bck.mkvi534
-rw-r--r--Master/texmf-dist/tex/context/base/anch-pgr.lua671
-rw-r--r--Master/texmf-dist/tex/context/base/anch-pgr.mkii9
-rw-r--r--Master/texmf-dist/tex/context/base/anch-pgr.mkiv1698
-rw-r--r--Master/texmf-dist/tex/context/base/anch-pos.lua924
-rw-r--r--Master/texmf-dist/tex/context/base/anch-pos.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/anch-pos.mkiv787
-rw-r--r--Master/texmf-dist/tex/context/base/anch-snc.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/anch-snc.mkiv60
-rw-r--r--Master/texmf-dist/tex/context/base/anch-tab.mkiv375
-rw-r--r--Master/texmf-dist/tex/context/base/attr-col.lua12
-rw-r--r--Master/texmf-dist/tex/context/base/attr-col.mkiv64
-rw-r--r--Master/texmf-dist/tex/context/base/attr-eff.mkiv17
-rw-r--r--Master/texmf-dist/tex/context/base/attr-ini.lua67
-rw-r--r--Master/texmf-dist/tex/context/base/attr-ini.mkiv70
-rw-r--r--Master/texmf-dist/tex/context/base/attr-lay.lua64
-rw-r--r--Master/texmf-dist/tex/context/base/attr-lay.mkiv47
-rw-r--r--Master/texmf-dist/tex/context/base/attr-neg.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/attr-neg.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/back-exp.lua2707
-rw-r--r--Master/texmf-dist/tex/context/base/back-exp.mkiv96
-rw-r--r--Master/texmf-dist/tex/context/base/back-ini.lua13
-rw-r--r--Master/texmf-dist/tex/context/base/back-ini.mkiv44
-rw-r--r--Master/texmf-dist/tex/context/base/back-pdf.lua596
-rw-r--r--Master/texmf-dist/tex/context/base/back-pdf.mkiv204
-rw-r--r--Master/texmf-dist/tex/context/base/back-swf.mkiv90
-rw-r--r--Master/texmf-dist/tex/context/base/back-u3d.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/bibl-bib.lua10
-rw-r--r--Master/texmf-dist/tex/context/base/bibl-bib.mkiv33
-rw-r--r--Master/texmf-dist/tex/context/base/bibl-tra.lua7
-rw-r--r--Master/texmf-dist/tex/context/base/bibl-tra.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/bibl-tra.mkiv103
-rw-r--r--Master/texmf-dist/tex/context/base/blob-ini.lua65
-rw-r--r--Master/texmf-dist/tex/context/base/blob-ini.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-default.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-escaped.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-lua.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-lua.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-mp.lua115
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-mp.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-nested.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-parsed-xml.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-tex.mkiv33
-rw-r--r--Master/texmf-dist/tex/context/base/buff-imp-xml.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-ini.lua148
-rw-r--r--Master/texmf-dist/tex/context/base/buff-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-ini.mkiv210
-rw-r--r--Master/texmf-dist/tex/context/base/buff-par.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/buff-ver.lua171
-rw-r--r--Master/texmf-dist/tex/context/base/buff-ver.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/buff-ver.mkiv580
-rw-r--r--Master/texmf-dist/tex/context/base/bxml-apa.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/catc-act.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/catc-act.mkiv59
-rw-r--r--Master/texmf-dist/tex/context/base/catc-ctx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/catc-ctx.mkiv57
-rw-r--r--Master/texmf-dist/tex/context/base/catc-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/catc-def.mkiv119
-rw-r--r--Master/texmf-dist/tex/context/base/catc-ini.lua7
-rw-r--r--Master/texmf-dist/tex/context/base/catc-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/catc-ini.mkiv390
-rw-r--r--Master/texmf-dist/tex/context/base/catc-sym.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/catc-sym.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/catc-xml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/catc-xml.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/char-act.mkiv95
-rw-r--r--Master/texmf-dist/tex/context/base/char-cjk.lua18
-rw-r--r--Master/texmf-dist/tex/context/base/char-def.lua43547
-rw-r--r--Master/texmf-dist/tex/context/base/char-enc.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/char-ent.lua2257
-rw-r--r--Master/texmf-dist/tex/context/base/char-ini.lua95
-rw-r--r--Master/texmf-dist/tex/context/base/char-ini.mkiv10
-rw-r--r--Master/texmf-dist/tex/context/base/char-utf.lua66
-rw-r--r--Master/texmf-dist/tex/context/base/char-utf.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/chem-ini.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/chem-str.lua35
-rw-r--r--Master/texmf-dist/tex/context/base/chem-str.mkiv82
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-bas.lua140
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-bas.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-com.lua72
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-com.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-ini.lua517
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-ini.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-int.lua67
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-int.mkiv10
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-ver.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/cldf-ver.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/colo-ema.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/colo-ext.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/colo-ext.mkiv104
-rw-r--r--Master/texmf-dist/tex/context/base/colo-grp.mkiv168
-rw-r--r--Master/texmf-dist/tex/context/base/colo-hex.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/colo-imp-dem.mkiv260
-rw-r--r--Master/texmf-dist/tex/context/base/colo-imp-ema.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/colo-imp-rgb.mkiv313
-rw-r--r--Master/texmf-dist/tex/context/base/colo-imp-xwi.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/colo-ini.lua193
-rw-r--r--Master/texmf-dist/tex/context/base/colo-ini.mkii6
-rw-r--r--Master/texmf-dist/tex/context/base/colo-ini.mkiv1028
-rw-r--r--Master/texmf-dist/tex/context/base/colo-rgb.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/colo-run.lua66
-rw-r--r--Master/texmf-dist/tex/context/base/colo-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/colo-run.mkiv329
-rw-r--r--Master/texmf-dist/tex/context/base/colo-xwi.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-cs.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-cs.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-de.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-de.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-en.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-en.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-err.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-fil.mkii5
-rw-r--r--Master/texmf-dist/tex/context/base/cont-fil.mkiv9
-rw-r--r--Master/texmf-dist/tex/context/base/cont-fr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-fr.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-gb.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-gb.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-it.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-it.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-log.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-log.mkiv140
-rw-r--r--Master/texmf-dist/tex/context/base/cont-new.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/cont-new.mkiv80
-rw-r--r--Master/texmf-dist/tex/context/base/cont-nl.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-nl.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-pe.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-ro.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/cont-ro.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/context-base.lmx7
-rw-r--r--Master/texmf-dist/tex/context/base/context-version.pdfbin0 -> 4076 bytes
-rw-r--r--Master/texmf-dist/tex/context/base/context-version.pngbin0 -> 105890 bytes
-rw-r--r--Master/texmf-dist/tex/context/base/context.css26
-rw-r--r--Master/texmf-dist/tex/context/base/context.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/context.mkiv141
-rw-r--r--Master/texmf-dist/tex/context/base/core-con.lua97
-rw-r--r--Master/texmf-dist/tex/context/base/core-con.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-con.mkiv294
-rw-r--r--Master/texmf-dist/tex/context/base/core-ctx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-ctx.mkiv12
-rw-r--r--Master/texmf-dist/tex/context/base/core-dat.lua246
-rw-r--r--Master/texmf-dist/tex/context/base/core-dat.mkiv101
-rw-r--r--Master/texmf-dist/tex/context/base/core-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-def.mkiv38
-rw-r--r--Master/texmf-dist/tex/context/base/core-env.lua41
-rw-r--r--Master/texmf-dist/tex/context/base/core-env.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-env.mkiv577
-rw-r--r--Master/texmf-dist/tex/context/base/core-fil.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-fil.mkiv243
-rw-r--r--Master/texmf-dist/tex/context/base/core-fnt.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-fnt.mkiv142
-rw-r--r--Master/texmf-dist/tex/context/base/core-gen.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-gen.mkiv166
-rw-r--r--Master/texmf-dist/tex/context/base/core-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-ini.mkiv91
-rw-r--r--Master/texmf-dist/tex/context/base/core-job.lua212
-rw-r--r--Master/texmf-dist/tex/context/base/core-job.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-job.mkiv313
-rw-r--r--Master/texmf-dist/tex/context/base/core-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-mis.mkiv1720
-rw-r--r--Master/texmf-dist/tex/context/base/core-par.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-stg.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-sys.lua5
-rw-r--r--Master/texmf-dist/tex/context/base/core-sys.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-sys.mkiv369
-rw-r--r--Master/texmf-dist/tex/context/base/core-two.lua91
-rw-r--r--Master/texmf-dist/tex/context/base/core-two.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-two.mkiv61
-rw-r--r--Master/texmf-dist/tex/context/base/core-uti.lua121
-rw-r--r--Master/texmf-dist/tex/context/base/core-uti.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-uti.mkiv11
-rw-r--r--Master/texmf-dist/tex/context/base/core-var.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/core-var.mkiv28
-rw-r--r--Master/texmf-dist/tex/context/base/data-bin.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/data-env.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/data-exp.lua211
-rw-r--r--Master/texmf-dist/tex/context/base/data-fil.lua3
-rw-r--r--Master/texmf-dist/tex/context/base/data-ini.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/data-lst.lua15
-rw-r--r--Master/texmf-dist/tex/context/base/data-lua.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/data-pre.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/data-res.lua1057
-rw-r--r--Master/texmf-dist/tex/context/base/data-tex.lua39
-rw-r--r--Master/texmf-dist/tex/context/base/data-tmf.lua15
-rw-r--r--Master/texmf-dist/tex/context/base/data-tmp.lua15
-rw-r--r--Master/texmf-dist/tex/context/base/data-tre.lua10
-rw-r--r--Master/texmf-dist/tex/context/base/data-vir.lua3
-rw-r--r--Master/texmf-dist/tex/context/base/data-zip.lua12
-rw-r--r--Master/texmf-dist/tex/context/base/enco-032.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-037.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-acc.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-ans.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-cas.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-chi.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-com.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-cyr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-ec.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-ecm.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-el.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-fde.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-ffr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-fpl.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-fro.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-fsl.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-grk.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-heb.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-il2.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-ini.mkiv42
-rw-r--r--Master/texmf-dist/tex/context/base/enco-l7x.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-pdf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-pfr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-pol.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-qx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-t5.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-tbo.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-uc.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-vna.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/enco-x5.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/export-example.css711
-rw-r--r--Master/texmf-dist/tex/context/base/export-example.rng377
-rw-r--r--Master/texmf-dist/tex/context/base/export-example.tex120
-rw-r--r--Master/texmf-dist/tex/context/base/file-ini.lua38
-rw-r--r--Master/texmf-dist/tex/context/base/file-ini.mkvi225
-rw-r--r--Master/texmf-dist/tex/context/base/file-job.lua685
-rw-r--r--Master/texmf-dist/tex/context/base/file-job.mkvi294
-rw-r--r--Master/texmf-dist/tex/context/base/file-lib.lua64
-rw-r--r--Master/texmf-dist/tex/context/base/file-lib.mkvi20
-rw-r--r--Master/texmf-dist/tex/context/base/file-mod.lua170
-rw-r--r--Master/texmf-dist/tex/context/base/file-mod.mkvi250
-rw-r--r--Master/texmf-dist/tex/context/base/file-res.lua110
-rw-r--r--Master/texmf-dist/tex/context/base/file-res.mkvi151
-rw-r--r--Master/texmf-dist/tex/context/base/file-syn.lua48
-rw-r--r--Master/texmf-dist/tex/context/base/file-syn.mkvi66
-rw-r--r--Master/texmf-dist/tex/context/base/filt-bas.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/filt-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/font-afm.lua14
-rw-r--r--Master/texmf-dist/tex/context/base/font-agl.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/font-bfm.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/font-chi.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/font-chk.lua261
-rw-r--r--Master/texmf-dist/tex/context/base/font-col.lua34
-rw-r--r--Master/texmf-dist/tex/context/base/font-col.mkvi (renamed from Master/texmf-dist/tex/context/base/font-col.mkiv)84
-rw-r--r--Master/texmf-dist/tex/context/base/font-con.lua359
-rw-r--r--Master/texmf-dist/tex/context/base/font-ctx.lua468
-rw-r--r--Master/texmf-dist/tex/context/base/font-def.lua110
-rw-r--r--Master/texmf-dist/tex/context/base/font-emp.mkvi231
-rw-r--r--Master/texmf-dist/tex/context/base/font-ext.lua313
-rw-r--r--Master/texmf-dist/tex/context/base/font-fbk.lua137
-rw-r--r--Master/texmf-dist/tex/context/base/font-fea.mkvi189
-rw-r--r--Master/texmf-dist/tex/context/base/font-fil.mkvi391
-rw-r--r--Master/texmf-dist/tex/context/base/font-gds.lua258
-rw-r--r--Master/texmf-dist/tex/context/base/font-gds.mkiv17
-rw-r--r--Master/texmf-dist/tex/context/base/font-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/font-ini.mkiv4414
-rw-r--r--Master/texmf-dist/tex/context/base/font-ini.mkvi2282
-rw-r--r--Master/texmf-dist/tex/context/base/font-jap.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/font-lib.mkvi94
-rw-r--r--Master/texmf-dist/tex/context/base/font-map.lua75
-rw-r--r--Master/texmf-dist/tex/context/base/font-mat.mkvi414
-rw-r--r--Master/texmf-dist/tex/context/base/font-mis.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/font-ota.lua19
-rw-r--r--Master/texmf-dist/tex/context/base/font-otb.lua111
-rw-r--r--Master/texmf-dist/tex/context/base/font-otc.lua230
-rw-r--r--Master/texmf-dist/tex/context/base/font-otd.lua51
-rw-r--r--Master/texmf-dist/tex/context/base/font-otf.lua284
-rw-r--r--Master/texmf-dist/tex/context/base/font-otn.lua973
-rw-r--r--Master/texmf-dist/tex/context/base/font-ott.lua67
-rw-r--r--Master/texmf-dist/tex/context/base/font-pre.mkiv486
-rw-r--r--Master/texmf-dist/tex/context/base/font-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/font-run.mkiv45
-rw-r--r--Master/texmf-dist/tex/context/base/font-set.mkvi144
-rw-r--r--Master/texmf-dist/tex/context/base/font-sty.mkvi386
-rw-r--r--Master/texmf-dist/tex/context/base/font-sym.mkvi242
-rw-r--r--Master/texmf-dist/tex/context/base/font-syn.lua39
-rw-r--r--Master/texmf-dist/tex/context/base/font-tfm.lua19
-rw-r--r--Master/texmf-dist/tex/context/base/font-tra.mkiv97
-rw-r--r--Master/texmf-dist/tex/context/base/font-uni.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/font-uni.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/font-unk.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/font-unk.mkiv96
-rw-r--r--Master/texmf-dist/tex/context/base/font-var.mkvi53
-rw-r--r--Master/texmf-dist/tex/context/base/font-xtx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/grph-epd.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/grph-fig.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/grph-fig.mkiv217
-rw-r--r--Master/texmf-dist/tex/context/base/grph-fil.lua15
-rw-r--r--Master/texmf-dist/tex/context/base/grph-inc.lua189
-rw-r--r--Master/texmf-dist/tex/context/base/grph-inc.mkii6
-rw-r--r--Master/texmf-dist/tex/context/base/grph-inc.mkiv58
-rw-r--r--Master/texmf-dist/tex/context/base/grph-raw.mkiv14
-rw-r--r--Master/texmf-dist/tex/context/base/grph-trf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/grph-trf.mkiv1219
-rw-r--r--Master/texmf-dist/tex/context/base/hand-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/hand-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/hand-ini.mkiv47
-rw-r--r--Master/texmf-dist/tex/context/base/java-ans.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/java-exa.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/java-fil.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/java-fld.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/java-imp-exa.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/java-imp-fil.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/java-imp-fld.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/java-imp-rhh.mkiv34
-rw-r--r--Master/texmf-dist/tex/context/base/java-imp-stp.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/java-ini.lua48
-rw-r--r--Master/texmf-dist/tex/context/base/java-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/java-ini.mkiv29
-rw-r--r--Master/texmf-dist/tex/context/base/java-stp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/l-aux.lua13
-rw-r--r--Master/texmf-dist/tex/context/base/l-boolean.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/l-dir.lua18
-rw-r--r--Master/texmf-dist/tex/context/base/l-file.lua69
-rw-r--r--Master/texmf-dist/tex/context/base/l-io.lua5
-rw-r--r--Master/texmf-dist/tex/context/base/l-lpeg.lua267
-rw-r--r--Master/texmf-dist/tex/context/base/l-math.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/l-os.lua39
-rw-r--r--Master/texmf-dist/tex/context/base/l-pdfview.lua72
-rw-r--r--Master/texmf-dist/tex/context/base/l-table.lua50
-rw-r--r--Master/texmf-dist/tex/context/base/l-unicode.lua77
-rw-r--r--Master/texmf-dist/tex/context/base/l-url.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/l-utils.lua12
-rw-r--r--Master/texmf-dist/tex/context/base/lang-alt.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ana.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-art.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-bal.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-cel.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-chi.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ctx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-cyr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-def.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/lang-def.mkiv147
-rw-r--r--Master/texmf-dist/tex/context/base/lang-dis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-frd.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-frq.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ger.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-grk.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ind.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ini.lua14
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ini.mkiv184
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ita.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-jap.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-lab.lua100
-rw-r--r--Master/texmf-dist/tex/context/base/lang-lab.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-lab.mkiv183
-rw-r--r--Master/texmf-dist/tex/context/base/lang-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-mis.mkiv280
-rw-r--r--Master/texmf-dist/tex/context/base/lang-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-sla.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-spa.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-spa.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-spe.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-txt.lua48
-rw-r--r--Master/texmf-dist/tex/context/base/lang-ura.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-url.lua90
-rw-r--r--Master/texmf-dist/tex/context/base/lang-url.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-url.mkiv54
-rw-r--r--Master/texmf-dist/tex/context/base/lang-vn.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/lang-wrd.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/lang-wrd.mkiv37
-rw-r--r--Master/texmf-dist/tex/context/base/layo-ini.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-ano.lua144
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-col.lua488
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-epa.lua13
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-epd.lua41
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-fld.lua347
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-fmt.lua47
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-grp.lua158
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-ini.lua80
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-mis.lua150
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-mov.lua63
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-nod.lua39
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-ren.lua122
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-swf.lua133
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-tag.lua3
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-u3d.lua44
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-wid.lua114
-rw-r--r--Master/texmf-dist/tex/context/base/lpdf-xmp.lua32
-rw-r--r--Master/texmf-dist/tex/context/base/luat-bas.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/luat-cbk.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/luat-cod.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/luat-cod.mkiv34
-rw-r--r--Master/texmf-dist/tex/context/base/luat-exe.lua64
-rw-r--r--Master/texmf-dist/tex/context/base/luat-fio.lua36
-rw-r--r--Master/texmf-dist/tex/context/base/luat-ini.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/luat-ini.mkiv82
-rw-r--r--Master/texmf-dist/tex/context/base/luat-iop.lua243
-rw-r--r--Master/texmf-dist/tex/context/base/luat-lib.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/luat-lua.lua14
-rw-r--r--Master/texmf-dist/tex/context/base/luat-mac.lua154
-rw-r--r--Master/texmf-dist/tex/context/base/luat-run.lua7
-rw-r--r--Master/texmf-dist/tex/context/base/luat-sto.lua36
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-aux.lua240
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-css.lua (renamed from Master/texmf-dist/tex/context/base/x-css.lua)82
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-css.mkiv (renamed from Master/texmf-dist/tex/context/base/x-css.mkiv)6
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-ctx.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-ctx.mkiv69
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-dir.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-ent.lua45
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-ini.mkiv162
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-lpt.lua63
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-sor.lua5
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-sor.mkiv12
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-tab.lua308
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-tex.lua869
-rw-r--r--Master/texmf-dist/tex/context/base/lxml-xml.lua287
-rw-r--r--Master/texmf-dist/tex/context/base/m-arabtex.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/m-barcodes.mkiv8
-rw-r--r--Master/texmf-dist/tex/context/base/m-chart.lua877
-rw-r--r--Master/texmf-dist/tex/context/base/m-chart.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/m-chart.mkiv2546
-rw-r--r--Master/texmf-dist/tex/context/base/m-chart.mkvi492
-rw-r--r--Master/texmf-dist/tex/context/base/m-chart.tex18
-rw-r--r--Master/texmf-dist/tex/context/base/m-chemic.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/m-chemic.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/m-cweb.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-database.lua68
-rw-r--r--Master/texmf-dist/tex/context/base/m-database.mkii3
-rw-r--r--Master/texmf-dist/tex/context/base/m-database.mkiv35
-rw-r--r--Master/texmf-dist/tex/context/base/m-datastrc.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-dratex.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/m-edtsnc.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/m-educat.tex92
-rw-r--r--Master/texmf-dist/tex/context/base/m-fields.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/m-format.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-graph.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/m-graph.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/m-layout.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-level.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/m-markdown.lua824
-rw-r--r--Master/texmf-dist/tex/context/base/m-markdown.mkiv88
-rw-r--r--Master/texmf-dist/tex/context/base/m-mathcrap.mkiv8
-rw-r--r--Master/texmf-dist/tex/context/base/m-mkivhacks.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/m-morse.mkvi2
-rw-r--r--Master/texmf-dist/tex/context/base/m-narrowtt.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-newmat.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-ntb-to-xtb.mkiv5
-rw-r--r--Master/texmf-dist/tex/context/base/m-pdfsnc.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/m-pictex.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-pstricks.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/m-pstricks.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/m-pstricks.mkiv25
-rw-r--r--Master/texmf-dist/tex/context/base/m-punk.mkiv8
-rw-r--r--Master/texmf-dist/tex/context/base/m-quest.tex232
-rw-r--r--Master/texmf-dist/tex/context/base/m-r.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-spreadsheet.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/m-steps.lua227
-rw-r--r--Master/texmf-dist/tex/context/base/m-steps.mkii (renamed from Master/texmf-dist/tex/context/base/m-steps.tex)16
-rw-r--r--Master/texmf-dist/tex/context/base/m-steps.mkvi382
-rw-r--r--Master/texmf-dist/tex/context/base/m-streams.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-subsub.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/m-timing.mkiv16
-rw-r--r--Master/texmf-dist/tex/context/base/m-translate.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/m-units.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/m-units.mkiv44
-rw-r--r--Master/texmf-dist/tex/context/base/m-visual.mkii (renamed from Master/texmf-dist/tex/context/base/m-visual.tex)5
-rw-r--r--Master/texmf-dist/tex/context/base/m-visual.mkiv252
-rw-r--r--Master/texmf-dist/tex/context/base/m-zint.mkiv12
-rw-r--r--Master/texmf-dist/tex/context/base/math-act.lua106
-rw-r--r--Master/texmf-dist/tex/context/base/math-ali.mkiv805
-rw-r--r--Master/texmf-dist/tex/context/base/math-ams.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-arr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-arr.mkiv98
-rw-r--r--Master/texmf-dist/tex/context/base/math-cow.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-def.mkiv144
-rw-r--r--Master/texmf-dist/tex/context/base/math-del.mkiv26
-rw-r--r--Master/texmf-dist/tex/context/base/math-dim.lua241
-rw-r--r--Master/texmf-dist/tex/context/base/math-dis.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/math-ent.lua2103
-rw-r--r--Master/texmf-dist/tex/context/base/math-eul.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-for.mkiv83
-rw-r--r--Master/texmf-dist/tex/context/base/math-fou.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-frc.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-frc.mkiv223
-rw-r--r--Master/texmf-dist/tex/context/base/math-ini.lua216
-rw-r--r--Master/texmf-dist/tex/context/base/math-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-ini.mkiv940
-rw-r--r--Master/texmf-dist/tex/context/base/math-inl.mkiv12
-rw-r--r--Master/texmf-dist/tex/context/base/math-int.mkiv149
-rw-r--r--Master/texmf-dist/tex/context/base/math-lan.mkiv67
-rw-r--r--Master/texmf-dist/tex/context/base/math-lbr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-map.lua750
-rw-r--r--Master/texmf-dist/tex/context/base/math-noa.lua533
-rw-r--r--Master/texmf-dist/tex/context/base/math-pln.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-pln.mkiv246
-rw-r--r--Master/texmf-dist/tex/context/base/math-ren.lua69
-rw-r--r--Master/texmf-dist/tex/context/base/math-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-scr.mkiv65
-rw-r--r--Master/texmf-dist/tex/context/base/math-tag.lua198
-rw-r--r--Master/texmf-dist/tex/context/base/math-tex.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-tim.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-uni.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/math-vfu.lua178
-rw-r--r--Master/texmf-dist/tex/context/base/meta-clp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-dum.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-fig.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-fig.mkiv40
-rw-r--r--Master/texmf-dist/tex/context/base/meta-fun.lua23
-rw-r--r--Master/texmf-dist/tex/context/base/meta-fun.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-imp-clp.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-imp-dum.mkiv66
-rw-r--r--Master/texmf-dist/tex/context/base/meta-imp-fen.mkiv173
-rw-r--r--Master/texmf-dist/tex/context/base/meta-imp-mis.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-imp-nav.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-imp-pre.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-imp-txt.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/meta-ini.lua93
-rw-r--r--Master/texmf-dist/tex/context/base/meta-ini.mkii14
-rw-r--r--Master/texmf-dist/tex/context/base/meta-ini.mkiv1010
-rw-r--r--Master/texmf-dist/tex/context/base/meta-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-nav.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-pag.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-pag.mkiv232
-rw-r--r--Master/texmf-dist/tex/context/base/meta-pdf.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/meta-pdf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-pdf.mkiv426
-rw-r--r--Master/texmf-dist/tex/context/base/meta-pdh.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/meta-pdh.mkiv17
-rw-r--r--Master/texmf-dist/tex/context/base/meta-pre.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-tex.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-tex.mkiv128
-rw-r--r--Master/texmf-dist/tex/context/base/meta-txt.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-xml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/meta-xml.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/metatex.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-ctx.lua3
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-ctx.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-pdf.lua75
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-pdf.mkiv192
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-pps.lua293
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-pps.mkiv136
-rw-r--r--Master/texmf-dist/tex/context/base/mlib-run.lua107
-rw-r--r--Master/texmf-dist/tex/context/base/mtx-context-arrange.tex25
-rw-r--r--Master/texmf-dist/tex/context/base/mtx-context-combine.tex10
-rw-r--r--Master/texmf-dist/tex/context/base/mtx-context-common.tex4
-rw-r--r--Master/texmf-dist/tex/context/base/mtx-context-ideas.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/mtx-context-listing.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/mtx-context-markdown.tex92
-rw-r--r--Master/texmf-dist/tex/context/base/mtx-context-select.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/mtx-context-timing.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-aux.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/mult-aux.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-aux.mkiv617
-rw-r--r--Master/texmf-dist/tex/context/base/mult-chk.lua10
-rw-r--r--Master/texmf-dist/tex/context/base/mult-chk.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-chk.mkiv30
-rw-r--r--Master/texmf-dist/tex/context/base/mult-com.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-con.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-de.mkii67
-rw-r--r--Master/texmf-dist/tex/context/base/mult-def.lua304
-rw-r--r--Master/texmf-dist/tex/context/base/mult-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-def.mkiv22
-rw-r--r--Master/texmf-dist/tex/context/base/mult-dim.mkvi126
-rw-r--r--Master/texmf-dist/tex/context/base/mult-en.mkii67
-rw-r--r--Master/texmf-dist/tex/context/base/mult-fr.mkii43
-rw-r--r--Master/texmf-dist/tex/context/base/mult-fst.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-fst.mkiv41
-rw-r--r--Master/texmf-dist/tex/context/base/mult-ini.lua64
-rw-r--r--Master/texmf-dist/tex/context/base/mult-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-ini.mkiv225
-rw-r--r--Master/texmf-dist/tex/context/base/mult-it.mkii43
-rw-r--r--Master/texmf-dist/tex/context/base/mult-low.lua250
-rw-r--r--Master/texmf-dist/tex/context/base/mult-mes.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/mult-mps.lua112
-rw-r--r--Master/texmf-dist/tex/context/base/mult-nl.mkii47
-rw-r--r--Master/texmf-dist/tex/context/base/mult-pe.mkii43
-rw-r--r--Master/texmf-dist/tex/context/base/mult-prm.lua1114
-rw-r--r--Master/texmf-dist/tex/context/base/mult-prm.mkiv63
-rw-r--r--Master/texmf-dist/tex/context/base/mult-ro.mkii43
-rw-r--r--Master/texmf-dist/tex/context/base/mult-sys.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/mult-sys.mkiv839
-rw-r--r--Master/texmf-dist/tex/context/base/node-acc.lua63
-rw-r--r--Master/texmf-dist/tex/context/base/node-aux.lua42
-rw-r--r--Master/texmf-dist/tex/context/base/node-bck.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/node-bck.mkiv71
-rw-r--r--Master/texmf-dist/tex/context/base/node-fin.mkiv13
-rw-r--r--Master/texmf-dist/tex/context/base/node-fnt.lua15
-rw-r--r--Master/texmf-dist/tex/context/base/node-ini.lua59
-rw-r--r--Master/texmf-dist/tex/context/base/node-ini.mkiv23
-rw-r--r--Master/texmf-dist/tex/context/base/node-inj.lua105
-rw-r--r--Master/texmf-dist/tex/context/base/node-mig.lua21
-rw-r--r--Master/texmf-dist/tex/context/base/node-mig.mkiv8
-rw-r--r--Master/texmf-dist/tex/context/base/node-pag.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/node-par.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/node-par.mkiv32
-rw-r--r--Master/texmf-dist/tex/context/base/node-pro.lua15
-rw-r--r--Master/texmf-dist/tex/context/base/node-ref.lua28
-rw-r--r--Master/texmf-dist/tex/context/base/node-res.lua19
-rw-r--r--Master/texmf-dist/tex/context/base/node-rul.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/node-rul.mkiv261
-rw-r--r--Master/texmf-dist/tex/context/base/node-ser.lua23
-rw-r--r--Master/texmf-dist/tex/context/base/node-shp.lua8
-rw-r--r--Master/texmf-dist/tex/context/base/node-spl.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/node-spl.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/node-tra.lua62
-rw-r--r--Master/texmf-dist/tex/context/base/node-tsk.lua86
-rw-r--r--Master/texmf-dist/tex/context/base/node-typ.lua42
-rw-r--r--Master/texmf-dist/tex/context/base/norm-alo.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/norm-ctx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/norm-ctx.mkiv6
-rw-r--r--Master/texmf-dist/tex/context/base/norm-etx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/norm-ltx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/norm-ptx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/norm-tex.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/norm-xtx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/pack-bar.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/pack-bck.mkvi256
-rw-r--r--Master/texmf-dist/tex/context/base/pack-box.mkii21
-rw-r--r--Master/texmf-dist/tex/context/base/pack-box.mkiv905
-rw-r--r--Master/texmf-dist/tex/context/base/pack-com.mkiv798
-rw-r--r--Master/texmf-dist/tex/context/base/pack-fen.mkiv97
-rw-r--r--Master/texmf-dist/tex/context/base/pack-lyr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/pack-lyr.mkiv847
-rw-r--r--Master/texmf-dist/tex/context/base/pack-mis.mkvi71
-rw-r--r--Master/texmf-dist/tex/context/base/pack-mrl.mkiv870
-rw-r--r--Master/texmf-dist/tex/context/base/pack-obj.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/pack-obj.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/pack-obj.mkiv94
-rw-r--r--Master/texmf-dist/tex/context/base/pack-pos.mkiv19
-rw-r--r--Master/texmf-dist/tex/context/base/pack-rul.lua50
-rw-r--r--Master/texmf-dist/tex/context/base/pack-rul.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/pack-rul.mkiv3619
-rw-r--r--Master/texmf-dist/tex/context/base/page-app.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-app.mkiv197
-rw-r--r--Master/texmf-dist/tex/context/base/page-bck.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-bck.mkiv687
-rw-r--r--Master/texmf-dist/tex/context/base/page-box.mkvi309
-rw-r--r--Master/texmf-dist/tex/context/base/page-brk.mkiv410
-rw-r--r--Master/texmf-dist/tex/context/base/page-col.mkiv156
-rw-r--r--Master/texmf-dist/tex/context/base/page-com.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/page-fac.mkiv77
-rw-r--r--Master/texmf-dist/tex/context/base/page-flt.lua95
-rw-r--r--Master/texmf-dist/tex/context/base/page-flt.mkiv115
-rw-r--r--Master/texmf-dist/tex/context/base/page-flw.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-flw.mkiv5
-rw-r--r--Master/texmf-dist/tex/context/base/page-grd.mkiv85
-rw-r--r--Master/texmf-dist/tex/context/base/page-imp.mkii34
-rw-r--r--Master/texmf-dist/tex/context/base/page-imp.mkiv502
-rw-r--r--Master/texmf-dist/tex/context/base/page-inf.mkiv106
-rw-r--r--Master/texmf-dist/tex/context/base/page-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-ini.mkiv1573
-rw-r--r--Master/texmf-dist/tex/context/base/page-ins.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-ins.mkiv3
-rw-r--r--Master/texmf-dist/tex/context/base/page-lay.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-lay.mkiv1572
-rw-r--r--Master/texmf-dist/tex/context/base/page-lin.lua7
-rw-r--r--Master/texmf-dist/tex/context/base/page-lin.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-lin.mkiv31
-rw-r--r--Master/texmf-dist/tex/context/base/page-log.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-mak.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-mak.mkiv225
-rw-r--r--Master/texmf-dist/tex/context/base/page-mak.mkvi210
-rw-r--r--Master/texmf-dist/tex/context/base/page-mar.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-mar.mkiv808
-rw-r--r--Master/texmf-dist/tex/context/base/page-mbk.mkvi250
-rw-r--r--Master/texmf-dist/tex/context/base/page-mis.lua77
-rw-r--r--Master/texmf-dist/tex/context/base/page-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-mis.mkiv246
-rw-r--r--Master/texmf-dist/tex/context/base/page-mrk.mkiv202
-rw-r--r--Master/texmf-dist/tex/context/base/page-mul.mkii14
-rw-r--r--Master/texmf-dist/tex/context/base/page-mul.mkiv1045
-rw-r--r--Master/texmf-dist/tex/context/base/page-not.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-not.mkiv10
-rw-r--r--Master/texmf-dist/tex/context/base/page-one.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-one.mkiv598
-rw-r--r--Master/texmf-dist/tex/context/base/page-otr.mkvi290
-rw-r--r--Master/texmf-dist/tex/context/base/page-par.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-par.mkiv7
-rw-r--r--Master/texmf-dist/tex/context/base/page-plg.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-plg.mkiv89
-rw-r--r--Master/texmf-dist/tex/context/base/page-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-run.mkiv232
-rw-r--r--Master/texmf-dist/tex/context/base/page-sel.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/page-set.mkii10
-rw-r--r--Master/texmf-dist/tex/context/base/page-set.mkiv315
-rw-r--r--Master/texmf-dist/tex/context/base/page-sid.mkii6
-rw-r--r--Master/texmf-dist/tex/context/base/page-sid.mkiv1153
-rw-r--r--Master/texmf-dist/tex/context/base/page-spr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-spr.mkiv6
-rw-r--r--Master/texmf-dist/tex/context/base/page-str.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/page-str.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-str.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/page-txt.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/page-txt.mkiv794
-rw-r--r--Master/texmf-dist/tex/context/base/page-txt.mkvi885
-rw-r--r--Master/texmf-dist/tex/context/base/page-var.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/pdfr-ec.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/pdfr-il2.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/phys-dim.lua878
-rw-r--r--Master/texmf-dist/tex/context/base/phys-dim.mkiv751
-rw-r--r--Master/texmf-dist/tex/context/base/ppchtex.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/ppchtex.mkiv25
-rw-r--r--Master/texmf-dist/tex/context/base/prop-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/prop-ini.mkiv50
-rw-r--r--Master/texmf-dist/tex/context/base/prop-lay.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/prop-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-1.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-10.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-13.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-15.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-16.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-2.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-3.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-4.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-5.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-7.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-8859-9.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-cp1250.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-cp1251.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-cp1252.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-cp1253.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-cp1254.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-cp1257.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-cyp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-cyr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-ibm.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-ini.lua43
-rw-r--r--Master/texmf-dist/tex/context/base/regi-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-ini.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/regi-mac.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-syn.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-uni.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/regi-utf.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/regi-vis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-abr-01.tex14
-rw-r--r--Master/texmf-dist/tex/context/base/s-abr-02.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-abr-03.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-abr-04.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-art-01.mkiv36
-rw-r--r--Master/texmf-dist/tex/context/base/s-cdr-01.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-chi-00.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-def-01.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-faq-00.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-faq-01.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-faq-02.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-faq-03.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-01.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-10.mkiv9
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-11.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-20.mkiv44
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-21.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-23.mkiv66
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-24.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-25.mkiv198
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-26.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-28.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-29.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-30.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-31.mkiv32
-rw-r--r--Master/texmf-dist/tex/context/base/s-fnt-32.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-fonts-missing.mkiv79
-rw-r--r--Master/texmf-dist/tex/context/base/s-fonts-tables.lua319
-rw-r--r--Master/texmf-dist/tex/context/base/s-fonts-tables.mkiv30
-rw-r--r--Master/texmf-dist/tex/context/base/s-grk-00.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-inf-01.mkvi4
-rw-r--r--Master/texmf-dist/tex/context/base/s-inf-02.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-inf-03.mkiv28
-rw-r--r--Master/texmf-dist/tex/context/base/s-jap-00.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-lan-03.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-lan-04.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-mag-01.tex14
-rw-r--r--Master/texmf-dist/tex/context/base/s-map-10.mkiv131
-rw-r--r--Master/texmf-dist/tex/context/base/s-mat-10.mkiv245
-rw-r--r--Master/texmf-dist/tex/context/base/s-mat-11.mkiv106
-rw-r--r--Master/texmf-dist/tex/context/base/s-mat-12.mkiv406
-rw-r--r--Master/texmf-dist/tex/context/base/s-mod-00.mkii36
-rw-r--r--Master/texmf-dist/tex/context/base/s-mod-00.mkiv467
-rw-r--r--Master/texmf-dist/tex/context/base/s-mod-01.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-mod-01.mkiv345
-rw-r--r--Master/texmf-dist/tex/context/base/s-mod-02.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-mod-02.mkiv409
-rw-r--r--Master/texmf-dist/tex/context/base/s-mod.ctx1
-rw-r--r--Master/texmf-dist/tex/context/base/s-phy-01.mkiv111
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-00.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-01.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-02.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-03.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-04.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-05.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-06.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-07.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-08.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-09.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-10.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-11.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-12.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-13.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-14.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-15.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-16.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-17.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-18.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-19.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-22.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-23.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-26.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-27.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-30.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-30.mkiv6
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-50.tex4
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-60.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-60.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-61.tex5
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-62.tex5
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-63.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-64.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-66.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-68.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-69.mkiv5
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-70.mkiv30
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-71.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-71.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-93.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-pre-96.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/s-ptj-01.tex12
-rw-r--r--Master/texmf-dist/tex/context/base/s-reg-01.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/s-syn-01.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-bar.mkvi150
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-but.mkvi555
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-fld.lua11
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-fld.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-fld.mkvi394
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-hlp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-hlp.mkvi47
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-ini.mkvi78
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-int.mkii7
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-nav.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-pag.mkvi123
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-ref.mkvi2
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-wid.lua22
-rw-r--r--Master/texmf-dist/tex/context/base/scrn-wid.mkvi169
-rw-r--r--Master/texmf-dist/tex/context/base/scrp-cjk.lua955
-rw-r--r--Master/texmf-dist/tex/context/base/scrp-ini.lua66
-rw-r--r--Master/texmf-dist/tex/context/base/scrp-ini.mkiv21
-rw-r--r--Master/texmf-dist/tex/context/base/sort-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/sort-ini.lua13
-rw-r--r--Master/texmf-dist/tex/context/base/sort-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/sort-ini.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/sort-lan.lua37
-rw-r--r--Master/texmf-dist/tex/context/base/sort-lan.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spac-adj.lua (renamed from Master/texmf-dist/tex/context/base/spac-par.lua)4
-rw-r--r--Master/texmf-dist/tex/context/base/spac-adj.mkiv50
-rw-r--r--Master/texmf-dist/tex/context/base/spac-ali.lua4
-rw-r--r--Master/texmf-dist/tex/context/base/spac-ali.mkiv1221
-rw-r--r--Master/texmf-dist/tex/context/base/spac-chr.lua200
-rw-r--r--Master/texmf-dist/tex/context/base/spac-chr.mkiv90
-rw-r--r--Master/texmf-dist/tex/context/base/spac-def.mkiv110
-rw-r--r--Master/texmf-dist/tex/context/base/spac-fnt.mkiv94
-rw-r--r--Master/texmf-dist/tex/context/base/spac-gen.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spac-grd.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spac-grd.mkiv95
-rw-r--r--Master/texmf-dist/tex/context/base/spac-hor.mkiv876
-rw-r--r--Master/texmf-dist/tex/context/base/spac-lin.mkiv148
-rw-r--r--Master/texmf-dist/tex/context/base/spac-pag.mkiv193
-rw-r--r--Master/texmf-dist/tex/context/base/spac-par.mkiv253
-rw-r--r--Master/texmf-dist/tex/context/base/spac-ver.lua32
-rw-r--r--Master/texmf-dist/tex/context/base/spac-ver.mkiv1585
-rw-r--r--Master/texmf-dist/tex/context/base/spec-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-dpm.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-dvi.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-fdf.mkii5
-rw-r--r--Master/texmf-dist/tex/context/base/spec-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-pdf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-ps.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-tpd.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-tr.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-tst.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-var.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-win.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/spec-yy.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/status-files.pdfbin23577 -> 24332 bytes
-rw-r--r--Master/texmf-dist/tex/context/base/status-lua.pdfbin154401 -> 178785 bytes
-rw-r--r--Master/texmf-dist/tex/context/base/status-mkiv.lua1513
-rw-r--r--Master/texmf-dist/tex/context/base/status-mkiv.tex161
-rw-r--r--Master/texmf-dist/tex/context/base/strc-bkm.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/strc-bkm.mkiv11
-rw-r--r--Master/texmf-dist/tex/context/base/strc-blk.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/strc-blk.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-blk.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/strc-con.lua (renamed from Master/texmf-dist/tex/context/base/strc-des.lua)4
-rw-r--r--Master/texmf-dist/tex/context/base/strc-con.mkvi892
-rw-r--r--Master/texmf-dist/tex/context/base/strc-def.mkiv158
-rw-r--r--Master/texmf-dist/tex/context/base/strc-des.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-des.mkiv1130
-rw-r--r--Master/texmf-dist/tex/context/base/strc-des.mkvi200
-rw-r--r--Master/texmf-dist/tex/context/base/strc-doc.lua393
-rw-r--r--Master/texmf-dist/tex/context/base/strc-doc.mkiv84
-rw-r--r--Master/texmf-dist/tex/context/base/strc-enu.mkvi385
-rw-r--r--Master/texmf-dist/tex/context/base/strc-flt.mkii18
-rw-r--r--Master/texmf-dist/tex/context/base/strc-flt.mkiv2054
-rw-r--r--Master/texmf-dist/tex/context/base/strc-flt.mkvi2120
-rw-r--r--Master/texmf-dist/tex/context/base/strc-ind.mkiv123
-rw-r--r--Master/texmf-dist/tex/context/base/strc-ini.lua140
-rw-r--r--Master/texmf-dist/tex/context/base/strc-ini.mkvi (renamed from Master/texmf-dist/tex/context/base/strc-ini.mkiv)33
-rw-r--r--Master/texmf-dist/tex/context/base/strc-itm.lua21
-rw-r--r--Master/texmf-dist/tex/context/base/strc-itm.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-itm.mkiv1408
-rw-r--r--Master/texmf-dist/tex/context/base/strc-itm.mkvi1573
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lab.mkiv96
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lev.lua24
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lev.mkiv92
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lev.mkvi96
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lnt.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lnt.mkvi (renamed from Master/texmf-dist/tex/context/base/strc-lnt.mkiv)87
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lst.lua241
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lst.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lst.mkiv1080
-rw-r--r--Master/texmf-dist/tex/context/base/strc-lst.mkvi1296
-rw-r--r--Master/texmf-dist/tex/context/base/strc-mar.lua123
-rw-r--r--Master/texmf-dist/tex/context/base/strc-mar.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-mar.mkiv79
-rw-r--r--Master/texmf-dist/tex/context/base/strc-mat.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-mat.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-mat.mkiv417
-rw-r--r--Master/texmf-dist/tex/context/base/strc-not.lua116
-rw-r--r--Master/texmf-dist/tex/context/base/strc-not.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-not.mkiv1378
-rw-r--r--Master/texmf-dist/tex/context/base/strc-not.mkvi1727
-rw-r--r--Master/texmf-dist/tex/context/base/strc-num.lua110
-rw-r--r--Master/texmf-dist/tex/context/base/strc-num.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-num.mkiv796
-rw-r--r--Master/texmf-dist/tex/context/base/strc-pag.lua77
-rw-r--r--Master/texmf-dist/tex/context/base/strc-pag.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-pag.mkiv249
-rw-r--r--Master/texmf-dist/tex/context/base/strc-prc.lua9
-rw-r--r--Master/texmf-dist/tex/context/base/strc-ref.lua1874
-rw-r--r--Master/texmf-dist/tex/context/base/strc-ref.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-ref.mkvi (renamed from Master/texmf-dist/tex/context/base/strc-ref.mkiv)936
-rw-r--r--Master/texmf-dist/tex/context/base/strc-reg.lua16
-rw-r--r--Master/texmf-dist/tex/context/base/strc-reg.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-reg.mkiv39
-rw-r--r--Master/texmf-dist/tex/context/base/strc-ren.mkiv255
-rw-r--r--Master/texmf-dist/tex/context/base/strc-rsc.lua154
-rw-r--r--Master/texmf-dist/tex/context/base/strc-sbe.mkiv110
-rw-r--r--Master/texmf-dist/tex/context/base/strc-sec.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-sec.mkiv1133
-rw-r--r--Master/texmf-dist/tex/context/base/strc-swd.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-syn.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-syn.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/strc-syn.mkiv172
-rw-r--r--Master/texmf-dist/tex/context/base/strc-tag.lua200
-rw-r--r--Master/texmf-dist/tex/context/base/strc-tag.mkiv387
-rw-r--r--Master/texmf-dist/tex/context/base/strc-xml.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/supp-ali.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-ali.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-box.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-box.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-box.mkiv1603
-rw-r--r--Master/texmf-dist/tex/context/base/supp-dir.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-dir.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-emp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-eps.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-fil.lua334
-rw-r--r--Master/texmf-dist/tex/context/base/supp-fil.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-fil.mkiv462
-rw-r--r--Master/texmf-dist/tex/context/base/supp-fun.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-fun.mkiv58
-rw-r--r--Master/texmf-dist/tex/context/base/supp-lat.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-mat.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-mat.mkiv61
-rw-r--r--Master/texmf-dist/tex/context/base/supp-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-mpe.mkii5
-rw-r--r--Master/texmf-dist/tex/context/base/supp-mps.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-mrk.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-num.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-num.mkiv128
-rw-r--r--Master/texmf-dist/tex/context/base/supp-pat.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-pdf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-ran.lua7
-rw-r--r--Master/texmf-dist/tex/context/base/supp-ran.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-ran.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/supp-spe.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-tpi.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-vis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/supp-vis.mkiv507
-rw-r--r--Master/texmf-dist/tex/context/base/symb-cow.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-eur.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-glm.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-imp-cow.mkiv (renamed from Master/texmf-dist/tex/context/base/symb-cow.mkiv)2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-imp-eur.mkiv (renamed from Master/texmf-dist/tex/context/base/symb-eur.mkiv)2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-imp-jmn.mkiv (renamed from Master/texmf-dist/tex/context/base/symb-jmn.mkiv)2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-imp-mis.mkiv (renamed from Master/texmf-dist/tex/context/base/symb-mis.mkiv)25
-rw-r--r--Master/texmf-dist/tex/context/base/symb-imp-mvs.mkiv (renamed from Master/texmf-dist/tex/context/base/symb-mvs.mkiv)2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-imp-nav.mkiv (renamed from Master/texmf-dist/tex/context/base/symb-nav.mkiv)2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-ini.lua30
-rw-r--r--Master/texmf-dist/tex/context/base/symb-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-ini.mkiv233
-rw-r--r--Master/texmf-dist/tex/context/base/symb-jmn.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-mis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-mvs.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-nav.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-run.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-uni.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/symb-was.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-aux.lua52
-rw-r--r--Master/texmf-dist/tex/context/base/syst-aux.mkiv2607
-rw-r--r--Master/texmf-dist/tex/context/base/syst-con.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/syst-con.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-con.mkiv15
-rw-r--r--Master/texmf-dist/tex/context/base/syst-ext.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-fnt.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-fnt.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-gen.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-ini.mkiv598
-rw-r--r--Master/texmf-dist/tex/context/base/syst-lua.lua62
-rw-r--r--Master/texmf-dist/tex/context/base/syst-lua.mkiv8
-rw-r--r--Master/texmf-dist/tex/context/base/syst-mes.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-new.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-pln.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-pln.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/syst-rtp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-rtp.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-str.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/syst-tex.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-com.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-com.mkiv34
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-ltb.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-ltb.mkiv72
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-ntb.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-ntb.mkiv78
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-nte.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-nte.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-tab.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-tab.mkiv93
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-tbl.lua21
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-tbl.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-tbl.mkiv2572
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-tsp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-tsp.mkiv259
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-xnt.mkvi135
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-xtb.lua986
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-xtb.mkvi689
-rw-r--r--Master/texmf-dist/tex/context/base/task-ini.lua23
-rw-r--r--Master/texmf-dist/tex/context/base/task-ini.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/toks-ini.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/toks-ini.mkiv42
-rw-r--r--Master/texmf-dist/tex/context/base/trac-deb.mkiv30
-rw-r--r--Master/texmf-dist/tex/context/base/trac-fil.lua149
-rw-r--r--Master/texmf-dist/tex/context/base/trac-inf.lua8
-rw-r--r--Master/texmf-dist/tex/context/base/trac-lmx.lua14
-rw-r--r--Master/texmf-dist/tex/context/base/trac-log.lua77
-rw-r--r--Master/texmf-dist/tex/context/base/trac-set.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/trac-tex.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/trac-tex.mkiv14
-rw-r--r--Master/texmf-dist/tex/context/base/trac-vis.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/trac-vis.mkiv66
-rw-r--r--Master/texmf-dist/tex/context/base/type-buy.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-cbg.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-cow.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-def.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-def.mkiv50
-rw-r--r--Master/texmf-dist/tex/context/base/type-exp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-fbk.mkiv70
-rw-r--r--Master/texmf-dist/tex/context/base/type-fsf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-ghz.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-antykwa.mkiv228
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-antykwapoltawskiego.mkiv140
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-asana.mkiv35
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-averia.mkiv90
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-buy.mkiv37
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-cambria.mkiv73
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-charter.mkiv36
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-cleartype.mkiv56
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-computer-modern-unicode.mkiv64
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-cow.mkiv (renamed from Master/texmf-dist/tex/context/base/type-cow.mkiv)2
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-dejavu.mkiv92
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-euler.mkiv47
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-ghz.mkiv (renamed from Master/texmf-dist/tex/context/base/type-ghz.mkiv)12
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-hgz.mkiv (renamed from Master/texmf-dist/tex/context/base/type-hgz.mkiv)0
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-husayni.mkiv (renamed from Master/texmf-dist/tex/context/base/type-husayni-default.mkiv)0
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-hvmath.mkiv30
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-inconsolata.mkiv25
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-informal.mkiv (renamed from Master/texmf-dist/tex/context/base/type-buy.mkiv)38
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-iwona.mkiv236
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-kurier.mkiv56
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-latinmodern.mkiv224
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-liberation.mkiv47
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-libertine.mkiv63
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-lmnames.mkiv129
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-lucida-opentype.mkiv92
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-lucida-typeone.mkiv134
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-mathdesign.mkiv32
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-mathtimes.mkiv31
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-mscore.mkiv64
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-osx.mkiv (renamed from Master/texmf-dist/tex/context/base/type-mac.mkiv)28
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-postscript.mkiv26
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-punknova.mkiv34
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-texgyre.mkiv222
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-unfonts.mkiv142
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-xits.mkiv57
-rw-r--r--Master/texmf-dist/tex/context/base/type-imp-xitsbidi.mkiv16
-rw-r--r--Master/texmf-dist/tex/context/base/type-ini.lua76
-rw-r--r--Master/texmf-dist/tex/context/base/type-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-ini.mkiv525
-rw-r--r--Master/texmf-dist/tex/context/base/type-ini.mkvi605
-rw-r--r--Master/texmf-dist/tex/context/base/type-lua.mkiv80
-rw-r--r--Master/texmf-dist/tex/context/base/type-mac.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-msw.mkiv1
-rw-r--r--Master/texmf-dist/tex/context/base/type-one.mkii127
-rw-r--r--Master/texmf-dist/tex/context/base/type-one.mkiv97
-rw-r--r--Master/texmf-dist/tex/context/base/type-otf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-otf.mkiv1946
-rw-r--r--Master/texmf-dist/tex/context/base/type-pre.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-run.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/type-set.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-set.mkiv131
-rw-r--r--Master/texmf-dist/tex/context/base/type-siz.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-siz.mkiv317
-rw-r--r--Master/texmf-dist/tex/context/base/type-tmf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-tmf.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/type-win.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/type-win.mkiv118
-rw-r--r--Master/texmf-dist/tex/context/base/type-xtx.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/typo-brk.lua116
-rw-r--r--Master/texmf-dist/tex/context/base/typo-brk.mkiv92
-rw-r--r--Master/texmf-dist/tex/context/base/typo-cap.lua90
-rw-r--r--Master/texmf-dist/tex/context/base/typo-cap.mkiv75
-rw-r--r--Master/texmf-dist/tex/context/base/typo-cln.lua32
-rw-r--r--Master/texmf-dist/tex/context/base/typo-cln.mkiv9
-rw-r--r--Master/texmf-dist/tex/context/base/typo-del.mkiv607
-rw-r--r--Master/texmf-dist/tex/context/base/typo-dig.lua41
-rw-r--r--Master/texmf-dist/tex/context/base/typo-dig.mkiv8
-rw-r--r--Master/texmf-dist/tex/context/base/typo-dir.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/typo-dir.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/typo-ini.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/typo-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/typo-ini.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/typo-itc.lua255
-rw-r--r--Master/texmf-dist/tex/context/base/typo-itc.mkvi62
-rw-r--r--Master/texmf-dist/tex/context/base/typo-krn.lua139
-rw-r--r--Master/texmf-dist/tex/context/base/typo-krn.mkiv59
-rw-r--r--Master/texmf-dist/tex/context/base/typo-mar.lua593
-rw-r--r--Master/texmf-dist/tex/context/base/typo-mar.mkiv335
-rw-r--r--Master/texmf-dist/tex/context/base/typo-pag.lua183
-rw-r--r--Master/texmf-dist/tex/context/base/typo-pag.mkiv20
-rw-r--r--Master/texmf-dist/tex/context/base/typo-par.lua184
-rw-r--r--Master/texmf-dist/tex/context/base/typo-par.mkiv107
-rw-r--r--Master/texmf-dist/tex/context/base/typo-prc.lua126
-rw-r--r--Master/texmf-dist/tex/context/base/typo-prc.mkvi (renamed from Master/texmf-dist/tex/context/base/strc-prc.mkiv)72
-rw-r--r--Master/texmf-dist/tex/context/base/typo-rep.lua43
-rw-r--r--Master/texmf-dist/tex/context/base/typo-rep.mkiv12
-rw-r--r--Master/texmf-dist/tex/context/base/typo-scr.mkiv104
-rw-r--r--Master/texmf-dist/tex/context/base/typo-spa.lua116
-rw-r--r--Master/texmf-dist/tex/context/base/typo-spa.mkiv35
-rw-r--r--Master/texmf-dist/tex/context/base/typo-txt.mkvi71
-rw-r--r--Master/texmf-dist/tex/context/base/unic-000.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-001.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-002.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-003.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-004.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-005.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-030.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-031.mkii3
-rw-r--r--Master/texmf-dist/tex/context/base/unic-032.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-033.mkii6
-rw-r--r--Master/texmf-dist/tex/context/base/unic-034.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-035.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-037.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-039.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-251.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-cjk.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-exp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/unic-ini.mkiv16
-rw-r--r--Master/texmf-dist/tex/context/base/unic-run.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/util-deb.lua121
-rw-r--r--Master/texmf-dist/tex/context/base/util-dim.lua31
-rw-r--r--Master/texmf-dist/tex/context/base/util-lua.lua19
-rw-r--r--Master/texmf-dist/tex/context/base/util-pck.lua44
-rw-r--r--Master/texmf-dist/tex/context/base/util-prs.lua18
-rw-r--r--Master/texmf-dist/tex/context/base/util-seq.lua113
-rw-r--r--Master/texmf-dist/tex/context/base/util-sto.lua24
-rw-r--r--Master/texmf-dist/tex/context/base/util-str.lua63
-rw-r--r--Master/texmf-dist/tex/context/base/util-tab.lua85
-rw-r--r--Master/texmf-dist/tex/context/base/verb-c.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/verb-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/verb-js.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/verb-jv.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/verb-mp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/verb-pl.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/verb-tex.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-asciimath.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/x-asciimath.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/x-calcmath.lua3
-rw-r--r--Master/texmf-dist/tex/context/base/x-calcmath.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-calcmath.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/x-cals.lua65
-rw-r--r--Master/texmf-dist/tex/context/base/x-cals.mkiv13
-rw-r--r--Master/texmf-dist/tex/context/base/x-chemml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-chemml.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/x-contml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-corres.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-ct.lua79
-rw-r--r--Master/texmf-dist/tex/context/base/x-ct.mkiv6
-rw-r--r--Master/texmf-dist/tex/context/base/x-dir-01.tex2
-rw-r--r--Master/texmf-dist/tex/context/base/x-dir-05.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-dir-05.mkiv4
-rw-r--r--Master/texmf-dist/tex/context/base/x-entities.mkiv18
-rw-r--r--Master/texmf-dist/tex/context/base/x-fe.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-fig-00.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-fig-01.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-fig-02.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-fig-03.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-fo.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-foxet.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-foxet.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/x-ldx.lua93
-rw-r--r--Master/texmf-dist/tex/context/base/x-ldx.mkiv13
-rw-r--r--Master/texmf-dist/tex/context/base/x-mathml.lua205
-rw-r--r--Master/texmf-dist/tex/context/base/x-mathml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-mathml.mkiv345
-rw-r--r--Master/texmf-dist/tex/context/base/x-newcml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-newmme.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-newmml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-newmml.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/x-newmmo.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-newpml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-pfs-01.mkiv399
-rw-r--r--Master/texmf-dist/tex/context/base/x-pfsense.ctx15
-rw-r--r--Master/texmf-dist/tex/context/base/x-physml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-physml.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-00.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-01.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-01.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-02.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-03.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-04.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-08.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-09.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-10.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-11.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-12.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-20.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-50.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-res-50.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/x-sch-00.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-sch-01.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-set-01.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-set-02.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-set-11.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-set-11.mkiv7
-rw-r--r--Master/texmf-dist/tex/context/base/x-set-12.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-set-12.mkiv5
-rw-r--r--Master/texmf-dist/tex/context/base/x-steps.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-steps.mkiv99
-rw-r--r--Master/texmf-dist/tex/context/base/x-udhr.mkiv98
-rw-r--r--Master/texmf-dist/tex/context/base/x-xml-01.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-xml-02.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-xml-11.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/x-xtag.mkiv62
-rw-r--r--Master/texmf-dist/tex/context/base/xetx-ini.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-ent.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-exp.mkii4
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-ext.mkii6
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-hyp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-ini.mkii129
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-map.mkii10
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-mmc.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-mml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-mmp.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-pml.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-pmu.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-pre.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-prs.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-raw.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-rng.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-run.mkii64
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-stk.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-utf.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-xsd.mkii2
-rw-r--r--Master/texmf-dist/tex/context/base/xtag-xsl.mkii4
-rw-r--r--Master/texmf-dist/tex/context/fonts/antykwapoltawskiego.lfg2
-rw-r--r--Master/texmf-dist/tex/context/fonts/asana-math.lfg18
-rw-r--r--Master/texmf-dist/tex/context/fonts/cambria-math.lfg27
-rw-r--r--Master/texmf-dist/tex/context/fonts/demo.lfg18
-rw-r--r--Master/texmf-dist/tex/context/fonts/lm-math.lfg100
-rw-r--r--Master/texmf-dist/tex/context/fonts/lm.lfg199
-rw-r--r--Master/texmf-dist/tex/context/fonts/lucida-opentype-math.lfg12
-rw-r--r--Master/texmf-dist/tex/context/fonts/lucida-typeone-math.lfg (renamed from Master/texmf-dist/tex/context/fonts/lucida-math.lfg)6
-rw-r--r--Master/texmf-dist/tex/context/fonts/px-math.lfg1
-rw-r--r--Master/texmf-dist/tex/context/fonts/tx-math.lfg1
-rw-r--r--Master/texmf-dist/tex/context/fonts/xits-math.lfg25
-rw-r--r--Master/texmf-dist/tex/context/interface/cont-cs.xml32
-rw-r--r--Master/texmf-dist/tex/context/interface/cont-de.xml32
-rw-r--r--Master/texmf-dist/tex/context/interface/cont-en.xml30
-rw-r--r--Master/texmf-dist/tex/context/interface/cont-fr.xml32
-rw-r--r--Master/texmf-dist/tex/context/interface/cont-it.xml32
-rw-r--r--Master/texmf-dist/tex/context/interface/cont-nl.xml40
-rw-r--r--Master/texmf-dist/tex/context/interface/cont-pe.xml32
-rw-r--r--Master/texmf-dist/tex/context/interface/cont-ro.xml32
-rw-r--r--Master/texmf-dist/tex/context/interface/keys-cs.xml43
-rw-r--r--Master/texmf-dist/tex/context/interface/keys-de.xml67
-rw-r--r--Master/texmf-dist/tex/context/interface/keys-en.xml67
-rw-r--r--Master/texmf-dist/tex/context/interface/keys-fr.xml43
-rw-r--r--Master/texmf-dist/tex/context/interface/keys-it.xml43
-rw-r--r--Master/texmf-dist/tex/context/interface/keys-nl.xml47
-rw-r--r--Master/texmf-dist/tex/context/interface/keys-pe.xml43
-rw-r--r--Master/texmf-dist/tex/context/interface/keys-ro.xml43
-rw-r--r--Master/texmf-dist/tex/context/sample/mill.pngbin154867 -> 154869 bytes
-rw-r--r--Master/texmf-dist/tex/context/test/pdf-a1a-2005.mkiv7
-rw-r--r--Master/texmf-dist/tex/context/test/pdf-a1b-2005.mkiv8
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-basics-gen.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-basics-gen.lua)65
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-basics-nod.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-basics-nod.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-basics.tex (renamed from Master/texmf-dist/tex/generic/context/luatex-basics.tex)2
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-cbk.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-cbk.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-def.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-def.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-demo-vf-1.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-enc.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-enc.lua)2
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-ext.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-ext.lua)6
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-lua.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-lua.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-merged.lua)3750
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-syn.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-syn.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-tfm.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts-tfm.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts.lua)19
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.tex (renamed from Master/texmf-dist/tex/generic/context/luatex-fonts.tex)2
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-mplib.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-mplib.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-mplib.tex (renamed from Master/texmf-dist/tex/generic/context/luatex-mplib.tex)2
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-plain.tex25
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor-test.tex (renamed from Master/texmf-dist/tex/generic/context/luatex-preprocessor-test.tex)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor.lua (renamed from Master/texmf-dist/tex/generic/context/luatex-preprocessor.lua)0
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor.tex (renamed from Master/texmf-dist/tex/generic/context/luatex-preprocessor.tex)2
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-test.tex (renamed from Master/texmf-dist/tex/generic/context/luatex-test.tex)4
-rw-r--r--Master/texmf-dist/tex/generic/context/m-metapo.tex89
-rw-r--r--Master/texmf-dist/tex/generic/context/mptopdf/mptopdf.tex (renamed from Master/texmf-dist/tex/generic/context/mptopdf.tex)2
-rw-r--r--Master/texmf-dist/tex/generic/context/ppchtex/m-ch-de.tex (renamed from Master/texmf-dist/tex/generic/context/m-ch-de.tex)0
-rw-r--r--Master/texmf-dist/tex/generic/context/ppchtex/m-ch-en.tex (renamed from Master/texmf-dist/tex/generic/context/m-ch-en.tex)0
-rw-r--r--Master/texmf-dist/tex/generic/context/ppchtex/m-ch-nl.tex (renamed from Master/texmf-dist/tex/generic/context/m-ch-nl.tex)0
-rw-r--r--Master/texmf-dist/tex/generic/context/ppchtex/ppchtex.noc (renamed from Master/texmf-dist/tex/generic/context/ppchtex.noc)0
-rw-r--r--Master/texmf-dist/tex/latex/context/m-metapo.sty5
-rw-r--r--Master/texmf-dist/tex/latex/context/ppchtex/m-ch-de.sty (renamed from Master/texmf-dist/tex/latex/context/m-ch-de.sty)0
-rw-r--r--Master/texmf-dist/tex/latex/context/ppchtex/m-ch-en.sty (renamed from Master/texmf-dist/tex/latex/context/m-ch-en.sty)0
-rw-r--r--Master/texmf-dist/tex/latex/context/ppchtex/m-ch-nl.sty (renamed from Master/texmf-dist/tex/latex/context/m-ch-nl.sty)0
-rw-r--r--Master/texmf-dist/tex/latex/context/ppchtex/m-pictex.sty (renamed from Master/texmf-dist/tex/latex/context/m-pictex.sty)0
-rw-r--r--Master/texmf/web2c/texmfcnf.lua4
1507 files changed, 219137 insertions, 100486 deletions
diff --git a/Build/source/texk/texlive/context/Makefile.am b/Build/source/texk/texlive/context/Makefile.am
index 29816af7058..3554daae853 100644
--- a/Build/source/texk/texlive/context/Makefile.am
+++ b/Build/source/texk/texlive/context/Makefile.am
@@ -17,7 +17,6 @@ dist_bin_SCRIPTS = \
luatools \
mtxrun \
pstopdf \
- rlxtools \
texexec \
texmfstart
endif !WIN32
diff --git a/Build/source/texk/texlive/context/Makefile.in b/Build/source/texk/texlive/context/Makefile.in
index ca7960d8f9c..c0b8b94590c 100644
--- a/Build/source/texk/texlive/context/Makefile.in
+++ b/Build/source/texk/texlive/context/Makefile.in
@@ -61,7 +61,7 @@ mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__dist_bin_SCRIPTS_DIST = context ctxtools luatools mtxrun pstopdf \
- rlxtools texexec texmfstart
+ texexec texmfstart
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -193,7 +193,6 @@ top_srcdir = @top_srcdir@
@WIN32_FALSE@ luatools \
@WIN32_FALSE@ mtxrun \
@WIN32_FALSE@ pstopdf \
-@WIN32_FALSE@ rlxtools \
@WIN32_FALSE@ texexec \
@WIN32_FALSE@ texmfstart
diff --git a/Build/source/texk/texlive/context/mtxrun b/Build/source/texk/texlive/context/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Build/source/texk/texlive/context/mtxrun
+++ b/Build/source/texk/texlive/context/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Build/source/texk/texlive/context/rlxtools b/Build/source/texk/texlive/context/rlxtools
deleted file mode 100755
index 3c62a592c62..00000000000
--- a/Build/source/texk/texlive/context/rlxtools
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-mtxrun --script rlxtools "$@"
diff --git a/Master/bin/alpha-linux/mtxrun b/Master/bin/alpha-linux/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/alpha-linux/mtxrun
+++ b/Master/bin/alpha-linux/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/amd64-freebsd/mtxrun b/Master/bin/amd64-freebsd/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/amd64-freebsd/mtxrun
+++ b/Master/bin/amd64-freebsd/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/amd64-kfreebsd/mtxrun b/Master/bin/amd64-kfreebsd/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/amd64-kfreebsd/mtxrun
+++ b/Master/bin/amd64-kfreebsd/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/i386-cygwin/mtxrun b/Master/bin/i386-cygwin/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/i386-cygwin/mtxrun
+++ b/Master/bin/i386-cygwin/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/i386-freebsd/mtxrun b/Master/bin/i386-freebsd/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/i386-freebsd/mtxrun
+++ b/Master/bin/i386-freebsd/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/i386-kfreebsd/mtxrun b/Master/bin/i386-kfreebsd/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/i386-kfreebsd/mtxrun
+++ b/Master/bin/i386-kfreebsd/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/i386-linux/mtxrun b/Master/bin/i386-linux/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/i386-linux/mtxrun
+++ b/Master/bin/i386-linux/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/i386-netbsd/mtxrun b/Master/bin/i386-netbsd/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/i386-netbsd/mtxrun
+++ b/Master/bin/i386-netbsd/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/i386-solaris/mtxrun b/Master/bin/i386-solaris/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/i386-solaris/mtxrun
+++ b/Master/bin/i386-solaris/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/mips-irix/mtxrun b/Master/bin/mips-irix/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/mips-irix/mtxrun
+++ b/Master/bin/mips-irix/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/powerpc-aix/mtxrun b/Master/bin/powerpc-aix/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/powerpc-aix/mtxrun
+++ b/Master/bin/powerpc-aix/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/powerpc-linux/mtxrun b/Master/bin/powerpc-linux/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/powerpc-linux/mtxrun
+++ b/Master/bin/powerpc-linux/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/sparc-linux/mtxrun b/Master/bin/sparc-linux/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/sparc-linux/mtxrun
+++ b/Master/bin/sparc-linux/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/sparc-solaris/mtxrun b/Master/bin/sparc-solaris/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/sparc-solaris/mtxrun
+++ b/Master/bin/sparc-solaris/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/universal-darwin/mtxrun b/Master/bin/universal-darwin/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/universal-darwin/mtxrun
+++ b/Master/bin/universal-darwin/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/win32/mtxrun.dll b/Master/bin/win32/mtxrun.dll
index 4116c5a24a6..4116c5a24a6 100755..100644
--- a/Master/bin/win32/mtxrun.dll
+++ b/Master/bin/win32/mtxrun.dll
Binary files differ
diff --git a/Master/bin/win32/mtxrun.lua b/Master/bin/win32/mtxrun.lua
index 7adcd3023a8..335c4fcb9e0 100755..100644
--- a/Master/bin/win32/mtxrun.lua
+++ b/Master/bin/win32/mtxrun.lua
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/x86_64-darwin/mtxrun b/Master/bin/x86_64-darwin/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/x86_64-darwin/mtxrun
+++ b/Master/bin/x86_64-darwin/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/x86_64-linux/mtxrun b/Master/bin/x86_64-linux/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/x86_64-linux/mtxrun
+++ b/Master/bin/x86_64-linux/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/bin/x86_64-solaris/mtxrun b/Master/bin/x86_64-solaris/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/bin/x86_64-solaris/mtxrun
+++ b/Master/bin/x86_64-solaris/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/texmf-dist/context/data/scite/cont-cs-scite.properties b/Master/texmf-dist/context/data/scite/cont-cs-scite.properties
deleted file mode 100644
index 5c9cc3354df..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-cs-scite.properties
+++ /dev/null
@@ -1 +0,0 @@
-keywordclass.macros.context.cs=CAP Cap Caps MESIC Rimskecislice SLOVA SLOVO Slova Slovo VSEDNIDEN Znak Znaky aktualnicislonadpisu aktualnidatum appendix barva bilemisto bublinkovanapoveda bypassblocks cap cernalinka cernelinky chapter chem cisla cislonadpisu citace citovat comment completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregister coupledregister crlf datum definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling definetype definetypeface definuj definujbarvu definujblok definujbloksekce definujbuffer definujfont definujformatodkazu definujinterakcnimenu definujinterakcnimenu definujkombinovanyseznam definujkonverzi definujlogo definujnadpis definujobrazeksymbol definujodkaz definujodsazovani definujodstavce definujopis definujoramovani definujoramovanytext definujpaletu definujplvouciobjekt definujpodpole definujpole definujpopis definujpopisek definujprekryv definujpreskok definujprofil definujprogram definujprostredizakladnihofontu definujrejstrik definujsablonutabulky definujsekci definujseznam definujseznamodkazu definujskupinubarev definujstartstop definujsymbol definujsynonumumfontu definujsynonyma definujtabelaci definujtext definujtrideni definujupravu definujvelikostpapiru definujverzi definujvycet definujvystup definujzakladnifont definujzasobnikpoli definujznaceni description dodrzujprofil dodrzujverzi dodrzujverziprofilu dvoustrannypapir emptylines enumeration externiobraz footnotetext forceblocks framedtext hl hlavnijazyk indentation ininner inouter instalacejazyka interakcnilista interakcnitlacitka jazyk jdidolu jdina jdinabox klonujpole konvertujcislo kopirujpole korekcebilehomista labeling listsymbol loadsorts loadsynonyms mapfontsize marginalnilinka marginalnitext matematika mediaeval meritko mesic mezera mrizka nadpis nadruhyokraj name naokraj nastavbarvu nastavbarvy nastavbilamista nastavblok nastavbloksekce nastavbuffer nastavcernelinky nastavcislonadpisu nastavcislostrany nastavcislovani nastavcislovaniodstavcu nastavcislovaniradku nastavcislovanistran nastavcitaci nastavdefinicipoznamekpodcarou nastavdeleniplvoucichobjektu nastavdelitko nastavdolnitexty nastavexterniobrazy nastavhorejsek nastavhornitexty nastavinterakci nastavinterakcnilistu nastavinterakcnimenu nastavinterakcniobrazovku nastavjazyk nastavkapitalky nastavkombinovanyseznam nastavkomentar nastavlegendu nastavmarginalie nastavmarginalniblok nastavmarginalnilinky nastavmeziradkovoumezeru nastavnadpis nastavnadpisy nastavodkazovani nastavodsazeni nastavodsazovani nastavodstavce nastavopis nastavoramovanetexty nastavoramovani nastavorez nastavotoceni nastavpaletu nastavplvouciobjekt nastavplvouciobjekty nastavpodcislostrany nastavpodtrzeni nastavpole nastavpolozky nastavpopisek nastavpopisky nastavpopisy nastavpozadi nastavpozadi nastavpoznamkypodcarou nastavprechodstrany nastavpreskok nastavprofily nastavprogramy nastavprostredizakladnihofontu nastavpublikace nastavradkovani nastavradky nastavrastr nastavrejstrik nastavrovnice nastavsadusymbolu nastavsekci nastavseznam nastavseznamodkazu nastavsirkucary nastavsloupce nastavspodek nastavspojeni nastavsynchronizaci nastavsynchronizacnilistu nastavsynonyma nastavsystem nastavtab nastavtabelaci nastavtabulky nastavtenkelinky nastavtext nastavtexthlavicky nastavtextovelinky nastavtextpopisku nastavtexttexty nastavtextyupati nastavtextyzahlavi nastavtlacitka nastavtoleranci nastavtrideni nastavtype nastavumisteniprotejsku nastavumistovani nastavupati nastavupravu nastavurl nastavusporadani nastavvelikostpapiru nastavverze nastavvsechnapole nastavvycty nastavvyplnovelinky nastavvyplnoveradky nastavvystup nastavvzhled nastavzahlavi nastavzakladnifont nastavzarovnani nastavznaceni nastavzuzeni nastrane nejakyradek nekde nextsection nivy nizky nocap nop obrazovka odkaz odkaz odkaznadatum odkaznastranu odkaznatext odsazovani okr opis opissoubor oramovani oref orez otocit overbar overbars overstrike overstrikes oznacverzi paragraph parovastrana part pis placefloat placelistoffloats placelistofsorts placelistofsynonyms placereferencelist pol pole polozka polozky popisky porovnejpaletu porovnejskupinubarev pozadi pozice poznamka poznamkapodcarou pref prelozit premistinamrizku prepninazakladnifont preskoc prizpusobivepole prizpusobvzhled program propojeneznaceni propojenydokument propojenyrejstrik publikace ran ref register reservefloat reset resettextcontent resetznaceni rimskecislice rozdelplvouciobjekt rozpojeneznaceni roztazene schovejbloky section sedabarva seeregister settextcontent setupfonthandling setupfontsynonym setupforms setupinterlinespace2 setupitemgroup setuplistalternative setuppaper setupstrut sloupec slovovpravo sort spodek stanovcharakteristickuseznamu stanovcislonadpisu startalignment startbarva startbuffer startbuffer startcitace startcolumns startcombination startcomment startdescription startdocument startenumeration startfakt startfigure startfloattext startformula startframedtext starthiding startinteraktivnimenu startitemgroup startkomponenta startlegend startline startlinecorrection startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginalnilinka startmarginblock startnamemakeup startnarrower startopposite startoverlay startoverview startparagraph startpositioning startpostponing startpozadi startprodukt startprofile startprojekt startprostredi startregister startsymbolset startsynchronization starttable starttables starttabulate starttextovalinka starttyping startunpacked startverze startzhustene stopalignment stopbarva stopbuffer stopbuffer stopcitace stopcolumns stopcombination stopcomment stopdescription stopdocument stopenumeration stopfakt stopfigure stopfloattext stopformula stopframedtext stophiding stopinteraktivnimenu stopitemgroup stopkomponenta stoplegend stopline stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginalnilinka stopmarginblock stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview stopparagraph stoppositioning stoppostponing stoppozadi stopprodukt stopprofile stopprojekt stopprostredi stopsymbolset stopsynchronization stoptable stoptables stoptabulate stoptextovalinka stoptyping stopunpacked stopverze stopzhustene strana sub subject subsection subsubject subsubsection subsubsubject sym symbol synchronizacnilista synchronizovat synonym tab tecky tenkalinka tenkelinky tex texthlavicky textovalinka textpopisku title tlacitko tref tvrdemezery typebuffer typstrany ukazbarvu ukazexterniobrazy ukazmrizku ukaznastaveni ukazpaletu ukazpodpery ukazpole ukazpostredizakladnihofontu ukazramecek ukazsadusymbolu ukazskupinubarev ukazupravu ukazvytisk ukazvzhled ukazzakladnifont umistikombinovanyseznam umistikombinovanyseznam umistilegendu umistiloga umistilokalnipoznamkypodcarou umistinadsebe umistinamrizku umistipodrovnici umistipoznamkypodcarou umistirejstrik umistirejstrik umistirovnici umistiseznam umistivedlesebe umistizalozky underbar underbars usedirectory usetypescript usetypescriptfile uzijURL uzijbloky uzijexternidokument uzijexterniobraz uzijexternisoubor uzijexternisoubory uzijexternizvuk uzijkodovani uzijmodul uzijodkazy uzijprikazy uzijspeciality uzijsymbol verze vl vlasovalinka vlevo vpravo vradku vsedniden vyberbloky vyberpapir vyberverzi vyplnenytext vyplnovelinky vyplnovepole vyplnovyradek vysoky zablokujinterakcnimenu zachovejbloky zadnamezera zadnebilemisto zadnedalsibloky zadnedalsisoubory zadnehorniadolniradky zadneodsazovani zadnezahlaviaupati zadneznaceni zadnyseznam zalozka zapisdorejstriku zapisdoseznamu zapisdoseznamuodkazu zapismeziseznam zaramovani zarovnanonastred zarovnanovlevo zarovnanovpravo zasobnikpoli zaznamovepole zhustene ziskejbuffer ziskejznaceni zlomek znaceni znak znaky zpracujbloky zpracujstranu zrcadlit zref \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cont-cz-scite.properties b/Master/texmf-dist/context/data/scite/cont-cz-scite.properties
deleted file mode 100644
index 256a4ea3bd5..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-cz-scite.properties
+++ /dev/null
@@ -1,76 +0,0 @@
-keywordclass.macros.context.cz=\
- MESIC Rimskecislice SLOVA SLOVO Slova Slovo \
- VSEDNIDEN Znak Znaky aktualnicislonadpisu aktualnidatum arg \
- barva bilemisto bublinkovanapoveda bypassblocks cernalinka cernelinky \
- chem cisla cislonadpisu citace citovat completeregister \
- crlf datum definerawfont definerule definetextposition definetextvariable \
- definetype definuj definujbarvu definujblok definujbloksekce definujbuffer \
- definujfont definujformatodkazu definujinterakcnimenu definujkombinovanyseznam definujkonverzi definujlogo \
- definujnadpis definujobrazeksymbol definujodkaz definujodsazovani definujodstavce definujopis \
- definujoramovani definujoramovanytext definujpaletu definujplvouciobjekt definujpodpole definujpole \
- definujpopis definujpopisek definujprekryv definujpreskok definujprofil definujprogram \
- definujprostredizakladnihofontu definujrejstrik definujsablonutabulky definujsekci definujseznam definujseznamodkazu \
- definujskupinubarev definujstartstop definujsymbol definujsynonyma definujtabelaci definujtext \
- definujtrideni definujupravu definujvelikostpapiru definujverzi definujvycet definujvystup \
- definujzakladnifont definujzasobnikpoli definujznaceni dodrzujprofil dodrzujverzi dodrzujverziprofilu \
- dvoustrannypapir emptylines externiobraz footnotetext forceblocks hl \
- hlavnijazyk ininner inouter instalacejazyka interakcnilista interakcnitlacitka \
- jazyk jdidolu jdina jdinabox klonujpole komentar \
- konvertujcislo kopirujpole korekcebilehomista listsymbol marginalnilinka marginalnitext \
- matematika meritko mesic mezera mrizka nadpis \
- nadruhyokraj nadtrzeni nadtrzeno naokraj nastavbarvu nastavbarvy \
- nastavbilamista nastavblok nastavbloksekce nastavbuffer nastavcernelinky nastavcislonadpisu \
- nastavcislostrany nastavcislovani nastavcislovaniodstavcu nastavcislovaniradku nastavcislovanistran nastavcitaci \
- nastavdefinicipoznamekpodcarou nastavdeleniplvoucichobjektu nastavdelitko nastavdolnitexty nastavexterniobrazy nastavhorejsek \
- nastavhornitexty nastavinterakci nastavinterakcnilistu nastavinterakcniobrazovku nastavjazyk nastavkapitalky \
- nastavkombinovanyseznam nastavkomentar nastavlegendu nastavmarginalie nastavmarginalniblok nastavmarginalnilinky \
- nastavmeziradkovoumezeru nastavnadpis nastavnadpisy nastavodkazovani nastavodsazeni nastavodsazovani \
- nastavodstavce nastavopis nastavoramovanetexty nastavoramovani nastavorez nastavotoceni \
- nastavpaletu nastavplvouciobjekt nastavplvouciobjekty nastavpodcislostrany nastavpodtrzeni nastavpole \
- nastavpolozky nastavpopisek nastavpopisky nastavpopisy nastavpozadi nastavpoznamkypodcarou \
- nastavprechodstrany nastavpreskok nastavprofily nastavprogramy nastavprostredizakladnihofontu nastavpublikace \
- nastavradkovani nastavradky nastavrastr nastavrejstrik nastavsadusymbolu nastavsekci \
- nastavseznam nastavseznamodkazu nastavsirkucary nastavsloupce nastavspodek nastavspojeni \
- nastavsynchronizaci nastavsynchronizacnilistu nastavsynonyma nastavsystem nastavtab nastavtabelaci \
- nastavtabulky nastavtenkelinky nastavtext nastavtexthlavicky nastavtextovelinky nastavtextpopisku \
- nastavtexttexty nastavtextyupati nastavtextyzahlavi nastavtlacitka nastavtoleranci nastavtrideni \
- nastavtype nastavumisteniprotejsku nastavumistovani nastavupati nastavupravu nastavurl \
- nastavusporadani nastavvelikostpapiru nastavverze nastavvsechnapole nastavvycty nastavvyplnovelinky \
- nastavvyplnoveradky nastavvystup nastavvzhled nastavzahlavi nastavzakladnifont nastavzarovnani \
- nastavznaceni nastavzuzeni nastrane nejakyradek nekde nivy \
- nizky nop obrazovka odkaz odkaznadatum odkaznastranu \
- odkaznatext odsazovani okr opis opissoubor oramovani \
- oref orez otocit oznacverzi parovastrana pis \
- placefloat placereferencelist placerule placetextvariable podtrzeni podtrzeno \
- pol pole polozka polozky popisky porovnejpaletu \
- porovnejskupinubarev positiontext pozadi pozice poznamka poznamkapodcarou \
- pref prelozit premistinamrizku prepninazakladnifont preskoc preskrtnuti \
- preskrtnuto prizpusobivepole prizpusobvzhled program propojeneznaceni propojenydokument \
- propojenyrejstrik publikace ran ref reset resetznaceni \
- rimskecislice rozdelplvouciobjekt rozpojeneznaceni roztazene schovejbloky scitani \
- sedabarva settextcontent settextvariable setupforms setupitemgroup setuppaper \
- setuprule setupstrut setuptextposition setuptextvariable sloupec slovovpravo \
- spodek stanovcharakteristickuseznamu stanovcislonadpisu start startbarva startcitace \
- startfakt startinteraktivnimenu startkomentar startkomponenta startmarginalnilinka startpozadi \
- startprodukt startprojekt startprostredi starttextovalinka startverze startzhustene \
- stop stopbarva stopcitace stopfakt stopinteraktivnimenu stopkomentar \
- stopkomponenta stopmarginalnilinka stoppozadi stopprodukt stopprojekt stopprostredi \
- stoptextovalinka stopverze stopzhustene strana switchtorawfont sym \
- symbol synchronizacnilista synchronizovat tab tecky tenkalinka \
- tenkelinky tex texthlavicky textovalinka textpopisku textvariable \
- tlacitko tref tvrdemezery typebuffer typstrany ukazbarvu \
- ukazexterniobrazy ukazmrizku ukaznastaveni ukazpaletu ukazpodpery ukazpole \
- ukazpostredizakladnihofontu ukazramecek ukazsadusymbolu ukazskupinubarev ukazupravu ukazvytisk \
- ukazvzhled ukazzakladnifont umistikombinovanyseznam umistilegendu umistiloga umistilokalnipoznamkypodcarou \
- umistinadsebe umistinamrizku umistipodrovnici umistipoznamkypodcarou umistirejstrik umistirovnici \
- umistiseznam umistivedlesebe umistizalozky uzijURL uzijbloky uzijexternidokument \
- uzijexterniobraz uzijexternisoubor uzijexternisoubory uzijexternizvuk uzijkodovani uzijmodul \
- uzijodkazy uzijprikazy uzijspeciality uzijsymbol verze vl \
- vlasovalinka vlevo vpravo vradku vsedniden vyberbloky \
- vyberpapir vyberverzi vyplnenytext vyplnovelinky vyplnovepole vyplnovyradek \
- vysoky zablokujinterakcnimenu zachovejbloky zadnamezera zadnebilemisto zadnedalsibloky \
- zadnedalsisoubory zadnehorniadolniradky zadneodsazovani zadnezahlaviaupati zadneznaceni zadnyseznam \
- zadnytest zalozka zapisdorejstriku zapisdoseznamu zapisdoseznamuodkazu zapismeziseznam \
- zaramovani zarovnanonastred zarovnanovlevo zarovnanovpravo zasobnikpoli zaznamovepole \
- zhustene ziskejbuffer ziskejznaceni zlomek znaceni znak \
- znaky zpracujbloky zpracujstranu zrcadlit zref
diff --git a/Master/texmf-dist/context/data/scite/cont-de-scite.properties b/Master/texmf-dist/context/data/scite/cont-de-scite.properties
deleted file mode 100644
index 249fc6a5905..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-de-scite.properties
+++ /dev/null
@@ -1 +0,0 @@
-keywordclass.macros.context.de=Buchstabe Buchstaben CAP Cap Caps MONAT Roemischezahlen WOCHENTAG WOERTER WORT Woerter Wort amgitterausrichten amgitterneuausrichten appendix aufseite ausfuellfeld ausfuelltext ausschnitt bearbeitebloecke bearbeiteseite behaltebloecke bei benutzekodierung benutzespezielles beschrifteversion beschriftung bestimmekopfnummer bestimmelistencharakeristika bildschirm blanko bookmark bruch buchstabe buchstaben but bypassblocks cap chapter chem comment completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregister coupledregister crlf datum definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling defineoutput defineschriftsynonym definetype definetypeface definiereabbsymbol definiereabsaetze definiereabschnitt definiereabschnittsblock definierebeschreibung definierebeschreibungen definierebeschriftung definiereblanko definiereblock definiereeinzug definierefarbe definierefarbengruppe definierefeld definierefeldstapel definierefliesstext definierefliesstextumgebung definieregleitobjekt definiereinteraktionsmenue definiereinteraktionsmenue definierekonversion definierelabel definiereliste definierelogo definieren definierenummerierung definiereoverlay definierepalette definierepapierformat definiereprofil definiereprogramme definierepuffer definierereferenz definierereferenzformat definierereferenzliste definiereregister definiereschrift definieresortieren definierestartstop definieresubfeld definieresymbol definieresynonyme definieretabellenvorlage definieretabulator definieretext definieretippen definiereueberschrift definiereumbruch definiereumrahmt definiereumrahmtertext definiereversion definierezusammengestellteliste description doppelseite doppelseitigespapier drehen duennelinie duennerumriss einezeile einziehen emptylines entknuepfebeschriftung enumeration externeabbildung farbe feld feldstapel festesspatium folgeprofil folgeprofilversion folgeversion footnotetext forceblocks format framedtext fussnote gefuelltesrechteck gefuelltezeile gestreckt gitter graufarbe haarlinie hauptsprache heutigesdatum heutigeskopfnummer hintergrund hl hoch holebeschriftung holepuffer imlinken imrechten imumriss in inaktiviereinteraktionsmenue inanderermarginale indentation ininner inmarginalie inouter installieresprache interaktionsbalken interaktionsknopfe inzeile irgendwo its keinebeschriftung keinebloeckemehr keinedateienmehr keinekopfundfusszeilen keineliste keinspatium keinzeilenobenundunten keinzwischenraum kleinerdurchschuss klonierefeld knopf konvertierezahl kopf kopfnummer kopierefeld korrigierezwischenraum labeling labels labeltext linksbuendig listsymbol loadsorts loadsynonyms mapfontsize mar marginallinie marginaltext mathematik mediaeval monat nachunten name nextsection nichteinziehen nocap nop notiz overbar overbars overstrike overstrikes paragraph part passelayoutan passendfeld placefloat placelistoffloats placelistofsorts placelistofsynonyms placereferencelist platzierebookmarks platziereformel platzierefussnoten platzierelegende platziereliste platzierelogo platzierelokalefussnoten platzierenebeneinander platziereregister platziereregister platziereuntereinander platziereunterformel platzierezusammengestellteliste platzierezusammengestellteliste pos position posten programm publikation punkt ran rechteck rechtecke rechtsbuendig ref referenz register registrierefelder reservefloat resettextcontent roemischezahlen ruecksetzten ruecksetztenbeschriftung schreibezumregister schreibezurliste schreibezurreferenzliste schreibezwischenliste section seeregister seite seitenreferenz seitentyp settext setupfonthandling setupfontsynonym setupforms setupinterlinespace2 setupitemgroup setuplistalternative setuppaper setupstrut showsymbolset sort spalte spatium spiegeln sprache startalignment startbuffer startbuffer startcolumns startcombination startcomment startdescription startdocument startenumeration startfarbe startfigure startfloattext startformula startframedtext startgeg starthiding starthintergrund startinteraktionsmenue startitemgroup startkleinerdurchschuss startkomponente startlegend startline startlinecorrection startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginallinie startmarginblock startnamemakeup startnarrower startopposite startoverlay startoverview startparagraph startpositioning startpostponing startprodukt startprofile startprojekt startregister startsymbolset startsynchronization starttable starttables starttabulate starttextlinie starttyping startumgebung startunpacked startversion startzitat stelleabsaetzeein stelleabsatznummerierungein stelleabschnittein stelleabschnittsblockein stelleanordnenein stelleausgabeein stelleausrichtungein stelleausschnittein stellebeschreibungein stellebeschriftungein stellebilderunterschriftein stellebildunterschriftein stellebindestrichein stelleblankoein stelleblockein stelledrehenein stelleduennerumrissein stelleeinziehenein stelleeinzuegein stelleengerein stelleexterneabbildungenein stellefarbeein stellefarbenein stellefeldein stellefelderin stellefliesstextein stellefliesstextumgebungein stelleformelnein stellefussnotendefinitionein stellefussnotenein stellefusszeileein stellefusszeilentextein stellegefuelltesrechteckein stellegefuelltezeileein stellegegenueberplatzierenein stellegleitobjekteein stellegleitobjektein stellehintergruendeein stellehintergrundein stelleinmarginalieein stelleinteraktionein stelleinteraktionsbalkenein stelleinteraktionsbildschirmein stelleinteraktionsmenueein stelleknopfein stellekombinationein stellekommentarein stellekopfzahlein stellekopfzeileein stellekopfzeilentextein stellelabeltextein stellelayoutein stellelegendeein stellelinienbreiteein stellelisteein stellemarginalblockein stellemarginallinieein stellenobenein stellenummerierungein stellepaletteein stellepapierformatein stelleplatziegeteiltegleitobjekt stellepositionierenein stellepostenein stelleprofilein stelleprogrammein stellepublikationein stellepufferein stellerasterein stellerechteckein stellereferenzierenein stellereferenzlisteein stelleregisterein stelleseitennummerein stelleseitennummeriernungein stelleseitenuebergangein stellesortierenein stellespaltenein stellespatiumein stellespracheein stellesymbolsetein stellesynchronisationein stellesynchronisationsbalkenein stellesynonymein stellesystemein stelletabein stelletabellenein stelletabulatorein stelletextein stelletextobenein stelletexttexteein stelletextumrissein stelletextuntenein stelletipein stelletippenein stelletoleranzein stelleueberschriftein stelleueberschriftenein stelleueberschrifttextein stelleumbruchein stelleumrahmtein stelleumrahmtetexteein stelleuntenein stelleunterseitennummerein stelleunterstreichenein stelleurlein stelleversalienein stelleversionein stellezeilenabstandein stellezeilenein stellezeilennumerierungein stellezitierenein stellezusammengestelltelisteein stellezwischenraumein stopalignment stopbuffer stopbuffer stopcolumns stopcombination stopcomment stopdescription stopdocument stopenumeration stopfarbe stopfigure stopfloattext stopformula stopframedtext stopgeg stophiding stophintergrund stopinteraktionsmenue stopitemgroup stopkleinerdurchschuss stopkomponente stoplegend stopline stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginallinie stopmarginblock stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview stopparagraph stoppositioning stoppostponing stopprodukt stopprofile stopprojekt stopsymbolset stopsynchronization stoptable stoptables stoptabulate stoptextlinie stoptyping stopumgebung stopunpacked stopversion stopzitat sub subject subsection subsubject subsubsection subsubsubject sym symbol synchronisationsbalken synchronisieren synonym tab teilegleitobjekt tex textlinie textreferenz tief tiho tip tippedatei tippen tippepuffer title tooltip ueber ueberschrifttext uebersetzten umrahmt underbar underbars usedirectory usetypescript usetypescriptfile verbergebloecke vergleichefarbengruppe vergleichepalette verknuepfebeschriftung verknuepfedokument verknuepfregister version verweis verweisdatum verwendeURL verwendebefehl verwendebloecke verwendeexteresdokument verwendeexterneabbildung verwendeexternedatei verwendeexternedateien verwendeexternestonstueck verwendemodul verwendereferenzen verwendesymbole vl von waehlebloeckeaus waehlepapieraus waehleversionaus wechselezumfliesstext wochentag wortrechts zeigedruck zeigeeinstellungen zeigeexterneabbildungen zeigefarbe zeigefarbengruppe zeigefelder zeigefliesstext zeigefliesstextumgebung zeigegitter zeigelayout zeigepalette zeigerahmen zeigestruts zeigeumbruch zentriert ziffern zitat zitieren zu zurbox zwischenraum \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cont-en-scite.properties b/Master/texmf-dist/context/data/scite/cont-en-scite.properties
deleted file mode 100644
index a83042bf6eb..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-en-scite.properties
+++ /dev/null
@@ -1 +0,0 @@
-keywordclass.macros.context.en=CAP Cap Caps Character Characters MONTH Romannumerals WEEKDAY WORD WORDS Word Words about adaptlayout appendix at atpage background blackrule blackrules blank bookmark but button bypassblocks cap chapter character characters chem clip clonefield color column comment comparecolorgroup comparepalet completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregister convertnumber copyfield correctwhitespace coupledocument coupledregister couplemarking couplepage couplepaper coupleregister crlf currentdate currentheadnumber date decouplemarking define defineblank defineblock definebodyfont definebodyfontDEF definebodyfontREF definebodyfontenvironment definebuffer definecolor definecolorgroup definecombinedlist defineconversion definedescription definedfont defineenumeration definefield definefieldstack definefiguresymbol definefloat definefont definefontfeature definefonthandling definefontsynonym defineframed defineframedtext definehead defineindenting defineinteractionmenu defineinteractionmenu definelabel definelist definelogo definemakeup definemarking defineoutput defineoverlay definepalet definepapersize defineparagraphs defineprofile defineprogram definereference definereferenceformat definereferencelist defineregister definesection definesectionblock definesorting definestartstop definesubfield definesymbol definesynonyms definetabletemplate definetabulate definetext definetype definetypeface definetyping defineversion description determineheadnumber determinelistcharacteristics disableinteractionmenu emptylines enumeration externalfigure field fieldstack fillinfield fillinline fillinrules fillintext fitfield fixedspaces followprofile followprofileversion followversion footnote footnotetext forceblocks fraction framed framedtext from getbuffer getmarking godown goto gotobox graycolor grid hairline head headnumber headtext hideblocks high hl in indentation indenting inframed ininner inleft inline inmargin inothermargin inouter inright installlanguage interactionbar interactionbuttons item items its keepblocks labeling labels labeltext language leftaligned listsymbol loadsorts loadsynonyms logfields lohi low mainlanguage mapfontsize mar marginrule margintext marking markversion mathematics mediaeval midaligned mirror month moveongrid name nextsection nocap noheaderandfooterlines noindenting nolist nomarking nomoreblocks nomorefiles nop nospace note notopandbottomlines nowhitespace numbers overbar overbars overstrike overstrikes packed page pagereference pagetype paragraph part periods placebookmarks placecombinedlist placecombinedlist placefloat placefootnotes placeformula placelegend placelist placelistoffloats placelistofsorts placelistofsynonyms placelocalfootnotes placelogos placeongrid placeontopofeachother placereferencelist placeregister placeregister placesidebyside placesubformula position processblocks processpage program publication quotation quote ran ref reference referral referraldate register reservefloat reset resetmarking resettextcontent rightaligned romannumerals rotate scale screen section seeregister selectblocks selectpaper selectversion settextcontent setupalign setuparranging setupbackground setupbackgrounds setupblackrules setupblank setupblock setupbodyfont setupbodyfontenvironment setupbottom setupbottomtexts setupbuffer setupbuttons setupcapitals setupcaption setupcaptions setupclipping setupcolor setupcolors setupcolumns setupcombinations setupcombinedlist setupcomment setupdescriptions setupenumerations setupexternalfigures setupfield setupfields setupfillinlines setupfillinrules setupfloat setupfloats setupfloatsplitting setupfonthandling setupfontsynonym setupfooter setupfootertexts setupfootnotedefinition setupfootnotes setupforms setupformulae setupframed setupframedtexts setuphead setupheader setupheadertexts setupheadnumber setupheads setupheadtext setuphyphenmark setupindentations setupindenting setupinmargin setupinteraction setupinteractionbar setupinteractionmenu setupinteractionscreen setupinterlinespace setupinterlinespace2 setupitemgroup setupitems setuplabeltext setuplanguage setuplayout setuplegend setuplinenumbering setuplines setuplinewidth setuplist setuplistalternative setupmakeup setupmarginblocks setupmarginrules setupmarking setupnarrower setupnumbering setupoppositeplacing setupoutput setuppagenumber setuppagenumbering setuppagetransitions setuppalet setuppaper setuppapersize setupparagraphnumbering setupparagraphs setuppositioning setupprofiles setupprograms setuppublications setupquote setupreferencelist setupreferencing setupregister setuprotate setupscreens setupsection setupsectionblock setupsorting setupspacing setupstrut setupsubpagenumber setupsymbolset setupsynchronization setupsynchronizationbar setupsynonyms setupsystem setuptab setuptables setuptabulate setuptext setuptextrules setuptexttexts setupthinrules setuptolerance setuptop setuptoptexts setuptype setuptyping setupunderbar setupurl setupversions setupwhitespace showbodyfont showbodyfontenvironment showcolor showcolorgroup showexternalfigures showfields showframe showgrid showlayout showmakeup showpalet showprint showsetups showstruts showsymbolset someline somewhere sort space splitfloat startalignment startbackground startbuffer startbuffer startcolor startcolumns startcombination startcomment startcomponent startdescription startdocument startenumeration startenvironment startfact startfigure startfloattext startformula startframedtext starthiding startinteractionmenu startitemgroup startlegend startline startlinecorrection startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock startmarginrule startnamemakeup startnarrower startopposite startoverlay startoverview startpacked startparagraph startpositioning startpostponing startproduct startprofile startproject startquotation startregister startsymbolset startsynchronization starttable starttables starttabulate starttextrule starttyping startunpacked startversion stopalignment stopbackground stopbuffer stopbuffer stopcolor stopcolumns stopcombination stopcomment stopcomponent stopdescription stopdocument stopenumeration stopenvironment stopfact stopfigure stopfloattext stopformula stopframedtext stophiding stopinteractionmenu stopitemgroup stoplegend stopline stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock stopmarginrule stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview stoppacked stopparagraph stoppositioning stoppostponing stopproduct stopprofile stopproject stopquotation stopsymbolset stopsynchronization stoptable stoptables stoptabulate stoptextrule stoptyping stopunpacked stopversion stretched sub subject subsection subsubject subsubsection subsubsubject switchtobodyfont sym symbol synchronizationbar synchronize synonym tab tex textreference textrule thinrule thinrules title tooltip translate typ type typebuffer typefile underbar underbars useURL useblocks usecommands usedirectory useencoding useexternaldocument useexternalfigure useexternalfile useexternalfiles useexternalsoundtrack usemodule usereferences usespecials usesymbols usetypescript usetypescriptfile version vl weekday whitespace wordright writebetweenlist writetolist writetoreferencelist writetoregister \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cont-fr-scite.properties b/Master/texmf-dist/context/data/scite/cont-fr-scite.properties
deleted file mode 100644
index 5ecccf961dd..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-fr-scite.properties
+++ /dev/null
@@ -1 +0,0 @@
-keywordclass.macros.context.fr=CAP Cap Caps Caractere Caracteres Chiffresromains JOURSEMAINE MOIS MOT MOTS Mot Mots a adaptedisposition ajustechamp alaligne alapage aligneadroite aligneagauche aligneaumilieu appendix arriereplan baha barreinteraction barresynchronisation bas bouton boutonsinteraction but cacheblocs cap caractere caracteres champ changepolicecorps chapter chem chiffresromains citation citer clip clonechamp colonne comment comparegroupecouleur comparepalette completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregistre composeenalinea concernant convertitnumero copitchamp corrigeespaceblanc couleur couleurgrise coupledocument coupledregister couplemarquage couplepapier coupleregistre crlf dactylographier dans dansautremarge dansdroite dansgauche dansmarge date datecourante daterecommandation de decouplemarquage definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling defineframed defineframedtext definetypeface definit definitbloc definitblocsection definitbuffer definitchamp definitcompoalinea definitconversion definitcouleur definitdactylo definitdemarrestoppe definitdescription definitenumeration definitenvironnementpolicecorps definitetiquette definitflottant definitformatreference definitgroupecouleur definitliste definitlisteimbriquee definitlistereference definitlogo definitmakeup definitmarquage definitmenuinteraction definitmenuinteraction definitnotepdp definitpalette definitparagraphes definitpilechamp definitpolice definitpolicecorps definitprofil definitprogramme definitreference definitregistre definitrevetement definitsection definitsortie definitsouschamp definitsymbole definitsymbolefigure definitsynonymepolice definitsynonymes definittabulation definittaillepapier definittete definittexte definittrametableau definittri definittype definitversion definitvide definitvide demarreciter deplacesurgrille description determinecaracteristiqueliste determinenumerotete echelle ecran ecritdansliste ecritdanslistereference ecritentreliste ecritregistre el element elements emptylines enumeration espace espaceblanc espacesfixes etiquettes etire fichierdactylo figureexterne forceblocs fraction framed framedtext gardeblocs grille groupe haut hl indentation inframed inhibemenuinteraction ininner inouter installelangue joursemaine labeling labeltexte langue langueprincipale ligneh lignenoire ligneregleetexte lignesnoires listesymbole loadsorts loadsynonyms logchamp mapfontsize mar margereglee marquage marquageversion marquepage mathematique mediaeval mois montrecadre montrechamps montrecouleur montredisposition montreedition montreenvironnementpolicecorps montrefiguresexternes montregrille montregroupecouleur montrejeusymboles montremakeup montrepalette montrepolicecorps montrereglages montrestruts motdroit name nextsection nocap nop note notepdp numeros numerotete numerotetecourant obtientmarquage oriente overbar overbars overstrike overstrikes page pagedouble paragraph part pasplusdeblocs pasplusdefichiers periodes pilechamp placecoteacote placeflottant placeformule placelegende placelesunsaudessusdesautres placeliste placelisteinmbriquee placelisteinmbriquee placelistereference placelistoffloats placelistofsorts placelistofsynonyms placelogos placemarquespages placenotespdp placenotespdplocales placeregistre placeregistre placesousformule placesurgrille position prendbuffer programme publication qqpart ran raz razmarquage recommandation ref reference referencepage referencetexte reflete register reglealignement reglealineas reglearrangement reglearriereplan reglearriereplans reglebarreinteraction reglebarresynchronisation reglebloc regleblocmarge regleblocsection regleboutons reglebuffer reglecapitales reglechamp reglechamps regleclipping reglecolonnes reglecombinaisons reglecommentaire reglecompoetroite reglecomposeenalinea reglecouleur reglecouleurs regledactylo regledansmarge regledescriptions regledisposition regleecraninteraction regleecrans regleelements regleencadre regleentete regleenumerations regleenvironnementpolicecorps regleepaisseurligne regleespaceblanc regleespacement regleespacementinterligne reglefiguresexternes regleflottant regleflottants regleformulaires regleformules regleinf regleinteraction regleintitule regleintitules reglejeusymboles reglelabeltexte reglelangue reglelegende reglelignes reglelignesnoires reglelignesreglestexte regleliste reglelisteimbriquee reglelistereference reglemakeup reglemargereglee reglemarquage reglemarquagehyphenation reglemenuinteraction reglenotepdp reglenumeropage reglenumerotation reglenumerotationligne reglenumerotationpage reglenumerotationparagraphe reglenumerotete regleoriente reglepalette reglepapier regleparagraphes reglepdp regleplacementopposition reglepolicecorps reglepositionnement regleprofils regleprogrammes reglepublications reglereferencage regleregistre regleremplitligne regleremplitlignesreglees reglesection regleseparationflottant reglesortie reglesouslignage reglesousnumeropage reglestrut reglesup reglesynchronisation reglesynonymes reglesysteme regletab regletableaux regletabulation regletaillepapier regletete regletetes regletexte regletextesentete regletextesinf regletextespdp regletextessup regletextestexte regletextetete regletolerance regletraitsfins regletransitionspage regletri regletype regleurl regleversions remplitchamp remplitligne remplitlignesreglees remplittexte reservefloat resettextcontent sansalinea sansespace sansespaceblanc sanslignesenteteetpdp sanslignessupetinf sansliste sansmarquage sauteblocs section seeregister selectionneblocs selectionnepapier selectionneversion separeflottant settext setupfonthandling setupfontsynonym setupframedtexts setupinterlinespace2 setupitemgroup setuplistalternative sort startalignment startarriereplan startbuffer startbuffer startcitation startcolumns startcombination startcomment startcomposant startcouleur startdescription startdocument startenumeration startenvironement startfait startfigure startfloattext startformula startframedtext startgroupe starthiding startitemgroup startlegend startligneregleetexte startline startlinecorrection startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes startmakeup startmargereglee startmarginblock startmenuinteraction startnamemakeup startnarrower startopposite startoverlay startoverview startparagraph startpositioning startpostponing startproduit startprofile startprojet startregister startsymbolset startsynchronization starttable starttables starttabulate starttyping startunpacked startversion stopalignment stoparriereplan stopbuffer stopbuffer stopcitation stopcolumns stopcombination stopcomment stopcomposant stopcouleur stopdescription stopdocument stopenumeration stopenvironement stopfait stopfigure stopfloattext stopformula stopframedtext stopgroupe stophiding stopitemgroup stoplegend stopligneregleetexte stopline stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmargereglee stopmarginblock stopmenuinteraction stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview stopparagraph stoppositioning stoppostponing stopproduit stopprofile stopprojet stopsymbolset stopsynchronization stoptable stoptables stoptabulate stoptyping stopunpacked stopversion sub subject subsection subsubject subsubsection subsubsubject suggestion suivantprofil suivantversion suivantversionprofil sym symbole synchronise synonym tab tapebuffer tapepage tete tex textemarge textenotepdp textetete title traduire traiteblocs traitepage traitfin traitsfins typ underbar underbars uneligne usedirectory usetypescript usetypescriptfile utiliseURL utiliseblocs utilisecommandes utilisedocumentexterne utiliseencodage utilisefichierexterne utilisefichiersexternes utilisefigureexterne utilisemodule utilisepsiteaudioexterne utilisereferences utilisespecialites utilisesymboles va vaalaboite vaenbas version vide vl \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cont-it-scite.properties b/Master/texmf-dist/context/data/scite/cont-it-scite.properties
deleted file mode 100644
index 699cd0f1e73..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-it-scite.properties
+++ /dev/null
@@ -1 +0,0 @@
-keywordclass.macros.context.it=CAP Cap Caps GIORNOSETTIMANA Lettera Lettere MESE Numeriromani PAROLA PAROLE Parola Parole accoppiacarta accoppiadocumento accoppiamarcatura accoppiapagina accoppiaregistro adattacampo adattalayout al allineacentro allineadestra allineasinistra ap apagina appendix barrainterazione barrasincronizzazione bastablocchi bastafile cambiaafontdeltesto campi camporiempimento cap capello chapter chim circondato citazione clip clonacampo colonna colore coloregrigio comment completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregister confrontagruppocolori confrontatavolozza convertinumero copiacampo correggispaziobianco coupledregister crlf da daqualcheparte data datadioggi datareferral definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling definetypeface definisci definisciambientefontdeltesto definisciblocco definiscibloccosezione definiscibuffer definiscicampo definiscicapoversi definiscicolore definisciconversione definiscidescrizione definiscidimensionicarta definiscielenco definiscielencocombinato definiscienumerazione definiscietichetta definiscifigurasimbolo definiscifont definiscifontdeltesto definisciformatoriferimento definiscigruppocolori definisciincorniciato definisciiniziatermina definiscilistariferimenti definiscilogo definiscimakeup definiscimarcatura definiscimenuinterazione definiscimenuinterazione definiscimodellotabella definiscioggettomobile definisciordinamento definiscioutput definisciprofilo definisciprogramma definisciregistro definiscirientro definisciriferimento definiscirigovuoto definiscisezione definiscisimbolo definiscisinonimi definiscisinonimofont definiscisottocampo definiscisovrapposizione definiscistackcampi definiscitabulato definiscitavolozza definiscitesta definiscitesto definiscitestoincorniciato definiscitype definiscityping definisciversion description determinacarattersticheelenco determinanumerotesta disabilitamenuinterazione el elaborablocchi elaborapagina elementi elemento emptylines enumeration etichette figuraesterna fondo forzablocchi framedtext frazione giornosettimana griglia hl impaccato impostaallineamento impostaambientefontdeltesto impostaampiezzariga impostabarrainterazione impostabarrasincronizzazione impostablocchimargine impostablocco impostabloccosezione impostabuffer impostacampi impostacampo impostacapoversi impostacaption impostacaptions impostacima impostaclippling impostacolonne impostacolore impostacolori impostacombinazioni impostacommento impostadefinizionenotepdp impostadescrizioni impostadimensionicarta impostaelementi impostaelenco impostaelencocombinato impostaenumerazioni impostafigureesterne impostafondo impostafontdeltesto impostaforms impostaformule impostaincorniciato impostainmargine impostainstestazione impostainterazione impostainterlinea impostalayout impostalegenda impostalineemargine impostalineenere impostalineeriempimento impostalineesottili impostalineetesto impostalingua impostalistariferimenti impostamaiuscole impostamakeup impostamarcatura impostamenuinterazione impostamenzione impostanotepdp impostanumerazione impostanumerazionecapoversi impostanumerazionepagina impostanumerazionerighe impostanumeropagina impostanumerosottopagina impostanumerotesta impostaoggettimobili impostaoggettomobile impostaordinamento impostaoutput impostaparranging impostapdp impostapiustretto impostaposizionamento impostaposizionamentoopposti impostaprofili impostaprogrammi impostapubblicazioni impostapulsanti impostaregistro impostarientri impostarientro impostariferimento impostarighe impostarigheriempimento impostarigovuoto impostarotazione impostaschermi impostaschermointerazione impostasegnosillabazione impostasetsimboli impostasezione impostasfondi impostasfondo impostasincronizzazione impostasinonimi impostasistema impostasottolinea impostaspaziatura impostaspaziobianco impostaspezzamentooggettomobile impostastrut impostatab impostatabelle impostatabulato impostatavolozza impostatesta impostateste impostatesticima impostatestifondo impostatestiincorniciati impostatestiintestazioni impostatestipdp impostatesto impostatestoetichette impostatestointestazioni impostatestotesti impostatolleranza impostatransizionepagina impostatype impostatyping impostaurl impostaversioni in inaltromargine incorniciato indentation indestra ininner inmargine inouter inriga insinistra installalingua intorno labeling lettera lettere lineamargine lineanera lineasottile lineatesto lineenere lineeriempimento lineesottili lingua linguaprincipale listsymbol loadsorts loadsynonyms logcampi mapfontsize mar marcatura marcaversione matematica mediaeval menzione mese mettielenco mettielencocombinato mettielencocombinato mettifiancoafianco mettiformula mettiingriglia mettilegenda mettiloghi mettinotepdp mettinotepdplocali mettiregistro mettiregistro mettisegnalibro mettisottoformula mettiunosullaltro mostraambientefontdeltesto mostracampi mostracolore mostracornice mostrafiguresterne mostrafontdeltesto mostragriglia mostragruppocolori mostraimpostazioni mostralyout mostramakeup mostrasetsimboli mostrastampa mostrastruts mostratavolozza name nascondiblocchi nextsection nienteelenco nientelineecimafondo nientelineintestazionepdp nientemarcatura nienterientro nientespazio nientespaziobianco nocap nop nota notapdp numeri numeriromani numerotesta numerotestacorrente overbar overbars overstrike overstrikes pagina paragraph paroladestra part ped pedap placefloat placelistoffloats placelistofsorts placelistofsynonyms placereferencelist posizione prendibuffer prendimarcatura programma pubblicazione pulsante pulsantinterazione punti qualcheriga ran referral register reimposta reimpostamarcatura reservefloat resettextcontent rientro rif riferimento riferimentopagina riferimentotesto riflessione rigariempimento rigovuoto ruota saltablocchi scala schermo scrividentroelenco scriviinelenco scriviinlistariferimenti scriviinregistro section seeregister segnalibro seguiprofilo seguiversione seguiversioneprofilo selezionablocchi selezionacarta selezionaversione separamarcatura settext setupfonthandling setupfontsynonym setupinterlinespace2 setupitemgroup setuplistalternative setuppaper sfondo sim simbolo sincronizza sort spazifissi spazio spaziobianco spezzaoggettomobile spostaagriglia stackcampi startalignment startambiente startbuffer startbuffer startcitazione startcolore startcolumns startcombination startcomment startcomponenet startdescription startdocument startenumeration startfatto startfigure startfloattext startformula startframedtext starthiding startimpaccato startitemgroup startlegend startline startlineamargine startlineatesto startlinecorrection startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock startmenuinterattivo startnamemakeup startnarrower startopposite startoverlay startoverview startparagraph startpositioning startpostponing startprodotto startprofile startprogetto startregister startsfondo startsymbolset startsynchronization starttable starttables starttabulate starttyping startunpacked startversione stirato stopalignment stopambiente stopbuffer stopbuffer stopcitazione stopcolore stopcolumns stopcombination stopcomment stopcomponenet stopdescription stopdocument stopenumeration stopfatto stopfigure stopfloattext stopformula stopframedtext stophiding stopimpaccato stopitemgroup stoplegend stopline stoplineamargine stoplineatesto stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock stopmenuinterattivo stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview stopparagraph stoppositioning stoppostponing stopprodotto stopprofile stopprogetto stopsfondo stopsymbolset stopsynchronization stoptable stoptables stoptabulate stoptyping stopunpacked stopversione sub subject subsection subsubject subsubsection subsubsubject synonym tab testa testoetichetta testoinmargine testoinstestazioni testonotapdp testoriempimento tex tieniblocchi tipopagina title tooltip traduci typ type typebuffer typefile underbar underbars usaURL usablocco usacodifica usacolonnasonoraesterna usacomandi usadocumentoesterno usafiguraesterna usafileesterni usafileesterno usamodulo usariferimenti usasimboli usaspecialita usedirectory usetypescript usetypescriptfile vaia vaiabox vaigiu versione vl \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cont-nl-scite.properties b/Master/texmf-dist/context/data/scite/cont-nl-scite.properties
deleted file mode 100644
index a36e8f475d6..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-nl-scite.properties
+++ /dev/null
@@ -1 +0,0 @@
-keywordclass.macros.context.nl=CAP Cap Caps Letter Letters MAAND Romeins WEEKDAG WOORD WOORDEN Woord Woorden about achtergrond appendix bepaalkopnummer bepaallijstkenmerken blanko blokje blokjes blokkeerinteractiemenu bookmark breuk but button cap chapter chem cijfers citaat citeer clip comment completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms converteernummer copieerveld corrigeerwitruimte coupledregister crlf datum definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling definetypeface definieer definieeralineas definieerbeeldmerk definieerblanko definieerblok definieerbuffer definieerconversie definieerfiguursymbool definieerfont definieerfontsynoniem definieerinteractiemenu definieerinteractiemenu definieerkadertekst definieerkleur definieerkleurgroep definieerkop definieerkorps definieerkorpsomgeving definieerlijst definieermarkering definieeromlijnd definieeropmaak definieeroverlay definieerpalet definieerpapierformaat definieerplaatsblok definieerprofiel definieerprogramma definieerreferentie definieerreferentieformaat definieerreferentielijst definieerregister definieersamengesteldelijst definieersectie definieersectieblok definieersorteren definieerstartstop definieersubveld definieersymbool definieersynoniemen definieertabelvorm definieertabulatie definieertekst definieertype definieertypen definieeruitvoer definieerveld definieerveldstapel definieerversie description doordefinieren doorlabelen doornummeren doorspringen dunnelijn dunnelijnen eenregel enumeration ergens externfiguur forceerblokken framedtext gebruikURL gebruikblokken gebruikcommandos gebruikexterndocument gebruikexternefile gebruikexternefiles gebruikexternfiguur gebruikexterngeluidsfragment gebruikmodule gebruikreferenties gebruikspecials gebruiksymbolen gebruiktypescript gebruiktypescriptfile geenblokkenmeer geenbovenenonderregels geenfilesmeer geenhoofdenvoetregels geenlijst geenmarkering geenspatie geenwitruimte grijskleur haalbuffer haalmarkering haarlijn handhaafblokken hl hoofdtaal hoog huidigedatum huidigekopnummer in inanderemarge inbinnen inbuiten indentation inlijnd inlinker inmarge inrechter inregel inspringen installeertaal interactiebalk interactiebuttons invullijnen invulregel invultekst invulveld items its kantlijn kenmerk kenmerkdatum kleur kloonveld kolom kop kopnummer koppeldocument koppelmarkering koppelpagina koppelpapier koppelregister koptekst laag labeling labels labeltekst laho legeregels letter letters lijstsymbool loadsorts loadsynonyms maand mapfontsize mar margetekst markeer markeerversie mediaeval naar naarbox name nextsection nietinspringen nocap noot nop omlaag omlijnd ontkoppelmarkering op opelkaar oppagina overbar overbars overstrike overstrikes pagina paginareferentie paragraph part paslayoutaan passeerblokken passendveld plaatsbeeldmerken plaatsbookmarks plaatsformule plaatslegenda plaatslijst plaatslokalevoetnoten plaatsnaastelkaar plaatsonderelkaar plaatsopgrid plaatsplaatsblok plaatsreferentielijst plaatsregister plaatsregister plaatssamengesteldelijst plaatssamengesteldelijst plaatssubformule plaatsvoetnoten placelistoffloats placelistofsorts placelistofsynonyms positioneer programma publicatie punten ran ref referentie regellinks regelmidden regelrechts register registreervelden reservefloat reset resetmarkering resettextcontent romeins rooster roteer schaal scherm schrijfnaarlijst schrijfnaarreferentielijst schrijfnaarregister schrijftussenlijst section seeregister selecteerblokken selecteerpapier selecteerversie setupfonthandling setupfontsynonym setupinterlinespace2 setuplistalternative som soortpagina sort spatie spiegel splitsplaatsblok startachtergrond startalignment startbuffer startbuffer startcitaat startcolumns startcombination startcomment startdescription startdocument startenumeration startfigure startfloattext startformula startframedtext startgeg starthiding startinteractiemenu startitemgroup startkantlijn startkleur startlegend startline startlinecorrection startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock startnamemakeup startnarrower startomgeving startonderdeel startopelkaar startopposite startoverlay startoverview startparagraph startpositioning startpostponing startprodukt startprofile startprojekt startregister startsymbolset startsynchronization starttable starttables starttabulate starttekstlijn starttyping startunpacked startversie stelachtergrondenin stelachtergrondin stelalineasin stelarrangerenin stelblankoin stelblokin stelblokjesin stelblokkopjein stelblokkopjesin stelbovenin stelboventekstenin stelbufferin stelbuttonsin stelciterenin stelclipin stelcombinatiesin stelcommentaarin steldoordefinierenin steldoornummerenin steldoorspringenin steldunnelijnenin stelexternefigurenin stelformulesin stelformulierenin stelhoofdin stelhoofdtekstenin stelinmargein stelinspringenin stelinteractiebalkin stelinteractiein stelinteractiemenuin stelinteractieschermin stelinterliniein stelinvullijnenin stelinvulregelsin stelitemgroepin stelitemsin stelkadertekstenin stelkantlijnin stelkapitalenin stelkleurenin stelkleurin stelkolommenin stelkopin stelkopnummerin stelkoppeltekenin stelkoppenin stelkoptekstin stelkorpsin stelkorpsomgevingin stellabeltekstin stellayoutin stellegendain stellijndiktein stellijstin stelmargeblokkenin stelmarkeringin stelnaastplaatsenin stelnummerenin stelomlijndin stelonderin stelonderstrepenin stelondertekstenin stelopmaakin stelpaginanummerin stelpaginanummeringin stelpaginaovergangenin stelpaletin stelpapierformaatin stelpapierin stelparagraafnummerenin stelplaatsblokin stelplaatsblokkenin stelplaatsbloksplitsenin stelpositionerenin stelprofielenin stelprogrammasin stelpublicatiesin stelrastersin stelreferentielijstin stelrefererenin stelregelnummerenin stelregelsin stelregisterin stelroterenin stelsamengesteldelijstin stelsectieblokin stelsectiein stelsmallerin stelsorterenin stelspatieringin stelstrutin stelsubpaginanummerin stelsymboolsetin stelsynchronisatiebalkin stelsynchronisatiein stelsynoniemenin stelsysteemin steltaalin steltabellenin steltabin steltabulatiein steltekstin steltekstinhoudin steltekstlijnenin stelteksttekstenin steltolerantiein steltypein steltypenin steluitlijnenin steluitvoerin stelurlin stelveldenin stelveldin stelversiesin stelvoetin stelvoetnootdefinitiein stelvoetnotenin stelvoettekstenin stelwitruimtein stopachtergrond stopalignment stopbuffer stopbuffer stopcitaat stopcolumns stopcombination stopcomment stopdescription stopdocument stopenumeration stopfigure stopfloattext stopformula stopframedtext stopgeg stophiding stopinteractiemenu stopitemgroup stopkantlijn stopkleur stoplegend stopline stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock stopnamemakeup stopnarrower stopomgeving stoponderdeel stopopelkaar stopopposite stopoverlay stopoverview stopparagraph stoppositioning stoppostponing stopprodukt stopprofile stopprojekt stopsymbolset stopsynchronization stoptable stoptables stoptabulate stoptekstlijn stoptyping stopunpacked stopversie sub subject subsection subsubject subsubsection subsubsubject suggestie switchnaarkorps sym symbool synchronisatiebalk synchroniseer synonym taal tab tekstlijn tekstreferentie tex title toonexternefiguren toongrid tooninstellingen toonkader toonkleur toonkleurgroep toonkorps toonkorpsomgeving toonlayout toonopmaak toonpalet toonprint toonstruts toonsymboolset toonvelden typ type typebuffer typefile uit uitgerekt underbar underbars usecodering usedirectory vastespaties veld veldstapel verbergblokken vergelijkkleurgroep vergelijkpalet verplaatsopgrid versie vertaal verwerkblokken verwerkpagina vl voetnoot voetnoottekst volgprofiel volgprofielversie volgversie volledigregister weekdag wiskunde witruimte woordrechts \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cont-pe-scite.properties b/Master/texmf-dist/context/data/scite/cont-pe-scite.properties
deleted file mode 100644
index c89f52b8f20..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-pe-scite.properties
+++ /dev/null
@@ -1 +0,0 @@
-keywordclass.macros.context.pe=CAP Cap Caps Character Characters MONTH Romannumerals WEEKDAY WORD WORDS Word Words appendix cap chapter chem comment completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms coupledregister crlf definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling definetypeface description enumeration framedtext indentation its labeling loadsorts loadsynonyms mapfontsize mediaeval name nextsection nocap overbar overbars overstrike overstrikes paragraph part placelistoffloats placelistofsorts placelistofsynonyms ran register reservefloat resettextcontent section seeregister setupcapitals setupfonthandling setupfontsynonym setupinterlinespace2 setuplistalternative setupurl sort startalignment startbuffer startbuffer startcolumns startcombination startcomment startdescription startdocument startenumeration startfigure startfloattext startformula startframedtext starthiding startitemgroup startlegend startline startlinecorrection startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock startnamemakeup startnarrower startopposite startoverlay startoverview startparagraph startpositioning startpostponing startprofile startregister startsymbolset startsynchronization starttable starttables starttabulate starttyping startunpacked startتولید startحقیقت startخط‌حاشیه startخط‌متن startرنگ startÙشرده startمحیط startمنوی‌پانل startمولÙÙ‡ startنسخه startنقل‌قول startپروژه startپس‌زمینه stopalignment stopbuffer stopbuffer stopcolumns stopcombination stopcomment stopdescription stopdocument stopenumeration stopfigure stopfloattext stopformula stopframedtext stophiding stopitemgroup stoplegend stopline stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview stopparagraph stoppositioning stoppostponing stopprofile stopsymbolset stopsynchronization stoptable stoptables stoptabulate stoptyping stopunpacked stopتولید stopحقیقت stopخط‌حاشیه stopخط‌متن stopرنگ stopÙشرده stopمحیط stopمنوی‌پانل stopمولÙÙ‡ stopنسخه stopنقل‌قول stopپروژه stopپس‌زمینه sub subject subsection subsubject subsubsection subsubsubject synonym title tooltip typ underbar underbars useURL usedirectory آیتم آیتمها آینه اجباربلوکها از ازکارانداختن‌منوی‌پانل استÙاده‌بلوکها استÙاده‌دستخط‌تایپ استÙاده‌رمزینه استÙاده‌شکل‌خارجی استÙاده‌Ùرمانها استÙاده‌قطعه‌موزیک‌خارجی استÙاده‌مدول استÙاده‌مرجعها استÙاده‌نمادها استÙاده‌نوشتارخارجی استÙاده‌ویژگیها استÙاده‌پرونده‌خارجی استÙاده‌پرونده‌دستخط‌تایپ استÙاده‌پرونده‌های‌خارجی اعدادلاتین اما انتخاب‌برگ انتخاب‌بلوکها انتخاب‌نسخه انتقال‌به‌توری بارگذاری‌آرایش بارگذاری‌آیتمها بارگذاری‌ارجاع بارگذاری‌اندازه‌برگ بارگذاری‌باریکتر بارگذاری‌باÙر بارگذاری‌بالا بارگذاری‌بخش بارگذاری‌بردباری بارگذاری‌برنامه‌ها بارگذاری‌برگ بارگذاری‌بست بارگذاری‌بلوک بارگذاری‌بلوکهای‌حاشیه بارگذاری‌بلوک‌بخش بارگذاری‌تایپ بارگذاری‌تایپ‌کردن بارگذاری‌تب بارگذاری‌ترتیب بارگذاری‌ترتیب بارگذاری‌ترکیب‌ها بارگذاری‌تطابق بارگذاری‌تعریÙ‌پانوشت بارگذاری‌تنظیم بارگذاری‌ته‌برگ بارگذاری‌تورÙتگی بارگذاری‌تورÙتگیها بارگذاری‌توضیح بارگذاری‌ثبت بارگذاری‌جدولها بارگذاری‌جدول‌بندی بارگذاری‌خالی بارگذاری‌خروجی بارگذاری‌خطها بارگذاری‌خطهای‌حاشیه بارگذاری‌خطهای‌سیاه بارگذاری‌خطهای‌متن بارگذاری‌خطها‌ی‌نازک بارگذاری‌درج‌درخطها بارگذاری‌درج‌مخال٠بارگذاری‌درون‌حاشیه بارگذاری‌دوران بارگذاری‌دکمه‌ها بارگذاری‌راهنما بارگذاری‌رنگ بارگذاری‌رنگها بارگذاری‌زبان بارگذاری‌ستونها بارگذاری‌سر بارگذاری‌سربرگ بارگذاری‌سرها بارگذاری‌سیستم بارگذاری‌شرح بارگذاری‌شرح بارگذاری‌شرحها بارگذاری‌شماره‌زیرصÙحه بارگذاری‌شماره‌سر بارگذاری‌شماره‌صÙحه بارگذاری‌شماره‌گذاری بارگذاری‌شماره‌گذاریها بارگذاری‌شماره‌گذاری‌صÙحه بارگذاری‌شماره‌گذاری‌پاراگرا٠بارگذاری‌شماره‌‌گذاری‌خط بارگذاری‌شناور بارگذاری‌شناورها بارگذاری‌شکاÙتن‌شناورها بارگذاری‌شکلهای‌خارجی بارگذاری‌طرح بارگذاری‌طرح‌بندی بارگذاری‌عرض‌خط بارگذاری‌Ùاصله‌بین‌خط بارگذاری‌Ùرمولها بارگذاری‌Ùضای‌سÙید بارگذاری‌Ùضا‌گذاری بارگذاری‌قالبی بارگذاری‌قلم‌متن بارگذاری‌لوح بارگذاری‌لیست بارگذاری‌لیست‌ترکیبی بارگذاری‌لیست‌مرجع بارگذاری‌مترادÙها بارگذاری‌متن بارگذاری‌متنهای‌بالا بارگذاری‌متن‌سر بارگذاری‌متن‌سربرگ بارگذاری‌متن‌قالبی بارگذاری‌متن‌متنها بارگذاری‌متن‌پانوشت بارگذاری‌متن‌پایین بارگذاری‌مجموعه‌نماد بارگذاری‌محیط‌قلم‌متن بارگذاری‌منوی‌پانل بارگذاری‌مکان‌گذاری بارگذاری‌میدان بارگذاری‌میدانها بارگذاری‌میله‌تطابق بارگذاری‌میله‌زیر بارگذاری‌میله‌پانل بارگذاری‌نسخه‌ها بارگذاری‌نشانه‌شکستن بارگذاری‌نشانه‌گذاری بارگذاری‌نشرها بارگذاری‌نقل بارگذاری‌پاراگراÙها بارگذاری‌پانل بارگذاری‌پانوشتها بارگذاری‌پایین بارگذاری‌پرده‌ها بارگذاری‌پرده‌پانل بارگذاری‌پروÙایلها بارگذاری‌پرکردن‌خطها بارگذاری‌پس‌زمینه بارگذاری‌پس‌زمینه‌ها بارگذاری‌چیدن بارگذاری‌گذارصÙحه بارگذاری‌گروه‌آیتم بازنشانی بازنشانی‌نشانه‌گذاری باگذاری‌متن‌برچسب بدون‌بلوکهای‌بیشتر بدون‌تورÙتگی بدون‌خط‌بالاوپایین بدون‌خط‌سروته‌برگ بدون‌Ùایلهای‌بیشتر بدون‌Ùضا بدون‌Ùضای‌سÙید بدون‌لیست بدون‌نشانه‌گذاری برنامه بروبه بروبه‌جعبه بروپایین برچسبها بلند بلوکهای‌پردازش بلوکها‌پنهان بنویس‌بین‌لیست بنویس‌درثبت بنویس‌درلیست‌مرجع بنویس‌در‌لیست تاریخ تاریخ‌جاری تاریخ‌رجوع تایپ تایپ‌باÙر تایپ‌پرونده تب ترجمه تطابق تعری٠تعریÙ‌آرایش تعریÙ‌آرم تعریÙ‌الگوی‌جدول تعریÙ‌اندازه‌برگ تعریÙ‌باÙر تعریÙ‌بخش تعریÙ‌برنامه تعریÙ‌برچسب تعریÙ‌بلوک تعریÙ‌بلوک‌بخش تعریÙ‌تایپ تعریÙ‌تایپ‌کردن تعریÙ‌تبدیل تعریÙ‌ترتیب تعریÙ‌توده‌میدان تعریÙ‌تورÙتگی تعریÙ‌ثبت تعریÙ‌جدول‌بندی تعریÙ‌خالی تعریÙ‌خروجی تعریÙ‌رنگ تعریÙ‌زیرمیدان تعریÙ‌سر تعریÙ‌شرح تعریÙ‌شروع‌پایان تعریÙ‌شماره‌بندی تعریÙ‌شمایل‌مرجع تعریÙ‌شناور تعریÙ‌قالبی تعریÙ‌قلم تعریÙ‌قلم‌متن تعریÙ‌لوح تعریÙ‌لیست تعریÙ‌لیست‌ترکیبی تعریÙ‌لیست‌مرجع تعریÙ‌مترادÙها تعریÙ‌مترادÙ‌قلم تعریÙ‌متن تعریÙ‌متن‌قالبی تعریÙ‌محیط‌قلم‌بدنه تعریÙ‌مرجع تعریÙ‌منوی‌پانل تعریÙ‌منوی‌پانل تعریÙ‌میدان تعریÙ‌نسخه تعریÙ‌نشانه‌گذاری تعریÙ‌نماد تعریÙ‌نمادشکل تعریÙ‌پاراگراÙها تعریÙ‌پروÙایل تعریÙ‌پوشش تعریÙ‌گروه‌رنگ تعیین‌شماره‌سر تعیین‌محتوای‌متن تعیین‌مشخصات‌لیست تغییربه‌قلم‌بدنه تنظیم‌راست تنظیم‌طرح‌بندی تنظیم‌وسط تورÙتگی توری تک ثبت‌زوج ثبت‌کامل جداسازی‌نشانه‌گذاری حاش حر٠حرÙها Ø­Ùظ‌بلوکها خالی خطهای‌سیاه خطهای‌نازک خطها‌خالی خط‌حاشیه خط‌سیاه خط‌متن خط‌مو خط‌نازک خ‌ا خ‌ع در درج‌آرمها درج‌ثبت درج‌ثبت درج‌درخط درج‌درخطها درج‌درمتن درج‌درمیدان درج‌در‌بالای‌یکدیگر درج‌در‌توری درج‌راهنما درج‌زیرÙرمول درج‌شناور درج‌Ùرمول درج‌لیست درج‌لیست‌مختلط درج‌لیست‌مختلط درج‌لیست‌مرجع درج‌پانوشتها درج‌پانوشتهای‌موضعی درج‌چوب‌خط درج‌کنار‌به‌کنار درحاشیه درحاشیه‌دیگر درخارجی درخط درداخلی درراست درصÙحه درقالبی درمورد درون درچپ دریاÙت‌باÙر دریاÙت‌نشانه دوران دکمه دکمه‌پانل رج رجوع رنگ رنگ‌خاکستری روزهÙته ریاضی زبان زبان‌اصلی ستون سر شماره‌سر شماره‌سرجاری شماره‌مبدل شماره‌ها شکاÙتن‌شناور شکل‌خارجی صÙحه صÙحه‌زوج صÙحه‌پردازش عبوربلوکها Ùشرده Ùضا Ùضاهای‌ثابت Ùضای‌سÙید Ùضای‌سÙیدصحیح قالبی لوح‌مقایسه ماه متن‌برچسب متن‌حاشیه متن‌سر متن‌پانوشت مرجع مرجع‌صÙحه مرجع‌متن مقایسه‌گروه‌رنگ مقیاس منÙÛŒ مکان میدان میدانهای‌گزارش میدان‌شبیه‌سازی میدان‌پشته میدان‌کپی میله‌تطابق میله‌پانل نسخه نسخه‌نشانه نشانه‌گذاری نشانه‌گذاری‌زوج نشر نصب‌زبان نقطه‌ها نقل نقل‌قول نم نماد نمادلیست نمایش‌آرایش نمایش‌بارگذاریها نمایش‌بستها نمایش‌توری نمایش‌رنگ نمایش‌شکلهای‌خارجی نمایش‌طرح‌بندی نمایش‌قالب نمایش‌قلم‌بدنه نمایش‌لوح نمایش‌مجموعه‌علامت نمایش‌محیط‌قلم‌بدنه نمایش‌میدانها نمایش‌چاپ نمایش‌گروه‌رنگ نوشتارزوج نوع‌صÙحه پابا پانوشت پایین پرده پرکردن‌میدان پس‌زمینه پیروی‌نسخه پیروی‌نسخه‌پروÙایل پیروی‌پروÙایل چوبخط چپ‌چین کاغذزوج کسر کشیده کلمه‌راست گیره یادداشت یک‌جا یک‌خط \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cont-ro-scite.properties b/Master/texmf-dist/context/data/scite/cont-ro-scite.properties
deleted file mode 100644
index 3f9cc57e160..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-ro-scite.properties
+++ /dev/null
@@ -1 +0,0 @@
-keywordclass.macros.context.ro=CAP CUVANT CUVINTE Cap Caps Cuvant Cuvinte LUNA Litera Litere Numereromane ZIDINSAPTAMANA adapteazaaspect adubuffer adumarcaje afiseazaaspect afiseazacampuri afiseazaculoare afiseazafiguriexterne afiseazafonttext afiseazagrid afiseazagrupculoare afiseazamakeup afiseazamediufonttext afiseazapaleta afiseazarama afiseazasetari afiseazasetsimboluri afiseazastruts afiseazatiparire aliniat aliniatcentru aliniatdreapta aliniatstanga appendix ascundeblocuri barainteractiune barasincronizare blanc but butoaneinteractiune buton camp campumplere cap chapter chem citat clip cloneazacamp coloana comment comparagrupculoare comparapaleta completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregister convertestenumar copiazacamp corecteazaspatiualb coupledregister crlf culoare culoaregri cupleazadocument cupleazamarcaje cupleazaregistru cuvantdreapta data datacurenta datareferit decupleazamarcaje definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling defineste definestealiat definesteantet definesteblanc definestebloc definesteblocsectiune definestebuffer definestecamp definesteconversie definesteculoare definestedescriere definestedimensiunehartie definesteenumerare definesteeticheta definestefloat definestefont definestefonttext definesteformatreferinte definestegrupculori definesteinconjurare definestelista definestelistacombinata definestelistareferinte definestelogo definestemakeup definestemarcaje definestemediulfonttext definestemeniuinteractiune definestemeniuinteractiune definesteoutput definesteoverlay definestepaleta definesteparagraf definesteprofil definesteprogram definestereferinte definesteregistru definestesablontabel definestesectiune definestesimbol definestesimbolfigura definestesinonim definestesinonimfont definestesortare definestestartstop definestestivacampuri definestesubcamp definestetabulatori definestetext definestetexteinconjurate definestetextinconjurat definestetyping definesteversiune definetype definetypeface description despre determinacaracteristicilelistei determinanumartitlu dezactiveazameniuinteractiune din dute dutebox ecran el element element emptylines enumeration etichete faraaliniat farafisiere faraliniiantetsisubsol faraliniisussijos faralista faramarcaje faraspatiu faraspatiualb figuraexterna firdepar folosesteURL folosestebloc folosestecodificarea folosestecomenzi folosestedocumentextern folosestefiguraexterna folosestefisiereexterne folosestefisierextern folosestemodul folosestemuzicaexterna folosestereferinte folosestesimboluri folosestespeciale footnotetext forteazablocuri fractie framed framedtext fundal gatablocuri grid hartiedubla hl impachetat impartefloat in inalt inaltamargine indentation indreapta inframed ininner injos inlinie inouter instalarelimba instanga intins jos jossus la labeling lapagina limba limbaprincipala liniemargine linieneagra liniesubtire linieumplere liniinegre liniisubtiri listsymbol litera litere loadsorts loadsynonyms logcampuri luna mapfontsize mar marcaje marcheazaversiune marginal matematica mediaeval minicitat mutapegrid name nextsection nocap nop nota notasubsol numartitlu numartitlucurent numere numereromane olinie overbar overbars overstrike overstrikes pagina paginadubla paragraph part pastreazablocuri placefloat placelistoffloats placelistofsorts placelistofsynonyms placereferencelist plaseazapegrid plaseazasemnecarte potrivestecamp pozitie proceseazabloc proceseazapagina program publicatie puncte punedeasuprafiecareia punefatainfata puneformula punelegenda punelista punelistacombinata punelistacombinata punelogouri punenotesubsol punenotesubsollocale puneregistru puneregistru punesubformula ran ref referinta referintapagina referintatext referit reflexie register reservefloat reset reseteazamarcaje resettextcontent riglatext rigleumplere roteste saripesteblocuri scala scriebuffer scrieinlista scrieinlistareferinte scrieinregistru scrieintreliste section seeregister selecteazablocuri selecteazahartie selecteazaversiune semncarte setarebarasincronizare setarelimba setareoutput setarepozitie setaresincronizare seteazaaliniat seteazaaliniate seteazaalinierea seteazaantet seteazaaranjareapag seteazaaspect seteazabarainteractiune seteazablanc seteazabloc seteazablocsectiune seteazablocurimarginale seteazabuffer seteazabutoane seteazacamp seteazacampuri seteazaclipping seteazacoloane seteazacombinari seteazacomentariu seteazaculoare seteazaculori seteazadefinireanotasubsol seteazadescriere seteazadimensiunihartie seteazaecrane seteazaecraninteractiune seteazaelemente seteazaenumerare seteazafiguriexterne seteazafloat seteazafloats seteazafonttext seteazaformulare seteazaformule seteazafundal seteazafundaluri seteazagrosimelinie seteazaimpartireafloat seteazainconjurat seteazaingust seteazainteractiunea seteazajos seteazalegenda seteazalegenda seteazalegendele seteazaliniesilabe seteazaliniesubtire seteazalinii seteazaliniimargine seteazaliniinegre seteazaliniiumplere seteazalista seteazalistacombinata seteazalistareferinte seteazamajuscule seteazamakeup seteazamarcaje seteazamarginal seteazamediulfonttext seteazameniuinteractiune seteazaminicitat seteazanotasubsol seteazanumarpagina seteazanumarsubpagina seteazanumartitlu seteazanumerotare seteazanumerotarelinii seteazanumerotarepagina seteazanumerotareparagrafe seteazapaleta seteazaparagrafe seteazaplasareaopozita seteazaprofile seteazaprograme seteazapublicatii seteazareferinte seteazaregistru seteazarigletext seteazarigleumplere seteazarotare seteazasectiune seteazasimbol seteazasinonime seteazasistem seteazasortare seteazaspatiu seteazaspatiualb seteazaspatiuinterliniar seteazastrut seteazasublinie seteazasubsol seteazasus seteazatab seteazatabele seteazatabulatori seteazatext seteazatexteantet seteazatextejos seteazatextesubsol seteazatextesus seteazatextetext seteazatexteticheta seteazatexttitlu seteazatitlu seteazatitluri seteazatoleranta seteazatranzitiepagina seteazatype seteazatyping seteazaurl seteazaversiuni settextcontent setupfonthandling setupfontsynonym setupinterlinespace2 setupitemgroup setuplistalternative setuppaper sim simbol sincronizeaza sort spatiifixate spatiu spatiualb startalignment startbuffer startbuffer startcitat startcolumns startcombination startcomment startcomponenta startculoare startdescription startdocument startenumeration startfact startfigure startfloattext startformula startframedtext startfundal starthiding startimpachetat startitemgroup startlegend startline startlinecorrection startlinenumbering startlines startliniemargine startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock startmediu startmeniuinteractiune startnamemakeup startnarrower startopposite startoverlay startoverview startparagraph startpositioning startpostponing startprodus startprofile startproiect startregister startriglatext startsymbolset startsynchronization starttable starttables starttabulate starttyping startunpacked startversiune stivacampuri stopalignment stopbuffer stopbuffer stopcitat stopcolumns stopcombination stopcomment stopcomponenta stopculoare stopdescription stopdocument stopenumeration stopfact stopfigure stopfloattext stopformula stopframedtext stopfundal stophiding stopimpachetat stopitemgroup stoplegend stopline stoplinecorrection stoplinenumbering stoplines stopliniemargine stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock stopmediu stopmeniuinteractiune stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview stopparagraph stoppositioning stoppostponing stopprodus stopprofile stopproiect stopriglatext stopsymbolset stopsynchronization stoptable stoptables stoptabulate stoptyping stopunpacked stopversiune sub subject subsection subsubject subsubsection subsubsubject synonym tab tex texteticheta textmarginal texttitlu textumplere tippagina title titlu tooltip traduce trecilafonttext typ type typefile underbar underbars undeva urmeazaprofil urmeazaversiune urmeazaversiuneprofil usedirectory usetypescript usetypescriptfile versiune vl zidinsaptamana \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cont-xx-scite.properties b/Master/texmf-dist/context/data/scite/cont-xx-scite.properties
deleted file mode 100644
index 395062b7a3e..00000000000
--- a/Master/texmf-dist/context/data/scite/cont-xx-scite.properties
+++ /dev/null
@@ -1,178 +0,0 @@
-# low level (visible) support macros, english only
-
-keywordclass.macros.context.undocumented.support=\
- doif doifelse doifnot \
- doifnothing doifsomething doifelsenothing \
- doifvalue doifnotvalue doifelsevalue \
- doifdefined doifundefined doifundefinedelse doifdefinedelse \
- doifinset doifinsetelse doifnotinsetelse \
- doifcommon doifnotcommon doifcommonelse \
- doifnextcharelse \
- doiffieldelse \
- ifdefined ifundefined ifconditional \
- setstrut setfontstrut strut begstrut endstrut strutdepth strutheight showstruts verticalstrut \
- newcounter increment decrement doglobal \
- expanded protect unprotect unprotected unexpanded \
- digits \
- snaptogrid \
- hpos vpos \
- readfile \
- donothing \
- doiftextelse doiftext \
- forgetall setlocalhsize localhsize \
- dogotopar dowithnextbox dowithnextboxcontent nextbox \
- tbox bbox sbox struttedbox \
- definemeasure definehspace hspace dontleavehmode \
- convertargument convertcommand \
- appendtoks prependtoks to at and \
- scratchcounter scratchbox scratchdimen scratchskip \
- zeropoint zerocount zerodimen \
- empty emptytoks plusone plustwo \
- setvalue setxvalue setevalue setgvalue letvalue letgvalue globalletvalue getvalue \
- beforesplitstring aftersplitstring splitstring \
- processcommalist processcommacommand commalistelement \
- processaction processallactionsinset processfirstactioninset \
- iftrialtypesetting \
- startbaselinecorrection stopbaselinecorrection \
- startnointerference stopnointerference \
- dorecurse dostepwiserecurse doloop exitloop \
- doifnotflagged doifflagged setflag
-
-# xml specific commands, english only
-
-keywordclass.macros.context.undocumented.xml=\
- defineXMLsave defineXMLgsave defineXMLenvironment defineXMLargument \
- defineXMLignore defineXMLcommand defineXMLgrouped defineXMLpickup defineXMLnested \
- defineXMLstore defineXMLenvironmentsave defineXMLprocess defineXMLsingular \
- saveXMLelement defineXMLgstore saveXMLasdata gsaveXMLasdata defineXMLsavecontent \
- doifXMLdataelse doifXMLdata saveXMLdata processXMLelement startXMLdata stopXMLdata \
- XMLflush flushXMLelement XMLerase \
- XMLpar XMLop doifXMLparelse doifXMLop \
- defXMLstring \
- processXMLbuffer useXMLfilter \
- countXMLchildren \
- startXMLignore stopXMLignore startXMLmapping stopXMLmapping \
- processXMLfile processXMLfilegrouped
-
-# metafun specific commands, english only
-
-keywordclass.macros.context.undocumented.metafun=\
- startMPgraphic stopMPgraphic includeMPgraphic useMPlibrary setupMPvariables \
- startMPenvironment stopMPenvironment startMPinclusions stopMPinclusions \
- MPcolor MPvar MPx MPy MPw MPh MPd MPp \
- starttypescript stoptypescript usetypescript loadmapfile \
- startMPdrawing stopMPdrawing MPdrawingdonetrue getMPdrawing resetMPdrawing \
- startuseMPgraphic stopuseMPgraphic startusableMPgraphic stopusableMPgraphic useMPgraphic \
- startuniqueMPpagegraphic stopuniqueMPpagegraphic uniqueMPpagegraphic \
- startreusableMPgraphic stopreusableMPgraphic reuseMPgraphic \
- startuniqueMPgraphic stopuniqueMPgraphic uniqueMPgraphic
-
-# modules
-
-keywordclass.macros.context.undocumented.modules=\
- setupFLOWcharts setupFLOWshapes setupFLOWlines \
- startFLOWchart stopFLOWchart FLOWchart includeFLOWchart startFLOWcell stopFLOWcell
-
-# english only commands
-
-keywordclass.macros.context.undocumented.common=\
- start stop \
- ConTeXt \
- environment component product project \
- starttextdata stoptextdata \
- definedfont definefontsynonym setupfontsynonym \
- vfilll hfilll \
- startmode startnotmode stopmode stopnotmode doifmode doifnotmode doifmodeelse enablemode disablemode \
- resetlayer definelayer placelayer flushlayer tightlayer setuplayer setlayer setlayerframed \
- definelayerpreset \
- overlayfigure overlaybutton \
- startsetups stopsetups startlocalsetups stoplocalsetups setups \
- setvariables setevariables setgvariables setxvariables getvariable \
- loadmapfile definetypeface usetypescript usetypescriptfile \
- useJSscripts startJSscripts stopJSscripts startJSpreamble stopJSpreamble startJScode stopJScode \
- showfont showaccents showcharacters \
- showlayoutcomponents showgridsnapping showgridboxes \
- startTEXpage stopTEXpage startMPpage stopMPpage \
- bTABLE eTABLE bTR eTR bTD eTD bTH eTH setupTABLE \
- bTABLEhead eTABLEhead bTABLEnext eTABLEnext bTABLEfoot eTABLEfoot bTABLEbody eTABLEbody \
- NC NR VL HL AR SR FR MR LR EQ
-
-# dutch commands (nl)
-
-keywordclass.macros.context.undocumented.main.nl=\
- starttekst stoptekst startstandaardopmaak stopstandaardopmaak \
- definieerlayout \
- definieerplaats \
- omgeving onderdeel projekt produkt \
- startopsomming stopopsomming stelopsommingin definieeritemgroep \
- stelnummeringin
-
-# english commands (en)
-
-keywordclass.macros.context.undocumented.main.en=\
- starttext stoptext startstandardmakeup stopstandardmakeup \
- placefigure definelayout setupencoding \
- defineframedcontent startframedcontent stopframedcontent \
- getfiguredimensionsonly defineexternalfigure \
- definemainfield \
- includemenu \
- starthanging stophanging \
- setupattachments \
- definepagebreak \
- startitemize stopitemize \
- startfrontmatter stopfrontmatter startbackmatter stopbackmatter \
- startbodymatter stopbodymatter startappendices stopappendices \
- definetextbackground setuptextbackground starttextbackground stoptextbackground \
- definepushbutton definepushsymbol \
- setcollector definecollector flushcollector
-
-# german commands (de)
-
-keywordclass.macros.context.undocumented.main.de=\
-
-# czech commands (cz)
-
-keywordclass.macros.context.undocumented.main.cz=\
-
-# italian commands (it)
-
-keywordclass.macros.context.undocumented.main.it=\
-
-# romanian commands (ro)
-
-keywordclass.macros.context.undocumented.main.ro=\
-
-# common undocumented macros
-
-keywordclass.macros.context.undocumented.base=\
- $(keywordclass.macros.context.undocumented.support) \
- $(keywordclass.macros.context.undocumented.xml) \
- $(keywordclass.macros.context.undocumented.metafun) \
- $(keywordclass.macros.context.undocumented.modules) \
- $(keywordclass.macros.context.undocumented.common)
-
-# language specific undocumented macros
-
-keywordclass.macros.context.undocumented.nl=\
- $(keywordclass.macros.context.undocumented.base) \
- $(keywordclass.macros.context.undocumented.main.nl)
-
-keywordclass.macros.context.undocumented.en=\
- $(keywordclass.macros.context.undocumented.base) \
- $(keywordclass.macros.context.undocumented.main.en)
-
-keywordclass.macros.context.undocumented.de=\
- $(keywordclass.macros.context.undocumented.base) \
- $(keywordclass.macros.context.undocumented.main.de)
-
-keywordclass.macros.context.undocumented.cz=\
- $(keywordclass.macros.context.undocumented.base) \
- $(keywordclass.macros.context.undocumented.main.cz)
-
-keywordclass.macros.context.undocumented.it=\
- $(keywordclass.macros.context.undocumented.base) \
- $(keywordclass.macros.context.undocumented.main.it)
-
-keywordclass.macros.context.undocumented.ro=\
- $(keywordclass.macros.context.undocumented.base) \
- $(keywordclass.macros.context.undocumented.main.ro) \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/cscite.rme b/Master/texmf-dist/context/data/scite/cscite.rme
deleted file mode 100644
index f084100c951..00000000000
--- a/Master/texmf-dist/context/data/scite/cscite.rme
+++ /dev/null
@@ -1,50 +0,0 @@
-Files:
-
-cont-nl-scite.properties : keywords for the dutch user interface
-cont-en-scite.properties : keywords for the english user interface
-cont-de-scite.properties : keywords for the german user interface
-cont-cz-scite.properties : keywords for the czech user interface
-cont-it-scite.properties : keywords for the italian user interface
-cont-ro-scite.properties : keywords for the romanian user interface
-cont-xx-scite.properties : additional keywords
-metafun-scite.properties : keywords for the metafun collection
-
-context.properties : a configuration suitable for context
-
-
-Method 1:
-
-Copy the property files to the path where your local "SciTEUser.properties"
-file lives. Add the following entries to "SciTEUser.properties":
-
-import cont-nl-scite
-import cont-en-scite
-import cont-de-scite
-import cont-cz-scite
-import cont-it-scite
-import cont-ro-scite
-import cont-xx-scite
-import metafun-scite
-
-import context
-
-If you want latex syntax higlighting as well, you should also import the file
-"latex-scite.properties" (no suffix needed).
-
-
-Method 2:
-
-Copy the property files to the path where your local "SciTEGlobal.properties"
-file lives.
-
-Copy the files "context.properties to the path where "SciTEUser.properties"
-lives. Add the following entries to "SciTEUser.properties":
-
-import context
-
-
-Info:
-
-Hans Hagen
-PRAGMA ADE, Hasselt NL
-http://www.pragma-ade.com \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/latex-scite.properties b/Master/texmf-dist/context/data/scite/latex-scite.properties
deleted file mode 100644
index 15e3579a784..00000000000
--- a/Master/texmf-dist/context/data/scite/latex-scite.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-keywordclass.macros.latex.all=\
- begin end documentstyle documentclass \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-context.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-context.lua
new file mode 100644
index 00000000000..8c2a59209ed
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-context.lua
@@ -0,0 +1,4 @@
+return {
+ ["constants"]={ "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive", "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint", "points", "halfpoint", "zeroskip", "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi", "normalpagebox", "endoflinetoken", "outputnewlinechar", "emptytoks", "empty", "undefined", "voidbox", "emptybox", "emptyvbox", "emptyhbox", "bigskipamount", "medskipamount", "smallskipamount", "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion", "luatexengine", "pdftexengine", "xetexengine", "unknownengine", "etexversion", "pdftexversion", "xetexversion", "xetexrevision", "activecatcode", "bgroup", "egroup", "endline", "conditionaltrue", "conditionalfalse", "attributeunsetvalue", "uprotationangle", "rightrotationangle", "downrotationangle", "leftrotationangle", "inicatcodes", "ctxcatcodes", "texcatcodes", "notcatcodes", "txtcatcodes", "vrbcatcodes", "prtcatcodes", "nilcatcodes", "luacatcodes", "tpacatcodes", "tpbcatcodes", "xmlcatcodes", "escapecatcode", "begingroupcatcode", "endgroupcatcode", "mathshiftcatcode", "alignmentcatcode", "endoflinecatcode", "parametercatcode", "superscriptcatcode", "subscriptcatcode", "ignorecatcode", "spacecatcode", "lettercatcode", "othercatcode", "activecatcode", "commentcatcode", "invalidcatcode", "tabasciicode", "newlineasciicode", "formfeedasciicode", "endoflineasciicode", "endoffileasciicode", "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode", "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode", "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode", "lessthanasciicode", "morethanasciicode", "doublecommentsignal", "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode", "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode", "primeasciicode", "activemathcharcode", "activetabtoken", "activeformfeedtoken", "activeendoflinetoken", "batchmodecode", "nonstopmodecode", "scrollmodecode", "errorstopmodecode", "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode", "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode", "discretionarygroupcode", "insertgroupcode", "vcentergroupcode", "mathchoicegroupcode", "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "vadjustgroupcode", "charnodecode", "hlistnodecode", "vlistnodecode", "rulenodecode", "insertnodecode", "marknodecode", "adjustnodecode", "ligaturenodecode", "discretionarynodecode", "whatsitnodecode", "mathnodecode", "gluenodecode", "kernnodecode", "penaltynodecode", "unsetnodecode", "mathsnodecode", "charifcode", "catifcode", "numifcode", "dimifcode", "oddifcode", "vmodeifcode", "hmodeifcode", "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode", "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode", "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink", "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint", "interwordspace", "interwordstretch", "interwordshrink", "exheight", "emwidth", "extraspace", "mathsupdisplay", "mathsupnormal", "mathsupcramped", "mathsubnormal", "mathsubcombined", "mathaxisheight", "startmode", "stopmode", "startnotmode", "stopnotmode", "startmodeset", "stopmodeset", "doifmode", "doifmodeelse", "doifnotmode", "startallmodes", "stopallmodes", "startnotallmodes", "stopnotallmodes", "doifallmodes", "doifallmodeselse", "doifnotallmodes", "startenvironment", "stopenvironment", "environment", "startcomponent", "stopcomponent", "component", "startproduct", "stopproduct", "product", "startproject", "stopproject", "project", "starttext", "stoptext", "startdocument", "stopdocument", "documentvariable", "startmodule", "stopmodule", "usemodule", "startTEXpage", "stopTEXpage", "enablemode", "disablemode", "preventmode", "pushmode", "popmode", "typescriptone", "typescripttwo", "typescriptthree", "mathsizesuffix", "mathordcode", "mathopcode", "mathbincode", "mathrelcode", "mathopencode", "mathclosecode", "mathpunctcode", "mathalphacode", "mathinnercode", "mathnothingcode", "mathlimopcode", "mathnolopcode", "mathboxcode", "mathchoicecode", "mathaccentcode", "mathradicalcode", "constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument", "continueifinputfile" },
+ ["helpers"]={ "startsetups", "stopsetups", "startxmlsetups", "stopxmlsetups", "startluasetups", "stopluasetups", "starttexsetups", "stoptexsetups", "startrawsetups", "stoprawsetups", "startlocalsetups", "stoplocalsetups", "starttexdefinition", "stoptexdefinition", "starttexcode", "stoptexcode", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", "booleanmodevalue", "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif", "newlanguage", "newfamily", "newfam", "newhelp", "then", "donothing", "dontcomplain", "donetrue", "donefalse", "htdp", "unvoidbox", "vfilll", "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha", "currentcatcodetable", "defaultcatcodetable", "catcodetablename", "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable", "pushcatcodetable", "popcatcodetable", "restorecatcodes", "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand", "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg", "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern", "ruledhglue", "ruledvglue", "normalhglue", "normalvglue", "ruledpenalty", "scratchcounter", "globalscratchcounter", "scratchdimen", "globalscratchdimen", "scratchskip", "globalscratchskip", "scratchmuskip", "globalscratchmuskip", "scratchtoks", "globalscratchtoks", "scratchbox", "globalscratchbox", "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", "doif", "doifnot", "doifelse", "doifinset", "doifnotinset", "doifinsetelse", "doifnextcharelse", "doifnextoptionalelse", "doifnextbgroupelse", "doifnextparenthesiselse", "doiffastoptionalcheckelse", "doifundefinedelse", "doifdefinedelse", "doifundefined", "doifdefined", "doifelsevalue", "doifvalue", "doifnotvalue", "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse", "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing", "doifdimensionelse", "doifnumberelse", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", "doifassignmentelse", "tracingall", "tracingnone", "loggingall", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", "endgraf", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace", "executeifdefined", "singleexpandafter", "doubleexpandafter", "tripleexpandafter", "dontleavehmode", "removelastspace", "removeunwantedspaces", "wait", "writestatus", "define", "redefine", "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "measure", "getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", "globallet", "glet", "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist", "processaction", "processallactions", "processfirstactioninset", "processallactionsinset", "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect", "firstofoneargument", "firstoftwoarguments", "secondoftwoarguments", "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments", "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments", "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments", "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments", "firstofoneunexpanded", "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments", "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals", "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant", "newmacro", "setnewmacro", "newfraction", "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "modulonumber", "dividenumber", "getfirstcharacter", "doiffirstcharelse", "startnointerference", "stopnointerference", "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "begstrut", "endstrut" },
+} \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-interfaces.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-interfaces.lua
new file mode 100644
index 00000000000..ee7b7571841
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-interfaces.lua
@@ -0,0 +1,10 @@
+return {
+ ["cs"]={ "CAP", "Cap", "Caps", "Cisla", "KAP", "Kap", "Kaps", "MESIC", "Rimskecislice", "SLOVA", "SLOVO", "Slova", "Slovo", "VSEDNIDEN", "Znak", "Znaky", "aktualnicislonadpisu", "aktualnidatum", "appendix", "arg", "atleftmargin", "atrightmargin", "barevnalista", "barva", "bilemisto", "bottomspace", "bublinkovanapoveda", "bydliste", "bypassblocks", "cap", "celkovypocetstran", "cernalinka", "cernelinky", "chapter", "chem", "cisla", "cislonadpisu", "cislopodrovnice", "cislorovnice", "cislostrany", "citace", "citovat", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "coupledregister", "crlf", "cutspace", "datum", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "definepagebreak", "defineplacement", "definerawfont", "definerule", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definuj", "definujakcent", "definujbarvu", "definujblok", "definujbloksekce", "definujbuffer", "definujfont", "definujformatodkazu", "definujhbox", "definujhlavnipole", "definujinterakcnimenu", "definujkombinovanyseznam", "definujkonverzi", "definujlogo", "definujnadpis", "definujobrazeksymbol", "definujodkaz", "definujodstavce", "definujopis", "definujoramovani", "definujoramovanytext", "definujpaletu", "definujplvouciobjekt", "definujpodpole", "definujpole", "definujpopis", "definujpopisek", "definujprekryv", "definujpreskok", "definujprikaz", "definujprofil", "definujprogram", "definujprostredizakladnihofontu", "definujrejstrik", "definujsablonutabulky", "definujsekci", "definujseznam", "definujseznamodkazu", "definujskupinubarev", "definujstartstop", "definujstyl", "definujstylfontu", "definujsymbol", "definujsynonumumfontu", "definujsynonyma", "definujtabelaci", "definujtext", "definujtrideni", "definujupravu", "definujvelikostpapiru", "definujverzi", "definujvycet", "definujvystup", "definujzakladnifont", "definujzasobnikpoli", "definujznaceni", "definujznak", "delkaseznamu", "description", "dodrzujprofil", "dodrzujverzi", "dodrzujverziprofilu", "dvoustrannypapir", "emptylines", "enumeration", "externiobraz", "fakt", "footnotetext", "forceblocks", "framedtext", "getnumber", "headsym", "hl", "hlavnijazyk", "hlavniuroven", "hodnotabarvy", "hodnotasedi", "immediatebetweenlist", "immediatetolist", "indentation", "ininner", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "instalacejazyka", "interakcnilista", "interakcnitlacitka", "interaktivnimenu", "jazyk", "jdidolu", "jdina", "jdinabox", "jdinastranu", "jmeno", "kap", "klonujpole", "komponenta", "konvertujcislo", "kopirujpole", "korekcebilehomista", "labeling", "leg", "listsymbol", "loadsorts", "loadsynonyms", "maoramovani", "mapfontsize", "marginalnilinka", "marginalninadpis", "marginalnislovo", "marginalnitext", "matematika", "mazaramovani", "mediaeval", "meritko", "mesic", "mezera", "moveformula", "movesidefloat", "mrizka", "nadpis", "nadruhyokraj", "nalevo", "nalevyokraj", "name", "naokraj", "napravo", "napravyokraj", "nastavbarvu", "nastavbarvy", "nastavbilamista", "nastavblok", "nastavbloksekce", "nastavbuffer", "nastavcernelinky", "nastavcislonadpisu", "nastavcislostrany", "nastavcislovani", "nastavcislovaniodstavcu", "nastavcislovaniradku", "nastavcislovanistran", "nastavcitaci", "nastavdefinicipoznamekpodcarou", "nastavdeleniplvoucichobjektu", "nastavdelitko", "nastavdolnitexty", "nastaveni", "nastavexterniobrazy", "nastavhorejsek", "nastavhornitexty", "nastavinterakci", "nastavinterakcnilistu", "nastavinterakcnimenu", "nastavinterakcniobrazovku", "nastavjazyk", "nastavkapitalky", "nastavkombinovanyseznam", "nastavkomentar", "nastavkomentarstrany", "nastavlegendu", "nastavmarginalie", "nastavmarginalniblok", "nastavmarginalnilinky", "nastavmeziradkovoumezeru", "nastavnadpis", "nastavnadpisy", "nastavodkazovani", "nastavodsazovani", "nastavodstavce", "nastavopis", "nastavoramovanetexty", "nastavoramovani", "nastavorez", "nastavotoceni", "nastavpaletu", "nastavplvouciobjekt", "nastavplvouciobjekty", "nastavpodcislostrany", "nastavpodtrzeni", "nastavpole", "nastavpolozky", "nastavpopisek", "nastavpopisky", "nastavpopisy", "nastavpozadi", "nastavpoznamkypodcarou", "nastavprechodstrany", "nastavpreskok", "nastavprofily", "nastavprogramy", "nastavprostredizakladnihofontu", "nastavpublikace", "nastavradkovani", "nastavradky", "nastavrastr", "nastavrejstrik", "nastavrovnice", "nastavsadusymbolu", "nastavsekci", "nastavseznam", "nastavseznamodkazu", "nastavsirkucary", "nastavsloupce", "nastavspodek", "nastavspojeni", "nastavsynchronizaci", "nastavsynchronizacnilistu", "nastavsynonyma", "nastavsystem", "nastavtab", "nastavtabelaci", "nastavtabulky", "nastavtenkelinky", "nastavtext", "nastavtexthlavicky", "nastavtextovelinky", "nastavtextpopisku", "nastavtexttexty", "nastavtextyupati", "nastavtextyzahlavi", "nastavtlacitka", "nastavtoleranci", "nastavtrideni", "nastavtype", "nastavumisteniprotejsku", "nastavumistovani", "nastavupati", "nastavupravu", "nastavurl", "nastavusporadani", "nastavvelikostpapiru", "nastavverze", "nastavvsechnapole", "nastavvycty", "nastavvyplnovelinky", "nastavvyplnoveradky", "nastavvystup", "nastavvzhled", "nastavzahlavi", "nastavzakladnifont", "nastavzarovnani", "nastavznaceni", "nastavzuzeni", "nastrane", "navigating", "nejakyradek", "nekde", "nextsection", "neznamo", "nivy", "nizky", "nocap", "nokap", "nop", "numberofsubpages", "obrazovka", "odkaz", "odkaznadatum", "odkaznastranu", "odkaznatext", "odkazujici", "odsazenishora", "odsazenizleva", "odsazovani", "okr", "opakovat", "opis", "opissoubor", "oramovani", "oref", "orez", "otocit", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "oznaceni", "oznacverzi", "pagedepth", "pageoffset", "paragraph", "parovastrana", "part", "pis", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placepagenumber", "placerawlist", "placereferencelist", "placerule", "placetextvariable", "plnezneni", "pol", "pole", "polozka", "polozky", "popisky", "poppisek", "porovnejpaletu", "porovnejskupinubarev", "positiontext", "pozadi", "pozice", "poznamka", "poznamkapodcarou", "pref", "prelozit", "premistinamrizku", "prepninazakladnifont", "preskoc", "prizpusobivepole", "prizpusobvzhled", "produkt", "program", "projekt", "propojeneznaceni", "propojenydokument", "propojenyrejstrik", "prostredi", "publikace", "ran", "ref", "register", "reservefloat", "reset", "resetnumber", "resettextcontent", "resetznaceni", "rimskecislice", "rozdelplvouciobjekt", "rozmer", "rozpojeneznaceni", "roztazene", "schovejbloky", "section", "sedabarva", "seeregister", "setnumber", "settextcontent", "settextvariable", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupforms", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setuprule", "setupstartstop", "setupstrut", "setuptextposition", "setuptextvariable", "sirkalevehookraje", "sirkalevemarginalie", "sirkamarginalie", "sirkaokraje", "sirkapapiru", "sirkapravehookraje", "sirkapravemarginalie", "sirkasazby", "sirkaseznamu", "sirkatextu", "sirkatiskpapiru", "sloupec", "slovovpravo", "sort", "spodek", "stanovcharakteristickuseznamu", "stanovcislonadpisu", "startalignment", "startbarva", "startbuffer", "startcislovaniradku", "startcitace", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startdescription", "startdocument", "startdokument", "startenumeration", "startfakt", "startfigure", "startfloattext", "startformula", "startframedtext", "startglobalni", "starthiding", "startinteraktivnimenu", "startitemgroup", "startkodovani", "startkomponenta", "startkorekceradku", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokalni", "startlokalnipoznamkypodcarou", "startmakeup", "startmarginalniblok", "startmarginalnilinka", "startmarginblock", "startnamemakeup", "startnarrower", "startnezhustene", "startobraz", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startpozadi", "startprehled", "startprekryv", "startprodukt", "startprofil", "startprofile", "startprojekt", "startprostredi", "startprotejsek", "startradek", "startradky", "startrastr", "startregister", "startsadasymbolu", "startsloupce", "startspojeni", "startsymbolset", "startsynchronizace", "startsynchronization", "starttable", "starttables", "starttabulate", "starttabulka", "starttabulky", "starttext", "starttextovalinka", "starttyping", "startumistovani", "startunpacked", "startuprava", "startverze", "startzarovnavani", "startzhustene", "startzuzeni", "stopalignment", "stopbarva", "stopbuffer", "stopcislovaniradku", "stopcitace", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopdokument", "stopenumeration", "stopfakt", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopglobalni", "stophiding", "stopinteraktivnimenu", "stopitemgroup", "stopkodovani", "stopkomponenta", "stopkorekceradku", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokalni", "stoplokalnipoznamkypodcarou", "stopmakeup", "stopmarginalniblok", "stopmarginalnilinka", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopnezhustene", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stoppozadi", "stopprehled", "stopprekryv", "stopprodukt", "stopprofil", "stopprofile", "stopprojekt", "stopprostredi", "stopprotejsek", "stopradek", "stopradky", "stoprastr", "stopsloupce", "stopspojeni", "stopsymbolset", "stopsynchronizace", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptabulka", "stoptabulky", "stoptext", "stoptextovalinka", "stoptyping", "stopumistovani", "stopunpacked", "stopuprava", "stopverze", "stopzarovnavani", "stopzhustene", "stopzuzeni", "strana", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtorawfont", "sym", "symbol", "synchronizacnilista", "synchronizovat", "synonym", "tab", "tecky", "tenkalinka", "tenkelinky", "testcolumn", "testpage", "tex", "texthlavicky", "textovalinka", "textpopisku", "textvariable", "title", "tlacitko", "tlacitkomenu", "tloustkacary", "tref", "tvrdamezera", "tvrdemezery", "txt", "typebuffer", "ukazbarvu", "ukazexterniobrazy", "ukazmrizku", "ukaznastaveni", "ukazpaletu", "ukazpodpery", "ukazpole", "ukazpostredizakladnihofontu", "ukazramecek", "ukazsadusymbolu", "ukazskupinubarev", "ukazupravu", "ukazvytisk", "ukazvzhled", "ukazzakladnifont", "umistikombinovanyseznam", "umistilegendu", "umistiloga", "umistilokalnipoznamkypodcarou", "umistinadsebe", "umistinamrizku", "umistipodrovnici", "umistipoznamkypodcarou", "umistirejstrik", "umistirovnici", "umistiseznam", "umistivedlesebe", "umistizalozky", "underbar", "underbars", "urcicharakteristikurejstriku", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "uzijJSscripts", "uzijURL", "uzijadresar", "uzijbloky", "uzijexternidokument", "uzijexterniobraz", "uzijexternisoubor", "uzijexternisoubory", "uzijexternizvuk", "uzijkodovani", "uzijmodul", "uzijmoduly", "uzijodkazy", "uzijprikazy", "uzijspeciality", "uzijsymbol", "uzijurl", "verze", "vl", "vlasovalinka", "vlevo", "vpravo", "vradku", "vsedniden", "vyberbloky", "vyberpapir", "vyberverzi", "vyplnenytext", "vyplnovelinky", "vyplnovepole", "vyplnovyradek", "vyskahorejsku", "vyskapapiru", "vyskasazby", "vyskaseznamu", "vyskaspodku", "vyskatextu", "vyskatiskpapiru", "vyskaupati", "vyskazahlavi", "vysoky", "vyznam", "vzdalenosthorejsku", "vzdalenostlevehookraje", "vzdalenostlevemarginalie", "vzdalenostmarginalie", "vzdalenostokraje", "vzdalenostpravehookraje", "vzdalenostpravemarginalie", "vzdalenostspodku", "vzdalenostupati", "vzdalenostzahlavi", "zablokujinterakcnimenu", "zachovejbloky", "zadnamezera", "zadnebilemisto", "zadnedalsibloky", "zadnedalsisoubory", "zadnehorniadolniradky", "zadneodsazovani", "zadnezahlaviaupati", "zadneznaceni", "zadnyrozmer", "zadnyseznam", "zadnytest", "zalozka", "zapisdorejstriku", "zapisdoseznamu", "zapisdoseznamuodkazu", "zapismeziseznam", "zaramovani", "zarovnanonastred", "zarovnanovlevo", "zarovnanovpravo", "zasobnikpoli", "zaznamovepole", "zhustene", "ziskejbuffer", "ziskejznaceni", "zlomek", "znaceni", "znak", "znaky", "zpracujbloky", "zpracujstranu", "zrcadlit", "zref", "zvysujicicislo" },
+ ["de"]={ "Buchstabe", "Buchstaben", "CAP", "Cap", "Caps", "KAP", "Kap", "Kaps", "MONAT", "Roemischezahlen", "WOCHENTAG", "WOERTER", "WORT", "Woerter", "Wort", "Ziffern", "abstandlinkerrand", "abstandoben", "abstandrechterrand", "abstandunten", "amgitterausrichten", "amgitterneuausrichten", "appendix", "arg", "atleftmargin", "atrightmargin", "aufseite", "ausfuellfeld", "ausfuelltext", "ausschnitt", "bearbeitebloecke", "bearbeiteseite", "bedeutung", "behaltebloecke", "bei", "bemerkung", "benutzekodierung", "benutzespezielles", "benutzeverzeichnis", "beschrifteversion", "beschriftung", "bestimmekopfnummer", "bestimmelistencharakeristika", "bestimmeregistercharakteristika", "bildschirm", "blanko", "bookmark", "bottomspace", "breitelinkerrand", "breiterechterrand", "bruch", "buchstabe", "buchstaben", "but", "bypassblocks", "cap", "chapter", "chem", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "coupledregister", "crlf", "cutspace", "datum", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "defineoutput", "definepagebreak", "defineplacement", "definerawfont", "definerule", "defineschriftsynonym", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definiereabbsymbol", "definiereabsaetze", "definiereabschnitt", "definiereabschnittsblock", "definiereakzent", "definierebefehl", "definierebeschreibung", "definierebeschreibungen", "definierebeschriftung", "definiereblanko", "definiereblock", "definierefarbe", "definierefarbengruppe", "definierefeld", "definierefeldstapel", "definierefliesstext", "definierefliesstextumgebung", "definieregleitobjekt", "definierehauptfeld", "definierehbox", "definiereinteraktionsmenue", "definierekonversion", "definierelabel", "definiereliste", "definierelogo", "definieren", "definierenummerierung", "definiereoverlay", "definierepalette", "definierepapierformat", "definiereprofil", "definiereprogramme", "definierepuffer", "definierereferenz", "definierereferenzformat", "definierereferenzliste", "definiereregister", "definiereschrift", "definiereschriftstil", "definieresortieren", "definierestartstop", "definierestil", "definieresubfeld", "definieresymbol", "definieresynonyme", "definieretabellenvorlage", "definieretabulator", "definieretext", "definieretippen", "definiereueberschrift", "definiereumbruch", "definiereumrahmt", "definiereumrahmtertext", "definiereversion", "definierezeichen", "definierezusammengestellteliste", "description", "dimension", "doppelseite", "doppelseitigespapier", "drehen", "duennelinie", "duennerumriss", "einezeile", "einstellungen", "einziehen", "emptylines", "entknuepfebeschriftung", "enumeration", "externeabbildung", "farbbalken", "farbe", "farbewert", "feld", "feldstapel", "festesspatium", "folgeprofil", "folgeprofilversion", "folgeversion", "footnotetext", "forceblocks", "format", "formelnummer", "framedtext", "fussnote", "fusszeileabstand", "fusszeilenhoehe", "gefuelltesrechteck", "gefuelltezeile", "geg", "gesamtseitenanzahl", "gestreckt", "getnumber", "gitter", "graufarbe", "grauwert", "haarlinie", "hauptsprache", "headsym", "heutigesdatum", "heutigeskopfnummer", "hintergrund", "hl", "hoch", "hoeheoben", "hoeheunten", "holebeschriftung", "holepuffer", "imlinken", "imlinkenrand", "immaumrise", "immediatebetweenlist", "immediatetolist", "imrechten", "imrechtenrand", "imumriss", "in", "inaktiviereinteraktionsmenue", "inanderermarginale", "indentation", "ininner", "inlinkermarginale", "inmarginalie", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inrechtermarginale", "installieresprache", "interaktionsbalken", "interaktionsknopfe", "interaktionsmenue", "inzeile", "irgendwo", "its", "kap", "keindimension", "keinebeschriftung", "keinebloeckemehr", "keinedateienmehr", "keinekopfundfusszeilen", "keineliste", "keinspatium", "keintest", "keinzeilenobenundunten", "keinzwischenraum", "kleinerdurchschuss", "klonierefeld", "knopf", "komponente", "konvertierezahl", "kopf", "kopfniveau", "kopfnummer", "kopfweite", "kopfzeilenabstand", "kopfzeilenhoehe", "kopierefeld", "korrigierezwischenraum", "label", "labeling", "labels", "labeltext", "leg", "liniendicke", "linkemarginalafstand", "linkemarginalbreite", "linksbuendig", "listenbreite", "listenhoehe", "listenlaenge", "listsymbol", "loadsorts", "loadsynonyms", "mapfontsize", "mar", "marginalafstand", "marginalbreite", "marginallinie", "marginaltext", "marginaltitel", "marginalwort", "mathematik", "maumrise", "mediaeval", "menueknopf", "monat", "moveformula", "movesidefloat", "nachunten", "name", "navigating", "nextsection", "nichteinziehen", "nocap", "nokap", "nop", "notiz", "numberofsubpages", "nummererhoehen", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "papierbreite", "papierhoehe", "paragraph", "part", "passelayoutan", "passendfeld", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placepagenumber", "placerawlist", "placereferencelist", "placerule", "placetextvariable", "platzierebookmarks", "platziereformel", "platzierefussnoten", "platzierelegende", "platziereliste", "platzierelogo", "platzierelokalefussnoten", "platzierenebeneinander", "platziereregister", "platziereuntereinander", "platziereunterformel", "platzierezusammengestellteliste", "pos", "position", "positiontext", "posten", "printpapierbreite", "printpapierhoehe", "produkt", "programm", "projekt", "publikation", "punkt", "ran", "randabstand", "randbreite", "rechteck", "rechtecke", "rechtemarginalafstand", "rechtemarginalbreite", "rechtsbuendig", "ref", "referenz", "referieren", "register", "registrierefelder", "reservefloat", "resetnumber", "resettextcontent", "roemischezahlen", "ruecksetzten", "ruecksetztenbeschriftung", "rumpfweite", "satzbreite", "satzhoehe", "schreibezumregister", "schreibezurliste", "schreibezurreferenzliste", "schreibezwischenliste", "section", "seeregister", "seite", "seitenreferenz", "seitenummer", "setnumber", "settext", "settextvariable", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupforms", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setuprule", "setupstartstop", "setupstrut", "setuptextposition", "setuptextvariable", "showsymbolset", "sort", "spalte", "spatium", "spiegeln", "sprache", "startabbildung", "startalignment", "startausrichtung", "startbuffer", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startdescription", "startdocument", "startdokument", "startenger", "startenumeration", "startfarbe", "startfigure", "startfloattext", "startformula", "startframedtext", "startgeg", "startgegenueber", "startglobal", "startgrosserdurchschuss", "starthiding", "starthintergrund", "startinteraktionsmenue", "startitemgroup", "startkleinerdurchschuss", "startkodierung", "startkombination", "startkomponente", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokal", "startlokalefussnoten", "startmakeup", "startmarginalblock", "startmarginallinie", "startmarginblock", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositionieren", "startpositioning", "startpostponing", "startprodukt", "startprofil", "startprofile", "startprojekt", "startraster", "startregister", "startspalten", "startsymbolset", "startsynchronisation", "startsynchronization", "starttabelle", "starttabellen", "starttable", "starttables", "starttabulate", "starttext", "starttextlinie", "starttyping", "startueberblick", "startumbruch", "startumgebung", "startunpacked", "startversion", "startzeile", "startzeilen", "startzeilenkorrektur", "startzeilennumerierung", "startzitat", "stelleabsaetzeein", "stelleabsatznummerierungein", "stelleabschnittein", "stelleabschnittsblockein", "stelleanordnenein", "stelleaufzaehlungenein", "stelleausgabeein", "stelleausrichtungein", "stelleausschnittein", "stellebeschreibungein", "stellebeschriftungein", "stellebilderunterschriftein", "stellebildunterschriftein", "stellebindestrichein", "stelleblankoein", "stelleblockein", "stelledrehenein", "stelleduennerumrissein", "stelleeinziehenein", "stelleengerein", "stelleexterneabbildungenein", "stellefarbeein", "stellefarbenein", "stellefeldein", "stellefelderin", "stellefliesstextein", "stellefliesstextumgebungein", "stelleformelnein", "stellefussnotendefinitionein", "stellefussnotenein", "stellefusszeileein", "stellefusszeilentextein", "stellegefuelltesrechteckein", "stellegefuelltezeileein", "stellegegenueberplatzierenein", "stellegleitobjekteein", "stellegleitobjektein", "stellehintergruendeein", "stellehintergrundein", "stelleinmarginalieein", "stelleinteraktionein", "stelleinteraktionsbalkenein", "stelleinteraktionsbildschirmein", "stelleinteraktionsmenueein", "stelleknopfein", "stellekombinationein", "stellekommentarein", "stellekopfzahlein", "stellekopfzeileein", "stellekopfzeilentextein", "stellelabeltextein", "stellelayoutein", "stellelegendeein", "stellelinienbreiteein", "stellelisteein", "stellemarginalblockein", "stellemarginallinieein", "stellenobenein", "stellenummerierungein", "stellepaletteein", "stellepapierformatein", "stelleplatziegeteiltegleitobjekt", "stellepositionierenein", "stellepostenein", "stelleprofilein", "stelleprogrammein", "stellepublikationein", "stellepufferein", "stellerasterein", "stellerechteckein", "stellereferenzierenein", "stellereferenzlisteein", "stelleregisterein", "stelleseitenkommentarein", "stelleseitennummerein", "stelleseitennummeriernungein", "stelleseitenuebergangein", "stellesortierenein", "stellespaltenein", "stellespatiumein", "stellespracheein", "stellesymbolsetein", "stellesynchronisationein", "stellesynchronisationsbalkenein", "stellesynonymein", "stellesystemein", "stelletabein", "stelletabellenein", "stelletabulatorein", "stelletextein", "stelletextobenein", "stelletexttexteein", "stelletextumrissein", "stelletextuntenein", "stelletipein", "stelletippenein", "stelletoleranzein", "stelleueberschriftein", "stelleueberschriftenein", "stelleueberschrifttextein", "stelleumbruchein", "stelleumrahmtein", "stelleumrahmtetexteein", "stelleuntenein", "stelleunterseitennummerein", "stelleunterstreichenein", "stelleurlein", "stelleversalienein", "stelleversionein", "stellezeilenabstandein", "stellezeilenein", "stellezeilennumerierungein", "stellezitierenein", "stellezusammengestelltelisteein", "stellezwischenraumein", "stopalignment", "stopausrichtung", "stopbuffer", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopdokument", "stopenger", "stopenumeration", "stopfarbe", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgeg", "stopgegenueber", "stopglobal", "stopgrosserdurchschuss", "stophiding", "stophintergrund", "stopinteraktionsmenue", "stopitemgroup", "stopkleinerdurchschuss", "stopkodierung", "stopkombination", "stopkomponente", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokal", "stoplokalefussnoten", "stopmakeup", "stopmarginalblock", "stopmarginallinie", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositionieren", "stoppositioning", "stoppostponing", "stopprodukt", "stopprofil", "stopprofile", "stopprojekt", "stopraster", "stopspalten", "stopsymbolset", "stopsynchronisation", "stopsynchronization", "stoptabelle", "stoptabellen", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptextlinie", "stoptyping", "stopueberblick", "stopumbruch", "stopumgebung", "stopunpacked", "stopversion", "stopzeile", "stopzeilen", "stopzeilenkorrektur", "stopzeilennumerierung", "stopzitat", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtorawfont", "sym", "symbol", "synchronisationsbalken", "synchronisieren", "synonym", "tab", "teilegleitobjekt", "testcolumn", "testpage", "tex", "textbreite", "texthoehe", "textlinie", "textreferenz", "textvariable", "tief", "tiho", "tip", "tippedatei", "tippen", "tippepuffer", "title", "tooltip", "txt", "ueber", "ueberschrifttext", "uebersetzten", "umgebung", "umrahmt", "unbekant", "underbar", "underbars", "unterformelnummer", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "verbergebloecke", "vergleichefarbengruppe", "vergleichepalette", "verknuepfebeschriftung", "verknuepfedokument", "verknuepfregister", "version", "verweis", "verweisdatum", "verwendeJSscript", "verwendeURL", "verwendebefehl", "verwendebloecke", "verwendeexteresdokument", "verwendeexterneabbildung", "verwendeexternedatei", "verwendeexternedateien", "verwendeexternestonstueck", "verwendemodul", "verwendemodule", "verwendereferenzen", "verwendesymbole", "verwendeurl", "vl", "volleswort", "von", "waehlebloeckeaus", "waehlepapieraus", "waehleversionaus", "wechselezumfliesstext", "wiederholen", "wochentag", "wohnort", "wortrechts", "zeigedruck", "zeigeeinstellungen", "zeigeexterneabbildungen", "zeigefarbe", "zeigefarbengruppe", "zeigefelder", "zeigefliesstext", "zeigefliesstextumgebung", "zeigegitter", "zeigelayout", "zeigepalette", "zeigerahmen", "zeigestruts", "zeigeumbruch", "zentriert", "ziffern", "zitat", "zitieren", "zu", "zurbox", "zurseite", "zwischenraum" },
+ ["en"]={ "CAP", "Cap", "Caps", "Character", "Characters", "MONTH", "Numbers", "Romannumerals", "WEEKDAY", "WORD", "WORDS", "Word", "Words", "about", "adaptlayout", "adding", "appendix", "arg", "at", "atleftmargin", "atpage", "atrightmargin", "background", "backspace", "blackrule", "blackrules", "blank", "bookmark", "bottomdistance", "bottomheight", "bottomspace", "but", "button", "bypassblocks", "cap", "chapter", "character", "characters", "chem", "clip", "clonefield", "color", "colorbar", "colorvalue", "column", "comment", "comparecolorgroup", "comparepalet", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completepagenumber", "completeregister", "component", "convertnumber", "copyfield", "correctwhitespace", "coupledocument", "coupledregister", "couplemarking", "couplepage", "couplepaper", "coupleregister", "crlf", "currentdate", "currentheadnumber", "cutspace", "date", "decouplemarking", "decrementnumber", "define", "defineaccent", "defineblank", "defineblock", "definebodyfont", "definebodyfontDEF", "definebodyfontREF", "definebodyfontenvironment", "definebuffer", "definecharacter", "definecolor", "definecolorgroup", "definecolumnbreak", "definecolumnset", "definecombination", "definecombinedlist", "definecommand", "defineconversion", "definedescription", "definedfont", "defineenumeration", "definefield", "definefieldstack", "definefiguresymbol", "definefloat", "definefont", "definefontfeature", "definefonthandling", "definefontstyle", "definefontsynonym", "defineframed", "defineframedtext", "definehbox", "definehead", "defineindentedtext", "defineinmargin", "defineinteractionmenu", "defineitemgroup", "definelabel", "definelayer", "definelayout", "definelist", "definelogo", "definemainfield", "definemakeup", "definemarking", "definemathalignment", "defineoutput", "defineoverlay", "definepagebreak", "definepalet", "definepapersize", "defineparagraphs", "defineplacement", "defineprofile", "defineprogram", "definerawfont", "definereference", "definereferenceformat", "definereferencelist", "defineregister", "definerule", "definesection", "definesectionblock", "definesorting", "definestartstop", "definestyle", "definesubfield", "definesymbol", "definesynonyms", "definetabletemplate", "definetabulate", "definetext", "definetextposition", "definetextvariable", "definetype", "definetypeface", "definetyping", "defineversion", "description", "determineheadnumber", "determinelistcharacteristics", "determineregistercharacteristics", "dimension", "disableinteractionmenu", "domicile", "donttest", "edgedistance", "edgewidth", "emptylines", "enumeration", "environment", "externalfigure", "fact", "field", "fieldstack", "fillinfield", "fillinline", "fillinrules", "fillintext", "fitfield", "fixedspace", "fixedspaces", "followprofile", "followprofileversion", "followversion", "footerdistance", "footerheight", "footnote", "footnotetext", "forceblocks", "formulanumber", "fraction", "framed", "framedtext", "from", "getbuffer", "getmarking", "getnumber", "godown", "goto", "gotobox", "gotopage", "graycolor", "greyvalue", "grid", "hairline", "head", "headerdistance", "headerheight", "headlevel", "headnumber", "headsym", "headtext", "hideblocks", "high", "hl", "immediatebetweenlist", "immediatetolist", "in", "incrementnumber", "indentation", "indenting", "inframed", "infull", "ininner", "inleft", "inleftedge", "inleftmargin", "inline", "inmaframed", "inmargin", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inothermargin", "inouter", "inright", "inrightedge", "inrightmargin", "installlanguage", "interactionbar", "interactionbuttons", "interactionmenu", "item", "items", "its", "keepblocks", "label", "labeling", "labels", "labeltext", "language", "leftaligned", "leftedgedistance", "leftedgewidth", "leftmargindistance", "leftmarginwidth", "leg", "linethickness", "listheight", "listlength", "listsymbol", "listwidth", "loadsorts", "loadsynonyms", "logfields", "lohi", "low", "maframed", "mainlanguage", "makeupheight", "makeupwidth", "mapfontsize", "mar", "margindistance", "marginrule", "margintext", "margintitle", "marginwidth", "marginword", "marking", "markversion", "mathematics", "mediaeval", "menubutton", "midaligned", "mirror", "month", "moveformula", "moveongrid", "movesidefloat", "name", "navigating", "nextsection", "nocap", "nodimension", "noheaderandfooterlines", "noindenting", "nolist", "nomarking", "nomoreblocks", "nomorefiles", "nop", "nospace", "note", "notopandbottomlines", "nowhitespace", "numberofsubpages", "numbers", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "packed", "page", "pagedepth", "pagenumber", "pageoffset", "pagereference", "paperheight", "paperwidth", "paragraph", "part", "periods", "placebookmarks", "placecombinedlist", "placefloat", "placefootnotes", "placeformula", "placeheadnumber", "placeheadtext", "placelegend", "placelist", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placelocalfootnotes", "placelogos", "placeongrid", "placeontopofeachother", "placepagenumber", "placerawlist", "placereferencelist", "placeregister", "placerule", "placesidebyside", "placesubformula", "placetextvariable", "position", "positiontext", "printpaperheight", "printpaperwidth", "processblocks", "processpage", "product", "program", "project", "publication", "quotation", "quote", "ran", "redo", "ref", "reference", "referral", "referraldate", "referring", "register", "remark", "reservefloat", "reset", "resetmarking", "resetnumber", "resettextcontent", "rightaligned", "rightedgedistance", "rightedgewidth", "rightmargindistance", "rightmarginwidth", "romannumerals", "rotate", "scale", "screen", "section", "seeregister", "selectblocks", "selectpaper", "selectversion", "setnumber", "settextcontent", "settextvariable", "setupalign", "setupanswerarea", "setuparranging", "setupbackground", "setupbackgrounds", "setupblackrules", "setupblank", "setupblock", "setupbodyfont", "setupbodyfontenvironment", "setupbottom", "setupbottomtexts", "setupbuffer", "setupbuttons", "setupcapitals", "setupcaption", "setupcaptions", "setupclipping", "setupcolor", "setupcolors", "setupcolumns", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupcombinations", "setupcombinedlist", "setupcomment", "setupdescriptions", "setupenumerations", "setupexternalfigures", "setupfield", "setupfields", "setupfillinlines", "setupfillinrules", "setupfloat", "setupfloats", "setupfloatsplitting", "setupfonthandling", "setupfontsynonym", "setupfooter", "setupfootertexts", "setupfootnotedefinition", "setupfootnotes", "setupforms", "setupformulae", "setupframed", "setupframedtexts", "setuphead", "setupheader", "setupheadertexts", "setupheadnumber", "setupheads", "setupheadtext", "setuphyphenmark", "setupindentedtext", "setupindenting", "setupinmargin", "setupinteraction", "setupinteractionbar", "setupinteractionmenu", "setupinteractionscreen", "setupinterlinespace", "setupinterlinespace2", "setupitemgroup", "setupitemizations", "setupitems", "setuplabeltext", "setuplanguage", "setuplayout", "setuplegend", "setuplinenumbering", "setuplines", "setuplinewidth", "setuplist", "setuplistalternative", "setupmakeup", "setupmarginblocks", "setupmarginrules", "setupmarking", "setupmathalignment", "setupnarrower", "setupnumber", "setupnumbering", "setupoppositeplacing", "setupoutput", "setuppagecomment", "setuppagenumber", "setuppagenumbering", "setuppagetransitions", "setuppalet", "setuppaper", "setuppapersize", "setupparagraphnumbering", "setupparagraphs", "setupplacement", "setuppositioning", "setupprofiles", "setupprograms", "setuppublications", "setupquote", "setupreferencelist", "setupreferencing", "setupregister", "setuprotate", "setuprule", "setups", "setupscreens", "setupsection", "setupsectionblock", "setupsorting", "setupspacing", "setupstartstop", "setupstrut", "setupsubpagenumber", "setupsymbolset", "setupsynchronization", "setupsynchronizationbar", "setupsynonyms", "setupsystem", "setuptab", "setuptables", "setuptabulate", "setuptext", "setuptextposition", "setuptextrules", "setuptexttexts", "setuptextvariable", "setupthinrules", "setuptolerance", "setuptop", "setuptoptexts", "setuptype", "setuptyping", "setupunderbar", "setupurl", "setupversions", "setupwhitespace", "showbodyfont", "showbodyfontenvironment", "showcolor", "showcolorgroup", "showexternalfigures", "showfields", "showframe", "showgrid", "showlayout", "showmakeup", "showpalet", "showprint", "showsetups", "showstruts", "showsymbolset", "someline", "somewhere", "sort", "space", "splitfloat", "startalignment", "startbackground", "startbuffer", "startcoding", "startcolor", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombination", "startcomment", "startcomponent", "startdescription", "startdocument", "startenumeration", "startenvironment", "startfact", "startfigure", "startfloattext", "startformula", "startframedtext", "startglobal", "starthiding", "startinteractionmenu", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmarginrule", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startpacked", "startparagraph", "startpositioning", "startpostponing", "startproduct", "startprofile", "startproject", "startquotation", "startraster", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttext", "starttextrule", "starttyping", "startunpacked", "startversion", "stopalignment", "stopbackground", "stopbuffer", "stopcoding", "stopcolor", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombination", "stopcomment", "stopcomponent", "stopdescription", "stopdocument", "stopenumeration", "stopenvironment", "stopfact", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopglobal", "stophiding", "stopinteractionmenu", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmarginrule", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stoppacked", "stopparagraph", "stoppositioning", "stoppostponing", "stopproduct", "stopprofile", "stopproject", "stopquotation", "stopraster", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptextrule", "stoptyping", "stopunpacked", "stopversion", "stretched", "sub", "subformulanumber", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "switchtobodyfont", "switchtorawfont", "sym", "symbol", "synchronizationbar", "synchronize", "synonym", "tab", "testcolumn", "testpage", "tex", "textheight", "textreference", "textrule", "textvariable", "textwidth", "thinrule", "thinrules", "title", "tooltip", "topdistance", "topheight", "topspace", "totalnumberofpages", "translate", "txt", "typ", "type", "typebuffer", "typefile", "underbar", "underbars", "unitmeaning", "unknown", "useJSscripts", "useURL", "useXMLfilter", "useblocks", "usecommands", "usedirectory", "useencoding", "useexternaldocument", "useexternalfigure", "useexternalfile", "useexternalfiles", "useexternalsoundtrack", "usemodule", "usemodules", "usereferences", "usespecials", "usesymbols", "usetypescript", "usetypescriptfile", "useurl", "version", "vl", "weekday", "whitespace", "wordright", "writebetweenlist", "writetolist", "writetoreferencelist", "writetoregister" },
+ ["fr"]={ "CAP", "Cap", "Caps", "Caractere", "Caracteres", "Chiffresromains", "JOURSEMAINE", "MOIS", "MOT", "MOTS", "Mot", "Mots", "Numeros", "a", "adaptedisposition", "affectenumero", "affectevariabletexte", "ajustechamp", "alaligne", "alapage", "aligneadroite", "aligneagauche", "aligneaumilieu", "appendix", "arg", "arriereplan", "atleftmargin", "atrightmargin", "baha", "barrecouleur", "barreinteraction", "barresynchronisation", "bas", "bouton", "boutonmenu", "boutonsinteraction", "but", "cacheblocs", "cap", "caractere", "caracteres", "champ", "changepolicebrute", "changepolicecorps", "chapter", "chem", "chiffresromains", "citation", "citer", "clip", "clonechamp", "colonne", "comment", "commentaire", "comparegroupecouleur", "comparepalette", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completenumeropage", "completeregistre", "composant", "composeenalinea", "concernant", "convertitnumero", "copitchamp", "corrigeespaceblanc", "couleur", "couleurgrise", "coupledocument", "coupledregister", "couplemarquage", "couplepapier", "coupleregistre", "crlf", "cutspace", "dactylographier", "dans", "dansautremarge", "dansborddroit", "dansbordgauche", "dansdroite", "dansgauche", "dansmarge", "dansmargedroite", "dansmargegauche", "date", "datecourante", "daterecommandation", "de", "decouplemarquage", "decrementenumero", "definebodyfontDEF", "definebodyfontREF", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineframed", "defineframedtext", "defineindentedtext", "defineitemgroup", "definemathalignment", "defineplacement", "definetypeface", "definicaractere", "definit", "definitaccent", "definitbloc", "definitblocsection", "definitbuffer", "definitcalque", "definitchamp", "definitchampprincipal", "definitcommande", "definitconversion", "definitcouleur", "definitdactylo", "definitdansmarge", "definitdemarrestoppe", "definitdescription", "definitdisposition", "definitenumeration", "definitenvironnementpolicecorps", "definitetiquette", "definitflottant", "definitformatreference", "definitgroupecouleur", "definithbox", "definitjeucolonne", "definitliste", "definitlisteimbriquee", "definitlistereference", "definitlogo", "definitmakeup", "definitmarquage", "definitmenuinteraction", "definitnotepdp", "definitpalette", "definitparagraphes", "definitpilechamp", "definitpolice", "definitpolicebrute", "definitpolicecorps", "definitpositiontexte", "definitprofil", "definitprogramme", "definitreference", "definitregistre", "definitregle", "definitrevetement", "definitsautdecolonne", "definitsautdepage", "definitsection", "definitsortie", "definitsouschamp", "definitstyle", "definitstylepolice", "definitsymbole", "definitsymbolefigure", "definitsynonymepolice", "definitsynonymes", "definittabulation", "definittaillepapier", "definittete", "definittexte", "definittrametableau", "definittri", "definittype", "definitvariabletexte", "definitversion", "definitvide", "demarrealignement", "demarrearriereplan", "demarreblocmarge", "demarrecitation", "demarreciter", "demarrecodage", "demarrecolonnes", "demarrecombinaison", "demarrecompoetroite", "demarrecomposant", "demarrecorrectionligne", "demarrecouleur", "demarredegroupe", "demarredocument", "demarreenvironement", "demarrefigure", "demarreglobal", "demarregroupe", "demarrejeucolonne", "demarrejeusymboles", "demarreligne", "demarreligneregleetexte", "demarrelignes", "demarrelocal", "demarremakeup", "demarremargereglee", "demarrenotespdplocales", "demarrenumerotationligne", "demarreopposition", "demarrepositionnement", "demarreproduit", "demarreprofil", "demarreprojet", "demarreraster", "demarrerevetement", "demarresynchronisation", "demarretableau", "demarretableaux", "demarretexte", "demarreversion", "demarrevuedensemble", "deplaceformule", "deplacesurgrille", "description", "determinecaracteristiqueliste", "determinecaracteristiquesregistre", "determinenumerotete", "dimension", "distancebord", "distanceborddroit", "distancebordgauche", "distanceentete", "distanceinf", "distancemarge", "distancemargedroite", "distancemargegauche", "distancepdp", "distancesup", "domicile", "echelle", "ecran", "ecritdansliste", "ecritdanslistereference", "ecritentreliste", "ecritregistre", "el", "element", "elements", "emptylines", "enumeration", "environement", "espace", "espaceblanc", "espacefixe", "espaceinf", "espacesfixes", "espacesup", "etiquette", "etiquettes", "etire", "fait", "faitreference", "fichierdactylo", "figureexterne", "forceblocs", "fraction", "framed", "framedtext", "gardeblocs", "getnumber", "grille", "groupe", "haut", "hauteureditionpapier", "hauteurentete", "hauteurinf", "hauteurliste", "hauteurmakeup", "hauteurpapier", "hauteurpdp", "hauteursup", "hauteurtexte", "headsym", "hl", "immediatebetweenlist", "immediatetolist", "inconnu", "incrementenumero", "indentation", "inframed", "infull", "inhibemenuinteraction", "ininner", "inmframed", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "installelangue", "joursemaine", "labeling", "labeltexte", "langue", "langueprincipale", "largeurbord", "largeurborddroit", "largeurbordgauche", "largeureditionpapier", "largeurligne", "largeurliste", "largeurmakeup", "largeurmarge", "largeurmargedroite", "largeurmargegauche", "largeurpapier", "largeurtexte", "leg", "ligneh", "lignenoire", "ligneregleetexte", "lignesnoires", "listesymbole", "llongueurliste", "loadsorts", "loadsynonyms", "logchamp", "mapfontsize", "mar", "margereglee", "marquage", "marquageversion", "marquepage", "mathematique", "mediaeval", "menuinteraction", "mframed", "mois", "montrecadre", "montrechamps", "montrecouleur", "montredisposition", "montreedition", "montreenvironnementpolicecorps", "montrefiguresexternes", "montregrille", "montregroupecouleur", "montrejeusymboles", "montremakeup", "montrepalette", "montrepolicecorps", "montrereglages", "montrestruts", "motdroit", "motmarge", "movesidefloat", "name", "navigating", "nextsection", "niveautete", "nocap", "nombredesouspages", "nombretotaldepages", "nommacro", "nop", "note", "notepdp", "numeroformule", "numeropage", "numeros", "numerosousformule", "numerotete", "numerotetecourant", "obtientmarquage", "oriente", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "page", "pagedepth", "pagedouble", "pageoffset", "paragraph", "part", "pasplusdeblocs", "pasplusdefichiers", "periodes", "pilechamp", "placecoteacote", "placeflottant", "placeformule", "placelegende", "placelesunsaudessusdesautres", "placeliste", "placelisteinmbriquee", "placelistereference", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placelogos", "placemarquespages", "placenotespdp", "placenotespdplocales", "placenumeropage", "placenumerotete", "placerawlist", "placeregistre", "placeregle", "placesousformule", "placesurgrille", "placetextetete", "placevariabletexte", "position", "positionnetexte", "prendbuffer", "produit", "programme", "projet", "publication", "qqpart", "ran", "raz", "razmarquage", "raznumero", "recommandation", "ref", "refait", "reference", "referencepage", "referencetexte", "reflete", "register", "reglages", "reglealignement", "reglearrangement", "reglearriereplan", "reglearriereplans", "reglebarreinteraction", "reglebarresynchronisation", "reglebloc", "regleblocmarge", "regleblocsection", "regleboutons", "reglebuffer", "reglecapitales", "reglechamp", "reglechamps", "regleclipping", "reglecolonnes", "reglecombinaisons", "reglecommentaire", "reglecommentairepage", "reglecompoetroite", "reglecomposeenalinea", "reglecouleur", "reglecouleurs", "regledactylo", "regledansmarge", "regledemarrestoppe", "regledescriptions", "regledisposition", "regleecraninteraction", "regleecrans", "regleelements", "regleencadre", "regleentete", "regleenumerations", "regleenvironnementpolicecorps", "regleepaisseurligne", "regleespaceblanc", "regleespacement", "regleespacementinterligne", "reglefiguresexternes", "regleflottant", "regleflottants", "regleformulaires", "regleformules", "reglegroupeselements", "regleinf", "regleinteraction", "regleintitule", "regleintitules", "reglejeucolonne", "reglejeusymboles", "reglelabeltexte", "reglelangue", "reglelegende", "reglelignes", "reglelignesnoires", "reglelignesreglestexte", "regleliste", "reglelisteimbriquee", "reglelistereference", "reglemakeup", "reglemargereglee", "reglemarquage", "reglemarquagehyphenation", "reglemenuinteraction", "reglenotepdp", "reglenumero", "reglenumeropage", "reglenumerotation", "reglenumerotationligne", "reglenumerotationpage", "reglenumerotationparagraphe", "reglenumerotete", "regleoriente", "reglepalette", "reglepapier", "regleparagraphes", "reglepdp", "regleplacementopposition", "reglepolicecorps", "reglepositionnement", "reglepositiontexte", "regleprofils", "regleprogrammes", "reglepublications", "reglereferencage", "regleregistre", "regleregle", "regleremplitligne", "regleremplitlignesreglees", "reglesection", "regleseparationflottant", "reglesortie", "reglesouslignage", "reglesousnumeropage", "reglestrut", "reglesup", "reglesynchronisation", "reglesynonymes", "reglesysteme", "regletab", "regletableaux", "regletabulation", "regletaillepapier", "regletete", "regletetes", "regletexte", "regletextesentete", "regletextesinf", "regletextespdp", "regletextessup", "regletextestexte", "regletextetete", "regletolerance", "regletraitsfins", "regletransitionspage", "regletri", "regletype", "regleurl", "reglevariabletexte", "regleversions", "remplitchamp", "remplitligne", "remplitlignesreglees", "remplittexte", "reservefloat", "resettextcontent", "retourarriere", "sansalinea", "sansdimension", "sansespace", "sansespaceblanc", "sanslignesenteteetpdp", "sanslignessupetinf", "sansliste", "sansmarquage", "sanstest", "sauteblocs", "section", "seeregister", "selectionneblocs", "selectionnepapier", "selectionneversion", "sensunite", "separeflottant", "settext", "setupanswerarea", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupframedtexts", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupplacement", "sort", "sousnumeropage", "startalignment", "startarriereplan", "startbuffer", "startcitation", "startcolumnmakeup", "startcolumns", "startcombination", "startcomment", "startcomposant", "startcouleur", "startdescription", "startdocument", "startenumeration", "startenvironement", "startfait", "startfigure", "startfloattext", "startformula", "startframedtext", "startgroupe", "starthiding", "startitemgroup", "startlegend", "startligneregleetexte", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmargereglee", "startmarginblock", "startmenuinteraction", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startproduit", "startprofile", "startprojet", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startversion", "stopalignment", "stoparriereplan", "stopbuffer", "stopcitation", "stopcolumnmakeup", "stopcolumns", "stopcombination", "stopcomment", "stopcompoetroite", "stopcomposant", "stopcouleur", "stopdescription", "stopdocument", "stopenumeration", "stopenvironement", "stopfait", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgroupe", "stophiding", "stopitemgroup", "stoplegend", "stopligneregleetexte", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmargereglee", "stopmarginblock", "stopmenuinteraction", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppealignement", "stoppearriereplan", "stoppeblocmarge", "stoppecitation", "stoppecodage", "stoppecolonnes", "stoppecombinaison", "stoppecomposant", "stoppecorrectionligne", "stoppecouleur", "stoppedegroupe", "stoppedocument", "stoppeenvironement", "stoppeglobal", "stoppegroupe", "stoppejeucolonne", "stoppeligne", "stoppeligneregleetexte", "stoppelignes", "stoppelocal", "stoppemakeup", "stoppemargereglee", "stoppenotespdplocales", "stoppenumerotationligne", "stoppeopposition", "stoppepositionnement", "stoppeproduit", "stoppeprofil", "stoppeprojet", "stopperaster", "stopperevetement", "stoppesynchronisation", "stoppetableau", "stoppetableaux", "stoppetexte", "stoppeversion", "stoppevuedensemble", "stoppositioning", "stoppostponing", "stopproduit", "stopprofile", "stopprojet", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopversion", "sub", "subject", "subsection", "subsubject", "subsubsection", "subsubsubject", "suggestion", "suivantprofil", "suivantversion", "suivantversionprofil", "sym", "symbole", "synchronise", "synonym", "tab", "tapebuffer", "testcolumn", "testpage", "tete", "tex", "textemarge", "textenotepdp", "textetete", "title", "titremarge", "traduire", "traiteblocs", "traitepage", "traitfin", "traitsfins", "txt", "typ", "underbar", "underbars", "uneligne", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "utiliseJSscripts", "utiliseURL", "utiliseblocs", "utilisechemin", "utilisecommandes", "utilisedocumentexterne", "utiliseencodage", "utilisefichierexterne", "utilisefichiersexternes", "utilisefigureexterne", "utilisemodule", "utilisemodules", "utilisepsiteaudioexterne", "utilisereferences", "utilisespecialites", "utilisesymboles", "utiliseurl", "va", "vaalaboite", "vaalapage", "vaenbas", "valeurcouleur", "valeurgris", "variabletexte", "version", "vide", "vl" },
+ ["it"]={ "CAP", "Cap", "Caps", "GIORNOSETTIMANA", "Lettera", "Lettere", "MESE", "Numeri", "Numeriromani", "PAROLA", "PAROLE", "Parola", "Parole", "accoppiacarta", "accoppiadocumento", "accoppiamarcatura", "accoppiapagina", "accoppiaregistro", "adattacampo", "adattalayout", "al", "allineacentro", "allineadestra", "allineasinistra", "altezzacarta", "altezzacartastampa", "altezzacima", "altezzaelenco", "altezzafondo", "altezzaintestazione", "altezzamakeup", "altezzapdp", "altezzatesto", "ambiente", "ampiezzabordo", "ampiezzabordodestro", "ampiezzabordosinistro", "ampiezzacarta", "ampiezzacartastampa", "ampiezzaelenco", "ampiezzamakeup", "ampiezzamargine", "ampiezzamarginedestro", "ampiezzamarginesinistro", "ampiezzatesto", "ap", "apagina", "appendix", "arg", "atleftmargin", "atrightmargin", "barracolori", "barrainterazione", "barrasincronizzazione", "bastablocchi", "bastafile", "cambiaafontdeltesto", "campi", "camporiempimento", "cap", "capello", "chapter", "chim", "circondato", "citazione", "clip", "clonacampo", "colonna", "colore", "coloregrigio", "comment", "commento", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completeregister", "componenet", "confrontagruppocolori", "confrontatavolozza", "convertinumero", "copiacampo", "correggispaziobianco", "coupledregister", "crlf", "cutspace", "da", "daqualcheparte", "data", "datadioggi", "datareferral", "decrementnumber", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definemathalignment", "definepagebreak", "defineplacement", "definetypeface", "definisci", "definisciaccento", "definisciambientefontdeltesto", "definisciblocco", "definiscibloccosezione", "definiscibuffer", "definiscicampo", "definiscicampoprincipale", "definiscicapoversi", "definiscicarattere", "definiscicolore", "definiscicomando", "definisciconversione", "definiscidescrizione", "definiscidimensionicarta", "definiscielenco", "definiscielencocombinato", "definiscienumerazione", "definiscietichetta", "definiscifigurasimbolo", "definiscifont", "definiscifontdeltesto", "definiscifontgrezzo", "definisciformatoriferimento", "definiscigruppocolonne", "definiscigruppocolori", "definiscihbox", "definisciincorniciato", "definisciiniziatermina", "definiscilayout", "definiscilinea", "definiscilistariferimenti", "definiscilogo", "definiscimakeup", "definiscimarcatura", "definiscimenuinterazione", "definiscimodellotabella", "definiscioggettomobile", "definisciordinamento", "definiscioutput", "definisciposizionetesto", "definisciprofilo", "definisciprogramma", "definisciregistro", "definisciriferimento", "definiscirigovuoto", "definiscisezione", "definiscisimbolo", "definiscisinonimi", "definiscisinonimofont", "definiscisottocampo", "definiscisovrapposizione", "definiscistackcampi", "definiscistile", "definiscistilefont", "definiscitabulato", "definiscitavolozza", "definiscitesta", "definiscitesto", "definiscitestoincorniciato", "definiscitype", "definiscityping", "definiscivariabiletesto", "definisciversion", "description", "determinacaratteristicheregistro", "determinacarattersticheelenco", "determinanumerotesta", "dimensione", "disabilitamenuinterazione", "distanzabordo", "distanzabordodestro", "distanzabordosinistro", "distanzacima", "distanzafondo", "distanzaintestazione", "distanzamargine", "distanzamarginedestro", "distanzamarginesinistro", "distanzapdp", "domicilio", "el", "elaborablocchi", "elaborapagina", "elementi", "elemento", "emptylines", "enumeration", "etichetta", "etichette", "fatto", "figuraesterna", "fondo", "forzablocchi", "framedtext", "frazione", "getnumber", "giornosettimana", "griglia", "headsym", "hl", "ignoto", "immediatebetweenlist", "immediatetolist", "impaccato", "impostaallineamento", "impostaambientefontdeltesto", "impostaampiezzariga", "impostabarrainterazione", "impostabarrasincronizzazione", "impostablocchimargine", "impostablocco", "impostabloccosezione", "impostabuffer", "impostacampi", "impostacampo", "impostacapoversi", "impostacaption", "impostacaptions", "impostacima", "impostaclippling", "impostacolonne", "impostacolore", "impostacolori", "impostacombinazioni", "impostacommento", "impostacommentopagina", "impostadefinizionenotepdp", "impostadescrizioni", "impostadimensionicarta", "impostaelementi", "impostaelencazioni", "impostaelenco", "impostaelencocombinato", "impostaenumerazioni", "impostafigureesterne", "impostafondo", "impostafontdeltesto", "impostaforms", "impostaformule", "impostagruppocolonne", "impostaincorniciato", "impostainiziatermina", "impostainmargine", "impostainstestazione", "impostainterazione", "impostainterlinea", "impostalayout", "impostalegenda", "impostalinea", "impostalineemargine", "impostalineenere", "impostalineeriempimento", "impostalineesottili", "impostalineetesto", "impostalingua", "impostalistariferimenti", "impostamaiuscole", "impostamakeup", "impostamarcatura", "impostamenuinterazione", "impostamenzione", "impostanotepdp", "impostanumerazione", "impostanumerazionecapoversi", "impostanumerazionepagina", "impostanumerazionerighe", "impostanumeropagina", "impostanumerosottopagina", "impostanumerotesta", "impostaoggettimobili", "impostaoggettomobile", "impostaordinamento", "impostaoutput", "impostaparranging", "impostapdp", "impostapiustretto", "impostaposizionamento", "impostaposizionamentoopposti", "impostaposizionetesto", "impostaprofili", "impostaprogrammi", "impostapubblicazioni", "impostapulsanti", "impostaregistro", "impostarientro", "impostariferimento", "impostarighe", "impostarigheriempimento", "impostarigovuoto", "impostarotazione", "impostaschermi", "impostaschermointerazione", "impostasegnosillabazione", "impostasetsimboli", "impostasezione", "impostasfondi", "impostasfondo", "impostasincronizzazione", "impostasinonimi", "impostasistema", "impostasottolinea", "impostaspaziatura", "impostaspaziobianco", "impostaspezzamentooggettomobile", "impostastrut", "impostatab", "impostatabelle", "impostatabulato", "impostatavolozza", "impostatesta", "impostateste", "impostatesticima", "impostatestifondo", "impostatestiincorniciati", "impostatestiintestazioni", "impostatestipdp", "impostatesto", "impostatestoetichette", "impostatestointestazioni", "impostatestotesti", "impostatolleranza", "impostatransizionepagina", "impostatype", "impostatyping", "impostaurl", "impostavariabiletesto", "impostaversioni", "impostazioni", "in", "inaltromargine", "incorniciato", "incrementanumero", "indentation", "indestra", "ininner", "iniziaallineamento", "iniziaambiente", "iniziabloccomargine", "iniziacitazione", "iniziacodifica", "iniziacolonne", "iniziacolore", "iniziacombinazione", "iniziacomponente", "iniziacorrezioneriga", "iniziadocumento", "iniziafigura", "iniziaglobale", "iniziagruppocolonne", "iniziaimpaccato", "inizialineamargine", "inizialineatesto", "inizialocale", "iniziamakeup", "inizianotepdplocali", "inizianumerazionerighe", "iniziaopposto", "iniziaoverview", "iniziapiustretto", "iniziaposizionamento", "iniziaprodotto", "iniziaprofilo", "iniziaprogetto", "iniziaraster", "iniziariga", "iniziarighe", "iniziasetsimboli", "iniziasfondo", "iniziasincronizzazione", "iniziasovrapposizione", "iniziatabella", "iniziatabelle", "iniziatesto", "iniziaunpacked", "iniziaversione", "inlatodestro", "inlatosinistro", "inmaframed", "inmargine", "inmarginedestro", "inmarginesinistro", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inriga", "insinistra", "installalingua", "intorno", "labeling", "leg", "lettera", "lettere", "lineamargine", "lineanera", "lineasottile", "lineatesto", "lineenere", "lineeriempimento", "lineesottili", "lingua", "linguaprincipale", "listsymbol", "livellotesta", "loadsorts", "loadsynonyms", "logcampi", "lunghezzaelenco", "maframed", "mapfontsize", "mar", "marcatura", "marcaversione", "matematica", "mediaeval", "menuinterattivo", "menzione", "mese", "mettielenco", "mettielencocombinato", "mettifiancoafianco", "mettiformula", "mettiingriglia", "mettilegenda", "mettilinea", "mettiloghi", "mettinotepdp", "mettinotepdplocali", "mettinumeropagina", "mettiregistro", "mettisegnalibro", "mettisottoformula", "mettiunosullaltro", "mettivariabiletesto", "mostraambientefontdeltesto", "mostracampi", "mostracolore", "mostracornice", "mostrafiguresterne", "mostrafontdeltesto", "mostragriglia", "mostragruppocolori", "mostraimpostazioni", "mostralyout", "mostramakeup", "mostrasetsimboli", "mostrastampa", "mostrastruts", "mostratavolozza", "movesidefloat", "name", "nascondiblocchi", "navigating", "nextsection", "nientedimensioni", "nienteelenco", "nientelineecimafondo", "nientelineintestazionepdp", "nientemarcatura", "nienterientro", "nientespazio", "nientespaziobianco", "nocap", "nome", "nomeunita", "nop", "nota", "notapdp", "notest", "numberofsubpages", "numeri", "numeriromani", "numeroformula", "numeropagina", "numeropaginacompleto", "numerosottoformula", "numerotesta", "numerotestacorrente", "numerototaledipagine", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "pagina", "paragraph", "paroladestra", "parolainmargine", "part", "passaafontgrezzo", "ped", "pedap", "perlungo", "placefloat", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placerawlist", "placereferencelist", "posizionanumerotesta", "posizionatesto", "posizionatestotesta", "posizione", "prendibuffer", "prendimarcatura", "prodotto", "progetto", "programma", "pubblicazione", "pulsante", "pulsantemenu", "pulsantinterazione", "punti", "qualcheriga", "ran", "referral", "referring", "register", "reimposta", "reimpostamarcatura", "reservefloat", "resetnumber", "resettextcontent", "rientro", "rif", "rifai", "riferimento", "riferimentopagina", "riferimentotesto", "riflessione", "rigariempimento", "rigovuoto", "ruota", "saltablocchi", "scala", "schermo", "scrividentroelenco", "scriviinelenco", "scriviinlistariferimenti", "scriviinregistro", "section", "seeregister", "segnalibro", "seguiprofilo", "seguiversione", "seguiversioneprofilo", "selezionablocchi", "selezionacarta", "selezionaversione", "separamarcatura", "setnumber", "settext", "setupanswerarea", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setuppaper", "setupplacement", "setvariabiletesto", "sfondo", "sim", "simbolo", "sincronizza", "sort", "spazifissi", "spazio", "spaziobianco", "spaziocima", "spaziodietro", "spaziofisso", "spaziofondo", "spessoreriga", "spezzaoggettomobile", "spostaagriglia", "spostaformula", "stackcampi", "startalignment", "startambiente", "startbuffer", "startcitazione", "startcolore", "startcolumnmakeup", "startcolumns", "startcombination", "startcomment", "startcomponenet", "startdescription", "startdocument", "startenumeration", "startfatto", "startfigure", "startfloattext", "startformula", "startframedtext", "starthiding", "startimpaccato", "startitemgroup", "startlegend", "startline", "startlineamargine", "startlineatesto", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmenuinterattivo", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startprodotto", "startprofile", "startprogetto", "startregister", "startsfondo", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startversione", "stirato", "stopalignment", "stopambiente", "stopbuffer", "stopcitazione", "stopcolore", "stopcolumnmakeup", "stopcolumns", "stopcombination", "stopcomment", "stopcomponenet", "stopdescription", "stopdocument", "stopenumeration", "stopfatto", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stophiding", "stopimpaccato", "stopitemgroup", "stoplegend", "stopline", "stoplineamargine", "stoplineatesto", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmenuinterattivo", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stopprodotto", "stopprofile", "stopprogetto", "stopsfondo", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopversione", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "tab", "terminaallineamento", "terminaambiente", "terminabloccomargine", "terminacitazione", "terminacodifica", "terminacolonne", "terminacolore", "terminacombinazione", "terminacomponente", "terminacorrezioneriga", "terminadocumento", "terminaglobale", "terminagruppocolonne", "terminaimpaccato", "terminalineamargine", "terminalineatesto", "terminalocale", "terminamakeup", "terminanotepdplocali", "terminanumerazionerighe", "terminaopposto", "terminaoverview", "terminapiustretto", "terminaposizionamento", "terminaprodotto", "terminaprofili", "terminaprogetto", "terminaraster", "terminariga", "terminarighe", "terminasfondo", "terminasincronizzazione", "terminasovrapposizione", "terminatabella", "terminatabelle", "terminatesto", "terminaunpacked", "terminaversioni", "testa", "testcolumn", "testoetichetta", "testoinmargine", "testoinstestazioni", "testonotapdp", "testoriempimento", "testpage", "tex", "tieniblocchi", "title", "titoloinmargine", "tooltip", "traduci", "txt", "typ", "type", "typebuffer", "typefile", "underbar", "underbars", "usaJSscripts", "usaURL", "usablocco", "usacartella", "usacodifica", "usacolonnasonoraesterna", "usacomandi", "usadocumentoesterno", "usafiguraesterna", "usafileesterni", "usafileesterno", "usamoduli", "usamodulo", "usariferimenti", "usasimboli", "usaspecialita", "usaurl", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "vaia", "vaiabox", "vaiapagina", "vaigiu", "valorecolore", "valoregrigio", "variabiletesto", "versione", "vl" },
+ ["nl"]={ "CAP", "Cap", "Caps", "Cijfers", "KAP", "Kap", "Kaps", "Letter", "Letters", "MAAND", "Romeins", "WEEKDAG", "WOORD", "WOORDEN", "Woord", "Woorden", "aantalsubpaginas", "about", "achtergrond", "appendix", "arg", "bepaalkopnummer", "bepaallijstkenmerken", "bepaalregisterkenmerken", "betekenis", "binnenmargeafstand", "binnenmargebreedte", "binnenrandafstand", "binnenrandbreedte", "blanko", "blokje", "blokjes", "blokkeerinteractiemenu", "bodemwit", "bookmark", "bovenafstand", "bovenhoogte", "breuk", "buitenmargeafstand", "buitenmargebreedte", "buitenrandafstand", "buitenrandbreedte", "but", "button", "cap", "chapter", "chem", "cijfers", "citaat", "citeer", "clip", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "converteernummer", "copieerveld", "corrigeerwitruimte", "coupledregister", "crlf", "datum", "definebodyfontDEF", "definebodyfontREF", "definedfont", "definefontfeature", "definefonthandling", "definerawfont", "definetypeface", "definieer", "definieeraccent", "definieeralineas", "definieerbeeldmerk", "definieerblanko", "definieerblok", "definieerbuffer", "definieercombinatie", "definieercommando", "definieerconversie", "definieerfiguursymbool", "definieerfont", "definieerfontstijl", "definieerfontsynoniem", "definieerhbox", "definieerhoofdveld", "definieeringesprongentext", "definieerinmarge", "definieerinteractiemenu", "definieeritemgroep", "definieerkadertekst", "definieerkarakter", "definieerkleur", "definieerkleurgroep", "definieerkolomgroep", "definieerkolomovergang", "definieerkop", "definieerkorps", "definieerkorpsomgeving", "definieerlayer", "definieerlayout", "definieerletter", "definieerlijn", "definieerlijst", "definieermarkering", "definieeromlijnd", "definieeropmaak", "definieeroverlay", "definieerpaginaovergang", "definieerpalet", "definieerpapierformaat", "definieerplaats", "definieerplaatsblok", "definieerprofiel", "definieerprogramma", "definieerreferentie", "definieerreferentieformaat", "definieerreferentielijst", "definieerregister", "definieersamengesteldelijst", "definieersectie", "definieersectieblok", "definieersorteren", "definieerstartstop", "definieersubveld", "definieersymbool", "definieersynoniemen", "definieertabelvorm", "definieertabulatie", "definieertekst", "definieertekstpositie", "definieertekstvariabele", "definieertype", "definieertypen", "definieeruitvoer", "definieerveld", "definieerveldstapel", "definieerversie", "definieerwiskundeuitlijnen", "description", "dimensie", "directnaarlijst", "directtussenlijst", "doordefinieren", "doorlabelen", "doornummeren", "dunnelijn", "dunnelijnen", "eenregel", "enumeration", "ergens", "externfiguur", "forceerblokken", "formulenummer", "framedtext", "gebruikJSscripts", "gebruikURL", "gebruikXMLfilter", "gebruikblokken", "gebruikcommandos", "gebruikexterndocument", "gebruikexternefile", "gebruikexternefiles", "gebruikexternfiguur", "gebruikexterngeluidsfragment", "gebruikgebied", "gebruikmodule", "gebruikmodules", "gebruikreferenties", "gebruikspecials", "gebruiksymbolen", "gebruiktypescript", "gebruiktypescriptfile", "gebruikurl", "geenblokkenmeer", "geenbovenenonderregels", "geendimensie", "geenfilesmeer", "geenhoofdenvoetregels", "geenlijst", "geenmarkering", "geenspatie", "geentest", "geenwitruimte", "geg", "grijskleur", "grijswaarde", "haalbuffer", "haalmarkering", "haalnummer", "haarlijn", "handhaafblokken", "herhaal", "hl", "hoofdafstand", "hoofdhoogte", "hoofdtaal", "hoog", "huidigedatum", "huidigekopnummer", "in", "inanderemarge", "inbinnen", "inbuiten", "indentation", "inlijnd", "inlinker", "inlinkermarge", "inlinkerrand", "inmarge", "inrechter", "inrechtermarge", "inrechterrand", "inregel", "inspringen", "installeertaal", "instellingen", "interactiebalk", "interactiebuttons", "interactiemenu", "invullijnen", "invulregel", "invultekst", "invulveld", "inwilijnd", "items", "its", "kantlijn", "kap", "kenmerk", "kenmerkdatum", "kentekstvariabeletoe", "kleur", "kleurenbalk", "kleurwaarde", "kloonveld", "kolom", "kop", "kopniveau", "kopnummer", "koppeldocument", "koppelmarkering", "koppelpagina", "koppelpapier", "koppelregister", "kopsym", "koptekst", "kopwit", "laag", "label", "labeling", "labels", "labeltekst", "laho", "leg", "legeregels", "letter", "letters", "lijndikte", "lijstbreedte", "lijsthoogte", "lijstlengte", "lijstsymbool", "linkermargeafstand", "linkermargebreedte", "linkerrandafstand", "linkerrandbreedte", "loadsorts", "loadsynonyms", "maand", "mapfontsize", "mar", "margeafstand", "margebreedte", "margetekst", "margetitel", "margewoord", "markeer", "markeerversie", "mediaeval", "menubutton", "naam", "naar", "naarbox", "naarpagina", "name", "navigerend", "nextsection", "nietinspringen", "nocap", "nokap", "noot", "nop", "omgeving", "omlaag", "omlijnd", "onbekend", "onderafstand", "onderdeel", "onderhoogte", "ontkoppelmarkering", "op", "opelkaar", "oplinkermarge", "oppagina", "oprechtermarge", "overbar", "overbars", "overstrike", "overstrikes", "pagina", "paginadiepte", "paginanummer", "paginaoffset", "paginareferentie", "papierbreedte", "papierhoogte", "paragraph", "part", "paslayoutaan", "passeerblokken", "passendveld", "plaatsbeeldmerken", "plaatsbookmarks", "plaatsformule", "plaatskopnummer", "plaatskoptekst", "plaatslegenda", "plaatslijn", "plaatslijst", "plaatslokalevoetnoten", "plaatsnaastelkaar", "plaatsonderelkaar", "plaatsopgrid", "plaatspaginanummer", "plaatsplaatsblok", "plaatsreferentielijst", "plaatsregister", "plaatsruwelijst", "plaatssamengesteldelijst", "plaatssubformule", "plaatstekstvariabele", "plaatsvoetnoten", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "positioneer", "positioneertekst", "printpapierbreedte", "printpapierhoogte", "produkt", "programma", "projekt", "publicatie", "punten", "ran", "randafstand", "randbreedte", "rechtermargeafstand", "rechtermargebreedte", "rechterrandafstand", "rechterrandbreedte", "ref", "refereer", "referentie", "regellinks", "regelmidden", "regelrechts", "register", "registreervelden", "reservefloat", "reset", "resetmarkering", "resetnummer", "resettekstinhoud", "resettextcontent", "romeins", "rooster", "roteer", "rugwit", "schaal", "scherm", "schrijfnaarlijst", "schrijfnaarreferentielijst", "schrijfnaarregister", "schrijftussenlijst", "section", "seeregister", "selecteerblokken", "selecteerpapier", "selecteerversie", "setnummer", "setupfonthandling", "setupfontsynonym", "setupinterlinespace2", "setuplistalternative", "snijwit", "som", "sort", "spatie", "spiegel", "splitsplaatsblok", "startachtergrond", "startalignment", "startbuffer", "startcitaat", "startcodering", "startcolumns", "startcombinatie", "startcombination", "startcomment", "startdescription", "startdocument", "startenumeration", "startfigure", "startfiguur", "startfloattext", "startformula", "startframedtext", "startgeg", "startglobaal", "starthiding", "startinteractiemenu", "startitemgroup", "startkantlijn", "startkleur", "startkolomgroep", "startkolommen", "startkolomopmaak", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startlokaal", "startlokalevoetnoten", "startmakeup", "startmargeblok", "startmarginblock", "startnaast", "startnamemakeup", "startnarrower", "startomgeving", "startonderdeel", "startopelkaar", "startopmaak", "startopposite", "startoverlay", "startoverview", "startoverzicht", "startparagraph", "startpositioneren", "startpositioning", "startpostponing", "startprodukt", "startprofiel", "startprofile", "startprojekt", "startraster", "startregel", "startregelcorrectie", "startregelnummeren", "startregels", "startregister", "startsmaller", "startsymbolset", "startsymboolset", "startsynchronisatie", "startsynchronization", "starttabel", "starttabellen", "starttable", "starttables", "starttabulate", "starttekst", "starttekstlijn", "starttyping", "startuitlijnen", "startunpacked", "startvanelkaar", "startversie", "stelachtergrondenin", "stelachtergrondin", "stelalineasin", "stelantwoordgebiedin", "stelarrangerenin", "stelblankoin", "stelblokin", "stelblokjesin", "stelblokkopjein", "stelblokkopjesin", "stelbovenin", "stelboventekstenin", "stelbufferin", "stelbuttonsin", "stelciterenin", "stelclipin", "stelcombinatiesin", "stelcommentaarin", "steldoordefinierenin", "steldoornummerenin", "steldunnelijnenin", "stelexternefigurenin", "stelformulesin", "stelformulierenin", "stelhoofdin", "stelhoofdtekstenin", "stelingesprongentextin", "stelinmargein", "stelinspringenin", "stelinteractiebalkin", "stelinteractiein", "stelinteractiemenuin", "stelinteractieschermin", "stelinterliniein", "stelinvullijnenin", "stelinvulregelsin", "stelitemgroepin", "stelitemsin", "stelkadertekstenin", "stelkantlijnin", "stelkapitalenin", "stelkleurenin", "stelkleurin", "stelkolomgroepin", "stelkolomgroepregelsin", "stelkolomgroepstartin", "stelkolommenin", "stelkopin", "stelkopnummerin", "stelkoppeltekenin", "stelkoppenin", "stelkoptekstin", "stelkorpsin", "stelkorpsomgevingin", "stellabeltekstin", "stellayoutin", "stellegendain", "stellijndiktein", "stellijnin", "stellijstin", "stelmargeblokkenin", "stelmarkeringin", "stelnaastplaatsenin", "stelnummerenin", "stelnummerin", "stelomlijndin", "stelonderin", "stelonderstrepenin", "stelondertekstenin", "stelopmaakin", "stelopsommingenin", "stelpaginacommentaarin", "stelpaginanummerin", "stelpaginanummeringin", "stelpaginaovergangenin", "stelpaletin", "stelpapierformaatin", "stelpapierin", "stelparagraafnummerenin", "stelplaatsblokin", "stelplaatsblokkenin", "stelplaatsbloksplitsenin", "stelplaatsin", "stelpositionerenin", "stelprofielenin", "stelprogrammasin", "stelpublicatiesin", "stelrastersin", "stelreferentielijstin", "stelrefererenin", "stelregelnummerenin", "stelregelsin", "stelregisterin", "stelroterenin", "stelsamengesteldelijstin", "stelsectieblokin", "stelsectiein", "stelsmallerin", "stelsorterenin", "stelspatieringin", "stelstartstopin", "stelstrutin", "stelsubpaginanummerin", "stelsymboolsetin", "stelsynchronisatiebalkin", "stelsynchronisatiein", "stelsynoniemenin", "stelsysteemin", "steltaalin", "steltabellenin", "steltabin", "steltabulatiein", "steltekstin", "steltekstinhoudin", "steltekstlijnenin", "steltekstpositiein", "stelteksttekstenin", "steltekstvariabelein", "steltolerantiein", "steltypein", "steltypenin", "steluitlijnenin", "steluitvoerin", "stelurlin", "stelveldenin", "stelveldin", "stelversiesin", "stelvoetin", "stelvoetnootdefinitiein", "stelvoetnotenin", "stelvoettekstenin", "stelwiskundeuitlijnenin", "stelwitruimtein", "stopachtergrond", "stopalignment", "stopbuffer", "stopcitaat", "stopcodering", "stopcolumns", "stopcombinatie", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopenumeration", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopgeg", "stopglobaal", "stophiding", "stopinteractiemenu", "stopitemgroup", "stopkantlijn", "stopkleur", "stopkolomgroep", "stopkolommen", "stopkolomopmaak", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stoplokaal", "stoplokalevoetnoten", "stopmakeup", "stopmargeblok", "stopmarginblock", "stopnaast", "stopnamemakeup", "stopnarrower", "stopomgeving", "stoponderdeel", "stopopelkaar", "stopopmaak", "stopopposite", "stopoverlay", "stopoverview", "stopoverzicht", "stopparagraph", "stoppositioneren", "stoppositioning", "stoppostponing", "stopprodukt", "stopprofiel", "stopprofile", "stopprojekt", "stopraster", "stopregel", "stopregelcorrectie", "stopregelnummeren", "stopregels", "stopsmaller", "stopsymbolset", "stopsynchronisatie", "stopsynchronization", "stoptabel", "stoptabellen", "stoptable", "stoptables", "stoptabulate", "stoptekst", "stoptekstlijn", "stoptyping", "stopuitlijnen", "stopunpacked", "stopvanelkaar", "stopversie", "sub", "subformulenummer", "subject", "subpaginanummer", "subsection", "subsubject", "subsubsection", "subsubsubject", "suggestie", "switchnaarkorps", "switchtorawfont", "sym", "symbool", "synchronisatiebalk", "synchroniseer", "synonym", "taal", "tab", "tekstbreedte", "teksthoogte", "tekstlijn", "tekstreferentie", "tekstvariabele", "testkolom", "testpagina", "tex", "title", "toelichting", "toonexternefiguren", "toongrid", "tooninstellingen", "toonkader", "toonkleur", "toonkleurgroep", "toonkorps", "toonkorpsomgeving", "toonlayout", "toonopmaak", "toonpalet", "toonprint", "toonstruts", "toonsymboolset", "toonvelden", "totaalaantalpaginas", "txt", "typ", "type", "typebuffer", "typefile", "uit", "uitgerekt", "underbar", "underbars", "usecodering", "usedirectory", "vastespatie", "vastespaties", "veld", "veldstapel", "verbergblokken", "vergelijkkleurgroep", "vergelijkpalet", "verhoognummer", "verlaagnummer", "verplaatsformule", "verplaatsopgrid", "verplaatszijblok", "versie", "vertaal", "verwerkblokken", "verwerkpagina", "vl", "voetafstand", "voethoogte", "voetnoot", "voetnoottekst", "volgprofiel", "volgprofielversie", "volgversie", "volledigepaginanummer", "volledigregister", "voluit", "weekdag", "wilijnd", "wiskunde", "witruimte", "woonplaats", "woordrechts", "zetbreedte", "zethoogte" },
+ ["pe"]={ "CAP", "Cap", "Caps", "Character", "Characters", "MONTH", "Numbers", "Romannumerals", "WEEKDAY", "WORD", "WORDS", "Word", "Words", "appendix", "cap", "chapter", "chem", "comment", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "coupledregister", "crlf", "definebodyfontDEF", "definebodyfontREF", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "definetypeface", "description", "enumeration", "framedtext", "indentation", "inmframed", "its", "labeling", "loadsorts", "loadsynonyms", "mapfontsize", "mediaeval", "mframed", "name", "nextsection", "nocap", "overbar", "overbars", "overstrike", "overstrikes", "paragraph", "part", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "ran", "register", "reservefloat", "resettextcontent", "section", "seeregister", "setupanswerarea", "setupcapitals", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setuplistalternative", "setupurl", "sort", "startalignment", "startbuffer", "startcolumns", "startcombination", "startcomment", "startdescription", "startdocument", "startenumeration", "startfigure", "startfloattext", "startformula", "startframedtext", "starthiding", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startnamemakeup", "startnarrower", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startprofile", "startraster", "startregister", "startsymbolset", "startsynchronization", "starttable", "starttables", "starttabulate", "starttyping", "startunpacked", "startتولید", "startحقیقت", "startخط‌حاشیه", "startخط‌متن", "startرنگ", "startÙشرده", "startمحیط", "startمنوی‌پانل", "startمولÙÙ‡", "startنسخه", "startنقل‌قول", "startپروژه", "startپس‌زمینه", "stopalignment", "stopbuffer", "stopcolumns", "stopcombination", "stopcomment", "stopdescription", "stopdocument", "stopenumeration", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stophiding", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopnamemakeup", "stopnarrower", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stopprofile", "stopraster", "stopsymbolset", "stopsynchronization", "stoptable", "stoptables", "stoptabulate", "stoptyping", "stopunpacked", "stopتولید", "stopحقیقت", "stopخط‌حاشیه", "stopخط‌متن", "stopرنگ", "stopÙشرده", "stopمحیط", "stopمنوی‌پانل", "stopمولÙÙ‡", "stopنسخه", "stopنقل‌قول", "stopپروژه", "stopپس‌زمینه", "sub", "subject", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "title", "tooltip", "txt", "typ", "underbar", "underbars", "useJSscripts", "useURL", "useXMLfilter", "usedirectory", "useurl", "Ø¢Ùست‌صÙحه", "آیتم", "آیتمها", "آینه", "اجباربلوکها", "ارتÙاع‌آرایش", "ارتÙاع‌بالا", "ارتÙاع‌برگ", "ارتÙاع‌ته‌برگ", "ارتÙاع‌خط", "ارتÙاع‌سربرگ", "ارتÙاع‌متن", "ارتÙاع‌پایین", "از", "ازکارانداختن‌منوی‌پانل", "استÙاده‌بلوکها", "استÙاده‌دستخط‌تایپ", "استÙاده‌رمزینه", "استÙاده‌شکل‌خارجی", "استÙاده‌Ùرمانها", "استÙاده‌قطعه‌موزیک‌خارجی", "استÙاده‌مدول", "استÙاده‌مدولها", "استÙاده‌مرجعها", "استÙاده‌مسیر", "استÙاده‌نمادها", "استÙاده‌نوشتارخارجی", "استÙاده‌ویژگیها", "استÙاده‌پرونده‌خارجی", "استÙاده‌پرونده‌دستخط‌تایپ", "استÙاده‌پرونده‌های‌خارجی", "اعدادلاتین", "اÙزودن", "اما", "امتحان‌نکن", "انتخاب‌برگ", "انتخاب‌بلوکها", "انتخاب‌نسخه", "انتقال‌به‌توری", "انتقال‌Ùرمول", "انتقال‌کنار‌شناور", "انجام‌دوباره", "بارگذاریها", "بارگذاری‌آرایش", "بارگذاری‌آیتمها", "بارگذاری‌ارجاع", "بارگذاری‌اندازه‌برگ", "بارگذاری‌باریکتر", "بارگذاری‌باÙر", "بارگذاری‌بالا", "بارگذاری‌بخش", "بارگذاری‌بردباری", "بارگذاری‌برنامه‌ها", "بارگذاری‌برگ", "بارگذاری‌بست", "بارگذاری‌بلوک", "بارگذاری‌بلوکهای‌حاشیه", "بارگذاری‌بلوک‌بخش", "بارگذاری‌تایپ", "بارگذاری‌تایپ‌کردن", "بارگذاری‌تب", "بارگذاری‌ترتیب", "بارگذاری‌ترکیب‌ها", "بارگذاری‌تطابق", "بارگذاری‌تعریÙ‌پانوشت", "بارگذاری‌تنظیم", "بارگذاری‌تنظیم‌ریاضی", "بارگذاری‌ته‌برگ", "بارگذاری‌تورÙتگی", "بارگذاری‌توضیح", "بارگذاری‌توضیح‌صÙحه", "بارگذاری‌ثبت", "بارگذاری‌جانشانی", "بارگذاری‌جدولها", "بارگذاری‌جدول‌بندی", "بارگذاری‌خالی", "بارگذاری‌خروجی", "بارگذاری‌خط", "بارگذاری‌خطها", "بارگذاری‌خطهای‌حاشیه", "بارگذاری‌خطهای‌سیاه", "بارگذاری‌خطهای‌متن", "بارگذاری‌خطهای‌مجموعه‌ستون", "بارگذاری‌خطها‌ی‌نازک", "بارگذاری‌درج‌درخطها", "بارگذاری‌درج‌مخالÙ", "بارگذاری‌درون‌حاشیه", "بارگذاری‌دوران", "بارگذاری‌دکمه‌ها", "بارگذاری‌راهنما", "بارگذاری‌رنگ", "بارگذاری‌رنگها", "بارگذاری‌زبان", "بارگذاری‌ستونها", "بارگذاری‌سر", "بارگذاری‌سربرگ", "بارگذاری‌سرها", "بارگذاری‌سیستم", "بارگذاری‌شرح", "بارگذاری‌شرحها", "بارگذاری‌شروع‌مجموعه‌ستون", "بارگذاری‌شروع‌پایان", "بارگذاری‌شماره", "بارگذاری‌شماره‌زیرصÙحه", "بارگذاری‌شماره‌سر", "بارگذاری‌شماره‌صÙحه", "بارگذاری‌شماره‌گذاری", "بارگذاری‌شماره‌گذاریها", "بارگذاری‌شماره‌گذاری‌صÙحه", "بارگذاری‌شماره‌گذاری‌پاراگراÙ", "بارگذاری‌شماره‌‌گذاری‌خط", "بارگذاری‌شناور", "بارگذاری‌شناورها", "بارگذاری‌شکاÙتن‌شناورها", "بارگذاری‌شکلهای‌خارجی", "بارگذاری‌طرح", "بارگذاری‌طرح‌بندی", "بارگذاری‌عرض‌خط", "بارگذاری‌Ùاصله‌بین‌خط", "بارگذاری‌Ùرمولها", "بارگذاری‌Ùضای‌سÙید", "بارگذاری‌Ùضا‌گذاری", "بارگذاری‌قالبی", "بارگذاری‌قلم‌متن", "بارگذاری‌لوح", "بارگذاری‌لیست", "بارگذاری‌لیست‌ترکیبی", "بارگذاری‌لیست‌مرجع", "بارگذاری‌مترادÙها", "بارگذاری‌متغیر‌متن", "بارگذاری‌متن", "بارگذاری‌متنهای‌بالا", "بارگذاری‌متن‌سر", "بارگذاری‌متن‌سربرگ", "بارگذاری‌متن‌قالبی", "بارگذاری‌متن‌متنها", "بارگذاری‌متن‌پانوشت", "بارگذاری‌متن‌پایین", "بارگذاری‌مجموعه‌ستون", "بارگذاری‌مجموعه‌نماد", "بارگذاری‌محیط‌قلم‌متن", "بارگذاری‌منوی‌پانل", "بارگذاری‌مکان‌متن", "بارگذاری‌مکان‌گذاری", "بارگذاری‌میدان", "بارگذاری‌میدانها", "بارگذاری‌میله‌تطابق", "بارگذاری‌میله‌زیر", "بارگذاری‌میله‌پانل", "بارگذاری‌نسخه‌ها", "بارگذاری‌نشانه‌شکستن", "بارگذاری‌نشانه‌گذاری", "بارگذاری‌نشرها", "بارگذاری‌نقل", "بارگذاری‌پاراگراÙها", "بارگذاری‌پانل", "بارگذاری‌پانوشتها", "بارگذاری‌پایین", "بارگذاری‌پرده‌ها", "بارگذاری‌پرده‌پانل", "بارگذاری‌پروÙایلها", "بارگذاری‌پرکردن‌خطها", "بارگذاری‌پس‌زمینه", "بارگذاری‌پس‌زمینه‌ها", "بارگذاری‌چیدن", "بارگذاری‌گذارصÙحه", "بارگذاری‌گروههای‌آیتم", "بارگذاری‌گروه‌آیتم", "بازنشانی", "بازنشانی‌شماره", "بازنشانی‌متن", "بازنشانی‌نشانه‌گذاری", "باگذاری‌متن‌برچسب", "بدون‌بعد", "بدون‌بلوکهای‌بیشتر", "بدون‌تورÙتگی", "بدون‌خط‌بالاوپایین", "بدون‌خط‌سروته‌برگ", "بدون‌Ùایلهای‌بیشتر", "بدون‌Ùضا", "بدون‌Ùضای‌سÙید", "بدون‌لیست", "بدون‌نشانه‌گذاری", "برنامه", "بروبه", "بروبه‌جعبه", "بروبه‌صÙحه", "بروپایین", "برچسب", "برچسبها", "بعد", "بلند", "بلوکهای‌پردازش", "بلوکها‌پنهان", "بنویس‌بین‌لیست", "بنویس‌درثبت", "بنویس‌درلیست‌مرجع", "بنویس‌در‌لیست", "تاریخ", "تاریخ‌جاری", "تاریخ‌رجوع", "تایپ", "تایپ‌باÙر", "تایپ‌پرونده", "تب", "ترجمه", "تطابق", "تعریÙ", "تعریÙ‌آرایش", "تعریÙ‌آرم", "تعریÙ‌الگوی‌جدول", "تعریÙ‌اندازه‌برگ", "تعریÙ‌باÙر", "تعریÙ‌بخش", "تعریÙ‌برنامه", "تعریÙ‌برچسب", "تعریÙ‌بلوک", "تعریÙ‌بلوک‌بخش", "تعریÙ‌تایپ", "تعریÙ‌تایپ‌کردن", "تعریÙ‌تبدیل", "تعریÙ‌ترتیب", "تعریÙ‌ترکیب", "تعریÙ‌تنظیم‌ریاضی", "تعریÙ‌توده‌میدان", "تعریÙ‌ثبت", "تعریÙ‌جانشانی", "تعریÙ‌جدول‌بندی", "تعریÙ‌جعبه‌‌اÙÙ‚ÛŒ", "تعریÙ‌حرÙ", "تعریÙ‌خالی", "تعریÙ‌خروجی", "تعریÙ‌خط‌حائل", "تعریÙ‌درون‌حاشیه", "تعریÙ‌رنگ", "تعریÙ‌زیرمیدان", "تعریÙ‌سبک", "تعریÙ‌سبک‌قلم", "تعریÙ‌سر", "تعریÙ‌شرح", "تعریÙ‌شروع‌پایان", "تعریÙ‌شماره‌بندی", "تعریÙ‌شمایل‌مرجع", "تعریÙ‌شناور", "تعریÙ‌شکستن‌ستون", "تعریÙ‌شکست‌صÙحه", "تعریÙ‌طرح‌بندی", "تعریÙ‌Ùرمان", "تعریÙ‌قالبی", "تعریÙ‌قلم", "تعریÙ‌قلم‌خام", "تعریÙ‌قلم‌متن", "تعریÙ‌لایه", "تعریÙ‌لهجه", "تعریÙ‌لوح", "تعریÙ‌لیست", "تعریÙ‌لیست‌ترکیبی", "تعریÙ‌لیست‌مرجع", "تعریÙ‌مترادÙها", "تعریÙ‌مترادÙ‌قلم", "تعریÙ‌متغیرمتن", "تعریÙ‌متن", "تعریÙ‌متن‌قالبی", "تعریÙ‌مجموعه‌ستون", "تعریÙ‌محیط‌قلم‌بدنه", "تعریÙ‌مرجع", "تعریÙ‌منوی‌پانل", "تعریÙ‌مکان‌متن", "تعریÙ‌میدان", "تعریÙ‌میدان‌اصلی", "تعریÙ‌نسخه", "تعریÙ‌نشانه‌گذاری", "تعریÙ‌نماد", "تعریÙ‌نمادشکل", "تعریÙ‌پاراگراÙها", "تعریÙ‌پروÙایل", "تعریÙ‌پوشش", "تعریÙ‌گروه‌آیتم", "تعریÙ‌گروه‌رنگ", "تعیین‌شماره", "تعیین‌شماره‌سر", "تعیین‌متغیر‌متن", "تعیین‌محتوای‌متن", "تعیین‌مشخصات‌ثبت", "تعیین‌مشخصات‌لیست", "تغییربه‌قلم‌بدنه", "تغییربه‌قلم‌خام", "تنظیم‌راست", "تنظیم‌طرح‌بندی", "تنظیم‌وسط", "توجه", "تورÙتگی", "توری", "تولید", "تک", "ثبت‌زوج", "ثبت‌کامل", "جداسازی‌نشانه‌گذاری", "حاش", "حرÙ", "حرÙها", "Ø­Ùظ‌بلوکها", "حقیقت", "خالی", "خطهای‌سیاه", "خطهای‌نازک", "خطها‌خالی", "خط‌حاشیه", "خط‌سیاه", "خط‌متن", "خط‌مو", "خط‌نازک", "خ‌ا", "خ‌ع", "در", "درج‌آرمها", "درج‌ثبت", "درج‌خط", "درج‌درخط", "درج‌درخطها", "درج‌درمتن", "درج‌درمیدان", "درج‌در‌بالای‌یکدیگر", "درج‌در‌توری", "درج‌راهنما", "درج‌زیرÙرمول", "درج‌شماره‌سر", "درج‌شماره‌صÙحه", "درج‌شناور", "درج‌Ùرمول", "درج‌لیست", "درج‌لیست‌خام", "درج‌لیست‌مختلط", "درج‌لیست‌مرجع", "درج‌متغیرمتن", "درج‌متن‌سر", "درج‌پانوشتها", "درج‌پانوشتهای‌موضعی", "درج‌چوب‌خط", "درج‌کنار‌به‌کنار", "درحاشیه", "درحاشیه‌دیگر", "درحاشیه‌راست", "درحاشیه‌چپ", "درخارجی", "درخط", "درداخلی", "درراست", "درصÙحه", "درقالبی", "درلبه‌راست", "درلبه‌چپ", "درمورد", "درون", "درپر", "درچپ", "دریاÙت‌باÙر", "دریاÙت‌شماره", "دریاÙت‌نشانه", "دوران", "دکمه", "دکمه‌منو", "دکمه‌پانل", "رج", "رجوع", "رنگ", "رنگ‌خاکستری", "روزهÙته", "ریاضی", "زبان", "زبان‌اصلی", "ستون", "ستون‌امتحان", "سر", "سرپوش‌کوچک‌نه", "شروع‌آرایش", "شروع‌آرایش‌ستون", "شروع‌باریکتر", "شروع‌بازبینی", "شروع‌بلوک‌حاشیه", "شروع‌ترکیب", "شروع‌تصحیح‌خط", "شروع‌تطابق", "شروع‌تنظیم", "شروع‌تولید", "شروع‌جدول", "شروع‌جدولها", "شروع‌خط", "شروع‌خطها", "شروع‌خط‌حاشیه", "شروع‌خط‌متن", "شروع‌رنگ", "شروع‌ستونها", "شروع‌سراسری", "شروع‌شماره‌گذاری‌خط", "شروع‌شکل", "شروع‌غیر‌Ùشرده", "شروع‌Ùشرده", "شروع‌متن", "شروع‌مجموعه‌ستون", "شروع‌مجموعه‌نماد", "شروع‌محیط", "شروع‌مخالÙ", "شروع‌موضعی", "شروع‌مولÙÙ‡", "شروع‌مکان‌گذاری", "شروع‌نسخه", "شروع‌نقل‌قول", "شروع‌نوشتار", "شروع‌پانوشتهای‌موضعی", "شروع‌پروÙایل", "شروع‌پروژه", "شروع‌پس‌زمینه", "شروع‌پوشش", "شروع‌کد", "شماره‌اÙزایش", "شماره‌زیرصÙحه", "شماره‌زیرÙرمول", "شماره‌سر", "شماره‌سرجاری", "شماره‌صÙحه", "شماره‌صÙحه‌کامل", "شماره‌Ùرمول", "شماره‌مبدل", "شماره‌ها", "شماره‌کاهش", "شماره‌کل‌صÙحه‌ها", "شکاÙتن‌شناور", "شکل‌خارجی", "صÙحه", "صÙحه‌تست", "صÙحه‌زوج", "صÙحه‌پردازش", "طول‌لیست", "عبوربلوکها", "عرض‌آرایش", "عرض‌برگ", "عرض‌حاشیه", "عرض‌حاشیه‌خارجی", "عرض‌حاشیه‌داخلی", "عرض‌حاشیه‌راست", "عرض‌حاشیه‌چپ", "عرض‌خط", "عرض‌لبه", "عرض‌لبه‌خارجی", "عرض‌لبه‌داخلی", "عرض‌لبه‌راست", "عرض‌لبه‌چپ", "عرض‌لیست", "عرض‌متن", "عمق‌صÙحه", "عنوان‌حاشیه", "Ùاصله‌بالا", "Ùاصله‌ته‌برگ", "Ùاصله‌حاشیه", "Ùاصله‌حاشیه‌خارجی", "Ùاصله‌حاشیه‌داخلی", "Ùاصله‌حاشیه‌راست", "Ùاصله‌حاشیه‌چپ", "Ùاصله‌سربرگ", "Ùاصله‌لبه", "Ùاصله‌لبه‌خارجی", "Ùاصله‌لبه‌داخلی", "Ùاصله‌لبه‌راست", "Ùاصله‌لبه‌چپ", "Ùاصله‌پایین", "Ùاصله‌پشت", "Ùشرده", "Ùضا", "Ùضاهای‌ثابت", "Ùضای‌بالا", "Ùضای‌برش", "Ùضای‌ثابت", "Ùضای‌سÙید", "Ùضای‌سÙیدصحیح", "Ùضای‌پایین", "Ùوری‌به‌لیست", "Ùوری‌بین‌لیست", "قالبی", "لوح‌مقایسه", "ماه", "متغیر متن", "متن‌برچسب", "متن‌حاشیه", "متن‌سر", "متن‌پانوشت", "محیط", "مراجعه", "مرجع", "مرجع‌صÙحه", "مرجع‌متن", "مرحله‌سر", "مسکن", "معنی‌واحد", "مقایسه‌گروه‌رنگ", "مقدارخاکستری", "مقداررنگ", "مقیاس", "منÙÛŒ", "منوی‌پانل", "مولÙÙ‡", "مکان", "مکان‌متن", "میدان", "میدانهای‌گزارش", "میدان‌شبیه‌سازی", "میدان‌پشته", "میدان‌کپی", "میله‌تطابق", "میله‌رنگ", "میله‌پانل", "ناشناس", "نام‌ماکرو", "نسخه", "نسخه‌نشانه", "نشانه‌گذاری", "نشانه‌گذاری‌زوج", "نشر", "نصب‌زبان", "نقطه‌ها", "نقل", "نقل‌قول", "نم", "نماد", "نمادسر", "نمادلیست", "نمایش‌آرایش", "نمایش‌بارگذاریها", "نمایش‌بستها", "نمایش‌توری", "نمایش‌رنگ", "نمایش‌شکلهای‌خارجی", "نمایش‌طرح‌بندی", "نمایش‌قالب", "نمایش‌قلم‌بدنه", "نمایش‌لوح", "نمایش‌مجموعه‌علامت", "نمایش‌محیط‌قلم‌بدنه", "نمایش‌میدانها", "نمایش‌چاپ", "نمایش‌گروه‌رنگ", "نوشتارزوج", "هدایت", "پا", "پابا", "پانوشت", "پایان‌آرایش", "پایان‌آرایش‌ستون", "پایان‌بازبینی", "پایان‌بلوک‌حاشیه", "پایان‌ترکیب", "پایان‌تصحیح‌خط", "پایان‌تطابق", "پایان‌تنظیم", "پایان‌تولید", "پایان‌جدول", "پایان‌جدولها", "پایان‌خط", "پایان‌خطها", "پایان‌خط‌حاشیه", "پایان‌خط‌متن", "پایان‌رنگ", "پایان‌ستونها", "پایان‌سراسری", "پایان‌شماره‌گذاری‌خط", "پایان‌غیرÙشرده", "پایان‌Ùشرده", "پایان‌متن", "پایان‌مجموعه‌ستون", "پایان‌محیط", "پایان‌مخالÙ", "پایان‌موضعی", "پایان‌مولÙÙ‡", "پایان‌مکان‌گذاری", "پایان‌نازکتر", "پایان‌نسخه", "پایان‌نقل‌قول", "پایان‌نوشتار", "پایان‌پانوشتهای‌موضعی", "پایان‌پروÙایل", "پایان‌پروژه", "پایان‌پس‌زمینه", "پایان‌پوشش", "پایان‌کد", "پایین", "پرده", "پروژه", "پرکردن‌میدان", "پس‌زمینه", "پیروی‌نسخه", "پیروی‌نسخه‌پروÙایل", "پیروی‌پروÙایل", "چاپ‌ارتÙاع‌برگ", "چاپ‌عرض‌برگ", "چوبخط", "چپ‌چین", "کاغذزوج", "کسر", "کشیده", "کلمه‌حاشیه", "کلمه‌راست", "گیره", "یادداشت", "یک‌جا", "یک‌خط" },
+ ["ro"]={ "CAP", "CUVANT", "CUVINTE", "Cap", "Caps", "Cuvant", "Cuvinte", "KAP", "Kap", "Kaps", "LUNA", "Litera", "Litere", "Numere", "Numereromane", "ZIDINSAPTAMANA", "adapteazaaspect", "adubuffer", "adumarcaje", "afiseazaaspect", "afiseazacampuri", "afiseazaculoare", "afiseazafiguriexterne", "afiseazafonttext", "afiseazagrid", "afiseazagrupculoare", "afiseazamakeup", "afiseazamediufonttext", "afiseazapaleta", "afiseazarama", "afiseazasetari", "afiseazasetsimboluri", "afiseazastruts", "afiseazatiparire", "aliniat", "aliniatcentru", "aliniatdreapta", "aliniatstanga", "appendix", "arg", "ascundeblocuri", "atleftmargin", "atrightmargin", "baraculoare", "barainteractiune", "barasincronizare", "blanc", "but", "butoaneinteractiune", "buton", "butonmeniu", "camp", "campumplere", "cap", "chapter", "chem", "citat", "clip", "cloneazacamp", "coloana", "comment", "comparagrupculoare", "comparapaleta", "completeazanumarpagina", "completecombinedlist", "completelistoffloats", "completelistofsorts", "completelistofsynonyms", "completeregister", "componenta", "convertestenumar", "copiazacamp", "corecteazaspatiualb", "coupledregister", "crlf", "culoare", "culoaregri", "cupleazadocument", "cupleazamarcaje", "cupleazaregistru", "cutspace", "cuvantdreapta", "cuvantmarginal", "data", "datacurenta", "datareferit", "decrementnumber", "decupleazamarcaje", "definebodyfontDEF", "definebodyfontREF", "definecolumnbreak", "definecolumnset", "definecombination", "definedfont", "definefontfeature", "definefonthandling", "defineindentedtext", "defineinmargin", "defineitemgroup", "definelayer", "definelayout", "definemathalignment", "definepagebreak", "defineplacement", "defineste", "definesteaccent", "definesteantet", "definesteblanc", "definestebloc", "definesteblocsectiune", "definestebuffer", "definestecamp", "definestecampprincipal", "definestecaracter", "definestecomanda", "definesteconversie", "definesteculoare", "definestedescriere", "definestedimensiunehartie", "definesteenumerare", "definesteeticheta", "definestefloat", "definestefont", "definestefontraw", "definestefonttext", "definesteformatreferinte", "definestegrupculori", "definestehbox", "definesteinconjurare", "definestelista", "definestelistacombinata", "definestelistareferinte", "definestelogo", "definestemakeup", "definestemarcaje", "definestemediulfonttext", "definestemeniuinteractiune", "definesteoutput", "definesteoverlay", "definestepaleta", "definesteparagraf", "definestepozitietext", "definesteprofil", "definesteprogram", "definestereferinte", "definesteregistru", "definesterigla", "definestesablontabel", "definestesectiune", "definestesimbol", "definestesimbolfigura", "definestesinonim", "definestesinonimfont", "definestesortare", "definestestartstop", "definestestil", "definestestilfont", "definestestivacampuri", "definestesubcamp", "definestetabulatori", "definestetext", "definestetexteinconjurate", "definestetextinconjurat", "definestetyping", "definestevariabilatext", "definesteversiune", "definetype", "definetypeface", "description", "despre", "determinacaracteristicilelistei", "determinacaracteristiciregistru", "determinanumartitlu", "dezactiveazameniuinteractiune", "dimensiune", "din", "distantaantet", "distantacolt", "distantacoltdreapta", "distantacoltstanga", "distantajos", "distantamargine", "distantamarginedreapta", "distantamarginestanga", "distantasubsol", "distantasus", "domiciliu", "dute", "dutebox", "dutepagina", "ecran", "el", "element", "emptylines", "enumeration", "eticheta", "etichete", "fact", "faraaliniat", "faradimensiune", "farafisiere", "faraliniiantetsisubsol", "faraliniisussijos", "faralista", "faramarcaje", "faraspatiu", "faraspatiualb", "figuraexterna", "firdepar", "folosesteURL", "folosestebloc", "folosestecodificarea", "folosestecomenzi", "folosestedirector", "folosestedocumentextern", "folosestefiguraexterna", "folosestefisiereexterne", "folosestefisierextern", "folosestemodul", "folosestemodule", "folosestemuzicaexterna", "folosestereferinte", "folosestescriptJS", "folosestesimboluri", "folosestespeciale", "folosesteurl", "footnotetext", "forteazablocuri", "fractie", "framed", "framedtext", "fundal", "gatablocuri", "getnumber", "grid", "grosimelinie", "hartiedubla", "headsym", "hl", "immediatebetweenlist", "immediatetolist", "impachetat", "impartefloat", "in", "inalt", "inaltamargine", "inaltimeantet", "inaltimehartie", "inaltimehartieimprimanta", "inaltimejos", "inaltimelista", "inaltimemakeup", "inaltimesubsol", "inaltimesus", "inaltimetext", "indentation", "indreapta", "inframed", "ininner", "injos", "inlinie", "inmaframed", "inmargineadreapta", "inmargineastanga", "inneredgedistance", "inneredgewidth", "innermargindistance", "innermarginwidth", "inouter", "inparteadreapta", "inparteastanga", "instalarelimba", "instanga", "intins", "jos", "jossus", "kap", "la", "labeling", "lapagina", "latimecoltdreapta", "latimecoltstanga", "latimecolturi", "latimehartie", "latimehartieimprimanta", "latimelista", "latimemakeup", "latimemargine", "latimemarginedreapta", "latimemarginestanga", "latimetext", "leg", "limba", "limbaprincipala", "liniemargine", "linieneagra", "liniesubtire", "linieumplere", "liniinegre", "liniisubtiri", "listsymbol", "litera", "litere", "loadsorts", "loadsynonyms", "logcampuri", "luna", "lungimelista", "maframed", "mapfontsize", "mar", "marcaje", "marcheazaversiune", "marginal", "matematica", "mediaeval", "mediu", "meniuinteractiune", "minicitat", "moveformula", "movesidefloat", "mutapegrid", "name", "navigating", "necunoscut", "nextsection", "niveltitlu", "nocap", "nokap", "nop", "nota", "notasubsol", "numarformula", "numarincrement", "numarpagina", "numarsubformula", "numartitlu", "numartitlucurent", "numartotalpagini", "numberofsubpages", "nume", "numere", "numereromane", "numeunitate", "nutesta", "olinie", "outeredgedistance", "outeredgewidth", "outermargindistance", "outermarginwidth", "overbar", "overbars", "overstrike", "overstrikes", "pagedepth", "pageoffset", "pagina", "paginadubla", "paragraph", "part", "pastreazablocuri", "pelung", "placefloat", "placeheadnumber", "placeheadtext", "placelistoffloats", "placelistofsorts", "placelistofsynonyms", "placerawlist", "placereferencelist", "plaseazapegrid", "plaseazasemnecarte", "potrivestecamp", "pozitie", "pozitietext", "proceseazabloc", "proceseazapagina", "produs", "program", "proiect", "publicatie", "puncte", "punedeasuprafiecareia", "punefatainfata", "puneformula", "punelegenda", "punelista", "punelistacombinata", "punelogouri", "punenotesubsol", "punenotesubsollocale", "punenumarpagina", "puneregistru", "punerigla", "punesubformula", "punevariabilatext", "ran", "ref", "refa", "referinta", "referintapagina", "referintatext", "referit", "referring", "reflexie", "register", "remarca", "reservefloat", "reset", "reseteazamarcaje", "resetnumber", "resettextcontent", "riglatext", "rigleumplere", "roteste", "saripesteblocuri", "scala", "scriebuffer", "scrieinlista", "scrieinlistareferinte", "scrieinregistru", "scrieintreliste", "section", "seeregister", "selecteazablocuri", "selecteazahartie", "selecteazaversiune", "semncarte", "setarebarasincronizare", "setareitemization", "setarelimba", "setareoutput", "setarepozitie", "setaresincronizare", "setari", "seteazaaliniat", "seteazaalinierea", "seteazaantet", "seteazaaranjareapag", "seteazaaspect", "seteazabarainteractiune", "seteazablanc", "seteazabloc", "seteazablocsectiune", "seteazablocurimarginale", "seteazabuffer", "seteazabutoane", "seteazacamp", "seteazacampuri", "seteazaclipping", "seteazacoloane", "seteazacombinari", "seteazacomentariu", "seteazacomentariupagina", "seteazaculoare", "seteazaculori", "seteazadefinireanotasubsol", "seteazadescriere", "seteazadimensiunihartie", "seteazaecrane", "seteazaecraninteractiune", "seteazaelemente", "seteazaenumerare", "seteazafiguriexterne", "seteazafloat", "seteazafloats", "seteazafonttext", "seteazaformulare", "seteazaformule", "seteazafundal", "seteazafundaluri", "seteazagrosimelinie", "seteazaimpartireafloat", "seteazainconjurat", "seteazaingust", "seteazainteractiunea", "seteazajos", "seteazalegenda", "seteazalegendele", "seteazaliniesilabe", "seteazaliniesubtire", "seteazalinii", "seteazaliniimargine", "seteazaliniinegre", "seteazaliniiumplere", "seteazalista", "seteazalistacombinata", "seteazalistareferinte", "seteazamajuscule", "seteazamakeup", "seteazamarcaje", "seteazamarginal", "seteazamediulfonttext", "seteazameniuinteractiune", "seteazaminicitat", "seteazanotasubsol", "seteazanumarpagina", "seteazanumarsubpagina", "seteazanumartitlu", "seteazanumerotare", "seteazanumerotarelinii", "seteazanumerotarepagina", "seteazanumerotareparagrafe", "seteazapaleta", "seteazaparagrafe", "seteazaplasareaopozita", "seteazapozitietext", "seteazaprofile", "seteazaprograme", "seteazapublicatii", "seteazareferinte", "seteazaregistru", "seteazarigla", "seteazarigletext", "seteazarigleumplere", "seteazarotare", "seteazasectiune", "seteazasimbol", "seteazasinonime", "seteazasistem", "seteazasortare", "seteazaspatiu", "seteazaspatiualb", "seteazaspatiuinterliniar", "seteazastrut", "seteazasublinie", "seteazasubsol", "seteazasus", "seteazatab", "seteazatabele", "seteazatabulatori", "seteazatext", "seteazatexteantet", "seteazatextejos", "seteazatextesubsol", "seteazatextesus", "seteazatextetext", "seteazatexteticheta", "seteazatexttitlu", "seteazatitlu", "seteazatitluri", "seteazatoleranta", "seteazatranzitiepagina", "seteazatype", "seteazatyping", "seteazaurl", "seteazavariabilatext", "seteazaversiuni", "setnumber", "settextcontent", "setupanswerarea", "setupcolumnset", "setupcolumnsetlines", "setupcolumnsetstart", "setupfonthandling", "setupfontsynonym", "setupindentedtext", "setupinterlinespace2", "setupitemgroup", "setuplistalternative", "setupmathalignment", "setupnumber", "setuppaper", "setupplacement", "setupstartstop", "setvariabilatext", "sim", "simbol", "sincronizeaza", "sort", "spatiifixate", "spatiu", "spatiualb", "spatiufixat", "spatiujos", "spatiuspate", "spatiusus", "startalignment", "startaliniere", "startblocmarginal", "startbuffer", "startcitat", "startcodificare", "startcoloane", "startcolumnmakeup", "startcolumns", "startcolumnset", "startcombinare", "startcombination", "startcomment", "startcomponenta", "startcorectielinie", "startculoare", "startdescription", "startdocument", "startenumeration", "startfact", "startfigura", "startfigure", "startfloattext", "startformula", "startframedtext", "startfundal", "startglobal", "starthiding", "startimpachetat", "startingust", "startitemgroup", "startlegend", "startline", "startlinecorrection", "startlinenumbering", "startlines", "startlinie", "startliniemargine", "startlinii", "startlocal", "startlocalenvironment", "startlocalfootnotes", "startmakeup", "startmarginblock", "startmediu", "startmeniuinteractiune", "startnamemakeup", "startnarrower", "startneimpachetat", "startnotesubsollocale", "startnumerotarelinii", "startopozit", "startopposite", "startoverlay", "startoverview", "startparagraph", "startpositioning", "startpostponing", "startpozitionare", "startprodus", "startprofil", "startprofile", "startproiect", "startraster", "startregister", "startriglatext", "startsetsimboluri", "startsincronizare", "startsymbolset", "startsynchronization", "starttabel", "starttabele", "starttable", "starttables", "starttabulate", "starttext", "starttyping", "startunpacked", "startversiune", "stivacampuri", "stopalignment", "stopaliniere", "stopblobal", "stopblocmarginal", "stopbuffer", "stopcitat", "stopcodificare", "stopcoloane", "stopcolumnmakeup", "stopcolumns", "stopcolumnset", "stopcombinare", "stopcombination", "stopcomment", "stopcomponenta", "stopcorectielinie", "stopculoare", "stopdescription", "stopdocument", "stopenumeration", "stopfact", "stopfigure", "stopfloattext", "stopformula", "stopframedtext", "stopfundal", "stophiding", "stopimpachetat", "stopingust", "stopitemgroup", "stoplegend", "stopline", "stoplinecorrection", "stoplinenumbering", "stoplines", "stoplinie", "stopliniemargine", "stoplinii", "stoplocal", "stoplocalenvironment", "stoplocalfootnotes", "stopmakeup", "stopmarginblock", "stopmediu", "stopmeniuinteractiune", "stopnamemakeup", "stopnarrower", "stopneimpachetat", "stopnotesubsollocale", "stopnumerotarelinii", "stopopozit", "stopopposite", "stopoverlay", "stopoverview", "stopparagraph", "stoppositioning", "stoppostponing", "stoppozitionare", "stopprodus", "stopprofil", "stopprofile", "stopproiect", "stopraster", "stopriglatext", "stopsincronizare", "stopsymbolset", "stopsynchronization", "stoptabel", "stoptabele", "stoptable", "stoptables", "stoptabulate", "stoptext", "stoptyping", "stopunpacked", "stopversiune", "sub", "subject", "subpagenumber", "subsection", "subsubject", "subsubsection", "subsubsubject", "synonym", "tab", "testcolumn", "testpage", "tex", "texteticheta", "textmarginal", "texttitlu", "textumplere", "title", "titlu", "titlumarginal", "tooltip", "traduce", "trecilafontraw", "trecilafonttext", "txt", "typ", "type", "typefile", "underbar", "underbars", "undeva", "urmeazaprofil", "urmeazaversiune", "urmeazaversiuneprofil", "useXMLfilter", "usedirectory", "usetypescript", "usetypescriptfile", "valoareculoare", "valoaregri", "variabilatext", "versiune", "vl", "zidinsaptamana" },
+} \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metafun.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metafun.lua
new file mode 100644
index 00000000000..749be7663c1
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metafun.lua
@@ -0,0 +1,4 @@
+return {
+ ["commands"]={ "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "acosh", "asinh", "sinh", "cosh", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "smoothed", "cornered", "superellipsed", "randomized", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withlinearshading", "withcircularshading", "withfromshadecolor", "withtoshadecolor", "withshading", "shadedinto", "withcircularshade", "withlinearshade", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "graphictext", "loadfigure", "externalfigure", "withmask", "figure", "register", "bitmapimage", "colordecimals", "ddecimal", "dddecimal", "ddddecimal", "textext", "thetextext", "rawtextext", "textextoffset", "verbatim", "thelabel", "label", "transparent", "withtransparency", "asgroup", "infont", "set_linear_vector", "linear_shade", "define_linear_shade", "define_circular_linear_shade", "define_sampled_linear_shade", "set_circular_vector", "circular_shade", "define_circular_shade", "define_circular_linear_shade", "define_sampled_circular_shade", "space", "CRLF", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedpath", "constructedpairs", "punkedfunction", "curvedfunction", "tightfunction", "punkedpath", "curvedpath", "tightpath", "punkedpairs", "curvedpairs", "tightpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "normalfill", "normaldraw", "visualizepaths", "naturalizepaths", "drawboundary", "drawwholepath", "visualizeddraw", "visualizedfill", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions" },
+ ["internals"]={ "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel", "shadefactor", "textextoffset", "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent", "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent" },
+} \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metapost.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metapost.lua
new file mode 100644
index 00000000000..d3c19908956
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-metapost.lua
@@ -0,0 +1,7 @@
+return {
+ ["commands"]={ "beginfig", "endfig", "rotatedaround", "reflectedabout", "arrowhead", "currentpen", "currentpicture", "cuttings", "defaultfont", "extra_beginfig", "extra_endfig", "ditto", "EOF", "down", "evenly", "fullcircle", "halfcircle", "identity", "in", "left", "origin", "pensquare", "quartercircle", "right", "unitsquare", "up", "withdots", "abs", "bbox", "ceiling", "center", "cutafter", "cutbefore", "dir", "directionpoint", "div", "dotprod", "intersectionpoint", "inverse", "mod", "round", "unitvector", "whatever", "cutdraw", "draw", "drawarrow", "drawdblarrow", "fill", "filldraw", "drawdot", "loggingall", "interact", "tracingall", "tracingnone", "pickup", "undraw", "unfill", "unfilldraw", "buildcycle", "dashpattern", "decr", "dotlabel", "dotlabels", "drawoptions", "incr", "label", "labels", "max", "min", "thelabel", "z", "beginchar", "blacker", "capsule_end", "change_width", "define_blacker_pixels", "define_corrected_pixels", "define_good_x_pixels", "define_good_y_pixels", "define_horizontal_corrected_pixels", "define_pixels", "define_whole_blacker_pixels", "define_whole_pixels", "define_whole_vertical_blacker_pixels", "define_whole_vertical_pixels", "endchar", "extra_beginchar", "extra_endchar", "extra_setup", "font_coding_scheme", "clearxy", "clearit", "clearpen", "shipit", "font_extra_space", "exitunless", "relax", "hide", "gobble", "gobbled", "stop", "blankpicture", "counterclockwise", "tensepath", "takepower", "direction", "softjoin", "makelabel", "rotatedabout", "flex", "superellipse", "erase", "image", "nullpen", "savepen", "clearpen", "penpos", "penlabels", "range", "numtok", "thru", "z", "laboff", "bye", "red", "green", "blue", "cyan", "magenta", "yellow", "black", "white", "background", "graypart", "graycolor", "mm", "pt", "dd", "bp", "cm", "pc", "cc", "in" },
+ ["internals"]={ "mitered", "rounded", "beveled", "butt", "squared", "eps", "epsilon", "infinity", "bboxmargin", "ahlength", "ahangle", "labeloffset", "dotlabeldiam", "defaultpen", "defaultscale", "join_radius", "pen_lft", "pen_rt", "pen_top", "pen_bot" },
+ ["primitives"]={ "charcode", "day", "linecap", "linejoin", "miterlimit", "month", "pausing", "prologues", "showstopping", "time", "tracingcapsules", "tracingchoices", "mpprocset", "tracingcommands", "tracingequations", "tracinglostchars", "tracingmacros", "tracingonline", "tracingoutput", "tracingrestores", "tracingspecs", "tracingstats", "tracingtitles", "truecorners", "warningcheck", "year", "false", "nullpicture", "pencircle", "true", "and", "angle", "arclength", "arctime", "ASCII", "boolean", "bot", "char", "color", "cosd", "cycle", "decimal", "directiontime", "floor", "fontsize", "hex", "infont", "intersectiontimes", "known", "length", "llcorner", "lrcorner", "makepath", "makepen", "mexp", "mlog", "normaldeviate", "not", "numeric", "oct", "odd", "or", "path", "pair", "pen", "penoffset", "picture", "point", "postcontrol", "precontrol", "reverse", "rotated", "scaled", "shifted", "sind", "slanted", "sqrt", "str", "string", "subpath", "substring", "transform", "transformed", "ulcorner", "uniformdeviate", "unknown", "urcorner", "xpart", "xscaled", "xxpart", "xypart", "ypart", "yscaled", "yxpart", "yypart", "zscaled", "addto", "clip", "input", "interim", "let", "newinternal", "save", "setbounds", "shipout", "show", "showdependencies", "showtoken", "showvariable", "special", "begingroup", "endgroup", "of", "curl", "tension", "and", "controls", "interpath", "on", "off", "def", "vardef", "enddef", "expr", "suffix", "text", "primary", "secondary", "tertiary", "primarydef", "secondarydef", "tertiarydef", "randomseed", "also", "contour", "doublepath", "withcolor", "withpen", "dashed", "if", "else", "elseif", "fi", "for", "endfor", "forever", "exitif", "forsuffixes", "downto", "upto", "step", "until", "charlist", "extensible", "fontdimen", "headerbyte", "kern", "ligtable", "boundarychar", "chardp", "charext", "charht", "charic", "charwd", "designsize", "fontmaking", "charexists", "cullit", "currenttransform", "gfcorners", "grayfont", "hround", "imagerules", "lowres_fix", "nodisplays", "notransforms", "openit", "displaying", "currentwindow", "screen_rows", "screen_cols", "pixels_per_inch", "cull", "display", "openwindow", "numspecial", "totalweight", "autorounding", "fillin", "proofing", "tracingpens", "xoffset", "chardx", "granularity", "smoothing", "turningcheck", "yoffset", "chardy", "hppp", "tracingedges", "vppp", "extra_beginfig", "extra_endfig", "mpxbreak", "endinput", "message", "delimiters", "turningnumber", "errmessage", "readstring", "scantokens", "end", "outer", "inner", "write", "to", "readfrom", "withprescript", "withpostscript", "top", "bot", "lft", "rt", "ulft", "urt", "llft", "lrt", "redpart", "greenpart", "bluepart", "cyanpart", "magentapart", "yellowpart", "blackpart", "greypart", "rgbcolor", "cmykcolor", "greycolor", "graycolor", "colormodel", "graypart", "expandafter" },
+ ["shortcuts"]={ "..", "...", "--", "---", "&" },
+ ["tex"]={ "btex", "etex", "verbatimtex" },
+} \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-tex.lua b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-tex.lua
new file mode 100644
index 00000000000..0dd0e1764b0
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/data/scite-context-data-tex.lua
@@ -0,0 +1,9 @@
+return {
+ ["aleph"]={ "AlephVersion", "Alephminorversion", "Alephrevision", "Alephversion", "Omegaminorversion", "Omegarevision", "Omegaversion", "boxdir", "pagebottomoffset", "pagerightoffset" },
+ ["etex"]={ "botmarks", "clubpenalties", "currentgrouplevel", "currentgrouptype", "currentifbranch", "currentiflevel", "currentiftype", "detokenize", "dimexpr", "displaywidowpenalties", "eTeXVersion", "eTeXminorversion", "eTeXrevision", "eTeXversion", "everyeof", "firstmarks", "fontchardp", "fontcharht", "fontcharic", "fontcharwd", "glueexpr", "glueshrink", "glueshrinkorder", "gluestretch", "gluestretchorder", "gluetomu", "ifcsname", "ifdefined", "iffontchar", "interactionmode", "interlinepenalties", "lastlinefit", "lastnodetype", "marks", "muexpr", "mutoglue", "numexpr", "pagediscards", "parshapedimen", "parshapeindent", "parshapelength", "predisplaydirection", "protected", "readline", "savinghyphcodes", "savingvdiscards", "scantokens", "showgroups", "showifs", "showtokens", "splitbotmarks", "splitdiscards", "splitfirstmarks", "topmarks", "tracingassigns", "tracinggroups", "tracingifs", "tracingnesting", "tracingscantokens", "unexpanded", "unless", "widowpenalties" },
+ ["luatex"]={ "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Umathaccent", "Umathaccents", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathbotaccent", "Umathchar", "Umathchardef", "Umathcharnum", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathopbinspacing", "Umathopclosespacing", "Umathopenbinspacing", "Umathopenclosespacing", "Umathopeninnerspacing", "Umathopenopenspacing", "Umathopenopspacing", "Umathopenordspacing", "Umathopenpunctspacing", "Umathopenrelspacing", "Umathoperatorsize", "Umathopinnerspacing", "Umathopopenspacing", "Umathopopspacing", "Umathopordspacing", "Umathoppunctspacing", "Umathoprelspacing", "Umathordbinspacing", "Umathordclosespacing", "Umathordinnerspacing", "Umathordopenspacing", "Umathordopspacing", "Umathordordspacing", "Umathordpunctspacing", "Umathordrelspacing", "Umathoverbarkern", "Umathoverbarrule", "Umathoverbarvgap", "Umathoverdelimiterbgap", "Umathoverdelimitervgap", "Umathpunctbinspacing", "Umathpunctclosespacing", "Umathpunctinnerspacing", "Umathpunctopenspacing", "Umathpunctopspacing", "Umathpunctordspacing", "Umathpunctpunctspacing", "Umathpunctrelspacing", "Umathquad", "Umathradicaldegreeafter", "Umathradicaldegreebefore", "Umathradicaldegreeraise", "Umathradicalkern", "Umathradicalrule", "Umathradicalvgap", "Umathrelbinspacing", "Umathrelclosespacing", "Umathrelinnerspacing", "Umathrelopenspacing", "Umathrelopspacing", "Umathrelordspacing", "Umathrelpunctspacing", "Umathrelrelspacing", "Umathspaceafterscript", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Uoverdelimiter", "Uradical", "Uroot", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Usubscript", "Usuperscript", "Uunderdelimiter", "alignmark", "aligntab", "attribute", "attributedef", "catcodetable", "clearmarks", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "fontid", "formatname", "gleaders", "ifabsdim", "ifabsnum", "ifprimitive", "initcatcodetable", "latelua", "luaescapestring", "luastartup", "luatexdatestamp", "luatexrevision", "luatexversion", "mathstyle", "nokerns", "noligs", "outputbox", "pageleftoffset", "pagetopoffset", "postexhyphenchar", "posthyphenchar", "preexhyphenchar", "prehyphenchar", "primitive", "savecatcodetable", "scantextokens", "suppressfontnotfounderror", "suppressifcsnameerror", "suppresslongerror", "suppressoutererror", "synctex" },
+ ["omega"]={ "OmegaVersion", "bodydir", "chardp", "charht", "charit", "charwd", "leftghost", "localbrokenpenalty", "localinterlinepenalty", "localleftbox", "localrightbox", "mathdir", "odelcode", "odelimiter", "omathaccent", "omathchar", "omathchardef", "omathcode", "oradical", "pagedir", "pageheight", "pagewidth", "pardir", "rightghost", "textdir" },
+ ["pdftex"]={ "efcode", "expanded", "ifincsname", "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "leftmarginkern", "letterspacefont", "lpcode", "pdfadjustspacing", "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", "pdfignoreddimen", "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", "pdfinclusionerrorlevel", "pdfinfo", "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagecolordepth", "pdflastximagepages", "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", "pdfmapfile", "pdfmapline", "pdfminorversion", "pdfnames", "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfobjcompresslevel", "pdfoptionpdfminorversion", "pdfoutline", "pdfoutput", "pdfpageattr", "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", "pdfpagesattr", "pdfpagewidth", "pdfpkmode", "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", "pdfrandomseed", "pdfrefobj", "pdfrefxform", "pdfrefximage", "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", "pdftexbanner", "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", "pdftracingfonts", "pdftrailer", "pdfuniformdeviate", "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", "pdfxformname", "pdfxformresources", "pdfximage", "pdfximagebbox", "quitvmode", "rightmarginkern", "rpcode", "tagcode" },
+ ["tex"]={ "-", "/", "AlephVersion", "Alephminorversion", "Alephrevision", "Alephversion", "OmegaVersion", "Omegaminorversion", "Omegarevision", "Omegaversion", "Udelcode", "Udelcodenum", "Udelimiter", "Udelimiterover", "Udelimiterunder", "Umathaccent", "Umathaccents", "Umathaxis", "Umathbinbinspacing", "Umathbinclosespacing", "Umathbininnerspacing", "Umathbinopenspacing", "Umathbinopspacing", "Umathbinordspacing", "Umathbinpunctspacing", "Umathbinrelspacing", "Umathbotaccent", "Umathchar", "Umathchardef", "Umathcharnum", "Umathclosebinspacing", "Umathcloseclosespacing", "Umathcloseinnerspacing", "Umathcloseopenspacing", "Umathcloseopspacing", "Umathcloseordspacing", "Umathclosepunctspacing", "Umathcloserelspacing", "Umathcode", "Umathcodenum", "Umathconnectoroverlapmin", "Umathfractiondelsize", "Umathfractiondenomdown", "Umathfractiondenomvgap", "Umathfractionnumup", "Umathfractionnumvgap", "Umathfractionrule", "Umathinnerbinspacing", "Umathinnerclosespacing", "Umathinnerinnerspacing", "Umathinneropenspacing", "Umathinneropspacing", "Umathinnerordspacing", "Umathinnerpunctspacing", "Umathinnerrelspacing", "Umathlimitabovebgap", "Umathlimitabovekern", "Umathlimitabovevgap", "Umathlimitbelowbgap", "Umathlimitbelowkern", "Umathlimitbelowvgap", "Umathopbinspacing", "Umathopclosespacing", "Umathopenbinspacing", "Umathopenclosespacing", "Umathopeninnerspacing", "Umathopenopenspacing", "Umathopenopspacing", "Umathopenordspacing", "Umathopenpunctspacing", "Umathopenrelspacing", "Umathoperatorsize", "Umathopinnerspacing", "Umathopopenspacing", "Umathopopspacing", "Umathopordspacing", "Umathoppunctspacing", "Umathoprelspacing", "Umathordbinspacing", "Umathordclosespacing", "Umathordinnerspacing", "Umathordopenspacing", "Umathordopspacing", "Umathordordspacing", "Umathordpunctspacing", "Umathordrelspacing", "Umathoverbarkern", "Umathoverbarrule", "Umathoverbarvgap", "Umathoverdelimiterbgap", "Umathoverdelimitervgap", "Umathpunctbinspacing", "Umathpunctclosespacing", "Umathpunctinnerspacing", "Umathpunctopenspacing", "Umathpunctopspacing", "Umathpunctordspacing", "Umathpunctpunctspacing", "Umathpunctrelspacing", "Umathquad", "Umathradicaldegreeafter", "Umathradicaldegreebefore", "Umathradicaldegreeraise", "Umathradicalkern", "Umathradicalrule", "Umathradicalvgap", "Umathrelbinspacing", "Umathrelclosespacing", "Umathrelinnerspacing", "Umathrelopenspacing", "Umathrelopspacing", "Umathrelordspacing", "Umathrelpunctspacing", "Umathrelrelspacing", "Umathspaceafterscript", "Umathstackdenomdown", "Umathstacknumup", "Umathstackvgap", "Umathsubshiftdown", "Umathsubshiftdrop", "Umathsubsupshiftdown", "Umathsubsupvgap", "Umathsubtopmax", "Umathsupbottommin", "Umathsupshiftdrop", "Umathsupshiftup", "Umathsupsubbottommax", "Umathunderbarkern", "Umathunderbarrule", "Umathunderbarvgap", "Umathunderdelimiterbgap", "Umathunderdelimitervgap", "Uoverdelimiter", "Uradical", "Uroot", "Ustack", "Ustartdisplaymath", "Ustartmath", "Ustopdisplaymath", "Ustopmath", "Usubscript", "Usuperscript", "Uunderdelimiter", "above", "abovedisplayshortskip", "abovedisplayskip", "abovewithdelims", "accent", "adjdemerits", "advance", "afterassignment", "aftergroup", "alignmark", "aligntab", "atop", "atopwithdelims", "attribute", "attributedef", "badness", "baselineskip", "batchmode", "begingroup", "belowdisplayshortskip", "belowdisplayskip", "binoppenalty", "bodydir", "botmark", "botmarks", "box", "boxdir", "boxmaxdepth", "brokenpenalty", "catcode", "catcodetable", "char", "chardef", "chardp", "charht", "charit", "charwd", "cleaders", "clearmarks", "closein", "closeout", "clubpenalties", "clubpenalty", "copy", "count", "countdef", "cr", "crampeddisplaystyle", "crampedscriptscriptstyle", "crampedscriptstyle", "crampedtextstyle", "crcr", "csname", "currentgrouplevel", "currentgrouptype", "currentifbranch", "currentiflevel", "currentiftype", "day", "deadcycles", "def", "defaulthyphenchar", "defaultskewchar", "delcode", "delimiter", "delimiterfactor", "delimitershortfall", "detokenize", "dimen", "dimendef", "dimexpr", "directlua", "discretionary", "displayindent", "displaylimits", "displaystyle", "displaywidowpenalties", "displaywidowpenalty", "displaywidth", "divide", "doublehyphendemerits", "dp", "dump", "eTeXVersion", "eTeXminorversion", "eTeXrevision", "eTeXversion", "edef", "efcode", "else", "emergencystretch", "end", "endcsname", "endgroup", "endinput", "endlinechar", "eqno", "errhelp", "errmessage", "errorcontextlines", "errorstopmode", "escapechar", "everycr", "everydisplay", "everyeof", "everyhbox", "everyjob", "everymath", "everypar", "everyvbox", "exhyphenchar", "exhyphenpenalty", "expandafter", "expanded", "fam", "fi", "finalhyphendemerits", "firstmark", "firstmarks", "floatingpenalty", "font", "fontchardp", "fontcharht", "fontcharic", "fontcharwd", "fontdimen", "fontid", "fontname", "formatname", "futurelet", "gdef", "gleaders", "global", "globaldefs", "glueexpr", "glueshrink", "glueshrinkorder", "gluestretch", "gluestretchorder", "gluetomu", "halign", "hangafter", "hangindent", "hbadness", "hbox", "hfil", "hfill", "hfilneg", "hfuzz", "hoffset", "holdinginserts", "hrule", "hsize", "hskip", "hss", "ht", "hyphenation", "hyphenchar", "hyphenpenalty", "if", "ifabsdim", "ifabsnum", "ifcase", "ifcat", "ifcsname", "ifdefined", "ifdim", "ifeof", "iffalse", "iffontchar", "ifhbox", "ifhmode", "ifincsname", "ifinner", "ifmmode", "ifnum", "ifodd", "ifpdfabsdim", "ifpdfabsnum", "ifpdfprimitive", "ifprimitive", "iftrue", "ifvbox", "ifvmode", "ifvoid", "ifx", "ignorespaces", "immediate", "indent", "initcatcodetable", "input", "inputlineno", "insert", "insertpenalties", "interactionmode", "interlinepenalties", "interlinepenalty", "jobname", "kern", "language", "lastbox", "lastkern", "lastlinefit", "lastnodetype", "lastpenalty", "lastskip", "latelua", "lccode", "leaders", "left", "leftghost", "lefthyphenmin", "leftmarginkern", "leftskip", "leqno", "let", "letterspacefont", "limits", "linepenalty", "lineskip", "lineskiplimit", "localbrokenpenalty", "localinterlinepenalty", "localleftbox", "localrightbox", "long", "looseness", "lower", "lowercase", "lpcode", "luaescapestring", "luastartup", "luatexdatestamp", "luatexrevision", "luatexversion", "mag", "mark", "marks", "mathaccent", "mathbin", "mathchar", "mathchardef", "mathchoice", "mathclose", "mathcode", "mathdir", "mathinner", "mathop", "mathopen", "mathord", "mathpunct", "mathrel", "mathstyle", "mathsurround", "maxdeadcycles", "maxdepth", "meaning", "medmuskip", "message", "middle", "mkern", "month", "moveleft", "moveright", "mskip", "muexpr", "multiply", "muskip", "muskipdef", "mutoglue", "newlinechar", "noalign", "noboundary", "noexpand", "noindent", "nokerns", "noligs", "nolimits", "nolocaldirs", "nolocalwhatsits", "nonscript", "nonstopmode", "nulldelimiterspace", "nullfont", "number", "numexpr", "odelcode", "odelimiter", "omathaccent", "omathchar", "omathchardef", "omathcode", "omit", "openin", "openout", "or", "oradical", "outer", "output", "outputbox", "outputpenalty", "over", "overfullrule", "overline", "overwithdelims", "pagebottomoffset", "pagedepth", "pagedir", "pagediscards", "pagefilllstretch", "pagefillstretch", "pagefilstretch", "pagegoal", "pageheight", "pageleftoffset", "pagerightoffset", "pageshrink", "pagestretch", "pagetopoffset", "pagetotal", "pagewidth", "par", "pardir", "parfillskip", "parindent", "parshape", "parshapedimen", "parshapeindent", "parshapelength", "parskip", "patterns", "pausing", "pdfadjustspacing", "pdfannot", "pdfcatalog", "pdfcolorstack", "pdfcolorstackinit", "pdfcompresslevel", "pdfcopyfont", "pdfcreationdate", "pdfdecimaldigits", "pdfdest", "pdfdestmargin", "pdfdraftmode", "pdfeachlinedepth", "pdfeachlineheight", "pdfendlink", "pdfendthread", "pdffirstlineheight", "pdffontattr", "pdffontexpand", "pdffontname", "pdffontobjnum", "pdffontsize", "pdfgamma", "pdfgentounicode", "pdfglyphtounicode", "pdfhorigin", "pdfignoreddimen", "pdfimageapplygamma", "pdfimagegamma", "pdfimagehicolor", "pdfimageresolution", "pdfincludechars", "pdfinclusioncopyfonts", "pdfinclusionerrorlevel", "pdfinfo", "pdfinsertht", "pdflastannot", "pdflastlinedepth", "pdflastlink", "pdflastobj", "pdflastxform", "pdflastximage", "pdflastximagecolordepth", "pdflastximagepages", "pdflastxpos", "pdflastypos", "pdflinkmargin", "pdfliteral", "pdfmapfile", "pdfmapline", "pdfminorversion", "pdfnames", "pdfnoligatures", "pdfnormaldeviate", "pdfobj", "pdfobjcompresslevel", "pdfoptionpdfminorversion", "pdfoutline", "pdfoutput", "pdfpageattr", "pdfpagebox", "pdfpageheight", "pdfpageref", "pdfpageresources", "pdfpagesattr", "pdfpagewidth", "pdfpkmode", "pdfpkresolution", "pdfprimitive", "pdfprotrudechars", "pdfpxdimen", "pdfrandomseed", "pdfrefobj", "pdfrefxform", "pdfrefximage", "pdfreplacefont", "pdfrestore", "pdfretval", "pdfsave", "pdfsavepos", "pdfsetmatrix", "pdfsetrandomseed", "pdfstartlink", "pdfstartthread", "pdftexbanner", "pdftexrevision", "pdftexversion", "pdfthread", "pdfthreadmargin", "pdftracingfonts", "pdftrailer", "pdfuniformdeviate", "pdfuniqueresname", "pdfvorigin", "pdfxform", "pdfxformattr", "pdfxformname", "pdfxformresources", "pdfximage", "pdfximagebbox", "penalty", "postdisplaypenalty", "postexhyphenchar", "posthyphenchar", "predisplaydirection", "predisplaypenalty", "predisplaysize", "preexhyphenchar", "prehyphenchar", "pretolerance", "prevdepth", "prevgraf", "primitive", "protected", "quitvmode", "radical", "raise", "read", "readline", "relax", "relpenalty", "right", "rightghost", "righthyphenmin", "rightmarginkern", "rightskip", "romannumeral", "rpcode", "savecatcodetable", "savinghyphcodes", "savingvdiscards", "scantextokens", "scantokens", "scriptfont", "scriptscriptfont", "scriptscriptstyle", "scriptspace", "scriptstyle", "scrollmode", "setbox", "setlanguage", "sfcode", "shipout", "show", "showbox", "showboxbreadth", "showboxdepth", "showgroups", "showifs", "showlists", "showthe", "showtokens", "skewchar", "skip", "skipdef", "spacefactor", "spaceskip", "span", "special", "splitbotmark", "splitbotmarks", "splitdiscards", "splitfirstmark", "splitfirstmarks", "splitmaxdepth", "splittopskip", "string", "suppressfontnotfounderror", "suppressifcsnameerror", "suppresslongerror", "suppressoutererror", "synctex", "tabskip", "tagcode", "textdir", "textfont", "textstyle", "the", "thickmuskip", "thinmuskip", "time", "toks", "toksdef", "tolerance", "topmark", "topmarks", "topskip", "tracingassigns", "tracingcommands", "tracinggroups", "tracingifs", "tracinglostchars", "tracingmacros", "tracingnesting", "tracingonline", "tracingoutput", "tracingpages", "tracingparagraphs", "tracingrestores", "tracingscantokens", "tracingstats", "uccode", "uchyph", "underline", "unexpanded", "unhbox", "unhcopy", "unkern", "unless", "unpenalty", "unskip", "unvbox", "unvcopy", "uppercase", "vadjust", "valign", "vbadness", "vbox", "vcenter", "vfil", "vfill", "vfilneg", "vfuzz", "voffset", "vrule", "vsize", "vskip", "vsplit", "vss", "vtop", "wd", "widowpenalties", "widowpenalty", "write", "xdef", "xleaders", "xspaceskip", "year" },
+ ["xetex"]={ "XeTeXversion" },
+} \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-cld.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-cld.lua
new file mode 100644
index 00000000000..4aa2901d232
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-cld.lua
@@ -0,0 +1,23 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for cld",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local lexer = lexer
+local token = lexer.token
+
+local cldlexer = { _NAME = "cld", _FILENAME = "scite-context-lexer-cld" }
+local whitespace = lexer.WHITESPACE -- maybe we need to fix this
+local context = lexer.context
+
+local lualexer = lexer.load('scite-context-lexer-lua')
+
+cldlexer._rules = lualexer._rules_cld
+cldlexer._tokenstyles = lualexer._tokenstyles
+cldlexer._foldsymbols = lualexer._foldsymbols
+cldlexer._directives = lualexer._directives
+
+return cldlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua-longstring.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua-longstring.lua
new file mode 100644
index 00000000000..26bdb8dbccb
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua-longstring.lua
@@ -0,0 +1,22 @@
+local lexer = lexer
+local token = lexer.token
+local P = lpeg.P
+
+local stringlexer = { _NAME = "lua-longstring", _FILENAME = "scite-context-lexer-lua-longstring" }
+local whitespace = lexer.WHITESPACE
+local context = lexer.context
+
+local space = lexer.space
+local nospace = 1 - space
+
+local p_spaces = token(whitespace, space ^1)
+local p_string = token("string", nospace^1)
+
+stringlexer._rules = {
+ { "whitespace", p_spaces },
+ { "string", p_string },
+}
+
+stringlexer._tokenstyles = lexer.context.styleset
+
+return stringlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua.lua
new file mode 100644
index 00000000000..0ace7afc6ff
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-lua.lua
@@ -0,0 +1,264 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local lexer = lexer
+local token, style, colors, exact_match, no_style = lexer.token, lexer.style, lexer.colors, lexer.exact_match, lexer.style_nothing
+local P, R, S, C, Cg, Cb, Cs, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cg, lpeg.Cb, lpeg.Cs, lpeg.Cmt
+local match, find = string.match, string.find
+local setmetatable = setmetatable
+
+-- beware: all multiline is messy, so even if it's no lexer, it should be an embedded lexer
+-- we probably could use a local whitespace variant but this is cleaner
+
+local lualexer = { _NAME = "lua", _FILENAME = "scite-context-lexer-lua" }
+local whitespace = lexer.WHITESPACE
+local context = lexer.context
+
+local stringlexer = lexer.load("scite-context-lexer-lua-longstring")
+
+local directives = { } -- communication channel
+
+-- this will be extended
+
+local keywords = {
+ 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', -- 'goto',
+ 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true',
+ 'until', 'while',
+}
+
+local functions = {
+ 'assert', 'collectgarbage', 'dofile', 'error', 'getfenv', 'getmetatable',
+ 'ipairs', 'load', 'loadfile', 'loadstring', 'module', 'next', 'pairs',
+ 'pcall', 'print', 'rawequal', 'rawget', 'rawset', 'require', 'setfenv',
+ 'setmetatable', 'tonumber', 'tostring', 'type', 'unpack', 'xpcall', "select",
+}
+
+local constants = {
+ '_G', '_VERSION', '_M', "...",
+}
+
+local depricated = {
+ "arg", "arg.n",
+}
+
+local csnames = { -- todo: option
+ "context",
+ "metafun",
+ "metapost",
+}
+
+local level = nil
+local setlevel = function(_,i,s) level = s return i end
+
+local equals = P("=")^0
+
+local longonestart = P("[[")
+local longonestop = P("]]")
+local longonestring = (1-longonestop)^0
+
+local longtwostart = P('[') * Cmt(equals,setlevel) * P('[')
+local longtwostop = P(']') * equals * P(']')
+
+local sentinels = { } setmetatable(sentinels, { __index = function(t,k) local v = "]" .. k .. "]" t[k] = v return v end })
+
+local longtwostring = P(function(input,index)
+ if level then
+ -- local sentinel = ']' .. level .. ']'
+ local sentinel = sentinels[level]
+ local _, stop = find(input,sentinel,index,true)
+ return stop and stop + 1 - #sentinel or #input + 1
+ end
+end)
+
+ local longtwostring_body = longtwostring
+
+ local longtwostring_end = P(function(input,index)
+ if level then
+ -- local sentinel = ']' .. level .. ']'
+ local sentinel = sentinels[level]
+ local _, stop = find(input,sentinel,index,true)
+ return stop and stop + 1 or #input + 1
+ end
+ end)
+
+local longcomment = Cmt(#('[[' + ('[' * C(equals) * '[')), function(input,index,level)
+ -- local sentinel = ']' .. level .. ']'
+ local sentinel = sentinels[level]
+ local _, stop = find(input,sentinel,index,true)
+ return stop and stop + 1 or #input + 1
+end)
+
+local space = lexer.space -- S(" \n\r\t\f\v")
+local any = lexer.any
+
+local squote = P("'")
+local dquote = P('"')
+local escaped = P("\\") * P(1)
+local dashes = P('--')
+
+local spacing = token(whitespace, space^1)
+local rest = token("default", any)
+
+local shortcomment = token("comment", dashes * lexer.nonnewline^0)
+local longcomment = token("comment", dashes * longcomment)
+
+-- fails on very long string with \ at end of lines (needs embedded lexer)
+-- and also on newline before " but it makes no sense to waste time on it
+
+local shortstring = token("quote", dquote)
+ * token("string", (escaped + (1-dquote))^0)
+ * token("quote", dquote)
+ + token("quote", squote)
+ * token("string", (escaped + (1-squote))^0)
+ * token("quote", squote)
+
+----- longstring = token("quote", longonestart)
+----- * token("string", longonestring)
+----- * token("quote", longonestop)
+----- + token("quote", longtwostart)
+----- * token("string", longtwostring)
+----- * token("quote", longtwostop)
+
+local string = shortstring
+----- + longstring
+
+lexer.embed_lexer(lualexer, stringlexer, token("quote",longtwostart), token("string",longtwostring_body) * token("quote",longtwostring_end))
+
+local integer = P("-")^-1 * (lexer.hex_num + lexer.dec_num)
+local number = token("number", lexer.float + integer)
+
+-- officially 127-255 are ok but not utf so useless
+
+local validword = R("AZ","az","__") * R("AZ","az","__","09")^0
+
+local identifier = token("default",validword)
+
+----- operator = token("special", P('..') + P('~=') + S('+-*/%^#=<>;:,.{}[]()')) -- maybe split off {}[]()
+----- operator = token("special", S('+-*/%^#=<>;:,{}[]()') + P('..') + P('.') + P('~=') ) -- maybe split off {}[]()
+local operator = token("special", S('+-*/%^#=<>;:,{}[]().') + P('~=') ) -- no ^1 because of nested lexers
+
+local structure = token("special", S('{}[]()'))
+
+local optionalspace = spacing^0
+local hasargument = #S("{(")
+
+local gotokeyword = token("keyword", P("goto"))
+ * spacing
+ * token("grouping",validword)
+local gotolabel = token("keyword", P("::"))
+ * token("grouping",validword)
+ * token("keyword", P("::"))
+
+local keyword = token("keyword", exact_match(keywords ))
+local builtin = token("plain", exact_match(functions))
+local constant = token("data", exact_match(constants))
+local csname = token("user", exact_match(csnames ))
+ * (
+ optionalspace * hasargument
+ + ( optionalspace * token("special", P(".")) * optionalspace * token("user", validword) )^1
+ )
+
+lualexer._rules = {
+ { 'whitespace', spacing },
+ { 'keyword', keyword },
+ -- { 'structure', structure },
+ { 'function', builtin },
+ { 'csname', csname },
+ { 'constant', constant },
+ { 'goto', gotokeyword },
+ { 'identifier', identifier },
+ { 'string', string },
+ { 'number', number },
+ { 'longcomment', longcomment },
+ { 'shortcomment', shortcomment },
+-- { 'number', number },
+ { 'label', gotolabel },
+ { 'operator', operator },
+ { 'rest', rest },
+}
+
+lualexer._tokenstyles = context.styleset
+
+lualexer._foldsymbols = {
+ _patterns = {
+ -- '%l+', -- costly
+ -- '%l%l+',
+ '[a-z][a-z]+',
+ -- '[%({%)}%[%]]',
+ '[{}%[%]]',
+ },
+ ['keyword'] = { -- challenge: if=0 then=1 else=-1 elseif=-1
+ ['if'] = 1,
+ ['end'] = -1,
+ ['do'] = 1,
+ ['function'] = 1,
+ ['repeat'] = 1,
+ ['until'] = -1,
+ },
+ ['comment'] = {
+ ['['] = 1, [']'] = -1,
+ },
+ ['quote'] = { -- to be tested
+ ['['] = 1, [']'] = -1,
+ },
+ ['special'] = {
+ -- ['('] = 1, [')'] = -1,
+ ['{'] = 1, ['}'] = -1,
+ },
+}
+
+-- embedded in tex:
+
+local cstoken = R("az","AZ","\127\255") + S("@!?_")
+local texcsname = P("\\") * cstoken^1
+local commentline = P('%') * (1-S("\n\r"))^0
+
+local texcomment = token('comment', Cmt(commentline, function() return directives.cld_inline end))
+
+local longthreestart = P("\\!!bs")
+local longthreestop = P("\\!!es")
+local longthreestring = (1-longthreestop)^0
+
+local texstring = token("quote", longthreestart)
+ * token("string", longthreestring)
+ * token("quote", longthreestop)
+
+-- local texcommand = token("user", texcsname)
+local texcommand = token("warning", texcsname)
+
+-- local texstring = token("quote", longthreestart)
+-- * (texcommand + token("string",P(1-texcommand-longthreestop)^1) - longthreestop)^0 -- we match long non-\cs sequences
+-- * token("quote", longthreestop)
+
+-- local whitespace = "whitespace"
+-- local spacing = token(whitespace, space^1)
+
+lualexer._directives = directives
+
+lualexer._rules_cld = {
+ { 'whitespace', spacing },
+ { 'texstring', texstring },
+ { 'texcomment', texcomment },
+ { 'texcommand', texcommand },
+ -- { 'structure', structure },
+ { 'keyword', keyword },
+ { 'function', builtin },
+ { 'csname', csname },
+ { 'constant', constant },
+ { 'identifier', identifier },
+ { 'string', string },
+ { 'longcomment', longcomment },
+ { 'shortcomment', shortcomment }, -- should not be used inline so best signal it as comment (otherwise complex state till end of inline)
+ { 'number', number },
+ { 'operator', operator },
+ { 'rest', rest },
+}
+
+return lualexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-mps.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-mps.lua
new file mode 100644
index 00000000000..e6987f6c64c
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-mps.lua
@@ -0,0 +1,142 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for metafun",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local lexer = lexer
+local global, string, table, lpeg = _G, string, table, lpeg
+local token, exact_match = lexer.token, lexer.exact_match
+local P, R, S, V, C, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cmt
+local type = type
+
+local metafunlexer = { _NAME = "mps", _FILENAME = "scite-context-lexer-mps" }
+local whitespace = lexer.WHITESPACE
+local context = lexer.context
+
+local metapostprimitives = { }
+local metapostinternals = { }
+local metapostshortcuts = { }
+local metapostcommands = { }
+
+local metafuninternals = { }
+local metafunshortcuts = { }
+local metafuncommands = { }
+
+local mergedshortcuts = { }
+local mergedinternals = { }
+
+do
+
+ local definitions = context.loaddefinitions("scite-context-data-metapost")
+
+ if definitions then
+ metapostprimitives = definitions.primitives or { }
+ metapostinternals = definitions.internals or { }
+ metapostshortcuts = definitions.shortcuts or { }
+ metapostcommands = definitions.commands or { }
+ end
+
+ local definitions = context.loaddefinitions("scite-context-data-metafun")
+
+ if definitions then
+ metafuninternals = definitions.internals or { }
+ metafunshortcuts = definitions.shortcuts or { }
+ metafuncommands = definitions.commands or { }
+ end
+
+ for i=1,#metapostshortcuts do
+ mergedshortcuts[#mergedshortcuts+1] = metapostshortcuts[i]
+ end
+ for i=1,#metafunshortcuts do
+ mergedshortcuts[#mergedshortcuts+1] = metafunshortcuts[i]
+ end
+
+ for i=1,#metapostinternals do
+ mergedinternals[#mergedinternals+1] = metapostinternals[i]
+ end
+ for i=1,#metafuninternals do
+ mergedinternals[#mergedinternals+1] = metafuninternals[i]
+ end
+
+end
+
+local space = lexer.space -- S(" \n\r\t\f\v")
+local any = lexer.any
+
+local dquote = P('"')
+local cstoken = R("az","AZ") + P("_")
+local number = context.patterns.real
+
+local cstokentex = R("az","AZ","\127\255") + S("@!?_")
+
+-- we could collapse as in tex
+
+local spacing = token(whitespace, space^1)
+local rest = token('default', any)
+local comment = token('comment', P('%') * (1-S("\n\r"))^0)
+local internal = token('reserved', exact_match(mergedshortcuts,false))
+local shortcut = token('data', exact_match(mergedinternals))
+local helper = token('command', exact_match(metafuncommands))
+local plain = token('plain', exact_match(metapostcommands))
+local quoted = token('quote', dquote)
+ * token('string', P(1-dquote)^0)
+ * token('quote', dquote)
+local texstuff = token('quote', P("btex ") + P("verbatimtex "))
+ * token('string', P(1-P(" etex"))^0)
+ * token('quote', P(" etex"))
+local primitive = token('primitive', exact_match(metapostprimitives))
+local identifier = token('default', cstoken^1)
+local number = token('number', number)
+local grouping = token('grouping', S("()[]{}")) -- can be an option
+local special = token('special', S("#()[]{}<>=:\"")) -- or else := <> etc split
+local texlike = token('string', P("\\") * cstokentex^1)
+local extra = token('extra', S("`~%^&_-+*/\'|\\"))
+
+metafunlexer._rules = {
+ { 'whitespace', spacing },
+ { 'comment', comment },
+ { 'internal', internal },
+ { 'shortcut', shortcut },
+ { 'helper', helper },
+ { 'plain', plain },
+ { 'primitive', primitive },
+ { 'texstuff', texstuff },
+ { 'identifier', identifier },
+ { 'number', number },
+ { 'quoted', quoted },
+ -- { 'grouping', grouping }, -- can be an option
+ { 'special', special },
+ -- { 'texlike', texlike },
+ { 'extra', extra },
+ { 'rest', rest },
+}
+
+metafunlexer._tokenstyles = context.styleset
+
+metafunlexer._foldsymbols = {
+ _patterns = {
+ "%l+",
+ },
+ ["primitive"] = {
+ ["beginfig"] = 1,
+ ["endfig"] = -1,
+ ["def"] = 1,
+ ["vardef"] = 1,
+ ["primarydef"] = 1,
+ ["secondarydef" ] = 1,
+ ["tertiarydef"] = 1,
+ ["enddef"] = -1,
+ ["if"] = 1,
+ ["fi"] = -1,
+ ["for"] = 1,
+ ["forever"] = 1,
+ ["endfor"] = -1,
+ }
+}
+
+return metafunlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf-object.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf-object.lua
new file mode 100644
index 00000000000..6d0b6d8da8e
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf-object.lua
@@ -0,0 +1,117 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for pdf",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local lexer = lexer
+local token = lexer.token
+local P, R, S, C, V = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.V
+
+local pdfobjectlexer = { _NAME = "pdf-object", _FILENAME = "scite-context-lexer-pdf-object" }
+local whitespace = lexer.WHITESPACE -- triggers states
+local context = lexer.context
+local patterns = context.patterns
+
+local space = lexer.space
+local somespace = space^1
+
+local newline = S("\n\r")
+local real = patterns.real
+local cardinal = patterns.cardinal
+
+local lparent = P("(")
+local rparent = P(")")
+local langle = P("<")
+local rangle = P(">")
+local escape = P("\\")
+local anything = P(1)
+local unicodetrigger = P("feff")
+
+local nametoken = 1 - space - S("<>/[]()")
+local name = P("/") * nametoken^1
+
+local p_string = P { ( escape * anything + lparent * V(1) * rparent + (1 - rparent) )^0 }
+
+local t_spacing = token(whitespace, space^1)
+local t_spaces = token(whitespace, space^1)^0
+
+local p_stream = P("stream")
+local p_endstream = P("endstream")
+----- p_obj = P("obj")
+local p_endobj = P("endobj")
+local p_reference = P("R")
+
+local p_objectnumber = patterns.cardinal
+local p_comment = P('%') * (1-S("\n\r"))^0
+
+local string = token("quote", lparent)
+ * token("string", p_string)
+ * token("quote", rparent)
+local unicode = token("quote", langle)
+ * token("plain", unicodetrigger)
+ * token("string", (1-rangle)^1)
+ * token("quote", rangle)
+local whatsit = token("quote", langle)
+ * token("string", (1-rangle)^1)
+ * token("quote", rangle)
+local keyword = token("command", name)
+local constant = token("constant", name)
+local number = token('number', real)
+-- local reference = token("number", cardinal)
+-- * t_spacing
+-- * token("number", cardinal)
+local reserved = token("number", P("true") + P("false") + P("NULL"))
+local reference = token("warning", cardinal)
+ * t_spacing
+ * token("warning", cardinal)
+ * t_spacing
+ * token("keyword", p_reference)
+local t_comment = token("comment", p_comment)
+
+-- t_openobject = token("number", p_objectnumber)
+-- * t_spacing
+-- * token("number", p_objectnumber)
+-- * t_spacing
+-- * token("keyword", p_obj)
+local t_closeobject = token("keyword", p_endobj)
+
+local t_opendictionary = token("grouping", P("<<"))
+local t_closedictionary = token("grouping", P(">>"))
+
+local t_openarray = token("grouping", P("["))
+local t_closearray = token("grouping", P("]"))
+
+local t_stream = token("keyword", p_stream)
+-- * token("default", newline * (1-newline*p_endstream*newline)^1 * newline)
+ * token("default", (1 - p_endstream)^1)
+ * token("keyword", p_endstream)
+
+local t_dictionary = { "dictionary",
+ dictionary = t_opendictionary * (t_spaces * keyword * t_spaces * V("whatever"))^0 * t_spaces * t_closedictionary,
+ array = t_openarray * (t_spaces * V("whatever"))^0 * t_spaces * t_closearray,
+ whatever = V("dictionary") + V("array") + constant + reference + string + unicode + number + whatsit,
+ }
+
+local t_object = { "object", -- weird that we need to catch the end here (probably otherwise an invalid lpeg)
+ object = t_spaces * (V("dictionary") * t_spaces * t_stream^-1 + V("array") + V("number") + t_spaces) * t_spaces * t_closeobject,
+ dictionary = t_opendictionary * (t_spaces * keyword * t_spaces * V("whatever"))^0 * t_spaces * t_closedictionary,
+ array = t_openarray * (t_spaces * V("whatever"))^0 * t_spaces * t_closearray,
+ number = number,
+ whatever = V("dictionary") + V("array") + constant + reference + string + unicode + number + reserved + whatsit,
+ }
+
+pdfobjectlexer._shared = {
+ dictionary = t_dictionary,
+}
+
+pdfobjectlexer._rules = {
+ { 'whitespace', t_spacing },
+ { 'object', t_object },
+}
+
+pdfobjectlexer._tokenstyles = context.styleset
+
+return pdfobjectlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf-xref.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf-xref.lua
new file mode 100644
index 00000000000..f205e913053
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf-xref.lua
@@ -0,0 +1,51 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for pdf xref",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local lexer = lexer
+local token = lexer.token
+local P, R = lpeg.P, lpeg.R
+
+-- xref
+-- cardinal cardinal [character]
+-- ..
+-- %%EOF | startxref | trailer
+
+local pdfxreflexer = { _NAME = "pdf-xref", _FILENAME = "scite-context-lexer-pdf-xref" }
+local whitespace = lexer.WHITESPACE -- triggers states
+local context = lexer.context
+local patterns = context.patterns
+
+local pdfobjectlexer = lexer.load("scite-context-lexer-pdf-object")
+
+local spacing = patterns.spacing
+
+local t_spacing = token(whitespace, spacing)
+
+local p_trailer = P("trailer")
+
+local t_number = token("number", R("09")^1)
+ * t_spacing
+ * token("number", R("09")^1)
+ * t_spacing
+ * (token("keyword", R("az","AZ")) * t_spacing)^-1
+
+local t_xref = t_number^1
+
+-- local t_xref = token("default", (1-p_trailer)^1)
+-- * token("keyword", p_trailer)
+-- * t_spacing
+-- * pdfobjectlexer._shared.dictionary
+
+pdfxreflexer._rules = {
+ { 'whitespace', t_spacing },
+ { 'xref', t_xref },
+}
+
+pdfxreflexer._tokenstyles = context.styleset
+
+return pdfxreflexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf.lua
new file mode 100644
index 00000000000..685fdb16e71
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-pdf.lua
@@ -0,0 +1,80 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for pdf",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local lexer = lexer
+local token = lexer.token
+local P, R, S = lpeg.P, lpeg.R, lpeg.S
+
+local pdflexer = { _NAME = "pdf", _FILENAME = "scite-context-lexer-pdf" }
+local whitespace = lexer.WHITESPACE -- triggers states
+
+local pdfobjectlexer = lexer.load("scite-context-lexer-pdf-object")
+local pdfxreflexer = lexer.load("scite-context-lexer-pdf-xref")
+
+local context = lexer.context
+local patterns = context.patterns
+
+local space = patterns.space
+local spacing = patterns.spacing
+local nospacing = patterns.nospacing
+local anything = patterns.anything
+local restofline = patterns.restofline
+
+local t_spacing = token(whitespace, spacing)
+local t_rest = token("default", nospacing) -- anything
+
+local p_obj = P("obj")
+local p_endobj = P("endobj")
+local p_xref = P("xref")
+local p_startxref = P("startxref")
+local p_eof = P("%%EOF")
+local p_trailer = P("trailer")
+
+local p_objectnumber = patterns.cardinal
+local p_comment = P('%') * restofline
+
+local t_comment = token("comment", p_comment)
+local t_openobject = token("warning", p_objectnumber)
+ * t_spacing
+ * token("warning", p_objectnumber)
+ * t_spacing
+ * token("keyword", p_obj)
+ * t_spacing^0
+local t_closeobject = token("keyword", p_endobj)
+
+-- We could do clever xref parsing but why should we (i.e. we should check for
+-- the xref body. As a pdf file is not edited, we could do without a nested
+-- lexer anyway.
+
+local t_trailer = token("keyword", p_trailer)
+ * t_spacing
+ * pdfobjectlexer._shared.dictionary
+
+local t_openxref = token("plain", p_xref)
+local t_closexref = token("plain", p_startxref)
+ + token("comment", p_eof)
+ + t_trailer
+local t_startxref = token("plain", p_startxref)
+ * t_spacing
+ * token("number", R("09")^1)
+
+lexer.embed_lexer(pdflexer, pdfobjectlexer, t_openobject, t_closeobject)
+lexer.embed_lexer(pdflexer, pdfxreflexer, t_openxref, t_closexref)
+
+pdflexer._rules = {
+ { 'whitespace', t_spacing },
+ { 'comment', t_comment },
+ { 'xref', t_startxref },
+ { 'rest', t_rest },
+}
+
+pdflexer._tokenstyles = context.styleset
+
+return pdflexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-tex.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-tex.lua
new file mode 100644
index 00000000000..68b67488e6f
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-tex.lua
@@ -0,0 +1,464 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for context",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- maybe: _LINEBYLINE variant for large files (no nesting)
+-- maybe: protected_macros
+
+--[[
+
+ experiment dd 2009/10/28 .. todo:
+
+ -- figure out if tabs instead of splits are possible
+ -- locate an option to enter name in file dialogue (like windows permits)
+ -- figure out why loading a file fails
+ -- we cannot print to the log pane
+ -- we cannot access props["keywordclass.macros.context.en"]
+ -- lexer.get_property only handles integers
+ -- we cannot run a command to get the location of mult-def.lua
+
+ -- local interface = props["keywordclass.macros.context.en"]
+ -- local interface = lexer.get_property("keywordclass.macros.context.en","")
+
+ -- it seems that whitespace triggers the lexer when embedding happens, but this
+ -- is quite fragile due to duplicate styles .. lexer.WHITESPACE is a number
+ -- (initially) ... _NAME vs filename (but we don't want to overwrite files)
+
+ -- this lexer does not care about other macro packages (one can of course add a fake
+ -- interface but it's not on the agenda)
+
+]]--
+
+if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local lexer = lexer
+local global, string, table, lpeg = _G, string, table, lpeg
+local token, exact_match = lexer.token, lexer.exact_match
+local P, R, S, V, C, Cmt, Cp, Cc, Ct = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cmt, lpeg.Cp, lpeg.Cc, lpeg.Ct
+local type, next = type, next
+local find, match, lower, upper = string.find, string.match, string.lower, string.upper
+
+-- module(...)
+
+local contextlexer = { _NAME = "tex", _FILENAME = "scite-context-lexer-tex" }
+local whitespace = lexer.WHITESPACE
+local context = lexer.context
+
+local cldlexer = lexer.load('scite-context-lexer-cld')
+----- cldlexer = lexer.load('scite-context-lexer-lua')
+local mpslexer = lexer.load('scite-context-lexer-mps')
+
+local commands = { en = { } }
+local primitives = { }
+local helpers = { }
+local constants = { }
+
+do -- todo: only once, store in global
+
+ local definitions = context.loaddefinitions("scite-context-data-interfaces")
+
+ if definitions then
+ for interface, list in next, definitions do
+ local c = { }
+ for i=1,#list do
+ c[list[i]] = true
+ end
+ if interface ~= "en" then
+ list = definitions.en
+ if list then
+ for i=1,#list do
+ c[list[i]] = true
+ end
+ end
+ end
+ commands[interface] = c
+ end
+ end
+
+ local definitions = context.loaddefinitions("scite-context-data-context")
+
+ if definitions then
+ helpers = definitions.helpers or { }
+ constants = definitions.constants or { }
+ end
+
+ local definitions = context.loaddefinitions("scite-context-data-tex")
+
+ if definitions then
+ local function add(data,normal)
+ for k, v in next, data do
+ if v ~= "/" and v ~= "-" then
+ primitives[#primitives+1] = v
+ if normal then
+ primitives[#primitives+1] = "normal" .. v
+ end
+ end
+ end
+ end
+ add(definitions.tex,true)
+ add(definitions.etex)
+ add(definitions.pdftex)
+ add(definitions.aleph)
+ add(definitions.omega)
+ add(definitions.luatex)
+ add(definitions.xetex)
+ end
+
+end
+
+local currentcommands = commands.en or { }
+
+local cstoken = R("az","AZ","\127\255") + S("@!?_")
+
+local knowncommand = Cmt(cstoken^1, function(_,i,s)
+ return currentcommands[s] and i
+end)
+
+local utfchar = context.utfchar
+local wordtoken = context.patterns.wordtoken
+local iwordtoken = context.patterns.iwordtoken
+local wordpattern = context.patterns.wordpattern
+local iwordpattern = context.patterns.iwordpattern
+local invisibles = context.patterns.invisibles
+local checkedword = context.checkedword
+local styleofword = context.styleofword
+local setwordlist = context.setwordlist
+local validwords = false
+
+-- % language=uk
+
+local knownpreamble = Cmt(#P("% "), function(input,i,_) -- todo : utfbomb
+ if i < 10 then
+ validwords = false
+ local s, e, word = find(input,'^(.+)[\n\r]',i) -- combine with match
+ if word then
+ local interface = match(word,"interface=([a-z]+)")
+ if interface then
+ currentcommands = commands[interface] or commands.en or { }
+ end
+ local language = match(word,"language=([a-z]+)")
+ validwords = language and setwordlist(language)
+ end
+ end
+ return false
+end)
+
+-- -- the token list contains { "style", endpos } entries
+-- --
+-- -- in principle this is faster but it is also crash sensitive for large files
+
+-- local constants_hash = { } for i=1,#constants do constants_hash [constants [i]] = true end
+-- local helpers_hash = { } for i=1,#helpers do helpers_hash [helpers [i]] = true end
+-- local primitives_hash = { } for i=1,#primitives do primitives_hash[primitives[i]] = true end
+
+-- local specialword = Ct( P('\\') * Cmt( C(cstoken^1), function(input,i,s)
+-- if currentcommands[s] then
+-- return true, "command", i
+-- elseif constants_hash[s] then
+-- return true, "data", i
+-- elseif helpers_hash[s] then
+-- return true, "plain", i
+-- elseif primitives_hash[s] then
+-- return true, "primitive", i
+-- else -- if starts with if then primitive
+-- return true, "user", i
+-- end
+-- end) )
+
+-- local specialword = P('\\') * Cmt( C(cstoken^1), function(input,i,s)
+-- if currentcommands[s] then
+-- return true, { "command", i }
+-- elseif constants_hash[s] then
+-- return true, { "data", i }
+-- elseif helpers_hash[s] then
+-- return true, { "plain", i }
+-- elseif primitives_hash[s] then
+-- return true, { "primitive", i }
+-- else -- if starts with if then primitive
+-- return true, { "user", i }
+-- end
+-- end)
+
+-- experiment: keep space with whatever ... less tables
+
+-- 10pt
+
+local commentline = P('%') * (1-S("\n\r"))^0
+local endline = S("\n\r")^1
+
+local space = lexer.space -- S(" \n\r\t\f\v")
+local any = lexer.any
+local backslash = P("\\")
+local hspace = S(" \t")
+
+local p_spacing = space^1
+local p_rest = any
+
+local p_preamble = knownpreamble
+local p_comment = commentline
+local p_command = backslash * knowncommand
+local p_constant = backslash * exact_match(constants)
+local p_helper = backslash * exact_match(helpers)
+local p_primitive = backslash * exact_match(primitives)
+local p_ifprimitive = P('\\if') * cstoken^1
+local p_csname = backslash * (cstoken^1 + P(1))
+local p_grouping = S("{$}")
+local p_special = S("#()[]<>=\"")
+local p_extra = S("`~%^&_-+/\'|")
+local p_text = iwordtoken^1 --maybe add punctuation and space
+
+local p_reserved = backslash * (
+ P("??") + R("az") * P("!")
+ ) * cstoken^1
+
+local p_number = context.patterns.real
+local p_unit = P("pt") + P("bp") + P("sp") + P("mm") + P("cm") + P("cc") + P("dd")
+
+-- no looking back = #(1-S("[=")) * cstoken^3 * #(1-S("=]"))
+
+-- This one gives stack overflows:
+--
+-- local p_word = Cmt(iwordpattern, function(_,i,s)
+-- if validwords then
+-- return checkedword(validwords,s,i)
+-- else
+-- return true, { "text", i }
+-- end
+-- end)
+--
+-- So we use this one instead:
+
+local p_word = Ct( iwordpattern / function(s) return styleofword(validwords,s) end * Cp() ) -- the function can be inlined
+
+----- p_text = (1 - p_grouping - p_special - p_extra - backslash - space + hspace)^1
+
+-- keep key pressed at end-of syst-aux.mkiv:
+--
+-- 0 : 15 sec
+-- 1 : 13 sec
+-- 2 : 10 sec
+--
+-- the problem is that quite some style subtables get generated so collapsing ranges helps
+
+local option = 1
+
+if option == 1 then
+
+ p_comment = p_comment^1
+ p_grouping = p_grouping^1
+ p_special = p_special^1
+ p_extra = p_extra^1
+
+ p_command = p_command^1
+ p_constant = p_constant^1
+ p_helper = p_helper^1
+ p_primitive = p_primitive^1
+ p_ifprimitive = p_ifprimitive^1
+ p_reserved = p_reserved^1
+
+elseif option == 2 then
+
+ local included = space^0
+
+ p_comment = (p_comment * included)^1
+ p_grouping = (p_grouping * included)^1
+ p_special = (p_special * included)^1
+ p_extra = (p_extra * included)^1
+
+ p_command = (p_command * included)^1
+ p_constant = (p_constant * included)^1
+ p_helper = (p_helper * included)^1
+ p_primitive = (p_primitive * included)^1
+ p_ifprimitive = (p_ifprimitive * included)^1
+ p_reserved = (p_reserved * included)^1
+
+end
+
+local p_invisible = invisibles^1
+
+local spacing = token(whitespace, p_spacing )
+
+local rest = token('default', p_rest )
+local preamble = token('preamble', p_preamble )
+local comment = token('comment', p_comment )
+local command = token('command', p_command )
+local constant = token('data', p_constant )
+local helper = token('plain', p_helper )
+local primitive = token('primitive', p_primitive )
+local ifprimitive = token('primitive', p_ifprimitive)
+local reserved = token('reserved', p_reserved )
+local csname = token('user', p_csname )
+local grouping = token('grouping', p_grouping )
+local number = token('number', p_number )
+ * token('constant', p_unit )
+local special = token('special', p_special )
+local reserved = token('reserved', p_reserved ) -- reserved internal preproc
+local extra = token('extra', p_extra )
+local invisible = token('invisible', p_invisible )
+local text = token('default', p_text )
+local word = p_word
+
+----- startluacode = token("grouping", P("\\startluacode"))
+----- stopluacode = token("grouping", P("\\stopluacode"))
+
+local luastatus = false
+local luatag = nil
+local lualevel = 0
+
+local function startdisplaylua(_,i,s)
+ luatag = s
+ luastatus = "display"
+ cldlexer._directives.cld_inline = false
+ return true
+end
+
+local function stopdisplaylua(_,i,s)
+ local ok = luatag == s
+ if ok then
+ cldlexer._directives.cld_inline = false
+ luastatus = false
+ end
+ return ok
+end
+
+local function startinlinelua(_,i,s)
+ if luastatus == "display" then
+ return false
+ elseif not luastatus then
+ luastatus = "inline"
+ cldlexer._directives.cld_inline = true
+ lualevel = 1
+ return true
+ else-- if luastatus == "inline" then
+ lualevel = lualevel + 1
+ return true
+ end
+end
+
+local function stopinlinelua_b(_,i,s) -- {
+ if luastatus == "display" then
+ return false
+ elseif luastatus == "inline" then
+ lualevel = lualevel + 1
+ return false
+ else
+ return true
+ end
+end
+
+local function stopinlinelua_e(_,i,s) -- }
+ if luastatus == "display" then
+ return false
+ elseif luastatus == "inline" then
+ lualevel = lualevel - 1
+ local ok = lualevel <= 0 -- was 0
+ if ok then
+ cldlexer._directives.cld_inline = false
+ luastatus = false
+ end
+ return ok
+ else
+ return true
+ end
+end
+
+contextlexer._reset_parser = function()
+ luastatus = false
+ luatag = nil
+ lualevel = 0
+end
+
+local luaenvironment = P("luacode")
+
+local inlinelua = P("\\") * (
+ P("ctx") * ( P("lua") + P("command") + P("late") * (P("lua") + P("command")) )
+ + P("cld") * ( P("command") + P("context") )
+ )
+
+local startlua = P("\\start") * Cmt(luaenvironment,startdisplaylua)
+ + inlinelua * space^0 * Cmt(P("{"),startinlinelua)
+
+local stoplua = P("\\stop") * Cmt(luaenvironment,stopdisplaylua)
+ + Cmt(P("{"),stopinlinelua_b)
+ + Cmt(P("}"),stopinlinelua_e)
+
+local startluacode = token("embedded", startlua)
+local stopluacode = #stoplua * token("embedded", stoplua)
+
+local metafuncall = ( P("use") + P("reusable") + P("unique") ) * ("MPgraphic")
+
+local metafunenvironment = metafuncall -- ( P("use") + P("reusable") + P("unique") ) * ("MPgraphic")
+ + P("MP") * ( P("code")+ P("page") + P("inclusions") + P("initializations") + P("definitions") + P("extensions") + P("graphic") )
+
+local startmetafun = P("\\start") * metafunenvironment
+local stopmetafun = P("\\stop") * metafunenvironment
+
+local openargument = token("special", P("{"))
+local closeargument = token("special", P("}"))
+local argumentcontent = token("default",(1-P("}"))^0) -- maybe space needs a treatment
+
+local metafunarguments = (spacing^0 * openargument * argumentcontent * closeargument)^-2
+
+local startmetafuncode = token("embedded", startmetafun) * metafunarguments
+local stopmetafuncode = token("embedded", stopmetafun)
+
+local callers = token("embedded", P("\\") * metafuncall) * metafunarguments
+
+lexer.embed_lexer(contextlexer, cldlexer, startluacode, stopluacode)
+lexer.embed_lexer(contextlexer, mpslexer, startmetafuncode, stopmetafuncode)
+
+-- Watch the text grabber, after all, we're talking mostly of text (beware,
+-- no punctuation here as it can be special. We might go for utf here.
+
+contextlexer._rules = {
+ { "whitespace", spacing },
+ { "preamble", preamble },
+ { "word", word },
+ { "text", text }, -- non words
+ { "comment", comment },
+ { "constant", constant },
+ { "callers", callers },
+ { "helper", helper },
+ { "command", command },
+ { "primitive", primitive },
+ { "ifprimitive", ifprimitive },
+ { "reserved", reserved },
+ { "csname", csname },
+ -- { "whatever", specialword }, -- not yet, crashes
+ { "grouping", grouping },
+ -- { "number", number },
+ { "special", special },
+ { "extra", extra },
+ { "invisible", invisible },
+ { "rest", rest },
+}
+
+contextlexer._tokenstyles = context.styleset
+-- contextlexer._tokenstyles = context.stylesetcopy() -- experiment
+
+-- contextlexer._tokenstyles[#contextlexer._tokenstyles + 1] = { cldlexer._NAME..'_whitespace', lexer.style_whitespace }
+-- contextlexer._tokenstyles[#contextlexer._tokenstyles + 1] = { mpslexer._NAME..'_whitespace', lexer.style_whitespace }
+
+
+local folds = {
+ ["\\start"] = 1, ["\\stop" ] = -1,
+ ["\\begin"] = 1, ["\\end" ] = -1,
+}
+
+contextlexer._foldsymbols = {
+ _patterns = {
+ "\\start", "\\stop", -- regular environments
+ "\\begin", "\\end", -- (moveable) blocks
+ },
+ ["helper"] = folds,
+ ["data"] = folds,
+ ["command"] = folds,
+ ["user"] = folds, -- csname
+ ["grouping"] = folds,
+}
+
+return contextlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-txt.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-txt.lua
new file mode 100644
index 00000000000..012167aeb4c
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-txt.lua
@@ -0,0 +1,86 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for plain text (with spell checking)",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local lexer = lexer
+local token = lexer.token
+local P, S, Cmt, Cp, Ct = lpeg.P, lpeg.S, lpeg.Cmt, lpeg.Cp, lpeg.Ct
+local find, match = string.find, string.match
+
+local textlexer = { _NAME = "txt", _FILENAME = "scite-context-lexer-txt" }
+local whitespace = lexer.WHITESPACE
+local context = lexer.context
+
+local space = lexer.space
+local any = lexer.any
+
+local wordtoken = context.patterns.wordtoken
+local wordpattern = context.patterns.wordpattern
+local checkedword = context.checkedword
+local styleofword = context.styleofword
+local setwordlist = context.setwordlist
+local validwords = false
+
+-- local styleset = context.newstyleset {
+-- "default",
+-- "text", "okay", "error", "warning",
+-- "preamble",
+-- }
+
+-- [#!-%] language=uk
+
+local p_preamble = Cmt(#(S("#!-%") * P(" ")), function(input,i,_) -- todo: utf bomb
+ if i == 1 then -- < 10 then
+ validwords = false
+ local s, e, line = find(input,'^[#!%-%%](.+)[\n\r]',i)
+ if line then
+ local language = match(line,"language=([a-z]+)")
+ if language then
+ validwords = setwordlist(language)
+ end
+ end
+ end
+ return false
+end)
+
+local t_preamble =
+ token("preamble", p_preamble)
+
+-- local t_word =
+-- Cmt(wordpattern, function(_,i,s)
+-- if validwords then
+-- return checkedword(validwords,s,i)
+-- else
+-- return true, { "text", i }
+-- end
+-- end)
+
+local t_word =
+ Ct( wordpattern / function(s) return styleofword(validwords,s) end * Cp() ) -- the function can be inlined
+
+local t_text =
+ token("default", wordtoken^1)
+
+local t_rest =
+ token("default", (1-wordtoken-space)^1)
+
+local t_spacing =
+ token(whitespace, space^1)
+
+textlexer._rules = {
+ { "whitespace", t_spacing },
+ { "preamble", t_preamble },
+ { "word", t_word }, -- words >= 3
+ { "text", t_text }, -- non words
+ { "rest", t_rest },
+}
+
+textlexer._tokenstyles = context.styleset
+
+return textlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-cdata.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-cdata.lua
new file mode 100644
index 00000000000..97253e14035
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-cdata.lua
@@ -0,0 +1,30 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for xml cdata",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local lexer = lexer
+local token = lexer.token
+local P = lpeg.P
+
+local xmlcdatalexer = { _NAME = "xml-cdata", _FILENAME = "scite-context-lexer-xml-cdata" }
+local whitespace = lexer.WHITESPACE -- triggers states
+local context = lexer.context
+
+local space = lexer.space
+local nospace = 1 - space - P("]]>")
+
+local p_spaces = token(whitespace, space ^1)
+local p_cdata = token("comment", nospace^1)
+
+xmlcdatalexer._rules = {
+ { "whitespace", p_spaces },
+ { "cdata", p_cdata },
+}
+
+xmlcdatalexer._tokenstyles = context.styleset
+
+return xmlcdatalexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-comment.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-comment.lua
new file mode 100644
index 00000000000..eab3b2a61c8
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml-comment.lua
@@ -0,0 +1,39 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for xml comments",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+local lexer = lexer
+local token = lexer.token
+local P = lpeg.P
+
+local xmlcommentlexer = { _NAME = "xml-comment", _FILENAME = "scite-context-lexer-xml-comment" }
+local whitespace = lexer.WHITESPACE
+local context = lexer.context
+
+local space = lexer.space
+local nospace = 1 - space - P("-->")
+
+local p_spaces = token(whitespace, space ^1)
+local p_comment = token("comment", nospace^1)
+
+xmlcommentlexer._rules = {
+ { "whitespace", p_spaces },
+ { "comment", p_comment },
+}
+
+xmlcommentlexer._tokenstyles = context.styleset
+
+xmlcommentlexer._foldsymbols = {
+ _patterns = {
+ "<%!%-%-", "%-%->", -- comments
+ },
+ ["comment"] = {
+ ["<!--"] = 1, ["-->" ] = -1,
+ }
+}
+
+return xmlcommentlexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml.lua
new file mode 100644
index 00000000000..34636127fc7
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer-xml.lua
@@ -0,0 +1,334 @@
+local info = {
+ version = 1.002,
+ comment = "scintilla lpeg lexer for metafun",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- adapted from the regular context pretty printer code (after all, lexing
+-- boils down to much of the same and there are only so many ways to do
+-- things). Simplified a bit as we have a different nesting model.
+
+-- todo: parse entities in attributes
+
+if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local lexer = lexer
+local global, string, table, lpeg = _G, string, table, lpeg
+local token, exact_match = lexer.token, lexer.exact_match
+local P, R, S, V, C, Cmt, Ct, Cp = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cmt, lpeg.Ct, lpeg.Cp
+local type = type
+local match, find = string.match, string.find
+
+local xmllexer = { _NAME = "xml", _FILENAME = "scite-context-lexer-xml" }
+local whitespace = lexer.WHITESPACE -- triggers states
+local context = lexer.context
+
+local xmlcommentlexer = lexer.load("scite-context-lexer-xml-comment") -- indirect (some issue with the lexer framework)
+local xmlcdatalexer = lexer.load("scite-context-lexer-xml-cdata") -- indirect (some issue with the lexer framework)
+
+local space = lexer.space -- S(" \t\n\r\v\f")
+local any = lexer.any -- P(1)
+
+local dquote = P('"')
+local squote = P("'")
+local colon = P(":")
+local semicolon = P(";")
+local equal = P("=")
+local ampersand = P("&")
+
+local name = (R("az","AZ","09") + S('_-.'))^1
+local openbegin = P("<")
+local openend = P("</")
+local closebegin = P("/>") + P(">")
+local closeend = P(">")
+local opencomment = P("<!--")
+local closecomment = P("-->")
+local openinstruction = P("<?")
+local closeinstruction = P("?>")
+local opencdata = P("<![CDATA[")
+local closecdata = P("]]>")
+local opendoctype = P("<!DOCTYPE") -- could grab the whole doctype
+local closedoctype = P("]>") + P(">")
+
+-- <!DOCTYPE Something PUBLIC "... ..." "..." [ ... ] >
+-- <!DOCTYPE Something PUBLIC "... ..." "..." >
+-- <!DOCTYPE Something SYSTEM "... ..." [ ... ] >
+-- <!DOCTYPE Something SYSTEM "... ..." >
+-- <!DOCTYPE Something [ ... ] >
+-- <!DOCTYPE Something >
+
+local entity = ampersand * (1-semicolon)^1 * semicolon
+
+local utfchar = context.utfchar
+local wordtoken = context.patterns.wordtoken
+local iwordtoken = context.patterns.iwordtoken
+local wordpattern = context.patterns.wordpattern
+local iwordpattern = context.patterns.iwordpattern
+local invisibles = context.patterns.invisibles
+local checkedword = context.checkedword
+local styleofword = context.styleofword
+local setwordlist = context.setwordlist
+local validwords = false
+
+
+-- <?xml version="1.0" encoding="UTF-8" language="uk" ?>
+--
+-- <?context-directive editor language us ?>
+
+local p_preamble = Cmt(#P("<?xml "), function(input,i,_) -- todo: utf bomb
+ if i < 200 then
+ validwords = false
+ local language = match(input,"^<%?xml[^>]*%?>%s*<%?context%-directive%s+editor%s+language%s+(..)%s+%?>")
+ -- if not language then
+ -- language = match(input,'^<%?xml[^>]*language=[\"\'](..)[\"\'][^>]*%?>',i)
+ -- end
+ if language then
+ validwords = setwordlist(language)
+ end
+ end
+ return false
+end)
+
+-- local p_word =
+-- Cmt(iwordpattern, function(_,i,s)
+-- if validwords then
+-- return checkedword(validwords,s,i)
+-- else
+-- return true, { "text", i } -- or default
+-- end
+-- end)
+
+local p_word =
+ Ct( iwordpattern / function(s) return styleofword(validwords,s) end * Cp() ) -- the function can be inlined
+
+local p_rest =
+ token("default", any)
+
+local p_text =
+ token("default", (1-S("<>&")-space)^1)
+
+local p_spacing =
+ token(whitespace, space^1)
+-- token("whitespace", space^1)
+
+local p_optionalwhitespace =
+ p_spacing^0
+
+local p_localspacing =
+ token("default", space^1)
+
+-- Because we want a differently colored open and close we need an embedded lexer (whitespace
+-- trigger). What is actually needed is that scintilla applies the current whitespace style.
+-- Even using different style keys is not robust as they can be shared. I'll fix the main
+-- lexer code.
+
+local p_sstring =
+ token("quote",dquote)
+ * token("string",(1-dquote)^0) -- different from context
+ * token("quote",dquote)
+
+local p_dstring =
+ token("quote",squote)
+ * token("string",(1-squote)^0) -- different from context
+ * token("quote",squote)
+
+-- local p_comment =
+-- token("command",opencomment)
+-- * token("comment",(1-closecomment)^0) -- different from context
+-- * token("command",closecomment)
+
+-- local p_cdata =
+-- token("command",opencdata)
+-- * token("comment",(1-closecdata)^0) -- different from context
+-- * token("command",closecdata)
+
+-- maybe cdata just text (then we don't need the extra lexer as we only have one comment then)
+
+-- <!DOCTYPE Something PUBLIC "... ..." "..." [ ... ] >
+-- <!DOCTYPE Something PUBLIC "... ..." "..." >
+-- <!DOCTYPE Something SYSTEM "... ..." [ ... ] >
+-- <!DOCTYPE Something SYSTEM "... ..." >
+-- <!DOCTYPE Something [ ... ] >
+-- <!DOCTYPE Something >
+
+-- <!ENTITY xxxx SYSTEM "yyyy" NDATA zzzz>
+-- <!ENTITY xxxx PUBLIC "yyyy" >
+-- <!ENTITY xxxx "yyyy" >
+
+local p_docstr = p_dstring + p_sstring
+
+local p_docent = token("command",P("<!ENTITY"))
+ * p_optionalwhitespace
+ * token("keyword",name)
+ * p_optionalwhitespace
+ * (
+ (
+ token("constant",P("SYSTEM"))
+ * p_optionalwhitespace
+ * p_docstr
+ * p_optionalwhitespace
+ * token("constant",P("NDATA"))
+ * p_optionalwhitespace
+ * token("keyword",name)
+ ) + (
+ token("constant",P("PUBLIC"))
+ * p_optionalwhitespace
+ * p_docstr
+ ) + (
+ p_docstr
+ )
+ )
+ * p_optionalwhitespace
+ * token("command",P(">"))
+
+local p_docele = token("command",P("<!ELEMENT"))
+ * p_optionalwhitespace
+ * token("keyword",name)
+ * p_optionalwhitespace
+ * token("command",P("("))
+ * (
+ p_spacing
+ + token("constant",P("#CDATA") + P("#PCDATA") + P("ANY"))
+ + token("text",P(","))
+ + token("comment",(1-S(",)"))^1)
+ )^1
+ * token("command",P(")"))
+ * p_optionalwhitespace
+ * token("command",P(">"))
+
+local p_docset = token("command",P("["))
+ * p_optionalwhitespace
+ * ((p_optionalwhitespace * (p_docent + p_docele))^1 + token("comment",(1-P("]"))^0))
+ * p_optionalwhitespace
+ * token("command",P("]"))
+
+local p_doctype = token("command",P("<!DOCTYPE"))
+ * p_optionalwhitespace
+ * token("keyword",name)
+ * p_optionalwhitespace
+ * (
+ (
+ token("constant",P("PUBLIC"))
+ * p_optionalwhitespace
+ * p_docstr
+ * p_optionalwhitespace
+ * p_docstr
+ * p_optionalwhitespace
+ ) + (
+ token("constant",P("SYSTEM"))
+ * p_optionalwhitespace
+ * p_docstr
+ * p_optionalwhitespace
+ )
+ )^-1
+ * p_docset^-1
+ * p_optionalwhitespace
+ * token("command",P(">"))
+
+lexer.embed_lexer(xmllexer, xmlcommentlexer, token("command",opencomment), token("command",closecomment))
+lexer.embed_lexer(xmllexer, xmlcdatalexer, token("command",opencdata), token("command",closecdata))
+
+-- local p_name =
+-- token("plain",name)
+-- * (
+-- token("default",colon)
+-- * token("keyword",name)
+-- )
+-- + token("keyword",name)
+
+local p_name = -- more robust
+ token("plain",name * colon)^-1
+ * token("keyword",name)
+
+-- local p_key =
+-- token("plain",name)
+-- * (
+-- token("default",colon)
+-- * token("constant",name)
+-- )
+-- + token("constant",name)
+
+local p_key =
+ token("plain",name * colon)^-1
+ * token("constant",name)
+
+local p_attributes = (
+ p_optionalwhitespace
+ * p_key
+ * p_optionalwhitespace
+ * token("plain",equal)
+ * p_optionalwhitespace
+ * (p_dstring + p_sstring)
+ * p_optionalwhitespace
+)^0
+
+local p_open =
+ token("keyword",openbegin)
+ * (
+ p_name
+ * p_optionalwhitespace
+ * p_attributes
+ * token("keyword",closebegin)
+ +
+ token("error",(1-closebegin)^1)
+ )
+
+local p_close =
+ token("keyword",openend)
+ * (
+ p_name
+ * p_optionalwhitespace
+ * token("keyword",closeend)
+ +
+ token("error",(1-closeend)^1)
+ )
+
+local p_entity =
+ token("constant",entity)
+
+local p_instruction =
+ token("command",openinstruction * P("xml"))
+ * p_optionalwhitespace
+ * p_attributes
+ * p_optionalwhitespace
+ * token("command",closeinstruction)
+ + token("command",openinstruction * name)
+ * token("default",(1-closeinstruction)^1)
+ * token("command",closeinstruction)
+
+local p_invisible =
+ token("invisible",invisibles^1)
+
+-- local p_preamble =
+-- token('preamble', p_preamble )
+
+xmllexer._rules = {
+ { "whitespace", p_spacing },
+ { "preamble", p_preamble },
+ { "word", p_word },
+-- { "text", p_text },
+-- { "comment", p_comment },
+-- { "cdata", p_cdata },
+ { "doctype", p_doctype },
+ { "instruction", p_instruction },
+ { "close", p_close },
+ { "open", p_open },
+ { "entity", p_entity },
+ { "invisible", p_invisible },
+ { "rest", p_rest },
+}
+
+xmllexer._tokenstyles = context.styleset
+
+xmllexer._foldsymbols = { -- somehow doesn't work yet
+ _patterns = {
+ "[<>]",
+ },
+ ["keyword"] = {
+ ["<"] = 1, [">"] = -1,
+ },
+}
+
+return xmllexer
diff --git a/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer.lua b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer.lua
new file mode 100644
index 00000000000..2db37e26b41
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/scite-context-lexer.lua
@@ -0,0 +1,825 @@
+local info = {
+ version = 1.002,
+ comment = "basics for scintilla lpeg lexer for context/metafun",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "contains copyrighted code from mitchell.att.foicica.com",
+
+}
+
+-- The fold and lex functions are copied and patched from original code by Mitchell (see
+-- lexer.lua). All errors are mine.
+--
+-- I've considered making a whole copy and patch the other functions too as we need
+-- an extra nesting model. However, I don't want to maintain too much. An unfortunate
+-- change in 3.03 is that no longer a script can be specified. This means that instead
+-- of loading the extensions via the properties file, we now need to load them in our
+-- own lexers, unless of course we replace lexer.lua completely (which adds another
+-- installation issue).
+--
+-- Another change has been that _LEXERHOME is no longer available. It looks like more and
+-- more functionality gets dropped so maybe at some point we need to ship our own dll/so
+-- files. For instance, I'd like to have access to the current filename and other scite
+-- properties. For instance, we could cache some info with each file, if only we had
+-- knowledge of what file we're dealing with.
+--
+-- For huge files folding can be pretty slow and I do have some large ones that I keep
+-- open all the time. Loading is normally no ussue, unless one has remembered the status
+-- and the cursor is at the last line of a 200K line file. Optimizing the fold function
+-- brought down loading of char-def.lua from 14 sec => 8 sec. Replacing the word_match
+-- function and optimizing the lex function gained another 2+ seconds. A 6 second load
+-- is quite ok for me.
+--
+-- When the lexer path is copied to the textadept lexer path, and the theme definition to
+-- theme path (as lexer.lua), the lexer works there as well. When I have time and motive
+-- I will make a proper setup file to tune the look and feel a bit and associate suffixes
+-- with the context lexer. The textadept editor has a nice style tracing option but lacks
+-- the tabs for selecting files that scite has. It also has no integrated run that pipes
+-- to the log pane (I wonder if it could borrow code from the console2 project). Interesting
+-- is that the jit version of textadept crashes on lexing large files (and does not feel
+-- faster either).
+--
+-- Function load(lexer_name) starts with _M.WHITESPACE = lexer_name..'_whitespace' which
+-- means that we need to have it frozen at the moment we load another lexer. Because spacing
+-- is used to revert to a parent lexer we need to make sure that we load children as late
+-- as possible in order not to get the wrong whitespace trigger. This took me quite a while
+-- to figure out (not being that familiar with the internals). The lex and fold functions
+-- have been optimized. It is a pitty that there is no proper print available. Another thing
+-- needed is a default style in ourown theme style definition, as otherwise we get wrong
+-- nested lexers, especially if they are larger than a view. This is the hardest part of
+-- getting things right.
+--
+-- Eventually it might be safer to copy the other methods from lexer.lua here as well so
+-- that we have no dependencies, apart from the c library (for which at some point the api
+-- will be stable I guess).
+--
+-- It's a pitty that there is no scintillua library for the OSX version of scite. Even
+-- better would be to have the scintillua library as integral part of scite as that way I
+-- could use OSX alongside windows and linux (depending on needs). Also nice would be to
+-- have a proper interface to scite then because currently the lexer is rather isolated and the
+-- lua version does not provide all standard libraries. It would also be good to have lpeg
+-- support in the regular scite lua extension (currently you need to pick it up from someplace
+-- else).
+
+local lpeg = require 'lpeg'
+
+local R, P, S, C, V, Cp, Cs, Ct, Cmt, Cc, Cf, Cg = lpeg.R, lpeg.P, lpeg.S, lpeg.C, lpeg.V, lpeg.Cp, lpeg.Cs, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Cf, lpeg.Cg
+local lpegmatch = lpeg.match
+local find, gmatch, match, lower, upper, gsub = string.find, string.gmatch, string.match, string.lower, string.upper, string.gsub
+local concat = table.concat
+local global = _G
+local type, next, setmetatable, rawset = type, next, setmetatable, rawset
+
+if lexer then
+ -- in recent c++ code the lexername and loading is hard coded
+elseif _LEXERHOME then
+ dofile(_LEXERHOME .. '/lexer.lua') -- pre 3.03 situation
+else
+ dofile('lexer.lua') -- whatever
+end
+
+lexer.context = lexer.context or { }
+local context = lexer.context
+
+context.patterns = context.patterns or { }
+local patterns = context.patterns
+
+lexer._CONTEXTEXTENSIONS = true
+
+local locations = {
+ -- lexer.context.path,
+ "data", -- optional data directory
+ "..", -- regular scite directory
+}
+
+local function collect(name)
+-- local definitions = loadfile(name .. ".luc") or loadfile(name .. ".lua")
+ local okay, definitions = pcall(function () return require(name) end)
+ if okay then
+ if type(definitions) == "function" then
+ definitions = definitions()
+ end
+ if type(definitions) == "table" then
+ return definitions
+ end
+ end
+end
+
+function context.loaddefinitions(name)
+ for i=1,#locations do
+ local data = collect(locations[i] .. "/" .. name)
+ if data then
+ return data
+ end
+ end
+end
+
+-- maybe more efficient:
+
+function context.word_match(words,word_chars,case_insensitive)
+ local chars = '%w_' -- maybe just "" when word_chars
+ if word_chars then
+ chars = '^([' .. chars .. gsub(word_chars,'([%^%]%-])', '%%%1') ..']+)'
+ else
+ chars = '^([' .. chars ..']+)'
+ end
+ if case_insensitive then
+ local word_list = { }
+ for i=1,#words do
+ word_list[lower(words[i])] = true
+ end
+ return P(function(input, index)
+ local s, e, word = find(input,chars,index)
+ return word and word_list[lower(word)] and e + 1 or nil
+ end)
+ else
+ local word_list = { }
+ for i=1,#words do
+ word_list[words[i]] = true
+ end
+ return P(function(input, index)
+ local s, e, word = find(input,chars,index)
+ return word and word_list[word] and e + 1 or nil
+ end)
+ end
+end
+
+local idtoken = R("az","AZ","\127\255","__")
+local digit = R("09")
+local sign = S("+-")
+local period = P(".")
+local space = S(" \n\r\t\f\v")
+
+patterns.idtoken = idtoken
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.period = period
+
+patterns.cardinal = digit^1
+patterns.integer = sign^-1 * digit^1
+
+patterns.real =
+ sign^-1 * ( -- at most one
+ digit^1 * period * digit^0 -- 10.0 10.
+ + digit^0 * period * digit^1 -- 0.10 .10
+ + digit^1 -- 10
+ )
+
+patterns.restofline = (1-S("\n\r"))^1
+patterns.space = space
+patterns.spacing = space^1
+patterns.nospacing = (1-space)^1
+patterns.anything = P(1)
+
+function context.exact_match(words,word_chars,case_insensitive)
+ local characters = concat(words)
+ local pattern -- the concat catches _ etc
+ if word_chars == true or word_chars == false or word_chars == nil then
+ word_chars = ""
+ end
+ if type(word_chars) == "string" then
+ pattern = S(characters) + idtoken
+ if case_insensitive then
+ pattern = pattern + S(upper(characters)) + S(lower(characters))
+ end
+ if word_chars ~= "" then
+ pattern = pattern + S(word_chars)
+ end
+ elseif word_chars then
+ pattern = word_chars
+ end
+ if case_insensitive then
+ local list = { }
+ for i=1,#words do
+ list[lower(words[i])] = true
+ end
+ return Cmt(pattern^1, function(_,i,s)
+ return list[lower(s)] -- and i or nil
+ end)
+ else
+ local list = { }
+ for i=1,#words do
+ list[words[i]] = true
+ end
+ return Cmt(pattern^1, function(_,i,s)
+ return list[s] -- and i or nil
+ end)
+ end
+end
+
+-- spell checking (we can only load lua files)
+
+-- return {
+-- words = {
+-- ["someword"] = "someword",
+-- ["anotherword"] = "Anotherword",
+-- },
+-- }
+
+local lists = { }
+
+local splitter = (Cf(Ct("") * (Cg(C((1-S(" \t\n\r"))^1 * Cc(true))) + P(1))^1,rawset) )^0
+local splitter = (Cf(Ct("") * (Cg(C(R("az","AZ","\127\255")^1) * Cc(true)) + P(1))^1,rawset) )^0
+
+local function splitwords(words)
+ return lpegmatch(splitter,words)
+end
+
+function context.setwordlist(tag,limit) -- returns hash (lowercase keys and original values)
+ if not tag or tag == "" then
+ return false
+ elseif lists[tag] ~= nil then
+ return lists[tag]
+ else
+ local list = context.loaddefinitions("spell-" .. tag)
+ if not list or type(list) ~= "table" then
+ lists[tag] = false
+ return false
+ elseif type(list.words) == "string" then
+ list = splitwords(list.words) or false
+ lists[tag] = list
+ return list
+ else
+ list = list.words or false
+ lists[tag] = list
+ return list
+ end
+ end
+end
+
+patterns.wordtoken = R("az","AZ","\127\255")
+patterns.wordpattern = patterns.wordtoken^3 -- todo: if limit and #s < limit then
+
+function context.checkedword(validwords,s,i) -- ,limit
+ if not validwords then
+ return true, { "text", i }
+-- return true, { "default", i }
+ else
+ -- keys are lower
+ local word = validwords[s]
+ if word == s then
+ return true, { "okay", i } -- exact match
+ elseif word then
+ return true, { "warning", i } -- case issue
+ else
+ local word = validwords[lower(s)]
+ if word == s then
+ return true, { "okay", i } -- exact match
+ elseif word then
+ return true, { "warning", i } -- case issue
+ elseif upper(s) == s then
+ return true, { "warning", i } -- probably a logo or acronym
+ else
+ return true, { "error", i }
+ end
+ end
+ end
+end
+
+function context.styleofword(validwords,s) -- ,limit
+ if not validwords then
+ return "text"
+ else
+ -- keys are lower
+ local word = validwords[s]
+ if word == s then
+ return "okay" -- exact match
+ elseif word then
+ return "warning" -- case issue
+ else
+ local word = validwords[lower(s)]
+ if word == s then
+ return "okay" -- exact match
+ elseif word then
+ return "warning" -- case issue
+ elseif upper(s) == s then
+ return "warning" -- probably a logo or acronym
+ else
+ return "error"
+ end
+ end
+ end
+end
+
+-- overloaded functions
+
+local FOLD_BASE = SC_FOLDLEVELBASE
+local FOLD_HEADER = SC_FOLDLEVELHEADERFLAG
+local FOLD_BLANK = SC_FOLDLEVELWHITEFLAG
+
+local get_style_at = GetStyleAt
+local get_property = GetProperty
+local get_indent_amount = GetIndentAmount
+
+local h_table, b_table, n_table = { }, { }, { }
+
+setmetatable(h_table, { __index = function(t,level) local v = { level, FOLD_HEADER } t[level] = v return v end })
+setmetatable(b_table, { __index = function(t,level) local v = { level, FOLD_BLANK } t[level] = v return v end })
+setmetatable(n_table, { __index = function(t,level) local v = { level } t[level] = v return v end })
+
+-- local newline = P("\r\n") + S("\r\n")
+-- local splitlines = Ct( ( Ct ( (Cp() * Cs((1-newline)^1) * newline^-1) + (Cp() * Cc("") * newline) ) )^0)
+--
+-- local lines = lpegmatch(splitlines,text) -- iterating over lines is faster
+-- for i=1, #lines do
+-- local li = lines[i]
+-- local line = li[2]
+-- if line ~= "" then
+-- local pos = li[1]
+-- for i=1,nofpatterns do
+-- for s, m in gmatch(line,patterns[i]) do
+-- if hash[m] then
+-- local symbols = fold_symbols[get_style_at(start_pos + pos + s - 1)]
+-- if symbols then
+-- local l = symbols[m]
+-- if l then
+-- local t = type(l)
+-- if t == 'number' then
+-- current_level = current_level + l
+-- elseif t == 'function' then
+-- current_level = current_level + l(text, pos, line, s, match)
+-- end
+-- if current_level < FOLD_BASE then -- integrate in previous
+-- current_level = FOLD_BASE
+-- end
+-- end
+-- end
+-- end
+-- end
+-- end
+-- if current_level > prev_level then
+-- folds[line_num] = h_table[prev_level] -- { prev_level, FOLD_HEADER }
+-- else
+-- folds[line_num] = n_table[prev_level] -- { prev_level }
+-- end
+-- prev_level = current_level
+-- else
+-- folds[line_num] = b_table[prev_level] -- { prev_level, FOLD_BLANK }
+-- end
+-- line_num = line_num + 1
+-- end
+
+local newline = P("\r\n") + S("\r\n")
+local p_yes = Cp() * Cs((1-newline)^1) * newline^-1
+local p_nop = newline
+
+local function fold_by_parsing(text,start_pos,start_line,start_level,lexer)
+ local foldsymbols = lexer._foldsymbols
+ if not foldsymbols then
+ return { }
+ end
+ local patterns = foldsymbols._patterns
+ if not patterns then
+ return { }
+ end
+ local nofpatterns = #patterns
+ if nofpatterns == 0 then
+ return { }
+ end
+ local folds = { }
+ local line_num = start_line
+ local prev_level = start_level
+ local current_level = prev_level
+ local validmatches = foldsymbols._validmatches
+ if not validmatches then
+ validmatches = { }
+ for symbol, matches in next, foldsymbols do -- whatever = { start = 1, stop = -1 }
+ if not find(symbol,"^_") then -- brrr
+ for s, _ in next, matches do
+ validmatches[s] = true
+ end
+ end
+ end
+ foldsymbols._validmatches = validmatches
+ end
+ local function action_y(pos,line) -- we can consider moving the local functions outside (drawback: folds is kept)
+ for i=1,nofpatterns do
+ for s, m in gmatch(line,patterns[i]) do
+ if validmatches[m] then
+ local symbols = foldsymbols[get_style_at(start_pos + pos + s - 1)]
+ if symbols then
+ local action = symbols[m]
+ if action then
+ if type(action) == 'number' then -- we could store this in validmatches if there was only one symbol category
+ current_level = current_level + action
+ else
+ current_level = current_level + action(text,pos,line,s,m)
+ end
+ if current_level < FOLD_BASE then
+ current_level = FOLD_BASE
+ end
+ end
+ end
+ end
+ end
+ end
+ if current_level > prev_level then
+ folds[line_num] = h_table[prev_level] -- { prev_level, FOLD_HEADER }
+ else
+ folds[line_num] = n_table[prev_level] -- { prev_level }
+ end
+ prev_level = current_level
+ line_num = line_num + 1
+ end
+ local function action_n()
+ folds[line_num] = b_table[prev_level] -- { prev_level, FOLD_BLANK }
+ line_num = line_num + 1
+ end
+ if lexer._reset_parser then
+ lexer._reset_parser()
+ end
+ local lpegpattern = (p_yes/action_y + p_nop/action_n)^0 -- not too efficient but indirect function calls are neither but
+ lpegmatch(lpegpattern,text) -- keys are not pressed that fast ... large files are slow anyway
+ return folds
+end
+
+local function fold_by_indentation(text,start_pos,start_line,start_level)
+ local folds = { }
+ local current_line = start_line
+ local prev_level = start_level
+ for _, line in gmatch(text,'([\t ]*)(.-)\r?\n') do
+ if line ~= "" then
+ local current_level = FOLD_BASE + get_indent_amount(current_line)
+ if current_level > prev_level then -- next level
+ local i = current_line - 1
+ while true do
+ local f = folds[i]
+ if f and f[2] == FOLD_BLANK then
+ i = i - 1
+ else
+ break
+ end
+ end
+ local f = folds[i]
+ if f then
+ f[2] = FOLD_HEADER
+ end -- low indent
+ folds[current_line] = n_table[current_level] -- { current_level } -- high indent
+ elseif current_level < prev_level then -- prev level
+ local f = folds[current_line - 1]
+ if f then
+ f[1] = prev_level -- high indent
+ end
+ folds[current_line] = n_table[current_level] -- { current_level } -- low indent
+ else -- same level
+ folds[current_line] = n_table[prev_level] -- { prev_level }
+ end
+ prev_level = current_level
+ else
+ folds[current_line] = b_table[prev_level] -- { prev_level, FOLD_BLANK }
+ end
+ current_line = current_line + 1
+ end
+ return folds
+end
+
+local function fold_by_line(text,start_pos,start_line,start_level)
+ local folds = { }
+ for _ in gmatch(text,".-\r?\n") do
+ folds[start_line] = n_table[start_level] -- { start_level }
+ start_line = start_line + 1
+ end
+ return folds
+end
+
+local threshold_by_lexer = 512 * 1024 -- we don't know the filesize yet
+local threshold_by_parsing = 512 * 1024 -- we don't know the filesize yet
+local threshold_by_indentation = 512 * 1024 -- we don't know the filesize yet
+local threshold_by_line = 512 * 1024 -- we don't know the filesize yet
+
+function context.fold(text,start_pos,start_line,start_level) -- hm, we had size thresholds .. where did they go
+ if text == '' then
+ return { }
+ end
+ local lexer = global._LEXER
+ local fold_by_lexer = lexer._fold
+ local fold_by_symbols = lexer._foldsymbols
+ local filesize = 0 -- we don't know that
+ if fold_by_lexer then
+ if filesize <= threshold_by_lexer then
+ return fold_by_lexer(text,start_pos,start_line,start_level,lexer)
+ end
+ elseif fold_by_symbols and get_property('fold.by.parsing',1) > 0 then
+ if filesize <= threshold_by_parsing then
+ return fold_by_parsing(text,start_pos,start_line,start_level,lexer)
+ end
+ elseif get_property('fold.by.indentation',1) > 0 then
+ if filesize <= threshold_by_indentation then
+ return fold_by_indentation(text,start_pos,start_line,start_level,lexer)
+ end
+ elseif get_property('fold.by.line',1) > 0 then
+ if filesize <= threshold_by_line then
+ return fold_by_line(text,start_pos,start_line,start_level,lexer)
+ end
+ end
+ return { }
+end
+
+-- The following code is mostly unchanged:
+
+local function add_rule(lexer, id, rule)
+ if not lexer._RULES then
+ lexer._RULES = {}
+ lexer._RULEORDER = {}
+ end
+ lexer._RULES[id] = rule
+ lexer._RULEORDER[#lexer._RULEORDER + 1] = id
+end
+
+local function add_style(lexer, token_name, style)
+ local len = lexer._STYLES.len
+ if len == 32 then
+ len = len + 8
+ end
+ if len >= 128 then
+ print('Too many styles defined (128 MAX)')
+ end
+ lexer._TOKENS[token_name] = len
+ lexer._STYLES[len] = style
+ lexer._STYLES.len = len + 1
+end
+
+local function join_tokens(lexer)
+ local patterns, order = lexer._RULES, lexer._RULEORDER
+ local token_rule = patterns[order[1]]
+ for i=2,#order do
+ token_rule = token_rule + patterns[order[i]]
+ end
+ lexer._TOKENRULE = token_rule
+ return lexer._TOKENRULE
+end
+
+local function add_lexer(grammar, lexer, token_rule)
+ local token_rule = join_tokens(lexer)
+ local lexer_name = lexer._NAME
+ local children = lexer._CHILDREN
+ for i=1,#children do
+ local child = children[i]
+ if child._CHILDREN then
+ add_lexer(grammar, child)
+ end
+ local child_name = child._NAME
+ local rules = child._EMBEDDEDRULES[lexer_name]
+ local rules_token_rule = grammar['__'..child_name] or rules.token_rule
+ grammar[child_name] = (-rules.end_rule * rules_token_rule)^0 * rules.end_rule^-1 * V(lexer_name)
+ local embedded_child = '_' .. child_name
+ grammar[embedded_child] = rules.start_rule * (-rules.end_rule * rules_token_rule)^0 * rules.end_rule^-1
+ token_rule = V(embedded_child) + token_rule
+ end
+ grammar['__' .. lexer_name] = token_rule
+ grammar[lexer_name] = token_rule^0
+end
+
+local function build_grammar(lexer, initial_rule)
+ local children = lexer._CHILDREN
+ if children then
+ local lexer_name = lexer._NAME
+ if not initial_rule then
+ initial_rule = lexer_name
+ end
+ local grammar = { initial_rule }
+ add_lexer(grammar, lexer)
+ lexer._INITIALRULE = initial_rule
+ lexer._GRAMMAR = Ct(P(grammar))
+ else
+ lexer._GRAMMAR = Ct(join_tokens(lexer)^0)
+ end
+end
+
+-- so far. We need these local functions in the next one.
+
+function context.lex(text,init_style)
+ local lexer = global._LEXER
+ local grammar = lexer._GRAMMAR
+ if not grammar then
+ return { }
+ elseif lexer._LEXBYLINE then -- we could keep token
+ local tokens = { }
+ local offset = 0
+ local noftokens = 0
+ if true then
+ for line in gmatch(text,'[^\r\n]*\r?\n?') do -- could be an lpeg
+ local line_tokens = lpegmatch(grammar,line)
+ if line_tokens then
+ for i=1,#line_tokens do
+ local token = line_tokens[i]
+ token[2] = token[2] + offset
+ noftokens = noftokens + 1
+ tokens[noftokens] = token
+ end
+ end
+ offset = offset + #line
+ if noftokens > 0 and tokens[noftokens][2] ~= offset then
+ noftokens = noftokens + 1
+ tokens[noftokens] = { 'default', offset + 1 }
+ end
+ end
+ else -- alternative
+ local lasttoken, lastoffset
+ for line in gmatch(text,'[^\r\n]*\r?\n?') do -- could be an lpeg
+ local line_tokens = lpegmatch(grammar,line)
+ if line_tokens then
+ for i=1,#line_tokens do
+ lasttoken = line_tokens[i]
+ lastoffset = lasttoken[2] + offset
+ lasttoken[2] = lastoffset
+ noftokens = noftokens + 1
+ tokens[noftokens] = lasttoken
+ end
+ end
+ offset = offset + #line
+ if lastoffset ~= offset then
+ lastoffset = offset + 1
+ lasttoken = { 'default', lastoffset }
+ noftokens = noftokens + 1
+ tokens[noftokens] = lasttoken
+ end
+ end
+ end
+ return tokens
+ elseif lexer._CHILDREN then
+ -- as we cannot print, tracing is not possible ... this might change as we can as well
+ -- generate them all in one go (sharing as much as possible)
+ local _hash = lexer._HASH
+ if not hash then
+ hash = { }
+ lexer._HASH = hash
+ end
+ grammar = hash[init_style]
+ if grammar then
+ lexer._GRAMMAR = grammar
+ else
+ for style, style_num in next, lexer._TOKENS do
+ if style_num == init_style then
+ -- the name of the lexers is filtered from the whitespace
+ -- specification
+ local lexer_name = match(style,'^(.+)_whitespace') or lexer._NAME
+ if lexer._INITIALRULE ~= lexer_name then
+ grammar = hash[lexer_name]
+ if not grammar then
+ build_grammar(lexer,lexer_name)
+ grammar = lexer._GRAMMAR
+ hash[lexer_name] = grammar
+ end
+ end
+ break
+ end
+ end
+ grammar = grammar or lexer._GRAMMAR
+ hash[init_style] = grammar
+ end
+ return lpegmatch(grammar,text)
+ else
+ return lpegmatch(grammar,text)
+ end
+end
+
+-- todo: keywords: one lookup and multiple matches
+
+function context.token(name, patt)
+ return Ct(patt * Cc(name) * Cp())
+end
+
+lexer.fold = context.fold
+lexer.lex = context.lex
+lexer.token = context.token
+lexer.exact_match = context.exact_match
+
+-- helper .. alas ... the lexer's lua instance is rather crippled .. not even
+-- math is part of it
+
+local floor = math and math.floor
+local char = string.char
+
+if not floor then
+
+ floor = function(n)
+ return tonumber(string.format("%d",n))
+ end
+
+ math = math or { }
+
+ math.floor = floor
+
+end
+
+local function utfchar(n)
+ if n < 0x80 then
+ return char(n)
+ elseif n < 0x800 then
+ return char(
+ 0xC0 + floor(n/0x40),
+ 0x80 + (n % 0x40)
+ )
+ elseif n < 0x10000 then
+ return char(
+ 0xE0 + floor(n/0x1000),
+ 0x80 + (floor(n/0x40) % 0x40),
+ 0x80 + (n % 0x40)
+ )
+ elseif n < 0x40000 then
+ return char(
+ 0xF0 + floor(n/0x40000),
+ 0x80 + floor(n/0x1000),
+ 0x80 + (floor(n/0x40) % 0x40),
+ 0x80 + (n % 0x40)
+ )
+ else
+ -- return char(
+ -- 0xF1 + floor(n/0x1000000),
+ -- 0x80 + floor(n/0x40000),
+ -- 0x80 + floor(n/0x1000),
+ -- 0x80 + (floor(n/0x40) % 0x40),
+ -- 0x80 + (n % 0x40)
+ -- )
+ return "?"
+ end
+end
+
+context.utfchar = utfchar
+
+-- a helper from l-lpeg:
+
+local gmatch = string.gmatch
+
+local function make(t)
+ local p
+ for k, v in next, t do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- patterns.invisibles =
+-- P(utfchar(0x00A0)) -- nbsp
+-- + P(utfchar(0x2000)) -- enquad
+-- + P(utfchar(0x2001)) -- emquad
+-- + P(utfchar(0x2002)) -- enspace
+-- + P(utfchar(0x2003)) -- emspace
+-- + P(utfchar(0x2004)) -- threeperemspace
+-- + P(utfchar(0x2005)) -- fourperemspace
+-- + P(utfchar(0x2006)) -- sixperemspace
+-- + P(utfchar(0x2007)) -- figurespace
+-- + P(utfchar(0x2008)) -- punctuationspace
+-- + P(utfchar(0x2009)) -- breakablethinspace
+-- + P(utfchar(0x200A)) -- hairspace
+-- + P(utfchar(0x200B)) -- zerowidthspace
+-- + P(utfchar(0x202F)) -- narrownobreakspace
+-- + P(utfchar(0x205F)) -- math thinspace
+
+patterns.invisibles = lpeg.utfchartabletopattern {
+ utfchar(0x00A0), -- nbsp
+ utfchar(0x2000), -- enquad
+ utfchar(0x2001), -- emquad
+ utfchar(0x2002), -- enspace
+ utfchar(0x2003), -- emspace
+ utfchar(0x2004), -- threeperemspace
+ utfchar(0x2005), -- fourperemspace
+ utfchar(0x2006), -- sixperemspace
+ utfchar(0x2007), -- figurespace
+ utfchar(0x2008), -- punctuationspace
+ utfchar(0x2009), -- breakablethinspace
+ utfchar(0x200A), -- hairspace
+ utfchar(0x200B), -- zerowidthspace
+ utfchar(0x202F), -- narrownobreakspace
+ utfchar(0x205F), -- math thinspace
+}
+
+-- now we can make:
+
+patterns.iwordtoken = patterns.wordtoken - patterns.invisibles
+patterns.iwordpattern = patterns.iwordtoken^3
+
+-- require("themes/scite-context-theme")
+
+-- In order to deal with some bug in additional styles (I have no cue what is
+-- wrong, but additional styles get ignored and clash somehow) I just copy the
+-- original lexer code ... see original for comments.
diff --git a/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme-keep.lua b/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme-keep.lua
new file mode 100644
index 00000000000..7f9423d9a30
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme-keep.lua
@@ -0,0 +1,233 @@
+local info = {
+ version = 1.002,
+ comment = "theme for scintilla lpeg lexer for context/metafun",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- context_path = string.split(os.resultof("mtxrun --find-file context.mkiv"))[1] or ""
+-- global.trace("OEPS") -- how do we get access to the regular lua extensions
+
+-- The regular styles set the main lexer styles table but we avoid that in order not
+-- to end up with updating issues. We just use another table.
+
+-- if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local context_path = "t:/sources" -- c:/data/tex-context/tex/texmf-context/tex/base
+local font_name = 'Dejavu Sans Mono'
+local font_size = 14
+
+if not WIN32 then
+ font_name = '!' .. font_name
+end
+
+local color = lexer.color
+local style = lexer.style
+
+lexer.context = lexer.context or { }
+local context = lexer.context
+
+context.path = context_path
+
+colors = {
+ red = color('7F', '00', '00'),
+ green = color('00', '7F', '00'),
+ blue = color('00', '00', '7F'),
+ cyan = color('00', '7F', '7F'),
+ magenta = color('7F', '00', '7F'),
+ yellow = color('7F', '7F', '00'),
+ orange = color('B0', '7F', '00'),
+ --
+ white = color('FF', 'FF', 'FF'),
+ light = color('CF', 'CF', 'CF'),
+ grey = color('80', '80', '80'),
+ dark = color('4F', '4F', '4F'),
+ black = color('00', '00', '00'),
+ --
+ selection = color('F7', 'F7', 'F7'),
+ logpanel = color('E7', 'E7', 'E7'),
+ textpanel = color('CF', 'CF', 'CF'),
+ linepanel = color('A7', 'A7', 'A7'),
+ tippanel = color('44', '44', '44'),
+ --
+ right = color('00', '00', 'FF'),
+ wrong = color('FF', '00', '00'),
+}
+
+colors.teal = colors.cyan
+colors.purple = colors.magenta
+
+-- to be set:
+--
+-- style_nothing
+-- style_class
+-- style_comment
+-- style_constant
+-- style_definition
+-- style_error
+-- style_function
+-- style_keyword
+-- style_number
+-- style_operator
+-- style_string
+-- style_preproc
+-- style_tag
+-- style_type
+-- style_variable
+-- style_embedded
+-- style_label
+-- style_regex
+-- style_identifier
+--
+-- style_line_number
+-- style_bracelight
+-- style_bracebad
+-- style_controlchar
+-- style_indentguide
+-- style_calltip
+
+style_default = style {
+ font = font_name,
+ size = font_size,
+ fore = colors.black,
+ back = colors.textpanel,
+}
+
+style_nothing = style {
+ -- empty
+}
+
+style_number = style { fore = colors.cyan }
+style_comment = style { fore = colors.yellow }
+style_string = style { fore = colors.magenta }
+style_keyword = style { fore = colors.blue, bold = true }
+
+style_quote = style { fore = colors.blue, bold = true }
+style_special = style { fore = colors.blue }
+style_extra = style { fore = colors.yellow }
+
+style_embedded = style { fore = colors.black, bold = true }
+
+style_char = style { fore = colors.magenta }
+style_reserved = style { fore = colors.magenta, bold = true }
+style_class = style { fore = colors.black, bold = true }
+style_constant = style { fore = colors.cyan, bold = true }
+style_definition = style { fore = colors.black, bold = true }
+style_okay = style { fore = colors.dark }
+style_error = style { fore = colors.red }
+style_warning = style { fore = colors.orange }
+style_invisible = style { back = colors.orange }
+style_function = style { fore = colors.black, bold = true }
+style_operator = style { fore = colors.blue }
+style_preproc = style { fore = colors.yellow, bold = true }
+style_tag = style { fore = colors.cyan }
+style_type = style { fore = colors.blue }
+style_variable = style { fore = colors.black }
+style_identifier = style_nothing
+
+style_standout = style { fore = colors.orange, bold = true }
+
+style_line_number = style { back = colors.linepanel }
+style_bracelight = style_standout
+style_bracebad = style_standout
+style_indentguide = style { fore = colors.linepanel, back = colors.white }
+style_calltip = style { fore = colors.white, back = colors.tippanel }
+style_controlchar = style_nothing
+
+style_label = style { fore = colors.red, bold = true } -- style { fore = colors.cyan, bold = true }
+style_regex = style_string
+
+style_command = style { fore = colors.green, bold = true }
+
+-- only bold seems to work
+
+lexer.style_nothing = style_nothing
+lexer.style_class = style_class
+lexer.style_comment = style_comment
+lexer.style_constant = style_constant
+lexer.style_definition = style_definition
+lexer.style_error = style_error
+lexer.style_function = style_function
+lexer.style_keyword = style_keyword
+lexer.style_number = style_number
+lexer.style_operator = style_operator
+lexer.style_string = style_string
+lexer.style_preproc = style_preproc
+lexer.style_tag = style_tag
+lexer.style_type = style_type
+lexer.style_variable = style_variable
+lexer.style_embedded = style_embedded
+lexer.style_label = style_label
+lexer.style_regex = style_regex
+lexer.style_identifier = style_nothing
+
+local styles = { -- as we have globals we could do with less
+
+ -- ["whitespace"] = style_whitespace, -- not to be set!
+
+["default"] = style_nothing,
+["number"] = style_number,
+["comment"] = style_comment,
+["keyword"] = style_keyword,
+["string"] = style_string,
+["preproc"] = style_preproc,
+
+ ["reserved"] = style_reserved,
+ ["internal"] = style_standout,
+
+ ["command"] = style_command,
+ ["preamble"] = style_comment,
+ ["embedded"] = style_embedded,
+ ["grouping"] = style { fore = colors.red },
+["label"] = style_label,
+ ["primitive"] = style_keyword,
+ ["plain"] = style { fore = colors.dark, bold = true },
+ ["user"] = style { fore = colors.green },
+ ["data"] = style_constant,
+ ["special"] = style_special,
+ ["extra"] = style_extra,
+ ["quote"] = style_quote,
+
+ ["okay"] = style_okay,
+ ["warning"] = style_warning,
+ ["invisible"] = style_invisible,
+["error"] = style_error,
+
+}
+
+-- Old method (still available):
+
+local styleset = { }
+
+for k, v in next, styles do
+ styleset[#styleset+1] = { k, v }
+end
+
+context.styles = styles
+context.styleset = styleset
+
+-- We need to be sparse due to some limitation (and the number of built in styles
+-- growing).
+
+-- function context.newstyleset(list)
+-- local t = { }
+-- if list then
+-- for i=1,#list do
+-- t[list[i]] = true
+-- end
+-- end
+-- return t
+-- end
+
+-- function context.usestyle(set,name)
+-- set[name] = true
+-- return name
+-- end
+
+-- function context.usestyleset(set)
+-- local t = { }
+-- for k, _ in next, set do
+-- t[#t+1] = { k, styles[k] or styles.default }
+-- end
+-- end
diff --git a/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme.lua b/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme.lua
new file mode 100644
index 00000000000..7b305d3e5d5
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/lexers/themes/scite-context-theme.lua
@@ -0,0 +1,224 @@
+local info = {
+ version = 1.002,
+ comment = "theme for scintilla lpeg lexer for context/metafun",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- context_path = string.split(os.resultof("mtxrun --find-file context.mkiv"))[1] or ""
+-- global.trace("OEPS") -- how do we get access to the regular lua extensions
+
+-- The regular styles set the main lexer styles table but we avoid that in order not
+-- to end up with updating issues. We just use another table.
+
+if not lexer._CONTEXTEXTENSIONS then require("scite-context-lexer") end
+
+local context_path = "t:/sources" -- c:/data/tex-context/tex/texmf-context/tex/base
+local font_name = 'Dejavu Sans Mono'
+local font_size = 14
+
+if not WIN32 then
+ font_name = '!' .. font_name
+end
+
+local color = lexer.color
+local style = lexer.style
+
+lexer.context = lexer.context or { }
+local context = lexer.context
+
+context.path = context_path
+
+local colors = {
+ red = color('7F', '00', '00'),
+ green = color('00', '7F', '00'),
+ blue = color('00', '00', '7F'),
+ cyan = color('00', '7F', '7F'),
+ magenta = color('7F', '00', '7F'),
+ yellow = color('7F', '7F', '00'),
+ orange = color('B0', '7F', '00'),
+ --
+ white = color('FF', 'FF', 'FF'),
+ light = color('CF', 'CF', 'CF'),
+ grey = color('80', '80', '80'),
+ dark = color('4F', '4F', '4F'),
+ black = color('00', '00', '00'),
+ --
+ selection = color('F7', 'F7', 'F7'),
+ logpanel = color('E7', 'E7', 'E7'),
+ textpanel = color('CF', 'CF', 'CF'),
+ linepanel = color('A7', 'A7', 'A7'),
+ tippanel = color('44', '44', '44'),
+ --
+ right = color('00', '00', 'FF'),
+ wrong = color('FF', '00', '00'),
+}
+
+colors.teal = colors.cyan
+colors.purple = colors.magenta
+
+lexer.colors = colors
+
+-- defaults:
+
+local style_nothing = style { }
+----- style_whitespace = style { }
+local style_comment = style { fore = colors.yellow }
+local style_string = style { fore = colors.magenta }
+local style_number = style { fore = colors.cyan }
+local style_keyword = style { fore = colors.blue, bold = true }
+local style_identifier = style_nothing
+local style_operator = style { fore = colors.blue }
+local style_error = style { fore = colors.red }
+local style_preproc = style { fore = colors.yellow, bold = true }
+local style_constant = style { fore = colors.cyan, bold = true }
+local style_variable = style { fore = colors.black }
+local style_function = style { fore = colors.black, bold = true }
+local style_class = style { fore = colors.black, bold = true }
+local style_type = style { fore = colors.blue }
+local style_label = style { fore = colors.red, bold = true }
+local style_regex = style { fore = colors.magenta }
+
+-- reserved:
+
+local style_default = style { font = font_name, size = font_size, fore = colors.black, back = colors.textpanel }
+local style_text = style { font = font_name, size = font_size, fore = colors.black, back = colors.textpanel }
+local style_line_number = style { back = colors.linepanel }
+local style_bracelight = style { fore = colors.orange, bold = true }
+local style_bracebad = style { fore = colors.orange, bold = true }
+local style_indentguide = style { fore = colors.linepanel, back = colors.white }
+local style_calltip = style { fore = colors.white, back = colors.tippanel }
+local style_controlchar = style_nothing
+
+-- extras:
+
+local style_quote = style { fore = colors.blue, bold = true }
+local style_special = style { fore = colors.blue }
+local style_extra = style { fore = colors.yellow }
+local style_embedded = style { fore = colors.black, bold = true }
+----- style_char = style { fore = colors.magenta }
+local style_reserved = style { fore = colors.magenta, bold = true }
+local style_definition = style { fore = colors.black, bold = true }
+local style_okay = style { fore = colors.dark }
+local style_warning = style { fore = colors.orange }
+local style_invisible = style { back = colors.orange }
+local style_tag = style { fore = colors.cyan }
+----- style_standout = style { fore = colors.orange, bold = true }
+local style_command = style { fore = colors.green, bold = true }
+local style_internal = style { fore = colors.orange, bold = true }
+local style_internal = style { fore = colors.orange, bold = true }
+
+local style_preamble = style { fore = colors.yellow }
+local style_grouping = style { fore = colors.red }
+local style_primitive = style { fore = colors.blue, bold = true }
+local style_plain = style { fore = colors.dark, bold = true }
+local style_user = style { fore = colors.green }
+local style_data = style { fore = colors.cyan, bold = true }
+
+
+-- used by the generic lexer:
+
+lexer.style_nothing = style_nothing -- 0
+-----.whitespace = style_whitespace -- 1
+lexer.style_comment = style_comment -- 2
+lexer.style_string = style_string -- 3
+lexer.style_number = style_number -- 4
+lexer.style_keyword = style_keyword -- 5
+lexer.style_identifier = style_nothing -- 6
+lexer.style_operator = style_operator -- 7
+lexer.style_error = style_error -- 8
+lexer.style_preproc = style_preproc -- 9
+lexer.style_constant = style_constant -- 10
+lexer.style_variable = style_variable -- 11
+lexer.style_function = style_function -- 12
+lexer.style_class = style_class -- 13
+lexer.style_type = style_type -- 14
+lexer.style_label = style_label -- 15
+lexer.style_regex = style_regexp -- 16
+
+lexer.style_default = style_default -- 32
+lexer.style_line_number = style_line_number -- 33
+lexer.style_bracelight = style_bracelight -- 34
+lexer.style_bracebad = style_bracebad -- 35
+lexer.style_indentguide = style_indentguide -- 36
+lexer.style_calltip = style_calltip -- 37
+lexer.style_controlchar = style_controlchar -- 38
+
+local styles = { -- as we have globals we could do with less
+
+ -- ["whitespace"] = style_whitespace, -- not to be set!
+ ["default"] = style_nothing, -- else no good backtracking to start-of-child
+ -- ["number"] = style_number,
+ -- ["comment"] = style_comment,
+ -- ["keyword"] = style_keyword,
+ -- ["string"] = style_string,
+ -- ["preproc"] = style_preproc,
+ -- ["error"] = style_error,
+ -- ["label"] = style_label,
+
+ ["invisible"] = style_invisible,
+ ["quote"] = style_quote,
+ ["special"] = style_special,
+ ["extra"] = style_extra,
+ ["embedded"] = style_embedded,
+ -- ["char"] = style_char,
+ ["reserved"] = style_reserved,
+ -- ["definition"] = style_definition,
+ ["okay"] = style_okay,
+ ["warning"] = style_warning,
+ -- ["standout"] = style_standout,
+ ["command"] = style_command,
+ ["internal"] = style_internal,
+ ["preamble"] = style_preamble,
+ ["grouping"] = style_grouping,
+ ["primitive"] = style_primitive,
+ ["plain"] = style_plain,
+ ["user"] = style_user,
+ ["data"] = style_data,
+
+ ["text"] = style_text, -- style_default
+
+}
+
+local styleset = { }
+
+for k, v in next, styles do
+ styleset[#styleset+1] = { k, v }
+end
+
+context.styles = styles
+context.styleset = styleset
+
+function context.stylesetcopy()
+ local t = { }
+ for i=1,#styleset do
+ t[i] = styleset[i]
+ end
+ t[#t+1] = { "whitespace", style_nothing }
+ return t
+end
+
+-- We can be sparse if needed:
+
+-- function context.newstyleset(list)
+-- local t = { }
+-- if list then
+-- for i=1,#list do
+-- t[list[i]] = true
+-- end
+-- end
+-- return t
+-- end
+
+-- function context.usestyle(set,name)
+-- set[name] = true
+-- return name
+-- end
+
+-- function context.usestyleset(set)
+-- local t = { }
+-- for k, _ in next, set do
+-- t[#t+1] = { k, styles[k] or styles.default }
+-- end
+-- end
diff --git a/Master/texmf-dist/context/data/scite/metafun-scite.properties b/Master/texmf-dist/context/data/scite/metafun-scite.properties
deleted file mode 100644
index 55b7ae607fb..00000000000
--- a/Master/texmf-dist/context/data/scite/metafun-scite.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-keywordclass.metafun.all=\
- unitcircle fulldiamond unitdiamond \
- halfcircle quartercircle \
- llcircle lrcircle urcircle ulcircle \
- tcircle bcircle lcircle rcircle \
- lltriangle lrtriangle urtriangle ultriangle \
- smoothed cornered superellipsed randomized squeezed \
- punked curved unspiked simplified blownup stretched \
- enlarged leftenlarged topenlarged rightenlarged bottomenlarged \
- llenlarged lrenlarged urenlarged ulenlarged \
- llmoved lrmoved urmoved ulmoved \
- boundingbox innerboundingbox outerboundingbox \
- bottomboundary leftboundary topboundary rightboundary \
- xsized ysized xysized \
- cmyk transparent withshade spotcolor \
- drawfill undrawfill \
- inverted uncolored softened grayed \
- textext graphictext \
- loadfigure externalfigure \ No newline at end of file
diff --git a/Master/texmf-dist/context/data/scite/metapost.properties b/Master/texmf-dist/context/data/scite/metapost.properties
new file mode 100644
index 00000000000..fe89b65eb57
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/metapost.properties
@@ -0,0 +1 @@
+import scite-metapost
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-context.properties b/Master/texmf-dist/context/data/scite/scite-context-data-context.properties
new file mode 100644
index 00000000000..c0622e213bc
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-context.properties
@@ -0,0 +1,129 @@
+keywordclass.context.helpers=\
+startsetups stopsetups startxmlsetups stopxmlsetups \
+startluasetups stopluasetups starttexsetups stoptexsetups startrawsetups \
+stoprawsetups startlocalsetups stoplocalsetups starttexdefinition stoptexdefinition \
+starttexcode stoptexcode doifsetupselse doifsetups doifnotsetups \
+setup setups texsetup xmlsetup luasetup \
+directsetup newmode setmode resetmode newsystemmode \
+setsystemmode resetsystemmode pushsystemmode popsystemmode booleanmodevalue \
+newcount newdimen newskip newmuskip newbox \
+newtoks newread newwrite newmarks newinsert \
+newattribute newif newlanguage newfamily newfam \
+newhelp then donothing dontcomplain donetrue \
+donefalse htdp unvoidbox vfilll mathbox \
+mathlimop mathnolop mathnothing mathalpha currentcatcodetable \
+defaultcatcodetable catcodetablename newcatcodetable startcatcodetable stopcatcodetable \
+startextendcatcodetable stopextendcatcodetable pushcatcodetable popcatcodetable restorecatcodes \
+setcatcodetable letcatcodecommand defcatcodecommand uedcatcodecommand hglue \
+vglue hfillneg vfillneg hfilllneg vfilllneg \
+ruledhss ruledhfil ruledhfill ruledhfilneg ruledhfillneg \
+normalhfillneg ruledvss ruledvfil ruledvfill ruledvfilneg \
+ruledvfillneg normalvfillneg ruledhbox ruledvbox ruledvtop \
+ruledvcenter ruledhskip ruledvskip ruledkern ruledmskip \
+ruledmkern ruledhglue ruledvglue normalhglue normalvglue \
+ruledpenalty scratchcounter globalscratchcounter scratchdimen globalscratchdimen \
+scratchskip globalscratchskip scratchmuskip globalscratchmuskip scratchtoks \
+globalscratchtoks scratchbox globalscratchbox nextbox dowithnextbox \
+dowithnextboxcs dowithnextboxcontent dowithnextboxcontentcs scratchwidth scratchheight \
+scratchdepth scratchoffset scratchdistance scratchhsize scratchvsize \
+scratchcounterone scratchcountertwo scratchcounterthree scratchdimenone scratchdimentwo \
+scratchdimenthree scratchskipone scratchskiptwo scratchskipthree scratchmuskipone \
+scratchmuskiptwo scratchmuskipthree scratchtoksone scratchtokstwo scratchtoksthree \
+scratchboxone scratchboxtwo scratchboxthree doif doifnot \
+doifelse doifinset doifnotinset doifinsetelse doifnextcharelse \
+doifnextoptionalelse doifnextbgroupelse doifnextparenthesiselse doiffastoptionalcheckelse doifundefinedelse \
+doifdefinedelse doifundefined doifdefined doifelsevalue doifvalue \
+doifnotvalue doifnothing doifsomething doifelsenothing doifsomethingelse \
+doifvaluenothing doifvaluesomething doifelsevaluenothing doifdimensionelse doifnumberelse \
+doifcommonelse doifcommon doifnotcommon doifinstring doifnotinstring \
+doifinstringelse doifassignmentelse tracingall tracingnone loggingall \
+appendtoks prependtoks appendtotoks prependtotoks to \
+endgraf empty null space quad \
+enspace obeyspaces obeylines normalspace executeifdefined \
+singleexpandafter doubleexpandafter tripleexpandafter dontleavehmode removelastspace \
+removeunwantedspaces wait writestatus define redefine \
+setmeasure setemeasure setgmeasure setxmeasure definemeasure \
+measure getvalue setvalue setevalue setgvalue \
+setxvalue letvalue letgvalue resetvalue undefinevalue \
+ignorevalue setuvalue setuevalue setugvalue setuxvalue \
+globallet glet getparameters geteparameters getgparameters \
+getxparameters forgetparameters copyparameters processcommalist processcommacommand \
+quitcommalist quitprevcommalist processaction processallactions processfirstactioninset \
+processallactionsinset unexpanded expanded startexpanded stopexpanded \
+protected protect unprotect firstofoneargument firstoftwoarguments \
+secondoftwoarguments firstofthreearguments secondofthreearguments thirdofthreearguments firstoffourarguments \
+secondoffourarguments thirdoffourarguments fourthoffourarguments firstoffivearguments secondoffivearguments \
+thirdoffivearguments fourthoffivearguments fifthoffivearguments firstofsixarguments secondofsixarguments \
+thirdofsixarguments fourthofsixarguments fifthofsixarguments sixthofsixarguments firstofoneunexpanded \
+gobbleoneargument gobbletwoarguments gobblethreearguments gobblefourarguments gobblefivearguments \
+gobblesixarguments gobblesevenarguments gobbleeightarguments gobbleninearguments gobbletenarguments \
+gobbleoneoptional gobbletwooptionals gobblethreeoptionals gobblefouroptionals gobblefiveoptionals \
+dorecurse doloop exitloop dostepwiserecurse recurselevel \
+recursedepth dofastloopcs newconstant setnewconstant newconditional \
+settrue setfalse setconstant newmacro setnewmacro \
+newfraction dosingleempty dodoubleempty dotripleempty doquadrupleempty \
+doquintupleempty dosixtupleempty doseventupleempty dosingleargument dodoubleargument \
+dotripleargument doquadrupleargument dosinglegroupempty dodoublegroupempty dotriplegroupempty \
+doquadruplegroupempty doquintuplegroupempty nopdfcompression maximumpdfcompression normalpdfcompression \
+modulonumber dividenumber getfirstcharacter doiffirstcharelse startnointerference \
+stopnointerference strut setstrut strutbox strutht \
+strutdp strutwd begstrut endstrut
+
+keywordclass.context.constants=\
+zerocount minusone minustwo plusone \
+plustwo plusthree plusfour plusfive plussix \
+plusseven pluseight plusnine plusten plussixteen \
+plushundred plusthousand plustenthousand plustwentythousand medcard \
+maxcard zeropoint onepoint halfapoint onebasepoint \
+maxdimen scaledpoint thousandpoint points halfpoint \
+zeroskip pluscxxvii pluscxxviii pluscclv pluscclvi \
+normalpagebox endoflinetoken outputnewlinechar emptytoks empty \
+undefined voidbox emptybox emptyvbox emptyhbox \
+bigskipamount medskipamount smallskipamount fmtname fmtversion \
+texengine texenginename texengineversion luatexengine pdftexengine \
+xetexengine unknownengine etexversion pdftexversion xetexversion \
+xetexrevision activecatcode bgroup egroup endline \
+conditionaltrue conditionalfalse attributeunsetvalue uprotationangle rightrotationangle \
+downrotationangle leftrotationangle inicatcodes ctxcatcodes texcatcodes \
+notcatcodes txtcatcodes vrbcatcodes prtcatcodes nilcatcodes \
+luacatcodes tpacatcodes tpbcatcodes xmlcatcodes escapecatcode \
+begingroupcatcode endgroupcatcode mathshiftcatcode alignmentcatcode endoflinecatcode \
+parametercatcode superscriptcatcode subscriptcatcode ignorecatcode spacecatcode \
+lettercatcode othercatcode activecatcode commentcatcode invalidcatcode \
+tabasciicode newlineasciicode formfeedasciicode endoflineasciicode endoffileasciicode \
+spaceasciicode hashasciicode dollarasciicode commentasciicode ampersandasciicode \
+colonasciicode backslashasciicode circumflexasciicode underscoreasciicode leftbraceasciicode \
+barasciicode rightbraceasciicode tildeasciicode delasciicode lessthanasciicode \
+morethanasciicode doublecommentsignal atsignasciicode exclamationmarkasciicode questionmarkasciicode \
+doublequoteasciicode singlequoteasciicode forwardslashasciicode primeasciicode activemathcharcode \
+activetabtoken activeformfeedtoken activeendoflinetoken batchmodecode nonstopmodecode \
+scrollmodecode errorstopmodecode bottomlevelgroupcode simplegroupcode hboxgroupcode \
+adjustedhboxgroupcode vboxgroupcode vtopgroupcode aligngroupcode noaligngroupcode \
+outputgroupcode mathgroupcode discretionarygroupcode insertgroupcode vcentergroupcode \
+mathchoicegroupcode semisimplegroupcode mathshiftgroupcode mathleftgroupcode vadjustgroupcode \
+charnodecode hlistnodecode vlistnodecode rulenodecode insertnodecode \
+marknodecode adjustnodecode ligaturenodecode discretionarynodecode whatsitnodecode \
+mathnodecode gluenodecode kernnodecode penaltynodecode unsetnodecode \
+mathsnodecode charifcode catifcode numifcode dimifcode \
+oddifcode vmodeifcode hmodeifcode mmodeifcode innerifcode \
+voidifcode hboxifcode vboxifcode xifcode eofifcode \
+trueifcode falseifcode caseifcode definedifcode csnameifcode \
+fontcharifcode fontslantperpoint fontinterwordspace fontinterwordstretch fontinterwordshrink \
+fontexheight fontemwidth fontextraspace slantperpoint interwordspace \
+interwordstretch interwordshrink exheight emwidth extraspace \
+mathsupdisplay mathsupnormal mathsupcramped mathsubnormal mathsubcombined \
+mathaxisheight startmode stopmode startnotmode stopnotmode \
+startmodeset stopmodeset doifmode doifmodeelse doifnotmode \
+startallmodes stopallmodes startnotallmodes stopnotallmodes doifallmodes \
+doifallmodeselse doifnotallmodes startenvironment stopenvironment environment \
+startcomponent stopcomponent component startproduct stopproduct \
+product startproject stopproject project starttext \
+stoptext startdocument stopdocument documentvariable startmodule \
+stopmodule usemodule startTEXpage stopTEXpage enablemode \
+disablemode preventmode pushmode popmode typescriptone \
+typescripttwo typescriptthree mathsizesuffix mathordcode mathopcode \
+mathbincode mathrelcode mathopencode mathclosecode mathpunctcode \
+mathalphacode mathinnercode mathnothingcode mathlimopcode mathnolopcode \
+mathboxcode mathchoicecode mathaccentcode mathradicalcode constantnumber \
+constantnumberargument constantdimen constantdimenargument constantemptyargument continueifinputfile
+
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-interfaces.properties b/Master/texmf-dist/context/data/scite/scite-context-data-interfaces.properties
new file mode 100644
index 00000000000..c205bb568d9
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-interfaces.properties
@@ -0,0 +1,1276 @@
+keywordclass.context.it=\
+CAP Cap Caps GIORNOSETTIMANA \
+Lettera Lettere MESE Numeri Numeriromani \
+PAROLA PAROLE Parola Parole accoppiacarta \
+accoppiadocumento accoppiamarcatura accoppiapagina accoppiaregistro adattacampo \
+adattalayout al allineacentro allineadestra allineasinistra \
+altezzacarta altezzacartastampa altezzacima altezzaelenco altezzafondo \
+altezzaintestazione altezzamakeup altezzapdp altezzatesto ambiente \
+ampiezzabordo ampiezzabordodestro ampiezzabordosinistro ampiezzacarta ampiezzacartastampa \
+ampiezzaelenco ampiezzamakeup ampiezzamargine ampiezzamarginedestro ampiezzamarginesinistro \
+ampiezzatesto ap apagina appendix arg \
+atleftmargin atrightmargin barracolori barrainterazione barrasincronizzazione \
+bastablocchi bastafile cambiaafontdeltesto campi camporiempimento \
+cap capello chapter chim circondato \
+citazione clip clonacampo colonna colore \
+coloregrigio comment commento completecombinedlist completelistoffloats \
+completelistofsorts completelistofsynonyms completeregister componenet confrontagruppocolori \
+confrontatavolozza convertinumero copiacampo correggispaziobianco coupledregister \
+crlf cutspace da daqualcheparte data \
+datadioggi datareferral decrementnumber definebodyfontDEF definebodyfontREF \
+definecolumnbreak definecombination definedfont definefontfeature definefonthandling \
+defineindentedtext defineinmargin defineitemgroup definelayer definemathalignment \
+definepagebreak defineplacement definetypeface definisci definisciaccento \
+definisciambientefontdeltesto definisciblocco definiscibloccosezione definiscibuffer definiscicampo \
+definiscicampoprincipale definiscicapoversi definiscicarattere definiscicolore definiscicomando \
+definisciconversione definiscidescrizione definiscidimensionicarta definiscielenco definiscielencocombinato \
+definiscienumerazione definiscietichetta definiscifigurasimbolo definiscifont definiscifontdeltesto \
+definiscifontgrezzo definisciformatoriferimento definiscigruppocolonne definiscigruppocolori definiscihbox \
+definisciincorniciato definisciiniziatermina definiscilayout definiscilinea definiscilistariferimenti \
+definiscilogo definiscimakeup definiscimarcatura definiscimenuinterazione definiscimodellotabella \
+definiscioggettomobile definisciordinamento definiscioutput definisciposizionetesto definisciprofilo \
+definisciprogramma definisciregistro definisciriferimento definiscirigovuoto definiscisezione \
+definiscisimbolo definiscisinonimi definiscisinonimofont definiscisottocampo definiscisovrapposizione \
+definiscistackcampi definiscistile definiscistilefont definiscitabulato definiscitavolozza \
+definiscitesta definiscitesto definiscitestoincorniciato definiscitype definiscityping \
+definiscivariabiletesto definisciversion description determinacaratteristicheregistro determinacarattersticheelenco \
+determinanumerotesta dimensione disabilitamenuinterazione distanzabordo distanzabordodestro \
+distanzabordosinistro distanzacima distanzafondo distanzaintestazione distanzamargine \
+distanzamarginedestro distanzamarginesinistro distanzapdp domicilio el \
+elaborablocchi elaborapagina elementi elemento emptylines \
+enumeration etichetta etichette fatto figuraesterna \
+fondo forzablocchi framedtext frazione getnumber \
+giornosettimana griglia headsym hl ignoto \
+immediatebetweenlist immediatetolist impaccato impostaallineamento impostaambientefontdeltesto \
+impostaampiezzariga impostabarrainterazione impostabarrasincronizzazione impostablocchimargine impostablocco \
+impostabloccosezione impostabuffer impostacampi impostacampo impostacapoversi \
+impostacaption impostacaptions impostacima impostaclippling impostacolonne \
+impostacolore impostacolori impostacombinazioni impostacommento impostacommentopagina \
+impostadefinizionenotepdp impostadescrizioni impostadimensionicarta impostaelementi impostaelencazioni \
+impostaelenco impostaelencocombinato impostaenumerazioni impostafigureesterne impostafondo \
+impostafontdeltesto impostaforms impostaformule impostagruppocolonne impostaincorniciato \
+impostainiziatermina impostainmargine impostainstestazione impostainterazione impostainterlinea \
+impostalayout impostalegenda impostalinea impostalineemargine impostalineenere \
+impostalineeriempimento impostalineesottili impostalineetesto impostalingua impostalistariferimenti \
+impostamaiuscole impostamakeup impostamarcatura impostamenuinterazione impostamenzione \
+impostanotepdp impostanumerazione impostanumerazionecapoversi impostanumerazionepagina impostanumerazionerighe \
+impostanumeropagina impostanumerosottopagina impostanumerotesta impostaoggettimobili impostaoggettomobile \
+impostaordinamento impostaoutput impostaparranging impostapdp impostapiustretto \
+impostaposizionamento impostaposizionamentoopposti impostaposizionetesto impostaprofili impostaprogrammi \
+impostapubblicazioni impostapulsanti impostaregistro impostarientro impostariferimento \
+impostarighe impostarigheriempimento impostarigovuoto impostarotazione impostaschermi \
+impostaschermointerazione impostasegnosillabazione impostasetsimboli impostasezione impostasfondi \
+impostasfondo impostasincronizzazione impostasinonimi impostasistema impostasottolinea \
+impostaspaziatura impostaspaziobianco impostaspezzamentooggettomobile impostastrut impostatab \
+impostatabelle impostatabulato impostatavolozza impostatesta impostateste \
+impostatesticima impostatestifondo impostatestiincorniciati impostatestiintestazioni impostatestipdp \
+impostatesto impostatestoetichette impostatestointestazioni impostatestotesti impostatolleranza \
+impostatransizionepagina impostatype impostatyping impostaurl impostavariabiletesto \
+impostaversioni impostazioni in inaltromargine incorniciato \
+incrementanumero indentation indestra ininner iniziaallineamento \
+iniziaambiente iniziabloccomargine iniziacitazione iniziacodifica iniziacolonne \
+iniziacolore iniziacombinazione iniziacomponente iniziacorrezioneriga iniziadocumento \
+iniziafigura iniziaglobale iniziagruppocolonne iniziaimpaccato inizialineamargine \
+inizialineatesto inizialocale iniziamakeup inizianotepdplocali inizianumerazionerighe \
+iniziaopposto iniziaoverview iniziapiustretto iniziaposizionamento iniziaprodotto \
+iniziaprofilo iniziaprogetto iniziaraster iniziariga iniziarighe \
+iniziasetsimboli iniziasfondo iniziasincronizzazione iniziasovrapposizione iniziatabella \
+iniziatabelle iniziatesto iniziaunpacked iniziaversione inlatodestro \
+inlatosinistro inmaframed inmargine inmarginedestro inmarginesinistro \
+inneredgedistance inneredgewidth innermargindistance innermarginwidth inouter \
+inriga insinistra installalingua intorno labeling \
+leg lettera lettere lineamargine lineanera \
+lineasottile lineatesto lineenere lineeriempimento lineesottili \
+lingua linguaprincipale listsymbol livellotesta loadsorts \
+loadsynonyms logcampi lunghezzaelenco maframed mapfontsize \
+mar marcatura marcaversione matematica mediaeval \
+menuinterattivo menzione mese mettielenco mettielencocombinato \
+mettifiancoafianco mettiformula mettiingriglia mettilegenda mettilinea \
+mettiloghi mettinotepdp mettinotepdplocali mettinumeropagina mettiregistro \
+mettisegnalibro mettisottoformula mettiunosullaltro mettivariabiletesto mostraambientefontdeltesto \
+mostracampi mostracolore mostracornice mostrafiguresterne mostrafontdeltesto \
+mostragriglia mostragruppocolori mostraimpostazioni mostralyout mostramakeup \
+mostrasetsimboli mostrastampa mostrastruts mostratavolozza movesidefloat \
+name nascondiblocchi navigating nextsection nientedimensioni \
+nienteelenco nientelineecimafondo nientelineintestazionepdp nientemarcatura nienterientro \
+nientespazio nientespaziobianco nocap nome nomeunita \
+nop nota notapdp notest numberofsubpages \
+numeri numeriromani numeroformula numeropagina numeropaginacompleto \
+numerosottoformula numerotesta numerotestacorrente numerototaledipagine outeredgedistance \
+outeredgewidth outermargindistance outermarginwidth overbar overbars \
+overstrike overstrikes pagedepth pageoffset pagina \
+paragraph paroladestra parolainmargine part passaafontgrezzo \
+ped pedap perlungo placefloat placelistoffloats \
+placelistofsorts placelistofsynonyms placerawlist placereferencelist posizionanumerotesta \
+posizionatesto posizionatestotesta posizione prendibuffer prendimarcatura \
+prodotto progetto programma pubblicazione pulsante \
+pulsantemenu pulsantinterazione punti qualcheriga ran \
+referral referring register reimposta reimpostamarcatura \
+reservefloat resetnumber resettextcontent rientro rif \
+rifai riferimento riferimentopagina riferimentotesto riflessione \
+rigariempimento rigovuoto ruota saltablocchi scala \
+schermo scrividentroelenco scriviinelenco scriviinlistariferimenti scriviinregistro \
+section seeregister segnalibro seguiprofilo seguiversione \
+seguiversioneprofilo selezionablocchi selezionacarta selezionaversione separamarcatura \
+setnumber settext setupanswerarea setupcolumnsetlines setupcolumnsetstart \
+setupfonthandling setupfontsynonym setupindentedtext setupinterlinespace2 setupitemgroup \
+setuplistalternative setupmathalignment setuppaper setupplacement setvariabiletesto \
+sfondo sim simbolo sincronizza sort \
+spazifissi spazio spaziobianco spaziocima spaziodietro \
+spaziofisso spaziofondo spessoreriga spezzaoggettomobile spostaagriglia \
+spostaformula stackcampi startalignment startambiente startbuffer \
+startcitazione startcolore startcolumnmakeup startcolumns startcombination \
+startcomment startcomponenet startdescription startdocument startenumeration \
+startfatto startfigure startfloattext startformula startframedtext \
+starthiding startimpaccato startitemgroup startlegend startline \
+startlineamargine startlineatesto startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
+startmenuinterattivo startnamemakeup startnarrower startopposite startoverlay \
+startoverview startparagraph startpositioning startpostponing startprodotto \
+startprofile startprogetto startregister startsfondo startsymbolset \
+startsynchronization starttable starttables starttabulate starttyping \
+startunpacked startversione stirato stopalignment stopambiente \
+stopbuffer stopcitazione stopcolore stopcolumnmakeup stopcolumns \
+stopcombination stopcomment stopcomponenet stopdescription stopdocument \
+stopenumeration stopfatto stopfigure stopfloattext stopformula \
+stopframedtext stophiding stopimpaccato stopitemgroup stoplegend \
+stopline stoplineamargine stoplineatesto stoplinecorrection stoplinenumbering \
+stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
+stopmarginblock stopmenuinterattivo stopnamemakeup stopnarrower stopopposite \
+stopoverlay stopoverview stopparagraph stoppositioning stoppostponing \
+stopprodotto stopprofile stopprogetto stopsfondo stopsymbolset \
+stopsynchronization stoptable stoptables stoptabulate stoptyping \
+stopunpacked stopversione sub subject subpagenumber \
+subsection subsubject subsubsection subsubsubject synonym \
+tab terminaallineamento terminaambiente terminabloccomargine terminacitazione \
+terminacodifica terminacolonne terminacolore terminacombinazione terminacomponente \
+terminacorrezioneriga terminadocumento terminaglobale terminagruppocolonne terminaimpaccato \
+terminalineamargine terminalineatesto terminalocale terminamakeup terminanotepdplocali \
+terminanumerazionerighe terminaopposto terminaoverview terminapiustretto terminaposizionamento \
+terminaprodotto terminaprofili terminaprogetto terminaraster terminariga \
+terminarighe terminasfondo terminasincronizzazione terminasovrapposizione terminatabella \
+terminatabelle terminatesto terminaunpacked terminaversioni testa \
+testcolumn testoetichetta testoinmargine testoinstestazioni testonotapdp \
+testoriempimento testpage tex tieniblocchi title \
+titoloinmargine tooltip traduci txt typ \
+type typebuffer typefile underbar underbars \
+usaJSscripts usaURL usablocco usacartella usacodifica \
+usacolonnasonoraesterna usacomandi usadocumentoesterno usafiguraesterna usafileesterni \
+usafileesterno usamoduli usamodulo usariferimenti usasimboli \
+usaspecialita usaurl useXMLfilter usedirectory usetypescript \
+usetypescriptfile vaia vaiabox vaiapagina vaigiu \
+valorecolore valoregrigio variabiletesto versione vl
+
+keywordclass.context.fr=\
+CAP Cap Caps Caractere \
+Caracteres Chiffresromains JOURSEMAINE MOIS MOT \
+MOTS Mot Mots Numeros a \
+adaptedisposition affectenumero affectevariabletexte ajustechamp alaligne \
+alapage aligneadroite aligneagauche aligneaumilieu appendix \
+arg arriereplan atleftmargin atrightmargin baha \
+barrecouleur barreinteraction barresynchronisation bas bouton \
+boutonmenu boutonsinteraction but cacheblocs cap \
+caractere caracteres champ changepolicebrute changepolicecorps \
+chapter chem chiffresromains citation citer \
+clip clonechamp colonne comment commentaire \
+comparegroupecouleur comparepalette completecombinedlist completelistoffloats completelistofsorts \
+completelistofsynonyms completenumeropage completeregistre composant composeenalinea \
+concernant convertitnumero copitchamp corrigeespaceblanc couleur \
+couleurgrise coupledocument coupledregister couplemarquage couplepapier \
+coupleregistre crlf cutspace dactylographier dans \
+dansautremarge dansborddroit dansbordgauche dansdroite dansgauche \
+dansmarge dansmargedroite dansmargegauche date datecourante \
+daterecommandation de decouplemarquage decrementenumero definebodyfontDEF \
+definebodyfontREF definecombination definedfont definefontfeature definefonthandling \
+defineframed defineframedtext defineindentedtext defineitemgroup definemathalignment \
+defineplacement definetypeface definicaractere definit definitaccent \
+definitbloc definitblocsection definitbuffer definitcalque definitchamp \
+definitchampprincipal definitcommande definitconversion definitcouleur definitdactylo \
+definitdansmarge definitdemarrestoppe definitdescription definitdisposition definitenumeration \
+definitenvironnementpolicecorps definitetiquette definitflottant definitformatreference definitgroupecouleur \
+definithbox definitjeucolonne definitliste definitlisteimbriquee definitlistereference \
+definitlogo definitmakeup definitmarquage definitmenuinteraction definitnotepdp \
+definitpalette definitparagraphes definitpilechamp definitpolice definitpolicebrute \
+definitpolicecorps definitpositiontexte definitprofil definitprogramme definitreference \
+definitregistre definitregle definitrevetement definitsautdecolonne definitsautdepage \
+definitsection definitsortie definitsouschamp definitstyle definitstylepolice \
+definitsymbole definitsymbolefigure definitsynonymepolice definitsynonymes definittabulation \
+definittaillepapier definittete definittexte definittrametableau definittri \
+definittype definitvariabletexte definitversion definitvide demarrealignement \
+demarrearriereplan demarreblocmarge demarrecitation demarreciter demarrecodage \
+demarrecolonnes demarrecombinaison demarrecompoetroite demarrecomposant demarrecorrectionligne \
+demarrecouleur demarredegroupe demarredocument demarreenvironement demarrefigure \
+demarreglobal demarregroupe demarrejeucolonne demarrejeusymboles demarreligne \
+demarreligneregleetexte demarrelignes demarrelocal demarremakeup demarremargereglee \
+demarrenotespdplocales demarrenumerotationligne demarreopposition demarrepositionnement demarreproduit \
+demarreprofil demarreprojet demarreraster demarrerevetement demarresynchronisation \
+demarretableau demarretableaux demarretexte demarreversion demarrevuedensemble \
+deplaceformule deplacesurgrille description determinecaracteristiqueliste determinecaracteristiquesregistre \
+determinenumerotete dimension distancebord distanceborddroit distancebordgauche \
+distanceentete distanceinf distancemarge distancemargedroite distancemargegauche \
+distancepdp distancesup domicile echelle ecran \
+ecritdansliste ecritdanslistereference ecritentreliste ecritregistre el \
+element elements emptylines enumeration environement \
+espace espaceblanc espacefixe espaceinf espacesfixes \
+espacesup etiquette etiquettes etire fait \
+faitreference fichierdactylo figureexterne forceblocs fraction \
+framed framedtext gardeblocs getnumber grille \
+groupe haut hauteureditionpapier hauteurentete hauteurinf \
+hauteurliste hauteurmakeup hauteurpapier hauteurpdp hauteursup \
+hauteurtexte headsym hl immediatebetweenlist immediatetolist \
+inconnu incrementenumero indentation inframed infull \
+inhibemenuinteraction ininner inmframed inneredgedistance inneredgewidth \
+innermargindistance innermarginwidth inouter installelangue joursemaine \
+labeling labeltexte langue langueprincipale largeurbord \
+largeurborddroit largeurbordgauche largeureditionpapier largeurligne largeurliste \
+largeurmakeup largeurmarge largeurmargedroite largeurmargegauche largeurpapier \
+largeurtexte leg ligneh lignenoire ligneregleetexte \
+lignesnoires listesymbole llongueurliste loadsorts loadsynonyms \
+logchamp mapfontsize mar margereglee marquage \
+marquageversion marquepage mathematique mediaeval menuinteraction \
+mframed mois montrecadre montrechamps montrecouleur \
+montredisposition montreedition montreenvironnementpolicecorps montrefiguresexternes montregrille \
+montregroupecouleur montrejeusymboles montremakeup montrepalette montrepolicecorps \
+montrereglages montrestruts motdroit motmarge movesidefloat \
+name navigating nextsection niveautete nocap \
+nombredesouspages nombretotaldepages nommacro nop note \
+notepdp numeroformule numeropage numeros numerosousformule \
+numerotete numerotetecourant obtientmarquage oriente outeredgedistance \
+outeredgewidth outermargindistance outermarginwidth overbar overbars \
+overstrike overstrikes page pagedepth pagedouble \
+pageoffset paragraph part pasplusdeblocs pasplusdefichiers \
+periodes pilechamp placecoteacote placeflottant placeformule \
+placelegende placelesunsaudessusdesautres placeliste placelisteinmbriquee placelistereference \
+placelistoffloats placelistofsorts placelistofsynonyms placelogos placemarquespages \
+placenotespdp placenotespdplocales placenumeropage placenumerotete placerawlist \
+placeregistre placeregle placesousformule placesurgrille placetextetete \
+placevariabletexte position positionnetexte prendbuffer produit \
+programme projet publication qqpart ran \
+raz razmarquage raznumero recommandation ref \
+refait reference referencepage referencetexte reflete \
+register reglages reglealignement reglearrangement reglearriereplan \
+reglearriereplans reglebarreinteraction reglebarresynchronisation reglebloc regleblocmarge \
+regleblocsection regleboutons reglebuffer reglecapitales reglechamp \
+reglechamps regleclipping reglecolonnes reglecombinaisons reglecommentaire \
+reglecommentairepage reglecompoetroite reglecomposeenalinea reglecouleur reglecouleurs \
+regledactylo regledansmarge regledemarrestoppe regledescriptions regledisposition \
+regleecraninteraction regleecrans regleelements regleencadre regleentete \
+regleenumerations regleenvironnementpolicecorps regleepaisseurligne regleespaceblanc regleespacement \
+regleespacementinterligne reglefiguresexternes regleflottant regleflottants regleformulaires \
+regleformules reglegroupeselements regleinf regleinteraction regleintitule \
+regleintitules reglejeucolonne reglejeusymboles reglelabeltexte reglelangue \
+reglelegende reglelignes reglelignesnoires reglelignesreglestexte regleliste \
+reglelisteimbriquee reglelistereference reglemakeup reglemargereglee reglemarquage \
+reglemarquagehyphenation reglemenuinteraction reglenotepdp reglenumero reglenumeropage \
+reglenumerotation reglenumerotationligne reglenumerotationpage reglenumerotationparagraphe reglenumerotete \
+regleoriente reglepalette reglepapier regleparagraphes reglepdp \
+regleplacementopposition reglepolicecorps reglepositionnement reglepositiontexte regleprofils \
+regleprogrammes reglepublications reglereferencage regleregistre regleregle \
+regleremplitligne regleremplitlignesreglees reglesection regleseparationflottant reglesortie \
+reglesouslignage reglesousnumeropage reglestrut reglesup reglesynchronisation \
+reglesynonymes reglesysteme regletab regletableaux regletabulation \
+regletaillepapier regletete regletetes regletexte regletextesentete \
+regletextesinf regletextespdp regletextessup regletextestexte regletextetete \
+regletolerance regletraitsfins regletransitionspage regletri regletype \
+regleurl reglevariabletexte regleversions remplitchamp remplitligne \
+remplitlignesreglees remplittexte reservefloat resettextcontent retourarriere \
+sansalinea sansdimension sansespace sansespaceblanc sanslignesenteteetpdp \
+sanslignessupetinf sansliste sansmarquage sanstest sauteblocs \
+section seeregister selectionneblocs selectionnepapier selectionneversion \
+sensunite separeflottant settext setupanswerarea setupcolumnsetlines \
+setupcolumnsetstart setupfonthandling setupfontsynonym setupframedtexts setupindentedtext \
+setupinterlinespace2 setupitemgroup setuplistalternative setupmathalignment setupplacement \
+sort sousnumeropage startalignment startarriereplan startbuffer \
+startcitation startcolumnmakeup startcolumns startcombination startcomment \
+startcomposant startcouleur startdescription startdocument startenumeration \
+startenvironement startfait startfigure startfloattext startformula \
+startframedtext startgroupe starthiding startitemgroup startlegend \
+startligneregleetexte startline startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startmakeup startmargereglee \
+startmarginblock startmenuinteraction startnamemakeup startnarrower startopposite \
+startoverlay startoverview startparagraph startpositioning startpostponing \
+startproduit startprofile startprojet startregister startsymbolset \
+startsynchronization starttable starttables starttabulate starttyping \
+startunpacked startversion stopalignment stoparriereplan stopbuffer \
+stopcitation stopcolumnmakeup stopcolumns stopcombination stopcomment \
+stopcompoetroite stopcomposant stopcouleur stopdescription stopdocument \
+stopenumeration stopenvironement stopfait stopfigure stopfloattext \
+stopformula stopframedtext stopgroupe stophiding stopitemgroup \
+stoplegend stopligneregleetexte stopline stoplinecorrection stoplinenumbering \
+stoplines stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
+stopmargereglee stopmarginblock stopmenuinteraction stopnamemakeup stopnarrower \
+stopopposite stopoverlay stopoverview stopparagraph stoppealignement \
+stoppearriereplan stoppeblocmarge stoppecitation stoppecodage stoppecolonnes \
+stoppecombinaison stoppecomposant stoppecorrectionligne stoppecouleur stoppedegroupe \
+stoppedocument stoppeenvironement stoppeglobal stoppegroupe stoppejeucolonne \
+stoppeligne stoppeligneregleetexte stoppelignes stoppelocal stoppemakeup \
+stoppemargereglee stoppenotespdplocales stoppenumerotationligne stoppeopposition stoppepositionnement \
+stoppeproduit stoppeprofil stoppeprojet stopperaster stopperevetement \
+stoppesynchronisation stoppetableau stoppetableaux stoppetexte stoppeversion \
+stoppevuedensemble stoppositioning stoppostponing stopproduit stopprofile \
+stopprojet stopsymbolset stopsynchronization stoptable stoptables \
+stoptabulate stoptyping stopunpacked stopversion sub \
+subject subsection subsubject subsubsection subsubsubject \
+suggestion suivantprofil suivantversion suivantversionprofil sym \
+symbole synchronise synonym tab tapebuffer \
+testcolumn testpage tete tex textemarge \
+textenotepdp textetete title titremarge traduire \
+traiteblocs traitepage traitfin traitsfins txt \
+typ underbar underbars uneligne useXMLfilter \
+usedirectory usetypescript usetypescriptfile utiliseJSscripts utiliseURL \
+utiliseblocs utilisechemin utilisecommandes utilisedocumentexterne utiliseencodage \
+utilisefichierexterne utilisefichiersexternes utilisefigureexterne utilisemodule utilisemodules \
+utilisepsiteaudioexterne utilisereferences utilisespecialites utilisesymboles utiliseurl \
+va vaalaboite vaalapage vaenbas valeurcouleur \
+valeurgris variabletexte version vide vl
+
+keywordclass.context.de=\
+Buchstabe Buchstaben CAP Cap \
+Caps KAP Kap Kaps MONAT \
+Roemischezahlen WOCHENTAG WOERTER WORT Woerter \
+Wort Ziffern abstandlinkerrand abstandoben abstandrechterrand \
+abstandunten amgitterausrichten amgitterneuausrichten appendix arg \
+atleftmargin atrightmargin aufseite ausfuellfeld ausfuelltext \
+ausschnitt bearbeitebloecke bearbeiteseite bedeutung behaltebloecke \
+bei bemerkung benutzekodierung benutzespezielles benutzeverzeichnis \
+beschrifteversion beschriftung bestimmekopfnummer bestimmelistencharakeristika bestimmeregistercharakteristika \
+bildschirm blanko bookmark bottomspace breitelinkerrand \
+breiterechterrand bruch buchstabe buchstaben but \
+bypassblocks cap chapter chem comment \
+completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completepagenumber \
+completeregister coupledregister crlf cutspace datum \
+decrementnumber definebodyfontDEF definebodyfontREF definecolumnbreak definecolumnset \
+definecombination definedfont definefontfeature definefonthandling defineindentedtext \
+defineinmargin defineitemgroup definelayer definelayout definemathalignment \
+defineoutput definepagebreak defineplacement definerawfont definerule \
+defineschriftsynonym definetextposition definetextvariable definetype definetypeface \
+definiereabbsymbol definiereabsaetze definiereabschnitt definiereabschnittsblock definiereakzent \
+definierebefehl definierebeschreibung definierebeschreibungen definierebeschriftung definiereblanko \
+definiereblock definierefarbe definierefarbengruppe definierefeld definierefeldstapel \
+definierefliesstext definierefliesstextumgebung definieregleitobjekt definierehauptfeld definierehbox \
+definiereinteraktionsmenue definierekonversion definierelabel definiereliste definierelogo \
+definieren definierenummerierung definiereoverlay definierepalette definierepapierformat \
+definiereprofil definiereprogramme definierepuffer definierereferenz definierereferenzformat \
+definierereferenzliste definiereregister definiereschrift definiereschriftstil definieresortieren \
+definierestartstop definierestil definieresubfeld definieresymbol definieresynonyme \
+definieretabellenvorlage definieretabulator definieretext definieretippen definiereueberschrift \
+definiereumbruch definiereumrahmt definiereumrahmtertext definiereversion definierezeichen \
+definierezusammengestellteliste description dimension doppelseite doppelseitigespapier \
+drehen duennelinie duennerumriss einezeile einstellungen \
+einziehen emptylines entknuepfebeschriftung enumeration externeabbildung \
+farbbalken farbe farbewert feld feldstapel \
+festesspatium folgeprofil folgeprofilversion folgeversion footnotetext \
+forceblocks format formelnummer framedtext fussnote \
+fusszeileabstand fusszeilenhoehe gefuelltesrechteck gefuelltezeile geg \
+gesamtseitenanzahl gestreckt getnumber gitter graufarbe \
+grauwert haarlinie hauptsprache headsym heutigesdatum \
+heutigeskopfnummer hintergrund hl hoch hoeheoben \
+hoeheunten holebeschriftung holepuffer imlinken imlinkenrand \
+immaumrise immediatebetweenlist immediatetolist imrechten imrechtenrand \
+imumriss in inaktiviereinteraktionsmenue inanderermarginale indentation \
+ininner inlinkermarginale inmarginalie inneredgedistance inneredgewidth \
+innermargindistance innermarginwidth inouter inrechtermarginale installieresprache \
+interaktionsbalken interaktionsknopfe interaktionsmenue inzeile irgendwo \
+its kap keindimension keinebeschriftung keinebloeckemehr \
+keinedateienmehr keinekopfundfusszeilen keineliste keinspatium keintest \
+keinzeilenobenundunten keinzwischenraum kleinerdurchschuss klonierefeld knopf \
+komponente konvertierezahl kopf kopfniveau kopfnummer \
+kopfweite kopfzeilenabstand kopfzeilenhoehe kopierefeld korrigierezwischenraum \
+label labeling labels labeltext leg \
+liniendicke linkemarginalafstand linkemarginalbreite linksbuendig listenbreite \
+listenhoehe listenlaenge listsymbol loadsorts loadsynonyms \
+mapfontsize mar marginalafstand marginalbreite marginallinie \
+marginaltext marginaltitel marginalwort mathematik maumrise \
+mediaeval menueknopf monat moveformula movesidefloat \
+nachunten name navigating nextsection nichteinziehen \
+nocap nokap nop notiz numberofsubpages \
+nummererhoehen outeredgedistance outeredgewidth outermargindistance outermarginwidth \
+overbar overbars overstrike overstrikes pagedepth \
+pageoffset papierbreite papierhoehe paragraph part \
+passelayoutan passendfeld placefloat placeheadnumber placeheadtext \
+placelistoffloats placelistofsorts placelistofsynonyms placepagenumber placerawlist \
+placereferencelist placerule placetextvariable platzierebookmarks platziereformel \
+platzierefussnoten platzierelegende platziereliste platzierelogo platzierelokalefussnoten \
+platzierenebeneinander platziereregister platziereuntereinander platziereunterformel platzierezusammengestellteliste \
+pos position positiontext posten printpapierbreite \
+printpapierhoehe produkt programm projekt publikation \
+punkt ran randabstand randbreite rechteck \
+rechtecke rechtemarginalafstand rechtemarginalbreite rechtsbuendig ref \
+referenz referieren register registrierefelder reservefloat \
+resetnumber resettextcontent roemischezahlen ruecksetzten ruecksetztenbeschriftung \
+rumpfweite satzbreite satzhoehe schreibezumregister schreibezurliste \
+schreibezurreferenzliste schreibezwischenliste section seeregister seite \
+seitenreferenz seitenummer setnumber settext settextvariable \
+setupanswerarea setupcolumnset setupcolumnsetlines setupcolumnsetstart setupfonthandling \
+setupfontsynonym setupforms setupindentedtext setupinterlinespace2 setupitemgroup \
+setuplistalternative setupmathalignment setupnumber setuppaper setupplacement \
+setuprule setupstartstop setupstrut setuptextposition setuptextvariable \
+showsymbolset sort spalte spatium spiegeln \
+sprache startabbildung startalignment startausrichtung startbuffer \
+startcolumnmakeup startcolumns startcolumnset startcombination startcomment \
+startdescription startdocument startdokument startenger startenumeration \
+startfarbe startfigure startfloattext startformula startframedtext \
+startgeg startgegenueber startglobal startgrosserdurchschuss starthiding \
+starthintergrund startinteraktionsmenue startitemgroup startkleinerdurchschuss startkodierung \
+startkombination startkomponente startlegend startline startlinecorrection \
+startlinenumbering startlines startlocal startlocalenvironment startlocalfootnotes \
+startlokal startlokalefussnoten startmakeup startmarginalblock startmarginallinie \
+startmarginblock startnamemakeup startnarrower startopposite startoverlay \
+startoverview startparagraph startpositionieren startpositioning startpostponing \
+startprodukt startprofil startprofile startprojekt startraster \
+startregister startspalten startsymbolset startsynchronisation startsynchronization \
+starttabelle starttabellen starttable starttables starttabulate \
+starttext starttextlinie starttyping startueberblick startumbruch \
+startumgebung startunpacked startversion startzeile startzeilen \
+startzeilenkorrektur startzeilennumerierung startzitat stelleabsaetzeein stelleabsatznummerierungein \
+stelleabschnittein stelleabschnittsblockein stelleanordnenein stelleaufzaehlungenein stelleausgabeein \
+stelleausrichtungein stelleausschnittein stellebeschreibungein stellebeschriftungein stellebilderunterschriftein \
+stellebildunterschriftein stellebindestrichein stelleblankoein stelleblockein stelledrehenein \
+stelleduennerumrissein stelleeinziehenein stelleengerein stelleexterneabbildungenein stellefarbeein \
+stellefarbenein stellefeldein stellefelderin stellefliesstextein stellefliesstextumgebungein \
+stelleformelnein stellefussnotendefinitionein stellefussnotenein stellefusszeileein stellefusszeilentextein \
+stellegefuelltesrechteckein stellegefuelltezeileein stellegegenueberplatzierenein stellegleitobjekteein stellegleitobjektein \
+stellehintergruendeein stellehintergrundein stelleinmarginalieein stelleinteraktionein stelleinteraktionsbalkenein \
+stelleinteraktionsbildschirmein stelleinteraktionsmenueein stelleknopfein stellekombinationein stellekommentarein \
+stellekopfzahlein stellekopfzeileein stellekopfzeilentextein stellelabeltextein stellelayoutein \
+stellelegendeein stellelinienbreiteein stellelisteein stellemarginalblockein stellemarginallinieein \
+stellenobenein stellenummerierungein stellepaletteein stellepapierformatein stelleplatziegeteiltegleitobjekt \
+stellepositionierenein stellepostenein stelleprofilein stelleprogrammein stellepublikationein \
+stellepufferein stellerasterein stellerechteckein stellereferenzierenein stellereferenzlisteein \
+stelleregisterein stelleseitenkommentarein stelleseitennummerein stelleseitennummeriernungein stelleseitenuebergangein \
+stellesortierenein stellespaltenein stellespatiumein stellespracheein stellesymbolsetein \
+stellesynchronisationein stellesynchronisationsbalkenein stellesynonymein stellesystemein stelletabein \
+stelletabellenein stelletabulatorein stelletextein stelletextobenein stelletexttexteein \
+stelletextumrissein stelletextuntenein stelletipein stelletippenein stelletoleranzein \
+stelleueberschriftein stelleueberschriftenein stelleueberschrifttextein stelleumbruchein stelleumrahmtein \
+stelleumrahmtetexteein stelleuntenein stelleunterseitennummerein stelleunterstreichenein stelleurlein \
+stelleversalienein stelleversionein stellezeilenabstandein stellezeilenein stellezeilennumerierungein \
+stellezitierenein stellezusammengestelltelisteein stellezwischenraumein stopalignment stopausrichtung \
+stopbuffer stopcolumnmakeup stopcolumns stopcolumnset stopcombination \
+stopcomment stopdescription stopdocument stopdokument stopenger \
+stopenumeration stopfarbe stopfigure stopfloattext stopformula \
+stopframedtext stopgeg stopgegenueber stopglobal stopgrosserdurchschuss \
+stophiding stophintergrund stopinteraktionsmenue stopitemgroup stopkleinerdurchschuss \
+stopkodierung stopkombination stopkomponente stoplegend stopline \
+stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment \
+stoplocalfootnotes stoplokal stoplokalefussnoten stopmakeup stopmarginalblock \
+stopmarginallinie stopmarginblock stopnamemakeup stopnarrower stopopposite \
+stopoverlay stopoverview stopparagraph stoppositionieren stoppositioning \
+stoppostponing stopprodukt stopprofil stopprofile stopprojekt \
+stopraster stopspalten stopsymbolset stopsynchronisation stopsynchronization \
+stoptabelle stoptabellen stoptable stoptables stoptabulate \
+stoptext stoptextlinie stoptyping stopueberblick stopumbruch \
+stopumgebung stopunpacked stopversion stopzeile stopzeilen \
+stopzeilenkorrektur stopzeilennumerierung stopzitat sub subject \
+subpagenumber subsection subsubject subsubsection subsubsubject \
+switchtorawfont sym symbol synchronisationsbalken synchronisieren \
+synonym tab teilegleitobjekt testcolumn testpage \
+tex textbreite texthoehe textlinie textreferenz \
+textvariable tief tiho tip tippedatei \
+tippen tippepuffer title tooltip txt \
+ueber ueberschrifttext uebersetzten umgebung umrahmt \
+unbekant underbar underbars unterformelnummer useXMLfilter \
+usedirectory usetypescript usetypescriptfile verbergebloecke vergleichefarbengruppe \
+vergleichepalette verknuepfebeschriftung verknuepfedokument verknuepfregister version \
+verweis verweisdatum verwendeJSscript verwendeURL verwendebefehl \
+verwendebloecke verwendeexteresdokument verwendeexterneabbildung verwendeexternedatei verwendeexternedateien \
+verwendeexternestonstueck verwendemodul verwendemodule verwendereferenzen verwendesymbole \
+verwendeurl vl volleswort von waehlebloeckeaus \
+waehlepapieraus waehleversionaus wechselezumfliesstext wiederholen wochentag \
+wohnort wortrechts zeigedruck zeigeeinstellungen zeigeexterneabbildungen \
+zeigefarbe zeigefarbengruppe zeigefelder zeigefliesstext zeigefliesstextumgebung \
+zeigegitter zeigelayout zeigepalette zeigerahmen zeigestruts \
+zeigeumbruch zentriert ziffern zitat zitieren \
+zu zurbox zurseite zwischenraum
+
+keywordclass.context.cs=\
+CAP Cap Caps Cisla \
+KAP Kap Kaps MESIC Rimskecislice \
+SLOVA SLOVO Slova Slovo VSEDNIDEN \
+Znak Znaky aktualnicislonadpisu aktualnidatum appendix \
+arg atleftmargin atrightmargin barevnalista barva \
+bilemisto bottomspace bublinkovanapoveda bydliste bypassblocks \
+cap celkovypocetstran cernalinka cernelinky chapter \
+chem cisla cislonadpisu cislopodrovnice cislorovnice \
+cislostrany citace citovat comment completecombinedlist \
+completelistoffloats completelistofsorts completelistofsynonyms completepagenumber completeregister \
+coupledregister crlf cutspace datum decrementnumber \
+definebodyfontDEF definebodyfontREF definecolumnbreak definecolumnset definecombination \
+definedfont definefontfeature definefonthandling defineindentedtext defineinmargin \
+defineitemgroup definelayer definelayout definemathalignment definepagebreak \
+defineplacement definerawfont definerule definetextposition definetextvariable \
+definetype definetypeface definuj definujakcent definujbarvu \
+definujblok definujbloksekce definujbuffer definujfont definujformatodkazu \
+definujhbox definujhlavnipole definujinterakcnimenu definujkombinovanyseznam definujkonverzi \
+definujlogo definujnadpis definujobrazeksymbol definujodkaz definujodstavce \
+definujopis definujoramovani definujoramovanytext definujpaletu definujplvouciobjekt \
+definujpodpole definujpole definujpopis definujpopisek definujprekryv \
+definujpreskok definujprikaz definujprofil definujprogram definujprostredizakladnihofontu \
+definujrejstrik definujsablonutabulky definujsekci definujseznam definujseznamodkazu \
+definujskupinubarev definujstartstop definujstyl definujstylfontu definujsymbol \
+definujsynonumumfontu definujsynonyma definujtabelaci definujtext definujtrideni \
+definujupravu definujvelikostpapiru definujverzi definujvycet definujvystup \
+definujzakladnifont definujzasobnikpoli definujznaceni definujznak delkaseznamu \
+description dodrzujprofil dodrzujverzi dodrzujverziprofilu dvoustrannypapir \
+emptylines enumeration externiobraz fakt footnotetext \
+forceblocks framedtext getnumber headsym hl \
+hlavnijazyk hlavniuroven hodnotabarvy hodnotasedi immediatebetweenlist \
+immediatetolist indentation ininner inneredgedistance inneredgewidth \
+innermargindistance innermarginwidth inouter instalacejazyka interakcnilista \
+interakcnitlacitka interaktivnimenu jazyk jdidolu jdina \
+jdinabox jdinastranu jmeno kap klonujpole \
+komponenta konvertujcislo kopirujpole korekcebilehomista labeling \
+leg listsymbol loadsorts loadsynonyms maoramovani \
+mapfontsize marginalnilinka marginalninadpis marginalnislovo marginalnitext \
+matematika mazaramovani mediaeval meritko mesic \
+mezera moveformula movesidefloat mrizka nadpis \
+nadruhyokraj nalevo nalevyokraj name naokraj \
+napravo napravyokraj nastavbarvu nastavbarvy nastavbilamista \
+nastavblok nastavbloksekce nastavbuffer nastavcernelinky nastavcislonadpisu \
+nastavcislostrany nastavcislovani nastavcislovaniodstavcu nastavcislovaniradku nastavcislovanistran \
+nastavcitaci nastavdefinicipoznamekpodcarou nastavdeleniplvoucichobjektu nastavdelitko nastavdolnitexty \
+nastaveni nastavexterniobrazy nastavhorejsek nastavhornitexty nastavinterakci \
+nastavinterakcnilistu nastavinterakcnimenu nastavinterakcniobrazovku nastavjazyk nastavkapitalky \
+nastavkombinovanyseznam nastavkomentar nastavkomentarstrany nastavlegendu nastavmarginalie \
+nastavmarginalniblok nastavmarginalnilinky nastavmeziradkovoumezeru nastavnadpis nastavnadpisy \
+nastavodkazovani nastavodsazovani nastavodstavce nastavopis nastavoramovanetexty \
+nastavoramovani nastavorez nastavotoceni nastavpaletu nastavplvouciobjekt \
+nastavplvouciobjekty nastavpodcislostrany nastavpodtrzeni nastavpole nastavpolozky \
+nastavpopisek nastavpopisky nastavpopisy nastavpozadi nastavpoznamkypodcarou \
+nastavprechodstrany nastavpreskok nastavprofily nastavprogramy nastavprostredizakladnihofontu \
+nastavpublikace nastavradkovani nastavradky nastavrastr nastavrejstrik \
+nastavrovnice nastavsadusymbolu nastavsekci nastavseznam nastavseznamodkazu \
+nastavsirkucary nastavsloupce nastavspodek nastavspojeni nastavsynchronizaci \
+nastavsynchronizacnilistu nastavsynonyma nastavsystem nastavtab nastavtabelaci \
+nastavtabulky nastavtenkelinky nastavtext nastavtexthlavicky nastavtextovelinky \
+nastavtextpopisku nastavtexttexty nastavtextyupati nastavtextyzahlavi nastavtlacitka \
+nastavtoleranci nastavtrideni nastavtype nastavumisteniprotejsku nastavumistovani \
+nastavupati nastavupravu nastavurl nastavusporadani nastavvelikostpapiru \
+nastavverze nastavvsechnapole nastavvycty nastavvyplnovelinky nastavvyplnoveradky \
+nastavvystup nastavvzhled nastavzahlavi nastavzakladnifont nastavzarovnani \
+nastavznaceni nastavzuzeni nastrane navigating nejakyradek \
+nekde nextsection neznamo nivy nizky \
+nocap nokap nop numberofsubpages obrazovka \
+odkaz odkaznadatum odkaznastranu odkaznatext odkazujici \
+odsazenishora odsazenizleva odsazovani okr opakovat \
+opis opissoubor oramovani oref orez \
+otocit outeredgedistance outeredgewidth outermargindistance outermarginwidth \
+overbar overbars overstrike overstrikes oznaceni \
+oznacverzi pagedepth pageoffset paragraph parovastrana \
+part pis placefloat placeheadnumber placeheadtext \
+placelistoffloats placelistofsorts placelistofsynonyms placepagenumber placerawlist \
+placereferencelist placerule placetextvariable plnezneni pol \
+pole polozka polozky popisky poppisek \
+porovnejpaletu porovnejskupinubarev positiontext pozadi pozice \
+poznamka poznamkapodcarou pref prelozit premistinamrizku \
+prepninazakladnifont preskoc prizpusobivepole prizpusobvzhled produkt \
+program projekt propojeneznaceni propojenydokument propojenyrejstrik \
+prostredi publikace ran ref register \
+reservefloat reset resetnumber resettextcontent resetznaceni \
+rimskecislice rozdelplvouciobjekt rozmer rozpojeneznaceni roztazene \
+schovejbloky section sedabarva seeregister setnumber \
+settextcontent settextvariable setupanswerarea setupcolumnset setupcolumnsetlines \
+setupcolumnsetstart setupfonthandling setupfontsynonym setupforms setupindentedtext \
+setupinterlinespace2 setupitemgroup setuplistalternative setupmathalignment setupnumber \
+setuppaper setupplacement setuprule setupstartstop setupstrut \
+setuptextposition setuptextvariable sirkalevehookraje sirkalevemarginalie sirkamarginalie \
+sirkaokraje sirkapapiru sirkapravehookraje sirkapravemarginalie sirkasazby \
+sirkaseznamu sirkatextu sirkatiskpapiru sloupec slovovpravo \
+sort spodek stanovcharakteristickuseznamu stanovcislonadpisu startalignment \
+startbarva startbuffer startcislovaniradku startcitace startcolumnmakeup \
+startcolumns startcolumnset startcombination startcomment startdescription \
+startdocument startdokument startenumeration startfakt startfigure \
+startfloattext startformula startframedtext startglobalni starthiding \
+startinteraktivnimenu startitemgroup startkodovani startkomponenta startkorekceradku \
+startlegend startline startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startlokalni startlokalnipoznamkypodcarou \
+startmakeup startmarginalniblok startmarginalnilinka startmarginblock startnamemakeup \
+startnarrower startnezhustene startobraz startopposite startoverlay \
+startoverview startparagraph startpositioning startpostponing startpozadi \
+startprehled startprekryv startprodukt startprofil startprofile \
+startprojekt startprostredi startprotejsek startradek startradky \
+startrastr startregister startsadasymbolu startsloupce startspojeni \
+startsymbolset startsynchronizace startsynchronization starttable starttables \
+starttabulate starttabulka starttabulky starttext starttextovalinka \
+starttyping startumistovani startunpacked startuprava startverze \
+startzarovnavani startzhustene startzuzeni stopalignment stopbarva \
+stopbuffer stopcislovaniradku stopcitace stopcolumnmakeup stopcolumns \
+stopcolumnset stopcombination stopcomment stopdescription stopdocument \
+stopdokument stopenumeration stopfakt stopfigure stopfloattext \
+stopformula stopframedtext stopglobalni stophiding stopinteraktivnimenu \
+stopitemgroup stopkodovani stopkomponenta stopkorekceradku stoplegend \
+stopline stoplinecorrection stoplinenumbering stoplines stoplocal \
+stoplocalenvironment stoplocalfootnotes stoplokalni stoplokalnipoznamkypodcarou stopmakeup \
+stopmarginalniblok stopmarginalnilinka stopmarginblock stopnamemakeup stopnarrower \
+stopnezhustene stopopposite stopoverlay stopoverview stopparagraph \
+stoppositioning stoppostponing stoppozadi stopprehled stopprekryv \
+stopprodukt stopprofil stopprofile stopprojekt stopprostredi \
+stopprotejsek stopradek stopradky stoprastr stopsloupce \
+stopspojeni stopsymbolset stopsynchronizace stopsynchronization stoptable \
+stoptables stoptabulate stoptabulka stoptabulky stoptext \
+stoptextovalinka stoptyping stopumistovani stopunpacked stopuprava \
+stopverze stopzarovnavani stopzhustene stopzuzeni strana \
+sub subject subpagenumber subsection subsubject \
+subsubsection subsubsubject switchtorawfont sym symbol \
+synchronizacnilista synchronizovat synonym tab tecky \
+tenkalinka tenkelinky testcolumn testpage tex \
+texthlavicky textovalinka textpopisku textvariable title \
+tlacitko tlacitkomenu tloustkacary tref tvrdamezera \
+tvrdemezery txt typebuffer ukazbarvu ukazexterniobrazy \
+ukazmrizku ukaznastaveni ukazpaletu ukazpodpery ukazpole \
+ukazpostredizakladnihofontu ukazramecek ukazsadusymbolu ukazskupinubarev ukazupravu \
+ukazvytisk ukazvzhled ukazzakladnifont umistikombinovanyseznam umistilegendu \
+umistiloga umistilokalnipoznamkypodcarou umistinadsebe umistinamrizku umistipodrovnici \
+umistipoznamkypodcarou umistirejstrik umistirovnici umistiseznam umistivedlesebe \
+umistizalozky underbar underbars urcicharakteristikurejstriku useXMLfilter \
+usedirectory usetypescript usetypescriptfile uzijJSscripts uzijURL \
+uzijadresar uzijbloky uzijexternidokument uzijexterniobraz uzijexternisoubor \
+uzijexternisoubory uzijexternizvuk uzijkodovani uzijmodul uzijmoduly \
+uzijodkazy uzijprikazy uzijspeciality uzijsymbol uzijurl \
+verze vl vlasovalinka vlevo vpravo \
+vradku vsedniden vyberbloky vyberpapir vyberverzi \
+vyplnenytext vyplnovelinky vyplnovepole vyplnovyradek vyskahorejsku \
+vyskapapiru vyskasazby vyskaseznamu vyskaspodku vyskatextu \
+vyskatiskpapiru vyskaupati vyskazahlavi vysoky vyznam \
+vzdalenosthorejsku vzdalenostlevehookraje vzdalenostlevemarginalie vzdalenostmarginalie vzdalenostokraje \
+vzdalenostpravehookraje vzdalenostpravemarginalie vzdalenostspodku vzdalenostupati vzdalenostzahlavi \
+zablokujinterakcnimenu zachovejbloky zadnamezera zadnebilemisto zadnedalsibloky \
+zadnedalsisoubory zadnehorniadolniradky zadneodsazovani zadnezahlaviaupati zadneznaceni \
+zadnyrozmer zadnyseznam zadnytest zalozka zapisdorejstriku \
+zapisdoseznamu zapisdoseznamuodkazu zapismeziseznam zaramovani zarovnanonastred \
+zarovnanovlevo zarovnanovpravo zasobnikpoli zaznamovepole zhustene \
+ziskejbuffer ziskejznaceni zlomek znaceni znak \
+znaky zpracujbloky zpracujstranu zrcadlit zref \
+zvysujicicislo
+
+keywordclass.context.en=\
+CAP Cap Caps Character \
+Characters MONTH Numbers Romannumerals WEEKDAY \
+WORD WORDS Word Words about \
+adaptlayout adding appendix arg at \
+atleftmargin atpage atrightmargin background backspace \
+blackrule blackrules blank bookmark bottomdistance \
+bottomheight bottomspace but button bypassblocks \
+cap chapter character characters chem \
+clip clonefield color colorbar colorvalue \
+column comment comparecolorgroup comparepalet completecombinedlist \
+completelistoffloats completelistofsorts completelistofsynonyms completepagenumber completeregister \
+component convertnumber copyfield correctwhitespace coupledocument \
+coupledregister couplemarking couplepage couplepaper coupleregister \
+crlf currentdate currentheadnumber cutspace date \
+decouplemarking decrementnumber define defineaccent defineblank \
+defineblock definebodyfont definebodyfontDEF definebodyfontREF definebodyfontenvironment \
+definebuffer definecharacter definecolor definecolorgroup definecolumnbreak \
+definecolumnset definecombination definecombinedlist definecommand defineconversion \
+definedescription definedfont defineenumeration definefield definefieldstack \
+definefiguresymbol definefloat definefont definefontfeature definefonthandling \
+definefontstyle definefontsynonym defineframed defineframedtext definehbox \
+definehead defineindentedtext defineinmargin defineinteractionmenu defineitemgroup \
+definelabel definelayer definelayout definelist definelogo \
+definemainfield definemakeup definemarking definemathalignment defineoutput \
+defineoverlay definepagebreak definepalet definepapersize defineparagraphs \
+defineplacement defineprofile defineprogram definerawfont definereference \
+definereferenceformat definereferencelist defineregister definerule definesection \
+definesectionblock definesorting definestartstop definestyle definesubfield \
+definesymbol definesynonyms definetabletemplate definetabulate definetext \
+definetextposition definetextvariable definetype definetypeface definetyping \
+defineversion description determineheadnumber determinelistcharacteristics determineregistercharacteristics \
+dimension disableinteractionmenu domicile donttest edgedistance \
+edgewidth emptylines enumeration environment externalfigure \
+fact field fieldstack fillinfield fillinline \
+fillinrules fillintext fitfield fixedspace fixedspaces \
+followprofile followprofileversion followversion footerdistance footerheight \
+footnote footnotetext forceblocks formulanumber fraction \
+framed framedtext from getbuffer getmarking \
+getnumber godown goto gotobox gotopage \
+graycolor greyvalue grid hairline head \
+headerdistance headerheight headlevel headnumber headsym \
+headtext hideblocks high hl immediatebetweenlist \
+immediatetolist in incrementnumber indentation indenting \
+inframed infull ininner inleft inleftedge \
+inleftmargin inline inmaframed inmargin inneredgedistance \
+inneredgewidth innermargindistance innermarginwidth inothermargin inouter \
+inright inrightedge inrightmargin installlanguage interactionbar \
+interactionbuttons interactionmenu item items its \
+keepblocks label labeling labels labeltext \
+language leftaligned leftedgedistance leftedgewidth leftmargindistance \
+leftmarginwidth leg linethickness listheight listlength \
+listsymbol listwidth loadsorts loadsynonyms logfields \
+lohi low maframed mainlanguage makeupheight \
+makeupwidth mapfontsize mar margindistance marginrule \
+margintext margintitle marginwidth marginword marking \
+markversion mathematics mediaeval menubutton midaligned \
+mirror month moveformula moveongrid movesidefloat \
+name navigating nextsection nocap nodimension \
+noheaderandfooterlines noindenting nolist nomarking nomoreblocks \
+nomorefiles nop nospace note notopandbottomlines \
+nowhitespace numberofsubpages numbers outeredgedistance outeredgewidth \
+outermargindistance outermarginwidth overbar overbars overstrike \
+overstrikes packed page pagedepth pagenumber \
+pageoffset pagereference paperheight paperwidth paragraph \
+part periods placebookmarks placecombinedlist placefloat \
+placefootnotes placeformula placeheadnumber placeheadtext placelegend \
+placelist placelistoffloats placelistofsorts placelistofsynonyms placelocalfootnotes \
+placelogos placeongrid placeontopofeachother placepagenumber placerawlist \
+placereferencelist placeregister placerule placesidebyside placesubformula \
+placetextvariable position positiontext printpaperheight printpaperwidth \
+processblocks processpage product program project \
+publication quotation quote ran redo \
+ref reference referral referraldate referring \
+register remark reservefloat reset resetmarking \
+resetnumber resettextcontent rightaligned rightedgedistance rightedgewidth \
+rightmargindistance rightmarginwidth romannumerals rotate scale \
+screen section seeregister selectblocks selectpaper \
+selectversion setnumber settextcontent settextvariable setupalign \
+setupanswerarea setuparranging setupbackground setupbackgrounds setupblackrules \
+setupblank setupblock setupbodyfont setupbodyfontenvironment setupbottom \
+setupbottomtexts setupbuffer setupbuttons setupcapitals setupcaption \
+setupcaptions setupclipping setupcolor setupcolors setupcolumns \
+setupcolumnset setupcolumnsetlines setupcolumnsetstart setupcombinations setupcombinedlist \
+setupcomment setupdescriptions setupenumerations setupexternalfigures setupfield \
+setupfields setupfillinlines setupfillinrules setupfloat setupfloats \
+setupfloatsplitting setupfonthandling setupfontsynonym setupfooter setupfootertexts \
+setupfootnotedefinition setupfootnotes setupforms setupformulae setupframed \
+setupframedtexts setuphead setupheader setupheadertexts setupheadnumber \
+setupheads setupheadtext setuphyphenmark setupindentedtext setupindenting \
+setupinmargin setupinteraction setupinteractionbar setupinteractionmenu setupinteractionscreen \
+setupinterlinespace setupinterlinespace2 setupitemgroup setupitemizations setupitems \
+setuplabeltext setuplanguage setuplayout setuplegend setuplinenumbering \
+setuplines setuplinewidth setuplist setuplistalternative setupmakeup \
+setupmarginblocks setupmarginrules setupmarking setupmathalignment setupnarrower \
+setupnumber setupnumbering setupoppositeplacing setupoutput setuppagecomment \
+setuppagenumber setuppagenumbering setuppagetransitions setuppalet setuppaper \
+setuppapersize setupparagraphnumbering setupparagraphs setupplacement setuppositioning \
+setupprofiles setupprograms setuppublications setupquote setupreferencelist \
+setupreferencing setupregister setuprotate setuprule setups \
+setupscreens setupsection setupsectionblock setupsorting setupspacing \
+setupstartstop setupstrut setupsubpagenumber setupsymbolset setupsynchronization \
+setupsynchronizationbar setupsynonyms setupsystem setuptab setuptables \
+setuptabulate setuptext setuptextposition setuptextrules setuptexttexts \
+setuptextvariable setupthinrules setuptolerance setuptop setuptoptexts \
+setuptype setuptyping setupunderbar setupurl setupversions \
+setupwhitespace showbodyfont showbodyfontenvironment showcolor showcolorgroup \
+showexternalfigures showfields showframe showgrid showlayout \
+showmakeup showpalet showprint showsetups showstruts \
+showsymbolset someline somewhere sort space \
+splitfloat startalignment startbackground startbuffer startcoding \
+startcolor startcolumnmakeup startcolumns startcolumnset startcombination \
+startcomment startcomponent startdescription startdocument startenumeration \
+startenvironment startfact startfigure startfloattext startformula \
+startframedtext startglobal starthiding startinteractionmenu startitemgroup \
+startlegend startline startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
+startmarginrule startnamemakeup startnarrower startopposite startoverlay \
+startoverview startpacked startparagraph startpositioning startpostponing \
+startproduct startprofile startproject startquotation startraster \
+startregister startsymbolset startsynchronization starttable starttables \
+starttabulate starttext starttextrule starttyping startunpacked \
+startversion stopalignment stopbackground stopbuffer stopcoding \
+stopcolor stopcolumnmakeup stopcolumns stopcolumnset stopcombination \
+stopcomment stopcomponent stopdescription stopdocument stopenumeration \
+stopenvironment stopfact stopfigure stopfloattext stopformula \
+stopframedtext stopglobal stophiding stopinteractionmenu stopitemgroup \
+stoplegend stopline stoplinecorrection stoplinenumbering stoplines \
+stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock \
+stopmarginrule stopnamemakeup stopnarrower stopopposite stopoverlay \
+stopoverview stoppacked stopparagraph stoppositioning stoppostponing \
+stopproduct stopprofile stopproject stopquotation stopraster \
+stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
+stoptext stoptextrule stoptyping stopunpacked stopversion \
+stretched sub subformulanumber subject subpagenumber \
+subsection subsubject subsubsection subsubsubject switchtobodyfont \
+switchtorawfont sym symbol synchronizationbar synchronize \
+synonym tab testcolumn testpage tex \
+textheight textreference textrule textvariable textwidth \
+thinrule thinrules title tooltip topdistance \
+topheight topspace totalnumberofpages translate txt \
+typ type typebuffer typefile underbar \
+underbars unitmeaning unknown useJSscripts useURL \
+useXMLfilter useblocks usecommands usedirectory useencoding \
+useexternaldocument useexternalfigure useexternalfile useexternalfiles useexternalsoundtrack \
+usemodule usemodules usereferences usespecials usesymbols \
+usetypescript usetypescriptfile useurl version vl \
+weekday whitespace wordright writebetweenlist writetolist \
+writetoreferencelist writetoregister
+
+keywordclass.context.ro=\
+CAP CUVANT CUVINTE Cap \
+Caps Cuvant Cuvinte KAP Kap \
+Kaps LUNA Litera Litere Numere \
+Numereromane ZIDINSAPTAMANA adapteazaaspect adubuffer adumarcaje \
+afiseazaaspect afiseazacampuri afiseazaculoare afiseazafiguriexterne afiseazafonttext \
+afiseazagrid afiseazagrupculoare afiseazamakeup afiseazamediufonttext afiseazapaleta \
+afiseazarama afiseazasetari afiseazasetsimboluri afiseazastruts afiseazatiparire \
+aliniat aliniatcentru aliniatdreapta aliniatstanga appendix \
+arg ascundeblocuri atleftmargin atrightmargin baraculoare \
+barainteractiune barasincronizare blanc but butoaneinteractiune \
+buton butonmeniu camp campumplere cap \
+chapter chem citat clip cloneazacamp \
+coloana comment comparagrupculoare comparapaleta completeazanumarpagina \
+completecombinedlist completelistoffloats completelistofsorts completelistofsynonyms completeregister \
+componenta convertestenumar copiazacamp corecteazaspatiualb coupledregister \
+crlf culoare culoaregri cupleazadocument cupleazamarcaje \
+cupleazaregistru cutspace cuvantdreapta cuvantmarginal data \
+datacurenta datareferit decrementnumber decupleazamarcaje definebodyfontDEF \
+definebodyfontREF definecolumnbreak definecolumnset definecombination definedfont \
+definefontfeature definefonthandling defineindentedtext defineinmargin defineitemgroup \
+definelayer definelayout definemathalignment definepagebreak defineplacement \
+defineste definesteaccent definesteantet definesteblanc definestebloc \
+definesteblocsectiune definestebuffer definestecamp definestecampprincipal definestecaracter \
+definestecomanda definesteconversie definesteculoare definestedescriere definestedimensiunehartie \
+definesteenumerare definesteeticheta definestefloat definestefont definestefontraw \
+definestefonttext definesteformatreferinte definestegrupculori definestehbox definesteinconjurare \
+definestelista definestelistacombinata definestelistareferinte definestelogo definestemakeup \
+definestemarcaje definestemediulfonttext definestemeniuinteractiune definesteoutput definesteoverlay \
+definestepaleta definesteparagraf definestepozitietext definesteprofil definesteprogram \
+definestereferinte definesteregistru definesterigla definestesablontabel definestesectiune \
+definestesimbol definestesimbolfigura definestesinonim definestesinonimfont definestesortare \
+definestestartstop definestestil definestestilfont definestestivacampuri definestesubcamp \
+definestetabulatori definestetext definestetexteinconjurate definestetextinconjurat definestetyping \
+definestevariabilatext definesteversiune definetype definetypeface description \
+despre determinacaracteristicilelistei determinacaracteristiciregistru determinanumartitlu dezactiveazameniuinteractiune \
+dimensiune din distantaantet distantacolt distantacoltdreapta \
+distantacoltstanga distantajos distantamargine distantamarginedreapta distantamarginestanga \
+distantasubsol distantasus domiciliu dute dutebox \
+dutepagina ecran el element emptylines \
+enumeration eticheta etichete fact faraaliniat \
+faradimensiune farafisiere faraliniiantetsisubsol faraliniisussijos faralista \
+faramarcaje faraspatiu faraspatiualb figuraexterna firdepar \
+folosesteURL folosestebloc folosestecodificarea folosestecomenzi folosestedirector \
+folosestedocumentextern folosestefiguraexterna folosestefisiereexterne folosestefisierextern folosestemodul \
+folosestemodule folosestemuzicaexterna folosestereferinte folosestescriptJS folosestesimboluri \
+folosestespeciale folosesteurl footnotetext forteazablocuri fractie \
+framed framedtext fundal gatablocuri getnumber \
+grid grosimelinie hartiedubla headsym hl \
+immediatebetweenlist immediatetolist impachetat impartefloat in \
+inalt inaltamargine inaltimeantet inaltimehartie inaltimehartieimprimanta \
+inaltimejos inaltimelista inaltimemakeup inaltimesubsol inaltimesus \
+inaltimetext indentation indreapta inframed ininner \
+injos inlinie inmaframed inmargineadreapta inmargineastanga \
+inneredgedistance inneredgewidth innermargindistance innermarginwidth inouter \
+inparteadreapta inparteastanga instalarelimba instanga intins \
+jos jossus kap la labeling \
+lapagina latimecoltdreapta latimecoltstanga latimecolturi latimehartie \
+latimehartieimprimanta latimelista latimemakeup latimemargine latimemarginedreapta \
+latimemarginestanga latimetext leg limba limbaprincipala \
+liniemargine linieneagra liniesubtire linieumplere liniinegre \
+liniisubtiri listsymbol litera litere loadsorts \
+loadsynonyms logcampuri luna lungimelista maframed \
+mapfontsize mar marcaje marcheazaversiune marginal \
+matematica mediaeval mediu meniuinteractiune minicitat \
+moveformula movesidefloat mutapegrid name navigating \
+necunoscut nextsection niveltitlu nocap nokap \
+nop nota notasubsol numarformula numarincrement \
+numarpagina numarsubformula numartitlu numartitlucurent numartotalpagini \
+numberofsubpages nume numere numereromane numeunitate \
+nutesta olinie outeredgedistance outeredgewidth outermargindistance \
+outermarginwidth overbar overbars overstrike overstrikes \
+pagedepth pageoffset pagina paginadubla paragraph \
+part pastreazablocuri pelung placefloat placeheadnumber \
+placeheadtext placelistoffloats placelistofsorts placelistofsynonyms placerawlist \
+placereferencelist plaseazapegrid plaseazasemnecarte potrivestecamp pozitie \
+pozitietext proceseazabloc proceseazapagina produs program \
+proiect publicatie puncte punedeasuprafiecareia punefatainfata \
+puneformula punelegenda punelista punelistacombinata punelogouri \
+punenotesubsol punenotesubsollocale punenumarpagina puneregistru punerigla \
+punesubformula punevariabilatext ran ref refa \
+referinta referintapagina referintatext referit referring \
+reflexie register remarca reservefloat reset \
+reseteazamarcaje resetnumber resettextcontent riglatext rigleumplere \
+roteste saripesteblocuri scala scriebuffer scrieinlista \
+scrieinlistareferinte scrieinregistru scrieintreliste section seeregister \
+selecteazablocuri selecteazahartie selecteazaversiune semncarte setarebarasincronizare \
+setareitemization setarelimba setareoutput setarepozitie setaresincronizare \
+setari seteazaaliniat seteazaalinierea seteazaantet seteazaaranjareapag \
+seteazaaspect seteazabarainteractiune seteazablanc seteazabloc seteazablocsectiune \
+seteazablocurimarginale seteazabuffer seteazabutoane seteazacamp seteazacampuri \
+seteazaclipping seteazacoloane seteazacombinari seteazacomentariu seteazacomentariupagina \
+seteazaculoare seteazaculori seteazadefinireanotasubsol seteazadescriere seteazadimensiunihartie \
+seteazaecrane seteazaecraninteractiune seteazaelemente seteazaenumerare seteazafiguriexterne \
+seteazafloat seteazafloats seteazafonttext seteazaformulare seteazaformule \
+seteazafundal seteazafundaluri seteazagrosimelinie seteazaimpartireafloat seteazainconjurat \
+seteazaingust seteazainteractiunea seteazajos seteazalegenda seteazalegendele \
+seteazaliniesilabe seteazaliniesubtire seteazalinii seteazaliniimargine seteazaliniinegre \
+seteazaliniiumplere seteazalista seteazalistacombinata seteazalistareferinte seteazamajuscule \
+seteazamakeup seteazamarcaje seteazamarginal seteazamediulfonttext seteazameniuinteractiune \
+seteazaminicitat seteazanotasubsol seteazanumarpagina seteazanumarsubpagina seteazanumartitlu \
+seteazanumerotare seteazanumerotarelinii seteazanumerotarepagina seteazanumerotareparagrafe seteazapaleta \
+seteazaparagrafe seteazaplasareaopozita seteazapozitietext seteazaprofile seteazaprograme \
+seteazapublicatii seteazareferinte seteazaregistru seteazarigla seteazarigletext \
+seteazarigleumplere seteazarotare seteazasectiune seteazasimbol seteazasinonime \
+seteazasistem seteazasortare seteazaspatiu seteazaspatiualb seteazaspatiuinterliniar \
+seteazastrut seteazasublinie seteazasubsol seteazasus seteazatab \
+seteazatabele seteazatabulatori seteazatext seteazatexteantet seteazatextejos \
+seteazatextesubsol seteazatextesus seteazatextetext seteazatexteticheta seteazatexttitlu \
+seteazatitlu seteazatitluri seteazatoleranta seteazatranzitiepagina seteazatype \
+seteazatyping seteazaurl seteazavariabilatext seteazaversiuni setnumber \
+settextcontent setupanswerarea setupcolumnset setupcolumnsetlines setupcolumnsetstart \
+setupfonthandling setupfontsynonym setupindentedtext setupinterlinespace2 setupitemgroup \
+setuplistalternative setupmathalignment setupnumber setuppaper setupplacement \
+setupstartstop setvariabilatext sim simbol sincronizeaza \
+sort spatiifixate spatiu spatiualb spatiufixat \
+spatiujos spatiuspate spatiusus startalignment startaliniere \
+startblocmarginal startbuffer startcitat startcodificare startcoloane \
+startcolumnmakeup startcolumns startcolumnset startcombinare startcombination \
+startcomment startcomponenta startcorectielinie startculoare startdescription \
+startdocument startenumeration startfact startfigura startfigure \
+startfloattext startformula startframedtext startfundal startglobal \
+starthiding startimpachetat startingust startitemgroup startlegend \
+startline startlinecorrection startlinenumbering startlines startlinie \
+startliniemargine startlinii startlocal startlocalenvironment startlocalfootnotes \
+startmakeup startmarginblock startmediu startmeniuinteractiune startnamemakeup \
+startnarrower startneimpachetat startnotesubsollocale startnumerotarelinii startopozit \
+startopposite startoverlay startoverview startparagraph startpositioning \
+startpostponing startpozitionare startprodus startprofil startprofile \
+startproiect startraster startregister startriglatext startsetsimboluri \
+startsincronizare startsymbolset startsynchronization starttabel starttabele \
+starttable starttables starttabulate starttext starttyping \
+startunpacked startversiune stivacampuri stopalignment stopaliniere \
+stopblobal stopblocmarginal stopbuffer stopcitat stopcodificare \
+stopcoloane stopcolumnmakeup stopcolumns stopcolumnset stopcombinare \
+stopcombination stopcomment stopcomponenta stopcorectielinie stopculoare \
+stopdescription stopdocument stopenumeration stopfact stopfigure \
+stopfloattext stopformula stopframedtext stopfundal stophiding \
+stopimpachetat stopingust stopitemgroup stoplegend stopline \
+stoplinecorrection stoplinenumbering stoplines stoplinie stopliniemargine \
+stoplinii stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup \
+stopmarginblock stopmediu stopmeniuinteractiune stopnamemakeup stopnarrower \
+stopneimpachetat stopnotesubsollocale stopnumerotarelinii stopopozit stopopposite \
+stopoverlay stopoverview stopparagraph stoppositioning stoppostponing \
+stoppozitionare stopprodus stopprofil stopprofile stopproiect \
+stopraster stopriglatext stopsincronizare stopsymbolset stopsynchronization \
+stoptabel stoptabele stoptable stoptables stoptabulate \
+stoptext stoptyping stopunpacked stopversiune sub \
+subject subpagenumber subsection subsubject subsubsection \
+subsubsubject synonym tab testcolumn testpage \
+tex texteticheta textmarginal texttitlu textumplere \
+title titlu titlumarginal tooltip traduce \
+trecilafontraw trecilafonttext txt typ type \
+typefile underbar underbars undeva urmeazaprofil \
+urmeazaversiune urmeazaversiuneprofil useXMLfilter usedirectory usetypescript \
+usetypescriptfile valoareculoare valoaregri variabilatext versiune \
+vl zidinsaptamana
+
+keywordclass.context.pe=\
+CAP Cap Caps Character \
+Characters MONTH Numbers Romannumerals WEEKDAY \
+WORD WORDS Word Words appendix \
+cap chapter chem comment completecombinedlist \
+completelistoffloats completelistofsorts completelistofsynonyms coupledregister crlf \
+definebodyfontDEF definebodyfontREF definedfont definefontfeature definefonthandling \
+defineindentedtext definetypeface description enumeration framedtext \
+indentation inmframed its labeling loadsorts \
+loadsynonyms mapfontsize mediaeval mframed name \
+nextsection nocap overbar overbars overstrike \
+overstrikes paragraph part placelistoffloats placelistofsorts \
+placelistofsynonyms ran register reservefloat resettextcontent \
+section seeregister setupanswerarea setupcapitals setupfonthandling \
+setupfontsynonym setupindentedtext setupinterlinespace2 setuplistalternative setupurl \
+sort startalignment startbuffer startcolumns startcombination \
+startcomment startdescription startdocument startenumeration startfigure \
+startfloattext startformula startframedtext starthiding startitemgroup \
+startlegend startline startlinecorrection startlinenumbering startlines \
+startlocal startlocalenvironment startlocalfootnotes startmakeup startmarginblock \
+startnamemakeup startnarrower startopposite startoverlay startoverview \
+startparagraph startpositioning startpostponing startprofile startraster \
+startregister startsymbolset startsynchronization starttable starttables \
+starttabulate starttyping startunpacked startتولید startحقیقت \
+startخط‌حاشیه startخط‌متن startرنگ startÙشرده startمحیط \
+startمنوی‌پانل startمولÙÙ‡ startنسخه startنقل‌قول startپروژه \
+startپس‌زمینه stopalignment stopbuffer stopcolumns stopcombination \
+stopcomment stopdescription stopdocument stopenumeration stopfigure \
+stopfloattext stopformula stopframedtext stophiding stopitemgroup \
+stoplegend stopline stoplinecorrection stoplinenumbering stoplines \
+stoplocal stoplocalenvironment stoplocalfootnotes stopmakeup stopmarginblock \
+stopnamemakeup stopnarrower stopopposite stopoverlay stopoverview \
+stopparagraph stoppositioning stoppostponing stopprofile stopraster \
+stopsymbolset stopsynchronization stoptable stoptables stoptabulate \
+stoptyping stopunpacked stopتولید stopحقیقت stopخط‌حاشیه \
+stopخط‌متن stopرنگ stopÙشرده stopمحیط stopمنوی‌پانل \
+stopمولÙÙ‡ stopنسخه stopنقل‌قول stopپروژه stopپس‌زمینه \
+sub subject subsection subsubject subsubsection \
+subsubsubject synonym title tooltip txt \
+typ underbar underbars useJSscripts useURL \
+useXMLfilter usedirectory useurl Ø¢Ùست‌صÙحه آیتم \
+آیتمها آینه اجباربلوکها ارتÙاع‌آرایش ارتÙاع‌بالا \
+ارتÙاع‌برگ ارتÙاع‌ته‌برگ ارتÙاع‌خط ارتÙاع‌سربرگ ارتÙاع‌متن \
+ارتÙاع‌پایین از ازکارانداختن‌منوی‌پانل استÙاده‌بلوکها استÙاده‌دستخط‌تایپ \
+استÙاده‌رمزینه استÙاده‌شکل‌خارجی استÙاده‌Ùرمانها استÙاده‌قطعه‌موزیک‌خارجی استÙاده‌مدول \
+استÙاده‌مدولها استÙاده‌مرجعها استÙاده‌مسیر استÙاده‌نمادها استÙاده‌نوشتارخارجی \
+استÙاده‌ویژگیها استÙاده‌پرونده‌خارجی استÙاده‌پرونده‌دستخط‌تایپ استÙاده‌پرونده‌های‌خارجی اعدادلاتین \
+اÙزودن اما امتحان‌نکن انتخاب‌برگ انتخاب‌بلوکها \
+انتخاب‌نسخه انتقال‌به‌توری انتقال‌Ùرمول انتقال‌کنار‌شناور انجام‌دوباره \
+بارگذاریها بارگذاری‌آرایش بارگذاری‌آیتمها بارگذاری‌ارجاع بارگذاری‌اندازه‌برگ \
+بارگذاری‌باریکتر بارگذاری‌باÙر بارگذاری‌بالا بارگذاری‌بخش بارگذاری‌بردباری \
+بارگذاری‌برنامه‌ها بارگذاری‌برگ بارگذاری‌بست بارگذاری‌بلوک بارگذاری‌بلوکهای‌حاشیه \
+بارگذاری‌بلوک‌بخش بارگذاری‌تایپ بارگذاری‌تایپ‌کردن بارگذاری‌تب بارگذاری‌ترتیب \
+بارگذاری‌ترکیب‌ها بارگذاری‌تطابق بارگذاری‌تعریÙ‌پانوشت بارگذاری‌تنظیم بارگذاری‌تنظیم‌ریاضی \
+بارگذاری‌ته‌برگ بارگذاری‌تورÙتگی بارگذاری‌توضیح بارگذاری‌توضیح‌صÙحه بارگذاری‌ثبت \
+بارگذاری‌جانشانی بارگذاری‌جدولها بارگذاری‌جدول‌بندی بارگذاری‌خالی بارگذاری‌خروجی \
+بارگذاری‌خط بارگذاری‌خطها بارگذاری‌خطهای‌حاشیه بارگذاری‌خطهای‌سیاه بارگذاری‌خطهای‌متن \
+بارگذاری‌خطهای‌مجموعه‌ستون بارگذاری‌خطها‌ی‌نازک بارگذاری‌درج‌درخطها بارگذاری‌درج‌مخال٠بارگذاری‌درون‌حاشیه \
+بارگذاری‌دوران بارگذاری‌دکمه‌ها بارگذاری‌راهنما بارگذاری‌رنگ بارگذاری‌رنگها \
+بارگذاری‌زبان بارگذاری‌ستونها بارگذاری‌سر بارگذاری‌سربرگ بارگذاری‌سرها \
+بارگذاری‌سیستم بارگذاری‌شرح بارگذاری‌شرحها بارگذاری‌شروع‌مجموعه‌ستون بارگذاری‌شروع‌پایان \
+بارگذاری‌شماره بارگذاری‌شماره‌زیرصÙحه بارگذاری‌شماره‌سر بارگذاری‌شماره‌صÙحه بارگذاری‌شماره‌گذاری \
+بارگذاری‌شماره‌گذاریها بارگذاری‌شماره‌گذاری‌صÙحه بارگذاری‌شماره‌گذاری‌پاراگرا٠بارگذاری‌شماره‌‌گذاری‌خط بارگذاری‌شناور \
+بارگذاری‌شناورها بارگذاری‌شکاÙتن‌شناورها بارگذاری‌شکلهای‌خارجی بارگذاری‌طرح بارگذاری‌طرح‌بندی \
+بارگذاری‌عرض‌خط بارگذاری‌Ùاصله‌بین‌خط بارگذاری‌Ùرمولها بارگذاری‌Ùضای‌سÙید بارگذاری‌Ùضا‌گذاری \
+بارگذاری‌قالبی بارگذاری‌قلم‌متن بارگذاری‌لوح بارگذاری‌لیست بارگذاری‌لیست‌ترکیبی \
+بارگذاری‌لیست‌مرجع بارگذاری‌مترادÙها بارگذاری‌متغیر‌متن بارگذاری‌متن بارگذاری‌متنهای‌بالا \
+بارگذاری‌متن‌سر بارگذاری‌متن‌سربرگ بارگذاری‌متن‌قالبی بارگذاری‌متن‌متنها بارگذاری‌متن‌پانوشت \
+بارگذاری‌متن‌پایین بارگذاری‌مجموعه‌ستون بارگذاری‌مجموعه‌نماد بارگذاری‌محیط‌قلم‌متن بارگذاری‌منوی‌پانل \
+بارگذاری‌مکان‌متن بارگذاری‌مکان‌گذاری بارگذاری‌میدان بارگذاری‌میدانها بارگذاری‌میله‌تطابق \
+بارگذاری‌میله‌زیر بارگذاری‌میله‌پانل بارگذاری‌نسخه‌ها بارگذاری‌نشانه‌شکستن بارگذاری‌نشانه‌گذاری \
+بارگذاری‌نشرها بارگذاری‌نقل بارگذاری‌پاراگراÙها بارگذاری‌پانل بارگذاری‌پانوشتها \
+بارگذاری‌پایین بارگذاری‌پرده‌ها بارگذاری‌پرده‌پانل بارگذاری‌پروÙایلها بارگذاری‌پرکردن‌خطها \
+بارگذاری‌پس‌زمینه بارگذاری‌پس‌زمینه‌ها بارگذاری‌چیدن بارگذاری‌گذارصÙحه بارگذاری‌گروههای‌آیتم \
+بارگذاری‌گروه‌آیتم بازنشانی بازنشانی‌شماره بازنشانی‌متن بازنشانی‌نشانه‌گذاری \
+باگذاری‌متن‌برچسب بدون‌بعد بدون‌بلوکهای‌بیشتر بدون‌تورÙتگی بدون‌خط‌بالاوپایین \
+بدون‌خط‌سروته‌برگ بدون‌Ùایلهای‌بیشتر بدون‌Ùضا بدون‌Ùضای‌سÙید بدون‌لیست \
+بدون‌نشانه‌گذاری برنامه بروبه بروبه‌جعبه بروبه‌صÙحه \
+بروپایین برچسب برچسبها بعد بلند \
+بلوکهای‌پردازش بلوکها‌پنهان بنویس‌بین‌لیست بنویس‌درثبت بنویس‌درلیست‌مرجع \
+بنویس‌در‌لیست تاریخ تاریخ‌جاری تاریخ‌رجوع تایپ \
+تایپ‌باÙر تایپ‌پرونده تب ترجمه تطابق \
+تعری٠تعریÙ‌آرایش تعریÙ‌آرم تعریÙ‌الگوی‌جدول تعریÙ‌اندازه‌برگ \
+تعریÙ‌باÙر تعریÙ‌بخش تعریÙ‌برنامه تعریÙ‌برچسب تعریÙ‌بلوک \
+تعریÙ‌بلوک‌بخش تعریÙ‌تایپ تعریÙ‌تایپ‌کردن تعریÙ‌تبدیل تعریÙ‌ترتیب \
+تعریÙ‌ترکیب تعریÙ‌تنظیم‌ریاضی تعریÙ‌توده‌میدان تعریÙ‌ثبت تعریÙ‌جانشانی \
+تعریÙ‌جدول‌بندی تعریÙ‌جعبه‌‌اÙÙ‚ÛŒ تعریÙ‌حر٠تعریÙ‌خالی تعریÙ‌خروجی \
+تعریÙ‌خط‌حائل تعریÙ‌درون‌حاشیه تعریÙ‌رنگ تعریÙ‌زیرمیدان تعریÙ‌سبک \
+تعریÙ‌سبک‌قلم تعریÙ‌سر تعریÙ‌شرح تعریÙ‌شروع‌پایان تعریÙ‌شماره‌بندی \
+تعریÙ‌شمایل‌مرجع تعریÙ‌شناور تعریÙ‌شکستن‌ستون تعریÙ‌شکست‌صÙحه تعریÙ‌طرح‌بندی \
+تعریÙ‌Ùرمان تعریÙ‌قالبی تعریÙ‌قلم تعریÙ‌قلم‌خام تعریÙ‌قلم‌متن \
+تعریÙ‌لایه تعریÙ‌لهجه تعریÙ‌لوح تعریÙ‌لیست تعریÙ‌لیست‌ترکیبی \
+تعریÙ‌لیست‌مرجع تعریÙ‌مترادÙها تعریÙ‌مترادÙ‌قلم تعریÙ‌متغیرمتن تعریÙ‌متن \
+تعریÙ‌متن‌قالبی تعریÙ‌مجموعه‌ستون تعریÙ‌محیط‌قلم‌بدنه تعریÙ‌مرجع تعریÙ‌منوی‌پانل \
+تعریÙ‌مکان‌متن تعریÙ‌میدان تعریÙ‌میدان‌اصلی تعریÙ‌نسخه تعریÙ‌نشانه‌گذاری \
+تعریÙ‌نماد تعریÙ‌نمادشکل تعریÙ‌پاراگراÙها تعریÙ‌پروÙایل تعریÙ‌پوشش \
+تعریÙ‌گروه‌آیتم تعریÙ‌گروه‌رنگ تعیین‌شماره تعیین‌شماره‌سر تعیین‌متغیر‌متن \
+تعیین‌محتوای‌متن تعیین‌مشخصات‌ثبت تعیین‌مشخصات‌لیست تغییربه‌قلم‌بدنه تغییربه‌قلم‌خام \
+تنظیم‌راست تنظیم‌طرح‌بندی تنظیم‌وسط توجه تورÙتگی \
+توری تولید تک ثبت‌زوج ثبت‌کامل \
+جداسازی‌نشانه‌گذاری حاش حر٠حرÙها Ø­Ùظ‌بلوکها \
+حقیقت خالی خطهای‌سیاه خطهای‌نازک خطها‌خالی \
+خط‌حاشیه خط‌سیاه خط‌متن خط‌مو خط‌نازک \
+خ‌ا خ‌ع در درج‌آرمها درج‌ثبت \
+درج‌خط درج‌درخط درج‌درخطها درج‌درمتن درج‌درمیدان \
+درج‌در‌بالای‌یکدیگر درج‌در‌توری درج‌راهنما درج‌زیرÙرمول درج‌شماره‌سر \
+درج‌شماره‌صÙحه درج‌شناور درج‌Ùرمول درج‌لیست درج‌لیست‌خام \
+درج‌لیست‌مختلط درج‌لیست‌مرجع درج‌متغیرمتن درج‌متن‌سر درج‌پانوشتها \
+درج‌پانوشتهای‌موضعی درج‌چوب‌خط درج‌کنار‌به‌کنار درحاشیه درحاشیه‌دیگر \
+درحاشیه‌راست درحاشیه‌چپ درخارجی درخط درداخلی \
+درراست درصÙحه درقالبی درلبه‌راست درلبه‌چپ \
+درمورد درون درپر درچپ دریاÙت‌باÙر \
+دریاÙت‌شماره دریاÙت‌نشانه دوران دکمه دکمه‌منو \
+دکمه‌پانل رج رجوع رنگ رنگ‌خاکستری \
+روزهÙته ریاضی زبان زبان‌اصلی ستون \
+ستون‌امتحان سر سرپوش‌کوچک‌نه شروع‌آرایش شروع‌آرایش‌ستون \
+شروع‌باریکتر شروع‌بازبینی شروع‌بلوک‌حاشیه شروع‌ترکیب شروع‌تصحیح‌خط \
+شروع‌تطابق شروع‌تنظیم شروع‌تولید شروع‌جدول شروع‌جدولها \
+شروع‌خط شروع‌خطها شروع‌خط‌حاشیه شروع‌خط‌متن شروع‌رنگ \
+شروع‌ستونها شروع‌سراسری شروع‌شماره‌گذاری‌خط شروع‌شکل شروع‌غیر‌Ùشرده \
+شروع‌Ùشرده شروع‌متن شروع‌مجموعه‌ستون شروع‌مجموعه‌نماد شروع‌محیط \
+شروع‌مخال٠شروع‌موضعی شروع‌مولÙÙ‡ شروع‌مکان‌گذاری شروع‌نسخه \
+شروع‌نقل‌قول شروع‌نوشتار شروع‌پانوشتهای‌موضعی شروع‌پروÙایل شروع‌پروژه \
+شروع‌پس‌زمینه شروع‌پوشش شروع‌کد شماره‌اÙزایش شماره‌زیرصÙحه \
+شماره‌زیرÙرمول شماره‌سر شماره‌سرجاری شماره‌صÙحه شماره‌صÙحه‌کامل \
+شماره‌Ùرمول شماره‌مبدل شماره‌ها شماره‌کاهش شماره‌کل‌صÙحه‌ها \
+شکاÙتن‌شناور شکل‌خارجی صÙحه صÙحه‌تست صÙحه‌زوج \
+صÙحه‌پردازش طول‌لیست عبوربلوکها عرض‌آرایش عرض‌برگ \
+عرض‌حاشیه عرض‌حاشیه‌خارجی عرض‌حاشیه‌داخلی عرض‌حاشیه‌راست عرض‌حاشیه‌چپ \
+عرض‌خط عرض‌لبه عرض‌لبه‌خارجی عرض‌لبه‌داخلی عرض‌لبه‌راست \
+عرض‌لبه‌چپ عرض‌لیست عرض‌متن عمق‌صÙحه عنوان‌حاشیه \
+Ùاصله‌بالا Ùاصله‌ته‌برگ Ùاصله‌حاشیه Ùاصله‌حاشیه‌خارجی Ùاصله‌حاشیه‌داخلی \
+Ùاصله‌حاشیه‌راست Ùاصله‌حاشیه‌چپ Ùاصله‌سربرگ Ùاصله‌لبه Ùاصله‌لبه‌خارجی \
+Ùاصله‌لبه‌داخلی Ùاصله‌لبه‌راست Ùاصله‌لبه‌چپ Ùاصله‌پایین Ùاصله‌پشت \
+Ùشرده Ùضا Ùضاهای‌ثابت Ùضای‌بالا Ùضای‌برش \
+Ùضای‌ثابت Ùضای‌سÙید Ùضای‌سÙیدصحیح Ùضای‌پایین Ùوری‌به‌لیست \
+Ùوری‌بین‌لیست قالبی لوح‌مقایسه ماه متغیر متن \
+متن‌برچسب متن‌حاشیه متن‌سر متن‌پانوشت محیط \
+مراجعه مرجع مرجع‌صÙحه مرجع‌متن مرحله‌سر \
+مسکن معنی‌واحد مقایسه‌گروه‌رنگ مقدارخاکستری مقداررنگ \
+مقیاس منÙÛŒ منوی‌پانل مولÙÙ‡ مکان \
+مکان‌متن میدان میدانهای‌گزارش میدان‌شبیه‌سازی میدان‌پشته \
+میدان‌کپی میله‌تطابق میله‌رنگ میله‌پانل ناشناس \
+نام‌ماکرو نسخه نسخه‌نشانه نشانه‌گذاری نشانه‌گذاری‌زوج \
+نشر نصب‌زبان نقطه‌ها نقل نقل‌قول \
+نم نماد نمادسر نمادلیست نمایش‌آرایش \
+نمایش‌بارگذاریها نمایش‌بستها نمایش‌توری نمایش‌رنگ نمایش‌شکلهای‌خارجی \
+نمایش‌طرح‌بندی نمایش‌قالب نمایش‌قلم‌بدنه نمایش‌لوح نمایش‌مجموعه‌علامت \
+نمایش‌محیط‌قلم‌بدنه نمایش‌میدانها نمایش‌چاپ نمایش‌گروه‌رنگ نوشتارزوج \
+هدایت پا پابا پانوشت پایان‌آرایش \
+پایان‌آرایش‌ستون پایان‌بازبینی پایان‌بلوک‌حاشیه پایان‌ترکیب پایان‌تصحیح‌خط \
+پایان‌تطابق پایان‌تنظیم پایان‌تولید پایان‌جدول پایان‌جدولها \
+پایان‌خط پایان‌خطها پایان‌خط‌حاشیه پایان‌خط‌متن پایان‌رنگ \
+پایان‌ستونها پایان‌سراسری پایان‌شماره‌گذاری‌خط پایان‌غیرÙشرده پایان‌Ùشرده \
+پایان‌متن پایان‌مجموعه‌ستون پایان‌محیط پایان‌مخال٠پایان‌موضعی \
+پایان‌مولÙÙ‡ پایان‌مکان‌گذاری پایان‌نازکتر پایان‌نسخه پایان‌نقل‌قول \
+پایان‌نوشتار پایان‌پانوشتهای‌موضعی پایان‌پروÙایل پایان‌پروژه پایان‌پس‌زمینه \
+پایان‌پوشش پایان‌کد پایین پرده پروژه \
+پرکردن‌میدان پس‌زمینه پیروی‌نسخه پیروی‌نسخه‌پروÙایل پیروی‌پروÙایل \
+چاپ‌ارتÙاع‌برگ چاپ‌عرض‌برگ چوبخط چپ‌چین کاغذزوج \
+کسر کشیده کلمه‌حاشیه کلمه‌راست گیره \
+یادداشت یک‌جا یک‌خط
+
+keywordclass.context.nl=\
+CAP Cap Caps Cijfers \
+KAP Kap Kaps Letter Letters \
+MAAND Romeins WEEKDAG WOORD WOORDEN \
+Woord Woorden aantalsubpaginas about achtergrond \
+appendix arg bepaalkopnummer bepaallijstkenmerken bepaalregisterkenmerken \
+betekenis binnenmargeafstand binnenmargebreedte binnenrandafstand binnenrandbreedte \
+blanko blokje blokjes blokkeerinteractiemenu bodemwit \
+bookmark bovenafstand bovenhoogte breuk buitenmargeafstand \
+buitenmargebreedte buitenrandafstand buitenrandbreedte but button \
+cap chapter chem cijfers citaat \
+citeer clip comment completecombinedlist completelistoffloats \
+completelistofsorts completelistofsynonyms converteernummer copieerveld corrigeerwitruimte \
+coupledregister crlf datum definebodyfontDEF definebodyfontREF \
+definedfont definefontfeature definefonthandling definerawfont definetypeface \
+definieer definieeraccent definieeralineas definieerbeeldmerk definieerblanko \
+definieerblok definieerbuffer definieercombinatie definieercommando definieerconversie \
+definieerfiguursymbool definieerfont definieerfontstijl definieerfontsynoniem definieerhbox \
+definieerhoofdveld definieeringesprongentext definieerinmarge definieerinteractiemenu definieeritemgroep \
+definieerkadertekst definieerkarakter definieerkleur definieerkleurgroep definieerkolomgroep \
+definieerkolomovergang definieerkop definieerkorps definieerkorpsomgeving definieerlayer \
+definieerlayout definieerletter definieerlijn definieerlijst definieermarkering \
+definieeromlijnd definieeropmaak definieeroverlay definieerpaginaovergang definieerpalet \
+definieerpapierformaat definieerplaats definieerplaatsblok definieerprofiel definieerprogramma \
+definieerreferentie definieerreferentieformaat definieerreferentielijst definieerregister definieersamengesteldelijst \
+definieersectie definieersectieblok definieersorteren definieerstartstop definieersubveld \
+definieersymbool definieersynoniemen definieertabelvorm definieertabulatie definieertekst \
+definieertekstpositie definieertekstvariabele definieertype definieertypen definieeruitvoer \
+definieerveld definieerveldstapel definieerversie definieerwiskundeuitlijnen description \
+dimensie directnaarlijst directtussenlijst doordefinieren doorlabelen \
+doornummeren dunnelijn dunnelijnen eenregel enumeration \
+ergens externfiguur forceerblokken formulenummer framedtext \
+gebruikJSscripts gebruikURL gebruikXMLfilter gebruikblokken gebruikcommandos \
+gebruikexterndocument gebruikexternefile gebruikexternefiles gebruikexternfiguur gebruikexterngeluidsfragment \
+gebruikgebied gebruikmodule gebruikmodules gebruikreferenties gebruikspecials \
+gebruiksymbolen gebruiktypescript gebruiktypescriptfile gebruikurl geenblokkenmeer \
+geenbovenenonderregels geendimensie geenfilesmeer geenhoofdenvoetregels geenlijst \
+geenmarkering geenspatie geentest geenwitruimte geg \
+grijskleur grijswaarde haalbuffer haalmarkering haalnummer \
+haarlijn handhaafblokken herhaal hl hoofdafstand \
+hoofdhoogte hoofdtaal hoog huidigedatum huidigekopnummer \
+in inanderemarge inbinnen inbuiten indentation \
+inlijnd inlinker inlinkermarge inlinkerrand inmarge \
+inrechter inrechtermarge inrechterrand inregel inspringen \
+installeertaal instellingen interactiebalk interactiebuttons interactiemenu \
+invullijnen invulregel invultekst invulveld inwilijnd \
+items its kantlijn kap kenmerk \
+kenmerkdatum kentekstvariabeletoe kleur kleurenbalk kleurwaarde \
+kloonveld kolom kop kopniveau kopnummer \
+koppeldocument koppelmarkering koppelpagina koppelpapier koppelregister \
+kopsym koptekst kopwit laag label \
+labeling labels labeltekst laho leg \
+legeregels letter letters lijndikte lijstbreedte \
+lijsthoogte lijstlengte lijstsymbool linkermargeafstand linkermargebreedte \
+linkerrandafstand linkerrandbreedte loadsorts loadsynonyms maand \
+mapfontsize mar margeafstand margebreedte margetekst \
+margetitel margewoord markeer markeerversie mediaeval \
+menubutton naam naar naarbox naarpagina \
+name navigerend nextsection nietinspringen nocap \
+nokap noot nop omgeving omlaag \
+omlijnd onbekend onderafstand onderdeel onderhoogte \
+ontkoppelmarkering op opelkaar oplinkermarge oppagina \
+oprechtermarge overbar overbars overstrike overstrikes \
+pagina paginadiepte paginanummer paginaoffset paginareferentie \
+papierbreedte papierhoogte paragraph part paslayoutaan \
+passeerblokken passendveld plaatsbeeldmerken plaatsbookmarks plaatsformule \
+plaatskopnummer plaatskoptekst plaatslegenda plaatslijn plaatslijst \
+plaatslokalevoetnoten plaatsnaastelkaar plaatsonderelkaar plaatsopgrid plaatspaginanummer \
+plaatsplaatsblok plaatsreferentielijst plaatsregister plaatsruwelijst plaatssamengesteldelijst \
+plaatssubformule plaatstekstvariabele plaatsvoetnoten placelistoffloats placelistofsorts \
+placelistofsynonyms positioneer positioneertekst printpapierbreedte printpapierhoogte \
+produkt programma projekt publicatie punten \
+ran randafstand randbreedte rechtermargeafstand rechtermargebreedte \
+rechterrandafstand rechterrandbreedte ref refereer referentie \
+regellinks regelmidden regelrechts register registreervelden \
+reservefloat reset resetmarkering resetnummer resettekstinhoud \
+resettextcontent romeins rooster roteer rugwit \
+schaal scherm schrijfnaarlijst schrijfnaarreferentielijst schrijfnaarregister \
+schrijftussenlijst section seeregister selecteerblokken selecteerpapier \
+selecteerversie setnummer setupfonthandling setupfontsynonym setupinterlinespace2 \
+setuplistalternative snijwit som sort spatie \
+spiegel splitsplaatsblok startachtergrond startalignment startbuffer \
+startcitaat startcodering startcolumns startcombinatie startcombination \
+startcomment startdescription startdocument startenumeration startfigure \
+startfiguur startfloattext startformula startframedtext startgeg \
+startglobaal starthiding startinteractiemenu startitemgroup startkantlijn \
+startkleur startkolomgroep startkolommen startkolomopmaak startlegend \
+startline startlinecorrection startlinenumbering startlines startlocal \
+startlocalenvironment startlocalfootnotes startlokaal startlokalevoetnoten startmakeup \
+startmargeblok startmarginblock startnaast startnamemakeup startnarrower \
+startomgeving startonderdeel startopelkaar startopmaak startopposite \
+startoverlay startoverview startoverzicht startparagraph startpositioneren \
+startpositioning startpostponing startprodukt startprofiel startprofile \
+startprojekt startraster startregel startregelcorrectie startregelnummeren \
+startregels startregister startsmaller startsymbolset startsymboolset \
+startsynchronisatie startsynchronization starttabel starttabellen starttable \
+starttables starttabulate starttekst starttekstlijn starttyping \
+startuitlijnen startunpacked startvanelkaar startversie stelachtergrondenin \
+stelachtergrondin stelalineasin stelantwoordgebiedin stelarrangerenin stelblankoin \
+stelblokin stelblokjesin stelblokkopjein stelblokkopjesin stelbovenin \
+stelboventekstenin stelbufferin stelbuttonsin stelciterenin stelclipin \
+stelcombinatiesin stelcommentaarin steldoordefinierenin steldoornummerenin steldunnelijnenin \
+stelexternefigurenin stelformulesin stelformulierenin stelhoofdin stelhoofdtekstenin \
+stelingesprongentextin stelinmargein stelinspringenin stelinteractiebalkin stelinteractiein \
+stelinteractiemenuin stelinteractieschermin stelinterliniein stelinvullijnenin stelinvulregelsin \
+stelitemgroepin stelitemsin stelkadertekstenin stelkantlijnin stelkapitalenin \
+stelkleurenin stelkleurin stelkolomgroepin stelkolomgroepregelsin stelkolomgroepstartin \
+stelkolommenin stelkopin stelkopnummerin stelkoppeltekenin stelkoppenin \
+stelkoptekstin stelkorpsin stelkorpsomgevingin stellabeltekstin stellayoutin \
+stellegendain stellijndiktein stellijnin stellijstin stelmargeblokkenin \
+stelmarkeringin stelnaastplaatsenin stelnummerenin stelnummerin stelomlijndin \
+stelonderin stelonderstrepenin stelondertekstenin stelopmaakin stelopsommingenin \
+stelpaginacommentaarin stelpaginanummerin stelpaginanummeringin stelpaginaovergangenin stelpaletin \
+stelpapierformaatin stelpapierin stelparagraafnummerenin stelplaatsblokin stelplaatsblokkenin \
+stelplaatsbloksplitsenin stelplaatsin stelpositionerenin stelprofielenin stelprogrammasin \
+stelpublicatiesin stelrastersin stelreferentielijstin stelrefererenin stelregelnummerenin \
+stelregelsin stelregisterin stelroterenin stelsamengesteldelijstin stelsectieblokin \
+stelsectiein stelsmallerin stelsorterenin stelspatieringin stelstartstopin \
+stelstrutin stelsubpaginanummerin stelsymboolsetin stelsynchronisatiebalkin stelsynchronisatiein \
+stelsynoniemenin stelsysteemin steltaalin steltabellenin steltabin \
+steltabulatiein steltekstin steltekstinhoudin steltekstlijnenin steltekstpositiein \
+stelteksttekstenin steltekstvariabelein steltolerantiein steltypein steltypenin \
+steluitlijnenin steluitvoerin stelurlin stelveldenin stelveldin \
+stelversiesin stelvoetin stelvoetnootdefinitiein stelvoetnotenin stelvoettekstenin \
+stelwiskundeuitlijnenin stelwitruimtein stopachtergrond stopalignment stopbuffer \
+stopcitaat stopcodering stopcolumns stopcombinatie stopcombination \
+stopcomment stopdescription stopdocument stopenumeration stopfigure \
+stopfloattext stopformula stopframedtext stopgeg stopglobaal \
+stophiding stopinteractiemenu stopitemgroup stopkantlijn stopkleur \
+stopkolomgroep stopkolommen stopkolomopmaak stoplegend stopline \
+stoplinecorrection stoplinenumbering stoplines stoplocal stoplocalenvironment \
+stoplocalfootnotes stoplokaal stoplokalevoetnoten stopmakeup stopmargeblok \
+stopmarginblock stopnaast stopnamemakeup stopnarrower stopomgeving \
+stoponderdeel stopopelkaar stopopmaak stopopposite stopoverlay \
+stopoverview stopoverzicht stopparagraph stoppositioneren stoppositioning \
+stoppostponing stopprodukt stopprofiel stopprofile stopprojekt \
+stopraster stopregel stopregelcorrectie stopregelnummeren stopregels \
+stopsmaller stopsymbolset stopsynchronisatie stopsynchronization stoptabel \
+stoptabellen stoptable stoptables stoptabulate stoptekst \
+stoptekstlijn stoptyping stopuitlijnen stopunpacked stopvanelkaar \
+stopversie sub subformulenummer subject subpaginanummer \
+subsection subsubject subsubsection subsubsubject suggestie \
+switchnaarkorps switchtorawfont sym symbool synchronisatiebalk \
+synchroniseer synonym taal tab tekstbreedte \
+teksthoogte tekstlijn tekstreferentie tekstvariabele testkolom \
+testpagina tex title toelichting toonexternefiguren \
+toongrid tooninstellingen toonkader toonkleur toonkleurgroep \
+toonkorps toonkorpsomgeving toonlayout toonopmaak toonpalet \
+toonprint toonstruts toonsymboolset toonvelden totaalaantalpaginas \
+txt typ type typebuffer typefile \
+uit uitgerekt underbar underbars usecodering \
+usedirectory vastespatie vastespaties veld veldstapel \
+verbergblokken vergelijkkleurgroep vergelijkpalet verhoognummer verlaagnummer \
+verplaatsformule verplaatsopgrid verplaatszijblok versie vertaal \
+verwerkblokken verwerkpagina vl voetafstand voethoogte \
+voetnoot voetnoottekst volgprofiel volgprofielversie volgversie \
+volledigepaginanummer volledigregister voluit weekdag wilijnd \
+wiskunde witruimte woonplaats woordrechts zetbreedte \
+zethoogte
+
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-metafun.properties b/Master/texmf-dist/context/data/scite/scite-context-data-metafun.properties
new file mode 100644
index 00000000000..e0413b2dd75
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-metafun.properties
@@ -0,0 +1,53 @@
+keywordclass.metafun.internals=\
+nocolormodel greycolormodel graycolormodel rgbcolormodel \
+cmykcolormodel shadefactor textextoffset normaltransparent multiplytransparent \
+screentransparent overlaytransparent softlighttransparent hardlighttransparent colordodgetransparent \
+colorburntransparent darkentransparent lightentransparent differencetransparent exclusiontransparent \
+huetransparent saturationtransparent colortransparent luminositytransparent
+
+keywordclass.metafun.commands=\
+sqr log ln exp \
+inv pow pi radian tand \
+cotd sin cos tan cot \
+atan asin acos invsin invcos \
+acosh asinh sinh cosh paired \
+tripled unitcircle fulldiamond unitdiamond fullsquare \
+llcircle lrcircle urcircle ulcircle tcircle \
+bcircle lcircle rcircle lltriangle lrtriangle \
+urtriangle ultriangle smoothed cornered superellipsed \
+randomized squeezed enlonged shortened punked \
+curved unspiked simplified blownup stretched \
+enlarged leftenlarged topenlarged rightenlarged bottomenlarged \
+crossed laddered randomshifted interpolated paralleled \
+cutends peepholed llenlarged lrenlarged urenlarged \
+ulenlarged llmoved lrmoved urmoved ulmoved \
+rightarrow leftarrow centerarrow boundingbox innerboundingbox \
+outerboundingbox pushboundingbox popboundingbox bottomboundary leftboundary \
+topboundary rightboundary xsized ysized xysized \
+sized xyscaled intersection_point intersection_found penpoint \
+bbwidth bbheight withshade withlinearshading withcircularshading \
+withfromshadecolor withtoshadecolor withshading shadedinto withcircularshade \
+withlinearshade cmyk spotcolor multitonecolor namedcolor \
+drawfill undrawfill inverted uncolored softened \
+grayed greyed onlayer along graphictext \
+loadfigure externalfigure withmask figure register \
+bitmapimage colordecimals ddecimal dddecimal ddddecimal \
+textext thetextext rawtextext textextoffset verbatim \
+thelabel label transparent withtransparency asgroup \
+infont set_linear_vector linear_shade define_linear_shade define_circular_linear_shade \
+define_sampled_linear_shade set_circular_vector circular_shade define_circular_shade define_circular_linear_shade \
+define_sampled_circular_shade space CRLF grayscale greyscale \
+withgray withgrey colorpart readfile clearxy \
+unitvector center epsed anchored originpath \
+infinite break xstretched ystretched snapped \
+pathconnectors function constructedpath constructedpairs punkedfunction \
+curvedfunction tightfunction punkedpath curvedpath tightpath \
+punkedpairs curvedpairs tightpairs evenly oddly \
+condition pushcurrentpicture popcurrentpicture arrowpath tensecircle \
+roundedsquare colortype whitecolor blackcolor normalfill \
+normaldraw visualizepaths naturalizepaths drawboundary drawwholepath \
+visualizeddraw visualizedfill draworigin drawboundingbox drawpath \
+drawpoint drawpoints drawcontrolpoints drawcontrollines drawpointlabels \
+drawlineoptions drawpointoptions drawcontroloptions drawlabeloptions draworiginoptions \
+drawboundoptions drawpathoptions resetdrawoptions
+
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-metapost.properties b/Master/texmf-dist/context/data/scite/scite-context-data-metapost.properties
new file mode 100644
index 00000000000..d2027c9564e
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-metapost.properties
@@ -0,0 +1,96 @@
+keywordclass.metapost.primitives=\
+charcode day linecap linejoin \
+miterlimit month pausing prologues showstopping \
+time tracingcapsules tracingchoices mpprocset tracingcommands \
+tracingequations tracinglostchars tracingmacros tracingonline tracingoutput \
+tracingrestores tracingspecs tracingstats tracingtitles truecorners \
+warningcheck year false nullpicture pencircle \
+true and angle arclength arctime \
+ASCII boolean bot char color \
+cosd cycle decimal directiontime floor \
+fontsize hex infont intersectiontimes known \
+length llcorner lrcorner makepath makepen \
+mexp mlog normaldeviate not numeric \
+oct odd or path pair \
+pen penoffset picture point postcontrol \
+precontrol reverse rotated scaled shifted \
+sind slanted sqrt str string \
+subpath substring transform transformed ulcorner \
+uniformdeviate unknown urcorner xpart xscaled \
+xxpart xypart ypart yscaled yxpart \
+yypart zscaled addto clip input \
+interim let newinternal save setbounds \
+shipout show showdependencies showtoken showvariable \
+special begingroup endgroup of curl \
+tension and controls interpath on \
+off def vardef enddef expr \
+suffix text primary secondary tertiary \
+primarydef secondarydef tertiarydef randomseed also \
+contour doublepath withcolor withpen dashed \
+if else elseif fi for \
+endfor forever exitif forsuffixes downto \
+upto step until charlist extensible \
+fontdimen headerbyte kern ligtable boundarychar \
+chardp charext charht charic charwd \
+designsize fontmaking charexists cullit currenttransform \
+gfcorners grayfont hround imagerules lowres_fix \
+nodisplays notransforms openit displaying currentwindow \
+screen_rows screen_cols pixels_per_inch cull display \
+openwindow numspecial totalweight autorounding fillin \
+proofing tracingpens xoffset chardx granularity \
+smoothing turningcheck yoffset chardy hppp \
+tracingedges vppp extra_beginfig extra_endfig mpxbreak \
+endinput message delimiters turningnumber errmessage \
+readstring scantokens end outer inner \
+write to readfrom withprescript withpostscript \
+top bot lft rt ulft \
+urt llft lrt redpart greenpart \
+bluepart cyanpart magentapart yellowpart blackpart \
+greypart rgbcolor cmykcolor greycolor graycolor \
+colormodel graypart expandafter
+
+keywordclass.metapost.commands=\
+beginfig endfig rotatedaround reflectedabout \
+arrowhead currentpen currentpicture cuttings defaultfont \
+extra_beginfig extra_endfig ditto EOF down \
+evenly fullcircle halfcircle identity in \
+left origin pensquare quartercircle right \
+unitsquare up withdots abs bbox \
+ceiling center cutafter cutbefore dir \
+directionpoint div dotprod intersectionpoint inverse \
+mod round unitvector whatever cutdraw \
+draw drawarrow drawdblarrow fill filldraw \
+drawdot loggingall interact tracingall tracingnone \
+pickup undraw unfill unfilldraw buildcycle \
+dashpattern decr dotlabel dotlabels drawoptions \
+incr label labels max min \
+thelabel z beginchar blacker capsule_end \
+change_width define_blacker_pixels define_corrected_pixels define_good_x_pixels define_good_y_pixels \
+define_horizontal_corrected_pixels define_pixels define_whole_blacker_pixels define_whole_pixels define_whole_vertical_blacker_pixels \
+define_whole_vertical_pixels endchar extra_beginchar extra_endchar extra_setup \
+font_coding_scheme clearxy clearit clearpen shipit \
+font_extra_space exitunless relax hide gobble \
+gobbled stop blankpicture counterclockwise tensepath \
+takepower direction softjoin makelabel rotatedabout \
+flex superellipse erase image nullpen \
+savepen clearpen penpos penlabels range \
+numtok thru z laboff bye \
+red green blue cyan magenta \
+yellow black white background graypart \
+graycolor mm pt dd bp \
+cm pc cc in
+
+keywordclass.metapost.tex=\
+btex etex verbatimtex
+
+keywordclass.metapost.internals=\
+mitered rounded beveled butt \
+squared eps epsilon infinity bboxmargin \
+ahlength ahangle labeloffset dotlabeldiam defaultpen \
+defaultscale join_radius pen_lft pen_rt pen_top \
+pen_bot
+
+keywordclass.metapost.shortcuts=\
+.. ... -- --- \
+&
+
diff --git a/Master/texmf-dist/context/data/scite/scite-context-data-tex.properties b/Master/texmf-dist/context/data/scite/scite-context-data-tex.properties
new file mode 100644
index 00000000000..0f63b994dee
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-data-tex.properties
@@ -0,0 +1,238 @@
+keywordclass.tex.etex=\
+botmarks clubpenalties currentgrouplevel currentgrouptype \
+currentifbranch currentiflevel currentiftype detokenize dimexpr \
+displaywidowpenalties eTeXVersion eTeXminorversion eTeXrevision eTeXversion \
+everyeof firstmarks fontchardp fontcharht fontcharic \
+fontcharwd glueexpr glueshrink glueshrinkorder gluestretch \
+gluestretchorder gluetomu ifcsname ifdefined iffontchar \
+interactionmode interlinepenalties lastlinefit lastnodetype marks \
+muexpr mutoglue numexpr pagediscards parshapedimen \
+parshapeindent parshapelength predisplaydirection protected readline \
+savinghyphcodes savingvdiscards scantokens showgroups showifs \
+showtokens splitbotmarks splitdiscards splitfirstmarks topmarks \
+tracingassigns tracinggroups tracingifs tracingnesting tracingscantokens \
+unexpanded unless widowpenalties
+
+keywordclass.tex.pdftex=\
+efcode expanded ifincsname ifpdfabsdim \
+ifpdfabsnum ifpdfprimitive leftmarginkern letterspacefont lpcode \
+pdfadjustspacing pdfannot pdfcatalog pdfcolorstack pdfcolorstackinit \
+pdfcompresslevel pdfcopyfont pdfcreationdate pdfdecimaldigits pdfdest \
+pdfdestmargin pdfdraftmode pdfeachlinedepth pdfeachlineheight pdfendlink \
+pdfendthread pdffirstlineheight pdffontattr pdffontexpand pdffontname \
+pdffontobjnum pdffontsize pdfgamma pdfgentounicode pdfglyphtounicode \
+pdfhorigin pdfignoreddimen pdfimageapplygamma pdfimagegamma pdfimagehicolor \
+pdfimageresolution pdfincludechars pdfinclusioncopyfonts pdfinclusionerrorlevel pdfinfo \
+pdfinsertht pdflastannot pdflastlinedepth pdflastlink pdflastobj \
+pdflastxform pdflastximage pdflastximagecolordepth pdflastximagepages pdflastxpos \
+pdflastypos pdflinkmargin pdfliteral pdfmapfile pdfmapline \
+pdfminorversion pdfnames pdfnoligatures pdfnormaldeviate pdfobj \
+pdfobjcompresslevel pdfoptionpdfminorversion pdfoutline pdfoutput pdfpageattr \
+pdfpagebox pdfpageheight pdfpageref pdfpageresources pdfpagesattr \
+pdfpagewidth pdfpkmode pdfpkresolution pdfprimitive pdfprotrudechars \
+pdfpxdimen pdfrandomseed pdfrefobj pdfrefxform pdfrefximage \
+pdfreplacefont pdfrestore pdfretval pdfsave pdfsavepos \
+pdfsetmatrix pdfsetrandomseed pdfstartlink pdfstartthread pdftexbanner \
+pdftexrevision pdftexversion pdfthread pdfthreadmargin pdftracingfonts \
+pdftrailer pdfuniformdeviate pdfuniqueresname pdfvorigin pdfxform \
+pdfxformattr pdfxformname pdfxformresources pdfximage pdfximagebbox \
+quitvmode rightmarginkern rpcode tagcode
+
+keywordclass.tex.xetex=\
+XeTeXversion
+
+keywordclass.tex.tex=\
+- / AlephVersion Alephminorversion \
+Alephrevision Alephversion OmegaVersion Omegaminorversion Omegarevision \
+Omegaversion Udelcode Udelcodenum Udelimiter Udelimiterover \
+Udelimiterunder Umathaccent Umathaccents Umathaxis Umathbinbinspacing \
+Umathbinclosespacing Umathbininnerspacing Umathbinopenspacing Umathbinopspacing Umathbinordspacing \
+Umathbinpunctspacing Umathbinrelspacing Umathbotaccent Umathchar Umathchardef \
+Umathcharnum Umathclosebinspacing Umathcloseclosespacing Umathcloseinnerspacing Umathcloseopenspacing \
+Umathcloseopspacing Umathcloseordspacing Umathclosepunctspacing Umathcloserelspacing Umathcode \
+Umathcodenum Umathconnectoroverlapmin Umathfractiondelsize Umathfractiondenomdown Umathfractiondenomvgap \
+Umathfractionnumup Umathfractionnumvgap Umathfractionrule Umathinnerbinspacing Umathinnerclosespacing \
+Umathinnerinnerspacing Umathinneropenspacing Umathinneropspacing Umathinnerordspacing Umathinnerpunctspacing \
+Umathinnerrelspacing Umathlimitabovebgap Umathlimitabovekern Umathlimitabovevgap Umathlimitbelowbgap \
+Umathlimitbelowkern Umathlimitbelowvgap Umathopbinspacing Umathopclosespacing Umathopenbinspacing \
+Umathopenclosespacing Umathopeninnerspacing Umathopenopenspacing Umathopenopspacing Umathopenordspacing \
+Umathopenpunctspacing Umathopenrelspacing Umathoperatorsize Umathopinnerspacing Umathopopenspacing \
+Umathopopspacing Umathopordspacing Umathoppunctspacing Umathoprelspacing Umathordbinspacing \
+Umathordclosespacing Umathordinnerspacing Umathordopenspacing Umathordopspacing Umathordordspacing \
+Umathordpunctspacing Umathordrelspacing Umathoverbarkern Umathoverbarrule Umathoverbarvgap \
+Umathoverdelimiterbgap Umathoverdelimitervgap Umathpunctbinspacing Umathpunctclosespacing Umathpunctinnerspacing \
+Umathpunctopenspacing Umathpunctopspacing Umathpunctordspacing Umathpunctpunctspacing Umathpunctrelspacing \
+Umathquad Umathradicaldegreeafter Umathradicaldegreebefore Umathradicaldegreeraise Umathradicalkern \
+Umathradicalrule Umathradicalvgap Umathrelbinspacing Umathrelclosespacing Umathrelinnerspacing \
+Umathrelopenspacing Umathrelopspacing Umathrelordspacing Umathrelpunctspacing Umathrelrelspacing \
+Umathspaceafterscript Umathstackdenomdown Umathstacknumup Umathstackvgap Umathsubshiftdown \
+Umathsubshiftdrop Umathsubsupshiftdown Umathsubsupvgap Umathsubtopmax Umathsupbottommin \
+Umathsupshiftdrop Umathsupshiftup Umathsupsubbottommax Umathunderbarkern Umathunderbarrule \
+Umathunderbarvgap Umathunderdelimiterbgap Umathunderdelimitervgap Uoverdelimiter Uradical \
+Uroot Ustack Ustartdisplaymath Ustartmath Ustopdisplaymath \
+Ustopmath Usubscript Usuperscript Uunderdelimiter above \
+abovedisplayshortskip abovedisplayskip abovewithdelims accent adjdemerits \
+advance afterassignment aftergroup alignmark aligntab \
+atop atopwithdelims attribute attributedef badness \
+baselineskip batchmode begingroup belowdisplayshortskip belowdisplayskip \
+binoppenalty bodydir botmark botmarks box \
+boxdir boxmaxdepth brokenpenalty catcode catcodetable \
+char chardef chardp charht charit \
+charwd cleaders clearmarks closein closeout \
+clubpenalties clubpenalty copy count countdef \
+cr crampeddisplaystyle crampedscriptscriptstyle crampedscriptstyle crampedtextstyle \
+crcr csname currentgrouplevel currentgrouptype currentifbranch \
+currentiflevel currentiftype day deadcycles def \
+defaulthyphenchar defaultskewchar delcode delimiter delimiterfactor \
+delimitershortfall detokenize dimen dimendef dimexpr \
+directlua discretionary displayindent displaylimits displaystyle \
+displaywidowpenalties displaywidowpenalty displaywidth divide doublehyphendemerits \
+dp dump eTeXVersion eTeXminorversion eTeXrevision \
+eTeXversion edef efcode else emergencystretch \
+end endcsname endgroup endinput endlinechar \
+eqno errhelp errmessage errorcontextlines errorstopmode \
+escapechar everycr everydisplay everyeof everyhbox \
+everyjob everymath everypar everyvbox exhyphenchar \
+exhyphenpenalty expandafter expanded fam fi \
+finalhyphendemerits firstmark firstmarks floatingpenalty font \
+fontchardp fontcharht fontcharic fontcharwd fontdimen \
+fontid fontname formatname futurelet gdef \
+gleaders global globaldefs glueexpr glueshrink \
+glueshrinkorder gluestretch gluestretchorder gluetomu halign \
+hangafter hangindent hbadness hbox hfil \
+hfill hfilneg hfuzz hoffset holdinginserts \
+hrule hsize hskip hss ht \
+hyphenation hyphenchar hyphenpenalty if ifabsdim \
+ifabsnum ifcase ifcat ifcsname ifdefined \
+ifdim ifeof iffalse iffontchar ifhbox \
+ifhmode ifincsname ifinner ifmmode ifnum \
+ifodd ifpdfabsdim ifpdfabsnum ifpdfprimitive ifprimitive \
+iftrue ifvbox ifvmode ifvoid ifx \
+ignorespaces immediate indent initcatcodetable input \
+inputlineno insert insertpenalties interactionmode interlinepenalties \
+interlinepenalty jobname kern language lastbox \
+lastkern lastlinefit lastnodetype lastpenalty lastskip \
+latelua lccode leaders left leftghost \
+lefthyphenmin leftmarginkern leftskip leqno let \
+letterspacefont limits linepenalty lineskip lineskiplimit \
+localbrokenpenalty localinterlinepenalty localleftbox localrightbox long \
+looseness lower lowercase lpcode luaescapestring \
+luastartup luatexdatestamp luatexrevision luatexversion mag \
+mark marks mathaccent mathbin mathchar \
+mathchardef mathchoice mathclose mathcode mathdir \
+mathinner mathop mathopen mathord mathpunct \
+mathrel mathstyle mathsurround maxdeadcycles maxdepth \
+meaning medmuskip message middle mkern \
+month moveleft moveright mskip muexpr \
+multiply muskip muskipdef mutoglue newlinechar \
+noalign noboundary noexpand noindent nokerns \
+noligs nolimits nolocaldirs nolocalwhatsits nonscript \
+nonstopmode nulldelimiterspace nullfont number numexpr \
+odelcode odelimiter omathaccent omathchar omathchardef \
+omathcode omit openin openout or \
+oradical outer output outputbox outputpenalty \
+over overfullrule overline overwithdelims pagebottomoffset \
+pagedepth pagedir pagediscards pagefilllstretch pagefillstretch \
+pagefilstretch pagegoal pageheight pageleftoffset pagerightoffset \
+pageshrink pagestretch pagetopoffset pagetotal pagewidth \
+par pardir parfillskip parindent parshape \
+parshapedimen parshapeindent parshapelength parskip patterns \
+pausing pdfadjustspacing pdfannot pdfcatalog pdfcolorstack \
+pdfcolorstackinit pdfcompresslevel pdfcopyfont pdfcreationdate pdfdecimaldigits \
+pdfdest pdfdestmargin pdfdraftmode pdfeachlinedepth pdfeachlineheight \
+pdfendlink pdfendthread pdffirstlineheight pdffontattr pdffontexpand \
+pdffontname pdffontobjnum pdffontsize pdfgamma pdfgentounicode \
+pdfglyphtounicode pdfhorigin pdfignoreddimen pdfimageapplygamma pdfimagegamma \
+pdfimagehicolor pdfimageresolution pdfincludechars pdfinclusioncopyfonts pdfinclusionerrorlevel \
+pdfinfo pdfinsertht pdflastannot pdflastlinedepth pdflastlink \
+pdflastobj pdflastxform pdflastximage pdflastximagecolordepth pdflastximagepages \
+pdflastxpos pdflastypos pdflinkmargin pdfliteral pdfmapfile \
+pdfmapline pdfminorversion pdfnames pdfnoligatures pdfnormaldeviate \
+pdfobj pdfobjcompresslevel pdfoptionpdfminorversion pdfoutline pdfoutput \
+pdfpageattr pdfpagebox pdfpageheight pdfpageref pdfpageresources \
+pdfpagesattr pdfpagewidth pdfpkmode pdfpkresolution pdfprimitive \
+pdfprotrudechars pdfpxdimen pdfrandomseed pdfrefobj pdfrefxform \
+pdfrefximage pdfreplacefont pdfrestore pdfretval pdfsave \
+pdfsavepos pdfsetmatrix pdfsetrandomseed pdfstartlink pdfstartthread \
+pdftexbanner pdftexrevision pdftexversion pdfthread pdfthreadmargin \
+pdftracingfonts pdftrailer pdfuniformdeviate pdfuniqueresname pdfvorigin \
+pdfxform pdfxformattr pdfxformname pdfxformresources pdfximage \
+pdfximagebbox penalty postdisplaypenalty postexhyphenchar posthyphenchar \
+predisplaydirection predisplaypenalty predisplaysize preexhyphenchar prehyphenchar \
+pretolerance prevdepth prevgraf primitive protected \
+quitvmode radical raise read readline \
+relax relpenalty right rightghost righthyphenmin \
+rightmarginkern rightskip romannumeral rpcode savecatcodetable \
+savinghyphcodes savingvdiscards scantextokens scantokens scriptfont \
+scriptscriptfont scriptscriptstyle scriptspace scriptstyle scrollmode \
+setbox setlanguage sfcode shipout show \
+showbox showboxbreadth showboxdepth showgroups showifs \
+showlists showthe showtokens skewchar skip \
+skipdef spacefactor spaceskip span special \
+splitbotmark splitbotmarks splitdiscards splitfirstmark splitfirstmarks \
+splitmaxdepth splittopskip string suppressfontnotfounderror suppressifcsnameerror \
+suppresslongerror suppressoutererror synctex tabskip tagcode \
+textdir textfont textstyle the thickmuskip \
+thinmuskip time toks toksdef tolerance \
+topmark topmarks topskip tracingassigns tracingcommands \
+tracinggroups tracingifs tracinglostchars tracingmacros tracingnesting \
+tracingonline tracingoutput tracingpages tracingparagraphs tracingrestores \
+tracingscantokens tracingstats uccode uchyph underline \
+unexpanded unhbox unhcopy unkern unless \
+unpenalty unskip unvbox unvcopy uppercase \
+vadjust valign vbadness vbox vcenter \
+vfil vfill vfilneg vfuzz voffset \
+vrule vsize vskip vsplit vss \
+vtop wd widowpenalties widowpenalty write \
+xdef xleaders xspaceskip year
+
+keywordclass.tex.aleph=\
+AlephVersion Alephminorversion Alephrevision Alephversion \
+Omegaminorversion Omegarevision Omegaversion boxdir pagebottomoffset \
+pagerightoffset
+
+keywordclass.tex.luatex=\
+Udelcode Udelcodenum Udelimiter Udelimiterover \
+Udelimiterunder Umathaccent Umathaccents Umathaxis Umathbinbinspacing \
+Umathbinclosespacing Umathbininnerspacing Umathbinopenspacing Umathbinopspacing Umathbinordspacing \
+Umathbinpunctspacing Umathbinrelspacing Umathbotaccent Umathchar Umathchardef \
+Umathcharnum Umathclosebinspacing Umathcloseclosespacing Umathcloseinnerspacing Umathcloseopenspacing \
+Umathcloseopspacing Umathcloseordspacing Umathclosepunctspacing Umathcloserelspacing Umathcode \
+Umathcodenum Umathconnectoroverlapmin Umathfractiondelsize Umathfractiondenomdown Umathfractiondenomvgap \
+Umathfractionnumup Umathfractionnumvgap Umathfractionrule Umathinnerbinspacing Umathinnerclosespacing \
+Umathinnerinnerspacing Umathinneropenspacing Umathinneropspacing Umathinnerordspacing Umathinnerpunctspacing \
+Umathinnerrelspacing Umathlimitabovebgap Umathlimitabovekern Umathlimitabovevgap Umathlimitbelowbgap \
+Umathlimitbelowkern Umathlimitbelowvgap Umathopbinspacing Umathopclosespacing Umathopenbinspacing \
+Umathopenclosespacing Umathopeninnerspacing Umathopenopenspacing Umathopenopspacing Umathopenordspacing \
+Umathopenpunctspacing Umathopenrelspacing Umathoperatorsize Umathopinnerspacing Umathopopenspacing \
+Umathopopspacing Umathopordspacing Umathoppunctspacing Umathoprelspacing Umathordbinspacing \
+Umathordclosespacing Umathordinnerspacing Umathordopenspacing Umathordopspacing Umathordordspacing \
+Umathordpunctspacing Umathordrelspacing Umathoverbarkern Umathoverbarrule Umathoverbarvgap \
+Umathoverdelimiterbgap Umathoverdelimitervgap Umathpunctbinspacing Umathpunctclosespacing Umathpunctinnerspacing \
+Umathpunctopenspacing Umathpunctopspacing Umathpunctordspacing Umathpunctpunctspacing Umathpunctrelspacing \
+Umathquad Umathradicaldegreeafter Umathradicaldegreebefore Umathradicaldegreeraise Umathradicalkern \
+Umathradicalrule Umathradicalvgap Umathrelbinspacing Umathrelclosespacing Umathrelinnerspacing \
+Umathrelopenspacing Umathrelopspacing Umathrelordspacing Umathrelpunctspacing Umathrelrelspacing \
+Umathspaceafterscript Umathstackdenomdown Umathstacknumup Umathstackvgap Umathsubshiftdown \
+Umathsubshiftdrop Umathsubsupshiftdown Umathsubsupvgap Umathsubtopmax Umathsupbottommin \
+Umathsupshiftdrop Umathsupshiftup Umathsupsubbottommax Umathunderbarkern Umathunderbarrule \
+Umathunderbarvgap Umathunderdelimiterbgap Umathunderdelimitervgap Uoverdelimiter Uradical \
+Uroot Ustack Ustartdisplaymath Ustartmath Ustopdisplaymath \
+Ustopmath Usubscript Usuperscript Uunderdelimiter alignmark \
+aligntab attribute attributedef catcodetable clearmarks \
+crampeddisplaystyle crampedscriptscriptstyle crampedscriptstyle crampedtextstyle fontid \
+formatname gleaders ifabsdim ifabsnum ifprimitive \
+initcatcodetable latelua luaescapestring luastartup luatexdatestamp \
+luatexrevision luatexversion mathstyle nokerns noligs \
+outputbox pageleftoffset pagetopoffset postexhyphenchar posthyphenchar \
+preexhyphenchar prehyphenchar primitive savecatcodetable scantextokens \
+suppressfontnotfounderror suppressifcsnameerror suppresslongerror suppressoutererror synctex
+
+keywordclass.tex.omega=\
+OmegaVersion bodydir chardp charht \
+charit charwd leftghost localbrokenpenalty localinterlinepenalty \
+localleftbox localrightbox mathdir odelcode odelimiter \
+omathaccent omathchar omathchardef omathcode oradical \
+pagedir pageheight pagewidth pardir rightghost \
+textdir
+
diff --git a/Master/texmf-dist/context/data/scite/scite-context-external.properties b/Master/texmf-dist/context/data/scite/scite-context-external.properties
new file mode 100644
index 00000000000..6bba2b7ff91
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-external.properties
@@ -0,0 +1,85 @@
+# external lpeg lexers
+
+import $(SciteDefaultHome)/lexers/lpeg
+
+lexer.lpeg.home=$(SciteDefaultHome)/lexers
+
+# # pre 3.03:
+#
+#~ lexer.lpeg.script=$(lexer.lpeg.home)/scite-context-lexer.lua
+#
+# # post 3.03:
+#
+lexer.lpeg.script=$(lexer.lpeg.home)/lexer.lua
+#
+# where we load the extensions in the lexers themselves.
+
+lexer.lpeg.color.theme=$(lexer.lpeg.home)/themes/scite-context-theme.lua
+
+# alas, only a few properties are passed (only indentation)
+
+fold.by.parsing=1
+fold.by.indentation=0
+fold.by.line=0
+
+if PLAT_WIN
+ lexerpath.*.lpeg=$(lexer.lpeg.home)/LexLPeg.dll
+
+if PLAT_GTK
+ lexerpath.*.lpeg=$(lexer.lpeg.home)/liblexlpeg.so
+
+lexer.*.lpeg=lpeg
+
+lexer.$(file.patterns.metapost)=lpeg_scite-context-lexer-mps
+lexer.$(file.patterns.metafun)=lpeg_scite-context-lexer-mps
+lexer.$(file.patterns.context)=lpeg_scite-context-lexer-tex
+lexer.$(file.patterns.tex)=lpeg_scite-context-lexer-tex
+lexer.$(file.patterns.lua)=lpeg_scite-context-lexer-lua
+lexer.$(file.patterns.example)=lpeg_scite-context-lexer-xml
+lexer.$(file.patterns.text)=lpeg_scite-context-lexer-txt
+lexer.$(file.patterns.pdf)=lpeg_scite-context-lexer-pdf
+
+#~ lexer.$(file.patterns.metapost)=lpeg_ctx-mps
+#~ lexer.$(file.patterns.metafun)=lpeg_ctx-mps
+#~ lexer.$(file.patterns.context)=lpeg_ctx-tex
+#~ lexer.$(file.patterns.tex)=lpeg_ctx-tex
+#~ lexer.$(file.patterns.lua)=lpeg_ctx-lua
+#~ lexer.$(file.patterns.example)=lpeg_ctx-xml
+#~ lexer.$(file.patterns.text)=lpeg_ctx-txt
+#~ lexer.$(file.patterns.pdf)=lpeg_ctx-pdf
+
+comment.block.lpeg_scite-context-lexer-tex=%
+comment.block.at.line.start.lpeg_scite-context-lexer-tex=1
+
+comment.block.lpeg_scite-context-lexer-mps=%
+comment.block.at.line.start.lpeg_scite-context-lexer-mps=1
+
+comment.block.lpeg_scite-context-lexer-lua=--
+comment.block.at.line.start.lpeg_scite-context-lexer-lua=1
+
+comment.block.lpeg_scite-context-lexer-cld=--
+comment.block.at.line.start.lpeg_scite-context-lexer-cld=1
+
+comment.block.lpeg_props=#
+comment.block.at.line.start.lpeg_props=1
+
+#~ comment.block.lpeg_ctx-tex=%
+#~ comment.block.at.line.start.lpeg_ctx-tex=1
+
+#~ comment.block.lpeg_ctx-mps=%
+#~ comment.block.at.line.start.lpeg_ctx-mps=1
+
+#~ comment.block.lpeg_ctx-lua=--
+#~ comment.block.at.line.start.lpeg_ctx-lua=1
+
+#~ comment.block.lpeg_ctx-cld=--
+#~ comment.block.at.line.start.lpeg_ctx-cld=1
+
+#~ comment.block.lpeg_props=#
+#~ comment.block.at.line.start.lpeg_props=1
+
+#~ style.*.34=bold
+#~ style.*.35=bold
+
+style.*.34=$(styles.bracelight)
+style.*.35=$(styles.bracebad)
diff --git a/Master/texmf-dist/context/data/scite/scite-context-internal.properties b/Master/texmf-dist/context/data/scite/scite-context-internal.properties
new file mode 100644
index 00000000000..92806b8e22e
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-internal.properties
@@ -0,0 +1,82 @@
+# Metapost: lexer.metapost.interface.default
+#
+# 0 not used
+# 1 metapost primitives and commands
+# 2 metafun macros
+#
+# first lines of a metapost file are interpreted as follows:
+#
+# % interface=none|metapost|mp|metafun
+
+import scite-context-data-metapost
+import scite-context-data-metafun
+
+keywordclass.metapost.all=$(keywordclass.metapost.tex) $(keywordclass.metapost.plain) $(keywordclass.metapost.primitives)
+keywordclass.metafun.all=$(keywordclass.metafun.constants) $(keywordclass.metafun.helpers)
+
+keywords.$(file.patterns.metafun)=$(keywordclass.metapost.all)
+keywords2.$(file.patterns.metafun)=$(keywordclass.metapost.all) $(keywordclass.metafun.all)
+
+lexer.metapost.interface.default=2
+lexer.metapost.comment.process=0
+
+lexer.$(file.patterns.metapost)=metapost
+lexer.$(file.patterns.metafun)=metapost
+
+# Metapost: comments
+
+comment.block.metapost=%
+comment.block.at.line.start.metapost=1
+
+# internal lexers
+#
+# 0 all \commands
+# 1 tex etex pdftex omega primitives
+# 2 context nl (when context.properties is loaded)
+# 3 context en (when context.properties is loaded)
+# 4 context de (when context.properties is loaded)
+# 5 context cz (when context.properties is loaded)
+# 6 context it (when context.properties is loaded)
+# 7 context ro (when context.properties is loaded)
+# 8 latex (no keywords yet; will move up)
+#
+# first lines of a tex file are interpreted as follows
+#
+# % interface=all|nl|en|de|cz|it|ro|latex
+
+import scite-context-data-tex
+import scite-context-data-context
+import scite-context-data-interfaces
+
+word.characters.$(file.patterns.context)=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@!?_\\
+
+keywordclass.context.base=\
+ $(keywordclass.tex.tex) \
+ $(keywordclass.tex.etex) \
+ $(keywordclass.tex.pdftex) \
+ $(keywordclass.tex.aleph) \
+ $(keywordclass.tex.omega) \
+ $(keywordclass.tex.xetex) \
+ $(keywordclass.context.constants) \
+ $(keywordclass.context.helpers)
+
+keywords.$(file.patterns.context)=$(keywordclass.context.base)
+keywords2.$(file.patterns.context)=$(keywordclass.context.base) $(keywordclass.context.nl)
+keywords3.$(file.patterns.context)=$(keywordclass.context.base) $(keywordclass.context.en)
+keywords4.$(file.patterns.context)=$(keywordclass.context.base) $(keywordclass.context.de)
+keywords5.$(file.patterns.context)=$(keywordclass.context.base) $(keywordclass.context.cs)
+keywords6.$(file.patterns.context)=$(keywordclass.context.base) $(keywordclass.context.it)
+keywords7.$(file.patterns.context)=$(keywordclass.context.base) $(keywordclass.context.ro)
+keywords8.$(file.patterns.context)=$(keywordclass.context.base) $(keywordclass.context.fr)
+keywords9.$(file.patterns.context)=$(keywordclass.context.base) $(keywordclass.context.pe)
+
+comment.block.context=%
+comment.block.at.line.start.context=1
+
+lexer.context.interface.default=0
+lexer.context.use.keywords=1
+lexer.context.comment.process=0
+lexer.context.auto.if=1
+
+lexer.$(file.patterns.context)=tex
+lexer.$(file.patterns.tex)=tex
diff --git a/Master/texmf-dist/context/data/scite/scite-context-readme.pdf b/Master/texmf-dist/context/data/scite/scite-context-readme.pdf
new file mode 100644
index 00000000000..32c9628b60d
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-readme.pdf
Binary files differ
diff --git a/Master/texmf-dist/context/data/scite/scite-context-readme.tex b/Master/texmf-dist/context/data/scite/scite-context-readme.tex
new file mode 100644
index 00000000000..6221d7cde94
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-readme.tex
@@ -0,0 +1,858 @@
+% interface=en modes=icon,screen language=uk
+
+\usemodule[art-01]
+\usemodule[abr-02]
+
+\unexpanded\def\METAPOST{MetaPost}
+\unexpanded\def\METAFUN {MetaFun}
+
+\setuphead
+ [section]
+ [color=darkblue]
+
+\setuptype
+ [color=darkblue]
+
+\setuptyping
+ [color=darkblue]
+
+\setuptyping
+ [margin=yes]
+
+\setupwhitespace
+ [big]
+
+\definecolor[gray][s=.2,t=.5,a=1]
+
+\startuseMPgraphic{TitlePage}{darkness}
+ StartPage ;
+
+ numeric factor ; factor := 1/3 ;
+ numeric multiple ; multiple := PaperHeight/PaperWidth ; % 1.6 ;
+ numeric stages ; stages := multiple/16 ; % .1 ;
+ numeric darkness ; darkness := \MPvar{darkness} ;
+
+ def Scaled(expr s, m) =
+ if m = 1 :
+ scaled (2*s*PaperWidth)
+ else :
+ xscaled (2*s*PaperWidth) yscaled (2*s*PaperHeight)
+ fi
+ enddef ;
+
+ fill Page withcolor (factor*white) ;
+
+ fill fullcircle scaled (multiple*PaperWidth) shifted llcorner Page withcolor (factor*red) ;
+ fill fullcircle scaled (multiple*PaperWidth) shifted ulcorner Page withcolor (factor*green) ;
+ fill fullcircle scaled (multiple*PaperWidth) shifted urcorner Page withcolor (factor*blue) ;
+ fill fullcircle scaled (multiple*PaperWidth) shifted lrcorner Page withcolor (factor*yellow) ;
+
+ for i = llcorner Page, ulcorner Page, urcorner Page, lrcorner Page :
+ for j = 0 step stages until (10*stages-eps) : % or .8
+ fill fullcircle Scaled(j,1) shifted i withcolor transparent(1,\MPvar{darkness}*(1-j),white) ;
+ endfor ;
+ endfor ;
+
+ draw Page withpen pencircle scaled .1PaperWidth withcolor transparent(1,.5,.5white) ;
+
+ StopPage
+\stopuseMPgraphic
+
+\startmode[icon,screen]
+
+ \setuppapersize[S66][S66]
+
+ \setupbodyfont[10pt]
+
+\stopmode
+
+\startmode[icon]
+
+ \starttext
+
+ \startTEXpage
+ \useMPgraphic{TitlePage}{darkness=0.4}
+ \stopTEXpage
+
+ \stoptext
+
+\stopmode
+
+\starttext
+
+% title page
+
+\definelayer
+ [TitlePage]
+ [width=\paperwidth,
+ height=\paperheight]
+
+\setlayer
+ [TitlePage]
+ {\useMPgraphic{TitlePage}{darkness=1}}
+
+\setlayerframed
+ [TitlePage]
+ [preset=rightbottom,
+ hoffset=.1\paperwidth,
+ voffset=.1\paperwidth]
+ [align=left,
+ width=\hsize,
+ frame=off,
+ foregroundcolor=gray]
+ {\definedfont[SerifBold sa 10]SciTE\endgraf
+ \definedfont[SerifBold sa 2.48]IN CONTEXT MkIV\kern.25\bodyfontsize}
+
+\startTEXpage
+ \tightlayer[TitlePage]
+\stopTEXpage
+
+% main text
+
+\subject{About \SCITE}
+
+{\em This manual is under (re)construction.}
+
+For a long time at \PRAGMA\ we used \TEXEDIT, an editor we'd
+written in \MODULA. It had some project management features and
+recognized the project structure in \CONTEXT\ documents. Later we
+rewrote this to a platform independent reimplementation called
+\TEXWORK\ written in \PERLTK\ (not to be confused with the editor
+with the plural name).
+
+In the beginning of the century I can into \SCITE, written by Neil
+Hodgson. Although the mentioned editors provide some functionality
+not present in \SCITE\ we decided to use that editor because it
+frees us from maintaining our own. I ported our \TEX\ and
+\METAPOST\ (line based) syntax highlighting to \SCITE\ and got a
+lot of others for free.
+
+After a while I found out that there was an extension interface
+written in \LUA. I played with it and wrote a few extensions too.
+This pleasant experience later triggered the \LUATEX\ project.
+
+A decade into the century \SCITE\ got another new feature: you can
+write dynamic external lexers in \LUA\ using \LPEG. As in the
+meantime \CONTEXT\ has evolved in a \TEX/\LUA\ hybrid, it made
+sense to look into this. The result is a couple of lexers that
+suit \TEX, \METAPOST\ and \LUA\ usage in \CONTEXT\ \MKIV. As we
+also use \XML\ as input and output format a lexer for \XML\ is also
+provided. And because \PDF\ is one of the backend formats lexing of
+\PDF\ is also implemented. \footnote {In the process some of the
+general lexing framework was adapted to suit our demands for speed.
+We ship these files as well.}
+
+In the \CONTEXT\ (standalone) distribution you will find the
+relevant files under:
+
+\starttyping
+<texroot>/tex/texmf-context/context/data/scite
+\stoptyping
+
+Normally a user will not have to dive into the implementation
+details but in principle you can tweak the properties files to
+suit your purpose.
+
+\subject{The look and feel}
+
+The color scheme that we use is consistent over the lexers but we
+use more colors that in the traditional lexing. For instance,
+\TEX\ primitives, low level \TEX\ commands, \TEX\ constants, basic
+file structure related commands, and user commands all get a
+different treatment. When spell checking is turned on, we indicate
+unknown words, but also words that are known but might need
+checking, for instance because they have an uppercase character.
+In \in {figure} [fig:colors] we some of that in practice.
+
+\placefigure
+ [page]
+ [fig:colors]
+ {Nested lexers in action.}
+ {\rotate
+ [rotation=90]
+ {\externalfigure
+ [scite-context-visual.png]
+ [maxheight=1.2\textwidth,
+ maxwidth=.9\textheight]}}
+
+\subject{Installing \SCITE}
+
+Installing \SCITE\ is straightforward. We are most familiar with
+\MSWINDOWS\ but for other operating systems installation is not
+much different. First you need to fetch the archive from:
+
+\starttyping
+www.scintilla.org
+\stoptyping
+
+The \MSWINDOWS\ binaries are zipped in \type {wscite.zip}, and you
+can unzip this in any directory you want as long as you make sure
+that the binary ends up in your path or as shortcut on your
+desktop. So, say that you install \SCITE\ in:
+
+\starttyping
+c:\data\system\scite\wscite
+\stoptyping
+
+You need to add this path to your local path definition.
+Installing \SCITE\ to some known place has the advantage that you
+can move it around. There are no special dependencies on the
+operating system.
+
+Next you need to install the lpeg lexers. \footnote {Versions
+later than 2.11 will not run on Windows 2K. In that case you need
+to comment the external lexer import.} These can be fetched from:
+
+\starttyping
+code.google.com/p/scintilla
+\stoptyping
+
+On windows you need to copy the \type {lexers} subfolder to the
+\type {wscite} folder. For Linux the place depends on the
+distribution and I just copy them in the same path as where the
+regular properties files live.
+
+For \UNIX, one can take a precompiled version as well. Here we
+need to split the set of files into:
+
+\starttyping
+/usr/bin
+/usr/share/scite
+\stoptyping
+
+The second path is hard coded in the binary.
+
+If you want to use \CONTEXT, you need to copy the relevant files from
+
+\starttyping
+<texroot>/tex/texmf-context/context/data/scite
+\stoptyping
+
+to the path were \SCITE\ keeps its property files (\type (*.properties).
+
+There is a file called \type {SciteGlobal.properties}. At the end
+of that file (on windows it is in the path where the Scite binary)
+you then add a line to the end:
+
+\starttyping
+import scite-context-user
+\stoptyping
+
+You need to restart \SCITE\ in order to see if things work out as
+expected.
+
+Disabling the external lexer in a recent \SCITE\ is somewhat
+tricky. In that case the end of that file looks like:
+
+\starttyping
+imports.exclude=scite-context-external
+import *
+import scite-context-user
+\stoptyping
+
+In any case you need to make sure that the user file is loaded last.
+
+After this, things should run as expected (given that \TEX\ runs
+at the console as well).
+
+% In order to run the commands needed, we assume that the following programs
+% are installed:
+%
+% \startitemize[packed]
+% \item tidy (for quick and dirty checking of \XML\ files)
+% \item xsltproc (for converting \XML\ files into other formats)
+% \item acrobat (for viewing files)
+% \item ghostview (for viewing files, use gv on \UNIX)
+% \item rxvt (a console, only needed on \UNIX)
+% \stopitemize
+
+\subject{Fonts}
+
+The configuration file defaults to the Dejavu fonts. These free
+fonts are part of the \CONTEXT\ suite (also known as the
+standalone distribution). Of course you can fetch them from \type
+{http://dejavu-fonts.org} as well. You have to copy them to where
+your operating system expects them. In the suite they are
+available in
+
+\starttyping
+<contextroot>/tex/texmf/fonts/truetype/public/dejavu
+\stoptyping
+
+\subject{An alternative approach}
+
+If for some reason you prefer not to mess with property files in
+the main \SCITE\ path, you can follow a different route and
+selectively copy files to places.
+
+The following files are needed for the lpeg based lexer:
+
+\starttyping
+lexers/scite-context-lexer.lua
+lexers/scite-context-lexer-tex.lua
+lexers/scite-context-lexer-mps.lua
+lexers/scite-context-lexer-lua.lua
+lexers/scite-context-lexer-cld.lua
+lexers/scite-context-lexer-txt.lua
+lexers/scite-context-lexer-xml*.lua
+lexers/scite-context-lexer-pdf*.lua
+
+lexers/context/data/scite-context-data-tex.lua
+lexers/context/data/scite-context-data-context.lua
+lexers/context/data/scite-context-data-interfaces.lua
+lexers/context/data/scite-context-data-metapost.lua
+lexers/context/data/scite-context-data-metafun.lua
+
+lexers/themes/scite-context-theme.lua
+\stoptyping
+
+The data files are needed because we cannot access property files
+from within the lexer. If we could open a file we could use the
+property files instead.
+
+These files go to the \type {lexers} subpath in your \SCITE\
+installation. Normally this sits in the binary path. The
+following files provide some extensions. On windows you can copy
+these files to the path where the \SCITE\ binary lives.
+
+\starttyping
+scite-ctx.lua
+\stoptyping
+
+Because property files can only be loaded from the same path
+where the (user) file loads them you need to copy the following
+files to the same path where the loading is defined:
+
+\starttyping
+scite-context.properties
+scite-context-internal.properties
+scite-context-external.properties
+
+scite-pragma.properties
+
+scite-tex.properties
+scite-metapost.properties
+
+scite-context-data-tex.properties
+scite-context-data-context.properties
+scite-context-data-interfaces.properties
+scite-context-data-metapost.properties
+scite-context-data-metafun.properties
+
+scite-ctx.properties
+scite-ctx-context.properties
+scite-ctx-example.properties
+\stoptyping
+
+On Windows these go to:
+
+\starttyping
+c:/Users/YourName
+\stoptyping
+
+Next you need to add this to:
+
+\starttyping
+import scite-context
+import scite-context-internal
+import scite-context-external
+import scite-pragma
+\stoptyping
+
+to the file:
+
+\starttyping
+SciTEUser.properties
+\stoptyping
+
+Of course the pragma import is optional. You can comment either the
+internal or external variant but there is no reason not to keep them both.
+
+\subject{Extensions}
+
+Just a quick not to some extensions. If you select a part of the
+text (normally you do this with the shift key pressed) and you hit
+\type {Shift-F11}, you get a menu with some options. More (robust)
+ones will be provided at some point.
+
+\subject{Spell checking}
+
+If you want to have spell checking, you need have files with
+correct words on each line. The first line of a file determines
+the language:
+
+\starttyping
+% language=uk
+\stoptyping
+
+When you use the external lexers, you need to provide some files.
+Given that you have a text file with valid words only, you can run
+the following script:
+
+\starttyping
+mtxrun --script scite --words nl uk
+\stoptyping
+
+This will convert files with names like \type {spell-nl.txt} into
+\LUA\ files that you need to copy to the \type {lexers/data} path.
+Spell checking happens realtime when you have the language
+directive (just add a bogus character to disable it). Wrong words
+are colored red, and words that might have a case problem are
+colored orange. Recognized words are greyed and words with less
+than three characters are ignored.
+
+In the case of internal lexers, the following file is needed:
+
+\starttyping
+spell-uk.txt
+\stoptyping
+
+If you use the traditional lexer, this file is taken from the
+path determined by the environment variable:
+
+\starttyping
+CTXSPELLPATH
+\stoptyping
+
+As already mentioned, the lpeg lexer expects them in the data
+path. This is because the \LUA\ instance that does the lexing is
+rather minimalistic and lacks some libraries as well as cannot
+access the main \SCITE\ state.
+
+Spell checking in \type {txt} files is enabled by adding a first
+line:
+
+\starttyping
+[#!-%] language=uk
+\stoptyping
+
+The first character on that line is one of the four mentioned
+between square brackets. So,
+
+\starttyping
+# language=uk
+\stoptyping
+
+should work. For \XML\ files there are two methods. You can use the
+following (at the start of the file):
+
+\starttyping
+<?xml ... language="uk" ?>
+\stoptyping
+
+But probably better is to use the next directive just below the
+usual \XML\ marker line:
+
+\starttyping
+<?context-xml-directive editor language uk ?>
+\stoptyping
+
+\subject{Interface selection}
+
+In a similar fashion you can drive the interface checking:
+
+\starttyping
+% interface=nl
+\stoptyping
+
+\subject{Property files}
+
+The internal lexers are controlled by the property files while the
+external ones are steered with themes. Unfortunately there is
+hardly any access to properties from the external lexer code nor
+can we consult the file system and/or run programs like \type
+{mtxrun}. This means that we cannot use configuration files in the
+\CONTEXT\ distribution directly. Hopefully this changes with
+future releases.
+
+\subject{The external lexers}
+
+These are the more advanced. They provide more detail and the \CONTEXT\
+lexer also supports nested \METAPOST\ and \LUA. Currently there is no
+detailed configuration but this might change once they are stable.
+
+The external lexers operate on documents while the internal ones
+operate on lines. This can make the external lexers slow on large
+documents. We've optimized the code somewhat for speed and memory
+consumption but there's only so much one can do. While lexing each
+change in style needs a small table but allocating and garbage
+collecting many small tables comes at a price. Of course in
+practice this probably gets unnoticed. \footnote {I wrote the code
+in 2011 on a more than 5 years old Dell M90 laptop, so I suppose
+that speed is less an issue now.}
+
+In principle the external lexers can be used with \type
+{textadept} which also uses \type {scintilla}. Actually, support
+for lpeg lexing originates in \type {textadept}. Currently \type
+{textadept} lacks a couple of features I like about \SCITE\ (for
+instance it has no realtime logpane) and it's also still changing.
+At some point the \CONTEXT\ distribution might ship with files
+for \type {textadept} as well.
+
+The external lpeg lexers work okay with the \MSWINDOWS\ and
+\LINUX\ versions of \SCITE, but unfortunately at the time of
+writing this, the \LUA\ library that is needed is not available
+for the \MACOSX\ version of \SCITE. Also, due to the fact that the
+lexing framework is rather isolated, there are some issues that
+cannot be addressed in the properly, at least not currently.
+
+In addition to \CONTEXT\ and \METAFUN\ lexing a \LUA\ lexer is
+also provided so that we can handle \CONTEXT\ \LUA\ Document
+(\CLD) files too. There is also an \XML\ lexer. This one also
+provides spell checking. The \PDF\ lexer tries to do a good job on
+\PDF\ files, but it has some limitations. There is also a simple
+text file lexer that does spell checking.
+
+Don't worry if you see an orange rectangle in your \TEX\ or \XML\
+document. This indicates that there is a special space character
+there, for instance \type {0xA0}, the nonbreakable space. Of course
+we assume that you use \UTF8 as input encoding.
+
+\subject{The internal lexers}
+
+\SCITE\ has quite some built in lexers. A lexer is responsible for
+highlighting the syntax of your document. The way a \TEX\ file is
+treated is configured in the file:
+
+\starttyping
+tex.properties
+\stoptyping
+
+You can edit this file to your needs using the menu entry under
+\type {options} in the top bar. In this file, the following
+settings apply to the \TEX\ lexer:
+
+\starttyping
+lexer.tex.interface.default=0
+lexer.tex.use.keywords=1
+lexer.tex.comment.process=0
+lexer.tex.auto.if=1
+\stoptyping
+
+The option \type {lexer.tex.interface.default} determines the way
+keywords are highlighted. You can control the interface from your
+document as well, which makes more sense that editing the
+configuration file each time.
+
+\starttyping
+% interface=all|tex|nl|en|de|cz|it|ro|latex
+\stoptyping
+
+The values in the properties file and the keywords in the preamble
+line have the following meaning:
+
+\starttabulate[|lT|lT|p|]
+\NC 0 \NC all \NC all commands (preceded by a backslash) \NC \NR
+\NC 1 \NC tex \NC \TEX, \ETEX, \PDFTEX, \OMEGA\ primitives (and macros) \NC \NR
+\NC 2 \NC nl \NC the dutch \CONTEXT\ interface \NC \NR
+\NC 3 \NC en \NC the english \CONTEXT\ interface \NC \NR
+\NC 4 \NC de \NC the german \CONTEXT\ interface \NC \NR
+\NC 5 \NC cz \NC the czech \CONTEXT\ interface \NC \NR
+\NC 6 \NC it \NC the italian \CONTEXT\ interface \NC \NR
+\NC 7 \NC ro \NC the romanian \CONTEXT\ interface \NC \NR
+\NC 8 \NC latex \NC \LATEX\ (apart from packages) \NC \NR
+\stoptabulate
+
+The configuration file is set up in such a way that you can easily
+add more keywords to the lists. The keywords for the second and
+higher interfaces are defined in their own properties files. If
+you're curious about the way this is configures, you can peek into
+the property files that start with \type {scite-context}. When you
+have \CONTEXT\ installed you can generate configuration files with
+
+\starttyping
+mtxrun --script interface --scite
+\stoptyping
+
+You need to make sure that you move the result to the right place so best
+not mess around with this command and use the files from the distribution.
+
+Back to the properties in \type {tex.properties}. You can disable keyword
+coloring alltogether with:
+
+\starttyping
+lexer.tex.use.keywords=0
+\stoptyping
+
+but this is only handy for testing purposes. More interesting is that you can
+influence the way comment is treated:
+
+\starttyping
+lexer.tex.comment.process=0
+\stoptyping
+
+When set to zero, comment is not interpreted as \TEX\ code and it will come out
+in a uniform color. But, when set to one, you will get as much colors as a \TEX\
+source. It's a matter of taste what you choose.
+
+The lexer tries to cope with the \TEX\ syntax as good as possible and takes for
+instance care of the funny \type {^^} notation. A special treatment is
+applied to so called \type {\if}'s:
+
+\starttyping
+lexer.tex.auto.if=1
+\stoptyping
+
+This is the default setting. When set to one, all \type {\ifwhatever}'s will be
+seen as a command. When set to zero, only the primitive \type {\if}'s will be
+treated. In order not to confuse you, when this property is set to one, the
+lexer will not color an \type {\ifwhatever} that follows an \type {\newif}.
+
+\subject{The \METAPOST\ lexer}
+
+The \METAPOST\ lexer is set up slightly different from its \TEX\ counterpart,
+first of all because \METAPOST\ is more a language that \TEX. As with the
+\TEX\ lexer, we can control the interpretation of identifiers. The \METAPOST\
+specific configuration file is:
+
+\starttyping
+metapost.properties
+\stoptyping
+
+Here you can find properties like:
+
+\starttyping
+lexer.metapost.interface.default=1
+\stoptyping
+
+Instead of editing the configuration file you can control the lexer with the
+first line in your document:
+
+\starttyping
+% interface=none|metapost|mp|metafun
+\stoptyping
+
+The numbers and keywords have the following meaning:
+
+\starttabulate[|lT|lT|p|]
+\NC 0 \NC none \NC no highlighting of identifiers \NC \NR
+\NC 1 \NC metapost or mp \NC \METAPOST\ primitives and macros \NC \NR
+\NC 2 \NC metafun \NC \METAFUN\ macros \NC \NR
+\stoptabulate
+
+Similar to the \TEX\ lexer, you can influence the way comments are handled:
+
+\starttyping
+lexer.metapost.comment.process=1
+\stoptyping
+
+This will interpret comment as \METAPOST\ code, which is not that useful
+(opposite to \TEX, where documentation is often coded in \TEX).
+
+The lexer will color the \METAPOST\ keywords, and, when enabled also additional
+keywords (like those of \METAFUN). The additional keywords are colored and shown
+in a slanted font.
+
+The \METAFUN\ keywords are defined in a separate file:
+
+\starttyping
+metafun-scite.properties
+\stoptyping
+
+You can either copy this file to the path where you global properties files lives,
+or put a copy in the path of your user properties file. In that case you need to
+add an entry to the file \type {SciTEUser.properties}:
+
+\starttyping
+import metafun-scite
+\stoptyping
+
+The lexer is able to recognize \type {btex}||\type {etex} and will treat anything
+in between as just text. The same happens with strings (between \type {"}). Both
+act on a per line basis.
+
+\subject{Using \ConTeXt}
+
+When \type {mtxrun} is in your path, \CONTEXT\ should run out of the box. You can
+find \type {mtxrun} in:
+
+\starttyping
+<contextroot>/tex/texmf-mswin/bin
+\stoptyping
+
+or in a similar path that suits the operating system that you use.
+
+When you hit \type{CTRL-12} your document will be processed. Take a look at
+the \type {Tools} menu to see what more is provided.
+
+\subject{Extensions (using \LUA)}
+
+When the \LUA\ extensions are loaded, you will see a message
+in the log pane that looks like:
+
+\starttyping
+- see scite-ctx.properties for configuring info
+
+- ctx.spellcheck.wordpath set to ENV(CTXSPELLPATH)
+- ctxspellpath set to c:\data\develop\context\spell
+- ctx.spellcheck.wordpath expands to c:\data\develop\context\spell
+
+- ctx.wraptext.length is set to 65
+- key bindings:
+
+Shift + F11 pop up menu with ctx options
+
+Ctrl + B check spelling
+Ctrl + M wrap text (auto indent)
+Ctrl + R reset spelling results
+Ctrl + I insert template
+Ctrl + E open log file
+
+- recognized first lines:
+
+xml <?xml version='1.0' language='nl'
+tex % language=nl
+\stoptyping
+
+This message tells you what extras are available.
+
+\subject{Templates}
+
+There is an experimental template mechanism. One option is to define
+templates in a properties file. The property file \type
+{scite-ctx-context} contains definitions like:
+
+\starttyping
+command.25.$(file.patterns.context)=insert_template \
+$(ctx.template.list.context)
+
+ctx.template.list.context=\
+ itemize=structure.itemize.context|\
+ tabulate=structure.tabulate.context|\
+ natural TABLE=structure.TABLE.context|\
+ use MP graphic=graphics.usemp.context|\
+ reuse MP graphic=graphics.reusemp.context|\
+ typeface definition=fonts.typeface.context
+
+ctx.template.structure.itemize.context=\
+\startitemize\n\
+\item ?\n\
+\item ?\n\
+\item ?\n\
+\stopitemize\n
+\stoptyping
+
+The file \type {scite-ctx-example} defines \XML\ variants:
+
+\starttyping
+command.25.$(file.patterns.example)=insert_template \
+$(ctx.template.list.example)
+
+ctx.template.list.example=\
+ bold=font.bold.example|\
+ emphasized=font.emphasized.example|\
+ |\
+ inline math=math.inline.example|\
+ display math=math.display.example|\
+ |\
+ itemize=structure.itemize.example
+
+ctx.template.structure.itemize.example=\
+<itemize>\n\
+<item>?</item>\n\
+<item>?</item>\n\
+<item>?</item>\n\
+</itemize>\n
+\stoptyping
+
+For larger projects it makes sense to keep templates with the
+project. In one of our projects we have a directory in the
+path where the project files are kept which holds template files:
+
+\starttyping
+..../ctx-templates/achtergronden.xml
+..../ctx-templates/bewijs.xml
+\stoptyping
+
+One could define a template menu like we did previously:
+
+\starttyping
+ctx.templatelist.example=\
+ achtergronden=mathadore.achtergronden|\
+ bewijs=mathadore.bewijs|\
+
+ctx.template.mathadore.achtergronden.file=smt-achtergronden.xml
+ctx.template.mathadore.bewijs.file=smt-bewijs.xml
+\stoptyping
+
+However, when no such menu is defined, we will automatically scan
+the directory and build the menu without user intervention.
+
+\subject{Using \SCITE}
+
+The following keybindings are available in \SCITE. Most of this
+list is taken from the on|-|line help pages.
+
+\startbuffer[keybindings]
+\starttabulate[|l|p|]
+\FL
+\NC \rm \bf keybinding \NC \bf meaning (taken from the \SCITE\ help file) \NC \NR
+\ML
+\NC \type{Ctrl+Keypad+} \NC magnify text size \NC \NR
+\NC \type{Ctrl+Keypad-} \NC reduce text size \NC \NR
+\NC \type{Ctrl+Keypad/} \NC restore text size to normal \NC \NR
+\ML
+\NC \type{Ctrl+Keypad*} \NC expand or contract a fold point \NC \NR
+\ML
+\NC \type{Ctrl+Tab} \NC cycle through recent files \NC \NR
+\ML
+\NC \type{Tab} \NC indent block \NC \NR
+\NC \type{Shift+Tab} \NC dedent block \NC \NR
+\ML
+\NC \type{Ctrl+BackSpace} \NC delete to start of word \NC \NR
+\NC \type{Ctrl+Delete} \NC delete to end of word \NC \NR
+\NC \type{Ctrl+Shift+BackSpace} \NC delete to start of line \NC \NR
+\NC \type{Ctrl+Shift+Delete} \NC delete to end of line \NC \NR
+\ML
+\NC \type{Ctrl+Home} \NC go to start of document; \type{Shift} extends selection \NC \NR
+\NC \type{Ctrl+End} \NC go to end of document; \type{Shift} extends selection \NC \NR
+\NC \type{Alt+Home} \NC go to start of display line; \type{Shift} extends selection \NC \NR
+\NC \type{Alt+End} \NC go to end of display line; \type{Shift} extends selection \NC \NR
+\ML
+\NC \type{Ctrl+F2} \NC create or delete a bookmark \NC \NR
+\NC \type{F2} \NC go to next bookmark \NC \NR
+\ML
+\NC \type{Ctrl+F3} \NC find selection \NC \NR
+\NC \type{Ctrl+Shift+F3} \NC find selection backwards \NC \NR
+\ML
+\NC \type{Ctrl+Up} \NC scroll up \NC \NR
+\NC \type{Ctrl+Down} \NC scroll down \NC \NR
+\ML
+\NC \type{Ctrl+C} \NC copy selection to buffer \NC \NR
+\NC \type{Ctrl+V} \NC insert content of buffer \NC \NR
+\NC \type{Ctrl+X} \NC copy selection to buffer and delete selection \NC \NR
+\ML
+\NC \type{Ctrl+L} \NC line cut \NC \NR
+\NC \type{Ctrl+Shift+T} \NC line copy \NC \NR
+\NC \type{Ctrl+Shift+L} \NC line delete \NC \NR
+\NC \type{Ctrl+T} \NC line transpose with previous \NC \NR
+\NC \type{Ctrl+D} \NC line duplicate \NC \NR
+\ML
+\NC \type{Ctrl+K} \NC find matching preprocessor conditional, skipping nested ones \NC \NR
+\NC \type{Ctrl+Shift+K} \NC select to matching preprocessor conditional \NC \NR
+\NC \type{Ctrl+J} \NC find matching preprocessor conditional backwards, skipping nested ones \NC \NR
+\NC \type{Ctrl+Shift+J} \NC select to matching preprocessor conditional backwards \NC \NR
+\ML
+\NC \type{Ctrl+[} \NC previous paragraph; \type{Shift} extends selection \NC \NR
+\NC \type{Ctrl+]} \NC next paragraph; \type{Shift} extends selection \NC \NR
+\NC \type{Ctrl+Left} \NC previous word; \type{Shift} extends selection \NC \NR
+\NC \type{Ctrl+Right} \NC next word; \type{Shift} extends selection \NC \NR
+\NC \type{Ctrl+/} \NC previous word part; \type{Shift} extends selection \NC \NR
+\NC \type{Ctrl+\ } \NC next word part; \type{Shift} extends selection \NC \NR
+\LL
+\stoptabulate
+\stopbuffer
+
+\getbuffer[keybindings]
+
+\subject{Affiliation}
+
+\starttabulate[|l|l|]
+\NC author \NC Hans Hagen \NC \NR
+\NC copyright \NC PRAGMA ADE, Hasselt NL \NC \NR
+\NC more info \NC \type {www.pragma-ade.com} \NC \NR
+\NC \NC \type {www.contextgarden.net} \NC \NR
+\NC version \NC \currentdate \NC \NR
+\stoptabulate
+
+\stoptext
diff --git a/Master/texmf-dist/context/data/scite/scite-context-user.properties b/Master/texmf-dist/context/data/scite/scite-context-user.properties
new file mode 100644
index 00000000000..88e80303191
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-user.properties
@@ -0,0 +1,15 @@
+# this loades the basics
+
+import scite-context
+
+# internal lexing
+
+import scite-context-internal
+
+# external lexing (tex, mps, cld/lua, xml)
+
+import scite-context-external
+
+# this does some tuning
+
+import scite-pragma
diff --git a/Master/texmf-dist/context/data/scite/scite-context-visual.pdf b/Master/texmf-dist/context/data/scite/scite-context-visual.pdf
new file mode 100644
index 00000000000..69d82eda681
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-visual.pdf
@@ -0,0 +1,1364 @@
+%PDF-1.6
+%ÐÔÅØ
+17 0 obj
+<</Length 57118 >>
+stream
+0 g 0 G
+0 g 0 G
+BT
+/F1 11.955168 Tf 1 0 0 1 280.5345 760.6422 Tm [<0052>]TJ
+/F1 20.658493 Tf 1 0 0 1 70.867 696.3895 Tm [<0052>-750<00610051004B0032>-326<0037001C004D002B0076>-326<00690042006900480032>]TJ
+/F1 11.955168 Tf 1 0 0 1 83.2207 641.7609 Tm [<0068003F0032>-326<0069003F00420060002F>-326<0032004D0069006000760035>]TJ
+ET
+q
+1 0 0 1 70.867 664.3031 cm
+[]0 d 0 J 0.3985 w 0 0 m 318.8947 0 l S
+Q
+q
+1 0 0 1 71.0662 625.3676 cm
+[]0 d 0 J 0.3985 w 0 0 m 0 39.1348 l S
+Q
+q
+1 0 0 1 389.5625 625.3676 cm
+[]0 d 0 J 0.3985 w 0 0 m 0 39.1348 l S
+Q
+q
+1 0 0 1 70.867 625.5668 cm
+[]0 d 0 J 0.3985 w 0 0 m 318.8947 0 l S
+Q
+BT
+/F1 11.955168 Tf 1 0 0 1 83.2207 589.6746 Tm [<0068003F0032>-326<00370051006D00600069003F>-326<0032004D0069006000760035>]TJ
+ET
+q
+1 0 0 1 70.867 612.2169 cm
+[]0 d 0 J 0.3985 w 0 0 m 318.8947 0 l S
+Q
+q
+1 0 0 1 71.0662 573.2813 cm
+[]0 d 0 J 0.3985 w 0 0 m 0 39.1348 l S
+Q
+q
+1 0 0 1 389.5625 573.2813 cm
+[]0 d 0 J 0.3985 w 0 0 m 0 39.1348 l S
+Q
+q
+1 0 0 1 70.867 573.4806 cm
+[]0 d 0 J 0.3985 w 0 0 m 318.8947 0 l S
+Q
+BT
+/F1 11.955168 Tf 1 0 0 1 70.867 550.9383 Tm [<0068003F00420062>-293<00420062>-293<0044006D00620069>-293<00620051004B0032>-293<0069003200740069>-293<00690051>-293<002F0032004B0051004D006200690060001C00690032>-293<0069003F0032>-293<00600032001C004800690042004B0032>-293<00620054>-27<003200480048002B>26<003F0032002B>27<0046>27<00320060>-292<0042004D>-293<002B0051004B00230042004D001C006900420051004D>-293<007200420069003F>]TJ
+1 0 0 1 70.867 536.5108 Tm [<0069003F0032>-326<0032004B0023>-27<0032002F002F0032002F>-326<0048006D001C>-326<001C004D002F>-326<004B00320069001C0054>-27<005100620069>-326<004800320074003200600062>-326<001C004D002F>-326<0042004D00480042004D0032>-326<001C0062>-326<0072>27<003200480048>-326<001C0062>-326<002F0042006200540048001C>27<0076>-326<0048006D001C>-326<002B0051>-27<002F00320058>]TJ
+ET
+1 0 0 1 212.8474 389.4945 cm
+% mps graphic 1: begin
+q
+0 g 0 G
+10.000000 M
+1 j
+1 J
+0.500000 w
+1.417328 0.000000 m
+1.417328 0.375916 1.267960 0.736389 1.002182 1.002182 c
+0.736389 1.267960 0.375916 1.417328 0.000000 1.417328 c
+-0.375916 1.417328 -0.736389 1.267960 -1.002182 1.002182 c
+-1.267960 0.736389 -1.417328 0.375916 -1.417328 0.000000 c
+-1.417328 -0.375916 -1.267960 -0.736389 -1.002182 -1.002182 c
+-0.736389 -1.267960 -0.375916 -1.417328 0.000000 -1.417328 c
+0.375916 -1.417328 0.736389 -1.267960 1.002182 -1.002182 c
+1.267960 -0.736389 1.417328 -0.375916 1.417328 0.000000 c
+h S
+0.500000 w
+2.834641 0.000000 m
+2.834641 0.751831 2.535934 1.472778 2.004349 2.004349 c
+1.472778 2.535934 0.751831 2.834641 0.000000 2.834641 c
+-0.751831 2.834641 -1.472778 2.535934 -2.004349 2.004349 c
+-2.535934 1.472778 -2.834641 0.751831 -2.834641 0.000000 c
+-2.834641 -0.751831 -2.535934 -1.472778 -2.004349 -2.004349 c
+-1.472778 -2.535934 -0.751831 -2.834641 0.000000 -2.834641 c
+0.751831 -2.834641 1.472778 -2.535934 2.004349 -2.004349 c
+2.535934 -1.472778 2.834641 -0.751831 2.834641 0.000000 c
+h S
+0.500000 w
+4.251968 0.000000 m
+4.251968 1.127747 3.803894 2.209152 3.006531 3.006531 c
+2.209152 3.803894 1.127747 4.251968 0.000000 4.251968 c
+-1.127747 4.251968 -2.209152 3.803894 -3.006531 3.006531 c
+-3.803894 2.209152 -4.251968 1.127747 -4.251968 0.000000 c
+-4.251968 -1.127747 -3.803894 -2.209152 -3.006531 -3.006531 c
+-2.209152 -3.803894 -1.127747 -4.251968 0.000000 -4.251968 c
+1.127747 -4.251968 2.209152 -3.803894 3.006531 -3.006531 c
+3.803894 -2.209152 4.251968 -1.127747 4.251968 0.000000 c
+h S
+0.500000 w
+5.669281 0.000000 m
+5.669281 1.503647 5.071869 2.945541 4.008698 4.008698 c
+2.945541 5.071869 1.503647 5.669281 0.000000 5.669281 c
+-1.503647 5.669281 -2.945541 5.071869 -4.008698 4.008698 c
+-5.071869 2.945541 -5.669281 1.503647 -5.669281 0.000000 c
+-5.669281 -1.503647 -5.071869 -2.945541 -4.008698 -4.008698 c
+-2.945541 -5.071869 -1.503647 -5.669281 0.000000 -5.669281 c
+1.503647 -5.669281 2.945541 -5.071869 4.008698 -4.008698 c
+5.071869 -2.945541 5.669281 -1.503647 5.669281 0.000000 c
+h S
+0.500000 w
+7.086609 0.000000 m
+7.086609 1.879562 6.339828 3.681931 5.010880 5.010880 c
+3.681931 6.339828 1.879562 7.086609 0.000000 7.086609 c
+-1.879562 7.086609 -3.681931 6.339828 -5.010880 5.010880 c
+-6.339828 3.681931 -7.086609 1.879562 -7.086609 0.000000 c
+-7.086609 -1.879562 -6.339828 -3.681931 -5.010880 -5.010880 c
+-3.681931 -6.339828 -1.879562 -7.086609 0.000000 -7.086609 c
+1.879562 -7.086609 3.681931 -6.339828 5.010880 -5.010880 c
+6.339828 -3.681931 7.086609 -1.879562 7.086609 0.000000 c
+h S
+0.500000 w
+8.503922 0.000000 m
+8.503922 2.255478 7.607803 4.418320 6.013062 6.013062 c
+4.418320 7.607803 2.255478 8.503922 0.000000 8.503922 c
+-2.255478 8.503922 -4.418320 7.607803 -6.013062 6.013062 c
+-7.607803 4.418320 -8.503922 2.255478 -8.503922 0.000000 c
+-8.503922 -2.255478 -7.607803 -4.418320 -6.013062 -6.013062 c
+-4.418320 -7.607803 -2.255478 -8.503922 0.000000 -8.503922 c
+2.255478 -8.503922 4.418320 -7.607803 6.013062 -6.013062 c
+7.607803 -4.418320 8.503922 -2.255478 8.503922 0.000000 c
+h S
+0.500000 w
+9.921249 0.000000 m
+9.921249 2.631393 8.875763 5.154694 7.015228 7.015228 c
+5.154694 8.875763 2.631393 9.921249 0.000000 9.921249 c
+-2.631393 9.921249 -5.154694 8.875763 -7.015228 7.015228 c
+-8.875763 5.154694 -9.921249 2.631393 -9.921249 0.000000 c
+-9.921249 -2.631393 -8.875763 -5.154694 -7.015228 -7.015228 c
+-5.154694 -8.875763 -2.631393 -9.921249 0.000000 -9.921249 c
+2.631393 -9.921249 5.154694 -8.875763 7.015228 -7.015228 c
+8.875763 -5.154694 9.921249 -2.631393 9.921249 0.000000 c
+h S
+0.500000 w
+11.338562 0.000000 m
+11.338562 3.007309 10.143738 5.891083 8.017410 8.017410 c
+5.891083 10.143738 3.007309 11.338562 0.000000 11.338562 c
+-3.007309 11.338562 -5.891083 10.143738 -8.017410 8.017410 c
+-10.143738 5.891083 -11.338562 3.007309 -11.338562 0.000000 c
+-11.338562 -3.007309 -10.143738 -5.891083 -8.017410 -8.017410 c
+-5.891083 -10.143738 -3.007309 -11.338562 0.000000 -11.338562 c
+3.007309 -11.338562 5.891083 -10.143738 8.017410 -8.017410 c
+10.143738 -5.891083 11.338562 -3.007309 11.338562 0.000000 c
+h S
+0.500000 w
+12.755890 0.000000 m
+12.755890 3.383224 11.411697 6.627472 9.019592 9.019592 c
+6.627472 11.411697 3.383224 12.755890 0.000000 12.755890 c
+-3.383224 12.755890 -6.627472 11.411697 -9.019592 9.019592 c
+-11.411697 6.627472 -12.755890 3.383224 -12.755890 0.000000 c
+-12.755890 -3.383224 -11.411697 -6.627472 -9.019592 -9.019592 c
+-6.627472 -11.411697 -3.383224 -12.755890 0.000000 -12.755890 c
+3.383224 -12.755890 6.627472 -11.411697 9.019592 -9.019592 c
+11.411697 -6.627472 12.755890 -3.383224 12.755890 0.000000 c
+h S
+0.500000 w
+14.173203 0.000000 m
+14.173203 3.759140 12.679672 7.363861 10.021759 10.021759 c
+7.363861 12.679672 3.759140 14.173203 0.000000 14.173203 c
+-3.759140 14.173203 -7.363861 12.679672 -10.021759 10.021759 c
+-12.679672 7.363861 -14.173203 3.759140 -14.173203 0.000000 c
+-14.173203 -3.759140 -12.679672 -7.363861 -10.021759 -10.021759 c
+-7.363861 -12.679672 -3.759140 -14.173203 0.000000 -14.173203 c
+3.759140 -14.173203 7.363861 -12.679672 10.021759 -10.021759 c
+12.679672 -7.363861 14.173203 -3.759140 14.173203 0.000000 c
+h S
+0.500000 w
+15.590530 0.000000 m
+15.590530 4.135040 13.947632 8.100235 11.023941 11.023941 c
+8.100235 13.947632 4.135040 15.590530 0.000000 15.590530 c
+-4.135040 15.590530 -8.100235 13.947632 -11.023941 11.023941 c
+-13.947632 8.100235 -15.590530 4.135040 -15.590530 0.000000 c
+-15.590530 -4.135040 -13.947632 -8.100235 -11.023941 -11.023941 c
+-8.100235 -13.947632 -4.135040 -15.590530 0.000000 -15.590530 c
+4.135040 -15.590530 8.100235 -13.947632 11.023941 -11.023941 c
+13.947632 -8.100235 15.590530 -4.135040 15.590530 0.000000 c
+h S
+0.500000 w
+17.007843 0.000000 m
+17.007843 4.510956 15.215607 8.836624 12.026108 12.026108 c
+8.836624 15.215607 4.510956 17.007843 0.000000 17.007843 c
+-4.510956 17.007843 -8.836624 15.215607 -12.026108 12.026108 c
+-15.215607 8.836624 -17.007843 4.510956 -17.007843 0.000000 c
+-17.007843 -4.510956 -15.215607 -8.836624 -12.026108 -12.026108 c
+-8.836624 -15.215607 -4.510956 -17.007843 0.000000 -17.007843 c
+4.510956 -17.007843 8.836624 -15.215607 12.026108 -12.026108 c
+15.215607 -8.836624 17.007843 -4.510956 17.007843 0.000000 c
+h S
+0.500000 w
+18.425171 0.000000 m
+18.425171 4.886871 16.483566 9.573013 13.028290 13.028290 c
+9.573013 16.483566 4.886871 18.425171 0.000000 18.425171 c
+-4.886871 18.425171 -9.573013 16.483566 -13.028290 13.028290 c
+-16.483566 9.573013 -18.425171 4.886871 -18.425171 0.000000 c
+-18.425171 -4.886871 -16.483566 -9.573013 -13.028290 -13.028290 c
+-9.573013 -16.483566 -4.886871 -18.425171 0.000000 -18.425171 c
+4.886871 -18.425171 9.573013 -16.483566 13.028290 -13.028290 c
+16.483566 -9.573013 18.425171 -4.886871 18.425171 0.000000 c
+h S
+0.500000 w
+19.842484 0.000000 m
+19.842484 5.262787 17.751541 10.309402 14.030472 14.030472 c
+10.309402 17.751541 5.262787 19.842484 0.000000 19.842484 c
+-5.262787 19.842484 -10.309402 17.751541 -14.030472 14.030472 c
+-17.751541 10.309402 -19.842484 5.262787 -19.842484 0.000000 c
+-19.842484 -5.262787 -17.751541 -10.309402 -14.030472 -14.030472 c
+-10.309402 -17.751541 -5.262787 -19.842484 0.000000 -19.842484 c
+5.262787 -19.842484 10.309402 -17.751541 14.030472 -14.030472 c
+17.751541 -10.309402 19.842484 -5.262787 19.842484 0.000000 c
+h S
+0.500000 w
+21.259811 0.000000 m
+21.259811 5.638702 19.019501 11.045776 15.032639 15.032639 c
+11.045776 19.019501 5.638702 21.259811 0.000000 21.259811 c
+-5.638702 21.259811 -11.045776 19.019501 -15.032639 15.032639 c
+-19.019501 11.045776 -21.259811 5.638702 -21.259811 0.000000 c
+-21.259811 -5.638702 -19.019501 -11.045776 -15.032639 -15.032639 c
+-11.045776 -19.019501 -5.638702 -21.259811 0.000000 -21.259811 c
+5.638702 -21.259811 11.045776 -19.019501 15.032639 -15.032639 c
+19.019501 -11.045776 21.259811 -5.638702 21.259811 0.000000 c
+h S
+0.500000 w
+22.677124 0.000000 m
+22.677124 6.014618 20.287476 11.782166 16.034821 16.034821 c
+11.782166 20.287476 6.014618 22.677124 0.000000 22.677124 c
+-6.014618 22.677124 -11.782166 20.287476 -16.034821 16.034821 c
+-20.287476 11.782166 -22.677124 6.014618 -22.677124 0.000000 c
+-22.677124 -6.014618 -20.287476 -11.782166 -16.034821 -16.034821 c
+-11.782166 -20.287476 -6.014618 -22.677124 0.000000 -22.677124 c
+6.014618 -22.677124 11.782166 -20.287476 16.034821 -16.034821 c
+20.287476 -11.782166 22.677124 -6.014618 22.677124 0.000000 c
+h S
+0.500000 w
+24.094452 0.000000 m
+24.094452 6.390533 21.555435 12.518555 17.037003 17.037003 c
+12.518555 21.555435 6.390533 24.094452 0.000000 24.094452 c
+-6.390533 24.094452 -12.518555 21.555435 -17.037003 17.037003 c
+-21.555435 12.518555 -24.094452 6.390533 -24.094452 0.000000 c
+-24.094452 -6.390533 -21.555435 -12.518555 -17.037003 -17.037003 c
+-12.518555 -21.555435 -6.390533 -24.094452 0.000000 -24.094452 c
+6.390533 -24.094452 12.518555 -21.555435 17.037003 -17.037003 c
+21.555435 -12.518555 24.094452 -6.390533 24.094452 0.000000 c
+h S
+0.500000 w
+25.511765 0.000000 m
+25.511765 6.766434 22.823410 13.254944 18.039169 18.039169 c
+13.254944 22.823410 6.766434 25.511765 0.000000 25.511765 c
+-6.766434 25.511765 -13.254944 22.823410 -18.039169 18.039169 c
+-22.823410 13.254944 -25.511765 6.766434 -25.511765 0.000000 c
+-25.511765 -6.766434 -22.823410 -13.254944 -18.039169 -18.039169 c
+-13.254944 -22.823410 -6.766434 -25.511765 0.000000 -25.511765 c
+6.766434 -25.511765 13.254944 -22.823410 18.039169 -18.039169 c
+22.823410 -13.254944 25.511765 -6.766434 25.511765 0.000000 c
+h S
+0.500000 w
+26.929092 0.000000 m
+26.929092 7.142349 24.091370 13.991318 19.041351 19.041351 c
+13.991318 24.091370 7.142349 26.929092 0.000000 26.929092 c
+-7.142349 26.929092 -13.991318 24.091370 -19.041351 19.041351 c
+-24.091370 13.991318 -26.929092 7.142349 -26.929092 0.000000 c
+-26.929092 -7.142349 -24.091370 -13.991318 -19.041351 -19.041351 c
+-13.991318 -24.091370 -7.142349 -26.929092 0.000000 -26.929092 c
+7.142349 -26.929092 13.991318 -24.091370 19.041351 -19.041351 c
+24.091370 -13.991318 26.929092 -7.142349 26.929092 0.000000 c
+h S
+0.500000 w
+28.346405 0.000000 m
+28.346405 7.518265 25.359344 14.727707 20.043518 20.043518 c
+14.727707 25.359344 7.518265 28.346405 0.000000 28.346405 c
+-7.518265 28.346405 -14.727707 25.359344 -20.043518 20.043518 c
+-25.359344 14.727707 -28.346405 7.518265 -28.346405 0.000000 c
+-28.346405 -7.518265 -25.359344 -14.727707 -20.043518 -20.043518 c
+-14.727707 -25.359344 -7.518265 -28.346405 0.000000 -28.346405 c
+7.518265 -28.346405 14.727707 -25.359344 20.043518 -20.043518 c
+25.359344 -14.727707 28.346405 -7.518265 28.346405 0.000000 c
+h S
+0.500000 w
+29.763733 0.000000 m
+29.763733 7.894180 26.627304 15.464096 21.045700 21.045700 c
+15.464096 26.627304 7.894180 29.763733 0.000000 29.763733 c
+-7.894180 29.763733 -15.464096 26.627304 -21.045700 21.045700 c
+-26.627304 15.464096 -29.763733 7.894180 -29.763733 0.000000 c
+-29.763733 -7.894180 -26.627304 -15.464096 -21.045700 -21.045700 c
+-15.464096 -26.627304 -7.894180 -29.763733 0.000000 -29.763733 c
+7.894180 -29.763733 15.464096 -26.627304 21.045700 -21.045700 c
+26.627304 -15.464096 29.763733 -7.894180 29.763733 0.000000 c
+h S
+0.500000 w
+31.181046 0.000000 m
+31.181046 8.270096 27.895279 16.200485 22.047882 22.047882 c
+16.200485 27.895279 8.270096 31.181046 0.000000 31.181046 c
+-8.270096 31.181046 -16.200485 27.895279 -22.047882 22.047882 c
+-27.895279 16.200485 -31.181046 8.270096 -31.181046 0.000000 c
+-31.181046 -8.270096 -27.895279 -16.200485 -22.047882 -22.047882 c
+-16.200485 -27.895279 -8.270096 -31.181046 0.000000 -31.181046 c
+8.270096 -31.181046 16.200485 -27.895279 22.047882 -22.047882 c
+27.895279 -16.200485 31.181046 -8.270096 31.181046 0.000000 c
+h S
+0.500000 w
+32.598373 0.000000 m
+32.598373 8.646011 29.163239 16.936859 23.050049 23.050049 c
+16.936859 29.163239 8.646011 32.598373 0.000000 32.598373 c
+-8.646011 32.598373 -16.936859 29.163239 -23.050049 23.050049 c
+-29.163239 16.936859 -32.598373 8.646011 -32.598373 0.000000 c
+-32.598373 -8.646011 -29.163239 -16.936859 -23.050049 -23.050049 c
+-16.936859 -29.163239 -8.646011 -32.598373 0.000000 -32.598373 c
+8.646011 -32.598373 16.936859 -29.163239 23.050049 -23.050049 c
+29.163239 -16.936859 32.598373 -8.646011 32.598373 0.000000 c
+h S
+0.500000 w
+34.015686 0.000000 m
+34.015686 9.021927 30.431213 17.673248 24.052231 24.052231 c
+17.673248 30.431213 9.021927 34.015686 0.000000 34.015686 c
+-9.021927 34.015686 -17.673248 30.431213 -24.052231 24.052231 c
+-30.431213 17.673248 -34.015686 9.021927 -34.015686 0.000000 c
+-34.015686 -9.021927 -30.431213 -17.673248 -24.052231 -24.052231 c
+-17.673248 -30.431213 -9.021927 -34.015686 0.000000 -34.015686 c
+9.021927 -34.015686 17.673248 -30.431213 24.052231 -24.052231 c
+30.431213 -17.673248 34.015686 -9.021927 34.015686 0.000000 c
+h S
+0.500000 w
+35.433014 0.000000 m
+35.433014 9.397842 31.699173 18.409637 25.054413 25.054413 c
+18.409637 31.699173 9.397842 35.433014 0.000000 35.433014 c
+-9.397842 35.433014 -18.409637 31.699173 -25.054413 25.054413 c
+-31.699173 18.409637 -35.433014 9.397842 -35.433014 0.000000 c
+-35.433014 -9.397842 -31.699173 -18.409637 -25.054413 -25.054413 c
+-18.409637 -31.699173 -9.397842 -35.433014 0.000000 -35.433014 c
+9.397842 -35.433014 18.409637 -31.699173 25.054413 -25.054413 c
+31.699173 -18.409637 35.433014 -9.397842 35.433014 0.000000 c
+h S
+0.500000 w
+36.850327 0.000000 m
+36.850327 9.773743 32.967148 19.146027 26.056580 26.056580 c
+19.146027 32.967148 9.773743 36.850327 0.000000 36.850327 c
+-9.773743 36.850327 -19.146027 32.967148 -26.056580 26.056580 c
+-32.967148 19.146027 -36.850327 9.773743 -36.850327 0.000000 c
+-36.850327 -9.773743 -32.967148 -19.146027 -26.056580 -26.056580 c
+-19.146027 -32.967148 -9.773743 -36.850327 0.000000 -36.850327 c
+9.773743 -36.850327 19.146027 -32.967148 26.056580 -26.056580 c
+32.967148 -19.146027 36.850327 -9.773743 36.850327 0.000000 c
+h S
+0.500000 w
+38.267654 0.000000 m
+38.267654 10.149658 34.235107 19.882401 27.058762 27.058762 c
+19.882401 34.235107 10.149658 38.267654 0.000000 38.267654 c
+-10.149658 38.267654 -19.882401 34.235107 -27.058762 27.058762 c
+-34.235107 19.882401 -38.267654 10.149658 -38.267654 0.000000 c
+-38.267654 -10.149658 -34.235107 -19.882401 -27.058762 -27.058762 c
+-19.882401 -34.235107 -10.149658 -38.267654 0.000000 -38.267654 c
+10.149658 -38.267654 19.882401 -34.235107 27.058762 -27.058762 c
+34.235107 -19.882401 38.267654 -10.149658 38.267654 0.000000 c
+h S
+0.500000 w
+39.684967 0.000000 m
+39.684967 10.525574 35.503082 20.618790 28.060928 28.060928 c
+20.618790 35.503082 10.525574 39.684967 0.000000 39.684967 c
+-10.525574 39.684967 -20.618790 35.503082 -28.060928 28.060928 c
+-35.503082 20.618790 -39.684967 10.525574 -39.684967 0.000000 c
+-39.684967 -10.525574 -35.503082 -20.618790 -28.060928 -28.060928 c
+-20.618790 -35.503082 -10.525574 -39.684967 0.000000 -39.684967 c
+10.525574 -39.684967 20.618790 -35.503082 28.060928 -28.060928 c
+35.503082 -20.618790 39.684967 -10.525574 39.684967 0.000000 c
+h S
+0.500000 w
+41.102295 0.000000 m
+41.102295 10.901489 36.771042 21.355179 29.063110 29.063110 c
+21.355179 36.771042 10.901489 41.102295 0.000000 41.102295 c
+-10.901489 41.102295 -21.355179 36.771042 -29.063110 29.063110 c
+-36.771042 21.355179 -41.102295 10.901489 -41.102295 0.000000 c
+-41.102295 -10.901489 -36.771042 -21.355179 -29.063110 -29.063110 c
+-21.355179 -36.771042 -10.901489 -41.102295 0.000000 -41.102295 c
+10.901489 -41.102295 21.355179 -36.771042 29.063110 -29.063110 c
+36.771042 -21.355179 41.102295 -10.901489 41.102295 0.000000 c
+h S
+0.500000 w
+42.519608 0.000000 m
+42.519608 11.277405 38.039017 22.091568 30.065292 30.065292 c
+22.091568 38.039017 11.277405 42.519608 0.000000 42.519608 c
+-11.277405 42.519608 -22.091568 38.039017 -30.065292 30.065292 c
+-38.039017 22.091568 -42.519608 11.277405 -42.519608 0.000000 c
+-42.519608 -11.277405 -38.039017 -22.091568 -30.065292 -30.065292 c
+-22.091568 -38.039017 -11.277405 -42.519608 0.000000 -42.519608 c
+11.277405 -42.519608 22.091568 -38.039017 30.065292 -30.065292 c
+38.039017 -22.091568 42.519608 -11.277405 42.519608 0.000000 c
+h S
+0.500000 w
+43.936935 0.000000 m
+43.936935 11.653320 39.306976 22.827942 31.067459 31.067459 c
+22.827942 39.306976 11.653320 43.936935 0.000000 43.936935 c
+-11.653320 43.936935 -22.827942 39.306976 -31.067459 31.067459 c
+-39.306976 22.827942 -43.936935 11.653320 -43.936935 0.000000 c
+-43.936935 -11.653320 -39.306976 -22.827942 -31.067459 -31.067459 c
+-22.827942 -39.306976 -11.653320 -43.936935 0.000000 -43.936935 c
+11.653320 -43.936935 22.827942 -39.306976 31.067459 -31.067459 c
+39.306976 -22.827942 43.936935 -11.653320 43.936935 0.000000 c
+h S
+0.500000 w
+45.354248 0.000000 m
+45.354248 12.029236 40.574951 23.564331 32.069641 32.069641 c
+23.564331 40.574951 12.029236 45.354248 0.000000 45.354248 c
+-12.029236 45.354248 -23.564331 40.574951 -32.069641 32.069641 c
+-40.574951 23.564331 -45.354248 12.029236 -45.354248 0.000000 c
+-45.354248 -12.029236 -40.574951 -23.564331 -32.069641 -32.069641 c
+-23.564331 -40.574951 -12.029236 -45.354248 0.000000 -45.354248 c
+12.029236 -45.354248 23.564331 -40.574951 32.069641 -32.069641 c
+40.574951 -23.564331 45.354248 -12.029236 45.354248 0.000000 c
+h S
+0.500000 w
+46.771576 0.000000 m
+46.771576 12.405136 41.842911 24.300720 33.071808 33.071808 c
+24.300720 41.842911 12.405136 46.771576 0.000000 46.771576 c
+-12.405136 46.771576 -24.300720 41.842911 -33.071808 33.071808 c
+-41.842911 24.300720 -46.771576 12.405136 -46.771576 0.000000 c
+-46.771576 -12.405136 -41.842911 -24.300720 -33.071808 -33.071808 c
+-24.300720 -41.842911 -12.405136 -46.771576 0.000000 -46.771576 c
+12.405136 -46.771576 24.300720 -41.842911 33.071808 -33.071808 c
+41.842911 -24.300720 46.771576 -12.405136 46.771576 0.000000 c
+h S
+0.500000 w
+48.188889 0.000000 m
+48.188889 12.781052 43.110886 25.037109 34.073990 34.073990 c
+25.037109 43.110886 12.781052 48.188889 0.000000 48.188889 c
+-12.781052 48.188889 -25.037109 43.110886 -34.073990 34.073990 c
+-43.110886 25.037109 -48.188889 12.781052 -48.188889 0.000000 c
+-48.188889 -12.781052 -43.110886 -25.037109 -34.073990 -34.073990 c
+-25.037109 -43.110886 -12.781052 -48.188889 0.000000 -48.188889 c
+12.781052 -48.188889 25.037109 -43.110886 34.073990 -34.073990 c
+43.110886 -25.037109 48.188889 -12.781052 48.188889 0.000000 c
+h S
+0.500000 w
+49.606216 0.000000 m
+49.606216 13.156967 44.378845 25.773483 35.076172 35.076172 c
+25.773483 44.378845 13.156967 49.606216 0.000000 49.606216 c
+-13.156967 49.606216 -25.773483 44.378845 -35.076172 35.076172 c
+-44.378845 25.773483 -49.606216 13.156967 -49.606216 0.000000 c
+-49.606216 -13.156967 -44.378845 -25.773483 -35.076172 -35.076172 c
+-25.773483 -44.378845 -13.156967 -49.606216 0.000000 -49.606216 c
+13.156967 -49.606216 25.773483 -44.378845 35.076172 -35.076172 c
+44.378845 -25.773483 49.606216 -13.156967 49.606216 0.000000 c
+h S
+0.500000 w
+51.023529 0.000000 m
+51.023529 13.532883 45.646820 26.509872 36.078339 36.078339 c
+26.509872 45.646820 13.532883 51.023529 0.000000 51.023529 c
+-13.532883 51.023529 -26.509872 45.646820 -36.078339 36.078339 c
+-45.646820 26.509872 -51.023529 13.532883 -51.023529 0.000000 c
+-51.023529 -13.532883 -45.646820 -26.509872 -36.078339 -36.078339 c
+-26.509872 -45.646820 -13.532883 -51.023529 0.000000 -51.023529 c
+13.532883 -51.023529 26.509872 -45.646820 36.078339 -36.078339 c
+45.646820 -26.509872 51.023529 -13.532883 51.023529 0.000000 c
+h S
+0.500000 w
+52.440857 0.000000 m
+52.440857 13.908798 46.914780 27.246262 37.080521 37.080521 c
+27.246262 46.914780 13.908798 52.440857 0.000000 52.440857 c
+-13.908798 52.440857 -27.246262 46.914780 -37.080521 37.080521 c
+-46.914780 27.246262 -52.440857 13.908798 -52.440857 0.000000 c
+-52.440857 -13.908798 -46.914780 -27.246262 -37.080521 -37.080521 c
+-27.246262 -46.914780 -13.908798 -52.440857 0.000000 -52.440857 c
+13.908798 -52.440857 27.246262 -46.914780 37.080521 -37.080521 c
+46.914780 -27.246262 52.440857 -13.908798 52.440857 0.000000 c
+h S
+0.500000 w
+53.858170 0.000000 m
+53.858170 14.284714 48.182739 27.982651 38.082703 38.082703 c
+27.982651 48.182739 14.284714 53.858170 0.000000 53.858170 c
+-14.284714 53.858170 -27.982651 48.182739 -38.082703 38.082703 c
+-48.182739 27.982651 -53.858170 14.284714 -53.858170 0.000000 c
+-53.858170 -14.284714 -48.182739 -27.982651 -38.082703 -38.082703 c
+-27.982651 -48.182739 -14.284714 -53.858170 0.000000 -53.858170 c
+14.284714 -53.858170 27.982651 -48.182739 38.082703 -38.082703 c
+48.182739 -27.982651 53.858170 -14.284714 53.858170 0.000000 c
+h S
+0.500000 w
+55.275497 0.000000 m
+55.275497 14.660629 49.450714 28.719025 39.084869 39.084869 c
+28.719025 49.450714 14.660629 55.275497 0.000000 55.275497 c
+-14.660629 55.275497 -28.719025 49.450714 -39.084869 39.084869 c
+-49.450714 28.719025 -55.275497 14.660629 -55.275497 0.000000 c
+-55.275497 -14.660629 -49.450714 -28.719025 -39.084869 -39.084869 c
+-28.719025 -49.450714 -14.660629 -55.275497 0.000000 -55.275497 c
+14.660629 -55.275497 28.719025 -49.450714 39.084869 -39.084869 c
+49.450714 -28.719025 55.275497 -14.660629 55.275497 0.000000 c
+h S
+0.500000 w
+56.692810 0.000000 m
+56.692810 15.036530 50.718674 29.455414 40.087051 40.087051 c
+29.455414 50.718674 15.036530 56.692810 0.000000 56.692810 c
+-15.036530 56.692810 -29.455414 50.718674 -40.087051 40.087051 c
+-50.718674 29.455414 -56.692810 15.036530 -56.692810 0.000000 c
+-56.692810 -15.036530 -50.718674 -29.455414 -40.087051 -40.087051 c
+-29.455414 -50.718674 -15.036530 -56.692810 0.000000 -56.692810 c
+15.036530 -56.692810 29.455414 -50.718674 40.087051 -40.087051 c
+50.718674 -29.455414 56.692810 -15.036530 56.692810 0.000000 c
+h S
+0.500000 w
+58.110138 0.000000 m
+58.110138 15.412445 51.986649 30.191803 41.089218 41.089218 c
+30.191803 51.986649 15.412445 58.110138 0.000000 58.110138 c
+-15.412445 58.110138 -30.191803 51.986649 -41.089218 41.089218 c
+-51.986649 30.191803 -58.110138 15.412445 -58.110138 0.000000 c
+-58.110138 -15.412445 -51.986649 -30.191803 -41.089218 -41.089218 c
+-30.191803 -51.986649 -15.412445 -58.110138 0.000000 -58.110138 c
+15.412445 -58.110138 30.191803 -51.986649 41.089218 -41.089218 c
+51.986649 -30.191803 58.110138 -15.412445 58.110138 0.000000 c
+h S
+0.500000 w
+59.527451 0.000000 m
+59.527451 15.788361 53.254608 30.928192 42.091400 42.091400 c
+30.928192 53.254608 15.788361 59.527451 0.000000 59.527451 c
+-15.788361 59.527451 -30.928192 53.254608 -42.091400 42.091400 c
+-53.254608 30.928192 -59.527451 15.788361 -59.527451 0.000000 c
+-59.527451 -15.788361 -53.254608 -30.928192 -42.091400 -42.091400 c
+-30.928192 -53.254608 -15.788361 -59.527451 0.000000 -59.527451 c
+15.788361 -59.527451 30.928192 -53.254608 42.091400 -42.091400 c
+53.254608 -30.928192 59.527451 -15.788361 59.527451 0.000000 c
+h S
+0.500000 w
+60.944778 0.000000 m
+60.944778 16.164276 54.522583 31.664566 43.093582 43.093582 c
+31.664566 54.522583 16.164276 60.944778 0.000000 60.944778 c
+-16.164276 60.944778 -31.664566 54.522583 -43.093582 43.093582 c
+-54.522583 31.664566 -60.944778 16.164276 -60.944778 0.000000 c
+-60.944778 -16.164276 -54.522583 -31.664566 -43.093582 -43.093582 c
+-31.664566 -54.522583 -16.164276 -60.944778 0.000000 -60.944778 c
+16.164276 -60.944778 31.664566 -54.522583 43.093582 -43.093582 c
+54.522583 -31.664566 60.944778 -16.164276 60.944778 0.000000 c
+h S
+0.500000 w
+62.362091 0.000000 m
+62.362091 16.540192 55.790543 32.400955 44.095749 44.095749 c
+32.400955 55.790543 16.540192 62.362091 0.000000 62.362091 c
+-16.540192 62.362091 -32.400955 55.790543 -44.095749 44.095749 c
+-55.790543 32.400955 -62.362091 16.540192 -62.362091 0.000000 c
+-62.362091 -16.540192 -55.790543 -32.400955 -44.095749 -44.095749 c
+-32.400955 -55.790543 -16.540192 -62.362091 0.000000 -62.362091 c
+16.540192 -62.362091 32.400955 -55.790543 44.095749 -44.095749 c
+55.790543 -32.400955 62.362091 -16.540192 62.362091 0.000000 c
+h S
+0.500000 w
+63.779419 0.000000 m
+63.779419 16.916107 57.058517 33.137344 45.097931 45.097931 c
+33.137344 57.058517 16.916107 63.779419 0.000000 63.779419 c
+-16.916107 63.779419 -33.137344 57.058517 -45.097931 45.097931 c
+-57.058517 33.137344 -63.779419 16.916107 -63.779419 0.000000 c
+-63.779419 -16.916107 -57.058517 -33.137344 -45.097931 -45.097931 c
+-33.137344 -57.058517 -16.916107 -63.779419 0.000000 -63.779419 c
+16.916107 -63.779419 33.137344 -57.058517 45.097931 -45.097931 c
+57.058517 -33.137344 63.779419 -16.916107 63.779419 0.000000 c
+h S
+0.500000 w
+65.196732 0.000000 m
+65.196732 17.292023 58.326477 33.873734 46.100113 46.100113 c
+33.873734 58.326477 17.292023 65.196732 0.000000 65.196732 c
+-17.292023 65.196732 -33.873734 58.326477 -46.100113 46.100113 c
+-58.326477 33.873734 -65.196732 17.292023 -65.196732 0.000000 c
+-65.196732 -17.292023 -58.326477 -33.873734 -46.100113 -46.100113 c
+-33.873734 -58.326477 -17.292023 -65.196732 0.000000 -65.196732 c
+17.292023 -65.196732 33.873734 -58.326477 46.100113 -46.100113 c
+58.326477 -33.873734 65.196732 -17.292023 65.196732 0.000000 c
+h S
+0.500000 w
+66.614059 0.000000 m
+66.614059 17.667923 59.594452 34.610107 47.102280 47.102280 c
+34.610107 59.594452 17.667923 66.614059 0.000000 66.614059 c
+-17.667923 66.614059 -34.610107 59.594452 -47.102280 47.102280 c
+-59.594452 34.610107 -66.614059 17.667923 -66.614059 0.000000 c
+-66.614059 -17.667923 -59.594452 -34.610107 -47.102280 -47.102280 c
+-34.610107 -59.594452 -17.667923 -66.614059 0.000000 -66.614059 c
+17.667923 -66.614059 34.610107 -59.594452 47.102280 -47.102280 c
+59.594452 -34.610107 66.614059 -17.667923 66.614059 0.000000 c
+h S
+0.500000 w
+68.031372 0.000000 m
+68.031372 18.043839 60.862411 35.346497 48.104462 48.104462 c
+35.346497 60.862411 18.043839 68.031372 0.000000 68.031372 c
+-18.043839 68.031372 -35.346497 60.862411 -48.104462 48.104462 c
+-60.862411 35.346497 -68.031372 18.043839 -68.031372 0.000000 c
+-68.031372 -18.043839 -60.862411 -35.346497 -48.104462 -48.104462 c
+-35.346497 -60.862411 -18.043839 -68.031372 0.000000 -68.031372 c
+18.043839 -68.031372 35.346497 -60.862411 48.104462 -48.104462 c
+60.862411 -35.346497 68.031372 -18.043839 68.031372 0.000000 c
+h S
+0.500000 w
+69.448700 0.000000 m
+69.448700 18.419754 62.130386 36.082886 49.106628 49.106628 c
+36.082886 62.130386 18.419754 69.448700 0.000000 69.448700 c
+-18.419754 69.448700 -36.082886 62.130386 -49.106628 49.106628 c
+-62.130386 36.082886 -69.448700 18.419754 -69.448700 0.000000 c
+-69.448700 -18.419754 -62.130386 -36.082886 -49.106628 -49.106628 c
+-36.082886 -62.130386 -18.419754 -69.448700 0.000000 -69.448700 c
+18.419754 -69.448700 36.082886 -62.130386 49.106628 -49.106628 c
+62.130386 -36.082886 69.448700 -18.419754 69.448700 0.000000 c
+h S
+0.500000 w
+70.866013 0.000000 m
+70.866013 18.795670 63.398346 36.819275 50.108810 50.108810 c
+36.819275 63.398346 18.795670 70.866013 0.000000 70.866013 c
+-18.795670 70.866013 -36.819275 63.398346 -50.108810 50.108810 c
+-63.398346 36.819275 -70.866013 18.795670 -70.866013 0.000000 c
+-70.866013 -18.795670 -63.398346 -36.819275 -50.108810 -50.108810 c
+-36.819275 -63.398346 -18.795670 -70.866013 0.000000 -70.866013 c
+18.795670 -70.866013 36.819275 -63.398346 50.108810 -50.108810 c
+63.398346 -36.819275 70.866013 -18.795670 70.866013 0.000000 c
+h S
+0.500000 w
+72.283340 0.000000 m
+72.283340 19.171585 64.666321 37.555649 51.110992 51.110992 c
+37.555649 64.666321 19.171585 72.283340 0.000000 72.283340 c
+-19.171585 72.283340 -37.555649 64.666321 -51.110992 51.110992 c
+-64.666321 37.555649 -72.283340 19.171585 -72.283340 0.000000 c
+-72.283340 -19.171585 -64.666321 -37.555649 -51.110992 -51.110992 c
+-37.555649 -64.666321 -19.171585 -72.283340 0.000000 -72.283340 c
+19.171585 -72.283340 37.555649 -64.666321 51.110992 -51.110992 c
+64.666321 -37.555649 72.283340 -19.171585 72.283340 0.000000 c
+h S
+0.500000 w
+73.700653 0.000000 m
+73.700653 19.547501 65.934280 38.292038 52.113159 52.113159 c
+38.292038 65.934280 19.547501 73.700653 0.000000 73.700653 c
+-19.547501 73.700653 -38.292038 65.934280 -52.113159 52.113159 c
+-65.934280 38.292038 -73.700653 19.547501 -73.700653 0.000000 c
+-73.700653 -19.547501 -65.934280 -38.292038 -52.113159 -52.113159 c
+-38.292038 -65.934280 -19.547501 -73.700653 0.000000 -73.700653 c
+19.547501 -73.700653 38.292038 -65.934280 52.113159 -52.113159 c
+65.934280 -38.292038 73.700653 -19.547501 73.700653 0.000000 c
+h S
+0.500000 w
+75.117981 0.000000 m
+75.117981 19.923416 67.202255 39.028427 53.115341 53.115341 c
+39.028427 67.202255 19.923416 75.117981 0.000000 75.117981 c
+-19.923416 75.117981 -39.028427 67.202255 -53.115341 53.115341 c
+-67.202255 39.028427 -75.117981 19.923416 -75.117981 0.000000 c
+-75.117981 -19.923416 -67.202255 -39.028427 -53.115341 -53.115341 c
+-39.028427 -67.202255 -19.923416 -75.117981 0.000000 -75.117981 c
+19.923416 -75.117981 39.028427 -67.202255 53.115341 -53.115341 c
+67.202255 -39.028427 75.117981 -19.923416 75.117981 0.000000 c
+h S
+0.500000 w
+76.535294 0.000000 m
+76.535294 20.299316 68.470215 39.764816 54.117523 54.117523 c
+39.764816 68.470215 20.299316 76.535294 0.000000 76.535294 c
+-20.299316 76.535294 -39.764816 68.470215 -54.117523 54.117523 c
+-68.470215 39.764816 -76.535294 20.299316 -76.535294 0.000000 c
+-76.535294 -20.299316 -68.470215 -39.764816 -54.117523 -54.117523 c
+-39.764816 -68.470215 -20.299316 -76.535294 0.000000 -76.535294 c
+20.299316 -76.535294 39.764816 -68.470215 54.117523 -54.117523 c
+68.470215 -39.764816 76.535294 -20.299316 76.535294 0.000000 c
+h S
+0.500000 w
+77.952621 0.000000 m
+77.952621 20.675232 69.738190 40.501205 55.119690 55.119690 c
+40.501205 69.738190 20.675232 77.952621 0.000000 77.952621 c
+-20.675232 77.952621 -40.501205 69.738190 -55.119690 55.119690 c
+-69.738190 40.501205 -77.952621 20.675232 -77.952621 0.000000 c
+-77.952621 -20.675232 -69.738190 -40.501205 -55.119690 -55.119690 c
+-40.501205 -69.738190 -20.675232 -77.952621 0.000000 -77.952621 c
+20.675232 -77.952621 40.501205 -69.738190 55.119690 -55.119690 c
+69.738190 -40.501205 77.952621 -20.675232 77.952621 0.000000 c
+h S
+0.500000 w
+79.369934 0.000000 m
+79.369934 21.051147 71.006149 41.237579 56.121872 56.121872 c
+41.237579 71.006149 21.051147 79.369934 0.000000 79.369934 c
+-21.051147 79.369934 -41.237579 71.006149 -56.121872 56.121872 c
+-71.006149 41.237579 -79.369934 21.051147 -79.369934 0.000000 c
+-79.369934 -21.051147 -71.006149 -41.237579 -56.121872 -56.121872 c
+-41.237579 -71.006149 -21.051147 -79.369934 0.000000 -79.369934 c
+21.051147 -79.369934 41.237579 -71.006149 56.121872 -56.121872 c
+71.006149 -41.237579 79.369934 -21.051147 79.369934 0.000000 c
+h S
+0.500000 w
+80.787262 0.000000 m
+80.787262 21.427063 72.274124 41.973969 57.124039 57.124039 c
+41.973969 72.274124 21.427063 80.787262 0.000000 80.787262 c
+-21.427063 80.787262 -41.973969 72.274124 -57.124039 57.124039 c
+-72.274124 41.973969 -80.787262 21.427063 -80.787262 0.000000 c
+-80.787262 -21.427063 -72.274124 -41.973969 -57.124039 -57.124039 c
+-41.973969 -72.274124 -21.427063 -80.787262 0.000000 -80.787262 c
+21.427063 -80.787262 41.973969 -72.274124 57.124039 -57.124039 c
+72.274124 -41.973969 80.787262 -21.427063 80.787262 0.000000 c
+h S
+0.500000 w
+82.204575 0.000000 m
+82.204575 21.802979 73.542084 42.710358 58.126221 58.126221 c
+42.710358 73.542084 21.802979 82.204575 0.000000 82.204575 c
+-21.802979 82.204575 -42.710358 73.542084 -58.126221 58.126221 c
+-73.542084 42.710358 -82.204575 21.802979 -82.204575 0.000000 c
+-82.204575 -21.802979 -73.542084 -42.710358 -58.126221 -58.126221 c
+-42.710358 -73.542084 -21.802979 -82.204575 0.000000 -82.204575 c
+21.802979 -82.204575 42.710358 -73.542084 58.126221 -58.126221 c
+73.542084 -42.710358 82.204575 -21.802979 82.204575 0.000000 c
+h S
+0.500000 w
+83.621902 0.000000 m
+83.621902 22.178894 74.810059 43.446747 59.128403 59.128403 c
+43.446747 74.810059 22.178894 83.621902 0.000000 83.621902 c
+-22.178894 83.621902 -43.446747 74.810059 -59.128403 59.128403 c
+-74.810059 43.446747 -83.621902 22.178894 -83.621902 0.000000 c
+-83.621902 -22.178894 -74.810059 -43.446747 -59.128403 -59.128403 c
+-43.446747 -74.810059 -22.178894 -83.621902 0.000000 -83.621902 c
+22.178894 -83.621902 43.446747 -74.810059 59.128403 -59.128403 c
+74.810059 -43.446747 83.621902 -22.178894 83.621902 0.000000 c
+h S
+0.500000 w
+85.039215 0.000000 m
+85.039215 22.554810 76.078018 44.183121 60.130569 60.130569 c
+44.183121 76.078018 22.554810 85.039215 0.000000 85.039215 c
+-22.554810 85.039215 -44.183121 76.078018 -60.130569 60.130569 c
+-76.078018 44.183121 -85.039215 22.554810 -85.039215 0.000000 c
+-85.039215 -22.554810 -76.078018 -44.183121 -60.130569 -60.130569 c
+-44.183121 -76.078018 -22.554810 -85.039215 0.000000 -85.039215 c
+22.554810 -85.039215 44.183121 -76.078018 60.130569 -60.130569 c
+76.078018 -44.183121 85.039215 -22.554810 85.039215 0.000000 c
+h S
+0.500000 w
+86.456543 0.000000 m
+86.456543 22.930710 77.345993 44.919510 61.132751 61.132751 c
+44.919510 77.345993 22.930710 86.456543 0.000000 86.456543 c
+-22.930710 86.456543 -44.919510 77.345993 -61.132751 61.132751 c
+-77.345993 44.919510 -86.456543 22.930710 -86.456543 0.000000 c
+-86.456543 -22.930710 -77.345993 -44.919510 -61.132751 -61.132751 c
+-44.919510 -77.345993 -22.930710 -86.456543 0.000000 -86.456543 c
+22.930710 -86.456543 44.919510 -77.345993 61.132751 -61.132751 c
+77.345993 -44.919510 86.456543 -22.930710 86.456543 0.000000 c
+h S
+0.500000 w
+87.873856 0.000000 m
+87.873856 23.306625 78.613953 45.655899 62.134918 62.134918 c
+45.655899 78.613953 23.306625 87.873856 0.000000 87.873856 c
+-23.306625 87.873856 -45.655899 78.613953 -62.134918 62.134918 c
+-78.613953 45.655899 -87.873856 23.306625 -87.873856 0.000000 c
+-87.873856 -23.306625 -78.613953 -45.655899 -62.134918 -62.134918 c
+-45.655899 -78.613953 -23.306625 -87.873856 0.000000 -87.873856 c
+23.306625 -87.873856 45.655899 -78.613953 62.134918 -62.134918 c
+78.613953 -45.655899 87.873856 -23.306625 87.873856 0.000000 c
+h S
+0.500000 w
+89.291183 0.000000 m
+89.291183 23.682541 79.881927 46.392288 63.137100 63.137100 c
+46.392288 79.881927 23.682541 89.291183 0.000000 89.291183 c
+-23.682541 89.291183 -46.392288 79.881927 -63.137100 63.137100 c
+-79.881927 46.392288 -89.291183 23.682541 -89.291183 0.000000 c
+-89.291183 -23.682541 -79.881927 -46.392288 -63.137100 -63.137100 c
+-46.392288 -79.881927 -23.682541 -89.291183 0.000000 -89.291183 c
+23.682541 -89.291183 46.392288 -79.881927 63.137100 -63.137100 c
+79.881927 -46.392288 89.291183 -23.682541 89.291183 0.000000 c
+h S
+0.500000 w
+90.708496 0.000000 m
+90.708496 24.058456 81.149887 47.128662 64.139282 64.139282 c
+47.128662 81.149887 24.058456 90.708496 0.000000 90.708496 c
+-24.058456 90.708496 -47.128662 81.149887 -64.139282 64.139282 c
+-81.149887 47.128662 -90.708496 24.058456 -90.708496 0.000000 c
+-90.708496 -24.058456 -81.149887 -47.128662 -64.139282 -64.139282 c
+-47.128662 -81.149887 -24.058456 -90.708496 0.000000 -90.708496 c
+24.058456 -90.708496 47.128662 -81.149887 64.139282 -64.139282 c
+81.149887 -47.128662 90.708496 -24.058456 90.708496 0.000000 c
+h S
+0.500000 w
+92.125824 0.000000 m
+92.125824 24.434372 82.417862 47.865051 65.141449 65.141449 c
+47.865051 82.417862 24.434372 92.125824 0.000000 92.125824 c
+-24.434372 92.125824 -47.865051 82.417862 -65.141449 65.141449 c
+-82.417862 47.865051 -92.125824 24.434372 -92.125824 0.000000 c
+-92.125824 -24.434372 -82.417862 -47.865051 -65.141449 -65.141449 c
+-47.865051 -82.417862 -24.434372 -92.125824 0.000000 -92.125824 c
+24.434372 -92.125824 47.865051 -82.417862 65.141449 -65.141449 c
+82.417862 -47.865051 92.125824 -24.434372 92.125824 0.000000 c
+h S
+0.500000 w
+93.543137 0.000000 m
+93.543137 24.810287 83.685822 48.601440 66.143631 66.143631 c
+48.601440 83.685822 24.810287 93.543137 0.000000 93.543137 c
+-24.810287 93.543137 -48.601440 83.685822 -66.143631 66.143631 c
+-83.685822 48.601440 -93.543137 24.810287 -93.543137 0.000000 c
+-93.543137 -24.810287 -83.685822 -48.601440 -66.143631 -66.143631 c
+-48.601440 -83.685822 -24.810287 -93.543137 0.000000 -93.543137 c
+24.810287 -93.543137 48.601440 -83.685822 66.143631 -66.143631 c
+83.685822 -48.601440 93.543137 -24.810287 93.543137 0.000000 c
+h S
+0.500000 w
+94.960464 0.000000 m
+94.960464 25.186203 84.953796 49.337830 67.145813 67.145813 c
+49.337830 84.953796 25.186203 94.960464 0.000000 94.960464 c
+-25.186203 94.960464 -49.337830 84.953796 -67.145813 67.145813 c
+-84.953796 49.337830 -94.960464 25.186203 -94.960464 0.000000 c
+-94.960464 -25.186203 -84.953796 -49.337830 -67.145813 -67.145813 c
+-49.337830 -84.953796 -25.186203 -94.960464 0.000000 -94.960464 c
+25.186203 -94.960464 49.337830 -84.953796 67.145813 -67.145813 c
+84.953796 -49.337830 94.960464 -25.186203 94.960464 0.000000 c
+h S
+0.500000 w
+96.377777 0.000000 m
+96.377777 25.562119 86.221756 50.074203 68.147980 68.147980 c
+50.074203 86.221756 25.562119 96.377777 0.000000 96.377777 c
+-25.562119 96.377777 -50.074203 86.221756 -68.147980 68.147980 c
+-86.221756 50.074203 -96.377777 25.562119 -96.377777 0.000000 c
+-96.377777 -25.562119 -86.221756 -50.074203 -68.147980 -68.147980 c
+-50.074203 -86.221756 -25.562119 -96.377777 0.000000 -96.377777 c
+25.562119 -96.377777 50.074203 -86.221756 68.147980 -68.147980 c
+86.221756 -50.074203 96.377777 -25.562119 96.377777 0.000000 c
+h S
+0.500000 w
+97.795105 0.000000 m
+97.795105 25.938019 87.489731 50.810593 69.150162 69.150162 c
+50.810593 87.489731 25.938019 97.795105 0.000000 97.795105 c
+-25.938019 97.795105 -50.810593 87.489731 -69.150162 69.150162 c
+-87.489731 50.810593 -97.795105 25.938019 -97.795105 0.000000 c
+-97.795105 -25.938019 -87.489731 -50.810593 -69.150162 -69.150162 c
+-50.810593 -87.489731 -25.938019 -97.795105 0.000000 -97.795105 c
+25.938019 -97.795105 50.810593 -87.489731 69.150162 -69.150162 c
+87.489731 -50.810593 97.795105 -25.938019 97.795105 0.000000 c
+h S
+0.500000 w
+99.212418 0.000000 m
+99.212418 26.313934 88.757690 51.546982 70.152328 70.152328 c
+51.546982 88.757690 26.313934 99.212418 0.000000 99.212418 c
+-26.313934 99.212418 -51.546982 88.757690 -70.152328 70.152328 c
+-88.757690 51.546982 -99.212418 26.313934 -99.212418 0.000000 c
+-99.212418 -26.313934 -88.757690 -51.546982 -70.152328 -70.152328 c
+-51.546982 -88.757690 -26.313934 -99.212418 0.000000 -99.212418 c
+26.313934 -99.212418 51.546982 -88.757690 70.152328 -70.152328 c
+88.757690 -51.546982 99.212418 -26.313934 99.212418 0.000000 c
+h S
+0.500000 w
+100.629745 0.000000 m
+100.629745 26.689850 90.025665 52.283371 71.154510 71.154510 c
+52.283371 90.025665 26.689850 100.629745 0.000000 100.629745 c
+-26.689850 100.629745 -52.283371 90.025665 -71.154510 71.154510 c
+-90.025665 52.283371 -100.629745 26.689850 -100.629745 0.000000 c
+-100.629745 -26.689850 -90.025665 -52.283371 -71.154510 -71.154510 c
+-52.283371 -90.025665 -26.689850 -100.629745 0.000000 -100.629745 c
+26.689850 -100.629745 52.283371 -90.025665 71.154510 -71.154510 c
+90.025665 -52.283371 100.629745 -26.689850 100.629745 0.000000 c
+h S
+0.500000 w
+102.047058 0.000000 m
+102.047058 27.065765 91.293625 53.019745 72.156693 72.156693 c
+53.019745 91.293625 27.065765 102.047058 0.000000 102.047058 c
+-27.065765 102.047058 -53.019745 91.293625 -72.156693 72.156693 c
+-91.293625 53.019745 -102.047058 27.065765 -102.047058 0.000000 c
+-102.047058 -27.065765 -91.293625 -53.019745 -72.156693 -72.156693 c
+-53.019745 -91.293625 -27.065765 -102.047058 0.000000 -102.047058 c
+27.065765 -102.047058 53.019745 -91.293625 72.156693 -72.156693 c
+91.293625 -53.019745 102.047058 -27.065765 102.047058 0.000000 c
+h S
+0.500000 w
+103.464386 0.000000 m
+103.464386 27.441681 92.561600 53.756134 73.158859 73.158859 c
+53.756134 92.561600 27.441681 103.464386 0.000000 103.464386 c
+-27.441681 103.464386 -53.756134 92.561600 -73.158859 73.158859 c
+-92.561600 53.756134 -103.464386 27.441681 -103.464386 0.000000 c
+-103.464386 -27.441681 -92.561600 -53.756134 -73.158859 -73.158859 c
+-53.756134 -92.561600 -27.441681 -103.464386 0.000000 -103.464386 c
+27.441681 -103.464386 53.756134 -92.561600 73.158859 -73.158859 c
+92.561600 -53.756134 103.464386 -27.441681 103.464386 0.000000 c
+h S
+0.500000 w
+104.881699 0.000000 m
+104.881699 27.817596 93.829559 54.492523 74.161041 74.161041 c
+54.492523 93.829559 27.817596 104.881699 0.000000 104.881699 c
+-27.817596 104.881699 -54.492523 93.829559 -74.161041 74.161041 c
+-93.829559 54.492523 -104.881699 27.817596 -104.881699 0.000000 c
+-104.881699 -27.817596 -93.829559 -54.492523 -74.161041 -74.161041 c
+-54.492523 -93.829559 -27.817596 -104.881699 0.000000 -104.881699 c
+27.817596 -104.881699 54.492523 -93.829559 74.161041 -74.161041 c
+93.829559 -54.492523 104.881699 -27.817596 104.881699 0.000000 c
+h S
+0.500000 w
+106.299026 0.000000 m
+106.299026 28.193512 95.097519 55.228912 75.163223 75.163223 c
+55.228912 95.097519 28.193512 106.299026 0.000000 106.299026 c
+-28.193512 106.299026 -55.228912 95.097519 -75.163223 75.163223 c
+-95.097519 55.228912 -106.299026 28.193512 -106.299026 0.000000 c
+-106.299026 -28.193512 -95.097519 -55.228912 -75.163223 -75.163223 c
+-55.228912 -95.097519 -28.193512 -106.299026 0.000000 -106.299026 c
+28.193512 -106.299026 55.228912 -95.097519 75.163223 -75.163223 c
+95.097519 -55.228912 106.299026 -28.193512 106.299026 0.000000 c
+h S
+0.500000 w
+107.716339 0.000000 m
+107.716339 28.569412 96.365494 55.965286 76.165390 76.165390 c
+55.965286 96.365494 28.569412 107.716339 0.000000 107.716339 c
+-28.569412 107.716339 -55.965286 96.365494 -76.165390 76.165390 c
+-96.365494 55.965286 -107.716339 28.569412 -107.716339 0.000000 c
+-107.716339 -28.569412 -96.365494 -55.965286 -76.165390 -76.165390 c
+-55.965286 -96.365494 -28.569412 -107.716339 0.000000 -107.716339 c
+28.569412 -107.716339 55.965286 -96.365494 76.165390 -76.165390 c
+96.365494 -55.965286 107.716339 -28.569412 107.716339 0.000000 c
+h S
+0.500000 w
+109.133667 0.000000 m
+109.133667 28.945328 97.633453 56.701675 77.167572 77.167572 c
+56.701675 97.633453 28.945328 109.133667 0.000000 109.133667 c
+-28.945328 109.133667 -56.701675 97.633453 -77.167572 77.167572 c
+-97.633453 56.701675 -109.133667 28.945328 -109.133667 0.000000 c
+-109.133667 -28.945328 -97.633453 -56.701675 -77.167572 -77.167572 c
+-56.701675 -97.633453 -28.945328 -109.133667 0.000000 -109.133667 c
+28.945328 -109.133667 56.701675 -97.633453 77.167572 -77.167572 c
+97.633453 -56.701675 109.133667 -28.945328 109.133667 0.000000 c
+h S
+0.500000 w
+110.550980 0.000000 m
+110.550980 29.321243 98.901428 57.438065 78.169739 78.169739 c
+57.438065 98.901428 29.321243 110.550980 0.000000 110.550980 c
+-29.321243 110.550980 -57.438065 98.901428 -78.169739 78.169739 c
+-98.901428 57.438065 -110.550980 29.321243 -110.550980 0.000000 c
+-110.550980 -29.321243 -98.901428 -57.438065 -78.169739 -78.169739 c
+-57.438065 -98.901428 -29.321243 -110.550980 0.000000 -110.550980 c
+29.321243 -110.550980 57.438065 -98.901428 78.169739 -78.169739 c
+98.901428 -57.438065 110.550980 -29.321243 110.550980 0.000000 c
+h S
+0.500000 w
+111.968307 0.000000 m
+111.968307 29.697159 100.169388 58.174454 79.171921 79.171921 c
+58.174454 100.169388 29.697159 111.968307 0.000000 111.968307 c
+-29.697159 111.968307 -58.174454 100.169388 -79.171921 79.171921 c
+-100.169388 58.174454 -111.968307 29.697159 -111.968307 0.000000 c
+-111.968307 -29.697159 -100.169388 -58.174454 -79.171921 -79.171921 c
+-58.174454 -100.169388 -29.697159 -111.968307 0.000000 -111.968307 c
+29.697159 -111.968307 58.174454 -100.169388 79.171921 -79.171921 c
+100.169388 -58.174454 111.968307 -29.697159 111.968307 0.000000 c
+h S
+0.500000 w
+113.385620 0.000000 m
+113.385620 30.073074 101.437363 58.910828 80.174103 80.174103 c
+58.910828 101.437363 30.073074 113.385620 0.000000 113.385620 c
+-30.073074 113.385620 -58.910828 101.437363 -80.174103 80.174103 c
+-101.437363 58.910828 -113.385620 30.073074 -113.385620 0.000000 c
+-113.385620 -30.073074 -101.437363 -58.910828 -80.174103 -80.174103 c
+-58.910828 -101.437363 -30.073074 -113.385620 0.000000 -113.385620 c
+30.073074 -113.385620 58.910828 -101.437363 80.174103 -80.174103 c
+101.437363 -58.910828 113.385620 -30.073074 113.385620 0.000000 c
+h S
+0.500000 w
+114.802948 0.000000 m
+114.802948 30.448990 102.705322 59.647217 81.176270 81.176270 c
+59.647217 102.705322 30.448990 114.802948 0.000000 114.802948 c
+-30.448990 114.802948 -59.647217 102.705322 -81.176270 81.176270 c
+-102.705322 59.647217 -114.802948 30.448990 -114.802948 0.000000 c
+-114.802948 -30.448990 -102.705322 -59.647217 -81.176270 -81.176270 c
+-59.647217 -102.705322 -30.448990 -114.802948 0.000000 -114.802948 c
+30.448990 -114.802948 59.647217 -102.705322 81.176270 -81.176270 c
+102.705322 -59.647217 114.802948 -30.448990 114.802948 0.000000 c
+h S
+0.500000 w
+116.220261 0.000000 m
+116.220261 30.824905 103.973297 60.383606 82.178452 82.178452 c
+60.383606 103.973297 30.824905 116.220261 0.000000 116.220261 c
+-30.824905 116.220261 -60.383606 103.973297 -82.178452 82.178452 c
+-103.973297 60.383606 -116.220261 30.824905 -116.220261 0.000000 c
+-116.220261 -30.824905 -103.973297 -60.383606 -82.178452 -82.178452 c
+-60.383606 -103.973297 -30.824905 -116.220261 0.000000 -116.220261 c
+30.824905 -116.220261 60.383606 -103.973297 82.178452 -82.178452 c
+103.973297 -60.383606 116.220261 -30.824905 116.220261 0.000000 c
+h S
+0.500000 w
+117.637589 0.000000 m
+117.637589 31.200806 105.241257 61.119995 83.180618 83.180618 c
+61.119995 105.241257 31.200806 117.637589 0.000000 117.637589 c
+-31.200806 117.637589 -61.119995 105.241257 -83.180618 83.180618 c
+-105.241257 61.119995 -117.637589 31.200806 -117.637589 0.000000 c
+-117.637589 -31.200806 -105.241257 -61.119995 -83.180618 -83.180618 c
+-61.119995 -105.241257 -31.200806 -117.637589 0.000000 -117.637589 c
+31.200806 -117.637589 61.119995 -105.241257 83.180618 -83.180618 c
+105.241257 -61.119995 117.637589 -31.200806 117.637589 0.000000 c
+h S
+0.500000 w
+119.054901 0.000000 m
+119.054901 31.576721 106.509232 61.856369 84.182800 84.182800 c
+61.856369 106.509232 31.576721 119.054901 0.000000 119.054901 c
+-31.576721 119.054901 -61.856369 106.509232 -84.182800 84.182800 c
+-106.509232 61.856369 -119.054901 31.576721 -119.054901 0.000000 c
+-119.054901 -31.576721 -106.509232 -61.856369 -84.182800 -84.182800 c
+-61.856369 -106.509232 -31.576721 -119.054901 0.000000 -119.054901 c
+31.576721 -119.054901 61.856369 -106.509232 84.182800 -84.182800 c
+106.509232 -61.856369 119.054901 -31.576721 119.054901 0.000000 c
+h S
+0.500000 w
+120.472229 0.000000 m
+120.472229 31.952637 107.777191 62.592758 85.184982 85.184982 c
+62.592758 107.777191 31.952637 120.472229 0.000000 120.472229 c
+-31.952637 120.472229 -62.592758 107.777191 -85.184982 85.184982 c
+-107.777191 62.592758 -120.472229 31.952637 -120.472229 0.000000 c
+-120.472229 -31.952637 -107.777191 -62.592758 -85.184982 -85.184982 c
+-62.592758 -107.777191 -31.952637 -120.472229 0.000000 -120.472229 c
+31.952637 -120.472229 62.592758 -107.777191 85.184982 -85.184982 c
+107.777191 -62.592758 120.472229 -31.952637 120.472229 0.000000 c
+h S
+0.500000 w
+121.889542 0.000000 m
+121.889542 32.328552 109.045166 63.329147 86.187149 86.187149 c
+63.329147 109.045166 32.328552 121.889542 0.000000 121.889542 c
+-32.328552 121.889542 -63.329147 109.045166 -86.187149 86.187149 c
+-109.045166 63.329147 -121.889542 32.328552 -121.889542 0.000000 c
+-121.889542 -32.328552 -109.045166 -63.329147 -86.187149 -86.187149 c
+-63.329147 -109.045166 -32.328552 -121.889542 0.000000 -121.889542 c
+32.328552 -121.889542 63.329147 -109.045166 86.187149 -86.187149 c
+109.045166 -63.329147 121.889542 -32.328552 121.889542 0.000000 c
+h S
+0.500000 w
+123.306870 0.000000 m
+123.306870 32.704468 110.313126 64.065536 87.189331 87.189331 c
+64.065536 110.313126 32.704468 123.306870 0.000000 123.306870 c
+-32.704468 123.306870 -64.065536 110.313126 -87.189331 87.189331 c
+-110.313126 64.065536 -123.306870 32.704468 -123.306870 0.000000 c
+-123.306870 -32.704468 -110.313126 -64.065536 -87.189331 -87.189331 c
+-64.065536 -110.313126 -32.704468 -123.306870 0.000000 -123.306870 c
+32.704468 -123.306870 64.065536 -110.313126 87.189331 -87.189331 c
+110.313126 -64.065536 123.306870 -32.704468 123.306870 0.000000 c
+h S
+0.500000 w
+124.724182 0.000000 m
+124.724182 33.080383 111.581100 64.801910 88.191513 88.191513 c
+64.801910 111.581100 33.080383 124.724182 0.000000 124.724182 c
+-33.080383 124.724182 -64.801910 111.581100 -88.191513 88.191513 c
+-111.581100 64.801910 -124.724182 33.080383 -124.724182 0.000000 c
+-124.724182 -33.080383 -111.581100 -64.801910 -88.191513 -88.191513 c
+-64.801910 -111.581100 -33.080383 -124.724182 0.000000 -124.724182 c
+33.080383 -124.724182 64.801910 -111.581100 88.191513 -88.191513 c
+111.581100 -64.801910 124.724182 -33.080383 124.724182 0.000000 c
+h S
+0.500000 w
+126.141510 0.000000 m
+126.141510 33.456299 112.849060 65.538300 89.193680 89.193680 c
+65.538300 112.849060 33.456299 126.141510 0.000000 126.141510 c
+-33.456299 126.141510 -65.538300 112.849060 -89.193680 89.193680 c
+-112.849060 65.538300 -126.141510 33.456299 -126.141510 0.000000 c
+-126.141510 -33.456299 -112.849060 -65.538300 -89.193680 -89.193680 c
+-65.538300 -112.849060 -33.456299 -126.141510 0.000000 -126.141510 c
+33.456299 -126.141510 65.538300 -112.849060 89.193680 -89.193680 c
+112.849060 -65.538300 126.141510 -33.456299 126.141510 0.000000 c
+h S
+0.500000 w
+127.558823 0.000000 m
+127.558823 33.832199 114.117035 66.274689 90.195862 90.195862 c
+66.274689 114.117035 33.832199 127.558823 0.000000 127.558823 c
+-33.832199 127.558823 -66.274689 114.117035 -90.195862 90.195862 c
+-114.117035 66.274689 -127.558823 33.832199 -127.558823 0.000000 c
+-127.558823 -33.832199 -114.117035 -66.274689 -90.195862 -90.195862 c
+-66.274689 -114.117035 -33.832199 -127.558823 0.000000 -127.558823 c
+33.832199 -127.558823 66.274689 -114.117035 90.195862 -90.195862 c
+114.117035 -66.274689 127.558823 -33.832199 127.558823 0.000000 c
+h S
+0.500000 w
+128.976151 0.000000 m
+128.976151 34.208115 115.384995 67.011078 91.198029 91.198029 c
+67.011078 115.384995 34.208115 128.976151 0.000000 128.976151 c
+-34.208115 128.976151 -67.011078 115.384995 -91.198029 91.198029 c
+-115.384995 67.011078 -128.976151 34.208115 -128.976151 0.000000 c
+-128.976151 -34.208115 -115.384995 -67.011078 -91.198029 -91.198029 c
+-67.011078 -115.384995 -34.208115 -128.976151 0.000000 -128.976151 c
+34.208115 -128.976151 67.011078 -115.384995 91.198029 -91.198029 c
+115.384995 -67.011078 128.976151 -34.208115 128.976151 0.000000 c
+h S
+0.500000 w
+130.393463 0.000000 m
+130.393463 34.584030 116.652969 67.747452 92.200211 92.200211 c
+67.747452 116.652969 34.584030 130.393463 0.000000 130.393463 c
+-34.584030 130.393463 -67.747452 116.652969 -92.200211 92.200211 c
+-116.652969 67.747452 -130.393463 34.584030 -130.393463 0.000000 c
+-130.393463 -34.584030 -116.652969 -67.747452 -92.200211 -92.200211 c
+-67.747452 -116.652969 -34.584030 -130.393463 0.000000 -130.393463 c
+34.584030 -130.393463 67.747452 -116.652969 92.200211 -92.200211 c
+116.652969 -67.747452 130.393463 -34.584030 130.393463 0.000000 c
+h S
+0.500000 w
+131.810791 0.000000 m
+131.810791 34.959946 117.920929 68.483841 93.202393 93.202393 c
+68.483841 117.920929 34.959946 131.810791 0.000000 131.810791 c
+-34.959946 131.810791 -68.483841 117.920929 -93.202393 93.202393 c
+-117.920929 68.483841 -131.810791 34.959946 -131.810791 0.000000 c
+-131.810791 -34.959946 -117.920929 -68.483841 -93.202393 -93.202393 c
+-68.483841 -117.920929 -34.959946 -131.810791 0.000000 -131.810791 c
+34.959946 -131.810791 68.483841 -117.920929 93.202393 -93.202393 c
+117.920929 -68.483841 131.810791 -34.959946 131.810791 0.000000 c
+h S
+0.500000 w
+133.228104 0.000000 m
+133.228104 35.335861 119.188904 69.220230 94.204559 94.204559 c
+69.220230 119.188904 35.335861 133.228104 0.000000 133.228104 c
+-35.335861 133.228104 -69.220230 119.188904 -94.204559 94.204559 c
+-119.188904 69.220230 -133.228104 35.335861 -133.228104 0.000000 c
+-133.228104 -35.335861 -119.188904 -69.220230 -94.204559 -94.204559 c
+-69.220230 -119.188904 -35.335861 -133.228104 0.000000 -133.228104 c
+35.335861 -133.228104 69.220230 -119.188904 94.204559 -94.204559 c
+119.188904 -69.220230 133.228104 -35.335861 133.228104 0.000000 c
+h S
+0.500000 w
+134.645432 0.000000 m
+134.645432 35.711777 120.456863 69.956619 95.206741 95.206741 c
+69.956619 120.456863 35.711777 134.645432 0.000000 134.645432 c
+-35.711777 134.645432 -69.956619 120.456863 -95.206741 95.206741 c
+-120.456863 69.956619 -134.645432 35.711777 -134.645432 0.000000 c
+-134.645432 -35.711777 -120.456863 -69.956619 -95.206741 -95.206741 c
+-69.956619 -120.456863 -35.711777 -134.645432 0.000000 -134.645432 c
+35.711777 -134.645432 69.956619 -120.456863 95.206741 -95.206741 c
+120.456863 -69.956619 134.645432 -35.711777 134.645432 0.000000 c
+h S
+0.500000 w
+136.062744 0.000000 m
+136.062744 36.087692 121.724838 70.692993 96.208923 96.208923 c
+70.692993 121.724838 36.087692 136.062744 0.000000 136.062744 c
+-36.087692 136.062744 -70.692993 121.724838 -96.208923 96.208923 c
+-121.724838 70.692993 -136.062744 36.087692 -136.062744 0.000000 c
+-136.062744 -36.087692 -121.724838 -70.692993 -96.208923 -96.208923 c
+-70.692993 -121.724838 -36.087692 -136.062744 0.000000 -136.062744 c
+36.087692 -136.062744 70.692993 -121.724838 96.208923 -96.208923 c
+121.724838 -70.692993 136.062744 -36.087692 136.062744 0.000000 c
+h S
+0.500000 w
+137.480072 0.000000 m
+137.480072 36.463593 122.992798 71.429382 97.211090 97.211090 c
+71.429382 122.992798 36.463593 137.480072 0.000000 137.480072 c
+-36.463593 137.480072 -71.429382 122.992798 -97.211090 97.211090 c
+-122.992798 71.429382 -137.480072 36.463593 -137.480072 0.000000 c
+-137.480072 -36.463593 -122.992798 -71.429382 -97.211090 -97.211090 c
+-71.429382 -122.992798 -36.463593 -137.480072 0.000000 -137.480072 c
+36.463593 -137.480072 71.429382 -122.992798 97.211090 -97.211090 c
+122.992798 -71.429382 137.480072 -36.463593 137.480072 0.000000 c
+h S
+0.500000 w
+138.897385 0.000000 m
+138.897385 36.839508 124.260773 72.165771 98.213272 98.213272 c
+72.165771 124.260773 36.839508 138.897385 0.000000 138.897385 c
+-36.839508 138.897385 -72.165771 124.260773 -98.213272 98.213272 c
+-124.260773 72.165771 -138.897385 36.839508 -138.897385 0.000000 c
+-138.897385 -36.839508 -124.260773 -72.165771 -98.213272 -98.213272 c
+-72.165771 -124.260773 -36.839508 -138.897385 0.000000 -138.897385 c
+36.839508 -138.897385 72.165771 -124.260773 98.213272 -98.213272 c
+124.260773 -72.165771 138.897385 -36.839508 138.897385 0.000000 c
+h S
+0.500000 w
+140.314713 0.000000 m
+140.314713 37.215424 125.528732 72.902161 99.215439 99.215439 c
+72.902161 125.528732 37.215424 140.314713 0.000000 140.314713 c
+-37.215424 140.314713 -72.902161 125.528732 -99.215439 99.215439 c
+-125.528732 72.902161 -140.314713 37.215424 -140.314713 0.000000 c
+-140.314713 -37.215424 -125.528732 -72.902161 -99.215439 -99.215439 c
+-72.902161 -125.528732 -37.215424 -140.314713 0.000000 -140.314713 c
+37.215424 -140.314713 72.902161 -125.528732 99.215439 -99.215439 c
+125.528732 -72.902161 140.314713 -37.215424 140.314713 0.000000 c
+h S
+0.500000 w
+141.732025 0.000000 m
+141.732025 37.591339 126.796707 73.638535 100.217621 100.217621 c
+73.638535 126.796707 37.591339 141.732025 0.000000 141.732025 c
+-37.591339 141.732025 -73.638535 126.796707 -100.217621 100.217621 c
+-126.796707 73.638535 -141.732025 37.591339 -141.732025 0.000000 c
+-141.732025 -37.591339 -126.796707 -73.638535 -100.217621 -100.217621 c
+-73.638535 -126.796707 -37.591339 -141.732025 0.000000 -141.732025 c
+37.591339 -141.732025 73.638535 -126.796707 100.217621 -100.217621 c
+126.796707 -73.638535 141.732025 -37.591339 141.732025 0.000000 c
+h S
+Q
+% mps graphic 1: end
+1 0 0 1 -212.8474 -389.4945 cm
+BT
+/F1 11.955168 Tf 1 0 0 1 70.867 213.216 Tm [<00620051004B0032>-326<0069003200740069>]TJ
+ET
+endstream
+endobj
+16 0 obj
+<</Type/Page/Contents 17 0 R/Resources 15 0 R/MediaBox[0 0 595.2756 841.8898]/TrimBox [ 0.0000 0.0000 595.2756 841.8898 ] /CropBox [ 0.0000 0.0000 595.2756 841.8898 ]/Parent 19 0 R>>
+endobj
+15 0 obj
+<</Font<</F1 18 0 R>>/ProcSet[/PDF/Text]>>
+endobj
+20 0 obj
+<</Type /Metadata /Subtype /XML
+/Length 2310 >>
+stream
+<?xpacket begin="" id="aofvpmjxvtewsnhacjdezlda"?>
+
+<x:xmpmeta xmlns:x="adobe:ns:meta/">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <dc:format>application/pdf</dc:format>
+ <dc:creator>
+ <rdf:Seq>
+ <rdf:li/>
+ </rdf:Seq>
+ </dc:creator>
+ <dc:description/>
+ <dc:title>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default">scite-context-visual</rdf:li>
+ </rdf:Alt>
+ </dc:title>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/">
+ <pdfx:ConTeXt.Jobname>scite-context-visual</pdfx:ConTeXt.Jobname>
+ <pdfx:ConTeXt.Time>2011.11.09 18:39</pdfx:ConTeXt.Time>
+ <pdfx:ConTeXt.Url>www.pragma-ade.com</pdfx:ConTeXt.Url>
+ <pdfx:ConTeXt.Version>2011.11.08 19:35</pdfx:ConTeXt.Version>
+ <pdfx:ID>scite-context-visual.2011-11-09T18:39:10+01:00</pdfx:ID>
+ <pdfx:PTEX.Fullbanner>This is LuaTeX, Version beta-0.71.0-2011062811 (rev 4315) (TeX Live 2011) kpathsea version 6.0.1</pdfx:PTEX.Fullbanner>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+ <xmp:CreateDate>2011-11-09T18:39:10+01:00</xmp:CreateDate>
+ <xmp:CreatorTool>ConTeXt - 2011.11.08 19:35</xmp:CreatorTool>
+ <xmp:ModifyDate>2011-11-09T18:39:10+01:00</xmp:ModifyDate>
+ <xmp:MetadataDate>2011-11-09T18:39:10+01:00</xmp:MetadataDate>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <pdf:Keywords/>
+ <pdf:Producer>LuaTeX-0.71.0</pdf:Producer>
+ <pdf:Trapped>False</pdf:Trapped>
+ </rdf:Description>
+ <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">
+ <xmpMM:DocumentID>uuid:024960bd-4882-a9a1-9b6f-2a8fa9bd7367</xmpMM:DocumentID>
+ <xmpMM:InstanceID>uuid:5a250e9b-49b9-bcd7-8517-4d4de03fba07</xmpMM:InstanceID>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
+
+<?xpacket end="w"?>
+endstream
+endobj
+21 0 obj
+[28[490]35[544]43[435]47[544]50[435]53[272]55[299]63[544]66[272]68[299]70[517]72[272]75[816]77[544]81[490 490]84[544]88[272]96[381 544 386]104[707 381]109[544]114[707]116[517]118[517]]
+endobj
+22 0 obj
+<</Length 15 >>
+stream
+
+endstream
+endobj
+23 0 obj
+<</Subtype/CIDFontType0C/Length 3824 >>
+stream
+
+.
+Œ 8 ð ‹ûÿ†¨~v÷Žž¤ÝÛw­Ò÷bÌסŸønäÃuSRsƒ}e‹Àš÷CÁ‹³_²«h^™_9LUJnž}¢£œœ£´g‹|µ¢»³¹Æe1cû]ˆ?7>@<çrÈ͸³»ž§\ªg¶ Å™Ûû7¿)Bj`Zb¯»÷÷>—¯(Ÿø/Ÿ÷i³§×‹ÊL×÷×hø÷l÷-íûT\rai÷Ô²û€nÏ“„ZüꡯÌf¢¶eË÷ðì÷?ŒHasglwclYUh®¦z~ ‹œ÷bF‹–›¯£·¨¼©ôûTûd¡÷¨ÝÁ¡®×÷^Þø*÷ ”„‹ˆ‚ŠˆˆDuUmUN:À÷,÷:à´½±Â|d¢f‹bsœz£¢ž™¨ÎE»:û .#ûûë)÷÷©÷ ”(Ÿw²øŸ÷i³÷À׋ʋ×~ø—¨Gƒ’¼øõû€nÏ“„Zûq¨v`®Nû')ûûê)÷×·½ž™F÷y‹ˆ}u®hsbnYqû
+ìí÷?”h‹Mq\[o]xef^›¼np¸ŠÆµ±‹Èª¸¶§·›®²µyd¦ª]‹Lf‹¨ø³¨Ëw÷oÐø.¨l3ˆ—¯øÈ¢‹ŒwpsYf$n¢½‹¥Âügˆ3ln¦ì‹¬¬ë‹‰¦(ûV¨÷/Ÿø¨€¡óÌ÷›×ø÷l÷-íû3\L‡ˆÎìû€nÑ‘„_üj^€‹Jn¥Á‹§¨Á‹‰¥¨K‹¸÷Br´dË÷ðì÷?û G4>ln˜žwt¢|Ÿ§÷bž‹Œ–›¸©¼ž±ÖÇ0ûü‹ìâì÷L¼¦t rnwtrm¤x¢¦¡ §ûš‹¨÷γ¨n³óʇګÚ÷õø©p§`6n/x…Š÷¨û€nÏ“„Zû£^€‹Jn§Â‹©¦Ò‹‰¢¨„wJB‰–¯÷1ì³æØ“‹Šƒ‡{…pn¢€›ŸŸ˜¦(v¨ù1¦ÁÅ÷KÅÙÅø}÷LÈt¸p¬f¸^–d•û§X˜^½ËÑÃÊÙ÷8¡û6`‘‹‡•–‹÷^‹ˆ‡‹~„jNÉ[I—_û:2%[œ_°c®d®‚Òy®ƒÂ}™…ºtªUS@VD8^M–¶ZQ¿‡ÓŠ¬Š“‹‹€‹†yû^y‹†•‘Œ—’¬Çc¯Êiá÷Üê÷û•–v÷2÷š¬¸÷y¸÷ô÷Áj«‚”gªp‘I—m‘B™Çª ¹å÷‘.lƒŒ’‹Ž–‹ó‹ƒxu‚„¤ll‘kû gIT€‹h±h«o­„¹‚€˜ˆ¤w|˜uo`r[3I[±ïu‡Š‹‰‡‹ˆ€‹†yûy‹†•ŒŒ œ’‹š›\±Á‹œô¿ÅÚË‹¨ù
+Ì žŒŒŒ‘Œ³š ¡¦™‘Ž‘ ø~ù
+endstream
+endobj
+24 0 obj
+<</Type/FontDescriptor/FontName/EIELYR+LMRoman12-Regular/Flags 4/FontBBox[-422 -280 1394 1127]/Ascent 1127/CapHeight 683/Descent -280/ItalicAngle 0/StemV 91/XHeight 431/FontFile3 23 0 R/CIDSet 22 0 R>>
+endobj
+25 0 obj
+<</Length 1057 >>
+stream
+%!PS-Adobe-3.0 Resource-CMap
+%%DocumentNeededResources: ProcSet (CIDInit)
+%%IncludeResource: ProcSet (CIDInit)
+%%BeginResource: CMap (TeX-EIELYR-LMRoman12-Regular-0)
+%%Title: (TeX-EIELYR-LMRoman12-Regular-0 TeX EIELYR-LMRoman12-Regular 0)
+%%Version: 1.000
+%%EndComments
+/CIDInit /ProcSet findresource begin
+12 dict begin
+begincmap
+/CIDSystemInfo
+<< /Registry (TeX)
+/Ordering (EIELYR-LMRoman12-Regular)
+/Supplement 0
+>> def
+/CMapName /TeX-Identity-EIELYR-LMRoman12-Regular def
+/CMapType 2 def
+1 begincodespacerange
+<0000> <FFFF>
+endcodespacerange
+0 beginbfrange
+endbfrange
+27 beginbfchar
+<001C> <0061>
+<0023> <0062>
+<002B> <0063>
+<002F> <0064>
+<0032> <0065>
+<0035> <0021>
+<0037> <0066>
+<003F> <0068>
+<0042> <0069>
+<0044> <006A>
+<0046> <006B>
+<0048> <006C>
+<004B> <006D>
+<004D> <006E>
+<0051> <006F>
+<0052> <0031>
+<0054> <0070>
+<0058> <002E>
+<0060> <0072>
+<0061> <0053>
+<0062> <0073>
+<0068> <0054>
+<0069> <0074>
+<006D> <0075>
+<0072> <0077>
+<0074> <0078>
+<0076> <0079>
+endbfchar
+endcmap
+CMapName currentdict /CMap defineresource pop
+end
+end
+%%EndResource
+%%EOF
+endstream
+endobj
+18 0 obj
+<</Type/Font/Subtype/Type0/Encoding/Identity-H/BaseFont/EIELYR+LMRoman12-Regular/DescendantFonts[26 0 R]/ToUnicode 25 0 R>>
+endobj
+26 0 obj
+<</Type/Font/Subtype/CIDFontType0/BaseFont/EIELYR+LMRoman12-Regular/FontDescriptor 24 0 R/W 21 0 R/CIDSystemInfo<</Registry (Adobe)/Ordering (Identity)/Supplement 0>>>>
+endobj
+19 0 obj
+<</Type/Pages/Count 1/Kids[16 0 R]>>
+endobj
+27 0 obj
+<<>>
+endobj
+28 0 obj
+<</Type/Catalog/Pages 19 0 R/Names 27 0 R /Version /1.6 /PageLabels << /Nums [ 0 << /S /D >> ] >> /PageMode /UseNone /Metadata 20 0 R>>
+endobj
+29 0 obj
+<<
+/ConTeXt.Url (www.pragma-ade.com) /ConTeXt.Version (2011.11.08 19:35) /ConTeXt.Jobname (scite-context-visual) /CreationDate (D:20111109183910+01'00') /Trapped /False /Title <feff00730063006900740065002d0063006f006e0074006500780074002d00760069007300750061006c> /ConTeXt.Time (2011.11.09 18:39) /ID (scite-context-visual.2011-11-09T18:39:10+01:00) /Producer (LuaTeX-0.71.0) /ModDate (D:20111109183910+01'00') /Creator <feff0043006f006e00540065005800740020002d00200032003000310031002e00310031002e00300038002000310039003a00330035>
+/PTEX.Fullbanner (This is LuaTeX, Version beta-0.71.0-2011062811 (rev 4315) (TeX Live 2011) kpathsea version 6.0.1)>>
+endobj
+xref
+0 30
+0000000001 65535 f
+0000000002 00000 f
+0000000003 00000 f
+0000000004 00000 f
+0000000005 00000 f
+0000000006 00000 f
+0000000007 00000 f
+0000000008 00000 f
+0000000009 00000 f
+0000000010 00000 f
+0000000011 00000 f
+0000000012 00000 f
+0000000013 00000 f
+0000000014 00000 f
+0000000000 00000 f
+0000057388 00000 n
+0000057189 00000 n
+0000000015 00000 n
+0000065351 00000 n
+0000065676 00000 n
+0000057447 00000 n
+0000059844 00000 n
+0000060045 00000 n
+0000060117 00000 n
+0000064020 00000 n
+0000064238 00000 n
+0000065491 00000 n
+0000065729 00000 n
+0000065750 00000 n
+0000065902 00000 n
+trailer
+<</Size 30/Root 28 0 R/Info 29 0 R/ID[<1115B5541270CE955C1C8AF52AEDAC98> <1115B5541270CE955C1C8AF52AEDAC98>]>>
+startxref
+66566
+%%EOF
diff --git a/Master/texmf-dist/context/data/scite/scite-context-visual.png b/Master/texmf-dist/context/data/scite/scite-context-visual.png
new file mode 100644
index 00000000000..7368a68f141
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-visual.png
Binary files differ
diff --git a/Master/texmf-dist/context/data/scite/scite-context-visual.tex b/Master/texmf-dist/context/data/scite/scite-context-visual.tex
new file mode 100644
index 00000000000..0a1b8bb71eb
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-context-visual.tex
@@ -0,0 +1,52 @@
+% language=uk
+
+\usemodule[art-01]
+
+\defineframedtext
+ [entry]
+
+\starttext
+
+\startchapter[title=Some fancy title]
+
+ \startluacode
+ local entries = { -- there can be more
+ { text = "The third entry!" },
+ { text = "The fourth entry!" },
+ }
+
+ for i=1,#entries do
+ context.startentry()
+ context(entries[i].text)
+ context.stopentry()
+ end
+ \stopluacode
+
+ This is just some text to demonstrate the realtime spellchecker
+ in combination with the embedded lua and metapost lexers and
+ inline as well as display \ctxlua{context("lua code")}.
+
+ Non breakable spaces in for instance 10 mm and quads like here
+ are shown as well.
+
+ \startlinecorrection
+ \startMPcode
+ for i=1 upto 100 :
+ draw fullcircle scaled (i*mm) ;
+ endfor ;
+ \stopMPcode
+ \stoplinecorrection
+
+ \iftrue
+ \def\crap{some text} % who cares
+ \else
+ \def\crap{some crap} % about this
+ \fi
+
+ \blank[2*big]
+
+ \crap
+
+\stopchapter
+
+\stoptext
diff --git a/Master/texmf-dist/context/data/scite/context.properties b/Master/texmf-dist/context/data/scite/scite-context.properties
index 006cfe64071..4f91fae2d44 100644
--- a/Master/texmf-dist/context/data/scite/context.properties
+++ b/Master/texmf-dist/context/data/scite/scite-context.properties
@@ -27,35 +27,45 @@
# if PLAT_WIN
# find.command=fgrep -G -n $(find.what) $(find.files)
+# bugged: bad cursor
+#
+# technology=0
+#
+# not much difference
+#
+# buffered.draw=0
+#
+# no auto save:
+#
+# save.on.timer=0
+
# Just UTF-8
code.page=65001
output.code.page=65001
+# caret gets weird:
+#
+# technology=1
+
textwrapper.margin=4
textwrapper.length=68
+#~ textwrapper.length=80
# ConTeXt: suffixes (really needed)
file.patterns.tex=
file.patterns.latex=
-file.patterns.context=*.tex;*.tui;*.tuo;*.sty;*.mkii;*.mkiv;*.mkvi;
+file.patterns.context=*.tex;*.mkii;*.mkiv;*.mkvi;
-# ConTeXt : keywords (if not yet loaded already)
-
-import cont-cz-scite
-import cont-de-scite
-import cont-en-scite
-import cont-nl-scite
-import cont-ro-scite
-import cont-xx-scite
-import metafun-scite
-import latex-scite
+open.suffix.$(file.patterns.context)=.tex
# Example : patterns
file.patterns.xml=
-file.patterns.example=*.xml;*.xsl;*.xsd;*.fo;*.exa;*.rlb;*.rlg;*.rlv;*.rng;*.xfdf;*.xslt;*.dtd;*.lmx;*.ctx
+file.patterns.example=*.xml;*.xsl;*.xsd;*.fo;*.exa;*.rlb;*.rlg;*.rlv;*.rng;*.xfdf;*.xslt;*.dtd;*.lmx;*.ctx;*.export;
+
+open.suffix.$(file.patterns.example)=.xml
filter.example=eXaMpLe|$(file.patterns.example)|
@@ -63,7 +73,9 @@ lexer.$(file.patterns.example)=xml
# Lua : patterns
-file.patterns.lua=*.lua;*.luc;*.cld;*.tuc;*.luj
+file.patterns.lua=*.lua;*.luc;*.cld;*.tuc;*.luj;*.tma;*.lfg
+
+open.suffix.$(file.patterns.lua)=.lua
filter.lua=Lua MkIV|$(file.patterns.lua)|
lexer.$(file.patterns.lua)=lua
@@ -71,6 +83,18 @@ lexer.$(file.patterns.lua)=lua
command.compile.$(file.patterns.lua)=mtxrun --script "$(FileNameExt)"
command.go.$(file.patterns.lua)=mtxrun --script "$(FileNameExt)"
+# Test: patterns
+
+file.patterns.text=*.txt
+
+filter.text=Text |$(file.patterns.text)|
+
+file.patterns.pdf=*.pdf
+
+filter.pdf=PDF |$(file.patterns.pdf)|
+
+# lexer.$(file.patterns.txt)=txt
+
# Commands: some scripts
if PLAT_WIN
@@ -78,36 +102,29 @@ if PLAT_WIN
name.context.console=$(ComSpec)
name.context.gsview=gsview32.exe
name.context.acrobat=
- name.texexec.flag.pdfopen=--autopdf
+ name.flag.pdfopen=--autopdf
# consoles: rxvt,konsole | acrobat: acroread,xpdfopen
#
-# name.texexec.flag.pdfopen=--autopdf --xpdf
+# name.flag.pdfopen=--autopdf --xpdf
if PLAT_GTK
name.context.console=rxvt
name.context.gsview=gv
name.context.acrobat=acroread
- name.texexec.flag.pdfopen=--autopdf
+ name.flag.pdfopen=--autopdf
name.metafun.console=$(name.context.console)
name.example.console=$(name.context.console)
-if PLAT_WIN
- name.context.mtxrun=mtxrun --autogenerate
+name.context.mtxrun=mtxrun --autogenerate
-if PLAT_GTK
- name.context.mtxrun=mtxrun --autogenerate
-
-name.context.concheck=$(name.context.mtxrun) --script check
-name.context.texexec=$(name.context.mtxrun) --script context $(name.texexec.flag.pdfopen)
+name.context.check=$(name.context.mtxrun) --script check
+name.context.run=$(name.context.mtxrun) --script context $(name.flag.pdfopen)
name.context.texshow=$(name.context.mtxrun) texshow
-name.context.purge=$(name.context.mtxrun) ctxtools --purge --all
-name.context.update=$(name.context.mtxrun) texshow --update --force
+name.context.purge=$(name.context.mtxrun) --context --purge --all
name.context.showcase=$(name.context.mtxrun) --launch showcase.pdf
-name.context.backend=pdf
-
name.example.xmlcheck=tidy -quiet -utf8 -xml -errors
name.metafun.mptopdf=$(name.context.mtxrun) --script mptopdf
@@ -146,19 +163,15 @@ import scite-ctx
# hard coded compile / build / go
-command.compile.$(file.patterns.context)=$(name.context.concheck) $(FileNameExt)
+command.compile.$(file.patterns.context)=$(name.context.check) $(FileNameExt)
command.compile.$(file.patterns.metafun)=
command.compile.$(file.patterns.example)=$(name.example.xmlcheck) $(FileNameExt)
command.compile.*.fo=$(name.example.xmlcheck) $(FileNameExt)
-#command.compile.subsystem.$(file.patterns.context)=1
-#command.compile.subsystem.$(file.patterns.metafun)=1
-#command.compile.subsystem.$(file.patterns.example)=1
-
-command.build.$(file.patterns.context)=$(name.context.texexec) --$(name.context.backend) $(FileNameExt)
+command.build.$(file.patterns.context)=$(name.context.run) $(FileNameExt)
command.build.$(file.patterns.metafun)=$(name.metafun.mptopdf) $(FileNameExt)
-command.build.$(file.patterns.example)=$(name.context.texexec) --$(name.context.backend) --xml $(FileNameExt)
-command.build.*.fo=$(name.context.texexec) --$(name.context.backend) $(name.texexec.flag.pdfopen) --xml --use=foxet $(FileNameExt)
+command.build.$(file.patterns.example)=$(name.context.run) --xml $(FileNameExt)
+command.build.*.fo=$(name.context.run) $(name.flag.pdfopen) --xml --use=foxet $(FileNameExt)
command.build.subsystem.$(file.patterns.context)=1
command.build.subsystem.$(file.patterns.metafun)=1
@@ -188,7 +201,7 @@ command.name.0.$(file.patterns.context)=Check TeX File
command.name.0.$(file.patterns.metafun)=
command.name.0.$(file.patterns.example)=Check XML File
-command.0.$(file.patterns.context)=$(name.context.concheck) $(FileNameExt)
+command.0.$(file.patterns.context)=$(name.context.check) $(FileNameExt)
command.0.$(file.patterns.metafun)=
command.0.$(file.patterns.example)=$(name.example.xmlcheck) $(FileNameExt)
@@ -198,9 +211,9 @@ command.name.1.$(file.patterns.context)=Process TeX file
command.name.1.$(file.patterns.metafun)=Process METAPOST File
command.name.1.$(file.patterns.example)=Process XML File
-command.1.$(file.patterns.context)=$(name.context.texexec) --$(name.context.backend) $(FileNameExt)
-command.1.$(file.patterns.metafun)=$(name.context.texexec) --$(name.context.backend) --mptex $(FileNameExt)
-command.1.$(file.patterns.example)=$(name.context.texexec) --$(name.context.backend) --xml $(FileNameExt)
+command.1.$(file.patterns.context)=$(name.context.run) $(FileNameExt)
+command.1.$(file.patterns.metafun)=$(name.context.run) $(FileNameExt) --metapost
+command.1.$(file.patterns.example)=$(name.context.run) $(FileNameExt) --xml
command.1.subsystem.$(file.patterns.context)=1
command.1.subsystem.$(file.patterns.metafun)=1
@@ -208,32 +221,18 @@ command.1.subsystem.$(file.patterns.example)=1
# 2 : pdf viewing
-command.name.2.$(file.patterns.context)=View PDF File
-command.name.2.$(file.patterns.metafun)=
-command.name.2.$(file.patterns.example)=View PDF File
+command.name.2.$(file.patterns.context)=View PDF File with GhostScript
+command.name.2.$(file.patterns.metafun)=View PDF File with GhostScript
+command.name.2.$(file.patterns.example)=View PDF File with GhostScript
-command.2.$(file.patterns.context)=$(name.context.gsview) $(FileName).pdf
-command.2.$(file.patterns.metafun)=
-command.2.$(file.patterns.example)=$(name.context.gsview) $(FileName).pdf
+command.2.$(file.patterns.context)=$(name.context.gsview) $(FileDir)/$(FileName).pdf
+command.2.$(file.patterns.metafun)=$(name.context.gsview) $(FileDir)/$(FileName).pdf
+command.2.$(file.patterns.example)=$(name.context.gsview) $(FileDir)/$(FileName).pdf
command.subsystem.2.$(file.patterns.context)=2
command.subsystem.2.$(file.patterns.metafun)=2
command.subsystem.2.$(file.patterns.example)=2
-# 2 : postscript
-
-# command.name.2.$(file.patterns.context)=View PS File
-# command.name.2.$(file.patterns.metafun)=View PS File (1)
-# command.name.2.$(file.patterns.example)=View PS File
-
-# command.2.$(file.patterns.context)=$(name.context.gsview) $(FileName).ps
-# command.2.$(file.patterns.metafun)=$(name.context.gsview) $(FileName).1
-# command.2.$(file.patterns.example)=$(name.context.gsview) $(FileName).ps
-
-# command.subsystem.2.$(file.patterns.context)=2
-# command.subsystem.2.$(file.patterns.metafun)=2
-# command.subsystem.2.$(file.patterns.example)=2
-
# 3 : clean up
command.name.3.$(file.patterns.context)=Purge Files
@@ -254,18 +253,6 @@ command.name.4.$(file.patterns.context)=Show Documentation
command.name.4.$(file.patterns.metafun)=Show Documentation
command.name.4.$(file.patterns.example)=Show Documentation
-# 5 : example framework applications
-
-#~ command.5=$(name.context.examplap)
-#~ command.5.$(file.patterns.context)=$(name.context.examplap)
-#~ command.5.$(file.patterns.metafun)=$(name.context.examplap)
-#~ command.5.$(file.patterns.example)=$(name.context.examplap)
-
-#~ command.name.5=Start Interfaces
-#~ command.name.5.$(file.patterns.context)=Start Interfaces
-#~ command.name.5.$(file.patterns.metafun)=Start Interfaces
-#~ command.name.5.$(file.patterns.example)=Start Interfaces
-
# 6 : console
command.name.6=Start Console
@@ -285,43 +272,24 @@ command.name.7.$(file.patterns.context)=Generate Listing
command.name.7.$(file.patterns.metafun)=Generate Listing
command.name.7.$(file.patterns.example)=Generate Listing
-command.7=$(name.context.texexec) --$(name.context.backend) --list --result=$(FileName) $(FileNameExt)
-command.7.$(file.patterns.context)=$(name.context.texexec) --$(name.context.backend) --list --result=$(FileName) $(FileNameExt)
-command.7.$(file.patterns.metafun)=$(name.context.texexec) --$(name.context.backend) --list --result=$(FileName) $(FileNameExt)
-command.7.$(file.patterns.example)=$(name.context.texexec) --$(name.context.backend) --list --result=$(FileName) $(FileNameExt)
+command.7=$(name.context.run) --extra=listing --pretty --result=$(FileName) $(FileNameExt)
+command.7.$(file.patterns.context)=$(name.context.run) --extra=listing --pretty --result=$(FileName) $(FileNameExt)
+command.7.$(file.patterns.metafun)=$(name.context.run) --extra=listing --pretty --result=$(FileName) $(FileNameExt)
+command.7.$(file.patterns.example)=$(name.context.run) --extra=listing --pretty --result=$(FileName) $(FileNameExt)
command.7.subsystem=1
command.7.subsystem.$(file.patterns.context)=1
command.7.subsystem.$(file.patterns.metafun)=1
command.7.subsystem.$(file.patterns.example)=1
-# 8 : reserved
-
-command.name.8.$(file.patterns.context)=
-command.name.8.$(file.patterns.metafun)=
-command.name.8.$(file.patterns.example)=
-command.8.$(file.patterns.context)=
-command.8.$(file.patterns.metafun)=
-command.8.$(file.patterns.example)=
-
-# 9 : reserved
-
-command.name.9=
-command.name.9.$(file.patterns.context)=
-command.name.9.$(file.patterns.metafun)=
-command.name.9.$(file.patterns.example)=
-command.9.$(file.patterns.context)=
-command.9.$(file.patterns.metafun)=
-command.9.$(file.patterns.example)=
-
# 10: arranging
command.name.10.$(file.patterns.context)=Process and Arrange
command.name.10.$(file.patterns.metafun)=Process and Arrange
command.name.10.$(file.patterns.example)=Process and Arrange
-command.10.$(file.patterns.context)=$(name.context.texexec) --arrange --$(name.context.backend) $(FileNameExt)
-command.10.$(file.patterns.metafun)=$(name.context.texexec) --$(name.context.backend) --mptex $(FileNameExt)
-command.10.$(file.patterns.example)=$(name.context.texexec) --arrange --$(name.context.backend) --xml $(FileNameExt)
+command.10.$(file.patterns.context)=$(name.context.run) --arrange $(FileNameExt)
+command.10.$(file.patterns.metafun)=$(name.context.run) --mptex $(FileNameExt)
+command.10.$(file.patterns.example)=$(name.context.run) --arrange --xml $(FileNameExt)
command.10.subsystem.$(file.patterns.context)=1
command.10.subsystem.$(file.patterns.metafun)=1
command.10.subsystem.$(file.patterns.example)=1
@@ -331,9 +299,9 @@ command.10.subsystem.$(file.patterns.example)=1
command.name.11.$(file.patterns.context)=Generate Formats (pdfTeX)
command.name.11.$(file.patterns.metafun)=Generate Formats
command.name.11.$(file.patterns.example)=Generate Formats
-command.11.$(file.patterns.context)=$(name.context.texexec) --make --all --pdftex
-command.11.$(file.patterns.metafun)=$(name.context.texexec) --make --all
-command.11.$(file.patterns.example)=$(name.context.texexec) --make --all
+command.11.$(file.patterns.context)=$(name.context.run) --make --all --pdftex
+command.11.$(file.patterns.metafun)=$(name.context.run) --make --all
+command.11.$(file.patterns.example)=$(name.context.run) --make --all
command.11.subsystem.$(file.patterns.context)=1
command.11.subsystem.$(file.patterns.metafun)=1
command.11.subsystem.$(file.patterns.example)=1
@@ -341,27 +309,15 @@ command.11.subsystem.$(file.patterns.example)=1
# 12: make
command.name.12.$(file.patterns.context)=Generate Formats (luaTeX)
-command.12.$(file.patterns.context)=$(name.context.texexec) --make --all --luatex
+command.12.$(file.patterns.context)=$(name.context.run) --make --all --luatex
command.12.subsystem.$(file.patterns.context)=1
# 13: make
command.name.13.$(file.patterns.context)=Generate Formats (XeTeX)
-command.13.$(file.patterns.context)=$(name.context.texexec) --make --all --xetex
+command.13.$(file.patterns.context)=$(name.context.run) --make --all --xetex
command.13.subsystem.$(file.patterns.context)=1
-# 14: update
-
-command.name.14=Update ConTeXt
-command.name.14.$(file.patterns.context)=Update ConTeXt
-command.name.14.$(file.patterns.metafun)=Update ConTeXt
-command.name.14.$(file.patterns.example)=Update ConTeXt
-
-command.14=$(name.context.update)
-command.14.$(file.patterns.context)=$(name.context.update)
-command.14.$(file.patterns.metafun)=$(name.context.update)
-command.14.$(file.patterns.example)=$(name.context.update)
-
# 15: example
command.name.15=Documentation Server
@@ -387,25 +343,23 @@ Ctrl+F12|IDM_BUILD|\
Shift+F12|IDM_GO|\
Alt+F12|IDM_STOPEXECUTE|\
-# Editor: fonts (16.5/11.5)
+os.x.home.end.keys=0
-# install: fonts/truetype/hoekwater/lm/LMTypewriter10-Regular.ttf
+# Editor: fonts
if PLAT_WIN
- font.monospace=font:LMTypewriter10-Regular,size:14
- font.errorfont=font:LMTypewriter10-Regular,size:12
+ font.monospace=font:Dejavu Sans Mono,size:14
+ font.errorfont=font:Dejavu Sans Mono,size:8
if PLAT_GTK
- font.monospace=font:!lm mono 10 regular,size:14
- font.errorfont=font:!lm mono 10 regular,size:12
+ font.monospace=font:!Dejavu Sans Mono,size:14
+ font.errorfont=font:!Dejavu Sans Mono,size:8
-#~ if PLAT_WIN
- #~ font.monospace=font:Lucida Console,size:12
- #~ font.monospace=font:Lucida Sans Unicode,size:12
- #~ font.monospace=font:OpenSymbol,size:17
+if PLAT_MAC
+ font.monospace=font:Dejavu Sans Mono,size:14
+ font.errorfont=font:Dejavu Sans Mono,size:8
font.base=$(font.monospace)
-#~ font.small=$(font.monospace)
font.comment=$(font.monospace)
font.text=$(font.monospace)
font.text.comment=$(font.monospace)
@@ -413,19 +367,71 @@ font.embedded.base=$(font.monospace)
font.embedded.comment=$(font.monospace)
font.vbs=$(font.monospace)
-# Editor: colors
-
-color.back.linepanel=back:#A7A7A7
-color.back.textpanel=back:#CFCFCF
-color.back.logpanel=back:#EFEFEF
-color.back.selection=#F7F7F7
-
-color.fore.red=fore:#7F0000
-color.fore.green=fore:#007F00
-color.fore.blue=fore:#00007F
-color.fore.cyan=fore:#007F7F
-color.fore.magenta=fore:#7F007F
-color.fore.yellow=fore:#7F7F00
+# colors and styles
+
+colors.red=#7F0000
+colors.green=#007F00
+colors.blue=#00007F
+colors.cyan=#007F7F
+colors.magenta=#7F007F
+colors.yellow=#7F7F00
+
+colors.white=#FFFFFF
+colors.light= #CFCFCF
+colors.grey= #808080
+colors.dark= #4F4F4F
+colors.black= #000000
+colors.selection=#F7F7F7
+colors.logpanel=#E7E7E7
+colors.textpanel=#CFCFCF
+colors.linepanel=#A7A7A7
+colors.tippanel=#444444
+colors.right=#0000FF
+colors.wrong=#FF0000
+
+colors.teal=$(colors.cyan)
+colors.purple=$(colors.magenta)
+
+styles.default=fore:$(colors.black),back:$(colors.textpanel),$(font.base)
+styles.nothing=
+
+styles.number=fore:$(colors.cyan)
+styles.comment=fore:$(colors.yellow)
+styles.string=fore:$(colors.magenta)
+styles.keyword=fore:$(colors.blue),bold
+
+styles.char=fore:$(colors.magenta)
+styles.class=fore:$(colors.black),bold
+styles.constant=fore:$(colors.cyan),bold
+styles.definition=fore:$(colors.black),bold
+styles.error=fore:$(colors.red)
+styles.function=fore:$(colors.black),bold
+styles.operator=fore:$(colors.blue)
+styles.preproc=fore:$(colors.yellow),bold
+styles.tag=fore:$(colors.cyan)
+styles.type=fore:$(colors.blue)
+styles.variable=fore:$(colors.black)
+styles.identifier=$(styles.nothing)
+
+styles.linenumber=back:$(colors.linepanel)
+styles.bracelight=fore:$(colors.orange),bold
+styles.bracebad=fore:$(colors.orange),bold
+styles.indentguide=fore:$(colors.linepanel),back:$(colors.white)
+styles.calltip=fore:$(colors.white),back:$(colors.tippanel)
+styles.controlchar=$(styles.nothing)
+
+# end of colors and styles
+
+# Editor: color schemes
+
+caret.width=3
+
+style.*.32=$(font.base),back:$(colors.textpanel)
+style.*.33=$(font.base),back:$(colors.linepanel)
+
+style.errorlist.32=$(font.errorfont),back:$(colors.logpanel)
+
+selection.back=#000000
# Editor: fast switching between files
@@ -483,17 +489,19 @@ find.files=*.tex *.xml *.mp
if PLAT_WIN
find.command=fgrep -n $(find.what) $(find.files)
-source.files=$(file.patterns.context);$(file.patterns.metafun);$(file.patterns.example);*.pl;*.rb
+# todo:
+
+source.files=$(file.patterns.context);$(file.patterns.metafun);$(file.patterns.example);*.pl;*.rb;*.lua
# Editor: printing
if PLAT_WIN
- print.colour.mode=1
- print.margins=750,750,750,750
- print.header.format=$(FileNameExt) — Printed on $(CurrentDate), $(CurrentTime) — Page $(CurrentPage)
- print.footer.format=$(FilePath) — File date: $(FileDate) — File time: $(FileTime)
- print.header.style=font:LMTypewriter10,size:10
- print.footer.style=font:LMTypewriter10,size:10
+ print.colour.mode=1
+ print.margins=750,750,750,750
+ print.header.format=$(FileNameExt) — Printed on $(CurrentDate), $(CurrentTime) — Page $(CurrentPage)
+ print.footer.format=$(FilePath) — File date: $(FileDate) — File time: $(FileTime)
+ print.header.style=font:Dejavu Sans Mono,size:10
+ print.footer.style=font:Dejavu Sans Mono,size:10
# Editor: processing
@@ -515,45 +523,144 @@ default.file.ext=.tex
autocompleteword.automatic=1
autocomplete.choose.single=0
-api.*.tex=t:\sources\cont-en-scite.api
+# api.*.tex=t:\sources\cont-en-scite.api
# Logging
-style.errorlist.32=$(font.errorfont)
+style.errorlist.32=$(font.errorfont),back:$(colors.logpanel)
# Default
-style.errorlist.0=fore:#000000
-# python Error
-style.errorlist.1=$(color.fore.red)
-# gcc Error
-style.errorlist.2=$(color.fore.red)
-# Microsoft Error
-style.errorlist.3=$(color.fore.red)
-# command or return status
-style.errorlist.4=$(color.fore.green)
-# Borland error and warning messages
-style.errorlist.5=$(color.fore.red)
-# perl error and warning messages
-style.errorlist.6=$(color.fore.red)
-# .NET tracebacks
-style.errorlist.7=$(color.fore.red)
-# Lua error and warning messages
-style.errorlist.8=$(color.fore.red)
-# ctags
-style.errorlist.9=$(color.fore.red)
-# diff changed !
-style.errorlist.10=$(color.fore.green)
-# diff addition +
-style.errorlist.11=$(color.fore.blue)
-# diff deletion -
-style.errorlist.12=$(color.fore.cyan)
-# diff message ---
-style.errorlist.13=$(color.fore.red)
-# PHP error
-style.errorlist.14=$(color.fore.red)
-# Essential Lahey Fortran 90 error
-style.errorlist.15=$(color.fore.red)
-# Intel Fortran Compiler error
-style.errorlist.16=$(color.fore.red)
-
-# Context: end of file
+
+style.errorlist.0=fore:$(colors.black)
+style.errorlist.1=fore:$(colors.red)
+style.errorlist.2=fore:$(colors.red)
+style.errorlist.3=fore:$(colors.red)
+style.errorlist.4=fore:$(colors.green)
+style.errorlist.5=fore:$(colors.red)
+style.errorlist.6=fore:$(colors.red)
+style.errorlist.7=fore:$(colors.red)
+style.errorlist.8=fore:$(colors.red)
+style.errorlist.9=fore:$(colors.red)
+style.errorlist.10=fore:$(colors.green)
+style.errorlist.11=fore:$(colors.blue)
+style.errorlist.12=fore:$(colors.cyan)
+style.errorlist.13=fore:$(colors.red)
+style.errorlist.14=fore:$(colors.red)
+style.errorlist.15=fore:$(colors.red)
+style.errorlist.16=fore:$(colors.red)
+
+# Metapost: patterns
+
+file.patterns.metafun=
+
+file.patterns.metafun=*.mp;*.mpx;*.mpy;*.mpii;*.mpiv
+
+filter.metafun=MetaFun|$(file.patterns.metafun)|
+
+lexer.$(file.patterns.metafun)=metapost
+
+command.compile.$(file.patterns.metafun)=
+command.build.$(file.patterns.metafun)=context $(FileNameExt)
+command.go.$(file.patterns.metafun)=gv $(FileName).1
+
+command.0.$(file.patterns.metafun)=
+command.1.$(file.patterns.metafun)=
+command.2.$(file.patterns.metafun)=
+command.3.$(file.patterns.metafun)=
+command.4.$(file.patterns.metafun)=
+command.5.$(file.patterns.metafun)=
+command.6.$(file.patterns.metafun)=
+command.7.$(file.patterns.metafun)=
+command.8.$(file.patterns.metafun)=
+command.9.$(file.patterns.metafun)=
+
+# Shared highlighting
+
+styles.context.default=$(styles.nothing)
+styles.context.number=$(styles.number)
+styles.context.comment=$(styles.comment)
+styles.context.keyword=$(styles.keyword)
+styles.context.string=$(styles.string)
+
+styles.context.command=fore:$(colors.green),bold
+styles.context.preamble=$(styles.comment)
+styles.context.embedded=fore:$(colors.black),bold
+styles.context.grouping=fore:$(colors.red)
+styles.context.primitive=$(styles.keyword)
+styles.context.plain=fore:$(colors.dark),bold
+styles.context.user=fore:$(colors.green)
+styles.context.data=$(styles.constant)
+styles.context.special=fore:$(colors.blue)
+styles.context.extra=fore:$(colors.yellow)
+styles.context.quote=fore:$(colors.blue),bold
+
+# Metapost highlighting
+
+style.metapost.0=$(styles.context.default)
+style.metapost.1=$(styles.context.special)
+style.metapost.2=$(styles.context.grouping)
+style.metapost.3=$(styles.context.comment)
+style.metapost.4=$(styles.context.keyword)
+style.metapost.5=$(styles.context.default)
+style.metapost.6=$(styles.context.plain)
+style.metapost.34=$(styles.bracelight)
+style.metapost.35=$(styles.bracebad)
+
+# TeX highlighting
+
+style.tex.0=$(styles.context.default)
+style.tex.1=$(styles.context.special)
+style.tex.2=$(styles.context.grouping)
+style.tex.3=$(styles.context.comment)
+style.tex.4=$(styles.context.user)
+style.tex.34=$(styles.bracelight)
+style.tex.35=$(styles.bracebad)
+
+# style.tex.* : external styling happens elsewhere
+# style.mps.* : external styling happens elsewhere
+# style.cls.* : external styling happens elsewhere
+
+# Lua highlighting:
+#
+# might change as we change the cld lexer
+
+comment.block.lua=--
+comment.block.at.line.start.lua=1
+
+# braces.lua.style=10
+
+style.lua.32=$(styles.context.default)
+style.lua.0=$(styles.context.default)
+style.lua.1=$(styles.context.comment)
+style.lua.2=$(styles.context.comment)
+style.lua.3=$(styles.context.comment)
+style.lua.4=$(styles.context.number)
+style.lua.5=$(styles.context.keyword)
+style.lua.6=$(styles.context.string)
+style.lua.7=$(styles.context.string)
+style.lua.8=$(styles.context.comment)
+style.lua.9=$(styles.context.default)
+style.lua.10=$(styles.context.special)
+style.lua.11=$(styles.context.default)
+style.lua.12=$(styles.context.default)
+style.lua.13=$(styles.context.default)
+style.lua.14=$(styles.context.default)
+style.lua.15=$(styles.context.default)
+style.lua.16=$(styles.context.default)
+style.lua.17=$(styles.context.default)
+style.lua.18=$(styles.context.default)
+style.lua.19=$(styles.context.default)
+style.lua.20=$(styles.context.default)
+
+style.context.34=$(styles.bracelight)
+style.context.35=$(styles.bracebad)
+
+# folding
+
+fold=1
+fold.symbols=3
+fold.margin.colour=#CCCCCC
+
+# testing
+
+#~ cache.layout=
diff --git a/Master/texmf-dist/context/data/scite/scite-ctx-context.properties b/Master/texmf-dist/context/data/scite/scite-ctx-context.properties
new file mode 100644
index 00000000000..a1d5800e65a
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-ctx-context.properties
@@ -0,0 +1,49 @@
+command.name.25.$(file.patterns.context)=Whatever
+command.25.$(file.patterns.context)=insert_template $(ctx.template.list.context)
+
+ctx.template.list.context=\
+ itemize=structure.itemize.context|\
+ tabulate=structure.tabulate.context|\
+ natural TABLE=structure.TABLE.context|\
+ use MP graphic=graphics.usemp.context|\
+ reuse MP graphic=graphics.reusemp.context|\
+ typeface definition=fonts.typeface.context
+
+ctx.template.structure.itemize.context=\
+\startitemize\n\
+\item ?\n\
+\item ?\n\
+\item ?\n\
+\stopitemize\n
+
+ctx.template.structure.tabulate.context=\
+\starttabulate[|l|p|]\n\
+\NC ? \NC \NC \NR\n\
+\NC ? \NC \NC \NR\n\
+\NC ? \NC \NC \NR\n\
+\stoptabulate\n
+
+ctx.template.structure.TABLE.context=\
+\bTABLE\n\
+\bTR \bTD ? \eTD \bTD \eTD \eTR\n\
+\bTR \bTD ? \eTD \bTD \eTD \eTR\n\
+\bTR \bTD ? \eTD \bTD \eTD \eTR\n\
+\eTABLE\n
+
+ctx.template.graphics.usemp.context=\
+\defineoverlay[?][\useMPgraphic{}]\n\n\
+\startuseMPgraphic{}\n\n\
+\stopuseMPgraphic\n
+
+ctx.template.graphics.reusemp.context=\
+\defineoverlay[?][\reuseMPgraphic{}]\n\n\
+\startreusableMPgraphic{}\n\n\
+\stopreusableMPgraphic\n
+
+ctx.template.fonts.typeface.context=\
+\definetypeface[mainface][rm][serif][?][default][encoding=\defaultencoding]\n\
+\definetypeface[mainface][ss][sans] [?][default][encoding=\defaultencoding]\n\
+\definetypeface[mainface][tt][mono] [?][default][encoding=\defaultencoding]\n\
+\definetypeface[mainface][mm][math] [?][default][encoding=\defaultencoding]\n\
+\n\
+\setupbodyfont[mainface,10pt]\n
diff --git a/Master/texmf-dist/context/data/scite/scite-ctx-example.properties b/Master/texmf-dist/context/data/scite/scite-ctx-example.properties
new file mode 100644
index 00000000000..78b2f2859c2
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-ctx-example.properties
@@ -0,0 +1,23 @@
+command.25.$(file.patterns.example)=insert_template $(ctx.template.list.example)
+
+ctx.template.list.example=\
+ bold=font.bold.example|\
+ emphasized=font.emphasized.example|\
+ |\
+ inline math=math.inline.example|\
+ display math=math.display.example|\
+ |\
+ itemize=structure.itemize.example
+
+ctx.template.font.bold.example=<b>?</b>
+ctx.template.font.emphasized.example=<em>?</em>
+
+ctx.template.math.inline.example=<m>?</m>
+ctx.template.math.display.example=<math>?</math>
+
+ctx.template.structure.itemize.example=\
+<itemize>\n\
+<item>?</item>\n\
+<item>?</item>\n\
+<item>?</item>\n\
+</itemize>\n
diff --git a/Master/texmf-dist/context/data/scite/scite-ctx.lua b/Master/texmf-dist/context/data/scite/scite-ctx.lua
index 8e6b6ebab74..3557994f383 100644
--- a/Master/texmf-dist/context/data/scite/scite-ctx.lua
+++ b/Master/texmf-dist/context/data/scite/scite-ctx.lua
@@ -80,20 +80,20 @@ function traceln(str)
io.flush()
end
-function string:grab(delimiter)
- local list = {}
- for snippet in self:gmatch(delimiter) do
+function string.grab(str,delimiter)
+ local list = { }
+ for snippet in gmatch(str,delimiter) do
list[#list+1] = snippet
end
return list
end
-function string:expand()
- return (self:gsub("ENV%((%w+)%)", os.envvar))
+function string.expand(str)
+ return (gsub(str,"ENV%((%w+)%)", os.envvar))
end
-function string:strip()
- return (self:gsub("^%s*(.-)%s*$", "%1"))
+function string.strip(str)
+ return (gsub(str,"^%s*(.-)%s*$", "%1"))
end
function table.alphasort(list,i)
@@ -516,7 +516,7 @@ local worddone = 0
-- end
-- end
-function check_text()
+function check_text() -- obsolete, replaced by lexer
local dlanguage = props["ctx.spellcheck.language"]
local dwordsize = props["ctx.spellcheck.wordsize"]
@@ -836,3 +836,15 @@ menufunctions[14] = process_template_two
function open_log()
scite.Open(props['FileName'] .. ".log")
end
+
+if not lpeg then
+
+ local okay, root = pcall(function() return require "lpeg" end)
+
+ if okay then
+ lpeg = root
+ else
+ trace("\nwarning: lpeg not loaded\n")
+ end
+
+end
diff --git a/Master/texmf-dist/context/data/scite/scite-ctx.properties b/Master/texmf-dist/context/data/scite/scite-ctx.properties
index f23508acab4..8b2651c0d01 100644
--- a/Master/texmf-dist/context/data/scite/scite-ctx.properties
+++ b/Master/texmf-dist/context/data/scite/scite-ctx.properties
@@ -12,8 +12,7 @@
# <?xml version='1.0' language='uk' ?>
ext.lua.auto.reload=1
-#~ ext.lua.startup.script=$(SciteDefaultHome)/scite-ctx.lua
-ext.lua.startup.script=$(SciteUserHome)/scite-ctx.lua
+ext.lua.startup.script=$(SciteDefaultHome)/scite-ctx.lua
#~ extension.$(file.patterns.context)=scite-ctx.lua
#~ extension.$(file.patterns.example)=scite-ctx.lua
@@ -50,7 +49,7 @@ ctx.menulist.example=\
check=check_text|\
reset=reset_text
-ctx.wraptext.length=65
+ctx.wraptext.length=80
ctx.spellcheck.language=auto
ctx.spellcheck.wordsize=4
diff --git a/Master/texmf-dist/context/data/scite/scite-ctx.readme b/Master/texmf-dist/context/data/scite/scite-ctx.readme
deleted file mode 100644
index c5f5977a669..00000000000
--- a/Master/texmf-dist/context/data/scite/scite-ctx.readme
+++ /dev/null
@@ -1,19 +0,0 @@
-installation:
-
--- download scite and install it (take the normal scite, not one that ships with ruby)
--- copy the texmf-context\context\data\scite\*.properties to c:\users\<youraccount>
--- copy the texmf-context\context\data\scite\*.lua to the place where scite has its own support files (wscite)
--- add the line "import context" to your user properties file (entry under menu Options)
-
-running context:
-
--- add texmf-mswin\bin to your path
-
-or
-
--- start scite from a cmd that also calls setuptex
-
-spellchecking:
-
--- create a path for spell files and put spell files there (these are files with just words)
--- set the environment variable CTXSPELLPATH to this path
diff --git a/Master/texmf-dist/context/data/scite/scite-metapost.properties b/Master/texmf-dist/context/data/scite/scite-metapost.properties
new file mode 100644
index 00000000000..e3ac252445f
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-metapost.properties
@@ -0,0 +1,76 @@
+# file : metapost.properties
+# version : 18 august 2003++
+# author : Hans Hagen / PRAGMA ADE / www.pragma-ade.com
+
+# Metapost: patterns
+
+file.patterns.metapost=
+
+file.patterns.metapost=*.mp;*.mpx;
+
+filter.metapost=MetaPost|$(file.patterns.metapost)|
+
+lexer.$(file.patterns.metapost)=metapost
+
+# Metapost: commands (check process view)
+
+command.compile.$(file.patterns.metapost)=
+command.build.$(file.patterns.metapost)=mpost $(FileNameExt)
+command.go.$(file.patterns.metapost)=gv $(FileName).1
+
+command.0.$(file.patterns.metapost)=
+command.1.$(file.patterns.metapost)=
+command.2.$(file.patterns.metapost)=
+command.3.$(file.patterns.metapost)=
+command.4.$(file.patterns.metapost)=
+command.5.$(file.patterns.metapost)=
+command.6.$(file.patterns.metapost)=
+command.7.$(file.patterns.metapost)=
+command.8.$(file.patterns.metapost)=
+command.9.$(file.patterns.metapost)=
+
+# Metapost: highlighting
+
+style.metapost.0=fore:#7F7F00
+style.metapost.0=fore:#3F3F3F
+style.metapost.1=fore:#007F7F
+style.metapost.2=fore:#7F0000
+style.metapost.3=fore:#7F7F00
+style.metapost.4=fore:#007F00
+style.metapost.5=fore:#000000
+style.metapost.6=fore:#007F00,italics
+
+style.metapost.34=fore:#00007F
+style.metapost.35=fore:#7F007F
+
+# Metapost: comments
+
+comment.block.metapost=%
+comment.block.at.line.start.metapost=1
+
+# Metapost: lexer.metapost.interface.default
+#
+# 0 not used
+# 1 metapost primitives and commands
+# 2 metafun macros
+#
+# first lines of a metapost file are interpreted as follows:
+#
+# % interface=none|metapost|mp|metafun
+
+lexer.metapost.interface.default=1
+
+# Metapost: lexer.metapost.comment.process
+#
+# 0 don't interpret comment
+# 1 color comment like source code
+
+lexer.metapost.comment.process=0
+
+# Metapost: keywords
+
+import scite-context-data-metapost.properties
+
+keywords.$(file.patterns.metapost)=$(keywordclass.metapost.all)
+
+# Metapost: end of file
diff --git a/Master/texmf-dist/context/data/scite/scite-pragma.properties b/Master/texmf-dist/context/data/scite/scite-pragma.properties
new file mode 100644
index 00000000000..450c609b042
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-pragma.properties
@@ -0,0 +1,38 @@
+# file : pragma.properties
+# version : 18 august 2003
+# author : Hans Hagen / PRAGMA ADE / www.pragma-ade.com
+
+# save.backup.first=1
+# save.backup.once=1
+# save.backup.suffix=.bak
+
+# Editor: screen
+
+position.left=0
+position.top=0
+position.width=1920
+position.height=1160
+
+output.horizontal.size=250
+output.vertical.size=100
+
+# Editor: filters
+
+open.filter=\
+All Files (*.*)|*.*|\
+$(filter.context)\
+$(filter.metafun)\
+$(filter.example)\
+$(filter.lua)\
+$(filter.text)\
+$(filter.pdf)
+
+# Editor: menus
+
+menu.language=\
+TeX|tex||\
+Metapost|metapost||\
+XML|xml||\
+Lua|lua||\
+Text|txt||\
+PDF|pdf||
diff --git a/Master/texmf-dist/context/data/scite/scite-tex.properties b/Master/texmf-dist/context/data/scite/scite-tex.properties
new file mode 100644
index 00000000000..6933971e26d
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/scite-tex.properties
@@ -0,0 +1,116 @@
+# file : tex.properties
+# version : 18 august 2003
+# author : Hans Hagen / PRAGMA ADE / www.pragma-ade.com
+
+# TeX users may want to use the Latin Modern Typewriter font:
+#
+# use.monospaced=1
+# font.monospace=font:LMTypewriter10,size:16.5
+# font.errorfont=font:LMTypewriter10,size:11.5
+#
+# These and more presets are done in context.properties.
+
+# TeX: patterns
+
+file.patterns.tex=*.tex
+filter.tex=TeX|$(file.patterns.tex)|
+lexer.$(file.patterns.tex)=tex
+
+# TeX: commands (check process view)
+
+command.compile.$(file.patterns.tex)=
+command.build.$(file.patterns.tex)=tex $(FileNameExt)
+command.go.$(file.patterns.tex)=gv $(FileName).pdf
+
+command.0.$(file.patterns.tex)=
+command.1.$(file.patterns.tex)=
+command.2.$(file.patterns.tex)=
+command.3.$(file.patterns.tex)=
+command.4.$(file.patterns.tex)=
+command.5.$(file.patterns.tex)=
+command.6.$(file.patterns.tex)=
+command.7.$(file.patterns.tex)=
+command.8.$(file.patterns.tex)=
+command.9.$(file.patterns.tex)=
+
+# TeX: highlighting
+
+style.tex.0=fore:#3F3F3F
+style.tex.1=fore:#007F7F
+style.tex.2=fore:#7F0000
+style.tex.3=fore:#7F7F00
+style.tex.4=fore:#007F00
+style.tex.34=fore:#00007F
+style.tex.35=fore:#7F007F
+
+# TeX: comments
+
+comment.block.tex=%
+comment.block.at.line.start.tex=1
+
+# TeX: lexer.tex.interface.default
+#
+# 0 all \commands
+# 1 tex etex pdftex omega primitives
+# 2 context nl (when context.properties is loaded)
+# 3 context en (when context.properties is loaded)
+# 4 context de (when context.properties is loaded)
+# 5 context cz (when context.properties is loaded)
+# 6 context it (when context.properties is loaded)
+# 7 context ro (when context.properties is loaded)
+# 8 latex (no keywords yet; will move up)
+#
+# first lines of a tex file are interpreted as follows
+#
+# % interface=all|nl|en|de|cz|it|ro|latex
+
+lexer.tex.interface.default=0
+
+# TeX: lexer.tex.use.keywords
+#
+# 0 don't use keyword lists
+# 1 use keyword lists
+
+lexer.tex.use.keywords=1
+
+# TeX: lexer.tex.comment.process
+#
+# 0 don't interpret comment
+# 1 color comment like source code
+
+lexer.tex.comment.process=0
+
+# TeX: lexer.tex.auto.if
+#
+# 0 don't handle \if<unknown>
+# 1 treat \if<unknown> as command
+
+lexer.tex.auto.if=1
+
+# only the macros that make sense:
+
+import scite-context-data-tex.properties
+
+# collections
+
+keywordclass.tex.all=\
+ $(keywordclass.tex.tex) \
+ $(keywordclass.tex.etex) \
+ $(keywordclass.tex.pdftex) \
+ $(keywordclass.tex.aleph) \
+ $(keywordclass.tex.omega) \
+ $(keywordclass.tex.xetex) \
+ $(keywordclass.tex.plain)
+
+# keywords1 is not used since scintilla takes it from 'keywords' and
+# the other slots are used for context (interfaces) and slot 8 can
+# be used for latex but as scite ships with its own latex support
+# anyway so we don't bother about it here
+
+keywords.$(file.patterns.tex)=$(keywordclass.tex.all)
+
+# TeX: words
+
+word.characters.$(file.patterns.tex)=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@\\
+
+# TeX: end of file
diff --git a/Master/texmf-dist/context/data/scite/tex.properties b/Master/texmf-dist/context/data/scite/tex.properties
new file mode 100644
index 00000000000..3fbad41cb0e
--- /dev/null
+++ b/Master/texmf-dist/context/data/scite/tex.properties
@@ -0,0 +1 @@
+import scite-tex
diff --git a/Master/texmf-dist/context/data/textadept/context.lua b/Master/texmf-dist/context/data/textadept/context.lua
deleted file mode 100644
index f386eb87d13..00000000000
--- a/Master/texmf-dist/context/data/textadept/context.lua
+++ /dev/null
@@ -1,710 +0,0 @@
---[[
- Preliminary ConTeXT lexer
-
- % ConTeXt
- tex context
- mkii context
- mkiv context
-
- experiment dd 2009/10/28 .. todo:
-
- -- figure out if tabs instead of splits are possible
- -- locate an option to enter name in file dialogue (like windows permits)
- -- nesting of lua somehow does not re-lex while typing (backtrack till begin_...)
- -- find trick to overload latex lexer (mime_types, metatype trickery)
- -- convert scite lua scripts to textadept
- -- check linux and osx versions
- -- figure out why loading a file fails (lfs too)
-
- so, this is just an experiment
-
-]]--
-
-local textadept = _G.textadept
-
-module(..., package.seeall)
-
-local context = context
-local lua = require 'lua'
-
-local P, R, S, V = lpeg.P, lpeg.R, lpeg.S, lpeg.V
-
---~ local some_words = { "starttext", "stoptext", "writestatus" }
-
-local some_words = {
- "CAP",
- "Cap",
- "Caps",
- "Character",
- "Characters",
- "MONTH",
- "Romannumerals",
- "WEEKDAY",
- "WORD",
- "WORDS",
- "Word",
- "Words",
- "about",
- "adaptlayout",
- "adding",
- "appendix",
- "arg",
- "at",
- "atpage",
- "background",
- "blackrule",
- "blackrules",
- "blank",
- "bookmark",
- "but",
- "button",
- "bypassblocks",
- "cap",
- "chapter",
- "character",
- "characters",
- "chem",
- "clip",
- "clonefield",
- "color",
- "column",
- "comment",
- "comparecolorgroup",
- "comparepalet",
- "completecombinedlist",
- "completelistoffloats",
- "completelistofsorts",
- "completelistofsynonyms",
- "completeregister",
- "convertnumber",
- "copyfield",
- "correctwhitespace",
- "coupledocument",
- "coupledregister",
- "couplemarking",
- "couplepage",
- "couplepaper",
- "coupleregister",
- "crlf",
- "currentdate",
- "currentheadnumber",
- "date",
- "decouplemarking",
- "define",
- "defineblank",
- "defineblock",
- "definebodyfont",
- "definebodyfontenvironment",
- "definebuffer",
- "definecolor",
- "definecolorgroup",
- "definecombinedlist",
- "defineconversion",
- "definedescription",
- "defineenumeration",
- "definefield",
- "definefieldstack",
- "definefiguresymbol",
- "definefloat",
- "definefont",
- "defineframed",
- "defineframedtext",
- "definehead",
- "defineindenting",
- "defineinteractionmenu",
- "defineinteractionmenu",
- "definelabel",
- "definelist",
- "definelogo",
- "definemakeup",
- "definemarking",
- "defineoutput",
- "defineoverlay",
- "definepalet",
- "definepapersize",
- "defineparagraphs",
- "defineprofile",
- "defineprogram",
- "definerawfont",
- "definereference",
- "definereferenceformat",
- "definereferencelist",
- "defineregister",
- "definerule",
- "definesection",
- "definesectionblock",
- "definesorting",
- "definestartstop",
- "definesubfield",
- "definesymbol",
- "definesynonyms",
- "definetabletemplate",
- "definetabulate",
- "definetext",
- "definetextposition",
- "definetextvariable",
- "definetype",
- "definetyping",
- "defineversion",
- "description",
- "determineheadnumber",
- "determinelistcharacteristics",
- "disableinteractionmenu",
- "donttest",
- "emptylines",
- "enumeration",
- "externalfigure",
- "field",
- "fieldstack",
- "fillinfield",
- "fillinline",
- "fillinrules",
- "fillintext",
- "fitfield",
- "fixedspaces",
- "followprofile",
- "followprofileversion",
- "followversion",
- "footnote",
- "footnotetext",
- "forceblocks",
- "fraction",
- "framed",
- "framedtext",
- "from",
- "getbuffer",
- "getmarking",
- "godown",
- "goto",
- "gotobox",
- "graycolor",
- "grid",
- "hairline",
- "head",
- "headnumber",
- "headtext",
- "hideblocks",
- "high",
- "hl",
- "in",
- "indentation",
- "indenting",
- "inframed",
- "ininner",
- "inleft",
- "inline",
- "inmargin",
- "inothermargin",
- "inouter",
- "inright",
- "installlanguage",
- "interactionbar",
- "interactionbuttons",
- "item",
- "items",
- "its",
- "keepblocks",
- "labeling",
- "labels",
- "labeltext",
- "language",
- "leftaligned",
- "listsymbol",
- "loadsorts",
- "loadsynonyms",
- "logfields",
- "lohi",
- "low",
- "mainlanguage",
- "mar",
- "marginrule",
- "margintext",
- "marking",
- "markversion",
- "mathematics",
- "mediaeval",
- "midaligned",
- "mirror",
- "month",
- "moveongrid",
- "name",
- "nextsection",
- "nocap",
- "noheaderandfooterlines",
- "noindenting",
- "nolist",
- "nomarking",
- "nomoreblocks",
- "nomorefiles",
- "nop",
- "nospace",
- "note",
- "notopandbottomlines",
- "nowhitespace",
- "numbers",
- "overbar",
- "overbars",
- "overstrike",
- "overstrikes",
- "packed",
- "page",
- "pagereference",
- "pagetype",
- "paragraph",
- "part",
- "periods",
- "placebookmarks",
- "placecombinedlist",
- "placecombinedlist",
- "placefloat",
- "placefootnotes",
- "placeformula",
- "placelegend",
- "placelist",
- "placelistoffloats",
- "placelistofsorts",
- "placelistofsynonyms",
- "placelocalfootnotes",
- "placelogos",
- "placeongrid",
- "placeontopofeachother",
- "placereferencelist",
- "placeregister",
- "placeregister",
- "placerule",
- "placesidebyside",
- "placesubformula",
- "placetextvariable",
- "position",
- "positiontext",
- "processblocks",
- "processpage",
- "program",
- "publication",
- "quotation",
- "quote",
- "ran",
- "ref",
- "reference",
- "referral",
- "referraldate",
- "register",
- "reservefloat",
- "reset",
- "resetmarking",
- "resettextcontent",
- "rightaligned",
- "romannumerals",
- "rotate",
- "scale",
- "screen",
- "section",
- "seeregister",
- "selectblocks",
- "selectpaper",
- "selectversion",
- "settextcontent",
- "settextvariable",
- "setupalign",
- "setuparranging",
- "setupbackground",
- "setupbackgrounds",
- "setupblackrules",
- "setupblank",
- "setupblock",
- "setupbodyfont",
- "setupbodyfontenvironment",
- "setupbottom",
- "setupbottomtexts",
- "setupbuffer",
- "setupbuttons",
- "setupcapitals",
- "setupcaption",
- "setupcaptions",
- "setupclipping",
- "setupcolor",
- "setupcolors",
- "setupcolumns",
- "setupcombinations",
- "setupcombinedlist",
- "setupcomment",
- "setupdescriptions",
- "setupenumerations",
- "setupexternalfigures",
- "setupfield",
- "setupfields",
- "setupfillinlines",
- "setupfillinrules",
- "setupfloat",
- "setupfloats",
- "setupfloatsplitting",
- "setupfooter",
- "setupfootertexts",
- "setupfootnotedefinition",
- "setupfootnotes",
- "setupforms",
- "setupformulae",
- "setupframed",
- "setupframedtexts",
- "setuphead",
- "setupheader",
- "setupheadertexts",
- "setupheadnumber",
- "setupheads",
- "setupheadtext",
- "setuphyphenmark",
- "setupindentations",
- "setupindenting",
- "setupinmargin",
- "setupinteraction",
- "setupinteractionbar",
- "setupinteractionscreen",
- "setupinterlinespace",
- "setupinterlinespace",
- "setupitemgroup",
- "setupitems",
- "setuplabeltext",
- "setuplanguage",
- "setuplayout",
- "setuplegend",
- "setuplinenumbering",
- "setuplines",
- "setuplinewidth",
- "setuplist",
- "setuplistalternative",
- "setupmakeup",
- "setupmarginblocks",
- "setupmarginrules",
- "setupmarking",
- "setupnarrower",
- "setupnumbering",
- "setupoppositeplacing",
- "setupoutput",
- "setuppagenumber",
- "setuppagenumbering",
- "setuppagetransitions",
- "setuppalet",
- "setuppaper",
- "setuppapersize",
- "setupparagraphnumbering",
- "setupparagraphs",
- "setuppositioning",
- "setupprofiles",
- "setupprograms",
- "setuppublications",
- "setupquote",
- "setupreferencelist",
- "setupreferencing",
- "setupregister",
- "setuprotate",
- "setuprule",
- "setupscreens",
- "setupsection",
- "setupsectionblock",
- "setupsorting",
- "setupspacing",
- "setupstrut",
- "setupsubpagenumber",
- "setupsymbolset",
- "setupsynchronization",
- "setupsynchronizationbar",
- "setupsynonyms",
- "setupsystem",
- "setuptab",
- "setuptables",
- "setuptabulate",
- "setuptext",
- "setuptextposition",
- "setuptextrules",
- "setuptexttexts",
- "setuptextvariable",
- "setupthinrules",
- "setuptolerance",
- "setuptop",
- "setuptoptexts",
- "setuptype",
- "setuptyping",
- "setupunderbar",
- "setupurl",
- "setupversions",
- "setupwhitespace",
- "showbodyfont",
- "showbodyfontenvironment",
- "showcolor",
- "showcolorgroup",
- "showexternalfigures",
- "showfields",
- "showframe",
- "showgrid",
- "showlayout",
- "showmakeup",
- "showpalet",
- "showprint",
- "showsetups",
- "showstruts",
- "showsymbolset",
- "someline",
- "somewhere",
- "sort",
- "space",
- "splitfloat",
- "startalignment",
- "startbackground",
- "startbuffer",
- "startcolor",
- "startcolumns",
- "startcombination",
- "startcomment",
- "startcomponent",
- "startdescription",
- "startdocument",
- "startenumeration",
- "startenvironment",
- "startfact",
- "startfigure",
- "startfloattext",
- "startformula",
- "startframedtext",
- "starthiding",
- "startinteractionmenu",
- "startitemgroup",
- "startlegend",
- "startline",
- "startlinecorrection",
- "startlinenumbering",
- "startlines",
- "startlocal",
- "startlocalenvironment",
- "startlocalfootnotes",
- "startmakeup",
- "startmarginblock",
- "startmarginrule",
- "startnamemakeup",
- "startnarrower",
- "startopposite",
- "startoverlay",
- "startoverview",
- "startpacked",
- "startparagraph",
- "startpositioning",
- "startpostponing",
- "startproduct",
- "startprofile",
- "startproject",
- "startquotation",
- "startregister",
- "startsymbolset",
- "startsynchronization",
- "starttable",
- "starttables",
- "starttabulate",
- "starttextrule",
- "starttyping",
- "startunpacked",
- "startversion",
- "stopalignment",
- "stopbackground",
- "stopbuffer",
- "stopcolor",
- "stopcolumns",
- "stopcombination",
- "stopcomment",
- "stopcomponent",
- "stopdescription",
- "stopdocument",
- "stopenumeration",
- "stopenvironment",
- "stopfact",
- "stopfigure",
- "stopfloattext",
- "stopformula",
- "stopframedtext",
- "stophiding",
- "stopinteractionmenu",
- "stopitemgroup",
- "stoplegend",
- "stopline",
- "stoplinecorrection",
- "stoplinenumbering",
- "stoplines",
- "stoplocal",
- "stoplocalenvironment",
- "stoplocalfootnotes",
- "stopmakeup",
- "stopmarginblock",
- "stopmarginrule",
- "stopnamemakeup",
- "stopnarrower",
- "stopopposite",
- "stopoverlay",
- "stopoverview",
- "stoppacked",
- "stopparagraph",
- "stoppositioning",
- "stoppostponing",
- "stopproduct",
- "stopprofile",
- "stopproject",
- "stopquotation",
- "stopsymbolset",
- "stopsynchronization",
- "stoptable",
- "stoptables",
- "stoptabulate",
- "stoptextrule",
- "stoptyping",
- "stopunpacked",
- "stopversion",
- "stretched",
- "sub",
- "subject",
- "subsection",
- "subsubject",
- "subsubsection",
- "subsubsubject",
- "switchtobodyfont",
- "switchtorawfont",
- "sym",
- "symbol",
- "synchronizationbar",
- "synchronize",
- "synonym",
- "tab",
- "tex",
- "textreference",
- "textrule",
- "textvariable",
- "thinrule",
- "thinrules",
- "title",
- "tooltip",
- "translate",
- "typ",
- "type",
- "typebuffer",
- "typefile",
- "underbar",
- "underbars",
- "useURL",
- "useblocks",
- "usecommands",
- "usedirectory",
- "useencoding",
- "useexternaldocument",
- "useexternalfigure",
- "useexternalfile",
- "useexternalfiles",
- "useexternalsoundtrack",
- "usemodule",
- "usereferences",
- "usespecials",
- "usesymbols",
- "version",
- "vl",
- "weekday",
- "whitespace",
- "wordright",
- "writebetweenlist",
- "writetolist",
- "writetoreferencelist",
- "writetoregister",
-}
-
-local tex_word_match = word_match(word_list(some_words))
-
---~ local function tex_preamble_match()
---~ return P(function(input, index)
---~ if index < 10 then
---~ local s, e, word = input:find('^(.+)[\n\r]',index)
---~ if word then
---~ local interface = word:match("interface=(..)")
---~ if interface then
---~ local name = "c:/data/develop/context/lua/textadept/cont-" .. interface .. "-scite.lua"
---~ --~ local f = io.open(name,"rb") -- fails
---~ if f then
---~ local data = f:read("*all")
---~ data = data and loadstring(data)
---~ data = data and data()
---~ if data and type(data) == "table" then
---~ some_words = word_list(data)
---~ context.LoadTokens()
---~ -- InitLexer(context)
---~ end
---~ f:close()
---~ end
---~ end
---~ end
---~ end
---~ return false
---~ end)
---~ end
-
-local spacing = token('whitespace', S(" \n\r\t\f")^1)
---~ local preamble = token('preamble', P('%') * tex_preamble_match())
-local comment = token('comment', P('%') * (1-S("\n\r"))^0)
-local keyword = token('keyword', P('\\') * tex_word_match)
-local command = token('command', P('\\') * ((R("az","AZ")+S("@!?"))^1 + P(1)))
-local grouping = token('grouping', S("{$}"))
-local specials = token('specials', S("#()[]<>=\""))
-local extras = token('extras', S("`~%^&_-+/\'|"))
-
--- LexByLine = true
-
-local startluacode = token("grouping", P("\\startluacode"))
-local stopluacode = token("grouping", P("\\stopluacode"))
---~ local startctxlua = token("grouping", P("\\ctxlua") * spacing^0 * P("{"))
---~ local stopctxlua = token("grouping", P("}"))
-
---~ local startMPcode = token("grouping", P("\\startMPcode"))
---~ local stopMPcode = token("grouping", P("\\stopMPcode"))
---~ local startuseMPgraphic = token("grouping", P("\\startuseMPgraphic"))
---~ local stopuseMPgraphic = token("grouping", P("\\stopuseMPgraphic"))
---~ local startreusableMPgraphic = token("grouping", P("\\startreusableMPgraphic"))
---~ local stopreusableMPgraphic = token("grouping", P("\\stopreusableMPgraphic"))
---~ local startuniqueMPgraphic = token("grouping", P("\\startuniqueMPgraphic"))
---~ local stopuniqueMPgraphic = token("grouping", P("\\stopuniqueMPgraphic"))
-
-function LoadTokens()
-
- lua.LoadTokens()
-
- add_token(context, 'whitespace', spacing)
---~ add_token(context, 'preamble', preamble)
- add_token(context, 'comment', comment)
- add_token(context, 'keyword', keyword)
- add_token(context, 'command', command)
- add_token(context, 'grouping', grouping)
- add_token(context, 'specials', specials)
- add_token(context, 'extras', extras)
- add_token(context, 'any_char', any_char)
-
- lua.TokenPatterns.any_char = token('default', 1 - stopluacode)
-
- make_embeddable(lua, context, startluacode, stopluacode)
--- make_embeddable(lua, context, startctxlua, stopctxlua) -- no multiple embeddables unless more complex anychar
- embed_language(context, lua)
-
--- metapost.LoadTokens()
--- metapost.TokenPatterns.any_char = token('any_char', 1 - stopMPcode - stopuseMPgraphic - stopreusableMPgraphic - stopuniqueMPgraphic)
--- make_embeddable(metapost, context, startMPcode, stopMPcode )
--- make_embeddable(metapost, context, startuseMPgraphic, stopuseMPgraphic )
--- make_embeddable(metapost, context, startreusableMPgraphic, stopreusableMPgraphic)
--- make_embeddable(metapost, context, startuniqueMPgraphic, stopuniqueMPgraphic )
-end
-
-local bold = true
-local italic = true
-
-function LoadStyles()
- add_style('preamble', style_nothing .. { fore = colors.yellow, bold = bold })
- add_style('comment', style_nothing .. { fore = colors.yellow, bold = bold })
- add_style('keyword', style_nothing .. { fore = colors.green, bold = bold, italic = italic })
- add_style('command', style_nothing .. { fore = colors.green, bold = bold })
- add_style('grouping', style_nothing .. { fore = colors.red, bold = bold })
- add_style('specials', style_nothing .. { fore = colors.blue, bold = bold })
- add_style('extras', style_nothing .. { fore = colors.yellow, bold = bold })
-end
-
---~ textadept.mime_types.extensions["tex"] = context
---~ textadept.mime_types.extensions["mkii"] = context
---~ textadept.mime_types.extensions["mkiv"] = context
diff --git a/Master/texmf-dist/context/data/textpad/textpad-context-template.txt b/Master/texmf-dist/context/data/textpad/textpad-context-template.txt
deleted file mode 100644
index 48d0b86f9e0..00000000000
--- a/Master/texmf-dist/context/data/textpad/textpad-context-template.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-; TextPad syntax definitions for ConTeXt (and LaTeX, respectively)
-
-LaTeX=1
-
-[Syntax]
-Namespace1=6
-IgnoreCase=No
-InitKeyWordChars=\abcdefghijklmopqrstuvwxyzABCDEFGHIJKLMOPQRSTUVWXYZ
-KeyWordChars=A-Za-z0-9@*'`!
-BracketChars={}[]()
-OperatorChars=-+*/<>!~%^&|=
-PreprocStart=
-SyntaxStart=
-SyntaxEnd=
-CommentStart=
-CommentEnd=
-CommentStartAlt=$
-CommentEndAlt=$
-SingleComment=%
-SingleCommentCol=
-SingleCommentAlt=
-SingleCommentColAlt=
-SingleCommentEsc=\
-StringStart=
-StringEnd=
-StringAlt=
-StringEsc=
-CharStart=
-CharEnd=
-CharEsc=
-
-[Keywords 1]
-; category: tex commands
-; filename: tex-commands.txt
-
-[Keywords 2]
-; category: context commands
-; filename: context-commands-en.txt
-
-[Keywords 3]
-; category: context commands
-; filename: context-environments-en.txt
-
-[Keywords 4]
-; category: latex commands
-; filename: latex-commands-1.txt
-
-[Keywords 5]
-; category: latex commands
-; filename: latex-commands-2.txt
-
-[Keywords 6]
-; category: latex commands
-; filename: latex-commands-3.txt
diff --git a/Master/texmf-dist/fonts/map/pdftex/context/original-base.map b/Master/texmf-dist/fonts/map/pdftex/context/original-base.map
index 637a87aa518..4958426c522 100644
--- a/Master/texmf-dist/fonts/map/pdftex/context/original-base.map
+++ b/Master/texmf-dist/fonts/map/pdftex/context/original-base.map
@@ -6,8 +6,7 @@ rsfs10 rsfs10 <rsfs10.pfb
% marvosym
-fmvr8x MarVoSym <marvosym.pfb
-fmvri8x MarVoSym ".167 SlantFont" <marvosym.pfb
+umvs MarVoSym <marvosym.pfb
% context
diff --git a/Master/texmf-dist/metapost/context/base/metafun.mp b/Master/texmf-dist/metapost/context/base/metafun.mp
index 00011c8be51..ae0a6d6fdf7 100644
--- a/Master/texmf-dist/metapost/context/base/metafun.mp
+++ b/Master/texmf-dist/metapost/context/base/metafun.mp
@@ -1,75 +1,8 @@
-%D \module
-%D [ file=metafun.mp,
-%D version=2000.07.15,
-%D title=\CONTEXT\ \METAPOST\ graphics,
-%D subtitle=format generation file,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
+if known metafunversion : endinput ; fi ;
-%D When generating many graphics at runtime, it can save run
-%D time to use a format file. We could have named this file
-%D \type {context}, but this is error prone, because it forces
-%D to use the progname \type {mpost} or \type {context}
-%D explicitly, depending on the needs. When using the format,
-%D a mismatch in the memory specification of \type {mpost} or
-%D \type {context} (the \TEX\ one) could lead to lost strings
-%D (and as a result in buggy boundingbox and special
-%D handling). By using the name \type {metatex} we make sure
-%D that we use (unless overloaded) the settings of \type
-%D {mpost}.
-
-%D First we input John Hobby's metapost plain file. However,
-%D because we want to prevent dependency problems and in the
-%D end even may use a patched version, we prefer to use a
-%D copy,
-
-if unknown ahangle :
- input mp-base.mp ; % input plain.mp ;
+if known mplib :
+ input metafun.mpiv
else :
- let dump = relax ;
+ input metafun.mpii
fi ;
-input mp-tool.mp ;
-input mp-spec.mp ; % will be skipped in mkiv, some day
-input mp-core.mp ;
-input mp-page.mp ;
-input mp-text.mp ;
-input mp-txts.mp ;
-input mp-shap.mp ;
-input mp-butt.mp ;
-input mp-char.mp ;
-input mp-step.mp ;
-input mp-grph.mp ;
-input mp-figs.mp ;
-
-input mp-mlib.mp ;
-
-if known context_mlib : input mp-chem.mp ; fi ; % only when mkiv
-
-% mp-form.mp ;
-input mp-grid.mp ;
-input mp-func.mp ;
-
-string metafunversion ;
-
-metafunversion = "metafun" & " " &
- decimal year & "-" &
- decimal month & "-" &
- decimal day & " " &
- if ((time div 60) < 10) : "0" & fi
- decimal (time div 60) & ":" &
- if ((time-(time div 60)*60) < 10) : "0" & fi
- decimal (time-(time div 60)*60) ;
-
-let normalend = end ;
-
-def end =
- ; message "" ; message metafunversion ; message "" ; normalend ;
-enddef ;
-
-dump ; endinput .
diff --git a/Master/texmf-dist/metapost/context/base/metafun.mpii b/Master/texmf-dist/metapost/context/base/metafun.mpii
new file mode 100644
index 00000000000..0de186ed220
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/metafun.mpii
@@ -0,0 +1,65 @@
+%D \module
+%D [ file=metafun.mp,
+%D version=2000.07.15,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=format generation file,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 When generating many graphics at runtime, it can save run
+%D time to use a format file. We could have named this file
+%D \type {context}, but this is error prone, because it forces
+%D to use the progname \type {mpost} or \type {context}
+%D explicitly, depending on the needs. When using the format,
+%D a mismatch in the memory specification of \type {mpost} or
+%D \type {context} (the \TEX\ one) could lead to lost strings
+%D (and as a result in buggy boundingbox and special
+%D handling). By using the name \type {metatex} we make sure
+%D that we use (unless overloaded) the settings of \type
+%D {mpost}.
+
+%D First we input John Hobby's metapost plain file. However,
+%D because we want to prevent dependency problems and in the
+%D end even may use a patched version, we prefer to use a
+%D copy.
+
+input "mp-base.mpii" ;
+input "mp-tool.mpii" ;
+input "mp-spec.mpii" ;
+input "mp-core.mpii" ;
+input "mp-page.mpii" ;
+input "mp-text.mpii" ;
+input "mp-txts.mpii" ;
+input "mp-shap.mpii" ;
+input "mp-butt.mpii" ;
+input "mp-char.mpii" ;
+input "mp-step.mpii" ;
+input "mp-grph.mpii" ;
+input "mp-figs.mpii" ;
+%%%%% "mp-form.mpii" ;
+input "mp-grid.mpii" ;
+input "mp-func.mpii" ;
+
+string metafunversion ;
+
+metafunversion = "metafun ii" & " " &
+ decimal year & "-" &
+ decimal month & "-" &
+ decimal day & " " &
+ if ((time div 60) < 10) : "0" & fi
+ decimal (time div 60) & ":" &
+ if ((time-(time div 60)*60) < 10) : "0" & fi
+ decimal (time-(time div 60)*60) ;
+
+let normalend = end ;
+
+def end =
+ ; message "" ; message metafunversion ; message "" ; normalend ;
+enddef ;
+
+dump ;
diff --git a/Master/texmf-dist/metapost/context/base/metafun.mpiv b/Master/texmf-dist/metapost/context/base/metafun.mpiv
new file mode 100644
index 00000000000..d600764a3d0
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/metafun.mpiv
@@ -0,0 +1,52 @@
+%D \module
+%D [ file=metafun.mp,
+%D version=2000.07.15,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=format generation file,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 First we input John Hobby's metapost plain file. However,
+%D because we want to prevent dependency problems and in the
+%D end even may use a patched version, we prefer to use a
+%D copy.
+
+input "mp-base.mpiv" ;
+input "mp-tool.mpiv" ;
+input "mp-mlib.mpiv" ;
+% "mp-core.mpiv" ; % todo: namespace and cleanup
+input "mp-page.mpiv" ; % todo: namespace and cleanup
+input "mp-butt.mpiv" ; % todo: namespace and cleanup
+input "mp-shap.mpiv" ; % will be improved
+input "mp-grph.mpiv" ; % todo: namespace and cleanup
+input "mp-grid.mpiv" ; % todo: namespace and cleanup
+input "mp-form.mpiv" ; % under (re)construction
+input "mp-figs.mpiv" ; % obsolete, needs checking
+input "mp-func.mpiv" ; % under construction
+% "mp-text.mpiv" ; % loaded on demand
+% "mp-char.mpiv" ; % loaded on demand
+% "mp-step.mpiv" ; % loaded on demand
+% "mp-chem.mpiv" ; % loaded on demand
+
+string metafunversion ; metafunversion =
+ "metafun iv" & " " &
+ decimal year & "-" &
+ decimal month & "-" &
+ decimal day & " " &
+ if ((time div 60) < 10) : "0" & fi
+ decimal (time div 60) & ":" &
+ if ((time-(time div 60)*60) < 10) : "0" & fi
+ decimal (time-(time div 60)*60) ;
+
+let normalend = end ;
+
+def end =
+ ; message "" ; message metafunversion ; message "" ; normalend ;
+enddef ;
+
+dump ; % obsolete in mplib
diff --git a/Master/texmf-dist/metapost/context/base/mp-abck.mpiv b/Master/texmf-dist/metapost/context/base/mp-abck.mpiv
new file mode 100644
index 00000000000..977bebcfdb5
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-abck.mpiv
@@ -0,0 +1,269 @@
+%D \module
+%D [ file=mp-abck.mp,
+%D version=2012.02.19, % was mp-core: 1999.08.01, anchoring
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=anchored background macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+if known context_abck : endinput ; fi ;
+
+boolean context_abck ; context_abck := true ;
+
+path multiregs[], % region used for multipar (tracing only)
+ multipars[], % effective area (shape)
+ multibox ; % main boundingbox (of main region)
+
+string multikind[] ; % region state: single | first | middle | last (new method)
+
+numeric multilocs[], % 1=begin 2=between 3=end (old method)
+ nofmultipars ; % number of calculated areas
+
+numeric par_strut_height,
+ par_strut_depth,
+ par_line_height ;
+
+nofmultipars := 0 ;
+par_strut_height := 0 ;
+par_strut_depth := 0 ;
+par_line_height := 0 ;
+
+def boxgridoptions = withcolor .8red enddef ;
+def boxlineoptions = withcolor .8blue enddef ;
+def boxfilloptions = withcolor .8white enddef ;
+
+numeric boxgridtype ; boxgridtype := 0 ;
+numeric boxlinetype ; boxlinetype := 1 ;
+numeric boxfilltype ; boxfilltype := 1 ;
+numeric boxdashtype ; boxdashtype := 0 ;
+pair boxgriddirection ; boxgriddirection := up ;
+numeric boxgridwidth ; boxgridwidth := 1pt ;
+numeric boxlinewidth ; boxlinewidth := 1pt ;
+numeric boxlineradius ; boxlineradius := 0 ;
+numeric boxlineoffset ; boxlineoffset := 0 ;
+numeric boxfilloffset ; boxfilloffset := 0 ;
+numeric boxgriddistance ; boxgriddistance := .5cm ;
+numeric boxgridshift ; boxgridshift := 0 ;
+
+def abck_show_path(expr p, r, c) =
+ draw p withpen pencircle scaled .5pt withcolor c ;
+ if length(p) > 2 :
+ begingroup ; save _c_ ; path _c_ ; _c_ := fullcircle scaled r ;
+ for i=0 upto length(p) if cycle p : -1 fi :
+ fill _c_ shifted point i of p withcolor white ;
+ draw _c_ shifted point i of p withpen pencircle scaled .5pt withcolor c ;
+ endfor ;
+ fi ;
+enddef ;
+
+vardef abck_draw_path(expr p) =
+ if (length p > 2) and (bbwidth(p) > 1) and (bbheight(p) > 1) :
+ save pp ; path pp ;
+ pp := p if (boxlineradius>0) and (boxlinetype=2) : cornered boxlineradius fi ;
+ if boxfilltype > 0 :
+ if boxfilloffset > 0 :
+ interim linejoin := mitered ;
+ filldraw pp boxfilloptions withpen pencircle scaled (2*boxfilloffset) ;
+ else :
+ fill pp boxfilloptions ;
+ fi ;
+ fi ;
+ if boxlinetype > 0 :
+ draw pp boxlineoptions withpen pencircle scaled boxlinewidth ;
+ fi ;
+ fi ;
+enddef ;
+
+def abck_grid_line(expr start, width) =
+ % 1 = normal, 2 = with background (i.e. no shine-through)
+ if boxdashtype = 2 :
+ draw start -- start shifted (width,0)
+ withpen pencircle scaled boxgridwidth
+ boxfilloptions ;
+ fi ;
+ draw start -- start shifted (width,0)
+ if boxdashtype > 0 :
+ dashed evenly
+ fi
+ withpen pencircle scaled boxgridwidth
+ boxgridoptions ;
+enddef ;
+
+vardef abck_baseline_grid(expr pxy, pdir, at_baseline) =
+ save width ; width := bbwidth(pxy) ;
+ save height ; height := bbheight(pxy) ;
+ if (par_line_height > 0) and (height > 1) and (width > 1) and (boxgridwidth > 0) :
+ save i, grid, bb ; picture grid ; pair start ; path bb ;
+ grid := image ( % fails with inlinespace
+ if pdir = up :
+ for i = if at_baseline : par_strut_depth else : 0 fi step par_line_height until max(height,par_line_height) :
+ abck_grid_line(llcorner pxy shifted (0,+i),width) ;
+ endfor ;
+ else :
+ for i = if at_baseline : par_strut_height else : 0 fi step par_line_height until height :
+ abck_grid_line(ulcorner pxy shifted (0,-i),width) ;
+ endfor ;
+ fi ;
+ ) ;
+ clip grid to pxy ;
+ bb := boundingbox grid ;
+ grid := grid shifted (0,boxgridshift) ;
+ setbounds grid to bb ;
+ grid
+ else :
+ nullpicture
+ fi
+enddef ;
+
+vardef abck_graphic_grid(expr pxy, dx, dy, x, y) =
+ if (bbheight(pxy) > dy) and (bbwidth(pxy) > dx) and (boxgridwidth > 0) :
+ save grid ; picture grid ;
+ grid := image (
+ for i = xpart llcorner pxy step dx until xpart lrcorner pxy :
+ draw (i,ypart llcorner pxy) -- (i,ypart ulcorner pxy) withpen pencircle scaled boxgridwidth ;
+ endfor ;
+ for i = ypart llcorner pxy step dy until ypart ulcorner pxy :
+ draw (xpart llcorner pxy,i) -- (xpart lrcorner pxy,i) withpen pencircle scaled boxgridwidth ;
+ endfor
+ ) shifted (x,y) ;
+ clip grid to pxy ;
+ grid
+ else :
+ nullpicture
+ fi
+enddef ;
+
+def draw_multi_pars =
+ for i=1 upto nofmultipars :
+ abck_draw_path(multipars[i]) ;
+ if boxgridtype = 1 :
+ draw abck_baseline_grid(multipars[i],if multilocs[i]=1: down else: up fi,true) ;
+ elseif boxgridtype = 2 :
+ draw abck_baseline_grid(multipars[i],if multilocs[i]=1: down else: up fi,false) ;
+ elseif boxgridtype = 3 :
+ draw abck_baseline_grid(multipars[i],if multilocs[i]=1: down else: up fi,true) ;
+ draw abck_baseline_grid(multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight) ;
+ elseif boxgridtype = 4 :
+ draw abck_baseline_grid(multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight/2) ;
+ elseif boxgridtype = 11 :
+ draw abck_graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+ elseif boxgridtype = 12 :
+ draw abck_graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ;
+ fi ;
+ endfor ;
+enddef ;
+
+def show_multi_pars =
+ for i=1 upto nofmultipars :
+ abck_show_path(multipars[i], 6pt, .5blue) ;
+ endfor ;
+enddef ;
+
+def show_multi_kind =
+ for i=1 upto nofmultipars :
+ fill multipars[i]
+ withcolor
+ if multikind[i] = "single" : yellow
+ elseif multikind[i] = "first" : red
+ elseif multikind[i] = "middle" : green
+ elseif multikind[i] = "last" : blue
+ fi
+ withtransparency (1,.5)
+ ;
+ endfor ;
+enddef ;
+
+def multi_side_draw_options = enddef ;
+
+def draw_multi_side =
+ begingroup ; save p ; picture p ;
+ for i=1 upto nofmultipars :
+ p := image ( fill leftboundary multipars[i]
+ shifted (-boxlineoffset,0)
+ rightenlarged boxlinewidth boxlineoptions ;
+ ) ;
+ setbounds p to multipars[i] ;
+ draw p ;
+ endfor ;
+ endgroup ;
+enddef ;
+
+def draw_multi_side_path text t =
+ begingroup ; save p ; picture p ;
+ for i=1 upto nofmultipars :
+ p := image ( draw leftboundary multipars[i]
+ shifted (-boxlineoffset,0)
+ withpen pensquare scaled boxlinewidth boxlineoptions t ;
+ ) ;
+ setbounds p to multipars[i] ;
+ draw p ;
+ endfor ;
+ endgroup ;
+enddef ;
+
+% some extras
+
+path posboxes[],
+ posregions[] ;
+
+numeric multipages[],
+ nofposboxes ;
+
+nofposboxes := 0 ;
+
+% For the moment we keep these as they can be in use but they will
+% disappear.
+
+pair lxy[], rxy[], cxy[], llxy[], lrxy[], ulxy[], urxy[] ;
+path pxy[] ;
+numeric hxy[], wxy[], dxy[], nxy[] ;
+
+def box_found (expr n,x,y,w,h,d) =
+ not ((x=0) and (y=0) and (w=0) and (h=0) and (d=0))
+enddef ;
+
+def initialize_box_pos (expr pos,n,x,y,w,h,d) =
+ pair lxy, rxy, cxy, llxy, lrxy, ulxy, urxy ;
+ path pxy ; numeric hxy, wxy, dxy, nxy;
+ lxy := (x,y) ;
+ llxy := (x,y-d) ;
+ lrxy := (x+w,y-d) ;
+ urxy := (x+w,y+h) ;
+ ulxy := (x,y+h) ;
+ wxy := w ;
+ hxy := h ;
+ dxy := d ;
+ rxy := lxy shifted (wxy,0) ;
+ pxy := llxy--lrxy--urxy--ulxy--cycle ;
+ cxy := center pxy ;
+ nxy := n ;
+ freeze_box(pos) ;
+enddef ;
+
+def freeze_box (expr pos) =
+ lxy[pos] := lxy ;
+ llxy[pos] := llxy ;
+ lrxy[pos] := lrxy ;
+ urxy[pos] := urxy ;
+ ulxy[pos] := ulxy ;
+ wxy[pos] := wxy ;
+ hxy[pos] := hxy ;
+ dxy[pos] := dxy ;
+ rxy[pos] := rxy ;
+ pxy[pos] := pxy ;
+ cxy[pos] := cxy ;
+ nxy[pos] := nxy ;
+enddef ;
+
+def initialize_box (expr n,x,y,w,h,d) =
+ numeric bpos ; bpos := 0 ; initialize_box_pos(bpos,n,x,y,w,h,d) ;
+enddef ;
+
+def anchor_box (expr n,x,y,w,h,d) =
+ currentpicture := currentpicture shifted (-x,-y) ;
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-apos.mpiv b/Master/texmf-dist/metapost/context/base/mp-apos.mpiv
new file mode 100644
index 00000000000..fad185b7827
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-apos.mpiv
@@ -0,0 +1,102 @@
+%D \module
+%D [ file=mp-apos.mp,
+%D version=2012.02.19, % was mp-core: 1999.08.01, anchoring
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=anchored background macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+if known context_apos : endinput ; fi ;
+
+boolean context_apos ; context_apos := true ;
+
+path posboxes[],
+ posregions[] ;
+
+numeric multipages[],
+ nofposboxes ;
+
+nofposboxes := 0 ;
+
+def boxlineoptions = withcolor .8blue enddef ;
+def boxfilloptions = withcolor .8white enddef ;
+
+def connect_positions =
+ if nofposboxes = 2 :
+ pickup pencircle scaled boxlinewidth ;
+ path pa ; pa := posboxes[1] enlarged boxlineoffset ;
+ path pb ; pb := posboxes[2] enlarged boxlineoffset ;
+ if pospages[1] = pospages[2] :
+ draw posboxes[1] boxlineoptions ;
+ path pc ; pc := center pa {up} .. {down} center pb ;
+ pair cc ; cc := (pc intersection_point pa) ;
+ if intersection_found :
+ pc := pc cutbefore cc ;
+ cc := (pc intersection_point pb) ;
+ if intersection_found :
+ pc := pc cutafter cc ;
+ drawarrow pc boxlineoptions ;
+ drawarrow reverse pc boxlineoptions ;
+ fi ;
+ fi ;
+ elseif pospages[1] == RealPageNumber :
+ draw posboxes[1] boxlineoptions ;
+ path pc ; pc := center pa {up} ... {right} urcorner (posregions[1] enlarged (20pt,20pt)) ;
+ pair cc ; cc := (pc intersection_point pa) ;
+ if intersection_found :
+ pc := pc cutbefore cc ;
+ drawarrow pc boxlineoptions ;
+ fi ;
+ elseif pospages[2] == RealPageNumber :
+ draw posboxes[2] boxlineoptions ;
+ path pc ; pc := ulcorner (posregions[2] enlarged (20pt,20pt)) {right} ... {down} center pb ;
+ pair cc ; cc := (pc intersection_point pb) ;
+ if intersection_found :
+ pc := pc cutafter cc ;
+ drawarrow pc boxlineoptions ;
+ fi ;
+ fi ;
+ fi ;
+enddef ;
+
+% anch-bar:
+
+def anch_sidebars_draw (expr p_b_self, p_e_self, y_b_self, y_e_self, h_b_self, d_e_self,
+ x, y, w, h, alternative, distance, linewidth, linecolor, topoffset, bottomoffset) =
+ % beware, we anchor at (x,y)
+ begingroup ;
+ if alternative = 1 :
+ interim linecap := rounded ;
+ else :
+ interim linecap := butt ;
+ fi ;
+ save a, b ; pair a, b ;
+ if p_b_self = p_e_self :
+ a := (-distance,y_b_self+h_b_self-y) ;
+ b := (-distance,y_e_self-d_e_self-y) ;
+ elseif RealPageNumber = p_b_self :
+ a := (-distance,y_b_self+h_b_self-y) ;
+ b := (-distance,0) ;
+ elseif RealPageNumber = p_e_self :
+ a := (-distance,h) ;
+ b := (-distance,y_e_self-d_e_self-y) ;
+ else :
+ a := (-distance,h) ;
+ b := (-distance,0) ;
+ fi ;
+ a := (xpart a, min(ypart a + topoffset, h)) ;
+ b := (xpart b, max(ypart b - bottomoffset,0)) ;
+ draw
+ a -- b
+ if alternative = 1 :
+ dashed (withdots scaled (linewidth/2))
+ fi
+ withpen pencircle scaled linewidth
+ withcolor linecolor ;
+ endgroup ;
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-asnc.mpiv b/Master/texmf-dist/metapost/context/base/mp-asnc.mpiv
new file mode 100644
index 00000000000..cfee782e778
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-asnc.mpiv
@@ -0,0 +1,177 @@
+%D \module
+%D [ file=mp-asnc.mp,
+%D version=2012.02.19, % was mp-core: 1999.08.01, anchoring
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=anchored background macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+if known context_asnc : endinput ; fi ;
+
+boolean context_av ; context_asnc := true ;
+
+% will be replaced
+
+numeric sync_n[], sync_p[][], sync_w[][], sync_h[][], sync_d[][], sync_t[][] ;
+pair sync_xy[][] ; color sync_c[][] ;
+
+def ResetSyncTasks =
+ path SyncPaths[] ; numeric SyncTasks[], NOfSyncPaths, CurrentSyncClass ;
+ NOfSyncPaths := CurrentSyncClass := 0 ;
+ if unknown SyncLeftOffset : numeric SyncLeftOffset ; SyncLeftOffset := 0 ; fi ;
+ if unknown SyncWidth : numeric SyncWidth ; SyncWidth := 0 ; fi ;
+ if unknown SyncThreshold : numeric SyncThreshold ; SyncThreshold := LineHeight ; fi ;
+ if unknown SyncColor : color SyncColor ; SyncColor := .5white ; fi ;
+ if (SyncLeftOffset = 0) and (SyncWidth = 0) :
+ SyncWidth := if known TextWidth : TextWidth else : -1cm fi ;
+ fi ;
+enddef ;
+
+ResetSyncTasks ;
+
+vardef SyncBox(expr n, i, leftoffset, width, topoffset, bottomoffset) =
+ save o ; pair o ; o := (xpart llcorner PlainTextArea,ypart sync_xy[n][i]) ;
+ o shifted (leftoffset,sync_h[n][i]+topoffset) --
+ o shifted (width+leftoffset,sync_h[n][i]+topoffset) --
+ o shifted (width+leftoffset,bottomoffset) --
+ o shifted (leftoffset,bottomoffset) -- cycle
+enddef ;
+
+def SetSyncColor(expr n, i, c) =
+ sync_c[n][i] := c ;
+enddef ;
+
+def SetSyncThreshold(expr n, i, th) =
+ sync_th[n][i] := th ;
+enddef ;
+
+vardef TheSyncColor(expr n, i) =
+ if known sync_c[n][i] : sync_c[n][i] else : SyncColor fi
+enddef ;
+
+vardef TheSyncThreshold(expr n, i) =
+ if known sync_th[n][i] : sync_th[n][i] else : SyncThreshold fi
+enddef ;
+
+vardef PrepareSyncTasks(expr n, collapse, extendtop, prestartnext) =
+ ResetSyncTasks ;
+ if known sync_n[n] :
+ CurrentSyncClass := n ;
+ save ok, l, d ; boolean ok ; ok := false ; NOfSyncPaths := l := 0 ;
+ for i=1 upto sync_n[n] :
+ if RealPageNumber > sync_p[n][i] :
+ l := i ;
+ elseif RealPageNumber = sync_p[n][i] :
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ if not ok :
+ if i>1 :
+ if sync_t[n][i-1] = sync_t[n][i] :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i-1, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i-1 ;
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ ok := true ;
+ fi ;
+ endfor ;
+ if (NOfSyncPaths = 0) and (l > 0) :
+ NOfSyncPaths := 1 ;
+ SyncPaths[NOfSyncPaths] := SyncBox(n, l, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := l ;
+ fi ;
+ if NOfSyncPaths > 0 :
+ for i = 1 upto NOfSyncPaths-1 :
+ SyncPaths[i] := topboundary SyncPaths[i] -- reverse topboundary SyncPaths[i+1] -- cycle ;
+ endfor ;
+ if unknown SyncThresholdMethod :
+ numeric SyncThresholdMethod ; SyncThresholdMethod := 2 ;
+ fi ;
+ if extendtop :
+ if SyncThresholdMethod = 1 :
+ if NOfSyncPaths>1 :
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[2]]) ;
+ if (SyncTasks[2]>1) and (d > 0pt) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[2]])) and (sync_p[n][SyncTasks[2]] = RealPageNumber) :
+ SyncPaths[2] := SyncPaths[2] topenlarged PaperHeight ;
+ fi ;
+ fi ;
+ else :
+ for i = 1 upto NOfSyncPaths :
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[i]]) ;
+ if (d > 0) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[i]] = RealPageNumber) :
+ SyncPaths[i] := SyncPaths[i] topenlarged PaperHeight ;
+ fi ;
+ endfor ;
+ fi ;
+ fi ;
+ if prestartnext :
+ if NOfSyncPaths>1 :
+ if SyncTasks[NOfSyncPaths] < sync_n[n] : % there is a next one
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[NOfSyncPaths]+1]) ;
+ if (d > 0) and (d <= TheSyncThreshold(n, sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[NOfSyncPaths]+1] = RealPageNumber+1) :
+ SyncPaths[NOfSyncPaths+1] :=
+ (xpart ulcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) --
+ (xpart urcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) --
+ lrcorner SyncPaths[NOfSyncPaths] --
+ llcorner SyncPaths[NOfSyncPaths] -- cycle ;
+ SyncTasks[NOfSyncPaths+1] := SyncTasks[NOfSyncPaths]+1 ;
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ fi ;
+ fi ;
+ fi ;
+ else :
+ if NOfSyncPaths>1 :
+ d := ypart (sync_xy[n][SyncTasks[NOfSyncPaths]] - llcorner PlainTextArea) ;
+ if (d < TheSyncThreshold(n, SyncTasks[NOfSyncPaths])) :
+ NOfSyncPaths := NOfSyncPaths - 1 ;
+ SyncPaths[NOfSyncPaths] := SyncPaths[NOfSyncPaths] bottomenlarged PaperHeight ;
+ fi ;
+ fi ;
+ fi ;
+ if (NOfSyncPaths>1) and collapse :
+ save j ; numeric j ; j := 1 ;
+ for i = 2 upto NOfSyncPaths :
+ if sync_t[n][SyncTasks[i]] = sync_t[n][SyncTasks[j]] :
+ SyncPaths[j] := boundingbox image (draw SyncPaths[i] ; draw SyncPaths[j] ; ) ;
+ SyncTasks[j] := SyncTasks[i] ;
+ else :
+ j := j + 1 ;
+ SyncPaths[j] := SyncPaths[i] ;
+ SyncTasks[j] := SyncTasks[i] ;
+ fi ;
+ endfor ;
+ NOfSyncPaths := j ;
+ fi ;
+ fi ;
+ fi ;
+enddef ;
+
+def SyncTask(expr n) =
+ if known SyncTasks[n] : SyncTasks[n] else : 0 fi
+enddef ;
+
+def FlushSyncTasks =
+ for i = 1 upto NOfSyncPaths :
+ ProcessSyncTask(SyncPaths[i], TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]])) ;
+ endfor ;
+enddef ;
+
+def ProcessSyncTask(expr p, c) =
+ fill p withcolor c ;
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-back.mp b/Master/texmf-dist/metapost/context/base/mp-back.mp
index f49474cf77f..f588adea9c4 100644
--- a/Master/texmf-dist/metapost/context/base/mp-back.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-back.mp
@@ -11,8 +11,7 @@
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
%C details.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_back : endinput ; fi ;
+if known context_back : endinput ; fi ;
boolean context_back ; context_back := true ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-base.mp b/Master/texmf-dist/metapost/context/base/mp-base.mpii
index 93cb5e90c8d..93cb5e90c8d 100644
--- a/Master/texmf-dist/metapost/context/base/mp-base.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-base.mpii
diff --git a/Master/texmf-dist/metapost/context/base/mp-base.mpiv b/Master/texmf-dist/metapost/context/base/mp-base.mpiv
new file mode 100644
index 00000000000..7b3a69bb031
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-base.mpiv
@@ -0,0 +1,867 @@
+% This is a reformatted copy of the plain.mp file. We use a copy
+% because (1) we want to make sure that there are no unresolved
+% dependencies, and (2) we may patch this file eventually.
+
+% This file gives the macros for plain MetaPost It contains all the
+% features of plain METAFONT except those specific to font-making.
+% There are also a number of macros for labeling figures, etc.
+
+% For practical reasons I have moved some new code here (and might
+% remove some code as well). After all, there is no development in
+% this format.
+
+string base_name, base_version ;
+
+base_name := "plain" ;
+base_version := "0.63" ;
+
+message "Preloading the plain mem file, version " & base_version ;
+
+delimiters () ; % this makes parentheses behave like parentheses
+
+def upto = step 1 until enddef ;
+def downto = step -1 until enddef ;
+
+def exitunless expr c =
+ exitif not c
+enddef ;
+
+let relax = \ ; % ignore the word relax, as in TeX
+let \\ = \ ; % double relaxation is like single
+
+def [[ = [ [ enddef ;
+def ]] = ] ] enddef ;
+
+def -- =
+ {curl 1} .. {curl 1}
+enddef ;
+
+def --- =
+ .. tension infinity ..
+enddef ;
+
+def ... =
+ .. tension atleast 1 ..
+enddef ;
+
+def gobble primary g =
+enddef ;
+
+primarydef g gobbled gg =
+enddef ;
+
+def hide(text t) =
+ exitif numeric begingroup t ; endgroup ;
+enddef ;
+
+def ??? =
+ hide (
+ interim showstopping := 1 ;
+ showdependencies
+ )
+enddef ;
+
+def stop expr s =
+ message s ;
+ gobble readstring
+enddef ;
+
+warningcheck :=1 ;
+tracinglostchars :=1 ;
+
+def interact = % sets up to make "show" commands stop
+ hide (
+ showstopping := 1 ;
+ tracingonline := 1 ;
+ )
+enddef ;
+
+def loggingall = % puts tracing info into the log
+ tracingcommands := 3 ;
+ tracingtitles := 1 ;
+ tracingequations := 1 ;
+ tracingcapsules := 1 ;
+ tracingspecs := 2 ;
+ tracingchoices := 1 ;
+ tracinglostchars := 1 ;
+ tracingstats := 1 ;
+ tracingoutput := 1 ;
+ tracingmacros := 1 ;
+ tracingrestores := 1 ;
+enddef ;
+
+def tracingall = % turns on every form of tracing
+ tracingonline := 1 ;
+ showstopping := 1 ;
+ loggingall ;
+enddef ;
+
+def tracingnone = % turns off every form of tracing
+ tracingcommands := 0 ;
+ tracingtitles := 0 ;
+ tracingequations := 0 ;
+ tracingcapsules := 0 ;
+ tracingspecs := 0 ;
+ tracingchoices := 0 ;
+ tracinglostchars := 0 ;
+ tracingstats := 0 ;
+ tracingoutput := 0 ;
+ tracingmacros := 0 ;
+ tracingrestores := 0 ;
+enddef ;
+
+%% dash patterns
+
+vardef dashpattern(text t) =
+ save on, off, w ;
+ let on = _on_ ;
+ let off = _off_ ;
+ w = 0 ;
+ nullpicture t
+enddef ;
+
+tertiarydef p _on_ d =
+ begingroup save pic ;
+ picture pic;
+ pic = p ;
+ addto pic doublepath (w,w) .. (w+d,w) ;
+ w := w + d ;
+ pic shifted (0,d)
+ endgroup
+enddef ;
+
+tertiarydef p _off_ d =
+ begingroup w := w + d ;
+ p shifted (0,d)
+ endgroup
+enddef ;
+
+%% basic constants and mathematical macros
+
+% numeric constants
+
+newinternal eps, epsilon, infinity, _ ;
+
+eps := .00049 ; % this is a pretty small positive number
+epsilon := 1/256/256 ; % but this is the smallest
+infinity := 4095.99998 ; % and this is the largest
+_ := -1 ; % internal constant to make macros unreadable but shorter
+
+% linejoin and linecap types
+
+newinternal mitered, rounded, beveled, butt, squared ;
+
+mitered := 0 ; rounded := 1 ; beveled := 2 ;
+butt := 0 ; rounded := 1 ; squared := 2 ;
+
+% pair constants
+
+pair right, left, up, down, origin;
+
+origin = (0,0) ;
+up = -down = (0,1) ;
+right = -left = (1,0) ;
+
+% path constants
+
+path quartercircle, halfcircle, fullcircle, unitsquare ;
+
+fullcircle = makepath pencircle ;
+halfcircle = subpath (0,4) of fullcircle ;
+quartercircle = subpath (0,2) of fullcircle ;
+unitsquare = (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle ;
+
+% transform constants
+
+transform identity ;
+
+for z=origin,right,up :
+ z transformed identity = z ;
+endfor
+
+% color constants (all in rgb color space)
+
+color black, white, red, green, blue, cyan, magenta, yellow, background;
+
+black := (0,0,0) ;
+white := (1,1,1) ;
+red := (1,0,0) ;
+green := (0,1,0) ;
+blue := (0,0,1) ;
+cyan := (0,1,1) ;
+magenta := (1,0,1) ;
+yellow := (1,1,0) ;
+
+background := white ; % obsolete
+
+let graypart = greypart ;
+let graycolor = greycolor ;
+
+% picture constants
+
+picture blankpicture, evenly, withdots ;
+
+blankpicture = nullpicture ; % display blankpicture...
+evenly = dashpattern(on 3 off 3) ; % dashed evenly
+withdots = dashpattern(off 2.5 on 0 off 2.5) ; % dashed withdots
+
+% string constants
+
+string ditto, EOF ;
+
+ditto = char 34 ; % ASCII double-quote mark
+EOF = char 0 ; % end-of-file for readfrom and write..to
+
+% pen constants
+
+pen pensquare, penrazor, penspeck ;
+
+pensquare = makepen(unitsquare shifted -(.5,.5)) ;
+penrazor = makepen((-.5,0) -- (.5,0) -- cycle) ;
+penspeck = pensquare scaled eps ;
+
+% nullary operators
+
+vardef whatever =
+ save ? ;
+ ?
+enddef ;
+
+% unary operators
+
+let abs = length ;
+
+vardef round primary u =
+ if numeric u :
+ floor(u+.5)
+ elseif pair u :
+ (round xpart u, round ypart u)
+ else :
+ u
+ fi
+enddef ;
+
+vardef ceiling primary x =
+ -floor(-x)
+enddef ;
+
+vardef byte primary s =
+ if string s :
+ ASCII
+ fi s
+enddef ;
+
+vardef dir primary d =
+ right rotated d
+enddef ;
+
+vardef unitvector primary z =
+ z/abs z
+enddef ;
+
+vardef inverse primary T =
+ transform T_ ;
+ T_ transformed T = identity ;
+ T_
+enddef ;
+
+vardef counterclockwise primary c =
+ if turningnumber c <= 0 :
+ reverse
+ fi c
+enddef ;
+
+vardef tensepath expr r =
+ for k=0 upto length r - 1 :
+ point k of r ---
+ endfor
+ if cycle r :
+ cycle
+ else :
+ point infinity of r
+ fi
+enddef ;
+
+vardef center primary p =
+ .5[llcorner p, urcorner p]
+enddef ;
+
+% binary operators
+
+primarydef x mod y =
+ (x-y*floor(x/y))
+enddef ;
+
+primarydef x div y =
+ floor(x/y)
+enddef ;
+
+primarydef w dotprod z =
+ (xpart w * xpart z + ypart w * ypart z)
+enddef ;
+
+primarydef x**y =
+ if y=2 :
+ x*x
+ else :
+ takepower y of x
+ fi
+enddef ;
+
+def takepower expr y of x =
+ if x>0 :
+ mexp(y*mlog x)
+ elseif (x=0) and (y>0) :
+ 0
+ else :
+ 1
+ if y = floor y :
+ if y >= 0 :
+ for n=1 upto y :
+ *x
+ endfor
+ else :
+ for n=-1 downto y :
+ /x
+ endfor
+ fi
+ else :
+ hide(errmessage "Undefined power: " & decimal x&"**"&decimal y)
+ fi
+ fi
+enddef ;
+
+vardef direction expr t of p =
+ postcontrol t of p - precontrol t of p
+enddef ;
+
+vardef directionpoint expr z of p =
+ a_ := directiontime z of p ;
+ if a_ < 0 :
+ errmessage("The direction doesn't occur") ;
+ fi
+ point a_ of p
+enddef ;
+
+secondarydef p intersectionpoint q =
+ begingroup
+ save x_, y_ ;
+ (x_,y_) = p intersectiontimes q ;
+ if x_ < 0 :
+ errmessage("The paths don't intersect") ;
+ origin
+ else :
+ .5[point x_ of p, point y_ of q]
+ fi
+ endgroup
+enddef ;
+
+tertiarydef p softjoin q =
+ begingroup
+ c_ := fullcircle scaled 2join_radius shifted point 0 of q ;
+ a_ := ypart(c_ intersectiontimes p) ;
+ b_ := ypart(c_ intersectiontimes q) ;
+ if a_ < 0 :
+ point 0 of p{direction 0 of p}
+ else :
+ subpath(0,a_) of p
+ fi
+ ...
+ if b_ < 0 :
+ {direction infinity of q} point infinity of q
+ else :
+ subpath(b_,infinity) of q
+ fi
+ endgroup
+enddef ;
+
+newinternal join_radius, a_, b_ ; path c_ ;
+
+path cuttings ; % what got cut off
+
+tertiarydef a cutbefore b = % tries to cut as little as possible
+ begingroup
+ save t ;
+ (t, whatever) = a intersectiontimes b ;
+ if t < 0 :
+ cuttings := point 0 of a ;
+ a
+ else :
+ cuttings := subpath (0,t) of a ;
+ subpath (t,length a) of a
+ fi
+ endgroup
+enddef ;
+
+tertiarydef a cutafter b =
+ reverse (reverse a cutbefore b)
+ hide(cuttings := reverse cuttings)
+enddef ;
+
+% special operators
+
+vardef incr suffix $ = $:=$+1; $ enddef ;
+vardef decr suffix $ = $:=$-1; $ enddef ;
+
+def reflectedabout(expr w,z) = % reflects about the line w..z
+ transformed
+ begingroup
+ transform T_ ;
+ w transformed T_ = w ;
+ z transformed T_ = z ;
+ xxpart T_ = -yypart T_ ;
+ xypart T_ = yxpart T_ ; % T_ is a reflection
+ T_
+ endgroup
+enddef ;
+
+def rotatedaround(expr z, d) = % rotates d degrees around z
+ shifted -z rotated d shifted z
+enddef ;
+
+let rotatedabout = rotatedaround ; % for roundabout people
+
+vardef min(expr u)(text t) = % t is a list of numerics, pairs, or strings
+ save u_ ;
+ setu_ u ;
+ for uu = t :
+ if uu < u_ :
+ u_ := uu ;
+ fi
+ endfor
+ u_
+enddef ;
+
+vardef max(expr u)(text t) = % t is a list of numerics, pairs, or strings
+ save u_ ;
+ setu_ u ;
+ for uu = t :
+ if uu > u_ :
+ u_ := uu ;
+ fi
+ endfor
+ u_
+enddef ;
+
+def setu_ primary u =
+ if pair u :
+ pair u_
+ elseif string u :
+ string u_
+ fi ;
+ u_=u
+enddef ;
+
+def flex(text t) = % t is a list of pairs
+ hide (
+ n_ := 0 ;
+ for z=t :
+ z_[incr n_] := z ;
+ endfor
+ dz_ := z_[n_]-z_1
+ )
+ z_1 for k=2 upto n_-1 :
+ ... z_[k]{dz_}
+ endfor ... z_[n_]
+enddef ;
+
+newinternal n_; pair z_[],dz_;
+
+def superellipse(expr r,t,l,b,s) =
+ r { up } ... (s[xpart t,xpart r],s[ypart r,ypart t]) { t-r } ...
+ t { left } ... (s[xpart t,xpart l],s[ypart l,ypart t]) { l-t } ...
+ l { down } ... (s[xpart b,xpart l],s[ypart l,ypart b]) { b-l } ...
+ b { right } ... (s[xpart b,xpart r],s[ypart r,ypart b]) { r-b } ... cycle enddef ;
+
+vardef interpath(expr a,p,q) =
+ for t=0 upto length p-1 :
+ a[point t of p, point t of q] .. controls a[postcontrol t of p, postcontrol t of q] and a[precontrol t+1 of p, precontrol t+1 of q] ..
+ endfor
+ if cycle p :
+ cycle
+ else :
+ a[point infinity of p, point infinity of q]
+ fi
+enddef ;
+
+vardef solve@#(expr true_x,false_x)= % @#(true_x)=true, @#(false_x)=false
+ tx_:=true_x; fx_:=false_x;
+ forever :
+ x_ := .5[tx_,fx_] ;
+ exitif abs(tx_-fx_) <= tolerance ;
+ if @#(x_) :
+ tx_
+ else :
+ fx_
+ fi := x_ ;
+ endfor
+ x_ % now x_ is near where @# changes from true to false
+enddef ;
+
+newinternal tolerance, tx_, fx_, x_ ;
+
+tolerance := .01 ;
+
+vardef buildcycle(text ll) =
+ save ta_, tb_, k_, i_, pp_ ; path pp_[] ;
+ k_ = 0 ;
+ for q=ll :
+ pp_[incr k_] = q ;
+ endfor
+ i_ = k_ ;
+ for i=1 upto k_ :
+ (ta_[i], length pp_[i_]-tb_[i_]) = pp_[i] intersectiontimes reverse pp_[i_] ;
+ if ta_[i]<0 :
+ errmessage("Paths "& decimal i &" and "& decimal i_ &" don't intersect") ;
+ fi
+ i_ := i;
+ endfor
+ for i=1 upto k_ :
+ subpath (ta_[i],tb_[i]) of pp_[i] ..
+ endfor
+ cycle
+enddef ;
+
+%% units of measure
+
+mm := 2.83464 ;
+pt := 0.99626 ;
+dd := 1.06601 ;
+bp := 1 ;
+cm := 28.34645 ;
+pc := 11.95517 ;
+cc := 12.79213 ;
+in := 72 ;
+
+vardef magstep primary m = % obsolete
+ mexp(46.67432m)
+enddef ;
+
+%% macros for drawing and filling
+
+def drawoptions(text t) =
+ def _op_ = t enddef
+enddef ;
+
+% parameters that effect drawing
+
+linejoin := rounded ;
+linecap := rounded ;
+miterlimit := 10 ;
+
+drawoptions() ;
+
+pen currentpen ;
+picture currentpicture ;
+
+def fill expr c =
+ addto currentpicture contour c _op_
+enddef ;
+
+def draw expr p =
+ addto currentpicture
+ if picture p :
+ also p
+ else :
+ doublepath p withpen currentpen
+ fi
+ _op_
+enddef ;
+
+def filldraw expr c =
+ addto currentpicture contour c withpen currentpen _op_
+enddef ;
+
+def drawdot expr z =
+ addto currentpicture contour makepath currentpen shifted z _op_
+enddef ;
+
+def unfill expr c = fill c withcolor background enddef ;
+def undraw expr p = draw p withcolor background enddef ;
+def unfilldraw expr c = filldraw c withcolor background enddef ;
+def undrawdot expr z = drawdot z withcolor background enddef ;
+
+def erase text t =
+ def _e_ =
+ withcolor background hide(def _e_ = enddef ;)
+ enddef ;
+ t _e_
+enddef ;
+
+def _e_ = enddef ;
+
+def cutdraw text t =
+ begingroup
+ interim linecap := butt ;
+ draw t _e_ ;
+ endgroup
+enddef ;
+
+vardef image(text t) =
+ save currentpicture ;
+ picture currentpicture ;
+ currentpicture := nullpicture ;
+ t ;
+ currentpicture
+enddef ;
+
+def pickup secondary q =
+ if numeric q :
+ numeric_pickup_
+ else :
+ pen_pickup_
+ fi q
+enddef ;
+
+def numeric_pickup_ primary q =
+ if unknown pen_[q] :
+ errmessage "Unknown pen" ;
+ clearpen
+ else :
+ currentpen := pen_ [q] ;
+ pen_lft := pen_lft_[q] ;
+ pen_rt := pen_rt_ [q] ;
+ pen_top := pen_top_[q] ;
+ pen_bot := pen_bot_[q] ;
+ currentpen_path := pen_path_[q]
+ fi ;
+enddef ;
+
+def pen_pickup_ primary q =
+ currentpen := q ;
+ pen_lft :=xpart penoffset down of currentpen ;
+ pen_rt :=xpart penoffset up of currentpen ;
+ pen_top :=ypart penoffset left of currentpen ;
+ pen_bot :=ypart penoffset right of currentpen ;
+ path currentpen_path ;
+enddef ;
+
+newinternal pen_lft, pen_rt, pen_top, pen_bot, pen_count_ ;
+
+vardef savepen =
+ pen_[incr pen_count_] = currentpen ;
+ pen_lft_ [pen_count_] = pen_lft ;
+ pen_rt_ [pen_count_] = pen_rt ;
+ pen_top_ [pen_count_] = pen_top ;
+ pen_bot_ [pen_count_] = pen_bot ;
+ pen_path_[pen_count_] = currentpen_path ;
+ pen_count_
+enddef ;
+
+def clearpen = currentpen:=nullpen;
+ pen_lft := pen_rt := pen_top := pen_bot := 0 ;
+ path currentpen_path ;
+enddef ;
+
+def clear_pen_memory =
+ pen_count_ := 0 ;
+ numeric pen_lft_[], pen_rt_[], pen_top_[], pen_bot_[] ;
+ pen currentpen, pen_[];
+ path currentpen_path, pen_path_[] ;
+enddef ;
+
+vardef lft primary x = x + if pair x: (pen_lft,0) else: pen_lft fi enddef ;
+vardef rt primary x = x + if pair x: (pen_rt,0) else: pen_rt fi enddef ;
+vardef top primary y = y + if pair y: (0,pen_top) else: pen_top fi enddef ;
+vardef bot primary y = y + if pair y: (0,pen_bot) else: pen_bot fi enddef ;
+
+vardef penpos@#(expr b,d) =
+ (x@#r-x@#l,y@#r-y@#l) = (b,0) rotated d ;
+ x@# = .5(x@#l+x@#r) ;
+ y@# = .5(y@#l+y@#r) ; % ; added HH
+enddef ;
+
+path path_.l, path_.r ;
+
+def penstroke text t =
+ forsuffixes e = l, r :
+ path_.e := t ;
+ endfor
+ fill path_.l -- reverse path_.r -- cycle
+enddef ;
+
+%% High level drawing commands
+
+newinternal ahlength, ahangle ;
+
+ahlength := 4 ; % default arrowhead length 4bp
+ahangle := 45 ; % default head angle 45 degrees
+
+vardef arrowhead expr p =
+ save q, e ; path q ; pair e ;
+ e = point length p of p ;
+ q = gobble(p shifted -e cutafter makepath(pencircle scaled 2ahlength)) cuttings ;
+ (q rotated .5ahangle & reverse q rotated -.5ahangle -- cycle) shifted e
+enddef ;
+
+path _apth ;
+
+def drawarrow expr p = _apth := p ; _finarr enddef ;
+def drawdblarrow expr p = _apth := p ; _findarr enddef ;
+
+def _finarr text t =
+ draw _apth t ;
+ filldraw arrowhead _apth t
+enddef ;
+
+def _findarr text t =
+ draw _apth t ;
+ fill arrowhead _apth withpen currentpen t ;
+ fill arrowhead reverse _apth withpen currentpen t ; % ; added HH
+enddef ;
+
+%% macros for labels
+
+newinternal bboxmargin ;
+
+bboxmargin := 2bp ; % this can bite you
+
+vardef bbox primary p =
+ llcorner p - ( bboxmargin, bboxmargin) --
+ lrcorner p + ( bboxmargin,-bboxmargin) --
+ urcorner p + ( bboxmargin, bboxmargin) --
+ ulcorner p + (-bboxmargin, bboxmargin) -- cycle
+enddef ;
+
+string defaultfont ; newinternal defaultscale, labeloffset ;
+
+defaultfont := "cmr10" ;
+defaultscale := 1 ;
+labeloffset := 3bp ;
+
+vardef thelabel@#(expr s,z) = % Position s near z
+ save p ; picture p ;
+ if picture s :
+ p = s
+ else :
+ p = s infont defaultfont scaled defaultscale
+ fi ;
+ p shifted (z + labeloffset*laboff@# - ( labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p) )
+enddef ;
+
+def label =
+ draw thelabel
+enddef ;
+
+newinternal dotlabeldiam ;
+
+dotlabeldiam := 3bp ;
+
+vardef dotlabel@#(expr s,z) text t_ =
+ label@#(s,z) t_ ;
+ % label@#(s,z) ;
+ interim linecap := rounded ;
+ draw z withpen pencircle scaled dotlabeldiam t_ ;
+enddef ;
+
+def makelabel =
+ dotlabel
+enddef ;
+
+% this will be overloaded
+
+pair laboff, laboff.lft, laboff.rt, laboff.top, laboff.bot ;
+pair laboff.ulft, laboff.llft, laboff.urt, laboff.lrt ;
+
+laboff = (0,0) ; labxf = .5 ; labyf = .5 ;
+laboff.lft = (-1,0) ; labxf.lft = 1 ; labyf.lft = .5 ;
+laboff.rt = (1,0) ; labxf.rt = 0 ; labyf.rt = .5 ;
+laboff.bot = (0,-1) ; labxf.bot = .5 ; labyf.bot = 1 ;
+laboff.top = (0,1) ; labxf.top = .5 ; labyf.top = 0 ;
+laboff.ulft = (-.7,.7) ; labxf.ulft = 1 ; labyf.ulft = 0 ;
+laboff.urt = (.7,.7) ; labxf.urt = 0 ; labyf.urt = 0 ;
+laboff.llft = -(.7,.7) ; labxf.llft = 1 ; labyf.llft = 1 ;
+laboff.lrt = (.7,-.7) ; labxf.lrt = 0 ; labyf.lrt = 1 ;
+
+vardef labels@#(text t) =
+ forsuffixes $=t :
+ label@#(str$,z$) ;
+ endfor
+enddef ;
+
+% til lhere
+
+vardef dotlabels@#(text t) =
+ forsuffixes $=t:
+ dotlabel@#(str$,z$) ;
+ endfor
+enddef ;
+
+vardef penlabels@#(text t) =
+ forsuffixes $$=l,,r :
+ forsuffixes $=t :
+ makelabel@#(str$.$$,z$.$$) ;
+ endfor
+ endfor
+enddef ;
+
+def range expr x =
+ numtok[x]
+enddef ;
+
+def numtok suffix x =
+ x
+enddef ;
+
+tertiarydef m thru n =
+ m for x=m+1 step 1 until n :
+ , numtok[x]
+ endfor
+enddef ;
+
+%% Overall administration
+
+string extra_beginfig, extra_endfig ;
+
+extra_beginfig := "" ;
+extra_endfig := "" ;
+
+def beginfig(expr c) =
+ begingroup
+ charcode := c ;
+ clearxy ;
+ clearit ;
+ clearpen ;
+ pickup defaultpen ;
+ drawoptions() ;
+ scantokens extra_beginfig ;
+enddef ;
+
+def endfig =
+ ; % added by HH
+ scantokens extra_endfig ;
+ shipit ;
+ endgroup
+enddef ;
+
+%% last-minute items
+
+vardef z@# =
+ (x@#,y@#)
+enddef ;
+
+def clearxy =
+ save x, y
+enddef ;
+
+def clearit =
+ currentpicture := nullpicture
+enddef ;
+
+def shipit =
+ shipout currentpicture
+enddef ;
+
+let bye = end ;
+outer end, bye ;
+
+clear_pen_memory ; % initialize the savepen mechanism
+clearit ;
+
+% set default line width
+
+newinternal defaultpen ;
+
+pickup pencircle scaled .5bp ;
+
+defaultpen := savepen ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-butt.mp b/Master/texmf-dist/metapost/context/base/mp-butt.mp
deleted file mode 100644
index cf580211e59..00000000000
--- a/Master/texmf-dist/metapost/context/base/mp-butt.mp
+++ /dev/null
@@ -1,75 +0,0 @@
-%D \module
-%D [ file=mp-butt.mp,
-%D version=2000.05.31,
-%D title=\CONTEXT\ \METAPOST\ graphics,
-%D subtitle=buttons,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
-%C details.
-
-if unknown context_tool : input mp-tool ; fi ;
-if known context_butt : endinput ; fi ;
-
-boolean context_butt ; context_butt := true ;
-
-def some_button (expr button_type ,
- button_size ,
- button_linecolor ,
- button_fillcolor ) =
-
- numeric button_linewidth ; button_linewidth := button_size/10 ;
-
- drawoptions (withpen pencircle scaled button_linewidth
- withcolor button_linecolor) ;
-
- path p ; p := unitsquare scaled button_size ;
- numeric d ; d := button_size ;
- numeric l ; l := button_linewidth ;
-
- fill p withcolor button_fillcolor ; draw p ;
-
- if button_type=101 :
- draw (d-2l,2l)--(2l,.5d)--(d-2l,d-2l)--cycle ;
- elseif button_type=102 :
- draw (2l,2l)--(d-2l,.5d)--(2l,d-2l)--cycle ;
- elseif button_type=103 :
- for i=2l step 2l until d-2l :
- draw (2l,i)--(2l ,i) ;
- draw (4l,i)--(d-2l,i) ;
- endfor ;
- elseif button_type=104 :
- for i=2l step 2l until d-2l :
- draw (2l ,i)--(d/2-l,i) ;
- draw (d/2+l,i)--(d-2l ,i) ;
- endfor ;
- elseif button_type=105 :
- fill fullcircle scaled (.2d) shifted (.5d,.7d) ;
- fill fullcircle xscaled (.6d) yscaled d shifted (.5d,0) ;
- clip currentpicture to p ;
- draw p ;
- elseif button_type=106 :
- draw (2l,2l)--(d-2l,d-2l) ;
- draw (d-2l,2l)--(2l,d-2l) ;
- elseif button_type=107 :
- p := (3l,d-2l)--(d-3l,d-2l)--(.5d,4l)--cycle ;
- fill p ; draw p ;
- draw (.5d,2l) ;
- elseif button_type=108 :
- draw (.5d,2l)--(d-2l,d-2l)--(2l,d-2l)--cycle ;
- elseif button_type=109 :
- draw (.5d,d-2l)--(d-2l,2l)--(2l,2l)--cycle ;
- elseif button_type=110 :
- button_linewidth := button_linewidth/2 ;
- draw p enlarged (-2l,-l) ;
- for i=2l step l until d-2l :
- draw (3l,i)--(d-3l,i) ;
- endfor ;
- fi ;
-
-enddef ;
-
-endinput ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-butt.mpii b/Master/texmf-dist/metapost/context/base/mp-butt.mpii
new file mode 100644
index 00000000000..5c1edd42ebb
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-butt.mpii
@@ -0,0 +1,77 @@
+%D \module
+%D [ file=mp-butt.mp,
+%D version=2000.05.31,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=buttons,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if known context_butt : endinput ; fi ;
+
+boolean context_butt ; context_butt := true ;
+
+def predefinedbutton (expr button_type, button_size, button_linecolor, button_fillcolor) =
+
+ begingroup ;
+
+ save button_linewidth, p, d, l ;
+
+ numeric button_linewidth ; button_linewidth := button_size/10 ;
+
+ drawoptions (withpen pencircle scaled button_linewidth withcolor button_linecolor) ;
+
+ path p ; p := unitsquare scaled button_size ;
+ numeric d ; d := button_size ;
+ numeric l ; l := button_linewidth ;
+
+ fill p withcolor button_fillcolor ;
+ draw p ;
+
+ if button_type = 101 :
+ draw (d-2l,2l)--(2l,.5d)--(d-2l,d-2l)--cycle ;
+ elseif button_type = 102 :
+ draw (2l,2l)--(d-2l,.5d)--(2l,d-2l)--cycle ;
+ elseif button_type = 103 :
+ for i=2l step 2l until d-2l :
+ draw (2l,i)--(2l ,i) ;
+ draw (4l,i)--(d-2l,i) ;
+ endfor ;
+ elseif button_type = 104 :
+ for i=2l step 2l until d-2l :
+ draw (2l ,i)--(d/2-l,i) ;
+ draw (d/2+l,i)--(d-2l ,i) ;
+ endfor ;
+ elseif button_type = 105 :
+ fill fullcircle scaled (.2d) shifted (.5d,.7d) ;
+ fill fullcircle xscaled (.6d) yscaled d shifted (.5d,0) ;
+ clip currentpicture to p ;
+ draw p ;
+ elseif button_type = 106 :
+ draw (2l,2l)--(d-2l,d-2l) ;
+ draw (d-2l,2l)--(2l,d-2l) ;
+ elseif button_type = 107 :
+ p := (3l,d-2l)--(d-3l,d-2l)--(.5d,4l)--cycle ;
+ fill p ; draw p ;
+ draw (.5d,2l) ;
+ elseif button_type = 108 :
+ draw (.5d,2l)--(d-2l,d-2l)--(2l,d-2l)--cycle ;
+ elseif button_type = 109 :
+ draw (.5d,d-2l)--(d-2l,2l)--(2l,2l)--cycle ;
+ elseif button_type = 110 :
+ button_linewidth := button_linewidth/2 ;
+ draw p enlarged (-2l,-l) ;
+ for i=2l step l until d-2l :
+ draw (3l,i)--(d-3l,i) ;
+ endfor ;
+ fi ;
+
+ endgroup ;
+
+enddef ;
+
+let some_button = predefinedbutton
diff --git a/Master/texmf-dist/metapost/context/base/mp-butt.mpiv b/Master/texmf-dist/metapost/context/base/mp-butt.mpiv
new file mode 100644
index 00000000000..5c1edd42ebb
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-butt.mpiv
@@ -0,0 +1,77 @@
+%D \module
+%D [ file=mp-butt.mp,
+%D version=2000.05.31,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=buttons,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if known context_butt : endinput ; fi ;
+
+boolean context_butt ; context_butt := true ;
+
+def predefinedbutton (expr button_type, button_size, button_linecolor, button_fillcolor) =
+
+ begingroup ;
+
+ save button_linewidth, p, d, l ;
+
+ numeric button_linewidth ; button_linewidth := button_size/10 ;
+
+ drawoptions (withpen pencircle scaled button_linewidth withcolor button_linecolor) ;
+
+ path p ; p := unitsquare scaled button_size ;
+ numeric d ; d := button_size ;
+ numeric l ; l := button_linewidth ;
+
+ fill p withcolor button_fillcolor ;
+ draw p ;
+
+ if button_type = 101 :
+ draw (d-2l,2l)--(2l,.5d)--(d-2l,d-2l)--cycle ;
+ elseif button_type = 102 :
+ draw (2l,2l)--(d-2l,.5d)--(2l,d-2l)--cycle ;
+ elseif button_type = 103 :
+ for i=2l step 2l until d-2l :
+ draw (2l,i)--(2l ,i) ;
+ draw (4l,i)--(d-2l,i) ;
+ endfor ;
+ elseif button_type = 104 :
+ for i=2l step 2l until d-2l :
+ draw (2l ,i)--(d/2-l,i) ;
+ draw (d/2+l,i)--(d-2l ,i) ;
+ endfor ;
+ elseif button_type = 105 :
+ fill fullcircle scaled (.2d) shifted (.5d,.7d) ;
+ fill fullcircle xscaled (.6d) yscaled d shifted (.5d,0) ;
+ clip currentpicture to p ;
+ draw p ;
+ elseif button_type = 106 :
+ draw (2l,2l)--(d-2l,d-2l) ;
+ draw (d-2l,2l)--(2l,d-2l) ;
+ elseif button_type = 107 :
+ p := (3l,d-2l)--(d-3l,d-2l)--(.5d,4l)--cycle ;
+ fill p ; draw p ;
+ draw (.5d,2l) ;
+ elseif button_type = 108 :
+ draw (.5d,2l)--(d-2l,d-2l)--(2l,d-2l)--cycle ;
+ elseif button_type = 109 :
+ draw (.5d,d-2l)--(d-2l,2l)--(2l,2l)--cycle ;
+ elseif button_type = 110 :
+ button_linewidth := button_linewidth/2 ;
+ draw p enlarged (-2l,-l) ;
+ for i=2l step l until d-2l :
+ draw (3l,i)--(d-3l,i) ;
+ endfor ;
+ fi ;
+
+ endgroup ;
+
+enddef ;
+
+let some_button = predefinedbutton
diff --git a/Master/texmf-dist/metapost/context/base/mp-char.mp b/Master/texmf-dist/metapost/context/base/mp-char.mpii
index 786c1f904d2..5e7a31c5073 100644
--- a/Master/texmf-dist/metapost/context/base/mp-char.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-char.mpii
@@ -13,9 +13,8 @@
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
%C details.
-if unknown context_tool : input mp-tool ; fi ;
-if unknown context_shap : input mp-shap ; fi ;
-if known context_char : endinput ; fi ;
+if unknown context_shap : input "mp-shap.mpii" ; fi ;
+if known context_flow : endinput ; fi ;
boolean context_char ; context_char := true ;
@@ -37,7 +36,6 @@ grid_width := 60pt ; grid_height := 40pt ;
shape_width := 45pt ; shape_height := 30pt ;
chart_offset := 2pt ;
-
color chart_background_color ; chart_background_color := white ;
%D test mode
@@ -112,6 +110,7 @@ def new_chart =
color xydraw [][] ;
numeric xyline [][] ;
boolean xypeep [][] ;
+ picture xypicture[][] ;
numeric cpath ; cpath := 0 ;
path cpaths [] ;
@@ -234,6 +233,15 @@ def flush_shapes =
endfor ;
enddef ;
+def flush_pictures =
+ for x=1 upto max_x :
+ for y=1 upto max_y :
+ flush_picture (x, y) ;
+ endfor ;
+ endfor ;
+enddef ;
+
+
def draw_connection_point (expr x, y, z) =
pickup pencircle scaled if (z=0): 2 fi xyline[x][y] ;
drawdot xy_bottom(x,y,z,false) scaled_to_grid withcolor (1,0,0) ;
@@ -276,7 +284,7 @@ vardef points_initialized (expr xfrom, yfrom, xto, yto, n) =
fi
enddef ;
-def collapse_points = % this is now an mp-tool macro
+def collapse_points =
% remove redundant points
n := 1 ;
for i=2 upto xypoint:
@@ -451,6 +459,16 @@ def draw_midpoint (expr n) =
endgroup ;
enddef ;
+def flush_picture(expr x, y) =
+ if known xypicture[x][y]:
+ draw xypicture[x][y] shifted xy_offset((x+0.5)*grid_width,(max_y-y+1.5)*grid_height) ;
+ fi ;
+enddef ;
+
+def chart_draw_picture(expr x, y, p) =
+ xypicture[x][y] := p ;
+enddef ;
+
boolean reverse_connection ; reverse_connection := false ;
vardef up_on_grid (expr n) =
@@ -912,6 +930,7 @@ enddef ;
def end_chart =
flush_shapes ;
flush_connections ;
+ flush_pictures ;
cmin_x := cmin_x ;
cmax_x := cmin_x+cmax_x ;
cmin_y := cmin_y-1 ;
@@ -972,28 +991,16 @@ def end_sub_chart =
endgroup ;
enddef ;
-%D done
-
-endinput ;
-
-%D testing
-
-show_shapes(100) ;
-
-end
-
-%D more testing
-
-show_connections ;
-
-begin_chart (1,4,5) ;
- %clip_chart(1,1,1,2) ;
- new_shape (1,1,31) ;
- new_shape (1,2,3) ;
- new_shape (4,4,5) ;
- connect_top_left (1,1,0) (4,4,0) ;
- connect_bottom_top (1,2,0) (4,4,0) ;
- connect_left_right (1,2,0) (1,1,0) ;
-end_chart ;
-
-end
+% show_shapes(100) ;
+%
+% show_connections ;
+%
+% begin_chart (1,4,5) ;
+% %clip_chart(1,1,1,2) ;
+% new_shape (1,1,31) ;
+% new_shape (1,2,3) ;
+% new_shape (4,4,5) ;
+% connect_top_left (1,1,0) (4,4,0) ;
+% connect_bottom_top (1,2,0) (4,4,0) ;
+% connect_left_right (1,2,0) (1,1,0) ;
+% end_chart ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-char.mpiv b/Master/texmf-dist/metapost/context/base/mp-char.mpiv
new file mode 100644
index 00000000000..28fe4151246
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-char.mpiv
@@ -0,0 +1,1116 @@
+%D \module
+%D [ file=mp-char.mp,
+%D version=2011.10.1, % 1998.10.10,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=charts,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D This is ancient code .. but I see no need to rewrite it. This is
+%D already a partial rewrite but more could be delegated to \LUA\
+%D when used in \CONTEXT\ but it does not pay off now to look into
+%D that.
+
+%D For historic reason we first build and then flush but we could
+%D as well flush directly which would save us caching.
+
+if unknown context_shap : input "mp-shap.mpiv" ; fi ;
+if known context_flow : endinput ; fi ;
+
+boolean context_flow ; context_flow := true ;
+
+%D settings
+
+numeric flow_grid_width ; flow_grid_width := 60pt ;
+numeric flow_shape_width ; flow_shape_width := 45pt ;
+numeric flow_grid_height ; flow_grid_height := 40pt ;
+numeric flow_shape_height ; flow_shape_height := 30pt ;
+numeric flow_chart_offset ; flow_chart_offset := 2pt ;
+color flow_chart_background_color ; flow_chart_background_color := white ;
+boolean flow_show_mid_points ; flow_show_mid_points := false ;
+boolean flow_show_con_points ; flow_show_con_points := false ;
+boolean flow_show_all_points ; flow_show_all_points := false ;
+numeric flow_shape_line_width ; flow_shape_line_width := 2pt ;
+color flow_shape_line_color ; flow_shape_line_color := .5white ;
+color flow_shape_fill_color ; flow_shape_fill_color := .9white ;
+color flow_connection_line_color ; flow_connection_line_color := .2white ;
+
+numeric flow_connection_line_width ; flow_connection_line_width := flow_shape_line_width ;
+
+numeric flow_connection_smooth_size ; flow_connection_smooth_size := 5pt ;
+numeric flow_connection_arrow_size ; flow_connection_arrow_size := 4pt ;
+numeric flow_connection_dash_size ; flow_connection_dash_size := 3pt ;
+
+numeric flow_max_x ; flow_max_x := 6 ;
+numeric flow_max_y ; flow_max_y := 4 ;
+
+boolean flow_smooth ; flow_smooth := true ;
+boolean flow_peepshape ; flow_peepshape := false ;
+boolean flow_arrowtip ; flow_arrowtip := true ;
+boolean flow_dashline ; flow_dashline := false ;
+boolean flow_forcevalid ; flow_forcevalid := false ;
+boolean flow_touchshape ; flow_touchshape := false ;
+boolean flow_showcrossing ; flow_showcrossing := false ;
+boolean flow_reverse_y ; flow_reverse_y := true ;
+
+picture flow_dash_pattern ; flow_dash_pattern := nullpicture ;
+
+numeric flow_shape_node ; flow_shape_node := 0 ;
+numeric flow_shape_action ; flow_shape_action := 24 ;
+numeric flow_shape_procedure ; flow_shape_procedure := 5 ;
+numeric flow_shape_product ; flow_shape_product := 12 ;
+numeric flow_shape_decision ; flow_shape_decision := 14 ;
+numeric flow_shape_archive ; flow_shape_archive := 19 ;
+numeric flow_shape_loop ; flow_shape_loop := 35 ;
+numeric flow_shape_wait ; flow_shape_wait := 6 ;
+numeric flow_shape_subprocedure ; flow_shape_subprocedure := 20 ;
+numeric flow_shape_singledocument ; flow_shape_singledocument := 32 ;
+numeric flow_shape_multidocument ; flow_shape_multidocument := 33 ;
+numeric flow_shape_right ; flow_shape_right := 66 ;
+numeric flow_shape_left ; flow_shape_left := 67 ;
+numeric flow_shape_up ; flow_shape_up := 68 ;
+numeric flow_shape_down ; flow_shape_down := 69 ;
+
+numeric flow_label_offset ; flow_label_offset := 0 ;
+numeric flow_exit_offset ; flow_exit_offset := 0 ;
+numeric flow_comment_offset ; flow_comment_offset := 0 ;
+
+% vardef some_shape_path (expr type) == imported from mp-shap
+
+def flow_show_shapes(expr n) =
+ flow_begin_chart(n,8,10) ;
+ flow_show_con_points := true ;
+ for i=0 upto 7 :
+ for j=0 upto 9 :
+ flow_new_shape(i+1,j+1,i*10+j);
+ endfor ;
+ endfor ;
+ flow_end_chart ;
+enddef ;
+
+%D connections
+
+def flow_new_chart =
+
+ flow_grid_width := 60pt ;
+ flow_shape_width := 45pt ;
+ flow_grid_height := 40pt ;
+ flow_shape_height := 30pt ;
+ flow_chart_offset := 2pt ;
+ flow_chart_background_color := white ;
+ flow_show_mid_points := false ;
+ flow_show_con_points := false ;
+ flow_show_all_points := false ;
+ flow_shape_line_width := 2pt ;
+ flow_shape_line_color := .5white ;
+ flow_shape_fill_color := .9white ;
+ flow_connection_line_color := .2white ;
+ flow_connection_line_width := flow_shape_line_width ;
+ flow_connection_smooth_size := 5pt ;
+ flow_connection_arrow_size := 4pt ;
+ flow_connection_dash_size := 3pt ;
+ flow_label_offset := 0 ;
+ flow_exit_offset := 0 ;
+ flow_comment_offset := 0 ;
+
+ flow_max_x := 6 ;
+ flow_max_y := 4 ;
+
+ flow_smooth := true ;
+ flow_peepshape := false ;
+ flow_arrowtip := true ;
+ flow_dashline := false ;
+ flow_forcevalid := false ;
+ flow_touchshape := false ;
+ flow_showcrossing := false ;
+ flow_reverse_y := true ;
+
+ flow_dash_pattern := nullpicture ;
+
+ numeric flow_xypoint ; flow_xypoint := 0 ;
+ numeric flow_cpath ; flow_cpath := 0 ;
+
+ pair flow_xypoints [] ;
+ boolean flow_xyfree [][] ;
+ path flow_xypath [][] ;
+ numeric flow_xysx [][] ;
+ numeric flow_xysy [][] ;
+ color flow_xyfill [][] ;
+ color flow_xydraw [][] ;
+ numeric flow_xyline [][] ;
+ boolean flow_xypeep [][] ;
+ picture flow_xytext [][] ;
+ picture flow_xylabel [][] ;
+ picture flow_xyexit [][] ;
+ picture flow_xycomment [][] ;
+ path flow_cpaths [] ;
+ numeric flow_cline [] ;
+ color flow_ccolor [] ;
+ boolean flow_carrow [] ;
+ boolean flow_cdash [] ;
+ boolean flow_ccross [] ;
+ picture flow_tpicture [][] ;
+ picture flow_bpicture [][] ;
+ picture flow_lpicture [][] ;
+ picture flow_rpicture [][] ;
+ path flow_connections[][][] ;
+
+ predefined_shapes[61] := (fullcircle scaled (1.5*predefined_shapes_yradius) xscaled (flow_grid_height/flow_grid_width)) ;
+ predefined_shapes[62] := (fullcircle scaled (2.0*predefined_shapes_yradius) xscaled (flow_grid_height/flow_grid_width)) ;
+
+enddef ;
+
+flow_new_chart ;
+
+def flow_y_pos(expr y) =
+% if flow_reverse_y :
+ flow_max_y + 1 - y
+% else :
+% y
+% fi
+enddef ;
+
+def flow_initialize_grid(expr maxx, maxy) =
+ flow_max_x := maxx ;
+ flow_max_y := maxy ;
+ flow_dsp_x := 0 ;
+ flow_dsp_y := 0 ;
+ for x=1 upto flow_max_x :
+ for y=1 upto flow_max_y :
+ flow_xyfree[x][y] := true ;
+ flow_xyfill[x][y] := flow_shape_fill_color ;
+ flow_xydraw[x][y] := flow_shape_line_color ;
+ flow_xyline[x][y] := flow_shape_line_width ;
+ endfor ;
+ endfor ;
+enddef ;
+
+def flow_scaled_to_grid =
+ xscaled flow_grid_width yscaled flow_grid_height
+enddef ;
+
+def flow_xy_offset(expr x, y) =
+ (x+.5,y+.5)
+enddef ;
+
+def flow_draw_shape(expr x, yy, p, sx, sy) =
+ begingroup ;
+ save y ; numeric y ;
+ y := flow_y_pos(yy) ;
+ flow_xypath [x][y] := (p xscaled sx yscaled sy) shifted flow_xy_offset(x,y) ;
+ flow_xyfree [x][y] := false ;
+ flow_xysx [x][y] := sx ;
+ flow_xysy [x][y] := sy ;
+ flow_xyfill [x][y] := flow_shape_fill_color ;
+ flow_xydraw [x][y] := flow_shape_line_color ;
+ flow_xyline [x][y] := flow_shape_line_width ;
+ flow_xypeep [x][y] := flow_peepshape ;
+ endgroup ;
+enddef ;
+
+vardef flow_i_point (expr x, y, p, t) =
+ begingroup ;
+ save q, ok ; pair q ; boolean ok ;
+ q := flow_xypath[x][y] intersection_point ((p) shifted flow_xy_offset(x,y)) ;
+ ok := true ;
+ if not ok :
+ message (t & " of shape (" & decimal x & "," & decimal y & ") limited") ;
+ fi ;
+ q
+ endgroup
+enddef ;
+
+vardef flow_trimmed (expr x, y, z, t) =
+ if flow_touchshape and t :
+ flow_xyline[x][y]/z
+ else :
+ epsilon
+ fi
+enddef ;
+
+numeric flow_zfactor ; flow_zfactor := 1/3 ;
+
+vardef flow_xy_bottom (expr x, y, z, t) =
+ flow_i_point(x, y, ((0,0)--(0,-2)) shifted (flow_zfactor*z*flow_xysx[x][y],0), "bottom")
+ shifted(0,-flow_trimmed(x,y,flow_grid_height,t))
+enddef ;
+
+vardef flow_xy_top (expr x, y, z, t) =
+ flow_i_point (x, y, ((0,0)--(0,2)) shifted (flow_zfactor*z*flow_xysx[x][y],0), "top")
+ shifted(0,flow_trimmed(x,y,flow_grid_height,t))
+enddef ;
+
+vardef flow_xy_left (expr x, y, z, t) =
+ flow_i_point (x, y, ((0,0)--(-2,0)) shifted (0,flow_zfactor*z*flow_xysy[x][y]), "left")
+ shifted(-flow_trimmed(x,y,flow_grid_width,t),0)
+enddef ;
+
+vardef flow_xy_right (expr x, y, z, t) =
+ flow_i_point (x, y, ((0,0)--(2,0)) shifted (0,flow_zfactor*z*flow_xysy[x][y]), "right")
+ shifted(flow_trimmed(x,y,flow_grid_width,t),0)
+enddef ;
+
+def flow_flush_shapes =
+ for x=1 upto flow_max_x :
+ for y=1 upto flow_max_y :
+ flow_flush_shape(x, y) ;
+ endfor ;
+ endfor ;
+enddef ;
+
+def flow_flush_pictures =
+ for x=1 upto flow_max_x :
+ for y=1 upto flow_max_y :
+ flow_flush_picture(x, y) ;
+ endfor ;
+ endfor ;
+enddef ;
+
+def flow_draw_connection_point(expr x, y, z) =
+ pickup pencircle scaled if (z=0): 2 fi flow_xyline[x][y] ;
+ drawdot flow_xy_bottom(x,y,z,false) flow_scaled_to_grid withcolor (1,0,0) ;
+ drawdot flow_xy_top (x,y,z,false) flow_scaled_to_grid withcolor (0,1,0) ;
+ drawdot flow_xy_left (x,y,z,false) flow_scaled_to_grid withcolor (0,0,1) ;
+ drawdot flow_xy_right (x,y,z,false) flow_scaled_to_grid withcolor (1,1,0) ;
+enddef ;
+
+def flow_flush_shape(expr x, yy) =
+ begingroup ;
+ save y ; numeric y ;
+ y := flow_y_pos(yy) ;
+ if not flow_xyfree[x][y] :
+ pickup pencircle scaled flow_xyline[x][y] ;
+ if flow_xypeep[x][y] :
+ fill (flow_xypath[x][y] peepholed (unitsquare shifted (x,y)))
+ flow_scaled_to_grid withpen pencircle scaled 0
+ withcolor flow_chart_background_color ;
+ else :
+ fill flow_xypath[x][y] flow_scaled_to_grid withcolor flow_xyfill[x][y] ;
+ fi ;
+ draw flow_xypath[x][y] flow_scaled_to_grid withcolor flow_xydraw[x][y] ;
+ if flow_show_con_points or flow_show_all_points :
+ flow_draw_connection_point(x, y, 0) ;
+ fi ;
+ if flow_show_all_points :
+ for i=-1 upto 1 :
+ flow_draw_connection_point(x, y, i) ;
+ endfor ;
+ fi ;
+ fi ;
+ endgroup ;
+enddef ;
+
+vardef flow_points_initialized(expr xfrom, yfrom, xto, yto, n) =
+ if unknown flow_xyfree[xfrom][yfrom] or unknown flow_xyfree[xto][yto] :
+ flow_xypoint := 0 ; false
+ elseif not flow_xyfree[xfrom][yfrom] and not flow_xyfree[xto][yto] :
+ flow_xypoint := n ; true
+ else :
+ flow_xypoint := 0 ; false
+ fi
+enddef ;
+
+def flow_collapse_points = % this can become a core macro
+ begingroup ;
+ % remove redundant points
+ save n ; numeric n ;
+ n := 1 ;
+ for i=2 upto flow_xypoint :
+ if not (flow_xypoints[i] = flow_xypoints[n]) :
+ n := n + 1 ;
+ flow_xypoints[n] := flow_xypoints[i]
+ fi ;
+ endfor ;
+ flow_xypoint := n ;
+ % make straight lines
+ if flow_xypoints[2] = flow_xypoints[flow_xypoint-1] :
+ flow_xypoints[3] := flow_xypoints[flow_xypoint] ;
+ flow_xypoint := 3 ;
+ fi ;
+ endgroup ;
+enddef ;
+
+vardef flow_smooth_connection(expr a,b) =
+ if ypart a = ypart b :
+ a shifted ( if xpart a >= xpart b : - fi (flow_connection_smooth_size/flow_grid_width ),0)
+ else :
+ a shifted (0,if ypart a >= ypart b : - fi (flow_connection_smooth_size/flow_grid_height) )
+ fi
+enddef ;
+
+vardef flow_trim_points =
+ begingroup
+ save p, a, b, d, i ; numeric a, b ; path p ; pair d ;
+ p := for i=1 upto flow_xypoint-1 : flow_xypoints[i]-- endfor flow_xypoints[flow_xypoint] ;
+ if flow_touchshape :
+ a := flow_shape_line_width/flow_grid_width ;
+ b := flow_shape_line_width/flow_grid_height ;
+ else :
+ a := epsilon ;
+ b := epsilon ;
+ fi ;
+ d := direction infinity of p ;
+ flow_xypoints[flow_xypoint] := flow_xypoints[flow_xypoint] shifted
+ if xpart d < 0 : (+a,0) ;
+ elseif xpart d > 0 : (-a,0) ;
+ elseif ypart d < 0 : (0,+b) ;
+ elseif ypart d > 0 : (0,-b) ;
+ else : origin ;
+ fi ;
+ d := direction 0 of p ;
+ flow_xypoints[1] := flow_xypoints[1] shifted
+ if xpart d < 0 : (-a,0) ;
+ elseif xpart d > 0 : (+a,0) ;
+ elseif ypart d < 0 : (0,-b) ;
+ elseif ypart d > 0 : (0,+b) ;
+ else : origin ;
+ fi ;
+ endgroup
+enddef ;
+
+vardef flow_trim_points = enddef ;
+
+vardef flow_connection_path =
+ if flow_reverse_connection : reverse fi (flow_xypoints[1] --
+ for i=2 upto flow_xypoint-1 :
+ if flow_smooth :
+ flow_smooth_connection(flow_xypoints[i],flow_xypoints[i-1]) ..
+ controls flow_xypoints[i] and flow_xypoints[i] ..
+ flow_smooth_connection(flow_xypoints[i],flow_xypoints[i+1]) --
+ else :
+ flow_xypoints[i] --
+ fi
+ endfor
+ flow_xypoints[flow_xypoint])
+enddef ;
+
+def flow_draw_connection(expr i,xfrom,yfrom,xto,yto) = % 'i' is a comment reference
+ if flow_xypoint > 0 :
+ flow_collapse_points ;
+ flow_trim_points ;
+ flow_cpath := flow_cpath + 1 ; % maybe also store as x,y
+ flow_cpaths[flow_cpath] := flow_connection_path flow_scaled_to_grid ;
+ flow_cline[flow_cpath] := flow_connection_line_width ;
+ flow_ccolor[flow_cpath] := flow_connection_line_color ;
+ flow_carrow[flow_cpath] := flow_arrowtip ;
+ flow_cdash[flow_cpath] := flow_dashline ;
+ flow_ccross[flow_cpath] := flow_showcrossing ;
+ if flow_reverse_connection :
+ flow_connections[xto] [yto] [i] := flow_cpaths[flow_cpath] ;
+ else :
+ flow_connections[xfrom][yfrom][i] := flow_cpaths[flow_cpath] ;
+ fi ;
+ else :
+ message("no connection defined") ;
+ fi ;
+ flow_reverse_connection := false ;
+enddef ;
+
+def flow_flush_connections = % protect locals
+ begingroup ;
+ save ip, crossing, cp ; numeric ip ; boolean crossing ; path cp ;
+ ahlength := flow_connection_arrow_size ;
+ flow_dash_pattern := dashpattern(on flow_connection_dash_size off flow_connection_dash_size) ;
+ for i=1 upto flow_cpath :
+ if flow_ccross[i] :
+ crossing := false ;
+ for j=1 upto i :
+ if not (point infinity of flow_cpaths[i] = point infinity of flow_cpaths[j]) :
+ ip := flow_cpaths[i] intersection_point flow_cpaths[j] ;
+ if intersection_found : crossing := true fi ;
+ fi ;
+ endfor ;
+ if crossing :
+ pickup pencircle scaled 2flow_cline[i] ;
+ cp := flow_cpaths[i] ;
+ cp := cp cutbefore point .05 length cp of cp ;
+ cp := cp cutafter point .95 length cp of cp ;
+ draw cp withcolor flow_chart_background_color ;
+ fi ;
+ fi ;
+ pickup pencircle scaled flow_cline[i] ;
+ if flow_carrow[i] :
+ if flow_cdash[i] :
+ drawarrow flow_cpaths[i] withcolor flow_ccolor[i] dashed flow_dash_pattern ;
+ else :
+ drawarrow flow_cpaths[i] withcolor flow_ccolor[i] ;
+ fi ;
+ else :
+ if flow_cdash[i] :
+ draw flow_cpaths[i] withcolor flow_ccolor[i] dashed flow_dash_pattern ;
+ else :
+ draw flow_cpaths[i] withcolor flow_ccolor[i] ;
+ fi ;
+ fi ;
+ flow_draw_midpoint(i) ;
+ endfor ;
+ endgroup ;
+enddef ;
+
+def flow_draw_midpoint (expr n) =
+ begingroup
+ save p ; pair p ;
+ p := point .5*length(flow_cpaths[n]) of flow_cpaths[n];
+ pickup pencircle scaled 2flow_cline[n] ;
+ if flow_show_mid_points :
+ drawdot p withcolor .7white ;
+ fi ;
+ endgroup ;
+enddef ;
+
+def flow_flush_picture(expr x, yy) =
+ begingroup ;
+ save y ; numeric y ;
+ y := flow_y_pos(yy) ; % maybe move this to the makers
+ if known flow_xytext[x][y] :
+ draw flow_xytext[x][y] ;
+ fi ;
+ if known flow_xylabel[x][y] :
+ draw flow_xylabel[x][y] ;
+ fi ;
+ if known flow_xyexit[x][y] :
+ draw flow_xyexit[x][y] ;
+ fi ;
+ if known flow_xycomment[x][y] :
+ draw flow_xycomment[x][y] ;
+ fi ;
+ endgroup ;
+enddef ;
+
+vardef flow_offset(expr x, y) =
+ flow_xy_offset((x+0.5)*flow_grid_width,(flow_max_y-y+1.5)*flow_grid_height)
+ shifted (-flow_xyline[x][y]/4,-flow_xyline[x][y]/4) % terrible hack (some compensation)
+enddef ;
+
+def flow_chart_draw_text(expr x, y, p) =
+ if known flow_xytext[x][y] :
+ addto flow_xytext[x][y] also
+ else :
+ flow_xytext[x][y] :=
+ fi
+ p shifted flow_offset(x,y) ;
+enddef ;
+
+def flow_chart_draw_label (expr x, y, loc, txt) =
+ begingroup ;
+ save p, s ; path p ; picture s ;
+ p := fullsquare xscaled flow_grid_width yscaled flow_grid_height ;
+ p := p shifted flow_offset(x,y) ;
+ s := txt ;
+ setbounds s to boundingbox s enlarged flow_label_offset ;
+ if known flow_xylabel[x][y] :
+ addto flow_xylabel[x][y] also
+ else :
+ flow_xylabel[x][y] :=
+ fi
+ if loc = "tr" : anchored.llft(s,0.5[ulcorner p,urcorner p]) ;
+ elseif loc = "t" : anchored.bot (s,0.5[ulcorner p,urcorner p]) ;
+ elseif loc = "tl" : anchored.lrt (s,0.5[ulcorner p,urcorner p]) ;
+ elseif loc = "br" : anchored.ulft(s,0.5[llcorner p,lrcorner p]) ;
+ elseif loc = "b" : anchored.top (s,0.5[llcorner p,lrcorner p]) ;
+ elseif loc = "bl" : anchored.urt (s,0.5[llcorner p,lrcorner p]) ;
+ elseif loc = "lb" : anchored.urt (s,0.5[ulcorner p,llcorner p]) ;
+ elseif loc = "l" : anchored.rt (s,0.5[ulcorner p,llcorner p]) ;
+ elseif loc = "lt" : anchored.lrt (s,0.5[ulcorner p,llcorner p]) ;
+ elseif loc = "rb" : anchored.ulft(s,0.5[urcorner p,lrcorner p]) ;
+ elseif loc = "r" : anchored.lft (s,0.5[urcorner p,lrcorner p]) ;
+ elseif loc = "rt" : anchored.llft(s,0.5[urcorner p,lrcorner p]) ;
+ else : anchored (s,center p) ;
+ fi ;
+ endgroup ;
+enddef ;
+
+def flow_chart_draw_exit (expr x, y, loc, txt) =
+ begingroup ;
+ save p, s ; path p ; picture s ;
+ p := fullsquare xscaled flow_grid_width yscaled flow_grid_height ;
+ p := p shifted flow_offset(x,y) ;
+ s := txt ;
+ setbounds s to boundingbox s enlarged flow_exit_offset ;
+ if known flow_xyexit[x][y] :
+ addto flow_xyexit[x][y] also
+ else :
+ flow_xyexit[x][y] :=
+ fi
+ if loc = "t" : anchored.top(s,0.5[ulcorner p,urcorner p]) ;
+ elseif loc = "b" : anchored.bot(s,0.5[llcorner p,lrcorner p]) ;
+ elseif loc = "l" : anchored.lft(s,0.5[ulcorner p,llcorner p]) ;
+ elseif loc = "r" : anchored.rt (s,0.5[urcorner p,lrcorner p]) ;
+ else : anchored (s,center p) ;
+ fi ;
+ endgroup ;
+enddef ;
+
+def flow_chart_draw_comment (expr x, y, i, loc, len, txt) = % per connection
+ begingroup ;
+ if known flow_connections[x][y][i] :
+ save p, q, s ; path p, q ; picture s ;
+ p := fullsquare xscaled flow_shape_width yscaled flow_shape_height ;
+ p := p shifted flow_offset(x,y) ;
+ q := flow_connections[x][y][i] ; % already relocated
+ s := txt ;
+ setbounds s to boundingbox s enlarged flow_comment_offset ;
+ if known flow_xycomment[x][y] :
+ addto flow_xycomment[x][y] also
+ else :
+ flow_xycomment[x][y] :=
+ fi
+ if loc = "tr" : anchored.llft(s,if len = 0 : 0.5[ulcorner p,urcorner p] else : point len along q fi) ;
+ elseif loc = "t" : anchored.bot (s,if len = 0 : 0.5[ulcorner p,urcorner p] else : point len along q fi) ;
+ elseif loc = "tl" : anchored.lrt (s,if len = 0 : 0.5[ulcorner p,urcorner p] else : point len along q fi) ;
+ elseif loc = "br" : anchored.ulft(s,if len = 0 : 0.5[llcorner p,lrcorner p] else : point len along q fi) ;
+ elseif loc = "b" : anchored.top (s,if len = 0 : 0.5[llcorner p,lrcorner p] else : point len along q fi) ;
+ elseif loc = "bl" : anchored.urt (s,if len = 0 : 0.5[llcorner p,lrcorner p] else : point len along q fi) ;
+ elseif loc = "lb" : anchored.urt (s,if len = 0 : 0.5[ulcorner p,llcorner p] else : point len along q fi) ;
+ elseif loc = "l" : anchored.rt (s,if len = 0 : 0.5[ulcorner p,llcorner p] else : point len along q fi) ;
+ elseif loc = "lt" : anchored.lrt (s,if len = 0 : 0.5[ulcorner p,llcorner p] else : point len along q fi) ;
+ elseif loc = "rb" : anchored.ulft(s,if len = 0 : 0.5[urcorner p,lrcorner p] else : point len along q fi) ;
+ elseif loc = "r" : anchored.lft (s,if len = 0 : 0.5[urcorner p,lrcorner p] else : point len along q fi) ;
+ elseif loc = "rt" : anchored.llft(s,if len = 0 : 0.5[urcorner p,lrcorner p] else : point len along q fi) ;
+ elseif loc = "tr:*" : anchored.llft(s,point 0 of q) ;
+ elseif loc = "t:*" : anchored.bot (s,point 0 of q) ;
+ elseif loc = "tl:*" : anchored.lrt (s,point 0 of q) ;
+ elseif loc = "br:*" : anchored.ulft(s,point 0 of q) ;
+ elseif loc = "b:*" : anchored.top (s,point 0 of q) ;
+ elseif loc = "bl:*" : anchored.urt (s,point 0 of q) ;
+ elseif loc = "lb:*" : anchored.urt (s,point 0 of q) ;
+ elseif loc = "l:*" : anchored.rt (s,point 0 of q) ;
+ elseif loc = "lt:*" : anchored.lrt (s,point 0 of q) ;
+ elseif loc = "rb:*" : anchored.ulft(s,point 0 of q) ;
+ elseif loc = "r:*" : anchored.lft (s,point 0 of q) ;
+ elseif loc = "rt:*" : anchored.llft(s,point 0 of q) ;
+ else : anchored (s,point 0 of q) ;
+ fi ;
+ fi ;
+ endgroup ;
+enddef ;
+
+boolean flow_reverse_connection ; flow_reverse_connection := false ;
+
+vardef flow_up_on_grid (expr n) =
+ (xpart flow_xypoints[n],(ypart flow_xypoints[n]+1) div 1)
+enddef ;
+
+vardef flow_down_on_grid (expr n) =
+ (xpart flow_xypoints[n],(ypart flow_xypoints[n]) div 1)
+enddef ;
+
+vardef flow_left_on_grid (expr n) =
+ ((xpart flow_xypoints[n]) div 1, ypart flow_xypoints[n])
+enddef ;
+
+vardef flow_right_on_grid (expr n) =
+ ((xpart flow_xypoints[n]+1) div 1, ypart flow_xypoints[n])
+enddef ;
+
+vardef flow_x_on_grid (expr n, xfrom, xto, zfrom) =
+ if (xfrom = xto) and not (zfrom = 0) :
+ if (zfrom=1) : flow_right_on_grid(2) else : flow_left_on_grid(2) fi
+ elseif xpart flow_xypoints[1] < xpart flow_xypoints[6] :
+ flow_right_on_grid(n)
+ else :
+ flow_left_on_grid(n)
+ fi
+enddef ;
+
+vardef flow_y_on_grid (expr n, yfrom, yto, zfrom) =
+ if (yfrom = yto) and not (zfrom = 0) :
+ if (zfrom = 1) : flow_up_on_grid(2) else : flow_down_on_grid(2) fi
+ elseif ypart flow_xypoints[1] < ypart flow_xypoints[6] :
+ flow_up_on_grid(n)
+ else :
+ flow_down_on_grid(n)
+ fi
+enddef ;
+
+vardef flow_xy_on_grid (expr n, m) =
+ (xpart flow_xypoints[n], ypart flow_xypoints[m])
+enddef ;
+
+vardef flow_down_to_grid (expr a,b) =
+ (xpart flow_xypoints[a], ypart flow_xypoints[if ypart flow_xypoints[a]<ypart flow_xypoints[b] : a else : b fi])
+enddef ;
+
+vardef flow_up_to_grid (expr a,b) =
+ (xpart flow_xypoints[a], ypart flow_xypoints[if ypart flow_xypoints[a]>ypart flow_xypoints[b] : a else : b fi])
+enddef ;
+
+vardef flow_left_to_grid (expr a,b) =
+ (xpart flow_xypoints[if xpart flow_xypoints[a]<xpart flow_xypoints[b] : a else : b fi], ypart flow_xypoints[a])
+enddef ;
+
+vardef flow_right_to_grid (expr a,b) =
+ (xpart flow_xypoints[if xpart flow_xypoints[a]>xpart flow_xypoints[b] : a else : b fi], ypart flow_xypoints[a])
+enddef ;
+
+vardef flow_valid_connection (expr xfrom, yfrom, xto, yto) =
+ begingroup ;
+ save ok, vc, pp ; boolean ok ; pair vc ; path pp ;
+ save flow_xyfirst, flow_xylast ; pair flow_xyfirst, flow_xylast ;
+ % check for slanted lines
+ ok := true ;
+ for i=1 upto flow_xypoint-1 :
+ if not ((xpart flow_xypoints[i]=xpart flow_xypoints[i+1]) or (ypart flow_xypoints[i]=ypart flow_xypoints[i+1])) :
+ ok := false ;
+ fi ;
+ endfor ;
+ if not ok :
+ % message("slanted");
+ false
+ elseif flow_forcevalid :
+ % message("force");
+ true
+ elseif (xfrom=xto) and (yfrom=yto) :
+ % message("self");
+ false
+ else :
+ % check for crossing shapes
+ flow_xyfirst := flow_xypoints[1] ;
+ flow_xylast := flow_xypoints[flow_xypoint] ;
+ flow_trim_points ;
+ pp := for i=1 upto flow_xypoint-1 : flow_xypoints[i]-- endfor flow_xypoints[flow_xypoint] ;
+ flow_xypoints[1] := flow_xyfirst ;
+ flow_xypoints[flow_xypoint] := flow_xylast ;
+ for i=1 upto flow_max_x :
+ for j=1 upto flow_max_y : % was bug: xfrom,yto
+ if not ( ( (i,j)=(xfrom,yfrom) ) or ( (i,j)=(xto,yto) ) ) :
+ if not flow_xyfree[i][j] :
+ vc := pp intersection_point flow_xypath[i][j] ;
+ if intersection_found :
+ ok := false
+ fi ;
+ fi ;
+ fi ;
+ endfor ;
+ endfor ;
+ % if not ok: message("crossing") ; fi ;
+ ok
+ fi
+ endgroup
+enddef ;
+
+def flow_connect_top_bottom (expr n) (expr xfrom, yyfrom, zfrom) (expr xto, yyto, zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,6) :
+ flow_xypoints[1] := flow_xy_top(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[6] := flow_xy_bottom(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_up_on_grid(1) ;
+ flow_xypoints[5] := flow_down_on_grid(6) ;
+ flow_xypoints[3] := flow_up_to_grid(2,5) ;
+ flow_xypoints[4] := flow_up_to_grid(2,5) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ;
+ flow_xypoints[4] := flow_xy_on_grid(3,5) ;
+ fi ;
+ %%%% begin experiment
+ flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ;
+ flow_xypoints[4] := flow_xypoints[4] shifted (flow_dsp_x,0) ;
+ if flow_dsp_y>0 :
+ flow_xypoints[2] := flow_xypoints[2] shifted (0,flow_dsp_y) ;
+ flow_xypoints[3] := flow_xypoints[3] shifted (0,flow_dsp_y) ;
+ elseif flow_dsp_y<0 :
+ flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ;
+ flow_xypoints[5] := flow_xypoints[5] shifted (0,flow_dsp_y) ;
+ fi
+ %%%% end experiment
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_left_right (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,6) :
+ flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[6] := flow_xy_right(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_left_on_grid(1) ;
+ flow_xypoints[5] := flow_right_on_grid(6) ;
+ flow_xypoints[3] := flow_left_to_grid(2,5) ;
+ flow_xypoints[4] := flow_left_to_grid(2,5) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ;
+ flow_xypoints[4] := flow_xy_on_grid(5,3) ;
+ fi ;
+ %%%% begin experiment
+ if flow_dsp_y <> 0 :
+ flow_xypoints[3] := flow_xypoints[3] shifted (0,-flow_dsp_y) ;
+ flow_xypoints[4] := flow_xypoints[4] shifted (0,-flow_dsp_y) ;
+ fi ;
+ %%%% end experiment
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_left_top (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,5) :
+ flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[5] := flow_xy_top(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_left_on_grid(1) ;
+ flow_xypoints[4] := flow_up_on_grid(5) ;
+ flow_xypoints[3] := flow_left_to_grid(2,5) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_xy_on_grid(2,4) ;
+ fi ;
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_left_bottom (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,5) :
+ flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[5] := flow_xy_bottom(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_left_on_grid(1) ;
+ flow_xypoints[4] := flow_down_on_grid(5) ;
+ flow_xypoints[3] := flow_left_to_grid(2,5) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_xy_on_grid(2,4) ;
+ fi ;
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_right_top (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,5) :
+ flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[5] := flow_xy_top(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_right_on_grid(1) ;
+ flow_xypoints[4] := flow_up_on_grid(5) ;
+ flow_xypoints[3] := flow_right_to_grid(2,5) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_xy_on_grid(2,4) ;
+ fi ;
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_right_bottom (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,5) :
+ flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[5] := flow_xy_bottom(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_right_on_grid(1) ;
+ flow_xypoints[4] := flow_down_on_grid(5) ;
+ flow_xypoints[3] := flow_right_to_grid(2,5) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_xy_on_grid(2,4) ;
+ fi ;
+ %%%% begin experiment
+ flow_xypoints[2] := flow_xypoints[2] shifted (flow_dsp_x,0) ;
+ flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ;
+ if flow_dsp_y>0 :
+ flow_xypoints[3] := flow_xypoints[3] shifted (0,-flow_dsp_y) ;
+ flow_xypoints[4] := flow_xypoints[4] shifted (0,-flow_dsp_y) ;
+ elseif flow_dsp_y<0 :
+ flow_xypoints[3] := flow_xypoints[3] shifted (0,flow_dsp_y) ;
+ flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ;
+ fi
+ %%%% end experiment
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_left_left (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,6) :
+ flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[6] := flow_xy_left(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_left_on_grid(1) ;
+ flow_xypoints[5] := flow_left_on_grid(6) ;
+ flow_xypoints[3] := flow_left_to_grid(2,5) ;
+ flow_xypoints[4] := flow_left_to_grid(5,2) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ;
+ flow_xypoints[4] := flow_xy_on_grid(5,3) ;
+ fi ;
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_right_right (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,6) :
+ flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[6] := flow_xy_right(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_right_on_grid(1) ;
+ flow_xypoints[5] := flow_right_on_grid(6) ;
+ flow_xypoints[3] := flow_right_to_grid(2,5) ;
+ flow_xypoints[4] := flow_right_to_grid(5,2) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ;
+ flow_xypoints[4] := flow_xy_on_grid(5,3) ;
+ fi ;
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_top_top (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,6) :
+ flow_xypoints[1] := flow_xy_top(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[6] := flow_xy_top(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_up_on_grid(1) ;
+ flow_xypoints[5] := flow_up_on_grid(6) ;
+ flow_xypoints[3] := flow_up_to_grid(2,5) ;
+ flow_xypoints[4] := flow_up_to_grid(5,2) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ;
+ flow_xypoints[4] := flow_xy_on_grid(3,5) ;
+ fi ;
+ %%%% begin experiment (todo: not value but just + and )
+ if flow_dsp_y <> 0 :
+ flow_xypoints[2] := flow_xypoints[2] shifted (0,flow_dsp_y) ;
+ flow_xypoints[3] := flow_xypoints[3] shifted (0,flow_dsp_y) ;
+ flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ;
+ flow_xypoints[5] := flow_xypoints[5] shifted (0,flow_dsp_y) ;
+ fi ;
+ %%%% end experiment
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_bottom_bottom (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) =
+ yfrom := flow_y_pos(yyfrom) ;
+ yto := flow_y_pos(yyto) ;
+ if flow_points_initialized(xfrom,yfrom,xto,yto,6) :
+ flow_xypoints[1] := flow_xy_bottom(xfrom,yfrom,zfrom,true) ;
+ flow_xypoints[6] := flow_xy_bottom(xto,yto,zto,true) ;
+ flow_xypoints[2] := flow_down_on_grid(1) ;
+ flow_xypoints[5] := flow_down_on_grid(6) ;
+ flow_xypoints[3] := flow_down_to_grid(2,5) ;
+ flow_xypoints[4] := flow_down_to_grid(5,2) ;
+ if not flow_valid_connection(xfrom,yfrom,xto,yto) :
+ flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ;
+ flow_xypoints[4] := flow_xy_on_grid(3,5) ;
+ fi ;
+ %%%% begin experiment
+ flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ;
+ flow_xypoints[4] := flow_xypoints[4] shifted (flow_dsp_x,0) ;
+ if flow_dsp_y<0 :
+ flow_xypoints[2] := flow_xypoints[2] shifted (0,-flow_dsp_y) ;
+ flow_xypoints[3] := flow_xypoints[3] shifted (0,-flow_dsp_y) ;
+ elseif flow_dsp_y>0 :
+ flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ;
+ flow_xypoints[5] := flow_xypoints[5] shifted (0,flow_dsp_y) ;
+ fi
+ %%%% end experiment
+ flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ;
+ fi ;
+enddef ;
+
+def flow_connect_bottom_top (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ flow_reverse_connection := true ;
+ flow_connect_top_bottom (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def flow_connect_right_left (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ flow_reverse_connection := true ;
+ flow_connect_left_right (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def flow_connect_top_left (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ flow_reverse_connection := true ;
+ flow_connect_left_top (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def flow_connect_bottom_left (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ flow_reverse_connection := true ;
+ flow_connect_left_bottom (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def flow_connect_top_right (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ flow_reverse_connection := true ;
+ flow_connect_right_top (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def flow_connect_bottom_right (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) =
+ flow_reverse_connection := true ;
+ flow_connect_right_bottom (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ;
+enddef ;
+
+def flow_draw_test_shape(expr x, y) =
+ flow_draw_shape(x,y,fullcircle, .7, .7) ;
+enddef ;
+
+def flow_draw_test_shapes =
+ for i=1 upto flow_max_x :
+ for j=1 upto flow_max_y :
+ flow_draw_test_shape(i,j) ;
+ endfor ;
+ endfor ;
+enddef;
+
+def flow_draw_test_area =
+ pickup pencircle scaled .5flow_shape_line_width ;
+ draw (unitsquare xscaled flow_max_x yscaled flow_max_y shifted (1,1)) flow_scaled_to_grid withcolor blue ;
+enddef ;
+
+def flow_show_connection(expr n, m) =
+
+ flow_begin_chart(100+n,6,6) ;
+
+ flow_draw_test_area ;
+
+ flow_smooth := true ;
+ flow_arrowtip := true ;
+ flow_dashline := true ;
+
+ flow_draw_test_shape(2,2) ; flow_draw_test_shape(4,5) ;
+ flow_draw_test_shape(3,3) ; flow_draw_test_shape(5,1) ;
+ flow_draw_test_shape(2,5) ; flow_draw_test_shape(1,3) ;
+ flow_draw_test_shape(6,2) ; flow_draw_test_shape(4,6) ;
+
+ if (m=1) :
+ flow_connect_top_bottom (0) (2,2,0) (4,5,0) ;
+ flow_connect_top_bottom (0) (3,3,0) (5,1,0) ;
+ flow_connect_top_bottom (0) (2,5,0) (1,3,0) ;
+ flow_connect_top_bottom (0) (6,2,0) (4,6,0) ;
+ elseif (m=2) :
+ flow_connect_top_top (0) (2,2,0) (4,5,0) ;
+ flow_connect_top_top (0) (3,3,0) (5,1,0) ;
+ flow_connect_top_top (0) (2,5,0) (1,3,0) ;
+ flow_connect_top_top (0) (6,2,0) (4,6,0) ;
+ elseif (m=3) :
+ flow_connect_bottom_bottom (0) (2,2,0) (4,5,0) ;
+ flow_connect_bottom_bottom (0) (3,3,0) (5,1,0) ;
+ flow_connect_bottom_bottom (0) (2,5,0) (1,3,0) ;
+ flow_connect_bottom_bottom (0) (6,2,0) (4,6,0) ;
+ elseif (m=4) :
+ flow_connect_left_right (0) (2,2,0) (4,5,0) ;
+ flow_connect_left_right (0) (3,3,0) (5,1,0) ;
+ flow_connect_left_right (0) (2,5,0) (1,3,0) ;
+ flow_connect_left_right (0) (6,2,0) (4,6,0) ;
+ elseif (m=5) :
+ flow_connect_left_left (0) (2,2,0) (4,5,0) ;
+ flow_connect_left_left (0) (3,3,0) (5,1,0) ;
+ flow_connect_left_left (0) (2,5,0) (1,3,0) ;
+ flow_connect_left_left (0) (6,2,0) (4,6,0) ;
+ elseif (m=6) :
+ flow_connect_right_right (0) (2,2,0) (4,5,0) ;
+ flow_connect_right_right (0) (3,3,0) (5,1,0) ;
+ flow_connect_right_right (0) (2,5,0) (1,3,0) ;
+ flow_connect_right_right (0) (6,2,0) (4,6,0) ;
+ elseif (m=7) :
+ flow_connect_left_top (0) (2,2,0) (4,5,0) ;
+ flow_connect_left_top (0) (3,3,0) (5,1,0) ;
+ flow_connect_left_top (0) (2,5,0) (1,3,0) ;
+ flow_connect_left_top (0) (6,2,0) (4,6,0) ;
+ elseif (m=8) :
+ flow_connect_left_bottom (0) (2,2,0) (4,5,0) ;
+ flow_connect_left_bottom (0) (3,3,0) (5,1,0) ;
+ flow_connect_left_bottom (0) (2,5,0) (1,3,0) ;
+ flow_connect_left_bottom (0) (6,2,0) (4,6,0) ;
+ elseif (m=9) :
+ flow_connect_right_top (0) (2,2,0) (4,5,0) ;
+ flow_connect_right_top (0) (3,3,0) (5,1,0) ;
+ flow_connect_right_top (0) (2,5,0) (1,3,0) ;
+ flow_connect_right_top (0) (6,2,0) (4,6,0) ;
+ else :
+ flow_connect_right_bottom (0) (2,2,0) (4,5,0) ;
+ flow_connect_right_bottom (0) (3,3,0) (5,1,0) ;
+ flow_connect_right_bottom (0) (2,5,0) (1,3,0) ;
+ flow_connect_right_bottom (0) (6,2,0) (4,6,0) ;
+ fi ;
+
+ flow_end_chart ;
+
+enddef ;
+
+def flow_show_connections =
+ for f=1 upto 10 :
+ flow_show_connection(f,f) ;
+ endfor ;
+enddef ;
+
+%D charts
+
+def flow_clip_chart(expr minx, miny, maxx, maxy) =
+ flow_cmin_x := minx ;
+ flow_cmax_x := maxx ;
+ flow_cmin_y := miny ;
+ flow_cmax_y := maxy ;
+enddef ;
+
+def flow_begin_chart(expr n, maxx, maxy) =
+ flow_new_chart ;
+ flow_chart_figure := n ;
+ flow_chart_scale := 1 ;
+ if flow_chart_figure>0:
+ beginfig(flow_chart_figure) ;
+ fi ;
+ flow_initialize_grid (maxx, maxy) ;
+ bboxmargin := 0 ;
+ flow_cmin_x := 1 ;
+ flow_cmax_x := maxx ;
+ flow_cmin_y := 1 ;
+ flow_cmax_y := maxy ;
+enddef ;
+
+def flow_end_chart =
+ begingroup ;
+ save p ; path p ;
+ flow_flush_shapes ;
+ flow_flush_connections ;
+ flow_flush_pictures ;
+ flow_cmin_x := flow_cmin_x ;
+ flow_cmax_x := flow_cmin_x+flow_cmax_x ;
+ flow_cmin_y := flow_cmin_y-1 ;
+ flow_cmax_y := flow_cmin_y+flow_cmax_y ;
+ if flow_reverse_y :
+ flow_cmin_y := flow_y_pos(flow_cmin_y) ;
+ flow_cmax_y := flow_y_pos(flow_cmax_y) ;
+ fi ;
+ p := (((flow_cmin_x,flow_cmin_y)--(flow_cmax_x,flow_cmin_y)--
+ (flow_cmax_x,flow_cmax_y)--(flow_cmin_x,flow_cmax_y)--cycle))
+ flow_scaled_to_grid ;
+ %draw p withcolor red ;
+ p := p enlarged flow_chart_offset ;
+ clip currentpicture to p ;
+ setbounds currentpicture to p ;
+ endgroup ;
+ currentpicture := currentpicture scaled flow_chart_scale ;
+ if flow_chart_figure>0:
+ endfig ;
+ fi ;
+enddef ;
+
+def flow_new_shape(expr x, y, n) =
+ if known n :
+ if (x>0) and (x<=flow_max_x) and (y>0) and (y<=flow_max_y) :
+ flow_draw_shape(x,y,some_shape_path(n), flow_shape_width/flow_grid_width, flow_shape_height/flow_grid_height) ;
+ else :
+ message ("shape outside grid ignored") ;
+ fi ;
+ else :
+ message ("shape not known" ) ;
+ fi ;
+enddef ;
+
+def flow_begin_sub_chart =
+ begingroup ;
+ save flow_shape_line_width, flow_connection_line_width ;
+ save flow_shape_line_color, flow_shape_fill_color, flow_connection_line_color ;
+ color flow_shape_line_color, flow_shape_fill_color, flow_connection_line_color ;
+ save flow_smooth, flow_arrowtip, flow_dashline, flow_peepshape ;
+ boolean flow_smooth, flow_arrowtip, flow_dashline, flow_peepshape ;
+enddef ;
+
+def flow_end_sub_chart =
+ endgroup ;
+enddef ;
+
diff --git a/Master/texmf-dist/metapost/context/base/mp-chem.mp b/Master/texmf-dist/metapost/context/base/mp-chem.mpiv
index c70dafd85cd..04fec713bb4 100644
--- a/Master/texmf-dist/metapost/context/base/mp-chem.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-chem.mpiv
@@ -15,7 +15,9 @@
% either consistent setting or not
-if known chem_reset : endinput ; fi ;
+if known context_chem : endinput ; fi ;
+
+boolean context_chem ; context_chem := true ;
numeric
chem_width, chem_radical_min, chem_radical_max, chem_text_max, chem_circle_radius,
@@ -140,16 +142,15 @@ def chem_stop_structure =
setbounds currentpicture to chem_setting_bbox ;
enddef ;
-def chem_start_component =
-enddef ;
-def chem_stop_component =
-enddef ;
+def chem_start_component = enddef ;
+def chem_stop_component = enddef ;
def chem_pb =
% draw boundingbox currentpicture withpen pencircle scaled 1mm withcolor blue ;
% draw origin withpen pencircle scaled 2mm withcolor blue ;
chem_doing_pb := true ;
enddef ;
+
def chem_pe =
% draw boundingbox currentpicture withpen pencircle scaled .5mm withcolor red ;
% draw origin withpen pencircle scaled 1mm withcolor red ;
@@ -176,38 +177,49 @@ enddef ;
vardef chem_b (expr n, f, t, r, c) =
chem_draw (n, chem_b_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_sb (expr n, f, t, r, c) =
chem_draw (n, chem_sb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_s (expr n, f, t, r, c) =
chem_draw (n, chem_s_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_ss (expr n, f, t, r, c) =
chem_draw (n, chem_ss_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_mid (expr n, r, c) =
chem_draw_fixed (n, chem_midt_path[n], r, c) ;
chem_draw_fixed (n, chem_midb_path[n], r, c) ;
enddef ;
+
vardef chem_mids (expr n, r, c) =
chem_draw_fixed (n, chem_midst_path[n], r, c) ;
chem_draw_fixed (n, chem_midsb_path[n], r, c) ;
enddef ;
+
vardef chem_mss (expr n, f, t, r, c) =
chem_draw (n, chem_mss_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_pss (expr n, f, t, r, c) =
chem_draw (n, chem_pss_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_msb (expr n, f, t, r, c) =
chem_draw (n, chem_msb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_psb (expr n, f, t, r, c) =
chem_draw (n, chem_psb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_eb (expr n, f, t, r, c) =
chem_draw (n, chem_eb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_db (expr n, f, t, r, c) =
if n = 1 :
chem_draw (n, chem_msb_path [n], f, t, r, c) ;
@@ -217,20 +229,25 @@ vardef chem_db (expr n, f, t, r, c) =
chem_draw (n, chem_dbr_path [n], f, t, r, c) ;
fi ;
enddef ;
+
vardef chem_er (expr n, f, t, r, c) =
chem_draw (n, chem_rl_path[n], f, t, r, c) ;
chem_draw (n, chem_rr_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_dr (expr n, f, t, r, c) =
chem_draw (n, chem_srl_path[n], f, t, r, c) ;
chem_draw (n, chem_srr_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_ad (expr n, f, t, r, c) =
chem_draw_arrow(n, chem_ad_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_au (expr n, f, t, r, c) =
chem_draw_arrow(n, chem_au_path[n], f, t, r, c)
enddef ;
+
vardef chem_r (expr n, f, t, r, c) =
if n < 0 :
chem_draw_vertical (n, chem_r_path[n], f, t, r, c) ;
@@ -238,27 +255,35 @@ vardef chem_r (expr n, f, t, r, c) =
chem_draw (n, chem_r_path[n], f, t, r, c) ;
fi ;
enddef ;
+
vardef chem_rd (expr n, f, t, r, c) =
chem_dashed_normal (n, chem_r_path[n], f, t, r, c)
enddef ;
+
vardef chem_mrd (expr n, f, t, r, c) =
chem_dashed_normal (n, chem_mr_path[n], f, t, r, c)
enddef ;
+
vardef chem_prd (expr n, f, t, r, c) =
chem_dashed_normal (n, chem_pr_path[n], f, t, r, c)
enddef ;
+
vardef chem_br (expr n, f, t, r, c) =
chem_fill (n, chem_br_path[n], f, t, r, c )
enddef ;
+
vardef chem_rb (expr n, f, t, r, c) =
chem_fill (n, chem_rb_path[n], f, t, r, c)
enddef ;
+
vardef chem_mrb (expr n, f, t, r, c) =
chem_fill (n, chem_mrb_path[n], f, t, r, c)
enddef ;
+
vardef chem_prb (expr n, f, t, r, c) =
chem_fill (n, chem_prb_path[n], f, t, r, c)
enddef ;
+
vardef chem_mr (expr n, f, t, r, c) =
if n < 0 :
chem_draw_vertical(n, chem_mr_path[n], f, t, r, c)
@@ -266,6 +291,7 @@ vardef chem_mr (expr n, f, t, r, c) =
chem_draw (n, chem_mr_path[n], f, t, r, c)
fi
enddef ;
+
vardef chem_pr (expr n, f, t, r, c) =
if n < 0 :
chem_draw_vertical(n, chem_pr_path[n], f, t, r, c)
@@ -273,75 +299,95 @@ vardef chem_pr (expr n, f, t, r, c) =
chem_draw (n, chem_pr_path[n], f, t, r, c)
fi
enddef ;
+
vardef chem_sr (expr n, f, t, r, c) =
chem_draw (n, chem_sr_path[n], f, t, r, c)
enddef ;
+
vardef chem_msr (expr n, f, t, r, c) =
chem_draw (n, chem_msr_path[n], f, t, r, c)
enddef ;
+
vardef chem_psr (expr n, f, t, r, c) =
chem_draw (n, chem_psr_path[n], f, t, r, c)
enddef ;
+
vardef chem_c (expr n, f, t, r, c) =
chem_draw (n, chem_c_path[n], f, t, r, c)
enddef ;
+
vardef chem_cc (expr n, f, t, r, c) =
chem_draw (n, chem_cc_path[n], f, f, r, c)
enddef ;
+
vardef chem_cd (expr n, f, t, r, c) =
chem_dashed_connected (n, chem_c_path[n], f, t, r, c)
enddef ;
+
vardef chem_ccd (expr n, f, t, r, c) =
chem_dashed_normal (n, chem_cc_path[n], f, f, r, c)
enddef ;
+
vardef chem_rn (expr n, i, t) =
chem_rt (n,i,t) ;
enddef ;
+
vardef chem_rtn (expr n, i, t) =
chem_rtt(n,i,t) ;
enddef ;
+
vardef chem_rbn (expr n, i, t) =
chem_rbt(n,i,t) ;
enddef ;
+
vardef chem_tb (expr n, f, t, r, c) = % one
chem_draw (n, chem_msb_path[n], f, t, r, c) ;
chem_draw (n, chem_sb_path [n], f, t, r, c) ;
chem_draw (n, chem_psb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_ep (expr n, f, t, r, c) = % one
chem_draw (n, chem_e_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_es (expr n, f, t, r, c) = % one
chem_draw_dot (n, center chem_e_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_ed (expr n, f, t, r, c) = % one
chem_draw_dot (n, point 0 of chem_e_path[n], f, t, r, c) ;
chem_draw_dot (n, point 1 of chem_e_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_et (expr n, f, t, r, c) = % one
chem_draw_dot (n, point 0 of chem_e_path[n], f, t, r, c) ;
chem_draw_dot (n, center chem_e_path[n], f, t, r, c) ;
chem_draw_dot (n, point 1 of chem_e_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_sd (expr n, f, t, r, c) = % one
chem_draw (n, chem_ddt_path[n], f, t, r, c) ;
chem_draw (n, chem_ddb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_rdd (expr n, f, t, r, c) = % one
chem_draw (n, chem_ldt_path[n], f, t, r, c) ;
chem_draw (n, chem_ldb_path[n], f, t, r, c) ;
chem_draw (n, chem_psb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_ldd (expr n, f, t, r, c) = % one
chem_draw (n, chem_msb_path[n], f, t, r, c) ;
chem_draw (n, chem_rdt_path[n], f, t, r, c) ;
chem_draw (n, chem_rdb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_hb (expr n, f, t, r, c) = % one
chem_draw_dot (n, point 0 of chem_sb_path[n], f, t, r, c) ;
chem_draw_dot (n, center chem_sb_path[n], f, t, r, c) ;
chem_draw_dot (n, point 1 of chem_sb_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_bb (expr n, f, t, r, c) = % one
if n < 0 :
chem_fill (n, chem_bb_path[n], 1, 1, r, c) ;
@@ -350,14 +396,17 @@ vardef chem_bb (expr n, f, t, r, c) = % one
chem_fill (n, chem_bb_path[n], f, t, r, c) ;
fi ;
enddef ;
+
vardef chem_oe (expr n, f, t, r, c) = % one
chem_draw (n, chem_oe_path[n], f, t, r, c) ;
enddef ;
+
vardef chem_bd (expr n, f, t, r, c) = % one
for i=0 upto 5 :
chem_draw (n, subpath (2i,2i+1) of chem_bd_path[n], f, t, r, c) ;
endfor ;
enddef ;
+
vardef chem_bw (expr n, f, t, r, c) = % one
chem_draw (n, chem_bw_path[n], f, t, r, c) ;
enddef ;
@@ -365,9 +414,11 @@ enddef ;
vardef chem_z_zero@#(text t) =
chem_text@#(t, chem_do(origin)) ;
enddef ;
+
vardef chem_cz_zero@#(text t) =
chem_text@#(t, chem_do(origin)) ;
enddef ;
+
vardef chem_z@#(expr n, p) (text t) =
if p = 0 :
chem_text@#(t, chem_do(origin)) ;
@@ -375,6 +426,7 @@ vardef chem_z@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ;
fi ;
enddef ;
+
vardef chem_cz@#(expr n, p) (text t) =
if n = 1 :
chem_c_text(t, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ;
@@ -382,9 +434,11 @@ vardef chem_cz@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_b_zero[n] rotated chem_ang(n,p))) ;
fi ;
enddef ;
+
vardef chem_midz@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_mid_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+
vardef chem_rz@#(expr n, p) (text t) =
if n < 0 :
% quite special
@@ -393,9 +447,11 @@ vardef chem_rz@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_r_zero[n] rotated chem_ang(n,p))) ;
fi ;
enddef ;
+
vardef chem_crz@#(expr n, p) (text tx) =
chem_text(tx, chem_do(chem_crz_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+
vardef chem_mrz@#(expr n, p) (text t) =
if n < 0 :
% quite special
@@ -404,6 +460,7 @@ vardef chem_mrz@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_mr_zero[n] rotated chem_ang(n,p))) ;
fi ;
enddef ;
+
vardef chem_prz@#(expr n, p) (text t) =
if n < 0 :
% quite special
@@ -412,15 +469,19 @@ vardef chem_prz@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_pr_zero[n] rotated chem_ang(n,p))) ;
fi ;
enddef ;
+
vardef chem_rt@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+
vardef chem_rtt@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+
vardef chem_rbt@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+
vardef chem_zt@#(expr n, p) (text t) =
if n = 1 :
chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
@@ -428,6 +489,7 @@ vardef chem_zt@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
fi ;
enddef ;
+
vardef chem_zn@#(expr n, p) (text t) =
if n = 1 :
chem_text@#(t, chem_do(chem_rt_zero[n] rotated chem_ang(n,p))) ;
@@ -435,15 +497,19 @@ vardef chem_zn@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_n_zero[n] rotated chem_ang(n,p))) ;
fi ;
enddef ;
+
vardef chem_zbt@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+
vardef chem_zbn@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_rtt_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+
vardef chem_ztt@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
enddef ;
+
vardef chem_ztn@#(expr n, p) (text t) =
chem_text@#(t, chem_do(chem_rbt_zero[n] rotated chem_ang(n,p))) ;
enddef ;
@@ -456,8 +522,8 @@ vardef chem_text@#(expr txt, z) = % adapted copy of thelabel@
save p ; picture p ;
p := textext(txt) ;
p := p
- if (labtype@# >= 10) : shifted (0,ypart center p) fi
- shifted (z + chem_text_offset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p)) ;
+ if (mfun_labtype@# >= 10) : shifted (0,ypart center p) fi
+ shifted (z + chem_text_offset*mfun_laboff@# - (mfun_labxf@#*lrcorner p + mfun_labyf@#*ulcorner p + (1-mfun_labxf@#-mfun_labyf@#)*llcorner p)) ;
if chem_text_trace :
draw z withpen pencircle scaled 2pt withcolor red ;
draw boundingbox p withpen pencircle scaled 1pt withcolor red ;
@@ -481,15 +547,19 @@ enddef ;
vardef chem_ang (expr n, d) =
((-1 * (d-1) * chem_angle[n]) + (-chem_rotation+1) * 90 + chem_start[n]) % no ;
enddef ;
+
vardef chem_rot (expr n, d) =
chem_rotation := d ;
enddef ;
+
vardef chem_adj (expr n, d) =
chem_adjacent := d ;
enddef ;
+
vardef chem_sub (expr n, d) =
chem_substituent := d ;
enddef ;
+
vardef chem_dir (expr n, d) =
if n = 1 :
chem_direction_p := (origin - 2*center(chem_b_path[n] rotated chem_ang(n,d+1))) ;
@@ -497,6 +567,7 @@ vardef chem_dir (expr n, d) =
chem_shift := chem_shift + chem_direction_p ;
fi ;
enddef ;
+
vardef chem_mov (expr n, d) =
if d = 0 :
currentpicture := currentpicture shifted - chem_shift ;
@@ -507,6 +578,7 @@ vardef chem_mov (expr n, d) =
chem_shift := chem_shift + chem_move_p ;
fi ;
enddef ;
+
vardef chem_off (expr n, d) =
if (d = 1) or (d = 2) or (d = 8) : % positive
currentpicture := currentpicture shifted (-chem_setting_offset,0) ;
@@ -554,6 +626,7 @@ vardef chem_draw (expr n, path_fragment, from_point, to_point, linewidth, lineco
draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor ;
endfor ;
enddef ;
+
vardef chem_fill (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
for i:=from_point upto to_point:
fill (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled 0 withcolor linecolor ;
@@ -565,24 +638,29 @@ vardef chem_dashed_normal (expr n, path_fragment, from_point, to_point, linewidt
draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor dashed evenly ;
endfor ;
enddef ;
+
vardef chem_dashed_connected (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
draw for i:=from_point upto to_point:
(path_fragment rotated chem_ang(n,i)) if i < to_point : -- fi
endfor withpen pencircle scaled linewidth withcolor linecolor dashed evenly ;
enddef ;
+
vardef chem_draw_dot (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
for i:=from_point upto to_point:
draw (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled (chem_dot_factor*linewidth) withcolor linecolor ;
endfor ;
enddef ;
+
vardef chem_draw_fixed (expr n, path_fragment, linewidth, linecolor) =
draw (path_fragment rotated chem_ang(n,1)) withpen pencircle scaled linewidth withcolor linecolor ;
enddef ;
+
vardef chem_draw_arrow (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
for i:=from_point upto to_point:
drawarrow (path_fragment rotated chem_ang(n,i)) withpen pencircle scaled linewidth withcolor linecolor ;
endfor ;
enddef ;
+
vardef chem_draw_vertical (expr n, path_fragment, from_point, to_point, linewidth, linecolor) =
% quite special
for i:=from_point upto to_point:
@@ -603,6 +681,7 @@ vardef chem_save =
% chem_rotation := 1 ;
currentpicture := nullpicture ;
enddef ;
+
vardef chem_restore =
if chem_stack_n > 0 :
currentpicture := currentpicture shifted - chem_shift ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-core.mp b/Master/texmf-dist/metapost/context/base/mp-core.mpii
index 2ccdad22c24..c07f0976fd6 100644
--- a/Master/texmf-dist/metapost/context/base/mp-core.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-core.mpii
@@ -1,6 +1,4 @@
-
-if unknown context_tool : input mp-tool ; fi ;
-if known context_core : endinput ; fi ;
+if known context_core : endinput ; fi ;
boolean context_core ; context_core := true ;
@@ -1377,10 +1375,6 @@ def ProcessSyncTask(expr p, c) =
fill p withcolor c ;
enddef ;
-endinput ;
-
-end
-
% for Jelle Huisman
%
% \setupcolors[state=start]
diff --git a/Master/texmf-dist/metapost/context/base/mp-core.mpiv b/Master/texmf-dist/metapost/context/base/mp-core.mpiv
new file mode 100644
index 00000000000..fd0b8bb9c73
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-core.mpiv
@@ -0,0 +1,1558 @@
+%D \module
+%D [ file=mp-core.mp,
+%D version=1999.08.01, % anchoring
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=background macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+if known context_core : endinput ; fi ;
+
+boolean context_core ; context_core := true ;
+
+%D Copied to here .. not used any more.
+
+def SaveTextAreas =
+ path SavedTextAreas [] ;
+ path SavedTextColumns[] ;
+ numeric NOfSavedTextAreas ;
+ numeric NOfSavedTextColumns ;
+ for i=1 upto NOfTextAreas :
+ SavedTextAreas[i] := TextAreas[i] ;
+ endfor ;
+ for i=1 upto NOfTextColumns :
+ SavedTextColumns[i] := TextColumns[i] ;
+ endfor ;
+ NOfSavedTextAreas := NOfTextAreas ;
+ NOfSavedTextColumns := NOfTextColumns ;
+enddef ;
+
+def ResetTextAreas =
+ path TextAreas[], TextColumns[], PlainTextArea, RegionTextArea ;
+ numeric NOfTextAreas ; NOfTextAreas := 0 ;
+ numeric NOfTextColumns ; NOfTextColumns := 0 ;
+ numeric nofmultipars ; nofmultipars := 0 ;
+ TextAreas[0] := TextColumns[0] := origin -- cycle ;
+enddef ;
+
+ResetTextAreas ; SaveTextAreas ; ;
+
+def RegisterTextArea (expr x, y, w, h, d) =
+ begingroup ;
+ save p ; path p ;
+ p := unitsquare xyscaled(w,h+d) shifted (x,y-d) ;
+ if NOfTextAreas>0 :
+ % if needed, concatenate areas
+ if (round(llcorner TextAreas[NOfTextAreas]) = round(ulcorner p)) and
+ (round(lrcorner TextAreas[NOfTextAreas]) = round(urcorner p)) :
+ p :=
+ ulcorner TextAreas[NOfTextAreas] --
+ urcorner TextAreas[NOfTextAreas] --
+ lrcorner p --
+ llcorner p -- cycle ;
+ else :
+ NOfTextAreas := NOfTextAreas + 1 ;
+ fi ;
+ else :
+ NOfTextAreas := NOfTextAreas + 1 ;
+ fi ;
+ TextAreas[NOfTextAreas] := p ;
+ if NOfTextColumns>0 :
+ if (round(xpart llcorner TextColumns[NOfTextColumns]) = round(xpart ulcorner p)) and
+ (round(xpart lrcorner TextColumns[NOfTextColumns]) = round(xpart urcorner p)) :
+ p :=
+ ulcorner TextColumns[NOfTextColumns] --
+ urcorner TextColumns[NOfTextColumns] --
+ lrcorner p --
+ llcorner p -- cycle ;
+ else :
+ NOfTextColumns := NOfTextColumns + 1 ;
+ fi ;
+ else :
+ NOfTextColumns := NOfTextColumns + 1 ;
+ fi ;
+ TextColumns[NOfTextColumns] := p ;
+ endgroup ;
+enddef ;
+
+%D We store a local area in slot zero.
+
+def RegisterPlainTextArea(expr x,y,w,h,d) =
+ PlainTextArea := unitsquare xyscaled(w,h+d) shifted (x,y-d) ;
+enddef ;
+
+def RegisterRegionTextArea(expr x,y,w,h,d) =
+ RegionTextArea := unitsquare xyscaled(w,h+d) shifted (x,y-d) ;
+ % RegionTextArea := RegionTextArea enlarged 2mm ;
+enddef ;
+
+def RegisterLocalTextArea (expr x, y, w, h, d) =
+ TextAreas[0] := TextColumns[0] := unitsquare xyscaled(w,h+d) shifted (x,y-d) ;
+enddef ;
+
+def ResetLocalTextArea =
+ TextAreas[0] := TextColumns[0] := origin -- cycle ;
+enddef ;
+
+ResetLocalTextArea ;
+
+vardef InsideTextArea (expr _i_, _xy_) =
+ (round(xpart _xy_) >= round(xpart llcorner TextAreas[_i_])) and
+ (round(xpart _xy_) <= round(xpart lrcorner TextAreas[_i_])) and
+ (round(ypart _xy_) >= round(ypart llcorner TextAreas[_i_])) and
+ (round(ypart _xy_) <= round(ypart urcorner TextAreas[_i_]))
+enddef ;
+
+vardef InsideSavedTextArea (expr _i_, _xy_) =
+ (round(xpart _xy_) >= round(xpart llcorner SavedTextAreas[_i_])) and
+ (round(xpart _xy_) <= round(xpart lrcorner SavedTextAreas[_i_])) and
+ (round(ypart _xy_) >= round(ypart llcorner SavedTextAreas[_i_])) and
+ (round(ypart _xy_) <= round(ypart urcorner SavedTextAreas[_i_]))
+enddef ;
+
+vardef InsideSomeTextArea (expr _xy_) =
+ save ok ; boolean ok ; ok := false ;
+ for i := 1 upto NOfTextAreas :
+ if InsideTextArea(i,_xy_) :
+ ok := true ; % we can move the exit here
+ fi ;
+ exitif ok ;
+ endfor ;
+ ok
+enddef ;
+
+vardef InsideSomeSavedTextArea (expr _xy_) =
+ save ok ; boolean ok ; ok := false ;
+ for i := 1 upto NOfSavedTextAreas :
+ if InsideSavedTextArea(i,_xy_) :
+ ok := true ;
+ fi ;
+ exitif ok ;
+ endfor ;
+ ok
+enddef ;
+
+vardef TextAreaX (expr x) =
+ numeric _TextAreaX_ ; _TextAreaX_ := 0 ;
+ for i := 1 upto NOfTextAreas :
+ if (round(x) >= round(xpart llcorner TextAreas[i])) and
+ (round(x) <= round(xpart lrcorner TextAreas[i])) :
+ _TextAreaX_ := xpart llcorner TextAreas[i] ;
+ fi ;
+ endfor ;
+ _TextAreaX_
+enddef ;
+
+vardef TextAreaY (expr y) =
+ numeric _TextAreaY_ ; _TextAreaY_ := 0 ;
+ for i := 1 upto NOfTextAreas :
+ if (round(y) >= round(ypart llcorner TextAreas[NOfTextAreas])) and
+ (round(y) <= round(ypart ulcorner TextAreas[NOfTextAreas])) :
+ _TextAreaY_ := ypart llcorner TextAreas[NOfTextAreas] ;
+ fi ;
+ endfor ;
+ _TextAreaY_
+enddef ;
+
+vardef TextAreaXY (expr x, y) =
+ pair _TextAreaXY_ ; _TextAreaXY_ := origin ;
+ for i := 1 upto NOfTextAreas :
+ if (round(x) >= round(xpart llcorner TextAreas[i])) and
+ (round(x) <= round(xpart lrcorner TextAreas[i])) and
+ (round(y) >= round(ypart llcorner TextAreas[i])) and
+ (round(y) <= round(ypart ulcorner TextAreas[i])) :
+ _TextAreaXY_ := llconer TextAreas[i] ;
+ fi ;
+ endfor ;
+ _TextAreaXY_
+enddef ;
+
+vardef TextAreaW (expr x) =
+ numeric _TextAreaW_ ; _TextAreaW_ := 0 ;
+ for i := 1 upto NOfTextAreas :
+ if (round(x) >= round(xpart llcorner TextAreas[i])) and
+ (round(x) <= round(xpart lrcorner TextAreas[i])) :
+ _TextAreaW_ := bbwidth(TextAreas[i]) ;
+ fi ;
+ endfor ;
+ _TextAreaW_
+enddef ;
+
+vardef TextAreaH (expr y) =
+ numeric _TextAreaH_ ; _TextAreaH_ := 0 ;
+ for i := 1 upto NOfTextAreas :
+ if (round(y) >= round(ypart llcorner TextAreas[i])) and
+ (round(y) <= round(ypart ulcorner TextAreas[i])) :
+ _TextAreaH_ := bbheight(TextAreas[i]) ;
+ fi ;
+ endfor ;
+ _TextAreaH_
+enddef ;
+
+vardef TextAreaWH (expr x, y) =
+ pair _TextAreaWH_ ; _TextAreaWH_ := origin ;
+ for i := 1 upto NOfTextAreas :
+ if (round(x) >= round(xpart llcorner TextAreas[i])) and
+ (round(x) <= round(xpart lrcorner TextAreas[i])) and
+ (round(y) >= round(ypart llcorner TextAreas[i])) and
+ (round(y) <= round(ypart ulcorner TextAreas[i])) :
+ _TextAreaWH_ := (bbwidth(TextAreas[i]),bbheight(TextAreas[i])) ;
+ fi ;
+ endfor ;
+ _TextAreaWH_
+enddef ;
+
+%D Till here.
+
+pair lxy[], rxy[], cxy[], llxy[], lrxy[], ulxy[], urxy[] ;
+path pxy[] ;
+numeric hxy[], wxy[], dxy[], nxy[] ;
+
+def box_found (expr n,x,y,w,h,d) =
+ not ((x=0) and (y=0) and (w=0) and (h=0) and (d=0))
+enddef ;
+
+def initialize_box_pos (expr pos,n,x,y,w,h,d) =
+ pair lxy, rxy, cxy, llxy, lrxy, ulxy, urxy ;
+ path pxy ; numeric hxy, wxy, dxy, nxy;
+ lxy := (x,y) ;
+ llxy := (x,y-d) ;
+ lrxy := (x+w,y-d) ;
+ urxy := (x+w,y+h) ;
+ ulxy := (x,y+h) ;
+ wxy := w ;
+ hxy := h ;
+ dxy := d ;
+ rxy := lxy shifted (wxy,0) ;
+ pxy := llxy--lrxy--urxy--ulxy--cycle ;
+ cxy := center pxy ;
+ nxy := n ;
+ freeze_box(pos) ;
+enddef ;
+
+def freeze_box (expr pos) =
+ lxy[pos] := lxy ;
+ llxy[pos] := llxy ;
+ lrxy[pos] := lrxy ;
+ urxy[pos] := urxy ;
+ ulxy[pos] := ulxy ;
+ wxy[pos] := wxy ;
+ hxy[pos] := hxy ;
+ dxy[pos] := dxy ;
+ rxy[pos] := rxy ;
+ pxy[pos] := pxy ;
+ cxy[pos] := cxy ;
+ nxy[pos] := nxy ;
+enddef ;
+
+def initialize_box (expr n,x,y,w,h,d) =
+ numeric bpos ; bpos := 0 ; initialize_box_pos(bpos,n,x,y,w,h,d) ;
+enddef ;
+
+def initialize_area (expr fn,fx,fy,fw,fh,fd,
+ tn,tx,ty,tw,th,td) =
+ numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+ numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+ do_initialize_area (fpos, tpos) ;
+enddef ;
+
+def do_initialize_area (expr fpos, tpos) =
+ lxy := lxy[fpos] ;
+ llxy := (xpart llxy[fpos], ypart llxy[tpos]) ;
+ lrxy := lrxy[tpos] ;
+ urxy := (xpart urxy[tpos], ypart urxy[fpos]) ;
+ ulxy := ulxy[fpos] ;
+ wxy := xpart lrxy - xpart llxy ;
+ hxy := hxy[fpos] ;
+ dxy := dxy[tpos] ;
+ rxy := lxy shifted (wxy,0) ;
+ pxy := llxy--lrxy--urxy--ulxy--cycle ;
+ cxy := center pxy ;
+enddef ;
+
+def set_par_line_height (expr ph, pd) =
+ par_strut_height := if ph>0 : ph elseif StrutHeight>0 : StrutHeight else : 8pt fi ;
+ par_strut_depth := if pd>0 : pd elseif StrutDepth >0 : StrutDepth else : 3pt fi ;
+ par_line_height := par_strut_height + par_strut_depth ;
+enddef ;
+
+def initialize_par (expr fn,fx,fy,fw,fh,fd,
+ tn,tx,ty,tw,th,td,
+ mn,mx,my,mw,mh,md,
+ pn,px,py,pw,ph,pd,
+ rw,rl,rr,rh,ra,ri) =
+
+ numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+ numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+ numeric mpos ; mpos := 3 ; initialize_box_pos(mpos,mn,mx,my,mw,mh,md) ;
+ numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ;
+
+ numeric par_strut_height, par_strut_depth, par_line_height ;
+
+ set_par_line_height (ph, pd) ;
+
+ do_initialize_area (fpos, tpos) ;
+ do_initialize_par (fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) ;
+
+enddef ;
+
+def initialize_area_par (expr fn,fx,fy,fw,fh,fd,
+ tn,tx,ty,tw,th,td,
+ wn,wx,wy,ww,wh,wd) =
+
+ numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+ numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+ numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ;
+
+ numeric par_strut_height, par_strut_depth, par_line_height ;
+
+ set_par_line_height (wh, wd) ;
+
+ numeric ffpos ; ffpos := 4 ; initialize_box_pos(ffpos,wn,wx,fy,0,wh,wd) ;
+ numeric ttpos ; ttpos := 5 ; initialize_box_pos(ttpos,wn,wx+ww,ty,0,wh,wd) ;
+
+ do_initialize_area (ffpos, ttpos) ;
+
+ numeric mpos ; mpos := 6 ; freeze_box(mpos) ;
+
+ do_initialize_par (fpos, tpos, mpos, ffpos, 0,0,0,0,0,0) ;
+
+enddef ;
+
+def do_initialize_par (expr fpos, tpos, mpos, ppos, rw,rl,rr,rh,ra,ri) =
+
+ pair lref, rref, pref, lhref, rhref ;
+
+ % clip the page area to the left and right skips
+
+ llxy[mpos] := llxy[mpos] shifted (+rl,0) ;
+ lrxy[mpos] := lrxy[mpos] shifted (-rr,0) ;
+ urxy[mpos] := urxy[mpos] shifted (-rr,0) ;
+ ulxy[mpos] := ulxy[mpos] shifted (+rl,0) ;
+
+ % fixate the leftskip, rightskip and hanging indentation
+
+ lref := (xpart llxy[mpos],ypart ulxy[ppos]) ; lhref := lref shifted (rh,0) ;
+ rref := (xpart lrxy[mpos],ypart urxy[ppos]) ; rhref := rref shifted (rh,0) ;
+
+ pref := lxy[ppos] ;
+
+ if nxy[tpos] > nxy[fpos] :
+ if nxy[fpos] = nxy[mpos] :
+ % first of multiple pages
+ llxy[tpos] := llxy[mpos] ;
+ lrxy[tpos] := lrxy[mpos] ;
+ urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ;
+ ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ;
+ boxgriddirection := down ;
+ elseif nxy[tpos] = nxy[mpos] :
+ % last of multiple pages
+ llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ;
+ lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ;
+ urxy[fpos] := urxy[mpos] ;
+ ulxy[fpos] := ulxy[mpos] ;
+ boxgriddirection := up ;
+ else :
+ % middle of multiple pages
+ llxy[fpos] := ulxy[mpos] shifted (0,-par_line_height) ;
+ lrxy[fpos] := urxy[mpos] shifted (0,-par_line_height) ;
+ urxy[fpos] := urxy[mpos] ;
+ ulxy[fpos] := ulxy[mpos] ;
+ llxy[tpos] := llxy[mpos] ;
+ lrxy[tpos] := lrxy[mpos] ;
+ urxy[tpos] := lrxy[mpos] shifted (0,par_line_height) ;
+ ulxy[tpos] := llxy[mpos] shifted (0,par_line_height) ;
+ boxgriddirection := up ;
+ fi ;
+ else :
+ % just one page
+ boxgriddirection := up ;
+ fi ;
+
+ path txy, bxy, pxy, mxy ;
+
+ txy := originpath ; % top
+ bxy := originpath ; % bottom
+ pxy := originpath ; % composed
+
+ boolean lefthang, righthang, somehang ;
+
+ % we only hang on the first of a multiple page background
+
+ if nxy[mpos] > nxy[fpos] :
+ lefthang := righthang := somehang := false ;
+ else :
+ lefthang := (rh>0) ; righthang := (rh<0) ; somehang := false ;
+ fi ;
+
+ if lefthang :
+ mxy := boundingbox (lref -- lref shifted (rh,ra*par_line_height)) ;
+ elseif righthang :
+ mxy := boundingbox (rref -- rref shifted (rh,ra*par_line_height)) ;
+ else :
+ mxy := originpath ;
+ fi ;
+
+ if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) :
+
+ % We have a one-liner. Watch how er use the bottom pos for
+ % determining the height.
+
+ llxy[fpos] := (xpart llxy[fpos], ypart llxy[tpos]) ;
+ ulxy[fpos] := (xpart ulxy[fpos], ypart ulxy[tpos]) ;
+
+ else :
+
+ % We have a multi-liner. For convenience we now correct the
+ % begin and end points for indentation.
+
+ if lefthang and (round(ypart llxy[tpos]) >= round(ypart lrcorner mxy)) :
+ llxy[tpos] := (xpart lhref, ypart llxy[tpos]) ;
+ ulxy[tpos] := (xpart lhref, ypart ulxy[tpos]) ;
+ else :
+ llxy[tpos] := (xpart lref, ypart llxy[tpos]) ;
+ ulxy[tpos] := (xpart lref, ypart ulxy[tpos]) ;
+ fi ;
+
+ if righthang and (round(ypart lrxy[fpos]) >= round(ypart llcorner mxy)) :
+ lrxy[fpos] := (xpart rhref, ypart lrxy[fpos]) ;
+ urxy[fpos] := (xpart rhref, ypart urxy[fpos]) ;
+ else :
+ lrxy[fpos] := (xpart rref, ypart lrxy[fpos]) ;
+ urxy[fpos] := (xpart rref, ypart urxy[fpos]) ;
+ fi ;
+
+ fi ;
+
+ somehang := (ypart ulxy[fpos]>ypart llcorner mxy) and
+ (ypart llxy[tpos]<ypart llcorner mxy) ;
+
+ if round(ypart llxy[fpos]) = round(ypart llxy[tpos]) :
+
+ % A (short) one-liner goes into the top box.
+
+ txy := llxy[fpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[fpos] -- cycle ;
+
+ elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) and
+ (round(xpart lrxy[tpos]) < round(xpart llxy[fpos])) :
+
+ % We have a sentence that spans two lines but with only end
+ % of line and begin of line segments. We need to take care of
+ % indentation.
+
+ txy := llxy[fpos] -- lrxy[fpos] -- urxy[fpos] -- ulxy[fpos] -- cycle ;
+ bxy := llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- ulxy[tpos] -- cycle ;
+
+ elseif (round(ypart llxy[fpos]) = round(ypart ulxy[tpos])) :
+
+ % We have a sentence that spans two lines but with overlap.
+
+ pxy :=
+ llxy[tpos] -- lrxy[tpos] -- urxy[tpos] -- lrxy[fpos] --
+ urxy[fpos] -- ulxy[fpos] -- llxy[fpos] -- ulxy[tpos] -- cycle ;
+
+ elseif lefthang and somehang :
+
+ % We have a sentence that spans more than two lines with
+ % left hanging indentation.
+
+ pxy :=
+ llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+ (xpart urxy[fpos],ypart urxy[tpos]) --
+ urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+ if round(ypart urxy[tpos]) < round(ypart llcorner mxy) :
+ (xpart lrcorner mxy,ypart llxy[fpos]) --
+ lrcorner mxy --
+ (xpart llxy[tpos],ypart llcorner mxy) --
+ else :
+ (xpart llxy[tpos],ypart llxy[fpos]) --
+ fi
+ cycle ;
+
+ elseif righthang and somehang :
+
+ % We have a sentence that spans more than two lines with
+ % right hanging indentation.
+
+ pxy :=
+ llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+ if round(ypart urxy[tpos]) < round(ypart llcorner mxy) :
+ (xpart lrcorner mxy,ypart urxy[tpos]) --
+ lrcorner mxy -- llcorner mxy --
+ else :
+ (xpart urxy[fpos],ypart urxy[tpos]) --
+ fi
+ urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+ (xpart llxy[tpos],ypart llxy[fpos]) --
+ cycle ;
+
+ else :
+
+ % We have a sentence that spans more than two lines with
+ % no hanging indentation.
+
+ pxy :=
+ llxy[tpos] -- lrxy[tpos] -- urxy[tpos] --
+ (xpart urxy[fpos],ypart urxy[tpos]) --
+ urxy[fpos] -- ulxy[fpos] -- llxy[fpos] --
+ (xpart llxy[tpos],ypart llxy[fpos]) --
+ cycle ;
+
+ fi ;
+
+ pxy := simplified pxy ;
+ pxy := unspiked pxy ;
+
+enddef ;
+
+TopSkip := 0 ; % will move
+StrutHeight := 0 ; % will move
+
+pair last_multi_par_shift ; last_multi_par_shift := origin ;
+
+def relocate_multipars (expr xy) =
+ last_multi_par_shift := xy ;
+ for i=1 upto nofmultipars :
+ multipars[i] := multipars[i] shifted last_multi_par_shift ;
+ endfor ;
+enddef ;
+
+boolean compensate_multi_par_topskip ;
+boolean span_multi_column_pars ;
+boolean auto_multi_par_hsize ;
+boolean enable_multi_par_fallback ;
+
+compensate_multi_par_topskip := true ;
+span_multi_column_pars := false ;
+auto_multi_par_hsize := false ; % true ;
+enable_multi_par_fallback := true ;
+
+vardef multi_par_at_top (expr i) =
+ (round (ypart ulcorner multipars[i]) = round (ypart ulcorner (TextAreas[multirefs[i]] shifted last_multi_par_shift)))
+enddef ;
+
+numeric nofmultipars ; nofmultipars := 0 ;
+
+boolean obey_multi_par_hang ; obey_multi_par_hang := true ;
+boolean obey_multi_par_more ; obey_multi_par_more := true ;
+boolean snap_multi_par_tops ; snap_multi_par_tops := true ;
+boolean local_multi_par_area ; local_multi_par_area := false ;
+boolean use_multi_par_region ; use_multi_par_region := false ;
+boolean ignore_multi_par_page ; ignore_multi_par_page := false ;
+boolean force_multi_par_chain ; force_multi_par_chain := true ;
+boolean one_piece_multi_par ; one_piece_multi_par := false ;
+boolean check_multi_par_chain ; check_multi_par_chain := true ; % extra page check
+
+boolean multi_column_first_page_hack; multi_column_first_page_hack := true ; % seems to work ok
+
+def simplify_multi_pars = % boundingbox ipv shape als optie
+ for i := 1 upto nofmultipars :
+ multipars[i] := boundingbox multipars[i] ;
+ endfor ;
+enddef ;
+
+def save_multipar (expr i, l, p) =
+ nofmultipars := nofmultipars + 1 ;
+ multirefs[nofmultipars] := i ;
+ multilocs[nofmultipars] := l ;
+ multipars[nofmultipars] := unspiked (simplified p) ;
+enddef ;
+
+def prepare_multi_pars (expr fn,fx,fy,fw,fh,fd,
+ tn,tx,ty,tw,th,td,
+ wn,wx,wy,ww,wh,wd,
+ pn,px,py,pw,ph,pd,
+ rw,rl,rr,rh,ra,ri) =
+
+% fill PlainTextArea withcolor red ;
+% fill RegionTextArea withcolor green;
+
+ if span_multi_column_pars :
+ begingroup ;
+ save TextAreas ; path TextAreas[] ;
+ save NOfTextAreas ; numeric NOfTextAreas ;
+ for i=1 upto NOfTextColumns :
+ TextAreas[i] := TextColumns[i] ;
+ endfor ;
+ NOfTextAreas := NOfTextColumns ;
+ fi ;
+
+ last_multi_par_shift := origin ;
+
+% save _tx_, _ty_, _fx_, _fy_ ;
+% if use_multi_par_region :
+% _fx_ := fx ; %min(xpart ulcorner RegionTextArea,fx) ;
+% _fy_ := fy ; %min(xpart ulcorner RegionTextArea,fy) ;
+% _tx_ := min(xpart lrcorner RegionTextArea,tx) ;
+% _ty_ := min(xpart lrcorner RegionTextArea,ty) ;
+% else :
+% _fx_ := fx ;
+% _fy_ := fy ;
+% _tx_ := tx ;
+% _ty_ := ty ;
+% fi ;
+
+% numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,_fx_,_fy_,fw,fh,fd) ;
+% numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,_tx_,_ty_,tw,th,td) ;
+ numeric fpos ; fpos := 1 ; initialize_box_pos(fpos,fn,fx,fy,fw,fh,fd) ;
+ numeric tpos ; tpos := 2 ; initialize_box_pos(tpos,tn,tx,ty,tw,th,td) ;
+ numeric wpos ; wpos := 3 ; initialize_box_pos(wpos,wn,wx,wy,ww,wh,wd) ;
+ numeric ppos ; ppos := 4 ; initialize_box_pos(ppos,pn,px,py,pw,ph,pd) ;
+
+ if local_multi_par_area :
+ RealPageNumber := fn ;
+ NOfTextAreas := 1 ;
+ NOfSavedTextAreas := 0 ;
+ TextAreas[1] := TextAreas[0] ;
+ TextColumns[1] := TextColumns[0] ;
+ nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ;
+ elseif use_multi_par_region :
+ RealPageNumber := fn ;
+ NOfTextAreas := 1 ;
+ NOfSavedTextAreas := 0 ;
+ TextAreas[1] := RegionTextArea ;
+ TextColumns[1] := RegionTextArea ;
+ nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ;
+ elseif ignore_multi_par_page :
+ RealPageNumber := fn ;
+ nxy[fpos] := nxy[tpos] := nxy[wpos] := nxy[ppos] := RealPageNumber ;
+ fi ;
+
+ numeric par_strut_height, par_strut_depth, par_line_height ;
+
+ set_par_line_height (ph, pd) ;
+
+ numeric par_hang_indent, par_hang_after, par_indent, par_left_skip, par_right_skip ;
+
+ par_hang_indent := rh ;
+ par_hang_after := ra ;
+ par_indent := ri ;
+ par_left_skip := rl ;
+ par_right_skip := rr ;
+
+ pair par_start_pos ;
+ pair par_stop_pos ;
+
+ par_start_pos := llxy[fpos]
+ if par_indent <0: shifted (-par_indent, 0) fi
+ if par_left_skip<0: shifted (-par_left_skip,0) fi ;
+
+ par_stop_pos := lrxy[tpos]
+ if par_right_skip<0: shifted (par_right_skip,0) fi ; % nasty as the endpos can be shifted by rightskip
+
+ if wxy[wpos]>0 :
+ left_skip := rl + xpart llxy[wpos] - xpart llxy[ppos] ;
+ right_skip := rw - left_skip - ww ;
+ else :
+ left_skip := rl ;
+ right_skip := rr ;
+ fi ;
+
+ path multipar, multipars[] ;
+ numeric multiref, multirefs[] ;
+ numeric multiloc, multilocs[] ; % 1=begin 2=between 3=end
+
+ numeric multi_par_pages ; multi_par_pages := nxy[tpos]-nxy[fpos]+1 ;
+
+ % locals .. why can't i move these outside?
+
+ vardef _pmp_set_multipar_ (expr i) =
+ ( (TextAreas[i] leftenlarged -left_skip) rightenlarged (-right_skip
+ if auto_multi_par_hsize : + rw - bbwidth(TextAreas[i]) fi) )
+ enddef ;
+
+ vardef _pmp_snapped_multi_pos_ (expr p) =
+ if snap_multi_par_tops :
+ if abs(ypart p - ypart ulcorner multipar) < par_line_height :
+ (xpart p,ypart ulcorner multipar)
+ else :
+ p
+ fi
+ else :
+ p
+ fi
+ enddef ;
+
+ vardef _pmp_estimated_par_lines_ (expr h) =
+ round(h/par_line_height)
+ enddef ;
+
+ vardef _pmp_top_multi_par_(expr p) =
+ (round(_pmp_estimated_par_lines_(bbheight(p)*par_line_height))=round(bbheight(p)))
+ enddef ;
+
+ vardef _pmp_multi_par_tsc_(expr p) =
+ if _pmp_top_multi_par_(p) : TopSkipCorrection else : 0 fi
+ enddef ;
+
+ vardef _pmp_estimated_multi_par_height_ (expr n, t) =
+ if round(par_line_height)=0 :
+ 0
+ else :
+ save ok, h ; boolean ok ;
+ numeric h ; h := 0 ;
+ ok := false ;
+ if (nxy[fpos]=RealPageNumber-1) :
+ for i := 1 upto NOfSavedTextAreas :
+ if (InsideSavedTextArea(i,par_start_pos)) :
+ ok := true ;
+ h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - ypart llcorner SavedTextAreas[i]) ;
+ elseif ok :
+ h := h + _pmp_estimated_par_lines_(bbheight(SavedTextAreas[i])) ;
+ fi ;
+ endfor ;
+ fi ;
+ if ok :
+ for i := 1 upto n-1 :
+ h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ;
+ endfor ;
+ else :
+ % already: ok := false ;
+ for i := 1 upto n-1 :
+ if (InsideTextArea(i,par_start_pos)) :
+ ok := true ;
+ h := h + _pmp_estimated_par_lines_(ypart ulxy[fpos] - ypart llcorner TextAreas[i]) ;
+ elseif ok :
+ h := h + _pmp_estimated_par_lines_(bbheight(TextAreas[i])) ;
+ fi ;
+ endfor ;
+ fi ;
+ h
+ fi
+ enddef ;
+
+ vardef _pmp_left_top_hang_ (expr same_area) =
+
+ par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ;
+
+ if (par_hang_indent>0) and (par_hang_after<0) and obey_multi_par_hang :
+ pair _ul_ ; _ul_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos]));
+ pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ;
+ if same_area :
+ _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llxy[tpos])) ;
+ fi ;
+ if obey_multi_par_more and (round(par_line_height)>0) :
+ par_hang_after := min(0,round(par_hang_after + (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+ fi ;
+ (xpart _ul_ + par_hang_indent, ypart lrxy[fpos]) --
+ (xpart _ul_ + par_hang_indent, ypart _pa_) --
+ (xpart ulcorner multipar, ypart _pa_)
+ else :
+ (xpart ulcorner multipar, ypart lrxy[fpos])
+ fi
+ enddef ;
+
+ vardef _pmp_right_top_hang_ (expr same_area) =
+
+ par_hang_after := ra + _pmp_estimated_par_lines_(py-fy) ;
+
+ if (par_hang_indent<0) and (par_hang_after<0) and obey_multi_par_hang :
+ pair _ur_ ; _ur_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ;
+ pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart llcorner multipar)) ;
+ if same_area :
+ _pa_ := (xpart _pa_,max(ypart _pa_ -TopSkipCorrection,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ;
+ fi ;
+ if obey_multi_par_more and (round(par_line_height)>0) :
+ par_hang_after := min(0,round(par_hang_after + (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+ fi ;
+ (xpart urcorner multipar, ypart _pa_) --
+ (xpart _ur_ + par_hang_indent, ypart _pa_) --
+ (xpart _ur_ + par_hang_indent, ypart _pmp_snapped_multi_pos_(urxy[fpos]))
+ else :
+ (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos]))
+ fi
+ enddef ;
+
+ vardef _pmp_x_left_top_hang_ (expr i, t) =
+ par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ;
+ if (par_hang_indent>0) and (par_hang_after<0) :
+ pair _ul_ ; _ul_ := ulcorner multipar ;
+ pair _pa_ ; _pa_ := _ul_ shifted (0,par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+ if t :
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart llxy[tpos]));
+ fi ;
+ if abs(ypart _pa_-ypart llxy[tpos])<par_line_height :
+ _pa_ := (xpart _pa_,ypart llxy[tpos]);
+ fi ;
+ if abs(ypart _pa_-ypart llcorner multipar)<par_line_height :
+ _pa_ := (xpart _pa_,ypart llcorner multipar);
+ fi ;
+ (xpart _ul_, ypart _pa_) --
+ (xpart _ul_ + par_hang_indent, ypart _pa_) --
+ (xpart _ul_ + par_hang_indent, ypart _ul_)
+ else :
+ ulcorner multipar
+ fi
+ enddef ;
+
+ vardef _pmp_x_right_top_hang_ (expr i, t) =
+ par_hang_after := min(0,ra + _pmp_estimated_multi_par_height_(i,t)) ;
+ if (par_hang_indent<0) and (par_hang_after<0) :
+ pair _ur_ ; _ur_ := urcorner multipar ;
+ pair _pa_ ; _pa_ := _ur_ shifted (0,par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+ if t :
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(urxy[tpos]))) ;
+ fi ;
+ (xpart _ur_ + par_hang_indent, ypart _ur_) --
+ (xpart _ur_ + par_hang_indent, ypart _pa_) --
+ (xpart _ur_, ypart _pa_)
+ else :
+ urcorner multipar
+ fi
+ enddef ;
+
+ vardef _pmp_left_bottom_hang_ (expr same_area) =
+ pair _ll_, _sa_, _pa_ ;
+ _sa_ := if same_area : llxy[tpos] else : lrcorner multipar fi ;
+ if (par_hang_indent>0) and (par_hang_after>0) and obey_multi_par_hang :
+ _ll_ := (xpart ulcorner multipar, ypart _pmp_snapped_multi_pos_(ulxy[fpos])) ;
+ _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+ if same_area :
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+ fi ;
+ if obey_multi_par_more and (round(par_line_height)>0) :
+ par_hang_after := max(0,round(par_hang_after - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+ fi ;
+ _pa_ --
+ (xpart _pa_ + par_hang_indent,ypart _pa_) --
+ (xpart _pa_ + par_hang_indent,ypart _sa_)
+ else :
+ (xpart llcorner multipar, ypart _sa_)
+ fi
+ enddef ;
+
+ vardef _pmp_right_bottom_hang_ (expr same_area) =
+ pair _lr_, _sa_, _pa_ ;
+ _sa_ := if same_area : _pmp_snapped_multi_pos_(ulxy[tpos]) else : lrcorner multipar fi ;
+ if (par_hang_indent<0) and (par_hang_after>0) and obey_multi_par_hang :
+ _lr_ := (xpart urcorner multipar, ypart _pmp_snapped_multi_pos_(urxy[fpos])) ;
+ _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+ if same_area :
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart _pmp_snapped_multi_pos_(ulxy[tpos]))) ;
+ fi ;
+ if obey_multi_par_more and (round(par_line_height)>0) :
+ par_hang_after := max(0,round(par_hang_after - (ypart urxy[fpos]-ypart _pa_)/par_line_height)) ;
+ fi ;
+ (xpart _pa_ + par_hang_indent,ypart _sa_) --
+ (xpart _pa_ + par_hang_indent,ypart _pa_) --
+ _pa_
+ else :
+ (xpart lrcorner multipar, ypart _sa_)
+ fi
+ enddef ;
+
+ vardef _pmp_x_left_bottom_hang_ (expr i, t) =
+ pair _ll_, _sa_, _pa_ ;
+ _sa_ := if t : llxy[tpos] else : llcorner multipar fi ;
+ if (par_hang_indent>0) and (ra>0) :
+ par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i,t)) ;
+ _ll_ := ulcorner multipar ;
+ _pa_ := _ll_ shifted (0,-par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart llcorner multipar)) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+ % we need to compensate for topskip enlarged areas
+ if abs(ypart _pa_ - ypart _sa_) > par_line_height :
+ (xpart _pa_ + par_hang_indent,ypart _sa_) --
+ (xpart _pa_ + par_hang_indent,ypart _pa_) --
+ fi
+ _pa_
+ else :
+ (xpart llcorner multipar, ypart _sa_)
+ fi
+ enddef ;
+
+ vardef _pmp_x_right_bottom_hang_ (expr i, t) =
+ pair _lr_, _sa_, _pa_ ;
+ _sa_ := if t : _pmp_snapped_multi_pos_(ulxy[tpos]) else : llcorner multipar fi ;
+ if (par_hang_indent<0) and (ra>0) :
+ par_hang_after := max(0,ra - _pmp_estimated_multi_par_height_(i, t)) ;
+ _lr_ := urcorner multipar ;
+ _pa_ := _lr_ shifted (0,-par_hang_after*par_line_height) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart lrcorner multipar)) ;
+ _pa_ := (xpart _pa_,max(ypart _pa_,ypart _sa_)) ;
+ % we need to compensate for topskip enlarged areas
+ _pa_
+ if abs(ypart _pa_ - ypart _sa_) > par_line_height :
+ -- (xpart _pa_ + par_hang_indent,ypart _pa_)
+ -- (xpart _pa_ + par_hang_indent,ypart _sa_)
+ fi
+ else :
+ (xpart lrcorner multipar, ypart _sa_)
+ fi
+ enddef ;
+
+ % def _pmp_test_multipar_ =
+ % multipar := boundingbox multipar ;
+ % enddef ;
+
+ % first loop
+
+ ii := 0 ; nn := NOfTextAreas+1 ; nofmultipars := 0 ;
+
+ if enable_multi_par_fallback and (nxy[fpos]=RealPageNumber)
+ and (nxy[tpos]=RealPageNumber) and not (InsideSomeTextArea(lxy[fpos]) and InsideSomeTextArea(rxy[tpos])) :
+
+ % fallback
+
+ % multipar :=
+ % llxy[fpos] --
+ % lrxy[tpos] --
+ % urxy[tpos] --
+ % ulxy[fpos] -- cycle ;
+ %
+ % save_multipar (1,1,multipar) ;
+
+ % we need to take the boundingbox because there can be
+ % more lines and we want a proper rectange
+
+ multipar :=
+ ulxy[fpos] --
+ urxy[tpos] --
+ lrxy[fpos] --
+ llxy[tpos] -- cycle ;
+
+ save_multipar (1,1,boundingbox(multipar)) ;
+
+ else :
+
+ % normal
+
+ for i=1 upto NOfTextAreas :
+
+ TopSkipCorrection := 0 ;
+
+ multipar := _pmp_set_multipar_(i) ;
+
+ % watch how we compensate for negative indentation
+
+ if (nxy[fpos]=RealPageNumber) and (InsideTextArea(i,par_start_pos)) :
+
+ % first one in chain
+
+ ii := i ;
+
+ if (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) :
+
+ % in same area
+
+ nn := i ;
+
+ if compensate_multi_par_topskip and (round(LineHeight-ph-pd)=0) :
+
+ TopSkipCorrection := TopSkip - StrutHeight ;
+
+ if round(ypart ulxy[fpos] + TopSkipCorrection) = round(ypart ulcorner TextAreas[i]) :
+ ulxy[fpos] := ulxy[fpos] shifted (0,TopSkipCorrection) ;
+ urxy[fpos] := urxy[fpos] shifted (0,TopSkipCorrection) ;
+ else :
+ TopSkipCorrection := 0 ;
+ fi ;
+
+ fi ;
+
+ if ypart llxy[fpos] = ypart llxy[tpos] :
+
+ multipar :=
+ llxy[fpos] --
+ lrxy[tpos] --
+ _pmp_snapped_multi_pos_(urxy[tpos]) --
+ _pmp_snapped_multi_pos_(ulxy[fpos]) --
+ cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ elseif (ypart llxy[fpos] = ypart ulxy[tpos]) and (xpart llxy[tpos] < xpart llxy[fpos]) :
+
+ % two loners
+
+ multipar := if obey_multi_par_hang :
+
+ _pmp_right_bottom_hang_(true) --
+ _pmp_right_top_hang_(true) --
+ _pmp_snapped_multi_pos_(urxy[fpos]) --
+ lrxy[fpos] --
+
+ else :
+
+ llxy[fpos] --
+ (xpart urcorner multipar, ypart llxy[fpos]) --
+ (xpart urcorner multipar, ypart ulxy[fpos]) --
+ _pmp_snapped_multi_pos_(ulxy[fpos]) --
+
+ fi cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ multipar := _pmp_set_multipar_(i) ;
+
+ multipar := if obey_multi_par_hang :
+
+ _pmp_left_bottom_hang_(true) --
+ llxy[tpos] --
+ _pmp_snapped_multi_pos_(ulxy[tpos]) --
+ _pmp_left_top_hang_(true) --
+
+ else :
+
+ (xpart llcorner multipar, ypart llxy[tpos]) --
+ llxy[tpos] --
+ _pmp_snapped_multi_pos_(ulxy[tpos]) --
+ (xpart llcorner multipar, ypart ulxy[tpos]) --
+
+ fi cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ else :
+
+ multipar := if obey_multi_par_hang :
+
+ _pmp_left_bottom_hang_(true) --
+ llxy[tpos] --
+ _pmp_snapped_multi_pos_(ulxy[tpos]) --
+ _pmp_right_bottom_hang_(true) --
+ _pmp_right_top_hang_(true) --
+ _pmp_snapped_multi_pos_(urxy[fpos]) --
+ lrxy[fpos] --
+ _pmp_left_top_hang_(true) --
+
+ else :
+
+ (xpart llcorner multipar, ypart llxy[tpos]) --
+ llxy[tpos] --
+ _pmp_snapped_multi_pos_(ulxy[tpos]) --
+ (xpart lrcorner multipar, ypart ulxy[tpos]) --
+ (xpart urcorner multipar, ypart urxy[fpos]) --
+ _pmp_snapped_multi_pos_(urxy[fpos]) --
+ lrxy[fpos] --
+ (xpart ulcorner multipar, ypart lrxy[fpos]) --
+
+ fi cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ fi ;
+
+ else :
+
+ multipar := if obey_multi_par_hang :
+
+ _pmp_left_bottom_hang_(false) --
+ _pmp_right_bottom_hang_(false) --
+ _pmp_right_top_hang_(false) --
+ _pmp_snapped_multi_pos_(urxy[fpos]) --
+ lrxy[fpos] --
+ _pmp_left_top_hang_(false) --
+
+ else :
+
+ llcorner multipar --
+ lrcorner multipar --
+ (xpart urcorner multipar, ypart urxy[fpos]) --
+ _pmp_snapped_multi_pos_(urxy[fpos]) --
+ lrxy[fpos] --
+ (xpart ulcorner multipar, ypart lrxy[fpos]) --
+
+ fi cycle ;
+
+ save_multipar (i,1,multipar) ;
+
+ fi ;
+
+ elseif (nxy[tpos]=RealPageNumber) and (InsideTextArea(i,par_stop_pos)) :
+
+ % last one in chain
+
+ nn := i ;
+
+ if obey_multi_par_hang and obey_multi_par_more :
+
+ multipar :=
+ _pmp_x_left_top_hang_(i,true) --
+ _pmp_x_right_top_hang_(i,true) --
+ _pmp_x_right_bottom_hang_(i,true) --
+ _pmp_snapped_multi_pos_(ulxy[tpos]) --
+ llxy[tpos] --
+ _pmp_x_left_bottom_hang_(i,true) --
+ cycle ;
+
+ else :
+
+ multipar :=
+ ulcorner multipar --
+ urcorner multipar --
+ (xpart lrcorner multipar, ypart urxy[tpos]) --
+ _pmp_snapped_multi_pos_(ulxy[tpos]) --
+ llxy[tpos] --
+ (xpart llcorner multipar, ypart llxy[tpos]) --
+ cycle ;
+
+ fi ;
+
+ save_multipar (i,3,multipar) ;
+
+ elseif multi_column_first_page_hack and ((nxy[fpos]=RealPageNumber) and (nxy[tpos]>=RealPageNumber) and (NOfTextColumns>1)) :
+
+ save_multipar (i,2,multipar) ;
+
+ else :
+ % handled later
+ fi ;
+
+ endfor ;
+
+
+ % second loop
+
+ if force_multi_par_chain or (ii > 1) :
+
+ for i=ii+1 upto nn-1 :
+
+ % rest of chain / todo : hang
+
+ % hm, the second+ column in column sets now gets lost in a NOfTextColumns
+
+ if (not check_multi_par_chain) or ((nxy[fpos]<RealPageNumber) and (nxy[tpos]>RealPageNumber)) :
+
+ multipar := _pmp_set_multipar_(i) ;
+
+ if obey_multi_par_hang and obey_multi_par_more :
+
+ multipar :=
+ _pmp_x_left_top_hang_(i,false) --
+ _pmp_x_right_top_hang_(i,false) --
+ _pmp_x_right_bottom_hang_(i,false) --
+ _pmp_x_left_bottom_hang_(i,false) --
+ cycle ;
+
+ fi ;
+
+ save_multipar(i,2,multipar) ;
+
+ fi ;
+
+ endfor ;
+
+ fi ;
+
+ % end of normal/fallback
+
+ fi ;
+
+ if span_multi_column_pars :
+ endgroup ;
+ fi ;
+
+ % potential safeguard:
+
+ % for i=1 upto nofmultipars :
+ % if length p <= 4 :
+ % multipars[i] := boundingbox(multipars[i]) ;
+ % fi ;
+ % end ;
+
+ % quick hack for gb:
+
+ one_piece_multi_par := (nofmultipars=1) and (pn=tn) ;
+
+enddef ;
+
+def boxgridoptions = withcolor .8red enddef ;
+def boxlineoptions = withcolor .8blue enddef ;
+def boxfilloptions = withcolor .8white enddef ;
+
+numeric boxgridtype ; boxgridtype := 0 ;
+numeric boxlinetype ; boxlinetype := 1 ;
+numeric boxfilltype ; boxfilltype := 1 ;
+numeric boxdashtype ; boxdashtype := 0 ;
+pair boxgriddirection ; boxgriddirection := up ;
+numeric boxgridwidth ; boxgridwidth := 1pt ;
+numeric boxlinewidth ; boxlinewidth := 1pt ;
+numeric boxlineradius ; boxlineradius := 0pt ;
+numeric boxfilloffset ; boxfilloffset := 0pt ;
+numeric boxgriddistance ; boxgriddistance := .5cm ;
+numeric boxgridshift ; boxgridshift := 0pt ;
+
+def draw_box =
+ draw pxy boxlineoptions withpen pencircle scaled boxlinewidth ;
+ draw lxy -- rxy boxlineoptions withpen pencircle scaled boxgridwidth ;
+enddef ;
+
+def draw_par = % 1 2 3 11 12
+ do_draw_par(pxy) ; do_draw_par(txy) ; do_draw_par(bxy) ;
+ for i = pxy, txy, bxy :
+ if boxgridtype = 1 :
+ boxgriddirection := origin ;
+ draw baseline_grid (i,boxgriddirection,true ) boxgridoptions ;
+ elseif boxgridtype = 2 :
+ boxgriddirection := origin ;
+ draw baseline_grid (i,boxgriddirection,false) boxgridoptions ;
+ elseif boxgridtype = 3 :
+ boxgriddirection := origin ;
+ draw baseline_grid (i,boxgriddirection,true ) boxgridoptions ;
+ draw baseline_grid (i,boxgriddirection,true ) shifted (0,ExHeight) boxgridoptions ;
+ elseif boxgridtype = 4 :
+ boxgriddirection := origin ;
+ draw baseline_grid (i,boxgriddirection,true ) shifted (0,ExHeight/2) boxgridoptions ;
+ elseif boxgridtype = 11 :
+ draw graphic_grid(i,boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+ elseif boxgridtype = 12 :
+ draw graphic_grid(i,boxgriddistance,boxgriddistance,0,0) ;
+ fi ;
+ endfor ;
+enddef ;
+
+def do_show_par (expr p, r, c) =
+ if length(p) > 2 :
+ for i=0 upto length(p) :
+ draw fullcircle scaled r shifted point i of p withpen pencircle scaled .5pt withcolor c ;
+ endfor ;
+ fi ;
+ draw p withpen pencircle scaled .5pt withcolor c ;
+enddef ;
+
+def show_par =
+ if length(mxy) > 2 :
+ draw mxy dashed evenly withpen pencircle scaled .5pt withcolor .5white ;
+ fi ;
+ do_show_par(txy, 4pt, .5green) ;
+ do_show_par(bxy, 6pt, .5blue ) ;
+ do_show_par(pxy, 8pt, .5red ) ;
+ draw pref withpen pencircle scaled 2pt ;
+enddef ;
+
+def sort_multi_pars =
+ if nofmultipars>1 :
+ begingroup ;
+ save _p_, _n_ ; path _p_ ; numeric _n_ ;
+ for i := 1 upto nofmultipars :
+ if multilocs[i] = 3 :
+ _p_ := multipars[nofmultipars] ;
+ multipars[nofmultipars] := multipars[i] ;
+ multipars[i] := _p_ ;
+ _n_ := multirefs[nofmultipars] ;
+ multirefs[nofmultipars] := multirefs[i] ;
+ multirefs[i] := _n_ ;
+ _n_ := multilocs[nofmultipars] ;
+ multilocs[nofmultipars] := multilocs[i] ;
+ multilocs[i] := _n_ ;
+ fi ;
+ endfor ;
+ endgroup ;
+ fi ;
+enddef ;
+
+def collapse_multi_pars =
+ if nofmultipars>1 :
+ begingroup ;
+ save _nofmultipars_ ; numeric _nofmultipars_ ;
+ _nofmultipars_ := 1 ;
+ sort_multi_pars ; % block not in order: 1, 3, 2....
+ for i:=1 upto nofmultipars-1 :
+ if (round(xpart(llcorner multipars[i]-llcorner multipars[i+1]))=0) and
+ (round(xpart(lrcorner multipars[i]-lrcorner multipars[i+1]))=0) :
+ multilocs[_nofmultipars_] := multilocs[i+1] ;
+ multirefs[_nofmultipars_] := multirefs[i+1] ;
+ multipars[_nofmultipars_] :=
+ ulcorner multipars[_nofmultipars_] --
+ urcorner multipars[_nofmultipars_] --
+ lrcorner multipars[i+1] --
+ llcorner multipars[i+1] -- cycle ;
+ else :
+ _nofmultipars_ := _nofmultipars_ + 1 ;
+ multipars[_nofmultipars_] := multipars[i+1] ;
+ multilocs[_nofmultipars_] := multilocs[i+1] ;
+ multirefs[_nofmultipars_] := multirefs[i+1] ;
+ fi ;
+ endfor ;
+ nofmultipars := _nofmultipars_ ;
+ endgroup ;
+ fi ;
+enddef ;
+
+def draw_multi_pars =
+ for i=1 upto nofmultipars :
+ do_draw_par(multipars[i]) ;
+ if boxgridtype= 1 :
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ;
+ elseif boxgridtype= 2 :
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,false) ;
+ elseif boxgridtype= 3 :
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) ;
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight) ;
+ elseif boxgridtype= 4 :
+ draw baseline_grid (multipars[i],if multilocs[i]=1: down else: up fi,true) shifted (0,ExHeight/2) ;
+ elseif boxgridtype=11 :
+ draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,boxgriddistance/2,boxgriddistance/2) ;
+ elseif boxgridtype=12 :
+ draw graphic_grid(multipars[i],boxgriddistance,boxgriddistance,0,0) ;
+ fi ;
+ endfor ;
+enddef ;
+
+def show_multi_pars =
+ for i=1 upto nofmultipars :
+ do_show_par(multipars[i], 6pt, .5blue) ;
+ endfor ;
+enddef ;
+
+vardef do_draw_par (expr p) =
+ if (length p>2) and (bbwidth(p)>1) and (bbheight(p)>1) :
+ save pp ; path pp ;
+ if (boxlineradius>0) and (boxlinetype=2) :
+ pp := p cornered boxlineradius ;
+ else :
+ pp := p ;
+ fi ;
+ if boxfilltype>0 :
+ if boxfilloffset>0 :
+ % temporary hack
+ begingroup ;
+ interim linejoin := mitered ;
+ filldraw pp boxfilloptions withpen pencircle scaled (2*boxfilloffset) ;
+ endgroup ;
+ else :
+ fill pp boxfilloptions ;
+ fi ;
+ fi ;
+ if boxlinetype>0 :
+ draw pp boxlineoptions withpen pencircle scaled boxlinewidth ;
+ fi ;
+ fi ;
+enddef ;
+
+vardef baseline_grid (expr pxy, pdir, at_baseline) =
+ save width ; width := bbwidth(pxy) ;
+ save height ; height := bbheight(pxy) ;
+ if (par_line_height>0) and (height>1) and (width>1) and (boxgridwidth>0) :
+ save i, grid, bb ; picture grid ; pair start ; path bb ;
+ def _do_ (expr start) =
+ % 1 = normal, 2 = with background (i.e. no shine-through)
+ if boxdashtype = 2 :
+ draw start -- start shifted (width,0)
+ withpen pencircle scaled boxgridwidth
+ boxfilloptions ;
+ fi ;
+ draw start -- start shifted (width,0)
+ if boxdashtype > 0 :
+ dashed evenly
+ fi
+ withpen pencircle scaled boxgridwidth
+ boxgridoptions ;
+ enddef ;
+ grid := image ( % fails with inlinespace
+ if pdir=up :
+ for i = if at_baseline : par_strut_depth else : 0 fi step par_line_height until max(height,par_line_height) :
+ _do_ (llcorner pxy shifted (0,+i)) ;
+ endfor ;
+ else :
+ for i = if at_baseline : par_strut_height else : 0 fi step par_line_height until height :
+ _do_ (ulcorner pxy shifted (0,-i)) ;
+ endfor ;
+ fi ;
+ ) ;
+ clip grid to pxy ;
+ bb := boundingbox grid ;
+ grid := grid shifted (0,boxgridshift) ;
+ setbounds grid to bb ;
+ grid
+ else :
+ nullpicture
+ fi
+enddef ;
+
+vardef graphic_grid (expr pxy, dx, dy, x, y) =
+ if (bbheight(pxy)>dy) and (bbwidth(pxy)>dx) and (boxgridwidth>0) :
+ save grid ; picture grid ;
+ grid := image (
+ for i = xpart llcorner pxy step dx until xpart lrcorner pxy :
+ draw (i,ypart llcorner pxy) -- (i,ypart ulcorner pxy) withpen pencircle scaled boxgridwidth ;
+ endfor ;
+ for i = ypart llcorner pxy step dy until ypart ulcorner pxy :
+ draw (xpart llcorner pxy,i) -- (xpart lrcorner pxy,i) withpen pencircle scaled boxgridwidth ;
+ endfor
+ ) shifted (x,y) ;
+ clip grid to pxy ;
+ grid
+ else :
+ nullpicture
+ fi
+enddef ;
+
+def anchor_box (expr n,x,y,w,h,d) =
+ currentpicture := currentpicture shifted (-x,-y) ;
+enddef ;
+
+let draw_area = draw_box ;
+let anchor_area = anchor_box ;
+let anchor_par = anchor_box ;
+
+numeric sync_n[], sync_p[][], sync_w[][], sync_h[][], sync_d[][], sync_t[][] ;
+pair sync_xy[][] ; color sync_c[][] ;
+
+def ResetSyncTasks =
+ path SyncPaths[] ; numeric SyncTasks[], NOfSyncPaths, CurrentSyncClass ;
+ NOfSyncPaths := CurrentSyncClass := 0 ;
+ if unknown SyncLeftOffset : numeric SyncLeftOffset ; SyncLeftOffset := 0 ; fi ;
+ if unknown SyncWidth : numeric SyncWidth ; SyncWidth := 0 ; fi ;
+ if unknown SyncThreshold : numeric SyncThreshold ; SyncThreshold := LineHeight ; fi ;
+ if unknown SyncColor : color SyncColor ; SyncColor := .5white ; fi ;
+ if (SyncLeftOffset = 0) and (SyncWidth = 0) :
+ SyncWidth := if known TextWidth : TextWidth else : -1cm fi ;
+ fi ;
+enddef ;
+
+ResetSyncTasks ;
+
+vardef SyncBox(expr n, i, leftoffset, width, topoffset, bottomoffset) =
+ save o ; pair o ; o := (xpart llcorner PlainTextArea,ypart sync_xy[n][i]) ;
+ o shifted (leftoffset,sync_h[n][i]+topoffset) --
+ o shifted (width+leftoffset,sync_h[n][i]+topoffset) --
+ o shifted (width+leftoffset,bottomoffset) --
+ o shifted (leftoffset,bottomoffset) -- cycle
+enddef ;
+
+def SetSyncColor(expr n, i, c) =
+ sync_c[n][i] := c ;
+enddef ;
+
+def SetSyncThreshold(expr n, i, th) =
+ sync_th[n][i] := th ;
+enddef ;
+
+vardef TheSyncColor(expr n, i) =
+ if known sync_c[n][i] : sync_c[n][i] else : SyncColor fi
+enddef ;
+
+vardef TheSyncThreshold(expr n, i) =
+ if known sync_th[n][i] : sync_th[n][i] else : SyncThreshold fi
+enddef ;
+
+vardef PrepareSyncTasks(expr n, collapse, extendtop, prestartnext) =
+ ResetSyncTasks ;
+ if known sync_n[n] :
+ CurrentSyncClass := n ;
+ save ok, l, d ; boolean ok ; ok := false ; NOfSyncPaths := l := 0 ;
+ for i=1 upto sync_n[n] :
+ if RealPageNumber > sync_p[n][i] :
+ l := i ;
+ elseif RealPageNumber = sync_p[n][i] :
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ if not ok :
+ if i>1 :
+ if sync_t[n][i-1] = sync_t[n][i] :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i-1, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i-1 ;
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ else :
+ SyncPaths[NOfSyncPaths] := SyncBox(n, i, SyncLeftOffset, SyncWidth, 0, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := i ;
+ fi ;
+ ok := true ;
+ fi ;
+ endfor ;
+ if (NOfSyncPaths = 0) and (l > 0) :
+ NOfSyncPaths := 1 ;
+ SyncPaths[NOfSyncPaths] := SyncBox(n, l, SyncLeftOffset, SyncWidth, PaperHeight, -PaperHeight) ;
+ SyncTasks[NOfSyncPaths] := l ;
+ fi ;
+ if NOfSyncPaths > 0 :
+ for i = 1 upto NOfSyncPaths-1 :
+ SyncPaths[i] := topboundary SyncPaths[i] -- reverse topboundary SyncPaths[i+1] -- cycle ;
+ endfor ;
+ if unknown SyncThresholdMethod :
+ numeric SyncThresholdMethod ; SyncThresholdMethod := 2 ;
+ fi ;
+ if extendtop :
+ if SyncThresholdMethod = 1 :
+ if NOfSyncPaths>1 :
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[2]]) ;
+ if (SyncTasks[2]>1) and (d > 0pt) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[2]])) and (sync_p[n][SyncTasks[2]] = RealPageNumber) :
+ SyncPaths[2] := SyncPaths[2] topenlarged PaperHeight ;
+ fi ;
+ fi ;
+ else :
+ for i = 1 upto NOfSyncPaths :
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[i]]) ;
+ if (d > 0) and (d <= TheSyncThreshold(n,sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[i]] = RealPageNumber) :
+ SyncPaths[i] := SyncPaths[i] topenlarged PaperHeight ;
+ fi ;
+ endfor ;
+ fi ;
+ fi ;
+ if prestartnext :
+ if NOfSyncPaths>1 :
+ if SyncTasks[NOfSyncPaths] < sync_n[n] : % there is a next one
+ d := ypart (ulcorner PlainTextArea - sync_xy[n][SyncTasks[NOfSyncPaths]+1]) ;
+ if (d > 0) and (d <= TheSyncThreshold(n, sync_t[n][SyncTasks[i]])) and (sync_p[n][SyncTasks[NOfSyncPaths]+1] = RealPageNumber+1) :
+ SyncPaths[NOfSyncPaths+1] :=
+ (xpart ulcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) --
+ (xpart urcorner SyncPaths[NOfSyncPaths],ypart llcorner PlainTextArea) --
+ lrcorner SyncPaths[NOfSyncPaths] --
+ llcorner SyncPaths[NOfSyncPaths] -- cycle ;
+ SyncTasks[NOfSyncPaths+1] := SyncTasks[NOfSyncPaths]+1 ;
+ NOfSyncPaths := NOfSyncPaths + 1 ;
+ fi ;
+ fi ;
+ fi ;
+ else :
+ if NOfSyncPaths>1 :
+ d := ypart (sync_xy[n][SyncTasks[NOfSyncPaths]] - llcorner PlainTextArea) ;
+ if (d < TheSyncThreshold(n, SyncTasks[NOfSyncPaths])) :
+ NOfSyncPaths := NOfSyncPaths - 1 ;
+ SyncPaths[NOfSyncPaths] := SyncPaths[NOfSyncPaths] bottomenlarged PaperHeight ;
+ fi ;
+ fi ;
+ fi ;
+ if (NOfSyncPaths>1) and collapse :
+ save j ; numeric j ; j := 1 ;
+ for i = 2 upto NOfSyncPaths :
+ if sync_t[n][SyncTasks[i]] = sync_t[n][SyncTasks[j]] :
+ SyncPaths[j] := boundingbox image (draw SyncPaths[i] ; draw SyncPaths[j] ; ) ;
+ SyncTasks[j] := SyncTasks[i] ;
+ else :
+ j := j + 1 ;
+ SyncPaths[j] := SyncPaths[i] ;
+ SyncTasks[j] := SyncTasks[i] ;
+ fi ;
+ endfor ;
+ NOfSyncPaths := j ;
+ fi ;
+ fi ;
+ fi ;
+enddef ;
+
+def SyncTask(expr n) =
+ if known SyncTasks[n] : SyncTasks[n] else : 0 fi
+enddef ;
+
+def FlushSyncTasks =
+ for i = 1 upto NOfSyncPaths :
+ ProcessSyncTask(SyncPaths[i], TheSyncColor(CurrentSyncClass,sync_t[CurrentSyncClass][SyncTasks[i]])) ;
+ endfor ;
+enddef ;
+
+def ProcessSyncTask(expr p, c) =
+ fill p withcolor c ;
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-crop.mpiv b/Master/texmf-dist/metapost/context/base/mp-crop.mpiv
new file mode 100644
index 00000000000..260823e687f
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-crop.mpiv
@@ -0,0 +1,194 @@
+%D \module
+%D [ file=mp-crop.mp,
+%D version=2011.06.23,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=Cropmarks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+if known context_crop : endinput ; fi ;
+
+boolean context_crop ; context_crop := true ;
+
+vardef crop_marks_lines (expr box, length, offset, nx, ny) =
+ save p ; picture p ; save w, h, x, y ; numeric w, h, x, y ;
+ p := image (
+ x := if nx = 0 : 1 else : nx - 1 fi ;
+ y := if ny = 0 : 1 else : ny - 1 fi ;
+ w := bbwidth (box) / x ;
+ h := bbheight(box) / y ;
+ for i=0 upto y :
+ draw ((llcorner box) -- (llcorner box) shifted (-length,0)) shifted (-offset,i*h) ;
+ draw ((lrcorner box) -- (lrcorner box) shifted ( length,0)) shifted ( offset,i*h) ;
+ endfor ;
+ for i=0 upto x :
+ draw ((llcorner box) -- (llcorner box) shifted (0,-length)) shifted (i*w,-offset) ;
+ draw ((ulcorner box) -- (ulcorner box) shifted (0, length)) shifted (i*w, offset) ;
+ endfor ;
+ ) ;
+ setbounds p to box ;
+ p
+enddef ;
+
+vardef crop_marks_cmyk =
+ save p ; picture p ; p := image (
+ fill ulcircle scaled 12.5 withcolor (1,0,0,0) ;
+ fill urcircle scaled 12.5 withcolor (0,1,0,0) ;
+ fill lrcircle scaled 12.5 withcolor (0,0,1,0) ;
+ fill llcircle scaled 12.5 withcolor (0,0,0,1) ;
+ draw (-10,0) -- (10,0) ;
+ draw (0,-10) -- (0,10) ;
+ draw fullcircle scaled 12.5 ;
+ ) ;
+ setbounds p to fullsquare scaled 20 ;
+ p
+enddef ;
+
+vardef crop_marks_gray =
+ save p ; picture p ; p := image (
+ fill ulcircle scaled 12.5 withcolor (0.00) ;
+ fill urcircle scaled 12.5 withcolor (0.25) ;
+ fill lrcircle scaled 12.5 withcolor (0.50) ;
+ fill llcircle scaled 12.5 withcolor (0.75) ;
+ draw (-10,0) -- (10,0) ;
+ draw (0,-10) -- (0,10) ;
+ draw (-6,0) -- (6,0) withcolor white ;
+ draw (0,-6) -- (0,6) withcolor white ;
+ draw fullcircle scaled 12.5 ;
+ ) ;
+ setbounds p to fullsquare scaled 20 ;
+ p
+enddef ;
+
+vardef crop_marks_cmykrgb =
+ save p ; picture p ; p := image (
+ fill ulcircle scaled 15 withcolor (1,0,0) ;
+ fill urcircle scaled 15 withcolor (0,1,0) ;
+ fill lrcircle scaled 15 withcolor (0,0,1) ;
+ fill llcircle scaled 15 withcolor (.5,.5,.5) ;
+ fill ulcircle scaled 10 withcolor (1,0,0,0) ;
+ fill urcircle scaled 10 withcolor (0,1,0,0) ;
+ fill lrcircle scaled 10 withcolor (0,0,1,0) ;
+ fill llcircle scaled 10 withcolor (0,0,0,1) ;
+ draw (-10,0) -- (10,0) ;
+ draw (0,-10) -- (0,10) ;
+ draw fullcircle scaled 10 ;
+ draw fullcircle scaled 15 ;
+ ) ;
+ setbounds p to fullsquare scaled 20 ;
+ p
+enddef ;
+
+vardef crop_color(expr c, h, w, dx, dy, ts) =
+ image (
+ save p ; path p ;
+ for i=1 upto 6 :
+ p := fullsquare
+ xscaled w
+ yscaled h
+ shifted (dx,dy-i*h) ;
+ fill p
+ withcolor (crop_colors[i]*c) ;
+ draw textext("\format{'@0.2f'," & decimal crop_colors[i] & "}")
+ scaled ts
+ shifted center p withcolor white ;
+ endfor ;
+ )
+enddef ;
+
+vardef crop_gray(expr c, h, w, dx, dy, ts) =
+ image (
+ save p ; path p ;
+ for i=.05 step .05 until 1 :
+ p := fullsquare
+ xscaled w
+ yscaled h
+ shifted (20*(i-1)*w+dx,dy) ;
+ fill p
+ withcolor (i*c) ;
+ draw textext("\format{'@0.2f'," & decimal i & "}")
+ scaled ts
+ shifted center p withcolor white ;
+ endfor ;
+ )
+enddef ;
+
+% draw crop_marks_cmyk shifted llcorner more ;
+% draw crop_marks_cmyk shifted lrcorner more ;
+% draw crop_marks_cmyk shifted ulcorner more ;
+% draw crop_marks_cmyk shifted urcorner more ;
+
+def page_marks_add_color(expr width, height, length, offset) = % todo: namespace
+
+ path page ; page := fullsquare xscaled width yscaled height ;
+ path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+ numeric crop_colors[] ;
+ crop_colors[1] := 1 ;
+ crop_colors[2] := 0.95 ;
+ crop_colors[3] := 0.75 ;
+ crop_colors[4] := 0.50 ;
+ crop_colors[5] := 0.25 ;
+ crop_colors[6] := 0.05 ;
+
+ numeric h ; h := height / 20 ;
+ numeric w ; w := width / 20 ;
+ numeric d ; d := offset + length/2 ;
+
+ draw crop_color((1,0,0,0),h,length,xpart ulcorner page - d, 10h,length/20) ;
+ draw crop_color((0,1,0,0),h,length,xpart ulcorner page - d,3.5h,length/20) ;
+ draw crop_color((0,0,1,0),h,length,xpart ulcorner page - d, -3h,length/20) ;
+
+ draw crop_color((0,1,1,0),h,length,xpart urcorner page + d, 10h,length/20) ;
+ draw crop_color((1,0,1,0),h,length,xpart urcorner page + d,3.5h,length/20) ;
+ draw crop_color((1,1,0,0),h,length,xpart urcorner page + d, -3h,length/20) ;
+
+ draw crop_gray((0,0,0,1),length, w,-xpart llcorner page,-ypart llcorner page + d ,w/20) ;
+ draw crop_gray((1,0,0,0),length/3,w,-xpart llcorner page, ypart llcorner page - d + 1length/3,w/20) ;
+ draw crop_gray((0,1,0,0),length/3,w,-xpart llcorner page, ypart llcorner page - d - 0length/3,w/20) ;
+ draw crop_gray((0,0,1,0),length/3,w,-xpart llcorner page, ypart llcorner page - d - 1length/3,w/20) ;
+
+ setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_marking(expr width, height, length, offset) = % todo: namespace
+
+ path page ; page := fullsquare xscaled width yscaled height ;
+ path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+ draw crop_marks_gray shifted center(topboundary more) shifted (0, offset+length);
+ draw crop_marks_cmyk shifted center(bottomboundary more) shifted (0,-offset-length);
+
+ setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_lines(expr width, height, length, offset, nx, ny) = % todo: namespace
+
+ path page ; page := fullsquare xscaled width yscaled height ;
+ path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+ draw crop_marks_lines(page,length,offset,nx,ny) ;
+
+ setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_number(expr width, height, length, offset, n) = % todo: namespace
+
+ path page ; page := fullsquare xscaled width yscaled height ;
+ path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+ for s=llcorner more, lrcorner more, ulcorner more, urcorner more :
+ draw textext(decimal n) shifted s ;
+ endfor ;
+
+ setbounds currentpicture to page ;
+
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-figs.mp b/Master/texmf-dist/metapost/context/base/mp-figs.mpii
index da5fa0d1691..aecdc07e76b 100644
--- a/Master/texmf-dist/metapost/context/base/mp-figs.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-figs.mpii
@@ -1,5 +1,5 @@
%D \module
-%D [ file=mp-tool.mp,
+%D [ file=mp-figs.mp,
%D version=2003.01.15,
%D title=\CONTEXT\ \METAPOST\ graphics,
%D subtitle=figures,
@@ -11,40 +11,37 @@
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
%C details.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_figs : endinput ; fi ;
+if known context_figs : endinput ; fi ;
boolean context_figs ; context_figs := true ;
% todo: check defined
def registerfigure(expr name,width,height) =
- begingroup ;
- save s ; string s ; s := cleanstring(name) ;
- scantokens( s & "_width := " & decimal(width)) ;
- scantokens( s & "_height := " & decimal(height)) ;
- endgroup ;
+ begingroup ;
+ save s ; string s ; s := cleanstring(name) ;
+ scantokens( s & "_width := " & decimal(width )) ;
+ scantokens( s & "_height := " & decimal(height)) ;
+ endgroup ;
enddef ;
vardef figuresize(expr name) =
- save s ; string s ; s := cleanstring(name) ;
- save p ; pair p ;
- scantokens( "p := " & "(" & s & "_width" & "," & s & "_height" & ")" ) ;
- p
+ save s, p ; string s ; pair p ;
+ s := cleanstring(name) ;
+ scantokens( "p := " & "(" & s & "_width" & "," & s & "_height" & ")" ) ;
+ p
enddef ;
vardef figurewidth(expr name) =
- xpart figuresize(name)
+ xpart figuresize(name)
enddef ;
vardef figureheight(expr name) =
- ypart figuresize(name)
+ ypart figuresize(name)
enddef ;
-def figuredimensions = figuresize enddef ; % for old times sake
+let figuredimensions = figuresize ; % for old times sake
def naturalfigure(expr name) =
externalfigure name xyscaled(figuresize(name))
enddef ;
-
-endinput
diff --git a/Master/texmf-dist/metapost/context/base/mp-figs.mpiv b/Master/texmf-dist/metapost/context/base/mp-figs.mpiv
new file mode 100644
index 00000000000..aecdc07e76b
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-figs.mpiv
@@ -0,0 +1,47 @@
+%D \module
+%D [ file=mp-figs.mp,
+%D version=2003.01.15,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=figures,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if known context_figs : endinput ; fi ;
+
+boolean context_figs ; context_figs := true ;
+
+% todo: check defined
+
+def registerfigure(expr name,width,height) =
+ begingroup ;
+ save s ; string s ; s := cleanstring(name) ;
+ scantokens( s & "_width := " & decimal(width )) ;
+ scantokens( s & "_height := " & decimal(height)) ;
+ endgroup ;
+enddef ;
+
+vardef figuresize(expr name) =
+ save s, p ; string s ; pair p ;
+ s := cleanstring(name) ;
+ scantokens( "p := " & "(" & s & "_width" & "," & s & "_height" & ")" ) ;
+ p
+enddef ;
+
+vardef figurewidth(expr name) =
+ xpart figuresize(name)
+enddef ;
+
+vardef figureheight(expr name) =
+ ypart figuresize(name)
+enddef ;
+
+let figuredimensions = figuresize ; % for old times sake
+
+def naturalfigure(expr name) =
+ externalfigure name xyscaled(figuresize(name))
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-fobg.mp b/Master/texmf-dist/metapost/context/base/mp-fobg.mp
index 712efe751aa..f8b709572bb 100644
--- a/Master/texmf-dist/metapost/context/base/mp-fobg.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-fobg.mp
@@ -11,8 +11,7 @@
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
%C details.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_fobg : endinput ; fi ;
+if known context_fobg : endinput ; fi ;
boolean context_fobg ; context_fobg := true ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-form.mp b/Master/texmf-dist/metapost/context/base/mp-form.mpii
index 60ea4cac214..d1dac32db23 100644
--- a/Master/texmf-dist/metapost/context/base/mp-form.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-form.mpii
@@ -15,31 +15,15 @@
boolean mant_font ; mant_font := true ; % signals graph not to load form
-if known mplib :
- boolean fmt_loaded ; fmt_loaded := true ;
- expandafter endinput
-fi ;
-
-if known fmt_loaded : expandafter endinput fi ;
- boolean fmt_loaded ; fmt_loaded := true ;
+if known context_form : endinput ; fi ;
-if unknown fmt_precision :
- numeric fmt_precision ; fmt_precision := 3 ;
-fi ;
-
-if unknown fmt_initialize :
- boolean fmt_initialize ; fmt_initialize := true ;
-fi ;
-
-if unknown fmt_separator :
- string fmt_separator ; fmt_separator := "%" ;
-fi ;
-
-if unknown fmt_zerocheck :
- boolean fmt_zerocheck ; fmt_zerocheck := false ;
-fi ;
+boolean context_form ; context_form := true ;
-boolean fmt_metapost ; fmt_metapost := true ; % == use old method
+if unknown fmt_metapost : boolean fmt_metapost ; fmt_metapost := true ; fi ; % == use old method
+if unknown fmt_precision : numeric fmt_precision ; fmt_precision := 3 ; fi ;
+if unknown fmt_initialize : boolean fmt_initialize ; fmt_initialize := true ; fi ;
+if unknown fmt_separator : string fmt_separator ; fmt_separator := "%" ; fi ;
+if unknown fmt_zerocheck : boolean fmt_zerocheck ; fmt_zerocheck := false ; fi ;
% As said, all clever code is from John, the more stupid
% extensions are mine. The following string variables are
diff --git a/Master/texmf-dist/metapost/context/base/mp-form.mpiv b/Master/texmf-dist/metapost/context/base/mp-form.mpiv
new file mode 100644
index 00000000000..56df0bd63bf
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-form.mpiv
@@ -0,0 +1,30 @@
+%D \module
+%D [ file=mp-form.mp,
+%D version=2011.10.14,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=form support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+% The graph package will be replaced by our own variant using
+% MetaPost 2 features and textext.
+
+if known context_form : endinput ; fi ;
+
+boolean context_form ; context_form := true ;
+
+string Fmfont_ ; Fmfont_ := "crap" ;
+
+% The following function accept a number or string that can be
+% converted to a number by \LUA. The first argument is a format
+% where @ can be used instead of %. The number is typeset in math
+% mode and @3e is converted into @.3e.
+
+vardef mfun_format_number(expr fmt, i) =
+ "\ctxlua{metapost.formatnumber('" & fmt & "'," & if string i : i else : decimal i fi & ")}"
+enddef
diff --git a/Master/texmf-dist/metapost/context/base/mp-func.mp b/Master/texmf-dist/metapost/context/base/mp-func.mp
deleted file mode 100644
index d8646ef3bdd..00000000000
--- a/Master/texmf-dist/metapost/context/base/mp-func.mp
+++ /dev/null
@@ -1,59 +0,0 @@
-%D \module
-%D [ file=mp-func.mp,
-%D version=2001.12.29,
-%D title=\CONTEXT\ \METAPOST\ graphics,
-%D subtitle=function hacks,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
-%C details.
-
-%D Under construction.
-
-if unknown context_tool : input mp-tool ; fi ;
-if known context_func : endinput ; fi ;
-
-boolean context_func ; context_func := true ;
-
-string pathconnectors[] ;
-
-pathconnectors[0] := "," ;
-pathconnectors[1] := "--" ;
-pathconnectors[2] := ".." ;
-pathconnectors[3] := "..." ;
-
-vardef function (expr f) (expr u, t, b, e, s) = save x ; numeric x ;
- for xx := b step s until e :
- hide (x := xx ;) if xx>b : scantokens(pathconnectors[f]) fi
- (scantokens(u),scantokens(t))
- endfor
-enddef ;
-
-def punkedfunction = function (1) enddef ;
-def curvedfunction = function (2) enddef ;
-def tightfunction = function (3) enddef ;
-
-vardef constructedpath (expr f) (text t) =
- save ok ; boolean ok ; ok := false ;
- for i=t :
- if ok : scantokens(pathconnectors[f]) else : ok := true ; fi i
- endfor
-enddef ;
-
-def punkedpath = constructedpath (1) enddef ;
-def curvedpath = constructedpath (2) enddef ;
-def tightpath = constructedpath (3) enddef ;
-
-vardef constructedpairs (expr f) (text p) =
- save i ; i := -1 ;
- forever : exitif unknown p[incr(i)] ;
- if i>0 : scantokens(pathconnectors[f]) fi p[i]
- endfor
-enddef ;
-
-def punkedpairs = constructedpairs (1) enddef ;
-def curvedpairs = constructedpairs (2) enddef ;
-def tightpairs = constructedpairs (3) enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-func.mpii b/Master/texmf-dist/metapost/context/base/mp-func.mpii
new file mode 100644
index 00000000000..407d534e890
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-func.mpii
@@ -0,0 +1,58 @@
+%D \module
+%D [ file=mp-func.mp,
+%D version=2001.12.29,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=function hacks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if known context_func : endinput ; fi ;
+
+boolean context_func ; context_func := true ;
+
+string pathconnectors[] ;
+
+pathconnectors[0] := "," ;
+pathconnectors[1] := "--" ;
+pathconnectors[2] := ".." ;
+pathconnectors[3] := "..." ;
+
+vardef function (expr f) (expr u, t, b, e, s) = save x ; numeric x ;
+ for xx := b step s until e :
+ hide (x := xx ;) if xx>b : scantokens(pathconnectors[f]) fi
+ (scantokens(u),scantokens(t))
+ endfor
+enddef ;
+
+def punkedfunction = function (1) enddef ;
+def curvedfunction = function (2) enddef ;
+def tightfunction = function (3) enddef ;
+
+vardef constructedpath (expr f) (text t) =
+ save ok ; boolean ok ; ok := false ;
+ for i=t :
+ if ok : scantokens(pathconnectors[f]) else : ok := true ; fi i
+ endfor
+enddef ;
+
+def punkedpath = constructedpath (1) enddef ;
+def curvedpath = constructedpath (2) enddef ;
+def tightpath = constructedpath (3) enddef ;
+
+vardef constructedpairs (expr f) (text p) =
+ save i ; i := -1 ;
+ forever : exitif unknown p[incr(i)] ;
+ if i>0 : scantokens(pathconnectors[f]) fi p[i]
+ endfor
+enddef ;
+
+def punkedpairs = constructedpairs (1) enddef ;
+def curvedpairs = constructedpairs (2) enddef ;
+def tightpairs = constructedpairs (3) enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-func.mpiv b/Master/texmf-dist/metapost/context/base/mp-func.mpiv
new file mode 100644
index 00000000000..26037f48cb7
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-func.mpiv
@@ -0,0 +1,78 @@
+%D \module
+%D [ file=mp-func.mp,
+%D version=2001.12.29,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=function hacks,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if known context_func : endinput ; fi ;
+
+boolean context_func ; context_func := true ;
+
+string mfun_pathconnectors[] ;
+
+mfun_pathconnectors[0] := "," ;
+mfun_pathconnectors[1] := "--" ;
+mfun_pathconnectors[2] := ".." ;
+mfun_pathconnectors[3] := "..." ;
+
+def pathconnectors = mfun_pathconnectors enddef ;
+
+vardef mfun_function (expr f) (expr u, t, b, e, s) =
+ save x ; numeric x ;
+ for xx := b step s until e :
+ hide (x := xx ;)
+ if xx > b :
+ scantokens(mfun_pathconnectors[f])
+ fi
+ (scantokens(u),scantokens(t))
+ endfor
+enddef ;
+
+def function = mfun_function enddef ; % let doesn't work here
+def punkedfunction = mfun_function (1) enddef ;
+def curvedfunction = mfun_function (2) enddef ;
+def tightfunction = mfun_function (3) enddef ;
+
+vardef mfun_constructedpath (expr f) (text t) =
+ save ok ; boolean ok ; ok := false ;
+ for i=t :
+ if ok :
+ scantokens(mfun_pathconnectors[f])
+ else :
+ ok := true ;
+ fi
+ i
+ endfor
+enddef ;
+
+def constructedpath = mfun_constructedpath enddef ; % let doesn't work here
+def punkedpath = mfun_constructedpath (1) enddef ;
+def curvedpath = mfun_constructedpath (2) enddef ;
+def tightpath = mfun_constructedpath (3) enddef ;
+
+vardef mfun_constructedpairs (expr f) (text p) =
+ save i ; i := -1 ;
+ forever :
+ exitif unknown p[incr(i)] ;
+ if i>0 :
+ scantokens(mfun_pathconnectors[f])
+ fi
+ p[i]
+ endfor
+enddef ;
+
+def constructedpairs = mfun_constructedpairs enddef ; % let doesn't work here
+def punkedpairs = mfun_constructedpairs (1) enddef ;
+def curvedpairs = mfun_constructedpairs (2) enddef ;
+def tightpairs = mfun_constructedpairs (3) enddef ;
+
+
diff --git a/Master/texmf-dist/metapost/context/base/mp-grid.mp b/Master/texmf-dist/metapost/context/base/mp-grid.mpii
index c87df821cfa..c49fbeec297 100644
--- a/Master/texmf-dist/metapost/context/base/mp-grid.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-grid.mpii
@@ -13,8 +13,7 @@
%D Under construction.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_grid : endinput ; fi ;
+if known context_grid : endinput ; fi ;
boolean context_grid ; context_grid := true ;
@@ -23,7 +22,7 @@ numeric fmt_precision ; fmt_precision := 3 ;
boolean fmt_initialize ; fmt_initialize := false ;
boolean fmt_zerocheck ; fmt_zerocheck := true ;
-if unknown fmt_loaded : input mp-form ; fi ;
+if unknown fmt_loaded : input "mp-form.mpii" ; fi ;
boolean fmt_pictures ; fmt_pictures := true ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-grid.mpiv b/Master/texmf-dist/metapost/context/base/mp-grid.mpiv
new file mode 100644
index 00000000000..e7420e4f663
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-grid.mpiv
@@ -0,0 +1,142 @@
+%D \module
+%D [ file=mp-grid.mp,
+%D version=2000.07.10,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=grid support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if known context_grid : endinput ; fi ;
+
+boolean context_grid ; context_grid := true ;
+
+string fmt_separator ; fmt_separator := "@" ;
+numeric fmt_precision ; fmt_precision := 3 ;
+boolean fmt_initialize ; fmt_initialize := false ;
+boolean fmt_zerocheck ; fmt_zerocheck := true ;
+
+if unknown fmt_loaded : input "mp-form.mpiv" ; fi ;
+
+boolean fmt_pictures ; fmt_pictures := true ;
+
+def do_format = if fmt_pictures : format else : formatstr fi enddef ;
+def do_mformat = if fmt_pictures : Mformat else : Mformatstr fi enddef ;
+
+numeric grid_eps ; grid_eps = eps ;
+
+def hlingrid (expr Min, Max, Step, Length, Width) text t =
+ image (
+ for i=Min step Step until Max+grid_eps :
+ draw (origin--(Width,0)) shifted (0,i*(Length/Max)) t ;
+ endfor ;
+ ) ;
+enddef ;
+
+def vlingrid (expr Min, Max, Step, Length, Height) text t =
+ image (
+ for i=Min step Step until Max+grid_eps :
+ draw (origin--(0,Height)) shifted (i*(Length/Max),0) t ;
+ endfor ;
+ ) ;
+enddef ;
+
+def hloggrid (expr Min, Max, Step, Length, Width) text t =
+ image (
+ for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+ draw (origin--(Width,0)) shifted (0,Length*log(i)) t ;
+ endfor ;
+ ) ;
+enddef ;
+
+def vloggrid (expr Min, Max, Step, Length, Height) text t =
+ image (
+ for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+ draw (origin--(0,Height)) shifted (Length*log(i),0) t ;
+ endfor ;
+ ) ;
+enddef ;
+
+vardef hlintext@#(expr Min, Max, Step, Length, Format) text t =
+ image (
+ for i=Min step Step until Max+grid_eps :
+ draw textext@#(mfun_format_number(Format,i)) shifted (0,i*(Length/Max)) t ;
+ endfor ;
+ )
+enddef ;
+
+vardef vlintext@#(expr Min, Max, Step, Length, Format) text t =
+ image (
+ for i=Min step Step until Max+grid_eps :
+ draw textext@#(mfun_format_number(Format,i)) shifted (i*(Length/Max),0) t ;
+ endfor ;
+ )
+enddef ;
+
+vardef hlogtext@#(expr Min, Max, Step, Length, Format) text t =
+ image (
+ for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+ draw textext@#(mfun_format_number(Format,i)) shifted (0,Length*log(i)) t ;
+ endfor ;
+ )
+enddef ;
+
+vardef vlogtext@#(expr Min, Max, Step, Length, Format) text t =
+ image (
+ for i=max(Min,1) step Step until min(Max,10)+grid_eps :
+ draw textext@#(mfun_format_number(Format,i)) shifted (Length*log(i),0) t ;
+ endfor ;
+ )
+enddef ;
+
+vardef hlinlabel@#(expr Min, Max, Step, Length) text t =
+ image (
+ for i=Min step Step until Max+grid_eps :
+ draw thelabel@#(decimal i,(0,i*(Length/Max))) t ;
+ endfor ;
+ )
+enddef ;
+
+vardef vlinlabel@#(expr Min, Max, Step, Length) text t =
+ image (
+ for i=Min step Step until Max+grid_eps :
+ draw thelabel@#(decimal i,(i*(Length/Max),0)) t ;
+ endfor ;
+ )
+enddef ;
+
+vardef linlog(expr xy) = ( xpart xy, log(ypart xy)) enddef ;
+vardef loglin(expr xy) = (log(xpart xy), ypart xy) enddef ;
+vardef loglog(expr xy) = (log(xpart xy), log(ypart xy)) enddef ;
+vardef linlin(expr xy) = ( (xpart xy), (ypart xy)) enddef ;
+
+vardef loglinpath primary p = processpath (p) (loglin) enddef ;
+vardef linlogpath primary p = processpath (p) (linlog) enddef ;
+vardef loglogpath primary p = processpath (p) (loglog) enddef ;
+vardef linlinpath primary p = processpath (p) (linlin) enddef ;
+
+vardef processpath (expr p) (text pp) =
+ if path p :
+ for i=0 upto length(p)-1 :
+ pp(point i of p) .. controls
+ pp(postcontrol i of p) and
+ pp(precontrol (i+1) of p) ..
+ endfor
+ if cycle p :
+ cycle
+ else :
+ pp(point length(p) of p)
+ fi
+ elseif pair p :
+ pp(p)
+ else :
+ p
+ fi
+enddef ;
+
diff --git a/Master/texmf-dist/metapost/context/base/mp-grph.mp b/Master/texmf-dist/metapost/context/base/mp-grph.mpii
index 3cd9f2cfbda..148d9834a95 100644
--- a/Master/texmf-dist/metapost/context/base/mp-grph.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-grph.mpii
@@ -13,8 +13,7 @@
%D Under construction.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_grph : endinput ; fi ;
+if known context_grph : endinput ; fi ;
boolean context_grph ; context_grph := true ;
@@ -22,13 +21,29 @@ string CRLF ; CRLF := char 10 & char 13 ;
picture _currentpicture_ ;
+numeric _fig_nesting_ ; _fig_nesting_ := 0 ;
+
def beginfig (expr c) =
- begingroup
- charcode := c ;
- resetfig ;
- scantokens extra_beginfig ;
+ _fig_nesting_ := _fig_nesting_ + 1 ;
+ if _fig_nesting_ = 1 :
+ begingroup
+ charcode := c ;
+ resetfig ;
+ scantokens extra_beginfig ;
+ fi ;
enddef ;
+def endfig =
+ ; % safeguard
+ if _fig_nesting_ = 1 :
+ scantokens extra_endfig;
+ shipit ;
+ endgroup ;
+ fi ;
+ _fig_nesting_ := _fig_nesting_ - 1 ;
+enddef;
+
+
def resetfig =
clearxy ;
clearit ;
@@ -275,28 +290,21 @@ def graphictextdirective text t =
graphictextstring := graphictextstring & t & CRLF ;
enddef ;
-endinput
-
% example
-
-input mp-grph ;
-
- graphictextformat := "context" ;
-% graphictextformat := "plain" ;
-% graphictextformat := "latex" ; graphictextdirective "\documentclass[]{article}" ;
-
-beginfig (1) ;
- graphictext
- "\vbox{\hsize10cm \input tufte }"
- scaled 8
- withdrawcolor blue
- withfillcolor red
- withpen pencircle scaled 2pt ;
-endfig ;
-
-beginfig(1) ;
- loadfigure "gracht.mp" rotated 20 ;
- loadfigure "koe.mp" number 1 scaled 2 ;
-endfig ;
-
-end
+%
+% % graphictextformat := "context" ;
+% % graphictextformat := "plain" ;
+%
+% beginfig (1) ;
+% graphictext
+% "\vbox{\hsize10cm \input tufte }"
+% scaled 8
+% withdrawcolor blue
+% withfillcolor red
+% withpen pencircle scaled 2pt ;
+% endfig ;
+%
+% beginfig(1) ;
+% loadfigure "gracht.mp" rotated 20 ;
+% loadfigure "koe.mp" number 1 scaled 2 ;
+% endfig ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-grph.mpiv b/Master/texmf-dist/metapost/context/base/mp-grph.mpiv
new file mode 100644
index 00000000000..3cbe42bdb45
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-grph.mpiv
@@ -0,0 +1,259 @@
+%D \module
+%D [ file=mp-grph.mp,
+%D version=2000.12.14,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=graphic text support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D Under construction.
+
+if known context_grph : endinput ; fi ;
+
+boolean context_grph ; context_grph := true ;
+
+picture _currentpicture_ ;
+
+numeric _fig_nesting_ ; _fig_nesting_ := 0 ;
+
+def beginfig (expr c) =
+ _fig_nesting_ := _fig_nesting_ + 1 ;
+ if _fig_nesting_ = 1 :
+ begingroup
+ charcode := c ;
+ resetfig ;
+ scantokens extra_beginfig ;
+ fi ;
+enddef ;
+
+def endfig =
+ ; % safeguard
+ if _fig_nesting_ = 1 :
+ scantokens extra_endfig ;
+ shipit ;
+ endgroup ;
+ fi ;
+ _fig_nesting_ := _fig_nesting_ - 1 ;
+enddef;
+
+def resetfig =
+ clearxy ;
+ clearit ;
+ clearpen ;
+ pickup defaultpen ;
+ interim linecap := linecap ;
+ interim linejoin := linejoin ;
+ interim miterlimit := miterlimit ;
+ save _background_ ; color _background_ ; _background_ := background ;
+ save background ; color background ; background := _background_ ;
+ drawoptions () ;
+enddef ;
+
+def protectgraphicmacros =
+ save showtext ;
+ save beginfig ; let beginfig = begingraphictextfig ;
+ save endfig ; let endfig = endgraphictextfig ;
+ save end ; let end = relax ;
+ interim prologues := prologues ;
+ resetfig ; % resets currentpicture
+enddef ;
+
+numeric currentgraphictext ; currentgraphictext := 0 ;
+
+def data_mpo_file = job_name & "-mpgraph.mpo" enddef ;
+def data_mpy_file = job_name & "-mpgraph.mpy" enddef ;
+
+def begingraphictextfig (expr n) =
+ foundpicture := n ;
+ scratchpicture := nullpicture ;
+enddef ;
+
+def endgraphictextfig =
+ if foundpicture = currentgraphictext :
+ expandafter endinput
+ else :
+ scratchpicture := nullpicture ;
+ fi ;
+enddef ;
+
+def loadfigure primary filename =
+ doloadfigure (filename)
+enddef ;
+
+def doloadfigure (expr filename) text figureattributes =
+ begingroup ;
+ save figurenumber, figurepicture, number, fixedplace ;
+ numeric figurenumber ; figurenumber := 0 ;
+ boolean figureshift ; figureshift := true ;
+ picture figurepicture ; figurepicture := currentpicture ;
+ def number primary n = hide(figurenumber := n) enddef ;
+ def fixedplace = hide(figureshift := false) enddef ;
+ protectgraphicmacros ;
+ % defaults
+ interim linecap := rounded ;
+ interim linejoin := rounded ;
+ interim miterlimit := 10 ;
+ %
+ currentpicture := nullpicture ;
+ draw fullcircle figureattributes ; % expand number
+ currentpicture := nullpicture ;
+ def beginfig (expr n) =
+ currentpicture := nullpicture ;
+ if (figurenumber=n) or (figurenumber=0) :
+ let endfig = endinput ;
+ fi ;
+ enddef ;
+ let endfig = relax ;
+ readfile(filename) ;
+ if figureshift :
+ currentpicture := currentpicture shifted -llcorner currentpicture ;
+ fi ;
+ addto figurepicture also currentpicture figureattributes ;
+ currentpicture := figurepicture ;
+ endgroup ;
+enddef ;
+
+def graphictext primary t =
+ hide (
+ if mfun_trial_run :
+ let mfun_graphic_text = mfun_no_graphic_text ;
+ else :
+ let mfun_graphic_text = mfun_do_graphic_text ;
+ fi
+ )
+ mfun_graphic_text(t)
+enddef ;
+
+def mfun_do_graphic_text (expr t) =
+ % withprescript "gt_stage=final"
+ begingroup ;
+ save figurepicture ; picture figurepicture ;
+ figurepicture := currentpicture ; currentpicture := nullpicture ;
+ currentgraphictext := currentgraphictext + 1 ;
+ mfun_finish_graphic_text % picks up directives
+enddef ;
+
+def mfun_no_graphic_text (expr t) text rest =
+ draw unitsquare withprescript "gt_stage=trial" withpostscript t
+enddef ;
+
+def mfun_finish_graphic_text text x_op_x =
+ protectgraphicmacros ; % resets currentpicture
+ interim linecap := butt ; % normally rounded
+ interim linejoin := mitered ; % normally rounded
+ interim miterlimit := 10 ; % todo
+ let normalwithshade = withshade ;
+ save foundpicture, scratchpicture, str ;
+ save fill, draw, withshade, reversefill, outlinefill ;
+ save withfillcolor, withdrawcolor ; % quite important
+ numeric foundpicture ; picture scratchpicture ; string str ;
+ def draw expr p =
+ % the first, naive implementation was:
+ % addto scratchpicture doublepath p withpen currentpen ;
+ % but it is better to turn lines into fills
+ addto scratchpicture contour boundingbox
+ image (addto currentpicture doublepath p withpen currentpen) ;
+ enddef ;
+ def fill expr p =
+ addto scratchpicture contour p withpen currentpen ;
+ enddef ;
+ def f_op_f = enddef ; boolean f_color ; f_color := false ;
+ def d_op_d = enddef ; boolean d_color ; d_color := false ;
+ def s_op_s = enddef ; boolean s_color ; s_color := false ;
+ boolean reverse_fill ; reverse_fill := false ;
+ boolean outline_fill ; outline_fill := false ;
+ def reversefill =
+ hide(reverse_fill := true )
+ enddef ;
+ def outlinefill =
+ hide(outline_fill := true )
+ enddef ;
+ def withshade primary c =
+ hide(def s_op_s = normalwithshade c enddef ; s_color := true )
+ enddef ;
+ def withfillcolor primary c =
+ hide(def f_op_f = withcolor c enddef ; f_color := true )
+ enddef ;
+ def withdrawcolor primary c =
+ hide(def d_op_d = withcolor c enddef ; d_color := true )
+ enddef ;
+ scratchpicture := nullpicture ;
+ addto scratchpicture doublepath origin x_op_x ; % pre-roll
+ for i within scratchpicture : % Below here is a dirty tricky test!
+ if (urcorner dashpart i) = origin :
+ outline_fill := false ;
+ fi ;
+ endfor ;
+ scratchpicture := nullpicture ;
+ readfile(data_mpy_file) ;
+ scratchpicture := (scratchpicture shifted -llcorner scratchpicture) scaled (1/10) ;
+ if not d_color and not f_color :
+ d_color := true ;
+ fi
+ if s_color :
+ d_color := false ;
+ f_color := false ;
+ fi ;
+ currentpicture := figurepicture ;
+ if d_color and not reverse_fill :
+ for i within scratchpicture :
+ if f_color and outline_fill :
+ addto currentpicture doublepath pathpart i _op_ x_op_x f_op_f dashed nullpicture ;
+ fi ;
+ if filled i :
+ addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+ fi ;
+ endfor ;
+ fi ;
+ if f_color :
+ for i within scratchpicture :
+ if filled i :
+ addto currentpicture contour pathpart i _op_ x_op_x f_op_f withpen pencircle scaled 0 ;
+ fi ;
+ endfor ;
+ fi ;
+ if d_color and reverse_fill :
+ for i within scratchpicture :
+ if filled i :
+ addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+ fi ;
+ endfor ;
+ fi ;
+ if s_color :
+ for i within scratchpicture :
+ if filled i :
+ addto currentpicture contour pathpart i _op_ x_op_x s_op_s ;
+ fi ;
+ endfor ;
+ else :
+ for i within scratchpicture :
+ if stroked i :
+ addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
+ fi ;
+ endfor ;
+ fi ;
+ endgroup ;
+enddef ;
+
+% example
+%
+% beginfig (1) ;
+% graphictext
+% "\vbox{\hsize10cm \input tufte }"
+% scaled 8
+% withdrawcolor blue
+% withfillcolor red
+% withpen pencircle scaled 2pt ;
+% endfig ;
+%
+% beginfig(1) ;
+% loadfigure "gracht.mp" rotated 20 ;
+% loadfigure "koe.mp" number 1 scaled 2 ;
+% endfig ;
+%
+% end
diff --git a/Master/texmf-dist/metapost/context/base/mp-idea.mpiv b/Master/texmf-dist/metapost/context/base/mp-idea.mpiv
new file mode 100644
index 00000000000..462d9755359
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-idea.mpiv
@@ -0,0 +1,30 @@
+% redpart (1,1,0,0) crashes
+
+% let normalredpart = redpart ;
+% let normalgreenpart = greenpart ;
+% let normalbluepart = bluepart ;
+% let normalcyanpart = cyanpart ;
+% let normalmagentapart = magentapart ;
+% let normalyellowpart = yellowpart ;
+% let normalblackpart = blackpart ;
+
+% vardef redpart expr p = if cmykcolor p : 1 - normalcyanpart p elseif rgbcolor p : normalredpart p else : p fi enddef ;
+% vardef greenpart expr p = if cmykcolor p : 1 - normalmagentapart p elseif rgbcolor p : normalgreenpart p else : p fi enddef ;
+% vardef bluepart expr p = if cmykcolor p : 1 - normalyellowpart p elseif rgbcolor p : normalbluepart p else : p fi enddef ;
+% vardef cyanpart expr p = if cmykcolor p : normalcyanpart p elseif rgbcolor p : 1 - normalredpart p else : p fi enddef ;
+% vardef magentapart expr p = if cmykcolor p : normalmagentapart p elseif rgbcolor p : 1 - normalgreenpart p else : p fi enddef ;
+% vardef yellowpart expr p = if cmykcolor p : normalyellowpart p elseif rgbcolor p : 1 - normalbluepart p else : p fi enddef ;
+% vardef blackpart expr p = if cmykcolor p : normalblackpart p elseif rgbcolor p : 0 else : p fi enddef ;
+
+vardef rcomponent expr p = if rgbcolor p : redpart p elseif cmykcolor p : 1 - cyanpart p else : p fi enddef ;
+vardef gcomponent expr p = if rgbcolor p : greenpart p elseif cmykcolor p : 1 - magentapart p else : p fi enddef ;
+vardef bcomponent expr p = if rgbcolor p : bluepart p elseif cmykcolor p : 1 - yellowpart p else : p fi enddef ;
+vardef ccomponent expr p = if cmykcolor p : cyanpart p elseif rgbcolor p : 1 - redpart p else : p fi enddef ;
+vardef mcomponent expr p = if cmykcolor p : magentapart p elseif rgbcolor p : 1 - greenpart p else : p fi enddef ;
+vardef ycomponent expr p = if cmykcolor p : yellowpart p elseif rgbcolor p : 1 - bluepart p else : p fi enddef ;
+vardef bcomponent expr p = if cmykcolor p : blackpart p elseif rgbcolor p : 0 else : p fi enddef ;
+
+vardef somecolor = (1,1,0,0) enddef ;
+
+fill OverlayBox withcolor (rcomponent somecolor,gcomponent somecolor,bcomponent somecolor) ;
+fill OverlayBox withcolor (ccomponent somecolor,mcomponent somecolor,ycomponent somecolor,bcomponent somecolor) ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-mlib.mp b/Master/texmf-dist/metapost/context/base/mp-mlib.mp
deleted file mode 100644
index 6c7115cb7d4..00000000000
--- a/Master/texmf-dist/metapost/context/base/mp-mlib.mp
+++ /dev/null
@@ -1,533 +0,0 @@
-%D \module
-%D [ file=mp-mlib.mp,
-%D version=2008.03.21,
-%D title=\CONTEXT\ \METAPOST\ graphics,
-%D subtitle=plugins,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
-%C details.
-
-if unknown mplib : endinput ; fi ;
-if known context_mlib : endinput ; fi ;
-
-boolean context_mlib ; context_mlib := true ;
-
-%D Color and transparency
-
-newinternal normaltransparent ; normaltransparent := 1 ;
-newinternal multiplytransparent ; multiplytransparent := 2 ;
-newinternal screentransparent ; screentransparent := 3 ;
-newinternal overlaytransparent ; overlaytransparent := 4 ;
-newinternal softlighttransparent ; softlighttransparent := 5 ;
-newinternal hardlighttransparent ; hardlighttransparent := 6 ;
-newinternal colordodgetransparent ; colordodgetransparent := 7 ;
-newinternal colorburntransparent ; colorburntransparent := 8 ;
-newinternal darkentransparent ; darkentransparent := 9 ;
-newinternal lightentransparent ; lightentransparent := 10 ;
-newinternal differencetransparent ; differencetransparent := 11 ;
-newinternal exclusiontransparent ; exclusiontransparent := 12 ;
-
-vardef transparency_alternative_to_number(expr name) =
- if string name :
- if expandafter known scantokens(name & "transparent") :
- scantokens(name & "transparent")
- else :
- 0
- fi
- elseif name < 13 :
- name
- else :
- 0
- fi
-enddef ;
-
-def spotcolor(expr n, v) =
- 1
- withprescript "sp_name=" & n
- withprescript "sp_value=" & v
-enddef ;
-
-def multitonecolor(expr name, fractions, components, value) =
- 1
- withprescript "sp_name=" & name
- withprescript "sp_fractions=" & decimal fractions
- withprescript "sp_components=" & components
- withprescript "sp_value=" & value
-enddef ;
-
-def transparent(expr alternative, transparency)(text c) =
- c
- withprescript "tr_alternative=" & decimal transparency_alternative_to_number(alternative)
- withprescript "tr_transparency=" & decimal transparency
-enddef ;
-
-def withtransparency(expr alternative, transparency) =
- withprescript "tr_alternative=" & decimal transparency_alternative_to_number(alternative)
- withprescript "tr_transparency=" & decimal transparency
-enddef ;
-
-def cmyk(expr c, m, y, k) =
- (c,m,y,k)
-enddef ;
-
-% Texts
-
-numeric _tt_w_[], _tt_h_[], _tt_d_[] ;
-numeric _tt_n_ ; _tt_n_ := 0 ;
-picture _tt_p_ ; _tt_p_ := nullpicture ;
-boolean _trial_run_ ; _trial_run_ := false ;
-
-def resettextexts =
- _tt_n_ := 0 ;
- _tt_p_ := nullpicture ;
-enddef ;
-
-def flushtextexts =
- addto currentpicture also _tt_p_
-enddef ;
-
-extra_endfig := "flushtextexts;" & extra_endfig;
-extra_beginfig := extra_beginfig & "resettextexts;";
-
-% We collect and flush them all, as we can also have temporary textexts
-% that gets never really flushed but are used for calculations. So, we
-% flush twice: once in location in order to pick up e.g. color properties,
-% and once at the end because we need to flush missing ones.
-
-vardef rawtextext(expr str) =
- if str = "" :
- nullpicture
- elseif _trial_run_ :
- _tt_n_ := _tt_n_ + 1 ;
- addto _tt_p_ doublepath unitsquare
- withprescript "tx_number=" & decimal _tt_n_
- withprescript "tx_stage=extra"
- withpostscript str ;
- image (
- addto currentpicture doublepath unitsquare
- withprescript "tx_number=" & decimal _tt_n_
- withprescript "tx_stage=trial"
- withpostscript str
- )
- else :
- _tt_n_ := _tt_n_ + 1 ;
- if known _tt_d_[_tt_n_] :
- image (
- addto currentpicture doublepath unitsquare
- xscaled _tt_w_[_tt_n_]
- yscaled (_tt_h_[_tt_n_] + _tt_d_[_tt_n_])
- withprescript "tx_number=" & decimal _tt_n_
- withprescript "tx_stage=final"
- ; % withpostscript str ;
- ) shifted (0,-_tt_d_[_tt_n_])
- else :
- image (
- addto currentpicture doublepath unitsquare ;
- )
- fi
- fi
-enddef ;
-
-% More text
-
-pair laboff.d, laboff.dlft, laboff.drt ; % new positional suffixes
-pair laboff.origin, laboff.raw ; % graph mess
-
-laboff.d := laboff ; labxf.d := labxf ; labyf.d := labyf ;
-laboff.dlft := laboff.lft ; labxf.dlft := labxf.lft ; labyf.dlft := labyf.lft ;
-laboff.drt := laboff.rt ; labxf.drt := labxf.rt ; labyf.drt := labyf.rt ;
-
-labtype := 0 ; labtype.lft := 1 ; labtype.rt := 2 ;
-labtype.bot := 3 ; labtype.top := 4 ; labtype.ulft := 5 ;
-labtype.urt := 6 ; labtype.llft := 7 ; labtype.lrt := 8 ;
-labtype.d := 10 ; labtype.dlft := 11 ; labtype.drt := 12 ;
-labtype.origin := 0 ; labtype.raw := 0 ;
-
-% laboff.origin = (infinity,infinity) ; labxf.origin := 0 ; labyf.origin := 0 ;
-% laboff.raw = (infinity,infinity) ; labxf.raw := 0 ; labyf.raw := 0 ;
-
-% todo: thelabel.origin("xxxx",origin) (overflows)
-
-laboff.origin = (0,0) ; labxf.origin := 0 ; labyf.origin := 0 ;
-laboff.raw = (0,0) ; labxf.raw := 0 ; labyf.raw := 0 ;
-
-pair laboff.l ; laboff.l = laboff.lft ;
-pair laboff.r ; laboff.r = laboff.rt ;
-pair laboff.b ; laboff.b = laboff.bot ;
-pair laboff.t ; laboff.t = laboff.top ;
-pair laboff.l_t ; laboff.l_t = laboff.ulft ;
-pair laboff.r_t ; laboff.r_t = laboff.urt ;
-pair laboff.l_b ; laboff.l_b = laboff.llft ;
-pair laboff.r_b ; laboff.r_b = laboff.lrt ;
-pair laboff.t_l ; laboff.t_l = laboff.ulft ;
-pair laboff.t_r ; laboff.t_r = laboff.urt ;
-pair laboff.b_l ; laboff.b_l = laboff.llft ;
-pair laboff.b_r ; laboff.b_r = laboff.lrt ;
-
-numeric labxf.l ; labxf.l = labxf.lft ;
-numeric labxf.r ; labxf.r = labxf.rt ;
-numeric labxf.b ; labxf.b = labxf.bot ;
-numeric labxf.t ; labxf.t = labxf.top ;
-numeric labxf.l_t ; labxf.l_t = labxf.ulft ;
-numeric labxf.r_t ; labxf.r_t = labxf.urt ;
-numeric labxf.l_b ; labxf.l_b = labxf.llft ;
-numeric labxf.r_b ; labxf.r_b = labxf.lrt ;
-numeric labxf.t_l ; labxf.t_l = labxf.ulft ;
-numeric labxf.t_r ; labxf.t_r = labxf.urt ;
-numeric labxf.b_l ; labxf.b_l = labxf.llft ;
-numeric labxf.b_r ; labxf.b_r = labxf.lrt ;
-
-numeric labyf.l ; labyf.l = labyf.lft ;
-numeric labyf.r ; labyf.r = labyf.rt ;
-numeric labyf.b ; labyf.b = labyf.bot ;
-numeric labyf.t ; labyf.t = labyf.top ;
-numeric labyf.l_t ; labyf.l_t = labyf.ulft ;
-numeric labyf.r_t ; labyf.r_t = labyf.urt ;
-numeric labyf.l_b ; labyf.l_b = labyf.llft ;
-numeric labyf.r_b ; labyf.r_b = labyf.lrt ;
-numeric labyf.t_l ; labyf.t_l = labyf.ulft ;
-numeric labyf.t_r ; labyf.t_r = labyf.urt ;
-numeric labyf.b_l ; labyf.b_l = labyf.llft ;
-numeric labyf.b_r ; labyf.b_r = labyf.lrt ;
-
-numeric labtype.l ; labtype.l = labtype.lft ;
-numeric labtype.r ; labtype.r = labtype.rt ;
-numeric labtype.b ; labtype.b = labtype.bot ;
-numeric labtype.t ; labtype.t = labtype.top ;
-numeric labtype.l_t ; labtype.l_t = labtype.ulft ;
-numeric labtype.r_t ; labtype.r_t = labtype.urt ;
-numeric labtype.l_b ; labtype.l_b = labtype.llft ;
-numeric labtype.r_b ; labtype.r_b = labtype.lrt ;
-numeric labtype.t_l ; labtype.t_l = labtype.ulft ;
-numeric labtype.t_r ; labtype.t_r = labtype.urt ;
-numeric labtype.b_l ; labtype.b_l = labtype.llft ;
-numeric labtype.b_r ; labtype.b_r = labtype.lrt ;
-
-vardef thetextext@#(expr p,z) = % adapted copy of thelabel@
- if string p :
- thetextext@#(rawtextext(p),z)
- else :
- p
- if (labtype@# >= 10) : shifted (0,ypart center p) fi
- shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p))
- fi
-enddef ;
-
-vardef textext@#(expr txt) =
- interim labeloffset := textextoffset ;
- if string txt :
- thetextext@#(rawtextext(txt),origin)
- else :
- thetextext@#(txt,origin)
- fi
-enddef ;
-
-% \starttext
-% \startMPpage
-% numeric value ; value = 123 ;
-% label.lft(decimal value,origin) ;
-% draw "oeps" infont defaultfont ;
-% \stopMPpage
-% \stoptext
-
-vardef thelabel@#(expr s, z) =
- save p ; picture p ;
- if picture s :
- p = s ;
- else :
- p = textext("\definedfont[" & defaultfont & "]" & s) scaled defaultscale ;
- fi ;
- p shifted (z + labeloffset*laboff@# - (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p))
-enddef;
-
-let normalinfont = infont ;
-
-primarydef str infont name = % very naughty !
- if name = "" :
- textext(str)
- else :
- textext("\definedfont[" & name & "]" & str)
- fi
-enddef ;
-
-% Shades
-
-newinternal shadefactor ; shadefactor := 1 ;
-pair shadeoffset ; shadeoffset := origin ;
-boolean trace_shades ; trace_shades := false ;
-
-def set_linear_vector (suffix a,b)(expr p,n) =
- if (n=1) : a := llcorner p ; b := urcorner p ;
- elseif (n=2) : a := lrcorner p ; b := ulcorner p ;
- elseif (n=3) : a := urcorner p ; b := llcorner p ;
- elseif (n=4) : a := ulcorner p ; b := lrcorner p ;
- elseif (n=5) : a := .5[ulcorner p,llcorner p] ; b := .5[urcorner p,lrcorner p] ;
- elseif (n=6) : a := .5[llcorner p,lrcorner p] ; b := .5[ulcorner p,urcorner p] ;
- elseif (n=7) : a := .5[lrcorner p,urcorner p] ; b := .5[llcorner p,ulcorner p] ;
- elseif (n=8) : a := .5[urcorner p,ulcorner p] ; b := .5[lrcorner p,llcorner p] ;
- else : a := .5[ulcorner p,llcorner p] ; b := .5[urcorner p,lrcorner p] ;
- fi ;
-enddef ;
-
-def set_circular_vector (suffix ab, r)(expr p,n) =
- if (n=1) : ab := llcorner p ;
- elseif (n=2) : ab := lrcorner p ;
- elseif (n=3) : ab := urcorner p ;
- elseif (n=4) : ab := ulcorner p ;
- else : ab := center p ; r := .5r ;
- fi ;
-enddef ;
-
-def circular_shade (expr p, n, ca, cb) =
- begingroup ;
- save ab, r ; pair ab ; numeric r ;
- r := (xpart lrcorner p - xpart llcorner p) ++ (ypart urcorner p - ypart lrcorner p) ;
- set_circular_vector(ab,r)(p,n) ;
- fill p withcircularshade(ab,ab,0,r,ca,cb) ;
- if trace_shades :
- drawarrow ab -- ab shifted (0,r) withpen pencircle scaled 1pt withcolor .5white ;
- fi ;
- endgroup ;
-enddef ;
-
-def linear_shade (expr p, n, ca, cb) =
- begingroup ;
- save a, b, sh ; pair a, b ;
- set_linear_vector(a,b)(p,n) ;
- fill p withlinearshade(a,b,ca,cb) ;
- if trace_shades :
- drawarrow a -- b withpen pencircle scaled 1pt withcolor .5white ;
- fi ;
- endgroup ;
-enddef ;
-
-def withcircularshade (expr a, b, ra, rb, ca, cb) =
- withprescript "sh_type=circular"
- withprescript "sh_domain=0 1"
- withprescript "sh_factor=" & decimal shadefactor
- withprescript "sh_color_a=" & colordecimals ca
- withprescript "sh_color_b=" & colordecimals cb
- withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset)
- withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset)
- withprescript "sh_radius_a=" & decimal ra
- withprescript "sh_radius_b=" & decimal rb
-enddef ;
-
-def withlinearshade (expr a, b, ca, cb) =
- withprescript "sh_type=linear"
- withprescript "sh_domain=0 1"
- withprescript "sh_factor=" & decimal shadefactor
- withprescript "sh_color_a=" & colordecimals ca
- withprescript "sh_color_b=" & colordecimals cb
- withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset)
- withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset)
-enddef ;
-
-string _defined_cs_pre_[] ; numeric _defined_cs_ ; _defined_cs_:= 0 ;
-string prescript_separator ; prescript_separator := char(13) ;
-
-vardef define_circular_shade (expr a, b, ra, rb, ca, cb) =
- _defined_cs_ := _defined_cs_ + 1 ;
- _defined_cs_pre_ [_defined_cs_] := "sh_type=circular"
- & prescript_separator & "sh_domain=0 1"
- & prescript_separator & "sh_factor=" & decimal shadefactor
- & prescript_separator & "sh_color_a=" & colordecimals ca
- & prescript_separator & "sh_color_b=" & colordecimals cb
- & prescript_separator & "sh_center_a=" & ddecimal (a shifted shadeoffset)
- & prescript_separator & "sh_center_b=" & ddecimal (b shifted shadeoffset)
- & prescript_separator & "sh_radius_a=" & decimal ra
- & prescript_separator & "sh_radius_b=" & decimal rb
- ;
- _defined_cs_
-enddef ;
-
-vardef define_linear_shade (expr a, b, ca, cb) =
- _defined_cs_ := _defined_cs_ + 1 ;
- _defined_cs_pre_ [_defined_cs_] := "sh_type=linear"
- & prescript_separator & "sh_domain=0 1"
- & prescript_separator & "sh_factor=" & decimal shadefactor
- & prescript_separator & "sh_color_a=" & colordecimals ca
- & prescript_separator & "sh_color_b=" & colordecimals cb
- & prescript_separator & "sh_center_a=" & ddecimal (a shifted shadeoffset)
- & prescript_separator & "sh_center_b=" & ddecimal (b shifted shadeoffset)
- ;
- _defined_cs_
-enddef ;
-
-primarydef p withshade sc =
- p withprescript _defined_cs_pre_[sc]
-enddef ;
-
-% vardef predefined_linear_shade (expr p, n, ca, cb) =
-% save a, b, sh ; pair a, b ;
-% set_linear_vector(a,b)(p,n) ;
-% define_linear_shade (a,b,ca,cb)
-% enddef ;
-%
-% vardef predefined_circular_shade (expr p, n, ca, cb) =
-% save ab, r ; pair ab ; numeric r ;
-% r := (xpart lrcorner p - xpart llcorner p) ++ (ypart urcorner p - ypart lrcorner p) ;
-% set_circular_vector(ab,r)(p,n) ;
-% define_circular_shade(ab,ab,0,r,ca,cb)
-% enddef ;
-
-% NEW EXPERIMENTAL CODE
-
-def withlinearshading (expr a, b) =
- withprescript "sh_type=linear"
- withprescript "sh_domain=0 1"
- withprescript "sh_factor=" & decimal shadefactor
- withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset)
- withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset)
-enddef ;
-
-def withcircularshading (expr a, b, ra, rb) =
- withprescript "sh_type=circular"
- withprescript "sh_domain=0 1"
- withprescript "sh_factor=" & decimal shadefactor
- withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset)
- withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset)
- withprescript "sh_radius_a=" & decimal ra
- withprescript "sh_radius_b=" & decimal rb
-enddef ;
-
-def withfromshadecolor expr t =
- withprescript "sh_color=into"
- withprescript "sh_color_a=" & colordecimals t
-enddef ;
-
-def withtoshadecolor expr t =
- withprescript "sh_color=into"
- withprescript "sh_color_b=" & colordecimals t
-enddef ;
-
-def withshading (expr how)(text rest) =
- if how = "linear" :
- withlinearshading(rest)
- elseif how = "circular" :
- withcircularshading(rest)
- else :
- % nothing
- fi
-enddef ;
-
-primarydef a shadedinto b =
- 1
- withprescript "sh_color=into"
- withprescript "sh_color_a=" & colordecimals a
- withprescript "sh_color_b=" & colordecimals b
-enddef ;
-
-% END OF NEW
-
-% Graphic text (we will move code here)
-
-def graphictext primary t =
- if _trial_run_ :
- let dographictextindeed = nographictext ;
- else :
- let dographictextindeed = dographictext ;
- fi
- dographictextindeed(t)
-enddef ;
-
-def dographictext (expr t) =
- % withprescript "gt_stage=final"
- begingroup ;
- save figurepicture ; picture figurepicture ;
- figurepicture := currentpicture ; currentpicture := nullpicture ;
- currentgraphictext := currentgraphictext + 1 ;
- dofinishgraphictext
-enddef ;
-
-def nographictext (expr t) text rest =
- draw unitsquare withprescript "gt_stage=trial" withpostscript t
-enddef ;
-
-% def savegraphictext (expr str) =
-% enddef ;
-
-% def erasegraphictextfile =
-% enddef ;
-
-% Layers
-
-def onlayer primary name =
- withprescript "la_name=" & name
-enddef ;
-
-
-% Figures
-
-% def externalfigure primary filename =
-% doexternalfigure (filename)
-% enddef ;
-%
-% def doexternalfigure (expr filename) text transformation =
-% if true : % a bit incompatible esp scaled 1cm now scaled the natural size
-% draw rawtextext("\externalfigure[" & filename & "]") transformation ;
-% else :
-% draw unitsquare transformation withprescript "fg_name=" & filename ;
-% fi ;
-% enddef ;
-
-def withmask primary filename =
- withprescript "fg_mask=" & filename
-enddef ;
-
-def externalfigure primary filename =
- if false :
- rawtextext("\externalfigure[" & filename & "]")
- else :
- image (
- addto currentpicture doublepath unitsquare
- withprescript "fg_name=" & filename ;
- )
-% unitsquare
-% withpen pencircle scaled 0
-% withprescript "fg_name=" & filename
- fi
-enddef ;
-
-def figure primary filename =
- rawtextext("\externalfigure[" & filename & "]")
-enddef ;
-
-% Positions
-
-def register (expr label, width, height, offset) =
- image (
- addto currentpicture doublepath unitsquare xscaled width yscaled height shifted offset
- withprescript "ps_label=" & label ;
- ) ; % no transformations
-enddef ;
-
-% Housekeeping
-
-extra_beginfig := extra_beginfig & "currentgraphictext := 0 ; " ;
-extra_endfig := extra_endfig & "finishsavingdata ; " ;
-extra_endfig := extra_endfig & "resettextexts ; " ;
-
-boolean cmykcolors ; cmykcolors := true ;
-boolean spotcolors ; spotcolors := true ;
-
-% Bonus
-
-vardef verbatim(expr str) =
- ditto & "\detokenize{" & str & "}" & ditto
-enddef ;
-
-% New
-
-def bitmapimage(expr xresolution, yresolution, data) =
- image (
- addto currentpicture doublepath unitsquare
- withprescript "bm_xresolution=" & decimal xresolution
- withprescript "bm_yresolution=" & decimal yresolution
- withpostscript data ;
- )
-enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-mlib.mpiv b/Master/texmf-dist/metapost/context/base/mp-mlib.mpiv
new file mode 100644
index 00000000000..ef3408198f9
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-mlib.mpiv
@@ -0,0 +1,616 @@
+%D \module
+%D [ file=mp-mlib.mp,
+%D version=2008.03.21,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=plugins,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if unknown mplib : endinput ; fi ;
+if known context_mlib : endinput ; fi ;
+
+boolean context_mlib ; context_mlib := true ;
+
+%D Color and transparency
+%D
+%D Separable:
+
+newinternal normaltransparent ; normaltransparent := 1 ;
+newinternal multiplytransparent ; multiplytransparent := 2 ;
+newinternal screentransparent ; screentransparent := 3 ;
+newinternal overlaytransparent ; overlaytransparent := 4 ;
+newinternal softlighttransparent ; softlighttransparent := 5 ;
+newinternal hardlighttransparent ; hardlighttransparent := 6 ;
+newinternal colordodgetransparent ; colordodgetransparent := 7 ;
+newinternal colorburntransparent ; colorburntransparent := 8 ;
+newinternal darkentransparent ; darkentransparent := 9 ;
+newinternal lightentransparent ; lightentransparent := 10 ;
+newinternal differencetransparent ; differencetransparent := 11 ;
+newinternal exclusiontransparent ; exclusiontransparent := 12 ;
+
+%D Nonseparable:
+
+newinternal huetransparent ; huetransparent := 13 ;
+newinternal saturationtransparent ; saturationtransparent := 14 ;
+newinternal colortransparent ; colortransparent := 15 ;
+newinternal luminositytransparent ; luminositytransparent := 16 ;
+
+vardef transparency_alternative_to_number(expr name) =
+ if string name :
+ if expandafter known scantokens(name & "transparent") :
+ scantokens(name & "transparent")
+ else :
+ 0
+ fi
+ elseif name < 17 :
+ name
+ else :
+ 0
+ fi
+enddef ;
+
+def namedcolor (expr n) =
+ 1
+ withprescript "sp_type=named"
+ withprescript "sp_name=" & n
+enddef ;
+
+def spotcolor(expr n, v) =
+ 1
+ withprescript "sp_type=spot"
+ withprescript "sp_name=" & n
+ withprescript "sp_value=" & v
+enddef ;
+
+def multitonecolor(expr name, fractions, components, value) =
+ 1
+ withprescript "sp_type=multitone"
+ withprescript "sp_name=" & name
+ withprescript "sp_fractions=" & decimal fractions
+ withprescript "sp_components=" & components
+ withprescript "sp_value=" & value
+enddef ;
+
+def transparent(expr alternative, transparency)(text c) =
+ 1 % this permits withcolor x intoshade y
+ withprescript "tr_alternative=" & decimal transparency_alternative_to_number(alternative)
+ withprescript "tr_transparency=" & decimal transparency
+ withcolor c
+enddef ;
+
+def withtransparency(expr alternative, transparency) =
+ withprescript "tr_alternative=" & decimal transparency_alternative_to_number(alternative)
+ withprescript "tr_transparency=" & decimal transparency
+enddef ;
+
+def cmyk(expr c, m, y, k) = % provided for downward compability
+ (c,m,y,k)
+enddef ;
+
+% Texts (todo: better strut ratio, now .7 hardcoded, should be passed)
+
+newinternal textextoffset ; textextoffset := 0 ;
+
+numeric mfun_tt_w[], mfun_tt_h[], mfun_tt_d[] ; % we can consider using colors (less hash space)
+numeric mfun_tt_n ; mfun_tt_n := 0 ;
+picture mfun_tt_p ; mfun_tt_p := nullpicture ;
+boolean mfun_trial_run ; mfun_trial_run := false ;
+
+def mfun_reset_tex_texts =
+ mfun_tt_n := 0 ;
+ mfun_tt_p := nullpicture ;
+enddef ;
+
+def mfun_flush_tex_texts =
+ addto currentpicture also mfun_tt_p
+enddef ;
+
+extra_endfig := "mfun_flush_tex_texts;" & extra_endfig;
+extra_beginfig := extra_beginfig & "mfun_reset_tex_texts;";
+
+% We collect and flush them all, as we can also have temporary textexts
+% that gets never really flushed but are used for calculations. So, we
+% flush twice: once in location in order to pick up e.g. color properties,
+% and once at the end because we need to flush missing ones.
+
+vardef rawtextext(expr str) =
+ if str = "" :
+ nullpicture
+ elseif mfun_trial_run :
+ mfun_tt_n := mfun_tt_n + 1 ;
+ addto mfun_tt_p doublepath unitsquare
+ withprescript "tx_number=" & decimal mfun_tt_n
+ withprescript "tx_stage=extra"
+ withpostscript str ;
+ image (
+ addto currentpicture doublepath unitsquare
+ withprescript "tx_number=" & decimal mfun_tt_n
+ withprescript "tx_stage=trial"
+ withpostscript str
+ )
+ else :
+ mfun_tt_n := mfun_tt_n + 1 ;
+ if known mfun_tt_d[mfun_tt_n] :
+ image (
+ addto currentpicture doublepath unitsquare
+ xscaled mfun_tt_w[mfun_tt_n]
+ yscaled (mfun_tt_h[mfun_tt_n] + mfun_tt_d[mfun_tt_n])
+ withprescript "tx_number=" & decimal mfun_tt_n
+ withprescript "tx_stage=final"
+ ; % withpostscript str ;
+ ) shifted (0,-mfun_tt_d[mfun_tt_n])
+ else :
+ image (
+ addto currentpicture doublepath unitsquare ;
+ )
+ fi
+ fi
+enddef ;
+
+% More text
+
+defaultfont := "Mono" ; % was cmr10, could be lmmono10-regular, but is fed into context anyway
+
+vardef fontsize expr name =
+ save size ; numeric size ;
+ size := bbwidth(textext("\MPfontsizehskip{" & name & "}")) ;
+ if size = 0 :
+ 12pt
+ else :
+ size
+ fi
+enddef ;
+
+pair mfun_laboff ; mfun_laboff := (0,0) ;
+pair mfun_laboff.lft ; mfun_laboff.lft := (-1,0) ;
+pair mfun_laboff.rt ; mfun_laboff.rt := (1,0) ;
+pair mfun_laboff.bot ; mfun_laboff.bot := (0,-1) ;
+pair mfun_laboff.top ; mfun_laboff.top := (0,1) ;
+pair mfun_laboff.ulft ; mfun_laboff.ulft := (-.7,.7) ;
+pair mfun_laboff.urt ; mfun_laboff.urt := (.7,.7) ;
+pair mfun_laboff.llft ; mfun_laboff.llft := -(.7,.7) ;
+pair mfun_laboff.lrt ; mfun_laboff.lrt := (.7,-.7) ;
+
+pair mfun_laboff.d ; mfun_laboff.d := mfun_laboff ;
+pair mfun_laboff.dlft ; mfun_laboff.dlft := mfun_laboff.lft ;
+pair mfun_laboff.drt ; mfun_laboff.drt := mfun_laboff.rt ;
+pair mfun_laboff.origin ; mfun_laboff.origin := origin ;
+pair mfun_laboff.raw ; mfun_laboff.raw := origin ;
+
+pair mfun_laboff.l ; mfun_laboff.l := mfun_laboff.lft ;
+pair mfun_laboff.r ; mfun_laboff.r := mfun_laboff.rt ;
+pair mfun_laboff.b ; mfun_laboff.b := mfun_laboff.bot ;
+pair mfun_laboff.t ; mfun_laboff.t := mfun_laboff.top ;
+pair mfun_laboff.l_t ; mfun_laboff.l_t := mfun_laboff.ulft ;
+pair mfun_laboff.r_t ; mfun_laboff.r_t := mfun_laboff.urt ;
+pair mfun_laboff.l_b ; mfun_laboff.l_b := mfun_laboff.llft ;
+pair mfun_laboff.r_b ; mfun_laboff.r_b := mfun_laboff.lrt ;
+pair mfun_laboff.t_l ; mfun_laboff.t_l := mfun_laboff.ulft ;
+pair mfun_laboff.t_r ; mfun_laboff.t_r := mfun_laboff.urt ;
+pair mfun_laboff.b_l ; mfun_laboff.b_l := mfun_laboff.llft ;
+pair mfun_laboff.b_r ; mfun_laboff.b_r := mfun_laboff.lrt ;
+
+mfun_labxf := 0.5 ;
+mfun_labxf.lft := mfun_labxf.l := 1 ;
+mfun_labxf.rt := mfun_labxf.r := 0 ;
+mfun_labxf.bot := mfun_labxf.b := 0.5 ;
+mfun_labxf.top := mfun_labxf.t := 0.5 ;
+mfun_labxf.ulft := mfun_labxf.l_t := mfun_labxf.t_l := 1 ;
+mfun_labxf.urt := mfun_labxf.r_t := mfun_labxf.t_r := 0 ;
+mfun_labxf.llft := mfun_labxf.l_b := mfun_labxf.b_l := 1 ;
+mfun_labxf.lrt := mfun_labxf.r_b := mfun_labxf.b_r := 0 ;
+
+mfun_labxf.d := mfun_labxf ;
+mfun_labxf.dlft := mfun_labxf.lft ;
+mfun_labxf.drt := mfun_labxf.rt ;
+mfun_labxf.origin := 0 ;
+mfun_labxf.raw := 0 ;
+
+mfun_labyf := 0.5 ;
+mfun_labyf.lft := mfun_labyf.l := 0.5 ;
+mfun_labyf.rt := mfun_labyf.r := 0.5 ;
+mfun_labyf.bot := mfun_labyf.b := 1 ;
+mfun_labyf.top := mfun_labyf.t := 0 ;
+mfun_labyf.ulft := mfun_labyf.l_t := mfun_labyf.t_l := 0 ;
+mfun_labyf.urt := mfun_labyf.r_t := mfun_labyf.t_r := 0 ;
+mfun_labyf.llft := mfun_labyf.l_b := mfun_labyf.b_l := 1 ;
+mfun_labyf.lrt := mfun_labyf.r_b := mfun_labyf.b_r := 1 ;
+
+mfun_labyf.d := mfun_labyf ;
+mfun_labyf.dlft := mfun_labyf.lft ;
+mfun_labyf.drt := mfun_labyf.rt ;
+mfun_labyf.origin := 0 ;
+mfun_labyf.raw := 0 ;
+
+mfun_labtype := 0 ;
+mfun_labtype.lft := mfun_labtype.l := 1 ;
+mfun_labtype.rt := mfun_labtype.r := 2 ;
+mfun_labtype.bot := mfun_labtype.b := 3 ;
+mfun_labtype.top := mfun_labtype.t := 4 ;
+mfun_labtype.ulft := mfun_labtype.l_t := mfun_labtype.t_l := 5 ;
+mfun_labtype.urt := mfun_labtype.r_t := mfun_labtype.t_r := 6 ;
+mfun_labtype.llft := mfun_labtype.l_b := mfun_labtype.b_l := 7 ;
+mfun_labtype.lrt := mfun_labtype.r_b := mfun_labtype.b_r := 8 ;
+mfun_labtype.d := 10 ;
+mfun_labtype.dlft := 11 ;
+mfun_labtype.drt := 12 ;
+mfun_labtype.origin := 0 ;
+mfun_labtype.raw := 0 ;
+
+vardef thetextext@#(expr p,z) =
+ % interim labeloffset := textextoffset ;
+ if string p :
+ thetextext@#(rawtextext(p),z)
+ else :
+ p
+ if (mfun_labtype@# >= 10) :
+ shifted (0,ypart center p)
+ fi
+ shifted (z + textextoffset*mfun_laboff@# - (mfun_labxf@#*lrcorner p + mfun_labyf@#*ulcorner p + (1-mfun_labxf@#-mfun_labyf@#)*llcorner p))
+ fi
+enddef ;
+
+vardef textext@#(expr p) = % no draw hers
+ thetextext@#(p,origin)
+enddef ;
+
+vardef thelabel@#(expr p,z) =
+ if string p :
+ thelabel@#(rawtextext("\definedfont[" & defaultfont & "]" & p) scaled defaultscale,z)
+ else :
+ p shifted (z + labeloffset*mfun_laboff@# - (mfun_labxf@#*lrcorner p + mfun_labyf@#*ulcorner p + (1-mfun_labxf@#-mfun_labyf@#)*llcorner p))
+ fi
+enddef;
+
+def label = % takes two arguments, contrary to textext that takes one
+ draw thelabel
+enddef ;
+
+vardef anchored@#(expr p, z) = % beware: no "+ mfun_laboff@#" here (never!)
+ p
+ if (mfun_labtype@# >= 10) :
+ shifted (0,ypart center p)
+ fi
+ shifted (z + (mfun_labxf@#*lrcorner p + mfun_labyf@#*ulcorner p + (1-mfun_labxf@#-mfun_labyf@#)*llcorner p))
+enddef ;
+
+let normalinfont = infont ;
+
+primarydef str infont name = % nasty hack
+ if name = "" :
+ textext(str)
+ else :
+ textext("\definedfont[" & name & "]" & str)
+ fi
+enddef ;
+
+% Shades
+
+newinternal shadefactor ; shadefactor := 1 ;
+pair shadeoffset ; shadeoffset := origin ;
+boolean trace_shades ; trace_shades := false ;
+
+def set_linear_vector (suffix a,b)(expr p,n) =
+ if (n=1) : a := llcorner p ; b := urcorner p ;
+ elseif (n=2) : a := lrcorner p ; b := ulcorner p ;
+ elseif (n=3) : a := urcorner p ; b := llcorner p ;
+ elseif (n=4) : a := ulcorner p ; b := lrcorner p ;
+ elseif (n=5) : a := .5[ulcorner p,llcorner p] ; b := .5[urcorner p,lrcorner p] ;
+ elseif (n=6) : a := .5[llcorner p,lrcorner p] ; b := .5[ulcorner p,urcorner p] ;
+ elseif (n=7) : a := .5[lrcorner p,urcorner p] ; b := .5[llcorner p,ulcorner p] ;
+ elseif (n=8) : a := .5[urcorner p,ulcorner p] ; b := .5[lrcorner p,llcorner p] ;
+ else : a := .5[ulcorner p,llcorner p] ; b := .5[urcorner p,lrcorner p] ;
+ fi ;
+enddef ;
+
+def set_circular_vector (suffix ab, r)(expr p,n) =
+ if (n=1) : ab := llcorner p ;
+ elseif (n=2) : ab := lrcorner p ;
+ elseif (n=3) : ab := urcorner p ;
+ elseif (n=4) : ab := ulcorner p ;
+ else : ab := center p ; r := .5r ;
+ fi ;
+enddef ;
+
+def circular_shade (expr p, n, ca, cb) =
+ begingroup ;
+ save ab, r ; pair ab ; numeric r ;
+ r := (xpart lrcorner p - xpart llcorner p) ++ (ypart urcorner p - ypart lrcorner p) ;
+ set_circular_vector(ab,r)(p,n) ;
+ fill p withcircularshade(ab,ab,0,r,ca,cb) ;
+ if trace_shades :
+ drawarrow ab -- ab shifted (0,r) withpen pencircle scaled 1pt withcolor .5white ;
+ fi ;
+ endgroup ;
+enddef ;
+
+def linear_shade (expr p, n, ca, cb) =
+ begingroup ;
+ save a, b, sh ; pair a, b ;
+ set_linear_vector(a,b)(p,n) ;
+ fill p withlinearshade(a,b,ca,cb) ;
+ if trace_shades :
+ drawarrow a -- b withpen pencircle scaled 1pt withcolor .5white ;
+ fi ;
+ endgroup ;
+enddef ;
+
+def withcircularshade (expr a, b, ra, rb, ca, cb) =
+ withprescript "sh_type=circular"
+ withprescript "sh_domain=0 1"
+ withprescript "sh_factor=" & decimal shadefactor
+ withprescript "sh_color_a=" & colordecimals ca
+ withprescript "sh_color_b=" & colordecimals cb
+ withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset)
+ withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset)
+ withprescript "sh_radius_a=" & decimal ra
+ withprescript "sh_radius_b=" & decimal rb
+enddef ;
+
+def withlinearshade (expr a, b, ca, cb) =
+ withprescript "sh_type=linear"
+ withprescript "sh_domain=0 1"
+ withprescript "sh_factor=" & decimal shadefactor
+ withprescript "sh_color_a=" & colordecimals ca
+ withprescript "sh_color_b=" & colordecimals cb
+ withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset)
+ withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset)
+enddef ;
+
+string mfun_defined_cs_pre[] ; numeric mfun_defined_cs ; mfun_defined_cs := 0 ;
+
+string mfun_prescript_separator ; mfun_prescript_separator := char(13) ;
+
+vardef define_circular_shade (expr a, b, ra, rb, ca, cb) =
+ mfun_defined_cs := mfun_defined_cs + 1 ;
+ mfun_defined_cs_pre[mfun_defined_cs] := "sh_type=circular"
+ & mfun_prescript_separator & "sh_domain=0 1"
+ & mfun_prescript_separator & "sh_factor=" & decimal shadefactor
+ & mfun_prescript_separator & "sh_color_a=" & colordecimals ca
+ & mfun_prescript_separator & "sh_color_b=" & colordecimals cb
+ & mfun_prescript_separator & "sh_center_a=" & ddecimal (a shifted shadeoffset)
+ & mfun_prescript_separator & "sh_center_b=" & ddecimal (b shifted shadeoffset)
+ & mfun_prescript_separator & "sh_radius_a=" & decimal ra
+ & mfun_prescript_separator & "sh_radius_b=" & decimal rb
+ ;
+ mfun_defined_cs
+enddef ;
+
+vardef define_linear_shade (expr a, b, ca, cb) =
+ mfun_defined_cs := mfun_defined_cs + 1 ;
+ mfun_defined_cs_pre[mfun_defined_cs] := "sh_type=linear"
+ & mfun_prescript_separator & "sh_domain=0 1"
+ & mfun_prescript_separator & "sh_factor=" & decimal shadefactor
+ & mfun_prescript_separator & "sh_color_a=" & colordecimals ca
+ & mfun_prescript_separator & "sh_color_b=" & colordecimals cb
+ & mfun_prescript_separator & "sh_center_a=" & ddecimal (a shifted shadeoffset)
+ & mfun_prescript_separator & "sh_center_b=" & ddecimal (b shifted shadeoffset)
+ ;
+ mfun_defined_cs
+enddef ;
+
+primarydef p withshade sc =
+ p withprescript mfun_defined_cs_pre[sc]
+enddef ;
+
+
+vardef define_sampled_linear_shade(expr a,b,n)(text t) =
+ mfun_defined_cs := mfun_defined_cs + 1 ;
+ mfun_defined_cs_pre[mfun_defined_cs] := "ssh_type=linear"
+ & mfun_prescript_separator & "ssh_center_a=" & ddecimal (a shifted shadeoffset)
+ & mfun_prescript_separator & "ssh_center_b=" & ddecimal (b shifted shadeoffset)
+ & mfun_prescript_separator & "ssh_nofcolors=" & decimal n
+ & mfun_prescript_separator & "ssh_domain=" & domstr
+ & mfun_prescript_separator & "ssh_extend=" & extstr
+ & mfun_prescript_separator & "ssh_colors=" & colstr
+ & mfun_prescript_separator & "ssh_bounds=" & bndstr
+ & mfun_prescript_separator & "ssh_ranges=" & ranstr
+ ;
+ mfun_defined_cs
+enddef ;
+
+vardef define_sampled_circular_shade(expr a,b,ra,rb,n)(text t) =
+ mfun_defined_cs := mfun_defined_cs + 1 ;
+ mfun_defined_cs_pre[mfun_defined_cs] := "ssh_type=circular"
+ & mfun_prescript_separator & "ssh_center_a=" & ddecimal (a shifted shadeoffset)
+ & mfun_prescript_separator & "ssh_radius_a=" & decimal ra
+ & mfun_prescript_separator & "ssh_center_b=" & ddecimal (b shifted shadeoffset)
+ & mfun_prescript_separator & "ssh_radius_b=" & decimal rb
+ & mfun_prescript_separator & "ssh_nofcolors=" & decimal n
+ & mfun_prescript_separator & "ssh_domain=" & domstr
+ & mfun_prescript_separator & "ssh_extend=" & extstr
+ & mfun_prescript_separator & "ssh_colors=" & colstr
+ & mfun_prescript_separator & "ssh_bounds=" & bndstr
+ & mfun_prescript_separator & "ssh_ranges=" & ranstr
+ ;
+ mfun_defined_cs
+enddef ;
+
+% vardef predefined_linear_shade (expr p, n, ca, cb) =
+% save a, b, sh ; pair a, b ;
+% set_linear_vector(a,b)(p,n) ;
+% define_linear_shade (a,b,ca,cb)
+% enddef ;
+%
+% vardef predefined_circular_shade (expr p, n, ca, cb) =
+% save ab, r ; pair ab ; numeric r ;
+% r := (xpart lrcorner p - xpart llcorner p) ++ (ypart urcorner p - ypart lrcorner p) ;
+% set_circular_vector(ab,r)(p,n) ;
+% define_circular_shade(ab,ab,0,r,ca,cb)
+% enddef ;
+
+% NEW EXPERIMENTAL CODE
+
+def withlinearshading (expr a, b) =
+ withprescript "sh_type=linear"
+ withprescript "sh_domain=0 1"
+ withprescript "sh_factor=" & decimal shadefactor
+ withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset)
+ withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset)
+enddef ;
+
+def withcircularshading (expr a, b, ra, rb) =
+ withprescript "sh_type=circular"
+ withprescript "sh_domain=0 1"
+ withprescript "sh_factor=" & decimal shadefactor
+ withprescript "sh_center_a=" & ddecimal (a shifted shadeoffset)
+ withprescript "sh_center_b=" & ddecimal (b shifted shadeoffset)
+ withprescript "sh_radius_a=" & decimal ra
+ withprescript "sh_radius_b=" & decimal rb
+enddef ;
+
+def withfromshadecolor expr t =
+ withprescript "sh_color=into"
+ withprescript "sh_color_a=" & colordecimals t
+enddef ;
+
+def withtoshadecolor expr t =
+ withprescript "sh_color=into"
+ withprescript "sh_color_b=" & colordecimals t
+enddef ;
+
+def withshading (expr how)(text rest) =
+ if how = "linear" :
+ withlinearshading(rest)
+ elseif how = "circular" :
+ withcircularshading(rest)
+ else :
+ % nothing
+ fi
+enddef ;
+
+primarydef a shadedinto b =
+ 1 % does not work with transparency
+ withprescript "sh_color=into"
+ withprescript "sh_color_a=" & colordecimals a
+ withprescript "sh_color_b=" & colordecimals b
+enddef ;
+
+% Layers
+
+def onlayer primary name =
+ withprescript "la_name=" & name
+enddef ;
+
+% Figures
+
+% def externalfigure primary filename =
+% doexternalfigure (filename)
+% enddef ;
+%
+% def doexternalfigure (expr filename) text transformation =
+% if true : % a bit incompatible esp scaled 1cm now scaled the natural size
+% draw rawtextext("\externalfigure[" & filename & "]") transformation ;
+% else :
+% draw unitsquare transformation withprescript "fg_name=" & filename ;
+% fi ;
+% enddef ;
+
+def withmask primary filename =
+ withprescript "fg_mask=" & filename
+enddef ;
+
+def externalfigure primary filename =
+ if false :
+ rawtextext("\externalfigure[" & filename & "]")
+ else :
+ image (
+ addto currentpicture doublepath unitsquare
+ withprescript "fg_name=" & filename ;
+ )
+% unitsquare
+% withpen pencircle scaled 0
+% withprescript "fg_name=" & filename
+ fi
+enddef ;
+
+def figure primary filename =
+ rawtextext("\externalfigure[" & filename & "]")
+enddef ;
+
+% Positions
+
+def register (expr label, width, height, offset) =
+% draw image (
+ addto currentpicture doublepath unitsquare xscaled width yscaled height shifted offset
+ withprescript "ps_label=" & label ;
+% ) ; % no transformations
+enddef ;
+
+% Housekeeping
+
+extra_beginfig := extra_beginfig & "currentgraphictext := 0 ; " ;
+extra_endfig := extra_endfig & "finishsavingdata ; " ;
+extra_endfig := extra_endfig & "mfun_reset_tex_texts ; " ;
+
+% Bonus
+
+vardef verbatim(expr str) =
+ ditto & "\detokenize{" & str & "}" & ditto
+enddef ;
+
+% New
+
+def bitmapimage(expr xresolution, yresolution, data) =
+ image (
+ addto currentpicture doublepath unitsquare
+ withprescript "bm_xresolution=" & decimal xresolution
+ withprescript "bm_yresolution=" & decimal yresolution
+ withpostscript data ;
+ )
+enddef ;
+
+% TODO:
+
+let property = picture ;
+
+vardef properties(text t) =
+ image(draw unitcircle t)
+enddef ;
+
+def withproperties expr p =
+ if colormodel p = 3 :
+ withcolor greypart p
+ elseif colormodel p = 5 :
+ withcolor (redpart p,greenpart p,bluepart p)
+ elseif colormodel p = 7 :
+ withcolor (cyanpart p,magentapart p,yellowpart p,blackpart p)
+ fi
+ % todo, when available in mp:
+ %
+ % withprescript prescript p
+ % withpostscript postscript p
+ %
+ % todo, penpart
+enddef ;
+
+% property p ; p = properties(withcolor (1,1,0,1)) ;
+% fill fullcircle scaled 20cm withproperties p ;
+
+% Experimental:
+
+primarydef t asgroup s = % s = isolated|knockout
+ begingroup
+ save grouppicture, wrappedpicture, groupbounds ;
+ picture grouppicture, wrappedpicture ; path groupbounds ;
+ grouppicture := if picture t : t else : image(draw t) fi ;
+ groupbounds := boundingbox grouppicture ;
+ wrappedpicture:= nullpicture ;
+ addto wrappedpicture contour groupbounds
+ withprescript "gr_state=start"
+ withprescript "gr_type=" & s
+ withprescript "gr_llx=" & decimal xpart llcorner groupbounds
+ withprescript "gr_lly=" & decimal ypart llcorner groupbounds
+ withprescript "gr_urx=" & decimal xpart urcorner groupbounds
+ withprescript "gr_ury=" & decimal ypart urcorner groupbounds ;
+ addto wrappedpicture also grouppicture ;
+ addto wrappedpicture contour groupbounds
+ withprescript "gr_state=stop" ;
+ wrappedpicture
+ endgroup
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-page.mp b/Master/texmf-dist/metapost/context/base/mp-page.mpii
index 59d8bccbcd7..c7542a5f989 100644
--- a/Master/texmf-dist/metapost/context/base/mp-page.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-page.mpii
@@ -14,8 +14,7 @@
%D This module is rather preliminary and subjected to
%D changes.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_page : endinput ; fi ;
+if known context_page : endinput ; fi ;
boolean context_page ; context_page := true ;
@@ -402,6 +401,8 @@ enddef ;
def StartPage =
+ begingroup ;
+
if PageStateAvailable :
LoadPageState ;
SwapPageState ;
@@ -416,6 +417,8 @@ def StopPage =
BoundPageAreas ;
+ endgroup ;
+
enddef ;
def OverlayBox =
@@ -475,4 +478,182 @@ def position_anchor_bar(expr p_b_self, p_e_self, y_b_self, y_e_self, h_b_self, d
StopPage ;
enddef ;
-endinput ;
+% Crop stuff
+
+vardef crop_marks_lines (expr box, length, offset, nx, ny) =
+ save p ; picture p ; save w, h, x, y ; numeric w, h, x, y ;
+ p := image (
+ x := if nx = 0 : 1 else : nx - 1 fi ;
+ y := if ny = 0 : 1 else : ny - 1 fi ;
+ w := bbwidth (box) / x ;
+ h := bbheight(box) / y ;
+ for i=0 upto y :
+ draw ((llcorner box) -- (llcorner box) shifted (-length,0)) shifted (-offset,i*h) ;
+ draw ((lrcorner box) -- (lrcorner box) shifted ( length,0)) shifted ( offset,i*h) ;
+ endfor ;
+ for i=0 upto x :
+ draw ((llcorner box) -- (llcorner box) shifted (0,-length)) shifted (i*w,-offset) ;
+ draw ((ulcorner box) -- (ulcorner box) shifted (0, length)) shifted (i*w, offset) ;
+ endfor ;
+ ) ;
+ setbounds p to box ;
+ p
+enddef ;
+
+vardef crop_marks_cmyk =
+ save p ; picture p ; p := image (
+ fill ulcircle scaled 12.5 withcolor (1,0,0,0) ;
+ fill urcircle scaled 12.5 withcolor (0,1,0,0) ;
+ fill lrcircle scaled 12.5 withcolor (0,0,1,0) ;
+ fill llcircle scaled 12.5 withcolor (0,0,0,1) ;
+ draw (-10,0) -- (10,0) ;
+ draw (0,-10) -- (0,10) ;
+ draw fullcircle scaled 12.5 ;
+ ) ;
+ setbounds p to fullsquare scaled 20 ;
+ p
+enddef ;
+
+vardef crop_marks_gray =
+ save p ; picture p ; p := image (
+ fill ulcircle scaled 12.5 withcolor (0.00) ;
+ fill urcircle scaled 12.5 withcolor (0.25) ;
+ fill lrcircle scaled 12.5 withcolor (0.50) ;
+ fill llcircle scaled 12.5 withcolor (0.75) ;
+ draw (-10,0) -- (10,0) ;
+ draw (0,-10) -- (0,10) ;
+ draw (-6,0) -- (6,0) withcolor white ;
+ draw (0,-6) -- (0,6) withcolor white ;
+ draw fullcircle scaled 12.5 ;
+ ) ;
+ setbounds p to fullsquare scaled 20 ;
+ p
+enddef ;
+
+vardef crop_marks_cmykrgb =
+ save p ; picture p ; p := image (
+ fill ulcircle scaled 15 withcolor (1,0,0) ;
+ fill urcircle scaled 15 withcolor (0,1,0) ;
+ fill lrcircle scaled 15 withcolor (0,0,1) ;
+ fill llcircle scaled 15 withcolor (.5,.5,.5) ;
+ fill ulcircle scaled 10 withcolor (1,0,0,0) ;
+ fill urcircle scaled 10 withcolor (0,1,0,0) ;
+ fill lrcircle scaled 10 withcolor (0,0,1,0) ;
+ fill llcircle scaled 10 withcolor (0,0,0,1) ;
+ draw (-10,0) -- (10,0) ;
+ draw (0,-10) -- (0,10) ;
+ draw fullcircle scaled 10 ;
+ draw fullcircle scaled 15 ;
+ ) ;
+ setbounds p to fullsquare scaled 20 ;
+ p
+enddef ;
+
+vardef crop_color(expr c, h, w, dx, dy, ts) =
+ image (
+ save p ; path p ;
+ for i=1 upto 6 :
+ p := fullsquare
+ xscaled w
+ yscaled h
+ shifted (dx,dy-i*h) ;
+ fill p
+ withcolor (crop_colors[i]*c) ;
+ draw textext("\format{'@0.2f'," & decimal crop_colors[i] & "}")
+ scaled ts
+ shifted center p withcolor white ;
+ endfor ;
+ )
+enddef ;
+
+vardef crop_gray(expr c, h, w, dx, dy, ts) =
+ image (
+ save p ; path p ;
+ for i=.05 step .05 until 1 :
+ p := fullsquare
+ xscaled w
+ yscaled h
+ shifted (20*(i-1)*w+dx,dy) ;
+ fill p
+ withcolor (i*c) ;
+ draw textext("\format{'@0.2f'," & decimal i & "}")
+ scaled ts
+ shifted center p withcolor white ;
+ endfor ;
+ )
+enddef ;
+
+% draw crop_marks_cmyk shifted llcorner more ;
+% draw crop_marks_cmyk shifted lrcorner more ;
+% draw crop_marks_cmyk shifted ulcorner more ;
+% draw crop_marks_cmyk shifted urcorner more ;
+
+def page_marks_add_color(expr width, height, length, offset) = % todo: namespace
+
+ path page ; page := fullsquare xscaled width yscaled height ;
+ path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+ numeric crop_colors[] ;
+ crop_colors[1] := 1 ;
+ crop_colors[2] := 0.95 ;
+ crop_colors[3] := 0.75 ;
+ crop_colors[4] := 0.50 ;
+ crop_colors[5] := 0.25 ;
+ crop_colors[6] := 0.05 ;
+
+ numeric h ; h := height / 20 ;
+ numeric w ; w := width / 20 ;
+ numeric d ; d := offset + length/2 ;
+
+ draw crop_color((1,0,0,0),h,length,xpart ulcorner page - d, 10h,length/20) ;
+ draw crop_color((0,1,0,0),h,length,xpart ulcorner page - d,3.5h,length/20) ;
+ draw crop_color((0,0,1,0),h,length,xpart ulcorner page - d, -3h,length/20) ;
+
+ draw crop_color((0,1,1,0),h,length,xpart urcorner page + d, 10h,length/20) ;
+ draw crop_color((1,0,1,0),h,length,xpart urcorner page + d,3.5h,length/20) ;
+ draw crop_color((1,1,0,0),h,length,xpart urcorner page + d, -3h,length/20) ;
+
+ draw crop_gray((0,0,0,1),length, w,-xpart llcorner page,-ypart llcorner page + d ,w/20) ;
+ draw crop_gray((1,0,0,0),length/3,w,-xpart llcorner page, ypart llcorner page - d + 1length/3,w/20) ;
+ draw crop_gray((0,1,0,0),length/3,w,-xpart llcorner page, ypart llcorner page - d - 0length/3,w/20) ;
+ draw crop_gray((0,0,1,0),length/3,w,-xpart llcorner page, ypart llcorner page - d - 1length/3,w/20) ;
+
+ setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_marking(expr width, height, length, offset) = % todo: namespace
+
+ path page ; page := fullsquare xscaled width yscaled height ;
+ path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+ draw crop_marks_gray shifted center(topboundary more) shifted (0, offset+length);
+ draw crop_marks_cmyk shifted center(bottomboundary more) shifted (0,-offset-length);
+
+ setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_lines(expr width, height, length, offset, nx, ny) = % todo: namespace
+
+ path page ; page := fullsquare xscaled width yscaled height ;
+ path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+ draw crop_marks_lines(page,length,offset,nx,ny) ;
+
+ setbounds currentpicture to page ;
+
+enddef ;
+
+def page_marks_add_number(expr width, height, length, offset, n) = % todo: namespace
+
+ path page ; page := fullsquare xscaled width yscaled height ;
+ path more ; more := page enlarged (offset+length/2,offset+length/2) ;
+
+ for s=llcorner more, lrcorner more, ulcorner more, urcorner more :
+ draw textext(decimal n) shifted s ;
+ endfor ;
+
+ setbounds currentpicture to page ;
+
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-page.mpiv b/Master/texmf-dist/metapost/context/base/mp-page.mpiv
new file mode 100644
index 00000000000..bb8218be5d3
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-page.mpiv
@@ -0,0 +1,322 @@
+%D \module
+%D [ file=mp-page.mp,
+%D version=1999.03.10,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=page enhancements,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 rather preliminary and subjected to
+%D changes.
+
+if known context_page : endinput ; fi ;
+
+boolean context_page ; context_page := true ;
+
+if unknown PageStateAvailable :
+ boolean PageStateAvailable ;
+ PageStateAvailable := false ;
+fi ;
+
+if unknown OnRightPage :
+ boolean OnRightPage ;
+ OnRightPage := true ;
+fi ;
+
+if unknown OnOddPage :
+ boolean OnOddPage ;
+ OnOddPage := true ;
+fi ;
+
+if unknown InPageBody :
+ boolean InPageBody ;
+ InPageBody := false ;
+fi ;
+
+string CurrentLayout ;
+
+CurrentLayout := "default" ;
+
+PageNumber := 0 ;
+PaperHeight := 845.04684pt ;
+PaperWidth := 597.50787pt ;
+PrintPaperHeight := 845.04684pt ;
+PrintPaperWidth := 597.50787pt ;
+TopSpace := 71.12546pt ;
+BottomSpace := 0.0pt ;
+BackSpace := 71.13275pt ;
+CutSpace := 0.0pt ;
+MakeupHeight := 711.3191pt ;
+MakeupWidth := 426.78743pt ;
+TopHeight := 0.0pt ;
+TopDistance := 0.0pt ;
+HeaderHeight := 56.90294pt ;
+HeaderDistance := 0.0pt ;
+TextHeight := 597.51323pt ;
+FooterDistance := 0.0pt ;
+FooterHeight := 56.90294pt ;
+BottomDistance := 0.0pt ;
+BottomHeight := 0.0pt ;
+LeftEdgeWidth := 0.0pt ;
+LeftEdgeDistance := 0.0pt ;
+LeftMarginWidth := 75.58197pt ;
+LeftMarginDistance := 11.99829pt ;
+TextWidth := 426.78743pt ;
+RightMarginDistance := 11.99829pt ;
+RightMarginWidth := 75.58197pt ;
+RightEdgeDistance := 0.0pt ;
+RightEdgeWidth := 0.0pt ;
+
+PageOffset := 0.0pt ;
+PageDepth := 0.0pt ;
+
+LayoutColumns := 0 ;
+LayoutColumnDistance:= 0.0pt ;
+LayoutColumnWidth := 0.0pt ;
+
+LeftEdge := -4 ; Top := -40 ;
+LeftEdgeSeparator := -3 ; TopSeparator := -30 ;
+LeftMargin := -2 ; Header := -20 ;
+LeftMarginSeparator := -1 ; HeaderSeparator := -10 ;
+Text := 0 ; Text := 0 ;
+RightMarginSeparator := +1 ; FooterSeparator := +10 ;
+RightMargin := +2 ; Footer := +20 ;
+RightEdgeSeparator := +3 ; BottomSeparator := +30 ;
+RightEdge := +4 ; Bottom := +40 ;
+
+Margin := LeftMargin ; % obsolete
+Edge := LeftEdge ; % obsolete
+InnerMargin := RightMargin ; % obsolete
+InnerEdge := RightEdge ; % obsolete
+OuterMargin := LeftMargin ; % obsolete
+OuterEdge := LeftEdge ; % obsolete
+
+InnerMarginWidth := 0pt ;
+OuterMarginWidth := 0pt ;
+InnerMarginDistance := 0pt ;
+OuterMarginDistance := 0pt ;
+
+InnerEdgeWidth := 0pt ;
+OuterEdgeWidth := 0pt ;
+InnerEdgeDistance := 0pt ;
+OuterEdgeDistance := 0pt ;
+
+path Area [][] ; pair Location [][] ; path Field [][] ; path Page ;
+numeric HorPos ; numeric Hstep [] ; numeric Hsize [] ;
+numeric VerPos ; numeric Vstep [] ; numeric Vsize [] ;
+
+for VerPos=Top step 10 until Bottom:
+ for HorPos=LeftEdge step 1 until RightEdge:
+ Area[HorPos][VerPos] := origin--cycle ;
+ Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
+ Location[HorPos][VerPos] := origin ;
+ Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+ Field[HorPos][VerPos] := origin--cycle ;
+ Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+ endfor ;
+endfor ;
+
+% def LoadPageState =
+% scantokens "input mp-state.tmp" ;
+% enddef ;
+
+def SwapPageState =
+ if not OnRightPage :
+ BackSpace := PaperWidth-MakeupWidth-BackSpace ;
+ CutSpace := PaperWidth-MakeupWidth-CutSpace ;
+ i := LeftMarginWidth ;
+ LeftMarginWidth := RightMarginWidth ;
+ RightMarginWidth := i ;
+ i := LeftMarginDistance ;
+ LeftMarginDistance := RightMarginDistance ;
+ RightMarginDistance := i ;
+ i := LeftEdgeWidth ;
+ LeftEdgeWidth := RightEdgeWidth ;
+ RightEdgeWidth := i ;
+ i := LeftEdgeDistance ;
+ LeftEdgeDistance := RightEdgeDistance ;
+ RightEdgeDistance := i ;
+
+ % these are now available as ..Width and ..Distance
+
+ Margin := LeftMargin ;
+ Edge := LeftEdge ;
+ InnerMargin := RightMargin ;
+ InnerEdge := RightEdge ;
+ OuterMargin := LeftMargin ;
+ OuterEdge := LeftEdge ;
+ else :
+ Margin := RightMargin ;
+ Edge := RightEdge ;
+ InnerMargin := LeftMargin ;
+ InnerEdge := LeftEdge ;
+ OuterMargin := RightMargin ;
+ OuterEdge := RightEdge ;
+ fi ;
+enddef ;
+
+def SetPageAreas =
+
+ numeric Vsize[], Hsize[], Vstep[], Hstep[] ;
+
+ Vsize[Top] = TopHeight ;
+ Vsize[TopSeparator] = TopDistance ;
+ Vsize[Header] = HeaderHeight ;
+ Vsize[HeaderSeparator] = HeaderDistance ;
+ Vsize[Text] = TextHeight ;
+ Vsize[FooterSeparator] = FooterDistance ;
+ Vsize[Footer] = FooterHeight ;
+ Vsize[BottomSeparator] = BottomDistance ;
+ Vsize[Bottom] = BottomHeight ;
+
+ Vstep[Top] = Vstep[TopSeparator] +Vsize[TopSeparator] ;
+ Vstep[TopSeparator] = PaperHeight-TopSpace ;
+ Vstep[Header] = Vstep[TopSeparator] -Vsize[Header] ;
+ Vstep[HeaderSeparator] = Vstep[Header] -Vsize[HeaderSeparator] ;
+ Vstep[Text] = Vstep[HeaderSeparator]-Vsize[Text] ;
+ Vstep[FooterSeparator] = Vstep[Text] -Vsize[FooterSeparator] ;
+ Vstep[Footer] = Vstep[FooterSeparator]-Vsize[Footer] ;
+ Vstep[BottomSeparator] = Vstep[Footer] -Vsize[BottomSeparator] ;
+ Vstep[Bottom] = Vstep[BottomSeparator]-Vsize[Bottom] ;
+
+ Hsize[LeftEdge] = LeftEdgeWidth ;
+ Hsize[LeftEdgeSeparator] = LeftEdgeDistance ;
+ Hsize[LeftMargin] = LeftMarginWidth ;
+ Hsize[LeftMarginSeparator] = LeftMarginDistance ;
+ Hsize[Text] = MakeupWidth ;
+ Hsize[RightMarginSeparator] = RightMarginDistance ;
+ Hsize[RightMargin] = RightMarginWidth ;
+ Hsize[RightEdgeSeparator] = RightEdgeDistance ;
+ Hsize[RightEdge] = RightEdgeWidth ;
+
+ Hstep[LeftEdge] = Hstep[LeftEdgeSeparator] -Hsize[LeftEdge] ;
+ Hstep[LeftEdgeSeparator] = Hstep[LeftMargin] -Hsize[LeftEdgeSeparator] ;
+ Hstep[LeftMargin] = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ;
+ Hstep[LeftMarginSeparator] = Hstep[Text] -Hsize[LeftMarginSeparator] ;
+ Hstep[Text] = BackSpace ;
+ Hstep[RightMarginSeparator] = Hstep[Text] +Hsize[Text] ;
+ Hstep[RightMargin] = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ;
+ Hstep[RightEdgeSeparator] = Hstep[RightMargin] +Hsize[RightMargin] ;
+ Hstep[RightEdge] = Hstep[RightEdgeSeparator] +Hsize[RightEdgeSeparator] ;
+
+ for VerPos=Top step 10 until Bottom:
+ for HorPos=LeftEdge step 1 until RightEdge:
+ Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ;
+ Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
+ Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ;
+ Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
+ Field[HorPos][VerPos] := Area[HorPos][VerPos] shifted Location[HorPos][VerPos] ;
+ Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
+ endfor ;
+ endfor ;
+
+ Page := unitsquare xscaled PaperWidth yscaled PaperHeight ;
+
+enddef ;
+
+def BoundPageAreas =
+ % pickup pencircle scaled 0pt ;
+ bboxmargin := 0 ; setbounds currentpicture to Page ;
+enddef ;
+
+def StartPage =
+ begingroup ;
+ if PageStateAvailable :
+ LoadPageState ;
+ SwapPageState ;
+ fi ;
+ SetPageAreas ;
+ BoundPageAreas ;
+enddef ;
+
+def StopPage =
+ BoundPageAreas ;
+ endgroup ;
+enddef ;
+
+% cover pages
+
+def BoundCoverAreas =
+ % todo: add cropmarks
+ bboxmargin := 0 ; setbounds currentpicture to Paper enlarged PaperBleed ;
+enddef ;
+
+def SetCoverAreas =
+
+ if unknown SpineWidth :
+ SpineWidth := 8mm ;
+ fi ;
+
+ if unknown PaperBleed :
+ PaperBleed := 0 ;
+ fi ;
+
+ FrontPageWidth := PaperWidth ;
+ BackPageWidth := PaperWidth ;
+ PaperWidth := 2 * PaperWidth + SpineWidth ;
+
+ FrontPageHeight := PaperHeight ;
+ BackPageHeight := PaperHeight ;
+ PaperHeight := PaperHeight ;
+ SpineHeight := PaperHeight ;
+
+ path Paper ; Paper := unitsquare xscaled PaperWidth yscaled PaperHeight ;
+ path Spine ; Spine := unitsquare xscaled SpineWidth yscaled PaperHeight shifted (BackPageWidth,0);
+ path BackPage ; BackPage := unitsquare xscaled BackPageWidth yscaled PaperHeight ;
+ path FrontPage ; FrontPage := unitsquare xscaled FrontPageWidth yscaled PaperHeight shifted (BackPageWidth+SpineWidth,0) ;
+
+enddef ;
+
+
+def StartCover =
+ begingroup ;
+ if PageStateAvailable :
+ LoadPageState ;
+ % SwapPageState ;
+ fi ;
+ SetPageAreas ;
+ SetCoverAreas ;
+ BoundCoverAreas ;
+enddef ;
+
+def StopCover =
+ BoundCoverAreas ;
+ endgroup ;
+enddef ;
+
+% overlays:
+
+def OverlayBox =
+ (unitsquare xyscaled (OverlayWidth,OverlayHeight))
+enddef ;
+
+% handy
+
+def innerenlarged =
+ hide(LoadPageState)
+ if OnRightPage : leftenlarged else : rightenlarged fi
+enddef ;
+
+def outerenlarged =
+ hide(LoadPageState)
+ if OnRightPage : rightenlarged else : leftenlarged fi
+enddef ;
+
+% obsolete
+
+def llEnlarged (expr p,d) = (llcorner p shifted (-d,-d)) enddef ;
+def lrEnlarged (expr p,d) = (lrcorner p shifted (+d,-d)) enddef ;
+def urEnlarged (expr p,d) = (urcorner p shifted (+d,+d)) enddef ;
+def ulEnlarged (expr p,d) = (ulcorner p shifted (-d,+d)) enddef ;
+
+def Enlarged (expr p, d) =
+ (llEnlarged (p,d) --
+ lrEnlarged (p,d) --
+ urEnlarged (p,d) --
+ ulEnlarged (p,d) -- cycle)
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-shap.mp b/Master/texmf-dist/metapost/context/base/mp-shap.mp
deleted file mode 100644
index 0f5fe431d99..00000000000
--- a/Master/texmf-dist/metapost/context/base/mp-shap.mp
+++ /dev/null
@@ -1,307 +0,0 @@
-%D \module
-%D [ file=mp-shap.mp,
-%D version=2000.05.31,
-%D title=\CONTEXT\ \METAPOST\ graphics,
-%D subtitle=shapes,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
-%C details.
-
-if unknown context_tool : input mp-tool ; fi ;
-if known context_shap : endinput ; fi ;
-
-boolean context_shap ; context_shap := true ;
-
-vardef some_shape_path (expr type) =
-
- begingroup ;
-
- save border, xradius, yradius,
- normal, mirror, rotate,
- lc, rc, tc, bc, ll, lr, ur, ul,
- llx, lrx, urx, ulx, lly, lry, ury, uly ;
-
- path border ;
-
- xradius := .15 ; xxradius := .10 ;
- yradius := .15 ; yyradius := .10 ;
-
- pair ll ; ll := llcorner (unitsquare shifted (-.5,-.5)) ;
- pair lr ; lr := lrcorner (unitsquare shifted (-.5,-.5)) ;
- pair ur ; ur := urcorner (unitsquare shifted (-.5,-.5)) ;
- pair ul ; ul := ulcorner (unitsquare shifted (-.5,-.5)) ;
-
- pair llx ; llx := ll shifted (xradius,0) ;
- pair lly ; lly := ll shifted (0,yradius) ;
-
- pair lrx ; lrx := lr shifted (-xradius,0) ;
- pair lry ; lry := lr shifted (0,yradius) ;
-
- pair urx ; urx := ur shifted (-xradius,0) ;
- pair ury ; ury := ur shifted (0,-yradius) ;
-
- pair ulx ; ulx := ul shifted (xradius,0) ;
- pair uly ; uly := ul shifted (0,-yradius) ;
-
- pair llxx ; llxx := ll shifted (xxradius,0) ;
- pair llyy ; llyy := ll shifted (0,yyradius) ;
-
- pair lrxx ; lrxx := lr shifted (-xxradius,0) ;
- pair lryy ; lryy := lr shifted (0,yyradius) ;
-
- pair urxx ; urxx := ur shifted (-xxradius,0) ;
- pair uryy ; uryy := ur shifted (0,-yyradius) ;
-
- pair ulxx ; ulxx := ul shifted (xxradius,0) ;
- pair ulyy ; ulyy := ul shifted (0,-yyradius) ;
-
- pair lc ; lc := ll shifted (0,.5) ;
- pair rc ; rc := lr shifted (0,.5) ;
- pair tc ; tc := ul shifted (.5,0) ;
- pair bc ; bc := ll shifted (.5,0) ;
-
- def mirror (expr p) =
- p rotatedaround(origin,180)
- enddef ;
-
- def normal (expr p ) =
- p
- enddef ;
-
- def rotate (expr p) =
- p rotated 45
- enddef ;
-
- if type= 0 :
- border := normal (origin--cycle) ;
-
- elseif type= 5 :
- border := normal (llx--lrx{right}...rc...{left}urx--ulx{left}...lc...{right}cycle) ;
- elseif type= 6 :
- border := normal (ll--lrx{right}...rc...{left}urx--ul--cycle) ;
- elseif type= 7 :
- border := mirror (ll--lrx{right}...rc...{left}urx--ul--cycle) ;
- elseif type= 8 :
- border := normal (lr--ury{up}...tc...{down}uly--ll--cycle) ;
- elseif type= 9 :
- border := mirror (lr--ury{up}...tc...{down}uly--ll--cycle) ;
- elseif type=10 :
- border := normal (ll--lr--ur--ul--ll--ur--ul--ll--cycle) ;
- elseif type=11 :
- border := normal (ll--lr--ur--ul--ll--lr--ul--ll--cycle) ;
- elseif type=12 :
- border := normal (ll--lrx--ur--ulx--cycle) ;
- elseif type=13 :
- border := normal (llx--lr--urx--ul--cycle) ;
- elseif type=14 :
- border := normal (lly--bc--lry--ury--tc--uly--cycle) ;
- elseif type=15 :
- border := normal (llx--lrx--rc--urx--ulx--lc--cycle) ;
- elseif type=16 :
- border := normal (ll--lrx--rc--urx--ul--cycle) ;
- elseif type=17 :
- border := mirror (ll--lrx--rc--urx--ul--cycle) ;
- elseif type=18 :
- border := normal (lr--ury--tc--uly--ll--cycle) ;
- elseif type=19 :
- border := mirror (lr--ury--tc--uly--ll--cycle) ;
- elseif type=20 :
- border := normal (ll--lr--ur--ul--ll--llxx--ulxx--ul--ll--
- lr--ur--urxx--lrxx--cycle) ;
- elseif type=21 :
- border := normal (ul--ll--lr--ur--ul--ulyy--uryy--ur--ul--
- ll--lr--lryy--llyy--cycle) ;
- elseif type=22 :
- border := normal (ll--lrx--lry--ur--ulx--uly--cycle) ;
- elseif type=23 :
- border := normal (llx--lr--ury--urx--ul--lly--cycle) ;
- elseif type=24 :
- border := normal (ll--lr--ur--ul--cycle) ;
- elseif type=25 :
- border := normal (llx--lrx--lry--ury--urx--ulx--uly--lly--cycle) ;
- elseif type=26 :
- border := normal (ll--lrx--lry--ur--ul--cycle) ;
- elseif type=27 :
- border := mirror (ll--lr--ury--urx--ul--cycle) ;
- elseif type=28 :
- border := normal (ll--lr--ury--urx--ul--cycle) ;
- elseif type=29 :
- border := mirror (ll--lrx--lry--ur--ul--cycle) ;
- elseif type=30 :
- border := rotate (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc &
- bc--tc & tc{left}..{down}lc & lc--rc &
- rc{up}..tc{left}...{down}lc...{right}bc & cycle) ;
- elseif type=31 :
- border := normal (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc &
- bc--tc & tc{left}..{down}lc & lc--rc &
- rc{up}..tc{left}...{down}lc...{right}bc & cycle) ;
- elseif type=32 :
- border := normal (ll{right}...{right}lry--ur--ul--ll--cycle) ;
- elseif type=33 :
- border := normal (ll{right}...{right}lry--ur--ul--ll--cycle
- --ul--ulx--ulx shifted(0,yyradius)
- --ur shifted(yyradius,yyradius)
- --lry shifted(yyradius,yyradius)
- --lry shifted(0,yyradius)
- --ur--ul--cycle ) ;
- elseif type=34 :
- border := normal (uly..tc..ury &
- ury..tc shifted (0,-2yradius)..uly &
- uly--lly &
- lly..bc..lry &
- lry--ury &
- ury..tc shifted (0,-2yradius)..uly & cycle ) ;
- elseif type=35 :
- border := normal (bc{right}...rc{up}...tc{left}...lc{down}...cycle) ;
- elseif type=36 :
- border := normal (ul--tc{right}..rc{down}..{left}bc--ll &
- ll..(xpart llx, ypart lc)..ul & cycle) ;
- elseif type=37 :
- border := mirror (ul--tc{right}..rc{down}..{left}bc--ll &
- ll..(xpart llx, ypart lc)..ul & cycle) ;
- elseif type=38 :
- border := normal (ll--lc{up}..tc{right}..{down}rc--lr &
- lr..(xpart bc, ypart lly)..ll & cycle) ;
- elseif type=39 :
- border := mirror (ll--lc{up}..tc{right}..{down}rc--lr &
- lr..(xpart bc, ypart lly)..ll & cycle) ;
- elseif type=40 :
- border := normal (ll--lr--ur--ul--ll--ur--ul--ll--lr--ul--ll--cycle) ;
- elseif type=41 :
- border := normal (ll--lr--ur--ul--ll--lr--rc--lc--ll--bc--tc--ul--ll & cycle) ;
- elseif type=42 :
- border := normal (ll--lr--origin shifted (+epsilon,0)--
- ur--ul--origin shifted (-epsilon,0)--cycle) ;
- elseif type=43 :
- border := normal (ll--ul--origin shifted (0,+epsilon)--
- ur--lr--origin shifted (0,-epsilon)--cycle) ;
- elseif type=45 :
- border := normal (bc--rc--tc--lc--cycle) ;
- elseif type=46 :
- border := normal (ll--ul--rc--cycle) ;
- elseif type=47 :
- border := mirror (ll--ul--rc--cycle) ;
- elseif type=48 :
- border := mirror (ul--ur--bc--cycle) ;
- elseif type=49 :
- border := normal (ul--ur--bc--cycle) ;
-
- elseif type=56 :
- border := normal (ll--lry--ury--ul--cycle) ;
- elseif type=57 :
- border := mirror (ll--lry--ury--ul--cycle) ;
- elseif type=58 :
- border := normal (ll--ulx--urx--lr--cycle) ;
- elseif type=59 :
- border := mirror (ll--ulx--urx--lr--cycle) ;
-
- elseif type=61 :
- border := normal (fullcircle scaled (1.5*yradius) xscaled (grid_height/grid_width)) ;
- elseif type=62 :
- border := normal (fullcircle scaled (2.0*yradius) xscaled (grid_height/grid_width)) ;
-
- elseif type=66 :
- border := normal (rc--origin shifted ( epsilon,0) --cycle &
- rc--origin --cycle ) ;
- elseif type=67 :
- border := normal (lc--origin shifted (-epsilon,0) --cycle &
- lc--origin --cycle ) ;
- elseif type=68 :
- border := normal (tc--origin shifted (0, epsilon) --cycle &
- tc--origin --cycle ) ;
- elseif type=69 :
- border := normal (bc--origin shifted (0,-epsilon) --cycle &
- bc--origin --cycle ) ;
-
- elseif type=75 :
- border := mirror (lly--lry--ury--uly--cycle) ;
- elseif type=76 :
- border := mirror (ll--lr--ur--uly--cycle) ;
- elseif type=77 :
- border := mirror (ll--lr--ury--ul--cycle) ;
- elseif type=78 :
- border := mirror (lly--lr--ur--ul--cycle) ;
- elseif type=79 :
- border := mirror (ll--lry--ur--ul--cycle) ;
-
- else :
- border := normal (origin--cycle) ;
- %border := normal (ll--lr--ur--ul--cycle) ;
- fi ;
-
- border
-
- endgroup
-
-enddef;
-
-def some_shape ( expr shape_type ,
- shape_width ,
- shape_height ,
- shape_linewidth ,
- shape_linecolor ,
- shape_fillcolor ) =
-
- path p ; p :=
- some_shape_path (shape_type)
- xscaled shape_width
- yscaled shape_height ;
-
- pickup pencircle scaled shape_linewidth ;
-
- fill p withcolor shape_fillcolor ;
- draw p withcolor shape_linecolor ;
-
-enddef ;
-
-vardef drawshape (expr t, p, lw, lc, fc) =
- save pp ;
- if t>1 : % normal shape
- path pp ;
- pp := some_shape_path(t) xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
- fill pp withcolor fc ;
- draw pp withpen pencircle scaled lw withcolor lc ;
- elseif t=1 : % background only
- path pp ;
- pp := fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
- fill pp withcolor fc ;
- else : % dimensions only
- picture pp ; pp := nullpicture ;
- setbounds pp to fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
- draw pp ;
- fi ;
-enddef ;
-
-vardef drawline (expr t, p, lw, lc) =
- if (t>0) and (length(p)>1) :
- saveoptions ;
- drawoptions(withpen pencircle scaled lw withcolor lc) ;
- draw p ;
- if t = 1 :
- draw arrowheadonpath(p,1) ;
- elseif t = 2 :
- draw arrowheadonpath(reverse p,1) ;
- elseif t = 3 :
- for $ = p,reverse p : draw arrowheadonpath($,1) ; endfor ;
- elseif t = 11 :
- draw arrowheadonpath(p,1/2) ;
- elseif t = 12 :
- draw arrowheadonpath(reverse p,1/2) ;
- elseif t = 13 :
- for $=p,reverse p : draw arrowheadonpath($,1) ; endfor ;
- for $=p,reverse p : draw arrowheadonpath($,3/4) ; endfor ;
- elseif t = 21 :
- for $=1/5,1/2,4/5 : draw arrowheadonpath(p,$) ; endfor ;
- elseif t = 22 :
- for $=1/5,1/2,4/5 : draw arrowheadonpath(reverse p,$) ; endfor ;
- elseif t = 23 :
- for $=p,reverse p : draw arrowheadonpath($,1/4) ; endfor ;
- fi ;
- fi ;
-enddef ;
-
-endinput ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-shap.mpii b/Master/texmf-dist/metapost/context/base/mp-shap.mpii
new file mode 100644
index 00000000000..2915069976e
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-shap.mpii
@@ -0,0 +1,206 @@
+%D \module
+%D [ file=mp-shap.mp,
+%D version=2000.05.31,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=shapes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if known context_shap : endinput ; fi ;
+
+boolean context_shap ; context_shap := true ;
+
+path predefined_shapes[] ;
+
+begingroup ;
+
+save xradius, yradius, xxradius, yyradius ;
+save ll, lr, ur, ul, llx, lly, lrx, lry, urx, ury, ulx, uly, llxx, llyy, lrxx, lryy, urxx, uryy, ulxx, ulyy, lc, rc, tc, bc ;
+
+numeric xradius, yradius, xxradius, yyradius ;
+pair ll, lr, ur, ul, llx, lly, lrx, lry, urx, ury, ulx, uly, llxx, llyy, lrxx, lryy, urxx, uryy, ulxx, ulyy, lc, rc, tc, bc ;
+
+xradius := .15 ;
+yradius := .15 ;
+xxradius := .10 ;
+yyradius := .10 ;
+
+ll := llcorner (unitsquare shifted (-.5,-.5)) ;
+lr := lrcorner (unitsquare shifted (-.5,-.5)) ;
+ur := urcorner (unitsquare shifted (-.5,-.5)) ;
+ul := ulcorner (unitsquare shifted (-.5,-.5)) ;
+
+llx := ll shifted (xradius,0) ;
+lly := ll shifted (0,yradius) ;
+
+lrx := lr shifted (-xradius,0) ;
+lry := lr shifted (0,yradius) ;
+
+urx := ur shifted (-xradius,0) ;
+ury := ur shifted (0,-yradius) ;
+
+ulx := ul shifted (xradius,0) ;
+uly := ul shifted (0,-yradius) ;
+
+llxx := ll shifted (xxradius,0) ;
+llyy := ll shifted (0,yyradius) ;
+
+lrxx := lr shifted (-xxradius,0) ;
+lryy := lr shifted (0,yyradius) ;
+
+urxx := ur shifted (-xxradius,0) ;
+uryy := ur shifted (0,-yyradius) ;
+
+ulxx := ul shifted (xxradius,0) ;
+ulyy := ul shifted (0,-yyradius) ;
+
+lc := ll shifted (0,.5) ;
+rc := lr shifted (0,.5) ;
+tc := ul shifted (.5,0) ;
+bc := ll shifted (.5,0) ;
+
+predefined_shapes[ 0] := (origin--cycle) ;
+predefined_shapes[ 5] := (llx--lrx{right}...rc...{left}urx--ulx{left}...lc...{right}cycle) ;
+predefined_shapes[ 6] := (ll--lrx{right}...rc...{left}urx--ul--cycle) ;
+predefined_shapes[ 7] := (ll--lrx{right}...rc...{left}urx--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[ 8] := (lr--ury{up}...tc...{down}uly--ll--cycle) ;
+predefined_shapes[ 9] := (lr--ury{up}...tc...{down}uly--ll--cycle) rotatedaround(origin,180) ;
+predefined_shapes[10] := (ll--lr--ur--ul--ll--ur--ul--ll--cycle) ;
+predefined_shapes[11] := (ll--lr--ur--ul--ll--lr--ul--ll--cycle) ;
+predefined_shapes[12] := (ll--lrx--ur--ulx--cycle) ;
+predefined_shapes[13] := (llx--lr--urx--ul--cycle) ;
+predefined_shapes[14] := (lly--bc--lry--ury--tc--uly--cycle) ;
+predefined_shapes[15] := (llx--lrx--rc--urx--ulx--lc--cycle) ;
+predefined_shapes[16] := (ll--lrx--rc--urx--ul--cycle) ;
+predefined_shapes[17] := (ll--lrx--rc--urx--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[18] := (lr--ury--tc--uly--ll--cycle) ;
+predefined_shapes[19] := (lr--ury--tc--uly--ll--cycle) rotatedaround(origin,180) ;
+predefined_shapes[20] := (ll--lr--ur--ul--ll--llxx--ulxx--ul--ll--lr--ur--urxx--lrxx--cycle) ;
+predefined_shapes[21] := (ul--ll--lr--ur--ul--ulyy--uryy--ur--ul--ll--lr--lryy--llyy--cycle) ;
+predefined_shapes[22] := (ll--lrx--lry--ur--ulx--uly--cycle) ;
+predefined_shapes[23] := (llx--lr--ury--urx--ul--lly--cycle) ;
+predefined_shapes[24] := (ll--lr--ur--ul--cycle) ;
+predefined_shapes[25] := (llx--lrx--lry--ury--urx--ulx--uly--lly--cycle) ;
+predefined_shapes[26] := (ll--lrx--lry--ur--ul--cycle) ;
+predefined_shapes[27] := (ll--lr--ury--urx--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[28] := (ll--lr--ury--urx--ul--cycle) ;
+predefined_shapes[29] := (ll--lrx--lry--ur--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[30] := (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc & bc--tc & tc{left}..{down}lc & lc--rc & rc{up}..tc{left}...{down}lc...{right}bc & cycle) rotated 45;
+predefined_shapes[31] := (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc & bc--tc & tc{left}..{down}lc & lc--rc & rc{up}..tc{left}...{down}lc...{right}bc & cycle) ;
+predefined_shapes[32] := (ll{right}...{right}lry--ur--ul--ll--cycle) ;
+predefined_shapes[33] := (ll{right}...{right}lry--ur--ul--ll--cycle--ul--ulx--ulx shifted(0,yyradius)--ur shifted(yyradius,yyradius)--lry shifted(yyradius,yyradius)--lry shifted(0,yyradius)--ur--ul--cycle ) ;
+predefined_shapes[34] := (uly..tc..ury & ury..tc shifted (0,-2yradius)..uly & uly--lly & lly..bc..lry & lry--ury & ury..tc shifted (0,-2yradius)..uly & cycle ) ;
+predefined_shapes[35] := (bc{right}...rc{up}...tc{left}...lc{down}...cycle) ;
+predefined_shapes[36] := (ul--tc{right}..rc{down}..{left}bc--ll & ll..(xpart llx, ypart lc)..ul & cycle) ;
+predefined_shapes[37] := (ul--tc{right}..rc{down}..{left}bc--ll & ll..(xpart llx, ypart lc)..ul & cycle) rotatedaround(origin,180) ;
+predefined_shapes[38] := (ll--lc{up}..tc{right}..{down}rc--lr & lr..(xpart bc, ypart lly)..ll & cycle) ;
+predefined_shapes[39] := (ll--lc{up}..tc{right}..{down}rc--lr & lr..(xpart bc, ypart lly)..ll & cycle) rotatedaround(origin,180) ;
+predefined_shapes[40] := (ll--lr--ur--ul--ll--ur--ul--ll--lr--ul--ll--cycle) ;
+predefined_shapes[41] := (ll--lr--ur--ul--ll--lr--rc--lc--ll--bc--tc--ul--ll & cycle) ;
+predefined_shapes[42] := (ll--lr--origin shifted (+epsilon,0)--ur--ul--origin shifted (-epsilon,0)--cycle) ;
+predefined_shapes[43] := (ll--ul--origin shifted (0,+epsilon)--ur--lr--origin shifted (0,-epsilon)--cycle) ;
+predefined_shapes[45] := (bc--rc--tc--lc--cycle) ;
+predefined_shapes[46] := (ll--ul--rc--cycle) ;
+predefined_shapes[47] := (ll--ul--rc--cycle) rotatedaround(origin,180) ;
+predefined_shapes[48] := (ul--ur--bc--cycle) rotatedaround(origin,180) ;
+predefined_shapes[49] := (ul--ur--bc--cycle) ;
+predefined_shapes[56] := (ll--lry--ury--ul--cycle) ;
+predefined_shapes[57] := (ll--lry--ury--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[58] := (ll--ulx--urx--lr--cycle) ;
+predefined_shapes[59] := (ll--ulx--urx--lr--cycle) rotatedaround(origin,180);
+predefined_shapes[66] := (rc--origin shifted ( epsilon,0) --cycle & rc--origin--cycle ) ;
+predefined_shapes[67] := (lc--origin shifted (-epsilon,0) --cycle & lc--origin--cycle ) ;
+predefined_shapes[68] := (tc--origin shifted (0, epsilon) --cycle & tc--origin--cycle ) ;
+predefined_shapes[69] := (bc--origin shifted (0,-epsilon) --cycle & bc--origin--cycle ) ;
+predefined_shapes[75] := (lly--lry--ury--uly--cycle) rotatedaround(origin,180) ;
+predefined_shapes[76] := (ll--lr--ur--uly--cycle) rotatedaround(origin,180) ;
+predefined_shapes[77] := (ll--lr--ury--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[78] := (lly--lr--ur--ul--cycle) rotatedaround(origin,180) ;
+predefined_shapes[79] := (ll--lry--ur--ul--cycle) rotatedaround(origin,180) ;
+
+numeric predefined_shapes_xradius ; predefined_shapes_xradius := xradius ;
+numeric predefined_shapes_yradius ; predefined_shapes_yradius := yradius ;
+numeric predefined_shapes_xxradius ; predefined_shapes_xxradius := xxradius ;
+numeric predefined_shapes_yyradius ; predefined_shapes_yyradius := yyradius ;
+
+endgroup ;
+
+vardef some_shape_path (expr type) =
+ if known predefined_shapes[type] : predefined_shapes[type] else : predefined_shapes[0] fi
+enddef ;
+
+def some_shape (expr shape_type, shape_width, shape_height, shape_linewidth, shape_linecolor, shape_fillcolor) =
+ begingroup ;
+ save p ; path p ;
+ p := some_shape_path (shape_type) xscaled shape_width yscaled shape_height ;
+ pickup pencircle scaled shape_linewidth ;
+ fill p withcolor shape_fillcolor ;
+ draw p withcolor shape_linecolor ;
+ endgroup ;
+enddef ;
+
+vardef drawpredefinedshape (expr t, p, lw, lc, fc) =
+ save pp ;
+ if t>1 : % normal shape
+ path pp ;
+ pp := some_shape_path(t) xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ fill pp withcolor fc ;
+ draw pp withpen pencircle scaled lw withcolor lc ;
+ elseif t=1 : % background only
+ path pp ;
+ pp := fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ fill pp withcolor fc ;
+ else : % dimensions only
+ picture pp ; pp := nullpicture ;
+ setbounds pp to fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ draw pp ;
+ fi ;
+enddef ;
+
+vardef drawpredefinedline (expr t, p, lw, lc) =
+ if (t>0) and (length(p)>1) :
+ saveoptions ;
+ drawoptions(withpen pencircle scaled lw withcolor lc) ;
+ draw p ;
+ if t = 1 :
+ draw arrowheadonpath(p,1) ;
+ elseif t = 2 :
+ draw arrowheadonpath(reverse p,1) ;
+ elseif t = 3 :
+ for $ = p,reverse p :
+ draw arrowheadonpath($,1) ;
+ endfor ;
+ elseif t = 11 :
+ draw arrowheadonpath(p,1/2) ;
+ elseif t = 12 :
+ draw arrowheadonpath(reverse p,1/2) ;
+ elseif t = 13 :
+ for $=p,reverse p :
+ draw arrowheadonpath($,1) ;
+ endfor ;
+ for $=p,reverse p :
+ draw arrowheadonpath($,3/4) ;
+ endfor ;
+ elseif t = 21 :
+ for $=1/5,1/2,4/5 :
+ draw arrowheadonpath(p,$) ;
+ endfor ;
+ elseif t = 22 :
+ for $=1/5,1/2,4/5 :
+ draw arrowheadonpath(reverse p,$) ;
+ endfor ;
+ elseif t = 23 :
+ for $=p,reverse p :
+ draw arrowheadonpath($,1/4) ;
+ endfor ;
+ fi ;
+ fi ;
+enddef ;
+
+let drawshape = drawpredefinedshape ;
+let drawline = drawpredefinedline ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-shap.mpiv b/Master/texmf-dist/metapost/context/base/mp-shap.mpiv
new file mode 100644
index 00000000000..c86edaf82bf
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-shap.mpiv
@@ -0,0 +1,218 @@
+%D \module
+%D [ file=mp-shap.mp,
+%D version=2000.05.31,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=shapes,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+if known context_shap : endinput ; fi ;
+
+boolean context_shap ; context_shap := true ;
+
+path predefined_shapes[] ;
+
+def start_predefined_shape_definition =
+
+ begingroup ;
+
+ save xradius, yradius, xxradius, yyradius ;
+ save ll, lr, ur, ul, llx, lly, lrx, lry, urx, ury, ulx, uly, llxx, llyy, lrxx, lryy, urxx, uryy, ulxx, ulyy, lc, rc, tc, bc ;
+
+ numeric xradius, yradius, xxradius, yyradius ;
+ pair ll, lr, ur, ul, llx, lly, lrx, lry, urx, ury, ulx, uly, llxx, llyy, lrxx, lryy, urxx, uryy, ulxx, ulyy, lc, rc, tc, bc ;
+
+ xradius := .15 ;
+ yradius := .15 ;
+ xxradius := .10 ;
+ yyradius := .10 ;
+
+ ll := llcorner (unitsquare shifted (-.5,-.5)) ;
+ lr := lrcorner (unitsquare shifted (-.5,-.5)) ;
+ ur := urcorner (unitsquare shifted (-.5,-.5)) ;
+ ul := ulcorner (unitsquare shifted (-.5,-.5)) ;
+
+ llx := ll shifted (xradius,0) ;
+ lly := ll shifted (0,yradius) ;
+
+ lrx := lr shifted (-xradius,0) ;
+ lry := lr shifted (0,yradius) ;
+
+ urx := ur shifted (-xradius,0) ;
+ ury := ur shifted (0,-yradius) ;
+
+ ulx := ul shifted (xradius,0) ;
+ uly := ul shifted (0,-yradius) ;
+
+ llxx := ll shifted (xxradius,0) ;
+ llyy := ll shifted (0,yyradius) ;
+
+ lrxx := lr shifted (-xxradius,0) ;
+ lryy := lr shifted (0,yyradius) ;
+
+ urxx := ur shifted (-xxradius,0) ;
+ uryy := ur shifted (0,-yyradius) ;
+
+ ulxx := ul shifted (xxradius,0) ;
+ ulyy := ul shifted (0,-yyradius) ;
+
+ lc := ll shifted (0,.5) ;
+ rc := lr shifted (0,.5) ;
+ tc := ul shifted (.5,0) ;
+ bc := ll shifted (.5,0) ;
+
+enddef ;
+
+def stop_predefined_shape_definition =
+
+ endgroup ;
+
+enddef ;
+
+start_predefined_shape_definition ;
+
+ predefined_shapes[ 0] := (origin--cycle) ;
+ predefined_shapes[ 5] := (llx--lrx{right}...rc...{left}urx--ulx{left}...lc...{right}cycle) ;
+ predefined_shapes[ 6] := (ll--lrx{right}...rc...{left}urx--ul--cycle) ;
+ predefined_shapes[ 7] := (ll--lrx{right}...rc...{left}urx--ul--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[ 8] := (lr--ury{up}...tc...{down}uly--ll--cycle) ;
+ predefined_shapes[ 9] := (lr--ury{up}...tc...{down}uly--ll--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[10] := (ll--lr--ur--ul--ll--ur--ul--ll--cycle) ;
+ predefined_shapes[11] := (ll--lr--ur--ul--ll--lr--ul--ll--cycle) ;
+ predefined_shapes[12] := (ll--lrx--ur--ulx--cycle) ;
+ predefined_shapes[13] := (llx--lr--urx--ul--cycle) ;
+ predefined_shapes[14] := (lly--bc--lry--ury--tc--uly--cycle) ;
+ predefined_shapes[15] := (llx--lrx--rc--urx--ulx--lc--cycle) ;
+ predefined_shapes[16] := (ll--lrx--rc--urx--ul--cycle) ;
+ predefined_shapes[17] := (ll--lrx--rc--urx--ul--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[18] := (lr--ury--tc--uly--ll--cycle) ;
+ predefined_shapes[19] := (lr--ury--tc--uly--ll--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[20] := (ll--lr--ur--ul--ll--llxx--ulxx--ul--ll--lr--ur--urxx--lrxx--cycle) ;
+ predefined_shapes[21] := (ul--ll--lr--ur--ul--ulyy--uryy--ur--ul--ll--lr--lryy--llyy--cycle) ;
+ predefined_shapes[22] := (ll--lrx--lry--ur--ulx--uly--cycle) ;
+ predefined_shapes[23] := (llx--lr--ury--urx--ul--lly--cycle) ;
+ predefined_shapes[24] := (ll--lr--ur--ul--cycle) ;
+ predefined_shapes[25] := (llx--lrx--lry--ury--urx--ulx--uly--lly--cycle) ;
+ predefined_shapes[26] := (ll--lrx--lry--ur--ul--cycle) ;
+ predefined_shapes[27] := (ll--lr--ury--urx--ul--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[28] := (ll--lr--ury--urx--ul--cycle) ;
+ predefined_shapes[29] := (ll--lrx--lry--ur--ul--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[30] := (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc & bc--tc & tc{left}..{down}lc & lc--rc & rc{up}..tc{left}...{down}lc...{right}bc & cycle) rotated 45;
+ predefined_shapes[31] := (bc{right}...{up}rc...tc{left}...{down}lc...{right}bc & bc--tc & tc{left}..{down}lc & lc--rc & rc{up}..tc{left}...{down}lc...{right}bc & cycle) ;
+ predefined_shapes[32] := (ll{right}...{right}lry--ur--ul--ll--cycle) ;
+ predefined_shapes[33] := (ll{right}...{right}lry--ur--ul--ll--cycle--ul--ulx--ulx shifted(0,yyradius)--ur shifted(yyradius,yyradius)--lry shifted(yyradius,yyradius)--lry shifted(0,yyradius)--ur--ul--cycle ) ;
+ predefined_shapes[34] := (uly..tc..ury & ury..tc shifted (0,-2yradius)..uly & uly--lly & lly..bc..lry & lry--ury & ury..tc shifted (0,-2yradius)..uly & cycle ) ;
+ predefined_shapes[35] := (bc{right}...rc{up}...tc{left}...lc{down}...cycle) ;
+ predefined_shapes[36] := (ul--tc{right}..rc{down}..{left}bc--ll & ll..(xpart llx, ypart lc)..ul & cycle) ;
+ predefined_shapes[37] := (ul--tc{right}..rc{down}..{left}bc--ll & ll..(xpart llx, ypart lc)..ul & cycle) rotatedaround(origin,180) ;
+ predefined_shapes[38] := (ll--lc{up}..tc{right}..{down}rc--lr & lr..(xpart bc, ypart lly)..ll & cycle) ;
+ predefined_shapes[39] := (ll--lc{up}..tc{right}..{down}rc--lr & lr..(xpart bc, ypart lly)..ll & cycle) rotatedaround(origin,180) ;
+ predefined_shapes[40] := (ll--lr--ur--ul--ll--ur--ul--ll--lr--ul--ll--cycle) ;
+ predefined_shapes[41] := (ll--lr--ur--ul--ll--lr--rc--lc--ll--bc--tc--ul--ll & cycle) ;
+ predefined_shapes[42] := (ll--lr--origin shifted (+epsilon,0)--ur--ul--origin shifted (-epsilon,0)--cycle) ;
+ predefined_shapes[43] := (ll--ul--origin shifted (0,+epsilon)--ur--lr--origin shifted (0,-epsilon)--cycle) ;
+ predefined_shapes[45] := (bc--rc--tc--lc--cycle) ;
+ predefined_shapes[46] := (ll--ul--rc--cycle) ;
+ predefined_shapes[47] := (ll--ul--rc--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[48] := (ul--ur--bc--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[49] := (ul--ur--bc--cycle) ;
+ predefined_shapes[56] := (ll--lry--ury--ul--cycle) ;
+ predefined_shapes[57] := (ll--lry--ury--ul--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[58] := (ll--ulx--urx--lr--cycle) ;
+ predefined_shapes[59] := (ll--ulx--urx--lr--cycle) rotatedaround(origin,180);
+ predefined_shapes[66] := (rc--origin shifted ( epsilon,0) --cycle & rc--origin--cycle ) ;
+ predefined_shapes[67] := (lc--origin shifted (-epsilon,0) --cycle & lc--origin--cycle ) ;
+ predefined_shapes[68] := (tc--origin shifted (0, epsilon) --cycle & tc--origin--cycle ) ;
+ predefined_shapes[69] := (bc--origin shifted (0,-epsilon) --cycle & bc--origin--cycle ) ;
+ predefined_shapes[75] := (lly--lry--ury--uly--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[76] := (ll--lr--ur--uly--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[77] := (ll--lr--ury--ul--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[78] := (lly--lr--ur--ul--cycle) rotatedaround(origin,180) ;
+ predefined_shapes[79] := (ll--lry--ur--ul--cycle) rotatedaround(origin,180) ;
+
+ numeric predefined_shapes_xradius ; predefined_shapes_xradius := xradius ;
+ numeric predefined_shapes_yradius ; predefined_shapes_yradius := yradius ;
+ numeric predefined_shapes_xxradius ; predefined_shapes_xxradius := xxradius ;
+ numeric predefined_shapes_yyradius ; predefined_shapes_yyradius := yyradius ;
+
+stop_predefined_shape_definition ;
+
+vardef some_shape_path (expr type) =
+ if known predefined_shapes[type] : predefined_shapes[type] else : predefined_shapes[0] fi
+enddef ;
+
+def some_shape (expr shape_type, shape_width, shape_height, shape_linewidth, shape_linecolor, shape_fillcolor) =
+ begingroup ;
+ save p ; path p ;
+ p := some_shape_path (shape_type) xscaled shape_width yscaled shape_height ;
+ pickup pencircle scaled shape_linewidth ;
+ fill p withcolor shape_fillcolor ;
+ draw p withcolor shape_linecolor ;
+ endgroup ;
+enddef ;
+
+vardef drawpredefinedshape (expr t, p, lw, lc, fc) =
+ save pp ;
+ if t>1 : % normal shape
+ path pp ;
+ pp := some_shape_path(t) xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ fill pp withcolor fc ;
+ draw pp withpen pencircle scaled lw withcolor lc ;
+ elseif t=1 : % background only
+ path pp ;
+ pp := fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ fill pp withcolor fc ;
+ else : % dimensions only
+ picture pp ; pp := nullpicture ;
+ setbounds pp to fullsquare xyscaled(bbwidth(p), bbheight(p)) shifted center p ;
+ draw pp ;
+ fi ;
+enddef ;
+
+vardef drawpredefinedline (expr t, p, lw, lc) =
+ if (t>0) and (length(p)>1) :
+ saveoptions ;
+ drawoptions(withpen pencircle scaled lw withcolor lc) ;
+ draw p ;
+ if t = 1 :
+ draw arrowheadonpath(p,1) ;
+ elseif t = 2 :
+ draw arrowheadonpath(reverse p,1) ;
+ elseif t = 3 :
+ for $ = p,reverse p :
+ draw arrowheadonpath($,1) ;
+ endfor ;
+ elseif t = 11 :
+ draw arrowheadonpath(p,1/2) ;
+ elseif t = 12 :
+ draw arrowheadonpath(reverse p,1/2) ;
+ elseif t = 13 :
+ for $=p,reverse p :
+ draw arrowheadonpath($,1) ;
+ endfor ;
+ for $=p,reverse p :
+ draw arrowheadonpath($,3/4) ;
+ endfor ;
+ elseif t = 21 :
+ for $=1/5,1/2,4/5 :
+ draw arrowheadonpath(p,$) ;
+ endfor ;
+ elseif t = 22 :
+ for $=1/5,1/2,4/5 :
+ draw arrowheadonpath(reverse p,$) ;
+ endfor ;
+ elseif t = 23 :
+ for $=p,reverse p :
+ draw arrowheadonpath($,1/4) ;
+ endfor ;
+ fi ;
+ fi ;
+enddef ;
+
+let drawshape = drawpredefinedshape ;
+let drawline = drawpredefinedline ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-spec.mp b/Master/texmf-dist/metapost/context/base/mp-spec.mpii
index 123e75faaae..7cb960524b6 100644
--- a/Master/texmf-dist/metapost/context/base/mp-spec.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-spec.mpii
@@ -47,9 +47,7 @@
%D for instance shading. More information can be found in
%D type {supp-mpe.tex}.
-if known mplib : endinput ; fi ;
-if unknown context_tool : input mp-tool ; fi ;
-if known context_spec : endinput ; fi ;
+if known context_spec : endinput ; fi ;
boolean context_spec ; context_spec := true ;
@@ -715,8 +713,6 @@ enddef ;
% spotcolor is already scaled
-endinput ;
-
% just an exercise (due to a question by Chof on the context mailing list); scaling of
% 'special' colors is not possible and the next solution is incomplete (spot colors,
% transparency, etc); watch the the tricky chained macro construction
diff --git a/Master/texmf-dist/metapost/context/base/mp-step.mp b/Master/texmf-dist/metapost/context/base/mp-step.mpii
index d602f701430..a8d0df8e094 100644
--- a/Master/texmf-dist/metapost/context/base/mp-step.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-step.mpii
@@ -11,8 +11,7 @@
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
%C details.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_step : endinput ; fi ;
+if known context_step : endinput ; fi ;
boolean context_step ; context_step := true ;
@@ -39,7 +38,7 @@ enddef ;
def analyze_step_chart =
numeric n[], l[][], r[][] ; pair p[] ;
- n[t] := n[b] := 0 ; numeric tb ;
+ n[t] := n[b] := 0 ; numeric tb ;
for i=1 upto nofcells : for nn = t, b :
if bbwidth(cells[nn][i])>0 : n[nn] := n[nn] + 1 ; fi ;
l[t][i] := r[t][i] := l[b][i] := r[b][i] := 0 ;
@@ -80,15 +79,15 @@ vardef get_step_chart_top_line (expr i, j) =
p[3] := p[3] shifted (0,+line_v_offset) ;
(p[1] {up} ... p[2] ... {down} p[3])
else :
- origin
- fi
+ origin
+ fi
else :
- origin
- fi
+ origin
+ fi
else :
- origin
- fi
-enddef ;
+ origin
+ fi
+enddef ;
vardef get_step_chart_bot_line (expr i, j) =
if bbwidth(cells[b][i])>0 :
@@ -108,31 +107,31 @@ vardef get_step_chart_bot_line (expr i, j) =
p[3] := p[3] shifted (0,-line_v_offset) ;
(p[1] {down} ... p[2] ... {up} p[3])
else :
- origin
- fi
+ origin
+ fi
else :
- origin
- fi
+ origin
+ fi
else :
- origin
- fi
+ origin
+ fi
enddef ;
def end_step_chart =
- for i=1 upto nofcells : for nn = t, b :
- if bbwidth(cells[nn][i]) >0 : draw cells[nn][i] ; fi ;
+ for i=1 upto nofcells : for nn = t, b :
+ if bbwidth(cells[nn][i]) >0 : draw cells[nn][i] ; fi ;
endfor ; endfor ;
- for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b :
+ for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b :
if known lines[nn][i][j] :
if bbwidth(lines[nn][i][j])>0 : draw lines[nn][i][j] ; fi ;
- fi ;
+ fi ;
endfor ; endfor ; endfor ;
for i=1 upto nofcells : for j=i upto nofcells : for nn = t, b :
if bbwidth(texts[nn][i][j])>0 : draw texts[nn][i][j] ; fi ;
endfor ; endfor ; endfor ;
enddef ;
-%D Step tables.
+%D Step tables.
def begin_step_table =
initialize_step_variables ;
@@ -141,13 +140,13 @@ def begin_step_table =
enddef ;
def end_step_table =
- for i=1 upto nofcells : if known cells[i] : if bbwidth(cells[i])>0 :
- draw cells[i] ;
+ for i=1 upto nofcells : if known cells[i] : if bbwidth(cells[i])>0 :
+ draw cells[i] ;
fi ; fi ; endfor ;
- for i=1 upto nofcells : if known lines[i] : if bbwidth(lines[i])>0 :
- draw lines[i] ;
+ for i=1 upto nofcells : if known lines[i] : if bbwidth(lines[i])>0 :
+ draw lines[i] ;
fi ; fi ; endfor ;
- for i=1 upto nofcells : if known texts[i] : if bbwidth(texts[i])>0 :
+ for i=1 upto nofcells : if known texts[i] : if bbwidth(texts[i])>0 :
draw texts[i] ;
fi ; fi ; endfor ;
enddef ;
@@ -167,8 +166,6 @@ vardef get_step_table_line (expr i) =
fi
enddef ;
-endinput
-
%D The older method let \METAPOST\ do the typesetting. The
%D macros needed for that are included here for educational
%D purposes.
diff --git a/Master/texmf-dist/metapost/context/base/mp-step.mpiv b/Master/texmf-dist/metapost/context/base/mp-step.mpiv
new file mode 100644
index 00000000000..21a20ce7172
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-step.mpiv
@@ -0,0 +1,376 @@
+%D \module
+%D [ file=mp-cell.mpiv, % mp-step.mp,
+%D version=2010.10.07, % 2001.05.22,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=steps,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+% step prefixes .. no save needed
+
+if known context_cell : endinput ; fi ;
+
+boolean context_cell ; context_cell := true ;
+
+def initialize_step_variables =
+ save
+ text_fill_color, text_line_color, text_line_width, text_offset,
+ cell_fill_color, cell_line_color, cell_line_width, cell_offset,
+ line_line_color, line_line_width, line_alternative,
+ line_distance, cell_distance_y, cell_distance_x,
+ nofcells, chart_vertical ;
+
+ color text_line_color ; text_line_color := red ;
+ color cell_line_color ; cell_line_color := blue ;
+ color line_line_color ; line_line_color := green ;
+
+ color text_fill_color ; text_fill_color := white ;
+ color cell_fill_color ; cell_fill_color := white ;
+
+ numeric text_line_width ; text_line_width := 2pt ;
+ numeric cell_line_width ; cell_line_width := 2pt ;
+ numeric line_line_width ; line_line_width := 2pt ;
+
+ numeric text_offset ; text_offset := 4pt ;
+ numeric cell_offset ; cell_offset := 4pt ;
+
+ numeric line_distance ; line_distance := 10pt ; % between line and text
+ numeric line_offset ; line_offset := 4pt ; % between center and start of line
+ numeric line_height ; line_height := 20pt ;
+
+ numeric cell_distance_y ; cell_distance_y := 20pt ;
+ numeric cell_distance_x ; cell_distance_x := 20pt ;
+
+ numeric text_distance_set ; text_distance_set := 4pt ;
+
+ boolean chart_vertical ; chart_vertical := false ;
+
+ numeric nofcells ; nofcells := 0 ;
+
+enddef ;
+
+def step_cells (expr t, b) =
+ nofcells := nofcells + 1 ;
+ cells_t[nofcells] := textext.d(t) ;
+ cells_b[nofcells] := textext.d(b) ;
+ texts_t[nofcells] := nullpicture ;
+ texts_m[nofcells] := nullpicture ;
+ texts_b[nofcells] := nullpicture ;
+enddef ;
+
+def step_texts (expr t, b) =
+ texts_t[nofcells] := textext.d(t) ;
+ texts_m[nofcells] := textext.d(m) ;
+ texts_b[nofcells] := textext.d(b) ;
+enddef ;
+
+def step_begin_cell =
+ nofcells := nofcells + 1 ;
+ cells_t[nofcells] := nullpicture ;
+ cells_b[nofcells] := nullpicture ;
+ texts_t[nofcells] := nullpicture ;
+ texts_m[nofcells] := nullpicture ;
+ texts_b[nofcells] := nullpicture ;
+enddef ;
+
+def step_end_cell =
+enddef ;
+
+def step_cell_top (expr t) = cells_t[nofcells] := textext.d(t) ; enddef ;
+def step_cell_bot (expr b) = cells_b[nofcells] := textext.d(b) ; enddef ;
+def step_text_top (expr t) = texts_t[nofcells] := textext.d(t) ; enddef ;
+def step_text_mid (expr m) = texts_m[nofcells] := textext.d(m) ; enddef ;
+def step_text_bot (expr b) = texts_b[nofcells] := textext.d(b) ; enddef ;
+
+def step_begin_chart =
+ begingroup ;
+ initialize_step_variables ;
+ save nofcells ; numeric nofcells ; nofcells := 0 ;
+ save cells_t, cells_m, cells_b ; picture cells_t[], cells_m[], cells_b[] ;
+ save texts_t, texts_m, texts_b ; picture texts_t[], texts_m[], texts_b[] ;
+enddef ;
+
+def step_end_chart =
+ % we could combine some loops but this is cleaner
+ save dx, delta ; numeric dx, delta ;
+ save p ; path p ;
+ save one_row_only ; boolean one_row_only ;
+ save cell_t, next_t, text_t ; picture cell_t, next_t, text_t ;
+ save cell_m, next_m, text_m ; picture cell_m, next_m, text_m ;
+ save cell_b, next_b, text_b ; picture cell_b, next_b, text_b ;
+ save height_t, width_t, max_height_t, max_width_t ; numeric height_t, width_t, max_height_t, max_width_t ;
+ save height_m, width_m, max_height_m, max_width_m ; numeric height_m, width_m, max_height_m, max_width_m ;
+ save height_b, width_b, max_height_b, max_width_b ; numeric height_b, width_b, max_height_b, max_width_b ;
+ % check rows
+ one_row_only := true ;
+ for i=1 upto nofcells :
+ if bbwidth(cells_b[i]) > 0 :
+ one_row_only := false ;
+ fi ;
+ endfor ;
+ % swap and rotate
+ if chart_vertical :
+ if one_row_only :
+ % deal with mid_texts
+ max_width_t := max_width_m := max_width_b := 0 ;
+ for i=1 upto nofcells :
+ width_t := bbwidth(texts_t[i]) ;
+ width_m := bbwidth(texts_m[i]) ;
+ width_b := bbwidth(texts_b[i]) ;
+ if width_t > max_width_t : max_width_t := width_t fi ;
+ if width_m > max_width_m : max_width_m := width_m fi ;
+ if width_b > max_width_b : max_width_b := width_b fi ;
+ endfor ;
+ if max_width_m > 0 :
+ for i=1 upto nofcells :
+ text_t := texts_t[i] ; width_t := bbwidth(text_t) ;
+ text_m := texts_m[i] ; width_m := bbwidth(text_m) ;
+ text_b := texts_b[i] ; width_b := bbwidth(text_b) ;
+ if width_t < max_width_t :
+ setbounds text_t to boundingbox text_t leftenlarged (max_width_t - width_t) ;
+ fi ;
+ if width_m < max_width_m :
+ setbounds text_m to boundingbox text_m leftenlarged ((max_width_m - width_m)/2) ;
+ setbounds text_m to boundingbox text_m rightenlarged ((max_width_m - width_m)/2) ;
+ fi ;
+ if width_b < max_width_b :
+ setbounds text_b to boundingbox text_b rightenlarged (max_width_b - width_b) ;
+ fi ;
+ text_t := text_t shifted (- xpart llcorner text_t, 0) ;
+ text_m := text_m shifted (- xpart llcorner text_m, 0) ;
+ text_b := text_b shifted (- xpart llcorner text_b, 0) ;
+ texts_t[i] := image (
+ draw text_t ;
+ draw text_m shifted (max_width_t + text_distance_set,0) ;
+ draw text_b shifted (max_width_t + max_width_m + 2*text_distance_set,0) ;
+ ) rotated 90 ;
+ texts_m[i] := texts_b[i] := nullpicture ;
+ cells_t[i] := cells_t[i] rotated 90 ;
+ endfor ;
+ else :
+ for i=1 upto nofcells :
+ cells_t[i] := cells_t[i] rotated 90 ;
+ texts_t[i] := texts_t[i] rotated 90 ;
+ texts_b[i] := texts_b[i] rotated 90 ;
+ endfor ;
+ fi ;
+ else :
+ for i=1 upto nofcells :
+ cell_t := cells_t[i] ;
+ cell_b := cells_b[i] ;
+ cells_t[i] := cell_b rotated 90 ;
+ cells_b[i] := cell_t rotated 90 ;
+ text_t := texts_t[i] ;
+ text_b := texts_b[i] ;
+ texts_t[i] := text_b rotated 90 ;
+ texts_b[i] := text_t rotated 90 ;
+ endfor ;
+ fi ;
+ fi ;
+ % align horizontal
+ for i=1 upto nofcells :
+ cell_t := cells_t[i] ;
+ cell_b := cells_b[i] ;
+ width_t := bbwidth(cell_t) ;
+ width_b := bbwidth(cell_b) ;
+ if (width_t = 0) and (width_b = 0) :
+ % skip
+ elseif (width_t > 0) and (width_t < width_b) :
+ delta := (width_b-width_t)/2 ;
+ setbounds cell_t to boundingbox cell_t leftenlarged delta rightenlarged delta ;
+ cells_t[i] := cell_t ;
+ elseif (width_b > 0) and (width_t > width_b) :
+ delta := (width_t-width_b)/2 ;
+ setbounds cell_b to boundingbox cell_b leftenlarged delta rightenlarged delta ;
+ cells_b[i] := cell_b ;
+ fi ;
+ endfor ;
+ % analyze vertical
+ max_height_t := 0 ;
+ max_height_b := 0 ;
+ for i=1 upto nofcells :
+ cell_t := cells_t[i] ;
+ cell_b := cells_b[i] ;
+ height_t := bbheight(cell_t) ;
+ height_b := bbheight(cell_b) ;
+ if height_t > 0 :
+ setbounds cell_t to boundingbox cell_t enlarged cell_offset ;
+ height_t := height_t + 2 * cell_offset ;
+ cells_t[i] := cell_t ;
+ fi ;
+ if height_b > 0 :
+ setbounds cell_b to boundingbox cell_b enlarged cell_offset ;
+ height_b := height_b + 2 * cell_offset ;
+ cells_b[i] := cell_b ;
+ fi ;
+ if height_t > max_height_t :
+ max_height_t := height_t ;
+ fi
+ if height_b > max_height_b :
+ max_height_b := height_b ;
+ fi ;
+ endfor ;
+ % align vertical
+ for i=1 upto nofcells :
+ cell_t := cells_t[i] ;
+ cell_b := cells_b[i] ;
+ height_t := bbheight(cell_t) ;
+ height_b := bbheight(cell_b) ;
+ if height_t > 0 :
+ delta := (max_height_t-height_t)/2 ;
+ setbounds cell_t to boundingbox cell_t topenlarged delta bottomenlarged delta ;
+ fi ;
+ if height_b > 0 :
+ delta := (max_height_b-height_b)/2 ;
+ setbounds cell_b to boundingbox cell_b topenlarged delta bottomenlarged delta ;
+ fi ;
+ cells_t[i] := cell_t ;
+ cells_b[i] := cell_b ;
+ endfor ;
+ % position
+ dx := 0 ;
+ for i=1 upto nofcells :
+ cell_t := cells_t[i] ;
+ cell_b := cells_b[i] ;
+ cell_t := cell_t shifted -llcorner cell_t ;
+ cell_b := cell_b shifted -llcorner cell_b ;
+ cell_t := cell_t shifted (dx, 0) ;
+ cell_b := cell_b shifted (dx,-cell_distance_y-max_height_b) ;
+ cells_t[i] := cell_t ;
+ cells_b[i] := cell_b ;
+ width_t := bbwidth(cell_t) ;
+ width_b := bbwidth(cell_b) ;
+ if width_t > 0 :
+ dx := dx + cell_distance_x + width_t ;
+ elseif width_b > 0 :
+ dx := dx + cell_distance_x + width_b ;
+ fi ;
+ endfor ;
+ % flush
+ for i=1 upto nofcells :
+ cell_t := cells_t[i] ;
+ cell_b := cells_b[i] ;
+ width_t := bbwidth(cell_t) ;
+ width_b := bbwidth(cell_b) ;
+ if width_t > 0 :
+ fill boundingbox cell_t withcolor cell_fill_color ;
+ draw boundingbox cell_t withpen pencircle scaled cell_line_width withcolor cell_line_color ;
+ draw cell_t ;
+ fi ;
+ if width_b > 0 :
+ fill boundingbox cell_b withcolor cell_fill_color ;
+ draw boundingbox cell_b withpen pencircle scaled cell_line_width withcolor cell_line_color ;
+ draw cell_b ;
+ fi ;
+ endfor ;
+ %
+ def midtopboundary expr p = 0.5[ulcorner boundingbox p, urcorner boundingbox p] enddef ;
+ def midbottomboundary expr p = 0.5[llcorner boundingbox p, lrcorner boundingbox p] enddef ;
+ % draw top and bottom text boxes
+ for i=1 upto nofcells-1 :
+ text_t := texts_t[i] ;
+ text_b := texts_b[i] ;
+ if bbwidth(text_t) > 0 :
+ setbounds text_t to boundingbox text_t enlarged text_offset ;
+ texts_t[i] := text_t ;
+ fi ;
+ if bbwidth(text_b) > 0 :
+ setbounds text_b to boundingbox text_b enlarged text_offset ;
+ texts_b[i] := text_b ;
+ fi ;
+ endfor ;
+ % arrows
+ for i=1 upto nofcells-1 :
+ cell_t := cells_t[i] ;
+ cell_b := cells_b[i] ;
+ next_t := cells_t[i+1] ;
+ next_b := cells_b[i+1] ;
+ pair t_a, t_b, t_c, b_a, b_b, b_c ;
+ t_a := midtopboundary cell_t ;
+ t_b := midtopboundary next_t ;
+ t_c := (xpart 0.5[t_a,t_b], ypart t_a+line_height+line_distance) ;
+ if one_row_only :
+ b_a := midbottomboundary cell_t ;
+ b_b := midbottomboundary next_t ;
+ else :
+ b_a := midbottomboundary cell_b ;
+ b_b := midbottomboundary next_b ;
+ fi ;
+ b_c := (xpart 0.5[b_a,b_b], ypart b_a-line_height-line_distance) ;
+ texts_t[i] := thelabel.top(texts_t[i],t_c) ;
+ texts_b[i] := thelabel.bot(texts_b[i],b_c) ;
+ endfor ;
+ %
+ for i=1 upto nofcells-1 : % todo arrows when empty text
+ cell_t := cells_t[i] ;
+ cell_b := cells_b[i] ;
+ next_t := cells_t[i+1] ;
+ next_b := cells_b[i+1] ;
+ text_t := texts_t[i] ;
+ text_b := texts_b[i] ;
+ if bbwidth(text_t) > 0 :
+ if bbwidth(cell_t) > 0 :
+ drawarrow midtopboundary cell_t
+ shifted (if i > 1 : line_offset else : 0 fi, cell_line_width) {up} ..
+ midbottomboundary text_t shifted (0,-line_distance) ..
+ {down} midtopboundary next_t shifted(if i < nofcells - 1 : -line_offset else : 0 fi,cell_line_width)
+ withpen pencircle scaled line_line_width
+ withcolor line_line_color ;
+ else :
+ fi ;
+ fi ;
+ if bbwidth(text_b) > 0 :
+ if one_row_only :
+ cell_b := cell_t ;
+ next_b := next_t ;
+ fi ;
+ if bbwidth(cell_b) > 0 :
+ drawarrow midbottomboundary cell_b
+ shifted (if i > 1 : line_offset else : 0 fi, -cell_line_width) {down} ..
+ midtopboundary text_b shifted (0, line_distance) ..
+ {up} midbottomboundary next_b shifted (if i < nofcells - 1 : -line_offset else : 0 fi,-cell_line_width)
+ withpen pencircle scaled line_line_width
+ withcolor line_line_color ;
+ else :
+ fi ;
+ fi ;
+ endfor ;
+ % draw top and bottom text boxes
+ for i=1 upto nofcells-1 :
+ text_t := texts_t[i] ;
+ text_b := texts_b[i] ;
+ if bbwidth(text_t) > 0 :
+ fill boundingbox text_t withcolor text_fill_color ;
+ draw boundingbox text_t withpen pencircle scaled text_line_width withcolor text_line_color ;
+ draw text_t ;
+ fi ;
+ if bbwidth(text_b) > 0 :
+ fill boundingbox text_b withcolor text_fill_color ;
+ draw boundingbox text_b withpen pencircle scaled text_line_width withcolor text_line_color ;
+ draw text_b ;
+ fi ;
+ endfor ;
+ if chart_vertical :
+ % rotate back
+ currentpicture := currentpicture rotated -90 ;
+ fi ;
+ endgroup ;
+enddef ;
+
+% start_begin_step ;
+% step_cells ("\strut test 0", "\strut test 0") ;
+% step_cells ("\strut test 1", "\vbox{\hsize3cm \strut oeps 1\crlf oeps 1}") ;
+% step_texts ("\strut 1", "\strut 1") ;
+% step_cells ("\strut test 2", "\strut oeps 2 oeps 2") ;
+% step_cells ("\strut test X", "\strut test X") ;
+% step_texts ("\strut 2", "\strut 2") ;
+% step_cells ("\strut test 3", "\strut oeps 3 oeps 3") ;
+% step_texts ("\strut 3", "\strut 3") ;
+% step_cells ("\strut test 4", "\strut oeps 4 oeps 4") ;
+% step_texts ("\strut 4", "\strut 4") ;
+% stop_end_chart ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-text.mp b/Master/texmf-dist/metapost/context/base/mp-text.mpii
index 60e16c09bbb..67dff15f9ce 100644
--- a/Master/texmf-dist/metapost/context/base/mp-text.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-text.mpii
@@ -13,8 +13,7 @@
%D Under construction.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_text : endinput ; fi ;
+if known context_text : endinput ; fi ;
boolean context_text ; context_text := true ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-text.mpiv b/Master/texmf-dist/metapost/context/base/mp-text.mpiv
new file mode 100644
index 00000000000..c7bafeb8a06
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-text.mpiv
@@ -0,0 +1,163 @@
+%D \module
+%D [ file=mp-text.mp,
+%D version=2000.07.10,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=text support,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
+%C details.
+
+%D This one is only used in metafun so it will become a module.
+
+if known context_text : endinput ; fi ;
+
+boolean context_text ; context_text := true ;
+
+def build_parshape (expr p, offset_or_path, dx, dy, baselineskip, strutheight, strutdepth, topskip) =
+
+ if unknown trace_parshape :
+ boolean trace_parshape ; trace_parshape := false ;
+ fi ;
+
+ begingroup ;
+
+ save
+ q, l, r, line, tt, bb,
+ n, hsize, vsize, vvsize, voffset, hoffset, width, indent,
+ ll, lll, rr, rrr, cp, cq, t, b ;
+
+ path
+ q, l, r, line, tt, bb ;
+ numeric
+ n, hsize, vsize, vvsize, voffset, hoffset, width[], indent[] ;
+ pair
+ ll, lll, rr, rrr, cp, cq, t, b ;
+
+ n := 0 ;
+ cp := center p ;
+
+ if path offset_or_path :
+ q := offset_or_path ;
+ cq := center q ;
+ voffset := dy ;
+ hoffset := dx ;
+ else :
+ q := p ;
+ cq := center q ;
+ hoffset := offset_or_path + dx ;
+ voffset := offset_or_path + dy ;
+ fi ;
+
+ hsize := xpart lrcorner q - xpart llcorner q ;
+ vsize := ypart urcorner q - ypart lrcorner q ;
+
+ q := p shifted - cp ;
+
+ startsavingdata ;
+
+ savedata "\global\parvoffset " & decimal voffset&"bp " ;
+ savedata "\global\parhoffset " & decimal hoffset&"bp " ;
+ savedata "\global\parwidth " & decimal hsize&"bp " ;
+ savedata "\global\parheight " & decimal vsize&"bp " ;
+
+ if not path offset_or_path :
+ q := q xscaled ((hsize-2hoffset)/hsize) yscaled ((vsize-2voffset)/vsize) ;
+ fi ;
+
+ hsize := xpart lrcorner q - xpart llcorner q ;
+ vsize := ypart urcorner q - ypart lrcorner q ;
+
+ t := (ulcorner q -- urcorner q) intersection_point q ;
+ b := (llcorner q -- lrcorner q) intersection_point q ;
+
+ if xpart directionpoint t of q < 0 :
+ q := reverse q ;
+ fi ;
+
+ l := q cutbefore t ;
+ l := l if xpart point 0 of q < 0 : & q fi cutafter b ;
+
+ r := q cutbefore b ;
+ r := r if xpart point 0 of q > 0 : & q fi cutafter t ;
+
+ % tt := (ulcorner q -- urcorner q) shifted (0,-topskip) ;
+ % bb := (llcorner q -- lrcorner q) shifted (0,strutdepth) ;
+
+ % l := l cutbefore (l intersection_point tt) ;
+ % l := l cutafter (l intersection_point bb) ;
+ % r := r cutbefore (r intersection_point bb) ;
+ % r := r cutafter (r intersection_point tt) ;
+
+ if trace_parshape :
+ drawarrow p withpen pencircle scaled 2pt withcolor red ;
+ drawarrow l shifted cp withpen pencircle scaled 1pt withcolor green ;
+ drawarrow r shifted cp withpen pencircle scaled 1pt withcolor blue ;
+ fi ;
+
+ vardef found_point (expr lin, pat, sig) =
+ pair a, b ;
+ a := pat intersection_point (lin shifted (0,strutheight)) ;
+ if intersection_found :
+ a := a shifted (0,-strutheight) ;
+ else :
+ a := pat intersection_point lin ;
+ fi ;
+ b := pat intersection_point (lin shifted (0,-strutdepth)) ;
+ if intersection_found :
+ if sig :
+ if xpart b > xpart a : a := b shifted (0,strutdepth) fi ;
+ else :
+ if xpart b < xpart a : a := b shifted (0,strutdepth) fi ;
+ fi ;
+ fi ;
+ a
+ enddef ;
+
+ if (strutheight+strutdepth<baselineskip) :
+ vvsize := vsize ;
+ else :
+ vvsize := (vsize div baselineskip) * baselineskip ;
+ fi ;
+
+ for i=topskip step baselineskip until vvsize :
+
+ line := (ulcorner q -- urcorner q) shifted (0,-i-eps) ;
+
+ ll := found_point(line,l,true ) ;
+ rr := found_point(line,r,false) ;
+
+ if trace_parshape :
+ fill (ll--rr--rr shifted (0,strutheight)--ll shifted (0,strutheight)--cycle) shifted cp withcolor .5white ;
+ fill (ll--rr--rr shifted (0,-strutdepth)--ll shifted (0,-strutdepth)--cycle) shifted cp withcolor .7white ;
+ draw ll shifted cp withpen pencircle scaled 2pt ;
+ draw rr shifted cp withpen pencircle scaled 2pt ;
+ draw (ll--rr) shifted cp withpen pencircle scaled .5pt ;
+ fi ;
+
+ n := n + 1 ;
+ indent[n] := abs(xpart ll - xpart llcorner q) ;
+ width[n] := abs(xpart rr - xpart ll) ;
+
+ if (i=strutheight) and (width[n]<baselineskip) :
+ n := n - 1 ;
+ savedata "\global\chardef\parfirst=1 " ;
+ fi ;
+
+ endfor ;
+
+ savedata "\global\parlines " & decimal n ;
+ savedata "\global\partoks{ " ;
+ for i=1 upto n:
+ savedata decimal indent[i]&"bp " & decimal width[i]&"bp " ;
+ endfor ;
+ savedata "}" ;
+
+ stopsavingdata ;
+
+ endgroup ;
+
+enddef ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-tool.mp b/Master/texmf-dist/metapost/context/base/mp-tool.mpii
index 7f047fefcce..96932d58ab3 100644
--- a/Master/texmf-dist/metapost/context/base/mp-tool.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-tool.mpii
@@ -85,10 +85,6 @@ mpprocset := 1 ;
%
% protect ;
-%D A semicolor to be used in specials: ? ? ?
-
-string semicolor ; semicolor := char 59 ;
-
%D By including this module, \METAPOST\ automatically writes a
%D high resolution boundingbox to the \POSTSCRIPT\ file. This
%D hack is due to John Hobby himself.
@@ -96,8 +92,6 @@ string semicolor ; semicolor := char 59 ;
% When somehow the first one gets no HiRes, then make sure
% that the format matches the mem sizes in the config file.
-% eerste " " er uit
-
string space ; space = char 32 ;
vardef ddecimal primary p =
@@ -132,18 +126,6 @@ cmykcolormodel := 7 ;
let grayscale = numeric ;
-% def colorlike(expr c) text v = % colorlike(a) b, c, d ;
-% forsuffixes i=v : % save i ;
-% if cmykcolor c :
-% cmykcolor i ;
-% elseif rgbcolor c :
-% rgbcolor i ;
-% else :
-% grayscale i ;
-% fi ;
-% endfor ;
-% enddef ;
-
vardef colorlike(text c) text v = % colorlike(a) b, c, d ;
save _p_ ; picture _p_ ;
forsuffixes i=v :
@@ -858,15 +840,15 @@ vardef bottomboundary primary p =
if pair p : p else : (llcorner p -- lrcorner p) fi
enddef ;
-vardef rightboundary primary p =
+vardef rightboundary primary p =
if pair p : p else : (lrcorner p -- urcorner p) fi
enddef ;
-vardef topboundary primary p =
+vardef topboundary primary p =
if pair p : p else : (urcorner p -- ulcorner p) fi
enddef ;
-vardef leftboundary primary p =
+vardef leftboundary primary p =
if pair p : p else : (ulcorner p -- llcorner p) fi
enddef ;
@@ -2131,19 +2113,28 @@ enddef ;
% handy
-vardef bbwidth (expr p) =
- (if known p :
- if path p or picture p :
- xpart (lrcorner p - llcorner p)
- else : 0 fi else : 0
- fi )
+vardef bbwidth (expr p) = % vardef width_of primary p =
+ if known p :
+ if path p or picture p :
+ xpart (lrcorner p - llcorner p)
+ else :
+ 0
+ fi
+ else :
+ 0
+ fi
enddef ;
-vardef bbheight (expr p) =
- (if known p : if path p or picture p :
- ypart (urcorner p - lrcorner p)
- else : 0 fi else : 0
- fi)
+vardef bbheight (expr p) = % vardef heigth_of primary p =
+ if known p :
+ if path p or picture p :
+ ypart (urcorner p - lrcorner p)
+ else :
+ 0
+ fi
+ else :
+ 0
+ fi
enddef ;
color nocolor ; numeric noline ; % both unknown signals
@@ -2262,7 +2253,7 @@ vardef simplified expr p =
(reverse dostraightened(+1,dostraightened(+1,reverse p)))
enddef ;
-vardef unspiked expr p =
+vardef unspiked expr p =
(reverse dostraightened(-1,dostraightened(-1,reverse p)))
enddef ;
@@ -2450,8 +2441,18 @@ enddef ;
% new
-vardef colorpart(expr i) =
- (redpart i, greenpart i,bluepart i)
+% vardef colorpart(expr i) =
+% (redpart i, greenpart i,bluepart i)
+% enddef ;
+
+vardef colorpart(expr c) =
+ if colormodel c = 3 :
+ graypart c
+ elseif colormodel c = 5 :
+ (redpart c,greenpart c,bluepart c)
+ elseif colormodel c = 7 :
+ (cyanpart c,magentapart c,yellowpart c,blackpart c)
+ fi
enddef ;
% for david arnold:
@@ -2561,7 +2562,3 @@ primarydef p snapped s =
fi ; )
p
enddef ;
-
-% done
-
-endinput ;
diff --git a/Master/texmf-dist/metapost/context/base/mp-tool.mpiv b/Master/texmf-dist/metapost/context/base/mp-tool.mpiv
new file mode 100644
index 00000000000..39449b511cf
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/mp-tool.mpiv
@@ -0,0 +1,2183 @@
+%D \module
+%D [ file=mp-tool.mp,
+%D version=1998.02.15,
+%D title=\CONTEXT\ \METAPOST\ graphics,
+%D subtitle=auxiliary macros,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+if known context_tool : endinput ; fi ;
+
+boolean context_tool ; context_tool := true ;
+
+let @## = @# ;
+
+%D New, version number testing:
+%D
+%D \starttyping
+%D fill fullcircle scaled 2cm withcolor if mpversiongt("0.6") : red else : green fi ;
+%D fill fullcircle scaled 1cm withcolor if mpversionlt(0.6) : blue else : white fi ;
+%D \stoptyping
+
+if not known mpversion : string mpversion ; mpversion := "0.641" ; fi ;
+
+% vardef mpversiongt(expr s) =
+% scantokens (mpversion & " > " & if numeric s : decimal s else : s fi)
+% enddef ;
+% vardef mpversionlt(expr s) =
+% scantokens (mpversion & " < " & if numeric s : decimal s else : s fi)
+% enddef ;
+% vardef mpversioneq(expr s) =
+% scantokens (mpversion & " = " & if numeric s : decimal s else : s fi)
+% enddef ;
+
+%D More interesting:
+%D
+%D \starttyping
+%D fill fullcircle scaled 4cm withcolor if mpversiongt("0.6") : red else : green fi ;
+%D fill fullcircle scaled 2cm withcolor if mpversionlt(0.6) : blue else : white fi ;
+%D fill fullcircle scaled 1cm withcolor if mpversioncmp(0.6,">=") : yellow else : black fi ;
+%D \stoptyping
+
+% no longer needed as we load runtime
+
+vardef mpversioncmp(expr s, c) =
+ scantokens (mpversion & c & if numeric s : decimal s else : s fi)
+enddef ;
+
+vardef mpversionlt (expr s) = mpversioncmp(s, "<") enddef ;
+vardef mpversioneq (expr s) = mpversioncmp(s, "=") enddef ;
+vardef mpversiongt (expr s) = mpversioncmp(s, ">") enddef ;
+
+%D We always want \EPS\ conforming output, so we say:
+
+prologues := 1 ;
+warningcheck := 0 ;
+mpprocset := 1 ;
+
+%D Namespace handling:
+
+% let exclamationmark = ! ;
+% let questionmark = ? ;
+%
+% def unprotect =
+% let ! = relax ;
+% let ? = relax ;
+% enddef ;
+%
+% def protect =
+% let ! = exclamationmark ;
+% let ? = questionmark ;
+% enddef ;
+%
+% unprotect ;
+%
+% mp!some!module = 10 ; show mp!some!module ; show somemodule ;
+%
+% protect ;
+
+string space ; space := char 32 ;
+string CRLF ; CRLF := char 10 & char 13 ;
+
+vardef ddecimal primary p =
+ decimal xpart p & " " & decimal ypart p
+enddef ;
+
+%D Colors:
+
+newinternal nocolormodel ; nocolormodel := 1 ;
+newinternal greycolormodel ; greycolormodel := 3 ;
+newinternal graycolormodel ; graycolormodel := 3 ;
+newinternal rgbcolormodel ; rgbcolormodel := 5 ;
+newinternal cmykcolormodel ; cmykcolormodel := 7 ;
+
+let grayscale = numeric ;
+let greyscale = numeric ;
+
+vardef colorpart expr c =
+ if not picture c :
+ 0
+ elseif colormodel c = greycolormodel :
+ greypart c
+ elseif colormodel c = rgbcolormodel :
+ (redpart c,greenpart c,bluepart c)
+ elseif colormodel c = cmykcolormodel :
+ (cyanpart c,magentapart c,yellowpart c,blackpart c)
+ else :
+ 0 % black
+ fi
+enddef ;
+
+vardef colorlike(text c) text v = % colorlike(a) b, c, d ;
+ save _p_ ; picture _p_ ;
+ forsuffixes i=v :
+ _p_ := image(draw origin withcolor c ;) ; % intercept pre and postscripts
+ if (colormodel _p_ = cmykcolormodel) :
+ cmykcolor i ;
+ elseif (colormodel _p_ = rgbcolormodel) :
+ rgbcolor i ;
+ else :
+ greycolor i ;
+ fi ;
+ endfor ;
+enddef ;
+
+%D Also handy (when we flush colors):
+
+vardef dddecimal primary c =
+ decimal redpart c & " " & decimal greenpart c & " " & decimal bluepart c
+enddef ;
+
+vardef ddddecimal primary c =
+ decimal cyanpart c & " " & decimal magentapart c & " " & decimal yellowpart c & " " & decimal blackpart c
+enddef ;
+
+vardef colordecimals primary c =
+ if cmykcolor c :
+ decimal cyanpart c & ":" & decimal magentapart c & ":" & decimal yellowpart c & ":" & decimal blackpart c
+ elseif rgbcolor c :
+ decimal redpart c & ":" & decimal greenpart c & ":" & decimal bluepart c
+ else :
+ decimal c
+ fi
+enddef ;
+
+%D We have standardized data file names:
+
+def job_name =
+ jobname
+enddef ;
+
+def data_mpd_file =
+ job_name & "-mp.mpd"
+enddef ;
+
+%D Because \METAPOST\ has a hard coded limit of 4~datafiles,
+%D we need some trickery when we have multiple files.
+
+if unknown collapse_data :
+ boolean collapse_data ;
+ collapse_data := false ;
+fi ;
+
+boolean savingdata ; savingdata := false ;
+boolean savingdatadone ; savingdatadone := false ;
+
+def savedata expr txt =
+ write if collapse_data :
+ txt
+ else :
+ if savingdata : txt else : "\MPdata{" & decimal charcode & "}{" & txt & "}" fi & "%"
+ fi to data_mpd_file ;
+enddef ;
+
+def startsavingdata =
+ savingdata := true ;
+ savingdatadone := true ;
+ if collapse_data :
+ write "\MPdata{" & decimal charcode & "}{%" to data_mpd_file ;
+ fi ;
+enddef ;
+
+def stopsavingdata =
+ if collapse_data :
+ write "}%" to data_mpd_file ;
+ fi ;
+ savingdata := false ;
+enddef ;
+
+def finishsavingdata =
+ if savingdatadone :
+ write EOF to data_mpd_file ;
+ savingdatadone := false ;
+ fi ;
+enddef ;
+
+%D Instead of a keystroke eating save and allocation
+%D sequence, you can use the \citeer {new} alternatives to
+%D save and allocate in one command.
+
+def newcolor text v = forsuffixes i=v : save i ; color i ; endfor ; enddef ;
+def newnumeric text v = forsuffixes i=v : save i ; numeric i ; endfor ; enddef ;
+def newboolean text v = forsuffixes i=v : save i ; boolean i ; endfor ; enddef ;
+def newtransform text v = forsuffixes i=v : save i ; transform i ; endfor ; enddef ;
+def newpath text v = forsuffixes i=v : save i ; path i ; endfor ; enddef ;
+def newpicture text v = forsuffixes i=v : save i ; picture i ; endfor ; enddef ;
+def newstring text v = forsuffixes i=v : save i ; string i ; endfor ; enddef ;
+def newpair text v = forsuffixes i=v : save i ; pair i ; endfor ; enddef ;
+
+%D Sometimes we don't want parts of the graphics add to the
+%D bounding box. One way of doing this is to save the bounding
+%D box, draw the graphics that may not count, and restore the
+%D bounding box.
+%D
+%D \starttypen
+%D push_boundingbox currentpicture;
+%D pop_boundingbox currentpicture;
+%D \stoptypen
+%D
+%D The bounding box can be called with:
+%D
+%D \starttypen
+%D boundingbox currentpicture
+%D inner_boundingbox currentpicture
+%D outer_boundingbox currentpicture
+%D \stoptypen
+%D
+%D Especially the latter one can be of use when we include
+%D the graphic in a document that is clipped to the bounding
+%D box. In such occasions one can use:
+%D
+%D \starttypen
+%D set_outer_boundingbox currentpicture;
+%D \stoptypen
+%D
+%D Its counterpart is:
+%D
+%D \starttypen
+%D set_inner_boundingbox p
+%D \stoptypen
+
+path mfun_boundingbox_stack ;
+numeric mfun_boundingbox_stack_depth ;
+
+mfun_boundingbox_stack_depth := 0 ;
+
+def pushboundingbox text p =
+ mfun_boundingbox_stack_depth := mfun_boundingbox_stack_depth + 1 ;
+ mfun_boundingbox_stack[mfun_boundingbox_stack_depth] := boundingbox p ;
+enddef ;
+
+def popboundingbox text p =
+ setbounds p to mfun_boundingbox_stack[mfun_boundingbox_stack_depth] ;
+ mfun_boundingbox_stack[mfun_boundingbox_stack_depth] := origin ;
+ mfun_boundingbox_stack_depth := mfun_boundingbox_stack_depth - 1 ;
+enddef ;
+
+let push_boundingbox = pushboundingbox ; % downward compatible
+let pop_boundingbox = popboundingbox ; % downward compatible
+
+vardef boundingbox primary p =
+ if (path p) or (picture p) :
+ llcorner p -- lrcorner p -- urcorner p -- ulcorner p
+ else :
+ origin
+ fi -- cycle
+enddef;
+
+vardef innerboundingbox primary p =
+ top rt llcorner p --
+ top lft lrcorner p --
+ bot lft urcorner p --
+ bot rt ulcorner p -- cycle
+enddef;
+
+vardef outerboundingbox primary p =
+ bot lft llcorner p --
+ bot rt lrcorner p --
+ top rt urcorner p --
+ top lft ulcorner p -- cycle
+enddef;
+
+def inner_boundingbox = innerboundingbox enddef ;
+def outer_boundingbox = outerboundingbox enddef ;
+
+vardef set_inner_boundingbox text q = % obsolete
+ setbounds q to innerboundingbox q;
+enddef;
+
+vardef set_outer_boundingbox text q = % obsolete
+ setbounds q to outerboundingbox q;
+enddef;
+
+%D Some missing functions can be implemented rather
+%D straightforward:
+
+numeric Pi ; Pi := 3.1415926 ;
+
+vardef sqr primary x = x*x enddef ;
+vardef log primary x = if x=0: 0 else: mlog(x)/mlog(10) fi enddef ;
+vardef ln primary x = if x=0: 0 else: mlog(x)/256 fi enddef ;
+vardef exp primary x = (mexp 256)**x enddef ;
+vardef inv primary x = if x=0: 0 else: x**-1 fi enddef ;
+
+vardef pow (expr x,p) = x**p enddef ;
+
+vardef asin primary x = x+(x**3)/6+3(x**5)/40 enddef ;
+vardef acos primary x = asin(-x) enddef ;
+vardef atan primary x = x-(x**3)/3+(x**5)/5-(x**7)/7 enddef ;
+vardef tand primary x = sind(x)/cosd(x) enddef ;
+
+%D Here are Taco Hoekwater's alternatives (but vardef'd and primaried).
+
+pi := 3.1415926 ; radian := 180/pi ; % 2pi*radian = 360 ;
+
+vardef tand primary x = sind(x)/cosd(x) enddef ;
+vardef cotd primary x = cosd(x)/sind(x) enddef ;
+
+vardef sin primary x = sind(x*radian) enddef ;
+vardef cos primary x = cosd(x*radian) enddef ;
+vardef tan primary x = sin(x)/cos(x) enddef ;
+vardef cot primary x = cos(x)/sin(x) enddef ;
+
+vardef asin primary x = angle((1+-+x,x)) enddef ;
+vardef acos primary x = angle((x,1+-+x)) enddef ;
+
+vardef invsin primary x = (asin(x))/radian enddef ;
+vardef invcos primary x = (acos(x))/radian enddef ;
+
+vardef acosh primary x = ln(x+(x+-+1)) enddef ;
+vardef asinh primary x = ln(x+(x++1)) enddef ;
+
+vardef sinh primary x = save xx ; xx = exp x ; (xx-1/xx)/2 enddef ;
+vardef cosh primary x = save xx ; xx = exp x ; (xx+1/xx)/2 enddef ;
+
+%D We provide two macros for drawing stripes across a shape.
+%D The first method (with the n suffix) uses another method,
+%D slower in calculation, but more efficient when drawn. The
+%D first macro divides the sides into n equal parts. The
+%D first argument specifies the way the lines are drawn, while
+%D the second argument identifier the way the shape is to be
+%D drawn.
+%D
+%D \starttypen
+%D stripe_path_n
+%D (dashed evenly withcolor blue)
+%D (filldraw)
+%D fullcircle xscaled 100 yscaled 40 shifted (50,50) withpen pencircle scaled 4;
+%D \stoptypen
+%D
+%D The a (or angle) alternative supports arbitrary angles and
+%D is therefore more versatile.
+%D
+%D \starttypen
+%D stripe_path_a
+%D (withpen pencircle scaled 2 withcolor red)
+%D (draw)
+%D fullcircle xscaled 100 yscaled 40 withcolor blue;
+%D \stoptypen
+%D
+%D The first alternative obeys:
+
+stripe_n := 10;
+stripe_slot := 3;
+
+%D When no pen dimensions are passed, the slot determines
+%D the spacing.
+%D
+%D The angle alternative is influenced by:
+
+% to be redone: use image
+
+stripe_gap := 5;
+stripe_angle := 45;
+
+def stripe_path_n (text s_spec) (text s_draw) expr s_path =
+ do_stripe_path_n (s_spec) (s_draw) (s_path)
+enddef;
+
+def do_stripe_path_n (text s_spec) (text s_draw) (expr s_path) text s_text =
+ begingroup ;
+ save curpic, newpic, bb, pp, ww ;
+ picture curpic, newpic ;
+ path bb, pp ;
+ pp := s_path ;
+ curpic := currentpicture ;
+ currentpicture := nullpicture ;
+ s_draw pp s_text ;
+ bb := boundingbox currentpicture ;
+ newpic := currentpicture ;
+ currentpicture := nullpicture;
+ ww := min(ypart urcorner newpic - ypart llcorner newpic,xpart urcorner newpic - xpart llcorner newpic) ;
+ ww := ww/(stripe_slot*stripe_n) ;
+ for i=1/stripe_n step 1/stripe_n until 1 :
+ draw point (1+i) of bb -- point (3-i) of bb withpen pencircle scaled ww s_spec ;
+ endfor ;
+ for i=0 step 1/stripe_n until 1 :
+ draw point (3+i) of bb -- point (1-i) of bb withpen pencircle scaled ww s_spec;
+ endfor ;
+ clip currentpicture to pp ;
+ addto newpic also currentpicture ;
+ currentpicture := curpic ;
+ addto currentpicture also newpic ;
+ endgroup ;
+enddef ;
+
+def stripe_path_a (text s_spec) (text s_draw) expr s_path =
+ do_stripe_path_a (s_spec) (s_draw) (s_path)
+enddef;
+
+def do_stripe_path_a (text s_spec) (text s_draw) (expr s_path) text s_text =
+ begingroup ;
+ save curpic, newpic, pp; picture curpic, newpic; path pp ;
+ pp := s_path ;
+ curpic := currentpicture ;
+ currentpicture := nullpicture ;
+ s_draw pp s_text ;
+ def do_stripe_rotation (expr p) =
+ (currentpicture rotatedaround(center p,stripe_angle))
+ enddef ;
+ s_max := max (
+ xpart llcorner do_stripe_rotation(currentpicture),
+ xpart urcorner do_stripe_rotation(currentpicture),
+ ypart llcorner do_stripe_rotation(currentpicture),
+ ypart urcorner do_stripe_rotation(currentpicture)
+ ) ;
+ newpic := currentpicture ;
+ currentpicture := nullpicture ;
+ for i=-s_max-.5stripe_gap step stripe_gap until s_max :
+ draw (-s_max,i)--(s_max,i) s_spec ;
+ endfor ;
+ currentpicture := do_stripe_rotation(newpic) ;
+ clip currentpicture to pp ;
+ addto newpic also currentpicture ;
+ currentpicture := curpic ;
+ addto currentpicture also newpic ;
+ endgroup ;
+enddef;
+
+%D A few normalizing macros:
+
+primarydef p xsized w =
+ (p if (bbwidth (p)>0) and (w>0) : scaled (w/bbwidth (p)) fi)
+enddef ;
+
+primarydef p ysized h =
+ (p if (bbheight(p)>0) and (h>0) : scaled (h/bbheight(p)) fi)
+enddef ;
+
+primarydef p xysized s =
+ begingroup
+ save wh, w, h ; pair wh ; numeric w, h ;
+ wh := paired (s) ; w := bbwidth(p) ; h := bbheight(p) ;
+ p
+ if (w>0) and (h>0) :
+ if xpart wh > 0 : xscaled (xpart wh/w) fi
+ if ypart wh > 0 : yscaled (ypart wh/h) fi
+ fi
+ endgroup
+enddef ;
+
+let sized = xysized ;
+
+def xscale_currentpicture(expr w) = % obsolete
+ currentpicture := currentpicture xsized w ;
+enddef;
+
+def yscale_currentpicture(expr h) = % obsolete
+ currentpicture := currentpicture ysized h ;
+enddef;
+
+def xyscale_currentpicture(expr w, h) = % obsolete
+ currentpicture := currentpicture xysized (w,h) ;
+enddef;
+
+def scale_currentpicture(expr w, h) = % obsolete
+ currentpicture := currentpicture xsized w ;
+ currentpicture := currentpicture ysized h ;
+enddef;
+
+%D A full circle is centered at the origin, while a unitsquare
+%D is located in the first quadrant. Now guess what kind of
+%D path fullsquare and unitcircle do return.
+
+path fullsquare, unitcircle ;
+
+fullsquare := unitsquare shifted - center unitsquare ;
+unitcircle := fullcircle shifted urcorner fullcircle ;
+
+%D Some more paths:
+
+path urcircle, ulcircle, llcircle, lrcircle ;
+
+urcircle := origin -- (+.5,0) & (+.5,0){up} .. (0,+.5) & (0,+.5) -- cycle ;
+ulcircle := origin -- (0,+.5) & (0,+.5){left} .. (-.5,0) & (-.5,0) -- cycle ;
+llcircle := origin -- (-.5,0) & (-.5,0){down} .. (0,-.5) & (0,-.5) -- cycle ;
+lrcircle := origin -- (0,-.5) & (0,-.5){right} .. (+.5,0) & (+.5,0) -- cycle ;
+
+path tcircle, bcircle, lcircle, rcircle ;
+
+tcircle = origin -- (+.5,0) & (+.5,0) {up} .. (0,+.5) .. {down} (-.5,0) -- cycle ;
+bcircle = origin -- (-.5,0) & (-.5,0) {down} .. (0,-.5) .. {up} (+.5,0) -- cycle ;
+lcircle = origin -- (0,+.5) & (0,+.5) {left} .. (-.5,0) .. {right} (0,-.5) -- cycle ;
+rcircle = origin -- (0,-.5) & (0,-.5) {right} .. (+.5,0) .. {left} (0,+.5) -- cycle ;
+
+path urtriangle, ultriangle, lltriangle, lrtriangle ; % watch out: it's contrary to what you expect and starts in the origin
+
+urtriangle := origin -- (+.5,0) -- (0,+.5) -- cycle ;
+ultriangle := origin -- (0,+.5) -- (-.5,0) -- cycle ;
+lltriangle := origin -- (-.5,0) -- (0,-.5) -- cycle ;
+lrtriangle := origin -- (0,-.5) -- (+.5,0) -- cycle ;
+
+path unitdiamond, fulldiamond ;
+
+unitdiamond := (.5,0) -- (1,.5) -- (.5,1) -- (0,.5) -- cycle ;
+fulldiamond := unitdiamond shifted - center unitdiamond ;
+
+%D More robust:
+
+% let normalscaled = scaled ;
+% let normalxscaled = xscaled ;
+% let normalyscaled = yscaled ;
+%
+% def scaled expr s = normalscaled (s) enddef ;
+% def xscaled expr s = normalxscaled (s) enddef ;
+% def yscaled expr s = normalyscaled (s) enddef ;
+
+%D Shorter
+
+primarydef p xyscaled q = % secundarydef does not work out well
+ begingroup
+ save qq ; pair qq ;
+ qq = paired(q) ;
+ p
+ if xpart qq <> 0 : xscaled (xpart qq) fi
+ if ypart qq <> 0 : yscaled (ypart qq) fi
+ endgroup
+enddef ;
+
+%D Some personal code that might move to another module
+
+def set_grid(expr w, h, nx, ny) =
+ boolean grid[][] ; boolean grid_full ;
+ numeric grid_w, grid_h, grid_nx, grid_ny, grid_x, grid_y, grid_left ;
+ grid_w := w ;
+ grid_h := h ;
+ grid_nx := nx ;
+ grid_ny := ny ;
+ grid_x := round(w/grid_nx) ; % +.5) ;
+ grid_y := round(h/grid_ny) ; % +.5) ;
+ grid_left := (1+grid_x)*(1+grid_y) ;
+ grid_full := false ;
+ for i=0 upto grid_x :
+ for j=0 upto grid_y :
+ grid[i][j] := false ;
+ endfor ;
+ endfor ;
+enddef ;
+
+vardef new_on_grid(expr _dx_, _dy_) =
+ dx := _dx_ ;
+ dy := _dy_ ;
+ ddx := min(round(dx/grid_nx),grid_x) ; % +.5),grid_x) ;
+ ddy := min(round(dy/grid_ny),grid_y) ; % +.5),grid_y) ;
+ if not grid_full and not grid[ddx][ddy] :
+ grid[ddx][ddy] := true ;
+ grid_left := grid_left-1 ;
+ grid_full := (grid_left=0) ;
+ true
+ else :
+ false
+ fi
+enddef ;
+
+%D usage: \type{innerpath peepholed outerpath}.
+%D
+%D beginfig(1);
+%D def fullsquare = (unitsquare shifted -center unitsquare) enddef ;
+%D fill (fullsquare scaled 200) withcolor red ;
+%D path p ; p := (fullcircle scaled 100) ; bboxmargin := 0 ;
+%D fill p peepholed bbox p ;
+%D endfig;
+
+secondarydef p peepholed q =
+ begingroup
+ save start ; pair start ;
+ start := point 0 of p ;
+ if xpart start >= xpart center p :
+ if ypart start >= ypart center p :
+ urcorner q -- ulcorner q -- llcorner q -- lrcorner q --
+ reverse p -- lrcorner q -- cycle
+ else :
+ lrcorner q -- urcorner q -- ulcorner q -- llcorner q --
+ reverse p -- llcorner q -- cycle
+ fi
+ else :
+ if ypart start > ypart center p :
+ ulcorner q -- llcorner q -- lrcorner q -- urcorner q --
+ reverse p -- urcorner q -- cycle
+ else :
+ llcorner q -- lrcorner q -- urcorner q -- ulcorner q --
+ reverse p -- ulcorner q -- cycle
+ fi
+ fi
+ endgroup
+enddef ;
+
+boolean intersection_found ;
+
+secondarydef p intersection_point q =
+ begingroup
+ save x_, y_ ;
+ (x_,y_) = p intersectiontimes q ;
+ if x_<0 :
+ intersection_found := false ;
+ center p % origin
+ else :
+ intersection_found := true ;
+ .5[point x_ of p, point y_ of q]
+ fi
+ endgroup
+enddef ;
+
+%D New, undocumented, experimental:
+
+vardef tensecircle (expr width, height, offset) =
+ (-width/2,-height/2) ... (0,-height/2-offset) ...
+ (+width/2,-height/2) ... (+width/2+offset,0) ...
+ (+width/2,+height/2) ... (0,+height/2+offset) ...
+ (-width/2,+height/2) ... (-width/2-offset,0) ... cycle
+enddef ;
+
+vardef roundedsquare (expr width, height, offset) =
+ (offset,0) -- (width-offset,0) {right} ..
+ (width,offset) -- (width,height-offset) {up} ..
+ (width-offset,height) -- (offset,height) {left} ..
+ (0,height-offset) -- (0,offset) {down} .. cycle
+enddef ;
+
+%D Some colors.
+
+def colortype(expr c) =
+ if cmykcolor c : cmykcolor elseif rgbcolor c : rgbcolor else : grayscale fi
+enddef ;
+
+vardef whitecolor(expr c) =
+ if cmykcolor c : (0,0,0,0) elseif rgbcolor c : (1,1,1) else : 1 fi
+enddef ;
+
+vardef blackcolor(expr c) =
+ if cmykcolor c : (0,0,0,1) elseif rgbcolor c : (0,0,0) else : 0 fi
+enddef ;
+
+%D Well, this is the dangerous and naive version:
+
+def drawfill text t =
+ fill t ;
+ draw t ;
+enddef;
+
+%D This two step approach saves the path first, since it can
+%D be a function. Attributes must not be randomized.
+
+def drawfill expr c =
+ path _c_ ; _c_ := c ;
+ mfun_do_drawfill
+enddef ;
+
+def mfun_do_drawfill text t =
+ draw _c_ t ;
+ fill _c_ t ;
+enddef;
+
+def undrawfill expr c =
+ drawfill c withcolor background % rather useless
+enddef ;
+
+%D Moved from mp-char.mp
+
+vardef paired primary d =
+ if pair d : d else : (d,d) fi
+enddef ;
+
+vardef tripled primary d =
+ if color d : d else : (d,d,d) fi
+enddef ;
+
+% maybe secondaries:
+
+primarydef p enlarged d = ( p llmoved d -- p lrmoved d -- p urmoved d -- p ulmoved d -- cycle ) enddef ;
+primarydef p llenlarged d = ( p llmoved d -- lrcorner p -- urcorner p -- ulcorner p -- cycle ) enddef ;
+primarydef p lrenlarged d = ( llcorner p -- p lrmoved d -- urcorner p -- ulcorner p -- cycle ) enddef ;
+primarydef p urenlarged d = ( llcorner p -- lrcorner p -- p urmoved d -- ulcorner p -- cycle ) enddef ;
+primarydef p ulenlarged d = ( llcorner p -- lrcorner p -- urcorner p -- p ulmoved d -- cycle ) enddef ;
+
+primarydef p llmoved d = ( (llcorner p) shifted (-xpart paired(d),-ypart paired(d)) ) enddef ;
+primarydef p lrmoved d = ( (lrcorner p) shifted (+xpart paired(d),-ypart paired(d)) ) enddef ;
+primarydef p urmoved d = ( (urcorner p) shifted (+xpart paired(d),+ypart paired(d)) ) enddef ;
+primarydef p ulmoved d = ( (ulcorner p) shifted (-xpart paired(d),+ypart paired(d)) ) enddef ;
+
+primarydef p leftenlarged d = ( (llcorner p) shifted (-d,0) -- lrcorner p -- urcorner p -- (ulcorner p) shifted (-d,0) -- cycle ) enddef ;
+primarydef p rightenlarged d = ( llcorner p -- (lrcorner p) shifted (d,0) -- (urcorner p) shifted (d,0) -- ulcorner p -- cycle ) enddef ;
+primarydef p topenlarged d = ( llcorner p -- lrcorner p -- (urcorner p) shifted (0,d) -- (ulcorner p) shifted (0,d) -- cycle ) enddef ;
+primarydef p bottomenlarged d = ( llcorner p shifted (0,-d) -- lrcorner p shifted (0,-d) -- urcorner p -- ulcorner p -- cycle ) enddef ;
+
+%D Handy for testing/debugging:
+
+primarydef p crossed d = (
+ if pair p :
+ p shifted (-d, 0) -- p --
+ p shifted ( 0,-d) -- p --
+ p shifted (+d, 0) -- p --
+ p shifted ( 0,+d) -- p -- cycle
+ else :
+ center p shifted (-d, 0) -- llcorner p --
+ center p shifted ( 0,-d) -- lrcorner p --
+ center p shifted (+d, 0) -- urcorner p --
+ center p shifted ( 0,+d) -- ulcorner p -- cycle
+ fi
+) enddef ;
+
+%D Also handy (math ladders):
+
+vardef laddered primary p = % was expr
+ point 0 of p
+ for i=1 upto length(p) :
+ -- (xpart (point i of p), ypart (point (i-1) of p)) -- (point i of p)
+ endfor
+enddef ;
+
+%D Saves typing:
+
+% vardef bottomboundary primary p = (llcorner p -- lrcorner p) enddef ;
+% vardef rightboundary primary p = (lrcorner p -- urcorner p) enddef ;
+% vardef topboundary primary p = (urcorner p -- ulcorner p) enddef ;
+% vardef leftboundary primary p = (ulcorner p -- llcorner p) enddef ;
+
+vardef bottomboundary primary p = if pair p : p else : (llcorner p -- lrcorner p) fi enddef ;
+vardef rightboundary primary p = if pair p : p else : (lrcorner p -- urcorner p) fi enddef ;
+vardef topboundary primary p = if pair p : p else : (urcorner p -- ulcorner p) fi enddef ;
+vardef leftboundary primary p = if pair p : p else : (ulcorner p -- llcorner p) fi enddef ;
+
+%D Nice too:
+
+primarydef p superellipsed s =
+ superellipse (
+ .5[lrcorner p,urcorner p],
+ .5[urcorner p,ulcorner p],
+ .5[ulcorner p,llcorner p],
+ .5[llcorner p,lrcorner p],
+ s
+ )
+enddef ;
+
+primarydef p squeezed s = (
+ (llcorner p .. .5[llcorner p,lrcorner p] shifted ( 0, ypart paired(s)) .. lrcorner p) &
+ (lrcorner p .. .5[lrcorner p,urcorner p] shifted (-xpart paired(s), 0) .. urcorner p) &
+ (urcorner p .. .5[urcorner p,ulcorner p] shifted ( 0,-ypart paired(s)) .. ulcorner p) &
+ (ulcorner p .. .5[ulcorner p,llcorner p] shifted ( xpart paired(s), 0) .. llcorner p) & cycle
+) enddef ;
+
+primarydef p randomshifted s =
+ begingroup ;
+ save ss ; pair ss ;
+ ss := paired(s) ;
+ p shifted (-.5xpart ss + uniformdeviate xpart ss,-.5ypart ss + uniformdeviate ypart ss)
+ endgroup
+enddef ;
+
+primarydef p randomized s = (
+ if path p :
+ for i=0 upto length(p)-1 :
+ ((point i of p) randomshifted s) .. controls
+ ((postcontrol i of p) randomshifted s) and
+ ((precontrol (i+1) of p) randomshifted s) ..
+ endfor
+ if cycle p :
+ cycle
+ else :
+ ((point length(p) of p) randomshifted s)
+ fi
+ elseif pair p :
+ p randomshifted s
+ elseif cmykcolor p :
+ if color s :
+ (uniformdeviate cyanpart s * cyanpart p,
+ uniformdeviate magentapart s * magentapart p,
+ uniformdeviate yellowpart s * yellowpart p,
+ uniformdeviate blackpart s * blackpart p)
+ elseif pair s :
+ ((xpart s + uniformdeviate (ypart s - xpart s)) * p)
+ else :
+ (uniformdeviate s * p)
+ fi
+ elseif rgbcolor p :
+ if color s :
+ (uniformdeviate redpart s * redpart p,
+ uniformdeviate greenpart s * greenpart p,
+ uniformdeviate bluepart s * bluepart p)
+ elseif pair s :
+ ((xpart s + uniformdeviate (ypart s - xpart s)) * p)
+ else :
+ (uniformdeviate s * p)
+ fi
+ elseif color p :
+ if color s :
+ (uniformdeviate greypart s * greypart p)
+ elseif pair s :
+ ((xpart s + uniformdeviate (ypart s - xpart s)) * p)
+ else :
+ (uniformdeviate s * p)
+ fi
+ else :
+ p + uniformdeviate s
+ fi
+) enddef ;
+
+%D Not perfect (alternative for interpath)
+
+vardef interpolated(expr s, p, q) =
+ save m ; numeric m ;
+ m := max(length(p),length(q)) ;
+ if path p :
+ for i=0 upto m-1 :
+ s[point (i /m) along p,point (i /m) along q] .. controls
+ s[postcontrol (i /m) along p,postcontrol (i /m) along q] and
+ s[precontrol ((i+1)/m) along p,precontrol ((i+1)/m) along q] ..
+ endfor
+ if cycle p :
+ cycle
+ else :
+ s[point infinity of p,point infinity of q]
+ fi
+ else :
+ a[p,q]
+ fi
+enddef ;
+
+%D Interesting too:
+
+primarydef p paralleled d = (
+ p shifted if d < 0 : - fi ((point abs(d) on (p rotatedaround(point 0 of p,90))) - point 0 of p)
+) enddef ;
+
+vardef punked primary p =
+ point 0 of p for i=1 upto length(p)-1 : -- point i of p endfor
+ if cycle p : -- cycle else : -- point length(p) of p fi
+enddef ;
+
+vardef curved primary p =
+ point 0 of p for i=1 upto length(p)-1 : .. point i of p endfor
+ if cycle p : .. cycle else : .. point length(p) of p fi
+enddef ;
+
+primarydef p blownup s =
+ begingroup
+ save _p_ ; path _p_ ;
+ _p_ := p xysized (bbwidth(p)+2(xpart paired(s)),bbheight(p)+2(ypart paired(s))) ;
+ (_p_ shifted (center p - center _p_))
+ endgroup
+enddef ;
+
+%D Rather fundamental.
+
+% not yet ok
+
+vardef leftrightpath(expr p, l) = % used in s-pre-19
+ save q, r, t, b ; path q, r ; pair t, b ;
+ t := (ulcorner p -- urcorner p) intersection_point p ;
+ b := (llcorner p -- lrcorner p) intersection_point p ;
+ r := if xpart directionpoint t of p < 0 : reverse p else : p fi ; % r is needed, else problems when reverse is fed
+ q := r cutbefore if l: t else: b fi ;
+ q := q if xpart point 0 of r > 0 : & r fi cutafter if l: b else: t fi ;
+ q
+enddef ;
+
+vardef leftpath expr p = leftrightpath(p,true ) enddef ;
+vardef rightpath expr p = leftrightpath(p,false) enddef ;
+
+%D Drawoptions
+
+def saveoptions =
+ save _op_ ; def _op_ = enddef ;
+enddef ;
+
+%D Tracing. (not yet in lexer)
+
+let normaldraw = draw ;
+let normalfill = fill ;
+
+% bugged in mplib so ...
+
+def normalfill expr c = addto currentpicture contour c _op_ enddef ;
+def normaldraw expr p = addto currentpicture if picture p: also p else: doublepath p withpen currentpen fi _op_ enddef ;
+
+def drawlineoptions (text t) = def _lin_opt_ = t enddef ; enddef ;
+def drawpointoptions (text t) = def _pnt_opt_ = t enddef ; enddef ;
+def drawcontroloptions(text t) = def _ctr_opt_ = t enddef ; enddef ;
+def drawlabeloptions (text t) = def _lab_opt_ = t enddef ; enddef ;
+def draworiginoptions (text t) = def _ori_opt_ = t enddef ; enddef ;
+def drawboundoptions (text t) = def _bnd_opt_ = t enddef ; enddef ;
+def drawpathoptions (text t) = def _pth_opt_ = t enddef ; enddef ;
+
+def resetdrawoptions =
+ drawlineoptions (withpen pencircle scaled 1pt withcolor .5white) ;
+ drawpointoptions (withpen pencircle scaled 4pt withcolor black) ;
+ drawcontroloptions(withpen pencircle scaled 2.5pt withcolor black) ;
+ drawlabeloptions () ;
+ draworiginoptions (withpen pencircle scaled 1pt withcolor .5white) ;
+ drawboundoptions (dashed evenly _ori_opt_) ;
+ drawpathoptions (withpen pencircle scaled 5pt withcolor .8white) ;
+enddef ;
+
+resetdrawoptions ;
+
+%D Path.
+
+def drawpath expr p =
+ normaldraw p _pth_opt_
+enddef ;
+
+%D Arrow.
+
+vardef drawarrowpath expr p =
+ save autoarrows ; boolean autoarrows ; autoarrows := true ;
+ drawarrow p _pth_opt_
+enddef ;
+
+def midarrowhead expr p =
+ arrowhead p cutafter (point length(p cutafter point .5 along p)+ahlength on p)
+enddef ;
+
+vardef arrowheadonpath (expr p, s) =
+ save autoarrows ; boolean autoarrows ;
+ autoarrows := true ;
+ set_ahlength(scaled ahfactor) ; % added
+ arrowhead p if s<1 : cutafter (point (s*arclength(p)+.5ahlength) on p) fi
+enddef ;
+
+%D Points.
+
+def drawpoint expr c =
+ if string c :
+ string _c_ ;
+ _c_ := "(" & c & ")" ;
+ dotlabel.urt(_c_, scantokens _c_) ;
+ drawdot scantokens _c_
+ else :
+ dotlabel.urt("(" & decimal xpart c & "," & decimal ypart c & ")", c) ;
+ drawdot c
+ fi _pnt_opt_
+enddef ;
+
+%D PathPoints.
+
+def drawpoints expr c = path _c_ ; _c_ := c ; mfun_draw_points enddef ;
+def drawcontrolpoints expr c = path _c_ ; _c_ := c ; mfun_draw_controlpoints enddef ;
+def drawcontrollines expr c = path _c_ ; _c_ := c ; mfun_draw_controllines enddef ;
+def drawpointlabels expr c = path _c_ ; _c_ := c ; mfun_draw_pointlabels enddef ;
+
+def mfun_draw_points text t =
+ for _i_=0 upto length(_c_) :
+ normaldraw point _i_ of _c_ _pnt_opt_ t ;
+ endfor ;
+enddef;
+
+def mfun_draw_controlpoints text t =
+ for _i_=0 upto length(_c_) :
+ normaldraw precontrol _i_ of _c_ _ctr_opt_ t ;
+ normaldraw postcontrol _i_ of _c_ _ctr_opt_ t ;
+ endfor ;
+enddef;
+
+def mfun_draw_controllines text t =
+ for _i_=0 upto length(_c_) :
+ normaldraw point _i_ of _c_ -- precontrol _i_ of _c_ _lin_opt_ t ;
+ normaldraw point _i_ of _c_ -- postcontrol _i_ of _c_ _lin_opt_ t ;
+ endfor ;
+enddef;
+
+boolean swappointlabels ; swappointlabels := false ;
+
+def mfun_draw_pointlabels text t =
+ for _i_=0 upto length(_c_) :
+ pair _u_ ; _u_ := unitvector(direction _i_ of _c_) rotated if swappointlabels : - fi 90 ;
+ pair _p_ ; _p_ := (point _i_ of _c_) ;
+ _u_ := 12 * defaultscale * _u_ ;
+ normaldraw thelabel ( decimal _i_, _p_ shifted if cycle _c_ and (_i_=0) : - fi _u_ ) _lab_opt_ t ;
+ endfor ;
+enddef;
+
+%D Bounding box.
+
+def drawboundingbox expr p =
+ normaldraw boundingbox p _bnd_opt_
+enddef ;
+
+%D Origin.
+
+numeric originlength ; originlength := .5cm ;
+
+def draworigin text t =
+ normaldraw (origin shifted (0, originlength) -- origin shifted (0,-originlength)) _ori_opt_ t ;
+ normaldraw (origin shifted ( originlength,0) -- origin shifted (-originlength,0)) _ori_opt_ t ;
+enddef;
+
+%D Axis.
+
+numeric tickstep ; tickstep := 5mm ;
+numeric ticklength ; ticklength := 2mm ;
+
+def drawxticks expr c = path _c_ ; _c_ := c ; mfun_draw_xticks enddef ;
+def drawyticks expr c = path _c_ ; _c_ := c ; mfun_draw_yticks enddef ;
+def drawticks expr c = path _c_ ; _c_ := c ; mfun_draw_ticks enddef ;
+
+% Adding eps prevents disappearance due to rounding errors.
+
+def mfun_draw_xticks text t =
+ for i=0 step -tickstep until xpart llcorner _c_ - eps :
+ if (i<=xpart lrcorner _c_) :
+ normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ;
+ fi ;
+ endfor ;
+ for i=0 step tickstep until xpart lrcorner _c_ + eps :
+ if (i>=xpart llcorner _c_) :
+ normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ;
+ fi ;
+ endfor ;
+ normaldraw (llcorner _c_ -- ulcorner _c_) shifted (-xpart llcorner _c_,0) _ori_opt_ t ;
+enddef ;
+
+def mfun_draw_yticks text t =
+ for i=0 step -tickstep until ypart llcorner _c_ - eps :
+ if (i<=ypart ulcorner _c_) :
+ normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ;
+ fi ;
+ endfor ;
+ for i=0 step tickstep until ypart ulcorner _c_ + eps :
+ if (i>=ypart llcorner _c_) :
+ normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ;
+ fi ;
+ endfor ;
+ normaldraw (llcorner _c_ -- lrcorner _c_) shifted (0,-ypart llcorner _c_) _ori_opt_ t ;
+enddef ;
+
+def mfun_draw_ticks text t =
+ drawxticks _c_ t ;
+ drawyticks _c_ t ;
+enddef ;
+
+%D All of it except axis.
+
+def drawwholepath expr p =
+ draworigin ;
+ drawpath p ;
+ drawcontrollines p ;
+ drawcontrolpoints p ;
+ drawpoints p ;
+ drawboundingbox p ;
+ drawpointlabels p ;
+enddef ;
+
+%D Tracing.
+
+def visualizeddraw expr c =
+ if picture c : normaldraw c else : path _c_ ; _c_ := c ; do_visualizeddraw fi
+enddef ;
+
+def visualizedfill expr c =
+ if picture c : normalfill c else : path _c_ ; _c_ := c ; do_visualizedfill fi
+enddef ;
+
+def do_visualizeddraw text t =
+ draworigin ;
+ drawpath _c_ t ;
+ drawcontrollines _c_ ;
+ drawcontrolpoints _c_ ;
+ drawpoints _c_ ;
+ drawboundingbox _c_ ;
+ drawpointlabels _c_ ;
+enddef ;
+
+def do_visualizedfill text t =
+ if cycle _c_ : normalfill _c_ t fi ;
+ draworigin ;
+ drawcontrollines _c_ ;
+ drawcontrolpoints _c_ ;
+ drawpoints _c_ ;
+ drawboundingbox _c_ ;
+ drawpointlabels _c_ ;
+enddef ;
+
+def visualizepaths =
+ let fill = visualizedfill ;
+ let draw = visualizeddraw ;
+enddef ;
+
+def naturalizepaths =
+ let fill = normalfill ;
+ let draw = normaldraw ;
+enddef ;
+
+extra_endfig := extra_endfig & " naturalizepaths ; " ;
+
+%D Noce tracer:
+
+def drawboundary primary p =
+ draw p dashed evenly withcolor white ;
+ draw p dashed oddly withcolor black ;
+ draw (- llcorner p) withpen pencircle scaled 3 withcolor white ;
+ draw (- llcorner p) withpen pencircle scaled 1.5 withcolor black ;
+enddef ;
+
+%D Also handy:
+
+extra_beginfig := extra_beginfig & " truecorners := 0 ; " ; % restores
+extra_beginfig := extra_beginfig & " miterlimit := 10 ; " ; % restores
+extra_beginfig := extra_beginfig & " linejoin := rounded ; " ; % restores
+extra_beginfig := extra_beginfig & " linecap := rounded ; " ; % restores
+
+%D Normally, arrowheads don't scale well. So we provide a
+%D hack.
+
+boolean autoarrows ; autoarrows := false ;
+numeric ahfactor ; ahfactor := 2.5 ;
+
+def set_ahlength (text t) =
+ % ahlength := (ahfactor*pen_size(_op_ t)) ; % _op_ added
+ % problem: _op_ can contain color so a no-go, we could apply the transform
+ % but i need to figure out the best way (fakepicture and take components).
+ ahlength := (ahfactor*pen_size(t)) ;
+enddef ;
+
+vardef pen_size (text t) =
+ save p ; picture p ; p := nullpicture ;
+ addto p doublepath (top origin -- bot origin) t ;
+ (ypart urcorner p - ypart lrcorner p)
+enddef ;
+
+%D The next two macros are adapted versions of plain
+%D \METAPOST\ definitions.
+
+vardef arrowpath expr p = % patch by Peter Rolf: supports squared pen and shifting (hh: maybe just use center of head as first)
+ (p cutafter makepath(pencircle scaled 2(ahlength*cosd(.5ahangle)) shifted point length p of p))
+enddef;
+
+% def _finarr text t =
+% if autoarrows : set_ahlength (t) fi ;
+% draw arrowpath _apth t ; % arrowpath added
+% filldraw arrowhead _apth t ;
+% enddef;
+
+def _finarr text t =
+ if autoarrows : set_ahlength (t) fi ;
+ draw arrowpath _apth t ; % arrowpath added
+ fill arrowhead _apth t ;
+ draw arrowhead _apth t ;
+enddef;
+
+def _findarr text t =
+ if autoarrows : set_ahlength (t) fi ;
+ draw arrowpath _apth t ;
+ fill arrowhead _apth withpen currentpen t ;
+ fill arrowhead reverse _apth withpen currentpen t ;
+enddef ;
+
+%D Handy too ......
+
+vardef pointarrow (expr pat, loc, len, off) =
+ save l, r, s, t ; path l, r ; numeric s ; pair t ;
+ t := if pair loc : loc else : point loc along pat fi ;
+ s := len/2 - off ; if s<=0 : s := 0 elseif s>len : s := len fi ;
+ r := pat cutbefore t ;
+ r := (r cutafter point (arctime s of r) of r) ;
+ s := len/2 + off ; if s<=0 : s := 0 elseif s>len : s := len fi ;
+ l := reverse (pat cutafter t) ;
+ l := (reverse (l cutafter point (arctime s of l) of l)) ;
+ (l..r)
+enddef ;
+
+def rightarrow (expr pat,tim,len) = pointarrow(pat,tim,len,-len) enddef ;
+def leftarrow (expr pat,tim,len) = pointarrow(pat,tim,len,+len) enddef ;
+def centerarrow (expr pat,tim,len) = pointarrow(pat,tim,len, 0) enddef ;
+
+%D The \type {along} and \type {on} operators can be used
+%D as follows:
+%D
+%D \starttypen
+%D drawdot point .5 along somepath ;
+%D drawdot point 3cm on somepath ;
+%D \stoptypen
+%D
+%D The number denotes a percentage (fraction).
+
+primarydef pct along pat = % also negative
+ (arctime (pct * (arclength pat)) of pat) of pat
+enddef ;
+
+primarydef len on pat = % no outer ( ) .. somehow fails
+ (arctime if len>0 : len else : (arclength(pat)+len) fi of pat) of pat
+enddef ;
+
+% this cuts of a piece from both ends
+
+tertiarydef pat cutends len =
+ begingroup
+ save tap ; path tap ;
+ tap := pat cutbefore (point (xpart paired(len)) on pat) ;
+ (tap cutafter (point -(ypart paired(len)) on tap))
+ endgroup
+enddef ;
+
+%D To be documented.
+
+path freesquare ;
+
+freesquare := (
+ (-1,0) -- (-1,-1) -- (0,-1) -- (+1,-1) --
+ (+1,0) -- (+1,+1) -- (0,+1) -- (-1,+1) -- cycle
+) scaled .5 ;
+
+numeric freelabeloffset ; freelabeloffset := 3pt ;
+numeric freedotlabelsize ; freedotlabelsize := 3pt ;
+
+vardef thefreelabel (expr str, loc, ori) =
+ save s, p, q, l ; picture s ; path p, q ; pair l ;
+ interim labeloffset := freelabeloffset ;
+ s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ;
+ setbounds s to boundingbox s enlarged freelabeloffset ;
+ p := fullcircle scaled (2*length(loc-ori)) shifted ori ;
+ q := freesquare xyscaled (urcorner s - llcorner s) ;
+ l := point xpart (p intersectiontimes (ori--loc shifted (loc-ori))) of q ;
+ setbounds s to boundingbox s enlarged -freelabeloffset ; % new
+ % draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ;
+ (s shifted -l)
+enddef ;
+
+vardef freelabel (expr str, loc, ori) =
+ draw thefreelabel(str,loc,ori) ;
+enddef ;
+
+vardef freedotlabel (expr str, loc, ori) =
+ interim linecap := rounded ;
+ draw loc withpen pencircle scaled freedotlabelsize ;
+ draw thefreelabel(str,loc,ori) ;
+enddef ;
+
+%D \starttypen
+%D drawarrow anglebetween(line_a,line_b,somelabel) ;
+%D \stoptypen
+
+newinternal angleoffset ; angleoffset := 0pt ;
+newinternal anglelength ; anglelength := 20pt ;
+newinternal anglemethod ; anglemethod := 1 ;
+
+vardef anglebetween (expr a, b, str) = % path path string
+ save pointa, pointb, common, middle, offset ;
+ pair pointa, pointb, common, middle, offset ;
+ save curve ; path curve ;
+ save where ; numeric where ;
+ if round point 0 of a = round point 0 of b :
+ common := point 0 of a ;
+ else :
+ common := a intersectionpoint b ;
+ fi ;
+ pointa := point anglelength on a ;
+ pointb := point anglelength on b ;
+ where := turningnumber (common--pointa--pointb--cycle) ;
+ middle := (reverse(common--pointa) rotatedaround (pointa,-where*90))
+ intersection_point
+ (reverse(common--pointb) rotatedaround (pointb, where*90)) ;
+ if not intersection_found :
+ middle := point .5 along
+ ((reverse(common--pointa) rotatedaround (pointa,-where*90)) --
+ ( (common--pointb) rotatedaround (pointb, where*90))) ;
+ fi ;
+ if anglemethod = 0 :
+ curve := pointa{unitvector(middle-pointa)}.. pointb;
+ middle := point .5 along curve ;
+ curve := common ;
+ elseif anglemethod = 1 :
+ curve := pointa{unitvector(middle-pointa)}.. pointb;
+ middle := point .5 along curve ;
+ elseif anglemethod = 2 :
+ middle := common rotatedaround(.5[pointa,pointb],180) ;
+ curve := pointa--middle--pointb ;
+ elseif anglemethod = 3 :
+ curve := pointa--middle--pointb ;
+ elseif anglemethod = 4 :
+ curve := pointa..controls middle..pointb ;
+ middle := point .5 along curve ;
+ fi ;
+ draw thefreelabel(str, middle, common) ; % withcolor black ;
+ curve
+enddef ;
+
+% Stack
+
+picture mfun_current_picture_stack[] ;
+numeric mfun_current_picture_depth ;
+
+mfun_current_picture_depth := 0 ;
+
+def pushcurrentpicture =
+ mfun_current_picture_depth := mfun_current_picture_depth + 1 ;
+ mfun_current_picture_stack[mfun_current_picture_depth] := currentpicture ;
+ currentpicture := nullpicture ;
+enddef ;
+
+def popcurrentpicture text t = % optional text
+ if mfun_current_picture_depth > 0 :
+ addto mfun_current_picture_stack[mfun_current_picture_depth] also currentpicture t ;
+ currentpicture := mfun_current_picture_stack[mfun_current_picture_depth] ;
+ mfun_current_picture_stack[mfun_current_picture_depth] := nullpicture ;
+ mfun_current_picture_depth := mfun_current_picture_depth - 1 ;
+ fi ;
+enddef ;
+
+%D colorcircle(size, red, green, blue) ;
+
+vardef colorcircle (expr size, red, green, blue) = % might move
+ save r, g, b, c, m, y, w ; save radius ;
+ path r, g, b, c, m, y, w ; numeric radius ;
+
+ radius := 5cm ; pickup pencircle scaled (radius/25) ;
+
+ transform t ; t := identity rotatedaround(origin,120) ;
+
+ r := fullcircle rotated 90 scaled radius shifted (0,radius/4) rotatedaround(origin,135) ;
+
+ b := r transformed t ; g := b transformed t ;
+
+ c := buildcycle(subpath(1,7) of g,subpath(1,7) of b) ;
+ y := c transformed t ; m := y transformed t ;
+
+ w := buildcycle(subpath(3,5) of r, subpath(3,5) of g,subpath(3,5) of b) ;
+
+ pushcurrentpicture ;
+
+ fill r withcolor red ;
+ fill g withcolor green ;
+ fill b withcolor blue ;
+ fill c withcolor white - red ;
+ fill m withcolor white - green ;
+ fill y withcolor white - blue ;
+ fill w withcolor white ;
+
+ for i = r,g,b,c,m,y : draw i withcolor .5white ; endfor ;
+
+ currentpicture := currentpicture xsized size ;
+
+ popcurrentpicture ;
+enddef ;
+
+% penpoint (i,2) of somepath -> inner / outer point
+
+vardef penpoint expr pnt of p =
+ save n, d ; numeric n, d ;
+ (n,d) = if pair pnt : pnt else : (pnt,1) fi ;
+ (point n of p shifted ((penoffset direction n of p of currentpen) scaled d))
+enddef ;
+
+% nice: currentpicture := inverted currentpicture ;
+
+primarydef p uncolored c =
+ if color p :
+ c - p
+ else :
+ image (
+ for i within p :
+ addto currentpicture
+ if stroked i or filled i :
+ if filled i :
+ contour
+ else :
+ doublepath
+ fi
+ pathpart i
+ dashed dashpart i withpen penpart i
+ else :
+ also i
+ fi
+ withcolor c-(redpart i, greenpart i, bluepart i) ;
+ endfor ;
+ )
+ fi
+enddef ;
+
+vardef inverted primary p =
+ p uncolored white
+enddef ;
+
+primarydef p softened c =
+ begingroup
+ save cc ; color cc ; cc := tripled(c) ;
+ if color p :
+ (redpart cc * redpart p,greenpart cc * greenpart p, bluepart cc * bluepart p)
+ else :
+ image (
+ for i within p :
+ addto currentpicture
+ if stroked i or filled i :
+ if filled i :
+ contour
+ else :
+ doublepath
+ fi
+ pathpart i
+ dashed dashpart i withpen penpart i
+ else :
+ also i
+ fi
+ withcolor (redpart cc * redpart i, greenpart cc * greenpart i, bluepart cc * bluepart i) ;
+ endfor ;
+ )
+ fi
+ endgroup
+enddef ;
+
+vardef grayed primary p =
+ if color p :
+ tripled(.30redpart p+.59greenpart p+.11bluepart p)
+ else :
+ image (
+ for i within p :
+ addto currentpicture
+ if stroked i or filled i :
+ if filled i :
+ contour
+ else :
+ doublepath
+ fi
+ pathpart i
+ dashed dashpart i
+ withpen penpart i
+ else :
+ also i
+ fi
+ withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ;
+ endfor ;
+ )
+ fi
+enddef ;
+
+% yes or no: "text" infont "cmr12" at 24pt ;
+
+% let normalinfont = infont ;
+%
+% numeric lastfontsize ; lastfontsize = fontsize defaultfont ;
+%
+% def infont primary name = % no vardef, no expr
+% hide(lastfontsize := fontsize name) % no ;
+% normalinfont name
+% enddef ;
+%
+% def scaledat expr size =
+% scaled (size/lastfontsize)
+% enddef ;
+%
+% let at = scaledat ;
+
+% like decimal
+
+def condition primary b = if b : "true" else : "false" fi enddef ;
+
+% undocumented
+
+primarydef p stretched s =
+ begingroup
+ save pp ; path pp ; pp := p xyscaled s ;
+ (pp shifted ((point 0 of p) - (point 0 of pp)))
+ endgroup
+enddef ;
+
+primarydef p enlonged len =
+ begingroup
+ if pair p :
+ save q ; path q ; q := origin -- p ;
+ save al ; al := arclength(q) ;
+ if al > 0 :
+ point 1 of (q stretched ((al+len)/al))
+ else :
+ p
+ fi
+ else :
+ save al ; al := arclength(p) ;
+ if al > 0 :
+ p stretched ((al+len)/al)
+ else :
+ p
+ fi
+ fi
+ endgroup
+enddef ;
+
+% path p ; p := (0,0) -- (10cm,5cm) ;
+% drawarrow p withcolor red ;
+% drawarrow p shortened 1cm withcolor green ;
+
+primarydef p shortened d =
+ reverse ( ( reverse (p enlonged -d) ) enlonged -d )
+enddef ;
+
+% yes or no, untested -)
+
+def xshifted expr dx = shifted(dx,0) enddef ;
+def yshifted expr dy = shifted(0,dy) enddef ;
+
+% also handy
+
+% right: str = readfrom ("abc" & ".def" ) ;
+% wrong: str = readfrom "abc" & ".def" ;
+
+% Every 62th read fails so we need to try again!
+
+% def readfile (expr name) =
+% if (readfrom (name) <> EOF) :
+% scantokens("input " & name & ";") ;
+% elseif (readfrom (name) <> EOF) :
+% scantokens("input " & name & ";") ;
+% fi ;
+% closefrom (name) ;
+% enddef ;
+%
+% this sometimes fails on the elseif, so :
+%
+
+def readfile (expr name) =
+ begingroup ; save ok ; boolean ok ;
+ if (readfrom (name) <> EOF) :
+ ok := false ;
+ elseif (readfrom (name) <> EOF) :
+ ok := false ;
+ else :
+ ok := true ;
+ fi ;
+ if not ok :
+ scantokens("input " & name & " ") ;
+ fi ;
+ closefrom (name) ;
+ endgroup ;
+enddef ;
+
+% permits redefinition of end in macro
+
+inner end ;
+
+% this will be redone (when needed) using scripts and backend handling
+
+let normalwithcolor = withcolor ;
+
+def remapcolors =
+ def withcolor primary c = normalwithcolor remappedcolor(c) enddef ;
+enddef ;
+
+def normalcolors =
+ let withcolor = normalwithcolor ;
+enddef ;
+
+def resetcolormap =
+ color color_map[][][] ;
+ normalcolors ;
+enddef ;
+
+resetcolormap ;
+
+def r_color primary c = redpart c enddef ;
+def g_color primary c = greenpart c enddef ;
+def b_color primary c = bluepart c enddef ;
+
+def remapcolor(expr old, new) =
+ color_map[redpart old][greenpart old][bluepart old] := new ;
+enddef ;
+
+def remappedcolor(expr c) =
+ if known color_map[redpart c][greenpart c][bluepart c] :
+ color_map[redpart c][greenpart c][bluepart c]
+ else :
+ c
+ fi
+enddef ;
+
+% Thanks to Jens-Uwe Morawski for pointing out that we need
+% to treat bounded and clipped components as local pictures.
+
+def recolor suffix p = p := repathed (0,p) enddef ;
+def refill suffix p = p := repathed (1,p) enddef ;
+def redraw suffix p = p := repathed (2,p) enddef ;
+def retext suffix p = p := repathed (3,p) enddef ;
+def untext suffix p = p := repathed (4,p) enddef ;
+
+% primarydef p recolored t = repathed(0,p) t enddef ;
+% primarydef p refilled t = repathed(1,p) t enddef ;
+% primarydef p redrawn t = repathed(2,p) t enddef ;
+% primarydef p retexted t = repathed(3,p) t enddef ;
+% primarydef p untexted t = repathed(4,p) t enddef ;
+
+color refillbackground ; refillbackground := (1,1,1) ;
+
+def restroke suffix p = p := repathed (21,p) enddef ; % keep attributes
+def reprocess suffix p = p := repathed (22,p) enddef ; % no attributes
+
+% also 11 and 12
+
+vardef repathed (expr mode, p) text t =
+ begingroup ;
+ if mode = 0 :
+ save withcolor ;
+ remapcolors ;
+ fi ;
+ save _p_, _pp_, _ppp_, _f_, _b_, _t_ ;
+ picture _p_, _pp_, _ppp_ ; color _f_ ; path _b_ ; transform _t_ ;
+ _b_ := boundingbox p ;
+ _p_ := nullpicture ;
+ for i within p :
+ _f_ := (redpart i, greenpart i, bluepart i) ;
+ if bounded i :
+ _pp_ := repathed(mode,i) t ;
+ setbounds _pp_ to pathpart i ;
+ addto _p_ also _pp_ ;
+ elseif clipped i :
+ _pp_ := repathed(mode,i) t ;
+ clip _pp_ to pathpart i ;
+ addto _p_ also _pp_ ;
+ elseif stroked i :
+ if mode=21 :
+ _ppp_ := i ; % indirectness is needed
+ addto _p_ also image(scantokens(t & " pathpart _ppp_")
+ dashed dashpart i withpen penpart i
+ withcolor _f_ ; ) ;
+ elseif mode=22 :
+ _ppp_ := i ; % indirectness is needed
+ addto _p_ also image(scantokens(t & " pathpart _ppp_")) ;
+ else :
+ addto _p_ doublepath pathpart i
+ dashed dashpart i withpen penpart i
+ withcolor _f_ % (redpart i, greenpart i, bluepart i)
+ if mode = 2 :
+ t
+ fi ;
+ fi ;
+ elseif filled i :
+ if mode=11 :
+ _ppp_ := i ; % indirectness is needed
+ addto _p_ also image(scantokens(t & " pathpart _ppp_")
+ withcolor _f_ ; ) ;
+ elseif mode=12 :
+ _ppp_ := i ; % indirectness is needed
+ addto _p_ also image(scantokens(t & " pathpart _ppp_")) ;
+ else :
+ addto _p_ contour pathpart i
+ withcolor _f_
+ if (mode=1) and (_f_<>refillbackground) :
+ t
+ fi ;
+ fi ;
+ elseif textual i : % textpart i <> "" :
+ if mode <> 4 :
+ % transform _t_ ;
+ % (xpart _t_, xxpart _t_, xypart _t_) = (xpart i, xxpart i, xypart i) ;
+ % (ypart _t_, yypart _t_, yxpart _t_) = (ypart i, yypart i, yxpart i) ;
+ % addto _p_ also
+ % textpart i infont fontpart i % todo : other font
+ % transformed _t_
+ % withpen penpart i
+ % withcolor _f_
+ % if mode=3 : t fi ;
+ addto _p_ also i
+ if mode=3 :
+ t
+ fi ;
+ fi ;
+ else :
+ addto _p_ also i ;
+ fi ;
+ endfor ;
+ setbounds _p_ to _b_ ;
+ _p_
+ endgroup
+enddef ;
+
+% After a question of Denis on how to erase a z variable, Jacko
+% suggested to assign whatever to x and y. So a clearz
+% variable can be defined as:
+%
+% vardef clearz@# =
+% x@# := whatever ;
+% y@# := whatever ;
+% enddef ;
+%
+% but Jacko suggested a redefinition of clearxy:
+%
+% def clearxy text s =
+% clearxy_index_:=0;
+% for $:=s:
+% clearxy_index_:=clearxy_index_+1; endfor;
+% if clearxy_index_=0:
+% save x,y;
+% else:
+% forsuffixes $:=s: x$:=whatever; y$:=whatever; endfor;
+% fi
+% enddef;
+%
+% which i decided to simplify to:
+
+def clearxy text s =
+ if false for $ := s : or true endfor :
+ forsuffixes $ := s : x$ := whatever ; y$ := whatever ; endfor ;
+ else :
+ save x, y ;
+ fi
+enddef ;
+
+% so now we can say: clearxy ; as well as clearxy 1, 2, 3 ;
+
+% show x0 ; z0 = (10,10) ;
+% show x0 ; x0 := whatever ; y0 := whatever ;
+% show x0 ; z0 = (20,20) ;
+% show x0 ; clearxy 0 ;
+% show x0 ; z0 = (30,30) ;
+
+primarydef p smoothed d =
+ (p llmoved (-xpart paired(d),0) -- p lrmoved (-xpart paired(d),0) {right} ..
+ p lrmoved (0,-ypart paired(d)) -- p urmoved (0,-ypart paired(d)) {up} ..
+ p urmoved (-xpart paired(d),0) -- p ulmoved (-xpart paired(d),0) {left} ..
+ p ulmoved (0,-ypart paired(d)) -- p llmoved (0,-ypart paired(d)) {down} .. cycle)
+enddef ;
+
+primarydef p cornered c =
+ ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) --
+ for i=1 upto length(p) :
+ (point i-1 of p) shifted (c*(unitvector(point i of p - point i-1 of p))) --
+ (point i of p) shifted (c*(unitvector(point i-1 of p - point i of p))) ..
+ controls point i of p ..
+ endfor cycle)
+enddef ;
+
+% cmyk color support
+
+% vardef cmyk(expr c,m,y,k) = % elsewhere
+% (1-c-k,1-m-k,1-y-k)
+% enddef ;
+
+% handy
+
+% vardef bbwidth (expr p) = % vardef width_of primary p =
+% if known p :
+% if path p or picture p :
+% xpart (lrcorner p - llcorner p)
+% else :
+% 0
+% fi
+% else :
+% 0
+% fi
+% enddef ;
+
+vardef bbwidth primary p =
+ if unknown p :
+ 0
+ elseif path p or picture p :
+ xpart (lrcorner p - llcorner p)
+ else :
+ 0
+ fi
+enddef ;
+
+% vardef bbheight (expr p) = % vardef heigth_of primary p =
+% if known p :
+% if path p or picture p :
+% ypart (urcorner p - lrcorner p)
+% else :
+% 0
+% fi
+% else :
+% 0
+% fi
+% enddef ;
+
+vardef bbheight primary p =
+ if unknown p :
+ 0
+ elseif path p or picture p :
+ ypart (urcorner p - lrcorner p)
+ else :
+ 0
+ fi
+enddef ;
+
+color nocolor ; numeric noline ; % both unknown signals
+
+def dowithpath (expr p, lw, lc, bc) =
+ if known p :
+ if known bc :
+ fill p withcolor bc ;
+ fi ;
+ if known lw and known lc :
+ draw p withpen pencircle scaled lw withcolor lc ;
+ elseif known lw :
+ draw p withpen pencircle scaled lw ;
+ elseif known lc :
+ draw p withcolor lc ;
+ fi ;
+ fi ;
+enddef ;
+
+% result from metafont discussion list (denisr/boguslawj)
+
+def [[ = [ [ enddef ; def [[[ = [ [ [ enddef ;
+def ]] = ] ] enddef ; def ]]] = ] ] ] enddef ;
+
+let == = = ;
+
+% added
+
+picture oddly ; % evenly already defined
+
+evenly := dashpattern(on 3 off 3) ;
+oddly := dashpattern(off 3 on 3) ;
+
+% not perfect, but useful since it removes redundant points.
+
+vardef mfun_straightened(expr sign, p) =
+ save _p_, _q_ ; path _p_, _q_ ;
+ _p_ := p ;
+ forever :
+ _q_ := mfun_do_straightened(sign, _p_) ;
+ exitif length(_p_) = length(_q_) ;
+ _p_ := _q_ ;
+ endfor ;
+ _q_
+enddef ;
+
+vardef mfun_do_straightened(expr sign, p) =
+ if length(p)>2 : % was 1, but straight lines are ok
+ save pp ; path pp ;
+ pp := point 0 of p ;
+ for i=1 upto length(p)-1 :
+ if round(point i of p) <> round(point length(pp) of pp) :
+ pp := pp -- point i of p ;
+ fi ;
+ endfor ;
+ save n, ok ; numeric n ; boolean ok ;
+ n := length(pp) ; ok := false ;
+ if n>2 :
+ for i=0 upto n : % evt hier ook round
+ if unitvector(round(point i of pp - point if i=0 : n else : i-1 fi of pp)) <>
+ sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp - point i of pp)) :
+ if ok :
+ --
+ else :
+ ok := true ;
+ fi point i of pp
+ fi
+ endfor
+ if ok and (cycle p) :
+ -- cycle
+ fi
+ else :
+ pp
+ fi
+ else :
+ p
+ fi
+enddef ;
+
+vardef simplified expr p = (
+ reverse mfun_straightened(+1,mfun_straightened(+1,reverse p))
+) enddef ;
+
+vardef unspiked expr p = (
+ reverse mfun_straightened(-1,mfun_straightened(-1,reverse p))
+) enddef ;
+
+% path p ;
+% p := (2cm,1cm) -- (2cm,1cm) -- (2cm,1cm) -- (3cm,1cm) --
+% (4cm,1cm) -- (4cm,2cm) -- (4cm,2.5cm) -- (4cm,3cm) --
+% (3cm,3cm) -- (2cm,3cm) -- (1cm,3cm) -- (-1cm,3cm) --
+% .5[(-1cm,3cm),(1cm,1cm)] -- (1cm,1cm) -- cycle ;
+%
+% p := unitcircle scaled 4cm ;
+%
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+% p := p shifted (4cm,0) ; p := straightened p ;
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+% p := p shifted (4cm,0) ; p := straightened p ;
+% drawpath p ; drawpoints p ; drawpointlabels p ;
+
+% new
+
+path originpath ; originpath := origin -- cycle ;
+
+vardef unitvector primary z =
+ if abs z = abs origin : z else : z/abs z fi
+enddef;
+
+% also new
+
+% vardef anchored@#(expr p, z) = % maybe use the textext variant
+% p shifted (z + (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p))
+% enddef ;
+
+% epsed(1.2345)
+
+vardef epsed (expr e) =
+ e if e>0 : + eps elseif e<0 : - eps fi
+enddef ;
+
+% handy
+
+def withgray primary g =
+ withcolor (g,g,g)
+enddef ;
+
+% for metafun
+
+if unknown darkred : color darkred ; darkred := .625(1,0,0) fi ;
+if unknown darkgreen : color darkgreen ; darkgreen := .625(0,1,0) fi ;
+if unknown darkblue : color darkblue ; darkblue := .625(0,0,1) fi ;
+if unknown darkcyan : color darkcyan ; darkcyan := .625(0,1,1) fi ;
+if unknown darkmagenta : color darkmagenta ; darkmagenta := .625(1,0,1) fi ;
+if unknown darkyellow : color darkyellow ; darkyellow := .625(1,1,0) fi ;
+if unknown darkgray : color darkgray ; darkgray := .625(1,1,1) fi ;
+if unknown lightgray : color lightgray ; lightgray := .875(1,1,1) fi ;
+
+% an improved plain mp macro
+
+vardef center primary p =
+ if pair p :
+ p
+ else :
+ .5[llcorner p, urcorner p]
+ fi
+enddef;
+
+% new, yet undocumented
+
+vardef rangepath (expr p, d, a) =
+ if length p>0 :
+ (d*unitvector(direction 0 of p) rotated a) shifted point 0 of p
+ -- p --
+ (d*unitvector(direction length(p) of p) rotated a) shifted point length(p) of p
+ else :
+ p
+ fi
+enddef ;
+
+% under construction
+
+vardef straightpath (expr a, b, method) =
+ if (method<1) or (method>6) :
+ (a--b)
+ elseif method = 1 :
+ (a --
+ if xpart a > xpart b :
+ if ypart a > ypart b :
+ (xpart b,ypart a) --
+ elseif ypart a < ypart b :
+ (xpart a,ypart b) --
+ fi
+ elseif xpart a < xpart b :
+ if ypart a > ypart b :
+ (xpart a,ypart b) --
+ elseif ypart a < ypart b :
+ (xpart b,ypart a) --
+ fi
+ fi
+ b)
+ elseif method = 3 :
+ (a --
+ if xpart a > xpart b :
+ (xpart b,ypart a) --
+ elseif xpart a < xpart b :
+ (xpart a,ypart b) --
+ fi
+ b)
+ elseif method = 5 :
+ (a --
+ if ypart a > ypart b :
+ (xpart b,ypart a) --
+ elseif ypart a < ypart b :
+ (xpart a,ypart b) --
+ fi
+ b)
+ else :
+ (reverse straightpath(b,a,method-1))
+ fi
+enddef ;
+
+% handy for myself
+
+def addbackground text t =
+ begingroup ;
+ save p, b ; picture p ; path b ;
+ b := boundingbox currentpicture ;
+ p := currentpicture ; currentpicture := nullpicture ;
+ fill b t ;
+ setbounds currentpicture to b ;
+ addto currentpicture also p ;
+ endgroup ;
+enddef ;
+
+% makes a (line) into an infinite one (handy for calculating
+% intersection points
+
+vardef infinite expr p =
+ (-infinity*unitvector(direction 0 of p)
+ shifted point 0 of p
+ -- p --
+ +infinity*unitvector(direction length(p) of p)
+ shifted point length(p) of p)
+enddef ;
+
+% obscure macros: create var from string and replace - and :
+% (needed for process color id's) .. will go away
+
+string mfun_clean_ascii[] ;
+
+def register_dirty_chars(expr str) =
+ for i = 0 upto length(str)-1 :
+ mfun_clean_ascii[ASCII substring(i,i+1) of str] := "_" ;
+ endfor ;
+enddef ;
+
+register_dirty_chars("+-*/:;., ") ;
+
+vardef cleanstring (expr s) =
+ save ss ; string ss, si ; ss = "" ; save i ;
+ for i=0 upto length(s) :
+ si := substring(i,i+1) of s ;
+ ss := ss & if known mfun_clean_ascii[ASCII si] : mfun_clean_ascii[ASCII si] else : si fi ;
+ endfor ;
+ ss
+enddef ;
+
+vardef asciistring (expr s) =
+ save ss ; string ss, si ; ss = "" ; save i ;
+ for i=0 upto length(s) :
+ si := substring(i,i+1) of s ;
+ if (ASCII si >= ASCII "0") and (ASCII si <= ASCII "9") :
+ ss := ss & char(scantokens(si) + ASCII "A") ;
+ else :
+ ss := ss & si ;
+ fi ;
+ endfor ;
+ ss
+enddef ;
+
+vardef setunstringed (expr s, v) =
+ scantokens(cleanstring(s)) := v ;
+enddef ;
+
+vardef getunstringed (expr s) =
+ scantokens(cleanstring(s))
+enddef ;
+
+vardef unstringed (expr s) =
+ expandafter known scantokens(cleanstring(s))
+enddef ;
+
+% for david arnold:
+
+% showgrid(-5,10,1cm,-10,10,1cm);
+
+def showgrid (expr MinX, MaxX, DeltaX, MinY, MaxY, DeltaY) = % will move
+ begingroup
+ save size ; numeric size ; size := 2pt ;
+ for x=MinX upto MaxX :
+ for y=MinY upto MaxY :
+ draw (x*DeltaX, y*DeltaY) withpen pencircle scaled
+ if (x mod 5 = 0) and (y mod 5 = 0) :
+ 1.5size withcolor .50white
+ else :
+ size withcolor .75white
+ fi ;
+ endfor ;
+ endfor ;
+ for x=MinX upto MaxX:
+ label.bot(textext("\infofont " & decimal x), (x*DeltaX,-size)) ;
+ endfor ;
+ for y=MinY upto MaxY:
+ label.lft(textext("\infofont " & decimal y), (-size,y*DeltaY)) ;
+ endfor ;
+ endgroup
+enddef;
+
+% new, handy for:
+%
+% \startuseMPgraphic{map}{n}
+% \includeMPgraphic{map:germany} ;
+% c_phantom (\MPvar{n}<1) (
+% fill map_germany withcolor \MPcolor{lightgray} ;
+% draw map_germany withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+% ) ;
+% \includeMPgraphic{map:austria} ;
+% c_phantom (\MPvar{n}<2) (
+% fill map_austria withcolor \MPcolor{lightgray} ;
+% draw map_austria withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+% ) ;
+% c_phantom (\MPvar{n}<3) (
+% \includeMPgraphic{map:swiss} ;
+% fill map_swiss withcolor \MPcolor{lightgray} ;
+% draw map_swiss withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+% ) ;
+% c_phantom (\MPvar{n}<4) (
+% \includeMPgraphic{map:luxembourg} ;
+% fill map_luxembourg withcolor \MPcolor{lightgray} ;
+% draw map_luxembourg withpen pencircle scaled 1pt withcolor \MPcolor{darkgray} ;
+% ) ;
+% \stopuseMPgraphic
+%
+% \useMPgraphic{map}{n=3}
+
+vardef phantom (text t) = % to be checked
+ picture _p_ ;
+ _p_ := image(t) ;
+ addto _p_ also currentpicture ;
+ setbounds currentpicture to boundingbox _p_ ;
+enddef ;
+
+vardef c_phantom (expr b) (text t) =
+ if b :
+ picture _p_ ;
+ _p_ := image(t) ;
+ addto _p_ also currentpicture ;
+ setbounds currentpicture to boundingbox _p_ ;
+ else :
+ t ;
+ fi ;
+enddef ;
+
+%D Handy:
+
+def break =
+ exitif true fi ;
+enddef ;
+
+%D New too:
+
+primarydef p xstretched w = (
+ p if (bbwidth (p)>0) and (w>0) : xscaled (w/bbwidth (p)) fi
+) enddef ;
+
+primarydef p ystretched h = (
+ p if (bbheight(p)>0) and (h>0) : yscaled (h/bbheight(p)) fi
+) enddef ;
+
+primarydef p snapped s =
+ hide (
+ if path p :
+ forever :
+ exitif (bbheight(p) <= s) and (bbwidth(p) <= s) ;
+ p := p scaled (1/2) ;
+ endfor ;
+ elseif numeric p :
+ forever :
+ exitif p <= s ;
+ p := p scaled (1/2) ;
+ endfor ;
+ fi ;
+ )
+ p
+enddef ;
+
+% vardef somecolor = (1,1,0,0) enddef ;
+
+% fill OverlayBox withcolor (rcomponent somecolor,gcomponent somecolor,bcomponent somecolor) ;
+% fill OverlayBox withcolor (ccomponent somecolor,mcomponent somecolor,ycomponent somecolor,bcomponent somecolor) ;
+
+% This could be standard mplib 2 behaviour:
+
+vardef rcomponent expr p = if rgbcolor p : redpart p elseif cmykcolor p : 1 - cyanpart p else : p fi enddef ;
+vardef gcomponent expr p = if rgbcolor p : greenpart p elseif cmykcolor p : 1 - magentapart p else : p fi enddef ;
+vardef bcomponent expr p = if rgbcolor p : bluepart p elseif cmykcolor p : 1 - yellowpart p else : p fi enddef ;
+vardef ccomponent expr p = if cmykcolor p : cyanpart p elseif rgbcolor p : 1 - redpart p else : p fi enddef ;
+vardef mcomponent expr p = if cmykcolor p : magentapart p elseif rgbcolor p : 1 - greenpart p else : p fi enddef ;
+vardef ycomponent expr p = if cmykcolor p : yellowpart p elseif rgbcolor p : 1 - bluepart p else : p fi enddef ;
+vardef bcomponent expr p = if cmykcolor p : blackpart p elseif rgbcolor p : 0 else : p fi enddef ;
+
diff --git a/Master/texmf-dist/metapost/context/base/mp-txts.mp b/Master/texmf-dist/metapost/context/base/mp-txts.mpii
index f208c714900..d3d25293dbf 100644
--- a/Master/texmf-dist/metapost/context/base/mp-txts.mp
+++ b/Master/texmf-dist/metapost/context/base/mp-txts.mpii
@@ -11,8 +11,7 @@
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
%C details.
-if unknown context_tool : input mp-tool ; fi ;
-if known context_txts : endinput ; fi ;
+if known context_txts : endinput ; fi ;
boolean context_txts ; context_txts := true ;
diff --git a/Master/texmf-dist/scripts/context/lua/luatools.rme b/Master/texmf-dist/scripts/context/lua/luatools.rme
deleted file mode 100644
index 901e9a9a3fc..00000000000
--- a/Master/texmf-dist/scripts/context/lua/luatools.rme
+++ /dev/null
@@ -1,3 +0,0 @@
-On MSWindows the luatools.lua script is called
-with luatools.exe. On Unix you can either rename
-luatools.lua to luatools, or use a symlink.
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-chars.lua b/Master/texmf-dist/scripts/context/lua/mtx-chars.lua
index dc760c4e7e6..ad2c499bef4 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-chars.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-chars.lua
@@ -6,10 +6,12 @@ if not modules then modules = { } end modules ['mtx-chars'] = {
license = "see context related readme files"
}
+-- obsolete: --stix convert stix table to math table
+
local helpinfo = [[
---stix convert stix table to math table
--xtx generate xetx-*.tex (used by xetex)
--pdf generate pdfr-def.tex (used by pdftex)
+--entities generate entities table
]]
local application = logs.application {
@@ -20,7 +22,10 @@ local application = logs.application {
local report = application.report
-local format, concat, utfchar, upper = string.format, table.concat, unicode.utf8.char, string.upper
+local format, gmatch, upper, lower = string.format, string.gmatch, string.upper, string.lower
+local tonumber = tonumber
+local concat = table.concat
+local utfchar = utf.char
scripts = scripts or { }
scripts.chars = scripts.chars or { }
@@ -321,10 +326,63 @@ function scripts.chars.makeencoutf()
end
end
+local entityfiles = {
+ "http://www.w3.org/2003/entities/2007/w3centities-f.ent",
+ "http://www.w3.org/2003/entities/2007/htmlmathml-f.ent",
+}
+
+function scripts.chars.xmlentities()
+ local done = { }
+ local entities = { "local entities = utilities.storage.allocate {" }
+ for i=1,#entityfiles do
+ local f = entityfiles[i]
+ local s = url.hashed(f)
+ local b = file.basename(s.path)
+ local n = resolvers.findfile(b)
+ local data = io.loaddata(n)
+ for name, value in gmatch(data,'<!ENTITY +(%S+) +"(.-)" *>') do
+ if not done[name] then
+ done[name] = true
+ local str, hex
+ local low = lower(name)
+ if name == "newline" then
+ -- let's forget about that one
+ elseif name == "lt" then
+ str, hex = "<", format("%s %05X",hex,c)
+ elseif name == "gt" then
+ str, hex = ">", format("%s %05X",hex,c)
+ elseif name == "amp" then
+ str, hex = "&", format("%s %05X",hex,c)
+ else
+ for t, c in gmatch(value,"&#([x]*)([^;]+);") do
+ if t == "x" then
+ c = tonumber(c,16)
+ else
+ c = tonumber(c)
+ end
+ if str then
+ str, hex = str .. utfchar(c), format("%s %05X",hex,c)
+ else
+ str, hex = utfchar(c), format("U+%05X",c)
+ end
+ end
+ end
+ if str and hex then
+ entities[#entities+1] = format(' ["%s"] = %q, -- %s',name,str,hex)
+ end
+ end
+ end
+ end
+ entities[#entities+1] = "}"
+ io.savedata("xmlentities.tmp",concat(entities,"\n"))
+end
+
if environment.argument("stix") then
local inname = environment.files[1] or ""
local outname = environment.files[2] or ""
scripts.chars.stixtomkiv(inname,outname)
+elseif environment.argument("entities") then
+ scripts.chars.xmlentities()
elseif environment.argument("xtx") then
scripts.chars.makeencoutf()
elseif environment.argument("pdf") then
@@ -332,3 +390,28 @@ elseif environment.argument("pdf") then
else
application.help()
end
+
+-- local http = require("socket.http")
+-- local ltn12 = require("ltn12")
+--
+-- local t = { }
+-- local status, message = http.request {
+-- url = f,
+-- sink = ltn12.sink.table(t)
+-- }
+--
+-- local template = [[
+-- <?xml version='1.0' ?>
+--
+-- <!DOCTYPE dummy [
+--
+-- %s
+--
+-- ]>
+--
+-- <dummy>This is just a placeholder.</dummy>
+-- ]]
+--
+-- local e = string.format(template,io.loaddata(n))
+-- local x = xml.convert(e, { utfize_entities = true } )
+-- local entities = x.entities
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-check.lua b/Master/texmf-dist/scripts/context/lua/mtx-check.lua
index e0ab3b88276..8307a02c6b2 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-check.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-check.lua
@@ -6,6 +6,10 @@ if not modules then modules = { } end modules ['mtx-check'] = {
license = "see context related readme files"
}
+local P, R, S, V, C, CP, CC, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cp, lpeg.Cc, lpeg.match
+local gsub, sub, format = string.gsub, string.sub, string.format
+local insert, remove = table.insert, table.remove
+
local helpinfo = [[
--convert check tex file for errors
]]
@@ -31,21 +35,25 @@ validator.direct = false
validator.printer = print
validator.tracer = print
-local message = function(position, kind)
+local message = function(position, kind, extra)
local ve = validator.errors
- ve[#ve+1] = { kind, position, validator.n }
+ ve[#ve+1] = { kind, position, validator.n, extra }
if validator.direct then
- validator.printer(string.format("%s error at position %s (line %s)", kind, position, validator.n))
+ position = position or "eof"
+ if extra then
+ validator.printer(format("%s error at position %s (line %s) (%s)",kind,position,validator.n,extra))
+ else
+ validator.printer(format("%s error at position %s (line %s)",kind,position,validator.n))
+ end
end
end
+
local progress = function(position, data, kind)
if validator.trace then
- validator.tracer(string.format("%s at position %s: %s", kind, position, data or ""))
+ validator.tracer(format("%s at position %s: %s", kind, position, data or ""))
end
end
-local P, R, S, V, C, CP, CC = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cp, lpeg.Cc
-
local i_m, d_m = P("$"), P("$$")
local l_s, r_s = P("["), P("]")
local l_g, r_g = P("{"), P("}")
@@ -61,44 +69,117 @@ local newline = crlf + cr + lf
local line = newline / function() validator.n = validator.n + 1 end
--- local grammar = P { "tokens",
--- ["tokens"] = (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0,
--- ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0),
--- ["grouped"] = CP() * C(l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g) * CC("group") / progress,
--- ["setup"] = CP() * C(l_s * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s) * CC("setup") / progress,
--- ["display"] = CP() * C(d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m) * CC("display") / progress,
--- ["inline"] = CP() * C(i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m) * CC("inline") / progress,
--- ["errors"] = (V("gerror") + V("serror") + V("derror") + V("ierror")) * true,
--- ["gerror"] = CP() * (l_g + r_g) * CC("grouping") / message,
--- ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message,
--- ["derror"] = CP() * d_m * CC("display math error") / message,
--- ["ierror"] = CP() * i_m * CC("inline math error") / message,
--- }
-
local startluacode = P("\\startluacode")
local stopluacode = P("\\stopluacode")
local somecode = startluacode * (1-stopluacode)^1 * stopluacode
-local grammar = P { "tokens",
- ["tokens"] = (V("ignore") + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0,
- ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0),
- ["grouped"] = l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g,
- ["setup"] = l_s * (okay + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s,
- ["display"] = d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m,
- ["inline"] = i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m,
- ["errors"] = (V("gerror")+ V("serror") + V("derror") + V("ierror")),
- ["gerror"] = CP() * (l_g + r_g) * CC("grouping") / message,
- ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message,
- ["derror"] = CP() * d_m * CC("display math error") / message,
- ["ierror"] = CP() * i_m * CC("inline math error") / message,
- ["ignore"] = somecode,
+local stack = { }
+
+local function push(p,s)
+-- print("start",p,s)
+ insert(stack,{ p, s, validator.n })
+end
+
+local function pop(p,s)
+-- print("stop",p,s)
+ local top = remove(stack)
+ if not top then
+ message(p,"missing start")
+ elseif top[2] ~= s then
+ message(p,"missing stop",format("see line %s",top[3]))
+ else
+ -- okay
+ end
+end
+
+local cstoken = R("az","AZ","\127\255")
+
+local start = CP() * P("\\start") * C(cstoken^0) / push
+local stop = CP() * P("\\stop") * C(cstoken^0) / pop
+
+local contextgrammar = P { "tokens",
+ ["tokens"] = (V("ignore") + V("start") + V("stop") + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0,
+ ["start"] = start,
+ ["stop"] = stop,
+ ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0),
+ ["grouped"] = l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g,
+ ["setup"] = l_s * (okay + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s,
+ ["display"] = d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m,
+ ["inline"] = i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m,
+ ["errors"] = V("gerror") + V("serror") + V("derror") + V("ierror"),
+ ["gerror"] = CP() * (l_g + r_g) * CC("grouping error") / message,
+ ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message,
+ ["derror"] = CP() * d_m * CC("display math error") / message,
+ ["ierror"] = CP() * i_m * CC("inline math error") / message,
+ ["ignore"] = somecode,
+}
+
+-- metafun variant
+
+local function push(p,s)
+ insert(stack,{ p, s, validator.n })
+end
+
+local function pop(p,s)
+ local top = remove(stack)
+ if not top then
+ message(p,"missing <some>def")
+ end
+end
+
+local function finish(p)
+ local bot = stack[1]
+ if bot then
+ message(false,format("missing enddef for %s",bot[2]),format("see line %s",bot[3]))
+ end
+ stack = { }
+end
+
+local l_b, r_b = P("["), P("]")
+local l_g, r_g = P("{"), P("}")
+local l_p, r_p = P("("), P(")")
+
+local start = CP() * C( P("vardef") + P("primarydef") + P("secondarydef") + P("tertiarydef") + P("def") ) / push
+local stop = CP() * C( P("enddef") ) / pop
+
+local dstring = P('"') * (1-P('"'))^0 * P('"')
+local semicolon = P(";")
+
+local separator = line + space + semicolon
+
+-- todo: start/stop also in ()
+
+local metafungrammar = P { "tokens",
+ ["tokens"] = (V("start") + V("stop") + V("string") + V("whatever") + V("braces") + V("brackets") + V("parentheses") + V("errors") + 1)^0
+ * (CP() / finish),
+ ["start"] = separator * start * #separator,
+ ["stop"] = separator * stop * #separator,
+ ["string"] = dstring,
+ ["whatever"] = line + C(P("%") * (1-line)^0),
+ ["braces"] = l_g * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_g - r_g))^0 * r_g,
+ ["brackets"] = l_b * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_b - r_b))^0 * r_b,
+ ["parentheses"] = l_p * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_p - r_p))^0 * r_p,
+ ["errors"] = V("gerror") + V("berror") + V("perror"),
+ ["gerror"] = CP() * (l_g + r_g) * CC("braces error") / message,
+ ["berror"] = CP() * (l_b + r_b) * CC("brackets error") / message,
+ ["perror"] = CP() * (l_p + r_p) * CC("parentheses error") / message,
}
-function validator.check(str)
+local grammars = {
+ mp = metafungrammar,
+ mpii = metafungrammar,
+ mpiv = metafungrammar,
+ tex = contextgrammar,
+ mkii = contextgrammar,
+ mkiv = contextgrammar,
+}
+
+function validator.check(str,filetype)
validator.n = 1
validator.errors = { }
- grammar:match(str)
+ local grammar = grammars[filetype] or grammars.tex
+ lpegmatch(grammar,str)
end
--~ str = [[
@@ -109,23 +190,32 @@ end
--~ ]]
--~ str = string.rep(str,10)
+local remapper = {
+ ["\n"] = " <lf> ",
+ ["\r"] = " <cr> ",
+ ["\t"] = " <tab> ",
+}
+
function scripts.checker.check(filename)
local str = io.loaddata(filename)
if str then
- validator.check(str)
+ validator.check(str,file.suffix(filename))
local errors = validator.errors
if #errors > 0 then
for k=1,#errors do
local v = errors[k]
- local kind, position, line = v[1], v[2], v[3]
- local data = str:sub(position-30,position+30)
- data = data:gsub("(.)", {
- ["\n"] = " <lf> ",
- ["\r"] = " <cr> ",
- ["\t"] = " <tab> ",
- })
- data = data:gsub("^ *","")
- print(string.format("% 5i %-10s %s", line, kind, data))
+ local kind, position, line, extra = v[1], v[2], v[3], v[4]
+ if not position then
+ position = #str
+ end
+ local data = sub(str,position-30,position+30)
+ data = gsub(data,".", remapper)
+ data = gsub(data,"^ *","")
+ if extra then
+ print(format("% 5i %-10s %s (%s)", line, kind, data, extra))
+ else
+ print(format("% 5i %-10s %s", line, kind, data))
+ end
end
else
print("no error")
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-context.lua b/Master/texmf-dist/scripts/context/lua/mtx-context.lua
index 5645e476050..3052365092a 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-context.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-context.lua
@@ -66,7 +66,6 @@ expert options:
--update update context from website (not to be confused with contextgarden)
--profile profile job (use: mtxrun --script profile --analyze)
--timing generate timing and statistics overview
---tracefiles show some extra info when locating files (at the tex end)
--extra=name process extra (mtx-context-<name> in distribution)
--extras show extras
@@ -453,6 +452,7 @@ scripts.context.multipass = {
-- suffixes = { ".tuo", ".tuc" },
suffixes = { ".tuc" },
nofruns = 8,
+-- nofruns = 7, -- test oscillation
}
function scripts.context.multipass.hashfiles(jobname)
@@ -475,7 +475,7 @@ function scripts.context.multipass.changed(oldhash, newhash)
return false
end
-function scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,currentrun,finalrun)
+function scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,currentrun,finalrun,once)
-- take jobname from ctx
jobname = file.removesuffix(jobname)
local f = io.open(jobname..".top","w")
@@ -526,14 +526,15 @@ function scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,curr
--
setalways("%% feedback and basic job control")
--
- -- Option file, we can pass more on the commandline some day soon.
+ -- Option file, we can pass more on the commandline some day soon. Actually we
+ -- should use directives and trackers.
--
setfixed ("timing" , "\\usemodule[timing]")
setfixed ("batchmode" , "\\batchmode")
setfixed ("batch" , "\\batchmode")
setfixed ("nonstopmode" , "\\nonstopmode")
setfixed ("nonstop" , "\\nonstopmode")
- setfixed ("tracefiles" , "\\tracefilestrue")
+ -- setfixed ("tracefiles" , "\\tracefilestrue")
setfixed ("nostats" , "\\nomkivstatistics")
setfixed ("paranoid" , "\\def\\maxreadlevel{1}")
--
@@ -554,6 +555,9 @@ function scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,curr
setvalue ("setuppath" , "\\setupsystem[\\c!directory={%s}]")
setvalue ("randomseed" , "\\setupsystem[\\c!random=%s]")
setvalue ("arguments" , "\\setupenv[%s]")
+ if once then
+ setalways("\\enabledirectives[system.runonce]")
+ end
setalways("%% modes")
setvalues("modefile" , "\\readlocfile{%s}{}{}")
setvalues("mode" , "\\enablemode[%s]", true)
@@ -590,7 +594,7 @@ function scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,curr
end
end
-function scripts.context.multipass.copyluafile(jobname)
+function scripts.context.multipass.copyluafile(jobname) -- obsolete
local tuaname, tucname = jobname..".tua", jobname..".tuc"
if lfs.isfile(tuaname) then
os.remove(tucname)
@@ -623,7 +627,7 @@ scripts.context.interfaces = {
de = "cont-de",
fr = "cont-fr",
nl = "cont-nl",
- cz = "cont-cz",
+ cs = "cont-cs",
it = "cont-it",
ro = "cont-ro",
pe = "cont-pe",
@@ -638,14 +642,18 @@ scripts.context.defaultformats = {
-- "plain"
}
+local lpegpatterns, Cs, P = lpeg.patterns, lpeg.Cs, lpeg.P
+
+local pattern = lpegpatterns.utfbom^-1 * (P("%% ") + P("% ")) * Cs((1-lpegpatterns.newline)^1)
+
local function analyze(filename) -- only files on current path
local f = io.open(file.addsuffix(filename,"tex"))
if f then
local t = { }
local line = f:read("*line") or ""
- local preamble = match(line,"[\254\255]*%%%s+(.+)$") -- there can be an utf bomb in front
+ local preamble = lpeg.match(pattern,line)
if preamble then
- for key, value in gmatch(preamble,"(%S+)=(%S+)") do
+ for key, value in gmatch(preamble,"(%S+)%s*=%s*(%S+)") do
t[key] = value
end
t.type = "tex"
@@ -661,7 +669,6 @@ local function analyze(filename) -- only files on current path
f:close()
return t
end
- return nil
end
local function makestub(wrap,template,filename,prepname)
@@ -898,7 +905,7 @@ function scripts.context.run(ctxdata,filename)
end
flags[#flags+1] = format('--backend="%s"',backend)
--
- local command = format("luatex %s %s", concat(flags," "), quote(filename))
+ local command = format("luatex %s %s \\stoptext", concat(flags," "), quote(filename))
local oldhash, newhash = scripts.context.multipass.hashfiles(jobname), { }
local once = environment.argument("once")
local maxnofruns = (once and 1) or scripts.context.multipass.nofruns
@@ -906,7 +913,7 @@ function scripts.context.run(ctxdata,filename)
for i=1,maxnofruns do
-- 1:first run, 2:successive run, 3:once, 4:last of maxruns
local kindofrun = (once and 3) or (i==1 and 1) or (i==maxnofruns and 4) or 2
- scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,i,false) -- kindofrun, currentrun, final
+ scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,i,false,once) -- kindofrun, currentrun, final
report("run %s: %s",i,command)
--~ print("\n") -- cleaner, else continuation on same line
print("") -- cleaner, else continuation on same line
@@ -1133,14 +1140,10 @@ function scripts.context.autoctx()
scripts.context.run(ctxdata)
end
--- todo: quite after first image
-
local template = [[
- \starttext
- \startMPpage %% %s
- input "%s" ;
- \stopMPpage
- \stoptext
+\starttext
+ \directMPgraphic{%s}{input "%s"}
+\stoptext
]]
local loaded = false
@@ -1211,7 +1214,8 @@ local temporary_runfiles = {
"tui", "tua", "tup", "ted", "tes", "top",
"log", "tmp", "run", "bck", "rlg",
"mpt", "mpx", "mpd", "mpo", "mpb", "ctl",
- "synctex.gz", "pgf"
+ "synctex.gz", "pgf",
+ "prep",
}
local persistent_runfiles = {
@@ -1219,7 +1223,8 @@ local persistent_runfiles = {
}
local special_runfiles = {
- "-mpgraph*", "-mprun*", "-temp-*"
+--~ "-mpgraph*", "-mprun*", "-temp-*" -- hm, wasn't this escaped?
+ "-mpgraph", "-mprun", "-temp-"
}
local function purge_file(dfile,cfile)
@@ -1393,6 +1398,9 @@ end
function scripts.context.extras(pattern)
-- only in base path, i.e. only official ones
+ if type(pattern) ~= "string" then
+ pattern = "*"
+ end
local found = resolvers.findfile("context.mkiv")
if found ~= "" then
pattern = file.join(dir.expandname(file.dirname(found)),format("mtx-context-%s.tex",pattern or "*"))
@@ -1638,6 +1646,7 @@ elseif environment.argument("ctx") then
elseif environment.argument("mp") or environment.argument("metapost") then
scripts.context.timed(scripts.context.metapost)
elseif environment.argument("version") then
+ application.identify()
scripts.context.version()
elseif environment.argument("touch") then
scripts.context.touch()
@@ -1648,7 +1657,7 @@ elseif environment.argument("expert") then
elseif environment.argument("modules") then
scripts.context.modules()
elseif environment.argument("extras") then
- scripts.context.extras()
+ scripts.context.extras(environment.files[1] or environment.argument("extras"))
elseif environment.argument("extra") then
scripts.context.extra()
elseif environment.argument("help") then
@@ -1675,7 +1684,7 @@ elseif environment.argument("purge") then
scripts.context.purge()
elseif environment.argument("purgeall") then
-- only when no filename given, supports --pattern
- scripts.context.purge(true)
+ scripts.context.purge(true,nil,true)
else
application.help("basic")
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-convert.lua b/Master/texmf-dist/scripts/context/lua/mtx-convert.lua
index 0c5c01bbfbe..b4e6e010bf8 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-convert.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-convert.lua
@@ -23,16 +23,27 @@ local application = logs.application {
helpinfo = helpinfo,
}
+local format, find = string.format, string.find
+local concat = table.concat
+
local report = application.report
-graphics = graphics or { }
-graphics.converters = graphics.converters or { }
+scripts = scripts or { }
+scripts.convert = scripts.convert or { }
+local convert = scripts.convert
+convert.converters = convert.converters or { }
+local converters = convert.converters
+
+local gsprogram = (os.type == "windows" and "gswin32c") or "gs"
+local gstemplate_eps = "%s -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dEPSCrop -dNOPAUSE -dSAFER -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit"
+local gstemplate_ps = "%s -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dNOPAUSE -dSAFER -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit"
-local gsprogram = (os.type == "windows" and "gswin32c") or "gs"
-local gstemplate = "%s -q -sDEVICE=pdfwrite -dEPSCrop -dNOPAUSE -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit"
+function converters.eps(oldname,newname)
+ return format(gstemplate_eps,gsprogram,newname,oldname)
+end
-function graphics.converters.eps(oldname,newname)
- return gstemplate:format(gsprogram,newname,oldname)
+function converters.ps(oldname,newname)
+ return format(gstemplate_ps,gsprogram,newname,oldname)
end
local improgram = "convert"
@@ -42,21 +53,21 @@ local imtemplate = {
high = "%s -quality 100 -compress zip %s pdf:%s",
}
-function graphics.converters.jpg(oldname,newname)
+function converters.jpg(oldname,newname)
local ea = environment.arguments
local quality = (ea.high and 'high') or (ea.medium and 'medium') or (ea.low and 'low') or 'high'
- return imtemplate[quality]:format(improgram,oldname,newname)
+ return format(imtemplate[quality],improgram,oldname,newname)
end
-graphics.converters.gif = graphics.converters.jpg
-graphics.converters.tif = graphics.converters.jpg
-graphics.converters.tiff = graphics.converters.jpg
-graphics.converters.png = graphics.converters.jpg
+converters.gif = converters.jpg
+converters.tif = converters.jpg
+converters.tiff = converters.jpg
+converters.png = converters.jpg
-local function convert(kind,oldname,newname)
- if graphics.converters[kind] then -- extra test
+function converters.convertgraphic(kind,oldname,newname)
+ if converters[kind] then -- extra test
local tmpname = file.replacesuffix(newname,"tmp")
- local command = graphics.converters[kind](oldname,tmpname)
+ local command = converters[kind](oldname,tmpname)
report("command: %s",command)
io.flush()
os.spawn(command)
@@ -68,58 +79,62 @@ local function convert(kind,oldname,newname)
end
end
-function graphics.converters.convertpath(inputpath,outputpath)
+function converters.convertpath(inputpath,outputpath)
inputpath = inputpath or "."
outputpath = outputpath or "."
for name in lfs.dir(inputpath) do
local suffix = file.extname(name)
- if name:find("%.$") then
+ if find(name,"%.$") then
-- skip . and ..
- elseif graphics.converters[suffix] then
+ elseif converters[suffix] then
local oldname = file.join(inputpath,name)
local newname = file.join(outputpath,file.replacesuffix(name,"pdf"))
local et = lfs.attributes(oldname,"modification")
local pt = lfs.attributes(newname,"modification")
if not pt or et > pt then
dir.mkdirs(outputpath)
- convert(suffix,oldname,newname)
+ converters.convertgraphic(suffix,oldname,newname)
end
elseif lfs.isdir(inputpath .. "/".. name) then
- graphics.converters.convertpath(inputpath .. "/".. name,outputpath .. "/".. name)
+ converters.convertpath(inputpath .. "/".. name,outputpath .. "/".. name)
end
end
end
-function graphics.converters.convertfile(oldname)
+function converters.convertfile(oldname)
local suffix = file.extname(oldname)
- if graphics.converters[suffix] then
- local newname = file.replacesuffix(name,"pdf")
+ if converters[suffix] then
+ local newname = file.replacesuffix(oldname,"pdf")
if oldname == newname then
-- todo: downsample, crop etc
elseif environment.argument("force") then
- convert(suffix,oldname,newname)
+ converters.convertgraphic(suffix,oldname,newname)
else
local et = lfs.attributes(oldname,"modification")
local pt = lfs.attributes(newname,"modification")
if not pt or et > pt then
- convert(suffix,oldname,newname)
+ converters.convertgraphic(suffix,oldname,newname)
end
end
end
end
-scripts = scripts or { }
-scripts.convert = scripts.convert or { }
+if environment.ownscript then
+ -- stand alone
+else
+ report(application.banner)
+ return convert
+end
-scripts.convert.delay = 5 * 60 -- 5 minutes
+convert.delay = 5 * 60 -- 5 minutes
-function scripts.convert.convertall()
+function convert.convertall()
local watch = environment.arguments.watch or false
- local delay = environment.arguments.delay or scripts.convert.delay
+ local delay = environment.arguments.delay or convert.delay
local input = environment.arguments.inputpath or "."
local output = environment.arguments.outputpath or "."
while true do
- graphics.converters.convertpath(input, output)
+ converters.convertpath(input, output)
if watch then
os.sleep(delay)
else
@@ -128,17 +143,17 @@ function scripts.convert.convertall()
end
end
-function scripts.convert.convertgiven()
+function convert.convertgiven()
local files = environment.files
for i=1,#files do
- graphics.converters.convertfile(files[i])
+ converters.convertfile(files[i])
end
end
-if environment.argument("convertall") then
- scripts.convert.convertall()
+if environment.arguments.convertall then
+ convert.convertall()
elseif environment.files[1] then
- scripts.convert.convertgiven()
+ convert.convertgiven()
else
application.help()
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-epub.lua b/Master/texmf-dist/scripts/context/lua/mtx-epub.lua
index 70ee7828cee..7d1c157749f 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-epub.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-epub.lua
@@ -18,7 +18,7 @@ if not modules then modules = { } end modules ['mtx-epub'] = {
-- first we need a decent strategy to export them. More information will be
-- available on the wiki.
-local format = string.format
+local format, gsub = string.format, string.gsub
local concat = table.concat
local helpinfo = [[
@@ -60,12 +60,13 @@ local package = [[
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
<dc:title>My Title</dc:title>
<dc:language>en</dc:language>
- <dc:identifier id="%s" />
+ <dc:identifier id="%s" >urn:uuid:%s</dc:identifier>
<dc:creator opf:file-as="Self, My" opf:role="aut">MySelf</dc:creator>
+ <dc:date>%s</dc:date>
</metadata>
<manifest>
- %s
+%s
</manifest>
<spine toc="ncx">
@@ -75,24 +76,65 @@ local package = [[
</package>
]]
--- We need to figure out what is permitted; numbers only seem to give
--- problems is some applications as do names with dashes.
+local item = [[ <item id='%s' href='%s' media-type='%s'/>]]
+
+local toc = [[
+<?xml version="1.0"?>
+
+<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">
+
+<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
+
+ <head>
+ <meta name="dtb:uid" content="%s" />
+ <meta name="dtb:depth" content="2" />
+ <meta name="dtb:totalPgeCount" content="0" />
+ <meta name="dtb:maxPageNumber" content="0" />
+ </head>
+
+ <docTitle>
+ <text>%s</text>
+ </docTitle>
+
+ <navMap>
+ <navPoint id="np-1" playOrder="1">
+ <navLabel>
+ <text>start</text>
+ </navLabel>
+ <content src="%s"/>
+ </navPoint>
+ </navMap>
+
+</ncx>
+]]
+
+-- We need to figure out what is permitted. Numbers only seem to give
+-- problems is some applications as do names with dashes. Also the
+-- optional toc is supposed to be there and although id's are by
+-- concept neutral, there are sometimes hard requirements with respect
+-- to their name like ncx and toc.ncx). Maybe we should stick to 3.0
+-- only.
local function dumbid(filename)
-- return (string.gsub(os.uuid(),"%-%","")) -- to be tested
- return file.nameonly(filename)
+ return file.nameonly(filename) .. "-" .. file.extname(filename)
end
local mimetypes = {
xhtml = "application/xhtml+xml",
+ xml = "application/xhtml+xml",
css = "text/css",
+ svg = "image/svg+xml",
+ png = "image/png",
+ jpg = "image/jpeg",
+ ncx = "application/x-dtbncx+xml",
-- default = "text/plain",
}
local idmakers = {
ncx = function(filename) return "ncx" end,
-- css = function(filename) return "stylesheet" end,
- default = function(filename) return dubmid(filename) end,
+ default = function(filename) return dumbid(filename) end,
}
-- specification = {
@@ -106,63 +148,145 @@ local idmakers = {
-- }
-- }
+local function locateimages(oldname,newname,subpath)
+ local data = io.loaddata(oldname)
+ local images = { }
+ local done = gsub(data,"(background%-image *: * url%()(.-)(%))", function(before,name,after)
+ if subpath then
+ name = file.join(subpath,name)
+ end
+ images[#images+1] = name
+ return before .. name .. after
+ end)
+ if newname then
+ io.savedata(done,newname)
+ end
+ return images
+end
+
+local zippers = {
+ {
+ name = "zip",
+ uncompressed = "zip %s -X -0 %s",
+ compressed = "zip %s -X -9 -r %s",
+ },
+ {
+ name = "7zip (7z)",
+ uncompressed = "7z a -tzip -mx0 %s %s",
+ compressed = "7z a -tzip %s %s",
+ },
+}
+
function scripts.epub.make()
local filename = environment.files[1]
- if filename and filename ~= "" then
+ if filename and filename ~= "" and type(filename) == "string" then
filename = file.basename(filename)
local specfile = file.replacesuffix(filename,"specification")
local specification = lfs.isfile(specfile) and dofile(specfile) or { }
- -- inspect(specification)
+-- inspect(specification)
local name = specification.name or file.removesuffix(filename)
- local identifier = specification.identifier or os.uuid()
+ local identifier = specification.identifier or os.uuid(true)
local files = specification.files or { file.addsuffix(filename,"xhtml") }
+ local images = specification.images or { }
local root = specification.root or files[1]
+ -- identifier = gsub(identifier,"[^a-zA-z0-9]","")
+
+ identifier = "BookId" -- weird requirement
+
local epubname = name
local epubpath = file.replacesuffix(name,"tree")
local epubfile = file.replacesuffix(name,"epub")
local epubroot = file.replacesuffix(name,"opf")
+ local epubtoc = "toc.ncx"
+ application.report("creating paths in tree %s",epubpath)
lfs.mkdir(epubpath)
lfs.mkdir(file.join(epubpath,"META-INF"))
lfs.mkdir(file.join(epubpath,"OPS"))
- local used = { }
+ local used = { }
- for i=1,#files do
- local filename = files[i]
+ local function copyone(filename)
local suffix = file.suffix(filename)
local mime = mimetypes[suffix]
if mime then
local idmaker = idmakers[suffix] or idmakers.default
- file.copy(filename,file.join(epubpath,"OPS",filename))
- used[#used+1] = format("<item id='%s' href='%s' media-type='%s'/>",idmaker(filename),filename,mime)
+ local target = file.join(epubpath,"OPS",filename)
+ file.copy(filename,target)
+ application.report("copying %s to %s",filename,target)
+ used[#used+1] = format(item,idmaker(filename),filename,mime)
end
end
+ copyone("toc.ncx")
+
+ local function copythem(files)
+ for i=1,#files do
+ local filename = files[i]
+ if type(filename) == "string" then
+ copyone(filename)
+ end
+ end
+ end
+
+ copythem(files)
+
+ local theimages = { }
+
+ for k, v in table.sortedpairs(images) do
+ theimages[#theimages+1] = k
+ if not lfs.isfile(k) and file.extname(k) == "svg" and file.extname(v) == "pdf" then
+ local command = format("inkscape --export-plain-svg=%s %s",k,v)
+ application.report("running command '%s'\n\n",command)
+ os.execute(command)
+ end
+ end
+
+ copythem(theimages)
+
+ local idmaker = idmakers[file.extname(root)] or idmakers.default
+
container = format(container,epubroot)
- package = format(package,identifier,identifier,concat(used,"\n"),file.removesuffix(root))
+ package = format(package,identifier,identifier,os.uuid(),os.date("!%Y-%m-%dT%H:%M:%SZ"),concat(used,"\n"),idmaker(root))
+ toc = format(toc,identifier,"title",root)
io.savedata(file.join(epubpath,"mimetype"),mimetype)
io.savedata(file.join(epubpath,"META-INF","container.xml"),container)
io.savedata(file.join(epubpath,"OPS",epubroot),package)
+ io.savedata(file.join(epubpath,"OPS",epubtoc),toc)
- lfs.chdir(epubpath)
+ application.report("creating archive\n\n")
+
+ local done = false
+ local list = { }
+ lfs.chdir(epubpath)
os.remove(epubfile)
- os.execute(format("zip %s -0 %s",epubfile,"mimetype"))
- os.execute(format("zip %s -r %s",epubfile,"META-INF"))
- os.execute(format("zip %s -r %s",epubfile,"OPS"))
+ for i=1,#zippers do
+ local zipper = zippers[i]
+ if os.execute(format(zipper.uncompressed,epubfile,"mimetype")) then
+ os.execute(format(zipper.compressed,epubfile,"META-INF"))
+ os.execute(format(zipper.compressed,epubfile,"OPS"))
+ done = zipper.name
+ else
+ list[#list+1] = zipper.name
+ end
+ end
lfs.chdir("..")
- application.report("epub archive: %s",file.join(epubpath,epubfile))
+ if done then
+ application.report("epub archive made using %s: %s",done,file.join(epubpath,epubfile))
+ else
+ application.report("no epub archive made, install one of: %s",concat(list," "))
+ end
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua b/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua
index 8c8f47a70ab..c5b458c1422 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua
@@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['mtx-fonts'] = {
local helpinfo = [[
--save save open type font in raw table
+--unpack save a tma file in a more readale format
--reload generate new font database
--reload --simple generate 'luatex-fonts-names.lua' (not for context!)
@@ -334,6 +335,23 @@ function scripts.fonts.list()
end
+function scripts.fonts.unpack()
+ local name = file.removesuffix(file.basename(environment.files[1] or ""))
+ if name and name ~= "" then
+ local cache = containers.define("fonts", "otf", 2.730, true)
+ local cleanname = containers.cleanname(name)
+ local data = containers.read(cache,cleanname)
+ if data then
+ local savename = file.addsuffix(cleanname .. "-unpacked","tma")
+ report("fontsave, saving data in %s",savename)
+ fonts.handlers.otf.enhancers.unpack(data)
+ io.savedata(savename,table.serialize(data,true))
+ else
+ report("unknown file '%s'",name)
+ end
+ end
+end
+
function scripts.fonts.save()
local name = environment.files[1] or ""
local sub = environment.files[2] or ""
@@ -387,6 +405,8 @@ elseif environment.argument("reload") then
scripts.fonts.reload()
elseif environment.argument("save") then
scripts.fonts.save()
+elseif environment.argument("unpack") then
+ scripts.fonts.unpack()
elseif environment.argument("statistics") then
fonts.names.statistics()
else
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-grep.lua b/Master/texmf-dist/scripts/context/lua/mtx-grep.lua
index 963422c68ec..6e33d440c4c 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-grep.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-grep.lua
@@ -10,6 +10,7 @@ local helpinfo = [[
--pattern search for pattern (optional)
--count count matches only
--nocomment skip lines that start with %% or #
+--xml pattern is lpath expression
patterns are lua patterns and need to be escaped accordingly
]]
@@ -35,68 +36,100 @@ local content = lpeg.C((1-newline)^0) * newline
local write_nl = texio.write_nl
+ -- local pattern = "LIJST[@TYPE='BULLET']/LIJSTITEM[contains(text(),'Kern')]"
+
function scripts.grep.find(pattern, files, offset)
if pattern and pattern ~= "" then
statistics.starttiming(scripts.grep)
local nofmatches, noffiles, nofmatchedfiles = 0, 0, 0
local n, m, name, check = 0, 0, "", nil
local count, nocomment = environment.argument("count"), environment.argument("nocomment")
- if nocomment then
- if count then
- check = function(line)
- n = n + 1
- if find(line,"^[%%#]") then
- -- skip
- elseif find(line,pattern) then
- m = m + 1
- end
- end
- else
- check = function(line)
- n = n + 1
- if find(line,"^[%%#]") then
- -- skip
- elseif find(line,pattern) then
- m = m + 1
- write_nl(format("%s %6i: %s",name,n,line))
- io.flush()
+ if environment.argument("xml") then
+ for i=offset or 1, #files do
+ local globbed = dir.glob(files[i])
+ for i=1,#globbed do
+ local nam = globbed[i]
+ name = nam
+ local data = xml.load(name)
+ if data and not data.error then
+ n, m, noffiles = 0, 0, noffiles + 1
+ if count then
+ for c in xml.collected(data,pattern) do
+ m = m + 1
+ end
+ if m > 0 then
+ nofmatches = nofmatches + m
+ nofmatchedfiles = nofmatchedfiles + 1
+ write_nl(format("%s: %s",name,m))
+ io.flush()
+ end
+ else
+ for c in xml.collected(data,pattern) do
+ m = m + 1
+ write_nl(format("%s: %s",name,xml.tostring(c)))
+ end
+ end
end
end
end
else
- if count then
- check = function(line)
- n = n + 1
- if find(line,pattern) then
- m = m + 1
+ if nocomment then
+ if count then
+ check = function(line)
+ n = n + 1
+ if find(line,"^[%%#]") then
+ -- skip
+ elseif find(line,pattern) then
+ m = m + 1
+ end
+ end
+ else
+ check = function(line)
+ n = n + 1
+ if find(line,"^[%%#]") then
+ -- skip
+ elseif find(line,pattern) then
+ m = m + 1
+ write_nl(format("%s %6i: %s",name,n,line))
+ io.flush()
+ end
end
end
else
- check = function(line)
- n = n + 1
- if find(line,pattern) then
- m = m + 1
- write_nl(format("%s %6i: %s",name,n,line))
- io.flush()
+ if count then
+ check = function(line)
+ n = n + 1
+ if find(line,pattern) then
+ m = m + 1
+ end
+ end
+ else
+ check = function(line)
+ n = n + 1
+ if find(line,pattern) then
+ m = m + 1
+ write_nl(format("%s %6i: %s",name,n,line))
+ io.flush()
+ end
end
end
end
- end
- local capture = (content/check)^0
- for i=offset or 1, #files do
- local globbed = dir.glob(files[i])
- for i=1,#globbed do
- local nam = globbed[i]
- name = nam
- local data = io.loaddata(name)
- if data then
- n, m, noffiles = 0, 0, noffiles + 1
- capture:match(data)
- if count and m > 0 then
- nofmatches = nofmatches + m
- nofmatchedfiles = nofmatchedfiles + 1
- write_nl(format("%s: %s",name,m))
- io.flush()
+ local capture = (content/check)^0
+ for i=offset or 1, #files do
+ local globbed = dir.glob(files[i])
+ for i=1,#globbed do
+ local nam = globbed[i]
+ name = nam
+ local data = io.loaddata(name)
+ if data then
+ n, m, noffiles = 0, 0, noffiles + 1
+ capture:match(data)
+ if count and m > 0 then
+ nofmatches = nofmatches + m
+ nofmatchedfiles = nofmatchedfiles + 1
+ write_nl(format("%s: %s",name,m))
+ io.flush()
+ end
end
end
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-interface.lua b/Master/texmf-dist/scripts/context/lua/mtx-interface.lua
index 954cb449870..f52fde345d5 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-interface.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-interface.lua
@@ -47,132 +47,167 @@ local flushers = { }
local userinterfaces = { 'en','cs','de','it','nl','ro','fr','pe' }
local messageinterfaces = { 'en','cs','de','it','nl','ro','fr','pe','no' }
-function flushers.scite(interface,commands)
- local result, i = {}, 0
- result[#result+1] = format("keywordclass.macros.context.%s=",interface)
- for i=1,#commands do
- local command = commands[i]
- if i==0 then
- result[#result+1] = "\\\n"
- i = 5
- else
- i = i - 1
+local function collect(filename,class,data)
+ if data then
+ local result = { }
+ for name, list in next, data do
+ result[#result+1] = format("keywordclass.%s.%s=\\\n",class,name)
+ for i=1,#list do
+ if i%5 == 0 then
+ result[#result+1] = "\\\n"
+ end
+ result[#result+1] = format("%s ",list[i])
+ end
+ result[#result+1] = "\n\n"
end
- result[#result+1] = format("%s ",command)
+ io.savedata(file.addsuffix(filename,"properties"),concat(result))
+ io.savedata(file.addsuffix(filename,"lua"), table.serialize(data,true))
+ else
+ os.remove(filename)
+ end
+end
+
+function flushers.scite(collected)
+ local data = { }
+ for interface, whatever in next, collected do
+ data[interface] = whatever.commands
end
- io.savedata(format("cont-%s-scite.properties",interface), concat(result),"\n")
- io.savedata(format("cont-%s-scite.lua",interface), table.serialize(commands,true))
+ collect("scite-context-data-interfaces", "context", data)
+ collect("scite-context-data-metapost", "metapost", dofile(resolvers.findfile("mult-mps.lua")))
+ collect("scite-context-data-metafun", "metafun", dofile(resolvers.findfile("mult-fun.lua")))
+ collect("scite-context-data-context", "context", dofile(resolvers.findfile("mult-low.lua")))
+ collect("scite-context-data-tex", "tex", dofile(resolvers.findfile("mult-prm.lua")))
end
-function flushers.jedit(interface,commands)
- local result = {}
- result[#result+1] = "<?xml version='1.0'?>"
- result[#result+1] = "<!DOCTYPE MODE SYSTEM 'xmode.dtd'>\n"
- result[#result+1] = "<MODE>"
- result[#result+1] = "\t<RULES>"
- result[#result+1] = "\t\t<KEYWORDS>"
- for i=1,#commands do
- result[#result+1] = format("\t\t\t<KEYWORD2>%s</KEYWORD2>",commands[i])
+function flushers.jedit(collected)
+ for interface, whatever in next, collected do
+ local commands = whatever.commands
+ local environments = whatever.environments
+ local result = { }
+ result[#result+1] = "<?xml version='1.0'?>"
+ result[#result+1] = "<!DOCTYPE MODE SYSTEM 'xmode.dtd'>\n"
+ result[#result+1] = "<MODE>"
+ result[#result+1] = "\t<RULES>"
+ result[#result+1] = "\t\t<KEYWORDS>"
+ for i=1,#commands do
+ result[#result+1] = format("\t\t\t<KEYWORD2>%s</KEYWORD2>",commands[i])
+ end
+ result[#result+1] = "\t\t</KEYWORDS>"
+ result[#result+1] = "\t</RULES>"
+ result[#result+1] = "</MODE>"
+ io.savedata(format("context-jedit-%s.xml",interface), concat(result),"\n")
end
- result[#result+1] = "\t\t</KEYWORDS>"
- result[#result+1] = "\t</RULES>"
- result[#result+1] = "</MODE>"
- io.savedata(format("context-jedit-%s.xml",interface), concat(result),"\n")
end
-function flushers.bbedit(interface,commands)
- local result = {}
- result[#result+1] = "<?xml version='1.0'?>"
- result[#result+1] = "<key>BBLMKeywordList</key>"
- result[#result+1] = "<array>"
- for i=1,#commands do
- result[#result+1] = format("\t<string>\\%s</string>",commands[i])
+function flushers.bbedit(collected)
+ for interface, whatever in next, collected do
+ local commands = whatever.commands
+ local environments = whatever.environments
+ local result = {}
+ result[#result+1] = "<?xml version='1.0'?>"
+ result[#result+1] = "<key>BBLMKeywordList</key>"
+ result[#result+1] = "<array>"
+ for i=1,#commands do
+ result[#result+1] = format("\t<string>\\%s</string>",commands[i])
+ end
+ result[#result+1] = "</array>"
+ io.savedata(format("context-bbedit-%s.xml",interface), concat(result),"\n")
end
- result[#result+1] = "</array>"
- io.savedata(format("context-bbedit-%s.xml",interface), concat(result),"\n")
end
-function flushers.raw(interface,commands)
- for i=1,#commands do
- report(commands[i])
+function flushers.raw(collected)
+ for interface, whatever in next, collected do
+ local commands = whatever.commands
+ local environments = whatever.environments
+ for i=1,#commands do
+ report(commands[i])
+ end
end
end
local textpadcreator = "mtx-interface-textpad.lua"
-function flushers.text(interface,commands,environments)
- local c, cname = { }, format("context-commands-%s.txt",interface)
- local e, ename = { }, format("context-environments-%s.txt",interface)
- report("saving '%s'",cname)
- for i=1,#commands do
- c[#c+1] = format("\\%s",commands[i])
- end
- io.savedata(cname,concat(c,"\n"))
- report("saving '%s'",ename)
- for i=1,#environments do
- e[#e+1] = format("\\start%s",environments[i])
- e[#e+1] = format("\\stop%s", environments[i])
+function flushers.text(collected)
+ for interface, whatever in next, collected do
+ local commands = whatever.commands
+ local environments = whatever.environments
+ local c, cname = { }, format("context-commands-%s.txt",interface)
+ local e, ename = { }, format("context-environments-%s.txt",interface)
+ report("saving '%s'",cname)
+ for i=1,#commands do
+ c[#c+1] = format("\\%s",commands[i])
+ end
+ io.savedata(cname,concat(c,"\n"))
+ report("saving '%s'",ename)
+ for i=1,#environments do
+ e[#e+1] = format("\\start%s",environments[i])
+ e[#e+1] = format("\\stop%s", environments[i])
+ end
+ io.savedata(format("context-environments-%s.txt",interface),concat(e,"\n"))
end
- io.savedata(format("context-environments-%s.txt",interface),concat(e,"\n"))
end
-function flushers.textpad(interface,commands,environments)
- flushers.text(interface,commands,environments)
- --
- -- plugin, this is a rewrite of a file provided by Lukas Prochazka
- --
- local function merge(templatedata,destinationdata,categories)
- report("loading '%s'",templatedata)
- local data = io.loaddata(templatedata)
- local done = 0
- for i=1,#categories do
- local category = categories[i]
- local cpattern = ";%s*category:%s*(" .. category .. ")%s*[\n\r]+"
- local fpattern = ";%s*filename:%s*(" .. "%S+" .. ")%s*[\n\r]+"
- data = gsub(data,cpattern..fpattern,function(category,filename)
- local found = resolvers.findfile(filename) or ""
- local blob = found ~= "" and io.loaddata(found) or ""
- if blob == "" then
- report("category: %s, filename: %s, not found",category,filename)
- else
- done = done + 1
- report("category: %s, filename: %s, merged",category,filename)
- end
- return format("; category: %s\n; filename: %s\n%s\n\n",category,filename,blob)
- end)
+function flushers.textpad(collected)
+ flushers.text(collected)
+ for interface, whatever in next, collected do
+ local commands = whatever.commands
+ local environments = whatever.environments
+ --
+ -- plugin, this is a rewrite of a file provided by Lukas Prochazka
+ --
+ local function merge(templatedata,destinationdata,categories)
+ report("loading '%s'",templatedata)
+ local data = io.loaddata(templatedata)
+ local done = 0
+ for i=1,#categories do
+ local category = categories[i]
+ local cpattern = ";%s*category:%s*(" .. category .. ")%s*[\n\r]+"
+ local fpattern = ";%s*filename:%s*(" .. "%S+" .. ")%s*[\n\r]+"
+ data = gsub(data,cpattern..fpattern,function(category,filename)
+ local found = resolvers.findfile(filename) or ""
+ local blob = found ~= "" and io.loaddata(found) or ""
+ if blob == "" then
+ report("category: %s, filename: %s, not found",category,filename)
+ else
+ done = done + 1
+ report("category: %s, filename: %s, merged",category,filename)
+ end
+ return format("; category: %s\n; filename: %s\n%s\n\n",category,filename,blob)
+ end)
+ end
+ if done > 0 then
+ report("saving '%s' (%s files merged)",destinationdata,done)
+ io.savedata(destinationdata,data)
+ else
+ report("skipping '%s' (no files merged)",destinationdata)
+ end
end
- if done > 0 then
- report("saving '%s' (%s files merged)",destinationdata,done)
- io.savedata(destinationdata,data)
+ local templatename = "textpad-context-template.txt"
+ local templatedata = resolvers.findfile(templatename) or ""
+ if templatedata == "" then
+ report("unable to locate template '%s'",templatename)
else
- report("skipping '%s' (no files merged)",destinationdata)
+ merge(templatedata, "context.syn", { "tex commands","context commands" })
+ if environment.argument("textpad") == "latex" then
+ merge(templatedata, "context-latex.syn", { "tex commands","context commands", "latex commands" })
+ end
end
- end
- local templatename = "textpad-context-template.txt"
- local templatedata = resolvers.findfile(templatename) or ""
- if templatedata == "" then
- report("unable to locate template '%s'",templatename)
- else
- merge(templatedata, "context.syn", { "tex commands","context commands" })
- if environment.argument("textpad") == "latex" then
- merge(templatedata, "context-latex.syn", { "tex commands","context commands", "latex commands" })
+ local r = { }
+ local c = io.loaddata("context-commands-en.txt") or "" -- sits on the same path
+ local e = io.loaddata("context-environments-en.txt") or "" -- sits on the same path
+ for s in gmatch(c,"\\(.-)%s") do
+ r[#r+1] = format("\n!TEXT=%s\n\\%s\n!",s,s)
end
+ for s in gmatch(e,"\\start(.-)%s+\\stop(.-)") do
+ r[#r+1] = format("\n!TEXT=%s (start/stop)\n\\start%s \\^\\stop%s\n!",s,s,s)
+ end
+ sort(r)
+ insert(r,1,"!TCL=597,\n!TITLE=ConTeXt\n!SORT=N\n!CHARSET=DEFAULT")
+ io.savedata("context.tcl",concat(r,"\n"))
+ -- cleanup
+ os.remove("context-commands-en.txt")
+ os.remove("context-environments-en.txt")
end
- local r = { }
- local c = io.loaddata("context-commands-en.txt") or "" -- sits on the same path
- local e = io.loaddata("context-environments-en.txt") or "" -- sits on the same path
- for s in gmatch(c,"\\(.-)%s") do
- r[#r+1] = format("\n!TEXT=%s\n\\%s\n!",s,s)
- end
- for s in gmatch(e,"\\start(.-)%s+\\stop(.-)") do
- r[#r+1] = format("\n!TEXT=%s (start/stop)\n\\start%s \\^\\stop%s\n!",s,s,s)
- end
- sort(r)
- insert(r,1,"!TCL=597,\n!TITLE=ConTeXt\n!SORT=N\n!CHARSET=DEFAULT")
- io.savedata("context.tcl",concat(r,"\n"))
- -- cleanup
- os.remove("context-commands-en.txt")
- os.remove("context-environments-en.txt")
end
function scripts.interface.editor(editor,split,forcedinterfaces)
@@ -184,6 +219,7 @@ function scripts.interface.editor(editor,split,forcedinterfaces)
if xmlfile == "" then
report("unable to locate cont-en.xml")
end
+ local collected = { }
for i=1,#interfaces do
local interface = interfaces[i]
local keyfile = resolvers.findfile(format("keys-%s.xml",interface)) or ""
@@ -222,10 +258,43 @@ function scripts.interface.editor(editor,split,forcedinterfaces)
if #commands > 0 then
sort(commands)
sort(environments)
- flushers[editor](interface,commands,environments)
+ collected[interface] = {
+ commands = commands,
+ environments = environments,
+ }
end
end
end
+ -- awaiting completion of the xml file
+ local definitions = dofile(resolvers.findfile("mult-def.lua"))
+ if definitions then
+ local commands = { en = { } }
+ for command, languages in next, definitions.commands do
+ commands.en[languages.en or command] = true
+ for language, command in next, languages do
+ local c = commands[language]
+ if c then
+ c[command] = true
+ else
+ commands[language] = { [command] = true }
+ end
+ end
+ end
+ for language, data in next, commands do
+ local fromlua = data
+ local fromxml = collected[language].commands
+ for i=1,#fromxml do
+ local c = fromxml[i]
+ if not fromlua[c] then
+ -- print(language,c)
+ fromlua[c] = true
+ end
+ end
+ collected[language].commands = table.sortedkeys(fromlua)
+ end
+ end
+ --
+ flushers[editor](collected)
end
function scripts.interface.check()
@@ -332,7 +401,8 @@ function scripts.interface.interfaces()
end
function scripts.interface.preprocess()
- require("luat-mac.lua")
+ dofile(resolvers.findfile("luat-mac.lua"))
+ -- require("luat-mac.lua")
local newsuffix = environment.argument("suffix") or "log"
local force = environment.argument("force")
for i=1,#environment.files do
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-modules.lua b/Master/texmf-dist/scripts/context/lua/mtx-modules.lua
index 8f3ab89cfb6..902b12ac303 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-modules.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-modules.lua
@@ -47,46 +47,60 @@ local report = application.report
-- start-stop commands. The suffix specificaction can be overruled at runtime,
-- but defaults to the file extension. This specification can be used for language
-- depended verbatim typesetting.
+--
+-- In the mkiv variant we filter the \module settings so that we don't have
+-- to mess with global document settings.
-local find, format, sub, is_empty, strip = string.find, string.format, string.sub, string.is_empty, string.strip
+local find, format, sub, is_empty, strip, gsub = string.find, string.format, string.sub, string.is_empty, string.strip, string.gsub
local function source_to_ted(inpname,outname,filetype)
- local inp = io.open(inpname)
- if not inp then
- report("unable to open '%s'",inpname)
- return
- end
- local out = io.open(outname,"w")
- if not out then
- report("unable to open '%s'",outname)
+ local data = io.loaddata(inpname)
+ if data == "" then
+ report("invalid module name '%s'",inpname)
return
end
report("converting '%s' to '%s'",inpname,outname)
local skiplevel, indocument, indefinition = 0, false, false
- out:write(format("\\startmodule[type=%s]\n",filetype or file.suffix(inpname)))
- for line in inp:lines() do
---~ line = strip(line)
+ local started = false
+ local settings = format("type=%s",filetype or file.suffix(inpname))
+ local preamble, n = lpeg.match(lpeg.Cs((1-lpeg.patterns.newline^2)^1) * lpeg.Cp(),data)
+ if preamble then
+ preamble = string.match(preamble,"\\module.-%[(.-)%]")
+ if preamble then
+ preamble = gsub(preamble,"%%D *","")
+ preamble = gsub(preamble,"%%(.-)[\n\r]","")
+ preamble = gsub(preamble,"[\n\r]","")
+ preamble = strip(preamble)
+ settings = format("%s,%s",settings,preamble)
+ data = string.sub(data,n,#data)
+ end
+ end
+ local lines = string.splitlines(data)
+ local result = { }
+ result[#result+1] = format("\\startmoduledocumentation[%s]",settings)
+ for i=1,#lines do
+ local line = lines[i]
if find(line,"^%%D ") or find(line,"^%%D$") then
if skiplevel == 0 then
- local someline = (#line < 3 and "") or sub(line,4,#line)
+ local someline = #line < 3 and "" or sub(line,4,#line)
if indocument then
- out:write(format("%s\n",someline))
+ result[#result+1] = someline
else
if indefinition then
- out:write("\\stopdefinition\n")
+ result[#result+1] = "\\stopdefinition"
indefinition = false
end
if not indocument then
- out:write("\n\\startdocumentation\n")
+ result[#result+1] = "\\startdocumentation"
end
- out:write(format("%s\n",someline))
+ result[#result+1] = someline
indocument = true
end
end
elseif find(line,"^%%M ") or find(line,"^%%M$") then
if skiplevel == 0 then
local someline = (#line < 3 and "") or sub(line,4,#line)
- out:write(format("%s\n",someline))
+ result[#result+1] = someline
end
elseif find(line,"^%%S B") then
skiplevel = skiplevel + 1
@@ -99,36 +113,36 @@ local function source_to_ted(inpname,outname,filetype)
inlocaldocument = false
local someline = line
if indocument then
- out:write("\\stopdocumentation\n")
+ result[#result+1] = "\\stopdocumentation"
indocument = false
end
if indefinition then
if is_empty(someline) then
- out:write("\\stopdefinition\n")
+ result[#result+1] = "\\stopdefinition"
indefinition = false
else
- out:write(format("%s\n",someline))
+ result[#result+1] = someline
end
elseif not is_empty(someline) then
- out:write("\n\\startdefinition\n")
+ result[#result+1] = "\n"
+ result[#result+1] = "\\startdefinition"
indefinition = true
if inlocaldocument then
-- nothing
else
- out:write(format("%s\n",someline))
+ result[#result+1] = someline
end
end
end
end
if indocument then
- out:write("\\stopdocumentation\n")
+ result[#result+1] = "\\stopdocumentation"
end
if indefinition then
- out:write("\\stopdefinition\n")
+ result[#result+1] = "\\stopdefinition"
end
- out:write("\\stopmodule\n")
- out:close()
- inp:close()
+ result[#result+1] = "\\stopmoduledocumentation"
+ io.savedata(outname,table.concat(result,"\n"))
return true
end
@@ -150,7 +164,7 @@ function scripts.modules.process(runtex)
end
local done = source_to_ted(shortname,longname)
if done and runtex then
- os.execute(format("mtxrun --script context --usemodule=mod-01 %s",longname))
+ os.execute(format("mtxrun --script context --usemodule=mod-01 --purge %s",longname))
processed[#processed+1] = longname
end
end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua b/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua
new file mode 100644
index 00000000000..5654b8bc487
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua
@@ -0,0 +1,117 @@
+if not modules then modules = { } end modules ['mtx-pdf'] = {
+ version = 1.001,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local helpinfo = [[
+--info show some info about the given file
+--metadata show metadata xml blob
+]]
+
+local application = logs.application {
+ name = "mtx-pdf",
+ banner = "ConTeXt PDF Helpers 0.01",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+dofile(resolvers.findfile("lpdf-epd.lua","tex"))
+
+scripts = scripts or { }
+scripts.pdf = scripts.pdf or { }
+
+local function loadpdffile(filename)
+ if not filename or filename == "" then
+ report("no filename given")
+ elseif not lfs.isfile(filename) then
+ report("unknown file '%s'",filename)
+ else
+ local pdffile = lpdf.epdf.load(filename)
+ if pdffile then
+ return pdffile
+ else
+ report("no valid pdf file '%s'",filename)
+ end
+ end
+end
+
+function scripts.pdf.info()
+ local filename = environment.files[1]
+ local pdffile = loadpdffile(filename)
+ if pdffile then
+ local catalog = pdffile.Catalog
+ local info = pdffile.Info
+ local pages = pdffile.pages
+ local nofpages = pages.n -- no # yet. will be in 5.2
+
+ report("filename > %s",filename)
+ report("pdf version > %s",catalog.Version)
+ report("number of pages > %s",nofpages)
+ report("title > %s",info.Title)
+ report("creator > %s",info.Creator)
+ report("producer > %s",info.Producer)
+ report("creation date > %s",info.CreationDate)
+ report("modification date > %s",info.ModDate)
+
+ local width, height, start
+ for i=1, nofpages do
+ local page = pages[i]
+ local bbox = page.CropBox or page.MediaBox
+ local w, h = bbox[4]-bbox[2],bbox[3]-bbox[1]
+ if w ~= width or h ~= height then
+ if start then
+ report("cropbox > pages: %s-%s, width: %s, height: %s",start,i-1,width,height)
+ end
+ width, height, start = w, h, i
+ end
+ end
+ report("cropbox > pages: %s-%s, width: %s, height: %s",start,nofpages,width,height)
+ end
+end
+
+function scripts.pdf.metadata()
+ local filename = environment.files[1]
+ local pdffile = loadpdffile(filename)
+ if pdffile then
+ local catalog = pdffile.Catalog
+ local metadata = catalog.Metadata
+ if metadata then
+ report("metadata > \n\n%s\n",metadata())
+ else
+ report("no metadata")
+ end
+ end
+end
+
+if environment.argument("info") then
+ scripts.pdf.info()
+elseif environment.argument("metadata") then
+ scripts.pdf.metadata()
+else
+ application.help()
+end
+
+-- a variant on an experiment by hartmut
+
+--~ function downloadlinks(filename)
+--~ local document = lpdf.epdf.load(filename)
+--~ if document then
+--~ local pages = document.pages
+--~ for p = 1,#pages do
+--~ local annotations = pages[p].Annots
+--~ if annotations then
+--~ for a=1,#annotations do
+--~ local annotation = annotations[a]
+--~ local uri = annotation.Subtype == "Link" and annotation.A and annotation.A.URI
+--~ if uri and string.find(uri,"^http") then
+--~ os.execute("wget " .. uri)
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-rsync.lua b/Master/texmf-dist/scripts/context/lua/mtx-rsync.lua
new file mode 100644
index 00000000000..b549d5bcb62
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/lua/mtx-rsync.lua
@@ -0,0 +1,168 @@
+if not modules then modules = { } end modules ['mtx-rsync'] = {
+ version = 1.000,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is an experimental script that will be extended over time and
+-- is used by myself. An example or a copy spec:
+--
+--
+-- local devdir = "m:/develop/services"
+-- local orgdir = "m:/pod/m4all"
+--
+-- return {
+-- {
+-- origin = { devdir, "framework/scripts/d-dispatchers.lua"},
+-- target = { orgdir, "framework/scripts" },
+-- },
+-- {
+-- origin = { devdir, "framework/scripts/common/*"},
+-- target = { orgdir, "framework/scripts/common" },
+-- },
+-- {
+-- origin = { devdir, "framework/scripts/d-buildtool.lua" },
+-- target = { orgdir, "framework/scripts" }
+-- },
+-- {
+-- origin = { devdir, "framework/scripts/buildtool/*"},
+-- target = { orgdir, "framework/scripts/buildtool" },
+-- },
+-- {
+-- origin = { devdir, "framework/m4all*" },
+-- target = { orgdir, "framework" },
+-- },
+-- {
+-- origin = { devdir, "framework/configurations/*m4all*"},
+-- target = { orgdir, "framework/configurations" },
+-- },
+-- {
+-- recurse = true,
+-- origin = { devdir, "context/tex/texmf-project/tex/context/user/m4all/*" },
+-- target = { orgdir, "context/tex/texmf-project/tex/context/user/m4all" },
+-- },
+-- }
+
+local helpinfo = [[
+--job use given file as specification
+--dryrun show what would happen
+--force force run
+]]
+
+local application = logs.application {
+ name = "mtx-rsync",
+ banner = "Rsync Helpers 0.10",
+ helpinfo = helpinfo,
+}
+
+local format, gsub = string.format, string.gsub
+local concat = table.concat
+
+local report_message = logs.new("rsync message")
+local report_dryrun = logs.new("rsync dryrun")
+local report_normal = logs.new("rsync normal")
+local report_command = logs.new("rsync command")
+
+local cleanup
+
+if os.platform == "mswin" then
+ os.setenv("CYGWIN","nontsec")
+ cleanup = function(name)
+ return (gsub(name,"([a-zA-Z]):/", "/cygdrive/%1/"))
+ end
+else
+ cleanup = function(name)
+ return name
+ end
+end
+
+function rsynccommand(dryrun,recurse,origin,target)
+ local command = "rsync -ptlv "
+ if dryrun then
+ command = command .. "-n "
+ end
+ if recurse then
+ command = command .. "-r "
+ end
+ return format('%s %s %s',command,origin,target)
+end
+
+scripts = scripts or { }
+scripts.rsync = scripts.rsync or { }
+local rsync = scripts.rsync
+
+rsync.mode = "command"
+
+function rsync.run(origin,target,message,recurse)
+ if type(origin) == "table" then
+ origin = concat(origin,"/")
+ end
+ if type(target) == "table" then
+ target = concat(target,"/")
+ end
+ origin = cleanup(origin)
+ target = cleanup(target)
+ if message then
+ report_message(message)
+ end
+ if rsync.mode == "dryrun" then
+ local command = rsynccommand(true,recurse,origin,target)
+ report_dryrun(command.."\n")
+ os.execute(command)
+ elseif rsync.mode == "force" then
+ local command = rsynccommand(false,recurse,origin,target)
+ report_normal(command.."\n")
+ os.execute(command)
+ else
+ local command = rsynccommand(true,recurse,origin,target)
+ report_command(command)
+ end
+end
+
+function rsync.job(list)
+ if type(list) == "string" and lfs.isfile(list) then
+ list = dofile(list)
+ end
+ if type(list) ~= "table" then
+ report_message("invalid job specification")
+ return
+ end
+ for i=1,#list do
+ local li = list[i]
+ local origin = li.origin
+ local target = li.target
+ local message = li.message
+ local recurse = li.recurse
+ if origin and #origin > 0 and target and #target > 0 then -- string or table
+ rsync.run(origin,target,message,recurse)
+ else
+ report_message("invalid job specification at index %s",i)
+ end
+ end
+end
+
+if environment.ownscript then
+ -- stand alone
+else
+ report(application.banner)
+ return rsync
+end
+
+local arguments = environment.arguments
+local files = environment.files
+
+if arguments.dryrun then
+ rsync.mode = "dryrun"
+elseif arguments.force then
+ rsync.mode = "force"
+end
+
+if arguments.job then
+ rsync.job(files[1])
+elseif files[1] and files[2] then
+ rsync.run(files[1],files[2])
+else
+ application.help()
+end
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-scite.lua b/Master/texmf-dist/scripts/context/lua/mtx-scite.lua
index 0ac09b01702..116555e79b0 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-scite.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-scite.lua
@@ -6,17 +6,22 @@ if not modules then modules = { } end modules ['mtx-scite'] = {
license = "see context related readme files"
}
--- todo: append to global properties else order of loading problem
--- linux problem ... files are under root protection so we need --install
+local P, R, S, C, Ct, Cf, Cc, Cg = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.Cg
+local lpegmatch = lpeg.match
+local format, lower, gmatch = string.format, string.lower, string.gmatch
+
+-- local helpinfo = [[
+-- --start [--verbose] start scite
+-- --test report what will happen
+-- ]]
local helpinfo = [[
---start [--verbose] start scite
---test report what will happen
+--words convert spell-*.txt into spell-*.lua
]]
local application = logs.application {
name = "mtx-scite",
- banner = "Scite Startup Script 1.00",
+ banner = "Scite Helper Script 1.00",
helpinfo = helpinfo,
}
@@ -25,148 +30,202 @@ local report = application.report
scripts = scripts or { }
scripts.scite = scripts.scite or { }
-local scitesignals = { "scite-context.rme", "context.properties" }
-local screenfont = "lmtypewriter10-regular.ttf"
+-- todo: append to global properties else order of loading problem
+-- linux problem ... files are under root protection so we need --install
+--
+-- local scitesignals = { "scite-context.rme", "context.properties" }
+-- local screenfont = "lmtypewriter10-regular.ttf"
-function scripts.scite.start(indeed)
- local usedsignal, datapath, fullname, workname, userpath, fontpath
- if os.type == "windows" then
- workname = "scite.exe"
- userpath = os.getenv("USERPROFILE") or ""
- fontpath = os.getenv("SYSTEMROOT")
- fontpath = (fontpath and file.join(fontpath,"fonts")) or ""
- else
- workname = "scite"
- userpath = os.getenv("HOME") or ""
- fontpath = ""
- end
- local binpaths = file.split_path(os.getenv("PATH")) or file.split_path(os.getenv("path"))
- for i=1,#scitesignals do
- local scitesignal = scitesignals[i]
- local scitepath = resolvers.findfile(scitesignal,"other text files") or ""
- if scitepath ~= "" then
- scitepath = file.dirname(scitepath) -- data
- if scitepath == "" then
- scitepath = resolvers.cleanpath(lfs.currentdir())
- else
- usedsignal, datapath = scitesignal, scitepath
- break
- end
- end
- end
- if not datapath or datapath == "" then
- report("invalid datapath, maybe you need to regenerate the file database")
- return false
- end
- if not binpaths or #binpaths == 0 then
- report("invalid binpath")
- return false
- end
- for i=1,#binpaths do
- local p = file.join(binpaths[i],workname)
- if lfs.isfile(p) and lfs.attributes(p,"size") > 10000 then -- avoind stub
- fullname = p
- break
- end
- end
- if not fullname then
- report("unable to locate %s",workname)
- return false
- end
- local properties = dir.glob(file.join(datapath,"*.properties"))
- local luafiles = dir.glob(file.join(datapath,"*.lua"))
- local extrafont = resolvers.findfile(screenfont,"truetype font") or ""
- local pragmafound = dir.glob(file.join(datapath,"pragma.properties"))
- if userpath == "" then
- report("unable to figure out userpath")
- return false
- end
- local verbose = environment.argument("verbose")
- local tobecopied, logdata = { }, { }
- local function check_state(fullname,newpath)
- local basename = file.basename(fullname)
- local destination = file.join(newpath,basename)
- local pa, da = lfs.attributes(fullname), lfs.attributes(destination)
- if not da then
- logdata[#logdata+1] = { "new : %s", basename }
- tobecopied[#tobecopied+1] = { fullname, destination }
- elseif pa.modification > da.modification then
- logdata[#logdata+1] = { "outdated : %s", basename }
- tobecopied[#tobecopied+1] = { fullname, destination }
- else
- logdata[#logdata+1] = { "up to date : %s", basename }
+-- function scripts.scite.start(indeed)
+-- local usedsignal, datapath, fullname, workname, userpath, fontpath
+-- if os.type == "windows" then
+-- workname = "scite.exe"
+-- userpath = os.getenv("USERPROFILE") or ""
+-- fontpath = os.getenv("SYSTEMROOT")
+-- fontpath = (fontpath and file.join(fontpath,"fonts")) or ""
+-- else
+-- workname = "scite"
+-- userpath = os.getenv("HOME") or ""
+-- fontpath = ""
+-- end
+-- local binpaths = file.split_path(os.getenv("PATH")) or file.split_path(os.getenv("path"))
+-- for i=1,#scitesignals do
+-- local scitesignal = scitesignals[i]
+-- local scitepath = resolvers.findfile(scitesignal,"other text files") or ""
+-- if scitepath ~= "" then
+-- scitepath = file.dirname(scitepath) -- data
+-- if scitepath == "" then
+-- scitepath = resolvers.cleanpath(lfs.currentdir())
+-- else
+-- usedsignal, datapath = scitesignal, scitepath
+-- break
+-- end
+-- end
+-- end
+-- if not datapath or datapath == "" then
+-- report("invalid datapath, maybe you need to regenerate the file database")
+-- return false
+-- end
+-- if not binpaths or #binpaths == 0 then
+-- report("invalid binpath")
+-- return false
+-- end
+-- for i=1,#binpaths do
+-- local p = file.join(binpaths[i],workname)
+-- if lfs.isfile(p) and lfs.attributes(p,"size") > 10000 then -- avoind stub
+-- fullname = p
+-- break
+-- end
+-- end
+-- if not fullname then
+-- report("unable to locate %s",workname)
+-- return false
+-- end
+-- local properties = dir.glob(file.join(datapath,"*.properties"))
+-- local luafiles = dir.glob(file.join(datapath,"*.lua"))
+-- local extrafont = resolvers.findfile(screenfont,"truetype font") or ""
+-- local pragmafound = dir.glob(file.join(datapath,"pragma.properties"))
+-- if userpath == "" then
+-- report("unable to figure out userpath")
+-- return false
+-- end
+-- local verbose = environment.argument("verbose")
+-- local tobecopied, logdata = { }, { }
+-- local function check_state(fullname,newpath)
+-- local basename = file.basename(fullname)
+-- local destination = file.join(newpath,basename)
+-- local pa, da = lfs.attributes(fullname), lfs.attributes(destination)
+-- if not da then
+-- logdata[#logdata+1] = { "new : %s", basename }
+-- tobecopied[#tobecopied+1] = { fullname, destination }
+-- elseif pa.modification > da.modification then
+-- logdata[#logdata+1] = { "outdated : %s", basename }
+-- tobecopied[#tobecopied+1] = { fullname, destination }
+-- else
+-- logdata[#logdata+1] = { "up to date : %s", basename }
+-- end
+-- end
+-- for i=1,#properties do
+-- check_state(properties[i],userpath)
+-- end
+-- for i=1,#luafiles do
+-- check_state(luafiles[i],userpath)
+-- end
+-- if fontpath ~= "" then
+-- check_state(extrafont,fontpath)
+-- end
+-- local userpropfile = "SciTEUser.properties"
+-- if os.name ~= "windows" then
+-- userpropfile = "." .. userpropfile
+-- end
+-- local fullpropfile = file.join(userpath,userpropfile)
+-- local userpropdata = io.loaddata(fullpropfile) or ""
+-- local propfiledone = false
+-- if pragmafound then
+-- if userpropdata == "" then
+-- logdata[#logdata+1] = { "error : no user properties found on '%s'", fullpropfile }
+-- elseif string.find(userpropdata,"import *pragma") then
+-- logdata[#logdata+1] = { "up to date : 'import pragma' in '%s'", userpropfile }
+-- else
+-- logdata[#logdata+1] = { "yet unset : 'import pragma' in '%s'", userpropfile }
+-- userproperties = userpropdata .. "\n\nimport pragma\n\n"
+-- propfiledone = true
+-- end
+-- else
+-- if string.find(userpropdata,"import *context") then
+-- logdata[#logdata+1] = { "up to date : 'import context' in '%s'", userpropfile }
+-- else
+-- logdata[#logdata+1] = { "yet unset : 'import context' in '%s'", userpropfile }
+-- userproperties = userpropdata .. "\n\nimport context\n\n"
+-- propfiledone = true
+-- end
+-- end
+-- if not indeed or verbose then
+-- report("used signal: %s", usedsignal)
+-- report("data path : %s", datapath)
+-- report("full name : %s", fullname)
+-- report("user path : %s", userpath)
+-- report("extra font : %s", extrafont)
+-- end
+-- if #logdata > 0 then
+-- report("")
+-- for k=1,#logdata do
+-- local v = logdata[k]
+-- report(v[1],v[2])
+-- end
+-- end
+-- if indeed then
+-- if #tobecopied > 0 then
+-- report("warning : copying updated files")
+-- for i=1,#tobecopied do
+-- local what = tobecopied[i]
+-- report("copying : '%s' => '%s'",what[1],what[2])
+-- file.copy(what[1],what[2])
+-- end
+-- end
+-- if propfiledone then
+-- report("saving : '%s'",userpropfile)
+-- io.savedata(fullpropfile,userpropdata)
+-- end
+-- os.launch(fullname)
+-- end
+-- end
+
+-- local splitter = (Cf(Ct("") * (Cg(C(R("az","AZ","\127\255")^1) * Cc(true)) + P(1))^1,rawset) )^0
+--
+-- local function splitwords(words)
+-- return lpegmatch(splitter,words) -- or just split and tohash
+-- end
+
+local function splitwords(words)
+ local w = { }
+ for s in string.gmatch(words,"[a-zA-Z\127-255]+") do
+ if #s > 2 then -- will become option
+ w[lower(s)] = s
end
end
- for i=1,#properties do
- check_state(properties[i],userpath)
- end
- for i=1,#luafiles do
- check_state(luafiles[i],userpath)
- end
- if fontpath ~= "" then
- check_state(extrafont,fontpath)
- end
- local userpropfile = "SciTEUser.properties"
- if os.name ~= "windows" then
- userpropfile = "." .. userpropfile
- end
- local fullpropfile = file.join(userpath,userpropfile)
- local userpropdata = io.loaddata(fullpropfile) or ""
- local propfiledone = false
- if pragmafound then
- if userpropdata == "" then
- logdata[#logdata+1] = { "error : no user properties found on '%s'", fullpropfile }
- elseif string.find(userpropdata,"import *pragma") then
- logdata[#logdata+1] = { "up to date : 'import pragma' in '%s'", userpropfile }
- else
- logdata[#logdata+1] = { "yet unset : 'import pragma' in '%s'", userpropfile }
- userproperties = userpropdata .. "\n\nimport pragma\n\n"
- propfiledone = true
- end
- else
- if string.find(userpropdata,"import *context") then
- logdata[#logdata+1] = { "up to date : 'import context' in '%s'", userpropfile }
+ return w
+end
+
+-- maybe: lowerkey = UpperWhatever
+
+function scripts.scite.words()
+ for i=1,#environment.files do
+ local tag = environment.files[i]
+ local tag = string.match(tag,"spell%-(..)%.") or tag
+ local txtname = format("spell-%s.txt",tag)
+ local luaname = format("spell-%s.lua",tag)
+ local lucname = format("spell-%s.luc",tag)
+ if lfs.isfile(txtname) then
+ report("loading %s",txtname)
+ local olddata = io.loaddata(txtname) or ""
+ local newdata = {
+ words = splitwords(olddata),
+ -- words = olddata,
+ source = oldname,
+ }
+ report("saving %s",luaname)
+ io.savedata(luaname,table.serialize(newdata,true))
+ report("compiling %s",lucname)
+ os.execute(format("luac -s -o %s %s",lucname,luaname))
else
- logdata[#logdata+1] = { "yet unset : 'import context' in '%s'", userpropfile }
- userproperties = userpropdata .. "\n\nimport context\n\n"
- propfiledone = true
+ report("no data file %s",txtname)
end
end
- if not indeed or verbose then
- report("used signal: %s", usedsignal)
- report("data path : %s", datapath)
- report("full name : %s", fullname)
- report("user path : %s", userpath)
- report("extra font : %s", extrafont)
- end
- if #logdata > 0 then
- report("")
- for k=1,#logdata do
- local v = logdata[k]
- report(v[1],v[2])
- end
- end
- if indeed then
- if #tobecopied > 0 then
- report("warning : copying updated files")
- for i=1,#tobecopied do
- local what = tobecopied[i]
- report("copying : '%s' => '%s'",what[1],what[2])
- file.copy(what[1],what[2])
- end
- end
- if propfiledone then
- report("saving : '%s'",userpropfile)
- io.savedata(fullpropfile,userpropdata)
- end
- os.launch(fullname)
- end
+ report("you need to move the lua files to lexers/data")
end
-if environment.argument("start") then
- scripts.scite.start(true)
-elseif environment.argument("test") then
- scripts.scite.start()
+-- if environment.argument("start") then
+-- scripts.scite.start(true)
+-- elseif environment.argument("test") then
+-- scripts.scite.start()
+-- else
+-- application.help()
+-- end
+
+if environment.argument("words") then
+ scripts.scite.words()
else
application.help()
end
+
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua b/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua
index 15f393853c1..a212e1369d0 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-server-ctx-help.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['mtx-server-ctx-help'] = {
}
-- todo in lua interface: noargument, oneargument, twoarguments, threearguments
+-- todo: pickup translations from mult file
--~ dofile(resolvers.findfile("l-aux.lua","tex"))
--~ dofile(resolvers.findfile("l-url.lua","tex"))
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-server.lua b/Master/texmf-dist/scripts/context/lua/mtx-server.lua
index 4547877b5ef..068d5111130 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-server.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-server.lua
@@ -29,7 +29,8 @@ scripts.webserver = scripts.webserver or { }
dofile(resolvers.findfile("l-url.lua","tex"))
dofile(resolvers.findfile("luat-soc.lua","tex"))
-local socket = socket or require("socket") -- redundant in future version
+local socket = socket or require("socket")
+local http = socket or require("socket.http")
local format = string.format
-- The following two lists are taken from webrick (ruby) and
@@ -300,45 +301,50 @@ function scripts.webserver.run(configuration)
report("scripts subpath: %s",configuration.scripts)
report("context services: http://localhost:%s/mtx-server-ctx-startup.lua",configuration.port)
local server = assert(socket.bind("*", configuration.port))
---~ local reading = { server }
+-- local reading = { server }
while true do -- no multiple clients
local start = os.clock()
---~ local input = socket.select(reading)
---~ local client = input:accept()
+-- local input = socket.select(reading)
+-- local client = input:accept()
local client = server:accept()
client:settimeout(configuration.timeout or 60)
local request, e = client:receive()
+-- local request, e = client:receive("*a") -- doesn't work well (so no post)
if e then
errormessage(client,configuration,404)
else
local from = client:getpeername()
report("request from: %s",tostring(from))
- local fullurl = request:match("GET (.+) HTTP/.*$") -- todo: more clever
- fullurl = socket.url.unescape(fullurl)
- local hashed = url.hashed(fullurl)
- local query = url.query(hashed.query)
- local filename = hashed.path
---~ table.print(hashed)
- if filename then
- filename = socket.url.unescape(filename)
- report("requested action: %s",filename)
- if filename:find("%.%.") then
- filename = nil -- invalid path
- end
- if filename == nil or filename == "" or filename == "/" then
- filename = configuration.index
- report("invalid filename, forcing: %s",filename)
- end
- local suffix = file.extname(filename)
- local action = handlers[suffix] or handlers.generic
- if action then
- report("performing action: %s",filename)
- action(client,configuration,filename,suffix,false,hashed) -- filename and no content
+ local fullurl = request:match("GET (.+) HTTP/.*$") or "" -- todo: more clever / post
+ if fullurl == "" then
+ errormessage(client,configuration,404)
+ else
+ fullurl = socket.url.unescape(fullurl)
+ local hashed = url.hashed(fullurl)
+ local query = url.query(hashed.query)
+ local filename = hashed.path
+-- table.print(hashed)
+ if filename then
+ filename = socket.url.unescape(filename)
+ report("requested action: %s",filename)
+ if filename:find("%.%.") then
+ filename = nil -- invalid path
+ end
+ if filename == nil or filename == "" or filename == "/" then
+ filename = configuration.index
+ report("invalid filename, forcing: %s",filename)
+ end
+ local suffix = file.extname(filename)
+ local action = handlers[suffix] or handlers.generic
+ if action then
+ report("performing action: %s",filename)
+ action(client,configuration,filename,suffix,false,hashed) -- filename and no content
+ else
+ errormessage(client,configuration,404)
+ end
else
errormessage(client,configuration,404)
end
- else
- errormessage(client,configuration,404)
end
end
client:close()
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-tools.lua b/Master/texmf-dist/scripts/context/lua/mtx-tools.lua
index 905b3aa8583..45961a639a0 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-tools.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-tools.lua
@@ -112,7 +112,7 @@ function scripts.tools.dirtoxml()
local root = environment.argument('root') or "."
local outputfile = environment.argument('output')
- local recurse = environment.argument('recurse')
+ local recurse = environment.argument('recurse') or false
local stripname = environment.argument('stripname')
local longname = environment.argument('longname')
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-update.lua b/Master/texmf-dist/scripts/context/lua/mtx-update.lua
index 750c7488692..52c72da6d4d 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-update.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-update.lua
@@ -20,7 +20,8 @@ local helpinfo = [[
--rsync=string rsync binary (rsync)
--texroot=string installation directory (not guessed for the moment)
--engine=string tex engine (luatex, pdftex, xetex)
---extras=string extra modules (can be list or 'all')
+--modules=string extra modules (can be list or 'all')
+--fonts=string additional fonts (can be list or 'all')
--goodies=string extra binaries (like scite and texworks)
--force instead of a dryrun, do the real thing
--update update minimal tree
@@ -31,13 +32,13 @@ local helpinfo = [[
local application = logs.application {
name = "mtx-update",
- banner = "ConTeXt Minimals Updater 0.22",
+ banner = "ConTeXt Minimals Updater 0.30",
helpinfo = helpinfo,
}
local report = application.report
-local format, concat, gmatch, gsub = string.format, table.concat, string.gmatch, string.gsub
+local format, concat, gmatch, gsub, find = string.format, table.concat, string.gmatch, string.gsub, string.find
scripts = scripts or { }
scripts.update = scripts.update or { }
@@ -60,7 +61,7 @@ scripts.update.texformats = {
"cont-ro",
"cont-uk",
"cont-pe",
- "cont-xp",
+ -- "cont-xp",
"mptopdf",
"plain"
}
@@ -92,7 +93,6 @@ scripts.update.base = {
{ "fonts/common/", "texmf" },
{ "fonts/other/", "texmf" }, -- not *really* needed, but helpful
{ "context/<version>/", "texmf-context" },
- { "context/img/", "texmf-context" },
{ "misc/setuptex/", "." },
{ "misc/web2c", "texmf" },
{ "bin/common/<platform>/", "texmf-<platform>" },
@@ -180,6 +180,9 @@ scripts.update.selfscripts = {
scripts.update.modules = {
}
+scripts.update.fonts = {
+}
+
function scripts.update.run(str)
-- important, otherwise formats fly to a weird place
-- (texlua sets luatex as the engine, we need to reset that or to fix texexec :)
@@ -211,7 +214,8 @@ function scripts.update.synchronize()
local bin = states.get("rsync.program") -- rsync
local url = states.get("rsync.server") -- contextgarden.net
local version = states.get("context.version") -- current (or beta)
- local extras = states.get("extras") -- extras (like modules)
+ local modules = states.get("modules") -- modules (third party)
+ local fonts = states.get("fonts") -- fonts (experimental or special)
local goodies = states.get("goodies") -- goodies (like editors)
local force = environment.argument("force")
@@ -229,6 +233,7 @@ function scripts.update.synchronize()
dir.mkdirs(format("%s/%s", texroot, "texmf-local"))
dir.mkdirs(format("%s/%s", texroot, "texmf-project"))
dir.mkdirs(format("%s/%s", texroot, "texmf-fonts"))
+ dir.mkdirs(format("%s/%s", texroot, "texmf-modules"))
end
if ok or not force then
@@ -291,20 +296,41 @@ function scripts.update.synchronize()
-- rsync://contextgarden.net/minimals/current/modules/
- if extras and type(extras) == "table" then
+ if modules and type(modules) == "table" then
-- fetch the list of available modules from rsync server
local available_modules = get_list_of_files_from_rsync({"modules/"})
-- hash of requested modules
- -- local h = table.tohash(extras:split(","))
+ -- local h = table.tohash(modules:split(","))
+ local asked = table.copy(modules)
+ asked.all = nil
for i=1,#available_modules do
local s = available_modules[i]
- -- if extras == "all" or h[s] then
- if extras.all or extras[s] then
- scripts.update.modules[#scripts.update.modules+1] = { format("modules/%s/",s), "texmf-context" }
+ if modules.all or modules[s] then
+ scripts.update.modules[#scripts.update.modules+1] = { format("modules/%s/",s), "texmf-modules" }
end
+ asked[s] = nil
+ end
+ if next(asked) then
+ report("skipping unknown modules: %s",table.concat(table.sortedkeys(asked),", "))
+ end
+ end
+
+ -- rsync://contextgarden.net/minimals/current/fonts/extra/
+
+ if fonts and type(fonts) == "table" then
+ local available_fonts = get_list_of_files_from_rsync({"fonts/extra/"})
+ local asked = table.copy(fonts)
+ asked.all = nil
+ for i=1,#available_fonts do
+ local s = available_fonts[i]
+ if fonts.all or fonts[s] then
+ scripts.update.fonts[#scripts.update.fonts+1] = { format("fonts/extra/%s/",s), "texmf" }
+ end
+ asked[s] = nil
+ end
+ if next(asked) then
+ report("skipping unknown fonts: %s",table.concat(table.sortedkeys(asked),", "))
end
- -- TODO: check if every module from the list has been added and issue warning otherwise
- -- one idea to do it: remove every value from h once added and then check if anything is left in h
end
local function add_collection(collection,platform)
@@ -318,7 +344,7 @@ function scripts.update.synchronize()
destination = gsub(destination,"\\","/")
archive = gsub(archive,"<version>",version)
if osplatform == "windows" or osplatform == "mswin" then
- destination = gsub(destination,"([a-zA-Z]):/", "/cygdrive/%1/")
+ destination = gsub(destination,"([a-zA-Z]):/", "/cygdrive/%1/") -- ^
end
individual[#individual+1] = { archive, destination }
end
@@ -332,6 +358,9 @@ function scripts.update.synchronize()
for platform, _ in next, platforms do
add_collection(scripts.update.modules,platform)
end
+ for platform, _ in next, platforms do
+ add_collection(scripts.update.fonts,platform)
+ end
for engine, _ in next, engines do
for platform, _ in next, platforms do
add_collection(scripts.update.engines[engine],platform)
@@ -372,7 +401,7 @@ function scripts.update.synchronize()
if not environment.argument("force") then
dryrunflags = "--dry-run"
end
- if (destination:find("texmf$") or destination:find("texmf%-context$")) and (not environment.argument("keep")) then
+ if (destination:find("texmf$") or destination:find("texmf%-context$") or destination:find("texmf%-modules$")) and (not environment.argument("keep")) then
deleteflags = states.get("rsync.flags.delete")
end
command = format("%s %s %s %s %s'%s' '%s'", bin, normalflags, deleteflags, dryrunflags, url, archives, destination)
@@ -417,7 +446,7 @@ function scripts.update.synchronize()
resolvers.load_tree(texroot) -- else we operate in the wrong tree
-- update filename database for pdftex/xetex
- scripts.update.run(format('mtxrun --tree="%s" --direct mktexlsr',texroot))
+ scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot))
-- update filename database for luatex
scripts.update.run(format('mtxrun --tree="%s" --generate',texroot))
@@ -446,7 +475,7 @@ function scripts.update.make()
resolvers.load_tree(texroot)
- scripts.update.run(format('mtxrun --tree="%s" --direct mktexlsr',texroot))
+ scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot))
scripts.update.run(format('mtxrun --tree="%s" --generate',texroot))
local askedformats = formats
@@ -479,8 +508,10 @@ function scripts.update.make()
if not force then
report("make, use --force to really make formats")
end
- scripts.update.run(format('mtxrun --tree="%s" --direct mktexlsr',texroot))
+
+ scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot)) -- needed for mpost
scripts.update.run(format('mtxrun --tree="%s" --generate',texroot))
+
report("make, done")
end
@@ -496,7 +527,7 @@ if scripts.savestate then
states.set("info.version",0.1) -- ok
states.set("info.count",(states.get("info.count") or 0) + 1,1,false) -- ok
- states.set("info.comment","this file contains the settings of the last 'mtxrun --script update ' run",false) -- ok
+ states.set("info.comment","this file contains the settings of the last 'mtxrun --script update' run",false) -- ok
states.set("info.date",os.date("!%Y-%m-%d %H:%M:%S")) -- ok
states.set("rsync.program", environment.argument("rsync"), "rsync", true) -- ok
@@ -513,18 +544,30 @@ if scripts.savestate then
for r in gmatch(environment.argument("repository") or "current","([^, ]+)") do
if valid[r] then states.set("repositories." .. r, true) end
end
+
local valid = scripts.update.engines
- for r in gmatch(environment.argument("engine") or "all","([^, ]+)") do
- if r == "all" then
- for k, v in next, valid do
- if k ~= "all" then
- states.set("engines." .. k, true)
+ local engine = environment.argument("engine") or ""
+ if engine == "" then
+ local e = states.get("engines")
+ if not e or not next(e) then
+ engine = "all"
+ end
+ end
+ if engine ~= "" then
+ for r in gmatch(engine,"([^, ]+)") do
+ if r == "all" then
+ for k, v in next, valid do
+ if k ~= "all" then
+ states.set("engines." .. k, true)
+ end
end
+ break
+ elseif valid[r] then
+ states.set("engines." .. r, true)
end
- elseif valid[r] then
- states.set("engines." .. r, true)
end
end
+
local valid = scripts.update.platforms
for r in gmatch(environment.argument("platform") or os.platform,"([^, ]+)") do
if valid[r] then states.set("platforms." .. r, true) end
@@ -543,8 +586,20 @@ if scripts.savestate then
states.set("formats.cont-nl", true)
states.set("formats.metafun", true)
- for r in gmatch(environment.argument("extras") or "","([^, ]+)") do
- states.set("extras." .. r, true)
+ for r in gmatch(environment.argument("extras") or "","([^, ]+)") do -- for old times sake
+ if r ~= "all" and not find(r,"^[a-z]%-") then
+ r = "t-" .. r
+ end
+ states.set("modules." .. r, true)
+ end
+ for r in gmatch(environment.argument("modules") or "","([^, ]+)") do
+ if r ~= "all" and not find(r,"^[a-z]%-") then
+ r = "t-" .. r
+ end
+ states.set("modules." .. r, true)
+ end
+ for r in gmatch(environment.argument("fonts") or "","([^, ]+)") do
+ states.set("fonts." .. r, true)
end
for r in gmatch(environment.argument("goodies") or "","([^, ]+)") do
states.set("goodies." .. r, true)
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-watch.lua b/Master/texmf-dist/scripts/context/lua/mtx-watch.lua
index 5bd0ad5f496..118d1a8154e 100644
--- a/Master/texmf-dist/scripts/context/lua/mtx-watch.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtx-watch.lua
@@ -30,6 +30,8 @@ scripts.watch = scripts.watch or { }
local format, concat, difftime, time = string.format, table.concat, os.difftime, os.time
local next, type = next, type
+local basename, dirname, joinname = file.basename, file.dirname, file.join
+local lfsdir, lfsattributes = lfs.dir, lfs.attributes
-- the machine/instance matches the server app we use
@@ -68,9 +70,10 @@ local function noset(t)
end
end
-local lfsdir, lfsattributes = lfs.dir, lfs.attributes
-local function glob(files,path)
+-- todo: split order (o-name.luj) and combine with atime to determine sort order.
+
+local function glob(files,path) -- some day: sort by name (order prefix) and atime
for name in lfsdir(path) do
if name:find("^%.") then
-- skip . and ..
@@ -86,7 +89,8 @@ local function glob(files,path)
glob(files,name)
end
elseif name:find(".%luj$") then
- files[name] = a.change or a.ctime or a.modification or a.mtime
+ -- files[name] = a.change or a.ctime or a.modification or a.mtime
+ files[#files+1] = { dirname(name), basename(name) }
end
end
end
@@ -94,6 +98,16 @@ end
local clock = os.gettimeofday or os.time -- we cannot trust os.clock on linux
+local function filenamesort(a,b)
+ local fa, da = a[1], a[2]
+ local fb, db = b[1], b[2]
+ if da == db then
+ return fa < fb
+ else
+ return da < db
+ end
+end
+
function scripts.watch.watch()
local delay = tonumber(environment.argument("delay") or 5) or 5
if delay == 0 then
@@ -120,8 +134,13 @@ function scripts.watch.watch()
lfs.chdir(path)
local files = { }
glob(files,path)
- table.sort(files) -- what gets sorted here, todo: by time
- for name, time in next, files do
+ table.sort(files,filenamesort)
+-- for name, time in next, files do
+ for i=1,#files do
+ local f = files[i]
+ local dirname = f[1]
+ local basename = f[2] -- we can use that later on
+ local name = joinname(dirname,basename)
--~ local ok, joblog = xpcall(function() return dofile(name) end, function() end )
local ok, joblog = pcall(dofile,name)
if ok and joblog then
diff --git a/Master/texmf-dist/scripts/context/lua/mtxrun.lua b/Master/texmf-dist/scripts/context/lua/mtxrun.lua
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/texmf-dist/scripts/context/lua/mtxrun.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtxrun.lua
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/texmf-dist/scripts/context/lua/mtxrun.rme b/Master/texmf-dist/scripts/context/lua/mtxrun.rme
deleted file mode 100644
index 9850e389d74..00000000000
--- a/Master/texmf-dist/scripts/context/lua/mtxrun.rme
+++ /dev/null
@@ -1,18 +0,0 @@
-On MSWindows the mtxrun.lua script is called with
-mtxrun.exe. On Unix you can either rename mtxrun.lua
-to mtxrun, or use a symlink.
-
-You can create additional stubs, like
-
-copy mtxrun.exe luatools.exe
-copy mtxrun.exe texexec.exe
-copy mtxrun.exe context.exe
-copy mtxrun.exe mtx-server.exe
-
-The mtxrun.exe program is rather dump and only
-intercepts mtxrun, luatools and texmfstart (for
-old times sake) and passes the buck to mtxrun.lua
-which happens to know enough of mkii to deal
-with kpse based lookups and therefore acts like
-texmfstart but when used with mkiv it behaves
-more clever and looks for more.
diff --git a/Master/texmf-dist/scripts/context/ruby/ctxtools.rb b/Master/texmf-dist/scripts/context/ruby/ctxtools.rb
index 339f3d4906a..f6493a3fcd3 100644
--- a/Master/texmf-dist/scripts/context/ruby/ctxtools.rb
+++ b/Master/texmf-dist/scripts/context/ruby/ctxtools.rb
@@ -606,12 +606,12 @@ end
#D structured as:
#D
#D \starttypen
-#D \startmodule[type=suffix]
+#D \startmoduledocumentation[type=suffix]
#D \startdocumentation
#D \stopdocumentation
#D \startdefinition
#D \stopdefinition
-#D \stopmodule
+#D \stopmoduledocumentation
#D \stoptypen
#D
#D Macro definitions specific to the documentation are not
@@ -661,7 +661,7 @@ class Commands
else
tex.rewind # seek(0)
end
- ted.puts("\\startmodule[type=#{filetype}]\n")
+ ted.puts("\\startmoduledocumentation[type=#{filetype}]\n")
while str = tex.gets do
if skippingbang then
skippingbang = false
@@ -737,7 +737,7 @@ class Commands
if indefinition then
ted.puts("\\stopdefinition\n")
end
- ted.puts("\\stopmodule\n")
+ ted.puts("\\stopmoduledocumentation\n")
ted.close
if nofdocuments == 0 && nofdefinitions == 0 then
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/pstopdf.exe b/Master/texmf-dist/scripts/context/stubs/mswin/metatex.exe
index 2d45f27494d..2d45f27494d 100755
--- a/Master/texmf-dist/scripts/context/stubs/mswin/pstopdf.exe
+++ b/Master/texmf-dist/scripts/context/stubs/mswin/metatex.exe
Binary files differ
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/rlxtools.exe b/Master/texmf-dist/scripts/context/stubs/mswin/mptopdf.exe
index 745eaf22464..2d45f27494d 100755
--- a/Master/texmf-dist/scripts/context/stubs/mswin/rlxtools.exe
+++ b/Master/texmf-dist/scripts/context/stubs/mswin/mptopdf.exe
Binary files differ
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dll b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dll
index 4116c5a24a6..4116c5a24a6 100755..100644
--- a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dll
+++ b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.dll
Binary files differ
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
index 7adcd3023a8..335c4fcb9e0 100755..100644
--- a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
+++ b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/ctxtools.exe b/Master/texmf-dist/scripts/context/stubs/mswin/mtxworks.exe
index 745eaf22464..2d45f27494d 100755
--- a/Master/texmf-dist/scripts/context/stubs/mswin/ctxtools.exe
+++ b/Master/texmf-dist/scripts/context/stubs/mswin/mtxworks.exe
Binary files differ
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/ctxtools b/Master/texmf-dist/scripts/context/stubs/unix/ctxtools
deleted file mode 100755
index 2e6bd4afaa0..00000000000
--- a/Master/texmf-dist/scripts/context/stubs/unix/ctxtools
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-mtxrun --script ctxtools "$@"
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/metatex b/Master/texmf-dist/scripts/context/stubs/unix/metatex
new file mode 100755
index 00000000000..f0c6b65d42f
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/stubs/unix/metatex
@@ -0,0 +1,2 @@
+#!/bin/sh
+mtxrun --script metatex "$@"
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/mptopdf b/Master/texmf-dist/scripts/context/stubs/unix/mptopdf
new file mode 100755
index 00000000000..1473337405a
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/stubs/unix/mptopdf
@@ -0,0 +1,2 @@
+#!/bin/sh
+mtxrun --script mptopdf "$@"
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/mtxrun b/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
index 7adcd3023a8..335c4fcb9e0 100755
--- a/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
+++ b/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
@@ -160,509 +160,6 @@ end -- of closure
do -- create closure to overcome 200 locals limit
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
-
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
-
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
-
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
-
-
-end -- of closure
-
-do -- create closure to overcome 200 locals limit
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -675,11 +172,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1022,6 +520,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1214,19 +714,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1571,6 +1072,730 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+
+
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
end -- of closure
@@ -1831,6 +2056,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- of closure
@@ -2061,7 +2291,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -2167,9 +2397,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -2400,6 +2630,39 @@ function os.timezone(delta)
end
end
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
+
end -- of closure
@@ -2499,10 +2762,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -2523,6 +2786,15 @@ function file.join(...)
end
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -2532,12 +2804,17 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
@@ -2594,7 +2871,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2690,10 +2967,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
+
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2828,12 +3137,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
+
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -2854,11 +3170,14 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+
-- todo: cache them
local rootletter = R("az","AZ")
@@ -3007,8 +3326,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -3056,13 +3373,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -3245,7 +3562,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -3277,7 +3594,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -3285,7 +3602,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -3313,10 +3630,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
@@ -3381,10 +3698,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
@@ -3545,7 +3858,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3573,7 +3886,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -3590,14 +3903,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -3612,17 +3925,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -3637,7 +3950,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -3706,15 +4019,67 @@ end
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
+
+
end -- of closure
do -- create closure to overcome 200 locals limit
@@ -3750,8 +4115,8 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
@@ -3771,9 +4136,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3789,14 +4155,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -3840,13 +4223,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -3854,17 +4243,56 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
+
end -- of closure
@@ -3886,8 +4314,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -3916,8 +4344,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -3946,13 +4374,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -3973,6 +4401,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -3990,6 +4419,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -3999,6 +4429,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -4008,6 +4439,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
@@ -4176,14 +4608,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
@@ -4210,9 +4657,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -4240,8 +4687,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -4322,9 +4773,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
@@ -4562,61 +5019,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -4638,6 +5089,7 @@ end
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -4645,11 +5097,30 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
+
end -- of closure
@@ -4668,7 +5139,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -4770,10 +5241,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -4847,7 +5318,7 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
@@ -4931,6 +5402,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -5167,6 +5642,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
@@ -5237,7 +5714,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -5252,6 +5729,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -5357,6 +5838,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -5416,6 +5901,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -5585,21 +6071,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -5681,6 +6204,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -5707,6 +6237,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -5772,6 +6303,11 @@ else
end
end
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
+
end -- of closure
@@ -6277,6 +6813,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -6301,10 +6841,11 @@ xml = xml or { }
local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -6417,9 +6958,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -6585,7 +7139,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -6596,6 +7150,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -6637,7 +7243,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -6658,34 +7264,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -6700,18 +7316,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -6761,7 +7384,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -6796,6 +7419,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -6803,17 +7428,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -6845,17 +7475,30 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -6893,7 +7536,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -6907,7 +7550,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -6915,16 +7558,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -6953,7 +7622,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -7032,18 +7701,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -7054,14 +7720,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -7077,7 +7743,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -7098,11 +7764,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -7137,7 +7803,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -7265,20 +7931,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -7287,28 +7966,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -7428,7 +8113,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
@@ -7620,8 +8305,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -7649,6 +8334,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -7940,6 +8626,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -7947,15 +8639,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -7979,11 +8667,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -8135,7 +8823,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -8164,10 +8855,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -8194,13 +8883,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -8364,7 +9053,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -8497,9 +9186,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -8508,7 +9197,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -8534,6 +9223,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
@@ -8856,10 +9562,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -9004,7 +9712,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -9031,18 +9739,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -9105,32 +9825,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
+ end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -9138,16 +9865,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -9346,6 +10080,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -9378,6 +10181,53 @@ xml.remap_tag = xml.remaptag obsolete.remap_tag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
+
end -- of closure
@@ -9391,15 +10241,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -9413,6 +10265,21 @@ local function all(collected)
return collected
end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -9429,34 +10296,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -9467,7 +10337,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -9485,108 +10355,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -9641,14 +10572,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -9656,6 +10587,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -9664,8 +10597,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
@@ -9719,7 +10652,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -9781,7 +10714,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
@@ -9954,7 +10887,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -9974,19 +10907,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -10043,12 +10963,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -10081,41 +10998,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -10140,8 +11072,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -10201,13 +11133,22 @@ end
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -10245,25 +11186,122 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
+ return files
+end
+
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
return files
end
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
end -- of closure
@@ -10361,12 +11399,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -10503,7 +11541,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
@@ -10589,6 +11627,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -10651,11 +11690,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -10746,7 +11781,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -10870,9 +11905,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10939,7 +11974,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
@@ -11112,7 +12147,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -11155,7 +12190,58 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
+
+
local unset_variable = "unset"
@@ -11177,7 +12263,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -11257,6 +12343,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -11348,7 +12435,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -11356,6 +12443,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -11370,7 +12465,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -11406,6 +12501,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -11495,11 +12603,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -11507,7 +12610,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -11551,6 +12654,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -11838,6 +12974,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -11897,9 +13034,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -11919,297 +13069,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
+ if #result > 0 then
+ return "qualified", result
+ end
end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
- end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
+ end
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
- end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
- end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
+ end
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
end
- if stamp then
- instance.found[stamp] = result
+ if #result > 0 then
+ return "onpath", result
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
-
-
-
-
-
-
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
+ end
+end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -12370,6 +13646,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -12383,6 +13663,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
@@ -12540,6 +13823,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -12578,7 +13863,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -12621,8 +13906,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -12637,7 +13923,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
@@ -12797,7 +14083,7 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
resolvers.registerfilehash(path,content,true)
end
@@ -13152,6 +14438,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
@@ -13419,11 +14717,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -13437,6 +14735,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
@@ -13596,8 +14896,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
@@ -13804,7 +15111,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -13812,11 +15125,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
@@ -13837,6 +15151,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -13867,10 +15182,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -13879,9 +15194,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
@@ -14168,8 +15483,8 @@ own = { } -- not local, might change
own.libs = { -- order can be made better
'l-string.lua',
- 'l-lpeg.lua',
'l-table.lua',
+ 'l-lpeg.lua',
'l-io.lua',
'l-number.lua',
'l-set.lua',
@@ -14240,7 +15555,7 @@ end
-- End of hack.
-local format, gsub, gmatch, match = string.format, string.gsub, string.gmatch, string.match
+local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find
local concat = table.concat
own.name = (environment and environment.ownname) or arg[0] or 'mtxrun.lua'
@@ -14362,7 +15677,7 @@ local helpinfo = [[
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--internal run script using built in libraries (same as --ctxlua)
---locate locate given filename
+--locate locate given filename in database (default) or system (--first --all --detail)
--autotree use texmf tree cf. env 'texmfstart_tree' or 'texmfstarttree'
--tree=pathtotree use given texmf tree (default file: 'setuptex.tmf')
@@ -14410,7 +15725,7 @@ local helpinfo = [[
local application = logs.application {
name = "mtxrun",
- banner = "ConTeXt TDS Runner Tool 1.30",
+ banner = "ConTeXt TDS Runner Tool 1.31",
helpinfo = helpinfo,
}
@@ -14455,12 +15770,12 @@ runners.registered = {
xmltools = { 'xmltools.rb', true },
-- luatools = { 'luatools.lua', true },
mtxtools = { 'mtxtools.rb', true },
- pdftrimwhite = { 'pdftrimwhite.pl', false }
+ pdftrimwhite = { 'pdftrimwhite.pl', false },
}
runners.launchers = {
windows = { },
- unix = { }
+ unix = { },
}
-- like runners.libpath("framework"): looks on script's subpath
@@ -14487,7 +15802,7 @@ function runners.prepare()
end
local touchname = environment.argument("iftouched")
if type(touchname) == "string" and touchname ~= "" then
- local oldname, newname = string.split(touchname, ",")
+ local oldname, newname = string.splitup(touchname, ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
if e_verbose then
@@ -14521,11 +15836,11 @@ function runners.execute_script(fullname,internal,nosplit)
if path ~= "" then
result = fullname
elseif name then
- name = name:gsub("^int[%a]*:",function()
+ name = gsub(name,"^int[%a]*:",function()
internal = true
return ""
end )
- name = name:gsub("^script:","")
+ name = gsub(name,"^script:","")
if suffix == "" and runners.registered[name] and runners.registered[name][1] then
name = runners.registered[name][1]
suffix = file.extname(name)
@@ -14555,13 +15870,15 @@ function runners.execute_script(fullname,internal,nosplit)
environment.ownscript = result
dofile(result)
else
- local quotedresult = result
- if string.match(result,' ') and not string.match(result,"^\".*\"$") then quotedresult = '"' .. result .. '"' end
local binary = runners.applications[file.extname(result)]
+ result = string.quoted(string.unquoted(result))
+ -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then
+ -- result = '"' .. result .. '"'
+ -- end
if binary and binary ~= "" then
- quotedresult = binary .. " " .. quotedresult
+ result = binary .. " " .. result
end
- local command = quotedresult .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
+ local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote)
if e_verbose then
report()
report("executing: %s",command)
@@ -14606,7 +15923,7 @@ function runners.execute_program(fullname)
local before, after = environment.splitarguments(fullname)
for k=1,#after do after[k] = resolvers.resolve(after[k]) end
environment.initializearguments(after)
- fullname = fullname:gsub("^bin:","")
+ fullname = gsub(fullname,"^bin:","")
local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "")
report()
report("executing: %s",command)
@@ -14667,10 +15984,24 @@ function runners.resolve_string(filename)
end
end
-function runners.locate_file(filename)
- -- differs from texmfstart where locate appends .com .exe .bat ... todo
+-- differs from texmfstart where locate appends .com .exe .bat ... todo
+
+function runners.locate_file(filename) -- was given file but only searches in tree
if filename and filename ~= "" then
- runners.report_location(resolvers.findgivenfile(filename))
+ if environment.argument("first") then
+ runners.report_location(resolvers.findfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findfile,filename)
+ elseif environment.argument("all") then
+ local result, status = resolvers.findfiles(filename)
+ if status and environment.argument("detail") then
+ runners.report_location(status)
+ else
+ runners.report_location(result)
+ end
+ else
+ runners.report_location(resolvers.findgivenfile(filename))
+ -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename)
+ end
end
end
@@ -14679,12 +16010,12 @@ function runners.locate_platform()
end
function runners.report_location(result)
- if e_verbose then
- reportline()
- if result and result ~= "" then
- report(result)
- else
- report("not found")
+ if type(result) == "table" then
+ for i=1,#result do
+ if i > 1 then
+ io.write("\n")
+ end
+ io.write(result[i])
end
else
io.write(result)
@@ -14742,8 +16073,8 @@ function resolvers.launch(str)
end
function runners.launch_file(filename)
- instance.allresults = true
trackers.enable("resolvers.locating")
+ local allresults = environment.arguments["all"]
local pattern = environment.arguments["pattern"]
if not pattern or pattern == "" then
pattern = filename
@@ -14751,15 +16082,15 @@ function runners.launch_file(filename)
if not pattern or pattern == "" then
report("provide name or --pattern=")
else
- local t = resolvers.findfiles(pattern)
+ local t = resolvers.findfiles(pattern,nil,allresults)
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern)
+ t = resolvers.findfiles("*/" .. pattern,nil,allresults)
end
if not t or #t == 0 then
- t = resolvers.findfiles("*/" .. pattern .. "*")
+ t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults)
end
if t and #t > 0 then
- if environment.arguments["all"] then
+ if allresults then
for _, v in pairs(t) do
report("launching %s", v)
resolvers.launch(v)
@@ -14774,6 +16105,11 @@ function runners.launch_file(filename)
end
end
+local mtxprefixes = {
+ { "^mtx%-", "mtx-" },
+ { "^mtx%-t%-", "mtx-t-" },
+}
+
function runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
@@ -14799,24 +16135,27 @@ function runners.find_mtx_script(filename)
return fullname
end
-- mtx- prefix checking
- local mtxprefix = (filename:find("^mtx%-") and "") or "mtx-"
- -- context namespace, mtx-<filename>
- fullname = mtxprefix .. filename
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename>s
- fullname = mtxprefix .. basename .. "s" .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
- end
- -- context namespace, mtx-<filename minus trailing s>
- fullname = mtxprefix .. basename:gsub("s$","") .. "." .. suffix
- fullname = found(fullname) or resolvers.findfile(fullname)
- if fullname and fullname ~= "" then
- return fullname
+ for i=1,#mtxprefixes do
+ local mtxprefix = mtxprefixes[i]
+ mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2]
+ -- context namespace, mtx-<filename>
+ fullname = mtxprefix .. filename
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = mtxprefix .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix
+ fullname = found(fullname) or resolvers.findfile(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
end
-- context namespace, just <filename>
fullname = resolvers.findfile(filename)
@@ -14963,9 +16302,11 @@ instance.lsrmode = environment.argument("lsr") or false
local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))]
-if environment.argument("usekpse") or environment.argument("forcekpse") or is_mkii_stub then
+local e_argument = environment.argument
+
+if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then
- resolvers.load_tree(environment.argument('tree'),true) -- force resolve of TEXMFCNF
+ resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF
os.setenv("engine","")
os.setenv("progname","")
@@ -14978,7 +16319,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
other = "other text files",
}
- local progname = environment.argument("progname") or 'context'
+ local progname = e_argument("progname") or 'context'
local function kpse_initialized()
texconfig.kpse_init = true
@@ -14993,7 +16334,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
local findfile = resolvers.findfile
local showpath = resolvers.showpath
- if environment.argument("forcekpse") then
+ if e_argument("forcekpse") then
function resolvers.findfile(name,kind)
return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or ""
@@ -15002,7 +16343,7 @@ if environment.argument("usekpse") or environment.argument("forcekpse") or is_mk
return (kpse_initialized():show_path(name)) or ""
end
- elseif environment.argument("usekpse") or is_mkii_stub then
+ elseif e_argument("usekpse") or is_mkii_stub then
resolvers.load()
@@ -15041,12 +16382,12 @@ else
end
end
- resolvers.load_tree(environment.argument('tree'))
+ resolvers.load_tree(e_argument('tree'),e_argument("resolve"))
end
-if environment.argument("selfmerge") then
+if e_argument("selfmerge") then
-- embed used libraries
@@ -15056,27 +16397,27 @@ if environment.argument("selfmerge") then
utilities.merger.selfmerge(own.name,own.libs,{ found })
end
-elseif environment.argument("selfclean") then
+elseif e_argument("selfclean") then
-- remove embedded libraries
runners.loadbase()
utilities.merger.selfclean(own.name)
-elseif environment.argument("selfupdate") then
+elseif e_argument("selfupdate") then
runners.loadbase()
trackers.enable("resolvers.locating")
resolvers.updatescript(own.name,"mtxrun")
-elseif environment.argument("ctxlua") or environment.argument("internal") then
+elseif e_argument("ctxlua") or e_argument("internal") then
-- run a script by loading it (using libs)
runners.loadbase()
ok = runners.execute_script(filename,true)
-elseif environment.argument("script") or environment.argument("scripts") then
+elseif e_argument("script") or e_argument("scripts") then
-- run a script by loading it (using libs), pass args
@@ -15087,109 +16428,110 @@ elseif environment.argument("script") or environment.argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
-elseif environment.argument("execute") then
+elseif e_argument("execute") then
-- execute script
runners.loadbase()
ok = runners.execute_script(filename)
-elseif environment.argument("direct") then
+elseif e_argument("direct") then
-- equals bin:
runners.loadbase()
ok = runners.execute_program(filename)
-elseif environment.argument("edit") then
+elseif e_argument("edit") then
-- edit file
runners.loadbase()
runners.edit_script(filename)
-elseif environment.argument("launch") then
+elseif e_argument("launch") then
runners.loadbase()
runners.launch_file(filename)
-elseif environment.argument("makestubs") then
+elseif e_argument("makestubs") then
-- make stubs (depricated)
runners.handle_stubs(true)
-elseif environment.argument("removestubs") then
+elseif e_argument("removestubs") then
-- remove stub (depricated)
runners.loadbase()
runners.handle_stubs(false)
-elseif environment.argument("resolve") then
+elseif e_argument("resolve") then
-- resolve string
runners.loadbase()
runners.resolve_string(filename)
-elseif environment.argument("locate") then
+elseif e_argument("locate") then
- -- locate file
+ -- locate file (only database)
runners.loadbase()
runners.locate_file(filename)
-elseif environment.argument("platform") or environment.argument("show-platform") then
+elseif e_argument("platform") or e_argument("show-platform") then
-- locate platform
runners.loadbase()
runners.locate_platform()
-elseif environment.argument("prefixes") then
+elseif e_argument("prefixes") then
runners.loadbase()
runners.prefixes()
-elseif environment.argument("timedrun") then
+elseif e_argument("timedrun") then
-- locate platform
runners.loadbase()
runners.timedrun(filename)
-elseif environment.argument("variables") or environment.argument("show-variables") or environment.argument("expansions") or environment.argument("show-expansions") then
+elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then
-- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename)
resolvers.load("nofiles")
- resolvers.listers.variables(environment.argument("pattern"))
+ resolvers.listers.variables(e_argument("pattern"))
-elseif environment.argument("configurations") or environment.argument("show-configurations") then
+elseif e_argument("configurations") or e_argument("show-configurations") then
-- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename)
resolvers.load("nofiles")
resolvers.listers.configurations()
-elseif environment.argument("find-file") then
+elseif e_argument("find-file") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename)
resolvers.load()
- local e_pattern = environment.argument("pattern")
- local e_format = environment.argument("format")
+ local e_all = e_argument("all")
+ local e_pattern = e_argument("pattern")
+ local e_format = e_argument("format")
+ local finder = e_all and resolvers.findfiles or resolvers.findfile
if not e_pattern then
runners.register_arguments(filename)
environment.initializearguments(environment.arguments_after)
- resolvers.dowithfilesandreport(resolvers.findfiles,environment.files,e_format)
+ resolvers.dowithfilesandreport(finder,environment.files,e_format)
elseif type(e_pattern) == "string" then
- instance.allresults = true -- brrrr
- resolvers.dowithfilesandreport(resolvers.findfiles,{ e_pattern }, e_format)
+ resolvers.dowithfilesandreport(finder,{ e_pattern },e_format)
end
-elseif environment.argument("find-path") then
+elseif e_argument("find-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename)
@@ -15201,7 +16543,7 @@ elseif environment.argument("find-path") then
print(path)
end
-elseif environment.argument("expand-braces") then
+elseif e_argument("expand-braces") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename)
@@ -15210,7 +16552,7 @@ elseif environment.argument("expand-braces") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
-elseif environment.argument("expand-path") then
+elseif e_argument("expand-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename)
@@ -15219,7 +16561,7 @@ elseif environment.argument("expand-path") then
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
-elseif environment.argument("expand-var") or environment.argument("expand-variable") then
+elseif e_argument("expand-var") or e_argument("expand-variable") then
-- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename)
@@ -15228,7 +16570,7 @@ elseif environment.argument("expand-var") or environment.argument("expand-variab
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
-elseif environment.argument("show-path") or environment.argument("path-value") then
+elseif e_argument("show-path") or e_argument("path-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename)
@@ -15237,7 +16579,7 @@ elseif environment.argument("show-path") or environment.argument("path-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
-elseif environment.argument("var-value") or environment.argument("show-value") then
+elseif e_argument("var-value") or e_argument("show-value") then
-- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename)
@@ -15246,28 +16588,36 @@ elseif environment.argument("var-value") or environment.argument("show-value") t
environment.initializearguments(environment.arguments_after)
resolvers.dowithfilesandreport(resolvers.variable,environment.files)
-elseif environment.argument("format-path") then
+elseif e_argument("format-path") then
-- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename)
resolvers.load()
report(caches.getwritablepath("format"))
-elseif environment.argument("pattern") then
+elseif e_argument("pattern") then
-- luatools
- runners.execute_ctx_script("mtx-base","--pattern='" .. environment.argument("pattern") .. "'",filename)
+ runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename)
-elseif environment.argument("generate") then
+elseif e_argument("generate") then
-- luatools
- instance.renewcache = true
- trackers.enable("resolvers.locating")
- resolvers.load()
+ if filename and filename ~= "" then
+ resolvers.load("nofiles")
+ trackers.enable("resolvers.locating")
+ resolvers.renew(filename)
+ else
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+ end
-elseif environment.argument("make") or environment.argument("ini") or environment.argument("compile") then
+ e_verbose = true
+
+elseif e_argument("make") or e_argument("ini") or e_argument("compile") then
-- luatools: runners.execute_ctx_script("mtx-base","--make",filename)
@@ -15275,29 +16625,33 @@ elseif environment.argument("make") or environment.argument("ini") or environmen
trackers.enable("resolvers.locating")
environment.make_format(filename)
-elseif environment.argument("run") then
+elseif e_argument("run") then
-- luatools
runners.execute_ctx_script("mtx-base","--run",filename)
-elseif environment.argument("fmt") then
+elseif e_argument("fmt") then
-- luatools
runners.execute_ctx_script("mtx-base","--fmt",filename)
-elseif environment.argument("help") and filename=='base' then
+elseif e_argument("help") and filename=='base' then
-- luatools
runners.execute_ctx_script("mtx-base","--help")
-elseif environment.argument("help") or filename=='help' or filename == "" then
+elseif e_argument("version") then
+
+ application.version()
+
+elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
-elseif filename:find("^bin:") then
+elseif find(filename,"^bin:") then
runners.loadbase()
ok = runners.execute_program(filename)
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/mtxworks b/Master/texmf-dist/scripts/context/stubs/unix/mtxworks
new file mode 100755
index 00000000000..ef8f230c3a3
--- /dev/null
+++ b/Master/texmf-dist/scripts/context/stubs/unix/mtxworks
@@ -0,0 +1,2 @@
+#!/bin/sh
+mtxrun --script texworks --start
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/pstopdf b/Master/texmf-dist/scripts/context/stubs/unix/pstopdf
deleted file mode 100755
index 5b38ed426cb..00000000000
--- a/Master/texmf-dist/scripts/context/stubs/unix/pstopdf
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-texmfstart pstopdf.rb "$@"
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/rlxtools b/Master/texmf-dist/scripts/context/stubs/unix/rlxtools
deleted file mode 100755
index 3c62a592c62..00000000000
--- a/Master/texmf-dist/scripts/context/stubs/unix/rlxtools
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-mtxrun --script rlxtools "$@"
diff --git a/Master/texmf-dist/tex/context/base/anch-bar.mkii b/Master/texmf-dist/tex/context/base/anch-bar.mkii
index d08573c0f60..39d5c7f77e7 100644
--- a/Master/texmf-dist/tex/context/base/anch-bar.mkii
+++ b/Master/texmf-dist/tex/context/base/anch-bar.mkii
@@ -5,7 +5,7 @@
%D subtitle=Margin Bars and alike,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/anch-bar.mkiv b/Master/texmf-dist/tex/context/base/anch-bar.mkiv
index 1013e76096f..9f9770fb6a3 100644
--- a/Master/texmf-dist/tex/context/base/anch-bar.mkiv
+++ b/Master/texmf-dist/tex/context/base/anch-bar.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Margin Bars and alike,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -53,81 +53,72 @@
%D \stopsidebar
%D \stoptyping
-\newcount\currentsidebar
-\newdimen\sidebardistance
+\installcorenamespace{sidebar}
-\unexpanded\def\setupsidebars
- {\dodoubleargument\dosetupsidebars}
+\installcommandhandler \??sidebar {sidebar} \??sidebar
-\def\dosetupsidebars[#1][#2]%
- {\ifsecondargument
- \getparameters[\??br#1][#2]%
- \else
- \getparameters[\??br][#1]%
- \fi}
+\newcount\c_anch_sidebars_n
+\newdimen\c_anch_sidebars_distance
% \setupMPvariables
-% [mpos:bar]
+% [mpos:sidebar]
% [linecolor=red,
% linewidth=2pt,
% distance=5pt]
-\setupsidebars
+\setupsidebar
[\c!rulethickness=2pt,
- \c!rulecolor=red,
+ \c!rulecolor=\s!black,
+ \c!alternative=0,
+ \c!topoffset=0pt,
+ \c!bottomoffset=0pt,
\c!distance=.5\bodyfontsize]
-\unexpanded\def\definesidebar
- {\dodoubleempty\dodefinesidebar}
-
-\def\dodefinesidebar[#1][#2]%
- {\copyparameters
- [\??br#1][\??br]
- [\c!rulethickness,\c!rulecolor,\c!distance]%
- \getparameters
- [\??br#1][#2]}
+\let\setupsidebars\setupsidebar
\unexpanded\def\startsidebar
- {\dosingleempty\dostartsidebar}
+ {\dosingleempty\anch_sidebars_start}
-\def\dostartsidebar[#1]%
+\def\anch_sidebars_start[#1]%
{\bgroup
+ \def\currentsidebar{#1}%
\dontleavehmode
- \checktextbackgrounds
- \global\advance\currentsidebar\plusone
- \doifelsenothing{#1}
- {\advance\sidebardistance\@@brdistance}
- {\doifelsevaluenothing{\??br#1\c!distance}
- {\advance\sidebardistance\@@brdistance}
- {\sidebardistance\getvalue{\??br#1\c!distance}}}%
+ \global\advance\c_anch_sidebars_n\plusone
+ \advance\c_anch_sidebars_distance\sidebarparameter\c!distance
\startpositionoverlay{text-1}%
- \expanded{\setMPpositiongraphicrange
- {b:side:\the\currentsidebar}%
- {e:side:\the\currentsidebar}%
- {mpos:bar}%
- {self=side:\the\currentsidebar,
- linewidth=\getvalue{\??br#1\c!rulethickness},
- linecolor=\getvalue{\??br#1\c!rulecolor},
- distance=\the\sidebardistance}}%
+ \normalexpanded{\setMPpositiongraphicrange % maybe expand in definition
+ {b:sidebar:\the\c_anch_sidebars_n}%
+ {e:sidebar:\the\c_anch_sidebars_n}%
+ {mpos:sidebar}%
+ {self=sidebar:\the\c_anch_sidebars_n,
+ linewidth=\sidebarparameter\c!rulethickness,
+ linecolor=\sidebarparameter\c!rulecolor,
+ alternative=\sidebarparameter\c!alternative,
+ topoffset=\sidebarparameter\c!topoffset,
+ bottomoffset=\sidebarparameter\c!bottomoffset,
+ distance=\the\c_anch_sidebars_distance}}%
\stoppositionoverlay
- \bpos{side:\the\currentsidebar}\ignorespaces}
-
-% \def\dostopsidebar#1%
-% {\removelastspace\tpos{side:#1}\carryoverpar\egroup}
+ \bpos{sidebar:\the\c_anch_sidebars_n}}
\unexpanded\def\stopsidebar
- {\removelastspace\tpos{side:\the\currentsidebar}\carryoverpar\egroup}
-
-\startMPpositionmethod{mpos:bar}
- \startMPpositiongraphic{mpos:bar}{linecolor,linewidth,distance}%
- position_anchor_bar (
- \MPp\MPbself, \MPp\MPeself,
- \MPy\MPbself, \MPy\MPeself,
- \MPh\MPbself, \MPd\MPeself,
- \MPvar{distance}, \MPvar{linewidth}, \MPvar{linecolor}
+ {\removelastspace
+ \epos{sidebar:\the\c_anch_sidebars_n}
+ \carryoverpar\egroup}
+
+%D Let's keep this nice and simple (okay, we could pass the 6 variables in
+%D one lua call).
+
+\startMPpositionmethod{mpos:sidebar}
+ \startMPpositiongraphic{mpos:sidebar}{linecolor,linewidth,distance,alternative}%
+ if unknown context_apos : input mp-apos.mpiv ; fi ;
+ anch_sidebars_draw (
+ \MPp\MPbself,\MPp\MPeself,\MPy\MPbself,\MPy\MPeself,\MPh\MPbself,\MPd\MPeself,
+ \MPx{\textanchor},\MPy{\textanchor},\MPw{\textanchor},\MPh{\textanchor},
+ \MPvar{alternative},\MPvar{distance},\MPvar{linewidth},\MPvar{linecolor},
+ \MPvar{topoffset}, \MPvar{bottomoffset}
) ;
\stopMPpositiongraphic
- \MPpositiongraphic{mpos:bar}{}%
+ \MPpositiongraphic{mpos:sidebar}{}%
\stopMPpositionmethod
%D We now reimplement the margin rules handler defined in
@@ -153,8 +144,7 @@
\definesidebar
[\v!margin]
- [\c!rulecolor=\s!black,
- \c!rulethickness=\@@karulethickness,
+ [\c!rulethickness=\@@karulethickness,
\c!distance=\dimexpr\leftmargindistance-\@@karulethickness/2\relax]
\definecomplexorsimple\startmarginrule
@@ -169,7 +159,7 @@
\else
\def\@@kadefaultwidth{#1}%
\let\stopmarginrule\dostopmarginrule
- \@EA\startsidebar\@EA[\@EA\v!margin\@EA]%
+ \normalexpanded{\startsidebar[\v!margin]}% why expanded
\fi}
\def\dostopmarginrule
diff --git a/Master/texmf-dist/tex/context/base/anch-bck.mkvi b/Master/texmf-dist/tex/context/base/anch-bck.mkvi
new file mode 100644
index 00000000000..8ec056468dd
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/anch-bck.mkvi
@@ -0,0 +1,534 @@
+%D \module
+%D [ file=anch-bck, % moved from anch-pgr (1999.08.01)
+%D version=2011.12.19,
+%D title=\CONTEXT\ Anchoring 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.
+
+\writestatus{loading}{ConTeXt Anchoring Macros / Backgrounds}
+
+%D This module is quite okay but at some point I might add methods
+%D that use attributes although not too much is to be expected,
+%D apart from better anchoring. In fact better anchoring can be
+%D done independent of that.
+
+\unprotect
+
+% we can flush 5 in one call (saved 4 lua calls) .. brrr wself .. will change
+
+\def\MPposset#1{\ctxcommand{MPposset("#1")}} % will go
+
+% This might be overloaded later on:
+
+% \defineoverlay[\v!text-2][\positionoverlay{\v!text-2}]
+% \defineoverlay[\v!text-1][\positionoverlay{\v!text-1}]
+% \defineoverlay[\v!text+1][\positionoverlay{\v!text+1}]
+% \defineoverlay[\v!text+2][\positionoverlay{\v!text+2}]
+
+% Paragraph positions:
+
+\newcount\c_anch_backgrounds_text_n
+
+\def\v_anch_backgrounds_text_current {tbg:0}
+\def\v_anch_backgrounds_anchor_current_b{b:\v_anch_backgrounds_text_current}
+\def\v_anch_backgrounds_anchor_current_e{e:\v_anch_backgrounds_text_current}
+
+\def\anch_backgrounds_text_initialize_next
+ {\global\advance\c_anch_backgrounds_text_n\plusone
+ \edef\v_anch_backgrounds_text_current{tbg:\number\c_anch_backgrounds_text_n}}
+
+% The first position can be used in the middle of a paragraph in which case we're
+% too late with initializing par positions. Therefore we check if positions are
+% used at all.
+%
+% tricky: we need to catch newly set! otherwise an old run can have positions
+
+\unexpanded\def\anch_backgrounds_text_initialize
+ {\ctxcommand{doifelsepositionsused()}\enableparpositions\donothing
+ \global\let\anch_backgrounds_text_initialize\relax}
+
+\appendtoks
+ \anch_backgrounds_text_initialize
+\to \everystarttext
+
+%D Some MP
+
+\newcount\MPparcounter
+
+\def\MPself {\MPvar{self}}
+\def\MPbself {b:\MPvar{self}}
+\def\MPeself {e:\MPvar{self}}
+\def\MPparanchor{p:\number\MPparcounter}
+
+% \carryoverpar is needed for left/right floats
+
+% \definetextbackground[more][state=start,backgroundcolor=red] % location=paragraph
+% \definetextbackground[test][state=start,backgroundcolor=green]
+%
+% \page \placefigure[left]{}{}
+%
+% \starttextbackground[test]
+% \readfile{ward}{}{}
+% \starttextbackground[more]
+% \readfile{ward}{}{}
+% \stoptextbackground
+% \readfile{ward}{}{}
+% \stoptextbackground
+%
+% \page \placefigure[right]{}{}
+%
+% \starttextbackground[test]
+% \readfile{ward}{}{}
+% \starttextbackground[more]
+% \readfile{ward}{}{}
+% \stoptextbackground
+% \readfile{ward}{}{}
+% \stoptextbackground
+
+\newcount\c_anch_backgrounds_text_level
+
+\installcorenamespace{textbackground}
+\installcorenamespace{textbackgroundlevel}
+
+\installcommandhandler \??textbackground {textbackground} \??textbackground
+
+\appendtoks
+ \setuevalue{\currenttextbackground}{\groupedcommand{\starttextbackground[\currenttextbackground]}{\stoptextbackground}}%
+ \setuevalue{\e!start\currenttextbackground}{\starttextbackground[\currenttextbackground]}%
+ \setuevalue{\e!stop \currenttextbackground}{\stoptextbackground}%
+% \doif{\textbackgroundparameter\c!state}\v!start\checkpositionoverlays
+\to \everydefinetextbackground
+
+% \appendtoks
+% \doif{\textbackgroundparameter\c!state}\v!start\checkpositionoverlays
+% \to \everysetuptextbackground
+
+\unexpanded\def\starttextbackground
+ {\begingroup
+ \advance\c_anch_backgrounds_text_level\plusone
+ \dodoubleempty\anch_backgrounds_text_start}
+
+\def\anch_backgrounds_text_start[#tag][#settings]%
+ {%\checkpositionoverlays
+ \def\currenttextbackground{#tag}%
+ \anch_backgrounds_text_initialize_next
+ \ifsecondargument
+ \setupcurrenttextbackground[#settings]%
+ \fi
+ \doifelse{\textbackgroundparameter\c!state}\v!start
+ \anch_backgrounds_text_preset_yes
+ \anch_backgrounds_text_preset_nop
+ \anch_backgrounds_text_start_indeed}
+
+% todo \backgroundvariable\c!variant
+
+\let\anch_backgrounds_text_start_indeed\relax
+\let\anch_backgrounds_text_stop_indeed \relax
+
+\setvalue{\??textbackgroundlevel\v!text}%
+ {\let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_txt
+ \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_txt}
+
+\setvalue{\??textbackgroundlevel\v!paragraph}%
+ {\ifnum\c_anch_backgrounds_text_level>\plusone
+ \let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_txt
+ \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_txt
+ \else
+ \let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_par
+ \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_par
+ \fi}
+
+\setvalue{\??textbackgroundlevel\v!none}%
+ {\anch_backgrounds_text_preset_nop}
+
+\def\anch_backgrounds_text_preset_nop
+ {\let\anch_backgrounds_text_start_indeed\relax
+ \let\anch_backgrounds_text_stop_indeed \relax}
+
+\def\anch_backgrounds_text_preset_yes
+ {\anch_backgrounds_text_preset_nop
+ \csname\??textbackgroundlevel\textbackgroundparameter\c!location\endcsname
+ \edef\m_anch_backgrounds_text_frame {\textbackgroundparameter\c!frame}%
+ \edef\m_anch_backgrounds_text_corner {\textbackgroundparameter\c!corner}%
+ \edef\m_anch_backgrounds_text_background{\textbackgroundparameter\c!background}%
+ \ifx\m_anch_backgrounds_text_frame\v!on
+ \ifx\m_anch_backgrounds_text_corner\v!round
+ \let\m_anch_backgrounds_text_frame\!!plustwo
+ \else
+ \let\m_anch_backgrounds_text_frame\!!plusone
+ \fi
+ \else
+ \let\m_anch_backgrounds_text_frame\!!zerocount
+ \fi
+ \ifx\m_anch_backgrounds_text_background\v!color
+ \let\m_anch_backgrounds_text_background\!!plusone
+ \else
+ \let\m_anch_backgrounds_text_background\!!zerocount
+ \fi
+ \startpositionoverlay{\textbackgroundoverlay{\textbackgroundparameter\c!level}}%
+ \anch_backgrounds_text_meta_graphic % gets expanded directly
+ \stoppositionoverlay}
+
+\def\anch_backgrounds_text_meta_graphic
+ {\normalexpanded
+ {\setMPpositiongraphicrange % needs to be optimized
+ {\v_anch_backgrounds_anchor_current_b}%
+ {\v_anch_backgrounds_anchor_current_e}%
+ {\textbackgroundparameter\c!method}%
+ {self=\v_anch_backgrounds_text_current,
+ mp=\textbackgroundparameter\c!mp,
+ gridtype=\textbackgroundparameter\c!alternative,
+ filltype=\m_anch_backgrounds_text_background,
+ linetype=\m_anch_backgrounds_text_frame,
+ dashtype=\textbackgroundparameter\c!dash,
+ gridcolor=\textbackgroundparameter\c!framecolor,
+ linecolor=\textbackgroundparameter\c!framecolor,
+ lineoffset=\textbackgroundparameter\c!frameoffset,
+ fillcolor=\textbackgroundparameter\c!backgroundcolor,
+ filloffset=\textbackgroundparameter\c!backgroundoffset,
+ gridwidth=\textbackgroundparameter\c!rulethickness,
+ gridshift=\textbackgroundparameter\c!voffset,
+ linewidth=\textbackgroundparameter\c!rulethickness,
+ lineradius=\textbackgroundparameter\c!radius}}}
+
+\unexpanded\def\stoptextbackground
+ {\anch_backgrounds_text_stop_indeed
+ \carryoverpar\endgroup} % why doesn't this work ?
+
+\unexpanded\def\starttextbackgroundmanual
+ {\begingroup
+ \usetextbackgroundstyleandcolor\c!style\c!color
+ \bpos\v_anch_backgrounds_text_current}
+
+\unexpanded\def\stoptextbackgroundmanual
+ {\epos\v_anch_backgrounds_text_current
+ \carryoverpar\endgroup}
+
+\def\anch_backgrounds_text_start_txt
+ {\ifvmode \dontleavehmode \fi
+ \begingroup
+ \usetextbackgroundstyleandcolor\c!style\c!color
+ \bpos\v_anch_backgrounds_text_current}
+
+\def\anch_backgrounds_text_stop_txt
+ {\epos\v_anch_backgrounds_text_current
+ \carryoverpar\endgroup}
+
+\newskip\textbackgroundskip
+
+\def\anch_backgrounds_text_start_par
+ {\endgraf % new
+ \textbackgroundparameter\c!before
+ \begingroup
+ \begingroup
+ \resetallattributes % \attribute\linenumberattribute \attributeunsetvalue
+ \noindent
+ \ifgridsnapping
+ \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!topoffset}%
+ \ifdim\textbackgroundskip>\zeropoint
+ \struttedbox{\hbox{\raise\textbackgroundskip\hbox{\bpos\v_anch_backgrounds_text_current}}}%
+ \else
+ \bpos\v_anch_backgrounds_text_current
+ \fi
+ \else
+ \bpos\v_anch_backgrounds_text_current
+ \fi
+ \endgraf % we need a vertical nobreak - 29/06/2004
+ \endgroup
+ \nobreak
+ \vskip-\lineheight
+ \nobreak
+ \ifgridsnapping \else
+ \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!topoffset}%
+ \ifdim\textbackgroundskip>\zeropoint
+ \kern\textbackgroundskip\nobreak
+ \fi
+ \fi
+ \dosetleftskipadaption{\textbackgroundparameter\c!leftoffset}%
+ \advance\leftskip\leftskipadaption
+ \dosetleftskipadaption{\textbackgroundparameter\c!rightoffset}%
+ \advance\rightskip\leftskipadaption
+ % new
+ \dosetraggedcommand{\textbackgroundparameter\c!align}%
+ \raggedcommand
+ %
+ \usetextbackgroundstyleandcolor\c!style\c!color
+ \nowhitespace
+ \nobreak % new per 23/04/2006 (else potential break when whitespace)
+ \seteffectivehsize
+ \doinhibitblank % \blank[\v!disable]% new
+ \par}
+
+\def\anch_backgrounds_text_stop_par
+ {\par
+ \removelastskip % new
+ \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!bottomoffset}%
+ \ifdim\lastskip>\zeropoint
+ \advance\textbackgroundskip-\lastskip
+ \fi
+ \ifgridsnapping \else \ifdim\textbackgroundskip>\zeropoint
+ \kern\textbackgroundskip\nobreak
+ \fi \fi
+ \nobreak
+ \vskip-\dimexpr\lineheight+\parskip\relax
+ \nobreak
+ \endgroup
+ \begingroup
+ \forgeteverypar % NOT REALLY NEEDED, SAVES HASH/MEM
+ \resetallattributes % \attribute\linenumberattribute \attributeunsetvalue
+ \nobreak \noindent \strut \hfill \kern\zeropoint
+ \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!bottomoffset}%
+ \ifgridsnapping % experimental, pascal (todo: topoffset in same way)
+ \ifdim\textbackgroundskip>\zeropoint
+ \struttedbox\plusone{\hbox{\lower\textbackgroundskip\hbox{\epos\v_anch_backgrounds_text_current}}}%
+ \else
+ \epos\v_anch_backgrounds_text_current
+ \fi
+ \else
+ \epos\v_anch_backgrounds_text_current
+ \fi
+ \endgraf
+ \carryoverpar\endgroup
+ \endgraf % new
+ \textbackgroundparameter\c!after}
+
+\unexpanded\def\checkpositionoverlays
+ {\ifproductionrun
+ \enabletextarearegistration
+ \enablehiddenbackground
+ \global\let\checkpositionoverlays\relax
+ \fi}
+
+\setuptextbackground
+ [\c!mp=mpos:region:draw,
+ \c!method=mpos:region,
+ \c!state=\v!start,
+ \c!location=\v!text,
+ \c!leftoffset=\!!zeropoint, % 1em,
+ \c!rightoffset=\textbackgroundparameter\c!leftoffset,
+ \c!topoffset=\!!zeropoint, % \v!medium,
+ \c!bottomoffset=\textbackgroundparameter\c!topoffset,
+ \c!level=-1,
+ \c!alternative=0,
+ \c!align=,
+ \c!dash=0, % to be internationalized
+ \c!background=\v!color,
+ \c!backgroundcolor=lightgray,
+ \c!backgroundoffset=\!!zeropoint,
+ \c!corner=\v!rectangular,
+ \c!radius=.5\bodyfontsize,
+ \c!voffset=\!!zeropoint,
+ \c!frame=\v!on,
+ \c!framecolor=blue,
+ \c!frameoffset=\!!zeropoint,
+ \c!rulethickness=\linewidth]
+
+%D The \METAPOST\ connection:
+
+% gridtype = 1 => baseline
+% gridtype = 2 => betweenline
+
+\setupMPvariables
+ [mpos:region]
+ [mp=mpos:region:unset,
+ gridtype=0,
+ linetype=1,
+ filltype=1,
+ dashtype=0, % 1 = dashed, 2 = dashed with background
+ gridcolor=red,
+ linecolor=blue,
+ fillcolor=lightgray,
+ filloffset=\!!zeropoint,
+ linewidth=\linewidth,
+ gridwidth=\linewidth,
+ gridshift=\!!zeropoint,
+ lineradius=.5\bodyfontsize,
+ lineoffset=\!!zeropoint,
+ dashtype=1]
+
+\startuseMPgraphic{mpos:region:setup}
+ if unknown context_abck : input mp-abck.mpiv ; fi ;
+ boxgridtype := \MPvar{gridtype} ;
+ boxlinetype := \MPvar{linetype} ;
+ boxfilltype := \MPvar{filltype} ;
+ boxdashtype := \MPvar{dashtype} ;
+ boxfilloffset := \MPvar{filloffset} ;
+ boxlinewidth := \MPvar{linewidth} ;
+ boxgridwidth := \MPvar{gridwidth} ;
+ boxgridshift := \MPvar{gridshift} ;
+ boxlineradius := \MPvar{lineradius} ;
+ boxlineoffset := \MPvar{lineoffset} ;
+ %
+ def boxgridoptions = withcolor \MPvar{gridcolor} enddef ;
+ def boxlineoptions = withcolor \MPvar{linecolor} enddef ;
+ def boxfilloptions = withcolor \MPvar{fillcolor} enddef ;
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:extra}
+ % user stuff
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:anchor}
+ setbounds currentpicture to multibox ;
+\stopuseMPgraphic
+
+% \startMPpositionmethod{mpos:region}
+% \startMPpositiongraphic{mpos:region}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset}
+% \includeMPgraphic{mpos:region:setup} ;
+% \includeMPgraphic{mpos:region:extra} ;
+% \MPgetmultipars{\MPvar{self}}{\MPanchorid} ;
+% \includeMPgraphic{\MPvar{mp}} ;
+% \includeMPgraphic{mpos:region:anchor} ;
+% \stopMPpositiongraphic
+% \MPpositiongraphic{mpos:region}{}%
+% \stopMPpositionmethod
+
+\startMPpositiongraphic{mpos:region}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset}
+ \includeMPgraphic{mpos:region:setup} ;
+ \includeMPgraphic{mpos:region:extra} ;
+ \MPgetmultipars{\MPvar{self}}{\MPanchorid} ;
+ \includeMPgraphic{\MPvar{mp}} ;
+ \includeMPgraphic{mpos:region:anchor} ;
+\stopMPpositiongraphic
+
+\startMPpositionmethod{mpos:region}
+ \MPpositiongraphic{mpos:region}{}%
+\stopMPpositionmethod
+
+\startuseMPgraphic{mpos:region:draw}
+ draw_multi_pars
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:show}
+ show_multi_pars
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:kind}
+ show_multi_kind
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:sideline}
+ draw_multi_side
+\stopuseMPgraphic
+
+\startuseMPgraphic{mpos:region:sideline:dashed}
+ draw_multi_side_path dashed evenly ;
+\stopuseMPgraphic
+
+%D As an example we define a grid background:
+
+\definetextbackground
+ [\v!grid]
+ [\c!state=\v!stop,
+ \c!location=\v!paragraph,
+ \c!frame=\v!off,
+ \c!framecolor=red,
+ \c!background=,
+ \c!alternative=1]
+
+\ifx\basegrid\undefined \else \letvalue\v!grid=\basegrid \fi
+
+%D Some examples (that might become modules anch-imp-whatever):
+
+\setupMPvariables
+ [mpos:encircle]
+ [fillcolor=lightgray,
+ filloffset=\!!zeropoint,
+ linecolor=blue,
+ lineoffset=5pt,
+ linewidth=1pt]
+
+\startMPpositiongraphic{mpos:encircle}{linecolor,fillcolor,linewidth,lineoffset}
+ if unknown context_apos : input mp-apos.mpiv ; fi ;
+ \MPgetposboxes{\MPvar{self}}{\MPanchorid}
+ if nofposboxes = 1 :
+ posboxes[1] := posboxes[1] enlarged \MPvar{lineoffset} cornered \MPvar{lineoffset} ;
+ fill posboxes[1] withcolor \MPvar{fillcolor} ;
+ draw posboxes[1] withpen pencircle scaled \MPvar{linewidth} withcolor \MPvar{linecolor} ;
+ fi ;
+\stopMPpositiongraphic
+
+\setupMPvariables
+ [mpos:connect]
+ [linecolor=red,
+ lineoffset=.25ex,
+ linewidth=1pt]
+
+\startMPpositiongraphic{mpos:connect}{linecolor,lineoffset,linewidth}
+ if unknown context_apos : input mp-apos.mpiv ; fi ;
+ boxlinewidth := \MPvar{linewidth} ;
+ boxlineoffset := \MPvar{lineoffset} ;
+ def boxlineoptions = withcolor \MPvar{linecolor} enddef ;
+ \MPgetposboxes{\MPvar{from},\MPvar{to}}{\MPanchorid}
+ connect_positions ;
+\stopMPpositiongraphic
+
+\protect \endinput
+
+\definetextbackground[underline] [location=text,alternative=1,background=,frame=off]
+\definetextbackground[overstrike] [location=text,alternative=2,background=,frame=off]
+\definetextbackground[exlines] [location=text,alternative=3,background=,frame=off]
+\definetextbackground[strikethrough][location=text,alternative=4,background=,frame=off]
+
+\definestartstop [underline]
+ [before={\starttextbackground[underline]},
+ after=\stoptextbackground]
+
+\definestartstop
+ [overstrike]
+ [before={\starttextbackground[overstrike]},
+ after=\stoptextbackground]
+
+\definestartstop
+ [exlines]
+ [before={\starttextbackground[exlines]},
+ after=\stoptextbackground]
+
+\definestartstop
+ [strikethrough]
+ [before={\starttextbackground[strikethrough]},
+ after=\stoptextbackground]
+
+\definetextbackground
+ [sideline]
+ [mp=mpos:region:sideline,
+ location=paragraph,
+ framecolor=red,
+ frameoffset=5mm]
+
+\definestartstop [sideline]
+ [before={\starttextbackground[sideline]},
+ after=\stoptextbackground]
+
+\starttext
+
+ \startunderline \input tufte \stopunderline \blank
+ \startoverstrike \input tufte \stopoverstrike \blank
+ \startexlines \input tufte \stopexlines \blank
+ \startstrikethrough \input tufte \stopstrikethrough \blank
+ \startsideline \input tufte \stopsideline \blank
+
+ \page
+
+ \startpositionoverlay{text-1}
+ \setMPpositiongraphic{connect-1-b}{mpos:connect}{from=connect-1-b,to=connect-1-e}
+ \setMPpositiongraphic{connect-1-e}{mpos:connect}{from=connect-1-b,to=connect-1-e}
+ \stoppositionoverlay
+
+ \startpositionoverlay{text-1}
+ \setMPpositiongraphic{encircle-1}{mpos:encircle}{self=encircle-1}
+ \stoppositionoverlay
+
+ test \hpos{connect-1-b}{START}
+ \dorecurse{10}{\input ward}
+ \hpos{encircle-1}{\strut HERE}
+ \dorecurse{10}{\input ward}
+ \hpos{connect-1-e}{STOP} test
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/anch-pgr.lua b/Master/texmf-dist/tex/context/base/anch-pgr.lua
new file mode 100644
index 00000000000..bf4dcbe0287
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/anch-pgr.lua
@@ -0,0 +1,671 @@
+if not modules then modules = { } end modules ['anch-pgr'] = {
+ version = 1.001,
+ comment = "companion to anch-pgr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: we need to clean up lists (of previous pages)
+
+local format = string.format
+local abs = math.abs
+local concat, sort = table.concat, table.sort
+local splitter = lpeg.splitat(":")
+local lpegmatch = lpeg.match
+
+local jobpositions = job.positions
+
+local report_graphics = logs.reporter("graphics")
+
+local function point(n)
+ return format("%.5fpt",n/65536)
+end
+
+local function pair(x,y)
+ return format("(%.5fpt,%.5fpt)",x/65536,y/65536)
+end
+
+local function path(t)
+ return concat(t,"--") .. "--cycle"
+end
+
+local function regionarea(r)
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ return {
+ pair(rx, rh - ry),
+ pair(rw, rh - ry),
+ pair(rw, rd - ry),
+ pair(rx, rd - ry),
+ }
+end
+
+-- we can use a 'local t, n' and reuse the table
+
+local eps = 2
+
+local function add(t,x,y,last)
+ local n = #t
+ if n == 0 then
+ t[n+1] = { x, y }
+ elseif n == 1 then
+ local tn = t[1]
+ if abs(tn[1]-x) <= eps or abs(tn[2]-y) <= eps then
+ t[n+1] = { x, y }
+ end
+ else
+ local tm = t[n-1]
+ local tn = t[n]
+ local lx = tn[1]
+ local ly = tn[2]
+ if abs(lx-tm[1]) <= eps and abs(lx-x) <= eps then
+ if abs(ly-y) > eps then
+ tn[2] = y
+ end
+ elseif abs(ly-tm[2]) <= eps and abs(ly-y) <= eps then
+ if abs(lx-x) > eps then
+ tn[1] = x
+ end
+ elseif not last then
+ t[n+1] = { x, y }
+ end
+ end
+end
+
+local function finish(t)
+ local n = #t
+ if n > 1 then
+ local first = t[1]
+ local last = t[n]
+ if abs(first[1]-last[1]) <= eps and abs(first[2]-last[2]) <= eps then
+ t[n] = nil
+ end
+ end
+end
+
+local function clip(t,ytop,ybot)
+ local first, last = 1, #t
+ for i=first,last do
+ local y = t[i][2]
+ if ytop < y then
+ first = i
+ end
+ if ybot > y then
+ last = i
+ break
+ end
+ end
+ local lp = { }
+ lp[#lp+1] = { t[first][1], ytop }
+ for i=first+1,last-1 do
+ lp[#lp+1] = { t[i][1], t[i][2] }
+ end
+ lp[#lp+1] = { t[last][1], ybot }
+ return lp
+end
+
+-- todo: mark regions and free paragraphs in collected
+
+local function shapes(r,rx,ry,rw,rh,rd,lytop,lybot,rytop,rybot)
+ -- we assume that we only hang per page and not cross pages
+ -- which makes sense as hanging is only uses in special cases
+ --
+ -- we can remove data as soon as a page is done so we could
+ -- remember per page and discard areas after each shipout
+ local leftshape, rightshape
+-- leftshape = r.leftshape
+-- rightshape = r.rightshape
+-- if not leftshape then
+ leftshape = { { rx, rh } }
+ rightshape = { { rw, rh } }
+ local paragraphs = r.paragraphs
+ local extending = false
+ if paragraphs then
+ for i=1,#paragraphs do
+ local p = paragraphs[i]
+ local ha = p.ha
+ if ha and ha ~= 0 then
+ local py = p.y
+ local ph = p.h
+ local pd = p.d
+ local hi = p.hi
+ local hang = ha * (ph + pd)
+ local py_ph = py + ph
+ -- ha < 0 hi < 0 : right top
+ -- ha < 0 hi > 0 : left top
+ if ha < 0 then
+ if hi < 0 then -- right
+ add(rightshape,rw , py_ph)
+ add(rightshape,rw + hi, py_ph)
+ add(rightshape,rw + hi, py_ph + hang)
+ add(rightshape,rw , py_ph + hang)
+ else
+ -- left
+ add(leftshape,rx, py_ph)
+ add(leftshape,rx + hi, py_ph)
+ add(leftshape,rx + hi, py_ph + hang)
+ add(leftshape,rx, py_ph + hang)
+ end
+ end
+extending = false
+ else -- we need to clip to the next par
+ local ps = p.ps
+ if ps then
+ local py = p.y
+ local ph = p.h
+ local pd = p.d
+ local step = ph + pd
+ local size = #ps * step
+ local py_ph = py + ph
+ add(leftshape,rx,py_ph)
+ add(rightshape,rw,py_ph)
+ for i=1,#ps do
+ local p = ps[i]
+ local l = p[1]
+ local w = p[2]
+ add(leftshape,rx + l, py_ph)
+ add(rightshape,rx + l + w, py_ph)
+ py_ph = py_ph - step
+ add(leftshape,rx + l, py_ph)
+ add(rightshape,rx + l + w, py_ph)
+ end
+ extending = true
+-- add(left,rx,py_ph)
+-- add(right,rw,py_ph)
+ else
+ if extending then
+ local py = p.y
+ local ph = p.h
+ local pd = p.d
+ local py_ph = py + ph
+ local py_pd = py - pd
+ add(leftshape,leftshape[#leftshape][1],py_ph)
+ add(rightshape,rightshape[#rightshape][1],py_ph)
+ add(leftshape,rx,py_ph)
+ add(rightshape,rw,py_ph)
+extending = false
+ end
+ end
+ end
+ end
+ end
+ -- we can have a simple variant when no paragraphs
+ if extending then
+ -- not ok
+ leftshape[#leftshape][2] = rd
+ rightshape[#rightshape][2] = rw
+ else
+ add(leftshape,rx,rd)
+ add(rightshape,rw,rd)
+ end
+-- r.leftshape = leftshape
+-- r.rightshape = rightshape
+-- end
+ return clip(leftshape,lytop,lybot), clip(rightshape,rytop,rybot)
+end
+
+local function singlepart(b,e,r,left,right)
+ local bx, by = b.x, b.y
+ local ex, ey = e.x, e.y
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ if left then
+ rx = rx + left
+ rw = rw - right
+ end
+ local bh = by + b.h
+ local bd = by - b.d
+ local eh = ey + e.h
+ local ed = ey - e.d
+ if ex == rx then
+ -- We probably have a strut at the next line so we force a width
+ -- although of course it is better to move up. But as we have whitespace
+ -- (at least visually) injected then it's best to stress the issue.
+ ex = rw
+ end
+ local area
+ if by == ey then
+ area = {
+ pair(bx,bh-ry),
+ pair(ex,eh-ry),
+ pair(ex,ed-ry),
+ pair(bx,bd-ry),
+ }
+ else
+ area = { }
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,ed,bh,eh)
+ add(area,bx,bh-ry)
+ for i=1,#rightshapes do
+ local ri = rightshapes[i]
+ add(area,ri[1],ri[2]-ry)
+ end
+ add(area,ex,eh-ry)
+ add(area,ex,ed-ry)
+ for i=#leftshapes,1,-1 do
+ local li = leftshapes[i]
+ add(area,li[1],li[2]-ry)
+ end
+ add(area,bx,bd-ry)
+ add(area,bx,bh-ry,true) -- finish last straight line (but no add as we cycle)
+ finish(area)
+ for i=1,#area do
+ local a = area[i]
+ area[i] = pair(a[1],a[2])
+ end
+ end
+ return {
+ location = "single",
+ region = r,
+ area = area,
+ }
+end
+
+local function firstpart(b,r,left,right)
+ local bx, by = b.x, b.y
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ if left then
+ rx = rx + left
+ rw = rw - right
+ end
+ local bh = by + b.h
+ local bd = by - b.d
+ local area = { }
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,bd,rd,bh,rd)
+ add(area,bx,bh-ry)
+ for i=1,#rightshapes do
+ local ri = rightshapes[i]
+ add(area,ri[1],ri[2]-ry)
+ end
+ for i=#leftshapes,1,-1 do
+ local li = leftshapes[i]
+ add(area,li[1],li[2]-ry)
+ end
+ add(area,bx,bd-ry)
+ add(area,bx,bh-ry,true) -- finish last straight line (but no add as we cycle)
+ finish(area)
+ for i=1,#area do
+ local a = area[i]
+ area[i] = pair(a[1],a[2])
+ end
+ return {
+ location = "first",
+ region = r,
+ area = area,
+ }
+end
+
+local function middlepart(r,left,right)
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ if left then
+ rx = rx + left
+ rw = rw - right
+ end
+ local area = { }
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,rd,rh,rd)
+ for i=#leftshapes,1,-1 do
+ local li = leftshapes[i]
+ add(area,li[1],li[2]-ry)
+ end
+ for i=1,#rightshapes do
+ local ri = rightshapes[i]
+ add(area,ri[1],ri[2]-ry)
+ end
+ finish(area)
+ for i=1,#area do
+ local a = area[i]
+ area[i] = pair(a[1],a[2])
+ end
+ return {
+ location = "middle",
+ region = r,
+ area = area,
+ }
+end
+
+local function lastpart(e,r,left,right)
+ local ex, ey = e.x, e.y
+ local rx, ry = r.x, r.y
+ local rw = rx + r.w
+ local rh = ry + r.h
+ local rd = ry - r.d
+ if left then
+ rx = rx + left
+ rw = rw - right
+ end
+ local eh = ey + e.h
+ local ed = ey - e.d
+ local area = { }
+ -- two cases: till end and halfway e line
+ local leftshapes, rightshapes = shapes(r,rx,ry,rw,rh,rd,rh,ed,rh,eh)
+ for i=1,#rightshapes do
+ local ri = rightshapes[i]
+ add(area,ri[1],ri[2]-ry)
+ end
+ add(area,ex,eh-ry)
+ add(area,ex,ed-ry)
+ for i=#leftshapes,1,-1 do
+ local li = leftshapes[i]
+ add(area,li[1],li[2]-ry)
+ end
+ finish(area)
+ for i=1,#area do
+ local a = area[i]
+ area[i] = pair(a[1],a[2])
+ end
+ return {
+ location = "last",
+ region = r,
+ area = area,
+ }
+end
+
+graphics = graphics or { }
+local backgrounds = { }
+
+graphics.backgrounds = backgrounds
+
+local function calculatemultipar(tag)
+ local collected = jobpositions.collected
+ local b = collected[format("b:%s",tag)]
+ local e = collected[format("e:%s",tag)]
+ if not b or not e then
+ report_graphics("invalid tag '%s'",tag)
+ return { }
+ end
+ local br = b.r
+ local er = e.r
+ if not br or not er then
+ report_graphics("invalid region for '%s'",tag)
+ return { }
+ end
+ local btag, bindex = lpegmatch(splitter,br)
+ local etag, eindex = lpegmatch(splitter,er)
+ if not bindex or not eindex or btag ~= etag then
+ report_graphics("invalid indices for '%s'",tag)
+ return { }
+ end
+ local bindex = tonumber(bindex)
+ local eindex = tonumber(eindex)
+ -- Here we compensate for columns (in tables): a table can have a set of column
+ -- entries and these are shared. We compensate left/right based on the columns
+ -- x and w but need to take the region into acount where the specification was
+ -- flushed and not the begin pos's region, because otherwise we get the wrong
+ -- compensation for assymetrical doublesided layouts.
+ local left = 0
+ local right = 0
+ local rc = b.c
+ if rc then
+ rc = collected[rc]
+ if rc then
+ local tb = collected[rc.r]
+ if tb then
+ left = -(tb.x - rc.x)
+ right = (tb.w - rc.w - left) -- tb.x - rc.x
+ end
+ end
+ end
+ -- Obeying intermediate changes of left/rightskip makes no sense as it will
+ -- look bad, so we only look at the begin situation.
+ --
+ local bn = b.n
+ if bn then
+ local bp = collected[format("p:%s",bn)]
+ if bp then
+ left = left + bp.ls
+ right = right + bp.rs
+ end
+ end
+ --
+ if bindex == eindex then
+ return {
+ list = { [b.p] = { singlepart(b,e,collected[br],left,right) } },
+ bpos = b,
+ epos = e,
+ }
+ else
+ local list = {
+ [b.p] = { firstpart(b,collected[br],left,right) },
+ }
+ for i=bindex+1,eindex-1 do
+ br = format("%s:%s",btag,i)
+ local r = collected[br]
+ if not r then
+ report_graphics("invalid middle for '%s'",br)
+ else
+ local p = r.p
+ local pp = list[p]
+ if pp then
+ pp[#pp+1] = middlepart(r,left,right)
+ else
+ list[p] = { middlepart(r,left,right) }
+ end
+ end
+ end
+ local p = e.p
+ local pp = list[p]
+ if pp then
+ pp[#pp+1] = lastpart(e,collected[er],left,right)
+ else
+ list[p] = { lastpart(e,collected[er],left,right) }
+ end
+ return {
+ list = list,
+ bpos = b,
+ epos = e,
+ }
+ end
+end
+
+-- local pending = { } -- needs gc
+--
+-- local function register(data,n,anchor)
+-- local pa = pending[anchor]
+-- if not pa then
+-- pa = { }
+-- pending[anchor] = pa
+-- end
+-- for page, pagedata in next, data do
+-- local pap = pa[page]
+-- if pap then
+-- pap[#pap+1] = n
+-- else
+-- pa[page] = { n }
+-- end
+-- end
+-- end
+--
+-- function backgrounds.registered(anchor,page)
+-- local pa = pending[anchor]
+-- if pa then
+-- concat(pa,",")
+-- else
+-- return ""
+-- end
+-- end
+
+local pbg = { } -- will move to pending
+
+function backgrounds.calculatemultipar(n)
+ if not pbg[n] then
+ pbg[n] = calculatemultipar("pbg",n) or { }
+ end
+end
+
+local multilocs = {
+ single = 1, -- maybe 0
+ first = 1,
+ middle = 2,
+ last = 3,
+}
+
+-- if unknown context_abck : input mp-abck.mpiv ; fi ;
+
+local template_a = [[
+path multiregs[], multipars[], multibox ;
+string multikind[] ;
+numeric multilocs[], nofmultipars ;
+nofmultipars := %s ;
+multibox := unitsquare xyscaled %s ;
+numeric par_strut_height, par_strut_depth, par_line_height ;
+par_strut_height := %s ;
+par_strut_depth := %s ;
+par_line_height := %s ;
+]]
+
+local template_b = [[
+multilocs[%s] := %s ;
+multikind[%s] := "%s" ;
+multipars[%s] := (%s) shifted - %s ;
+]]
+
+local template_c = [[
+multiregs[%s] := (%s) shifted - %s ;
+]]
+
+local template_d = [[
+setbounds currentpicture to multibox ;
+]]
+
+function backgrounds.fetchmultipar(n,anchor,page)
+ local data = pbg[n]
+ if not data then
+ data = calculatemultipar(n)
+ pbg[n] = data -- can be replaced by register
+ -- register(data.list,n,anchor)
+ end
+ if data then
+ local list = data.list
+ if list then
+ local pagedata = list[page]
+ if pagedata then
+ local nofmultipars = #pagedata
+ -- report_graphics("fetching '%s' at page %s using anchor '%s' containing %s multipars",n,page,anchor,nofmultipars)
+ local a = jobpositions.collected[anchor]
+ if not a then
+ report_graphics("missing anchor '%s'",anchor)
+ else
+ local trace = false
+ local x, y, w, h, d = a.x, a.y, a.w, a.h, a.d
+ local bpos = data.bpos
+ local bh, bd = bpos.h, bpos.d
+ local result = { format(template_a,nofmultipars,pair(w,h+d),point(bh),point(bd),point(bh+bd)) }
+ for i=1,nofmultipars do
+ local region = pagedata[i]
+ result[#result+1] = format(template_b,
+ i, multilocs[region.location],
+ i, region.location,
+ i, path(region.area), pair(x,y-region.region.y))
+ if trace then
+ result[#result+1] = format(template_c,
+ i, path(regionarea(region.region)), offset)
+ end
+ end
+ data[page] = nil
+ result[#result+1] = template_d
+ result = concat(result,"\n")
+ return result
+ end
+ end
+ end
+ end
+ return format(template_a,0,"origin",0,0,0)
+end
+
+backgrounds.point = point
+backgrounds.pair = pair
+backgrounds.path = path
+
+function commands.fetchmultipar(n,anchor,page)
+ context(backgrounds.fetchmultipar(n,anchor,page))
+end
+
+local template_a = [[
+path posboxes[], posregions[] ;
+numeric pospages[] ;
+numeric nofposboxes ;
+nofposboxes := %s ;
+%s ;
+]]
+
+local template_b = [[
+pospages[%s] := %s ;
+posboxes[%s] := %s--%s--%s--%s--cycle ;
+posregions[%s] := %s--%s--%s--%s--cycle ;
+]]
+
+function commands.fetchposboxes(tags,anchor,page) -- no caching (yet) / todo: anchor, page
+ local collected = jobpositions.collected
+ if type(tags) == "string" then
+ tags = utilities.parsers.settings_to_array(tags)
+ end
+ local list, nofboxes = { }, 0
+ for i=1,#tags do
+ local tag= tags[i]
+ local c = collected[tag]
+ if c then
+ local r = c.r
+ if r then
+ r = collected[r]
+ if r then
+ local rx, ry, rw, rh, rd = r.x, r.y, r.w, r.h, r.d
+ local cx = c.x - rx
+ local cy = c.y - ry
+ local cw = cx + c.w
+ local ch = cy + c.h
+ local cd = cy - c.d
+ nofboxes = nofboxes + 1
+ list[nofboxes] = format(template_b,
+ nofboxes,c.p,
+ nofboxes,pair(cx,ch),pair(cw,ch),pair(cw,cd),pair(cx,cd),
+ nofboxes,pair(0,rh),pair(rw,rh),pair(rw,rd),pair(0,rd)
+ )
+ end
+ end
+ else
+ print("\n missing",tag)
+ end
+ end
+ -- print(format(template_a,nofboxes,concat(list)))
+ context(template_a,nofboxes,concat(list))
+end
+
+local doifelse = commands.doifelse
+
+function commands.doifelsemultipar(n,page)
+ local data = pbg[n]
+ if not data then
+ data = calculatemultipar(n)
+ pbg[n] = data
+ end
+ if page then
+ doifelse(data and data[page] and true)
+ else
+ doifelse(data and next(data) and true)
+ end
+end
+
+function commands.doifelserangeonpage(first,last,page)
+ local collected = jobpositions.collected
+ local f = collected[first]
+ if not f then
+ doifelse(false)
+ return
+ end
+ local l = collected[last]
+ if not l then
+ doifelse(false)
+ return
+ end
+ doifelse(page >= f.p and page <= l.p)
+end
diff --git a/Master/texmf-dist/tex/context/base/anch-pgr.mkii b/Master/texmf-dist/tex/context/base/anch-pgr.mkii
index cc7ae77f4c5..4ceea844c1f 100644
--- a/Master/texmf-dist/tex/context/base/anch-pgr.mkii
+++ b/Master/texmf-dist/tex/context/base/anch-pgr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Positioning Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -456,13 +456,6 @@
\defineoverlay[\v!text+1][\positionoverlay{\v!text+1}]
\defineoverlay[\v!text+2][\positionoverlay{\v!text+2}]
-%D The auxiliary \METAPOST\ macros are defined by default,
-%D by saying:
-
-\startMPextensions
- if unknown context_core : input mp-core.mp ; fi ;
-\stopMPextensions
-
%D Some of these macros are pretty clever but too complicated
%D to be nice. When things are kind of stable I'll clean up
%D this mess.
diff --git a/Master/texmf-dist/tex/context/base/anch-pgr.mkiv b/Master/texmf-dist/tex/context/base/anch-pgr.mkiv
index afa88193384..a417d26e3eb 100644
--- a/Master/texmf-dist/tex/context/base/anch-pgr.mkiv
+++ b/Master/texmf-dist/tex/context/base/anch-pgr.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Positioning Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -14,86 +14,159 @@
\writestatus{loading}{ConTeXt Anchoring Macros / Grapics}
%D Before we come to graphics support, we have to make sure of
-%D the reference point on the page. The next macro does so and
-%D is hooked into the page building routine.
+%D the reference point on the page. The next macros do so and
+%D are hooked into the page building routine.
-%D I will speed up this module when I have a proper torture
-%D test file.
+\registerctxluafile{anch-pgr}{1.001}
\unprotect
-% in the future, the depth of tail will reflect page depth
+%D A few more low level macros take care of defining and recalling
+%D actions. Actions are saved globally! The lists can become quite
+%D long because there can be lots of parameters passed on so we
+%D clean up the list afterwards.
-\ifx\textheight\undefined \def\textheight{\vsize} \fi
+\newtoks\everypositionaction
+\newtoks\everyinsertpositionaction
+\newtoks\everycleanpositionaction
-%D The next macros so some housekeeping.
+\installcorenamespace{positionaction}
+\installcorenamespace{positioncleanup}
-\def\pageanchor{page:0} % for the moment only one pagesize
-\def\textanchor{text:\the\realpageno}
-\def\headanchor{head:\the\realpageno} % virtual position
-\def\tailanchor{tail:\the\realpageno} % virtual position
+\unexpanded\def\dosetpositionaction#1%
+ {\expandafter\gdef\csname\??positionaction#1\endcsname} % nicely gobbles spaces
-%D Anchors:
+\unexpanded\def\doifpositionaction#1%
+ {\ifcsname\??positionaction#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
-\def\dopresetpositionanchors % also mkii
- {\bgroup
- \!!dimena\ifdim\topskip>\strutht\topskip\else\strutht\fi
- \!!dimenb\dimexpr\MPy\textanchor+\MPh\textanchor-\!!dimena\relax
- \!!dimenc\dimexpr\MPy\textanchor+\strutdp\relax
- \!!dimend\MPx\textanchor
- \!!dimene\MPw\textanchor
- \replacepospxywhd\headanchor\realfolio\!!dimend\!!dimenb\!!dimene\!!dimena\strutdp
- \replacepospxywhd\tailanchor\realfolio\!!dimend\!!dimenc\!!dimene\strutht \strutdp
- \egroup}
+\unexpanded\def\doifpositionactionelse#1%
+ {\ifcsname\??positionaction#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
-\def\presetpositionanchors% compatibility hack (still needed?)
- {\ifpositioning
- \dopresetpositionanchors
+\unexpanded\def\dopositionaction#1%
+ {\edef\currentpositionaction{#1}%
+ \ifcsname\??positionaction\currentpositionaction\endcsname
+ \anch_positions_action_indeed
\fi}
-%D The first version of this module implemented head and tail
-%D anchors. Currently we stick to just one anchor and derive
-%D the head and tail anchors from this one.
+\def\anch_positions_action_indeed
+ {\doifpositionelse\currentpositionaction
+ \anch_positions_action_indeed_yes
+ \anch_positions_action_indeed_nop}
+
+\def\anch_positions_action_indeed_nop
+ {\anch_positions_trace_action_nop}
+
+\def\anch_positions_action_indeed_yes % we need a way to figure out if we have actions
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\anch_positions_trace_action_yes
+ \the\everyinsertpositionaction
+ \the\everypositionaction
+ \csname\??positionaction\currentpositionaction\endcsname
+ \anch_positions_cleanup_action}%
+ \smashedbox\scratchbox % smashing is really needed else we get problems with too big overlays
+ \endgroup}
+
+\unexpanded\def\anch_positions_trace_action_nop_indeed
+ {\anch_positions_trace\clap\darkred{<\currentpositionaction>}}
+
+\unexpanded\def\anch_positions_trace_action_yes_indeed
+ {\anch_positions_trace\clap\darkgreen{<\currentpositionaction>}}
-\def\showanchor#1%
- {\expanded{\writestatus{#1}
- {\MPp{#1}\string|\MPx{#1}\string|\MPy{#1}\string|%
- \MPw{#1}\string|\MPh{#1}\string|\MPd{#1}}}}
+\let\anch_positions_trace_action_nop\relax
+\let\anch_positions_trace_action_yes\relax
-%D We set these anchors before and after each page.
+\appendtoks
+ \let\anch_positions_trace_action_nop\anch_positions_trace_action_nop_indeed
+ \let\anch_positions_trace_action_yes\anch_positions_trace_action_yes_indeed
+\to \t_anch_positions_tracers
+
+%D Here the complication has to do with collecting actions
+%D for later execution. This collection is especially handy
+%D when we want to move actions to a specific layer. Such
+%D series of actions are stored in a macro that is cleaned up
+%D after each invocation.
+
+\def\anch_positions_cleanup_action % not in trialtypesetting
+ {\ifcsname\??positioncleanup\currentpositionaction\endcsname
+ \the\everycleanpositionaction
+ % \iflocalpositioning
+ % % erase
+ % \expandafter\let\csname\??positioncleanup\currentpositionaction\endcsname\empty
+ % \else
+ % globalize expansion cleans up
+ \setxvalue{\??positioncleanup\currentpositionaction}{\csname\??positioncleanup\currentpositionaction\endcsname}%
+ % \fi
+ \fi}
-\appendtoks \presetpositionanchors \to \beforeeverypage
-\appendtoks \presetpositionanchors \to \aftereverypage
+\def\handlepositionaction#1\with#2\on#3% ugly
+ {\begingroup
+ \edef\currentpositionanchor
+ {\ifx\currentpositionoverlay\empty#3\else\currentpositionoverlay::\MPanchoridentifier\fi}%
+ \normalexpanded{\dosetpositionaction{\currentpositionanchor}{\noexpand\getvalue{\??positioncleanup\currentpositionanchor}}}%
+ \let#1\relax
+ \ifcsname\??positioncleanup\currentpositionanchor\endcsname
+ \setxvalue{\??positioncleanup\currentpositionanchor}%
+ {\csname\??positioncleanup\currentpositionanchor\endcsname#1#2}%
+ \else
+ \setxvalue{\??positioncleanup\currentpositionanchor}%
+ {#1#2}%
+ \fi
+ \endgroup}
-% todo: change with each page size change
+%D The first version of this module implemented head and tail
+%D anchors. Currently we stick to just one anchor and derive
+%D the head and tail anchors from this one. We set these
+%D anchors before and after each page.
-\def\registerpageposition#1% this one is flushed first !
+\unexpanded\def\anch_positions_register_page#1% this one is flushed first ! ... can't we avoid this one
{\ifpositioning\ifcase\realpageno\or
\ifdim\printpaperheight=\paperheight
\ifdim\printpaperwidth=\paperwidth
% not needed,
\else
- \setbox#1\hbox{\hpos\pageanchor{\box#1}}%
+ \anch_positions_register_page_indeed{#1}%
\fi
\else
- \setbox#1\ruledhbox{\hpos\pageanchor{\box#1}}%
+ \anch_positions_register_page_indeed{#1}%
\fi
\fi\fi}
-\unexpanded\def\placepositionanchors % todo : depth pagebox
+% \def\anch_positions_register_page_indeed#1%
+% {\setbox#1\hbox{\hpos\pageanchor{\box#1}}}
+
+\def\anch_positions_register_page_indeed#1% maybe like text
+ {\ifvbox#1\setbox#1\hbox{\box#1}\fi
+ \anch_make_page_box{#1}}
+
+\unexpanded\def\anch_positions_place_anchors
{\ifpositioning
- \setbox\scratchbox\vbox to \textheight
- {\simpletopskipcorrection
- \hbox{\strut\dopositionaction\headanchor}%
- \vfill
- \hbox{\strut\dopositionaction\tailanchor}}%
- \dp\scratchbox\zeropoint
- \wd\scratchbox\makeupwidth % not \zeropoint, else wrong text backgrounds
- \hpos\textanchor{\box\scratchbox}%
+ \anch_positions_place_anchors_yes
\else
- \vskip\textheight
+ \anch_positions_place_anchors_nop
\fi}
-
+
+\def\anch_positions_place_anchors_yes % todo : depth pagebox
+ {\begingroup
+ \setbox\scratchbox\emptyhbox
+ \ht\scratchbox\textheight
+ \dp\scratchbox\zeropoint
+ \wd\scratchbox\makeupwidth
+ \anch_mark_text_box\scratchbox
+ \box\scratchbox
+ \endgroup}
+
+\def\anch_positions_place_anchors_nop
+ {\vskip\textheight}
+
%D \macros
%D {positionoverlay,startpositionoverlay}
%D
@@ -144,8 +217,8 @@
%D
%D \typebuffer[graphic]
-\def\MPanchoridentifier{mpa} % {mp-anchor}
-\def\MPoverlayposprefix{MO::}
+\def\MPanchoridentifier{mpa} % {mp-anchor}
+%def\MPoverlayposprefix{MO::} % not used
%D The rest of the definitions concerning such overlays may
%D look complicated,
@@ -155,91 +228,110 @@
%D Position actions are automatically executed when a position
%D is set.
-\let\MPanchornumber\realfolio
+% \newcount\localpositionnumber % incremented elsewhere
+% \newif\iflocalpositioning
+%
+% \def\textbackgroundoverlay#1{\iflocalpositioning\v!local\else\v!text\fi#1}
+% \def\MPanchornumber {\the\iflocalpositioning\localpositionnumber\else\realpageno\fi}
+
+\def\textbackgroundoverlay#1{\v!text#1}
+\def\MPanchornumber {\the\realpageno}
-\def\positionoverlay#1% the test prevents too many redundant positions
+\def\positionoverlay % the test prevents too many redundant positions
{\ifpositioning % in (not used) text* position layers
- \vbox to \overlayheight
- {\doifpositionactionelse{#1::\MPanchoridentifier}%
- {\edef\MPanchorid{#1::\MPanchoridentifier:\MPanchornumber}%
- \edef\MPanchor##1{\MPpos{\MPanchorid}}%
- \the\everyinsertpositionaction
- \copyposition{#1::\MPanchoridentifier}{#1::\MPanchoridentifier:\MPanchornumber}%
- \hpos
- {#1::\MPanchoridentifier:\MPanchornumber}%
- % this is ok
- %{\hbox to \overlaywidth{\dopositionaction{#1::\MPanchoridentifier}\hss}}}%
- % but this one prevents cyclic runs due to
- % rounding errors
- {\setbox\scratchbox\hbox to \overlaywidth{\dopositionaction{#1::\MPanchoridentifier}\hss}%
- \ht\scratchbox\overlayheight
- \dp\scratchbox\zeropoint
- \box\scratchbox}}%
- {\hbox to \overlaywidth{\hss}}%
- \vfill}%
+ \expandafter\anch_positions_overlay_indeed
+ \else % also \iftrialtypesetting test here?
+ \expandafter\gobbleoneargument
\fi}
-\unexpanded\def\startpositionoverlay#1%
- {\iftrialtypesetting % we don't want redundant entries in the list
- \@EA\gobbleuntil\@EA\stoppositionoverlay
- \else
- \def\currentpositionoverlay{#1}%
+\def\anch_positions_overlay_indeed#1%
+ {\begingroup
+ \edef\currentpositionoverlay{#1}%
+ \ifcsname\??positionaction\currentpositionoverlay::\MPanchoridentifier\endcsname
+ \anch_positions_overlay_compose
+ \fi
+ \endgroup}
+
+\def\MPoverlayanchor#1{\MPpos\MPanchorid}
+
+\def\anch_positions_overlay_compose
+ {\vbox to \overlayheight
+ {%\writestatus{!!!}{\currentpositionoverlay/\MPanchoridentifier/\MPanchornumber}%
+ \edef\MPanchorid{\currentpositionoverlay::\MPanchoridentifier:\MPanchornumber}% realpageno
+% \edef\MPanchor##1{\MPpos\MPanchorid}%
+ \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
+ \the\everyinsertpositionaction
+ \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
+ \setbox\scratchbox\hbox to \overlaywidth{\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
+ \ht\scratchbox\overlayheight
+ \dp\scratchbox\zeropoint
+ \ctxcommand{markregionbox(\number\scratchbox,"\MPanchorid")}% needs an hbox
+ \box\scratchbox
+ \vfill}}
+
+\def\positionregionoverlay % shares regions
+ {\ifpositioning
+ \expandafter\anch_positions_region_overlay_indeed
+ \else % also \iftrialtypesetting test here?
+ \expandafter\gobbletwoarguments
\fi}
-\unexpanded\def\stoppositionoverlay
- {\let\currentpositionoverlay\empty}
+\let\currentpositionregion\empty
-\def\resetpositionoverlay#1%
- {\dosetpositionaction{#1::\MPanchoridentifier::}{}}
+\def\anch_positions_region_overlay_indeed#1#2%
+ {\begingroup
+ \edef\currentpositionregion {#1}%
+ \edef\currentpositionoverlay{#2}%
+ \ifcsname\??positionaction\currentpositionoverlay::\MPanchoridentifier\endcsname
+ \anch_positions_region_overlay_compose
+ \fi
+ \endgroup}
+
+\def\anch_positions_region_overlay_compose
+ {\vbox to \overlayheight
+ {\let\MPanchorid\currentpositionregion
+ \let\MPanchor\MPoverlayanchor % no need to fetch it already, seldom used
+ \the\everyinsertpositionaction
+ \copyposition{\currentpositionoverlay::\MPanchoridentifier}\MPanchorid
+ \setbox\scratchbox\hbox to \overlaywidth{\dopositionaction{\currentpositionoverlay::\MPanchoridentifier}\hss}%
+ \ht\scratchbox\overlayheight
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \vfill}}
+
+% \let\anch_positions_overlay_nop\gobbleoneargument
+
+\unexpanded\def\startpositionoverlay
+ {\iftrialtypesetting
+ \expandafter\anch_positions_overlay_start_nop
+ \else
+ \expandafter\anch_positions_overlay_start_yes
+ \fi}
-%D Here the complication has to do with collecting actions
-%D for later execution. This collection is especially handy
-%D when we want to move actions to a specific layer.
-%D Such series of actions are stored in a macro (the one
-%D with the funny \type {++}) which is cleaned up after each
-%D invocation.
+\def\anch_positions_overlay_start_nop#1\stoppositionoverlay
+ {}
-\newtoks\everycleanpositionaction
-\newtoks\everyinsertpositionaction
+\def\anch_positions_overlay_start_yes#1%
+ {\checkpositionoverlays
+ \edef\currentpositionoverlay{#1}}
-\def\cleanuppositionaction#1% not in trialtypesetting
- {\ifcsname\POSactionprefix#1++\endcsname
- \the\everycleanpositionaction
- \iflocalpositioning
- \letgvalue{\POSactionprefix#1++}\empty
- \else
- \setxvalue{\POSactionprefix#1++}{\getvalue{\POSactionprefix#1++}}%
- \fi
- \fi}
+\unexpanded\def\stoppositionoverlay
+ {\let\currentpositionoverlay\empty}
-\def\handlepositionaction#1\with#2\on#3%
- {\bgroup
- \ifx\currentpositionoverlay\empty
- \edef\!!stringa{#3}% no layer, just pos itself as anchor
- \else
- \edef\!!stringa{\currentpositionoverlay::\MPanchoridentifier}%
- \fi
- \edef\!!stringc{\POSactionprefix\!!stringa++}%
- \expanded{\dosetpositionaction{\!!stringa}{\noexpand\getvalue{\!!stringc}}}%
- \global\let#1\relax
- \edef\!!stringb{\executeifdefined\!!stringc\empty}%
- \setxvalue\!!stringc{\!!stringb#1#2}%
- \egroup}
-
-%D The indirectness enables us redefine macros for special
-%D purposes, like a cleanup.
-
-\def\handlepositionboxes#1#2#3%
- {\handlepositionaction\dohandlepositionboxes\with{#1}{#2}{#3}\on{#2}}
-
-\def\doinsertpositionboxes#1#2#3% pos tag setups
- {\ifnum\MPp{#1}=\realpageno\relax % can be sped up
- \executeifdefined{\MPoverlayposprefix#1}\gobblethreearguments{#1}{#2}{#3}%
- \fi}
+% \def\resetpositionoverlay#1%
+% {\dosetpositionaction{#1::\MPanchoridentifier::}{}}
-\appendtoks
- \let\dohandlepositionboxes\doinsertpositionboxes % was handle ?
-\to \everyinsertpositionaction
+% \def\handlepositionboxes#1#2#3%
+% {\handlepositionaction\dohandlepositionboxes\with{#1}{#2}{#3}\on{#2}}
+%
+% \def\doinsertpositionboxes#1#2#3% pos tag setups
+% {\ifnum\MPp{#1}=\realpageno\relax % can be sped up
+% \executeifdefined{\MPoverlayposprefix#1}\gobblethreearguments{#1}{#2}{#3}% not used
+% \fi}
+%
+% \appendtoks
+% \let\dohandlepositionboxes\doinsertpositionboxes % was handle ?
+% \to \everyinsertpositionaction
\def\docleanpositionboxes#1#2#3% pos tag setups
{\ifnum\MPp{#1}<\realpageno \else
@@ -247,87 +339,84 @@
\fi}
\appendtoks
- \let\dohandlepositionboxes\docleanpositionboxes
+ \let\dohandlepositionboxes\docleanpositionboxes
\to \everycleanpositionaction
%D A position graphic is a normal (non||reused) \METAPOST\
%D graphic, used immediately, with zero dimensions, so that a
%D sequence of them does not harm.
+\installcorenamespace{positiongraphic}
+\installcorenamespace{positionmethod}
+%installcorenamespace{graphicvariable}
+
\newbox\positiongraphicbox
\def\startMPpositiongraphic % id setups
- {\dodoublegroupempty\dostartMPpositiongraphic}
+ {\dodoublegroupempty\anch_positions_meta_graphic_start}
-\long\def\dostartMPpositiongraphic#1#2#3\stopMPpositiongraphic
- {\long\setgvalue{MPG:#1}% tag list mpcode
- {\useMPpositiongraphic{#1}{#2}{#3}}}
+\def\anch_positions_meta_graphic_start#1#2#3\stopMPpositiongraphic % tag list mpcode
+ {\setgvalue{\??positiongraphic#1}{\anch_positions_meta_graphic_use{#1}{#2}{#3}}}
\let\stopMPpositiongraphic\relax
-\def\prepareMPpositionvariables
- {\ifcsname\@@meta self\endcsname\else\setvalue{\@@meta self}{\currentposition}\fi
- \ifcsname\@@meta from\endcsname\else\setvalue{\@@meta from}{\currentposition}\fi}
+\def\anch_positions_meta_graphic_prepare
+ {\ifcsname\??gv\currentmpvariableclass:self\endcsname \else
+ \letvalue{\??gv\currentmpvariableclass:self}\currentposition
+ \fi
+ \ifcsname\??gv\currentmpvariableclass:from\endcsname \else
+ \letvalue{\??gv\currentmpvariableclass:from}\currentposition
+ \fi}
-\long\def\useMPpositiongraphic#1#2#3%
- {\bgroup
- \prepareMPvariables{#2}%
- \prepareMPpositionvariables
- \enableincludeMPgraphics
+\def\anch_positions_meta_graphic_use#1#2#3%
+ {\begingroup
+ \meta_prepare_variables{#2}%
+ \anch_positions_meta_graphic_prepare
\startMPcode#3\stopMPcode
- \egroup}
-
-% Now we need a adapted action handler:
+ \endgroup}
-\def\dopositionaction#1% test saves hash entry in etex
- {\ifcsname\POSactionprefix#1::\endcsname
- \dodopositionaction{#1}%
- \fi}
+\def\MPpositiongraphic
+ {\dodoublegroupempty\anch_positions_meta_graphic_direct}
-\def\dodopositionaction#1%
- {\ifnum\MPp{#1}>\zerocount % new
- \bgroup
- \setbox\scratchbox\hbox
- \bgroup
- \traceposstring\clap\red{<#1>}%
- \the\everyinsertpositionaction
- \the\everypositionaction
- \csname\POSactionprefix#1::\endcsname
- \cleanuppositionaction{#1}%
- \egroup % smashed is really needed else
- \smashedbox\scratchbox % we get problems with too big
- \egroup % overlays (s-pre-0x.tex)
+\def\anch_positions_meta_graphic_direct#1% tag setups
+ {\ifcsname\??positionmethod#1\endcsname % method
+ \expandafter\anch_positions_meta_graphic_direct_indeed_method
+ \else\ifcsname\??positiongraphic#1\endcsname
+ \doubleexpandafter\anch_positions_meta_graphic_direct_indeed_normal
\else
- % shouldn't happen too often
- \traceposstring\clap\cyan{<#1>}%
- \fi}
+ \doubleexpandafter\anch_positions_meta_graphic_direct_indeed_unknown
+ \fi\fi{#1}}
-\def\MPpositiongraphic
- {\dodoublegroupempty\doMPpositiongraphic}
-
-\def\doMPpositiongraphic#1#2% tag setups
- {\bgroup
- \def\@@meta{#1:}%
- \setupMPvariables[#2]%
- \prepareMPpositionvariables
- \MPshiftdrawingtrue
- \def\doMPpositiongraphic##1##2%
- {{% new, see (techniek)
- \def\@@meta{##1:}%
- \setupMPvariables[#2,##2]%
- \prepareMPpositionvariables
- % and needed
- \getvalue{MPG:##1}}}% temp hack
- \setbox\positiongraphicbox\hbox
- {\ignorespaces
- \executeifdefined{MPM:#1}{\executeifdefined{MPG:#1}\donothing}%
- \removelastspace}%
+\let\anch_positions_meta_graphic_direct_indeed_unknown\gobbletwoarguments
+
+\def\anch_positions_meta_graphic_direct_indeed_method
+ {\anch_positions_meta_graphic_direct_indeed\??positionmethod}
+
+\def\anch_positions_meta_graphic_direct_indeed_normal
+ {\anch_positions_meta_graphic_direct_indeed\??positiongraphic}
+
+\def\anch_positions_meta_graphic_direct_indeed#1#2#3% what tag setups
+ {\begingroup
+ \setupMPvariables[#2][#3]%
+ \edef\currentmpvariableclass{#2}%
+ \anch_positions_meta_graphic_prepare
+ \obeyMPboxorigin % do we also set the size ? when needed this must be done in mp ... might change
+ \def\anch_positions_meta_graphic_direct{\anch_positions_meta_graphic_nested{#3}}% takes two extra arguments
+ \setbox\positiongraphicbox\hbox{\ignorespaces\csname#1#2\endcsname\removelastspace}%
\smashbox\positiongraphicbox
\box\positiongraphicbox
- \egroup}
+ \endgroup}
+
+\def\anch_positions_meta_graphic_nested#1#2#3% nesting used in prikkels / pascal (might go away)
+ {\begingroup
+ \setupMPvariables[#2][#1,#3]%
+ \edef\currentmpvariableclass{#2}%
+ \anch_positions_meta_graphic_prepare
+ \getvalue{\??positiongraphic#2}%
+ \endgroup}%
-\long\def\startMPpositionmethod#1#2\stopMPpositionmethod
- {\long\setgvalue{MPM:#1}{#2}} % todo: var list here
+\def\startMPpositionmethod#1#2\stopMPpositionmethod
+ {\setgvalue{\??positionmethod#1}{#2}} % todo: var list here
\let\stopMPpositionmethod\relax
@@ -352,21 +441,21 @@
\fi}
\appendtoks
- \let\dohandleMPpositiongraphic\doinsertMPpositiongraphic
+ \let\dohandleMPpositiongraphic\doinsertMPpositiongraphic
\to \everyinsertpositionaction
\def\docleanMPpositiongraphic#1#2#3% pos tag setups
{\ifnum\MPp{#1}<\realpageno \else
- \noexpand \dohandleMPpositiongraphic{#1}{#2}{#3}%
+ \noexpand\dohandleMPpositiongraphic{#1}{#2}{#3}%
\fi}
\appendtoks
- \let\dohandleMPpositiongraphic\docleanMPpositiongraphic
+ \let\dohandleMPpositiongraphic\docleanMPpositiongraphic
\to \everycleanpositionaction
%D Graphics that span two positions (beware, does not cross pages).
-\def\setMPpositiongraphicrange
+\unexpanded\def\setMPpositiongraphicrange
{\doquadruplegroupempty\dosetMPpositiongraphicrange}
\def\dosetMPpositiongraphicrange#1#2#3#4% bpos epos tag vars
@@ -380,26 +469,14 @@
{\handlepositionaction\dohandleMPpositiongraphicrange\with{#1}{#2}{#3}{#4}\on{#2}}
\def\doinsertMPpositiongraphicrange#1#2#3#4% pos pos tag setups
- {\ifnum\MPp{#1}\MPp{#2}>\zerocount
- \iflocalpositioning
- \donetrue
- \else
- \donefalse
- \ifnum\MPp{#1}=\realpageno
- \donetrue
- \else\ifnum\MPp{#2}=\realpageno
- \donetrue
- \else\ifnum\MPp{#1}<\realpageno\relax\ifnum\MPp{#2}>\realpageno
- \donetrue
- \fi\fi\fi\fi
- \fi
- \ifdone
- \def\currentposition{#1}\MPpositiongraphic{#3}{#4}%
- \fi
- \fi}
+ {\ctxcommand{doifelserangeonpage("#1","#2",\number\realpageno)}%
+ {%\writestatus{YES}{#1/#2 => #3}%
+ \def\currentposition{#1}%
+ \MPpositiongraphic{#3}{#4}}%
+ {}}%\writestatus{NOP}{#1/#2 = #3}}}
\appendtoks
- \let\dohandleMPpositiongraphicrange\doinsertMPpositiongraphicrange
+ \let\dohandleMPpositiongraphicrange\doinsertMPpositiongraphicrange
\to \everyinsertpositionaction
\def\docleanMPpositiongraphicrange#1#2#3#4% pos tag setups
@@ -408,1211 +485,14 @@
\fi}
\appendtoks
- \let\dohandleMPpositiongraphicrange\docleanMPpositiongraphicrange
+ \let\dohandleMPpositiongraphicrange\docleanMPpositiongraphicrange
\to \everycleanpositionaction
-
-% will be overloaded, and/or code below moved to core-box
-
-\defineoverlay[\v!text-2][\positionoverlay{\v!text-2}]
-\defineoverlay[\v!text-1][\positionoverlay{\v!text-1}]
-\defineoverlay[\v!text+1][\positionoverlay{\v!text+1}]
-\defineoverlay[\v!text+2][\positionoverlay{\v!text+2}]
-
-%D The auxiliary \METAPOST\ macros are defined by default,
-%D by saying:
-
-\startMPextensions
- if unknown context_core : input mp-core.mp ; fi ;
-\stopMPextensions
-
-%D Some of these macros are pretty clever but too complicated
-%D to be nice. When things are kind of stable I'll clean up
-%D this mess.
-
-%D THIS NEEDS A CLEANUP
-
-\setupMPvariables
- [mpos:box]
- [linecolor=blue,
- linewidth=\linewidth,
- fillcolor=lightgray,
- filloffset=\!!zeropoint]
-
-\startMPpositiongraphic{mpos:box}{fillcolor,linecolor,linewidth}
- initialize_box(\MPpos{\MPvar{self}}) ;
- boxfillcolor := \MPvar{fillcolor} ;
- boxlinecolor := \MPvar{linecolor} ;
- boxlinewidth := \MPvar{linewidth} ;
- boxfilloffset := \MPvar{filloffset} ;
- draw_box ;
- anchor_box(\MPanchor{\MPvar{self}}) ;
-\stopMPpositiongraphic
-
-\setupMPvariables
- [mpos:area]
- [linecolor=blue,
- linewidth=\linewidth,
- fillcolor=lightgray,
- filloffset=\!!zeropoint]
-
-\startMPpositiongraphic{mpos:area}{fillcolor,linecolor,linewidth}
- initialize_area(\MPpos{b:\MPvar{self}},\MPpos{e:\MPvar{self}}) ;
- boxfillcolor := \MPvar{fillcolor} ;
- boxlinecolor := \MPvar{linecolor} ;
- boxlinewidth := \MPvar{linewidth} ;
- boxfilloffset := \MPvar{filloffset} ;
- draw_area ;
- anchor_area(\MPanchor{b:\MPvar{self}}) ;
-\stopMPpositiongraphic
-
-%D This is already cleaned up.
-
-% gridtype = 1 => baseline
-% gridtype = 2 => betweenline
-
-\setupMPvariables
- [mpos:par]
- [mp=mpos:par:shape,
- gridtype=0,
- linetype=1,
- filltype=1,
- dashtype=0, % 1 = dashed, 2 = dashed with background
- %snaptops=true, % not that nice: true/false
- gridcolor=red,
- linecolor=blue,
- fillcolor=lightgray,
- filloffset=\!!zeropoint,
- linewidth=\linewidth,
- gridwidth=\linewidth,
- gridshift=\!!zeropoint,
- lineradius=.5\bodyfontsize,
- dashtype=1]
-
-\startuseMPgraphic{mpos:par:shape}
- \iftracepositions show_par \else draw_par \fi ;
-\stopuseMPgraphic
-
-\startuseMPgraphic{mpos:par:setup}
- boxgridtype := \MPvar{gridtype} ;
- boxlinetype := \MPvar{linetype} ;
- boxfilltype := \MPvar{filltype} ;
- boxdashtype := \MPvar{dashtype} ;
- boxgridcolor := \MPvar{gridcolor} ;
- boxlinecolor := \MPvar{linecolor} ;
- boxfillcolor := \MPvar{fillcolor} ;
- boxfilloffset := \MPvar{filloffset} ;
- boxlinewidth := \MPvar{linewidth} ;
- boxgridwidth := \MPvar{gridwidth} ;
- boxgridshift := \MPvar{gridshift} ;
- boxlineradius := \MPvar{lineradius} ;
- %snap_multi_par_tops := \MPvar{snaptops} ;
-\stopuseMPgraphic
-
-\startuseMPgraphic{mpos:par:extra}
- % user stuff, like:
- % snap_multi_par_tops := false ;
-\stopuseMPgraphic
-
-\ifx\MPparcounter\undefined \newcounter\MPparcounter \fi
-
-\def\MPself {\MPvar{self}}
-\def\MPbself {b:\MPself}
-\def\MPeself {e:\MPself}
-\def\MPwself {w:\MPself}
-\def\MPparanchor{p:\MPparcounter}
-
-\def\MPl#1{\MPplus{#1}20}
-\def\MPr#1{\MPplus{#1}30}
-
-\startMPpositionmethod{mpos:par} %%%%%%%%%%% will become obsolete
- \edef\MPparcounter{\MPv\MPbself{1}{0}}%
- \doifpositionelse\MPwself
- {\startMPpositiongraphic{mpos:par}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius}
- initialize_area_par(\MPpos\MPbself,
- \MPpos\MPeself,
- \MPpos\MPwself) ;
- \includeMPgraphic{mpos:par:setup} ;
- \includeMPgraphic{mpos:par:extra} ;
- \includeMPgraphic{\MPvar{mp}} ;
- anchor_par(\MPanchor\MPbself) ;
- \stopMPpositiongraphic}
- {\startMPpositiongraphic{mpos:par}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius}
- initialize_par(\MPpos\MPbself,
- \MPpos\MPeself,
- \MPpos\textanchor,
- \MPpos\MPparanchor,
- \MPvv \MPparanchor{0pt,0pt,0pt,0pt,0,0pt}) ;
- \includeMPgraphic{mpos:par:setup} ;
- \includeMPgraphic{mpos:par:extra} ;
- \includeMPgraphic{\MPvar{mp}} ;
- anchor_par(\MPanchor\MPbself) ;
- \stopMPpositiongraphic}%
- \MPpositiongraphic{mpos:par}{}%
-\stopMPpositionmethod
-
-%D The next alternative works in columnsets :
-
-% \iftracepositions show\else draw\fi_multi_pars ;
-
-\startuseMPgraphic{mpos:par:columnset}
- \iftracepositions show_multi_pars \else draw_multi_pars \fi ;
-\stopuseMPgraphic
-
-\startuseMPgraphic{mpos:par:sideline}{linecolor,lineoffset}
- for i=1 upto nofmultipars :
- fill leftboundary multipars[i]
- shifted (-\MPvar{lineoffset},0)
- rightenlarged 1mm withcolor \MPvar{linecolor} ;
- endfor ;
-\stopuseMPgraphic
-
-\startMPpositionmethod{mpos:par:columnset}
- \edef\MPparcounter{\MPv\MPbself{1}{0}}%
- \startMPpositiongraphic{mpos:par}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius}
- \includeMPgraphic{mpos:par:setup} ;
- \includeMPgraphic{mpos:par:extra} ;
- prepare_multi_pars(\MPpos\MPbself,\MPpos\MPeself,\MPpos\MPwself,
- \MPpos\MPparanchor,\MPvv\MPparanchor{0pt,0pt,0pt,0pt,0,0pt}) ;
- relocate_multipars(-\MPxy\MPanchorid) ; % inside layerpos
- \includeMPgraphic{\MPvar{mp}} ;
- \stopMPpositiongraphic
- \MPpositiongraphic{mpos:par}{}%
-\stopMPpositionmethod
-
-%D \starttyping
-%D \setupbackground
-%D [test]
-%D [mp=mpos:par:columnset,
-%D method=mpos:par:columnset]
-%D \stoptyping
-
-%D We need to treat floats in a special way.
-
-\startMPinitializations
- local_multi_par_area:=\iflocalpositioning true\else false\fi;
-\stopMPinitializations
-
-\def\textbackgroundoverlay#1%
- {\iflocalpositioning\v!local\else\v!text\fi#1}
-
-\newcounter\localpositionnumber
-
-\def\MPanchornumber
- {\iflocalpositioning\localpositionnumber\else\the\realpageno\fi}
-
-%D So far for the trickery.
-
-\newcount\textbackgrounddepth
-
-\ifdefined\nofparbackgrounds\else \newcount\nofparbackgrounds \fi
-
-\ifx\totalnofparbackgrounds\undefined \newcounter\totalnofparbackgrounds \fi
-
-\appendtoks
- \expanded{\savecurrentvalue\noexpand\totalnofparbackgrounds{\number\nofparbackgrounds}}%
-\to \everybye
-
-% actually we can just ask lua to give us the nofpositions (or a least n<>0)
-
-\appendtoks
- % a position can be mid paragraph in which case we're behind
- % this will change when we move positions to lua
- \initializeparbackgrounds
-\to \everystarttext
-
-\def\initializeparbackgrounds
- {\ifcase\totalnofparbackgrounds\else
- \enableparpositions
- \fi}
-
-\unexpanded\def\starttextbackground
- {\bgroup
- \advance\textbackgrounddepth\plusone
- \dodoubleempty\dostarttextbackground}
-
-\let\dodostarttextbackground\relax
-\let\dodostoptextbackground \relax
-
-\def\currentparbackground{pbg:0}
-\def\nextparbackground {pbg:1}
-
-\def\btbanchor{b:\currentparbackground}
-\def\etbanchor{e:\currentparbackground}
-\def\nextbtbanchor{b:\nextparbackground}
-\def\nextetbanchor{e:\nextparbackground}
+\let\dohandleMPpositiongraphicrange\gobblefourarguments
-\def\textbackgroundparameter#1%
- {\csname\??td\currenttextbackground#1\endcsname}
+% Helpers:
-\let\backgroundvariable\textbackgroundparameter % will become obsolete
+\def\MPgetposboxes #1#2{\ctxcommand{fetchposboxes("#1","#2",\the\realpageno)}}
+\def\MPgetmultipars#1#2{\ctxcommand{fetchmultipar("#1","#2",\the\realpageno)}}
-% \definetextbackground[more][state=start,backgroundcolor=red] % location=paragraph
-% \definetextbackground[test][state=start,backgroundcolor=green]
-%
-% \page \placefigure[left]{}{}
-%
-% \starttextbackground[test]
-% \readfile{ward}{}{}
-% \starttextbackground[more]
-% \readfile{ward}{}{}
-% \stoptextbackground
-% \readfile{ward}{}{}
-% \stoptextbackground
-%
-% \page \placefigure[right]{}{}
-%
-% \starttextbackground[test]
-% \readfile{ward}{}{}
-% \starttextbackground[more]
-% \readfile{ward}{}{}
-% \stoptextbackground
-% \readfile{ward}{}{}
-% \stoptextbackground
-
-\def\dostarttextbackground[#1][#2]%
- {\checktextbackgrounds
- \def\currenttextbackground{#1}%
- \global\advance\nofparbackgrounds\plusone
- \edef\currentparbackground{pbg:\number\nofparbackgrounds}%
- \xdef\nextparbackground{pbg:\number\numexpr\nofparbackgrounds+\plusone\relax}% still xdef ?
- % todo : \synchonizepositionpage{b:\currentparbackground}{s:\currentparbackground}%
- \setuptextbackground[#1][#2]%
- \let\dodostarttextbackground\relax
- \let\dodostoptextbackground \relax
- \doif{\textbackgroundparameter\c!state}\v!start{\dopresettextbackground{#1}}%
- \dodostarttextbackground}
-
-% todo \backgroundvariable\c!variant
-
-\def\dopresettextbackground#1% todo: \backgroundparameter
- {\normalexpanded{\noexpand\processaction[\textbackgroundparameter\c!location]}
- [ \v!text=>\let\dodostarttextbackground\dostarttextbackgroundtxt
- \let\dodostoptextbackground \dostoptextbackgroundtxt,
- \v!paragraph=>\let\dodostarttextbackground\dostarttextbackgroundpar
- \let\dodostoptextbackground \dostoptextbackgroundpar,
- \v!none=>\let\dodostarttextbackground\relax
- \let\dodostoptextbackground \relax]%
- \ifx\dodostarttextbackground\dostarttextbackgroundpar % untested
- \ifnum\textbackgrounddepth>\plusone % new
- \let\dodostarttextbackground\dostarttextbackgroundtxt
- \let\dodostoptextbackground \dostoptextbackgroundtxt
- \fi
- \fi
- \doifelse{\textbackgroundparameter\c!frame}\v!on
- {\doifelse{\textbackgroundparameter\c!corner}\v!round
- {\setvalue{\??td#1\c!frame}{2}}
- {\setvalue{\??td#1\c!frame}{1}}}
- {\setvalue{\??td#1\c!frame}{0}}%
- \doifelse{\textbackgroundparameter\c!background}\v!color
- {\setvalue{\??td#1\c!background}{1}}
- {\setvalue{\??td#1\c!background}{0}}%
- %\startpositionoverlay{\v!text\getvalue{\??td#1\c!level}}%
- \startpositionoverlay{\textbackgroundoverlay{\textbackgroundparameter\c!level}}%
- \expanded
- {\setMPpositiongraphicrange % moet veel efficienter
- {\btbanchor}% {b:\currentparbackground}%
- {\etbanchor}% {e:\currentparbackground}%
- {\textbackgroundparameter\c!method}%
- {self=\currentparbackground,
- mp=\textbackgroundparameter\c!mp,
- gridtype=\textbackgroundparameter\c!alternative,
- filltype=\textbackgroundparameter\c!background,
- linetype=\textbackgroundparameter\c!frame,
- dashtype=\textbackgroundparameter{dash}, % to be internationalized
- gridcolor=\textbackgroundparameter\c!framecolor,
- linecolor=\textbackgroundparameter\c!framecolor,
- lineoffset=\textbackgroundparameter\c!frameoffset,
- fillcolor=\textbackgroundparameter\c!backgroundcolor,
- filloffset=\textbackgroundparameter\c!backgroundoffset,
- gridwidth=\textbackgroundparameter\c!rulethickness,
- gridshift=\textbackgroundparameter\c!voffset,
- linewidth=\textbackgroundparameter\c!rulethickness,
- lineradius=\textbackgroundparameter\c!radius}}%
- \stoppositionoverlay}
-
-\unexpanded\def\stoptextbackground
- {\dodostoptextbackground
- \carryoverpar\egroup}
-
-\unexpanded\def\starttextbackgroundmanual
- {\dostartattributes{\??td\currenttextbackground}\c!style\c!color\empty
- \fpos\currentparbackground\ignorespaces}
-
-\unexpanded\def\stoptextbackgroundmanual
- {\tpos\currentparbackground
- \dostopattributes}
-
-\def\dostarttextbackgroundtxt
- {\ifvmode \dontleavehmode \fi
- \dostartattributes{\??td\currenttextbackground}\c!style\c!color\empty
- \fpos\currentparbackground\ignorespaces}
-
-\def\dostoptextbackgroundtxt
- {\tpos\currentparbackground
- \dostopattributes}
-
-\newskip\textbackgroundskip
-
-\def\dostarttextbackgroundpar
- {\endgraf % new
- \textbackgroundparameter\c!before
- \noindent
- \ifgridsnapping
- \doassignsomeskip\textbackgroundparameter\c!topoffset\to\textbackgroundskip
- \ifdim\textbackgroundskip>\zeropoint
- \struttedbox{\hbox{\raise\textbackgroundskip\hbox{\fpos\currentparbackground}}}%
- \else
- \fpos\currentparbackground
- \fi
- \else
- \fpos\currentparbackground
- \fi
- \bgroup
- \endgraf % we need a vertical nobreak - 29/06/2004
- \nobreak \vskip-\lineheight \nobreak
- \ifgridsnapping \else
- \doassignsomeskip\textbackgroundparameter\c!topoffset\to\textbackgroundskip
- \ifdim\textbackgroundskip>\zeropoint
- \kern\textbackgroundskip\nobreak
- \fi
- \fi
- \dosetleftskipadaption{\textbackgroundparameter\c!leftoffset}%
- \advance\leftskip\leftskipadaption
- \dosetleftskipadaption{\textbackgroundparameter\c!rightoffset}%
- \advance\rightskip\leftskipadaption
- % new
- \dosetraggedcommand{\textbackgroundparameter\c!align}%
- \raggedcommand
- %
- \dostartattributes{\??td\currenttextbackground}\c!style\c!color\empty
- \nowhitespace
- \nobreak % new per 23/04/2006 (else potential break when whitespace)
- \seteffectivehsize
- \doinhibitblank % \blank[\v!disable]% new
- \par}
-
-\def\dostoptextbackgroundpar
- {\par
- \removelastskip % new
- \dostopattributes
- \doassignsomeskip\textbackgroundparameter\c!bottomoffset\to\textbackgroundskip
- \ifdim\lastskip>\zeropoint
- \advance\textbackgroundskip-\lastskip
- \fi
- \ifgridsnapping \else \ifdim\textbackgroundskip>\zeropoint
- \kern\textbackgroundskip\nobreak
- \fi \fi
- \nobreak \vskip-\lineheight \nobreak
- \nowhitespace
- \egroup
- \bgroup \forgeteverypar % NOT REALLY NEEDED, SAVES HASH/MEM
- \nobreak \noindent \strut \hfill \kern\zeropoint
- \doassignsomeskip\textbackgroundparameter\c!bottomoffset\to\textbackgroundskip
- \ifgridsnapping % experimental, pascal (todo: topoffset in same way)
- \ifdim\textbackgroundskip>\zeropoint
- \struttedbox{\hbox{\lower\textbackgroundskip\hbox{\tpos\currentparbackground}}}%
- \else
- \tpos\currentparbackground
- \fi
- \else
- \tpos\currentparbackground
- \fi
- \egroup
- \endgraf % new
- \textbackgroundparameter\c!after}
-
-\let\textparpages \!!zeropoint
-\let\textparheight\!!zeropoint
-\let\textparwidth \!!zeropoint
-
-\def\calculatetextpardimensions
- {\docalculatetextpardimensions\btbanchor\etbanchor\MPparanchor}
-
-\def\calculatenexttextpardimensions
- {\docalculatetextpardimensions\nextbtbanchor\nextetbanchor\relax}
-
-\def\docalculatetextpardimensions#1#2#3% #1=\btbanchor #2=\etbanchor (adapted 8/6/2009)
- {\scratchcounter\numexpr\MPp#2-\MPp#1\relax
- \edef\textparpages
- {\the\scratchcounter}%
- \edef\textparheight
- {\the\dimexpr
- \ifcase\scratchcounter
- % one page
- \MPy#1-\MPy#2%
- \else
- % two or more pages
- \ifnum\scratchcounter>2
- \ifnum\scratchcounter<5
- % more pages
- \textheight*\numexpr\scratchcounter+\minusone
- \else
- % keep'm small
- 5\textheight
- \fi
- \else
- \MPy#1-\MPy#2-\MPy\textanchor+\MPy\textanchor+\MPh\textanchor
- \fi
- \fi
- \relax}%
- \edef\textparwidth
- {\the\dimexpr
- \ifcase\scratchcounter
- % one page
- \MPx#2-\MPx#1%
- \else
- % two or more pages / maybe also hang
- \ifx#3\relax
- \makeupwidth % \textwidth
- \else
- \MPw\MPparanchor-\MPl\MPparanchor-\MPr\MPparanchor
- \fi
- \fi
- \relax}}
-
-\def\mintextparheight{4\lineheight}
-
-\def\dontsplitnexttextbackground % dangerous but useful
- {\ifdim\pagetotal>\textheight \else
- \ifdim\pagegoal=\maxdimen \else
- \calculatenexttextpardimensions
- % too tricky
- % \scratchdimen=\textparheight
- % \advance\scratchdimen\pagetotal\relax
- % \ifdim\scratchdimen>\pagegoal
- % \page
- % \fi
- \ifdim\textparheight>\zeropoint
- \ifdim\textparheight>\mintextparheight\else
- \page % option
- \fi
- \fi
- \fi
- \fi}
-
-\unexpanded\def\definetextbackground
- {\dodoubleempty\dodefinetextbackground}
-
-\def\dodefinetextbackground[#1][#2]% parent and ..parameter
- {\ifsecondargument % why ?
- \copyparameters[\??td#1][\??td]
- [\c!state,\c!location,\c!alternative,\c!mp,\c!method,
- \c!background,\c!backgroundcolor,\c!corner,\c!level,
- \c!backgroundoffset,\c!before,\c!after,\c!align,dash, % dash not yet internationalized
- \c!radius,\c!frame,\c!framecolor,\c!rulethickness,\c!voffset,\c!frameoffset,
- \c!leftoffset,\c!rightoffset,\c!topoffset,\c!bottomoffset]%
- \getparameters[\??td#1][#2]%
- \doifvalue{\??td#1\c!state}\v!start\checktextbackgrounds
- \setuvalue{#1}%
- {\groupedcommand{\starttextbackground[#1]}{\stoptextbackground}}%
- \setvalue{\e!start#1}{\starttextbackground[#1]}%
- \setvalue{\e!stop #1}{\stoptextbackground}%
- \fi}
-
-\unexpanded\def\setuptextbackground
- {\dodoubleargument\dosetuptextbackground}
-
-\def\dosetuptextbackground[#1][#2]%
- {\ifsecondargument
- \doifelsenothing{#1}
- {\dodosetuptextbackground{#2}\empty}
- {\processcommalist[#1]{\dodosetuptextbackground{#2}}}%
- \else
- \dodosetuptextbackground{#1}\empty
- \fi}
-
-\def\dodosetuptextbackground#1#2%
- {\getparameters[\??td#2][#1]%
- \def\currenttextbackground{#2}%
- \doifvalue{\??td#2\c!state}\v!start\checktextbackgrounds}
-
-\let\currenttextbackground\empty
-
-\def\checktextbackgrounds
- {\ifproductionrun
- \enabletextarearegistration
- \enablehiddenbackground
- \fi}
-
-\setuptextbackground
- [\c!mp=mpos:par:columnset, % buggy: mpos:par:shape
- \c!method=mpos:par:columnset, %
- \c!state=\v!start,
- \c!location=\v!text,
- \c!leftoffset=\!!zeropoint, % 1em,
- \c!rightoffset=\textbackgroundparameter\c!leftoffset,
- \c!topoffset=\!!zeropoint, % \v!medium,
- \c!bottomoffset=\textbackgroundparameter\c!topoffset,
- \c!level=-1,
- \c!alternative=0,
- \c!align=,
- dash=0, % to be internationalized
- \c!background=\v!color,
- \c!backgroundcolor=lightgray,
- \c!backgroundoffset=\!!zeropoint,
- \c!corner=\v!rectangular,
- \c!radius=.5\bodyfontsize,
- \c!voffset=\!!zeropoint,
- \c!frame=\v!on,
- \c!framecolor=blue,
- \c!rulethickness=\linewidth]
-
-%D As an example we define a grid background:
-
-\definetextbackground
- [\v!grid]
- [\c!state=\v!stop,
- \c!location=\v!paragraph,
- \c!frame=\v!off,
- \c!framecolor=red,
- \c!background=,
- \c!alternative=1]
-
-\ifx\basegrid\undefined \else \letvalue\v!grid=\basegrid \fi
-
-\setupMPvariables
- [mpos:connect]
- [linecolor=red,
- linewidth=1pt]
-
-\setupMPvariables
- [mpos:encircle]
- [fillcolor=lightgray,
- filloffset=\!!zeropoint,
- linecolor=blue,
- linewidth=1pt]
-
-% these might become macros in mp-page
-
-\startuseMPgraphic{mpos:common:ec}
- path pa ; pair ca ; color lc ; numeric lw ;
- lw := \MPvar{linewidth} ;
- lc := \MPvar{linecolor} ;
- initialize_box(\MPpos{\MPvar{self}}) ;
- pa := pxy ; ca := cxy ; pa := boundingbox pa enlarged 2lw ;
- pa := llcorner pa...lrcorner pa...urcorner pa...ulcorner pa...cycle ;
- drawoptions (withpen pencircle scaled lw withcolor lc) ;
-\stopuseMPgraphic
-
-\startMPpositiongraphic{mpos:encircle}{linecolor,fillcolor,linewidth}
- \includeMPgraphic{mpos:common:ec}
- fill pa withcolor \MPvar{fillcolor} ; draw pa ;
- anchor_box(\MPanchor{\MPvar{self}}) ;
-\stopMPpositiongraphic
-
-\startMPpositiongraphic{mpos:connect}{linecolor,linewidth}
- path pb, pc ; pair cb, cc ;
- \includeMPgraphic{mpos:common:ec}
- initialize_box(\MPpos{\MPvar{to}}) ;
- pb := pxy ; cb := cxy ; pb := boundingbox pb enlarged 2lw ;
- pb := llcorner pb...lrcorner pb...urcorner pb...ulcorner pb...cycle ;
- pc := ca {up} .. {down} cb ;
- cc := (pc intersection_point pa) ;
- if intersection_found :
- pc := pc cutbefore cc ;
- cc := (pc intersection_point pb) ;
- if intersection_found :
- pc := pc cutafter cc ;
- drawarrow pc ; drawarrow reverse pc ;
- fi ;
- fi ;
- anchor_box(\MPanchor{\MPvar{self}}) ;
-\stopMPpositiongraphic
-
-%D \macros
-%D {stackposdown, stackposup, stackposleft,stackposright}
-%D
-%D A non graphic example of the use of positioning, is to stack
-%D text in for instance the margin.
-%D
-%D \stackposdown \inleft {some text}The text \type {some text}
-%D goes into the left margin, and \stackposdown \inleft {some
-%D more}\type {some more} as well. When they overlap, they
-%D will not touch.
-%D
-%D Here we said \type {\stackposdown \inleft{some text}}. Instead
-%D of \stackposleft \inleft {one}stacking \stackposleft \inleft
-%D {two}vertically, one can stack horizontally by \stackposleft
-%D \inleft {three}using \type {\stackposleft}.
-%D
-%D We can go in all four directions, using \type {\stackposdown},
-%D \type {\stackposup}, \type {\stackposleft} and \type
-%D {\stackposright}.
-
-\def\stackposdistance{.5em}
-
-\newcount\currentautopos
-\newcount\previousautopos
-
-\def\POSstackprefix{stack:}
-
-\def\dostackposbox#1#2%
- {\dowithnextbox
- {#2{\previousautopos\currentautopos
- \global\advance\currentautopos\plusone
- \edef\currentposition {\POSstackprefix\number\currentautopos}%
- \edef\previousposition{\POSstackprefix\number\previousautopos}%
- \hpos\currentposition{\doifoverlappingelse\currentposition\previousposition{#1}{\flushnextbox}}}}%
- \hbox}
-
-\def\stackposup {\dostackposbox{\raise\lineheight\flushnextbox}}
-\def\stackposdown {\dostackposbox{\lower\lineheight\flushnextbox}}
-\def\stackposleft {\dostackposbox{\copy\nextbox\hskip\nextboxwd\hskip\stackposdistance}}
-\def\stackposright{\dostackposbox{\hskip\stackposdistance\hskip\nextboxwd\flushnextbox}}
-
-% obsolete
-%
-% %D \macros
-% %D {stackeddown}
-% %D
-% %D However, a better implementation is possible with the
-% %D following macro. We now have an extra key \type {stack} for
-% %D margin settings. When set to \type {yes}, this macro comes
-% %D into action.
-%
-% % Because there can be many stacked items in a line and successive lines, we
-% % play dirty and adapt the position and height of the current node so that
-% % this becomes visible to a next pass.
-% %
-% % \startbuffer
-% % \inleft {test 1} test 1 \inleft {test 2} test 2 \endgraf
-% % \inleft {test 3} test 3
-% % \stopbuffer
-% % \getbuffer \typebuffer \flushstatus \page
-% %
-% % \startbuffer
-% % \inleft {test 1} test 1 \inleft {test 2} test 2 \inleft {test 3} test 3 \endgraf
-% % \inleft {test 4} test 4
-% % \stopbuffer
-% % \getbuffer \typebuffer \flushstatus \page
-% %
-% % \startbuffer
-% % \inleft {test 1} test 1 \endgraf
-% % \inleft {test 2} test 2 \endgraf
-% % \inleft {test 3} test 3
-% % \stopbuffer
-% % \getbuffer \typebuffer \flushstatus \page
-% %
-% % \startbuffer
-% % \inleft {test 1\\test 1} test 1 \inleft {test 2} test 2 \endgraf
-% % \inleft {test 3} test 3
-% % \stopbuffer
-% % \getbuffer \typebuffer \flushstatus \page
-% %
-% % \startbuffer
-% % \inleft {test 1\\test 1\\test 1\\test 1\\test 1} test 1 \endgraf
-% % test 2 \endgraf
-% % \inleft {test 3} test 3
-% % \stopbuffer
-% % \getbuffer \typebuffer \flushstatus \page
-% %
-% % \startbuffer
-% % \inleft{test 1} test \inleft{test 2} test \inleft{test 3\\test 3} test
-% % \stopbuffer
-% % \getbuffer \typebuffer \flushstatus \page
-% %
-% % \startbuffer
-% % \inleft{test 1\\test 1\\test 1} test \inleft{test 2\\test 2} test \inleft{test 3\\test 3\\test 3} test \endgraf
-% % \inleft{test 1\\test 1\\test 1} test \inleft{test 2\\test 2} test \inleft{test 3\\test 3\\test 3} test
-% % \stopbuffer
-% % \getbuffer \typebuffer \flushstatus \page
-%
-% \newdimen\laststackvmove % use \scratchdimenone instead of skip
-%
-% \def\stackeddown
-% {\bgroup
-% % this macro assumes a few things and is meant to work for margin notes
-% \dowithnextbox
-% {\global\advance\currentautopos\plusone
-% \global\laststackvmove\zeropoint
-% \hpos{\POSstackprefix\number\currentautopos}
-% {\edef\next
-% {\nextboxht\the\nextboxht
-% \nextboxdp\the\nextboxdp
-% \nextboxwd\the\nextboxwd}%
-% \previousautopos\currentautopos
-% \scratchdimen\zeropoint
-% \scratchcounter\zerocount
-% \doloop
-% {\advance\previousautopos\minusone
-% \edef\currentposition {\POSstackprefix\number\currentautopos}%
-% \edef\previousposition{\POSstackprefix\number\previousautopos}%
-% \ifnum\MPp\currentposition=\MPp\previousposition\relax
-% %\registerstatus{doing \number\currentautopos/\number\previousautopos}%
-% \doifoverlappingelse\currentposition\previousposition
-% {\scratchskip\dimexpr
-% \MPy\currentposition
-% -\MPy\previousposition
-% -\MPd\currentposition % untested
-% +\MPd\previousposition % untested
-% +\MPh\currentposition
-% \relax\relax % second relax realy needed, forgotten while dimexpressing
-% % todo: also take depth into account
-% \ifdim\scratchskip<\scratchdimen
-% %\registerstatus{no \the\scratchskip}%
-% \else
-% %\registerstatus{yes \the\scratchskip}%
-% \scratchdimen\scratchskip
-% \fi}%
-% \donothing % {\registerstatus{next}}%
-% \ifnum\previousautopos<\zerocount\exitloop\fi
-% \else
-% \exitloop
-% \fi}%
-% \ifdim\scratchdimen=\zeropoint \else
-% \bgroup
-% \edef\currentposition{\POSstackprefix\number\currentautopos}%
-% \scratchskip\scratchdimen
-% \advance\scratchskip\MPh\currentposition
-% \scratchdimen-\scratchdimen
-% \advance\scratchdimen\MPy\currentposition
-% %\registerstatus{old \number\currentautopos: \MPy\currentposition/\MPh\currentposition}%
-% \expanded{\replacepospxywhd
-% {\currentposition}{\MPp\currentposition}{\MPx\currentposition}{\the\scratchdimen}%
-% {\MPw\currentposition}{\the\scratchskip}{\MPd\currentposition}}%
-% %\registerstatus{new \number\currentautopos: \MPy\currentposition/\MPh\currentposition}%
-% \egroup
-% \global\laststackvmove\scratchdimen % new
-% \setbox\nextbox\iftracepositions\@EA\ruledhbox\else\@EA\hbox\fi
-% {\lower\scratchdimen\flushnextbox}%
-% \next
-% %\registerstatus{\strut}%
-% \fi
-% \flushnextbox}%
-% \egroup}}
-%
-% %D The next hack make sure that margin texts near faulty
-% %D strutted lines are handled ok.
-%
-% \newif\ifrepositionmarginbox \repositionmarginboxtrue
-%
-% \newcount\currentmarginpos
-%
-% \def\dopositionmarginbox#1%
-% {\bgroup
-% \ifrepositionmarginbox
-% \global\advance\currentmarginpos\plusone
-% %\setposition{\s!margin:\number\currentmarginpos}% not always
-% \ifcase\marginrepositionmethod
-% % nothing
-% \or
-% % nothing
-% \or
-% % stack / page check yet untested
-% \setposition{\s!margin:\number\currentmarginpos}%
-% \scratchdimen\MPy{\s!margin:\number\currentmarginpos}%
-% \global\advance\currentmarginpos\plusone
-% \advance\scratchdimen -\MPy{\s!margin:\number\currentmarginpos}%
-% \advance\scratchdimen -\strutdp
-% % new but bugged
-% % \setbox#1\hbox
-% % {\hskip-\MPx{\s!margin:\number\currentmarginpos}%
-% % \hskip\MPx{head:\the\realpageno}%
-% % \box#1}%
-% % so far
-% \setbox#1\hbox
-% {\setposition{\s!margin:\number\currentmarginpos}%
-% \raise\scratchdimen\box#1}%
-% \or
-% % move up
-% \setposition{\s!margin:\number\currentmarginpos}%
-% \ifnum\MPp{p:\number\parposcounter}=\MPp{\s!margin:\number\currentmarginpos}\relax
-% \scratchdimen\dimexpr\MPy{p:\number\parposcounter}-\MPy{\s!margin:\number\currentmarginpos}\relax
-% \expanded{\setbox#1\hbox{\raise\scratchdimen\box#1}\ht#1\the\ht#1\dp#1\the\dp#1}%
-% \fi
-% \or
-% % move up, assume end of par
-% \setposition{\s!margin:\number\currentmarginpos}%
-% \ifnum\MPp{p:\number\parposcounter}=\MPp{\s!margin:\number\currentmarginpos}\relax
-% \getnoflines\margincontentheight
-% \advance\noflines\minusone
-% \scratchdimen\noflines\lineheight
-% \else
-% \scratchdimen\dimexpr\MPy{p:\number\parposcounter}-\MPy{\s!margin:\number\currentmarginpos}\relax
-% \fi
-% \expanded{\setbox#1\hbox{\raise\scratchdimen\box#1}\ht#1\the\ht#1\dp#1\the\dp#1}%
-% \fi
-% \dp#1\zeropoint
-% \ht#1\zeropoint
-% \fi
-% \graphicvadjust{\dontleavehmode\box#1}% dontleavehmode is needed to get direction right
-% \egroup}
-%
-% % \setnewconstant\marginrepositionmethod\plusone % sidemethod
-% % \setnewconstant\margincontentmethod \plusthree % textmethod % beware: 1 = old method
-% % \setnewconstant\marginpagecheckmethod \plusone % splitmethod
-
-%D \macros
-%D {GFC, GTC, GSC}
-%D
-%D The next macros extend tables and tabulation with
-%D backgrounds and position related features. Areas are
-%D specified with symbolic names, and symbolic references to
-%D the graphics involved. Each table has its own namespace.
-
-\newconditional\tablehaspositions
-\newcount\noftabpositions
-\newtoks \posXCtoks
-
-\def\dotablebpos{\bpos}
-\def\dotableepos{\epos}
-
-\def\tbPOSprefix
- {tbp:\number\noftabpositions:}
-
-\def\tablepos
- {\normalexpanded{\global\posXCtoks\emptytoks\the\posXCtoks}}
-
-\let\tabulatepos\tablepos
-
-\def\dodododoGSC[#1:#2]%
- {\remappositionframed{#2}{\tbPOSprefix#1}%
- \dotablebpos{\tbPOSprefix#1}%
- \doglobal\appendtoks\@EA\dotableepos\@EA{\tbPOSprefix#1}\to\posXCtoks}
-
-\def\dododoGSC[#1:#2:#3]%
- {\doglobal\appendtoks\dodododoGSC[#1:#2]\to\posXCtoks\NC}
-
-\def\dodoGSC[#1]%
- {\def\docommand##1{\dododoGSC[##1:##1]}%
- \processcommalist[#1]\docommand}
-
-\def\dodododoGFC[#1:#2:#3]%
- {\remappositionframed{#2}{\tbPOSprefix#1}%
- \dotablebpos{\tbPOSprefix#1}}
-
-\def\dododoGFC[#1]%
- {\def\docommand##1{\dodododoGFC[##1:##1]}%
- \processcommalist[#1]\docommand}
-
-\def\dodoGFC[#1]%
- {\doglobal\appendtoks\dododoGFC[#1]\to\posXCtoks\NC}
-
-\def\dododododoGTC[#1:#2]%
- {\dotableepos{\tbPOSprefix#1}}
-
-\def\dodododoGTC[#1]%
- {\def\docommand##1{\dododododoGTC[##1:##1]}%
- \processcommalist[#1]\docommand}
-
-\def\dododoGTC[#1]%
- {\doglobal\appendtoks\dodododoGTC[#1]\to\posXCtoks}
-
-\def\dodoGTC[#1]%
- {\doglobal\appendtoks\dododoGTC[#1]\to\posXCtoks\NC}
-
-\def\dodododoXC[#1#2]%
- {\if#1>\dodoGFC [#2:#2]\else
- \if#1+\dodoGFC [#2:#2]\else
- \if#1<\dodoGTC [#2:#2]\else
- \if#1-\dodoGTC [#2:#2]\else
- \if#1=\dodoGSC [#2:#2]\else
- \dodoGSC[#1#2:#1#2]\fi\fi\fi\fi\fi}
-
-\def\dododoXC#1%
- {\dodododoXC[#1]}
-
-\def\dodoXC[#1]%
- {{\let\NC\relax\processcommalist[#1]\dododoXC}}
-
-\def\@@checktablepositionstate
- {\iftrialtypesetting
- \global\settrue\tablehaspositions
- \firstargumentfalse
- \fi}
-
-\def\doGSC[#1]{\@@checktablepositionstate\iffirstargument\dodoGSC[#1]\else\expandafter\NC\fi}
-\def\doGFC[#1]{\@@checktablepositionstate\iffirstargument\dodoGFC[#1]\else\expandafter\NC\fi}
-\def\doGTC[#1]{\@@checktablepositionstate\iffirstargument\dodoGTC[#1]\else\expandafter\NC\fi}
-\def\doXC [#1]{\@@checktablepositionstate\iffirstargument\dodoXC [#1]\else\expandafter\fi\NC}
-
-\def\tbGSC{\dosingleempty\doGSC}
-\def\tbGFC{\dosingleempty\doGFC}
-\def\tbGTC{\dosingleempty\doGTC}
-\def\tbXC {\dosingleempty\doXC }
-
-%D The amount of code to support tables and tabulation is
-%D rather minimalistic.
-
-\let\tabulatepos\tablepos
-
-\def\tabulatenormalpos
- {\iftrialtypesetting
- % nothing
- \else\ifconditional\tablehaspositions
- \hss\tabulatepos\hss
- \else
- % nothing
- \fi\fi}
-
-\def\tabulateequalpos
- {\iftrialtypesetting
- \tabulateEQ
- \else\ifconditional\tablehaspositions
- \tabulateEQpos
- \else
- \tabulateEQ
- \fi\fi}
-
-\def\tabulateEQpos
- {\setbox\scratchbox\hbox{\tabulateEQ}%
- \hbox to \wd\scratchbox{\hss\kern\zeropoint\tabulatepos\hss}%
- \hskip-\wd\scratchbox
- \box\scratchbox}
-
-\appendtoks
- \global\advance\noftabpositions\plusone
- \global\setfalse\tablehaspositions
-\to \everytabulate
-
-% We need to handle paragraphs as well.
-
-\let\doflushtabulateepos\relax
-
-\def\dotabulatebpos
- {\bpos}
-
-\def\dotabulateepos#1%
- {\ifvoid\tablebox\tabulatecolumn
- \epos{#1}%
- \glet\doflushtabulateepos\relax
- \else
- \gdef\doflushtabulateepos{\epos{#1}}%
- \fi}
-
-\def\flushtabulatesplitbox
- {\box\tabulatebox
- \iftrialtypesetting\else\ifconditional\tablehaspositions\doflushtabulateepos\fi\fi}
-
-\appendtoks
- \let\dotablebpos\dotabulatebpos
- \let\dotableepos\dotabulateepos
- \glet\doflushtabulateepos\relax
-\to \everytabulate
-
-%D In order to prevent potential clashes with abbreviations,
-%D postpone the mapping.
-
-\appendtoks
- \let\GSC\tbGSC \let\GFC\tbGFC \let\GTC\tbGTC \let\XC\tbXC
-\to \everytabulate
-
-%D \macros
-%D {definepositionframed}
-%D
-%D The next example show how to provide backgrounds to table
-%D cells. First we define some framed backgrounds.
-%D
-%D \startbuffer
-%D \definepositionframed[x][background=color,backgroundcolor=red]
-%D \definepositionframed[y][background=color,backgroundcolor=green]
-%D \definepositionframed[z][background=color,backgroundcolor=blue]
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D % \getbuffer
-%D
-%D \startbuffer
-%D \starttabulate[|c|c|c|]
-%D \GFC[f:x] this is a small \NC table \NC in which we \NC \FR
-%D \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
-%D \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
-%D \stoptabulate
-%D \stopbuffer
-%D
-%D The table itself defines three areas (a, b and~c) using
-%D these frames.
-%D
-%D \typebuffer
-%D % \getbuffer
-%D
-%D Tables (based on \TABLE) are supported by:
-
-\def\normalTABLEsimplebar {\unskip\!ttRightGlue&\tablepos&} % |
-\def\normalTABLEcomplexbar{\unskip\!ttRightGlue&\omit\tablepos\!ttAlternateVrule} % \|
-\def\normalTABLEquote {\unskip\!ttRightGlue&\omit\tablepos&} % "
-
-\appendtoks
- \global\advance\noftabpositions\plusone
- \global\setfalse\tablehaspositions
-\to \everytable
-
-%D Since we don't want nameclashes:
-
-\appendtoks
- \let\GSC\tbGSC \let\GFC\tbGFC \let\GTC\tbGTC \let\XC\tbXC
-\to \everytable
-
-%D In the previous example, we could have provided an overlay to
-%D the framed definition. A more direct approach is demonstrated
-%D below:
-%D
-%D \startbuffer
-%D \def\cw#1{\color[white]{#1}}
-%D
-%D \startMPpositiongraphic{tableshade}
-%D initialize_area(\MPpos{\MPvar{from}},\MPpos{\MPvar{to}}) ;
-%D color c ; c := \MPvar{color} ;
-%D linear_shade(pxy,0,.4c,.9c) ;
-%D anchor_area(\MPanchor{\MPvar{from}}) ;
-%D \stopMPpositiongraphic
-%D
-%D \setMPpositiongraphic{b:x}{tableshade}{from=b:x,to=e:x,color=red}
-%D \setMPpositiongraphic{b:y}{tableshade}{from=b:y,to=e:y,color=green}
-%D \setMPpositiongraphic{b:z}{tableshade}{from=b:z,to=e:z,color=blue}
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-%D
-%D The definition of the table looks about the same as the
-%D previous one:
-%D
-%D \startbuffer
-%D \starttable[|c|c|c|]
-%D \GFC[b:z] \cw{this is a small} \NC \cw{table} \NC in which we \NC \FR
-%D \NC \cw{will demonstrate} \GFC[c:y] \cw{that this} \GTC[c] \cw{positioning} \NC \MR
-%D \GSC[a:x] \cw{mechanism also} \GTC[b] \cw{works quite well} \NC in tables \NC \LR
-%D \stoptable
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \getbuffer
-
-% \definepositionframed[w][background=color,backgroundcolor=yellow]
-% \definepositionframed[x][background=color,backgroundcolor=red]
-% \definepositionframed[y][background=color,backgroundcolor=green]
-% \definepositionframed[z][background=color,backgroundcolor=blue]
-%
-% \starttabulate[|c|c|c|]
-% \NC this is a small \NC table \NC in which we \NC \FR
-% \NC will demonstrate \NC that this \NC positioning \NC \MR
-% \NC mechanism also \NC works quite well \NC in tables \NC \LR
-% \stoptabulate
-%
-% \starttabulate[|c|c|c|]
-% \GFC[f:x] this is a small \GTC table \NC in which we \NC \FR
-% \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
-% \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
-% \stoptabulate
-%
-% \starttabulate[|c|c|c|]
-% \GFC[f:x,d:w] this is a small \GTC[d] table \NC in which we \NC \FR
-% \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
-% \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
-% \stoptabulate
-%
-% \starttabulate[|c|c|c|]
-% \XC[+f:x] this is a small \XC table \NC in which we \NC \FR
-% \NC will demonstrate \XC[+g:z] that this \XC[-g] positioning \NC \MR
-% \XC[=e:y] mechanism also \XC[-f] works quite well \NC in tables \NC \LR
-% \stoptabulate
-%
-% \starttabulate[|c|c|c|]
-% \XC[+f:x,+d:w] this is a small \XC[-d] table \NC in which we \NC \FR
-% \NC will demonstrate \XC[+g:z] that this \XC[-g] positioning \NC \MR
-% \XC[=e:y] mechanism also \XC[-f] works quite well \NC in tables \NC \LR
-% \stoptabulate
-
-% evt [b:x]
-%
-% \definepositionframed[x][background=color,fillcolor=red]
-% \definepositionframed[y][background=color,fillcolor=green]
-% \definepositionframed[z][background=color,fillcolor=blue]
-
-\def\remappositionframed#1#2% from to
- {\copyposition{b:#1}{b:#2}%
- \copyposition{e:#1}{e:#2}%
- \dosetpositionaction{b:#2}{\dopositionaction{b:#1}}}
-
-\unexpanded\def\definepositionframed
- {\dodoubleargument\dodefinepositionframed}
-
-\def\dodefinepositionframed[#1][#2]%
- {\dosetpositionaction{b:#1}{\dopositionframed[#1][#2]}}
-
-\def\positionframed
- {\dodoubleempty\dopositionframed}
-
-\def\dopositionframed[#1][#2]%
- {\bgroup
- \setbox\scratchbox\hbox
- {\dimen0=\MPx{e:#1}%
- \advance\dimen0 -\MPx{b:#1}%
- \dimen2=\MPy{b:#1}%
- \advance\dimen2 -\MPy{e:#1}%
- \advance\dimen2 \MPd{e:#1}%
- \lower\dimen2\hbox
- {\advance\dimen2 \MPh{b:#1}%
- \framed
- [\c!width=\dimen0,\c!height=\dimen2,
- \c!offset=\v!overlay,#2]{}}}%
- \smashedbox\scratchbox
- \egroup}
-
-% \def\sethdistances#1%
-% {\hbox{\lpos{ml:#1}\hpos{mh:#1}{\strut}\rpos{mr:#1}}}
-%
-% \def\gethdistances#1%
-% {\scratchdimen\MPx{mh:#1}%
-% \advance\scratchdimen -\MPx{ml#1}%
-% \edef\lefthdistance{\the\scratchdimen}%
-% \scratchdimen\MPx{mr:#1}%
-% \advance\scratchdimen -\MPx{mh:#1}%
-% \edef\righthdistance{\the\scratchdimen}}
-
\protect \endinput
-
-% todo 1: shift down option
-
-% \startuseMPgraphic{mpos:par:columnset}
-% \iftracepositions show_multi_pars \else draw_multi_pars \fi ;
-% path p ; p := boundingbox currentpicture ;
-% currentpicture := currentpicture shifted (0,-StrutDepth/2) ;
-% setbounds currentpicture to p ;
-% \stopuseMPgraphic
-
-\definetextbackground[underline] [location=text,alternative=1,background=,frame=off]
-\definetextbackground[overstrike] [location=text,alternative=2,background=,frame=off]
-\definetextbackground[exlines] [location=text,alternative=3,background=,frame=off]
-\definetextbackground[strikethrough][location=text,alternative=4,background=,frame=off]
-
-\definestartstop [underline]
- [before={\starttextbackground[underline]},
- after=\stoptextbackground]
-
-\definestartstop
- [overstrike]
- [before={\starttextbackground[overstrike]},
- after=\stoptextbackground]
-
-\definestartstop
- [exlines]
- [before={\starttextbackground[exlines]},
- after=\stoptextbackground]
-
-\definestartstop
- [strikethrough]
- [before={\starttextbackground[strikethrough]},
- after=\stoptextbackground]
-
-\definetextbackground
- [sideline]
- [mp=mpos:par:sideline,
- location=paragraph,
- framecolor=red,
- frameoffset=5mm]
-
-\definestartstop [sideline]
- [before={\starttextbackground[sideline]},
- after=\stoptextbackground]
-
-\starttext
- \startunderline \input tufte \stopunderline \blank
- \startoverstrike \input tufte \stopoverstrike \blank
- \startexlines \input tufte \stopexlines \blank
- \startstrikethrough \input tufte \stopstrikethrough \blank
- \startsideline \input tufte \stopsideline \blank
-\stoptext
diff --git a/Master/texmf-dist/tex/context/base/anch-pos.lua b/Master/texmf-dist/tex/context/base/anch-pos.lua
index 789e1aefe71..5d01a6e466d 100644
--- a/Master/texmf-dist/tex/context/base/anch-pos.lua
+++ b/Master/texmf-dist/tex/context/base/anch-pos.lua
@@ -12,18 +12,36 @@ can we store much more information in <l n='lua'/> but it's also
more efficient.</p>
--ldx]]--
--- to be considered: store as numbers instead of string
+-- plus (extra) is obsolete but we will keep it for a while
+
-- maybe replace texsp by our own converter (stay at the lua end)
+-- eventually mp will have large numbers so we can use sp there too
-local tostring = tostring
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local tostring, next, rawget, setmetatable = tostring, next, rawget, setmetatable
+local concat, sort = table.concat, table.sort
+local format, gmatch, match = string.format, string.gmatch, string.match
+local rawget = rawget
local lpegmatch = lpeg.match
+local insert, remove = table.insert, table.remove
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
-local texsp = tex.sp
+local texsp, texcount, texbox, texdimen, texsetcount = tex.sp, tex.count, tex.box, tex.dimen, tex.setcount
----- texsp = string.todimen -- because we cache this is much faster but no rounding
-local collected = allocate()
-local tobesaved = allocate()
+local pdf = pdf -- h and v are variables
+
+local setmetatableindex = table.setmetatableindex
+local new_latelua = nodes.pool.latelua
+local find_tail = node.slide
+
+local variables = interfaces.variables
+local v_text = variables.text
+local v_column = variables.column
+
+local pt = number.dimenfactors.pt
+local pts = number.pts
+
+local collected = allocate()
+local tobesaved = allocate()
local jobpositions = {
collected = collected,
@@ -32,186 +50,616 @@ local jobpositions = {
job.positions = jobpositions
-_ptbs_, _pcol_ = tobesaved, collected -- global
+_plib_ = jobpositions -- might go
+
+local default = { -- not r and paragraphs etc
+ __index = {
+ x = 0, -- x position baseline
+ y = 0, -- y position baseline
+ w = 0, -- width
+ h = 0, -- height
+ d = 0, -- depth
+ p = 0, -- page
+ n = 0, -- paragraph
+ ls = 0, -- leftskip
+ rs = 0, -- rightskip
+ hi = 0, -- hangindent
+ ha = 0, -- hangafter
+ hs = 0, -- hsize
+ pi = 0, -- parindent
+ ps = false, -- parshape
+ }
+}
+
+local function sorter(a,b)
+ return a.y > b.y
+end
+
+local nofusedregions = 0
+local nofmissingregions = 0
+local nofregular = 0
-local dx, dy, nx, ny = "0pt", "0pt", 0, 0
+-- todo: register subsets and count them indepently
local function initializer()
tobesaved = jobpositions.tobesaved
collected = jobpositions.collected
- _ptbs_ = tobesaved -- global
- _pcol_ = collected -- global
- -- local p = collected["page:0"] -- page:1
- -- if p then
- -- dx, nx = p[2] or "0pt", 0
- -- dy, ny = p[3] or "0pt", 0
+ -- enhance regions with paragraphs
+ for tag, data in next, collected do
+ local region = data.r
+ if region then
+ local r = collected[region]
+ if r then
+ local paragraphs = r.paragraphs
+ if not paragraphs then
+ r.paragraphs = { data }
+ else
+ paragraphs[#paragraphs+1] = data
+ end
+ nofusedregions = nofusedregions + 1
+ else
+ nofmissingregions = nofmissingregions + 1
+ end
+ else
+ nofregular = nofregular + 1
+ end
+ setmetatable(data,default)
+ end
+ -- add metatable
+ -- for tag, data in next, collected do
+ -- setmetatable(data,default)
-- end
+ -- sort this data
+ for tag, data in next, collected do
+ local region = data.r
+ if region then
+ local r = collected[region]
+ if r then
+ local paragraphs = r.paragraphs
+ if paragraphs and #paragraphs > 1 then
+ sort(paragraphs,sorter)
+ end
+ end
+ end
+ -- so, we can be sparse and don't need 'or 0' code
+ end
end
job.register('job.positions.collected', tobesaved, initializer)
-function jobpositions.copy(target,source)
- collected[target] = collected[source] or tobesaved[source]
+local regions = { }
+local nofregions = 0
+local region = nil
+
+local columns = { }
+local nofcolumns = 0
+local column = nil
+
+local nofpages = nil
+
+-- beware ... we're not sparse here as lua will reserve slots for the nilled
+
+local function setdim(name,w,h,d,extra) -- will be used when we move to sp allover
+ local x = pdf.h
+ local y = pdf.v
+ if x == 0 then x = nil end
+ if y == 0 then y = nil end
+ if w == 0 then w = nil end
+ if h == 0 then h = nil end
+ if d == 0 then d = nil end
+ if extra == "" then extra = nil end
+ -- todo: sparse
+ tobesaved[name] = {
+ p = texcount.realpageno,
+ x = x,
+ y = y,
+ w = w,
+ h = h,
+ d = d,
+ e = extra,
+ r = region,
+ c = column,
+ }
+end
+
+local function setall(name,p,x,y,w,h,d,extra)
+ if x == 0 then x = nil end
+ if y == 0 then y = nil end
+ if w == 0 then w = nil end
+ if h == 0 then h = nil end
+ if d == 0 then d = nil end
+ if extra == "" then extra = nil end
+ -- todo: sparse
+ tobesaved[name] = {
+ p = p,
+ x = x,
+ y = y,
+ w = w,
+ h = h,
+ d = d,
+ e = extra,
+ r = region,
+ c = column,
+ }
+end
+
+local function enhance(data)
+ if not data then
+ return nil
+ end
+ if data.r == true then -- or ""
+ data.r = region
+ end
+ if data.x == true then
+ data.x = pdf.h
+ end
+ if data.y == true then
+ data.y = pdf.v
+ end
+ if data.p == true then
+ data.p = texcount.realpageno
+ end
+ if data.c == true then
+ data.c = column
+ end
+ if data.w == 0 then
+ data.w = nil
+ end
+ if data.h == 0 then
+ data.h = nil
+ end
+ if data.d == 0 then
+ data.d = nil
+ end
+ return data
end
-function jobpositions.replace(name,...)
- collected[name] = {...}
+local function set(name,index,val)
+ local data = enhance(val or index)
+ if val then
+ container = tobesaved[name]
+ if not container then
+ tobesaved[name] = {
+ [index] = data
+ }
+ else
+ container[index] = data
+ end
+ else
+ tobesaved[name] = data
+ end
end
-function jobpositions.page(id)
- local jpi = collected[id] or tobesaved[id]
- if jpi then
- return texsp(jpi[1])
+local function get(id,index)
+ if index then
+ local container = collected[id]
+ return container and container[index]
else
- return 0
+ return collected[id]
end
end
-function jobpositions.x(id)
- local jpi = collected[id] or tobesaved[id]
- if jpi then
- return texsp(jpi[2]) - nx
+jobpositions.setdim = setdim
+jobpositions.setall = setall
+jobpositions.set = set
+jobpositions.get = get
+
+commands.setpos = setall
+
+-- will become private table (could also become attribute driven but too nasty
+-- as attributes can bleed e.g. in margin stuff)
+
+function jobpositions.b_col(tag)
+ tobesaved[tag] = {
+ r = true,
+ x = pdf.h,
+ w = 0,
+ }
+ insert(columns,tag)
+ column = tag
+end
+
+function jobpositions.e_col(tag)
+ local t = tobesaved[column]
+ if not t then
+ -- something's wrong
else
- return 0
+ t.w = pdf.h - t.x
+ t.r = region
end
+ remove(columns)
+ column = columns[#columns]
end
-function jobpositions.y(id)
- local jpi = collected[id] or tobesaved[id]
- if jpi then
- return texsp(jpi[3]) - ny
- else
- return 0
+function commands.bcolumn(tag,register)
+ insert(columns,tag)
+ column = tag
+ if register then
+ context(new_latelua(format("_plib_.b_col(%q)",tag)))
end
end
-function jobpositions.width(id)
- local jpi = collected[id] or tobesaved[id]
- if jpi then
- return texsp(jpi[4])
- else
- return 0
+function commands.ecolumn(register)
+ if register then
+ context(new_latelua("_plib_.e_col()"))
end
+ remove(columns)
+ column = columns[#columns]
end
-function jobpositions.height(id)
- local jpi = collected[id] or tobesaved[id]
- if jpi then
- return texsp(jpi[5])
- else
- return 0
+-- regions
+
+function jobpositions.b_region(tag)
+ local last = tobesaved[tag]
+ last.x = pdf.h
+last.y = pdf.v
+ last.p = texcount.realpageno
+ insert(regions,tag)
+ region = tag
+end
+
+function jobpositions.e_region(correct)
+ local last = tobesaved[region]
+if correct then
+ last.h = last.y - pdf.v
+end
+ last.y = pdf.v
+ remove(regions)
+ region = regions[#regions]
+end
+
+function jobpositions.markregionbox(n,tag,correct)
+ if not tag or tag == "" then
+ nofregions = nofregions + 1
+ tag = format("region:%s",nofregions)
+ end
+ local box = texbox[n]
+ local w = box.width
+ local h = box.height
+ local d = box.depth
+ tobesaved[tag] = {
+ p = true,
+ x = true,
+ y = pdf.v, -- true,
+ w = w ~= 0 and w or nil,
+ h = h ~= 0 and h or nil,
+ d = d ~= 0 and d or nil,
+ }
+ local push = new_latelua(format("_plib_.b_region(%q)",tag))
+ local pop = new_latelua(format("_plib_.e_region(%s)",tostring(correct)))
+ -- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end
+ local head = box.list
+ if head then
+ local tail = find_tail(head)
+ head.prev = push
+ push.next = head
+ pop .prev = tail
+ tail.next = pop
+ else -- we can have a simple push/pop
+ push.next = pop
+ pop.prev = push
+ end
+ box.list = push
+end
+
+function jobpositions.enhance(name)
+ enhance(tobesaved[name])
+end
+
+function commands.pos(name,t)
+ tobesaved[name] = t
+ context(new_latelua(format("_plib_.enhance(%q)",name)))
+end
+
+local nofparagraphs = 0
+
+function commands.parpos() -- todo: relate to localpar (so this is an intermediate variant)
+ nofparagraphs = nofparagraphs + 1
+ texsetcount("global","c_anch_positions_paragraph",nofparagraphs)
+ local strutbox = texbox.strutbox
+ local t = {
+ p = true,
+ c = true,
+ r = true,
+ x = true,
+ y = true,
+ h = strutbox.height,
+ d = strutbox.depth,
+ hs = tex.hsize,
+ }
+ local leftskip = tex.leftskip.width
+ local rightskip = tex.rightskip.width
+ local hangindent = tex.hangindent
+ local hangafter = tex.hangafter
+ local parindent = tex.parindent
+ local parshape = tex.parshape
+ if leftskip ~= 0 then
+ t.ls = leftskip
+ end
+ if rightskip ~= 0 then
+ t.rs = rightskip
end
+ if hangindent ~= 0 then
+ t.hi = hangindent
+ end
+ if hangafter ~= 1 and hangafter ~= 0 then -- can not be zero .. so it needs to be 1 if zero
+ t.ha = hangafter
+ end
+ if parindent ~= 0 then
+ t.pi = parindent
+ end
+ if parshape and #parshape > 0 then
+ t.ps = parshape
+ end
+ local tag = format("p:%s",nofparagraphs)
+ tobesaved[tag] = t
+ context(new_latelua(format("_plib_.enhance(%q)",tag)))
+end
+
+function commands.posxy(name) -- can node.write be used here?
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ }
+ context(new_latelua(format("_plib_.enhance(%q)",name)))
+end
+
+function commands.poswhd(name,w,h,d)
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ w = w,
+ h = h,
+ d = d,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ }
+ context(new_latelua(format("_plib_.enhance(%q)",name)))
+end
+
+function commands.posplus(name,w,h,d,extra)
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ w = w,
+ h = h,
+ d = d,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ e = extra,
+ }
+ context(new_latelua(format("_plib_.enhance(%q)",name)))
+end
+
+function commands.posstrut(name,w,h,d)
+ local strutbox = texbox.strutbox
+ tobesaved[name] = {
+ p = true,
+ c = column,
+ r = true,
+ x = true,
+ y = true,
+ h = strutbox.height,
+ d = strutbox.depth,
+ n = nofparagraphs > 0 and nofparagraphs or nil,
+ }
+ context(new_latelua(format("_plib_.enhance(%q)",name)))
+end
+
+function jobpositions.getreserved(tag,n)
+ if tag == v_column then
+ local fulltag = format("%s:%s:%s",tag,texcount.realpageno,n or 1)
+ local data = collected[fulltag]
+ if data then
+ return data, fulltag
+ end
+ tag = v_text
+ end
+ if tag == v_text then
+ local fulltag = format("%s:%s",tag,texcount.realpageno)
+ return collected[fulltag] or false, fulltag
+ end
+ return collected[tag] or false, tag
+end
+
+function jobpositions.copy(target,source)
+ collected[target] = collected[source]
+end
+
+function jobpositions.replace(id,p,x,y,w,h,d)
+ collected[id] = { p = p, x = x, y = y, w = w, h = h, d = d } -- c g
+end
+
+function jobpositions.page(id)
+ local jpi = collected[id]
+ return jpi and jpi.p
+end
+
+function jobpositions.region(id)
+ local jpi = collected[id]
+ return jpi and jpi.r or false
+end
+
+function jobpositions.column(id)
+ local jpi = collected[id]
+ return jpi and jpi.c or false
+end
+
+function jobpositions.paragraph(id)
+ local jpi = collected[id]
+ return jpi and jpi.n
+end
+
+jobpositions.p = jobpositions.page
+jobpositions.r = jobpositions.region
+jobpositions.c = jobpositions.column
+jobpositions.n = jobpositions.paragraph
+
+function jobpositions.x(id)
+ local jpi = collected[id]
+ return jpi and jpi.x
+end
+
+function jobpositions.y(id)
+ local jpi = collected[id]
+ return jpi and jpi.y
+end
+
+function jobpositions.width(id)
+ local jpi = collected[id]
+ return jpi and jpi.w
+end
+
+function jobpositions.height(id)
+ local jpi = collected[id]
+ return jpi and jpi.h
end
function jobpositions.depth(id)
- local jpi = collected[id] or tobesaved[id]
- if jpi then
- return texsp(jpi[6])
- else
- return 0
- end
+ local jpi = collected[id]
+ return jpi and jpi.d
+end
+
+function jobpositions.leftskip(id)
+ local jpi = collected[id]
+ return jpi and jpi.ls
+end
+
+function jobpositions.rightskip(id)
+ local jpi = collected[id]
+ return jpi and jpi.rs
+end
+
+function jobpositions.hsize(id)
+ local jpi = collected[id]
+ return jpi and jpi.hs
+end
+
+function jobpositions.parindent(id)
+ local jpi = collected[id]
+ return jpi and jpi.pi
+end
+
+function jobpositions.hangindent(id)
+ local jpi = collected[id]
+ return jpi and jpi.hi
+end
+
+function jobpositions.hangafter(id)
+ local jpi = collected[id]
+ return jpi and jpi.ha or 1
end
function jobpositions.xy(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- return texsp(jpi[2]) - nx, texsp(jpi[3]) - ny
+ return jpi.x, jpi.y
else
return 0, 0
end
end
function jobpositions.lowerleft(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- return texsp(jpi[2]) - nx, texsp(jpi[3]) - texsp(jpi[6]) - ny
+ return jpi.x, jpi.y - jpi.d
else
return 0, 0
end
end
function jobpositions.lowerright(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- return texsp(jpi[2]) + texsp(jpi[4]) - nx, texsp(jpi[3]) - texsp(jpi[6]) - ny
+ return jpi.x + jpi.w, jpi.y - jpi.d
else
return 0, 0
end
end
function jobpositions.upperright(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- return texsp(jpi[2]) + texsp(jpi[4]) - nx, texsp(jpi[3]) + texsp(jpi[5]) - ny
+ return jpi.x + jpi.w, jpi.y + jpi.h
else
return 0, 0
end
end
function jobpositions.upperleft(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- return texsp(jpi[2]) - nx, texsp(jpi[3]) + texsp(jpi[5]) - ny
+ return jpi.x, jpi.y + jpi.h
else
return 0, 0
end
end
function jobpositions.position(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- return texsp(jpi[1]), texsp(jpi[2]), texsp(jpi[3]), texsp(jpi[4]), texsp(jpi[5]), texsp(jpi[6])
+ return jpi.p, jpi.x, jpi.y, jpi.w, jpi.h, jpi.d
else
return 0, 0, 0, 0, 0, 0
end
end
function jobpositions.extra(id,n,default) -- assume numbers
- local jpi = collected[id] or tobesaved[id]
- if not jpi then
- return default
- else
- local split = jpi[0]
- if not split then
- split = lpegmatch(splitter,jpi[7])
- jpi[0] = split
+ local jpi = collected[id]
+ if jpi then
+ local e = jpi.e
+ if e then
+ local split = jpi.split
+ if not split then
+ split = lpegmatch(splitter,jpi.e)
+ jpi.split = split
+ end
+ return texsp(split[n]) or default -- watch the texsp here
end
- return texsp(split[n]) or default
end
+ return default
end
-local function overlapping(one,two,overlappingmargin)
- one = collected[one] or tobesaved[one]
- two = collected[two] or tobesaved[two]
- if one and two and one[1] == two[1] then
+local function overlapping(one,two,overlappingmargin) -- hm, strings so this is wrong .. texsp
+ one = collected[one]
+ two = collected[two]
+ if one and two and one.p == two.p then
if not overlappingmargin then
overlappingmargin = 2
end
- local x_one = one[2]
- local x_two = two[2]
- local w_two = two[4]
+ local x_one = one.x
+ local x_two = two.x
+ local w_two = two.w
local llx_one = x_one - overlappingmargin
local urx_two = x_two + w_two + overlappingmargin
if llx_one > urx_two then
return false
end
- local w_one = one[4]
+ local w_one = one.w
local urx_one = x_one + w_one + overlappingmargin
local llx_two = x_two - overlappingmargin
if urx_one < llx_two then
return false
end
- local y_one = one[3]
- local y_two = two[3]
- local d_one = one[6]
- local h_two = two[5]
+ local y_one = one.y
+ local y_two = two.y
+ local d_one = one.d
+ local h_two = two.h
local lly_one = y_one - d_one - overlappingmargin
local ury_two = y_two + h_two + overlappingmargin
if lly_one > ury_two then
return false
end
- local h_one = one[5]
- local d_two = two[6]
+ local h_one = one.h
+ local d_two = two.d
local ury_one = y_one + h_one + overlappingmargin
local lly_two = y_two - d_two - overlappingmargin
if ury_one < lly_two then
@@ -223,10 +671,12 @@ end
local function onsamepage(list,page)
for id in gmatch(list,"(, )") do
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- local p = jpi[1]
- if not page then
+ local p = jpi.p
+ if not p then
+ return false
+ elseif not page then
page = p
elseif page ~= p then
return false
@@ -245,132 +695,293 @@ commands.replacepospxywhd = jobpositions.replace
commands.copyposition = jobpositions.copy
function commands.MPp(id)
- local jpi = collected[id] or tobesaved[id]
- context(jpi and jpi[1] or '0')
+ local jpi = collected[id]
+ if jpi then
+ local p = jpi.p
+ if p and p ~= true then
+ context(p)
+ return
+ end
+ end
+ context('0')
end
function commands.MPx(id)
- local jpi = collected[id] or tobesaved[id]
- local x = jpi and jpi[2]
- if x then
- if nx == 0 then
- context(x)
- else
- context('\\the\\dimexpr%s-%s\\relax',x,dx)
+ local jpi = collected[id]
+ if jpi then
+ local x = jpi.x
+ if x and x ~= true and x ~= 0 then
+ context("%.5fpt",x*pt)
+ return
end
- else
- context('0pt')
end
+ context('0pt')
end
function commands.MPy(id)
- local jpi = collected[id] or tobesaved[id]
- local y = jpi and jpi[3]
- if y then
- if ny == 0 then
- context(y)
- else
- context('\\the\\dimexpr%s-%s\\relax',y,dy)
+ local jpi = collected[id]
+ if jpi then
+ local y = jpi.y
+ if y and y ~= true and y ~= 0 then
+ context("%.5fpt",y*pt)
+ return
end
- else
- context('0pt')
end
+ context('0pt')
end
function commands.MPw(id)
- local jpi = collected[id] or tobesaved[id]
- context(jpi and jpi[4] or '0pt')
+ local jpi = collected[id]
+ if jpi then
+ local w = jpi.w
+ if w and w ~= 0 then
+ context("%.5fpt",w*pt)
+ return
+ end
+ end
+ context('0pt')
end
function commands.MPh(id)
- local jpi = collected[id] or tobesaved[id]
- context(jpi and jpi[5] or '0pt')
+ local jpi = collected[id]
+ if jpi then
+ local h = jpi.h
+ if h and h ~= 0 then
+ context("%.5fpt",h*pt)
+ return
+ end
+ end
+ context('0pt')
end
function commands.MPd(id)
- local jpi = collected[id] or tobesaved[id]
- context(jpi and jpi[6] or '0pt')
+ local jpi = collected[id]
+ if jpi then
+ local d = jpi.d
+ if d and d ~= 0 then
+ context("%.5fpt",d*pt)
+ return
+ end
+ end
+ context('0pt')
end
function commands.MPxy(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- context('(%s-%s,%s-%s)',jpi[2],dx,jpi[3],dy)
+ context('(%.5fpt,%.5fpt)',
+ jpi.x*pt,
+ jpi.y*pt
+ )
else
context('(0,0)')
end
end
function commands.MPll(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- context('(%s-%s,%s-%s-%s)',jpi[2],dx,jpi[3],jpi[6],dy)
+ context('(%.5fpt,%.5fpt)',
+ jpi.x *pt,
+ (jpi.y-jpi.d)*pt
+ )
else
- context('(0,0)')
+ context('(0,0)') -- for mp only
end
end
function commands.MPlr(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- context('(%s+%s-%s,%s-%s-%s)',jpi[2],jpi[4],dx,jpi[3],jpi[6],dy)
+ context('(%.5fpt,%.5fpt)',
+ (jpi.x + jpi.w)*pt,
+ (jpi.y - jpi.d)*pt
+ )
else
- context('(0,0)')
+ context('(0,0)') -- for mp only
end
end
function commands.MPur(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- context('(%s+%s-%s,%s+%s-%s)',jpi[2],jpi[4],dx,jpi[3],jpi[5],dy)
+ context('(%.5fpt,%.5fpt)',
+ (jpi.x + jpi.w)*pt,
+ (jpi.y + jpi.h)*pt
+ )
else
- context('(0,0)')
+ context('(0,0)') -- for mp only
end
end
function commands.MPul(id)
- local jpi = collected[id] or tobesaved[id]
+ local jpi = collected[id]
if jpi then
- context('(%s-%s,%s+%s-%s)',jpi[2],dx,jpi[3],jpi[5],dy)
+ context('(%.5fpt,%.5fpt)',
+ jpi.x *pt,
+ (jpi.y + jpi.h)*pt
+ )
else
- context('(0,0)')
+ context('(0,0)') -- for mp only
+ end
+end
+
+local function MPpos(id)
+ local jpi = collected[id]
+ if jpi then
+ local p = jpi.p
+ if p then
+ context("%s,%.5fpt,%.5fpt,%.5fpt,%.5fpt,%.5fpt",
+ p,
+ jpi.x*pt,
+ jpi.y*pt,
+ jpi.w*pt,
+ jpi.h*pt,
+ jpi.d*pt
+ )
+ return
+ end
+ end
+ context('0,0,0,0,0,0') -- for mp only
+end
+
+commands.MPpos = MPpos
+
+function commands.MPn(id)
+ local jpi = collected[id]
+ if jpi then
+ local n = jpi.n
+ if n then
+ context(n)
+ return
+ end
end
+ context(0)
end
-function commands.MPpos(id)
- local jpi = collected[id] or tobesaved[id]
+function commands.MPc(id)
+ local jpi = collected[id]
if jpi then
- context(concat(jpi,',',1,6))
+ local c = jpi.c
+ if c and p ~= true then
+ context(c)
+ return
+ end
+ end
+ context(c) -- number
+end
+
+function commands.MPr(id)
+ local jpi = collected[id]
+ if jpi then
+ local r = jpi.r
+ if r and p ~= true then
+ context(r)
+ return
+ end
+ end
+end
+
+local function MPpardata(n)
+ local t = collected[n]
+ if not t then
+ local tag = format("p:%s",n)
+ t = collected[tag]
+ end
+ if t then
+ context("%.5fpt,%.5fpt,%.5fpt,%.5fpt,%s,%.5fpt",
+ t.hs*pt,
+ t.ls*pt,
+ t.rs*pt,
+ t.hi*pt,
+ t.ha,
+ t.pi*pt
+ )
else
- context('0,0,0,0,0,0')
+ context("0,0,0,0,0,0") -- for mp only
end
end
-local splitter = lpeg.Ct(lpeg.splitat(","))
+commands.MPpardata = MPpardata
-function commands.MPplus(id,n,default)
- local jpi = collected[id] or tobesaved[id]
- if not jpi then
- context(default)
+function commands.MPposset(id) -- special helper, used in backgrounds
+ local b = format("b:%s",id)
+ local e = format("e:%s",id)
+ local w = format("w:%s",id)
+ local p = format("p:%s",jobpositions.n(b))
+ MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p)
+end
+
+function commands.MPls(id)
+ local t = collected[id]
+ if t then
+ context("%.5fpt",t.ls*pt)
else
- local split = jpi[0]
- if not split then
- split = lpegmatch(splitter,jpi[7])
- jpi[0] = split
+ context("0pt")
+ end
+end
+
+function commands.MPrs(id)
+ local t = collected[id]
+ if t then
+ context("%.5fpt",t.rs*pt)
+ else
+ context("0pt")
+ end
+end
+
+local splitter = lpeg.tsplitat(",")
+
+function commands.MPplus(id,n,default)
+ local jpi = collected[id]
+ if jpi then
+ local e = jpi.e
+ if e then
+ local split = jpi.split
+ if not split then
+ split = lpegmatch(splitter,jpi.e)
+ jpi.split = split
+ end
+ context(split[n] or default)
+ return
end
- context(split[n] or default)
end
+ context(default)
end
function commands.MPrest(id,default)
- local jpi = collected[id] or tobesaved[id]
- context(jpi and jpi[7] or default)
+ local jpi = collected[id]
+ context(jpi and jpi.e or default)
+end
+
+function commands.MPxywhd(id)
+ local t = collected[id]
+ if t then
+ context("%.5fpt,%.5fpt,%.5fpt,%.5fpt,%.5fpt",
+ t.x*pt,
+ t.y*pt,
+ t.w*pt,
+ t.h*pt,
+ t.d*pt
+ )
+ else
+ context("0,0,0,0,0") -- for mp only
+ end
end
-- is testcase already defined? if so, then local
function commands.doifpositionelse(name)
- commands.testcase(collected[name] or tobesaved[name])
+ commands.doifelse(collected[name])
+end
+
+function commands.doifposition(name)
+ commands.doif(collected[name])
+end
+
+function commands.doifpositiononpage(name,page) -- probably always realpageno
+ local c = collected[name]
+ commands.testcase(c and c.p == page)
end
function commands.doifoverlappingelse(one,two,overlappingmargin)
@@ -384,3 +995,22 @@ end
function commands.doifpositionsonthispageelse(list)
commands.testcase(onsamepage(list,tostring(tex.count.realpageno)))
end
+
+function commands.doifelsepositionsused()
+ commands.testcase(next(collected))
+end
+
+commands.markcolumnbox = jobpositions.markcolumnbox
+commands.markregionbox = jobpositions.markregionbox
+
+-- statistics (at least for the moment, when testing)
+
+statistics.register("positions", function()
+ local total = nofregular + nofusedregions + nofmissingregions
+ if total > 0 then
+ return format("%s collected, %s regulars, %s regions, %s unresolved regions",
+ total, nofregular, nofusedregions, nofmissingregions)
+ else
+ return nil
+ end
+end)
diff --git a/Master/texmf-dist/tex/context/base/anch-pos.mkii b/Master/texmf-dist/tex/context/base/anch-pos.mkii
index c793f7ba4a8..b86cee5cc03 100644
--- a/Master/texmf-dist/tex/context/base/anch-pos.mkii
+++ b/Master/texmf-dist/tex/context/base/anch-pos.mkii
@@ -5,7 +5,7 @@
%D subtitle=Positioning Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/anch-pos.mkiv b/Master/texmf-dist/tex/context/base/anch-pos.mkiv
index dc231bcff82..2e13eeba2cc 100644
--- a/Master/texmf-dist/tex/context/base/anch-pos.mkiv
+++ b/Master/texmf-dist/tex/context/base/anch-pos.mkiv
@@ -5,211 +5,86 @@
%D subtitle=Positioning Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
-% needs a cleanup, things may change; we also need to move the mp
-% related code to meta-pos
-
-% shorter tags, ..:achtergrond:.. etc in pos actions
-% dubbele text- * pos's eruit
-
-% class pos -> als gelijk aan vorige, dan niet niet definieren
-% en erven, maw:
-%
-% 1 -> opslaan
-% 2 -> undef, dus == prev
-% 3 -> undef, dus == prev
-% 4 -> opslaan
-
\writestatus{loading}{ConTeXt Anchoring Macros / Positioning}
-% saveposition : tag page x y
-% savepositionwhd : tag page x y w h d
-% savepositionplus : tag page x y w h d list
-%
-% at some point (when we no longer share code) we will move to numbers
-% do that we have less garbage collection and hashing
-%
-% the global table _ptbs_ is equivalent to job.positions.tobesaved
-% the global table _pcol_ is equivalent to job.positions.collected
-%
-% btw, using a function is more efficient than passing longer code
-% snippets to ctxlua
+%D In \MKIV\ there was already a different housekeeping model for positions quite
+%D early, but starting in 2012 more dramatic changes started to happen, especially
+%D in relation to background graphics. It will probably take some time to settle.
\registerctxluafile{anch-pos}{1.001}
-% todo: topskip als optie voor eerste regel achtergrond
-% todo: build pos layers on top of layers
-% todo: positionlayer pos van text-1 etc delen
-
-%D Although \TEX\ has a rather powerful channel to the outside
-%D world, called \type {\special}, real communication with
-%D other programs is complicated by the fact that no positional
-%D information is available. Mid 1999, I discussed this with
-%D \THANH, the author of \PDFTEX, and after some experiments,
-%D \PDFTEX\ was extended with a simple but effective mechanism,
-%D that provided positional information. The interesting
-%D thought is that, although \TEX\ is frozen, similar
-%D functionality could have been achieved with \type
-%D {\specials} and an additional \DVI\ postprocessor.
-%D
-%D Since we want to be as compatible as can be, \CONTEXT\ will
-%D support both methods, although the development is primarily
-%D driven by the \PDFTEX\ way of doing things. Since the
-%D mechanism is basically not limited to one application, for
-%D the moment we stick to building the functionality around one
-%D \CONTEXT\ special command, but at the same time we keep our
-%D eyes open for extensions in other directions.
-%D
-%D A question that may arise when one reads this module, is to
-%D what extend these macros are generic, in the sense that they
-%D could be collected in a support module instead of a core
-%D module. Since the mechanism described here will closely
-%D cooperate with the \METAPOST\ support built in \CONTEXT,
-%D which in turn will be tightly integrated with the \CONTEXT\
-%D overlay mechanisms, I decided to write a core module instead
-%D of a support one. This makes even more sense, when one takes
-%D into account that this kind of support depends on special
-%D drivers.
-
\unprotect
-%D The first application of positional information was embedded
-%D graphics. Since we are interacting with text, it made sense
-%D to take the current line height and depth into account too.
-%D This is why we have two basic position macros: one for
-%D simple positions, and one for boxes.
-%D
-%D We could have sticked to one special, and actually did so in
-%D earlier experiments, but for convenience, as well for
-%D clearness, we now have two alternatives. This approach will
-%D save us quite some bytes when storing large quantities of
-%D positional information. We save as less information as
-%D needed, that is, we save no dimensions, in a \METAPOST\
-%D friendly way.
-%D
-%D The three specials involved are:
+%D The first application of positional information was embedded graphics. Since we
+%D are interacting with text, it made sense to take the current line height and
+%D depth into account too. This is why we have position macros for simple positions
+%D and one boxes.
%D
%D \starttyping
%D \dosetposition {identifier}
%D \dosetpositionwhd {identifier} {width} {height} {depth}
%D \dosetpositionplus {identifier} {width} {height} {depth} {list}
-%D \dosetpositionpapersize {width} {height}
%D \stoptyping
-%D
-%D Positions are either generated at a delayed write time
-%D (in \PDFTEX), or derived from the dvi file. The actual
-%D method is implemented in a special driver. If needed, the
-%D driver can fall back on the following macros.
-
-\def\dolazysaveposition #1#2#3#4{\normalexpanded{\ctxlatelua{_ptbs_['#1']={#2,"#3","#4"}}}}
-\def\dolazysavepositionwhd #1#2#3#4#5#6#7{\normalexpanded{\ctxlatelua{_ptbs_['#1']={#2,"#3","#4","#5","#6","#7"}}}}
-\def\dolazysavepositionplus#1#2#3#4#5#6#7#8{\normalexpanded{\ctxlatelua{_ptbs_['#1']={#2,"#3","#4","#5","#6","#7","#8"}}}}
-\def\dosaveposition #1#2#3#4{\normalexpanded{\ctxlua {_ptbs_['#1']={#2,"#3","#4"}}}}
-\def\dosavepositionwhd #1#2#3#4#5#6#7{\normalexpanded{\ctxlua {_ptbs_['#1']={#2,"#3","#4","#5","#6","#7"}}}}
-\def\dosavepositionplus #1#2#3#4#5#6#7#8{\normalexpanded{\ctxlua {_ptbs_['#1']={#2,"#3","#4","#5","#6","#7","#8"}}}}
-
-\def\lastsavedpositionx {\the\dimexpr\pdflastxpos\scaledpoint\relax}
-\def\lastsavedpositiony {\the\dimexpr\pdflastypos\scaledpoint\relax}
-\let\savecurrentposition\pdfsavepos
-
-\def\dosetposition#1% will become commands.setposition
- {\savecurrentposition
- \normalexpanded{\ctxlatelua{_ptbs_['#1']={%
- \noexpand\realfolio,"\noexpand\lastsavedpositionx","\noexpand\lastsavedpositiony"}}}}
-
-\def\dosetpositionwhd#1#2#3#4%
- {\savecurrentposition
- \normalexpanded{\ctxlatelua{_ptbs_['#1']={%
- \noexpand\realfolio,"\noexpand\lastsavedpositionx","\noexpand\lastsavedpositiony","#2","#3","#4"}}}}
-\def\dosetpositionplus#1#2#3#4#5%
- {\savecurrentposition
- \normalexpanded{\ctxlatelua{_ptbs_['#1']={%
- \noexpand\realfolio,"\noexpand\lastsavedpositionx","\noexpand\lastsavedpositiony","#2","#3","#4","#5"}}}}
+\def\dosaveposition #1#2#3#4{\ctxcommand{setpos("#1",\number#2,\number\dimexpr#3,\number\dimexpr#4)}}
+\def\dosavepositionwhd #1#2#3#4#5#6#7{\ctxcommand{setpos("#1",\number#2,\number\dimexpr#3,\number\dimexpr#4,\number\dimexpr#5,\number\dimexpr#6,\number\dimexpr#7)}}
+\def\dosavepositionplus#1#2#3#4#5#6#7#8{\ctxcommand{setpos("#1",\number#2,\number\dimexpr#3,\number\dimexpr#4,\number\dimexpr#5,\number\dimexpr#6,\number\dimexpr#7,"#8")}}
-\let\dosetpositionpapersize\gobbletwoarguments
+\def\dosetposition #1{\ctxcommand{posxy("#1")}}
+\def\dosetpositionwhd #1#2#3#4{\ctxcommand{poswhd("#1",\number\dimexpr#2,\number\dimexpr#3,\number\dimexpr#4)}}
+\def\dosetpositionplus#1#2#3#4#5{\ctxcommand{posplus("#1",\number\dimexpr#2,\number\dimexpr#3,\number\dimexpr#4,"#5")}}
+\def\dosetpositionbox #1#2{\ctxcommand{poswhd("#1",\number\wd#2,\number\ht#2,\number\dp#2)}}
+\def\dosetpositionstrut #1{\ctxcommand{posstrut("#1")}}
-\newbox\positionbox
-\newif \ifpositioning
-
-\def\POSprefix{POS::}
-
-\let\setpospx \gobblefourarguments % suppress errors with mkii tuo file
-\let\setpospxywhd \gobblesevenarguments % suppress errors with mkii tuo file
-\let\setpospxyplus\gobbleeightarguments % suppress errors with mkii tuo file
-
-%D This is real tricky! The page anchor is applied to the
-%D page box and therefore flushed first. So, when present, it
-%D is applied to all positions except itself.
-
-% 0 = don't relocate page origin 1 = relocate page origin once
-
-\setnewconstant\positionanchormode\plusone
+\newbox\b_anch_position
+\newif \ifpositioning % sort of public
%D Sometimes we want to trick the position handler a bit:
-\def\replacepospxywhd#1#2#3#4#5#6#7{\ctxcommand{replacepospxywhd('#1',\number#2,"\the\dimexpr#3\relax","\the\dimexpr#4\relax","\the\dimexpr#5\relax","\the\dimexpr#6\relax","\the\dimexpr#7\relax")}}
-
-%D For postprocessing purposes, we save the number of
-%D positions.
-
-\newcount\currentpositions % current number of positions
-
-%D The next switch can be used to communicate a special
-%D situation. Positioning and associated actions can be
-%D executed any time. However, in for instance backgrounds
-%D they can be collected in a layer, for instance the text
-%D layer (especially the hidden text layer). In the case of
-%D floats, we run into problems, since the page information is
-%D not applicable when the content floats indeed. In such
-%D situations one can treat positions and graphics local.
-
-\newif\iflocalpositioning % todo: conditional
-
-%D Watch out: sometimes a pagebreak occurs inside a float
-%D placement, so there we need to disable local mode.
-
-\appendtoks
- \localpositioningtrue
-\to \everyinsidefloat
-
-\appendtoks
- \localpositioningfalse
-\to \everypagebody
+\def\replacepospxywhd#1#2#3#4#5#6#7% when used we can better make a helper
+ {\ctxcommand{replacepospxywhd('#1',\number#2,\number\dimexpr#3,\number\dimexpr#4,\number\dimexpr#5,\number\dimexpr#6,\number\dimexpr#7)}}
%D \macros
-%D {MPp, MPx, MPy, MPw, MPh, MPd,
-%D MPxy, MPll, MPlr, MPur, MPul, MPpos}
+%D {MPp, MPx, MPy, MPw, MPh, MPd, MPxy, MPll, MPlr, MPur, MPul, MPpos, MPanchor}
%D
-%D Access to the positional information is provided by macros
-%D with short names that are clearly meant for \METAPOST\ but
-%D nowadays also used for other purposes.
-
-\def\MPp #1{\ctxcommand{MPp("#1")}}
-\def\MPx #1{\ctxcommand{MPx("#1")}}
-\def\MPy #1{\ctxcommand{MPy("#1")}}
-\def\MPw #1{\ctxcommand{MPw("#1")}}
-\def\MPh #1{\ctxcommand{MPh("#1")}}
-\def\MPd #1{\ctxcommand{MPd("#1")}}
-\def\MPxy #1{\ctxcommand{MPxy("#1")}}
-\def\MPll #1{\ctxcommand{MPll("#1")}}
-\def\MPlr #1{\ctxcommand{MPlr("#1")}}
-\def\MPur #1{\ctxcommand{MPur("#1")}}
-\def\MPul #1{\ctxcommand{MPul("#1")}}
-\def\MPpos#1{\ctxcommand{MPpos("#1")}}
+%D Access to the positional information is provided by macros with short names
+%S that are clearly meant for \METAPOST\ but nowadays also used for other purposes.
+
+\def\MPp #1{\ctxcommand{MPp("#1")}} \let\MPpage \MPp
+\def\MPr #1{\ctxcommand{MPr("#1")}} \let\MPregion \MPr
+\def\MPc #1{\ctxcommand{MPc("#1")}} \let\MPcolumn \MPc
+\def\MPn #1{\ctxcommand{MPn("#1")}} \let\MPparagraph\MPn
+\def\MPx #1{\ctxcommand{MPx("#1")}}
+\def\MPy #1{\ctxcommand{MPy("#1")}}
+\def\MPw #1{\ctxcommand{MPw("#1")}} % first we need to replace \MPwidth etc
+\def\MPh #1{\ctxcommand{MPh("#1")}}
+\def\MPd #1{\ctxcommand{MPd("#1")}}
+\def\MPxy #1{\ctxcommand{MPxy("#1")}}
+\def\MPll #1{\ctxcommand{MPll("#1")}}
+\def\MPlr #1{\ctxcommand{MPlr("#1")}}
+\def\MPur #1{\ctxcommand{MPur("#1")}}
+\def\MPul #1{\ctxcommand{MPul("#1")}}
+\def\MPpos #1{\ctxcommand{MPpos("#1")}} \let\MPanchor\MPpos % overloaded locally when needed
+\def\MPe #1{\ctxcommand{MPe("#1")}}
+
+\def\MPls #1{\ctxcommand{MPls("#1")}} \let\MPleftskip\MPls % compatible feature
+\def\MPrs #1{\ctxcommand{MPrs("#1")}} \let\MPrightkip\MPrs % compatible feature
+
+\def\MPpardata#1{\ctxcommand{MPpardata("#1")}}
+\def\MPxywhd #1{\ctxcommand{MPxywhd("#1")}}
%D \macros
%D {MPplus, MPrest, MPv, MPvv}
%D
-%D Since we will probably keep on extending, we provide a
-%D general extension macro. The plus alternative takes an
-%D extra argument, denoting what additional parameter to pick
-%D up. So, the third extra is fetched with,
+%D Since we will probably keep on extending, we provide a general extension
+%D macro. The plus alternative takes an extra argument, denoting what additional
+%D parameter to pick up. So, the third extra is fetched with,
%D
%D \starttyping
%D \MPplus{identifier}{3}{default}
@@ -226,429 +101,305 @@
\def\MPplus#1#2#3{\ctxcommand{MPplus("#1",#2,"#3")}} \let\MPv \MPplus
\def\MPrest #1#2{\ctxcommand{MPrest("#1","#2")}} \let\MPvv\MPrest
-%D \macros
-%D {MPanchor}
-%D
-%D For readability we define a few synonyms:
+%D There are two low level positioning macros. Both store the position as well
+%D as execute an action associated with that position.
-\def\MPanchor{\MPpos}
+\let\dopositionaction\gobbleoneargument % implemented later
-%D There are two low level positioning macros. Both store the
-%D position as well as execute an action associated with that
-%D position.
-
-\def\initializenextposition
+\def\anch_positions_initialize
{\ifpositioning \else
\global\positioningtrue
- \dosetpositionpapersize\printpaperwidth\printpaperheight
- \fi
- \global\advance\currentpositions\plusone}
+ \fi}
-\def\setpositiononly#1%
+\unexpanded\def\setpositiononly
{\iftrialtypesetting
- % nothing
+ \expandafter\gobbleoneargument
\else
- \initializenextposition
- \def\currentposition{#1}%
- \dosetposition\currentposition
+ \expandafter\anch_positions_set_only_indeed
\fi}
-\def\setposition#1%
+\def\anch_positions_set_only_indeed#1%
+ {\anch_positions_initialize
+ \edef\currentposition{#1}%
+ \dosetposition\currentposition}
+
+\unexpanded\def\setposition
{\iftrialtypesetting
- % nothing
+ \expandafter\gobbleoneargument
\else
- \initializenextposition
- \def\currentposition{#1}%
- \dosetposition\currentposition
- \traceposstring\llap\green{\currentposition>}%
- \dopositionaction\currentposition
+ \expandafter\anch_positions_set_indeed
\fi}
-\def\setpositiondata#1#2#3#4%
- {\iftrialtypesetting \else
- \initializenextposition
- \hbox
- {\def\currentposition{#1}%
- \dosetpositionwhd\currentposition
- {\the\dimexpr#2\relax}%
- {\the\dimexpr#3\relax}%
- {\the\dimexpr#4\relax}%
- \traceposstring\llap\green{\currentposition>}%
- \dopositionaction\currentposition
- \hss}%
- \fi}
+\def\anch_positions_set_indeed#1%
+ {\anch_positions_initialize
+ \edef\currentposition{#1}%
+ \dosetposition\currentposition
+ \anch_positions_trace_left
+ \dopositionaction\currentposition}
-\def\setpositionbox#1%
- {\dowithnextbox
- {\iftrialtypesetting
- \flushnextbox
- \else
- \initializenextposition
- \hbox to \nextboxwd
- {\edef\currentposition{#1}%
- \dosetpositionwhd\currentposition
- {\the\nextboxwd}%
- {\the\nextboxht}%
- {\the\nextboxdp}%
- \traceposstring\llap\green{\currentposition>}%
- \setbox\positionbox\flushnextbox
- \dopositionaction\currentposition
- \box\positionbox
- \hss}%
- \fi}}
-
-\def\setpositiondataplus#1#2#3#4#5%
- {\iftrialtypesetting \else
- \initializenextposition
- \hbox % bug: to \nextboxwd
- {\edef\currentposition{#1}%
- \dosetpositionplus\currentposition
- {\the\dimexpr#2\relax}%
- {\the\dimexpr#3\relax}%
- {\the\dimexpr#4\relax}%
- {#5}%
- \traceposstring\rlap\magenta{<\currentposition}%
- \dopositionaction\currentposition
- \hss}%
+\unexpanded\def\setpositiondata
+ {\iftrialtypesetting
+ \expandafter\gobblefourarguments
+ \else
+ \expandafter\anch_positions_set_data_indeed
\fi}
-\def\setpositionplus#1#2%
- {\dowithnextbox
- {\iftrialtypesetting
- \flushnextbox
- \else
- \initializenextposition
- \hbox to \nextboxwd
- {\edef\currentposition{#1}%
- \dosetpositionplus\currentposition
- {\the\nextboxwd}%
- {\the\nextboxht}%
- {\the\nextboxdp}%
- {#2}%
- \traceposstring\rlap\magenta{<\currentposition}%
- \setbox\positionbox\flushnextbox
- \dopositionaction\currentposition
- \box\positionbox
- \hss}%
- \fi}}
+\def\anch_positions_set_data_indeed#1#2#3#4%
+ {\anch_positions_initialize
+ \hbox
+ {\edef\currentposition{#1}%
+ \dosetpositionwhd\currentposition{#2}{#3}{#4}% already \the\dimexpr
+ \anch_positions_trace_left
+ \dopositionaction\currentposition
+ \hss}}
-\let\currentposition\s!unknown
+\unexpanded\def\setpositionbox
+ {\iftrialtypesetting
+ \expandafter\anch_positions_set_box_nop
+ \else
+ \expandafter\anch_positions_set_box_yes
+ \fi}
-%D A few more low level macros take care of defining and
-%D recalling actions. We could save this information in the
-%D position containers themselves, this would save hash
-%D entries, but at the cost of much more time consuming
-%D expansion. Actions are saved globally!
+\def\anch_positions_set_box_nop#1%
+ {\dowithnextboxcs\flushnextbox}
-\newtoks\everypositionaction
+\def\anch_positions_set_box_yes#1%
+ {\dowithnextbox{\anch_positions_set_box_finish{#1}}}
-\let\POSactionprefix\POSprefix
+\def\anch_positions_set_box_finish#1%
+ {\anch_positions_initialize
+ \hbox to \wd\nextbox
+ {\edef\currentposition{#1}%
+ \dosetpositionbox\currentposition\nextbox
+ \anch_positions_trace_left
+ \setbox\b_anch_position\box\nextbox
+ \dopositionaction\currentposition
+ \box\b_anch_position
+ \hss}}
-\def\dosetpositionaction#1%
- {\setgvalue{\POSactionprefix#1::}}
+\unexpanded\def\setpositionstrut
+ {\iftrialtypesetting
+ \expandafter\anch_positions_set_strut_nop
+ \else
+ \expandafter\anch_positions_set_strut_yes
+ \fi}
-%D The lists can become quite long (also because there can
-%D be lots of parameters passed on) so we provide a hook
-%D to clean up the list afterwards.
+\def\anch_positions_set_strut_nop#1%
+ {\strut}
-\let\cleanuppositionaction\gobbleoneargument
+\def\anch_positions_set_strut_yes#1%
+ {\anch_positions_initialize
+ \hbox to \zeropoint
+ {\edef\currentposition{#1}%
+ \dosetpositionstrut\currentposition
+ \anch_positions_trace_left
+ \dopositionaction\currentposition
+ \strut
+ \hss}}
-\def\doifpositionaction#1%
- {\ifcsname\POSactionprefix#1::\endcsname
- \@EA\firstofoneargument
+\unexpanded\def\setpositiondataplus
+ {\iftrialtypesetting
+ \expandafter\gobblefivearguments
\else
- \@EA\gobbleoneargument
+ \expandafter\anch_positions_set_plus_indeed
\fi}
-\def\doifpositionactionelse#1%
- {\ifcsname\POSactionprefix#1::\endcsname
- \@EA\firstoftwoarguments
+\def\anch_positions_set_plus_indeed#1#2#3#4#5%
+ {\anch_positions_initialize
+ \hbox % just package
+ {\edef\currentposition{#1}%
+ \dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% already \the\dimexpr
+ \anch_positions_trace_right
+ \dopositionaction\currentposition
+ \hss}}
+
+\unexpanded\def\setpositionplus
+ {\iftrialtypesetting
+ \expandafter\anch_positions_set_plus_nop
\else
- \@EA\secondoftwoarguments
+ \expandafter\anch_positions_set_plus_yes
\fi}
+\def\anch_positions_set_plus_nop#1#2%
+ {\dowithnextboxcs\flushnextbox}
+
+\def\anch_positions_set_plus_yes#1#2%
+ {\dowithnextbox{\anch_positions_set_plus_yes_finish{#1}{#2}}}
+
+\def\anch_positions_set_plus_yes_finish#1#2%
+ {\anch_positions_initialize
+ \hbox to \nextboxwd
+ {\edef\currentposition{#1}%
+ \dosetpositionplus\currentposition{\wd\nextbox}{\ht\nextbox}{\dp\nextbox}{#2}%
+ \anch_positions_trace_right
+ \setbox\b_anch_position\flushnextbox
+ \dopositionaction\currentposition
+ \box\b_anch_position
+ \hss}}
+
+\let\currentposition\s!unknown
+
+%D A few special ones .. will be cleaned up
+
+\def\pageanchor {page:\the\realpageno} % for the moment only one pagesize
+\def\textanchor {text:\the\realpageno}
+\def\regionanchor{region:0}
+
+\newcount\c_anch_column % will be delegated to lua
+\newcount\c_anch_text % will be delegated to lua
+
+\unexpanded\def\anch_mark_column_box#1%
+ {\global\advance\c_anch_column\plusone
+ \ctxcommand{markregionbox(\number#1,"columnarea:\the\c_anch_column")}} % extra height
+
+\unexpanded\def\anch_mark_region_box
+ {\iftrialtypesetting
+ \singleexpandafter\gobbleoneargument
+ \else\ifpositioning
+ \doubleexpandafter\anch_mark_region_box_indeed
+ \else
+ \doubleexpandafter\gobbleoneargument
+ \fi\fi}
+
+\unexpanded\def\anch_mark_region_box_indeed#1%
+ {\ctxcommand{markregionbox(\number#1)}}
+
+\unexpanded\def\anch_mark_flow_box#1% will be extended / renamed
+ {\hbox\bgroup
+ \global\advance\c_anch_text\plusone
+ \ctxcommand{markregionbox(\number#1,"textarea:\the\c_anch_text")}%
+ \box#1%
+ \egroup}
+
+\unexpanded\def\anch_mark_flow_only#1% will be extended / renamed
+ {\global\advance\c_anch_text\plusone
+ \ctxcommand{markregionbox(\number#1,"textarea:\the\c_anch_text",true)}}
+
+\unexpanded\def\anch_make_page_box#1% maybe like text
+ {\ctxcommand{markregionbox(\number#1,"\pageanchor")}} % needs an hbox
+
+\unexpanded\def\anch_mark_text_box#1%
+ {\ctxcommand{markregionbox(\number#1,"\textanchor")}} % needs an hbox
+
%D We can copy a position with:
%D
%D \starttyping
%D \copyposition {to} {from}
%D \stoptyping
%D
-%D Again, this is a global action.
+%D Again, this is a global operation.
\def\copyposition#1#2{\ctxcommand{copyposition('#1','#2')}}
-%D The fact that handling positions is a two pass operation, is
-%D one of the reasons why we need to be able to test for
-%D existence, using:
+%D The fact that handling positions is a two pass operation, is one of the
+%D reasons why we need to be able to test for existence, using:
%D
%D \starttyping
%D \doifpositionelse {identifier} {found action} {not found action}
%D \stoptyping
\def\doifpositionelse#1{\ctxcommand{doifpositionelse('#1')}}
-
-%D We have now arrived at a few macros that would make sense as
-%D support macros, but ended up in the core.
+\def\doifposition #1{\ctxcommand{doifposition('#1')}}
%D \macros
%D {xypos}
%D
-%D We have several macros available to save positions. Later
-%D we will see applications.
+%D We have several macros available to save positions. Later we will see
+%D applications.
%D
%D \starttabulate[|l|l||]
%D \NC \type {\xypos} \NC \NC simple position with no dimensions \NC \NR
-%D \NC \type {\hpos} \NC \NC position and characteristics of a \type {\hbox} \NC \NR
-%D \NC \type {\vpos} \NC \NC position and characteristics of a \type {\vbox} \NC \NR
+%D \NC \type {\hpos} \NC \NC position and characteristics of a \type {\hbox} \NC \NR
+%D \NC \type {\vpos} \NC \NC position and characteristics of a \type {\vbox} \NC \NR
%D \NC \type {\bpos} \NC b: \NC begin point in a line \NC \NR
%D \NC \type {\epos} \NC e: \NC end point in a line \NC \NR
-%D \NC \type {\fpos} \NC f: \NC begin point in a paragraph \NC \NR
-%D \NC \type {\tpos} \NC t: \NC end point in a paragraph \NC \NR
%D \stoptabulate
%D
%D Each macro takes an identifier as argument, and the \type
%D {\hpos} and \type {\vpos} also expect box content.
-% \def\xypos{\initializenextposition\dosetposition}
-
\let\xypos\setpositiononly
-\def\hpos#1{\dontleavehmode\setpositionbox{#1}\hbox}
-\def\vpos#1{\setpositionbox{#1}\vbox}
-
-\def\bpos#1{\hpos{b:#1}{\strut}\ignorespaces}
-\def\epos#1{\removelastspace\hpos{e:#1}{\strut}}
-
-\def\fpos#1%
- {\setpositionplus{b:#1}{\number\parposcounter}\horizontalstrut
- \ignorespaces}
-
-\def\tpos#1%
- {\removelastspace
- \setpositionplus{e:#1}{\number\parposcounter}\horizontalstrut}
-
-\def\ffpos#1%
- {\setpositionplus{b:#1}{\number\parposcounter}\horizontalstrut\wpos{#1}%
- \ignorespaces}
-
-\def\ttpos#1%
- {\removelastspace
- \setpositionplus{e:#1}{\number\parposcounter}\horizontalstrut}
-
-\def\wpos#1%
- {\dontleavehmode\vadjust % may disappear if buried
- {\setbox0\hbox{\raise\strutdp\hbox{\rawwpos{#1}}}%
- \rlap{\smashedbox0}}}
-
-\def\wwpos#1% \hsmashed{\llap{\rawwpos{#1}}}
- {\rlap
- {\setbox0\hbox{\rawwpos{#1}}%
- \smashedbox0}}
-
-\def\rawwpos#1%
- {\hpos{w:#1}
- {\strut
- \hskip-\leftskip
- \hskip\hsize
- \hskip-\rightskip}}
-
-% the next macro disables par positions (in inner boxes) and
-% only registers the width
+\unexpanded\def\hpos#1{\dontleavehmode\setpositionbox{#1}\hbox}
+\unexpanded\def\vpos#1{\setpositionbox{#1}\vbox}
+\unexpanded\def\bpos#1{\dontleavehmode \setpositionstrut{b:#1}\ignorespaces}
+\unexpanded\def\epos#1{\removeunwantedspaces\setpositionstrut{e:#1}}
-\def\setinnerparpositions
- {\let\fpos\ffpos
- \let\tpos\ttpos
- \let\wpos\wwpos}
+%D When we want to calculate more complex backgrounds, we need to know what the
+%D current indentation scheme is. At the cost of many positions and memory, we
+%D can keep track of them. This mechanism is activated automatically based on
+%D information collected in the previous pass.
-% example of usage: (see for application "techniek")
-%
-% \appendtoks
-% \setinnerparpositions
-% \to \everytabulate
+\newtoks \t_anch_positions_tracers
+\newcount\c_anch_positions_paragraph
-%D When we want to calculate more complex backgrounds, we
-%D need to know what the current indentation scheme is. At
-%D the cost of many positions and memory, we can keep track
-%D of them. This mechanism is activated automatically
-%D based on information collected in the previous pass.
+\unexpanded\def\tracepositions
+ {\the\t_anch_positions_tracers}
-\newcount\parposcounter
-\newif \ifpositioningpar
-\newif \iftracepositions
-
-% we can check for used entries, and if not, then not add one
-
-\def\enableparpositions % global
+\unexpanded\def\enableparpositions % global
{\global\let\registerparoptions\doregisterparoptions
- \global\positioningtrue
- \global\positioningpartrue}
+ \global\positioningtrue}
-\def\disableparpositions % local
- {\positioningparfalse}
+\let\disableparpositions\relax
\let\registerparoptions\relax
-\def\doregisterparoptions
+\unexpanded\def\doregisterparoptions
{\iftrialtypesetting \else
\ifinpagebody \else \ifmmode \else \ifinformula \else
- \dodoregisterparoptions
+ \anch_positions_register_par_options
\fi \fi \fi
\fi}
-\def\dodoregisterparoptions
- {\global\advance\parposcounter\plusone
- \setpositiondataplus
- {p:\number\parposcounter}% identifier
- {\the\zeropoint}%
- {\the\strutht}%
- {\the\strutdp}%
- {\the\hsize,\the\dimexpr\leftskip\relax,\the\dimexpr\rightskip\relax,\the\hangindent,\the\hangafter,\the\parindent}%
- %\normalhbox{\registerparsymbol}%
- \iftracepositions\registerparsymbol\fi}
-
-\def\traceposstring#1#2#3%
- {\iftracepositions
- \smashedhbox
- {#1{\infofont#2#3}%
- \scratchdimen.5\points
- \kern-2\scratchdimen
- \vrule\!!width4\scratchdimen\!!height\scratchdimen\!!depth\scratchdimen}%
- \fi}
-
-\def\registerparsymbol
- {\iftracepositions
- \smashedhbox to \zeropoint
- {\hss
- \startcolor[blue]%
- \llap{\infofont\number\parposcounter}%
- \scratchdimen\onepoint
- \vrule
- \!!width 4\scratchdimen
- \!!height2\scratchdimen
- \!!depth 2\scratchdimen
- \stopcolor
- \hss}%
- \fi}
-
-% \appendtoks \registerparoptions \to \everypar
+\def\anch_positions_register_par_options_normal
+ {\dontleavehmode\ctxcommand{parpos()}}
-%D Eperimental code, don't use this yet: (must be sped up anyway)
+\def\anch_positions_register_par_options_traced
+ {\anch_positions_register_par_options_normal
+ \smashedhbox to \zeropoint
+ {\hss
+ \startcolor[blue]%
+ \llap{\infofont\number\c_anch_positions_paragraph}%
+ \vrule
+ \!!width 4\onepoint
+ \!!height2\onepoint
+ \!!depth 2\onepoint
+ \stopcolor
+ \hss}}
-\def\@@noden{node:n:}
-\def\@@nodeo{node:o:}
-\def\@@nodep{node:p:}
-
-\def\doifelsenodelocation#1%
- {\ifcsname\@@noden#1\endcsname
- \expandafter\firstoftwoarguments
- \else
- \expandafter\secondoftwoarguments
- \fi}
-
-\def\nextnodelocation#1%
- {\ifcsname\@@noden#1\endcsname\pluscounter{\@@noden#1}\fi}
-
-\def\newnodelocation#1%
- {\ifcsname\@@noden#1\endcsname
- \setcounter{\@@noden#1}\zerocount
- \letgvalue {\@@nodeo#1}\!!zerocount
- \fi}
+\let\anch_positions_register_par_options\anch_positions_register_par_options_normal
-\def\tagnodelocation#1%
- {\ifcsname\@@noden#1\endcsname\xypos{\@@nodep#1:\countervalue{\@@noden#1}}\fi}
+\appendtoks
+ \let\anch_positions_register_par_options\anch_positions_register_par_options_traced
+\to \t_anch_positions_tracers
-\def\getnodelocationp#1{\MPp{\@@nodep#1:\countervalue{\@@noden#1}}}
-\def\getnodelocationx#1{\MPx{\@@nodep#1:\countervalue{\@@noden#1}}}
-\def\getnodelocationy#1{\MPy{\@@nodep#1:\countervalue{\@@noden#1}}}
+\unexpanded\def\anch_positions_trace#1#2#3%
+ {\smashedhbox
+ {#1{\infofont#2#3}%
+ \kern-\onepoint
+ \vrule\!!width2\onepoint\!!height\halfapoint\!!depth\halfapoint}}
-\def\numnodelocationp#1#2{\MPp{\@@nodep#1:\number#2}}
-\def\numnodelocationx#1#2{\MPx{\@@nodep#1:\number#2}}
-\def\numnodelocationy#1#2{\MPy{\@@nodep#1:\number#2}}
+\unexpanded\def\anch_positions_trace_left_indeed
+ {\anch_positions_trace\llap\darkmagenta{\currentposition>}}
-\def\getnodelocationn#1{\countervalue{\@@noden#1}}
-\def\getnodelocationo#1{\getvalue {\@@nodeo#1}}
+\unexpanded\def\anch_positions_trace_right_indeed
+ {\anch_positions_trace\rlap\darkcyan{<\currentposition}}
-\setnewconstant\nodelocationmode\plusone
+\let\anch_positions_trace_left \relax
+\let\anch_positions_trace_right\relax
-\def\analyzenodelocation#1%
- {\ifcsname\@@noden#1\endcsname
- \doanalyzenodelocation{#1}{\getnodelocationn{#1}}\zerocount
- \fi}
+\appendtoks
+ \let\anch_positions_trace_left \anch_positions_trace_left_indeed
+ \let\anch_positions_trace_right \anch_positions_trace_right_indeed
+\to \t_anch_positions_tracers
-\def\doanalyzenodelocation#1#2#3% class n default
- {\begingroup
- \donefalse
- \ifcase\nodelocationmode
- % do nothing
- \else
- \edef\nodelocationselfn{#2}%
- \edef\nodelocationselfp{\numnodelocationp{#1}\nodelocationselfn}%
- \edef\nodelocationselfx{\numnodelocationx{#1}\nodelocationselfn}%
- \edef\nodelocationselfy{\numnodelocationy{#1}\nodelocationselfn}%
- \scratchcounter\plusone
- \doloop
- {\ifnum\recurselevel=\nodelocationselfn\relax
- \donetrue
- \else
- \edef\nodelocationotherp{\numnodelocationp{#1}\recurselevel}%
- \edef\nodelocationotherx{\numnodelocationx{#1}\recurselevel}%
- \edef\nodelocationothery{\numnodelocationy{#1}\recurselevel}%
- \ifcase\nodelocationmode
- \or
- % ok for single column
- \ifcase\nodelocationotherp\relax
- \exitloop
- \else\ifnum\nodelocationotherp<\nodelocationselfp\relax
- \donetrue \advance\scratchcounter\plusone
- \else\ifnum\nodelocationotherp>\nodelocationselfp\relax
- % skip
- \else\ifdim\nodelocationothery>\nodelocationselfy\relax
- \donetrue \advance\scratchcounter\plusone
- \else\ifdim\nodelocationothery<\nodelocationselfy\relax
- % skip
- \else\ifdim\nodelocationotherx<\nodelocationselfx\relax
- \donetrue \advance\scratchcounter\plusone
- \fi\fi\fi\fi\fi\fi
- \or
- % acceptable for double column
- \ifcase\nodelocationotherp\relax
- \exitloop
- \else\ifnum\nodelocationotherp<\nodelocationselfp\relax
- \donetrue \advance\scratchcounter\plusone
- \else\ifnum\nodelocationotherp>\nodelocationselfp\relax
- % skip
- \else\ifnum\recurselevel>\nodelocationselfn\relax
- \donetrue \exitloop
- \else
- \donetrue \advance\scratchcounter\plusone
- \fi\fi\fi\fi
- \else
- \exitloop
- \fi
- \fi}%
- \fi
- \ifdone \else
- \scratchcounter#3\relax
- \fi
- \setxvalue{\@@nodeo#1}{\the\scratchcounter}%
- \endgroup}
-
-\unexpanded\def\shownodelocation#1%
- {\ifcsname\@@noden#1\endcsname
- \analyzenodelocation{#1}%
- (#1,%
- n:\getnodelocationn{#1},%
- p:\getnodelocationp{#1},%
- x:\getnodelocationx{#1},%
- y:\getnodelocationy{#1},%
- o:\getnodelocationo{#1})%
- \fi}
+% \appendtoks \registerparoptions \to \everypar
%D \macros
%D {doifoverlappingelse}
%D
-%D A first application of positional information, is to
-%D determine if two boxes do overlap:
+%D A first application of positional information, is to determine if two
+%D boxes do overlap:
%D
%D \starttyping
%D \doifoverlappingelse{point a}{point b}
@@ -662,8 +413,8 @@
%D {doifpositionsonsamepageelse,
%D doifpositionsonthispageelse}
%D
-%D Instead of letting the user handle fuzzy expansion, we
-%D provide a simple test on positions being on the same page.
+%D Instead of letting the user handle fuzzy expansion, we provide a simple test on
+%D positions being on the same page.
%D
%D \starttyping
%D \doifpositionsonsamepageelse{point a}{point b}
@@ -677,18 +428,4 @@
\def\doifpositionsonsamepageelse#1{\ctxcommand{doifpositionsonsamepageelse("#1")}}
\def\doifpositionsonthispageelse#1{\ctxcommand{doifpositionsonthispageelse("#1")}}
-%D Plugins:
-
-\let\MPv \MPplus
-\let\MPvv \MPrest
-\let\MPanchor\MPpos
-
-%D \macros
-%D {POSp, POSx, POSy, POSh, POSd, POSw}
-%D
-%D This is obsolete in \MKIV:
-
-\let\POSp\MPp \let\POSx\MPx \let\POSy\MPy
-\let\POSh\MPh \let\POSd\MPd \let\POSw\MPw
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/anch-snc.mkii b/Master/texmf-dist/tex/context/base/anch-snc.mkii
index cf5b35d6961..01704e0c8e6 100644
--- a/Master/texmf-dist/tex/context/base/anch-snc.mkii
+++ b/Master/texmf-dist/tex/context/base/anch-snc.mkii
@@ -5,7 +5,7 @@
%D subtitle=Synchronization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/anch-snc.mkiv b/Master/texmf-dist/tex/context/base/anch-snc.mkiv
index f976047c9b9..77ebc3e0e71 100644
--- a/Master/texmf-dist/tex/context/base/anch-snc.mkiv
+++ b/Master/texmf-dist/tex/context/base/anch-snc.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Synchronization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,21 +17,26 @@
\unprotect
+\ifx\s!num \undefined \def\s!num {num} \fi
\ifx\s!set \undefined \def\s!set {set} \fi
\ifx\s!reset \undefined \def\s!reset {reset} \fi
\ifx\s!preset \undefined \def\s!preset {preset} \fi
\ifx\s!syncpos\undefined \def\s!syncpos{syncpos} \fi
\unexpanded\def\definesyncpositions[#1]%
- {\global\let\flushsyncpositions\doflushsyncpositions % only when used
- \setcounter{\s!num:\s!syncpos:#1}{0}%
- \doglobal\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions
+ {\ifcsname\s!num:\s!syncpos:#1\endcsname \else
+ \global\let\flushsyncpositions\doflushsyncpositions % only when used
+ \global\let\flushsyncresets \doflushsyncresets
+ \global\let\flushsyncpresets \doflushsyncpresets
+ \expandafter\newcount\csname\s!num:\s!syncpos:#1\endcsname
+ \doglobal\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions
\doglobal\appendtoksonce\csname\s!preset:\s!syncpos:#1\endcsname\to\presetsyncpositions
% to be tested:
% \doglobal\expandafter\appendtoksonce\csname\s!reset :\s!syncpos:#1\endcsname\to\resetsyncpositions
% \doglobal\expandafter\appendtoksonce\csname\s!preset:\s!syncpos:#1\endcsname\to\presetsyncpositions
- \setgvalue{\s!syncpos:#1}{sync_n[#1] := 0 ;}%
- \setgvalue{\s!set:\s!syncpos:#1}{\dosetsyncpositions{#1}}}
+ \setgvalue{\s!syncpos:#1}{sync_n[#1] := 0 ;}%
+ \setgvalue{\s!set:\s!syncpos:#1}{\dosetsyncpositions{#1}}%
+ \fi}
\def\syncposition
{\dodoubleempty\dosyncposition}
@@ -50,13 +55,10 @@
{\letgvalue{\s!reset:\s!syncpos:#1}\relax
\letgvalue{\s!preset:\s!syncpos:#1}\relax
\ifcsname\s!syncpos:#1\endcsname
- \pluscounter{\s!num:\s!syncpos:#1}%
+ \global\advance\csname\s!num:\s!syncpos:#1\endcsname\plusone
\setsyncpositions{#1}%
% option: geen w/h, alleen p 0 0 0 data
- \setpositionplus
- {\s!syncpos:#1:\countervalue{\s!num:\s!syncpos:#1}}%
- {#2}%
- \hbox{\strut\traceposstring\llap\green{#3/\countervalue{\s!num:\s!syncpos:#1}/#1/#2>>}}%
+ \setpositionplus{\s!syncpos:#1:\the\csname\s!num:\s!syncpos:#1\endcsname}{#2}\hbox{\strut}%
\else
\strut
\fi}
@@ -130,15 +132,21 @@
\endgroup}
\def\flushsyncxxsets#1%
- {\setbox\scratchbox\hbox{\the#1}%
+ {\begingroup
+ \setbox\scratchbox\hbox{\the#1}%
\ifvoid\scratchbox\else
- \prewordbreak \let\prewordbreak\relax % only once
+ \prewordbreak
+ %\let\prewordbreak\relax % only once
\smashbox\scratchbox
\box\scratchbox
- \fi}
+ \fi
+ \endgroup}
-\def\flushsyncresets {\flushsyncxxsets\resetsyncpositions }
-\def\flushsyncpresets{\flushsyncxxsets\presetsyncpositions}
+\let\flushsyncresets \relax
+\let\flushsyncpresets\relax
+
+\def\doflushsyncresets {\flushsyncxxsets\resetsyncpositions }
+\def\doflushsyncpresets{\flushsyncxxsets\presetsyncpositions}
% \appendtoks \flushsyncpositions \to \everypar
% \appendtoks \flushsyncpositions \to \everyheadstart
@@ -147,13 +155,18 @@
%
% \appendtoks \flushsyncpositions \to \neverypar
-\protect \endinput
+\protect
+
+\continueifinputfile{anch-snc.mkiv}
\starttext
+\setupbodyfont[dejavu]
+
\definesyncpositions[1]
\startuseMPgraphic{sync}
+ if unknown context_abck : input mp-abck.mpiv ; fi ;
StartPage ;
\getsyncpositions{1} ;
SyncThreshold := 2LineHeight ;
@@ -177,9 +190,14 @@
\setupbackgrounds[page][background=tempoverlay]
-\syncposition[1][1] \input ward \endgraf
-\syncposition[1][2] \input ward \endgraf
-\syncposition[1][3] \input ward \endgraf
-\syncposition[1][4] \input ward \endgraf
+\dorecurse {10} {
+
+ \startchapter[title={Test #1}]
+ \syncposition[1][1] \dorecurse{10}{\input ward \endgraf}
+ \syncposition[1][2] \dorecurse {4}{\input ward \endgraf}
+ \syncposition[1][3] \dorecurse {7}{\input ward \endgraf}
+ \syncposition[1][4] \dorecurse {3}{\input ward \endgraf}
+ \stopchapter
+}
\stoptext
diff --git a/Master/texmf-dist/tex/context/base/anch-tab.mkiv b/Master/texmf-dist/tex/context/base/anch-tab.mkiv
new file mode 100644
index 00000000000..4bdaa2ef984
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/anch-tab.mkiv
@@ -0,0 +1,375 @@
+%D \module
+%D [ file=anch-pgr, % moved from anch-pgr (1999.08.01)
+%D version=2011.12.19, % 1999.08.01,
+%D title=\CONTEXT\ Anchoring Macros,
+%D subtitle=Table Extensions,
+%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 Anchoring Macros / Table Extensions}
+
+\unprotect
+
+\newcount\c_anch_tabs
+
+\unexpanded\def\tabl_tabulate_hook_b
+ {\iftrialtypesetting\else
+ \ifpositioning
+ \ifcase\c_tabl_tabulate_noflines % \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines
+ \tabl_tabulate_hook_b_first
+ \else
+ \tabl_tabulate_hook_b_next
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_tabulate_hook_e
+ {\iftrialtypesetting\else
+ \ifpositioning
+ \ifcase\c_tabl_tabulate_noflines % \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines
+ \tabl_tabulate_hook_e_first
+ \else
+ \tabl_tabulate_hook_e_next
+ \fi
+ \fi
+ \fi}
+
+\unexpanded\def\tabl_tabulate_hook_b_first
+ {\ctxcommand{bcolumn("tabulate:\the\c_anch_tabs:\the\c_tabl_tabulate_column",true)}}
+
+\unexpanded\def\tabl_tabulate_hook_b_next
+ {\ctxcommand{bcolumn("tabulate:\the\c_anch_tabs:\the\c_tabl_tabulate_column")}}
+
+\unexpanded\def\tabl_tabulate_hook_e_first
+ {\ctxcommand{ecolumn(true)}}
+
+\unexpanded\def\tabl_tabulate_hook_e_next
+ {\ctxcommand{ecolumn()}}
+
+% \appendtoks \registerparoptions \to \everypar
+
+\appendtoks
+ \global\advance\c_anch_tabs\plusone
+\to \everytabulate
+
+%D Beware, the following code is somewhat weird and experimental
+%D and might be dropped or become a loadable module.
+
+%D \macros
+%D {GFC, GTC, GSC}
+%D
+%D The next macros extend tables and tabulation with
+%D backgrounds and position related features. Areas are
+%D specified with symbolic names, and symbolic references to
+%D the graphics involved. Each table has its own namespace.
+
+\newconditional\tablehaspositions
+\newcount\noftabpositions
+\newtoks \posXCtoks
+
+\def\dotablebpos{\bpos}
+\def\dotableepos{\epos}
+
+\installcorenamespace{positiontables}
+
+\def\tbPOSprefix
+ {\??positiontables\number\noftabpositions:}
+
+\def\tablepos
+ {\normalexpanded{\global\posXCtoks\emptytoks\the\posXCtoks}}
+
+\let\tabulatepos\tablepos
+
+\def\dodododoGSC[#1:#2]%
+ {\remappositionframed{#2}{\tbPOSprefix#1}%
+ \dotablebpos{\tbPOSprefix#1}%
+ \doglobal\appendtoks\@EA\dotableepos\@EA{\tbPOSprefix#1}\to\posXCtoks}
+
+\def\dododoGSC[#1:#2:#3]%
+ {\doglobal\appendtoks\dodododoGSC[#1:#2]\to\posXCtoks\NC}
+
+\def\dodoGSC[#1]%
+ {\def\docommand##1{\dododoGSC[##1:##1]}%
+ \processcommalist[#1]\docommand}
+
+\def\dodododoGFC[#1:#2:#3]%
+ {\remappositionframed{#2}{\tbPOSprefix#1}%
+ \dotablebpos{\tbPOSprefix#1}}
+
+\def\dododoGFC[#1]%
+ {\def\docommand##1{\dodododoGFC[##1:##1]}%
+ \processcommalist[#1]\docommand}
+
+\def\dodoGFC[#1]%
+ {\doglobal\appendtoks\dododoGFC[#1]\to\posXCtoks\NC}
+
+\def\dododododoGTC[#1:#2]%
+ {\dotableepos{\tbPOSprefix#1}}
+
+\def\dodododoGTC[#1]%
+ {\def\docommand##1{\dododododoGTC[##1:##1]}%
+ \processcommalist[#1]\docommand}
+
+\def\dododoGTC[#1]%
+ {\doglobal\appendtoks\dodododoGTC[#1]\to\posXCtoks}
+
+\def\dodoGTC[#1]%
+ {\doglobal\appendtoks\dododoGTC[#1]\to\posXCtoks\NC}
+
+\def\dodododoXC[#1#2]%
+ {\if#1>\dodoGFC [#2:#2]\else
+ \if#1+\dodoGFC [#2:#2]\else
+ \if#1<\dodoGTC [#2:#2]\else
+ \if#1-\dodoGTC [#2:#2]\else
+ \if#1=\dodoGSC [#2:#2]\else
+ \dodoGSC[#1#2:#1#2]\fi\fi\fi\fi\fi}
+
+\def\dododoXC#1%
+ {\dodododoXC[#1]}
+
+\def\dodoXC[#1]%
+ {{\let\NC\relax\processcommalist[#1]\dododoXC}}
+
+\def\@@checktablepositionstate
+ {\iftrialtypesetting
+ \global\settrue\tablehaspositions
+ \firstargumentfalse
+ \fi}
+
+\def\doGSC[#1]{\@@checktablepositionstate\iffirstargument\dodoGSC[#1]\else\expandafter\NC\fi}
+\def\doGFC[#1]{\@@checktablepositionstate\iffirstargument\dodoGFC[#1]\else\expandafter\NC\fi}
+\def\doGTC[#1]{\@@checktablepositionstate\iffirstargument\dodoGTC[#1]\else\expandafter\NC\fi}
+\def\doXC [#1]{\@@checktablepositionstate\iffirstargument\dodoXC [#1]\else\expandafter\fi\NC}
+
+\def\tbGSC{\dosingleempty\doGSC}
+\def\tbGFC{\dosingleempty\doGFC}
+\def\tbGTC{\dosingleempty\doGTC}
+\def\tbXC {\dosingleempty\doXC }
+
+%D The amount of code to support tables and tabulation is
+%D rather minimalistic.
+
+\let\tabulatepos\tablepos
+
+\def\tabulatenormalpos
+ {\iftrialtypesetting
+ % nothing
+ \else\ifconditional\tablehaspositions
+ \hss\tabulatepos\hss
+ \else
+ % nothing
+ \fi\fi}
+
+\def\tabulateequalpos
+ {\iftrialtypesetting
+ \tabulateEQ
+ \else\ifconditional\tablehaspositions
+ \tabulateEQpos
+ \else
+ \tabulateEQ
+ \fi\fi}
+
+\def\tabulateEQpos
+ {\setbox\scratchbox\hbox{\tabulateEQ}%
+ \hbox to \wd\scratchbox{\hss\kern\zeropoint\tabulatepos\hss}%
+ \hskip-\wd\scratchbox
+ \box\scratchbox}
+
+\appendtoks
+ \global\advance\noftabpositions\plusone
+ \global\setfalse\tablehaspositions
+\to \everytabulate
+
+% We need to handle paragraphs as well.
+
+\let\doflushtabulateepos\relax
+
+\def\dotabulatebpos
+ {\bpos}
+
+\def\dotabulateepos#1%
+ {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
+ \epos{#1}%
+ \glet\doflushtabulateepos\relax
+ \else
+ \gdef\doflushtabulateepos{\epos{#1}}%
+ \fi}
+
+\def\flushtabulatesplitbox
+ {\box\b_tabl_tabulate
+ \iftrialtypesetting\else\ifconditional\tablehaspositions\doflushtabulateepos\fi\fi}
+
+\appendtoks
+ \let\dotablebpos\dotabulatebpos % ?
+ \let\dotableepos\dotabulateepos % ?
+ \glet\doflushtabulateepos\relax
+\to \everytabulate
+
+%D In order to prevent potential clashes with abbreviations,
+%D postpone the mapping.
+
+\appendtoks
+ \let\GSC\tbGSC
+ \let\GFC\tbGFC
+ \let\GTC\tbGTC
+ \let\XC \tbXC
+\to \everytabulate
+
+%D \macros
+%D {definepositionframed}
+%D
+%D The next example show how to provide backgrounds to table
+%D cells. First we define some framed backgrounds.
+%D
+%D \startbuffer
+%D \definepositionframed[x][background=color,backgroundcolor=red]
+%D \definepositionframed[y][background=color,backgroundcolor=green]
+%D \definepositionframed[z][background=color,backgroundcolor=blue]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D % \getbuffer
+%D
+%D \startbuffer
+%D \starttabulate[|c|c|c|]
+%D \GFC[f:x] this is a small \NC table \NC in which we \NC \FR
+%D \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
+%D \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D The table itself defines three areas (a, b and~c) using
+%D these frames.
+%D
+%D \typebuffer
+%D % \getbuffer
+%D
+%D Tables (based on \TABLE) are supported by:
+
+\def\normalTABLEsimplebar {\unskip\!ttRightGlue&\tablepos&} % |
+\def\normalTABLEcomplexbar{\unskip\!ttRightGlue&\omit\tablepos\!ttAlternateVrule} % \|
+\def\normalTABLEquote {\unskip\!ttRightGlue&\omit\tablepos&} % "
+
+\appendtoks
+ \global\advance\noftabpositions\plusone
+ \global\setfalse\tablehaspositions
+\to \everytable
+
+%D Since we don't want nameclashes:
+
+\appendtoks
+ \let\GSC\tbGSC
+ \let\GFC\tbGFC
+ \let\GTC\tbGTC
+ \let\XC \tbXC
+\to \everytable
+
+%D In the previous example, we could have provided an overlay to
+%D the framed definition. A more direct approach is demonstrated
+%D below:
+%D
+%D \startbuffer
+%D \def\cw#1{\color[white]{#1}}
+%D
+%D \startMPpositiongraphic{tableshade}
+%D initialize_area(\MPpos{\MPvar{from}},\MPpos{\MPvar{to}}) ;
+%D color c ; c := \MPvar{color} ;
+%D linear_shade(pxy,0,.4c,.9c) ;
+%D anchor_area(\MPanchor{\MPvar{from}}) ;
+%D \stopMPpositiongraphic
+%D
+%D \setMPpositiongraphic{b:x}{tableshade}{from=b:x,to=e:x,color=red}
+%D \setMPpositiongraphic{b:y}{tableshade}{from=b:y,to=e:y,color=green}
+%D \setMPpositiongraphic{b:z}{tableshade}{from=b:z,to=e:z,color=blue}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D The definition of the table looks about the same as the
+%D previous one:
+%D
+%D \startbuffer
+%D \starttable[|c|c|c|]
+%D \GFC[b:z] \cw{this is a small} \NC \cw{table} \NC in which we \NC \FR
+%D \NC \cw{will demonstrate} \GFC[c:y] \cw{that this} \GTC[c] \cw{positioning} \NC \MR
+%D \GSC[a:x] \cw{mechanism also} \GTC[b] \cw{works quite well} \NC in tables \NC \LR
+%D \stoptable
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \getbuffer
+
+% \definepositionframed[w][background=color,backgroundcolor=yellow]
+% \definepositionframed[x][background=color,backgroundcolor=red]
+% \definepositionframed[y][background=color,backgroundcolor=green]
+% \definepositionframed[z][background=color,backgroundcolor=blue]
+%
+% \starttabulate[|c|c|c|]
+% \NC this is a small \NC table \NC in which we \NC \FR
+% \NC will demonstrate \NC that this \NC positioning \NC \MR
+% \NC mechanism also \NC works quite well \NC in tables \NC \LR
+% \stoptabulate
+%
+% \starttabulate[|c|c|c|]
+% \GFC[f:x] this is a small \GTC table \NC in which we \NC \FR
+% \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
+% \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
+% \stoptabulate
+%
+% \starttabulate[|c|c|c|]
+% \GFC[f:x,d:w] this is a small \GTC[d] table \NC in which we \NC \FR
+% \NC will demonstrate \GFC[g:z] that this \GTC[g] positioning \NC \MR
+% \GSC[e:y] mechanism also \GTC[f] works quite well \NC in tables \NC \LR
+% \stoptabulate
+%
+% \starttabulate[|c|c|c|]
+% \XC[+f:x] this is a small \XC table \NC in which we \NC \FR
+% \NC will demonstrate \XC[+g:z] that this \XC[-g] positioning \NC \MR
+% \XC[=e:y] mechanism also \XC[-f] works quite well \NC in tables \NC \LR
+% \stoptabulate
+%
+% \starttabulate[|c|c|c|]
+% \XC[+f:x,+d:w] this is a small \XC[-d] table \NC in which we \NC \FR
+% \NC will demonstrate \XC[+g:z] that this \XC[-g] positioning \NC \MR
+% \XC[=e:y] mechanism also \XC[-f] works quite well \NC in tables \NC \LR
+% \stoptabulate
+
+% evt [b:x]
+%
+% \definepositionframed[x][background=color,fillcolor=red]
+% \definepositionframed[y][background=color,fillcolor=green]
+% \definepositionframed[z][background=color,fillcolor=blue]
+
+\def\remappositionframed#1#2% from to
+ {\copyposition{b:#1}{b:#2}%
+ \copyposition{e:#1}{e:#2}%
+ \dosetpositionaction{b:#2}{\dopositionaction{b:#1}}}
+
+\unexpanded\def\definepositionframed
+ {\dodoubleargument\dodefinepositionframed}
+
+\def\dodefinepositionframed[#1][#2]%
+ {\dosetpositionaction{b:#1}{\dopositionframed[#1][#2]}}
+
+\unexpanded\def\positionframed
+ {\bgroup
+ \dodoubleempty\dopositionframed}
+
+\def\dopositionframed[#1][#2]%
+ {\setbox\scratchbox\hbox
+ {\scratchwidth \dimexpr\MPx{e:#1}-\MPx{b:#1}\relax
+ \scratchdepth \dimexpr\MPy{b:#1}-\MPy{e:#1}+\MPd{e:#1}\relax
+ \scratchheight\dimexpr\scratchdepth+\MPh{b:#1}\relax
+ \lower\scratchdepth\hbox
+ {\framed[\c!width=\scratchwidth,\c!height=\scratchheight,\c!offset=\v!overlay,#2]{}}}%
+ \smashedbox\scratchbox
+ \egroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/attr-col.lua b/Master/texmf-dist/tex/context/base/attr-col.lua
index 871ac3e03cf..c592d1dc1cb 100644
--- a/Master/texmf-dist/tex/context/base/attr-col.lua
+++ b/Master/texmf-dist/tex/context/base/attr-col.lua
@@ -9,6 +9,9 @@ if not modules then modules = { } end modules ['attr-col'] = {
-- this module is being reconstructed and code will move to other places
-- we can also do the nsnone via a metatable and then also se index 0
+-- list could as well refer to the tables (instead of numbers that
+-- index into another table) .. depends on what we need
+
local type = type
local format = string.format
local concat = table.concat
@@ -45,7 +48,7 @@ local unsetvalue = attributes.unsetvalue
-- we can also collapse the two attributes: n, n+1, n+2 and then
-- at the tex end add 0, 1, 2, but this is not faster and less
-- flexible (since sometimes we freeze color attribute values at
--- the lua end of the game
+-- the lua end of the game)
--
-- we also need to store the colorvalues because we need then in mp
--
@@ -349,13 +352,15 @@ end
-- transparencies
+local a_transparency = attributes.private('transparency')
+
attributes.transparencies = attributes.transparencies or { }
local transparencies = attributes.transparencies
transparencies.registered = transparencies.registered or { }
transparencies.data = allocate()
transparencies.values = transparencies.values or { }
transparencies.triggering = true
-transparencies.attribute = attributes.private('transparency')
+transparencies.attribute = a_transparency
transparencies.supported = true
storage.register("attributes/transparencies/registered", transparencies.registered, "attributes.transparencies.registered")
@@ -393,6 +398,9 @@ function transparencies.register(name,a,t,force) -- name is irrelevant here (can
elseif force and not data[n] then
register_transparency(n,a,t)
end
+ if name then
+ list[a_transparency][name] = n -- not grouped, so only global transparencies
+ end
return registered[stamp]
end
diff --git a/Master/texmf-dist/tex/context/base/attr-col.mkiv b/Master/texmf-dist/tex/context/base/attr-col.mkiv
index 8d61ee8aeff..6231755e914 100644
--- a/Master/texmf-dist/tex/context/base/attr-col.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-col.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Color,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -17,66 +17,6 @@
\unprotect
-% todo: no need for 'color' argument, we can set that once at startup; currently
-% a bit inconsistent
-
-% 1=off 2=gray 3=spot 4=rgb 5=cmyk 6=cmy % only 1/2/4/5 are supported
-%
-% We could combine this in one attribute but this is not faster and also
-% less flexible because sometimes we want to freeze the attribute bit.
-
-% % color (layer on top)
-%
-% \def\dosetcolormodel#1% overloaded later
-% {\ctxcommand{setcolormodel('#1')}} % sets attribute
-%
-% \dosetcolormodel{all}
-%
-% \def\registerrgbcolor#1#2#3#4% not used
-% {\setevalue{(cs:#1)}{\attribute\colorattribute\ctxcommand{registercolor('#1','rgb' ,#2,#3,#4)}}}
-%
-% \def\registercmykcolor#1#2#3#4#5% not used
-% {\setevalue{(cs:#1)}{\attribute\colorattribute\ctxcommand{registercolor('#1','cmyk',#2,#3,#4,#5)}}}
-%
-% \def\registergraycolor#1#2% not used
-% {\setevalue{(cs:#1)}{\attribute\colorattribute\ctxcommand{registercolor('#1','gray',#2)}}}
-
-% % transparency (layer on top)
-%
-% \def\registertransparency#1#2#3%
-% {\setevalue{(ts:#1)}{\attribute\transparencyattribute\ctxcommand{registertransparency(#2,#3)} }}
-%
-% \def\sometransparencyswitch#1%
-% {\csname(ts:#1)\endcsname}
-%
-% \def\sometransparencyswitch
-% {\ctxcommand{enabletransparency()}%
-% \gdef\sometransparencyswitch##1{\csname(ts:##1)\endcsname}%
-% \sometransparencyswitch}
-%
-% \registertransparency {one} {1} {.5}
-% \registertransparency {two} {1} {.6}
-
-% overprint
-
-\def\registercolorintent#1#2%
- {\setevalue{(os:#1)}{\attribute\colorintentattribute\ctxcommand{registercolorintent('#2')} }}
-
-\def\dotriggercolorintent
- {\ctxcommand{enablecolorintents()}%
- \gdef\dotriggercolorintent##1{\csname(os:##1)\endcsname}%
- \dotriggercolorintent}
-
-\registercolorintent{knockout} {knockout}
-\registercolorintent{overprint}{overprint}
-
-\installattributestack\colorintentattribute
-
-\setevalue{(os:#\v!none}{\attribute\colorintentattribute\attributeunsetvalue} % does this work out ok?
+% We implement this elsewhere but some coce might end up here.
\protect \endinput
-
-% test case
-%
-% {\green \hbox to \hsize{\leaders\hrule \hfill a}\par}
-% {\red \hbox to \hsize{\leaders\hbox{x}\hfill a}\par}
diff --git a/Master/texmf-dist/tex/context/base/attr-eff.mkiv b/Master/texmf-dist/tex/context/base/attr-eff.mkiv
index 3526276c7e7..c5c94537c14 100644
--- a/Master/texmf-dist/tex/context/base/attr-eff.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-eff.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Effects,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -17,21 +17,6 @@
\unprotect
-% \def\registereffect#1#2#3% #2=stretch #3=rulethickness
-% {\setxvalue{(es:#1:#2:\number\dimexpr#3\relax)}% todo: set attribute at lua end
-% {\attribute\effectattribute\ctxcommand{registereffect('#1',#2,\number\dimexpr#3\relax)}\relax}}
-%
-% \def\dotriggereffect
-% {\ctxcommand{enableeffect()}% can then move to caller
-% \gdef\dotriggereffect##1##2##3%
-% {\ifcsname(es:##1:##2:\number\dimexpr##3\relax)\endcsname\else\registereffect{##1}{##2}{##3}\fi
-% \csname(es:##1:##2:\number\dimexpr##3\relax)\endcsname}%
-% \dotriggereffect}
-%
-% \def\registereffect#1#2#3% #2=stretch #3=rulethickness
-% {\setxvalue{(es:#1:#2:\number\dimexpr#3\relax)}% todo: set attribute at lua end
-% {\attribute\effectattribute\ctxcommand{registereffect('#1',#2,\number\dimexpr#3\relax)}\relax}}
-
\gdef\dotriggereffect#1#2#3%
{\ctxcommand{triggereffect('#1',#2,\number\dimexpr#3\relax)}}
diff --git a/Master/texmf-dist/tex/context/base/attr-ini.lua b/Master/texmf-dist/tex/context/base/attr-ini.lua
index 96d7c7228c7..f3714fcb4d9 100644
--- a/Master/texmf-dist/tex/context/base/attr-ini.lua
+++ b/Master/texmf-dist/tex/context/base/attr-ini.lua
@@ -32,9 +32,14 @@ storage.register("attributes/names", names, "attributes.names")
storage.register("attributes/numbers", numbers, "attributes.numbers")
storage.register("attributes/list", list, "attributes.list")
+names [0] = "fontdynamic"
+numbers["fontdynamic"] = 0
+
function attributes.define(name,number) -- at the tex end
if not numbers[name] then
- numbers[name], names[number], list[number] = number, name, { }
+ numbers[name] = number
+ names[number] = name
+ list[number] = { }
end
end
@@ -85,22 +90,72 @@ end
-- new (actually a tracer)
-function attributes.ofnode(n)
- local a = n.attr
- if a then
- a = a.next
+local report_attribute = logs.reporter("attributes")
+
+local function showlist(what,list)
+ if list then
+ local a = list.next
+ local i = 0
while a do
local number, value = a.number, a.value
- texio.write_nl(format("%s : attribute %3i, value %4i, name %s",tostring(n),number,value,names[number] or '?'))
+ i = i + 1
+ report_attribute("%s %2i: attribute %3i, value %4i, name %s",tostring(what),i,number,value,names[number] or '?')
a = a.next
end
end
end
+function attributes.showcurrent()
+ showlist("current",node.current_attr())
+end
+
+function attributes.ofnode(n)
+ showlist(n,n.attr)
+end
+
-- interface
commands.defineattribute = attributes.define
+commands.showattributes = attributes.showcurrent
function commands.getprivateattribute(name)
context(attributes.private(name))
end
+
+-- rather special
+
+local store = { }
+
+function commands.savecurrentattributes(name)
+ name = name or ""
+ local n = node.current_attr()
+ n = n and n.next
+ local t = { }
+ while n do
+ t[n.number] = n.value
+ n = n.next
+ end
+ store[name] = {
+ attr = t,
+ font = font.current(),
+ }
+end
+
+function commands.restorecurrentattributes(name)
+ name = name or ""
+ local t = store[name]
+ if t then
+ local attr = t.attr
+ local font = t.font
+ if attr then
+ for k, v in next, attr do
+ tex.attribute[k] = v
+ end
+ end
+ if font then
+ -- tex.font = font
+ context.getvalue(fonts.hashes.csnames[font]) -- we don't have a direct way yet (will discuss it with taco)
+ end
+ end
+ -- store[name] = nil
+end
diff --git a/Master/texmf-dist/tex/context/base/attr-ini.mkiv b/Master/texmf-dist/tex/context/base/attr-ini.mkiv
index ba6ca369fc5..a1550b4be98 100644
--- a/Master/texmf-dist/tex/context/base/attr-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -21,16 +21,20 @@
\registerctxluafile{attr-ini}{1.001}
-\def\pushattribute#1%
- {\global\advance\csname\??ae:\string#1\endcsname\plusone
- \global\expandafter\mathchardef\csname\??ae:\string#1:\number\csname\??ae:\string#1\endcsname\endcsname\attribute#1}
+\installcorenamespace{attributecount} % the counter representing the attribute (attrdef'd)
+\installcorenamespace{attributeid} % the internal number
+\installcorenamespace{attributestack} % the attribute specific stack
-\def\popattribute#1%
- {\attribute#1\csname\??ae:\string#1:\number\csname\??ae:\string#1\endcsname\endcsname
- \global\advance\csname\??ae:\string#1\endcsname\minusone}
+\unexpanded\def\pushattribute#1%
+ {\global\advance\csname\??attributestack\string#1\endcsname\plusone
+ \global\expandafter\mathchardef\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname\attribute#1}
-\def\installattributestack#1%
- {\expandafter\newcount\csname\??ae:\string#1\endcsname}
+\unexpanded\def\popattribute#1%
+ {\attribute#1\csname\??attributestack\string#1:\number\csname\??attributestack\string#1\endcsname\endcsname
+ \global\advance\csname\??attributestack\string#1\endcsname\minusone}
+
+\unexpanded\def\installattributestack#1%
+ {\expandafter\newcount\csname\??attributestack\string#1\endcsname}
\newtoks \attributesresetlist
@@ -38,39 +42,43 @@
\ifdefined \s!public \else \def\s!public{public} \fi % for metatex % or hard check later
\unexpanded\def\defineattribute
- {\dodoubleempty\dodefineattribute}
+ {\dodoubleempty\attr_basics_define}
-\def\dodefineattribute[#1][#2]% alternatively we can let lua do the housekeeping
- {\expandafter\newattribute\csname @attr@#1\endcsname
- \expandafter\newconstant \csname :attr:#1\endcsname
- \csname :attr:#1\endcsname\lastallocatedattribute
- \ctxcommand{defineattribute("#1",\number\lastallocatedattribute)}%
- %\writestatus\m!system{defining attribute #1 with number \number\lastallocatedattribute}%
- \doifnotinset\s!global{#2}{\appendetoks\csname @attr@#1\endcsname\attributeunsetvalue\to\attributesresetlist}%
- \doifinset \s!public{#2}{\expandafter\let\csname#1attribute\expandafter\endcsname\csname :attr:#1\endcsname}}
+\def\attr_basics_define[#1][#2]% alternatively we can let lua do the housekeeping
+ {\expandafter\newattribute\csname\??attributecount#1\endcsname
+ \expandafter\newconstant \csname\??attributeid#1\endcsname
+ \csname\??attributeid#1\endcsname\c_syst_last_allocated_attribute
+ \ctxcommand{defineattribute("#1",\number\c_syst_last_allocated_attribute)}%
+ \doifnotinset\s!global{#2}{\appendetoks\csname\??attributecount#1\endcsname\attributeunsetvalue\to\attributesresetlist}%
+ \doifinset \s!public{#2}{\expandafter\let\csname#1attribute\expandafter\endcsname\csname\??attributeid#1\endcsname}}
\unexpanded\def\definesystemattribute
- {\dodoubleempty\dodefinesystemattribute}
+ {\dodoubleempty\attr_basics_define_system}
-\def\dodefinesystemattribute[#1][#2]% alternatively we can let lua do the housekeeping
+\def\attr_basics_define_system[#1][#2]% alternatively we can let lua do the housekeeping
{\scratchcounter\ctxcommand{getprivateattribute("#1")}\relax
- \expandafter\attributedef\csname @attr@#1\endcsname\scratchcounter
- \expandafter\newconstant \csname :attr:#1\endcsname
- \csname :attr:#1\endcsname\scratchcounter
+ \expandafter\attributedef\csname\??attributecount#1\endcsname\scratchcounter
+ \expandafter\newconstant \csname\??attributeid#1\endcsname
+ \csname\??attributeid#1\endcsname\scratchcounter
%\writestatus\m!system{defining system attribute #1 with number \number\scratchcounter}%
- \doifnotinset\s!global{#2}{\appendetoks\csname @attr@#1\endcsname\attributeunsetvalue\to\attributesresetlist}%
- \doifinset \s!public{#2}{\expandafter\let\csname#1attribute\expandafter\endcsname\csname :attr:#1\endcsname}}
+ \doifnotinset\s!global{#2}{\appendetoks\csname\??attributecount#1\endcsname\attributeunsetvalue\to\attributesresetlist}%
+ \doifinset \s!public{#2}{\expandafter\let\csname#1attribute\expandafter\endcsname\csname\??attributeid#1\endcsname}}
% expandable so we can \edef them for speed
-\def\dosetattribute#1#2{\csname @attr@#1\endcsname#2\relax}
-\def\doresetattribute#1{\csname @attr@#1\endcsname\attributeunsetvalue}
-\def\dogetattribute #1{\number\csname @attr@#1\endcsname}
-\def\dogetattributeid#1{\number\csname :attr:#1\endcsname}
+\def\dosetattribute#1#2{\csname\??attributecount#1\endcsname#2\relax}
+\def\doresetattribute#1{\csname\??attributecount#1\endcsname\attributeunsetvalue}
+\def\dogetattribute #1{\number\csname\??attributecount#1\endcsname}
+\def\dogetattributeid#1{\number\csname\??attributeid#1\endcsname}
\let\dompattribute\gobbletwoarguments
-\def\resetallattributes{\the\attributesresetlist}
+\unexpanded\def\resetallattributes{\the\attributesresetlist}
+
+%D Rather special.
+
+\unexpanded\def\savecurrentattributes #1{\ctxcommand{savecurrentattributes ("#1")}}
+\unexpanded\def\restorecurrentattributes#1{\ctxcommand{restorecurrentattributes("#1")}}
%D For the moment we put this here (later it will move to where it's used):
@@ -92,4 +100,6 @@
\definesystemattribute [ruled] [public]
\definesystemattribute [shifted] [public]
+\unexpanded\def\showattributes{\ctxcommand{showattributes()}}
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/attr-lay.lua b/Master/texmf-dist/tex/context/base/attr-lay.lua
index e12938fa45e..bcdc541f7b6 100644
--- a/Master/texmf-dist/tex/context/base/attr-lay.lua
+++ b/Master/texmf-dist/tex/context/base/attr-lay.lua
@@ -98,20 +98,6 @@ local function initializer(...)
return states.initialize(...)
end
-local function register(name,lw) -- if not inimode redefine data[n] in first call
- local stamp = format(template,name)
- local n = registered[stamp]
- if not n then
- n = #values + 1
- values[n] = name
- registered[stamp] = n
- listwise[n] = lw or false
- end
- return registered[stamp] -- == n
-end
-
-viewerlayers.register = register
-
attributes.viewerlayers.handler = nodes.installattributehandler {
name = "viewerlayer",
namespace = viewerlayers,
@@ -120,11 +106,19 @@ attributes.viewerlayers.handler = nodes.installattributehandler {
processor = states.stacked,
}
+local stack, enabled, global = { }, false, false
+
function viewerlayers.enable(value)
if value == false or not viewerlayers.supported then
- tasks.disableaction("shipouts","attributes.viewerlayers.handler")
+ if enabled then
+ tasks.disableaction("shipouts","attributes.viewerlayers.handler")
+ end
+ enabled = false
else
- tasks.enableaction("shipouts","attributes.viewerlayers.handler")
+ if not enabled then
+ tasks.enableaction("shipouts","attributes.viewerlayers.handler")
+ end
+ enabled = true
end
end
@@ -134,16 +128,31 @@ function viewerlayers.forcesupport(value)
viewerlayers.enable(value)
end
+local function register(name,lw) -- if not inimode redefine data[n] in first call
+ if not enabled then
+ viewerlayers.enable(true)
+ end
+ local stamp = format(template,name)
+ local n = registered[stamp]
+ if not n then
+ n = #values + 1
+ values[n] = name
+ registered[stamp] = n
+ listwise[n] = lw or false -- lw forces a used
+ end
+ return registered[stamp] -- == n
+end
+
+viewerlayers.register = register
+
function viewerlayers.setfeatures(hasorder)
viewerlayers.hasorder = hasorder
end
-local stack, enabled, global = { }, false, false
-
function viewerlayers.start(name)
- if not enabled then
- viewerlayers.enable(true)
- end
+-- if not enabled then
+-- viewerlayers.enable(true)
+-- end
insert(stack,texgetattribute(a_viewerlayer))
local a = register(name) or unsetvalue
if global or scopes[name] == v_global then
@@ -188,4 +197,15 @@ function viewerlayers.define(settings)
end
end
-commands.defineviewerlayer = viewerlayers.define
+commands.defineviewerlayer = viewerlayers.define
+commands.startviewerlayer = viewerlayers.start
+commands.stopviewerlayer = viewerlayers.stop
+
+function commands.definedviewerlayer(settings)
+ viewerlayers.define(settings)
+ context(register(settings.tag,true)) -- true forces a use
+end
+
+function commands.registeredviewerlayer(name)
+ context(register(name,true)) -- true forces a use
+end
diff --git a/Master/texmf-dist/tex/context/base/attr-lay.mkiv b/Master/texmf-dist/tex/context/base/attr-lay.mkiv
index b1f3c944e46..67cd204e2f6 100644
--- a/Master/texmf-dist/tex/context/base/attr-lay.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-lay.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Viewerlayers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -15,21 +15,14 @@
\unprotect
-\def\c!printable{printable} % todo
-
\registerctxluafile{attr-lay}{1.001}
% needs to work over stopitemize grouping etc
-\def\registerviewerlayer#1#2% global !
- {\setxvalue{(vl:#1)}{\global\attribute\viewerlayerattribute\ctxlua{tex.write(attributes.viewerlayers.register('#2'))} }}
-
-\setevalue{(vl:)}{\global\attribute\viewerlayerattribute\attributeunsetvalue}
-
-\def\dotriggerviewerlayer % move to lua
- {\ctxlua{attributes.viewerlayers.enable()}%
- \gdef\dotriggerviewerlayer##1{\csname(vl:##1)\endcsname}%
- \dotriggerviewerlayer}
+% \def\registerviewerlayer#1#2% global !
+% {\setxvalue{\??ql:#1}{\global\attribute\viewerlayerattribute\ctxlua{tex.write(attributes.viewerlayers.register('#2'))} }}
+%
+% \setevalue{\??ql:}{\global\attribute\viewerlayerattribute\attributeunsetvalue}
\getparameters
[\??lr]
@@ -58,8 +51,8 @@
\setugvalue{\e!stop #1}{\stopviewerlayer }}%
\endgroup}
-\unexpanded\def\startviewerlayer[#1]{\ctxlua{attributes.viewerlayers.start("#1")}} % not grouped
-\unexpanded\def\stopviewerlayer {\ctxlua{attributes.viewerlayers.stop()}} % not grouped
+\unexpanded\def\startviewerlayer[#1]{\ctxcommand{startviewerlayer("#1")}} % not grouped
+\unexpanded\def\stopviewerlayer {\ctxcommand{stopviewerlayer()}} % not grouped
\unexpanded\def\viewerlayer [#1]{\groupedcommand{\startviewerlayer[#1]}{\stopviewerlayer}} % grouped
% some day we will keep this at the lua end as the info is only needed there
@@ -70,36 +63,36 @@
\appendtoks
\let\currentviewerlayer\empty
-\to \everypagebody
+\to \everybeforepagebody
% layout components are implemented rather directly (speed)
-\def\doinitializelayoutcomponent#1#2%
- {\ctxcommand{defineviewerlayer{% this will move to the lua end i.e be merged with register
- tag = "#1:#2",
- title = "#1 #2",
+\def\doinitializelayoutcomponent#1%
+ {\edef\layoutcomponentboxattribute{\ctxcommand{definedviewerlayer{%
+ tag = "#1",
+ title = utilities.strings.nice("#1"), % only here as in steps we have step:<number>
visible = "\v!start",
editable = "\v!yes",
printable = "\v!yes"
- }}%
- \edef\layoutcomponentboxattribute{attr \viewerlayerattribute \ctxlua{tex.write(attributes.viewerlayers.register('#1:#2',true))}\relax}%
- \expandafter\glet\csname\??ly>#1:#2\endcsname\layoutcomponentboxattribute}
+ }}}%
+ \edef\layoutcomponentboxattribute{attr \viewerlayerattribute \layoutcomponentboxattribute\relax}%
+ \expandafter\glet\csname\??lr:a:#1\endcsname\layoutcomponentboxattribute}
-\def\dosetlayoutcomponentattribute#1#2% make this faster
- {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??ly>#1:#2\endcsname
+\def\dosetlayoutcomponentattribute#1% make this faster
+ {\expandafter\let\expandafter\layoutcomponentboxattribute\csname\??lr:a:#1\endcsname
\ifx\layoutcomponentboxattribute\relax
- \doinitializelayoutcomponent{#1}{#2}% get rid of { }
+ \doinitializelayoutcomponent{#1}% get rid of { }
\fi}
\def\doresetlayoutcomponentattribute
{\let\layoutcomponentboxattribute\empty}
-\let\setlayoutcomponentattribute \gobbletwoarguments
+\let\setlayoutcomponentattribute \gobbleoneargument
\let\resetlayoutcomponentattribute\relax
\let\layoutcomponentboxattribute \empty
\def\showlayoutcomponents
- {\ctxlua{attributes.viewerlayers.enable()}%
+ {\ctxlua{attributes.viewerlayers.enable()}% will go
\let\setlayoutcomponentattribute \dosetlayoutcomponentattribute
\let\resetlayoutcomponentattribute\doresetlayoutcomponentattribute}
diff --git a/Master/texmf-dist/tex/context/base/attr-neg.lua b/Master/texmf-dist/tex/context/base/attr-neg.lua
index 766295a16fd..4d89cb49b64 100644
--- a/Master/texmf-dist/tex/context/base/attr-neg.lua
+++ b/Master/texmf-dist/tex/context/base/attr-neg.lua
@@ -29,6 +29,8 @@ local negatives = attributes.negatives
local a_negative = attributes.private("negative")
+local v_none = interfaces.variables.none
+
negatives.data = allocate()
negatives.attribute = a_negative
@@ -41,7 +43,7 @@ local data = negatives.data
local registered = negatives.registered
local function extender(negatives,key)
- if key == "none" then
+ if key == "none" then -- v_none then
local d = data[1]
negatives.none = d
return d
diff --git a/Master/texmf-dist/tex/context/base/attr-neg.mkiv b/Master/texmf-dist/tex/context/base/attr-neg.mkiv
index 2b817bb711a..0fc5070f1bd 100644
--- a/Master/texmf-dist/tex/context/base/attr-neg.mkiv
+++ b/Master/texmf-dist/tex/context/base/attr-neg.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Negation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -19,7 +19,7 @@
% positive and negative are preregistered
-\def\dotriggernegative#1{\ctxcommand{triggernegative('#1'))}}
+\def\dotriggernegative#1{\ctxcommand{triggernegative('#1')}}
\unexpanded\def\startnegative{\dotriggernegative\v!negative}
\unexpanded\def\stopnegative {\dotriggernegative\v!positive}
diff --git a/Master/texmf-dist/tex/context/base/back-exp.lua b/Master/texmf-dist/tex/context/base/back-exp.lua
index 7f52223a17b..3ce40a6c58b 100644
--- a/Master/texmf-dist/tex/context/base/back-exp.lua
+++ b/Master/texmf-dist/tex/context/base/back-exp.lua
@@ -8,52 +8,37 @@ if not modules then modules = { } end modules ['back-exp'] = {
-- language -> only mainlanguage, local languages should happen through start/stoplanguage
-- tocs/registers -> maybe add a stripper (i.e. just don't flush entries in final tree)
+-- footnotes -> css 3
+-- bodyfont -> in styles.css
+-- delimited -> left/right string (needs marking)
-- Because we need to look ahead we now always build a tree (this was optional in
-- the beginning). The extra overhead in the frontend is neglectable.
-
--- We can consider replacing attributes by the hash entry ... slower in resolving but it's still
--- quite okay.
-
--- todo: less attributes e.g. internal only first node
--- todo: build xml tree in mem (handy for cleaning)
-
--- delimited: left/right string (needs marking)
-
-local nodecodes = nodes.nodecodes
-local traverse_nodes = node.traverse
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-
-local function locate(start,wantedid,wantedsubtype)
- for n in traverse_nodes(start) do
- local id = n.id
- if id == wantedid then
- if not wantedsubtype or n.subtype == wantedsubtype then
- return n
- end
- elseif id == hlist_code or id == vlist_code then
- local found = locate(n.list,wantedid,wantedsubtype)
- if found then
- return found
- end
- end
- end
-end
-
-nodes.locate = locate
+--
+-- We can optimize the code ... currently the overhead is some 10% for xml + html so
+-- there is no hurry.
local next, type = next, type
-local format, match, concat, rep, sub, gsub, gmatch = string.format, string.match, table.concat, string.rep, string.sub, string.gsub, string.gmatch
+local format, match, concat, rep, sub, gsub, gmatch, find = string.format, string.match, table.concat, string.rep, string.sub, string.gsub, string.gmatch, string.find
local lpegmatch = lpeg.match
-local utfchar, utfsub = utf.char, utf.sub
+local utfchar, utfbyte, utfsub, utfgsub = utf.char, utf.byte, utf.sub, utf.gsub
local insert, remove = table.insert, table.remove
+local topoints = number.topoints
+local utfvalues = string.utfvalues
+local fromunicode16 = fonts.mappings.fromunicode16
+local sortedhash = table.sortedhash
+
+local trace_export = false trackers.register ("export.trace", function(v) trace_export = v end)
+local trace_spacing = false trackers.register ("export.trace.spacing", function(v) trace_spacing = v end)
+local less_state = false directives.register("export.lessstate", function(v) less_state = v end)
+local show_comment = true directives.register("export.comment", function(v) show_comment = v end)
-local trace_export = false trackers.register ("structures.export", function(v) trace_export = v end)
-local trace_spaces = false trackers.register ("structures.export.spaces", function(v) trace_spaces = v end)
-local trace_tree = false trackers.register ("structures.export.showtree", function(v) trace_tree = v end)
-local less_state = false directives.register("structures.export.lessstate", function(v) less_state = v end)
-local page_breaks = false directives.register("structures.export.pagebreaks", function(v) page_breaks = v end)
+-- maybe we will also support these:
+--
+-- local css_hyphens = false directives.register("export.css.hyphens", function(v) css_hyphens = v end)
+-- local css_textalign = false directives.register("export.css.textalign", function(v) css_textalign = v end)
+-- local css_bodyfontsize = false directives.register("export.css.bodyfontsize", function(v) css_bodyfontsize = v end)
+-- local css_textwidth = false directives.register("export.css.textwidth", function(v) css_textwidth = v end)
local report_export = logs.reporter("backend","export")
@@ -66,6 +51,7 @@ local settings_to_array = utilities.parsers.settings_to_array
local setmetatableindex = table.setmetatableindex
local tasks = nodes.tasks
local fontchar = fonts.hashes.characters
+local fontquads = fonts.hashes.quads
local languagenames = languages.numbers
local nodecodes = nodes.nodecodes
@@ -82,31 +68,34 @@ local disc_code = nodecodes.disc
local insert_code = nodecodes.insert
local whatsit_code = nodecodes.whatsit
local refximage_code = whatsitcodes.pdfrefximage
+local localpar_code = whatsitcodes.localpar
local userskip_code = skipcodes.userskip
local rightskip_code = skipcodes.rightskip
local parfillskip_code = skipcodes.parfillskip
+local spaceskip_code = skipcodes.spaceskip
+local xspaceskip_code = skipcodes.xspaceskip
local line_code = listcodes.line
-local a_tagged = attributes.private('tagged')
-local a_image = attributes.private('image')
+local a_characters = attributes.private('characters')
+local a_exportstatus = attributes.private('exportstatus')
-local a_taggedalign = attributes.private("taggedalign")
-local a_taggedcolumns = attributes.private("taggedcolumns")
-local a_taggedrows = attributes.private("taggedrows")
+local a_tagged = attributes.private('tagged')
local a_taggedpar = attributes.private("taggedpar")
-local a_taggedpacked = attributes.private("taggedpacked")
-local a_taggedsymbol = attributes.private("taggedsymbol")
-local a_taggedinsert = attributes.private("taggedinsert")
-local a_taggedtag = attributes.private("taggedtag")
-
+local a_image = attributes.private('image')
local a_reference = attributes.private('reference')
+local a_textblock = attributes.private("textblock")
+
local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+local traverse_id = node.traverse_id
local traverse_nodes = node.traverse
local slide_nodelist = node.slide
local texattribute = tex.attribute
+local texdimen = tex.dimen
+local texcount = tex.count
local unsetvalue = attributes.unsetvalue
local locate_node = nodes.locate
@@ -116,32 +105,69 @@ local taglist = structurestags.taglist
local properties = structurestags.properties
local userdata = structurestags.userdata -- might be combines with taglist
local tagdata = structurestags.data
+local tagmetadata = structurestags.metadata
+local detailedtag = structurestags.detailedtag
local starttiming = statistics.starttiming
local stoptiming = statistics.stoptiming
-- todo: more locals (and optimize)
-local version = "0.20"
-local result = nil -- todo: nofresult
-local entry = nil
-local attributehash = { }
-local hyphen = utfchar(0xAD) -- todo: also emdash etc
-local colonsplitter = lpeg.splitat(":")
-local dashsplitter = lpeg.splitat("-")
-local threshold = 65536
-local indexing = false
-local linedone = false
-local inlinedepth = 0
-local tree = { data = { }, depth = 0 } -- root
-local treestack = { }
-local treehash = { }
-local extras = { }
-local nofbreaks = 0
-local used = { }
-local exporting = false
-local last = nil
-local lastpar = nil
+local exportversion = "0.30"
+
+local nofcurrentcontent = 0 -- so we don't free (less garbage collection)
+local currentcontent = { }
+local currentnesting = nil
+local currentattribute = nil
+local last = nil
+local currentparagraph = nil
+
+local noftextblocks = 0
+
+local attributehash = { } -- to be considered: set the values at the tex end
+local hyphencode = 0xAD
+local hyphen = utfchar(0xAD) -- todo: also emdash etc
+local colonsplitter = lpeg.splitat(":")
+local dashsplitter = lpeg.splitat("-")
+local threshold = 65536
+local indexing = false
+local keephyphens = false
+
+local finetuning = { }
+
+local treestack = { }
+local nesting = { }
+local currentdepth = 0
+
+local tree = { data = { }, fulltag == "root" } -- root
+local treeroot = tree
+local treehash = { }
+local extras = { }
+local checks = { }
+local finalizers = { }
+local nofbreaks = 0
+local used = { }
+local exporting = false
+local restart = false
+local specialspaces = { [0x20] = " " } -- for conversion
+local somespace = { [0x20] = true, [" "] = true } -- for testing
+local entities = { ["&"] = "&amp;", [">"] = "&gt;", ["<"] = "&lt;" }
+local attribentities = { ["&"] = "&amp;", [">"] = "&gt;", ["<"] = "&lt;", ['"'] = "quot;" }
+
+local alignmapping = {
+ flushright = "right",
+ middle = "center",
+ flushleft = "left",
+}
+
+local numbertoallign = {
+ [0] = "justify", ["0"] = "justify", [variables.normal ] = "justify",
+ [1] = "right", ["1"] = "right", [variables.flushright] = "right",
+ [2] = "center", ["2"] = "center", [variables.middle ] = "center",
+ [3] = "left", ["3"] = "left", [variables.flushleft ] = "left",
+}
+
+local defaultnature = "mixed" -- "inline"
setmetatableindex(used, function(t,k)
if k then
@@ -151,16 +177,15 @@ setmetatableindex(used, function(t,k)
end
end)
-local joiner_1 = " "
-local joiner_2 = " " -- todo: test if this one can always be ""
-local joiner_3 = " "
-local joiner_4 = " "
-local joiner_5 = " "
-local joiner_6 = " "
-local joiner_7 = "\n"
-local joiner_8 = " "
-local joiner_9 = " "
-local joiner_0 = " "
+setmetatableindex(specialspaces, function(t,k)
+ local v = utfchar(k)
+ t[k] = v
+ entities[v] = format("&#x%X;",k)
+ somespace[k] = true
+ somespace[v] = true
+ return v
+end)
+
local namespaced = {
-- filled on
@@ -185,15 +210,31 @@ local namespaces = {
merror = "m",
math = "m",
mrow = "m",
+ mtable = "m",
+ mtr = "m",
+ mtd = "m",
+ mfenced = "m",
+ maction = "m",
+ mspace = "m",
}
setmetatableindex(namespaced, function(t,k)
- local namespace = namespaces[k]
- local v = namespace and namespace .. ":" .. k or k
- t[k] = v
- return v
+ if k then
+ local namespace = namespaces[k]
+ local v = namespace and namespace .. ":" .. k or k
+ t[k] = v
+ return v
+ end
end)
+local function attribute(key,value)
+ if value and value ~= "" then
+ return format(' %s="%s"',key,gsub(value,".",attribentities))
+ else
+ return ""
+ end
+end
+
-- local P, C, Cc = lpeg.P, lpeg.C, lpeg.Cc
--
-- local dash, colon = P("-"), P(":")
@@ -211,180 +252,375 @@ local function hashlistdata()
local ci = c[i]
local tag = ci.references.tag
if tag then
- listdata[ci.metadata.kind .. ":" .. ci.metadata.name .. "-" .. tag] = ci
+ local m = ci.metadata
+ listdata[m.kind .. ":" .. m.name .. "-" .. tag] = ci
+ end
+ end
+end
+
+--~ local spaces = { } -- watch how we also moved the -1 in depth-1 to the creator
+
+--~ setmetatableindex(spaces, function(t,k)
+--~ if not k then
+--~ return ""
+--~ end
+--~ local s = rep(" ",k-1)
+--~ t[k] = s
+--~ return s
+--~ end)
+
+local spaces = utilities.strings.newrepeater(" ",-1)
+
+function structurestags.setattributehash(fulltag,key,value) -- public hash
+ if type(fulltag) == "number" then
+ fulltag = taglist[fulltag]
+ if fulltag then
+ fulltag = fulltag[#fulltag]
end
end
+ if fulltag then
+ local ah = attributehash[fulltag] -- could be metatable magic
+ if not ah then
+ ah = { }
+ attributehash[fulltag] = ah
+ end
+ ah[key] = value
+ end
+end
+
+
+-- experiment: styles and images
+--
+-- officially we should convert to bp but we round anyway
+
+local usedstyles = { }
+
+-- /* padding : ; */
+-- /* text-justify : inter-word ; */
+
+local documenttemplate = [[
+document {
+ font-size : %s !important ;
+ max-width : %s !important ;
+ text-align : %s !important ;
+ hyphens : %s !important ;
+}
+]]
+
+local styletemplate = [[
+%s[detail='%s'] {
+ font-style : %s ;
+ font-variant : %s ;
+ font-weight : %s ;
+ font-family : %s ;
+ color : %s ;
+}]]
+
+local function allusedstyles(xmlfile)
+ local result = { format("/* styles for file %s */",xmlfile) }
+ --
+ local bodyfont = finetuning.bodyfont
+ local width = finetuning.width
+ local hyphen = finetuning.hyphen
+ local align = finetuning.align
+ --
+ if not bodyfont or bodyfont == "" then
+ bodyfont = "12pt"
+ elseif type(bodyfont) == "number" then
+ bodyfont = number.todimen(bodyfont,"pt","%ipt") or "12pt"
+ end
+ if not width or width == "" then
+ width = "50em"
+ elseif type(width) == "number" then
+ width = number.todimen(width,"pt","%ipt") or "50em"
+ end
+ if hyphen == variables.yes then
+ hyphen = "manual"
+ else
+ hyphen = "inherited"
+ end
+ if align then
+ align = numbertoallign[align]
+ end
+ if not align then
+ align = hyphens and "justify" or "inherited"
+ end
+ --
+ result[#result+1] = format(documenttemplate,bodyfont,width,align,hyphen)
+ --
+ local colorspecification = xml.css.colorspecification
+ local fontspecification = xml.css.fontspecification
+ for element, details in sortedhash(usedstyles) do
+ for detail, data in sortedhash(details) do
+ local s = fontspecification(data.style)
+ local c = colorspecification(data.color)
+ result[#result+1] = format(styletemplate,element,detail,
+ s.style or "inherit",
+ s.variant or "inherit",
+ s.weight or "inherit",
+ s.family or "inherit",
+ c or "inherit")
+ end
+ end
+ return concat(result,"\n\n")
+end
+
+local usedimages = { }
+
+local imagetemplate = [[
+%s[id="%s"] {
+ display : block ;
+ background-image : url(%s) ;
+ background-size : 100%% auto ;
+ background-repeat : no-repeat ;
+ width : %s ;
+ height : %s ;
+}]]
+
+local function allusedimages(xmlfile)
+ local result = { format("/* images for file %s */",xmlfile) }
+ for element, details in sortedhash(usedimages) do
+ for detail, data in sortedhash(details) do
+ local name = data.name
+ if file.extname(name) == "pdf" then
+ -- temp hack .. we will have a remapper
+ name = file.replacesuffix(name,"svg")
+ end
+ result[#result+1] = format(imagetemplate,element,detail,name,data.width,data.height)
+ end
+ end
+ return concat(result,"\n\n")
end
-local spaces = { } -- watch how we also moved the -1 in depth-1 to the creator
+local function uniqueusedimages()
+ local unique = { }
+ for element, details in next, usedimages do
+ for detail, data in next, details do
+ local name = data.name
+ if file.extname(name) == "pdf" then
+ unique[file.replacesuffix(name,"svg")] = name
+ else
+ unique[name] = name
+ end
+ end
+ end
+ return unique
+end
-setmetatableindex(spaces, function(t,k) t[k] = rep(" ",k-1) return t[k] end)
+--
properties.vspace = { export = "break", nature = "display" }
-properties.pbreak = { export = "pagebreak", nature = "display" }
+----------------- = { export = "pagebreak", nature = "display" }
-local function makebreak(entry)
+local function makebreaklist(list)
nofbreaks = nofbreaks + 1
- local t, tl = { }, entry[1]
- if tl then
- for i=1,#tl do
- t[i] = tl[i]
+ local t = { }
+ if list then
+ for i=1,#list do
+ t[i] = list[i]
end
end
- t[#t+1] = "break-" .. nofbreaks
- return { t, { "" }, 0, 0 }
+ t[#t+1] = "break-" .. nofbreaks -- maybe no number
+ return t
end
-local function makebreaknode(node)
+local breakattributes = {
+ type = "collapse"
+}
+
+local function makebreaknode(attributes) -- maybe no fulltag
nofbreaks = nofbreaks + 1
return {
tg = "break",
fulltag = "break-" .. nofbreaks,
n = nofbreaks,
- depth = node.depth,
element = "break",
nature = "display",
- data = { },
- attribute = { } ,
- parnumber = 0,
+ attributes = attributes or nil,
+ -- data = { }, -- not needed
+ -- attribute = 0, -- not needed
+ -- parnumber = 0,
}
end
local fields = { "title", "subtitle", "author", "keywords" }
-function extras.document(handle,element,detail,n,fulltag,hash)
- handle:write(format(" language=%q",languagenames[tex.count.mainlanguagenumber]))
+local function checkdocument(root)
+ local data = root.data
+ if data then
+ for i=1,#data do
+ local di = data[i]
+ if di.content then
+ -- ok
+ elseif di.tg == "ignore" then
+ di.element = ""
+ checkdocument(di)
+ else
+ -- can't happen
+ end
+ end
+ end
+end
+
+function extras.document(result,element,detail,n,fulltag,di)
+ result[#result+1] = format(" language=%q",languagenames[tex.count.mainlanguagenumber])
if not less_state then
- handle:write(format(" file=%q",tex.jobname))
- handle:write(format(" date=%q",os.date()))
- handle:write(format(" context=%q",environment.version))
- handle:write(format(" version=%q",version))
- handle:write(format(" xmlns:m=%q","http://www.w3.org/1998/Math/MathML"))
+ result[#result+1] = format(" file=%q",tex.jobname)
+ result[#result+1] = format(" date=%q",os.date())
+ result[#result+1] = format(" context=%q",environment.version)
+ result[#result+1] = format(" version=%q",exportversion)
+ result[#result+1] = format(" xmlns:m=%q","http://www.w3.org/1998/Math/MathML")
local identity = interactions.general.getidentity()
for i=1,#fields do
local key = fields[i]
local value = identity[key]
if value and value ~= "" then
- handle:write(format(" %s=%q",key,value))
+ result[#result+1] = format(" %s=%q",key,value)
end
end
end
+ checkdocument(di)
end
-local snames, snumbers = { }, { }
+local itemgroups = { }
-function structurestags.setitemgroup(packed,symbol,di)
- local s = snumbers[symbol]
- if not s then
- s = #snames + 1
- snames[s], snumbers[symbol] = symbol, s
+function structurestags.setitemgroup(current,packed,symbol)
+ itemgroups[detailedtag("itemgroup",current)] = {
+ packed = packed,
+ symbol = symbol,
+ }
+end
+
+function extras.itemgroup(result,element,detail,n,fulltag,di)
+ local hash = itemgroups[fulltag]
+ if hash then
+ local v = hash.packed
+ if v then
+ result[#result+1] = " packed='yes'"
+ end
+ local v = hash.symbol
+ if v then
+ result[#result+1] = attribute("symbol",v)
+ end
end
- texattribute[a_taggedpacked] = packed and 1 or unsetvalue
- texattribute[a_taggedsymbol] = s
end
--- todo: per class
+local synonyms = { }
-local synonymnames, synonymnumbers = { }, { } -- can be one hash
+function structurestags.setsynonym(current,tag)
+ synonyms[detailedtag("synonym",current)] = tag
+end
-function structurestags.setsynonym(class,tag)
- local s = synonymnumbers[tag]
- if not s then
- s = #synonymnames + 1
- synonymnames[s], synonymnumbers[tag] = tag, s
+function extras.synonym(result,element,detail,n,fulltag,di)
+ local tag = synonyms[fulltag]
+ if tag then
+ result[#result+1] = format(" tag='%s'",tag)
end
- texattribute[a_taggedtag] = s
end
-local sortingnames, sortingnumbers = { }, { } -- can be one hash
+local sortings = { }
-function structurestags.setsorting(class,tag)
- local s = sortingnumbers[tag]
- if not s then
- s = #sortingnames + 1
- sortingnames[s], sortingnumbers[tag] = tag, s
+function structurestags.setsorting(current,tag)
+ sortings[detailedtag("sorting",current)] = tag
+end
+
+function extras.sorting(result,element,detail,n,fulltag,di)
+ local tag = sortings[fulltag]
+ if tag then
+ result[#result+1] = format(" tag='%s'",tag)
end
- texattribute[a_taggedtag] = s
end
-local insertids = { }
+usedstyles.highlight = { }
-function structurestags.setdescriptionid(tag,n)
+function structurestags.sethighlight(current,style,color) -- we assume global styles
+ usedstyles.highlight[current] = {
+ style = style, -- xml.css.fontspecification(style),
+ color = color, -- xml.css.colorspec(color),
+ }
+end
+
+local descriptions = { }
+local symbols = { }
+local linked = { }
+
+function structurestags.setdescription(tag,n)
local nd = structures.notes.get(tag,n) -- todo: use listdata instead
if nd then
- local r = nd.references
- texattribute[a_taggedinsert] = r.internal or unsetvalue
- else
- texattribute[a_taggedinsert] = unsetvalue
+ local references = nd.references
+ descriptions[references and references.internal] = detailedtag("description",tag)
end
end
-function extras.descriptiontag(handle,element,detail,n,fulltag,di)
- local hash = attributehash[fulltag]
- if hash then
- local v = hash.insert
- v = v and insertids[v]
- if v then
- handle:write(" insert='",v,"'")
- end
+function structurestags.setdescriptionsymbol(tag,n)
+ local nd = structures.notes.get(tag,n) -- todo: use listdata instead
+ if nd then
+ local references = nd.references
+ symbols[references and references.internal] = detailedtag("descriptionsymbol",tag)
end
end
-function extras.descriptionsymbol(handle,element,detail,n,fulltag,di)
- local hash = attributehash[fulltag]
- if hash then
- local v = hash.insert
- v = v and insertids[v]
- if v then
- handle:write(" insert='",v,"'")
+function finalizers.descriptions(tree)
+ local n = 0
+ for id, tag in next, descriptions do
+ local sym = symbols[id]
+ if sym then
+ n = n + 1
+ linked[tag] = n
+ linked[sym] = n
end
end
end
-function extras.synonym(handle,element,detail,n,fulltag,di)
- local hash = attributehash[fulltag]
- if hash then
- local v = hash.tag
- v = v and synonymnames[v]
- if v then
- handle:write(" tag='",v,"'")
- end
+function extras.description(result,element,detail,n,fulltag,di)
+ local id = linked[fulltag]
+ if id then
+ result[#result+1] = format(" insert='%s'",id) -- maybe just fulltag
end
end
-function extras.sorting(handle,element,detail,n,fulltag,di)
- local hash = attributehash[fulltag]
- if hash then
- local v = hash.tag
- v = v and sortingnames[v]
- if v then
- handle:write(" tag='",v,"'")
- end
+function extras.descriptionsymbol(result,element,detail,n,fulltag,di)
+ local id = linked[fulltag]
+ if id then
+ result[#result+1] = format(" insert='%s'",id)
end
end
-function extras.image(handle,element,detail,n,fulltag,di)
- local hash = attributehash[fulltag]
- if hash then
- local v = hash.imageindex
- if v then
- local figure = img.ofindex(v)
- if figure then
- local fullname = figure.filepath
- local name = file.basename(fullname)
- local path = file.dirname(fullname)
- local page = figure.page or 1
- if name ~= "" then
- handle:write(" name='",name,"'")
- end
- if path ~= "" then
- handle:write(" path='",path,"'")
- end
- if page > 1 then
- handle:write(" page='",page,"'")
- end
- end
+usedimages.image = { }
+
+function structurestags.setfigure(name,page,width,height)
+ usedimages.image[detailedtag("image")] = {
+ name = name,
+ page = page,
+ width = number.todimen(width,"cm","%0.3fcm"),
+ height = number.todimen(height,"cm","%0.3fcm"),
+ }
+end
+
+function extras.image(result,element,detail,n,fulltag,di)
+ local data = usedimages.image[fulltag]
+ if data then
+ result[#result+1] = attribute("name",data.name)
+ if tonumber(data.page) > 1 then
+ result[#result+1] = format(" page='%s'",data.page)
end
+ result[#result+1] = format(" id='%s' width='%s' height='%s'",fulltag,data.width,data.height)
+ end
+end
+
+local combinations = { }
+
+function structurestags.setcombination(nx,ny)
+ combinations[detailedtag("combination")] = {
+ nx = nx,
+ ny = ny,
+ }
+end
+
+function extras.combination(result,element,detail,n,fulltag,di)
+ local data = combinations[fulltag]
+ if data then
+ result[#result+1] = format(" nx='%s' ny='%s'",data.nx,data.ny)
end
end
@@ -393,37 +629,37 @@ end
local evaluators = { }
local specials = { }
-evaluators.inner = function(handle,var)
+evaluators.inner = function(result,var)
local inner = var.inner
- if var.inner then
- handle:write(" location='",inner,"'")
+ if inner then
+ result[#result+1] = attribute("location",inner)
end
end
-evaluators.outer = function(handle,var)
+evaluators.outer = function(result,var)
local file, url = references.checkedfileorurl(var.outer,var.outer)
if url then
- handle:write(" url='",url,"'")
+ result[#result+1] = attribute("url",url)
elseif file then
- handle:write(" file='",file,"'")
+ result[#result+1] = attribute("file",file)
end
end
-evaluators["outer with inner"] = function(handle,var)
+evaluators["outer with inner"] = function(result,var)
local file = references.checkedfile(var.f)
if file then
- handle:write(" file='",file,"'")
+ result[#result+1] = attribute("file",file)
end
local inner = var.inner
- if var.inner then
- handle:write(" location='",inner,"'")
+ if inner then
+ result[#result+1] = attribute("location",inner)
end
end
-evaluators.special = function(handle,var)
+evaluators.special = function(result,var)
local handler = specials[var.special]
if handler then
- handler(handle,var)
+ handler(result,var)
end
end
@@ -431,99 +667,449 @@ evaluators["special outer with operation"] = evaluators.special
evaluators["special operation"] = evaluators.special
evaluators["special operation with arguments"] = evaluators.special
-function specials.url(handle,var)
+function specials.url(result,var)
local url = references.checkedurl(var.operation)
if url then
- handle:write(" url='",url,"'")
+ result[#result+1] = attribute("url",url)
end
end
-function specials.file(handle,var)
+function specials.file(result,var)
local file = references.checkedfile(var.operation)
if file then
- handle:write(" file='",file,"'")
+ result[#result+1] = attribute("file",file)
end
end
-function specials.fileorurl(handle,var)
+function specials.fileorurl(result,var)
local file, url = references.checkedfileorurl(var.operation,var.operation)
if url then
- handle:write(" url='",url,"'")
+ result[#result+1] = attribute("url",url)
elseif file then
- handle:write(" file='",file,"'")
+ result[#result+1] = attribute("file",file)
end
end
-function specials.internal(handle,var)
+function specials.internal(result,var)
local internal = references.checkedurl(var.operation)
if internal then
- handle:write(" location='aut:",internal,"'")
+ result[#result+1] = format(" location='aut:%s'",internal)
end
end
-local function adddestination(handle,references) -- todo: specials -> exporters and then concat
+local referencehash = { }
+
+local function adddestination(result,references) -- todo: specials -> exporters and then concat
if references then
local reference = references.reference
if reference and reference ~= "" then
local prefix = references.prefix
if prefix and prefix ~= "" then
- handle:write(" prefix='",prefix,"'")
+ result[#result+1] = format(" prefix='%s'",prefix)
end
- handle:write(" destination='",reference,"'")
+ result[#result+1] = format(" destination='%s'",reference)
for i=1,#references do
local r = references[i]
local e = evaluators[r.kind]
if e then
- e(handle,r)
+ e(result,r)
end
end
end
end
end
-local function addreference(handle,references)
+local function addreference(result,references)
if references then
local reference = references.reference
if reference and reference ~= "" then
local prefix = references.prefix
if prefix and prefix ~= "" then
- handle:write(" prefix='",prefix,"'")
+ result[#result+1] = format(" prefix='%s'",prefix)
end
- handle:write(" reference='",reference,"'")
+ result[#result+1] = format(" reference='%s'",reference)
end
local internal = references.internal
if internal and internal ~= "" then
- handle:write(" location='aut:",internal,"'")
+ result[#result+1] = format(" location='aut:%s'",internal)
end
end
end
-function extras.link(handle,element,detail,n,fulltag,di)
+function extras.link(result,element,detail,n,fulltag,di)
-- for instance in lists a link has nested elements and no own text
- local hash = attributehash[fulltag]
- if hash then
- local references = hash.reference
- if references then
- adddestination(handle,structures.references.get(references))
- end
+ local reference = referencehash[fulltag]
+ if reference then
+ adddestination(result,structures.references.get(reference))
return true
else
local data = di.data
if data then
for i=1,#data do
local di = data[i]
- if di and extras.link(handle,element,detail,n,di.fulltag,di) then
- return true
+ if di then
+ local fulltag = di.fulltag
+ if fulltag and extras.link(result,element,detail,n,fulltag,di) then
+ return true
+ end
end
end
end
end
end
-function extras.section(handle,element,detail,n,fulltag,di)
+-- no settings, as these are obscure ones
+
+local automathrows = true directives.register("backend.export.math.autorows", function(v) automathrows = v end)
+local automathapply = true directives.register("backend.export.math.autoapply", function(v) automathapply = v end)
+local automathnumber = true directives.register("backend.export.math.autonumber", function(v) automathnumber = v end)
+local automathstrip = true directives.register("backend.export.math.autostrip", function(v) automathstrip = v end)
+
+local functions = mathematics.categories.functions
+
+local function collapse(di,i,data,ndata,detail,element)
+ local collapsing = di.data
+ if data then
+ di.element = element
+ di.detail = nil
+ i = i + 1
+ while i <= ndata do
+ local dn = data[i]
+ if dn.detail == detail then
+ collapsing[#collapsing+1] = dn.data[1]
+ dn.skip = "ignore"
+ i = i + 1
+ else
+ break
+ end
+ end
+ end
+ return i
+end
+
+local function collapse_mn(di,i,data,ndata)
+ local collapsing = di.data
+ if data then
+ i = i + 1
+ while i <= ndata do
+ local dn = data[i]
+ local tg = dn.tg
+ if tg == "mn" then
+ collapsing[#collapsing+1] = dn.data[1]
+ dn.skip = "ignore"
+ i = i + 1
+ elseif tg == "mo" then
+ local d = dn.data[1]
+ if d == "." then
+ collapsing[#collapsing+1] = d
+ dn.skip = "ignore"
+ i = i + 1
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ end
+ return i
+end
+
+-- maybe delay __i__ till we need it
+
+local function checkmath(root) -- we can provide utf.toentities as an option
+ local data = root.data
+ if data then
+ local ndata = #data
+ local roottg = root.tg
+ if roottg == "msubsup" then
+ local nucleus, superscript, subscript
+ for i=1,ndata do
+ local di = data[i]
+ if not di then
+ -- weird
+ elseif di.content then
+ -- text
+ elseif not nucleus then
+ nucleus = i
+ elseif not superscript then
+ superscript = i
+ elseif not subscript then
+ subscript = i
+ else
+ -- error
+ end
+ end
+ if superscript and subscript then
+ local sup, sub = data[superscript], data[subscript]
+ data[superscript], data[subscript] = sub, sup
+ -- sub.__o__, sup.__o__ = subscript, superscript
+ sub.__i__, sup.__i__ = superscript, subscript
+ end
+ elseif roottg == "mfenced" then
+ local new, n = { }, 0
+ local attributes = { }
+ root.attributes = attributes
+ for i=1,ndata do
+ local di = data[i]
+ if not di then
+ -- weird
+ elseif di.content then
+ n = n + 1
+ new[n] = di
+ else
+ local tg = di.tg
+ if tg == "mleft" then
+ attributes.left = tostring(di.data[1].data[1].content)
+ elseif tg == "mmiddle" then
+ attributes.middle = tostring(di.data[1].data[1].content)
+ elseif tg == "mright" then
+ attributes.right = tostring(di.data[1].data[1].content)
+ else
+ n = n + 1
+ di.__i__ = n
+ new[n] = di
+ end
+ end
+ end
+ root.data = new
+ ndata = n
+ end
+ if ndata == 0 then
+ return
+ elseif ndata == 1 then
+ local d = data[1]
+ if not d then
+ return
+ elseif d.content then
+ return
+ elseif #root.data == 1 then
+ local tg = d.tg
+ if automathrows and roottg == "mrow" then
+ -- maybe just always ! check spec first
+ if tg == "mrow" or tg == "mfenced" or tg == "mfrac" or tg == "mroot" or tg == "msqrt"then
+ root.skip = "comment"
+ elseif tg == "mo" then
+ root.skip = "comment"
+ end
+ elseif roottg == "mo" then
+ if tg == "mo" then
+ root.skip = "comment"
+ end
+ end
+ end
+ end
+ local i = 1
+ while i <= ndata do -- -- -- TOO MUCH NESTED CHECKING -- -- --
+ local di = data[i]
+ if di and not di.content then
+ local tg = di.tg
+ local detail = di.detail
+ if tg == "math" then
+ -- di.element = "mrow" -- when properties
+ di.skip = "comment"
+ checkmath(di)
+ i = i + 1
+ elseif tg == "mover" or tg == "munder" or tg == "munderover" then
+ if detail == "accent" then
+ di.attributes = { accent = "true" }
+ di.detail = nil
+ end
+ checkmath(di)
+ i = i + 1
+ elseif tg == "mroot" then
+ if #di.data == 1 then
+ -- else firefox complains
+ di.element = "msqrt"
+ end
+ checkmath(di)
+ i = i + 1
+ elseif tg == "break" then
+ di.skip = "comment"
+ i = i + 1
+ elseif tg == "mrow" and detail then
+ di.detail = nil
+ checkmath(di)
+ di = {
+ element = "maction",
+ nature = "display",
+ attributes = { actiontype = detail },
+ data = { di },
+ n = 0,
+ }
+ data[i] = di
+ i = i + 1
+ elseif detail then
+ -- no checkmath(di) here
+ local category = tonumber(detail) or 0
+ if category == 1 then -- mo
+ i = collapse(di,i,data,ndata,detail,"mo")
+ elseif category == 2 then -- mi
+ i = collapse(di,i,data,ndata,detail,"mi")
+ elseif category == 3 then -- mn
+ i = collapse(di,i,data,ndata,detail,"mn")
+ elseif category == 4 then -- ms
+ i = collapse(di,i,data,ndata,detail,"ms")
+ elseif category >= 1000 then
+ local apply = category >= 2000
+ if apply then
+ category = category - 1000
+ end
+ if tg == "mi" then -- function
+ if roottg == "mrow" then
+ root.skip = "comment"
+ root.element = "function"
+ end
+ i = collapse(di,i,data,ndata,detail,"mi")
+ local tag = functions[category]
+ if tag then
+ di.data = { tag }
+ end
+ if apply then
+ di.after = {
+ {
+ element = "mo",
+ -- comment = "apply function",
+ -- data = { utfchar(0x2061) },
+ data = { "&#x2061;" },
+ nature = "mixed",
+ }
+ }
+ elseif automathapply then -- make function
+ local following
+ if i <= ndata then
+ -- normally not the case
+ following = data[i]
+ else
+ local parent = di.__p__ -- == root
+ if parent.tg == "mrow" then
+ parent = parent.__p__
+ end
+ local index = parent.__i__
+ following = parent.data[index+1]
+ end
+ if following then
+ local tg = following.tg
+ if tg == "mrow" or tg == "mfenced" then -- we need to figure out the right condition
+ di.after = {
+ {
+ element = "mo",
+ -- comment = "apply function",
+ -- data = { utfchar(0x2061) },
+ data = { "&#x2061;" },
+ nature = "mixed",
+ }
+ }
+ end
+ end
+ end
+ else -- some problem
+ checkmath(di)
+ i = i + 1
+ end
+ else
+ checkmath(di)
+ i = i + 1
+ end
+ elseif automathnumber and tg == "mn" then
+ checkmath(di)
+ i = collapse_mn(di,i,data,ndata)
+ else
+ checkmath(di)
+ i = i + 1
+ end
+ else -- can be string or boolean
+ if parenttg ~= "mtext" and di == " " then
+ data[i] = false
+ end
+ i = i + 1
+ end
+ end
+ end
+end
+
+function stripmath(di)
+ if not di then
+ --
+ elseif di.content then
+ return di
+ else
+ local tg = di.tg
+ if tg == "mtext" or tg == "ms" then
+ return di
+ else
+ local data = di.data
+ local ndata = #data
+ local n = 0
+ for i=1,ndata do
+ local di = data[i]
+ if di and not di.content then
+ di = stripmath(di)
+ end
+ if di then
+ local content = di.content
+ if not content then
+ n = n + 1
+ di.__i__ = n
+ data[n] = di
+ elseif content == " " or content == "" then
+ -- skip
+ else
+ n = n + 1
+ data[n] = di
+ end
+ end
+ end
+ for i=ndata,n+1,-1 do
+ data[i] = nil
+ end
+ if #data > 0 then
+ return di
+ end
+ end
+ end
+end
+
+function checks.math(di)
+ local hash = attributehash[di.fulltag]
+ local mode = (hash and hash.mode) == "display" and "block" or "inline"
+ di.attributes = {
+ display = mode
+ }
+ -- can be option if needed:
+ if mode == "inline" then
+ di.nature = "mixed" -- else spacing problem (maybe inline)
+ else
+ di.nature = "display"
+ end
+ if automathstrip then
+ stripmath(di)
+ end
+ checkmath(di)
+end
+
+local a, z, A, Z = 0x61, 0x7A, 0x41, 0x5A
+
+function extras.mi(result,element,detail,n,fulltag,di) -- check with content
+ local str = di.data[1].content
+ if str and sub(str,1,1) ~= "&" then -- hack but good enough (maybe gsub op eerste)
+ for v in utfvalues(str) do
+ if (v >= a and v <= z) or (v >= A and v <= Z) then
+ local a = di.attributes
+ if a then
+ a.mathvariant = "normal"
+ else
+ di.attributes = { mathvariant = "normal" }
+ end
+ end
+ end
+ end
+end
+
+function extras.section(result,element,detail,n,fulltag,di)
local data = listdata[fulltag]
if data then
- addreference(handle,data.references)
+ addreference(result,data.references)
return true
else
local data = di.data
@@ -532,7 +1118,7 @@ function extras.section(handle,element,detail,n,fulltag,di)
local di = data[i]
if di then
local ft = di.fulltag
- if ft and extras.section(handle,element,detail,n,ft,di) then
+ if ft and extras.section(result,element,detail,n,ft,di) then
return true
end
end
@@ -541,17 +1127,17 @@ function extras.section(handle,element,detail,n,fulltag,di)
end
end
-function extras.float(handle,element,detail,n,fulltag,di)
+function extras.float(result,element,detail,n,fulltag,di)
local data = listdata[fulltag]
if data then
- addreference(handle,data.references)
+ addreference(result,data.references)
return true
else
local data = di.data
if data then
for i=1,#data do
local di = data[i]
- if di and extras.section(handle,element,detail,n,di.fulltag,di) then
+ if di and extras.section(result,element,detail,n,di.fulltag,di) then
return true
end
end
@@ -559,164 +1145,492 @@ function extras.float(handle,element,detail,n,fulltag,di)
end
end
-function extras.itemgroup(handle,element,detail,n,fulltag,di)
- local data = di.data
- for i=1,#data do
- local di = data[i]
- if type(di) == "table" and di.tg == "item" then
- local ddata = di.data
- for i=1,#ddata do
- local ddi = ddata[i]
- if type(ddi) == "table" then
- local tg = ddi.tg
- if tg == "itemtag" or tg == "itemcontent" then
- local hash = attributehash[ddi.fulltag]
- if hash then
- local v = hash.packed
- if v and v == 1 then
- handle:write(" packed='yes'")
- end
- local v = hash.symbol
- if v then
- handle:write(" symbol='",snames[v],"'")
- end
- return
- end
- end
- end
- end
- end
+local tabledata = { }
+
+function structurestags.settablecell(rows,columns,align)
+ if align > 0 or rows > 1 or columns > 1 then
+ tabledata[detailedtag("tablecell")] = {
+ rows = rows,
+ columns = columns,
+ align = align,
+ }
end
end
-function extras.tablecell(handle,element,detail,n,fulltag,di)
- local hash = attributehash[fulltag]
+function extras.tablecell(result,element,detail,n,fulltag,di)
+ local hash = tabledata[fulltag]
if hash then
+ local v = hash.columns
+ if v and v > 1 then
+ result[#result+1] = format(" columns='%s'",v)
+ end
+ local v = hash.rows
+ if v and v > 1 then
+ result[#result+1] = format(" rows='%s'",v)
+ end
local v = hash.align
if not v or v == 0 then
-- normal
- elseif v == 1 then
- handle:write(" align='flushright'")
+ elseif v == 1 then -- use numbertoalign here
+ result[#result+1] = " align='flushright'"
elseif v == 2 then
- handle:write(" align='middle'")
+ result[#result+1] = " align='middle'"
elseif v == 3 then
- handle:write(" align='flushleft'")
+ result[#result+1] = " align='flushleft'"
end
- local v = hash.columns
- if v and v > 1 then
- handle:write(" columns='",v,"'")
- end
- local v = hash.rows
- if v and v > 1 then
- handle:write(" rows='",v,"'")
+ end
+end
+
+local tabulatedata = { }
+
+function structurestags.settabulatecell(align)
+ if align > 0 then
+ tabulatedata[detailedtag("tabulatecell")] = {
+ align = align,
+ }
+ end
+end
+
+function extras.tabulate(result,element,detail,n,fulltag,di)
+ local data = di.data
+ for i=1,#data do
+ local di = data[i]
+ if di.tg == "tabulaterow" then
+ local did = di.data
+ local content = false
+ for i=1,#did do
+ local d = did[i].data
+ if d and #d > 0 and d[1].content then
+ content = true
+ break
+ end
+ end
+ if not content then
+ di.element = "" -- or simply remove
+ end
end
end
end
-function extras.tabulatecell(handle,element,detail,n,fulltag,di)
- local hash = attributehash[fulltag]
+function extras.tabulatecell(result,element,detail,n,fulltag,di)
+ local hash = tabulatedata[fulltag]
if hash then
local v = hash.align
if not v or v == 0 then
-- normal
elseif v == 1 then
- handle:write(" align='flushright'")
+ result[#result+1] = " align='flushleft'"
elseif v == 2 then
- handle:write(" align='middle'")
+ result[#result+1] = " align='flushright'"
elseif v == 3 then
- handle:write(" align='flushleft'")
+ result[#result+1] = " align='middle'"
end
end
end
-local function emptytag(handle,element,nature,depth)
- handle:write("\n",spaces[depth],"<",namespaced[element],"/>\n")
+-- flusher
+
+local linedone = false -- can go ... we strip newlines anyway
+local inlinedepth = 0
+
+-- todo: #result -> nofresult
+
+local function emptytag(result,element,nature,depth,di) -- currently only break but at some point
+ local a = di.attributes -- we might add detail etc
+ if a then -- happens seldom
+ if linedone then
+ result[#result+1] = format("%s<%s",spaces[depth],namespaced[element])
+ else
+ result[#result+1] = format("\n%s<%s",spaces[depth],namespaced[element])
+ end
+ for k, v in next, a do
+ result[#result+1] = format(" %s=%q",k,v)
+ end
+ result[#result+1] = "/>\n"
+ else
+ if linedone then
+ result[#result+1] = format("%s<%s/>\n",spaces[depth],namespaced[element])
+ else
+ result[#result+1] = format("\n%s<%s/>\n",spaces[depth],namespaced[element])
+ end
+ end
+ linedone = false
end
-local function begintag(handle,element,nature,depth,di,empty)
- local detail, n, fulltag = di.detail, di.n, di.fulltag
+local function begintag(result,element,nature,depth,di,skip)
+ -- if needed we can use a local result with xresult
+ local detail = di.detail
+ local n = di.n
+ local fulltag = di.fulltag
+ local comment = di.comment
if nature == "inline" then
linedone = false
inlinedepth = inlinedepth + 1
+ if show_comment and comment then
+ result[#result+1] = format("<!-- %s -->",comment)
+ end
elseif nature == "mixed" then
if inlinedepth > 0 then
+ if show_comment and comment then
+ result[#result+1] = format("<!-- %s -->",comment)
+ end
elseif linedone then
- handle:write(spaces[depth])
+ result[#result+1] = spaces[depth]
+ if show_comment and comment then
+ result[#result+1] = format("<!-- %s -->",comment)
+ end
else
- handle:write("\n",spaces[depth])
+ result[#result+1] = format("\n%s",spaces[depth])
linedone = false
+ if show_comment and comment then
+ result[#result+1] = format("<!-- %s -->\n%s",comment,spaces[depth])
+ end
end
inlinedepth = inlinedepth + 1
else
if inlinedepth > 0 then
+ if show_comment and comment then
+ result[#result+1] = format("<!-- %s -->",comment)
+ end
elseif linedone then
- handle:write(spaces[depth])
+ result[#result+1] = spaces[depth]
+ if show_comment and comment then
+ result[#result+1] = format("<!-- %s -->",comment)
+ end
else
- handle:write("\n",spaces[depth])
+ result[#result+1] = format("\n%s",spaces[depth]) -- can introduced extra line in mixed+mixed (filtered later on)
linedone = false
+ if show_comment and comment then
+ result[#result+1] = format("<!-- %s -->\n%s",comment,spaces[depth])
+ end
end
end
- handle:write("<",namespaced[element])
- if detail then
- handle:write(" detail='",detail,"'")
- end
- if indexing and n then
- handle:write(" n='",n,"'")
- end
- local extra = extras[element]
- if extra then
- extra(handle,element,detail,n,fulltag,di)
- end
- local u = userdata[fulltag]
- if u then
- for k, v in next, u do
- handle:write(format(" %s=%q",k,v))
+ if skip == "comment" then
+ if show_comment then
+ result[#result+1] = format("<!-- begin %s -->",namespaced[element])
end
+ elseif skip then
+ -- ignore
+ else
+ result[#result+1] = format("<%s",namespaced[element])
+ if detail then
+ result[#result+1] = format(" detail=%q",detail)
+ end
+ if indexing and n then
+ result[#result+1] = format(" n=%q",n)
+ end
+ local extra = extras[element]
+ if extra then
+ extra(result,element,detail,n,fulltag,di)
+ end
+ local u = userdata[fulltag]
+ if u then
+ for k, v in next, u do
+ result[#result+1] = format(" %s=%q",k,v)
+ end
+ end
+ local a = di.attributes
+ if a then
+ for k, v in next, a do
+ result[#result+1] = format(" %s=%q",k,v)
+ end
+ end
+ result[#result+1] = ">"
end
- if not empty then
- handle:write(">")
- if inlinedepth > 0 then
- elseif nature == "display" then
- handle:write("\n")
+ if inlinedepth > 0 then
+ elseif nature == "display" then
+ result[#result+1] = "\n"
+ linedone = true
+ end
+ used[element][detail or ""] = nature -- for template css
+ local metadata = tagmetadata[fulltag]
+ if metadata then
+ if not linedone then
+ result[#result+1] = "\n"
linedone = true
end
+ result[#result+1] = format("%s<metadata>\n",spaces[depth])
+ for k, v in table.sortedpairs(metadata) do
+ v = utfgsub(v,".",entities)
+ result[#result+1] = format("%s<metavariable name=%q>%s</metavariable>\n",spaces[depth+1],k,v)
+ end
+ result[#result+1] = format("%s</metadata>\n",spaces[depth])
end
- used[element][detail or ""] = nature
end
-local function endtag(handle,element,nature,depth,empty)
+local function endtag(result,element,nature,depth,skip)
if nature == "display" then
if inlinedepth == 0 then
- if empty then
- handle:write("</>\n")
- else
- if not linedone then
- handle:write("\n")
+ if not linedone then
+ result[#result+1] = "\n"
+ end
+ if skip == "comment" then
+ if show_comment then
+ result[#result+1] = format("%s<!-- end %s -->\n",spaces[depth],namespaced[element])
end
- handle:write(spaces[depth],"</",namespaced[element],">\n")
+ elseif skip then
+ -- ignore
+ else
+ result[#result+1] = format("%s</%s>\n",spaces[depth],namespaced[element])
end
linedone = true
else
- if empty then
- handle:write("/>")
+ if skip == "comment" then
+ if show_comment then
+ result[#result+1] = format("<!-- end %s -->",namespaced[element])
+ end
+ elseif skip then
+ -- ignore
else
- handle:write("</",namespaced[element],">")
+ result[#result+1] = format("</%s>",namespaced[element])
end
end
else
inlinedepth = inlinedepth - 1
- if empty then
- handle:write("/>")
+ if skip == "comment" then
+ if show_comment then
+ result[#result+1] = format("<!-- end %s -->",namespaced[element])
+ end
+ elseif skip then
+ -- ignore
else
- handle:write("</",namespaced[element],">")
+ result[#result+1] = format("</%s>",namespaced[element])
end
linedone = false
end
end
-local function push(fulltag,depth,entry)
- local attribute, parnumber = entry[3], entry[4]
- -- local tg, detail, n = lpegmatch(tagsplitter,fulltag)
+local function flushtree(result,data,nature,depth)
+ depth = depth + 1
+ local nofdata = #data
+ for i=1,nofdata do
+ local di = data[i]
+ if not di then
+ -- whatever
+ elseif di.content then
+ -- already has breaks
+ local content = utfgsub(di.content,".",entities)
+ if i == nofdata and sub(content,-1) == "\n" then -- move check
+ -- can be an end of line in par but can also be the last line
+ if trace_spacing then
+ result[#result+1] = format("<c n='%s'>%s</c>",di.parnumber or 0,sub(content,1,-2))
+ else
+ result[#result+1] = sub(content,1,-2)
+ end
+ result[#result+1] = " "
+ else
+ if trace_spacing then
+ result[#result+1] = format("<c n='%s'>%s</c>",di.parnumber or 0,content)
+ else
+ result[#result+1] = content
+ end
+ end
+ linedone = false
+ elseif not di.collapsed then -- ignore collapsed data (is appended, reconstructed par)
+ local element = di.element
+ if element == "break" then -- or element == "pagebreak"
+ emptytag(result,element,nature,depth,di)
+ elseif element == "" or di.skip == "ignore" then
+ -- skip
+ else
+ if di.before then
+ flushtree(result,di.before,nature,depth)
+ end
+ local natu = di.nature
+ local skip = di.skip
+ if di.breaknode then
+ emptytag(result,"break","display",depth,di)
+ end
+ begintag(result,element,natu,depth,di,skip)
+ flushtree(result,di.data,natu,depth)
+-- if sub(result[#result],-1) == " " and natu ~= "inline" then
+-- result[#result] = sub(result[#result],1,-2)
+-- end
+ endtag(result,element,natu,depth,skip)
+ if di.after then
+ flushtree(result,di.after,nature,depth)
+ end
+ end
+ end
+ end
+end
+
+local function breaktree(tree,parent,parentelement) -- also removes double breaks
+ local data = tree.data
+ if data then
+ local nofdata = #data
+ local prevelement
+ local prevnature
+ local prevparnumber
+ local newdata = { }
+ local nofnewdata = 0
+ for i=1,nofdata do
+ local di = data[i]
+ if not di then
+ -- skip
+ elseif di.content then
+ local parnumber = di.parnumber
+ if prevnature == "inline" and prevparnumber and prevparnumber ~= parnumber then
+ nofnewdata = nofnewdata + 1
+ if trace_spacing then
+ newdata[nofnewdata] = makebreaknode { type = "a", p = prevparnumber, n = parnumber }
+ else
+ newdata[nofnewdata] = makebreaknode()
+ end
+ end
+ prevelement = nil
+ prevnature = "inline"
+ prevparnumber = parnumber
+ nofnewdata = nofnewdata + 1
+ newdata[nofnewdata] = di
+ elseif not di.collapsed then
+ local element = di.element
+ if element == "break" then -- or element == "pagebreak"
+ if prevelement == "break" then
+ di.element = ""
+ end
+ prevelement = element
+ prevnature = "display"
+ elseif element == "" or di.skip == "ignore" then
+ -- skip
+ else
+ local nature = di.nature
+ local parnumber = di.parnumber
+ if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then
+ nofnewdata = nofnewdata + 1
+ if trace_spacing then
+ newdata[nofnewdata] = makebreaknode { type = "b", p = prevparnumber, n = parnumber }
+ else
+ newdata[nofnewdata] = makebreaknode()
+ end
+ end
+ prevnature = nature
+ prevparnumber = parnumber
+ prevelement = element
+ breaktree(di,tree,element)
+ end
+ nofnewdata = nofnewdata + 1
+ newdata[nofnewdata] = di
+ else
+ local nature = di.nature
+ local parnumber = di.parnumber
+ if prevnature == "inline" and nature == "inline" and prevparnumber and prevparnumber ~= parnumber then
+ nofnewdata = nofnewdata + 1
+ if trace_spacing then
+ newdata[nofnewdata] = makebreaknode { type = "c", p = prevparnumber, n = parnumber }
+ else
+ newdata[nofnewdata] = makebreaknode()
+ end
+ end
+ prevnature = nature
+ prevparnumber = parnumber
+ nofnewdata = nofnewdata + 1
+ newdata[nofnewdata] = di
+ end
+ end
+ tree.data = newdata
+ end
+end
+
+-- also tabulaterow reconstruction .. maybe better as a checker
+-- i.e cell attribute
+
+local function collapsetree()
+ for tag, trees in next, treehash do
+ local d = trees[1].data
+ if d then
+ local nd = #d
+ if nd > 0 then
+ for i=2,#trees do
+ local currenttree = trees[i]
+ local currentdata = currenttree.data
+ local currentpar = currenttree.parnumber
+ local previouspar = trees[i-1].parnumber
+ currenttree.collapsed = true
+ -- is the next ok?
+ if previouspar == 0 or not (di and di.content) then
+ previouspar = nil -- no need anyway so no further testing needed
+ end
+ for j=1,#currentdata do
+ local cd = currentdata[j]
+ if not cd or cd == "" then
+ -- skip
+ elseif cd.content then
+ if not currentpar then
+ -- add space ?
+ elseif not previouspar then
+ -- add space ?
+ elseif currentpar ~= previouspar then
+ nd = nd + 1
+ if trace_spacing then
+ d[nd] = makebreaknode { type = "d", p = previouspar, n = currentpar }
+ else
+ d[nd] = makebreaknode()
+ end
+ end
+ previouspar = currentpar
+ nd = nd + 1
+ d[nd] = cd
+ else
+ nd = nd + 1
+ d[nd] = cd
+ end
+ currentdata[j] = false
+ end
+ end
+ end
+ end
+ end
+end
+
+local function finalizetree(tree)
+ for _, finalizer in next, finalizers do
+ finalizer(tree)
+ end
+end
+
+local function indextree(tree)
+ local data = tree.data
+ if data then
+ local n, new = 0, { }
+ for i=1,#data do
+ local d = data[i]
+ if not d then
+ -- skip
+ elseif d.content then
+ n = n + 1
+ new[n] = d
+ elseif not d.collapsed then
+ n = n + 1
+ d.__i__ = n
+ d.__p__ = tree
+ indextree(d)
+ new[n] = d
+ end
+ end
+ tree.data = new
+ end
+end
+
+local function checktree(tree)
+ local data = tree.data
+ if data then
+ for i=1,#data do
+ local d = data[i]
+ if type(d) == "table" then
+ local check = checks[d.tg]
+ if check then
+ check(d)
+ end
+ checktree(d)
+ end
+ end
+ end
+end
+
+-- collector code
+
+local function push(fulltag,depth)
local tag, n = lpegmatch(dashsplitter,fulltag)
local tg, detail = lpegmatch(colonsplitter,tag)
local element, nature
@@ -724,468 +1638,207 @@ local function push(fulltag,depth,entry)
local pd = properties[tag]
local pt = properties[tg]
element = pd and pd.export or pt and pt.export or tg
- nature = pd and pd.nature or pt and pt.nature or "inline"
+ nature = pd and pd.nature or pt and pt.nature or defaultnature
else
local p = properties[tg]
element = p and p.export or tg
nature = p and p.nature or "inline"
end
+ local treedata = tree.data
local t = {
- -- parent = tree,
tg = tg,
fulltag = fulltag,
detail = detail,
n = tonumber(n), -- more efficient
- depth = depth,
element = element,
nature = nature,
data = { },
- attribute = attribute,
- parnumber = parnumber,
- -- node = entry[5], -- will go
+ attribute = currentattribute,
+ parnumber = currentparagraph,
}
- local treedata = tree.data
treedata[#treedata+1] = t
- insert(treestack,tree)
+ currentdepth = currentdepth + 1
+ nesting[currentdepth] = fulltag
+ treestack[currentdepth] = tree
+ if trace_export then
+ if detail and detail ~= "" then
+ report_export("%s<%s trigger='%s' paragraph='%s' index='%s' detail='%s'>",spaces[currentdepth-1],fulltag,currentattribute or 0,currentparagraph or 0,#treedata,detail)
+ else
+ report_export("%s<%s trigger='%s' paragraph='%s' index='%s'>",spaces[currentdepth-1],fulltag,currentattribute or 0,currentparagraph or 0,#treedata)
+ end
+ end
tree = t
- local h = treehash[fulltag]
- if h then
- h[#h+1] = t
+ if tg == "break" then
+ -- no need for this
else
- treehash[fulltag] = { t }
+ local h = treehash[fulltag]
+ if h then
+ h[#h+1] = t
+ else
+ treehash[fulltag] = { t }
+ end
end
end
local function pop()
- tree = remove(treestack)
+ local top = nesting[currentdepth]
+ tree = treestack[currentdepth]
+ currentdepth = currentdepth - 1
+ if trace_export then
+ if top then
+ report_export("%s</%s>",spaces[currentdepth],top)
+ else
+ report_export("</%s>",top)
+ end
+ end
end
-local function flushresult(entry)
- local current, content = entry[1], entry[2]
- if not content then
- -- skip, normally this cannot happen
- else
- local newdepth, olddepth, content = #current, #treestack, concat(content)
+local function continueexport()
+ if nofcurrentcontent > 0 then
if trace_export then
- report_export("%s => %s : handling: %s",olddepth,newdepth,current[newdepth])
+ report_export("%s<!-- injecting pagebreak space -->",spaces[currentdepth])
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " " -- pagebreak
+ end
+end
+
+local function pushentry(current)
+ if current then
+ if restart then
+ continueexport()
+ restart = false
+ end
+ local newdepth = #current
+ local olddepth = currentdepth
+ if trace_export then
+ report_export("%s<!-- moving from depth %s to %s (%s) -->",spaces[currentdepth],olddepth,newdepth,current[newdepth])
end
if olddepth <= 0 then
for i=1,newdepth do
- if trace_export then
- report_export("[1] push : %s",current[i])
- end
- push(current[i],i,entry)
+ push(current[i],i)
end
- if content then
- tree.data[#tree.data+1] = content
- end
- elseif newdepth < olddepth then
- for i=newdepth,olddepth-1 do
- if trace_export then
- report_export("[2a] pop : %s",current[i])
- end
- pop()
- end
- -- we can have a pagebreak and for instance a new chapter
- -- will mess up the structure then
- for i=newdepth,1,-1 do
- if current[i] ~= treestack[i].fulltag then -- needs checking
- if trace_export then
- report_export("[2b] pop : %s",current[i])
+ else
+ local difference
+ if olddepth < newdepth then
+ for i=1,olddepth do
+ if current[i] ~= nesting[i] then
+ difference = i
+ break
end
- pop()
- else
- break
end
- end
- olddepth = #treestack
- for i=olddepth+1,newdepth do
- if trace_export then
- report_export("[2] push : %s",current[i])
+ else
+ for i=1,newdepth do
+ if current[i] ~= nesting[i] then
+ difference = i
+ break
+ end
end
- push(current[i],i,entry)
- end
- if content then
- tree.data[#tree.data+1] = content
end
- elseif newdepth > olddepth then
- for i=olddepth,1,-1 do
- if current[i] ~= treestack[i].fulltag then
- if trace_export then
- report_export("[3] pop : %s",current[i])
- end
+ if difference then
+ for i=olddepth,difference,-1 do
pop()
- else
- break
end
- end
- olddepth = #treestack
- for i=olddepth+1,newdepth do
- if trace_export then
- report_export("[3] push : %s",current[i])
+ for i=difference,newdepth do
+ push(current[i],i)
end
- push(current[i],i,entry)
- end
- if content then
- tree.data[#tree.data+1] = content
- end
- elseif current[newdepth] == treestack[olddepth] then --move up ?
- -- continuation
- if content then
- tree.data[#tree.data+1] = content
- end
- else
- for i=olddepth,1,-1 do
- if current[i] ~= treestack[i].fulltag then
- if trace_export then
- report_export("[4] pop : %s",current[i])
- end
- pop()
- else
- break
+ elseif newdepth > olddepth then
+ for i=olddepth+1,newdepth do
+ push(current[i],i)
end
- end
- olddepth = #treestack
- for i=olddepth+1,newdepth do
- if trace_export then
- report_export("[4] push : %s",current[i])
+ elseif newdepth < olddepth then
+ for i=olddepth,newdepth,-1 do
+ pop()
end
- push(current[i],i,entry)
- end
- if content then
- tree.data[#tree.data+1] = content
+ elseif trace_export then
+ report_export("%s<!-- staying at depth %s (%s) -->",spaces[currentdepth],newdepth,nesting[newdepth] or "?")
end
end
+ return olddepth, newdepth
end
end
-local function checkinserts(data)
- local nofinserts = 0
- for i=1,#data do
- local di = data[i]
- if type(di) == "table" then -- id ~= false
- if di.element == "descriptionsymbol" then
- local hash = attributehash[di.fulltag]
- if hash then
- local i = hash.insert
- if i then
- nofinserts = nofinserts + 1
- insertids[i] = nofinserts
- end
- else
- -- something is wrong
+local function pushcontent(addbreak)
+ if nofcurrentcontent > 0 then
+ if addbreak then
+ if currentcontent[nofcurrentcontent] == "\n" then
+ if trace_export then
+ report_export("%s<!-- removing newline -->",spaces[currentdepth])
end
- end
- if di.data then
- checkinserts(di.data)
+ nofcurrentcontent = nofcurrentcontent - 1
end
end
- end
-end
-
-local function flushtree(handle,data,nature)
- local nofdata = #data
- for i=1,nofdata do
- local di = data[i]
- if not di then
- -- collapsed
- elseif type(di) == "string" then
-if i == nofdata and sub(di,-1) == joiner_7 then
- if nature == "inline" or nature == "mixed" then
- handle:write(sub(di,1,-2))
- else
- handle:write(sub(di,1,-2)," ")
- end
-else
- handle:write(di)
-end
- linedone = false
- elseif not di.collapsed then
- local element = di.element
- if element == "break" or element == "pagebreak" then
- emptytag(handle,element,nature,di.depth)
- else
- local nature, depth = di.nature, di.depth
- local did = di.data
- local nid = #did
- if nid == 0 or (nid == 1 and did[1] == "") then
- begintag(handle,element,nature,depth,di,true)
- -- no content
- endtag(handle,element,nature,depth,true)
- else
- begintag(handle,element,nature,depth,di)
- flushtree(handle,did,nature)
- endtag(handle,element,nature,depth)
- end
+ local content = concat(currentcontent,"",1,nofcurrentcontent)
+ if content == "" then
+ -- omit; when addbreak we could push, remove spaces, pop
+ elseif somespace[content] and addbreak then
+ -- omit; when addbreak we could push, remove spaces, pop
+ else
+ local olddepth, newdepth
+ local list = taglist[currentattribute]
+ if list then
+ olddepth, newdepth = pushentry(list)
end
- end
- end
-end
-
-local function collapsetree()
- for k, v in next, treehash do
- local d = v[1].data
- local nd = #d
- for i=2,#v do
- local vi = v[i]
- local vd = vi.data
- local done = false
- local lpn = v[i-1].parnumber
- if lpn and lpn == 0 then lpn = nil end
- if type(d[1]) ~= "string" then lpn = nil end -- no need anyway so no further testing needed
-local justdone = false
- for j=1,#vd do
- local vdj = vd[j]
- if type(vdj) == "string" then
---~ print(vdj)
- -- experiment, should be improved
- -- can be simplified ... lpn instead of done
- if done then
- nd = nd + 1
- d[nd] = joiner_1
- else
- done = true
- local pn = vi.parnumber
- if not pn then
- nd = nd + 1
- d[nd] = joiner_2
- lpn = nil
- elseif not lpn then
- nd = nd + 1
- d[nd] = joiner_3
- lpn = pn
- elseif pn and pn ~= lpn then
- nd = nd + 1
- d[nd] = makebreaknode(vi)
- lpn = pn
- else
- -- nd = nd + 1
- -- d[nd] = joiner_4 -- we need to be more clever
- end
- end
- else
---~ nd = nd + 1
---~ d[nd] = joiner_3
- -- lpn = nil
- end
- if vdj ~= "" then
- nd = nd + 1
- d[nd] = vdj -- hm, any?
+ local td = tree.data
+ local nd = #td
+ td[nd+1] = { parnumber = currentparagraph, content = content }
+ if trace_export then
+ report_export("%s<!-- start content with length %s -->",spaces[currentdepth],#content)
+ report_export("%s%s",spaces[currentdepth],(gsub(content,"\n","\\n")))
+ report_export("%s<!-- stop content -->",spaces[currentdepth])
+ end
+ if olddepth then
+ for i=newdepth-1,olddepth,-1 do
+ pop()
end
- vd[j] = false
end
- v[i].collapsed = true
end
+ nofcurrentcontent = 0
end
-end
-
-local function prunetree(tree)
- if not tree.collapsed then
- local data = tree.data
- if data then
- local p, np = { }, 0
- for i=1,#data do
- local d = data[i]
- if type(d) == "table" then
- if not d.collapsed then
- prunetree(d)
- np = np + 1
- p[np] = d
- end
- elseif type(d) == "string" then
- np = np + 1
- p[np] = d
- end
- end
- tree.data = np > 0 and p
+ if addbreak then
+ pushentry(makebreaklist(currentnesting))
+ if trace_export then
+ report_export("%s<!-- break added due to %s -->",spaces[currentdepth],addbreak)
end
end
end
local function finishexport()
- if entry then
- local result = entry[2]
- if result and result[#result] == " " then
- result[#result] = nil -- nicer, remove last space
+ if trace_export then
+ report_export("%s<!-- start finalizing -->",spaces[currentdepth])
+ end
+ if nofcurrentcontent > 0 then
+ if somespace[currentcontent[nofcurrentcontent]] then
+ if trace_export then
+ report_export("%s<!-- removing space -->",spaces[currentdepth])
+ end
+ nofcurrentcontent = nofcurrentcontent - 1
end
- flushresult(entry)
+ pushcontent()
end
- for i=#treestack,1,-1 do
+ for i=currentdepth,1,-1 do
pop()
end
+ currentcontent = { } -- we're nice and do a cleanup
+ if trace_export then
+ report_export("%s<!-- stop finalizing -->",spaces[currentdepth])
+ end
end
-local displaymapping = {
- inline = "inline",
- display = "block",
- mixed = "inline",
-}
+-- whatsit_code localpar_code
-local e_template = [[
-%s {
- display: %s ;
-}]]
-
-local d_template = [[
-%s[detail=%s] {
- display: %s ;
-}]]
-
--- encoding='utf-8'
-
-local xmlpreamble = [[
-<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
-
-<!-- input filename : %- 17s -->
-<!-- processing date : %- 17s -->
-<!-- context version : %- 17s -->
-<!-- exporter version : %- 17s -->
-]]
-
-local csspreamble = [[
-
-<?xml-stylesheet type="text/css" href="%s"?>
-]]
-
-local cssfile, xhtmlfile = nil, nil
-
-directives.register("backend.export.css", function(v) cssfile = v end)
-directives.register("backend.export.xhtml",function(v) xhtmlfile = v end)
-
-local function stopexport(v)
- starttiming(treehash)
- report_export("finalizing")
- finishexport()
- collapsetree()
- if trace_tree then
- prunetree(tree)
- report_export(table.serialize(tree,"root"))
- end
- checkinserts(tree.data)
- hashlistdata()
- if type(v) ~= "string" or v == variables.yes or v == "" then
- v = tex.jobname
- end
- local xmlfile = file.addsuffix(v,"export")
- local handle = io.open(xmlfile,"wb")
- if handle then
- local files = { }
- local specification = {
- name = file.removesuffix(v),
- identifier = os.uuid(),
- files = files,
- }
- report_export("saving xml data in '%s",xmlfile)
- handle:write(format(xmlpreamble,tex.jobname,os.date(),environment.version,version))
- if type(cssfile) == "string" then
- local cssfiles = settings_to_array(cssfile)
- for i=1,#cssfiles do
- local cssfile = cssfiles[i]
- files[#files+1] = cssfile
- if type(cssfile) ~= "string" or cssfile == variables.yes or cssfile == "" or cssfile == xmlfile then
- cssfile = file.replacesuffix(xmlfile,"css")
- else
- cssfile = file.addsuffix(cssfile,"css")
- end
- report_export("adding css reference '%s",cssfile)
- handle:write(format(csspreamble,cssfile))
- end
- end
- flushtree(handle,tree.data)
- handle:close()
- -- css template file
- local cssfile = file.replacesuffix(xmlfile,"template")
- report_export("saving css template in '%s",cssfile)
- local templates = { format("/* template for file %s */",xmlfile) }
- for element, details in table.sortedhash(used) do
- templates[#templates+1] = format("/* category: %s */",element)
- for detail, nature in table.sortedhash(details) do
- local d = displaymapping[nature or "display"] or "block"
- if detail == "" then
- templates[#templates+1] = format(e_template,element,d)
- else
- templates[#templates+1] = format(d_template,element,detail,d)
- end
- end
- end
- io.savedata(cssfile,concat(templates,"\n\n"))
- -- xhtml references
- if xhtmlfile then
- -- messy
- if type(v) ~= "string" or xhtmlfile == true or xhtmlfile == variables.yes or xhtmlfile == "" or xhtmlfile == xmlfile then
- xhtmlfile = file.replacesuffix(xmlfile,"xhtml")
- else
- xhtmlfile = file.addsuffix(xhtmlfile,"xhtml")
- end
- report_export("saving xhtml variant in '%s",xhtmlfile)
- local xmltree = xml.load(xmlfile)
- if xmltree then
- local xmlwrap = xml.wrap
- for e in xml.collected(xmltree,"/document") do
- e.at["xmlns:xhtml"] = "http://www.w3.org/1999/xhtml"
- break
- end
- local wrapper = { tg = "a", ns = "xhtml", at = { href = "unknown" } }
- for e in xml.collected(xmltree,"link") do
- local location = e.at.location
- if location then
- wrapper.at.href = "#" .. gsub(location,":","_")
- xmlwrap(e,wrapper)
- end
- end
- local wrapper = { tg = "a", ns = "xhtml", at = { name = "unknown" } }
- for e in xml.collected(xmltree,"!link[@location]") do
- local location = e.at.location
- if location then
- wrapper.at.name = gsub(location,":","_")
- xmlwrap(e,wrapper)
- end
- end
- xml.save(xmltree,xhtmlfile)
- end
- files[#files+1] = xhtmlfile
- specification.root = xhtmlfile
- local specfile = file.replacesuffix(xmlfile,"specification")
- report_export("saving specification in '%s' (mtxrun --script epub --make %s)",specfile,specfile)
- io.savedata(specfile,table.serialize(specification,true))
- end
+local function tracedchar(c)
+ if c == 0x20 then
+ return "[space]"
+ elseif c == 0 then
+ return "[signal]"
else
- report_export("unable to saving xml in '%s",xmlfile)
- end
- stoptiming(treehash)
-end
-
-local function startexport(v)
- if v and not exporting then
- nodes.tasks.appendaction("shipouts", "normalizers", "nodes.handlers.export")
- report_export("enabling export to xml")
- luatex.registerstopactions(function() stopexport(v) end)
- if trace_spaces then
- joiner_1 = "<S1/>" joiner_2 = "<S2/>" joiner_3 = "<S3/>" joiner_4 = "<S4/>" joiner_5 = "<S5/>"
- joiner_6 = "<S6/>" joiner_7 = "<S7/>" joiner_8 = "<S8/>" joiner_9 = "<S9/>" joiner_0 = "<S0/>"
- end
- exporting = true
+ return utfchar(c)
end
end
-directives.register("backend.export",startexport) -- maybe .name
-
-local function injectbreak()
- flushresult(entry)
- flushresult(makebreak(entry))
- result = { }
- entry = { entry[1], result, last, lastpar } -- entry[1] ?
-end
-
-local function injectspace(a,joiner)
- flushresult(entry)
- result = { joiner }
- local tl = taglist[a]
- entry = { tl , result, a, lastpar, n }
-end
-
-local function collectresults(head,list,p)
- local preceding = p or false
+local function collectresults(head,list) -- is last used (we also have currentattribute)
+ local p
for n in traverse_nodes(head) do
local id = n.id -- 14: image, 8: literal (mp)
if id == glyph_code then
@@ -1198,52 +1851,65 @@ local function collectresults(head,list,p)
-- we could add tonunicodes for ligatures (todo)
local components = n.components
if components then -- we loose data
- collectresults(components,nil,preceding)
---~ preceding = true
+ collectresults(components,nil)
else
+ local c = n.char
if last ~= at then
local tl = taglist[at]
- if entry then
- flushresult(entry)
+-- if trace_export then
+-- report_export("%s<!-- processing glyph %s (tag %s) -->",spaces[currentdepth],utfchar(c),at)
+-- end
+ pushcontent()
+ currentnesting = tl
+ currentparagraph = has_attribute(n,a_taggedpar)
+ currentattribute = at
+ last = at
+ pushentry(currentnesting)
+ if trace_export then
+ report_export("%s<!-- processing glyph %s (tag %s) -->",spaces[currentdepth],tracedchar(c),at)
+ end
+ -- We need to intercept this here; maybe I will also move this
+ -- to a regular setter at the tex end.
+ local r = has_attribute(n,a_reference)
+ if r then
+ referencehash[tl[#tl]] = r -- fulltag
end
- if preceding then
- preceding = false
- result = { joiner_5 }
- else
- result = { }
+ --
+ elseif last then
+ local ap = has_attribute(n,a_taggedpar)
+ if ap ~= currentparagraph then
+ pushcontent(format("new paragraph (%s -> %s)",tostring(currentparagraph),tostring(ap)))
+ pushentry(currentnesting)
+ currentattribute = last
+ currentparagraph = ap
end
- lastpar = has_attribute(n,a_taggedpar)
- entry = { tl, result, at, lastpar, n }
- local ah = { -- this includes detail !
- align = has_attribute(n,a_taggedalign ),
- columns = has_attribute(n,a_taggedcolumns),
- rows = has_attribute(n,a_taggedrows ),
- packed = has_attribute(n,a_taggedpacked ),
- symbol = has_attribute(n,a_taggedsymbol ),
- insert = has_attribute(n,a_taggedinsert ),
- reference = has_attribute(n,a_reference ),
- tag = has_attribute(n,a_taggedtag ), -- used for synonyms
- }
- if next(ah) then
- attributehash[tl[#tl]] = ah
+ if trace_export then
+ report_export("%s<!-- processing glyph %s (tag %s) -->",spaces[currentdepth],tracedchar(c),last)
end
- last = at
- elseif last then
- local at = has_attribute(n,a_taggedpar)
- if at ~= lastpar then
- injectbreak()
- lastpar = at
+ else
+ if trace_export then
+ report_export("%s<!-- processing glyph %s (tag %s) -->",spaces[currentdepth],tracedchar(c),at)
end
end
- local c = n.char
- if c == 0x26 then
- result[#result+1] = "&amp;"
- elseif c == 0x3E then
- result[#result+1] = "&gt;"
- elseif c == 0x3C then
- result[#result+1] = "&lt;"
- elseif c == 0 then
- result[#result+1] = "" -- utfchar(0) -- todo: check if "" is needed
+ local s = has_attribute(n,a_exportstatus)
+ if s then
+ c = s
+ end
+ if c == 0 then
+ if trace_export then
+ report_export("%s<!-- skipping last glyph -->",spaces[currentdepth])
+ end
+ elseif c == 0x20 then
+ local a = has_attribute(n,a_characters)
+ nofcurrentcontent = nofcurrentcontent + 1
+ if a then
+ if trace_export then
+ report_export("%s<!-- turning last space into special space U+%05X -->",spaces[currentdepth],a)
+ end
+ currentcontent[nofcurrentcontent] = specialspaces[a] -- special space
+ else
+ currentcontent[nofcurrentcontent] = " "
+ end
else
local fc = fontchar[n.font]
if fc then
@@ -1251,17 +1917,19 @@ local function collectresults(head,list,p)
if fc then
local u = fc.tounicode
if u and u ~= "" then
- for s in gmatch(u,"....") do -- is this ok?
- result[#result+1] = utfchar(tonumber(s,16))
- end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(fromunicode16(u))
else
- result[#result+1] = utfchar(c)
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(c)
end
else -- weird, happens in hz (we really need to get rid of the pseudo fonts)
- result[#result+1] = utfchar(c)
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(c)
end
else
- result[#result+1] = utfchar(c)
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = utfchar(c)
end
end
end
@@ -1270,112 +1938,483 @@ local function collectresults(head,list,p)
local ai = has_attribute(n,a_image)
if ai then
local at = has_attribute(n,a_tagged)
- if entry then
- flushresult(entry)
- result = { }
- entry[2] = result -- mess, to be sorted out, but otherwise duplicates (still some spacing issues)
+ if nofcurrentcontent > 0 then
+ pushcontent()
+ pushentry(currentnesting) -- ??
end
- local tl = taglist[at]
- local i = locate_node(n,whatsit_code,refximage_code)
- if i then
- attributehash[tl[#tl]] = { imageindex = i.index }
+ pushentry(taglist[at]) -- has an index, todo: flag empty element
+ if trace_export then
+ report_export("%s<!-- processing image (tag %s)",spaces[currentdepth],last)
end
- flushresult { tl, { }, 0, 0 } -- has an index, todo: flag empty element
last = nil
- lastpar = nil
+ currentparagraph = nil
else
---~ if result and #result > 0 then -- and n.subtype == line_code then
---~ local r = result[#result]
---~ if type(r) == "string" and r ~= " " then
---~ local s = utfsub(r,-1)
---~ if s == hyphen then
---~ result[#result] = utfsub(r,1,-2)
---~ elseif s ~= joiner_7 then
---~ result[#result] = r .. joiner_7
---~ --~ preceding = true
---~ end
---~ end
---~ preceding = false
---~ end
-- we need to determine an end-of-line
- preceding = collectresults(n.list,n,preceding)
- preceding = false
+ collectresults(n.list,n)
end
elseif id == disc_code then -- probably too late
+ if keephyphens then
+ local pre = n.pre
+ if pre and not pre.next and pre.id == glyph_code and pre.char == hyphencode then
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = hyphen
+ end
+ end
collectresults(n.replace,nil)
- preceding = false
elseif id == glue_code then
-- we need to distinguish between hskips and vskips
- local subtype = n.subtype
- if subtype == userskip_code then -- todo space_code
- if n.spec.width > threshold then
---~ preceding = true
- if result and last and #result > 0 and result[#result] ~= " " then
+ local ca = has_attribute(n,a_characters)
+ if ca == 0 then
+ -- skip this one ... already converted special character (node-acc)
+ elseif ca then
+ local a = has_attribute(n,a_tagged)
+ if a then
+ local c = specialspaces[ca]
+ if last ~= a then
+ local tl = taglist[a]
+ if trace_export then
+ report_export("%s<!-- processing space glyph U+%05X (tag %s) case 1 -->",spaces[currentdepth],ca,a)
+ end
+ pushcontent()
+ currentnesting = tl
+ currentparagraph = has_attribute(n,a_taggedpar)
+ currentattribute = a
+ last = a
+ pushentry(currentnesting)
+ -- no reference check (see above)
+ elseif last then
+ local ap = has_attribute(n,a_taggedpar)
+ if ap ~= currentparagraph then
+ pushcontent(format("new paragraph (%s -> %s)",tostring(currentparagraph),tostring(ap)))
+ pushentry(currentnesting)
+ currentattribute = last
+ currentparagraph = ap
+ end
+ if trace_export then
+ report_export("%s<!-- processing space glyph U+%05X (tag %s) case 2 -->",spaces[currentdepth],ca,last)
+ end
+ end
+ -- if somespace[currentcontent[nofcurrentcontent]] then
+ -- if trace_export then
+ -- report_export("%s<!-- removing space -->",spaces[currentdepth])
+ -- end
+ -- nofcurrentcontent = nofcurrentcontent - 1
+ -- end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = c
+ end
+ else
+ local subtype = n.subtype
+ if subtype == userskip_code then
+ if n.spec.width > threshold then
+ if last and not somespace[currentcontent[nofcurrentcontent]] then
+ local a = has_attribute(n,a_tagged)
+ if a == last then
+ if trace_export then
+ report_export("%s<!-- injecting spacing 5a -->",spaces[currentdepth])
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ elseif a then
+ -- e.g LOGO<space>LOGO
+ if trace_export then
+ report_export("%s<!-- processing glue > threshold (tag %s => %s) -->",spaces[currentdepth],last,a)
+ end
+ pushcontent()
+ if trace_export then
+ report_export("%s<!-- injecting spacing 5b -->",spaces[currentdepth])
+ end
+ last = a
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
+ end
+ end
+ end
+ elseif subtype == spaceskip_code or subtype == xspaceskip_code then
+ if not somespace[currentcontent[nofcurrentcontent]] then
+ local a = has_attribute(n,a_tagged)
+ if a == last then
+ if trace_export then
+ report_export("%s<!-- injecting spacing 7 (stay in element) -->",spaces[currentdepth])
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ else
+ if trace_export then
+ report_export("%s<!-- injecting spacing 7 (end of element) -->",spaces[currentdepth])
+ end
+ last = a
+ pushcontent()
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
+ end
+ end
+ elseif subtype == rightskip_code then
+ -- a line
+ if nofcurrentcontent > 0 then
+ local r = currentcontent[nofcurrentcontent]
+ if r == hyphen then
+ if not keephyphens then
+ nofcurrentcontent = nofcurrentcontent - 1
+ end
+ elseif not somespace[r] then
+ local a = has_attribute(n,a_tagged)
+ if a == last then
+ if trace_export then
+ report_export("%s<!-- injecting spacing 1 (end of line, stay in element) -->",spaces[currentdepth])
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ else
+ if trace_export then
+ report_export("%s<!-- injecting spacing 1 (end of line, end of element) -->",spaces[currentdepth])
+ end
+ last = a
+ pushcontent()
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
+ end
+ end
+ end
+ elseif subtype == parfillskip_code then
+ -- deal with paragaph endings (crossings) elsewhere and we quit here
+ -- as we don't want the rightskip space addition
+ return
+ end
+ end
+ elseif id == kern_code then
+ local kern = n.kern
+ if kern > 0 then
+ local limit = threshold
+ if p and p.id == glyph_code then
+ limit = fontquads[p.font] / 4
+ end
+ if kern > limit then
+ if last and not somespace[currentcontent[nofcurrentcontent]] then
local a = has_attribute(n,a_tagged)
if a == last then
- result[#result+1] = joiner_6
- preceding = false
+ if not somespace[currentcontent[nofcurrentcontent]] then
+ if trace_export then
+ report_export("%s<!-- injecting spacing 8 (%s) -->",spaces[currentdepth],topoints(kern,true))
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ end
elseif a then
-- e.g LOGO<space>LOGO
- preceding = false
+ if trace_export then
+ report_export("%s<!-- processing kern, threshold %s, tag %s => %s -->",spaces[currentdepth],topoints(limit,true),last,a)
+ end
last = a
- injectspace(last,joiner_6)
+ pushcontent()
+ if trace_export then
+ report_export("%s<!-- injecting spacing 9 (%s) -->",spaces[currentdepth],topoints(kern,true))
+ end
+ nofcurrentcontent = nofcurrentcontent + 1
+ currentcontent[nofcurrentcontent] = " "
+ currentnesting = taglist[last]
+ pushentry(currentnesting)
+ currentattribute = last
end
end
end
- elseif subtype == rightskip_code or subtype == parfillskip_code then
-if result and #result > 0 then -- and n.subtype == line_code then
- local r = result[#result]
- if type(r) == "string" and r ~= " " then
- local s = utfsub(r,-1)
- if s == hyphen then
- result[#result] = utfsub(r,1,-2)
- elseif s ~= joiner_7 then
- result[#result] = r .. joiner_7
---~ preceding = true
+ end
end
+ p = n
end
- preceding = false
end
- end
- elseif id == kern_code then
- if n.kern > threshold then
---~ preceding = true
- if result and last and #result > 0 and result[#result] ~= " " then
- local a = has_attribute(n,a_tagged)
- if a == last then
- result[#result+1] = joiner_8
- preceding = false
- elseif a then
- -- e.g LOGO<space>LOGO
- preceding = false
- last = a
- injectspace(last,joiner_8)
- end
- end
+
+function nodes.handlers.export(head) -- hooks into the page builder
+ starttiming(treehash)
+ if trace_export then
+ report_export("%s<!-- start flushing page -->",spaces[currentdepth])
+ end
+ -- continueexport()
+ restart = true
+ collectresults(head)
+ if trace_export then
+ report_export("%s<!-- stop flushing page -->",spaces[currentdepth])
+ end
+ stoptiming(treehash)
+ return head, true
+end
+
+function builders.paragraphs.tag(head)
+ noftextblocks = noftextblocks + 1
+ for n in traverse_id(hlist_code,head) do
+ local subtype = n.subtype
+ if subtype == line_code then
+ set_attribute(n,a_textblock,noftextblocks)
+ elseif subtype == glue_code or subtype == kern_code then
+ set_attribute(n,a_textblock,0)
+ end
+ end
+ return false
+end
+
+-- encoding='utf-8'
+
+local xmlpreamble = [[
+<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
+
+<!-- input filename : %- 17s -->
+<!-- processing date : %- 17s -->
+<!-- context version : %- 17s -->
+<!-- exporter version : %- 17s -->
+
+]]
+
+local function wholepreamble()
+ return format(xmlpreamble,tex.jobname,os.date(),environment.version,exportversion)
+end
+
+
+local csspreamble = [[
+<?xml-stylesheet type="text/css" href="%s"?>
+]]
+
+local function allusedstylesheets(xmlfile,cssfiles,files)
+ local result = { }
+ for i=1,#cssfiles do
+ local cssfile = cssfiles[i]
+ if type(cssfile) ~= "string" or cssfile == variables.yes or cssfile == "" or cssfile == xmlfile then
+ cssfile = file.replacesuffix(xmlfile,"css")
+ else
+ cssfile = file.addsuffix(cssfile,"css")
+ end
+ files[#files+1] = cssfile
+ report_export("adding css reference '%s",cssfile)
+ result[#result+1] = format(csspreamble,cssfile)
+ end
+ return concat(result)
+end
+
+local e_template = [[
+%s {
+ display: %s ;
+}]]
+
+local d_template = [[
+%s[detail=%s] {
+ display: %s ;
+}]]
+
+local displaymapping = {
+ inline = "inline",
+ display = "block",
+ mixed = "inline",
+}
+
+local function allusedelements(xmlfile)
+ local result = { format("/* template for file %s */",xmlfile) }
+ for element, details in table.sortedhash(used) do
+ result[#result+1] = format("/* category: %s */",element)
+ for detail, nature in table.sortedhash(details) do
+ local d = displaymapping[nature or "display"] or "block"
+ if detail == "" then
+ result[#result+1] = format(e_template,element,d)
+ else
+ result[#result+1] = format(d_template,element,detail,d)
end
end
end
- return preceding
+ return concat(result,"\n\n")
+end
+
+local function allcontent(tree)
+ local result = { }
+ flushtree(result,tree.data,"display",0) -- we need to collect images
+ result = concat(result)
+ result = gsub(result,"\n *\n","\n")
+ result = gsub(result,"\n +([^< ])","\n%1")
+ return result
end
-function nodes.handlers.export(head)
- if result then
- -- maybe we need a better test for what is in result so far
- if page_breaks then
- joiner_0 = "<pagebreak/>"
+-- local xhtmlpreamble = [[
+-- <!DOCTYPE html PUBLIC
+-- "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
+-- "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd"
+-- >
+-- ]]
+
+local function cleanxhtmltree(xmltree)
+ if xmltree then
+ local xmlwrap = xml.wrap
+ for e in xml.collected(xmltree,"/document") do
+ e.at["xmlns:xhtml"] = "http://www.w3.org/1999/xhtml"
+ break
end
- result[#result+1] = joiner_0
+ -- todo: inject xhtmlpreamble (xmlns should have be enough)
+ local wrapper = { tg = "a", ns = "xhtml", at = { href = "unknown" } }
+ for e in xml.collected(xmltree,"link") do
+ local at = e.at
+ local href
+ if at.location then
+ href = "#" .. gsub(at.location,":","_")
+ elseif at.url then
+ href = at.url
+ elseif at.file then
+ href = at.file
+ end
+ if href then
+ wrapper.at.href = href
+ xmlwrap(e,wrapper)
+ end
+ end
+ local wrapper = { tg = "a", ns = "xhtml", at = { name = "unknown" } }
+ for e in xml.collected(xmltree,"!link[@location]") do
+ local location = e.at.location
+ if location then
+ wrapper.at.name = gsub(location,":","_")
+ xmlwrap(e,wrapper)
+ end
+ end
+ return xmltree
+ else
+ return xml.convert("<?xml version='1.0'?>\n<error>invalid xhtml tree</error>")
end
+end
+
+local cssfile, xhtmlfile = nil, nil
+
+directives.register("backend.export.css", function(v) cssfile = v end)
+directives.register("backend.export.xhtml",function(v) xhtmlfile = v end)
+
+local function stopexport(v)
starttiming(treehash)
- collectresults(head)
- -- no flush here, pending page stuff
+ --
+ finishexport()
+ --
+ collapsetree(tree)
+ indextree(tree)
+ checktree(tree)
+ breaktree(tree)
+ finalizetree(tree)
+ --
+ hashlistdata()
+ --
+ if type(v) ~= "string" or v == variables.yes or v == "" then
+ v = tex.jobname
+ end
+ local basename = file.basename(v)
+ local xmlfile = file.addsuffix(basename,"export")
+ --
+ local imagefilename = file.addsuffix(file.removesuffix(xmlfile) .. "-images","css")
+ local stylefilename = file.addsuffix(file.removesuffix(xmlfile) .. "-styles","css")
+ local templatefilename = file.replacesuffix(xmlfile,"template")
+ local specificationfilename = file.replacesuffix(xmlfile,"specification")
+ --
+ if xhtml and not cssfile then
+ cssfile = true
+ end
+ local cssfiles = { }
+ if cssfile then
+ if cssfile == true then
+ cssfiles = { "export-example.css" }
+ else
+ cssfiles = settings_to_array(cssfile or "")
+ end
+ insert(cssfiles,1,imagefilename)
+ insert(cssfiles,1,stylefilename)
+ end
+ cssfiles = table.unique(cssfiles)
+ --
+ local result = allcontent(tree) -- also does some housekeeping and data collecting
+ --
+ local files = {
+ }
+ local results = concat {
+ wholepreamble(),
+ allusedstylesheets(xmlfile,cssfiles,files), -- ads to files
+ result,
+ }
+ --
+ files = table.unique(files)
+ --
+ report_export("saving xml data in '%s",xmlfile)
+ io.savedata(xmlfile,results)
+ --
+ report_export("saving css image definitions in '%s",imagefilename)
+ io.savedata(imagefilename,allusedimages(xmlfile))
+ --
+ report_export("saving css style definitions in '%s",stylefilename)
+ io.savedata(stylefilename,allusedstyles(xmlfile))
+ --
+ report_export("saving css template in '%s",templatefilename)
+ io.savedata(templatefilename,allusedelements(xmlfile))
+ --
+ if xhtmlfile then
+ if type(v) ~= "string" or xhtmlfile == true or xhtmlfile == variables.yes or xhtmlfile == "" or xhtmlfile == xmlfile then
+ xhtmlfile = file.replacesuffix(xmlfile,"xhtml")
+ else
+ xhtmlfile = file.addsuffix(xhtmlfile,"xhtml")
+ end
+ files[#files+1] = xhtmlfile
+ report_export("saving xhtml variant in '%s",xhtmlfile)
+ local xmltree = cleanxhtmltree(xml.convert(results))
+ xml.save(xmltree,xhtmlfile)
+ local specification = {
+ name = file.removesuffix(v),
+ identifier = os.uuid(),
+ images = uniqueusedimages(),
+ root = xhtmlfile,
+ files = files,
+ }
+ report_export("saving specification in '%s' (mtxrun --script epub --make %s)",specificationfilename,specificationfilename)
+ io.savedata(specificationfilename,table.serialize(specification,true))
+ end
stoptiming(treehash)
- return head, true
end
+local appendaction = nodes.tasks.appendaction
+local enableaction = nodes.tasks.enableaction
+
+function commands.setupexport(t)
+ table.merge(finetuning,t)
+ keephyphens = finetuning.hyphen == variables.yes
+end
+
+local function startexport(v)
+ if v and not exporting then
+ report_export("enabling export to xml")
+-- not yet known in task-ini
+ appendaction("shipouts","normalizers", "nodes.handlers.export")
+-- enableaction("shipouts","nodes.handlers.export")
+ enableaction("shipouts","nodes.handlers.accessibility")
+ enableaction("math", "noads.handlers.tags")
+--~ appendaction("finalizers","lists","builders.paragraphs.tag")
+--~ enableaction("finalizers","builders.paragraphs.tag")
+ luatex.registerstopactions(function() stopexport(v) end)
+ exporting = true
+ end
+end
+
+directives.register("backend.export",startexport) -- maybe .name
+
statistics.register("xml exporting time", function()
if exporting then
- return format("%s seconds", statistics.elapsedtime(treehash))
+ return format("%s seconds, version %s", statistics.elapsedtime(treehash),exportversion)
end
end)
+
+-- These are called at the tex end:
+
+commands.settagitemgroup = structurestags.setitemgroup
+commands.settagsynonym = structurestags.setsynonym
+commands.settagsorting = structurestags.setsorting
+commands.settagdescription = structurestags.setdescription
+commands.settagdescriptionsymbol = structurestags.setdescriptionsymbol
+commands.settaghighlight = structurestags.sethighlight
+commands.settagfigure = structurestags.setfigure
+commands.settagcombination = structurestags.setcombination
+commands.settagtablecell = structurestags.settablecell
+commands.settagtabulatecell = structurestags.settabulatecell
diff --git a/Master/texmf-dist/tex/context/base/back-exp.mkiv b/Master/texmf-dist/tex/context/base/back-exp.mkiv
index 88272fca70c..871d08b1991 100644
--- a/Master/texmf-dist/tex/context/base/back-exp.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-exp.mkiv
@@ -5,7 +5,7 @@
%D subtitle=XML export,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -26,25 +26,30 @@
% we can replace this by a more generic attributeset mechanism where we bind
% to any element (needed anyway, see userdata thingies)
-\definesystemattribute[taggedrows] [public]
-\definesystemattribute[taggedcolumns][public]
-\definesystemattribute[taggedalign] [public]
-\definesystemattribute[taggedpar] [public]
-\definesystemattribute[taggedpacked] [public]
-\definesystemattribute[taggedsymbol] [public]
-\definesystemattribute[taggedinsert] [public]
-\definesystemattribute[taggedtag] [public]
+\definesystemattribute[taggedpar][public]
-\def\setelementexporttag
- {\dotripleargument\dosetelementexporttag}
+\unexpanded\def\setelementexporttag
+ {\dotripleargument\back_export_set_element_tag}
-\def\dosetelementexporttag[#1][#2][#3]%
+\def\back_export_set_element_tag
{\ifthirdargument
- \ctxlua{structures.tags.settagproperty("#1","#2", "#3")}%
+ \expandafter \back_export_set_element_tag_a
\else\ifsecondargument
- \ctxlua{structures.tags.settagproperty("#1","export", "#2")}%
+ \doubleexpandafter\back_export_set_element_tag_b
\fi\fi}
+\def\back_export_set_element_tag_a[#1][#2][#3]{\taggedctxcommand{settagproperty("#1","#2","#3")}}
+\def\back_export_set_element_tag_b[#1][#2][#3]{\taggedctxcommand{settagproperty("#1","export","#2")}}
+
+% todo: no need for calls when trialtypesetting
+
+\def\taggedctxcommand
+ {\iftrialtypesetting
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\ctxcommand
+ \fi}
+
\newcount\tagparcounter
\let\dotagsetparcounter\relax
@@ -62,41 +67,50 @@
\to \everytabulatepar % tricky, maybe this should be neverypar
\appendtoks
- \def\dotagnoftablecolumns{\attribute\taggedcolumnsattribute\!!counta}%
- \def\dotagnoftablerows {\attribute\taggedrowsattribute \!!countb}%
+ \unexpanded\def\dotagTABLEcell {\taggedctxcommand{settagtablecell(\number\tablecellrows,\number\tablecellcolumns,\number\raggedstatus)}}%
+ \unexpanded\def\dotagTABLEsignal{\char\zerocount}% brrr, we need to tag empty cells (unless we start numbering)
\to \everyenableelements
\appendtoks
- \def\dotagTABLEalign{\attribute\taggedalignattribute\raggedstatus}%
- \def\dotagTABLEcell {\char\zerocount}%
+ \unexpanded\def\dotagtabulatecell {\taggedctxcommand{settagtabulatecell(\number\c_tabl_tabulate_align)}}%
+ \unexpanded\def\dotagtabulatesignal{\dontleavehmode\char\zerocount\ignorespaces}%
\to \everyenableelements
\appendtoks
- \def\dotagtabulatealign{\attribute\taggedalignattribute\ifcase\tabulatealign\attributeunsetvalue\or\plusthree\or\plusone\or\plustwo\or\attributeunsetvalue\fi}%
+ \unexpanded\def\dotagsynonym{\taggedctxcommand{settagsynonym("\currentsynonym","\currentsynonymtag")}}%
+\to \everyenableelements
+
+\appendtoks % frozen and assumed global per highlight class
+ \unexpanded\def\dotaghighlight{\taggedctxcommand{settaghighlight("\currenthighlight","\highlightparameter\c!style",\number\attribute\colorattribute)}}%
+\to \everyenableelements
+
+\appendtoks % we can have differently scaled images
+ \unexpanded\def\dotagfigure{\taggedctxcommand{settagfigure("\figurefileoriginal","\figurefilepage",\number\dimexpr\figurewidth,\number\dimexpr\figureheight)}}%
\to \everyenableelements
\appendtoks
- \def\dotagsynonym{\ctxlua{structures.tags.setsynonym("\currentsynonym","\currentsynonymtag")}}%
+ \unexpanded\def\dotagcombination{\taggedctxcommand{settagcombination(\combinationparameter\c!nx,\combinationparameter\c!ny)}}%
+ %\unexpanded\def\dotagcombination{\taggedctxcommand{settagcombination(\number\horcombination,\number\totcombination)}}%
\to \everyenableelements
\appendtoks
- \def\dotagsorting{\ctxlua{structures.tags.setsorting("\currentsorting","\currentsortingtag")}}%
+ \unexpanded\def\dotagsorting{\taggedctxcommand{settagsorting("\currentsorting","\currentsortingtag")}}%
\to \everyenableelements
\appendtoks
- \def\dotagsetparcounter{\global\advance\tagparcounter\plusone\attribute\taggedparattribute\tagparcounter}%
+ \unexpanded\def\dotagsetparcounter{\global\advance\tagparcounter\plusone\attribute\taggedparattribute\tagparcounter}%
\to \everyenableelements
\appendtoks
- \def\dotagsetitemize{\ctxlua{structures.tags.setitemgroup(\ifconditional\packlistitem true\else false\fi,"\currentitemsymbol")}}%
+ \unexpanded\def\dotagsetitemgroup{\taggedctxcommand{settagitemgroup("\currentitemgroup",\ifconditional\c_strc_itemgroups_pack true\else false\fi,"\currentitemgroupsymbol")}}%
\to \everyenableelements
\appendtoks
- \def\dotagsetdescriptiontag{\ctxlua{structures.tags.setdescriptionid("\currentdescription",\currentdescriptionnumberentry)}}%
+ \unexpanded\def\dotagsetdescription{\taggedctxcommand{settagdescription("\currentdescription",\currentdescriptionnumberentry)}}%
\to \everyenableelements
\appendtoks
- \def\dotagsetnotesymbol{\ctxlua{structures.tags.setdescriptionid("\currentnote",\currentnotenumber)}}%
+ \unexpanded\def\dotagsetnotesymbol{\taggedctxcommand{settagdescriptionsymbol("\currentnote",\currentnotenumber)}}%
\to \everyenableelements
\appendtoks
@@ -105,9 +119,33 @@
% The action: \setupbackend[export=yes] % or filename
-\def\c!export {export} % maybe: option={css,xhtml}
-\def\c!css {css}
-\def\c!xhtml {xhtml}
+% maybe xhtml css settings will move to setupexport
+
+% maybe some day a definer
+
+\installcorenamespace{export}
+
+\installparameterhandler \??export {export}
+\installsetuphandler \??export {export}
+
+\setupexport
+ [\c!align=\number\raggedstatus,
+ \c!bodyfont=\bodyfontsize,
+ \c!width=\textwidth,
+ \c!hyphen=\v!no]
+
+\def\dosynchronizeexport
+ {\let\currentexport\empty
+ \ctxcommand{setupexport{
+ align = "\exportparameter\c!align",
+ bodyfont = \number\dimexpr\exportparameter\c!bodyfont,
+ width = \number\dimexpr\exportparameter\c!width,
+ hyphen = "\exportparameter\c!hyphen",
+ }}}
+
+\appendtoks
+ \doifsomething{\backendparameter\c!export}{\dosynchronizeexport}%
+\to \everystarttext
\appendtoks
\doifsomething{\backendparameter\c!xhtml}
@@ -118,7 +156,7 @@
\appendtoks
\doifsomething{\backendparameter\c!export}
- {\setupstructure
+ {\setuptagging
[\c!state=\v!start]%
\enabledirectives
[backend.export=\backendparameter\c!export]}%
diff --git a/Master/texmf-dist/tex/context/base/back-ini.lua b/Master/texmf-dist/tex/context/base/back-ini.lua
index 39de73741e2..0c02e201a68 100644
--- a/Master/texmf-dist/tex/context/base/back-ini.lua
+++ b/Master/texmf-dist/tex/context/base/back-ini.lua
@@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['back-ini'] = {
license = "see context related readme files"
}
+local next, type = next, type
+local format = string.format
+local sind, cosd = math.sind, math.cosd
backends = backends or { }
local backends = backends
@@ -73,7 +76,7 @@ end
statistics.register("used backend", function()
local bc = backends.current
if bc ~= "unknown" then
- return string.format("%s (%s)",bc,backends[bc].comment or "no comment")
+ return format("%s (%s)",bc,backends[bc].comment or "no comment")
else
return nil
end
@@ -89,3 +92,11 @@ tables.vfspecials = allocate {
startslant = comment,
stopslant = comment,
}
+
+-- -- experimental code --
+
+function commands.pdfrotation(a)
+ local s, c = sind(a), cosd(a)
+ context("%s %s %s %s",c,s,-s,c)
+end
+
diff --git a/Master/texmf-dist/tex/context/base/back-ini.mkiv b/Master/texmf-dist/tex/context/base/back-ini.mkiv
index a3cf2ca54c4..8ece8f6e13b 100644
--- a/Master/texmf-dist/tex/context/base/back-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -50,12 +50,15 @@
%D Not everything here makes sense and the content of this file will
%D definitely change.
-\let \dostartrotation \gobbleoneargument
-\let \dostoprotation \donothing
-\let \dostartscaling \gobbletwoarguments
-\let \dostopscaling \donothing
-\let \dostartmirroring \donothing
-\let \dostopmirroring \donothing
+\newcount\backendtransformlevel
+
+\let \dostartrotation \gobbleoneargument
+\let \dostoprotation \donothing
+\let \dostartscaling \gobbletwoarguments
+\let \dostopscaling \donothing
+\let \dostartmirroring \donothing
+\let \dostopmirroring \donothing
+\let \dotransformnextbox\gobblesixarguments % and pass last box
%D \macros
%D {doovalbox}
@@ -135,28 +138,19 @@
%D know what the target file will be. In other driver
%D modules we wil set \type {\jobsuffix} to \type {pdf}.
-\def\jobsuffix{pdf}
-
-\ifdefined\resetsystemmode \else % can't happen
- \let\setsystemmode \gobbleoneargument
- \let\resetsystemmode\gobbleoneargument
-\fi
+%D Backend configuration:
-\def\setjobsuffix#1%
- {\resetsystemmode\jobsuffix
- \edef\jobsuffix{#1}%
- \setsystemmode\jobsuffix}
+\installcorenamespace{backend}
-\unexpanded\def\setupoutput[#1]{} % will be command line switch
+\installsetuponlycommandhandler \??backend {backend}
-%D New:
+\let\jobsuffix\empty
-\newtoks\everysetupbackend
-
-\def\backendparameter#1{\csname\ifcsname\??bc#1\endcsname\??bc#1\else\s!empty\fi\endcsname}
+\unexpanded\def\back_job_set_suffix#1% % checking could happen in mode
+ {\ifx\jobsuffix\empty\else\resetsystemmode\jobsuffix\fi
+ \edef\jobsuffix{#1}%
+ \ifx\jobsuffix\empty\else\setsystemmode \jobsuffix\fi}
-\def\setupbackend[#1]%
- {\getparameters[\??bc][#1]%
- \the\everysetupbackend}
+\back_job_set_suffix{pdf} % default
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/back-pdf.lua b/Master/texmf-dist/tex/context/base/back-pdf.lua
index 33cb8c97558..63261aa3b8e 100644
--- a/Master/texmf-dist/tex/context/base/back-pdf.lua
+++ b/Master/texmf-dist/tex/context/base/back-pdf.lua
@@ -6,570 +6,7 @@ if not modules then modules = { } end modules ['back-pdf'] = {
license = "see context related readme files"
}
--- we will move code to lpdf-* files (second cleanup stage in 2011/2012)
-
--- the push/pop is a mess (only needed for calculate ...) .. will be done differently
-
---[[ldx--
-<p>This module implements a couple of cleanup methods. We need these
-in order to meet the <l n='pdf'/> specification. Watch the double
-parenthesis; they are needed because otherwise we would pass more
-than one argument to <l n='tex'/>.</p>
---ldx]]--
-
-local type, next, tostring = type, next, tostring
-local char, byte, format, gsub, rep, gmatch = string.char, string.byte, string.format, string.gsub, string.rep, string.gmatch
-local concat = table.concat
-local round = math.round
-local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
-
-local backends, lpdf, nodes, node = backends, lpdf, nodes, node
-
-local copy_node = node.copy
-
-local nodeinjections = backends.pdf.nodeinjections
-local codeinjections = backends.pdf.codeinjections
-local registrations = backends.pdf.registrations
-
-local nodepool = nodes.pool
-
-local register = nodepool.register
-
-local pdfconstant = lpdf.constant
-local pdfstring = lpdf.string
-local pdfdictionary = lpdf.dictionary
-local pdfarray = lpdf.array
-local pdfreference = lpdf.reference
-local pdfverbose = lpdf.verbose
-local pdfflushobject = lpdf.flushobject
-local pdfimmediateobject = lpdf.immediateobject
-
-local pdfliteral = nodepool.pdfliteral
-local pdfannotation_node = nodepool.pdfannotation
-
-function nodeinjections.rgbcolor(r,g,b)
- return register(pdfliteral(format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)))
-end
-
-function nodeinjections.cmykcolor(c,m,y,k)
- return register(pdfliteral(format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)))
-end
-
-function nodeinjections.graycolor(s) -- caching 0/1 does not pay off
- return register(pdfliteral(format("%s g %s G",s,s)))
-end
-
-function nodeinjections.spotcolor(n,f,d,p)
- if type(p) == "string" then
- p = gsub(p,","," ") -- brr misuse of spot
- end
- return register(pdfliteral(format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)))
-end
-
-function nodeinjections.transparency(n)
- return register(pdfliteral(format("/Tr%s gs",n)))
-end
-
-local effects = {
- normal = 0,
- inner = 0,
- outer = 1,
- both = 2,
- hidden = 3,
-}
-
-function nodeinjections.effect(effect,stretch,rulethickness)
- -- always, no zero test (removed)
- rulethickness = number.dimenfactors["bp"] * rulethickness
- effect = effects[effect] or effects['normal']
- return register(pdfliteral(format("%s Tc %s w %s Tr",stretch,rulethickness,effect))) -- watch order
-end
-
--- cached ..
-
-local cache = { }
-
-function codeinjections.startlayer(name)
- codeinjections.useviewerlayer(name)
- return format("/OC /%s BDC",name)
-end
-
-function codeinjections.stoplayer(name)
- return "EMC"
-end
-
-function nodeinjections.startlayer(name)
- local c = cache[name]
- if not c then
- codeinjections.useviewerlayer(name)
- c = register(pdfliteral(format("/OC /%s BDC",name)))
- cache[name] = c
- end
- return copy_node(c)
-end
-
-local stop = register(pdfliteral("EMC"))
-
-function nodeinjections.stoplayer()
- return copy_node(stop)
-end
-
-local cache = { }
-
-function nodeinjections.switchlayer(name) -- not used, optimization
- local c = cache[name]
- if not c then
- codeinjections.useviewerlayer(name)
- c = register(pdfliteral(format("EMC /OC /%s BDC",name)))
- end
- return copy_node(c)
-end
-
--- code, will move to lpdf-*
-
-function nodeinjections.insertmovie(specification)
- -- managed in figure inclusion: width, height, factor, repeat, controls, preview, label, foundname
- local width = specification.width
- local height = specification.height
- local factor = specification.factor or number.dimenfactors.bp
- local moviedict = pdfdictionary {
- F = specification.foundname,
- Aspect = pdfarray { factor * width, factor * height },
- Poster = (specification.preview and true) or false,
- }
- local controldict = pdfdictionary {
- ShowControls = (specification.controls and true) or false,
- Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil,
- }
- local action = pdfdictionary {
- Subtype = pdfconstant("Movie"),
- Border = pdfarray { 0, 0, 0 },
- T = format("movie %s",specification.label),
- Movie = moviedict,
- A = controldict,
- }
- node.write(pdfannotation_node(width,height,0,action()))
-end
-
-function nodeinjections.insertsound(specification)
- -- rmanaged in interaction: repeat, label, foundname
- local soundclip = interactions.soundclips.soundclip(specification.label)
- if soundclip then
- local controldict = pdfdictionary {
- Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil
- }
- local sounddict = pdfdictionary {
- F = soundclip.filename
- }
- local action = pdfdictionary {
- Subtype = pdfconstant("Movie"),
- Border = pdfarray { 0, 0, 0 },
- T = format("sound %s",specification.label),
- Movie = sounddict,
- A = controldict,
- }
- node.write(pdfannotation_node(0,0,0,action()))
- end
-end
-
--- spot- and indexcolors
-
-local pdf_separation = pdfconstant("Separation")
-local pdf_indexed = pdfconstant("Indexed")
-local pdf_device_n = pdfconstant("DeviceN")
-local pdf_device_rgb = pdfconstant("DeviceRGB")
-local pdf_device_cmyk = pdfconstant("DeviceCMYK")
-local pdf_device_gray = pdfconstant("DeviceGray")
-local pdf_extgstate = pdfconstant("ExtGState")
-
-local pdf_rbg_range = pdfarray { 0, 1, 0, 1, 0, 1 }
-local pdf_cmyk_range = pdfarray { 0, 1, 0, 1, 0, 1, 0, 1 }
-local pdf_gray_range = pdfarray { 0, 1 }
-
-local rgb_function = "dup %s mul exch dup %s mul exch %s mul"
-local cmyk_function = "dup %s mul exch dup %s mul exch dup %s mul exch %s mul"
-local gray_function = "%s mul"
-
-local documentcolorspaces = pdfdictionary()
-
-local spotcolorhash = { } -- not needed
-local spotcolornames = { }
-local indexcolorhash = { }
-local delayedindexcolors = { }
-
-function registrations.spotcolorname(name,e)
- spotcolornames[name] = e or name
-end
-
-function registrations.getspotcolorreference(name)
- return spotcolorhash[name]
-end
-
--- beware: xpdf/okular/evince cannot handle the spot->process shade
-
-local processcolors
-
-local function registersomespotcolor(name,noffractions,names,p,colorspace,range,funct)
- noffractions = tonumber(noffractions) or 1 -- to be checked
- if noffractions == 0 then
- -- can't happen
- elseif noffractions == 1 then
- local dictionary = pdfdictionary {
- FunctionType = 4,
- Domain = { 0, 1 },
- Range = range,
- }
- local calculations = pdfimmediateobject("stream",format("{ %s }",funct),dictionary()) -- todo: lpdf.stream
- -- local calculations = pdfobject {
- -- type = "stream",
- -- immediate = true,
- -- string = format("{ %s }",funct),
- -- attr = dictionary(),
- -- }
- local array = pdfarray {
- pdf_separation,
- pdfconstant(spotcolornames[name] or name),
- colorspace,
- pdfreference(calculations),
- }
- local m = pdfimmediateobject(tostring(array))
- local mr = pdfreference(m)
- spotcolorhash[name] = m
- documentcolorspaces[name] = mr
- lpdf.adddocumentcolorspace(name,mr)
- else
- local cnames = pdfarray()
- local domain = pdfarray()
- local colorants = pdfdictionary()
- for n in gmatch(names,"[^,]+") do
- local name = spotcolornames[n] or n
- if n == "cyan" then
- name = "Cyan"
- elseif n == "magenta" then
- name = "Magenta"
- elseif n == "yellow" then
- name = "Yellow"
- elseif n == "black" then
- name = "Black"
- else
- colorants[name] = pdfreference(spotcolorhash[name] or spotcolorhash[n])
- end
- cnames[#cnames+1] = pdfconstant(name)
- domain[#domain+1] = 0
- domain[#domain+1] = 1
- end
- if not processcolors then
- local specification = pdfdictionary {
- ColorSpace = pdfconstant("DeviceCMYK"),
- Components = pdfarray {
- pdfconstant("Cyan"),
- pdfconstant("Magenta"),
- pdfconstant("Yellow"),
- pdfconstant("Black")
- }
- }
- processcolors = pdfreference(pdfimmediateobject(tostring(specification)))
- end
- local dictionary = pdfdictionary {
- FunctionType = 4,
- Domain = domain,
- Range = range,
- }
- local calculation = pdfimmediateobject("stream",format("{ %s %s }",rep("pop ",noffractions),funct),dictionary())
- local channels = pdfdictionary {
- Subtype = pdfconstant("NChannel"),
- Colorants = colorants,
- Process = processcolors,
- }
- local array = pdfarray {
- pdf_device_n,
- cnames,
- colorspace,
- pdfreference(calculation),
- lpdf.shareobjectreference(tostring(channels)), -- optional but needed for shades
- }
- local m = pdfimmediateobject(tostring(array))
- local mr = pdfreference(m)
- spotcolorhash[name] = m
- documentcolorspaces[name] = mr
- lpdf.adddocumentcolorspace(name,mr)
- end
-end
-
--- wrong name
-
-local function registersomeindexcolor(name,noffractions,names,p,colorspace,range,funct)
- noffractions = tonumber(noffractions) or 1 -- to be checked
- local cnames = pdfarray()
- local domain = pdfarray()
- if names == "" then
- names = name .. ",None"
- else
- names = names .. ",None"
- end
- for n in gmatch(names,"[^,]+") do
- cnames[#cnames+1] = pdfconstant(spotcolornames[n] or n)
- domain[#domain+1] = 0
- domain[#domain+1] = 1
- end
- local dictionary = pdfdictionary {
- FunctionType = 4,
- Domain = domain,
- Range = range,
- }
- local n = pdfimmediateobject("stream",format("{ %s %s }",rep("exch pop ",noffractions),funct),dictionary()) -- exch pop
- local a = pdfarray {
- pdf_device_n,
- cnames,
- colorspace,
- pdfreference(n),
- }
- if p == "" then
- p = "1"
- else
- p = p .. ",1"
- end
- local pi = { }
- for pp in gmatch(p,"[^,]+") do
- pi[#pi+1] = tonumber(pp)
- end
- local vector, set, n = { }, { }, #pi
- for i=255,0,-1 do
- for j=1,n do
- set[j] = format("%02X",round(pi[j]*i))
- end
- vector[#vector+1] = concat(set)
- end
- vector = pdfverbose { "<", concat(vector, " "), ">" }
- local n = pdfimmediateobject(tostring(pdfarray{ pdf_indexed, a, 255, vector }))
- lpdf.adddocumentcolorspace(format("%s_indexed",name),pdfreference(n))
- return n
-end
-
--- actually, names (parent) is the hash
-
-local function delayindexcolor(name,names,func)
- local hash = (names ~= "" and names) or name
- delayedindexcolors[hash] = func
-end
-
-local function indexcolorref(name) -- actually, names (parent) is the hash
- if not indexcolorhash[name] then
- local delayedindexcolor = delayedindexcolors[name]
- if type(delayedindexcolor) == "function" then
- indexcolorhash[name] = delayedindexcolor()
- delayedindexcolors[name] = true
- end
- end
- return indexcolorhash[name]
-end
-
-function registrations.rgbspotcolor(name,noffractions,names,p,r,g,b)
---~ print(name,noffractions,names,p,r,g,b)
- if noffractions == 1 then
- registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,format(rgb_function,r,g,b))
- else
- registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,format("%s %s %s",r,g,b))
- end
- delayindexcolor(name,names,function()
- return registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,format(rgb_function,r,g,b))
- end)
-end
-
-function registrations.cmykspotcolor(name,noffractions,names,p,c,m,y,k)
- if noffractions == 1 then
- registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
- else
- registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format("%s %s %s %s",c,m,y,k))
- end
- delayindexcolor(name,names,function()
- return registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
- end)
-end
-
-function registrations.grayspotcolor(name,noffractions,names,p,s)
- if noffractions == 1 then
- registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,format(gray_function,s))
- else
- registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,s)
- end
- delayindexcolor(name,names,function()
- return registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,format(gray_function,s))
- end)
-end
-
-function registrations.rgbindexcolor(name,noffractions,names,p,r,g,b)
- registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,format(rgb_function,r,g,b))
-end
-
-function registrations.cmykindexcolor(name,noffractions,names,p,c,m,y,k)
- registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
-end
-
-function registrations.grayindexcolor(name,noffractions,names,p,s)
- registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,gray_function)
-end
-
-function codeinjections.setfigurecolorspace(data,figure)
- local color = data.request.color
- if color then
- local ref = indexcolorref(color)
- if ref then
- figure.colorspace = ref
- data.used.color = color
- end
- end
-end
-
--- transparency
-
-local transparencies = { [0] =
- pdfconstant("Normal"),
- pdfconstant("Normal"),
- pdfconstant("Multiply"),
- pdfconstant("Screen"),
- pdfconstant("Overlay"),
- pdfconstant("SoftLight"),
- pdfconstant("HardLight"),
- pdfconstant("ColorDodge"),
- pdfconstant("ColorBurn"),
- pdfconstant("Darken"),
- pdfconstant("Lighten"),
- pdfconstant("Difference"),
- pdfconstant("Exclusion"),
- pdfconstant("Compatible"),
-}
-
-local documenttransparencies = { }
-local transparencyhash = { } -- share objects
-
-local done = false
-
-function registrations.transparency(n,a,t)
- if not done then
- local d = pdfdictionary {
- Type = pdf_extgstate,
- ca = 1,
- CA = 1,
- BM = transparencies[1],
- AIS = false,
- }
- local m = pdfimmediateobject(tostring(d))
- local mr = pdfreference(m)
- transparencyhash[0] = m
- documenttransparencies[0] = mr
- lpdf.adddocumentextgstate("Tr0",mr)
- done = true
- end
- if n > 0 and not transparencyhash[n] then
- local d = pdfdictionary {
- Type = pdf_extgstate,
- ca = tonumber(t),
- CA = tonumber(t),
- BM = transparencies[tonumber(a)] or transparencies[0],
- AIS = false,
- }
- local m = pdfimmediateobject(tostring(d))
- local mr = pdfreference(m)
- transparencyhash[n] = m
- documenttransparencies[n] = mr
- lpdf.adddocumentextgstate(format("Tr%s",n),mr)
- end
-end
-
--- overloaded in lpdf-xmp:
-
-function codeinjections.adddocumentinfo(key,value)
- lpdf.addtoinfo(key,lpdf.tosixteen(value))
-end
-
--- graphics
-
-function codeinjections.setfigurealternative(data,figure)
- local request = data.request
- local display = request.display
- if display and display ~= "" then
- local nested = figures.push {
- name = display,
- page = request.page,
- size = request.size,
- prefix = request.prefix,
- cache = request.cache,
- width = request.width,
- height = request.height,
- }
- figures.identify()
- local displayfigure = figures.check()
- if displayfigure then
- -- figure.aform = true
- img.immediatewrite(figure)
- local a = pdfarray {
- pdfdictionary {
- Image = pdfreference(figure.objnum),
- DefaultForPrinting = true,
- }
- }
- local d = pdfdictionary {
- Alternates = pdfreference(pdfimmediateobject(tostring(a))),
- }
- displayfigure.attr = d()
- figures.pop()
- return displayfigure, nested
- else
- figures.pop()
- end
- end
-end
-
-function codeinjections.getpreviewfigure(request)
- local figure = figures.initialize(request)
- if not figure then
- return
- end
- figure = figures.identify(figure)
- if not figure then
- return
- end
- figure = figures.check(figure)
- if not figure then
- return
- end
- local image = figure.status.private
- if image then
- img.immediatewrite(image)
- end
- return figure
-end
-
-function codeinjections.setfiguremask(data,figure) -- mark
- local request = data.request
- local mask = request.mask
- if mask and mask ~= "" then
- figures.push {
- name = mask,
- page = request.page,
- size = request.size,
- prefix = request.prefix,
- cache = request.cache,
- width = request.width,
- height = request.height,
- }
- figures.identify()
- local maskfigure = figures.check()
- if maskfigure then
- local image = maskfigure.status.private
- if image then
- img.immediatewrite(image)
- local d = pdfdictionary {
- Interpolate = false,
- SMask = pdfreference(image.objnum),
- }
- figure.attr = d()
- end
- end
- figures.pop()
- end
-end
+local codeinjections = backends.pdf.codeinjections
local outputfilename
@@ -580,35 +17,4 @@ function codeinjections.getoutputfilename()
return outputfilename
end
--- temp hack
-
-local factor = number.dimenfactors.bp
-
-function img.package(image)
- local boundingbox = image.bbox
- local imagetag = "Im" .. image.index
- local resources = pdfdictionary {
- ProcSet = pdfarray {
- pdfconstant("PDF"),
- pdfconstant("ImageC")
- },
- Resources = pdfdictionary {
- XObject = pdfdictionary {
- [imagetag] = pdfreference(image.objnum)
- }
- }
- }
- local width = boundingbox[3]
- local height = boundingbox[4]
- local xform = img.scan {
- attr = resources(),
- stream = format("%s 0 0 %s 0 0 cm /%s Do",width,height,imagetag),
- bbox = { 0, 0, width/factor, height/factor },
- }
- img.immediatewrite(xform)
- return xform
-end
-
--- till here
-
backends.install("pdf")
diff --git a/Master/texmf-dist/tex/context/base/back-pdf.mkiv b/Master/texmf-dist/tex/context/base/back-pdf.mkiv
index 5b7de128de4..9e441e224a6 100644
--- a/Master/texmf-dist/tex/context/base/back-pdf.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-pdf.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\PDF,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -13,16 +13,18 @@
\writestatus{loading}{ConTeXt Backend Macros / PDF}
+%registerctxluafile{lpdf-aux}{1.001} % common helpers
\registerctxluafile{lpdf-ini}{1.001}
+\registerctxluafile{lpdf-nod}{1.001}
\registerctxluafile{lpdf-col}{1.000}
\registerctxluafile{lpdf-xmp}{1.001}
-\registerctxluafile{lpdf-nod}{1.001}
\registerctxluafile{lpdf-mis}{1.001}
\registerctxluafile{lpdf-ano}{1.001}
\registerctxluafile{lpdf-ren}{1.001}
\registerctxluafile{lpdf-grp}{1.001}
\registerctxluafile{lpdf-wid}{1.001}
\registerctxluafile{lpdf-fld}{1.001}
+\registerctxluafile{lpdf-mov}{1.001}
\registerctxluafile{lpdf-u3d}{1.001}
\registerctxluafile{lpdf-swf}{1.001}
\registerctxluafile{lpdf-tag}{1.001}
@@ -54,9 +56,9 @@
%D This one can be consulted by users although the suffix is also
%D a system mode.
-\setjobsuffix{pdf}
+\back_job_set_suffix{pdf}
-%D PDF/X (matbe combine the two lua calls)
+%D PDF/X (maybe combine the two lua calls)
\setupbackend
[xmpfile=]
@@ -85,22 +87,21 @@
%D These are the only official methods to add stuff to the resources.
-\def\pdfbackendsetcatalog #1#2{\ctxlua{lpdf.addtocatalog ("#1",\!!bs#2\!!es)}}
-\def\pdfbackendsetinfo #1#2{\ctxlua{lpdf.addtoinfo ("#1",\!!bs#2\!!es)}}
-\def\pdfbackendsetname #1#2{\ctxlua{lpdf.addtonames ("#1",\!!bs#2\!!es)}}
+\unexpanded\def\pdfbackendsetcatalog #1#2{\ctxlua{lpdf.addtocatalog ("#1",\!!bs#2\!!es)}}
+\unexpanded\def\pdfbackendsetinfo #1#2{\ctxlua{lpdf.addtoinfo ("#1",\!!bs#2\!!es)}}
+\unexpanded\def\pdfbackendsetname #1#2{\ctxlua{lpdf.addtonames ("#1",\!!bs#2\!!es)}}
-\def\pdfbackendsetpageattribute #1#2{\ctxlua{lpdf.addtopageattributes ("#1",\!!bs#2\!!es)}}
-\def\pdfbackendsetpagesattribute#1#2{\ctxlua{lpdf.addtopagesattributes("#1",\!!bs#2\!!es)}}
-\def\pdfbackendsetpageresource #1#2{\ctxlua{lpdf.addtopageresources ("#1",\!!bs#2\!!es)}}
+\unexpanded\def\pdfbackendsetpageattribute #1#2{\ctxlua{lpdf.addtopageattributes ("#1",\!!bs#2\!!es)}}
+\unexpanded\def\pdfbackendsetpagesattribute#1#2{\ctxlua{lpdf.addtopagesattributes("#1",\!!bs#2\!!es)}}
+\unexpanded\def\pdfbackendsetpageresource #1#2{\ctxlua{lpdf.addtopageresources ("#1",\!!bs#2\!!es)}}
-\def\pdfbackendsetextgstate #1#2{\ctxlua{lpdf.adddocumentextgstate ("#1",lpdf.verbose(\!!bs#2\!!es))}}
-\def\pdfbackendsetcolorspace #1#2{\ctxlua{lpdf.adddocumentcolorspace("#1",lpdf.verbose(\!!bs#2\!!es))}}
-\def\pdfbackendsetpattern #1#2{\ctxlua{lpdf.adddocumentpattern ("#1",lpdf.verbose(\!!bs#2\!!es))}}
-\def\pdfbackendsetshade #1#2{\ctxlua{lpdf.adddocumentshade ("#1",lpdf.verbose(\!!bs#2\!!es))}}
+\unexpanded\def\pdfbackendsetextgstate #1#2{\ctxlua{lpdf.adddocumentextgstate ("#1",lpdf.verbose(\!!bs#2\!!es))}}
+\unexpanded\def\pdfbackendsetcolorspace #1#2{\ctxlua{lpdf.adddocumentcolorspace("#1",lpdf.verbose(\!!bs#2\!!es))}}
+\unexpanded\def\pdfbackendsetpattern #1#2{\ctxlua{lpdf.adddocumentpattern ("#1",lpdf.verbose(\!!bs#2\!!es))}}
+\unexpanded\def\pdfbackendsetshade #1#2{\ctxlua{lpdf.adddocumentshade ("#1",lpdf.verbose(\!!bs#2\!!es))}}
-\def\pdfbackendcurrentresources {\ctxlua{lpdf.collectedresources()}}
-
-\def\pdfcolor #1{\ctxlua{lpdf.pdfcolor(\thecolorattribute{#1})}} \let\PDFcolor\pdfcolor
+ \def\pdfbackendcurrentresources {\cldcontext{lpdf.collectedresources()}}
+ \def\pdfcolor #1{\ctxlua{lpdf.pdfcolor(\thecolorattribute{#1})}} \let\PDFcolor\pdfcolor
%D Let's block these:
@@ -113,7 +114,7 @@
%D An example of usage is:
-\appendtoks
+\appendtoks % this will be moved to lua
\pdfbackendsetinfo{ConTeXt.Version}{\contextversion}%
\pdfbackendsetinfo{ConTeXt.Time} {\number\normalyear.\twodigits\normalmonth.\twodigits\normalday\space \twodigits\currenthour:\twodigits\currentminute}%
\pdfbackendsetinfo{ConTeXt.Jobname}{\jobname}%
@@ -122,31 +123,84 @@
%D Transformations. Some day we will use primitives (once they're fixed).
-\def\dostartrotation#1% grouped
- {\forcecolorhack
- \pdfliteral{q \ctxlua{lpdf.rotationcm(#1)}}}
-
-\def\dostoprotation
- {\pdfliteral{Q}}
-
-\def\dostartscaling#1#2% the test is needed because acrobat is bugged!
- {\forcecolorhack
- \pdfliteral{q \ifdim#1\points=\zeropoint.0001\else#1\fi\space 0 0
- \ifdim#2\points=\zeropoint.0001\else#2\fi\space 0 0 cm}}
-
-\def\dostopscaling
- {\pdfliteral{Q}}
-
-\def\dostartmirroring{\pdfliteral{-1 0 0 1 0 0 cm}}
-\def\dostopmirroring {\pdfliteral{-1 0 0 1 0 0 cm}}
-
-\def\dostartclipping#1#2#3% todo (still needed?)
+% \def\dostartscaling#1#2% the test is needed because acrobat is bugged!
+% {\forcecolorhack % maybe use signal instead
+% \pdfliteral{q \ifdim#1\points=\zeropoint.0001\else#1\fi\space 0 0
+% \ifdim#2\points=\zeropoint.0001\else#2\fi\space 0 0 cm}}
+%
+% \def\dostopscaling
+% {\pdfliteral{Q}}
+%
+% \def\dostartrotation#1% grouped
+% {\forcecolorhack % maybe use signal instead
+% \pdfliteral{q \cldcontext{lpdf.rotationcm(#1)}}}
+%
+% \def\dostoprotation
+% {\pdfliteral{Q}}
+%
+% function lpdf.rotationcm(a)
+% local s, c = sind(a), cosd(a)
+% return format("%s %s %s %s 0 0 cm",c,s,-s,c)
+% end
+%
+% \def\dostartmirroring{\pdfliteral{-1 0 0 1 0 0 cm}}
+% \def\dostopmirroring {\pdfliteral{-1 0 0 1 0 0 cm}}
+
+% todo: inject at the lua end cq. deal with #5 and #6 too
+
+\unexpanded\def\dostartrotation#1% grouped
+ {\forcecolorhack % maybe use signal instead
+ \advance\backendtransformlevel\plusone
+ \pdfsave
+ \pdfsetmatrix{\ctxcommand{pdfrotation(#1)}}}
+
+\unexpanded\def\dostoprotation
+ {\pdfrestore
+ \advance\backendtransformlevel\minusone}
+
+\unexpanded\def\dostartscaling#1#2% the test is needed because acrobat is bugged!
+ {\forcecolorhack % maybe use signal instead
+ \advance\backendtransformlevel\plusone
+ \pdfsave
+ \pdfsetmatrix
+ {\ifdim#1\points=\zeropoint.0001\else#1\fi\space 0 0
+ \ifdim#2\points=\zeropoint.0001\else#2\fi\space}}% 0 0
+
+\unexpanded\def\dostopscaling
+ {\pdfrestore
+ \advance\backendtransformlevel\minusone}
+
+\unexpanded\def\dostartmirroring
+ {\advance\backendtransformlevel\plusone
+ \pdfsave
+ \pdfsetmatrix{-1 0 0 1}} % 0 0
+
+\unexpanded\def\dostopmirroring
+ {\pdfrestore
+ \advance\backendtransformlevel\minusone}
+
+\unexpanded\def\dotransformnextbox#1#2#3#4#5#6% sx rx ry sy tx ty (will change) / basepoints !
+ {\advance\backendtransformlevel\plusone
+ % fixing ht/dp/wd should happen elsewhere
+ \dowithnextbox{\dodotransformnextbox{#5}{#6}{#1 #2 #3 #4}}}
+
+\unexpanded\def\dodotransformnextbox#1#2#3%
+ {\hbox
+ {\hskip#1\onebasepoint
+ \raise#2\onebasepoint\hbox
+ {\pdfsave
+ \pdfsetmatrix{#3}% 0 0 (no #5 #6 yet)
+ \box\nextbox
+ \pdfrestore
+ \advance\backendtransformlevel\minusone}}}
+
+\unexpanded\def\dostartclipping#1#2#3%
{\PointsToBigPoints{#2}\width
\PointsToBigPoints{#3}\height
- \grabMPclippath{#1}{1}\width\height{0 0 m \width\space 0 l \width \height l 0 \height l}%
+ \meta_grab_clip_path{#1}\width\height{0 0 m \width\space 0 l \width \height l 0 \height l}%
\pdfliteral{q 0 w \MPclippath\space W n}}
-\def\dostopclipping
+\unexpanded\def\dostopclipping
{\pdfliteral{Q n}}
%D The following will move to the backend \LUA\ code:
@@ -156,7 +210,8 @@
%D Temporary hack, will be removed or improved or default.
-\def\TransparencyHack{\ctxlua{backends.codeinjections.addtransparencygroup()}}
+%def\TransparencyHack{\ctxlua{backends.codeinjections.addtransparencygroup()}}
+\def\TransparencyHack{\setupcolors[\c!pagecolormodel=\v!auto]}
%D \macros
%D {dostartobject,dostopobject,doinsertobject}
@@ -168,13 +223,15 @@
\def\dostartobject#1#2#3#4#5%
{\bgroup
\setbox\objectbox\vbox\bgroup
- \def\dodostopobject{\egroup\doregisterobject{#1}{#2}}}
+ \def\back_object_stop{\egroup\back_object_register{#1}{#2}}}
\def\dostopobject
- {\dodostopobject
+ {\back_object_stop
\egroup}
-\def\doregisterobject#1#2%
+% attr {/Group << /S /Transparency /I false /K true >>}
+
+\def\back_object_register#1#2%
{\the\pdfbackendeveryxform
\finalizeobjectbox\objectbox
\immediate\pdfxform resources {\pdfbackendcurrentresources}\objectbox
@@ -183,10 +240,13 @@
\def\doresetobjects
{}
+\let\m_back_object_reference\empty
+
\def\doinsertobject#1#2%
{\begingroup
\doifobjectreferencefoundelse{#1}{#2}
- {\dogetobjectreference{#1}{#2}\PDFobjectreference\pdfrefxform\PDFobjectreference}%
+ {\dogetobjectreference{#1}{#2}\m_back_object_reference
+ \pdfrefxform\m_back_object_reference}%
\donothing
\endgroup}
@@ -196,8 +256,8 @@
{\begingroup
\xdef\lastpredefinedsymbol{#1}%
\settightobject{SYM}{#1}\hbox{\symbol[#1]}% to be checked ... maybe only fitting
- \dogetobjectreference{SYM}{#1}\lastref
- \ctxlua{backends.codeinjections.registersymbol("#1",\lastref)}%
+ \dogetobjectreference{SYM}{#1}\m_back_object_reference
+ \ctxlua{backends.codeinjections.registersymbol("#1",\m_back_object_reference)}%
\endgroup}
% for the moment here
@@ -213,24 +273,39 @@
%D implemented in the \POSTSCRIPT\ driver. This code is
%D somewhat obsolete as we now have metapost embedded.
-\def\doPDFovalcalc#1#2#3%
- {\PointsToBigPoints{\dimexpr#1+#2\relax}#3}
+% \def\back_oval_calculate#1#2#3%
+% {\PointsToBigPoints{\dimexpr#2+#3\relax}#1}
-\def\doovalbox#1#2#3#4#5#6#7#8% todo: \scratchdimen/\scatchbox
+\unexpanded\def\doovalbox#1#2#3#4#5#6#7#8%
{\forcecolorhack
\bgroup
- \dimen0=#4\divide\dimen0 \plustwo
- \doPDFovalcalc{0pt}{+\dimen0}\xmin
- \doPDFovalcalc{#1}{-\dimen0}\xmax
- \doPDFovalcalc{#2}{-\dimen0}\ymax
- \doPDFovalcalc{-#3}{+\dimen0}\ymin
- \advance\dimen0 by #5%
- \doPDFovalcalc{0pt}{+\dimen0}\xxmin
- \doPDFovalcalc{#1}{-\dimen0}\xxmax
- \doPDFovalcalc{#2}{-\dimen0}\yymax
- \doPDFovalcalc{-#3}{+\dimen0}\yymin
- \doPDFovalcalc{#4}{\zeropoint}\stroke
- \doPDFovalcalc{#5}{\zeropoint}\radius
+% \scratchdimen#4%
+% \divide\scratchdimen\plustwo
+% \back_oval_calculate\xmin \zeropoint\scratchdimen
+% \back_oval_calculate\xmax {#1}{-\scratchdimen}%
+% \back_oval_calculate\ymax {#2}{-\scratchdimen}%
+% \back_oval_calculate\ymin {-#3}\scratchdimen
+% \advance\scratchdimen by #5%
+% \back_oval_calculate\xxmin \zeropoint\scratchdimen
+% \back_oval_calculate\xxmax {#1}{-\scratchdimen}%
+% \back_oval_calculate\yymax {#2}{-\scratchdimen}%
+% \back_oval_calculate\yymin {-#3}\scratchdimen
+% \back_oval_calculate\stroke{#4}\zeropoint
+% \back_oval_calculate\radius{#5}\zeropoint
+ %
+ \PointsToBigPoints{#4} \stroke
+ \PointsToBigPoints{#5} \radius
+ \scratchdimen\dimexpr#4/\plustwo\relax
+ \PointsToBigPoints \scratchdimen \xmin
+ \PointsToBigPoints{\dimexpr #1-\scratchdimen}\xmax
+ \PointsToBigPoints{\dimexpr #2-\scratchdimen}\ymax
+ \PointsToBigPoints{\dimexpr-#3+\scratchdimen}\ymin
+ \advance\scratchdimen by #5\relax
+ \PointsToBigPoints \scratchdimen \xxmin
+ \PointsToBigPoints{\dimexpr #1-\scratchdimen}\xxmax
+ \PointsToBigPoints{\dimexpr #2-\scratchdimen}\yymax
+ \PointsToBigPoints{\dimexpr-#3+\scratchdimen}\yymin
+ %
\edef\dostroke{#6}%
\edef\dofill{#7}%
\edef\mode{\number#8 \space}%
@@ -428,10 +503,13 @@
\fi
Q}%
\fi}%
- \wd\scratchbox#1\ht\scratchbox#2\dp\scratchbox#3\box\scratchbox
+ \wd\scratchbox#1%
+ \ht\scratchbox#2%
+ \dp\scratchbox#3%
+ \box\scratchbox
\egroup}
-\unexpanded\def\pdfactualtext#1#2%
+\unexpanded\def\pdfactualtext#1#2% not interfaced
{\pdfliteral direct{/Span <</ActualText \ctxlua{tex.write(lpdf.tosixteen("#2"))} >> BDC}%
#1%
\pdfliteral direct{EMC}}
diff --git a/Master/texmf-dist/tex/context/base/back-swf.mkiv b/Master/texmf-dist/tex/context/base/back-swf.mkiv
new file mode 100644
index 00000000000..1d225b550ea
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/back-swf.mkiv
@@ -0,0 +1,90 @@
+%D \module
+%D [ file=back-swf,
+%D version=2009.12.31,
+%D title=\CONTEXT\ Backend Macros,
+%D subtitle=Shockwave Experiment,
+%D author=Hans Hagen \& Luigi Scarso,
+%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.
+
+% This is only a placeholder that demonstrates the usage of swf
+% resources.
+
+%D \starttyping
+%D \starttext
+%D
+%D \enabletrackers[graphics.locating]
+%D \enabletrackers[backend.swf]
+%D
+%D \startluaparameterset [swf:relative:resources]
+%D relativepaths = {
+%D "assets"
+%D }
+%D \stopluaparameterset
+%D
+%D \startluaparameterset[swf:relative:display]
+%D toolbar = true,
+%D preview = "images/posterframes/*.jpg", -- relative to assets
+%D open = "click",
+%D close = "focus",
+%D \stopluaparameterset
+%D
+%D \startTEXpage
+%D \externalfigure
+%D [whatever.swf]
+%D [resources=swf:relative:resources,
+%D display=swf:relative:display]
+%D \stopTEXpage
+%D \stoptyping
+
+\stoptext
+
+\endinput
+
+\starttext
+
+\startluaparameterset [swf:myset:display:1]
+ toolbar = true,
+ preview = "assets/images/posterframes/SPT_14-16_Ra_01_PN_LE01_02_DoLikeMeLater_posterframe.jpg",
+ -- preview = "t:/sources/cow.pdf",
+ -- preview = "t:/sources/hacker.jpg",
+ open = "click", -- click page focus
+ close = "focus", -- click page focus
+\stopluaparameterset
+
+\startluaparameterset [swf:myset:resources:1]
+ paths = {
+ "assets"
+ },
+ files = {
+ -- "somename_1"
+ -- "somename_1"
+ }
+\stopluaparameterset
+
+\startluaparameterset [swf:dolikemelater:resources]
+ paths = {
+ "assets"
+ },
+\stopluaparameterset
+
+\starttext
+
+% preview=swf:myset:display:1
+% controls=swf:myset:controls:1
+% resources=swf:myset:resources:1
+
+\placefigure
+ {flash demo}
+ {\startcombination[2*2]
+ {\externalfigure[trasf1.swf][width=0.45\textwidth,height=0.25\textheight]} {one}
+ {\externalfigure[trasf2.swf][width=0.45\textwidth,height=0.25\textheight]} {two}
+ {\externalfigure[trasf3.swf][width=0.45\textwidth,height=0.25\textheight]} {three}
+ {\externalfigure[trasf4.swf][width=0.45\textwidth,height=0.25\textheight]} {four}
+ \stopcombination}
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/back-u3d.mkiv b/Master/texmf-dist/tex/context/base/back-u3d.mkiv
index e2609449650..dfe8a90c2a6 100644
--- a/Master/texmf-dist/tex/context/base/back-u3d.mkiv
+++ b/Master/texmf-dist/tex/context/base/back-u3d.mkiv
@@ -5,7 +5,7 @@
%D subtitle=U3D Experiment,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/bibl-bib.lua b/Master/texmf-dist/tex/context/base/bibl-bib.lua
index e0e5a6c3a42..444f7e9bcc4 100644
--- a/Master/texmf-dist/tex/context/base/bibl-bib.lua
+++ b/Master/texmf-dist/tex/context/base/bibl-bib.lua
@@ -204,12 +204,12 @@ function bibtex.toxml(session,options)
local strip = options.strip -- todo: interface
local entries = session.entries
r = r + 1 ; result[r] = format("<?xml version='1.0' standalone='yes'?>")
- result[#result+1] = format("<bibtex>")
+ r = r + 1 ; result[r] = format("<bibtex>")
for id, categories in next, session.data do
id = lower(gsub(id,"^@",""))
for name, entry in next, categories do
if not entries or entries[name] then
- result[#result+1] = format("<entry tag='%s' category='%s'>",lower(name),id)
+ r = r + 1 ; result[r] = format("<entry tag='%s' category='%s'>",lower(name),id)
for key, value in next, entry do
value = gsub(value,"\\(.)",ihatethis)
value = lpegmatch(escaped_pattern,value)
@@ -306,9 +306,9 @@ local P, Ct, lpegmatch, lpegpatterns = lpeg.P, lpeg.Ct, lpeg.match, lpeg.pattern
local space, comma = P(" "), P(",")
-local andsplitter = Ct(lpeg.splitat(space^1 * "and" * space^1))
-local commasplitter = Ct(lpeg.splitat(space^0 * comma * space^0))
-local spacesplitter = Ct(lpeg.splitat(space^1))
+local andsplitter = lpeg.tsplitat(space^1 * "and" * space^1)
+local commasplitter = lpeg.tsplitat(space^0 * comma * space^0)
+local spacesplitter = lpeg.tsplitat(space^1)
local firstcharacter = lpegpatterns.utf8byte
local function is_upper(str)
diff --git a/Master/texmf-dist/tex/context/base/bibl-bib.mkiv b/Master/texmf-dist/tex/context/base/bibl-bib.mkiv
index 681be325f2b..56007d21c1f 100644
--- a/Master/texmf-dist/tex/context/base/bibl-bib.mkiv
+++ b/Master/texmf-dist/tex/context/base/bibl-bib.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen \& Taco Hoekwater,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -527,24 +527,29 @@
\edef\currentbibtexsession{#1}%
\let\currentlist\currentbibtexsession
\setuplist[\currentbibtexsession][\c!criterium=\v!previous,#2]
- \doifelsenothing{\namedlistparameter\currentbibtexsession\c!title}
- {\systemsuppliedchapter[\currentbibtexsession]{\headtext{\currentbibtexsession}}}
- {\normalexpanded{\systemsuppliedchapter[\currentbibtexsession]{\namedlistparameter\currentbibtexsession\c!title}}}%
- \dodoplacebibtexpublications}
+ \edef\currentbibtexsessiontitle{\namedlistparameter\currentbibtexsession\c!title}%
+ \ifx\currentbibtexsessiontitle\empty
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbibtexsession,\c!title={\headtext{\currentbibtexsession}}]}%
+ \else
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbibtexsession,\c!title={\currentbibtexsessiontitle}]}%
+ \fi
+ \dodoplacebibtexpublications
+ \stopnamedsection
+ \endgroup}
\def\doplacebibtexpublications[#1][#2]%
{\begingroup
\edef\currentbibtexsession{#1}%
\let\currentlist\currentbibtexsession
\setuplist[\currentbibtexsession][\c!criterium=\v!previous,#2]%
- \dodoplacebibtexpublications}
+ \dodoplacebibtexpublications
+ \endgroup}
\def\dodoplacebibtexpublications
{\determinelistcharacteristics[\currentbibtexsession]%
\the\everysetupbibtexlistplacement
\forgetall
\typesetbibtexlist
- \endgroup
\global\advance\bibtexblock\plusone}
\setvalue{\??pb:\c!numbering:\v!short}#1% todo var s -> short tag
@@ -614,7 +619,8 @@
\to \everysetupbibtexlistplacement
\def\typesetbibtexlist
- {\dobeginoflist
+ {\begingroup
+ \startpacked[\v!blank]%
\doif{\namedlistparameter\currentbibtexsession\c!criterium}\v!cite
{\setuplist[\currentbibtexsession][\c!criterium=\v!here]}%
\doifelse{\bibtexpublicationsparameter\c!method}\v!local
@@ -627,7 +633,8 @@
{\namedlistparameter\currentbibtexsession\c!extras}%
{\namedlistparameter\currentbibtexsession\c!order}%
\ctxlua{bibtex.hacks.flush("\bibtexpublicationsparameter\c!sorttype")}%
- \doendoflist}
+ \stoppacked
+ \endgroup}
\unexpanded\def\typesetbibtexpublication#1%
{\edef\currentbibtexsessiontag{#1}%
@@ -645,7 +652,11 @@
{\doifbibreferencefoundelse\currentbibtexsessiontag
{\global\advance\bibtexcounter\plusone
\ctxlua{bibtex.hacks.registerplaced("\currentbibtexsessiontag")}%
- \dodolistelement{\currentbibtexsession}{}{\number\bibtexcounter}{\thebibtexpublicationlistelement}{}{}}
+ \let\currentlist\currentbibtexsession
+ \let\currentlistentrynumber \bibtexcounter
+ \let\currentlistentrytitle \thebibtexpublicationlistelement
+ \let\currentlistentrypagenumber\empty
+ \strc_lists_apply_renderingsetup}
{}} % invalid
\def\thebibtexpublicationlistelement
@@ -725,7 +736,7 @@
{\dontleavehmode
\begingroup
\bibtexcitationparameter\v!left
- \penalty\!!tenthousand
+ \penalty\plustenthousand
\ctxlua{bibtex.hacks.resolve("","\number\bibtexblock","#1")}%
\bibtexcitationparameter\v!right
\endgroup}
diff --git a/Master/texmf-dist/tex/context/base/bibl-tra.lua b/Master/texmf-dist/tex/context/base/bibl-tra.lua
index 4ae81188d87..d6644664529 100644
--- a/Master/texmf-dist/tex/context/base/bibl-tra.lua
+++ b/Master/texmf-dist/tex/context/base/bibl-tra.lua
@@ -28,9 +28,9 @@ local list, done, alldone, used, registered, ordered = { }, { }, { }, { }, { },
local mode = 0
local template = utilities.strings.striplong([[
- \citation{*}
- \bibstyle{cont-%s}
- \bibdata{%s}
+ \citation{*}
+ \bibstyle{cont-%s}
+ \bibdata{%s}
]])
function hacks.process(settings)
@@ -128,6 +128,7 @@ local function compare(a,b)
end
function hacks.resolve(prefix,block,reference) -- maybe already feed it split
+ -- needs checking (the prefix in relation to components)
local subset = references.collected[prefix or ""] or references.collected[""]
if subset then
local result, nofresult, done = { }, 0, { }
diff --git a/Master/texmf-dist/tex/context/base/bibl-tra.mkii b/Master/texmf-dist/tex/context/base/bibl-tra.mkii
index 2c03a7f9160..a9ce392a22a 100644
--- a/Master/texmf-dist/tex/context/base/bibl-tra.mkii
+++ b/Master/texmf-dist/tex/context/base/bibl-tra.mkii
@@ -5,7 +5,7 @@
%D subtitle=Publications,
%D author=Taco Hoekwater,
%D date=\currentdate,
-%D copyright=Public Domain]
+%D copyright={Public Domain}]
%C
%C Donated to the public domain.
diff --git a/Master/texmf-dist/tex/context/base/bibl-tra.mkiv b/Master/texmf-dist/tex/context/base/bibl-tra.mkiv
index 8e2f61641f3..3531703adc9 100644
--- a/Master/texmf-dist/tex/context/base/bibl-tra.mkiv
+++ b/Master/texmf-dist/tex/context/base/bibl-tra.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Publications,
%D author=Taco Hoekwater,
%D date=\currentdate,
-%D copyright=Public Domain]
+%D copyright={Public Domain}]
%C
%C Donated to the public domain.
@@ -23,6 +23,8 @@
%D A bit ongoing: make more local macros prefixed with bib, i.e. the bib
%D namespace is reserved.
+%D Todo: commandhandler
+
\writestatus{loading}{ConTeXt Bibliography Support / BibTeX}
\definefilesynonym[bib][obsolete]
@@ -186,6 +188,7 @@
[pubs]
[\c!state=\v!start,
\c!criterium=\@@pbcriterium,
+ \c!headnumber=\v!always, % needed as we provide our own and need to force
\c!width=]
\installstructurelistprocessor{pubs:userdata}%
@@ -310,8 +313,8 @@
\def\@@pbinumbercommand{\executeifdefined{\??pb:\c!numbercommand:\@@pbnumbering}\firstofoneargument}
-\letvalue{\??pb:\c!numbercommand:\v!yes }\firstofoneargument
-\letvalue{\??pb:\c!numbercommand:\v!no }\gobbleoneargument
+\setvalue{\??pb:\c!numbercommand:\v!yes }#1{#1}%
+\setvalue{\??pb:\c!numbercommand:\v!no }#1{}
\setvalue{\??pb:\c!numbercommand:\v!short}#1{\bibgetvars\currentpublicationkey}
\setvalue{\??pb:\c!numbercommand:\v!bib }#1{\bibgetvarn\currentpublicationkey}
@@ -656,9 +659,7 @@
%D Now prohibits comments, so % can be used for urls
\unexpanded\def\startpublication
- {\begingroup
- \catcode\commentasciicode\othercatcode
- \dosingleempty\dostartpublication}
+ {\dosingleempty\dostartpublication}
\let\stoppublication\relax
@@ -676,12 +677,17 @@
% hm, we can store at the lua end ...
-\long\def\dostartpublication[#1]#2\stoppublication
- {\doifassignmentelse{#1}%
+\def\dostartpublication[#1]%
+ {\begingroup
+ \doifassignmentelse{#1}%
{\getparameters[\??pb][k=\s!unknown,t=article,n=,s=,a=,y=,o=,u=,#1]}%
{\getparameters[\??pb][k=#1,t=article,n=,s=,a=,y=,o=,u=]}%
\ctxlua{bibtex.hacks.register("\@@pbk")}%
- \setxvalue{pbd:\@@pbk}##1{\noexpand\ifcase##1\noexpand\or
+ \catcode\commentasciicode\othercatcode
+ \dodostartpublication}
+
+\def\dodostartpublication#1\stoppublication
+ {\setxvalue{pbd:\@@pbk}##1{\noexpand\ifcase##1\noexpand\or
\@@pbk\noexpand\or
\@@pba\noexpand\or
\@@pby\noexpand\or
@@ -690,7 +696,7 @@
\@@pbt\noexpand\or
\@@pbo\noexpand\or
\@@pbu\noexpand\or
- \normalunexpanded{#2}\noexpand\fi}%
+ \normalunexpanded{#1}\noexpand\fi}%
\endgroup
\ignorespaces}
@@ -737,9 +743,10 @@
\def\doprocessbibtexentry#1{\typesetapublication{#1}}
-\def\typesetpubslist
- {\preloadbiblist
- \dobeginoflist
+\unexpanded\def\typesetpubslist
+ {\begingroup
+ \startpacked[\v!blank]%
+ \preloadbiblist
% \the\initializebibdefinitions % COMMENTED
\edef\currentlist{pubs}%
\ctxlua{bibtex.hacks.reset(\number\bibtexoncemode)}%
@@ -755,12 +762,12 @@
{\listparameter\c!extras}%
{\listparameter\c!order}}%
\ctxlua{bibtex.hacks.flush("\@@pbsorttype")}%
- \doendoflist}
+ \stoppacked
+ \endgroup}
\newif\ifinpublist
-
-\def\initializepubslist
+\unexpanded\def\initializepubslist
{\def\currentlist{pubs}%
\edef\@@pbnumbering{\@@pbnumbering}%
\doifelse\@@pbautohang\v!yes
@@ -799,22 +806,26 @@
\doifelse{\publicationlistparameter\c!maybeyear}{\v!off}{\def\maybeyear##1{}}{\def\maybeyear##1{##1}}%
\forgetall}
-\def\outdented#1% move to supp-box ?
+\unexpanded\def\outdented#1% move to supp-box ?
{\hskip-\hangindent#1\relax}
%D The full list of publications
-\def\completepublications
+\unexpanded\def\completepublications
{\dosingleempty\docompletepublications}
\def\docompletepublications[#1]%
{\begingroup
-% \setuplist[pubs][\c!criterium=\v!previous,#1]
- \setuplist[pubs][#1]
- \doifelsenothing{\publicationlistparameter\c!title}
- {\systemsuppliedchapter[pubs]{\headtext{pubs}}}
- {\normalexpanded{\systemsuppliedchapter[pubs]{\publicationlistparameter\c!title}}}%
- \dodoplacepublications}
+ \setuplist[pubs][#1]%
+ \edef\currentbibtexsessiontitle{\publicationlistparameter\c!title}%
+ \ifx\currentbibtexsessiontitle\empty
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=pubs,\c!title={\headtext{pubs}}]}%
+ \else
+ \normalexpanded{\startnamedsection[\v!chapter][\c!reference=pubs,\c!title={\currentbibtexsessiontitle}]}%
+ \fi
+ \dodoplacepublications
+ \stopnamedsection
+ \endgroup}
%D And the portion with the entries only.
@@ -825,9 +836,9 @@
\def\doplacepublications[#1]%
{\begingroup
-% \setuplist[pubs][\c!criterium=\v!previous,#1]%
\setuplist[pubs][#1]%
- \dodoplacepublications}
+ \dodoplacepublications
+ \endgroup}
\def\dodoplacepublications
{\determinelistcharacteristics[pubs]%
@@ -837,7 +848,6 @@
\inpublisttrue
\typesetpubslist
\inpublistfalse
- \endgroup
\global\advance\bibtexblock\plusone}
%D \subsubject{What's in a publication}
@@ -865,16 +875,17 @@
{\global\advance\bibtexcounter\plusone
\def\currentpublicationkey{#1}%
\ctxlua{bibtex.hacks.registerplaced("#1")}%
- \dodolistelement
- {pubs}%
- {}%
- {\number\bibtexcounter}%
- {\expanded{\reference[\bibrefprefix#1]{\number\bibtexcounter}}%
- \strut\dotypesetapublication{#1}\strut}%
- {}%
- {}}
+ \def \currentlist {pubs}%
+ \edef\currentlistentrynumber {\number\bibtexcounter}%
+ \let \currentlistentrytitle \bibtexpubtext
+ \let \currentlistentrypagenumber\empty
+ \strc_lists_apply_renderingsetup}
{}} % invalid
+\def\bibtexpubtext
+ {\expanded{\reference[\bibrefprefix\currentpublicationkey]{\number\bibtexcounter}}%
+ \strut\dotypesetapublication\currentpublicationkey\strut}
+
\def\dotypesetapublication#1%
{\bgroup
\the\initializebibdefinitions % NEW
@@ -945,7 +956,11 @@
\ifx\LOextras\empty
\setupcite[\@@currentalternative][#1]%
\else
- \expandafter\ifx\csname LOright\endcsname \relax
+ \expandafter\ifx\csname \??pv \@@currentalternative\c!right\endcsname\relax
+ % avoids tail recursion
+ \expandafter\let\csname \??pv \@@currentalternative\c!right\endcsname\empty
+ \fi
+ \expandafter\ifx\csname LOright\endcsname \relax
\edef\LOextras{{\LOextras\bibalternative\c!right}}%
\else
\edef\LOextras{{\LOextras\LOright}}%
@@ -1025,7 +1040,9 @@
%D does not have to be year info always. \type{\thebibyears} is
%D pre-initialized because this makes the insertion macros simpler.
%D
-%D In `normal' \TeX, of course there are expansion problems again.
+%D In normal \TEX, of course there are expansion problems again.
+
+%D Delegate this to \LUA.
\def\ixbibauthoryear#1#2#3#4%
{\bgroup
@@ -1215,9 +1232,11 @@
%D
%D The final task is looping over that list until a match is found.
-\def\gotobiblink#1[#2]{\doifreferencefoundelse{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{}}
-\def\atbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\at [\bibrefprefix#1]}{}}
-\def\inbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\expanded{\goto{\currentreferencetext}}[\bibrefprefix#1]}{}}
+%D Beware, we can have cites without reference match.
+
+\def\gotobiblink#1[#2]{\doifreferencefoundelse{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{#1}}
+\def\atbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\at [\bibrefprefix#1]}{#1}}
+\def\inbiblink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\expanded{\goto{\currentreferencetext}}[\bibrefprefix#1]}{#1}}
%D \macros{bibauthoryearref,bibauthoryearsref,bibauthorref,bibyearref}
%D
@@ -1414,7 +1433,7 @@
\def\bibnumref[#1]%
{\begingroup
\bibalternative\v!left
- \penalty\!!tenthousand
+ \penalty\plustenthousand
\ctxlua{bibtex.hacks.resolve("","\number\bibtexblock","#1")}%
\bibalternative\v!right
\endgroup}
@@ -1450,7 +1469,7 @@
{\getcommalistsize[#1]%
\global\bibitemcounter\commalistsize
\bibresetrefsep
- \processcommalist[#1]\dobibauthornumref }
+ \processcommalist[#1]\dobibauthornumref}
\def\dobibauthornumref#1%
{\bibinsertrefsep
diff --git a/Master/texmf-dist/tex/context/base/blob-ini.lua b/Master/texmf-dist/tex/context/base/blob-ini.lua
index 48cf4e39314..b97485b1b93 100644
--- a/Master/texmf-dist/tex/context/base/blob-ini.lua
+++ b/Master/texmf-dist/tex/context/base/blob-ini.lua
@@ -28,28 +28,19 @@ if not modules then modules = { } end modules ['blob-ini'] = {
-- blob.paragraph
-- blob.page
-local type = type
+local type, tostring = type, tostring
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local report_blobs = logs.reporter("blobs")
-local fontdata = fonts.hashes.identifiers
+local t_tonodes = typesetters.tonodes
+local t_hpack = typesetters.hpack
-local nodepool = nodes.pool
-
-local new_glyph = nodepool.glyph
-local new_glue = nodepool.glue
-
-local copy_node = node.copy
-local copy_node_list = node.copy_list
-local insert_node_after = node.insert_after
local flush_node_list = node.flush_list
local hpack_node_list = node.hpack
local vpack_node_list = node.vpack
local write_node = node.write
-local current_font = font.current
-
blobs = blobs or { }
local newline = lpegpatterns.newline
@@ -57,7 +48,7 @@ local space = lpegpatterns.spacer
local spacing = newline * space^0
local content = (space^1)/" " + (1-spacing)
-local ctxtextcapture = lpeg.Ct ( (
+local ctxtextcapture = lpeg.Ct ( ( -- needs checking (see elsewhere)
space^0 * (
newline^2 * space^0 * lpeg.Cc("")
+ newline * space^0 * lpeg.Cc(" ")
@@ -71,6 +62,18 @@ function blobs.new()
}
end
+function blobs.dispose(t)
+ local list = t.list
+ for i=1,#list do
+ local li = list[i]
+ local pack = li.pack
+ if pack then
+ flush_node_list(pack)
+ li.pack = nil
+ end
+ end
+end
+
function blobs.append(t,str) -- will be link nodes.link
local typ = type(str)
local dummy = nil
@@ -94,7 +97,7 @@ function blobs.append(t,str) -- will be link nodes.link
noflist = noflist + 1
list[noflist] = l
end
- local head, tail = tonodes(str,nil,nil)
+ local head, tail = t_tonodes(str,nil,nil)
if head then
if l.head then
l.tail.next = head
@@ -129,13 +132,26 @@ end
function blobs.write(t)
local list = t.list
for i=1,#list do
- local pack = list[i].pack
+ local li = list[i]
+ local pack = li.pack
if pack then
write_node(pack)
+ flush_node_list(pack)
+ li.pack = nil
end
end
end
+function blobs.dimensions(t)
+ local list = t.list
+ local first = list and list[1]
+ if first then
+ local pack = first.pack
+ return pack.width, pack.height, pack.depth
+ else
+ return 0, 0, 0
+ end
+end
-- blob.char
-- blob.line: head, tail
@@ -157,3 +173,22 @@ end
--~ pack = false,
--~ properties = { },
--~ end
+
+-- for the moment here:
+
+function commands.widthofstring(str)
+ local l = t_hpack(str)
+ context(number.todimen(l.width))
+ flush_node_list(l)
+end
+
+-- less efficient:
+--
+-- function commands.widthof(str)
+-- local b = blobs.new()
+-- blobs.append(b,str)
+-- blobs.pack(b)
+-- local w = blobs.dimensions(b)
+-- context(number.todimen(w))
+-- blobs.dispose(b)
+-- end
diff --git a/Master/texmf-dist/tex/context/base/blob-ini.mkiv b/Master/texmf-dist/tex/context/base/blob-ini.mkiv
index 7f63ec73d91..4fdb9e4b6ce 100644
--- a/Master/texmf-dist/tex/context/base/blob-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/blob-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -18,9 +18,25 @@
%D down the road (close to version 1.00 of \LUATEX). Typesetting in
%D pure \LUA\ sometimes makes sense.
+\registerctxluafile{node-typ}{1.001} % experimental
\registerctxluafile{blob-ini}{1.001}
-\endinput
+%D For the moment here:
+
+\unprotect
+
+% this one takes simple (utf) strings
+
+\def\widthofstring#1{\ctxcommand{widthofstring(\!!bs#1\!!es)}}
+
+% this one takes anything that can be typeset
+
+\unexpanded\def\setwidthof#1\to#2%
+ {\bgroup
+ \setbox\scratchbox\hbox{#1}%
+ \expanded{\egroup\def\noexpand#2{\the\wd\scratchbox}}}
+
+\protect \endinput
% \starttext
%
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-default.mkiv b/Master/texmf-dist/tex/context/base/buff-imp-default.mkiv
index 7a935e218b8..5cff34c7006 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-default.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-imp-default.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Default,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-escaped.mkiv b/Master/texmf-dist/tex/context/base/buff-imp-escaped.mkiv
index 55d2fb093bd..13850475a82 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-escaped.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-imp-escaped.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Escaped,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-lua.lua b/Master/texmf-dist/tex/context/base/buff-imp-lua.lua
index 3a3bb3d2c08..1147666cce8 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-lua.lua
+++ b/Master/texmf-dist/tex/context/base/buff-imp-lua.lua
@@ -146,7 +146,7 @@ local special = S("-+/*^%=#") + P("..")
local equals = P("=")^0
local open = P("[") * Cg(equals, "init") * P("[") * P("\n")^-1 -- maybe better: patterns.newline^-1
local close = P("]") * C(equals) * P("]")
-local closeeq = Cmt(close * Cb("init"), function(s,i,a,b) return a == b end)
+local closeeq = Cmt(close * Cb("init"), function(s,i,a,b) return a == b end) -- wrong return value
local longstring = open * Cs((P(1) - closeeq)^0) * close * Carg(1)
local function long(content,equals,settings)
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-lua.mkiv b/Master/texmf-dist/tex/context/base/buff-imp-lua.mkiv
index a04e2385143..dc601bd7b8e 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-lua.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-imp-lua.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\LUA,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-mp.lua b/Master/texmf-dist/tex/context/base/buff-imp-mp.lua
index 6b8a2653661..f219df79753 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-mp.lua
+++ b/Master/texmf-dist/tex/context/base/buff-imp-mp.lua
@@ -6,98 +6,15 @@ if not modules then modules = { } end modules ['buff-imp-mp'] = {
license = "see context related readme files"
}
-local P, S, V, patterns = lpeg.P, lpeg.S, lpeg.V, lpeg.patterns
-
-local primitives = table.tohash {
- 'charcode', 'day', 'linecap', 'linejoin', 'miterlimit', 'month', 'pausing',
- 'prologues', 'showstopping', 'time', 'tracingcapsules', 'tracingchoices',
- 'tracingcommands', 'tracingequations', 'tracinglostchars',
- 'tracingmacros', 'tracingonline', 'tracingoutput', 'tracingrestores',
- 'tracingspecs', 'tracingstats', 'tracingtitles', 'truecorners',
- 'warningcheck', 'year', 'mpprocset',
- 'false', 'nullpicture', 'pencircle', 'true',
- 'and', 'angle', 'arclength', 'arctime', 'ASCII', 'bluepart', 'boolean', 'bot',
- 'char', 'color', 'cosd', 'cycle', 'decimal', 'directiontime', 'floor', 'fontsize',
- 'greenpart', 'hex', 'infont', 'intersectiontimes', 'known', 'length', 'llcorner',
- 'lrcorner', 'makepath', 'makepen', 'mexp', 'mlog', 'normaldeviate', 'not',
- 'numeric', 'oct', 'odd', 'or', 'path', 'pair', 'pen', 'penoffset', 'picture', 'point',
- 'postcontrol', 'precontrol', 'redpart', 'reverse', 'rotated', 'scaled',
- 'shifted', 'sind', 'slanted', 'sqrt', 'str', 'string', 'subpath', 'substring',
- 'transform', 'transformed', 'ulcorner', 'uniformdeviate', 'unknown',
- 'urcorner', 'xpart', 'xscaled', 'xxpart', 'xypart', 'ypart', 'yscaled', 'yxpart',
- 'yypart', 'zscaled',
- 'addto', 'clip', 'input', 'interim', 'let', 'newinternal', 'save', 'setbounds',
- 'shipout', 'show', 'showdependencies', 'showtoken', 'showvariable',
- 'special',
- 'begingroup', 'endgroup', 'of', 'curl', 'tension', 'and', 'controls',
- 'reflectedabout', 'rotatedaround', 'interpath', 'on', 'off', 'beginfig',
- 'endfig', 'def', 'vardef', 'enddef', 'epxr', 'suffix', 'text', 'primary', 'secondary',
- 'tertiary', 'primarydef', 'secondarydef', 'tertiarydef', 'top', 'bottom',
- 'ulft', 'urt', 'llft', 'lrt', 'randomseed', 'also', 'contour', 'doublepath',
- 'withcolor', 'withpen', 'dashed', 'if', 'else', 'elseif', 'fi', 'for', 'endfor', 'forever', 'exitif',
- 'forsuffixes', 'downto', 'upto', 'step', 'until',
- 'charlist', 'extensible', 'fontdimen', 'headerbyte', 'kern', 'ligtable',
- 'boundarychar', 'chardp', 'charext', 'charht', 'charic', 'charwd', 'designsize',
- 'fontmaking', 'charexists',
- 'cullit', 'currenttransform', 'gfcorners', 'grayfont', 'hround',
- 'imagerules', 'lowres_fix', 'nodisplays', 'notransforms', 'openit',
- 'displaying', 'currentwindow', 'screen_rows', 'screen_cols',
- 'pixels_per_inch', 'cull', 'display', 'openwindow', 'numspecial',
- 'totalweight', 'autorounding', 'fillin', 'proofing', 'tracingpens',
- 'xoffset', 'chardx', 'granularity', 'smoothing', 'turningcheck', 'yoffset',
- 'chardy', 'hppp', 'tracingedges', 'vppp',
- 'extra_beginfig', 'extra_endfig', 'mpxbreak',
- 'end', 'btex', 'etex', 'verbatimtex'
-}
-
-local plain = table.tohash {
- 'ahangle', 'ahlength', 'bboxmargin', 'defaultpen', 'defaultscale',
- 'labeloffset', 'background', 'currentpen', 'currentpicture', 'cuttings',
- 'defaultfont', 'extra_beginfig', 'extra_endfig',
- 'beveled', 'black', 'blue', 'bp', 'butt', 'cc', 'cm', 'dd', 'ditto', 'down', 'epsilon',
- 'evenly', 'fullcircle', 'green', 'halfcircle', 'identity', 'in', 'infinity', 'left',
- 'mitered', 'mm', 'origin', 'pensquare', 'pt', 'quartercircle', 'red', 'right',
- 'rounded', 'squared', 'unitsquare', 'up', 'white', 'withdots',
- 'abs', 'bbox', 'ceiling', 'center', 'cutafter', 'cutbefore', 'dir',
- 'directionpoint', 'div', 'dotprod', 'intersectionpoint', 'inverse', 'mod', 'lft',
- 'round', 'rt', 'unitvector', 'whatever',
- 'cutdraw', 'draw', 'drawarrow', 'drawdblarrow', 'fill', 'filldraw', 'drawdot',
- 'loggingall', 'pickup', 'tracingall', 'tracingnone', 'undraw', 'unfill',
- 'unfilldraw',
- 'buildcycle', 'dashpattern', 'decr', 'dotlabel', 'dotlabels', 'drawoptions',
- 'incr', 'label', 'labels', 'max', 'min', 'thelabel', 'z',
- 'beginchar', 'blacker', 'capsule_end', 'change_width',
- 'define_blacker_pixels', 'define_corrected_pixels',
- 'define_good_x_pixels', 'define_good_y_pixels',
- 'define_horizontal_corrected_pixels', 'define_pixels',
- 'define_whole_blacker_pixels', 'define_whole_pixels',
- 'define_whole_vertical_blacker_pixels',
- 'define_whole_vertical_pixels', 'endchar', 'extra_beginchar',
- 'extra_endchar', 'extra_setup', 'font_coding_scheme',
- 'font_extra_space'
-}
+-- Now that we also use lpeg lexers in scite, we can share the keywords
+-- so we have moved the keyword lists to mult-mps.lua. Don't confuse the
+-- scite lexers with the ones we use here. Of course all those lexers
+-- boil down to doing similar things, but here we need more control over
+-- the rendering and have a different way of nesting. It is no coincidence
+-- that the coloring looks similar: both are derived from earlier lexing (in
+-- texedit, mkii and the c++ scite lexer).
-local metafun = table.tohash {
- 'unitcircle', 'fulldiamond', 'unitdiamond',
- 'halfcircle', 'quartercircle',
- 'llcircle', 'lrcircle', 'urcircle', 'ulcircle',
- 'tcircle', 'bcircle', 'lcircle', 'rcircle',
- 'lltriangle', 'lrtriangle', 'urtriangle', 'ultriangle',
- 'smoothed', 'cornered', 'superellipsed', 'randomized', 'squeezed',
- 'punked', 'curved', 'unspiked', 'simplified', 'blownup', 'stretched',
- 'paralled', 'enlonged', 'shortened',
- 'enlarged', 'leftenlarged', 'topenlarged', 'rightenlarged', 'bottomenlarged',
- 'llenlarged', 'lrenlarged', 'urenlarged', 'ulenlarged',
- 'llmoved', 'lrmoved', 'urmoved', 'ulmoved',
- 'boundingbox', 'innerboundingbox', 'outerboundingbox',
- 'bottomboundary', 'leftboundary', 'topboundary', 'rightboundary',
- 'xsized', 'ysized', 'xysized',
- 'cmyk', 'transparent', 'withshade', 'spotcolor',
- 'drawfill', 'undrawfill',
- 'inverted', 'uncolored', 'softened', 'grayed',
- 'textext', 'graphictext',
- 'loadfigure', 'externalfigure'
-}
+local P, S, V, patterns = lpeg.P, lpeg.S, lpeg.V, lpeg.patterns
local context = context
local verbatim = context.verbatim
@@ -116,7 +33,23 @@ local MetapostSnippetNamePlain = verbatim.MetapostSnippetNamePlain
local MetapostSnippetNameMetafun = verbatim.MetapostSnippetNameMetafun
local MetapostSnippetName = verbatim.MetapostSnippetName
+local primitives, plain, metafun
+
+local function initialize()
+ local mps = dofile(resolvers.findfile("mult-mps.lua","tex")) or {
+ primitives = { },
+ plain = { },
+ metafun = { },
+ }
+ primitives = table.tohash(mps.primitives)
+ plain = table.tohash(mps.plain)
+ metafun = table.tohash(mps.metafun)
+end
+
local function visualizename(s)
+ if not primitives then
+ initialize()
+ end
if primitives[s] then
MetapostSnippetNamePrimitive(s)
elseif plain[s] then
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-mp.mkiv b/Master/texmf-dist/tex/context/base/buff-imp-mp.mkiv
index 55e13b12da1..a40eb6c303f 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-mp.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-imp-mp.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\METAPOST,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-nested.mkiv b/Master/texmf-dist/tex/context/base/buff-imp-nested.mkiv
index 627acc68508..7815086dbfa 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-nested.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-imp-nested.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Nested,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-parsed-xml.mkiv b/Master/texmf-dist/tex/context/base/buff-imp-parsed-xml.mkiv
index 1aa8fbc7411..bd348a67dd8 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-parsed-xml.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-imp-parsed-xml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Parsed \XML,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-tex.mkiv b/Master/texmf-dist/tex/context/base/buff-imp-tex.mkiv
index 3849757292b..c582523d53b 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-tex.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-imp-tex.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\TEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -49,3 +49,34 @@
[\c!option=tex]
\protect \endinput
+
+% needs thinking ... (esp outer start/stop)
+%
+% \definestartstop
+% [TexSnippet]
+% [DefaultSnippet]
+%
+% \definevisualizer
+% [TexSnippetName]
+% [\c!color=darkgreen,
+% \c!style=boldface]
+%
+% \definevisualizer
+% [TexSnippetGroup]
+% [\c!color=darkred,
+% \c!style=boldface]
+%
+% \definevisualizer
+% [TexSnippetBoundary]
+% [\c!color=darkblue,
+% \c!style=boldface]
+%
+% \definevisualizer
+% [TexSnippetSpecial]
+% [\c!color=darkyellow,
+% \c!style=boldface]
+%
+% \definevisualizer
+% [TexSnippetComment]
+% [\c!color=darkyellow,
+% \c!style=boldface]
diff --git a/Master/texmf-dist/tex/context/base/buff-imp-xml.mkiv b/Master/texmf-dist/tex/context/base/buff-imp-xml.mkiv
index 68dc9ed1394..f880ab88225 100644
--- a/Master/texmf-dist/tex/context/base/buff-imp-xml.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-imp-xml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\XML,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-ini.lua b/Master/texmf-dist/tex/context/base/buff-ini.lua
index 70328f0f198..7098679ca17 100644
--- a/Master/texmf-dist/tex/context/base/buff-ini.lua
+++ b/Master/texmf-dist/tex/context/base/buff-ini.lua
@@ -7,63 +7,73 @@ if not modules then modules = { } end modules ['buff-ini'] = {
}
local trace_run = false trackers.register("buffers.run", function(v) trace_run = v end)
+local trace_grab = false trackers.register("buffers.grab", function(v) trace_grab = v end)
local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end)
-local report_buffers = logs.reporter("buffers","usage")
+local report_buffers = logs.reporter("buffers","usage")
+local report_grabbing = logs.reporter("buffers","grabbing")
local concat = table.concat
local type, next = type, next
-local sub, format, count, splitlines = string.sub, string.format, string.count, string.splitlines
+local sub, format, match, find = string.sub, string.format, string.match, string.find
+local count, splitlines = string.count, string.splitlines
local variables = interfaces.variables
local settings_to_array = utilities.parsers.settings_to_array
-local texprint, ctxcatcodes = tex.print, tex.ctxcatcodes
+
+local ctxcatcodes = tex.ctxcatcodes
+local txtcatcodes = tex.txtcatcodes
buffers = { }
local buffers = buffers
local context = context
-local data = { }
-
-function buffers.raw(name)
- return data[name] or ""
-end
+local cache = { }
local function erase(name)
- data[name] = nil
+ cache[name] = nil
end
-local function assign(name,str)
- data[name] = str
+local function assign(name,str,catcodes)
+ cache[name] = { data = str, catcodes = catcodes }
end
local function append(name,str)
- data[name] = (data[name] or "") .. str
+ local buffer = cache[name]
+ if buffer then
+ buffer.data = buffer.data .. str
+ else
+ cache[name] = { data = str }
+ end
end
local function exists(name)
- return data[name] ~= nil
+ return cache[name]
end
-local function getcontent(name) -- == raw
- return data[name] or ""
+local function getcontent(name)
+ local buffer = name and cache[name]
+ return buffer and buffer.data or ""
end
local function getlines(name)
- local d = name and data[name]
- return d and splitlines(d)
+ local buffer = name and cache[name]
+ return buffer and splitlines(buffer.data)
end
local function collectcontent(names,separator) -- no print
if type(names) == "string" then
names = settings_to_array(names)
end
- if #names == 1 then
+ local nnames = #names
+ if nnames == 0 then
+ return getcontent("") -- default buffer
+ elseif nnames == 1 then
return getcontent(names[1])
else
local t, n = { }, 0
- for i=1,#names do
+ for i=1,nnames do
local c = getcontent(names[i])
if c ~= "" then
n = n + 1
@@ -74,6 +84,7 @@ local function collectcontent(names,separator) -- no print
end
end
+buffers.raw = getcontent
buffers.erase = erase
buffers.assign = assign
buffers.append = append
@@ -100,15 +111,31 @@ local function countnesting(b,e)
return p
end
-local counters = { }
-local nesting = 0
+local counters = { }
+local nesting = 0
+local autoundent = true
+local continue = false
-function commands.grabbuffer(name,begintag,endtag,bufferdata) -- maybe move \\ to call
+-- Beware: the first character of bufferdata has to be discarded as it's there to
+-- prevent gobbling of newlines in the case of nested buffers. The last one is
+-- a newlinechar and is removed too.
+--
+-- An \n is unlikely to show up as \r is the endlinechar but \n is more generic
+-- for us.
+
+function commands.grabbuffer(name,begintag,endtag,bufferdata,catcodes) -- maybe move \\ to call
local dn = getcontent(name)
if dn == "" then
nesting = 0
+ continue = false
+ end
+ if trace_grab then
+ if #bufferdata > 30 then
+ report_grabbing("%s => |%s..%s|",name,sub(bufferdata,1,10),sub(bufferdata,-10,#bufferdata))
+ else
+ report_grabbing("%s => |%s|",name,bufferdata)
+ end
end
- -- nesting = nesting + count(bufferdata,"\\"..begintag) - count(bufferdata,"\\"..endtag)
local counter = counters[begintag]
if not counter then
counter = countnesting(begintag,endtag)
@@ -117,20 +144,46 @@ function commands.grabbuffer(name,begintag,endtag,bufferdata) -- maybe move \\ t
nesting = nesting + lpegmatch(counter,bufferdata)
local more = nesting > 0
if more then
- dn = dn .. bufferdata .. endtag
+ dn = dn .. sub(bufferdata,2,-1) .. endtag
nesting = nesting - 1
+ continue = true
else
- if dn == "" then
- dn = sub(bufferdata,1,-2)
+ if continue then
+ dn = dn .. sub(bufferdata,2,-2) -- no \r, \n is more generic
else
- dn = dn .. "\n" .. sub(bufferdata,1,-2) -- no \r, \n is more generic
+ if dn == "" then
+ dn = sub(bufferdata,2,-2)
+ else
+ dn = dn .. "\n" .. sub(bufferdata,2,-2) -- no \r, \n is more generic
+ end
end
local last = sub(dn,-1)
if last == "\n" or last == "\r" then -- \n is unlikely as \r is the endlinechar
dn = sub(dn,1,-2)
end
+ if autoundent then
+ local margin = match(dn,"[\n\r]( +)[\n\r]*$") or ""
+ local indent = #margin
+ if indent > 0 then
+ local lines = splitlines(dn)
+ local ok = true
+ local pattern = "^" .. margin
+ for i=1,#lines do
+ local l = lines[i]
+ if find(l,pattern) then
+ lines[i] = sub(l,indent+1)
+ else
+ ok = false
+ break
+ end
+ end
+ if ok then
+ dn = concat(lines,"\n")
+ end
+ end
+ end
end
- assign(name,dn)
+ assign(name,dn,catcodes)
commands.testcase(more)
end
@@ -142,13 +195,13 @@ local function prepared(name,list) -- list is optional
list = name
end
if not name or name == "" then
- name = tex.jobname .. "-" .. list .. ".tmp"
+ name = list
end
local content = collectcontent(list,nil) or ""
if content == "" then
content = "empty buffer"
end
- return name, content
+ return tex.jobname .. "-" .. name .. ".tmp", content
end
local capsule = "\\starttext\n%s\n\\stoptext\n"
@@ -177,16 +230,31 @@ function commands.savebuffer(list,name) -- name is optional
end
function commands.getbuffer(name)
- local str = data[name]
- if str and str ~= "" then
+ local str = getcontent(name)
+ if str ~= "" then
context.viafile(str)
end
end
-function commands.getbuffermkvi(name)
+function commands.getbuffermkvi(name) -- rather direct !
context.viafile(resolvers.macros.preprocessed(getcontent(name)))
end
+function commands.gettexbuffer(name)
+ local buffer = name and cache[name]
+ if buffer and buffer.data ~= "" then
+ context.pushcatcodetable()
+ if buffer.catcodes == txtcatcodes then
+ context.setcatcodetable(txtcatcodes)
+ else
+ context.setcatcodetable(ctxcatcodes)
+ end
+ -- context(function() context.viafile(buffer.data) end)
+ context.getbuffer { name } -- viafile flushes too soon
+ context.popcatcodetable()
+ end
+end
+
function commands.getbufferctxlua(name)
local ok = loadstring(getcontent(name))
if ok then
@@ -200,10 +268,14 @@ function commands.doifelsebuffer(name)
commands.testcase(exists(name))
end
--- This only used for mp buffers and is a kludge. Don't
--- change the texprint into texsprint as it fails because
--- "p<nl>enddef" becomes "penddef" then.
+-- This only used for mp buffers and is a kludge. Don't change the
+-- texprint into texsprint as it fails because "p<nl>enddef" becomes
+-- "penddef" then.
+
+-- function commands.feedback(names)
+-- texprint(ctxcatcodes,splitlines(collectcontent(names)))
+-- end
-function commands.feedback(names)
- texprint(ctxcatcodes,splitlines(collectcontent(names)))
+function commands.feedback(names) -- bad name, maybe rename to injectbuffercontent
+ context.printlines(collectcontent(names))
end
diff --git a/Master/texmf-dist/tex/context/base/buff-ini.mkii b/Master/texmf-dist/tex/context/base/buff-ini.mkii
index fc147d09041..40baaec9354 100644
--- a/Master/texmf-dist/tex/context/base/buff-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/buff-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Buffers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-ini.mkiv b/Master/texmf-dist/tex/context/base/buff-ini.mkiv
index 7bd382fe2e9..239a274c0a8 100644
--- a/Master/texmf-dist/tex/context/base/buff-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Buffers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -20,143 +20,143 @@
% number is messy and not needed as we store the number anyway
% we can get rid of \c!number
-\newcount\nofdefinedbuffers
-
\let\currentbuffer\empty
\def\doifelsebuffer#1%
{\ctxcommand{doifelsebuffer("#1")}}
-\def\resetbuffer
- {\dosingleempty\doresetbuffer}
+\unexpanded\def\resetbuffer
+ {\dosingleempty\buff_reset}
-\def\doresetbuffer[#1]%
+\def\buff_reset[#1]%
{\ctxcommand{erasebuffer("#1")}}
-\unexpanded\def\dostartdefinedbuffer
- {\bgroup
+\setuvalue{\e!start\v!buffer}%
+ {\begingroup % (3)
\obeylines
- \doquadrupleempty\dodostartbuffer}
-
-\let\dostartbuffer\dostartdefinedbuffer % used in some modules
+ \dosingleempty\buff_start}
-\def\dodostartbuffer[#1][#2][#3][#4]% [category] [name] [start] [stop]
- {\iffourthargument
- \def\next{\dododostartbuffer{#1}{#2}{#3}{#4}}%
- \else
- \def\next{\dododostartbuffer {}{#1}{#2}{#3}}%
- \fi
- \next}
+\def\buff_start[#1]%
+ {\buff_start_indeed{}{#1}{\e!start\v!buffer}{\e!stop\v!buffer}}
-\def\dododostartbuffer#1#2#3#4% \donothing needed !
- {\normalexpanded{\dodowithbuffer{#2}{#3}{#4}{\donothing}{\egroup\noexpand\getvalue{#4}}}}
+\def\buff_start_indeed#1#2#3#4% \donothing needed !
+ {\normalexpanded{\buff_pickup{#2}{#3}{#4}{}{\buff_stop{#4}}}}
-\setvalue{\e!start\v!buffer}%
- {\bgroup
+\unexpanded\def\grabbufferdata % was: \dostartbuffer
+ {\begingroup % (4)
\obeylines
- \dosingleempty\redostartbuffer}
+ \doquadrupleempty\buff_grab_direct_indeed}
-\def\redostartbuffer[#1]%
- {\dododostartbuffer{}{#1}{\e!start\v!buffer}{\e!stop\v!buffer}}
+\unexpanded\def\grabbufferdatadirect % name start stop
+ {\begingroup % (6)
+ \buff_start_indeed\empty}
-\def\dowithbuffer#1#2#3% name, startsequence, stopsequence, before, after
- {\normalexpanded{\dodowithbuffer{#1}{#2}{#3}}}
+\def\buff_grab_direct_indeed % [category] [name] [start] [stop]
+ {\iffourthargument
+ \expandafter\buff_grab_direct_indeed_a
+ \else
+ \expandafter\buff_grab_direct_indeed_b
+ \fi}
-\unexpanded\long\def\dodowithbuffer#1#2#3#4#5% name, startsequence, stopsequence, before, after
- {#4%
- \bgroup
+\def\buff_grab_direct_indeed_a[#1][#2][#3][#4]{\buff_start_indeed {#1}{#2}{#3}{#4}}
+\def\buff_grab_direct_indeed_b[#1][#2][#3][#4]{\buff_start_indeed\empty{#1}{#2}{#3}}
+
+\unexpanded\def\buff_pickup#1#2#3#4#5% name, startsequence, stopsequence, before, after
+ {\begingroup % (1)
+ #4%
+ \begingroup % (2)
+ \edef\catcodetableofbuffer{\number\catcodetable}%
\ctxcommand{erasebuffer("#1")}%
- \setcatcodetable \vrbcatcodes
- \long\def\nododowithbuffer
- {\egroup
+ \setcatcodetable\vrbcatcodes
+ \def\buff_finish
+ {\endgroup % (1)
+ \endgroup % (2)
#5}%
- \long\def\dododowithbuffer##1#3% is detokenize needed? TEST
- {\ctxcommand{grabbuffer("#1","#2","#3",\!!bs\detokenize{##1}\!!es)} % space ?
- \dododowithbuffer
- \nododowithbuffer}%
- \dododowithbuffer}
+ \def\buff_gobble##1#3% is detokenize needed? TEST
+ %{\ctxcommand{grabbuffer("#1","#2","#3",\!!bs\detokenize{##1}\!!es)} % space ?
+ {\ctxcommand{grabbuffer("#1","#2","#3",\!!bs>##1\!!es,\catcodetableofbuffer)}% space ?
+ \buff_gobble
+ \buff_finish}%
+ \buff_gobble}
-\def\setbuffer
- {\dosingleempty\dosetbuffer}
+\unexpanded\def\buff_stop#1%
+ {\endgroup % (3 & 4 & 5 & 6)
+ \getvalue{#1}}
-\let\endbuffer\relax
+\unexpanded\def\setbuffer
+ {\dosingleempty\buff_set}
-\long\def\dosetbuffer[#1]#2\endbuffer % seldom used so we just pass #2
- {\ctxcommand{assignbuffer("#1", \!!bs\detokenize{#2}\!!es)}}
+\let\endbuffer\relax
-\def\namedbufferparameter#1#2{\csname\??bu#1#2\endcsname}
+\def\buff_set[#1]#2\endbuffer % seldom used so we just pass #2
+ {\ctxcommand{assignbuffer("#1",\!!bs\detokenize{#2}\!!es,\number\catcodetable)}}
-\unexpanded\def\setupbuffer
- {\dodoubleempty\dosetupbuffer}
+% beware, never adapt the global buffer settings, actually we might introduce
+% a broken parent chain for this purpose but on the other hand it's not that
+% different from framed cum suis
-\def\dosetupbuffer[#1][#2]%
- {\ifsecondargument
- \getparameters[\??bu#1][#2]%
- \else
- \getparameters[\??bu][#1]%
- \fi}
+\installcorenamespace{buffer}
-\newtoks\everydefinebuffer
+\installcommandhandler \??buffer {buffer} \??buffer
-\unexpanded\def\definebuffer
- {\dodoubleempty\dodefinebuffer}
+\setupbuffer
+ [\c!before=,
+ \c!after=]
-\def\dodefinebuffer[#1][#2]%
- {\iffirstargument
- \global\advance\nofdefinedbuffers\plusone
- \setevalue{\??bu#1\c!number}{\number\nofdefinedbuffers}%
- \def\currentbuffer{#1}%
- \getparameters[\??bu#1][#2]%
- \the\everydefinebuffer
- \else
- % fatal error
- \fi}
+\newcount\c_buff_n_of_defined
-\def\thebuffernumber #1{\csname\??bu#1\c!number\endcsname}
-\def\thedefinedbuffer#1{def-\csname\??bu#1\c!number\endcsname}
+\let\currentdefinedbuffer\s!dummy
\appendtoks
- \setuevalue{\e!start\currentbuffer}%
- {\noexpand\dostartdefinedbuffer
- [\currentbuffer]%
- [def-\number\nofdefinedbuffers]%
- [\e!start\currentbuffer]%
- [\e!stop\currentbuffer]}%
- \setuevalue{\e!get\currentbuffer}%
- {\noexpand\dogetdefinedbuffer
- [\currentbuffer]%
- [def-\number\nofdefinedbuffers]}%
+ \global\advance\c_buff_n_of_defined\plusone
+ \setexpandedbufferparameter\c!number{\number\c_buff_n_of_defined}%
+ \edef\currentdefinedbuffer{def-\number\c_buff_n_of_defined}%
+ \setuevalue{\e!start\currentbuffer}{\buff_start_defined{\currentbuffer}{\currentdefinedbuffer}{\e!start\currentbuffer}{\e!stop\currentbuffer}}%
+ \setuevalue{\e!get\currentbuffer }{\buff_get_stored{\currentbuffer}{\currentdefinedbuffer}}%
\to \everydefinebuffer
-\def\doprocessbufferlist#1#2%
- {\doifelsenothing{#1}
- {\dododogetbuffer\empty}
- {\processcommalist[#1]#2}}
+\unexpanded\def\buff_start_defined
+ {\begingroup % (5)
+ \buff_start_indeed}
+
+\def\thebuffernumber #1{\namedbufferparameter{#1}\c!number}
+\def\thedefinedbuffer#1{def-\namedbufferparameter{#1}\c!number}
\unexpanded\def\getbuffer % no [settings yet]
- {\dosingleempty\dogetbuffer}
+ {\dosingleempty\buff_get}
-\unexpanded\def\dogetbuffer[#1]% [name]
+\unexpanded\def\buff_get[#1]% [name]
{\namedbufferparameter\empty\c!before
- \doprocessbufferlist{#1}\dododogetbuffer
+ \doifelsenothing{#1}
+ {\buff_get_stored_indeed\empty}
+ {\processcommalist[#1]\buff_get_stored_indeed}%
\namedbufferparameter\empty\c!after}
-\def\dogetdefinedbuffer[#1][#2]%
+\unexpanded\def\buff_get_stored#1#2%
{\namedbufferparameter{#1}\c!before
- \dododogetbuffer{#2}%
+ \buff_get_stored_indeed{#2}%
\namedbufferparameter{#1}\c!after}
-\def\dododogetbuffer#1%
+\unexpanded\def\buff_get_stored_indeed#1%
{\ctxcommand{getbuffer("#1")}}
-\definebuffer[\v!hiding] \setupbuffer[\v!hiding][\c!before=,\c!after=]
-
-\let\processTEXbuffer\getbuffer % handy synonym
+\definebuffer
+ [\v!hiding]
\setupbuffer
+ [\v!hiding]
[\c!before=,
\c!after=]
+\unexpanded\def\processTEXbuffer % keep case, maybe also lower
+ {\dosingleempty\buff_process_tex}
+
+\def\buff_process_tex[#1]%
+ {\pushcatcodetable
+ \catcodetable\ctxcatcodes % \setcatcodetable
+ \buff_get_stored_indeed{#1}%
+ \popcatcodetable}
+
% only mkiv:
%
% \startbuffer[x]
@@ -165,26 +165,38 @@
%
% \savebuffer[x][temp.log]
-\unexpanded\def\savebuffer{\dodoubleempty\dosavebuffer}
+\unexpanded\def\savebuffer
+ {\dodoubleempty\buff_save}
-\def\dosavebuffer[#1][#2]{\ctxcommand{savebuffer("#1","#2")}}
+\def\buff_save[#1][#2]%
+ {\ctxcommand{savebuffer("#1","#2")}}
%D Experimental: no expansion of commands in buffer!
% \startbuffer[what]
-% tex.print("WHAT")
+% context("WHAT")
% \stopbuffer
% \startbuffer
-% tex.print("JOBNAME")
+% context("JOBNAME")
% \stopbuffer
%
% \ctxluabuffer[what] \ctxluabuffer
-\def\ctxluabuffer {\dosingleempty\doctxluabuffer}
-\def\mkvibuffer {\dosingleempty\domkvibuffer}
-\def\mkvibufferraw{\dosingleempty\domkvibufferraw}
+\unexpanded\def\ctxluabuffer {\dosingleempty\buff_ctxlua}
+\unexpanded\def\mkvibuffer {\dosingleempty\buff_mkvi}
+% what was: \mkvibufferraw
+
+\def\buff_ctxlua[#1]{\ctxcommand{getbufferctxlua("#1")}}
+\def\buff_mkvi [#1]{\ctxcommand{getbuffermkvi("#1")}}
+
+% used elsewhere
+
+\unexpanded\def\doprocesstexbuffer#1{\buff_process_tex[#1]} % still used?
+
+\let\dostartbuffer\grabbufferdata % for old times sake
+
+% new (expandable):
-\def\doctxluabuffer [#1]{\ctxcommand{getbufferctxlua("#1")}}
-\def\domkvibuffer [#1]{\ctxcommand{getbuffermkvi("#1")}}
+\def\getbufferdata[#1]{\buff_get_stored_indeed{#1}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/buff-par.mkiv b/Master/texmf-dist/tex/context/base/buff-par.mkiv
index c44a75050b1..7d35676bdec 100644
--- a/Master/texmf-dist/tex/context/base/buff-par.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-par.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Parallel,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -85,7 +85,7 @@
\def\doflushparalleldefault{\directsetup{\parallelparameter\c!setups}}
\startsetups parallel:place:default
- \hangafter1
+ \hangafter\plusone
\hangindent4em
\dontleavehmode
\hbox to 3em \bgroup
diff --git a/Master/texmf-dist/tex/context/base/buff-ver.lua b/Master/texmf-dist/tex/context/base/buff-ver.lua
index bd274a36a7b..004d8985896 100644
--- a/Master/texmf-dist/tex/context/base/buff-ver.lua
+++ b/Master/texmf-dist/tex/context/base/buff-ver.lua
@@ -15,7 +15,7 @@ local type, next, rawset, rawget, setmetatable, getmetatable = type, next, rawse
local format, lower, upper,match, find, sub = string.format, string.lower, string.upper, string.match, string.find, string.sub
local splitlines = string.splitlines
local concat = table.concat
-local C, P, R, V, Carg, Cc, Cs = lpeg.C, lpeg.P, lpeg.R, lpeg.V, lpeg.Carg, lpeg.Cc, lpeg.Cs
+local C, P, R, S, V, Carg, Cc, Cs = lpeg.C, lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.Carg, lpeg.Cc, lpeg.Cs
local patterns, lpegmatch, is_lpeg = lpeg.patterns, lpeg.match, lpeg.is_lpeg
local trace_visualize = false trackers.register("buffers.visualize", function(v) trace_visualize = v end)
@@ -38,7 +38,7 @@ local addsuffix = file.addsuffix
local v_auto = variables.auto
local v_yes = variables.yes
--- beware, these all get an argument (like newline)
+-- beware, all macros have an argument:
local doinlineverbatimnewline = context.doinlineverbatimnewline
local doinlineverbatimbeginline = context.doinlineverbatimbeginline
@@ -250,10 +250,6 @@ function visualizers.load(name)
end
end
-function commands.doifelsevisualizer(name)
- commands.testcase(specifications[lower(name)])
-end
-
function visualizers.register(name,specification)
name = lower(name)
if trace_visualize then
@@ -344,25 +340,85 @@ local function hack(pattern)
return Cs(pattern * Cc(signal))
end
-function visualizers.registerescapepattern(name,before,after,normalmethod,escapemethod)
+local split_processor = typesetters.processors.split
+local apply_processor = typesetters.processors.apply
+
+-- todo: { before = b, after = a, processor = p }, ...
+
+function visualizers.registerescapepattern(name,befores,afters,normalmethod,escapemethod,processors)
local escapepattern = escapepatterns[name]
if not escapepattern then
- if trace_visualize then
- report_visualizers("registering escape pattern, name: '%s', before: '%s', after: '%s'",name,before,after)
+ if type(befores) ~= "table" then befores = { befores } end
+ if type(afters) ~= "table" then afters = { afters } end
+ if type(processors) ~= "table" then processors = { processors } end
+ for i=1,#befores do
+ local before = befores[i]
+ local after = afters[i]
+ local processor = processors[i]
+ if trace_visualize then
+ report_visualizers("registering escape pattern, name: '%s', index: '%s', before: '%s', after: '%s', processor: '%s'",
+ name,i,before,after,processor or "default")
+ end
+ before = P(before) * space_pattern
+ after = space_pattern * P(after)
+ local action
+ if processor then
+ action = function(s) apply_processor(processor,s) end
+ else
+ action = escapemethod or texmethod
+ end
+ local ep = (before / "") * ((1 - after)^0 / action) * (after / "")
+ if escapepattern then
+ escapepattern = escapepattern + ep
+ else
+ escapepattern = ep
+ end
end
- before, after = P(before) * space_pattern, space_pattern * P(after)
escapepattern = (
- (before / "")
- * ((1 - after)^0 / (escapemethod or texmethod))
- * (after / "")
- + hack((1 - before)^1) / (normalmethod or defaultmethod)
+ escapepattern
+ + hack((1 - escapepattern)^1) / (normalmethod or defaultmethod)
)^0
escapepatterns[name] = escapepattern
end
return escapepattern
end
-function visualizers.registerescapecommand(name,token,normalmethod,escapecommand)
+function visualizers.registerescapeline(name,befores,normalmethod,escapemethod,processors)
+ local escapepattern = escapepatterns[name]
+ if not escapepattern then
+ if type(befores) ~= "table" then befores = { befores } end
+ if type(processors) ~= "table" then processors = { processors } end
+ for i=1,#befores do
+ local before = befores[i]
+ local processor = processors[i]
+ if trace_visualize then
+ report_visualizers("registering escape line pattern, name: '%s', before: '%s', after: <<newline>>",name,before)
+ end
+ before = P(before) * space_pattern
+ after = space_pattern * P("\n")
+ local action
+ if processor then
+ action = function(s) apply_processor(processor,s) end
+ else
+ action = escapemethod or texmethod
+ end
+ local ep = (before / "") * ((1 - after)^0 / action) * (space_pattern / "")
+ if escapepattern then
+ escapepattern = escapepattern + ep
+ else
+ escapepattern = ep
+ end
+ end
+ escapepattern = (
+ escapepattern
+ + hack((1 - escapepattern)^1) / (normalmethod or defaultmethod)
+ )^0
+ escapepatterns[name] = escapepattern
+ end
+ return escapepattern
+end
+
+function visualizers.registerescapecommand(name,token,normalmethod,escapecommand,processor)
local escapepattern = escapepatterns[name]
if not escapepattern then
if trace_visualize then
@@ -389,24 +445,39 @@ local function visualize(content,settings) -- maybe also method in settings
local m
local e = settings.escape
if e and e ~= "" then
- local newname = format("%s-%s",e,method)
+ local newname = format("%s : %s",method,e)
local newspec = specifications[newname]
if newspec then
m = newspec
else
- local start, stop
+ local starts, stops, processors = { }, { }, { }
if e == v_yes then
- start, stop = "/BTEX", "/ETEX"
+ starts[1] = "/BTEX"
+ stops [1] = "/ETEX"
else
- start, stop = match(e,"^(.-),(.-)$") -- todo: lpeg
+ local s = settings_to_array(e,true)
+ for i=1,#s do
+ local si = s[i]
+ local processor, pattern = split_processor(si)
+ si = processor and pattern or si
+ local start, stop = match(si,"^(.-),(.-)$")
+ if start then
+ local n = #starts + 1
+ starts[n] = start
+ stops [n] = stop or ""
+ processors[n] = processor
+ end
+ end
end
local oldvisualizer = specifications[method] or specifications.default
local oldparser = oldvisualizer.direct
local newparser
- if start and stop then
- newparser = visualizers.registerescapepattern(newname,start,stop,oldparser)
+ if starts[1] and stops[1] ~= "" then
+ newparser = visualizers.registerescapepattern(newname,starts,stops,oldparser,nil,processors)
+ elseif starts[1] then
+ newparser = visualizers.registerescapeline(newname,starts,oldparser,nil,processors)
else -- for old times sake: /em
- newparser = visualizers.registerescapecommand(newname,e,oldparser)
+ newparser = visualizers.registerescapecommand(newname,e,oldparser,nil,processors)
end
m = visualizers.register(newname, {
parser = newparser,
@@ -487,31 +558,31 @@ end
-- helpers
-local function realign(lines,forced_n) -- no, auto, <number>
- forced_n = (forced_n == v_auto and huge) or tonumber(forced_n)
- if forced_n then
- local n = 0
+local function realign(lines,strip) -- "yes", <number>
+ local n
+ if strip == v_yes then
+ n = math.huge
for i=1, #lines do
local spaces = find(lines[i],"%S")
if not spaces then
-- empty line
- elseif not n then
- n = spaces
elseif spaces == 0 then
n = 0
break
- elseif n > spaces then
+ elseif spaces < n then
n = spaces
end
end
- if n > 0 then
- if n > forced_n then
- n = forced_n
- end
- for i=1,#d do
- lines[i] = sub(lines[i],n)
- end
+ n = n - 1
+ else
+ n = tonumber(strip)
+ end
+ if n and n > 0 then
+ local copy = { }
+ for i=1,#lines do
+ copy[i] = sub(lines[i],n+1)
end
+ return copy
end
return lines
end
@@ -543,6 +614,7 @@ local function getrange(lines,first,last,range) -- 1,3 1,+3 fromhere,tothere
if last < 0 then
last = noflines + last
end
+ local range = settings.range
local what = settings_to_array(range)
local r_first, r_last = what[1], what[2]
local f, l = tonumber(r_first), tonumber(r_last)
@@ -597,7 +669,7 @@ end
local function filter(lines,settings) -- todo: inline or display in settings
local strip = settings.strip
- if strip == v_yes then
+ if strip and strip ~= "" then
lines = realign(lines,strip)
end
local line, n = 0, 0
@@ -611,15 +683,24 @@ local function filter(lines,settings) -- todo: inline or display in settings
return content, m
end
--- main functions
-
local getlines = buffers.getlines
+-- interface
+
+function commands.doifelsevisualizer(name)
+ commands.testcase(specifications[lower(name)])
+end
+
+commands.loadvisualizer = visualizers.load
+
+--~ local decodecomment = resolvers.macros.decodecomment -- experiment
+
function commands.typebuffer(settings)
local lines = getlines(settings.name)
if lines then
local content, m = filter(lines,settings)
if content and content ~= "" then
+--~ content = decodecomment(content)
content = dotabs(content,settings)
visualize(content,checkedsettings(settings,"display"))
end
@@ -639,9 +720,20 @@ end
-- not really buffers but it's closely related
+-- A string.gsub(str,"(\\.-) +$","%1") is faster than an lpeg when there is a
+-- match but slower when there is no match. But anyway, we need a more clever
+-- parser so we use lpeg.
+--
+-- [[\text ]] [[\text{}]] [[\text \text ]] [[\text \\ \text ]]
+
+----- strip = Cs((P(" ")^1 * P(-1)/"" + 1)^0)
+local strip = Cs((P("\\") * ((1-S("\\ "))^1) * (P(" ")/"") + 1)^0) --
+
function commands.typestring(settings)
local content = settings.data
if content and content ~= "" then
+ content = lpegmatch(strip,content) -- can be an option, btu needed in e.g. tabulate
+ -- content = decodecomment(content)
-- content = dotabs(content,settings)
visualize(content,checkedsettings(settings,"inline"))
end
@@ -658,6 +750,7 @@ function commands.typefile(settings)
str = regimes.translate(str,regime)
end
if str and str~= "" then
+--~ content = decodecomment(content)
local lines = splitlines(str)
local content, m = filter(lines,settings)
if content and content ~= "" then
diff --git a/Master/texmf-dist/tex/context/base/buff-ver.mkii b/Master/texmf-dist/tex/context/base/buff-ver.mkii
index 3552961010f..fbe56892ea1 100644
--- a/Master/texmf-dist/tex/context/base/buff-ver.mkii
+++ b/Master/texmf-dist/tex/context/base/buff-ver.mkii
@@ -5,7 +5,7 @@
%D subtitle=Verbatim,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/buff-ver.mkiv b/Master/texmf-dist/tex/context/base/buff-ver.mkiv
index c8f07ddb4b9..5336c4458bd 100644
--- a/Master/texmf-dist/tex/context/base/buff-ver.mkiv
+++ b/Master/texmf-dist/tex/context/base/buff-ver.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Verbatim,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,10 +19,16 @@
\definesystemattribute[verbatimline][public]
-\appendtoksonce \attribute\verbatimlineattribute \attributeunsetvalue \to \everyforgetall
+\appendtoksonce
+ \attribute\verbatimlineattribute\attributeunsetvalue
+\to \everyforgetall
%D Initializations.
+\installcorenamespace{typinglines}
+\installcorenamespace{typingspace}
+\installcorenamespace{typingblank} % needs checking ... used?
+
\newtoks\everyinitializeverbatim
\appendtoks
@@ -37,88 +43,83 @@
\unexpanded\def\specialcontrolspace{\hskip\zeropoint\fastcontrolspace\hskip\zeropoint}
-\setvalue{\??tp:\c!lines:\v!yes }{\obeybreakpoints}
-\setvalue{\??tp:\c!lines:\v!hyphenated}{\obeyhyphens}
-
-\setvalue{\??tp:\c!space:\v!on }{\let\obeyedspace\specialcontrolspace}
-\setvalue{\??tp:\c!space:\v!stretch }{\let\obeyedspace\specialstretchedspace}
-\setvalue{\??tp:\c!space:\v!normal }{}
-\setvalue{\??tp:\c!space:\v!fixed }{\let\obeyedspace\specialfixedspace}
+\setvalue{\??typinglines\v!yes }{\obeybreakpoints}
+\setvalue{\??typinglines\v!hyphenated}{\obeyhyphens}
-\setvalue{\??tp:\c!blank:\v!standard }{\ctxparskip}
-\setvalue{\??tp:\c!blank:\v!small }{\smallskipamount}
-\setvalue{\??tp:\c!blank:\v!medium }{\medskipamount}
-\setvalue{\??tp:\c!blank:\v!big }{\bigskipamount}
-\setvalue{\??tp:\c!blank:\v!halfline }{.5\baselineskip}
-\setvalue{\??tp:\c!blank:\v!line }{\baselineskip}
-\setvalue{\??tp:\c!blank:\v!none }{\zeropoint}
-
-\def\secondstageinitializetype
- {\let\obeyedspace\specialobeyedspace
- \csname\??tp:\c!space:\typeparameter\c!space\endcsname
- \relax\the\everyinitializeverbatim\relax}
+\setvalue{\??typingspace\v!on }{\let\obeyedspace\specialcontrolspace}
+\setvalue{\??typingspace\v!stretch }{\let\obeyedspace\specialstretchedspace}
+\setvalue{\??typingspace\v!normal }{}
+\setvalue{\??typingspace\v!fixed }{\let\obeyedspace\specialfixedspace}
-\def\secondstageinitializetyping
- {\let\obeyedspace\specialobeyedspace
- \csname\??tp:\c!space:\typingparameter\c!space\endcsname
- \csname\??tp:\c!lines:\typingparameter\c!lines\endcsname
- \relax\the\everyinitializeverbatim\relax}
+\setvalue{\??typingblank\v!standard }{\s_spac_whitespace_parskip}
+\setvalue{\??typingblank\v!small }{\smallskipamount}
+\setvalue{\??typingblank\v!medium }{\medskipamount}
+\setvalue{\??typingblank\v!big }{\bigskipamount}
+\setvalue{\??typingblank\v!halfline }{.5\baselineskip}
+\setvalue{\??typingblank\v!line }{\baselineskip}
+\setvalue{\??typingblank\v!none }{\zeropoint}
-\def\firststageinitializetype
+\def\buff_verbatim_initialize_type_one
{\let\obeylines\ignorelines
\ignorehyphens % default
- \dosettypeattributes\c!style\c!color
+ \usetypestyleandcolor\c!style\c!color
\setcatcodetable\vrbcatcodes}
-\let\doverbatimsetlinemargin\relax
+\def\buff_verbatim_initialize_type_two
+ {\let\obeyedspace\specialobeyedspace
+ \csname\??typingspace\typeparameter\c!space\endcsname
+ \relax\the\everyinitializeverbatim\relax}
+
+\let\buff_verbatim_set_line_margin\relax
-\def\dodoverbatimsetlinemargin
+\def\buff_verbatim_set_line_margin_indeed
{\getpagestatus
- \ifrightpage
- \hskip\typingparameter\c!oddmargin\relax
- \else
- \hskip\typingparameter\c!evenmargin\relax
- \fi}
+ \hskip\ifrightpage\typingparameter\c!oddmargin\else\typingparameter\c!evenmargin\fi\relax}
-\def\docheckverbatimmargins
+\def\buff_verbatim_check_margins
{\scratchskip\typingparameter\c!oddmargin\relax
\ifzeropt\scratchskip
\else
- \let\doverbatimsetlinemargin\dodoverbatimsetlinemargin
+ \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
\fi
\scratchskip\typingparameter\c!evenmargin\relax
\ifzeropt\scratchskip
\else
- \let\doverbatimsetlinemargin\dodoverbatimsetlinemargin
+ \let\buff_verbatim_set_line_margin\buff_verbatim_set_line_margin_indeed
\fi
- \ifx\doverbatimsetlinemargin\relax
+ \ifx\buff_verbatim_set_line_margin\relax
\doadaptleftskip{\typingparameter\c!margin}%
\fi}
-\def\firststageinitializetyping
- {\switchtobodyfont[\typingparameter\c!bodyfont]%
- \docheckverbatimmargins
- \dosettypingattributes\c!style\c!color
+\def\buff_verbatim_initialize_typing_one
+ {\switchtobodyfont[\typingparameter\c!bodyfont]% can be low level call
+ \buff_verbatim_check_margins
+ \usetypingstyleandcolor\c!style\c!color
\doifsomething{\typingparameter\c!align}{\setupalign[\typingparameter\c!align]}%
\ignorehyphens} % default
+\def\buff_verbatim_initialize_typing_two
+ {\let\obeyedspace\specialobeyedspace
+ \csname\??typingspace\typingparameter\c!space\endcsname
+ \csname\??typinglines\typingparameter\c!lines\endcsname
+ \relax\the\everyinitializeverbatim\relax}
+
%D \macros
%D {definetype,setuptype}
%D
%D Specific inline verbatim commands can be defined with the
%D following command.
-\installcommandhandler{\??ty}{type}{\??ty}
+\installcorenamespace{type}
+
+\installcommandhandler \??type {type} \??type
\appendtoks
- \normalexpanded{\dodefinetype{\currenttype}}%
+ \setuevalue{\currenttype}{\buff_verbatim_type{\currenttype}}%
\to \everydefinetype
-\unexpanded\def\dodefinetype#1%
- {\setuvalue{#1}{\dotype{#1}}}
-
\appendtoks
- \doinitializevisualizer{\typeparameter\c!option}%
+ \buff_verbatim_initialize_visualizer{\typeparameter\c!option}%
\to \everysetuptype
%D \macros
@@ -138,68 +139,22 @@
%D
%D The definitions default to the standard typing values.
-\installcommandhandler{\??tp}{typing}{\??tp}
+\installcorenamespace{typing}
+
+\installcommandhandler \??typing {typing} \??typing
\appendtoks
- \normalexpanded{\dodefinetyping{\currenttyping}}%
+ \setuevalue{\e!start\currenttyping}{\buff_verbatim_typing_start{\currenttyping}}%
+ \setuevalue{\e!stop \currenttyping}{\buff_verbatim_typing_stop {\currenttyping}}%
+ \normalexpanded{\definelinenumbering[\currenttyping]}%
\to \everydefinetyping
-\unexpanded\def\dodefinetyping#1%
- {\setvalue{\e!start#1}{\dostarttyping{#1}}%
- \setvalue{\e!stop #1}{\dostoptyping {#1}}}
-
\appendtoks
- \doinitializevisualizer{\typingparameter\c!option}% we can check at the tex end
+ \buff_verbatim_initialize_visualizer{\typingparameter\c!option}% we can check at the tex end
\to \everysetuptyping
-\def\doinitializevisualizer#1%
- {\ifproductionrun\ctxlua{visualizers.load("#1")}\fi}
-
-% \definetype[typeTEX][option=tex]
-%
-% \typeTEX|\example---oeps|. this---ligates---again.
-% \typeTEX{\example---oeps}. this---ligates---again.
-% \type {\example---oeps}. this---ligates---again.
-
-%D \startbuffer
-%D \setuptyping[TEX][escape=yes]
-%D
-%D \startTEX
-%D /BTEX\em sometex/ETEX
-%D /BTEX\em sometex/ETEX \after
-%D \before /BTEX\em sometex/ETEX
-%D \before /BTEX\em sometex/ETEX \after
-%D \before /BTEX\em sometex/ETEX \inbetween /BTEX\em sometex/ETEX \after
-%D \before \after
-%D \stopTEX
-%D \stopbuffer
-%D
-%D \typebuffer \start \getbuffer \stop
-%D
-%D \startbuffer
-%D \setuptyping[TEX][escape={[[,]]}]
-%D
-%D \startTEX
-%D [[\em sometex]]
-%D [[\em sometex]] \after
-%D \before [[\em sometex]]
-%D \before [[\em sometex]] \after
-%D \before [[\em sometex]] \inbetween [[\em sometex]] \after
-%D \before \after
-%D \stopTEX
-%D \stopbuffer
-%D
-%D \typebuffer \start \getbuffer \stop
-%D
-%D \startbuffer
-%D \setuptyping[TEX][escape=//]
-%D
-%D \startTEX
-%D //\em sometex
-%D \before //\em sometex
-%D \stopTEX
-%D
-%D \typebuffer \start \getbuffer \stop
+\def\buff_verbatim_initialize_visualizer#1%
+ {\ifproductionrun\ctxcommand{loadvisualizer("#1")}\fi}
%D Verbatim command are very sensitive to argument processing,
%D which is a direct result of the \CATCODES\ being fixed at
@@ -220,12 +175,6 @@
%D \type{<<} and \type{>>} as delimiters. This alternative can
%D be used in situations where slanted typeseting is needed.
-\def\lesscharacter {<}
-\def\morecharacter {>}
-\let\texescape \textbackslash
-\let\leftargument \textbraceleft
-\let\rightargument \textbraceright
-
%D \macros
%D {type}
%D
@@ -270,97 +219,95 @@
%D
%D \typebuffer
-% beware, the command is supposed to do something like
-% \framed and not manipulate content i.e. it gets no
-% argument but something b/egrouped instead
-%
-% so, if we only had left and right it woul dbe:
-%
-% \def\doleftoftype {\typeparameter\c!left\bgroup} % we need the grouping in order
-% \def\dorightoftype{\egroup\typeparameter\c!right} % to get the normal font
-%
-% but with command:
+% Beware, the command is supposed to do something like \framed and not
+% manipulate content i.e. it gets no argument but something b/egrouped
+% instead:
+
+\def\buff_verbatim_left_of_type
+ {\typeparameter\c!left
+ \typeparameter\c!command\bgroup}
-\def\doleftoftype {\typeparameter\c!left\typeparameter\c!command\bgroup}
-\def\dorightoftype{\egroup\typeparameter\c!right}
+\def\buff_verbatim_right_of_type
+ {\egroup
+ \typeparameter\c!right}
-\unexpanded\def\type{\dotype\empty}
-\unexpanded\def\typ {\dotyp \empty}
+\unexpanded\def\type{\buff_verbatim_type\empty}
+\unexpanded\def\typ {\buff_verbatim_typ \empty}
-\def\dotype#1%
+\unexpanded\def\buff_verbatim_type#1%
{\dontleavehmode
\bgroup
\edef\currenttype{#1}%
- \doifnextoptionalelse\redotype\dodotype}
+ \doifnextoptionalelse\buff_verbatim_type_yes\buff_verbatim_type_nop}
-\def\redotype[#1]%
- {\getparameters[\??ty\currenttype][#1]%
- \dodotype}
+\def\buff_verbatim_type_yes[#1]%
+ {\setupcurrenttype[#1]%
+ \buff_verbatim_type_nop}
-\def\dodotype
- {\doleftoftype
- \futurelet\next\dodotypeone}
+\def\buff_verbatim_type_nop
+ {\buff_verbatim_left_of_type
+ \futurelet\next\buff_verbatim_type_one}
-\def\dotyp#1%
+\def\buff_verbatim_typ#1%
{\dontleavehmode
\bgroup
\edef\currenttype{#1}%
\lettypeparameter\v!lines\v!hyphenated
\let\specialobeyedspace\specialstretchedspace
- \doifnextoptionalelse\redotype\dodotype}
+ \doifnextoptionalelse\buff_verbatim_type_yes\buff_verbatim_type_nop}
-\def\dodotypeone
+\def\buff_verbatim_type_one
{\ifx\next\bgroup
- \@EA\dodotypeA
+ \expandafter\buff_verbatim_type_a
\else
- \@EA\dodotypetwo
+ \expandafter\buff_verbatim_type_two
\fi}
-\def\dodotypetwo
+\def\buff_verbatim_type_two
{\catcode`<=\othercatcode % old precaution
\catcode`>=\othercatcode % old precaution
- \futurelet\next\dodotypethree}
+ \futurelet\next\buff_verbatim_type_three}
-\def\dodotypethree
+\def\buff_verbatim_type_three
{\if\next<%
- \@EA\dodotypeB
+ \expandafter\buff_verbatim_type_b
\else
- \@EA\dodotypeC
+ \expandafter\buff_verbatim_type_c
\fi}
-\def\dodotypeA
- {\firststageinitializetype
+\def\buff_verbatim_type_a
+ {\buff_verbatim_initialize_type_one
\setcatcodetable\tpacatcodes
- \dodotypenormal}
+ \buff_verbatim_type_normal}
-\def\dodotypeB#1%
- {\firststageinitializetype
+\def\buff_verbatim_type_b#1%
+ {\buff_verbatim_initialize_type_one
\setcatcodetable\tpbcatcodes
- \dodotypenested}
+ \buff_verbatim_type_nested}
-\def\dodotypeC#1%
- {\firststageinitializetype
+\def\buff_verbatim_type_c#1%
+ {\buff_verbatim_initialize_type_one
\setcatcodetable\vrbcatcodes
- \def\next##1#1{\dodotypenormal{##1}}%
+ \def\next##1#1{\buff_verbatim_type_normal{##1}}%
\next}
-\def\dodotypenormal#1%
- {\secondstageinitializetype
+\def\buff_verbatim_type_normal#1%
+ {\buff_verbatim_initialize_type_two
\dostarttagged\t!verbatim\currenttype
- \ctxcommand{typestring {
+ \ctxcommand{typestring{
data = \!!bs\detokenize{#1}\!!es,
tab = "\typeparameter\c!tab",
method = "\typeparameter\c!option",
nature = "inline",
}}%
\dostoptagged
- \dorightoftype
+ \buff_verbatim_right_of_type
\egroup}
-\def\dodotypenested#1%
- {\secondstageinitializetype
+\def\buff_verbatim_type_nested#1%
+ {\buff_verbatim_initialize_type_two
\dostarttagged\t!verbatim\currenttype
- \ctxcommand{typestring {
+ \ctxcommand{typestring{
data = \!!bs\detokenize{#1}\!!es,
tab = "\typeparameter\c!tab",
method = "nested", % we force a special visualizer
@@ -368,7 +315,7 @@
nature = "inline",
}}%
\dostoptagged
- \dorightoftype
+ \buff_verbatim_right_of_type
\egroup
\gobbleoneargument} % grab last >
@@ -382,28 +329,28 @@
%D works all right, but a decent hyphenation support of
%D \type{\tt} text will be implemented soon.
-\def\specialfixedspace {\kern\interwordspace\relax}
-\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
-\def\specialstretchedspace{\hskip.5\interwordspace\!!plus.125\interwordstretch\relax} % more but not less
-\def\specialcontrolspace {\hskip\zeropoint\hbox{\normalcontrolspace}\hskip\zeropoint\relax}
+\unexpanded\def\specialfixedspace {\kern\interwordspace\relax}
+\unexpanded\def\specialobeyedspace {\hskip\interwordspace\relax} % better than spaceskip
+\unexpanded\def\specialstretchedspace{\hskip.5\interwordspace\!!plus.125\interwordstretch\relax} % more but not less
+\unexpanded\def\specialcontrolspace {\hskip\zeropoint\hbox{\normalcontrolspace}\hskip\zeropoint\relax}
-\def\obeyhyphens
+\unexpanded\def\obeyhyphens
{\let\obeyedspace \specialobeyedspace % maybe \specialstretchedspace
\let\controlspace\specialcontrolspace
\spaceskip.25em\relax} % hm a bit of stretch !
-\def\obeybreakpoints
+\unexpanded\def\obeybreakpoints
{\ignorehyphens
\veryraggedright}
-\def\ignorehyphens
+\unexpanded\def\ignorehyphens
{\language\minusone % extra bonus, the \null should do the job too
\let\obeyedspace \specialobeyedspace
\let\controlspace\specialcontrolspace
\spaceskip.5em\relax}
%D \macros
-%D {tex,arg,mat,dis}
+%D {tex,arg,mat,dis,astype}
%D
%D Sometimes, for instance when we pass verbatim text as an
%D argument, the fixed \CATCODES\ interfere with our wishes. An
@@ -413,61 +360,77 @@
%D troublesome solution. Instead we stick to some 'old'
%D \CONTEXT\ macros for typesetting typical \TEX\ characters.
-\def\setgroupedtype
- {\firststageinitializetype
+\def\lesscharacter {<} % obsolete
+\def\morecharacter {>} % obsolete
+
+\let\texescape \textbackslash
+\let\leftargument \textbraceleft
+\let\rightargument \textbraceright
+\let\inlinemathmarker \textdollar
+\def\displaymathmarker{\textdollar\textdollar}
+
+\def\buff_verbatim_special_type#1#2%
+ {\dontleavehmode\bgroup
+ \buff_verbatim_initialize_type_one
\catcode\leftbraceasciicode \begingroupcatcode
- \catcode\rightbraceasciicode\endgroupcatcode}
+ \catcode\rightbraceasciicode\endgroupcatcode
+ #1%
+ \aftergroup#2%
+ \let\nexttoken}
-\unexpanded\def\tex{\groupedcommand{\setgroupedtype\texescape}{\relax}}
-\unexpanded\def\arg{\groupedcommand{\setgroupedtype\leftargument}{\rightargument}}
-\unexpanded\def\mat{\groupedcommand{\setgroupedtype\$}{\$}}
-\unexpanded\def\dis{\groupedcommand{\setgroupedtype\$\$}{\$\$}}
+\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}
\let\normaltexttex\tex
\let\normaltextarg\arg
\let\normaltextmat\mat
\let\normaltextdis\dis
-\def\astype{\groupedcommand{\dosettypeattributes\c!style\c!color}{}}
+\unexpanded\def\astype{\bgroup\usetypestyleandcolor\c!style\c!color\let\nexttoken}
-%D The basic display verbatim commands are defined in an
-%D indirect way. As we will see, they are a specific case of a
-%D more general mechanism.
+%D The basic display verbatim commands are defined in an indirect way. As we
+%D will see, they are a specific case of a more general mechanism.
-\let\beginofverbatimlines\relax
-\let\endofverbatimlines \relax
+\let\beginofverbatimlines\relax % hooks
+\let\endofverbatimlines \relax % hooks
-\def\dostarttyping#1% tricky non standard lookahead
- {\bgroup
+\unexpanded\def\buff_verbatim_typing_start#1% tricky non standard lookahead
+ {\begingroup
\edef\currenttyping{#1}%
\obeylines
- \futurelet\nexttoken\dodostarttyping}
+ \futurelet\nexttoken\buff_verbatim_typing_start_indeed}
-\def\dodostarttyping
+\def\buff_verbatim_typing_start_indeed
{\ifx\nexttoken[%
- \expandafter\dododostarttyping
+ \expandafter\buff_verbatim_typing_start_yes
\else
- \expandafter\nododostarttyping
+ \expandafter\buff_verbatim_typing_start_nop
\fi}
-\def\nododostarttyping
- {\dododostarttyping[]}
+\def\buff_verbatim_typing_start_nop
+ {\typingparameter\c!before
+ \startpacked[\v!blank]
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}}
-\def\dododostarttyping[#1]%
+\def\buff_verbatim_typing_start_yes[#1]%
{\typingparameter\c!before
\startpacked[\v!blank]
\doifassignmentelse{#1}
{\setuptyping[\currenttyping][#1]}
{\doifinset\v!continue{#1}{\setuptyping[\currenttyping][\c!continue=\v!yes]}}%
- \dosetuptypelinenumbering
- \firststageinitializetyping
- \normalexpanded{\dotypeblockverbatim{\e!start\currenttyping}{\e!stop\currenttyping}}}
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \normalexpanded{\buff_verbatim_type_block{\e!start\currenttyping}{\e!stop\currenttyping}}}
-\unexpanded\def\dotypeblockverbatim#1#2%
- {\dowithbuffer{_typing_}{#1}{#2}{}{\dodotypeblockverbatim{#1}{#2}}}
+\unexpanded\def\buff_verbatim_type_block#1#2%
+ {\buff_pickup{_typing_}{#1}{#2}{}{\buff_verbatim_type_block_verbatim_indeed{#1}{#2}}} % was dowithbuffer
-\def\dodotypeblockverbatim#1#2%
- {\secondstageinitializetyping
+\def\buff_verbatim_type_block_verbatim_indeed#1#2%
+ {\buff_verbatim_initialize_typing_two
\dostarttagged\t!verbatimblock\currenttyping
\beginofverbatimlines
\dostarttagged\t!verbatimlines\empty
@@ -485,10 +448,11 @@
\dostoptagged
\csname#2\endcsname}
-\def\dostoptyping#1% hm, currenttyping
+\unexpanded\def\buff_verbatim_typing_stop#1% hm, currenttyping
{\stoppacked
\typingparameter\c!after
- \normalexpanded{\egroup\checknextindentation[\typingparameter\c!indentnext]}%
+ \useindentnextparameter\typingparameter
+ \endgroup
\dorechecknextindentation}
%D Line numbering for files is combined with filtering, while
@@ -545,43 +509,47 @@
% [category] [settings] {name} % for historic reasons, all filenames are {}
-\def\typefile
- {\dodoubleempty\dotypefile}
+\unexpanded\def\typefile
+ {\dodoubleempty\buff_verbatim_type_file}
-\def\dotypefile[#1][#2]#3%
- {\bgroup
+\def\buff_verbatim_type_file[#1][#2]#3%
+ {\begingroup
\ifsecondargument
\setuptyping[#1][#2]%
- \dododotypefile{#1}{#3}%
+ \buff_verbatim_type_file_checked{#1}{#3}%
\else\iffirstargument
\doifassignmentelse{#1}
{\setuptyping[\v!file][#1]
- \dododotypefile\v!file{#3}}
- {\dododotypefile{#1}{#3}}%
+ \buff_verbatim_type_file_checked\v!file{#3}}
+ {\buff_verbatim_type_file_checked{#1}{#3}}%
\else
- \dododotypefile\v!file{#3}%
+ \buff_verbatim_type_file_checked\v!file{#3}%
\fi\fi
- \egroup}
+ \endgroup}
-\def\dododotypefile#1#2%
+\def\buff_verbatim_type_file_checked#1#2%
{\doifelsetypingfile{#2}
- {\dodododotypefile{#1}\readfilename}
+ {\buff_verbatim_type_file_indeed{#1}\askedtypingfile}
{\showmessage\m!verbatims1{#2}}}
-\def\doifelsetypingfile#1% sets \readfilename (we will make this proper mkiv i.e. less messy)
- {\doiflocfileelse{#1}
- {\firstoftwoarguments}
- {\doifinputfileelse{#1}
- {\def\readfilename{#1}\firstoftwoarguments} % messy, looks wrong too
- {\secondoftwoarguments}}}
+\unexpanded\def\doifelsetypingfile#1%
+ {\edef\askedtypingfile{\locfilename{#1}}%
+ \ifx\askedtypingfile\empty
+ \edef\askedtypingfile{\locfilename{#1.tex}}% downward compatible
+ \fi
+ \ifx\askedtypingfile\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
-\def\dodododotypefile#1#2% category name
+\def\buff_verbatim_type_file_indeed#1#2% category name
{\edef\currenttyping{#1}%
\typingparameter\c!before
\startpacked[\v!blank]
- \dosetuptypelinenumbering
- \firststageinitializetyping
- \secondstageinitializetyping
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_initialize_typing_two
\dostarttagged\t!verbatimblock\currenttyping
\beginofverbatimlines
\dostarttagged\t!verbatimlines\empty
@@ -616,7 +584,7 @@
\def\endofverbatimlinenumbering
{\stoplinenumbering}
-\def\dosetuptypelinenumbering
+\def\buff_verbatim_setup_line_numbering
{\ifdefined\startlinenumbering
\edef\currenttypingnumbering{\typingparameter\c!numbering}%
\ifx\currenttypingnumbering\v!file
@@ -658,94 +626,94 @@
%D but they also default to the values below. Watch the
%D alternative escape character.
+% \tttf gives problems with {\tx \type...}
+% \tt\tf does not adapt to e.g. \bf
+
\setuptyping
- [ \c!before=\blank,
- \c!after=\blank,
- %\c!bodyfont=,
- %\c!color=,
- \c!space=\v!off,
- \c!page=\v!no,
- \c!tab=\v!yes, % what is this: \s!ascii ?
- \c!option=\v!none,
- \c!text=\v!no,
- \c!style=\tttf,
- \c!indentnext=\v!yes,
- \c!margin=\!!zeropoint,
- \c!evenmargin=\!!zeropoint,
- \c!oddmargin=\!!zeropoint,
- \c!blank=\v!line,
- %\c!escape=, % yes | no | {START,STOP} | default when yes: {BTEX,ETEX}
- \c!numbering=\v!no,
- %\c!lines=,
- %\c!range=,
- \c!start=1,
- %\c!stop=,
- \c!step=1,
- %\c!continue=,
- \c!strip=\v!no] %auto or number
+ [\c!before=\blank,
+ \c!after=\blank,
+ %\c!bodyfont=,
+ %\c!color=,
+ \c!space=\v!off,
+ \c!page=\v!no,
+ \c!tab=\v!yes, % what is this: \s!ascii ?
+ \c!option=\v!none,
+ \c!text=\v!no,
+ \c!style=\tt,
+ \c!indentnext=\v!yes,
+ \c!margin=\!!zeropoint,
+ \c!evenmargin=\!!zeropoint,
+ \c!oddmargin=\!!zeropoint,
+ \c!blank=\v!line,
+ %\c!escape=, % yes | no | {START,STOP} | default when yes: {BTEX,ETEX}
+ \c!numbering=\v!no,
+ %\c!lines=,
+ %\c!range=,
+ \c!start=1,
+ %\c!stop=,
+ \c!step=1,
+ %\c!continue=,
+ \c!strip=\v!no] % auto or number
\definetyping[\v!typing]
-\setuptyping[\v!file] [\s!parent=\??tp\v!typing] % we don't want \start..\stop overload
-\setuptyping[\v!buffer][\s!parent=\??tp\v!file] % we don't want \start..\stop overload
+\setuptyping[\v!file] [\s!parent=\??typing\v!typing] % we don't want \start..\stop overload
+\setuptyping[\v!buffer][\s!parent=\??typing\v!file] % we don't want \start..\stop overload
%D The setups for inline verbatim default to:
\setuptype
- [ \c!space=\v!off,
- %\c!color=,
- \c!style=\tt\tf, % \tttf gives problems with {\tx \type...}
+ [\c!space=\v!off,
+ %\c!color=,
+ \c!style=\tt,
%\c!option=\v!normal,
- \c!page=\v!no,
- \c!tab=\v!yes]
+ \c!page=\v!no,
+ \c!tab=\v!yes]
%D Buffers
% [name] [settings] | [name] | [settings]
\unexpanded\def\typebuffer
- {\dodoubleempty\dotypebuffer}
+ {\dodoubleempty\buff_verbatim_type_buffer}
-\unexpanded\def\dotypedefinedbuffer
- {\dotripleempty\dodotypedefinedbuffer}
+\unexpanded\def\buff_verbatim_type_defined_buffer
+ {\dotripleempty\buff_verbatim_type_defined_buffer_indeed}
\appendtoks
- \setuevalue{\e!type\currentbuffer}%
- {\noexpand\dotypedefinedbuffer
- [\v!buffer]%
- [def-\number\nofdefinedbuffers]}%
+ \setuevalue{\e!type\currentbuffer}{\buff_verbatim_type_defined_buffer[\v!buffer][\currentdefinedbuffer]}%
\to \everydefinebuffer
-\def\dotypebuffer[#1][#2]%
- {\bgroup
+\unexpanded\def\buff_verbatim_type_buffer[#1][#2]%
+ {\begingroup
\ifsecondargument
\setuptyping[\v!buffer][#2]%
- \processcommalist[#1]{\dododotypebuffer\v!buffer}% [name] [settings]
+ \processcommalist[#1]{\buff_verbatim_type_buffer_indeed\v!buffer}% [name] [settings]
\else\iffirstargument
\doifassignmentelse{#1}
{\setuptyping[\v!buffer][#1]%
- \dododotypebuffer\v!buffer\empty}% [settings]
- {\processcommalist[#1]{\dododotypebuffer\v!buffer}}% [name]
+ \buff_verbatim_type_buffer_indeed\v!buffer\empty}% [settings]
+ {\processcommalist[#1]{\buff_verbatim_type_buffer_indeed\v!buffer}}% [name]
\else
- \dododotypebuffer\v!buffer\empty% []
+ \buff_verbatim_type_buffer_indeed\v!buffer\empty% []
\fi\fi
- \egroup}
+ \endgroup}
-\def\dodotypedefinedbuffer[#1][#2][#3]% category name settings
- {\bgroup
+\def\buff_verbatim_type_defined_buffer_indeed[#1][#2][#3]% category name settings
+ {\begingroup
\ifthirdargument
\setuptyping[#1][#3]%
\fi
- \dododotypebuffer{#1}{#2}%
- \egroup}
+ \buff_verbatim_type_buffer_indeed{#1}{#2}%
+ \endgroup}
-\def\dododotypebuffer#1#2% category name
+\def\buff_verbatim_type_buffer_indeed#1#2% category name
{\edef\currenttyping{#1}%
\typingparameter\c!before
\startpacked[\v!blank]
- \dosetuptypelinenumbering
- \firststageinitializetyping
- \secondstageinitializetyping
+ \buff_verbatim_setup_line_numbering
+ \buff_verbatim_initialize_typing_one
+ \buff_verbatim_initialize_typing_two
\beginofverbatimlines
\dostarttagged\t!verbatimblock{#1}%
\ctxcommand{typebuffer {
@@ -763,31 +731,33 @@
\stoppacked
\typingparameter\c!after}
-% process buffers .. settings
+% get : before/after of buffer
+% typing : before/after of typing
+% process : no before/after (special case anyway)
+
+% the next one is obsolete (bad name and used nowhere) so if it stays
+% the name will change
\unexpanded\def\processbuffer
- {\dodoubleempty\doprocessbuffer}
+ {\writestatus{nota bene}{\string\processbuffer\space is obsolete}%
+ \dodoubleempty\buff_verbatim_process}
-\def\doprocessbuffer[#1][#2]%
- {\bgroup
+\def\buff_verbatim_process[#1][#2]%
+ {\begingroup
\ifsecondargument
\setuptyping[\v!buffer][#2]%
- \processcommalist[#1]{\dodoprocessbuffer\v!buffer}% [name] [settings]
+ \processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}% [name] [settings]
\else\iffirstargument
\doifassignmentelse{#1}
{\setuptyping[\v!buffer][#1]%
- \dodoprocessbuffer\v!buffer\empty}% [settings]
- {\processcommalist[#1]{\dodoprocessbuffer\v!buffer}}% [name]
+ \buff_verbatim_process_indeed\v!buffer\empty}% [settings]
+ {\processcommalist[#1]{\buff_verbatim_process_indeed\v!buffer}}% [name]
\else
- \dodoprocessbuffer\v!buffer\empty% []
+ \buff_verbatim_process_indeed\v!buffer\empty% []
\fi\fi
- \egroup}
-
-% get : before/after of buffer
-% typing : before/after of typing
-% process : no before/after (special case anyway)
+ \endgroup}
-\def\dodoprocessbuffer#1#2%
+\def\buff_verbatim_process_indeed#1#2%
{\edef\currenttyping{#1}%
\ctxcommand{processbuffer {
name = "#2",
@@ -797,21 +767,23 @@
nature = "direct",
}}}
+% so far for obsolete
+
% line numbering, keep broken lines together
\newcount\nofverbatimlines
-\def\doverbatimbeginofline
+\unexpanded\def\buff_verbatim_begin_of_line
{\ifconditional\verbatimnumberinglines
\global\advance\nofverbatimlines\plusone
\attribute\verbatimlineattribute\nofverbatimlines
\fi
\noindent
- \doverbatimsetlinemargin
+ \buff_verbatim_set_line_margin
\the\everyline\strut
\dostarttagged\t!verbatimline\empty}
-\def\doverbatimendofline
+\unexpanded\def\buff_verbatim_end_of_line
{\dostoptagged
\obeyedline % still needed?
\par
@@ -819,7 +791,7 @@
\attribute\verbatimlineattribute\attributeunsetvalue
\fi}
-\def\doverbatimemptyline
+\unexpanded\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
@@ -836,11 +808,11 @@
\def\doinlineverbatimnewline {\obeyedspace}
\def\doinlineverbatimemptyline {\obeyedspace}
-\def\dodisplayverbatimstart {\doverbatimbeginofline}
-\def\dodisplayverbatimstop {\doverbatimendofline}
-\def\dodisplayverbatimbeginline {\doverbatimbeginofline}
-\def\dodisplayverbatimnewline {\doverbatimendofline\par}
-\def\dodisplayverbatimemptyline {\doverbatimemptyline}
+\def\dodisplayverbatimstart {\buff_verbatim_begin_of_line}
+\def\dodisplayverbatimstop {\buff_verbatim_end_of_line}
+\def\dodisplayverbatimbeginline {\buff_verbatim_begin_of_line}
+\def\dodisplayverbatimnewline {\buff_verbatim_end_of_line\par}
+\def\dodisplayverbatimemptyline {\buff_verbatim_empty_line}
\def\doverbatimspace {\obeyedspace}
@@ -848,4 +820,20 @@
\loadmarkfile{buff-imp-nested} % preloaded as otherwise spurious spaces inline due to loading
\loadmarkfile{buff-imp-escaped} % for completeness
+%D To be considered:
+
+% \installcorenamespace{visualizer}
+%
+% \installcommandhandler \??visualizer {visualizer} \??visualizer
+%
+% \appendtoks
+% \setuevalue{\currentvisualizer}{\buff_verbatim_visualize{\currentvisualizer}}%
+% \to \everydefinevisualizer
+%
+% \unexpanded\def\buff_verbatim_visualize#1%
+% {\bgroup
+% \def\currentvisualizer{#1}%
+% \usevisualizerstyleandcolor\c!style\c!color
+% \let\next}
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/bxml-apa.mkiv b/Master/texmf-dist/tex/context/base/bxml-apa.mkiv
index 5fc87e5efc6..35319e4cea1 100644
--- a/Master/texmf-dist/tex/context/base/bxml-apa.mkiv
+++ b/Master/texmf-dist/tex/context/base/bxml-apa.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Publications,
%D author={Taco Hoekwater \& Hans Hagen},
%D date=\currentdate,
-%D copyright={Hans Hagen \& Taco Hoekwater}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/catc-act.mkii b/Master/texmf-dist/tex/context/base/catc-act.mkii
index 41b7e8b981d..6535afc56b8 100644
--- a/Master/texmf-dist/tex/context/base/catc-act.mkii
+++ b/Master/texmf-dist/tex/context/base/catc-act.mkii
@@ -5,7 +5,7 @@
%D subtitle=Default Catcode Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/catc-act.mkiv b/Master/texmf-dist/tex/context/base/catc-act.mkiv
index 2cde28e44f1..df228c20322 100644
--- a/Master/texmf-dist/tex/context/base/catc-act.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-act.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Default Catcode Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -14,17 +14,22 @@
%D This module deals with some active character handling. Use
%D with care.
+\unprotect
+
%D \macros
%D {installactivecharacter}
-\def\installactivecharacter#1 %
- {\edef\temp{\detokenize{#1}}%
- \cctcounterc\expandafter`\temp\relax % relax needed
+\let\m_syst_catcodes_temp\empty
+
+\normalprotected\def\installactivecharacter#1 %
+ {\edef\m_syst_catcodes_temp{\detokenize{#1}}%
+ \c_syst_catcodes_c\expandafter`\m_syst_catcodes_temp\relax % relax needed
\expandafter\startextendcatcodetable
- \expandafter\ctxcatcodes\expandafter\catcode\the\cctcounterc\activecatcode
+ \expandafter\ctxcatcodes\expandafter\catcode\the\c_syst_catcodes_c\activecatcode
\stopextendcatcodetable
- \letcatcodecommand \ctxcatcodes \cctcounterc \temp \relax
- \ifnum\currentcatcodetable=\ctxcatcodes \setcatcodetable\ctxcatcodes \fi}
+ \letcatcodecommand \ctxcatcodes \c_syst_catcodes_c \m_syst_catcodes_temp \relax
+ \ifnum\currentcatcodetable=\ctxcatcodes \setcatcodetable\ctxcatcodes \fi
+ \let\m_syst_catcodes_temp\empty}
%D \macros
%D {defineactivecharacter}
@@ -32,34 +37,36 @@
%D Use this one with care, esp in combination with catcode
%D vectors. There are better ways now.
-\chardef\activehackcode=`~
+\setnewconstant\c_syst_catcodes_hack\tildeasciicode % also defined in catc-ini.mkiv
-\def\defineactivecharacter #1#2 #3%
- {\cctcounterc\uccode\activehackcode
- \if#1"\uccode\activehackcode\expandafter\doifnumberelse\expandafter{\string#1#2}\empty #1#2\else
- \uccode\activehackcode\expandafter\doifnumberelse\expandafter{\string#1#2}\empty`#1#2\fi
- \catcode\uccode\activehackcode\activecatcode
- \uppercase{\def\next{~}}%
- \uccode\activehackcode\cctcounterc
- \expandafter\expandafter\expandafter\def\expandafter\next\expandafter
- {\expandafter\dohandleactivecharacter\next{#3}}}
+\normalprotected\def\defineactivecharacter #1#2 #3% uses \doifnumberelse which is not yet defined
+ {\c_syst_catcodes_c\uccode\c_syst_catcodes_hack
+ \if#1"\uccode\c_syst_catcodes_hack\expandafter\doifnumberelse\expandafter{\string#1#2}\empty #1#2\else
+ \uccode\c_syst_catcodes_hack\expandafter\doifnumberelse\expandafter{\string#1#2}\empty`#1#2\fi
+ \catcode\uccode\c_syst_catcodes_hack\activecatcode
+ \uppercase{\def\m_syst_catcodes_temp{~}}% brrr
+ \uccode\c_syst_catcodes_hack\c_syst_catcodes_c
+ \expandafter\expandafter\expandafter\def\expandafter\m_syst_catcodes_temp\expandafter
+ {\expandafter\syst_catcodes_handle\m_syst_catcodes_temp{#3}}%
+ \let\m_syst_catcodes_temp\empty}
\chardef\activecharactermode\plusone % overloading still backward compatible
-\def\dodohandleactivecharacter#1#2{#2}
-\def\donthandleactivecharacter#1#2{\noexpand#1}
-
-\def\dohandleactivecharacter
+\def\syst_catcodes_handle
{\ifcase\activecharactermode
- \expandafter\donthandleactivecharacter
+ \expandafter\syst_catcodes_handle_nop
\else
- \expandafter\dodohandleactivecharacter
+ \expandafter\syst_catcodes_handle_yes
\fi}
-\def\makecharacteractive #1 {\catcode`#1\active}
+\def\syst_catcodes_handle_yes#1#2{#2}
+\def\syst_catcodes_handle_nop#1#2{\noexpand#1}
+
+\normalprotected\def\makecharacteractive #1 %
+ {\catcode`#1\activecatcode}
-\def\installanddefineactivecharacter #1 % #2%
+\normalprotected\def\installanddefineactivecharacter #1 % #2%
{\normalexpanded{\noexpand\installactivecharacter \utfchar{#1} }%
\defineactivecharacter #1 }% {#2}}
-\endinput
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/catc-ctx.mkii b/Master/texmf-dist/tex/context/base/catc-ctx.mkii
index 6bf4e9cfb24..8bb43c1f92c 100644
--- a/Master/texmf-dist/tex/context/base/catc-ctx.mkii
+++ b/Master/texmf-dist/tex/context/base/catc-ctx.mkii
@@ -5,7 +5,7 @@
%D subtitle=Extra Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/catc-ctx.mkiv b/Master/texmf-dist/tex/context/base/catc-ctx.mkiv
index bdba6aeee0e..bd5c16d69a3 100644
--- a/Master/texmf-dist/tex/context/base/catc-ctx.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-ctx.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Extra Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -21,15 +21,20 @@
\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\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
@@ -41,25 +46,26 @@
\stopcatcodetable
\startcatcodetable \prtcatcodes
- \catcode\tabasciicode \spacecatcode
- \catcode\endoflineasciicode \endoflinecatcode
- \catcode\formfeedasciicode \endoflinecatcode
- \catcode\spaceasciicode \spacecatcode
- \catcode\endoffileasciicode \ignorecatcode
- \catcode\circumflexasciicode\superscriptcatcode
- \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`\@ \lettercatcode
- \catcode`\! \lettercatcode
- \catcode`\? \lettercatcode
- \catcode\tildeasciicode \activecatcode
- \catcode\barasciicode \activecatcode
+ \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\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
%startcatcodetable \mthcatcodes
@@ -98,8 +104,8 @@
\catcode\formfeedasciicode \othercatcode
\catcode\spaceasciicode \othercatcode
\catcode\endoffileasciicode \othercatcode
- \catcode`\< \begingroupcatcode
- \catcode`\> \endgroupcatcode
+ \catcode\lessthanasciicode \begingroupcatcode
+ \catcode\morethanasciicode \endgroupcatcode
\stopcatcodetable
\startcatcodetable \txtcatcodes
@@ -111,6 +117,7 @@
\catcode\backslashasciicode \escapecatcode
\catcode\leftbraceasciicode \begingroupcatcode
\catcode\rightbraceasciicode\endgroupcatcode
+ \catcode\doublecommentsignal\commentcatcode
\stopcatcodetable
\letcatcodecommand \ctxcatcodes \barasciicode \relax
diff --git a/Master/texmf-dist/tex/context/base/catc-def.mkii b/Master/texmf-dist/tex/context/base/catc-def.mkii
index 275a9a6cda4..25044bdf056 100644
--- a/Master/texmf-dist/tex/context/base/catc-def.mkii
+++ b/Master/texmf-dist/tex/context/base/catc-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Default Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/catc-def.mkiv b/Master/texmf-dist/tex/context/base/catc-def.mkiv
index 0bd7deed72b..26e8cb11ea2 100644
--- a/Master/texmf-dist/tex/context/base/catc-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-def.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Default Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -21,11 +21,11 @@
\ifdefined\prtcatcodes \else \newcatcodetable \prtcatcodes \fi
\startcatcodetable \nilcatcodes
- \catcode\tabasciicode \spacecatcode
- \catcode\endoflineasciicode\endoflinecatcode
- \catcode\formfeedasciicode \endoflinecatcode
- \catcode\spaceasciicode \spacecatcode
- \catcode\endoffileasciicode\ignorecatcode
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
\stopcatcodetable
\startcatcodetable \texcatcodes
@@ -65,27 +65,27 @@
\stopcatcodetable
\startcatcodetable \notcatcodes % probably less needed
- \catcode\tabasciicode \spacecatcode
- \catcode\endoflineasciicode \endoflinecatcode
- \catcode\formfeedasciicode \endoflinecatcode
- \catcode\spaceasciicode \spacecatcode
- \catcode\endoffileasciicode \ignorecatcode
- \catcode\circumflexasciicode\othercatcode
- \catcode\underscoreasciicode\othercatcode
- \catcode\ampersandasciicode \othercatcode
- \catcode\tildeasciicode \othercatcode
- \catcode\hashasciicode \othercatcode
- \catcode\dollarasciicode \othercatcode
- \catcode\commentasciicode \othercatcode
- \catcode`\< \othercatcode
- \catcode`\> \othercatcode
- \catcode\leftbraceasciicode \othercatcode
- \catcode\rightbraceasciicode\othercatcode
- \catcode`\" \othercatcode
- \catcode`\' \othercatcode
- \catcode`\/ \othercatcode
- \catcode\backslashasciicode \othercatcode
- \catcode\barasciicode \othercatcode
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode \othercatcode
+ \catcode\underscoreasciicode \othercatcode
+ \catcode\ampersandasciicode \othercatcode
+ \catcode\tildeasciicode \othercatcode
+ \catcode\hashasciicode \othercatcode
+ \catcode\dollarasciicode \othercatcode
+ \catcode\commentasciicode \othercatcode
+ \catcode\lessthanasciicode \othercatcode
+ \catcode\morethanasciicode \othercatcode
+ \catcode\leftbraceasciicode \othercatcode
+ \catcode\rightbraceasciicode \othercatcode
+ \catcode\doublequoteasciicode \othercatcode
+ \catcode\singlequoteasciicode \othercatcode
+ \catcode\forwardslashasciicode\othercatcode
+ \catcode\backslashasciicode \othercatcode
+ \catcode\barasciicode \othercatcode
\stopcatcodetable
\startcatcodetable \vrbcatcodes % probably less needed
@@ -97,47 +97,48 @@
\stopcatcodetable
\startcatcodetable \prtcatcodes
- \catcode\tabasciicode \spacecatcode
- \catcode\endoflineasciicode \endoflinecatcode
- \catcode\formfeedasciicode \endoflinecatcode
- \catcode\spaceasciicode \spacecatcode
- \catcode\endoffileasciicode \ignorecatcode
- \catcode\circumflexasciicode\superscriptcatcode
-% \catcode\underscoreasciicode\subscriptcatcode
- \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`\@ \lettercatcode
- \catcode`\! \lettercatcode
- \catcode`\? \lettercatcode
- \catcode\tildeasciicode \activecatcode
- \catcode\barasciicode \activecatcode
+ \catcode\tabasciicode \spacecatcode
+ \catcode\endoflineasciicode \endoflinecatcode
+ \catcode\formfeedasciicode \endoflinecatcode
+ \catcode\spaceasciicode \spacecatcode
+ \catcode\endoffileasciicode \ignorecatcode
+ \catcode\circumflexasciicode \superscriptcatcode
+ %catcode\underscoreasciicode \subscriptcatcode
+ \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
%D Because some characters have a special meaning, we provide
%D shortcuts to their character representation.
-\chardef\^=\circumflexasciicode
-\chardef\_=\underscoreasciicode % but way too wide in lm, so ... until that's fixed:
-\chardef\&=\ampersandasciicode
-\chardef\%=\commentasciicode
-\chardef\#=\hashasciicode
-\chardef\$=\dollarasciicode
-\chardef\{=\leftbraceasciicode
-\chardef\}=\rightbraceasciicode
-\chardef\\=\backslashasciicode
+\chardef \^ = \circumflexasciicode
+\chardef \_ = \underscoreasciicode % but way too wide in lm, so ... until that's fixed:
+\chardef \& = \ampersandasciicode
+\chardef \% = \commentasciicode
+\chardef \# = \hashasciicode
+\chardef \$ = \dollarasciicode
+\chardef \{ = \leftbraceasciicode
+\chardef \} = \rightbraceasciicode
+\chardef \\ = \backslashasciicode
+\chardef \| = \barasciicode
%def\_{\leavevmode \kern.06em \vbox{\hrule width.3em}}
-\def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}}
+\def\_{\dontleavehmode \kern.06em \vbox{\hrule width.3em}} % this will become a \chardef
%D From now on we can use the protection mechanisms.
-\def\unprotect {\pushcatcodetable\setcatcodetable\prtcatcodes}
-\def\protect {\popcatcodetable}
+\normalprotected\def\unprotect{\pushcatcodetable\setcatcodetable\prtcatcodes}
+\normalprotected\def\protect {\popcatcodetable}
\endinput
diff --git a/Master/texmf-dist/tex/context/base/catc-ini.lua b/Master/texmf-dist/tex/context/base/catc-ini.lua
index 2749f403c9c..b2c793a6a98 100644
--- a/Master/texmf-dist/tex/context/base/catc-ini.lua
+++ b/Master/texmf-dist/tex/context/base/catc-ini.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['catc-ini'] = {
license = "see context related readme files"
}
+-- todo: everywhere replace tex.ctxcatcodes -> catcodes.numbers.ctxcatcodes
+
catcodes = catcodes or { }
catcodes.numbers = catcodes.numbers or { }
catcodes.names = catcodes.names or { }
@@ -31,3 +33,8 @@ end
for k, v in next, catcodes.numbers do
tex[k] = v
end
+
+-- nasty
+
+table.setmetatableindex(catcodes.numbers,function(t,k) if type(k) == "number" then t[k] = k return k end end)
+table.setmetatableindex(catcodes.names, function(t,k) if type(k) == "string" then t[k] = k return k end end)
diff --git a/Master/texmf-dist/tex/context/base/catc-ini.mkii b/Master/texmf-dist/tex/context/base/catc-ini.mkii
index 900f617563a..7527466e103 100644
--- a/Master/texmf-dist/tex/context/base/catc-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/catc-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Catcode Handling,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/catc-ini.mkiv b/Master/texmf-dist/tex/context/base/catc-ini.mkiv
index 9221d17c51f..26c3ceee990 100644
--- a/Master/texmf-dist/tex/context/base/catc-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Catcode Handling,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -16,53 +16,65 @@
\registerctxluafile{catc-ini}{1.001}
+\unprotect
+
%D A long standing wish has been the availability of catcode
%D arrays. Because traditional \TEX\ does not provide this we
%D implement a fake method in the \MKII\ file. There is some
%D overlap in code with \MKII\ but we take that for granted.
-\setnewconstant\escapecatcode 0
-\setnewconstant\begingroupcatcode 1
-\setnewconstant\endgroupcatcode 2
-\setnewconstant\mathshiftcatcode 3
-\setnewconstant\alignmentcatcode 4
-\setnewconstant\endoflinecatcode 5
-\setnewconstant\parametercatcode 6
-\setnewconstant\superscriptcatcode 7
-\setnewconstant\subscriptcatcode 8
-\setnewconstant\ignorecatcode 9
-\setnewconstant\spacecatcode 10
-\setnewconstant\lettercatcode 11
-\setnewconstant\othercatcode 12 \let\other \othercatcode
-\setnewconstant\activecatcode 13 \let\active\activecatcode
-\setnewconstant\commentcatcode 14
-\setnewconstant\invalidcatcode 15
-
-\setnewconstant\tabasciicode 9
-\setnewconstant\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
-\setnewconstant\formfeedasciicode 12
-\setnewconstant\endoflineasciicode 13 % somewhat messy but this can be the active \par
-\setnewconstant\endoffileasciicode 26
-\setnewconstant\spaceasciicode 32
-\setnewconstant\hashasciicode 35
-\setnewconstant\dollarasciicode 36
-\setnewconstant\commentasciicode 37
-\setnewconstant\ampersandasciicode 38
-\setnewconstant\backslashasciicode 92 % `\\
-\setnewconstant\circumflexasciicode 94
-\setnewconstant\underscoreasciicode 95
-\setnewconstant\leftbraceasciicode 123 % `\{
-\setnewconstant\barasciicode 124 % `\|
-\setnewconstant\rightbraceasciicode 125 % `\}
-\setnewconstant\tildeasciicode 126 % `\~
-\setnewconstant\delasciicode 127
-
-\bgroup
+\setnewconstant\escapecatcode 0
+\setnewconstant\begingroupcatcode 1
+\setnewconstant\endgroupcatcode 2
+\setnewconstant\mathshiftcatcode 3
+\setnewconstant\alignmentcatcode 4
+\setnewconstant\endoflinecatcode 5
+\setnewconstant\parametercatcode 6
+\setnewconstant\superscriptcatcode 7
+\setnewconstant\subscriptcatcode 8
+\setnewconstant\ignorecatcode 9
+\setnewconstant\spacecatcode 10
+\setnewconstant\lettercatcode 11
+\setnewconstant\othercatcode 12 % finally obsolete: \let\other \othercatcode
+\setnewconstant\activecatcode 13 % finally obsolete: \let\active\activecatcode
+\setnewconstant\commentcatcode 14
+\setnewconstant\invalidcatcode 15
+
+\setnewconstant\tabasciicode 9
+\setnewconstant\newlineasciicode 10 % don't confuse this one with \endoflineasciicode
+\setnewconstant\formfeedasciicode 12
+\setnewconstant\endoflineasciicode 13 % somewhat messy but this can be the active \par
+\setnewconstant\endoffileasciicode 26
+\setnewconstant\spaceasciicode 32
+\setnewconstant\exclamationmarkasciicode 33 % ! used in namespace protection
+\setnewconstant\doublequoteasciicode 34 % "
+\setnewconstant\hashasciicode 35
+\setnewconstant\dollarasciicode 36
+\setnewconstant\commentasciicode 37
+\setnewconstant\ampersandasciicode 38
+\setnewconstant\singlequoteasciicode 39 % '
+\setnewconstant\primeasciicode 39 % '
+\setnewconstant\forwardslashasciicode 47 % /
+\setnewconstant\colonasciicode 58
+\setnewconstant\lessthanasciicode 60 % < used as alternative verbatim {
+\setnewconstant\morethanasciicode 62 % > used as alternative verbatim }
+\setnewconstant\questionmarkasciicode 63 % ? used in namespace protection
+\setnewconstant\atsignasciicode 64 % @ used in namespace protection
+\setnewconstant\backslashasciicode 92 % `\\
+\setnewconstant\circumflexasciicode 94
+\setnewconstant\underscoreasciicode 95
+\setnewconstant\leftbraceasciicode 123 % `\{
+\setnewconstant\barasciicode 124 % `\|
+\setnewconstant\rightbraceasciicode 125 % `\}
+\setnewconstant\tildeasciicode 126 % `\~
+\setnewconstant\delasciicode 127
+
+\begingroup
\catcode \tabasciicode \activecatcode \gdef\activetabtoken {^^I}
\gdef\outputnewlinechar {^^J}
\catcode \formfeedasciicode \activecatcode \gdef\activeformfeedtoken {^^L}
\catcode \endoflineasciicode \activecatcode \gdef\activeendoflinetoken{^^M}
-\egroup
+\endgroup
% \endlinechar = \endoflineasciicode % appended to input lines
% \newlinechar = \newlineasciicode % can be used in write
@@ -70,33 +82,26 @@
% rather special and used in writing to file: \let\par\outputnewlinechar
\def\initializenewlinechar % operating system dependent
- {\bgroup
+ {\begingroup
\newlinechar\newlineasciicode
\xdef\outputnewlinechar{^^J}%
- \egroup}
-
-\ifx\gobbleoneargument\undefined \long\def\gobbleoneargument#1{} \fi
-
-\newif \ifrecatcodeuppercharacters % only used in good old tex
+ \endgroup}
-\newcount\cctdefcounter \cctdefcounter\zerocount % 0 = signal, so advance before allocate
+\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
-\newcount\cctcountera
-\newcount\cctcounterb
-\newcount\cctcounterc
-
-\def\newcatcodetable#1%
- {\global\advance\cctdefcounter\plusone
- \expandafter\xdef\csname @@ccn:\number\cctdefcounter\endcsname{\string#1}% logging
+\normalprotected\def\newcatcodetable#1% we could move the cctdefcounter to lua
+ {\global\advance\c_syst_catcodes_n\plusone
+ \expandafter\xdef\csname\??qm:n:\number\c_syst_catcodes_n\endcsname{\string#1}% logging
\newconstant#1%
- #1\cctdefcounter
+ #1\c_syst_catcodes_n
\ctxlua{catcodes.register("\expandafter\gobbleoneargument\string#1",\number#1)}}
-\newcatcodetable \scratchcatcodes \initcatcodetable\scratchcatcodes
-
-\newtoks \setdefaultcatcodes
+\newtoks \everysetdefaultcatcodes
-\setdefaultcatcodes
+\everysetdefaultcatcodes % this might get dropped
{\catcode\backslashasciicode\othercatcode
\catcode\endoflineasciicode\othercatcode
\catcode\spaceasciicode \othercatcode
@@ -104,27 +109,29 @@
\catcode\delasciicode \othercatcode}
\long\normalprotected\def\startcatcodetable#1#2\stopcatcodetable
- {\bgroup
- \catcodetable\scratchcatcodes
- \the\setdefaultcatcodes
+ {\begingroup
+ \catcodetable\inicatcodes
+ \the\everysetdefaultcatcodes
#2%
\savecatcodetable#1\relax
- \egroup}
+ \endgroup}
-\def\permitcircumflexescape % to be used grouped
- {\catcode\circumflexasciicode\superscriptcatcode}
-
-\let\permitcaretescape\permitcircumflexescape
-
-\newcatcodetable\dummycatcodes
+\let\stopcatcodetable\relax
\long\normalprotected\def\startextendcatcodetable#1#2\stopextendcatcodetable
- {\bgroup
+ {\begingroup
\catcodetable#1\relax
\globaldefs\plusone
#2%
\globaldefs\zerocount
- \egroup}
+ \endgroup}
+
+\let\stopextendcatcodetable\relax
+
+\normalprotected\def\permitcircumflexescape % to be used grouped
+ {\catcode\circumflexasciicode\superscriptcatcode}
+
+\let\permitcaretescape\permitcircumflexescape
% ==
%
@@ -135,101 +142,93 @@
% \catcodetable\scratchcounter
% \egroup}
-\def\letcatcodecommand
- {\afterassignment\letcatcodecommanda\cctcountera}
-
-\def\letcatcodecommanda
- {\afterassignment\letcatcodecommandb\cctcounterb}
-
-\let\currentcatcodetable\catcodetable
-
%D The next command can be defined in a cleaner way in the
%D Mk IV file but we want to have a fast one with a minimal
%D chance for interference. Do we still need this complex
%D mechanism? Future versions of \MKIV\ might only use
%D active characters for very special cases.
-\setnewconstant\activehackcode \tildeasciicode
+\setnewconstant\c_syst_catcodes_hack\tildeasciicode
+
+%D Once a catcode is assigned, the next assignments will happen
+%D faster. We predefine some prefixes ahead of mult-sys.
-%D Once a catcode is assigned, the next assignments will happen faster.
+\def\??ql{@@ql} % let : \let
+\def\??qd{@@qd} % def : \def
+\def\??qu{@@qu} % ued : \unexpanded\def
+\def\??qm{@@qm} % \meaning
-% (expandable) let
+\def\letcatcodecommand{\afterassignment\syst_catcodes_let_a\c_syst_catcodes_a}
+\def\defcatcodecommand{\afterassignment\syst_catcodes_def_a\c_syst_catcodes_a}
+\def\uedcatcodecommand{\afterassignment\syst_catcodes_ued_a\c_syst_catcodes_a}
-\def\letcatcodecommand {\afterassignment\letcatcodecommanda\cctcountera}
-\def\letcatcodecommanda{\afterassignment\letcatcodecommandb\cctcounterb}
+\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\letcatcodecommandb % each time
- {\ifcsname CCL:\number\cctcountera:\number\cctcounterb\endcsname
- \csname CCL:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+\def\syst_catcodes_let_b % each time
+ {\ifcsname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\else
- \expandafter\letcatcodecommandc
+ \expandafter\syst_catcodes_let_c
\fi}
-\def\letcatcodecommandc % only first time
- {\expandafter\gdef\csname CCL:\number\cctcountera:\number\cctcounterb\expandafter\endcsname\expandafter
- {\expandafter\let\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname}%
- \reinstatecatcodecommandua % unexpanded
- \csname CCL:\number\cctcountera:\number\cctcounterb\endcsname}
-
-% expandable def
-
-\def\defcatcodecommand {\afterassignment\defcatcodecommanda\cctcountera}
-\def\defcatcodecommanda{\afterassignment\defcatcodecommandb\cctcounterb}
-
-\def\defcatcodecommandb % each time
- {\ifcsname CCD:\number\cctcountera:\number\cctcounterb\endcsname
- \csname CCD:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+\def\syst_catcodes_def_b % each time
+ {\ifcsname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\else
- \expandafter\defcatcodecommandc
+ \expandafter\syst_catcodes_def_c
\fi}
-\def\defcatcodecommandc % only first time (we could use \normalexpanded here)
- {\expandafter\gdef\csname CCD:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
- \expandafter##\expandafter1\expandafter
- {\expandafter\def\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname{##1}}%
- \reinstatecatcodecommanda
- \csname CCD:\number\cctcountera:\number\cctcounterb\endcsname}
+\def\syst_catcodes_ued_b % each time
+ {\ifcsname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname
+ \csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ \else
+ \expandafter\syst_catcodes_ued_c
+ \fi}
-% unexpandable def (e.g. used for discretionaries)
+\def\syst_catcodes_let_c % only first time
+ {\expandafter\gdef\csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname\expandafter
+ {\expandafter\let\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}%
+ \syst_catcodes_reinstate_unexpanded
+ \csname\??ql:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
-\def\uedcatcodecommand {\afterassignment\uedcatcodecommanda\cctcountera}
-\def\uedcatcodecommanda{\afterassignment\uedcatcodecommandb\cctcounterb}
-\def\uedcatcodecommandb % each time
- {\ifcsname CCU:\number\cctcountera:\number\cctcounterb\endcsname
- \csname CCU:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
- \else
- \expandafter\uedcatcodecommandc
- \fi}
+\def\syst_catcodes_def_c % only first time (we could use \normalexpanded here)
+ {\expandafter\gdef\csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
+ \expandafter##\expandafter1\expandafter
+ {\expandafter\def\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ \syst_catcodes_reinstate_normal
+ \csname\??qd:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
-\def\uedcatcodecommandc % only first time
- {\expandafter\gdef\csname CCU:\number\cctcountera:\number\cctcounterb\expandafter\endcsname
+\def\syst_catcodes_ued_c % only first time
+ {\expandafter\gdef\csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\expandafter\endcsname
\expandafter##\expandafter1\expandafter
- {\expandafter\normalprotected\expandafter\def\csname CCC:\number\cctcountera:\number\cctcounterb\endcsname{##1}}%
- \reinstatecatcodecommandua % unexpanded
- \csname CCU:\number\cctcountera:\number\cctcounterb\endcsname}
-
-\def\reinstatecatcodecommand{\afterassignment\reinstatecatcodecommanda\cctcounterb}
-
-\def\reinstatecatcodecommanda % can be used when a direct definition has been done
- {\bgroup % and the selector has been lost
- \uccode\activehackcode\cctcounterb
- \catcode\uccode\activehackcode\activecatcode
- \uppercase{\xdef~{\noexpand\catcodecommand{\number\cctcounterb}}}%
- \egroup}
-
-\def\reinstatecatcodecommandua % can be used when a direct definition has been done
- {\bgroup % and the selector has been lost
- \uccode\activehackcode\cctcounterb
- \catcode\uccode\activehackcode\activecatcode
- \uppercase{\normalprotected\xdef~{\noexpand\catcodecommand{\number\cctcounterb}}}%
- \egroup}
+ {\expandafter\normalprotected\expandafter\def\csname\??qm:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname{##1}}%
+ \syst_catcodes_reinstate_unexpanded
+ \csname\??qu:\number\c_syst_catcodes_a:\number\c_syst_catcodes_b\endcsname}
+
+\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{\normalprotected\xdef~{\noexpand\catcodecommand{\number\c_syst_catcodes_b}}}%
+ \endgroup}
\newconstant\defaultcatcodetable
\def\catcodecommand#1%
- {\csname CCC:\number
- \ifcsname CCC:\number\currentcatcodetable:\number#1\endcsname
+ {\csname\??qm:\number
+ \ifcsname\??qm:\number\currentcatcodetable:\number#1\endcsname
\currentcatcodetable \else \defaultcatcodetable
\fi
:\number#1\endcsname}
@@ -247,108 +246,79 @@
%D what the next macros do. Saving the catcodes can be
%D disabled by saying \type{\localcatcodestrue}.
-% quite likely we will define \unexpanded earlier on so
-% that \normalprotected will go
-
-\let\savedcatcodetable\relax
-
-\newcount\catcoderestorelevel
+\newcount\c_syst_catcodes_level
\normalprotected\def\pushcatcodetable
- {\advance\catcoderestorelevel\plusone
- \tracepushcatcodetable
- \expandafter\chardef\csname scct:\number\catcoderestorelevel\endcsname\currentcatcodetable}
+ {\advance\c_syst_catcodes_level\plusone
+ \syst_catcodes_trace_push
+ \expandafter\chardef\csname\??qm:t:\number\c_syst_catcodes_level\endcsname\currentcatcodetable}
\normalprotected\def\popcatcodetable
- {\ifcase\catcoderestorelevel
- \showcatcodenestingerror
+ {\ifcase\c_syst_catcodes_level
+ \syst_catcodes_trace_nesting_error
\else
- \expandafter\catcodetable\csname scct:\number\catcoderestorelevel\endcsname
- \tracepopcatcodetable
- \advance\catcoderestorelevel\minusone
+ \expandafter\catcodetable\csname\??qm:t:\number\c_syst_catcodes_level\endcsname
+ \syst_catcodes_trace_pop
+ \advance\c_syst_catcodes_level\minusone
\fi}
-\normalprotected\def\showcatcodenestingerror % can be overloaded
+\normalprotected\def\syst_catcodes_trace_nesting_error
{\immediate\write16{}%
- \immediate\write16{Fatal error: catcode push/pop mismatch. Fix this!}\wait\end
+ \immediate\write16{Fatal error: catcode push/pop mismatch. Fix this! (restore level: \number\c_syst_catcodes_level)}\wait\end
\immediate\write16{}}
\normalprotected\def\restorecatcodes % takes previous level
- {\ifnum\catcoderestorelevel>\plusone
- \expandafter\catcodetable\csname scct:\number\numexpr\catcoderestorelevel-1\relax\endcsname
+ {\ifnum\c_syst_catcodes_level>\plusone
+ \expandafter\catcodetable\csname\??qm:t:\number\numexpr\c_syst_catcodes_level-1\relax\endcsname
\fi}
-\newtoks\everycatcodetable
+% \newtoks\everycatcodetable
\normalprotected\def\setcatcodetable#1%
{\catcodetable#1%
- \the\everycatcodetable
- \tracesetcatcodetable}
+% \the\everycatcodetable
+ \syst_catcodes_trace_set}
+
+%D Handy for debugging:
+%D
+%D \starttyping
+%D \tracecatcodetables
+%D \stoptyping
-\def\dotracecatcodetable#1{\immediate\write16{[#1]}}
+\normalprotected\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\tracecatcodetables
- {\def\tracesetcatcodetable {\dotracecatcodetable{set \catcodetablename\space at \number\catcoderestorelevel}}%
- \def\tracepushcatcodetable{\dotracecatcodetable{push \catcodetablename\space from \catcodetableprev\space at \number\catcoderestorelevel}}%
- \def\tracepopcatcodetable {\dotracecatcodetable{pop \catcodetablename\space to \catcodetableprev\space at \number\catcoderestorelevel}}}
+\def\syst_catcodes_trace#1{\immediate\write16{[#1]}}
-\def\catcodetableprev
- {\ifnum\numexpr\catcoderestorelevel-1\relax>\zerocount
- \csname @@ccn:\number\csname scct:\number\numexpr\catcoderestorelevel-1\relax\endcsname\endcsname
+\def\syst_catcodes_prev
+ {\ifnum\numexpr\c_syst_catcodes_level-1\relax>\zerocount
+ \csname\??qm:n:\number\csname\??qm:t:\number\numexpr\c_syst_catcodes_level-1\relax\endcsname\endcsname
\else
-%
\fi}
\def\catcodetablename
{\ifnum\currentcatcodetable>\zerocount
- \csname @@ccn:\number\currentcatcodetable\endcsname
+ \csname\??qm:n:\number\currentcatcodetable\endcsname
\else
-%
\fi}
-\ifx\empty\undefined \def\empty{} \fi
+\let\syst_catcodes_trace_set \empty
+\let\syst_catcodes_trace_push\empty
+\let\syst_catcodes_trace_pop \empty
-\let\tracesetcatcodetable \empty
-\let\tracepushcatcodetable\empty
-\let\tracepopcatcodetable \empty
+% \tracecatcodetables
-%D Handy for debugging:
+\protect
-% \tracecatcodetables
+%D We still have to define these so let's do that now:
-% D Only in \MKIV\ (to be used when crossing pages with changed catcodes
-% D in the current vector):
-% D
-% D \starttyping
-% D \normalprotected\def\startcrap
-% D {\bgroup
-% D \pushcatcodes
-% D \whitespace
-% D \obeylines
-% D \activatespacehandler\v!yes
-% D \strut}
-% D
-% D \normalprotected\def\stopcrap
-% D {\popcatcodes
-% D \egroup}
-% D \stoptyping
-%
-% \newcount\catcodetablelevel
-%
-% \def\pushcatcodes
-% {\bgroup
-% \global\advance\catcodetablelevel\plusone
-% \ifcsname @@ccf:\number\catcodetablelevel\endcsname \else
-% \global\advance\cctdefcounter\plusone
-% \expandafter\global\expandafter\chardef\csname @@ccf:\number\catcodetablelevel\endcsname\cctdefcounter
-% \fi
-% \catcodetable\ctxcatcodes
-% \expandafter\savecatcodetable\csname @@ccf:\number\catcodetablelevel\endcsname
-% \egroup
-% \expandafter\catcodetable\csname @@ccf:\number\catcodetablelevel\endcsname}
-%
-% \def\popcatcodes
-% {\global\advance\catcodetablelevel\minusone}
+\newcatcodetable \inicatcodes
+\initcatcodetable\inicatcodes
-\endinput
+\let\currentcatcodetable\catcodetable
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/catc-sym.mkii b/Master/texmf-dist/tex/context/base/catc-sym.mkii
index 91cac5f90d7..55782f11ed2 100644
--- a/Master/texmf-dist/tex/context/base/catc-sym.mkii
+++ b/Master/texmf-dist/tex/context/base/catc-sym.mkii
@@ -5,7 +5,7 @@
%D subtitle=Some Handy Constants,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/catc-sym.mkiv b/Master/texmf-dist/tex/context/base/catc-sym.mkiv
index 91cac5f90d7..82169d9947d 100644
--- a/Master/texmf-dist/tex/context/base/catc-sym.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-sym.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Some Handy Constants,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -63,13 +63,13 @@
%D them for convenience and compatibility. Some old engine code
%D has been removed.
-\def\uncatcodespecials {\setcatcodetable\nilcatcodes \uncatcodespacetokens}
-\def\setnaturalcatcodes {\setcatcodetable\nilcatcodes}
-\def\setnormalcatcodes {\setcatcodetable\ctxcatcodes} % maybe \texcatcodes
-\def\uncatcodecharacters {\setcatcodetable\nilcatcodes} % was fast version, gone now
-\def\uncatcodeallcharacters{\setcatcodetable\nilcatcodes} % was slow one, with restore
+\normalprotected\def\uncatcodespecials {\setcatcodetable\nilcatcodes \uncatcodespacetokens}
+\normalprotected\def\setnaturalcatcodes {\setcatcodetable\nilcatcodes}
+\normalprotected\def\setnormalcatcodes {\setcatcodetable\ctxcatcodes} % maybe \texcatcodes
+\normalprotected\def\uncatcodecharacters {\setcatcodetable\nilcatcodes} % was fast version, gone now
+\normalprotected\def\uncatcodeallcharacters{\setcatcodetable\nilcatcodes} % was slow one, with restore
-\def\uncatcodespacetokens
+\normalprotected\def\uncatcodespacetokens
{\catcode\spaceasciicode \spacecatcode
\catcode\formfeedasciicode \ignorecatcode
\catcode\endoflineasciicode\endoflinecatcode
@@ -84,10 +84,10 @@
\newtoks\everyverbosechacters
-\def\setverbosecscharacter#1%
+\normalprotected\def\setverbosecscharacter#1%
{\edef#1{\string#1}}
-\def\setverbosecscharacters
+\normalprotected\def\setverbosecscharacters
{\the\everyverbosechacters}
\bgroup
@@ -180,8 +180,8 @@
\long\def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantokens{#2\ignorespaces}\endgroup}
\ifx\scantextokens\undefined \else
- \long\def\rescan#1{\scantextokens{#1}}
- \long\def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantextokens{#2}\endgroup}
+ \long\def\rescan#1{\scantextokens{#1}}
+ \long\def\rescanwithsetup#1#2{\begingroup\directsetup{#1}\scantextokens{#2}\endgroup}
\fi
\endinput
diff --git a/Master/texmf-dist/tex/context/base/catc-xml.mkii b/Master/texmf-dist/tex/context/base/catc-xml.mkii
index 2349e01a247..45eb5a421a1 100644
--- a/Master/texmf-dist/tex/context/base/catc-xml.mkii
+++ b/Master/texmf-dist/tex/context/base/catc-xml.mkii
@@ -5,7 +5,7 @@
%D subtitle=\XML\ Catcode Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/catc-xml.mkiv b/Master/texmf-dist/tex/context/base/catc-xml.mkiv
index 1f11d353a27..5e7df11f5cb 100644
--- a/Master/texmf-dist/tex/context/base/catc-xml.mkiv
+++ b/Master/texmf-dist/tex/context/base/catc-xml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\XML\ Catcode Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/char-act.mkiv b/Master/texmf-dist/tex/context/base/char-act.mkiv
index 1045d59758c..011c29d07fa 100644
--- a/Master/texmf-dist/tex/context/base/char-act.mkiv
+++ b/Master/texmf-dist/tex/context/base/char-act.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Active,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -15,18 +15,7 @@
\unprotect
-%D \macros
-%D {processingverbatim}
-%D
-%D Typesetting a file in most cases results in more than one
-%D page. Because we don't want problems with files that are
-%D read in during the construction of the page, we set \type
-%D {\ifprocessingverbatim}, so the output routine can adapt
-%D its behavior. Originally we used \type {\scratchread}, but
-%D because we want to support nesting, we decided to use a
-%D separate input file.
-
-\newif\ifprocessingverbatim
+\ifdefined\page_otr_fill_and_eject_page \else \let\page_otr_fill_and_eject_page\relax \fi % forward reference
%D \macros
%D {obeyedspace, obeyedtab, obeyedline, obeyedpage}
@@ -35,10 +24,10 @@
%D \NEWLINE\ and \NEWPAGE\ active and assigning them
%D \type{\obeysomething}, but first we set some default values.
-\def\obeyedspace {\ifprocessingverbatim\hbox{ }\else\space\fi}
+\def\obeyedspace {\space}
\def\obeyedtab {\obeyedspace}
\def\obeyedline {\par}
-\def\obeyedpage {\vfill\eject}
+\def\obeyedpage {\page_otr_fill_and_eject_page}
%D \macros
%D {controlspace,setcontrolspaces}
@@ -47,14 +36,13 @@
%D spaces (control spaces) we only have to adapt the definition
%D of \type{\obeyedspace} to:
-\def\controlspace{\hbox{\char32}} % rather tex
-\def\normalspace { }
-\def\normalspaces{\catcode\spaceasciicode\spacecatcode}
+\unexpanded\def\controlspace{\hbox{\char32}} % rather tex, we need the unicode value
+\unexpanded\def\normalspaces{\catcode\spaceasciicode\spacecatcode}
\bgroup
-\catcode\spaceasciicode\activecatcode
-\gdef\obeyspaces{\catcode\spaceasciicode\activecatcode\def {\obeyedspace}}
-\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}}
+ \catcode\spaceasciicode\activecatcode
+ \unexpanded\gdef\obeyspaces{\catcode\spaceasciicode\activecatcode\def {\obeyedspace}}
+ \unexpanded\gdef\setcontrolspaces{\catcode\spaceasciicode\activecatcode\def {\controlspace}}
\egroup
%D \macros
@@ -66,44 +54,19 @@
%D \NEWPAGE\ character locally, we redefine the meaning of
%D this (often already) active character.
-% \bgroup \permitcircumflexescape
-
-% \catcode\formfeedasciicode\activecatcode
-
-% \gdef^^L{\par}
-
-% \egroup
-
\expandafter\def\activeformfeedtoken{\par}
%D The following indirect definitions enable us to implement
%D all kind of \type{\obeyed} handlers.
-% \bgroup \permitcircumflexescape
-
-% \catcode\tabasciicode \activecatcode
-% \catcode\endoflineasciicode\activecatcode
-% \catcode\formfeedasciicode \activecatcode
-
-% \gdef\obeytabs {\catcode\tabasciicode \activecatcode\def^^I{\obeyedtab }}
-% \gdef\obeylines {\catcode\endoflineasciicode\activecatcode\def^^M{\obeyedline}}
-% \gdef\obeypages {\catcode\formfeedasciicode \activecatcode\def^^L{\obeyedpage}}
-
-% \gdef\ignoretabs {\catcode\tabasciicode \activecatcode\def^^I{\obeyedspace}}
-% \gdef\ignorelines{\catcode\endoflineasciicode\activecatcode\def^^M{\obeyedspace}}
-% \gdef\ignorepages{\catcode\formfeedasciicode \ignorecatcode}
-% \gdef\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode}
+\unexpanded\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }}
+\unexpanded\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}}
+\unexpanded\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}}
-% \egroup
-
-\def\obeytabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedtab }}
-\def\obeylines {\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedline}}
-\def\obeypages {\catcode\formfeedasciicode \activecatcode\expandafter\def\activeformfeedtoken {\obeyedpage}}
-
-\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}}
-\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}}
-\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode}
-\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode}
+\unexpanded\def\ignoretabs {\catcode\tabasciicode \activecatcode\expandafter\def\activetabtoken {\obeyedspace}}
+\unexpanded\def\ignorelines{\catcode\endoflineasciicode\activecatcode\expandafter\def\activeendoflinetoken{\obeyedspace}}
+\unexpanded\def\ignorepages{\catcode\formfeedasciicode \ignorecatcode}
+\unexpanded\def\ignoreeofs {\catcode\endoffileasciicode\ignorecatcode}
%D \macros
%D {naturaltextext}
@@ -112,31 +75,11 @@
%D too. We also introduce a switch that can be used in the
%D drivers and set in higher level shell macros.
-\def\naturaltextext#1\relax
- {\bgroup
+\unexpanded\def\naturaltextext#1\relax % this command will become obsolete
+ {\begingroup
\def\ascii{#1}%
\setcatcodetable\ctxcatcodes
\prettynaturalfont{\scantextokens\expandafter{\ascii}\ifhmode\unskip\fi}%
- \egroup}
+ \endgroup}
\endinput \protect
-
-% obsolete (old hack for idris)
-
-%D This is a hack, and only meant for special situations. We don't
-%D support this in for instance verbatim. The active characters map
-%D onto the \CONTEXT\ names and font handling etc. is up to the user.
-
-%D This feature is obsolete.
-
-\registerctxluafile{char-act}{1.001}
-
-\def\enableactiveutf {\ctxlua{characters.active.enable()}}
-\def\disableactiveutf{\ctxlua{characters.active.disable()}}
-\def\testactiveutf #1{\ctxlua{characters.active.test("#1")}}
-
-%D Usage:
-%D
-%D \starttyping
-%D \enableactiveutf \testactiveutf{eacute}
-%D \stoptyping
diff --git a/Master/texmf-dist/tex/context/base/char-cjk.lua b/Master/texmf-dist/tex/context/base/char-cjk.lua
index 067371c6478..b077f4a3e0e 100644
--- a/Master/texmf-dist/tex/context/base/char-cjk.lua
+++ b/Master/texmf-dist/tex/context/base/char-cjk.lua
@@ -247,7 +247,7 @@ local hangul_syllable_basetable = {
local hangul_syllable_metatable = {
__index = function(t,k)
local u = t.unicodeslot
- if k == "fscode" then
+ if k == "fscode" or k == "leadconsonant" then
return leadconsonant(u)
elseif k == "decomposed" then
return { decomposed(u) }
@@ -261,6 +261,22 @@ local hangul_syllable_metatable = {
end
}
+function characters.remap_hangul_syllabe(t)
+ local tt = type(t)
+ if tt == "number" then
+ return remapped[t] or t
+ elseif tt == "table" then
+ local r = { }
+ for i=1,#t do
+ local ti = t[i]
+ r[i] = remapped[ti] or ti
+ end
+ return r
+ else
+ return t
+ end
+end
+
local hangul_syllable_extender = function(k,v)
local t = {
unicodeslot = k,
diff --git a/Master/texmf-dist/tex/context/base/char-def.lua b/Master/texmf-dist/tex/context/base/char-def.lua
index c830774cbfa..1e3b8a595da 100644
--- a/Master/texmf-dist/tex/context/base/char-def.lua
+++ b/Master/texmf-dist/tex/context/base/char-def.lua
@@ -369,7 +369,7 @@ characters.data={
cjkwd="na",
description="RIGHT PARENTHESIS",
direction="on",
- linebreak="cl",
+ linebreak="cp",
mathclass="close",
mathname="rparent",
mirror=0x0028,
@@ -384,6 +384,7 @@ characters.data={
linebreak="al",
mathclass="binary",
mathname="ast",
+ mathsymbol=0x2217,
unicodeslot=0x002A,
},
{
@@ -400,20 +401,20 @@ characters.data={
adobename="comma",
category="po",
cjkwd="na",
+ contextname="textcomma",
description="COMMA",
direction="cs",
linebreak="is",
- mathclass="punctuation", -- redundant
- mathspec={
- {
- class="punctuation",
- name="textcomma",
- },
- {
- class="ord",
- name="mathcomma",
- },
- },
+ mathclass="punctuation",
+--mathspec={
+-- {
+-- class="punctuation",
+-- },
+-- {
+-- class="ord",
+-- name="mathcomma",
+-- },
+--},
unicodeslot=0x002C,
},
{
@@ -430,19 +431,18 @@ characters.data={
adobename="period",
category="po",
cjkwd="na",
+ contextname="textperiod",
description="FULL STOP",
direction="cs",
linebreak="is",
mathclass="ord",
mathspec={
- {
- class="ord",
- name="mathperiod",
- },
- {
- class="punctuation",
- name="textperiod",
- },
+-- {
+-- class="ord",
+-- },
+-- {
+-- class="punctuation",
+-- },
{
class="punctuation",
name="ldotp",
@@ -458,6 +458,7 @@ characters.data={
description="SOLIDUS",
direction="cs",
linebreak="sy",
+ mathclass="ord",
mathsymbol=0x2044,
unicodeslot=0x002F,
},
@@ -602,8 +603,16 @@ characters.data={
description="EQUALS SIGN",
direction="on",
linebreak="al",
- mathclass="relation",
- mathname="eq",
+ mathspec={
+ {
+ class="relation",
+ name="eq",
+ },
+ {
+ class="relation",
+ name="Relbar",
+ },
+ },
unicodeslot=0x003D,
},
{
@@ -956,7 +965,7 @@ characters.data={
cjkwd="na",
description="RIGHT SQUARE BRACKET",
direction="on",
- linebreak="cl",
+ linebreak="cp",
mathclass="close",
mathname="rbrack",
mirror=0x005B,
@@ -1600,7 +1609,7 @@ characters.data={
contextname="exclamdown",
description="INVERTED EXCLAMATION MARK",
direction="on",
- linebreak="ai",
+ linebreak="op",
unicodeslot=0x00A1,
},
{
@@ -1938,7 +1947,7 @@ characters.data={
contextname="questiondown",
description="INVERTED QUESTION MARK",
direction="on",
- linebreak="ai",
+ linebreak="op",
unicodeslot=0x00BF,
},
{
@@ -7465,6 +7474,7 @@ characters.data={
{
adobename="circumflex",
category="lm",
+ comment="check special",
contextname="textcircumflex",
description="MODIFIER LETTER CIRCUMFLEX ACCENT",
direction="on",
@@ -7478,6 +7488,7 @@ characters.data={
adobename="caron",
category="lm",
cjkwd="a",
+ comment="check special",
contextname="textcaron",
description="CARON",
direction="on",
@@ -7706,7 +7717,7 @@ characters.data={
cjkwd="a",
description="MODIFIER LETTER CROSS ACCENT",
direction="on",
- linebreak="al",
+ linebreak="bb",
unicodeslot=0x02DF,
},
{
@@ -8924,7 +8935,35 @@ characters.data={
linebreak="cm",
unicodeslot=0x036F,
},
- [0x0374]={
+ {
+ category="lu",
+ description="GREEK CAPITAL LETTER HETA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0370,
+ },
+ {
+ category="ll",
+ description="GREEK SMALL LETTER HETA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0371,
+ },
+ {
+ category="lu",
+ description="GREEK CAPITAL LETTER ARCHAIC SAMPI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0372,
+ },
+ {
+ category="ll",
+ description="GREEK SMALL LETTER ARCHAIC SAMPI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0373,
+ },
+ {
adobename="numeralsigngreek",
category="sk",
description="GREEK NUMERAL SIGN",
@@ -8933,7 +8972,7 @@ characters.data={
specials={ "char", 0x02B9 },
unicodeslot=0x0374,
},
- [0x0375]={
+ {
adobename="numeralsignlowergreek",
category="sk",
description="GREEK LOWER NUMERAL SIGN",
@@ -8941,6 +8980,20 @@ characters.data={
linebreak="al",
unicodeslot=0x0375,
},
+ {
+ category="lu",
+ description="GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0376,
+ },
+ {
+ category="ll",
+ description="GREEK SMALL LETTER PAMPHYLIAN DIGAMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0377,
+ },
[0x037A]={
adobename="ypogegrammeni",
category="lm",
@@ -9886,6 +9939,13 @@ characters.data={
uccode=0x038F,
unicodeslot=0x03CE,
},
+ [0x03CF]={
+ category="lu",
+ description="GREEK CAPITAL KAI SYMBOL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x03CF,
+ },
[0x03D0]={
adobename="betasymbolgreek",
category="ll",
@@ -11763,6 +11823,13 @@ characters.data={
linebreak="cm",
unicodeslot=0x0486,
},
+ [0x0487]={
+ category="mn",
+ description="COMBINING CYRILLIC POKRYTIE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0487,
+ },
[0x0488]={
category="me",
description="COMBINING CYRILLIC HUNDRED THOUSANDS SIGN",
@@ -13203,6 +13270,146 @@ characters.data={
uccode=0x0512,
unicodeslot=0x0513,
},
+ [0x0514]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0514,
+ },
+ [0x0515]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0515,
+ },
+ [0x0516]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER RHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0516,
+ },
+ [0x0517]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER RHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0517,
+ },
+ [0x0518]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER YAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0518,
+ },
+ [0x0519]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER YAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0519,
+ },
+ [0x051A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x051A,
+ },
+ [0x051B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x051B,
+ },
+ [0x051C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x051C,
+ },
+ [0x051D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x051D,
+ },
+ [0x051E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER ALEUT KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x051E,
+ },
+ [0x051F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER ALEUT KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x051F,
+ },
+ [0x0520]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0520,
+ },
+ [0x0521]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0521,
+ },
+ [0x0522]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0522,
+ },
+ [0x0523]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0523,
+ },
+ [0x0524]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER PE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0524,
+ },
+ [0x0525]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER PE WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0525,
+ },
+ [0x0526]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0526,
+ },
+ [0x0527]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SHHA WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0527,
+ },
[0x0531]={
adobename="Aybarmenian",
category="lu",
@@ -14717,6 +14924,41 @@ characters.data={
unicodeslot=0x0603,
visible="yes",
},
+ [0x0606]={
+ category="sm",
+ description="ARABIC-INDIC CUBE ROOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0606,
+ },
+ [0x0607]={
+ category="sm",
+ description="ARABIC-INDIC FOURTH ROOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0607,
+ },
+ [0x0608]={
+ category="sm",
+ description="ARABIC RAY",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0608,
+ },
+ [0x0609]={
+ category="po",
+ description="ARABIC-INDIC PER MILLE SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x0609,
+ },
+ [0x060A]={
+ category="po",
+ description="ARABIC-INDIC PER TEN THOUSAND SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x060A,
+ },
[0x060B]={
category="sc",
description="AFGHANI SIGN",
@@ -14729,7 +14971,7 @@ characters.data={
category="po",
description="ARABIC COMMA",
direction="cs",
- linebreak="ex",
+ linebreak="is",
unicodeslot=0x060C,
},
[0x060D]={
@@ -14795,6 +15037,41 @@ characters.data={
linebreak="cm",
unicodeslot=0x0615,
},
+ [0x0616]={
+ category="mn",
+ description="ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0616,
+ },
+ [0x0617]={
+ category="mn",
+ description="ARABIC SMALL HIGH ZAIN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0617,
+ },
+ [0x0618]={
+ category="mn",
+ description="ARABIC SMALL FATHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0618,
+ },
+ [0x0619]={
+ category="mn",
+ description="ARABIC SMALL DAMMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0619,
+ },
+ [0x061A]={
+ category="mn",
+ description="ARABIC SMALL KASRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x061A,
+ },
[0x061B]={
adobename="semicolonarabic",
category="po",
@@ -14818,6 +15095,13 @@ characters.data={
linebreak="ex",
unicodeslot=0x061F,
},
+ [0x0620]={
+ category="lo",
+ description="ARABIC LETTER KASHMIRI YEH",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0620,
+ },
[0x0621]={
adobename="hamzasukunarabic",
category="lo",
@@ -15036,6 +15320,41 @@ characters.data={
linebreak="al",
unicodeslot=0x063A,
},
+ [0x063B]={
+ category="lo",
+ description="ARABIC LETTER KEHEH WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x063B,
+ },
+ [0x063C]={
+ category="lo",
+ description="ARABIC LETTER KEHEH WITH THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x063C,
+ },
+ [0x063D]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH INVERTED V",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x063D,
+ },
+ [0x063E]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x063E,
+ },
+ [0x063F]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x063F,
+ },
[0x0640]={
adobename="tatweelarabic",
category="lm",
@@ -15272,6 +15591,13 @@ characters.data={
linebreak="cm",
unicodeslot=0x065E,
},
+ [0x065F]={
+ category="mn",
+ description="ARABIC WAVY HAMZA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x065F,
+ },
[0x0660]={
adobename="zerohackarabic",
category="nd",
@@ -15357,7 +15683,7 @@ characters.data={
category="po",
description="ARABIC PERCENT SIGN",
direction="et",
- linebreak="ex",
+ linebreak="po",
unicodeslot=0x066A,
},
[0x066B]={
@@ -16245,8 +16571,8 @@ characters.data={
[0x06DE]={
category="me",
description="ARABIC START OF RUB EL HIZB",
- direction="nsm",
- linebreak="cm",
+ direction="on",
+ linebreak="al",
unicodeslot=0x06DE,
},
[0x06DF]={
@@ -16597,7 +16923,7 @@ characters.data={
[0x070F]={
category="cf",
description="SYRIAC ABBREVIATION MARK",
- direction="bn",
+ direction="an",
linebreak="al",
unicodeslot=0x070F,
visible="yes",
@@ -17276,6 +17602,132 @@ characters.data={
shcode=0x0633,
unicodeslot=0x076D,
},
+ [0x076E]={
+ category="lo",
+ description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x076E,
+ },
+ [0x076F]={
+ category="lo",
+ description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x076F,
+ },
+ [0x0770]={
+ category="lo",
+ description="ARABIC LETTER SEEN WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0770,
+ },
+ [0x0771]={
+ category="lo",
+ description="ARABIC LETTER REH WITH SMALL ARABIC LETTER TAH AND TWO DOTS",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0771,
+ },
+ [0x0772]={
+ category="lo",
+ description="ARABIC LETTER HAH WITH SMALL ARABIC LETTER TAH ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0772,
+ },
+ [0x0773]={
+ category="lo",
+ description="ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0773,
+ },
+ [0x0774]={
+ category="lo",
+ description="ARABIC LETTER ALEF WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0774,
+ },
+ [0x0775]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0775,
+ },
+ [0x0776]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0776,
+ },
+ [0x0777]={
+ category="lo",
+ description="ARABIC LETTER FARSI YEH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0777,
+ },
+ [0x0778]={
+ category="lo",
+ description="ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0778,
+ },
+ [0x0779]={
+ category="lo",
+ description="ARABIC LETTER WAW WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x0779,
+ },
+ [0x077A]={
+ category="lo",
+ description="ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT TWO ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x077A,
+ },
+ [0x077B]={
+ category="lo",
+ description="ARABIC LETTER YEH BARREE WITH EXTENDED ARABIC-INDIC DIGIT THREE ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x077B,
+ },
+ [0x077C]={
+ category="lo",
+ description="ARABIC LETTER HAH WITH EXTENDED ARABIC-INDIC DIGIT FOUR BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x077C,
+ },
+ [0x077D]={
+ category="lo",
+ description="ARABIC LETTER SEEN WITH EXTENDED ARABIC-INDIC DIGIT FOUR ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x077D,
+ },
+ [0x077E]={
+ category="lo",
+ description="ARABIC LETTER SEEN WITH INVERTED V",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x077E,
+ },
+ [0x077F]={
+ category="lo",
+ description="ARABIC LETTER KAF WITH TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0x077F,
+ },
[0x0780]={
category="lo",
description="THAANA LETTER HAA",
@@ -18039,6 +18491,643 @@ characters.data={
linebreak="al",
unicodeslot=0x07FA,
},
+ [0x0800]={
+ category="lo",
+ description="SAMARITAN LETTER ALAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0800,
+ },
+ [0x0801]={
+ category="lo",
+ description="SAMARITAN LETTER BIT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0801,
+ },
+ [0x0802]={
+ category="lo",
+ description="SAMARITAN LETTER GAMAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0802,
+ },
+ [0x0803]={
+ category="lo",
+ description="SAMARITAN LETTER DALAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0803,
+ },
+ [0x0804]={
+ category="lo",
+ description="SAMARITAN LETTER IY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0804,
+ },
+ [0x0805]={
+ category="lo",
+ description="SAMARITAN LETTER BAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0805,
+ },
+ [0x0806]={
+ category="lo",
+ description="SAMARITAN LETTER ZEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0806,
+ },
+ [0x0807]={
+ category="lo",
+ description="SAMARITAN LETTER IT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0807,
+ },
+ [0x0808]={
+ category="lo",
+ description="SAMARITAN LETTER TIT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0808,
+ },
+ [0x0809]={
+ category="lo",
+ description="SAMARITAN LETTER YUT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0809,
+ },
+ [0x080A]={
+ category="lo",
+ description="SAMARITAN LETTER KAAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x080A,
+ },
+ [0x080B]={
+ category="lo",
+ description="SAMARITAN LETTER LABAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x080B,
+ },
+ [0x080C]={
+ category="lo",
+ description="SAMARITAN LETTER MIM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x080C,
+ },
+ [0x080D]={
+ category="lo",
+ description="SAMARITAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x080D,
+ },
+ [0x080E]={
+ category="lo",
+ description="SAMARITAN LETTER SINGAAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x080E,
+ },
+ [0x080F]={
+ category="lo",
+ description="SAMARITAN LETTER IN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x080F,
+ },
+ [0x0810]={
+ category="lo",
+ description="SAMARITAN LETTER FI",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0810,
+ },
+ [0x0811]={
+ category="lo",
+ description="SAMARITAN LETTER TSAADIY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0811,
+ },
+ [0x0812]={
+ category="lo",
+ description="SAMARITAN LETTER QUF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0812,
+ },
+ [0x0813]={
+ category="lo",
+ description="SAMARITAN LETTER RISH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0813,
+ },
+ [0x0814]={
+ category="lo",
+ description="SAMARITAN LETTER SHAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0814,
+ },
+ [0x0815]={
+ category="lo",
+ description="SAMARITAN LETTER TAAF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0815,
+ },
+ [0x0816]={
+ category="mn",
+ description="SAMARITAN MARK IN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0816,
+ },
+ [0x0817]={
+ category="mn",
+ description="SAMARITAN MARK IN-ALAF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0817,
+ },
+ [0x0818]={
+ category="mn",
+ description="SAMARITAN MARK OCCLUSION",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0818,
+ },
+ [0x0819]={
+ category="mn",
+ description="SAMARITAN MARK DAGESH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0819,
+ },
+ [0x081A]={
+ category="lm",
+ description="SAMARITAN MODIFIER LETTER EPENTHETIC YUT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x081A,
+ },
+ [0x081B]={
+ category="mn",
+ description="SAMARITAN MARK EPENTHETIC YUT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x081B,
+ },
+ [0x081C]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN LONG E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x081C,
+ },
+ [0x081D]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x081D,
+ },
+ [0x081E]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN OVERLONG AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x081E,
+ },
+ [0x081F]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN LONG AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x081F,
+ },
+ [0x0820]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0820,
+ },
+ [0x0821]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN OVERLONG A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0821,
+ },
+ [0x0822]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN LONG A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0822,
+ },
+ [0x0823]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0823,
+ },
+ [0x0824]={
+ category="lm",
+ description="SAMARITAN MODIFIER LETTER SHORT A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0824,
+ },
+ [0x0825]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN SHORT A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0825,
+ },
+ [0x0826]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN LONG U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0826,
+ },
+ [0x0827]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0827,
+ },
+ [0x0828]={
+ category="lm",
+ description="SAMARITAN MODIFIER LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0828,
+ },
+ [0x0829]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN LONG I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0829,
+ },
+ [0x082A]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x082A,
+ },
+ [0x082B]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x082B,
+ },
+ [0x082C]={
+ category="mn",
+ description="SAMARITAN VOWEL SIGN SUKUN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x082C,
+ },
+ [0x082D]={
+ category="mn",
+ description="SAMARITAN MARK NEQUDAA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x082D,
+ },
+ [0x0830]={
+ category="po",
+ description="SAMARITAN PUNCTUATION NEQUDAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0830,
+ },
+ [0x0831]={
+ category="po",
+ description="SAMARITAN PUNCTUATION AFSAAQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0831,
+ },
+ [0x0832]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ANGED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0832,
+ },
+ [0x0833]={
+ category="po",
+ description="SAMARITAN PUNCTUATION BAU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0833,
+ },
+ [0x0834]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ATMAAU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0834,
+ },
+ [0x0835]={
+ category="po",
+ description="SAMARITAN PUNCTUATION SHIYYAALAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0835,
+ },
+ [0x0836]={
+ category="po",
+ description="SAMARITAN ABBREVIATION MARK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0836,
+ },
+ [0x0837]={
+ category="po",
+ description="SAMARITAN PUNCTUATION MELODIC QITSA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0837,
+ },
+ [0x0838]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ZIQAA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0838,
+ },
+ [0x0839]={
+ category="po",
+ description="SAMARITAN PUNCTUATION QITSA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0839,
+ },
+ [0x083A]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ZAEF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x083A,
+ },
+ [0x083B]={
+ category="po",
+ description="SAMARITAN PUNCTUATION TURU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x083B,
+ },
+ [0x083C]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ARKAANU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x083C,
+ },
+ [0x083D]={
+ category="po",
+ description="SAMARITAN PUNCTUATION SOF MASHFAAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x083D,
+ },
+ [0x083E]={
+ category="po",
+ description="SAMARITAN PUNCTUATION ANNAAU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x083E,
+ },
+ [0x0840]={
+ category="lo",
+ description="MANDAIC LETTER HALQA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0840,
+ },
+ [0x0841]={
+ category="lo",
+ description="MANDAIC LETTER AB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0841,
+ },
+ [0x0842]={
+ category="lo",
+ description="MANDAIC LETTER AG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0842,
+ },
+ [0x0843]={
+ category="lo",
+ description="MANDAIC LETTER AD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0843,
+ },
+ [0x0844]={
+ category="lo",
+ description="MANDAIC LETTER AH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0844,
+ },
+ [0x0845]={
+ category="lo",
+ description="MANDAIC LETTER USHENNA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0845,
+ },
+ [0x0846]={
+ category="lo",
+ description="MANDAIC LETTER AZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0846,
+ },
+ [0x0847]={
+ category="lo",
+ description="MANDAIC LETTER IT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0847,
+ },
+ [0x0848]={
+ category="lo",
+ description="MANDAIC LETTER ATT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0848,
+ },
+ [0x0849]={
+ category="lo",
+ description="MANDAIC LETTER AKSA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0849,
+ },
+ [0x084A]={
+ category="lo",
+ description="MANDAIC LETTER AK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x084A,
+ },
+ [0x084B]={
+ category="lo",
+ description="MANDAIC LETTER AL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x084B,
+ },
+ [0x084C]={
+ category="lo",
+ description="MANDAIC LETTER AM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x084C,
+ },
+ [0x084D]={
+ category="lo",
+ description="MANDAIC LETTER AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x084D,
+ },
+ [0x084E]={
+ category="lo",
+ description="MANDAIC LETTER AS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x084E,
+ },
+ [0x084F]={
+ category="lo",
+ description="MANDAIC LETTER IN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x084F,
+ },
+ [0x0850]={
+ category="lo",
+ description="MANDAIC LETTER AP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0850,
+ },
+ [0x0851]={
+ category="lo",
+ description="MANDAIC LETTER ASZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0851,
+ },
+ [0x0852]={
+ category="lo",
+ description="MANDAIC LETTER AQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0852,
+ },
+ [0x0853]={
+ category="lo",
+ description="MANDAIC LETTER AR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0853,
+ },
+ [0x0854]={
+ category="lo",
+ description="MANDAIC LETTER ASH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0854,
+ },
+ [0x0855]={
+ category="lo",
+ description="MANDAIC LETTER AT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0855,
+ },
+ [0x0856]={
+ category="lo",
+ description="MANDAIC LETTER DUSHENNA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0856,
+ },
+ [0x0857]={
+ category="lo",
+ description="MANDAIC LETTER KAD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0857,
+ },
+ [0x0858]={
+ category="lo",
+ description="MANDAIC LETTER AIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x0858,
+ },
+ [0x0859]={
+ category="mn",
+ description="MANDAIC AFFRICATION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0859,
+ },
+ [0x085A]={
+ category="mn",
+ description="MANDAIC VOCALIZATION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x085A,
+ },
+ [0x085B]={
+ category="mn",
+ description="MANDAIC GEMINATION MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x085B,
+ },
+ [0x085E]={
+ category="po",
+ description="MANDAIC PUNCTUATION",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x085E,
+ },
+ [0x0900]={
+ category="mn",
+ description="DEVANAGARI SIGN INVERTED CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0900,
+ },
[0x0901]={
adobename="candrabindudeva",
category="mn",
@@ -18497,6 +19586,20 @@ characters.data={
linebreak="al",
unicodeslot=0x0939,
},
+ [0x093A]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN OE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x093A,
+ },
+ [0x093B]={
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN OOE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x093B,
+ },
[0x093C]={
adobename="nuktadeva",
category="mn",
@@ -18641,6 +19744,20 @@ characters.data={
linebreak="cm",
unicodeslot=0x094D,
},
+ [0x094E]={
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN PRISHTHAMATRA E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x094E,
+ },
+ [0x094F]={
+ category="mc",
+ description="DEVANAGARI VOWEL SIGN AW",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x094F,
+ },
[0x0950]={
adobename="omdeva",
category="lo",
@@ -18681,6 +19798,27 @@ characters.data={
linebreak="cm",
unicodeslot=0x0954,
},
+ [0x0955]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN CANDRA LONG E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0955,
+ },
+ [0x0956]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN UE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0956,
+ },
+ [0x0957]={
+ category="mn",
+ description="DEVANAGARI VOWEL SIGN UUE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0957,
+ },
[0x0958]={
adobename="qadeva",
category="lo",
@@ -18889,6 +20027,69 @@ characters.data={
linebreak="al",
unicodeslot=0x0970,
},
+ [0x0971]={
+ category="lm",
+ description="DEVANAGARI SIGN HIGH SPACING DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0971,
+ },
+ [0x0972]={
+ category="lo",
+ description="DEVANAGARI LETTER CANDRA A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0972,
+ },
+ [0x0973]={
+ category="lo",
+ description="DEVANAGARI LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0973,
+ },
+ [0x0974]={
+ category="lo",
+ description="DEVANAGARI LETTER OOE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0974,
+ },
+ [0x0975]={
+ category="lo",
+ description="DEVANAGARI LETTER AW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0975,
+ },
+ [0x0976]={
+ category="lo",
+ description="DEVANAGARI LETTER UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0976,
+ },
+ [0x0977]={
+ category="lo",
+ description="DEVANAGARI LETTER UUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0977,
+ },
+ [0x0979]={
+ category="lo",
+ description="DEVANAGARI LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0979,
+ },
+ [0x097A]={
+ category="lo",
+ description="DEVANAGARI LETTER HEAVY YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x097A,
+ },
[0x097B]={
category="lo",
description="DEVANAGARI LETTER GGA",
@@ -19590,7 +20791,7 @@ characters.data={
category="sc",
description="BENGALI RUPEE MARK",
direction="et",
- linebreak="pr",
+ linebreak="po",
unicodeslot=0x09F2,
},
[0x09F3]={
@@ -19598,7 +20799,7 @@ characters.data={
category="sc",
description="BENGALI RUPEE SIGN",
direction="et",
- linebreak="pr",
+ linebreak="po",
unicodeslot=0x09F3,
},
[0x09F4]={
@@ -19646,7 +20847,7 @@ characters.data={
category="no",
description="BENGALI CURRENCY DENOMINATOR SIXTEEN",
direction="l",
- linebreak="al",
+ linebreak="po",
unicodeslot=0x09F9,
},
[0x09FA]={
@@ -19657,6 +20858,13 @@ characters.data={
linebreak="al",
unicodeslot=0x09FA,
},
+ [0x09FB]={
+ category="sc",
+ description="BENGALI GANDA MARK",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x09FB,
+ },
[0x0A01]={
category="mn",
description="GURMUKHI SIGN ADAK BINDI",
@@ -20112,6 +21320,13 @@ characters.data={
linebreak="cm",
unicodeslot=0x0A4D,
},
+ [0x0A51]={
+ category="mn",
+ description="GURMUKHI SIGN UDAAT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0A51,
+ },
[0x0A59]={
adobename="khhagurmukhi",
category="lo",
@@ -20276,6 +21491,13 @@ characters.data={
linebreak="al",
unicodeslot=0x0A74,
},
+ [0x0A75]={
+ category="mn",
+ description="GURMUKHI SIGN YAKASH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0A75,
+ },
[0x0A81]={
adobename="candrabindugujarati",
category="mn",
@@ -21333,6 +22555,13 @@ characters.data={
linebreak="cm",
unicodeslot=0x0B43,
},
+ [0x0B44]={
+ category="mn",
+ description="ORIYA VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0B44,
+ },
[0x0B47]={
category="mc",
description="ORIYA VOWEL SIGN E",
@@ -21422,6 +22651,20 @@ characters.data={
linebreak="al",
unicodeslot=0x0B61,
},
+ [0x0B62]={
+ category="mn",
+ description="ORIYA VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0B62,
+ },
+ [0x0B63]={
+ category="mn",
+ description="ORIYA VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0B63,
+ },
[0x0B66]={
category="nd",
description="ORIYA DIGIT ZERO",
@@ -21506,6 +22749,48 @@ characters.data={
linebreak="al",
unicodeslot=0x0B71,
},
+ [0x0B72]={
+ category="no",
+ description="ORIYA FRACTION ONE QUARTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0B72,
+ },
+ [0x0B73]={
+ category="no",
+ description="ORIYA FRACTION ONE HALF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0B73,
+ },
+ [0x0B74]={
+ category="no",
+ description="ORIYA FRACTION THREE QUARTERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0B74,
+ },
+ [0x0B75]={
+ category="no",
+ description="ORIYA FRACTION ONE SIXTEENTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0B75,
+ },
+ [0x0B76]={
+ category="no",
+ description="ORIYA FRACTION ONE EIGHTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0B76,
+ },
+ [0x0B77]={
+ category="no",
+ description="ORIYA FRACTION THREE SIXTEENTHS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0B77,
+ },
[0x0B82]={
category="mn",
description="TAMIL SIGN ANUSVARA",
@@ -21853,6 +23138,13 @@ characters.data={
linebreak="cm",
unicodeslot=0x0BCD,
},
+ [0x0BD0]={
+ category="lo",
+ description="TAMIL OM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0BD0,
+ },
[0x0BD7]={
category="mc",
description="TAMIL AU LENGTH MARK",
@@ -22371,6 +23663,13 @@ characters.data={
linebreak="al",
unicodeslot=0x0C39,
},
+ [0x0C3D]={
+ category="lo",
+ description="TELUGU SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0C3D,
+ },
[0x0C3E]={
category="mn",
description="TELUGU VOWEL SIGN AA",
@@ -22484,6 +23783,20 @@ characters.data={
linebreak="cm",
unicodeslot=0x0C56,
},
+ [0x0C58]={
+ category="lo",
+ description="TELUGU LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0C58,
+ },
+ [0x0C59]={
+ category="lo",
+ description="TELUGU LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0C59,
+ },
[0x0C60]={
category="lo",
description="TELUGU LETTER VOCALIC RR",
@@ -22498,6 +23811,20 @@ characters.data={
linebreak="al",
unicodeslot=0x0C61,
},
+ [0x0C62]={
+ category="mn",
+ description="TELUGU VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0C62,
+ },
+ [0x0C63]={
+ category="mn",
+ description="TELUGU VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0C63,
+ },
[0x0C66]={
category="nd",
description="TELUGU DIGIT ZERO",
@@ -22568,6 +23895,62 @@ characters.data={
linebreak="nu",
unicodeslot=0x0C6F,
},
+ [0x0C78]={
+ category="no",
+ description="TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0C78,
+ },
+ [0x0C79]={
+ category="no",
+ description="TELUGU FRACTION DIGIT ONE FOR ODD POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0C79,
+ },
+ [0x0C7A]={
+ category="no",
+ description="TELUGU FRACTION DIGIT TWO FOR ODD POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0C7A,
+ },
+ [0x0C7B]={
+ category="no",
+ description="TELUGU FRACTION DIGIT THREE FOR ODD POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0C7B,
+ },
+ [0x0C7C]={
+ category="no",
+ description="TELUGU FRACTION DIGIT ONE FOR EVEN POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0C7C,
+ },
+ [0x0C7D]={
+ category="no",
+ description="TELUGU FRACTION DIGIT TWO FOR EVEN POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0C7D,
+ },
+ [0x0C7E]={
+ category="no",
+ description="TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x0C7E,
+ },
+ [0x0C7F]={
+ category="so",
+ description="TELUGU SIGN TUUMU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0C7F,
+ },
[0x0C82]={
category="mc",
description="KANNADA SIGN ANUSVARA",
@@ -23164,14 +24547,14 @@ characters.data={
[0x0CF1]={
category="so",
description="KANNADA SIGN JIHVAMULIYA",
- direction="on",
+ direction="l",
linebreak="al",
unicodeslot=0x0CF1,
},
[0x0CF2]={
category="so",
description="KANNADA SIGN UPADHMANIYA",
- direction="on",
+ direction="l",
linebreak="al",
unicodeslot=0x0CF2,
},
@@ -23427,6 +24810,13 @@ characters.data={
linebreak="al",
unicodeslot=0x0D28,
},
+ [0x0D29]={
+ category="lo",
+ description="MALAYALAM LETTER NNNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D29,
+ },
[0x0D2A]={
category="lo",
description="MALAYALAM LETTER PA",
@@ -23539,6 +24929,20 @@ characters.data={
linebreak="al",
unicodeslot=0x0D39,
},
+ [0x0D3A]={
+ category="lo",
+ description="MALAYALAM LETTER TTTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D3A,
+ },
+ [0x0D3D]={
+ category="lo",
+ description="MALAYALAM SIGN AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D3D,
+ },
[0x0D3E]={
category="mc",
description="MALAYALAM VOWEL SIGN AA",
@@ -23581,6 +24985,13 @@ characters.data={
linebreak="cm",
unicodeslot=0x0D43,
},
+ [0x0D44]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0D44,
+ },
[0x0D46]={
category="mc",
description="MALAYALAM VOWEL SIGN E",
@@ -23633,6 +25044,13 @@ characters.data={
linebreak="cm",
unicodeslot=0x0D4D,
},
+ [0x0D4E]={
+ category="lo",
+ description="MALAYALAM LETTER DOT REPH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D4E,
+ },
[0x0D57]={
category="mc",
description="MALAYALAM AU LENGTH MARK",
@@ -23654,6 +25072,20 @@ characters.data={
linebreak="al",
unicodeslot=0x0D61,
},
+ [0x0D62]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0D62,
+ },
+ [0x0D63]={
+ category="mn",
+ description="MALAYALAM VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0D63,
+ },
[0x0D66]={
category="nd",
description="MALAYALAM DIGIT ZERO",
@@ -23724,6 +25156,97 @@ characters.data={
linebreak="nu",
unicodeslot=0x0D6F,
},
+ [0x0D70]={
+ category="no",
+ description="MALAYALAM NUMBER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D70,
+ },
+ [0x0D71]={
+ category="no",
+ description="MALAYALAM NUMBER ONE HUNDRED",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D71,
+ },
+ [0x0D72]={
+ category="no",
+ description="MALAYALAM NUMBER ONE THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D72,
+ },
+ [0x0D73]={
+ category="no",
+ description="MALAYALAM FRACTION ONE QUARTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D73,
+ },
+ [0x0D74]={
+ category="no",
+ description="MALAYALAM FRACTION ONE HALF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D74,
+ },
+ [0x0D75]={
+ category="no",
+ description="MALAYALAM FRACTION THREE QUARTERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D75,
+ },
+ [0x0D79]={
+ category="so",
+ description="MALAYALAM DATE MARK",
+ direction="l",
+ linebreak="po",
+ unicodeslot=0x0D79,
+ },
+ [0x0D7A]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU NN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D7A,
+ },
+ [0x0D7B]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D7B,
+ },
+ [0x0D7C]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D7C,
+ },
+ [0x0D7D]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D7D,
+ },
+ [0x0D7E]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D7E,
+ },
+ [0x0D7F]={
+ category="lo",
+ description="MALAYALAM LETTER CHILLU K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0D7F,
+ },
[0x0D82]={
category="mc",
description="SINHALA SIGN ANUSVARAYA",
@@ -26196,6 +27719,20 @@ characters.data={
linebreak="al",
unicodeslot=0x0F6A,
},
+ [0x0F6B]={
+ category="lo",
+ description="TIBETAN LETTER KKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0F6B,
+ },
+ [0x0F6C]={
+ category="lo",
+ description="TIBETAN LETTER RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0F6C,
+ },
[0x0F71]={
category="mn",
description="TIBETAN VOWEL SIGN AA",
@@ -26392,6 +27929,34 @@ characters.data={
linebreak="al",
unicodeslot=0x0F8B,
},
+ [0x0F8C]={
+ category="lo",
+ description="TIBETAN SIGN INVERTED MCHU CAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0F8C,
+ },
+ [0x0F8D]={
+ category="mn",
+ description="TIBETAN SUBJOINED SIGN LCE TSA CAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0F8D,
+ },
+ [0x0F8E]={
+ category="mn",
+ description="TIBETAN SUBJOINED SIGN MCHU CAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0F8E,
+ },
+ [0x0F8F]={
+ category="mn",
+ description="TIBETAN SUBJOINED SIGN INVERTED MCHU CAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x0F8F,
+ },
[0x0F90]={
category="mn",
description="TIBETAN SUBJOINED LETTER KA",
@@ -26811,6 +28376,13 @@ characters.data={
linebreak="al",
unicodeslot=0x0FCC,
},
+ [0x0FCE]={
+ category="so",
+ description="TIBETAN SIGN RDEL NAG RDEL DKAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0FCE,
+ },
[0x0FCF]={
category="so",
description="TIBETAN SIGN RDEL NAG GSUM",
@@ -26832,6 +28404,69 @@ characters.data={
linebreak="bb",
unicodeslot=0x0FD1,
},
+ [0x0FD2]={
+ category="po",
+ description="TIBETAN MARK NYIS TSHEG",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x0FD2,
+ },
+ [0x0FD3]={
+ category="po",
+ description="TIBETAN MARK INITIAL BRDA RNYING YIG MGO MDUN MA",
+ direction="l",
+ linebreak="bb",
+ unicodeslot=0x0FD3,
+ },
+ [0x0FD4]={
+ category="po",
+ description="TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0FD4,
+ },
+ [0x0FD5]={
+ category="so",
+ description="RIGHT-FACING SVASTI SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0FD5,
+ },
+ [0x0FD6]={
+ category="so",
+ description="LEFT-FACING SVASTI SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0FD6,
+ },
+ [0x0FD7]={
+ category="so",
+ description="RIGHT-FACING SVASTI SIGN WITH DOTS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0FD7,
+ },
+ [0x0FD8]={
+ category="so",
+ description="LEFT-FACING SVASTI SIGN WITH DOTS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x0FD8,
+ },
+ [0x0FD9]={
+ category="po",
+ description="TIBETAN MARK LEADING MCHAN RTAGS",
+ direction="l",
+ linebreak="gl",
+ unicodeslot=0x0FD9,
+ },
+ [0x0FDA]={
+ category="po",
+ description="TIBETAN MARK TRAILING MCHAN RTAGS",
+ direction="l",
+ linebreak="gl",
+ unicodeslot=0x0FDA,
+ },
[0x1000]={
category="lo",
description="MYANMAR LETTER KA",
@@ -27070,6 +28705,13 @@ characters.data={
linebreak="sa",
unicodeslot=0x1021,
},
+ [0x1022]={
+ category="lo",
+ description="MYANMAR LETTER SHAN A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1022,
+ },
[0x1023]={
category="lo",
description="MYANMAR LETTER I",
@@ -27106,6 +28748,13 @@ characters.data={
linebreak="sa",
unicodeslot=0x1027,
},
+ [0x1028]={
+ category="lo",
+ description="MYANMAR LETTER MON E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1028,
+ },
[0x1029]={
category="lo",
description="MYANMAR LETTER O",
@@ -27120,6 +28769,13 @@ characters.data={
linebreak="sa",
unicodeslot=0x102A,
},
+ [0x102B]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN TALL AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x102B,
+ },
[0x102C]={
category="mc",
description="MYANMAR VOWEL SIGN AA",
@@ -27169,6 +28825,27 @@ characters.data={
linebreak="sa",
unicodeslot=0x1032,
},
+ [0x1033]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN MON II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1033,
+ },
+ [0x1034]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN MON O",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1034,
+ },
+ [0x1035]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN E ABOVE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1035,
+ },
[0x1036]={
category="mn",
description="MYANMAR SIGN ANUSVARA",
@@ -27197,6 +28874,48 @@ characters.data={
linebreak="sa",
unicodeslot=0x1039,
},
+ [0x103A]={
+ category="mn",
+ description="MYANMAR SIGN ASAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x103A,
+ },
+ [0x103B]={
+ category="mc",
+ description="MYANMAR CONSONANT SIGN MEDIAL YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x103B,
+ },
+ [0x103C]={
+ category="mc",
+ description="MYANMAR CONSONANT SIGN MEDIAL RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x103C,
+ },
+ [0x103D]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MEDIAL WA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x103D,
+ },
+ [0x103E]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MEDIAL HA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x103E,
+ },
+ [0x103F]={
+ category="lo",
+ description="MYANMAR LETTER GREAT SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x103F,
+ },
[0x1040]={
category="nd",
description="MYANMAR DIGIT ZERO",
@@ -27379,6 +29098,496 @@ characters.data={
linebreak="sa",
unicodeslot=0x1059,
},
+ [0x105A]={
+ category="lo",
+ description="MYANMAR LETTER MON NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x105A,
+ },
+ [0x105B]={
+ category="lo",
+ description="MYANMAR LETTER MON JHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x105B,
+ },
+ [0x105C]={
+ category="lo",
+ description="MYANMAR LETTER MON BBA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x105C,
+ },
+ [0x105D]={
+ category="lo",
+ description="MYANMAR LETTER MON BBE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x105D,
+ },
+ [0x105E]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MON MEDIAL NA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x105E,
+ },
+ [0x105F]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MON MEDIAL MA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x105F,
+ },
+ [0x1060]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN MON MEDIAL LA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1060,
+ },
+ [0x1061]={
+ category="lo",
+ description="MYANMAR LETTER SGAW KAREN SHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1061,
+ },
+ [0x1062]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN SGAW KAREN EU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1062,
+ },
+ [0x1063]={
+ category="mc",
+ description="MYANMAR TONE MARK SGAW KAREN HATHI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1063,
+ },
+ [0x1064]={
+ category="mc",
+ description="MYANMAR TONE MARK SGAW KAREN KE PHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1064,
+ },
+ [0x1065]={
+ category="lo",
+ description="MYANMAR LETTER WESTERN PWO KAREN THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1065,
+ },
+ [0x1066]={
+ category="lo",
+ description="MYANMAR LETTER WESTERN PWO KAREN PWA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1066,
+ },
+ [0x1067]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN WESTERN PWO KAREN EU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1067,
+ },
+ [0x1068]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN WESTERN PWO KAREN UE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1068,
+ },
+ [0x1069]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-1",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1069,
+ },
+ [0x106A]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-2",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106A,
+ },
+ [0x106B]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-3",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106B,
+ },
+ [0x106C]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-4",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106C,
+ },
+ [0x106D]={
+ category="mc",
+ description="MYANMAR SIGN WESTERN PWO KAREN TONE-5",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106D,
+ },
+ [0x106E]={
+ category="lo",
+ description="MYANMAR LETTER EASTERN PWO KAREN NNA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106E,
+ },
+ [0x106F]={
+ category="lo",
+ description="MYANMAR LETTER EASTERN PWO KAREN YWA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x106F,
+ },
+ [0x1070]={
+ category="lo",
+ description="MYANMAR LETTER EASTERN PWO KAREN GHWA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1070,
+ },
+ [0x1071]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN GEBA KAREN I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1071,
+ },
+ [0x1072]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN KAYAH OE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1072,
+ },
+ [0x1073]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN KAYAH U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1073,
+ },
+ [0x1074]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN KAYAH EE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1074,
+ },
+ [0x1075]={
+ category="lo",
+ description="MYANMAR LETTER SHAN KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1075,
+ },
+ [0x1076]={
+ category="lo",
+ description="MYANMAR LETTER SHAN KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1076,
+ },
+ [0x1077]={
+ category="lo",
+ description="MYANMAR LETTER SHAN GA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1077,
+ },
+ [0x1078]={
+ category="lo",
+ description="MYANMAR LETTER SHAN CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1078,
+ },
+ [0x1079]={
+ category="lo",
+ description="MYANMAR LETTER SHAN ZA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1079,
+ },
+ [0x107A]={
+ category="lo",
+ description="MYANMAR LETTER SHAN NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107A,
+ },
+ [0x107B]={
+ category="lo",
+ description="MYANMAR LETTER SHAN DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107B,
+ },
+ [0x107C]={
+ category="lo",
+ description="MYANMAR LETTER SHAN NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107C,
+ },
+ [0x107D]={
+ category="lo",
+ description="MYANMAR LETTER SHAN PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107D,
+ },
+ [0x107E]={
+ category="lo",
+ description="MYANMAR LETTER SHAN FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107E,
+ },
+ [0x107F]={
+ category="lo",
+ description="MYANMAR LETTER SHAN BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x107F,
+ },
+ [0x1080]={
+ category="lo",
+ description="MYANMAR LETTER SHAN THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1080,
+ },
+ [0x1081]={
+ category="lo",
+ description="MYANMAR LETTER SHAN HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1081,
+ },
+ [0x1082]={
+ category="mn",
+ description="MYANMAR CONSONANT SIGN SHAN MEDIAL WA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1082,
+ },
+ [0x1083]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN SHAN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1083,
+ },
+ [0x1084]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN SHAN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1084,
+ },
+ [0x1085]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN SHAN E ABOVE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1085,
+ },
+ [0x1086]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN SHAN FINAL Y",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1086,
+ },
+ [0x1087]={
+ category="mc",
+ description="MYANMAR SIGN SHAN TONE-2",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1087,
+ },
+ [0x1088]={
+ category="mc",
+ description="MYANMAR SIGN SHAN TONE-3",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1088,
+ },
+ [0x1089]={
+ category="mc",
+ description="MYANMAR SIGN SHAN TONE-5",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1089,
+ },
+ [0x108A]={
+ category="mc",
+ description="MYANMAR SIGN SHAN TONE-6",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108A,
+ },
+ [0x108B]={
+ category="mc",
+ description="MYANMAR SIGN SHAN COUNCIL TONE-2",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108B,
+ },
+ [0x108C]={
+ category="mc",
+ description="MYANMAR SIGN SHAN COUNCIL TONE-3",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108C,
+ },
+ [0x108D]={
+ category="mn",
+ description="MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x108D,
+ },
+ [0x108E]={
+ category="lo",
+ description="MYANMAR LETTER RUMAI PALAUNG FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108E,
+ },
+ [0x108F]={
+ category="mc",
+ description="MYANMAR SIGN RUMAI PALAUNG TONE-5",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x108F,
+ },
+ [0x1090]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1090,
+ },
+ [0x1091]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1091,
+ },
+ [0x1092]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1092,
+ },
+ [0x1093]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1093,
+ },
+ [0x1094]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1094,
+ },
+ [0x1095]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1095,
+ },
+ [0x1096]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1096,
+ },
+ [0x1097]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1097,
+ },
+ [0x1098]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1098,
+ },
+ [0x1099]={
+ category="nd",
+ description="MYANMAR SHAN DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1099,
+ },
+ [0x109A]={
+ category="mc",
+ description="MYANMAR SIGN KHAMTI TONE-1",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109A,
+ },
+ [0x109B]={
+ category="mc",
+ description="MYANMAR SIGN KHAMTI TONE-3",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109B,
+ },
+ [0x109C]={
+ category="mc",
+ description="MYANMAR VOWEL SIGN AITON A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109C,
+ },
+ [0x109D]={
+ category="mn",
+ description="MYANMAR VOWEL SIGN AITON AI",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x109D,
+ },
+ [0x109E]={
+ category="so",
+ description="MYANMAR SYMBOL SHAN ONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109E,
+ },
+ [0x109F]={
+ category="so",
+ description="MYANMAR SYMBOL SHAN EXCLAMATION",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x109F,
+ },
[0x10A0]={
category="lu",
description="GEORGIAN CAPITAL LETTER AN",
@@ -28719,6 +30928,46 @@ characters.data={
linebreak="jl",
unicodeslot=0x1159,
},
+ [0x115A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG KIYEOK-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115A,
+ },
+ [0x115B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115B,
+ },
+ [0x115C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115C,
+ },
+ [0x115D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG NIEUN-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115D,
+ },
+ [0x115E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-RIEUL",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0x115E,
+ },
[0x115F]={
category="lo",
cjkwd="w",
@@ -29196,6 +31445,46 @@ characters.data={
linebreak="jv",
unicodeslot=0x11A2,
},
+ [0x11A3]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG A-EU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A3,
+ },
+ [0x11A4]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG YA-U",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A4,
+ },
+ [0x11A5]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG YEO-YA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A5,
+ },
+ [0x11A6]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG O-YA",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A6,
+ },
+ [0x11A7]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG O-YAE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0x11A7,
+ },
[0x11A8]={
category="lo",
description="HANGUL JONGSEONG KIYEOK",
@@ -29770,6 +32059,54 @@ characters.data={
linebreak="jt",
unicodeslot=0x11F9,
},
+ [0x11FA]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG KIYEOK-NIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FA,
+ },
+ [0x11FB]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG KIYEOK-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FB,
+ },
+ [0x11FC]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG KIYEOK-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FC,
+ },
+ [0x11FD]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG KIYEOK-KHIEUKH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FD,
+ },
+ [0x11FE]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG KIYEOK-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FE,
+ },
+ [0x11FF]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGNIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0x11FF,
+ },
[0x1200]={
category="lo",
description="ETHIOPIC SYLLABLE HA",
@@ -32052,6 +34389,20 @@ characters.data={
linebreak="al",
unicodeslot=0x135A,
},
+ [0x135D]={
+ category="mn",
+ description="ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x135D,
+ },
+ [0x135E]={
+ category="mn",
+ description="ETHIOPIC COMBINING VOWEL LENGTH MARK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x135E,
+ },
[0x135F]={
category="mn",
description="ETHIOPIC COMBINING GEMINATION MARK",
@@ -33039,6 +35390,13 @@ characters.data={
linebreak="al",
unicodeslot=0x13F4,
},
+ [0x1400]={
+ category="pd",
+ description="CANADIAN SYLLABICS HYPHEN",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x1400,
+ },
[0x1401]={
category="lo",
description="CANADIAN SYLLABICS E",
@@ -37449,6 +39807,69 @@ characters.data={
linebreak="al",
unicodeslot=0x1676,
},
+ [0x1677]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1677,
+ },
+ [0x1678]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1678,
+ },
+ [0x1679]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1679,
+ },
+ [0x167A]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167A,
+ },
+ [0x167B]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167B,
+ },
+ [0x167C]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167C,
+ },
+ [0x167D]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE THWAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167D,
+ },
+ [0x167E]={
+ category="lo",
+ description="CANADIAN SYLLABICS WOODS-CREE FINAL TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167E,
+ },
+ [0x167F]={
+ category="lo",
+ description="CANADIAN SYLLABICS BLACKFOOT W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x167F,
+ },
[0x1680]={
category="zs",
description="OGHAM SPACE MARK",
@@ -39604,14 +42025,14 @@ characters.data={
category="po",
description="MONGOLIAN COMMA",
direction="on",
- linebreak="ba",
+ linebreak="ex",
unicodeslot=0x1802,
},
[0x1803]={
category="po",
description="MONGOLIAN FULL STOP",
direction="on",
- linebreak="ba",
+ linebreak="ex",
unicodeslot=0x1803,
},
[0x1804]={
@@ -39646,14 +42067,14 @@ characters.data={
category="po",
description="MONGOLIAN MANCHU COMMA",
direction="on",
- linebreak="ba",
+ linebreak="ex",
unicodeslot=0x1808,
},
[0x1809]={
category="po",
description="MONGOLIAN MANCHU FULL STOP",
direction="on",
- linebreak="ba",
+ linebreak="ex",
unicodeslot=0x1809,
},
[0x180A]={
@@ -39767,6 +42188,10 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1820,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
},
[0x1821]={
category="lo",
@@ -39774,6 +42199,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1821,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1822]={
category="lo",
@@ -39781,6 +42209,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1822,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1823]={
category="lo",
@@ -39788,6 +42219,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1823,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1824]={
category="lo",
@@ -39795,6 +42229,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1824,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1825]={
category="lo",
@@ -39802,6 +42239,10 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1825,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
},
[0x1826]={
category="lo",
@@ -39809,6 +42250,10 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1826,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
},
[0x1827]={
category="lo",
@@ -39823,6 +42268,11 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1828,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="separate form",
+ },
},
[0x1829]={
category="lo",
@@ -39837,6 +42287,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x182A,
+ variants={
+ [0x180B]="alternative form",
+ },
},
[0x182B]={
category="lo",
@@ -39851,6 +42304,11 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x182C,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="fourth form",
+ },
},
[0x182D]={
category="lo",
@@ -39858,6 +42316,11 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x182D,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="feminine form",
+ },
},
[0x182E]={
category="lo",
@@ -39879,6 +42342,10 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1830,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
},
[0x1831]={
category="lo",
@@ -39893,6 +42360,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1832,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1833]={
category="lo",
@@ -39900,6 +42370,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1833,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1834]={
category="lo",
@@ -39914,6 +42387,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1835,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1836]={
category="lo",
@@ -39921,6 +42397,10 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1836,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
},
[0x1837]={
category="lo",
@@ -39935,6 +42415,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1838,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1839]={
category="lo",
@@ -40019,6 +42502,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1844,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1845]={
category="lo",
@@ -40026,6 +42512,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1845,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1846]={
category="lo",
@@ -40033,6 +42522,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1846,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1847]={
category="lo",
@@ -40040,6 +42532,10 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1847,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
},
[0x1848]={
category="lo",
@@ -40047,6 +42543,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1848,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1849]={
category="lo",
@@ -40054,6 +42553,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1849,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x184A]={
category="lo",
@@ -40082,6 +42584,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x184D,
+ variants={
+ [0x180B]="feminine form",
+ },
},
[0x184E]={
category="lo",
@@ -40089,6 +42594,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x184E,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x184F]={
category="lo",
@@ -40194,6 +42702,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x185D,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x185E]={
category="lo",
@@ -40201,6 +42712,10 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x185E,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
},
[0x185F]={
category="lo",
@@ -40215,6 +42730,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1860,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1861]={
category="lo",
@@ -40236,6 +42754,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1863,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1864]={
category="lo",
@@ -40271,6 +42792,10 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1868,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ },
},
[0x1869]={
category="lo",
@@ -40278,6 +42803,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1869,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x186A]={
category="lo",
@@ -40320,6 +42848,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x186F,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1870]={
category="lo",
@@ -40348,6 +42879,11 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1873,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="fourth form",
+ },
},
[0x1874]={
category="lo",
@@ -40355,6 +42891,11 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1874,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="feminine first medial form",
+ [0x180D]="feminine second medial form",
+ },
},
[0x1875]={
category="lo",
@@ -40369,6 +42910,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1876,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1877]={
category="lo",
@@ -40383,6 +42927,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1880,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1881]={
category="lo",
@@ -40390,6 +42937,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1881,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1882]={
category="lo",
@@ -40432,6 +42982,11 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1887,
+ variants={
+ [0x180B]="second form",
+ [0x180C]="third form",
+ [0x180D]="fourth form",
+ },
},
[0x1888]={
category="lo",
@@ -40439,6 +42994,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x1888,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x1889]={
category="lo",
@@ -40453,6 +43011,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0x188A,
+ variants={
+ [0x180B]="second form",
+ },
},
[0x188B]={
category="lo",
@@ -40671,6 +43232,503 @@ characters.data={
linebreak="cm",
unicodeslot=0x18A9,
},
+ [0x18AA]={
+ category="lo",
+ description="MONGOLIAN LETTER MANCHU ALI GALI LHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18AA,
+ },
+ [0x18B0]={
+ category="lo",
+ description="CANADIAN SYLLABICS OY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B0,
+ },
+ [0x18B1]={
+ category="lo",
+ description="CANADIAN SYLLABICS AY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B1,
+ },
+ [0x18B2]={
+ category="lo",
+ description="CANADIAN SYLLABICS AAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B2,
+ },
+ [0x18B3]={
+ category="lo",
+ description="CANADIAN SYLLABICS WAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B3,
+ },
+ [0x18B4]={
+ category="lo",
+ description="CANADIAN SYLLABICS POY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B4,
+ },
+ [0x18B5]={
+ category="lo",
+ description="CANADIAN SYLLABICS PAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B5,
+ },
+ [0x18B6]={
+ category="lo",
+ description="CANADIAN SYLLABICS PWOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B6,
+ },
+ [0x18B7]={
+ category="lo",
+ description="CANADIAN SYLLABICS TAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B7,
+ },
+ [0x18B8]={
+ category="lo",
+ description="CANADIAN SYLLABICS KAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B8,
+ },
+ [0x18B9]={
+ category="lo",
+ description="CANADIAN SYLLABICS KWAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18B9,
+ },
+ [0x18BA]={
+ category="lo",
+ description="CANADIAN SYLLABICS MAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BA,
+ },
+ [0x18BB]={
+ category="lo",
+ description="CANADIAN SYLLABICS NOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BB,
+ },
+ [0x18BC]={
+ category="lo",
+ description="CANADIAN SYLLABICS NAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BC,
+ },
+ [0x18BD]={
+ category="lo",
+ description="CANADIAN SYLLABICS LAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BD,
+ },
+ [0x18BE]={
+ category="lo",
+ description="CANADIAN SYLLABICS SOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BE,
+ },
+ [0x18BF]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18BF,
+ },
+ [0x18C0]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C0,
+ },
+ [0x18C1]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C1,
+ },
+ [0x18C2]={
+ category="lo",
+ description="CANADIAN SYLLABICS SHWOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C2,
+ },
+ [0x18C3]={
+ category="lo",
+ description="CANADIAN SYLLABICS YOY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C3,
+ },
+ [0x18C4]={
+ category="lo",
+ description="CANADIAN SYLLABICS YAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C4,
+ },
+ [0x18C5]={
+ category="lo",
+ description="CANADIAN SYLLABICS RAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C5,
+ },
+ [0x18C6]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C6,
+ },
+ [0x18C7]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY NWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C7,
+ },
+ [0x18C8]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C8,
+ },
+ [0x18C9]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY NWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18C9,
+ },
+ [0x18CA]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CA,
+ },
+ [0x18CB]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY NWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CB,
+ },
+ [0x18CC]={
+ category="lo",
+ description="CANADIAN SYLLABICS NWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CC,
+ },
+ [0x18CD]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY NWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CD,
+ },
+ [0x18CE]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CE,
+ },
+ [0x18CF]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18CF,
+ },
+ [0x18D0]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D0,
+ },
+ [0x18D1]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D1,
+ },
+ [0x18D2]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D2,
+ },
+ [0x18D3]={
+ category="lo",
+ description="CANADIAN SYLLABICS RWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D3,
+ },
+ [0x18D4]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D4,
+ },
+ [0x18D5]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D5,
+ },
+ [0x18D6]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D6,
+ },
+ [0x18D7]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D7,
+ },
+ [0x18D8]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D8,
+ },
+ [0x18D9]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18D9,
+ },
+ [0x18DA]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DA,
+ },
+ [0x18DB]={
+ category="lo",
+ description="CANADIAN SYLLABICS OJIBWAY SH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DB,
+ },
+ [0x18DC]={
+ category="lo",
+ description="CANADIAN SYLLABICS EASTERN W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DC,
+ },
+ [0x18DD]={
+ category="lo",
+ description="CANADIAN SYLLABICS WESTERN W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DD,
+ },
+ [0x18DE]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL SMALL RING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DE,
+ },
+ [0x18DF]={
+ category="lo",
+ description="CANADIAN SYLLABICS FINAL RAISED DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18DF,
+ },
+ [0x18E0]={
+ category="lo",
+ description="CANADIAN SYLLABICS R-CREE RWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E0,
+ },
+ [0x18E1]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E1,
+ },
+ [0x18E2]={
+ category="lo",
+ description="CANADIAN SYLLABICS WEST-CREE LAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E2,
+ },
+ [0x18E3]={
+ category="lo",
+ description="CANADIAN SYLLABICS THWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E3,
+ },
+ [0x18E4]={
+ category="lo",
+ description="CANADIAN SYLLABICS THWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E4,
+ },
+ [0x18E5]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E5,
+ },
+ [0x18E6]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E6,
+ },
+ [0x18E7]={
+ category="lo",
+ description="CANADIAN SYLLABICS TTHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E7,
+ },
+ [0x18E8]={
+ category="lo",
+ description="CANADIAN SYLLABICS TLHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E8,
+ },
+ [0x18E9]={
+ category="lo",
+ description="CANADIAN SYLLABICS TLHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18E9,
+ },
+ [0x18EA]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI SHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EA,
+ },
+ [0x18EB]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI SHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EB,
+ },
+ [0x18EC]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI HOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EC,
+ },
+ [0x18ED]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GWU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18ED,
+ },
+ [0x18EE]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DENE GEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EE,
+ },
+ [0x18EF]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18EF,
+ },
+ [0x18F0]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER GWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F0,
+ },
+ [0x18F1]={
+ category="lo",
+ description="CANADIAN SYLLABICS SAYISI JUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F1,
+ },
+ [0x18F2]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER JWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F2,
+ },
+ [0x18F3]={
+ category="lo",
+ description="CANADIAN SYLLABICS BEAVER DENE L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F3,
+ },
+ [0x18F4]={
+ category="lo",
+ description="CANADIAN SYLLABICS BEAVER DENE R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F4,
+ },
+ [0x18F5]={
+ category="lo",
+ description="CANADIAN SYLLABICS CARRIER DENTAL S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x18F5,
+ },
[0x1900]={
category="lo",
description="LIMBU VOWEL-CARRIER LETTER",
@@ -41672,6 +44730,20 @@ characters.data={
linebreak="sa",
unicodeslot=0x19A9,
},
+ [0x19AA]={
+ category="lo",
+ description="NEW TAI LUE LETTER HIGH SUA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19AA,
+ },
+ [0x19AB]={
+ category="lo",
+ description="NEW TAI LUE LETTER LOW SUA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19AB,
+ },
[0x19B0]={
category="mc",
description="NEW TAI LUE VOWEL SIGN VOWEL SHORTENER",
@@ -41924,6 +44996,13 @@ characters.data={
linebreak="nu",
unicodeslot=0x19D9,
},
+ [0x19DA]={
+ category="no",
+ description="NEW TAI LUE THAM DIGIT ONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x19DA,
+ },
[0x19DE]={
category="po",
description="NEW TAI LUE SIGN LAE",
@@ -42362,7 +45441,7 @@ characters.data={
category="po",
description="BUGINESE PALLAWA",
direction="l",
- linebreak="ba",
+ linebreak="al",
unicodeslot=0x1A1E,
},
[0x1A1F]={
@@ -42372,6 +45451,895 @@ characters.data={
linebreak="al",
unicodeslot=0x1A1F,
},
+ [0x1A20]={
+ category="lo",
+ description="TAI THAM LETTER HIGH KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A20,
+ },
+ [0x1A21]={
+ category="lo",
+ description="TAI THAM LETTER HIGH KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A21,
+ },
+ [0x1A22]={
+ category="lo",
+ description="TAI THAM LETTER HIGH KXA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A22,
+ },
+ [0x1A23]={
+ category="lo",
+ description="TAI THAM LETTER LOW KA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A23,
+ },
+ [0x1A24]={
+ category="lo",
+ description="TAI THAM LETTER LOW KXA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A24,
+ },
+ [0x1A25]={
+ category="lo",
+ description="TAI THAM LETTER LOW KHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A25,
+ },
+ [0x1A26]={
+ category="lo",
+ description="TAI THAM LETTER NGA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A26,
+ },
+ [0x1A27]={
+ category="lo",
+ description="TAI THAM LETTER HIGH CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A27,
+ },
+ [0x1A28]={
+ category="lo",
+ description="TAI THAM LETTER HIGH CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A28,
+ },
+ [0x1A29]={
+ category="lo",
+ description="TAI THAM LETTER LOW CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A29,
+ },
+ [0x1A2A]={
+ category="lo",
+ description="TAI THAM LETTER LOW SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2A,
+ },
+ [0x1A2B]={
+ category="lo",
+ description="TAI THAM LETTER LOW CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2B,
+ },
+ [0x1A2C]={
+ category="lo",
+ description="TAI THAM LETTER NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2C,
+ },
+ [0x1A2D]={
+ category="lo",
+ description="TAI THAM LETTER RATA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2D,
+ },
+ [0x1A2E]={
+ category="lo",
+ description="TAI THAM LETTER HIGH RATHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2E,
+ },
+ [0x1A2F]={
+ category="lo",
+ description="TAI THAM LETTER DA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A2F,
+ },
+ [0x1A30]={
+ category="lo",
+ description="TAI THAM LETTER LOW RATHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A30,
+ },
+ [0x1A31]={
+ category="lo",
+ description="TAI THAM LETTER RANA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A31,
+ },
+ [0x1A32]={
+ category="lo",
+ description="TAI THAM LETTER HIGH TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A32,
+ },
+ [0x1A33]={
+ category="lo",
+ description="TAI THAM LETTER HIGH THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A33,
+ },
+ [0x1A34]={
+ category="lo",
+ description="TAI THAM LETTER LOW TA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A34,
+ },
+ [0x1A35]={
+ category="lo",
+ description="TAI THAM LETTER LOW THA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A35,
+ },
+ [0x1A36]={
+ category="lo",
+ description="TAI THAM LETTER NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A36,
+ },
+ [0x1A37]={
+ category="lo",
+ description="TAI THAM LETTER BA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A37,
+ },
+ [0x1A38]={
+ category="lo",
+ description="TAI THAM LETTER HIGH PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A38,
+ },
+ [0x1A39]={
+ category="lo",
+ description="TAI THAM LETTER HIGH PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A39,
+ },
+ [0x1A3A]={
+ category="lo",
+ description="TAI THAM LETTER HIGH FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3A,
+ },
+ [0x1A3B]={
+ category="lo",
+ description="TAI THAM LETTER LOW PA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3B,
+ },
+ [0x1A3C]={
+ category="lo",
+ description="TAI THAM LETTER LOW FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3C,
+ },
+ [0x1A3D]={
+ category="lo",
+ description="TAI THAM LETTER LOW PHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3D,
+ },
+ [0x1A3E]={
+ category="lo",
+ description="TAI THAM LETTER MA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3E,
+ },
+ [0x1A3F]={
+ category="lo",
+ description="TAI THAM LETTER LOW YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A3F,
+ },
+ [0x1A40]={
+ category="lo",
+ description="TAI THAM LETTER HIGH YA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A40,
+ },
+ [0x1A41]={
+ category="lo",
+ description="TAI THAM LETTER RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A41,
+ },
+ [0x1A42]={
+ category="lo",
+ description="TAI THAM LETTER RUE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A42,
+ },
+ [0x1A43]={
+ category="lo",
+ description="TAI THAM LETTER LA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A43,
+ },
+ [0x1A44]={
+ category="lo",
+ description="TAI THAM LETTER LUE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A44,
+ },
+ [0x1A45]={
+ category="lo",
+ description="TAI THAM LETTER WA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A45,
+ },
+ [0x1A46]={
+ category="lo",
+ description="TAI THAM LETTER HIGH SHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A46,
+ },
+ [0x1A47]={
+ category="lo",
+ description="TAI THAM LETTER HIGH SSA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A47,
+ },
+ [0x1A48]={
+ category="lo",
+ description="TAI THAM LETTER HIGH SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A48,
+ },
+ [0x1A49]={
+ category="lo",
+ description="TAI THAM LETTER HIGH HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A49,
+ },
+ [0x1A4A]={
+ category="lo",
+ description="TAI THAM LETTER LLA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4A,
+ },
+ [0x1A4B]={
+ category="lo",
+ description="TAI THAM LETTER A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4B,
+ },
+ [0x1A4C]={
+ category="lo",
+ description="TAI THAM LETTER LOW HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4C,
+ },
+ [0x1A4D]={
+ category="lo",
+ description="TAI THAM LETTER I",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4D,
+ },
+ [0x1A4E]={
+ category="lo",
+ description="TAI THAM LETTER II",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4E,
+ },
+ [0x1A4F]={
+ category="lo",
+ description="TAI THAM LETTER U",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A4F,
+ },
+ [0x1A50]={
+ category="lo",
+ description="TAI THAM LETTER UU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A50,
+ },
+ [0x1A51]={
+ category="lo",
+ description="TAI THAM LETTER EE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A51,
+ },
+ [0x1A52]={
+ category="lo",
+ description="TAI THAM LETTER OO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A52,
+ },
+ [0x1A53]={
+ category="lo",
+ description="TAI THAM LETTER LAE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A53,
+ },
+ [0x1A54]={
+ category="lo",
+ description="TAI THAM LETTER GREAT SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A54,
+ },
+ [0x1A55]={
+ category="mc",
+ description="TAI THAM CONSONANT SIGN MEDIAL RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A55,
+ },
+ [0x1A56]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN MEDIAL LA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A56,
+ },
+ [0x1A57]={
+ category="mc",
+ description="TAI THAM CONSONANT SIGN LA TANG LAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A57,
+ },
+ [0x1A58]={
+ category="mn",
+ description="TAI THAM SIGN MAI KANG LAI",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A58,
+ },
+ [0x1A59]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN FINAL NGA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A59,
+ },
+ [0x1A5A]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN LOW PA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5A,
+ },
+ [0x1A5B]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN HIGH RATHA OR LOW PA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5B,
+ },
+ [0x1A5C]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN MA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5C,
+ },
+ [0x1A5D]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN BA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5D,
+ },
+ [0x1A5E]={
+ category="mn",
+ description="TAI THAM CONSONANT SIGN SA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A5E,
+ },
+ [0x1A60]={
+ category="mn",
+ description="TAI THAM SIGN SAKOT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A60,
+ },
+ [0x1A61]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN A",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A61,
+ },
+ [0x1A62]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN MAI SAT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A62,
+ },
+ [0x1A63]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A63,
+ },
+ [0x1A64]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN TALL AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A64,
+ },
+ [0x1A65]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A65,
+ },
+ [0x1A66]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN II",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A66,
+ },
+ [0x1A67]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN UE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A67,
+ },
+ [0x1A68]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN UUE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A68,
+ },
+ [0x1A69]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A69,
+ },
+ [0x1A6A]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A6A,
+ },
+ [0x1A6B]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN O",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A6B,
+ },
+ [0x1A6C]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN OA BELOW",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A6C,
+ },
+ [0x1A6D]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN OY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A6D,
+ },
+ [0x1A6E]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A6E,
+ },
+ [0x1A6F]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN AE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A6F,
+ },
+ [0x1A70]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN OO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A70,
+ },
+ [0x1A71]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN AI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A71,
+ },
+ [0x1A72]={
+ category="mc",
+ description="TAI THAM VOWEL SIGN THAM AI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1A72,
+ },
+ [0x1A73]={
+ category="mn",
+ description="TAI THAM VOWEL SIGN OA ABOVE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A73,
+ },
+ [0x1A74]={
+ category="mn",
+ description="TAI THAM SIGN MAI KANG",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A74,
+ },
+ [0x1A75]={
+ category="mn",
+ description="TAI THAM SIGN TONE-1",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A75,
+ },
+ [0x1A76]={
+ category="mn",
+ description="TAI THAM SIGN TONE-2",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A76,
+ },
+ [0x1A77]={
+ category="mn",
+ description="TAI THAM SIGN KHUEN TONE-3",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A77,
+ },
+ [0x1A78]={
+ category="mn",
+ description="TAI THAM SIGN KHUEN TONE-4",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A78,
+ },
+ [0x1A79]={
+ category="mn",
+ description="TAI THAM SIGN KHUEN TONE-5",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A79,
+ },
+ [0x1A7A]={
+ category="mn",
+ description="TAI THAM SIGN RA HAAM",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A7A,
+ },
+ [0x1A7B]={
+ category="mn",
+ description="TAI THAM SIGN MAI SAM",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A7B,
+ },
+ [0x1A7C]={
+ category="mn",
+ description="TAI THAM SIGN KHUEN-LUE KARAN",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0x1A7C,
+ },
+ [0x1A7F]={
+ category="mn",
+ description="TAI THAM COMBINING CRYPTOGRAMMIC DOT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1A7F,
+ },
+ [0x1A80]={
+ category="nd",
+ description="TAI THAM HORA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A80,
+ },
+ [0x1A81]={
+ category="nd",
+ description="TAI THAM HORA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A81,
+ },
+ [0x1A82]={
+ category="nd",
+ description="TAI THAM HORA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A82,
+ },
+ [0x1A83]={
+ category="nd",
+ description="TAI THAM HORA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A83,
+ },
+ [0x1A84]={
+ category="nd",
+ description="TAI THAM HORA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A84,
+ },
+ [0x1A85]={
+ category="nd",
+ description="TAI THAM HORA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A85,
+ },
+ [0x1A86]={
+ category="nd",
+ description="TAI THAM HORA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A86,
+ },
+ [0x1A87]={
+ category="nd",
+ description="TAI THAM HORA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A87,
+ },
+ [0x1A88]={
+ category="nd",
+ description="TAI THAM HORA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A88,
+ },
+ [0x1A89]={
+ category="nd",
+ description="TAI THAM HORA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A89,
+ },
+ [0x1A90]={
+ category="nd",
+ description="TAI THAM THAM DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A90,
+ },
+ [0x1A91]={
+ category="nd",
+ description="TAI THAM THAM DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A91,
+ },
+ [0x1A92]={
+ category="nd",
+ description="TAI THAM THAM DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A92,
+ },
+ [0x1A93]={
+ category="nd",
+ description="TAI THAM THAM DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A93,
+ },
+ [0x1A94]={
+ category="nd",
+ description="TAI THAM THAM DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A94,
+ },
+ [0x1A95]={
+ category="nd",
+ description="TAI THAM THAM DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A95,
+ },
+ [0x1A96]={
+ category="nd",
+ description="TAI THAM THAM DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A96,
+ },
+ [0x1A97]={
+ category="nd",
+ description="TAI THAM THAM DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A97,
+ },
+ [0x1A98]={
+ category="nd",
+ description="TAI THAM THAM DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A98,
+ },
+ [0x1A99]={
+ category="nd",
+ description="TAI THAM THAM DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1A99,
+ },
+ [0x1AA0]={
+ category="po",
+ description="TAI THAM SIGN WIANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA0,
+ },
+ [0x1AA1]={
+ category="po",
+ description="TAI THAM SIGN WIANGWAAK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA1,
+ },
+ [0x1AA2]={
+ category="po",
+ description="TAI THAM SIGN SAWAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA2,
+ },
+ [0x1AA3]={
+ category="po",
+ description="TAI THAM SIGN KEOW",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA3,
+ },
+ [0x1AA4]={
+ category="po",
+ description="TAI THAM SIGN HOY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA4,
+ },
+ [0x1AA5]={
+ category="po",
+ description="TAI THAM SIGN DOKMAI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA5,
+ },
+ [0x1AA6]={
+ category="po",
+ description="TAI THAM SIGN REVERSED ROTATED RANA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA6,
+ },
+ [0x1AA7]={
+ category="lm",
+ description="TAI THAM SIGN MAI YAMOK",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA7,
+ },
+ [0x1AA8]={
+ category="po",
+ description="TAI THAM SIGN KAAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA8,
+ },
+ [0x1AA9]={
+ category="po",
+ description="TAI THAM SIGN KAANKUU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AA9,
+ },
+ [0x1AAA]={
+ category="po",
+ description="TAI THAM SIGN SATKAAN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AAA,
+ },
+ [0x1AAB]={
+ category="po",
+ description="TAI THAM SIGN SATKAANKUU",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AAB,
+ },
+ [0x1AAC]={
+ category="po",
+ description="TAI THAM SIGN HANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AAC,
+ },
+ [0x1AAD]={
+ category="po",
+ description="TAI THAM SIGN CAANG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0x1AAD,
+ },
[0x1B00]={
category="mn",
description="BALINESE SIGN ULU RICEM",
@@ -43003,7 +46971,7 @@ characters.data={
category="po",
description="BALINESE WINDU",
direction="l",
- linebreak="ba",
+ linebreak="al",
unicodeslot=0x1B5C,
},
[0x1B5D]={
@@ -43230,6 +47198,1882 @@ characters.data={
linebreak="al",
unicodeslot=0x1B7C,
},
+ [0x1B80]={
+ category="mn",
+ description="SUNDANESE SIGN PANYECEK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B80,
+ },
+ [0x1B81]={
+ category="mn",
+ description="SUNDANESE SIGN PANGLAYAR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1B81,
+ },
+ [0x1B82]={
+ category="mc",
+ description="SUNDANESE SIGN PANGWISAD",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1B82,
+ },
+ [0x1B83]={
+ category="lo",
+ description="SUNDANESE LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B83,
+ },
+ [0x1B84]={
+ category="lo",
+ description="SUNDANESE LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B84,
+ },
+ [0x1B85]={
+ category="lo",
+ description="SUNDANESE LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B85,
+ },
+ [0x1B86]={
+ category="lo",
+ description="SUNDANESE LETTER AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B86,
+ },
+ [0x1B87]={
+ category="lo",
+ description="SUNDANESE LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B87,
+ },
+ [0x1B88]={
+ category="lo",
+ description="SUNDANESE LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B88,
+ },
+ [0x1B89]={
+ category="lo",
+ description="SUNDANESE LETTER EU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B89,
+ },
+ [0x1B8A]={
+ category="lo",
+ description="SUNDANESE LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8A,
+ },
+ [0x1B8B]={
+ category="lo",
+ description="SUNDANESE LETTER QA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8B,
+ },
+ [0x1B8C]={
+ category="lo",
+ description="SUNDANESE LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8C,
+ },
+ [0x1B8D]={
+ category="lo",
+ description="SUNDANESE LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8D,
+ },
+ [0x1B8E]={
+ category="lo",
+ description="SUNDANESE LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8E,
+ },
+ [0x1B8F]={
+ category="lo",
+ description="SUNDANESE LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B8F,
+ },
+ [0x1B90]={
+ category="lo",
+ description="SUNDANESE LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B90,
+ },
+ [0x1B91]={
+ category="lo",
+ description="SUNDANESE LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B91,
+ },
+ [0x1B92]={
+ category="lo",
+ description="SUNDANESE LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B92,
+ },
+ [0x1B93]={
+ category="lo",
+ description="SUNDANESE LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B93,
+ },
+ [0x1B94]={
+ category="lo",
+ description="SUNDANESE LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B94,
+ },
+ [0x1B95]={
+ category="lo",
+ description="SUNDANESE LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B95,
+ },
+ [0x1B96]={
+ category="lo",
+ description="SUNDANESE LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B96,
+ },
+ [0x1B97]={
+ category="lo",
+ description="SUNDANESE LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B97,
+ },
+ [0x1B98]={
+ category="lo",
+ description="SUNDANESE LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B98,
+ },
+ [0x1B99]={
+ category="lo",
+ description="SUNDANESE LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B99,
+ },
+ [0x1B9A]={
+ category="lo",
+ description="SUNDANESE LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9A,
+ },
+ [0x1B9B]={
+ category="lo",
+ description="SUNDANESE LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9B,
+ },
+ [0x1B9C]={
+ category="lo",
+ description="SUNDANESE LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9C,
+ },
+ [0x1B9D]={
+ category="lo",
+ description="SUNDANESE LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9D,
+ },
+ [0x1B9E]={
+ category="lo",
+ description="SUNDANESE LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9E,
+ },
+ [0x1B9F]={
+ category="lo",
+ description="SUNDANESE LETTER XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1B9F,
+ },
+ [0x1BA0]={
+ category="lo",
+ description="SUNDANESE LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BA0,
+ },
+ [0x1BA1]={
+ category="mc",
+ description="SUNDANESE CONSONANT SIGN PAMINGKAL",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BA1,
+ },
+ [0x1BA2]={
+ category="mn",
+ description="SUNDANESE CONSONANT SIGN PANYAKRA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA2,
+ },
+ [0x1BA3]={
+ category="mn",
+ description="SUNDANESE CONSONANT SIGN PANYIKU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA3,
+ },
+ [0x1BA4]={
+ category="mn",
+ description="SUNDANESE VOWEL SIGN PANGHULU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA4,
+ },
+ [0x1BA5]={
+ category="mn",
+ description="SUNDANESE VOWEL SIGN PANYUKU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA5,
+ },
+ [0x1BA6]={
+ category="mc",
+ description="SUNDANESE VOWEL SIGN PANAELAENG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BA6,
+ },
+ [0x1BA7]={
+ category="mc",
+ description="SUNDANESE VOWEL SIGN PANOLONG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BA7,
+ },
+ [0x1BA8]={
+ category="mn",
+ description="SUNDANESE VOWEL SIGN PAMEPET",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA8,
+ },
+ [0x1BA9]={
+ category="mn",
+ description="SUNDANESE VOWEL SIGN PANEULEUNG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BA9,
+ },
+ [0x1BAA]={
+ category="mc",
+ description="SUNDANESE SIGN PAMAAEH",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BAA,
+ },
+ [0x1BAE]={
+ category="lo",
+ description="SUNDANESE LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BAE,
+ },
+ [0x1BAF]={
+ category="lo",
+ description="SUNDANESE LETTER SYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BAF,
+ },
+ [0x1BB0]={
+ category="nd",
+ description="SUNDANESE DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB0,
+ },
+ [0x1BB1]={
+ category="nd",
+ description="SUNDANESE DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB1,
+ },
+ [0x1BB2]={
+ category="nd",
+ description="SUNDANESE DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB2,
+ },
+ [0x1BB3]={
+ category="nd",
+ description="SUNDANESE DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB3,
+ },
+ [0x1BB4]={
+ category="nd",
+ description="SUNDANESE DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB4,
+ },
+ [0x1BB5]={
+ category="nd",
+ description="SUNDANESE DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB5,
+ },
+ [0x1BB6]={
+ category="nd",
+ description="SUNDANESE DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB6,
+ },
+ [0x1BB7]={
+ category="nd",
+ description="SUNDANESE DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB7,
+ },
+ [0x1BB8]={
+ category="nd",
+ description="SUNDANESE DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB8,
+ },
+ [0x1BB9]={
+ category="nd",
+ description="SUNDANESE DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1BB9,
+ },
+ [0x1BC0]={
+ category="lo",
+ description="BATAK LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC0,
+ },
+ [0x1BC1]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC1,
+ },
+ [0x1BC2]={
+ category="lo",
+ description="BATAK LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC2,
+ },
+ [0x1BC3]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC3,
+ },
+ [0x1BC4]={
+ category="lo",
+ description="BATAK LETTER MANDAILING HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC4,
+ },
+ [0x1BC5]={
+ category="lo",
+ description="BATAK LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC5,
+ },
+ [0x1BC6]={
+ category="lo",
+ description="BATAK LETTER KARO BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC6,
+ },
+ [0x1BC7]={
+ category="lo",
+ description="BATAK LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC7,
+ },
+ [0x1BC8]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC8,
+ },
+ [0x1BC9]={
+ category="lo",
+ description="BATAK LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BC9,
+ },
+ [0x1BCA]={
+ category="lo",
+ description="BATAK LETTER MANDAILING NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCA,
+ },
+ [0x1BCB]={
+ category="lo",
+ description="BATAK LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCB,
+ },
+ [0x1BCC]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCC,
+ },
+ [0x1BCD]={
+ category="lo",
+ description="BATAK LETTER PAKPAK WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCD,
+ },
+ [0x1BCE]={
+ category="lo",
+ description="BATAK LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCE,
+ },
+ [0x1BCF]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BCF,
+ },
+ [0x1BD0]={
+ category="lo",
+ description="BATAK LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD0,
+ },
+ [0x1BD1]={
+ category="lo",
+ description="BATAK LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD1,
+ },
+ [0x1BD2]={
+ category="lo",
+ description="BATAK LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD2,
+ },
+ [0x1BD3]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD3,
+ },
+ [0x1BD4]={
+ category="lo",
+ description="BATAK LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD4,
+ },
+ [0x1BD5]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD5,
+ },
+ [0x1BD6]={
+ category="lo",
+ description="BATAK LETTER SOUTHERN TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD6,
+ },
+ [0x1BD7]={
+ category="lo",
+ description="BATAK LETTER NORTHERN TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD7,
+ },
+ [0x1BD8]={
+ category="lo",
+ description="BATAK LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD8,
+ },
+ [0x1BD9]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BD9,
+ },
+ [0x1BDA]={
+ category="lo",
+ description="BATAK LETTER MANDAILING SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDA,
+ },
+ [0x1BDB]={
+ category="lo",
+ description="BATAK LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDB,
+ },
+ [0x1BDC]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDC,
+ },
+ [0x1BDD]={
+ category="lo",
+ description="BATAK LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDD,
+ },
+ [0x1BDE]={
+ category="lo",
+ description="BATAK LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDE,
+ },
+ [0x1BDF]={
+ category="lo",
+ description="BATAK LETTER SIMALUNGUN LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BDF,
+ },
+ [0x1BE0]={
+ category="lo",
+ description="BATAK LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE0,
+ },
+ [0x1BE1]={
+ category="lo",
+ description="BATAK LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE1,
+ },
+ [0x1BE2]={
+ category="lo",
+ description="BATAK LETTER NDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE2,
+ },
+ [0x1BE3]={
+ category="lo",
+ description="BATAK LETTER MBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE3,
+ },
+ [0x1BE4]={
+ category="lo",
+ description="BATAK LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE4,
+ },
+ [0x1BE5]={
+ category="lo",
+ description="BATAK LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BE5,
+ },
+ [0x1BE6]={
+ category="mn",
+ description="BATAK SIGN TOMPI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BE6,
+ },
+ [0x1BE7]={
+ category="mc",
+ description="BATAK VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BE7,
+ },
+ [0x1BE8]={
+ category="mn",
+ description="BATAK VOWEL SIGN PAKPAK E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BE8,
+ },
+ [0x1BE9]={
+ category="mn",
+ description="BATAK VOWEL SIGN EE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BE9,
+ },
+ [0x1BEA]={
+ category="mc",
+ description="BATAK VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BEA,
+ },
+ [0x1BEB]={
+ category="mc",
+ description="BATAK VOWEL SIGN KARO I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BEB,
+ },
+ [0x1BEC]={
+ category="mc",
+ description="BATAK VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BEC,
+ },
+ [0x1BED]={
+ category="mn",
+ description="BATAK VOWEL SIGN KARO O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BED,
+ },
+ [0x1BEE]={
+ category="mc",
+ description="BATAK VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BEE,
+ },
+ [0x1BEF]={
+ category="mn",
+ description="BATAK VOWEL SIGN U FOR SIMALUNGUN SA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BEF,
+ },
+ [0x1BF0]={
+ category="mn",
+ description="BATAK CONSONANT SIGN NG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BF0,
+ },
+ [0x1BF1]={
+ category="mn",
+ description="BATAK CONSONANT SIGN H",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1BF1,
+ },
+ [0x1BF2]={
+ category="mc",
+ description="BATAK PANGOLAT",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BF2,
+ },
+ [0x1BF3]={
+ category="mc",
+ description="BATAK PANONGONAN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1BF3,
+ },
+ [0x1BFC]={
+ category="po",
+ description="BATAK SYMBOL BINDU NA METEK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BFC,
+ },
+ [0x1BFD]={
+ category="po",
+ description="BATAK SYMBOL BINDU PINARBORAS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BFD,
+ },
+ [0x1BFE]={
+ category="po",
+ description="BATAK SYMBOL BINDU JUDUL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BFE,
+ },
+ [0x1BFF]={
+ category="po",
+ description="BATAK SYMBOL BINDU PANGOLAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1BFF,
+ },
+ [0x1C00]={
+ category="lo",
+ description="LEPCHA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C00,
+ },
+ [0x1C01]={
+ category="lo",
+ description="LEPCHA LETTER KLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C01,
+ },
+ [0x1C02]={
+ category="lo",
+ description="LEPCHA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C02,
+ },
+ [0x1C03]={
+ category="lo",
+ description="LEPCHA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C03,
+ },
+ [0x1C04]={
+ category="lo",
+ description="LEPCHA LETTER GLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C04,
+ },
+ [0x1C05]={
+ category="lo",
+ description="LEPCHA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C05,
+ },
+ [0x1C06]={
+ category="lo",
+ description="LEPCHA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C06,
+ },
+ [0x1C07]={
+ category="lo",
+ description="LEPCHA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C07,
+ },
+ [0x1C08]={
+ category="lo",
+ description="LEPCHA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C08,
+ },
+ [0x1C09]={
+ category="lo",
+ description="LEPCHA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C09,
+ },
+ [0x1C0A]={
+ category="lo",
+ description="LEPCHA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0A,
+ },
+ [0x1C0B]={
+ category="lo",
+ description="LEPCHA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0B,
+ },
+ [0x1C0C]={
+ category="lo",
+ description="LEPCHA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0C,
+ },
+ [0x1C0D]={
+ category="lo",
+ description="LEPCHA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0D,
+ },
+ [0x1C0E]={
+ category="lo",
+ description="LEPCHA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0E,
+ },
+ [0x1C0F]={
+ category="lo",
+ description="LEPCHA LETTER PLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C0F,
+ },
+ [0x1C10]={
+ category="lo",
+ description="LEPCHA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C10,
+ },
+ [0x1C11]={
+ category="lo",
+ description="LEPCHA LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C11,
+ },
+ [0x1C12]={
+ category="lo",
+ description="LEPCHA LETTER FLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C12,
+ },
+ [0x1C13]={
+ category="lo",
+ description="LEPCHA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C13,
+ },
+ [0x1C14]={
+ category="lo",
+ description="LEPCHA LETTER BLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C14,
+ },
+ [0x1C15]={
+ category="lo",
+ description="LEPCHA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C15,
+ },
+ [0x1C16]={
+ category="lo",
+ description="LEPCHA LETTER MLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C16,
+ },
+ [0x1C17]={
+ category="lo",
+ description="LEPCHA LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C17,
+ },
+ [0x1C18]={
+ category="lo",
+ description="LEPCHA LETTER TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C18,
+ },
+ [0x1C19]={
+ category="lo",
+ description="LEPCHA LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C19,
+ },
+ [0x1C1A]={
+ category="lo",
+ description="LEPCHA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1A,
+ },
+ [0x1C1B]={
+ category="lo",
+ description="LEPCHA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1B,
+ },
+ [0x1C1C]={
+ category="lo",
+ description="LEPCHA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1C,
+ },
+ [0x1C1D]={
+ category="lo",
+ description="LEPCHA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1D,
+ },
+ [0x1C1E]={
+ category="lo",
+ description="LEPCHA LETTER HLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1E,
+ },
+ [0x1C1F]={
+ category="lo",
+ description="LEPCHA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C1F,
+ },
+ [0x1C20]={
+ category="lo",
+ description="LEPCHA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C20,
+ },
+ [0x1C21]={
+ category="lo",
+ description="LEPCHA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C21,
+ },
+ [0x1C22]={
+ category="lo",
+ description="LEPCHA LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C22,
+ },
+ [0x1C23]={
+ category="lo",
+ description="LEPCHA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C23,
+ },
+ [0x1C24]={
+ category="mc",
+ description="LEPCHA SUBJOINED LETTER YA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C24,
+ },
+ [0x1C25]={
+ category="mc",
+ description="LEPCHA SUBJOINED LETTER RA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C25,
+ },
+ [0x1C26]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C26,
+ },
+ [0x1C27]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C27,
+ },
+ [0x1C28]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C28,
+ },
+ [0x1C29]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C29,
+ },
+ [0x1C2A]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C2A,
+ },
+ [0x1C2B]={
+ category="mc",
+ description="LEPCHA VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C2B,
+ },
+ [0x1C2C]={
+ category="mn",
+ description="LEPCHA VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C2C,
+ },
+ [0x1C2D]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN K",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C2D,
+ },
+ [0x1C2E]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN M",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C2E,
+ },
+ [0x1C2F]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C2F,
+ },
+ [0x1C30]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN N",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C30,
+ },
+ [0x1C31]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN P",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C31,
+ },
+ [0x1C32]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C32,
+ },
+ [0x1C33]={
+ category="mn",
+ description="LEPCHA CONSONANT SIGN T",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C33,
+ },
+ [0x1C34]={
+ category="mc",
+ description="LEPCHA CONSONANT SIGN NYIN-DO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C34,
+ },
+ [0x1C35]={
+ category="mc",
+ description="LEPCHA CONSONANT SIGN KANG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1C35,
+ },
+ [0x1C36]={
+ category="mn",
+ description="LEPCHA SIGN RAN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C36,
+ },
+ [0x1C37]={
+ category="mn",
+ description="LEPCHA SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1C37,
+ },
+ [0x1C3B]={
+ category="po",
+ description="LEPCHA PUNCTUATION TA-ROL",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3B,
+ },
+ [0x1C3C]={
+ category="po",
+ description="LEPCHA PUNCTUATION NYET THYOOM TA-ROL",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3C,
+ },
+ [0x1C3D]={
+ category="po",
+ description="LEPCHA PUNCTUATION CER-WA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3D,
+ },
+ [0x1C3E]={
+ category="po",
+ description="LEPCHA PUNCTUATION TSHOOK CER-WA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3E,
+ },
+ [0x1C3F]={
+ category="po",
+ description="LEPCHA PUNCTUATION TSHOOK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C3F,
+ },
+ [0x1C40]={
+ category="nd",
+ description="LEPCHA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C40,
+ },
+ [0x1C41]={
+ category="nd",
+ description="LEPCHA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C41,
+ },
+ [0x1C42]={
+ category="nd",
+ description="LEPCHA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C42,
+ },
+ [0x1C43]={
+ category="nd",
+ description="LEPCHA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C43,
+ },
+ [0x1C44]={
+ category="nd",
+ description="LEPCHA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C44,
+ },
+ [0x1C45]={
+ category="nd",
+ description="LEPCHA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C45,
+ },
+ [0x1C46]={
+ category="nd",
+ description="LEPCHA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C46,
+ },
+ [0x1C47]={
+ category="nd",
+ description="LEPCHA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C47,
+ },
+ [0x1C48]={
+ category="nd",
+ description="LEPCHA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C48,
+ },
+ [0x1C49]={
+ category="nd",
+ description="LEPCHA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C49,
+ },
+ [0x1C4D]={
+ category="lo",
+ description="LEPCHA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C4D,
+ },
+ [0x1C4E]={
+ category="lo",
+ description="LEPCHA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C4E,
+ },
+ [0x1C4F]={
+ category="lo",
+ description="LEPCHA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C4F,
+ },
+ [0x1C50]={
+ category="nd",
+ description="OL CHIKI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C50,
+ },
+ [0x1C51]={
+ category="nd",
+ description="OL CHIKI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C51,
+ },
+ [0x1C52]={
+ category="nd",
+ description="OL CHIKI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C52,
+ },
+ [0x1C53]={
+ category="nd",
+ description="OL CHIKI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C53,
+ },
+ [0x1C54]={
+ category="nd",
+ description="OL CHIKI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C54,
+ },
+ [0x1C55]={
+ category="nd",
+ description="OL CHIKI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C55,
+ },
+ [0x1C56]={
+ category="nd",
+ description="OL CHIKI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C56,
+ },
+ [0x1C57]={
+ category="nd",
+ description="OL CHIKI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C57,
+ },
+ [0x1C58]={
+ category="nd",
+ description="OL CHIKI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C58,
+ },
+ [0x1C59]={
+ category="nd",
+ description="OL CHIKI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1C59,
+ },
+ [0x1C5A]={
+ category="lo",
+ description="OL CHIKI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5A,
+ },
+ [0x1C5B]={
+ category="lo",
+ description="OL CHIKI LETTER AT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5B,
+ },
+ [0x1C5C]={
+ category="lo",
+ description="OL CHIKI LETTER AG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5C,
+ },
+ [0x1C5D]={
+ category="lo",
+ description="OL CHIKI LETTER ANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5D,
+ },
+ [0x1C5E]={
+ category="lo",
+ description="OL CHIKI LETTER AL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5E,
+ },
+ [0x1C5F]={
+ category="lo",
+ description="OL CHIKI LETTER LAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C5F,
+ },
+ [0x1C60]={
+ category="lo",
+ description="OL CHIKI LETTER AAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C60,
+ },
+ [0x1C61]={
+ category="lo",
+ description="OL CHIKI LETTER AAJ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C61,
+ },
+ [0x1C62]={
+ category="lo",
+ description="OL CHIKI LETTER AAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C62,
+ },
+ [0x1C63]={
+ category="lo",
+ description="OL CHIKI LETTER AAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C63,
+ },
+ [0x1C64]={
+ category="lo",
+ description="OL CHIKI LETTER LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C64,
+ },
+ [0x1C65]={
+ category="lo",
+ description="OL CHIKI LETTER IS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C65,
+ },
+ [0x1C66]={
+ category="lo",
+ description="OL CHIKI LETTER IH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C66,
+ },
+ [0x1C67]={
+ category="lo",
+ description="OL CHIKI LETTER INY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C67,
+ },
+ [0x1C68]={
+ category="lo",
+ description="OL CHIKI LETTER IR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C68,
+ },
+ [0x1C69]={
+ category="lo",
+ description="OL CHIKI LETTER LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C69,
+ },
+ [0x1C6A]={
+ category="lo",
+ description="OL CHIKI LETTER UC",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6A,
+ },
+ [0x1C6B]={
+ category="lo",
+ description="OL CHIKI LETTER UD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6B,
+ },
+ [0x1C6C]={
+ category="lo",
+ description="OL CHIKI LETTER UNN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6C,
+ },
+ [0x1C6D]={
+ category="lo",
+ description="OL CHIKI LETTER UY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6D,
+ },
+ [0x1C6E]={
+ category="lo",
+ description="OL CHIKI LETTER LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6E,
+ },
+ [0x1C6F]={
+ category="lo",
+ description="OL CHIKI LETTER EP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C6F,
+ },
+ [0x1C70]={
+ category="lo",
+ description="OL CHIKI LETTER EDD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C70,
+ },
+ [0x1C71]={
+ category="lo",
+ description="OL CHIKI LETTER EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C71,
+ },
+ [0x1C72]={
+ category="lo",
+ description="OL CHIKI LETTER ERR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C72,
+ },
+ [0x1C73]={
+ category="lo",
+ description="OL CHIKI LETTER LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C73,
+ },
+ [0x1C74]={
+ category="lo",
+ description="OL CHIKI LETTER OTT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C74,
+ },
+ [0x1C75]={
+ category="lo",
+ description="OL CHIKI LETTER OB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C75,
+ },
+ [0x1C76]={
+ category="lo",
+ description="OL CHIKI LETTER OV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C76,
+ },
+ [0x1C77]={
+ category="lo",
+ description="OL CHIKI LETTER OH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C77,
+ },
+ [0x1C78]={
+ category="lm",
+ description="OL CHIKI MU TTUDDAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C78,
+ },
+ [0x1C79]={
+ category="lm",
+ description="OL CHIKI GAAHLAA TTUDDAAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C79,
+ },
+ [0x1C7A]={
+ category="lm",
+ description="OL CHIKI MU-GAAHLAA TTUDDAAG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C7A,
+ },
+ [0x1C7B]={
+ category="lm",
+ description="OL CHIKI RELAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C7B,
+ },
+ [0x1C7C]={
+ category="lm",
+ description="OL CHIKI PHAARKAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C7C,
+ },
+ [0x1C7D]={
+ category="lm",
+ description="OL CHIKI AHAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1C7D,
+ },
+ [0x1C7E]={
+ category="po",
+ description="OL CHIKI PUNCTUATION MUCAAD",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C7E,
+ },
+ [0x1C7F]={
+ category="po",
+ description="OL CHIKI PUNCTUATION DOUBLE MUCAAD",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x1C7F,
+ },
+ [0x1CD0]={
+ category="mn",
+ description="VEDIC TONE KARSHANA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD0,
+ },
+ [0x1CD1]={
+ category="mn",
+ description="VEDIC TONE SHARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD1,
+ },
+ [0x1CD2]={
+ category="mn",
+ description="VEDIC TONE PRENKHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD2,
+ },
+ [0x1CD3]={
+ category="po",
+ description="VEDIC SIGN NIHSHVASA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CD3,
+ },
+ [0x1CD4]={
+ category="mn",
+ description="VEDIC SIGN YAJURVEDIC MIDLINE SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD4,
+ },
+ [0x1CD5]={
+ category="mn",
+ description="VEDIC TONE YAJURVEDIC AGGRAVATED INDEPENDENT SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD5,
+ },
+ [0x1CD6]={
+ category="mn",
+ description="VEDIC TONE YAJURVEDIC INDEPENDENT SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD6,
+ },
+ [0x1CD7]={
+ category="mn",
+ description="VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD7,
+ },
+ [0x1CD8]={
+ category="mn",
+ description="VEDIC TONE CANDRA BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD8,
+ },
+ [0x1CD9]={
+ category="mn",
+ description="VEDIC TONE YAJURVEDIC KATHAKA INDEPENDENT SVARITA SCHROEDER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CD9,
+ },
+ [0x1CDA]={
+ category="mn",
+ description="VEDIC TONE DOUBLE SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDA,
+ },
+ [0x1CDB]={
+ category="mn",
+ description="VEDIC TONE TRIPLE SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDB,
+ },
+ [0x1CDC]={
+ category="mn",
+ description="VEDIC TONE KATHAKA ANUDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDC,
+ },
+ [0x1CDD]={
+ category="mn",
+ description="VEDIC TONE DOT BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDD,
+ },
+ [0x1CDE]={
+ category="mn",
+ description="VEDIC TONE TWO DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDE,
+ },
+ [0x1CDF]={
+ category="mn",
+ description="VEDIC TONE THREE DOTS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CDF,
+ },
+ [0x1CE0]={
+ category="mn",
+ description="VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE0,
+ },
+ [0x1CE1]={
+ category="mc",
+ description="VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1CE1,
+ },
+ [0x1CE2]={
+ category="mn",
+ description="VEDIC SIGN VISARGA SVARITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE2,
+ },
+ [0x1CE3]={
+ category="mn",
+ description="VEDIC SIGN VISARGA UDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE3,
+ },
+ [0x1CE4]={
+ category="mn",
+ description="VEDIC SIGN REVERSED VISARGA UDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE4,
+ },
+ [0x1CE5]={
+ category="mn",
+ description="VEDIC SIGN VISARGA ANUDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE5,
+ },
+ [0x1CE6]={
+ category="mn",
+ description="VEDIC SIGN REVERSED VISARGA ANUDATTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE6,
+ },
+ [0x1CE7]={
+ category="mn",
+ description="VEDIC SIGN VISARGA UDATTA WITH TAIL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE7,
+ },
+ [0x1CE8]={
+ category="mn",
+ description="VEDIC SIGN VISARGA ANUDATTA WITH TAIL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CE8,
+ },
+ [0x1CE9]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA ANTARGOMUKHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CE9,
+ },
+ [0x1CEA]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA BAHIRGOMUKHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEA,
+ },
+ [0x1CEB]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA VAMAGOMUKHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEB,
+ },
+ [0x1CEC]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEC,
+ },
+ [0x1CED]={
+ category="mn",
+ description="VEDIC SIGN TIRYAK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1CED,
+ },
+ [0x1CEE]={
+ category="lo",
+ description="VEDIC SIGN HEXIFORM LONG ANUSVARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEE,
+ },
+ [0x1CEF]={
+ category="lo",
+ description="VEDIC SIGN LONG ANUSVARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CEF,
+ },
+ [0x1CF0]={
+ category="lo",
+ description="VEDIC SIGN RTHANG LONG ANUSVARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CF0,
+ },
+ [0x1CF1]={
+ category="lo",
+ description="VEDIC SIGN ANUSVARA UBHAYATO MUKHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1CF1,
+ },
+ [0x1CF2]={
+ category="mc",
+ description="VEDIC SIGN ARDHAVISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x1CF2,
+ },
[0x1D00]={
category="ll",
description="LATIN LETTER SMALL CAPITAL A",
@@ -44788,6 +50632,216 @@ characters.data={
linebreak="cm",
unicodeslot=0x1DCA,
},
+ [0x1DCB]={
+ category="mn",
+ description="COMBINING BREVE-MACRON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCB,
+ },
+ [0x1DCC]={
+ category="mn",
+ description="COMBINING MACRON-BREVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCC,
+ },
+ [0x1DCD]={
+ category="mn",
+ description="COMBINING DOUBLE CIRCUMFLEX ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCD,
+ },
+ [0x1DCE]={
+ category="mn",
+ description="COMBINING OGONEK ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCE,
+ },
+ [0x1DCF]={
+ category="mn",
+ description="COMBINING ZIGZAG BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DCF,
+ },
+ [0x1DD0]={
+ category="mn",
+ description="COMBINING IS BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD0,
+ },
+ [0x1DD1]={
+ category="mn",
+ description="COMBINING UR ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD1,
+ },
+ [0x1DD2]={
+ category="mn",
+ description="COMBINING US ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD2,
+ },
+ [0x1DD3]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER FLATTENED OPEN A ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD3,
+ },
+ [0x1DD4]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER AE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD4,
+ },
+ [0x1DD5]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER AO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD5,
+ },
+ [0x1DD6]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER AV",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD6,
+ },
+ [0x1DD7]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER C CEDILLA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD7,
+ },
+ [0x1DD8]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER INSULAR D",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD8,
+ },
+ [0x1DD9]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER ETH",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DD9,
+ },
+ [0x1DDA]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER G",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDA,
+ },
+ [0x1DDB]={
+ category="mn",
+ description="COMBINING LATIN LETTER SMALL CAPITAL G",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDB,
+ },
+ [0x1DDC]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER K",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDC,
+ },
+ [0x1DDD]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDD,
+ },
+ [0x1DDE]={
+ category="mn",
+ description="COMBINING LATIN LETTER SMALL CAPITAL L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDE,
+ },
+ [0x1DDF]={
+ category="mn",
+ description="COMBINING LATIN LETTER SMALL CAPITAL M",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DDF,
+ },
+ [0x1DE0]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER N",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE0,
+ },
+ [0x1DE1]={
+ category="mn",
+ description="COMBINING LATIN LETTER SMALL CAPITAL N",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE1,
+ },
+ [0x1DE2]={
+ category="mn",
+ description="COMBINING LATIN LETTER SMALL CAPITAL R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE2,
+ },
+ [0x1DE3]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER R ROTUNDA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE3,
+ },
+ [0x1DE4]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER S",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE4,
+ },
+ [0x1DE5]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER LONG S",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE5,
+ },
+ [0x1DE6]={
+ category="mn",
+ description="COMBINING LATIN SMALL LETTER Z",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DE6,
+ },
+ [0x1DFC]={
+ category="mn",
+ description="COMBINING DOUBLE INVERTED BREVE BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DFC,
+ },
+ [0x1DFD]={
+ category="mn",
+ description="COMBINING ALMOST EQUAL TO BELOW",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1DFD,
+ },
[0x1DFE]={
category="mn",
description="COMBINING LEFT ARROWHEAD ABOVE",
@@ -46512,6 +52566,34 @@ characters.data={
uccode=0x1E60,
unicodeslot=0x1E9B,
},
+ [0x1E9C]={
+ category="ll",
+ description="LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1E9C,
+ },
+ [0x1E9D]={
+ category="ll",
+ description="LATIN SMALL LETTER LONG S WITH HIGH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1E9D,
+ },
+ [0x1E9E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER SHARP S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1E9E,
+ },
+ [0x1E9F]={
+ category="ll",
+ description="LATIN SMALL LETTER DELTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1E9F,
+ },
[0x1EA0]={
adobename="Adotbelow",
category="lu",
@@ -47592,6 +53674,48 @@ characters.data={
uccode=0x1EF8,
unicodeslot=0x1EF9,
},
+ [0x1EFA]={
+ category="lu",
+ description="LATIN CAPITAL LETTER MIDDLE-WELSH LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFA,
+ },
+ [0x1EFB]={
+ category="ll",
+ description="LATIN SMALL LETTER MIDDLE-WELSH LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFB,
+ },
+ [0x1EFC]={
+ category="lu",
+ description="LATIN CAPITAL LETTER MIDDLE-WELSH V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFC,
+ },
+ [0x1EFD]={
+ category="ll",
+ description="LATIN SMALL LETTER MIDDLE-WELSH V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFD,
+ },
+ [0x1EFE]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Y WITH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFE,
+ },
+ [0x1EFF]={
+ category="ll",
+ description="LATIN SMALL LETTER Y WITH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1EFF,
+ },
[0x1F00]={
category="ll",
contextname="greekalphapsili",
@@ -50086,7 +56210,7 @@ characters.data={
contextname="greekoxia",
description="GREEK OXIA",
direction="on",
- linebreak="al",
+ linebreak="bb",
specials={ "char", 0x00B4 },
unicodeslot=0x1FFD,
},
@@ -50190,7 +56314,7 @@ characters.data={
},
[0x200A]={
category="zs",
- contextname="figurespace",
+ contextname="hairspace",
description="HAIR SPACE",
direction="ws",
linebreak="ba",
@@ -50492,8 +56616,16 @@ characters.data={
description="HORIZONTAL ELLIPSIS",
direction="on",
linebreak="in",
- mathclass="inner",
- mathname="ldots",
+ mathspec={
+ {
+ class="inner",
+ name="ldots",
+ },
+ {
+ class="inner",
+ name="dots",
+ }
+ },
specials={ "compat", 0x002E, 0x002E, 0x002E },
unicodeslot=0x2026,
},
@@ -50601,6 +56733,8 @@ characters.data={
description="DOUBLE PRIME",
direction="et",
linebreak="po",
+ mathclass="nothing",
+ mathname="doubleprime",
specials={ "compat", 0x2032, 0x2032 },
unicodeslot=0x2033,
},
@@ -50609,6 +56743,8 @@ characters.data={
description="TRIPLE PRIME",
direction="et",
linebreak="po",
+ mathclass="nothing",
+ mathname="tripleprime",
specials={ "compat", 0x2032, 0x2032, 0x2032 },
unicodeslot=0x2034,
},
@@ -50744,7 +56880,7 @@ characters.data={
linebreak="is",
mathspec={
{
- class="binary",
+ class="ord",
name="slash",
},
{
@@ -50981,6 +57117,13 @@ characters.data={
linebreak="al",
unicodeslot=0x2063,
},
+ [0x2064]={
+ category="cf",
+ description="INVISIBLE PLUS",
+ direction="bn",
+ linebreak="al",
+ unicodeslot=0x2064,
+ },
[0x206A]={
category="cf",
description="INHIBIT SYMMETRIC SWAPPING",
@@ -51329,6 +57472,70 @@ characters.data={
specials={ "sub", 0x0259 },
unicodeslot=0x2094,
},
+ [0x2095]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER H",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x0068 },
+ unicodeslot=0x2095,
+ },
+ [0x2096]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER K",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x006B },
+ unicodeslot=0x2096,
+ },
+ [0x2097]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER L",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x006C },
+ unicodeslot=0x2097,
+ },
+ [0x2098]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER M",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x006D },
+ unicodeslot=0x2098,
+ },
+ [0x2099]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER N",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x006E },
+ unicodeslot=0x2099,
+ },
+ [0x209A]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER P",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x0070 },
+ unicodeslot=0x209A,
+ },
+ [0x209B]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER S",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x0073 },
+ unicodeslot=0x209B,
+ },
+ [0x209C]={
+ category="lm",
+ description="LATIN SUBSCRIPT SMALL LETTER T",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x0074 },
+ unicodeslot=0x209C,
+ },
[0x20A0]={
category="sc",
description="EURO-CURRENCY SIGN",
@@ -51497,6 +57704,34 @@ characters.data={
linebreak="pr",
unicodeslot=0x20B5,
},
+ [0x20B6]={
+ category="sc",
+ description="LIVRE TOURNOIS SIGN",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0x20B6,
+ },
+ [0x20B7]={
+ category="sc",
+ description="SPESMILO SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B7,
+ },
+ [0x20B8]={
+ category="sc",
+ description="TENGE SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B8,
+ },
+ [0x20B9]={
+ category="sc",
+ description="INDIAN RUPEE SIGN",
+ direction="et",
+ linebreak="pr",
+ unicodeslot=0x20B9,
+ },
[0x20D0]={
category="mn",
description="COMBINING LEFT HARPOON ABOVE",
@@ -51740,6 +57975,13 @@ characters.data={
linebreak="cm",
unicodeslot=0x20EF,
},
+ [0x20F0]={
+ category="mn",
+ description="COMBINING ASTERISK ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x20F0,
+ },
[0x2100]={
category="so",
description="ACCOUNT OF",
@@ -52453,6 +58695,37 @@ characters.data={
uccode=0x2132,
unicodeslot=0x214E,
},
+ [0x214F]={
+ category="so",
+ description="SYMBOL FOR SAMARITAN SOURCE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x214F,
+ },
+ [0x2150]={
+ category="no",
+ description="VULGAR FRACTION ONE SEVENTH",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x0031, 0x2044, 0x0037 },
+ unicodeslot=0x2150,
+ },
+ [0x2151]={
+ category="no",
+ description="VULGAR FRACTION ONE NINTH",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x0031, 0x2044, 0x0039 },
+ unicodeslot=0x2151,
+ },
+ [0x2152]={
+ category="no",
+ description="VULGAR FRACTION ONE TENTH",
+ direction="on",
+ linebreak="al",
+ specials={ "fraction", 0x0031, 0x2044, 0x0031, 0x0030 },
+ unicodeslot=0x2152,
+ },
[0x2153]={
adobename="onethird",
category="no",
@@ -52984,6 +59257,43 @@ characters.data={
uccode=0x2183,
unicodeslot=0x2184,
},
+ [0x2185]={
+ category="nl",
+ description="ROMAN NUMERAL SIX LATE FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2185,
+ },
+ [0x2186]={
+ category="nl",
+ description="ROMAN NUMERAL FIFTY EARLY FORM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2186,
+ },
+ [0x2187]={
+ category="nl",
+ description="ROMAN NUMERAL FIFTY THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2187,
+ },
+ [0x2188]={
+ category="nl",
+ description="ROMAN NUMERAL ONE HUNDRED THOUSAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2188,
+ },
+ [0x2189]={
+ category="no",
+ cjkwd="a",
+ description="VULGAR FRACTION ZERO THIRDS",
+ direction="on",
+ linebreak="ai",
+ specials={ "fraction", 0x0030, 0x2044, 0x0033 },
+ unicodeslot=0x2189,
+ },
[0x2190]={
adobename="arrowleft",
category="sm",
@@ -52991,6 +59301,7 @@ characters.data={
description="LEFTWARDS ARROW",
direction="on",
linebreak="ai",
+ mathfiller="leftarrowfill",
mathspec={
{
class="relation",
@@ -53030,6 +59341,7 @@ characters.data={
description="RIGHTWARDS ARROW",
direction="on",
linebreak="ai",
+ mathfiller="rightarrowfill",
mathspec={
{
class="relation",
@@ -54204,8 +60516,16 @@ characters.data={
description="NOT AN ELEMENT OF",
direction="on",
linebreak="al",
- mathclass="relation",
- mathname="nin",
+ mathspec={
+ {
+ class="relation",
+ name="notin",
+ },
+ {
+ class="relation",
+ name="nin",
+ },
+ },
mirror=0x220C,
specials={ "char", 0x2208, 0x0338 },
unicodeslot=0x2209,
@@ -54307,10 +60627,21 @@ characters.data={
[0x2212]={
adobename="minus",
category="sm",
+--comment="the mathclass is needed for mathsymbol remapping",
description="MINUS SIGN",
direction="es",
linebreak="pr",
- mathclass="binary",
+--mathclass="binary",
+ mathspec={
+ {
+ class="binary",
+ name="minus",
+ },
+ {
+ class="relation",
+ name="relbar",
+ },
+ },
unicodeslot=0x2212,
},
[0x2213]={
@@ -54576,6 +60907,9 @@ characters.data={
mathclass="binary",
mathname="cap",
unicodeslot=0x2229,
+ variants={
+ [0xFE00]="with serifs",
+ },
},
[0x222A]={
adobename="union",
@@ -54587,6 +60921,9 @@ characters.data={
mathclass="binary",
mathname="cup",
unicodeslot=0x222A,
+ variants={
+ [0xFE00]="with serifs",
+ },
},
[0x222B]={
adobename="integral",
@@ -54989,6 +61326,8 @@ characters.data={
description="APPROACHES THE LIMIT",
direction="on",
linebreak="al",
+ mathclass="relation",
+ mathname="doteq",
unicodeslot=0x2250,
},
[0x2251]={
@@ -55262,6 +61601,9 @@ characters.data={
mathname="lneqq",
mirror=0x2269,
unicodeslot=0x2268,
+ variants={
+ [0xFE00]="with vertical stroke",
+ },
},
[0x2269]={
category="sm",
@@ -55272,6 +61614,9 @@ characters.data={
mathname="gneqq",
mirror=0x2268,
unicodeslot=0x2269,
+ variants={
+ [0xFE00]="with vertical stroke",
+ },
},
[0x226A]={
adobename="muchless",
@@ -55376,6 +61721,9 @@ characters.data={
mathname="lesssim",
mirror=0x2273,
unicodeslot=0x2272,
+ variants={
+ [0xFE00]="following the slant of the lower leg",
+ },
},
[0x2273]={
adobename="greaterorequivalent",
@@ -55387,6 +61735,9 @@ characters.data={
mathname="gtrsim",
mirror=0x2272,
unicodeslot=0x2273,
+ variants={
+ [0xFE00]="following the slant of the lower leg",
+ },
},
[0x2274]={
category="sm",
@@ -55645,6 +61996,9 @@ characters.data={
mathname="subsetneq",
mirror=0x228B,
unicodeslot=0x228A,
+ variants={
+ [0xFE00]="with stroke through bottom members",
+ },
},
[0x228B]={
adobename="supersetnotequal",
@@ -55656,6 +62010,9 @@ characters.data={
mathname="supsetneq",
mirror=0x228A,
unicodeslot=0x228B,
+ variants={
+ [0xFE00]="with stroke through bottom members",
+ },
},
[0x228C]={
category="sm",
@@ -55728,6 +62085,9 @@ characters.data={
mathclass="binary",
mathname="sqcap",
unicodeslot=0x2293,
+ variants={
+ [0xFE00]="with serifs",
+ },
},
[0x2294]={
category="sm",
@@ -55737,6 +62097,9 @@ characters.data={
mathclass="binary",
mathname="sqcup",
unicodeslot=0x2294,
+ variants={
+ [0xFE00]="with serifs",
+ },
},
[0x2295]={
adobename="pluscircle",
@@ -55748,6 +62111,9 @@ characters.data={
mathclass="binary",
mathname="oplus",
unicodeslot=0x2295,
+ variants={
+ [0xFE00]="with white rim",
+ },
},
[0x2296]={
adobename="minuscircle",
@@ -55768,6 +62134,9 @@ characters.data={
mathclass="binary",
mathname="otimes",
unicodeslot=0x2297,
+ variants={
+ [0xFE00]="with white rim",
+ },
},
[0x2298]={
category="sm",
@@ -55816,6 +62185,9 @@ characters.data={
mathclass="binary",
mathname="circledequals",
unicodeslot=0x229C,
+ variants={
+ [0xFE00]="with equal sign touching the circle",
+ },
},
[0x229D]={
category="sm",
@@ -56026,21 +62398,21 @@ characters.data={
},
[0x22B2]={
category="sm",
+ comment="cramped triangleleft",
description="NORMAL SUBGROUP OF",
direction="on",
linebreak="al",
mathclass="bin",
- mathname="triangleleft",
mirror=0x22B3,
unicodeslot=0x22B2,
},
[0x22B3]={
category="sm",
+ comment="cramped triangleright",
description="CONTAINS AS NORMAL SUBGROUP",
direction="on",
linebreak="al",
mathclass="bin",
- mathname="triangleright",
mirror=0x22B2,
unicodeslot=0x22B3,
},
@@ -56444,6 +62816,9 @@ characters.data={
mathname="lesseqgtr",
mirror=0x22DB,
unicodeslot=0x22DA,
+ variants={
+ [0xFE00]="with slanted equal",
+ },
},
[0x22DB]={
adobename="greaterequalorless",
@@ -56455,6 +62830,9 @@ characters.data={
mathname="gtreqless",
mirror=0x22DA,
unicodeslot=0x22DB,
+ variants={
+ [0xFE00]="with slanted equal",
+ },
},
[0x22DC]={
category="sm",
@@ -56857,8 +63235,16 @@ characters.data={
description="LEFT CEILING",
direction="on",
linebreak="al",
- mathclass="open",
- mathname="lceil",
+ mathspec = {
+ {
+ class="open",
+ name="lceil",
+ },
+ {
+ class="open",
+ name="lceiling",
+ }
+ },
mirror=0x2309,
unicodeslot=0x2308,
},
@@ -56867,8 +63253,16 @@ characters.data={
description="RIGHT CEILING",
direction="on",
linebreak="al",
- mathclass="close",
- mathname="rceil",
+ mathspec = {
+ {
+ class="close",
+ name="rceil",
+ },
+ {
+ class="close",
+ name="rceiling",
+ }
+ },
mirror=0x2308,
unicodeslot=0x2309,
},
@@ -58476,6 +64870,90 @@ characters.data={
linebreak="al",
unicodeslot=0x23E7,
},
+ [0x23E8]={
+ category="so",
+ description="DECIMAL EXPONENT SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E8,
+ },
+ [0x23E9]={
+ category="so",
+ description="BLACK RIGHT-POINTING DOUBLE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23E9,
+ },
+ [0x23EA]={
+ category="so",
+ description="BLACK LEFT-POINTING DOUBLE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EA,
+ },
+ [0x23EB]={
+ category="so",
+ description="BLACK UP-POINTING DOUBLE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EB,
+ },
+ [0x23EC]={
+ category="so",
+ description="BLACK DOWN-POINTING DOUBLE TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EC,
+ },
+ [0x23ED]={
+ category="so",
+ description="BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23ED,
+ },
+ [0x23EE]={
+ category="so",
+ description="BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EE,
+ },
+ [0x23EF]={
+ category="so",
+ description="BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23EF,
+ },
+ [0x23F0]={
+ category="so",
+ description="ALARM CLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F0,
+ },
+ [0x23F1]={
+ category="so",
+ description="STOPWATCH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F1,
+ },
+ [0x23F2]={
+ category="so",
+ description="TIMER CLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F2,
+ },
+ [0x23F3]={
+ category="so",
+ description="HOURGLASS WITH FLOWING SAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x23F3,
+ },
[0x2400]={
category="so",
description="SYMBOL FOR NULL",
@@ -61746,6 +68224,8 @@ characters.data={
description="BLACK SQUARE",
direction="on",
linebreak="ai",
+ mathclass="ord",
+ mathname="blacksquare",
unicodeslot=0x25A0,
},
[0x25A1]={
@@ -61773,7 +68253,6 @@ characters.data={
direction="on",
linebreak="al",
mathclass="ord",
- mathname="blacksquare",
unicodeslot=0x25A2,
},
[0x25A3]={
@@ -61960,6 +68439,8 @@ characters.data={
description="WHITE RIGHT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
+ mathclass="bin",
+ mathname="triangleright",
unicodeslot=0x25B7,
},
[0x25B8]={
@@ -62045,6 +68526,8 @@ characters.data={
description="WHITE LEFT-POINTING TRIANGLE",
direction="on",
linebreak="ai",
+ mathclass="bin",
+ mathname="triangleleft",
unicodeslot=0x25C1,
},
[0x25C2]={
@@ -63286,6 +69769,8 @@ characters.data={
description="BLACK DIAMOND SUIT",
direction="on",
linebreak="al",
+ mathclass="ord",
+ mathname="blacklozenge",
unicodeslot=0x2666,
},
[0x2667]={
@@ -63687,6 +70172,29 @@ characters.data={
linebreak="al",
unicodeslot=0x269C,
},
+ [0x269D]={
+ category="so",
+ description="OUTLINED WHITE STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x269D,
+ },
+ [0x269E]={
+ category="so",
+ cjkwd="a",
+ description="THREE LINES CONVERGING RIGHT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x269E,
+ },
+ [0x269F]={
+ category="so",
+ cjkwd="a",
+ description="THREE LINES CONVERGING LEFT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x269F,
+ },
[0x26A0]={
category="so",
description="WARNING SIGN",
@@ -63820,6 +70328,601 @@ characters.data={
linebreak="al",
unicodeslot=0x26B2,
},
+ [0x26B3]={
+ category="so",
+ description="CERES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B3,
+ },
+ [0x26B4]={
+ category="so",
+ description="PALLAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B4,
+ },
+ [0x26B5]={
+ category="so",
+ description="JUNO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B5,
+ },
+ [0x26B6]={
+ category="so",
+ description="VESTA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B6,
+ },
+ [0x26B7]={
+ category="so",
+ description="CHIRON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B7,
+ },
+ [0x26B8]={
+ category="so",
+ description="BLACK MOON LILITH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B8,
+ },
+ [0x26B9]={
+ category="so",
+ description="SEXTILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26B9,
+ },
+ [0x26BA]={
+ category="so",
+ description="SEMISEXTILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26BA,
+ },
+ [0x26BB]={
+ category="so",
+ description="QUINCUNX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26BB,
+ },
+ [0x26BC]={
+ category="so",
+ description="SESQUIQUADRATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26BC,
+ },
+ [0x26BD]={
+ category="so",
+ description="SOCCER BALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26BD,
+ },
+ [0x26BE]={
+ category="so",
+ cjkwd="a",
+ description="BASEBALL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26BE,
+ },
+ [0x26BF]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED KEY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26BF,
+ },
+ [0x26C0]={
+ category="so",
+ description="WHITE DRAUGHTS MAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26C0,
+ },
+ [0x26C1]={
+ category="so",
+ description="WHITE DRAUGHTS KING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26C1,
+ },
+ [0x26C2]={
+ category="so",
+ description="BLACK DRAUGHTS MAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26C2,
+ },
+ [0x26C3]={
+ category="so",
+ description="BLACK DRAUGHTS KING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26C3,
+ },
+ [0x26C4]={
+ category="so",
+ cjkwd="a",
+ description="SNOWMAN WITHOUT SNOW",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26C4,
+ },
+ [0x26C5]={
+ category="so",
+ cjkwd="a",
+ description="SUN BEHIND CLOUD",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26C5,
+ },
+ [0x26C6]={
+ category="so",
+ cjkwd="a",
+ description="RAIN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26C6,
+ },
+ [0x26C7]={
+ category="so",
+ cjkwd="a",
+ description="BLACK SNOWMAN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26C7,
+ },
+ [0x26C8]={
+ category="so",
+ cjkwd="a",
+ description="THUNDER CLOUD AND RAIN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26C8,
+ },
+ [0x26C9]={
+ category="so",
+ cjkwd="a",
+ description="TURNED WHITE SHOGI PIECE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26C9,
+ },
+ [0x26CA]={
+ category="so",
+ cjkwd="a",
+ description="TURNED BLACK SHOGI PIECE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26CA,
+ },
+ [0x26CB]={
+ category="so",
+ cjkwd="a",
+ description="WHITE DIAMOND IN SQUARE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26CB,
+ },
+ [0x26CC]={
+ category="so",
+ cjkwd="a",
+ description="CROSSING LANES",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26CC,
+ },
+ [0x26CD]={
+ category="so",
+ cjkwd="a",
+ description="DISABLED CAR",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26CD,
+ },
+ [0x26CE]={
+ category="so",
+ description="OPHIUCHUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26CE,
+ },
+ [0x26CF]={
+ category="so",
+ cjkwd="a",
+ description="PICK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26CF,
+ },
+ [0x26D0]={
+ category="so",
+ cjkwd="a",
+ description="CAR SLIDING",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D0,
+ },
+ [0x26D1]={
+ category="so",
+ cjkwd="a",
+ description="HELMET WITH WHITE CROSS",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D1,
+ },
+ [0x26D2]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED CROSSING LANES",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D2,
+ },
+ [0x26D3]={
+ category="so",
+ cjkwd="a",
+ description="CHAINS",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D3,
+ },
+ [0x26D4]={
+ category="so",
+ cjkwd="a",
+ description="NO ENTRY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D4,
+ },
+ [0x26D5]={
+ category="so",
+ cjkwd="a",
+ description="ALTERNATE ONE-WAY LEFT WAY TRAFFIC",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D5,
+ },
+ [0x26D6]={
+ category="so",
+ cjkwd="a",
+ description="BLACK TWO-WAY LEFT WAY TRAFFIC",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D6,
+ },
+ [0x26D7]={
+ category="so",
+ cjkwd="a",
+ description="WHITE TWO-WAY LEFT WAY TRAFFIC",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D7,
+ },
+ [0x26D8]={
+ category="so",
+ cjkwd="a",
+ description="BLACK LEFT LANE MERGE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D8,
+ },
+ [0x26D9]={
+ category="so",
+ cjkwd="a",
+ description="WHITE LEFT LANE MERGE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26D9,
+ },
+ [0x26DA]={
+ category="so",
+ cjkwd="a",
+ description="DRIVE SLOW SIGN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DA,
+ },
+ [0x26DB]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY WHITE DOWN-POINTING TRIANGLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DB,
+ },
+ [0x26DC]={
+ category="so",
+ cjkwd="a",
+ description="LEFT CLOSED ENTRY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DC,
+ },
+ [0x26DD]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED SALTIRE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DD,
+ },
+ [0x26DE]={
+ category="so",
+ cjkwd="a",
+ description="FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DE,
+ },
+ [0x26DF]={
+ category="so",
+ cjkwd="a",
+ description="BLACK TRUCK",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26DF,
+ },
+ [0x26E0]={
+ category="so",
+ cjkwd="a",
+ description="RESTRICTED LEFT ENTRY-1",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26E0,
+ },
+ [0x26E1]={
+ category="so",
+ cjkwd="a",
+ description="RESTRICTED LEFT ENTRY-2",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26E1,
+ },
+ [0x26E2]={
+ category="so",
+ description="ASTRONOMICAL SYMBOL FOR URANUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E2,
+ },
+ [0x26E3]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26E3,
+ },
+ [0x26E4]={
+ category="so",
+ description="PENTAGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E4,
+ },
+ [0x26E5]={
+ category="so",
+ description="RIGHT-HANDED INTERLACED PENTAGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E5,
+ },
+ [0x26E6]={
+ category="so",
+ description="LEFT-HANDED INTERLACED PENTAGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E6,
+ },
+ [0x26E7]={
+ category="so",
+ description="INVERTED PENTAGRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x26E7,
+ },
+ [0x26E8]={
+ category="so",
+ cjkwd="a",
+ description="BLACK CROSS ON SHIELD",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26E8,
+ },
+ [0x26E9]={
+ category="so",
+ cjkwd="a",
+ description="SHINTO SHRINE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26E9,
+ },
+ [0x26EA]={
+ category="so",
+ cjkwd="a",
+ description="CHURCH",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EA,
+ },
+ [0x26EB]={
+ category="so",
+ cjkwd="a",
+ description="CASTLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EB,
+ },
+ [0x26EC]={
+ category="so",
+ cjkwd="a",
+ description="HISTORIC SITE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EC,
+ },
+ [0x26ED]={
+ category="so",
+ cjkwd="a",
+ description="GEAR WITHOUT HUB",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26ED,
+ },
+ [0x26EE]={
+ category="so",
+ cjkwd="a",
+ description="GEAR WITH HANDLES",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EE,
+ },
+ [0x26EF]={
+ category="so",
+ cjkwd="a",
+ description="MAP SYMBOL FOR LIGHTHOUSE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26EF,
+ },
+ [0x26F0]={
+ category="so",
+ cjkwd="a",
+ description="MOUNTAIN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F0,
+ },
+ [0x26F1]={
+ category="so",
+ cjkwd="a",
+ description="UMBRELLA ON GROUND",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F1,
+ },
+ [0x26F2]={
+ category="so",
+ cjkwd="a",
+ description="FOUNTAIN",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F2,
+ },
+ [0x26F3]={
+ category="so",
+ cjkwd="a",
+ description="FLAG IN HOLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F3,
+ },
+ [0x26F4]={
+ category="so",
+ cjkwd="a",
+ description="FERRY",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F4,
+ },
+ [0x26F5]={
+ category="so",
+ cjkwd="a",
+ description="SAILBOAT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F5,
+ },
+ [0x26F6]={
+ category="so",
+ cjkwd="a",
+ description="SQUARE FOUR CORNERS",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F6,
+ },
+ [0x26F7]={
+ category="so",
+ cjkwd="a",
+ description="SKIER",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F7,
+ },
+ [0x26F8]={
+ category="so",
+ cjkwd="a",
+ description="ICE SKATE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F8,
+ },
+ [0x26F9]={
+ category="so",
+ cjkwd="a",
+ description="PERSON WITH BALL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26F9,
+ },
+ [0x26FA]={
+ category="so",
+ cjkwd="a",
+ description="TENT",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26FA,
+ },
+ [0x26FB]={
+ category="so",
+ cjkwd="a",
+ description="JAPANESE BANK SYMBOL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26FB,
+ },
+ [0x26FC]={
+ category="so",
+ cjkwd="a",
+ description="HEADSTONE GRAVEYARD SYMBOL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26FC,
+ },
+ [0x26FD]={
+ category="so",
+ cjkwd="a",
+ description="FUEL PUMP",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26FD,
+ },
+ [0x26FE]={
+ category="so",
+ cjkwd="a",
+ description="CUP ON BLACK SQUARE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26FE,
+ },
+ [0x26FF]={
+ category="so",
+ cjkwd="a",
+ description="WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x26FF,
+ },
[0x2701]={
category="so",
description="UPPER BLADE SCISSORS",
@@ -63848,6 +70951,13 @@ characters.data={
linebreak="al",
unicodeslot=0x2704,
},
+ [0x2705]={
+ category="so",
+ description="WHITE HEAVY CHECK MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2705,
+ },
[0x2706]={
category="so",
description="TELEPHONE LOCATION SIGN",
@@ -63876,6 +70986,20 @@ characters.data={
linebreak="al",
unicodeslot=0x2709,
},
+ [0x270A]={
+ category="so",
+ description="RAISED FIST",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x270A,
+ },
+ [0x270B]={
+ category="so",
+ description="RAISED HAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x270B,
+ },
[0x270C]={
category="so",
description="VICTORY HAND",
@@ -64077,6 +71201,13 @@ characters.data={
linebreak="al",
unicodeslot=0x2727,
},
+ [0x2728]={
+ category="so",
+ description="SPARKLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2728,
+ },
[0x2729]={
category="so",
description="STRESS OUTLINED WHITE STAR",
@@ -64323,6 +71454,13 @@ characters.data={
linebreak="al",
unicodeslot=0x274B,
},
+ [0x274C]={
+ category="so",
+ description="CROSS MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x274C,
+ },
[0x274D]={
category="so",
description="SHADOWED WHITE CIRCLE",
@@ -64330,6 +71468,13 @@ characters.data={
linebreak="al",
unicodeslot=0x274D,
},
+ [0x274E]={
+ category="so",
+ description="NEGATIVE SQUARED CROSS MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x274E,
+ },
[0x274F]={
category="so",
description="LOWER RIGHT DROP-SHADOWED WHITE SQUARE",
@@ -64358,6 +71503,27 @@ characters.data={
linebreak="al",
unicodeslot=0x2752,
},
+ [0x2753]={
+ category="so",
+ description="BLACK QUESTION MARK ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2753,
+ },
+ [0x2754]={
+ category="so",
+ description="WHITE QUESTION MARK ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2754,
+ },
+ [0x2755]={
+ category="so",
+ description="WHITE EXCLAMATION MARK ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2755,
+ },
[0x2756]={
category="so",
description="BLACK DIAMOND MINUS WHITE X",
@@ -64365,6 +71531,14 @@ characters.data={
linebreak="al",
unicodeslot=0x2756,
},
+ [0x2757]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY EXCLAMATION MARK SYMBOL",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2757,
+ },
[0x2758]={
category="so",
description="LIGHT VERTICAL BAR",
@@ -64414,6 +71588,20 @@ characters.data={
linebreak="qu",
unicodeslot=0x275E,
},
+ [0x275F]={
+ category="so",
+ description="HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x275F,
+ },
+ [0x2760]={
+ category="so",
+ description="HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2760,
+ },
[0x2761]={
category="so",
description="CURVED STEM PARAGRAPH SIGN ORNAMENT",
@@ -64811,6 +71999,27 @@ characters.data={
linebreak="al",
unicodeslot=0x2794,
},
+ [0x2795]={
+ category="so",
+ description="HEAVY PLUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2795,
+ },
+ [0x2796]={
+ category="so",
+ description="HEAVY MINUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2796,
+ },
+ [0x2797]={
+ category="so",
+ description="HEAVY DIVISION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2797,
+ },
[0x2798]={
category="so",
description="HEAVY SOUTH EAST ARROW",
@@ -64980,6 +72189,13 @@ characters.data={
linebreak="al",
unicodeslot=0x27AF,
},
+ [0x27B0]={
+ category="so",
+ description="CURLY LOOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27B0,
+ },
[0x27B1]={
category="so",
description="NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW",
@@ -65078,6 +72294,13 @@ characters.data={
linebreak="al",
unicodeslot=0x27BE,
},
+ [0x27BF]={
+ category="so",
+ description="DOUBLE CURLY LOOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27BF,
+ },
[0x27C0]={
category="sm",
description="THREE DIMENSIONAL ANGLE",
@@ -65161,6 +72384,27 @@ characters.data={
linebreak="al",
unicodeslot=0x27CA,
},
+ [0x27CC]={
+ category="sm",
+ description="LONG DIVISION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27CC,
+ },
+ [0x27CE]={
+ category="sm",
+ description="SQUARED LOGICAL AND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27CE,
+ },
+ [0x27CF]={
+ category="sm",
+ description="SQUARED LOGICAL OR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x27CF,
+ },
[0x27D0]={
category="sm",
description="WHITE DIAMOND WITH CENTRED DOT",
@@ -65409,7 +72653,6 @@ characters.data={
},
[0x27EE]={
category="ps",
- cjkwd="na",
description="MATHEMATICAL LEFT FLATTENED PARENTHESIS",
direction="on",
linebreak="op",
@@ -65420,7 +72663,6 @@ characters.data={
},
[0x27EF]={
category="pe",
- cjkwd="na",
description="MATHEMATICAL RIGHT FLATTENED PARENTHESIS",
direction="on",
linebreak="cl",
@@ -69073,8 +76315,6 @@ characters.data={
description="BLACK LOZENGE",
direction="on",
linebreak="al",
- mathclass="ord",
- mathname="blacklozenge",
unicodeslot=0x29EB,
},
[0x29EC]={
@@ -69227,6 +76467,8 @@ characters.data={
description="N-ARY CIRCLED DOT OPERATOR",
direction="on",
linebreak="al",
+ mathclass="limop",
+ mathname="bigodot",
unicodeslot=0x2A00,
},
[0x2A01]={
@@ -69253,7 +76495,7 @@ characters.data={
direction="on",
linebreak="al",
mathclass="limop",
- mathname="bigodot",
+ mathname="bigudot",
unicodeslot=0x2A03,
},
[0x2A04]={
@@ -69670,6 +76912,9 @@ characters.data={
linebreak="al",
mirror=0x2A3D,
unicodeslot=0x2A3C,
+ variants={
+ [0xFE00]="tall variant with narrow foot",
+ },
},
[0x2A3D]={
category="sm",
@@ -69678,6 +76923,9 @@ characters.data={
linebreak="al",
mirror=0x2A3C,
unicodeslot=0x2A3D,
+ variants={
+ [0xFE00]="tall variant with narrow foot",
+ },
},
[0x2A3E]={
category="sm",
@@ -70405,6 +77653,9 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2A9D,
+ variants={
+ [0xFE00]="with similar following the slant of the upper leg",
+ },
},
[0x2A9E]={
category="sm",
@@ -70412,6 +77663,9 @@ characters.data={
direction="on",
linebreak="al",
unicodeslot=0x2A9E,
+ variants={
+ [0xFE00]="with similar following the slant of the upper leg",
+ },
},
[0x2A9F]={
category="sm",
@@ -70519,6 +77773,9 @@ characters.data={
linebreak="al",
mirror=0x2AAD,
unicodeslot=0x2AAC,
+ variants={
+ [0xFE00]="with slanted equal",
+ },
},
[0x2AAD]={
category="sm",
@@ -70527,6 +77784,9 @@ characters.data={
linebreak="al",
mirror=0x2AAC,
unicodeslot=0x2AAD,
+ variants={
+ [0xFE00]="with slanted equal",
+ },
},
[0x2AAE]={
category="sm",
@@ -70783,6 +78043,9 @@ characters.data={
mathclass="relation",
mathname="subsetneqq",
unicodeslot=0x2ACB,
+ variants={
+ [0xFE00]="with stroke through bottom members",
+ },
},
[0x2ACC]={
category="sm",
@@ -70792,6 +78055,9 @@ characters.data={
mathclass="relation",
mathname="supsetneqq",
unicodeslot=0x2ACC,
+ variants={
+ [0xFE00]="with stroke through bottom members",
+ },
},
[0x2ACD]={
category="sm",
@@ -71360,6 +78626,41 @@ characters.data={
linebreak="al",
unicodeslot=0x2B1A,
},
+ [0x2B1B]={
+ category="so",
+ description="BLACK LARGE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1B,
+ },
+ [0x2B1C]={
+ category="so",
+ description="WHITE LARGE SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1C,
+ },
+ [0x2B1D]={
+ category="so",
+ description="BLACK VERY SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1D,
+ },
+ [0x2B1E]={
+ category="so",
+ description="WHITE VERY SMALL SQUARE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1E,
+ },
+ [0x2B1F]={
+ category="so",
+ description="BLACK PENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B1F,
+ },
[0x2B20]={
category="so",
description="WHITE PENTAGON",
@@ -71388,6 +78689,368 @@ characters.data={
linebreak="al",
unicodeslot=0x2B23,
},
+ [0x2B24]={
+ category="so",
+ description="BLACK LARGE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B24,
+ },
+ [0x2B25]={
+ category="so",
+ description="BLACK MEDIUM DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B25,
+ },
+ [0x2B26]={
+ category="so",
+ description="WHITE MEDIUM DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B26,
+ },
+ [0x2B27]={
+ category="so",
+ description="BLACK MEDIUM LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B27,
+ },
+ [0x2B28]={
+ category="so",
+ description="WHITE MEDIUM LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B28,
+ },
+ [0x2B29]={
+ category="so",
+ description="BLACK SMALL DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B29,
+ },
+ [0x2B2A]={
+ category="so",
+ description="BLACK SMALL LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2A,
+ },
+ [0x2B2B]={
+ category="so",
+ description="WHITE SMALL LOZENGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2B,
+ },
+ [0x2B2C]={
+ category="so",
+ description="BLACK HORIZONTAL ELLIPSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2C,
+ },
+ [0x2B2D]={
+ category="so",
+ description="WHITE HORIZONTAL ELLIPSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2D,
+ },
+ [0x2B2E]={
+ category="so",
+ description="BLACK VERTICAL ELLIPSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2E,
+ },
+ [0x2B2F]={
+ category="so",
+ description="WHITE VERTICAL ELLIPSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B2F,
+ },
+ [0x2B30]={
+ category="sm",
+ description="LEFT ARROW WITH SMALL CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B30,
+ },
+ [0x2B31]={
+ category="sm",
+ description="THREE LEFTWARDS ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B31,
+ },
+ [0x2B32]={
+ category="sm",
+ description="LEFT ARROW WITH CIRCLED PLUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B32,
+ },
+ [0x2B33]={
+ category="sm",
+ description="LONG LEFTWARDS SQUIGGLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B33,
+ },
+ [0x2B34]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B34,
+ },
+ [0x2B35]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B35,
+ },
+ [0x2B36]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW FROM BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B36,
+ },
+ [0x2B37]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED TRIPLE DASH ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B37,
+ },
+ [0x2B38]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH DOTTED STEM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B38,
+ },
+ [0x2B39]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH TAIL WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B39,
+ },
+ [0x2B3A]={
+ category="sm",
+ description="LEFTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B3A,
+ },
+ [0x2B3B]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH TAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B3B,
+ },
+ [0x2B3C]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B3C,
+ },
+ [0x2B3D]={
+ category="sm",
+ description="LEFTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B3D,
+ },
+ [0x2B3E]={
+ category="sm",
+ description="LEFTWARDS ARROW THROUGH X",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B3E,
+ },
+ [0x2B3F]={
+ category="sm",
+ description="WAVE ARROW POINTING DIRECTLY LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B3F,
+ },
+ [0x2B40]={
+ category="sm",
+ description="EQUALS SIGN ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B40,
+ },
+ [0x2B41]={
+ category="sm",
+ description="REVERSE TILDE OPERATOR ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B41,
+ },
+ [0x2B42]={
+ category="sm",
+ description="LEFTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B42,
+ },
+ [0x2B43]={
+ category="sm",
+ description="RIGHTWARDS ARROW THROUGH GREATER-THAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B43,
+ },
+ [0x2B44]={
+ category="sm",
+ description="RIGHTWARDS ARROW THROUGH SUPERSET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B44,
+ },
+ [0x2B45]={
+ category="so",
+ description="LEFTWARDS QUADRUPLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B45,
+ },
+ [0x2B46]={
+ category="so",
+ description="RIGHTWARDS QUADRUPLE ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B46,
+ },
+ [0x2B47]={
+ category="sm",
+ description="REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B47,
+ },
+ [0x2B48]={
+ category="sm",
+ description="RIGHTWARDS ARROW ABOVE REVERSE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B48,
+ },
+ [0x2B49]={
+ category="sm",
+ description="TILDE OPERATOR ABOVE LEFTWARDS ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B49,
+ },
+ [0x2B4A]={
+ category="sm",
+ description="LEFTWARDS ARROW ABOVE ALMOST EQUAL TO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4A,
+ },
+ [0x2B4B]={
+ category="sm",
+ description="LEFTWARDS ARROW ABOVE REVERSE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4B,
+ },
+ [0x2B4C]={
+ category="sm",
+ description="RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B4C,
+ },
+ [0x2B50]={
+ category="so",
+ description="WHITE MEDIUM STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B50,
+ },
+ [0x2B51]={
+ category="so",
+ description="BLACK SMALL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B51,
+ },
+ [0x2B52]={
+ category="so",
+ description="WHITE SMALL STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B52,
+ },
+ [0x2B53]={
+ category="so",
+ description="BLACK RIGHT-POINTING PENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B53,
+ },
+ [0x2B54]={
+ category="so",
+ description="WHITE RIGHT-POINTING PENTAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2B54,
+ },
+ [0x2B55]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY LARGE CIRCLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B55,
+ },
+ [0x2B56]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY OVAL WITH OVAL INSIDE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B56,
+ },
+ [0x2B57]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY CIRCLE WITH CIRCLE INSIDE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B57,
+ },
+ [0x2B58]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY CIRCLE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B58,
+ },
+ [0x2B59]={
+ category="so",
+ cjkwd="a",
+ description="HEAVY CIRCLED SALTIRE",
+ direction="on",
+ linebreak="ai",
+ unicodeslot=0x2B59,
+ },
[0x2C00]={
category="lu",
description="GLAGOLITIC CAPITAL LETTER AZU",
@@ -72257,6 +79920,55 @@ characters.data={
uccode=0x2C6B,
unicodeslot=0x2C6C,
},
+ [0x2C6D]={
+ category="lu",
+ description="LATIN CAPITAL LETTER ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C6D,
+ },
+ [0x2C6E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER M WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C6E,
+ },
+ [0x2C6F]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C6F,
+ },
+ [0x2C70]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED ALPHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C70,
+ },
+ [0x2C71]={
+ category="ll",
+ description="LATIN SMALL LETTER V WITH RIGHT HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C71,
+ },
+ [0x2C72]={
+ category="lu",
+ description="LATIN CAPITAL LETTER W WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C72,
+ },
+ [0x2C73]={
+ category="ll",
+ description="LATIN SMALL LETTER W WITH HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C73,
+ },
[0x2C74]={
category="ll",
description="LATIN SMALL LETTER V WITH CURL",
@@ -72288,6 +80000,64 @@ characters.data={
linebreak="al",
unicodeslot=0x2C77,
},
+ [0x2C78]={
+ category="ll",
+ description="LATIN SMALL LETTER E WITH NOTCH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C78,
+ },
+ [0x2C79]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED R WITH TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C79,
+ },
+ [0x2C7A]={
+ category="ll",
+ description="LATIN SMALL LETTER O WITH LOW RING INSIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C7A,
+ },
+ [0x2C7B]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL TURNED E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C7B,
+ },
+ [0x2C7C]={
+ category="ll",
+ description="LATIN SUBSCRIPT SMALL LETTER J",
+ direction="l",
+ linebreak="al",
+ specials={ "sub", 0x006A },
+ unicodeslot=0x2C7C,
+ },
+ [0x2C7D]={
+ category="lm",
+ description="MODIFIER LETTER CAPITAL V",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0x0056 },
+ unicodeslot=0x2C7D,
+ },
+ [0x2C7E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH SWASH TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C7E,
+ },
+ [0x2C7F]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Z WITH SWASH TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2C7F,
+ },
[0x2C80]={
category="lu",
description="COPTIC CAPITAL LETTER ALFA",
@@ -73137,11 +80907,60 @@ characters.data={
linebreak="al",
unicodeslot=0x2CEA,
},
+ [0x2CEB]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CEB,
+ },
+ [0x2CEC]={
+ category="ll",
+ description="COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CEC,
+ },
+ [0x2CED]={
+ category="lu",
+ description="COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CED,
+ },
+ [0x2CEE]={
+ category="ll",
+ description="COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x2CEE,
+ },
+ [0x2CEF]={
+ category="mn",
+ description="COPTIC COMBINING NI ABOVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2CEF,
+ },
+ [0x2CF0]={
+ category="mn",
+ description="COPTIC COMBINING SPIRITUS ASPER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2CF0,
+ },
+ [0x2CF1]={
+ category="mn",
+ description="COPTIC COMBINING SPIRITUS LENIS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2CF1,
+ },
[0x2CF9]={
category="po",
description="COPTIC OLD NUBIAN FULL STOP",
direction="on",
- linebreak="ba",
+ linebreak="ex",
unicodeslot=0x2CF9,
},
[0x2CFA]={
@@ -73176,7 +80995,7 @@ characters.data={
category="po",
description="COPTIC FULL STOP",
direction="on",
- linebreak="ba",
+ linebreak="ex",
unicodeslot=0x2CFE,
},
[0x2CFF]={
@@ -73793,6 +81612,7 @@ characters.data={
},
[0x2D5B]={
category="lo",
+ cjkwd="w",
description="TIFINAGH LETTER YASH",
direction="l",
linebreak="al",
@@ -73800,6 +81620,7 @@ characters.data={
},
[0x2D5C]={
category="lo",
+ cjkwd="w",
description="TIFINAGH LETTER YAT",
direction="l",
linebreak="al",
@@ -73844,14 +81665,14 @@ characters.data={
category="lo",
description="TIFINAGH LETTER YAY",
direction="l",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2D62,
},
[0x2D63]={
category="lo",
description="TIFINAGH LETTER YAZ",
direction="l",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2D63,
},
[0x2D64]={
@@ -73876,6 +81697,20 @@ characters.data={
specials={ "super", 0x2D61 },
unicodeslot=0x2D6F,
},
+ [0x2D70]={
+ category="po",
+ description="TIFINAGH SEPARATOR MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x2D70,
+ },
+ [0x2D7F]={
+ category="mn",
+ description="TIFINAGH CONSONANT JOINER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2D7F,
+ },
[0x2D80]={
category="lo",
description="ETHIOPIC SYLLABLE LOA",
@@ -74069,14 +81904,14 @@ characters.data={
category="lo",
description="ETHIOPIC SYLLABLE SSEE",
direction="l",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2DA4,
},
[0x2DA5]={
category="lo",
description="ETHIOPIC SYLLABLE SSE",
direction="l",
- linebreak="al",
+ linebreak="id",
unicodeslot=0x2DA5,
},
[0x2DA6]={
@@ -74429,6 +82264,230 @@ characters.data={
linebreak="al",
unicodeslot=0x2DDE,
},
+ [0x2DE0]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER BE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE0,
+ },
+ [0x2DE1]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER VE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE1,
+ },
+ [0x2DE2]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER GHE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE2,
+ },
+ [0x2DE3]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER DE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE3,
+ },
+ [0x2DE4]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER ZHE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE4,
+ },
+ [0x2DE5]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER ZE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE5,
+ },
+ [0x2DE6]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER KA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE6,
+ },
+ [0x2DE7]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER EL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE7,
+ },
+ [0x2DE8]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER EM",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE8,
+ },
+ [0x2DE9]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER EN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DE9,
+ },
+ [0x2DEA]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEA,
+ },
+ [0x2DEB]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER PE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEB,
+ },
+ [0x2DEC]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER ER",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEC,
+ },
+ [0x2DED]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER ES",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DED,
+ },
+ [0x2DEE]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER TE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEE,
+ },
+ [0x2DEF]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER HA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DEF,
+ },
+ [0x2DF0]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER TSE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF0,
+ },
+ [0x2DF1]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER CHE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF1,
+ },
+ [0x2DF2]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER SHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF2,
+ },
+ [0x2DF3]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER SHCHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF3,
+ },
+ [0x2DF4]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER FITA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF4,
+ },
+ [0x2DF5]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER ES-TE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF5,
+ },
+ [0x2DF6]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF6,
+ },
+ [0x2DF7]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER IE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF7,
+ },
+ [0x2DF8]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER DJERV",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF8,
+ },
+ [0x2DF9]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER MONOGRAPH UK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DF9,
+ },
+ [0x2DFA]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER YAT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFA,
+ },
+ [0x2DFB]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER YU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFB,
+ },
+ [0x2DFC]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER IOTIFIED A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFC,
+ },
+ [0x2DFD]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER LITTLE YUS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFD,
+ },
+ [0x2DFE]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER BIG YUS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFE,
+ },
+ [0x2DFF]={
+ category="mn",
+ description="COMBINING CYRILLIC LETTER IOTIFIED BIG YUS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x2DFF,
+ },
[0x2E00]={
category="po",
description="RIGHT ANGLE SUBSTITUTION MARKER",
@@ -74605,6 +82664,34 @@ characters.data={
linebreak="ba",
unicodeslot=0x2E17,
},
+ [0x2E18]={
+ category="po",
+ description="INVERTED INTERROBANG",
+ direction="on",
+ linebreak="op",
+ unicodeslot=0x2E18,
+ },
+ [0x2E19]={
+ category="po",
+ description="PALM BRANCH",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E19,
+ },
+ [0x2E1A]={
+ category="pd",
+ description="HYPHEN WITH DIAERESIS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E1A,
+ },
+ [0x2E1B]={
+ category="po",
+ description="TILDE WITH RING ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E1B,
+ },
[0x2E1C]={
category="pi",
description="LEFT LOW PARAPHRASE BRACKET",
@@ -74621,6 +82708,156 @@ characters.data={
mirror=0x2E1C,
unicodeslot=0x2E1D,
},
+ [0x2E1E]={
+ category="po",
+ description="TILDE WITH DOT ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E1E,
+ },
+ [0x2E1F]={
+ category="po",
+ description="TILDE WITH DOT BELOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E1F,
+ },
+ [0x2E20]={
+ category="pi",
+ description="LEFT VERTICAL BAR WITH QUILL",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E21,
+ unicodeslot=0x2E20,
+ },
+ [0x2E21]={
+ category="pf",
+ description="RIGHT VERTICAL BAR WITH QUILL",
+ direction="on",
+ linebreak="qu",
+ mirror=0x2E20,
+ unicodeslot=0x2E21,
+ },
+ [0x2E22]={
+ category="ps",
+ description="TOP LEFT HALF BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2E23,
+ unicodeslot=0x2E22,
+ },
+ [0x2E23]={
+ category="pe",
+ description="TOP RIGHT HALF BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2E22,
+ unicodeslot=0x2E23,
+ },
+ [0x2E24]={
+ category="ps",
+ description="BOTTOM LEFT HALF BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2E25,
+ unicodeslot=0x2E24,
+ },
+ [0x2E25]={
+ category="pe",
+ description="BOTTOM RIGHT HALF BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2E24,
+ unicodeslot=0x2E25,
+ },
+ [0x2E26]={
+ category="ps",
+ description="LEFT SIDEWAYS U BRACKET",
+ direction="on",
+ linebreak="op",
+ mirror=0x2E27,
+ unicodeslot=0x2E26,
+ },
+ [0x2E27]={
+ category="pe",
+ description="RIGHT SIDEWAYS U BRACKET",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2E26,
+ unicodeslot=0x2E27,
+ },
+ [0x2E28]={
+ category="ps",
+ description="LEFT DOUBLE PARENTHESIS",
+ direction="on",
+ linebreak="op",
+ mirror=0x2E29,
+ unicodeslot=0x2E28,
+ },
+ [0x2E29]={
+ category="pe",
+ description="RIGHT DOUBLE PARENTHESIS",
+ direction="on",
+ linebreak="cl",
+ mirror=0x2E28,
+ unicodeslot=0x2E29,
+ },
+ [0x2E2A]={
+ category="po",
+ description="TWO DOTS OVER ONE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E2A,
+ },
+ [0x2E2B]={
+ category="po",
+ description="ONE DOT OVER TWO DOTS PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E2B,
+ },
+ [0x2E2C]={
+ category="po",
+ description="SQUARED FOUR DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E2C,
+ },
+ [0x2E2D]={
+ category="po",
+ description="FIVE DOT MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E2D,
+ },
+ [0x2E2E]={
+ category="po",
+ description="REVERSED QUESTION MARK",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0x2E2E,
+ },
+ [0x2E2F]={
+ category="lm",
+ description="VERTICAL TILDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x2E2F,
+ },
+ [0x2E30]={
+ category="po",
+ description="RING POINT",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E30,
+ },
+ [0x2E31]={
+ category="po",
+ description="WORD SEPARATOR MIDDLE DOT",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x2E31,
+ },
[0x2E80]={
category="so",
cjkwd="w",
@@ -80254,6 +88491,14 @@ characters.data={
linebreak="id",
unicodeslot=0x312C,
},
+ [0x312D]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER IH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x312D,
+ },
[0x3131]={
adobename="kiyeokkorean",
category="lo",
@@ -81528,6 +89773,30 @@ characters.data={
linebreak="id",
unicodeslot=0x31B7,
},
+ [0x31B8]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER GH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B8,
+ },
+ [0x31B9]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER LH",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31B9,
+ },
+ [0x31BA]={
+ category="lo",
+ cjkwd="w",
+ description="BOPOMOFO LETTER ZY",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x31BA,
+ },
[0x31C0]={
category="so",
cjkwd="w",
@@ -81656,6 +89925,166 @@ characters.data={
linebreak="id",
unicodeslot=0x31CF,
},
+ [0x31D0]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE H",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D0,
+ },
+ [0x31D1]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE S",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D1,
+ },
+ [0x31D2]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE P",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D2,
+ },
+ [0x31D3]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SP",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D3,
+ },
+ [0x31D4]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE D",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D4,
+ },
+ [0x31D5]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D5,
+ },
+ [0x31D6]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D6,
+ },
+ [0x31D7]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D7,
+ },
+ [0x31D8]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SWZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D8,
+ },
+ [0x31D9]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE ST",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31D9,
+ },
+ [0x31DA]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DA,
+ },
+ [0x31DB]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE PD",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DB,
+ },
+ [0x31DC]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE PZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DC,
+ },
+ [0x31DD]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE TN",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DD,
+ },
+ [0x31DE]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SZZ",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DE,
+ },
+ [0x31DF]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE SWG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31DF,
+ },
+ [0x31E0]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HXWG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31E0,
+ },
+ [0x31E1]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE HZZZG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31E1,
+ },
+ [0x31E2]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE PG",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31E2,
+ },
+ [0x31E3]={
+ category="so",
+ cjkwd="w",
+ description="CJK STROKE Q",
+ direction="on",
+ linebreak="id",
+ unicodeslot=0x31E3,
+ },
[0x31F0]={
category="lo",
cjkwd="w",
@@ -82451,6 +90880,106 @@ characters.data={
specials={ "compat", 0x0028, 0x81F3, 0x0029 },
unicodeslot=0x3243,
},
+ [0x3244]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH QUESTION",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x554F },
+ unicodeslot=0x3244,
+ },
+ [0x3245]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH KINDERGARTEN",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5E7C },
+ unicodeslot=0x3245,
+ },
+ [0x3246]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH SCHOOL",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x6587 },
+ unicodeslot=0x3246,
+ },
+ [0x3247]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH KOTO",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x7B8F },
+ unicodeslot=0x3247,
+ },
+ [0x3248]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER TEN ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x3248,
+ },
+ [0x3249]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER TWENTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x3249,
+ },
+ [0x324A]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER THIRTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324A,
+ },
+ [0x324B]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER FORTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324B,
+ },
+ [0x324C]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER FIFTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324C,
+ },
+ [0x324D]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER SIXTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324D,
+ },
+ [0x324E]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER SEVENTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324E,
+ },
+ [0x324F]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED NUMBER EIGHTY ON BLACK SQUARE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x324F,
+ },
[0x3250]={
category="so",
cjkwd="w",
@@ -96709,6 +105238,3618 @@ characters.data={
linebreak="id",
unicodeslot=0xA4C6,
},
+ [0xA4D0]={
+ category="lo",
+ description="LISU LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D0,
+ },
+ [0xA4D1]={
+ category="lo",
+ description="LISU LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D1,
+ },
+ [0xA4D2]={
+ category="lo",
+ description="LISU LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D2,
+ },
+ [0xA4D3]={
+ category="lo",
+ description="LISU LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D3,
+ },
+ [0xA4D4]={
+ category="lo",
+ description="LISU LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D4,
+ },
+ [0xA4D5]={
+ category="lo",
+ description="LISU LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D5,
+ },
+ [0xA4D6]={
+ category="lo",
+ description="LISU LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D6,
+ },
+ [0xA4D7]={
+ category="lo",
+ description="LISU LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D7,
+ },
+ [0xA4D8]={
+ category="lo",
+ description="LISU LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D8,
+ },
+ [0xA4D9]={
+ category="lo",
+ description="LISU LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4D9,
+ },
+ [0xA4DA]={
+ category="lo",
+ description="LISU LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DA,
+ },
+ [0xA4DB]={
+ category="lo",
+ description="LISU LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DB,
+ },
+ [0xA4DC]={
+ category="lo",
+ description="LISU LETTER DZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DC,
+ },
+ [0xA4DD]={
+ category="lo",
+ description="LISU LETTER TSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DD,
+ },
+ [0xA4DE]={
+ category="lo",
+ description="LISU LETTER TSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DE,
+ },
+ [0xA4DF]={
+ category="lo",
+ description="LISU LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4DF,
+ },
+ [0xA4E0]={
+ category="lo",
+ description="LISU LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E0,
+ },
+ [0xA4E1]={
+ category="lo",
+ description="LISU LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E1,
+ },
+ [0xA4E2]={
+ category="lo",
+ description="LISU LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E2,
+ },
+ [0xA4E3]={
+ category="lo",
+ description="LISU LETTER ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E3,
+ },
+ [0xA4E4]={
+ category="lo",
+ description="LISU LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E4,
+ },
+ [0xA4E5]={
+ category="lo",
+ description="LISU LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E5,
+ },
+ [0xA4E6]={
+ category="lo",
+ description="LISU LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E6,
+ },
+ [0xA4E7]={
+ category="lo",
+ description="LISU LETTER XA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E7,
+ },
+ [0xA4E8]={
+ category="lo",
+ description="LISU LETTER HHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E8,
+ },
+ [0xA4E9]={
+ category="lo",
+ description="LISU LETTER FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4E9,
+ },
+ [0xA4EA]={
+ category="lo",
+ description="LISU LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EA,
+ },
+ [0xA4EB]={
+ category="lo",
+ description="LISU LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EB,
+ },
+ [0xA4EC]={
+ category="lo",
+ description="LISU LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EC,
+ },
+ [0xA4ED]={
+ category="lo",
+ description="LISU LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4ED,
+ },
+ [0xA4EE]={
+ category="lo",
+ description="LISU LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EE,
+ },
+ [0xA4EF]={
+ category="lo",
+ description="LISU LETTER AE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4EF,
+ },
+ [0xA4F0]={
+ category="lo",
+ description="LISU LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F0,
+ },
+ [0xA4F1]={
+ category="lo",
+ description="LISU LETTER EU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F1,
+ },
+ [0xA4F2]={
+ category="lo",
+ description="LISU LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F2,
+ },
+ [0xA4F3]={
+ category="lo",
+ description="LISU LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F3,
+ },
+ [0xA4F4]={
+ category="lo",
+ description="LISU LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F4,
+ },
+ [0xA4F5]={
+ category="lo",
+ description="LISU LETTER UE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F5,
+ },
+ [0xA4F6]={
+ category="lo",
+ description="LISU LETTER UH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F6,
+ },
+ [0xA4F7]={
+ category="lo",
+ description="LISU LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F7,
+ },
+ [0xA4F8]={
+ category="lm",
+ description="LISU LETTER TONE MYA TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F8,
+ },
+ [0xA4F9]={
+ category="lm",
+ description="LISU LETTER TONE NA PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4F9,
+ },
+ [0xA4FA]={
+ category="lm",
+ description="LISU LETTER TONE MYA CYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4FA,
+ },
+ [0xA4FB]={
+ category="lm",
+ description="LISU LETTER TONE MYA BO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4FB,
+ },
+ [0xA4FC]={
+ category="lm",
+ description="LISU LETTER TONE MYA NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4FC,
+ },
+ [0xA4FD]={
+ category="lm",
+ description="LISU LETTER TONE MYA JEU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA4FD,
+ },
+ [0xA4FE]={
+ category="po",
+ description="LISU PUNCTUATION COMMA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA4FE,
+ },
+ [0xA4FF]={
+ category="po",
+ description="LISU PUNCTUATION FULL STOP",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA4FF,
+ },
+ [0xA500]={
+ category="lo",
+ description="VAI SYLLABLE EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA500,
+ },
+ [0xA501]={
+ category="lo",
+ description="VAI SYLLABLE EEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA501,
+ },
+ [0xA502]={
+ category="lo",
+ description="VAI SYLLABLE HEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA502,
+ },
+ [0xA503]={
+ category="lo",
+ description="VAI SYLLABLE WEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA503,
+ },
+ [0xA504]={
+ category="lo",
+ description="VAI SYLLABLE WEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA504,
+ },
+ [0xA505]={
+ category="lo",
+ description="VAI SYLLABLE PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA505,
+ },
+ [0xA506]={
+ category="lo",
+ description="VAI SYLLABLE BHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA506,
+ },
+ [0xA507]={
+ category="lo",
+ description="VAI SYLLABLE BEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA507,
+ },
+ [0xA508]={
+ category="lo",
+ description="VAI SYLLABLE MBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA508,
+ },
+ [0xA509]={
+ category="lo",
+ description="VAI SYLLABLE KPEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA509,
+ },
+ [0xA50A]={
+ category="lo",
+ description="VAI SYLLABLE MGBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50A,
+ },
+ [0xA50B]={
+ category="lo",
+ description="VAI SYLLABLE GBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50B,
+ },
+ [0xA50C]={
+ category="lo",
+ description="VAI SYLLABLE FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50C,
+ },
+ [0xA50D]={
+ category="lo",
+ description="VAI SYLLABLE VEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50D,
+ },
+ [0xA50E]={
+ category="lo",
+ description="VAI SYLLABLE TEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50E,
+ },
+ [0xA50F]={
+ category="lo",
+ description="VAI SYLLABLE THEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA50F,
+ },
+ [0xA510]={
+ category="lo",
+ description="VAI SYLLABLE DHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA510,
+ },
+ [0xA511]={
+ category="lo",
+ description="VAI SYLLABLE DHHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA511,
+ },
+ [0xA512]={
+ category="lo",
+ description="VAI SYLLABLE LEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA512,
+ },
+ [0xA513]={
+ category="lo",
+ description="VAI SYLLABLE REE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA513,
+ },
+ [0xA514]={
+ category="lo",
+ description="VAI SYLLABLE DEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA514,
+ },
+ [0xA515]={
+ category="lo",
+ description="VAI SYLLABLE NDEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA515,
+ },
+ [0xA516]={
+ category="lo",
+ description="VAI SYLLABLE SEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA516,
+ },
+ [0xA517]={
+ category="lo",
+ description="VAI SYLLABLE SHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA517,
+ },
+ [0xA518]={
+ category="lo",
+ description="VAI SYLLABLE ZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA518,
+ },
+ [0xA519]={
+ category="lo",
+ description="VAI SYLLABLE ZHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA519,
+ },
+ [0xA51A]={
+ category="lo",
+ description="VAI SYLLABLE CEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51A,
+ },
+ [0xA51B]={
+ category="lo",
+ description="VAI SYLLABLE JEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51B,
+ },
+ [0xA51C]={
+ category="lo",
+ description="VAI SYLLABLE NJEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51C,
+ },
+ [0xA51D]={
+ category="lo",
+ description="VAI SYLLABLE YEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51D,
+ },
+ [0xA51E]={
+ category="lo",
+ description="VAI SYLLABLE KEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51E,
+ },
+ [0xA51F]={
+ category="lo",
+ description="VAI SYLLABLE NGGEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA51F,
+ },
+ [0xA520]={
+ category="lo",
+ description="VAI SYLLABLE GEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA520,
+ },
+ [0xA521]={
+ category="lo",
+ description="VAI SYLLABLE MEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA521,
+ },
+ [0xA522]={
+ category="lo",
+ description="VAI SYLLABLE NEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA522,
+ },
+ [0xA523]={
+ category="lo",
+ description="VAI SYLLABLE NYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA523,
+ },
+ [0xA524]={
+ category="lo",
+ description="VAI SYLLABLE I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA524,
+ },
+ [0xA525]={
+ category="lo",
+ description="VAI SYLLABLE IN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA525,
+ },
+ [0xA526]={
+ category="lo",
+ description="VAI SYLLABLE HI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA526,
+ },
+ [0xA527]={
+ category="lo",
+ description="VAI SYLLABLE HIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA527,
+ },
+ [0xA528]={
+ category="lo",
+ description="VAI SYLLABLE WI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA528,
+ },
+ [0xA529]={
+ category="lo",
+ description="VAI SYLLABLE WIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA529,
+ },
+ [0xA52A]={
+ category="lo",
+ description="VAI SYLLABLE PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52A,
+ },
+ [0xA52B]={
+ category="lo",
+ description="VAI SYLLABLE BHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52B,
+ },
+ [0xA52C]={
+ category="lo",
+ description="VAI SYLLABLE BI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52C,
+ },
+ [0xA52D]={
+ category="lo",
+ description="VAI SYLLABLE MBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52D,
+ },
+ [0xA52E]={
+ category="lo",
+ description="VAI SYLLABLE KPI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52E,
+ },
+ [0xA52F]={
+ category="lo",
+ description="VAI SYLLABLE MGBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA52F,
+ },
+ [0xA530]={
+ category="lo",
+ description="VAI SYLLABLE GBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA530,
+ },
+ [0xA531]={
+ category="lo",
+ description="VAI SYLLABLE FI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA531,
+ },
+ [0xA532]={
+ category="lo",
+ description="VAI SYLLABLE VI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA532,
+ },
+ [0xA533]={
+ category="lo",
+ description="VAI SYLLABLE TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA533,
+ },
+ [0xA534]={
+ category="lo",
+ description="VAI SYLLABLE THI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA534,
+ },
+ [0xA535]={
+ category="lo",
+ description="VAI SYLLABLE DHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA535,
+ },
+ [0xA536]={
+ category="lo",
+ description="VAI SYLLABLE DHHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA536,
+ },
+ [0xA537]={
+ category="lo",
+ description="VAI SYLLABLE LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA537,
+ },
+ [0xA538]={
+ category="lo",
+ description="VAI SYLLABLE RI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA538,
+ },
+ [0xA539]={
+ category="lo",
+ description="VAI SYLLABLE DI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA539,
+ },
+ [0xA53A]={
+ category="lo",
+ description="VAI SYLLABLE NDI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53A,
+ },
+ [0xA53B]={
+ category="lo",
+ description="VAI SYLLABLE SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53B,
+ },
+ [0xA53C]={
+ category="lo",
+ description="VAI SYLLABLE SHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53C,
+ },
+ [0xA53D]={
+ category="lo",
+ description="VAI SYLLABLE ZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53D,
+ },
+ [0xA53E]={
+ category="lo",
+ description="VAI SYLLABLE ZHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53E,
+ },
+ [0xA53F]={
+ category="lo",
+ description="VAI SYLLABLE CI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA53F,
+ },
+ [0xA540]={
+ category="lo",
+ description="VAI SYLLABLE JI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA540,
+ },
+ [0xA541]={
+ category="lo",
+ description="VAI SYLLABLE NJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA541,
+ },
+ [0xA542]={
+ category="lo",
+ description="VAI SYLLABLE YI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA542,
+ },
+ [0xA543]={
+ category="lo",
+ description="VAI SYLLABLE KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA543,
+ },
+ [0xA544]={
+ category="lo",
+ description="VAI SYLLABLE NGGI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA544,
+ },
+ [0xA545]={
+ category="lo",
+ description="VAI SYLLABLE GI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA545,
+ },
+ [0xA546]={
+ category="lo",
+ description="VAI SYLLABLE MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA546,
+ },
+ [0xA547]={
+ category="lo",
+ description="VAI SYLLABLE NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA547,
+ },
+ [0xA548]={
+ category="lo",
+ description="VAI SYLLABLE NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA548,
+ },
+ [0xA549]={
+ category="lo",
+ description="VAI SYLLABLE A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA549,
+ },
+ [0xA54A]={
+ category="lo",
+ description="VAI SYLLABLE AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54A,
+ },
+ [0xA54B]={
+ category="lo",
+ description="VAI SYLLABLE NGAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54B,
+ },
+ [0xA54C]={
+ category="lo",
+ description="VAI SYLLABLE HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54C,
+ },
+ [0xA54D]={
+ category="lo",
+ description="VAI SYLLABLE HAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54D,
+ },
+ [0xA54E]={
+ category="lo",
+ description="VAI SYLLABLE WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54E,
+ },
+ [0xA54F]={
+ category="lo",
+ description="VAI SYLLABLE WAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA54F,
+ },
+ [0xA550]={
+ category="lo",
+ description="VAI SYLLABLE PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA550,
+ },
+ [0xA551]={
+ category="lo",
+ description="VAI SYLLABLE BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA551,
+ },
+ [0xA552]={
+ category="lo",
+ description="VAI SYLLABLE BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA552,
+ },
+ [0xA553]={
+ category="lo",
+ description="VAI SYLLABLE MBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA553,
+ },
+ [0xA554]={
+ category="lo",
+ description="VAI SYLLABLE KPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA554,
+ },
+ [0xA555]={
+ category="lo",
+ description="VAI SYLLABLE KPAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA555,
+ },
+ [0xA556]={
+ category="lo",
+ description="VAI SYLLABLE MGBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA556,
+ },
+ [0xA557]={
+ category="lo",
+ description="VAI SYLLABLE GBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA557,
+ },
+ [0xA558]={
+ category="lo",
+ description="VAI SYLLABLE FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA558,
+ },
+ [0xA559]={
+ category="lo",
+ description="VAI SYLLABLE VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA559,
+ },
+ [0xA55A]={
+ category="lo",
+ description="VAI SYLLABLE TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55A,
+ },
+ [0xA55B]={
+ category="lo",
+ description="VAI SYLLABLE THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55B,
+ },
+ [0xA55C]={
+ category="lo",
+ description="VAI SYLLABLE DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55C,
+ },
+ [0xA55D]={
+ category="lo",
+ description="VAI SYLLABLE DHHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55D,
+ },
+ [0xA55E]={
+ category="lo",
+ description="VAI SYLLABLE LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55E,
+ },
+ [0xA55F]={
+ category="lo",
+ description="VAI SYLLABLE RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA55F,
+ },
+ [0xA560]={
+ category="lo",
+ description="VAI SYLLABLE DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA560,
+ },
+ [0xA561]={
+ category="lo",
+ description="VAI SYLLABLE NDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA561,
+ },
+ [0xA562]={
+ category="lo",
+ description="VAI SYLLABLE SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA562,
+ },
+ [0xA563]={
+ category="lo",
+ description="VAI SYLLABLE SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA563,
+ },
+ [0xA564]={
+ category="lo",
+ description="VAI SYLLABLE ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA564,
+ },
+ [0xA565]={
+ category="lo",
+ description="VAI SYLLABLE ZHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA565,
+ },
+ [0xA566]={
+ category="lo",
+ description="VAI SYLLABLE CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA566,
+ },
+ [0xA567]={
+ category="lo",
+ description="VAI SYLLABLE JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA567,
+ },
+ [0xA568]={
+ category="lo",
+ description="VAI SYLLABLE NJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA568,
+ },
+ [0xA569]={
+ category="lo",
+ description="VAI SYLLABLE YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA569,
+ },
+ [0xA56A]={
+ category="lo",
+ description="VAI SYLLABLE KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56A,
+ },
+ [0xA56B]={
+ category="lo",
+ description="VAI SYLLABLE KAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56B,
+ },
+ [0xA56C]={
+ category="lo",
+ description="VAI SYLLABLE NGGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56C,
+ },
+ [0xA56D]={
+ category="lo",
+ description="VAI SYLLABLE GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56D,
+ },
+ [0xA56E]={
+ category="lo",
+ description="VAI SYLLABLE MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56E,
+ },
+ [0xA56F]={
+ category="lo",
+ description="VAI SYLLABLE NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA56F,
+ },
+ [0xA570]={
+ category="lo",
+ description="VAI SYLLABLE NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA570,
+ },
+ [0xA571]={
+ category="lo",
+ description="VAI SYLLABLE OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA571,
+ },
+ [0xA572]={
+ category="lo",
+ description="VAI SYLLABLE OON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA572,
+ },
+ [0xA573]={
+ category="lo",
+ description="VAI SYLLABLE HOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA573,
+ },
+ [0xA574]={
+ category="lo",
+ description="VAI SYLLABLE WOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA574,
+ },
+ [0xA575]={
+ category="lo",
+ description="VAI SYLLABLE WOON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA575,
+ },
+ [0xA576]={
+ category="lo",
+ description="VAI SYLLABLE POO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA576,
+ },
+ [0xA577]={
+ category="lo",
+ description="VAI SYLLABLE BHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA577,
+ },
+ [0xA578]={
+ category="lo",
+ description="VAI SYLLABLE BOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA578,
+ },
+ [0xA579]={
+ category="lo",
+ description="VAI SYLLABLE MBOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA579,
+ },
+ [0xA57A]={
+ category="lo",
+ description="VAI SYLLABLE KPOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57A,
+ },
+ [0xA57B]={
+ category="lo",
+ description="VAI SYLLABLE MGBOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57B,
+ },
+ [0xA57C]={
+ category="lo",
+ description="VAI SYLLABLE GBOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57C,
+ },
+ [0xA57D]={
+ category="lo",
+ description="VAI SYLLABLE FOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57D,
+ },
+ [0xA57E]={
+ category="lo",
+ description="VAI SYLLABLE VOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57E,
+ },
+ [0xA57F]={
+ category="lo",
+ description="VAI SYLLABLE TOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA57F,
+ },
+ [0xA580]={
+ category="lo",
+ description="VAI SYLLABLE THOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA580,
+ },
+ [0xA581]={
+ category="lo",
+ description="VAI SYLLABLE DHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA581,
+ },
+ [0xA582]={
+ category="lo",
+ description="VAI SYLLABLE DHHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA582,
+ },
+ [0xA583]={
+ category="lo",
+ description="VAI SYLLABLE LOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA583,
+ },
+ [0xA584]={
+ category="lo",
+ description="VAI SYLLABLE ROO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA584,
+ },
+ [0xA585]={
+ category="lo",
+ description="VAI SYLLABLE DOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA585,
+ },
+ [0xA586]={
+ category="lo",
+ description="VAI SYLLABLE NDOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA586,
+ },
+ [0xA587]={
+ category="lo",
+ description="VAI SYLLABLE SOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA587,
+ },
+ [0xA588]={
+ category="lo",
+ description="VAI SYLLABLE SHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA588,
+ },
+ [0xA589]={
+ category="lo",
+ description="VAI SYLLABLE ZOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA589,
+ },
+ [0xA58A]={
+ category="lo",
+ description="VAI SYLLABLE ZHOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58A,
+ },
+ [0xA58B]={
+ category="lo",
+ description="VAI SYLLABLE COO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58B,
+ },
+ [0xA58C]={
+ category="lo",
+ description="VAI SYLLABLE JOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58C,
+ },
+ [0xA58D]={
+ category="lo",
+ description="VAI SYLLABLE NJOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58D,
+ },
+ [0xA58E]={
+ category="lo",
+ description="VAI SYLLABLE YOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58E,
+ },
+ [0xA58F]={
+ category="lo",
+ description="VAI SYLLABLE KOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA58F,
+ },
+ [0xA590]={
+ category="lo",
+ description="VAI SYLLABLE NGGOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA590,
+ },
+ [0xA591]={
+ category="lo",
+ description="VAI SYLLABLE GOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA591,
+ },
+ [0xA592]={
+ category="lo",
+ description="VAI SYLLABLE MOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA592,
+ },
+ [0xA593]={
+ category="lo",
+ description="VAI SYLLABLE NOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA593,
+ },
+ [0xA594]={
+ category="lo",
+ description="VAI SYLLABLE NYOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA594,
+ },
+ [0xA595]={
+ category="lo",
+ description="VAI SYLLABLE U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA595,
+ },
+ [0xA596]={
+ category="lo",
+ description="VAI SYLLABLE UN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA596,
+ },
+ [0xA597]={
+ category="lo",
+ description="VAI SYLLABLE HU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA597,
+ },
+ [0xA598]={
+ category="lo",
+ description="VAI SYLLABLE HUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA598,
+ },
+ [0xA599]={
+ category="lo",
+ description="VAI SYLLABLE WU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA599,
+ },
+ [0xA59A]={
+ category="lo",
+ description="VAI SYLLABLE WUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59A,
+ },
+ [0xA59B]={
+ category="lo",
+ description="VAI SYLLABLE PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59B,
+ },
+ [0xA59C]={
+ category="lo",
+ description="VAI SYLLABLE BHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59C,
+ },
+ [0xA59D]={
+ category="lo",
+ description="VAI SYLLABLE BU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59D,
+ },
+ [0xA59E]={
+ category="lo",
+ description="VAI SYLLABLE MBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59E,
+ },
+ [0xA59F]={
+ category="lo",
+ description="VAI SYLLABLE KPU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA59F,
+ },
+ [0xA5A0]={
+ category="lo",
+ description="VAI SYLLABLE MGBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A0,
+ },
+ [0xA5A1]={
+ category="lo",
+ description="VAI SYLLABLE GBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A1,
+ },
+ [0xA5A2]={
+ category="lo",
+ description="VAI SYLLABLE FU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A2,
+ },
+ [0xA5A3]={
+ category="lo",
+ description="VAI SYLLABLE VU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A3,
+ },
+ [0xA5A4]={
+ category="lo",
+ description="VAI SYLLABLE TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A4,
+ },
+ [0xA5A5]={
+ category="lo",
+ description="VAI SYLLABLE THU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A5,
+ },
+ [0xA5A6]={
+ category="lo",
+ description="VAI SYLLABLE DHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A6,
+ },
+ [0xA5A7]={
+ category="lo",
+ description="VAI SYLLABLE DHHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A7,
+ },
+ [0xA5A8]={
+ category="lo",
+ description="VAI SYLLABLE LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A8,
+ },
+ [0xA5A9]={
+ category="lo",
+ description="VAI SYLLABLE RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5A9,
+ },
+ [0xA5AA]={
+ category="lo",
+ description="VAI SYLLABLE DU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AA,
+ },
+ [0xA5AB]={
+ category="lo",
+ description="VAI SYLLABLE NDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AB,
+ },
+ [0xA5AC]={
+ category="lo",
+ description="VAI SYLLABLE SU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AC,
+ },
+ [0xA5AD]={
+ category="lo",
+ description="VAI SYLLABLE SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AD,
+ },
+ [0xA5AE]={
+ category="lo",
+ description="VAI SYLLABLE ZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AE,
+ },
+ [0xA5AF]={
+ category="lo",
+ description="VAI SYLLABLE ZHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5AF,
+ },
+ [0xA5B0]={
+ category="lo",
+ description="VAI SYLLABLE CU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B0,
+ },
+ [0xA5B1]={
+ category="lo",
+ description="VAI SYLLABLE JU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B1,
+ },
+ [0xA5B2]={
+ category="lo",
+ description="VAI SYLLABLE NJU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B2,
+ },
+ [0xA5B3]={
+ category="lo",
+ description="VAI SYLLABLE YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B3,
+ },
+ [0xA5B4]={
+ category="lo",
+ description="VAI SYLLABLE KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B4,
+ },
+ [0xA5B5]={
+ category="lo",
+ description="VAI SYLLABLE NGGU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B5,
+ },
+ [0xA5B6]={
+ category="lo",
+ description="VAI SYLLABLE GU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B6,
+ },
+ [0xA5B7]={
+ category="lo",
+ description="VAI SYLLABLE MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B7,
+ },
+ [0xA5B8]={
+ category="lo",
+ description="VAI SYLLABLE NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B8,
+ },
+ [0xA5B9]={
+ category="lo",
+ description="VAI SYLLABLE NYU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5B9,
+ },
+ [0xA5BA]={
+ category="lo",
+ description="VAI SYLLABLE O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BA,
+ },
+ [0xA5BB]={
+ category="lo",
+ description="VAI SYLLABLE ON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BB,
+ },
+ [0xA5BC]={
+ category="lo",
+ description="VAI SYLLABLE NGON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BC,
+ },
+ [0xA5BD]={
+ category="lo",
+ description="VAI SYLLABLE HO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BD,
+ },
+ [0xA5BE]={
+ category="lo",
+ description="VAI SYLLABLE HON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BE,
+ },
+ [0xA5BF]={
+ category="lo",
+ description="VAI SYLLABLE WO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5BF,
+ },
+ [0xA5C0]={
+ category="lo",
+ description="VAI SYLLABLE WON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C0,
+ },
+ [0xA5C1]={
+ category="lo",
+ description="VAI SYLLABLE PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C1,
+ },
+ [0xA5C2]={
+ category="lo",
+ description="VAI SYLLABLE BHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C2,
+ },
+ [0xA5C3]={
+ category="lo",
+ description="VAI SYLLABLE BO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C3,
+ },
+ [0xA5C4]={
+ category="lo",
+ description="VAI SYLLABLE MBO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C4,
+ },
+ [0xA5C5]={
+ category="lo",
+ description="VAI SYLLABLE KPO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C5,
+ },
+ [0xA5C6]={
+ category="lo",
+ description="VAI SYLLABLE MGBO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C6,
+ },
+ [0xA5C7]={
+ category="lo",
+ description="VAI SYLLABLE GBO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C7,
+ },
+ [0xA5C8]={
+ category="lo",
+ description="VAI SYLLABLE GBON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C8,
+ },
+ [0xA5C9]={
+ category="lo",
+ description="VAI SYLLABLE FO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5C9,
+ },
+ [0xA5CA]={
+ category="lo",
+ description="VAI SYLLABLE VO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CA,
+ },
+ [0xA5CB]={
+ category="lo",
+ description="VAI SYLLABLE TO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CB,
+ },
+ [0xA5CC]={
+ category="lo",
+ description="VAI SYLLABLE THO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CC,
+ },
+ [0xA5CD]={
+ category="lo",
+ description="VAI SYLLABLE DHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CD,
+ },
+ [0xA5CE]={
+ category="lo",
+ description="VAI SYLLABLE DHHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CE,
+ },
+ [0xA5CF]={
+ category="lo",
+ description="VAI SYLLABLE LO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5CF,
+ },
+ [0xA5D0]={
+ category="lo",
+ description="VAI SYLLABLE RO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D0,
+ },
+ [0xA5D1]={
+ category="lo",
+ description="VAI SYLLABLE DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D1,
+ },
+ [0xA5D2]={
+ category="lo",
+ description="VAI SYLLABLE NDO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D2,
+ },
+ [0xA5D3]={
+ category="lo",
+ description="VAI SYLLABLE SO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D3,
+ },
+ [0xA5D4]={
+ category="lo",
+ description="VAI SYLLABLE SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D4,
+ },
+ [0xA5D5]={
+ category="lo",
+ description="VAI SYLLABLE ZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D5,
+ },
+ [0xA5D6]={
+ category="lo",
+ description="VAI SYLLABLE ZHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D6,
+ },
+ [0xA5D7]={
+ category="lo",
+ description="VAI SYLLABLE CO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D7,
+ },
+ [0xA5D8]={
+ category="lo",
+ description="VAI SYLLABLE JO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D8,
+ },
+ [0xA5D9]={
+ category="lo",
+ description="VAI SYLLABLE NJO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5D9,
+ },
+ [0xA5DA]={
+ category="lo",
+ description="VAI SYLLABLE YO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DA,
+ },
+ [0xA5DB]={
+ category="lo",
+ description="VAI SYLLABLE KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DB,
+ },
+ [0xA5DC]={
+ category="lo",
+ description="VAI SYLLABLE NGGO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DC,
+ },
+ [0xA5DD]={
+ category="lo",
+ description="VAI SYLLABLE GO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DD,
+ },
+ [0xA5DE]={
+ category="lo",
+ description="VAI SYLLABLE MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DE,
+ },
+ [0xA5DF]={
+ category="lo",
+ description="VAI SYLLABLE NO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5DF,
+ },
+ [0xA5E0]={
+ category="lo",
+ description="VAI SYLLABLE NYO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E0,
+ },
+ [0xA5E1]={
+ category="lo",
+ description="VAI SYLLABLE E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E1,
+ },
+ [0xA5E2]={
+ category="lo",
+ description="VAI SYLLABLE EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E2,
+ },
+ [0xA5E3]={
+ category="lo",
+ description="VAI SYLLABLE NGEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E3,
+ },
+ [0xA5E4]={
+ category="lo",
+ description="VAI SYLLABLE HE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E4,
+ },
+ [0xA5E5]={
+ category="lo",
+ description="VAI SYLLABLE HEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E5,
+ },
+ [0xA5E6]={
+ category="lo",
+ description="VAI SYLLABLE WE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E6,
+ },
+ [0xA5E7]={
+ category="lo",
+ description="VAI SYLLABLE WEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E7,
+ },
+ [0xA5E8]={
+ category="lo",
+ description="VAI SYLLABLE PE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E8,
+ },
+ [0xA5E9]={
+ category="lo",
+ description="VAI SYLLABLE BHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5E9,
+ },
+ [0xA5EA]={
+ category="lo",
+ description="VAI SYLLABLE BE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EA,
+ },
+ [0xA5EB]={
+ category="lo",
+ description="VAI SYLLABLE MBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EB,
+ },
+ [0xA5EC]={
+ category="lo",
+ description="VAI SYLLABLE KPE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EC,
+ },
+ [0xA5ED]={
+ category="lo",
+ description="VAI SYLLABLE KPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5ED,
+ },
+ [0xA5EE]={
+ category="lo",
+ description="VAI SYLLABLE MGBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EE,
+ },
+ [0xA5EF]={
+ category="lo",
+ description="VAI SYLLABLE GBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5EF,
+ },
+ [0xA5F0]={
+ category="lo",
+ description="VAI SYLLABLE GBEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F0,
+ },
+ [0xA5F1]={
+ category="lo",
+ description="VAI SYLLABLE FE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F1,
+ },
+ [0xA5F2]={
+ category="lo",
+ description="VAI SYLLABLE VE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F2,
+ },
+ [0xA5F3]={
+ category="lo",
+ description="VAI SYLLABLE TE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F3,
+ },
+ [0xA5F4]={
+ category="lo",
+ description="VAI SYLLABLE THE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F4,
+ },
+ [0xA5F5]={
+ category="lo",
+ description="VAI SYLLABLE DHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F5,
+ },
+ [0xA5F6]={
+ category="lo",
+ description="VAI SYLLABLE DHHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F6,
+ },
+ [0xA5F7]={
+ category="lo",
+ description="VAI SYLLABLE LE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F7,
+ },
+ [0xA5F8]={
+ category="lo",
+ description="VAI SYLLABLE RE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F8,
+ },
+ [0xA5F9]={
+ category="lo",
+ description="VAI SYLLABLE DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5F9,
+ },
+ [0xA5FA]={
+ category="lo",
+ description="VAI SYLLABLE NDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FA,
+ },
+ [0xA5FB]={
+ category="lo",
+ description="VAI SYLLABLE SE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FB,
+ },
+ [0xA5FC]={
+ category="lo",
+ description="VAI SYLLABLE SHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FC,
+ },
+ [0xA5FD]={
+ category="lo",
+ description="VAI SYLLABLE ZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FD,
+ },
+ [0xA5FE]={
+ category="lo",
+ description="VAI SYLLABLE ZHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FE,
+ },
+ [0xA5FF]={
+ category="lo",
+ description="VAI SYLLABLE CE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA5FF,
+ },
+ [0xA600]={
+ category="lo",
+ description="VAI SYLLABLE JE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA600,
+ },
+ [0xA601]={
+ category="lo",
+ description="VAI SYLLABLE NJE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA601,
+ },
+ [0xA602]={
+ category="lo",
+ description="VAI SYLLABLE YE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA602,
+ },
+ [0xA603]={
+ category="lo",
+ description="VAI SYLLABLE KE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA603,
+ },
+ [0xA604]={
+ category="lo",
+ description="VAI SYLLABLE NGGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA604,
+ },
+ [0xA605]={
+ category="lo",
+ description="VAI SYLLABLE NGGEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA605,
+ },
+ [0xA606]={
+ category="lo",
+ description="VAI SYLLABLE GE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA606,
+ },
+ [0xA607]={
+ category="lo",
+ description="VAI SYLLABLE GEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA607,
+ },
+ [0xA608]={
+ category="lo",
+ description="VAI SYLLABLE ME",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA608,
+ },
+ [0xA609]={
+ category="lo",
+ description="VAI SYLLABLE NE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA609,
+ },
+ [0xA60A]={
+ category="lo",
+ description="VAI SYLLABLE NYE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA60A,
+ },
+ [0xA60B]={
+ category="lo",
+ description="VAI SYLLABLE NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA60B,
+ },
+ [0xA60C]={
+ category="lm",
+ description="VAI SYLLABLE LENGTHENER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA60C,
+ },
+ [0xA60D]={
+ category="po",
+ description="VAI COMMA",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0xA60D,
+ },
+ [0xA60E]={
+ category="po",
+ description="VAI FULL STOP",
+ direction="on",
+ linebreak="ex",
+ unicodeslot=0xA60E,
+ },
+ [0xA60F]={
+ category="po",
+ description="VAI QUESTION MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0xA60F,
+ },
+ [0xA610]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA610,
+ },
+ [0xA611]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA611,
+ },
+ [0xA612]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE SOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA612,
+ },
+ [0xA613]={
+ category="lo",
+ description="VAI SYMBOL FEENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA613,
+ },
+ [0xA614]={
+ category="lo",
+ description="VAI SYMBOL KEENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA614,
+ },
+ [0xA615]={
+ category="lo",
+ description="VAI SYMBOL TING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA615,
+ },
+ [0xA616]={
+ category="lo",
+ description="VAI SYMBOL NII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA616,
+ },
+ [0xA617]={
+ category="lo",
+ description="VAI SYMBOL BANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA617,
+ },
+ [0xA618]={
+ category="lo",
+ description="VAI SYMBOL FAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA618,
+ },
+ [0xA619]={
+ category="lo",
+ description="VAI SYMBOL TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA619,
+ },
+ [0xA61A]={
+ category="lo",
+ description="VAI SYMBOL DANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61A,
+ },
+ [0xA61B]={
+ category="lo",
+ description="VAI SYMBOL DOONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61B,
+ },
+ [0xA61C]={
+ category="lo",
+ description="VAI SYMBOL KUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61C,
+ },
+ [0xA61D]={
+ category="lo",
+ description="VAI SYMBOL TONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61D,
+ },
+ [0xA61E]={
+ category="lo",
+ description="VAI SYMBOL DO-O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61E,
+ },
+ [0xA61F]={
+ category="lo",
+ description="VAI SYMBOL JONG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA61F,
+ },
+ [0xA620]={
+ category="nd",
+ description="VAI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA620,
+ },
+ [0xA621]={
+ category="nd",
+ description="VAI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA621,
+ },
+ [0xA622]={
+ category="nd",
+ description="VAI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA622,
+ },
+ [0xA623]={
+ category="nd",
+ description="VAI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA623,
+ },
+ [0xA624]={
+ category="nd",
+ description="VAI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA624,
+ },
+ [0xA625]={
+ category="nd",
+ description="VAI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA625,
+ },
+ [0xA626]={
+ category="nd",
+ description="VAI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA626,
+ },
+ [0xA627]={
+ category="nd",
+ description="VAI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA627,
+ },
+ [0xA628]={
+ category="nd",
+ description="VAI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA628,
+ },
+ [0xA629]={
+ category="nd",
+ description="VAI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA629,
+ },
+ [0xA62A]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA62A,
+ },
+ [0xA62B]={
+ category="lo",
+ description="VAI SYLLABLE NDOLE DO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA62B,
+ },
+ [0xA640]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER ZEMLYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA640,
+ },
+ [0xA641]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER ZEMLYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA641,
+ },
+ [0xA642]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DZELO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA642,
+ },
+ [0xA643]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DZELO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA643,
+ },
+ [0xA644]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER REVERSED DZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA644,
+ },
+ [0xA645]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER REVERSED DZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA645,
+ },
+ [0xA646]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER IOTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA646,
+ },
+ [0xA647]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER IOTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA647,
+ },
+ [0xA648]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DJERV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA648,
+ },
+ [0xA649]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DJERV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA649,
+ },
+ [0xA64A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER MONOGRAPH UK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64A,
+ },
+ [0xA64B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER MONOGRAPH UK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64B,
+ },
+ [0xA64C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER BROAD OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64C,
+ },
+ [0xA64D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER BROAD OMEGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64D,
+ },
+ [0xA64E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER NEUTRAL YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64E,
+ },
+ [0xA64F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER NEUTRAL YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA64F,
+ },
+ [0xA650]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER YERU WITH BACK YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA650,
+ },
+ [0xA651]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER YERU WITH BACK YER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA651,
+ },
+ [0xA652]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED YAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA652,
+ },
+ [0xA653]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER IOTIFIED YAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA653,
+ },
+ [0xA654]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER REVERSED YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA654,
+ },
+ [0xA655]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER REVERSED YU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA655,
+ },
+ [0xA656]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA656,
+ },
+ [0xA657]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER IOTIFIED A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA657,
+ },
+ [0xA658]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA658,
+ },
+ [0xA659]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER CLOSED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA659,
+ },
+ [0xA65A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER BLENDED YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65A,
+ },
+ [0xA65B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER BLENDED YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65B,
+ },
+ [0xA65C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65C,
+ },
+ [0xA65D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65D,
+ },
+ [0xA65E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65E,
+ },
+ [0xA65F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER YN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA65F,
+ },
+ [0xA660]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER REVERSED TSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA660,
+ },
+ [0xA661]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER REVERSED TSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA661,
+ },
+ [0xA662]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SOFT DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA662,
+ },
+ [0xA663]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SOFT DE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA663,
+ },
+ [0xA664]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SOFT EL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA664,
+ },
+ [0xA665]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SOFT EL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA665,
+ },
+ [0xA666]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SOFT EM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA666,
+ },
+ [0xA667]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SOFT EM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA667,
+ },
+ [0xA668]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER MONOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA668,
+ },
+ [0xA669]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER MONOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA669,
+ },
+ [0xA66A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER BINOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66A,
+ },
+ [0xA66B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER BINOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66B,
+ },
+ [0xA66C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66C,
+ },
+ [0xA66D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DOUBLE MONOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66D,
+ },
+ [0xA66E]={
+ category="lo",
+ description="CYRILLIC LETTER MULTIOCULAR O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA66E,
+ },
+ [0xA66F]={
+ category="mn",
+ description="COMBINING CYRILLIC VZMET",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA66F,
+ },
+ [0xA670]={
+ category="me",
+ description="COMBINING CYRILLIC TEN MILLIONS SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA670,
+ },
+ [0xA671]={
+ category="me",
+ description="COMBINING CYRILLIC HUNDRED MILLIONS SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA671,
+ },
+ [0xA672]={
+ category="me",
+ description="COMBINING CYRILLIC THOUSAND MILLIONS SIGN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA672,
+ },
+ [0xA673]={
+ category="po",
+ description="SLAVONIC ASTERISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA673,
+ },
+ [0xA67C]={
+ category="mn",
+ description="COMBINING CYRILLIC KAVYKA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA67C,
+ },
+ [0xA67D]={
+ category="mn",
+ description="COMBINING CYRILLIC PAYEROK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA67D,
+ },
+ [0xA67E]={
+ category="po",
+ description="CYRILLIC KAVYKA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA67E,
+ },
+ [0xA67F]={
+ category="lm",
+ description="CYRILLIC PAYEROK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA67F,
+ },
+ [0xA680]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA680,
+ },
+ [0xA681]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA681,
+ },
+ [0xA682]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DZWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA682,
+ },
+ [0xA683]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DZWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA683,
+ },
+ [0xA684]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER ZHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA684,
+ },
+ [0xA685]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER ZHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA685,
+ },
+ [0xA686]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER CCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA686,
+ },
+ [0xA687]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER CCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA687,
+ },
+ [0xA688]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER DZZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA688,
+ },
+ [0xA689]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER DZZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA689,
+ },
+ [0xA68A]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68A,
+ },
+ [0xA68B]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68B,
+ },
+ [0xA68C]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68C,
+ },
+ [0xA68D]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68D,
+ },
+ [0xA68E]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TSWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68E,
+ },
+ [0xA68F]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TSWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA68F,
+ },
+ [0xA690]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TSSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA690,
+ },
+ [0xA691]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TSSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA691,
+ },
+ [0xA692]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER TCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA692,
+ },
+ [0xA693]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER TCHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA693,
+ },
+ [0xA694]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER HWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA694,
+ },
+ [0xA695]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER HWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA695,
+ },
+ [0xA696]={
+ category="lu",
+ description="CYRILLIC CAPITAL LETTER SHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA696,
+ },
+ [0xA697]={
+ category="ll",
+ description="CYRILLIC SMALL LETTER SHWE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA697,
+ },
+ [0xA6A0]={
+ category="lo",
+ description="BAMUM LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A0,
+ },
+ [0xA6A1]={
+ category="lo",
+ description="BAMUM LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A1,
+ },
+ [0xA6A2]={
+ category="lo",
+ description="BAMUM LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A2,
+ },
+ [0xA6A3]={
+ category="lo",
+ description="BAMUM LETTER KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A3,
+ },
+ [0xA6A4]={
+ category="lo",
+ description="BAMUM LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A4,
+ },
+ [0xA6A5]={
+ category="lo",
+ description="BAMUM LETTER REE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A5,
+ },
+ [0xA6A6]={
+ category="lo",
+ description="BAMUM LETTER TAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A6,
+ },
+ [0xA6A7]={
+ category="lo",
+ description="BAMUM LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A7,
+ },
+ [0xA6A8]={
+ category="lo",
+ description="BAMUM LETTER NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A8,
+ },
+ [0xA6A9]={
+ category="lo",
+ description="BAMUM LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6A9,
+ },
+ [0xA6AA]={
+ category="lo",
+ description="BAMUM LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AA,
+ },
+ [0xA6AB]={
+ category="lo",
+ description="BAMUM LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AB,
+ },
+ [0xA6AC]={
+ category="lo",
+ description="BAMUM LETTER RII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AC,
+ },
+ [0xA6AD]={
+ category="lo",
+ description="BAMUM LETTER RIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AD,
+ },
+ [0xA6AE]={
+ category="lo",
+ description="BAMUM LETTER LEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AE,
+ },
+ [0xA6AF]={
+ category="lo",
+ description="BAMUM LETTER MEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6AF,
+ },
+ [0xA6B0]={
+ category="lo",
+ description="BAMUM LETTER TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B0,
+ },
+ [0xA6B1]={
+ category="lo",
+ description="BAMUM LETTER NDAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B1,
+ },
+ [0xA6B2]={
+ category="lo",
+ description="BAMUM LETTER NJAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B2,
+ },
+ [0xA6B3]={
+ category="lo",
+ description="BAMUM LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B3,
+ },
+ [0xA6B4]={
+ category="lo",
+ description="BAMUM LETTER SUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B4,
+ },
+ [0xA6B5]={
+ category="lo",
+ description="BAMUM LETTER MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B5,
+ },
+ [0xA6B6]={
+ category="lo",
+ description="BAMUM LETTER SHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B6,
+ },
+ [0xA6B7]={
+ category="lo",
+ description="BAMUM LETTER SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B7,
+ },
+ [0xA6B8]={
+ category="lo",
+ description="BAMUM LETTER SHEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B8,
+ },
+ [0xA6B9]={
+ category="lo",
+ description="BAMUM LETTER SEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6B9,
+ },
+ [0xA6BA]={
+ category="lo",
+ description="BAMUM LETTER KYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BA,
+ },
+ [0xA6BB]={
+ category="lo",
+ description="BAMUM LETTER KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BB,
+ },
+ [0xA6BC]={
+ category="lo",
+ description="BAMUM LETTER NUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BC,
+ },
+ [0xA6BD]={
+ category="lo",
+ description="BAMUM LETTER NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BD,
+ },
+ [0xA6BE]={
+ category="lo",
+ description="BAMUM LETTER NJUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BE,
+ },
+ [0xA6BF]={
+ category="lo",
+ description="BAMUM LETTER YOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6BF,
+ },
+ [0xA6C0]={
+ category="lo",
+ description="BAMUM LETTER SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C0,
+ },
+ [0xA6C1]={
+ category="lo",
+ description="BAMUM LETTER YUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C1,
+ },
+ [0xA6C2]={
+ category="lo",
+ description="BAMUM LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C2,
+ },
+ [0xA6C3]={
+ category="lo",
+ description="BAMUM LETTER NSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C3,
+ },
+ [0xA6C4]={
+ category="lo",
+ description="BAMUM LETTER KEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C4,
+ },
+ [0xA6C5]={
+ category="lo",
+ description="BAMUM LETTER PEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C5,
+ },
+ [0xA6C6]={
+ category="lo",
+ description="BAMUM LETTER NJEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C6,
+ },
+ [0xA6C7]={
+ category="lo",
+ description="BAMUM LETTER NTEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C7,
+ },
+ [0xA6C8]={
+ category="lo",
+ description="BAMUM LETTER PUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C8,
+ },
+ [0xA6C9]={
+ category="lo",
+ description="BAMUM LETTER WUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6C9,
+ },
+ [0xA6CA]={
+ category="lo",
+ description="BAMUM LETTER PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CA,
+ },
+ [0xA6CB]={
+ category="lo",
+ description="BAMUM LETTER FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CB,
+ },
+ [0xA6CC]={
+ category="lo",
+ description="BAMUM LETTER RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CC,
+ },
+ [0xA6CD]={
+ category="lo",
+ description="BAMUM LETTER LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CD,
+ },
+ [0xA6CE]={
+ category="lo",
+ description="BAMUM LETTER MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CE,
+ },
+ [0xA6CF]={
+ category="lo",
+ description="BAMUM LETTER NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6CF,
+ },
+ [0xA6D0]={
+ category="lo",
+ description="BAMUM LETTER REUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D0,
+ },
+ [0xA6D1]={
+ category="lo",
+ description="BAMUM LETTER RAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D1,
+ },
+ [0xA6D2]={
+ category="lo",
+ description="BAMUM LETTER KEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D2,
+ },
+ [0xA6D3]={
+ category="lo",
+ description="BAMUM LETTER NGKWAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D3,
+ },
+ [0xA6D4]={
+ category="lo",
+ description="BAMUM LETTER NGGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D4,
+ },
+ [0xA6D5]={
+ category="lo",
+ description="BAMUM LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D5,
+ },
+ [0xA6D6]={
+ category="lo",
+ description="BAMUM LETTER SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D6,
+ },
+ [0xA6D7]={
+ category="lo",
+ description="BAMUM LETTER PUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D7,
+ },
+ [0xA6D8]={
+ category="lo",
+ description="BAMUM LETTER FU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D8,
+ },
+ [0xA6D9]={
+ category="lo",
+ description="BAMUM LETTER FOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6D9,
+ },
+ [0xA6DA]={
+ category="lo",
+ description="BAMUM LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DA,
+ },
+ [0xA6DB]={
+ category="lo",
+ description="BAMUM LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DB,
+ },
+ [0xA6DC]={
+ category="lo",
+ description="BAMUM LETTER LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DC,
+ },
+ [0xA6DD]={
+ category="lo",
+ description="BAMUM LETTER PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DD,
+ },
+ [0xA6DE]={
+ category="lo",
+ description="BAMUM LETTER LOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DE,
+ },
+ [0xA6DF]={
+ category="lo",
+ description="BAMUM LETTER KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6DF,
+ },
+ [0xA6E0]={
+ category="lo",
+ description="BAMUM LETTER MBEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E0,
+ },
+ [0xA6E1]={
+ category="lo",
+ description="BAMUM LETTER REN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E1,
+ },
+ [0xA6E2]={
+ category="lo",
+ description="BAMUM LETTER MEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E2,
+ },
+ [0xA6E3]={
+ category="lo",
+ description="BAMUM LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E3,
+ },
+ [0xA6E4]={
+ category="lo",
+ description="BAMUM LETTER TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E4,
+ },
+ [0xA6E5]={
+ category="lo",
+ description="BAMUM LETTER KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E5,
+ },
+ [0xA6E6]={
+ category="nl",
+ description="BAMUM LETTER MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E6,
+ },
+ [0xA6E7]={
+ category="nl",
+ description="BAMUM LETTER MBAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E7,
+ },
+ [0xA6E8]={
+ category="nl",
+ description="BAMUM LETTER TET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E8,
+ },
+ [0xA6E9]={
+ category="nl",
+ description="BAMUM LETTER KPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6E9,
+ },
+ [0xA6EA]={
+ category="nl",
+ description="BAMUM LETTER TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EA,
+ },
+ [0xA6EB]={
+ category="nl",
+ description="BAMUM LETTER NTUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EB,
+ },
+ [0xA6EC]={
+ category="nl",
+ description="BAMUM LETTER SAMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EC,
+ },
+ [0xA6ED]={
+ category="nl",
+ description="BAMUM LETTER FAAMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6ED,
+ },
+ [0xA6EE]={
+ category="nl",
+ description="BAMUM LETTER KOVUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EE,
+ },
+ [0xA6EF]={
+ category="nl",
+ description="BAMUM LETTER KOGHOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6EF,
+ },
+ [0xA6F0]={
+ category="mn",
+ description="BAMUM COMBINING MARK KOQNDON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA6F0,
+ },
+ [0xA6F1]={
+ category="mn",
+ description="BAMUM COMBINING MARK TUKWENTIS",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA6F1,
+ },
+ [0xA6F2]={
+ category="po",
+ description="BAMUM NJAEMLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA6F2,
+ },
+ [0xA6F3]={
+ category="po",
+ description="BAMUM FULL STOP",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F3,
+ },
+ [0xA6F4]={
+ category="po",
+ description="BAMUM COLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F4,
+ },
+ [0xA6F5]={
+ category="po",
+ description="BAMUM COMMA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F5,
+ },
+ [0xA6F6]={
+ category="po",
+ description="BAMUM SEMICOLON",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F6,
+ },
+ [0xA6F7]={
+ category="po",
+ description="BAMUM QUESTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA6F7,
+ },
[0xA700]={
category="sk",
description="MODIFIER LETTER CHINESE TONE YIN PING",
@@ -96898,6 +109039,41 @@ characters.data={
linebreak="al",
unicodeslot=0xA71A,
},
+ [0xA71B]={
+ category="lm",
+ description="MODIFIER LETTER RAISED UP ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71B,
+ },
+ [0xA71C]={
+ category="lm",
+ description="MODIFIER LETTER RAISED DOWN ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71C,
+ },
+ [0xA71D]={
+ category="lm",
+ description="MODIFIER LETTER RAISED EXCLAMATION MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71D,
+ },
+ [0xA71E]={
+ category="lm",
+ description="MODIFIER LETTER RAISED INVERTED EXCLAMATION MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71E,
+ },
+ [0xA71F]={
+ category="lm",
+ description="MODIFIER LETTER LOW INVERTED EXCLAMATION MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA71F,
+ },
[0xA720]={
category="sk",
description="MODIFIER LETTER STRESS AND HIGH TONE",
@@ -96912,6 +109088,896 @@ characters.data={
linebreak="al",
unicodeslot=0xA721,
},
+ [0xA722]={
+ category="lu",
+ description="LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA722,
+ },
+ [0xA723]={
+ category="ll",
+ description="LATIN SMALL LETTER EGYPTOLOGICAL ALEF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA723,
+ },
+ [0xA724]={
+ category="lu",
+ description="LATIN CAPITAL LETTER EGYPTOLOGICAL AIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA724,
+ },
+ [0xA725]={
+ category="ll",
+ description="LATIN SMALL LETTER EGYPTOLOGICAL AIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA725,
+ },
+ [0xA726]={
+ category="lu",
+ description="LATIN CAPITAL LETTER HENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA726,
+ },
+ [0xA727]={
+ category="ll",
+ description="LATIN SMALL LETTER HENG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA727,
+ },
+ [0xA728]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA728,
+ },
+ [0xA729]={
+ category="ll",
+ description="LATIN SMALL LETTER TZ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA729,
+ },
+ [0xA72A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TRESILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72A,
+ },
+ [0xA72B]={
+ category="ll",
+ description="LATIN SMALL LETTER TRESILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72B,
+ },
+ [0xA72C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER CUATRILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72C,
+ },
+ [0xA72D]={
+ category="ll",
+ description="LATIN SMALL LETTER CUATRILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72D,
+ },
+ [0xA72E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER CUATRILLO WITH COMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72E,
+ },
+ [0xA72F]={
+ category="ll",
+ description="LATIN SMALL LETTER CUATRILLO WITH COMMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA72F,
+ },
+ [0xA730]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA730,
+ },
+ [0xA731]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA731,
+ },
+ [0xA732]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA732,
+ },
+ [0xA733]={
+ category="ll",
+ description="LATIN SMALL LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA733,
+ },
+ [0xA734]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA734,
+ },
+ [0xA735]={
+ category="ll",
+ description="LATIN SMALL LETTER AO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA735,
+ },
+ [0xA736]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA736,
+ },
+ [0xA737]={
+ category="ll",
+ description="LATIN SMALL LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA737,
+ },
+ [0xA738]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA738,
+ },
+ [0xA739]={
+ category="ll",
+ description="LATIN SMALL LETTER AV",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA739,
+ },
+ [0xA73A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73A,
+ },
+ [0xA73B]={
+ category="ll",
+ description="LATIN SMALL LETTER AV WITH HORIZONTAL BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73B,
+ },
+ [0xA73C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER AY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73C,
+ },
+ [0xA73D]={
+ category="ll",
+ description="LATIN SMALL LETTER AY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73D,
+ },
+ [0xA73E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER REVERSED C WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73E,
+ },
+ [0xA73F]={
+ category="ll",
+ description="LATIN SMALL LETTER REVERSED C WITH DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA73F,
+ },
+ [0xA740]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA740,
+ },
+ [0xA741]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA741,
+ },
+ [0xA742]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA742,
+ },
+ [0xA743]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA743,
+ },
+ [0xA744]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA744,
+ },
+ [0xA745]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA745,
+ },
+ [0xA746]={
+ category="lu",
+ description="LATIN CAPITAL LETTER BROKEN L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA746,
+ },
+ [0xA747]={
+ category="ll",
+ description="LATIN SMALL LETTER BROKEN L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA747,
+ },
+ [0xA748]={
+ category="lu",
+ description="LATIN CAPITAL LETTER L WITH HIGH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA748,
+ },
+ [0xA749]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH HIGH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA749,
+ },
+ [0xA74A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74A,
+ },
+ [0xA74B]={
+ category="ll",
+ description="LATIN SMALL LETTER O WITH LONG STROKE OVERLAY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74B,
+ },
+ [0xA74C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER O WITH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74C,
+ },
+ [0xA74D]={
+ category="ll",
+ description="LATIN SMALL LETTER O WITH LOOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74D,
+ },
+ [0xA74E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74E,
+ },
+ [0xA74F]={
+ category="ll",
+ description="LATIN SMALL LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA74F,
+ },
+ [0xA750]={
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA750,
+ },
+ [0xA751]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA751,
+ },
+ [0xA752]={
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH FLOURISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA752,
+ },
+ [0xA753]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH FLOURISH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA753,
+ },
+ [0xA754]={
+ category="lu",
+ description="LATIN CAPITAL LETTER P WITH SQUIRREL TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA754,
+ },
+ [0xA755]={
+ category="ll",
+ description="LATIN SMALL LETTER P WITH SQUIRREL TAIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA755,
+ },
+ [0xA756]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA756,
+ },
+ [0xA757]={
+ category="ll",
+ description="LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA757,
+ },
+ [0xA758]={
+ category="lu",
+ description="LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA758,
+ },
+ [0xA759]={
+ category="ll",
+ description="LATIN SMALL LETTER Q WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA759,
+ },
+ [0xA75A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER R ROTUNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75A,
+ },
+ [0xA75B]={
+ category="ll",
+ description="LATIN SMALL LETTER R ROTUNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75B,
+ },
+ [0xA75C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER RUM ROTUNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75C,
+ },
+ [0xA75D]={
+ category="ll",
+ description="LATIN SMALL LETTER RUM ROTUNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75D,
+ },
+ [0xA75E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER V WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75E,
+ },
+ [0xA75F]={
+ category="ll",
+ description="LATIN SMALL LETTER V WITH DIAGONAL STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA75F,
+ },
+ [0xA760]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA760,
+ },
+ [0xA761]={
+ category="ll",
+ description="LATIN SMALL LETTER VY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA761,
+ },
+ [0xA762]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VISIGOTHIC Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA762,
+ },
+ [0xA763]={
+ category="ll",
+ description="LATIN SMALL LETTER VISIGOTHIC Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA763,
+ },
+ [0xA764]={
+ category="lu",
+ description="LATIN CAPITAL LETTER THORN WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA764,
+ },
+ [0xA765]={
+ category="ll",
+ description="LATIN SMALL LETTER THORN WITH STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA765,
+ },
+ [0xA766]={
+ category="lu",
+ description="LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA766,
+ },
+ [0xA767]={
+ category="ll",
+ description="LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA767,
+ },
+ [0xA768]={
+ category="lu",
+ description="LATIN CAPITAL LETTER VEND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA768,
+ },
+ [0xA769]={
+ category="ll",
+ description="LATIN SMALL LETTER VEND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA769,
+ },
+ [0xA76A]={
+ category="lu",
+ description="LATIN CAPITAL LETTER ET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76A,
+ },
+ [0xA76B]={
+ category="ll",
+ description="LATIN SMALL LETTER ET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76B,
+ },
+ [0xA76C]={
+ category="lu",
+ description="LATIN CAPITAL LETTER IS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76C,
+ },
+ [0xA76D]={
+ category="ll",
+ description="LATIN SMALL LETTER IS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76D,
+ },
+ [0xA76E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER CON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76E,
+ },
+ [0xA76F]={
+ category="ll",
+ description="LATIN SMALL LETTER CON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA76F,
+ },
+ [0xA770]={
+ category="lm",
+ description="MODIFIER LETTER US",
+ direction="l",
+ linebreak="al",
+ specials={ "super", 0xA76F },
+ unicodeslot=0xA770,
+ },
+ [0xA771]={
+ category="ll",
+ description="LATIN SMALL LETTER DUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA771,
+ },
+ [0xA772]={
+ category="ll",
+ description="LATIN SMALL LETTER LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA772,
+ },
+ [0xA773]={
+ category="ll",
+ description="LATIN SMALL LETTER MUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA773,
+ },
+ [0xA774]={
+ category="ll",
+ description="LATIN SMALL LETTER NUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA774,
+ },
+ [0xA775]={
+ category="ll",
+ description="LATIN SMALL LETTER RUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA775,
+ },
+ [0xA776]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL RUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA776,
+ },
+ [0xA777]={
+ category="ll",
+ description="LATIN SMALL LETTER TUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA777,
+ },
+ [0xA778]={
+ category="ll",
+ description="LATIN SMALL LETTER UM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA778,
+ },
+ [0xA779]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA779,
+ },
+ [0xA77A]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77A,
+ },
+ [0xA77B]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77B,
+ },
+ [0xA77C]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77C,
+ },
+ [0xA77D]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77D,
+ },
+ [0xA77E]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED INSULAR G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77E,
+ },
+ [0xA77F]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED INSULAR G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA77F,
+ },
+ [0xA780]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA780,
+ },
+ [0xA781]={
+ category="ll",
+ description="LATIN SMALL LETTER TURNED L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA781,
+ },
+ [0xA782]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA782,
+ },
+ [0xA783]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA783,
+ },
+ [0xA784]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA784,
+ },
+ [0xA785]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA785,
+ },
+ [0xA786]={
+ category="lu",
+ description="LATIN CAPITAL LETTER INSULAR T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA786,
+ },
+ [0xA787]={
+ category="ll",
+ description="LATIN SMALL LETTER INSULAR T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA787,
+ },
+ [0xA788]={
+ category="lm",
+ description="MODIFIER LETTER LOW CIRCUMFLEX ACCENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0xA788,
+ },
+ [0xA789]={
+ category="sk",
+ description="MODIFIER LETTER COLON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA789,
+ },
+ [0xA78A]={
+ category="sk",
+ description="MODIFIER LETTER SHORT EQUALS SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78A,
+ },
+ [0xA78B]={
+ category="lu",
+ description="LATIN CAPITAL LETTER SALTILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78B,
+ },
+ [0xA78C]={
+ category="ll",
+ description="LATIN SMALL LETTER SALTILLO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78C,
+ },
+ [0xA78D]={
+ category="lu",
+ description="LATIN CAPITAL LETTER TURNED H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78D,
+ },
+ [0xA78E]={
+ category="ll",
+ description="LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA78E,
+ },
+ [0xA790]={
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA790,
+ },
+ [0xA791]={
+ category="ll",
+ description="LATIN SMALL LETTER N WITH DESCENDER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA791,
+ },
+ [0xA7A0]={
+ category="lu",
+ description="LATIN CAPITAL LETTER G WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A0,
+ },
+ [0xA7A1]={
+ category="ll",
+ description="LATIN SMALL LETTER G WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A1,
+ },
+ [0xA7A2]={
+ category="lu",
+ description="LATIN CAPITAL LETTER K WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A2,
+ },
+ [0xA7A3]={
+ category="ll",
+ description="LATIN SMALL LETTER K WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A3,
+ },
+ [0xA7A4]={
+ category="lu",
+ description="LATIN CAPITAL LETTER N WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A4,
+ },
+ [0xA7A5]={
+ category="ll",
+ description="LATIN SMALL LETTER N WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A5,
+ },
+ [0xA7A6]={
+ category="lu",
+ description="LATIN CAPITAL LETTER R WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A6,
+ },
+ [0xA7A7]={
+ category="ll",
+ description="LATIN SMALL LETTER R WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A7,
+ },
+ [0xA7A8]={
+ category="lu",
+ description="LATIN CAPITAL LETTER S WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A8,
+ },
+ [0xA7A9]={
+ category="ll",
+ description="LATIN SMALL LETTER S WITH OBLIQUE STROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7A9,
+ },
+ [0xA7FA]={
+ category="ll",
+ description="LATIN LETTER SMALL CAPITAL TURNED M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FA,
+ },
+ [0xA7FB]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER REVERSED F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FB,
+ },
+ [0xA7FC]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER REVERSED P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FC,
+ },
+ [0xA7FD]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER INVERTED M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FD,
+ },
+ [0xA7FE]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER I LONGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FE,
+ },
+ [0xA7FF]={
+ category="lo",
+ description="LATIN EPIGRAPHIC LETTER ARCHAIC M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA7FF,
+ },
[0xA800]={
category="lo",
description="SYLOTI NAGRI LETTER A",
@@ -97220,6 +110286,76 @@ characters.data={
linebreak="al",
unicodeslot=0xA82B,
},
+ [0xA830]={
+ category="no",
+ description="NORTH INDIC FRACTION ONE QUARTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA830,
+ },
+ [0xA831]={
+ category="no",
+ description="NORTH INDIC FRACTION ONE HALF",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA831,
+ },
+ [0xA832]={
+ category="no",
+ description="NORTH INDIC FRACTION THREE QUARTERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA832,
+ },
+ [0xA833]={
+ category="no",
+ description="NORTH INDIC FRACTION ONE SIXTEENTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA833,
+ },
+ [0xA834]={
+ category="no",
+ description="NORTH INDIC FRACTION ONE EIGHTH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA834,
+ },
+ [0xA835]={
+ category="no",
+ description="NORTH INDIC FRACTION THREE SIXTEENTHS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA835,
+ },
+ [0xA836]={
+ category="so",
+ description="NORTH INDIC QUARTER MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA836,
+ },
+ [0xA837]={
+ category="so",
+ description="NORTH INDIC PLACEHOLDER MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA837,
+ },
+ [0xA838]={
+ category="sc",
+ description="NORTH INDIC RUPEE MARK",
+ direction="et",
+ linebreak="po",
+ unicodeslot=0xA838,
+ },
+ [0xA839]={
+ category="so",
+ description="NORTH INDIC QUANTITY MARK",
+ direction="et",
+ linebreak="al",
+ unicodeslot=0xA839,
+ },
[0xA840]={
category="lo",
description="PHAGS-PA LETTER KA",
@@ -97380,6 +110516,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0xA856,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping small a",
+ },
},
[0xA857]={
category="lo",
@@ -97422,6 +110561,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0xA85C,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping ha",
+ },
},
[0xA85D]={
category="lo",
@@ -97436,6 +110578,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0xA85E,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping i",
+ },
},
[0xA85F]={
category="lo",
@@ -97443,6 +110588,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0xA85F,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping u",
+ },
},
[0xA860]={
category="lo",
@@ -97450,6 +110598,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0xA860,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping e",
+ },
},
[0xA861]={
category="lo",
@@ -97506,6 +110657,9 @@ characters.data={
direction="l",
linebreak="al",
unicodeslot=0xA868,
+ variants={
+ [0xFE00]="phags-pa letter reversed shaping subjoined ya",
+ },
},
[0xA869]={
category="lo",
@@ -97612,6 +110766,4706 @@ characters.data={
linebreak="ex",
unicodeslot=0xA877,
},
+ [0xA880]={
+ category="mc",
+ description="SAURASHTRA SIGN ANUSVARA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA880,
+ },
+ [0xA881]={
+ category="mc",
+ description="SAURASHTRA SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA881,
+ },
+ [0xA882]={
+ category="lo",
+ description="SAURASHTRA LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA882,
+ },
+ [0xA883]={
+ category="lo",
+ description="SAURASHTRA LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA883,
+ },
+ [0xA884]={
+ category="lo",
+ description="SAURASHTRA LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA884,
+ },
+ [0xA885]={
+ category="lo",
+ description="SAURASHTRA LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA885,
+ },
+ [0xA886]={
+ category="lo",
+ description="SAURASHTRA LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA886,
+ },
+ [0xA887]={
+ category="lo",
+ description="SAURASHTRA LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA887,
+ },
+ [0xA888]={
+ category="lo",
+ description="SAURASHTRA LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA888,
+ },
+ [0xA889]={
+ category="lo",
+ description="SAURASHTRA LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA889,
+ },
+ [0xA88A]={
+ category="lo",
+ description="SAURASHTRA LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88A,
+ },
+ [0xA88B]={
+ category="lo",
+ description="SAURASHTRA LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88B,
+ },
+ [0xA88C]={
+ category="lo",
+ description="SAURASHTRA LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88C,
+ },
+ [0xA88D]={
+ category="lo",
+ description="SAURASHTRA LETTER EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88D,
+ },
+ [0xA88E]={
+ category="lo",
+ description="SAURASHTRA LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88E,
+ },
+ [0xA88F]={
+ category="lo",
+ description="SAURASHTRA LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA88F,
+ },
+ [0xA890]={
+ category="lo",
+ description="SAURASHTRA LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA890,
+ },
+ [0xA891]={
+ category="lo",
+ description="SAURASHTRA LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA891,
+ },
+ [0xA892]={
+ category="lo",
+ description="SAURASHTRA LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA892,
+ },
+ [0xA893]={
+ category="lo",
+ description="SAURASHTRA LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA893,
+ },
+ [0xA894]={
+ category="lo",
+ description="SAURASHTRA LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA894,
+ },
+ [0xA895]={
+ category="lo",
+ description="SAURASHTRA LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA895,
+ },
+ [0xA896]={
+ category="lo",
+ description="SAURASHTRA LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA896,
+ },
+ [0xA897]={
+ category="lo",
+ description="SAURASHTRA LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA897,
+ },
+ [0xA898]={
+ category="lo",
+ description="SAURASHTRA LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA898,
+ },
+ [0xA899]={
+ category="lo",
+ description="SAURASHTRA LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA899,
+ },
+ [0xA89A]={
+ category="lo",
+ description="SAURASHTRA LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89A,
+ },
+ [0xA89B]={
+ category="lo",
+ description="SAURASHTRA LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89B,
+ },
+ [0xA89C]={
+ category="lo",
+ description="SAURASHTRA LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89C,
+ },
+ [0xA89D]={
+ category="lo",
+ description="SAURASHTRA LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89D,
+ },
+ [0xA89E]={
+ category="lo",
+ description="SAURASHTRA LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89E,
+ },
+ [0xA89F]={
+ category="lo",
+ description="SAURASHTRA LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA89F,
+ },
+ [0xA8A0]={
+ category="lo",
+ description="SAURASHTRA LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A0,
+ },
+ [0xA8A1]={
+ category="lo",
+ description="SAURASHTRA LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A1,
+ },
+ [0xA8A2]={
+ category="lo",
+ description="SAURASHTRA LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A2,
+ },
+ [0xA8A3]={
+ category="lo",
+ description="SAURASHTRA LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A3,
+ },
+ [0xA8A4]={
+ category="lo",
+ description="SAURASHTRA LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A4,
+ },
+ [0xA8A5]={
+ category="lo",
+ description="SAURASHTRA LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A5,
+ },
+ [0xA8A6]={
+ category="lo",
+ description="SAURASHTRA LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A6,
+ },
+ [0xA8A7]={
+ category="lo",
+ description="SAURASHTRA LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A7,
+ },
+ [0xA8A8]={
+ category="lo",
+ description="SAURASHTRA LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A8,
+ },
+ [0xA8A9]={
+ category="lo",
+ description="SAURASHTRA LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8A9,
+ },
+ [0xA8AA]={
+ category="lo",
+ description="SAURASHTRA LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AA,
+ },
+ [0xA8AB]={
+ category="lo",
+ description="SAURASHTRA LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AB,
+ },
+ [0xA8AC]={
+ category="lo",
+ description="SAURASHTRA LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AC,
+ },
+ [0xA8AD]={
+ category="lo",
+ description="SAURASHTRA LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AD,
+ },
+ [0xA8AE]={
+ category="lo",
+ description="SAURASHTRA LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AE,
+ },
+ [0xA8AF]={
+ category="lo",
+ description="SAURASHTRA LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8AF,
+ },
+ [0xA8B0]={
+ category="lo",
+ description="SAURASHTRA LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B0,
+ },
+ [0xA8B1]={
+ category="lo",
+ description="SAURASHTRA LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B1,
+ },
+ [0xA8B2]={
+ category="lo",
+ description="SAURASHTRA LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B2,
+ },
+ [0xA8B3]={
+ category="lo",
+ description="SAURASHTRA LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8B3,
+ },
+ [0xA8B4]={
+ category="mc",
+ description="SAURASHTRA CONSONANT SIGN HAARU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B4,
+ },
+ [0xA8B5]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B5,
+ },
+ [0xA8B6]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B6,
+ },
+ [0xA8B7]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B7,
+ },
+ [0xA8B8]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN U",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B8,
+ },
+ [0xA8B9]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN UU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8B9,
+ },
+ [0xA8BA]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN VOCALIC R",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BA,
+ },
+ [0xA8BB]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN VOCALIC RR",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BB,
+ },
+ [0xA8BC]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN VOCALIC L",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BC,
+ },
+ [0xA8BD]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN VOCALIC LL",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BD,
+ },
+ [0xA8BE]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN E",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BE,
+ },
+ [0xA8BF]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN EE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8BF,
+ },
+ [0xA8C0]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8C0,
+ },
+ [0xA8C1]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8C1,
+ },
+ [0xA8C2]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN OO",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8C2,
+ },
+ [0xA8C3]={
+ category="mc",
+ description="SAURASHTRA VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA8C3,
+ },
+ [0xA8C4]={
+ category="mn",
+ description="SAURASHTRA SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8C4,
+ },
+ [0xA8CE]={
+ category="po",
+ description="SAURASHTRA DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA8CE,
+ },
+ [0xA8CF]={
+ category="po",
+ description="SAURASHTRA DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA8CF,
+ },
+ [0xA8D0]={
+ category="nd",
+ description="SAURASHTRA DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D0,
+ },
+ [0xA8D1]={
+ category="nd",
+ description="SAURASHTRA DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D1,
+ },
+ [0xA8D2]={
+ category="nd",
+ description="SAURASHTRA DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D2,
+ },
+ [0xA8D3]={
+ category="nd",
+ description="SAURASHTRA DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D3,
+ },
+ [0xA8D4]={
+ category="nd",
+ description="SAURASHTRA DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D4,
+ },
+ [0xA8D5]={
+ category="nd",
+ description="SAURASHTRA DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D5,
+ },
+ [0xA8D6]={
+ category="nd",
+ description="SAURASHTRA DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D6,
+ },
+ [0xA8D7]={
+ category="nd",
+ description="SAURASHTRA DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D7,
+ },
+ [0xA8D8]={
+ category="nd",
+ description="SAURASHTRA DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D8,
+ },
+ [0xA8D9]={
+ category="nd",
+ description="SAURASHTRA DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA8D9,
+ },
+ [0xA8E0]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT ZERO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E0,
+ },
+ [0xA8E1]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT ONE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E1,
+ },
+ [0xA8E2]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT TWO",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E2,
+ },
+ [0xA8E3]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT THREE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E3,
+ },
+ [0xA8E4]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT FOUR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E4,
+ },
+ [0xA8E5]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT FIVE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E5,
+ },
+ [0xA8E6]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT SIX",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E6,
+ },
+ [0xA8E7]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT SEVEN",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E7,
+ },
+ [0xA8E8]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT EIGHT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E8,
+ },
+ [0xA8E9]={
+ category="mn",
+ description="COMBINING DEVANAGARI DIGIT NINE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8E9,
+ },
+ [0xA8EA]={
+ category="mn",
+ description="COMBINING DEVANAGARI LETTER A",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EA,
+ },
+ [0xA8EB]={
+ category="mn",
+ description="COMBINING DEVANAGARI LETTER U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EB,
+ },
+ [0xA8EC]={
+ category="mn",
+ description="COMBINING DEVANAGARI LETTER KA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EC,
+ },
+ [0xA8ED]={
+ category="mn",
+ description="COMBINING DEVANAGARI LETTER NA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8ED,
+ },
+ [0xA8EE]={
+ category="mn",
+ description="COMBINING DEVANAGARI LETTER PA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EE,
+ },
+ [0xA8EF]={
+ category="mn",
+ description="COMBINING DEVANAGARI LETTER RA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8EF,
+ },
+ [0xA8F0]={
+ category="mn",
+ description="COMBINING DEVANAGARI LETTER VI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8F0,
+ },
+ [0xA8F1]={
+ category="mn",
+ description="COMBINING DEVANAGARI SIGN AVAGRAHA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA8F1,
+ },
+ [0xA8F2]={
+ category="lo",
+ description="DEVANAGARI SIGN SPACING CANDRABINDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F2,
+ },
+ [0xA8F3]={
+ category="lo",
+ description="DEVANAGARI SIGN CANDRABINDU VIRAMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F3,
+ },
+ [0xA8F4]={
+ category="lo",
+ description="DEVANAGARI SIGN DOUBLE CANDRABINDU VIRAMA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F4,
+ },
+ [0xA8F5]={
+ category="lo",
+ description="DEVANAGARI SIGN CANDRABINDU TWO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F5,
+ },
+ [0xA8F6]={
+ category="lo",
+ description="DEVANAGARI SIGN CANDRABINDU THREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F6,
+ },
+ [0xA8F7]={
+ category="lo",
+ description="DEVANAGARI SIGN CANDRABINDU AVAGRAHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F7,
+ },
+ [0xA8F8]={
+ category="po",
+ description="DEVANAGARI SIGN PUSHPIKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F8,
+ },
+ [0xA8F9]={
+ category="po",
+ description="DEVANAGARI GAP FILLER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8F9,
+ },
+ [0xA8FA]={
+ category="po",
+ description="DEVANAGARI CARET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8FA,
+ },
+ [0xA8FB]={
+ category="lo",
+ description="DEVANAGARI HEADSTROKE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA8FB,
+ },
+ [0xA900]={
+ category="nd",
+ description="KAYAH LI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA900,
+ },
+ [0xA901]={
+ category="nd",
+ description="KAYAH LI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA901,
+ },
+ [0xA902]={
+ category="nd",
+ description="KAYAH LI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA902,
+ },
+ [0xA903]={
+ category="nd",
+ description="KAYAH LI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA903,
+ },
+ [0xA904]={
+ category="nd",
+ description="KAYAH LI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA904,
+ },
+ [0xA905]={
+ category="nd",
+ description="KAYAH LI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA905,
+ },
+ [0xA906]={
+ category="nd",
+ description="KAYAH LI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA906,
+ },
+ [0xA907]={
+ category="nd",
+ description="KAYAH LI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA907,
+ },
+ [0xA908]={
+ category="nd",
+ description="KAYAH LI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA908,
+ },
+ [0xA909]={
+ category="nd",
+ description="KAYAH LI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA909,
+ },
+ [0xA90A]={
+ category="lo",
+ description="KAYAH LI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90A,
+ },
+ [0xA90B]={
+ category="lo",
+ description="KAYAH LI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90B,
+ },
+ [0xA90C]={
+ category="lo",
+ description="KAYAH LI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90C,
+ },
+ [0xA90D]={
+ category="lo",
+ description="KAYAH LI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90D,
+ },
+ [0xA90E]={
+ category="lo",
+ description="KAYAH LI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90E,
+ },
+ [0xA90F]={
+ category="lo",
+ description="KAYAH LI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA90F,
+ },
+ [0xA910]={
+ category="lo",
+ description="KAYAH LI LETTER ZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA910,
+ },
+ [0xA911]={
+ category="lo",
+ description="KAYAH LI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA911,
+ },
+ [0xA912]={
+ category="lo",
+ description="KAYAH LI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA912,
+ },
+ [0xA913]={
+ category="lo",
+ description="KAYAH LI LETTER HTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA913,
+ },
+ [0xA914]={
+ category="lo",
+ description="KAYAH LI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA914,
+ },
+ [0xA915]={
+ category="lo",
+ description="KAYAH LI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA915,
+ },
+ [0xA916]={
+ category="lo",
+ description="KAYAH LI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA916,
+ },
+ [0xA917]={
+ category="lo",
+ description="KAYAH LI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA917,
+ },
+ [0xA918]={
+ category="lo",
+ description="KAYAH LI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA918,
+ },
+ [0xA919]={
+ category="lo",
+ description="KAYAH LI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA919,
+ },
+ [0xA91A]={
+ category="lo",
+ description="KAYAH LI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91A,
+ },
+ [0xA91B]={
+ category="lo",
+ description="KAYAH LI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91B,
+ },
+ [0xA91C]={
+ category="lo",
+ description="KAYAH LI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91C,
+ },
+ [0xA91D]={
+ category="lo",
+ description="KAYAH LI LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91D,
+ },
+ [0xA91E]={
+ category="lo",
+ description="KAYAH LI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91E,
+ },
+ [0xA91F]={
+ category="lo",
+ description="KAYAH LI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA91F,
+ },
+ [0xA920]={
+ category="lo",
+ description="KAYAH LI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA920,
+ },
+ [0xA921]={
+ category="lo",
+ description="KAYAH LI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA921,
+ },
+ [0xA922]={
+ category="lo",
+ description="KAYAH LI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA922,
+ },
+ [0xA923]={
+ category="lo",
+ description="KAYAH LI LETTER OE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA923,
+ },
+ [0xA924]={
+ category="lo",
+ description="KAYAH LI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA924,
+ },
+ [0xA925]={
+ category="lo",
+ description="KAYAH LI LETTER OO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA925,
+ },
+ [0xA926]={
+ category="mn",
+ description="KAYAH LI VOWEL UE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA926,
+ },
+ [0xA927]={
+ category="mn",
+ description="KAYAH LI VOWEL E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA927,
+ },
+ [0xA928]={
+ category="mn",
+ description="KAYAH LI VOWEL U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA928,
+ },
+ [0xA929]={
+ category="mn",
+ description="KAYAH LI VOWEL EE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA929,
+ },
+ [0xA92A]={
+ category="mn",
+ description="KAYAH LI VOWEL O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA92A,
+ },
+ [0xA92B]={
+ category="mn",
+ description="KAYAH LI TONE PLOPHU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA92B,
+ },
+ [0xA92C]={
+ category="mn",
+ description="KAYAH LI TONE CALYA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA92C,
+ },
+ [0xA92D]={
+ category="mn",
+ description="KAYAH LI TONE CALYA PLOPHU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA92D,
+ },
+ [0xA92E]={
+ category="po",
+ description="KAYAH LI SIGN CWI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA92E,
+ },
+ [0xA92F]={
+ category="po",
+ description="KAYAH LI SIGN SHYA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA92F,
+ },
+ [0xA930]={
+ category="lo",
+ description="REJANG LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA930,
+ },
+ [0xA931]={
+ category="lo",
+ description="REJANG LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA931,
+ },
+ [0xA932]={
+ category="lo",
+ description="REJANG LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA932,
+ },
+ [0xA933]={
+ category="lo",
+ description="REJANG LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA933,
+ },
+ [0xA934]={
+ category="lo",
+ description="REJANG LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA934,
+ },
+ [0xA935]={
+ category="lo",
+ description="REJANG LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA935,
+ },
+ [0xA936]={
+ category="lo",
+ description="REJANG LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA936,
+ },
+ [0xA937]={
+ category="lo",
+ description="REJANG LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA937,
+ },
+ [0xA938]={
+ category="lo",
+ description="REJANG LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA938,
+ },
+ [0xA939]={
+ category="lo",
+ description="REJANG LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA939,
+ },
+ [0xA93A]={
+ category="lo",
+ description="REJANG LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93A,
+ },
+ [0xA93B]={
+ category="lo",
+ description="REJANG LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93B,
+ },
+ [0xA93C]={
+ category="lo",
+ description="REJANG LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93C,
+ },
+ [0xA93D]={
+ category="lo",
+ description="REJANG LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93D,
+ },
+ [0xA93E]={
+ category="lo",
+ description="REJANG LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93E,
+ },
+ [0xA93F]={
+ category="lo",
+ description="REJANG LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA93F,
+ },
+ [0xA940]={
+ category="lo",
+ description="REJANG LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA940,
+ },
+ [0xA941]={
+ category="lo",
+ description="REJANG LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA941,
+ },
+ [0xA942]={
+ category="lo",
+ description="REJANG LETTER MBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA942,
+ },
+ [0xA943]={
+ category="lo",
+ description="REJANG LETTER NGGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA943,
+ },
+ [0xA944]={
+ category="lo",
+ description="REJANG LETTER NDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA944,
+ },
+ [0xA945]={
+ category="lo",
+ description="REJANG LETTER NYJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA945,
+ },
+ [0xA946]={
+ category="lo",
+ description="REJANG LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA946,
+ },
+ [0xA947]={
+ category="mn",
+ description="REJANG VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA947,
+ },
+ [0xA948]={
+ category="mn",
+ description="REJANG VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA948,
+ },
+ [0xA949]={
+ category="mn",
+ description="REJANG VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA949,
+ },
+ [0xA94A]={
+ category="mn",
+ description="REJANG VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94A,
+ },
+ [0xA94B]={
+ category="mn",
+ description="REJANG VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94B,
+ },
+ [0xA94C]={
+ category="mn",
+ description="REJANG VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94C,
+ },
+ [0xA94D]={
+ category="mn",
+ description="REJANG VOWEL SIGN EU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94D,
+ },
+ [0xA94E]={
+ category="mn",
+ description="REJANG VOWEL SIGN EA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94E,
+ },
+ [0xA94F]={
+ category="mn",
+ description="REJANG CONSONANT SIGN NG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA94F,
+ },
+ [0xA950]={
+ category="mn",
+ description="REJANG CONSONANT SIGN N",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA950,
+ },
+ [0xA951]={
+ category="mn",
+ description="REJANG CONSONANT SIGN R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA951,
+ },
+ [0xA952]={
+ category="mc",
+ description="REJANG CONSONANT SIGN H",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA952,
+ },
+ [0xA953]={
+ category="mc",
+ description="REJANG VIRAMA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA953,
+ },
+ [0xA95F]={
+ category="po",
+ description="REJANG SECTION MARK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA95F,
+ },
+ [0xA960]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-MIEUM",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA960,
+ },
+ [0xA961]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA961,
+ },
+ [0xA962]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA962,
+ },
+ [0xA963]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG TIKEUT-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA963,
+ },
+ [0xA964]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA964,
+ },
+ [0xA965]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-SSANGKIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA965,
+ },
+ [0xA966]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA966,
+ },
+ [0xA967]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-SSANGTIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA967,
+ },
+ [0xA968]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-MIEUM",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA968,
+ },
+ [0xA969]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA969,
+ },
+ [0xA96A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-SSANGPIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96A,
+ },
+ [0xA96B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96B,
+ },
+ [0xA96C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96C,
+ },
+ [0xA96D]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-CIEUC",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96D,
+ },
+ [0xA96E]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG RIEUL-KHIEUKH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96E,
+ },
+ [0xA96F]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG MIEUM-KIYEOK",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA96F,
+ },
+ [0xA970]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG MIEUM-TIKEUT",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA970,
+ },
+ [0xA971]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG MIEUM-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA971,
+ },
+ [0xA972]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-SIOS-THIEUTH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA972,
+ },
+ [0xA973]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-KHIEUKH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA973,
+ },
+ [0xA974]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PIEUP-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA974,
+ },
+ [0xA975]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGSIOS-PIEUP",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA975,
+ },
+ [0xA976]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-RIEUL",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA976,
+ },
+ [0xA977]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG IEUNG-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA977,
+ },
+ [0xA978]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGCIEUC-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA978,
+ },
+ [0xA979]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGTHIEUTH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA979,
+ },
+ [0xA97A]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG PHIEUPH-HIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA97A,
+ },
+ [0xA97B]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG HIEUH-SIOS",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA97B,
+ },
+ [0xA97C]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL CHOSEONG SSANGYEORINHIEUH",
+ direction="l",
+ linebreak="jl",
+ unicodeslot=0xA97C,
+ },
+ [0xA980]={
+ category="mn",
+ description="JAVANESE SIGN PANYANGGA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA980,
+ },
+ [0xA981]={
+ category="mn",
+ description="JAVANESE SIGN CECAK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA981,
+ },
+ [0xA982]={
+ category="mn",
+ description="JAVANESE SIGN LAYAR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA982,
+ },
+ [0xA983]={
+ category="mc",
+ description="JAVANESE SIGN WIGNYAN",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA983,
+ },
+ [0xA984]={
+ category="lo",
+ description="JAVANESE LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA984,
+ },
+ [0xA985]={
+ category="lo",
+ description="JAVANESE LETTER I KAWI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA985,
+ },
+ [0xA986]={
+ category="lo",
+ description="JAVANESE LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA986,
+ },
+ [0xA987]={
+ category="lo",
+ description="JAVANESE LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA987,
+ },
+ [0xA988]={
+ category="lo",
+ description="JAVANESE LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA988,
+ },
+ [0xA989]={
+ category="lo",
+ description="JAVANESE LETTER PA CEREK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA989,
+ },
+ [0xA98A]={
+ category="lo",
+ description="JAVANESE LETTER NGA LELET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98A,
+ },
+ [0xA98B]={
+ category="lo",
+ description="JAVANESE LETTER NGA LELET RASWADI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98B,
+ },
+ [0xA98C]={
+ category="lo",
+ description="JAVANESE LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98C,
+ },
+ [0xA98D]={
+ category="lo",
+ description="JAVANESE LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98D,
+ },
+ [0xA98E]={
+ category="lo",
+ description="JAVANESE LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98E,
+ },
+ [0xA98F]={
+ category="lo",
+ description="JAVANESE LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA98F,
+ },
+ [0xA990]={
+ category="lo",
+ description="JAVANESE LETTER KA SASAK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA990,
+ },
+ [0xA991]={
+ category="lo",
+ description="JAVANESE LETTER KA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA991,
+ },
+ [0xA992]={
+ category="lo",
+ description="JAVANESE LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA992,
+ },
+ [0xA993]={
+ category="lo",
+ description="JAVANESE LETTER GA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA993,
+ },
+ [0xA994]={
+ category="lo",
+ description="JAVANESE LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA994,
+ },
+ [0xA995]={
+ category="lo",
+ description="JAVANESE LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA995,
+ },
+ [0xA996]={
+ category="lo",
+ description="JAVANESE LETTER CA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA996,
+ },
+ [0xA997]={
+ category="lo",
+ description="JAVANESE LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA997,
+ },
+ [0xA998]={
+ category="lo",
+ description="JAVANESE LETTER NYA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA998,
+ },
+ [0xA999]={
+ category="lo",
+ description="JAVANESE LETTER JA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA999,
+ },
+ [0xA99A]={
+ category="lo",
+ description="JAVANESE LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99A,
+ },
+ [0xA99B]={
+ category="lo",
+ description="JAVANESE LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99B,
+ },
+ [0xA99C]={
+ category="lo",
+ description="JAVANESE LETTER TTA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99C,
+ },
+ [0xA99D]={
+ category="lo",
+ description="JAVANESE LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99D,
+ },
+ [0xA99E]={
+ category="lo",
+ description="JAVANESE LETTER DDA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99E,
+ },
+ [0xA99F]={
+ category="lo",
+ description="JAVANESE LETTER NA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA99F,
+ },
+ [0xA9A0]={
+ category="lo",
+ description="JAVANESE LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A0,
+ },
+ [0xA9A1]={
+ category="lo",
+ description="JAVANESE LETTER TA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A1,
+ },
+ [0xA9A2]={
+ category="lo",
+ description="JAVANESE LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A2,
+ },
+ [0xA9A3]={
+ category="lo",
+ description="JAVANESE LETTER DA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A3,
+ },
+ [0xA9A4]={
+ category="lo",
+ description="JAVANESE LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A4,
+ },
+ [0xA9A5]={
+ category="lo",
+ description="JAVANESE LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A5,
+ },
+ [0xA9A6]={
+ category="lo",
+ description="JAVANESE LETTER PA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A6,
+ },
+ [0xA9A7]={
+ category="lo",
+ description="JAVANESE LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A7,
+ },
+ [0xA9A8]={
+ category="lo",
+ description="JAVANESE LETTER BA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A8,
+ },
+ [0xA9A9]={
+ category="lo",
+ description="JAVANESE LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9A9,
+ },
+ [0xA9AA]={
+ category="lo",
+ description="JAVANESE LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AA,
+ },
+ [0xA9AB]={
+ category="lo",
+ description="JAVANESE LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AB,
+ },
+ [0xA9AC]={
+ category="lo",
+ description="JAVANESE LETTER RA AGUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AC,
+ },
+ [0xA9AD]={
+ category="lo",
+ description="JAVANESE LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AD,
+ },
+ [0xA9AE]={
+ category="lo",
+ description="JAVANESE LETTER WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AE,
+ },
+ [0xA9AF]={
+ category="lo",
+ description="JAVANESE LETTER SA MURDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9AF,
+ },
+ [0xA9B0]={
+ category="lo",
+ description="JAVANESE LETTER SA MAHAPRANA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9B0,
+ },
+ [0xA9B1]={
+ category="lo",
+ description="JAVANESE LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9B1,
+ },
+ [0xA9B2]={
+ category="lo",
+ description="JAVANESE LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9B2,
+ },
+ [0xA9B3]={
+ category="mn",
+ description="JAVANESE SIGN CECAK TELU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B3,
+ },
+ [0xA9B4]={
+ category="mc",
+ description="JAVANESE VOWEL SIGN TARUNG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9B4,
+ },
+ [0xA9B5]={
+ category="mc",
+ description="JAVANESE VOWEL SIGN TOLONG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9B5,
+ },
+ [0xA9B6]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN WULU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B6,
+ },
+ [0xA9B7]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN WULU MELIK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B7,
+ },
+ [0xA9B8]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN SUKU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B8,
+ },
+ [0xA9B9]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN SUKU MENDUT",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9B9,
+ },
+ [0xA9BA]={
+ category="mc",
+ description="JAVANESE VOWEL SIGN TALING",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BA,
+ },
+ [0xA9BB]={
+ category="mc",
+ description="JAVANESE VOWEL SIGN DIRGA MURE",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BB,
+ },
+ [0xA9BC]={
+ category="mn",
+ description="JAVANESE VOWEL SIGN PEPET",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xA9BC,
+ },
+ [0xA9BD]={
+ category="mc",
+ description="JAVANESE CONSONANT SIGN KERET",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BD,
+ },
+ [0xA9BE]={
+ category="mc",
+ description="JAVANESE CONSONANT SIGN PENGKAL",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BE,
+ },
+ [0xA9BF]={
+ category="mc",
+ description="JAVANESE CONSONANT SIGN CAKRA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9BF,
+ },
+ [0xA9C0]={
+ category="mc",
+ description="JAVANESE PANGKON",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xA9C0,
+ },
+ [0xA9C1]={
+ category="po",
+ description="JAVANESE LEFT RERENGGAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C1,
+ },
+ [0xA9C2]={
+ category="po",
+ description="JAVANESE RIGHT RERENGGAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C2,
+ },
+ [0xA9C3]={
+ category="po",
+ description="JAVANESE PADA ANDAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C3,
+ },
+ [0xA9C4]={
+ category="po",
+ description="JAVANESE PADA MADYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C4,
+ },
+ [0xA9C5]={
+ category="po",
+ description="JAVANESE PADA LUHUR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C5,
+ },
+ [0xA9C6]={
+ category="po",
+ description="JAVANESE PADA WINDU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9C6,
+ },
+ [0xA9C7]={
+ category="po",
+ description="JAVANESE PADA PANGKAT",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA9C7,
+ },
+ [0xA9C8]={
+ category="po",
+ description="JAVANESE PADA LINGSA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA9C8,
+ },
+ [0xA9C9]={
+ category="po",
+ description="JAVANESE PADA LUNGSI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xA9C9,
+ },
+ [0xA9CA]={
+ category="po",
+ description="JAVANESE PADA ADEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CA,
+ },
+ [0xA9CB]={
+ category="po",
+ description="JAVANESE PADA ADEG ADEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CB,
+ },
+ [0xA9CC]={
+ category="po",
+ description="JAVANESE PADA PISELEH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CC,
+ },
+ [0xA9CD]={
+ category="po",
+ description="JAVANESE TURNED PADA PISELEH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CD,
+ },
+ [0xA9CF]={
+ category="lm",
+ description="JAVANESE PANGRANGKEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9CF,
+ },
+ [0xA9D0]={
+ category="nd",
+ description="JAVANESE DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D0,
+ },
+ [0xA9D1]={
+ category="nd",
+ description="JAVANESE DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D1,
+ },
+ [0xA9D2]={
+ category="nd",
+ description="JAVANESE DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D2,
+ },
+ [0xA9D3]={
+ category="nd",
+ description="JAVANESE DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D3,
+ },
+ [0xA9D4]={
+ category="nd",
+ description="JAVANESE DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D4,
+ },
+ [0xA9D5]={
+ category="nd",
+ description="JAVANESE DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D5,
+ },
+ [0xA9D6]={
+ category="nd",
+ description="JAVANESE DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D6,
+ },
+ [0xA9D7]={
+ category="nd",
+ description="JAVANESE DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D7,
+ },
+ [0xA9D8]={
+ category="nd",
+ description="JAVANESE DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D8,
+ },
+ [0xA9D9]={
+ category="nd",
+ description="JAVANESE DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xA9D9,
+ },
+ [0xA9DE]={
+ category="po",
+ description="JAVANESE PADA TIRTA TUMETES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9DE,
+ },
+ [0xA9DF]={
+ category="po",
+ description="JAVANESE PADA ISEN-ISEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xA9DF,
+ },
+ [0xAA00]={
+ category="lo",
+ description="CHAM LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA00,
+ },
+ [0xAA01]={
+ category="lo",
+ description="CHAM LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA01,
+ },
+ [0xAA02]={
+ category="lo",
+ description="CHAM LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA02,
+ },
+ [0xAA03]={
+ category="lo",
+ description="CHAM LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA03,
+ },
+ [0xAA04]={
+ category="lo",
+ description="CHAM LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA04,
+ },
+ [0xAA05]={
+ category="lo",
+ description="CHAM LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA05,
+ },
+ [0xAA06]={
+ category="lo",
+ description="CHAM LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA06,
+ },
+ [0xAA07]={
+ category="lo",
+ description="CHAM LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA07,
+ },
+ [0xAA08]={
+ category="lo",
+ description="CHAM LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA08,
+ },
+ [0xAA09]={
+ category="lo",
+ description="CHAM LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA09,
+ },
+ [0xAA0A]={
+ category="lo",
+ description="CHAM LETTER NGUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0A,
+ },
+ [0xAA0B]={
+ category="lo",
+ description="CHAM LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0B,
+ },
+ [0xAA0C]={
+ category="lo",
+ description="CHAM LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0C,
+ },
+ [0xAA0D]={
+ category="lo",
+ description="CHAM LETTER CHHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0D,
+ },
+ [0xAA0E]={
+ category="lo",
+ description="CHAM LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0E,
+ },
+ [0xAA0F]={
+ category="lo",
+ description="CHAM LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA0F,
+ },
+ [0xAA10]={
+ category="lo",
+ description="CHAM LETTER NHUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA10,
+ },
+ [0xAA11]={
+ category="lo",
+ description="CHAM LETTER NHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA11,
+ },
+ [0xAA12]={
+ category="lo",
+ description="CHAM LETTER NHJA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA12,
+ },
+ [0xAA13]={
+ category="lo",
+ description="CHAM LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA13,
+ },
+ [0xAA14]={
+ category="lo",
+ description="CHAM LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA14,
+ },
+ [0xAA15]={
+ category="lo",
+ description="CHAM LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA15,
+ },
+ [0xAA16]={
+ category="lo",
+ description="CHAM LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA16,
+ },
+ [0xAA17]={
+ category="lo",
+ description="CHAM LETTER NUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA17,
+ },
+ [0xAA18]={
+ category="lo",
+ description="CHAM LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA18,
+ },
+ [0xAA19]={
+ category="lo",
+ description="CHAM LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA19,
+ },
+ [0xAA1A]={
+ category="lo",
+ description="CHAM LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1A,
+ },
+ [0xAA1B]={
+ category="lo",
+ description="CHAM LETTER PPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1B,
+ },
+ [0xAA1C]={
+ category="lo",
+ description="CHAM LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1C,
+ },
+ [0xAA1D]={
+ category="lo",
+ description="CHAM LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1D,
+ },
+ [0xAA1E]={
+ category="lo",
+ description="CHAM LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1E,
+ },
+ [0xAA1F]={
+ category="lo",
+ description="CHAM LETTER MUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA1F,
+ },
+ [0xAA20]={
+ category="lo",
+ description="CHAM LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA20,
+ },
+ [0xAA21]={
+ category="lo",
+ description="CHAM LETTER BBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA21,
+ },
+ [0xAA22]={
+ category="lo",
+ description="CHAM LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA22,
+ },
+ [0xAA23]={
+ category="lo",
+ description="CHAM LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA23,
+ },
+ [0xAA24]={
+ category="lo",
+ description="CHAM LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA24,
+ },
+ [0xAA25]={
+ category="lo",
+ description="CHAM LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA25,
+ },
+ [0xAA26]={
+ category="lo",
+ description="CHAM LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA26,
+ },
+ [0xAA27]={
+ category="lo",
+ description="CHAM LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA27,
+ },
+ [0xAA28]={
+ category="lo",
+ description="CHAM LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA28,
+ },
+ [0xAA29]={
+ category="mn",
+ description="CHAM VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA29,
+ },
+ [0xAA2A]={
+ category="mn",
+ description="CHAM VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2A,
+ },
+ [0xAA2B]={
+ category="mn",
+ description="CHAM VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2B,
+ },
+ [0xAA2C]={
+ category="mn",
+ description="CHAM VOWEL SIGN EI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2C,
+ },
+ [0xAA2D]={
+ category="mn",
+ description="CHAM VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2D,
+ },
+ [0xAA2E]={
+ category="mn",
+ description="CHAM VOWEL SIGN OE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA2E,
+ },
+ [0xAA2F]={
+ category="mc",
+ description="CHAM VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA2F,
+ },
+ [0xAA30]={
+ category="mc",
+ description="CHAM VOWEL SIGN AI",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA30,
+ },
+ [0xAA31]={
+ category="mn",
+ description="CHAM VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA31,
+ },
+ [0xAA32]={
+ category="mn",
+ description="CHAM VOWEL SIGN UE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA32,
+ },
+ [0xAA33]={
+ category="mc",
+ description="CHAM CONSONANT SIGN YA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA33,
+ },
+ [0xAA34]={
+ category="mc",
+ description="CHAM CONSONANT SIGN RA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA34,
+ },
+ [0xAA35]={
+ category="mn",
+ description="CHAM CONSONANT SIGN LA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA35,
+ },
+ [0xAA36]={
+ category="mn",
+ description="CHAM CONSONANT SIGN WA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA36,
+ },
+ [0xAA40]={
+ category="lo",
+ description="CHAM LETTER FINAL K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA40,
+ },
+ [0xAA41]={
+ category="lo",
+ description="CHAM LETTER FINAL G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA41,
+ },
+ [0xAA42]={
+ category="lo",
+ description="CHAM LETTER FINAL NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA42,
+ },
+ [0xAA43]={
+ category="mn",
+ description="CHAM CONSONANT SIGN FINAL NG",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA43,
+ },
+ [0xAA44]={
+ category="lo",
+ description="CHAM LETTER FINAL CH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA44,
+ },
+ [0xAA45]={
+ category="lo",
+ description="CHAM LETTER FINAL T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA45,
+ },
+ [0xAA46]={
+ category="lo",
+ description="CHAM LETTER FINAL N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA46,
+ },
+ [0xAA47]={
+ category="lo",
+ description="CHAM LETTER FINAL P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA47,
+ },
+ [0xAA48]={
+ category="lo",
+ description="CHAM LETTER FINAL Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA48,
+ },
+ [0xAA49]={
+ category="lo",
+ description="CHAM LETTER FINAL R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA49,
+ },
+ [0xAA4A]={
+ category="lo",
+ description="CHAM LETTER FINAL L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA4A,
+ },
+ [0xAA4B]={
+ category="lo",
+ description="CHAM LETTER FINAL SS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA4B,
+ },
+ [0xAA4C]={
+ category="mn",
+ description="CHAM CONSONANT SIGN FINAL M",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xAA4C,
+ },
+ [0xAA4D]={
+ category="mc",
+ description="CHAM CONSONANT SIGN FINAL H",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xAA4D,
+ },
+ [0xAA50]={
+ category="nd",
+ description="CHAM DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA50,
+ },
+ [0xAA51]={
+ category="nd",
+ description="CHAM DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA51,
+ },
+ [0xAA52]={
+ category="nd",
+ description="CHAM DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA52,
+ },
+ [0xAA53]={
+ category="nd",
+ description="CHAM DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA53,
+ },
+ [0xAA54]={
+ category="nd",
+ description="CHAM DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA54,
+ },
+ [0xAA55]={
+ category="nd",
+ description="CHAM DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA55,
+ },
+ [0xAA56]={
+ category="nd",
+ description="CHAM DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA56,
+ },
+ [0xAA57]={
+ category="nd",
+ description="CHAM DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA57,
+ },
+ [0xAA58]={
+ category="nd",
+ description="CHAM DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA58,
+ },
+ [0xAA59]={
+ category="nd",
+ description="CHAM DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xAA59,
+ },
+ [0xAA5C]={
+ category="po",
+ description="CHAM PUNCTUATION SPIRAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAA5C,
+ },
+ [0xAA5D]={
+ category="po",
+ description="CHAM PUNCTUATION DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAA5D,
+ },
+ [0xAA5E]={
+ category="po",
+ description="CHAM PUNCTUATION DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAA5E,
+ },
+ [0xAA5F]={
+ category="po",
+ description="CHAM PUNCTUATION TRIPLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xAA5F,
+ },
+ [0xAA60]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI GA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA60,
+ },
+ [0xAA61]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI CA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA61,
+ },
+ [0xAA62]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI CHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA62,
+ },
+ [0xAA63]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI JA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA63,
+ },
+ [0xAA64]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI JHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA64,
+ },
+ [0xAA65]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI NYA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA65,
+ },
+ [0xAA66]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI TTA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA66,
+ },
+ [0xAA67]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI TTHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA67,
+ },
+ [0xAA68]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI DDA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA68,
+ },
+ [0xAA69]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI DDHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA69,
+ },
+ [0xAA6A]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI DHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6A,
+ },
+ [0xAA6B]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI NA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6B,
+ },
+ [0xAA6C]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI SA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6C,
+ },
+ [0xAA6D]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI HA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6D,
+ },
+ [0xAA6E]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI HHA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6E,
+ },
+ [0xAA6F]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI FA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA6F,
+ },
+ [0xAA70]={
+ category="lm",
+ description="MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA70,
+ },
+ [0xAA71]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI XA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA71,
+ },
+ [0xAA72]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI ZA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA72,
+ },
+ [0xAA73]={
+ category="lo",
+ description="MYANMAR LETTER KHAMTI RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA73,
+ },
+ [0xAA74]={
+ category="lo",
+ description="MYANMAR LOGOGRAM KHAMTI OAY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA74,
+ },
+ [0xAA75]={
+ category="lo",
+ description="MYANMAR LOGOGRAM KHAMTI QN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA75,
+ },
+ [0xAA76]={
+ category="lo",
+ description="MYANMAR LOGOGRAM KHAMTI HM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA76,
+ },
+ [0xAA77]={
+ category="so",
+ description="MYANMAR SYMBOL AITON EXCLAMATION",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA77,
+ },
+ [0xAA78]={
+ category="so",
+ description="MYANMAR SYMBOL AITON ONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA78,
+ },
+ [0xAA79]={
+ category="so",
+ description="MYANMAR SYMBOL AITON TWO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA79,
+ },
+ [0xAA7A]={
+ category="lo",
+ description="MYANMAR LETTER AITON RA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA7A,
+ },
+ [0xAA7B]={
+ category="mc",
+ description="MYANMAR SIGN PAO KAREN TONE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA7B,
+ },
+ [0xAA80]={
+ category="lo",
+ description="TAI VIET LETTER LOW KO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA80,
+ },
+ [0xAA81]={
+ category="lo",
+ description="TAI VIET LETTER HIGH KO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA81,
+ },
+ [0xAA82]={
+ category="lo",
+ description="TAI VIET LETTER LOW KHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA82,
+ },
+ [0xAA83]={
+ category="lo",
+ description="TAI VIET LETTER HIGH KHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA83,
+ },
+ [0xAA84]={
+ category="lo",
+ description="TAI VIET LETTER LOW KHHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA84,
+ },
+ [0xAA85]={
+ category="lo",
+ description="TAI VIET LETTER HIGH KHHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA85,
+ },
+ [0xAA86]={
+ category="lo",
+ description="TAI VIET LETTER LOW GO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA86,
+ },
+ [0xAA87]={
+ category="lo",
+ description="TAI VIET LETTER HIGH GO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA87,
+ },
+ [0xAA88]={
+ category="lo",
+ description="TAI VIET LETTER LOW NGO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA88,
+ },
+ [0xAA89]={
+ category="lo",
+ description="TAI VIET LETTER HIGH NGO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA89,
+ },
+ [0xAA8A]={
+ category="lo",
+ description="TAI VIET LETTER LOW CO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8A,
+ },
+ [0xAA8B]={
+ category="lo",
+ description="TAI VIET LETTER HIGH CO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8B,
+ },
+ [0xAA8C]={
+ category="lo",
+ description="TAI VIET LETTER LOW CHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8C,
+ },
+ [0xAA8D]={
+ category="lo",
+ description="TAI VIET LETTER HIGH CHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8D,
+ },
+ [0xAA8E]={
+ category="lo",
+ description="TAI VIET LETTER LOW SO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8E,
+ },
+ [0xAA8F]={
+ category="lo",
+ description="TAI VIET LETTER HIGH SO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA8F,
+ },
+ [0xAA90]={
+ category="lo",
+ description="TAI VIET LETTER LOW NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA90,
+ },
+ [0xAA91]={
+ category="lo",
+ description="TAI VIET LETTER HIGH NYO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA91,
+ },
+ [0xAA92]={
+ category="lo",
+ description="TAI VIET LETTER LOW DO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA92,
+ },
+ [0xAA93]={
+ category="lo",
+ description="TAI VIET LETTER HIGH DO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA93,
+ },
+ [0xAA94]={
+ category="lo",
+ description="TAI VIET LETTER LOW TO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA94,
+ },
+ [0xAA95]={
+ category="lo",
+ description="TAI VIET LETTER HIGH TO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA95,
+ },
+ [0xAA96]={
+ category="lo",
+ description="TAI VIET LETTER LOW THO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA96,
+ },
+ [0xAA97]={
+ category="lo",
+ description="TAI VIET LETTER HIGH THO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA97,
+ },
+ [0xAA98]={
+ category="lo",
+ description="TAI VIET LETTER LOW NO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA98,
+ },
+ [0xAA99]={
+ category="lo",
+ description="TAI VIET LETTER HIGH NO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA99,
+ },
+ [0xAA9A]={
+ category="lo",
+ description="TAI VIET LETTER LOW BO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9A,
+ },
+ [0xAA9B]={
+ category="lo",
+ description="TAI VIET LETTER HIGH BO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9B,
+ },
+ [0xAA9C]={
+ category="lo",
+ description="TAI VIET LETTER LOW PO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9C,
+ },
+ [0xAA9D]={
+ category="lo",
+ description="TAI VIET LETTER HIGH PO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9D,
+ },
+ [0xAA9E]={
+ category="lo",
+ description="TAI VIET LETTER LOW PHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9E,
+ },
+ [0xAA9F]={
+ category="lo",
+ description="TAI VIET LETTER HIGH PHO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAA9F,
+ },
+ [0xAAA0]={
+ category="lo",
+ description="TAI VIET LETTER LOW FO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA0,
+ },
+ [0xAAA1]={
+ category="lo",
+ description="TAI VIET LETTER HIGH FO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA1,
+ },
+ [0xAAA2]={
+ category="lo",
+ description="TAI VIET LETTER LOW MO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA2,
+ },
+ [0xAAA3]={
+ category="lo",
+ description="TAI VIET LETTER HIGH MO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA3,
+ },
+ [0xAAA4]={
+ category="lo",
+ description="TAI VIET LETTER LOW YO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA4,
+ },
+ [0xAAA5]={
+ category="lo",
+ description="TAI VIET LETTER HIGH YO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA5,
+ },
+ [0xAAA6]={
+ category="lo",
+ description="TAI VIET LETTER LOW RO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA6,
+ },
+ [0xAAA7]={
+ category="lo",
+ description="TAI VIET LETTER HIGH RO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA7,
+ },
+ [0xAAA8]={
+ category="lo",
+ description="TAI VIET LETTER LOW LO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA8,
+ },
+ [0xAAA9]={
+ category="lo",
+ description="TAI VIET LETTER HIGH LO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAA9,
+ },
+ [0xAAAA]={
+ category="lo",
+ description="TAI VIET LETTER LOW VO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAA,
+ },
+ [0xAAAB]={
+ category="lo",
+ description="TAI VIET LETTER HIGH VO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAB,
+ },
+ [0xAAAC]={
+ category="lo",
+ description="TAI VIET LETTER LOW HO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAC,
+ },
+ [0xAAAD]={
+ category="lo",
+ description="TAI VIET LETTER HIGH HO",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAD,
+ },
+ [0xAAAE]={
+ category="lo",
+ description="TAI VIET LETTER LOW O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAE,
+ },
+ [0xAAAF]={
+ category="lo",
+ description="TAI VIET LETTER HIGH O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAAF,
+ },
+ [0xAAB0]={
+ category="mn",
+ description="TAI VIET MAI KANG",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB0,
+ },
+ [0xAAB1]={
+ category="lo",
+ description="TAI VIET VOWEL AA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAB1,
+ },
+ [0xAAB2]={
+ category="mn",
+ description="TAI VIET VOWEL I",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB2,
+ },
+ [0xAAB3]={
+ category="mn",
+ description="TAI VIET VOWEL UE",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB3,
+ },
+ [0xAAB4]={
+ category="mn",
+ description="TAI VIET VOWEL U",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB4,
+ },
+ [0xAAB5]={
+ category="lo",
+ description="TAI VIET VOWEL E",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAB5,
+ },
+ [0xAAB6]={
+ category="lo",
+ description="TAI VIET VOWEL O",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAB6,
+ },
+ [0xAAB7]={
+ category="mn",
+ description="TAI VIET MAI KHIT",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB7,
+ },
+ [0xAAB8]={
+ category="mn",
+ description="TAI VIET VOWEL IA",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAB8,
+ },
+ [0xAAB9]={
+ category="lo",
+ description="TAI VIET VOWEL UEA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAB9,
+ },
+ [0xAABA]={
+ category="lo",
+ description="TAI VIET VOWEL UA",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAABA,
+ },
+ [0xAABB]={
+ category="lo",
+ description="TAI VIET VOWEL AUE",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAABB,
+ },
+ [0xAABC]={
+ category="lo",
+ description="TAI VIET VOWEL AY",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAABC,
+ },
+ [0xAABD]={
+ category="lo",
+ description="TAI VIET VOWEL AN",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAABD,
+ },
+ [0xAABE]={
+ category="mn",
+ description="TAI VIET VOWEL AM",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAABE,
+ },
+ [0xAABF]={
+ category="mn",
+ description="TAI VIET TONE MAI EK",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAABF,
+ },
+ [0xAAC0]={
+ category="lo",
+ description="TAI VIET TONE MAI NUENG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAC0,
+ },
+ [0xAAC1]={
+ category="mn",
+ description="TAI VIET TONE MAI THO",
+ direction="nsm",
+ linebreak="sa",
+ unicodeslot=0xAAC1,
+ },
+ [0xAAC2]={
+ category="lo",
+ description="TAI VIET TONE MAI SONG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAAC2,
+ },
+ [0xAADB]={
+ category="lo",
+ description="TAI VIET SYMBOL KON",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADB,
+ },
+ [0xAADC]={
+ category="lo",
+ description="TAI VIET SYMBOL NUENG",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADC,
+ },
+ [0xAADD]={
+ category="lm",
+ description="TAI VIET SYMBOL SAM",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADD,
+ },
+ [0xAADE]={
+ category="po",
+ description="TAI VIET SYMBOL HO HOI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADE,
+ },
+ [0xAADF]={
+ category="po",
+ description="TAI VIET SYMBOL KOI KOI",
+ direction="l",
+ linebreak="sa",
+ unicodeslot=0xAADF,
+ },
+ [0xAB01]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB01,
+ },
+ [0xAB02]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB02,
+ },
+ [0xAB03]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB03,
+ },
+ [0xAB04]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB04,
+ },
+ [0xAB05]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB05,
+ },
+ [0xAB06]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE TTHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB06,
+ },
+ [0xAB09]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB09,
+ },
+ [0xAB0A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0A,
+ },
+ [0xAB0B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0B,
+ },
+ [0xAB0C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0C,
+ },
+ [0xAB0D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0D,
+ },
+ [0xAB0E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DDHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB0E,
+ },
+ [0xAB11]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB11,
+ },
+ [0xAB12]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB12,
+ },
+ [0xAB13]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB13,
+ },
+ [0xAB14]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB14,
+ },
+ [0xAB15]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB15,
+ },
+ [0xAB16]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE DZO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB16,
+ },
+ [0xAB20]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB20,
+ },
+ [0xAB21]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB21,
+ },
+ [0xAB22]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB22,
+ },
+ [0xAB23]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB23,
+ },
+ [0xAB24]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB24,
+ },
+ [0xAB25]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB25,
+ },
+ [0xAB26]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE CCHHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB26,
+ },
+ [0xAB28]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB28,
+ },
+ [0xAB29]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB29,
+ },
+ [0xAB2A]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2A,
+ },
+ [0xAB2B]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2B,
+ },
+ [0xAB2C]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2C,
+ },
+ [0xAB2D]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2D,
+ },
+ [0xAB2E]={
+ category="lo",
+ description="ETHIOPIC SYLLABLE BBO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xAB2E,
+ },
+ [0xABC0]={
+ category="lo",
+ description="MEETEI MAYEK LETTER KOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC0,
+ },
+ [0xABC1]={
+ category="lo",
+ description="MEETEI MAYEK LETTER SAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC1,
+ },
+ [0xABC2]={
+ category="lo",
+ description="MEETEI MAYEK LETTER LAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC2,
+ },
+ [0xABC3]={
+ category="lo",
+ description="MEETEI MAYEK LETTER MIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC3,
+ },
+ [0xABC4]={
+ category="lo",
+ description="MEETEI MAYEK LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC4,
+ },
+ [0xABC5]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC5,
+ },
+ [0xABC6]={
+ category="lo",
+ description="MEETEI MAYEK LETTER CHIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC6,
+ },
+ [0xABC7]={
+ category="lo",
+ description="MEETEI MAYEK LETTER TIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC7,
+ },
+ [0xABC8]={
+ category="lo",
+ description="MEETEI MAYEK LETTER KHOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC8,
+ },
+ [0xABC9]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NGOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABC9,
+ },
+ [0xABCA]={
+ category="lo",
+ description="MEETEI MAYEK LETTER THOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCA,
+ },
+ [0xABCB]={
+ category="lo",
+ description="MEETEI MAYEK LETTER WAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCB,
+ },
+ [0xABCC]={
+ category="lo",
+ description="MEETEI MAYEK LETTER YANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCC,
+ },
+ [0xABCD]={
+ category="lo",
+ description="MEETEI MAYEK LETTER HUK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCD,
+ },
+ [0xABCE]={
+ category="lo",
+ description="MEETEI MAYEK LETTER UN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCE,
+ },
+ [0xABCF]={
+ category="lo",
+ description="MEETEI MAYEK LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABCF,
+ },
+ [0xABD0]={
+ category="lo",
+ description="MEETEI MAYEK LETTER PHAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD0,
+ },
+ [0xABD1]={
+ category="lo",
+ description="MEETEI MAYEK LETTER ATIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD1,
+ },
+ [0xABD2]={
+ category="lo",
+ description="MEETEI MAYEK LETTER GOK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD2,
+ },
+ [0xABD3]={
+ category="lo",
+ description="MEETEI MAYEK LETTER JHAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD3,
+ },
+ [0xABD4]={
+ category="lo",
+ description="MEETEI MAYEK LETTER RAI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD4,
+ },
+ [0xABD5]={
+ category="lo",
+ description="MEETEI MAYEK LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD5,
+ },
+ [0xABD6]={
+ category="lo",
+ description="MEETEI MAYEK LETTER JIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD6,
+ },
+ [0xABD7]={
+ category="lo",
+ description="MEETEI MAYEK LETTER DIL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD7,
+ },
+ [0xABD8]={
+ category="lo",
+ description="MEETEI MAYEK LETTER GHOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD8,
+ },
+ [0xABD9]={
+ category="lo",
+ description="MEETEI MAYEK LETTER DHOU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABD9,
+ },
+ [0xABDA]={
+ category="lo",
+ description="MEETEI MAYEK LETTER BHAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDA,
+ },
+ [0xABDB]={
+ category="lo",
+ description="MEETEI MAYEK LETTER KOK LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDB,
+ },
+ [0xABDC]={
+ category="lo",
+ description="MEETEI MAYEK LETTER LAI LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDC,
+ },
+ [0xABDD]={
+ category="lo",
+ description="MEETEI MAYEK LETTER MIT LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDD,
+ },
+ [0xABDE]={
+ category="lo",
+ description="MEETEI MAYEK LETTER PA LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDE,
+ },
+ [0xABDF]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NA LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABDF,
+ },
+ [0xABE0]={
+ category="lo",
+ description="MEETEI MAYEK LETTER TIL LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABE0,
+ },
+ [0xABE1]={
+ category="lo",
+ description="MEETEI MAYEK LETTER NGOU LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABE1,
+ },
+ [0xABE2]={
+ category="lo",
+ description="MEETEI MAYEK LETTER I LONSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0xABE2,
+ },
+ [0xABE3]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN ONAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE3,
+ },
+ [0xABE4]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN INAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE4,
+ },
+ [0xABE5]={
+ category="mn",
+ description="MEETEI MAYEK VOWEL SIGN ANAP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xABE5,
+ },
+ [0xABE6]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN YENAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE6,
+ },
+ [0xABE7]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN SOUNAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE7,
+ },
+ [0xABE8]={
+ category="mn",
+ description="MEETEI MAYEK VOWEL SIGN UNAP",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xABE8,
+ },
+ [0xABE9]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN CHEINAP",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABE9,
+ },
+ [0xABEA]={
+ category="mc",
+ description="MEETEI MAYEK VOWEL SIGN NUNG",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABEA,
+ },
+ [0xABEB]={
+ category="po",
+ description="MEETEI MAYEK CHEIKHEI",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0xABEB,
+ },
+ [0xABEC]={
+ category="mc",
+ description="MEETEI MAYEK LUM IYEK",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0xABEC,
+ },
+ [0xABED]={
+ category="mn",
+ description="MEETEI MAYEK APUN IYEK",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xABED,
+ },
+ [0xABF0]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF0,
+ },
+ [0xABF1]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF1,
+ },
+ [0xABF2]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF2,
+ },
+ [0xABF3]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF3,
+ },
+ [0xABF4]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF4,
+ },
+ [0xABF5]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF5,
+ },
+ [0xABF6]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF6,
+ },
+ [0xABF7]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF7,
+ },
+ [0xABF8]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF8,
+ },
+ [0xABF9]={
+ category="nd",
+ description="MEETEI MAYEK DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0xABF9,
+ },
+ [0xD7B0]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG O-YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B0,
+ },
+ [0xD7B1]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG O-O-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B1,
+ },
+ [0xD7B2]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG YO-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B2,
+ },
+ [0xD7B3]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG YO-AE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B3,
+ },
+ [0xD7B4]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG YO-EO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B4,
+ },
+ [0xD7B5]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG U-YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B5,
+ },
+ [0xD7B6]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG U-I-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B6,
+ },
+ [0xD7B7]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG YU-AE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B7,
+ },
+ [0xD7B8]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG YU-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B8,
+ },
+ [0xD7B9]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG EU-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7B9,
+ },
+ [0xD7BA]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG EU-EO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BA,
+ },
+ [0xD7BB]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG EU-E",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BB,
+ },
+ [0xD7BC]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG EU-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BC,
+ },
+ [0xD7BD]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG I-YA-O",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BD,
+ },
+ [0xD7BE]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG I-YAE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BE,
+ },
+ [0xD7BF]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG I-YEO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7BF,
+ },
+ [0xD7C0]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG I-YE",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C0,
+ },
+ [0xD7C1]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG I-O-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C1,
+ },
+ [0xD7C2]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG I-YO",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C2,
+ },
+ [0xD7C3]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG I-YU",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C3,
+ },
+ [0xD7C4]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG I-I",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C4,
+ },
+ [0xD7C5]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG ARAEA-A",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C5,
+ },
+ [0xD7C6]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JUNGSEONG ARAEA-E",
+ direction="l",
+ linebreak="jv",
+ unicodeslot=0xD7C6,
+ },
+ [0xD7CB]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG NIEUN-RIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CB,
+ },
+ [0xD7CC]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG NIEUN-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CC,
+ },
+ [0xD7CD]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGTIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CD,
+ },
+ [0xD7CE]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGTIKEUT-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CE,
+ },
+ [0xD7CF]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG TIKEUT-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7CF,
+ },
+ [0xD7D0]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG TIKEUT-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D0,
+ },
+ [0xD7D1]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG TIKEUT-SIOS-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D1,
+ },
+ [0xD7D2]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG TIKEUT-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D2,
+ },
+ [0xD7D3]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG TIKEUT-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D3,
+ },
+ [0xD7D4]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG TIKEUT-THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D4,
+ },
+ [0xD7D5]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG RIEUL-SSANGKIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D5,
+ },
+ [0xD7D6]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG RIEUL-KIYEOK-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D6,
+ },
+ [0xD7D7]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGRIEUL-KHIEUKH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D7,
+ },
+ [0xD7D8]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG RIEUL-MIEUM-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D8,
+ },
+ [0xD7D9]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG RIEUL-PIEUP-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7D9,
+ },
+ [0xD7DA]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG RIEUL-PIEUP-PHIEUPH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DA,
+ },
+ [0xD7DB]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG RIEUL-YESIEUNG",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DB,
+ },
+ [0xD7DC]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG RIEUL-YEORINHIEUH-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DC,
+ },
+ [0xD7DD]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG KAPYEOUNRIEUL",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DD,
+ },
+ [0xD7DE]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG MIEUM-NIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DE,
+ },
+ [0xD7DF]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG MIEUM-SSANGNIEUN",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7DF,
+ },
+ [0xD7E0]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGMIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E0,
+ },
+ [0xD7E1]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG MIEUM-PIEUP-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E1,
+ },
+ [0xD7E2]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG MIEUM-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E2,
+ },
+ [0xD7E3]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PIEUP-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E3,
+ },
+ [0xD7E4]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PIEUP-RIEUL-PHIEUPH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E4,
+ },
+ [0xD7E5]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PIEUP-MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E5,
+ },
+ [0xD7E6]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E6,
+ },
+ [0xD7E7]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PIEUP-SIOS-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E7,
+ },
+ [0xD7E8]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PIEUP-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E8,
+ },
+ [0xD7E9]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PIEUP-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7E9,
+ },
+ [0xD7EA]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SIOS-MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EA,
+ },
+ [0xD7EB]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SIOS-KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EB,
+ },
+ [0xD7EC]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGSIOS-KIYEOK",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EC,
+ },
+ [0xD7ED]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGSIOS-TIKEUT",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7ED,
+ },
+ [0xD7EE]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SIOS-PANSIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EE,
+ },
+ [0xD7EF]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SIOS-CIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7EF,
+ },
+ [0xD7F0]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SIOS-CHIEUCH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F0,
+ },
+ [0xD7F1]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SIOS-THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F1,
+ },
+ [0xD7F2]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SIOS-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F2,
+ },
+ [0xD7F3]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PANSIOS-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F3,
+ },
+ [0xD7F4]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PANSIOS-KAPYEOUNPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F4,
+ },
+ [0xD7F5]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG YESIEUNG-MIEUM",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F5,
+ },
+ [0xD7F6]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG YESIEUNG-HIEUH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F6,
+ },
+ [0xD7F7]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG CIEUC-PIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F7,
+ },
+ [0xD7F8]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG CIEUC-SSANGPIEUP",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F8,
+ },
+ [0xD7F9]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG SSANGCIEUC",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7F9,
+ },
+ [0xD7FA]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PHIEUPH-SIOS",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7FA,
+ },
+ [0xD7FB]={
+ category="lo",
+ cjkwd="w",
+ description="HANGUL JONGSEONG PHIEUPH-THIEUTH",
+ direction="l",
+ linebreak="jt",
+ unicodeslot=0xD7FB,
+ },
[0xD800]={
category="cs",
description="<Non Private Use High Surrogate, First>",
@@ -100906,6 +118760,33 @@ characters.data={
specials={ "char", 0x983B },
unicodeslot=0xFA6A,
},
+ [0xFA6B]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA6B",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x6075 },
+ unicodeslot=0xFA6B,
+ },
+ [0xFA6C]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA6C",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x242EE },
+ unicodeslot=0xFA6C,
+ },
+ [0xFA6D]={
+ category="lo",
+ cjkwd="w",
+ description="CJK COMPATIBILITY IDEOGRAPH-FA6D",
+ direction="l",
+ linebreak="id",
+ specials={ "char", 0x8218 },
+ unicodeslot=0xFA6D,
+ },
[0xFA70]={
category="lo",
cjkwd="w",
@@ -103216,6 +121097,118 @@ characters.data={
specials={ "final", 0x06D3 },
unicodeslot=0xFBB1,
},
+ [0xFBB2]={
+ category="sk",
+ description="ARABIC SYMBOL DOT ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB2,
+ },
+ [0xFBB3]={
+ category="sk",
+ description="ARABIC SYMBOL DOT BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB3,
+ },
+ [0xFBB4]={
+ category="sk",
+ description="ARABIC SYMBOL TWO DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB4,
+ },
+ [0xFBB5]={
+ category="sk",
+ description="ARABIC SYMBOL TWO DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB5,
+ },
+ [0xFBB6]={
+ category="sk",
+ description="ARABIC SYMBOL THREE DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB6,
+ },
+ [0xFBB7]={
+ category="sk",
+ description="ARABIC SYMBOL THREE DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB7,
+ },
+ [0xFBB8]={
+ category="sk",
+ description="ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB8,
+ },
+ [0xFBB9]={
+ category="sk",
+ description="ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBB9,
+ },
+ [0xFBBA]={
+ category="sk",
+ description="ARABIC SYMBOL FOUR DOTS ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBA,
+ },
+ [0xFBBB]={
+ category="sk",
+ description="ARABIC SYMBOL FOUR DOTS BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBB,
+ },
+ [0xFBBC]={
+ category="sk",
+ description="ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBC,
+ },
+ [0xFBBD]={
+ category="sk",
+ description="ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBD,
+ },
+ [0xFBBE]={
+ category="sk",
+ description="ARABIC SYMBOL TWO DOTS VERTICALLY BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBE,
+ },
+ [0xFBBF]={
+ category="sk",
+ description="ARABIC SYMBOL RING",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBBF,
+ },
+ [0xFBC0]={
+ category="sk",
+ description="ARABIC SYMBOL SMALL TAH ABOVE",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBC0,
+ },
+ [0xFBC1]={
+ category="sk",
+ description="ARABIC SYMBOL SMALL TAH BELOW",
+ direction="al",
+ linebreak="al",
+ unicodeslot=0xFBC1,
+ },
[0xFBD3]={
category="lo",
description="ARABIC LETTER NG ISOLATED FORM",
@@ -107471,6 +125464,27 @@ characters.data={
linebreak="cm",
unicodeslot=0xFE23,
},
+ [0xFE24]={
+ category="mn",
+ description="COMBINING MACRON LEFT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE24,
+ },
+ [0xFE25]={
+ category="mn",
+ description="COMBINING MACRON RIGHT HALF",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE25,
+ },
+ [0xFE26]={
+ category="mn",
+ description="COMBINING CONJOINING MACRON",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0xFE26,
+ },
[0xFE30]={
adobename="twodotleadervertical",
category="po",
@@ -113971,6 +131985,958 @@ characters.data={
linebreak="al",
unicodeslot=0x1018A,
},
+ [0x10190]={
+ category="so",
+ description="ROMAN SEXTANS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10190,
+ },
+ [0x10191]={
+ category="so",
+ description="ROMAN UNCIA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10191,
+ },
+ [0x10192]={
+ category="so",
+ description="ROMAN SEMUNCIA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10192,
+ },
+ [0x10193]={
+ category="so",
+ description="ROMAN SEXTULA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10193,
+ },
+ [0x10194]={
+ category="so",
+ description="ROMAN DIMIDIA SEXTULA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10194,
+ },
+ [0x10195]={
+ category="so",
+ description="ROMAN SILIQUA SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10195,
+ },
+ [0x10196]={
+ category="so",
+ description="ROMAN DENARIUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10196,
+ },
+ [0x10197]={
+ category="so",
+ description="ROMAN QUINARIUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10197,
+ },
+ [0x10198]={
+ category="so",
+ description="ROMAN SESTERTIUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10198,
+ },
+ [0x10199]={
+ category="so",
+ description="ROMAN DUPONDIUS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x10199,
+ },
+ [0x1019A]={
+ category="so",
+ description="ROMAN AS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1019A,
+ },
+ [0x1019B]={
+ category="so",
+ description="ROMAN CENTURIAL SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1019B,
+ },
+ [0x101D0]={
+ category="so",
+ description="PHAISTOS DISC SIGN PEDESTRIAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D0,
+ },
+ [0x101D1]={
+ category="so",
+ description="PHAISTOS DISC SIGN PLUMED HEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D1,
+ },
+ [0x101D2]={
+ category="so",
+ description="PHAISTOS DISC SIGN TATTOOED HEAD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D2,
+ },
+ [0x101D3]={
+ category="so",
+ description="PHAISTOS DISC SIGN CAPTIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D3,
+ },
+ [0x101D4]={
+ category="so",
+ description="PHAISTOS DISC SIGN CHILD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D4,
+ },
+ [0x101D5]={
+ category="so",
+ description="PHAISTOS DISC SIGN WOMAN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D5,
+ },
+ [0x101D6]={
+ category="so",
+ description="PHAISTOS DISC SIGN HELMET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D6,
+ },
+ [0x101D7]={
+ category="so",
+ description="PHAISTOS DISC SIGN GAUNTLET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D7,
+ },
+ [0x101D8]={
+ category="so",
+ description="PHAISTOS DISC SIGN TIARA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D8,
+ },
+ [0x101D9]={
+ category="so",
+ description="PHAISTOS DISC SIGN ARROW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101D9,
+ },
+ [0x101DA]={
+ category="so",
+ description="PHAISTOS DISC SIGN BOW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DA,
+ },
+ [0x101DB]={
+ category="so",
+ description="PHAISTOS DISC SIGN SHIELD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DB,
+ },
+ [0x101DC]={
+ category="so",
+ description="PHAISTOS DISC SIGN CLUB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DC,
+ },
+ [0x101DD]={
+ category="so",
+ description="PHAISTOS DISC SIGN MANACLES",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DD,
+ },
+ [0x101DE]={
+ category="so",
+ description="PHAISTOS DISC SIGN MATTOCK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DE,
+ },
+ [0x101DF]={
+ category="so",
+ description="PHAISTOS DISC SIGN SAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101DF,
+ },
+ [0x101E0]={
+ category="so",
+ description="PHAISTOS DISC SIGN LID",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E0,
+ },
+ [0x101E1]={
+ category="so",
+ description="PHAISTOS DISC SIGN BOOMERANG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E1,
+ },
+ [0x101E2]={
+ category="so",
+ description="PHAISTOS DISC SIGN CARPENTRY PLANE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E2,
+ },
+ [0x101E3]={
+ category="so",
+ description="PHAISTOS DISC SIGN DOLIUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E3,
+ },
+ [0x101E4]={
+ category="so",
+ description="PHAISTOS DISC SIGN COMB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E4,
+ },
+ [0x101E5]={
+ category="so",
+ description="PHAISTOS DISC SIGN SLING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E5,
+ },
+ [0x101E6]={
+ category="so",
+ description="PHAISTOS DISC SIGN COLUMN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E6,
+ },
+ [0x101E7]={
+ category="so",
+ description="PHAISTOS DISC SIGN BEEHIVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E7,
+ },
+ [0x101E8]={
+ category="so",
+ description="PHAISTOS DISC SIGN SHIP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E8,
+ },
+ [0x101E9]={
+ category="so",
+ description="PHAISTOS DISC SIGN HORN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101E9,
+ },
+ [0x101EA]={
+ category="so",
+ description="PHAISTOS DISC SIGN HIDE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EA,
+ },
+ [0x101EB]={
+ category="so",
+ description="PHAISTOS DISC SIGN BULLS LEG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EB,
+ },
+ [0x101EC]={
+ category="so",
+ description="PHAISTOS DISC SIGN CAT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EC,
+ },
+ [0x101ED]={
+ category="so",
+ description="PHAISTOS DISC SIGN RAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101ED,
+ },
+ [0x101EE]={
+ category="so",
+ description="PHAISTOS DISC SIGN EAGLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EE,
+ },
+ [0x101EF]={
+ category="so",
+ description="PHAISTOS DISC SIGN DOVE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101EF,
+ },
+ [0x101F0]={
+ category="so",
+ description="PHAISTOS DISC SIGN TUNNY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F0,
+ },
+ [0x101F1]={
+ category="so",
+ description="PHAISTOS DISC SIGN BEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F1,
+ },
+ [0x101F2]={
+ category="so",
+ description="PHAISTOS DISC SIGN PLANE TREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F2,
+ },
+ [0x101F3]={
+ category="so",
+ description="PHAISTOS DISC SIGN VINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F3,
+ },
+ [0x101F4]={
+ category="so",
+ description="PHAISTOS DISC SIGN PAPYRUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F4,
+ },
+ [0x101F5]={
+ category="so",
+ description="PHAISTOS DISC SIGN ROSETTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F5,
+ },
+ [0x101F6]={
+ category="so",
+ description="PHAISTOS DISC SIGN LILY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F6,
+ },
+ [0x101F7]={
+ category="so",
+ description="PHAISTOS DISC SIGN OX BACK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F7,
+ },
+ [0x101F8]={
+ category="so",
+ description="PHAISTOS DISC SIGN FLUTE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F8,
+ },
+ [0x101F9]={
+ category="so",
+ description="PHAISTOS DISC SIGN GRATER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101F9,
+ },
+ [0x101FA]={
+ category="so",
+ description="PHAISTOS DISC SIGN STRAINER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101FA,
+ },
+ [0x101FB]={
+ category="so",
+ description="PHAISTOS DISC SIGN SMALL AXE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101FB,
+ },
+ [0x101FC]={
+ category="so",
+ description="PHAISTOS DISC SIGN WAVY BAND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x101FC,
+ },
+ [0x101FD]={
+ category="mn",
+ description="PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x101FD,
+ },
+ [0x10280]={
+ category="lo",
+ description="LYCIAN LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10280,
+ },
+ [0x10281]={
+ category="lo",
+ description="LYCIAN LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10281,
+ },
+ [0x10282]={
+ category="lo",
+ description="LYCIAN LETTER B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10282,
+ },
+ [0x10283]={
+ category="lo",
+ description="LYCIAN LETTER BH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10283,
+ },
+ [0x10284]={
+ category="lo",
+ description="LYCIAN LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10284,
+ },
+ [0x10285]={
+ category="lo",
+ description="LYCIAN LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10285,
+ },
+ [0x10286]={
+ category="lo",
+ description="LYCIAN LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10286,
+ },
+ [0x10287]={
+ category="lo",
+ description="LYCIAN LETTER W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10287,
+ },
+ [0x10288]={
+ category="lo",
+ description="LYCIAN LETTER Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10288,
+ },
+ [0x10289]={
+ category="lo",
+ description="LYCIAN LETTER TH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10289,
+ },
+ [0x1028A]={
+ category="lo",
+ description="LYCIAN LETTER J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028A,
+ },
+ [0x1028B]={
+ category="lo",
+ description="LYCIAN LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028B,
+ },
+ [0x1028C]={
+ category="lo",
+ description="LYCIAN LETTER Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028C,
+ },
+ [0x1028D]={
+ category="lo",
+ description="LYCIAN LETTER L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028D,
+ },
+ [0x1028E]={
+ category="lo",
+ description="LYCIAN LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028E,
+ },
+ [0x1028F]={
+ category="lo",
+ description="LYCIAN LETTER N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1028F,
+ },
+ [0x10290]={
+ category="lo",
+ description="LYCIAN LETTER MM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10290,
+ },
+ [0x10291]={
+ category="lo",
+ description="LYCIAN LETTER NN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10291,
+ },
+ [0x10292]={
+ category="lo",
+ description="LYCIAN LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10292,
+ },
+ [0x10293]={
+ category="lo",
+ description="LYCIAN LETTER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10293,
+ },
+ [0x10294]={
+ category="lo",
+ description="LYCIAN LETTER KK",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10294,
+ },
+ [0x10295]={
+ category="lo",
+ description="LYCIAN LETTER R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10295,
+ },
+ [0x10296]={
+ category="lo",
+ description="LYCIAN LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10296,
+ },
+ [0x10297]={
+ category="lo",
+ description="LYCIAN LETTER T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10297,
+ },
+ [0x10298]={
+ category="lo",
+ description="LYCIAN LETTER TT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10298,
+ },
+ [0x10299]={
+ category="lo",
+ description="LYCIAN LETTER AN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x10299,
+ },
+ [0x1029A]={
+ category="lo",
+ description="LYCIAN LETTER EN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1029A,
+ },
+ [0x1029B]={
+ category="lo",
+ description="LYCIAN LETTER H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1029B,
+ },
+ [0x1029C]={
+ category="lo",
+ description="LYCIAN LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1029C,
+ },
+ [0x102A0]={
+ category="lo",
+ description="CARIAN LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A0,
+ },
+ [0x102A1]={
+ category="lo",
+ description="CARIAN LETTER P2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A1,
+ },
+ [0x102A2]={
+ category="lo",
+ description="CARIAN LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A2,
+ },
+ [0x102A3]={
+ category="lo",
+ description="CARIAN LETTER L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A3,
+ },
+ [0x102A4]={
+ category="lo",
+ description="CARIAN LETTER UUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A4,
+ },
+ [0x102A5]={
+ category="lo",
+ description="CARIAN LETTER R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A5,
+ },
+ [0x102A6]={
+ category="lo",
+ description="CARIAN LETTER LD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A6,
+ },
+ [0x102A7]={
+ category="lo",
+ description="CARIAN LETTER A2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A7,
+ },
+ [0x102A8]={
+ category="lo",
+ description="CARIAN LETTER Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A8,
+ },
+ [0x102A9]={
+ category="lo",
+ description="CARIAN LETTER B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102A9,
+ },
+ [0x102AA]={
+ category="lo",
+ description="CARIAN LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AA,
+ },
+ [0x102AB]={
+ category="lo",
+ description="CARIAN LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AB,
+ },
+ [0x102AC]={
+ category="lo",
+ description="CARIAN LETTER D2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AC,
+ },
+ [0x102AD]={
+ category="lo",
+ description="CARIAN LETTER T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AD,
+ },
+ [0x102AE]={
+ category="lo",
+ description="CARIAN LETTER SH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AE,
+ },
+ [0x102AF]={
+ category="lo",
+ description="CARIAN LETTER SH2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102AF,
+ },
+ [0x102B0]={
+ category="lo",
+ description="CARIAN LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B0,
+ },
+ [0x102B1]={
+ category="lo",
+ description="CARIAN LETTER C-18",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B1,
+ },
+ [0x102B2]={
+ category="lo",
+ description="CARIAN LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B2,
+ },
+ [0x102B3]={
+ category="lo",
+ description="CARIAN LETTER NN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B3,
+ },
+ [0x102B4]={
+ category="lo",
+ description="CARIAN LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B4,
+ },
+ [0x102B5]={
+ category="lo",
+ description="CARIAN LETTER N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B5,
+ },
+ [0x102B6]={
+ category="lo",
+ description="CARIAN LETTER TT2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B6,
+ },
+ [0x102B7]={
+ category="lo",
+ description="CARIAN LETTER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B7,
+ },
+ [0x102B8]={
+ category="lo",
+ description="CARIAN LETTER SS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B8,
+ },
+ [0x102B9]={
+ category="lo",
+ description="CARIAN LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102B9,
+ },
+ [0x102BA]={
+ category="lo",
+ description="CARIAN LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BA,
+ },
+ [0x102BB]={
+ category="lo",
+ description="CARIAN LETTER UUUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BB,
+ },
+ [0x102BC]={
+ category="lo",
+ description="CARIAN LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BC,
+ },
+ [0x102BD]={
+ category="lo",
+ description="CARIAN LETTER K2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BD,
+ },
+ [0x102BE]={
+ category="lo",
+ description="CARIAN LETTER ND",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BE,
+ },
+ [0x102BF]={
+ category="lo",
+ description="CARIAN LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102BF,
+ },
+ [0x102C0]={
+ category="lo",
+ description="CARIAN LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C0,
+ },
+ [0x102C1]={
+ category="lo",
+ description="CARIAN LETTER G2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C1,
+ },
+ [0x102C2]={
+ category="lo",
+ description="CARIAN LETTER ST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C2,
+ },
+ [0x102C3]={
+ category="lo",
+ description="CARIAN LETTER ST2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C3,
+ },
+ [0x102C4]={
+ category="lo",
+ description="CARIAN LETTER NG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C4,
+ },
+ [0x102C5]={
+ category="lo",
+ description="CARIAN LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C5,
+ },
+ [0x102C6]={
+ category="lo",
+ description="CARIAN LETTER C-39",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C6,
+ },
+ [0x102C7]={
+ category="lo",
+ description="CARIAN LETTER TT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C7,
+ },
+ [0x102C8]={
+ category="lo",
+ description="CARIAN LETTER UUU2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C8,
+ },
+ [0x102C9]={
+ category="lo",
+ description="CARIAN LETTER RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102C9,
+ },
+ [0x102CA]={
+ category="lo",
+ description="CARIAN LETTER MB",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CA,
+ },
+ [0x102CB]={
+ category="lo",
+ description="CARIAN LETTER MB2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CB,
+ },
+ [0x102CC]={
+ category="lo",
+ description="CARIAN LETTER MB3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CC,
+ },
+ [0x102CD]={
+ category="lo",
+ description="CARIAN LETTER MB4",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CD,
+ },
+ [0x102CE]={
+ category="lo",
+ description="CARIAN LETTER LD2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CE,
+ },
+ [0x102CF]={
+ category="lo",
+ description="CARIAN LETTER E2",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102CF,
+ },
+ [0x102D0]={
+ category="lo",
+ description="CARIAN LETTER UUU3",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x102D0,
+ },
[0x10300]={
category="lo",
description="OLD ITALIC LETTER A",
@@ -116613,6 +135579,223 @@ characters.data={
linebreak="al",
unicodeslot=0x1083F,
},
+ [0x10840]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10840,
+ },
+ [0x10841]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10841,
+ },
+ [0x10842]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10842,
+ },
+ [0x10843]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10843,
+ },
+ [0x10844]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10844,
+ },
+ [0x10845]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10845,
+ },
+ [0x10846]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10846,
+ },
+ [0x10847]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10847,
+ },
+ [0x10848]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10848,
+ },
+ [0x10849]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10849,
+ },
+ [0x1084A]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084A,
+ },
+ [0x1084B]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084B,
+ },
+ [0x1084C]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084C,
+ },
+ [0x1084D]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084D,
+ },
+ [0x1084E]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084E,
+ },
+ [0x1084F]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1084F,
+ },
+ [0x10850]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10850,
+ },
+ [0x10851]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10851,
+ },
+ [0x10852]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10852,
+ },
+ [0x10853]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10853,
+ },
+ [0x10854]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10854,
+ },
+ [0x10855]={
+ category="lo",
+ description="IMPERIAL ARAMAIC LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10855,
+ },
+ [0x10857]={
+ category="po",
+ description="IMPERIAL ARAMAIC SECTION SIGN",
+ direction="r",
+ linebreak="ba",
+ unicodeslot=0x10857,
+ },
+ [0x10858]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10858,
+ },
+ [0x10859]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10859,
+ },
+ [0x1085A]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085A,
+ },
+ [0x1085B]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085B,
+ },
+ [0x1085C]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085C,
+ },
+ [0x1085D]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085D,
+ },
+ [0x1085E]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085E,
+ },
+ [0x1085F]={
+ category="no",
+ description="IMPERIAL ARAMAIC NUMBER TEN THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1085F,
+ },
[0x10900]={
category="lo",
description="PHOENICIAN LETTER ALF",
@@ -116795,6 +135978,20 @@ characters.data={
linebreak="al",
unicodeslot=0x10919,
},
+ [0x1091A]={
+ category="no",
+ description="PHOENICIAN NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1091A,
+ },
+ [0x1091B]={
+ category="no",
+ description="PHOENICIAN NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1091B,
+ },
[0x1091F]={
category="po",
description="PHOENICIAN WORD SEPARATOR",
@@ -116802,6 +135999,195 @@ characters.data={
linebreak="ba",
unicodeslot=0x1091F,
},
+ [0x10920]={
+ category="lo",
+ description="LYDIAN LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10920,
+ },
+ [0x10921]={
+ category="lo",
+ description="LYDIAN LETTER B",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10921,
+ },
+ [0x10922]={
+ category="lo",
+ description="LYDIAN LETTER G",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10922,
+ },
+ [0x10923]={
+ category="lo",
+ description="LYDIAN LETTER D",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10923,
+ },
+ [0x10924]={
+ category="lo",
+ description="LYDIAN LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10924,
+ },
+ [0x10925]={
+ category="lo",
+ description="LYDIAN LETTER V",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10925,
+ },
+ [0x10926]={
+ category="lo",
+ description="LYDIAN LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10926,
+ },
+ [0x10927]={
+ category="lo",
+ description="LYDIAN LETTER Y",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10927,
+ },
+ [0x10928]={
+ category="lo",
+ description="LYDIAN LETTER K",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10928,
+ },
+ [0x10929]={
+ category="lo",
+ description="LYDIAN LETTER L",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10929,
+ },
+ [0x1092A]={
+ category="lo",
+ description="LYDIAN LETTER M",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092A,
+ },
+ [0x1092B]={
+ category="lo",
+ description="LYDIAN LETTER N",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092B,
+ },
+ [0x1092C]={
+ category="lo",
+ description="LYDIAN LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092C,
+ },
+ [0x1092D]={
+ category="lo",
+ description="LYDIAN LETTER R",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092D,
+ },
+ [0x1092E]={
+ category="lo",
+ description="LYDIAN LETTER SS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092E,
+ },
+ [0x1092F]={
+ category="lo",
+ description="LYDIAN LETTER T",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1092F,
+ },
+ [0x10930]={
+ category="lo",
+ description="LYDIAN LETTER U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10930,
+ },
+ [0x10931]={
+ category="lo",
+ description="LYDIAN LETTER F",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10931,
+ },
+ [0x10932]={
+ category="lo",
+ description="LYDIAN LETTER Q",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10932,
+ },
+ [0x10933]={
+ category="lo",
+ description="LYDIAN LETTER S",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10933,
+ },
+ [0x10934]={
+ category="lo",
+ description="LYDIAN LETTER TT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10934,
+ },
+ [0x10935]={
+ category="lo",
+ description="LYDIAN LETTER AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10935,
+ },
+ [0x10936]={
+ category="lo",
+ description="LYDIAN LETTER EN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10936,
+ },
+ [0x10937]={
+ category="lo",
+ description="LYDIAN LETTER LY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10937,
+ },
+ [0x10938]={
+ category="lo",
+ description="LYDIAN LETTER NN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10938,
+ },
+ [0x10939]={
+ category="lo",
+ description="LYDIAN LETTER C",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10939,
+ },
+ [0x1093F]={
+ category="po",
+ description="LYDIAN TRIANGULAR MARK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x1093F,
+ },
[0x10A00]={
category="lo",
description="KHAROSHTHI LETTER A",
@@ -117257,6 +136643,3005 @@ characters.data={
linebreak="al",
unicodeslot=0x10A58,
},
+ [0x10A60]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A60,
+ },
+ [0x10A61]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A61,
+ },
+ [0x10A62]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A62,
+ },
+ [0x10A63]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A63,
+ },
+ [0x10A64]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A64,
+ },
+ [0x10A65]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A65,
+ },
+ [0x10A66]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A66,
+ },
+ [0x10A67]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A67,
+ },
+ [0x10A68]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A68,
+ },
+ [0x10A69]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A69,
+ },
+ [0x10A6A]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER SAT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6A,
+ },
+ [0x10A6B]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6B,
+ },
+ [0x10A6C]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6C,
+ },
+ [0x10A6D]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER KHETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6D,
+ },
+ [0x10A6E]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6E,
+ },
+ [0x10A6F]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A6F,
+ },
+ [0x10A70]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER FE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A70,
+ },
+ [0x10A71]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER ALEF",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A71,
+ },
+ [0x10A72]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER AYN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A72,
+ },
+ [0x10A73]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER DHADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A73,
+ },
+ [0x10A74]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A74,
+ },
+ [0x10A75]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A75,
+ },
+ [0x10A76]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER GHAYN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A76,
+ },
+ [0x10A77]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A77,
+ },
+ [0x10A78]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER ZAYN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A78,
+ },
+ [0x10A79]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER DHALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A79,
+ },
+ [0x10A7A]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7A,
+ },
+ [0x10A7B]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER THAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7B,
+ },
+ [0x10A7C]={
+ category="lo",
+ description="OLD SOUTH ARABIAN LETTER THETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7C,
+ },
+ [0x10A7D]={
+ category="no",
+ description="OLD SOUTH ARABIAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7D,
+ },
+ [0x10A7E]={
+ category="no",
+ description="OLD SOUTH ARABIAN NUMBER FIFTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7E,
+ },
+ [0x10A7F]={
+ category="po",
+ description="OLD SOUTH ARABIAN NUMERIC INDICATOR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10A7F,
+ },
+ [0x10B00]={
+ category="lo",
+ description="AVESTAN LETTER A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B00,
+ },
+ [0x10B01]={
+ category="lo",
+ description="AVESTAN LETTER AA",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B01,
+ },
+ [0x10B02]={
+ category="lo",
+ description="AVESTAN LETTER AO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B02,
+ },
+ [0x10B03]={
+ category="lo",
+ description="AVESTAN LETTER AAO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B03,
+ },
+ [0x10B04]={
+ category="lo",
+ description="AVESTAN LETTER AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B04,
+ },
+ [0x10B05]={
+ category="lo",
+ description="AVESTAN LETTER AAN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B05,
+ },
+ [0x10B06]={
+ category="lo",
+ description="AVESTAN LETTER AE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B06,
+ },
+ [0x10B07]={
+ category="lo",
+ description="AVESTAN LETTER AEE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B07,
+ },
+ [0x10B08]={
+ category="lo",
+ description="AVESTAN LETTER E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B08,
+ },
+ [0x10B09]={
+ category="lo",
+ description="AVESTAN LETTER EE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B09,
+ },
+ [0x10B0A]={
+ category="lo",
+ description="AVESTAN LETTER O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0A,
+ },
+ [0x10B0B]={
+ category="lo",
+ description="AVESTAN LETTER OO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0B,
+ },
+ [0x10B0C]={
+ category="lo",
+ description="AVESTAN LETTER I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0C,
+ },
+ [0x10B0D]={
+ category="lo",
+ description="AVESTAN LETTER II",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0D,
+ },
+ [0x10B0E]={
+ category="lo",
+ description="AVESTAN LETTER U",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0E,
+ },
+ [0x10B0F]={
+ category="lo",
+ description="AVESTAN LETTER UU",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B0F,
+ },
+ [0x10B10]={
+ category="lo",
+ description="AVESTAN LETTER KE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B10,
+ },
+ [0x10B11]={
+ category="lo",
+ description="AVESTAN LETTER XE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B11,
+ },
+ [0x10B12]={
+ category="lo",
+ description="AVESTAN LETTER XYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B12,
+ },
+ [0x10B13]={
+ category="lo",
+ description="AVESTAN LETTER XVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B13,
+ },
+ [0x10B14]={
+ category="lo",
+ description="AVESTAN LETTER GE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B14,
+ },
+ [0x10B15]={
+ category="lo",
+ description="AVESTAN LETTER GGE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B15,
+ },
+ [0x10B16]={
+ category="lo",
+ description="AVESTAN LETTER GHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B16,
+ },
+ [0x10B17]={
+ category="lo",
+ description="AVESTAN LETTER CE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B17,
+ },
+ [0x10B18]={
+ category="lo",
+ description="AVESTAN LETTER JE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B18,
+ },
+ [0x10B19]={
+ category="lo",
+ description="AVESTAN LETTER TE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B19,
+ },
+ [0x10B1A]={
+ category="lo",
+ description="AVESTAN LETTER THE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1A,
+ },
+ [0x10B1B]={
+ category="lo",
+ description="AVESTAN LETTER DE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1B,
+ },
+ [0x10B1C]={
+ category="lo",
+ description="AVESTAN LETTER DHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1C,
+ },
+ [0x10B1D]={
+ category="lo",
+ description="AVESTAN LETTER TTE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1D,
+ },
+ [0x10B1E]={
+ category="lo",
+ description="AVESTAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1E,
+ },
+ [0x10B1F]={
+ category="lo",
+ description="AVESTAN LETTER FE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B1F,
+ },
+ [0x10B20]={
+ category="lo",
+ description="AVESTAN LETTER BE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B20,
+ },
+ [0x10B21]={
+ category="lo",
+ description="AVESTAN LETTER BHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B21,
+ },
+ [0x10B22]={
+ category="lo",
+ description="AVESTAN LETTER NGE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B22,
+ },
+ [0x10B23]={
+ category="lo",
+ description="AVESTAN LETTER NGYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B23,
+ },
+ [0x10B24]={
+ category="lo",
+ description="AVESTAN LETTER NGVE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B24,
+ },
+ [0x10B25]={
+ category="lo",
+ description="AVESTAN LETTER NE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B25,
+ },
+ [0x10B26]={
+ category="lo",
+ description="AVESTAN LETTER NYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B26,
+ },
+ [0x10B27]={
+ category="lo",
+ description="AVESTAN LETTER NNE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B27,
+ },
+ [0x10B28]={
+ category="lo",
+ description="AVESTAN LETTER ME",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B28,
+ },
+ [0x10B29]={
+ category="lo",
+ description="AVESTAN LETTER HME",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B29,
+ },
+ [0x10B2A]={
+ category="lo",
+ description="AVESTAN LETTER YYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2A,
+ },
+ [0x10B2B]={
+ category="lo",
+ description="AVESTAN LETTER YE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2B,
+ },
+ [0x10B2C]={
+ category="lo",
+ description="AVESTAN LETTER VE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2C,
+ },
+ [0x10B2D]={
+ category="lo",
+ description="AVESTAN LETTER RE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2D,
+ },
+ [0x10B2E]={
+ category="lo",
+ description="AVESTAN LETTER LE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2E,
+ },
+ [0x10B2F]={
+ category="lo",
+ description="AVESTAN LETTER SE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B2F,
+ },
+ [0x10B30]={
+ category="lo",
+ description="AVESTAN LETTER ZE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B30,
+ },
+ [0x10B31]={
+ category="lo",
+ description="AVESTAN LETTER SHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B31,
+ },
+ [0x10B32]={
+ category="lo",
+ description="AVESTAN LETTER ZHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B32,
+ },
+ [0x10B33]={
+ category="lo",
+ description="AVESTAN LETTER SHYE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B33,
+ },
+ [0x10B34]={
+ category="lo",
+ description="AVESTAN LETTER SSHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B34,
+ },
+ [0x10B35]={
+ category="lo",
+ description="AVESTAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B35,
+ },
+ [0x10B39]={
+ category="po",
+ description="AVESTAN ABBREVIATION MARK",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B39,
+ },
+ [0x10B3A]={
+ category="po",
+ description="TINY TWO DOTS OVER ONE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3A,
+ },
+ [0x10B3B]={
+ category="po",
+ description="SMALL TWO DOTS OVER ONE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3B,
+ },
+ [0x10B3C]={
+ category="po",
+ description="LARGE TWO DOTS OVER ONE DOT PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3C,
+ },
+ [0x10B3D]={
+ category="po",
+ description="LARGE ONE DOT OVER TWO DOTS PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3D,
+ },
+ [0x10B3E]={
+ category="po",
+ description="LARGE TWO RINGS OVER ONE RING PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3E,
+ },
+ [0x10B3F]={
+ category="po",
+ description="LARGE ONE RING OVER TWO RINGS PUNCTUATION",
+ direction="on",
+ linebreak="ba",
+ unicodeslot=0x10B3F,
+ },
+ [0x10B40]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B40,
+ },
+ [0x10B41]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B41,
+ },
+ [0x10B42]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B42,
+ },
+ [0x10B43]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B43,
+ },
+ [0x10B44]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B44,
+ },
+ [0x10B45]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER WAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B45,
+ },
+ [0x10B46]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B46,
+ },
+ [0x10B47]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B47,
+ },
+ [0x10B48]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B48,
+ },
+ [0x10B49]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B49,
+ },
+ [0x10B4A]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4A,
+ },
+ [0x10B4B]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4B,
+ },
+ [0x10B4C]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER MEM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4C,
+ },
+ [0x10B4D]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4D,
+ },
+ [0x10B4E]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4E,
+ },
+ [0x10B4F]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER AYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B4F,
+ },
+ [0x10B50]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B50,
+ },
+ [0x10B51]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B51,
+ },
+ [0x10B52]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B52,
+ },
+ [0x10B53]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B53,
+ },
+ [0x10B54]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B54,
+ },
+ [0x10B55]={
+ category="lo",
+ description="INSCRIPTIONAL PARTHIAN LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B55,
+ },
+ [0x10B58]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B58,
+ },
+ [0x10B59]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B59,
+ },
+ [0x10B5A]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5A,
+ },
+ [0x10B5B]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5B,
+ },
+ [0x10B5C]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5C,
+ },
+ [0x10B5D]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5D,
+ },
+ [0x10B5E]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5E,
+ },
+ [0x10B5F]={
+ category="no",
+ description="INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B5F,
+ },
+ [0x10B60]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER ALEPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B60,
+ },
+ [0x10B61]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER BETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B61,
+ },
+ [0x10B62]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER GIMEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B62,
+ },
+ [0x10B63]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER DALETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B63,
+ },
+ [0x10B64]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER HE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B64,
+ },
+ [0x10B65]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER WAW-AYIN-RESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B65,
+ },
+ [0x10B66]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER ZAYIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B66,
+ },
+ [0x10B67]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER HETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B67,
+ },
+ [0x10B68]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER TETH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B68,
+ },
+ [0x10B69]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER YODH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B69,
+ },
+ [0x10B6A]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER KAPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6A,
+ },
+ [0x10B6B]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER LAMEDH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6B,
+ },
+ [0x10B6C]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER MEM-QOPH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6C,
+ },
+ [0x10B6D]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER NUN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6D,
+ },
+ [0x10B6E]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER SAMEKH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6E,
+ },
+ [0x10B6F]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER PE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B6F,
+ },
+ [0x10B70]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER SADHE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B70,
+ },
+ [0x10B71]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER SHIN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B71,
+ },
+ [0x10B72]={
+ category="lo",
+ description="INSCRIPTIONAL PAHLAVI LETTER TAW",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B72,
+ },
+ [0x10B78]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER ONE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B78,
+ },
+ [0x10B79]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER TWO",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B79,
+ },
+ [0x10B7A]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER THREE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7A,
+ },
+ [0x10B7B]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER FOUR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7B,
+ },
+ [0x10B7C]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER TEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7C,
+ },
+ [0x10B7D]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER TWENTY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7D,
+ },
+ [0x10B7E]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7E,
+ },
+ [0x10B7F]={
+ category="no",
+ description="INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10B7F,
+ },
+ [0x10C00]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C00,
+ },
+ [0x10C01]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI A",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C01,
+ },
+ [0x10C02]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C02,
+ },
+ [0x10C03]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C03,
+ },
+ [0x10C04]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI I",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C04,
+ },
+ [0x10C05]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI E",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C05,
+ },
+ [0x10C06]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON O",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C06,
+ },
+ [0x10C07]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C07,
+ },
+ [0x10C08]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI OE",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C08,
+ },
+ [0x10C09]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C09,
+ },
+ [0x10C0A]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0A,
+ },
+ [0x10C0B]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0B,
+ },
+ [0x10C0C]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEB",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0C,
+ },
+ [0x10C0D]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0D,
+ },
+ [0x10C0E]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0E,
+ },
+ [0x10C0F]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C0F,
+ },
+ [0x10C10]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C10,
+ },
+ [0x10C11]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C11,
+ },
+ [0x10C12]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AD",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C12,
+ },
+ [0x10C13]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AED",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C13,
+ },
+ [0x10C14]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON EZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C14,
+ },
+ [0x10C15]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI EZ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C15,
+ },
+ [0x10C16]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C16,
+ },
+ [0x10C17]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C17,
+ },
+ [0x10C18]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C18,
+ },
+ [0x10C19]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C19,
+ },
+ [0x10C1A]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1A,
+ },
+ [0x10C1B]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1B,
+ },
+ [0x10C1C]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OEK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1C,
+ },
+ [0x10C1D]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI OEK",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1D,
+ },
+ [0x10C1E]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1E,
+ },
+ [0x10C1F]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C1F,
+ },
+ [0x10C20]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEL",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C20,
+ },
+ [0x10C21]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ELT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C21,
+ },
+ [0x10C22]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON EM",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C22,
+ },
+ [0x10C23]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C23,
+ },
+ [0x10C24]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C24,
+ },
+ [0x10C25]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AEN",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C25,
+ },
+ [0x10C26]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ENT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C26,
+ },
+ [0x10C27]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ENT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C27,
+ },
+ [0x10C28]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ENC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C28,
+ },
+ [0x10C29]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ENC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C29,
+ },
+ [0x10C2A]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ENY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2A,
+ },
+ [0x10C2B]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ENY",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2B,
+ },
+ [0x10C2C]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ANG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2C,
+ },
+ [0x10C2D]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ENG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2D,
+ },
+ [0x10C2E]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AENG",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2E,
+ },
+ [0x10C2F]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON EP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C2F,
+ },
+ [0x10C30]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OP",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C30,
+ },
+ [0x10C31]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON IC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C31,
+ },
+ [0x10C32]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON EC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C32,
+ },
+ [0x10C33]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI EC",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C33,
+ },
+ [0x10C34]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C34,
+ },
+ [0x10C35]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C35,
+ },
+ [0x10C36]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON IQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C36,
+ },
+ [0x10C37]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI IQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C37,
+ },
+ [0x10C38]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C38,
+ },
+ [0x10C39]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI OQ",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C39,
+ },
+ [0x10C3A]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3A,
+ },
+ [0x10C3B]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AR",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3B,
+ },
+ [0x10C3C]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AER",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3C,
+ },
+ [0x10C3D]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AS",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3D,
+ },
+ [0x10C3E]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AES",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3E,
+ },
+ [0x10C3F]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ASH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C3F,
+ },
+ [0x10C40]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ASH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C40,
+ },
+ [0x10C41]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON ESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C41,
+ },
+ [0x10C42]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI ESH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C42,
+ },
+ [0x10C43]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C43,
+ },
+ [0x10C44]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C44,
+ },
+ [0x10C45]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON AET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C45,
+ },
+ [0x10C46]={
+ category="lo",
+ description="OLD TURKIC LETTER YENISEI AET",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C46,
+ },
+ [0x10C47]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON OT",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C47,
+ },
+ [0x10C48]={
+ category="lo",
+ description="OLD TURKIC LETTER ORKHON BASH",
+ direction="r",
+ linebreak="al",
+ unicodeslot=0x10C48,
+ },
+ [0x10E60]={
+ category="no",
+ description="RUMI DIGIT ONE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E60,
+ },
+ [0x10E61]={
+ category="no",
+ description="RUMI DIGIT TWO",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E61,
+ },
+ [0x10E62]={
+ category="no",
+ description="RUMI DIGIT THREE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E62,
+ },
+ [0x10E63]={
+ category="no",
+ description="RUMI DIGIT FOUR",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E63,
+ },
+ [0x10E64]={
+ category="no",
+ description="RUMI DIGIT FIVE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E64,
+ },
+ [0x10E65]={
+ category="no",
+ description="RUMI DIGIT SIX",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E65,
+ },
+ [0x10E66]={
+ category="no",
+ description="RUMI DIGIT SEVEN",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E66,
+ },
+ [0x10E67]={
+ category="no",
+ description="RUMI DIGIT EIGHT",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E67,
+ },
+ [0x10E68]={
+ category="no",
+ description="RUMI DIGIT NINE",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E68,
+ },
+ [0x10E69]={
+ category="no",
+ description="RUMI NUMBER TEN",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E69,
+ },
+ [0x10E6A]={
+ category="no",
+ description="RUMI NUMBER TWENTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6A,
+ },
+ [0x10E6B]={
+ category="no",
+ description="RUMI NUMBER THIRTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6B,
+ },
+ [0x10E6C]={
+ category="no",
+ description="RUMI NUMBER FORTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6C,
+ },
+ [0x10E6D]={
+ category="no",
+ description="RUMI NUMBER FIFTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6D,
+ },
+ [0x10E6E]={
+ category="no",
+ description="RUMI NUMBER SIXTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6E,
+ },
+ [0x10E6F]={
+ category="no",
+ description="RUMI NUMBER SEVENTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E6F,
+ },
+ [0x10E70]={
+ category="no",
+ description="RUMI NUMBER EIGHTY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E70,
+ },
+ [0x10E71]={
+ category="no",
+ description="RUMI NUMBER NINETY",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E71,
+ },
+ [0x10E72]={
+ category="no",
+ description="RUMI NUMBER ONE HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E72,
+ },
+ [0x10E73]={
+ category="no",
+ description="RUMI NUMBER TWO HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E73,
+ },
+ [0x10E74]={
+ category="no",
+ description="RUMI NUMBER THREE HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E74,
+ },
+ [0x10E75]={
+ category="no",
+ description="RUMI NUMBER FOUR HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E75,
+ },
+ [0x10E76]={
+ category="no",
+ description="RUMI NUMBER FIVE HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E76,
+ },
+ [0x10E77]={
+ category="no",
+ description="RUMI NUMBER SIX HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E77,
+ },
+ [0x10E78]={
+ category="no",
+ description="RUMI NUMBER SEVEN HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E78,
+ },
+ [0x10E79]={
+ category="no",
+ description="RUMI NUMBER EIGHT HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E79,
+ },
+ [0x10E7A]={
+ category="no",
+ description="RUMI NUMBER NINE HUNDRED",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7A,
+ },
+ [0x10E7B]={
+ category="no",
+ description="RUMI FRACTION ONE HALF",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7B,
+ },
+ [0x10E7C]={
+ category="no",
+ description="RUMI FRACTION ONE QUARTER",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7C,
+ },
+ [0x10E7D]={
+ category="no",
+ description="RUMI FRACTION ONE THIRD",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7D,
+ },
+ [0x10E7E]={
+ category="no",
+ description="RUMI FRACTION TWO THIRDS",
+ direction="an",
+ linebreak="al",
+ unicodeslot=0x10E7E,
+ },
+ [0x11000]={
+ category="mc",
+ description="BRAHMI SIGN CANDRABINDU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11000,
+ },
+ [0x11001]={
+ category="mn",
+ description="BRAHMI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11001,
+ },
+ [0x11002]={
+ category="mc",
+ description="BRAHMI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11002,
+ },
+ [0x11003]={
+ category="lo",
+ description="BRAHMI SIGN JIHVAMULIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11003,
+ },
+ [0x11004]={
+ category="lo",
+ description="BRAHMI SIGN UPADHMANIYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11004,
+ },
+ [0x11005]={
+ category="lo",
+ description="BRAHMI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11005,
+ },
+ [0x11006]={
+ category="lo",
+ description="BRAHMI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11006,
+ },
+ [0x11007]={
+ category="lo",
+ description="BRAHMI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11007,
+ },
+ [0x11008]={
+ category="lo",
+ description="BRAHMI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11008,
+ },
+ [0x11009]={
+ category="lo",
+ description="BRAHMI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11009,
+ },
+ [0x1100A]={
+ category="lo",
+ description="BRAHMI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100A,
+ },
+ [0x1100B]={
+ category="lo",
+ description="BRAHMI LETTER VOCALIC R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100B,
+ },
+ [0x1100C]={
+ category="lo",
+ description="BRAHMI LETTER VOCALIC RR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100C,
+ },
+ [0x1100D]={
+ category="lo",
+ description="BRAHMI LETTER VOCALIC L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100D,
+ },
+ [0x1100E]={
+ category="lo",
+ description="BRAHMI LETTER VOCALIC LL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100E,
+ },
+ [0x1100F]={
+ category="lo",
+ description="BRAHMI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1100F,
+ },
+ [0x11010]={
+ category="lo",
+ description="BRAHMI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11010,
+ },
+ [0x11011]={
+ category="lo",
+ description="BRAHMI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11011,
+ },
+ [0x11012]={
+ category="lo",
+ description="BRAHMI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11012,
+ },
+ [0x11013]={
+ category="lo",
+ description="BRAHMI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11013,
+ },
+ [0x11014]={
+ category="lo",
+ description="BRAHMI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11014,
+ },
+ [0x11015]={
+ category="lo",
+ description="BRAHMI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11015,
+ },
+ [0x11016]={
+ category="lo",
+ description="BRAHMI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11016,
+ },
+ [0x11017]={
+ category="lo",
+ description="BRAHMI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11017,
+ },
+ [0x11018]={
+ category="lo",
+ description="BRAHMI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11018,
+ },
+ [0x11019]={
+ category="lo",
+ description="BRAHMI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11019,
+ },
+ [0x1101A]={
+ category="lo",
+ description="BRAHMI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101A,
+ },
+ [0x1101B]={
+ category="lo",
+ description="BRAHMI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101B,
+ },
+ [0x1101C]={
+ category="lo",
+ description="BRAHMI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101C,
+ },
+ [0x1101D]={
+ category="lo",
+ description="BRAHMI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101D,
+ },
+ [0x1101E]={
+ category="lo",
+ description="BRAHMI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101E,
+ },
+ [0x1101F]={
+ category="lo",
+ description="BRAHMI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1101F,
+ },
+ [0x11020]={
+ category="lo",
+ description="BRAHMI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11020,
+ },
+ [0x11021]={
+ category="lo",
+ description="BRAHMI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11021,
+ },
+ [0x11022]={
+ category="lo",
+ description="BRAHMI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11022,
+ },
+ [0x11023]={
+ category="lo",
+ description="BRAHMI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11023,
+ },
+ [0x11024]={
+ category="lo",
+ description="BRAHMI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11024,
+ },
+ [0x11025]={
+ category="lo",
+ description="BRAHMI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11025,
+ },
+ [0x11026]={
+ category="lo",
+ description="BRAHMI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11026,
+ },
+ [0x11027]={
+ category="lo",
+ description="BRAHMI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11027,
+ },
+ [0x11028]={
+ category="lo",
+ description="BRAHMI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11028,
+ },
+ [0x11029]={
+ category="lo",
+ description="BRAHMI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11029,
+ },
+ [0x1102A]={
+ category="lo",
+ description="BRAHMI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102A,
+ },
+ [0x1102B]={
+ category="lo",
+ description="BRAHMI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102B,
+ },
+ [0x1102C]={
+ category="lo",
+ description="BRAHMI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102C,
+ },
+ [0x1102D]={
+ category="lo",
+ description="BRAHMI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102D,
+ },
+ [0x1102E]={
+ category="lo",
+ description="BRAHMI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102E,
+ },
+ [0x1102F]={
+ category="lo",
+ description="BRAHMI LETTER VA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1102F,
+ },
+ [0x11030]={
+ category="lo",
+ description="BRAHMI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11030,
+ },
+ [0x11031]={
+ category="lo",
+ description="BRAHMI LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11031,
+ },
+ [0x11032]={
+ category="lo",
+ description="BRAHMI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11032,
+ },
+ [0x11033]={
+ category="lo",
+ description="BRAHMI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11033,
+ },
+ [0x11034]={
+ category="lo",
+ description="BRAHMI LETTER LLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11034,
+ },
+ [0x11035]={
+ category="lo",
+ description="BRAHMI LETTER OLD TAMIL LLLA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11035,
+ },
+ [0x11036]={
+ category="lo",
+ description="BRAHMI LETTER OLD TAMIL RRA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11036,
+ },
+ [0x11037]={
+ category="lo",
+ description="BRAHMI LETTER OLD TAMIL NNNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11037,
+ },
+ [0x11038]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11038,
+ },
+ [0x11039]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN BHATTIPROLU AA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11039,
+ },
+ [0x1103A]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN I",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103A,
+ },
+ [0x1103B]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN II",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103B,
+ },
+ [0x1103C]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103C,
+ },
+ [0x1103D]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103D,
+ },
+ [0x1103E]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN VOCALIC R",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103E,
+ },
+ [0x1103F]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN VOCALIC RR",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x1103F,
+ },
+ [0x11040]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN VOCALIC L",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11040,
+ },
+ [0x11041]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN VOCALIC LL",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11041,
+ },
+ [0x11042]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11042,
+ },
+ [0x11043]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11043,
+ },
+ [0x11044]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN O",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11044,
+ },
+ [0x11045]={
+ category="mn",
+ description="BRAHMI VOWEL SIGN AU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11045,
+ },
+ [0x11046]={
+ category="mn",
+ description="BRAHMI VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11046,
+ },
+ [0x11047]={
+ category="po",
+ description="BRAHMI DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11047,
+ },
+ [0x11048]={
+ category="po",
+ description="BRAHMI DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x11048,
+ },
+ [0x11049]={
+ category="po",
+ description="BRAHMI PUNCTUATION DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11049,
+ },
+ [0x1104A]={
+ category="po",
+ description="BRAHMI PUNCTUATION DOUBLE DOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1104A,
+ },
+ [0x1104B]={
+ category="po",
+ description="BRAHMI PUNCTUATION LINE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1104B,
+ },
+ [0x1104C]={
+ category="po",
+ description="BRAHMI PUNCTUATION CRESCENT BAR",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1104C,
+ },
+ [0x1104D]={
+ category="po",
+ description="BRAHMI PUNCTUATION LOTUS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1104D,
+ },
+ [0x11052]={
+ category="no",
+ description="BRAHMI NUMBER ONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11052,
+ },
+ [0x11053]={
+ category="no",
+ description="BRAHMI NUMBER TWO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11053,
+ },
+ [0x11054]={
+ category="no",
+ description="BRAHMI NUMBER THREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11054,
+ },
+ [0x11055]={
+ category="no",
+ description="BRAHMI NUMBER FOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11055,
+ },
+ [0x11056]={
+ category="no",
+ description="BRAHMI NUMBER FIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11056,
+ },
+ [0x11057]={
+ category="no",
+ description="BRAHMI NUMBER SIX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11057,
+ },
+ [0x11058]={
+ category="no",
+ description="BRAHMI NUMBER SEVEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11058,
+ },
+ [0x11059]={
+ category="no",
+ description="BRAHMI NUMBER EIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11059,
+ },
+ [0x1105A]={
+ category="no",
+ description="BRAHMI NUMBER NINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105A,
+ },
+ [0x1105B]={
+ category="no",
+ description="BRAHMI NUMBER TEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105B,
+ },
+ [0x1105C]={
+ category="no",
+ description="BRAHMI NUMBER TWENTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105C,
+ },
+ [0x1105D]={
+ category="no",
+ description="BRAHMI NUMBER THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105D,
+ },
+ [0x1105E]={
+ category="no",
+ description="BRAHMI NUMBER FORTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105E,
+ },
+ [0x1105F]={
+ category="no",
+ description="BRAHMI NUMBER FIFTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1105F,
+ },
+ [0x11060]={
+ category="no",
+ description="BRAHMI NUMBER SIXTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11060,
+ },
+ [0x11061]={
+ category="no",
+ description="BRAHMI NUMBER SEVENTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11061,
+ },
+ [0x11062]={
+ category="no",
+ description="BRAHMI NUMBER EIGHTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11062,
+ },
+ [0x11063]={
+ category="no",
+ description="BRAHMI NUMBER NINETY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11063,
+ },
+ [0x11064]={
+ category="no",
+ description="BRAHMI NUMBER ONE HUNDRED",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11064,
+ },
+ [0x11065]={
+ category="no",
+ description="BRAHMI NUMBER ONE THOUSAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x11065,
+ },
+ [0x11066]={
+ category="nd",
+ description="BRAHMI DIGIT ZERO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11066,
+ },
+ [0x11067]={
+ category="nd",
+ description="BRAHMI DIGIT ONE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11067,
+ },
+ [0x11068]={
+ category="nd",
+ description="BRAHMI DIGIT TWO",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11068,
+ },
+ [0x11069]={
+ category="nd",
+ description="BRAHMI DIGIT THREE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x11069,
+ },
+ [0x1106A]={
+ category="nd",
+ description="BRAHMI DIGIT FOUR",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106A,
+ },
+ [0x1106B]={
+ category="nd",
+ description="BRAHMI DIGIT FIVE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106B,
+ },
+ [0x1106C]={
+ category="nd",
+ description="BRAHMI DIGIT SIX",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106C,
+ },
+ [0x1106D]={
+ category="nd",
+ description="BRAHMI DIGIT SEVEN",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106D,
+ },
+ [0x1106E]={
+ category="nd",
+ description="BRAHMI DIGIT EIGHT",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106E,
+ },
+ [0x1106F]={
+ category="nd",
+ description="BRAHMI DIGIT NINE",
+ direction="l",
+ linebreak="nu",
+ unicodeslot=0x1106F,
+ },
+ [0x11080]={
+ category="mn",
+ description="KAITHI SIGN CANDRABINDU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11080,
+ },
+ [0x11081]={
+ category="mn",
+ description="KAITHI SIGN ANUSVARA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x11081,
+ },
+ [0x11082]={
+ category="mc",
+ description="KAITHI SIGN VISARGA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x11082,
+ },
+ [0x11083]={
+ category="lo",
+ description="KAITHI LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11083,
+ },
+ [0x11084]={
+ category="lo",
+ description="KAITHI LETTER AA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11084,
+ },
+ [0x11085]={
+ category="lo",
+ description="KAITHI LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11085,
+ },
+ [0x11086]={
+ category="lo",
+ description="KAITHI LETTER II",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11086,
+ },
+ [0x11087]={
+ category="lo",
+ description="KAITHI LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11087,
+ },
+ [0x11088]={
+ category="lo",
+ description="KAITHI LETTER UU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11088,
+ },
+ [0x11089]={
+ category="lo",
+ description="KAITHI LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11089,
+ },
+ [0x1108A]={
+ category="lo",
+ description="KAITHI LETTER AI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108A,
+ },
+ [0x1108B]={
+ category="lo",
+ description="KAITHI LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108B,
+ },
+ [0x1108C]={
+ category="lo",
+ description="KAITHI LETTER AU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108C,
+ },
+ [0x1108D]={
+ category="lo",
+ description="KAITHI LETTER KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108D,
+ },
+ [0x1108E]={
+ category="lo",
+ description="KAITHI LETTER KHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108E,
+ },
+ [0x1108F]={
+ category="lo",
+ description="KAITHI LETTER GA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1108F,
+ },
+ [0x11090]={
+ category="lo",
+ description="KAITHI LETTER GHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11090,
+ },
+ [0x11091]={
+ category="lo",
+ description="KAITHI LETTER NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11091,
+ },
+ [0x11092]={
+ category="lo",
+ description="KAITHI LETTER CA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11092,
+ },
+ [0x11093]={
+ category="lo",
+ description="KAITHI LETTER CHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11093,
+ },
+ [0x11094]={
+ category="lo",
+ description="KAITHI LETTER JA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11094,
+ },
+ [0x11095]={
+ category="lo",
+ description="KAITHI LETTER JHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11095,
+ },
+ [0x11096]={
+ category="lo",
+ description="KAITHI LETTER NYA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11096,
+ },
+ [0x11097]={
+ category="lo",
+ description="KAITHI LETTER TTA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11097,
+ },
+ [0x11098]={
+ category="lo",
+ description="KAITHI LETTER TTHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11098,
+ },
+ [0x11099]={
+ category="lo",
+ description="KAITHI LETTER DDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x11099,
+ },
+ [0x1109A]={
+ category="lo",
+ description="KAITHI LETTER DDDHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x11099, 0x110BA },
+ unicodeslot=0x1109A,
+ },
+ [0x1109B]={
+ category="lo",
+ description="KAITHI LETTER DDHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1109B,
+ },
+ [0x1109C]={
+ category="lo",
+ description="KAITHI LETTER RHA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x1109B, 0x110BA },
+ unicodeslot=0x1109C,
+ },
+ [0x1109D]={
+ category="lo",
+ description="KAITHI LETTER NNA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1109D,
+ },
+ [0x1109E]={
+ category="lo",
+ description="KAITHI LETTER TA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1109E,
+ },
+ [0x1109F]={
+ category="lo",
+ description="KAITHI LETTER THA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1109F,
+ },
+ [0x110A0]={
+ category="lo",
+ description="KAITHI LETTER DA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A0,
+ },
+ [0x110A1]={
+ category="lo",
+ description="KAITHI LETTER DHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A1,
+ },
+ [0x110A2]={
+ category="lo",
+ description="KAITHI LETTER NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A2,
+ },
+ [0x110A3]={
+ category="lo",
+ description="KAITHI LETTER PA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A3,
+ },
+ [0x110A4]={
+ category="lo",
+ description="KAITHI LETTER PHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A4,
+ },
+ [0x110A5]={
+ category="lo",
+ description="KAITHI LETTER BA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A5,
+ },
+ [0x110A6]={
+ category="lo",
+ description="KAITHI LETTER BHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A6,
+ },
+ [0x110A7]={
+ category="lo",
+ description="KAITHI LETTER MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A7,
+ },
+ [0x110A8]={
+ category="lo",
+ description="KAITHI LETTER YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A8,
+ },
+ [0x110A9]={
+ category="lo",
+ description="KAITHI LETTER RA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110A9,
+ },
+ [0x110AA]={
+ category="lo",
+ description="KAITHI LETTER LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AA,
+ },
+ [0x110AB]={
+ category="lo",
+ description="KAITHI LETTER VA",
+ direction="l",
+ linebreak="al",
+ specials={ "char", 0x110A5, 0x110BA },
+ unicodeslot=0x110AB,
+ },
+ [0x110AC]={
+ category="lo",
+ description="KAITHI LETTER SHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AC,
+ },
+ [0x110AD]={
+ category="lo",
+ description="KAITHI LETTER SSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AD,
+ },
+ [0x110AE]={
+ category="lo",
+ description="KAITHI LETTER SA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AE,
+ },
+ [0x110AF]={
+ category="lo",
+ description="KAITHI LETTER HA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110AF,
+ },
+ [0x110B0]={
+ category="mc",
+ description="KAITHI VOWEL SIGN AA",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B0,
+ },
+ [0x110B1]={
+ category="mc",
+ description="KAITHI VOWEL SIGN I",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B1,
+ },
+ [0x110B2]={
+ category="mc",
+ description="KAITHI VOWEL SIGN II",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B2,
+ },
+ [0x110B3]={
+ category="mn",
+ description="KAITHI VOWEL SIGN U",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B3,
+ },
+ [0x110B4]={
+ category="mn",
+ description="KAITHI VOWEL SIGN UU",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B4,
+ },
+ [0x110B5]={
+ category="mn",
+ description="KAITHI VOWEL SIGN E",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B5,
+ },
+ [0x110B6]={
+ category="mn",
+ description="KAITHI VOWEL SIGN AI",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B6,
+ },
+ [0x110B7]={
+ category="mc",
+ description="KAITHI VOWEL SIGN O",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B7,
+ },
+ [0x110B8]={
+ category="mc",
+ description="KAITHI VOWEL SIGN AU",
+ direction="l",
+ linebreak="cm",
+ unicodeslot=0x110B8,
+ },
+ [0x110B9]={
+ category="mn",
+ description="KAITHI SIGN VIRAMA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110B9,
+ },
+ [0x110BA]={
+ category="mn",
+ description="KAITHI SIGN NUKTA",
+ direction="nsm",
+ linebreak="cm",
+ unicodeslot=0x110BA,
+ },
+ [0x110BB]={
+ category="po",
+ description="KAITHI ABBREVIATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110BB,
+ },
+ [0x110BC]={
+ category="po",
+ description="KAITHI ENUMERATION SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110BC,
+ },
+ [0x110BD]={
+ category="cf",
+ description="KAITHI NUMBER SIGN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x110BD,
+ },
+ [0x110BE]={
+ category="po",
+ description="KAITHI SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x110BE,
+ },
+ [0x110BF]={
+ category="po",
+ description="KAITHI DOUBLE SECTION MARK",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x110BF,
+ },
+ [0x110C0]={
+ category="po",
+ description="KAITHI DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x110C0,
+ },
+ [0x110C1]={
+ category="po",
+ description="KAITHI DOUBLE DANDA",
+ direction="l",
+ linebreak="ba",
+ unicodeslot=0x110C1,
+ },
[0x12000]={
category="lo",
description="CUNEIFORM SIGN A",
@@ -124133,6 +146518,11502 @@ characters.data={
linebreak="ba",
unicodeslot=0x12473,
},
+ [0x13000]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13000,
+ },
+ [0x13001]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13001,
+ },
+ [0x13002]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13002,
+ },
+ [0x13003]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13003,
+ },
+ [0x13004]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13004,
+ },
+ [0x13005]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13005,
+ },
+ [0x13006]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13006,
+ },
+ [0x13007]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13007,
+ },
+ [0x13008]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A006B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13008,
+ },
+ [0x13009]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13009,
+ },
+ [0x1300A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300A,
+ },
+ [0x1300B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300B,
+ },
+ [0x1300C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300C,
+ },
+ [0x1300D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300D,
+ },
+ [0x1300E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300E,
+ },
+ [0x1300F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1300F,
+ },
+ [0x13010]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13010,
+ },
+ [0x13011]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A014A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13011,
+ },
+ [0x13012]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13012,
+ },
+ [0x13013]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13013,
+ },
+ [0x13014]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13014,
+ },
+ [0x13015]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13015,
+ },
+ [0x13016]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13016,
+ },
+ [0x13017]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13017,
+ },
+ [0x13018]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13018,
+ },
+ [0x13019]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13019,
+ },
+ [0x1301A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301A,
+ },
+ [0x1301B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301B,
+ },
+ [0x1301C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301C,
+ },
+ [0x1301D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301D,
+ },
+ [0x1301E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301E,
+ },
+ [0x1301F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1301F,
+ },
+ [0x13020]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13020,
+ },
+ [0x13021]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13021,
+ },
+ [0x13022]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13022,
+ },
+ [0x13023]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13023,
+ },
+ [0x13024]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13024,
+ },
+ [0x13025]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A032A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13025,
+ },
+ [0x13026]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13026,
+ },
+ [0x13027]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13027,
+ },
+ [0x13028]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13028,
+ },
+ [0x13029]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13029,
+ },
+ [0x1302A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302A,
+ },
+ [0x1302B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302B,
+ },
+ [0x1302C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302C,
+ },
+ [0x1302D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302D,
+ },
+ [0x1302E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A040A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302E,
+ },
+ [0x1302F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1302F,
+ },
+ [0x13030]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13030,
+ },
+ [0x13031]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A042A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13031,
+ },
+ [0x13032]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13032,
+ },
+ [0x13033]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A043A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13033,
+ },
+ [0x13034]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13034,
+ },
+ [0x13035]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13035,
+ },
+ [0x13036]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A045A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13036,
+ },
+ [0x13037]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13037,
+ },
+ [0x13038]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13038,
+ },
+ [0x13039]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13039,
+ },
+ [0x1303A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303A,
+ },
+ [0x1303B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303B,
+ },
+ [0x1303C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303C,
+ },
+ [0x1303D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303D,
+ },
+ [0x1303E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303E,
+ },
+ [0x1303F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A054",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1303F,
+ },
+ [0x13040]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A055",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13040,
+ },
+ [0x13041]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A056",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13041,
+ },
+ [0x13042]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A057",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13042,
+ },
+ [0x13043]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A058",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13043,
+ },
+ [0x13044]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A059",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13044,
+ },
+ [0x13045]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A060",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13045,
+ },
+ [0x13046]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A061",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13046,
+ },
+ [0x13047]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A062",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13047,
+ },
+ [0x13048]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A063",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13048,
+ },
+ [0x13049]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A064",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13049,
+ },
+ [0x1304A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A065",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304A,
+ },
+ [0x1304B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A066",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304B,
+ },
+ [0x1304C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A067",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304C,
+ },
+ [0x1304D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A068",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304D,
+ },
+ [0x1304E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A069",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304E,
+ },
+ [0x1304F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH A070",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1304F,
+ },
+ [0x13050]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13050,
+ },
+ [0x13051]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13051,
+ },
+ [0x13052]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13052,
+ },
+ [0x13053]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13053,
+ },
+ [0x13054]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13054,
+ },
+ [0x13055]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13055,
+ },
+ [0x13056]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13056,
+ },
+ [0x13057]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13057,
+ },
+ [0x13058]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13058,
+ },
+ [0x13059]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH B009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13059,
+ },
+ [0x1305A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305A,
+ },
+ [0x1305B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305B,
+ },
+ [0x1305C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305C,
+ },
+ [0x1305D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C002B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305D,
+ },
+ [0x1305E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C002C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305E,
+ },
+ [0x1305F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1305F,
+ },
+ [0x13060]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13060,
+ },
+ [0x13061]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13061,
+ },
+ [0x13062]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13062,
+ },
+ [0x13063]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13063,
+ },
+ [0x13064]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13064,
+ },
+ [0x13065]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13065,
+ },
+ [0x13066]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13066,
+ },
+ [0x13067]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13067,
+ },
+ [0x13068]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13068,
+ },
+ [0x13069]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13069,
+ },
+ [0x1306A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306A,
+ },
+ [0x1306B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306B,
+ },
+ [0x1306C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306C,
+ },
+ [0x1306D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306D,
+ },
+ [0x1306E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306E,
+ },
+ [0x1306F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1306F,
+ },
+ [0x13070]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13070,
+ },
+ [0x13071]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13071,
+ },
+ [0x13072]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13072,
+ },
+ [0x13073]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13073,
+ },
+ [0x13074]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13074,
+ },
+ [0x13075]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH C024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13075,
+ },
+ [0x13076]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13076,
+ },
+ [0x13077]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13077,
+ },
+ [0x13078]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13078,
+ },
+ [0x13079]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13079,
+ },
+ [0x1307A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307A,
+ },
+ [0x1307B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307B,
+ },
+ [0x1307C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307C,
+ },
+ [0x1307D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307D,
+ },
+ [0x1307E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307E,
+ },
+ [0x1307F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1307F,
+ },
+ [0x13080]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13080,
+ },
+ [0x13081]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13081,
+ },
+ [0x13082]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13082,
+ },
+ [0x13083]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13083,
+ },
+ [0x13084]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13084,
+ },
+ [0x13085]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13085,
+ },
+ [0x13086]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13086,
+ },
+ [0x13087]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13087,
+ },
+ [0x13088]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13088,
+ },
+ [0x13089]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13089,
+ },
+ [0x1308A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308A,
+ },
+ [0x1308B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308B,
+ },
+ [0x1308C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308C,
+ },
+ [0x1308D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308D,
+ },
+ [0x1308E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308E,
+ },
+ [0x1308F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1308F,
+ },
+ [0x13090]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13090,
+ },
+ [0x13091]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13091,
+ },
+ [0x13092]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D027A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13092,
+ },
+ [0x13093]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13093,
+ },
+ [0x13094]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13094,
+ },
+ [0x13095]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13095,
+ },
+ [0x13096]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13096,
+ },
+ [0x13097]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D031A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13097,
+ },
+ [0x13098]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13098,
+ },
+ [0x13099]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13099,
+ },
+ [0x1309A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309A,
+ },
+ [0x1309B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D034A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309B,
+ },
+ [0x1309C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309C,
+ },
+ [0x1309D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309D,
+ },
+ [0x1309E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309E,
+ },
+ [0x1309F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1309F,
+ },
+ [0x130A0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A0,
+ },
+ [0x130A1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A1,
+ },
+ [0x130A2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A2,
+ },
+ [0x130A3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A3,
+ },
+ [0x130A4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A4,
+ },
+ [0x130A5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A5,
+ },
+ [0x130A6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A6,
+ },
+ [0x130A7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A7,
+ },
+ [0x130A8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D046A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A8,
+ },
+ [0x130A9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130A9,
+ },
+ [0x130AA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AA,
+ },
+ [0x130AB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D048A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AB,
+ },
+ [0x130AC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AC,
+ },
+ [0x130AD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AD,
+ },
+ [0x130AE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AE,
+ },
+ [0x130AF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130AF,
+ },
+ [0x130B0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B0,
+ },
+ [0x130B1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B1,
+ },
+ [0x130B2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B2,
+ },
+ [0x130B3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B3,
+ },
+ [0x130B4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B4,
+ },
+ [0x130B5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B5,
+ },
+ [0x130B6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D050I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B6,
+ },
+ [0x130B7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B7,
+ },
+ [0x130B8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B8,
+ },
+ [0x130B9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D052A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130B9,
+ },
+ [0x130BA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BA,
+ },
+ [0x130BB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D054",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BB,
+ },
+ [0x130BC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D054A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BC,
+ },
+ [0x130BD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D055",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BD,
+ },
+ [0x130BE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D056",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BE,
+ },
+ [0x130BF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D057",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130BF,
+ },
+ [0x130C0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D058",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C0,
+ },
+ [0x130C1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D059",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C1,
+ },
+ [0x130C2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D060",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C2,
+ },
+ [0x130C3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D061",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C3,
+ },
+ [0x130C4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D062",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C4,
+ },
+ [0x130C5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D063",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C5,
+ },
+ [0x130C6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D064",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C6,
+ },
+ [0x130C7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D065",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C7,
+ },
+ [0x130C8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D066",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C8,
+ },
+ [0x130C9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130C9,
+ },
+ [0x130CA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CA,
+ },
+ [0x130CB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CB,
+ },
+ [0x130CC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CC,
+ },
+ [0x130CD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CD,
+ },
+ [0x130CE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CE,
+ },
+ [0x130CF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130CF,
+ },
+ [0x130D0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D0,
+ },
+ [0x130D1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH D067H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D1,
+ },
+ [0x130D2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D2,
+ },
+ [0x130D3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D3,
+ },
+ [0x130D4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D4,
+ },
+ [0x130D5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D5,
+ },
+ [0x130D6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D6,
+ },
+ [0x130D7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D7,
+ },
+ [0x130D8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D8,
+ },
+ [0x130D9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130D9,
+ },
+ [0x130DA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DA,
+ },
+ [0x130DB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DB,
+ },
+ [0x130DC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DC,
+ },
+ [0x130DD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DD,
+ },
+ [0x130DE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DE,
+ },
+ [0x130DF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130DF,
+ },
+ [0x130E0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E0,
+ },
+ [0x130E1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E1,
+ },
+ [0x130E2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E2,
+ },
+ [0x130E3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E3,
+ },
+ [0x130E4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E4,
+ },
+ [0x130E5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E5,
+ },
+ [0x130E6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E6,
+ },
+ [0x130E7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E7,
+ },
+ [0x130E8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E8,
+ },
+ [0x130E9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130E9,
+ },
+ [0x130EA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E020A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EA,
+ },
+ [0x130EB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EB,
+ },
+ [0x130EC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EC,
+ },
+ [0x130ED]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130ED,
+ },
+ [0x130EE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EE,
+ },
+ [0x130EF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130EF,
+ },
+ [0x130F0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F0,
+ },
+ [0x130F1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F1,
+ },
+ [0x130F2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F2,
+ },
+ [0x130F3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E028A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F3,
+ },
+ [0x130F4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F4,
+ },
+ [0x130F5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F5,
+ },
+ [0x130F6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F6,
+ },
+ [0x130F7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F7,
+ },
+ [0x130F8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F8,
+ },
+ [0x130F9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130F9,
+ },
+ [0x130FA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E034A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FA,
+ },
+ [0x130FB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FB,
+ },
+ [0x130FC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FC,
+ },
+ [0x130FD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH E038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FD,
+ },
+ [0x130FE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FE,
+ },
+ [0x130FF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x130FF,
+ },
+ [0x13100]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13100,
+ },
+ [0x13101]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13101,
+ },
+ [0x13102]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13102,
+ },
+ [0x13103]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13103,
+ },
+ [0x13104]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13104,
+ },
+ [0x13105]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13105,
+ },
+ [0x13106]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13106,
+ },
+ [0x13107]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13107,
+ },
+ [0x13108]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13108,
+ },
+ [0x13109]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13109,
+ },
+ [0x1310A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310A,
+ },
+ [0x1310B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310B,
+ },
+ [0x1310C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F013A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310C,
+ },
+ [0x1310D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310D,
+ },
+ [0x1310E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310E,
+ },
+ [0x1310F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1310F,
+ },
+ [0x13110]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13110,
+ },
+ [0x13111]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13111,
+ },
+ [0x13112]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13112,
+ },
+ [0x13113]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13113,
+ },
+ [0x13114]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13114,
+ },
+ [0x13115]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F021A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13115,
+ },
+ [0x13116]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13116,
+ },
+ [0x13117]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13117,
+ },
+ [0x13118]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13118,
+ },
+ [0x13119]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13119,
+ },
+ [0x1311A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311A,
+ },
+ [0x1311B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311B,
+ },
+ [0x1311C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311C,
+ },
+ [0x1311D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311D,
+ },
+ [0x1311E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311E,
+ },
+ [0x1311F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1311F,
+ },
+ [0x13120]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F031A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13120,
+ },
+ [0x13121]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13121,
+ },
+ [0x13122]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13122,
+ },
+ [0x13123]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13123,
+ },
+ [0x13124]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13124,
+ },
+ [0x13125]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13125,
+ },
+ [0x13126]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13126,
+ },
+ [0x13127]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F037A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13127,
+ },
+ [0x13128]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13128,
+ },
+ [0x13129]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F038A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13129,
+ },
+ [0x1312A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312A,
+ },
+ [0x1312B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312B,
+ },
+ [0x1312C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312C,
+ },
+ [0x1312D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312D,
+ },
+ [0x1312E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312E,
+ },
+ [0x1312F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1312F,
+ },
+ [0x13130]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13130,
+ },
+ [0x13131]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F045A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13131,
+ },
+ [0x13132]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13132,
+ },
+ [0x13133]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F046A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13133,
+ },
+ [0x13134]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13134,
+ },
+ [0x13135]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F047A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13135,
+ },
+ [0x13136]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13136,
+ },
+ [0x13137]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13137,
+ },
+ [0x13138]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13138,
+ },
+ [0x13139]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13139,
+ },
+ [0x1313A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F051A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313A,
+ },
+ [0x1313B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F051B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313B,
+ },
+ [0x1313C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F051C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313C,
+ },
+ [0x1313D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313D,
+ },
+ [0x1313E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH F053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313E,
+ },
+ [0x1313F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1313F,
+ },
+ [0x13140]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13140,
+ },
+ [0x13141]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13141,
+ },
+ [0x13142]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13142,
+ },
+ [0x13143]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13143,
+ },
+ [0x13144]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13144,
+ },
+ [0x13145]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13145,
+ },
+ [0x13146]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13146,
+ },
+ [0x13147]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G007A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13147,
+ },
+ [0x13148]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G007B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13148,
+ },
+ [0x13149]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13149,
+ },
+ [0x1314A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314A,
+ },
+ [0x1314B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314B,
+ },
+ [0x1314C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314C,
+ },
+ [0x1314D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G011A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314D,
+ },
+ [0x1314E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314E,
+ },
+ [0x1314F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1314F,
+ },
+ [0x13150]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13150,
+ },
+ [0x13151]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13151,
+ },
+ [0x13152]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13152,
+ },
+ [0x13153]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13153,
+ },
+ [0x13154]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13154,
+ },
+ [0x13155]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13155,
+ },
+ [0x13156]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13156,
+ },
+ [0x13157]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G020A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13157,
+ },
+ [0x13158]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13158,
+ },
+ [0x13159]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13159,
+ },
+ [0x1315A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315A,
+ },
+ [0x1315B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315B,
+ },
+ [0x1315C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315C,
+ },
+ [0x1315D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315D,
+ },
+ [0x1315E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G026A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315E,
+ },
+ [0x1315F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1315F,
+ },
+ [0x13160]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13160,
+ },
+ [0x13161]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13161,
+ },
+ [0x13162]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13162,
+ },
+ [0x13163]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13163,
+ },
+ [0x13164]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13164,
+ },
+ [0x13165]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13165,
+ },
+ [0x13166]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13166,
+ },
+ [0x13167]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13167,
+ },
+ [0x13168]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13168,
+ },
+ [0x13169]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G036A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13169,
+ },
+ [0x1316A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316A,
+ },
+ [0x1316B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G037A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316B,
+ },
+ [0x1316C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316C,
+ },
+ [0x1316D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316D,
+ },
+ [0x1316E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316E,
+ },
+ [0x1316F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1316F,
+ },
+ [0x13170]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13170,
+ },
+ [0x13171]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13171,
+ },
+ [0x13172]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G043A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13172,
+ },
+ [0x13173]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13173,
+ },
+ [0x13174]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13174,
+ },
+ [0x13175]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G045A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13175,
+ },
+ [0x13176]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13176,
+ },
+ [0x13177]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13177,
+ },
+ [0x13178]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13178,
+ },
+ [0x13179]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13179,
+ },
+ [0x1317A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317A,
+ },
+ [0x1317B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317B,
+ },
+ [0x1317C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G052",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317C,
+ },
+ [0x1317D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G053",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317D,
+ },
+ [0x1317E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH G054",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317E,
+ },
+ [0x1317F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1317F,
+ },
+ [0x13180]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13180,
+ },
+ [0x13181]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13181,
+ },
+ [0x13182]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13182,
+ },
+ [0x13183]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13183,
+ },
+ [0x13184]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13184,
+ },
+ [0x13185]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13185,
+ },
+ [0x13186]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13186,
+ },
+ [0x13187]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH H008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13187,
+ },
+ [0x13188]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13188,
+ },
+ [0x13189]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13189,
+ },
+ [0x1318A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318A,
+ },
+ [0x1318B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318B,
+ },
+ [0x1318C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318C,
+ },
+ [0x1318D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318D,
+ },
+ [0x1318E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318E,
+ },
+ [0x1318F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1318F,
+ },
+ [0x13190]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13190,
+ },
+ [0x13191]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13191,
+ },
+ [0x13192]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13192,
+ },
+ [0x13193]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13193,
+ },
+ [0x13194]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13194,
+ },
+ [0x13195]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13195,
+ },
+ [0x13196]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I011A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13196,
+ },
+ [0x13197]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13197,
+ },
+ [0x13198]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13198,
+ },
+ [0x13199]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13199,
+ },
+ [0x1319A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH I015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319A,
+ },
+ [0x1319B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319B,
+ },
+ [0x1319C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319C,
+ },
+ [0x1319D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319D,
+ },
+ [0x1319E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319E,
+ },
+ [0x1319F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1319F,
+ },
+ [0x131A0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A0,
+ },
+ [0x131A1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A1,
+ },
+ [0x131A2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH K008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A2,
+ },
+ [0x131A3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A3,
+ },
+ [0x131A4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A4,
+ },
+ [0x131A5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A5,
+ },
+ [0x131A6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A6,
+ },
+ [0x131A7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A7,
+ },
+ [0x131A8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A8,
+ },
+ [0x131A9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131A9,
+ },
+ [0x131AA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AA,
+ },
+ [0x131AB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AB,
+ },
+ [0x131AC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH L008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AC,
+ },
+ [0x131AD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AD,
+ },
+ [0x131AE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AE,
+ },
+ [0x131AF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M001B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131AF,
+ },
+ [0x131B0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B0,
+ },
+ [0x131B1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B1,
+ },
+ [0x131B2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B2,
+ },
+ [0x131B3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B3,
+ },
+ [0x131B4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B4,
+ },
+ [0x131B5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B5,
+ },
+ [0x131B6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B6,
+ },
+ [0x131B7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B7,
+ },
+ [0x131B8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B8,
+ },
+ [0x131B9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131B9,
+ },
+ [0x131BA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BA,
+ },
+ [0x131BB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BB,
+ },
+ [0x131BC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BC,
+ },
+ [0x131BD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BD,
+ },
+ [0x131BE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BE,
+ },
+ [0x131BF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131BF,
+ },
+ [0x131C0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C0,
+ },
+ [0x131C1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C1,
+ },
+ [0x131C2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C2,
+ },
+ [0x131C3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C3,
+ },
+ [0x131C4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M012H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C4,
+ },
+ [0x131C5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C5,
+ },
+ [0x131C6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C6,
+ },
+ [0x131C7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C7,
+ },
+ [0x131C8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M015A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C8,
+ },
+ [0x131C9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131C9,
+ },
+ [0x131CA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CA,
+ },
+ [0x131CB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CB,
+ },
+ [0x131CC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CC,
+ },
+ [0x131CD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CD,
+ },
+ [0x131CE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CE,
+ },
+ [0x131CF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131CF,
+ },
+ [0x131D0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D0,
+ },
+ [0x131D1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D1,
+ },
+ [0x131D2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M022A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D2,
+ },
+ [0x131D3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D3,
+ },
+ [0x131D4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D4,
+ },
+ [0x131D5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M024A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D5,
+ },
+ [0x131D6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D6,
+ },
+ [0x131D7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D7,
+ },
+ [0x131D8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D8,
+ },
+ [0x131D9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131D9,
+ },
+ [0x131DA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M028A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DA,
+ },
+ [0x131DB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DB,
+ },
+ [0x131DC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DC,
+ },
+ [0x131DD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DD,
+ },
+ [0x131DE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M031A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DE,
+ },
+ [0x131DF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131DF,
+ },
+ [0x131E0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E0,
+ },
+ [0x131E1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M033A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E1,
+ },
+ [0x131E2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M033B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E2,
+ },
+ [0x131E3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E3,
+ },
+ [0x131E4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E4,
+ },
+ [0x131E5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E5,
+ },
+ [0x131E6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E6,
+ },
+ [0x131E7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E7,
+ },
+ [0x131E8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E8,
+ },
+ [0x131E9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131E9,
+ },
+ [0x131EA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M040A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EA,
+ },
+ [0x131EB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EB,
+ },
+ [0x131EC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EC,
+ },
+ [0x131ED]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131ED,
+ },
+ [0x131EE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH M044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EE,
+ },
+ [0x131EF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131EF,
+ },
+ [0x131F0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F0,
+ },
+ [0x131F1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F1,
+ },
+ [0x131F2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F2,
+ },
+ [0x131F3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F3,
+ },
+ [0x131F4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F4,
+ },
+ [0x131F5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F5,
+ },
+ [0x131F6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F6,
+ },
+ [0x131F7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F7,
+ },
+ [0x131F8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F8,
+ },
+ [0x131F9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131F9,
+ },
+ [0x131FA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FA,
+ },
+ [0x131FB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FB,
+ },
+ [0x131FC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FC,
+ },
+ [0x131FD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FD,
+ },
+ [0x131FE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FE,
+ },
+ [0x131FF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x131FF,
+ },
+ [0x13200]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13200,
+ },
+ [0x13201]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N018A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13201,
+ },
+ [0x13202]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N018B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13202,
+ },
+ [0x13203]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13203,
+ },
+ [0x13204]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13204,
+ },
+ [0x13205]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13205,
+ },
+ [0x13206]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13206,
+ },
+ [0x13207]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13207,
+ },
+ [0x13208]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13208,
+ },
+ [0x13209]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13209,
+ },
+ [0x1320A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N025A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320A,
+ },
+ [0x1320B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320B,
+ },
+ [0x1320C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320C,
+ },
+ [0x1320D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320D,
+ },
+ [0x1320E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320E,
+ },
+ [0x1320F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1320F,
+ },
+ [0x13210]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13210,
+ },
+ [0x13211]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13211,
+ },
+ [0x13212]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13212,
+ },
+ [0x13213]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N033A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13213,
+ },
+ [0x13214]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13214,
+ },
+ [0x13215]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N034A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13215,
+ },
+ [0x13216]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13216,
+ },
+ [0x13217]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N035A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13217,
+ },
+ [0x13218]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13218,
+ },
+ [0x13219]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13219,
+ },
+ [0x1321A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N037A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321A,
+ },
+ [0x1321B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321B,
+ },
+ [0x1321C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321C,
+ },
+ [0x1321D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321D,
+ },
+ [0x1321E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321E,
+ },
+ [0x1321F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH N042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1321F,
+ },
+ [0x13220]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13220,
+ },
+ [0x13221]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13221,
+ },
+ [0x13222]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13222,
+ },
+ [0x13223]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13223,
+ },
+ [0x13224]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13224,
+ },
+ [0x13225]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13225,
+ },
+ [0x13226]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13226,
+ },
+ [0x13227]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13227,
+ },
+ [0x13228]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13228,
+ },
+ [0x13229]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13229,
+ },
+ [0x1322A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322A,
+ },
+ [0x1322B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322B,
+ },
+ [0x1322C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322C,
+ },
+ [0x1322D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322D,
+ },
+ [0x1322E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322E,
+ },
+ [0x1322F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1322F,
+ },
+ [0x13230]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13230,
+ },
+ [0x13231]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13231,
+ },
+ [0x13232]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13232,
+ },
+ [0x13233]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13233,
+ },
+ [0x13234]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13234,
+ },
+ [0x13235]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NL020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13235,
+ },
+ [0x13236]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13236,
+ },
+ [0x13237]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13237,
+ },
+ [0x13238]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13238,
+ },
+ [0x13239]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13239,
+ },
+ [0x1323A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323A,
+ },
+ [0x1323B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323B,
+ },
+ [0x1323C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323C,
+ },
+ [0x1323D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323D,
+ },
+ [0x1323E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323E,
+ },
+ [0x1323F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1323F,
+ },
+ [0x13240]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13240,
+ },
+ [0x13241]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13241,
+ },
+ [0x13242]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU011A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13242,
+ },
+ [0x13243]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13243,
+ },
+ [0x13244]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13244,
+ },
+ [0x13245]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13245,
+ },
+ [0x13246]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13246,
+ },
+ [0x13247]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13247,
+ },
+ [0x13248]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13248,
+ },
+ [0x13249]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13249,
+ },
+ [0x1324A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU018A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324A,
+ },
+ [0x1324B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324B,
+ },
+ [0x1324C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324C,
+ },
+ [0x1324D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324D,
+ },
+ [0x1324E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324E,
+ },
+ [0x1324F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH NU022A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1324F,
+ },
+ [0x13250]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13250,
+ },
+ [0x13251]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13251,
+ },
+ [0x13252]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13252,
+ },
+ [0x13253]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13253,
+ },
+ [0x13254]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13254,
+ },
+ [0x13255]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13255,
+ },
+ [0x13256]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13256,
+ },
+ [0x13257]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13257,
+ },
+ [0x13258]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006A",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13258,
+ },
+ [0x13259]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006B",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13259,
+ },
+ [0x1325A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006C",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x1325A,
+ },
+ [0x1325B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006D",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1325B,
+ },
+ [0x1325C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006E",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1325C,
+ },
+ [0x1325D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O006F",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1325D,
+ },
+ [0x1325E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1325E,
+ },
+ [0x1325F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1325F,
+ },
+ [0x13260]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13260,
+ },
+ [0x13261]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13261,
+ },
+ [0x13262]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13262,
+ },
+ [0x13263]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O010B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13263,
+ },
+ [0x13264]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O010C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13264,
+ },
+ [0x13265]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13265,
+ },
+ [0x13266]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13266,
+ },
+ [0x13267]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13267,
+ },
+ [0x13268]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13268,
+ },
+ [0x13269]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13269,
+ },
+ [0x1326A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326A,
+ },
+ [0x1326B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326B,
+ },
+ [0x1326C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326C,
+ },
+ [0x1326D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326D,
+ },
+ [0x1326E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O019A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326E,
+ },
+ [0x1326F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1326F,
+ },
+ [0x13270]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O020A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13270,
+ },
+ [0x13271]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13271,
+ },
+ [0x13272]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13272,
+ },
+ [0x13273]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13273,
+ },
+ [0x13274]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13274,
+ },
+ [0x13275]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O024A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13275,
+ },
+ [0x13276]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13276,
+ },
+ [0x13277]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O025A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13277,
+ },
+ [0x13278]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13278,
+ },
+ [0x13279]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13279,
+ },
+ [0x1327A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327A,
+ },
+ [0x1327B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327B,
+ },
+ [0x1327C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O029A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327C,
+ },
+ [0x1327D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327D,
+ },
+ [0x1327E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O030A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327E,
+ },
+ [0x1327F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1327F,
+ },
+ [0x13280]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13280,
+ },
+ [0x13281]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13281,
+ },
+ [0x13282]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O033A",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x13282,
+ },
+ [0x13283]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13283,
+ },
+ [0x13284]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13284,
+ },
+ [0x13285]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13285,
+ },
+ [0x13286]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036A",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13286,
+ },
+ [0x13287]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036B",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x13287,
+ },
+ [0x13288]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036C",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13288,
+ },
+ [0x13289]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O036D",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x13289,
+ },
+ [0x1328A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328A,
+ },
+ [0x1328B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328B,
+ },
+ [0x1328C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328C,
+ },
+ [0x1328D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328D,
+ },
+ [0x1328E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328E,
+ },
+ [0x1328F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1328F,
+ },
+ [0x13290]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13290,
+ },
+ [0x13291]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13291,
+ },
+ [0x13292]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13292,
+ },
+ [0x13293]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13293,
+ },
+ [0x13294]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O047",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13294,
+ },
+ [0x13295]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O048",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13295,
+ },
+ [0x13296]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O049",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13296,
+ },
+ [0x13297]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O050",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13297,
+ },
+ [0x13298]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O050A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13298,
+ },
+ [0x13299]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O050B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13299,
+ },
+ [0x1329A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH O051",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329A,
+ },
+ [0x1329B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329B,
+ },
+ [0x1329C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329C,
+ },
+ [0x1329D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329D,
+ },
+ [0x1329E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329E,
+ },
+ [0x1329F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1329F,
+ },
+ [0x132A0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A0,
+ },
+ [0x132A1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A1,
+ },
+ [0x132A2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A2,
+ },
+ [0x132A3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A3,
+ },
+ [0x132A4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A4,
+ },
+ [0x132A5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A5,
+ },
+ [0x132A6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A6,
+ },
+ [0x132A7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH P011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A7,
+ },
+ [0x132A8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A8,
+ },
+ [0x132A9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132A9,
+ },
+ [0x132AA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AA,
+ },
+ [0x132AB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AB,
+ },
+ [0x132AC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AC,
+ },
+ [0x132AD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AD,
+ },
+ [0x132AE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Q007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AE,
+ },
+ [0x132AF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132AF,
+ },
+ [0x132B0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B0,
+ },
+ [0x132B1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B1,
+ },
+ [0x132B2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B2,
+ },
+ [0x132B3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B3,
+ },
+ [0x132B4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R003B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B4,
+ },
+ [0x132B5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B5,
+ },
+ [0x132B6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B6,
+ },
+ [0x132B7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B7,
+ },
+ [0x132B8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B8,
+ },
+ [0x132B9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132B9,
+ },
+ [0x132BA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BA,
+ },
+ [0x132BB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BB,
+ },
+ [0x132BC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BC,
+ },
+ [0x132BD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BD,
+ },
+ [0x132BE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BE,
+ },
+ [0x132BF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132BF,
+ },
+ [0x132C0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C0,
+ },
+ [0x132C1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C1,
+ },
+ [0x132C2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C2,
+ },
+ [0x132C3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C3,
+ },
+ [0x132C4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C4,
+ },
+ [0x132C5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C5,
+ },
+ [0x132C6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C6,
+ },
+ [0x132C7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C7,
+ },
+ [0x132C8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C8,
+ },
+ [0x132C9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132C9,
+ },
+ [0x132CA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CA,
+ },
+ [0x132CB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CB,
+ },
+ [0x132CC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CC,
+ },
+ [0x132CD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CD,
+ },
+ [0x132CE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CE,
+ },
+ [0x132CF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132CF,
+ },
+ [0x132D0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH R029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D0,
+ },
+ [0x132D1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D1,
+ },
+ [0x132D2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D2,
+ },
+ [0x132D3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D3,
+ },
+ [0x132D4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D4,
+ },
+ [0x132D5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D5,
+ },
+ [0x132D6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D6,
+ },
+ [0x132D7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D7,
+ },
+ [0x132D8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D8,
+ },
+ [0x132D9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132D9,
+ },
+ [0x132DA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DA,
+ },
+ [0x132DB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DB,
+ },
+ [0x132DC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DC,
+ },
+ [0x132DD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DD,
+ },
+ [0x132DE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DE,
+ },
+ [0x132DF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132DF,
+ },
+ [0x132E0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E0,
+ },
+ [0x132E1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S014A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E1,
+ },
+ [0x132E2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S014B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E2,
+ },
+ [0x132E3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E3,
+ },
+ [0x132E4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E4,
+ },
+ [0x132E5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E5,
+ },
+ [0x132E6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E6,
+ },
+ [0x132E7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E7,
+ },
+ [0x132E8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E8,
+ },
+ [0x132E9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132E9,
+ },
+ [0x132EA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EA,
+ },
+ [0x132EB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EB,
+ },
+ [0x132EC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EC,
+ },
+ [0x132ED]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132ED,
+ },
+ [0x132EE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EE,
+ },
+ [0x132EF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132EF,
+ },
+ [0x132F0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S026A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F0,
+ },
+ [0x132F1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S026B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F1,
+ },
+ [0x132F2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F2,
+ },
+ [0x132F3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F3,
+ },
+ [0x132F4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F4,
+ },
+ [0x132F5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F5,
+ },
+ [0x132F6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F6,
+ },
+ [0x132F7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F7,
+ },
+ [0x132F8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F8,
+ },
+ [0x132F9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132F9,
+ },
+ [0x132FA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FA,
+ },
+ [0x132FB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S035A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FB,
+ },
+ [0x132FC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FC,
+ },
+ [0x132FD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FD,
+ },
+ [0x132FE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FE,
+ },
+ [0x132FF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x132FF,
+ },
+ [0x13300]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13300,
+ },
+ [0x13301]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13301,
+ },
+ [0x13302]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13302,
+ },
+ [0x13303]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S043",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13303,
+ },
+ [0x13304]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S044",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13304,
+ },
+ [0x13305]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S045",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13305,
+ },
+ [0x13306]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH S046",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13306,
+ },
+ [0x13307]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13307,
+ },
+ [0x13308]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13308,
+ },
+ [0x13309]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13309,
+ },
+ [0x1330A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330A,
+ },
+ [0x1330B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330B,
+ },
+ [0x1330C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330C,
+ },
+ [0x1330D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330D,
+ },
+ [0x1330E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330E,
+ },
+ [0x1330F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T007A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1330F,
+ },
+ [0x13310]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13310,
+ },
+ [0x13311]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13311,
+ },
+ [0x13312]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13312,
+ },
+ [0x13313]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13313,
+ },
+ [0x13314]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13314,
+ },
+ [0x13315]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13315,
+ },
+ [0x13316]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T011A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13316,
+ },
+ [0x13317]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13317,
+ },
+ [0x13318]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13318,
+ },
+ [0x13319]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13319,
+ },
+ [0x1331A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331A,
+ },
+ [0x1331B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331B,
+ },
+ [0x1331C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331C,
+ },
+ [0x1331D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331D,
+ },
+ [0x1331E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331E,
+ },
+ [0x1331F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1331F,
+ },
+ [0x13320]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13320,
+ },
+ [0x13321]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13321,
+ },
+ [0x13322]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13322,
+ },
+ [0x13323]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13323,
+ },
+ [0x13324]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13324,
+ },
+ [0x13325]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13325,
+ },
+ [0x13326]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13326,
+ },
+ [0x13327]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13327,
+ },
+ [0x13328]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13328,
+ },
+ [0x13329]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13329,
+ },
+ [0x1332A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332A,
+ },
+ [0x1332B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332B,
+ },
+ [0x1332C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332C,
+ },
+ [0x1332D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T032A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332D,
+ },
+ [0x1332E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332E,
+ },
+ [0x1332F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T033A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1332F,
+ },
+ [0x13330]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13330,
+ },
+ [0x13331]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13331,
+ },
+ [0x13332]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH T036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13332,
+ },
+ [0x13333]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13333,
+ },
+ [0x13334]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13334,
+ },
+ [0x13335]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13335,
+ },
+ [0x13336]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13336,
+ },
+ [0x13337]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13337,
+ },
+ [0x13338]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13338,
+ },
+ [0x13339]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13339,
+ },
+ [0x1333A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U006B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333A,
+ },
+ [0x1333B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333B,
+ },
+ [0x1333C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333C,
+ },
+ [0x1333D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333D,
+ },
+ [0x1333E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333E,
+ },
+ [0x1333F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1333F,
+ },
+ [0x13340]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13340,
+ },
+ [0x13341]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13341,
+ },
+ [0x13342]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13342,
+ },
+ [0x13343]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13343,
+ },
+ [0x13344]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13344,
+ },
+ [0x13345]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13345,
+ },
+ [0x13346]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13346,
+ },
+ [0x13347]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13347,
+ },
+ [0x13348]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13348,
+ },
+ [0x13349]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13349,
+ },
+ [0x1334A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334A,
+ },
+ [0x1334B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334B,
+ },
+ [0x1334C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U023A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334C,
+ },
+ [0x1334D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334D,
+ },
+ [0x1334E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334E,
+ },
+ [0x1334F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1334F,
+ },
+ [0x13350]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13350,
+ },
+ [0x13351]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13351,
+ },
+ [0x13352]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13352,
+ },
+ [0x13353]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U029A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13353,
+ },
+ [0x13354]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13354,
+ },
+ [0x13355]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13355,
+ },
+ [0x13356]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13356,
+ },
+ [0x13357]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U032A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13357,
+ },
+ [0x13358]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13358,
+ },
+ [0x13359]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13359,
+ },
+ [0x1335A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335A,
+ },
+ [0x1335B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335B,
+ },
+ [0x1335C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335C,
+ },
+ [0x1335D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335D,
+ },
+ [0x1335E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335E,
+ },
+ [0x1335F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1335F,
+ },
+ [0x13360]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U041",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13360,
+ },
+ [0x13361]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH U042",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13361,
+ },
+ [0x13362]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13362,
+ },
+ [0x13363]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13363,
+ },
+ [0x13364]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13364,
+ },
+ [0x13365]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13365,
+ },
+ [0x13366]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13366,
+ },
+ [0x13367]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13367,
+ },
+ [0x13368]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13368,
+ },
+ [0x13369]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13369,
+ },
+ [0x1336A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336A,
+ },
+ [0x1336B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V001I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336B,
+ },
+ [0x1336C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336C,
+ },
+ [0x1336D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336D,
+ },
+ [0x1336E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336E,
+ },
+ [0x1336F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1336F,
+ },
+ [0x13370]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13370,
+ },
+ [0x13371]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13371,
+ },
+ [0x13372]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13372,
+ },
+ [0x13373]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V007A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13373,
+ },
+ [0x13374]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V007B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13374,
+ },
+ [0x13375]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13375,
+ },
+ [0x13376]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13376,
+ },
+ [0x13377]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13377,
+ },
+ [0x13378]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13378,
+ },
+ [0x13379]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V011A",
+ direction="l",
+ linebreak="op",
+ unicodeslot=0x13379,
+ },
+ [0x1337A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V011B",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1337A,
+ },
+ [0x1337B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V011C",
+ direction="l",
+ linebreak="cl",
+ unicodeslot=0x1337B,
+ },
+ [0x1337C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337C,
+ },
+ [0x1337D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V012A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337D,
+ },
+ [0x1337E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V012B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337E,
+ },
+ [0x1337F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1337F,
+ },
+ [0x13380]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13380,
+ },
+ [0x13381]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13381,
+ },
+ [0x13382]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13382,
+ },
+ [0x13383]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13383,
+ },
+ [0x13384]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13384,
+ },
+ [0x13385]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13385,
+ },
+ [0x13386]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13386,
+ },
+ [0x13387]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13387,
+ },
+ [0x13388]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13388,
+ },
+ [0x13389]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13389,
+ },
+ [0x1338A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338A,
+ },
+ [0x1338B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338B,
+ },
+ [0x1338C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338C,
+ },
+ [0x1338D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338D,
+ },
+ [0x1338E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338E,
+ },
+ [0x1338F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1338F,
+ },
+ [0x13390]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13390,
+ },
+ [0x13391]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13391,
+ },
+ [0x13392]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V020L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13392,
+ },
+ [0x13393]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13393,
+ },
+ [0x13394]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13394,
+ },
+ [0x13395]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13395,
+ },
+ [0x13396]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V023A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13396,
+ },
+ [0x13397]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13397,
+ },
+ [0x13398]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13398,
+ },
+ [0x13399]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13399,
+ },
+ [0x1339A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339A,
+ },
+ [0x1339B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339B,
+ },
+ [0x1339C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V028A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339C,
+ },
+ [0x1339D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339D,
+ },
+ [0x1339E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V029A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339E,
+ },
+ [0x1339F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1339F,
+ },
+ [0x133A0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V030A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A0,
+ },
+ [0x133A1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A1,
+ },
+ [0x133A2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V031A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A2,
+ },
+ [0x133A3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A3,
+ },
+ [0x133A4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V033",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A4,
+ },
+ [0x133A5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V033A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A5,
+ },
+ [0x133A6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V034",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A6,
+ },
+ [0x133A7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V035",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A7,
+ },
+ [0x133A8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V036",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A8,
+ },
+ [0x133A9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V037",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133A9,
+ },
+ [0x133AA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V037A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AA,
+ },
+ [0x133AB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V038",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AB,
+ },
+ [0x133AC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V039",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AC,
+ },
+ [0x133AD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V040",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AD,
+ },
+ [0x133AE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH V040A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AE,
+ },
+ [0x133AF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133AF,
+ },
+ [0x133B0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B0,
+ },
+ [0x133B1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B1,
+ },
+ [0x133B2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B2,
+ },
+ [0x133B3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B3,
+ },
+ [0x133B4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B4,
+ },
+ [0x133B5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B5,
+ },
+ [0x133B6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B6,
+ },
+ [0x133B7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B7,
+ },
+ [0x133B8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B8,
+ },
+ [0x133B9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W009A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133B9,
+ },
+ [0x133BA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BA,
+ },
+ [0x133BB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W010A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BB,
+ },
+ [0x133BC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BC,
+ },
+ [0x133BD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BD,
+ },
+ [0x133BE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BE,
+ },
+ [0x133BF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133BF,
+ },
+ [0x133C0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W014A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C0,
+ },
+ [0x133C1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C1,
+ },
+ [0x133C2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C2,
+ },
+ [0x133C3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C3,
+ },
+ [0x133C4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W017A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C4,
+ },
+ [0x133C5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C5,
+ },
+ [0x133C6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W018A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C6,
+ },
+ [0x133C7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C7,
+ },
+ [0x133C8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C8,
+ },
+ [0x133C9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133C9,
+ },
+ [0x133CA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CA,
+ },
+ [0x133CB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CB,
+ },
+ [0x133CC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CC,
+ },
+ [0x133CD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W024A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CD,
+ },
+ [0x133CE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH W025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CE,
+ },
+ [0x133CF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133CF,
+ },
+ [0x133D0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D0,
+ },
+ [0x133D1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D1,
+ },
+ [0x133D2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D2,
+ },
+ [0x133D3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X004A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D3,
+ },
+ [0x133D4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X004B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D4,
+ },
+ [0x133D5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D5,
+ },
+ [0x133D6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D6,
+ },
+ [0x133D7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X006A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D7,
+ },
+ [0x133D8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D8,
+ },
+ [0x133D9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133D9,
+ },
+ [0x133DA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH X008A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DA,
+ },
+ [0x133DB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DB,
+ },
+ [0x133DC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y001A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DC,
+ },
+ [0x133DD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DD,
+ },
+ [0x133DE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DE,
+ },
+ [0x133DF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133DF,
+ },
+ [0x133E0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E0,
+ },
+ [0x133E1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E1,
+ },
+ [0x133E2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E2,
+ },
+ [0x133E3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Y008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E3,
+ },
+ [0x133E4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E4,
+ },
+ [0x133E5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E5,
+ },
+ [0x133E6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E6,
+ },
+ [0x133E7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E7,
+ },
+ [0x133E8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E8,
+ },
+ [0x133E9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z002D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133E9,
+ },
+ [0x133EA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EA,
+ },
+ [0x133EB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z003A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EB,
+ },
+ [0x133EC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z003B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EC,
+ },
+ [0x133ED]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133ED,
+ },
+ [0x133EE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z004A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EE,
+ },
+ [0x133EF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133EF,
+ },
+ [0x133F0]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z005A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F0,
+ },
+ [0x133F1]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F1,
+ },
+ [0x133F2]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F2,
+ },
+ [0x133F3]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F3,
+ },
+ [0x133F4]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F4,
+ },
+ [0x133F5]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F5,
+ },
+ [0x133F6]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F6,
+ },
+ [0x133F7]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F7,
+ },
+ [0x133F8]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F8,
+ },
+ [0x133F9]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133F9,
+ },
+ [0x133FA]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FA,
+ },
+ [0x133FB]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FB,
+ },
+ [0x133FC]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FC,
+ },
+ [0x133FD]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FD,
+ },
+ [0x133FE]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FE,
+ },
+ [0x133FF]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x133FF,
+ },
+ [0x13400]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13400,
+ },
+ [0x13401]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13401,
+ },
+ [0x13402]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13402,
+ },
+ [0x13403]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z015I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13403,
+ },
+ [0x13404]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13404,
+ },
+ [0x13405]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13405,
+ },
+ [0x13406]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13406,
+ },
+ [0x13407]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13407,
+ },
+ [0x13408]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13408,
+ },
+ [0x13409]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13409,
+ },
+ [0x1340A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340A,
+ },
+ [0x1340B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340B,
+ },
+ [0x1340C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH Z016H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340C,
+ },
+ [0x1340D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA001",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340D,
+ },
+ [0x1340E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA002",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340E,
+ },
+ [0x1340F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA003",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1340F,
+ },
+ [0x13410]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA004",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13410,
+ },
+ [0x13411]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA005",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13411,
+ },
+ [0x13412]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA006",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13412,
+ },
+ [0x13413]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA007",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13413,
+ },
+ [0x13414]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA007A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13414,
+ },
+ [0x13415]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA007B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13415,
+ },
+ [0x13416]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA008",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13416,
+ },
+ [0x13417]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA009",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13417,
+ },
+ [0x13418]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA010",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13418,
+ },
+ [0x13419]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA011",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13419,
+ },
+ [0x1341A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA012",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341A,
+ },
+ [0x1341B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA013",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341B,
+ },
+ [0x1341C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA014",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341C,
+ },
+ [0x1341D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA015",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341D,
+ },
+ [0x1341E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA016",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341E,
+ },
+ [0x1341F]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA017",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1341F,
+ },
+ [0x13420]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA018",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13420,
+ },
+ [0x13421]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA019",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13421,
+ },
+ [0x13422]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA020",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13422,
+ },
+ [0x13423]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA021",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13423,
+ },
+ [0x13424]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA022",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13424,
+ },
+ [0x13425]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA023",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13425,
+ },
+ [0x13426]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA024",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13426,
+ },
+ [0x13427]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA025",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13427,
+ },
+ [0x13428]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA026",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13428,
+ },
+ [0x13429]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA027",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x13429,
+ },
+ [0x1342A]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA028",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342A,
+ },
+ [0x1342B]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA029",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342B,
+ },
+ [0x1342C]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA030",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342C,
+ },
+ [0x1342D]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA031",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342D,
+ },
+ [0x1342E]={
+ category="lo",
+ description="EGYPTIAN HIEROGLYPH AA032",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1342E,
+ },
+ [0x16800]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NGKUE MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16800,
+ },
+ [0x16801]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A GBIEE FON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16801,
+ },
+ [0x16802]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16802,
+ },
+ [0x16803]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PON MFON PIPAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16803,
+ },
+ [0x16804]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NAA MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16804,
+ },
+ [0x16805]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHUENSHUET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16805,
+ },
+ [0x16806]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TITA MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16806,
+ },
+ [0x16807]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NZA MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16807,
+ },
+ [0x16808]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHINDA PA NJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16808,
+ },
+ [0x16809]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PON PA NJI PIPAEMGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16809,
+ },
+ [0x1680A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PON PA NJI PIPAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680A,
+ },
+ [0x1680B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEMBGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680B,
+ },
+ [0x1680C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TU MAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680C,
+ },
+ [0x1680D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NGANGU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680D,
+ },
+ [0x1680E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEMVEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680E,
+ },
+ [0x1680F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MANSUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1680F,
+ },
+ [0x16810]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MVEUAENGAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16810,
+ },
+ [0x16811]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SEUNYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16811,
+ },
+ [0x16812]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NTOQPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16812,
+ },
+ [0x16813]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KEUKEUTNDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16813,
+ },
+ [0x16814]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NKINDI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16814,
+ },
+ [0x16815]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16815,
+ },
+ [0x16816]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NGKUENZEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16816,
+ },
+ [0x16817]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LAPAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16817,
+ },
+ [0x16818]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LET KUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16818,
+ },
+ [0x16819]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NTAP MFAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16819,
+ },
+ [0x1681A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEKEUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681A,
+ },
+ [0x1681B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PASHAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681B,
+ },
+ [0x1681C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A GHEUAERAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681C,
+ },
+ [0x1681D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PAMSHAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681D,
+ },
+ [0x1681E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MON NGGEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681E,
+ },
+ [0x1681F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NZUN MEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1681F,
+ },
+ [0x16820]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A U YUQ NAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16820,
+ },
+ [0x16821]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A GHEUAEGHEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16821,
+ },
+ [0x16822]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NTAP NTAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16822,
+ },
+ [0x16823]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SISA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16823,
+ },
+ [0x16824]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MGBASA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16824,
+ },
+ [0x16825]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MEUNJOMNDEUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16825,
+ },
+ [0x16826]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MOOMPUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16826,
+ },
+ [0x16827]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KAFA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16827,
+ },
+ [0x16828]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PA LEERAEWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16828,
+ },
+ [0x16829]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NDA LEERAEWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16829,
+ },
+ [0x1682A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682A,
+ },
+ [0x1682B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEMKPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682B,
+ },
+ [0x1682C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NIKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682C,
+ },
+ [0x1682D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682D,
+ },
+ [0x1682E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682E,
+ },
+ [0x1682F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1682F,
+ },
+ [0x16830]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SONJAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16830,
+ },
+ [0x16831]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TEUTEUWEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16831,
+ },
+ [0x16832]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAENYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16832,
+ },
+ [0x16833]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16833,
+ },
+ [0x16834]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NDAANGGEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16834,
+ },
+ [0x16835]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16835,
+ },
+ [0x16836]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MOOMEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16836,
+ },
+ [0x16837]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16837,
+ },
+ [0x16838]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LOMMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16838,
+ },
+ [0x16839]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A FIRI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16839,
+ },
+ [0x1683A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A ROM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683A,
+ },
+ [0x1683B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KPOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683B,
+ },
+ [0x1683C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683C,
+ },
+ [0x1683D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAP PIEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683D,
+ },
+ [0x1683E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHIRAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683E,
+ },
+ [0x1683F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NTAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1683F,
+ },
+ [0x16840]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SHOQ NSHUT YUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16840,
+ },
+ [0x16841]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NYIT MONGKEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16841,
+ },
+ [0x16842]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PAARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16842,
+ },
+ [0x16843]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NKAARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16843,
+ },
+ [0x16844]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A UNKNOWN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16844,
+ },
+ [0x16845]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NGGEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16845,
+ },
+ [0x16846]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAESI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16846,
+ },
+ [0x16847]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NJAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16847,
+ },
+ [0x16848]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MBANYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16848,
+ },
+ [0x16849]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NYET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16849,
+ },
+ [0x1684A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A TEUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684A,
+ },
+ [0x1684B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A SOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684B,
+ },
+ [0x1684C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A PAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684C,
+ },
+ [0x1684D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NSHIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684D,
+ },
+ [0x1684E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684E,
+ },
+ [0x1684F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1684F,
+ },
+ [0x16850]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A KAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16850,
+ },
+ [0x16851]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16851,
+ },
+ [0x16852]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A VEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16852,
+ },
+ [0x16853]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16853,
+ },
+ [0x16854]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16854,
+ },
+ [0x16855]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A NAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16855,
+ },
+ [0x16856]={
+ category="lo",
+ description="BAMUM LETTER PHASE-A MBAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16856,
+ },
+ [0x16857]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NSHUET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16857,
+ },
+ [0x16858]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B TU MAEMGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16858,
+ },
+ [0x16859]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16859,
+ },
+ [0x1685A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SET TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685A,
+ },
+ [0x1685B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B LOM NTEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685B,
+ },
+ [0x1685C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBA MAELEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685C,
+ },
+ [0x1685D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KIEEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685D,
+ },
+ [0x1685E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B YEURAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685E,
+ },
+ [0x1685F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBAARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1685F,
+ },
+ [0x16860]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16860,
+ },
+ [0x16861]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B PEESHI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16861,
+ },
+ [0x16862]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B YAFU LEERAEWA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16862,
+ },
+ [0x16863]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B LAM NSHUT NYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16863,
+ },
+ [0x16864]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NTIEE SHEUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16864,
+ },
+ [0x16865]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NDU NJAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16865,
+ },
+ [0x16866]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B GHEUGHEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16866,
+ },
+ [0x16867]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B PIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16867,
+ },
+ [0x16868]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B TU NSIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16868,
+ },
+ [0x16869]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SHET NJAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16869,
+ },
+ [0x1686A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SHEUAEQTU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686A,
+ },
+ [0x1686B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MFON TEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686B,
+ },
+ [0x1686C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBIT MBAAKET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686C,
+ },
+ [0x1686D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NYI NTEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686D,
+ },
+ [0x1686E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KEUPUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686E,
+ },
+ [0x1686F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B GHEUGHEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1686F,
+ },
+ [0x16870]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KEUYEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16870,
+ },
+ [0x16871]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B LAANAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16871,
+ },
+ [0x16872]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B PARUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16872,
+ },
+ [0x16873]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B VEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16873,
+ },
+ [0x16874]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGKINDI MVOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16874,
+ },
+ [0x16875]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGGEU MBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16875,
+ },
+ [0x16876]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B WUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16876,
+ },
+ [0x16877]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SAKEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16877,
+ },
+ [0x16878]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B TAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16878,
+ },
+ [0x16879]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MEUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16879,
+ },
+ [0x1687A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGGUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687A,
+ },
+ [0x1687B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGGUOQ LARGE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687B,
+ },
+ [0x1687C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MFIYAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687C,
+ },
+ [0x1687D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B SUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687D,
+ },
+ [0x1687E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBEURI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687E,
+ },
+ [0x1687F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MONTIEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1687F,
+ },
+ [0x16880]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NYAEMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16880,
+ },
+ [0x16881]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B PUNGAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16881,
+ },
+ [0x16882]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MEUT NGGEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16882,
+ },
+ [0x16883]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B FEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16883,
+ },
+ [0x16884]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MBUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16884,
+ },
+ [0x16885]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16885,
+ },
+ [0x16886]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16886,
+ },
+ [0x16887]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MA NJEUAENA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16887,
+ },
+ [0x16888]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MA NJUQA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16888,
+ },
+ [0x16889]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B LET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16889,
+ },
+ [0x1688A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGGAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688A,
+ },
+ [0x1688B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NSEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688B,
+ },
+ [0x1688C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688C,
+ },
+ [0x1688D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B KIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688D,
+ },
+ [0x1688E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-B NGOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688E,
+ },
+ [0x1688F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGKUE MAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1688F,
+ },
+ [0x16890]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NZA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16890,
+ },
+ [0x16891]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16891,
+ },
+ [0x16892]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C WANGKUOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16892,
+ },
+ [0x16893]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16893,
+ },
+ [0x16894]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDEUAEREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16894,
+ },
+ [0x16895]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGKAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16895,
+ },
+ [0x16896]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C GHARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16896,
+ },
+ [0x16897]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBEEKEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16897,
+ },
+ [0x16898]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C GBAYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16898,
+ },
+ [0x16899]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NYIR MKPARAQ MEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16899,
+ },
+ [0x1689A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NTU MBIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689A,
+ },
+ [0x1689B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689B,
+ },
+ [0x1689C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C PIRIEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689C,
+ },
+ [0x1689D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDOMBU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689D,
+ },
+ [0x1689E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBAA CABBAGE-TREE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689E,
+ },
+ [0x1689F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEUSHEUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1689F,
+ },
+ [0x168A0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C GHAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A0,
+ },
+ [0x168A1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEUKAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A1,
+ },
+ [0x168A2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YU MUOMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A2,
+ },
+ [0x168A3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NZEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A3,
+ },
+ [0x168A4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A4,
+ },
+ [0x168A5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSEUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A5,
+ },
+ [0x168A6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A6,
+ },
+ [0x168A7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YEUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A7,
+ },
+ [0x168A8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KPARAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A8,
+ },
+ [0x168A9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168A9,
+ },
+ [0x168AA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AA,
+ },
+ [0x168AB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDIDA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AB,
+ },
+ [0x168AC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TAASHAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AC,
+ },
+ [0x168AD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AD,
+ },
+ [0x168AE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TITA YUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AE,
+ },
+ [0x168AF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168AF,
+ },
+ [0x168B0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGUAEN NYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B0,
+ },
+ [0x168B1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C VEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B1,
+ },
+ [0x168B2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NANSANAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B2,
+ },
+ [0x168B3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MA KEUAERI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B3,
+ },
+ [0x168B4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NTAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B4,
+ },
+ [0x168B5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGUON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B5,
+ },
+ [0x168B6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C LAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B6,
+ },
+ [0x168B7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBIRIEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B7,
+ },
+ [0x168B8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MGBASAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B8,
+ },
+ [0x168B9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NTEUNGBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168B9,
+ },
+ [0x168BA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TEUTEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BA,
+ },
+ [0x168BB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BB,
+ },
+ [0x168BC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C FUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BC,
+ },
+ [0x168BD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BD,
+ },
+ [0x168BE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BE,
+ },
+ [0x168BF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSHAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168BF,
+ },
+ [0x168C0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C BUNG",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C0,
+ },
+ [0x168C1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C VEUAEPEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C1,
+ },
+ [0x168C2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBERAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C2,
+ },
+ [0x168C3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C3,
+ },
+ [0x168C4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C4,
+ },
+ [0x168C5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C LAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C5,
+ },
+ [0x168C6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TITUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C6,
+ },
+ [0x168C7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSUOT NGOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C7,
+ },
+ [0x168C8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C8,
+ },
+ [0x168C9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168C9,
+ },
+ [0x168CA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CA,
+ },
+ [0x168CB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MAESI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CB,
+ },
+ [0x168CC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CC,
+ },
+ [0x168CD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CD,
+ },
+ [0x168CE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CE,
+ },
+ [0x168CF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168CF,
+ },
+ [0x168D0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D0,
+ },
+ [0x168D1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C WUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D1,
+ },
+ [0x168D2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGGUEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D2,
+ },
+ [0x168D3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D3,
+ },
+ [0x168D4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NTEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D4,
+ },
+ [0x168D5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KUOP NKAARAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D5,
+ },
+ [0x168D6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NSUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D6,
+ },
+ [0x168D7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D7,
+ },
+ [0x168D8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MA NSIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D8,
+ },
+ [0x168D9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168D9,
+ },
+ [0x168DA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NDAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DA,
+ },
+ [0x168DB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SHUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DB,
+ },
+ [0x168DC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SETFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DC,
+ },
+ [0x168DD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DD,
+ },
+ [0x168DE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MAEMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DE,
+ },
+ [0x168DF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBANYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168DF,
+ },
+ [0x168E0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEUSEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E0,
+ },
+ [0x168E1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E1,
+ },
+ [0x168E2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E2,
+ },
+ [0x168E3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MBAA PICKET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E3,
+ },
+ [0x168E4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C YUWOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E4,
+ },
+ [0x168E5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NJEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E5,
+ },
+ [0x168E6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E6,
+ },
+ [0x168E7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C MUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E7,
+ },
+ [0x168E8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C SHIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E8,
+ },
+ [0x168E9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEN LAW",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168E9,
+ },
+ [0x168EA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C KEN FATIGUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EA,
+ },
+ [0x168EB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NGAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EB,
+ },
+ [0x168EC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C NAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EC,
+ },
+ [0x168ED]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C LIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168ED,
+ },
+ [0x168EE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C PIN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EE,
+ },
+ [0x168EF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C PEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168EF,
+ },
+ [0x168F0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-C TET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F0,
+ },
+ [0x168F1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MBUO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F1,
+ },
+ [0x168F2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D WAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F2,
+ },
+ [0x168F3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F3,
+ },
+ [0x168F4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F4,
+ },
+ [0x168F5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F5,
+ },
+ [0x168F6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F6,
+ },
+ [0x168F7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F7,
+ },
+ [0x168F8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F8,
+ },
+ [0x168F9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGAAMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168F9,
+ },
+ [0x168FA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FA,
+ },
+ [0x168FB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D WUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FB,
+ },
+ [0x168FC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FC,
+ },
+ [0x168FD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FD,
+ },
+ [0x168FE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FE,
+ },
+ [0x168FF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KEUAETMEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x168FF,
+ },
+ [0x16900]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16900,
+ },
+ [0x16901]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16901,
+ },
+ [0x16902]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16902,
+ },
+ [0x16903]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16903,
+ },
+ [0x16904]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16904,
+ },
+ [0x16905]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YAEMMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16905,
+ },
+ [0x16906]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KUOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16906,
+ },
+ [0x16907]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16907,
+ },
+ [0x16908]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16908,
+ },
+ [0x16909]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NDEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16909,
+ },
+ [0x1690A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MALEERI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690A,
+ },
+ [0x1690B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690B,
+ },
+ [0x1690C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690C,
+ },
+ [0x1690D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690D,
+ },
+ [0x1690E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690E,
+ },
+ [0x1690F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KEUOT MBUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1690F,
+ },
+ [0x16910]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKEURI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16910,
+ },
+ [0x16911]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16911,
+ },
+ [0x16912]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D GHAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16912,
+ },
+ [0x16913]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16913,
+ },
+ [0x16914]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D FEUFEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16914,
+ },
+ [0x16915]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NDEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16915,
+ },
+ [0x16916]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MGBOFUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16916,
+ },
+ [0x16917]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LEUAEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16917,
+ },
+ [0x16918]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NDON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16918,
+ },
+ [0x16919]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MONI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16919,
+ },
+ [0x1691A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MGBEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691A,
+ },
+ [0x1691B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PUUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691B,
+ },
+ [0x1691C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MGBIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691C,
+ },
+ [0x1691D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691D,
+ },
+ [0x1691E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691E,
+ },
+ [0x1691F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSIEEP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1691F,
+ },
+ [0x16920]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MBAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16920,
+ },
+ [0x16921]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KWAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16921,
+ },
+ [0x16922]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NYET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16922,
+ },
+ [0x16923]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TEUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16923,
+ },
+ [0x16924]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16924,
+ },
+ [0x16925]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YUWOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16925,
+ },
+ [0x16926]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16926,
+ },
+ [0x16927]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D RAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16927,
+ },
+ [0x16928]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16928,
+ },
+ [0x16929]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16929,
+ },
+ [0x1692A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692A,
+ },
+ [0x1692B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSIEET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692B,
+ },
+ [0x1692C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KEUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692C,
+ },
+ [0x1692D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PIP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692D,
+ },
+ [0x1692E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PEUTAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692E,
+ },
+ [0x1692F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NYUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1692F,
+ },
+ [0x16930]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16930,
+ },
+ [0x16931]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16931,
+ },
+ [0x16932]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MFIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16932,
+ },
+ [0x16933]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGWAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16933,
+ },
+ [0x16934]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YUOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16934,
+ },
+ [0x16935]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16935,
+ },
+ [0x16936]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D YUOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16936,
+ },
+ [0x16937]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NDAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16937,
+ },
+ [0x16938]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NTEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16938,
+ },
+ [0x16939]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16939,
+ },
+ [0x1693A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693A,
+ },
+ [0x1693B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693B,
+ },
+ [0x1693C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGKIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693C,
+ },
+ [0x1693D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TUOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693D,
+ },
+ [0x1693E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693E,
+ },
+ [0x1693F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1693F,
+ },
+ [0x16940]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16940,
+ },
+ [0x16941]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16941,
+ },
+ [0x16942]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MAENJET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16942,
+ },
+ [0x16943]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16943,
+ },
+ [0x16944]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16944,
+ },
+ [0x16945]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NGGUOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16945,
+ },
+ [0x16946]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NSHUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16946,
+ },
+ [0x16947]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NJUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16947,
+ },
+ [0x16948]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D GHEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16948,
+ },
+ [0x16949]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16949,
+ },
+ [0x1694A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D REN OLD",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694A,
+ },
+ [0x1694B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694B,
+ },
+ [0x1694C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694C,
+ },
+ [0x1694D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694D,
+ },
+ [0x1694E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D RII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694E,
+ },
+ [0x1694F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1694F,
+ },
+ [0x16950]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16950,
+ },
+ [0x16951]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16951,
+ },
+ [0x16952]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16952,
+ },
+ [0x16953]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16953,
+ },
+ [0x16954]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16954,
+ },
+ [0x16955]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16955,
+ },
+ [0x16956]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D KYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16956,
+ },
+ [0x16957]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16957,
+ },
+ [0x16958]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16958,
+ },
+ [0x16959]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NTEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16959,
+ },
+ [0x1695A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695A,
+ },
+ [0x1695B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695B,
+ },
+ [0x1695C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SHOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695C,
+ },
+ [0x1695D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D PUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695D,
+ },
+ [0x1695E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MVOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695E,
+ },
+ [0x1695F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D LOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1695F,
+ },
+ [0x16960]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D REN MUCH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16960,
+ },
+ [0x16961]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D TI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16961,
+ },
+ [0x16962]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D NTUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16962,
+ },
+ [0x16963]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D MBAA SEVEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16963,
+ },
+ [0x16964]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D SAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16964,
+ },
+ [0x16965]={
+ category="lo",
+ description="BAMUM LETTER PHASE-D FAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16965,
+ },
+ [0x16966]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16966,
+ },
+ [0x16967]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TOON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16967,
+ },
+ [0x16968]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MBEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16968,
+ },
+ [0x16969]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16969,
+ },
+ [0x1696A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E VOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696A,
+ },
+ [0x1696B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LOON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696B,
+ },
+ [0x1696C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696C,
+ },
+ [0x1696D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696D,
+ },
+ [0x1696E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E RAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696E,
+ },
+ [0x1696F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NSHUOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1696F,
+ },
+ [0x16970]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16970,
+ },
+ [0x16971]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16971,
+ },
+ [0x16972]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16972,
+ },
+ [0x16973]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16973,
+ },
+ [0x16974]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KPEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16974,
+ },
+ [0x16975]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E WUO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16975,
+ },
+ [0x16976]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16976,
+ },
+ [0x16977]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16977,
+ },
+ [0x16978]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16978,
+ },
+ [0x16979]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TOO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16979,
+ },
+ [0x1697A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KUOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697A,
+ },
+ [0x1697B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697B,
+ },
+ [0x1697C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NSHIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697C,
+ },
+ [0x1697D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGOP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697D,
+ },
+ [0x1697E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697E,
+ },
+ [0x1697F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1697F,
+ },
+ [0x16980]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16980,
+ },
+ [0x16981]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NSHUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16981,
+ },
+ [0x16982]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E RIMGBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16982,
+ },
+ [0x16983]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NJEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16983,
+ },
+ [0x16984]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PEEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16984,
+ },
+ [0x16985]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16985,
+ },
+ [0x16986]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGURAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16986,
+ },
+ [0x16987]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MGBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16987,
+ },
+ [0x16988]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16988,
+ },
+ [0x16989]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16989,
+ },
+ [0x1698A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NJAEMLI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698A,
+ },
+ [0x1698B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698B,
+ },
+ [0x1698C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LOOT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698C,
+ },
+ [0x1698D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698D,
+ },
+ [0x1698E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698E,
+ },
+ [0x1698F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAEN NTEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1698F,
+ },
+ [0x16990]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16990,
+ },
+ [0x16991]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16991,
+ },
+ [0x16992]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDAA SOFTNESS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16992,
+ },
+ [0x16993]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGUAESHAE NYAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16993,
+ },
+ [0x16994]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16994,
+ },
+ [0x16995]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHEUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16995,
+ },
+ [0x16996]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16996,
+ },
+ [0x16997]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16997,
+ },
+ [0x16998]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16998,
+ },
+ [0x16999]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TUMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16999,
+ },
+ [0x1699A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699A,
+ },
+ [0x1699B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699B,
+ },
+ [0x1699C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699C,
+ },
+ [0x1699D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E VEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699D,
+ },
+ [0x1699E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E WEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699E,
+ },
+ [0x1699F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LAAM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1699F,
+ },
+ [0x169A0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A0,
+ },
+ [0x169A1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A1,
+ },
+ [0x169A2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHAAMAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A2,
+ },
+ [0x169A3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGEUREUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A3,
+ },
+ [0x169A4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SHEUAEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A4,
+ },
+ [0x169A5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MGBEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A5,
+ },
+ [0x169A6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MBEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A6,
+ },
+ [0x169A7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NZAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A7,
+ },
+ [0x169A8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NKOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A8,
+ },
+ [0x169A9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GBET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169A9,
+ },
+ [0x169AA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AA,
+ },
+ [0x169AB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KUET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AB,
+ },
+ [0x169AC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AC,
+ },
+ [0x169AD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NYI CLEAVER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AD,
+ },
+ [0x169AE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YIT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AE,
+ },
+ [0x169AF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MFEUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169AF,
+ },
+ [0x169B0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDIAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B0,
+ },
+ [0x169B1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PIEEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B1,
+ },
+ [0x169B2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B2,
+ },
+ [0x169B3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LEUAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B3,
+ },
+ [0x169B4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B4,
+ },
+ [0x169B5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GBEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B5,
+ },
+ [0x169B6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B6,
+ },
+ [0x169B7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B7,
+ },
+ [0x169B8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B8,
+ },
+ [0x169B9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKAAMI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169B9,
+ },
+ [0x169BA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BA,
+ },
+ [0x169BB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BB,
+ },
+ [0x169BC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NTUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BC,
+ },
+ [0x169BD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PEUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BD,
+ },
+ [0x169BE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YEUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BE,
+ },
+ [0x169BF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169BF,
+ },
+ [0x169C0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NYI BETWEEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C0,
+ },
+ [0x169C1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NZUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C1,
+ },
+ [0x169C2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E POON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C2,
+ },
+ [0x169C3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C3,
+ },
+ [0x169C4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FUET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C4,
+ },
+ [0x169C5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C5,
+ },
+ [0x169C6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C6,
+ },
+ [0x169C7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHEUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C7,
+ },
+ [0x169C8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FU I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C8,
+ },
+ [0x169C9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MVI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169C9,
+ },
+ [0x169CA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PUAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CA,
+ },
+ [0x169CB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGKUM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CB,
+ },
+ [0x169CC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KUT",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CC,
+ },
+ [0x169CD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PIET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CD,
+ },
+ [0x169CE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NTAP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CE,
+ },
+ [0x169CF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YEUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169CF,
+ },
+ [0x169D0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGGUP",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D0,
+ },
+ [0x169D1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PA PEOPLE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D1,
+ },
+ [0x169D2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FU CALL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D2,
+ },
+ [0x169D3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D3,
+ },
+ [0x169D4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NJEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D4,
+ },
+ [0x169D5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D5,
+ },
+ [0x169D6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D6,
+ },
+ [0x169D7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D7,
+ },
+ [0x169D8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D8,
+ },
+ [0x169D9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169D9,
+ },
+ [0x169DA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PA PLURAL",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DA,
+ },
+ [0x169DB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DB,
+ },
+ [0x169DC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DC,
+ },
+ [0x169DD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NDAA MY HOUSE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DD,
+ },
+ [0x169DE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SHIQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DE,
+ },
+ [0x169DF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169DF,
+ },
+ [0x169E0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E0,
+ },
+ [0x169E1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YUAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E1,
+ },
+ [0x169E2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YOQ SWIMMING",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E2,
+ },
+ [0x169E3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YOQ COVER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E3,
+ },
+ [0x169E4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YUQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E4,
+ },
+ [0x169E5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E YUN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E5,
+ },
+ [0x169E6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E6,
+ },
+ [0x169E7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E7,
+ },
+ [0x169E8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NJEE EPOCH",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E8,
+ },
+ [0x169E9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169E9,
+ },
+ [0x169EA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E WUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EA,
+ },
+ [0x169EB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EB,
+ },
+ [0x169EC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E VEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EC,
+ },
+ [0x169ED]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169ED,
+ },
+ [0x169EE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EE,
+ },
+ [0x169EF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E REUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169EF,
+ },
+ [0x169F0]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E RAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F0,
+ },
+ [0x169F1]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGUAET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F1,
+ },
+ [0x169F2]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F2,
+ },
+ [0x169F3]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F3,
+ },
+ [0x169F4]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E SHOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F4,
+ },
+ [0x169F5]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FU REMEDY",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F5,
+ },
+ [0x169F6]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E NA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F6,
+ },
+ [0x169F7]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E PI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F7,
+ },
+ [0x169F8]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E LOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F8,
+ },
+ [0x169F9]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169F9,
+ },
+ [0x169FA]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FA,
+ },
+ [0x169FB]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FB,
+ },
+ [0x169FC]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FC,
+ },
+ [0x169FD]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TEU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FD,
+ },
+ [0x169FE]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E KI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FE,
+ },
+ [0x169FF]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E MON",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x169FF,
+ },
+ [0x16A00]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E TEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A00,
+ },
+ [0x16A01]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E FAQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A01,
+ },
+ [0x16A02]={
+ category="lo",
+ description="BAMUM LETTER PHASE-E GHOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A02,
+ },
+ [0x16A03]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A03,
+ },
+ [0x16A04]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A04,
+ },
+ [0x16A05]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A05,
+ },
+ [0x16A06]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F EE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A06,
+ },
+ [0x16A07]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F REE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A07,
+ },
+ [0x16A08]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F TAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A08,
+ },
+ [0x16A09]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NYI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A09,
+ },
+ [0x16A0A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F LA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0A,
+ },
+ [0x16A0B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F RII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0B,
+ },
+ [0x16A0C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F RIEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0C,
+ },
+ [0x16A0D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MEEEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0D,
+ },
+ [0x16A0E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F TAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0E,
+ },
+ [0x16A0F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NDAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A0F,
+ },
+ [0x16A10]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NJAEM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A10,
+ },
+ [0x16A11]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A11,
+ },
+ [0x16A12]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SUU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A12,
+ },
+ [0x16A13]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SHII",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A13,
+ },
+ [0x16A14]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A14,
+ },
+ [0x16A15]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A15,
+ },
+ [0x16A16]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KYEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A16,
+ },
+ [0x16A17]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A17,
+ },
+ [0x16A18]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A18,
+ },
+ [0x16A19]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A19,
+ },
+ [0x16A1A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NJUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1A,
+ },
+ [0x16A1B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F YOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1B,
+ },
+ [0x16A1C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SHU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1C,
+ },
+ [0x16A1D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F YA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1D,
+ },
+ [0x16A1E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NSHA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1E,
+ },
+ [0x16A1F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F PEUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A1F,
+ },
+ [0x16A20]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NTEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A20,
+ },
+ [0x16A21]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F WUE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A21,
+ },
+ [0x16A22]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F PEE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A22,
+ },
+ [0x16A23]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F RU",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A23,
+ },
+ [0x16A24]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A24,
+ },
+ [0x16A25]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F REUX",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A25,
+ },
+ [0x16A26]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A26,
+ },
+ [0x16A27]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NGKWAEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A27,
+ },
+ [0x16A28]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F NGGA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A28,
+ },
+ [0x16A29]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SHO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A29,
+ },
+ [0x16A2A]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F PUAE",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2A,
+ },
+ [0x16A2B]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F FOM",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2B,
+ },
+ [0x16A2C]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F WA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2C,
+ },
+ [0x16A2D]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F LI",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2D,
+ },
+ [0x16A2E]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F LOQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2E,
+ },
+ [0x16A2F]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A2F,
+ },
+ [0x16A30]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MBEN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A30,
+ },
+ [0x16A31]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F REN",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A31,
+ },
+ [0x16A32]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A32,
+ },
+ [0x16A33]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MO",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A33,
+ },
+ [0x16A34]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F MBAA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A34,
+ },
+ [0x16A35]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F TET",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A35,
+ },
+ [0x16A36]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F KPA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A36,
+ },
+ [0x16A37]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F SAMBA",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A37,
+ },
+ [0x16A38]={
+ category="lo",
+ description="BAMUM LETTER PHASE-F VUEQ",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x16A38,
+ },
+ [0x1B000]={
+ category="lo",
+ cjkwd="w",
+ description="KATAKANA LETTER ARCHAIC E",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x1B000,
+ },
+ [0x1B001]={
+ category="lo",
+ cjkwd="w",
+ description="HIRAGANA LETTER ARCHAIC YE",
+ direction="l",
+ linebreak="id",
+ unicodeslot=0x1B001,
+ },
[0x1D000]={
category="so",
description="BYZANTINE MUSICAL SYMBOL PSILI",
@@ -126128,6 +160009,13 @@ characters.data={
linebreak="al",
unicodeslot=0x1D126,
},
+ [0x1D129]={
+ category="so",
+ description="MUSICAL SYMBOL MULTIPLE MEASURE REST",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1D129,
+ },
[0x1D12A]={
category="so",
description="MUSICAL SYMBOL DOUBLE SHARP",
@@ -128633,6 +162521,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0041 },
unicodeslot=0x1D400,
+ visual="bf",
},
[0x1D401]={
category="lu",
@@ -128641,6 +162530,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0042 },
unicodeslot=0x1D401,
+ visual="bf",
},
[0x1D402]={
category="lu",
@@ -128649,6 +162539,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0043 },
unicodeslot=0x1D402,
+ visual="bf",
},
[0x1D403]={
category="lu",
@@ -128657,6 +162548,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0044 },
unicodeslot=0x1D403,
+ visual="bf",
},
[0x1D404]={
category="lu",
@@ -128665,6 +162557,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0045 },
unicodeslot=0x1D404,
+ visual="bf",
},
[0x1D405]={
category="lu",
@@ -128673,6 +162566,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0046 },
unicodeslot=0x1D405,
+ visual="bf",
},
[0x1D406]={
category="lu",
@@ -128681,6 +162575,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0047 },
unicodeslot=0x1D406,
+ visual="bf",
},
[0x1D407]={
category="lu",
@@ -128689,6 +162584,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0048 },
unicodeslot=0x1D407,
+ visual="bf",
},
[0x1D408]={
category="lu",
@@ -128697,6 +162593,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0049 },
unicodeslot=0x1D408,
+ visual="bf",
},
[0x1D409]={
category="lu",
@@ -128705,6 +162602,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004A },
unicodeslot=0x1D409,
+ visual="bf",
},
[0x1D40A]={
category="lu",
@@ -128713,6 +162611,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004B },
unicodeslot=0x1D40A,
+ visual="bf",
},
[0x1D40B]={
category="lu",
@@ -128721,6 +162620,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004C },
unicodeslot=0x1D40B,
+ visual="bf",
},
[0x1D40C]={
category="lu",
@@ -128729,6 +162629,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004D },
unicodeslot=0x1D40C,
+ visual="bf",
},
[0x1D40D]={
category="lu",
@@ -128737,6 +162638,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004E },
unicodeslot=0x1D40D,
+ visual="bf",
},
[0x1D40E]={
category="lu",
@@ -128745,6 +162647,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004F },
unicodeslot=0x1D40E,
+ visual="bf",
},
[0x1D40F]={
category="lu",
@@ -128753,6 +162656,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0050 },
unicodeslot=0x1D40F,
+ visual="bf",
},
[0x1D410]={
category="lu",
@@ -128761,6 +162665,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0051 },
unicodeslot=0x1D410,
+ visual="bf",
},
[0x1D411]={
category="lu",
@@ -128769,6 +162674,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0052 },
unicodeslot=0x1D411,
+ visual="bf",
},
[0x1D412]={
category="lu",
@@ -128777,6 +162683,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0053 },
unicodeslot=0x1D412,
+ visual="bf",
},
[0x1D413]={
category="lu",
@@ -128785,6 +162692,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0054 },
unicodeslot=0x1D413,
+ visual="bf",
},
[0x1D414]={
category="lu",
@@ -128793,6 +162701,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0055 },
unicodeslot=0x1D414,
+ visual="bf",
},
[0x1D415]={
category="lu",
@@ -128801,6 +162710,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0056 },
unicodeslot=0x1D415,
+ visual="bf",
},
[0x1D416]={
category="lu",
@@ -128809,6 +162719,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0057 },
unicodeslot=0x1D416,
+ visual="bf",
},
[0x1D417]={
category="lu",
@@ -128817,6 +162728,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0058 },
unicodeslot=0x1D417,
+ visual="bf",
},
[0x1D418]={
category="lu",
@@ -128825,6 +162737,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0059 },
unicodeslot=0x1D418,
+ visual="bf",
},
[0x1D419]={
category="lu",
@@ -128833,6 +162746,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x005A },
unicodeslot=0x1D419,
+ visual="bf",
},
[0x1D41A]={
category="ll",
@@ -128841,6 +162755,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0061 },
unicodeslot=0x1D41A,
+ visual="bf",
},
[0x1D41B]={
category="ll",
@@ -128849,6 +162764,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0062 },
unicodeslot=0x1D41B,
+ visual="bf",
},
[0x1D41C]={
category="ll",
@@ -128857,6 +162773,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0063 },
unicodeslot=0x1D41C,
+ visual="bf",
},
[0x1D41D]={
category="ll",
@@ -128865,6 +162782,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0064 },
unicodeslot=0x1D41D,
+ visual="bf",
},
[0x1D41E]={
category="ll",
@@ -128873,6 +162791,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0065 },
unicodeslot=0x1D41E,
+ visual="bf",
},
[0x1D41F]={
category="ll",
@@ -128881,6 +162800,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0066 },
unicodeslot=0x1D41F,
+ visual="bf",
},
[0x1D420]={
category="ll",
@@ -128889,6 +162809,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0067 },
unicodeslot=0x1D420,
+ visual="bf",
},
[0x1D421]={
category="ll",
@@ -128897,6 +162818,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0068 },
unicodeslot=0x1D421,
+ visual="bf",
},
[0x1D422]={
category="ll",
@@ -128905,6 +162827,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x1D422,
+ visual="bf",
},
[0x1D423]={
category="ll",
@@ -128913,6 +162836,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006A },
unicodeslot=0x1D423,
+ visual="bf",
},
[0x1D424]={
category="ll",
@@ -128921,6 +162845,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006B },
unicodeslot=0x1D424,
+ visual="bf",
},
[0x1D425]={
category="ll",
@@ -128929,6 +162854,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006C },
unicodeslot=0x1D425,
+ visual="bf",
},
[0x1D426]={
category="ll",
@@ -128937,6 +162863,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006D },
unicodeslot=0x1D426,
+ visual="bf",
},
[0x1D427]={
category="ll",
@@ -128945,6 +162872,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006E },
unicodeslot=0x1D427,
+ visual="bf",
},
[0x1D428]={
category="ll",
@@ -128953,6 +162881,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006F },
unicodeslot=0x1D428,
+ visual="bf",
},
[0x1D429]={
category="ll",
@@ -128961,6 +162890,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0070 },
unicodeslot=0x1D429,
+ visual="bf",
},
[0x1D42A]={
category="ll",
@@ -128969,6 +162899,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0071 },
unicodeslot=0x1D42A,
+ visual="bf",
},
[0x1D42B]={
category="ll",
@@ -128977,6 +162908,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0072 },
unicodeslot=0x1D42B,
+ visual="bf",
},
[0x1D42C]={
category="ll",
@@ -128985,6 +162917,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0073 },
unicodeslot=0x1D42C,
+ visual="bf",
},
[0x1D42D]={
category="ll",
@@ -128993,6 +162926,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0074 },
unicodeslot=0x1D42D,
+ visual="bf",
},
[0x1D42E]={
category="ll",
@@ -129001,6 +162935,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0075 },
unicodeslot=0x1D42E,
+ visual="bf",
},
[0x1D42F]={
category="ll",
@@ -129009,6 +162944,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0076 },
unicodeslot=0x1D42F,
+ visual="bf",
},
[0x1D430]={
category="ll",
@@ -129017,6 +162953,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0077 },
unicodeslot=0x1D430,
+ visual="bf",
},
[0x1D431]={
category="ll",
@@ -129025,6 +162962,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0078 },
unicodeslot=0x1D431,
+ visual="bf",
},
[0x1D432]={
category="ll",
@@ -129033,6 +162971,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0079 },
unicodeslot=0x1D432,
+ visual="bf",
},
[0x1D433]={
category="ll",
@@ -129041,6 +162980,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x007A },
unicodeslot=0x1D433,
+ visual="bf",
},
[0x1D434]={
category="lu",
@@ -129049,6 +162989,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0041 },
unicodeslot=0x1D434,
+ visual="it",
},
[0x1D435]={
category="lu",
@@ -129057,6 +162998,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0042 },
unicodeslot=0x1D435,
+ visual="it",
},
[0x1D436]={
category="lu",
@@ -129065,6 +163007,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0043 },
unicodeslot=0x1D436,
+ visual="it",
},
[0x1D437]={
category="lu",
@@ -129073,6 +163016,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0044 },
unicodeslot=0x1D437,
+ visual="it",
},
[0x1D438]={
category="lu",
@@ -129081,6 +163025,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0045 },
unicodeslot=0x1D438,
+ visual="it",
},
[0x1D439]={
category="lu",
@@ -129089,6 +163034,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0046 },
unicodeslot=0x1D439,
+ visual="it",
},
[0x1D43A]={
category="lu",
@@ -129097,6 +163043,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0047 },
unicodeslot=0x1D43A,
+ visual="it",
},
[0x1D43B]={
category="lu",
@@ -129105,6 +163052,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0048 },
unicodeslot=0x1D43B,
+ visual="it",
},
[0x1D43C]={
category="lu",
@@ -129113,6 +163061,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0049 },
unicodeslot=0x1D43C,
+ visual="it",
},
[0x1D43D]={
category="lu",
@@ -129121,6 +163070,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004A },
unicodeslot=0x1D43D,
+ visual="it",
},
[0x1D43E]={
category="lu",
@@ -129129,6 +163079,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004B },
unicodeslot=0x1D43E,
+ visual="it",
},
[0x1D43F]={
category="lu",
@@ -129137,6 +163088,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004C },
unicodeslot=0x1D43F,
+ visual="it",
},
[0x1D440]={
category="lu",
@@ -129145,6 +163097,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004D },
unicodeslot=0x1D440,
+ visual="it",
},
[0x1D441]={
category="lu",
@@ -129153,6 +163106,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004E },
unicodeslot=0x1D441,
+ visual="it",
},
[0x1D442]={
category="lu",
@@ -129161,6 +163115,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004F },
unicodeslot=0x1D442,
+ visual="it",
},
[0x1D443]={
category="lu",
@@ -129169,6 +163124,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0050 },
unicodeslot=0x1D443,
+ visual="it",
},
[0x1D444]={
category="lu",
@@ -129177,6 +163133,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0051 },
unicodeslot=0x1D444,
+ visual="it",
},
[0x1D445]={
category="lu",
@@ -129185,6 +163142,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0052 },
unicodeslot=0x1D445,
+ visual="it",
},
[0x1D446]={
category="lu",
@@ -129193,6 +163151,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0053 },
unicodeslot=0x1D446,
+ visual="it",
},
[0x1D447]={
category="lu",
@@ -129201,6 +163160,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0054 },
unicodeslot=0x1D447,
+ visual="it",
},
[0x1D448]={
category="lu",
@@ -129209,6 +163169,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0055 },
unicodeslot=0x1D448,
+ visual="it",
},
[0x1D449]={
category="lu",
@@ -129217,6 +163178,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0056 },
unicodeslot=0x1D449,
+ visual="it",
},
[0x1D44A]={
category="lu",
@@ -129225,6 +163187,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0057 },
unicodeslot=0x1D44A,
+ visual="it",
},
[0x1D44B]={
category="lu",
@@ -129233,6 +163196,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0058 },
unicodeslot=0x1D44B,
+ visual="it",
},
[0x1D44C]={
category="lu",
@@ -129241,6 +163205,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0059 },
unicodeslot=0x1D44C,
+ visual="it",
},
[0x1D44D]={
category="lu",
@@ -129249,6 +163214,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x005A },
unicodeslot=0x1D44D,
+ visual="it",
},
[0x1D44E]={
category="ll",
@@ -129257,6 +163223,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0061 },
unicodeslot=0x1D44E,
+ visual="it",
},
[0x1D44F]={
category="ll",
@@ -129265,6 +163232,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0062 },
unicodeslot=0x1D44F,
+ visual="it",
},
[0x1D450]={
category="ll",
@@ -129273,6 +163241,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0063 },
unicodeslot=0x1D450,
+ visual="it",
},
[0x1D451]={
category="ll",
@@ -129281,6 +163250,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0064 },
unicodeslot=0x1D451,
+ visual="it",
},
[0x1D452]={
category="ll",
@@ -129289,6 +163259,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0065 },
unicodeslot=0x1D452,
+ visual="it",
},
[0x1D453]={
category="ll",
@@ -129297,6 +163268,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0066 },
unicodeslot=0x1D453,
+ visual="it",
},
[0x1D454]={
category="ll",
@@ -129305,6 +163277,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0067 },
unicodeslot=0x1D454,
+ visual="it",
},
[0x1D456]={
category="ll",
@@ -129313,6 +163286,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x1D456,
+ visual="it",
},
[0x1D457]={
category="ll",
@@ -129321,6 +163295,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006A },
unicodeslot=0x1D457,
+ visual="it",
},
[0x1D458]={
category="ll",
@@ -129329,6 +163304,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006B },
unicodeslot=0x1D458,
+ visual="it",
},
[0x1D459]={
category="ll",
@@ -129337,6 +163313,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006C },
unicodeslot=0x1D459,
+ visual="it",
},
[0x1D45A]={
category="ll",
@@ -129345,6 +163322,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006D },
unicodeslot=0x1D45A,
+ visual="it",
},
[0x1D45B]={
category="ll",
@@ -129353,6 +163331,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006E },
unicodeslot=0x1D45B,
+ visual="it",
},
[0x1D45C]={
category="ll",
@@ -129361,6 +163340,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006F },
unicodeslot=0x1D45C,
+ visual="it",
},
[0x1D45D]={
category="ll",
@@ -129369,6 +163349,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0070 },
unicodeslot=0x1D45D,
+ visual="it",
},
[0x1D45E]={
category="ll",
@@ -129377,6 +163358,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0071 },
unicodeslot=0x1D45E,
+ visual="it",
},
[0x1D45F]={
category="ll",
@@ -129385,6 +163367,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0072 },
unicodeslot=0x1D45F,
+ visual="it",
},
[0x1D460]={
category="ll",
@@ -129393,6 +163376,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0073 },
unicodeslot=0x1D460,
+ visual="it",
},
[0x1D461]={
category="ll",
@@ -129401,6 +163385,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0074 },
unicodeslot=0x1D461,
+ visual="it",
},
[0x1D462]={
category="ll",
@@ -129409,6 +163394,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0075 },
unicodeslot=0x1D462,
+ visual="it",
},
[0x1D463]={
category="ll",
@@ -129417,6 +163403,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0076 },
unicodeslot=0x1D463,
+ visual="it",
},
[0x1D464]={
category="ll",
@@ -129425,6 +163412,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0077 },
unicodeslot=0x1D464,
+ visual="it",
},
[0x1D465]={
category="ll",
@@ -129433,6 +163421,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0078 },
unicodeslot=0x1D465,
+ visual="it",
},
[0x1D466]={
category="ll",
@@ -129441,6 +163430,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0079 },
unicodeslot=0x1D466,
+ visual="it",
},
[0x1D467]={
category="ll",
@@ -129449,6 +163439,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x007A },
unicodeslot=0x1D467,
+ visual="it",
},
[0x1D468]={
category="lu",
@@ -129457,6 +163448,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0041 },
unicodeslot=0x1D468,
+ visual="bi",
},
[0x1D469]={
category="lu",
@@ -129465,6 +163457,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0042 },
unicodeslot=0x1D469,
+ visual="bi",
},
[0x1D46A]={
category="lu",
@@ -129473,6 +163466,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0043 },
unicodeslot=0x1D46A,
+ visual="bi",
},
[0x1D46B]={
category="lu",
@@ -129481,6 +163475,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0044 },
unicodeslot=0x1D46B,
+ visual="bi",
},
[0x1D46C]={
category="lu",
@@ -129489,6 +163484,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0045 },
unicodeslot=0x1D46C,
+ visual="bi",
},
[0x1D46D]={
category="lu",
@@ -129497,6 +163493,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0046 },
unicodeslot=0x1D46D,
+ visual="bi",
},
[0x1D46E]={
category="lu",
@@ -129505,6 +163502,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0047 },
unicodeslot=0x1D46E,
+ visual="bi",
},
[0x1D46F]={
category="lu",
@@ -129513,6 +163511,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0048 },
unicodeslot=0x1D46F,
+ visual="bi",
},
[0x1D470]={
category="lu",
@@ -129521,6 +163520,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0049 },
unicodeslot=0x1D470,
+ visual="bi",
},
[0x1D471]={
category="lu",
@@ -129529,6 +163529,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004A },
unicodeslot=0x1D471,
+ visual="bi",
},
[0x1D472]={
category="lu",
@@ -129537,6 +163538,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004B },
unicodeslot=0x1D472,
+ visual="bi",
},
[0x1D473]={
category="lu",
@@ -129545,6 +163547,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004C },
unicodeslot=0x1D473,
+ visual="bi",
},
[0x1D474]={
category="lu",
@@ -129553,6 +163556,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004D },
unicodeslot=0x1D474,
+ visual="bi",
},
[0x1D475]={
category="lu",
@@ -129561,6 +163565,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004E },
unicodeslot=0x1D475,
+ visual="bi",
},
[0x1D476]={
category="lu",
@@ -129569,6 +163574,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004F },
unicodeslot=0x1D476,
+ visual="bi",
},
[0x1D477]={
category="lu",
@@ -129577,6 +163583,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0050 },
unicodeslot=0x1D477,
+ visual="bi",
},
[0x1D478]={
category="lu",
@@ -129585,6 +163592,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0051 },
unicodeslot=0x1D478,
+ visual="bi",
},
[0x1D479]={
category="lu",
@@ -129593,6 +163601,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0052 },
unicodeslot=0x1D479,
+ visual="bi",
},
[0x1D47A]={
category="lu",
@@ -129601,6 +163610,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0053 },
unicodeslot=0x1D47A,
+ visual="bi",
},
[0x1D47B]={
category="lu",
@@ -129609,6 +163619,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0054 },
unicodeslot=0x1D47B,
+ visual="bi",
},
[0x1D47C]={
category="lu",
@@ -129617,6 +163628,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0055 },
unicodeslot=0x1D47C,
+ visual="bi",
},
[0x1D47D]={
category="lu",
@@ -129625,6 +163637,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0056 },
unicodeslot=0x1D47D,
+ visual="bi",
},
[0x1D47E]={
category="lu",
@@ -129633,6 +163646,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0057 },
unicodeslot=0x1D47E,
+ visual="bi",
},
[0x1D47F]={
category="lu",
@@ -129641,6 +163655,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0058 },
unicodeslot=0x1D47F,
+ visual="bi",
},
[0x1D480]={
category="lu",
@@ -129649,6 +163664,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0059 },
unicodeslot=0x1D480,
+ visual="bi",
},
[0x1D481]={
category="lu",
@@ -129657,6 +163673,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x005A },
unicodeslot=0x1D481,
+ visual="bi",
},
[0x1D482]={
category="ll",
@@ -129665,6 +163682,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0061 },
unicodeslot=0x1D482,
+ visual="bi",
},
[0x1D483]={
category="ll",
@@ -129673,6 +163691,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0062 },
unicodeslot=0x1D483,
+ visual="bi",
},
[0x1D484]={
category="ll",
@@ -129681,6 +163700,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0063 },
unicodeslot=0x1D484,
+ visual="bi",
},
[0x1D485]={
category="ll",
@@ -129689,6 +163709,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0064 },
unicodeslot=0x1D485,
+ visual="bi",
},
[0x1D486]={
category="ll",
@@ -129697,6 +163718,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0065 },
unicodeslot=0x1D486,
+ visual="bi",
},
[0x1D487]={
category="ll",
@@ -129705,6 +163727,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0066 },
unicodeslot=0x1D487,
+ visual="bi",
},
[0x1D488]={
category="ll",
@@ -129713,6 +163736,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0067 },
unicodeslot=0x1D488,
+ visual="bi",
},
[0x1D489]={
category="ll",
@@ -129721,6 +163745,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0068 },
unicodeslot=0x1D489,
+ visual="bi",
},
[0x1D48A]={
category="ll",
@@ -129729,6 +163754,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x1D48A,
+ visual="bi",
},
[0x1D48B]={
category="ll",
@@ -129737,6 +163763,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006A },
unicodeslot=0x1D48B,
+ visual="bi",
},
[0x1D48C]={
category="ll",
@@ -129745,6 +163772,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006B },
unicodeslot=0x1D48C,
+ visual="bi",
},
[0x1D48D]={
category="ll",
@@ -129753,6 +163781,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006C },
unicodeslot=0x1D48D,
+ visual="bi",
},
[0x1D48E]={
category="ll",
@@ -129761,6 +163790,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006D },
unicodeslot=0x1D48E,
+ visual="bi",
},
[0x1D48F]={
category="ll",
@@ -129769,6 +163799,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006E },
unicodeslot=0x1D48F,
+ visual="bi",
},
[0x1D490]={
category="ll",
@@ -129777,6 +163808,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006F },
unicodeslot=0x1D490,
+ visual="bi",
},
[0x1D491]={
category="ll",
@@ -129785,6 +163817,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0070 },
unicodeslot=0x1D491,
+ visual="bi",
},
[0x1D492]={
category="ll",
@@ -129793,6 +163826,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0071 },
unicodeslot=0x1D492,
+ visual="bi",
},
[0x1D493]={
category="ll",
@@ -129801,6 +163835,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0072 },
unicodeslot=0x1D493,
+ visual="bi",
},
[0x1D494]={
category="ll",
@@ -129809,6 +163844,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0073 },
unicodeslot=0x1D494,
+ visual="bi",
},
[0x1D495]={
category="ll",
@@ -129817,6 +163853,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0074 },
unicodeslot=0x1D495,
+ visual="bi",
},
[0x1D496]={
category="ll",
@@ -129825,6 +163862,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0075 },
unicodeslot=0x1D496,
+ visual="bi",
},
[0x1D497]={
category="ll",
@@ -129833,6 +163871,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0076 },
unicodeslot=0x1D497,
+ visual="bi",
},
[0x1D498]={
category="ll",
@@ -129841,6 +163880,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0077 },
unicodeslot=0x1D498,
+ visual="bi",
},
[0x1D499]={
category="ll",
@@ -129849,6 +163889,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0078 },
unicodeslot=0x1D499,
+ visual="bi",
},
[0x1D49A]={
category="ll",
@@ -129857,6 +163898,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0079 },
unicodeslot=0x1D49A,
+ visual="bi",
},
[0x1D49B]={
category="ll",
@@ -129865,6 +163907,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x007A },
unicodeslot=0x1D49B,
+ visual="bi",
},
[0x1D49C]={
category="lu",
@@ -130201,6 +164244,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0041 },
unicodeslot=0x1D4D0,
+ visual="bf",
},
[0x1D4D1]={
category="lu",
@@ -130209,6 +164253,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0042 },
unicodeslot=0x1D4D1,
+ visual="bf",
},
[0x1D4D2]={
category="lu",
@@ -130217,6 +164262,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0043 },
unicodeslot=0x1D4D2,
+ visual="bf",
},
[0x1D4D3]={
category="lu",
@@ -130225,6 +164271,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0044 },
unicodeslot=0x1D4D3,
+ visual="bf",
},
[0x1D4D4]={
category="lu",
@@ -130233,6 +164280,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0045 },
unicodeslot=0x1D4D4,
+ visual="bf",
},
[0x1D4D5]={
category="lu",
@@ -130241,6 +164289,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0046 },
unicodeslot=0x1D4D5,
+ visual="bf",
},
[0x1D4D6]={
category="lu",
@@ -130249,6 +164298,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0047 },
unicodeslot=0x1D4D6,
+ visual="bf",
},
[0x1D4D7]={
category="lu",
@@ -130257,6 +164307,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0048 },
unicodeslot=0x1D4D7,
+ visual="bf",
},
[0x1D4D8]={
category="lu",
@@ -130265,6 +164316,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0049 },
unicodeslot=0x1D4D8,
+ visual="bf",
},
[0x1D4D9]={
category="lu",
@@ -130273,6 +164325,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004A },
unicodeslot=0x1D4D9,
+ visual="bf",
},
[0x1D4DA]={
category="lu",
@@ -130281,6 +164334,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004B },
unicodeslot=0x1D4DA,
+ visual="bf",
},
[0x1D4DB]={
category="lu",
@@ -130289,6 +164343,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004C },
unicodeslot=0x1D4DB,
+ visual="bf",
},
[0x1D4DC]={
category="lu",
@@ -130297,6 +164352,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004D },
unicodeslot=0x1D4DC,
+ visual="bf",
},
[0x1D4DD]={
category="lu",
@@ -130305,6 +164361,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004E },
unicodeslot=0x1D4DD,
+ visual="bf",
},
[0x1D4DE]={
category="lu",
@@ -130313,6 +164370,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004F },
unicodeslot=0x1D4DE,
+ visual="bf",
},
[0x1D4DF]={
category="lu",
@@ -130321,6 +164379,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0050 },
unicodeslot=0x1D4DF,
+ visual="bf",
},
[0x1D4E0]={
category="lu",
@@ -130329,6 +164388,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0051 },
unicodeslot=0x1D4E0,
+ visual="bf",
},
[0x1D4E1]={
category="lu",
@@ -130337,6 +164397,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0052 },
unicodeslot=0x1D4E1,
+ visual="bf",
},
[0x1D4E2]={
category="lu",
@@ -130345,6 +164406,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0053 },
unicodeslot=0x1D4E2,
+ visual="bf",
},
[0x1D4E3]={
category="lu",
@@ -130353,6 +164415,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0054 },
unicodeslot=0x1D4E3,
+ visual="bf",
},
[0x1D4E4]={
category="lu",
@@ -130361,6 +164424,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0055 },
unicodeslot=0x1D4E4,
+ visual="bf",
},
[0x1D4E5]={
category="lu",
@@ -130369,6 +164433,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0056 },
unicodeslot=0x1D4E5,
+ visual="bf",
},
[0x1D4E6]={
category="lu",
@@ -130377,6 +164442,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0057 },
unicodeslot=0x1D4E6,
+ visual="bf",
},
[0x1D4E7]={
category="lu",
@@ -130385,6 +164451,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0058 },
unicodeslot=0x1D4E7,
+ visual="bf",
},
[0x1D4E8]={
category="lu",
@@ -130393,6 +164460,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0059 },
unicodeslot=0x1D4E8,
+ visual="bf",
},
[0x1D4E9]={
category="lu",
@@ -130401,6 +164469,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x005A },
unicodeslot=0x1D4E9,
+ visual="bf",
},
[0x1D4EA]={
category="ll",
@@ -130409,6 +164478,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0061 },
unicodeslot=0x1D4EA,
+ visual="bf",
},
[0x1D4EB]={
category="ll",
@@ -130417,6 +164487,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0062 },
unicodeslot=0x1D4EB,
+ visual="bf",
},
[0x1D4EC]={
category="ll",
@@ -130425,6 +164496,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0063 },
unicodeslot=0x1D4EC,
+ visual="bf",
},
[0x1D4ED]={
category="ll",
@@ -130433,6 +164505,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0064 },
unicodeslot=0x1D4ED,
+ visual="bf",
},
[0x1D4EE]={
category="ll",
@@ -130441,6 +164514,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0065 },
unicodeslot=0x1D4EE,
+ visual="bf",
},
[0x1D4EF]={
category="ll",
@@ -130449,6 +164523,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0066 },
unicodeslot=0x1D4EF,
+ visual="bf",
},
[0x1D4F0]={
category="ll",
@@ -130457,6 +164532,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0067 },
unicodeslot=0x1D4F0,
+ visual="bf",
},
[0x1D4F1]={
category="ll",
@@ -130465,6 +164541,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0068 },
unicodeslot=0x1D4F1,
+ visual="bf",
},
[0x1D4F2]={
category="ll",
@@ -130473,6 +164550,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x1D4F2,
+ visual="bf",
},
[0x1D4F3]={
category="ll",
@@ -130481,6 +164559,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006A },
unicodeslot=0x1D4F3,
+ visual="bf",
},
[0x1D4F4]={
category="ll",
@@ -130489,6 +164568,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006B },
unicodeslot=0x1D4F4,
+ visual="bf",
},
[0x1D4F5]={
category="ll",
@@ -130497,6 +164577,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006C },
unicodeslot=0x1D4F5,
+ visual="bf",
},
[0x1D4F6]={
category="ll",
@@ -130505,6 +164586,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006D },
unicodeslot=0x1D4F6,
+ visual="bf",
},
[0x1D4F7]={
category="ll",
@@ -130513,6 +164595,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006E },
unicodeslot=0x1D4F7,
+ visual="bf",
},
[0x1D4F8]={
category="ll",
@@ -130521,6 +164604,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006F },
unicodeslot=0x1D4F8,
+ visual="bf",
},
[0x1D4F9]={
category="ll",
@@ -130529,6 +164613,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0070 },
unicodeslot=0x1D4F9,
+ visual="bf",
},
[0x1D4FA]={
category="ll",
@@ -130537,6 +164622,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0071 },
unicodeslot=0x1D4FA,
+ visual="bf",
},
[0x1D4FB]={
category="ll",
@@ -130545,6 +164631,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0072 },
unicodeslot=0x1D4FB,
+ visual="bf",
},
[0x1D4FC]={
category="ll",
@@ -130553,6 +164640,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0073 },
unicodeslot=0x1D4FC,
+ visual="bf",
},
[0x1D4FD]={
category="ll",
@@ -130561,6 +164649,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0074 },
unicodeslot=0x1D4FD,
+ visual="bf",
},
[0x1D4FE]={
category="ll",
@@ -130569,6 +164658,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0075 },
unicodeslot=0x1D4FE,
+ visual="bf",
},
[0x1D4FF]={
category="ll",
@@ -130577,6 +164667,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0076 },
unicodeslot=0x1D4FF,
+ visual="bf",
},
[0x1D500]={
category="ll",
@@ -130585,6 +164676,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0077 },
unicodeslot=0x1D500,
+ visual="bf",
},
[0x1D501]={
category="ll",
@@ -130593,6 +164685,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0078 },
unicodeslot=0x1D501,
+ visual="bf",
},
[0x1D502]={
category="ll",
@@ -130601,6 +164694,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0079 },
unicodeslot=0x1D502,
+ visual="bf",
},
[0x1D503]={
category="ll",
@@ -130609,6 +164703,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x007A },
unicodeslot=0x1D503,
+ visual="bf",
},
[0x1D504]={
category="lu",
@@ -131353,6 +165448,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0041 },
unicodeslot=0x1D56C,
+ visual="bf",
},
[0x1D56D]={
category="lu",
@@ -131361,6 +165457,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0042 },
unicodeslot=0x1D56D,
+ visual="bf",
},
[0x1D56E]={
category="lu",
@@ -131369,6 +165466,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0043 },
unicodeslot=0x1D56E,
+ visual="bf",
},
[0x1D56F]={
category="lu",
@@ -131377,6 +165475,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0044 },
unicodeslot=0x1D56F,
+ visual="bf",
},
[0x1D570]={
category="lu",
@@ -131385,6 +165484,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0045 },
unicodeslot=0x1D570,
+ visual="bf",
},
[0x1D571]={
category="lu",
@@ -131393,6 +165493,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0046 },
unicodeslot=0x1D571,
+ visual="bf",
},
[0x1D572]={
category="lu",
@@ -131401,6 +165502,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0047 },
unicodeslot=0x1D572,
+ visual="bf",
},
[0x1D573]={
category="lu",
@@ -131409,6 +165511,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0048 },
unicodeslot=0x1D573,
+ visual="bf",
},
[0x1D574]={
category="lu",
@@ -131417,6 +165520,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0049 },
unicodeslot=0x1D574,
+ visual="bf",
},
[0x1D575]={
category="lu",
@@ -131425,6 +165529,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004A },
unicodeslot=0x1D575,
+ visual="bf",
},
[0x1D576]={
category="lu",
@@ -131433,6 +165538,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004B },
unicodeslot=0x1D576,
+ visual="bf",
},
[0x1D577]={
category="lu",
@@ -131441,6 +165547,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004C },
unicodeslot=0x1D577,
+ visual="bf",
},
[0x1D578]={
category="lu",
@@ -131449,6 +165556,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004D },
unicodeslot=0x1D578,
+ visual="bf",
},
[0x1D579]={
category="lu",
@@ -131457,6 +165565,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004E },
unicodeslot=0x1D579,
+ visual="bf",
},
[0x1D57A]={
category="lu",
@@ -131465,6 +165574,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004F },
unicodeslot=0x1D57A,
+ visual="bf",
},
[0x1D57B]={
category="lu",
@@ -131473,6 +165583,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0050 },
unicodeslot=0x1D57B,
+ visual="bf",
},
[0x1D57C]={
category="lu",
@@ -131481,6 +165592,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0051 },
unicodeslot=0x1D57C,
+ visual="bf",
},
[0x1D57D]={
category="lu",
@@ -131489,6 +165601,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0052 },
unicodeslot=0x1D57D,
+ visual="bf",
},
[0x1D57E]={
category="lu",
@@ -131497,6 +165610,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0053 },
unicodeslot=0x1D57E,
+ visual="bf",
},
[0x1D57F]={
category="lu",
@@ -131505,6 +165619,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0054 },
unicodeslot=0x1D57F,
+ visual="bf",
},
[0x1D580]={
category="lu",
@@ -131513,6 +165628,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0055 },
unicodeslot=0x1D580,
+ visual="bf",
},
[0x1D581]={
category="lu",
@@ -131521,6 +165637,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0056 },
unicodeslot=0x1D581,
+ visual="bf",
},
[0x1D582]={
category="lu",
@@ -131529,6 +165646,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0057 },
unicodeslot=0x1D582,
+ visual="bf",
},
[0x1D583]={
category="lu",
@@ -131537,6 +165655,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0058 },
unicodeslot=0x1D583,
+ visual="bf",
},
[0x1D584]={
category="lu",
@@ -131545,6 +165664,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0059 },
unicodeslot=0x1D584,
+ visual="bf",
},
[0x1D585]={
category="lu",
@@ -131553,6 +165673,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x005A },
unicodeslot=0x1D585,
+ visual="bf",
},
[0x1D586]={
category="ll",
@@ -131561,6 +165682,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0061 },
unicodeslot=0x1D586,
+ visual="bf",
},
[0x1D587]={
category="ll",
@@ -131569,6 +165691,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0062 },
unicodeslot=0x1D587,
+ visual="bf",
},
[0x1D588]={
category="ll",
@@ -131577,6 +165700,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0063 },
unicodeslot=0x1D588,
+ visual="bf",
},
[0x1D589]={
category="ll",
@@ -131585,6 +165709,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0064 },
unicodeslot=0x1D589,
+ visual="bf",
},
[0x1D58A]={
category="ll",
@@ -131593,6 +165718,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0065 },
unicodeslot=0x1D58A,
+ visual="bf",
},
[0x1D58B]={
category="ll",
@@ -131601,6 +165727,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0066 },
unicodeslot=0x1D58B,
+ visual="bf",
},
[0x1D58C]={
category="ll",
@@ -131609,6 +165736,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0067 },
unicodeslot=0x1D58C,
+ visual="bf",
},
[0x1D58D]={
category="ll",
@@ -131617,6 +165745,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0068 },
unicodeslot=0x1D58D,
+ visual="bf",
},
[0x1D58E]={
category="ll",
@@ -131625,6 +165754,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x1D58E,
+ visual="bf",
},
[0x1D58F]={
category="ll",
@@ -131633,6 +165763,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006A },
unicodeslot=0x1D58F,
+ visual="bf",
},
[0x1D590]={
category="ll",
@@ -131641,6 +165772,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006B },
unicodeslot=0x1D590,
+ visual="bf",
},
[0x1D591]={
category="ll",
@@ -131649,6 +165781,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006C },
unicodeslot=0x1D591,
+ visual="bf",
},
[0x1D592]={
category="ll",
@@ -131657,6 +165790,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006D },
unicodeslot=0x1D592,
+ visual="bf",
},
[0x1D593]={
category="ll",
@@ -131665,6 +165799,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006E },
unicodeslot=0x1D593,
+ visual="bf",
},
[0x1D594]={
category="ll",
@@ -131673,6 +165808,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006F },
unicodeslot=0x1D594,
+ visual="bf",
},
[0x1D595]={
category="ll",
@@ -131681,6 +165817,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0070 },
unicodeslot=0x1D595,
+ visual="bf",
},
[0x1D596]={
category="ll",
@@ -131689,6 +165826,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0071 },
unicodeslot=0x1D596,
+ visual="bf",
},
[0x1D597]={
category="ll",
@@ -131697,6 +165835,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0072 },
unicodeslot=0x1D597,
+ visual="bf",
},
[0x1D598]={
category="ll",
@@ -131705,6 +165844,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0073 },
unicodeslot=0x1D598,
+ visual="bf",
},
[0x1D599]={
category="ll",
@@ -131713,6 +165853,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0074 },
unicodeslot=0x1D599,
+ visual="bf",
},
[0x1D59A]={
category="ll",
@@ -131721,6 +165862,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0075 },
unicodeslot=0x1D59A,
+ visual="bf",
},
[0x1D59B]={
category="ll",
@@ -131729,6 +165871,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0076 },
unicodeslot=0x1D59B,
+ visual="bf",
},
[0x1D59C]={
category="ll",
@@ -131737,6 +165880,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0077 },
unicodeslot=0x1D59C,
+ visual="bf",
},
[0x1D59D]={
category="ll",
@@ -131745,6 +165889,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0078 },
unicodeslot=0x1D59D,
+ visual="bf",
},
[0x1D59E]={
category="ll",
@@ -131753,6 +165898,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0079 },
unicodeslot=0x1D59E,
+ visual="bf",
},
[0x1D59F]={
category="ll",
@@ -131761,6 +165907,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x007A },
unicodeslot=0x1D59F,
+ visual="bf",
},
[0x1D5A0]={
category="lu",
@@ -132185,6 +166332,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0041 },
unicodeslot=0x1D5D4,
+ visual="bf",
},
[0x1D5D5]={
category="lu",
@@ -132193,6 +166341,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0042 },
unicodeslot=0x1D5D5,
+ visual="bf",
},
[0x1D5D6]={
category="lu",
@@ -132201,6 +166350,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0043 },
unicodeslot=0x1D5D6,
+ visual="bf",
},
[0x1D5D7]={
category="lu",
@@ -132209,6 +166359,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0044 },
unicodeslot=0x1D5D7,
+ visual="bf",
},
[0x1D5D8]={
category="lu",
@@ -132217,6 +166368,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0045 },
unicodeslot=0x1D5D8,
+ visual="bf",
},
[0x1D5D9]={
category="lu",
@@ -132225,6 +166377,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0046 },
unicodeslot=0x1D5D9,
+ visual="bf",
},
[0x1D5DA]={
category="lu",
@@ -132233,6 +166386,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0047 },
unicodeslot=0x1D5DA,
+ visual="bf",
},
[0x1D5DB]={
category="lu",
@@ -132241,6 +166395,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0048 },
unicodeslot=0x1D5DB,
+ visual="bf",
},
[0x1D5DC]={
category="lu",
@@ -132249,6 +166404,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0049 },
unicodeslot=0x1D5DC,
+ visual="bf",
},
[0x1D5DD]={
category="lu",
@@ -132257,6 +166413,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004A },
unicodeslot=0x1D5DD,
+ visual="bf",
},
[0x1D5DE]={
category="lu",
@@ -132265,6 +166422,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004B },
unicodeslot=0x1D5DE,
+ visual="bf",
},
[0x1D5DF]={
category="lu",
@@ -132273,6 +166431,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004C },
unicodeslot=0x1D5DF,
+ visual="bf",
},
[0x1D5E0]={
category="lu",
@@ -132281,6 +166440,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004D },
unicodeslot=0x1D5E0,
+ visual="bf",
},
[0x1D5E1]={
category="lu",
@@ -132289,6 +166449,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004E },
unicodeslot=0x1D5E1,
+ visual="bf",
},
[0x1D5E2]={
category="lu",
@@ -132297,6 +166458,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004F },
unicodeslot=0x1D5E2,
+ visual="bf",
},
[0x1D5E3]={
category="lu",
@@ -132305,6 +166467,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0050 },
unicodeslot=0x1D5E3,
+ visual="bf",
},
[0x1D5E4]={
category="lu",
@@ -132313,6 +166476,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0051 },
unicodeslot=0x1D5E4,
+ visual="bf",
},
[0x1D5E5]={
category="lu",
@@ -132321,6 +166485,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0052 },
unicodeslot=0x1D5E5,
+ visual="bf",
},
[0x1D5E6]={
category="lu",
@@ -132329,6 +166494,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0053 },
unicodeslot=0x1D5E6,
+ visual="bf",
},
[0x1D5E7]={
category="lu",
@@ -132337,6 +166503,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0054 },
unicodeslot=0x1D5E7,
+ visual="bf",
},
[0x1D5E8]={
category="lu",
@@ -132345,6 +166512,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0055 },
unicodeslot=0x1D5E8,
+ visual="bf",
},
[0x1D5E9]={
category="lu",
@@ -132353,6 +166521,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0056 },
unicodeslot=0x1D5E9,
+ visual="bf",
},
[0x1D5EA]={
category="lu",
@@ -132361,6 +166530,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0057 },
unicodeslot=0x1D5EA,
+ visual="bf",
},
[0x1D5EB]={
category="lu",
@@ -132369,6 +166539,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0058 },
unicodeslot=0x1D5EB,
+ visual="bf",
},
[0x1D5EC]={
category="lu",
@@ -132377,6 +166548,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0059 },
unicodeslot=0x1D5EC,
+ visual="bf",
},
[0x1D5ED]={
category="lu",
@@ -132385,6 +166557,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x005A },
unicodeslot=0x1D5ED,
+ visual="bf",
},
[0x1D5EE]={
category="ll",
@@ -132393,6 +166566,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0061 },
unicodeslot=0x1D5EE,
+ visual="bf",
},
[0x1D5EF]={
category="ll",
@@ -132401,6 +166575,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0062 },
unicodeslot=0x1D5EF,
+ visual="bf",
},
[0x1D5F0]={
category="ll",
@@ -132409,6 +166584,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0063 },
unicodeslot=0x1D5F0,
+ visual="bf",
},
[0x1D5F1]={
category="ll",
@@ -132417,6 +166593,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0064 },
unicodeslot=0x1D5F1,
+ visual="bf",
},
[0x1D5F2]={
category="ll",
@@ -132425,6 +166602,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0065 },
unicodeslot=0x1D5F2,
+ visual="bf",
},
[0x1D5F3]={
category="ll",
@@ -132433,6 +166611,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0066 },
unicodeslot=0x1D5F3,
+ visual="bf",
},
[0x1D5F4]={
category="ll",
@@ -132441,6 +166620,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0067 },
unicodeslot=0x1D5F4,
+ visual="bf",
},
[0x1D5F5]={
category="ll",
@@ -132449,6 +166629,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0068 },
unicodeslot=0x1D5F5,
+ visual="bf",
},
[0x1D5F6]={
category="ll",
@@ -132457,6 +166638,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x1D5F6,
+ visual="bf",
},
[0x1D5F7]={
category="ll",
@@ -132465,6 +166647,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006A },
unicodeslot=0x1D5F7,
+ visual="bf",
},
[0x1D5F8]={
category="ll",
@@ -132473,6 +166656,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006B },
unicodeslot=0x1D5F8,
+ visual="bf",
},
[0x1D5F9]={
category="ll",
@@ -132481,6 +166665,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006C },
unicodeslot=0x1D5F9,
+ visual="bf",
},
[0x1D5FA]={
category="ll",
@@ -132489,6 +166674,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006D },
unicodeslot=0x1D5FA,
+ visual="bf",
},
[0x1D5FB]={
category="ll",
@@ -132497,6 +166683,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006E },
unicodeslot=0x1D5FB,
+ visual="bf",
},
[0x1D5FC]={
category="ll",
@@ -132505,6 +166692,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006F },
unicodeslot=0x1D5FC,
+ visual="bf",
},
[0x1D5FD]={
category="ll",
@@ -132513,6 +166701,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0070 },
unicodeslot=0x1D5FD,
+ visual="bf",
},
[0x1D5FE]={
category="ll",
@@ -132521,6 +166710,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0071 },
unicodeslot=0x1D5FE,
+ visual="bf",
},
[0x1D5FF]={
category="ll",
@@ -132529,6 +166719,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0072 },
unicodeslot=0x1D5FF,
+ visual="bf",
},
[0x1D600]={
category="ll",
@@ -132537,6 +166728,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0073 },
unicodeslot=0x1D600,
+ visual="bf",
},
[0x1D601]={
category="ll",
@@ -132545,6 +166737,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0074 },
unicodeslot=0x1D601,
+ visual="bf",
},
[0x1D602]={
category="ll",
@@ -132553,6 +166746,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0075 },
unicodeslot=0x1D602,
+ visual="bf",
},
[0x1D603]={
category="ll",
@@ -132561,6 +166755,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0076 },
unicodeslot=0x1D603,
+ visual="bf",
},
[0x1D604]={
category="ll",
@@ -132569,6 +166764,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0077 },
unicodeslot=0x1D604,
+ visual="bf",
},
[0x1D605]={
category="ll",
@@ -132577,6 +166773,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0078 },
unicodeslot=0x1D605,
+ visual="bf",
},
[0x1D606]={
category="ll",
@@ -132585,6 +166782,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0079 },
unicodeslot=0x1D606,
+ visual="bf",
},
[0x1D607]={
category="ll",
@@ -132593,6 +166791,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x007A },
unicodeslot=0x1D607,
+ visual="bf",
},
[0x1D608]={
category="lu",
@@ -132601,6 +166800,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0041 },
unicodeslot=0x1D608,
+ visual="it",
},
[0x1D609]={
category="lu",
@@ -132609,6 +166809,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0042 },
unicodeslot=0x1D609,
+ visual="it",
},
[0x1D60A]={
category="lu",
@@ -132617,6 +166818,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0043 },
unicodeslot=0x1D60A,
+ visual="it",
},
[0x1D60B]={
category="lu",
@@ -132625,6 +166827,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0044 },
unicodeslot=0x1D60B,
+ visual="it",
},
[0x1D60C]={
category="lu",
@@ -132633,6 +166836,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0045 },
unicodeslot=0x1D60C,
+ visual="it",
},
[0x1D60D]={
category="lu",
@@ -132641,6 +166845,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0046 },
unicodeslot=0x1D60D,
+ visual="it",
},
[0x1D60E]={
category="lu",
@@ -132649,6 +166854,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0047 },
unicodeslot=0x1D60E,
+ visual="it",
},
[0x1D60F]={
category="lu",
@@ -132657,6 +166863,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0048 },
unicodeslot=0x1D60F,
+ visual="it",
},
[0x1D610]={
category="lu",
@@ -132665,6 +166872,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0049 },
unicodeslot=0x1D610,
+ visual="it",
},
[0x1D611]={
category="lu",
@@ -132673,6 +166881,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004A },
unicodeslot=0x1D611,
+ visual="it",
},
[0x1D612]={
category="lu",
@@ -132681,6 +166890,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004B },
unicodeslot=0x1D612,
+ visual="it",
},
[0x1D613]={
category="lu",
@@ -132689,6 +166899,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004C },
unicodeslot=0x1D613,
+ visual="it",
},
[0x1D614]={
category="lu",
@@ -132697,6 +166908,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004D },
unicodeslot=0x1D614,
+ visual="it",
},
[0x1D615]={
category="lu",
@@ -132705,6 +166917,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004E },
unicodeslot=0x1D615,
+ visual="it",
},
[0x1D616]={
category="lu",
@@ -132713,6 +166926,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004F },
unicodeslot=0x1D616,
+ visual="it",
},
[0x1D617]={
category="lu",
@@ -132721,6 +166935,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0050 },
unicodeslot=0x1D617,
+ visual="it",
},
[0x1D618]={
category="lu",
@@ -132729,6 +166944,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0051 },
unicodeslot=0x1D618,
+ visual="it",
},
[0x1D619]={
category="lu",
@@ -132737,6 +166953,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0052 },
unicodeslot=0x1D619,
+ visual="it",
},
[0x1D61A]={
category="lu",
@@ -132745,6 +166962,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0053 },
unicodeslot=0x1D61A,
+ visual="it",
},
[0x1D61B]={
category="lu",
@@ -132753,6 +166971,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0054 },
unicodeslot=0x1D61B,
+ visual="it",
},
[0x1D61C]={
category="lu",
@@ -132761,6 +166980,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0055 },
unicodeslot=0x1D61C,
+ visual="it",
},
[0x1D61D]={
category="lu",
@@ -132769,6 +166989,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0056 },
unicodeslot=0x1D61D,
+ visual="it",
},
[0x1D61E]={
category="lu",
@@ -132777,6 +166998,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0057 },
unicodeslot=0x1D61E,
+ visual="it",
},
[0x1D61F]={
category="lu",
@@ -132785,6 +167007,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0058 },
unicodeslot=0x1D61F,
+ visual="it",
},
[0x1D620]={
category="lu",
@@ -132793,6 +167016,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0059 },
unicodeslot=0x1D620,
+ visual="it",
},
[0x1D621]={
category="lu",
@@ -132801,6 +167025,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x005A },
unicodeslot=0x1D621,
+ visual="it",
},
[0x1D622]={
category="ll",
@@ -132809,6 +167034,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0061 },
unicodeslot=0x1D622,
+ visual="it",
},
[0x1D623]={
category="ll",
@@ -132817,6 +167043,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0062 },
unicodeslot=0x1D623,
+ visual="it",
},
[0x1D624]={
category="ll",
@@ -132825,6 +167052,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0063 },
unicodeslot=0x1D624,
+ visual="it",
},
[0x1D625]={
category="ll",
@@ -132833,6 +167061,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0064 },
unicodeslot=0x1D625,
+ visual="it",
},
[0x1D626]={
category="ll",
@@ -132841,6 +167070,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0065 },
unicodeslot=0x1D626,
+ visual="it",
},
[0x1D627]={
category="ll",
@@ -132849,6 +167079,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0066 },
unicodeslot=0x1D627,
+ visual="it",
},
[0x1D628]={
category="ll",
@@ -132857,6 +167088,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0067 },
unicodeslot=0x1D628,
+ visual="it",
},
[0x1D629]={
category="ll",
@@ -132865,6 +167097,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0068 },
unicodeslot=0x1D629,
+ visual="it",
},
[0x1D62A]={
category="ll",
@@ -132873,6 +167106,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x1D62A,
+ visual="it",
},
[0x1D62B]={
category="ll",
@@ -132881,6 +167115,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006A },
unicodeslot=0x1D62B,
+ visual="it",
},
[0x1D62C]={
category="ll",
@@ -132889,6 +167124,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006B },
unicodeslot=0x1D62C,
+ visual="it",
},
[0x1D62D]={
category="ll",
@@ -132897,6 +167133,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006C },
unicodeslot=0x1D62D,
+ visual="it",
},
[0x1D62E]={
category="ll",
@@ -132905,6 +167142,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006D },
unicodeslot=0x1D62E,
+ visual="it",
},
[0x1D62F]={
category="ll",
@@ -132913,6 +167151,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006E },
unicodeslot=0x1D62F,
+ visual="it",
},
[0x1D630]={
category="ll",
@@ -132921,6 +167160,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006F },
unicodeslot=0x1D630,
+ visual="it",
},
[0x1D631]={
category="ll",
@@ -132929,6 +167169,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0070 },
unicodeslot=0x1D631,
+ visual="it",
},
[0x1D632]={
category="ll",
@@ -132937,6 +167178,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0071 },
unicodeslot=0x1D632,
+ visual="it",
},
[0x1D633]={
category="ll",
@@ -132945,6 +167187,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0072 },
unicodeslot=0x1D633,
+ visual="it",
},
[0x1D634]={
category="ll",
@@ -132953,6 +167196,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0073 },
unicodeslot=0x1D634,
+ visual="it",
},
[0x1D635]={
category="ll",
@@ -132961,6 +167205,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0074 },
unicodeslot=0x1D635,
+ visual="it",
},
[0x1D636]={
category="ll",
@@ -132969,6 +167214,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0075 },
unicodeslot=0x1D636,
+ visual="it",
},
[0x1D637]={
category="ll",
@@ -132977,6 +167223,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0076 },
unicodeslot=0x1D637,
+ visual="it",
},
[0x1D638]={
category="ll",
@@ -132985,6 +167232,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0077 },
unicodeslot=0x1D638,
+ visual="it",
},
[0x1D639]={
category="ll",
@@ -132993,6 +167241,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0078 },
unicodeslot=0x1D639,
+ visual="it",
},
[0x1D63A]={
category="ll",
@@ -133001,6 +167250,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0079 },
unicodeslot=0x1D63A,
+ visual="it",
},
[0x1D63B]={
category="ll",
@@ -133009,6 +167259,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x007A },
unicodeslot=0x1D63B,
+ visual="it",
},
[0x1D63C]={
category="lu",
@@ -133017,6 +167268,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0041 },
unicodeslot=0x1D63C,
+ visual="bi",
},
[0x1D63D]={
category="lu",
@@ -133025,6 +167277,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0042 },
unicodeslot=0x1D63D,
+ visual="bi",
},
[0x1D63E]={
category="lu",
@@ -133033,6 +167286,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0043 },
unicodeslot=0x1D63E,
+ visual="bi",
},
[0x1D63F]={
category="lu",
@@ -133041,6 +167295,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0044 },
unicodeslot=0x1D63F,
+ visual="bi",
},
[0x1D640]={
category="lu",
@@ -133049,6 +167304,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0045 },
unicodeslot=0x1D640,
+ visual="bi",
},
[0x1D641]={
category="lu",
@@ -133057,6 +167313,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0046 },
unicodeslot=0x1D641,
+ visual="bi",
},
[0x1D642]={
category="lu",
@@ -133065,6 +167322,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0047 },
unicodeslot=0x1D642,
+ visual="bi",
},
[0x1D643]={
category="lu",
@@ -133073,6 +167331,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0048 },
unicodeslot=0x1D643,
+ visual="bi",
},
[0x1D644]={
category="lu",
@@ -133081,6 +167340,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0049 },
unicodeslot=0x1D644,
+ visual="bi",
},
[0x1D645]={
category="lu",
@@ -133089,6 +167349,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004A },
unicodeslot=0x1D645,
+ visual="bi",
},
[0x1D646]={
category="lu",
@@ -133097,6 +167358,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004B },
unicodeslot=0x1D646,
+ visual="bi",
},
[0x1D647]={
category="lu",
@@ -133105,6 +167367,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004C },
unicodeslot=0x1D647,
+ visual="bi",
},
[0x1D648]={
category="lu",
@@ -133113,6 +167376,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004D },
unicodeslot=0x1D648,
+ visual="bi",
},
[0x1D649]={
category="lu",
@@ -133121,6 +167385,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004E },
unicodeslot=0x1D649,
+ visual="bi",
},
[0x1D64A]={
category="lu",
@@ -133129,6 +167394,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x004F },
unicodeslot=0x1D64A,
+ visual="bi",
},
[0x1D64B]={
category="lu",
@@ -133137,6 +167403,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0050 },
unicodeslot=0x1D64B,
+ visual="bi",
},
[0x1D64C]={
category="lu",
@@ -133145,6 +167412,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0051 },
unicodeslot=0x1D64C,
+ visual="bi",
},
[0x1D64D]={
category="lu",
@@ -133153,6 +167421,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0052 },
unicodeslot=0x1D64D,
+ visual="bi",
},
[0x1D64E]={
category="lu",
@@ -133161,6 +167430,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0053 },
unicodeslot=0x1D64E,
+ visual="bi",
},
[0x1D64F]={
category="lu",
@@ -133169,6 +167439,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0054 },
unicodeslot=0x1D64F,
+ visual="bi",
},
[0x1D650]={
category="lu",
@@ -133177,6 +167448,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0055 },
unicodeslot=0x1D650,
+ visual="bi",
},
[0x1D651]={
category="lu",
@@ -133185,6 +167457,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0056 },
unicodeslot=0x1D651,
+ visual="bi",
},
[0x1D652]={
category="lu",
@@ -133193,6 +167466,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0057 },
unicodeslot=0x1D652,
+ visual="bi",
},
[0x1D653]={
category="lu",
@@ -133201,6 +167475,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0058 },
unicodeslot=0x1D653,
+ visual="bi",
},
[0x1D654]={
category="lu",
@@ -133209,6 +167484,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0059 },
unicodeslot=0x1D654,
+ visual="bi",
},
[0x1D655]={
category="lu",
@@ -133217,6 +167493,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x005A },
unicodeslot=0x1D655,
+ visual="bi",
},
[0x1D656]={
category="ll",
@@ -133225,6 +167502,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0061 },
unicodeslot=0x1D656,
+ visual="bi",
},
[0x1D657]={
category="ll",
@@ -133233,6 +167511,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0062 },
unicodeslot=0x1D657,
+ visual="bi",
},
[0x1D658]={
category="ll",
@@ -133241,6 +167520,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0063 },
unicodeslot=0x1D658,
+ visual="bi",
},
[0x1D659]={
category="ll",
@@ -133249,6 +167529,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0064 },
unicodeslot=0x1D659,
+ visual="bi",
},
[0x1D65A]={
category="ll",
@@ -133257,6 +167538,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0065 },
unicodeslot=0x1D65A,
+ visual="bi",
},
[0x1D65B]={
category="ll",
@@ -133265,6 +167547,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0066 },
unicodeslot=0x1D65B,
+ visual="bi",
},
[0x1D65C]={
category="ll",
@@ -133273,6 +167556,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0067 },
unicodeslot=0x1D65C,
+ visual="bi",
},
[0x1D65D]={
category="ll",
@@ -133281,6 +167565,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0068 },
unicodeslot=0x1D65D,
+ visual="bi",
},
[0x1D65E]={
category="ll",
@@ -133289,6 +167574,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0069 },
unicodeslot=0x1D65E,
+ visual="bi",
},
[0x1D65F]={
category="ll",
@@ -133297,6 +167583,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006A },
unicodeslot=0x1D65F,
+ visual="bi",
},
[0x1D660]={
category="ll",
@@ -133305,6 +167592,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006B },
unicodeslot=0x1D660,
+ visual="bi",
},
[0x1D661]={
category="ll",
@@ -133313,6 +167601,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006C },
unicodeslot=0x1D661,
+ visual="bi",
},
[0x1D662]={
category="ll",
@@ -133321,6 +167610,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006D },
unicodeslot=0x1D662,
+ visual="bi",
},
[0x1D663]={
category="ll",
@@ -133329,6 +167619,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006E },
unicodeslot=0x1D663,
+ visual="bi",
},
[0x1D664]={
category="ll",
@@ -133337,6 +167628,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x006F },
unicodeslot=0x1D664,
+ visual="bi",
},
[0x1D665]={
category="ll",
@@ -133345,6 +167637,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0070 },
unicodeslot=0x1D665,
+ visual="bi",
},
[0x1D666]={
category="ll",
@@ -133353,6 +167646,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0071 },
unicodeslot=0x1D666,
+ visual="bi",
},
[0x1D667]={
category="ll",
@@ -133361,6 +167655,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0072 },
unicodeslot=0x1D667,
+ visual="bi",
},
[0x1D668]={
category="ll",
@@ -133369,6 +167664,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0073 },
unicodeslot=0x1D668,
+ visual="bi",
},
[0x1D669]={
category="ll",
@@ -133377,6 +167673,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0074 },
unicodeslot=0x1D669,
+ visual="bi",
},
[0x1D66A]={
category="ll",
@@ -133385,6 +167682,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0075 },
unicodeslot=0x1D66A,
+ visual="bi",
},
[0x1D66B]={
category="ll",
@@ -133393,6 +167691,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0076 },
unicodeslot=0x1D66B,
+ visual="bi",
},
[0x1D66C]={
category="ll",
@@ -133401,6 +167700,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0077 },
unicodeslot=0x1D66C,
+ visual="bi",
},
[0x1D66D]={
category="ll",
@@ -133409,6 +167709,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0078 },
unicodeslot=0x1D66D,
+ visual="bi",
},
[0x1D66E]={
category="ll",
@@ -133417,6 +167718,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0079 },
unicodeslot=0x1D66E,
+ visual="bi",
},
[0x1D66F]={
category="ll",
@@ -133425,6 +167727,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x007A },
unicodeslot=0x1D66F,
+ visual="bi",
},
[0x1D670]={
category="lu",
@@ -133851,6 +168154,7 @@ characters.data={
mathname="imath",
specials={ "font", 0x0131 },
unicodeslot=0x1D6A4,
+ visual="it",
},
[0x1D6A5]={
category="ll",
@@ -133861,6 +168165,7 @@ characters.data={
mathname="jmath",
specials={ "font", 0x0237 },
unicodeslot=0x1D6A5,
+ visual="it",
},
[0x1D6A8]={
category="lu",
@@ -133869,6 +168174,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0391 },
unicodeslot=0x1D6A8,
+ visual="bf",
},
[0x1D6A9]={
category="lu",
@@ -133877,6 +168183,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0392 },
unicodeslot=0x1D6A9,
+ visual="bf",
},
[0x1D6AA]={
category="lu",
@@ -133885,6 +168192,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0393 },
unicodeslot=0x1D6AA,
+ visual="bf",
},
[0x1D6AB]={
category="lu",
@@ -133893,6 +168201,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0394 },
unicodeslot=0x1D6AB,
+ visual="bf",
},
[0x1D6AC]={
category="lu",
@@ -133901,6 +168210,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0395 },
unicodeslot=0x1D6AC,
+ visual="bf",
},
[0x1D6AD]={
category="lu",
@@ -133909,6 +168219,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0396 },
unicodeslot=0x1D6AD,
+ visual="bf",
},
[0x1D6AE]={
category="lu",
@@ -133917,6 +168228,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0397 },
unicodeslot=0x1D6AE,
+ visual="bf",
},
[0x1D6AF]={
category="lu",
@@ -133925,6 +168237,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0398 },
unicodeslot=0x1D6AF,
+ visual="bf",
},
[0x1D6B0]={
category="lu",
@@ -133933,6 +168246,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0399 },
unicodeslot=0x1D6B0,
+ visual="bf",
},
[0x1D6B1]={
category="lu",
@@ -133941,6 +168255,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039A },
unicodeslot=0x1D6B1,
+ visual="bf",
},
[0x1D6B2]={
category="lu",
@@ -133949,6 +168264,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039B },
unicodeslot=0x1D6B2,
+ visual="bf",
},
[0x1D6B3]={
category="lu",
@@ -133957,6 +168273,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039C },
unicodeslot=0x1D6B3,
+ visual="bf",
},
[0x1D6B4]={
category="lu",
@@ -133965,6 +168282,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039D },
unicodeslot=0x1D6B4,
+ visual="bf",
},
[0x1D6B5]={
category="lu",
@@ -133973,6 +168291,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039E },
unicodeslot=0x1D6B5,
+ visual="bf",
},
[0x1D6B6]={
category="lu",
@@ -133981,6 +168300,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039F },
unicodeslot=0x1D6B6,
+ visual="bf",
},
[0x1D6B7]={
category="lu",
@@ -133989,6 +168309,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A0 },
unicodeslot=0x1D6B7,
+ visual="bf",
},
[0x1D6B8]={
category="lu",
@@ -133997,6 +168318,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A1 },
unicodeslot=0x1D6B8,
+ visual="bf",
},
[0x1D6B9]={
category="lu",
@@ -134005,6 +168327,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F4 },
unicodeslot=0x1D6B9,
+ visual="bf",
},
[0x1D6BA]={
category="lu",
@@ -134013,6 +168336,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A3 },
unicodeslot=0x1D6BA,
+ visual="bf",
},
[0x1D6BB]={
category="lu",
@@ -134021,6 +168345,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A4 },
unicodeslot=0x1D6BB,
+ visual="bf",
},
[0x1D6BC]={
category="lu",
@@ -134029,6 +168354,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A5 },
unicodeslot=0x1D6BC,
+ visual="bf",
},
[0x1D6BD]={
category="lu",
@@ -134037,6 +168363,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A6 },
unicodeslot=0x1D6BD,
+ visual="bf",
},
[0x1D6BE]={
category="lu",
@@ -134045,6 +168372,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A7 },
unicodeslot=0x1D6BE,
+ visual="bf",
},
[0x1D6BF]={
category="lu",
@@ -134053,6 +168381,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A8 },
unicodeslot=0x1D6BF,
+ visual="bf",
},
[0x1D6C0]={
category="lu",
@@ -134061,6 +168390,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A9 },
unicodeslot=0x1D6C0,
+ visual="bf",
},
[0x1D6C1]={
category="sm",
@@ -134069,6 +168399,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x2207 },
unicodeslot=0x1D6C1,
+ visual="bf",
},
[0x1D6C2]={
category="ll",
@@ -134077,6 +168408,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B1 },
unicodeslot=0x1D6C2,
+ visual="bf",
},
[0x1D6C3]={
category="ll",
@@ -134085,6 +168417,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B2 },
unicodeslot=0x1D6C3,
+ visual="bf",
},
[0x1D6C4]={
category="ll",
@@ -134093,6 +168426,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B3 },
unicodeslot=0x1D6C4,
+ visual="bf",
},
[0x1D6C5]={
category="ll",
@@ -134101,6 +168435,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B4 },
unicodeslot=0x1D6C5,
+ visual="bf",
},
[0x1D6C6]={
category="ll",
@@ -134109,6 +168444,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B5 },
unicodeslot=0x1D6C6,
+ visual="bf",
},
[0x1D6C7]={
category="ll",
@@ -134117,6 +168453,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B6 },
unicodeslot=0x1D6C7,
+ visual="bf",
},
[0x1D6C8]={
category="ll",
@@ -134125,6 +168462,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B7 },
unicodeslot=0x1D6C8,
+ visual="bf",
},
[0x1D6C9]={
category="ll",
@@ -134133,6 +168471,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B8 },
unicodeslot=0x1D6C9,
+ visual="bf",
},
[0x1D6CA]={
category="ll",
@@ -134141,6 +168480,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B9 },
unicodeslot=0x1D6CA,
+ visual="bf",
},
[0x1D6CB]={
category="ll",
@@ -134149,6 +168489,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BA },
unicodeslot=0x1D6CB,
+ visual="bf",
},
[0x1D6CC]={
category="ll",
@@ -134157,6 +168498,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BB },
unicodeslot=0x1D6CC,
+ visual="bf",
},
[0x1D6CD]={
category="ll",
@@ -134165,6 +168507,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BC },
unicodeslot=0x1D6CD,
+ visual="bf",
},
[0x1D6CE]={
category="ll",
@@ -134173,6 +168516,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BD },
unicodeslot=0x1D6CE,
+ visual="bf",
},
[0x1D6CF]={
category="ll",
@@ -134181,6 +168525,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BE },
unicodeslot=0x1D6CF,
+ visual="bf",
},
[0x1D6D0]={
category="ll",
@@ -134189,6 +168534,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BF },
unicodeslot=0x1D6D0,
+ visual="bf",
},
[0x1D6D1]={
category="ll",
@@ -134197,6 +168543,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C0 },
unicodeslot=0x1D6D1,
+ visual="bf",
},
[0x1D6D2]={
category="ll",
@@ -134205,6 +168552,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C1 },
unicodeslot=0x1D6D2,
+ visual="bf",
},
[0x1D6D3]={
category="ll",
@@ -134213,6 +168561,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C2 },
unicodeslot=0x1D6D3,
+ visual="bf",
},
[0x1D6D4]={
category="ll",
@@ -134221,6 +168570,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C3 },
unicodeslot=0x1D6D4,
+ visual="bf",
},
[0x1D6D5]={
category="ll",
@@ -134229,6 +168579,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C4 },
unicodeslot=0x1D6D5,
+ visual="bf",
},
[0x1D6D6]={
category="ll",
@@ -134237,6 +168588,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C5 },
unicodeslot=0x1D6D6,
+ visual="bf",
},
[0x1D6D7]={
category="ll",
@@ -134245,6 +168597,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C6 },
unicodeslot=0x1D6D7,
+ visual="bf",
},
[0x1D6D8]={
category="ll",
@@ -134253,6 +168606,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C7 },
unicodeslot=0x1D6D8,
+ visual="bf",
},
[0x1D6D9]={
category="ll",
@@ -134261,6 +168615,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C8 },
unicodeslot=0x1D6D9,
+ visual="bf",
},
[0x1D6DA]={
category="ll",
@@ -134269,14 +168624,16 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C9 },
unicodeslot=0x1D6DA,
+ visual="bf",
},
[0x1D6DB]={
category="sm",
description="MATHEMATICAL BOLD PARTIAL DIFFERENTIAL",
- direction="l",
+ direction="on",
linebreak="al",
specials={ "font", 0x2202 },
unicodeslot=0x1D6DB,
+ visual="bf",
},
[0x1D6DC]={
category="ll",
@@ -134285,6 +168642,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F5 },
unicodeslot=0x1D6DC,
+ visual="bf",
},
[0x1D6DD]={
category="ll",
@@ -134293,6 +168651,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D1 },
unicodeslot=0x1D6DD,
+ visual="bf",
},
[0x1D6DE]={
category="ll",
@@ -134301,6 +168660,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F0 },
unicodeslot=0x1D6DE,
+ visual="bf",
},
[0x1D6DF]={
category="ll",
@@ -134309,6 +168669,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D5 },
unicodeslot=0x1D6DF,
+ visual="bf",
},
[0x1D6E0]={
category="ll",
@@ -134317,6 +168678,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F1 },
unicodeslot=0x1D6E0,
+ visual="bf",
},
[0x1D6E1]={
category="ll",
@@ -134325,6 +168687,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D6 },
unicodeslot=0x1D6E1,
+ visual="bf",
},
[0x1D6E2]={
category="lu",
@@ -134333,6 +168696,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0391 },
unicodeslot=0x1D6E2,
+ visual="it",
},
[0x1D6E3]={
category="lu",
@@ -134341,6 +168705,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0392 },
unicodeslot=0x1D6E3,
+ visual="it",
},
[0x1D6E4]={
category="lu",
@@ -134349,6 +168714,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0393 },
unicodeslot=0x1D6E4,
+ visual="it",
},
[0x1D6E5]={
category="lu",
@@ -134357,6 +168723,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0394 },
unicodeslot=0x1D6E5,
+ visual="it",
},
[0x1D6E6]={
category="lu",
@@ -134365,6 +168732,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0395 },
unicodeslot=0x1D6E6,
+ visual="it",
},
[0x1D6E7]={
category="lu",
@@ -134373,6 +168741,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0396 },
unicodeslot=0x1D6E7,
+ visual="it",
},
[0x1D6E8]={
category="lu",
@@ -134381,6 +168750,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0397 },
unicodeslot=0x1D6E8,
+ visual="it",
},
[0x1D6E9]={
category="lu",
@@ -134389,6 +168759,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0398 },
unicodeslot=0x1D6E9,
+ visual="it",
},
[0x1D6EA]={
category="lu",
@@ -134397,6 +168768,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0399 },
unicodeslot=0x1D6EA,
+ visual="it",
},
[0x1D6EB]={
category="lu",
@@ -134405,6 +168777,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039A },
unicodeslot=0x1D6EB,
+ visual="it",
},
[0x1D6EC]={
category="lu",
@@ -134413,6 +168786,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039B },
unicodeslot=0x1D6EC,
+ visual="it",
},
[0x1D6ED]={
category="lu",
@@ -134421,6 +168795,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039C },
unicodeslot=0x1D6ED,
+ visual="it",
},
[0x1D6EE]={
category="lu",
@@ -134429,6 +168804,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039D },
unicodeslot=0x1D6EE,
+ visual="it",
},
[0x1D6EF]={
category="lu",
@@ -134437,6 +168813,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039E },
unicodeslot=0x1D6EF,
+ visual="it",
},
[0x1D6F0]={
category="lu",
@@ -134445,6 +168822,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039F },
unicodeslot=0x1D6F0,
+ visual="it",
},
[0x1D6F1]={
category="lu",
@@ -134453,6 +168831,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A0 },
unicodeslot=0x1D6F1,
+ visual="it",
},
[0x1D6F2]={
category="lu",
@@ -134461,6 +168840,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A1 },
unicodeslot=0x1D6F2,
+ visual="it",
},
[0x1D6F3]={
category="lu",
@@ -134469,6 +168849,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F4 },
unicodeslot=0x1D6F3,
+ visual="it",
},
[0x1D6F4]={
category="lu",
@@ -134477,6 +168858,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A3 },
unicodeslot=0x1D6F4,
+ visual="it",
},
[0x1D6F5]={
category="lu",
@@ -134485,6 +168867,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A4 },
unicodeslot=0x1D6F5,
+ visual="it",
},
[0x1D6F6]={
category="lu",
@@ -134493,6 +168876,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A5 },
unicodeslot=0x1D6F6,
+ visual="it",
},
[0x1D6F7]={
category="lu",
@@ -134501,6 +168885,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A6 },
unicodeslot=0x1D6F7,
+ visual="it",
},
[0x1D6F8]={
category="lu",
@@ -134509,6 +168894,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A7 },
unicodeslot=0x1D6F8,
+ visual="it",
},
[0x1D6F9]={
category="lu",
@@ -134517,6 +168903,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A8 },
unicodeslot=0x1D6F9,
+ visual="it",
},
[0x1D6FA]={
category="lu",
@@ -134525,6 +168912,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A9 },
unicodeslot=0x1D6FA,
+ visual="it",
},
[0x1D6FB]={
category="sm",
@@ -134535,6 +168923,7 @@ characters.data={
mathname="nabla",
specials={ "font", 0x2207 },
unicodeslot=0x1D6FB,
+ visual="it",
},
[0x1D6FC]={
category="ll",
@@ -134543,6 +168932,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B1 },
unicodeslot=0x1D6FC,
+ visual="it",
},
[0x1D6FD]={
category="ll",
@@ -134551,6 +168941,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B2 },
unicodeslot=0x1D6FD,
+ visual="it",
},
[0x1D6FE]={
category="ll",
@@ -134559,6 +168950,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B3 },
unicodeslot=0x1D6FE,
+ visual="it",
},
[0x1D6FF]={
category="ll",
@@ -134567,6 +168959,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B4 },
unicodeslot=0x1D6FF,
+ visual="it",
},
[0x1D700]={
category="ll",
@@ -134575,6 +168968,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B5 },
unicodeslot=0x1D700,
+ visual="it",
},
[0x1D701]={
category="ll",
@@ -134583,6 +168977,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B6 },
unicodeslot=0x1D701,
+ visual="it",
},
[0x1D702]={
category="ll",
@@ -134591,6 +168986,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B7 },
unicodeslot=0x1D702,
+ visual="it",
},
[0x1D703]={
category="ll",
@@ -134599,6 +168995,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B8 },
unicodeslot=0x1D703,
+ visual="it",
},
[0x1D704]={
category="ll",
@@ -134607,6 +169004,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B9 },
unicodeslot=0x1D704,
+ visual="it",
},
[0x1D705]={
category="ll",
@@ -134615,6 +169013,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BA },
unicodeslot=0x1D705,
+ visual="it",
},
[0x1D706]={
category="ll",
@@ -134623,6 +169022,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BB },
unicodeslot=0x1D706,
+ visual="it",
},
[0x1D707]={
category="ll",
@@ -134631,6 +169031,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BC },
unicodeslot=0x1D707,
+ visual="it",
},
[0x1D708]={
category="ll",
@@ -134639,6 +169040,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BD },
unicodeslot=0x1D708,
+ visual="it",
},
[0x1D709]={
category="ll",
@@ -134647,6 +169049,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BE },
unicodeslot=0x1D709,
+ visual="it",
},
[0x1D70A]={
category="ll",
@@ -134655,6 +169058,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BF },
unicodeslot=0x1D70A,
+ visual="it",
},
[0x1D70B]={
category="ll",
@@ -134663,6 +169067,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C0 },
unicodeslot=0x1D70B,
+ visual="it",
},
[0x1D70C]={
category="ll",
@@ -134671,6 +169076,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C1 },
unicodeslot=0x1D70C,
+ visual="it",
},
[0x1D70D]={
category="ll",
@@ -134679,6 +169085,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C2 },
unicodeslot=0x1D70D,
+ visual="it",
},
[0x1D70E]={
category="ll",
@@ -134687,6 +169094,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C3 },
unicodeslot=0x1D70E,
+ visual="it",
},
[0x1D70F]={
category="ll",
@@ -134695,6 +169103,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C4 },
unicodeslot=0x1D70F,
+ visual="it",
},
[0x1D710]={
category="ll",
@@ -134703,6 +169112,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C5 },
unicodeslot=0x1D710,
+ visual="it",
},
[0x1D711]={
category="ll",
@@ -134711,6 +169121,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C6 },
unicodeslot=0x1D711,
+ visual="it",
},
[0x1D712]={
category="ll",
@@ -134719,6 +169130,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C7 },
unicodeslot=0x1D712,
+ visual="it",
},
[0x1D713]={
category="ll",
@@ -134727,6 +169139,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C8 },
unicodeslot=0x1D713,
+ visual="it",
},
[0x1D714]={
category="ll",
@@ -134735,14 +169148,16 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C9 },
unicodeslot=0x1D714,
+ visual="it",
},
[0x1D715]={
category="sm",
description="MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL",
- direction="l",
+ direction="on",
linebreak="al",
specials={ "font", 0x2202 },
unicodeslot=0x1D715,
+ visual="it",
},
[0x1D716]={
category="ll",
@@ -134751,6 +169166,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F5 },
unicodeslot=0x1D716,
+ visual="it",
},
[0x1D717]={
category="ll",
@@ -134761,6 +169177,7 @@ characters.data={
mathname="vartheta",
specials={ "font", 0x03D1 },
unicodeslot=0x1D717,
+ visual="it",
},
[0x1D718]={
category="ll",
@@ -134771,6 +169188,7 @@ characters.data={
mathname="varkappa",
specials={ "font", 0x03F0 },
unicodeslot=0x1D718,
+ visual="it",
},
[0x1D719]={
category="ll",
@@ -134779,6 +169197,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D5 },
unicodeslot=0x1D719,
+ visual="it",
},
[0x1D71A]={
category="ll",
@@ -134789,6 +169208,7 @@ characters.data={
mathname="varrho",
specials={ "font", 0x03F1 },
unicodeslot=0x1D71A,
+ visual="it",
},
[0x1D71B]={
category="ll",
@@ -134797,6 +169217,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D6 },
unicodeslot=0x1D71B,
+ visual="it",
},
[0x1D71C]={
category="lu",
@@ -134805,6 +169226,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0391 },
unicodeslot=0x1D71C,
+ visual="bi",
},
[0x1D71D]={
category="lu",
@@ -134813,6 +169235,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0392 },
unicodeslot=0x1D71D,
+ visual="bi",
},
[0x1D71E]={
category="lu",
@@ -134821,6 +169244,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0393 },
unicodeslot=0x1D71E,
+ visual="bi",
},
[0x1D71F]={
category="lu",
@@ -134829,6 +169253,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0394 },
unicodeslot=0x1D71F,
+ visual="bi",
},
[0x1D720]={
category="lu",
@@ -134837,6 +169262,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0395 },
unicodeslot=0x1D720,
+ visual="bi",
},
[0x1D721]={
category="lu",
@@ -134845,6 +169271,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0396 },
unicodeslot=0x1D721,
+ visual="bi",
},
[0x1D722]={
category="lu",
@@ -134853,6 +169280,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0397 },
unicodeslot=0x1D722,
+ visual="bi",
},
[0x1D723]={
category="lu",
@@ -134861,6 +169289,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0398 },
unicodeslot=0x1D723,
+ visual="bi",
},
[0x1D724]={
category="lu",
@@ -134869,6 +169298,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0399 },
unicodeslot=0x1D724,
+ visual="bi",
},
[0x1D725]={
category="lu",
@@ -134877,6 +169307,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039A },
unicodeslot=0x1D725,
+ visual="bi",
},
[0x1D726]={
category="lu",
@@ -134885,6 +169316,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039B },
unicodeslot=0x1D726,
+ visual="bi",
},
[0x1D727]={
category="lu",
@@ -134893,6 +169325,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039C },
unicodeslot=0x1D727,
+ visual="bi",
},
[0x1D728]={
category="lu",
@@ -134901,6 +169334,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039D },
unicodeslot=0x1D728,
+ visual="bi",
},
[0x1D729]={
category="lu",
@@ -134909,6 +169343,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039E },
unicodeslot=0x1D729,
+ visual="bi",
},
[0x1D72A]={
category="lu",
@@ -134917,6 +169352,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039F },
unicodeslot=0x1D72A,
+ visual="bi",
},
[0x1D72B]={
category="lu",
@@ -134925,6 +169361,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A0 },
unicodeslot=0x1D72B,
+ visual="bi",
},
[0x1D72C]={
category="lu",
@@ -134933,6 +169370,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A1 },
unicodeslot=0x1D72C,
+ visual="bi",
},
[0x1D72D]={
category="lu",
@@ -134941,6 +169379,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F4 },
unicodeslot=0x1D72D,
+ visual="bi",
},
[0x1D72E]={
category="lu",
@@ -134949,6 +169388,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A3 },
unicodeslot=0x1D72E,
+ visual="bi",
},
[0x1D72F]={
category="lu",
@@ -134957,6 +169397,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A4 },
unicodeslot=0x1D72F,
+ visual="bi",
},
[0x1D730]={
category="lu",
@@ -134965,6 +169406,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A5 },
unicodeslot=0x1D730,
+ visual="bi",
},
[0x1D731]={
category="lu",
@@ -134973,6 +169415,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A6 },
unicodeslot=0x1D731,
+ visual="bi",
},
[0x1D732]={
category="lu",
@@ -134981,6 +169424,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A7 },
unicodeslot=0x1D732,
+ visual="bi",
},
[0x1D733]={
category="lu",
@@ -134989,6 +169433,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A8 },
unicodeslot=0x1D733,
+ visual="bi",
},
[0x1D734]={
category="lu",
@@ -134997,6 +169442,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A9 },
unicodeslot=0x1D734,
+ visual="bi",
},
[0x1D735]={
category="sm",
@@ -135005,6 +169451,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x2207 },
unicodeslot=0x1D735,
+ visual="bi",
},
[0x1D736]={
category="ll",
@@ -135013,6 +169460,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B1 },
unicodeslot=0x1D736,
+ visual="bi",
},
[0x1D737]={
category="ll",
@@ -135021,6 +169469,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B2 },
unicodeslot=0x1D737,
+ visual="bi",
},
[0x1D738]={
category="ll",
@@ -135029,6 +169478,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B3 },
unicodeslot=0x1D738,
+ visual="bi",
},
[0x1D739]={
category="ll",
@@ -135037,6 +169487,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B4 },
unicodeslot=0x1D739,
+ visual="bi",
},
[0x1D73A]={
category="ll",
@@ -135045,6 +169496,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B5 },
unicodeslot=0x1D73A,
+ visual="bi",
},
[0x1D73B]={
category="ll",
@@ -135053,6 +169505,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B6 },
unicodeslot=0x1D73B,
+ visual="bi",
},
[0x1D73C]={
category="ll",
@@ -135061,6 +169514,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B7 },
unicodeslot=0x1D73C,
+ visual="bi",
},
[0x1D73D]={
category="ll",
@@ -135069,6 +169523,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B8 },
unicodeslot=0x1D73D,
+ visual="bi",
},
[0x1D73E]={
category="ll",
@@ -135077,6 +169532,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B9 },
unicodeslot=0x1D73E,
+ visual="bi",
},
[0x1D73F]={
category="ll",
@@ -135085,6 +169541,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BA },
unicodeslot=0x1D73F,
+ visual="bi",
},
[0x1D740]={
category="ll",
@@ -135093,6 +169550,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BB },
unicodeslot=0x1D740,
+ visual="bi",
},
[0x1D741]={
category="ll",
@@ -135101,6 +169559,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BC },
unicodeslot=0x1D741,
+ visual="bi",
},
[0x1D742]={
category="ll",
@@ -135109,6 +169568,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BD },
unicodeslot=0x1D742,
+ visual="bi",
},
[0x1D743]={
category="ll",
@@ -135117,6 +169577,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BE },
unicodeslot=0x1D743,
+ visual="bi",
},
[0x1D744]={
category="ll",
@@ -135125,6 +169586,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BF },
unicodeslot=0x1D744,
+ visual="bi",
},
[0x1D745]={
category="ll",
@@ -135133,6 +169595,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C0 },
unicodeslot=0x1D745,
+ visual="bi",
},
[0x1D746]={
category="ll",
@@ -135141,6 +169604,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C1 },
unicodeslot=0x1D746,
+ visual="bi",
},
[0x1D747]={
category="ll",
@@ -135149,6 +169613,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C2 },
unicodeslot=0x1D747,
+ visual="bi",
},
[0x1D748]={
category="ll",
@@ -135157,6 +169622,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C3 },
unicodeslot=0x1D748,
+ visual="bi",
},
[0x1D749]={
category="ll",
@@ -135165,6 +169631,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C4 },
unicodeslot=0x1D749,
+ visual="bi",
},
[0x1D74A]={
category="ll",
@@ -135173,6 +169640,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C5 },
unicodeslot=0x1D74A,
+ visual="bi",
},
[0x1D74B]={
category="ll",
@@ -135181,6 +169649,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C6 },
unicodeslot=0x1D74B,
+ visual="bi",
},
[0x1D74C]={
category="ll",
@@ -135189,6 +169658,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C7 },
unicodeslot=0x1D74C,
+ visual="bi",
},
[0x1D74D]={
category="ll",
@@ -135197,6 +169667,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C8 },
unicodeslot=0x1D74D,
+ visual="bi",
},
[0x1D74E]={
category="ll",
@@ -135205,14 +169676,16 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C9 },
unicodeslot=0x1D74E,
+ visual="bi",
},
[0x1D74F]={
category="sm",
description="MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL",
- direction="l",
+ direction="on",
linebreak="al",
specials={ "font", 0x2202 },
unicodeslot=0x1D74F,
+ visual="bi",
},
[0x1D750]={
category="ll",
@@ -135221,6 +169694,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F5 },
unicodeslot=0x1D750,
+ visual="bi",
},
[0x1D751]={
category="ll",
@@ -135229,6 +169703,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D1 },
unicodeslot=0x1D751,
+ visual="bi",
},
[0x1D752]={
category="ll",
@@ -135237,6 +169712,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F0 },
unicodeslot=0x1D752,
+ visual="bi",
},
[0x1D753]={
category="ll",
@@ -135245,6 +169721,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D5 },
unicodeslot=0x1D753,
+ visual="bi",
},
[0x1D754]={
category="ll",
@@ -135253,6 +169730,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F1 },
unicodeslot=0x1D754,
+ visual="bi",
},
[0x1D755]={
category="ll",
@@ -135261,6 +169739,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D6 },
unicodeslot=0x1D755,
+ visual="bi",
},
[0x1D756]={
category="lu",
@@ -135269,6 +169748,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0391 },
unicodeslot=0x1D756,
+ visual="bf",
},
[0x1D757]={
category="lu",
@@ -135277,6 +169757,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0392 },
unicodeslot=0x1D757,
+ visual="bf",
},
[0x1D758]={
category="lu",
@@ -135285,6 +169766,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0393 },
unicodeslot=0x1D758,
+ visual="bf",
},
[0x1D759]={
category="lu",
@@ -135293,6 +169775,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0394 },
unicodeslot=0x1D759,
+ visual="bf",
},
[0x1D75A]={
category="lu",
@@ -135301,6 +169784,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0395 },
unicodeslot=0x1D75A,
+ visual="bf",
},
[0x1D75B]={
category="lu",
@@ -135309,6 +169793,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0396 },
unicodeslot=0x1D75B,
+ visual="bf",
},
[0x1D75C]={
category="lu",
@@ -135317,6 +169802,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0397 },
unicodeslot=0x1D75C,
+ visual="bf",
},
[0x1D75D]={
category="lu",
@@ -135325,6 +169811,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0398 },
unicodeslot=0x1D75D,
+ visual="bf",
},
[0x1D75E]={
category="lu",
@@ -135333,6 +169820,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0399 },
unicodeslot=0x1D75E,
+ visual="bf",
},
[0x1D75F]={
category="lu",
@@ -135341,6 +169829,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039A },
unicodeslot=0x1D75F,
+ visual="bf",
},
[0x1D760]={
category="lu",
@@ -135349,6 +169838,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039B },
unicodeslot=0x1D760,
+ visual="bf",
},
[0x1D761]={
category="lu",
@@ -135357,6 +169847,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039C },
unicodeslot=0x1D761,
+ visual="bf",
},
[0x1D762]={
category="lu",
@@ -135365,6 +169856,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039D },
unicodeslot=0x1D762,
+ visual="bf",
},
[0x1D763]={
category="lu",
@@ -135373,6 +169865,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039E },
unicodeslot=0x1D763,
+ visual="bf",
},
[0x1D764]={
category="lu",
@@ -135381,6 +169874,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039F },
unicodeslot=0x1D764,
+ visual="bf",
},
[0x1D765]={
category="lu",
@@ -135389,6 +169883,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A0 },
unicodeslot=0x1D765,
+ visual="bf",
},
[0x1D766]={
category="lu",
@@ -135397,6 +169892,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A1 },
unicodeslot=0x1D766,
+ visual="bf",
},
[0x1D767]={
category="lu",
@@ -135405,6 +169901,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F4 },
unicodeslot=0x1D767,
+ visual="bf",
},
[0x1D768]={
category="lu",
@@ -135413,6 +169910,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A3 },
unicodeslot=0x1D768,
+ visual="bf",
},
[0x1D769]={
category="lu",
@@ -135421,6 +169919,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A4 },
unicodeslot=0x1D769,
+ visual="bf",
},
[0x1D76A]={
category="lu",
@@ -135429,6 +169928,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A5 },
unicodeslot=0x1D76A,
+ visual="bf",
},
[0x1D76B]={
category="lu",
@@ -135437,6 +169937,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A6 },
unicodeslot=0x1D76B,
+ visual="bf",
},
[0x1D76C]={
category="lu",
@@ -135445,6 +169946,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A7 },
unicodeslot=0x1D76C,
+ visual="bf",
},
[0x1D76D]={
category="lu",
@@ -135453,6 +169955,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A8 },
unicodeslot=0x1D76D,
+ visual="bf",
},
[0x1D76E]={
category="lu",
@@ -135461,6 +169964,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A9 },
unicodeslot=0x1D76E,
+ visual="bf",
},
[0x1D76F]={
category="sm",
@@ -135469,6 +169973,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x2207 },
unicodeslot=0x1D76F,
+ visual="bf",
},
[0x1D770]={
category="ll",
@@ -135477,6 +169982,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B1 },
unicodeslot=0x1D770,
+ visual="bf",
},
[0x1D771]={
category="ll",
@@ -135485,6 +169991,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B2 },
unicodeslot=0x1D771,
+ visual="bf",
},
[0x1D772]={
category="ll",
@@ -135493,6 +170000,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B3 },
unicodeslot=0x1D772,
+ visual="bf",
},
[0x1D773]={
category="ll",
@@ -135501,6 +170009,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B4 },
unicodeslot=0x1D773,
+ visual="bf",
},
[0x1D774]={
category="ll",
@@ -135509,6 +170018,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B5 },
unicodeslot=0x1D774,
+ visual="bf",
},
[0x1D775]={
category="ll",
@@ -135517,6 +170027,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B6 },
unicodeslot=0x1D775,
+ visual="bf",
},
[0x1D776]={
category="ll",
@@ -135525,6 +170036,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B7 },
unicodeslot=0x1D776,
+ visual="bf",
},
[0x1D777]={
category="ll",
@@ -135533,6 +170045,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B8 },
unicodeslot=0x1D777,
+ visual="bf",
},
[0x1D778]={
category="ll",
@@ -135541,6 +170054,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B9 },
unicodeslot=0x1D778,
+ visual="bf",
},
[0x1D779]={
category="ll",
@@ -135549,6 +170063,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BA },
unicodeslot=0x1D779,
+ visual="bf",
},
[0x1D77A]={
category="ll",
@@ -135557,6 +170072,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BB },
unicodeslot=0x1D77A,
+ visual="bf",
},
[0x1D77B]={
category="ll",
@@ -135565,6 +170081,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BC },
unicodeslot=0x1D77B,
+ visual="bf",
},
[0x1D77C]={
category="ll",
@@ -135573,6 +170090,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BD },
unicodeslot=0x1D77C,
+ visual="bf",
},
[0x1D77D]={
category="ll",
@@ -135581,6 +170099,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BE },
unicodeslot=0x1D77D,
+ visual="bf",
},
[0x1D77E]={
category="ll",
@@ -135589,6 +170108,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BF },
unicodeslot=0x1D77E,
+ visual="bf",
},
[0x1D77F]={
category="ll",
@@ -135597,6 +170117,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C0 },
unicodeslot=0x1D77F,
+ visual="bf",
},
[0x1D780]={
category="ll",
@@ -135605,6 +170126,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C1 },
unicodeslot=0x1D780,
+ visual="bf",
},
[0x1D781]={
category="ll",
@@ -135613,6 +170135,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C2 },
unicodeslot=0x1D781,
+ visual="bf",
},
[0x1D782]={
category="ll",
@@ -135621,6 +170144,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C3 },
unicodeslot=0x1D782,
+ visual="bf",
},
[0x1D783]={
category="ll",
@@ -135629,6 +170153,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C4 },
unicodeslot=0x1D783,
+ visual="bf",
},
[0x1D784]={
category="ll",
@@ -135637,6 +170162,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C5 },
unicodeslot=0x1D784,
+ visual="bf",
},
[0x1D785]={
category="ll",
@@ -135645,6 +170171,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C6 },
unicodeslot=0x1D785,
+ visual="bf",
},
[0x1D786]={
category="ll",
@@ -135653,6 +170180,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C7 },
unicodeslot=0x1D786,
+ visual="bf",
},
[0x1D787]={
category="ll",
@@ -135661,6 +170189,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C8 },
unicodeslot=0x1D787,
+ visual="bf",
},
[0x1D788]={
category="ll",
@@ -135669,14 +170198,16 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C9 },
unicodeslot=0x1D788,
+ visual="bf",
},
[0x1D789]={
category="sm",
description="MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL",
- direction="l",
+ direction="on",
linebreak="al",
specials={ "font", 0x2202 },
unicodeslot=0x1D789,
+ visual="bf",
},
[0x1D78A]={
category="ll",
@@ -135685,6 +170216,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F5 },
unicodeslot=0x1D78A,
+ visual="bf",
},
[0x1D78B]={
category="ll",
@@ -135693,6 +170225,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D1 },
unicodeslot=0x1D78B,
+ visual="bf",
},
[0x1D78C]={
category="ll",
@@ -135701,6 +170234,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F0 },
unicodeslot=0x1D78C,
+ visual="bf",
},
[0x1D78D]={
category="ll",
@@ -135709,6 +170243,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D5 },
unicodeslot=0x1D78D,
+ visual="bf",
},
[0x1D78E]={
category="ll",
@@ -135717,6 +170252,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F1 },
unicodeslot=0x1D78E,
+ visual="bf",
},
[0x1D78F]={
category="ll",
@@ -135725,6 +170261,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D6 },
unicodeslot=0x1D78F,
+ visual="bf",
},
[0x1D790]={
category="lu",
@@ -135733,6 +170270,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0391 },
unicodeslot=0x1D790,
+ visual="bi",
},
[0x1D791]={
category="lu",
@@ -135741,6 +170279,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0392 },
unicodeslot=0x1D791,
+ visual="bi",
},
[0x1D792]={
category="lu",
@@ -135749,6 +170288,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0393 },
unicodeslot=0x1D792,
+ visual="bi",
},
[0x1D793]={
category="lu",
@@ -135757,6 +170297,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0394 },
unicodeslot=0x1D793,
+ visual="bi",
},
[0x1D794]={
category="lu",
@@ -135765,6 +170306,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0395 },
unicodeslot=0x1D794,
+ visual="bi",
},
[0x1D795]={
category="lu",
@@ -135773,6 +170315,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0396 },
unicodeslot=0x1D795,
+ visual="bi",
},
[0x1D796]={
category="lu",
@@ -135781,6 +170324,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0397 },
unicodeslot=0x1D796,
+ visual="bi",
},
[0x1D797]={
category="lu",
@@ -135789,6 +170333,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0398 },
unicodeslot=0x1D797,
+ visual="bi",
},
[0x1D798]={
category="lu",
@@ -135797,6 +170342,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x0399 },
unicodeslot=0x1D798,
+ visual="bi",
},
[0x1D799]={
category="lu",
@@ -135805,6 +170351,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039A },
unicodeslot=0x1D799,
+ visual="bi",
},
[0x1D79A]={
category="lu",
@@ -135813,6 +170360,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039B },
unicodeslot=0x1D79A,
+ visual="bi",
},
[0x1D79B]={
category="lu",
@@ -135821,6 +170369,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039C },
unicodeslot=0x1D79B,
+ visual="bi",
},
[0x1D79C]={
category="lu",
@@ -135829,6 +170378,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039D },
unicodeslot=0x1D79C,
+ visual="bi",
},
[0x1D79D]={
category="lu",
@@ -135837,6 +170387,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039E },
unicodeslot=0x1D79D,
+ visual="bi",
},
[0x1D79E]={
category="lu",
@@ -135845,6 +170396,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x039F },
unicodeslot=0x1D79E,
+ visual="bi",
},
[0x1D79F]={
category="lu",
@@ -135853,6 +170405,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A0 },
unicodeslot=0x1D79F,
+ visual="bi",
},
[0x1D7A0]={
category="lu",
@@ -135861,6 +170414,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A1 },
unicodeslot=0x1D7A0,
+ visual="bi",
},
[0x1D7A1]={
category="lu",
@@ -135869,6 +170423,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F4 },
unicodeslot=0x1D7A1,
+ visual="bi",
},
[0x1D7A2]={
category="lu",
@@ -135877,6 +170432,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A3 },
unicodeslot=0x1D7A2,
+ visual="bi",
},
[0x1D7A3]={
category="lu",
@@ -135885,6 +170441,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A4 },
unicodeslot=0x1D7A3,
+ visual="bi",
},
[0x1D7A4]={
category="lu",
@@ -135893,6 +170450,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A5 },
unicodeslot=0x1D7A4,
+ visual="bi",
},
[0x1D7A5]={
category="lu",
@@ -135901,6 +170459,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A6 },
unicodeslot=0x1D7A5,
+ visual="bi",
},
[0x1D7A6]={
category="lu",
@@ -135909,6 +170468,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A7 },
unicodeslot=0x1D7A6,
+ visual="bi",
},
[0x1D7A7]={
category="lu",
@@ -135917,6 +170477,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A8 },
unicodeslot=0x1D7A7,
+ visual="bi",
},
[0x1D7A8]={
category="lu",
@@ -135925,6 +170486,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03A9 },
unicodeslot=0x1D7A8,
+ visual="bi",
},
[0x1D7A9]={
category="sm",
@@ -135933,6 +170495,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x2207 },
unicodeslot=0x1D7A9,
+ visual="bi",
},
[0x1D7AA]={
category="ll",
@@ -135941,6 +170504,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B1 },
unicodeslot=0x1D7AA,
+ visual="bi",
},
[0x1D7AB]={
category="ll",
@@ -135949,6 +170513,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B2 },
unicodeslot=0x1D7AB,
+ visual="bi",
},
[0x1D7AC]={
category="ll",
@@ -135957,6 +170522,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B3 },
unicodeslot=0x1D7AC,
+ visual="bi",
},
[0x1D7AD]={
category="ll",
@@ -135965,6 +170531,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B4 },
unicodeslot=0x1D7AD,
+ visual="bi",
},
[0x1D7AE]={
category="ll",
@@ -135973,6 +170540,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B5 },
unicodeslot=0x1D7AE,
+ visual="bi",
},
[0x1D7AF]={
category="ll",
@@ -135981,6 +170549,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B6 },
unicodeslot=0x1D7AF,
+ visual="bi",
},
[0x1D7B0]={
category="ll",
@@ -135989,6 +170558,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B7 },
unicodeslot=0x1D7B0,
+ visual="bi",
},
[0x1D7B1]={
category="ll",
@@ -135997,6 +170567,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B8 },
unicodeslot=0x1D7B1,
+ visual="bi",
},
[0x1D7B2]={
category="ll",
@@ -136005,6 +170576,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03B9 },
unicodeslot=0x1D7B2,
+ visual="bi",
},
[0x1D7B3]={
category="ll",
@@ -136013,6 +170585,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BA },
unicodeslot=0x1D7B3,
+ visual="bi",
},
[0x1D7B4]={
category="ll",
@@ -136021,6 +170594,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BB },
unicodeslot=0x1D7B4,
+ visual="bi",
},
[0x1D7B5]={
category="ll",
@@ -136029,6 +170603,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BC },
unicodeslot=0x1D7B5,
+ visual="bi",
},
[0x1D7B6]={
category="ll",
@@ -136037,6 +170612,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BD },
unicodeslot=0x1D7B6,
+ visual="bi",
},
[0x1D7B7]={
category="ll",
@@ -136045,6 +170621,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BE },
unicodeslot=0x1D7B7,
+ visual="bi",
},
[0x1D7B8]={
category="ll",
@@ -136053,6 +170630,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03BF },
unicodeslot=0x1D7B8,
+ visual="bi",
},
[0x1D7B9]={
category="ll",
@@ -136061,6 +170639,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C0 },
unicodeslot=0x1D7B9,
+ visual="bi",
},
[0x1D7BA]={
category="ll",
@@ -136069,6 +170648,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C1 },
unicodeslot=0x1D7BA,
+ visual="bi",
},
[0x1D7BB]={
category="ll",
@@ -136077,6 +170657,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C2 },
unicodeslot=0x1D7BB,
+ visual="bi",
},
[0x1D7BC]={
category="ll",
@@ -136085,6 +170666,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C3 },
unicodeslot=0x1D7BC,
+ visual="bi",
},
[0x1D7BD]={
category="ll",
@@ -136093,6 +170675,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C4 },
unicodeslot=0x1D7BD,
+ visual="bi",
},
[0x1D7BE]={
category="ll",
@@ -136101,6 +170684,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C5 },
unicodeslot=0x1D7BE,
+ visual="bi",
},
[0x1D7BF]={
category="ll",
@@ -136109,6 +170693,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C6 },
unicodeslot=0x1D7BF,
+ visual="bi",
},
[0x1D7C0]={
category="ll",
@@ -136117,6 +170702,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C7 },
unicodeslot=0x1D7C0,
+ visual="bi",
},
[0x1D7C1]={
category="ll",
@@ -136125,6 +170711,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C8 },
unicodeslot=0x1D7C1,
+ visual="bi",
},
[0x1D7C2]={
category="ll",
@@ -136133,14 +170720,16 @@ characters.data={
linebreak="al",
specials={ "font", 0x03C9 },
unicodeslot=0x1D7C2,
+ visual="bi",
},
[0x1D7C3]={
category="sm",
description="MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL",
- direction="l",
+ direction="on",
linebreak="al",
specials={ "font", 0x2202 },
unicodeslot=0x1D7C3,
+ visual="bi",
},
[0x1D7C4]={
category="ll",
@@ -136149,6 +170738,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F5 },
unicodeslot=0x1D7C4,
+ visual="bi",
},
[0x1D7C5]={
category="ll",
@@ -136157,6 +170747,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D1 },
unicodeslot=0x1D7C5,
+ visual="bi",
},
[0x1D7C6]={
category="ll",
@@ -136165,6 +170756,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F0 },
unicodeslot=0x1D7C6,
+ visual="bi",
},
[0x1D7C7]={
category="ll",
@@ -136173,6 +170765,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D5 },
unicodeslot=0x1D7C7,
+ visual="bi",
},
[0x1D7C8]={
category="ll",
@@ -136181,6 +170774,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03F1 },
unicodeslot=0x1D7C8,
+ visual="bi",
},
[0x1D7C9]={
category="ll",
@@ -136189,6 +170783,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03D6 },
unicodeslot=0x1D7C9,
+ visual="bi",
},
[0x1D7CA]={
category="lu",
@@ -136197,6 +170792,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03DC },
unicodeslot=0x1D7CA,
+ visual="bf",
},
[0x1D7CB]={
category="ll",
@@ -136205,6 +170801,7 @@ characters.data={
linebreak="al",
specials={ "font", 0x03DD },
unicodeslot=0x1D7CB,
+ visual="bf",
},
[0x1D7CE]={
category="nd",
@@ -136213,6 +170810,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0030 },
unicodeslot=0x1D7CE,
+ visual="bf",
},
[0x1D7CF]={
category="nd",
@@ -136221,6 +170819,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0031 },
unicodeslot=0x1D7CF,
+ visual="bf",
},
[0x1D7D0]={
category="nd",
@@ -136229,6 +170828,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0032 },
unicodeslot=0x1D7D0,
+ visual="bf",
},
[0x1D7D1]={
category="nd",
@@ -136237,6 +170837,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0033 },
unicodeslot=0x1D7D1,
+ visual="bf",
},
[0x1D7D2]={
category="nd",
@@ -136245,6 +170846,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0034 },
unicodeslot=0x1D7D2,
+ visual="bf",
},
[0x1D7D3]={
category="nd",
@@ -136253,6 +170855,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0035 },
unicodeslot=0x1D7D3,
+ visual="bf",
},
[0x1D7D4]={
category="nd",
@@ -136261,6 +170864,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0036 },
unicodeslot=0x1D7D4,
+ visual="bf",
},
[0x1D7D5]={
category="nd",
@@ -136269,6 +170873,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0037 },
unicodeslot=0x1D7D5,
+ visual="bf",
},
[0x1D7D6]={
category="nd",
@@ -136277,6 +170882,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0038 },
unicodeslot=0x1D7D6,
+ visual="bf",
},
[0x1D7D7]={
category="nd",
@@ -136285,6 +170891,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0039 },
unicodeslot=0x1D7D7,
+ visual="bf",
},
[0x1D7D8]={
category="nd",
@@ -136453,6 +171060,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0030 },
unicodeslot=0x1D7EC,
+ visual="bf",
},
[0x1D7ED]={
category="nd",
@@ -136461,6 +171069,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0031 },
unicodeslot=0x1D7ED,
+ visual="bf",
},
[0x1D7EE]={
category="nd",
@@ -136469,6 +171078,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0032 },
unicodeslot=0x1D7EE,
+ visual="bf",
},
[0x1D7EF]={
category="nd",
@@ -136477,6 +171087,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0033 },
unicodeslot=0x1D7EF,
+ visual="bf",
},
[0x1D7F0]={
category="nd",
@@ -136485,6 +171096,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0034 },
unicodeslot=0x1D7F0,
+ visual="bf",
},
[0x1D7F1]={
category="nd",
@@ -136493,6 +171105,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0035 },
unicodeslot=0x1D7F1,
+ visual="bf",
},
[0x1D7F2]={
category="nd",
@@ -136501,6 +171114,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0036 },
unicodeslot=0x1D7F2,
+ visual="bf",
},
[0x1D7F3]={
category="nd",
@@ -136509,6 +171123,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0037 },
unicodeslot=0x1D7F3,
+ visual="bf",
},
[0x1D7F4]={
category="nd",
@@ -136517,6 +171132,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0038 },
unicodeslot=0x1D7F4,
+ visual="bf",
},
[0x1D7F5]={
category="nd",
@@ -136525,6 +171141,7 @@ characters.data={
linebreak="nu",
specials={ "font", 0x0039 },
unicodeslot=0x1D7F5,
+ visual="bf",
},
[0x1D7F6]={
category="nd",
@@ -136606,6 +171223,8786 @@ characters.data={
specials={ "font", 0x0039 },
unicodeslot=0x1D7FF,
},
+ [0x1F000]={
+ category="so",
+ description="MAHJONG TILE EAST WIND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F000,
+ },
+ [0x1F001]={
+ category="so",
+ description="MAHJONG TILE SOUTH WIND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F001,
+ },
+ [0x1F002]={
+ category="so",
+ description="MAHJONG TILE WEST WIND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F002,
+ },
+ [0x1F003]={
+ category="so",
+ description="MAHJONG TILE NORTH WIND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F003,
+ },
+ [0x1F004]={
+ category="so",
+ description="MAHJONG TILE RED DRAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F004,
+ },
+ [0x1F005]={
+ category="so",
+ description="MAHJONG TILE GREEN DRAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F005,
+ },
+ [0x1F006]={
+ category="so",
+ description="MAHJONG TILE WHITE DRAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F006,
+ },
+ [0x1F007]={
+ category="so",
+ description="MAHJONG TILE ONE OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F007,
+ },
+ [0x1F008]={
+ category="so",
+ description="MAHJONG TILE TWO OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F008,
+ },
+ [0x1F009]={
+ category="so",
+ description="MAHJONG TILE THREE OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F009,
+ },
+ [0x1F00A]={
+ category="so",
+ description="MAHJONG TILE FOUR OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F00A,
+ },
+ [0x1F00B]={
+ category="so",
+ description="MAHJONG TILE FIVE OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F00B,
+ },
+ [0x1F00C]={
+ category="so",
+ description="MAHJONG TILE SIX OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F00C,
+ },
+ [0x1F00D]={
+ category="so",
+ description="MAHJONG TILE SEVEN OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F00D,
+ },
+ [0x1F00E]={
+ category="so",
+ description="MAHJONG TILE EIGHT OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F00E,
+ },
+ [0x1F00F]={
+ category="so",
+ description="MAHJONG TILE NINE OF CHARACTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F00F,
+ },
+ [0x1F010]={
+ category="so",
+ description="MAHJONG TILE ONE OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F010,
+ },
+ [0x1F011]={
+ category="so",
+ description="MAHJONG TILE TWO OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F011,
+ },
+ [0x1F012]={
+ category="so",
+ description="MAHJONG TILE THREE OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F012,
+ },
+ [0x1F013]={
+ category="so",
+ description="MAHJONG TILE FOUR OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F013,
+ },
+ [0x1F014]={
+ category="so",
+ description="MAHJONG TILE FIVE OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F014,
+ },
+ [0x1F015]={
+ category="so",
+ description="MAHJONG TILE SIX OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F015,
+ },
+ [0x1F016]={
+ category="so",
+ description="MAHJONG TILE SEVEN OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F016,
+ },
+ [0x1F017]={
+ category="so",
+ description="MAHJONG TILE EIGHT OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F017,
+ },
+ [0x1F018]={
+ category="so",
+ description="MAHJONG TILE NINE OF BAMBOOS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F018,
+ },
+ [0x1F019]={
+ category="so",
+ description="MAHJONG TILE ONE OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F019,
+ },
+ [0x1F01A]={
+ category="so",
+ description="MAHJONG TILE TWO OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F01A,
+ },
+ [0x1F01B]={
+ category="so",
+ description="MAHJONG TILE THREE OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F01B,
+ },
+ [0x1F01C]={
+ category="so",
+ description="MAHJONG TILE FOUR OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F01C,
+ },
+ [0x1F01D]={
+ category="so",
+ description="MAHJONG TILE FIVE OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F01D,
+ },
+ [0x1F01E]={
+ category="so",
+ description="MAHJONG TILE SIX OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F01E,
+ },
+ [0x1F01F]={
+ category="so",
+ description="MAHJONG TILE SEVEN OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F01F,
+ },
+ [0x1F020]={
+ category="so",
+ description="MAHJONG TILE EIGHT OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F020,
+ },
+ [0x1F021]={
+ category="so",
+ description="MAHJONG TILE NINE OF CIRCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F021,
+ },
+ [0x1F022]={
+ category="so",
+ description="MAHJONG TILE PLUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F022,
+ },
+ [0x1F023]={
+ category="so",
+ description="MAHJONG TILE ORCHID",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F023,
+ },
+ [0x1F024]={
+ category="so",
+ description="MAHJONG TILE BAMBOO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F024,
+ },
+ [0x1F025]={
+ category="so",
+ description="MAHJONG TILE CHRYSANTHEMUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F025,
+ },
+ [0x1F026]={
+ category="so",
+ description="MAHJONG TILE SPRING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F026,
+ },
+ [0x1F027]={
+ category="so",
+ description="MAHJONG TILE SUMMER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F027,
+ },
+ [0x1F028]={
+ category="so",
+ description="MAHJONG TILE AUTUMN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F028,
+ },
+ [0x1F029]={
+ category="so",
+ description="MAHJONG TILE WINTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F029,
+ },
+ [0x1F02A]={
+ category="so",
+ description="MAHJONG TILE JOKER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F02A,
+ },
+ [0x1F02B]={
+ category="so",
+ description="MAHJONG TILE BACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F02B,
+ },
+ [0x1F030]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL BACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F030,
+ },
+ [0x1F031]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F031,
+ },
+ [0x1F032]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F032,
+ },
+ [0x1F033]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F033,
+ },
+ [0x1F034]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F034,
+ },
+ [0x1F035]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F035,
+ },
+ [0x1F036]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F036,
+ },
+ [0x1F037]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-00-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F037,
+ },
+ [0x1F038]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F038,
+ },
+ [0x1F039]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F039,
+ },
+ [0x1F03A]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F03A,
+ },
+ [0x1F03B]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F03B,
+ },
+ [0x1F03C]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F03C,
+ },
+ [0x1F03D]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F03D,
+ },
+ [0x1F03E]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-01-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F03E,
+ },
+ [0x1F03F]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F03F,
+ },
+ [0x1F040]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F040,
+ },
+ [0x1F041]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F041,
+ },
+ [0x1F042]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F042,
+ },
+ [0x1F043]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F043,
+ },
+ [0x1F044]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F044,
+ },
+ [0x1F045]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-02-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F045,
+ },
+ [0x1F046]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F046,
+ },
+ [0x1F047]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F047,
+ },
+ [0x1F048]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F048,
+ },
+ [0x1F049]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F049,
+ },
+ [0x1F04A]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F04A,
+ },
+ [0x1F04B]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F04B,
+ },
+ [0x1F04C]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-03-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F04C,
+ },
+ [0x1F04D]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F04D,
+ },
+ [0x1F04E]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F04E,
+ },
+ [0x1F04F]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F04F,
+ },
+ [0x1F050]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F050,
+ },
+ [0x1F051]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F051,
+ },
+ [0x1F052]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F052,
+ },
+ [0x1F053]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-04-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F053,
+ },
+ [0x1F054]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F054,
+ },
+ [0x1F055]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F055,
+ },
+ [0x1F056]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F056,
+ },
+ [0x1F057]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F057,
+ },
+ [0x1F058]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F058,
+ },
+ [0x1F059]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F059,
+ },
+ [0x1F05A]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-05-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F05A,
+ },
+ [0x1F05B]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F05B,
+ },
+ [0x1F05C]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F05C,
+ },
+ [0x1F05D]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F05D,
+ },
+ [0x1F05E]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F05E,
+ },
+ [0x1F05F]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F05F,
+ },
+ [0x1F060]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F060,
+ },
+ [0x1F061]={
+ category="so",
+ description="DOMINO TILE HORIZONTAL-06-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F061,
+ },
+ [0x1F062]={
+ category="so",
+ description="DOMINO TILE VERTICAL BACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F062,
+ },
+ [0x1F063]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F063,
+ },
+ [0x1F064]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F064,
+ },
+ [0x1F065]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F065,
+ },
+ [0x1F066]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F066,
+ },
+ [0x1F067]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F067,
+ },
+ [0x1F068]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F068,
+ },
+ [0x1F069]={
+ category="so",
+ description="DOMINO TILE VERTICAL-00-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F069,
+ },
+ [0x1F06A]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F06A,
+ },
+ [0x1F06B]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F06B,
+ },
+ [0x1F06C]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F06C,
+ },
+ [0x1F06D]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F06D,
+ },
+ [0x1F06E]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F06E,
+ },
+ [0x1F06F]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F06F,
+ },
+ [0x1F070]={
+ category="so",
+ description="DOMINO TILE VERTICAL-01-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F070,
+ },
+ [0x1F071]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F071,
+ },
+ [0x1F072]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F072,
+ },
+ [0x1F073]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F073,
+ },
+ [0x1F074]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F074,
+ },
+ [0x1F075]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F075,
+ },
+ [0x1F076]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F076,
+ },
+ [0x1F077]={
+ category="so",
+ description="DOMINO TILE VERTICAL-02-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F077,
+ },
+ [0x1F078]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F078,
+ },
+ [0x1F079]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F079,
+ },
+ [0x1F07A]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F07A,
+ },
+ [0x1F07B]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F07B,
+ },
+ [0x1F07C]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F07C,
+ },
+ [0x1F07D]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F07D,
+ },
+ [0x1F07E]={
+ category="so",
+ description="DOMINO TILE VERTICAL-03-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F07E,
+ },
+ [0x1F07F]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F07F,
+ },
+ [0x1F080]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F080,
+ },
+ [0x1F081]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F081,
+ },
+ [0x1F082]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F082,
+ },
+ [0x1F083]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F083,
+ },
+ [0x1F084]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F084,
+ },
+ [0x1F085]={
+ category="so",
+ description="DOMINO TILE VERTICAL-04-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F085,
+ },
+ [0x1F086]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F086,
+ },
+ [0x1F087]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F087,
+ },
+ [0x1F088]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F088,
+ },
+ [0x1F089]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F089,
+ },
+ [0x1F08A]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F08A,
+ },
+ [0x1F08B]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F08B,
+ },
+ [0x1F08C]={
+ category="so",
+ description="DOMINO TILE VERTICAL-05-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F08C,
+ },
+ [0x1F08D]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-00",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F08D,
+ },
+ [0x1F08E]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-01",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F08E,
+ },
+ [0x1F08F]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-02",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F08F,
+ },
+ [0x1F090]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-03",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F090,
+ },
+ [0x1F091]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-04",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F091,
+ },
+ [0x1F092]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-05",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F092,
+ },
+ [0x1F093]={
+ category="so",
+ description="DOMINO TILE VERTICAL-06-06",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F093,
+ },
+ [0x1F0A0]={
+ category="so",
+ description="PLAYING CARD BACK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A0,
+ },
+ [0x1F0A1]={
+ category="so",
+ description="PLAYING CARD ACE OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A1,
+ },
+ [0x1F0A2]={
+ category="so",
+ description="PLAYING CARD TWO OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A2,
+ },
+ [0x1F0A3]={
+ category="so",
+ description="PLAYING CARD THREE OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A3,
+ },
+ [0x1F0A4]={
+ category="so",
+ description="PLAYING CARD FOUR OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A4,
+ },
+ [0x1F0A5]={
+ category="so",
+ description="PLAYING CARD FIVE OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A5,
+ },
+ [0x1F0A6]={
+ category="so",
+ description="PLAYING CARD SIX OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A6,
+ },
+ [0x1F0A7]={
+ category="so",
+ description="PLAYING CARD SEVEN OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A7,
+ },
+ [0x1F0A8]={
+ category="so",
+ description="PLAYING CARD EIGHT OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A8,
+ },
+ [0x1F0A9]={
+ category="so",
+ description="PLAYING CARD NINE OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0A9,
+ },
+ [0x1F0AA]={
+ category="so",
+ description="PLAYING CARD TEN OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0AA,
+ },
+ [0x1F0AB]={
+ category="so",
+ description="PLAYING CARD JACK OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0AB,
+ },
+ [0x1F0AC]={
+ category="so",
+ description="PLAYING CARD KNIGHT OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0AC,
+ },
+ [0x1F0AD]={
+ category="so",
+ description="PLAYING CARD QUEEN OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0AD,
+ },
+ [0x1F0AE]={
+ category="so",
+ description="PLAYING CARD KING OF SPADES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0AE,
+ },
+ [0x1F0B1]={
+ category="so",
+ description="PLAYING CARD ACE OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B1,
+ },
+ [0x1F0B2]={
+ category="so",
+ description="PLAYING CARD TWO OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B2,
+ },
+ [0x1F0B3]={
+ category="so",
+ description="PLAYING CARD THREE OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B3,
+ },
+ [0x1F0B4]={
+ category="so",
+ description="PLAYING CARD FOUR OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B4,
+ },
+ [0x1F0B5]={
+ category="so",
+ description="PLAYING CARD FIVE OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B5,
+ },
+ [0x1F0B6]={
+ category="so",
+ description="PLAYING CARD SIX OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B6,
+ },
+ [0x1F0B7]={
+ category="so",
+ description="PLAYING CARD SEVEN OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B7,
+ },
+ [0x1F0B8]={
+ category="so",
+ description="PLAYING CARD EIGHT OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B8,
+ },
+ [0x1F0B9]={
+ category="so",
+ description="PLAYING CARD NINE OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0B9,
+ },
+ [0x1F0BA]={
+ category="so",
+ description="PLAYING CARD TEN OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0BA,
+ },
+ [0x1F0BB]={
+ category="so",
+ description="PLAYING CARD JACK OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0BB,
+ },
+ [0x1F0BC]={
+ category="so",
+ description="PLAYING CARD KNIGHT OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0BC,
+ },
+ [0x1F0BD]={
+ category="so",
+ description="PLAYING CARD QUEEN OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0BD,
+ },
+ [0x1F0BE]={
+ category="so",
+ description="PLAYING CARD KING OF HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0BE,
+ },
+ [0x1F0C1]={
+ category="so",
+ description="PLAYING CARD ACE OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C1,
+ },
+ [0x1F0C2]={
+ category="so",
+ description="PLAYING CARD TWO OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C2,
+ },
+ [0x1F0C3]={
+ category="so",
+ description="PLAYING CARD THREE OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C3,
+ },
+ [0x1F0C4]={
+ category="so",
+ description="PLAYING CARD FOUR OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C4,
+ },
+ [0x1F0C5]={
+ category="so",
+ description="PLAYING CARD FIVE OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C5,
+ },
+ [0x1F0C6]={
+ category="so",
+ description="PLAYING CARD SIX OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C6,
+ },
+ [0x1F0C7]={
+ category="so",
+ description="PLAYING CARD SEVEN OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C7,
+ },
+ [0x1F0C8]={
+ category="so",
+ description="PLAYING CARD EIGHT OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C8,
+ },
+ [0x1F0C9]={
+ category="so",
+ description="PLAYING CARD NINE OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0C9,
+ },
+ [0x1F0CA]={
+ category="so",
+ description="PLAYING CARD TEN OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0CA,
+ },
+ [0x1F0CB]={
+ category="so",
+ description="PLAYING CARD JACK OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0CB,
+ },
+ [0x1F0CC]={
+ category="so",
+ description="PLAYING CARD KNIGHT OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0CC,
+ },
+ [0x1F0CD]={
+ category="so",
+ description="PLAYING CARD QUEEN OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0CD,
+ },
+ [0x1F0CE]={
+ category="so",
+ description="PLAYING CARD KING OF DIAMONDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0CE,
+ },
+ [0x1F0CF]={
+ category="so",
+ description="PLAYING CARD BLACK JOKER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0CF,
+ },
+ [0x1F0D1]={
+ category="so",
+ description="PLAYING CARD ACE OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D1,
+ },
+ [0x1F0D2]={
+ category="so",
+ description="PLAYING CARD TWO OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D2,
+ },
+ [0x1F0D3]={
+ category="so",
+ description="PLAYING CARD THREE OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D3,
+ },
+ [0x1F0D4]={
+ category="so",
+ description="PLAYING CARD FOUR OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D4,
+ },
+ [0x1F0D5]={
+ category="so",
+ description="PLAYING CARD FIVE OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D5,
+ },
+ [0x1F0D6]={
+ category="so",
+ description="PLAYING CARD SIX OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D6,
+ },
+ [0x1F0D7]={
+ category="so",
+ description="PLAYING CARD SEVEN OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D7,
+ },
+ [0x1F0D8]={
+ category="so",
+ description="PLAYING CARD EIGHT OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D8,
+ },
+ [0x1F0D9]={
+ category="so",
+ description="PLAYING CARD NINE OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0D9,
+ },
+ [0x1F0DA]={
+ category="so",
+ description="PLAYING CARD TEN OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0DA,
+ },
+ [0x1F0DB]={
+ category="so",
+ description="PLAYING CARD JACK OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0DB,
+ },
+ [0x1F0DC]={
+ category="so",
+ description="PLAYING CARD KNIGHT OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0DC,
+ },
+ [0x1F0DD]={
+ category="so",
+ description="PLAYING CARD QUEEN OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0DD,
+ },
+ [0x1F0DE]={
+ category="so",
+ description="PLAYING CARD KING OF CLUBS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0DE,
+ },
+ [0x1F0DF]={
+ category="so",
+ description="PLAYING CARD WHITE JOKER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F0DF,
+ },
+ [0x1F100]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT ZERO FULL STOP",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0030, 0x002E },
+ unicodeslot=0x1F100,
+ },
+ [0x1F101]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT ZERO COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0030, 0x002C },
+ unicodeslot=0x1F101,
+ },
+ [0x1F102]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT ONE COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0031, 0x002C },
+ unicodeslot=0x1F102,
+ },
+ [0x1F103]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT TWO COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0032, 0x002C },
+ unicodeslot=0x1F103,
+ },
+ [0x1F104]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT THREE COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0033, 0x002C },
+ unicodeslot=0x1F104,
+ },
+ [0x1F105]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT FOUR COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0034, 0x002C },
+ unicodeslot=0x1F105,
+ },
+ [0x1F106]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT FIVE COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0035, 0x002C },
+ unicodeslot=0x1F106,
+ },
+ [0x1F107]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT SIX COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0036, 0x002C },
+ unicodeslot=0x1F107,
+ },
+ [0x1F108]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT SEVEN COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0037, 0x002C },
+ unicodeslot=0x1F108,
+ },
+ [0x1F109]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT EIGHT COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0038, 0x002C },
+ unicodeslot=0x1F109,
+ },
+ [0x1F10A]={
+ category="no",
+ cjkwd="a",
+ description="DIGIT NINE COMMA",
+ direction="en",
+ linebreak="ai",
+ specials={ "compat", 0x0039, 0x002C },
+ unicodeslot=0x1F10A,
+ },
+ [0x1F110]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0041, 0x0029 },
+ unicodeslot=0x1F110,
+ },
+ [0x1F111]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0042, 0x0029 },
+ unicodeslot=0x1F111,
+ },
+ [0x1F112]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0043, 0x0029 },
+ unicodeslot=0x1F112,
+ },
+ [0x1F113]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0044, 0x0029 },
+ unicodeslot=0x1F113,
+ },
+ [0x1F114]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0045, 0x0029 },
+ unicodeslot=0x1F114,
+ },
+ [0x1F115]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0046, 0x0029 },
+ unicodeslot=0x1F115,
+ },
+ [0x1F116]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0047, 0x0029 },
+ unicodeslot=0x1F116,
+ },
+ [0x1F117]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER H",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0048, 0x0029 },
+ unicodeslot=0x1F117,
+ },
+ [0x1F118]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0049, 0x0029 },
+ unicodeslot=0x1F118,
+ },
+ [0x1F119]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x004A, 0x0029 },
+ unicodeslot=0x1F119,
+ },
+ [0x1F11A]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x004B, 0x0029 },
+ unicodeslot=0x1F11A,
+ },
+ [0x1F11B]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x004C, 0x0029 },
+ unicodeslot=0x1F11B,
+ },
+ [0x1F11C]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x004D, 0x0029 },
+ unicodeslot=0x1F11C,
+ },
+ [0x1F11D]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x004E, 0x0029 },
+ unicodeslot=0x1F11D,
+ },
+ [0x1F11E]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x004F, 0x0029 },
+ unicodeslot=0x1F11E,
+ },
+ [0x1F11F]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0050, 0x0029 },
+ unicodeslot=0x1F11F,
+ },
+ [0x1F120]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0051, 0x0029 },
+ unicodeslot=0x1F120,
+ },
+ [0x1F121]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0052, 0x0029 },
+ unicodeslot=0x1F121,
+ },
+ [0x1F122]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0053, 0x0029 },
+ unicodeslot=0x1F122,
+ },
+ [0x1F123]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0054, 0x0029 },
+ unicodeslot=0x1F123,
+ },
+ [0x1F124]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0055, 0x0029 },
+ unicodeslot=0x1F124,
+ },
+ [0x1F125]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0056, 0x0029 },
+ unicodeslot=0x1F125,
+ },
+ [0x1F126]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0057, 0x0029 },
+ unicodeslot=0x1F126,
+ },
+ [0x1F127]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0058, 0x0029 },
+ unicodeslot=0x1F127,
+ },
+ [0x1F128]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x0059, 0x0029 },
+ unicodeslot=0x1F128,
+ },
+ [0x1F129]={
+ category="so",
+ cjkwd="a",
+ description="PARENTHESIZED LATIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x0028, 0x005A, 0x0029 },
+ unicodeslot=0x1F129,
+ },
+ [0x1F12A]={
+ category="so",
+ cjkwd="a",
+ description="TORTOISE SHELL BRACKETED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ specials={ "compat", 0x3014, 0x0053, 0x3015 },
+ unicodeslot=0x1F12A,
+ },
+ [0x1F12B]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED ITALIC LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x0043 },
+ unicodeslot=0x1F12B,
+ },
+ [0x1F12C]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED ITALIC LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x0052 },
+ unicodeslot=0x1F12C,
+ },
+ [0x1F12D]={
+ category="so",
+ cjkwd="a",
+ description="CIRCLED CD",
+ direction="l",
+ linebreak="ai",
+ specials={ "circle", 0x0043, 0x0044 },
+ unicodeslot=0x1F12D,
+ },
+ [0x1F12E]={
+ category="so",
+ description="CIRCLED WZ",
+ direction="l",
+ linebreak="al",
+ specials={ "circle", 0x0057, 0x005A },
+ unicodeslot=0x1F12E,
+ },
+ [0x1F130]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0041 },
+ unicodeslot=0x1F130,
+ },
+ [0x1F131]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0042 },
+ unicodeslot=0x1F131,
+ },
+ [0x1F132]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0043 },
+ unicodeslot=0x1F132,
+ },
+ [0x1F133]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0044 },
+ unicodeslot=0x1F133,
+ },
+ [0x1F134]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0045 },
+ unicodeslot=0x1F134,
+ },
+ [0x1F135]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0046 },
+ unicodeslot=0x1F135,
+ },
+ [0x1F136]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0047 },
+ unicodeslot=0x1F136,
+ },
+ [0x1F137]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER H",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0048 },
+ unicodeslot=0x1F137,
+ },
+ [0x1F138]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0049 },
+ unicodeslot=0x1F138,
+ },
+ [0x1F139]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x004A },
+ unicodeslot=0x1F139,
+ },
+ [0x1F13A]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x004B },
+ unicodeslot=0x1F13A,
+ },
+ [0x1F13B]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x004C },
+ unicodeslot=0x1F13B,
+ },
+ [0x1F13C]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x004D },
+ unicodeslot=0x1F13C,
+ },
+ [0x1F13D]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x004E },
+ unicodeslot=0x1F13D,
+ },
+ [0x1F13E]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x004F },
+ unicodeslot=0x1F13E,
+ },
+ [0x1F13F]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0050 },
+ unicodeslot=0x1F13F,
+ },
+ [0x1F140]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0051 },
+ unicodeslot=0x1F140,
+ },
+ [0x1F141]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0052 },
+ unicodeslot=0x1F141,
+ },
+ [0x1F142]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0053 },
+ unicodeslot=0x1F142,
+ },
+ [0x1F143]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0054 },
+ unicodeslot=0x1F143,
+ },
+ [0x1F144]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0055 },
+ unicodeslot=0x1F144,
+ },
+ [0x1F145]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0056 },
+ unicodeslot=0x1F145,
+ },
+ [0x1F146]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0057 },
+ unicodeslot=0x1F146,
+ },
+ [0x1F147]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0058 },
+ unicodeslot=0x1F147,
+ },
+ [0x1F148]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0059 },
+ unicodeslot=0x1F148,
+ },
+ [0x1F149]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED LATIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x005A },
+ unicodeslot=0x1F149,
+ },
+ [0x1F14A]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED HV",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0048, 0x0056 },
+ unicodeslot=0x1F14A,
+ },
+ [0x1F14B]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED MV",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x004D, 0x0056 },
+ unicodeslot=0x1F14B,
+ },
+ [0x1F14C]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED SD",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0053, 0x0044 },
+ unicodeslot=0x1F14C,
+ },
+ [0x1F14D]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED SS",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0053, 0x0053 },
+ unicodeslot=0x1F14D,
+ },
+ [0x1F14E]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED PPV",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0050, 0x0050, 0x0056 },
+ unicodeslot=0x1F14E,
+ },
+ [0x1F14F]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED WC",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0057, 0x0043 },
+ unicodeslot=0x1F14F,
+ },
+ [0x1F150]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F150,
+ },
+ [0x1F151]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F151,
+ },
+ [0x1F152]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F152,
+ },
+ [0x1F153]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F153,
+ },
+ [0x1F154]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F154,
+ },
+ [0x1F155]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F155,
+ },
+ [0x1F156]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F156,
+ },
+ [0x1F157]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER H",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F157,
+ },
+ [0x1F158]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F158,
+ },
+ [0x1F159]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F159,
+ },
+ [0x1F15A]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15A,
+ },
+ [0x1F15B]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15B,
+ },
+ [0x1F15C]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15C,
+ },
+ [0x1F15D]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15D,
+ },
+ [0x1F15E]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15E,
+ },
+ [0x1F15F]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F15F,
+ },
+ [0x1F160]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F160,
+ },
+ [0x1F161]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F161,
+ },
+ [0x1F162]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F162,
+ },
+ [0x1F163]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F163,
+ },
+ [0x1F164]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F164,
+ },
+ [0x1F165]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F165,
+ },
+ [0x1F166]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F166,
+ },
+ [0x1F167]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F167,
+ },
+ [0x1F168]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F168,
+ },
+ [0x1F169]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE CIRCLED LATIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F169,
+ },
+ [0x1F170]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER A",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F170,
+ },
+ [0x1F171]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER B",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F171,
+ },
+ [0x1F172]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER C",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F172,
+ },
+ [0x1F173]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER D",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F173,
+ },
+ [0x1F174]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER E",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F174,
+ },
+ [0x1F175]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER F",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F175,
+ },
+ [0x1F176]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER G",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F176,
+ },
+ [0x1F177]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER H",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F177,
+ },
+ [0x1F178]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER I",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F178,
+ },
+ [0x1F179]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER J",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F179,
+ },
+ [0x1F17A]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER K",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17A,
+ },
+ [0x1F17B]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER L",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17B,
+ },
+ [0x1F17C]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER M",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17C,
+ },
+ [0x1F17D]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER N",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17D,
+ },
+ [0x1F17E]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER O",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17E,
+ },
+ [0x1F17F]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F17F,
+ },
+ [0x1F180]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER Q",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F180,
+ },
+ [0x1F181]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER R",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F181,
+ },
+ [0x1F182]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER S",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F182,
+ },
+ [0x1F183]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER T",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F183,
+ },
+ [0x1F184]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER U",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F184,
+ },
+ [0x1F185]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER V",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F185,
+ },
+ [0x1F186]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER W",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F186,
+ },
+ [0x1F187]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER X",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F187,
+ },
+ [0x1F188]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER Y",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F188,
+ },
+ [0x1F189]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED LATIN CAPITAL LETTER Z",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F189,
+ },
+ [0x1F18A]={
+ category="so",
+ cjkwd="a",
+ description="CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18A,
+ },
+ [0x1F18B]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED IC",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18B,
+ },
+ [0x1F18C]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED PA",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18C,
+ },
+ [0x1F18D]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED SA",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18D,
+ },
+ [0x1F18E]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED AB",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18E,
+ },
+ [0x1F18F]={
+ category="so",
+ cjkwd="a",
+ description="NEGATIVE SQUARED WC",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F18F,
+ },
+ [0x1F190]={
+ category="so",
+ cjkwd="a",
+ description="SQUARE DJ",
+ direction="l",
+ linebreak="ai",
+ specials={ "square", 0x0044, 0x004A },
+ unicodeslot=0x1F190,
+ },
+ [0x1F191]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED CL",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F191,
+ },
+ [0x1F192]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED COOL",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F192,
+ },
+ [0x1F193]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED FREE",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F193,
+ },
+ [0x1F194]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED ID",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F194,
+ },
+ [0x1F195]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED NEW",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F195,
+ },
+ [0x1F196]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED NG",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F196,
+ },
+ [0x1F197]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED OK",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F197,
+ },
+ [0x1F198]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED SOS",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F198,
+ },
+ [0x1F199]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED UP WITH EXCLAMATION MARK",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F199,
+ },
+ [0x1F19A]={
+ category="so",
+ cjkwd="a",
+ description="SQUARED VS",
+ direction="l",
+ linebreak="ai",
+ unicodeslot=0x1F19A,
+ },
+ [0x1F1E6]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER A",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1E6,
+ },
+ [0x1F1E7]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER B",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1E7,
+ },
+ [0x1F1E8]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER C",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1E8,
+ },
+ [0x1F1E9]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER D",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1E9,
+ },
+ [0x1F1EA]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER E",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1EA,
+ },
+ [0x1F1EB]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER F",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1EB,
+ },
+ [0x1F1EC]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER G",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1EC,
+ },
+ [0x1F1ED]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER H",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1ED,
+ },
+ [0x1F1EE]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER I",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1EE,
+ },
+ [0x1F1EF]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER J",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1EF,
+ },
+ [0x1F1F0]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER K",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F0,
+ },
+ [0x1F1F1]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER L",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F1,
+ },
+ [0x1F1F2]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER M",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F2,
+ },
+ [0x1F1F3]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER N",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F3,
+ },
+ [0x1F1F4]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER O",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F4,
+ },
+ [0x1F1F5]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER P",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F5,
+ },
+ [0x1F1F6]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER Q",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F6,
+ },
+ [0x1F1F7]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER R",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F7,
+ },
+ [0x1F1F8]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER S",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F8,
+ },
+ [0x1F1F9]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER T",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1F9,
+ },
+ [0x1F1FA]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER U",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1FA,
+ },
+ [0x1F1FB]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER V",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1FB,
+ },
+ [0x1F1FC]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER W",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1FC,
+ },
+ [0x1F1FD]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER X",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1FD,
+ },
+ [0x1F1FE]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER Y",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1FE,
+ },
+ [0x1F1FF]={
+ category="so",
+ description="REGIONAL INDICATOR SYMBOL LETTER Z",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F1FF,
+ },
+ [0x1F200]={
+ category="so",
+ cjkwd="w",
+ description="SQUARE HIRAGANA HOKA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x307B, 0x304B },
+ unicodeslot=0x1F200,
+ },
+ [0x1F201]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED KATAKANA KOKO",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B3, 0x30B3 },
+ unicodeslot=0x1F201,
+ },
+ [0x1F202]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED KATAKANA SA",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30B5 },
+ unicodeslot=0x1F202,
+ },
+ [0x1F210]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-624B",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x624B },
+ unicodeslot=0x1F210,
+ },
+ [0x1F211]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5B57",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5B57 },
+ unicodeslot=0x1F211,
+ },
+ [0x1F212]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-53CC",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x53CC },
+ unicodeslot=0x1F212,
+ },
+ [0x1F213]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED KATAKANA DE",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x30C7 },
+ unicodeslot=0x1F213,
+ },
+ [0x1F214]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4E8C",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4E8C },
+ unicodeslot=0x1F214,
+ },
+ [0x1F215]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-591A",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x591A },
+ unicodeslot=0x1F215,
+ },
+ [0x1F216]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-89E3",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x89E3 },
+ unicodeslot=0x1F216,
+ },
+ [0x1F217]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5929",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5929 },
+ unicodeslot=0x1F217,
+ },
+ [0x1F218]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4EA4",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4EA4 },
+ unicodeslot=0x1F218,
+ },
+ [0x1F219]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6620",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6620 },
+ unicodeslot=0x1F219,
+ },
+ [0x1F21A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7121",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7121 },
+ unicodeslot=0x1F21A,
+ },
+ [0x1F21B]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6599",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6599 },
+ unicodeslot=0x1F21B,
+ },
+ [0x1F21C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-524D",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x524D },
+ unicodeslot=0x1F21C,
+ },
+ [0x1F21D]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5F8C",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5F8C },
+ unicodeslot=0x1F21D,
+ },
+ [0x1F21E]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-518D",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x518D },
+ unicodeslot=0x1F21E,
+ },
+ [0x1F21F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-65B0",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x65B0 },
+ unicodeslot=0x1F21F,
+ },
+ [0x1F220]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-521D",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x521D },
+ unicodeslot=0x1F220,
+ },
+ [0x1F221]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7D42",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7D42 },
+ unicodeslot=0x1F221,
+ },
+ [0x1F222]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-751F",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x751F },
+ unicodeslot=0x1F222,
+ },
+ [0x1F223]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-8CA9",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x8CA9 },
+ unicodeslot=0x1F223,
+ },
+ [0x1F224]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-58F0",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x58F0 },
+ unicodeslot=0x1F224,
+ },
+ [0x1F225]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5439",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5439 },
+ unicodeslot=0x1F225,
+ },
+ [0x1F226]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6F14",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6F14 },
+ unicodeslot=0x1F226,
+ },
+ [0x1F227]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6295",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6295 },
+ unicodeslot=0x1F227,
+ },
+ [0x1F228]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6355",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6355 },
+ unicodeslot=0x1F228,
+ },
+ [0x1F229]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4E00",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4E00 },
+ unicodeslot=0x1F229,
+ },
+ [0x1F22A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4E09",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4E09 },
+ unicodeslot=0x1F22A,
+ },
+ [0x1F22B]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-904A",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x904A },
+ unicodeslot=0x1F22B,
+ },
+ [0x1F22C]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5DE6",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5DE6 },
+ unicodeslot=0x1F22C,
+ },
+ [0x1F22D]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-4E2D",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x4E2D },
+ unicodeslot=0x1F22D,
+ },
+ [0x1F22E]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-53F3",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x53F3 },
+ unicodeslot=0x1F22E,
+ },
+ [0x1F22F]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6307",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6307 },
+ unicodeslot=0x1F22F,
+ },
+ [0x1F230]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-8D70",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x8D70 },
+ unicodeslot=0x1F230,
+ },
+ [0x1F231]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6253",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6253 },
+ unicodeslot=0x1F231,
+ },
+ [0x1F232]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7981",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7981 },
+ unicodeslot=0x1F232,
+ },
+ [0x1F233]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7A7A",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7A7A },
+ unicodeslot=0x1F233,
+ },
+ [0x1F234]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5408",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5408 },
+ unicodeslot=0x1F234,
+ },
+ [0x1F235]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6E80",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6E80 },
+ unicodeslot=0x1F235,
+ },
+ [0x1F236]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6709",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6709 },
+ unicodeslot=0x1F236,
+ },
+ [0x1F237]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-6708",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x6708 },
+ unicodeslot=0x1F237,
+ },
+ [0x1F238]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-7533",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x7533 },
+ unicodeslot=0x1F238,
+ },
+ [0x1F239]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-5272",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x5272 },
+ unicodeslot=0x1F239,
+ },
+ [0x1F23A]={
+ category="so",
+ cjkwd="w",
+ description="SQUARED CJK UNIFIED IDEOGRAPH-55B6",
+ direction="l",
+ linebreak="id",
+ specials={ "square", 0x55B6 },
+ unicodeslot=0x1F23A,
+ },
+ [0x1F240]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x672C, 0x3015 },
+ unicodeslot=0x1F240,
+ },
+ [0x1F241]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x4E09, 0x3015 },
+ unicodeslot=0x1F241,
+ },
+ [0x1F242]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x4E8C, 0x3015 },
+ unicodeslot=0x1F242,
+ },
+ [0x1F243]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-5B89",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x5B89, 0x3015 },
+ unicodeslot=0x1F243,
+ },
+ [0x1F244]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-70B9",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x70B9, 0x3015 },
+ unicodeslot=0x1F244,
+ },
+ [0x1F245]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6253",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x6253, 0x3015 },
+ unicodeslot=0x1F245,
+ },
+ [0x1F246]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x76D7, 0x3015 },
+ unicodeslot=0x1F246,
+ },
+ [0x1F247]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x52DD, 0x3015 },
+ unicodeslot=0x1F247,
+ },
+ [0x1F248]={
+ category="so",
+ cjkwd="w",
+ description="TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557",
+ direction="l",
+ linebreak="id",
+ specials={ "compat", 0x3014, 0x6557, 0x3015 },
+ unicodeslot=0x1F248,
+ },
+ [0x1F250]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ADVANTAGE",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x5F97 },
+ unicodeslot=0x1F250,
+ },
+ [0x1F251]={
+ category="so",
+ cjkwd="w",
+ description="CIRCLED IDEOGRAPH ACCEPT",
+ direction="l",
+ linebreak="id",
+ specials={ "circle", 0x53EF },
+ unicodeslot=0x1F251,
+ },
+ [0x1F300]={
+ category="so",
+ description="CYCLONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F300,
+ },
+ [0x1F301]={
+ category="so",
+ description="FOGGY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F301,
+ },
+ [0x1F302]={
+ category="so",
+ description="CLOSED UMBRELLA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F302,
+ },
+ [0x1F303]={
+ category="so",
+ description="NIGHT WITH STARS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F303,
+ },
+ [0x1F304]={
+ category="so",
+ description="SUNRISE OVER MOUNTAINS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F304,
+ },
+ [0x1F305]={
+ category="so",
+ description="SUNRISE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F305,
+ },
+ [0x1F306]={
+ category="so",
+ description="CITYSCAPE AT DUSK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F306,
+ },
+ [0x1F307]={
+ category="so",
+ description="SUNSET OVER BUILDINGS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F307,
+ },
+ [0x1F308]={
+ category="so",
+ description="RAINBOW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F308,
+ },
+ [0x1F309]={
+ category="so",
+ description="BRIDGE AT NIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F309,
+ },
+ [0x1F30A]={
+ category="so",
+ description="WATER WAVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F30A,
+ },
+ [0x1F30B]={
+ category="so",
+ description="VOLCANO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F30B,
+ },
+ [0x1F30C]={
+ category="so",
+ description="MILKY WAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F30C,
+ },
+ [0x1F30D]={
+ category="so",
+ description="EARTH GLOBE EUROPE-AFRICA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F30D,
+ },
+ [0x1F30E]={
+ category="so",
+ description="EARTH GLOBE AMERICAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F30E,
+ },
+ [0x1F30F]={
+ category="so",
+ description="EARTH GLOBE ASIA-AUSTRALIA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F30F,
+ },
+ [0x1F310]={
+ category="so",
+ description="GLOBE WITH MERIDIANS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F310,
+ },
+ [0x1F311]={
+ category="so",
+ description="NEW MOON SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F311,
+ },
+ [0x1F312]={
+ category="so",
+ description="WAXING CRESCENT MOON SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F312,
+ },
+ [0x1F313]={
+ category="so",
+ description="FIRST QUARTER MOON SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F313,
+ },
+ [0x1F314]={
+ category="so",
+ description="WAXING GIBBOUS MOON SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F314,
+ },
+ [0x1F315]={
+ category="so",
+ description="FULL MOON SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F315,
+ },
+ [0x1F316]={
+ category="so",
+ description="WANING GIBBOUS MOON SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F316,
+ },
+ [0x1F317]={
+ category="so",
+ description="LAST QUARTER MOON SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F317,
+ },
+ [0x1F318]={
+ category="so",
+ description="WANING CRESCENT MOON SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F318,
+ },
+ [0x1F319]={
+ category="so",
+ description="CRESCENT MOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F319,
+ },
+ [0x1F31A]={
+ category="so",
+ description="NEW MOON WITH FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F31A,
+ },
+ [0x1F31B]={
+ category="so",
+ description="FIRST QUARTER MOON WITH FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F31B,
+ },
+ [0x1F31C]={
+ category="so",
+ description="LAST QUARTER MOON WITH FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F31C,
+ },
+ [0x1F31D]={
+ category="so",
+ description="FULL MOON WITH FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F31D,
+ },
+ [0x1F31E]={
+ category="so",
+ description="SUN WITH FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F31E,
+ },
+ [0x1F31F]={
+ category="so",
+ description="GLOWING STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F31F,
+ },
+ [0x1F320]={
+ category="so",
+ description="SHOOTING STAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F320,
+ },
+ [0x1F330]={
+ category="so",
+ description="CHESTNUT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F330,
+ },
+ [0x1F331]={
+ category="so",
+ description="SEEDLING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F331,
+ },
+ [0x1F332]={
+ category="so",
+ description="EVERGREEN TREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F332,
+ },
+ [0x1F333]={
+ category="so",
+ description="DECIDUOUS TREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F333,
+ },
+ [0x1F334]={
+ category="so",
+ description="PALM TREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F334,
+ },
+ [0x1F335]={
+ category="so",
+ description="CACTUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F335,
+ },
+ [0x1F337]={
+ category="so",
+ description="TULIP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F337,
+ },
+ [0x1F338]={
+ category="so",
+ description="CHERRY BLOSSOM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F338,
+ },
+ [0x1F339]={
+ category="so",
+ description="ROSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F339,
+ },
+ [0x1F33A]={
+ category="so",
+ description="HIBISCUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F33A,
+ },
+ [0x1F33B]={
+ category="so",
+ description="SUNFLOWER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F33B,
+ },
+ [0x1F33C]={
+ category="so",
+ description="BLOSSOM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F33C,
+ },
+ [0x1F33D]={
+ category="so",
+ description="EAR OF MAIZE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F33D,
+ },
+ [0x1F33E]={
+ category="so",
+ description="EAR OF RICE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F33E,
+ },
+ [0x1F33F]={
+ category="so",
+ description="HERB",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F33F,
+ },
+ [0x1F340]={
+ category="so",
+ description="FOUR LEAF CLOVER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F340,
+ },
+ [0x1F341]={
+ category="so",
+ description="MAPLE LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F341,
+ },
+ [0x1F342]={
+ category="so",
+ description="FALLEN LEAF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F342,
+ },
+ [0x1F343]={
+ category="so",
+ description="LEAF FLUTTERING IN WIND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F343,
+ },
+ [0x1F344]={
+ category="so",
+ description="MUSHROOM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F344,
+ },
+ [0x1F345]={
+ category="so",
+ description="TOMATO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F345,
+ },
+ [0x1F346]={
+ category="so",
+ description="AUBERGINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F346,
+ },
+ [0x1F347]={
+ category="so",
+ description="GRAPES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F347,
+ },
+ [0x1F348]={
+ category="so",
+ description="MELON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F348,
+ },
+ [0x1F349]={
+ category="so",
+ description="WATERMELON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F349,
+ },
+ [0x1F34A]={
+ category="so",
+ description="TANGERINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F34A,
+ },
+ [0x1F34B]={
+ category="so",
+ description="LEMON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F34B,
+ },
+ [0x1F34C]={
+ category="so",
+ description="BANANA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F34C,
+ },
+ [0x1F34D]={
+ category="so",
+ description="PINEAPPLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F34D,
+ },
+ [0x1F34E]={
+ category="so",
+ description="RED APPLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F34E,
+ },
+ [0x1F34F]={
+ category="so",
+ description="GREEN APPLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F34F,
+ },
+ [0x1F350]={
+ category="so",
+ description="PEAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F350,
+ },
+ [0x1F351]={
+ category="so",
+ description="PEACH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F351,
+ },
+ [0x1F352]={
+ category="so",
+ description="CHERRIES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F352,
+ },
+ [0x1F353]={
+ category="so",
+ description="STRAWBERRY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F353,
+ },
+ [0x1F354]={
+ category="so",
+ description="HAMBURGER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F354,
+ },
+ [0x1F355]={
+ category="so",
+ description="SLICE OF PIZZA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F355,
+ },
+ [0x1F356]={
+ category="so",
+ description="MEAT ON BONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F356,
+ },
+ [0x1F357]={
+ category="so",
+ description="POULTRY LEG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F357,
+ },
+ [0x1F358]={
+ category="so",
+ description="RICE CRACKER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F358,
+ },
+ [0x1F359]={
+ category="so",
+ description="RICE BALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F359,
+ },
+ [0x1F35A]={
+ category="so",
+ description="COOKED RICE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F35A,
+ },
+ [0x1F35B]={
+ category="so",
+ description="CURRY AND RICE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F35B,
+ },
+ [0x1F35C]={
+ category="so",
+ description="STEAMING BOWL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F35C,
+ },
+ [0x1F35D]={
+ category="so",
+ description="SPAGHETTI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F35D,
+ },
+ [0x1F35E]={
+ category="so",
+ description="BREAD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F35E,
+ },
+ [0x1F35F]={
+ category="so",
+ description="FRENCH FRIES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F35F,
+ },
+ [0x1F360]={
+ category="so",
+ description="ROASTED SWEET POTATO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F360,
+ },
+ [0x1F361]={
+ category="so",
+ description="DANGO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F361,
+ },
+ [0x1F362]={
+ category="so",
+ description="ODEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F362,
+ },
+ [0x1F363]={
+ category="so",
+ description="SUSHI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F363,
+ },
+ [0x1F364]={
+ category="so",
+ description="FRIED SHRIMP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F364,
+ },
+ [0x1F365]={
+ category="so",
+ description="FISH CAKE WITH SWIRL DESIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F365,
+ },
+ [0x1F366]={
+ category="so",
+ description="SOFT ICE CREAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F366,
+ },
+ [0x1F367]={
+ category="so",
+ description="SHAVED ICE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F367,
+ },
+ [0x1F368]={
+ category="so",
+ description="ICE CREAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F368,
+ },
+ [0x1F369]={
+ category="so",
+ description="DOUGHNUT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F369,
+ },
+ [0x1F36A]={
+ category="so",
+ description="COOKIE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F36A,
+ },
+ [0x1F36B]={
+ category="so",
+ description="CHOCOLATE BAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F36B,
+ },
+ [0x1F36C]={
+ category="so",
+ description="CANDY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F36C,
+ },
+ [0x1F36D]={
+ category="so",
+ description="LOLLIPOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F36D,
+ },
+ [0x1F36E]={
+ category="so",
+ description="CUSTARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F36E,
+ },
+ [0x1F36F]={
+ category="so",
+ description="HONEY POT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F36F,
+ },
+ [0x1F370]={
+ category="so",
+ description="SHORTCAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F370,
+ },
+ [0x1F371]={
+ category="so",
+ description="BENTO BOX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F371,
+ },
+ [0x1F372]={
+ category="so",
+ description="POT OF FOOD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F372,
+ },
+ [0x1F373]={
+ category="so",
+ description="COOKING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F373,
+ },
+ [0x1F374]={
+ category="so",
+ description="FORK AND KNIFE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F374,
+ },
+ [0x1F375]={
+ category="so",
+ description="TEACUP WITHOUT HANDLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F375,
+ },
+ [0x1F376]={
+ category="so",
+ description="SAKE BOTTLE AND CUP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F376,
+ },
+ [0x1F377]={
+ category="so",
+ description="WINE GLASS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F377,
+ },
+ [0x1F378]={
+ category="so",
+ description="COCKTAIL GLASS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F378,
+ },
+ [0x1F379]={
+ category="so",
+ description="TROPICAL DRINK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F379,
+ },
+ [0x1F37A]={
+ category="so",
+ description="BEER MUG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F37A,
+ },
+ [0x1F37B]={
+ category="so",
+ description="CLINKING BEER MUGS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F37B,
+ },
+ [0x1F37C]={
+ category="so",
+ description="BABY BOTTLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F37C,
+ },
+ [0x1F380]={
+ category="so",
+ description="RIBBON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F380,
+ },
+ [0x1F381]={
+ category="so",
+ description="WRAPPED PRESENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F381,
+ },
+ [0x1F382]={
+ category="so",
+ description="BIRTHDAY CAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F382,
+ },
+ [0x1F383]={
+ category="so",
+ description="JACK-O-LANTERN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F383,
+ },
+ [0x1F384]={
+ category="so",
+ description="CHRISTMAS TREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F384,
+ },
+ [0x1F385]={
+ category="so",
+ description="FATHER CHRISTMAS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F385,
+ },
+ [0x1F386]={
+ category="so",
+ description="FIREWORKS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F386,
+ },
+ [0x1F387]={
+ category="so",
+ description="FIREWORK SPARKLER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F387,
+ },
+ [0x1F388]={
+ category="so",
+ description="BALLOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F388,
+ },
+ [0x1F389]={
+ category="so",
+ description="PARTY POPPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F389,
+ },
+ [0x1F38A]={
+ category="so",
+ description="CONFETTI BALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F38A,
+ },
+ [0x1F38B]={
+ category="so",
+ description="TANABATA TREE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F38B,
+ },
+ [0x1F38C]={
+ category="so",
+ description="CROSSED FLAGS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F38C,
+ },
+ [0x1F38D]={
+ category="so",
+ description="PINE DECORATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F38D,
+ },
+ [0x1F38E]={
+ category="so",
+ description="JAPANESE DOLLS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F38E,
+ },
+ [0x1F38F]={
+ category="so",
+ description="CARP STREAMER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F38F,
+ },
+ [0x1F390]={
+ category="so",
+ description="WIND CHIME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F390,
+ },
+ [0x1F391]={
+ category="so",
+ description="MOON VIEWING CEREMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F391,
+ },
+ [0x1F392]={
+ category="so",
+ description="SCHOOL SATCHEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F392,
+ },
+ [0x1F393]={
+ category="so",
+ description="GRADUATION CAP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F393,
+ },
+ [0x1F3A0]={
+ category="so",
+ description="CAROUSEL HORSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A0,
+ },
+ [0x1F3A1]={
+ category="so",
+ description="FERRIS WHEEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A1,
+ },
+ [0x1F3A2]={
+ category="so",
+ description="ROLLER COASTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A2,
+ },
+ [0x1F3A3]={
+ category="so",
+ description="FISHING POLE AND FISH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A3,
+ },
+ [0x1F3A4]={
+ category="so",
+ description="MICROPHONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A4,
+ },
+ [0x1F3A5]={
+ category="so",
+ description="MOVIE CAMERA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A5,
+ },
+ [0x1F3A6]={
+ category="so",
+ description="CINEMA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A6,
+ },
+ [0x1F3A7]={
+ category="so",
+ description="HEADPHONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A7,
+ },
+ [0x1F3A8]={
+ category="so",
+ description="ARTIST PALETTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A8,
+ },
+ [0x1F3A9]={
+ category="so",
+ description="TOP HAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3A9,
+ },
+ [0x1F3AA]={
+ category="so",
+ description="CIRCUS TENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3AA,
+ },
+ [0x1F3AB]={
+ category="so",
+ description="TICKET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3AB,
+ },
+ [0x1F3AC]={
+ category="so",
+ description="CLAPPER BOARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3AC,
+ },
+ [0x1F3AD]={
+ category="so",
+ description="PERFORMING ARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3AD,
+ },
+ [0x1F3AE]={
+ category="so",
+ description="VIDEO GAME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3AE,
+ },
+ [0x1F3AF]={
+ category="so",
+ description="DIRECT HIT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3AF,
+ },
+ [0x1F3B0]={
+ category="so",
+ description="SLOT MACHINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B0,
+ },
+ [0x1F3B1]={
+ category="so",
+ description="BILLIARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B1,
+ },
+ [0x1F3B2]={
+ category="so",
+ description="GAME DIE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B2,
+ },
+ [0x1F3B3]={
+ category="so",
+ description="BOWLING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B3,
+ },
+ [0x1F3B4]={
+ category="so",
+ description="FLOWER PLAYING CARDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B4,
+ },
+ [0x1F3B5]={
+ category="so",
+ description="MUSICAL NOTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B5,
+ },
+ [0x1F3B6]={
+ category="so",
+ description="MULTIPLE MUSICAL NOTES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B6,
+ },
+ [0x1F3B7]={
+ category="so",
+ description="SAXOPHONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B7,
+ },
+ [0x1F3B8]={
+ category="so",
+ description="GUITAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B8,
+ },
+ [0x1F3B9]={
+ category="so",
+ description="MUSICAL KEYBOARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3B9,
+ },
+ [0x1F3BA]={
+ category="so",
+ description="TRUMPET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3BA,
+ },
+ [0x1F3BB]={
+ category="so",
+ description="VIOLIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3BB,
+ },
+ [0x1F3BC]={
+ category="so",
+ description="MUSICAL SCORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3BC,
+ },
+ [0x1F3BD]={
+ category="so",
+ description="RUNNING SHIRT WITH SASH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3BD,
+ },
+ [0x1F3BE]={
+ category="so",
+ description="TENNIS RACQUET AND BALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3BE,
+ },
+ [0x1F3BF]={
+ category="so",
+ description="SKI AND SKI BOOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3BF,
+ },
+ [0x1F3C0]={
+ category="so",
+ description="BASKETBALL AND HOOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C0,
+ },
+ [0x1F3C1]={
+ category="so",
+ description="CHEQUERED FLAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C1,
+ },
+ [0x1F3C2]={
+ category="so",
+ description="SNOWBOARDER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C2,
+ },
+ [0x1F3C3]={
+ category="so",
+ description="RUNNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C3,
+ },
+ [0x1F3C4]={
+ category="so",
+ description="SURFER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C4,
+ },
+ [0x1F3C6]={
+ category="so",
+ description="TROPHY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C6,
+ },
+ [0x1F3C7]={
+ category="so",
+ description="HORSE RACING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C7,
+ },
+ [0x1F3C8]={
+ category="so",
+ description="AMERICAN FOOTBALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C8,
+ },
+ [0x1F3C9]={
+ category="so",
+ description="RUGBY FOOTBALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3C9,
+ },
+ [0x1F3CA]={
+ category="so",
+ description="SWIMMER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3CA,
+ },
+ [0x1F3E0]={
+ category="so",
+ description="HOUSE BUILDING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E0,
+ },
+ [0x1F3E1]={
+ category="so",
+ description="HOUSE WITH GARDEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E1,
+ },
+ [0x1F3E2]={
+ category="so",
+ description="OFFICE BUILDING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E2,
+ },
+ [0x1F3E3]={
+ category="so",
+ description="JAPANESE POST OFFICE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E3,
+ },
+ [0x1F3E4]={
+ category="so",
+ description="EUROPEAN POST OFFICE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E4,
+ },
+ [0x1F3E5]={
+ category="so",
+ description="HOSPITAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E5,
+ },
+ [0x1F3E6]={
+ category="so",
+ description="BANK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E6,
+ },
+ [0x1F3E7]={
+ category="so",
+ description="AUTOMATED TELLER MACHINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E7,
+ },
+ [0x1F3E8]={
+ category="so",
+ description="HOTEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E8,
+ },
+ [0x1F3E9]={
+ category="so",
+ description="LOVE HOTEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3E9,
+ },
+ [0x1F3EA]={
+ category="so",
+ description="CONVENIENCE STORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3EA,
+ },
+ [0x1F3EB]={
+ category="so",
+ description="SCHOOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3EB,
+ },
+ [0x1F3EC]={
+ category="so",
+ description="DEPARTMENT STORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3EC,
+ },
+ [0x1F3ED]={
+ category="so",
+ description="FACTORY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3ED,
+ },
+ [0x1F3EE]={
+ category="so",
+ description="IZAKAYA LANTERN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3EE,
+ },
+ [0x1F3EF]={
+ category="so",
+ description="JAPANESE CASTLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3EF,
+ },
+ [0x1F3F0]={
+ category="so",
+ description="EUROPEAN CASTLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F3F0,
+ },
+ [0x1F400]={
+ category="so",
+ description="RAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F400,
+ },
+ [0x1F401]={
+ category="so",
+ description="MOUSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F401,
+ },
+ [0x1F402]={
+ category="so",
+ description="OX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F402,
+ },
+ [0x1F403]={
+ category="so",
+ description="WATER BUFFALO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F403,
+ },
+ [0x1F404]={
+ category="so",
+ description="COW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F404,
+ },
+ [0x1F405]={
+ category="so",
+ description="TIGER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F405,
+ },
+ [0x1F406]={
+ category="so",
+ description="LEOPARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F406,
+ },
+ [0x1F407]={
+ category="so",
+ description="RABBIT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F407,
+ },
+ [0x1F408]={
+ category="so",
+ description="CAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F408,
+ },
+ [0x1F409]={
+ category="so",
+ description="DRAGON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F409,
+ },
+ [0x1F40A]={
+ category="so",
+ description="CROCODILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F40A,
+ },
+ [0x1F40B]={
+ category="so",
+ description="WHALE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F40B,
+ },
+ [0x1F40C]={
+ category="so",
+ description="SNAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F40C,
+ },
+ [0x1F40D]={
+ category="so",
+ description="SNAKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F40D,
+ },
+ [0x1F40E]={
+ category="so",
+ description="HORSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F40E,
+ },
+ [0x1F40F]={
+ category="so",
+ description="RAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F40F,
+ },
+ [0x1F410]={
+ category="so",
+ description="GOAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F410,
+ },
+ [0x1F411]={
+ category="so",
+ description="SHEEP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F411,
+ },
+ [0x1F412]={
+ category="so",
+ description="MONKEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F412,
+ },
+ [0x1F413]={
+ category="so",
+ description="ROOSTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F413,
+ },
+ [0x1F414]={
+ category="so",
+ description="CHICKEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F414,
+ },
+ [0x1F415]={
+ category="so",
+ description="DOG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F415,
+ },
+ [0x1F416]={
+ category="so",
+ description="PIG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F416,
+ },
+ [0x1F417]={
+ category="so",
+ description="BOAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F417,
+ },
+ [0x1F418]={
+ category="so",
+ description="ELEPHANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F418,
+ },
+ [0x1F419]={
+ category="so",
+ description="OCTOPUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F419,
+ },
+ [0x1F41A]={
+ category="so",
+ description="SPIRAL SHELL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F41A,
+ },
+ [0x1F41B]={
+ category="so",
+ description="BUG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F41B,
+ },
+ [0x1F41C]={
+ category="so",
+ description="ANT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F41C,
+ },
+ [0x1F41D]={
+ category="so",
+ description="HONEYBEE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F41D,
+ },
+ [0x1F41E]={
+ category="so",
+ description="LADY BEETLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F41E,
+ },
+ [0x1F41F]={
+ category="so",
+ description="FISH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F41F,
+ },
+ [0x1F420]={
+ category="so",
+ description="TROPICAL FISH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F420,
+ },
+ [0x1F421]={
+ category="so",
+ description="BLOWFISH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F421,
+ },
+ [0x1F422]={
+ category="so",
+ description="TURTLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F422,
+ },
+ [0x1F423]={
+ category="so",
+ description="HATCHING CHICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F423,
+ },
+ [0x1F424]={
+ category="so",
+ description="BABY CHICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F424,
+ },
+ [0x1F425]={
+ category="so",
+ description="FRONT-FACING BABY CHICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F425,
+ },
+ [0x1F426]={
+ category="so",
+ description="BIRD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F426,
+ },
+ [0x1F427]={
+ category="so",
+ description="PENGUIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F427,
+ },
+ [0x1F428]={
+ category="so",
+ description="KOALA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F428,
+ },
+ [0x1F429]={
+ category="so",
+ description="POODLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F429,
+ },
+ [0x1F42A]={
+ category="so",
+ description="DROMEDARY CAMEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F42A,
+ },
+ [0x1F42B]={
+ category="so",
+ description="BACTRIAN CAMEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F42B,
+ },
+ [0x1F42C]={
+ category="so",
+ description="DOLPHIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F42C,
+ },
+ [0x1F42D]={
+ category="so",
+ description="MOUSE FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F42D,
+ },
+ [0x1F42E]={
+ category="so",
+ description="COW FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F42E,
+ },
+ [0x1F42F]={
+ category="so",
+ description="TIGER FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F42F,
+ },
+ [0x1F430]={
+ category="so",
+ description="RABBIT FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F430,
+ },
+ [0x1F431]={
+ category="so",
+ description="CAT FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F431,
+ },
+ [0x1F432]={
+ category="so",
+ description="DRAGON FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F432,
+ },
+ [0x1F433]={
+ category="so",
+ description="SPOUTING WHALE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F433,
+ },
+ [0x1F434]={
+ category="so",
+ description="HORSE FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F434,
+ },
+ [0x1F435]={
+ category="so",
+ description="MONKEY FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F435,
+ },
+ [0x1F436]={
+ category="so",
+ description="DOG FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F436,
+ },
+ [0x1F437]={
+ category="so",
+ description="PIG FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F437,
+ },
+ [0x1F438]={
+ category="so",
+ description="FROG FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F438,
+ },
+ [0x1F439]={
+ category="so",
+ description="HAMSTER FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F439,
+ },
+ [0x1F43A]={
+ category="so",
+ description="WOLF FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F43A,
+ },
+ [0x1F43B]={
+ category="so",
+ description="BEAR FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F43B,
+ },
+ [0x1F43C]={
+ category="so",
+ description="PANDA FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F43C,
+ },
+ [0x1F43D]={
+ category="so",
+ description="PIG NOSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F43D,
+ },
+ [0x1F43E]={
+ category="so",
+ description="PAW PRINTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F43E,
+ },
+ [0x1F440]={
+ category="so",
+ description="EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F440,
+ },
+ [0x1F442]={
+ category="so",
+ description="EAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F442,
+ },
+ [0x1F443]={
+ category="so",
+ description="NOSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F443,
+ },
+ [0x1F444]={
+ category="so",
+ description="MOUTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F444,
+ },
+ [0x1F445]={
+ category="so",
+ description="TONGUE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F445,
+ },
+ [0x1F446]={
+ category="so",
+ description="WHITE UP POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F446,
+ },
+ [0x1F447]={
+ category="so",
+ description="WHITE DOWN POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F447,
+ },
+ [0x1F448]={
+ category="so",
+ description="WHITE LEFT POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F448,
+ },
+ [0x1F449]={
+ category="so",
+ description="WHITE RIGHT POINTING BACKHAND INDEX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F449,
+ },
+ [0x1F44A]={
+ category="so",
+ description="FISTED HAND SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F44A,
+ },
+ [0x1F44B]={
+ category="so",
+ description="WAVING HAND SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F44B,
+ },
+ [0x1F44C]={
+ category="so",
+ description="OK HAND SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F44C,
+ },
+ [0x1F44D]={
+ category="so",
+ description="THUMBS UP SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F44D,
+ },
+ [0x1F44E]={
+ category="so",
+ description="THUMBS DOWN SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F44E,
+ },
+ [0x1F44F]={
+ category="so",
+ description="CLAPPING HANDS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F44F,
+ },
+ [0x1F450]={
+ category="so",
+ description="OPEN HANDS SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F450,
+ },
+ [0x1F451]={
+ category="so",
+ description="CROWN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F451,
+ },
+ [0x1F452]={
+ category="so",
+ description="WOMANS HAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F452,
+ },
+ [0x1F453]={
+ category="so",
+ description="EYEGLASSES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F453,
+ },
+ [0x1F454]={
+ category="so",
+ description="NECKTIE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F454,
+ },
+ [0x1F455]={
+ category="so",
+ description="T-SHIRT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F455,
+ },
+ [0x1F456]={
+ category="so",
+ description="JEANS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F456,
+ },
+ [0x1F457]={
+ category="so",
+ description="DRESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F457,
+ },
+ [0x1F458]={
+ category="so",
+ description="KIMONO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F458,
+ },
+ [0x1F459]={
+ category="so",
+ description="BIKINI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F459,
+ },
+ [0x1F45A]={
+ category="so",
+ description="WOMANS CLOTHES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F45A,
+ },
+ [0x1F45B]={
+ category="so",
+ description="PURSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F45B,
+ },
+ [0x1F45C]={
+ category="so",
+ description="HANDBAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F45C,
+ },
+ [0x1F45D]={
+ category="so",
+ description="POUCH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F45D,
+ },
+ [0x1F45E]={
+ category="so",
+ description="MANS SHOE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F45E,
+ },
+ [0x1F45F]={
+ category="so",
+ description="ATHLETIC SHOE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F45F,
+ },
+ [0x1F460]={
+ category="so",
+ description="HIGH-HEELED SHOE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F460,
+ },
+ [0x1F461]={
+ category="so",
+ description="WOMANS SANDAL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F461,
+ },
+ [0x1F462]={
+ category="so",
+ description="WOMANS BOOTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F462,
+ },
+ [0x1F463]={
+ category="so",
+ description="FOOTPRINTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F463,
+ },
+ [0x1F464]={
+ category="so",
+ description="BUST IN SILHOUETTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F464,
+ },
+ [0x1F465]={
+ category="so",
+ description="BUSTS IN SILHOUETTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F465,
+ },
+ [0x1F466]={
+ category="so",
+ description="BOY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F466,
+ },
+ [0x1F467]={
+ category="so",
+ description="GIRL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F467,
+ },
+ [0x1F468]={
+ category="so",
+ description="MAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F468,
+ },
+ [0x1F469]={
+ category="so",
+ description="WOMAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F469,
+ },
+ [0x1F46A]={
+ category="so",
+ description="FAMILY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F46A,
+ },
+ [0x1F46B]={
+ category="so",
+ description="MAN AND WOMAN HOLDING HANDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F46B,
+ },
+ [0x1F46C]={
+ category="so",
+ description="TWO MEN HOLDING HANDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F46C,
+ },
+ [0x1F46D]={
+ category="so",
+ description="TWO WOMEN HOLDING HANDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F46D,
+ },
+ [0x1F46E]={
+ category="so",
+ description="POLICE OFFICER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F46E,
+ },
+ [0x1F46F]={
+ category="so",
+ description="WOMAN WITH BUNNY EARS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F46F,
+ },
+ [0x1F470]={
+ category="so",
+ description="BRIDE WITH VEIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F470,
+ },
+ [0x1F471]={
+ category="so",
+ description="PERSON WITH BLOND HAIR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F471,
+ },
+ [0x1F472]={
+ category="so",
+ description="MAN WITH GUA PI MAO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F472,
+ },
+ [0x1F473]={
+ category="so",
+ description="MAN WITH TURBAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F473,
+ },
+ [0x1F474]={
+ category="so",
+ description="OLDER MAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F474,
+ },
+ [0x1F475]={
+ category="so",
+ description="OLDER WOMAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F475,
+ },
+ [0x1F476]={
+ category="so",
+ description="BABY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F476,
+ },
+ [0x1F477]={
+ category="so",
+ description="CONSTRUCTION WORKER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F477,
+ },
+ [0x1F478]={
+ category="so",
+ description="PRINCESS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F478,
+ },
+ [0x1F479]={
+ category="so",
+ description="JAPANESE OGRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F479,
+ },
+ [0x1F47A]={
+ category="so",
+ description="JAPANESE GOBLIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F47A,
+ },
+ [0x1F47B]={
+ category="so",
+ description="GHOST",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F47B,
+ },
+ [0x1F47C]={
+ category="so",
+ description="BABY ANGEL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F47C,
+ },
+ [0x1F47D]={
+ category="so",
+ description="EXTRATERRESTRIAL ALIEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F47D,
+ },
+ [0x1F47E]={
+ category="so",
+ description="ALIEN MONSTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F47E,
+ },
+ [0x1F47F]={
+ category="so",
+ description="IMP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F47F,
+ },
+ [0x1F480]={
+ category="so",
+ description="SKULL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F480,
+ },
+ [0x1F481]={
+ category="so",
+ description="INFORMATION DESK PERSON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F481,
+ },
+ [0x1F482]={
+ category="so",
+ description="GUARDSMAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F482,
+ },
+ [0x1F483]={
+ category="so",
+ description="DANCER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F483,
+ },
+ [0x1F484]={
+ category="so",
+ description="LIPSTICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F484,
+ },
+ [0x1F485]={
+ category="so",
+ description="NAIL POLISH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F485,
+ },
+ [0x1F486]={
+ category="so",
+ description="FACE MASSAGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F486,
+ },
+ [0x1F487]={
+ category="so",
+ description="HAIRCUT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F487,
+ },
+ [0x1F488]={
+ category="so",
+ description="BARBER POLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F488,
+ },
+ [0x1F489]={
+ category="so",
+ description="SYRINGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F489,
+ },
+ [0x1F48A]={
+ category="so",
+ description="PILL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F48A,
+ },
+ [0x1F48B]={
+ category="so",
+ description="KISS MARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F48B,
+ },
+ [0x1F48C]={
+ category="so",
+ description="LOVE LETTER",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F48C,
+ },
+ [0x1F48D]={
+ category="so",
+ description="RING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F48D,
+ },
+ [0x1F48E]={
+ category="so",
+ description="GEM STONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F48E,
+ },
+ [0x1F48F]={
+ category="so",
+ description="KISS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F48F,
+ },
+ [0x1F490]={
+ category="so",
+ description="BOUQUET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F490,
+ },
+ [0x1F491]={
+ category="so",
+ description="COUPLE WITH HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F491,
+ },
+ [0x1F492]={
+ category="so",
+ description="WEDDING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F492,
+ },
+ [0x1F493]={
+ category="so",
+ description="BEATING HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F493,
+ },
+ [0x1F494]={
+ category="so",
+ description="BROKEN HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F494,
+ },
+ [0x1F495]={
+ category="so",
+ description="TWO HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F495,
+ },
+ [0x1F496]={
+ category="so",
+ description="SPARKLING HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F496,
+ },
+ [0x1F497]={
+ category="so",
+ description="GROWING HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F497,
+ },
+ [0x1F498]={
+ category="so",
+ description="HEART WITH ARROW",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F498,
+ },
+ [0x1F499]={
+ category="so",
+ description="BLUE HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F499,
+ },
+ [0x1F49A]={
+ category="so",
+ description="GREEN HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F49A,
+ },
+ [0x1F49B]={
+ category="so",
+ description="YELLOW HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F49B,
+ },
+ [0x1F49C]={
+ category="so",
+ description="PURPLE HEART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F49C,
+ },
+ [0x1F49D]={
+ category="so",
+ description="HEART WITH RIBBON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F49D,
+ },
+ [0x1F49E]={
+ category="so",
+ description="REVOLVING HEARTS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F49E,
+ },
+ [0x1F49F]={
+ category="so",
+ description="HEART DECORATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F49F,
+ },
+ [0x1F4A0]={
+ category="so",
+ description="DIAMOND SHAPE WITH A DOT INSIDE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A0,
+ },
+ [0x1F4A1]={
+ category="so",
+ description="ELECTRIC LIGHT BULB",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A1,
+ },
+ [0x1F4A2]={
+ category="so",
+ description="ANGER SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A2,
+ },
+ [0x1F4A3]={
+ category="so",
+ description="BOMB",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A3,
+ },
+ [0x1F4A4]={
+ category="so",
+ description="SLEEPING SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A4,
+ },
+ [0x1F4A5]={
+ category="so",
+ description="COLLISION SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A5,
+ },
+ [0x1F4A6]={
+ category="so",
+ description="SPLASHING SWEAT SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A6,
+ },
+ [0x1F4A7]={
+ category="so",
+ description="DROPLET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A7,
+ },
+ [0x1F4A8]={
+ category="so",
+ description="DASH SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A8,
+ },
+ [0x1F4A9]={
+ category="so",
+ description="PILE OF POO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4A9,
+ },
+ [0x1F4AA]={
+ category="so",
+ description="FLEXED BICEPS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4AA,
+ },
+ [0x1F4AB]={
+ category="so",
+ description="DIZZY SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4AB,
+ },
+ [0x1F4AC]={
+ category="so",
+ description="SPEECH BALLOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4AC,
+ },
+ [0x1F4AD]={
+ category="so",
+ description="THOUGHT BALLOON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4AD,
+ },
+ [0x1F4AE]={
+ category="so",
+ description="WHITE FLOWER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4AE,
+ },
+ [0x1F4AF]={
+ category="so",
+ description="HUNDRED POINTS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4AF,
+ },
+ [0x1F4B0]={
+ category="so",
+ description="MONEY BAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B0,
+ },
+ [0x1F4B1]={
+ category="so",
+ description="CURRENCY EXCHANGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B1,
+ },
+ [0x1F4B2]={
+ category="so",
+ description="HEAVY DOLLAR SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B2,
+ },
+ [0x1F4B3]={
+ category="so",
+ description="CREDIT CARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B3,
+ },
+ [0x1F4B4]={
+ category="so",
+ description="BANKNOTE WITH YEN SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B4,
+ },
+ [0x1F4B5]={
+ category="so",
+ description="BANKNOTE WITH DOLLAR SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B5,
+ },
+ [0x1F4B6]={
+ category="so",
+ description="BANKNOTE WITH EURO SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B6,
+ },
+ [0x1F4B7]={
+ category="so",
+ description="BANKNOTE WITH POUND SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B7,
+ },
+ [0x1F4B8]={
+ category="so",
+ description="MONEY WITH WINGS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B8,
+ },
+ [0x1F4B9]={
+ category="so",
+ description="CHART WITH UPWARDS TREND AND YEN SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4B9,
+ },
+ [0x1F4BA]={
+ category="so",
+ description="SEAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4BA,
+ },
+ [0x1F4BB]={
+ category="so",
+ description="PERSONAL COMPUTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4BB,
+ },
+ [0x1F4BC]={
+ category="so",
+ description="BRIEFCASE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4BC,
+ },
+ [0x1F4BD]={
+ category="so",
+ description="MINIDISC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4BD,
+ },
+ [0x1F4BE]={
+ category="so",
+ description="FLOPPY DISK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4BE,
+ },
+ [0x1F4BF]={
+ category="so",
+ description="OPTICAL DISC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4BF,
+ },
+ [0x1F4C0]={
+ category="so",
+ description="DVD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C0,
+ },
+ [0x1F4C1]={
+ category="so",
+ description="FILE FOLDER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C1,
+ },
+ [0x1F4C2]={
+ category="so",
+ description="OPEN FILE FOLDER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C2,
+ },
+ [0x1F4C3]={
+ category="so",
+ description="PAGE WITH CURL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C3,
+ },
+ [0x1F4C4]={
+ category="so",
+ description="PAGE FACING UP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C4,
+ },
+ [0x1F4C5]={
+ category="so",
+ description="CALENDAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C5,
+ },
+ [0x1F4C6]={
+ category="so",
+ description="TEAR-OFF CALENDAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C6,
+ },
+ [0x1F4C7]={
+ category="so",
+ description="CARD INDEX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C7,
+ },
+ [0x1F4C8]={
+ category="so",
+ description="CHART WITH UPWARDS TREND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C8,
+ },
+ [0x1F4C9]={
+ category="so",
+ description="CHART WITH DOWNWARDS TREND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4C9,
+ },
+ [0x1F4CA]={
+ category="so",
+ description="BAR CHART",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4CA,
+ },
+ [0x1F4CB]={
+ category="so",
+ description="CLIPBOARD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4CB,
+ },
+ [0x1F4CC]={
+ category="so",
+ description="PUSHPIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4CC,
+ },
+ [0x1F4CD]={
+ category="so",
+ description="ROUND PUSHPIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4CD,
+ },
+ [0x1F4CE]={
+ category="so",
+ description="PAPERCLIP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4CE,
+ },
+ [0x1F4CF]={
+ category="so",
+ description="STRAIGHT RULER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4CF,
+ },
+ [0x1F4D0]={
+ category="so",
+ description="TRIANGULAR RULER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D0,
+ },
+ [0x1F4D1]={
+ category="so",
+ description="BOOKMARK TABS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D1,
+ },
+ [0x1F4D2]={
+ category="so",
+ description="LEDGER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D2,
+ },
+ [0x1F4D3]={
+ category="so",
+ description="NOTEBOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D3,
+ },
+ [0x1F4D4]={
+ category="so",
+ description="NOTEBOOK WITH DECORATIVE COVER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D4,
+ },
+ [0x1F4D5]={
+ category="so",
+ description="CLOSED BOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D5,
+ },
+ [0x1F4D6]={
+ category="so",
+ description="OPEN BOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D6,
+ },
+ [0x1F4D7]={
+ category="so",
+ description="GREEN BOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D7,
+ },
+ [0x1F4D8]={
+ category="so",
+ description="BLUE BOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D8,
+ },
+ [0x1F4D9]={
+ category="so",
+ description="ORANGE BOOK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4D9,
+ },
+ [0x1F4DA]={
+ category="so",
+ description="BOOKS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4DA,
+ },
+ [0x1F4DB]={
+ category="so",
+ description="NAME BADGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4DB,
+ },
+ [0x1F4DC]={
+ category="so",
+ description="SCROLL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4DC,
+ },
+ [0x1F4DD]={
+ category="so",
+ description="MEMO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4DD,
+ },
+ [0x1F4DE]={
+ category="so",
+ description="TELEPHONE RECEIVER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4DE,
+ },
+ [0x1F4DF]={
+ category="so",
+ description="PAGER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4DF,
+ },
+ [0x1F4E0]={
+ category="so",
+ description="FAX MACHINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E0,
+ },
+ [0x1F4E1]={
+ category="so",
+ description="SATELLITE ANTENNA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E1,
+ },
+ [0x1F4E2]={
+ category="so",
+ description="PUBLIC ADDRESS LOUDSPEAKER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E2,
+ },
+ [0x1F4E3]={
+ category="so",
+ description="CHEERING MEGAPHONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E3,
+ },
+ [0x1F4E4]={
+ category="so",
+ description="OUTBOX TRAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E4,
+ },
+ [0x1F4E5]={
+ category="so",
+ description="INBOX TRAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E5,
+ },
+ [0x1F4E6]={
+ category="so",
+ description="PACKAGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E6,
+ },
+ [0x1F4E7]={
+ category="so",
+ description="E-MAIL SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E7,
+ },
+ [0x1F4E8]={
+ category="so",
+ description="INCOMING ENVELOPE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E8,
+ },
+ [0x1F4E9]={
+ category="so",
+ description="ENVELOPE WITH DOWNWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4E9,
+ },
+ [0x1F4EA]={
+ category="so",
+ description="CLOSED MAILBOX WITH LOWERED FLAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4EA,
+ },
+ [0x1F4EB]={
+ category="so",
+ description="CLOSED MAILBOX WITH RAISED FLAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4EB,
+ },
+ [0x1F4EC]={
+ category="so",
+ description="OPEN MAILBOX WITH RAISED FLAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4EC,
+ },
+ [0x1F4ED]={
+ category="so",
+ description="OPEN MAILBOX WITH LOWERED FLAG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4ED,
+ },
+ [0x1F4EE]={
+ category="so",
+ description="POSTBOX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4EE,
+ },
+ [0x1F4EF]={
+ category="so",
+ description="POSTAL HORN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4EF,
+ },
+ [0x1F4F0]={
+ category="so",
+ description="NEWSPAPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F0,
+ },
+ [0x1F4F1]={
+ category="so",
+ description="MOBILE PHONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F1,
+ },
+ [0x1F4F2]={
+ category="so",
+ description="MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F2,
+ },
+ [0x1F4F3]={
+ category="so",
+ description="VIBRATION MODE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F3,
+ },
+ [0x1F4F4]={
+ category="so",
+ description="MOBILE PHONE OFF",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F4,
+ },
+ [0x1F4F5]={
+ category="so",
+ description="NO MOBILE PHONES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F5,
+ },
+ [0x1F4F6]={
+ category="so",
+ description="ANTENNA WITH BARS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F6,
+ },
+ [0x1F4F7]={
+ category="so",
+ description="CAMERA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F7,
+ },
+ [0x1F4F9]={
+ category="so",
+ description="VIDEO CAMERA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4F9,
+ },
+ [0x1F4FA]={
+ category="so",
+ description="TELEVISION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4FA,
+ },
+ [0x1F4FB]={
+ category="so",
+ description="RADIO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4FB,
+ },
+ [0x1F4FC]={
+ category="so",
+ description="VIDEOCASSETTE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F4FC,
+ },
+ [0x1F500]={
+ category="so",
+ description="TWISTED RIGHTWARDS ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F500,
+ },
+ [0x1F501]={
+ category="so",
+ description="CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F501,
+ },
+ [0x1F502]={
+ category="so",
+ description="CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F502,
+ },
+ [0x1F503]={
+ category="so",
+ description="CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F503,
+ },
+ [0x1F504]={
+ category="so",
+ description="ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F504,
+ },
+ [0x1F505]={
+ category="so",
+ description="LOW BRIGHTNESS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F505,
+ },
+ [0x1F506]={
+ category="so",
+ description="HIGH BRIGHTNESS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F506,
+ },
+ [0x1F507]={
+ category="so",
+ description="SPEAKER WITH CANCELLATION STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F507,
+ },
+ [0x1F508]={
+ category="so",
+ description="SPEAKER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F508,
+ },
+ [0x1F509]={
+ category="so",
+ description="SPEAKER WITH ONE SOUND WAVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F509,
+ },
+ [0x1F50A]={
+ category="so",
+ description="SPEAKER WITH THREE SOUND WAVES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F50A,
+ },
+ [0x1F50B]={
+ category="so",
+ description="BATTERY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F50B,
+ },
+ [0x1F50C]={
+ category="so",
+ description="ELECTRIC PLUG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F50C,
+ },
+ [0x1F50D]={
+ category="so",
+ description="LEFT-POINTING MAGNIFYING GLASS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F50D,
+ },
+ [0x1F50E]={
+ category="so",
+ description="RIGHT-POINTING MAGNIFYING GLASS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F50E,
+ },
+ [0x1F50F]={
+ category="so",
+ description="LOCK WITH INK PEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F50F,
+ },
+ [0x1F510]={
+ category="so",
+ description="CLOSED LOCK WITH KEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F510,
+ },
+ [0x1F511]={
+ category="so",
+ description="KEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F511,
+ },
+ [0x1F512]={
+ category="so",
+ description="LOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F512,
+ },
+ [0x1F513]={
+ category="so",
+ description="OPEN LOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F513,
+ },
+ [0x1F514]={
+ category="so",
+ description="BELL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F514,
+ },
+ [0x1F515]={
+ category="so",
+ description="BELL WITH CANCELLATION STROKE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F515,
+ },
+ [0x1F516]={
+ category="so",
+ description="BOOKMARK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F516,
+ },
+ [0x1F517]={
+ category="so",
+ description="LINK SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F517,
+ },
+ [0x1F518]={
+ category="so",
+ description="RADIO BUTTON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F518,
+ },
+ [0x1F519]={
+ category="so",
+ description="BACK WITH LEFTWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F519,
+ },
+ [0x1F51A]={
+ category="so",
+ description="END WITH LEFTWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51A,
+ },
+ [0x1F51B]={
+ category="so",
+ description="ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51B,
+ },
+ [0x1F51C]={
+ category="so",
+ description="SOON WITH RIGHTWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51C,
+ },
+ [0x1F51D]={
+ category="so",
+ description="TOP WITH UPWARDS ARROW ABOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51D,
+ },
+ [0x1F51E]={
+ category="so",
+ description="NO ONE UNDER EIGHTEEN SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51E,
+ },
+ [0x1F51F]={
+ category="so",
+ description="KEYCAP TEN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F51F,
+ },
+ [0x1F520]={
+ category="so",
+ description="INPUT SYMBOL FOR LATIN CAPITAL LETTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F520,
+ },
+ [0x1F521]={
+ category="so",
+ description="INPUT SYMBOL FOR LATIN SMALL LETTERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F521,
+ },
+ [0x1F522]={
+ category="so",
+ description="INPUT SYMBOL FOR NUMBERS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F522,
+ },
+ [0x1F523]={
+ category="so",
+ description="INPUT SYMBOL FOR SYMBOLS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F523,
+ },
+ [0x1F524]={
+ category="so",
+ description="INPUT SYMBOL FOR LATIN LETTERS",
+ direction="l",
+ linebreak="al",
+ unicodeslot=0x1F524,
+ },
+ [0x1F525]={
+ category="so",
+ description="FIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F525,
+ },
+ [0x1F526]={
+ category="so",
+ description="ELECTRIC TORCH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F526,
+ },
+ [0x1F527]={
+ category="so",
+ description="WRENCH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F527,
+ },
+ [0x1F528]={
+ category="so",
+ description="HAMMER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F528,
+ },
+ [0x1F529]={
+ category="so",
+ description="NUT AND BOLT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F529,
+ },
+ [0x1F52A]={
+ category="so",
+ description="HOCHO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F52A,
+ },
+ [0x1F52B]={
+ category="so",
+ description="PISTOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F52B,
+ },
+ [0x1F52C]={
+ category="so",
+ description="MICROSCOPE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F52C,
+ },
+ [0x1F52D]={
+ category="so",
+ description="TELESCOPE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F52D,
+ },
+ [0x1F52E]={
+ category="so",
+ description="CRYSTAL BALL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F52E,
+ },
+ [0x1F52F]={
+ category="so",
+ description="SIX POINTED STAR WITH MIDDLE DOT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F52F,
+ },
+ [0x1F530]={
+ category="so",
+ description="JAPANESE SYMBOL FOR BEGINNER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F530,
+ },
+ [0x1F531]={
+ category="so",
+ description="TRIDENT EMBLEM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F531,
+ },
+ [0x1F532]={
+ category="so",
+ description="BLACK SQUARE BUTTON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F532,
+ },
+ [0x1F533]={
+ category="so",
+ description="WHITE SQUARE BUTTON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F533,
+ },
+ [0x1F534]={
+ category="so",
+ description="LARGE RED CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F534,
+ },
+ [0x1F535]={
+ category="so",
+ description="LARGE BLUE CIRCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F535,
+ },
+ [0x1F536]={
+ category="so",
+ description="LARGE ORANGE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F536,
+ },
+ [0x1F537]={
+ category="so",
+ description="LARGE BLUE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F537,
+ },
+ [0x1F538]={
+ category="so",
+ description="SMALL ORANGE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F538,
+ },
+ [0x1F539]={
+ category="so",
+ description="SMALL BLUE DIAMOND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F539,
+ },
+ [0x1F53A]={
+ category="so",
+ description="UP-POINTING RED TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53A,
+ },
+ [0x1F53B]={
+ category="so",
+ description="DOWN-POINTING RED TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53B,
+ },
+ [0x1F53C]={
+ category="so",
+ description="UP-POINTING SMALL RED TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53C,
+ },
+ [0x1F53D]={
+ category="so",
+ description="DOWN-POINTING SMALL RED TRIANGLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F53D,
+ },
+ [0x1F550]={
+ category="so",
+ description="CLOCK FACE ONE OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F550,
+ },
+ [0x1F551]={
+ category="so",
+ description="CLOCK FACE TWO OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F551,
+ },
+ [0x1F552]={
+ category="so",
+ description="CLOCK FACE THREE OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F552,
+ },
+ [0x1F553]={
+ category="so",
+ description="CLOCK FACE FOUR OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F553,
+ },
+ [0x1F554]={
+ category="so",
+ description="CLOCK FACE FIVE OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F554,
+ },
+ [0x1F555]={
+ category="so",
+ description="CLOCK FACE SIX OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F555,
+ },
+ [0x1F556]={
+ category="so",
+ description="CLOCK FACE SEVEN OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F556,
+ },
+ [0x1F557]={
+ category="so",
+ description="CLOCK FACE EIGHT OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F557,
+ },
+ [0x1F558]={
+ category="so",
+ description="CLOCK FACE NINE OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F558,
+ },
+ [0x1F559]={
+ category="so",
+ description="CLOCK FACE TEN OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F559,
+ },
+ [0x1F55A]={
+ category="so",
+ description="CLOCK FACE ELEVEN OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F55A,
+ },
+ [0x1F55B]={
+ category="so",
+ description="CLOCK FACE TWELVE OCLOCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F55B,
+ },
+ [0x1F55C]={
+ category="so",
+ description="CLOCK FACE ONE-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F55C,
+ },
+ [0x1F55D]={
+ category="so",
+ description="CLOCK FACE TWO-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F55D,
+ },
+ [0x1F55E]={
+ category="so",
+ description="CLOCK FACE THREE-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F55E,
+ },
+ [0x1F55F]={
+ category="so",
+ description="CLOCK FACE FOUR-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F55F,
+ },
+ [0x1F560]={
+ category="so",
+ description="CLOCK FACE FIVE-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F560,
+ },
+ [0x1F561]={
+ category="so",
+ description="CLOCK FACE SIX-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F561,
+ },
+ [0x1F562]={
+ category="so",
+ description="CLOCK FACE SEVEN-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F562,
+ },
+ [0x1F563]={
+ category="so",
+ description="CLOCK FACE EIGHT-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F563,
+ },
+ [0x1F564]={
+ category="so",
+ description="CLOCK FACE NINE-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F564,
+ },
+ [0x1F565]={
+ category="so",
+ description="CLOCK FACE TEN-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F565,
+ },
+ [0x1F566]={
+ category="so",
+ description="CLOCK FACE ELEVEN-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F566,
+ },
+ [0x1F567]={
+ category="so",
+ description="CLOCK FACE TWELVE-THIRTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F567,
+ },
+ [0x1F5FB]={
+ category="so",
+ description="MOUNT FUJI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5FB,
+ },
+ [0x1F5FC]={
+ category="so",
+ description="TOKYO TOWER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5FC,
+ },
+ [0x1F5FD]={
+ category="so",
+ description="STATUE OF LIBERTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5FD,
+ },
+ [0x1F5FE]={
+ category="so",
+ description="SILHOUETTE OF JAPAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5FE,
+ },
+ [0x1F5FF]={
+ category="so",
+ description="MOYAI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F5FF,
+ },
+ [0x1F601]={
+ category="so",
+ description="GRINNING FACE WITH SMILING EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F601,
+ },
+ [0x1F602]={
+ category="so",
+ description="FACE WITH TEARS OF JOY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F602,
+ },
+ [0x1F603]={
+ category="so",
+ description="SMILING FACE WITH OPEN MOUTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F603,
+ },
+ [0x1F604]={
+ category="so",
+ description="SMILING FACE WITH OPEN MOUTH AND SMILING EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F604,
+ },
+ [0x1F605]={
+ category="so",
+ description="SMILING FACE WITH OPEN MOUTH AND COLD SWEAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F605,
+ },
+ [0x1F606]={
+ category="so",
+ description="SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F606,
+ },
+ [0x1F607]={
+ category="so",
+ description="SMILING FACE WITH HALO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F607,
+ },
+ [0x1F608]={
+ category="so",
+ description="SMILING FACE WITH HORNS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F608,
+ },
+ [0x1F609]={
+ category="so",
+ description="WINKING FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F609,
+ },
+ [0x1F60A]={
+ category="so",
+ description="SMILING FACE WITH SMILING EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F60A,
+ },
+ [0x1F60B]={
+ category="so",
+ description="FACE SAVOURING DELICIOUS FOOD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F60B,
+ },
+ [0x1F60C]={
+ category="so",
+ description="RELIEVED FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F60C,
+ },
+ [0x1F60D]={
+ category="so",
+ description="SMILING FACE WITH HEART-SHAPED EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F60D,
+ },
+ [0x1F60E]={
+ category="so",
+ description="SMILING FACE WITH SUNGLASSES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F60E,
+ },
+ [0x1F60F]={
+ category="so",
+ description="SMIRKING FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F60F,
+ },
+ [0x1F610]={
+ category="so",
+ description="NEUTRAL FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F610,
+ },
+ [0x1F612]={
+ category="so",
+ description="UNAMUSED FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F612,
+ },
+ [0x1F613]={
+ category="so",
+ description="FACE WITH COLD SWEAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F613,
+ },
+ [0x1F614]={
+ category="so",
+ description="PENSIVE FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F614,
+ },
+ [0x1F616]={
+ category="so",
+ description="CONFOUNDED FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F616,
+ },
+ [0x1F618]={
+ category="so",
+ description="FACE THROWING A KISS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F618,
+ },
+ [0x1F61A]={
+ category="so",
+ description="KISSING FACE WITH CLOSED EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F61A,
+ },
+ [0x1F61C]={
+ category="so",
+ description="FACE WITH STUCK-OUT TONGUE AND WINKING EYE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F61C,
+ },
+ [0x1F61D]={
+ category="so",
+ description="FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F61D,
+ },
+ [0x1F61E]={
+ category="so",
+ description="DISAPPOINTED FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F61E,
+ },
+ [0x1F620]={
+ category="so",
+ description="ANGRY FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F620,
+ },
+ [0x1F621]={
+ category="so",
+ description="POUTING FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F621,
+ },
+ [0x1F622]={
+ category="so",
+ description="CRYING FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F622,
+ },
+ [0x1F623]={
+ category="so",
+ description="PERSEVERING FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F623,
+ },
+ [0x1F624]={
+ category="so",
+ description="FACE WITH LOOK OF TRIUMPH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F624,
+ },
+ [0x1F625]={
+ category="so",
+ description="DISAPPOINTED BUT RELIEVED FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F625,
+ },
+ [0x1F628]={
+ category="so",
+ description="FEARFUL FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F628,
+ },
+ [0x1F629]={
+ category="so",
+ description="WEARY FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F629,
+ },
+ [0x1F62A]={
+ category="so",
+ description="SLEEPY FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F62A,
+ },
+ [0x1F62B]={
+ category="so",
+ description="TIRED FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F62B,
+ },
+ [0x1F62D]={
+ category="so",
+ description="LOUDLY CRYING FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F62D,
+ },
+ [0x1F630]={
+ category="so",
+ description="FACE WITH OPEN MOUTH AND COLD SWEAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F630,
+ },
+ [0x1F631]={
+ category="so",
+ description="FACE SCREAMING IN FEAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F631,
+ },
+ [0x1F632]={
+ category="so",
+ description="ASTONISHED FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F632,
+ },
+ [0x1F633]={
+ category="so",
+ description="FLUSHED FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F633,
+ },
+ [0x1F635]={
+ category="so",
+ description="DIZZY FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F635,
+ },
+ [0x1F636]={
+ category="so",
+ description="FACE WITHOUT MOUTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F636,
+ },
+ [0x1F637]={
+ category="so",
+ description="FACE WITH MEDICAL MASK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F637,
+ },
+ [0x1F638]={
+ category="so",
+ description="GRINNING CAT FACE WITH SMILING EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F638,
+ },
+ [0x1F639]={
+ category="so",
+ description="CAT FACE WITH TEARS OF JOY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F639,
+ },
+ [0x1F63A]={
+ category="so",
+ description="SMILING CAT FACE WITH OPEN MOUTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F63A,
+ },
+ [0x1F63B]={
+ category="so",
+ description="SMILING CAT FACE WITH HEART-SHAPED EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F63B,
+ },
+ [0x1F63C]={
+ category="so",
+ description="CAT FACE WITH WRY SMILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F63C,
+ },
+ [0x1F63D]={
+ category="so",
+ description="KISSING CAT FACE WITH CLOSED EYES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F63D,
+ },
+ [0x1F63E]={
+ category="so",
+ description="POUTING CAT FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F63E,
+ },
+ [0x1F63F]={
+ category="so",
+ description="CRYING CAT FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F63F,
+ },
+ [0x1F640]={
+ category="so",
+ description="WEARY CAT FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F640,
+ },
+ [0x1F645]={
+ category="so",
+ description="FACE WITH NO GOOD GESTURE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F645,
+ },
+ [0x1F646]={
+ category="so",
+ description="FACE WITH OK GESTURE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F646,
+ },
+ [0x1F647]={
+ category="so",
+ description="PERSON BOWING DEEPLY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F647,
+ },
+ [0x1F648]={
+ category="so",
+ description="SEE-NO-EVIL MONKEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F648,
+ },
+ [0x1F649]={
+ category="so",
+ description="HEAR-NO-EVIL MONKEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F649,
+ },
+ [0x1F64A]={
+ category="so",
+ description="SPEAK-NO-EVIL MONKEY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F64A,
+ },
+ [0x1F64B]={
+ category="so",
+ description="HAPPY PERSON RAISING ONE HAND",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F64B,
+ },
+ [0x1F64C]={
+ category="so",
+ description="PERSON RAISING BOTH HANDS IN CELEBRATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F64C,
+ },
+ [0x1F64D]={
+ category="so",
+ description="PERSON FROWNING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F64D,
+ },
+ [0x1F64E]={
+ category="so",
+ description="PERSON WITH POUTING FACE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F64E,
+ },
+ [0x1F64F]={
+ category="so",
+ description="PERSON WITH FOLDED HANDS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F64F,
+ },
+ [0x1F680]={
+ category="so",
+ description="ROCKET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F680,
+ },
+ [0x1F681]={
+ category="so",
+ description="HELICOPTER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F681,
+ },
+ [0x1F682]={
+ category="so",
+ description="STEAM LOCOMOTIVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F682,
+ },
+ [0x1F683]={
+ category="so",
+ description="RAILWAY CAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F683,
+ },
+ [0x1F684]={
+ category="so",
+ description="HIGH-SPEED TRAIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F684,
+ },
+ [0x1F685]={
+ category="so",
+ description="HIGH-SPEED TRAIN WITH BULLET NOSE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F685,
+ },
+ [0x1F686]={
+ category="so",
+ description="TRAIN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F686,
+ },
+ [0x1F687]={
+ category="so",
+ description="METRO",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F687,
+ },
+ [0x1F688]={
+ category="so",
+ description="LIGHT RAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F688,
+ },
+ [0x1F689]={
+ category="so",
+ description="STATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F689,
+ },
+ [0x1F68A]={
+ category="so",
+ description="TRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F68A,
+ },
+ [0x1F68B]={
+ category="so",
+ description="TRAM CAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F68B,
+ },
+ [0x1F68C]={
+ category="so",
+ description="BUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F68C,
+ },
+ [0x1F68D]={
+ category="so",
+ description="ONCOMING BUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F68D,
+ },
+ [0x1F68E]={
+ category="so",
+ description="TROLLEYBUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F68E,
+ },
+ [0x1F68F]={
+ category="so",
+ description="BUS STOP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F68F,
+ },
+ [0x1F690]={
+ category="so",
+ description="MINIBUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F690,
+ },
+ [0x1F691]={
+ category="so",
+ description="AMBULANCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F691,
+ },
+ [0x1F692]={
+ category="so",
+ description="FIRE ENGINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F692,
+ },
+ [0x1F693]={
+ category="so",
+ description="POLICE CAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F693,
+ },
+ [0x1F694]={
+ category="so",
+ description="ONCOMING POLICE CAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F694,
+ },
+ [0x1F695]={
+ category="so",
+ description="TAXI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F695,
+ },
+ [0x1F696]={
+ category="so",
+ description="ONCOMING TAXI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F696,
+ },
+ [0x1F697]={
+ category="so",
+ description="AUTOMOBILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F697,
+ },
+ [0x1F698]={
+ category="so",
+ description="ONCOMING AUTOMOBILE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F698,
+ },
+ [0x1F699]={
+ category="so",
+ description="RECREATIONAL VEHICLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F699,
+ },
+ [0x1F69A]={
+ category="so",
+ description="DELIVERY TRUCK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F69A,
+ },
+ [0x1F69B]={
+ category="so",
+ description="ARTICULATED LORRY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F69B,
+ },
+ [0x1F69C]={
+ category="so",
+ description="TRACTOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F69C,
+ },
+ [0x1F69D]={
+ category="so",
+ description="MONORAIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F69D,
+ },
+ [0x1F69E]={
+ category="so",
+ description="MOUNTAIN RAILWAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F69E,
+ },
+ [0x1F69F]={
+ category="so",
+ description="SUSPENSION RAILWAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F69F,
+ },
+ [0x1F6A0]={
+ category="so",
+ description="MOUNTAIN CABLEWAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A0,
+ },
+ [0x1F6A1]={
+ category="so",
+ description="AERIAL TRAMWAY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A1,
+ },
+ [0x1F6A2]={
+ category="so",
+ description="SHIP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A2,
+ },
+ [0x1F6A3]={
+ category="so",
+ description="ROWBOAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A3,
+ },
+ [0x1F6A4]={
+ category="so",
+ description="SPEEDBOAT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A4,
+ },
+ [0x1F6A5]={
+ category="so",
+ description="HORIZONTAL TRAFFIC LIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A5,
+ },
+ [0x1F6A6]={
+ category="so",
+ description="VERTICAL TRAFFIC LIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A6,
+ },
+ [0x1F6A7]={
+ category="so",
+ description="CONSTRUCTION SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A7,
+ },
+ [0x1F6A8]={
+ category="so",
+ description="POLICE CARS REVOLVING LIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A8,
+ },
+ [0x1F6A9]={
+ category="so",
+ description="TRIANGULAR FLAG ON POST",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6A9,
+ },
+ [0x1F6AA]={
+ category="so",
+ description="DOOR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6AA,
+ },
+ [0x1F6AB]={
+ category="so",
+ description="NO ENTRY SIGN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6AB,
+ },
+ [0x1F6AC]={
+ category="so",
+ description="SMOKING SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6AC,
+ },
+ [0x1F6AD]={
+ category="so",
+ description="NO SMOKING SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6AD,
+ },
+ [0x1F6AE]={
+ category="so",
+ description="PUT LITTER IN ITS PLACE SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6AE,
+ },
+ [0x1F6AF]={
+ category="so",
+ description="DO NOT LITTER SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6AF,
+ },
+ [0x1F6B0]={
+ category="so",
+ description="POTABLE WATER SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B0,
+ },
+ [0x1F6B1]={
+ category="so",
+ description="NON-POTABLE WATER SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B1,
+ },
+ [0x1F6B2]={
+ category="so",
+ description="BICYCLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B2,
+ },
+ [0x1F6B3]={
+ category="so",
+ description="NO BICYCLES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B3,
+ },
+ [0x1F6B4]={
+ category="so",
+ description="BICYCLIST",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B4,
+ },
+ [0x1F6B5]={
+ category="so",
+ description="MOUNTAIN BICYCLIST",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B5,
+ },
+ [0x1F6B6]={
+ category="so",
+ description="PEDESTRIAN",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B6,
+ },
+ [0x1F6B7]={
+ category="so",
+ description="NO PEDESTRIANS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B7,
+ },
+ [0x1F6B8]={
+ category="so",
+ description="CHILDREN CROSSING",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B8,
+ },
+ [0x1F6B9]={
+ category="so",
+ description="MENS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6B9,
+ },
+ [0x1F6BA]={
+ category="so",
+ description="WOMENS SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6BA,
+ },
+ [0x1F6BB]={
+ category="so",
+ description="RESTROOM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6BB,
+ },
+ [0x1F6BC]={
+ category="so",
+ description="BABY SYMBOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6BC,
+ },
+ [0x1F6BD]={
+ category="so",
+ description="TOILET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6BD,
+ },
+ [0x1F6BE]={
+ category="so",
+ description="WATER CLOSET",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6BE,
+ },
+ [0x1F6BF]={
+ category="so",
+ description="SHOWER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6BF,
+ },
+ [0x1F6C0]={
+ category="so",
+ description="BATH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6C0,
+ },
+ [0x1F6C1]={
+ category="so",
+ description="BATHTUB",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6C1,
+ },
+ [0x1F6C2]={
+ category="so",
+ description="PASSPORT CONTROL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6C2,
+ },
+ [0x1F6C3]={
+ category="so",
+ description="CUSTOMS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6C3,
+ },
+ [0x1F6C4]={
+ category="so",
+ description="BAGGAGE CLAIM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6C4,
+ },
+ [0x1F6C5]={
+ category="so",
+ description="LEFT LUGGAGE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F6C5,
+ },
+ [0x1F700]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR QUINTESSENCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F700,
+ },
+ [0x1F701]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AIR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F701,
+ },
+ [0x1F702]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR FIRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F702,
+ },
+ [0x1F703]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR EARTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F703,
+ },
+ [0x1F704]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR WATER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F704,
+ },
+ [0x1F705]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUAFORTIS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F705,
+ },
+ [0x1F706]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUA REGIA",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F706,
+ },
+ [0x1F707]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUA REGIA-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F707,
+ },
+ [0x1F708]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUA VITAE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F708,
+ },
+ [0x1F709]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AQUA VITAE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F709,
+ },
+ [0x1F70A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VINEGAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70A,
+ },
+ [0x1F70B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VINEGAR-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70B,
+ },
+ [0x1F70C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VINEGAR-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70C,
+ },
+ [0x1F70D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SULFUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70D,
+ },
+ [0x1F70E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR PHILOSOPHERS SULFUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70E,
+ },
+ [0x1F70F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BLACK SULFUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F70F,
+ },
+ [0x1F710]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F710,
+ },
+ [0x1F711]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F711,
+ },
+ [0x1F712]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F712,
+ },
+ [0x1F713]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CINNABAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F713,
+ },
+ [0x1F714]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SALT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F714,
+ },
+ [0x1F715]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR NITRE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F715,
+ },
+ [0x1F716]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VITRIOL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F716,
+ },
+ [0x1F717]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VITRIOL-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F717,
+ },
+ [0x1F718]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ROCK SALT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F718,
+ },
+ [0x1F719]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ROCK SALT-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F719,
+ },
+ [0x1F71A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR GOLD",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71A,
+ },
+ [0x1F71B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SILVER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71B,
+ },
+ [0x1F71C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR IRON ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71C,
+ },
+ [0x1F71D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR IRON ORE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71D,
+ },
+ [0x1F71E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CROCUS OF IRON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71E,
+ },
+ [0x1F71F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS OF IRON",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F71F,
+ },
+ [0x1F720]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR COPPER ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F720,
+ },
+ [0x1F721]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR IRON-COPPER ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F721,
+ },
+ [0x1F722]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATE OF COPPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F722,
+ },
+ [0x1F723]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CROCUS OF COPPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F723,
+ },
+ [0x1F724]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CROCUS OF COPPER-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F724,
+ },
+ [0x1F725]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR COPPER ANTIMONIATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F725,
+ },
+ [0x1F726]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SALT OF COPPER ANTIMONIATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F726,
+ },
+ [0x1F727]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF COPPER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F727,
+ },
+ [0x1F728]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VERDIGRIS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F728,
+ },
+ [0x1F729]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TIN ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F729,
+ },
+ [0x1F72A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR LEAD ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72A,
+ },
+ [0x1F72B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ANTIMONY ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72B,
+ },
+ [0x1F72C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATE OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72C,
+ },
+ [0x1F72D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SALT OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72D,
+ },
+ [0x1F72E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72E,
+ },
+ [0x1F72F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR VINEGAR OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F72F,
+ },
+ [0x1F730]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F730,
+ },
+ [0x1F731]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F731,
+ },
+ [0x1F732]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F732,
+ },
+ [0x1F733]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F733,
+ },
+ [0x1F734]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F734,
+ },
+ [0x1F735]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REGULUS-4",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F735,
+ },
+ [0x1F736]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ALKALI",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F736,
+ },
+ [0x1F737]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ALKALI-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F737,
+ },
+ [0x1F738]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MARCASITE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F738,
+ },
+ [0x1F739]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SAL-AMMONIAC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F739,
+ },
+ [0x1F73A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ARSENIC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73A,
+ },
+ [0x1F73B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REALGAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73B,
+ },
+ [0x1F73C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR REALGAR-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73C,
+ },
+ [0x1F73D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AURIPIGMENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73D,
+ },
+ [0x1F73E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BISMUTH ORE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73E,
+ },
+ [0x1F73F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TARTAR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F73F,
+ },
+ [0x1F740]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TARTAR-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F740,
+ },
+ [0x1F741]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR QUICK LIME",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F741,
+ },
+ [0x1F742]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BORAX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F742,
+ },
+ [0x1F743]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BORAX-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F743,
+ },
+ [0x1F744]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BORAX-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F744,
+ },
+ [0x1F745]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ALUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F745,
+ },
+ [0x1F746]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR OIL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F746,
+ },
+ [0x1F747]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SPIRIT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F747,
+ },
+ [0x1F748]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TINCTURE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F748,
+ },
+ [0x1F749]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR GUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F749,
+ },
+ [0x1F74A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR WAX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74A,
+ },
+ [0x1F74B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR POWDER",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74B,
+ },
+ [0x1F74C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CALX",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74C,
+ },
+ [0x1F74D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TUTTY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74D,
+ },
+ [0x1F74E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CAPUT MORTUUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74E,
+ },
+ [0x1F74F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SCEPTER OF JOVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F74F,
+ },
+ [0x1F750]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CADUCEUS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F750,
+ },
+ [0x1F751]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR TRIDENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F751,
+ },
+ [0x1F752]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR STARRED TRIDENT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F752,
+ },
+ [0x1F753]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR LODESTONE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F753,
+ },
+ [0x1F754]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SOAP",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F754,
+ },
+ [0x1F755]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR URINE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F755,
+ },
+ [0x1F756]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR HORSE DUNG",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F756,
+ },
+ [0x1F757]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ASHES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F757,
+ },
+ [0x1F758]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR POT ASHES",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F758,
+ },
+ [0x1F759]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BRICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F759,
+ },
+ [0x1F75A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR POWDERED BRICK",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75A,
+ },
+ [0x1F75B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR AMALGAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75B,
+ },
+ [0x1F75C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75C,
+ },
+ [0x1F75D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75D,
+ },
+ [0x1F75E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR SUBLIMATION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75E,
+ },
+ [0x1F75F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR PRECIPITATE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F75F,
+ },
+ [0x1F760]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR DISTILL",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F760,
+ },
+ [0x1F761]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR DISSOLVE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F761,
+ },
+ [0x1F762]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR DISSOLVE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F762,
+ },
+ [0x1F763]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR PURIFY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F763,
+ },
+ [0x1F764]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR PUTREFACTION",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F764,
+ },
+ [0x1F765]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F765,
+ },
+ [0x1F766]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE-2",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F766,
+ },
+ [0x1F767]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE-3",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F767,
+ },
+ [0x1F768]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE-4",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F768,
+ },
+ [0x1F769]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR CRUCIBLE-5",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F769,
+ },
+ [0x1F76A]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR ALEMBIC",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76A,
+ },
+ [0x1F76B]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BATH OF MARY",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76B,
+ },
+ [0x1F76C]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR BATH OF VAPOURS",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76C,
+ },
+ [0x1F76D]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR RETORT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76D,
+ },
+ [0x1F76E]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR HOUR",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76E,
+ },
+ [0x1F76F]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR NIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F76F,
+ },
+ [0x1F770]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR DAY-NIGHT",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F770,
+ },
+ [0x1F771]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR MONTH",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F771,
+ },
+ [0x1F772]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR HALF DRAM",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F772,
+ },
+ [0x1F773]={
+ category="so",
+ description="ALCHEMICAL SYMBOL FOR HALF OUNCE",
+ direction="on",
+ linebreak="al",
+ unicodeslot=0x1F773,
+ },
[0x2F800]={
category="lo",
cjkwd="w",
diff --git a/Master/texmf-dist/tex/context/base/char-enc.mkiv b/Master/texmf-dist/tex/context/base/char-enc.mkiv
index 9fe9a363bdb..86ab2591a41 100644
--- a/Master/texmf-dist/tex/context/base/char-enc.mkiv
+++ b/Master/texmf-dist/tex/context/base/char-enc.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Encodings,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/char-ent.lua b/Master/texmf-dist/tex/context/base/char-ent.lua
new file mode 100644
index 00000000000..d2ac22bbf2c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/char-ent.lua
@@ -0,0 +1,2257 @@
+if not modules then modules = { } end modules ['math-ent'] = {
+ version = 1.001,
+ comment = "companion to math-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "derived from the mathml 2.0 specification",
+}
+
+-- http://www.w3.org/2003/entities/2007/w3centities-f.ent
+-- http://www.w3.org/2003/entities/2007/htmlmathml-f.ent
+
+-- this might go into char-def
+
+local entities = utilities.storage.allocate {
+ ["AElig"] = "Æ", -- U+000C6
+ ["AMP"] = "&", -- U+00026
+ ["Aacgr"] = "Ά", -- U+00386
+ ["Aacute"] = "Ã", -- U+000C1
+ ["Abreve"] = "Ä‚", -- U+00102
+ ["Acirc"] = "Â", -- U+000C2
+ ["Acy"] = "Ð", -- U+00410
+ ["Afr"] = "ð”„", -- U+1D504
+ ["Agr"] = "Α", -- U+00391
+ ["Agrave"] = "À", -- U+000C0
+ ["Alpha"] = "Α", -- U+00391
+ ["Amacr"] = "Ä€", -- U+00100
+ ["And"] = "â©“", -- U+02A53
+ ["Aogon"] = "Ä„", -- U+00104
+ ["Aopf"] = "ð”¸", -- U+1D538
+ ["ApplyFunction"] = "â¡", -- U+02061
+ ["Aring"] = "Ã…", -- U+000C5
+ ["Ascr"] = "ð’œ", -- U+1D49C
+ ["Assign"] = "≔", -- U+02254
+ ["Atilde"] = "Ã", -- U+000C3
+ ["Auml"] = "Ä", -- U+000C4
+ ["Backslash"] = "∖", -- U+02216
+ ["Barv"] = "⫧", -- U+02AE7
+ ["Barwed"] = "⌆", -- U+02306
+ ["Bcy"] = "Б", -- U+00411
+ ["Because"] = "∵", -- U+02235
+ ["Bernoullis"] = "ℬ", -- U+0212C
+ ["Beta"] = "Î’", -- U+00392
+ ["Bfr"] = "ð”…", -- U+1D505
+ ["Bgr"] = "Î’", -- U+00392
+ ["Bopf"] = "ð”¹", -- U+1D539
+ ["Breve"] = "˘", -- U+002D8
+ ["Bscr"] = "ℬ", -- U+0212C
+ ["Bumpeq"] = "≎", -- U+0224E
+ ["CHcy"] = "Ч", -- U+00427
+ ["COPY"] = "©", -- U+000A9
+ ["Cacute"] = "Ć", -- U+00106
+ ["Cap"] = "â‹’", -- U+022D2
+ ["CapitalDifferentialD"] = "â……", -- U+02145
+ ["Cayleys"] = "â„­", -- U+0212D
+ ["Ccaron"] = "Č", -- U+0010C
+ ["Ccedil"] = "Ç", -- U+000C7
+ ["Ccirc"] = "Ĉ", -- U+00108
+ ["Cconint"] = "∰", -- U+02230
+ ["Cdot"] = "ÄŠ", -- U+0010A
+ ["Cedilla"] = "¸", -- U+000B8
+ ["CenterDot"] = "·", -- U+000B7
+ ["Cfr"] = "â„­", -- U+0212D
+ ["Chi"] = "Χ", -- U+003A7
+ ["CircleDot"] = "⊙", -- U+02299
+ ["CircleMinus"] = "⊖", -- U+02296
+ ["CirclePlus"] = "⊕", -- U+02295
+ ["CircleTimes"] = "⊗", -- U+02297
+ ["ClockwiseContourIntegral"] = "∲", -- U+02232
+ ["CloseCurlyDoubleQuote"] = "â€", -- U+0201D
+ ["CloseCurlyQuote"] = "’", -- U+02019
+ ["Colon"] = "∷", -- U+02237
+ ["Colone"] = "â©´", -- U+02A74
+ ["Congruent"] = "≡", -- U+02261
+ ["Conint"] = "∯", -- U+0222F
+ ["ContourIntegral"] = "∮", -- U+0222E
+ ["Copf"] = "â„‚", -- U+02102
+ ["Coproduct"] = "âˆ", -- U+02210
+ ["CounterClockwiseContourIntegral"] = "∳", -- U+02233
+ ["Cross"] = "⨯", -- U+02A2F
+ ["Cscr"] = "ð’ž", -- U+1D49E
+ ["Cup"] = "â‹“", -- U+022D3
+ ["CupCap"] = "â‰", -- U+0224D
+ ["DD"] = "â……", -- U+02145
+ ["DDotrahd"] = "⤑", -- U+02911
+ ["DJcy"] = "Ђ", -- U+00402
+ ["DScy"] = "Ð…", -- U+00405
+ ["DZcy"] = "Ð", -- U+0040F
+ ["Dagger"] = "‡", -- U+02021
+ ["Darr"] = "↡", -- U+021A1
+ ["Dashv"] = "⫤", -- U+02AE4
+ ["Dcaron"] = "ÄŽ", -- U+0010E
+ ["Dcy"] = "Д", -- U+00414
+ ["Del"] = "∇", -- U+02207
+ ["Delta"] = "Δ", -- U+00394
+ ["Dfr"] = "ð”‡", -- U+1D507
+ ["Dgr"] = "Δ", -- U+00394
+ ["DiacriticalAcute"] = "´", -- U+000B4
+ ["DiacriticalDot"] = "Ë™", -- U+002D9
+ ["DiacriticalDoubleAcute"] = "Ë", -- U+002DD
+ ["DiacriticalGrave"] = "`", -- U+00060
+ ["DiacriticalTilde"] = "˜", -- U+002DC
+ ["Diamond"] = "â‹„", -- U+022C4
+ ["DifferentialD"] = "â…†", -- U+02146
+ ["Dopf"] = "ð”»", -- U+1D53B
+ ["Dot"] = "¨", -- U+000A8
+ ["DotDot"] = "⃜", -- U+020DC
+ ["DotEqual"] = "â‰", -- U+02250
+ ["DoubleContourIntegral"] = "∯", -- U+0222F
+ ["DoubleDot"] = "¨", -- U+000A8
+ ["DoubleDownArrow"] = "⇓", -- U+021D3
+ ["DoubleLeftArrow"] = "â‡", -- U+021D0
+ ["DoubleLeftRightArrow"] = "⇔", -- U+021D4
+ ["DoubleLeftTee"] = "⫤", -- U+02AE4
+ ["DoubleLongLeftArrow"] = "⟸", -- U+027F8
+ ["DoubleLongLeftRightArrow"] = "⟺", -- U+027FA
+ ["DoubleLongRightArrow"] = "⟹", -- U+027F9
+ ["DoubleRightArrow"] = "⇒", -- U+021D2
+ ["DoubleRightTee"] = "⊨", -- U+022A8
+ ["DoubleUpArrow"] = "⇑", -- U+021D1
+ ["DoubleUpDownArrow"] = "⇕", -- U+021D5
+ ["DoubleVerticalBar"] = "∥", -- U+02225
+ ["DownArrow"] = "↓", -- U+02193
+ ["DownArrowBar"] = "⤓", -- U+02913
+ ["DownArrowUpArrow"] = "⇵", -- U+021F5
+ ["DownBreve"] = "Ì‘", -- U+00311
+ ["DownLeftRightVector"] = "â¥", -- U+02950
+ ["DownLeftTeeVector"] = "⥞", -- U+0295E
+ ["DownLeftVector"] = "↽", -- U+021BD
+ ["DownLeftVectorBar"] = "⥖", -- U+02956
+ ["DownRightTeeVector"] = "⥟", -- U+0295F
+ ["DownRightVector"] = "â‡", -- U+021C1
+ ["DownRightVectorBar"] = "⥗", -- U+02957
+ ["DownTee"] = "⊤", -- U+022A4
+ ["DownTeeArrow"] = "↧", -- U+021A7
+ ["Downarrow"] = "⇓", -- U+021D3
+ ["Dscr"] = "ð’Ÿ", -- U+1D49F
+ ["Dstrok"] = "Ä", -- U+00110
+ ["EEacgr"] = "Ή", -- U+00389
+ ["EEgr"] = "Η", -- U+00397
+ ["ENG"] = "ÅŠ", -- U+0014A
+ ["ETH"] = "Ã", -- U+000D0
+ ["Eacgr"] = "Έ", -- U+00388
+ ["Eacute"] = "É", -- U+000C9
+ ["Ecaron"] = "Äš", -- U+0011A
+ ["Ecirc"] = "Ê", -- U+000CA
+ ["Ecy"] = "Э", -- U+0042D
+ ["Edot"] = "Ä–", -- U+00116
+ ["Efr"] = "ð”ˆ", -- U+1D508
+ ["Egr"] = "Ε", -- U+00395
+ ["Egrave"] = "È", -- U+000C8
+ ["Element"] = "∈", -- U+02208
+ ["Emacr"] = "Ä’", -- U+00112
+ ["EmptySmallSquare"] = "â—»", -- U+025FB
+ ["EmptyVerySmallSquare"] = "â–«", -- U+025AB
+ ["Eogon"] = "Ę", -- U+00118
+ ["Eopf"] = "ð”¼", -- U+1D53C
+ ["Epsilon"] = "Ε", -- U+00395
+ ["Equal"] = "⩵", -- U+02A75
+ ["EqualTilde"] = "≂", -- U+02242
+ ["Equilibrium"] = "⇌", -- U+021CC
+ ["Escr"] = "â„°", -- U+02130
+ ["Esim"] = "⩳", -- U+02A73
+ ["Eta"] = "Η", -- U+00397
+ ["Euml"] = "Ë", -- U+000CB
+ ["Exists"] = "∃", -- U+02203
+ ["ExponentialE"] = "â…‡", -- U+02147
+ ["Fcy"] = "Ф", -- U+00424
+ ["Ffr"] = "ð”‰", -- U+1D509
+ ["FilledSmallSquare"] = "â—¼", -- U+025FC
+ ["FilledVerySmallSquare"] = "â–ª", -- U+025AA
+ ["Fopf"] = "ð”½", -- U+1D53D
+ ["ForAll"] = "∀", -- U+02200
+ ["Fouriertrf"] = "ℱ", -- U+02131
+ ["Fscr"] = "ℱ", -- U+02131
+ ["GJcy"] = "Ѓ", -- U+00403
+ ["GT"] = ">", -- U+0003E
+ ["Gamma"] = "Γ", -- U+00393
+ ["Gammad"] = "Ϝ", -- U+003DC
+ ["Gbreve"] = "Äž", -- U+0011E
+ ["Gcedil"] = "Ä¢", -- U+00122
+ ["Gcirc"] = "Ĝ", -- U+0011C
+ ["Gcy"] = "Г", -- U+00413
+ ["Gdot"] = "Ä ", -- U+00120
+ ["Gfr"] = "ð”Š", -- U+1D50A
+ ["Gg"] = "â‹™", -- U+022D9
+ ["Ggr"] = "Γ", -- U+00393
+ ["Gopf"] = "ð”¾", -- U+1D53E
+ ["GreaterEqual"] = "≥", -- U+02265
+ ["GreaterEqualLess"] = "â‹›", -- U+022DB
+ ["GreaterFullEqual"] = "≧", -- U+02267
+ ["GreaterGreater"] = "⪢", -- U+02AA2
+ ["GreaterLess"] = "≷", -- U+02277
+ ["GreaterSlantEqual"] = "⩾", -- U+02A7E
+ ["GreaterTilde"] = "≳", -- U+02273
+ ["Gscr"] = "ð’¢", -- U+1D4A2
+ ["Gt"] = "≫", -- U+0226B
+ ["HARDcy"] = "Ъ", -- U+0042A
+ ["Hacek"] = "ˇ", -- U+002C7
+ ["Hat"] = "^", -- U+0005E
+ ["Hcirc"] = "Ĥ", -- U+00124
+ ["Hfr"] = "ℌ", -- U+0210C
+ ["HilbertSpace"] = "â„‹", -- U+0210B
+ ["Hopf"] = "â„", -- U+0210D
+ ["HorizontalLine"] = "─", -- U+02500
+ ["Hscr"] = "â„‹", -- U+0210B
+ ["Hstrok"] = "Ħ", -- U+00126
+ ["HumpDownHump"] = "≎", -- U+0224E
+ ["HumpEqual"] = "â‰", -- U+0224F
+ ["IEcy"] = "Е", -- U+00415
+ ["IJlig"] = "IJ", -- U+00132
+ ["IOcy"] = "Ð", -- U+00401
+ ["Iacgr"] = "Ί", -- U+0038A
+ ["Iacute"] = "Ã", -- U+000CD
+ ["Icirc"] = "ÃŽ", -- U+000CE
+ ["Icy"] = "И", -- U+00418
+ ["Idigr"] = "Ϊ", -- U+003AA
+ ["Idot"] = "Ä°", -- U+00130
+ ["Ifr"] = "â„‘", -- U+02111
+ ["Igr"] = "Ι", -- U+00399
+ ["Igrave"] = "Ì", -- U+000CC
+ ["Im"] = "â„‘", -- U+02111
+ ["Imacr"] = "Ī", -- U+0012A
+ ["ImaginaryI"] = "â…ˆ", -- U+02148
+ ["Implies"] = "⇒", -- U+021D2
+ ["Int"] = "∬", -- U+0222C
+ ["Integral"] = "∫", -- U+0222B
+ ["Intersection"] = "â‹‚", -- U+022C2
+ ["InvisibleComma"] = "â£", -- U+02063
+ ["InvisibleTimes"] = "â¢", -- U+02062
+ ["Iogon"] = "Ä®", -- U+0012E
+ ["Iopf"] = "ð•€", -- U+1D540
+ ["Iota"] = "Ι", -- U+00399
+ ["Iscr"] = "â„", -- U+02110
+ ["Itilde"] = "Ĩ", -- U+00128
+ ["Iukcy"] = "І", -- U+00406
+ ["Iuml"] = "Ã", -- U+000CF
+ ["Jcirc"] = "Ä´", -- U+00134
+ ["Jcy"] = "Й", -- U+00419
+ ["Jfr"] = "ð”", -- U+1D50D
+ ["Jopf"] = "ð•", -- U+1D541
+ ["Jscr"] = "ð’¥", -- U+1D4A5
+ ["Jsercy"] = "Ј", -- U+00408
+ ["Jukcy"] = "Є", -- U+00404
+ ["KHcy"] = "Ð¥", -- U+00425
+ ["KHgr"] = "Χ", -- U+003A7
+ ["KJcy"] = "Ќ", -- U+0040C
+ ["Kappa"] = "Κ", -- U+0039A
+ ["Kcedil"] = "Ķ", -- U+00136
+ ["Kcy"] = "К", -- U+0041A
+ ["Kfr"] = "ð”Ž", -- U+1D50E
+ ["Kgr"] = "Κ", -- U+0039A
+ ["Kopf"] = "ð•‚", -- U+1D542
+ ["Kscr"] = "ð’¦", -- U+1D4A6
+ ["LJcy"] = "Љ", -- U+00409
+ ["LT"] = "<", -- U+00026
+ ["Lacute"] = "Ĺ", -- U+00139
+ ["Lambda"] = "Λ", -- U+0039B
+ ["Lang"] = "⟪", -- U+027EA
+ ["Laplacetrf"] = "â„’", -- U+02112
+ ["Larr"] = "↞", -- U+0219E
+ ["Lcaron"] = "Ľ", -- U+0013D
+ ["Lcedil"] = "Ä»", -- U+0013B
+ ["Lcy"] = "Л", -- U+0041B
+ ["LeftAngleBracket"] = "⟨", -- U+027E8
+ ["LeftArrow"] = "â†", -- U+02190
+ ["LeftArrowBar"] = "⇤", -- U+021E4
+ ["LeftArrowRightArrow"] = "⇆", -- U+021C6
+ ["LeftCeiling"] = "⌈", -- U+02308
+ ["LeftDoubleBracket"] = "⟦", -- U+027E6
+ ["LeftDownTeeVector"] = "⥡", -- U+02961
+ ["LeftDownVector"] = "⇃", -- U+021C3
+ ["LeftDownVectorBar"] = "⥙", -- U+02959
+ ["LeftFloor"] = "⌊", -- U+0230A
+ ["LeftRightArrow"] = "↔", -- U+02194
+ ["LeftRightVector"] = "⥎", -- U+0294E
+ ["LeftTee"] = "⊣", -- U+022A3
+ ["LeftTeeArrow"] = "↤", -- U+021A4
+ ["LeftTeeVector"] = "⥚", -- U+0295A
+ ["LeftTriangle"] = "⊲", -- U+022B2
+ ["LeftTriangleBar"] = "â§", -- U+029CF
+ ["LeftTriangleEqual"] = "⊴", -- U+022B4
+ ["LeftUpDownVector"] = "⥑", -- U+02951
+ ["LeftUpTeeVector"] = "⥠", -- U+02960
+ ["LeftUpVector"] = "↿", -- U+021BF
+ ["LeftUpVectorBar"] = "⥘", -- U+02958
+ ["LeftVector"] = "↼", -- U+021BC
+ ["LeftVectorBar"] = "⥒", -- U+02952
+ ["Leftarrow"] = "â‡", -- U+021D0
+ ["Leftrightarrow"] = "⇔", -- U+021D4
+ ["LessEqualGreater"] = "â‹š", -- U+022DA
+ ["LessFullEqual"] = "≦", -- U+02266
+ ["LessGreater"] = "≶", -- U+02276
+ ["LessLess"] = "⪡", -- U+02AA1
+ ["LessSlantEqual"] = "⩽", -- U+02A7D
+ ["LessTilde"] = "≲", -- U+02272
+ ["Lfr"] = "ð”", -- U+1D50F
+ ["Lgr"] = "Λ", -- U+0039B
+ ["Ll"] = "⋘", -- U+022D8
+ ["Lleftarrow"] = "⇚", -- U+021DA
+ ["Lmidot"] = "Ä¿", -- U+0013F
+ ["LongLeftArrow"] = "⟵", -- U+027F5
+ ["LongLeftRightArrow"] = "⟷", -- U+027F7
+ ["LongRightArrow"] = "⟶", -- U+027F6
+ ["Longleftarrow"] = "⟸", -- U+027F8
+ ["Longleftrightarrow"] = "⟺", -- U+027FA
+ ["Longrightarrow"] = "⟹", -- U+027F9
+ ["Lopf"] = "ð•ƒ", -- U+1D543
+ ["LowerLeftArrow"] = "↙", -- U+02199
+ ["LowerRightArrow"] = "↘", -- U+02198
+ ["Lscr"] = "â„’", -- U+02112
+ ["Lsh"] = "↰", -- U+021B0
+ ["Lstrok"] = "Å", -- U+00141
+ ["Lt"] = "≪", -- U+0226A
+ ["Map"] = "⤅", -- U+02905
+ ["Mcy"] = "М", -- U+0041C
+ ["MediumSpace"] = "âŸ", -- U+0205F
+ ["Mellintrf"] = "ℳ", -- U+02133
+ ["Mfr"] = "ð”", -- U+1D510
+ ["Mgr"] = "Μ", -- U+0039C
+ ["MinusPlus"] = "∓", -- U+02213
+ ["Mopf"] = "ð•„", -- U+1D544
+ ["Mscr"] = "ℳ", -- U+02133
+ ["Mu"] = "Μ", -- U+0039C
+ ["NJcy"] = "Њ", -- U+0040A
+ ["Nacute"] = "Ń", -- U+00143
+ ["Ncaron"] = "Ň", -- U+00147
+ ["Ncedil"] = "Å…", -- U+00145
+ ["Ncy"] = "Ð", -- U+0041D
+ ["NegativeMediumSpace"] = "​", -- U+0200B
+ ["NegativeThickSpace"] = "​", -- U+0200B
+ ["NegativeThinSpace"] = "​", -- U+0200B
+ ["NegativeVeryThinSpace"] = "​", -- U+0200B
+ ["NestedGreaterGreater"] = "≫", -- U+0226B
+ ["NestedLessLess"] = "≪", -- U+0226A
+ ["Nfr"] = "ð”‘", -- U+1D511
+ ["Ngr"] = "Î", -- U+0039D
+ ["NoBreak"] = "â ", -- U+02060
+ ["NonBreakingSpace"] = " ", -- U+000A0
+ ["Nopf"] = "â„•", -- U+02115
+ ["Not"] = "⫬", -- U+02AEC
+ ["NotCongruent"] = "≢", -- U+02262
+ ["NotCupCap"] = "≭", -- U+0226D
+ ["NotDoubleVerticalBar"] = "∦", -- U+02226
+ ["NotElement"] = "∉", -- U+02209
+ ["NotEqual"] = "≠", -- U+02260
+ ["NotEqualTilde"] = "≂̸", -- U+02242 00338
+ ["NotExists"] = "∄", -- U+02204
+ ["NotGreater"] = "≯", -- U+0226F
+ ["NotGreaterEqual"] = "≱", -- U+02271
+ ["NotGreaterFullEqual"] = "≧̸", -- U+02267 00338
+ ["NotGreaterGreater"] = "≫̸", -- U+0226B 00338
+ ["NotGreaterLess"] = "≹", -- U+02279
+ ["NotGreaterSlantEqual"] = "⩾̸", -- U+02A7E 00338
+ ["NotGreaterTilde"] = "≵", -- U+02275
+ ["NotHumpDownHump"] = "≎̸", -- U+0224E 00338
+ ["NotHumpEqual"] = "â‰Ì¸", -- U+0224F 00338
+ ["NotLeftTriangle"] = "⋪", -- U+022EA
+ ["NotLeftTriangleBar"] = "â§Ì¸", -- U+029CF 00338
+ ["NotLeftTriangleEqual"] = "⋬", -- U+022EC
+ ["NotLess"] = "≮", -- U+0226E
+ ["NotLessEqual"] = "≰", -- U+02270
+ ["NotLessGreater"] = "≸", -- U+02278
+ ["NotLessLess"] = "≪̸", -- U+0226A 00338
+ ["NotLessSlantEqual"] = "⩽̸", -- U+02A7D 00338
+ ["NotLessTilde"] = "≴", -- U+02274
+ ["NotNestedGreaterGreater"] = "⪢̸", -- U+02AA2 00338
+ ["NotNestedLessLess"] = "⪡̸", -- U+02AA1 00338
+ ["NotPrecedes"] = "⊀", -- U+02280
+ ["NotPrecedesEqual"] = "⪯̸", -- U+02AAF 00338
+ ["NotPrecedesSlantEqual"] = "â‹ ", -- U+022E0
+ ["NotReverseElement"] = "∌", -- U+0220C
+ ["NotRightTriangle"] = "â‹«", -- U+022EB
+ ["NotRightTriangleBar"] = "â§Ì¸", -- U+029D0 00338
+ ["NotRightTriangleEqual"] = "â‹­", -- U+022ED
+ ["NotSquareSubset"] = "âŠÌ¸", -- U+0228F 00338
+ ["NotSquareSubsetEqual"] = "â‹¢", -- U+022E2
+ ["NotSquareSuperset"] = "âŠÌ¸", -- U+02290 00338
+ ["NotSquareSupersetEqual"] = "â‹£", -- U+022E3
+ ["NotSubset"] = "⊂⃒", -- U+02282 020D2
+ ["NotSubsetEqual"] = "⊈", -- U+02288
+ ["NotSucceeds"] = "âŠ", -- U+02281
+ ["NotSucceedsEqual"] = "⪰̸", -- U+02AB0 00338
+ ["NotSucceedsSlantEqual"] = "â‹¡", -- U+022E1
+ ["NotSucceedsTilde"] = "≿̸", -- U+0227F 00338
+ ["NotSuperset"] = "⊃⃒", -- U+02283 020D2
+ ["NotSupersetEqual"] = "⊉", -- U+02289
+ ["NotTilde"] = "â‰", -- U+02241
+ ["NotTildeEqual"] = "≄", -- U+02244
+ ["NotTildeFullEqual"] = "≇", -- U+02247
+ ["NotTildeTilde"] = "≉", -- U+02249
+ ["NotVerticalBar"] = "∤", -- U+02224
+ ["Nscr"] = "ð’©", -- U+1D4A9
+ ["Ntilde"] = "Ñ", -- U+000D1
+ ["Nu"] = "Î", -- U+0039D
+ ["OElig"] = "Å’", -- U+00152
+ ["OHacgr"] = "Î", -- U+0038F
+ ["OHgr"] = "Ω", -- U+003A9
+ ["Oacgr"] = "Ό", -- U+0038C
+ ["Oacute"] = "Ó", -- U+000D3
+ ["Ocirc"] = "Ô", -- U+000D4
+ ["Ocy"] = "О", -- U+0041E
+ ["Odblac"] = "Å", -- U+00150
+ ["Ofr"] = "ð”’", -- U+1D512
+ ["Ogr"] = "Ο", -- U+0039F
+ ["Ograve"] = "Ã’", -- U+000D2
+ ["Omacr"] = "Ō", -- U+0014C
+ ["Omega"] = "Ω", -- U+003A9
+ ["Omicron"] = "Ο", -- U+0039F
+ ["Oopf"] = "ð•†", -- U+1D546
+ ["OpenCurlyDoubleQuote"] = "“", -- U+0201C
+ ["OpenCurlyQuote"] = "‘", -- U+02018
+ ["Or"] = "â©”", -- U+02A54
+ ["Oscr"] = "ð’ª", -- U+1D4AA
+ ["Oslash"] = "Ø", -- U+000D8
+ ["Otilde"] = "Õ", -- U+000D5
+ ["Otimes"] = "⨷", -- U+02A37
+ ["Ouml"] = "Ö", -- U+000D6
+ ["OverBar"] = "‾", -- U+0203E
+ ["OverBrace"] = "âž", -- U+023DE
+ ["OverBracket"] = "⎴", -- U+023B4
+ ["OverParenthesis"] = "âœ", -- U+023DC
+ ["PHgr"] = "Φ", -- U+003A6
+ ["PSgr"] = "Ψ", -- U+003A8
+ ["PartialD"] = "∂", -- U+02202
+ ["Pcy"] = "П", -- U+0041F
+ ["Pfr"] = "ð”“", -- U+1D513
+ ["Pgr"] = "Π", -- U+003A0
+ ["Phi"] = "Φ", -- U+003A6
+ ["Pi"] = "Π", -- U+003A0
+ ["PlusMinus"] = "±", -- U+000B1
+ ["Poincareplane"] = "ℌ", -- U+0210C
+ ["Popf"] = "â„™", -- U+02119
+ ["Pr"] = "⪻", -- U+02ABB
+ ["Precedes"] = "≺", -- U+0227A
+ ["PrecedesEqual"] = "⪯", -- U+02AAF
+ ["PrecedesSlantEqual"] = "≼", -- U+0227C
+ ["PrecedesTilde"] = "≾", -- U+0227E
+ ["Prime"] = "″", -- U+02033
+ ["Product"] = "âˆ", -- U+0220F
+ ["Proportion"] = "∷", -- U+02237
+ ["Proportional"] = "âˆ", -- U+0221D
+ ["Pscr"] = "ð’«", -- U+1D4AB
+ ["Psi"] = "Ψ", -- U+003A8
+ ["QUOT"] = "\"", -- U+00022
+ ["Qfr"] = "ð””", -- U+1D514
+ ["Qopf"] = "â„š", -- U+0211A
+ ["Qscr"] = "ð’¬", -- U+1D4AC
+ ["RBarr"] = "â¤", -- U+02910
+ ["REG"] = "®", -- U+000AE
+ ["Racute"] = "Å”", -- U+00154
+ ["Rang"] = "⟫", -- U+027EB
+ ["Rarr"] = "↠", -- U+021A0
+ ["Rarrtl"] = "⤖", -- U+02916
+ ["Rcaron"] = "Ř", -- U+00158
+ ["Rcedil"] = "Å–", -- U+00156
+ ["Rcy"] = "Р", -- U+00420
+ ["Re"] = "ℜ", -- U+0211C
+ ["ReverseElement"] = "∋", -- U+0220B
+ ["ReverseEquilibrium"] = "⇋", -- U+021CB
+ ["ReverseUpEquilibrium"] = "⥯", -- U+0296F
+ ["Rfr"] = "ℜ", -- U+0211C
+ ["Rgr"] = "Ρ", -- U+003A1
+ ["Rho"] = "Ρ", -- U+003A1
+ ["RightAngleBracket"] = "⟩", -- U+027E9
+ ["RightArrow"] = "→", -- U+02192
+ ["RightArrowBar"] = "⇥", -- U+021E5
+ ["RightArrowLeftArrow"] = "⇄", -- U+021C4
+ ["RightCeiling"] = "⌉", -- U+02309
+ ["RightDoubleBracket"] = "⟧", -- U+027E7
+ ["RightDownTeeVector"] = "â¥", -- U+0295D
+ ["RightDownVector"] = "⇂", -- U+021C2
+ ["RightDownVectorBar"] = "⥕", -- U+02955
+ ["RightFloor"] = "⌋", -- U+0230B
+ ["RightTee"] = "⊢", -- U+022A2
+ ["RightTeeArrow"] = "↦", -- U+021A6
+ ["RightTeeVector"] = "⥛", -- U+0295B
+ ["RightTriangle"] = "⊳", -- U+022B3
+ ["RightTriangleBar"] = "â§", -- U+029D0
+ ["RightTriangleEqual"] = "⊵", -- U+022B5
+ ["RightUpDownVector"] = "â¥", -- U+0294F
+ ["RightUpTeeVector"] = "⥜", -- U+0295C
+ ["RightUpVector"] = "↾", -- U+021BE
+ ["RightUpVectorBar"] = "⥔", -- U+02954
+ ["RightVector"] = "⇀", -- U+021C0
+ ["RightVectorBar"] = "⥓", -- U+02953
+ ["Rightarrow"] = "⇒", -- U+021D2
+ ["Ropf"] = "â„", -- U+0211D
+ ["RoundImplies"] = "⥰", -- U+02970
+ ["Rrightarrow"] = "⇛", -- U+021DB
+ ["Rscr"] = "â„›", -- U+0211B
+ ["Rsh"] = "↱", -- U+021B1
+ ["RuleDelayed"] = "⧴", -- U+029F4
+ ["SHCHcy"] = "Щ", -- U+00429
+ ["SHcy"] = "Ш", -- U+00428
+ ["SOFTcy"] = "Ь", -- U+0042C
+ ["Sacute"] = "Åš", -- U+0015A
+ ["Sc"] = "⪼", -- U+02ABC
+ ["Scaron"] = "Å ", -- U+00160
+ ["Scedil"] = "Åž", -- U+0015E
+ ["Scirc"] = "Ŝ", -- U+0015C
+ ["Scy"] = "С", -- U+00421
+ ["Sfr"] = "ð”–", -- U+1D516
+ ["Sgr"] = "Σ", -- U+003A3
+ ["ShortDownArrow"] = "↓", -- U+02193
+ ["ShortLeftArrow"] = "â†", -- U+02190
+ ["ShortRightArrow"] = "→", -- U+02192
+ ["ShortUpArrow"] = "↑", -- U+02191
+ ["Sigma"] = "Σ", -- U+003A3
+ ["SmallCircle"] = "∘", -- U+02218
+ ["Sopf"] = "ð•Š", -- U+1D54A
+ ["Sqrt"] = "√", -- U+0221A
+ ["Square"] = "â–¡", -- U+025A1
+ ["SquareIntersection"] = "⊓", -- U+02293
+ ["SquareSubset"] = "âŠ", -- U+0228F
+ ["SquareSubsetEqual"] = "⊑", -- U+02291
+ ["SquareSuperset"] = "âŠ", -- U+02290
+ ["SquareSupersetEqual"] = "⊒", -- U+02292
+ ["SquareUnion"] = "⊔", -- U+02294
+ ["Sscr"] = "ð’®", -- U+1D4AE
+ ["Star"] = "⋆", -- U+022C6
+ ["Sub"] = "â‹", -- U+022D0
+ ["Subset"] = "â‹", -- U+022D0
+ ["SubsetEqual"] = "⊆", -- U+02286
+ ["Succeeds"] = "≻", -- U+0227B
+ ["SucceedsEqual"] = "⪰", -- U+02AB0
+ ["SucceedsSlantEqual"] = "≽", -- U+0227D
+ ["SucceedsTilde"] = "≿", -- U+0227F
+ ["SuchThat"] = "∋", -- U+0220B
+ ["Sum"] = "∑", -- U+02211
+ ["Sup"] = "â‹‘", -- U+022D1
+ ["Superset"] = "⊃", -- U+02283
+ ["SupersetEqual"] = "⊇", -- U+02287
+ ["Supset"] = "â‹‘", -- U+022D1
+ ["THORN"] = "Þ", -- U+000DE
+ ["THgr"] = "Θ", -- U+00398
+ ["TRADE"] = "â„¢", -- U+02122
+ ["TSHcy"] = "Ћ", -- U+0040B
+ ["TScy"] = "Ц", -- U+00426
+ ["Tab"] = "\9", -- U+00009
+ ["Tau"] = "Τ", -- U+003A4
+ ["Tcaron"] = "Ť", -- U+00164
+ ["Tcedil"] = "Å¢", -- U+00162
+ ["Tcy"] = "Т", -- U+00422
+ ["Tfr"] = "ð”—", -- U+1D517
+ ["Tgr"] = "Τ", -- U+003A4
+ ["Therefore"] = "∴", -- U+02234
+ ["Theta"] = "Θ", -- U+00398
+ ["ThickSpace"] = "âŸâ€Š", -- U+0205F 0200A
+ ["ThinSpace"] = " ", -- U+02009
+ ["Tilde"] = "∼", -- U+0223C
+ ["TildeEqual"] = "≃", -- U+02243
+ ["TildeFullEqual"] = "≅", -- U+02245
+ ["TildeTilde"] = "≈", -- U+02248
+ ["Topf"] = "ð•‹", -- U+1D54B
+ ["TripleDot"] = "⃛", -- U+020DB
+ ["Tscr"] = "ð’¯", -- U+1D4AF
+ ["Tstrok"] = "Ŧ", -- U+00166
+ ["Uacgr"] = "ÎŽ", -- U+0038E
+ ["Uacute"] = "Ú", -- U+000DA
+ ["Uarr"] = "↟", -- U+0219F
+ ["Uarrocir"] = "⥉", -- U+02949
+ ["Ubrcy"] = "ÐŽ", -- U+0040E
+ ["Ubreve"] = "Ŭ", -- U+0016C
+ ["Ucirc"] = "Û", -- U+000DB
+ ["Ucy"] = "У", -- U+00423
+ ["Udblac"] = "Å°", -- U+00170
+ ["Udigr"] = "Ϋ", -- U+003AB
+ ["Ufr"] = "ð”˜", -- U+1D518
+ ["Ugr"] = "Î¥", -- U+003A5
+ ["Ugrave"] = "Ù", -- U+000D9
+ ["Umacr"] = "Ū", -- U+0016A
+ ["UnderBar"] = "_", -- U+0005F
+ ["UnderBrace"] = "âŸ", -- U+023DF
+ ["UnderBracket"] = "⎵", -- U+023B5
+ ["UnderParenthesis"] = "â", -- U+023DD
+ ["Union"] = "⋃", -- U+022C3
+ ["UnionPlus"] = "⊎", -- U+0228E
+ ["Uogon"] = "Ų", -- U+00172
+ ["Uopf"] = "ð•Œ", -- U+1D54C
+ ["UpArrow"] = "↑", -- U+02191
+ ["UpArrowBar"] = "⤒", -- U+02912
+ ["UpArrowDownArrow"] = "⇅", -- U+021C5
+ ["UpDownArrow"] = "↕", -- U+02195
+ ["UpEquilibrium"] = "⥮", -- U+0296E
+ ["UpTee"] = "⊥", -- U+022A5
+ ["UpTeeArrow"] = "↥", -- U+021A5
+ ["Uparrow"] = "⇑", -- U+021D1
+ ["Updownarrow"] = "⇕", -- U+021D5
+ ["UpperLeftArrow"] = "↖", -- U+02196
+ ["UpperRightArrow"] = "↗", -- U+02197
+ ["Upsi"] = "Ï’", -- U+003D2
+ ["Upsilon"] = "Î¥", -- U+003A5
+ ["Uring"] = "Å®", -- U+0016E
+ ["Uscr"] = "ð’°", -- U+1D4B0
+ ["Utilde"] = "Ũ", -- U+00168
+ ["Uuml"] = "Ü", -- U+000DC
+ ["VDash"] = "⊫", -- U+022AB
+ ["Vbar"] = "â««", -- U+02AEB
+ ["Vcy"] = "Ð’", -- U+00412
+ ["Vdash"] = "⊩", -- U+022A9
+ ["Vdashl"] = "⫦", -- U+02AE6
+ ["Vee"] = "â‹", -- U+022C1
+ ["Verbar"] = "‖", -- U+02016
+ ["Vert"] = "‖", -- U+02016
+ ["VerticalBar"] = "∣", -- U+02223
+ ["VerticalLine"] = "|", -- U+0007C
+ ["VerticalSeparator"] = "â˜", -- U+02758
+ ["VerticalTilde"] = "≀", -- U+02240
+ ["VeryThinSpace"] = " ", -- U+0200A
+ ["Vfr"] = "ð”™", -- U+1D519
+ ["Vopf"] = "ð•", -- U+1D54D
+ ["Vscr"] = "ð’±", -- U+1D4B1
+ ["Vvdash"] = "⊪", -- U+022AA
+ ["Wcirc"] = "Å´", -- U+00174
+ ["Wedge"] = "â‹€", -- U+022C0
+ ["Wfr"] = "ð”š", -- U+1D51A
+ ["Wopf"] = "ð•Ž", -- U+1D54E
+ ["Wscr"] = "ð’²", -- U+1D4B2
+ ["Xfr"] = "ð”›", -- U+1D51B
+ ["Xgr"] = "Ξ", -- U+0039E
+ ["Xi"] = "Ξ", -- U+0039E
+ ["Xopf"] = "ð•", -- U+1D54F
+ ["Xscr"] = "ð’³", -- U+1D4B3
+ ["YAcy"] = "Я", -- U+0042F
+ ["YIcy"] = "Ї", -- U+00407
+ ["YUcy"] = "Ю", -- U+0042E
+ ["Yacute"] = "Ã", -- U+000DD
+ ["Ycirc"] = "Ŷ", -- U+00176
+ ["Ycy"] = "Ы", -- U+0042B
+ ["Yfr"] = "ð”œ", -- U+1D51C
+ ["Yopf"] = "ð•", -- U+1D550
+ ["Yscr"] = "ð’´", -- U+1D4B4
+ ["Yuml"] = "Ÿ", -- U+00178
+ ["ZHcy"] = "Ж", -- U+00416
+ ["Zacute"] = "Ź", -- U+00179
+ ["Zcaron"] = "Ž", -- U+0017D
+ ["Zcy"] = "З", -- U+00417
+ ["Zdot"] = "Å»", -- U+0017B
+ ["ZeroWidthSpace"] = "​", -- U+0200B
+ ["Zeta"] = "Ζ", -- U+00396
+ ["Zfr"] = "ℨ", -- U+02128
+ ["Zgr"] = "Ζ", -- U+00396
+ ["Zopf"] = "ℤ", -- U+02124
+ ["Zscr"] = "ð’µ", -- U+1D4B5
+ ["aacgr"] = "ά", -- U+003AC
+ ["aacute"] = "á", -- U+000E1
+ ["abreve"] = "ă", -- U+00103
+ ["ac"] = "∾", -- U+0223E
+ ["acE"] = "∾̳", -- U+0223E 00333
+ ["acd"] = "∿", -- U+0223F
+ ["acirc"] = "â", -- U+000E2
+ ["acute"] = "´", -- U+000B4
+ ["acy"] = "а", -- U+00430
+ ["aelig"] = "æ", -- U+000E6
+ ["af"] = "â¡", -- U+02061
+ ["afr"] = "ð”ž", -- U+1D51E
+ ["agr"] = "α", -- U+003B1
+ ["agrave"] = "à", -- U+000E0
+ ["alefsym"] = "ℵ", -- U+02135
+ ["aleph"] = "ℵ", -- U+02135
+ ["alpha"] = "α", -- U+003B1
+ ["amacr"] = "Ä", -- U+00101
+ ["amalg"] = "⨿", -- U+02A3F
+ ["amp"] = "&", -- U+00026
+ ["and"] = "∧", -- U+02227
+ ["andand"] = "â©•", -- U+02A55
+ ["andd"] = "⩜", -- U+02A5C
+ ["andslope"] = "⩘", -- U+02A58
+ ["andv"] = "â©š", -- U+02A5A
+ ["ang"] = "∠", -- U+02220
+ ["ange"] = "⦤", -- U+029A4
+ ["angle"] = "∠", -- U+02220
+ ["angmsd"] = "∡", -- U+02221
+ ["angmsdaa"] = "⦨", -- U+029A8
+ ["angmsdab"] = "⦩", -- U+029A9
+ ["angmsdac"] = "⦪", -- U+029AA
+ ["angmsdad"] = "⦫", -- U+029AB
+ ["angmsdae"] = "⦬", -- U+029AC
+ ["angmsdaf"] = "⦭", -- U+029AD
+ ["angmsdag"] = "⦮", -- U+029AE
+ ["angmsdah"] = "⦯", -- U+029AF
+ ["angrt"] = "∟", -- U+0221F
+ ["angrtvb"] = "⊾", -- U+022BE
+ ["angrtvbd"] = "â¦", -- U+0299D
+ ["angsph"] = "∢", -- U+02222
+ ["angst"] = "Ã…", -- U+000C5
+ ["angzarr"] = "â¼", -- U+0237C
+ ["aogon"] = "Ä…", -- U+00105
+ ["aopf"] = "ð•’", -- U+1D552
+ ["ap"] = "≈", -- U+02248
+ ["apE"] = "â©°", -- U+02A70
+ ["apacir"] = "⩯", -- U+02A6F
+ ["ape"] = "≊", -- U+0224A
+ ["apid"] = "≋", -- U+0224B
+ ["apos"] = "'", -- U+00027
+ ["approx"] = "≈", -- U+02248
+ ["approxeq"] = "≊", -- U+0224A
+ ["aring"] = "Ã¥", -- U+000E5
+ ["ascr"] = "ð’¶", -- U+1D4B6
+ ["ast"] = "*", -- U+0002A
+ ["asymp"] = "≈", -- U+02248
+ ["asympeq"] = "â‰", -- U+0224D
+ ["atilde"] = "ã", -- U+000E3
+ ["auml"] = "ä", -- U+000E4
+ ["awconint"] = "∳", -- U+02233
+ ["awint"] = "⨑", -- U+02A11
+ ["b.Delta"] = "ðš«", -- U+1D6AB
+ ["b.Gamma"] = "ðšª", -- U+1D6AA
+ ["b.Gammad"] = "ðŸŠ", -- U+1D7CA
+ ["b.Lambda"] = "ðš²", -- U+1D6B2
+ ["b.Omega"] = "ð›€", -- U+1D6C0
+ ["b.Phi"] = "ðš½", -- U+1D6BD
+ ["b.Pi"] = "ðš·", -- U+1D6B7
+ ["b.Psi"] = "ðš¿", -- U+1D6BF
+ ["b.Sigma"] = "ðšº", -- U+1D6BA
+ ["b.Theta"] = "ðš¯", -- U+1D6AF
+ ["b.Upsi"] = "ðš¼", -- U+1D6BC
+ ["b.Xi"] = "ðšµ", -- U+1D6B5
+ ["b.alpha"] = "ð›‚", -- U+1D6C2
+ ["b.beta"] = "ð›ƒ", -- U+1D6C3
+ ["b.chi"] = "ð›˜", -- U+1D6D8
+ ["b.delta"] = "ð›…", -- U+1D6C5
+ ["b.epsi"] = "ð›†", -- U+1D6C6
+ ["b.epsiv"] = "ð›œ", -- U+1D6DC
+ ["b.eta"] = "ð›ˆ", -- U+1D6C8
+ ["b.gamma"] = "ð›„", -- U+1D6C4
+ ["b.gammad"] = "ðŸ‹", -- U+1D7CB
+ ["b.iota"] = "ð›Š", -- U+1D6CA
+ ["b.kappa"] = "ð›‹", -- U+1D6CB
+ ["b.kappav"] = "ð›ž", -- U+1D6DE
+ ["b.lambda"] = "ð›Œ", -- U+1D6CC
+ ["b.mu"] = "ð›", -- U+1D6CD
+ ["b.nu"] = "ð›Ž", -- U+1D6CE
+ ["b.omega"] = "ð›š", -- U+1D6DA
+ ["b.phi"] = "ð›—", -- U+1D6D7
+ ["b.phiv"] = "ð›Ÿ", -- U+1D6DF
+ ["b.pi"] = "ð›‘", -- U+1D6D1
+ ["b.piv"] = "ð›¡", -- U+1D6E1
+ ["b.psi"] = "ð›™", -- U+1D6D9
+ ["b.rho"] = "ð›’", -- U+1D6D2
+ ["b.rhov"] = "ð› ", -- U+1D6E0
+ ["b.sigma"] = "ð›”", -- U+1D6D4
+ ["b.sigmav"] = "ð›“", -- U+1D6D3
+ ["b.tau"] = "ð›•", -- U+1D6D5
+ ["b.thetas"] = "ð›‰", -- U+1D6C9
+ ["b.thetav"] = "ð›", -- U+1D6DD
+ ["b.upsi"] = "ð›–", -- U+1D6D6
+ ["b.xi"] = "ð›", -- U+1D6CF
+ ["b.zeta"] = "ð›‡", -- U+1D6C7
+ ["bNot"] = "â«­", -- U+02AED
+ ["backcong"] = "≌", -- U+0224C
+ ["backepsilon"] = "϶", -- U+003F6
+ ["backprime"] = "‵", -- U+02035
+ ["backsim"] = "∽", -- U+0223D
+ ["backsimeq"] = "â‹", -- U+022CD
+ ["barvee"] = "⊽", -- U+022BD
+ ["barwed"] = "⌅", -- U+02305
+ ["barwedge"] = "⌅", -- U+02305
+ ["bbrk"] = "⎵", -- U+023B5
+ ["bbrktbrk"] = "⎶", -- U+023B6
+ ["bcong"] = "≌", -- U+0224C
+ ["bcy"] = "б", -- U+00431
+ ["bdquo"] = "„", -- U+0201E
+ ["becaus"] = "∵", -- U+02235
+ ["because"] = "∵", -- U+02235
+ ["bemptyv"] = "⦰", -- U+029B0
+ ["bepsi"] = "϶", -- U+003F6
+ ["bernou"] = "ℬ", -- U+0212C
+ ["beta"] = "β", -- U+003B2
+ ["beth"] = "ℶ", -- U+02136
+ ["between"] = "≬", -- U+0226C
+ ["bfr"] = "ð”Ÿ", -- U+1D51F
+ ["bgr"] = "β", -- U+003B2
+ ["bigcap"] = "â‹‚", -- U+022C2
+ ["bigcirc"] = "â—¯", -- U+025EF
+ ["bigcup"] = "⋃", -- U+022C3
+ ["bigodot"] = "⨀", -- U+02A00
+ ["bigoplus"] = "â¨", -- U+02A01
+ ["bigotimes"] = "⨂", -- U+02A02
+ ["bigsqcup"] = "⨆", -- U+02A06
+ ["bigstar"] = "★", -- U+02605
+ ["bigtriangledown"] = "â–½", -- U+025BD
+ ["bigtriangleup"] = "â–³", -- U+025B3
+ ["biguplus"] = "⨄", -- U+02A04
+ ["bigvee"] = "â‹", -- U+022C1
+ ["bigwedge"] = "â‹€", -- U+022C0
+ ["bkarow"] = "â¤", -- U+0290D
+ ["blacklozenge"] = "⧫", -- U+029EB
+ ["blacksquare"] = "â–ª", -- U+025AA
+ ["blacktriangle"] = "â–´", -- U+025B4
+ ["blacktriangledown"] = "â–¾", -- U+025BE
+ ["blacktriangleleft"] = "â—‚", -- U+025C2
+ ["blacktriangleright"] = "â–¸", -- U+025B8
+ ["blank"] = "â£", -- U+02423
+ ["blk12"] = "â–’", -- U+02592
+ ["blk14"] = "â–‘", -- U+02591
+ ["blk34"] = "â–“", -- U+02593
+ ["block"] = "â–ˆ", -- U+02588
+ ["bne"] = "=⃥", -- U+0003D 020E5
+ ["bnequiv"] = "≡⃥", -- U+02261 020E5
+ ["bnot"] = "âŒ", -- U+02310
+ ["bopf"] = "ð•“", -- U+1D553
+ ["bot"] = "⊥", -- U+022A5
+ ["bottom"] = "⊥", -- U+022A5
+ ["bowtie"] = "⋈", -- U+022C8
+ ["boxDL"] = "â•—", -- U+02557
+ ["boxDR"] = "â•”", -- U+02554
+ ["boxDl"] = "â•–", -- U+02556
+ ["boxDr"] = "â•“", -- U+02553
+ ["boxH"] = "â•", -- U+02550
+ ["boxHD"] = "╦", -- U+02566
+ ["boxHU"] = "â•©", -- U+02569
+ ["boxHd"] = "╤", -- U+02564
+ ["boxHu"] = "╧", -- U+02567
+ ["boxUL"] = "â•", -- U+0255D
+ ["boxUR"] = "â•š", -- U+0255A
+ ["boxUl"] = "╜", -- U+0255C
+ ["boxUr"] = "â•™", -- U+02559
+ ["boxV"] = "â•‘", -- U+02551
+ ["boxVH"] = "╬", -- U+0256C
+ ["boxVL"] = "â•£", -- U+02563
+ ["boxVR"] = "â• ", -- U+02560
+ ["boxVh"] = "â•«", -- U+0256B
+ ["boxVl"] = "â•¢", -- U+02562
+ ["boxVr"] = "â•Ÿ", -- U+0255F
+ ["boxbox"] = "⧉", -- U+029C9
+ ["boxdL"] = "â••", -- U+02555
+ ["boxdR"] = "â•’", -- U+02552
+ ["boxdl"] = "â”", -- U+02510
+ ["boxdr"] = "┌", -- U+0250C
+ ["boxh"] = "─", -- U+02500
+ ["boxhD"] = "â•¥", -- U+02565
+ ["boxhU"] = "╨", -- U+02568
+ ["boxhd"] = "┬", -- U+0252C
+ ["boxhu"] = "â”´", -- U+02534
+ ["boxminus"] = "⊟", -- U+0229F
+ ["boxplus"] = "⊞", -- U+0229E
+ ["boxtimes"] = "⊠", -- U+022A0
+ ["boxuL"] = "â•›", -- U+0255B
+ ["boxuR"] = "╘", -- U+02558
+ ["boxul"] = "┘", -- U+02518
+ ["boxur"] = "â””", -- U+02514
+ ["boxv"] = "│", -- U+02502
+ ["boxvH"] = "╪", -- U+0256A
+ ["boxvL"] = "â•¡", -- U+02561
+ ["boxvR"] = "â•ž", -- U+0255E
+ ["boxvh"] = "┼", -- U+0253C
+ ["boxvl"] = "┤", -- U+02524
+ ["boxvr"] = "├", -- U+0251C
+ ["bprime"] = "‵", -- U+02035
+ ["breve"] = "˘", -- U+002D8
+ ["brvbar"] = "¦", -- U+000A6
+ ["bscr"] = "ð’·", -- U+1D4B7
+ ["bsemi"] = "â", -- U+0204F
+ ["bsim"] = "∽", -- U+0223D
+ ["bsime"] = "â‹", -- U+022CD
+ ["bsol"] = "\\", -- U+0005C
+ ["bsolb"] = "⧅", -- U+029C5
+ ["bsolhsub"] = "⟈", -- U+027C8
+ ["bull"] = "•", -- U+02022
+ ["bullet"] = "•", -- U+02022
+ ["bump"] = "≎", -- U+0224E
+ ["bumpE"] = "⪮", -- U+02AAE
+ ["bumpe"] = "â‰", -- U+0224F
+ ["bumpeq"] = "â‰", -- U+0224F
+ ["cacute"] = "ć", -- U+00107
+ ["cap"] = "∩", -- U+02229
+ ["capand"] = "â©„", -- U+02A44
+ ["capbrcup"] = "⩉", -- U+02A49
+ ["capcap"] = "â©‹", -- U+02A4B
+ ["capcup"] = "⩇", -- U+02A47
+ ["capdot"] = "â©€", -- U+02A40
+ ["caps"] = "∩︀", -- U+02229 0FE00
+ ["caret"] = "â", -- U+02041
+ ["caron"] = "ˇ", -- U+002C7
+ ["ccaps"] = "â©", -- U+02A4D
+ ["ccaron"] = "Ä", -- U+0010D
+ ["ccedil"] = "ç", -- U+000E7
+ ["ccirc"] = "ĉ", -- U+00109
+ ["ccups"] = "⩌", -- U+02A4C
+ ["ccupssm"] = "â©", -- U+02A50
+ ["cdot"] = "Ä‹", -- U+0010B
+ ["cedil"] = "¸", -- U+000B8
+ ["cemptyv"] = "⦲", -- U+029B2
+ ["cent"] = "¢", -- U+000A2
+ ["centerdot"] = "·", -- U+000B7
+ ["cfr"] = "ð” ", -- U+1D520
+ ["chcy"] = "ч", -- U+00447
+ ["check"] = "✓", -- U+02713
+ ["checkmark"] = "✓", -- U+02713
+ ["chi"] = "χ", -- U+003C7
+ ["cir"] = "â—‹", -- U+025CB
+ ["cirE"] = "⧃", -- U+029C3
+ ["circ"] = "ˆ", -- U+002C6
+ ["circeq"] = "≗", -- U+02257
+ ["circlearrowleft"] = "↺", -- U+021BA
+ ["circlearrowright"] = "↻", -- U+021BB
+ ["circledR"] = "®", -- U+000AE
+ ["circledS"] = "Ⓢ", -- U+024C8
+ ["circledast"] = "⊛", -- U+0229B
+ ["circledcirc"] = "⊚", -- U+0229A
+ ["circleddash"] = "âŠ", -- U+0229D
+ ["cire"] = "≗", -- U+02257
+ ["cirfnint"] = "â¨", -- U+02A10
+ ["cirmid"] = "⫯", -- U+02AEF
+ ["cirscir"] = "⧂", -- U+029C2
+ ["clubs"] = "♣", -- U+02663
+ ["clubsuit"] = "♣", -- U+02663
+ ["colon"] = ":", -- U+0003A
+ ["colone"] = "≔", -- U+02254
+ ["coloneq"] = "≔", -- U+02254
+ ["comma"] = ",", -- U+0002C
+ ["commat"] = "@", -- U+00040
+ ["comp"] = "âˆ", -- U+02201
+ ["compfn"] = "∘", -- U+02218
+ ["complement"] = "âˆ", -- U+02201
+ ["complexes"] = "â„‚", -- U+02102
+ ["cong"] = "≅", -- U+02245
+ ["congdot"] = "â©­", -- U+02A6D
+ ["conint"] = "∮", -- U+0222E
+ ["copf"] = "ð•”", -- U+1D554
+ ["coprod"] = "âˆ", -- U+02210
+ ["copy"] = "©", -- U+000A9
+ ["copysr"] = "â„—", -- U+02117
+ ["crarr"] = "↵", -- U+021B5
+ ["cross"] = "✗", -- U+02717
+ ["cscr"] = "ð’¸", -- U+1D4B8
+ ["csub"] = "â«", -- U+02ACF
+ ["csube"] = "â«‘", -- U+02AD1
+ ["csup"] = "â«", -- U+02AD0
+ ["csupe"] = "â«’", -- U+02AD2
+ ["ctdot"] = "⋯", -- U+022EF
+ ["cudarrl"] = "⤸", -- U+02938
+ ["cudarrr"] = "⤵", -- U+02935
+ ["cuepr"] = "â‹ž", -- U+022DE
+ ["cuesc"] = "â‹Ÿ", -- U+022DF
+ ["cularr"] = "↶", -- U+021B6
+ ["cularrp"] = "⤽", -- U+0293D
+ ["cup"] = "∪", -- U+0222A
+ ["cupbrcap"] = "⩈", -- U+02A48
+ ["cupcap"] = "⩆", -- U+02A46
+ ["cupcup"] = "â©Š", -- U+02A4A
+ ["cupdot"] = "âŠ", -- U+0228D
+ ["cupor"] = "â©…", -- U+02A45
+ ["cups"] = "∪︀", -- U+0222A 0FE00
+ ["curarr"] = "↷", -- U+021B7
+ ["curarrm"] = "⤼", -- U+0293C
+ ["curlyeqprec"] = "â‹ž", -- U+022DE
+ ["curlyeqsucc"] = "â‹Ÿ", -- U+022DF
+ ["curlyvee"] = "â‹Ž", -- U+022CE
+ ["curlywedge"] = "â‹", -- U+022CF
+ ["curren"] = "¤", -- U+000A4
+ ["curvearrowleft"] = "↶", -- U+021B6
+ ["curvearrowright"] = "↷", -- U+021B7
+ ["cuvee"] = "â‹Ž", -- U+022CE
+ ["cuwed"] = "â‹", -- U+022CF
+ ["cwconint"] = "∲", -- U+02232
+ ["cwint"] = "∱", -- U+02231
+ ["cylcty"] = "⌭", -- U+0232D
+ ["dArr"] = "⇓", -- U+021D3
+ ["dHar"] = "⥥", -- U+02965
+ ["dagger"] = "†", -- U+02020
+ ["daleth"] = "ℸ", -- U+02138
+ ["darr"] = "↓", -- U+02193
+ ["dash"] = "â€", -- U+02010
+ ["dashv"] = "⊣", -- U+022A3
+ ["dbkarow"] = "â¤", -- U+0290F
+ ["dblac"] = "Ë", -- U+002DD
+ ["dcaron"] = "Ä", -- U+0010F
+ ["dcy"] = "д", -- U+00434
+ ["dd"] = "â…†", -- U+02146
+ ["ddagger"] = "‡", -- U+02021
+ ["ddarr"] = "⇊", -- U+021CA
+ ["ddotseq"] = "â©·", -- U+02A77
+ ["deg"] = "°", -- U+000B0
+ ["delta"] = "δ", -- U+003B4
+ ["demptyv"] = "⦱", -- U+029B1
+ ["dfisht"] = "⥿", -- U+0297F
+ ["dfr"] = "ð”¡", -- U+1D521
+ ["dgr"] = "δ", -- U+003B4
+ ["dharl"] = "⇃", -- U+021C3
+ ["dharr"] = "⇂", -- U+021C2
+ ["diam"] = "â‹„", -- U+022C4
+ ["diamond"] = "â‹„", -- U+022C4
+ ["diamondsuit"] = "♦", -- U+02666
+ ["diams"] = "♦", -- U+02666
+ ["die"] = "¨", -- U+000A8
+ ["digamma"] = "Ï", -- U+003DD
+ ["disin"] = "⋲", -- U+022F2
+ ["div"] = "÷", -- U+000F7
+ ["divide"] = "÷", -- U+000F7
+ ["divideontimes"] = "⋇", -- U+022C7
+ ["divonx"] = "⋇", -- U+022C7
+ ["djcy"] = "Ñ’", -- U+00452
+ ["dlcorn"] = "⌞", -- U+0231E
+ ["dlcrop"] = "âŒ", -- U+0230D
+ ["dollar"] = "$", -- U+00024
+ ["dopf"] = "ð••", -- U+1D555
+ ["dot"] = "Ë™", -- U+002D9
+ ["doteq"] = "â‰", -- U+02250
+ ["doteqdot"] = "≑", -- U+02251
+ ["dotminus"] = "∸", -- U+02238
+ ["dotplus"] = "∔", -- U+02214
+ ["dotsquare"] = "⊡", -- U+022A1
+ ["doublebarwedge"] = "⌆", -- U+02306
+ ["downarrow"] = "↓", -- U+02193
+ ["downdownarrows"] = "⇊", -- U+021CA
+ ["downharpoonleft"] = "⇃", -- U+021C3
+ ["downharpoonright"] = "⇂", -- U+021C2
+ ["drbkarow"] = "â¤", -- U+02910
+ ["drcorn"] = "⌟", -- U+0231F
+ ["drcrop"] = "⌌", -- U+0230C
+ ["dscr"] = "ð’¹", -- U+1D4B9
+ ["dscy"] = "Ñ•", -- U+00455
+ ["dsol"] = "⧶", -- U+029F6
+ ["dstrok"] = "Ä‘", -- U+00111
+ ["dtdot"] = "⋱", -- U+022F1
+ ["dtri"] = "â–¿", -- U+025BF
+ ["dtrif"] = "â–¾", -- U+025BE
+ ["duarr"] = "⇵", -- U+021F5
+ ["duhar"] = "⥯", -- U+0296F
+ ["dwangle"] = "⦦", -- U+029A6
+ ["dzcy"] = "ÑŸ", -- U+0045F
+ ["dzigrarr"] = "⟿", -- U+027FF
+ ["eDDot"] = "â©·", -- U+02A77
+ ["eDot"] = "≑", -- U+02251
+ ["eacgr"] = "έ", -- U+003AD
+ ["eacute"] = "é", -- U+000E9
+ ["easter"] = "â©®", -- U+02A6E
+ ["ecaron"] = "Ä›", -- U+0011B
+ ["ecir"] = "≖", -- U+02256
+ ["ecirc"] = "ê", -- U+000EA
+ ["ecolon"] = "≕", -- U+02255
+ ["ecy"] = "Ñ", -- U+0044D
+ ["edot"] = "Ä—", -- U+00117
+ ["ee"] = "â…‡", -- U+02147
+ ["eeacgr"] = "ή", -- U+003AE
+ ["eegr"] = "η", -- U+003B7
+ ["efDot"] = "≒", -- U+02252
+ ["efr"] = "ð”¢", -- U+1D522
+ ["eg"] = "⪚", -- U+02A9A
+ ["egr"] = "ε", -- U+003B5
+ ["egrave"] = "è", -- U+000E8
+ ["egs"] = "⪖", -- U+02A96
+ ["egsdot"] = "⪘", -- U+02A98
+ ["el"] = "⪙", -- U+02A99
+ ["elinters"] = "â§", -- U+023E7
+ ["ell"] = "â„“", -- U+02113
+ ["els"] = "⪕", -- U+02A95
+ ["elsdot"] = "⪗", -- U+02A97
+ ["emacr"] = "Ä“", -- U+00113
+ ["empty"] = "∅", -- U+02205
+ ["emptyset"] = "∅", -- U+02205
+ ["emptyv"] = "∅", -- U+02205
+ ["emsp"] = " ", -- U+02003
+ ["emsp13"] = " ", -- U+02004
+ ["emsp14"] = " ", -- U+02005
+ ["eng"] = "Å‹", -- U+0014B
+ ["ensp"] = " ", -- U+02002
+ ["eogon"] = "Ä™", -- U+00119
+ ["eopf"] = "ð•–", -- U+1D556
+ ["epar"] = "â‹•", -- U+022D5
+ ["eparsl"] = "⧣", -- U+029E3
+ ["eplus"] = "⩱", -- U+02A71
+ ["epsi"] = "ε", -- U+003B5
+ ["epsilon"] = "ε", -- U+003B5
+ ["epsiv"] = "ϵ", -- U+003F5
+ ["eqcirc"] = "≖", -- U+02256
+ ["eqcolon"] = "≕", -- U+02255
+ ["eqsim"] = "≂", -- U+02242
+ ["eqslantgtr"] = "⪖", -- U+02A96
+ ["eqslantless"] = "⪕", -- U+02A95
+ ["equals"] = "=", -- U+0003D
+ ["equest"] = "≟", -- U+0225F
+ ["equiv"] = "≡", -- U+02261
+ ["equivDD"] = "⩸", -- U+02A78
+ ["eqvparsl"] = "⧥", -- U+029E5
+ ["erDot"] = "≓", -- U+02253
+ ["erarr"] = "⥱", -- U+02971
+ ["escr"] = "ℯ", -- U+0212F
+ ["esdot"] = "â‰", -- U+02250
+ ["esim"] = "≂", -- U+02242
+ ["eta"] = "η", -- U+003B7
+ ["eth"] = "ð", -- U+000F0
+ ["euml"] = "ë", -- U+000EB
+ ["euro"] = "€", -- U+020AC
+ ["excl"] = "!", -- U+00021
+ ["exist"] = "∃", -- U+02203
+ ["expectation"] = "â„°", -- U+02130
+ ["exponentiale"] = "â…‡", -- U+02147
+ ["fallingdotseq"] = "≒", -- U+02252
+ ["fcy"] = "Ñ„", -- U+00444
+ ["female"] = "♀", -- U+02640
+ ["ffilig"] = "ffi", -- U+0FB03
+ ["fflig"] = "ff", -- U+0FB00
+ ["ffllig"] = "ffl", -- U+0FB04
+ ["ffr"] = "ð”£", -- U+1D523
+ ["filig"] = "ï¬", -- U+0FB01
+ ["fjlig"] = "fj", -- U+00066 0006A
+ ["flat"] = "â™­", -- U+0266D
+ ["fllig"] = "fl", -- U+0FB02
+ ["fltns"] = "â–±", -- U+025B1
+ ["fnof"] = "Æ’", -- U+00192
+ ["fopf"] = "ð•—", -- U+1D557
+ ["forall"] = "∀", -- U+02200
+ ["fork"] = "â‹”", -- U+022D4
+ ["forkv"] = "â«™", -- U+02AD9
+ ["fpartint"] = "â¨", -- U+02A0D
+ ["frac12"] = "½", -- U+000BD
+ ["frac13"] = "â…“", -- U+02153
+ ["frac14"] = "¼", -- U+000BC
+ ["frac15"] = "â…•", -- U+02155
+ ["frac16"] = "â…™", -- U+02159
+ ["frac18"] = "â…›", -- U+0215B
+ ["frac23"] = "â…”", -- U+02154
+ ["frac25"] = "â…–", -- U+02156
+ ["frac34"] = "¾", -- U+000BE
+ ["frac35"] = "â…—", -- U+02157
+ ["frac38"] = "⅜", -- U+0215C
+ ["frac45"] = "â…˜", -- U+02158
+ ["frac56"] = "â…š", -- U+0215A
+ ["frac58"] = "â…", -- U+0215D
+ ["frac78"] = "â…ž", -- U+0215E
+ ["frasl"] = "â„", -- U+02044
+ ["frown"] = "⌢", -- U+02322
+ ["fscr"] = "ð’»", -- U+1D4BB
+ ["gE"] = "≧", -- U+02267
+ ["gEl"] = "⪌", -- U+02A8C
+ ["gacute"] = "ǵ", -- U+001F5
+ ["gamma"] = "γ", -- U+003B3
+ ["gammad"] = "Ï", -- U+003DD
+ ["gap"] = "⪆", -- U+02A86
+ ["gbreve"] = "ÄŸ", -- U+0011F
+ ["gcirc"] = "Ä", -- U+0011D
+ ["gcy"] = "г", -- U+00433
+ ["gdot"] = "Ä¡", -- U+00121
+ ["ge"] = "≥", -- U+02265
+ ["gel"] = "â‹›", -- U+022DB
+ ["geq"] = "≥", -- U+02265
+ ["geqq"] = "≧", -- U+02267
+ ["geqslant"] = "⩾", -- U+02A7E
+ ["ges"] = "⩾", -- U+02A7E
+ ["gescc"] = "⪩", -- U+02AA9
+ ["gesdot"] = "⪀", -- U+02A80
+ ["gesdoto"] = "⪂", -- U+02A82
+ ["gesdotol"] = "⪄", -- U+02A84
+ ["gesl"] = "⋛︀", -- U+022DB 0FE00
+ ["gesles"] = "⪔", -- U+02A94
+ ["gfr"] = "ð”¤", -- U+1D524
+ ["gg"] = "≫", -- U+0226B
+ ["ggg"] = "â‹™", -- U+022D9
+ ["ggr"] = "γ", -- U+003B3
+ ["gimel"] = "â„·", -- U+02137
+ ["gjcy"] = "Ñ“", -- U+00453
+ ["gl"] = "≷", -- U+02277
+ ["glE"] = "⪒", -- U+02A92
+ ["gla"] = "⪥", -- U+02AA5
+ ["glj"] = "⪤", -- U+02AA4
+ ["gnE"] = "≩", -- U+02269
+ ["gnap"] = "⪊", -- U+02A8A
+ ["gnapprox"] = "⪊", -- U+02A8A
+ ["gne"] = "⪈", -- U+02A88
+ ["gneq"] = "⪈", -- U+02A88
+ ["gneqq"] = "≩", -- U+02269
+ ["gnsim"] = "⋧", -- U+022E7
+ ["gopf"] = "ð•˜", -- U+1D558
+ ["grave"] = "`", -- U+00060
+ ["gscr"] = "â„Š", -- U+0210A
+ ["gsim"] = "≳", -- U+02273
+ ["gsime"] = "⪎", -- U+02A8E
+ ["gsiml"] = "âª", -- U+02A90
+ ["gt"] = ">", -- U+0003E
+ ["gtcc"] = "⪧", -- U+02AA7
+ ["gtcir"] = "⩺", -- U+02A7A
+ ["gtdot"] = "â‹—", -- U+022D7
+ ["gtlPar"] = "⦕", -- U+02995
+ ["gtquest"] = "⩼", -- U+02A7C
+ ["gtrapprox"] = "⪆", -- U+02A86
+ ["gtrarr"] = "⥸", -- U+02978
+ ["gtrdot"] = "â‹—", -- U+022D7
+ ["gtreqless"] = "â‹›", -- U+022DB
+ ["gtreqqless"] = "⪌", -- U+02A8C
+ ["gtrless"] = "≷", -- U+02277
+ ["gtrsim"] = "≳", -- U+02273
+ ["gvertneqq"] = "≩︀", -- U+02269 0FE00
+ ["gvnE"] = "≩︀", -- U+02269 0FE00
+ ["hArr"] = "⇔", -- U+021D4
+ ["hairsp"] = " ", -- U+0200A
+ ["half"] = "½", -- U+000BD
+ ["hamilt"] = "â„‹", -- U+0210B
+ ["hardcy"] = "ÑŠ", -- U+0044A
+ ["harr"] = "↔", -- U+02194
+ ["harrcir"] = "⥈", -- U+02948
+ ["harrw"] = "↭", -- U+021AD
+ ["hbar"] = "â„", -- U+0210F
+ ["hcirc"] = "Ä¥", -- U+00125
+ ["hearts"] = "♥", -- U+02665
+ ["heartsuit"] = "♥", -- U+02665
+ ["hellip"] = "…", -- U+02026
+ ["hercon"] = "⊹", -- U+022B9
+ ["hfr"] = "ð”¥", -- U+1D525
+ ["hksearow"] = "⤥", -- U+02925
+ ["hkswarow"] = "⤦", -- U+02926
+ ["hoarr"] = "⇿", -- U+021FF
+ ["homtht"] = "∻", -- U+0223B
+ ["hookleftarrow"] = "↩", -- U+021A9
+ ["hookrightarrow"] = "↪", -- U+021AA
+ ["hopf"] = "ð•™", -- U+1D559
+ ["horbar"] = "―", -- U+02015
+ ["hscr"] = "ð’½", -- U+1D4BD
+ ["hslash"] = "â„", -- U+0210F
+ ["hstrok"] = "ħ", -- U+00127
+ ["hybull"] = "âƒ", -- U+02043
+ ["hyphen"] = "â€", -- U+02010
+ ["iacgr"] = "ί", -- U+003AF
+ ["iacute"] = "í", -- U+000ED
+ ["ic"] = "â£", -- U+02063
+ ["icirc"] = "î", -- U+000EE
+ ["icy"] = "и", -- U+00438
+ ["idiagr"] = "Î", -- U+00390
+ ["idigr"] = "ÏŠ", -- U+003CA
+ ["iecy"] = "е", -- U+00435
+ ["iexcl"] = "¡", -- U+000A1
+ ["iff"] = "⇔", -- U+021D4
+ ["ifr"] = "ð”¦", -- U+1D526
+ ["igr"] = "ι", -- U+003B9
+ ["igrave"] = "ì", -- U+000EC
+ ["ii"] = "â…ˆ", -- U+02148
+ ["iiiint"] = "⨌", -- U+02A0C
+ ["iiint"] = "∭", -- U+0222D
+ ["iinfin"] = "⧜", -- U+029DC
+ ["iiota"] = "â„©", -- U+02129
+ ["ijlig"] = "ij", -- U+00133
+ ["imacr"] = "Ä«", -- U+0012B
+ ["image"] = "â„‘", -- U+02111
+ ["imagline"] = "â„", -- U+02110
+ ["imagpart"] = "â„‘", -- U+02111
+ ["imath"] = "ı", -- U+00131
+ ["imof"] = "⊷", -- U+022B7
+ ["imped"] = "Ƶ", -- U+001B5
+ ["in"] = "∈", -- U+02208
+ ["incare"] = "â„…", -- U+02105
+ ["infin"] = "∞", -- U+0221E
+ ["infintie"] = "â§", -- U+029DD
+ ["inodot"] = "ı", -- U+00131
+ ["int"] = "∫", -- U+0222B
+ ["intcal"] = "⊺", -- U+022BA
+ ["integers"] = "ℤ", -- U+02124
+ ["intercal"] = "⊺", -- U+022BA
+ ["intlarhk"] = "⨗", -- U+02A17
+ ["intprod"] = "⨼", -- U+02A3C
+ ["iocy"] = "Ñ‘", -- U+00451
+ ["iogon"] = "į", -- U+0012F
+ ["iopf"] = "ð•š", -- U+1D55A
+ ["iota"] = "ι", -- U+003B9
+ ["iprod"] = "⨼", -- U+02A3C
+ ["iquest"] = "¿", -- U+000BF
+ ["iscr"] = "ð’¾", -- U+1D4BE
+ ["isin"] = "∈", -- U+02208
+ ["isinE"] = "⋹", -- U+022F9
+ ["isindot"] = "⋵", -- U+022F5
+ ["isins"] = "â‹´", -- U+022F4
+ ["isinsv"] = "⋳", -- U+022F3
+ ["isinv"] = "∈", -- U+02208
+ ["it"] = "â¢", -- U+02062
+ ["itilde"] = "Ä©", -- U+00129
+ ["iukcy"] = "Ñ–", -- U+00456
+ ["iuml"] = "ï", -- U+000EF
+ ["jcirc"] = "ĵ", -- U+00135
+ ["jcy"] = "й", -- U+00439
+ ["jfr"] = "ð”§", -- U+1D527
+ ["jmath"] = "È·", -- U+00237
+ ["jopf"] = "ð•›", -- U+1D55B
+ ["jscr"] = "ð’¿", -- U+1D4BF
+ ["jsercy"] = "ј", -- U+00458
+ ["jukcy"] = "Ñ”", -- U+00454
+ ["kappa"] = "κ", -- U+003BA
+ ["kappav"] = "Ï°", -- U+003F0
+ ["kcedil"] = "Ä·", -- U+00137
+ ["kcy"] = "к", -- U+0043A
+ ["kfr"] = "ð”¨", -- U+1D528
+ ["kgr"] = "κ", -- U+003BA
+ ["kgreen"] = "ĸ", -- U+00138
+ ["khcy"] = "Ñ…", -- U+00445
+ ["khgr"] = "χ", -- U+003C7
+ ["kjcy"] = "ќ", -- U+0045C
+ ["kopf"] = "ð•œ", -- U+1D55C
+ ["kscr"] = "ð“€", -- U+1D4C0
+ ["lAarr"] = "⇚", -- U+021DA
+ ["lArr"] = "â‡", -- U+021D0
+ ["lAtail"] = "⤛", -- U+0291B
+ ["lBarr"] = "⤎", -- U+0290E
+ ["lE"] = "≦", -- U+02266
+ ["lEg"] = "⪋", -- U+02A8B
+ ["lHar"] = "⥢", -- U+02962
+ ["lacute"] = "ĺ", -- U+0013A
+ ["laemptyv"] = "⦴", -- U+029B4
+ ["lagran"] = "â„’", -- U+02112
+ ["lambda"] = "λ", -- U+003BB
+ ["lang"] = "⟨", -- U+027E8
+ ["langd"] = "⦑", -- U+02991
+ ["langle"] = "⟨", -- U+027E8
+ ["lap"] = "⪅", -- U+02A85
+ ["laquo"] = "«", -- U+000AB
+ ["larr"] = "â†", -- U+02190
+ ["larrb"] = "⇤", -- U+021E4
+ ["larrbfs"] = "⤟", -- U+0291F
+ ["larrfs"] = "â¤", -- U+0291D
+ ["larrhk"] = "↩", -- U+021A9
+ ["larrlp"] = "↫", -- U+021AB
+ ["larrpl"] = "⤹", -- U+02939
+ ["larrsim"] = "⥳", -- U+02973
+ ["larrtl"] = "↢", -- U+021A2
+ ["lat"] = "⪫", -- U+02AAB
+ ["latail"] = "⤙", -- U+02919
+ ["late"] = "⪭", -- U+02AAD
+ ["lates"] = "⪭︀", -- U+02AAD 0FE00
+ ["lbarr"] = "⤌", -- U+0290C
+ ["lbbrk"] = "â²", -- U+02772
+ ["lbrace"] = "{", -- U+0007B
+ ["lbrack"] = "[", -- U+0005B
+ ["lbrke"] = "⦋", -- U+0298B
+ ["lbrksld"] = "â¦", -- U+0298F
+ ["lbrkslu"] = "â¦", -- U+0298D
+ ["lcaron"] = "ľ", -- U+0013E
+ ["lcedil"] = "ļ", -- U+0013C
+ ["lceil"] = "⌈", -- U+02308
+ ["lcub"] = "{", -- U+0007B
+ ["lcy"] = "л", -- U+0043B
+ ["ldca"] = "⤶", -- U+02936
+ ["ldquo"] = "“", -- U+0201C
+ ["ldquor"] = "„", -- U+0201E
+ ["ldrdhar"] = "⥧", -- U+02967
+ ["ldrushar"] = "⥋", -- U+0294B
+ ["ldsh"] = "↲", -- U+021B2
+ ["le"] = "≤", -- U+02264
+ ["leftarrow"] = "â†", -- U+02190
+ ["leftarrowtail"] = "↢", -- U+021A2
+ ["leftharpoondown"] = "↽", -- U+021BD
+ ["leftharpoonup"] = "↼", -- U+021BC
+ ["leftleftarrows"] = "⇇", -- U+021C7
+ ["leftrightarrow"] = "↔", -- U+02194
+ ["leftrightarrows"] = "⇆", -- U+021C6
+ ["leftrightharpoons"] = "⇋", -- U+021CB
+ ["leftrightsquigarrow"] = "↭", -- U+021AD
+ ["leftthreetimes"] = "â‹‹", -- U+022CB
+ ["leg"] = "â‹š", -- U+022DA
+ ["leq"] = "≤", -- U+02264
+ ["leqq"] = "≦", -- U+02266
+ ["leqslant"] = "⩽", -- U+02A7D
+ ["les"] = "⩽", -- U+02A7D
+ ["lescc"] = "⪨", -- U+02AA8
+ ["lesdot"] = "â©¿", -- U+02A7F
+ ["lesdoto"] = "âª", -- U+02A81
+ ["lesdotor"] = "⪃", -- U+02A83
+ ["lesg"] = "⋚︀", -- U+022DA 0FE00
+ ["lesges"] = "⪓", -- U+02A93
+ ["lessapprox"] = "⪅", -- U+02A85
+ ["lessdot"] = "â‹–", -- U+022D6
+ ["lesseqgtr"] = "â‹š", -- U+022DA
+ ["lesseqqgtr"] = "⪋", -- U+02A8B
+ ["lessgtr"] = "≶", -- U+02276
+ ["lesssim"] = "≲", -- U+02272
+ ["lfisht"] = "⥼", -- U+0297C
+ ["lfloor"] = "⌊", -- U+0230A
+ ["lfr"] = "ð”©", -- U+1D529
+ ["lg"] = "≶", -- U+02276
+ ["lgE"] = "⪑", -- U+02A91
+ ["lgr"] = "λ", -- U+003BB
+ ["lhard"] = "↽", -- U+021BD
+ ["lharu"] = "↼", -- U+021BC
+ ["lharul"] = "⥪", -- U+0296A
+ ["lhblk"] = "â–„", -- U+02584
+ ["ljcy"] = "Ñ™", -- U+00459
+ ["ll"] = "≪", -- U+0226A
+ ["llarr"] = "⇇", -- U+021C7
+ ["llcorner"] = "⌞", -- U+0231E
+ ["llhard"] = "⥫", -- U+0296B
+ ["lltri"] = "â—º", -- U+025FA
+ ["lmidot"] = "Å€", -- U+00140
+ ["lmoust"] = "⎰", -- U+023B0
+ ["lmoustache"] = "⎰", -- U+023B0
+ ["lnE"] = "≨", -- U+02268
+ ["lnap"] = "⪉", -- U+02A89
+ ["lnapprox"] = "⪉", -- U+02A89
+ ["lne"] = "⪇", -- U+02A87
+ ["lneq"] = "⪇", -- U+02A87
+ ["lneqq"] = "≨", -- U+02268
+ ["lnsim"] = "⋦", -- U+022E6
+ ["loang"] = "⟬", -- U+027EC
+ ["loarr"] = "⇽", -- U+021FD
+ ["lobrk"] = "⟦", -- U+027E6
+ ["longleftarrow"] = "⟵", -- U+027F5
+ ["longleftrightarrow"] = "⟷", -- U+027F7
+ ["longmapsto"] = "⟼", -- U+027FC
+ ["longrightarrow"] = "⟶", -- U+027F6
+ ["looparrowleft"] = "↫", -- U+021AB
+ ["looparrowright"] = "↬", -- U+021AC
+ ["lopar"] = "⦅", -- U+02985
+ ["lopf"] = "ð•", -- U+1D55D
+ ["loplus"] = "⨭", -- U+02A2D
+ ["lotimes"] = "⨴", -- U+02A34
+ ["lowast"] = "∗", -- U+02217
+ ["lowbar"] = "_", -- U+0005F
+ ["loz"] = "â—Š", -- U+025CA
+ ["lozenge"] = "â—Š", -- U+025CA
+ ["lozf"] = "⧫", -- U+029EB
+ ["lpar"] = "(", -- U+00028
+ ["lparlt"] = "⦓", -- U+02993
+ ["lrarr"] = "⇆", -- U+021C6
+ ["lrcorner"] = "⌟", -- U+0231F
+ ["lrhar"] = "⇋", -- U+021CB
+ ["lrhard"] = "⥭", -- U+0296D
+ ["lrm"] = "‎", -- U+0200E
+ ["lrtri"] = "⊿", -- U+022BF
+ ["lsaquo"] = "‹", -- U+02039
+ ["lscr"] = "ð“", -- U+1D4C1
+ ["lsh"] = "↰", -- U+021B0
+ ["lsim"] = "≲", -- U+02272
+ ["lsime"] = "âª", -- U+02A8D
+ ["lsimg"] = "âª", -- U+02A8F
+ ["lsqb"] = "[", -- U+0005B
+ ["lsquo"] = "‘", -- U+02018
+ ["lsquor"] = "‚", -- U+0201A
+ ["lstrok"] = "Å‚", -- U+00142
+ ["lt"] = "<", -- U+00026
+ ["ltcc"] = "⪦", -- U+02AA6
+ ["ltcir"] = "⩹", -- U+02A79
+ ["ltdot"] = "â‹–", -- U+022D6
+ ["lthree"] = "â‹‹", -- U+022CB
+ ["ltimes"] = "⋉", -- U+022C9
+ ["ltlarr"] = "⥶", -- U+02976
+ ["ltquest"] = "â©»", -- U+02A7B
+ ["ltrPar"] = "⦖", -- U+02996
+ ["ltri"] = "â—ƒ", -- U+025C3
+ ["ltrie"] = "⊴", -- U+022B4
+ ["ltrif"] = "â—‚", -- U+025C2
+ ["lurdshar"] = "⥊", -- U+0294A
+ ["luruhar"] = "⥦", -- U+02966
+ ["lvertneqq"] = "≨︀", -- U+02268 0FE00
+ ["lvnE"] = "≨︀", -- U+02268 0FE00
+ ["mDDot"] = "∺", -- U+0223A
+ ["macr"] = "¯", -- U+000AF
+ ["male"] = "♂", -- U+02642
+ ["malt"] = "✠", -- U+02720
+ ["maltese"] = "✠", -- U+02720
+ ["map"] = "↦", -- U+021A6
+ ["mapsto"] = "↦", -- U+021A6
+ ["mapstodown"] = "↧", -- U+021A7
+ ["mapstoleft"] = "↤", -- U+021A4
+ ["mapstoup"] = "↥", -- U+021A5
+ ["marker"] = "â–®", -- U+025AE
+ ["mcomma"] = "⨩", -- U+02A29
+ ["mcy"] = "м", -- U+0043C
+ ["mdash"] = "—", -- U+02014
+ ["measuredangle"] = "∡", -- U+02221
+ ["mfr"] = "ð”ª", -- U+1D52A
+ ["mgr"] = "μ", -- U+003BC
+ ["mho"] = "℧", -- U+02127
+ ["micro"] = "µ", -- U+000B5
+ ["mid"] = "∣", -- U+02223
+ ["midast"] = "*", -- U+0002A
+ ["midcir"] = "â«°", -- U+02AF0
+ ["middot"] = "·", -- U+000B7
+ ["minus"] = "−", -- U+02212
+ ["minusb"] = "⊟", -- U+0229F
+ ["minusd"] = "∸", -- U+02238
+ ["minusdu"] = "⨪", -- U+02A2A
+ ["mlcp"] = "â«›", -- U+02ADB
+ ["mldr"] = "…", -- U+02026
+ ["mnplus"] = "∓", -- U+02213
+ ["models"] = "⊧", -- U+022A7
+ ["mopf"] = "ð•ž", -- U+1D55E
+ ["mp"] = "∓", -- U+02213
+ ["mscr"] = "ð“‚", -- U+1D4C2
+ ["mstpos"] = "∾", -- U+0223E
+ ["mu"] = "μ", -- U+003BC
+ ["multimap"] = "⊸", -- U+022B8
+ ["mumap"] = "⊸", -- U+022B8
+ ["nGg"] = "⋙̸", -- U+022D9 00338
+ ["nGt"] = "≫⃒", -- U+0226B 020D2
+ ["nGtv"] = "≫̸", -- U+0226B 00338
+ ["nLeftarrow"] = "â‡", -- U+021CD
+ ["nLeftrightarrow"] = "⇎", -- U+021CE
+ ["nLl"] = "⋘̸", -- U+022D8 00338
+ ["nLt"] = "≪⃒", -- U+0226A 020D2
+ ["nLtv"] = "≪̸", -- U+0226A 00338
+ ["nRightarrow"] = "â‡", -- U+021CF
+ ["nVDash"] = "⊯", -- U+022AF
+ ["nVdash"] = "⊮", -- U+022AE
+ ["nabla"] = "∇", -- U+02207
+ ["nacute"] = "Å„", -- U+00144
+ ["nang"] = "∠⃒", -- U+02220 020D2
+ ["nap"] = "≉", -- U+02249
+ ["napE"] = "⩰̸", -- U+02A70 00338
+ ["napid"] = "≋̸", -- U+0224B 00338
+ ["napos"] = "ʼn", -- U+00149
+ ["napprox"] = "≉", -- U+02249
+ ["natur"] = "â™®", -- U+0266E
+ ["natural"] = "â™®", -- U+0266E
+ ["naturals"] = "â„•", -- U+02115
+ ["nbsp"] = " ", -- U+000A0
+ ["nbump"] = "≎̸", -- U+0224E 00338
+ ["nbumpe"] = "â‰Ì¸", -- U+0224F 00338
+ ["ncap"] = "⩃", -- U+02A43
+ ["ncaron"] = "ň", -- U+00148
+ ["ncedil"] = "ņ", -- U+00146
+ ["ncong"] = "≇", -- U+02247
+ ["ncongdot"] = "⩭̸", -- U+02A6D 00338
+ ["ncup"] = "â©‚", -- U+02A42
+ ["ncy"] = "н", -- U+0043D
+ ["ndash"] = "–", -- U+02013
+ ["ne"] = "≠", -- U+02260
+ ["neArr"] = "⇗", -- U+021D7
+ ["nearhk"] = "⤤", -- U+02924
+ ["nearr"] = "↗", -- U+02197
+ ["nearrow"] = "↗", -- U+02197
+ ["nedot"] = "â‰Ì¸", -- U+02250 00338
+ ["nequiv"] = "≢", -- U+02262
+ ["nesear"] = "⤨", -- U+02928
+ ["nesim"] = "≂̸", -- U+02242 00338
+ ["nexist"] = "∄", -- U+02204
+ ["nexists"] = "∄", -- U+02204
+ ["nfr"] = "ð”«", -- U+1D52B
+ ["ngE"] = "≧̸", -- U+02267 00338
+ ["nge"] = "≱", -- U+02271
+ ["ngeq"] = "≱", -- U+02271
+ ["ngeqq"] = "≧̸", -- U+02267 00338
+ ["ngeqslant"] = "⩾̸", -- U+02A7E 00338
+ ["nges"] = "⩾̸", -- U+02A7E 00338
+ ["ngr"] = "ν", -- U+003BD
+ ["ngsim"] = "≵", -- U+02275
+ ["ngt"] = "≯", -- U+0226F
+ ["ngtr"] = "≯", -- U+0226F
+ ["nhArr"] = "⇎", -- U+021CE
+ ["nharr"] = "↮", -- U+021AE
+ ["nhpar"] = "⫲", -- U+02AF2
+ ["ni"] = "∋", -- U+0220B
+ ["nis"] = "⋼", -- U+022FC
+ ["nisd"] = "⋺", -- U+022FA
+ ["niv"] = "∋", -- U+0220B
+ ["njcy"] = "Ñš", -- U+0045A
+ ["nlArr"] = "â‡", -- U+021CD
+ ["nlE"] = "≦̸", -- U+02266 00338
+ ["nlarr"] = "↚", -- U+0219A
+ ["nldr"] = "‥", -- U+02025
+ ["nle"] = "≰", -- U+02270
+ ["nleftarrow"] = "↚", -- U+0219A
+ ["nleftrightarrow"] = "↮", -- U+021AE
+ ["nleq"] = "≰", -- U+02270
+ ["nleqq"] = "≦̸", -- U+02266 00338
+ ["nleqslant"] = "⩽̸", -- U+02A7D 00338
+ ["nles"] = "⩽̸", -- U+02A7D 00338
+ ["nless"] = "≮", -- U+0226E
+ ["nlsim"] = "≴", -- U+02274
+ ["nlt"] = "≮", -- U+0226E
+ ["nltri"] = "⋪", -- U+022EA
+ ["nltrie"] = "⋬", -- U+022EC
+ ["nmid"] = "∤", -- U+02224
+ ["nopf"] = "ð•Ÿ", -- U+1D55F
+ ["not"] = "¬", -- U+000AC
+ ["notin"] = "∉", -- U+02209
+ ["notinE"] = "⋹̸", -- U+022F9 00338
+ ["notindot"] = "⋵̸", -- U+022F5 00338
+ ["notinva"] = "∉", -- U+02209
+ ["notinvb"] = "â‹·", -- U+022F7
+ ["notinvc"] = "⋶", -- U+022F6
+ ["notni"] = "∌", -- U+0220C
+ ["notniva"] = "∌", -- U+0220C
+ ["notnivb"] = "⋾", -- U+022FE
+ ["notnivc"] = "⋽", -- U+022FD
+ ["npar"] = "∦", -- U+02226
+ ["nparallel"] = "∦", -- U+02226
+ ["nparsl"] = "⫽⃥", -- U+02AFD 020E5
+ ["npart"] = "∂̸", -- U+02202 00338
+ ["npolint"] = "⨔", -- U+02A14
+ ["npr"] = "⊀", -- U+02280
+ ["nprcue"] = "â‹ ", -- U+022E0
+ ["npre"] = "⪯̸", -- U+02AAF 00338
+ ["nprec"] = "⊀", -- U+02280
+ ["npreceq"] = "⪯̸", -- U+02AAF 00338
+ ["nrArr"] = "â‡", -- U+021CF
+ ["nrarr"] = "↛", -- U+0219B
+ ["nrarrc"] = "⤳̸", -- U+02933 00338
+ ["nrarrw"] = "â†Ì¸", -- U+0219D 00338
+ ["nrightarrow"] = "↛", -- U+0219B
+ ["nrtri"] = "â‹«", -- U+022EB
+ ["nrtrie"] = "â‹­", -- U+022ED
+ ["nsc"] = "âŠ", -- U+02281
+ ["nsccue"] = "â‹¡", -- U+022E1
+ ["nsce"] = "⪰̸", -- U+02AB0 00338
+ ["nscr"] = "ð“ƒ", -- U+1D4C3
+ ["nshortmid"] = "∤", -- U+02224
+ ["nshortparallel"] = "∦", -- U+02226
+ ["nsim"] = "â‰", -- U+02241
+ ["nsime"] = "≄", -- U+02244
+ ["nsimeq"] = "≄", -- U+02244
+ ["nsmid"] = "∤", -- U+02224
+ ["nspar"] = "∦", -- U+02226
+ ["nsqsube"] = "â‹¢", -- U+022E2
+ ["nsqsupe"] = "â‹£", -- U+022E3
+ ["nsub"] = "⊄", -- U+02284
+ ["nsubE"] = "⫅̸", -- U+02AC5 00338
+ ["nsube"] = "⊈", -- U+02288
+ ["nsubset"] = "⊂⃒", -- U+02282 020D2
+ ["nsubseteq"] = "⊈", -- U+02288
+ ["nsubseteqq"] = "⫅̸", -- U+02AC5 00338
+ ["nsucc"] = "âŠ", -- U+02281
+ ["nsucceq"] = "⪰̸", -- U+02AB0 00338
+ ["nsup"] = "⊅", -- U+02285
+ ["nsupE"] = "⫆̸", -- U+02AC6 00338
+ ["nsupe"] = "⊉", -- U+02289
+ ["nsupset"] = "⊃⃒", -- U+02283 020D2
+ ["nsupseteq"] = "⊉", -- U+02289
+ ["nsupseteqq"] = "⫆̸", -- U+02AC6 00338
+ ["ntgl"] = "≹", -- U+02279
+ ["ntilde"] = "ñ", -- U+000F1
+ ["ntlg"] = "≸", -- U+02278
+ ["ntriangleleft"] = "⋪", -- U+022EA
+ ["ntrianglelefteq"] = "⋬", -- U+022EC
+ ["ntriangleright"] = "â‹«", -- U+022EB
+ ["ntrianglerighteq"] = "â‹­", -- U+022ED
+ ["nu"] = "ν", -- U+003BD
+ ["num"] = "#", -- U+00023
+ ["numero"] = "â„–", -- U+02116
+ ["numsp"] = " ", -- U+02007
+ ["nvDash"] = "⊭", -- U+022AD
+ ["nvHarr"] = "⤄", -- U+02904
+ ["nvap"] = "â‰âƒ’", -- U+0224D 020D2
+ ["nvdash"] = "⊬", -- U+022AC
+ ["nvge"] = "≥⃒", -- U+02265 020D2
+ ["nvgt"] = ">⃒", -- U+0003E 020D2
+ ["nvinfin"] = "⧞", -- U+029DE
+ ["nvlArr"] = "⤂", -- U+02902
+ ["nvle"] = "≤⃒", -- U+02264 020D2
+ ["nvlt"] = "&⃒", -- U+00026 020D2
+ ["nvltrie"] = "⊴⃒", -- U+022B4 020D2
+ ["nvrArr"] = "⤃", -- U+02903
+ ["nvrtrie"] = "⊵⃒", -- U+022B5 020D2
+ ["nvsim"] = "∼⃒", -- U+0223C 020D2
+ ["nwArr"] = "⇖", -- U+021D6
+ ["nwarhk"] = "⤣", -- U+02923
+ ["nwarr"] = "↖", -- U+02196
+ ["nwarrow"] = "↖", -- U+02196
+ ["nwnear"] = "⤧", -- U+02927
+ ["oS"] = "Ⓢ", -- U+024C8
+ ["oacgr"] = "ό", -- U+003CC
+ ["oacute"] = "ó", -- U+000F3
+ ["oast"] = "⊛", -- U+0229B
+ ["ocir"] = "⊚", -- U+0229A
+ ["ocirc"] = "ô", -- U+000F4
+ ["ocy"] = "о", -- U+0043E
+ ["odash"] = "âŠ", -- U+0229D
+ ["odblac"] = "Å‘", -- U+00151
+ ["odiv"] = "⨸", -- U+02A38
+ ["odot"] = "⊙", -- U+02299
+ ["odsold"] = "⦼", -- U+029BC
+ ["oelig"] = "Å“", -- U+00153
+ ["ofcir"] = "⦿", -- U+029BF
+ ["ofr"] = "ð”¬", -- U+1D52C
+ ["ogon"] = "Ë›", -- U+002DB
+ ["ogr"] = "ο", -- U+003BF
+ ["ograve"] = "ò", -- U+000F2
+ ["ogt"] = "â§", -- U+029C1
+ ["ohacgr"] = "ÏŽ", -- U+003CE
+ ["ohbar"] = "⦵", -- U+029B5
+ ["ohgr"] = "ω", -- U+003C9
+ ["ohm"] = "Ω", -- U+003A9
+ ["oint"] = "∮", -- U+0222E
+ ["olarr"] = "↺", -- U+021BA
+ ["olcir"] = "⦾", -- U+029BE
+ ["olcross"] = "⦻", -- U+029BB
+ ["oline"] = "‾", -- U+0203E
+ ["olt"] = "⧀", -- U+029C0
+ ["omacr"] = "Å", -- U+0014D
+ ["omega"] = "ω", -- U+003C9
+ ["omicron"] = "ο", -- U+003BF
+ ["omid"] = "⦶", -- U+029B6
+ ["ominus"] = "⊖", -- U+02296
+ ["oopf"] = "ð• ", -- U+1D560
+ ["opar"] = "⦷", -- U+029B7
+ ["operp"] = "⦹", -- U+029B9
+ ["oplus"] = "⊕", -- U+02295
+ ["or"] = "∨", -- U+02228
+ ["orarr"] = "↻", -- U+021BB
+ ["ord"] = "â©", -- U+02A5D
+ ["order"] = "â„´", -- U+02134
+ ["orderof"] = "â„´", -- U+02134
+ ["ordf"] = "ª", -- U+000AA
+ ["ordm"] = "º", -- U+000BA
+ ["origof"] = "⊶", -- U+022B6
+ ["oror"] = "â©–", -- U+02A56
+ ["orslope"] = "â©—", -- U+02A57
+ ["orv"] = "â©›", -- U+02A5B
+ ["oscr"] = "â„´", -- U+02134
+ ["oslash"] = "ø", -- U+000F8
+ ["osol"] = "⊘", -- U+02298
+ ["otilde"] = "õ", -- U+000F5
+ ["otimes"] = "⊗", -- U+02297
+ ["otimesas"] = "⨶", -- U+02A36
+ ["ouml"] = "ö", -- U+000F6
+ ["ovbar"] = "⌽", -- U+0233D
+ ["par"] = "∥", -- U+02225
+ ["para"] = "¶", -- U+000B6
+ ["parallel"] = "∥", -- U+02225
+ ["parsim"] = "⫳", -- U+02AF3
+ ["parsl"] = "⫽", -- U+02AFD
+ ["part"] = "∂", -- U+02202
+ ["pcy"] = "п", -- U+0043F
+ ["percnt"] = "%", -- U+00025
+ ["period"] = ".", -- U+0002E
+ ["permil"] = "‰", -- U+02030
+ ["perp"] = "⊥", -- U+022A5
+ ["pertenk"] = "‱", -- U+02031
+ ["pfr"] = "ð”­", -- U+1D52D
+ ["pgr"] = "Ï€", -- U+003C0
+ ["phgr"] = "φ", -- U+003C6
+ ["phi"] = "φ", -- U+003C6
+ ["phiv"] = "Ï•", -- U+003D5
+ ["phmmat"] = "ℳ", -- U+02133
+ ["phone"] = "☎", -- U+0260E
+ ["pi"] = "Ï€", -- U+003C0
+ ["pitchfork"] = "â‹”", -- U+022D4
+ ["piv"] = "Ï–", -- U+003D6
+ ["planck"] = "â„", -- U+0210F
+ ["planckh"] = "â„Ž", -- U+0210E
+ ["plankv"] = "â„", -- U+0210F
+ ["plus"] = "+", -- U+0002B
+ ["plusacir"] = "⨣", -- U+02A23
+ ["plusb"] = "⊞", -- U+0229E
+ ["pluscir"] = "⨢", -- U+02A22
+ ["plusdo"] = "∔", -- U+02214
+ ["plusdu"] = "⨥", -- U+02A25
+ ["pluse"] = "⩲", -- U+02A72
+ ["plusmn"] = "±", -- U+000B1
+ ["plussim"] = "⨦", -- U+02A26
+ ["plustwo"] = "⨧", -- U+02A27
+ ["pm"] = "±", -- U+000B1
+ ["pointint"] = "⨕", -- U+02A15
+ ["popf"] = "ð•¡", -- U+1D561
+ ["pound"] = "£", -- U+000A3
+ ["pr"] = "≺", -- U+0227A
+ ["prE"] = "⪳", -- U+02AB3
+ ["prap"] = "⪷", -- U+02AB7
+ ["prcue"] = "≼", -- U+0227C
+ ["pre"] = "⪯", -- U+02AAF
+ ["prec"] = "≺", -- U+0227A
+ ["precapprox"] = "⪷", -- U+02AB7
+ ["preccurlyeq"] = "≼", -- U+0227C
+ ["preceq"] = "⪯", -- U+02AAF
+ ["precnapprox"] = "⪹", -- U+02AB9
+ ["precneqq"] = "⪵", -- U+02AB5
+ ["precnsim"] = "⋨", -- U+022E8
+ ["precsim"] = "≾", -- U+0227E
+ ["prime"] = "′", -- U+02032
+ ["primes"] = "â„™", -- U+02119
+ ["prnE"] = "⪵", -- U+02AB5
+ ["prnap"] = "⪹", -- U+02AB9
+ ["prnsim"] = "⋨", -- U+022E8
+ ["prod"] = "âˆ", -- U+0220F
+ ["profalar"] = "⌮", -- U+0232E
+ ["profline"] = "⌒", -- U+02312
+ ["profsurf"] = "⌓", -- U+02313
+ ["prop"] = "âˆ", -- U+0221D
+ ["propto"] = "âˆ", -- U+0221D
+ ["prsim"] = "≾", -- U+0227E
+ ["prurel"] = "⊰", -- U+022B0
+ ["pscr"] = "ð“…", -- U+1D4C5
+ ["psgr"] = "ψ", -- U+003C8
+ ["psi"] = "ψ", -- U+003C8
+ ["puncsp"] = " ", -- U+02008
+ ["qfr"] = "ð”®", -- U+1D52E
+ ["qint"] = "⨌", -- U+02A0C
+ ["qopf"] = "ð•¢", -- U+1D562
+ ["qprime"] = "â—", -- U+02057
+ ["qscr"] = "ð“†", -- U+1D4C6
+ ["quaternions"] = "â„", -- U+0210D
+ ["quatint"] = "⨖", -- U+02A16
+ ["quest"] = "?", -- U+0003F
+ ["questeq"] = "≟", -- U+0225F
+ ["quot"] = "\"", -- U+00022
+ ["rAarr"] = "⇛", -- U+021DB
+ ["rArr"] = "⇒", -- U+021D2
+ ["rAtail"] = "⤜", -- U+0291C
+ ["rBarr"] = "â¤", -- U+0290F
+ ["rHar"] = "⥤", -- U+02964
+ ["race"] = "∽̱", -- U+0223D 00331
+ ["racute"] = "Å•", -- U+00155
+ ["radic"] = "√", -- U+0221A
+ ["raemptyv"] = "⦳", -- U+029B3
+ ["rang"] = "⟩", -- U+027E9
+ ["rangd"] = "⦒", -- U+02992
+ ["range"] = "⦥", -- U+029A5
+ ["rangle"] = "⟩", -- U+027E9
+ ["raquo"] = "»", -- U+000BB
+ ["rarr"] = "→", -- U+02192
+ ["rarrap"] = "⥵", -- U+02975
+ ["rarrb"] = "⇥", -- U+021E5
+ ["rarrbfs"] = "⤠", -- U+02920
+ ["rarrc"] = "⤳", -- U+02933
+ ["rarrfs"] = "⤞", -- U+0291E
+ ["rarrhk"] = "↪", -- U+021AA
+ ["rarrlp"] = "↬", -- U+021AC
+ ["rarrpl"] = "⥅", -- U+02945
+ ["rarrsim"] = "⥴", -- U+02974
+ ["rarrtl"] = "↣", -- U+021A3
+ ["rarrw"] = "â†", -- U+0219D
+ ["ratail"] = "⤚", -- U+0291A
+ ["ratio"] = "∶", -- U+02236
+ ["rationals"] = "â„š", -- U+0211A
+ ["rbarr"] = "â¤", -- U+0290D
+ ["rbbrk"] = "â³", -- U+02773
+ ["rbrace"] = "}", -- U+0007D
+ ["rbrack"] = "]", -- U+0005D
+ ["rbrke"] = "⦌", -- U+0298C
+ ["rbrksld"] = "⦎", -- U+0298E
+ ["rbrkslu"] = "â¦", -- U+02990
+ ["rcaron"] = "Å™", -- U+00159
+ ["rcedil"] = "Å—", -- U+00157
+ ["rceil"] = "⌉", -- U+02309
+ ["rcub"] = "}", -- U+0007D
+ ["rcy"] = "Ñ€", -- U+00440
+ ["rdca"] = "⤷", -- U+02937
+ ["rdldhar"] = "⥩", -- U+02969
+ ["rdquo"] = "â€", -- U+0201D
+ ["rdquor"] = "â€", -- U+0201D
+ ["rdsh"] = "↳", -- U+021B3
+ ["real"] = "ℜ", -- U+0211C
+ ["realine"] = "â„›", -- U+0211B
+ ["realpart"] = "ℜ", -- U+0211C
+ ["reals"] = "â„", -- U+0211D
+ ["rect"] = "â–­", -- U+025AD
+ ["reg"] = "®", -- U+000AE
+ ["rfisht"] = "⥽", -- U+0297D
+ ["rfloor"] = "⌋", -- U+0230B
+ ["rfr"] = "ð”¯", -- U+1D52F
+ ["rgr"] = "Ï", -- U+003C1
+ ["rhard"] = "â‡", -- U+021C1
+ ["rharu"] = "⇀", -- U+021C0
+ ["rharul"] = "⥬", -- U+0296C
+ ["rho"] = "Ï", -- U+003C1
+ ["rhov"] = "ϱ", -- U+003F1
+ ["rightarrow"] = "→", -- U+02192
+ ["rightarrowtail"] = "↣", -- U+021A3
+ ["rightharpoondown"] = "â‡", -- U+021C1
+ ["rightharpoonup"] = "⇀", -- U+021C0
+ ["rightleftarrows"] = "⇄", -- U+021C4
+ ["rightleftharpoons"] = "⇌", -- U+021CC
+ ["rightrightarrows"] = "⇉", -- U+021C9
+ ["rightsquigarrow"] = "â†", -- U+0219D
+ ["rightthreetimes"] = "⋌", -- U+022CC
+ ["ring"] = "Ëš", -- U+002DA
+ ["risingdotseq"] = "≓", -- U+02253
+ ["rlarr"] = "⇄", -- U+021C4
+ ["rlhar"] = "⇌", -- U+021CC
+ ["rlm"] = "â€", -- U+0200F
+ ["rmoust"] = "⎱", -- U+023B1
+ ["rmoustache"] = "⎱", -- U+023B1
+ ["rnmid"] = "â«®", -- U+02AEE
+ ["roang"] = "⟭", -- U+027ED
+ ["roarr"] = "⇾", -- U+021FE
+ ["robrk"] = "⟧", -- U+027E7
+ ["ropar"] = "⦆", -- U+02986
+ ["ropf"] = "ð•£", -- U+1D563
+ ["roplus"] = "⨮", -- U+02A2E
+ ["rotimes"] = "⨵", -- U+02A35
+ ["rpar"] = ")", -- U+00029
+ ["rpargt"] = "⦔", -- U+02994
+ ["rppolint"] = "⨒", -- U+02A12
+ ["rrarr"] = "⇉", -- U+021C9
+ ["rsaquo"] = "›", -- U+0203A
+ ["rscr"] = "ð“‡", -- U+1D4C7
+ ["rsh"] = "↱", -- U+021B1
+ ["rsqb"] = "]", -- U+0005D
+ ["rsquo"] = "’", -- U+02019
+ ["rsquor"] = "’", -- U+02019
+ ["rthree"] = "⋌", -- U+022CC
+ ["rtimes"] = "â‹Š", -- U+022CA
+ ["rtri"] = "â–¹", -- U+025B9
+ ["rtrie"] = "⊵", -- U+022B5
+ ["rtrif"] = "â–¸", -- U+025B8
+ ["rtriltri"] = "⧎", -- U+029CE
+ ["ruluhar"] = "⥨", -- U+02968
+ ["rx"] = "â„ž", -- U+0211E
+ ["sacute"] = "Å›", -- U+0015B
+ ["sbquo"] = "‚", -- U+0201A
+ ["sc"] = "≻", -- U+0227B
+ ["scE"] = "⪴", -- U+02AB4
+ ["scap"] = "⪸", -- U+02AB8
+ ["scaron"] = "Å¡", -- U+00161
+ ["sccue"] = "≽", -- U+0227D
+ ["sce"] = "⪰", -- U+02AB0
+ ["scedil"] = "ÅŸ", -- U+0015F
+ ["scirc"] = "Å", -- U+0015D
+ ["scnE"] = "⪶", -- U+02AB6
+ ["scnap"] = "⪺", -- U+02ABA
+ ["scnsim"] = "â‹©", -- U+022E9
+ ["scpolint"] = "⨓", -- U+02A13
+ ["scsim"] = "≿", -- U+0227F
+ ["scy"] = "Ñ", -- U+00441
+ ["sdot"] = "â‹…", -- U+022C5
+ ["sdotb"] = "⊡", -- U+022A1
+ ["sdote"] = "⩦", -- U+02A66
+ ["seArr"] = "⇘", -- U+021D8
+ ["searhk"] = "⤥", -- U+02925
+ ["searr"] = "↘", -- U+02198
+ ["searrow"] = "↘", -- U+02198
+ ["sect"] = "§", -- U+000A7
+ ["semi"] = ";", -- U+0003B
+ ["seswar"] = "⤩", -- U+02929
+ ["setminus"] = "∖", -- U+02216
+ ["setmn"] = "∖", -- U+02216
+ ["sext"] = "✶", -- U+02736
+ ["sfgr"] = "Ï‚", -- U+003C2
+ ["sfr"] = "ð”°", -- U+1D530
+ ["sfrown"] = "⌢", -- U+02322
+ ["sgr"] = "σ", -- U+003C3
+ ["sharp"] = "♯", -- U+0266F
+ ["shchcy"] = "щ", -- U+00449
+ ["shcy"] = "ш", -- U+00448
+ ["shortmid"] = "∣", -- U+02223
+ ["shortparallel"] = "∥", -- U+02225
+ ["shy"] = "­", -- U+000AD
+ ["sigma"] = "σ", -- U+003C3
+ ["sigmaf"] = "Ï‚", -- U+003C2
+ ["sigmav"] = "Ï‚", -- U+003C2
+ ["sim"] = "∼", -- U+0223C
+ ["simdot"] = "⩪", -- U+02A6A
+ ["sime"] = "≃", -- U+02243
+ ["simeq"] = "≃", -- U+02243
+ ["simg"] = "⪞", -- U+02A9E
+ ["simgE"] = "⪠", -- U+02AA0
+ ["siml"] = "âª", -- U+02A9D
+ ["simlE"] = "⪟", -- U+02A9F
+ ["simne"] = "≆", -- U+02246
+ ["simplus"] = "⨤", -- U+02A24
+ ["simrarr"] = "⥲", -- U+02972
+ ["slarr"] = "â†", -- U+02190
+ ["smallsetminus"] = "∖", -- U+02216
+ ["smashp"] = "⨳", -- U+02A33
+ ["smeparsl"] = "⧤", -- U+029E4
+ ["smid"] = "∣", -- U+02223
+ ["smile"] = "⌣", -- U+02323
+ ["smt"] = "⪪", -- U+02AAA
+ ["smte"] = "⪬", -- U+02AAC
+ ["smtes"] = "⪬︀", -- U+02AAC 0FE00
+ ["softcy"] = "ь", -- U+0044C
+ ["sol"] = "/", -- U+0002F
+ ["solb"] = "⧄", -- U+029C4
+ ["solbar"] = "⌿", -- U+0233F
+ ["sopf"] = "ð•¤", -- U+1D564
+ ["spades"] = "â™ ", -- U+02660
+ ["spadesuit"] = "â™ ", -- U+02660
+ ["spar"] = "∥", -- U+02225
+ ["sqcap"] = "⊓", -- U+02293
+ ["sqcaps"] = "⊓︀", -- U+02293 0FE00
+ ["sqcup"] = "⊔", -- U+02294
+ ["sqcups"] = "⊔︀", -- U+02294 0FE00
+ ["sqsub"] = "âŠ", -- U+0228F
+ ["sqsube"] = "⊑", -- U+02291
+ ["sqsubset"] = "âŠ", -- U+0228F
+ ["sqsubseteq"] = "⊑", -- U+02291
+ ["sqsup"] = "âŠ", -- U+02290
+ ["sqsupe"] = "⊒", -- U+02292
+ ["sqsupset"] = "âŠ", -- U+02290
+ ["sqsupseteq"] = "⊒", -- U+02292
+ ["squ"] = "â–¡", -- U+025A1
+ ["square"] = "â–¡", -- U+025A1
+ ["squarf"] = "â–ª", -- U+025AA
+ ["squf"] = "â–ª", -- U+025AA
+ ["srarr"] = "→", -- U+02192
+ ["sscr"] = "ð“ˆ", -- U+1D4C8
+ ["ssetmn"] = "∖", -- U+02216
+ ["ssmile"] = "⌣", -- U+02323
+ ["sstarf"] = "⋆", -- U+022C6
+ ["star"] = "☆", -- U+02606
+ ["starf"] = "★", -- U+02605
+ ["straightepsilon"] = "ϵ", -- U+003F5
+ ["straightphi"] = "Ï•", -- U+003D5
+ ["strns"] = "¯", -- U+000AF
+ ["sub"] = "⊂", -- U+02282
+ ["subE"] = "â«…", -- U+02AC5
+ ["subdot"] = "⪽", -- U+02ABD
+ ["sube"] = "⊆", -- U+02286
+ ["subedot"] = "⫃", -- U+02AC3
+ ["submult"] = "â«", -- U+02AC1
+ ["subnE"] = "â«‹", -- U+02ACB
+ ["subne"] = "⊊", -- U+0228A
+ ["subplus"] = "⪿", -- U+02ABF
+ ["subrarr"] = "⥹", -- U+02979
+ ["subset"] = "⊂", -- U+02282
+ ["subseteq"] = "⊆", -- U+02286
+ ["subseteqq"] = "â«…", -- U+02AC5
+ ["subsetneq"] = "⊊", -- U+0228A
+ ["subsetneqq"] = "â«‹", -- U+02ACB
+ ["subsim"] = "⫇", -- U+02AC7
+ ["subsub"] = "â«•", -- U+02AD5
+ ["subsup"] = "â«“", -- U+02AD3
+ ["succ"] = "≻", -- U+0227B
+ ["succapprox"] = "⪸", -- U+02AB8
+ ["succcurlyeq"] = "≽", -- U+0227D
+ ["succeq"] = "⪰", -- U+02AB0
+ ["succnapprox"] = "⪺", -- U+02ABA
+ ["succneqq"] = "⪶", -- U+02AB6
+ ["succnsim"] = "â‹©", -- U+022E9
+ ["succsim"] = "≿", -- U+0227F
+ ["sum"] = "∑", -- U+02211
+ ["sung"] = "♪", -- U+0266A
+ ["sup"] = "⊃", -- U+02283
+ ["sup1"] = "¹", -- U+000B9
+ ["sup2"] = "²", -- U+000B2
+ ["sup3"] = "³", -- U+000B3
+ ["supE"] = "⫆", -- U+02AC6
+ ["supdot"] = "⪾", -- U+02ABE
+ ["supdsub"] = "⫘", -- U+02AD8
+ ["supe"] = "⊇", -- U+02287
+ ["supedot"] = "â«„", -- U+02AC4
+ ["suphsol"] = "⟉", -- U+027C9
+ ["suphsub"] = "â«—", -- U+02AD7
+ ["suplarr"] = "⥻", -- U+0297B
+ ["supmult"] = "â«‚", -- U+02AC2
+ ["supnE"] = "⫌", -- U+02ACC
+ ["supne"] = "⊋", -- U+0228B
+ ["supplus"] = "â«€", -- U+02AC0
+ ["supset"] = "⊃", -- U+02283
+ ["supseteq"] = "⊇", -- U+02287
+ ["supseteqq"] = "⫆", -- U+02AC6
+ ["supsetneq"] = "⊋", -- U+0228B
+ ["supsetneqq"] = "⫌", -- U+02ACC
+ ["supsim"] = "⫈", -- U+02AC8
+ ["supsub"] = "â«”", -- U+02AD4
+ ["supsup"] = "â«–", -- U+02AD6
+ ["swArr"] = "⇙", -- U+021D9
+ ["swarhk"] = "⤦", -- U+02926
+ ["swarr"] = "↙", -- U+02199
+ ["swarrow"] = "↙", -- U+02199
+ ["swnwar"] = "⤪", -- U+0292A
+ ["szlig"] = "ß", -- U+000DF
+ ["target"] = "⌖", -- U+02316
+ ["tau"] = "Ï„", -- U+003C4
+ ["tbrk"] = "⎴", -- U+023B4
+ ["tcaron"] = "Å¥", -- U+00165
+ ["tcedil"] = "Å£", -- U+00163
+ ["tcy"] = "Ñ‚", -- U+00442
+ ["tdot"] = "⃛", -- U+020DB
+ ["telrec"] = "⌕", -- U+02315
+ ["tfr"] = "ð”±", -- U+1D531
+ ["tgr"] = "Ï„", -- U+003C4
+ ["there4"] = "∴", -- U+02234
+ ["therefore"] = "∴", -- U+02234
+ ["theta"] = "θ", -- U+003B8
+ ["thetasym"] = "Ï‘", -- U+003D1
+ ["thetav"] = "Ï‘", -- U+003D1
+ ["thgr"] = "θ", -- U+003B8
+ ["thickapprox"] = "≈", -- U+02248
+ ["thicksim"] = "∼", -- U+0223C
+ ["thinsp"] = " ", -- U+02009
+ ["thkap"] = "≈", -- U+02248
+ ["thksim"] = "∼", -- U+0223C
+ ["thorn"] = "þ", -- U+000FE
+ ["tilde"] = "˜", -- U+002DC
+ ["times"] = "×", -- U+000D7
+ ["timesb"] = "⊠", -- U+022A0
+ ["timesbar"] = "⨱", -- U+02A31
+ ["timesd"] = "⨰", -- U+02A30
+ ["tint"] = "∭", -- U+0222D
+ ["toea"] = "⤨", -- U+02928
+ ["top"] = "⊤", -- U+022A4
+ ["topbot"] = "⌶", -- U+02336
+ ["topcir"] = "⫱", -- U+02AF1
+ ["topf"] = "ð•¥", -- U+1D565
+ ["topfork"] = "â«š", -- U+02ADA
+ ["tosa"] = "⤩", -- U+02929
+ ["tprime"] = "‴", -- U+02034
+ ["trade"] = "â„¢", -- U+02122
+ ["triangle"] = "â–µ", -- U+025B5
+ ["triangledown"] = "â–¿", -- U+025BF
+ ["triangleleft"] = "â—ƒ", -- U+025C3
+ ["trianglelefteq"] = "⊴", -- U+022B4
+ ["triangleq"] = "≜", -- U+0225C
+ ["triangleright"] = "â–¹", -- U+025B9
+ ["trianglerighteq"] = "⊵", -- U+022B5
+ ["tridot"] = "â—¬", -- U+025EC
+ ["trie"] = "≜", -- U+0225C
+ ["triminus"] = "⨺", -- U+02A3A
+ ["triplus"] = "⨹", -- U+02A39
+ ["trisb"] = "â§", -- U+029CD
+ ["tritime"] = "⨻", -- U+02A3B
+ ["trpezium"] = "â¢", -- U+023E2
+ ["tscr"] = "ð“‰", -- U+1D4C9
+ ["tscy"] = "ц", -- U+00446
+ ["tshcy"] = "Ñ›", -- U+0045B
+ ["tstrok"] = "ŧ", -- U+00167
+ ["twixt"] = "≬", -- U+0226C
+ ["twoheadleftarrow"] = "↞", -- U+0219E
+ ["twoheadrightarrow"] = "↠", -- U+021A0
+ ["uArr"] = "⇑", -- U+021D1
+ ["uHar"] = "⥣", -- U+02963
+ ["uacgr"] = "Ï", -- U+003CD
+ ["uacute"] = "ú", -- U+000FA
+ ["uarr"] = "↑", -- U+02191
+ ["ubrcy"] = "Ñž", -- U+0045E
+ ["ubreve"] = "Å­", -- U+0016D
+ ["ucirc"] = "û", -- U+000FB
+ ["ucy"] = "у", -- U+00443
+ ["udarr"] = "⇅", -- U+021C5
+ ["udblac"] = "ű", -- U+00171
+ ["udhar"] = "⥮", -- U+0296E
+ ["udiagr"] = "ΰ", -- U+003B0
+ ["udigr"] = "Ï‹", -- U+003CB
+ ["ufisht"] = "⥾", -- U+0297E
+ ["ufr"] = "ð”²", -- U+1D532
+ ["ugr"] = "Ï…", -- U+003C5
+ ["ugrave"] = "ù", -- U+000F9
+ ["uharl"] = "↿", -- U+021BF
+ ["uharr"] = "↾", -- U+021BE
+ ["uhblk"] = "â–€", -- U+02580
+ ["ulcorn"] = "⌜", -- U+0231C
+ ["ulcorner"] = "⌜", -- U+0231C
+ ["ulcrop"] = "âŒ", -- U+0230F
+ ["ultri"] = "â—¸", -- U+025F8
+ ["umacr"] = "Å«", -- U+0016B
+ ["uml"] = "¨", -- U+000A8
+ ["uogon"] = "ų", -- U+00173
+ ["uopf"] = "ð•¦", -- U+1D566
+ ["uparrow"] = "↑", -- U+02191
+ ["updownarrow"] = "↕", -- U+02195
+ ["upharpoonleft"] = "↿", -- U+021BF
+ ["upharpoonright"] = "↾", -- U+021BE
+ ["uplus"] = "⊎", -- U+0228E
+ ["upsi"] = "Ï…", -- U+003C5
+ ["upsih"] = "Ï’", -- U+003D2
+ ["upsilon"] = "Ï…", -- U+003C5
+ ["upuparrows"] = "⇈", -- U+021C8
+ ["urcorn"] = "âŒ", -- U+0231D
+ ["urcorner"] = "âŒ", -- U+0231D
+ ["urcrop"] = "⌎", -- U+0230E
+ ["uring"] = "ů", -- U+0016F
+ ["urtri"] = "â—¹", -- U+025F9
+ ["uscr"] = "ð“Š", -- U+1D4CA
+ ["utdot"] = "â‹°", -- U+022F0
+ ["utilde"] = "Å©", -- U+00169
+ ["utri"] = "â–µ", -- U+025B5
+ ["utrif"] = "â–´", -- U+025B4
+ ["uuarr"] = "⇈", -- U+021C8
+ ["uuml"] = "ü", -- U+000FC
+ ["uwangle"] = "⦧", -- U+029A7
+ ["vArr"] = "⇕", -- U+021D5
+ ["vBar"] = "⫨", -- U+02AE8
+ ["vBarv"] = "â«©", -- U+02AE9
+ ["vDash"] = "⊨", -- U+022A8
+ ["vangrt"] = "⦜", -- U+0299C
+ ["varepsilon"] = "ϵ", -- U+003F5
+ ["varkappa"] = "Ï°", -- U+003F0
+ ["varnothing"] = "∅", -- U+02205
+ ["varphi"] = "Ï•", -- U+003D5
+ ["varpi"] = "Ï–", -- U+003D6
+ ["varpropto"] = "âˆ", -- U+0221D
+ ["varr"] = "↕", -- U+02195
+ ["varrho"] = "ϱ", -- U+003F1
+ ["varsigma"] = "Ï‚", -- U+003C2
+ ["varsubsetneq"] = "⊊︀", -- U+0228A 0FE00
+ ["varsubsetneqq"] = "⫋︀", -- U+02ACB 0FE00
+ ["varsupsetneq"] = "⊋︀", -- U+0228B 0FE00
+ ["varsupsetneqq"] = "⫌︀", -- U+02ACC 0FE00
+ ["vartheta"] = "Ï‘", -- U+003D1
+ ["vartriangleleft"] = "⊲", -- U+022B2
+ ["vartriangleright"] = "⊳", -- U+022B3
+ ["vcy"] = "в", -- U+00432
+ ["vdash"] = "⊢", -- U+022A2
+ ["vee"] = "∨", -- U+02228
+ ["veebar"] = "⊻", -- U+022BB
+ ["veeeq"] = "≚", -- U+0225A
+ ["vellip"] = "â‹®", -- U+022EE
+ ["verbar"] = "|", -- U+0007C
+ ["vert"] = "|", -- U+0007C
+ ["vfr"] = "ð”³", -- U+1D533
+ ["vltri"] = "⊲", -- U+022B2
+ ["vnsub"] = "⊂⃒", -- U+02282 020D2
+ ["vnsup"] = "⊃⃒", -- U+02283 020D2
+ ["vopf"] = "ð•§", -- U+1D567
+ ["vprop"] = "âˆ", -- U+0221D
+ ["vrtri"] = "⊳", -- U+022B3
+ ["vscr"] = "ð“‹", -- U+1D4CB
+ ["vsubnE"] = "⫋︀", -- U+02ACB 0FE00
+ ["vsubne"] = "⊊︀", -- U+0228A 0FE00
+ ["vsupnE"] = "⫌︀", -- U+02ACC 0FE00
+ ["vsupne"] = "⊋︀", -- U+0228B 0FE00
+ ["vzigzag"] = "⦚", -- U+0299A
+ ["wcirc"] = "ŵ", -- U+00175
+ ["wedbar"] = "â©Ÿ", -- U+02A5F
+ ["wedge"] = "∧", -- U+02227
+ ["wedgeq"] = "≙", -- U+02259
+ ["weierp"] = "℘", -- U+02118
+ ["wfr"] = "ð”´", -- U+1D534
+ ["wopf"] = "ð•¨", -- U+1D568
+ ["wp"] = "℘", -- U+02118
+ ["wr"] = "≀", -- U+02240
+ ["wreath"] = "≀", -- U+02240
+ ["wscr"] = "ð“Œ", -- U+1D4CC
+ ["xcap"] = "â‹‚", -- U+022C2
+ ["xcirc"] = "â—¯", -- U+025EF
+ ["xcup"] = "⋃", -- U+022C3
+ ["xdtri"] = "â–½", -- U+025BD
+ ["xfr"] = "ð”µ", -- U+1D535
+ ["xgr"] = "ξ", -- U+003BE
+ ["xhArr"] = "⟺", -- U+027FA
+ ["xharr"] = "⟷", -- U+027F7
+ ["xi"] = "ξ", -- U+003BE
+ ["xlArr"] = "⟸", -- U+027F8
+ ["xlarr"] = "⟵", -- U+027F5
+ ["xmap"] = "⟼", -- U+027FC
+ ["xnis"] = "â‹»", -- U+022FB
+ ["xodot"] = "⨀", -- U+02A00
+ ["xopf"] = "ð•©", -- U+1D569
+ ["xoplus"] = "â¨", -- U+02A01
+ ["xotime"] = "⨂", -- U+02A02
+ ["xrArr"] = "⟹", -- U+027F9
+ ["xrarr"] = "⟶", -- U+027F6
+ ["xscr"] = "ð“", -- U+1D4CD
+ ["xsqcup"] = "⨆", -- U+02A06
+ ["xuplus"] = "⨄", -- U+02A04
+ ["xutri"] = "â–³", -- U+025B3
+ ["xvee"] = "â‹", -- U+022C1
+ ["xwedge"] = "â‹€", -- U+022C0
+ ["yacute"] = "ý", -- U+000FD
+ ["yacy"] = "Ñ", -- U+0044F
+ ["ycirc"] = "Å·", -- U+00177
+ ["ycy"] = "Ñ‹", -- U+0044B
+ ["yen"] = "Â¥", -- U+000A5
+ ["yfr"] = "ð”¶", -- U+1D536
+ ["yicy"] = "Ñ—", -- U+00457
+ ["yopf"] = "ð•ª", -- U+1D56A
+ ["yscr"] = "ð“Ž", -- U+1D4CE
+ ["yucy"] = "ÑŽ", -- U+0044E
+ ["yuml"] = "ÿ", -- U+000FF
+ ["zacute"] = "ź", -- U+0017A
+ ["zcaron"] = "ž", -- U+0017E
+ ["zcy"] = "з", -- U+00437
+ ["zdot"] = "ż", -- U+0017C
+ ["zeetrf"] = "ℨ", -- U+02128
+ ["zeta"] = "ζ", -- U+003B6
+ ["zfr"] = "ð”·", -- U+1D537
+ ["zgr"] = "ζ", -- U+003B6
+ ["zhcy"] = "ж", -- U+00436
+ ["zigrarr"] = "â‡", -- U+021DD
+ ["zopf"] = "ð•«", -- U+1D56B
+ ["zscr"] = "ð“", -- U+1D4CF
+ ["zwj"] = "â€", -- U+0200D
+ ["zwnj"] = "‌", -- U+0200C
+}
+
+characters = characters or { }
+characters.entities = entities
+
+entities.plusminus = "±" -- 0x000B1
+entities.minusplus = "∓" -- 0x02213
+entities.cdots = utf.char(0x02026) -- U+02026
diff --git a/Master/texmf-dist/tex/context/base/char-ini.lua b/Master/texmf-dist/tex/context/base/char-ini.lua
index 89f8336f826..244b8d2a70e 100644
--- a/Master/texmf-dist/tex/context/base/char-ini.lua
+++ b/Master/texmf-dist/tex/context/base/char-ini.lua
@@ -8,14 +8,15 @@ if not modules then modules = { } end modules ['char-ini'] = {
-- todo: make two files, one for format generation, one for format use
+-- we can remove the tag range starting at 0xE0000 (special applications)
+
local tex = tex
local utf = unicode.utf8
local utfchar, utfbyte, utfvalues = utf.char, utf.byte, string.utfvalues
local ustring = unicode.ustring
-local concat, unpack = table.concat, table.unpack
+local concat, unpack, tohash = table.concat, table.unpack, table.tohash
local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset
-local texsprint, texprint = tex.sprint, tex.print
local format, lower, gsub, match, gmatch = string.format, string.lower, string.gsub, string.match, string.match, string.gmatch
local P, R, lpegmatch = lpeg.P, lpeg.R, lpeg.match
@@ -25,11 +26,14 @@ local texsetlccode = tex.setlccode
local texsetuccode = tex.setuccode
local texsetsfcode = tex.setsfcode
local texsetcatcode = tex.setcatcode
+
+local contextsprint = context.sprint
local ctxcatcodes = tex.ctxcatcodes
local texcatcodes = tex.texcatcodes
+
local setmetatableindex = table.setmetatableindex
-local trace_defining = false trackers.register("characters.defining", function(v) characters_defining = v end)
+local trace_defining = false trackers.register("characters.defining", function(v) characters_defining = v end)
local report_defining = logs.reporter("characters")
@@ -105,11 +109,11 @@ setmetatableindex(data, function(t,k)
if tk == "string" then
k = lpegmatch(pattern,k) or utfbyte(k)
if k then
- local tk = rawget(t,k)
- if tk then
- return tk
+ local v = rawget(t,k)
+ if v then
+ return v
else
- -- goes to ranges
+ tk = "number" -- fall through to range
end
else
return private
@@ -121,10 +125,10 @@ setmetatableindex(data, function(t,k)
if k >= rr.first and k <= rr.last then
local extender = rr.extender
if extender then
- v = extender(k,v)
+ local v = extender(k,v)
+ t[k] = v
+ return v
end
- t[k] = v
- return v
end
end
end
@@ -366,7 +370,7 @@ characters.categorytags = categorytags
--~ special : cf (softhyphen) zs (emspace)
--~ characters: ll lm lo lt lu mn nl no pc pd pe pf pi po ps sc sk sm so
-local is_character = allocate ( table.tohash {
+local is_character = allocate ( tohash {
"lu","ll","lt","lm","lo",
"nd","nl","no",
"mn",
@@ -375,19 +379,19 @@ local is_character = allocate ( table.tohash {
"sm","sc","sk","so"
} )
-local is_letter = allocate ( table.tohash {
+local is_letter = allocate ( tohash {
"ll","lm","lo","lt","lu"
} )
-local is_command = allocate ( table.tohash {
+local is_command = allocate ( tohash {
"cf","zs"
} )
-local is_spacing = allocate ( table.tohash {
+local is_spacing = allocate ( tohash {
"zs", "zl","zp",
} )
-local is_mark = allocate ( table.tohash {
+local is_mark = allocate ( tohash {
"mn", "ms",
} )
@@ -416,7 +420,7 @@ setmetatableindex(characters.is_spacing, mt)
-- linebreak: todo: hash
--
-- normative : BK CR LF CM SG GL CB SP ZW NL WJ JL JV JT H2 H3
--- informative : XX OP CL QU NS EX SY IS PR PO NU AL ID IN HY BB BA SA AI B2
+-- informative : XX OP CL QU NS EX SY IS PR PO NU AL ID IN HY BB BA SA AI B2 new:CP
-- east asian width:
--
@@ -485,20 +489,28 @@ use the table. After all, we have this information available anyway.</p>
--ldx]]--
function characters.makeactive(n,name) -- let ?
- texsprint(ctxcatcodes,format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name))
+ contextsprint(ctxcatcodes,format("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name))
-- context("\\catcode%s=13\\unexpanded\\def %s{\\%s}",n,utfchar(n),name)
end
function tex.uprint(c,n)
if n then
- -- texsprint(c,charfromnumber(n))
- texsprint(c,utfchar(n))
+ -- contextsprint(c,charfromnumber(n))
+ contextsprint(c,utfchar(n))
else
- -- texsprint(charfromnumber(c))
- texsprint(utfchar(c))
+ -- contextsprint(charfromnumber(c))
+ contextsprint(utfchar(c))
end
end
+local temphack = tohash {
+ 0x00A0,
+ 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x200B, 0x200C, 0x200D,
+ 0x202F,
+ 0x205F,
+ -- 0xFEFF,
+}
+
function characters.define(tobelettered, tobeactivated) -- catcodetables
if trace_defining then
@@ -510,7 +522,7 @@ function characters.define(tobelettered, tobeactivated) -- catcodetables
for u, chr in next, data do -- these will be commands
local fallback = chr.fallback
if fallback then
- texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}") -- no texprint
+ contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\checkedchar{",u,"}{",fallback,"}}}")
a = a + 1
activated[a] = u
else
@@ -520,17 +532,19 @@ function characters.define(tobelettered, tobeactivated) -- catcodetables
if is_character[category] then
if chr.unicodeslot < 128 then
if is_letter[category] then
- texprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u)))
+ contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u))) -- has no s
else
- texprint(ctxcatcodes,format("\\chardef\\%s=%s",contextname,u))
+ contextsprint(ctxcatcodes,format("\\chardef\\%s=%s",contextname,u)) -- has no s
end
else
- texprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u)))
+ contextsprint(ctxcatcodes,format("\\def\\%s{%s}",contextname,utfchar(u))) -- has no s
end
elseif is_command[category] then
- texsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}") -- no texprint
+if not temphack[u] then
+ contextsprint("{\\catcode",u,"=13\\unexpanded\\gdef ",utfchar(u),"{\\"..contextname,"}}")
a = a + 1
activated[a] = u
+end
end
end
end
@@ -564,7 +578,9 @@ function characters.define(tobelettered, tobeactivated) -- catcodetables
if tobeactivated and nofactivated > 0 then
for i=1,nofactivated do
local u = activated[i]
- report_defining("character 0x%05X is active in sets %s (%s)",u,concat(tobeactivated,","),data[u].description)
+ if u then
+ report_defining("character 0x%05X is active in sets %s (%s)",u,concat(tobeactivated,","),data[u].description)
+ end
end
local saved = tex.catcodetable
for i=1,#tobeactivated do
@@ -574,7 +590,10 @@ function characters.define(tobelettered, tobeactivated) -- catcodetables
end
tex.catcodetable = vector
for i=1,nofactivated do
- texsetcatcode(activated[i],13)
+ local u = activated[i]
+ if u then
+ texsetcatcode(u,13)
+ end
end
end
tex.catcodetable = saved
@@ -664,7 +683,7 @@ end
-- xml support (moved)
function characters.remapentity(chr,slot)
- texsprint(format("{\\catcode%s=13\\xdef%s{\\string%s}}",slot,utfchar(slot),chr))
+ contextsprint(format("{\\catcode%s=13\\xdef%s{\\string%s}}",slot,utfchar(slot),chr))
end
characters.activeoffset = 0x10000 -- there will be remapped in that byte range
@@ -724,11 +743,21 @@ setmetatableindex(shchars, function(t,u) if u then local c = data[u] c = c and c
setmetatableindex(fschars, function(t,u) if u then local c = data[u] c = c and c.fscode c = c and utfstring(c) or (type(u) == "number" and utfchar(u)) or u t[u] = c return c end end)
local decomposed = allocate() characters.decomposed = decomposed -- lazy table
+local specials = allocate() characters.specials = specials -- lazy table
setmetatableindex(decomposed, function(t,u) -- either a table or false
if u then
local c = data[u]
- local s = c and c.decomposed or false
+ local s = c and c.decomposed or false -- could fall back to specials
+ t[u] = s
+ return s
+ end
+end)
+
+setmetatableindex(specials, function(t,u) -- either a table or false
+ if u then
+ local c = data[u]
+ local s = c and c.specials or false
t[u] = s
return s
end
@@ -863,7 +892,7 @@ function characters.flush(n,direct)
if direct then
return c
else
- texsprint(c)
+ contextsprint(c)
end
end
@@ -986,3 +1015,7 @@ if not characters.superscripts then
storage.register("characters/subscripts", subscripts, "characters.subscripts")
end
+
+-- interface
+
+commands.utfchar = tex.uprint
diff --git a/Master/texmf-dist/tex/context/base/char-ini.mkiv b/Master/texmf-dist/tex/context/base/char-ini.mkiv
index 68bc3b49702..d1d7574c954 100644
--- a/Master/texmf-dist/tex/context/base/char-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/char-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -40,7 +40,7 @@
%
% impossible in math mode so there always fallback (till we have gyre):
-\def\utfchar #1{\ctxlua{tex.uprint(\number#1)}}
+\def\utfchar #1{\ctxcommand{utfchar(\number#1)}}
\def\checkedchar {\relax\ifmmode\expandafter\checkedmathchar\else\expandafter\checkedtextchar\fi} % #1#2
\def\checkedmathchar#1#2{#2}
\def\checkedtextchar #1{\iffontchar\font#1 \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi{\char#1}}
@@ -74,9 +74,6 @@
%number\mthcatcodes,
\number\vrbcatcodes,
\number\prtcatcodes,
-% \number\xmlcatcodesn,
-% \number\xmlcatcodese,
-% \number\xmlcatcodesr,
\number\tpacatcodes,
\number\tpbcatcodes,
\number\txtcatcodes,
@@ -85,9 +82,6 @@
\number\ctxcatcodes,
\number\notcatcodes,
\number\prtcatcodes, % new
-% \number\xmlcatcodesn,
-% \number\xmlcatcodese,
-% \number\xmlcatcodesr,
}
)
% catcodes.register("xmlcatcodes",\number\xmlcatcodes)
diff --git a/Master/texmf-dist/tex/context/base/char-utf.lua b/Master/texmf-dist/tex/context/base/char-utf.lua
index 30124a6a2a6..a411c2d82a6 100644
--- a/Master/texmf-dist/tex/context/base/char-utf.lua
+++ b/Master/texmf-dist/tex/context/base/char-utf.lua
@@ -27,6 +27,7 @@ local allocate = utilities.storage.allocate
local charfromnumber = characters.fromnumber
-- todo: trackers
+-- graphemes: basic symbols
characters = characters or { }
local characters = characters
@@ -34,6 +35,9 @@ local characters = characters
characters.graphemes = allocate()
local graphemes = characters.graphemes
+characters.combined = allocate()
+local combined = characters.combined
+
characters.decomposed = allocate()
local decomposed = characters.decomposed
@@ -46,6 +50,8 @@ local filters = characters.filters
filters.utf = filters.utf or { }
local utffilters = characters.filters.utf
+-- is characters.combined cached?
+
--[[ldx--
<p>It only makes sense to collapse at runtime, since we don't expect
source code to depend on collapsing.</p>
@@ -72,33 +78,48 @@ local decomposed = allocate {
}
characters.decomposed = decomposed
-local function initialize()
- for unicode, v in next, characters.data do
+local function initialize() -- maybe only 'mn'
+ local data = characters.data
+ for unicode, v in next, data do
-- using vs and first testing for length is faster (.02->.01 s)
local vs = v.specials
- if vs and #vs == 3 and vs[1] == 'char' then
+ local vc = vs and #vs == 3 and vs[1]
+ if vc == "char" then
local one, two = vs[2], vs[3]
- local first, second, combined = utfchar(one), utfchar(two), utfchar(unicode)
+ if data[two].category == "mn" then
+ local cgf = combined[one]
+ if not cgf then
+ cgf = { [two] = unicode }
+ combined[one] = cgf
+ else
+ cgf[two] = unicode
+ end
+ end
+ local first, second, combination = utfchar(one), utfchar(two), utfchar(unicode)
local cgf = graphemes[first]
if not cgf then
- cgf = { }
+ cgf = { [second] = combination }
graphemes[first] = cgf
+ else
+ cgf[second] = combination
end
- cgf[second] = combined
if v.mathclass or v.mathspec then
local mps = mathpairs[two]
if not mps then
- mps = { }
+ mps = { [one] = unicode }
mathpairs[two] = mps
+ else
+ mps[one] = unicode -- here unicode
end
- mps[one] = unicode -- here unicode
local mps = mathpairs[second]
if not mps then
- mps = { }
+ mps = { [first] = combination }
mathpairs[second] = mps
+ else
+ mps[first] = combination
end
- mps[first] = combined
end
+ -- elseif vc == "compat" then
-- else
-- local description = v.description
-- if find(description,"LIGATURE") then
@@ -122,8 +143,11 @@ local function initialize()
end
end
initialize = false
+ characters.initialize = function() end -- when used outside tex
end
+characters.initialize = initialize
+
-- utffilters.addgrapheme(utfchar(318),'l','\string~')
-- utffilters.addgrapheme('c','a','b')
@@ -440,17 +464,23 @@ function utffilters.decompose(str)
return str
end
-local textfileactions = resolvers.openers.helpers.textfileactions
+local sequencers = utilities.sequencers
+
+if sequencers then
-utilities.sequencers.appendaction (textfileactions,"system","characters.filters.utf.collapse")
-utilities.sequencers.disableaction(textfileactions,"characters.filters.utf.collapse")
+ local textfileactions = resolvers.openers.helpers.textfileactions
-utilities.sequencers.appendaction (textfileactions,"system","characters.filters.utf.decompose")
-utilities.sequencers.disableaction(textfileactions,"characters.filters.utf.decompose")
+ sequencers.appendaction (textfileactions,"system","characters.filters.utf.collapse")
+ sequencers.disableaction(textfileactions,"characters.filters.utf.collapse")
+
+ sequencers.appendaction (textfileactions,"system","characters.filters.utf.decompose")
+ sequencers.disableaction(textfileactions,"characters.filters.utf.decompose")
+
+ function characters.filters.utf.enable()
+ sequencers.enableaction(textfileactions,"characters.filters.utf.collapse")
+ sequencers.enableaction(textfileactions,"characters.filters.utf.decompose")
+ end
-function characters.filters.utf.enable()
- utilities.sequencers.enableaction(textfileactions,"characters.filters.utf.collapse")
- utilities.sequencers.enableaction(textfileactions,"characters.filters.utf.decompose")
end
--[[ldx--
diff --git a/Master/texmf-dist/tex/context/base/char-utf.mkiv b/Master/texmf-dist/tex/context/base/char-utf.mkiv
index 2617356567d..280e7ef6daf 100644
--- a/Master/texmf-dist/tex/context/base/char-utf.mkiv
+++ b/Master/texmf-dist/tex/context/base/char-utf.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Unicode UTF,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/chem-ini.mkiv b/Master/texmf-dist/tex/context/base/chem-ini.mkiv
index c64575181db..c0a1d021e7c 100644
--- a/Master/texmf-dist/tex/context/base/chem-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/chem-ini.mkiv
@@ -4,7 +4,7 @@
%D subtitle=Chemistry,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/chem-str.lua b/Master/texmf-dist/tex/context/base/chem-str.lua
index 1a6ed4dc213..6e2af50fb4b 100644
--- a/Master/texmf-dist/tex/context/base/chem-str.lua
+++ b/Master/texmf-dist/tex/context/base/chem-str.lua
@@ -17,7 +17,7 @@ local report_chemistry = logs.reporter("chemistry")
local format, gmatch, match, lower, gsub = string.format, string.gmatch, string.match, string.lower, string.gsub
local concat, insert, remove = table.concat, table.insert, table.remove
-local apply = structures.processors.apply
+local processor_tostring = typesetters.processors.tostring
local lpegmatch = lpeg.match
local settings_to_array = utilities.parsers.settings_to_array
@@ -230,9 +230,9 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
m = m + 1 ; metacode[m] = syntax.pb.direct
if keys[special] == "text" and index then
if keys["c"..special] == "text" then -- can be option: auto ...
- metacode[#metacode+1] = format('chem_c%s(%s,%s,"");',special,bonds,index)
+ m = m + 1 ; metacode[m] = format('chem_c%s(%s,%s,"");',special,bonds,index)
else
- metacode[#metacode+1] = format('chem_%s(%s,%s,"");',special,bonds,index)
+ m = m + 1 ; metacode[m] = format('chem_%s(%s,%s,"");',special,bonds,index)
end
end
elseif operation == "save" then
@@ -319,7 +319,8 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if t then
local a = align and align[si]
if a then a = "." .. a else a = "" end
- m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,a,bonds,si,molecule(apply(t)))
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,a,bonds,si,t)
end
end
elseif upto then
@@ -329,14 +330,16 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if t then
local s = align and align[i]
if s then s = "." .. s else s = "" end
- m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,molecule(apply(t)))
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,t)
end
end
elseif index == 0 then
local t = text
if not t then txt, t = fetch(txt) end
if t then
- m = m + 1 ; metacode[m] = format('chem_%s_zero("\\dochemicaltext{%s}");',operation,molecule(apply(t)))
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format('chem_%s_zero("\\dochemicaltext{%s}");',operation,t)
end
elseif index then
local t = text
@@ -344,7 +347,8 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if t then
local s = align and align[index]
if s then s = "." .. s else s = "" end
- m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,index,molecule(apply(t)))
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,index,t)
end
else
for i=1,max do
@@ -353,7 +357,8 @@ local function process(spec,text,n,rulethickness,rulecolor,offset)
if t then
local s = align and align[i]
if s then s = "." .. s else s = "" end
- m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,molecule(apply(t)))
+ t = molecule(processor_tostring(t))
+ m = m + 1 ; metacode[m] = format('chem_%s%s(%s,%s,"\\dochemicaltext{%s}");',operation,s,bonds,i,t)
end
end
end
@@ -388,6 +393,9 @@ function chemicals.start(settings)
local textsize, rulethickness, rulecolor = settings.size, settings.rulethickness, settings.rulecolor
local width, height, scale, offset = settings.width or 0, settings.height or 0, settings.scale or "medium", settings.offset or 0
local l, r, t, b = settings.left or 0, settings.right or 0, settings.top or 0, settings.bottom or 0
+ --
+ metacode = { "if unknown context_chem : input mp-chem.mpiv ; fi ;" } -- no format anyway
+ --
if scale == variables.small then
scale = 500
elseif scale == variables.medium or scale == 0 then
@@ -398,8 +406,8 @@ function chemicals.start(settings)
scale = tonumber(scale)
if not scale or scale == 0 then
scale = 750
- elseif scale < 500 then
- scale = 500
+ elseif scale < 10 then
+ scale = 10
end
end
if width == variables.fit then
@@ -435,16 +443,19 @@ function chemicals.start(settings)
height = false
end
scale = 0.75 * scale/625
- metacode = { format("chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) ;",
+ --
+ metacode[#metacode+1] = format("chem_start_structure(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) ;",
chemicals.structures,
l/25, r/25, t/25, b/25, scale,
tostring(settings.axis == variables.on), tostring(width), tostring(height), tostring(offset)
- ) }
+ )
+ --
variant, keys, bonds, stack, rot, pstack = "six", { }, 6, { }, 1, { }
end
function chemicals.stop()
metacode[#metacode+1] = "chem_stop_structure ;"
+ --
local mpcode = concat(metacode,"\n")
if trace_structure then
report_chemistry("metapost code:\n%s", mpcode)
diff --git a/Master/texmf-dist/tex/context/base/chem-str.mkiv b/Master/texmf-dist/tex/context/base/chem-str.mkiv
index 6430830f73a..197c13bc6a2 100644
--- a/Master/texmf-dist/tex/context/base/chem-str.mkiv
+++ b/Master/texmf-dist/tex/context/base/chem-str.mkiv
@@ -4,7 +4,7 @@
%D subtitle=Chemistry,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -49,6 +49,8 @@
\unprotect
+\installcorenamespace{chemicalsymbol}
+
\unexpanded\def\setupchemical
{\dosingleempty\dosetupchemical}
@@ -80,16 +82,16 @@
{\dodoubleempty\dodefinechemicalsymbol}
\def\dodefinechemicalsymbol[#1][#2]%
- {\setvalue{\??cm::#1}{#2}}
+ {\setvalue{\??chemicalsymbol#1}{#2}}
-\def\chemicalsymbol[#1]%
- {\getvalue{\??cm::#1}}
+\unexpanded\def\chemicalsymbol[#1]%
+ {\getvalue{\??chemicalsymbol#1}}
% size (small medium big)
-\def\dosetchemicaltext
- {\dosetfontattribute \??cm\c!style
- \dosetcolorattribute\??cm\c!color}
+\unexpanded\def\dosetchemicaltext
+ {\dousestyleparameter\@@cmstyle
+ \dousecolorparameter\@@cmcolor}
\edef\chemicaltoplocation{t}
\edef\chemicalbotlocation{b}
@@ -194,7 +196,7 @@
\ignorespaces}
\appendtoks
- \setbox\chemicalbox\hbox{\raise\MPlly\onebasepoint\box\chemicalbox}%
+ \setbox\chemicalbox\hbox{\raise\MPlly\box\chemicalbox}%
\chemicalwidth \wd\chemicalbox
\chemicalheight\ht\chemicalbox
\chemicaldepth \dp\chemicalbox
@@ -204,7 +206,9 @@
\appendtoks
\edef\chemicalbodyfont{\chemicalparameter\c!bodyfont}%
- \doifnot\chemicalbodyfont\fontbody{\switchtobodyfont[\chemicalbodyfont]}% \fontbody is not expanded (yet)
+ \ifx\chemicalbodyfont\empty
+ \switchtobodyfont[\chemicalbodyfont]%
+ \fi
\getvalue{\??cm:\c!size:\chemicalparameter\c!size}%
% \to \everystructurechemical
\to \everychemical
@@ -269,6 +273,8 @@
\mathematics{#1%
{\strut\hbox \!!spread 2em{\hss\ctxlua{chemicals.inline(\!!bs#2\!!es)}\hss}}%
{\strut\hbox \!!spread 2em{\hss\ctxlua{chemicals.inline(\!!bs#3\!!es)}\hss}}}%
+% {\strut\hbox \!!spread 2em{\hss#2\hss}}%
+% {\strut\hbox \!!spread 2em{\hss#3\hss}}}%
\enspace}
% special macros (probably needs some more work)
@@ -278,7 +284,7 @@
\setbox0\hbox{\tx\setstrut\strut#3}%
\setbox2\hbox{\setstrut\strut\molecule{#4}}%
\setbox0\hbox{\raise\dimexpr\dp0+\ht2\relax\hbox to \wd2{#1\box0#2}}%
- \smashbox0
+% no: \smashbox0
\hbox{\box0\box2}%
\endgroup}%
@@ -287,7 +293,7 @@
\setbox0\hbox{\tx\setstrut\strut#3}%
\setbox2\hbox{\setstrut\strut#4}%
\setbox0\hbox{\lower\dimexpr\dp2+\ht0\relax\hbox to \wd2{#1\box0#2}}%
- \smashbox0
+% no: \smashbox0
\hbox{\box0\box2}%
\endgroup}%
@@ -337,7 +343,7 @@
\let\chemicalsmashedright \chemicalrightcentered
\unexpanded\def\chemicaloxidation#1#2#3%
- {\chemicaltop{\txx\ifcase#2\relax0\else#1\uppercase\expandafter{\romannumeral#2}\fi}{#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!
@@ -487,27 +493,51 @@
\unexpanded\def\formulachemical
{\relax\dotriplegroupempty\doformulachemical}
+% \def\doformulachemical#1#2#3% we could do hboxes and measure
+% {\ifthirdargument
+% \doifelsenothing{#2}\noformulachemicaltop{\doformulachemicaltop{#2}}%
+% \doifelsenothing{#3}\noformulachemicalbot{\doformulachemicalbot{#3}}%
+% \else\ifsecondargument
+% \noformulachemicaltop
+% \doifelsenothing{#2}\noformulachemicalbot{\doformulachemicalbot{#2}}%
+% \else
+% \noformulachemicaltop
+% \noformulachemicalbot
+% \fi\fi
+% \formulachemicalmid\expandafter{\the\formulachemicalmid\dodochemicalformulamid{#1}&}}
+%
+% \def\dodochemicalformulamid#1%
+% {\ifcsname\??chemicalsymbol\detokenize{#1}\endcsname
+% \csname\??chemicalsymbol\detokenize{#1}\expandafter\endcsname{}{}%
+% \else
+% \molecule{#1}{}{}%
+% \fi}
+
+\def\domidformulachemical#1%
+ {\csname\??chemicalsymbol\detokenize{#1}\endcsname}
+
\def\doformulachemical#1#2#3% we could do hboxes and measure
- {\ifthirdargument
- \doifelsenothing{#2}\noformulachemicaltop{\doformulachemicaltop{#2}}%
- \doifelsenothing{#3}\noformulachemicalbot{\doformulachemicalbot{#3}}%
- \else\ifsecondargument
- \noformulachemicaltop
- \doifelsenothing{#2}\noformulachemicalbot{\doformulachemicalbot{#2}}%
+ {\ifcsname\??chemicalsymbol\detokenize{#1}\endcsname
+ \formulachemicalmid\expandafter{\the\formulachemicalmid\domidformulachemical{#1}{#2}{#3}}%
\else
- \noformulachemicaltop
- \noformulachemicalbot
- \fi\fi
- \formulachemicalmid\expandafter{\the\formulachemicalmid\dodochemicalformulamid{#1}&}}
+ \ifthirdargument
+ \doifelsenothing{#2}\noformulachemicaltop{\doformulachemicaltop{#2}}%
+ \doifelsenothing{#3}\noformulachemicalbot{\doformulachemicalbot{#3}}%
+ \else\ifsecondargument
+ \noformulachemicaltop
+ \doifelsenothing{#2}\noformulachemicalbot{\doformulachemicalbot{#2}}%
+ \else
+ \noformulachemicaltop
+ \noformulachemicalbot
+ \fi\fi
+ \formulachemicalmid\expandafter{\the\formulachemicalmid\molecule{#1}&}%
+ \fi}
\def\noformulachemicaltop {\formulachemicaltop\expandafter{\the\formulachemicaltop&}}
\def\noformulachemicalbot {\formulachemicalbot\expandafter{\the\formulachemicalbot&}}
\def\doformulachemicaltop#1{\formulachemicaltop\expandafter{\the\formulachemicaltop\dodochemicalformulatop{#1}&}\settrue\formulachemicalhastop}
\def\doformulachemicalbot#1{\formulachemicalbot\expandafter{\the\formulachemicalbot\dodochemicalformulabot{#1}&}\settrue\formulachemicalhasbot}
-\def\dodochemicalformulamid#1%
- {\ifcsname\??cm::\detokenize{#1}\endcsname\csname\??cm::\detokenize{#1}\expandafter\endcsname\else\molecule{#1}\fi{}{}}
-
\def\dodochemicalformulatop#1{\strut#1}
\def\dodochemicalformulabot#1{\strut#1}
@@ -527,7 +557,7 @@
\c!right=0,
\c!top=0,
\c!bottom=0,
- \c!bodyfont=\the\bodyfontsize,
+ \c!bodyfont=,
\c!scale=\v!medium,
\c!size=\v!medium,
\c!textsize=\v!big,
diff --git a/Master/texmf-dist/tex/context/base/cldf-bas.lua b/Master/texmf-dist/tex/context/base/cldf-bas.lua
new file mode 100644
index 00000000000..30a9265bce4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/cldf-bas.lua
@@ -0,0 +1,140 @@
+if not modules then modules = { } end modules ['cldf-ini'] = {
+ version = 1.001,
+ comment = "companion to cldf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- -- speedtest needed:
+--
+-- local flush, writer = context.getlogger()
+--
+-- trackers.register("context.trace",function(v)
+-- flush, writer = context.getlogger()
+-- end)
+--
+-- function context.bgroup()
+-- flush(ctxcatcodes,"{")
+-- end
+--
+-- function context.egroup()
+-- flush(ctxcatcodes,"}")
+-- end
+
+local type = type
+local format = string.format
+local utfchar = utf.char
+local concat = table.concat
+
+local context = context
+local generics = context.generics
+local variables = interfaces.variables
+
+local new_rule = nodes.pool.rule
+
+function context.char(k) -- used as escape too, so don't change to utf
+ if type(k) == "table" then
+ -- for i=1,#k do
+ -- context(format([[\char%s\relax]],k[i]))
+ -- end
+ context([[\char%s\relax]],concat(k,[[\relax\char]]))
+ elseif k then
+ context([[\char%s\relax]],k)
+ end
+end
+
+function context.utfchar(k)
+ context(utfchar(k))
+end
+
+-- plain variants
+
+function context.chardef(cs,u)
+ context([[\chardef\%s=%s\relax]],k)
+end
+
+function context.par()
+ context([[\par]]) -- no need to add {} there
+end
+
+function context.bgroup()
+ context("{")
+end
+
+function context.egroup()
+ context("}")
+end
+
+function context.hrule(w,h,d,dir)
+ if type(w) == "table" then
+ context(new_rule(w.width,w.height,w.depth,w.dir))
+ else
+ context(new_rule(w,h,d,dir))
+ end
+end
+
+context.vrule = context.hrule
+
+--~ local hbox, bgroup, egroup = context.hbox, context.bgroup, context.egroup
+
+--~ function context.hbox(a,...)
+--~ if type(a) == "table" then
+--~ local s = { }
+--~ if a.width then
+--~ s[#s+1] = "to " .. a.width -- todo: check for number
+--~ elseif a.spread then
+--~ s[#s+1] = "spread " .. a.spread -- todo: check for number
+--~ end
+--~ -- todo: dir, attr etc
+--~ hbox(false,table.concat(s," "))
+--~ bgroup()
+--~ context(string.format(...))
+--~ egroup()
+--~ else
+--~ hbox(a,...)
+--~ end
+--~ end
+
+-- not yet used ... but will get variant at the tex end as well
+
+function context.sethboxregister (n) context("\\setbox %s\\hbox",n) end
+function context.setvboxregister (n) context("\\setbox %s\\vbox",n) end
+
+function context.starthboxregister(n)
+ if type(n) == "number" then
+ context("\\setbox%s\\hbox\\bgroup",n)
+ else
+ context("\\setbox\\%s\\hbox\\bgroup",n)
+ end
+end
+
+function context.startvboxregister(n)
+ if type(n) == "number" then
+ context("\\setbox%s\\vbox\\bgroup",n)
+ else
+ context("\\setbox\\%s\\vbox\\bgroup",n)
+ end
+end
+
+context.stophboxregister = context.egroup
+context.stopvboxregister = context.egroup
+
+function context.flushboxregister(n)
+ if type(n) == "number" then
+ context("\\box%s ",n)
+ else
+ context("\\box\\%s",n)
+ end
+end
+
+function context.beginvbox()
+ context("\\vbox\\bgroup") -- we can do \bvbox ... \evbox (less tokens)
+end
+
+function context.beginhbox()
+ context("\\hbox\\bgroup") -- todo: use fast one
+end
+
+context.endvbox = context.egroup
+context.endhbox = context.egroup
diff --git a/Master/texmf-dist/tex/context/base/cldf-bas.mkiv b/Master/texmf-dist/tex/context/base/cldf-bas.mkiv
new file mode 100644
index 00000000000..f2bd05177a1
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/cldf-bas.mkiv
@@ -0,0 +1,18 @@
+%D \module
+%D [ file=cldf-bas,
+%D version=2010.10.19,,
+%D title=\CONTEXT\ \LUA\ Document Functions,
+%D subtitle=Basics,
+%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 Lua Documents / Basics}
+
+\registerctxluafile{cldf-bas}{1.001}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/cldf-com.lua b/Master/texmf-dist/tex/context/base/cldf-com.lua
index e966b167b20..bacbbeafd6a 100644
--- a/Master/texmf-dist/tex/context/base/cldf-com.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-com.lua
@@ -6,11 +6,9 @@ if not modules then modules = { } end modules ['cldf-com'] = {
license = "see context related readme files"
}
-local tostring, type = tostring, type
-local format = string.format
-
+local tostring = tostring
local context = context
-local generics = context.generics
+local generics = context.generics -- needs documentation
local variables = interfaces.variables
generics.starttabulate = "start" .. variables.tabulate -- todo: e!start
@@ -37,69 +35,3 @@ function context.tabulaterow (...) tabulaterow(false, ...) end
function context.tabulaterowbold(...) tabulaterow("bold",...) end
function context.tabulaterowtype(...) tabulaterow("type",...) end
function context.tabulaterowtyp (...) tabulaterow("typ", ...) end
-
--- these will move up, just after cld definitions
-
-function context.char(k) -- todo: if catcode == letter or other then just the utf
- if type(k) == "table" then
- for i=1,#k do
- context(format([[\char%s\relax]],k[i]))
- end
- elseif k then
- context(format([[\char%s\relax]],k))
- end
-end
-
-function context.utfchar(k)
- context(utfchar(k))
-end
-
--- plain variants
-
-function context.chardef(cs,u)
- context(format([[\chardef\%s=%s\relax]],k)) -- context does already do format
-end
-
-function context.par()
- context([[\par]]) -- no need to add {} there
-end
-
-function context.bgroup()
- context("{")
-end
-
-function context.egroup()
- context("}")
-end
-
-local rule = nodes.pool.rule
-
-function context.hrule(w,h,d,dir)
- if type(w) == "table" then
- context(rule(w.width,w.height,w.depth,w.dir))
- else
- context(rule(w,h,d,dir))
- end
-end
-
-context.vrule = context.hrule
-
---~ local hbox, bgroup, egroup = context.hbox, context.bgroup, context.egroup
-
---~ function context.hbox(a,...)
---~ if type(a) == "table" then
---~ local s = { }
---~ if a.width then
---~ s[#s+1] = "to " .. a.width -- todo: check for number
---~ elseif a.spread then
---~ s[#s+1] = "spread " .. a.spread -- todo: check for number
---~ end
---~ -- todo: dir, attr etc
---~ hbox(false,table.concat(s," "))
---~ bgroup()
---~ context(string.format(...))
---~ egroup()
---~ else
---~ hbox(a,...)
---~ end
---~ end
diff --git a/Master/texmf-dist/tex/context/base/cldf-com.mkiv b/Master/texmf-dist/tex/context/base/cldf-com.mkiv
index 43071a58053..49190988893 100644
--- a/Master/texmf-dist/tex/context/base/cldf-com.mkiv
+++ b/Master/texmf-dist/tex/context/base/cldf-com.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cldf-ini.lua b/Master/texmf-dist/tex/context/base/cldf-ini.lua
index 8edc0502321..ed86c29234f 100644
--- a/Master/texmf-dist/tex/context/base/cldf-ini.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-ini.lua
@@ -6,35 +6,34 @@ if not modules then modules = { } end modules ['cldf-ini'] = {
license = "see context related readme files"
}
--- This is an experiment: generating context code at the lua end. After all
--- it is surprisingly simple to implement due to metatables. I was wondering
--- if there was a more natural way to deal with commands at the lua end.
--- Of course it's a bit slower but often more readable when mixed with lua
--- code. It can also be handy when generating documents from databases or
--- when constructing large tables or so.
+-- This started as an experiment: generating context code at the lua end. After all
+-- it is surprisingly simple to implement due to metatables. I was wondering if
+-- there was a more natural way to deal with commands at the lua end. Of course it's
+-- a bit slower but often more readable when mixed with lua code. It can also be handy
+-- when generating documents from databases or when constructing large tables or so.
--
--- Todo: optional checking against interface
--- Todo: coroutine trickery
--- Todo: maybe use txtcatcodes
-
+-- maybe optional checking against interface
+-- currently no coroutine trickery
+-- we could always use prtcatcodes (context.a_b_c) but then we loose protection
-- tflush needs checking ... sort of weird that it's not a table
-
-- __flushlines is an experiment and rather ugly so it will go away
+--
+-- tex.print == line with endlinechar appended
local tex = tex
context = context or { }
local context = context
-local format, find, gmatch, splitlines = string.format, string.find, string.gmatch, string.splitlines
-local next, type, tostring, setmetatable = next, type, tostring, setmetatable
+local format, find, gmatch, gsub = string.format, string.find, string.gmatch, string.gsub
+local next, type, tostring, tonumber, setmetatable = next, type, tostring, tonumber, setmetatable
local insert, remove, concat = table.insert, table.remove, table.concat
-local lpegmatch = lpeg.match
+local lpegmatch, lpegC, lpegS, lpegP, lpegCc = lpeg.match, lpeg.C, lpeg.S, lpeg.P, lpeg.Cc
local texsprint = tex.sprint
local textprint = tex.tprint
local texprint = tex.print
-local texiowrite = texio.write
+local texwrite = tex.write
local texcount = tex.count
local isnode = node.is_node -- after 0.65 just node.type
@@ -49,6 +48,8 @@ local vrbcatcodes = tex.vrbcatcodes
local xmlcatcodes = tex.xmlcatcodes
local flush = texsprint
+local flushdirect = texprint
+local flushraw = texwrite
local report_context = logs.reporter("cld","tex")
local report_cld = logs.reporter("cld","stack")
@@ -137,62 +138,188 @@ local catcodes = {
xml = xmlcatcodes, xmlcatcodes = xmlcatcodes,
}
-function context.pushcatcodes(c)
+local function pushcatcodes(c)
insert(catcodestack,currentcatcodes)
currentcatcodes = (c and catcodes[c] or tonumber(c)) or currentcatcodes
contentcatcodes = currentcatcodes
end
-function context.popcatcodes()
+local function popcatcodes()
currentcatcodes = remove(catcodestack) or currentcatcodes
contentcatcodes = currentcatcodes
end
-function tex.fprint(...) -- goodie
- texsprint(currentcatcodes,format(...))
-end
+context.pushcatcodes = pushcatcodes
+context.popcatcodes = popcatcodes
--- -- -- todo: tracing
+-- -- --
-local newline = lpeg.patterns.newline
-local space = lpeg.patterns.spacer
-local spacing = newline * space^0
-local content = lpeg.C((1-spacing)^1)
-local emptyline = space^0 * newline^2
-local endofline = space^0 * newline * space^0
-local simpleline = endofline * lpeg.P(-1)
+--~ local capture = (
+--~ space^0 * newline^2 * lpeg.Cc("") / texprint +
+--~ space^0 * newline * space^0 * lpeg.Cc(" ") / texsprint +
+--~ content / texsprint
+--~ )^0
+
+local newline = lpeg.patterns.newline
+local space = lpeg.patterns.spacer
+local spacing = newline * space^0
+local content = lpegC((1-spacing)^1) -- texsprint
+local emptyline = space^0 * newline^2 -- texprint("")
+local endofline = space^0 * newline * space^0 -- texsprint(" ")
+local simpleline = endofline * lpegP(-1) --
+
+local verbose = lpegC((1-space-newline)^1)
+local beginstripper = (lpegS(" \t")^1 * newline^1) / ""
+local endstripper = beginstripper * lpegP(-1)
+
+local justaspace = space * lpegCc("")
+local justanewline = newline * lpegCc("")
local function n_content(s)
flush(contentcatcodes,s)
end
+local function n_verbose(s)
+ flush(vrbcatcodes,s)
+end
+
local function n_endofline()
- texsprint(" \r")
+ flush(currentcatcodes," \r")
end
local function n_emptyline()
- texprint("\r")
+ flushdirect(currentcatcodes,"\r")
end
local function n_simpleline()
- texprint("\r")
+ flush(currentcatcodes," \r")
+end
+
+local n_exception = ""
+
+-- better a table specification
+
+function context.newtexthandler(specification) -- can also be used for verbose
+ specification = specification or { }
+ --
+ local s_catcodes = specification.catcodes
+ --
+ local f_before = specification.before
+ local f_after = specification.after
+ --
+ local f_endofline = specification.endofline or n_endofline
+ local f_emptyline = specification.emptyline or n_emptyline
+ local f_simpleline = specification.simpleline or n_simpleline
+ local f_content = specification.content or n_content
+ local f_space = specification.space
+ --
+ local p_exception = specification.exception
+ --
+ if s_catcodes then
+ f_content = function(s)
+ flush(s_catcodes,s)
+ end
+ end
+ --
+ local pattern
+ if f_space then
+ if p_exception then
+ local content = lpegC((1-spacing-p_exception)^1)
+ pattern =
+ (
+ justaspace / f_space
+ + justanewline / f_endofline
+ + p_exception
+ + content / f_content
+ )^0
+ else
+ local content = lpegC((1-space-endofline)^1)
+ pattern =
+ (
+ justaspace / f_space
+ + justanewline / f_endofline
+ + content / f_content
+ )^0
+ end
+ else
+ if p_exception then
+ local content = lpegC((1-spacing-p_exception)^1)
+ pattern =
+ simpleline / f_simpleline
+ +
+ (
+ emptyline / f_emptyline
+ + endofline / f_endofline
+ + p_exception
+ + content / f_content
+ )^0
+ else
+ local content = lpegC((1-spacing)^1)
+ pattern =
+ simpleline / f_simpleline
+ +
+ (
+ emptyline / f_emptyline
+ + endofline / f_endofline
+ + content / f_content
+ )^0
+ end
+ end
+ --
+ if f_before then
+ pattern = (P(true) / f_before) * pattern
+ end
+ --
+ if f_after then
+ pattern = pattern * (P(true) / f_after)
+ end
+ --
+ return function(str) return lpegmatch(pattern,str) end, pattern
+end
+
+function context.newverbosehandler(specification) -- a special variant for e.g. cdata in lxml-tex
+ specification = specification or { }
+ --
+ local f_line = specification.line or function() flushdirect("\r") end
+ local f_space = specification.space or function() flush(" ") end
+ local f_content = specification.content or n_verbose
+ local f_before = specification.before
+ local f_after = specification.after
+ --
+ local pattern =
+ justanewline / f_line -- so we get call{}
+ + verbose / f_content
+ + justaspace / f_space -- so we get call{}
+ --
+ if specification.strip then
+ pattern = beginstripper^0 * (endstripper + pattern)^0
+ else
+ pattern = pattern^0
+ end
+ --
+ if f_before then
+ pattern = (lpegP(true) / f_before) * pattern
+ end
+ --
+ if f_after then
+ pattern = pattern * (lpegP(true) / f_after)
+ end
+ --
+ return function(str) return lpegmatch(pattern,str) end, pattern
end
-function lpeg.texlinesplitter(f_content,f_endofline,f_emptyline,f_simpleline)
- local splitlines =
- simpleline / (f_simpleline or n_simpleline)
- + (
- emptyline / (f_emptyline or n_emptyline)
- + endofline / (f_endofline or n_emptyline)
- + content / (f_content or n_content)
- )^0
- return function(str) return lpegmatch(splitlines,str) end
-end
+local flushlines = context.newtexthandler {
+ content = n_content,
+ endofline = n_endofline,
+ emptyline = n_emptyline,
+ simpleline = n_simpleline,
+}
-local flushlines = lpeg.texlinesplitter(n_content,n_endofline,n_emptyline,n_simpleline)
+context.__flushlines = flushlines -- maybe context.helpers.flushtexlines
+context.__flush = flush
+context.__flushdirect = flushdirect
-context.__flushlines = flushlines -- maybe context.helpers.flushtexlines
-context.__flush = flush
+-- The next variant is only used in rare cases (buffer to mp):
local printlines_ctx = (
(newline) / function() texprint("") end +
@@ -204,7 +331,7 @@ local printlines_raw = (
(1-newline)^1 / function(s) texprint(s) end * newline^-1
)^0
-function context.printlines(str,raw)
+function context.printlines(str,raw) -- todo: see if via file is useable
if raw then
lpegmatch(printlines_raw,str)
else
@@ -212,22 +339,23 @@ function context.printlines(str,raw)
end
end
--- -- --
+-- This is the most reliable way to deal with nested buffers and other
+-- catcode sensitive data.
local methodhandler = resolvers.methodhandler
function context.viafile(data)
- -- this is the only way to deal with nested buffers
- -- and other catcode sensitive data
if data and data ~= "" then
local filename = resolvers.savers.byscheme("virtual","viafile",data)
+ -- context.startregime { "utf" }
context.input(filename)
+ -- context.stopregime()
end
end
-- -- --
-local function writer(parent,command,first,...)
+local function writer(parent,command,first,...) -- already optimized before call
local t = { first, ... }
flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes
local direct = false
@@ -246,6 +374,7 @@ local function writer(parent,command,first,...)
elseif ti == "" then
flush(currentcatcodes,"{}")
elseif typ == "string" then
+ -- is processelines seen ?
if processlines and find(ti,"[\n\r]") then -- we can check for ti == "\n"
flush(currentcatcodes,"{")
local flushlines = parent.__flushlines or flushlines
@@ -270,13 +399,13 @@ local function writer(parent,command,first,...)
if v == "" then
flush(currentcatcodes,",",k,'=')
else
- flush(currentcatcodes,",",k,'=',v)
+ flush(currentcatcodes,",",k,"={",v,"}")
end
else
if v == "" then
- flush(currentcatcodes,"[",k,'=')
+ flush(currentcatcodes,"[",k,"=")
else
- flush(currentcatcodes,"[",k,'=',v)
+ flush(currentcatcodes,"[",k,"={",v,"}")
end
done = true
end
@@ -302,8 +431,7 @@ local function writer(parent,command,first,...)
flush(currentcatcodes,"{\\cldf{",_store_f_(ti),"}}") -- todo: ctx|prt|texcatcodes
elseif typ == "boolean" then
if ti then
- -- flush(currentcatcodes,"^^M")
- texprint("")
+ flushdirect(currentcatcodes,"\r")
else
direct = true
end
@@ -332,9 +460,60 @@ local function indexer(parent,k)
return f
end
+-- Potential optimization: after the first call we know if there will be an
+-- argument. Of course there is the side effect that for instance abuse like
+-- context.NC(str) fails as well as optional arguments. So, we don't do this
+-- in practice. We just keep the next trick commented. The gain on some
+-- 100000 calls is not that large: 0.100 => 0.95 which is neglectable.
+--
+-- local function constructor(parent,k,c,first,...)
+-- if first == nil then
+-- local f = function()
+-- flush(currentcatcodes,c)
+-- end
+-- parent[k] = f
+-- return f()
+-- else
+-- local f = function(...)
+-- return writer(parent,c,...)
+-- end
+-- parent[k] = f
+-- return f(first,...)
+-- end
+-- end
+--
+-- local function indexer(parent,k)
+-- local c = "\\" .. tostring(generics[k] or k)
+-- local f = function(...)
+-- return constructor(parent,k,c,...)
+-- end
+-- parent[k] = f
+-- return f
+-- end
+
+-- only for internal usage:
+
+function context.constructcsonly(k) -- not much faster than the next but more mem efficient
+ local c = "\\" .. tostring(generics[k] or k)
+ rawset(context, k, function()
+ flush(prtcatcodes,c)
+ end)
+end
+
+function context.constructcs(k)
+ local c = "\\" .. tostring(generics[k] or k)
+ rawset(context, k, function(first,...)
+ if first == nil then
+ flush(prtcatcodes,c)
+ else
+ return writer(context,c,first,...)
+ end
+ end)
+end
+
local function caller(parent,f,a,...)
if not parent then
- -- so we don't need to test in the calling (slower but often no issue) (will go)
+ -- so we don't need to test in the calling (slower but often no issue)
elseif f ~= nil then
local typ = type(f)
if typ == "string" then
@@ -362,8 +541,7 @@ local function caller(parent,f,a,...)
flushlines(f)
-- ignore ... maybe some day
else
- -- flush(currentcatcodes,"^^M")
- texprint("")
+ flushdirect(currentcatcodes,"\r")
end
else
if a ~= nil then
@@ -407,15 +585,45 @@ function context.protect()
contentcatcodes = currentcatcodes
end
+function context.sprint(...) -- takes catcodes as first argument
+ flush(...)
+end
+
+function context.fprint(catcodes,fmt,first,...)
+ if type(catcodes) == "number" then
+ if first then
+ flush(catcodes,format(fmt,first,...))
+ else
+ flush(catcodes,fmt)
+ end
+ else
+ if fmt then
+ flush(format(catodes,fmt,first,...))
+ else
+ flush(catcodes)
+ end
+ end
+end
+
+function tex.fprint(fmt,first,...) -- goodie
+ if first then
+ flush(currentcatcodes,format(fmt,first,...))
+ else
+ flush(currentcatcodes,fmt)
+ end
+end
+
-- logging
local trace_stack = { }
-local normalflush = flush
-local normalwriter = writer
-local currenttrace = nil
-local nofwriters = 0
-local nofflushes = 0
+local normalflush = flush
+local normalflushdirect = flushdirect
+local normalflushraw = flushraw
+local normalwriter = writer
+local currenttrace = nil
+local nofwriters = 0
+local nofflushes = 0
statistics.register("traced context", function()
if nofwriters > 0 or nofflushes > 0 then
@@ -423,59 +631,99 @@ statistics.register("traced context", function()
end
end)
-local tracedwriter = function(parent,...)
+local tracedwriter = function(parent,...) -- also catcodes ?
nofwriters = nofwriters + 1
- local t, f, n = { "w : " }, flush, 0
- flush = function(...)
+ local savedflush = flush
+ local savedflushdirect = flushdirect -- unlikely to be used here
+ local t, n = { "w : - : " }, 1
+ local traced = function(normal,catcodes,...) -- todo: check for catcodes
+ local s = concat({...})
+ s = gsub(s,"\r","<<newline>>") -- unlikely
n = n + 1
- t[n] = concat({...},"",2)
- normalflush(...)
+ t[n] = s
+ normal(catcodes,...)
end
+ flush = function(...) traced(normalflush, ...) end
+ flushdirect = function(...) traced(normalflushdirect,...) end
normalwriter(parent,...)
- flush = f
+ flush = savedflush
+ flushdirect = savedflushdirect
currenttrace(concat(t))
end
-local tracedflush = function(...)
+-- we could reuse collapsed
+
+local traced = function(normal,one,two,...)
nofflushes = nofflushes + 1
- normalflush(...)
- local t = { ... }
- t[1] = "f : " -- replaces the catcode
- for i=2,#t do
- local ti = t[i]
- local tt = type(ti)
- if tt == "string" then
- -- ok
- elseif tt == "number" then
- -- ok
+ if two then
+ -- only catcodes if 'one' is number
+ normal(one,two,...)
+ local catcodes = type(one) == "number" and one
+ local arguments = catcodes and { two, ... } or { one, two, ... }
+ local collapsed, c = { format("f : %s : ", catcodes or '-') }, 1
+ for i=1,#arguments do
+ local argument = arguments[i]
+ local argtype = type(argument)
+ c = c + 1
+ if argtype == "string" then
+ collapsed[c] = gsub(argument,"\r","<<newline>>")
+ elseif argtype == "number" then
+ collapsed[c] = argument
+ else
+ collapsed[c] = format("<<%s>>",tostring(argument))
+ end
+ end
+ currenttrace(concat(collapsed))
+ else
+ -- no catcodes
+ normal(one)
+ local argtype = type(one)
+ if argtype == "string" then
+ currenttrace(format("f : - : %s",gsub(one,"\r","<<newline>>")))
+ elseif argtype == "number" then
+ currenttrace(format("f : - : %s",one))
else
- t[i] = format("<%s>",tostring(ti))
+ currenttrace(format("f : - : <<%s>>",tostring(one)))
end
- -- currenttrace(format("%02i: %s",i-1,tostring(t[i])))
end
- currenttrace(concat(t))
end
+local tracedflush = function(...) traced(normalflush, ...) end
+local tracedflushdirect = function(...) traced(normalflushdirect,...) end
+
local function pushlogger(trace)
+ trace = trace or report_context
insert(trace_stack,currenttrace)
currenttrace = trace
- flush, writer = tracedflush, tracedwriter
- context.__flush = flush
+ --
+ flush = tracedflush
+ flushdirect = tracedflushdirect
+ writer = tracedwriter
+ --
+ context.__flush = flush
+ context.__flushdirect = flushdirect
+ --
+ return flush, writer, flushdirect
end
local function poplogger()
currenttrace = remove(trace_stack)
if not currenttrace then
- flush, writer = normalflush, normalwriter
- context.__flush = flush
+ flush = normalflush
+ flushdirect = normalflushdirect
+ writer = normalwriter
+ --
+ context.__flush = flush
+ context.__flushdirect = flushdirect
end
+ return flush, writer, flushdirect
end
local function settracing(v)
if v then
- pushlogger(report_context)
+ return pushlogger(report_context)
else
- poplogger()
+ return poplogger()
end
end
@@ -483,9 +731,35 @@ end
trackers.register("context.trace",settracing)
-context.pushlogger = pushlogger
-context.poplogger = poplogger
-context.settracing = settracing
+context.pushlogger = pushlogger
+context.poplogger = poplogger
+context.settracing = settracing
+
+-- -- untested, no time now:
+--
+-- local tracestack, tracestacktop = { }, false
+--
+-- function context.pushtracing(v)
+-- insert(tracestack,tracestacktop)
+-- if type(v) == "function" then
+-- pushlogger(v)
+-- v = true
+-- else
+-- pushlogger()
+-- end
+-- tracestacktop = v
+-- settracing(v)
+-- end
+--
+-- function context.poptracing()
+-- poplogger()
+-- tracestacktop = remove(tracestack) or false
+-- settracing(tracestacktop)
+-- end
+
+function context.getlogger()
+ return flush, writer, flush_direct
+end
local trace_cld = false trackers.register("context.files", function(v) trace_cld = v end)
@@ -679,67 +953,10 @@ end
setmetatable(delayed, { __index = indexer, __call = caller } )
---~ Not that useful yet. Maybe something like this when the main loop
---~ is a coroutine. It also does not help taking care of nested calls.
---~ Even worse, it interferes with other mechanisms using context calls.
---~
---~ local create, yield, resume = coroutine.create, coroutine.yield, coroutine.resume
---~ local getflush, setflush = context.getflush, context.setflush
---~ local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
---~
---~ function context.getflush()
---~ return flush
---~ end
---~
---~ function context.setflush(newflush)
---~ local oldflush = flush
---~ flush = newflush or flush
---~ return oldflush
---~ end
---~
---~ function context.direct(f)
---~ local routine = create(f)
---~ local oldflush = getflush()
---~ function newflush(...)
---~ oldflush(...)
---~ yield(true)
---~ end
---~ setflush(newflush)
---~
---~ -- local function resumecontext()
---~ -- local done = resume(routine)
---~ -- if not done then
---~ -- return
---~ -- end
---~ -- resumecontext() -- stack overflow ... no tail recursion
---~ -- end
---~ -- context.resume = resumecontext
---~ -- texsprint(ctxcatcodes,"\\ctxlua{context.resume()}")
---~
---~ local function resumecontext()
---~ local done = resume(routine)
---~ if not done then
---~ return
---~ end
---~ -- texsprint(ctxcatcodes,"\\exitloop")
---~ texsprint(ctxcatcodes,"\\ctxlua{context.resume()}") -- can be simple macro call
---~ end
---~ context.resume = resumecontext
---~ -- texsprint(ctxcatcodes,"\\doloop{\\ctxlua{context.resume()}}") -- can be fast loop at the tex end
---~ texsprint(ctxcatcodes,"\\ctxlua{context.resume()}")
---~
---~ end
---~
---~ function something()
---~ context("\\setbox0")
---~ context("\\hbox{hans hagen xx}")
---~ context("\\the\\wd0/\\box0")
---~ end
---~
---~ context.direct(something)
-
-- helpers:
+-- we could have faster calls here
+
function context.concat(t,separator)
local done = false
for i=1,#t do
diff --git a/Master/texmf-dist/tex/context/base/cldf-ini.mkiv b/Master/texmf-dist/tex/context/base/cldf-ini.mkiv
index 8aef17f9340..4ad31d81ebe 100644
--- a/Master/texmf-dist/tex/context/base/cldf-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/cldf-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
@@ -28,6 +28,8 @@
%D \stopbuffer
%D
%D \typebuffer \getbuffer
+%D
+%D Anyway \unknown\ the following are {\em not} user commands:
\def\cldf#1{\directlua\zerocount{_cldf_(#1)}} % global (functions)
\def\cldn#1{\directlua\zerocount{_cldn_(#1)}} % global (nodes)
diff --git a/Master/texmf-dist/tex/context/base/cldf-int.lua b/Master/texmf-dist/tex/context/base/cldf-int.lua
index 2291fd849f0..55db9fa0b9d 100644
--- a/Master/texmf-dist/tex/context/base/cldf-int.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-int.lua
@@ -11,10 +11,13 @@ if not modules then modules = { } end modules ['mult-clm'] = {
-- needs checking
-- todo: multilingual
-local texsprint, ctxcatcodes, vrbcatcodes = tex.sprint, tex.ctxcatcodes, tex.vrbcatcodes
local format, insert, remove, concat = string.format, table.insert, table.remove, table.concat
local unpack = unpack or table.unpack
+local contextsprint = context.sprint
+local ctxcatcodes = tex.ctxcatcodes
+local vrbcatcodes = tex.vrbcatcodes
+
local trace_define = false trackers.register("context.define", function(v) trace_define = v end)
interfaces = interfaces or { }
@@ -25,6 +28,7 @@ _clma_ = utilities.parsers.settings_to_array
local starters, stoppers, macros, stack = { }, { }, { }, { }
local checkers = {
+ [0] = "",
"\\dosingleempty",
"\\dodoubleempty",
"\\dotripleempty",
@@ -55,6 +59,9 @@ end
_clmn_ = tonumber
+local estart = interfaces.elements.start
+local estop = interfaces.elements.stop
+
function interfaces.definecommand(name,specification) -- name is optional
if type(name) == "table" then
specification = name
@@ -66,53 +73,75 @@ function interfaces.definecommand(name,specification) -- name is optional
local environment = specification.environment
if na == 0 then
if environment then
- texsprint(ctxcatcodes,"\\clmb{",name,"}{\\ctxlua{_clmb_('",name,"')}}")
- texsprint(ctxcatcodes,"\\clme{",name,"}{\\ctxlua{_clme_('",name,"')}}")
- else
- texsprint(ctxcatcodes,"\\clmm{",name,"}{\\ctxlua{_clmm_('",name,"')}}")
+ contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{\\ctxlua{_clmb_('",name,"')}}")
+ contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
+ end
+ if not environment or environment == "both" then
+ contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{\\ctxlua{_clmm_('",name,"')}}")
end
else
+ -- we could flush immediate but tracing is bad then
stack[name] = { }
local opt, done = 0, false
+ local snippets = { } -- we can reuse it
local mkivdo = "\\mkivdo" .. name -- maybe clddo
- texsprint(ctxcatcodes,"\\def",mkivdo)
+ snippets[#snippets+1] = "\\def"
+ snippets[#snippets+1] = mkivdo
for i=1,na do
local a = arguments[i]
local variant = a[1]
if variant == "option" then
- texsprint(ctxcatcodes,"[#",i,"]")
+ snippets[#snippets+1] = "[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]"
if not done then
opt = opt + 1
end
else
done = true -- no more optional checking after this
- texsprint(ctxcatcodes,"#",i)
+ snippets[#snippets+1] = "#"
+ snippets[#snippets+1] = i
end
end
if environment then
- texsprint(ctxcatcodes,"{\\ctxlua{_clmb_('",name,"'")
+ snippets[#snippets+1] = "{\\ctxlua{_clmb_('"
+ snippets[#snippets+1] = name
+ snippets[#snippets+1] = "'"
else
- texsprint(ctxcatcodes,"{\\ctxlua{_clmm_('",name,"'")
+ snippets[#snippets+1] = "{\\ctxlua{_clmm_('"
+ snippets[#snippets+1] = name
+ snippets[#snippets+1] = "'"
end
for i=1,na do
local a = arguments[i]
local variant = a[2]
if variant == "list" then
- texsprint(ctxcatcodes,",_clma_([[#",i,"]])")
+ snippets[#snippets+1] = ",_clma_([[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]])"
elseif variant == "hash" then
- texsprint(ctxcatcodes,",_clmh_([[#",i,"]])")
+ snippets[#snippets+1] = ",_clmh_([[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]])"
elseif variant == "number" then
- texsprint(ctxcatcodes,",_clmn_([[#",i,"]])")
+ snippets[#snippets+1] = ",_clmn_([[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]])"
else
- texsprint(ctxcatcodes,",[[#",i,"]]")
+ snippets[#snippets+1] = ",[[#"
+ snippets[#snippets+1] = i
+ snippets[#snippets+1] = "]]"
end
end
- texsprint(ctxcatcodes,")}}")
+ snippets[#snippets+1] = ")}}"
+ contextsprint(ctxcatcodes,unpack(snippets))
if environment then
- texsprint(ctxcatcodes,"\\clme{",name,"}{\\ctxlua{_clme_('",name,"')}}")
- texsprint(ctxcatcodes,"\\clmb{",name,"}{",checkers[opt],mkivdo,"}")
- else
- texsprint(ctxcatcodes,"\\clmm{",name,"}{",checkers[opt],mkivdo,"}")
+ -- needs checking
+ contextsprint(ctxcatcodes,"\\setuvalue{",estart,name,"}{",checkers[opt],mkivdo,"}")
+ contextsprint(ctxcatcodes,"\\setuvalue{",estop, name,"}{\\ctxlua{_clme_('",name,"')}}")
+ end
+ if not environment or environment == "both" then
+ contextsprint(ctxcatcodes,"\\setuvalue{", name,"}{",checkers[opt],mkivdo,"}")
end
end
if environment then
diff --git a/Master/texmf-dist/tex/context/base/cldf-int.mkiv b/Master/texmf-dist/tex/context/base/cldf-int.mkiv
index cedac8fc0e2..da684694aee 100644
--- a/Master/texmf-dist/tex/context/base/cldf-int.mkiv
+++ b/Master/texmf-dist/tex/context/base/cldf-int.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,8 +17,10 @@
\unprotect
-\unexpanded\def\clmb#1{\unexpanded\expandafter\def\csname\e!start#1\endcsname}
-\unexpanded\def\clme#1{\unexpanded\expandafter\def\csname\e!stop #1\endcsname}
-\unexpanded\def\clmm#1{\unexpanded\expandafter\def\csname #1\endcsname}
+% now done directly
+%
+% \unexpanded\def\clmb#1{\unexpanded\expandafter\def\csname\e!start#1\endcsname}
+% \unexpanded\def\clme#1{\unexpanded\expandafter\def\csname\e!stop #1\endcsname}
+% \unexpanded\def\clmm#1{\unexpanded\expandafter\def\csname #1\endcsname}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/cldf-ver.lua b/Master/texmf-dist/tex/context/base/cldf-ver.lua
index fc681e83047..237078157bb 100644
--- a/Master/texmf-dist/tex/context/base/cldf-ver.lua
+++ b/Master/texmf-dist/tex/context/base/cldf-ver.lua
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['cldf-ver'] = {
license = "see context related readme files"
}
--- tex.print == line with endlinechar appended
-
local concat, tohandle = table.concat, table.tohandle
local find, splitlines = string.find, string.splitlines
local tostring, type = tostring, type
diff --git a/Master/texmf-dist/tex/context/base/cldf-ver.mkiv b/Master/texmf-dist/tex/context/base/cldf-ver.mkiv
index f85b28a0cf0..8e009035d2d 100644
--- a/Master/texmf-dist/tex/context/base/cldf-ver.mkiv
+++ b/Master/texmf-dist/tex/context/base/cldf-ver.mkiv
@@ -1,11 +1,11 @@
%D \module
%D [ file=cldf-com,
-%D version=2010.10.19,,
+%D version=2010.10.19,
%D title=\CONTEXT\ \LUA\ Document Functions,
%D subtitle=Verbatim,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/colo-ema.mkii b/Master/texmf-dist/tex/context/base/colo-ema.mkii
index e5e90b2355e..11d76f34209 100644
--- a/Master/texmf-dist/tex/context/base/colo-ema.mkii
+++ b/Master/texmf-dist/tex/context/base/colo-ema.mkii
@@ -5,7 +5,7 @@
%D subtitle=Emacs Colors,
%D author=Peter Rolf,
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/colo-ext.mkii b/Master/texmf-dist/tex/context/base/colo-ext.mkii
index 473c010e028..5b39a8e85dd 100644
--- a/Master/texmf-dist/tex/context/base/colo-ext.mkii
+++ b/Master/texmf-dist/tex/context/base/colo-ext.mkii
@@ -5,7 +5,7 @@
%D subtitle=Extras,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/colo-ext.mkiv b/Master/texmf-dist/tex/context/base/colo-ext.mkiv
index 771974d4d4f..af6c3830ecc 100644
--- a/Master/texmf-dist/tex/context/base/colo-ext.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-ext.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Extras,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -29,86 +29,80 @@
%D
%D will negate the colors in box zero.
-\def\negatecolorbox#1%
+% \unexpanded\def\negatecolorbox#1%
+% {\setbox#1\hbox
+% {\startnegative % might change
+% \startcolor[\s!white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor
+% \hskip-\wd#1%
+% \box#1%
+% \stopnegative}}
+
+\unexpanded\def\negatecolorbox#1%
{\setbox#1\hbox
- {\startnegativeproperty % might change
- \startcolor[white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor
+ {\startnegative % might change
+% \startcolor[\s!white]\vrule\!!height\ht#1\!!depth\dp#1\!!width\wd#1\stopcolor
+ \blackrule[\c!color=\s!white,\c!height=\ht#1,\c!depth=\dp#1,\c!width=\wd#1]%
\hskip-\wd#1%
\box#1%
- \stopnegativeproperty}}
+ \stopnegative}}
%D There are in principle two ways to handle overprint: bound to colors
%D or independent. For the moment we only support independent overprint
%D handling. Here we deal with a per-document setting.
+%D We can move the stack and attribute setting to the \LUA\ end.
+
+\installcorenamespace{colorintent}
+
+\unexpanded\def\registercolorintent#1#2%
+ {\setevalue{\??colorintent#1}{\attribute\colorintentattribute\ctxcommand{registercolorintent('#2')} }}
+
+\unexpanded\def\colo_intents_set
+ {\ctxcommand{enablecolorintents()}%
+ \unexpanded\gdef\colo_intents_set##1{\csname\??colorintent##1\endcsname}%
+ \colo_intents_set}
+
+\registercolorintent{knockout} {knockout}
+\registercolorintent{overprint}{overprint}
+
+\installattributestack\colorintentattribute
+
+\setevalue{\??colorintent\v!none}{\attribute\colorintentattribute\attributeunsetvalue} % or reset? used at all?
+
\unexpanded\def\startcolorintent[#1]%
{\pushattribute\colorintentattribute
- \dotriggercolorintent{#1}}
+ \colo_intents_set{#1}}
\unexpanded\def\stopcolorintent
{\popattribute\colorintentattribute}
\unexpanded\def\startoverprint{\startcolorintent[\v!overprint]}
-\unexpanded\def\stopoverprint {\stopcolorintent}
-
\unexpanded\def\startknockout {\startcolorintent[\v!knockout ]}
-\unexpanded\def\stopknockout {\stopcolorintent}
+
+\let\stopoverprint\stopcolorintent
+\let\stopknockout \stopcolorintent
\let\starttextcolorintent\relax
\let\stoptextcolorintent \relax
-\setupcolors
- [\c!overprint=\v!no]
-
\appendtoks
- \dosettextcolorintent
+ \colo_intents_set_text
\to \everysetupcolors
-\def\dosettextcolorintent
- {\doifnot\@@clintent\v!none
- {\xdef\starttextcolorintent{\noexpand\dotriggercolorintent{\@@clintent}}%
- \glet\dosettextcolorintent\relax
- \dotriggercolorintent\@@clintent}}
+\let\p_colo_intent\empty
+
+\def\colo_intents_set_text
+ {\edef\p_colo_intent{\colorsparameter\c!intent}%
+ \ifx\p_colo_intent\v!none \else
+ \unexpanded\xdef\starttextcolorintent{\colo_intents_set{\p_colo_intent}}%
+ \glet\colo_intents_set_text\relax
+ \colo_intents_set\p_colo_intent
+ \fi}
\appendtoks \starttextcolorintent \to \everystarttextproperties
\appendtoks \stoptextcolorintent \to \everystoptextproperties
-\setupcolors[\c!intent=\v!none]
-
-% A goodie that replaces the startMPcolor hackery
-
-% \definecolor[red-t] [r=1,t=0.5,a=1]
-% \definecolor[green-t][g=1,t=0.5,a=1]
-%
-% \defineintermediatecolor[mycolora][0.5,red,green]
-% \defineintermediatecolor[mycolorb][0.5,red-t,green-t]
-%
-% \definecolor[mycolorc][.5(blue,red)]
-% \definecolor[mycolord][.5(blue)]
-%
-% \enabledirectives[colors.pgf]
-% \definecolor[mycolorx][magenta!50!yellow]
-%
-% \starttext
-% test {\mycolora OEPS} test
-% test {\mycolorb OEPS} test
-% test {\mycolorc OEPS} test
-% test {\mycolord OEPS} test
-% test {\mycolorx OEPS} test
-% \stoptext
-
-\unexpanded\def\defineintermediatecolor
- {\dotripleempty\dodefineintermediatecolor}
-
-\def\dodefineintermediatecolor[#1][#2][#3]% \dotripleempty adds {} inside []
- {\dododefineintermediatecolor[#1][#2][#3]}
-
-\def\dododefineintermediatecolor[#1][#2,#3,#4][#5]%
- {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
- \ctxcommand{defineintermediatecolor("#1","#2",
- \thecolorattribute{#3},\thecolorattribute{#4},
- \thetransparencyattribute{#3},\thetransparencyattribute{#4},
- "#5",false,\iffreezecolors true\else false\fi)}% not global
- \dodefinecolorcommand\setvalue{#1}}
+\setupcolors
+ [\c!intent=\v!none]
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/colo-grp.mkiv b/Master/texmf-dist/tex/context/base/colo-grp.mkiv
new file mode 100644
index 00000000000..11b759062dc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/colo-grp.mkiv
@@ -0,0 +1,168 @@
+%D \module
+%D [ file=colo-grp,
+%D version=2011.12.27, % moved from colo-ini
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Groups,
+%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 Regular colors and palets are used most, contrary to groups
+%D which is why we define their support in a separate module.
+
+\writestatus{loading}{ConTeXt Color Macros / Groups}
+
+\unprotect
+
+%D \macros
+%D {definecolorgroup}
+%D
+%D The naming of the colors in this palet suggests some
+%D ordening, which in turn is suported by color grouping.
+%D
+%D \starttyping
+%D \definecolorgroup
+%D [red]
+%D [1.00:0.90:0.90,
+%D 1.00:0.80:0.80,
+%D 1.00:0.70:0.70,
+%D 1.00:0.55:0.55,
+%D 1.00:0.40:0.40,
+%D 1.00:0.25:0.25,
+%D 1.00:0.15:0.15,
+%D 0.90:0.00:0.00]
+%D \stoptyping
+%D
+%D In such a color group colors are numbered from~$1$ to~$n$.
+%D
+%D \showsetup{definecolorgroup}
+%D
+%D This kind of specification is not only more compact than
+%D defining each color separate, it also loads faster and takes
+%D less bytes.
+
+\installcorenamespace{colorgroup}
+\installcorenamespace{colorgroupsetter}
+
+\newcount\c_colo_groups_n % scratch counter
+
+\unexpanded\def\definecolorgroup % sort of obsolete, just use palets directly
+ {\dotripleempty\colo_groups_define}
+
+\def\colo_groups_define
+ {\ifthirdargument
+ \expandafter\colo_groups_define_normal
+ \else
+ \expandafter\colo_groups_define_checked
+ \fi}
+
+\def\colo_groups_define_normal[#1][#2][#3]%
+ {\c_colo_groups_n\zerocount
+ \processcommalist[#3]{\colo_groups_define_entry{#1}{#2}}}
+
+\def\colo_groups_define_checked[#1][#2][#3]%
+ {\doifinstringelse{:}{#2}
+ {\colo_groups_define_normal[#1][\v!rgb][#2]}
+ {\doloop % inherited
+ {\ifcsname\??colorgroup#2:\recurselevel\endcsname
+ \setevalue{\??colorgroup#1:\recurselevel}{\csname\??colorgroup#2:\recurselevel\endcsname}%
+ \else
+ \exitloop
+ \fi}}}
+
+\def\colo_groups_define_entry#1#2#3% name mode specification
+ {\advance\c_colo_groups_n\plusone
+ \csname\??colorgroupsetter\ifcsname\??colorgroupsetter#2\endcsname#2\else\s!rgb\fi\endcsname[#1:\the\c_colo_groups_n][#3:0:0:0:0]}
+
+\setvalue{\??colorgroupsetter\s!gray}[#1][#2:#3]{\definecolor[#1][s=#2]}
+\setvalue{\??colorgroupsetter\s!rgb }[#1][#2:#3:#4:#5]{\definecolor[#1][r=#2,g=#3,b=#4]}
+\setvalue{\??colorgroupsetter\s!cmyk}[#1][#2:#3:#4:#5:#6]{\definecolor[#1][c=#2,m=#3=,y=#4,k=#5]}
+\setvalue{\??colorgroupsetter\s!spot}[#1][#2:#3:#4]{\definespotcolor[#1][#2][p=#3]}
+
+%D \macros
+%D {showcolorgroup}
+%D
+%D We can show the group by:
+%D
+%D \startbuffer
+%D \showcolorgroup [blue] [horizontal,name,number,value]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or in color:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D which uses:
+%D
+%D \showsetup{showcolorgroup}
+
+\fetchruntimecommand \showcolorgroup {\f!colorprefix\s!run}
+
+%D There are ten predefined color groups, like
+%D \color[green]{\em groen}, \color[red]{\em rood},
+%D \color[blue]{\em blauw}, \color[cyan]{\em cyaan},
+%D \color[magenta]{\em magenta} and \color[yellow]{\em geel}.
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\hss
+%D \showcolorgroup [red] [vertical,name,number]\hss
+%D \showcolorgroup [green] [vertical,name]\hss
+%D \showcolorgroup [blue] [vertical,name]\hss
+%D \showcolorgroup [cyan] [vertical,name]\hss
+%D \showcolorgroup [magenta][vertical,name]\hss
+%D \showcolorgroup [yellow] [vertical,name]\hss}
+%D \stoplinecorrection
+%D
+%D These groups are used to define palets {\em alfa} upto {\em
+%D zeta}. As long as we don't use colors from the same row, we
+%D get ourselves distinctive palets. By activating such a palet
+%D one gains access to its members {\em top} to {\em charm} (of
+%D course one should use more suitable names than these).
+%D
+%D \startlinecorrection
+%D \hbox to \hsize
+%D {\showpalet [alfa] [vertical,name,number]\hss
+%D \showpalet [beta] [vertical,name]\hss
+%D \showpalet [gamma] [vertical,name]\hss
+%D \showpalet [delta] [vertical,name]\hss
+%D \showpalet [epsilon] [vertical,name]\hss
+%D \showpalet [zeta] [vertical,name]}
+%D \stoplinecorrection
+%D
+%D By using the keyword \type {value} the individual color
+%D components are shown too. When printed in color, these
+%D showcases show both the colors and the gray value.
+
+%D \macros
+%D {comparecolorgroup}
+%D
+%D The similar command:
+%D
+%D \startbuffer
+%D \comparecolorgroup [blue]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D shows color groups:
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+%D
+%D this commands are defined as:
+%D
+%D \showsetup{comparecolorgroup}
+
+\fetchruntimecommand \comparecolorgroup {\f!colorprefix\s!run}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/colo-hex.mkii b/Master/texmf-dist/tex/context/base/colo-hex.mkii
index db67f184102..ddf2d47065d 100644
--- a/Master/texmf-dist/tex/context/base/colo-hex.mkii
+++ b/Master/texmf-dist/tex/context/base/colo-hex.mkii
@@ -5,7 +5,7 @@
%D subtitle=Hex Colors,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/colo-imp-dem.mkiv b/Master/texmf-dist/tex/context/base/colo-imp-dem.mkiv
new file mode 100644
index 00000000000..5b794c5517b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/colo-imp-dem.mkiv
@@ -0,0 +1,260 @@
+%D \module
+%D [ file=colo-dem, % moved from colo-rgb,
+%D version=1995.01.01,
+%D title=\CONTEXT\ Color Macros,
+%D subtitle=Demo Palets and Groups,
+%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 Like colors, we first define the english colorgroups. These
+%D colorgroups are tuned for distinctive gray scale printing.
+
+\definecolorgroup
+ [gray]
+ [0.95:0.95:0.95,
+ 0.90:0.90:0.90,
+ 0.80:0.80:0.80,
+ 0.70:0.70:0.70,
+ 0.60:0.60:0.60,
+ 0.50:0.50:0.50,
+ 0.40:0.40:0.40,
+ 0.30:0.30:0.30,
+ 0.20:0.20:0.20,
+ 0.10:0.10:0.10,
+ 0.00:0.00:0.00]
+
+\definecolorgroup
+ [red]
+ [1.00:0.90:0.90,
+ 1.00:0.80:0.80,
+ 1.00:0.70:0.70,
+ 1.00:0.55:0.55,
+ 1.00:0.40:0.40,
+ 1.00:0.25:0.25,
+ 1.00:0.15:0.15,
+ 0.90:0.00:0.00]
+
+\definecolorgroup
+ [green]
+ [0.90:1.00:0.90,
+ 0.70:1.00:0.70,
+ 0.50:1.00:0.50,
+ 0.30:1.00:0.30,
+ 0.15:0.90:0.15,
+ 0.00:0.80:0.00,
+ 0.00:0.65:0.00,
+ 0.00:0.50:0.00]
+
+\definecolorgroup
+ [blue]
+ [0.90:0.95:1.00,
+ 0.80:0.90:1.00,
+ 0.55:0.85:1.00,
+ 0.30:0.80:1.00,
+ 0.15:0.75:1.00,
+ 0.00:0.70:1.00,
+ 0.00:0.55:1.00,
+ 0.00:0.40:1.00]
+
+\definecolorgroup
+ [cyan]
+ [0.80:1.00:1.00,
+ 0.60:1.00:1.00,
+ 0.30:1.00:1.00,
+ 0.00:0.95:0.95,
+ 0.00:0.85:0.85,
+ 0.00:0.75:0.75,
+ 0.00:0.60:0.60,
+ 0.00:0.50:0.50]
+
+\definecolorgroup
+ [magenta]
+ [1.00:0.90:1.00,
+ 1.00:0.80:1.00,
+ 1.00:0.65:1.00,
+ 1.00:0.50:1.00,
+ 1.00:0.35:1.00,
+ 1.00:0.15:1.00,
+ 0.90:0.05:0.90,
+ 0.80:0.00:0.80]
+
+\definecolorgroup
+ [yellow]
+ [1.00:1.00:0.70,
+ 1.00:1.00:0.00,
+ 1.00:0.85:0.05,
+ 1.00:0.70:0.00,
+ 1.00:0.55:0.00,
+ 0.95:0.40:0.00,
+ 0.80:0.30:0.00,
+ 0.60:0.30:0.00]
+
+\definecolorgroup
+ [red*]
+ [1.00:0.95:0.95,
+ 1.00:0.90:0.90,
+ 1.00:0.80:0.80,
+ 1.00:0.70:0.70,
+ 1.00:0.60:0.60,
+ 1.00:0.50:0.50,
+ 1.00:0.40:0.40,
+ 1.00:0.30:0.30]
+
+\definecolorgroup
+ [green*]
+ [0.95:1.00:0.95,
+ 0.90:1.00:0.90,
+ 0.80:1.00:0.80,
+ 0.70:1.00:0.70,
+ 0.60:1.00:0.60,
+ 0.50:1.00:0.50,
+ 0.40:1.00:0.40,
+ 0.30:1.00:0.30]
+
+\definecolorgroup
+ [blue*]
+ [0.95:0.95:1.00,
+ 0.90:0.90:1.00,
+ 0.80:0.80:1.00,
+ 0.70:0.70:1.00,
+ 0.60:0.60:1.00,
+ 0.50:0.50:1.00,
+ 0.40:0.40:1.00,
+ 0.30:0.30:1.00]
+
+\definecolorgroup
+ [yellow*]
+ [1.00:1.00:0.10,
+ 1.00:1.00:0.00,
+ 0.90:0.90:0.00,
+ 0.80:0.80:0.00,
+ 0.70:0.70:0.00,
+ 0.60:0.60:0.00,
+ 0.50:0.50:0.00,
+ 0.40:0.40:0.00]
+
+%D For the sake of implementing interface dependant color
+%D groups we support colorgroup duplication.
+
+\startinterface dutch
+ \definecolorgroup [grijs] [gray]
+ \definecolorgroup [rood] [red]
+ \definecolorgroup [groen] [green]
+ \definecolorgroup [blauw] [blue]
+ \definecolorgroup [cyaan] [cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [geel] [yellow]
+ \definecolorgroup [rood*] [red*]
+ \definecolorgroup [groen*] [green*]
+ \definecolorgroup [blauw*] [blue*]
+ \definecolorgroup [geel*] [yellow*]
+\stopinterface
+
+\startinterface german
+ \definecolorgroup [grau] [gray]
+ \definecolorgroup [rot] [red]
+ \definecolorgroup [gruen] [green]
+ \definecolorgroup [blau] [blue]
+ \definecolorgroup [cyan] [cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [gelb] [yellow]
+ \definecolorgroup [rot*] [red*]
+ \definecolorgroup [gruen*] [green*]
+ \definecolorgroup [blau*] [blue*]
+ \definecolorgroup [gelb*] [yellow*]
+\stopinterface
+
+\startinterface czech
+ \definecolorgroup [seda] [gray]
+ \definecolorgroup [cervena] [red]
+ \definecolorgroup [zelena] [green]
+ \definecolorgroup [modra] [blue]
+ \definecolorgroup [azurova] [cyan]
+ \definecolorgroup [fialova] [magenta]
+ \definecolorgroup [zluta] [yellow]
+ \definecolorgroup [cervena*] [red*]
+ \definecolorgroup [zelena*] [green*]
+ \definecolorgroup [modra*] [blue*]
+ \definecolorgroup [zluta*] [yellow*]
+\stopinterface
+
+\startinterface italian
+ \definecolorgroup [grigio] [gray]
+ \definecolorgroup [rosso] [red]
+ \definecolorgroup [verde] [green]
+ \definecolorgroup [blu] [blue]
+ \definecolorgroup [ciano] [cyan]
+ \definecolorgroup [azzurro] [cyan]
+ \definecolorgroup [turchino][cyan]
+ \definecolorgroup [magenta] [magenta]
+ \definecolorgroup [cremisi] [magenta]
+ \definecolorgroup [giallo] [yellow]
+ \definecolorgroup [rosso*] [red*]
+ \definecolorgroup [verde*] [green*]
+ \definecolorgroup [blu*] [blue*]
+ \definecolorgroup [giallo*] [yellow*]
+\stopinterface
+
+%D The next set of color palets is quite language independant.
+%D These palets are meant as examples.
+
+\definepalet
+ [alfa]
+ [ top=red:7,
+ bottom=green:6,
+ up=blue:5,
+ down=cyan:4,
+ strange=magenta:3,
+ charm=yellow:2]
+
+\definepalet
+ [beta]
+ [ top=red:7,
+ bottom=green:5,
+ up=blue:3,
+ down=cyan:6,
+ strange=magenta:2,
+ charm=yellow:1]
+
+\definepalet
+ [gamma]
+ [ top=red:2,
+ bottom=green:5,
+ up=blue:3,
+ down=cyan:6,
+ strange=magenta:7,
+ charm=yellow:4]
+
+\definepalet
+ [delta]
+ [ top=yellow*:5,
+ bottom=yellow*:3,
+ up=yellow*:2,
+ down=magenta:6,
+ strange=blue:4,
+ charm=blue:1]
+
+\definepalet
+ [epsilon]
+ [ top=cyan:7,
+ bottom=cyan:5,
+ up=blue:3,
+ down=yellow:6,
+ strange=yellow:4,
+ charm=yellow:2]
+
+\definepalet
+ [zeta]
+ [ top=red:6,
+ bottom=green:5,
+ up=blue:7,
+ down=cyan:4,
+ strange=magenta:3,
+ charm=yellow:2]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/colo-imp-ema.mkiv b/Master/texmf-dist/tex/context/base/colo-imp-ema.mkiv
index e5e90b2355e..11d76f34209 100644
--- a/Master/texmf-dist/tex/context/base/colo-imp-ema.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-imp-ema.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Emacs Colors,
%D author=Peter Rolf,
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/colo-imp-rgb.mkiv b/Master/texmf-dist/tex/context/base/colo-imp-rgb.mkiv
index 038e0ab0bf1..9bc6befbaa9 100644
--- a/Master/texmf-dist/tex/context/base/colo-imp-rgb.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-imp-rgb.mkiv
@@ -5,11 +5,11 @@
%D subtitle=RGB,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
%D Just to give users a start we define some colors. While
%D switching fonts is as international as can be, thanks to the
@@ -18,8 +18,8 @@
%D interface dependant colors. We use the color inheritance
%D mechanisms to implement the interface dependant ones.
-%D First we define some simple primary \cap{RGB} and \cap{CMYK}
-%D colors. All colors are defined in \cap{RGB} color space.
+%D For historic reasons all colors are defined in \RGB\ color
+%D space and there is no reason to change this.
\definecolor [red] [r=1, g=0, b=0]
\definecolor [green] [r=0, g=1, b=0]
@@ -30,33 +30,32 @@
\definecolor [yellow] [r=1, g=1, b=0]
\definecolor [white] [s=1] % [r=1, g=1, b=1]
-\definecolor [black] [s=0]
+\definecolor [black] [s=0]
\definecolor [gray] [s=.9]
-\definecolor [darkred] [r=.8, g=0, b=0]
-\definecolor [middlered] [r=.9, g=0, b=0]
-\definecolor [lightred] [r=1, g=0, b=0]
+% adapted per 2011.10.28
-\definecolor [darkgreen] [r=0, g=.6, b=0]
-\definecolor [middlegreen] [r=0, g=.8, b=0]
+\definecolor [lightred] [r=1, g=0, b=0]
\definecolor [lightgreen] [r=0, g=1, b=0]
-
-\definecolor [darkblue] [r=0, g=0, b=.8]
-\definecolor [middleblue] [r=0, g=0, b=.9]
\definecolor [lightblue] [r=0, g=0, b=1]
-\definecolor [darkcyan] [r=.6, g=.8, b=.8]
-\definecolor [middlecyan] [r=0, g=.8, b=.8]
-
-\definecolor [darkmagenta] [r=.8, g=.6, b=.8]
-\definecolor [middlemagenta] [r=1, g=0, b=.6]
+\definecolor [middlered] [r=.8, g=0, b=0]
+\definecolor [middlegreen] [r=0, g=.8, b=0]
+\definecolor [middleblue] [r=0, g=0, b=.8]
+\definecolor [middlecyan] [r=0, g=.6, b=.6]
+\definecolor [middlemagenta] [r=.6, g=0, b=.6]
+\definecolor [middleyellow] [r=.6, g=.6, b=.0]
-\definecolor [darkyellow] [r=.8, g=.8, b=.6]
-\definecolor [middleyellow] [r=1, g=1, b=.2]
+\definecolor [darkred] [r=.6, g=0, b=0]
+\definecolor [darkgreen] [r=0, g=.6, b=0]
+\definecolor [darkblue] [r=0, g=0, b=.6]
+\definecolor [darkcyan] [r=0, g=.4, b=.4]
+\definecolor [darkmagenta] [r=.4, g=0, b=.4]
+\definecolor [darkyellow] [r=.4, g=.4, b=0]
-\definecolor [darkgray] [s=.5]
-\definecolor [middlegray] [s=.7]
-\definecolor [lightgray] [s=.9]
+\definecolor [darkgray] [s=.60]
+\definecolor [middlegray] [s=.725]
+\definecolor [lightgray] [s=.85]
%D These colors are mapped to interface dependant colornames.
@@ -211,10 +210,10 @@
\definecolor [bluchiaro] [lightblue]
\definecolor [azzurroscuro] [darkcyan]
- \definecolor [azzurrochiaro] [middlecyan]
+ \definecolor [azzurrochiaro] [middlecyan]
- \definecolor [cremisiscuro] [darkmagenta]
- \definecolor [cremisichiaro] [middlemagenta]
+ \definecolor [cremisiscuro] [darkmagenta]
+ \definecolor [cremisichiaro] [middlemagenta]
\definecolor [gialloscuro] [darkyellow]
@@ -267,264 +266,8 @@
\stopinterface
-%D Like colors, we first define the english colorgroups. These
-%D colorgroups are tuned for distinctive gray scale printing.
-
-% todo : more efficient and real gray
-
-\definecolorgroup
- [gray]
- [0.95:0.95:0.95,
- 0.90:0.90:0.90,
- 0.80:0.80:0.80,
- 0.70:0.70:0.70,
- 0.60:0.60:0.60,
- 0.50:0.50:0.50,
- 0.40:0.40:0.40,
- 0.30:0.30:0.30,
- 0.20:0.20:0.20,
- 0.10:0.10:0.10,
- 0.00:0.00:0.00]
-
-\definecolorgroup
- [red]
- [1.00:0.90:0.90,
- 1.00:0.80:0.80,
- 1.00:0.70:0.70,
- 1.00:0.55:0.55,
- 1.00:0.40:0.40,
- 1.00:0.25:0.25,
- 1.00:0.15:0.15,
- 0.90:0.00:0.00]
-
-\definecolorgroup
- [green]
- [0.90:1.00:0.90,
- 0.70:1.00:0.70,
- 0.50:1.00:0.50,
- 0.30:1.00:0.30,
- 0.15:0.90:0.15,
- 0.00:0.80:0.00,
- 0.00:0.65:0.00,
- 0.00:0.50:0.00]
-
-\definecolorgroup
- [blue]
- [0.90:0.95:1.00,
- 0.80:0.90:1.00,
- 0.55:0.85:1.00,
- 0.30:0.80:1.00,
- 0.15:0.75:1.00,
- 0.00:0.70:1.00,
- 0.00:0.55:1.00,
- 0.00:0.40:1.00]
-
-\definecolorgroup
- [cyan]
- [0.80:1.00:1.00,
- 0.60:1.00:1.00,
- 0.30:1.00:1.00,
- 0.00:0.95:0.95,
- 0.00:0.85:0.85,
- 0.00:0.75:0.75,
- 0.00:0.60:0.60,
- 0.00:0.50:0.50]
-
-\definecolorgroup
- [magenta]
- [1.00:0.90:1.00,
- 1.00:0.80:1.00,
- 1.00:0.65:1.00,
- 1.00:0.50:1.00,
- 1.00:0.35:1.00,
- 1.00:0.15:1.00,
- 0.90:0.05:0.90,
- 0.80:0.00:0.80]
-
-\definecolorgroup
- [yellow]
- [1.00:1.00:0.70,
- 1.00:1.00:0.00,
- 1.00:0.85:0.05,
- 1.00:0.70:0.00,
- 1.00:0.55:0.00,
- 0.95:0.40:0.00,
- 0.80:0.30:0.00,
- 0.60:0.30:0.00]
-
-\definecolorgroup
- [red*]
- [1.00:0.95:0.95,
- 1.00:0.90:0.90,
- 1.00:0.80:0.80,
- 1.00:0.70:0.70,
- 1.00:0.60:0.60,
- 1.00:0.50:0.50,
- 1.00:0.40:0.40,
- 1.00:0.30:0.30]
-
-\definecolorgroup
- [green*]
- [0.95:1.00:0.95,
- 0.90:1.00:0.90,
- 0.80:1.00:0.80,
- 0.70:1.00:0.70,
- 0.60:1.00:0.60,
- 0.50:1.00:0.50,
- 0.40:1.00:0.40,
- 0.30:1.00:0.30]
-
-\definecolorgroup
- [blue*]
- [0.95:0.95:1.00,
- 0.90:0.90:1.00,
- 0.80:0.80:1.00,
- 0.70:0.70:1.00,
- 0.60:0.60:1.00,
- 0.50:0.50:1.00,
- 0.40:0.40:1.00,
- 0.30:0.30:1.00]
-
-\definecolorgroup
- [yellow*]
- [1.00:1.00:0.10,
- 1.00:1.00:0.00,
- 0.90:0.90:0.00,
- 0.80:0.80:0.00,
- 0.70:0.70:0.00,
- 0.60:0.60:0.00,
- 0.50:0.50:0.00,
- 0.40:0.40:0.00]
-
-%D For the sake of implementing interface dependant color
-%D groups we support colorgroup duplication.
-
-\startinterface dutch
- \definecolorgroup [grijs] [gray]
- \definecolorgroup [rood] [red]
- \definecolorgroup [groen] [green]
- \definecolorgroup [blauw] [blue]
- \definecolorgroup [cyaan] [cyan]
- \definecolorgroup [magenta] [magenta]
- \definecolorgroup [geel] [yellow]
- \definecolorgroup [rood*] [red*]
- \definecolorgroup [groen*] [green*]
- \definecolorgroup [blauw*] [blue*]
- \definecolorgroup [geel*] [yellow*]
-\stopinterface
-
-\startinterface german
- \definecolorgroup [grau] [gray]
- \definecolorgroup [rot] [red]
- \definecolorgroup [gruen] [green]
- \definecolorgroup [blau] [blue]
- \definecolorgroup [cyan] [cyan]
- \definecolorgroup [magenta] [magenta]
- \definecolorgroup [gelb] [yellow]
- \definecolorgroup [rot*] [red*]
- \definecolorgroup [gruen*] [green*]
- \definecolorgroup [blau*] [blue*]
- \definecolorgroup [gelb*] [yellow*]
-\stopinterface
-
-\startinterface czech
- \definecolorgroup [seda] [gray]
- \definecolorgroup [cervena] [red]
- \definecolorgroup [zelena] [green]
- \definecolorgroup [modra] [blue]
- \definecolorgroup [azurova] [cyan]
- \definecolorgroup [fialova] [magenta]
- \definecolorgroup [zluta] [yellow]
- \definecolorgroup [cervena*] [red*]
- \definecolorgroup [zelena*] [green*]
- \definecolorgroup [modra*] [blue*]
- \definecolorgroup [zluta*] [yellow*]
-\stopinterface
-
-\startinterface italian
- \definecolorgroup [grigio] [gray]
- \definecolorgroup [rosso] [red]
- \definecolorgroup [verde] [green]
- \definecolorgroup [blu] [blue]
- \definecolorgroup [ciano] [cyan]
- \definecolorgroup [azzurro] [cyan]
- \definecolorgroup [turchino][cyan]
- \definecolorgroup [magenta] [magenta]
- \definecolorgroup [cremisi] [magenta]
- \definecolorgroup [giallo] [yellow]
- \definecolorgroup [rosso*] [red*]
- \definecolorgroup [verde*] [green*]
- \definecolorgroup [blu*] [blue*]
- \definecolorgroup [giallo*] [yellow*]
-\stopinterface
+%D Bonus (needed for FO test):
-%D The next set of color palets is quite language independant.
-%D These palets are meant as examples.
-
-\definepalet
- [alfa]
- [ top=red:7,
- bottom=green:6,
- up=blue:5,
- down=cyan:4,
- strange=magenta:3,
- charm=yellow:2]
-
-\definepalet
- [beta]
- [ top=red:7,
- bottom=green:5,
- up=blue:3,
- down=cyan:6,
- strange=magenta:2,
- charm=yellow:1]
-
-\definepalet
- [gamma]
- [ top=red:2,
- bottom=green:5,
- up=blue:3,
- down=cyan:6,
- strange=magenta:7,
- charm=yellow:4]
-
-\definepalet
- [delta]
- [ top=yellow*:5,
- bottom=yellow*:3,
- up=yellow*:2,
- down=magenta:6,
- strange=blue:4,
- charm=blue:1]
-
-\definepalet
- [epsilon]
- [ top=cyan:7,
- bottom=cyan:5,
- up=blue:3,
- down=yellow:6,
- strange=yellow:4,
- charm=yellow:2]
-
-\definepalet
- [zeta]
- [ top=red:6,
- bottom=green:5,
- up=blue:7,
- down=cyan:4,
- strange=magenta:3,
- charm=yellow:2]
-
-%D The next four colors are used for typesetting verbatim \TEX\
-%D in color.
-
-\definecolor [texcolorone] [middlered]
-\definecolor [texcolortwo] [middlegreen]
-\definecolor [texcolorthree] [middleblue]
-\definecolor [texcolorfour] [darkyellow]
-
-%D Bonus (needed for FO test):
-
-\definecolor [orange] [r=1,g=.5]
+\definecolor [orange] [r=1,g=.5]
\endinput
diff --git a/Master/texmf-dist/tex/context/base/colo-imp-xwi.mkiv b/Master/texmf-dist/tex/context/base/colo-imp-xwi.mkiv
index 81e09d871bc..557e9c57c54 100644
--- a/Master/texmf-dist/tex/context/base/colo-imp-xwi.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-imp-xwi.mkiv
@@ -5,7 +5,7 @@
%D subtitle=X Windows,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/colo-ini.lua b/Master/texmf-dist/tex/context/base/colo-ini.lua
index c4e802ff587..08f1a303f05 100644
--- a/Master/texmf-dist/tex/context/base/colo-ini.lua
+++ b/Master/texmf-dist/tex/context/base/colo-ini.lua
@@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['colo-ini'] = {
}
local type, tonumber = type, tonumber
-local concat = table.concat
+local concat, insert, remove = table.concat, table.insert, table.remove
local format, gmatch, gsub, lower, match, find = string.format, string.gmatch, string.gsub, string.lower, string.match, string.find
local P, R, C, Cc = lpeg.P, lpeg.R, lpeg.C, lpeg.Cc
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
@@ -20,20 +20,48 @@ local attributes, context, commands = attributes, context, commands
local settings_to_hash_strict = utilities.parsers.settings_to_hash_strict
-local colors = attributes.colors
-local transparencies = attributes.transparencies
-local colorintents = attributes.colorintents
-local registrations = backends.registrations
-local settexattribute = tex.setattribute
-local gettexattribute = tex.getattribute
+local colors = attributes.colors
+local transparencies = attributes.transparencies
+local colorintents = attributes.colorintents
+local registrations = backends.registrations
+local settexattribute = tex.setattribute
+local gettexattribute = tex.getattribute
-local a_color = attributes.private('color')
-local a_transparency = attributes.private('transparency')
-local a_colorspace = attributes.private('colormodel')
-local a_background = attributes.private('background')
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
-local register_color = colors.register
-local attributes_list = attributes.list
+local register_color = colors.register
+local attributes_list = attributes.list
+
+local colorvalues = colors.values
+local transparencyvalues = transparencies.values
+
+colors.sets = colors.sets or { } -- sets are mostly used for
+local colorsets = colors.sets -- showing lists of defined
+local colorset = { } -- colors
+colorsets.default = colorset
+
+storage.register("attributes/colors/sets",colorsets,"attributes.colors.sets")
+
+local stack = { }
+
+function colors.pushset(name)
+ insert(stack,colorset)
+ colorset = colorsets[name]
+ if not colorset then
+ colorset = { }
+ colorsets[name] = colorset
+ end
+end
+
+function colors.popset(name)
+ colorset = remove(stack)
+end
+
+function colors.setlist(name)
+ return table.sortedkeys(name and name ~= "" and colorsets[name] or colorsets.default or {})
+end
local function definecolor(name, ca, global)
if ca and ca > 0 then
@@ -55,6 +83,7 @@ local function definecolor(name, ca, global)
context.colordefrlc(name)
end
end
+ colorset[name] = true-- maybe we can store more
end
local function inheritcolor(name, ca, global)
@@ -77,6 +106,7 @@ local function inheritcolor(name, ca, global)
context.colordefrlc(name)
end
end
+ colorset[name] = true-- maybe we can store more
end
local function definetransparent(name, ta, global)
@@ -137,13 +167,12 @@ local transparent = {
lighten = 10,
difference = 11,
exclusion = 12,
+ hue = 13,
+ saturation = 14,
+ color = 15,
+ luminosity = 16,
}
--- backend driven limitations
-
-colors.supported = true -- always true
-transparencies.supported = true
-
local gray_okay, rgb_okay, cmyk_okay, spot_okay, multichannel_okay, forced = true, true, true, true, true, false
function colors.forcesupport(gray,rgb,cmyk,spot,multichannel) -- pdfx driven
@@ -207,8 +236,7 @@ local registered = { }
local function do_registerspotcolor(parent,name,parentnumber,e,f,d,p)
if not registered[parent] then
---~ print("!!!1",parent)
- local v = colors.values[parentnumber]
+ local v = colorvalues[parentnumber]
if v then
local model = colors.default -- else problems with shading etc
if model == 1 then model = v[1] end
@@ -229,8 +257,7 @@ end
local function do_registermultitonecolor(parent,name,parentnumber,e,f,d,p) -- same as spot but different template
if not registered[parent] then
---~ print("!!!2",parent)
- local v = colors.values[parentnumber]
+ local v = colorvalues[parentnumber]
if v then
local model = colors.default -- else problems with shading etc
if model == 1 then model = v[1] end
@@ -343,10 +370,11 @@ function colors.defineprocesscolor(name,str,global,freeze) -- still inconsistent
-- end
end
end
+ colorset[name] = true-- maybe we can store more
end
function colors.isblack(ca) -- maybe commands
- local cv = ca > 0 and colors.value(ca)
+ local cv = ca > 0 and colorvalues[ca]
return (cv and cv[2] == 0) or false
end
@@ -373,6 +401,7 @@ function colors.definespotcolor(name,parent,str,global)
end
end
end
+ colorset[name] = true-- maybe we can store more
end
function colors.registerspotcolor(parent, str)
@@ -427,12 +456,16 @@ function colors.definemultitonecolor(name,multispec,colorspec,selfspec)
end
end
end
+ colorset[name] = true-- maybe we can store more
end
-function colors.mpcolor(model,ca,ta,default) -- will move to mlib-col
- local cv = colors.supported and colors.value(ca) -- faster when direct colors.values[ca]
+-- will move to mlib-col as colors in m,p are somewhat messy due to the fact
+-- that we cannot cast
+
+local function mpcolor(model,ca,ta,default)
+ local cv = colorvalues[ca]
if cv then
- local tv = transparencies.supported and transparencies.value(ta)
+ local tv = transparencyvalues[ta]
if model == 1 then
model = cv[1]
end
@@ -444,8 +477,13 @@ function colors.mpcolor(model,ca,ta,default) -- will move to mlib-col
return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
elseif model == 4 then
return format("transparent(%s,%s,cmyk(%s,%s,%s,%s))",tv[1],tv[2],cv[6],cv[7],cv[8],cv[9])
+ elseif model == 5 then
+ return format('transparent(%s,%s,multitonecolor("%s",%s,"%s","%s"))',tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
else
- return format("transparent(%s,%s,multitonecolor(\"%s\",%s,\"%s\",\"%s\"))",tv[1],tv[2],cv[10],cv[11],cv[12],cv[13])
+ return format("transparent(%s,%s,(%s,%s,%s))",tv[1],tv[2],cv[3],cv[4],cv[5])
+-- this will become (see ** in meta-ini.mkiv)
+--
+-- return format("transparent(%s,%s,(%s))",tv[1],tv[2],cv[2])
end
else
if model == 2 then
@@ -454,8 +492,13 @@ function colors.mpcolor(model,ca,ta,default) -- will move to mlib-col
return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
elseif model == 4 then
return format("cmyk(%s,%s,%s,%s)",cv[6],cv[7],cv[8],cv[9])
+ elseif model == 5 then
+ return format('multitonecolor("%s",%s,"%s","%s")',cv[10],cv[11],cv[12],cv[13])
else
- return format("multitonecolor(\"%s\",%s,\"%s\",\"%s\")",cv[10],cv[11],cv[12],cv[13])
+ return format("(%s,%s,%s)",cv[3],cv[4],cv[5])
+-- this will become (see ** in meta-ini.mkiv)
+--
+-- return format("%s",(cv[2]))
end
end
else
@@ -464,8 +507,15 @@ function colors.mpcolor(model,ca,ta,default) -- will move to mlib-col
end
end
+local function mpoptions(model,ca,ta,default) -- will move to mlib-col
+ return format("withcolor %s",mpcolor(model,ca,ta,default))
+end
+
+colors.mpcolor = mpcolor
+colors.mpoptions = mpoptions
+
function colors.formatcolor(ca,separator)
- local cv = colors.value(ca)
+ local cv = colorvalues[ca]
if cv then
local c, cn, f, t, model = { }, 0, 13, 13, cv[1]
if model == 2 then
@@ -486,12 +536,12 @@ function colors.formatcolor(ca,separator)
end
function colors.formatgray(ca,separator)
- local cv = colors.value(ca)
+ local cv = colorvalues[ca]
return format("%0.3f",(cv and cv[2]) or 0)
end
function colors.colorcomponents(ca) -- return list
- local cv = colors.value(ca)
+ local cv = colorvalues[ca]
if cv then
local model = cv[1]
if model == 2 then
@@ -511,7 +561,7 @@ function colors.colorcomponents(ca) -- return list
end
function colors.transparencycomponents(ta)
- local tv = transparencies.value(ta)
+ local tv = transparencyvalues[ta]
if tv then
return format("a=%1.3f t=%1.3f",tv[1],tv[2])
else
@@ -520,7 +570,7 @@ function colors.transparencycomponents(ta)
end
function colors.spotcolorname(ca,default)
- local cv, v = colors.value(ca), "unknown"
+ local cv, v = colorvalues[ca], "unknown"
if cv and cv[1] == 5 then
v = cv[10]
end
@@ -528,7 +578,7 @@ function colors.spotcolorname(ca,default)
end
function colors.spotcolorparent(ca,default)
- local cv, v = colors.value(ca), "unknown"
+ local cv, v = colorvalues[ca], "unknown"
if cv and cv[1] == 5 then
v = cv[12]
if v == "" then
@@ -539,7 +589,7 @@ function colors.spotcolorparent(ca,default)
end
function colors.spotcolorvalue(ca,default)
- local cv, v = colors.value(ca), 0
+ local cv, v = colorvalues[ca], 0
if cv and cv[1] == 5 then
v = cv[13]
end
@@ -563,7 +613,7 @@ end
function colors.defineintermediatecolor(name,fraction,c_one,c_two,a_one,a_two,specs,global,freeze)
fraction = tonumber(fraction) or 1
- local one, two = colors.value(c_one), colors.value(c_two)
+ local one, two = colorvalues[c_one], colorvalues[c_two]
if one then
if two then
local csone, cstwo = one[1], two[1]
@@ -607,7 +657,7 @@ function colors.defineintermediatecolor(name,fraction,c_one,c_two,a_one,a_two,sp
definecolor(name,ca,global,freeze)
end
end
- local one, two = transparencies.value(a_one), transparencies.value(a_two)
+ local one, two = transparencyvalues[a_one], transparencyvalues[a_two]
local t = settings_to_hash_strict(specs)
local ta = tonumber((t and t.a) or (one and one[1]) or (two and two[1]))
local tt = tonumber((t and t.t) or (one and two and f(one,two,2,fraction)))
@@ -625,7 +675,7 @@ end
--~ end
--~ function colors.defineduocolor(name,fraction_one,c_one,fraction_two,c_two,global,freeze)
---~ local one, two = colors.value(c_one), colors.value(c_two)
+--~ local one, two = colorvalues[c_one], colorvalues[c_two]
--~ if one and two then
--~ fraction_one = tonumber(fraction_one) or 1
--~ fraction_two = tonumber(fraction_two) or 1
@@ -663,7 +713,7 @@ end
function colors.definemixcolor(name,fractions,cs,global,freeze)
local values = { }
for i=1,#cs do -- do fraction in here
- local v = colors.value(cs[i])
+ local v = colorvalues[cs[i]]
if not v then
return
end
@@ -692,18 +742,32 @@ end
local patterns = { "colo-imp-%s.mkiv", "colo-imp-%s.tex", "colo-%s.mkiv", "colo-%s.tex" }
+local function action(name,foundname)
+ context.startreadingfile()
+ context.startcolorset { name }
+ context.input(foundname)
+ context.showmessage("colors",4,name)
+ context.stopcolorset()
+ context.stopreadingfile()
+end
+
+local function failure(name)
+ -- context.showmessage("colors",5,name)
+ report_colors("unknown: library '%s'",name)
+end
+
function colors.usecolors(name)
- commands.uselibrary(name,patterns,function(name,foundname)
- context.startreadingfile()
- context.input(foundname)
- context.showcolormessage("colors",4,name)
- context.stopreadingfile()
- end, function(name)
- context.showcolormessage("colors",5,name)
- end)
+ commands.uselibrary {
+ category = "color definition",
+ name = name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
end
--- interface
+-- interface (todo: use locals)
local setcolormodel = colors.setmodel
@@ -711,9 +775,9 @@ function commands.setcolormodel(model,weight)
settexattribute(a_colorspace,setcolormodel(model,weight))
end
-function commands.setrastercolor(name,s)
- settexattribute(a_color,colors.definesimplegray(name,s))
-end
+-- function commands.setrastercolor(name,s)
+-- settexattribute(a_color,colors.definesimplegray(name,s))
+-- end
function commands.registermaintextcolor(a)
colors.main = a
@@ -734,7 +798,11 @@ function commands.formatcolor (...) context(colors.formatcolor
function commands.formatgray (...) context(colors.formatgray (...)) end
function commands.mpcolor(model,ca,ta,default)
- context(colors.mpcolor(model,ca,ta,default))
+ context(mpcolor(model,ca,ta,default))
+end
+
+function commands.mpoptions(model,ca,ta,default)
+ context(mpoptions(model,ca,ta,default))
end
function commands.doifblackelse(a)
@@ -745,4 +813,25 @@ function commands.doifdrawingblackelse()
commands.doifelse(colors.isblack(gettexattribute(a_color)))
end
+-- function commands.withcolorsinset(name,command)
+-- local set
+-- if name and name ~= "" then
+-- set = colorsets[name]
+-- else
+-- set = colorsets.default
+-- end
+-- if set then
+-- if command then
+-- for name in table.sortedhash(set) do
+-- context[command](name)
+-- end
+-- else
+-- context(concat(table.sortedkeys(set),","))
+-- end
+-- end
+-- end
+
+commands.startcolorset = colors.pushset
+commands.stopcolorset = colors.popset
+
commands.usecolors = colors.usecolors
diff --git a/Master/texmf-dist/tex/context/base/colo-ini.mkii b/Master/texmf-dist/tex/context/base/colo-ini.mkii
index 484a085fe2b..f14f1e15e04 100644
--- a/Master/texmf-dist/tex/context/base/colo-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/colo-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -2757,6 +2757,10 @@
\definetransparency [lighten] [10]
\definetransparency [difference] [11]
\definetransparency [exclusion] [12]
+\definetransparency [hue] [13]
+\definetransparency [saturation] [14]
+\definetransparency [color] [15]
+\definetransparency [luminosity] [16]
\setupcolors
[\c!state=\v!stop,
diff --git a/Master/texmf-dist/tex/context/base/colo-ini.mkiv b/Master/texmf-dist/tex/context/base/colo-ini.mkiv
index 45fe1463383..164b39262ff 100644
--- a/Master/texmf-dist/tex/context/base/colo-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-ini.mkiv
@@ -5,13 +5,13 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 need to clean this up further but first we hav eto make sure that mkiv
+%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}
@@ -26,72 +26,49 @@
%D In \MKIV\ we have independent color, colorspace and transparency
%D but I'm still not sure if I keep it that way as it's probably more
-%D efficient to combine them (less attributes and finalizing).
+%D efficient to combine them (less attributes and finalizing). If
+%D it becomes a bottleneck we can set up a more complex system
+%D with one shared attribute for colorspace, color and transparency.
%D
-%D We use a couple of local registers. That way we don't have
-%D to group when converting colors. By the way, this is not
-%D really faster. We can sqeeze half a second runtime for 50K
-%D switches on a 1G machine, but the macros will become rather
-%D ugly then. To mention one such improvement: no colon
-%D after the key character (.25 sec).
-
-\newcount\colorcount
-
-%D When typesetting for paper, we prefer using the \cap{CMYK}
-%D color space, but for on||screen viewing we prefer \cap{RGB}
-%D (the previous implementation supported only this scheme).
-%D Independant of such specifications, we support some automatic
-%D conversions:
+%D When typesetting for paper, we prefer using the \CMYK\ color space,
+%D but for on||screen viewing we prefer \RGB\ (the previous
+%D implementation supported only this scheme). Independant of such
+%D specifications, we support some automatic conversions:
%D
%D \startitemize[packed]
-%D \item convert all colors to \cap{RGB}
-%D \item convert all colors to \cap{CMYK}
+%D \item convert all colors to \RGB
+%D \item convert all colors to \CMYK
%D \item convert all colors to gray scales
%D \stopitemize
%D
-%D We also support optimization of colors to gray scales.
-%D
-%D \startitemize[continue]
-%D \item reduce gray colors to gray scales
-%D \item reduce \cap{CMY} components to \cap{K}
-%D \stopitemize
-%D
%D These options are communicated by means of:
-\newif\ifRGBsupported
-\newif\ifCMYKsupported
-\newif\ifSPOTsupported
-\newif\ifpreferGRAY
-\newif\ifGRAYprefered
-\newif\ifconvertGRAY \convertGRAYtrue
-\newif\ifreduceCMYK
-\newif\ifconverttoGRAY
-\newif\ifweightGRAY \weightGRAYtrue
-
-\newif\ifconvertMPcolors
-\newif\ifreduceMPcolors
-\newif\ifforcegrayMPcolors
-
-%D The last boolean controls reduction of \cap{CMYK} to
-%D \cap{CMY} colors. When set to true, the black component
-%D is added to the other ones.
-%D
-%D Prefering gray is not the same as converting to gray.
-%D Conversion treats each color components in a different way,
-%D while prefering is just a reduction and thus a
-%D space||saving option.
-
-\newif\iffreezecolors \freezecolorsfalse
-\newif\ifincolor % true if colors enabled
-
-\let\colorlist \empty
-\let\currentspotcolor \empty
-\let\allspotcolors \empty
-\let\usedspotcolors \empty
-\let\currentpalet \empty
+\newconditional\c_colo_rgb_supported
+\newconditional\c_colo_cmyk_supported
+\newconditional\c_colo_spot_supported % backend driven
+\newconditional\c_colo_weight_gray \settrue\c_colo_weight_gray
+\newconditional\c_colo_convert_gray \settrue\c_colo_convert_gray
+\newconditional\c_colo_enabled
+\newconditional\c_colo_expanded
+
+\let\currentcolormodel \empty
+\let\currentcolorname \empty
+\let\currentcolorpalet \empty
+\let\currentcolorprefix\empty % \currentcolorpalet:
+
+\installcorenamespace{color}
+\installcorenamespace{colorattribute}
+\installcorenamespace{transparencyattribute}
+\installcorenamespace{colorsetter}
+\installcorenamespace{transparencysetter}
+\installcorenamespace{colorpaletspecification}
+\installcorenamespace{colorpalet}
+\installcorenamespace{colorstack}
+\installcorenamespace{colorconversions}
%D \macros
-%D {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor}
+%D {definecolor,defineglobalcolor,definenamedcolor,definespotcolor,definemultitonecolor,
+%D definetransparency}
%D
%D \startbuffer
%D \definecolor [blue] [c=1,m=.38,y=0,k=.64] % pantone pms 2965 uncoated m
@@ -114,83 +91,80 @@
%D
%D \getbuffer \typebuffer
-\unexpanded\def\definecolor {\dodoubleargument\dodefinecolor}
-\unexpanded\def\defineglobalcolor {\dodoubleargument\dodefineglobalcolor}
-\unexpanded\def\definenamedcolor {\dodoubleargument\dodefinenamedcolor}
-\unexpanded\def\definespotcolor {\dotripleargument\dodefinespotcolor}
-\unexpanded\def\definemultitonecolor{\doquadrupleempty\dodefinemultitonecolor}
+\unexpanded\def\definecolor {\dodoubleargument\colo_basics_define}
+\unexpanded\def\defineglobalcolor {\dodoubleargument\colo_basics_define_global}
+\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}
%D \macros
-%D {startcolor,stopcolor,
-%D faststartcolor,faststopcolor,
-%D startraster,stopraster,raster,
-%D color,graycolor}
+%D {startcolor,stopcolor,color,graycolor}
%D
-%D The local and global and raster commands are here just
-%D for compatibility with \MKII.
+%D The local and global commands are here just for compatibility
+%D with \MKII.
%D
%D \showsetup{startcolor}
%D
-%D \macros
-%D {color,graycolor}
-%D
-%D This leaves the simple color command:
-%D
-%D \showsetup{color}
-%D \showsetup{graycolor}
-%D
-%D This leaves the simple color command:
+%D The simple color commands are:
%D
%D \showsetup{color}
%D \showsetup{graycolor}
-\unexpanded\def\switchtocolor [#1]{\csname#1\endcsname}
-\unexpanded\def\color [#1]{\groupedcommand{\doactivatecolor{#1}}{}}
-\unexpanded\def\startcolor [#1]{\begingroup\doactivatecolor{#1}}
-\unexpanded\def\stopcolor {\endgroup}
-\unexpanded\def\graycolor [#1]{\groupedcommand{\dosetcolormodel{gray}\getvalue{#1}}{}}
-\unexpanded\def\colored [#1]{\groupedcommand{\definecolor[@colored@][#1]\doactivatecolor{@colored@}}{}}
-\unexpanded\def\fastcolored [#1]#2{\begingroup\dodefinefastcolor[@colored@][#1]\doactivatecolor{@colored@}#2\endgroup}
-\unexpanded\def\predefinecolor [#1]{\flushatshipout{\hbox{\color[#1]{}}}}
-\unexpanded\def\predefineindexcolor[#1]{\flushatshipout{\hbox{\color[#1]{}}}}
-
-% some of this will go away
-
-\unexpanded\def\startcolorpage {\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]}
-\unexpanded\def\stopcolorpage {\stopcolor}
-\unexpanded\def\startraster [#1]{\dosetrastercolor{#1}}
-\unexpanded\def\stopraster {}
-\unexpanded\def\raster [#1]{\groupedcommand{\dosetrastercolor{#1}}{}}
-\unexpanded\def\faststartcolor [#1]{\doactivatecolor{#1}}
-\unexpanded\def\faststopcolor {}
-\unexpanded\def\dosetcolorattribute#1#2{\ifcsname#1#2\endcsname\doactivatecolor{\csname#1#2\endcsname}\fi}
-
-\def\getcolorattributevalue#1#2% color macro (obsolete again, we have a better method)
- {\begingroup
- \doactivatecolor{#1}%
- \normalexpanded{\endgroup\edef\noexpand#2%
- {\ifnum\attribute\colorattribute=\attributeunsetvalue\else\number\attribute\colorattribute\fi}}}
+%D We expect sane behaviour in \MKIV\ so we don't used grouped command any
+%D longer.
-\let\grey\graycolor
+% \testfeatureonce{100000}{\color[red]{}} % 1.046 => 0.541
-%D Stacking:
+\unexpanded\def\switchtocolor[#1]{\csname#1\endcsname}
-% \colormodelattribute \colorattribute \transparencyattribute
+\unexpanded\def\color [#1]{\bgroup
+ \def\g_color{\colo_helpers_activate{#1}}%
+ \afterassignment\g_color
+ \let\nexttoken}
-\newcount\currentcolornesting
+\unexpanded\def\graycolor [#1]{\bgroup
+ \def\g_color{\colo_helpers_set_model\s!gray\colo_helpers_activate{#1}}%
+ \afterassignment\g_color
+ \let\nexttoken}
-\unexpanded\def\pushcolor[#1]%
- {\global\advance\currentcolornesting\plusone
- \expandafter\edef\csname\??cl:s:\number\currentcolornesting\endcsname
- {\attribute\colormodelattribute \the\attribute\colormodelattribute
- \attribute\colorattribute \the\attribute\colorattribute
- \attribute\transparencyattribute\the\attribute\transparencyattribute
- \space}% stack
- \doactivatecolor{#1}}
+\unexpanded\def\startcolor [#1]{\begingroup
+ \colo_helpers_activate{#1}}
-\unexpanded\def\popcolor
- {\csname\??cl:s:\number\currentcolornesting\endcsname
- \global\advance\currentcolornesting\minusone}
+\unexpanded\def\stopcolor {\endgroup}
+
+\unexpanded\def\colored [#1]{\bgroup
+ \def\g_color{\colo_basics_defined_and_activated{#1}}%
+ \afterassignment\g_color
+ \let\nexttoken}
+
+\unexpanded\def\fastcolored[#1]#2{\begingroup % is this command still needed?
+ \colo_basics_defined_and_activated{#1}%
+ #2%
+ \endgroup}
+
+\unexpanded\def\directcolored[#1]{\colo_basics_defined_and_activated{#1}}
+
+\unexpanded\def\fastcolor [#1]#2{\begingroup % is this command still needed?
+ \colo_helpers_activate{#1}%
+ #2%
+ \endgroup}
+
+\unexpanded\def\directcolor [#1]{\colo_helpers_activate{#1}}
+
+
+%D The following command is obsolete:
+
+\unexpanded\def\startcolorpage {\startcolor[\ifx\maintextcolor\empty\defaulttextcolor\else\maintextcolor\fi]}
+\unexpanded\def\stopcolorpage {\stopcolor}
+
+\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ...
+ {\begingroup
+ \colo_helpers_activate{#1}%
+ \normalexpanded{\endgroup\edef\noexpand#2%
+ {\ifnum\attribute\colorattribute=\attributeunsetvalue\else\number\attribute\colorattribute\fi}}}
+
+\let\grey\graycolor % these macros are only used in tracing
%D \macros
%D {startcurrentcolor,stopcurrentcolor}
@@ -204,106 +178,102 @@
%D Color definitions can be grouped in files with the name:
%D
%D \starttyping
-%D \f!colorprefix-identifier.tex
+%D colo-imp-tag.tex
%D \stoptyping
%D
-%D where \type{\f!colorprefix} is \unprotect {\tttf \f!colorprefix}.
-%D Loading such a file is done by \protect
+%D Loading such a file is done by:
%D
%D \showsetup{usecolors}
%D
-%D Some default colors are specified in \type{colo-rgb.tex},
-%D which is loaded into the format by:
+%D Some default colors are specified in \type {colo-imp-rgb},
+%D which is loaded into the format by default.
+%D
+%D Some demo palets and groups are defined in \type {colo-imp-dem}
+%D which can be loaded with:
%D
%D \starttyping
-%D \usecolors[rgb]
+%D \usecolors[dem]
%D \stoptyping
-\unexpanded\def\usecolors[#1]{\ctxcommand{usecolors(\!!bs#1\!!es)}}
+\unexpanded\def\startcolorset[#1]{\ctxcommand{startcolorset("#1")}}
+\unexpanded\def\stopcolorset {\ctxcommand{stopcolorset()}}
+\unexpanded\def\usecolors [#1]{\ctxcommand{usecolors("#1")}}
\let\setupcolor\usecolors
-%D \macros
-%D {definetransparency}
-%D
-%D This command numbers to names:
+\installsetuponlycommandhandler \??color {colors}
-\unexpanded\def\definetransparency
- {\dodoubleargument\dodefinetransparency}
+\let\colo_helpers_show_message\gobblethreearguments
-\unexpanded\def\setupcolors
- {\dosingleargument\dosetupcolors}
+% \newtoks\everysetupcolors
-\let\showcolormessage\gobblethreearguments
+\let\v_colo_freeze_state\s!false
+\let\v_colo_weight_state\s!false
-\newtoks\everysetupcolors
+\setvalue{\??colorconversions\v!yes}%
+ {\settrue \c_colo_convert_gray}
-\let\dosetcolorvalue \setvalue
-\def\colorfreezestate{false}
+\setvalue{\??colorconversions\v!always}%
+ {\settrue \c_colo_convert_gray
+ \setfalse\c_colo_rgb_supported
+ \setfalse\c_colo_cmyk_supported}
-\def\dosetupcolors[#1]% some no longer make sense in MkIV
- {\getparameters[\??cl][#1]%
- \doifelse\@@clspot\v!yes
- \SPOTsupportedtrue
- \SPOTsupportedfalse
- \doifelse\@@clreduction\v!yes
- \reduceCMYKtrue
- \reduceCMYKfalse
- \doifelse\@@clexpansion\v!yes
- \freezecolorstrue
- \freezecolorsfalse
- \iffreezecolors
- \let\dosetcolorvalue\setevalue
- \def\colorfreezestate{true}%
+\appendtoks
+ %
+ \doifelse{\directcolorsparameter\c!spot }\v!yes \settrue \setfalse\c_colo_spot_supported
+ \doifelse{\directcolorsparameter\c!expansion}\v!yes \settrue \setfalse\c_colo_expanded
+ \doifelse{\directcolorsparameter\c!factor }\v!no \setfalse\settrue \c_colo_weight_gray
+ \doifelse{\directcolorsparameter\c!rgb }\v!yes \settrue \setfalse\c_colo_rgb_supported
+ \doifelse{\directcolorsparameter\c!cmyk }\v!yes \settrue \setfalse\c_colo_cmyk_supported
+ \doifelse{\directcolorsparameter\c!state }\v!start\settrue \setfalse\c_colo_enabled
+ %
+ \ifconditional\c_colo_weight_gray
+ \let\v_colo_weight_state\s!true
\else
- \let\dosetcolorvalue\setvalue
- \def\colorfreezestate{false}%
+ \let\v_colo_weight_state\s!false
\fi
- \doifelse\@@clfactor\v!no
- \weightGRAYfalse
- \weightGRAYtrue
- \doifelse\@@clrgb\v!no
- {\ifRGBsupported \showcolormessage\m!colors {9}\v!rgb \RGBsupportedfalse \fi}
- {\ifRGBsupported \else\showcolormessage\m!colors{10}\v!rgb \RGBsupportedtrue \fi}%
- \doifelse\@@clcmyk\v!no
- {\ifCMYKsupported \showcolormessage\m!colors {9}\v!cmyk \CMYKsupportedfalse\fi}
- {\ifCMYKsupported\else\showcolormessage\m!colors{10}\v!cmyk \CMYKsupportedtrue \fi}%
- \doifelse\@@clmpcmyk\v!no
- {\ifMPcmykcolors \showcolormessage\m!colors {9}{\v!mp\v!cmyk}\MPcmykcolorsfalse \fi}
- {\ifMPcmykcolors \else\showcolormessage\m!colors{10}{\v!mp\v!cmyk}\MPcmykcolorstrue \fi}%
- \doifelse\@@clmpspot\v!no
- {\ifMPspotcolors \showcolormessage\m!colors {9}{\v!mp\v!spot}\MPspotcolorsfalse \fi}
- {\ifMPspotcolors \else\showcolormessage\m!colors{10}{\v!mp\v!spot}\MPspotcolorstrue \fi}%
- \preferGRAYfalse
- \convertGRAYtrue
- \processaction
- [\@@clconversion]
- [ \v!yes=>\preferGRAYtrue,
- \v!no=>\convertGRAYfalse,
- \v!never=>\convertGRAYfalse,
- \v!always=>\preferGRAYtrue\RGBsupportedfalse\CMYKsupportedfalse]%
- \ifRGBsupported
- \converttoGRAYfalse
- \forcegrayMPcolorsfalse
- \else\ifCMYKsupported
- \converttoGRAYfalse
- \forcegrayMPcolorsfalse
- \convertMPcolorstrue
- \ifreduceCMYK
- \reduceMPcolorstrue
- \fi
+ %
+ \ifconditional\c_colo_expanded
+ \let\v_colo_freeze_state\s!true
\else
- \ifconverttoGRAY\else\showcolormessage\m!colors{11}\empty\fi
- \converttoGRAYtrue
- \forcegrayMPcolorstrue
- \convertMPcolorsfalse
- \reduceMPcolorsfalse
- \fi\fi
- \doifelse\@@clstate\v!stop
- {\incolorfalse\forcegrayMPcolorstrue}%
- {\incolortrue\let\@@clstate\v!start}%
- \dosetupcolormodel
- \the\everysetupcolors}
+ \let\v_colo_freeze_state\s!false
+ \fi
+ %
+ \setfalse\c_colo_convert_gray
+ \getvalue{\??colorconversions\directcolorsparameter\c!conversion}% could be a nice \ifcsname
+ % too often:
+ \ifconditional\c_colo_rgb_supported \colo_helpers_show_message\m!colors9\v!rgb \fi
+ \ifconditional\c_colo_cmyk_supported\colo_helpers_show_message\m!colors9\v!cmyk\fi
+ \colo_helpers_set_current_model
+ \ifproductionrun
+ \edef\p_pagecolormodel{\directcolorsparameter\c!pagecolormodel}%
+ \ctxcommand{synchronizecolormodel("\ifx\p_pagecolormodel\v!auto \currentcolormodel \else \p_pagecolormodel \fi")}%
+ \fi
+\to \everysetupcolors
+
+\appendtoks
+ \setupcolors[\c!state=\v!start]%
+ \ctxcommand{enablecolor()}% % this can as well happen when
+ \ctxcommand{enabletransparency()}% % the handler is defined in lua
+ \let\colo_helpers_show_message\showmessage
+\to \everyjob
+
+%D We provide stacking independent of grouping.
+
+\newcount\c_colo_nesting
+
+\unexpanded\def\pushcolor[#1]%
+ {\global\advance\c_colo_nesting\plusone
+ \expandafter\edef\csname\??colorstack\number\c_colo_nesting\endcsname
+ {\attribute\colormodelattribute \the\attribute\colormodelattribute
+ \attribute\colorattribute \the\attribute\colorattribute
+ \attribute\transparencyattribute\the\attribute\transparencyattribute
+ \relax}% stack
+ \colo_helpers_activate{#1}}
+
+\unexpanded\def\popcolor
+ {\csname\??colorstack\number\c_colo_nesting\endcsname
+ \global\advance\c_colo_nesting\minusone}
%D In this documentation we will not go into too much details
%D on palets. Curious users can find more information on this
@@ -370,29 +340,34 @@
%D This saves us some typing in for instance the modules that
%D deal with pretty verbatim typesetting.
+\let\m_colo_palets_tmp\empty
+
\unexpanded\def\definepalet
- {\dodoubleargument\dodefinepalet}
+ {\dodoubleargument\colo_palets_define}
-\def\dodefinepalet[#1][#2]%
+\unexpanded\def\colo_palets_define[#1][#2]% todo
{\doifassignmentelse{#2}
- {%\showcolormessage\m!colors6{#1}%
- \letvalueempty{\??pa#1}%
- \setevalue{\??pa\??pa#1}{#2}%
- \def\dodododefinepalet[##1=##2]%
- {\doifvaluesomething{\??pa#1}
- {\setevalue{\??pa#1}{\csname\??pa#1\endcsname,}}%
- \setevalue{\??pa#1}{\csname\??pa#1\endcsname##1}%
- \dodefinepaletcolor{#1}{##1}{##2}}%
- \def\dododefinepalet##1%
- {\dodododefinepalet[##1]}%
- \processcommalist[#2]\dododefinepalet}
- {\doifdefined{\??pa#2}
- {\expanded{\dodefinepalet[#1][\csname\??pa\??pa#2\endcsname]}}}}
+ {%\colo_helpers_show_message\m!colors6{#1}%
+ \let\m_colo_palets_tmp\empty
+ \setevalue{\??colorpaletspecification#1}{#2}%
+ \processcommalist[#2]{\colo_palets_define_one{#1}}%
+ \letvalue{\??colorpalet#1}\m_colo_palets_tmp
+ \let\m_colo_palets_tmp\empty}
+ {\ifcsname\??colorpaletspecification#2\endcsname
+ \normalexpanded{\colo_palets_define[#1][\csname\??colorpaletspecification#2\endcsname]}%
+ \fi}}
+
+\def\colo_palets_define_one#1#2% get rid of { } in #2
+ {\colo_palets_define_two{#1}[#2]}%
+
+\def\colo_palets_define_two#1[#2=#3]%
+ {\edef\m_colo_palets_tmp{\ifx\m_colo_palets_tmp\empty\else\m_colo_palets_tmp,\fi#2}%
+ \colo_palets_define_set{#1}{#2}{#3}}%
\let\paletsize\!!zerocount
\def\getpaletsize[#1]%
- {\getcommacommandsize[\csname\??pa\??pa#1\endcsname]%
+ {\getcommacommandsize[\csname\??colorpaletspecification#1\endcsname]%
\edef\paletsize{\number\commalistsize}}
%D Instead of refering to colors, one can also directly specify
@@ -411,22 +386,25 @@
%D
%D \showsetup{setuppalet}
-\let\currentpalet\empty
+\newtoks\everysetuppalet
\unexpanded\def\setuppalet
- {\dosingleempty\dosetuppalet}
+ {\dosingleempty\colo_palets_setup}
-\def\dosetuppalet[#1]%
- {\edef\currentpalet{#1}%
- \ifx\currentpalet\empty
+\def\colo_palets_setup[#1]%
+ {\edef\currentcolorpalet{#1}%
+ \ifx\currentcolorpalet\empty
% seems to be a reset
- \else\ifcsname\??pa\currentpalet\endcsname
- \edef\currentpalet{#1:}%
+ \let\currentcolorprefix\empty
+ \else\ifcsname\??colorpalet\currentcolorpalet\endcsname
+ \edef\currentcolorprefix{#1:}%
\else
- \showcolormessage\m!colors7\currentpalet
- \let\currentpalet\empty
+ \colo_helpers_show_message\m!colors7\currentcolorpalet
+ \let\currentcolorpalet\empty
+ \let\currentcolorprefix\empty
\fi\fi
- \initializemaintextcolor}
+ \the\everysetuppalet
+ \colo_helpers_initialize_maintextcolor}
%D \macros
%D {showpalet}
@@ -451,120 +429,6 @@
\fetchruntimecommand \showcolorcomponents {\f!colorprefix\s!run}
%D \macros
-%D {definecolorgroup}
-%D
-%D The naming of the colors in this palet suggests some
-%D ordening, which in turn is suported by color grouping.
-%D
-%D \starttyping
-%D \definecolorgroup
-%D [red]
-%D [1.00:0.90:0.90,
-%D 1.00:0.80:0.80,
-%D 1.00:0.70:0.70,
-%D 1.00:0.55:0.55,
-%D 1.00:0.40:0.40,
-%D 1.00:0.25:0.25,
-%D 1.00:0.15:0.15,
-%D 0.90:0.00:0.00]
-%D \stoptyping
-%D
-%D In such a color group colors are numbered from~$1$ to~$n$.
-%D
-%D \showsetup{definecolorgroup}
-%D
-%D This kind of specification is not only more compact than
-%D defining each color separate, it also loads faster and takes
-%D less bytes.
-
-\unexpanded\def\definecolorgroup
- {\dotripleempty\dodefinecolorgroup}
-
-\def\dododefinecolorgroupgray [#1][#2:#3]{\definecolor [#1:\the\colorcount][s=#2]}
-\def\dododefinecolorgrouprgb [#1][#2:#3:#4:#5]{\definecolor [#1:\the\colorcount][r=#2,g=#3,b=#4]}
-\def\dododefinecolorgroupcmyk[#1][#2:#3:#4:#5:#6]{\definecolor [#1:\the\colorcount][c=#2,m=#3=,y=#4,k=#5]}
-\def\dododefinecolorgroupspot [#1][#2:#3:#4]{\definespotcolor[#1:\the\colorcount][#2][p=#3]}
-
-\def\dododefinecolorgroup#1#2%
- {\advance\colorcount\plusone
- \getvalue{dododefinecolorgroup\currentcolorspace}[#1][#2:0:0:0:0]}
-
-\def\dodefinecolorgroup[#1][#2][#3]% obsolete, just use palets
- {\ifthirdargument
- \doifelsenothing{#2}{\let\currentcolorspace\v!rgb}{\def\currentcolorspace{#2}}%
- \colorcount\zerocount
- \processcommalist[#3]{\dododefinecolorgroup{#1}}%
- \else
- \doifinstringelse{:}{#2}
- {\definecolorgroup[#1][\v!rgb][#2]}
- {\doloop
- {\ifcsname\??cr#2:\recurselevel\endcsname
- \setevalue{\??cr#1:\recurselevel}{\csname\??cr#2:\recurselevel\endcsname}%
- \else
- \exitloop
- \fi}}%
- \fi}
-
-%D \macros
-%D {showcolorgroup}
-%D
-%D We can show the group by:
-%D
-%D \startbuffer
-%D \showcolorgroup [blue] [horizontal,name,number,value]
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D or in color:
-%D
-%D \startlinecorrection
-%D \getbuffer
-%D \stoplinecorrection
-%D
-%D which uses:
-%D
-%D \showsetup{showcolorgroup}
-
-\fetchruntimecommand \showcolorgroup {\f!colorprefix\s!run}
-
-%D There are ten predefined color groups, like
-%D \color[green]{\em groen}, \color[red]{\em rood},
-%D \color[blue]{\em blauw}, \color[cyan]{\em cyaan},
-%D \color[magenta]{\em magenta} and \color[yellow]{\em geel}.
-%D
-%D \startlinecorrection
-%D \hbox to \hsize
-%D {\hss
-%D \showcolorgroup [red] [vertical,name,number]\hss
-%D \showcolorgroup [green] [vertical,name]\hss
-%D \showcolorgroup [blue] [vertical,name]\hss
-%D \showcolorgroup [cyan] [vertical,name]\hss
-%D \showcolorgroup [magenta][vertical,name]\hss
-%D \showcolorgroup [yellow] [vertical,name]\hss}
-%D \stoplinecorrection
-%D
-%D These groups are used to define palets {\em alfa} upto {\em
-%D zeta}. As long as we don't use colors from the same row, we
-%D get ourselves distinctive palets. By activating such a palet
-%D one gains access to its members {\em top} to {\em charm} (of
-%D course one should use more suitable names than these).
-%D
-%D \startlinecorrection
-%D \hbox to \hsize
-%D {\showpalet [alfa] [vertical,name,number]\hss
-%D \showpalet [beta] [vertical,name]\hss
-%D \showpalet [gamma] [vertical,name]\hss
-%D \showpalet [delta] [vertical,name]\hss
-%D \showpalet [epsilon] [vertical,name]\hss
-%D \showpalet [zeta] [vertical,name]}
-%D \stoplinecorrection
-%D
-%D By using the keyword \type {value} the individual color
-%D components are shown too. When printed in color, these
-%D showcases show both the colors and the gray value.
-
-%D \macros
%D {comparepalet}
%D
%D There are some more testing macros available:
@@ -588,29 +452,6 @@
\fetchruntimecommand \comparepalet {\f!colorprefix\s!run}
%D \macros
-%D {comparecolorgroup}
-%D
-%D The similar command:
-%D
-%D \startbuffer
-%D \comparecolorgroup [blue]
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D shows color groups:
-%D
-%D \startlinecorrection
-%D \getbuffer
-%D \stoplinecorrection
-%D
-%D this commands are defined as:
-%D
-%D \showsetup{comparecolorgroup}
-
-\fetchruntimecommand \comparecolorgroup {\f!colorprefix\s!run}
-
-%D \macros
%D {showcolor}
%D
%D But let's not forget that we also have the more traditional
@@ -652,7 +493,7 @@
{\edef#1{\negatedcolorcomponent{#1}}}
%D \macros
-%D {ifMPgraphics, ifMPcmykcolors, MPcolor}
+%D {MPcolor}
%D
%D A very special macro is \type{\MPcolor}. This one can be
%D used to pass a \CONTEXT\ color to \METAPOST.
@@ -661,53 +502,22 @@
%D \MPcolor{my own red}
%D \stoptyping
%D
-%D This macro returns a \METAPOST\ triplet \type{(R,G,B)}.
-%D Unless \CMYK\ color support is turned on with \type
-%D {MPcmyk}, only \cap{RGB} colors and gray scales are
-%D supported.
-
-\newif\ifMPcmykcolors % \MPcmykcolorsfalse
-\newif\ifMPspotcolors % \MPspotcolorsfalse
-
-\ifx\MPcolor\undefined
- \def\MPcolor#1{(0,0,0)}
-\fi
-
+%D This macro returns \METAPOST\ code that represents the
+%D color.
+%D
%D For the moment we keep the next downward compatibility
%D switch, i.e.\ expanded colors. However, predefined colors
%D and palets are no longer expanded (which is what I wanted
%D in the first place).
%D
-%D Well, in case we want to do color separation and use CMYK
-%D colors only, this is dangerous since unwanted remapping may
-%D take place. Especially when we redefine already defined
-%D colors in another color space (e.g. darkgreen is
-%D predefined in RGB color space, so a redefinition in CMYK
-%D coordinates before RGB mode is disabled, would give
-%D unexpected results due to the already frozen color spec.)
-
-%D In \MKIV\ we don't support color separation as we might now assume
-%D that printing houses have the right programs to do it themselves.
-%D The \MKII\ color separator was implemented as part of a project
-%D that needed. If it's ever needed in \MKIV\ i'll do it in the
-%D backend.
-
-\let\doifseparatingcolorselse\secondoftwoarguments
-\let\doifcolorchannelelse \secondofthreearguments
-\let\resetcolorseparation \relax
-\let\colorchannelprefix \empty
-\let\colorchannelsuffix \empty
-
-%D We now define the low level macros:
+%D In \MKIV\ we don't support color separation as we might now
+%D assume that printing houses have the right programs to do
+%D it themselves. If it's ever needed in \MKIV\ It is relatively
+%D easy to support it in the backend code.
% todo: palets in definecolor
% todo: {\red xx} vs \red{xx}
-% check: registerusedspotcolors
-% check: \currentcolorname
-% check: \outercolorname
-% check: \startcolormode
-
% \def\mptexcolor#1{"\dogetattributeid\s!color \somecolorattribute{#1} A"}
%
% \startMPpage
@@ -717,46 +527,42 @@
% draw btex test etex withprescript \mptexcolor{blue} ;
% \stopMPpage
-% \ifx\currentcolormodel\undefined \newcount\currentcolormodel \fi
-
-\def\currentcolormodel{\attribute\colormodelattribute}
+\unexpanded\def\setcolormodel[#1]% % beware, \setupcolors will overload this, so this one is
+ {\colo_helpers_set_model{#1}} % only for local usage
-\def\dosetcolormodel#1% no message
- {\ctxcommand{setcolormodel('#1',\ifweightGRAY true\else false\fi)}} % sets attribute
+\def\colo_helpers_set_model#1% direct
+ {\edef\currentcolormodel{#1}%
+ \ctxcommand{setcolormodel('\currentcolormodel',\v_colo_weight_state)}} % sets attribute at lua end
-\dosetcolormodel{all}
+\colo_helpers_set_model\s!all
-\def\dosetupcolormodel
- {\ifincolor
- \ifRGBsupported
- \ifCMYKsupported
- \dosetcolormodel{all}%
+\def\colo_helpers_set_current_model
+ {\ifconditional\c_colo_enabled
+ \ifconditional\c_colo_rgb_supported
+ \ifconditional\c_colo_cmyk_supported
+ \colo_helpers_set_model\s!all
\else
- \dosetcolormodel{rgb}%
+ \colo_helpers_set_model\s!rgb
\fi
\else
- \ifCMYKsupported
- \dosetcolormodel{cmyk}%
+ \ifconditional\c_colo_cmyk_supported
+ \colo_helpers_set_model\s!cmyk
\else
- \ifconvertGRAY
- \dosetcolormodel{gray}%
+ \ifconditional\c_colo_convert_gray
+ \colo_helpers_set_model\s!gray
\else
- \dosetcolormodel{none}%
+ \colo_helpers_set_model\s!none
\fi
\fi
\fi
\else
- \ifconvertGRAY
- \dosetcolormodel{gray}%
+ \ifconditional\c_colo_convert_gray
+ \colo_helpers_set_model\s!gray
\else
- \dosetcolormodel{none}%
+ \colo_helpers_set_model\s!none
\fi
\fi}
-\appendtoks
- \dosetupcolormodel
-\to \everyjob
-
% Currently in mkiv transparency is implemented independent of color. This costs
% a bit more processing time but gives the possibility to apply transparency
% independently in the future. Is this useful? If not we may as well combine them
@@ -766,87 +572,135 @@
% Since we couple definitions, we could stick to one test. Todo. Same for mpcolor.
-\letvalueempty{(cs:-}
-\letvalueempty{(ts:-}
-
-\def\doactivatecolor#1% : in currentpalet, maybe not, ugly (some day at the lua end)
- {\def\currentcolorname{#1}%
- \ifcsname(cs:\currentpalet#1)\endcsname
- \csname(cs:\currentpalet#1)\endcsname
- \csname(ts:\currentpalet#1)\endcsname
- \else\ifcsname(cs:#1)\endcsname
- \csname(cs:#1)\endcsname
- \csname(ts:#1)\endcsname
+\def\v_colo_dummy_name{d_u_m_m_y}
+
+\letvalue{\??colorsetter-}\empty % used?
+\letvalue{\??transparencysetter-}\empty % used?
+
+\def\colo_helpers_activate % two-step is not that much faster but less tracing
+ {\ifx\currentcolorprefix\empty
+ \expandafter\colo_helpers_activate_nop
+ \else
+ \expandafter\colo_helpers_activate_yes
+ \fi}
+
+\def\colo_helpers_activate_yes#1%
+ {\edef\currentcolorname{#1}%
+ \ifcsname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
+ \csname\??colorsetter\currentcolorprefix\currentcolorname\endcsname
+ \csname\??transparencysetter\currentcolorprefix\currentcolorname\endcsname
+ \else\ifcsname\??colorsetter\currentcolorname\endcsname
+ \csname\??colorsetter\currentcolorname\endcsname
+ \csname\??transparencysetter\currentcolorname\endcsname
\fi\fi}
-\let\normaldoactivatecolor\doactivatecolor
+\def\colo_helpers_activate_nop#1%
+ {\edef\currentcolorname{#1}%
+ \ifcsname\??colorsetter\currentcolorname\endcsname
+ \csname\??colorsetter\currentcolorname\endcsname
+ \csname\??transparencysetter\currentcolorname\endcsname
+ \fi}
-% if it becomes a bottleneck we can set up a more complex system with one shared
-% attribute for colorspace, color and transparency
-%
-% maybe always on
+\def\colo_helpers_activate_dummy
+ {\csname\??colorsetter \v_colo_dummy_name\endcsname
+ \csname\??transparencysetter\v_colo_dummy_name\endcsname}
-\def\doactivatecolor
- {\ifproductionrun
- \ctxcommand{enablecolor() commands.enabletransparency()}% not that efficient but at least robust
- \let\doactivatecolor\normaldoactivatecolor
- \expandafter\doactivatecolor
- \else
- \expandafter\normaldoactivatecolor
+\let\dousecolorparameter\colo_helpers_activate
+
+\unexpanded\def\dousecolorhashparameter#1#2%
+ {\ifcsname#1#2\endcsname
+ \expandafter\dousecolorparameter\csname#1#2\endcsname
\fi}
-\def\deactivatecolor
+\unexpanded\def\dousecurrentcolorparameter
+ {\let\currentcolorname\currentcolorparameter % maybe only when success
+ \ifcsname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
+ \csname\??colorsetter\currentcolorprefix\currentcolorparameter\endcsname
+ \csname\??transparencysetter\currentcolorprefix\currentcolorparameter\endcsname
+ \else\ifcsname\??colorsetter\currentcolorparameter\endcsname
+ \csname\??colorsetter\currentcolorparameter\endcsname
+ \csname\??transparencysetter\currentcolorparameter\endcsname
+ \fi\fi}
+
+\let\dosetcolorattribute\dousecolorhashparameter % for a while
+
+\unexpanded\def\deactivatecolor % sort of public but a bad name
{\let\currentcolorname\s!black
\attribute\colorattribute\attributeunsetvalue
\attribute\transparencyattribute\attributeunsetvalue}
-\def\dodefinecolorcommand#1#2%
- {\unexpanded#1{#2}{\doactivatecolor{#2}}}
+\def\colo_basics_define[#1][#2]%
+ {\ctxcommand{defineprocesscolor("#1","#2",false,\v_colo_freeze_state)}%
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}
-\let\colorlist\empty % not really used, only for colo-run
-\setfalse\collectcolorsinlist
-\def\collectcolorinlist#1{\doglobal\addtocommalist{#1}\colorlist}
+\def\colo_basics_define_global[#1][#2]%
+ {\ctxcommand{defineprocesscolor("#1","#2",true,\v_colo_freeze_state)}%
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}}
-\def\doregistercolor#1#2%
- {\ctxcommand{defineprocesscolor("#1","#2",false,\colorfreezestate)}}
+\def\colo_basics_define_named[#1][#2]%
+ {\ctxcommand{defineprocesscolor("#1","#2",false,\v_colo_freeze_state)}%
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}
-\def\dodefinecolor[#1][#2]%
- {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
- \ctxcommand{defineprocesscolor("#1","#2",false,\colorfreezestate)}%
- \dodefinecolorcommand\setvalue{#1}}
+\def\dodefinefastcolor[#1][#2]% still not fast but ok (might change)
+ {\ctxcommand{defineprocesscolor("#1","#2",false,\v_colo_freeze_state)}%
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}
-\def\dodefineglobalcolor[#1][#2]%
- {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
- \ctxcommand{defineprocesscolor("#1","#2",true,\colorfreezestate)}%
- \dodefinecolorcommand\setgvalue{#1}}
+\def\colo_basics_defined_and_activated#1%
+ {\ctxcommand{defineprocesscolor("\v_colo_dummy_name","#1",false,false)}%
+ \colo_helpers_activate_dummy}
-\def\dodefinenamedcolor[#1][#2]%
- {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
- \ctxcommand{defineprocesscolor("#1","#2",false,\colorfreezestate)}%
- \dodefinecolorcommand\setvalue{#1}}
+% Spotcolors used setxvalue but that messes up currentcolor
+% and probably no global is needed either but they are global
+% at the lua end (true argument) so we keep that if only because
+% spot colors often are a document wide property
-\def\dodefinespotcolor[#1][#2][#3]%
- {\ifconditional\collectcolorsinlist\collectcolorinlist{#1}\fi
- \ctxcommand{definespotcolor("#1","#2","#3",true)}%
- \dodefinecolorcommand\setxvalue{#1}}
+\def\colo_basics_define_spot[#1][#2][#3]%
+ {\ctxcommand{definespotcolor("#1","#2","#3",true)}%
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}}
-\def\dodefinemultitonecolor[#1][#2][#3][#4]%
+\def\colo_basics_define_multitone[#1][#2][#3][#4]%
{\ctxcommand{definemultitonecolor("#1","#2","#3","#4",true)}%
- \dodefinecolorcommand\setxvalue{#1}}
+ \unexpanded\setgvalue{#1}{\colo_helpers_activate{#1}}}
-\def\dodefinetransparency[#1][#2]%
+%D Transparencies (only):
+
+\def\colo_basics_define_transpancy[#1][#2]%
{\ctxcommand{definetransparency("#1",#2)}}
-\def\dosetrastercolor#1% slow, we need a fast one
- {\edef\@@rastervalue{#1}%
- \ifx\@@rastervalue\empty
- \let\@@rastervalue\@@rsscreen
- \fi
- \ctxcommand{setrastercolor("_raster_",\@@rastervalue)}} % sets attribute
+% A goodie that replaces the startMPcolor hackery
-\def\dodefinefastcolor[#1][#2]% still not fast but ok
- {\ctxcommand{defineprocesscolor("#1","#2",false,\colorfreezestate)}%
- \dodefinecolorcommand\setvalue{#1}}
+% \definecolor[red-t] [r=1,t=0.5,a=1]
+% \definecolor[green-t][g=1,t=0.5,a=1]
+%
+% \defineintermediatecolor[mycolora][0.5,red,green]
+% \defineintermediatecolor[mycolorb][0.5,red-t,green-t]
+%
+% \definecolor[mycolorc][.5(blue,red)]
+% \definecolor[mycolord][.5(blue)]
+%
+% \enabledirectives[colors.pgf]
+% \definecolor[mycolorx][magenta!50!yellow]
+%
+% \starttext
+% test {\mycolora OEPS} test
+% test {\mycolorb OEPS} test
+% test {\mycolorc OEPS} test
+% test {\mycolord OEPS} test
+% test {\mycolorx OEPS} test
+% \stoptext
+
+\unexpanded\def\defineintermediatecolor
+ {\dotripleempty\colo_basics_define_intermediate}
+
+\def\colo_basics_define_intermediate[#1][#2][#3]% \dotripleempty adds {} inside []
+ {\colo_basics_define_intermediate_indeed[#1][#2][#3]}
+
+\def\colo_basics_define_intermediate_indeed[#1][#2,#3,#4][#5]%
+ {\ctxcommand{defineintermediatecolor("#1","#2",
+ \thecolorattribute{#3},\thecolorattribute{#4},
+ \thetransparencyattribute{#3},\thetransparencyattribute{#4},
+ "#5",false,\iffreezecolors true\else false\fi)}% not global
+ \unexpanded\setvalue{#1}{\colo_helpers_activate{#1}}}
%D \macros
%D {doifcolorelse, doifcolor}
@@ -856,33 +710,24 @@
%D define ourselves a color conditional first.
\def\doifcolorelse#1%
- {\ifcsname(ca:\currentpalet#1)\endcsname
- \@EA\firstoftwoarguments
- \else\ifcsname(ca:#1)\endcsname
- \@EAEAEA\firstoftwoarguments
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else\ifcsname\??colorattribute#1\endcsname
+ \doubleexpandafter\firstoftwoarguments
\else
- \@EAEAEA\secondoftwoarguments
+ \doubleexpandafter\secondoftwoarguments
\fi\fi}
\def\doifcolor#1%
- {\ifcsname(ca:\currentpalet#1)\endcsname
- \@EA\firstofoneargument
- \else\ifcsname(ca:#1)\endcsname
- \@EAEAEA\firstofoneargument
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \expandafter\firstofoneargument
+ \else\ifcsname\??colorattribute#1\endcsname
+ \doubleexpandafter\firstofoneargument
\else
- \@EAEAEA\gobbleoneargument
+ \doubleexpandafter\gobbleoneargument
\fi\fi}
%D \macros
-%D {colored}
-%D
-%D A bit like \type {\definedfont}:
-
-\unexpanded\def\colored[#1]%
- {\ctxcommand{defineprocesscolor("@colored@","#1",false,false)}%
- \groupedcommand{\doactivatecolor{@colored@}}{}}
-
-%D \macros
%D {startregistercolor,stopregistercolor,permitcolormode}
%D
%D If you only want to register a color, the switch \type
@@ -908,94 +753,107 @@
%D \stopregistercolor
%D \stoptyping
-% can be cleaned up
-
\let\maintextcolor \empty
\def\defaulttextcolor {black}
-\def\@@themaintextcolor{themaintextcolor}
+\def\s!themaintextcolor{themaintextcolor}
\appendtoks
- \deactivatecolor
- \ifx\maintextcolor\empty\else\doactivatecolor\maintextcolor\fi
+ \deactivatecolor % public?
+ \ifx\maintextcolor\empty\else\colo_helpers_activate\maintextcolor\fi
\to \everybeforeoutput
-\def\registermaintextcolor
- {\ctxcommand{registermaintextcolor(\thecolorattribute\maintextcolor)}}
+\def\colo_helpers_switch_to_maintextcolor#1%
+ {\let\maintextcolor\s!themaintextcolor
+ \definecolor[\maintextcolor][#1]% can be fast one
+ \colo_helpers_activate\maintextcolor
+ \ctxcommand{registermaintextcolor(\thecolorattribute\maintextcolor)}}
\unexpanded\def\starttextcolor[#1]%
{\doifsomething{#1}
- {\definecolor[\@@themaintextcolor][#1]%
- \let\maintextcolor\@@themaintextcolor
- \doactivatecolor\maintextcolor
- \registermaintextcolor}}
+ {\colo_helpers_switch_to_maintextcolor{#1}}}
\let\stoptextcolor\relax
-\def\initializemaintextcolor
- {\doifelsenothing\@@cltextcolor
- {\definecolor[\@@themaintextcolor][\defaulttextcolor]}
- {\definecolor[\@@themaintextcolor][\@@cltextcolor]}%
- \let\maintextcolor\@@themaintextcolor
- \doactivatecolor\maintextcolor
- \registermaintextcolor}
+\let\p_colo_textcolor\empty
+
+\def\colo_helpers_initialize_maintextcolor
+ {\edef\p_colo_textcolor{\directcolorsparameter\c!textcolor}%
+ \ifx\p_colo_textcolor\empty
+ \colo_helpers_switch_to_maintextcolor\defaulttextcolor
+ \else
+ \colo_helpers_switch_to_maintextcolor\p_colo_textcolor
+ \fi}
+
+\appendtoks \colo_helpers_initialize_maintextcolor \to \everyjob
+\appendtoks \colo_helpers_initialize_maintextcolor \to \everysetupcolors
-\appendtoks \initializemaintextcolor \to \everyjob
-\appendtoks \initializemaintextcolor \to \everysetupcolors
+\def\colo_helpers_inherited_direct_cs#1{\csname\??colorsetter \ifcsname\??colorsetter #1\endcsname#1\fi\endcsname}
+\def\colo_helpers_inherited_direct_ca#1{\csname\??colorattribute \ifcsname\??colorattribute #1\endcsname#1\fi\endcsname}
+\def\colo_helpers_inherited_direct_ts#1{\csname\??transparencysetter \ifcsname\??transparencysetter #1\endcsname#1\fi\endcsname}
+\def\colo_helpers_inherited_direct_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute#1\endcsname#1\fi\endcsname}
-\def\doinheritdirectcs#1{\csname(cs:\ifcsname(cs:#1)\endcsname#1\fi)\endcsname}
-\def\doinheritdirectca#1{\csname(ca:\ifcsname(ca:#1)\endcsname#1\fi)\endcsname}
-\def\doinheritdirectts#1{\csname(ts:\ifcsname(ts:#1)\endcsname#1\fi)\endcsname}
-\def\doinheritdirectta#1{\csname(ta:\ifcsname(ta:#1)\endcsname#1\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_cs#1#2{\csname\??colorsetter \ifcsname\??colorsetter \??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_ts#1#2{\csname\??transparencysetter \ifcsname\??transparencysetter \??colorpalet#1:#2\endcsname\??colorpalet#1:#2\fi\endcsname}
-\def\doinheritpaletca#1#2{\csname(ca:\ifcsname(ca:\??pa#1:#2)\endcsname\??pa#1:#2\fi)\endcsname}
-\def\doinheritpaletcs#1#2{\csname(cs:\ifcsname(cs:\??pa#1:#2)\endcsname\??pa#1:#2\fi)\endcsname}
-\def\doinheritpaletta#1#2{\csname(ta:\ifcsname(ta:\??pa#1:#2)\endcsname\??pa#1:#2\fi)\endcsname}
-\def\doinheritpaletts#1#2{\csname(ts:\ifcsname(ts:\??pa#1:#2)\endcsname\??pa#1:#2\fi)\endcsname}
+\let\colo_helpers_set_value\setvalue
+
+\appendtoks
+ \ifconditional\c_colo_expanded
+ \let\colo_helpers_set_value\setevalue
+ \else
+ \let\colo_helpers_set_value\setvalue
+ \fi
+\to \everysetupcolors
-\def\dodefinepaletcolor#1#2#3%
+\def\colo_palets_define_set#1#2#3%
{\doifassignmentelse{#3}% \definepalet[test][xx={y=.4}]
- {\definecolor[\??pa#1:#2][#3]%
- \dosetcolorvalue{(cs:#1:#2)}{\doinheritpaletca{#1}{#2}}%
- \dosetcolorvalue{(ca:#1:#2)}{\doinheritpaletcs{#1}{#2}}%
- \dosetcolorvalue{(ts:#1:#2)}{\doinheritpaletta{#1}{#2}}%
- \dosetcolorvalue{(ta:#1:#2)}{\doinheritpaletts{#1}{#2}}}
- {\ifcsname(cs:#3)\endcsname % \definepalet[test][xx=green]
- \dosetcolorvalue{(cs:#1:#2)}{\doinheritdirectcs{#3}}%
- \dosetcolorvalue{(ca:#1:#2)}{\doinheritdirectca{#3}}%
- \dosetcolorvalue{(ts:#1:#2)}{\doinheritdirectts{#3}}%
- \dosetcolorvalue{(ta:#1:#2)}{\doinheritdirectta{#3}}%
+ {\definecolor[\??colorpalet#1:#2][#3]%
+ \colo_helpers_set_value{\??colorsetter #1:#2}{\colo_helpers_inherited_palet_ca{#1}{#2}}%
+ \colo_helpers_set_value{\??colorattribute #1:#2}{\colo_helpers_inherited_palet_cs{#1}{#2}}%
+ \colo_helpers_set_value{\??transparencysetter #1:#2}{\colo_helpers_inherited_palet_ta{#1}{#2}}%
+ \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_palet_ts{#1}{#2}}}
+ {\ifcsname\??colorsetter#3\endcsname % \definepalet[test][xx=green]
+ \colo_helpers_set_value{\??colorsetter #1:#2}{\colo_helpers_inherited_direct_cs{#3}}%
+ \colo_helpers_set_value{\??colorattribute #1:#2}{\colo_helpers_inherited_direct_ca{#3}}%
+ \colo_helpers_set_value{\??transparencysetter #1:#2}{\colo_helpers_inherited_direct_ts{#3}}%
+ \colo_helpers_set_value{\??transparencyattribute#1:#2}{\colo_helpers_inherited_direct_ta{#3}}%
\else
% not entered when making format
- \localundefine{(cs:#1:#2)}% \letvalue{(cs:#1:#2)}\undefined
- \localundefine{(ca:#1:#2)}% \letvalue{(ca:#1:#2)}\undefined
- \localundefine{(ts:#1:#2)}% \letvalue{(cs:#1:#2)}\undefined
- \localundefine{(ta:#1:#2)}% \letvalue{(ca:#1:#2)}\undefined
+ \localundefine{\??colorsetter #1:#2}%
+ \localundefine{\??colorattribute #1:#2}%
+ \localundefine{\??transparencysetter #1:#2}%
+ \localundefine{\??transparencyattribute#1:#2}%
\fi}}
-\setvalue{(cs:)}{} \setvalue{(ca:)}{0}
-\setvalue{(ts:)}{} \setvalue{(ta:)}{0}
+\letvalue{\??colorsetter }\empty \letvalue{\??colorattribute }\!!zerocount
+\letvalue{\??transparencysetter}\empty \letvalue{\??transparencyattribute}\!!zerocount
+
+\setvalue{\??colorattribute currentcolor}{\the\attribute\colorattribute} % for mpcolor
+\setvalue{\??transparencyattribute currentcolor}{\the\attribute\transparencyattribute} % for mpcolor
-\def\doinheritca#1{\csname(ca:\ifcsname(ca:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ca:#1)\endcsname#1\fi\fi)\endcsname}
-\def\doinheritcs#1{\csname(cs:\ifcsname(cs:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(cs:#1)\endcsname#1\fi\fi)\endcsname}
-\def\doinheritta#1{\csname(ta:\ifcsname(ta:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ta:#1)\endcsname#1\fi\fi)\endcsname}
-\def\doinheritts#1{\csname(ts:\ifcsname(ts:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ts:#1)\endcsname#1\fi\fi)\endcsname}
+\def\colo_helpers_inherited_current_ca#1{\csname\??colorattribute \ifcsname\??colorattribute \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute #1\endcsname#1\fi\fi\endcsname}
+\def\colo_helpers_inherited_current_cs#1{\csname\??colorsetter \ifcsname\??colorsetter \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorsetter #1\endcsname#1\fi\fi\endcsname}
+\def\colo_helpers_inherited_current_ta#1{\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
+\def\colo_helpers_inherited_current_ts#1{\csname\??transparencysetter \ifcsname\??transparencysetter \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencysetter #1\endcsname#1\fi\fi\endcsname}
%D Low level defs:
-\def\colordefalc#1#2{\setevalue{(ca:#1)}{#2}\setvalue {(cs:#1)}{\attribute\colorattribute #2 }}
-\def\colordefagc#1#2{\setxvalue{(ca:#1)}{#2}\setgvalue{(cs:#1)}{\attribute\colorattribute #2 }} % was not g
-\def\colordefalt#1#2{\setevalue{(ta:#1)}{#2}\setvalue {(ts:#1)}{\attribute\transparencyattribute#2 }}
-\def\colordefagt#1#2{\setxvalue{(ta:#1)}{#2}\setgvalue{(ts:#1)}{\attribute\transparencyattribute#2 }}
+\unexpanded\def\colordefalc#1#2{\setevalue{\??colorattribute #1}{#2}\setvalue {\??colorsetter #1}{\attribute\colorattribute #2 }}
+\unexpanded\def\colordefagc#1#2{\setxvalue{\??colorattribute #1}{#2}\setgvalue{\??colorsetter #1}{\attribute\colorattribute #2 }} % was not g
+\unexpanded\def\colordefalt#1#2{\setevalue{\??transparencyattribute#1}{#2}\setvalue {\??transparencysetter#1}{\attribute\transparencyattribute#2 }}
+\unexpanded\def\colordefagt#1#2{\setxvalue{\??transparencyattribute#1}{#2}\setgvalue{\??transparencysetter#1}{\attribute\transparencyattribute#2 }}
-\def\colordefflc#1#2{\setvalue {(ca:#1)}{\doinheritca{#2}}\setvalue {(cs:#1)}{\doinheritcs{#2}}}
-\def\colordeffgc#1#2{\setgvalue{(ca:#1)}{\doinheritca{#2}}\setvalue {(cs:#1)}{\doinheritcs{#2}}}
-\def\colordefflt#1#2{\setvalue {(ta:#1)}{\doinheritta{#2}}\setvalue {(ts:#1)}{\doinheritts{#2}}}
-\def\colordeffgt#1#2{\setgvalue{(ta:#1)}{\doinheritta{#2}}\setgvalue{(ts:#1)}{\doinheritts{#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}}}
-\def\colordefrlc #1{\localundefine {(ca:#1)}\localundefine {(cs:#1)}}
-\def\colordefrgc #1{\globalundefine{(ca:#1)}\globalundefine{(cs:#1)}}
-\def\colordefrlt #1{\localundefine {(ta:#1)}\localundefine {(ts:#1)}}
-\def\colordefrgt #1{\globalundefine{(ta:#1)}\globalundefine{(ts:#1)}}
+\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}}
%D \macros
%D {colorvalue, grayvalue}
@@ -1012,19 +870,22 @@
%D
%D show us:
%D
-%D \startvoorbeeld
+%D \startexample
%D \getbuffer
-%D \stopvoorbeeld
+%D \stopexample
\let\currentcolorname\s!black % todo
\let\outercolorname \s!black % todo
\let\colorformatseparator\space
-\def\MPcolor #1{\ctxcommand{mpcolor(\number\currentcolormodel,\number\doinheritca{#1},\number\doinheritta{#1})}}
+\def\MPcolor #1{\ctxcommand{mpcolor(\number\attribute\colormodelattribute,\number\colo_helpers_inherited_current_ca{#1},\number\colo_helpers_inherited_current_ta{#1})}}
+\def\MPoptions #1{\ctxcommand{mpoptions(\number\attribute\colormodelattribute,\number\colo_helpers_inherited_current_ca{#1},\number\colo_helpers_inherited_current_ta{#1})}}
-\def\thecolorattribute #1{\number\csname(ca:\ifcsname(ca:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ca:#1)\endcsname#1\fi\fi)\endcsname}
-\def\thetransparencyattribute#1{\number\csname(ta:\ifcsname(ta:\currentpalet#1)\endcsname\currentpalet#1\else\ifcsname(ta:#1)\endcsname#1\fi\fi)\endcsname}
+\def\thecolorattribute #1{\number\csname\??colorattribute \ifcsname\??colorattribute \currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??colorattribute #1\endcsname#1\fi\fi\endcsname}
+\def\thetransparencyattribute#1{\number\csname\??transparencyattribute\ifcsname\??transparencyattribute\currentcolorprefix#1\endcsname\currentcolorprefix#1\else\ifcsname\??transparencyattribute#1\endcsname#1\fi\fi\endcsname}
+
+\def\thecolormodelattribute {\the\attribute\colormodelattribute}
\def\internalspotcolorname #1{\ctxcommand{spotcolorname(\thecolorattribute{#1})}}
\def\internalspotcolorparent #1{\ctxcommand{spotcolorparent(\thecolorattribute{#1})}}
@@ -1059,12 +920,11 @@
% \normal added else fails in metafun manual (leaders do a hard scan)
-\unexpanded\def\forcecolorhack{\leaders\hrule\normalhskip\zeropoint}
+\unexpanded\def\forcecolorhack{\leaders\hrule\hskip\zeropoint}
-%D We default to the colors defined in \module{colo-rgb} and
-%D support both \cap{RGB} and \cap{CMYK} output. As you can
-%D see, color support is turned off by default. Reduction of
-%D gray colors to gray scales is turned on.
+%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:
\definecolor[black][s=0]
\definecolor[white][s=1]
@@ -1082,29 +942,21 @@
\definetransparency [lighten] [10]
\definetransparency [difference] [11]
\definetransparency [exclusion] [12]
+\definetransparency [hue] [13]
+\definetransparency [saturation] [14]
+\definetransparency [color] [15]
+\definetransparency [luminosity] [16]
\setupcolors
- [\c!state=\v!stop, % will be enabled later on
+ [\c!state=\v!stop, % color will be enabled later on
\c!conversion=\v!yes,
- \c!reduction=\v!no,
\c!rgb=\v!yes,
\c!cmyk=\v!yes,
\c!spot=\v!yes,
- \c!mp\c!cmyk=\@@clcmyk,
- \c!mp\c!spot=\@@clspot,
+ \c!pagecolormodel=\v!none,
\c!expansion=\v!no,
\c!textcolor=,
- \c!split=\v!no, % obsolete
- \c!factor=\v!yes,
- \c!criterium=\v!all] % obsolete
-
-\appendtoks
- \setupcolors[\c!state=\v!start]% later direct
-\to \everyjob
-
-\appendtoks
- \let\showcolormessage\showmessage
-\to \everyjob
+ \c!factor=\v!yes]
\setupcolor
[\v!rgb]
diff --git a/Master/texmf-dist/tex/context/base/colo-rgb.mkii b/Master/texmf-dist/tex/context/base/colo-rgb.mkii
index 038e0ab0bf1..f734c7a014c 100644
--- a/Master/texmf-dist/tex/context/base/colo-rgb.mkii
+++ b/Master/texmf-dist/tex/context/base/colo-rgb.mkii
@@ -5,7 +5,7 @@
%D subtitle=RGB,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/colo-run.lua b/Master/texmf-dist/tex/context/base/colo-run.lua
new file mode 100644
index 00000000000..4f1916d5ada
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/colo-run.lua
@@ -0,0 +1,66 @@
+if not modules then modules = { } end modules ['colo-run'] = {
+ version = 1.000,
+ comment = "companion to colo-run.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- For historic reasons the core has a couple of tracing
+-- features. Nowadays these would end up in modules.
+
+local colors= attributes.colors
+
+function commands.showcolorset(name)
+ local set = colors.setlist(name)
+ context.starttabulate { "|l|l|l|l|l|l|l|" }
+ for i=1,#set do
+ local s = set[i]
+ local r = { width = "4em", height = "max", depth = "max", color = s }
+ context.NC()
+ context.setcolormodel { "gray" }
+ context.blackrule(r)
+ context.NC()
+ context.blackrule(r)
+ context.NC()
+ context.grayvalue(s)
+ context.NC()
+ context.colorvalue(s)
+ context.NC()
+ context(s)
+ context.NC()
+ context.NR()
+ end
+ context.stoptabulate()
+end
+
+function commands.showcolorcomponents(list)
+ local set = utilities.parsers.settings_to_array(list)
+ context.starttabulate { "|lT|lT|lT|lT|" }
+ context.NC()
+ context("color")
+ context.NC()
+ context("name")
+ context.NC()
+ context("transparency")
+ context.NC()
+ context("specification ")
+ context.NC()
+ context.NR()
+ context.TB()
+ for i=1,#set do
+ local s = set[i]
+ context.NC()
+ context.showcolorbar { s }
+ context.NC()
+ context(s)
+ context.NC()
+ context.transparencycomponents(s)
+ context.NC()
+ context.colorcomponents(s)
+ context.NC()
+ context.NR()
+ end
+ context.stoptabulate()
+end
+
diff --git a/Master/texmf-dist/tex/context/base/colo-run.mkii b/Master/texmf-dist/tex/context/base/colo-run.mkii
index d94ea980128..02da462d385 100644
--- a/Master/texmf-dist/tex/context/base/colo-run.mkii
+++ b/Master/texmf-dist/tex/context/base/colo-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Runtime loaded commands,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/colo-run.mkiv b/Master/texmf-dist/tex/context/base/colo-run.mkiv
index d94ea980128..c330accf3dd 100644
--- a/Master/texmf-dist/tex/context/base/colo-run.mkiv
+++ b/Master/texmf-dist/tex/context/base/colo-run.mkiv
@@ -5,63 +5,82 @@
%D subtitle=Runtime loaded commands,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
+\registerctxluafile{colo-run}{1.000}
+
\unprotect
-% temp hack (not do be documented)
+%D Colors
+
+% These are nicer in \LUA\ code than in \TEX\ code but not more
+% efficient.
+
+\unexpanded\gdef\showcolorbar[#1]%
+ {\backgroundline[#1]{\strut\enspace\color[white]{white}\enspace\color[black]{black}\enspace}}
-% \gdef\doformatcolorP#1:#2:#3:#4:#5:#6\od % was undefined in colo-ini
-% {#1\colorformatseparator
-% \dodoformatcolor{#2}\colorformatseparator
-% \dodoformatcolor{#3}\colorformatseparator
-% \dodoformatcolor{#4}\colorformatseparator}
+\unexpanded\gdef\showcolor {\dosingleempty\colo_basics_show}
+\unexpanded\gdef\showcolorset {\dosingleempty\colo_basics_show_set}
+\unexpanded\gdef\showcolorcomponents{\dosingleempty\colo_basics_show_components}
-% \gdef\doformatgrayP#1:#2:#3:#4:#5:#6\od
-% {todo}
+\gdef\colo_basics_show_set [#1]{\ctxcommand{showcolorset("#1")}}
+\gdef\colo_basics_show_components[#1]{\ctxcommand{showcolorcomponents("#1")}}
-% so far
+\gdef\colo_basics_show[#1]% % we do this at the tex end as loading happens
+ {\usecolors [#1]% % delayed and we can only ask for the set if
+ \showcolorset[#1]} % loading has happened
-\gdef\showpalet
+% The rest might also be done in \LUA\ although there is not much
+% beauty to gain here (too much typesetting specific). Also, these
+% macros are pretty old and hardly used so best keep them as they
+% are.
+
+%D Palets
+
+\unexpanded\gdef\showpalet
{\dodoubleargument\doshowpalet}
\gdef\doshowpalet[#1][#2]%
- {\doifdefined{\??pa#1}
- {\doifinsetelse\v!vertical{#2}
- {\showverticalpalet[#1][#2]}
- {\showhorizontalpalet[#1][#2]}}}
-
-\gdef\showverticalpalet[#1][#2]%
- {\localvbox
- {\offinterlineskip
+ {\ifcsname\??colorpalet#1\endcsname
+ \doifinsetelse\v!vertical{#2} \colo_palets_show_vertical \colo_palets_show_horizontal [#1][#2]%
+ \fi}
+
+\gdef\colo_palets_show_vertical[#1][#2]%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
\setuppalet[#1]
- \def\rule
- {\vrule\!!width3em\!!height\strutht\!!depth\strutdp}
\tabskip\zeropoint
- \def\doshowpalet##1%
+ \def\colo_palets_show_palet##1%
{\doifinsetelse\v!number{#2}{##1\hskip.5em}{}&
- \color[##1]{\rule}\graycolor[##1]{\rule}&
+ \color[##1]{\vrule\!!width3em\!!height\strutht\!!depth\strutdp}%
+ \graycolor[##1]{\vrule\!!width3em\!!height\strutht\!!depth\strutdp}&
\doifinset\v!value{#2}{\hskip.5em\colorvalue{##1}}\crcr}
\halign
{\hss##&\hss##\hss&##\cr
- &\doifinset{\v!name}{#2}{\strut#1}&\cr%
- \processpalet[#1]\doshowpalet\crcr}}}
-
-\gdef\showhorizontalpalet[#1][#2]%
- {\localvbox
- {\offinterlineskip
+ &\doifinset\v!name{#2}{\strut#1}&\cr%
+ \colo_palets_process[#1]\colo_palets_show_palet\crcr}}}
+
+\gdef\colo_palets_show_horizontal[#1][#2]% todo: bTABLE etc
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
\setuppalet[#1]
\tabskip\zeropoint
\!!widtha\zeropoint
\doifinset\v!number{#2}
- {\def\doshowpalet##1%
+ {\def\colo_palets_show_palet##1%
{\setbox0\hbox{##1}%
\ifdim\!!widtha<\wd0\!!widtha\wd0\fi}%
- \processpalet[#1]\doshowpalet}%
+ \colo_palets_process[#1]\colo_palets_show_palet}%
\advance\!!widtha 1em
\ifdim\!!widtha<5em
\!!widtha5em
@@ -69,58 +88,92 @@
\halign
{##&&\hbox to \!!widtha{\hss##\hss}\cr
\doifinset\v!number{#2}
- {\def\doshowpalet##1{&\strut##1}%
- \processpalet[#1]\doshowpalet}\cr
+ {\def\colo_palets_show_palet##1{&\strut##1}%
+ \colo_palets_process[#1]\colo_palets_show_palet}\cr
\doifinset\v!name{#2}{#1\hskip.5em}%
- \def\doshowpalet##1%
+ \def\colo_palets_show_palet##1%
{&\strut\color[##1]{\vrule\!!width\!!widtha\!!height\strutht\!!depth\zeropoint}}%
- \processpalet[#1]\doshowpalet\crcr
+ \colo_palets_process[#1]\colo_palets_show_palet\crcr
\noalign{\vskip-\strutdepth}%
- \def\doshowpalet##1%
+ \def\colo_palets_show_palet##1%
{&\graycolor[##1]{\vrule\!!width\!!widtha\!!height\zeropoint\!!depth\strutdp}}%
- \processpalet[#1]\doshowpalet\crcr
+ \colo_palets_process[#1]\colo_palets_show_palet\crcr
\doifinset\v!value{#2}
- {\def\doshowpalet##1%
+ {\def\colo_palets_show_palet##1%
{&\vbox
{\hsize\!!widtha
\vskip.25ex
\everypar{\strut}
\veryraggedcenter
- \let\colorformatseparator=\endgraf
+ \let\colorformatseparator\endgraf
\colorvalue{##1}}}%
- \processpalet[#1]\doshowpalet}%
+ \colo_palets_process[#1]\colo_palets_show_palet}%
\crcr}}}
-\gdef\processpalet[#1]%
- {\expanded{\globalprocesscommalist[\getvalue{\??pa#1}]}}
+\gdef\colo_palets_process[#1]%
+ {\expanded{\globalprocesscommalist[\getvalue{\??colorpalet#1}]}}
+
+\unexpanded\gdef\comparepalet
+ {\dosingleargument\colo_palets_compare}
+
+\gdef\colo_palets_compare[#1]%
+ {\ifcsname\??colorpalet#1\endcsname
+ \hbox
+ {\colo_palets_compare_indeed\color[#1]%
+ \quad
+ \colo_palets_compare_indeed\graycolor[#1]}%
+ \fi}
+
+\gdef\colo_palets_compare_indeed#1[#2]%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
+ \setuppalet[#2]
+ \getcommacommandsize[\getvalue{\??colorpalet#2}]
+ \!!widtha2em\relax
+ \hsize\commalistsize\!!widtha
+ \def\colo_palets_compare##1%
+ {\hbox
+ {\setbox0\hbox
+ {#1[##1]{\vrule\!!width\hsize\!!height3ex}}%
+ \wd0\zeropoint
+ \box0
+ \hbox to \hsize
+ {\def\colo_palets_compare####1%
+ {\hbox to \!!widtha
+ {\hss#1[####1]{\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}\hss}}%
+ \processcommacommand[\getvalue{\??colorpalet#2}]\colo_palets_compare}}
+ \endgraf}
+ \processcommacommand[\getvalue{\??colorpalet#2}]\colo_palets_compare}}
+
+%D Groups
-\gdef\showcolorgroup
- {\dodoubleargument\doshowcolorgroup}
+\unexpanded\gdef\showcolorgroup
+ {\dodoubleargument\colo_groups_show}
-\gdef\doshowcolorgroup[#1][#2]%
+\gdef\colo_groups_show[#1][#2]%
{\doifcolor{#1:1}
- {\doifinsetelse\v!vertical{#2}
- {\showverticalcolorgroup[#1][#2]}
- {\showhorizontalcolorgroup[#1][#2]}}}
-
-\gdef\showhorizontalcolorgroup[#1][#2]%
- {\localvbox
- {\offinterlineskip
+ {\doifinsetelse\v!vertical{#2} \colo_groups_show_vertical \colo_groups_show_horizontal [#1][#2]}}
+
+\gdef\colo_groups_show_horizontal[#1][#2]%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
\setuppalet
\tabskip\zeropoint
- \def\rule
- {\vrule\!!width4em\!!height\strutht\!!depth\strutdp}
\def\colorformatseparator{\strut\cr}
- \def\dodoshowgroup##1%
- {\halign
- {\hss####\hss\cr
- \doifinset\v!number{#2}{\strut##1}\cr
- \color[#1:##1]{\vrule\!!width4em\!!height\strutht\!!depth\zeropoint}\cr
- \graycolor[#1:##1]{\vrule\!!width4em\!!height\zeropoint\!!depth\strutdp}\cr
- \doifinset\v!value{#2}{\colorvalue{#1:##1}\strut}\crcr}}
- \def\doshowgroup##1%
- {\doifcolor{#1:##1}
- {\vbox{\dodoshowgroup{##1}}}}%
+ \def\colo_groups_show_group##1%
+ {\doifcolor{#1:##1}{\vbox
+ {\halign
+ {\hss####\hss\cr
+ \doifinset\v!number{#2}{\strut##1}\cr
+ \color[#1:##1]{\vrule\!!width4em\!!height\strutht\!!depth\zeropoint}\cr
+ \graycolor[#1:##1]{\vrule\!!width4em\!!height\zeropoint\!!depth\strutdp}\cr
+ \doifinset\v!value{#2}{\colorvalue{#1:##1}\strut}\crcr}}}}%
\hbox
{\doifinset\v!name{#2}
{\strut
@@ -128,130 +181,58 @@
{\raise3\lineheight\hbox{#1\hskip.5em}}
{#1}%
\hskip.5em}%
- \doshowgroup1\doshowgroup2\doshowgroup3\doshowgroup4%
- \doshowgroup5\doshowgroup6\doshowgroup7\doshowgroup8}}}
-
-\gdef\showverticalcolorgroup[#1][#2]%
- {\localvbox
- {\offinterlineskip
+ \colo_groups_show_group1\colo_groups_show_group2\colo_groups_show_group3\colo_groups_show_group4%
+ \colo_groups_show_group5\colo_groups_show_group6\colo_groups_show_group7\colo_groups_show_group8}}}
+
+\gdef\colo_groups_show_vertical[#1][#2]%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \offinterlineskip
\setuppalet
\tabskip\zeropoint
- \def\rule
- {\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}%
- \def\doshowgroup##1%
+ \def\colo_groups_show_group##1%
{\doifcolor{#1:##1}
{\doifinset\v!number{#2}{##1\hskip.5em}&
- \color[#1:##1]{\rule}\graycolor[#1:##1]{\rule}&
+ \color[#1:##1]{\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}%
+ \graycolor[#1:##1]{\vrule\!!width2.5em\!!height\strutht\!!depth\strutdp}&
\doifinset\v!value{#2}{\hskip.5em\colorvalue{#1:##1}}\crcr}}%
\halign
{\hss##&\hss##\hss&##\hss\cr
&\doifinset\v!name{#2}{\strut#1}&\crcr
- \doshowgroup1\doshowgroup2\doshowgroup3\doshowgroup4%
- \doshowgroup5\doshowgroup6\doshowgroup7\doshowgroup8}}}
+ \colo_groups_show_group1\colo_groups_show_group2\colo_groups_show_group3\colo_groups_show_group4%
+ \colo_groups_show_group5\colo_groups_show_group6\colo_groups_show_group7\colo_groups_show_group8}}}
-\gdef\showcolor
- {\dosingleempty\doshowcolor}
+\unexpanded\gdef\comparecolorgroup
+ {\dosingleargument\colo_groups_compare}
-\gdef\doshowcolor[#1]%
- {\bgroup
- \iffirstargument
- \let\colorlist\empty % not really used, only for colo-run
- \let\colorstyle\empty
- \settrue\collectcolorsinlist
- \setupcolor[#1]%
- \fi
- \def\rule
- {\vrule\!!width4em\!!height\strutht\!!depth\strutdp}%
- \def\docommand##1%
- {\NC\graycolor[##1]{\rule}\NC\color[##1]{\rule}\NC\grayvalue{##1}\NC\colorvalue{##1}\NC##1\NC\NR}%
- \starttabulate[|l|l|l|l|l|l|l|]
- \expanded{\globalprocesscommalist[\colorlist]}\docommand
- \stoptabulate
- \egroup}
-
-\gdef\comparepalet
- {\dosingleargument\docomparepalet}
-
-\gdef\docomparepalet[#1]%
- {\doifdefined{\??pa#1}
- {\hbox
- {\dodocomparepalet\color[#1]%
- \quad
- \dodocomparepalet\graycolor[#1]}}}
-
-\gdef\dodocomparepalet#1[#2]%
- {\localvbox
- {\offinterlineskip
- \setuppalet[#2]
- \getcommacommandsize[\getvalue{\??pa#2}]
- \!!widtha2em\relax
- \hsize\commalistsize\!!widtha
- \def\rule%
- {\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}
- \def\dododocomparepalet##1%
- {\hbox
- {\setbox0\hbox
- {#1[##1]{\vrule\!!width\hsize\!!height3ex}}%
- \wd0\zeropoint
- \box0
- \hbox to \hsize
- {\def\dododocomparepalet####1%
- {\hbox to \!!widtha
- {\hss#1[####1]{\rule}\hss}}%
- \processcommacommand[\getvalue{\??pa#2}]\dododocomparepalet}}
- \endgraf}
- \processcommacommand[\getvalue{\??pa#2}]\dododocomparepalet}}
-
-\gdef\comparecolorgroup
- {\dosingleargument\docomparecolorgroup}
-
-\gdef\docomparecolorgroup[#1]%
+\gdef\colo_groups_compare[#1]%
{\doifcolor{#1:1}
{\hbox
- {\dodocomparecolorgroup\color[#1]%
+ {\colo_groups_compare_indeed\color[#1]%
\quad
- \dodocomparecolorgroup\graycolor[#1]}}}
-
-\gdef\dodocomparecolorgroup#1[#2]%
- {\localvbox
- {\!!counta\zerocount
- \dorecurse{15}
- {\doifcolor{#2:\recurselevel}{\advance\!!counta\plusone}}
+ \colo_groups_compare_indeed\graycolor[#1]}}}
+
+\gdef\colo_groups_compare_indeed#1[#2]%
+ {\vbox
+ {\forgetall
+ \setlocalhsize
+ \hsize\localhsize
+ \!!counta\zerocount
+ \dorecurse{15}{\doifcolor{#2:\recurselevel}{\advance\!!counta\plusone}}
\!!widtha2em\relax
\hsize\!!counta\!!widtha
- \def\rule
- {\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}
- \def\dododocomparecolorgroup##1%
- {\hbox to \hsize
- {\setbox0\hbox
- {#1[#2:##1]{\vrule\!!width\hsize\!!height3ex}}%
- \wd0\zeropoint
- \box0
- \hbox to \hsize
- {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\rule}\hss}}}
- \endgraf}
- \dorecurse\!!counta{\dododocomparecolorgroup\recurselevel}}}
-
-\gdef\dogetcolorcomponents#1%
- {\doifelsenothing{#1}
- {\appendtoks
- \TB
- \to \scratchtoks}
- {\appendtoks
- \NC\showcolorbar[#1]\NC#1\NC\transparencycomponents{#1}\NC\colorcomponents{#1}\NC \NR
- \to \scratchtoks}}
-
-\gdef\showcolorbar[#1]%
- {\backgroundline[#1]{\strut\enspace\color[white]{white}\enspace\color[black]{black}\enspace}}
-
-\gdef\showcolorcomponents[#1]%
- {\begingroup
- \scratchtoks{\TB}%
- \processcommacommand[#1]\dogetcolorcomponents
- \starttabulate[|lT|lT|lT|lT|]
- \NC color \NC name \NC transparency \NC specification \NC\NR
- \the\scratchtoks
- \stoptabulate
- \endgroup}
+ \dorecurse\!!counta{\colo_groups_compare_step{#1}{#2}\recurselevel}}}
+
+\def\colo_groups_compare_step#1#2#3%
+ {\hbox to \hsize
+ {\setbox0\hbox
+ {#1[#2:#3]{\vrule\!!width\hsize\!!height3ex}}%
+ \wd0\zeropoint
+ \box0
+ \hbox to \hsize
+ {\hss\dorecurse\!!counta{#1[#2:\recurselevel]{\vrule\!!width.5\!!widtha\!!height2.25ex\!!depth-.75ex}\hss}}}
+ \endgraf}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/colo-xwi.mkii b/Master/texmf-dist/tex/context/base/colo-xwi.mkii
index 81e09d871bc..557e9c57c54 100644
--- a/Master/texmf-dist/tex/context/base/colo-xwi.mkii
+++ b/Master/texmf-dist/tex/context/base/colo-xwi.mkii
@@ -5,7 +5,7 @@
%D subtitle=X Windows,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-cs.mkii b/Master/texmf-dist/tex/context/base/cont-cs.mkii
index 714bf956869..89b781c37a1 100644
--- a/Master/texmf-dist/tex/context/base/cont-cs.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-cs.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Czech Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-cs.mkiv b/Master/texmf-dist/tex/context/base/cont-cs.mkiv
index e1805b1c9ee..75e30fe6985 100644
--- a/Master/texmf-dist/tex/context/base/cont-cs.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-cs.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Czech Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-de.mkii b/Master/texmf-dist/tex/context/base/cont-de.mkii
index a110f67d2a4..5badc59d00b 100644
--- a/Master/texmf-dist/tex/context/base/cont-de.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-de.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ German Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-de.mkiv b/Master/texmf-dist/tex/context/base/cont-de.mkiv
index 1f41797816c..998f76466da 100644
--- a/Master/texmf-dist/tex/context/base/cont-de.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-de.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ German Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-en.mkii b/Master/texmf-dist/tex/context/base/cont-en.mkii
index c3d510f981a..9d0d4de2e33 100644
--- a/Master/texmf-dist/tex/context/base/cont-en.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-en.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ English Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-en.mkiv b/Master/texmf-dist/tex/context/base/cont-en.mkiv
index 1bf182cd8d4..f25ab69cbd1 100644
--- a/Master/texmf-dist/tex/context/base/cont-en.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-en.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ English Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-err.mkii b/Master/texmf-dist/tex/context/base/cont-err.mkii
index f01ce87aadb..00118f6ccec 100644
--- a/Master/texmf-dist/tex/context/base/cont-err.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-err.mkii
@@ -5,7 +5,7 @@
%D subtitle=Just A warning,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-fil.mkii b/Master/texmf-dist/tex/context/base/cont-fil.mkii
index b295872ca0c..e05d8eac46d 100644
--- a/Master/texmf-dist/tex/context/base/cont-fil.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-fil.mkii
@@ -5,7 +5,7 @@
%D subtitle=File Synonyms,
%D author=J. Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -121,4 +121,7 @@
\definefilesynonym [mml] [mathml]
\definefilesynonym [cml] [chemml]
+\definefilesynonym [letter] [cor-01]
+\definefilesynonym [memo] [cor-02]
+
\endinput
diff --git a/Master/texmf-dist/tex/context/base/cont-fil.mkiv b/Master/texmf-dist/tex/context/base/cont-fil.mkiv
index 2468f299861..db7505bcbd3 100644
--- a/Master/texmf-dist/tex/context/base/cont-fil.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-fil.mkiv
@@ -5,12 +5,15 @@
%D subtitle=File Synonyms,
%D author=J. Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
+% todo: use full names and remove calls at the tex end (now integrated in
+% lua library code
+
\writestatus{loading}{ConTeXt File Synonyms}
\definefilesynonym [chemics] [chemic]
@@ -93,4 +96,8 @@
\definefilesynonym [mml] [mathml]
\definefilesynonym [cml] [chemml]
+\definefilesynonym [letter] [cor-01]
+\definefilesynonym [memo] [cor-02]
+\definefilesynonym [resume] [cor-03]
+
\endinput
diff --git a/Master/texmf-dist/tex/context/base/cont-fr.mkii b/Master/texmf-dist/tex/context/base/cont-fr.mkii
index 6f1e806ad0e..e70cfe65eec 100644
--- a/Master/texmf-dist/tex/context/base/cont-fr.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-fr.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ French Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-fr.mkiv b/Master/texmf-dist/tex/context/base/cont-fr.mkiv
index 5b0946625e8..f45ec88c3f7 100644
--- a/Master/texmf-dist/tex/context/base/cont-fr.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-fr.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ French Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-gb.mkii b/Master/texmf-dist/tex/context/base/cont-gb.mkii
index 35b7c85a4e5..5cd0a9635b0 100644
--- a/Master/texmf-dist/tex/context/base/cont-gb.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-gb.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ English Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-gb.mkiv b/Master/texmf-dist/tex/context/base/cont-gb.mkiv
index 3a4ed609bac..f6dd4ba9ebc 100644
--- a/Master/texmf-dist/tex/context/base/cont-gb.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-gb.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ English Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-it.mkii b/Master/texmf-dist/tex/context/base/cont-it.mkii
index c594a0659cc..f15171403b3 100644
--- a/Master/texmf-dist/tex/context/base/cont-it.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-it.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Italian Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-it.mkiv b/Master/texmf-dist/tex/context/base/cont-it.mkiv
index af7a1149e6f..483eb858955 100644
--- a/Master/texmf-dist/tex/context/base/cont-it.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-it.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Italian Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-log.mkii b/Master/texmf-dist/tex/context/base/cont-log.mkii
index c89a2dd8f57..6a7a707952d 100644
--- a/Master/texmf-dist/tex/context/base/cont-log.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-log.mkii
@@ -5,7 +5,7 @@
%D subtitle=\TEX\ Logos,
%D author=J. Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-log.mkiv b/Master/texmf-dist/tex/context/base/cont-log.mkiv
index 171949ba011..67647920dbc 100644
--- a/Master/texmf-dist/tex/context/base/cont-log.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-log.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\TEX\ Logos,
%D author=J. Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -20,25 +20,31 @@
\unprotect
-\def\Mkern#1%
- {{\setbox\scratchbox\hbox{M}\kern#1\wd\scratchbox}}
-
\unexpanded\def\TeX
- {T%
- \Mkern{-.1667}\lower.5ex\hbox{E}%
- \Mkern{-.125}X}
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{M}%
+ T%
+ \kern-.1667\wd\scratchbox
+ \lower.5ex\hbox{E}%
+ \kern-.125\wd\scratchbox
+ X%
+ \endgroup}
\unexpanded\def\ConTeXt{Con\TeX t}
\unexpanded\def\PPCHTeX{ppch\TeX}
\unexpanded\def\PRAGMA {Pragma ADE}
\unexpanded\def\LaTeX % requested by erik frambach
- {{\setbox\scratchbox\hbox{L}%
- \scratchdimen\ht\scratchbox
- \setbox\scratchbox\hbox{\txx A}%
- L\kern-.55\wd\scratchbox
- \raise\scratchdimen\hbox{\lower\ht\scratchbox\copy\scratchbox}%
- \kern-.2\wd\scratchbox\TeX}}
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{L}%
+ \scratchdimen\ht\scratchbox
+ \setbox\scratchbox\hbox{\txx A}%
+ L\kern-.55\wd\scratchbox
+ \raise\scratchdimen\hbox{\lower\ht\scratchbox\copy\scratchbox}%
+ \kern-.2\wd\scratchbox\TeX
+ \endgroup}
\unexpanded\def\TaBlE
{T%
@@ -53,25 +59,27 @@
\kern-.075em C%
\kern-.11em\TeX}
-\def\AMSswitch#1%
+\def\syst_logos_ams_script#1%
{$\cal\ifdim\bodyfontsize>1.1em\scriptstyle\fi#1$}
\unexpanded\def\AmSTeX
- {\AMSswitch A%
- \kern-.1667em\lower.5ex\hbox{\AMSswitch M}%
- \kern-.125em\AMSswitch S%
+ {\dontleavehmode
+ \syst_logos_ams_script A%
+ \kern-.1667em\lower.5ex\hbox{\syst_logos_ams_script M}%
+ \kern-.125em\syst_logos_ams_script S%
-\TeX}
\unexpanded\def\LamSTeX
{L%
- \kern-.4em\raise.3ex\hbox{\AMSswitch A}%
- \kern-.25em\lower.4ex\hbox{\AMSswitch M}%
- \kern-.1em{\AMSswitch S}%
+ \kern-.4em\raise.3ex\hbox{\syst_logos_ams_script A}%
+ \kern-.25em\lower.4ex\hbox{\syst_logos_ams_script M}%
+ \kern-.1em{\syst_logos_ams_script S}%
-\TeX}
\unexpanded\def\AmSLaTeX
- {\AMSswitch A%
- \kern-.1667em\lower.5ex\hbox{\AMSswitch M}%
+ {\dontleavehmode
+ \syst_logos_ams_script A%
+ \kern-.1667em\lower.5ex\hbox{\syst_logos_ams_script M}%
\kern-.125em\AMSswitch S%
-\LaTeX}
@@ -83,37 +91,46 @@
%D
%D I changed this into one that adapts itself:
-\unexpanded\def\Context
- {{C\kern -.0667em\getscaledglyph{.8}\empty{O\kern -.0667emN\kern
+\unexpanded\def\Context % wrong usage of \getscaledglyph
+ {\dontleavehmode
+ \begingroup
+ C\kern -.0667em\getscaledglyph{.8}\empty{O\kern -.0667emN\kern
-.0549emT\doifitalicelse{\kern-.1em}{\kern-.1667em}\lower.5ex\hbox
- {E}\doifitalicelse\empty{\kern-.11em}X\kern-.055emT}}}
+ {E}\doifitalicelse\empty{\kern-.11em}X\kern-.055emT}%
+ \endgroup}
%D The \METAFONT\ and \METAPOST\ logos adapt themselves to the
%D current fontsize, an ugly but usefull hack.
\let\logofont\nullfont
-\loadmapfile[original-base.map]
+\loadmapfile[original-base.map] % stil needed?
\unexpanded\def\setMFPfont% more sensitive for low level changes
{\font\logofont=logo%
- \ifx\fontalternative\c!bf\else
- \ifx\fontalternative\c!it\else
- \ifx\fontalternative\c!sl\else
- \ifx\fontalternative\c!bi\else
- \ifx\fontalternative\c!bs\else
+ \ifx\fontalternative\s!bf\else
+ \ifx\fontalternative\s!it\else
+ \ifx\fontalternative\s!sl\else
+ \ifx\fontalternative\s!bi\else
+ \ifx\fontalternative\s!bs\else
\fi\fi\fi\fi\fi
- 10 at \currentfontscale\bodyfontsize
+ 10 at \currentfontscale\bodyfontsize % there is no afm in the minimals yet
\logofont}
-\def\MetaHyphen% there is no hyphenchar in this font
+\def\syst_logos_meta_hyphen % there is no hyphenchar in this font
{\discretionary{\vrule\!!height.33em\!!depth-.27em\!!width.33em}{}{}}
\unexpanded\def\MetaFont
- {{\setMFPfont META\MetaHyphen FONT}}
+ {\dontleavehmode
+ \begingroup
+ \setMFPfont META\syst_logos_meta_hyphen FONT%
+ \endgroup}
\unexpanded\def\MetaPost
- {{\setMFPfont META\MetaHyphen POST}}
+ {\dontleavehmode
+ \begingroup
+ \setMFPfont META\syst_logos_meta_hyphen POST%
+ \endgroup}
\unexpanded\def\MetaFun
{MetaFun}
@@ -158,7 +175,7 @@
% Adapted from a patch by Mojca:
-\def\@XeTeX@
+\def\syst_logos_xetex_e
{\setbox\scratchbox\hbox{E}%
\raise\dimexpr\ht\scratchbox+\dp\scratchbox\relax\hbox{\rotate[\c!rotation=180]{\box\scratchbox}}}
@@ -169,14 +186,14 @@
\iffontchar\font"018E\relax
\char"018E%
\else
- \ifx\fontalternative\c!bf\mirror{E}\else
- \ifx\fontalternative\c!it \@XeTeX@\else
- \ifx\fontalternative\c!sl \@XeTeX@\else
- \ifx\fontalternative\c!bi \@XeTeX@\else
- \ifx\fontalternative\c!bs \@XeTeX@\else
- \mirror{E}\fi\fi\fi\fi\fi
+ \ifx\fontalternative\s!bf \mirror{E}\else
+ \ifx\fontalternative\s!it\syst_logos_xetex_e\else
+ \ifx\fontalternative\s!sl\syst_logos_xetex_e\else
+ \ifx\fontalternative\s!bi\syst_logos_xetex_e\else
+ \ifx\fontalternative\s!bs\syst_logos_xetex_e\else
+ \mirror{E}\fi\fi\fi\fi\fi
\fi}%
- \kern-.1667em \TeX}
+ \kern-.1667em\TeX}
\let\ETEX \eTeX
\let\PDFTEX \pdfTeX
@@ -185,19 +202,19 @@
\let\LuaTeX \luaTeX
\let\XETEX \XeTeX
-\unexpanded\def\MkApproved % joke, not used so it might move
- {\dontleavehmode\rotate
- [\c!rotation={\ifnum\texengine=\luatexengine\ctxlua{tex.write(45-45*\the\luatexversion/100)}\else0\fi},
- \c!align=\v!middle,
- \c!foregroundstyle=\v!type,
- \c!foregroundcolor=darkred,
- \c!frame=\v!on,
- \c!offset=1ex,
- \c!background=\v!color,
- \c!backgroundcolor=lightgray,
- \c!framecolor=darkred,
- \c!rulethickness=2pt]
- {Mk\ifnum\texengine=\luatexengine IV\else II\fi\\approved}}
+% \unexpanded\def\MkApproved % joke, not used so it might move
+% {\dontleavehmode\rotate
+% [\c!rotation={\ifnum\texengine=\luatexengine\cldcontext{45-45*\the\luatexversion/100}\else0\fi},
+% \c!align=\v!middle,
+% \c!foregroundstyle=\v!type,
+% \c!foregroundcolor=darkred,
+% \c!frame=\v!on,
+% \c!offset=1ex,
+% \c!background=\v!color,
+% \c!backgroundcolor=lightgray,
+% \c!framecolor=darkred,
+% \c!rulethickness=2pt]
+% {Mk\ifnum\texengine=\luatexengine IV\else II\fi\\approved}}
% \unexpanded\def\luaTeX
% {\dontleavehmode\begingroup
@@ -214,10 +231,10 @@
%
% a further iteration from the list, patched again
-% \ifx\fontalternative\c!it -\else
-% \ifx\fontalternative\c!sl -\else
-% \ifx\fontalternative\c!bi -\else
-% \ifx\fontalternative\c!bs -\fi\fi\fi\fi
+% \ifx\fontalternative\s!it -\else
+% \ifx\fontalternative\s!sl -\else
+% \ifx\fontalternative\s!bi -\else
+% \ifx\fontalternative\s!bs -\fi\fi\fi\fi
\unexpanded\def\LuaTeX
{\dontleavehmode
@@ -250,4 +267,7 @@
\unexpanded\def\MKIV{MkIV}
\unexpanded\def\MKVI{MkVI}
+\unexpanded\def\MPII{MpII}
+\unexpanded\def\MPIV{MpIV}
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/cont-new.mkii b/Master/texmf-dist/tex/context/base/cont-new.mkii
index 1a81454d6c9..400df7282f6 100644
--- a/Master/texmf-dist/tex/context/base/cont-new.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-new.mkii
@@ -5,13 +5,13 @@
%D subtitle=New Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
-\newcontextversion{2011.05.18 18:04}
+\newcontextversion{2012.05.14 16:00}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
diff --git a/Master/texmf-dist/tex/context/base/cont-new.mkiv b/Master/texmf-dist/tex/context/base/cont-new.mkiv
index 3bda269efef..772d5780a70 100644
--- a/Master/texmf-dist/tex/context/base/cont-new.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-new.mkiv
@@ -5,13 +5,13 @@
%D subtitle=New Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
-\newcontextversion{2011.05.18 18:04}
+\newcontextversion{2012.05.14 16:00}
%D This file is loaded at runtime, thereby providing an
%D excellent place for hacks, patches, extensions and new
@@ -21,43 +21,6 @@
\writestatus\m!system{beware: some patches loaded from cont-new.mkiv}
-
-\def\fastscale#1%
- {\begingroup
- \ifnum#1=1000\relax
- \setfalse\scaleboxdone
- \else
- \settrue\scaleboxdone
- \edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1pt/1000\relax}%
- \let\finalscaleboxyscale\finalscaleboxxscale
- \fi
- \dowithnextbox{\doscaleboxindeed\flushnextbox\endgroup}\hbox}
-
-% \setupcaption [figure] [align=flushleft]
-% \setupcaption [figure-1] [align=flushleft,leftmargin=10mm]
-% \setupcaption [figure-2] [align=flushleft,leftmargin=10mm,rightmargin=-10mm,width=\textwidth]
-%
-% \startsetups somefigure
-% \ifdim\floatsetupwidth>\textwidth
-% \placesetupfloat[figure-2]
-% \else
-% \placesetupfloat[figure-1]
-% \fi
-% \stopsetups
-%
-% \placefloatwithsetups[somefigure]{}{\externalfigure[dummy][width=5cm,height=2cm]}
-
-\def\placefloatwithsetups
- {\dotripleempty\doplacefloatwithsetups}
-
-\long\def\doplacefloatwithsetups[#1][#2][#3]#4%
- {\def\floatsetupcaption {#4}%
- \def\floatsetupcontent {\copy\nextbox}%
- \def\floatsetupwidth {\wd\nextbox}%
- \def\floatsetupheight {\ht\nextbox}%
- \def\placesetupfloat[##1]{\placefloat[##1][#2][#3]{#4}{\floatsetupcontent}}% #4 and not \floatsetupcaption (unexpanded)
- \dowithnextbox{\setups[#1]}\vbox}
-
\def\dividedsize#1#2#3% size gap n
{\dimexpr
\ifnum\dimexpr#1\relax>\plusone
@@ -70,6 +33,8 @@
\definecomplexorsimple\widened
+\let\active\activecatcode % for a while (tikz)
+
% todo
%
% \def\definelocation{\dodoubleargument\dodefinelocation}
@@ -230,10 +195,12 @@
\setuplabeltext
[placeholder={, moved}]
+% move to support module, and then use context(...)
+
\startluacode
function commands.percentageof(str,dim)
local n = str:match("^(.*)%%$")
- tex.sprint(tex.ctxcatcodes,(n and (tonumber(n)/100)*dim .. "sp") or str)
+ context.sprint(tex.ctxcatcodes,(n and (tonumber(n)/100)*dim .. "sp") or str)
end
\stopluacode
@@ -361,8 +328,6 @@
% \the\dimexpr(\dimchoice{11pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
% \the\dimexpr(\dimchoice{14pt}{{<10pt}{8pt}{<12pt}{9pt}{<15pt}{10pt}{=11pt}{12pt}})
-\def\showsetupsdefinition[#1]{\showvalue{\??su:#1}} % temp hack for debugging
-
\def\tabulaterule % to be redone, not correct
{\dotabulaterule
{\hrule\!!height.5\scratchdimen\!!depth.5\scratchdimen\relax
@@ -428,8 +393,7 @@
\def\dostartgridcorrection[#1]%
{\ifgridsnapping
- \iffirstargument\doifsomething{#1}{\moveongrid[#1]}\fi
- \snaptogrid\vbox\bgroup
+ \snaptogrid[#1]\vbox\bgroup
\else
\startbaselinecorrection
\fi}
@@ -463,32 +427,6 @@
% \startplaatsen[links] bla \stopplaatsen
-% we don't register the paragraph characteristics, only the
-% width
-
-\appendtoks
- \setinnerparpositions % see "techniek" for application
-\to \everytabulate
-
-\def\fontclassname#1#2%
- {\ifcsname\??ff#1#2\endcsname
- \fontclassname{#1}{\csname\??ff#1#2\endcsname}%
- \else\ifcsname\??ff#2\endcsname
- \fontclassname{#1}{\csname\??ff#2\endcsname}%
- \else
- #2%
- \fi\fi}
-
-\def\defineclassfontsynonym
- {\dotripleargument\dodefineclassfontsynonym}
-
-\def\dodefineclassfontsynonym[#1][#2][#3]%
- {\definefontsynonym[#1][\fontclassname{#2}{#3}]}
-
-%\definefontsynonym [KopFont] [\fontclassname{officina}{SerifBold}]
-%
-%\defineclassfontsynonym [KopFont] [officina] [SerifBold]
-
\def\startcolumnmakeup % don't change
{\bgroup
\getrawnoflines\textheight % teksthoogte kan topskip hebben, dus raw
@@ -505,7 +443,7 @@
\wd\scratchbox\textwidth
\box\scratchbox
\egroup
- \synchronizehsize}
+ \page_otr_command_synchronize_hsize}
\long\def\startexternalfigure
{\dotripleempty\dostartexternalfigure}
diff --git a/Master/texmf-dist/tex/context/base/cont-nl.mkii b/Master/texmf-dist/tex/context/base/cont-nl.mkii
index 925ec899958..f9cefaaac06 100644
--- a/Master/texmf-dist/tex/context/base/cont-nl.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-nl.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Dutch Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-nl.mkiv b/Master/texmf-dist/tex/context/base/cont-nl.mkiv
index f6d2671e3fb..890ad8ca594 100644
--- a/Master/texmf-dist/tex/context/base/cont-nl.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-nl.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Dutch Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-pe.mkiv b/Master/texmf-dist/tex/context/base/cont-pe.mkiv
index e65ad132811..4f7efe959d5 100644
--- a/Master/texmf-dist/tex/context/base/cont-pe.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-pe.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ English Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-ro.mkii b/Master/texmf-dist/tex/context/base/cont-ro.mkii
index 59561319457..d68cf5a4558 100644
--- a/Master/texmf-dist/tex/context/base/cont-ro.mkii
+++ b/Master/texmf-dist/tex/context/base/cont-ro.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Romanian Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/cont-ro.mkiv b/Master/texmf-dist/tex/context/base/cont-ro.mkiv
index 90bbc27dce9..ac6f159f539 100644
--- a/Master/texmf-dist/tex/context/base/cont-ro.mkiv
+++ b/Master/texmf-dist/tex/context/base/cont-ro.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Romanian Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/context-base.lmx b/Master/texmf-dist/tex/context/base/context-base.lmx
index fd27927bf82..09817463b94 100644
--- a/Master/texmf-dist/tex/context/base/context-base.lmx
+++ b/Master/texmf-dist/tex/context/base/context-base.lmx
@@ -24,6 +24,13 @@
<link rel="StyleSheet" href="<?lua p(v) ?>" type="text/css" />
<?lua end end ?>
</head>
+ <?lua if (v('refreshtime') and (tonumber(v('refreshtime')) or 0) > 0) and v('refreshurl') then ?>
+ <!--[if IE]>
+ <script type="text/javascript">
+ setTimeout("document.location='<?lua pv('refreshurl') ?>'", 1000*<?lua pv('refreshtime') ?>);
+ </script>
+ <![endif]-->
+ <?lua end ?>
<?lua if v('action') then ?>
<form action="<?lua pv(action) ?>" enctype="multi-part/form-data" method="post">
<?lua end ?>
diff --git a/Master/texmf-dist/tex/context/base/context-version.pdf b/Master/texmf-dist/tex/context/base/context-version.pdf
new file mode 100644
index 00000000000..69902446d12
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/context-version.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/context/base/context-version.png b/Master/texmf-dist/tex/context/base/context-version.png
new file mode 100644
index 00000000000..044c6d7825d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/context-version.png
Binary files differ
diff --git a/Master/texmf-dist/tex/context/base/context.css b/Master/texmf-dist/tex/context/base/context.css
index f332ae242d6..be1dad79610 100644
--- a/Master/texmf-dist/tex/context/base/context.css
+++ b/Master/texmf-dist/tex/context/base/context.css
@@ -18,6 +18,26 @@ a.dir-view:link, a.dir-view:active, a.dir-view:visited {
.invalid {
color: #FF0000 ;
}
+button, .commonlink, .smallbutton {
+ font-weight: bold ;
+ font-size: 12px ;
+ text-decoration: none ;
+ color: #000000 ;
+ border-color: #7F7F7F ;
+ border-style: solid ;
+ border-width: .125ex ;
+ background-color: #FFFFFF ;
+ padding: .5ex ;
+}
+.smallbutton {
+ width: 1em ;
+}
+a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited {
+ font-weight: bold ;
+ font-size: 12px ;
+ text-decoration: none ;
+ color: #000000 ;
+}
h1, .title {
font-style: normal ;
font-weight: normal ;
@@ -110,7 +130,7 @@ p, li {
font-size: 16px ;
border-style: none ;
border-width: 0 ;
- background-color: <?lua pv('color-background-one')?> ;
+ background-color: <?lua pv('color-background-three')?> ;
_margin-left: -15px ;
}
#bottom {
@@ -143,7 +163,7 @@ p, li {
font-size: 16px ;
border-style: none ;
border-width: 0 ;
- background-color: <?lua pv('color-background-two')?> ;
+ background-color: <?lua pv('color-background-four')?> ;
}
#top-one {
position: absolute ;
@@ -235,7 +255,7 @@ p, li {
text-align: center ;
}
#right-safari {
- display: table ;
+ _display: table ;
width: 100% ;
height: 100% ;
}
diff --git a/Master/texmf-dist/tex/context/base/context.mkii b/Master/texmf-dist/tex/context/base/context.mkii
index 7312bdcf562..5ab89d934e0 100644
--- a/Master/texmf-dist/tex/context/base/context.mkii
+++ b/Master/texmf-dist/tex/context/base/context.mkii
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2011.05.18 18:04}
+\edef\contextversion{2012.05.14 16:00}
%D For those who want to use this:
diff --git a/Master/texmf-dist/tex/context/base/context.mkiv b/Master/texmf-dist/tex/context/base/context.mkiv
index 8f3586dea98..fcbe7872c35 100644
--- a/Master/texmf-dist/tex/context/base/context.mkiv
+++ b/Master/texmf-dist/tex/context/base/context.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,8 +19,11 @@
%D 2004.8.30 the low level interface is english. Watch out and adapt
%D your styles an modules.
+%D The order of loading will change when all modules have been cleaned
+%D up and the dependencies are more consistent.
+
\edef\contextformat {\jobname}
-\edef\contextversion{2011.05.18 18:04}
+\edef\contextversion{2012.05.14 16:00}
%D For those who want to use this:
@@ -54,8 +57,8 @@
%D We just quit if new functionality is expected.
-\ifnum\luatexversion<60 % also change message
- \writestatus{!!!!}{Your luatex binary is too old, you need at least version 0.60!}
+\ifnum\luatexversion<70 % also change message
+ \writestatus{!!!!}{Your luatex binary is too old, you need at least version 0.70!}
\expandafter\end
\fi
@@ -64,7 +67,7 @@
\newtoks\contextversiontoks \contextversiontoks\expandafter{\contextversion}
-%D Now the more fundamnetal code gets defined.
+%D Now the more fundamental code gets defined.
\loadmarkfile{norm-ctx}
\loadmarkfile{syst-pln}
@@ -92,7 +95,10 @@
\loadmarkfile{syst-fnt}
\loadmarkfile{syst-rtp}
-\loadmarkfile{supp-fil}
+\loadmkvifile{file-ini}
+\loadmkvifile{file-res}
+\loadmkvifile{file-lib}
+
\loadmarkfile{supp-dir}
\loadmarkfile{char-ini}
@@ -100,11 +106,11 @@
\loadmarkfile{char-act}
\loadmarkfile{mult-ini}
-%loadmarkfile{mult-fst} % obsolete
\loadmarkfile{mult-sys}
\loadmarkfile{mult-def}
\loadmarkfile{mult-chk}
\loadmarkfile{mult-aux}
+\loadmkvifile{mult-dim}
\loadmarkfile{cldf-int} % interface
@@ -120,6 +126,9 @@
\loadmarkfile{layo-ini}
\loadmarkfile{node-ini}
+
+\loadmarkfile{cldf-bas} % basics / depends on nodes
+
\loadmarkfile{node-fin}
\loadmarkfile{node-mig}
\loadmarkfile{node-par}
@@ -140,17 +149,20 @@
\loadmarkfile{supp-box}
\loadmarkfile{supp-vis}
-\loadmarkfile{supp-fun}
+\loadmarkfile{supp-fun} % close to obsolete
\loadmarkfile{supp-ran}
\loadmarkfile{supp-mat}
\loadmarkfile{supp-ali}
-\loadmarkfile{supp-num}
+\loadmarkfile{supp-num} % replaced
\loadmarkfile{typo-ini}
\loadmarkfile{page-ins}
-\loadmarkfile{core-fil}
+
+\loadmkvifile{file-syn}
+\loadmkvifile{file-mod}
+
\loadmarkfile{core-con}
\loadmarkfile{cont-fil}
@@ -164,11 +176,12 @@
\loadmarkfile{unic-ini}
-\loadmarkfile{core-gen}
\loadmarkfile{core-uti}
\loadmarkfile{core-two}
+\loadmarkfile{core-dat}
\loadmarkfile{colo-ini}
+\loadmarkfile{colo-grp} % optional
\loadmarkfile{colo-ext}
\loadmarkfile{node-bck} % overloads anch-pgr (experimental and undocumented)
@@ -180,39 +193,46 @@
\loadmarkfile{lang-def}
\loadmarkfile{lang-wrd} % can be optional
+\loadmkvifile{file-job} % why so late?
+
\loadmarkfile{symb-ini}
\loadmarkfile{sort-ini}
\loadmkvifile{pack-mis}
\loadmarkfile{pack-rul}
+\loadmarkfile{pack-mrl}
+\loadmkvifile{pack-bck}
+\loadmarkfile{pack-fen}
\loadmarkfile{lxml-ini}
\loadmarkfile{lxml-sor}
-\loadmarkfile{strc-ini}
+\loadmkvifile{typo-prc}
+
+\loadmkvifile{strc-ini}
\loadmarkfile{strc-tag}
\loadmarkfile{strc-doc}
\loadmarkfile{strc-num}
\loadmarkfile{strc-mar}
-\loadmarkfile{strc-prc}
\loadmarkfile{strc-sbe}
-\loadmarkfile{strc-lst}
+\loadmkvifile{strc-lst}
\loadmarkfile{strc-sec}
\loadmarkfile{strc-pag} % hm, depends on core-num
\loadmarkfile{strc-ren}
\loadmarkfile{strc-xml}
\loadmarkfile{strc-def} % might happen later
-\loadmarkfile{strc-ref}
+\loadmkvifile{strc-ref}
\loadmarkfile{strc-reg}
-\loadmarkfile{strc-lev} % experiment
+\loadmkvifile{strc-lev} % experiment
+\loadmarkfile{spac-ali}
\loadmarkfile{spac-hor}
\loadmarkfile{spac-ver}
-\loadmarkfile{spac-ali}
+\loadmarkfile{spac-lin}
\loadmarkfile{spac-pag}
-\loadmarkfile{spac-fnt}
\loadmarkfile{spac-par}
+%loadmarkfile{spac-adj} % no longer needed
\loadmarkfile{spac-def}
\loadmarkfile{spac-grd}
@@ -223,37 +243,50 @@
\loadmarkfile{pack-obj}
-\loadmarkfile{strc-itm}
-\loadmarkfile{strc-des}
+\loadmkvifile{strc-itm}
+
+\loadmkvifile{strc-con}
+\loadmkvifile{strc-des}
+\loadmkvifile{strc-enu}
+
+\loadmarkfile{strc-ind}
+\loadmarkfile{strc-lab}
\loadmarkfile{strc-syn}
\loadmarkfile{core-sys}
+\loadmarkfile{page-var}
+\loadmkvifile{page-otr}
\loadmarkfile{page-ini}
+\loadmarkfile{page-fac}
+\loadmarkfile{page-brk}
+\loadmarkfile{page-col}
+\loadmarkfile{page-inf}
+\loadmarkfile{page-grd}
\loadmarkfile{page-flt}
\loadmarkfile{page-bck}
\loadmarkfile{page-not}
\loadmarkfile{page-one}
\loadmarkfile{page-lay}
-\loadmarkfile{page-txt}
-\loadmarkfile{page-sid}
+\loadmkvifile{page-box}
+\loadmkvifile{page-txt}
+\loadmarkfile{page-sid} % when
-\loadmarkfile{strc-flt}
+\loadmkvifile{strc-flt}
\loadmarkfile{page-mis}
+\loadmkvifile{page-mbk}
\loadmarkfile{page-mul}
\loadmarkfile{page-set}
\loadmarkfile{pack-lyr}
\loadmarkfile{pack-pos}
-\loadmarkfile{page-mak}
+\loadmkvifile{page-mak}
\loadmarkfile{page-lin}
\loadmarkfile{page-par}
-%loadmarkfile{page-mar} % also commented code in anch-pgr.mkiv
+\loadmarkfile{typo-pag}
\loadmarkfile{typo-mar}
-\loadmarkfile{core-job} % why so late?
-
\loadmarkfile{buff-ini}
\loadmarkfile{buff-ver}
\loadmarkfile{buff-par}
@@ -289,35 +322,53 @@
\loadmarkfile{tabl-nte}
\loadmarkfile{tabl-ltb}
\loadmarkfile{tabl-tsp}
+\loadmkvifile{tabl-xtb}
\loadmarkfile{java-ini}
\loadmkvifile{scrn-fld}
\loadmkvifile{scrn-hlp}
-\loadmarkfile{char-enc}
-\loadmarkfile{font-ini}
+\loadmarkfile{char-enc} % will move up
+
+\loadmkvifile{font-lib}
+\loadmkvifile{font-fil}
+\loadmkvifile{font-var}
+\loadmkvifile{font-fea}
+\loadmkvifile{font-mat}
+\loadmkvifile{font-ini}
+\loadmkvifile{font-sym}
+\loadmkvifile{font-sty}
+\loadmkvifile{font-set}
+
+\loadmkvifile{font-emp}
+\loadmarkfile{font-pre}
\loadmarkfile{font-unk}
\loadmarkfile{font-tra}
\loadmarkfile{font-uni}
-\loadmarkfile{font-col}
+\loadmkvifile{font-col}
\loadmarkfile{font-gds}
+\loadmarkfile{lxml-css}
+
+\loadmarkfile{spac-chr} % depends on fonts
+
\loadmarkfile{blob-ini} % not to be used, we only use a helper
\loadmarkfile{typo-cln}
\loadmarkfile{typo-spa}
\loadmarkfile{typo-krn}
+\loadmkvifile{typo-itc}
\loadmarkfile{typo-dir}
\loadmarkfile{typo-brk}
\loadmarkfile{typo-cap}
\loadmarkfile{typo-dig}
\loadmarkfile{typo-rep}
+\loadmkvifile{typo-txt}
+\loadmarkfile{typo-par}
-\loadmarkfile{type-ini}
+\loadmkvifile{type-ini}
\loadmarkfile{type-set}
-\loadmarkfile{type-def}
-\loadmarkfile{type-lua}
\loadmarkfile{scrp-ini}
@@ -330,14 +381,18 @@
\loadmarkfile{meta-fun}
\loadmarkfile{meta-pag}
+\loadmarkfile{page-mrk} % depends on mp
+
\loadmarkfile{page-flw}
\loadmarkfile{page-spr}
\loadmarkfile{page-plg}
\loadmarkfile{page-str}
-\loadmarkfile{anch-pgr} % overloads tabl-tbl
+\loadmarkfile{anch-pgr} % can be moved up (nicer for dependencies)
+\loadmkvifile{anch-bck}
+\loadmarkfile{anch-tab} % overloads tabl-tbl
\loadmarkfile{anch-bar}
-\loadmarkfile{anch-snc}
+%loadmarkfile{anch-snc} % when needed this one will be redone
\loadmarkfile{math-ini}
\loadmarkfile{math-pln}
@@ -351,21 +406,27 @@
\loadmarkfile{math-del}
\loadmarkfile{math-inl}
\loadmarkfile{math-dis}
-\loadmarkfile{math-lan}
+%loadmarkfile{math-lan}
+
+\loadmarkfile{phys-dim}
\loadmarkfile{strc-mat}
\loadmarkfile{chem-ini}
\loadmarkfile{chem-str}
+\loadmarkfile{typo-scr}
+
\loadmarkfile{core-fnt}
\loadmarkfile{node-rul}
\loadmarkfile{node-spl}
-\loadmarkfile{strc-not}
-\loadmarkfile{strc-lnt}
+\loadmkvifile{strc-not}
+\loadmkvifile{strc-lnt}
\loadmarkfile{core-mis}
+\loadmarkfile{pack-com}
+\loadmarkfile{typo-del}
\loadmarkfile{grph-trf}
\loadmarkfile{grph-inc}
@@ -407,8 +468,8 @@
\loadmarkfile{back-pdf} % actually, this one should load the next three
\loadmarkfile{mlib-pdf}
\loadmarkfile{mlib-pps}
-\loadmarkfile{grph-epd}
\loadmarkfile{meta-pdf}
+\loadmarkfile{grph-epd}
\loadmarkfile{back-exp}
@@ -426,4 +487,6 @@
\ctxlua{statistics.savefmtstatus("\jobname","\contextversion","context.mkiv")}% can become automatic
\to \everydump
+% \tracingall
+
\errorstopmode \dump \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-con.lua b/Master/texmf-dist/tex/context/base/core-con.lua
index e8ef52d4bf8..e4b516e3b43 100644
--- a/Master/texmf-dist/tex/context/base/core-con.lua
+++ b/Master/texmf-dist/tex/context/base/core-con.lua
@@ -61,11 +61,16 @@ local counters = allocate {
0x0074, 0x0075, 0x0076, 0x007A, 0x017E
},
['greek'] = { -- this should be the lowercase table
- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
- 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
- 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
- 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
- 0x03A6, 0x03A7, 0x03A8, 0x03A9
+ -- 0x0391, 0x0392, 0x0393, 0x0394, 0x0395,
+ -- 0x0396, 0x0397, 0x0398, 0x0399, 0x039A,
+ -- 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
+ -- 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5,
+ -- 0x03A6, 0x03A7, 0x03A8, 0x03A9
+ 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5,
+ 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA,
+ 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
+ 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5,
+ 0x03C6, 0x03C7, 0x03C8, 0x03C9,
},
['arabic'] = {
0x0627, 0x0628, 0x062C, 0x062F, 0x0647,
@@ -298,7 +303,7 @@ local function toroman(n)
if n >= 4000 then
return toroman(floor(n/1000)) .. " " .. toroman(n%1000)
else
- return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] .. roman[2][floor((n%100)/10)] .. roman[1][floor((n% 10)/1)]
+ return rep("M",floor(n/1000)) .. roman[3][floor((n%1000)/100)] .. roman[2][floor((n%100)/10)] .. roman[1][floor((n%10)/1)]
end
end
@@ -705,7 +710,7 @@ end
local ordinals = {
english = function(n)
local two = n % 100
- if two == 11 or two == 12 or to == 13 then
+ if two == 11 or two == 12 or two == 13 then
return "th"
else
local one = n % 10
@@ -742,6 +747,7 @@ end
function commands.ordinal(n,language)
local t = language and ordinals[language]
local o = t and t(n)
+ context(n)
if o then
context.highordinalstr(o)
end
@@ -758,29 +764,29 @@ local v_space = variables.space
local convert = converters.convert
-local days = {
- variables.sunday,
- variables.monday,
- variables.tuesday,
- variables.wednesday,
- variables.thursday,
- variables.friday,
- variables.saturday,
+local days = { -- not variables.sunday
+ "sunday",
+ "monday",
+ "tuesday",
+ "wednesday",
+ "thursday",
+ "friday",
+ "saturday",
}
-local months = {
- variables.january,
- variables.february,
- variables.march,
- variables.april,
- variables.may,
- variables.june,
- variables.july,
- variables.august,
- variables.september,
- variables.october,
- variables.november,
- variables.december,
+local months = { -- not variables.januari
+ "january",
+ "february",
+ "march",
+ "april",
+ "may",
+ "june",
+ "july",
+ "august",
+ "september",
+ "october",
+ "november",
+ "december",
}
function commands.dayname(n)
@@ -802,16 +808,16 @@ end
-- a prelude to a function that we can use at the lua end
--- historic : day+ month:mnem
--- maybe better: day:ord month:mmem
+-- day:ord month:mmem
+-- j and jj obsolete
-function commands.currentdate(str,currentlanguage) -- j and jj obsolete
+function commands.currentdate(str,currentlanguage) -- second argument false : no label
local list = utilities.parsers.settings_to_array(str)
local year, month, day = tex.year, tex.month, tex.day
local auto = true
for i=1,#list do
local entry = list[i]
- local tag, plus = match(entry,"^([^%+:]+)(.*)$")
+ local tag, plus = languages.labels.split(entry)
local ordinal, mnemonic, whatordinal = false, false, nil
if not tag then
tag = entry
@@ -831,7 +837,9 @@ function commands.currentdate(str,currentlanguage) -- j and jj obsolete
elseif tag == "Y" then
context(year)
elseif tag == v_month or tag == "m" then
- if mnemonic then
+ if currentlanguage == false then
+ context(months[month] or "unknown")
+ elseif mnemonic then
commands.monthmnem(month)
else
commands.monthname(month)
@@ -841,7 +849,11 @@ function commands.currentdate(str,currentlanguage) -- j and jj obsolete
elseif tag == "M" then
context(month)
elseif tag == v_day or tag == "d" then
- context.convertnumber(v_day,day)
+ if currentlanguage == false then
+ context(days[day] or "unknown")
+ else
+ context.convertnumber(v_day,day)
+ end
whatordinal = day
elseif tag == "dd" then
context("%02i",day)
@@ -850,7 +862,12 @@ function commands.currentdate(str,currentlanguage) -- j and jj obsolete
context(day)
whatordinal = day
elseif tag == v_weekday or tag == "w" then
- commands.dayname(weekday(day,month,year))
+ local wd = weekday(day,month,year)
+ if currentlanguage == false then
+ context(days[wd] or "unknown")
+ else
+ commands.dayname(wd)
+ end
elseif tag == "W" then
context(weekday(day,month,year))
elseif tag == v_referral then
@@ -863,7 +880,15 @@ function commands.currentdate(str,currentlanguage) -- j and jj obsolete
auto = true
end
if ordinal and whatordinal then
- commands.ordinal(whatordinal,currentlanguage)
+ if currentlanguage == false then
+ -- ignore
+ else
+ context("%s",converters.ordinal(whatordinal,currentlanguage))
+ end
end
end
end
+
+function commands.rawdate(str)
+ commands.currentdate(str,false)
+end
diff --git a/Master/texmf-dist/tex/context/base/core-con.mkii b/Master/texmf-dist/tex/context/base/core-con.mkii
index c39bdd9d423..46fbe9b9ee6 100644
--- a/Master/texmf-dist/tex/context/base/core-con.mkii
+++ b/Master/texmf-dist/tex/context/base/core-con.mkii
@@ -5,7 +5,7 @@
%D subtitle=Conversion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-con.mkiv b/Master/texmf-dist/tex/context/base/core-con.mkiv
index e43e4ecda55..241d4316595 100644
--- a/Master/texmf-dist/tex/context/base/core-con.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-con.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Conversion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,8 +17,8 @@
\unprotect
-\ifx\currentlanguage\undefined \let\currentlanguage\empty \fi
-\ifx\labeltext \undefined \let\labeltext\firstofoneargument \fi
+\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
%D and dates. I considered splitting this module in a support
@@ -36,7 +36,7 @@
% needed for arab :
-\def\isolateseparators % even works with list separator overloading
+\unexpanded\def\isolateseparators % even works with list separator overloading
{\def\spr##1{{##1}}%
\def\stp##1{{##1}}}
@@ -158,11 +158,18 @@
%D These conversions are dedicated to Frans Goddijn.
\unexpanded\def\oldstylenumerals#1%
- {{\os\number#1}}
+ {\begingroup
+ \os\number#1%
+ \endgroup}
-\unexpanded\def\oldstyleromannumerals#1%
- {{\leftrulefalse\rightrulefalse\ss\txx\boxrulewidth.15ex
- \ruledhbox spread .15em{\hss\uppercased{\romannumerals{#1}}\hss}}}
+\unexpanded\def\oldstyleromannumerals#1% will become obsolete
+ {\begingroup
+ \leftrulefalse
+ \rightrulefalse
+ \ss\txx
+ \boxrulewidth.15ex
+ \ruledhbox spread .15em{\hss\uppercased{\romannumerals{#1}}\hss}%
+ \endgroup}
%D \macros
%D {protectconversion}
@@ -171,9 +178,8 @@
%D passed to \type{\write} en \type{\message}. That's why we
%D introduce:
-\def\protectconversion
- {\def\doconvertcharacters##1{##1}} % was \relax
- %{\def\doconvertcharacters##1{\ifcase0##1 0\else##1\fi}} more save
+\unexpanded\def\protectconversion
+ {\let\doconvertcharacters\firstofoneargument}
%D \macros
%D {normaltime,normalyear,normalmonth,normalday}
@@ -202,23 +208,21 @@
%D
%D Anyhow, the conversion looks like:
-\def\doconvertmonthlong #1{\ctxcommand{month(#1)}}
-\def\doconvertmonthshort#1{\ctxcommand{monthmnem(#1)}}
+\def\monthlong #1{\ctxcommand{month(#1)}}
+\def\monthshort#1{\ctxcommand{monthmnem(#1)}}
-\let\doconvertmonth\doconvertmonthlong
+\let\convertmonth\monthlong % for old times sake
%D We redefine the \TEX\ primitive \type{\month} as:
%D
%D \showsetup{month}
%D \showsetup{MONTH}
-\def\monthlong {\doconvertmonthlong}
-\def\monthshort{\doconvertmonthshort}
-\def\month {\doconvertmonth}
+\let\month \monthlong
-\def\MONTH #1{{\WORD{\month {#1}}}}
-\def\MONTHLONG #1{{\WORD{\monthlong {#1}}}}
-\def\MONTHSHORT#1{{\WORD{\monthshort{#1}}}}
+\def\MONTH #1{\WORD{\month {#1}}}
+\def\MONTHLONG #1{\WORD{\monthlong {#1}}}
+\def\MONTHSHORT#1{\WORD{\monthshort{#1}}}
%D We never explicitly needed this, but Tobias Burnus pointed
%D out that it would be handy to convert to the day of the
@@ -231,23 +235,26 @@
%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 This makes the year 1900 into a normal year and 1996 and
-%D 2000 into leap years, right? Well, converting to string
-%D looks familiar:
+%D The first one is sort of redundant. It takes the day
+%D number argument.
+%D
+%D \showsetup{weekday}
+%D \showsetup{WEEKDAY}
-\def\doconvertday#1{\ctxcommand{day(#1)}}
+\def\weekday#1{\ctxcommand{day(#1)}}
+\def\WEEKDAY#1{\WORD{\weekday{#1}}}
%D \macros
%D {getdayoftheweek, dayoftheweek}
\newcount\normalweekday
-% \def\getdayoftheweek#1#2#3{\normalweekday\ctxcommand{weekday(\number#1,\number#2,\number#3)}}
-% \def\dayoftheweek #1#2#3{\doconvertday{\ctxcommand{weekday(\number#1,\number#2,\number#3)}}}
-
-\def\getdayoftheweek#1#2#3{\normalweekday\ctxcommand{weekday(\number#1,\number#2,\number#3)}\relax} % number
-\def\dayoftheweek #1#2#3{\ctxcommand{weekdayname(\number#1,\number#2,\number#3)}} % name
+ \def\dayoftheweek #1#2#3{\ctxcommand{weekdayname(\number#1,\number#2,\number#3)}} % name
+\unexpanded\def\getdayoftheweek#1#2#3{\normalweekday\ctxcommand{weekday(\number#1,\number#2,\number#3)}\relax} % number
%D Using this macro in
%D
@@ -266,41 +273,14 @@
%D
%D gives
%D
-%D \startvoorbeeld
%D \startlines
%D \getbuffer
%D \stoplines
-%D \stopvoorbeeld
%D
%D The macro \type {\getdayoftheweek} can be used to calculate
%D the number \type {\normalweekday}.
%D \macros
-%D {weekday,WEEKDAY}
-%D
-%D The first one is sort of redundant. It takes the day
-%D number argument.
-%D
-%D \showsetup{weekday}
-%D \showsetup{WEEKDAY}
-
-\def\weekday
- {\doconvertday}
-
-\def\WEEKDAY#1%
- {{\WORD{\doconvertday{#1}}}}
-
-%D \macros
-%D {weekoftheday}
-%D
-%D {\em not yet implemented:}
-%D
-%D \starttyping
-%D \def\weekoftheday#1#2#3%
-%D {}
-%D \stoptyping
-
-%D \macros
%D {doifleapyearelse,
%D getdayspermonth}
%D
@@ -323,7 +303,7 @@
\def\doifleapyearelse#1%
{\ctxcommand{doifleapyearelse(\number#1)}}
-\def\getdayspermonth#1#2%
+\unexpanded\def\getdayspermonth#1#2%
{\edef\numberofdays{\ctxcommand{nofdays(\number#1,\number#2)}}}
\def\dayspermonth#1#2%
@@ -338,7 +318,7 @@
% [\the\normaltime=\the\time]
%D \macros
-%D {currentdate, date}
+%D {currentdate, rawdate, date}
%D
%D We use these conversion macros in the date formatting
%D macro:
@@ -353,11 +333,9 @@
%D \currentdate[WEEKDAY,day,MONTH,year] % still dutch example
%D \stopbuffer
%D
-%D \startvoorbeeld
%D \startlines
%D \getbuffer
%D \stoplines
-%D \stopvoorbeeld
%D
%D depending of course on the keywords. Here we gave:
%D
@@ -396,68 +374,6 @@
%D \getbuffer
%D \stoplines
-% \newtoks \everycurrentdate
-%
-% \newsignal\datesignal
-%
-% \def\dobetweendates
-% {\ifdim\lastskip=\datesignal\relax\else
-% \unskip\space
-% \hskip\datesignal\relax
-% \fi}
-%
-% \def\referraldatepattern{j,mm,dd} % jj,mm,dd changed at januari 1-1-2000
-%
-% \def\dodobetweendates
-% {\let\betweendates\dobetweendates}%
-%
-% \def\dodocurrentdate#1%
-% {\processallactionsinset[#1]
-% [ \v!year=>\betweendates
-% \convertnumber\v!year\normalyear,
-% yy=>\lasttwodigits\normalyear,
-% y=>\convertnumber\v!year\normalyear,
-% Y=>\number\normalyear,
-% \v!month=>\betweendates
-% \month\normalmonth,
-% mm=>\twodigits\normalmonth,
-% m=>\month\normalmonth,
-% M=>\number\normalmonth,
-% \v!day=>\betweendates
-% \convertnumber\v!day\normalday,
-% \v!day+=>\betweendates
-% \convertnumber\v!day\normalday
-% \ordinal\normalday,
-% dd=>\twodigits\normalday,
-% dd+=>\convertnumber\v!day{\twodigits\normalday}%
-% \ordinal\normalday,
-% d=>\convertnumber\v!day\normalday,
-% d+=>\convertnumber\v!day\normalday
-% \ordinal\normalday,
-% d=>\number\normalday,
-% \v!weekday=>\betweendates
-% \convertnumber\v!day{\dayoftheweek\normalday\normalmonth\normalyear},
-% w=>\convertnumber\v!day{\dayoftheweek\normalday\normalmonth\normalyear},
-% W=>\dayoftheweek\normalday\normalmonth\normalyear,
-% \v!referral=>\docomplexcurrentdate\referraldatepattern,
-% \v!space=>\unskip\ \hskip\datesignal,
-% \ =>\unskip\ \hskip\datesignal,
-% \s!default=>,
-% \s!unknown=>\unskip\commalistelement
-% \hskip\datesignal
-% \let\betweendates\dodobetweendates]}
-%
-% \def\docurrentdate[#1]%
-% {\begingroup
-% \the\everycurrentdate
-% \let\betweendates\dodobetweendates
-% \doifsomething{#1}{\edef\currentdatespecification{#1}}%
-% \normalexpanded{\dodocurrentdate{\currentdatespecification}}%
-% \ifdim\lastskip=\datesignal\relax
-% \unskip
-% \fi
-% \endgroup}
-
%D \starttabulate[|l|l|]
%D \HL
%D \NC year \NC (\currentdate[year]) \NC\NR
@@ -481,10 +397,10 @@
%D \HL
%D \NC referral \NC (\currentdate[referral]) \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 \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
@@ -499,9 +415,9 @@
\newtoks \everycurrentdate
\unexpanded\def\currentdate
- {\dosingleempty\docurrentdate}
+ {\dosingleempty\syst_converters_current_date}
-\def\docurrentdate[#1]%
+\def\syst_converters_current_date[#1]%
{\begingroup
\the\everycurrentdate
\doifsomething{#1}{\edef\currentdatespecification{#1}}%
@@ -509,9 +425,9 @@
\endgroup}
\unexpanded\def\date
- {\dodoubleempty\dodate}
+ {\dodoubleempty\syst_converters_date}
-\def\dodate[#1][#2]%
+\def\syst_converters_date[#1][#2]%
{\begingroup
\iffirstargument
\getparameters[\??da][d=\normalday,m=\normalmonth,y=\normalyear,#1]%
@@ -519,9 +435,12 @@
\normalmonth\@@dam\relax
\normalyear \@@day\relax
\fi
- \docurrentdate[#2]%
+ \syst_converters_current_date[#2]%
\endgroup}
+\def\rawdate[#1]% expandable and no labels
+ {\ctxcommand{rawdate(\!!bs\currentdatespecification\!!es)}}
+
%D \macros
%D {currenttime}
%D
@@ -536,17 +455,21 @@
\let\currenthour \!!plusone
\let\currentminute\!!plusone
+\let\currentsecond\!!plusone
\def\currenttimespecification{h,:,m}
-\def\complexcurrenttime[#1]%
+\unexpanded\def\currenttime
+ {\doifnextoptionalelse\syst_converters_current_time_yes\syst_converters_current_time_nop}
+
+
+\unexpanded\def\syst_converters_current_time_yes[#1]%
{\calculatecurrenttime
\processallactionsinset[#1][h=>\currenthour,m=>\currentminute,\s!unknown=>\commalistelement]}
-\def\simplecurrenttime
- {\expanded{\complexcurrenttime[\currenttimespecification]}}
+\unexpanded\def\syst_converters_current_time_nop
+ {\normalexpanded{\syst_converters_current_time_yes[\currenttimespecification]}}
-\definecomplexorsimple\currenttime
%D Because we're dealing with dates, we also introduce a few
%D day loops:
@@ -559,25 +482,25 @@
%D The counters \type {\normalyear}, \type {\normalmonth} and
%D \type{\normalday} can be used for for date manipulations.
-\long\def\processmonth#1#2#3% year month command
- {\bgroup
+\unexpanded\def\processmonth#1#2#3% year month command
+ {\begingroup
\getdayspermonth{#1}{#2}%
- \dostepwiserecurse1\numberofdays1%
+ \dostepwiserecurse\plusone\numberofdays\plusone
{\normalyear #1\relax
\normalmonth#2\relax
\normalday \recurselevel\relax
#3}%
- \egroup}
+ \endgroup}
\def\lastmonth{12} % can be set to e.g. 1 when testing
-\long\def\processyear#1#2#3#4% year command before after
- {\bgroup
+\unexpanded\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}%
- \egroup}
+ \endgroup}
%D \macros
%D {defineconversion, convertnumber}
@@ -603,62 +526,72 @@
%D \defineconversion [en] [whatever] [\something]
%D \stoptyping
+\installcorenamespace {conversion}
+\installcorenamespace {conversionarguments}
+\installcorenamespace {conversionwords}
+
\unexpanded\def\defineconversion
- {\dotripleempty\dodefineconversion}
+ {\dotripleempty\syst_converters_define_conversion}
-\def\dodefineconversion[#1][#2][#3]% from now on global (maybe local again some day)
+\def\syst_converters_define_conversion[#1][#2][#3]% from now on global (maybe local again some day)
{\ifthirdargument
- \dododefineconversion{#1#2}{#1:#2}{#3}%
+ \syst_converters_define_conversion_indeed{#1#2}{#1:#2}{#3}%
\else
- \dododefineconversion{#1}{#1}{#2}%
+ \syst_converters_define_conversion_indeed{#1}{#1}{#2}%
\fi}
-\def\dododefineconversion#1#2#3%
+\def\syst_converters_define_conversion_indeed#1#2#3%
{\doifinstringelse{,}{\detokenize{#3}}
{\ctxcommand{defineconversion("#2",\!!bs\detokenize{#3}\!!es)}%
- \setgvalue{\??cv#1}{\checkedconversion{#2}}}
- {\setgvalue{\??cv#1}{#3}}}
+ \setgvalue{\??conversion#1}{\syst_converters_checked_conversion{#2}}}
+ {\setgvalue{\??conversion#1}{#3}}}
-\def\checkedconversion#1#2%
+\def\syst_converters_checked_conversion#1#2%
{\ctxcommand{checkedconversion("#1",#2)}}
%D If a conversion is just a font switch then we need to make sure
%D that the number is indeed end up as number in the input, so we
%D need to handle the second argument.
-\def\convertnumber#1#2%
- {\csname
- \??cv=>% we want a fully expandable (no if interference)
- \ifcsname\??cv\currentlanguage#1\endcsname1\else
- \ifcsname\??cv #1\endcsname2\else
- 3\fi\fi
+\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}}
-\setvalue{\??cv=>1}#1{\csname\??cv\currentlanguage#1\endcsname}
-\setvalue{\??cv=>2}#1{\csname\??cv #1\endcsname}
-\letvalue{\??cv=>3}\checkedconversion
+\unexpanded\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
\def\doifconversiondefinedelse#1%
- {\ifcsname\??cv\currentlanguage#1\endcsname
- \@EA\firstoftwoarguments
- \else\ifcsname\??cv#1\endcsname
- \@EAEAEA\firstoftwoarguments
+ {\ifcsname\??conversion\currentlanguage#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else\ifcsname\??conversion#1\endcsname
+ \doubleexpandafter\firstoftwoarguments
\else
- \@EAEAEA\secondoftwoarguments
+ \doubleexpandafter\secondoftwoarguments
\fi\fi}
-\def\doifelseconversionnumber#1#2% slow but seldom used
- {\doifdefinedelse{\??cv#1#2}}
+\def\doifelseconversionnumber#1#2%
+ {\ifcsname\??conversion#1#2\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
%D Handy.
-\setvalue{\??cv:\c!n:\v!one }{1}
-\setvalue{\??cv:\c!n:\v!two }{2}
-\setvalue{\??cv:\c!n:\v!three}{3}
-\setvalue{\??cv:\c!n:\v!four }{4}
-\setvalue{\??cv:\c!n:\v!five }{5}
+\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}
-\def\wordtonumber#1#2{\ifcsname\??cv:\c!n:#1\endcsname\csname\??cv:\c!n:#1\endcsname\else#2\fi}
+\def\wordtonumber#1#2{\ifcsname\??conversionwords#1\endcsname\csname\??conversionwords#1\endcsname\else#2\fi}
% \defineconversion[ctx][c,o,n,t,e,x,t]
%
@@ -673,7 +606,7 @@
\def\highordinalstr #1{\high{\notsmallcapped{#1}}}
\def\ordinalstr #1{\notsmallcapped{#1}}
-\def\ordinaldaynumber #1{\ctxcommand{ordinal(#1,"\currentlanguage"}}
+\def\ordinaldaynumber #1{\ctxcommand{ordinal(#1,"\currentlanguage")}}
%D As longs as symbols are linked to levels or numbers, we can
%D also use the conversion mechanism, but in for instance the
@@ -689,8 +622,8 @@
\defineconversion [\v!none] [\numbers]
\defineconversion [\s!default] [\numbers]
-\defineconversion [month] [\doconvertmonthlong]
-\defineconversion [month:mnem] [\doconvertmonthshort]
+\defineconversion [month] [\monthlong]
+\defineconversion [month:mnem] [\monthshort]
\defineconversion [\v!character] [\character]
\defineconversion [\v!Character] [\Character]
@@ -747,7 +680,6 @@
\defineconversion [persiannumerals] [\persiannumerals]
\defineconversion [arabicexnumerals] [\arabicexnumerals]
-
\defineconversion [koreannumerals] [\koreannumerals]
\defineconversion [koreanparentnumerals] [\koreanparentnumerals]
\defineconversion [koreancirclenumerals] [\koreancirclenumerals]
@@ -764,9 +696,17 @@
\defineconversion [cn-c] [\chinesecapnumerals]
\defineconversion [cn-a] [\chineseallnumerals]
+%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 Symbol sets:
-\ifx\symbol\undefined \def\symbol[#1]{#1} \fi % todo
+\ifdefined\symbol \else \def\symbol[#1]{#1} \fi % todo
\defineconversion
[set 0]
diff --git a/Master/texmf-dist/tex/context/base/core-ctx.mkii b/Master/texmf-dist/tex/context/base/core-ctx.mkii
index 93cf8b4be2c..c693d10db6f 100644
--- a/Master/texmf-dist/tex/context/base/core-ctx.mkii
+++ b/Master/texmf-dist/tex/context/base/core-ctx.mkii
@@ -5,7 +5,7 @@
%D subtitle=Job Control,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-ctx.mkiv b/Master/texmf-dist/tex/context/base/core-ctx.mkiv
index f6e5a33f1be..e178ee21bea 100644
--- a/Master/texmf-dist/tex/context/base/core-ctx.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-ctx.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Job Control,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,10 +19,12 @@
\registerctxluafile{core-ctx}{1.000}
-\def\loadctxpreplist{\ctxcommand{loadctxpreplist()}\global\let\loadctxpreplist\relax}
+\def\loadctxpreplist
+ {\ctxcommand{loadctxpreplist()}%
+ \glet\loadctxpreplist\relax}
-% \prependtoks\loadctxpreplist\to\everyjob
-
-\appendtoks\loadctxpreplist\to\everystarttext % maybe too late but don't change it now
+\appendtoks
+ \loadctxpreplist
+\to \everystarttext % maybe too late but don't change it now
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-dat.lua b/Master/texmf-dist/tex/context/base/core-dat.lua
new file mode 100644
index 00000000000..071a3fe0b47
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/core-dat.lua
@@ -0,0 +1,246 @@
+if not modules then modules = { } end modules ['core-dat'] = {
+ version = 1.001,
+ comment = "companion to core-dat.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>This module provides a (multipass) container for arbitrary data. It
+replaces the twopass data mechanism.</p>
+--ldx]]--
+
+local tonumber = tonumber
+
+local context, commands = context, commands
+
+local trace_datasets = false trackers.register("job.datasets" , function(v) trace_datasets = v end)
+local trace_pagestates = false trackers.register("job.pagestates", function(v) trace_pagestates = v end)
+
+local report_dataset = logs.reporter("dataset")
+local report_pagestate = logs.reporter("pagestate")
+
+local allocate = utilities.storage.allocate
+local settings_to_hash = utilities.parsers.settings_to_hash
+local format = string.format
+local texcount = tex.count
+
+local v_yes = interfaces.variables.yes
+
+local new_latelua = nodes.pool.latelua
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local datasets = {
+ collected = collected,
+ tobesaved = tobesaved,
+}
+
+job.datasets = datasets
+
+local function initializer()
+ collected = datasets.collected
+ tobesaved = datasets.tobesaved
+end
+
+job.register('job.datasets.collected', tobesaved, initializer, nil)
+
+local sets = { }
+
+table.setmetatableindex(tobesaved, function(t,k)
+ local v = { }
+ t[k] = v
+ return v
+end)
+
+table.setmetatableindex(sets, function(t,k)
+ local v = {
+ index = 0,
+ order = 0,
+ }
+ t[k] = v
+ return v
+end)
+
+local function setdata(settings)
+ local name = settings.name
+ local tag = settings.tag
+ local data = settings.data
+ local list = tobesaved[name]
+ data = settings_to_hash(data) or { }
+ if not tag then
+ tag = #list + 1
+ else
+ tag = tonumber(tag) or tag -- autonumber saves keys
+ end
+ list[tag] = data
+ if settings.delay == v_yes then
+ local set = sets[name]
+ local index = set.index + 1
+ set.index = index
+ data.index = index
+ data.order = index
+ data.realpage = texcount.realpageno
+ if trace_datasets then
+ report_dataset("delayed: name %s, tag %s, index %s",name,tag,index)
+ end
+ elseif trace_datasets then
+ report_dataset("immediate: name %s, tag %s",name,tag)
+ end
+ return name, tag, data
+end
+
+datasets.setdata = setdata
+
+function datasets.extend(name,tag)
+ local set = sets[name]
+ local order = set.order + 1
+ local realpage = texcount.realpageno
+ set.order = order
+ local t = tobesaved[name][tag]
+ t.realpage = realpage
+ t.order = order
+ if trace_datasets then
+ report_dataset("flushed: name %s, tag %s, page %s, index %s, order",name,tag,t.index or 0,order,realpage)
+ end
+end
+
+function datasets.getdata(name,tag,key,default)
+ local t = collected[name]
+ if t then
+ t = t[tag] or t[tonumber(tag)]
+ if t then
+ if key then
+ return t[key] or default
+ else
+ return t
+ end
+ elseif trace_datasets then
+ report_dataset("unknown: name %s, tag %s",name,tag)
+ end
+ elseif trace_datasets then
+ report_dataset("unknown: name %s",name)
+ end
+ return default
+end
+
+function commands.setdataset(settings)
+ local name, tag, data = setdata(settings)
+ if settings.delay ~= v_yes then
+ --
+ elseif type(tag) == "number" then
+ context(new_latelua(format("job.datasets.extend(%q,%i)",name,tag)))
+ else
+ context(new_latelua(format("job.datasets.extend(%q,%q)",name,tag)))
+ end
+end
+
+function commands.datasetvariable(name,tag,key)
+ local t = collected[name]
+ t = t and (t[tag] or t[tonumber(tag)])
+ if t then
+ local s = t[key]
+ if s then
+ context(s)
+ end
+ end
+end
+
+--[[ldx--
+<p>We also provide an efficient variant for page states.</p>
+--ldx]]--
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local pagestates = {
+ collected = collected,
+ tobesaved = tobesaved,
+}
+
+job.pagestates = pagestates
+
+local function initializer()
+ collected = pagestates.collected
+ tobesaved = pagestates.tobesaved
+end
+
+job.register('job.pagestates.collected', tobesaved, initializer, nil)
+
+table.setmetatableindex(tobesaved, function(t,k)
+ local v = { }
+ t[k] = v
+ return v
+end)
+
+local function setstate(settings)
+ local name = settings.name
+ local tag = settings.tag
+ local list = tobesaved[name]
+ if not tag then
+ tag = #list + 1
+ else
+ tag = tonumber(tag) or tag -- autonumber saves keys
+ end
+ local realpage = texcount.realpageno
+ local data = realpage
+ list[tag] = data
+ if trace_pagestates then
+ report_pagestate("setting: name %s, tag %s, preset %s",name,tag,realpage)
+ end
+ return name, tag, data
+end
+
+pagestates.setstate = setstate
+
+function pagestates.extend(name,tag)
+ local realpage = texcount.realpageno
+ if trace_pagestates then
+ report_pagestate("synchronizing: name %s, tag %s, preset %s",name,tag,realpage)
+ end
+ tobesaved[name][tag] = realpage
+end
+
+function pagestates.realpage(name,tag,default)
+ local t = collected[name]
+ if t then
+ t = t[tag] or t[tonumber(tag)]
+ if t then
+ return tonumber(t or default)
+ elseif trace_pagestates then
+ report_pagestate("unknown: name %s, tag %s",name,tag)
+ end
+ elseif trace_pagestates then
+ report_pagestate("unknown: name %s",name)
+ end
+ return default
+end
+
+function commands.setpagestate(settings)
+ local name, tag, data = setstate(settings)
+ if type(tag) == "number" then
+ context(new_latelua(format("job.pagestates.extend(%q,%i)",name,tag)))
+ else
+ context(new_latelua(format("job.pagestates.extend(%q,%q)",name,tag)))
+ end
+end
+
+function commands.pagestaterealpage(name,tag)
+ local t = collected[name]
+ t = t and (t[tag] or t[tonumber(tag)])
+ if t then
+ context(t)
+ end
+end
+
+function commands.setpagestaterealpageno(name,tag)
+ local t = collected[name]
+ t = t and (t[tag] or t[tonumber(tag)])
+ if t then
+ texcount.realpagestateno = t
+ else
+ texcount.realpagestateno = texcount.realpageno
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/core-dat.mkiv b/Master/texmf-dist/tex/context/base/core-dat.mkiv
new file mode 100644
index 00000000000..5aef39d691a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/core-dat.mkiv
@@ -0,0 +1,101 @@
+%D \module
+%D [ file=core-dat,
+%D version=20122.04.17, % replaces core-two from 1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Multipass Datasets,
+%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 / Multipass Datasets}
+
+%D \starttyping
+%D \definedataset[test-1]
+%D \definedataset[test-2][delay=yes]
+%D
+%D \startlines
+%D set 1: \setdataset[test-1][whatever=this-or-that-1]
+%D set 2: \setdataset[test-2][whatever=this-or-that-2]
+%D set 3: \setdataset[test-2][whatever=this-or-that-3]
+%D \stoplines
+%D
+%D \startlines
+%D get 1: \datasetvariable{test-1}{1}{whatever} / \datasetvariable{test-1}{1}{realpage}
+%D get 2: \datasetvariable{test-2}{1}{whatever} / \datasetvariable{test-2}{1}{realpage}
+%D get 3: \datasetvariable{test-2}{2}{whatever} / \datasetvariable{test-2}{2}{realpage}
+%D \stoplines
+%D \stoptyping
+
+\unprotect
+
+\registerctxluafile{core-dat}{1.001}
+
+\installcorenamespace{dataset}
+
+\installcommandhandler \??dataset {dataset} \??dataset
+
+\unexpanded\def\setdataset
+ {\dotripleempty\syst_datasets_set}
+
+\def\syst_datasets_set
+ {\ifthirdargument
+ \expandafter\syst_datasets_set_named
+ \else
+ \expandafter\syst_datasets_set_indexed
+ \fi}
+
+\def\syst_datasets_set_named[#1][#2][#3]%
+ {\begingroup
+ \edef\currentdataset{#1}%
+ \ctxcommand{setdataset{
+ name = "\currentdataset",
+ tag = \!!bs#2\!!es,
+ delay = "\datasetparameter\c!delay",
+ data = \!!bs#3\!!es
+ }}%
+ \endgroup}
+
+\def\syst_datasets_set_indexed[#1][#2][#3]%
+ {\begingroup
+ \edef\currentdataset{#1}%
+ \ctxcommand{setdataset{
+ name = "\currentdataset",
+ delay = "\datasetparameter\c!delay",
+ data = \!!bs#2\!!es
+ }}%
+ \endgroup}
+
+\def\datasetvariable#1#2#3%
+ {\ctxcommand{datasetvariable("#1","#2","#3")}}
+
+\installcorenamespace{pagestate}
+
+\installcommandhandler \??pagestate {pagestate} \??pagestate
+
+\setuppagestate
+ [\c!delay=\v!yes]
+
+\unexpanded\def\setpagestate
+ {\dodoubleempty\syst_pagestates_set}
+
+\def\syst_pagestates_set[#1][#2]%
+ {\begingroup
+ \edef\currentpagestate{#1}%
+ \ctxcommand{setpagestate{
+ name = "\currentpagestate",
+ tag = \!!bs#2\!!es,
+ delay = "\pagestateparameter\c!delay",
+ }}%
+ \endgroup}
+
+\def\pagestaterealpage#1#2%
+ {\ctxcommand{pagestaterealpage("#1","#2")}}
+
+\def\setpagestaterealpageno#1#2%
+ {\ctxcommand{setpagestaterealpageno("#1","#2")}}
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/core-def.mkii b/Master/texmf-dist/tex/context/base/core-def.mkii
index ff7283356c1..971e8953d99 100644
--- a/Master/texmf-dist/tex/context/base/core-def.mkii
+++ b/Master/texmf-dist/tex/context/base/core-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Defaults,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-def.mkiv b/Master/texmf-dist/tex/context/base/core-def.mkiv
index 59c2c89c1e3..4f856f99622 100644
--- a/Master/texmf-dist/tex/context/base/core-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-def.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Defaults,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -26,10 +26,12 @@
% initialization order:
-\ifdefined\firststagepreloadfonts \else \let\firststagepreloadfonts \relax \fi
-\ifdefined\secondstagepreloadfonts \else \let\secondstagepreloadfonts\relax \fi
-\ifdefined\thirdstagepreloadfonts \else \let\thirdstagepreloadfonts \relax \fi
-\ifdefined\fourthstagepreloadfonts \else \let\fourthstagepreloadfonts\relax \fi
+\ifdefined\font_preloads_at_every_job \else \let\font_preloads_at_every_job \relax \fi
+\ifdefined\font_preloads_at_start_text \else \let\font_preloads_at_start_text\relax \fi
+\ifdefined\font_preloads_at_stop_text \else \let\font_preloads_at_stop_text \relax \fi
+
+\appendtoks \font_preloads_at_start_text \to \everystarttext
+\appendtoks \font_preloads_at_stop_text \to \everystoptext
%prependtoks \preloadtypescript \to \everyjob
\appendtoks \showcontextbanner \to \everyjob
@@ -37,17 +39,16 @@
\appendtoks \calculatecurrenttime \to \everyjob
\appendtoks \loadsystemfiles \to \everyjob
\appendtoks \loadoptionfile \to \everyjob % can load files !
-\appendtoks \firststagepreloadfonts \to \everyjob
+\appendtoks \font_preloads_at_every_job \to \everyjob
\appendtoks \settopskip \to \everyjob
-\appendtoks \initializeMPgraphics \to \everyjob % after loading system files
\appendtoks \initializemainlanguage \to \everyjob
%appendtoks \MPLIBregister \to \everyjob
\appendtoks \xmlinitialize \to \everyjob
-\appendtoks \newbackgroundfalse \to \everyjob % global
+\appendtoks \setfalse\c_page_backgrounds_new \to \everyjob
+\appendtoks \setfalse\c_page_backgrounds_some \to \everyjob
\appendtoks \initializepagecounters \to \everyjob
\appendtoks \directsetup{*runtime:options} \to \everyjob % we could erase them afterwards % order can change
\appendtoks \directsetup{*runtime:modules} \to \everyjob % we could erase them afterwards % order can change
-\appendtoks \checkpreprocessor \to \everyjob
%appendtoks \page[\v!last] \page \to \everybye % moved to core-job, we need to do this cleaner
\appendtoks \ifarrangingpages\poparrangedpages\fi \to \everybye
@@ -62,22 +63,11 @@
\prependtoks \lefttoright \to \everybeforeoutput
-\appendtoks \secondstagepreloadfonts \to \everystarttext
-\appendtoks \fourthstagepreloadfonts \to \everystoptext
-
% temporary here:
-\ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \dospecialin } \else \let\in \dospecialin \fi
-\ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \dospecialat } \else \let\at \dospecialat \fi
-\ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\dospecialabout} \else \let\about\dospecialabout \fi
-\ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \dospecialfrom } \else \let\from \dospecialfrom \fi
-\ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \dospecialabout} \else \let\over \dospecialabout \fi
-
\unexpanded\def\arg{\mathortext\normalmatharg\normaltextarg}
-% for the moment here
-
-\enablemode[*nofonts]
+% might move to \everydump or even disappear:
\nonknuthmode
@@ -92,4 +82,10 @@
\synchronizelocallinespecs
\to \everyswitchtobodyfont
+% who knows
+
+% \appendtoks
+% \resetcharacterspacing
+% \to \everyhyphenatedurl
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-env.lua b/Master/texmf-dist/tex/context/base/core-env.lua
index 694b2f07c42..c31df929e15 100644
--- a/Master/texmf-dist/tex/context/base/core-env.lua
+++ b/Master/texmf-dist/tex/context/base/core-env.lua
@@ -14,8 +14,8 @@ if not modules then modules = { } end modules ['core-env'] = {
local P, C, S, Cc, lpegmatch, patterns = lpeg.P, lpeg.C, lpeg.S, lpeg.Cc, lpeg.match, lpeg.patterns
local csname_id = token.csname_id
-local texcount = tex.count
local create = token.create
+local texcount = tex.count
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -71,9 +71,12 @@ setmetatableindex(tex.conditionals, function(t,k) -- 0 == true
end)
setmetatableindex(tex.ifs, function(t,k)
+ -- k = "if" .. k -- better not
return csname_id(k) ~= undefined and create(k)[2] == iftrue -- inefficient, this create, we need a helper
end)
+-- todo : global
+
function tex.settrue(name)
texcount[name] = 0
end
@@ -99,3 +102,39 @@ local pattern = (
function commands.autosetups(str)
lpegmatch(pattern,str)
end
+
+-- new (inefficient)
+
+local lookuptoken = token.lookup
+
+local dimencode = lookuptoken("scratchdimen" )[1]
+local countcode = lookuptoken("scratchcounter")[1]
+local tokencode = lookuptoken("scratchtoken" )[1]
+local skipcode = lookuptoken("scratchskip" )[1]
+
+local types = {
+ [dimencode] = "dimen",
+ [countcode] = "count",
+ [tokencode] = "token",
+ [skipcode ] = "skip",
+}
+
+function tex.isdimen(name)
+ return lookuptoken(name)[1] == dimencode
+end
+function tex.iscount(name)
+ return lookuptoken(name)[1] == countcode
+end
+function tex.istoken(name)
+ return lookuptoken(name)[1] == tokencode
+end
+function tex.isskip(name)
+ return lookuptoken(name)[1] == skipcode
+end
+
+function tex.type(name)
+ return types[lookuptoken(name)[1]] or "macro"
+end
+
+-- inspect(tex.isdimen("xxxxxxxxxxxxxxx"))
+-- inspect(tex.isdimen("textwidth"))
diff --git a/Master/texmf-dist/tex/context/base/core-env.mkii b/Master/texmf-dist/tex/context/base/core-env.mkii
index a22594b27a4..6058c4c9fa8 100644
--- a/Master/texmf-dist/tex/context/base/core-env.mkii
+++ b/Master/texmf-dist/tex/context/base/core-env.mkii
@@ -5,7 +5,7 @@
%D subtitle=New ones,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-env.mkiv b/Master/texmf-dist/tex/context/base/core-env.mkiv
index 2451b59501a..1819d084d0a 100644
--- a/Master/texmf-dist/tex/context/base/core-env.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-env.mkiv
@@ -5,7 +5,7 @@
%D subtitle=New ones,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -40,11 +40,12 @@
%D level style does not want that. Preventing can be
%D considered a permanent disabling on forehand.
-\def\@mode@{@md@}
-\def\@mode@{mode}
-
\def\systemmodeprefix{*}
+% we will have \installcorenamespace{mode} but need some hackery at the lua end then
+
+\installcorenamespace{modestack}
+
% todo: check prevent mode, also at the lua end
\setnewconstant\disabledmode \zerocount
@@ -53,42 +54,42 @@
% fast internal ones
-\def\donewmode#1%
- {\@EA\newcount\csname\@mode@#1\endcsname}
+\def\syst_modes_new#1%
+ {\expandafter\newcount\csname\s!mode#1\endcsname}
-\def\newmode#1%
- {\ifcsname\@mode@#1\endcsname\else\donewmode{#1}\fi}
+\unexpanded\def\newmode#1%
+ {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi}
-\def\setmode#1%
- {\ifcsname\@mode@#1\endcsname\else\donewmode{#1}\fi
- \csname\@mode@#1\endcsname\enabledmode}
+\unexpanded\def\setmode#1%
+ {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \csname\s!mode#1\endcsname\enabledmode}
-\def\resetmode#1%
- {\ifcsname\@mode@#1\endcsname\else\donewmode{#1}\fi
- \csname\@mode@#1\endcsname\disabledmode}
+\unexpanded\def\resetmode#1%
+ {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \csname\s!mode#1\endcsname\disabledmode}
-\def\newsystemmode#1%
- {\ifcsname\@mode@\systemmodeprefix#1\endcsname\else\donewmode{\systemmodeprefix#1}\fi}
+\unexpanded\def\newsystemmode#1%
+ {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi}
-\def\setsystemmode#1%
- {\ifcsname\@mode@\systemmodeprefix#1\endcsname\else\donewmode{\systemmodeprefix#1}\fi
- \csname\@mode@\systemmodeprefix#1\endcsname\enabledmode}
+\unexpanded\def\setsystemmode#1%
+ {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \csname\s!mode\systemmodeprefix#1\endcsname\enabledmode}
-\def\resetsystemmode#1%
- {\ifcsname\@mode@\systemmodeprefix#1\endcsname\else\donewmode{\systemmodeprefix#1}\fi
- \csname\@mode@\systemmodeprefix#1\endcsname\disabledmode}
+\unexpanded\def\resetsystemmode#1%
+ {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \csname\s!mode\systemmodeprefix#1\endcsname\disabledmode}
% \def\dosetsystemmode#1%
-% {\csname\@mode@\systemmodeprefix#1\endcsname\enabledmode}
+% {\csname\s!mode\systemmodeprefix#1\endcsname\enabledmode}
%
% \def\doresetsystemmode#1%
-% {\csname\@mode@\systemmodeprefix#1\endcsname\disabledmode}
+% {\csname\s!mode\systemmodeprefix#1\endcsname\disabledmode}
% demo: trialtypesetting is a systemmode as well as an if
-\newsystemmode{trialtypesetting}
+\newsystemmode{trialtypesetting} % the name of \@@trialtypesetting might change (also at the lua end)
-\expandafter\let\expandafter\@@trialtypesetting\csname\@mode@\systemmodeprefix trialtypesetting\endcsname % private !
+\expandafter\let\expandafter\@@trialtypesetting\csname\s!mode\systemmodeprefix trialtypesetting\endcsname % private !
\appendtoks
\@@trialtypesetting\enabledmode
@@ -100,110 +101,199 @@
% user ones
-\unexpanded\def\preventmode{\unprotect\dopreventmode}
-\unexpanded\def\enablemode {\unprotect\doenablemode }
-\unexpanded\def\disablemode{\unprotect\dodisablemode}
+\unexpanded\def\preventmode{\unprotect\syst_modes_prevent}
+\unexpanded\def\enablemode {\unprotect\syst_modes_enable }
+\unexpanded\def\disablemode{\unprotect\syst_modes_disable}
\let\definemode\disablemode % nicer
-\def\dopreventmode[#1]{\protect\rawprocesscommacommand[#1]\dodopreventmode}
-\def\doenablemode [#1]{\protect\rawprocesscommacommand[#1]\dodoenablemode }
-\def\dodisablemode[#1]{\protect\rawprocesscommacommand[#1]\dododisablemode}
+\def\syst_modes_prevent[#1]{\protect\rawprocesscommacommand[#1]\syst_modes_prevent_indeed}
+\def\syst_modes_enable [#1]{\protect\rawprocesscommacommand[#1]\syst_modes_enable_indeed }
+\def\syst_modes_disable[#1]{\protect\rawprocesscommacommand[#1]\syst_modes_disable_indeed}
-\def\dodopreventmode#1%
- {\ifcsname\@mode@#1\endcsname\else\donewmode{#1}\fi
- \csname\@mode@#1\endcsname\preventedmode}
+\def\syst_modes_prevent_indeed#1%
+ {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \csname\s!mode#1\endcsname\preventedmode}
-\def\dodoenablemode#1% we can speed it up by moving the new outside
- {\ifcsname\@mode@#1\endcsname\else\donewmode{#1}\fi
- \ifnum\csname\@mode@#1\endcsname=\preventedmode \else
- \csname\@mode@#1\endcsname\enabledmode
+\def\syst_modes_enable_indeed#1% we can speed it up by moving the new outside
+ {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \ifnum\csname\s!mode#1\endcsname=\preventedmode \else
+ \csname\s!mode#1\endcsname\enabledmode
\fi}
-\def\dododisablemode#1%
- {\ifcsname\@mode@#1\endcsname\else\donewmode{#1}\fi
- \ifnum\csname\@mode@#1\endcsname=\preventedmode \else
- \csname\@mode@#1\endcsname\disabledmode
+\def\syst_modes_disable_indeed#1%
+ {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \ifnum\csname\s!mode#1\endcsname=\preventedmode \else
+ \csname\s!mode#1\endcsname\disabledmode
\fi}
% handy for mp
\def\booleanmodevalue#1%
- {\ifcsname\@mode@#1\endcsname\ifcase\csname\@mode@#1\endcsname fals\else tru\fi\else fals\fi e}
+ {\ifcsname\s!mode#1\endcsname\ifcase\csname\s!mode#1\endcsname\s!false\else\s!true\fi\else\s!false\fi}
% check macros
-\newif\ifcheckedmode
-
-\def\dodocheckformode#1%
- {\ifcsname\@mode@#1\endcsname\ifcase\csname\@mode@#1\endcsname\else\checkedmodetrue\fi\fi}
-
-\def\docheckformode#1#2#3% will be sped up with a quit
- {\protect\checkedmodefalse\rawprocesscommacommand[#3]\dodocheckformode
- \ifcheckedmode\@EA#1\else\@EA#2\fi}
-
-\def\dodocheckforallmodes#1%
- {\ifcsname\@mode@#1\endcsname\ifcase\csname\@mode@#1\endcsname\checkedmodefalse\fi\else\checkedmodefalse\fi}
-
-\def\docheckforallmodes#1#2#3% will be sped up with a quit
- {\protect\checkedmodetrue\rawprocesscommacommand[#3]\dodocheckforallmodes
- \ifcheckedmode\@EA#1\else\@EA#2\fi}
+% For some reason the older version had an unprotect for grabbing the
+% mode list (only) which does not really make sense any more so that
+% has been removed. One should (un)protect at the outer level instead.
-% simple ones
+\newconditional\c_checked_mode
-\unexpanded\def\doifmodeelse{\unprotect\dodoifmodeelse}
-\unexpanded\def\doifmode {\unprotect\dodoifmode}
-\unexpanded\def\doifnotmode {\unprotect\dodoifnotmode}
-\unexpanded\def\startmode {\unprotect\dostartmode}
-\unexpanded\def\startnotmode{\unprotect\dostartnotmode}
+\def\syst_modes_check_indeed#1%
+ {\ifcsname\s!mode#1\endcsname
+ \ifcase\csname\s!mode#1\endcsname\else
+ \let\syst_modes_check_step\gobbleoneargument
+ \fi
+ \fi}
-\def\dodoifmodeelse
- {\docheckformode\firstoftwoarguments\secondoftwoarguments}
+\def\syst_modes_check#1#2#3%
+ {\let\syst_modes_check_step\syst_modes_check_indeed
+ \rawprocesscommacommand[#3]\syst_modes_check_step
+ \ifx\syst_modes_check_step\gobbleoneargument
+ \expandafter#1%
+ \else
+ \expandafter#2%
+ \fi}
-\def\dodoifmode
- {\docheckformode\firstofoneargument\gobbleoneargument}
+\def\syst_modes_check_all_indeed#1%
+ {\ifcsname\s!mode#1\endcsname
+ \ifcase\csname\s!mode#1\endcsname
+ \let\syst_modes_check_all_step\gobbleoneargument
+ \fi
+ \else
+ \let\syst_modes_check_all_step\gobbleoneargument
+ \fi}
-\def\dodoifnotmode
- {\docheckformode\gobbleoneargument\firstofoneargument}
+\def\syst_modes_check_all#1#2#3%
+ {\let\syst_modes_check_all_step\syst_modes_check_all_indeed
+ \rawprocesscommacommand[#3]\syst_modes_check_all_step
+ \ifx\syst_modes_check_all_step\gobbleoneargument
+ \expandafter#2%
+ \else
+ \expandafter#1%
+ \fi}
-\long\unexpanded\def\dostartmode[#1]%
- {\docheckformode\donothing\dostopmode{#1}}
+\unexpanded\def\doifmodeelse {\syst_modes_check\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifmode {\syst_modes_check\firstofoneargument\gobbleoneargument}
+\unexpanded\def\doifnotmode {\syst_modes_check\gobbleoneargument\firstofoneargument}
+\unexpanded\def\startmode [#1]{\syst_modes_check\donothing\syst_modes_stop_yes{#1}}
+\unexpanded\def\startnotmode [#1]{\syst_modes_check\syst_modes_stop_nop\donothing{#1}}
+\unexpanded\def\doifallmodeselse {\syst_modes_check_all\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifallmodes {\syst_modes_check_all\firstofoneargument\gobbleoneargument}
+\unexpanded\def\doifnotallmodes {\syst_modes_check_all\gobbleoneargument\firstofoneargument}
+\unexpanded\def\startallmodes [#1]{\syst_modes_check_all\donothing\syst_modes_stop_all_yes{#1}}
+\unexpanded\def\startnotallmodes[#1]{\syst_modes_check_all\syst_modes_stop_all_nop\donothing{#1}}
+
+\unexpanded\def\stopmode {} % no relax
+\unexpanded\def\stopnotmode {} % no relax
+\unexpanded\def\stopallmodes {} % no relax
+\unexpanded\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:
+
+\unexpanded\def\pushmode[#1]%
+ {\ifcsname\s!mode#1\endcsname\else\syst_modes_new{#1}\fi
+ \expandafter\edef\csname\??modestack#1\endcsname{\number\csname\s!mode#1\endcsname}%
+ \expandafter\pushmacro\csname\??modestack#1\endcsname}
+
+\unexpanded\def\popmode[#1]%
+ {\ifcsname\??modestack#1\endcsname
+ \expandafter\popmacro\csname\??modestack#1\endcsname
+ \csname\s!mode#1\endcsname\csname\??modestack#1\endcsname\relax
+ \fi}
-\long\def\dostartnotmode[#1]%
- {\docheckformode\dostopnotmode\donothing{#1}}
+\def\pushsystemmode#1%
+ {\ifcsname\s!mode\systemmodeprefix#1\endcsname\else\syst_modes_new{\systemmodeprefix#1}\fi
+ \expandafter\edef\csname\??modestack\systemmodeprefix#1\endcsname{\number\csname\s!mode\systemmodeprefix#1\endcsname}%
+ \expandafter\pushmacro\csname\??modestack\systemmodeprefix#1\endcsname}
-\unexpanded\def\stopmode {} % no relax
-\unexpanded\def\stopnotmode{} % no relax
+\def\popsystemmode#1%
+ {\ifcsname\??modestack\systemmodeprefix#1\endcsname
+ \expandafter\popmacro\csname\??modestack\systemmodeprefix#1\endcsname
+ \csname\s!mode\systemmodeprefix#1\endcsname\csname\??modestack\systemmodeprefix#1\endcsname\relax
+ \fi}
-\long\def\dostopmode #1\stopmode {}
-\long\def\dostopnotmode#1\stopnotmode{}
+%D Here is a relatively new variant of mode checking:
+%D
+%D \starttyping
+%D \enablemode[two]
+%D
+%D \startmodes
+%D [one] {1}
+%D [two] {2}
+%D [two] {2}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodes
+%D
+%D \startmodes
+%D [one] {1}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodes
+%D
+%D \startmodes
+%D [one] {
+%D \input tufte
+%D }
+%D [two] {
+%D \startmodes
+%D [one] {1}
+%D [two] {2}
+%D [two] {2}
+%D [three] {3}
+%D [default] {?}
+%D \stopmodes
+%D }
+%D [three] {
+%D \input zapf
+%D }
+%D [default] {
+%D \input ward
+%D }
+%D \stopmodes
+%D \stoptyping
-\unexpanded\def\doifallmodeselse{\unprotect\dodoifallmodeselse}
-\unexpanded\def\doifallmodes {\unprotect\dodoifallmodes}
-\unexpanded\def\doifnotallmodes {\unprotect\dodoifnotallmodes}
-\unexpanded\def\startallmodes {\unprotect\dostartallmodes}
-\unexpanded\def\startnotallmodes{\unprotect\dostartnotallmodes}
+\newconditional\c_syst_modes_set_done % conditionals can be pushed/popped
-\def\dodoifallmodeselse
- {\docheckforallmodes\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\startmodeset
+ {\pushmacro\c_syst_modes_set_done
+ \setfalse\conditionalfalse
+ \doifnextoptionalelse\syst_modes_set_start\syst_modes_set_quit}
-\def\dodoifallmodes
- {\docheckforallmodes\firstofoneargument\gobbleoneargument}
+\def\syst_modes_set_start[#1]%
+ {\edef\m_mode_case{#1}%
+ \ifx\m_mode_case\s!default
+ \ifconditional\c_syst_modes_set_done
+ \doubleexpandafter\syst_modes_set_quit
+ \else
+ \doubleexpandafter\syst_modes_set_yes
+ \fi
+ \else
+ \singleexpandafter\syst_modes_set_check
+ \fi}
-\def\dodoifnotallmodes
- {\docheckforallmodes\gobbleoneargument\firstofoneargument}
+\def\syst_modes_set_check
+ {\syst_modes_check\syst_modes_set_yes\syst_modes_set_nop\m_mode_case}
-\long\def\dostartallmodes[#1]%
- {\docheckforallmodes\donothing\dostopallmodes{#1}}
+\def\syst_modes_set_yes#1%
+ {\settrue\c_syst_modes_set_done
+ #1%
+ \doifnextoptionalelse\syst_modes_set_start\syst_modes_set_quit}
-\long\def\dostartnotallmodes[#1]%
- {\docheckforallmodes\dostopnotallmodes\donothing{#1}}
+\def\syst_modes_set_nop#1%
+ {\doifnextoptionalelse\syst_modes_set_start\syst_modes_set_quit}
-\unexpanded\def\stopallmodes {} % no relax
-\unexpanded\def\stopnotallmodes{} % no relax
+\def\syst_modes_set_quit#1\stopmodeset
+ {\popmacro\c_syst_modes_set_done}
-\long\def\dostopallmodes #1\stopallmodes {}
-\long\def\dostopnotallmodes#1\stopnotallmodes{}
+\let\stopmodeset\relax
%D Lets now set a mode:
@@ -211,38 +301,40 @@
%D Setups:
+\installcorenamespace{setup} % we can probably get rid of some :'s later on
+
\unexpanded\def\startsetups{} % to please dep checker
\unexpanded\def\stopsetups {} % to please dep checker
\expanded % will become obsolete
- {\long\def\@EA\noexpand\csname\e!start\v!setups\endcsname
+ {\def\expandafter\noexpand\csname\e!start\v!setups\endcsname
{\begingroup\noexpand\doifnextoptionalelse
- {\noexpand\dostartsetupsA\@EA\noexpand\csname\e!stop\v!setups\endcsname}
- {\noexpand\dostartsetupsB\@EA\noexpand\csname\e!stop\v!setups\endcsname}}}
+ {\noexpand\dostartsetupsA\expandafter\noexpand\csname\e!stop\v!setups\endcsname}
+ {\noexpand\dostartsetupsB\expandafter\noexpand\csname\e!stop\v!setups\endcsname}}}
\letvalue{\e!stop\v!setups}\relax
-\unexpanded\def\setups{\doifnextbgroupelse\dosetupsA\dosetupsB} % {..} or [..]
-\unexpanded\def\setup {\doifnextbgroupelse\dosetups \dosetupsC} % {..} or [..]
+\unexpanded\def\setups{\doifnextbgroupelse\syst_setups_a\syst_setups_b} % {..} or [..]
+\unexpanded\def\setup {\doifnextbgroupelse\syst_setups \syst_setups_c} % {..} or [..]
-\def\dosetupsA #1{\processcommacommand[#1]\dosetups} % {..}
-\def\dosetupsB[#1]{\processcommacommand[#1]\dosetups} % [..]
-\def\dosetupsC[#1]{\dosetups{#1}} % [..]
+\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}} % [..]
-\letvalue{\??su:\letterpercent}\gobbleoneargument
+\letvalue{\??setup:\letterpercent}\gobbleoneargument
-\def\dosetups#1% the grid option will be extended to other main modes
- {\csname\??su
+\def\syst_setups#1% the grid option will be extended to other main modes
+ {\csname\??setup
\ifgridsnapping
- \ifcsname\??su\v!grid:#1\endcsname\v!grid:#1\else\ifcsname\??su:#1\endcsname:#1\else:\letterpercent\fi\fi
+ \ifcsname\??setup\v!grid:#1\endcsname\v!grid:#1\else\ifcsname\??setup:#1\endcsname:#1\else:\letterpercent\fi\fi
\else
- \ifcsname\??su:#1\endcsname:#1\else:\letterpercent\fi
+ \ifcsname\??setup:#1\endcsname:#1\else:\letterpercent\fi
\fi
\endcsname\empty} % takes one argument
% We can consider:
%
-% \setvalue{\??su->\v!auto}#1{\ctxcommand{autosetup("#1")}}
+% \setvalue{\??setup->\v!auto}#1{\ctxcommand{autosetup("#1")}}
%
% ":\letterpercent" => "->\v!auto" with "\endcsname{#1}"
%
@@ -259,7 +351,7 @@
\fi}
% \def\dodoprocesslocalsetups
-% {\@EA\processcommalist\@EA[\tobeprocessedsetups]\dosetups}
+% {\expandafter\processcommalist\expandafter[\tobeprocessedsetups]\syst_setups}
% setups=S1
% setups=lua(S2)
@@ -273,16 +365,34 @@
{\ctxcommand{autosetups("#1")}}
\edef\setupwithargument#1% saves a few expansions
- {\noexpand\csname\??su:\noexpand\ifcsname\??su:#1\endcsname#1\noexpand\else\letterpercent\noexpand\fi\endcsname}
+ {\noexpand\csname\??setup:\noexpand\ifcsname\??setup:#1\endcsname#1\noexpand\else\letterpercent\noexpand\fi\endcsname}
-\let\directsetup\dosetups
-\let\texsetup \dosetups % nicer than \directsetup and more en par with xmlsetup and luasetup
+\let\directsetup\syst_setups
+\let\texsetup \syst_setups % nicer than \directsetup and more en par with xmlsetup and luasetup
+
+\unexpanded\def\doifsetupselse#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
-\def\doifsetupselse#1% to be done: grid
- {\doifdefinedelse{\??su:#1}} % doto: ifcsname
+\unexpanded\def\doifsetups#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\unexpanded\def\doifnotsetups#1% to be done: grid
+ {\ifcsname\??setup:#1\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
% \startluasetups oeps
-% tex.print("DONE")
+% context("DONE")
% a = 1
% b = 1
% \stopluasetups
@@ -302,44 +412,46 @@
% \xmlsetup{123}{zzz}
%
% \startbuffer[what]
-% tex.print("DONE")
+% context("DONE")
% \stopbuffer
%
% \startbuffer
-% tex.print("MORE")
+% context("MORE")
% \stopbuffer
%
% \ctxluabuffer[what]
%
% \ctxluabuffer
-\newtoks\everydefinesetups \appendtoks
+\newtoks\t_syst_setups_tex \appendtoks
\catcode\endoflineasciicode \ignorecatcode
-\to \everydefinesetups
+\to \t_syst_setups_tex
-\newtoks\everydefinelocalsetups \appendtoks
+\newtoks\t_syst_setups_loc \appendtoks
\catcode\endoflineasciicode \ignorecatcode
-\to \everydefinelocalsetups
+\to \t_syst_setups_loc
-\newtoks\everydefinerawsetups \appendtoks
+\newtoks\t_syst_setups_raw \appendtoks
% nothing
-\to \everydefinerawsetups
+\to \t_syst_setups_raw
-\newtoks\everydefinexmlsetups \appendtoks
+\newtoks\t_syst_setups_xml \appendtoks
\catcode\endoflineasciicode\ignorecatcode
\catcode\barasciicode \othercatcode
-\to \everydefinexmlsetups
+\to \t_syst_setups_xml
-\newtoks\everydefineluasetups \appendtoks
+\newtoks\t_syst_setups_lua \appendtoks
\obeylualines
\obeyluatokens
-\to \everydefineluasetups
+\to \t_syst_setups_lua
+
+% Is doglobal still relevant? Maybe always global? Or never? Anyway, it will become obsolete.
-\unexpanded\def\startluasetups {\begingroup\doifnextoptionalelse\dostartluasetupsA \dostartluasetupsB }
-\unexpanded\def\startxmlsetups {\begingroup\doifnextoptionalelse\dostartxmlsetupsA \dostartxmlsetupsB }
-\unexpanded\def\startrawsetups {\begingroup\doifnextoptionalelse\dostartrawsetupsA \dostartrawsetupsB }
-\unexpanded\def\startlocalsetups{\begingroup\doifnextoptionalelse\dostartlocalsetupsA\dostartlocalsetupsB}
-\unexpanded\def\startsetups {\begingroup\doifnextoptionalelse\dostartsetupsA \dostartsetupsB }
+\unexpanded\def\startluasetups {\begingroup\doifnextoptionalelse\syst_setups_start_lua_a\syst_setups_start_lua_b}
+\unexpanded\def\startxmlsetups {\begingroup\doifnextoptionalelse\syst_setups_start_xml_a\syst_setups_start_xml_b}
+\unexpanded\def\startrawsetups {\begingroup\doifnextoptionalelse\syst_setups_start_raw_a\syst_setups_start_raw_b}
+\unexpanded\def\startlocalsetups{\begingroup\doifnextoptionalelse\syst_setups_start_loc_a\syst_setups_start_loc_b}
+\unexpanded\def\startsetups {\begingroup\doifnextoptionalelse\syst_setups_start_tex_a\syst_setups_start_tex_b}
\let\stopluasetups \relax
\let\stopxmlsetups \relax
@@ -347,59 +459,62 @@
\let\stoplocalsetups \relax
\let\stopsetups \relax
-\def\dodostartluasetups #1#2#3\stopluasetups {\endgroup\dodoglobal\long\@EA\def\csname\??su#1:#2\@EA\endcsname\@EA##\@EA1\@EA{#3}}
-\def\dodostartxmlsetups #1#2#3\stopxmlsetups {\endgroup\dodoglobal\long\@EA\def\csname\??su#1:#2\@EA\endcsname\@EA##\@EA1\@EA{#3}}
-\def\dodostartrawsetups #1#2#3\stoprawsetups {\endgroup\dodoglobal\long\@EA\def\csname\??su#1:#2\@EA\endcsname\@EA##\@EA1\@EA{#3}}
-\def\dodostartlocalsetups #1#2#3\stoplocalsetups{\endgroup\dodoglobal\long\@EA\def\csname\??su#1:#2\@EA\endcsname\@EA##\@EA1\@EA{#3}}
-\def\dodostartsetups #1#2#3\stopsetups {\endgroup\dodoglobal\long\@EA\def\csname\??su#1:#2\@EA\endcsname\@EA##\@EA1\@EA{#3}}
-
-\def\dostartluasetups {\ifsecondargument\@EA\dostartluasetupsC \else\@EA\dostartluasetupsD \fi}
-\def\dostartxmlsetups {\ifsecondargument\@EA\dostartxmlsetupsC \else\@EA\dostartxmlsetupsD \fi}
-\def\dostartrawsetups {\ifsecondargument\@EA\dostartrawsetupsC \else\@EA\dostartrawsetupsD \fi}
-\def\dostartlocalsetups {\ifsecondargument\@EA\dostartlocalsetupsC\else\@EA\dostartlocalsetupsD\fi}
-\def\dostartsetups {\ifsecondargument\@EA\dostartsetupsC \else\@EA\dostartsetupsD \fi}
-
-\def\dostartluasetupsA {\the\everydefineluasetups \dodoubleempty\dostartluasetups} % [ ] delimited
-\def\dostartxmlsetupsA {\the\everydefinexmlsetups \dodoubleempty\dostartxmlsetups} % [ ] delimited
-\def\dostartrawsetupsA {\the\everydefinerawsetups \dodoubleempty\dostartrawsetups} % [ ] delimited
-\def\dostartlocalsetupsA {\the\everydefinelocalsetups\dodoubleempty\dostartlocalsetups} % [ ] delimited
-\def\dostartsetupsA {\the\everydefinesetups \dodoubleempty\dostartsetups} % [ ] delimited
-
-% empty preserves inner {} (is removed by the \@EA{#3})
-
-\def\dostartluasetupsB #1 {\the\everydefineluasetups \dodostartluasetups \empty{#1}\empty} % space delimited
-\def\dostartxmlsetupsB #1 {\the\everydefinexmlsetups \dodostartxmlsetups \empty{#1}\empty} % space delimited
-\def\dostartrawsetupsB #1 {\the\everydefinerawsetups \dodostartrawsetups \empty{#1}\empty} % space delimited
-\def\dostartlocalsetupsB #1 {\the\everydefinelocalsetups\dodostartlocalsetups\empty{#1}\empty} % space delimited
-\def\dostartsetupsB #1 {\the\everydefinesetups \dodostartsetups \empty{#1}\empty} % space delimited
-
-\def\dostartluasetupsC [#1][#2]{\the\everydefineluasetups \dodostartluasetups {#1}{#2}\empty} % [..] [..]
-\def\dostartxmlsetupsC [#1][#2]{\the\everydefinexmlsetups \dodostartxmlsetups {#1}{#2}\empty} % [..] [..]
-\def\dostartrawsetupsC [#1][#2]{\the\everydefinerawsetups \dodostartrawsetups {#1}{#2}\empty} % [..] [..]
-\def\dostartlocalsetupsC[#1][#2]{\the\everydefinelocalsetups\dodostartlocalsetups{#1}{#2}\empty} % [..] [..]
-\def\dostartsetupsC [#1][#2]{\the\everydefinesetups \dodostartsetups {#1}{#2}\empty} % [..] [..]
-
-\def\dostartluasetupsD [#1][#2]{\the\everydefineluasetups \dodostartluasetups \empty{#1}\empty} % [..]
-\def\dostartxmlsetupsD [#1][#2]{\the\everydefinexmlsetups \dodostartxmlsetups \empty{#1}\empty} % [..]
-\def\dostartrawsetupsD [#1][#2]{\the\everydefinerawsetups \dodostartrawsetups \empty{#1}\empty} % [..]
-\def\dostartlocalsetupsD[#1][#2]{\the\everydefinelocalsetups\dodostartlocalsetups\empty{#1}\empty} % [..]
-\def\dostartsetupsD [#1][#2]{\the\everydefinesetups \dodostartsetups \empty{#1}\empty} % [..]
-
-\def\luasetup#1{\ctxlua{\dosetups{#1}}}
+\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}
+
+\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} % [..]
+
+\def\luasetup#1{\ctxlua{\syst_setups{#1}}}
% % % %
\def\systemsetupsprefix{*}
-\def\systemsetups#1{\dosetups{\systemsetupsprefix#1}}
+\def\systemsetups#1{\syst_setups{\systemsetupsprefix#1}}
\def\resetsetups[#1]% see x-fo for usage
- {\ifcsname\??su\ifgridsnapping\v!grid\fi:#1\endcsname
- \dodoglobal\letbeundefined{\??su\ifgridsnapping\v!grid\fi:#1}%
+ {\ifcsname\??setup\ifgridsnapping\v!grid\fi:#1\endcsname
+ \dodoglobal\letbeundefined{\??setup\ifgridsnapping\v!grid\fi:#1}%
\else
- \dodoglobal\letbeundefined{\??su:#1}%
+ \dodoglobal\letbeundefined{\??setup:#1}%
\fi}
-
+
+\def\showsetupsdefinition[#1]%
+ {\showvalue{\??setup:#1}} % temp hack for debugging
+
%D \macros
%D {setvariables,getvariable,getvariabledefault}
%D
@@ -412,40 +527,40 @@
%D \setvariables[xx][titletitel=e]
%D \stoptyping
-\def\??vars{@@vars}
+\installcorenamespace{variables}
-\def\setvariables {\dotripleargument\dosetvariables[\getrawparameters ]}
-\def\setevariables{\dotripleargument\dosetvariables[\getraweparameters]}
-\def\setgvariables{\dotripleargument\dosetvariables[\getrawgparameters]}
-\def\setxvariables{\dotripleargument\dosetvariables[\getrawxparameters]}
+\unexpanded\def\setvariables {\dotripleargument\syst_variables_set[\getrawparameters ]}
+\unexpanded\def\setevariables{\dotripleargument\syst_variables_set[\getraweparameters]}
+\unexpanded\def\setgvariables{\dotripleargument\syst_variables_set[\getrawgparameters]}
+\unexpanded\def\setxvariables{\dotripleargument\syst_variables_set[\getrawxparameters]}
-\def\globalsetvariables % obsolete
- {\dotripleargument\dosetvariables[\globalgetrawparameters]}
+\unexpanded\def\globalsetvariables % obsolete
+ {\dotripleargument\syst_variables_set[\globalgetrawparameters]}
-\long\def\dosetvariables[#1][#2][#3]% tricky, test on s-pre-60
+\def\syst_variables_set[#1][#2][#3]% tricky, test on s-pre-60
{\errorisfataltrue
\doifelse{#2}\currentvariableclass
- {#1[\??vars:#2:][#3]}%
+ {#1[\??variables#2:][#3]}%
{\pushmacro\currentvariableclass
\def\currentvariableclass{#2}%
\getvariable{#2}\s!reset
- #1[\??vars:#2:][#3]%
+ #1[\??variables#2:][#3]%
\getvariable{#2}\s!set
\popmacro\currentvariableclass}%
\errorisfatalfalse}
-\long\def\setvariable #1#2#3{\long\expandafter\def \csname\??vars:#1:#2\endcsname{#3}}
-\long\def\setevariable#1#2#3{\long\expandafter\edef\csname\??vars:#1:#2\endcsname{#3}}
-\long\def\setgvariable#1#2#3{\long\expandafter\gdef\csname\??vars:#1:#2\endcsname{#3}}
-\long\def\setxvariable#1#2#3{\long\expandafter\xdef\csname\??vars:#1:#2\endcsname{#3}}
+\unexpanded\def\setvariable #1#2#3{\expandafter\def \csname\??variables#1:#2\endcsname{#3}}
+\unexpanded\def\setevariable#1#2#3{\expandafter\edef\csname\??variables#1:#2\endcsname{#3}}
+\unexpanded\def\setgvariable#1#2#3{\expandafter\gdef\csname\??variables#1:#2\endcsname{#3}}
+\unexpanded\def\setxvariable#1#2#3{\expandafter\xdef\csname\??variables#1:#2\endcsname{#3}}
\def\getvariable#1#2%
{\csname
- \ifcsname\??vars:#1:#2\endcsname\??vars:#1:#2\else\s!empty\fi
+ \ifcsname\??variables#1:#2\endcsname\??variables#1:#2\else\s!empty\fi
\endcsname}
\def\showvariable#1#2%
- {\showvalue{\ifcsname\??vars:#1:#2\endcsname\??vars:#1:#2\else\s!empty\fi}}
+ {\showvalue{\ifcsname\??variables#1:#2\endcsname\??variables#1:#2\else\s!empty\fi}}
\let\currentvariableclass\empty
@@ -454,20 +569,22 @@
%D
%D I'll probably forget that this on exists.
+\let\m_syst_variables_temp\empty
+
\def\checkvariables
- {\dodoubleargument\docheckvariables}
+ {\dodoubleargument\syst_variables_check}
-\def\docheckvariables
- {\dogetparameters\docheckrawvalue}
+\def\syst_variables_check
+ {\dogetparameters\syst_variables_check_value}
-\long\def\docheckrawvalue#1#2#3%
- {\ifcsname\??vars:#1:#2\endcsname
- \edef\checkedrawvalue{\csname\??vars:#1:#2\endcsname}%
- \ifx\checkedrawvalue\empty
- \long\expandafter\def\csname\??vars:#1:#2\endcsname{#3}%
+\def\syst_variables_check_value#1#2#3%
+ {\ifcsname\??variables#1:#2\endcsname
+ \edef\m_syst_variables_temp{\csname\??variables#1:#2\endcsname}%
+ \ifx\m_syst_variables_temp\empty
+ \expandafter\def\csname\??variables#1:#2\endcsname{#3}%
\fi
\else
- \long\expandafter\def\csname\??vars:#1:#2\endcsname{#3}%
+ \expandafter\def\csname\??variables#1:#2\endcsname{#3}%
\fi}
%D \macros
@@ -475,55 +592,37 @@
%D
%D A few trivial macros:
-\def\doifelsevariable#1#2%
- {\ifcsname\??vars:#1:#2\endcsname
+\unexpanded\def\doifelsevariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\def\doifvariable#1#2%
- {\ifcsname\??vars:#1:#2\endcsname
+\unexpanded\def\doifvariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-\def\doifnotvariable#1#2%
- {\ifcsname\??vars:#1:#2\endcsname
+\unexpanded\def\doifnotvariable#1#2%
+ {\ifcsname\??variables#1:#2\endcsname
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
\def\getvariabledefault#1#2% #3% can be command, so no ifcsname here
- {\executeifdefined{\??vars:#1:#2}}% {#3}
-
-% \unexpanded\def\setupenv{\dodoubleargument\rawgetparameters[\??en]}
-%
-% \def\doifenvelse#1{\doifdefinedelse{\??en#1}} % speed up
-% \def\doifenv #1{\doifdefined {\??en#1}} % speed up
-% \def\doifnotenv #1{\doifundefined {\??en#1}} % speed up
-%
-% \def\env#1{\csname\??en#1\endcsname}
-%
-% \def\envvar#1#2%
-% {\ifcsname\??en#1\endcsname
-% \csname\??en#1\endcsname\else#2%
-% \fi}
-%
-% low level change, now also accessible as \getvariable
-% {environment}{...}; the next macros will become obsolete
-% some day in favor of normal variables in the environment
-% namespace
-
-\def\s!environment{environment}
-
-\unexpanded\def\setupenv {\dotripleargument\dosetvariables[\getrawparameters][\s!environment]}
-\def\doifenvelse{\doifelsevariable \s!environment}
-\def\doifenv {\doifvariable \s!environment}
-\def\doifnotenv {\doifnotvariable \s!environment}
-\def\env {\getvariable \s!environment}
-\def\envvar {\getvariabledefault\s!environment}
+ {\executeifdefined{\??variables#1:#2}}% {#3}
+
+\unexpanded\def\setupenv
+ {\dotripleargument\syst_variables_set[\getrawparameters][\s!environment]}
+
+\unexpanded\def\doifenvelse{\doifelsevariable \s!environment}
+\unexpanded\def\doifenv {\doifvariable \s!environment}
+\unexpanded\def\doifnotenv {\doifnotvariable \s!environment}
+\def\env {\getvariable \s!environment}
+\def\envvar {\getvariabledefault\s!environment}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-fil.mkii b/Master/texmf-dist/tex/context/base/core-fil.mkii
index 0355920c778..6b0d8caf56d 100644
--- a/Master/texmf-dist/tex/context/base/core-fil.mkii
+++ b/Master/texmf-dist/tex/context/base/core-fil.mkii
@@ -5,7 +5,7 @@
%D subtitle=File Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-fil.mkiv b/Master/texmf-dist/tex/context/base/core-fil.mkiv
deleted file mode 100644
index 263030a9b75..00000000000
--- a/Master/texmf-dist/tex/context/base/core-fil.mkiv
+++ /dev/null
@@ -1,243 +0,0 @@
-%D \module
-%D [ file=core-fil,
-%D version=1997.11.15,
-%D title=\CONTEXT\ Core Macros,
-%D subtitle=File Support,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 / File Support}
-
-\unprotect
-
-%D \macros
-%D {definefilesynonym}
-%D
-%D One of the problems with loading files is that their names
-%D can depend on the interface language. We therefore need a
-%D method to define filesynonyms. The actual synonyms are
-%D 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
-
-% will be redone in mkiv
-
-\unexpanded\def\definefilesynonym
- {\dodoubleempty\dodefinefilesynonym}
-
-\def\dodefinefilesynonym[#1][#2]%
- {\ifcsname\??fs#1\endcsname
- \doifnotvalue{\??fs#1}{#2}{\showmessage\m!files1{#1 (#2),\getvalue{\??fs#1}}}%
- \fi
- \doifelse{#1}{#2}{\letbeundefined{\??fs#1}{#2}}{\setevalue{\??fs#1}{#2}}}
-
-%D \macros
-%D {definefilefallback}
-
-\unexpanded\def\definefilefallback
- {\dodoubleargument\dodefinefilefallback}
-
-\def\dodefinefilefallback[#1][#2]%
- {\doifnotfile{#1}
- {\def\docommand##1{\doiffile{##1}{\definefilesynonym[#1][##1]\quitcommalist}}%
- \processcommalist[#2]\docommand}}
-
-%D \macros
-%D {truefilename}
-%D
-%D At the system level such a filename can be called upon by
-%D saying:
-%D
-%D \starttyping
-%D \truefilename{filename/filesynonym}
-%D \stoptyping
-%D
-%D The implementation shows that nesting is supported.
-
-\def\truefilename#1% this will move to lua
- {\ifcsname\??fs#1\endcsname\expandafter\truefilename\csname\??fs#1\endcsname\else#1\fi}
-
-%D \macros
-%D {usemodule}
-%D
-%D Most of \CONTEXT is preloaded in the format file. Some very
-%D domain specific typesetting topics are however dealt with in
-%D separate modules, e.g. typesetting of chemical structure
-%D formulas. These modules are loaded by:
-%D
-%D \showsetup{usemodule}
-%D
-%D More information on the specific modules can be found in
-%D their dedicated manuals. We use \type {\next} so that we
-%D can \type {\end} in modules.
-
-\def\dodousemodules#1#2%
- {\ctxcommand{usemodules("#1","#2","\truefilename{#2}")}}
-
-\def\usemodules
- {\dotripleempty\dousemodules}
-
-\def\dousemodules[#1][#2][#3]%
- {\pushmacro\currentmodule
- \pushmacro\currentmoduleparameters
- \let\currentmoduleparameters\empty
- \ifthirdargument
- \doifelsenothing{#2}
- {\let\next\relax}
- {\def\currentmoduleparameters{#3}%
- \def\next{\processcommalist[#2]{\dodousemodules{#1}}}}%
- \else\ifsecondargument
- \doifelsenothing{#2}
- {\let\next\relax}
- {\doifassignmentelse{#2}
- {\def\currentmoduleparameters{#2}%
- \def\next{\processcommalist[#1]{\dodousemodules{}}}}
- {\def\next{\processcommalist[#2]{\dodousemodules{#1}}}}}%
- \else
- \def\next{\processcommalist[#1]{\dodousemodules{}}}%
- \fi\fi
- \next
- \popmacro\currentmoduleparameters
- \popmacro\currentmodule}
-
-\let\currentmoduleparameters\empty
-\let\currentmodule \s!unknown
-
-\unexpanded\def\startmodule
- {\doifnextoptionalelse\dostartmodule\nostartmodule}
-
-\def\nostartmodule #1 %
- {\dostartmodule[#1]}
-
-\def\dostartmodule[#1]%
- {\pushmacro\currentmodule
- \pushmacro\currentmoduleparameters
- \def\currentmodule{#1}}
-
-\unexpanded\def\stopmodule
- {\popmacro\currentmoduleparameters
- \popmacro\currentmodule}
-
-\unexpanded\def\setupmodule
- {\dodoubleempty\dosetupmodule}
-
-\def\dosetupmodule[#1][#2]%
- {\scratchtoks\expandafter{\currentmoduleparameters}%
- \ifsecondargument
- \getparameters[\??md:#1:][#2]%
- \expanded{\getparameters[\??md:#1:][\the\scratchtoks]}%
- \else
- \getparameters[\??md:\currentmodule:][#1]%
- \expanded{\getparameters[\??md:\currentmodule:][\the\scratchtoks]}%
- \fi
- \let\currentmoduleparameters\empty}
-
-\def\moduleparameter #1#2{\executeifdefined{\??md:#1:#2}{}}
-\def\currentmoduleparameter#1{\executeifdefined{\??md:\currentmodule:#1}{}}
-
-\def\useluamodule [#1]{\ctxlua{dofile(resolvers.findctxfile("#1"))}}
-\def\luaenvironment #1 {\ctxlua{dofile(resolvers.findctxfile("#1"))}}
-
-% \usemodule[newmml]
-% \usemodule[newmml][a=b]
-% \usemodule[x][newmml]
-% \usemodule[x][newmml][a=b]
-%
-% \startmodule [mathml]
-% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars will be set afterwards
-% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars are now forgotten
-% \stopmodule
-
-% one can introduce test sections with:
-%
-% \enablemode[newmml:test:\currentmoduleparameter{test}]
-% \startmode[newmml:test:yes} ... \stopmode
-%
-% these will be ignored unless test=yes
-%
-% however, a better way is:
-
-\let\stopmoduletestsection\donothing
-
-\unexpanded\def\startmoduletestsection
- {\bgroup
- \setupmodule % we need to make sure that the vars are set
- \doifelse{\currentmoduleparameter\v!test}\v!yes
- {\egroup
- \writestatus{\currentmodule}{loading experimental code}}
- {\egroup
- \writestatus{\currentmodule}{skipping experimental code}%
- \gobbleuntil\stopmoduletestsection}}
-
-%D We also support a singular call, which saves us for
-%D frustrations when we do a typo.
-
-\let\usemodule\usemodules
-
-%D To save memory, we implement some seldomly used commands
-%D in a lazy way. Nota bene: such runtime definitions are
-%D global.
-%D
-%D \starttyping
-%D \fetchruntimecommand\showaccents{\f!encodingprefix ...}
-%D \stoptyping
-
-\def\fetchruntimecommand#1#2%
- {\def#1{\dofetchruntimecommand#1{#2}}}
-
-\def\dofetchruntimecommand#1#2%
- {\doifnotflagged{#2}
- {\let#1\undefined
- \startreadingfile
- \startnointerference % \bgroup
- \cleanupfeatures % better \setnormalcatcodes / test first
- \readfile{#2.\mksuffix}\donothing\donothing
- \stopnointerference % \egroup
- \stopreadingfile
- \doglobal\setflag{#2}}%
- \ifx#1\undefined
- \writestatus\m!system{command \string#1 not found in file #2}%
- \gdef#1{{\infofont[unknown command \string#1]}}%
- \fi
- #1}
-
-%D Experimental:
-
-\let\checkpreprocessor\relax
-
-%D To be documented and probably moved
-
-\def\documentresources{\@@erurl}
-
-\unexpanded\def\setupexternalresources
- {\dodoubleargument\getparameters[\??er]}
-
-\setupexternalresources
- [url=]
-
-%D This module will be perfected / changed / weeded.
-
-\let\protectbufferstrue\relax % will go away ... now in cont-sys.tex
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-fnt.mkii b/Master/texmf-dist/tex/context/base/core-fnt.mkii
index 9bc2a66f5a6..542ca062a68 100644
--- a/Master/texmf-dist/tex/context/base/core-fnt.mkii
+++ b/Master/texmf-dist/tex/context/base/core-fnt.mkii
@@ -5,7 +5,7 @@
%D subtitle=Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-fnt.mkiv b/Master/texmf-dist/tex/context/base/core-fnt.mkiv
index 90dd9349649..980f1a85cd8 100644
--- a/Master/texmf-dist/tex/context/base/core-fnt.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-fnt.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -54,13 +54,13 @@
%D
%D or
%D
-%D \startvoorbeeld
+%D \startexample
%D \getbuffer
-%D \stopvoorbeeld
+%D \stopexample
%D
%D \showsetup{stretched}
-\def\stretched#1%
+\unexpanded\def\stretched#1%
{\ifvmode\hbox to \hsize\else\ifinner\else\hbox\fi\fi
\bgroup\processtokens\relax\hss\relax{\hss\hss}{#1}\egroup}
@@ -92,14 +92,16 @@
%D
%D this one uses fixed skips and kerns.
%D
-%D \startvoorbeeld
+%D \startexample
%D \getbuffer
-%D \stopvoorbeeld
+%D \stopexample
%D
%D The default skip can be set with:
%D Given the following settings, the space is 1em by default:
+%D OBSOLETE:
+
\def\stretchedspacefactor{4}
\def\stretchedspaceamount{.25em}
\def\stretchedbreaktokens{.@/}
@@ -153,132 +155,4 @@
\fi}%
\fi}
-%D \macros
-%D {low, high, lohi, hilo}
-%D
-%D Although \TEX\ is pretty well aware of super- and
-%D subscripts, its mechanism is mainly tuned for math mode.
-%D The next few commands take care of script texts both modes.
-%D
-%D \startbuffer
-%D The higher\high{one goes} the lower\low{one drops}, or\lohi{yes}{no}?
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \getbuffer
-%D
-%D Note the different placement of \type {\lohi}, where we
-%D need a bit more space. The implementation looks a bit
-%D fuzzy, since some \type {\fontdimen}'s are involved to
-%D determine the optimal placement.
-
-\def\dodohighlow
- {\ifx\fontsize\empty
- \ifmmode
- \ifnum\fam<0 \tx \else \holamathfont \fi
- \else
- \tx
- \fi
- \else
- \tx
- \fi}
-
-\def\dohighlow#1#2#3#4#5% todo, named fontdimens
- {\dontleavehmode
- \bgroup
- \scratchdimen\ifdim\fontexheight\textfont2=1ex #2\textfont2\else #3ex\fi
- \advance\scratchdimen #4ex
- \kern.1ex
- \setbox\scratchbox\hbox{#1\scratchdimen\hbox{\dodohighlow#5}}%
- \ht\scratchbox\strutheight
- \dp\scratchbox\strutdepth
- \box\scratchbox
- \egroup}
-
-\unexpanded\def\high{\dohighlow\raise\mathsupnormal{.86}{0}}
-\unexpanded\def\low {\dohighlow\lower\mathsubnormal{.48}{0}}
-
-\unexpanded\def\lohi
- {\dosingleempty\dolohi}
-
-\unexpanded\def\hilo
- {\dosingleempty\dohilo}
-
-\def\dolohi[#1]#2#3%
- {\dontleavehmode
- \hbox
- {\setbox4\hbox{\dohighlow\lower\mathsubnormal{.48}{.1}{#2}}%
- \setbox6\hbox{\dohighlow\raise\mathsupnormal{.86}{.1}{#3}}%
- \doif{#1}{\v!left}
- {\ifdim\wd4<\wd6
- \setbox4\hbox to \wd6{\hss\box4}%
- \else
- \setbox6\hbox to \wd4{\hss\box6}%
- \fi}%
- \ifdim\wd4<\wd6
- \wd4=\zeropoint\box4\box6
- \else
- \wd6=\zeropoint\box6\box4
- \fi}}
-
-\def\dohilo[#1]#2#3%
- {\dolohi[#1]{#3}{#2}}
-
-%D You can provide an optional keyword \type {left}, in which
-%D case the super and subscripts will be aligned in a way that
-%D permits placement at the left of a word (which means that
-%D it will be right aligned).
-%D
-%D \startbuffer
-%D \lohi{aha}{ah} test \lohi{aha}{ah} test
-%D \lohi[left]{aha}{ah} test \lohi[left]{aha}{ah} test
-%D \lohi{aha}{ah} test\lohi{aha}{ah} test
-%D \lohi[left]{aha}{ah}test \lohi[left]{aha}{ah}test
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \getbuffer
-
-%D \macros
-%D {setupinitial,placeinitial,checkinitial}
-%D
-%D {\em To be documented.}
-%D
-%D \starttyping
-%D \setupinitial[state=start] \placeinitial \input tufte
-%D \stoptyping
-%D
-%D and
-%D
-%D \starttyping
-%D \def\bpar{\ifvmode\checkinitial\fi}
-%D \def\epar{\ifhmode\par\fi\checkinitial}
-%D \stoptyping
-
-% to do: more fine tuning
-
-\unexpanded\def\setupinitial
- {\dodoubleempty\getparameters[\??dc]}
-
-\definefontsynonym[Initial][Regular] % prefered initial identifier
-\definefontsynonym[initial][Initial] % internal but accepted too
-
-\setupinitial
- [\c!state=\v!stop,
- \c!location=\v!text,
- \c!n=3,
- \c!distance=.125em,
- \c!command=,
- \s!font=initial]
-
-\def\AutoDroppedCapsCommand{\NiceDroppedCaps\@@dccommand\@@dcfont\@@dcdistance\@@dcn}%
-
-\unexpanded\def\placeinitial
- {\doifelse\@@dclocation\v!margin{\chardef\DropMode\plusone}{\chardef\DropMode\zerocount}%
- \doif \@@dcstate\v!start{\ifcase\@@dcn\else\AutoDroppedCaps\fi}}
-
-\let\checkinitial\CheckDroppedCaps
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-gen.mkii b/Master/texmf-dist/tex/context/base/core-gen.mkii
index b6ab2a208c2..0d7fcebe00c 100644
--- a/Master/texmf-dist/tex/context/base/core-gen.mkii
+++ b/Master/texmf-dist/tex/context/base/core-gen.mkii
@@ -5,7 +5,7 @@
%D subtitle=General,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-gen.mkiv b/Master/texmf-dist/tex/context/base/core-gen.mkiv
deleted file mode 100644
index b6ab2a208c2..00000000000
--- a/Master/texmf-dist/tex/context/base/core-gen.mkiv
+++ /dev/null
@@ -1,166 +0,0 @@
-%D \module
-%D [ file=core-gen,
-%D version=1995.10.10,
-%D title=\CONTEXT\ Core Macros,
-%D subtitle=General,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 / General}
-
-\unprotect
-
-%D \macros
-%D {assigndimension,assignalfadimension}
-%D
-%D Hieronder worden enkele commando's gedefinieerd rond
-%D toekenningen. Allereerst een commando om waarden aan
-%D een \DIMENSION\ toe te kennen:
-%D
-%D \starttyping
-%D \assigndimension
-%D {<waarde>|klein|middel|groot|-klein|-middel|-groot|geen}
-%D {\dimension}
-%D {waarde klein}
-%D {waarde middel}
-%D {waarde groot}
-%D \stoptyping
-%D
-%D Hierbij krijgt de \DIMENSION\ \type{\dimension} een waarde
-%D afhankelijk van het meegegeven trefwoord.
-%D
-%D \startnarrower
-%D \startlines
-%D \type{(-)klein }\qquad (--) waarde klein
-%D \type{(-)middel}\qquad (--) waarde middel
-%D \type{(-)groot }\qquad (--) waarde groot
-%D \type{geen }\qquad 0pt
-%D \type{waarde }\qquad waarde
-%D \stoplines
-%D \stopnarrower
-%D
-%D Een trefwoord mag worden voorafgegaan door een \type{-}.
-%D Deze macro toont een voorbeeld van het gebruik van
-%D \type{\processaction} en constanten.
-%D
-%D Analoog aan het bovenstaande commando kennen we een
-%D commando om waarden toe te kennen aan een macro:
-%D
-%D \starttyping
-%D \assignalfadimension
-%D {<waarde>|klein|middel|groot|geen}
-%D {\macro}
-%D {waarde klein}
-%D {waarde middel}
-%D {waarde groot}
-%D \stoptyping
-
-% The third (optimized) version:
-
-\def\@ad@{@ad@}
-
-\setvalue{\@ad@ \v!none }{\zeropoint\gobblethreearguments}
-\setvalue{\@ad@ \v!big }{\thirdofthreearguments}
-\setvalue{\@ad@ \v!medium}{\secondofthreearguments}
-\setvalue{\@ad@ \v!small }{\firstofthreearguments}
-\setvalue{\@ad@-\v!big }{-\thirdofthreearguments}
-\setvalue{\@ad@-\v!medium}{-\secondofthreearguments}
-\setvalue{\@ad@-\v!small }{-\firstofthreearguments}
-
-\def\assigndimension#1#2% #3 #4 #5
- {#2=\ifcsname\@ad@#1\endcsname
- \csname\@ad@#1\expandafter\endcsname
- \else
- #1\expandafter\gobblethreearguments
- \fi}
-
-\def\@aa@{@aa@}
-
-\setvalue{\@aa@\v!none }{0\gobblethreearguments}
-\setvalue{\@aa@\v!big }{\thirdofthreearguments}
-\setvalue{\@aa@\v!medium}{\secondofthreearguments}
-\setvalue{\@aa@\v!small }{\firstofthreearguments}
-
-\def\assignalfadimension#1#2#3#4#5% #3#4#5 are single digits
- {\edef#2{\ifcsname\@aa@#1\endcsname
- \csname\@aa@#1\expandafter\endcsname
- \else
- #1\expandafter\gobblethreearguments
- \fi#3#4#5}}
-
-%D \macros
-%D {assignvalue}
-%D
-%D Een variant hierop is het commando:
-%D
-%D \starttyping
-%D \assignvalue
-%D {<waarde>|klein|middel|groot}
-%D {\macro}
-%D {waarde klein }
-%D {waarde middel}
-%D {waarde groot}
-%D \stoptyping
-%D
-%D Hierbij krijgt \type{\macro} een waarde afhankelijk van
-%D het meegegeven trefwoord:
-%D
-%D \startnarrower
-%D \startlines
-%D \type{klein }\qquad waarde klein
-%D \type{middel}\qquad waarde middel
-%D \type{groot }\qquad waarde groot
-%D \type{waarde}\qquad waarde
-%D \stoplines
-%D \stopnarrower
-%D
-%D Hier doet \type{geen} dus niet mee.
-
-\def\@av@{@av@}
-
-\letvalue{\@av@\v!big }\thirdofthreearguments
-\letvalue{\@av@\v!medium}\secondofthreearguments
-\letvalue{\@av@\v!small }\firstofthreearguments
-
-\def\assignvalue#1#2#3#4#5%
- {\edef#2{\ifcsname\@av@#1\endcsname
- \csname\@av@#1\expandafter\endcsname
- \else
- #1\expandafter\gobblethreearguments
- \fi{#3}{#4}{#5}}}
-
-%D \macros
-%D {assignwidth}
-%D
-%D Een breedte van een opgegeven tekst kan worden berekend en
-%D toegekend aan een \DIMENSION\ met:
-%D
-%D \starttyping
-%D \assignwidth
-%D {\dimension}
-%D {<waarde>|passend|ruim}
-%D {tekst}
-%D \stoptyping
-%D
-%D Dit commando sluit, evenals de bovenstaande
-%D \type{\assign}||commando's, aan op de wijze waarop
-%D in de andere \CONTEXT||modules toekenningen
-%D plaatsvinden. Bij \type{ruim} wordt de gemeten breedte
-%D met 1~em vermeerderd.
-
-\def\assignwidth#1#2#3#4%
- {\doifelsenothing{#2}
- {\setbox\scratchbox\hbox{#3}%
- #1\wd\scratchbox}
- {\doifinsetelse{#2}{\v!fit,\v!broad}
- {\setbox\scratchbox\hbox{#3}%
- #1\wd\scratchbox
- \doif{#2}\v!broad{\advance#1 #4}}%
- {#1=#2}}}%
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-ini.mkii b/Master/texmf-dist/tex/context/base/core-ini.mkii
index 69edf9735ff..04535bec6f6 100644
--- a/Master/texmf-dist/tex/context/base/core-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/core-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Additional Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-ini.mkiv b/Master/texmf-dist/tex/context/base/core-ini.mkiv
index c823c9594d6..de37bf08f42 100644
--- a/Master/texmf-dist/tex/context/base/core-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Additional Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -21,40 +21,59 @@
\everypar \emptytoks
\neverypar \emptytoks
-%appendtoks \flushnotes \to \everypar
-\appendtoks \synchronizesidefloats \to \everypar
-
-\appendtoks \checkindentation \to \everypar
-\appendtoks \showparagraphnumber \to \everypar
-\appendtoks \restoreinterlinepenalty \to \everypar
-%appendtoks \flushmargincontents \to \everypar
-%appendtoks \flushcommentanchors \to \everypar
-\appendtoks \flushnotes \to \everypar
-\appendtoks \synchronizenotes \to \everypar
-\appendtoks \OTRSETshowstatus \to \everypar
-\appendtoks \flushpostponedbookmark \to \everypar
-\appendtoks \registerparoptions \to \everypar
-\appendtoks \flushsyncpositions \to \everypar
-\appendtoks \flushpostponednodedata \to \everypar
-\appendtoks \dohandlerepeatdelimitedtext \to \everypar
-\appendtoks \insertparagraphintro \to \everypar
-
-\appendtoks \flushpostponedbookmark \to \neverypar
-\appendtoks \flushpostponedbookmark \to \everylistentry
-
-\appendtoks \flushnotes \to \everydisplay
-\appendtoks \adjustsidefloatdisplaylines \to \everydisplay
-
-\appendtoks \flushsyncpositions \to \everyheadstart
-
-\appendtoks \flushsyncresets \to \everyendoftextbody
-
-\appendtoks \ignorespaces \to \everybeginofpar
-
-\appendtoks \removeunwantedspaces \to \everyendofpar
-%appendtoks \strut \to \everyendofpar % option ?
-\appendtoks \flushsyncresets \to \everyendofpar
-%appendtoks \setlastlinewidth \to \everyendofpar % gone, will be done in lua
-\appendtoks \endgraf \to \everyendofpar
+\appendtoks
+ %flushnotes
+ \page_otr_command_synchronize_side_floats % an otr specific command
+ \checkindentation
+ \showparagraphnumber
+ \restoreinterlinepenalty
+ %flushmargincontents
+ %flushcommentanchors
+ \flushnotes
+ \synchronizenotes
+ \OTRSETshowstatus
+ \flushpostponedbookmark
+ \registerparoptions
+ %\flushsyncpositions
+ \flushpostponednodedata
+ \typo_delimited_repeat
+ \insertparagraphintro
+\to \everypar
+
+\appendtoks
+ \flushpostponedbookmark
+\to \neverypar
+
+\appendtoks
+ \flushpostponedbookmark
+\to \everylistentry
+
+\appendtoks
+ \flushnotes
+\to \everydisplay
+
+\appendtoks
+ \adjustsidefloatdisplaylines
+\to \everydisplay
+
+% \appendtoks
+% \flushsyncpositions
+% \to \everyheadstart
+
+% \appendtoks
+% \flushsyncresets
+% \to \everyendoftextbody
+
+\appendtoks
+ \ignorespaces
+\to \everybeginofpar
+
+\appendtoks
+ \removeunwantedspaces
+ %strut % option ?
+ % \flushsyncresets
+ %setlastlinewidth % gone, will be done in lua
+ \endgraf
+\to \everyendofpar
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-job.lua b/Master/texmf-dist/tex/context/base/core-job.lua
deleted file mode 100644
index f56d2ca1f2e..00000000000
--- a/Master/texmf-dist/tex/context/base/core-job.lua
+++ /dev/null
@@ -1,212 +0,0 @@
-if not modules then modules = { } end modules ['core-job'] = {
- version = 1.001,
- comment = "companion to core-job.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local texsprint, texprint, texwrite = tex.sprint, tex.print, tex.write
-local ctxcatcodes, texcatcodes = tex.ctxcatcodes, tex.texcatcodes
-local lower, format, find, gmatch, gsub, match = string.lower, string.format, string.find, string.gmatch, string.gsub, string.match
-local concat = table.concat
-
-local commands, resolvers, context = commands, resolvers, context
-
--- main code
-
-resolvers.maxreadlevel = 3
-
-directives.register("resolvers.maxreadlevel", function(v) resolvers.maxreadlevel = tonumber(v) or resolvers.maxreadlevel end)
-
-local report_examodes = logs.reporter("system","examodes") -- maybe another category
-
-local function exists(n)
- if io.exists(n) then
- return n
- else
- n = file.addsuffix(n,'tex')
- if io.exists(n) then
- return n
- end
- end
- return nil
-end
-
-function resolvers.findctxfile(name,maxreadlevel)
- if file.is_qualified_path(name) then
- return name
- else
- -- not that efficient, too many ./ lookups
- local n = "./" .. name
- local found = exists(n)
- if found then
- return found
- else
- for i=1,maxreadlevel or resolvers.maxreadlevel or 0 do
- n = "../" .. n
- found = exists(n)
- if found then
- return found
- end
- end
- end
- return resolvers.findfile(name) or ""
- end
-end
-
-function commands.maxreadlevel()
- texwrite(resolvers.maxreadlevel)
-end
-
-function commands.processfile(name,maxreadlevel)
- name = resolvers.findctxfile(name,maxreadlevel)
- if name ~= "" then
- texsprint(ctxcatcodes,format("\\input %s\\relax",name)) -- we need \input {name}
- end
-end
-
-function commands.doifinputfileelse(name,maxreadlevel)
- commands.doifelse(resolvers.findctxfile(name,maxreadlevel) ~= "")
-end
-
-function commands.locatefilepath(name,maxreadlevel)
- texsprint(texcatcodes,file.dirname(resolvers.findctxfile(name,maxreadlevel)))
-end
-
-function commands.usepath(paths,maxreadlevel)
- resolvers.registerextrapath(paths)
- texsprint(texcatcodes,concat(resolvers.instance.extra_paths or {}, ""))
-end
-
-function commands.usesubpath(subpaths,maxreadlevel)
- resolvers.registerextrapath(nil,subpaths)
- texsprint(texcatcodes,concat(resolvers.instance.extra_paths or {}, ""))
-end
-
-function commands.usezipfile(name,tree)
- if tree and tree ~= "" then
- resolvers.usezipfile(format("zip:///%s?tree=%s",name,tree))
- else
- resolvers.usezipfile(format("zip:///%s",name))
- end
-end
-
--- for the moment here, maybe a module
-
---~ <?xml version='1.0' standalone='yes'?>
---~ <exa:variables xmlns:exa='htpp://www.pragma-ade.com/schemas/exa-variables.rng'>
---~ <exa:variable label='mode:pragma'>nee</exa:variable>
---~ <exa:variable label='mode:variant'>standaard</exa:variable>
---~ </exa:variables>
-
-local function convertexamodes(str)
- local x = xml.convert(str)
- for e in xml.collected(x,"exa:variable") do
- local label = e.at and e.at.label
- if label and label ~= "" then
- local data = xml.text(e)
- local mode = match(label,"^mode:(.+)$")
- if mode then
- context.enablemode { format("%s:%s",mode,data) }
- end
- context.setvariable("exa:variables",label,(gsub(data,"([{}])","\\%1")))
- end
- end
-end
-
--- we need a system file option: ,. .. etc + paths but no tex lookup so resolvers.findfile is wrong here
-
-function commands.loadexamodes(filename)
- if not filename or filename == "" then
- filename = file.removesuffix(tex.jobname)
- end
- filename = resolvers.findfile(file.addsuffix(filename,'ctm')) or ""
- if filename ~= "" then
- report_examodes("loading %s",filename) -- todo: message system
- convertexamodes(io.loaddata(filename))
- else
- report_examodes("no mode file %s",filename) -- todo: message system
- end
-end
-
-local report_options = logs.reporter("system","options")
-
-function commands.logoptionfile(name)
- -- todo: xml if xml logmode
- local f = io.open(name)
- if f then
- logs.pushtarget("logfile")
- report_options("begin of optionfile")
- report_options()
- for line in f:lines() do
- report_options(line)
- end
- report_options()
- report_options("end of optionfile")
- f:close()
- logs.poptarget()
- end
-end
-
---~ set functions not ok and not faster on mk runs either
---~
---~ local function doifcommonelse(a,b)
---~ local ba = find(a,",")
---~ local bb = find(b,",")
---~ if ba and bb then
---~ for sa in gmatch(a,"[^ ,]+") do
---~ for sb in gmatch(b,"[^ ,]+") do
---~ if sa == sb then
---~ context.setvalue("commalistelement",sa)
---~ return true
---~ end
---~ end
---~ end
---~ elseif ba then
---~ for sa in gmatch(a,"[^ ,]+") do
---~ if sa == b then
---~ context.setvalue("commalistelement",b)
---~ return true
---~ end
---~ end
---~ elseif bb then
---~ for sb in gmatch(b,"[^ ,]+") do
---~ if a == sb then
---~ context.setvalue("commalistelement",sb)
---~ return true
---~ end
---~ end
---~ else
---~ if a == b then
---~ context.setvalue("commalistelement",a)
---~ return true
---~ end
---~ end
---~ context.letvalueempty("commalistelement")
---~ return false
---~ end
---~ local function doifinsetelse(a,b)
---~ local bb = find(b,",")
---~ if bb then
---~ for sb in gmatch(b,"[^ ,]+") do
---~ if a == sb then
---~ texsprint(ctxcatcodes,"\\def\\commalistelement{",a,"}")
---~ return true
---~ end
---~ end
---~ else
---~ if a == b then
---~ texsprint(ctxcatcodes,"\\def\\commalistelement{",a,"}")
---~ return true
---~ end
---~ end
---~ texsprint(ctxcatcodes,"\\let\\commalistelement\\empty")
---~ return false
---~ end
---~ function commands.doifcommon (a,b) commands.doif (doifcommonelse(a,b)) end
---~ function commands.doifnotcommon (a,b) commands.doifnot (doifcommonelse(a,b)) end
---~ function commands.doifcommonelse(a,b) commands.doifelse(doifcommonelse(a,b)) end
---~ function commands.doifinset (a,b) commands.doif (doifinsetelse(a,b)) end
---~ function commands.doifnotinset (a,b) commands.doifnot (doifinsetelse(a,b)) end
---~ function commands.doifinsetelse (a,b) commands.doifelse(doifinsetelse(a,b)) end
diff --git a/Master/texmf-dist/tex/context/base/core-job.mkii b/Master/texmf-dist/tex/context/base/core-job.mkii
index 2cd22e409a5..e2dc16031ff 100644
--- a/Master/texmf-dist/tex/context/base/core-job.mkii
+++ b/Master/texmf-dist/tex/context/base/core-job.mkii
@@ -5,7 +5,7 @@
%D subtitle=Job Handling,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-job.mkiv b/Master/texmf-dist/tex/context/base/core-job.mkiv
deleted file mode 100644
index db8d3ed933e..00000000000
--- a/Master/texmf-dist/tex/context/base/core-job.mkiv
+++ /dev/null
@@ -1,313 +0,0 @@
-%D \module
-%D [ file=core-job, % copied from main-001,
-%D version=1997.03.31,
-%D title=\CONTEXT\ Core Macros,
-%D subtitle=Job Handling,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 still to be split and documented.
-
-\writestatus{loading}{ConTeXt Core Macros / Job Handling}
-
-\unprotect
-
-\registerctxluafile{core-job}{1.001}
-
-\let \currentproject \empty
-\let \currentproduct \empty
-\let \currentenvironment \empty
-\let \currentcomponent \empty
-
-\let \loadedfiles \empty
-\let \processedfiles \empty
-
-\let \nomorefiles \relax
-
-\let \allinputpaths \empty
-\let \locatedfilepath \empty
-
-\newcount\textlevel
-\newcount\fileprocesslevel
-
-\setvalue{\c!file::0}{\jobname}
-
-\def\processedfile % is used in styles, don't change !
- {\getvalue{\c!file::\number\fileprocesslevel}}
-
-\def\dostarttextfile#1%
- {\global\advance\fileprocesslevel\plusone
- \setxvalue{\c!file::\number\fileprocesslevel}{#1}%
- \doglobal\addtocommalist{#1}\processedfiles}
-
-\def\dostoptextfile
- {\global\advance\fileprocesslevel\minusone}
-
-\def\processlocalfile#1#2%
- {#1{#2}\donothing{\readfile{#2}\donothing\donothing}}
-
-\def\processfile #1{\ctxcommand{processfile("#1")}}
-\def\doifinputfileelse #1{\ctxcommand{doifinputfileelse("#1")}}
-\def\locatefilepath #1{\edef\locatedfilepath{\ctxcommand{locatefilepath("#1")}}}
-\def\usepath [#1]{\edef\allinputpaths{\ctxcommand{usepath("#1")}}}
-\def\usesubpath [#1]{\edef\allinputpaths{\ctxcommand{usesubpath("#1")}}}
-\def\usezipfile {\dodoubleempty\dousezipfile}
-\def\dousezipfile[#1][#2]{\ctxcommand{usezipfile("#1","#2")}} % [filename] [optional subtree]
-\def\loadexamodes {\dosingleempty\doloadexamodes}
-\def\doloadexamodes [#1]{\ctxcommand{loadexamodes("#1")}}
-
-\def\registerfileinfo[#1#2]#3% geen \showmessage ?
- {\writestatus\m!system{#1#2 file #3 at line \the\inputlineno}}
-
-\def\doloadsystemfile#1% only mkiv files
- {\readsysfile{#1.\mksuffix}{\showmessage\m!system2{#1.\mksuffix}}\donothing}
-
-\def\loadsystemfiles
- {\doloadsystemfile\f!newfilename % new code, to be integrated at some point, plus fixes posted on the list
- \doloadsystemfile\f!locfilename % new code, somewhat experimental, not distributed (outside the dev group)
- \doloadsystemfile\f!expfilename % new code, very experimental, can be engine specific, mostly for me only
- \doloadsystemfile\f!sysfilename} % local settings, but probably not that good an idea to use
-
-%D We don't want multiple jobfiles to interfere.
-
-\def\loadoptionfile % todo : mark document.* tables as storage
- {\readjobfile{\jobname.\f!optionextension}
- {\writestatus\m!system{\jobname.\f!optionextension\space loaded}%
- \ctxcommand{logoptionfile("\jobname.\f!optionextension")}}%
- {\writestatus\m!system{no \jobname.\f!optionextension}}}
-
-% Most natural ...
-%
-% \def\doateverystarttext
-% {\the\everystarttext
-% \global\let\doateverystarttext\relax}
-%
-% ... most practical, since we can load env's in a
-% something.run file (nested \starttext's; see for
-% instance x-res-08, where we definitely want to
-% open the file!).
-
-\def\doateverystarttext
- {\the\everystarttext
- \global\everystarttext\emptytoks}
-
-\unexpanded\def\starttext
- {\doateverystarttext
- \ifcase\textlevel
- \registerfileinfo[begin]\jobfilename
- \fi
- \global\advance\textlevel\plusone}
-
-\unexpanded\def\stoptext
- {\global\advance\textlevel\minusone
- \ifnum\textlevel>\zerocount \else
- \flushfinallayoutpage % optional
- \page % anyway
- \the\everystoptext
- %\the\everybye %
- %\the\everygoodbye % == \end (new)
- %\expandafter\normalend %
-\ifcase\textlevel
- \registerfileinfo[end]\jobfilename
-\fi
- \expandafter\finalend
- \fi}
-
-\def\forcequitjob#1%
- {\writestatus\m!system{forcing quit: #1}%
- \batchmode
- \dorecurse\textlevel{\stoptext}
- \normalend}
-
-\let\autostoptext\relax
-
-\def\autostarttext
- {\ifcase\textlevel
- \starttext
- \writestatus\m!system{auto \string\starttext..\string\stoptext}%
- \let\autostoptext\stoptext
- \fi}
-
-\def\finalend
- {\ifnum\textlevel>\zerocount \else
- \the\everybye
- \the\everygoodbye
- \doifsometokselse\everynotabene{\writeline\the\everynotabene\writeline}\donothing
- \global\everybye \emptytoks % rather unneeded
- \global\everygoodbye\emptytoks % but for sure
- \expandafter\normalend
- \fi}
-
-\let\end\finalend
-
-\def\emergencyend
- {\writestatus\m!system{invalid \@EA\string\csname\e!start\v!text\endcsname...\@EA\string\csname\e!stop\v!text\endcsname\space structure}%
- \stoptext}
-
-\def\currentfile{\inputfilename}
-
-\def\doexecutefileonce#1%
- {\beforesplitstring#1\at.\to\currentfile
- \doifnotinset\currentfile\loadedfiles
- {\addtocommalist\currentfile\loadedfiles
- \doexecutefile{#1}}}
-
-\def\doexecutefile#1%
- {\registerfileinfo[begin]{#1}%
- \dostarttextfile{#1}%
- \processfile{#1}%
- \dostoptextfile
- \registerfileinfo[end]{#1}}
-
-\def\donotexecutefile#1%
- {}
-
-\unexpanded\def\project {\doifnextoptionalelse\useproject \redoproject}
-\unexpanded\def\environment{\doifnextoptionalelse\useenvironment\redoenvironment}
-\unexpanded\def\product {\doifnextoptionalelse\useproduct \redoproduct}
-\unexpanded\def\component {\doifnextoptionalelse\usecomponent \redocomponent}
-
-\def\redoproject #1 {\useproject [#1]}
-\def\redoenvironment #1 {\useenvironment[#1]}
-\def\redoproduct #1 {\useproduct [#1]}
-\def\redocomponent #1 {\usecomponent [#1]}
-
-\def\useproject[#1]%
- {}
-
-\def\useenvironment[#1]% maybe commalist
- {\pushmacro\dostartenvironment % we could use a depth counter
- \pushmacro\stopenvironment
- \unexpanded\def\dostartenvironment[##1]{}%
- \let\stopenvironment\relax
- \startreadingfile
- \doexecutefileonce{#1}
- \stopreadingfile
- \popmacro\stopenvironment
- \popmacro\dostartenvironment}
-
-\def\useproduct[#1]%
- {}
-
-\def\usecomponent[#1]%
- {\dostarttextfile{#1}%
- \processfile{#1}%
- \dostoptextfile}
-
-\newcount\filelevel
-
-\let\currentcomponent \v!text
-\let\currentcomponentpath\f!currentpath
-
-\def\donextlevel#1#2#3#4#5#6#7\\% we will move this to lua
- {\pushmacro\currentcomponent
- \pushmacro\currentcomponentpath
- \let\currentcomponent#1%
- \setsystemmode\currentcomponent
- \splitfilename{#1}%
- \ifx\splitoffpath\empty
- \let\currentcomponentpath\f!currentpath
- \else
- \let\currentcomponentpath\splitoffpath
- \fi
- \beforesplitstring#7\at.\to#2\relax % can become path + base
- \ifcase\filelevel\relax
- \starttext
- \unexpanded\def\useproject [##1]{#3{##1}}%
- \unexpanded\def\useenvironment[##1]{#4{##1}}%
- \unexpanded\def\useproduct [##1]{#5{##1}}%
- \unexpanded\def\usecomponent [##1]{#6{##1}}%
- \fi
- \advance\filelevel\plusone
- \addtocommalist{#1}\loadedfiles}
-
-\def\doprevlevel
- {\popmacro\currentcomponentpath
- \popmacro\currentcomponent
- \setsystemmode\currentcomponent
- \ifnum\filelevel=\plusone
- \expandafter\stoptext
- \else
- \advance\filelevel\minusone
- \expandafter\endinput
- \fi}
-
-\unexpanded\def\startproject {\doifnextoptionalelse\dostartproject \redostartproject}
-\unexpanded\def\startenvironment{\doifnextoptionalelse\dostartenvironment\redostartenvironment}
-\unexpanded\def\startproduct {\doifnextoptionalelse\dostartproduct \redostartproduct}
-\unexpanded\def\startcomponent {\doifnextoptionalelse\dostartcomponent \redostartcomponent}
-
-\def\redostartproject #1 {\dostartproject [#1]}
-\def\redostartenvironment #1 {\dostartenvironment[#1]}
-\def\redostartproduct #1 {\dostartproduct [#1]}
-\def\redostartcomponent #1 {\dostartcomponent [#1]}
-
-\def\dostartproject[#1]%
- {\donextlevel\v!project\currentproject
- \donotexecutefile\doexecutefileonce
- \doexecutefileonce\doexecutefile#1\\}
-
-\def\dostartproduct[#1]%
- {\doateverystarttext
- \donextlevel\v!product\currentproduct
- \doexecutefileonce\doexecutefileonce
- \donotexecutefile\doexecutefile#1\\}
-
-\def\dostartcomponent[#1]%
- {\doateverystarttext
- \donextlevel\v!component\currentcomponent
- \doexecutefileonce\doexecutefileonce
- \donotexecutefile\doexecutefile#1\\}
-
-\def\dostartenvironment[#1]%
- {\donextlevel\v!environment\currentenvironment
- \donotexecutefile\doexecutefileonce
- \donotexecutefile\donotexecutefile#1\\}
-
-% \startproject test
-% 1: \startmode[*project] project \stopmode \endgraf
-% 2: \startmode[*product] product \stopmode \endgraf
-% \stopproject
-
-\unexpanded\def\stopproject {\doprevlevel}
-\unexpanded\def\stopproduct {\doprevlevel}
-\unexpanded\def\stopcomponent {\doprevlevel}
-\unexpanded\def\stopenvironment{\doprevlevel}
-
-% more or less replaced by modes
-
-\setvalue{\e!start\v!localenvironment}[#1]%
- {\let\loadedlocalenvironments\empty
- \def\docommand##1%
- {\beforesplitstring##1\at.\to\someevironment
- \addtocommalist\someevironment\loadedlocalenvironments}%
- \processcommalist[#1]\docommand
- \doifcommonelse{\currentproject,\currentproduct,\currentcomponent,\currentenvironment}\loadedlocalenvironments
- {\letvalue{\e!stop\v!localenvironment}\relax}
- {\grabuntil{\e!stop\v!localenvironment}\gobbleoneargument}}
-
-\setvalue{\v!localenvironment}{\doifnextoptionalelse\uselocalenvironment\redolocalenvironment}
-
-\def\redolocalenvironment#1 {\uselocalenvironment[#1]}
-
-\def\uselocalenvironment[#1]{\doexecutefileonce{#1}}
-
-\neverypar\emptytoks % here ?
-
-% \appendtoks \flushnotes \to \everypar
-% \appendtoks \synchronizesidefloats \to \everypar
-% \appendtoks \checkindentation \to \everypar
-% \appendtoks \showparagraphnumber \to \everypar
-% %appendtoks \flushmargincontents \to \everypar
-% \appendtoks \flushcommentanchors \to \everypar
-% \appendtoks \synchronizenotes \to \everypar
-
-% \appendtoks \flushnotes \to \everydisplay
-% \appendtoks \adjustsidefloatdisplaylines \to \everydisplay
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-mis.mkii b/Master/texmf-dist/tex/context/base/core-mis.mkii
index 6d77ef18eca..c44d61cbc3e 100644
--- a/Master/texmf-dist/tex/context/base/core-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/core-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Miscelaneous,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-mis.mkiv b/Master/texmf-dist/tex/context/base/core-mis.mkiv
index 06ee5b6173d..5c364f3c462 100644
--- a/Master/texmf-dist/tex/context/base/core-mis.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-mis.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Miscelaneous,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,22 +13,7 @@
\writestatus{loading}{ConTeXt Core Macros / Misc Commands}
-% todo: kleur in legenda + letter
-
-% %D You would not expect the next macro in \CONTEXT,
-% %D wouldn't you? It's there to warn \LATEX\ users that
-% %D something is wrong.
-% %D
-% %D Obsolete now:
-% %
-% % \def\documentstyle{\showmessage\m!system3\empty\stoptekst}
-% %
-% % \let\documentclass=\documentstyle
-% %D \macros
-% %D {simplifiedcommands, simplifycommands}
-% %D
-% %D I first needed this simplification in bookmarks. Users can
-% %D add their own if needed.
+% needs to be redone
\unprotect
@@ -59,15 +44,6 @@
% THIS WAS MAIN-002.TEX
-%\def\checkinterlineskip
-% {\ifvmode
-% \ifdim\lastskip>\zeropoint
-% \nointerlineskip
-% \else\ifdim\lastkern>\zeropoint
-% \nointerlineskip
-% \fi\fi
-% \fi}
-
\def\horitems#1#2% #1=breedte #2=commandos
{\scratchdimen#1%
\divide\scratchdimen \nofitems
@@ -179,10 +155,7 @@
\setlocalhsize
\hsize\localhsize
\dontcomplain
- %\doifundefined{doitems\@@islocation}%
- % {\let\@@islocation\v!left}%
- %\getvalue{doitems\@@islocation}}
- \executeifdefined{doitems\@@islocation}{\let\@@islocation\v!left}}
+ \executeifdefined{doitems\@@islocation}{\getvalue{doitems\v!left}}}
\definecomplexorsimpleempty\items
@@ -196,11 +169,6 @@
\c!inbetween={\blank[\v!medium]},
\c!after=\blank]
-% Te zijner tijd [plaats=boven,onder,midden] implementeren,
-% in dat geval moet eerst de maximale hoogte worden bepaald.
-%
-% Overigens kan een en ander mooier met \halign.
-
% there is quite some historic balast in this mechanism, the next variant
% is a first cleanup
@@ -321,7 +289,9 @@
{\!!widtha\alhsize
\divide\!!widtha \alnsize}
{\!!widtha\paragraphcellmeter\alcounter\c!width}%
- \dostartattributes{\??al\currentparagraph\number\alcounter}\c!style\c!color\empty
+ \begingroup
+ \dousestylehashparameter{\??al\currentparagraph\number\alcounter}\c!style
+ \dousecolorhashparameter{\??al\currentparagraph\number\alcounter}\c!color
\doifelse{\paragraphcellmeter\alcounter\c!height}\v!fit
{\setbox\scratchbox\vtop}
{\setbox\scratchbox\vtop to \paragraphcellmeter\alcounter\c!height}%
@@ -361,7 +331,7 @@
\wd\scratchbox\!!widtha
\fi
\box\scratchbox
- \dostopattributes
+ \endgroup
\ifnum\alcounter<\paragraphparameter\c!n\relax
\@EA\doparagraphcell
\else
@@ -416,6 +386,8 @@
\paragraphparameter\c!after
\egroup}
+% Is this used at all?
+
\def\dosetuptab[#1]%
{\getparameters[\??ta]
[\c!headstyle=\v!normal,
@@ -442,674 +414,6 @@
\setuptab
[\c!location=\v!left]
-\unexpanded\def\celsius #1{#1\mathematics{^\circ}C}
-\unexpanded\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax}
-\unexpanded\def\fraction#1#2{\mathematics{#1\over#2}}
-
-% very dutch
-
-\unexpanded\def\graden {\mathematics{^\circ}}
-
-\def\bedragprefix {\euro\normalfixedspace}
-\def\bedragsuffix {}
-\def\bedragempty {\euro}
-
-\unexpanded\def\bedrag#1%
- {\strut\hbox\bgroup
- \let\normalfixedspace\nonbreakablespace
- \doifelsenothing{#1}
- {\bedragempty}
- {\bedragprefix\digits{#1}\bedragsuffix}%
- \egroup}
-
-% \definieeralineas[test][n=3]
-%
-% \stelalineasin[test][3][breedte=4cm,uitlijnen=links]
-%
-% \startopelkaar
-% \test hans \\ ton \\ \bedrag{1.000,--} \\
-% \test hans \\ ton \\ \bedrag{~.~~1,--} \\
-% \test hans \\ ton \\ \bedrag{~.~~1,~~} \\
-% \test hans \\ ton \\ \bedrag{~.100,--} \\
-% \test hans \\ ton \\ \subtot{1.000,--} \\
-% \test hans \\ ton \\ \bedrag{1.000,--} \\
-% \test hans \\ ton \\ \bedrag{1.000,--} \\
-% \test hans \\ ton \\ \totaal{1.000,--} \\
-% \test hans \\ ton \\ \bedrag{nihil,--} \\
-% \test hans \\ ton \\ \totaal{nihil,--} \\
-% \test hans \\ ton \\ \subtot{nihil,--} \\
-% \stopopelkaar
-
-\def\periodswidth {.5em}
-\def\periodsdefault{3} % was 5, but now it's like \unknown
-
-\unexpanded\def\periods
- {\dosingleempty\doperiods}
-
-\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.\hss}\hss}%
- \endgroup}
-
-\unexpanded\def\unknown
- {\periods\relax} % relax prevents lookahead for []
-
-% Example by Wolfgang Schuster on the context list:
-%
-% \unexpanded\def\fourdots{{\def\periodswidth{.3em}\periods[4]}}
-%
-% Hello\fourdots\ World\fourdots \par Hello\fourdots\ World.
-
-% compatibility macros
-
-\def\doorsnede
- {\hbox{\rlap/$\circ$} }
-
-\unexpanded\def\ongeveer
- {\mathematics\pm}
-
-\setnewconstant\boundarycharactermode\plusone
-
-\def\midboundarycharacter#1#2%
- {\ifcase\boundarycharactermode
- \or
- %\nobreak
- \hskip\hspaceamount\currentlanguage{#2}%
- \languageparameter#1%
- %\nobreak
- \hskip\hspaceamount\currentlanguage{#2}%
- \or
- \languageparameter#1%
- \fi
- \boundarycharactermode\plusone}
-
-\def\leftboundarycharacter#1#2%
- {\ifcase\boundarycharactermode
- \or
- \languageparameter#1%
- \nobreak
- \hskip\hspaceamount\currentlanguage{#2}%
- \or
- \languageparameter#1%
- \fi
- \boundarycharactermode\plusone}
-
-\def\rightboundarycharacter#1#2%
- {\ifcase\boundarycharactermode
- \or
- \prewordbreak %\nobreak
- \hskip\hspaceamount\currentlanguage{#2}%
- \languageparameter#1%
- \or
- \languageparameter#1%
- \fi
- \boundarycharactermode\plusone}
-
-% actually this is pretty old, but temporary moved here
-%
-% obsolete:
-
-\unexpanded\def\setuphyphenmark
- {\dodoubleargument\getparameters[\??kp]}
-
-\unexpanded\def\setuphyphenmark[#1]% sign=normal|wide
- {\dodoubleargument\getparameters[\??kp][#1]%
- \doifelse\@@kpsign {\v!normal}% was inset?
- {\let\textmodehyphen\normalhyphen \let\textmodehyphendiscretionary\normalhyphendiscretionary}
- {\let\textmodehyphen\composedhyphen\let\textmodehyphendiscretionary\composedhyphendiscretionary}}
-
-\setuphyphenmark[\c!sign=\v!wide]
-% % \setuphyphenmark[\c!sign=\v!normal]
-
-\definesymbol[\c!lefthyphen] [\languageparameter\c!lefthyphen]
-\definesymbol[\c!righthyphen] [\languageparameter\c!righthyphen]
-\definesymbol[\c!hyphen] [\languageparameter\c!hyphen]
-
-\def\normalhyphen
- {\hbox{\directsymbol\empty\c!hyphen}}
-
-\def\composedhyphen
- {\hbox{\directsymbol\empty\c!compoundhyphen}}
-
-\def\normalhyphendiscretionary
- {\discretionary
- {\hbox{\directsymbol\empty\c!righthyphen}}
- {\hbox{\directsymbol\empty\c!lefthyphen}}
- {\hbox{\directsymbol\empty\c!hyphen}}}
-
-\def\composedhyphendiscretionary
- {\discretionary
- {\hbox{\directsymbol\empty\c!rightcompoundhyphen}}
- {\hbox{\directsymbol\empty\c!leftcompoundhyphen}}
- {\hbox{\directsymbol\empty\c!compoundhyphen}}}
-
-\let\textmodehyphen \composedhyphen
-\let\textmodehyphendiscretionary\composedhyphendiscretionary
-
-\definesymbol[\c!leftcompoundhyphen] [\languageparameter\c!leftcompoundhyphen]
-\definesymbol[\c!rightcompoundhyphen] [\languageparameter\c!rightcompoundhyphen]
-\definesymbol[\c!compoundhyphen] [\languageparameter\c!compoundhyphen]
-
-\definehspace [sentence] [\zeropoint]
-\definehspace [intersentence] [.250em]
-
-\definesymbol
- [\c!midsentence]
- [\midboundarycharacter\c!midsentence{sentence}]
-
-\definesymbol
- [\c!leftsentence]
- [\leftboundarycharacter\c!leftsentence{sentence}]
-
-\definesymbol
- [\c!rightsentence]
- [\rightboundarycharacter\c!rightsentence{sentence}]
-
-\definesymbol
- [\c!leftsubsentence]
- [\leftboundarycharacter\c!leftsubsentence{sentence}]
-
-\definesymbol
- [\c!rightsubsentence]
- [\rightboundarycharacter\c!rightsubsentence{sentence}]
-
-\newsignal \subsentencesignal
-\newcount \subsentencelevel
-
-\let\beforesubsentence\donothing
-\let\aftersubsentence \donothing
-
-% todo: make this language option
-%
-% \def\beforesubsentence{\removeunwantedspaces}
-% \def\aftersubsentence {\ignorespaces}
-
-\def\midsentence
- {\symbol[\c!midsentence]}
-
-\def\beginofsubsentence
- {\beforesubsentence
- \ifdim\lastkern=\subsentencesignal
- \unskip
- \kern\hspaceamount\currentlanguage{intersentence}%
- \fi
- \global\advance\subsentencelevel\plusone
- \ifnum\subsentencelevel=\plusone
- \dontleavehmode % was \leaveoutervmode
- \fi
- \dostarttagged\t!subsentence\empty
- \symbol[\ifodd\subsentencelevel\c!leftsentence\else\c!leftsubsentence\fi]%
- }% \ignorespaces}
-
-\def\endofsubsentence % relax prevents space gobbling
- {\symbol[\ifodd\subsentencelevel\c!rightsentence\else\c!rightsubsentence\fi]%
- \dostoptagged
- \global\advance\subsentencelevel\minusone
- \unskip
- \kern\subsentencesignal\relax
- \aftersubsentence}
-
-\def\beginofsubsentencespacing % relax prevents space gobbling
- {\kern\subsentencesignal\relax}% \ignorespaces}
-
-\def\endofsubsentencespacing
- {\ifdim\lastkern=\subsentencesignal
- \unskip
- \hskip\hspaceamount\currentlanguage{intersentence}%
- % no good, actually language dependent:
-% \ignorespaces
- \else
- \unskip
- \fi}
-
-%D \startbuffer
-%D test |<|test |<|test|>| test|>| test \par
-%D test|<|test|<|test|>|test|>|test \par
-%D test |<||<|test|>||>| test \par
-%D test \directdiscretionary{<}test\directdiscretionary{>} test \par
-%D \stopbuffer
-%D
-%D \typebuffer
-%D \getbuffer
-
-\unexpanded\def\startsubsentence{\beginofsubsentence \prewordbreak\beginofsubsentencespacing}
-\unexpanded\def\stopsubsentence {\endofsubsentencespacing\prewordbreak\endofsubsentence}
-\unexpanded\def\subsentence {\groupedcommand\startsubsentence\stopsubsentence}
-
-\enableactivediscretionaries
-
-\definehspace [quotation] [\zeropoint]
-\definehspace [interquotation] [.125em]
-
-%definehspace [quote] [\zeropoint]
-%definehspace [speech] [\zeropoint]
-
-\definehspace [quote] [\hspaceamount\currentlanguage{quotation}]
-\definehspace [speech] [\hspaceamount\currentlanguage{quotation}]
-
-\definesymbol
- [\c!leftquotation]
- [\leftboundarycharacter\c!leftquotation{quotation}]
-
-\definesymbol
- [\c!rightquotation]
- [\rightboundarycharacter\c!rightquotation{quotation}]
-
-\definesymbol
- [\c!leftquote]
- [\leftboundarycharacter\c!leftquote{quote}]
-
-\definesymbol
- [\c!rightquote]
- [\rightboundarycharacter\c!rightquote{quote}]
-
-\definesymbol
- [\c!leftspeech]
- [\leftboundarycharacter\c!leftspeech{speech}]
-
-\definesymbol
- [\c!rightspeech]
- [\rightboundarycharacter\c!rightspeech{speech}]
-
-\definesymbol
- [\c!middlespeech]
- [\leftboundarycharacter\c!middlespeech{speech}]
-
-\appendtoks\def\quotation#1{"#1"}\to\simplifiedcommands
-\appendtoks\def\quote #1{'#1'}\to\simplifiedcommands
-
-%D The next features was so desperately needed by Giuseppe
-%D Bilotta that he made a module for it. Since this is a
-%D typical example of core functionality, I decided to extend
-%D the low level quotation macros in such a way that a speech
-%D feature could be build on top of it. The speech opening and
-%D closing symbols are defined per language. Italian is an
-%D example of a language that has them set.
-
-% this will replace the quotation and speed definitions
-
-\newsignal\delimitedtextsignal
-
-\let\currentdelimitedtext\s!unknown
-
-\def\delimitedtextlevel{\csname\??ci:\currentdelimitedtext:\c!level\endcsname}
-
-\def\doinitializetextlevel#1%
- {\ifcsname\??ci:#1:\c!level\endcsname
- \csname\??ci:#1:\c!level\endcsname\zerocount
- \else
- \expandafter\newcount\csname\??ci:#1:\c!level\endcsname
- \fi}
-
-\def\delimitedtextparameter#1% will be sped up
- {\executeifdefined{\??ci\currentdelimitedtext:\number\delimitedtextlevel#1}%
- {\executeifdefined{\??ci\currentdelimitedtext#1}%
- {\executeifdefined{\??ci#1}\empty}}}
-
-\unexpanded\def\definedelimitedtext
- {\dodoubleempty\dodefinedelimitedtext}
-
-\def\dodefinedelimitedtext[#1][#2]%
- {\doinitializetextlevel{#1}%
- \doifassignmentelse{#2}
- {\getparameters
- [\??ci#1]
- [\c!location=\v!margin, % \v!text \v!paragraph
- \c!spacebefore=,
- \c!spaceafter=\delimitedtextparameter\c!spacebefore,
- \c!style=\v!normal,
- \c!color=,
- \c!leftmargin=\zeropoint,
- \c!rightmargin=\delimitedtextparameter\c!leftmargin,
- \c!indentnext=\v!yes,
- \c!before=,
- \c!after=,
- \c!left=,
- \c!right=,
- %\c!level=0,
- \c!repeat=\v!no,
- \c!method=,
- #2]}%
- {\doifdefined{#2}
- {\copyparameters[\??ci#1][\??ci#2]
- [\c!location,\c!spacebefore,\c!spaceafter,\c!style,\c!color,
- \c!leftmargin,\c!rightmargin,\c!indentnext,
- \c!before,\c!after,\c!left,\c!right]}}%
- \doifsomething{#1}
- {\setuvalue{#1}{\delimitedtext[#1]}%
- \setvalue{\e!start#1}{\startdelimitedtext[#1]}%
- \setvalue{\e!stop #1}{\stopdelimitedtext}}}
-
-\unexpanded\def\setupdelimitedtext
- {\dotripleargument\dosetupdelimitedtext}
-
-\def\dosetupdelimitedtext[#1][#2][#3]% #2 = optional level
- {\ifthirdargument
- \getparameters[\??ci#1:#2][#3]%
- \else\ifsecondargument
- \getparameters[\??ci#1][#2]%
- \else
- \getparameters[\??ci][#1]%
- \fi\fi}
-
-\def\dorepeatdelimitedtext
- {\relax\ifcase\delimitedtextlevel\else
- \dohandledelimitedtext\c!middle % maybe better \dohandleleftdelimitedtext
- \fi}
-
-\let\dohandlerepeatdelimitedtext\relax
-
-\unexpanded\def\startdelimitedtext[#1]%
- {\bgroup
- \pushdelimitedtext{#1}%
- \dostarttagged\t!delimitedblock\currentdelimitedtext
- \doifelse{\delimitedtextparameter\c!method}\s!font
- {\def\dostopdelimitedtext
- {\removeunwantedspaces\ignoredelimitedtext\c!right}%
- \ignoredelimitedtext\c!left\ignorespaces}
- {\doifelse{\delimitedtextparameter\c!repeat}\v!yes
- {\let\dohandlerepeatdelimitedtext\dorepeatdelimitedtext}%
- {\let\dohandlerepeatdelimitedtext\relax}%
- \doifinsetelse{\delimitedtextparameter\c!location}{\v!paragraph,\v!margin}%
- {\dosingleempty\dostartdelimitedtextpar}\dostartdelimitedtexttxt}}
-
-\def\dostartdelimitedtextpar[#1]%
- {\let\dostopdelimitedtext\dostopdelimitedtextpar
- \doifsomething{\delimitedtextparameter\c!spacebefore}
- {\blank[\delimitedtextparameter\c!spacebefore]}%
- \delimitedtextparameter\c!before
- % nicer:
- % \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
- % \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
- % backward compatible:
- \doifelsenothing{#1}
- {\endgraf
- \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
- \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
- \let\dodostopdelimitedtextpar\endgraf}
- {\startnarrower[#1]\let\dodostopdelimitedtextpar\stopnarrower}%
- % so far
- % \dochecknextindentation{\??ci\currentdelimitedtext}% AM: not here
- \pushmacro\checkindentation
- \doifsomething{\delimitedtextparameter\c!indenting} % WS
- {\setupindenting[\delimitedtextparameter\c!indenting]}%
- \dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color\empty
- \leftdelimitedtextmark
- \ignorespaces}
-
-\def\dostopdelimitedtextpar
- {\removeunwantedspaces
- \removelastskip
- \rightdelimitedtextmark
- \dostopattributes
- \popmacro\checkindentation
- \dodostopdelimitedtextpar
- \delimitedtextparameter\c!after
- \doifsomething{\delimitedtextparameter\c!spaceafter}
- {\blank[\delimitedtextparameter\c!spaceafter]}%
- \dochecknextindentation{\??ci\currentdelimitedtext}% AM: here
- \dorechecknextindentation}% AM: This was missing!
-
-\def\dostartdelimitedtexttxt
- {\let\dostopdelimitedtext\dostopdelimitedtexttxt
- \dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color\empty
- \dohandleleftdelimitedtext\c!left
- \ignorespaces}
-
-\def\dostopdelimitedtexttxt
- {\removeunwantedspaces
- \dohandlerightdelimitedtext\c!right
- \dostopattributes}
-
-\unexpanded\def\stopdelimitedtext
- {\dostopdelimitedtext
- \dostoptagged
- \popdelimitedtext
- \egroup}
-
-\def\pushdelimitedtext#1%
- {\globalpushmacro\currentdelimitedtext
- \def\currentdelimitedtext{#1}%
- \global\advance\delimitedtextlevel\plusone}
-
-\def\popdelimitedtext
- {\global\advance\delimitedtextlevel\minusone
- \globalpopmacro\currentdelimitedtext}
-
-\unexpanded\def\delimitedtext[#1]%
- {\dontleavehmode % following ones can be omited
- \pushdelimitedtext{#1}%
- \doifelse{\delimitedtextparameter\c!method}\s!font
- {\dofontdrivendelimited}
- {\doifinsetelse{\delimitedtextparameter\c!location}{\v!paragraph,\v!margin}%
- \dodelimitedtextpar\dodelimitedtexttxt}}
-
-% shortcuts
-
-\unexpanded\def\startdelimited{\startdelimitedtext}
-\unexpanded\def\stopdelimited {\stopdelimitedtext} % no let, dynamically assigned
-\def\delimited {\delimitedtext}
-
-\def\leftdelimitedtextmark
- {\doifsomething{\delimitedtextparameter\c!left}
- {\setbox\scratchbox\hbox{\delimitedtextparameter\c!left}%
- \dontleavehmode
- \doif{\delimitedtextparameter\c!location}\v!margin{\hskip-\wd\scratchbox}%
- \box\scratchbox}}
-
-\def\rightdelimitedtextmark
- {\doifsomething{\delimitedtextparameter\c!right}
- {\hsmash{\delimitedtextparameter\c!right}}}
-
-% \starttext
-% \hyphenatedword{groepsvrijstellingsverordeningen}\par
-% \hyphenatedword{\quote{groepsvrijstellingsverordeningen}}\par
-% \dorecurse{100}{\hskip300pt\hskip\recurselevel pt test \quote{xxx xxxx}.\par}
-% \page \setuppapersize[A5][A4]
-% \quotation {overly beautiful pusillanimous sesquipedalian
-% longwinded} test test test test test test test test test test test
-% test test test test test test test test test test test test test
-% test test test test test test test test test test test test test
-% test test test test test test test test test test test test test
-% test test test
-% \stoptext
-
-\def\dohandledelimitedtext#1#2%
- {\begingroup
- \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
- \ifdim\wd\scratchbox>\zeropoint
-% \ifdim\lastskip=\delimitedtextsignal
-% \unskip
- \ifdim\lastkern=\delimitedtextsignal
- \unkern
- \hskip\hspaceamount\currentlanguage{interquotation}%
- \else
- #2%
- \fi
- \ifhmode % else funny pagebeaks
- \penalty\plustenthousand
- \hskip\zeropoint % == \prewordbreak
- \fi
- \strut % new, needed below
- \delimitedtextparameter#1% unhbox\scratchbox
-% \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods
- \kern\delimitedtextsignal % +- \prewordbreak
- \fi
- \endgroup}
-
-\def\dohandleleftdelimitedtext#1#2%
- {\begingroup
- \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
- \ifdim\wd\scratchbox>\zeropoint
- \ifdim\lastkern=\delimitedtextsignal
- \unkern
- \hskip\hspaceamount\currentlanguage{interquotation}%
- \else\ifdim\lastskip=\delimitedtextsignal
- \unskip
- \hskip\hspaceamount\currentlanguage{interquotation}%
- \else
- #2%
- \fi\fi
- \strut % new, needed below
- \ifhmode % else funny pagebeaks
- \penalty\plustenthousand
- \hskip\zeropoint % == \prewordbreak
- \fi
- \strut % new, needed below
- \delimitedtextparameter#1% unhbox\scratchbox
- \hskip\delimitedtextsignal % +- \prewordbreak
- \fi
- \endgroup}
-
-\def\dohandlerightdelimitedtext#1#2%
- {\begingroup
- \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
- \ifdim\wd\scratchbox>\zeropoint
- \ifdim\lastkern=\delimitedtextsignal
- \unkern
- \penalty\plustenthousand
- \hskip\hspaceamount\currentlanguage{interquotation}%
- \else\ifdim\lastskip=\delimitedtextsignal
- \unskip
- \penalty\plustenthousand
- \hskip\hspaceamount\currentlanguage{interquotation}%
- \else
- #2%
- \fi\fi
- \ifhmode % else funny pagebeaks
- \penalty\plustenthousand
- \hskip\zeropoint % == \prewordbreak
- \fi
- \strut % new, needed below
- \delimitedtextparameter#1% unhbox\scratchbox
- \kern\delimitedtextsignal % +- \prewordbreak
- \fi
- \endgroup}
-
-
-\def\ignoredelimitedtext#1%
- {\delimitedtextparameter#1}
-
-\def\handledelimitedtext#1%
- {\dohandledelimitedtext{#1}\relax}
-
-\def\handleleftdelimitedtext#1%
- {\dohandleleftdelimitedtext{#1}\relax}
-
-\def\handlerightdelimitedtext#1%
- {\dohandlerightdelimitedtext{#1}\relax}
-
-% \unexpanded\def\dodelimitedtextpar
-% {\dohandleleftdelimitedtext\c!left\relax
-% \groupedcommand
-% \donothing
-% {\dohandlerightdelimitedtext\c!right\removelastskip
-% \popdelimitedtext}}
-
-\unexpanded\def\dodelimitedtextpar
- {\groupedcommand
- {\dostarttagged\t!delimited\currentdelimitedtext % block?
- \dohandleleftdelimitedtext\c!left\relax}
- {\dohandlerightdelimitedtext\c!right\removelastskip
- \dostoptagged
- \popdelimitedtext}}
-
-\unexpanded\def\dodelimitedtexttxt
- {\doifelse{\delimitedtextparameter\c!style}\v!normal
- \doquoteddelimited\doattributeddelimited}
-
-% \def\doquoteddelimited
-% {\dohandleleftdelimitedtext\c!left\relax
-% \groupedcommand
-% \donothing
-% {\dohandlerightdelimitedtext\c!right
-% \removelastskip
-% \popdelimitedtext}}
-
-\def\doquoteddelimited
- {\groupedcommand
- {\dostarttagged\t!delimited\currentdelimitedtext
- \dohandleleftdelimitedtext\c!left\relax}
- {\dohandlerightdelimitedtext\c!right
- \removelastskip
- \dostoptagged
- \popdelimitedtext}}
-
-\def\doattributeddelimited
- {\groupedcommand
- {\dostarttagged\t!delimited\currentdelimitedtext
- \dostartattributes{\??ci\currentdelimitedtext}\c!style\c!color}
- {\dostopattributes
- \dostoptagged
- \popdelimitedtext}}
-
-\def\dofontdrivendelimited
- {\simplegroupedcommand
- {\dostarttagged\t!delimited\currentdelimitedtext
- \languageparameter{\c!left\currentdelimitedtext}}
- {\languageparameter{\c!right\currentdelimitedtext}%
- \dostoptagged
- \popdelimitedtext}}
-
-% testcase for nesting:
-%
-% \quotation{... \quotation{...} ...}
-% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
-% \setupdelimitedtext[quotation][1][left=(,right=)]
-% \setupdelimitedtext[quotation][2][left={[},right={]}]
-% \setupdelimitedtext[quotation][3][left=\{,right=\}]
-% \quotation{... \quotation{...} ...}
-% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
-
-\definedelimitedtext
- [\v!quotation]
- [\c!left={\symbol[\c!leftquotation]},
- \c!right={\symbol[\c!rightquotation]},
- \c!leftmargin=\v!standard]
-
-\definedelimitedtext
- [\v!quote][\v!quotation]
-
-\setupdelimitedtext
- [\v!quote]
- [\c!location=\v!text,
- \c!left={\symbol[\c!leftquote]},
- \c!right={\symbol[\c!rightquote]}]
-
-\definedelimitedtext
- [\v!blockquote][\v!quotation]
-
-\setupdelimitedtext
- [\v!blockquote]
- [\c!left=,
- \c!right=]
-
-\definedelimitedtext
- [\v!speech][\v!quotation]
-
-\setupdelimitedtext
- [\v!speech]
- [\c!repeat=\v!yes,
- \c!left={\symbol[\c!leftspeech]},
- \c!middle={\symbol[\c!middlespeech]},
- \c!right={\symbol[\c!rightspeech]}]
-
-% how do we call an tight quote
-%
-% \definedelimitedtext
-% [\v!quotation][\v!quotation]
-%
-% \setupdelimitedtext
-% [\v!quotation]
-% [\c!indentnext=\v!no,
-% \c!spacebefore=\v!nowhite]
-
-\unexpanded\def\setupquotation{\setupdelimitedtext[\v!quotation]}
-\unexpanded\def\setupquote {\setupdelimitedtext[\v!quote]}
-
% seldom used, move from kernel to run time module
\ifx\tfx\undefined \let\tfx\relax \fi
@@ -1227,97 +531,6 @@
\let\grid\basegrid
-% only used at pragma, move from kernel to run time module
-
-\def\referraldate
- {\currentdate[\v!referral]}
-
-\def\doreferral[#1]%
- {\noheaderandfooterlines
- \bgroup
- \getparameters
- [\??km]
- [\c!bet=\unknown,\c!dat=\unknown,\c!ken=\unknown,
- \c!from=,\c!to=,\c!ref=,#1]%
- % moet anders, hoort niet in 01b
- \assigntranslation[\s!nl=referentie,\s!en=reference,\s!de=Referenz,\s!hr=referenca,\s!sp=referencia]\to\@@@kmref
- \assigntranslation[\s!nl=van,\s!en=from,\s!de=Von,\s!hr=od,\s!sp=de]\to\@@@kmvan
- \assigntranslation[\s!nl=aan,\s!en=to,\s!de=An,\s!hr=za,\s!sp=a]\to\@@@kmaan
- \assigntranslation[\s!nl=betreft,\s!en=concerns,\s!de=Betreff,\s!hr=predmet,\s!sp=]\to\@@@kmbet
- \assigntranslation[\s!nl=datum,\s!en=date,\s!de=Datum,\s!hr=datum,\s!sp=fecha]\to\@@@kmdat
- \assigntranslation[\s!nl=kenmerk,\s!en=mark,\s!de=Kennzeichen,\s!hr=oznaka,\s!sp=]\to\@@@kmken
- %
- \definetabulate[\s!dummy][|l|p|]
- \startdummy
- \NC\@@@kmbet\EQ\@@kmbet\NC\NR
- \NC\@@@kmdat\EQ\@@kmdat\NC\NR
- \NC\@@@kmken\EQ\expanded{\smallcapped{\@@kmken}}\NC\NR
- \doifsomething{\@@kmfrom\@@kmto}{\NC\NC\NC\NR}%
- \doifsomething \@@kmfrom {\NC\@@@kmvan\EQ\@@kmfrom\NC\NR}%
- \doifsomething \@@kmto {\NC\@@@kmaan\EQ\@@kmto\NC\NR}%
- \doifsomething \@@kmref {\NC\NC\NC\NR\NC\@@@kmref\EQ\@@kmref\NC\NR}%
- \stopdummy
- \egroup}
-
-\def\referral
- {\dosingleargument\doreferral}
-
-% FUZZY OLD STUFF: will be removed when not used in some manual;
-% rows instead of columns, i'd forgotten that this code exist
-%
-% \definesystemvariable{ri}
-%
-% \unexpanded\def\setuprows
-% {\dodoubleargument\getparameters[\??ri]}
-%
-% \definecomplexorsimpleempty\startrows
-%
-% \def\complexstartrows[#1]%
-% {\bgroup
-% \setuprows[#1]%
-% \let\do@@ribottom\relax
-% \def\row
-% {\do@@ribottom
-% \egroup
-% \dimen0\vsize
-% \divide\dimen0 \@@rin
-% \advance\dimen0 -\lineskip
-% \vbox to \dimen0
-% \bgroup
-% \@@ritop
-% \let\do@@ribottom\@@ribottom
-% \ignorespaces}%
-% \bgroup
-% \row}
-%
-% \unexpanded\def\stoprows
-% {\do@@ribottom
-% \egroup
-% \egroup}
-%
-% \setuprows
-% [\c!n=2,
-% \c!top=,
-% \c!bottom=\vfill]
-
-% THIS WAS MAIN-003.TEX
-
-% messages moved
-
-% messages moved
-
-% messages moved
-
-% messages moved
-
-% messages moved
-
-% messages moved
-
-% messages moved
-
-% messages moved
-
\definetabulate
[\v!legend]
[|emj1|i1|mR|]
@@ -1344,903 +557,8 @@
\unexpanded\def\xxbox
{\bgroup\aftergroup\egroup\hbox\bgroup\txx\let\next=}
-% \def\mrm#1%
-% {$\rm#1$}
-
-%D \macros
-%D {definepairedbox, setuppairedbox, placepairedbox}
-%D
-%D Paired boxes, formally called legends, but from now on a
-%D legend is just an instance, are primarily meant for
-%D typesetting some text alongside an illustration. Although
-%D there is quite some variation possible, the functionality is
-%D kept simple, if only because in most cases such pairs are
-%D typeset sober.
-%D
-%D The location specification accepts a pair, where the first
-%D keyword specifies the arrangement, and the second one the
-%D alignment. The first key of the location pair is one of
-%D \type {left}, \type {right}, \type {top} or \type {bottom},
-%D while the second key can also be \type {middle}.
-%D
-%D The first box is just collected in an horizontal box, but
-%D the second one is a vertical box that gets passed the
-%D bodyfont and alignment settings.
-
-%D Today we would implement this using layers .... but for the
-%D moment we keep it this way.
-
-% \startbuffer[test]
-% \test left \test left,top \test left,bottom \test left,middle
-% \test right \test right,top \test right,bottom \test right,middle
-% \test top \test top,left \test top,right \test top,middle
-% \test bottom \test bottom,left \test bottom,right \test bottom,middle
-% \stopbuffer
-%
-% \def\showtest#1%
-% {\pagina
-% \typebuffer[demo]
-% \def\test##1
-% {\startlinecorrection[blank]
-% \getbuffer[demo]%
-% \ruledhbox\placelegend
-% [bodyfont=6pt,location={##1}]
-% {\framed[width=.25\textwidth]{\tttf##1}}
-% {#1}
-% \stoplinecorrection}
-% \getbuffer[test]}
-%
-% \startbuffer[demo]
-% \setuplegend
-% [width=\hsize,maxwidth=\makeupwidth,
-% height=\vsize,maxheight=\makeupheight]
-% \stopbuffer
-%
-% \showtest{These examples demonstrate the default settings.}
-%
-% \startbuffer[demo]
-% \setuplegend
-% [width=\textwidth,
-% maxwidth=\textwidth]
-% \stopbuffer
-%
-% \showtest{\input tufte }
-%
-% \startbuffer[demo]
-% \setuplegend
-% [width=.65\textwidth]
-% \stopbuffer
-%
-% \showtest{\input knuth }
-%
-% \startbuffer[demo]
-% \setuplegend
-% [height=2cm]
-% \stopbuffer
-%
-% \showtest{These examples demonstrate some other settings.}
-%
-% \startbuffer[demo]
-% \setuplegend
-% [width=.65\textwidth,
-% height=2cm]
-% \stopbuffer
-%
-% \showtest{These examples demonstrate some other settings.}
-%
-% \startbuffer[demo]
-% \setuplegend
-% [n=2,align=right,width=.5\textwidth]
-% \stopbuffer
-%
-% \showtest{\input zapf }
-
-%D \macros
-%D {setuplegend, placelegend}
-%D
-%D It makes sense to typeset a legend to a figure in \TEX\
-%D and not in a drawing package. The macro \type {\placelegend}
-%D combines a figure (or something else) and its legend. This
-%D command is just a paired box.
-%D
-%D The legend is placed according to \type {location}, being
-%D \type {bottom} or \type {right}. The macro macro is used as
-%D follows.
-%D
-%D \starttyping
-%D \placefigure
-%D {whow}
-%D {\placelegend
-%D {\externalfigure[cow]}
-%D {\starttabulation
-%D \NC 1 \NC head \NC \NR
-%D \NC 2 \NC legs \NC \NR
-%D \NC 3 \NC tail \NC \NR
-%D \stoptabulation}}
-%D
-%D \placefigure
-%D {whow}
-%D {\placelegend
-%D {\externalfigure[cow]}
-%D {\starttabulation[|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 \stoptabulation}}
-%D
-%D \placefigure
-%D {whow}
-%D {\placelegend[n=2]
-%D {\externalfigure[cow]}
-%D {\starttabulation
-%D \NC 1 \NC head \NC \NR
-%D \NC 2 \NC legs \NC \NR
-%D \NC 3 \NC tail \NC \NR
-%D \stoptabulation}}
-%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 \stoptyping
-
-\newbox\firstpairedbox
-\newbox\secondpairedbox
-
-\unexpanded\def\definepairedbox
- {\dodoubleempty\dodefinepairedbox}
-
-\def\dodefinepairedbox[#1][#2]%
- {\getparameters
- [\??ld#1]
- [\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,
- #2]%
- \setvalue{\e!setup#1\e!endsetup}{\setuppairedbox[#1]}%
- \setvalue{\e!place#1}{\placepairedbox[#1]}}
-
-\unexpanded\def\setuppairedbox
- {\dodoubleempty\dosetuppairedbox}
-
-\def\dosetuppairedbox[#1]%
- {\getparameters[\??ld#1]}
-
-\unexpanded\def\placepairedbox
- {\bgroup\dodoubleempty\doplacepairedbox}
-
-\def\doplacepairedbox[#1][#2]% watch the hsize/vsize tricks
- {\setuppairedbox[#1][#2]% % and don't change them
- \copyparameters % brrr
- [\??ld][\??ld#1]
- [\c!n,\c!distance,\c!inbetween,\c!before,\c!after,
- \c!width,\c!height,\c!maxwidth,\c!maxheight,
- \c!color,\c!style,\c!bodyfont,\c!align,\c!location]%
- \@@ldbefore\bgroup
- \global\setsystemmode{pairedbox}%
- \beforefirstpairedbox
- \dowithnextbox
- {\betweenbothpairedboxes
- \dowithnextbox
- {\afterbothpairedboxes
- \egroup\@@ldafter
- \egroup}
- \vbox\bgroup
- \insidesecondpairedbox
- \let\next=}
- \hbox}
-
-\setnewconstant\pairedlocationa\plusone
-\setnewconstant\pairedlocationb\plusfour
-
-\def\beforefirstpairedbox
- {\pairedlocationa\plusone % left
- \pairedlocationb\plusfour % middle
- \getfromcommacommand[\@@ldlocation][1]%
- \processaction
- [\commalistelement]
- [ \v!left=>\pairedlocationa\zerocount,
- \v!right=>\pairedlocationa\plusone,
- \v!top=>\pairedlocationa\plustwo,
- \v!bottom=>\pairedlocationa\plusthree]%
- \getfromcommacommand[\@@ldlocation][2]%
- \processaction
- [\commalistelement]
- [ \v!left=>\pairedlocationb\zerocount,
- \v!right=>\pairedlocationb\plusone,
- \v!high=>\pairedlocationb\plustwo,
- \v!top=>\pairedlocationb\plustwo,
- \v!low=>\pairedlocationb\plusthree,
- \v!bottom=>\pairedlocationb\plusthree,
- \v!middle=>\pairedlocationb\plusfour]}
-
-\def\betweenbothpairedboxes
- {\switchtobodyfont[\@@ldbodyfont]% split under same regime
- \setbox\firstpairedbox\flushnextbox
- \ifnum\pairedlocationa<\plustwo
- \hsize\wd\firstpairedbox % trick
- \hsize\@@ldwidth
- \scratchdimen\wd\firstpairedbox
- \advance\scratchdimen \@@lddistance
- \bgroup\advance\scratchdimen \hsize
- \ifdim\scratchdimen>\@@ldmaxwidth\relax
- \egroup
- \hsize\@@ldmaxwidth
- \advance\hsize -\scratchdimen
- \else
- \egroup
- \fi
- \else
- \hsize\wd\firstpairedbox
- \hsize\@@ldwidth % can be \hsize
- \ifdim\hsize>\@@ldmaxwidth\relax \hsize\@@ldmaxwidth \fi % can be \hsize
- \fi
- \ifnum\@@ldn>\plusone
- \setrigidcolumnhsize\hsize\@@lddistance\@@ldn
- \fi}
-
-\def\afterbothpairedboxes
- {\setbox\secondpairedbox\vbox
- {\ifnum\@@ldn>1
- \rigidcolumnbalance\nextbox
- \else
- \flushnextbox
- \fi}%
- \ifnum\pairedlocationa<\plustwo\hbox\else\vbox\fi\bgroup % hide vsize
- \forgetall
- \ifnum\pairedlocationa<\plustwo
- \scratchdimen\maxoftwoboxdimens\ht\firstpairedbox\secondpairedbox
- \vsize\scratchdimen
- \ifdim\scratchdimen<\@@ldheight\relax % can be \vsize
- \scratchdimen\@@ldheight
- \fi
- \ifdim\scratchdimen>\@@ldmaxheight\relax
- \scratchdimen\@@ldmaxheight
- \fi
- \valignpairedbox\firstpairedbox \scratchdimen
- \valignpairedbox\secondpairedbox\scratchdimen
- \else
- \scratchdimen\maxoftwoboxdimens\wd\firstpairedbox\secondpairedbox
- \halignpairedbox\firstpairedbox \scratchdimen
- \halignpairedbox\secondpairedbox\scratchdimen
- \scratchdimen\ht\secondpairedbox
- \vsize\scratchdimen
- \ifdim\ht\secondpairedbox<\@@ldheight\relax % can be \vsize
- \scratchdimen\@@ldheight\relax % \relax needed
- \fi
- \ifdim\scratchdimen>\@@ldmaxheight\relax % todo: totale hoogte
- \scratchdimen\@@ldmaxheight\relax % \relax needed
- \fi
- \ifdim\scratchdimen>\ht\secondpairedbox
- \setbox\secondpairedbox\vbox to \scratchdimen
- {\ifnum\pairedlocationa=\plusthree \vss\fi %
- \box\secondpairedbox
- \ifnum\pairedlocationa=\plustwo \vss\fi}% \kern\zeropoint
- \fi
- \fi
- \ifcase\pairedlocationa
- \box\secondpairedbox\hskip\@@lddistance\box\firstpairedbox \or
- \box\firstpairedbox \hskip\@@lddistance\box\secondpairedbox\or
- \box\secondpairedbox\endgraf \nointerlineskip \@@ldinbetween \box\firstpairedbox \or
- \box\firstpairedbox \endgraf \nointerlineskip \@@ldinbetween \box\secondpairedbox\else
- \fi
- \egroup}
-
-\def\insidesecondpairedbox
- {\forgetall
- \setupalign[\@@ldalign]%
- \tolerantTABLEbreaktrue % hm.
- \blank[\v!disable]%
- \everypar{\begstrut}}
-
-\def\maxoftwoboxdimens#1#2#3%
- {#1\ifdim#1#2>#1#3 #2\else#3\fi}
-
-\def\valignpairedbox#1#2%
- {\setbox#1\vbox to #2
- {\ifcase\pairedlocationb\or\or\or\vss\or\vss\fi
- \box#1\relax
- \ifcase\pairedlocationb\or\or\vss\or\or\vss\fi}}
-
-\def\halignpairedbox#1#2%
- {\setbox#1\hbox to #2
- {\ifcase\pairedlocationb\or\hss\or\or\or\hss\fi
- \box#1\relax
- \ifcase\pairedlocationb\hss\or\or\or\or\hss\fi}}
-
-\definepairedbox[\v!legend]
-
-%D Goody:
-
-\appendtoks
- \global\resetsystemmode{combination}%
- \global\resetsystemmode{pairedbox}%
-\to \everyinsidefloat
-
-% todo: \startcombination \startcomb \stopcomb ...
-
-% needs to be mkiv'd
-
-\newcount\horcombination % counter
-\newcount\totcombination
-
-\unexpanded\def\definecombination
- {\dodoubleempty\dodefinecombination}
-
-\def\dodefinecombination[#1][#2]%
- {\copyparameters
- [\??co#1][\??co]
- [\c!width,\c!height,\c!distance,\c!location,%
- \c!before,\c!inbetween,\c!after,\c!align,%
- \c!style,\c!color]%
- \getparameters
- [\??co#1][#2]}
-
-\unexpanded\def\setupcombinations
- {\dodoubleempty\dosetupcombinations}
-
-\def\dosetupcombinations[#1][#2]%
- {\ifsecondargument
- \getparameters[\??co#1][#2]%
- \else
- \getparameters[\??co][#1]%
- \fi}
-
-\def\combinationparameter#1%
- {\csname\??co\currentcombination#1\endcsname}%
-
-\unexpanded\def\startcombination
- {\bgroup % so we can grab a group
- \dodoubleempty\dostartcombination}
-
-% \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
-
-\def\dostartcombination[#1][#2]%
- {\global\setsystemmode{combination}%
- \doifnothing{#1}\firstargumentfalse % to be sure (when called in macros)
- \doifnothing{#2}\secondargumentfalse % to be sure (when called in macros)
- \ifsecondargument
- \def\currentcombination{#1}%
- \edef\currentcombinationspec{#2*1*}%
- \else % better : \doifcombinationelse ... \??co#1\c!location
- \doifinstringelse{*}{#1}
- {\let\currentcombination\empty
- \edef\currentcombinationspec{#1*1*}}
- {\doifnumberelse{#1}
- {\let\currentcombination\empty
- \edef\currentcombinationspec{#1*1*}}
- {\def\currentcombination{#1}%
- \edef\currentcombinationspec{2*1*}}}%
- \fi
- \forgetall
- \doifelse{\combinationparameter\c!height}\v!fit
- \vbox {\vbox to \combinationparameter\c!height}%
- \bgroup
-\let\combination\empty % permits \combination{}{} handy for cld
- \expanded{\dodostartcombination[\currentcombinationspec]}}
-
-\long\def\dodostartcombination[#1*#2*#3]%
- {\setuphorizontaldivision
- [\c!n=\v!fit,\c!distance=\combinationparameter\c!distance]%
- \global\horcombination#1%
- \global\totcombination#2%
- \global\setbox\combinationstack\emptybox
- \xdef\maxhorcombination{\the\horcombination}%
- \multiply\totcombination\horcombination
- \tabskip\zeropoint
- \doifelse{\combinationparameter\c!width}\v!fit
- {\halign}{\halign to \combinationparameter\c!width}%
- \bgroup&%
- %\hfil##\hfil% now : location={left,top}
- \expanded{\doifnotinset{\v!left}{\combinationparameter\c!location}}\hfil
- ##%
- \expanded{\doifnotinset{\v!right}{\combinationparameter\c!location}}\hfil
- &\tabskip\zeropoint \!!plus 1fill##\cr
- \docombination}
-
-\def\docombination % we want to add struts but still ignore an empty box
- {\dowithnextbox
- {\setbox0\flushnextbox
- \dowithnextbox
- {\setbox2\flushnextbox
- \dodocombination}%
- \vtop\bgroup
- \def\next
- {\futurelet\nexttoken\nextnext}%
- \def\nextnext
- {\ifx\nexttoken\egroup \else % the next box is empty
- \hsize\wd0
- \setupalign[\combinationparameter\c!align]%
- \dostartattributes{\??co\currentcombination}\c!style\c!color\empty
- \bgroup
- \aftergroup\endstrut
- \aftergroup\dostopattributes
- \aftergroup\egroup
- \begstrut
- \fi}%
- \afterassignment\next\let\nexttoken=}
- \hbox}
-
-\def\depthonlybox
- {\dowithnextbox{\vtop{\hsize\wd\nextbox\kern\zeropoint\box\nextbox}}\vbox}
-
-\def\dodocombination
- {\vbox
- {\forgetall % \setupwhitespace[\v!none]%
- \let\next\vbox
- \expanded{\processallactionsinset[\combinationparameter\c!location]}
- [ \v!top=>\let\next\depthonlybox, % \tbox,
- \v!middle=>\let\next\halfwaybox]%
- \next{\copy0}%
- % we need to save the caption for a next alignment line
- \saveoncombinationstack2}%
- \ifnum\totcombination>\plusone
- \global\advance\totcombination\minusone
- \global\advance\horcombination\minusone
- \ifnum\horcombination=\zerocount
- \def\next
- {\cr
- \flushcombinationstack
- \noalign
- {\forgetall % \setupwhitespace[\v!none]% no
- \global\setbox\combinationstack\emptybox
- \nointerlineskip
- \combinationparameter\c!after
- \combinationparameter\c!before
- \vss
- \nointerlineskip}%
- \global\horcombination\maxhorcombination\relax
- \docombination}%
- \else
- \def\next
- {&&&\hskip\combinationparameter\c!distance&\docombination}%
- \fi
- \else
- \def\next
- {\cr
- \flushcombinationstack
- \egroup}%
- \fi
- \next}
-
-% formally ok:
-%
-% \unexpanded\def\stopcombination
-% {\egroup
-% \egroup}
-%
-% more robust:
-%
-% \unexpanded\def\stopcombination
-% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries
-% \egroup
-% \egroup}
-%
-% even better:
-
-\unexpanded\def\stopcombination
- {{\scratchtoks{{}{}{}}\dorecurse\totcombination{\appendtoks{}{}{}{}\to\scratchtoks}\expandafter}\the\scratchtoks
- \egroup
- \egroup}
-
-\newbox\combinationstack
-
-\def\saveoncombinationstack#1%
- {\global\setbox\combinationstack\hbox
- {\hbox{\box#1}\unhbox\combinationstack}}
-
-\def\flushcombinationstack
- {\noalign
- {\ifdim\ht\combinationstack>\zeropoint
-\nointerlineskip % nieuw
- \combinationparameter\c!inbetween
- \global\horcombination\maxhorcombination
- \globallet\doflushcombinationstack\dodoflushcombinationstack
- \else
- \global\setbox\combinationstack\emptybox
- \globallet\doflushcombinationstack\donothing
- \fi}%
- \doflushcombinationstack\crcr}
-
-\gdef\dodoflushcombinationstack
- {\global\setbox\combinationstack\hbox
- {\unhbox\combinationstack
- \global\setbox1\lastbox}%
- \box1% \ruledhbox{\box1}%
- \global\advance\horcombination\minusone\relax
- \ifnum\horcombination>\zerocount
- \def\next{&&&&\doflushcombinationstack}%
- \else
- \global\setbox\combinationstack\emptybox
- %\let\next\relax
- \@EA\gobbleoneargument
- \fi
- \next}
-
-\setupcombinations
- [\c!width=\v!fit,
- \c!height=\v!fit,
- \c!distance=1em,
- \c!location=\v!bottom, % can be something {top,left}
- \c!before=\blank,
- \c!inbetween={\blank[\v!medium]},
- \c!style=,
- \c!color=,
- \c!after=,
- \c!align=\v!middle]
-
-%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
-
-\unexpanded\def\startfloatcombination
- {\dodoubleempty\dostartfloatcombination}
-
-\def\dostartfloatcombination[#1][#2]%
- {\vbox\bgroup
- %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature
- \postcenterfloatmethod\zerocount
- \forcelocalfloats
- \unexpanded\def\stopfloatcombination
- {\scratchtoks\emptytoks
- \dorecurse\noflocalfloats
- {\appendetoks{\noexpand\getlocalfloat{\recurselevel}}{}\to\scratchtoks}%
- \expanded{\startcombination[#1]\the\scratchtoks}\stopcombination
- \resetlocalfloats
- \egroup}}
-
-\unexpanded\def\placerelativetoeachother#1#2%
- {\bgroup
- \dowithnextbox
- {\bgroup
- \setbox0\box\nextbox
- \dowithnextbox
- {\setbox2\box\nextbox
- #1{#2#########2\cr\box0\cr\box2\cr}
- \egroup
- \egroup}
- \hbox}
- \hbox}
-
-\unexpanded\def\placeontopofeachother{\placerelativetoeachother\halign\hss}
-\unexpanded\def\placesidebyside {\placerelativetoeachother\valign\vss}
-
-%D A couple of examples, demonstrating how the depth is
-%D taken care of:
-%D
-%D \startbuffer
-%D test\rotate[frame=on, rotation=0] {gans}%
-%D test\rotate[frame=on, rotation=90] {gans}%
-%D test\rotate[frame=on, rotation=180]{gans}%
-%D test\rotate[frame=on, rotation=270]{gans}%
-%D test
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-
-% When we rotate over arbitrary angles, we need to relocate the
-% resulting box because rotation brings that box onto the negative
-% axis. The calculations (mostly sin and cosine) need to be tuned for
-% the way a box is packages (i.e. the refence point). A typical example
-% of drawing, scribbling, and going back to the days of school math.
-%
-% We do a bit more calculations than needed, simply because that way
-% it's easier to debug the code.
-
-\def\dododorotatenextbox
- {\setbox\nextbox\vbox to \@@layerysiz
- {\vfill
- \hbox to \@@layerxsiz
- {\dostartrotation\@@rorotation
- \nextboxwd\zeropoint
- \nextboxht\zeropoint
- \flushnextbox
- \dostoprotation
- \hfill}%
- \kern\@@layerypos}%
- \setbox\nextbox\hbox
- {\kern\@@layerxpos
- \kern\@@layerxoff
- \lower\@@layeryoff\flushnextbox}}
-
-\def\dodorotatenextbox#1#2% quite some trial and error -)
- {\dontshowcomposition
- \dontcomplain
- \ifnum#2=\plusfour
- % new, location=middle
- \!!widthb \nextboxwd
- \!!heightb\nextboxht
- \!!depthb \nextboxdp
- \setbox\nextbox\vbox{\vskip.5\nextboxht\hskip-.5\nextboxwd\flushnextbox}%
- \smashbox\nextbox
- \fi
- \!!widtha \nextboxwd
- \!!heighta\nextboxht
- \!!deptha \nextboxdp
- \!!doneafalse
- \!!donebfalse
- \ifcase#2\or
- % 1: fit
- \or
- % 2: depth, not fit
- \!!doneatrue
- \!!donebtrue
- \or
- % 3: depth, fit
- \!!donebtrue
- \fi
- \setbox\nextbox\vbox{\hbox{\raise\nextboxdp\flushnextbox}}%
- \!!dimena \nextboxht
- \setcalculatedcos\cos\@@rorotation
- \setcalculatedsin\sin\@@rorotation
- \@@layerxpos\zeropoint
- \@@layerypos\zeropoint
- \@@layerxoff\zeropoint
- \@@layeryoff\zeropoint
- \ifdim\sin\points>\zeropoint
- \ifdim\cos\points>\zeropoint
- \@@layerxsiz \cos\!!widtha
- \@@layerysiz \sin\!!widtha
- \advance\@@layerxsiz \sin\!!dimena
- \advance\@@layerysiz \cos\!!dimena
- \@@layerypos \cos\!!dimena
- \if!!donea
- \@@layerxoff \negated\sin\!!dimena
- \advance\@@layerxoff \sin\!!deptha
- \fi
- \if!!doneb
- \@@layeryoff \cos\!!deptha
- \fi
- \dododorotatenextbox
- \else
- \@@layerxsiz \negated\cos\!!widtha
- \@@layerysiz \sin\!!widtha
- \advance\@@layerxsiz \sin\!!dimena
- \advance\@@layerysiz \negated\cos\!!dimena
- \@@layerxpos \negated\cos\!!widtha
- \if!!donea
- \@@layerxoff -\@@layerxsiz
- \advance\@@layerxoff \sin\!!deptha
- \fi
- \if!!doneb
- \@@layeryoff \negated\cos\!!heighta
- \fi
- \dododorotatenextbox
- \wd\nextbox\if!!donea\sin\!!deptha\else\@@layerxsiz\fi
- \fi
- \else
- \ifdim\cos\points<\zeropoint
- \@@layerxsiz \negated\cos\!!widtha
- \@@layerysiz \negated\sin\!!widtha
- \advance\@@layerxsiz \negated\sin\!!dimena
- \advance\@@layerysiz \negated\cos\!!dimena
- \@@layerxpos \@@layerxsiz
- \@@layerypos \negated\sin\!!widtha
- \if!!donea
- \@@layerxoff -\@@layerxsiz
- \advance\@@layerxoff \negated\sin\!!heighta
- \fi
- \if!!doneb
- \@@layeryoff \@@layerysiz
- \advance\@@layeryoff \cos\!!deptha
- \fi
- \dododorotatenextbox
- \wd\nextbox\if!!donea\negated\sin\!!heighta\else\@@layerxsiz\fi
- \else
- \@@layerxsiz \cos\!!widtha
- \@@layerysiz \negated\sin\!!widtha
- \advance\@@layerxsiz \negated\sin\!!dimena
- \advance\@@layerysiz \cos\!!dimena
- \ifdim\sin\points=\zeropoint
- \@@layerxpos \zeropoint
- \@@layerxoff \zeropoint
- \@@layerypos \@@layerysiz
- \if!!doneb
- \@@layeryoff \!!deptha
- \fi
- \else
- \@@layerypos \@@layerysiz
- \@@layerxpos \negated\sin\!!dimena
- \if!!donea
- \@@layerxoff -\@@layerxsiz
- \advance\@@layerxoff \negated\sin\!!heighta
- \fi
- \if!!doneb
- \@@layeryoff \negated\sin\!!deptha
- \fi
- \fi
- \dododorotatenextbox
- \ifdim\sin\points=\zeropoint
- \else
- \wd\nextbox\if!!donea\negated\sin\!!heighta\else\@@layerxsiz\fi
- \fi
- \fi
- \fi
- % new, location=middle
- \ifnum#2=\plusfour
- \setbox\nextbox\vbox{\vskip-.5\!!heightb\hskip.5\!!heightb\flushnextbox}%
- \nextboxwd\!!widthb
- \nextboxht\!!heightb
- \nextboxdp\!!depthb
- \fi}
-
-\def\dorotatenextbox#1#2%
- {\doifsomething{#1}
- {\edef\@@rorotation{\realnumber{#1}}% get rid of leading zeros and spaces
- \setbox\nextbox\vbox{\flushnextbox}% not really needed
- \dodorotatenextbox\@@rorotation#2}%
- \hbox{\boxcursor\flushnextbox}}
-
-\def\dodorotatebox#1% {angle} \hbox/\vbox/\vtop
- {\bgroup\hbox\bgroup % compatibility hack
- \dowithnextbox
- {\dorotatenextbox{#1}\plusone
- \egroup\egroup}}
-
-\def\dorotatebox#1% {angle} \hbox/\vbox/\vtop
- {\ifcase#1\relax
- \expandafter\gobbleoneargument
- \else
- \expandafter\dodorotatebox
- \fi{#1}}
-
-\unexpanded\def\rotate % \bgroup: \rotate kan argument zijn
- {\bgroup\complexorsimpleempty\rotate}
-
-% \def\complexrotate[#1]% framed met diepte !
-% {\getparameters[\??ro][#1]%
-% \processaction
-% [\@@rolocation]
-% [ \v!depth=>\!!counta\plusthree\donefalse,% depth fit - raw box
-% \v!fit=>\!!counta\plustwo \donefalse,% depth tight - raw box
-% \v!broad=>\!!counta\plusone \donefalse,% nodepth fit - raw box
-% \v!high=>\!!counta\plusone \donetrue ,% nodepth fit - framed
-% \v!middle=>\!!counta\plusfour \donefalse,% centered, keep dimensions
-% \s!default=>\!!counta\plusthree\donetrue ,% depth fit - framed
-% \s!unknown=>\!!counta\plusthree\donetrue ]% depth fit - framed
-% \ifdone
-% \def\docommand{\localframed[\??ro][#1,\c!location=]}%
-% \else
-% \let\docommand\relax
-% \fi
-% \dowithnextbox{\dorotatenextbox\@@rorotation\!!counta\egroup}\vbox\docommand}
-
-\setvalue{\??ro::\c!location::\v!depth }{\!!counta\plusthree\donefalse} % depth fit - raw box
-\setvalue{\??ro::\c!location::\v!fit }{\!!counta\plustwo \donefalse} % depth tight - raw box
-\setvalue{\??ro::\c!location::\v!broad }{\!!counta\plusone \donefalse} % nodepth fit - raw box
-\setvalue{\??ro::\c!location::\v!high }{\!!counta\plusone \donetrue } % nodepth fit - framed
-\setvalue{\??ro::\c!location::\v!middle }{\!!counta\plusfour \donefalse} % centered, keep dimensions
-\setvalue{\??ro::\c!location::\v!default}{\!!counta\plusthree\donetrue } % depth fit - framed
-
-\def\complexrotate[#1]% framed met diepte !
- {\getparameters[\??ro][#1]%
- \executeifdefined{\??ro::\c!location::\@@rolocation}{\!!counta\plusthree\donetrue}%
- \ifdone
- \def\docommand{\localframed[\??ro][#1,\c!location=]}%
- \else
- \let\docommand\relax
- \fi
- \dowithnextbox{\dorotatenextbox\@@rorotation\!!counta\egroup}\vbox\docommand}
-
-\presetlocalframed[\??ro]
-
-\unexpanded\def\setuprotate
- {\dodoubleargument\getparameters[\??ro]}
-
-\setuprotate
- [\c!rotation=90,
- \c!location=\v!normal,
- \c!width=\v!fit,
- \c!height=\v!fit,
- \c!offset=\v!overlay,
- \c!frame=\v!off]
-
-% \dostepwiserecurse{0}{360}{10}
-% {\startlinecorrection[blank]
-% \hbox
-% {\expanded{\setuprotate[rotation=\recurselevel]}%
-% \traceboxplacementtrue
-% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=depth] {\ruledhbox{\bfb (depth)}}}}%
-% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=fit] {\ruledhbox{\bfb (fit)}}}}%
-% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=broad] {\ruledhbox{\bfb (broad)}}}}%
-% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=normal]{\ruledhbox{\bfb (normal)}}}}%
-% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=high] {\ruledhbox{\bfb (high)}}}}}
-% \stoplinecorrection}
-
-% to be used in some other places! todo!
-%
-% divides \hsize in fractions, will be made a bit more
-% clever and advanced when needed
-%
-% \horizontaldivision[n/m,elements,distance]
-%
-% \horizontaldivision[2/5,3,1em]
-% \horizontaldivision[2/5,3,1em]
-% \horizontaldivision[1/5,3,1em]
-%
-% \setuphorizontaldivision[afstand=,aantal=] (passend,passend)
-
-\def\??fr{@@fr}
-
-\unexpanded\def\setuphorizontaldivision
- {\dodoubleargument\getparameters[\??fr]}
-
-\def\horizontaldivision
- {\dosingleargument\dohorizontaldivision}
-
-\def\dohorizontaldivision[#1]%
- {\dodohorizontaldivision[#1,,,,,,]}
-
-\def\dodohorizontaldivision[#1/#2,#3,#4,#5]%
- {\doifelsenothing{#3}
- {\doifelse\@@frn\v!fit
- {\!!counta#2\relax}
- {\!!counta\@@frn\relax}}
- {\!!counta#3\relax}%
- \doifelsenothing{#4}
- {\doifelse\@@frdistance\v!fit
- {\!!widtha\zeropoint}
- {\!!widtha\@@frdistance}}
- {\!!widtha#4}%
- \advance\!!counta \minusone
- \multiply\!!widtha \!!counta
- \advance\hsize -\!!widtha
- \divide\hsize #2\relax
- \hsize#1\hsize}
-
-\setuphorizontaldivision
- [\c!distance=\tfskipsize,
- \c!n=\v!fit]
-
-%D This one is for Daniel Pittman, who wanted tight
-%D fractions. We show three versions. First the simple
-%D one using \type {\low} and \type {high}:
+%D This one is for Daniel Pittman, who wanted tight fractions. We show
+%D three versions. First the simple one using \type {\low} and \type {high}:
%D
%D \startbuffer
%D \def\vfrac#1#2%
@@ -2298,7 +616,7 @@
\lower\dp0\hbox{\raise\dp2\hbox{\txx#2}}%
\fi}}
-\ifx\vfrac\undefined \let\vfrac\vulgarfraction \fi
+\ifdefined\vfrac \else \let\vfrac\vulgarfraction \fi
%D \starttabulate
%D \HL
@@ -2310,7 +628,7 @@
%D \NC 3 \NC \vulgarfractionmethod3 \vulgarfraction{1}{2} \NC\NR
%D \HL
%D \stoptabulate
-
+
%D Under construction:
%D
%D \starttyping
@@ -2322,6 +640,8 @@
%D \commalistsentence[a,b,c][+,-]
%D \stoptyping
+% obsolete .. use lua instead
+
\let\handlecommalistsentence\firstofoneargument
\def\commalistsentenceone{and-1}
@@ -2369,12 +689,10 @@
\def\commacommandsentence[#1]{\@EA\commalistsentence\@EA[#1]}
-\ifx\textcomma\undefined \def\textcomma{,} \fi
-
-\setuplabeltext [\s!nl] [and-1=\textcomma\ , and-2= en ]
-\setuplabeltext [\s!en] [and-1=\textcomma\ , and-2=\textcomma\ and ]
-\setuplabeltext [\s!de] [and-1=\textcomma\ , and-2= und ]
-\setuplabeltext [\s!hr] [and-1=\textcomma\ , and-2= i ]
+\setuplabeltext [\s!nl] [and-1={,} , and-2= en ] % 1, 2 en 3
+\setuplabeltext [\s!en] [and-1={,} , and-2={,} ] % 1, 2, 3
+\setuplabeltext [\s!de] [and-1={,} , and-2= und ] % 1, 2 und 3
+\setuplabeltext [\s!hr] [and-1={,} , and-2= i ] % 1, 2 i 3
%D \macros
%D {somekindoftab}
diff --git a/Master/texmf-dist/tex/context/base/core-par.mkii b/Master/texmf-dist/tex/context/base/core-par.mkii
index 0b283b294a9..69e2976d1f3 100644
--- a/Master/texmf-dist/tex/context/base/core-par.mkii
+++ b/Master/texmf-dist/tex/context/base/core-par.mkii
@@ -5,7 +5,7 @@
%D subtitle=Paragraph Tricks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-stg.mkii b/Master/texmf-dist/tex/context/base/core-stg.mkii
index 429e1e894ac..0d98da851d3 100644
--- a/Master/texmf-dist/tex/context/base/core-stg.mkii
+++ b/Master/texmf-dist/tex/context/base/core-stg.mkii
@@ -5,7 +5,7 @@
%D subtitle=Strategies,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-sys.lua b/Master/texmf-dist/tex/context/base/core-sys.lua
index 47a5c340df3..0be9fd588c7 100644
--- a/Master/texmf-dist/tex/context/base/core-sys.lua
+++ b/Master/texmf-dist/tex/context/base/core-sys.lua
@@ -6,7 +6,8 @@ if not modules then modules = { } end modules ['core-sys'] = {
license = "see context related readme files"
}
-local lower, extname, basename, removesuffix = string.lower, file.extname, file.basename, file.removesuffix
+local lower, format = string.lower, string.format
+local extname, basename, removesuffix = file.extname, file.basename, file.removesuffix
local environment = environment
@@ -21,5 +22,5 @@ end
statistics.register("result saved in file", function()
-- suffix will be fetched from backend
- return string.format( "%s.%s", environment.outputfilename, (tex.pdfoutput>0 and "pdf") or "dvi")
+ return format( "%s.%s", environment.outputfilename, (tex.pdfoutput>0 and "pdf") or "dvi")
end)
diff --git a/Master/texmf-dist/tex/context/base/core-sys.mkii b/Master/texmf-dist/tex/context/base/core-sys.mkii
index 24975ffb634..54778eeed52 100644
--- a/Master/texmf-dist/tex/context/base/core-sys.mkii
+++ b/Master/texmf-dist/tex/context/base/core-sys.mkii
@@ -5,7 +5,7 @@
%D subtitle=System,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-sys.mkiv b/Master/texmf-dist/tex/context/base/core-sys.mkiv
index f61cabec3d2..88e0ebf23f1 100644
--- a/Master/texmf-dist/tex/context/base/core-sys.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-sys.mkiv
@@ -5,7 +5,7 @@
%D subtitle=System,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -21,7 +21,7 @@
%D Version checking:
-\def\newcontextversion#1%
+\unexpanded\def\newcontextversion#1%
{\doifelse{#1}\contextversion
{\let\newcontextversion\gobbleoneargument}
{\writeline
@@ -35,30 +35,26 @@
%D End of lines to the output. \TEX\ will map this onto the platform specific
%D line ending. I hate this mess.
-\edef\operatingsystem {\ctxwrite {os.platform}}
+\edef\operatingsystem {\cldcontext{os.platform}}
+\def \jobfilename {\cldcontext{environment.jobfilename or ""}}
+\def \jobfilesuffix {\cldcontext{environment.jobfilesuffix or ""}}
+\def \inputfilebarename{\cldcontext{environment.inputfilebarename or ""}}
+\def \inputfilesuffix {\cldcontext{environment.inputfilesuffix or ""}}
+\def \inputfilename {\cldcontext{environment.inputfilename or ""}}
+\def \outputfilename {\cldcontext{environment.outputfilename or ""}}
-\def \jobfilename {\ctxsprint{environment.jobfilename or ""}}
-\def \jobfilesuffix {\ctxsprint{environment.jobfilesuffix or ""}}
-\def \inputfilebarename{\ctxsprint{environment.inputfilebarename or ""}}
-\def \inputfilesuffix {\ctxsprint{environment.inputfilesuffix or ""}}
-\def \inputfilename {\ctxsprint{environment.inputfilename or ""}}
-\def \outputfilename {\ctxsprint{environment.outputfilename or ""}}
+\installcorenamespace{system}
-\newtoks \everysetupsystem
-
-\unexpanded\def\setupsystem
- {\dosingleargument\dosetupsystem}
-
-\def\dosetupsystem[#1]%
- {\getparameters[\??sv][#1]%
- \the\everysetupsystem}
+\installdirectcommandhandler \??system {system}
\appendtoks
- \edef\outputresolution{\@@svresolution}%
+ \edef\outputresolution{\directsystemparameter\c!resolution}%
+ \edef\outputfilename {\directsystemparameter\c!file }%
+ \edef\inputfilename {\directsystemparameter\c!inputfile }%
\to \everysetupsystem
\appendtoks
- \ifcase\@@svn
+ \ifcase\directsystemparameter\c!n\relax
% % 0 : unknown
\or
\setsystemmode\v!first % 1 : first run
@@ -71,21 +67,16 @@
\fi
\to \everysetupsystem
-\appendtoks
- \edef\outputfilename{\@@svfile}%
- \edef\inputfilename {\@@svinputfile}%
-\to \everysetupsystem
-
-\let\@@jobsuffix\s!unknown
+\let\m_system_job_suffix\s!unknown
\appendtoks
- \resetsystemmode{suffix-\@@jobsuffix}%
- \edef\@@jobsuffix{\jobsuffix}%
- \setsystemmode{suffix-\@@jobsuffix}%
+ \resetsystemmode{suffix-\m_system_job_suffix}%
+ \edef\m_system_job_suffix{\jobsuffix}%
+ \setsystemmode{suffix-\m_system_job_suffix}%
\to \everysetupsystem
\appendtoks
- \ctxlua {commands.updatefilenames("\inputfilename","\outputfilename")}%
+ \ctxcommand{updatefilenames("\inputfilename","\outputfilename")}%
\to \everysetupsystem
% Some mechanisms (see x-res-01) use either \jobfilename or
@@ -95,13 +86,11 @@
\def\jobfullname{\jobfilename.\jobfilesuffix}
-\def\setjobfullname#1% #1 = default if not given
+\unexpanded\def\setjobfullname#1% #1 = default if not given
{\doifelsenothing\jobfilename
{\let\jobfullname\empty}
{\doif\jobfilesuffix\c!tex{\edef\jobfullname{\jobfilename.#1}}}}
-\def\systemparameter#1{\executeifdefined{\??sv#1}\empty}
-
%D There are a couple of system states avaiable:
%D
%D \starttabulate [|T|T|]
@@ -130,7 +119,7 @@
\unexpanded\def\setuprandomize[#1]%
{\doifsomething{#1}
- {\bgroup
+ {\begingroup
% tex's time is in minutes
\scratchcounter\normaltime
\processaction
@@ -143,7 +132,7 @@
\s!unknown=>\scratchcounter#1]%
\expanded{\setrandomseed{\the\scratchcounter}}%
% \writestatus\m!system{randomseed: \the\scratchcounter}%
- \egroup}}
+ \endgroup}}
\setupsystem
[\c!directory=,
@@ -158,25 +147,9 @@
%D Remark: windows programs normally handle \type {cr|lf|crlf} but unix
%D is more picky, so we default to the \type {cr}. I never understood why
%D \type {crlf} was not used in all systems, since it makes most sense.
+%D But anyway, in \MKIV\ we avoid most of the complications anyway as we
+%D deal with much at the \LUA\ end.
-\def\dostartglobaldefs#1#2%
- {\edef\!!stringa{\the\globaldefs}%
- \ifnum\globaldefs#10
- \globaldefs-\globaldefs
- \fi
- \advance\globaldefs #21
- \setevalue{@gd@\the\globaldefs}{\!!stringa}}
-
-\def\dostopglobaldefs
- {\doifdefinedelse{@gd@\the\globaldefs}
- {\globaldefs\getvalue{@gd@\the\globaldefs}\relax}
- {\globaldefs\zerocount}}
-
-\unexpanded\def\startlocal {\dostartglobaldefs>-}
-\unexpanded\def\stoplocal {\dostopglobaldefs}
-\unexpanded\def\startglobal {\dostartglobaldefs<+}
-\unexpanded\def\stopglobal {\dostopglobaldefs}
-
\def\complexstart[#1]{\bgroup\getvalue{\e!start#1}}
\def\complexstop [#1]{\getvalue{\e!stop #1}\egroup}
@@ -186,133 +159,87 @@
\definecomplexorsimple\start
\definecomplexorsimple\stop
-% \def\dododefinestartstop[#1][#2]% todo: use indirect commands
-% {\getparameters
-% [\??be#1]
-% [\c!before=,
-% \c!after=,
-% \c!inbetween=,
-% \c!commands=,
-% \c!style=,
-% #2]%
-% \setuvalue{#1}%
-% {\groupedcommand
-% {\getvalue{\??be#1\c!commands}%
-% \dostarttagged\t!construct{#1}%
-% \dostartattributes{\??be#1}\c!style\c!color}
-% {\dostopattributes
-% \dostoptagged
-% \getvalue{\??be#1\c!inbetween}}}%
-% \setuvalue{\e!start#1}%
-% {\getvalue{\??be#1\c!before}%
-% \bgroup
-% \getvalue{\??be#1\c!commands}%
-% \dostarttagged\t!construct{#1}%
-% \dostartattributes{\??be#1}\c!style\c!color\empty}%
-% \setuvalue{\e!stop#1}%
-% {\dostopattributes
-% \dostoptagged
-% \egroup
-% \getvalue{\??be#1\c!after}}}
-%
-% \def\dodefinestartstop[#1][#2]%
-% {\def\docommand##1{\dododefinestartstop[##1][#2]}%
-% \processcommalist[#1]\docommand}
-%
-% \unexpanded\def\definestartstop
-% {\dodoubleargument\dodefinestartstop}
-%
-% \def\dosetupstartstop[#1][#2]%
-% {\def\docommand##1{\getparameters[\??be##1][#2]}%
-% \processcommalist[#1]\docommand}
-%
-% \unexpanded\def\setupstartstop
-% {\dodoubleargument\dosetupstartstop}
-
-
% \c!before \c!after \c!inbetween \c!commands \c!style \c!color
-\installcommandhandler{\??be}{startstop}{\??be}
+\installcorenamespace{startstop}
+
+\installcommandhandler \??startstop {startstop} \??startstop
\appendtoks
- \normalexpanded{\dodefinestartstop{\currentstartstop}}%
+ \setuevalue{\e!start\currentstartstop}{\syst_startstop_start {\currentstartstop}}%
+ \setuevalue{\e!stop \currentstartstop}{\syst_startstop_stop {\currentstartstop}}%
+ \setuevalue {\currentstartstop}{\syst_startstop_indeed{\currentstartstop}}%
\to \everydefinestartstop
-\unexpanded\def\dodefinestartstop#1%
- {\setuvalue{#1}%
- {\groupedcommand
- {\def\currentstartstop{#1}%
- \startstopparameter\c!commands
- \dostarttagged\t!construct\currentstartstop
- \dosetstartstopattributes\c!style\c!color}
- {\def\currentstartstop{#1}%
- \dostoptagged
- \startstopparameter\c!inbetween}}%
- \setuvalue{\e!start#1}%
- {\namedstartstopparameter{#1}\c!before
- \bgroup
- \def\currentstartstop{#1}%
- \startstopparameter\c!commands
+\unexpanded\def\syst_startstop_start#1%
+ {\namedstartstopparameter{#1}\c!before
+ \bgroup
+ \def\currentstartstop{#1}%
+ \startstopparameter\c!commands
+ \dostarttagged\t!construct\currentstartstop
+ \usestartstopstyleandcolor\c!style\c!color}
+
+\unexpanded\def\syst_startstop_stop#1%
+ {\dostoptagged
+ \egroup
+ \namedstartstopparameter{#1}\c!after}
+
+\unexpanded\def\syst_startstop_indeed#1%
+ {\groupedcommand
+ {\def\currentstartstop{#1}%
+ \startstopparameter\c!commands % will become setups
\dostarttagged\t!construct\currentstartstop
- \dosetstartstopattributes\c!style\c!color}%
- \setuvalue{\e!stop#1}%
- {\dostoptagged
- \egroup
- \namedstartstopparameter{#1}\c!after}}
-
-% \docommand kan niet worden gebruikt omdat deze macro
-% soms lokaal wordt gebruikt
-
-% te zijner tijd:
-%
-% \definevariable {pc} % ProtectedCommand
-%
-% \def\executeprotected#1%
-% {\csname\??pc\string#1\endcsname}
-%
-% \unexpanded\def\defineprotected#1#2%
-% {\expandafter\def\csname\??pc\string#2\endcsname}
-%
-% \unexpanded\def\defineunprotected#1%
-% {\def#1}
-%
-% \def\doprotected%
-% {\ifx\next\define
-% \let\next=\defineprotected
-% \else
-% \let\next=\executeprotected
-% \fi
-% \next}
-%
-% \def\unexpanded%
-% {\futurelet\next\doprotected}
-%
-% \unexpanded\define\ziezo{ziezo}
-%
-% \unexpanded\ziezo
+ \usestartstopstyleandcolor\c!style\c!color}
+ {\def\currentstartstop{#1}%
+ \dostoptagged
+ \startstopparameter\c!inbetween}}
+
+\installcorenamespace{highlight}
+
+\installcommandhandler \??highlight {highlight} \??highlight % we could do with less
+
+\appendtoks
+ \setuevalue\currenthighlight{\typo_highlights_indeed{\currenthighlight}}%
+\to \everydefinehighlight
+
+\ifdefined\dotaghighlight \else \let\dotaghighlight\relax \fi
+
+\unexpanded\def\typo_highlights_indeed#1% inline style/color switch
+ {\dontleavehmode\groupedcommand % otherwise wrong par number in tags
+ {\def\currenthighlight{#1}%
+ \dostarttagged\t!highlight\currenthighlight
+ \usehighlightstyleandcolor\c!style\c!color
+ \dotaghighlight}
+ {\dostoptagged}}
-\def\complexdefine[#1]#2#3%
- {\ifx#2\undefined
- \else
+\unexpanded\def\define
+ {\doifnextoptionalelse\syst_basics_define_yes\syst_basics_define_nop}
+
+\unexpanded\def\syst_basics_define_yes[#1]#2#3%
+ {\ifdefined#2%
\showmessage\m!system4{\string#2}%
\fi
- \ifcase0#1\def#2{#3}%
- \or\def#2##1{#3}%
- \or\def#2##1##2{#3}%
- \or\def#2##1##2##3{#3}%
- \or\def#2##1##2##3##4{#3}%
- \or\def#2##1##2##3##4##5{#3}%
- \or\def#2##1##2##3##4##5##6{#3}%
- \or\def#2##1##2##3##4##5##6##7{#3}%
- \or\def#2##1##2##3##4##5##6##7##8{#3}%
- \or\def#2##1##2##3##4##5##6##7##8##9{#3}%
- \else\def#2{#3}%
- \fi}
-
-\definecomplexorsimpleempty\define
+ \ifcase0#1\relax
+ \def#2{#3}\or
+ \def#2##1{#3}\or
+ \def#2##1##2{#3}\or
+ \def#2##1##2##3{#3}\or
+ \def#2##1##2##3##4{#3}\or
+ \def#2##1##2##3##4##5{#3}\or
+ \def#2##1##2##3##4##5##6{#3}\or
+ \def#2##1##2##3##4##5##6##7{#3}\or
+ \def#2##1##2##3##4##5##6##7##8{#3}\or
+ \def#2##1##2##3##4##5##6##7##8##9{#3}\else
+ \def#2{#3}\fi}
+
+\unexpanded\def\syst_basics_define_nop#1#2%
+ {\ifdefined#1%
+ \showmessage\m!system4{\string#1}%
+ \fi
+ \def#1{#2}}
% \startluacode
-% local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+% local contextsprint, ctxcatcodes = context.sprint, tex.ctxcatcodes
% local format, match, gmatch, rep = string.format, string.match, string.gmatch, string.rep
% local empty = {
% "single",
@@ -341,38 +268,38 @@
% else
% n = 0
% end
-% texsprint(ctxcatcodes,format("\\unexpanded\\def\\%s",cmd))
+% contextsprint(ctxcatcodes,format("\\unexpanded\\def\\%s",cmd))
% if #a > 0 then
-% texsprint(ctxcatcodes,format("{\\do%sempty\\do%s}",empty[#a],cmd))
-% texsprint(ctxcatcodes,format("\\def\\do%s",cmd))
+% contextsprint(ctxcatcodes,format("{\\do%sempty\\do%s}",empty[#a],cmd))
+% contextsprint(ctxcatcodes,format("\\def\\do%s",cmd))
% for i=1,#a do
-% texsprint(ctxcatcodes,"[#",i,"]")
+% contextsprint(ctxcatcodes,"[#",i,"]")
% end
-% texsprint(ctxcatcodes,"{")
+% contextsprint(ctxcatcodes,"{")
% for i=#a,1,-1 do
-% texsprint(ctxcatcodes,format("\\if%sargument",check[i]))
-% texsprint(ctxcatcodes,format("\\def\\next{\\dodo%s",cmd))
+% contextsprint(ctxcatcodes,format("\\if%sargument",check[i]))
+% contextsprint(ctxcatcodes,format("\\def\\next{\\dodo%s",cmd))
% for j=1,#a-i do
-% texsprint(ctxcatcodes,format("[%s]",a[j]))
+% contextsprint(ctxcatcodes,format("[%s]",a[j]))
% end
% for j=1,i do
-% texsprint(ctxcatcodes,format("[#%s]",j))
+% contextsprint(ctxcatcodes,format("[#%s]",j))
% end
-% texsprint(ctxcatcodes,"}")
+% contextsprint(ctxcatcodes,"}")
% if i == 1 then
-% texsprint(ctxcatcodes,rep("\\fi",#a))
+% contextsprint(ctxcatcodes,rep("\\fi",#a))
% else
-% texsprint(ctxcatcodes,"\\else")
+% contextsprint(ctxcatcodes,"\\else")
% end
% end
-% texsprint(ctxcatcodes,"\\next}")
-% texsprint(ctxcatcodes,format("\\def\\dodo%s",cmd))
+% contextsprint(ctxcatcodes,"\\next}")
+% contextsprint(ctxcatcodes,format("\\def\\dodo%s",cmd))
% for i=1,#a do
-% texsprint(ctxcatcodes,"[#",i,"]")
+% contextsprint(ctxcatcodes,"[#",i,"]")
% end
% end
% for i=1,n do
-% texsprint(ctxcatcodes,"#",#a+i)
+% contextsprint(ctxcatcodes,"#",#a+i)
% end
% end
% \stopluacode
@@ -387,73 +314,19 @@
% \whateverb[A][B]{C}{D}
% \stoptext
+%D This is a checked variant of \type {\getvalue}.
+
\unexpanded\def\macroname#1% brrr
- {\executeifdefined{#1}\empty}
-
-\def\usecommands#1%
- {\bgroup
- \def\docommand##1{\setbox0\hbox{\getvalue{\string##1}##1}}%
- \processcommalist[#1]\docommand
- \egroup}
-
-\newif\ifforcefileexpansion % handy for document level overload
-
-%D The next implementation is about 4 times as faster than a
-%D processaction alternative on an string of average length.
-%D Since this feature is used in XML processing, it made sense
-%D to support this faster alternative. It's installable as well.
-%D
-%D We keep this around for \MKII\ \XML\ but it's not used in \MKIV\
-%D code as expansion is controlled in another way there.
-
-\def\installexpander#1#2#3% changed, no longer \convert..\to...
- {\setvalue{\s!do\c!expansion#1l}{#2}%
- \setvalue{\s!do\c!expansion#1g}{#3}}%
-
-% \convertexpanded is obsolete
-
-\long\def\doconvertexpanded#1#2#3% #4 % [l|g] \cs {kind} {data}
- {\csname % that we assign all exp a value
- \s!do\c!expansion
- \ifforcefileexpansion
- \v!yes
- \else\ifcsname\s!do\c!expansion#3#1\endcsname
- #3%
- \else
- \s!default
- \fi\fi
- #1%
- \endcsname#2}% #3
-
-\long\def\defconvertexpanded {\doconvertexpanded l}
-\long\def\gdefconvertexpanded{\doconvertexpanded g}
-
-\installexpander\v!command \defconvertedcommand \gdefconvertedcommand
-\installexpander\s!default \defconvertedargument \gdefconvertedargument
-\installexpander\empty \defconvertedargument \gdefconvertedargument
-\installexpander\v!no \defconvertedargument \gdefconvertedargument
-\installexpander\v!yes \defconvertedmeaning \gdefconvertedmeaning
-\installexpander\v!yes \defconvertedmeaning \gdefconvertedmeaning
-\installexpander\v!strict \defreducedargument \gdefreducedargument
-\installexpander {utf} \defreducedtoutf \gdefreducedtoutf
-
-\def\dodefconvertedmeaning#1#2#3% watch the double expansion !
- {\bgroup
- \xdef\@@globalexpanded{#3}%
- \xdef\@@globalexpanded{\@@globalexpanded}%
- \egroup
- #1#2\@@globalexpanded}
+ {\csname\ifcsname#1\endcsname#1\else\s!empty\fi\endcsname}
-\def\defconvertedmeaning {\dodefconvertedmeaning\defconvertedcommand}
-\def\gdefconvertedmeaning{\dodefconvertedmeaning\gdefconvertedcommand}
+% %D A weird one that I probably needed once, so it might as well become
+% %D obsolete.
+%
+% \unexpanded\def\usecommands#1%
+% {\begingroup
+% \def\docommand##1{\setbox\scratchbox\hbox{\csname\string##1\endcsname##1}}%
+% \processcommalist[#1]\docommand
+% \endgroup}
-\def\dodefreducedargument#1#2#3%
- {\begingroup
- \reducetocoding[raw]%
- \edef\ascii{#3}%
- \expandafter\endgroup\expandafter#1\expandafter#2\expandafter{\ascii}}
-\def\defreducedargument {\dodefreducedargument\edef}
-\def\gdefreducedargument{\dodefreducedargument\xdef}
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-two.lua b/Master/texmf-dist/tex/context/base/core-two.lua
index 51f6dd890b8..f94b102bced 100644
--- a/Master/texmf-dist/tex/context/base/core-two.lua
+++ b/Master/texmf-dist/tex/context/base/core-two.lua
@@ -7,7 +7,6 @@ if not modules then modules = { } end modules ['core-two'] = {
}
local remove, concat = table.remove, table.concat
-local texprint = tex.print
local allocate = utilities.storage.allocate
--[[ldx--
@@ -53,6 +52,19 @@ function jobpasses.savetagged(id,tag,str)
jti[tag] = str
end
+function jobpasses.getdata(id,index,default)
+ local jti = collected[id]
+ local value = jit and jti[index]
+ return value ~= "" and value or default or ""
+end
+
+function jobpasses.getfield(id,index,tag,default)
+ local jti = collected[id]
+ jti = jti and jti[index]
+ local value = jti and jti[tag]
+ return value ~= "" and value or default or ""
+end
+
function jobpasses.getcollected(id)
return collected[id] or { }
end
@@ -61,82 +73,85 @@ function jobpasses.gettobesaved(id)
return allocate(id)
end
-function jobpasses.get(id)
+local function get(id)
local jti = collected[id]
if jti and #jti > 0 then
- texprint(remove(jti,1))
+ return remove(jti,1)
end
end
-function jobpasses.first(id)
+local function first(id)
local jti = collected[id]
if jti and #jti > 0 then
- texprint(jti[1])
+ return jti[1]
end
end
-function jobpasses.last(id)
+local function last(id)
local jti = collected[id]
if jti and #jti > 0 then
- texprint(jti[#jti])
+ return jti[#jti]
end
end
-jobpasses.check = jobpasses.first
-
-function jobpasses.find(id,n)
+local function find(id,n)
local jti = collected[id]
if jti and jti[n] then
- texprint(jti[n])
+ return jti[n]
end
end
-function jobpasses.count(id)
+local function count(id)
local jti = collected[id]
- texprint((jti and #jti) or 0)
+ return jti and #jti or 0
end
-function jobpasses.list(id)
+local function list(id)
local jti = collected[id]
if jti then
- texprint(concat(jti,','))
+ return concat(jti,',')
end
end
-function jobpasses.doifinlistelse(id,str)
+local function inlist(id,str)
local jti = collected[id]
if jti then
- local found = false
for _, v in next, jti do
if v == str then
- found = true
- break
+ return true
end
end
- commands.testcase(found)
- else
- commands.testcase(false)
end
+ return false
end
+local check = first
+
--
-function jobpasses.savedata(id,data)
- local jti = allocate(id)
- jti[#jti+1] = data
- return #jti
-end
+jobpasses.get = get
+jobpasses.first = first
+jobpasses.last = last
+jobpasses.find = find
+jobpasses.list = list
+jobpasses.count = count
+jobpasses.check = check
+jobpasses.inlist = inlist
-function jobpasses.getdata(id,index,default)
- local jti = collected[id]
- local value = jit and jti[index]
- texprint((value ~= "" and value) or default or "")
-end
+-- interface
-function jobpasses.getfield(id,index,tag,default)
- local jti = collected[id]
- jti = jti and jti[index]
- local value = jti and jti[tag]
- texprint((value ~= "" and value) or default or "")
-end
+function commands.gettwopassdata (id) local r = get (id) if r then context(r) end end
+function commands.getfirsttwopassdata(id) local r = first(id) if r then context(r) end end
+function commands.getlasttwopassdata (id) local r = last (id) if r then context(r) end end
+function commands.findtwopassdata (id,n) local r = find (id,n) if r then context(r) end end
+function commands.gettwopassdatalist (id) local r = list (id) if r then context(r) end end
+function commands.counttwopassdata (id) local r = count(id) if r then context(r) end end
+function commands.checktwopassdata (id) local r = check(id) if r then context(r) end end
+
+commands.definetwopasslist = jobpasses.define
+commands.savetwopassdata = jobpasses.save
+commands.savetaggedtwopassdata = jobpasses.savetagged
+function commands.doifelseintwopassdata(id,str)
+ commands.testcase(inlist(id,str))
+end
diff --git a/Master/texmf-dist/tex/context/base/core-two.mkii b/Master/texmf-dist/tex/context/base/core-two.mkii
index 0f2e0048c8e..235be988edc 100644
--- a/Master/texmf-dist/tex/context/base/core-two.mkii
+++ b/Master/texmf-dist/tex/context/base/core-two.mkii
@@ -5,7 +5,7 @@
%D subtitle=Two Pass Data,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-two.mkiv b/Master/texmf-dist/tex/context/base/core-two.mkiv
index 332b2c89bbb..b08914ef407 100644
--- a/Master/texmf-dist/tex/context/base/core-two.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-two.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Two Pass Data,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -71,36 +71,51 @@
\unprotect
-\let\twopassdatalist\empty
+\registerctxluafile{core-two}{1.001}
-\newif\iftwopassdatafound
+\def\immediatesavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxcommand {savetwopassdata('#1',"#3")}}}
+\def\savetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata('#1',"#3")}}}
+\def\lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatecommand{savetwopassdata('#1',"#3")}}}
+\def\savetaggedtwopassdata #1#2#3#4{\normalexpanded{\noexpand\ctxcommand {savetaggedtwopassdata('#1','#3',"#4")}}}
+\def\lazysavetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\ctxlatecommand{savetaggedtwopassdata('#1','#3',"#4")}}}
-\registerctxluafile{core-two}{1.001}
+% temp hack: needs a proper \starteverytimeluacode
-%D I'm not that sure if this behaves exactly like mkii. This needs a cleanup.
+\setfalse\twopassdatafound
+\let \twopassdata \empty
+\let \twopassdatalist \empty
-\def\immediatesavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlua {job.passes.save('#1',"#3")}}}
-\def\savetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatelua{job.passes.save('#1',"#3")}}}
-\def\lazysavetwopassdata #1#2#3{\normalexpanded{\noexpand\ctxlatelua{job.passes.save('#1',"#3")}}}
-\def\savetaggedtwopassdata #1#2#3#4{\normalexpanded{\noexpand\ctxlua {job.passes.savetagged('#1','#3',"#4")}}}
-\def\lazysavetaggedtwopassdata#1#2#3#4{\normalexpanded{\noexpand\ctxlatelua{job.passes.savetagged('#1','#3',"#4")}}}
+\newif \iftwopassdatafound % obsolete, will go
-% temp hack: needs a proper \starteverytimeluacode
+\def\syst_twopass_check
+ {\ifx\twopassdata\empty
+ \twopassdatafoundfalse % obsolete
+ \setfalse\twopassdatafound
+ \else
+ \twopassdatafoundtrue % obsolete
+ \settrue\twopassdatafound
+ \fi}
+
+\def\syst_twopass_set_not_found
+ {\twopassdatafoundfalse % obsolete
+ \setfalse\twopassdatafound}
-\def\testtwopassdata{\ifx\twopassdata\empty\twopassdatafoundfalse\else\twopassdatafoundtrue\fi}
+\def\syst_twopass_set_found
+ {\twopassdatafoundtrue % obsolete
+ \settrue\twopassdatafound}
-% todo: move the edef to lua
+\unexpanded\def\definetwopasslist #1{\ctxcommand{definetwopasslist('#1')}}
+\unexpanded\def\gettwopassdata #1{\edef\twopassdata {\ctxcommand{gettwopassdata ("#1")}}\syst_twopass_check}
+\unexpanded\def\checktwopassdata #1{\edef\twopassdata {\ctxcommand{checktwopassdata ("#1")}}\syst_twopass_check}
+\unexpanded\def\findtwopassdata #1#2{\edef\twopassdata {\ctxcommand{findtwopassdata("#1","#2")}}\syst_twopass_check}
+\unexpanded\def\getfirsttwopassdata #1{\edef\twopassdata {\ctxcommand{getfirsttwopassdata ("#1")}}\syst_twopass_check}
+\unexpanded\def\getlasttwopassdata #1{\edef\twopassdata {\ctxcommand{getlasttwopassdata ("#1")}}%
+ \edef\noftwopassitems{\ctxcommand{counttwopassdata ("#1")}}\syst_twopass_check}
+\unexpanded\def\getnamedtwopassdatalist#1#2{\edef #1{\ctxcommand{gettwopassdatalist ("#2")}}}
+\unexpanded\def\gettwopassdatalist #1{\edef\twopassdatalist{\ctxcommand{gettwopassdatalist ("#1")}}}
-\unexpanded\def\definetwopasslist #1{\ctxlua{job.passes.define('#1')}}
-\def\gettwopassdata #1{\edef\twopassdata{\ctxlua{job.passes.get("#1")}}\testtwopassdata}
-\def\checktwopassdata #1{\edef\twopassdata{\ctxlua{job.passes.check("#1")}}\testtwopassdata}
-\def\findtwopassdata #1#2{\edef\twopassdata{\ctxlua{job.passes.find("#1","#2")}}\testtwopassdata}
-\def\getfirsttwopassdata #1{\edef\twopassdata{\ctxlua{job.passes.first("#1")}}\testtwopassdata}
-\def\getlasttwopassdata #1{\edef\twopassdata{\ctxlua{job.passes.last("#1")}}\edef\noftwopassitems{\ctxlua{job.passes.count("#1")}}\testtwopassdata}
-\def\getnamedtwopassdatalist#1#2{\edef#1{\ctxlua{job.passes.list("#2")}}}
-\def\gettwopassdatalist #1{\edef\twopassdatalist{\ctxlua{job.passes.list("#1")}}}
-\def\doifelseintwopassdata #1#2{\ctxlua{job.passes.doifinlistelse("#1","#2")}}
+\unexpanded\def\doifelseintwopassdata #1#2{\ctxcommand{doifelseintwopassdata("#1","#2")}}
-\let\getfromtwopassdata\findtwopassdata
+ \let\getfromtwopassdata \findtwopassdata
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-uti.lua b/Master/texmf-dist/tex/context/base/core-uti.lua
index 02411f13d99..1657a75e26d 100644
--- a/Master/texmf-dist/tex/context/base/core-uti.lua
+++ b/Master/texmf-dist/tex/context/base/core-uti.lua
@@ -19,9 +19,11 @@ saves much runtime but at the cost of more memory usage.</p>
local format, match = string.format, string.match
local next, type, tostring = next, type, tostring
+local concat = table.concat
local definetable = utilities.tables.definetable
local accesstable = utilities.tables.accesstable
+local migratetable = utilities.tables.migratetable
local serialize = table.serialize
local packers = utilities.packers
local allocate = utilities.storage.allocate
@@ -32,7 +34,7 @@ local report_jobcontrol = logs.reporter("jobcontrol")
job = job or { }
local job = job
-job.version = 1.14
+job.version = 1.19
-- some day we will implement loading of other jobs and then we need
-- job.jobs
@@ -51,10 +53,18 @@ end
job.comment(format("version: %1.2f",job.version))
+local enabled = true
+
+directives.register("job.save",function(v) enabled = v end)
+
+function job.disablesave() -- can be command
+ enabled = false
+end
+
function job.initialize(loadname,savename)
job.load(loadname) -- has to come after structure is defined !
luatex.registerstopactions(function()
- if not status.lasterrorstring or status.lasterrorstring == "" then
+ if enabled and not status.lasterrorstring or status.lasterrorstring == "" then
job.save(savename)
end
end)
@@ -66,7 +76,7 @@ end
-- as an example we implement variables
-local tobesaved, collected, checksums = allocate(), allocate(), allocate()
+local tobesaved, collected, checksums = allocate(), allocate(), allocate()
local jobvariables = {
collected = collected,
@@ -125,9 +135,11 @@ local jobpacker = packers.new(packlist,1.01)
job.pack = true
-local _save_, _load_ = { }, { } -- registers timing
+directives.register("job.pack",function(v) pack = v end)
+
+local _save_, _load_, _others_ = { }, { }, { } -- registers timing
-function job.save(filename)
+function job.save(filename) -- we could return a table but it can get pretty large
statistics.starttiming(_save_)
local f = io.open(filename,'w')
if f then
@@ -135,9 +147,13 @@ function job.save(filename)
f:write("-- ",comment[c],"\n")
end
f:write("\n")
+ f:write("local utilitydata = { }\n")
+ f:write("\n")
for l=1,#savelist do
- local list = savelist[l]
- local target, data, finalizer = list[1], list[2], list[4]
+ local list = savelist[l]
+ local target = format("utilitydata.%s",list[1])
+ local data = list[2]
+ local finalizer = list[4]
if type(finalizer) == "function" then
finalizer()
end
@@ -149,15 +165,17 @@ function job.save(filename)
end
if job.pack then
packers.strip(jobpacker)
- f:write(serialize(jobpacker,"job.packed",true,true),"\n")
+ f:write(serialize(jobpacker,"utilitydata.job.packed",true,true),"\n")
end
+ f:write("\n")
+ f:write("return utilitydata\n")
+ f:write("\n")
f:close()
end
statistics.stoptiming(_save_)
end
-function job.load(filename)
- statistics.starttiming(_load_)
+local function load(filename)
local data = io.loaddata(filename)
if data and data ~= "" then
local version = tonumber(match(data,"^-- version: ([%d%.]+)"))
@@ -165,24 +183,51 @@ function job.load(filename)
report_jobcontrol("version mismatch with jobfile: %s <> %s", version or "?", job.version)
else
local data = loadstring(data)
- if data then
- data()
- end
- for l=1,#savelist do
- local list = savelist[l]
- local target, initializer = list[1], list[3]
- local result = mark(accesstable(target))
- packers.unpack(result,job.packed,true)
- if type(initializer) == "function" then
- initializer(result)
- end
+ return data and data()
+ end
+ end
+end
+
+function job.load(filename)
+ statistics.starttiming(_load_)
+ local utilitydata = load(filename)
+ if utilitydata then
+ local jobpacker = utilitydata.job.packed
+ for l=1,#savelist do
+ local list = savelist[l]
+ local target = list[1]
+ local initializer = list[3]
+ local result = accesstable(target,utilitydata)
+ packers.unpack(result,jobpacker,true)
+ migratetable(target,mark(result))
+ if type(initializer) == "function" then
+ initializer(result)
end
- job.packed = nil
end
end
statistics.stoptiming(_load_)
end
+function job.loadother(filename)
+ statistics.starttiming(_load_)
+ _others_[#_others_+1] = file.nameonly(filename)
+ local utilitydata = load(filename)
+ if utilitydata then
+ local jobpacker = utilitydata.job.packed
+ local unpacked = { }
+ for l=1,#savelist do
+ local list = savelist[l]
+ local target = list[1]
+ local result = accesstable(target,utilitydata)
+ packers.unpack(result,jobpacker,true)
+ migratetable(target,result,unpacked)
+ end
+ unpacked.job.packed = nil -- nicer in inspecting
+ return unpacked
+ end
+ statistics.stoptiming(_load_)
+end
+
-- eventually this will end up in strc-ini
statistics.register("startup time", function()
@@ -190,8 +235,18 @@ statistics.register("startup time", function()
end)
statistics.register("jobdata time",function()
- if statistics.elapsedindeed(_save_) or statistics.elapsedindeed(_load_) then
- return format("%s seconds saving, %s seconds loading", statistics.elapsedtime(_save_), statistics.elapsedtime(_load_))
+ if enabled then
+ if #_others_ > 0 then
+ return format("%s seconds saving, %s seconds loading, other files: %s",statistics.elapsedtime(_save_),statistics.elapsedtime(_load_),concat(_others_," "))
+ else
+ return format("%s seconds saving, %s seconds loading",statistics.elapsedtime(_save_),statistics.elapsedtime(_load_))
+ end
+ else
+ if #_others_ > 0 then
+ return format("nothing saved, %s seconds loading, other files: %s",statistics.elapsedtime(_load_),concat(_others_," "))
+ else
+ return format("nothing saved, %s seconds loading",statistics.elapsedtime(_load_))
+ end
end
end)
@@ -212,13 +267,15 @@ statistics.register("randomizer", function()
end)
function statistics.formatruntime(runtime)
- local shipped = tex.count['nofshipouts']
- local pages = tex.count['realpageno'] - 1
- if shipped > 0 or pages > 0 then
- local persecond = shipped / runtime
- if pages == 0 then pages = shipped end
- return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond)
- else
- return format("%s seconds",runtime)
+ if not environment.initex then -- else error when testing as not counters yet
+ local shipped = tex.count['nofshipouts']
+ local pages = tex.count['realpageno'] - 1
+ if shipped > 0 or pages > 0 then
+ local persecond = shipped / runtime
+ if pages == 0 then pages = shipped end
+ return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond)
+ else
+ return format("%s seconds",runtime)
+ end
end
end
diff --git a/Master/texmf-dist/tex/context/base/core-uti.mkii b/Master/texmf-dist/tex/context/base/core-uti.mkii
index 5b8f66f5008..bd2fa46a0ff 100644
--- a/Master/texmf-dist/tex/context/base/core-uti.mkii
+++ b/Master/texmf-dist/tex/context/base/core-uti.mkii
@@ -5,7 +5,7 @@
%D subtitle=Utility File Handling,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-uti.mkiv b/Master/texmf-dist/tex/context/base/core-uti.mkiv
index 46a1e398af1..9a783f78a35 100644
--- a/Master/texmf-dist/tex/context/base/core-uti.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-uti.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Utility File Handling,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,7 +17,7 @@
\registerctxluafile{core-uti}{1.001}
-\def\savecurrentvalue#1#2%
+\def\savecurrentvalue#1#2% immediate, so not \unexpanded
{\ctxlua{job.variables.save("\strippedcsname#1","#2")}}
\appendtoks
@@ -35,11 +35,4 @@
}%
\to \everyjob
-\def\notuccompression{\ctxlua{job.pack=false}}
-
-%D Some styles might use these use these commands:
-
-\def\installprogram {\dosingleempty\doinstallprogram}
-\def\doinstallprogram[#1]{\gobbleoneargument}
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/core-var.mkii b/Master/texmf-dist/tex/context/base/core-var.mkii
index 4de1b871848..55c587fbfaf 100644
--- a/Master/texmf-dist/tex/context/base/core-var.mkii
+++ b/Master/texmf-dist/tex/context/base/core-var.mkii
@@ -5,7 +5,7 @@
%D subtitle=Variables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/core-var.mkiv b/Master/texmf-dist/tex/context/base/core-var.mkiv
index 45a593ee750..26559f2467f 100644
--- a/Master/texmf-dist/tex/context/base/core-var.mkiv
+++ b/Master/texmf-dist/tex/context/base/core-var.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Variables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,6 +15,8 @@
\unprotect
+%D Much of this will move to *-ini files.
+
%D We introduce a couple of variables that are used all over
%D \CONTEXT. Alternatively we could define them in each module
%D but as they are part of the bigger picture we prefer to do
@@ -65,12 +67,7 @@
\newtoks \everybeforepagebody
\newtoks \everyafterpagebody
-\let \everypagebody \everybeforepagebody % backward compatible
-
-%D Multipass:
-
-\newtoks \everybeforeutilityread
-\newtoks \everyafterutilityread
+\let \everypagebody \everybeforepagebody % backward compatible, will become obsolete
%D Floats:
@@ -86,8 +83,8 @@
\newtoks \everyendofpar
%newtoks \everyparflush
-\def\bpar{\the\everybeginofpar\ignorespaces} % may interfere with \everypar
-\def\epar{\ifhmode\removeunwantedspaces\the\everyendofpar\fi} % test prevents problems with \bpar\epar
+\unexpanded\def\bpar{\dostarttagged\t!paragraph\empty\the\everybeginofpar\ignorespaces} % may interfere with \everypar
+\unexpanded\def\epar{\ifhmode\removeunwantedspaces\the\everyendofpar\fi\dostoptagged } % test prevents problems with \bpar\epar
%D Lists:
@@ -235,19 +232,8 @@
%D Add-ons:
-\let\setlayoutcomponentattribute \gobbletwoarguments
+\let\setlayoutcomponentattribute \gobbleoneargument
\let\resetlayoutcomponentattribute\relax
\let\layoutcomponentboxattribute \empty
-
-%D Concepts:
-
-\newconstant\conceptmode
-
-\def\doifconcepttracing
- {\ifnum\conceptmode>\plustwo
- \expandafter\firstofoneargument
- \else
- \expandafter\gobbleoneargument
- \fi}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/data-bin.lua b/Master/texmf-dist/tex/context/base/data-bin.lua
index b18526c77b7..1d1e8b74959 100644
--- a/Master/texmf-dist/tex/context/base/data-bin.lua
+++ b/Master/texmf-dist/tex/context/base/data-bin.lua
@@ -14,13 +14,13 @@ function resolvers.findbinfile(filename,filetype)
end
function resolvers.openbinfile(filename)
- return methodhandler('loaders',filename)
+ return methodhandler('loaders',filename) -- a bit weird: load
end
function resolvers.loadbinfile(filename,filetype)
local fname = methodhandler('finders',filename,filetype)
if fname and fname ~= "" then
- return resolvers.openbinfile(fname)
+ return resolvers.openbinfile(fname) -- a bit weird: open
else
return resolvers.loaders.notfound()
end
diff --git a/Master/texmf-dist/tex/context/base/data-env.lua b/Master/texmf-dist/tex/context/base/data-env.lua
index 108858ccc14..2d9787b91bb 100644
--- a/Master/texmf-dist/tex/context/base/data-env.lua
+++ b/Master/texmf-dist/tex/context/base/data-env.lua
@@ -89,12 +89,12 @@ local relations = allocate { -- todo: handlers also here
mp = {
names = { "mp" },
variable = 'MPINPUTS',
- suffixes = { 'mp' },
+ suffixes = { 'mp', 'mpvi', 'mpiv', 'mpii' },
},
tex = {
names = { "tex" },
variable = 'TEXINPUTS',
- suffixes = { 'tex', "mkiv", "mkiv", "mkii" },
+ suffixes = { 'tex', "mkvi", "mkiv", "mkii" },
},
icc = {
names = { "icc", "icc profile", "icc profiles" },
@@ -231,7 +231,7 @@ end
resolvers.updaterelations() -- push this in the metatable -> newindex
local function simplified(t,k)
- return rawget(t,lower(gsub(k," ","")))
+ return k and rawget(t,lower(gsub(k," ",""))) or nil
end
setmetatableindex(formats, simplified)
diff --git a/Master/texmf-dist/tex/context/base/data-exp.lua b/Master/texmf-dist/tex/context/base/data-exp.lua
index 11e69bcae5d..52368f8a82e 100644
--- a/Master/texmf-dist/tex/context/base/data-exp.lua
+++ b/Master/texmf-dist/tex/context/base/data-exp.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['data-exp'] = {
license = "see context related readme files",
}
-local format, find, gmatch, lower = string.format, string.find, string.gmatch, string.lower
+local format, find, gmatch, lower, char, sub = string.format, string.find, string.gmatch, string.lower, string.char, string.sub
local concat, sort = table.concat, table.sort
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
local Ct, Cs, Cc, P, C, S = lpeg.Ct, lpeg.Cs, lpeg.Cc, lpeg.P, lpeg.C, lpeg.S
@@ -26,19 +26,6 @@ local resolvers = resolvers
-- all, when working on the main resolver code, I don't want to scroll
-- past this every time. See data-obs.lua for the gsub variant.
--- {a,b,c,d}
--- a,b,c/{p,q,r},d
--- a,b,c/{p,q,r}/d/{x,y,z}//
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
--- a{b,c}{d,e}f
--- {a,b,c,d}
--- {a,b,c/{p,q,r},d}
--- {a,b,c/{p,q,r}/d/{x,y,z}//}
--- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
--- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
--- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-
local function f_first(a,b)
local t, n = { }, 0
for s in gmatch(b,"[^,]+") do
@@ -95,12 +82,9 @@ local function splitpathexpr(str, newlist, validate) -- I couldn't resist lpeggi
str = lpegmatch(stripper_1,str)
if validate then
for s in gmatch(str,"[^,]+") do
- local restoreslashes = false
- if find(s, "//$") then restoreslashes = true end
s = validate(s)
if s then
n = n + 1 ; t[n] = s
- if restoreslashes and not find(s, "//$") then t[n] = t[n] .. '//' end
end
end
else
@@ -133,41 +117,56 @@ function resolvers.expandedpathfromlist(pathlist)
return newlist
end
+-- {a,b,c,d}
+-- a,b,c/{p,q,r},d
+-- a,b,c/{p,q,r}/d/{x,y,z}//
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a,b,c/{p,q/{x,y,z},r},d/{p,q,r}
+-- a{b,c}{d,e}f
+-- {a,b,c,d}
+-- {a,b,c/{p,q,r},d}
+-- {a,b,c/{p,q,r}/d/{x,y,z}//}
+-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
+-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
+
local cleanup = lpeg.replacer {
{ "!" , "" },
{ "\\" , "/" },
}
-local homedir
-
-function resolvers.cleanpath(str)
- if not homedir then
- homedir = lpegmatch(cleanup,environment.homedir or "")
- if homedir == string.char(127) or homedir == "" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if find(str,"~") then
- return "" -- special case
- else
- return str and lpegmatch(cleanup,str)
- end
- end
- else
- cleanup = lpeg.replacer {
- { "!" , "" },
- { "\\" , "/" },
- { "~" , homedir },
- }
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str)
+function resolvers.cleanpath(str) -- tricky, maybe only simple paths
+ local doslashes = (P("\\")/"/" + 1)^0
+ local donegation = (P("!") /"" )^0
+ local homedir = lpegmatch(Cs(donegation * doslashes),environment.homedir or "")
+ if homedir == "~" or homedir == "" or not lfs.isdir(homedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent paths")
+ end
+ function resolvers.cleanpath(str)
+ if not str or find(str,"~") then
+ return "" -- special case
+ else
+ return lpegmatch(cleanup,str)
end
end
+ else
+ local dohome = ((P("~")+P("$HOME"))/homedir)^0
+ local cleanup = Cs(donegation * dohome * doslashes)
+ function resolvers.cleanpath(str)
+ return str and lpegmatch(cleanup,str) or ""
+ end
end
return resolvers.cleanpath(str)
end
+-- print(resolvers.cleanpath(""))
+-- print(resolvers.cleanpath("!"))
+-- print(resolvers.cleanpath("~"))
+-- print(resolvers.cleanpath("~/test"))
+-- print(resolvers.cleanpath("!~/test"))
+-- print(resolvers.cleanpath("~/test~test"))
+
-- This one strips quotes and funny tokens.
local expandhome = P("~") / "$HOME" -- environment.homedir
@@ -192,8 +191,8 @@ end
local cache = { }
----- splitter = Ct(lpeg.splitat(S(ostype == "windows" and ";" or ":;"))) -- maybe add ,
-local splitter = Ct(lpeg.splitat(";")) -- as we move towards urls, prefixes and use tables we no longer do :
+----- splitter = lpeg.tsplitat(S(ostype == "windows" and ";" or ":;")) -- maybe add ,
+local splitter = lpeg.tsplitat(";") -- as we move towards urls, prefixes and use tables we no longer do :
local backslashswapper = lpeg.replacer("\\","/")
@@ -267,13 +266,22 @@ end
--~ test("ãƒ’ãƒ©ã‚®ãƒŽæ˜Žæœ /Pro W3;")
--~ test("ãƒ’ãƒ©ã‚®ãƒŽæ˜Žæœ Pro W3")
-local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+-- a lot of this caching can be stripped away when we have ssd's everywhere
+--
+-- we could cache all the (sub)paths here if needed
local attributes, directory = lfs.attributes, lfs.dir
+local weird = P(".")^1 + lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local timer = { }
+local scanned = { }
+local nofscans = 0
+local scancache = { }
+
local function scan(files,spec,path,n,m,r)
- local full = (path == "" and spec) or (spec .. path .. '/')
- local dirs, nofdirs = { }, 0
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
for name in directory(full) do
if not lpegmatch(weird,name) then
local mode = attributes(full..name,'mode')
@@ -311,23 +319,120 @@ local function scan(files,spec,path,n,m,r)
files, n, m, r = scan(files,spec,dirs[i],n,m,r)
end
end
+ scancache[sub(full,1,-2)] = files
return files, n, m, r
end
-function resolvers.scanfiles(path,branch)
+local fullcache = { }
+
+function resolvers.scanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = fullcache[realpath]
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
if trace_locating then
- report_expansions("scanning path '%s', branch '%s'",path, branch or path)
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
end
- local realpath = resolvers.resolve(path) -- no shortcut
local files, n, m, r = scan({ },realpath .. '/',"",0,0,0)
- files.__path__ = path -- can be selfautoparent:texmf-whatever
- files.__files__ = n
- files.__directories__ = m
- files.__remappings__ = r
+ files.__path__ = path -- can be selfautoparent:texmf-whatever
+ files.__files__ = n
+ files.__directories__ = m
+ files.__remappings__ = r
if trace_locating then
report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ fullcache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+local function simplescan(files,spec,path) -- first match only, no map and such
+ local full = (path == "" and spec) or (spec .. path .. '/')
+ local dirs = { }
+ local nofdirs = 0
+ for name in directory(full) do
+ if not lpegmatch(weird,name) then
+ local mode = attributes(full..name,'mode')
+ if mode == 'file' then
+ if not files[name] then
+ -- only first match
+ files[name] = path
+ end
+ elseif mode == 'directory' then
+ nofdirs = nofdirs + 1
+ if path ~= "" then
+ dirs[nofdirs] = path..'/'..name
+ else
+ dirs[nofdirs] = name
+ end
+ end
+ end
+ end
+ if nofdirs > 0 then
+ sort(dirs)
+ for i=1,nofdirs do
+ files = simplescan(files,spec,dirs[i])
+ end
+ end
return files
end
+local simplecache = { }
+local nofsharedscans = 0
+
+function resolvers.simplescanfiles(path,branch,usecache)
+ statistics.starttiming(timer)
+ local realpath = resolvers.resolve(path) -- no shortcut
+ if usecache then
+ local files = simplecache[realpath]
+ if not files then
+ files = scancache[realpath]
+ if files then
+ nofsharedscans = nofsharedscans + 1
+ end
+ end
+ if files then
+ if trace_locating then
+ report_expansions("using caches scan of path '%s', branch '%s'",path,branch or path)
+ end
+ return files
+ end
+ end
+ if trace_locating then
+ report_expansions("scanning path '%s', branch '%s'",path,branch or path)
+ end
+ local files = simplescan({ },realpath .. '/',"")
+ if trace_locating then
+ report_expansions("%s files found",table.count(files))
+ end
+ if usecache then
+ scanned[#scanned+1] = realpath
+ simplecache[realpath] = files
+ end
+ nofscans = nofscans + 1
+ statistics.stoptiming(timer)
+ return files
+end
+
+function resolvers.scandata()
+ table.sort(scanned)
+ return {
+ n = nofscans,
+ shared = nofsharedscans,
+ time = statistics.elapsedtime(timer),
+ paths = scanned,
+ }
+end
+
--~ print(table.serialize(resolvers.scanfiles("t:/sources")))
diff --git a/Master/texmf-dist/tex/context/base/data-fil.lua b/Master/texmf-dist/tex/context/base/data-fil.lua
index 0e82008f35e..6eb29ac3228 100644
--- a/Master/texmf-dist/tex/context/base/data-fil.lua
+++ b/Master/texmf-dist/tex/context/base/data-fil.lua
@@ -38,7 +38,8 @@ end
function generators.file(specification)
local path = specification.filename
- local content = resolvers.scanfiles(path)
+ local content = resolvers.scanfiles(path,false,true) -- scan once
+--~ inspect(content)
resolvers.registerfilehash(path,content,true)
end
diff --git a/Master/texmf-dist/tex/context/base/data-ini.lua b/Master/texmf-dist/tex/context/base/data-ini.lua
index 7b114e47b6b..16fbb8e25a4 100644
--- a/Master/texmf-dist/tex/context/base/data-ini.lua
+++ b/Master/texmf-dist/tex/context/base/data-ini.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['data-ini'] = {
license = "see context related readme files",
}
-local gsub, find, gmatch = string.gsub, string.find, string.gmatch
+local gsub, find, gmatch, char = string.gsub, string.find, string.gmatch, string.char
local concat = table.concat
local next, type = next, type
@@ -68,7 +68,7 @@ do
local homedir = osgetenv(ostype == "windows" and 'USERPROFILE' or 'HOME') or ''
if not homedir or homedir == "" then
- homedir = string.char(127) -- we need a value, later we wil trigger on it
+ homedir = char(127) -- we need a value, later we wil trigger on it
end
homedir = file.collapsepath(homedir)
diff --git a/Master/texmf-dist/tex/context/base/data-lst.lua b/Master/texmf-dist/tex/context/base/data-lst.lua
index 3f94253404f..048a26f0d1d 100644
--- a/Master/texmf-dist/tex/context/base/data-lst.lua
+++ b/Master/texmf-dist/tex/context/base/data-lst.lua
@@ -9,6 +9,7 @@ if not modules then modules = { } end modules ['data-lst'] = {
-- used in mtxrun, can be loaded later .. todo
local find, concat, upper, format = string.find, table.concat, string.upper, string.format
+local fastcopy, sortedpairs = table.fastcopy, table.sortedpairs
resolvers.listers = resolvers.listers or { }
@@ -39,10 +40,10 @@ function resolvers.listers.variables(pattern)
end
end
end
- local env = table.fastcopy(environment)
- local var = table.fastcopy(variables)
- local exp = table.fastcopy(expansions)
- for key, value in table.sortedpairs(configured) do
+ local env = fastcopy(environment)
+ local var = fastcopy(variables)
+ local exp = fastcopy(expansions)
+ for key, value in sortedpairs(configured) do
if key ~= "" and (pattern == "" or find(upper(key),pattern)) then
report_lists(key)
report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
@@ -51,9 +52,9 @@ function resolvers.listers.variables(pattern)
report_lists(" res: %s",resolvers.resolve(expansions[key]) or "unset")
end
end
- instance.environment = table.fastcopy(env)
- instance.variables = table.fastcopy(var)
- instance.expansions = table.fastcopy(exp)
+ instance.environment = fastcopy(env)
+ instance.variables = fastcopy(var)
+ instance.expansions = fastcopy(exp)
end
function resolvers.listers.configurations(report)
diff --git a/Master/texmf-dist/tex/context/base/data-lua.lua b/Master/texmf-dist/tex/context/base/data-lua.lua
index 06571440766..906a611ee16 100644
--- a/Master/texmf-dist/tex/context/base/data-lua.lua
+++ b/Master/texmf-dist/tex/context/base/data-lua.lua
@@ -78,8 +78,15 @@ local function loaded(libpaths,name,simple)
end
package.loaders[2] = function(name) -- was [#package.loaders+1]
- if trace_locating then -- mode detail
- report_libraries("! locating '%s'",name)
+ if file.suffix(name) == "" then
+ name = file.addsuffix(name,"lua") -- maybe a list
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s' with forced suffix",name)
+ end
+ else
+ if trace_locating then -- mode detail
+ report_libraries("! locating '%s'",name)
+ end
end
for i=1,#libformats do
local format = libformats[i]
diff --git a/Master/texmf-dist/tex/context/base/data-pre.lua b/Master/texmf-dist/tex/context/base/data-pre.lua
index 57905fa5e90..383ca291e97 100644
--- a/Master/texmf-dist/tex/context/base/data-pre.lua
+++ b/Master/texmf-dist/tex/context/base/data-pre.lua
@@ -24,6 +24,8 @@ local cleanpath, findgivenfile, expansion = resolvers.cleanpath, resolvers.findg
local getenv = resolvers.getenv -- we can probably also use resolvers.expansion
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
+-- getenv = function(...) return resolvers.getenv(...) end -- needs checking (definitions changes later on)
+
prefixes.environment = function(str)
return cleanpath(expansion(str))
end
@@ -62,7 +64,7 @@ end
prefixes.filename = function(str)
local fullname = findgivenfile(str) or ""
- return cleanpath(file.basename((fullname ~= "" and fullname) or str))
+ return cleanpath(file.basename((fullname ~= "" and fullname) or str)) -- no cleanpath needed here
end
prefixes.pathname = function(str)
@@ -105,8 +107,9 @@ function resolvers.allprefixes(separator)
end
local function _resolve_(method,target)
- if prefixes[method] then
- return prefixes[method](target)
+ local action = prefixes[method]
+ if action then
+ return action(target)
else
return method .. ":" .. target
end
@@ -121,7 +124,7 @@ end
local function resolve(str) -- use schemes, this one is then for the commandline only
local res = resolved[str]
if not res then
- res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_)
+ res = gsub(str,"([a-z][a-z]+):([^ \"\';]*)",_resolve_) -- home:xx;selfautoparent:xx; etc
resolved[str] = res
abstract[res] = str
end
diff --git a/Master/texmf-dist/tex/context/base/data-res.lua b/Master/texmf-dist/tex/context/base/data-res.lua
index d28a8a69767..73f3cc337e7 100644
--- a/Master/texmf-dist/tex/context/base/data-res.lua
+++ b/Master/texmf-dist/tex/context/base/data-res.lua
@@ -12,7 +12,7 @@ if not modules then modules = { } end modules ['data-res'] = {
-- instance but for practical purposes we now avoid this and use a
-- instance variable. We always have one instance active (sort of global).
--- todo: cache:/// home:///
+-- todo: cache:/// home:/// selfautoparent:/// (sometime end 2012)
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
@@ -55,22 +55,65 @@ resolvers.criticalvars = allocate { "SELFAUTOLOC", "SELFAUTODIR", "SELFAUTOPARE
resolvers.luacnfname = 'texmfcnf.lua'
resolvers.luacnfstate = "unknown"
--- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}' -- what a rubish path
-
--- changed by Taco Hoekwater to make <root>/texmfnf.lua take precedence,
--- while still allowing <root>/texmf/texmfnf.lua and
--- <root>/texmf/web2c/texmfnf.lua (in that order)
-resolvers.luacnfspec = '{selfautodir:,selfautoparent:};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,};{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
-
+-- The web2c tex binaries as well as kpse have built in paths for the configuration
+-- files and there can be a depressing truckload of them. This is actually the weak
+-- spot of a distribution. So we don't want:
+--
+-- resolvers.luacnfspec = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,}/web2c}'
+--
+-- but instead use:
+--
+-- resolvers.luacnfspec = 'selfautoparent:{/texmf{-local,}{,/web2c}}'
+--
+-- which does not make texlive happy as there is a texmf-local tree one level up
+-- (sigh), so we need this. (We can assume web2c as mkiv does not run on older
+-- texlives anyway.
+--
+-- texlive:
+--
+-- selfautodir:
+-- selfautoparent:
+-- selfautodir:share/texmf-local/web2c
+-- selfautodir:share/texmf/web2c
+-- selfautodir:texmf-local/web2c
+-- selfautodir:texmf/web2c
+-- selfautoparent:share/texmf-local/web2c
+-- selfautoparent:share/texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf/web2c
+--
+-- minimals:
+--
+-- home:texmf/web2c
+-- selfautoparent:texmf-local/web2c
+-- selfautoparent:texmf-context/web2c
+-- selfautoparent:texmf/web2c
+
+if this_is_texlive then
+ -- resolvers.luacnfspec = '{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = '{selfautodir:{/share,}/texmf-local/web2c,selfautoparent:{/share,}/texmf{-local,}/web2c}'
+ -- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c;selfautoparent:/texmf{-local,}/web2c'
+ resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+else
+ resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+end
+
+-- which (as we want users to use the web2c path) be can be simplified to this:
+--
+-- if environment and environment.ownpath and string.find(environment.ownpath,"[\\/]texlive[\\/]") then
+-- resolvers.luacnfspec = 'selfautodir:/texmf-local/web2c,selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- else
+-- resolvers.luacnfspec = 'selfautoparent:/texmf-local/web2c,selfautoparent:/texmf/web2c'
+-- end
--~ -- not yet, some reporters expect strings
--~ resolvers.luacnfspec = {
---~ "selfautoparent:/texmf-local",
+--~ "selfautoparent:/texmf-local", -- is actually a user mistake
--~ "selfautoparent:/texmf-local/web2c",
---~ "selfautoparent:/texmf",
+--~ "selfautoparent:/texmf", -- idem
--~ "selfautoparent:/texmf/web2c",
---~ "selfautoparent:",
+--~ "selfautoparent:", -- idem
--~ }
local unset_variable = "unset"
@@ -93,7 +136,7 @@ local instance = resolvers.instance or nil -- the current one (fast access)
function resolvers.setenv(key,value,raw)
if instance then
-- this one will be consulted first when we stay inside
- -- the current environment
+ -- the current environment (prefixes are not resolved here)
instance.environment[key] = value
-- we feed back into the environment, and as this is used
-- by other applications (via os.execute) we need to make
@@ -173,6 +216,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
remember = true,
diskcache = true,
renewcache = false,
+ renewtree = false,
loaderror = false,
savelists = true,
pattern = nil, -- lists
@@ -264,7 +308,7 @@ local function makepathexpression(str)
end
end
-local function reportcriticalvariables()
+local function reportcriticalvariables(cnfspec)
if trace_locating then
for i=1,#resolvers.criticalvars do
local k = resolvers.criticalvars[i]
@@ -272,6 +316,14 @@ local function reportcriticalvariables()
report_resolving("variable '%s' set to '%s'",k,v)
end
report_resolving()
+ if cnfspec then
+ if type(cnfspec) == "table" then
+ report_resolving("using configuration specification '%s'",concat(cnfspec,","))
+ else
+ report_resolving("using configuration specification '%s'",cnfspec)
+ end
+ end
+ report_resolving()
end
reportcriticalvariables = function() end
end
@@ -286,7 +338,7 @@ local function identify_configuration_files()
else
resolvers.luacnfstate = "environment"
end
- reportcriticalvariables()
+ reportcriticalvariables(cnfspec)
local cnfpaths = expandedpathfromlist(resolvers.splitpath(cnfspec))
local luacnfname = resolvers.luacnfname
for i=1,#cnfpaths do
@@ -322,6 +374,19 @@ local function load_configuration_files()
if blob then
local setups = instance.setups
local data = blob()
+ local parent = data and data.parent
+ if parent then
+ local filename = filejoin(pathname,parent)
+ local realname = resolvers.resolve(filename) -- no shortcut
+ local blob = loadfile(realname)
+ if blob then
+ local parentdata = blob()
+ if parentdata then
+ report_resolving("loading configuration file '%s'",filename)
+ data = table.merged(parentdata,data)
+ end
+ end
+ end
data = data and data.content
if data then
if trace_locating then
@@ -411,11 +476,6 @@ local function locate_file_databases()
local runtime = stripped == path
path = resolvers.cleanpath(path)
local spec = resolvers.splitmethod(stripped)
- -- TH Original did this the other way around (elseif and if tests
- -- reversed) but then the else branch was never reached, as 'runtime'
- -- would effectively be ignored. In turn, that meant that the wrong
- -- locator method was used, such that tree: and file: were treated
- -- identically (cached and no runtime search).
if runtime and (spec.noscheme or spec.scheme == "file") then
stripped = "tree:///" .. stripped
elseif spec.scheme == "cache" or spec.scheme == "file" then
@@ -423,7 +483,7 @@ local function locate_file_databases()
end
if trace_locating then
if runtime then
- report_resolving("locating list of '%s' (runtime)",path)
+ report_resolving("locating list of '%s' (runtime) (%s)",path,stripped)
else
report_resolving("locating list of '%s' (cached)",path)
end
@@ -467,6 +527,39 @@ local function save_file_databases() -- will become cachers
end
end
+function resolvers.renew(hashname)
+ if hashname and hashname ~= "" then
+ local expanded = resolvers.expansion(hashname) or ""
+ if expanded ~= "" then
+ if trace_locating then
+ report_resolving("identifying tree '%s' from '%s'",expanded,hashname)
+ end
+ hashname = expanded
+ else
+ if trace_locating then
+ report_resolving("identifying tree '%s'",hashname)
+ end
+ end
+ local realpath = resolvers.resolve(hashname)
+ if lfs.isdir(realpath) then
+ if trace_locating then
+ report_resolving("using path '%s'",realpath)
+ end
+ methodhandler('generators',hashname)
+ -- could be shared
+ local content = instance.files[hashname]
+ caches.collapsecontent(content)
+ if trace_locating then
+ report_resolving("saving tree '%s'",hashname)
+ end
+ caches.savecontent(hashname,"files",content)
+ -- till here
+ else
+ report_resolving("invalid path '%s'",realpath)
+ end
+ end
+end
+
local function load_databases()
locate_file_databases()
if instance.diskcache and not instance.renewcache then
@@ -754,6 +847,7 @@ local function collect_files(names)
if dname == "" or find(dname,"^%.") then
dname = false
else
+dname = gsub(dname,"*","%.*")
dname = "/" .. dname .. "$"
end
local hashes = instance.hashes
@@ -813,9 +907,22 @@ local function collect_files(names)
return noffiles > 0 and filelist or nil
end
-function resolvers.registerintrees(name)
- if not find(name,"^%.") then
- instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
+local fit = { }
+
+function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname)
+ local foundintrees = instance.foundintrees
+ if usedmethod == "direct" and filename == foundname and fit[foundname] then
+ -- just an extra lookup after a test on presence
+ else
+ local t = {
+ filename = filename,
+ format = format ~= "" and format or nil,
+ filetype = filetype ~= "" and filetype or nil,
+ usedmethod = usedmethod,
+ foundname = foundname,
+ }
+ fit[foundname] = t
+ foundintrees[#foundintrees+1] = t
end
end
@@ -835,588 +942,423 @@ end
local preparetreepattern = Cs((P(".")/"%%." + P("-")/"%%-" + P(1))^0 * Cc("$"))
--- this one is split in smaller functions but it needs testing
-
-local function collect_instance_files(filename,askedformat,allresults) -- todo : plugin (scanners, checkers etc)
- local result = { }
- local stamp = nil
- askedformat = askedformat or ""
- filename = collapsepath(filename)
- -- speed up / beware: format problem
- if instance.remember and not allresults then
- stamp = filename .. "--" .. askedformat
- if instance.found[stamp] then
+-- -- -- begin of main file search routing -- -- -- needs checking as previous has been patched
+
+local collect_instance_files
+
+local function find_analyze(filename,askedformat,allresults)
+ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
+ -- too tricky as filename can be bla.1.2.3:
+ --
+ -- if not suffixmap[ext] then
+ -- wantedfiles[#wantedfiles+1] = filename
+ -- end
+ wantedfiles[#wantedfiles+1] = filename
+ if askedformat == "" then
+ if ext == "" or not suffixmap[ext] then
+ local defaultsuffixes = resolvers.defaultsuffixes
+ for i=1,#defaultsuffixes do
+ local forcedname = filename .. '.' .. defaultsuffixes[i]
+ wantedfiles[#wantedfiles+1] = forcedname
+ filetype = resolvers.formatofsuffix(forcedname)
+ if trace_locating then
+ report_resolving("forcing filetype '%s'",filetype)
+ end
+ end
+ else
+ filetype = resolvers.formatofsuffix(filename)
if trace_locating then
- report_resolving("remembered file '%s'",filename)
+ report_resolving("using suffix based filetype '%s'",filetype)
end
- resolvers.registerintrees(filename) -- for tracing used files
- return instance.found[stamp]
end
- end
- if not dangerous[askedformat] then
- if isreadable(filename) then
- if trace_detail then
- report_resolving("file '%s' found directly",filename)
- end
- if stamp then
- instance.found[stamp] = { filename }
+ else
+ if ext == "" or not suffixmap[ext] then
+ local format_suffixes = suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ end
end
- return { filename }
+ end
+ filetype = askedformat
+ if trace_locating then
+ report_resolving("using given filetype '%s'",filetype)
end
end
+ return filetype, wantedfiles
+end
+
+local function find_direct(filename,allresults)
+ if not dangerous[askedformat] and isreadable(filename) then
+ if trace_detail then
+ report_resolving("file '%s' found directly",filename)
+ end
+ return "direct", { filename }
+ end
+end
+
+local function find_wildcard(filename,allresults)
if find(filename,'%*') then
if trace_locating then
report_resolving("checking wildcard '%s'", filename)
end
- result = resolvers.findwildcardfiles(filename) -- we can use th elocal
- elseif file.is_qualified_path(filename) then
- if isreadable(filename) then
- if trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
- result = { filename }
- else
- local forcedname, ok, suffix = "", false, fileextname(filename)
- if suffix == "" then -- why
- local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- local s = format_suffixes[i]
- forcedname = filename .. "." .. s
- if isreadable(forcedname) then
- if trace_locating then
- report_resolving("no suffix, forcing format filetype '%s'", s)
- end
- result, ok = { forcedname }, true
- break
- end
- end
- end
- end
- if not ok and suffix ~= "" then
- -- try to find in tree (no suffix manipulation), here we search for the
- -- matching last part of the name
- local basename = filebasename(filename)
- local pattern = lpegmatch(preparetreepattern,filename)
- -- messy .. to be sorted out
- local savedformat = askedformat
- local format = savedformat or ""
- if format == "" then
- askedformat = resolvers.formatofsuffix(suffix)
- end
- if not format then
- askedformat = "othertextfiles" -- kind of everything, maybe texinput is better
- end
- --
- if basename ~= filename then
- local resolved = collect_instance_files(basename,askedformat,allresults)
- if #result == 0 then -- shouldn't this be resolved ?
- local lowered = lower(basename)
- if filename ~= lowered then
- resolved = collect_instance_files(lowered,askedformat,allresults)
- end
- end
- resolvers.format = savedformat
- --
- for r=1,#resolved do
- local rr = resolved[r]
- if find(rr,pattern) then
- result[#result+1], ok = rr, true
- end
- end
- end
- -- a real wildcard:
- --
- -- if not ok then
- -- local filelist = collect_files({basename})
- -- for f=1,#filelist do
- -- local ff = filelist[f][3] or ""
- -- if find(ff,pattern) then
- -- result[#result+1], ok = ff, true
- -- end
- -- end
- -- end
- end
- if not ok and trace_locating then
- report_resolving("qualified name '%s'", filename)
- end
+ local method, result = resolvers.findwildcardfiles(filename)
+ if result then
+ return "wildcard", result
end
- else
- -- search spec
- local filetype, done, wantedfiles, ext = '', false, { }, fileextname(filename)
- -- -- tricky as filename can be bla.1.2.3
- -- if not suffixmap[ext] then --- probably needs to be done elsewhere too
- -- wantedfiles[#wantedfiles+1] = filename
- -- end
- wantedfiles[#wantedfiles+1] = filename
- if askedformat == "" then
- if ext == "" or not suffixmap[ext] then
- local defaultsuffixes = resolvers.defaultsuffixes
- for i=1,#defaultsuffixes do
- local forcedname = filename .. '.' .. defaultsuffixes[i]
- wantedfiles[#wantedfiles+1] = forcedname
- filetype = resolvers.formatofsuffix(forcedname)
+ end
+end
+
+local function find_qualified(filename,allresults) -- this one will be split too
+ if not file.is_qualified_path(filename) then
+ return
+ end
+ if trace_locating then
+ report_resolving("checking qualified name '%s'", filename)
+ end
+ if isreadable(filename) then
+ if trace_detail then
+ report_resolving("qualified file '%s' found", filename)
+ end
+ return "qualified", { filename }
+ end
+ if trace_detail then
+ report_resolving("locating qualified file '%s'", filename)
+ end
+ local forcedname, suffix = "", fileextname(filename)
+ if suffix == "" then -- why
+ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
+ if format_suffixes then
+ for i=1,#format_suffixes do
+ local s = format_suffixes[i]
+ forcedname = filename .. "." .. s
+ if isreadable(forcedname) then
if trace_locating then
- report_resolving("forcing filetype '%s'",filetype)
+ report_resolving("no suffix, forcing format filetype '%s'", s)
end
+ return "qualified", { forcedname }
end
- else
- filetype = resolvers.formatofsuffix(filename)
- if trace_locating then
- report_resolving("using suffix based filetype '%s'",filetype)
+ end
+ end
+ end
+ if suffix and suffix ~= "" then
+ -- try to find in tree (no suffix manipulation), here we search for the
+ -- matching last part of the name
+ local basename = filebasename(filename)
+ local pattern = lpegmatch(preparetreepattern,filename)
+ -- messy .. to be sorted out
+ local savedformat = askedformat
+ local format = savedformat or ""
+ if format == "" then
+ askedformat = resolvers.formatofsuffix(suffix)
+ end
+ if not format then
+ askedformat = "othertextfiles" -- kind of everything, maybe all
+ end
+ --
+ if basename ~= filename then
+ local resolved = collect_instance_files(basename,askedformat,allresults)
+ if #resolved == 0 then
+ local lowered = lower(basename)
+ if filename ~= lowered then
+ resolved = collect_instance_files(lowered,askedformat,allresults)
end
end
- else
- if ext == "" or not suffixmap[ext] then
- local format_suffixes = suffixes[askedformat]
- if format_suffixes then
- for i=1,#format_suffixes do
- wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
+ resolvers.format = savedformat
+ --
+ if #resolved > 0 then
+ local result = { }
+ for r=1,#resolved do
+ local rr = resolved[r]
+ if find(rr,pattern) then
+ result[#result+1] = rr
end
end
- end
- filetype = askedformat
- if trace_locating then
- report_resolving("using given filetype '%s'",filetype)
+ if #result > 0 then
+ return "qualified", result
+ end
end
end
- local typespec = resolvers.variableofformat(filetype)
- local pathlist = resolvers.expandedpathlist(typespec)
- if not pathlist or #pathlist == 0 then
- -- no pathlist, access check only / todo == wildcard
- if trace_detail then
- report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
- end
- for k=1,#wantedfiles do
- local fname = wantedfiles[k]
- if fname and isreadable(fname) then
- filename, done = fname, true
- result[#result+1] = filejoin('.',fname)
- break
- end
+ -- a real wildcard:
+ --
+ -- local filelist = collect_files({basename})
+ -- result = { }
+ -- for f=1,#filelist do
+ -- local ff = filelist[f][3] or ""
+ -- if find(ff,pattern) then
+ -- result[#result+1], ok = ff, true
+ -- end
+ -- end
+ -- if #result > 0 then
+ -- return "qualified", result
+ -- end
+ end
+end
+
+local function check_subpath(fname)
+ if isreadable(fname) then
+ if trace_detail then
+ report_resolving("found '%s' by deep scanning",fname)
+ end
+ return fname
+ end
+end
+
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local typespec = resolvers.variableofformat(filetype)
+ local pathlist = resolvers.expandedpathlist(typespec)
+ local method = "intree"
+ if pathlist and #pathlist > 0 then
+ -- list search
+ local filelist = collect_files(wantedfiles)
+ local dirlist = { }
+ if filelist then
+ for i=1,#filelist do
+ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
end
- -- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = collect_files(wantedfiles)
- local fl = filelist and filelist[1]
- if fl then
- filename = fl[3] -- not local?
- result[#result+1] = resolvers.resolve(filename)
- done = true
+ end
+ if trace_detail then
+ report_resolving("checking filename '%s'",filename)
+ end
+ local result = { }
+ for k=1,#pathlist do
+ local path = pathlist[k]
+ local pathname = lpegmatch(inhibitstripper,path)
+ local doscan = path == pathname -- no ^!!
+ if not find (pathname,'//$') then
+ doscan = false -- we check directly on the path
end
- else
- -- list search
- local filelist = collect_files(wantedfiles)
- local dirlist = { }
- if filelist then
- for i=1,#filelist do
- dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
+ local done = false
+ -- using file list
+ if filelist then -- database
+ -- compare list entries with permitted pattern -- /xx /xx//
+ local expression = makepathexpression(pathname)
+ if trace_detail then
+ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
end
- end
- if trace_detail then
- report_resolving("checking filename '%s'",filename)
- end
- for k=1,#pathlist do
- local path = pathlist[k]
- local pathname = lpegmatch(inhibitstripper,path)
- local doscan = path == pathname -- no ^!!
- if not find (pathname, '//$') then doscan = false end
- done = false
- -- using file list
- if filelist then
- -- compare list entries with permitted pattern -- /xx /xx//
- local expression = makepathexpression(pathname)
- if trace_detail then
- report_resolving("using pattern '%s' for path '%s'",expression,pathname)
- end
- for k=1,#filelist do
- local fl = filelist[k]
- local f = fl[2]
- local d = dirlist[k]
- if find(d,expression) then
- -- todo, test for readable
- result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
- done = true
- if allresults then
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
- end
- else
- if trace_detail then
- report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
- end
- break
+ for k=1,#filelist do
+ local fl = filelist[k]
+ local f = fl[2]
+ local d = dirlist[k]
+ if find(d,expression) then
+ -- todo, test for readable
+ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
+ done = true
+ if allresults then
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
end
- elseif trace_detail then
- report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
+ else
+ if trace_detail then
+ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
+ end
+ break
end
+ elseif trace_detail then
+ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
end
end
- if not done then
- -- check if on disk / unchecked / does not work at all / also zips
- -- TH perhaps it did not work because of missing resolvers.resolve()
- -- and resolvers.scanfiles() calls ...
- pathname = resolvers.resolve(pathname)
- local scheme = url.hasscheme(pathname)
- if not scheme or scheme == "file" then
- local pname = gsub(pathname,"%.%*$",'')
- if not find(pname,"%*") then
- local ppname = gsub(pname,"/+$","")
- if can_be_dir(ppname) then
- local files = {}
- if doscan then files = resolvers.scanfiles(ppname) end
+ end
+ if done then
+ method = "database"
+ else
+ method = "filesystem" -- bonus, even when !! is specified
+ pathname = gsub(pathname,"/+$","")
+ pathname = resolvers.resolve(pathname)
+ local scheme = url.hasscheme(pathname)
+ if not scheme or scheme == "file" then
+ local pname = gsub(pathname,"%.%*$",'')
+ if not find(pname,"%*") then
+ if can_be_dir(pname) then
+ -- quick root scan first
+ for k=1,#wantedfiles do
+ local w = wantedfiles[k]
+ local fname = check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ if not done and doscan then
+ -- collect files in path (and cache the result)
+ local files = resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w = wantedfiles[k]
- local subpath = ''
- if files[w] then
- subpath = type(files[w]) == "table" and files[w][1] or files[w]
- end
- local fname = filejoin(ppname,subpath,w)
- if isreadable(fname) then
- if trace_detail then
- report_resolving("found '%s' by scanning",fname)
+ local subpath = files[w]
+ if not subpath or subpath == "" then
+ -- rootscan already done
+ elseif type(subpath) == "string" then
+ local fname = check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp = subpath[i]
+ if sp == "" then
+ -- roottest already done
+ else
+ local fname = check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1] = fname
+ done = true
+ if not allresults then
+ break
+ end
+ end
+ end
+ end
+ if done and not allresults then
+ break
end
- result[#result+1] = fname
- done = true
- if not allresults then break end
end
end
- else
- -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
+ else
+ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
end
end
- if not done and doscan then
- -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
- end
- if done and not allresults then break end
+ end
+ -- todo recursive scanning
+ if done and not allresults then
+ break
end
end
+ if #result > 0 then
+ return method, result
+ end
end
- for k=1,#result do
- local rk = collapsepath(result[k])
- result[k] = rk
- resolvers.registerintrees(rk) -- for tracing used files
+end
+
+local function find_onpath(filename,filetype,wantedfiles,allresults)
+ if trace_detail then
+ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
end
- if stamp then
- instance.found[stamp] = result
+ local result = { }
+ for k=1,#wantedfiles do
+ local fname = wantedfiles[k]
+ if fname and isreadable(fname) then
+ filename = fname
+ result[#result+1] = filejoin('.',fname)
+ if not allresults then
+ break
+ end
+ end
+ end
+ if #result > 0 then
+ return "onpath", result
+ end
+end
+
+local function find_otherwise(filename,filetype,wantedfiles,allresults) -- other text files | any | whatever
+ local filelist = collect_files(wantedfiles)
+ local fl = filelist and filelist[1]
+ if fl then
+ return "otherwise", { resolvers.resolve(fl[3]) } -- filename
end
- return result
end
--- -- -- begin of main file search routing -- -- --
-
---~ local collect_instance_files
-
---~ local function find_direct(filename)
---~ if not dangerous[askedformat] and isreadable(filename) then
---~ if trace_detail then
---~ report_resolving("file '%s' found directly",filename)
---~ end
---~ return { filename }
---~ end
---~ end
-
---~ local function find_wildcard(filename)
---~ if find(filename,'%*') then
---~ if trace_locating then
---~ report_resolving("checking wildcard '%s'", filename)
---~ end
---~ return resolvers.findwildcardfiles(filename) -- we can use the local
---~ end
---~ end
-
---~ local function find_qualified(filename) -- this one will be split too
---~ if not file.is_qualified_path(filename) then
---~ return
---~ end
---~ if trace_locating then
---~ report_resolving("checking qualified name '%s'", filename)
---~ end
---~ if isreadable(filename) then
---~ if trace_detail then
---~ report_resolving("qualified file '%s' found", filename)
---~ end
---~ return { filename }
---~ else
---~ if trace_detail then
---~ report_resolving("locating qualified file '%s'", filename)
---~ end
---~ local forcedname, suffix = "", fileextname(filename)
---~ if suffix == "" then -- why
---~ local format_suffixes = askedformat == "" and resolvers.defaultsuffixes or suffixes[askedformat]
---~ if format_suffixes then
---~ for i=1,#format_suffixes do
---~ local s = format_suffixes[i]
---~ forcedname = filename .. "." .. s
---~ if isreadable(forcedname) then
---~ if trace_locating then
---~ report_resolving("no suffix, forcing format filetype '%s'", s)
---~ end
---~ return { forcedname }
---~ end
---~ end
---~ end
---~ end
---~ if suffix ~= "" then
---~ -- try to find in tree (no suffix manipulation), here we search for the
---~ -- matching last part of the name
---~ local basename = filebasename(filename)
---~ local pattern = lpegmatch(preparetreepattern,filename)
---~ -- messy .. to be sorted out
---~ local savedformat = askedformat
---~ local format = savedformat or ""
---~ if format == "" then
---~ askedformat = resolvers.formatofsuffix(suffix)
---~ end
---~ if not format then
---~ askedformat = "othertextfiles" -- kind of everything, maybe all
---~ end
---~ --
---~ if basename ~= filename then
---~ local resolved = collect_instance_files(basename,askedformat,allresults)
---~ if #resolved == 0 then
---~ local lowered = lower(basename)
---~ if filename ~= lowered then
---~ resolved = collect_instance_files(lowered,askedformat,allresults)
---~ end
---~ end
---~ resolvers.format = savedformat
---~ --
---~ if #resolved > 0 then
---~ local result = { }
---~ for r=1,#resolved do
---~ local rr = resolved[r]
---~ if find(rr,pattern) then
---~ result[#result+1] = rr
---~ end
---~ end
---~ if #result > 0 then
---~ return result
---~ end
---~ end
---~ end
---~ -- a real wildcard:
---~ --
---~ -- local filelist = collect_files({basename})
---~ -- result = { }
---~ -- for f=1,#filelist do
---~ -- local ff = filelist[f][3] or ""
---~ -- if find(ff,pattern) then
---~ -- result[#result+1], ok = ff, true
---~ -- end
---~ -- end
---~ -- if #result > 0 then
---~ -- return result
---~ -- end
---~ end
---~ end
---~ end
-
---~ local function find_analyze(filename,askedformat)
---~ local filetype, wantedfiles, ext = '', { }, fileextname(filename)
---~ -- too tricky as filename can be bla.1.2.3:
---~ --
---~ -- if not suffixmap[ext] then
---~ -- wantedfiles[#wantedfiles+1] = filename
---~ -- end
---~ wantedfiles[#wantedfiles+1] = filename
---~ if askedformat == "" then
---~ if ext == "" or not suffixmap[ext] then
---~ local defaultsuffixes = resolvers.defaultsuffixes
---~ for i=1,#defaultsuffixes do
---~ local forcedname = filename .. '.' .. defaultsuffixes[i]
---~ wantedfiles[#wantedfiles+1] = forcedname
---~ filetype = resolvers.formatofsuffix(forcedname)
---~ if trace_locating then
---~ report_resolving("forcing filetype '%s'",filetype)
---~ end
---~ end
---~ else
---~ filetype = resolvers.formatofsuffix(filename)
---~ if trace_locating then
---~ report_resolving("using suffix based filetype '%s'",filetype)
---~ end
---~ end
---~ else
---~ if ext == "" or not suffixmap[ext] then
---~ local format_suffixes = suffixes[askedformat]
---~ if format_suffixes then
---~ for i=1,#format_suffixes do
---~ wantedfiles[#wantedfiles+1] = filename .. "." .. format_suffixes[i]
---~ end
---~ end
---~ end
---~ filetype = askedformat
---~ if trace_locating then
---~ report_resolving("using given filetype '%s'",filetype)
---~ end
---~ end
---~ return filetype, wantedfiles
---~ end
-
---~ local function find_intree(filename,filetype,wantedfiles)
---~ local typespec = resolvers.variableofformat(filetype)
---~ local pathlist = resolvers.expandedpathlist(typespec)
---~ if pathlist and #pathlist > 0 then
---~ -- list search
---~ local filelist = collect_files(wantedfiles)
---~ local dirlist = { }
---~ if filelist then
---~ for i=1,#filelist do
---~ dirlist[i] = filedirname(filelist[i][3]) .. "/" -- was [2] .. gamble
---~ end
---~ end
---~ if trace_detail then
---~ report_resolving("checking filename '%s'",filename)
---~ end
---~ local result = { }
---~ for k=1,#pathlist do
---~ local path = pathlist[k]
---~ local pathname = lpegmatch(inhibitstripper,path)
---~ local doscan = path == pathname -- no ^!!
---~ local done = false
---~ -- using file list
---~ if filelist then
---~ -- compare list entries with permitted pattern -- /xx /xx//
---~ local expression = makepathexpression(pathname)
---~ if trace_detail then
---~ report_resolving("using pattern '%s' for path '%s'",expression,pathname)
---~ end
---~ for k=1,#filelist do
---~ local fl = filelist[k]
---~ local f = fl[2]
---~ local d = dirlist[k]
---~ if find(d,expression) then
---~ -- todo, test for readable
---~ result[#result+1] = resolvers.resolve(fl[3]) -- no shortcut
---~ done = true
---~ if allresults then
---~ if trace_detail then
---~ report_resolving("match to '%s' in hash for file '%s' and path '%s', continue scanning",expression,f,d)
---~ end
---~ else
---~ if trace_detail then
---~ report_resolving("match to '%s' in hash for file '%s' and path '%s', quit scanning",expression,f,d)
---~ end
---~ break
---~ end
---~ elseif trace_detail then
---~ report_resolving("no match to '%s' in hash for file '%s' and path '%s'",expression,f,d)
---~ end
---~ end
---~ end
---~ if not done and doscan then
---~ -- check if on disk / unchecked / does not work at all / also zips
---~ local scheme = url.hasscheme(pathname)
---~ if not scheme or scheme == "file" then
---~ local pname = gsub(pathname,"%.%*$",'')
---~ if not find(pname,"%*") then
---~ local ppname = gsub(pname,"/+$","")
---~ if can_be_dir(ppname) then
---~ for k=1,#wantedfiles do
---~ local w = wantedfiles[k]
---~ local fname = filejoin(ppname,w)
---~ if isreadable(fname) then
---~ if trace_detail then
---~ report_resolving("found '%s' by scanning",fname)
---~ end
---~ result[#result+1] = fname
---~ done = true
---~ if not allresults then break end
---~ end
---~ end
---~ else
---~ -- no access needed for non existing path, speedup (esp in large tree with lots of fake)
---~ end
---~ end
---~ end
---~ end
---~ if not done and doscan then
---~ -- todo: slow path scanning ... although we now have tree:// supported in $TEXMF
---~ end
---~ if done and not allresults then
---~ return #result > 0 and result
---~ end
---~ end
---~ end
---~ end
-
---~ local function find_onpath(filename,filetype,wantedfiles)
---~ local done = nil
---~ if trace_detail then
---~ report_resolving("checking filename '%s', filetype '%s', wanted files '%s'",filename, filetype or '?',concat(wantedfiles," | "))
---~ end
---~ for k=1,#wantedfiles do
---~ local fname = wantedfiles[k]
---~ if fname and isreadable(fname) then
---~ filename, done = fname, true
---~ result[#result+1] = filejoin('.',fname)
---~ break
---~ end
---~ end
---~ end
-
---~ local function find_otherwise(filename,filetype,wantedfiles) -- other text files | any | whatever
---~ local filelist = collect_files(wantedfiles)
---~ local fl = filelist and filelist[1]
---~ if fl then
---~ return { resolvers.resolve(fl[3]) } -- filename
---~ end
---~ end
-
---~ collect_instance_files = function(filename,askedformat,allresults) -- uses nested
---~ local result, stamp, filetype, wantedfiles
---~ askedformat = askedformat or ""
---~ filename = collapsepath(filename)
---~ if instance.remember and not allresults then
---~ stamp = format("%s--%s", filename, askedformat)
---~ result = stamp and instance.found[stamp]
---~ if result then
---~ if trace_locating then
---~ report_resolving("remembered file '%s'",filename)
---~ end
---~ return result
---~ end
---~ end
---~ result = find_direct (filename,stamp) or
---~ find_wildcard (filename) or
---~ find_qualified(filename)
---~ if not result then
---~ filetype, wantedfiles = find_analyze(filename,askedformat)
---~ result = find_intree (filename,filetype,wantedfiles) or
---~ find_onpath (filename,filetype,wantedfiles) or
---~ find_otherwise(filename,filetype,wantedfiles)
---~ end
---~ if result then
---~ for k=1,#result do
---~ local rk = collapsepath(result[k])
---~ result[k] = rk
---~ resolvers.registerintrees(rk) -- for tracing used files
---~ end
---~ else
---~ result = { } -- maybe false
---~ end
---~ if stamp then
---~ if trace_locating then
---~ report_resolving("remembering file '%s'",filename)
---~ end
---~ instance.found[stamp] = result
---~ end
---~ return result
---~ end
+-- we could have a loop over the 6 functions but then we'd have to
+-- always analyze
+
+collect_instance_files = function(filename,askedformat,allresults) -- uses nested
+ askedformat = askedformat or ""
+ filename = collapsepath(filename)
+ if allresults then
+ -- no need for caching, only used for tracing
+ local filetype, wantedfiles = find_analyze(filename,askedformat)
+ local results = {
+ { find_direct (filename,true) },
+ { find_wildcard (filename,true) },
+ { find_qualified(filename,true) },
+ { find_intree (filename,filetype,wantedfiles,true) },
+ { find_onpath (filename,filetype,wantedfiles,true) },
+ { find_otherwise(filename,filetype,wantedfiles,true) },
+ }
+ local result, status, done = { }, { }, { }
+ for k, r in next, results do
+ local method, list = r[1], r[2]
+ if method and list then
+ for i=1,#list do
+ local c = collapsepath(list[i])
+ if not done[c] then
+ result[#result+1] = c
+ done[c] = true
+ end
+ status[#status+1] = format("%-10s: %s",method,c)
+ end
+ end
+ end
+ if trace_detail then
+ report_resolving("lookup status: %s",table.serialize(status,filename))
+ end
+ return result, status
+ else
+ local method, result, stamp, filetype, wantedfiles
+ if instance.remember then
+ stamp = format("%s--%s", filename, askedformat)
+ result = stamp and instance.found[stamp]
+ if result then
+ if trace_locating then
+ report_resolving("remembered file '%s'",filename)
+ end
+ return result
+ end
+ end
+ method, result = find_direct(filename)
+ if not result then
+ method, result = find_wildcard(filename)
+ if not result then
+ method, result = find_qualified(filename)
+ if not result then
+ filetype, wantedfiles = find_analyze(filename,askedformat)
+ method, result = find_intree(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_onpath(filename,filetype,wantedfiles)
+ if not result then
+ method, result = find_otherwise(filename,filetype,wantedfiles)
+ end
+ end
+ end
+ end
+ end
+ if result and #result > 0 then
+ local foundname = collapsepath(result[1])
+ resolvers.registerintrees(filename,askedformat,filetype,method,foundname)
+ result = { foundname }
+ else
+ result = { } -- maybe false
+ end
+ if stamp then
+ if trace_locating then
+ report_resolving("remembering file '%s'",filename)
+ end
+ instance.found[stamp] = result
+ end
+ return result
+ end
+end
-- -- -- end of main file search routing -- -- --
+
local function findfiles(filename,filetype,allresults)
- local result = collect_instance_files(filename,filetype or "",allresults)
- if #result == 0 then
+ local result, status = collect_instance_files(filename,filetype or "",allresults)
+ if not result or #result == 0 then
local lowered = lower(filename)
if filename ~= lowered then
- return collect_instance_files(lowered,filetype or "",allresults)
+ result, status = collect_instance_files(lowered,filetype or "",allresults)
end
end
- return result
+ return result or { }, status
end
function resolvers.findfiles(filename,filetype)
@@ -1583,6 +1525,10 @@ function resolvers.load(option)
return files and next(files) and true
end
+function resolvers.loadtime()
+ return statistics.elapsedtime(instance)
+end
+
local function report(str)
if trace_locating then
report_resolving(str) -- has already verbose
@@ -1596,6 +1542,9 @@ function resolvers.dowithfilesandreport(command, files, ...) -- will move
if trace_locating then
report('') -- ?
end
+ if type(files) == "string" then
+ files = { files }
+ end
for f=1,#files do
local file = files[f]
local result = command(file,...)
diff --git a/Master/texmf-dist/tex/context/base/data-tex.lua b/Master/texmf-dist/tex/context/base/data-tex.lua
index 14148b20ea8..6cb361699fa 100644
--- a/Master/texmf-dist/tex/context/base/data-tex.lua
+++ b/Master/texmf-dist/tex/context/base/data-tex.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['data-tex'] = {
license = "see context related readme files"
}
+local char = string.char
+
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local report_tex = logs.reporter("resolvers","tex")
@@ -17,17 +19,17 @@ local methodhandler = resolvers.methodhandler
local splitlines = string.splitlines
local utffiletype = unicode.filetype
-local fileprocessor = nil
-local lineprocessor = nil
+-- local fileprocessor = nil
+-- local lineprocessor = nil
-local textfileactions = sequencers.reset {
- arguments = "str,filename",
+local textfileactions = sequencers.new {
+ arguments = "str,filename,coding",
returnvalues = "str",
results = "str",
}
-local textlineactions = sequencers.reset {
- arguments = "str,filename,linenumber,noflines",
+local textlineactions = sequencers.new {
+ arguments = "str,filename,linenumber,noflines,coding",
returnvalues = "str",
results = "str",
}
@@ -46,7 +48,10 @@ appendgroup(textlineactions,"before") -- user
appendgroup(textlineactions,"system") -- private
appendgroup(textlineactions,"after" ) -- user
-function helpers.textopener(tag,filename,filehandle)
+local ctrl_d = char( 4) -- unix
+local ctrl_z = char(26) -- windows
+
+function helpers.textopener(tag,filename,filehandle,coding)
local lines
local t_filehandle = type(filehandle)
if not filehandle then
@@ -60,7 +65,7 @@ function helpers.textopener(tag,filename,filehandle)
filehandle:close()
end
if type(lines) == "string" then
- local coding = utffiletype(lines)
+ local coding = coding or utffiletype(lines) -- so we can signal no regime
if trace_locating then
report_tex("%s opener, '%s' opened using method '%s'",tag,filename,coding)
end
@@ -72,11 +77,11 @@ function helpers.textopener(tag,filename,filehandle)
lines = unicode.utf32_to_utf8_be(lines)
elseif coding == "utf-32-le" then
lines = unicode.utf32_to_utf8_le(lines)
- else -- utf8 or unknown
- if textfileactions.dirty then -- maybe use autocompile
- fileprocessor = sequencers.compile(textfileactions)
+ else -- utf8 or unknown (could be a mkvi file)
+ local runner = textfileactions.runner
+ if runner then
+ lines = runner(lines,filename,coding) or lines
end
- lines = fileprocessor(lines,filename) or lines
lines = splitlines(lines)
end
elseif trace_locating then
@@ -111,11 +116,15 @@ function helpers.textopener(tag,filename,filehandle)
return nil
elseif content == "" then
return ""
+ -- elseif content == ctrl_d or ctrl_z then
+ -- return nil -- we need this as \endinput does not work in prints
else
- if textlineactions.dirty then
- lineprocessor = sequencers.compile(textlineactions) -- maybe use autocompile
+ local runner = textlineactions.runner
+ if runner then
+ return runner(content,filename,currentline,noflines,coding) or content
+ else
+ return content
end
- return lineprocessor(content,filename,currentline,noflines) or content
end
end
end
diff --git a/Master/texmf-dist/tex/context/base/data-tmf.lua b/Master/texmf-dist/tex/context/base/data-tmf.lua
index 9391e881ea7..260beb9f431 100644
--- a/Master/texmf-dist/tex/context/base/data-tmf.lua
+++ b/Master/texmf-dist/tex/context/base/data-tmf.lua
@@ -47,7 +47,13 @@ function resolvers.load_tree(tree,resolve)
-- Beware, we need to obey the relocatable autoparent so we
-- set TEXMFCNF to its raw value. This is somewhat tricky when
-- we run a mkii job from within. Therefore, in mtxrun, there
- -- is a resolve applied when we're in mkii/kpse mode.
+ -- is a resolve applied when we're in mkii/kpse mode or when
+ -- --resolve is passed to mtxrun. Maybe we should also set the
+ -- local AUTOPARENT etc. although these are alwasy set new.
+
+ if resolve then
+ resolvers.luacnfspec = resolvers.resolve(resolvers.luacnfspec)
+ end
setenv('SELFAUTOPARENT', newroot)
setenv('SELFAUTODIR', newtree)
@@ -55,11 +61,12 @@ function resolvers.load_tree(tree,resolve)
setenv('TEXROOT', newroot)
setenv('TEXOS', texos)
setenv('TEXMFOS', texmfos)
- setenv('TEXMFCNF', resolvers.luacnfspec, not resolve)
- setenv("PATH", newpath .. io.pathseparator .. getenv("PATH"))
+ setenv('TEXMFCNF', resolvers.luacnfspec,true) -- already resolved
+ setenv('PATH', newpath .. io.pathseparator .. getenv('PATH'))
report_tds("changing from root '%s' to '%s'",oldroot,newroot)
- report_tds("prepending '%s' to binary path",newpath)
+ report_tds("prepending '%s' to PATH",newpath)
+ report_tds("setting TEXMFCNF to '%s'",resolvers.luacnfspec)
report_tds()
end
end
diff --git a/Master/texmf-dist/tex/context/base/data-tmp.lua b/Master/texmf-dist/tex/context/base/data-tmp.lua
index 46c9b306283..6e235dd3466 100644
--- a/Master/texmf-dist/tex/context/base/data-tmp.lua
+++ b/Master/texmf-dist/tex/context/base/data-tmp.lua
@@ -23,6 +23,7 @@ luatools with a recache feature.</p>
--ldx]]--
local format, lower, gsub, concat = string.format, string.lower, string.gsub, table.concat
+local serialize, serializetofile = table.serialize, table.tofile
local mkdirs, isdir = dir.mkdirs, lfs.isdir
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
@@ -85,11 +86,7 @@ local function identify()
end
elseif not writable and caches.force then
local cacheparent = file.dirname(cachepath)
- -- TH: added 'or true' for deeply buried non-existent caches.
- -- file.is_writable() is not really important here, since this
- -- branch is only checked for as-yet non-existent paths, and
- -- it guards against mkdirs() failing, anyway.
- if file.is_writable(cacheparent) or true then
+ if file.is_writable(cacheparent) and true then -- we go on anyway (needed for mojca's kind of paths)
if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
mkdirs(cachepath)
if isdir(cachepath) and file.is_writable(cachepath) then
@@ -180,7 +177,7 @@ function caches.usedpaths()
end
function caches.configfiles()
- return table.concat(resolvers.instance.specification,";")
+ return concat(resolvers.instance.specification,";")
end
function caches.hashed(tree)
@@ -304,9 +301,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname,table.serialize(data,true,saveoptions))
+ file.savedata(tmaname,serialize(data,true,saveoptions))
else
- table.tofile(tmaname,data,true,saveoptions)
+ serializetofile(tmaname,data,true,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -373,7 +370,7 @@ function caches.savecontent(cachename,dataname,content)
content = content,
uuid = os.uuid(),
}
- local ok = io.savedata(luaname,table.serialize(data,true))
+ local ok = io.savedata(luaname,serialize(data,true))
if ok then
if trace_locating then
report_resolvers("category '%s', cachename '%s' saved in '%s'",dataname,cachename,luaname)
diff --git a/Master/texmf-dist/tex/context/base/data-tre.lua b/Master/texmf-dist/tex/context/base/data-tre.lua
index 8b72f046bfc..1b916bf26ae 100644
--- a/Master/texmf-dist/tex/context/base/data-tre.lua
+++ b/Master/texmf-dist/tex/context/base/data-tre.lua
@@ -47,11 +47,11 @@ function resolvers.finders.tree(specification)
end
function resolvers.locators.tree(specification)
- -- TH: resolvers.resolve() call was missing here
- local name = resolvers.resolve(specification.filename)
- if name ~= '' and lfs.isdir(name) then
+ local name = specification.filename
+ local realname = resolvers.resolve(name) -- no shortcut
+ if realname and realname ~= '' and lfs.isdir(realname) then
if trace_locating then
- report_trees("locator '%s' found",name)
+ report_trees("locator '%s' found",realname)
end
resolvers.appendhash('tree',name,false) -- don't cache
elseif trace_locating then
@@ -65,6 +65,8 @@ function resolvers.hashers.tree(specification)
report_trees("analysing '%s'",name)
end
resolvers.methodhandler("hashers",name)
+
+ resolvers.generators.file(specification)
end
resolvers.concatinators.tree = resolvers.concatinators.file
diff --git a/Master/texmf-dist/tex/context/base/data-vir.lua b/Master/texmf-dist/tex/context/base/data-vir.lua
index 5a288953faa..89359c19a08 100644
--- a/Master/texmf-dist/tex/context/base/data-vir.lua
+++ b/Master/texmf-dist/tex/context/base/data-vir.lua
@@ -55,7 +55,8 @@ function openers.virtual(specification)
report_virtual("opener, file '%s' opened",original)
end
data[original] = nil
- return openers.helpers.textopener("virtual",original,d)
+ -- With utf-8 we signal that no regime is to be applied!
+ return openers.helpers.textopener("virtual",original,d,"utf-8")
else
if trace_virtual then
report_virtual("opener, file '%s' not found",original)
diff --git a/Master/texmf-dist/tex/context/base/data-zip.lua b/Master/texmf-dist/tex/context/base/data-zip.lua
index 6a50d2aa942..1d2f2d4f63a 100644
--- a/Master/texmf-dist/tex/context/base/data-zip.lua
+++ b/Master/texmf-dist/tex/context/base/data-zip.lua
@@ -31,6 +31,18 @@ local archives = zip.archives
zip.registeredfiles = zip.registeredfiles or { }
local registeredfiles = zip.registeredfiles
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ zip.open = i_limiter.protect(zip.open)
+ limited = true
+ end
+ end
+end)
+
local function validzip(str) -- todo: use url splitter
if not find(str,"^zip://") then
return "zip:///" .. str
diff --git a/Master/texmf-dist/tex/context/base/enco-032.mkii b/Master/texmf-dist/tex/context/base/enco-032.mkii
index d7e15126c94..e3c24271e55 100644
--- a/Master/texmf-dist/tex/context/base/enco-032.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-032.mkii
@@ -5,7 +5,7 @@
%D subtitle=Unicode Goodies,
%D author={Taco Hoekwater},
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-037.mkii b/Master/texmf-dist/tex/context/base/enco-037.mkii
index d9fc653b2c5..a2aad46a575 100644
--- a/Master/texmf-dist/tex/context/base/enco-037.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-037.mkii
@@ -5,7 +5,7 @@
%D subtitle=Encoding for vector 37,
%D author=Luigi Scarso,
%D date=\currentdate,
-%D copyright={PRAGMA}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-acc.mkii b/Master/texmf-dist/tex/context/base/enco-acc.mkii
index e02536be6fe..7484fd50ee2 100644
--- a/Master/texmf-dist/tex/context/base/enco-acc.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-acc.mkii
@@ -5,7 +5,7 @@
%D subtitle=Composed Characters Commands,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen \& Ton Otten]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-ans.mkii b/Master/texmf-dist/tex/context/base/enco-ans.mkii
index 88baf0ad0bb..c71b2451a60 100644
--- a/Master/texmf-dist/tex/context/base/enco-ans.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-ans.mkii
@@ -5,7 +5,7 @@
%D subtitle=\YandY\ texnansi Encoding,
%D author={Patrick Gundlach, Hans Hagen},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-cas.mkii b/Master/texmf-dist/tex/context/base/enco-cas.mkii
index 38d12f9fa83..6ac35eb325c 100644
--- a/Master/texmf-dist/tex/context/base/enco-cas.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-cas.mkii
@@ -5,7 +5,7 @@
%D subtitle=Named Glyph Case Mapping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-chi.mkii b/Master/texmf-dist/tex/context/base/enco-chi.mkii
index 9d77893a01a..727720565fd 100644
--- a/Master/texmf-dist/tex/context/base/enco-chi.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-chi.mkii
@@ -5,7 +5,7 @@
%D subtitle=Traditional and Simplified Chinese,
%D author={Wang Lei \& Hans Hagen},
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-com.mkii b/Master/texmf-dist/tex/context/base/enco-com.mkii
index 42d0d4774ee..620ac0c96ee 100644
--- a/Master/texmf-dist/tex/context/base/enco-com.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-com.mkii
@@ -5,7 +5,7 @@
%D subtitle=Composed Characters Commands,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen \& Ton Otten]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-cyr.mkii b/Master/texmf-dist/tex/context/base/enco-cyr.mkii
index 36bca82b5e7..aa412d8d3a4 100644
--- a/Master/texmf-dist/tex/context/base/enco-cyr.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-cyr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Cyrillic,
%D author=...,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-def.mkii b/Master/texmf-dist/tex/context/base/enco-def.mkii
index 4d8e280cb70..20c885d4dca 100644
--- a/Master/texmf-dist/tex/context/base/enco-def.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Default Character Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-ec.mkii b/Master/texmf-dist/tex/context/base/enco-ec.mkii
index f0964897fba..918c85e1261 100644
--- a/Master/texmf-dist/tex/context/base/enco-ec.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-ec.mkii
@@ -5,7 +5,7 @@
%D subtitle=\LATEX\ EC Encoding,
%D author={Patrick Gundlach, Hans Hagen, Taco Hoekwater, Mojca Miklavec},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-ecm.mkii b/Master/texmf-dist/tex/context/base/enco-ecm.mkii
index b744739607d..8a97065747a 100644
--- a/Master/texmf-dist/tex/context/base/enco-ecm.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-ecm.mkii
@@ -5,7 +5,7 @@
%D subtitle=Glyphs that may not be present in EC,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-el.mkii b/Master/texmf-dist/tex/context/base/enco-el.mkii
index 24729967bae..f268dcb3c24 100644
--- a/Master/texmf-dist/tex/context/base/enco-el.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-el.mkii
@@ -5,7 +5,7 @@
%D subtitle=EuroLetter,
%D author={Several Users},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-fde.mkii b/Master/texmf-dist/tex/context/base/enco-fde.mkii
index da104b802b7..57e572c04f4 100644
--- a/Master/texmf-dist/tex/context/base/enco-fde.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-fde.mkii
@@ -5,7 +5,7 @@
%D subtitle=German Input Filter,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-ffr.mkii b/Master/texmf-dist/tex/context/base/enco-ffr.mkii
index 259b5994959..7e605bb052c 100644
--- a/Master/texmf-dist/tex/context/base/enco-ffr.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-ffr.mkii
@@ -5,7 +5,7 @@
%D subtitle=French Input Filter,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-fpl.mkii b/Master/texmf-dist/tex/context/base/enco-fpl.mkii
index 14d102ff1ce..ddf86569838 100644
--- a/Master/texmf-dist/tex/context/base/enco-fpl.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-fpl.mkii
@@ -5,7 +5,7 @@
%D subtitle=Polish Input Filter,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-fro.mkii b/Master/texmf-dist/tex/context/base/enco-fro.mkii
index e5f5e1257f2..af127216383 100644
--- a/Master/texmf-dist/tex/context/base/enco-fro.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-fro.mkii
@@ -5,7 +5,7 @@
%D subtitle=Romanian Input Filter,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-fsl.mkii b/Master/texmf-dist/tex/context/base/enco-fsl.mkii
index 86a41c88a37..8fbca98cafc 100644
--- a/Master/texmf-dist/tex/context/base/enco-fsl.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-fsl.mkii
@@ -5,7 +5,7 @@
%D subtitle=Slovenian Specialities,
%D author={Hans Hagen, Mojka Miklavec},
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-grk.mkii b/Master/texmf-dist/tex/context/base/enco-grk.mkii
index 882a3c9b0cd..6264f362e88 100644
--- a/Master/texmf-dist/tex/context/base/enco-grk.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-grk.mkii
@@ -5,7 +5,7 @@
%D subtitle=Greek,
%D author=Apostolos Syropoulos,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-heb.mkii b/Master/texmf-dist/tex/context/base/enco-heb.mkii
index 44374575273..a4ef2cd2c11 100644
--- a/Master/texmf-dist/tex/context/base/enco-heb.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-heb.mkii
@@ -5,7 +5,7 @@
%D subtitle=Hebrew,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-il2.mkii b/Master/texmf-dist/tex/context/base/enco-il2.mkii
index 9fb87b2fd77..9b08dc8972f 100644
--- a/Master/texmf-dist/tex/context/base/enco-il2.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-il2.mkii
@@ -5,7 +5,7 @@
%D subtitle=Czech and Slovak ISO Latin 2 Encoding,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-ini.mkii b/Master/texmf-dist/tex/context/base/enco-ini.mkii
index a277e74504f..8603f2420e1 100644
--- a/Master/texmf-dist/tex/context/base/enco-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-ini.mkiv b/Master/texmf-dist/tex/context/base/enco-ini.mkiv
index 491084b8c16..a942d511096 100644
--- a/Master/texmf-dist/tex/context/base/enco-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/enco-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -232,7 +232,7 @@
\unexpanded\def\fallbackcontrolspace
%{\getglyph{ComputerModernMono}\textcontrolspace}
- {\getglyph{LMTypewriter10-Regular}\textcontrolspace}
+ {\getglyph{LMTypewriter-Regular}\textcontrolspace}
\unexpanded\def\normalcontrolspace
{\iffontchar\font\textcontrolspace
@@ -339,4 +339,42 @@
\unexpanded\def\textplus
{\char"002B } % plus
+%D Moved from core-mis:
+
+\unexpanded\def\celsius #1{#1\mathematics{^\circ}C}
+\unexpanded\def\inch {\mathematics{\prime\prime}} % was: \hbox{\rm\char125\relax}
+\unexpanded\def\fraction#1#2{\mathematics{#1\over#2}}
+
+\def\periodswidth {.5em}
+\def\periodsdefault{3} % was 5, but now it's like \unknown
+
+\unexpanded\def\periods
+ {\dosingleempty\doperiods}
+
+% \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.\hss}\hss}%
+% \endgroup}
+%
+% better for export:
+
+\unexpanded\def\doperiods[#1]% todo: also n=,width= or maybe just #1,#2
+ {\dontleavehmode
+ \hbox\bgroup
+ \setbox\scratchbox\hbox to \periodswidth{\hss.\hss}%
+ \dorecurse{\iffirstargument#1\else\periodsdefault\fi}{\copy\scratchbox}%
+ \egroup}
+
+\unexpanded\def\unknown
+ {\periods\relax} % relax prevents lookahead for []
+
+% Example by Wolfgang Schuster on the context list:
+%
+% \unexpanded\def\fourdots{{\def\periodswidth{.3em}\periods[4]}}
+%
+% Hello\fourdots\ World\fourdots \par Hello\fourdots\ World.
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/enco-l7x.mkii b/Master/texmf-dist/tex/context/base/enco-l7x.mkii
index 776c683c165..2a0d12c9f57 100644
--- a/Master/texmf-dist/tex/context/base/enco-l7x.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-l7x.mkii
@@ -5,7 +5,7 @@
%D subtitle=\LATEX\ L7x Encoding,
%D author={Hans Hagen \& Mojca Miklavec},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-mis.mkii b/Master/texmf-dist/tex/context/base/enco-mis.mkii
index 92dc61b3f06..28523685e4e 100644
--- a/Master/texmf-dist/tex/context/base/enco-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Missing Glyphs,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-pdf.mkii b/Master/texmf-dist/tex/context/base/enco-pdf.mkii
index a03e81df25d..28e96067361 100644
--- a/Master/texmf-dist/tex/context/base/enco-pdf.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-pdf.mkii
@@ -5,7 +5,7 @@
%D subtitle=\YandY\ texnansi Encoding,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-pfr.mkii b/Master/texmf-dist/tex/context/base/enco-pfr.mkii
index b279e40aae5..aca2436c130 100644
--- a/Master/texmf-dist/tex/context/base/enco-pfr.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-pfr.mkii
@@ -5,7 +5,7 @@
%D subtitle=PDF Resources,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-pol.mkii b/Master/texmf-dist/tex/context/base/enco-pol.mkii
index a012f03708c..ec49c6e1d37 100644
--- a/Master/texmf-dist/tex/context/base/enco-pol.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-pol.mkii
@@ -5,7 +5,7 @@
%D subtitle=Polish Mixed Encoding,
%D author={Taco Hoekwater \& Hans Hagen},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-qx.mkii b/Master/texmf-dist/tex/context/base/enco-qx.mkii
index 798a182496a..b184fe0ac0c 100644
--- a/Master/texmf-dist/tex/context/base/enco-qx.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-qx.mkii
@@ -5,7 +5,7 @@
%D subtitle=Polish QX Encoding,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-run.mkii b/Master/texmf-dist/tex/context/base/enco-run.mkii
index 50fb52e158b..2f60a35b874 100644
--- a/Master/texmf-dist/tex/context/base/enco-run.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen \& Ton Otten]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-t5.mkii b/Master/texmf-dist/tex/context/base/enco-t5.mkii
index a8d80be1477..3f51b85855b 100644
--- a/Master/texmf-dist/tex/context/base/enco-t5.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-t5.mkii
@@ -5,7 +5,7 @@
%D subtitle=New Vietnamese Encoding,
%D author=Hans Hagen \& Adam Lindsay,
%D date=\currentdate,
-%D copyright=PRAGMA \& Adam Lindsay]
+%D copyright={Adam Lindsay \& Hans Hagen}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
diff --git a/Master/texmf-dist/tex/context/base/enco-tbo.mkii b/Master/texmf-dist/tex/context/base/enco-tbo.mkii
index 475be4602f8..5733acd32e0 100644
--- a/Master/texmf-dist/tex/context/base/enco-tbo.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-tbo.mkii
@@ -5,7 +5,7 @@
%D subtitle=TeXBaseOne Encoding,
%D author={Patrick Gundlach, Hans Hagen},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-uc.mkii b/Master/texmf-dist/tex/context/base/enco-uc.mkii
index 981eb6ae455..0be22318a0f 100644
--- a/Master/texmf-dist/tex/context/base/enco-uc.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-uc.mkii
@@ -5,7 +5,7 @@
%D subtitle=Unicode (backwards mapping),
%D author={Adam Lindsay \& Hans Hagen},
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-vna.mkii b/Master/texmf-dist/tex/context/base/enco-vna.mkii
index 05753f37b01..42fee43417b 100644
--- a/Master/texmf-dist/tex/context/base/enco-vna.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-vna.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vietnamese Accents,
%D author=Han The Thanh & Adam Lindsay & Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/enco-x5.mkii b/Master/texmf-dist/tex/context/base/enco-x5.mkii
index d3b701c1a0e..cde394e294c 100644
--- a/Master/texmf-dist/tex/context/base/enco-x5.mkii
+++ b/Master/texmf-dist/tex/context/base/enco-x5.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vietnamese Encoding,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/export-example.css b/Master/texmf-dist/tex/context/base/export-example.css
new file mode 100644
index 00000000000..06d51c5874c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/export-example.css
@@ -0,0 +1,711 @@
+/*
+
+ author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+ copyright : PRAGMA ADE / ConTeXt Development Team
+ license : see context related readme files
+ comment : companion to context.mkiv
+
+*/
+
+/* ignore : mixed */
+/* metadata: display */
+
+ignore {
+ display : none ;
+}
+
+xmetadata {
+ display : none ;
+}
+
+xmetavariable {
+ display : none ;
+}
+
+/* document : display */
+
+document:before {
+ content : attr(title) ;
+ font-size : 44pt ;
+ font-weight : bold ;
+ margin-bottom : 1em ;
+}
+
+document {
+ font-family : "DejaVu Serif", "Lucida Bright", serif ;
+ font-size : 12pt ;
+ max-width : 50em ;
+ padding : 1em ;
+ /* text-align : justify ; */
+ /* hyphens : manual ; */
+ /* text-justify : inter-word ; */
+}
+
+document>metadata {
+ font-family : "Lucida Console", "DejaVu Sans Mono", monospace ;
+ margin-bottom : 2em ;
+}
+
+document>metadata>metavariable[name="title"]:before {
+ content : "title\00A0\00A0\00A0:\00A0" ;
+}
+
+document>metadata>metavariable[name="author"]:before {
+ content : "author\00A0\00A0:\00A0" ;
+}
+
+document>metadata>metavariable[name="version"]:before {
+ content : "version\00A0:\00A0" ;
+}
+
+document>metadata>metavariable[name="title"], document>metadata>metavariable[name="author"], document>metadata>metavariable[name="version"] {
+ display : block ;
+}
+
+/* paragraph : mixed */
+/* p : mixed */
+
+paragraph, p {
+ display : block ;
+ margin-top : 0.5em ;
+ margin-bottom : 0.5em ;
+}
+
+/* break : display */
+
+break {
+ display : block ;
+ margin-bottom : 0.5em ;
+}
+
+/* construct : inline */
+/* highlight : inline */
+
+construct {
+}
+
+construct[detail="important"] {
+ font-weight : bold ;
+}
+
+highlight { /* todo: style and color */
+}
+
+/* section : display */
+/* sectiontitle : mixed */
+/* sectionnumber : mixed */
+/* sectioncontent : display */
+
+section {
+ display : block ;
+}
+
+sectioncontent {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+}
+
+section[detail="chapter"], section[detail="title"] {
+ margin-top : 3em ;
+ margin-bottom : 2em ;
+}
+
+section[detail="section"], section[detail="subject"] {
+ margin-top : 2.5em ;
+ margin-bottom : 2.5em ;
+}
+
+section[detail="subsection"], section[detail="subsubject"] {
+ margin-top : 2em ;
+ margin-bottom : 2em ;
+}
+
+section[detail="subsubsection"], section[detail="subsubsubject"] {
+ margin-top : 1em ;
+ margin-bottom : 0em ;
+}
+
+section[detail="summary"], section[detail="subsummary"] {
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+}
+
+section[detail="chapter"]>sectionnumber {
+ display : inline-block ;
+ margin-right : 1em ;
+ font-size : 3em ;
+ font-weight : bold ;
+}
+
+section[detail="chapter"]>sectiontitle, section[detail="title"]>sectiontitle {
+ font-size : 3em ;
+ font-weight : bold ;
+}
+
+section[detail="section"]>sectiontitle, section[detail="subject"]>sectiontitle {
+ font-size : 2.5em ;
+ font-weight : bold ;
+}
+
+section[detail="subsection"]>sectiontitle, section[detail="subsubject"]>sectiontitle{
+ font-size : 2em ;
+ font-weight : bold ;
+}
+
+section[detail="subsubsection"]>sectiontitle, section[detail="subsubsubject"]>sectiontitle{
+ font-size : 1em ;
+ font-weight : bold ;
+}
+
+section[detail="section"]>sectionnumber {
+ display : inline-block ;
+ margin-right : 1em ;
+ font-size : 2.5em ;
+ font-weight : bold ;
+}
+
+section[detail="summary"]>sectiontitle {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ font-weight : bold ;
+ border-bottom-style : solid ;
+ border-color : rgb(50%,50%,100%) ;
+ border-width : .15em;
+}
+
+section[detail="subsection"]>sectionnumber {
+ display : inline-block ;
+ margin-right : 1em ;
+ font-size : 2em ;
+ font-weight : bold ;
+}
+
+section[detail="subsection"]>sectionnumber {
+ display : inline-block ;
+ margin-right : 1em ;
+ font-size : 1em ;
+ font-weight : bold ;
+}
+
+section[detail="subsummary"]>sectiontitle {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ font-weight : bold ;
+ border-color : rgb(50%,50%,100%) ;
+ border-bottom-style : dotted ;
+ border-width : .15em ;
+}
+
+/* itemgroup : display */
+/* item : display */
+/* itemtag : mixed */
+/* itemcontent : mixed */
+
+/* type : alphabetic ; */
+/* suffix : '.' ; */
+
+@counter-style lower-greek { /* css 3 */
+ type : non-repeating ;
+ glyphs : 'α' 'β' 'γ' 'δ' 'ε' 'ζ' 'η' 'θ' 'ι' 'κ' 'λ' 'μ' 'ν' 'ξ' 'ο' 'Ï€' 'Ï' 'σ' 'Ï„' 'Ï…' 'φ' 'χ' 'ψ' 'ω' ;
+}
+
+@counter-style upper-greek { /* css 3 */
+ type : non-repeating ;
+ glyphs : 'Α' 'B' 'Γ' 'Δ' 'Ε' 'Ζ' 'Η' 'Θ' 'Ι' 'Κ' 'Λ' 'Îœ' 'Î' 'Ξ' 'Ο' 'Π' 'Ρ' 'Σ' 'Τ' 'Î¥' 'Φ' 'Χ' 'Ψ' 'Ω' ;
+}
+
+itemgroup {
+ display : block ;
+ margin-bottom : 0.5em ;
+ margin-top : 0.5em ;
+}
+
+itemgroup[symbol="1"] { list-style-type : disc ; }
+itemgroup[symbol="2"] { list-style-type : square ; }
+itemgroup[symbol="3"] { list-style-type : square ; }
+itemgroup[symbol="4"] { list-style-type : square ; }
+itemgroup[symbol="5"] { list-style-type : circ ; }
+itemgroup[symbol="a"] { list-style-type : lower-alpha ; }
+itemgroup[symbol="A"] { list-style-type : alpha ; }
+itemgroup[symbol="r"] { list-style-type : lower-roman ; }
+itemgroup[symbol="R"] { list-style-type : upper-roman ; }
+itemgroup[symbol="n"] { list-style-type : decimal ; }
+itemgroup[symbol="g"] { list-style-type : lower-greek ; }
+itemgroup[symbol="G"] { list-style-type : upper-greek ; }
+
+item {
+ display : list-item ;
+ margin-left : 1em ;
+ margin-bottom : 0.5em ;
+ margin-top : 0.5em ;
+}
+
+itemtag {
+ display: none ;
+}
+
+itemcontent {
+}
+
+/* description : display */
+/* descriptiontag : mixed */
+/* descriptioncontent : mixed */
+/* descriptionsymbol : inline */
+
+description {
+ display : block ;
+ margin-bottom : 1em ;
+ margin-top : 1em ;
+}
+
+descriptiontag {
+ float : left ;
+ clear : left ;
+ margin-right : 1em ;
+ text-align : left ;
+ font-weight : bold ;
+}
+
+descriptioncontent {
+}
+
+descriptionsymbol {
+}
+
+/* verbatimblock : display */
+/* verbatimlines : display */
+/* verbatimline : mixed */
+/* verbatim : inline */
+
+verbatimblock {
+ background-color : rgb(50%,50%,100%) ;
+ display : block ;
+ padding : 1em ;
+ margin-bottom : 1em ;
+ margin-top : 1em ;
+ font-family : "Lucida Console", "DejaVu Sans Mono", monospace ;
+}
+
+verbatimlines+verbatimlines {
+ display : block ;
+ margin-top : 1em ;
+}
+
+verbatimline {
+ display : block ;
+ white-space : pre-wrap ;
+}
+
+verbatim {
+ white-space : pre-wrap ;
+ color : rgb(60%,60%,0%) ;
+ font-family : "Lucida Console", "DejaVu Sans Mono", monospace ;
+}
+
+/* lines : display */
+/* line : mixed */
+
+lines {
+ display : block ;
+ margin-bottom : 1em ;
+ margin-top : 1em ;
+}
+
+lines+lines {
+ display : block ;
+ margin-top : 1em ;
+}
+
+line {
+ display : block ;
+ white-space : pre-wrap ;
+}
+
+/* synonym : inline */
+/* sorting : inline */
+
+sorting, synonym {
+ display : inline ;
+ font-variant : small-caps ;
+}
+
+/* register : display */
+/* registersection : display */
+/* registertag : mixed */
+/* registerentries : display */
+/* registerentry : mixed */
+/* registersee : mixed */
+/* registerpages : mixed */
+/* registerpage : inline */
+/* registerpagerange : mixed */
+
+register {
+ display: none ;
+}
+
+/* table : display */
+/* tablerow : display */
+/* tablecell : mixed */
+
+table {
+ display : table ;
+}
+
+tablerow {
+ display : table-row ;
+}
+
+tablecell[align="middle"] {
+ display : table-cell ;
+ text-align : center ;
+ padding : .1em ;
+}
+
+tablecell[align="flushleft"] {
+ display : table-cell ;
+ text-align : left ;
+ padding : .1em ;
+}
+
+tablecell[align="flushright"] {
+ display : table-cell ;
+ text-align : right ;
+ padding : .1em ;
+}
+
+tablecell {
+ display : table-cell ;
+ text-align : left ;
+ padding : .1em ;
+}
+
+/* tabulate : display */
+/* tabulaterow : display */
+/* tabulatecell : mixed */
+
+tabulate {
+ display : table ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+tabulaterow {
+ display : table-row ;
+}
+
+tabulatecell[align="middle"] {
+ display : table-cell ;
+ text-align : center ;
+ padding-right : 1em ;
+}
+
+tabulatecell[align="flushleft"] {
+ display : table-cell ;
+ text-align : left ;
+ padding-right : 1em ;
+}
+
+tabulatecell[align="flushright"] {
+ display : table-cell ;
+ text-align : right ;
+ padding-right : 1em ;
+}
+
+tabulatecell {
+ display : table-cell ;
+ text-align : left ;
+ padding-right : 1em ;
+}
+
+/* combination : display */
+/* combinationpair : display */
+/* combinationcontent : mixed */
+/* combinationcaption : mixed */
+
+combination {
+ display : table ;
+ margin-top : 0em ;
+ margin-bottom : 0em ;
+}
+
+combinationpair {
+ display : table-cell ;
+ padding-right : 1em ;
+}
+
+combinationcontent {
+ display : table-row ;
+ text-align : center ;
+}
+
+combinationcaption {
+ display : table-row ;
+ padding-top : 1ex ;
+ text-align : center ;
+}
+
+
+/* list : display */
+/* listitem : display */
+/* listtag : mixed */
+/* listcontent : mixed */
+/* listdata : mixed */
+/* listpage : mixed */
+
+list {
+ display : block ;
+}
+
+listitem[detail="chapter"] {
+ display : block ;
+ margin-top : 1em ;
+ font-weight : bold ;
+}
+
+listitem[detail="section"] {
+ display : block ;
+}
+
+listitem[detail="subsection"] {
+ display : block ;
+}
+
+listtag {
+ display : inline-block ;
+ width : 5em ;
+}
+
+listcontent {
+}
+
+listdata {
+}
+
+listpage {
+ display : none ;
+}
+
+/* delimitedblock : display */
+/* delimited : inline */
+/* subsentence : inline */
+
+/* :lang(en) */
+
+delimited[detail="quotation"]:before, delimitedblock[detail="quotation"]:before {
+ content : "\201C" ;
+}
+
+delimited[detail="quotation"]:after, delimitedblock[detail="quotation"]:after {
+ content : "\201D" ;
+}
+
+delimited[detail="quote"]:before, delimitedblock[detail="quote"]:before {
+ content : "\2018" ;
+}
+
+delimited[detail="quote"]:after, delimitedblock[detail="quote"]:after {
+ content : "\2019" ;
+}
+
+delimited {
+ display : inline
+}
+
+delimitedblock {
+ display : block
+}
+
+subsentence:before, subsentence:after {
+ content : "\2014" ;
+}
+
+subsentence {
+ display : inline
+}
+
+/* label : mixed */
+/* number : mixed */
+
+/* float : display */
+/* floatcaption : mixed */
+/* floatlabel : inline */
+/* floatnumber : inline */
+/* floattext : mixed */
+/* floatcontent : mixed */
+
+float {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+floatcaption {
+ display : block ;
+ margin-top : 0.5em ;
+ color : rgb(60%,60%,0%) ;
+}
+
+floatlabel {
+ font-weight : bold ;
+ margin-right : 1em ;
+}
+
+floatnumber {
+ font-weight : bold ;
+}
+
+floattext {
+}
+
+floatcontent {
+}
+
+/* image : mixed */
+/* mpgraphic : mixed */
+
+/* image {
+ display : block ;
+ background : url(hacker.jpg) ;
+ background-size : 100% auto ;
+ width : 8.992cm ;
+ height : 5.994cm ;
+} */
+
+mpgraphic:before { /* does not work with empty element */
+ content : "[runtime metapost graphic]" ;
+}
+
+mpgraphic {
+ display : inline ;
+}
+
+/* formula : display */
+/* subformula : display */
+/* formulaset : display */
+/* formulacaption : mixed */
+/* formulalabel : mixed */
+/* formulanumber : mixed */
+/* formulacontent : display */
+
+formula {
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+subformula { /* todo */
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+formulaset { /* todo */
+ display : block ;
+ margin-top : 1em ;
+ margin-bottom : 1em ;
+ margin-left : 2.5em ;
+}
+
+formulacaption { /* todo */
+ display : block ;
+ margin-top : 0.5em ;
+ color : rgb(60%,60%,0%) ;
+}
+
+formulalabel {
+ font-weight : bold ;
+ margin-right : 1em ;
+}
+
+formulanumber {
+ font-weight : bold ;
+}
+
+formulacontent {
+ display : block ;
+}
+
+/* link : inline */
+
+/* margintextblock : inline */
+/* margintext : inline */
+
+/* math : inline */
+/* mn : mixed */
+/* mi : mixed */
+/* mo : mixed */
+/* ms : mixed */
+/* mrow : display */
+/* msubsup : display */
+/* msub : display */
+/* msup : display */
+/* merror : mixed */
+/* munderover : display */
+/* munder : display */
+/* mover : display */
+/* mtext : mixed */
+/* mfrac : display */
+/* mroot : display */
+/* msqrt : display */
+/* mfenced : display */
+/* maction : display */
+/* mtable : display */
+/* mtr : display */
+/* mtd : display */
+
+/* quantity : inline */
+/* unit : inline */
+/* number : inline */
+
+quantity {
+}
+
+quantity>unit {
+}
+
+quantity>number {
+}
+
+/* sub : inline */
+/* sup : inline */
+/* subsup : inline */
+
+sup {
+ font-size : xx-small ;
+ line-height : 0 ;
+ vertical-align : top ;
+}
+
+sub {
+ font-size : xx-small ;
+ line-height : 0 ;
+ vertical-align : bottom ;
+}
+
+
+subsup>sup {
+ vertical-align : top ;
+}
+
+subsup>sub {
+ vertical-align : bottom ;
+}
+
+/* xhtml */
+
+a[href] {
+ text-decoration : none ;
+ color : inherit ;
+}
+
+a[href]:hover {
+ color : rgb(50%,0%,0%) ;
+ text-decoration : underline ;
+}
diff --git a/Master/texmf-dist/tex/context/base/export-example.rng b/Master/texmf-dist/tex/context/base/export-example.rng
new file mode 100644
index 00000000000..93b21ba50bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/export-example.rng
@@ -0,0 +1,377 @@
+# author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+# copyright : PRAGMA ADE / ConTeXt Development Team
+# license : see context related readme files
+# comment : companion to context.mkiv
+
+# todo: check all content (not yet ok but a bit boring job)
+# todo: add attributes
+# todo: we need more | and less ,
+#
+# validate with "rnv -c export-example.rng"
+
+namespace m = "http://www.w3.org/1998/Math/MathML"
+
+start = e_document
+
+# Because users can typeset anything the content is somewhat
+# unpredictable so this is just an indication of what to expect.
+
+c_everything =
+ text
+ | c_inline
+ | e_verbatimblock
+ | e_lines
+ | e_itemgroup
+ | e_table
+ | e_tabulate
+ | e_register
+ | e_list
+ | e_section
+ | e_float
+ | e_formula
+ | e_combination
+
+c_inline =
+ text
+ | e_ignore
+ | e_metadata
+ | e_construct
+ | e_highlight
+ | e_verbatim
+ | e_description
+ | e_descriptionsymbol
+ | e_sorting
+ | e_synonym
+ | e_image
+ | e_mpgraphic
+ | e_math
+ | e_sub
+ | e_sup
+ | e_subsup
+ | e_link
+ | e_margintext
+ | e_margintextblock
+
+# We pass some relevant information via attributes. The detail attribute
+# is common and provides information about the class or environment used.
+
+a_detail = attribute detail {
+ text
+}
+
+# The document element is the root of all.
+
+e_document = element document {
+ c_everything *
+}
+
+e_ignore = element ignore {
+ c_everything *
+}
+
+e_metadata = element metadata {
+ element metavariable {
+ attribute name { text } ?
+ , text
+ } *
+}
+
+e_section = element section {
+ a_detail ?
+ | (
+ element sectiontitle {
+ c_inline *
+ }
+ , element sectionnumber {
+ c_inline *
+ } *
+ , element sectioncontent {
+ c_everything *
+ }
+ )
+}
+
+e_paragraph = element paragraph {
+ c_inline *
+}
+
+e_p = element p {
+ c_inline *
+}
+
+e_break = element break {
+ empty
+}
+
+e_construct = element construct {
+ c_everything*
+}
+
+e_highlight = element highlight {
+ c_inline*
+}
+
+e_itemgroup = element itemgroup {
+ element item {
+ element itemtag {
+ c_inline *
+ }
+ } ,
+ element itemcontent {
+ c_everything *
+ }
+}
+
+e_combination = element combination {
+ element combinationpair {
+ element combinationcontent {
+ inline*
+ } ,
+ element combinationcaption {
+ inline*
+ }
+ }
+}
+
+e_description = element description {
+ element descriptiontag {
+ c_inline*
+ } ,
+ element descriptioncontent {
+ c_inline*
+ } ,
+ element descriptionsymbol {
+ c_inline*
+ }
+}
+
+e_descriptionsymbol = element descriptionsymbol {
+ c_inline*
+}
+
+e_verbatimblock = element verbatimblock {
+ element verbatimlines {
+ element verbatimline {
+ text
+ } *
+ } *
+}
+
+e_verbatim = element verbatim {
+ text
+}
+
+e_lines = element lines {
+ element line {
+ text
+ } *
+}
+
+e_synonym = element synonym {
+ text
+}
+
+e_sorting = element sorting {
+ text
+}
+
+e_register = element register {
+ element registersection {
+ element registertag {
+ text
+ } ?
+ ,
+ element registerentries {
+ (
+ element registerentry {
+ text
+ } |
+ element registersee {
+ text
+ }
+ ),
+ (
+ element registerpages {
+ element registerpage {
+ text
+ } *
+ } |
+ element registerpage {
+ text
+ } |
+ element registerpagerange {
+ element registerpage {
+ text
+ } ,
+ element registerpage {
+ text
+ }
+ }
+ )
+ } ?
+ } *
+}
+
+e_table = element table {
+ element tablerow {
+ element tablecell {
+ c_inline *
+ } *
+ } *
+}
+
+e_tabulate = element tabulate {
+ element tabulaterow {
+ element tabulatecell {
+ c_inline *
+ } *
+ } *
+}
+
+e_list = element list {
+ element listitem {
+ element listtag {
+ text
+ } ? ,
+ element listcontent {
+ text
+ } ? ,
+ element listdata {
+ text
+ } ? ,
+ element listpage {
+ text
+ } ?
+ }
+}
+
+e_delimitedblock = element delimitedblock {
+ c_everything*
+}
+
+e_delimited = element delimited {
+ c_inline
+}
+
+e_subsentence = element subsentence {
+ c_inline
+}
+
+e_float = element float {
+ element floatcaption {
+ element floatlabel {
+ text
+ } ,
+ element floatnumber {
+ text
+ } ,
+ element floattext {
+ c_inline
+ }
+ } ,
+ element floatcontent {
+ c_inline
+ }
+}
+
+e_image = element image {
+ empty
+}
+
+e_mpgraphic = element mpgraphic {
+ empty
+}
+
+e_formula = element formula {
+ element subformula {
+ element formulacontent {
+ e_math*
+ }
+ } ,
+ element formulaset {
+ element formulacontent {
+ e_math*
+ }
+ } ,
+ element formulacaption {
+ element formulalabel {
+ text
+ } ,
+ element formulanumber {
+ text
+ }
+ } ,
+ element formulacontent {
+ e_math*
+ }
+}
+
+e_link = element link {
+ c_inline
+}
+
+e_margintextblock = element margintextblock {
+ c_inline
+}
+
+e_margintext = element margintext {
+ c_inline
+}
+
+e_quantity = element quantity {
+ element unit {
+ text
+ } ,
+ element number {
+ text
+ }
+}
+
+e_unit = element unit {
+ text |
+ e_math
+}
+
+e_sub = element sub {
+ c_inline
+}
+
+e_sup = element sup {
+ c_inline
+}
+
+e_subsup = element subsup {
+ c_inline,
+ c_inline
+}
+
+# There are enough mathml dtd's out there so this is just a
+# simplified placeholder.
+
+e_math_basics =
+ element m:mn | m:mi | m:mo | m:ms | m:merror | m:mtext {
+ text
+ } |
+ element m:mrow | m:msub | m:msup | m:msqrt | m:mfenced | m:maction {
+ e_math_basics *
+ } |
+ element m:msubsup | m:munder | m:mover | m:mfrac | m:mroot {
+ e_math_basics,
+ e_math_basics
+ } |
+ element m:munderover {
+ e_math_basics,
+ e_math_basics,
+ e_math_basics
+ } |
+ element m:mtable {
+ element m:mtr {
+ element m:mtd {
+ e_math_basics *
+ } *
+ } *
+ }
+
+e_math = element m:math {
+ e_math_basics *
+}
diff --git a/Master/texmf-dist/tex/context/base/export-example.tex b/Master/texmf-dist/tex/context/base/export-example.tex
new file mode 100644
index 00000000000..3a70b92fdaa
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/export-example.tex
@@ -0,0 +1,120 @@
+% language=uk
+
+\usemodule[abr-01]
+
+\setupexport
+ [%bodyfont=16pt,
+ width=650pt,
+ %align=flushleft,
+ hyphen=yes]
+
+\setupbackend
+ [export=export-example.xml,
+ xhtml=export-example.xhtml,
+ css=export-example.css]
+
+% \setupalign
+% [flushleft]
+
+\settaggedmetadata
+ [title=Export Example,
+ author=Hans Hagen,
+ version=0.1]
+
+\setupbodyfont
+ [dejavu]
+
+\setupinteraction
+ [state=start]
+
+\setuplayout
+ [width=middle]
+
+\setupwhitespace
+ [big]
+
+\definedescription
+ [description]
+
+\enabledirectives[export.css.hyphens=yes]
+\enabledirectives[export.css.textwidth=100em]
+
+\definehighlight[interesting][style=bold,color=red]
+
+\starttext
+
+\startchapter[title=Example]
+
+\startparagraph \input zapf (Zapf) \stopparagraph
+
+\startparagraph
+ Watching a \interesting {movie} after reading a review on \goto{my favourite movie
+ reviews site}[url(http://outlawvern.com/)] is much more fun. \footnote {Just a note.}
+\stopparagraph
+
+\placefigure
+ {}
+ {\startcombination[3*1]
+ {\externalfigure[hacker.jpg][width=3cm]} {first}
+ {\externalfigure[hacker.jpg][width=4cm]} {second}
+ {\externalfigure[hacker.jpg][width=2cm]} {third}
+ \stopcombination}
+
+\startparagraph \input zapf (Zapf) \stopparagraph
+
+\placefigure
+ {}
+ {\externalfigure[mill.png]}
+
+\startparagraph \input tufte (Tufte) \stopparagraph
+
+\placefigure
+ {}
+ {\externalfigure[cow.pdf]}
+
+\startparagraph \input tufte (Tufte) \stopparagraph
+
+\startitemize[1]
+ \startitem \input ward (Ward) \stopitem
+ \startitem \input knuth (Knuth) \stopitem
+\stopitemize
+
+\startitemize[2,packed]
+ \startitem \input zapf (Zapf) \stopitem
+ \startitem \input tufte (Tufte) \stopitem
+\stopitemize
+
+\startparagraph \input zapf (Zapf) \stopparagraph
+
+\startdescription {Ward} \input ward \stopdescription
+
+\startdescription {Tufte} \input tufte \stopdescription
+
+\startparagraph \input knuth (Knuth) \stopparagraph
+
+\startformula
+e = mc^2
+\stopformula
+
+\startparagraph
+Okay, it's somewhat boring to always use the same formula, so how about
+$\sqrt{4} = 2$ or travelling at \unit{120 km/h} instead of $\unit{110 km/h}$.
+\stopparagraph
+
+\bTABLE
+\bTR \bTD test \eTD \bTD test \eTD \eTR
+\bTR \bTD[nx=2] test \eTD \eTR
+\eTABLE
+
+\starttabulate[|l|r|p|]
+\NC left \NC right \NC \input ward \NC \NR
+\NC l \NC r \NC \input ward \NC \NR
+\stoptabulate
+
+It looks like we're using \CONTEXT\ to produce some kind of \XML\ output.
+
+\typefile{export-example.tex}
+
+\stopchapter
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/file-ini.lua b/Master/texmf-dist/tex/context/base/file-ini.lua
new file mode 100644
index 00000000000..4f8b5b6e345
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-ini.lua
@@ -0,0 +1,38 @@
+if not modules then modules = { } end modules ['file-ini'] = {
+ version = 1.001,
+ comment = "companion to file-ini.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[ldx--
+<p>It's more convenient to manipulate filenames (paths) in
+<l n='lua'/> than in <l n='tex'/>. These methods have counterparts
+at the <l n='tex'/> side.</p>
+--ldx]]--
+
+resolvers.jobs = resolvers.jobs or { }
+
+local texcount = tex.count
+local setvalue = context.setvalue
+
+function commands.splitfilename(fullname)
+ local t = file.nametotable(fullname)
+ local path = t.path
+ texcount.splitoffkind = (path == "" and 0) or (path == '.' and 1) or 2
+ setvalue("splitofffull",fullname)
+ setvalue("splitoffpath",path)
+ setvalue("splitoffname",t.name)
+ setvalue("splitoffbase",t.base)
+ setvalue("splitofftype",t.suffix)
+end
+
+function commands.doifparentfileelse(n)
+ commands.doifelse(n == environment.jobname or n == environment.jobname .. '.tex' or n == environment.outputfilename)
+end
+
+function commands.doiffileexistelse(name)
+ local foundname = resolvers.findtexfile(name)
+ commands.doifelse(foundname and foundname ~= "")
+end
diff --git a/Master/texmf-dist/tex/context/base/file-ini.mkvi b/Master/texmf-dist/tex/context/base/file-ini.mkvi
new file mode 100644
index 00000000000..b0f6244aa9a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-ini.mkvi
@@ -0,0 +1,225 @@
+%D \module
+%D [ file=file-ini, % was supp-fil,
+%D version=20110701, % 1995.10.10,
+%D title=\CONTEXT\ File Macros,
+%D subtitle=Helpers,
+%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 \TEX\ operates on files, so one wouldn't wonder that there
+%D is a separate module for file commands. In \CONTEXT\ files
+%D are used for several purposes:
+%D
+%D \startitemize[packed]
+%D \item general textual input
+%D \item logging status information
+%D \item saving registers, lists and references
+%D \item buffering defered textual input
+%D \stopitemize
+%D
+%D When dealing with files we can load them as a whole, using
+%D the \type{\input} primitive or load them on a line||by||line
+%D basis, using \type{\read}. Writing is always done line by
+%D line, using \type{\write}.
+
+\writestatus{loading}{ConTeXt File Macros / Helpers}
+
+\registerctxluafile{file-ini}{1.001}
+
+\unprotect
+
+%D \macros
+%D {scratchread, scratchwrite}
+%D
+%D We define a scratch file for reading. Keep in mind that
+%D the number of files is limited to~16, so use this one when
+%D possible. We also define a scratch output file.
+
+\ifdefined\scratchread \else \newread \scratchread \fi
+\ifdefined\scratchwrite \else \newwrite\scratchwrite \fi
+
+%D Seldom needed:
+
+\def\openinputfile #handle#name{\immediate\openin #handle={#name}\relax}
+\def\openoutputfile #handle#name{\immediate\openout#handle={#name}\relax}
+
+\def\closeinputfile #handle{\immediate\closein #handle\relax}
+\def\closeoutputfile#handle{\immediate\closeout#handle\relax}
+
+%D \macros
+%D {writeln}
+%D
+%D This saves a few tokens:
+
+\def\writeln#handle{\write#handle{}}
+
+%D \macros
+%D {pushendofline,popendofline}
+%D
+%D When we are loading files in the middle of the typesetting
+%D process, for instance when we load references, we have to be
+%D sure that the reading process does not generate so called
+%D 'spurious spaces'. This can be prevented by assigning the
+%D line ending character the \CATCODE\ comment. This is
+%D accomplished by
+%D
+%D \starttyping
+%D \pushendofline
+%D ... reading ...
+%D \popendofline
+%D \stoptyping
+
+\newcount\c_system_files_eol_level
+
+\unexpanded\def\pushendofline
+ {\advance\c_system_files_eol_level\plusone
+ \expandafter\chardef\csname\??fi:eol:\number\c_system_files_eol_level\endcsname\catcode\endoflineasciicode
+ \catcode\endoflineasciicode\commentcatcode}
+
+\unexpanded\def\popendofline
+ {\catcode\endoflineasciicode\csname\??fi:eol:\number\c_system_files_eol_level\endcsname
+ \advance\c_system_files_eol_level\minusone}
+
+\unexpanded\def\restoreendofline
+ {\catcode\endoflineasciicode\endoflinecatcode}
+
+%D \macros
+%D {startreadingfile,stopreadingfile}
+%D
+%D A low level capsule:
+
+\newcount\readingfilelevel % no longer needed
+\newtoks \everystartreadingfile
+\newtoks \everystopreadingfile
+
+\unexpanded\def\startreadingfile% beter een every en \setnormalcatcodes
+ {\global\advance\readingfilelevel\plusone
+ \the\everystartreadingfile
+ \pushcatcodetable % saveguard
+ \setcatcodetable\ctxcatcodes
+ \ctxlua{regimes.push()}}% temporarily this way
+
+\unexpanded\def\stopreadingfile
+ {\popcatcodetable % saveguard
+ \ctxlua{regimes.pop()}% temporarily this way
+ \the\everystopreadingfile
+ \global\advance\readingfilelevel\minusone}
+
+%D \macros
+%D {input, normalinput}
+%D
+%D Sometimes we run into troubles when \type {\input} wants to get
+%D expanded, e.g. in a \type {\write} (which happens in the metafun
+%D manual when we permit long MP lines). So, instead of fixing that,
+%D we go for a redefinition of \type {\input}. Of course it's better
+%D to use \type {\readfile} or \type {\processfile}.
+
+\unexpanded\def\input{\normalinput}
+
+\def\inputgivenfile#name{\normalinput{#name}}
+
+%D \macros
+%D {doiffileelse}
+%D
+%D The next alternative only looks if a file is present. No
+%D loading is done. This one obeys the standard \TEX\ lookup.
+%D
+%D \starttyping
+%D \doiffileelse {filename} {found} {not found}
+%D \stoptyping
+
+\def\doiffileexistselse#name{\ctxcommand{doiffileexistelse([[#name]])}}
+
+\def\doiffileelse {\doiffileexistselse}
+\def\doiffile #name{\doiffileexistselse{#name}\firstofoneargument\gobbleoneargument}
+\def\doifnotfile #name{\doiffileexistselse{#name}\gobbleoneargument\firstofoneargument}
+
+%D \macros
+%D {doifparentfileelse}
+%D
+%D \starttyping
+%D \doifparentfileelse{filename}{yes}{no}
+%D \stoptyping
+
+\ifx\outputfilename\undefined \def\outputfilename{\jobname} \fi
+
+\def\doifparentfileelse#name{\ctxcommand{doifparentfileelse([[#name]])}}
+
+%D \macros
+%D {splitfilename}
+%D
+%D \startbuffer
+%D \def\showfilesplit
+%D {\bgroup \tttf
+%D \hbox{(full: \splitofffull)}\space
+%D \hbox{(path: \splitoffpath)}\space
+%D \hbox{(base: \splitoffbase)}\space
+%D \hbox{(name: \splitoffname)}\space
+%D \hbox{(type: \splitofftype)}\space
+%D \egroup}
+%D
+%D \splitfilename{c:/aa/bb/cc/dd.ee.ff} \showfilesplit \endgraf
+%D \splitfilename{c:/aa/bb/cc/dd.ee} \showfilesplit \endgraf
+%D \splitfilename{c:/aa/bb/cc/dd} \showfilesplit \endgraf
+%D
+%D \splitfilename{dd.ee.ff} \showfilesplit \endgraf
+%D \splitfilename{dd.ee} \showfilesplit \endgraf
+%D \splitfilename{dd} \showfilesplit \endgraf
+%D \stopbuffer
+%D
+%D \start \typebuffer \getbuffer \stop
+
+\newconstant\kindoffile % 0=normal 1=full path spec (or http) / set at the lua end
+
+\def\splitoffroot{.} \newconstant\splitoffkind
+
+\let\splitofffull\empty
+\let\splitoffpath\empty
+\let\splitoffbase\empty
+\let\splitoffname\empty
+\let\splitofftype\empty
+
+\def\splitfilename#name{\ctxcommand{splitfilename([[#name]])}}
+
+%D \macros
+%D {doonlyonce, doinputonce, doendinputonce}
+%D
+%D Especially macropackages need only be loaded once.
+%D Repetitive loading not only costs time, relocating registers
+%D often leads to abortion of the processing because \TEX's
+%D capacity is limited. One can prevent multiple execution and
+%D loading by using one of both:
+%D
+%D \starttyping
+%D \doonlyonce{actions}
+%D \doinputonce{filename}
+%D \doendinputonce{filename}
+%D \stoptyping
+%D
+%D This command obeys the standard method for locating files. We could
+%D move this function to the \LUA\ end.
+
+\unexpanded\def\doonlyonce#whatever%
+ {\ifcsname\??fi:#whatever\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \letgvalue{\??fi:#whatever}\relax
+ \expandafter\firstofoneargument
+ \fi}
+
+\unexpanded\def\doinputonce#name%
+ {\doonlyonce{#name}{\doiffileelse{#name}{\inputgivenfile{#name}}\donothing}}
+
+\unexpanded\def\doendinputonce#name%
+ {\ifcsname\??fi:#name\endcsname
+ \expandafter\endinput
+ \fi}
+
+\unexpanded\def\forgetdoingonce#whatever%
+ {\global\letbeundefined{\??fi:#whatever}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/file-job.lua b/Master/texmf-dist/tex/context/base/file-job.lua
new file mode 100644
index 00000000000..992e4b7ec70
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-job.lua
@@ -0,0 +1,685 @@
+if not modules then modules = { } end modules ['file-job'] = {
+ version = 1.001,
+ comment = "companion to file-job.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- in retrospect dealing it's not that bad to deal with the nesting
+-- and push/poppign at the tex end
+
+local format, gsub, match = string.format, string.gsub, string.match
+local insert, remove, concat = table.insert, table.remove, table.concat
+
+local commands, resolvers, context = commands, resolvers, context
+
+local trace_jobfiles = false trackers.register("system.jobfiles", function(v) trace_jobfiles = v end)
+
+local report_jobfiles = logs.reporter("system","jobfiles")
+
+local texsetcount = tex.setcount
+local elements = interfaces.elements
+local variables = interfaces.variables
+local logsnewline = logs.newline
+local logspushtarget = logs.pushtarget
+local logspoptarget = logs.poptarget
+
+local v_outer = variables.outer
+local v_text = variables.text
+local v_project = variables.project
+local v_environment = variables.environment
+local v_product = variables.product
+local v_component = variables.component
+local c_prefix = variables.prefix
+
+-- main code .. there is some overlap .. here we have loc://
+
+local function findctxfile(name) -- loc ? any ?
+ if file.is_qualified_path(name) then -- maybe when no suffix do some test for tex
+ return name
+ elseif not url.hasscheme(name) then
+ return resolvers.finders.byscheme("loc",name) or ""
+ else
+ return resolvers.findtexfile(name) or ""
+ end
+end
+
+resolvers.findctxfile = findctxfile
+
+function commands.processfile(name)
+ name = findctxfile(name)
+ if name ~= "" then
+ context.input(name)
+ end
+end
+
+function commands.doifinputfileelse(name)
+ commands.doifelse(findctxfile(name) ~= "")
+end
+
+function commands.locatefilepath(name)
+ context(file.dirname(findctxfile(name)))
+end
+
+function commands.usepath(paths)
+ resolvers.registerextrapath(paths)
+end
+
+function commands.usesubpath(subpaths)
+ resolvers.registerextrapath(nil,subpaths)
+end
+
+function commands.allinputpaths()
+ context(concat(resolvers.instance.extra_paths or { },","))
+end
+
+function commands.usezipfile(name,tree)
+ if tree and tree ~= "" then
+ resolvers.usezipfile(format("zip:///%s?tree=%s",name,tree))
+ else
+ resolvers.usezipfile(format("zip:///%s",name))
+ end
+end
+
+local report_system = logs.reporter("system","options")
+local report_options = logs.reporter("used options")
+
+function commands.copyfiletolog(name)
+ local f = io.open(name)
+ if f then
+ logspushtarget("logfile")
+ logsnewline()
+ report_system("start used options")
+ logsnewline()
+ for line in f:lines() do
+ report_options(line)
+ end
+ logsnewline()
+ report_system("stop used options")
+ logsnewline()
+ logspoptarget()
+ f:close()
+ end
+end
+
+-- moved from tex to lua:
+
+local texpatterns = { "%s.mkvi", "%s.mkiv", "%s.tex" }
+local luapatterns = { "%s.luc", "%s.lua" }
+local cldpatterns = { "%s.cld" }
+local xmlpatterns = { "%s.xml" }
+
+local uselibrary = commands.uselibrary
+local input = context.input
+
+-- status
+--
+-- these need to be synced with input stream:
+
+local processstack = { }
+local processedfile = ""
+local processedfiles = { }
+
+function commands.processedfile()
+ context(processedfile)
+end
+
+function commands.processedfiles()
+ context(concat(processedfiles,","))
+end
+
+function commands.dostarttextfile(name)
+ insert(processstack,name)
+ processedfile = name
+ insert(processedfiles,name)
+end
+
+function commands.dostoptextfile()
+ processedfile = remove(processstack) or ""
+end
+
+local function startprocessing(name,notext)
+ if not notext then
+ -- report_system("begin file %s at line %s",name,status.linenumber or 0)
+ context.dostarttextfile(name)
+ end
+end
+
+local function stopprocessing(notext)
+ if not notext then
+ context.dostoptextfile()
+ -- report_system("end file %s at line %s",name,status.linenumber or 0)
+ end
+end
+
+--
+
+local action = function(name,foundname) input(foundname) end
+local failure = function(name,foundname) end
+
+local function usetexfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = texpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+local action = function(name,foundname) dofile(foundname) end
+local failure = function(name,foundname) end
+
+local function useluafile(name,onlyonce,notext)
+ uselibrary {
+ name = name,
+ patterns = luapatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+end
+
+local action = function(name,foundname) dofile(foundname) end
+local failure = function(name,foundname) end
+
+local function usecldfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = cldpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+local action = function(name,foundname) context.xmlprocess(foundname,"main","") end
+local failure = function(name,foundname) end
+
+local function usexmlfile(name,onlyonce,notext)
+ startprocessing(name,notext)
+ uselibrary {
+ name = name,
+ patterns = xmlpatterns,
+ action = action,
+ failure = failure,
+ onlyonce = onlyonce,
+ }
+ stopprocessing(notext)
+end
+
+commands.usetexfile = usetexfile
+commands.useluafile = useluafile
+commands.usecldfile = usecldfile
+commands.usexmlfile = usexmlfile
+
+local suffixes = {
+ mkvi = usetexfile,
+ mkiv = usetexfile,
+ tex = usetexfile,
+ luc = useluafile,
+ lua = useluafile,
+ cld = usecldfile,
+ xml = usexmlfile,
+ [""] = usetexfile,
+}
+
+local function useanyfile(name,onlyonce)
+ local s = suffixes[file.suffix(name)]
+ if s then
+ s(file.removesuffix(name),onlyonce)
+ else
+ usetexfile(name,onlyonce) -- e.g. ctx file
+--~ resolvers.readfilename(name)
+ end
+end
+
+commands.useanyfile = useanyfile
+
+function resolvers.jobs.usefile(name,onlyonce,notext)
+ local s = suffixes[file.suffix(name)]
+ if s then
+ s(file.removesuffix(name),onlyonce,notext)
+ end
+end
+
+-- document structure
+
+local report_system = logs.reporter("system")
+
+local textlevel = 0 -- inaccessible for user, we need to define counter textlevel at the tex end
+
+local function dummyfunction() end
+
+local function startstoperror()
+ report_system("invalid \\%s%s ... \\%s%s structure",elements.start,v_text,elements.stop,v_text)
+ startstoperror = dummyfunction
+end
+
+local function starttext()
+ if textlevel == 0 then
+ if trace_jobfiles then
+ report_jobfiles("starting text")
+ end
+ -- registerfileinfo[begin]jobfilename
+ context.dostarttext()
+ end
+ textlevel = textlevel + 1
+ texsetcount("global","textlevel",textlevel)
+end
+
+local function stoptext()
+ if textlevel == 0 then
+ startstoperror()
+ elseif textlevel > 0 then
+ textlevel = textlevel - 1
+ end
+ texsetcount("global","textlevel",textlevel)
+ if textlevel <= 0 then
+ if trace_jobfiles then
+ report_jobfiles("stopping text")
+ end
+ context.dostoptext()
+ -- registerfileinfo[end]jobfilename
+ context.finalend()
+ commands.stoptext = dummyfunction
+ end
+end
+
+commands.starttext = starttext
+commands.stoptext = stoptext
+
+function commands.forcequitjob(reason)
+ if reason then
+ report_system("forcing quit: %s",reason)
+ else
+ report_system("forcing quit")
+ end
+ context.batchmode()
+ while textlevel >= 0 do
+ context.stoptext()
+ end
+end
+
+function commands.forceendjob()
+ report_system([[don't use \end to finish a document]])
+ context.stoptext()
+end
+
+function commands.autostarttext()
+ if textlevel == 0 then
+ report_system([[auto \starttext ... \stoptext]])
+ end
+ context.starttext()
+end
+
+commands.autostoptext = stoptext
+
+-- project structure
+
+function commands.processfilemany(name)
+ useanyfile(name,false)
+end
+
+function commands.processfileonce(name)
+ useanyfile(name,true)
+end
+
+function commands.processfilenone(name)
+ -- skip file
+end
+
+--
+
+local typestack = { }
+local pathstack = { }
+
+local currenttype = v_text
+local currentpath = "."
+
+local tree = { type = "text", name = "", branches = { } }
+local treestack = { }
+local top = tree.branches
+local root = tree
+
+local project_stack = { }
+local product_stack = { }
+local component_stack = { }
+local environment_stack = { }
+
+local stacks = {
+ [v_project ] = project_stack,
+ [v_product ] = product_stack,
+ [v_component ] = component_stack,
+ [v_environment] = environment_stack,
+}
+
+--
+
+local report_system = logs.reporter("system","structure")
+local report_structure = logs.reporter("used structure")
+
+local function pushtree(what,name)
+ local t = { }
+ top[#top+1] = { type = what, name = name, branches = t }
+ insert(treestack,top)
+ top = t
+end
+
+local function poptree()
+ top = remove(treestack)
+ -- inspect(top)
+end
+
+local function log_tree(top,depth)
+ report_structure("%s%s: %s",depth,top.type,top.name)
+ local branches = top.branches
+ if #branches > 0 then
+ depth = depth .. " "
+ for i=1,#branches do
+ log_tree(branches[i],depth)
+ end
+ end
+end
+
+local function logtree()
+ logspushtarget("logfile")
+ logsnewline()
+ report_system("start used structure")
+ logsnewline()
+ root.name = environment.jobname
+ log_tree(root,"")
+ logsnewline()
+ report_system("stop used structure")
+ logsnewline()
+ logspoptarget()
+end
+
+luatex.registerstopactions(logtree)
+
+job.structure = job.structure or { }
+job.structure.collected = job.structure.collected or { }
+job.structure.tobesaved = root
+job.structure.components = { }
+
+local function initialize()
+ local function collect(root,result)
+ local branches = root.branches
+ if branches then
+ for i=1,#branches do
+ local branch = branches[i]
+ if branch.type == "component" then
+ result[#result+1] = branch.name
+ end
+ collect(branch,result)
+ end
+ end
+ return result
+ end
+ job.structure.components = collect(job.structure.collected,{})
+end
+
+job.register('job.structure.collected',root,initialize)
+
+-- component: small unit, either or not components itself
+-- product : combination of components
+
+local processors = utilities.storage.allocate {
+ -- [v_outer] = {
+ -- [v_text] = { "many", context.processfilemany },
+ -- [v_project] = { "once", context.processfileonce },
+ -- [v_environment] = { "once", context.processfileonce },
+ -- [v_product] = { "many", context.processfileonce },
+ -- [v_component] = { "many", context.processfilemany },
+ -- },
+ [v_text] = {
+ [v_text] = { "many", context.processfilemany },
+ [v_project] = { "none", context.processfileonce }, -- none
+ [v_environment] = { "once", context.processfileonce }, -- once
+ [v_product] = { "none", context.processfileonce }, -- none
+ [v_component] = { "many", context.processfilemany }, -- many
+ },
+ [v_project] = {
+ [v_text] = { "many", context.processfilemany },
+ [v_project] = { "none", context.processfilenone }, -- none
+ [v_environment] = { "once", context.processfileonce }, -- once
+ [v_product] = { "once", context.processfilenone }, -- once
+ [v_component] = { "none", context.processfilenone }, -- many *
+ },
+ [v_environment] = {
+ [v_text] = { "many", context.processfilemany },
+ [v_project] = { "none", context.processfilenone }, -- none
+ [v_environment] = { "once", context.processfileonce }, -- once
+ [v_product] = { "none", context.processfilenone }, -- none
+ [v_component] = { "none", context.processfilenone }, -- none
+ },
+ [v_product] = {
+ [v_text] = { "many", context.processfilemany },
+ [v_project] = { "once", context.processfileonce }, -- once
+ [v_environment] = { "once", context.processfileonce }, -- once
+ [v_product] = { "none", context.processfilemany }, -- none
+ [v_component] = { "many", context.processfilemany }, -- many
+ },
+ [v_component] = {
+ [v_text] = { "many", context.processfilemany },
+ [v_project] = { "once", context.processfileonce }, -- once
+ [v_environment] = { "once", context.processfileonce }, -- once
+ [v_product] = { "none", context.processfilenone }, -- none
+ [v_component] = { "many", context.processfilemany }, -- many
+ }
+}
+
+local start = {
+ [v_text] = nil,
+ [v_project] = nil,
+ [v_environment] = context.startreadingfile,
+ [v_product] = context.starttext,
+ [v_component] = context.starttext,
+}
+
+local stop = {
+ [v_text] = nil,
+ [v_project] = nil,
+ [v_environment] = context.stopreadingfile,
+ [v_product] = context.stoptext,
+ [v_component] = context.stoptext,
+}
+
+resolvers.jobs.processors = processors
+
+local function topofstack(what)
+ local stack = stacks[what]
+ return stack and stack[#stack] or environment.jobname
+end
+
+local function productcomponent() -- only when in product
+ local product = product_stack[#product_stack]
+ if product and product ~= "" then
+ local component = component_stack[1]
+ if component and component ~= "" then
+ return component
+ end
+ end
+end
+
+local function justacomponent()
+ local product = product_stack[#product_stack]
+ if not product or product == "" then
+ local component = component_stack[1]
+ if component and component ~= "" then
+ return component
+ end
+ end
+end
+
+resolvers.jobs.productcomponent = productcomponent
+resolvers.jobs.justacomponent = justacomponent
+
+function resolvers.jobs.currentproject () return topofstack(v_project ) end
+function resolvers.jobs.currentproduct () return topofstack(v_product ) end
+function resolvers.jobs.currentcomponent () return topofstack(v_component ) end
+function resolvers.jobs.currentenvironment() return topofstack(v_environment) end
+
+local done = { }
+local tolerant = false -- too messy, mkii user with the wrong sructure should adapt
+
+local function process(what,name)
+ local depth = #typestack
+ local process
+-- if not tolerant then
+ -- okay, would be best but not compatible with mkii
+ process = processors[currenttype][what]
+-- elseif depth == 0 then
+-- -- could be a component, product or (brr) project
+-- if trace_jobfiles then
+-- report_jobfiles("%s : %s > %s (case 1)",depth,currenttype,v_outer)
+-- end
+-- process = processors[v_outer][what]
+-- elseif depth == 1 and typestack[1] == v_text then
+-- -- we're still not doing a component or product
+-- if trace_jobfiles then
+-- report_jobfiles("%s : %s > %s (case 2)",depth,currenttype,v_outer)
+-- end
+-- process = processors[v_outer][what]
+-- else
+-- process = processors[currenttype][what]
+-- end
+ if process then
+ local method = process[1]
+ if method == "none" then
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : ignoring %s '%s' in %s '%s'",depth,method,what,name,currenttype,topofstack(currenttype))
+ end
+ elseif method == "once" and done[name] then
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : skipping %s '%s' in %s '%s'",depth,method,what,name,currenttype,topofstack(currenttype))
+ end
+ else
+ -- keep in mind that we also handle "once" at the file level
+ -- so there is a double catch
+ done[name] = true
+ local before = start[what]
+ local after = stop [what]
+ if trace_jobfiles then
+ report_jobfiles("%s : %s : processing %s '%s' in %s '%s'",depth,method,what,name,currenttype,topofstack(currenttype))
+ end
+ if before then
+ before()
+ end
+ process[2](name)
+ if after then
+ after()
+ end
+ end
+ else
+ if trace_jobfiles then
+ report_jobfiles("%s : ? : ignoring %s '%s' in %s '%s'",depth,what,name,currenttype,topofstack(currenttype))
+ end
+ end
+end
+
+function commands.useproject (name) process(v_project, name) end
+function commands.useenvironment(name) process(v_environment,name) end
+function commands.useproduct (name) process(v_product, name) end
+function commands.usecomponent (name) process(v_component, name) end
+
+-- todo: setsystemmode to currenttype
+-- todo: make start/stop commands at the tex end
+
+local start = {
+ [v_project] = context.startprojectindeed,
+ [v_product] = context.startproductindeed,
+ [v_component] = context.startcomponentindeed,
+ [v_environment] = context.startenvironmentindeed,
+}
+
+local stop = {
+ [v_project] = context.stopprojectindeed,
+ [v_product] = context.stopproductindeed,
+ [v_component] = context.stopcomponentindeed,
+ [v_environment] = context.stopenvironmentindeed,
+}
+
+local function gotonextlevel(what,name) -- todo: something with suffix name
+ insert(stacks[what],name)
+ insert(typestack,currenttype)
+ insert(pathstack,currentpath)
+ currenttype = what
+ currentpath = file.dirname(name)
+ pushtree(what,name)
+ if start[what] then
+ start[what]()
+ end
+end
+
+local function gotopreviouslevel(what)
+ if stop[what] then
+ stop[what]()
+ end
+ poptree()
+ currentpath = remove(pathstack) or "."
+ currenttype = remove(typestack) or v_text
+ remove(stacks[what]) -- not currenttype ... weak recovery
+ -- context.endinput() -- does not work
+ context.signalendofinput(what)
+end
+
+function commands.startproject (name) gotonextlevel(v_project, name) end
+function commands.startproduct (name) gotonextlevel(v_product, name) end
+function commands.startcomponent (name) gotonextlevel(v_component, name) end
+function commands.startenvironment(name) gotonextlevel(v_environment,name) end
+
+function commands.stopproject () gotopreviouslevel(v_project ) end
+function commands.stopproduct () gotopreviouslevel(v_product ) end
+function commands.stopcomponent () gotopreviouslevel(v_component ) end
+function commands.stopenvironment() gotopreviouslevel(v_environment) end
+
+function commands.currentproject () context(topofstack(v_project )) end
+function commands.currentproduct () context(topofstack(v_product )) end
+function commands.currentcomponent () context(topofstack(v_component )) end
+function commands.currentenvironment() context(topofstack(v_environment)) end
+
+-- -- -- this will move -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+--
+-- <?xml version='1.0' standalone='yes'?>
+-- <exa:variables xmlns:exa='htpp://www.pragma-ade.com/schemas/exa-variables.rng'>
+-- <exa:variable label='mode:pragma'>nee</exa:variable>
+-- <exa:variable label='mode:variant'>standaard</exa:variable>
+-- </exa:variables>
+--
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+local report_examodes = logs.reporter("system","examodes")
+
+local function convertexamodes(str)
+ local x = xml.convert(str)
+ for e in xml.collected(x,"exa:variable") do
+ local label = e.at and e.at.label
+ if label and label ~= "" then
+ local data = xml.text(e)
+ local mode = match(label,"^mode:(.+)$")
+ if mode then
+ context.enablemode { format("%s:%s",mode,data) }
+ end
+ context.setvariable("exa:variables",label,(gsub(data,"([{}])","\\%1")))
+ end
+ end
+end
+
+function commands.loadexamodes(filename)
+ if not filename or filename == "" then
+ filename = file.removesuffix(tex.jobname)
+ end
+ filename = resolvers.findfile(file.addsuffix(filename,'ctm')) or ""
+ if filename ~= "" then
+ report_examodes("loading %s",filename) -- todo: message system
+ convertexamodes(io.loaddata(filename))
+ else
+ report_examodes("no mode file %s",filename) -- todo: message system
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/file-job.mkvi b/Master/texmf-dist/tex/context/base/file-job.mkvi
new file mode 100644
index 00000000000..83d9c78ba58
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-job.mkvi
@@ -0,0 +1,294 @@
+%D \module
+%D [ file=file-job, % copied from main-001, later core-job
+%D version=1997.03.31,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=Job 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 This module is still to be split and documented.
+
+\writestatus{loading}{ConTeXt File Macros / Job Handling}
+
+\unprotect
+
+\registerctxluafile{file-job}{1.001}
+
+% processing
+
+\unexpanded\def\doifinputfileelse#name%
+ {\ctxcommand{doifinputfileelse("#name")}}
+
+\unexpanded\def\processfile#name%
+ {\ctxcommand{processfile("#name")}}
+
+% path control
+
+\unexpanded\def\usepath[#path]%
+ {\ctxcommand{usepath("#path")}}
+
+\unexpanded\def\usesubpath[#path]%
+ {\ctxcommand{usesubpath("#path")}}
+
+\def\allinputpaths
+ {\ctxcommand{allinputpaths()}}
+
+% helper (not really needed nowadays)
+
+\let\locatedfilepath\empty
+
+\unexpanded\def\locatefilepath#name% no [] ?
+ {\edef\locatedfilepath{\ctxcommand{locatefilepath("#name")}}}
+
+% zip files are tree'd
+
+\unexpanded\def\usezipfile
+ {\dodoubleempty\syst_files_use_zip_file}
+
+\def\syst_files_use_zip_file[#zipname][#subtree]%
+ {\ctxcommand{usezipfile("#zipname","#subtree")}}
+
+% exa stuff might become obsolete:
+
+\unexpanded\def\loadexamodes
+ {\dosingleempty\syst_files_load_exa_modes}
+
+\def\syst_files_load_exa_modes[#name]%
+ {\ctxcommand{loadexamodes("#name")}}
+
+% runtime files (maybe also do this in lua?)
+
+% \def\doloadsystemfile#1% only mkiv files
+% {\readfile{sys:///#1.\mksuffix}{\showmessage\m!system2{#1.\mksuffix}}\donothing}
+
+\unexpanded\def\loadsystemfiles
+ {\syst_files_load\f!newfilename % new code, to be integrated at some point, plus fixes posted on the list
+ \syst_files_load\f!locfilename % new code, somewhat experimental, not distributed (outside the dev group)
+ \syst_files_load\f!expfilename % new code, very experimental, can be engine specific, mostly for me only
+ \syst_files_load\f!sysfilename} % local settings, but probably not that good an idea to use
+
+\def\syst_files_load#name% only mkiv files
+ {\readsysfile{#name.\mksuffix}{\showmessage\m!system2{#name.\mksuffix}}\donothing}
+
+\unexpanded\def\loadoptionfile
+ {\readjobfile{\jobname.\f!optionextension}
+ {\writestatus\m!system{\jobname.\f!optionextension\space loaded}%
+ \ctxcommand{copyfiletolog("\jobname.\f!optionextension")}}%
+ {\writestatus\m!system{no \jobname.\f!optionextension}}}
+
+% document structure
+
+\ifdefined\textlevel\else \newcount\textlevel \fi % might go away
+
+\unexpanded\def\dostarttext
+ {\glet\dostarttext\relax
+ \the\everystarttext
+ \global\everystarttext\emptytoks}
+
+\unexpanded\def\dostoptext
+ {\glet\dostoptext\relax
+ \flushfinallayoutpage % optional
+ \page % anyway
+ \the\everystoptext
+ \global\everystoptext\emptytoks
+ \the\everybye
+ \global\everybye\emptytoks
+ \the\everygoodbye
+ \global\everygoodbye\emptytoks
+ \doifsometokselse\everynotabene{\writeline\the\everynotabene\writeline}\donothing
+ \normalend} % tex's \end
+
+\unexpanded\def\starttext {\ctxcommand{starttext()}}
+\unexpanded\def\stoptext {\ctxcommand{stoptext()}}
+\unexpanded\def\forcequitjob {\ctxcommand{forcequitjob()}}
+\unexpanded\def\end {\ctxcommand{forceendjob()}}
+\unexpanded\def\autostarttext{\ctxcommand{autostarttext()}}
+\unexpanded\def\autostoptext {\ctxcommand{autostoptext()}}
+
+% protect structure
+
+\unexpanded\def\processfilemany#name{\ctxcommand{processfilemany("#name")}}
+\unexpanded\def\processfileonce#name{\ctxcommand{processfileonce("#name")}}
+\unexpanded\def\processfilenone#name{\ctxcommand{processfilenone("#name")}}
+
+\unexpanded\def\project {\doifnextoptionalelse\useproject \syst_structure_arg_project}
+\unexpanded\def\product {\doifnextoptionalelse\useproduct \syst_structure_arg_product}
+\unexpanded\def\component {\doifnextoptionalelse\usecomponent \syst_structure_arg_component}
+\unexpanded\def\environment{\doifnextoptionalelse\useenvironment\syst_structure_arg_environment}
+
+\def\syst_structure_arg_project #name {\ctxcommand{useproject ("#name")}}
+\def\syst_structure_arg_product #name {\ctxcommand{useproduct ("#name")}}
+\def\syst_structure_arg_component #name {\ctxcommand{usecomponent ("#name")}}
+\def\syst_structure_arg_environment#name {\ctxcommand{useenvironment("#name")}}
+
+\unexpanded\def\startproject {\doifnextoptionalelse\syst_structure_start_opt_project \syst_structure_start_arg_project }
+\unexpanded\def\startproduct {\doifnextoptionalelse\syst_structure_start_opt_product \syst_structure_start_arg_product }
+\unexpanded\def\startcomponent {\doifnextoptionalelse\syst_structure_start_opt_component \syst_structure_start_arg_component }
+\unexpanded\def\startenvironment{\doifnextoptionalelse\syst_structure_start_opt_environment\syst_structure_start_arg_environment}
+
+\def\syst_structure_start_arg_project #name {\ctxcommand{startproject ("#name")}}
+\def\syst_structure_start_arg_product #name {\ctxcommand{startproduct ("#name")}}
+\def\syst_structure_start_arg_component #name {\ctxcommand{startcomponent ("#name")}}
+\def\syst_structure_start_arg_environment#name {\ctxcommand{startenvironment("#name")}}
+
+\unexpanded\def\useproject [#name]{\ctxcommand{useproject ("#name")}}
+\unexpanded\def\useproduct [#name]{\ctxcommand{useproduct ("#name")}}
+\unexpanded\def\usecomponent [#name]{\ctxcommand{usecomponent ("#name")}}
+\unexpanded\def\useenvironment[#name]{\ctxcommand{useenvironment("#name")}}
+
+\unexpanded\def\syst_structure_start_opt_project [#name]{\ctxcommand{startproject ("#name")}}
+\unexpanded\def\syst_structure_start_opt_product [#name]{\ctxcommand{startproduct ("#name")}}
+\unexpanded\def\syst_structure_start_opt_component [#name]{\ctxcommand{startcomponent ("#name")}}
+\unexpanded\def\syst_structure_start_opt_environment[#name]{\ctxcommand{startenvironment("#name")}}
+
+\newconditional\endofinput % hack, needed because \endinput happens one level down in the input when we write from lua
+
+\unexpanded\def\signalendofinput#1% argument just for tracing
+ {\global\settrue\endofinput}
+
+\unexpanded\def\honorendofinput
+ {\ifconditional\endofinput
+ \global\setfalse\endofinput
+ \endinput
+ \fi}
+
+\unexpanded\def\stopproject {\ctxcommand{stopproject ()}\honorendofinput}
+\unexpanded\def\stopproduct {\ctxcommand{stopproduct ()}\honorendofinput}
+\unexpanded\def\stopcomponent {\ctxcommand{stopcomponent ()}\honorendofinput}
+\unexpanded\def\stopenvironment {\ctxcommand{stopenvironment()}\honorendofinput}
+
+\def\currentproject {\ctxcommand{currentproject ()}}
+\def\currentproduct {\ctxcommand{currentproduct ()}}
+\def\currentcomponent {\ctxcommand{currentcomponent ()}}
+\def\currentenvironment {\ctxcommand{currentenvironment()}}
+\def\processedfile {\ctxcommand{processedfile()}}
+\def\processedfiles {\ctxcommand{processedfiles()}}
+
+\unexpanded\def\dostarttextfile #name{\ctxcommand{dostarttextfile(name)}}
+\unexpanded\def\dostoptextfile {\ctxcommand{dostoptextfile()}}
+
+\unexpanded\def\loadtexfile [#name]{\ctxcommand{usetexfile("#name")}}
+\unexpanded\def\loadluafile [#name]{\ctxcommand{useluafile("#name")}}
+\unexpanded\def\loadcldfile [#name]{\ctxcommand{usecldfile("#name")}}
+\unexpanded\def\loadanyfile [#name]{\ctxcommand{useanyfile("#name")}}
+
+\unexpanded\def\loadtexfileonce [#name]{\ctxcommand{usetexfile("#name",true)}}
+\unexpanded\def\loadluafileonce [#name]{\ctxcommand{useluafile("#name",true)}}
+\unexpanded\def\loadcldfileonce [#name]{\ctxcommand{usecldfile("#name",true)}}
+\unexpanded\def\loadanyfileonce [#name]{\ctxcommand{useanyfile("#name",true)}}
+
+%D Handy for modules that have a test/demo appended.
+
+\def\continueifinputfile#name{\doifnot\inputfilename{#name}\endinput}
+%def\processifinputfile #name{\doif \inputfilename{#name}}
+
+% \startproject test
+% 1: \startmode[*project] project \stopmode \endgraf
+% 2: \startmode[*product] product \stopmode \endgraf
+% \stopproject
+
+% replaced by modes:
+%
+% \setvalue{\e!start\v!localenvironment}[#1]%
+% {\let\loadedlocalenvironments\empty
+% \def\docommand##1%
+% {\beforesplitstring##1\at.\to\someevironment
+% \addtocommalist\someevironment\loadedlocalenvironments}%
+% \processcommalist[#1]\docommand
+% \doifcommonelse{\currentproject,\currentproduct,\currentcomponent,\currentenvironment}\loadedlocalenvironments
+% {\letvalue{\e!stop\v!localenvironment}\relax}
+% {\grabuntil{\e!stop\v!localenvironment}\gobbleoneargument}}
+%
+% \setvalue{\v!localenvironment}{\doifnextoptionalelse\uselocalenvironment\redolocalenvironment}
+%
+% \def\redolocalenvironment#1 {\uselocalenvironment[#1]}
+% \def\uselocalenvironment[#1]{\doexecutefileonce{#1}}
+
+% weird place:
+
+\neverypar\emptytoks
+
+%D Wrappers (the signal is a synchronization with lua hack):
+
+\newsystemmode\v!project
+\newsystemmode\v!product
+\newsystemmode\v!component
+\newsystemmode\v!environment
+
+\unexpanded\def\startprojectindeed
+ {\starttext
+ \pushsystemmode\v!project
+ \setsystemmode\v!project}
+
+\unexpanded\def\stopprojectindeed
+ {\popsystemmode\v!project
+ \stoptext
+ \signalendofinput\v!project}
+
+\unexpanded\def\startproductindeed
+ {\starttext
+ \pushsystemmode\v!product
+ \setsystemmode\v!product}
+
+\unexpanded\def\stopproductindeed
+ {\popsystemmode\v!product
+ \stoptext
+ \signalendofinput\v!product}
+
+\unexpanded\def\startcomponentindeed
+ {\starttext
+ \pushreferenceprefix\currentcomponent
+ \pushsystemmode\v!component
+ \setsystemmode\v!component}
+
+\unexpanded\def\stopcomponentindeed
+ {\popsystemmode\v!component
+ \popreferenceprefix
+ \stoptext
+ \signalendofinput\v!component}
+
+\unexpanded\def\startenvironmentindeed
+ {\pushsystemmode\v!environment
+ \setsystemmode\v!environment}
+
+\unexpanded\def\stopenvironmentindeed
+ {\popsystemmode\v!environment
+ \signalendofinput\v!environment}
+
+%D Relatively new (might move as it depends on setups):
+
+\newtoks\everysetupdocument
+
+\unexpanded\def\startdocument % todo: dostarttagged\t!document
+ {\dosingleargument\syst_structure_document_start}
+
+\unexpanded\def\syst_structure_document_start[#settings]%
+ {\setvariables[\s!document][#settings]%
+ \the\everysetupdocument\relax
+ \starttext
+ \documentvariable\c!before}
+
+\unexpanded\def\stopdocument % todo: dostoptagged\t!document
+ {\documentvariable\c!after
+ \stoptext}
+
+\def\documentvariable#name%
+ {\getvariable\s!document{#name}}
+
+\unexpanded\def\setupdocument[#settings]%
+ {\setvariables[\s!document][#settings]%
+ \the\everysetupdocument\relax}
+
+\setvariables
+ [document]
+ [\c!before=\directsetup{\s!document:start},
+ \c!after=\directsetup{\s!document:stop}]
+
+%S The document: namespace will be used elsewhere too.
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/file-lib.lua b/Master/texmf-dist/tex/context/base/file-lib.lua
new file mode 100644
index 00000000000..92dacbf5cc6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-lib.lua
@@ -0,0 +1,64 @@
+if not modules then modules = { } end modules ['file-lib'] = {
+ version = 1.001,
+ comment = "companion to file-lib.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: check all usage of truefilename at the tex end and remove
+-- files there (and replace definitions by full names)
+
+local format = string.format
+
+local trace_files = false trackers.register("resolvers.readfile", function(v) trace_files = v end)
+local report_files = logs.reporter("files","readfile")
+
+local loaded = { }
+local defaultpatterns = { "%s" }
+
+local function defaultaction(name,foundname)
+ report_files("asked name: '%s', found name: '%s'",name,foundname)
+end
+
+local function defaultfailure(name)
+ report_files("asked name: '%s', not found",name)
+end
+
+function commands.uselibrary(specification) -- todo; reporter
+ local name = specification.name
+ if name and name ~= "" then
+ local patterns = specification.patterns or defaultpatterns
+ local action = specification.action or defaultaction
+ local failure = specification.failure or defaultfailure
+ local onlyonce = specification.onlyonce
+ local files = utilities.parsers.settings_to_array(name)
+ local done = false
+ for i=1,#files do
+ local filename = files[i]
+ if not loaded[filename] then
+ if onlyonce then
+ loaded[filename] = true -- todo: base this on return value
+ end
+ for i=1,#patterns do
+ local somename = format(patterns[i],filename)
+if environment.truefilename then
+ somename = environment.truefilename(somename)
+end
+ local foundname = resolvers.getreadfilename("any",".",somename) or ""
+ if foundname ~= "" then
+ action(name,foundname)
+ done = true
+ break
+ end
+ end
+ if done then
+ break
+ end
+ end
+ end
+ if failure and not done then
+ failure(name)
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/file-lib.mkvi b/Master/texmf-dist/tex/context/base/file-lib.mkvi
new file mode 100644
index 00000000000..76137ce15b9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-lib.mkvi
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=file-lib, % 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 / Libraries}
+
+\unprotect
+
+\registerctxluafile{file-lib}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/file-mod.lua b/Master/texmf-dist/tex/context/base/file-mod.lua
new file mode 100644
index 00000000000..e6592f0f062
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-mod.lua
@@ -0,0 +1,170 @@
+if not modules then modules = { } end modules ['file-mod'] = {
+ version = 1.001,
+ comment = "companion to file-mod.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This module will be redone! For instance, the prefixes will move to data-*
+-- as they arr sort of generic along with home:// etc/.
+
+-- context is not defined yet! todo! (we need to load tupp-fil after cld)
+-- todo: move startreadingfile to lua and push regime there
+
+--[[ldx--
+<p>It's more convenient to manipulate filenames (paths) in
+<l n='lua'/> than in <l n='tex'/>. These methods have counterparts
+at the <l n='tex'/> side.</p>
+--ldx]]--
+
+local format, concat, tonumber = string.format, table.concat, tonumber
+
+local trace_modules = false trackers.register("modules.loading", function(v) trace_modules = v end)
+
+local report_modules = logs.reporter("resolvers","modules")
+
+commands = commands or { }
+local commands = commands
+
+local findbyscheme = resolvers.finders.byscheme -- use different one
+
+-- modules can have a specific suffix or can specify one
+
+local prefixes = { "m", "p", "s", "x", "v", "t" }
+local suffixes = { "mkvi", "mkiv", "tex", "cld", "lua" } -- order might change and how about cld
+local modstatus = { }
+
+local function usemodule(name,hasscheme)
+ local foundname
+ if hasscheme then
+ -- no auto suffix as http will return a home page or error page
+ -- so we only add one if missing
+ local fullname = file.addsuffix(name,"tex")
+ if trace_modules then
+ report_modules("checking url: '%s'",fullname)
+ end
+ foundname = resolvers.findtexfile(fullname) or ""
+ elseif file.extname(name) ~= "" then
+ if trace_modules then
+ report_modules("checking file: '%s'",name)
+ end
+ foundname = findbyscheme("any",name) or ""
+ else
+ for i=1,#suffixes do
+ local fullname = file.addsuffix(name,suffixes[i])
+ if trace_modules then
+ report_modules("checking file: '%s'",fullname)
+ end
+ foundname = findbyscheme("any",fullname) or ""
+ if foundname ~= "" then
+ break
+ end
+ end
+ end
+ if foundname ~= "" then
+ if trace_modules then
+ report_modules("loading: '%s'",foundname)
+ end
+ context.startreadingfile()
+ resolvers.jobs.usefile(foundname,true) -- once, notext
+ -- context.input(foundname)
+ context.stopreadingfile()
+ return true
+ else
+ return false
+ end
+end
+
+function commands.usemodules(prefix,askedname,truename)
+ local truename = truename or environment.truefilename(askedname)
+ local hasprefix = prefix and prefix ~= ""
+ local hashname = ((hasprefix and prefix) or "*") .. "-" .. truename
+ local status = modstatus[hashname]
+ if status == 0 then
+ -- not found
+ elseif status == 1 then
+ status = status + 1
+ else
+ if trace_modules then
+ report_modules("locating: prefix: '%s', askedname: '%s', truename: '%s'",prefix or "", askedname or "", truename or "")
+ end
+ local hasscheme = url.hasscheme(truename)
+ if hasscheme then
+ -- no prefix and suffix done
+ if usemodule(truename,true) then
+ status = 1
+ else
+ status = 0
+ end
+ elseif hasprefix then
+ if usemodule(prefix .. "-" .. truename) then
+ status = 1
+ else
+ status = 0
+ end
+ else
+ for i=1,#prefixes do
+ -- todo: reconstruct name i.e. basename
+ local thename = prefixes[i] .. "-" .. truename
+ if usemodule(thename) then
+ status = 1
+ break
+ end
+ end
+ if status then
+ -- ok, don't change
+ elseif usemodule(truename) then
+ status = 1
+ else
+ status = 0
+ end
+ end
+ end
+ if status == 0 then
+ report_modules("not found: '%s'",askedname)
+ elseif status == 1 then
+ report_modules("loaded: '%s'",trace_modules and truename or askedname)
+ else
+ report_modules("already loaded: '%s'",trace_modules and truename or askedname)
+ end
+ modstatus[hashname] = status
+end
+
+statistics.register("loaded tex modules", function()
+ if next(modstatus) then
+ local t, f, nt, nf = { }, { }, 0, 0
+ for k, v in table.sortedhash(modstatus) do
+ k = file.basename(k)
+ if v == 0 then
+ nf = nf + 1
+ f[nf] = k
+ else
+ nt = nt + 1
+ t[nt] = k
+ end
+ end
+ local ts = (nt>0 and format(" (%s)",concat(t," "))) or ""
+ local fs = (nf>0 and format(" (%s)",concat(f," "))) or ""
+ return format("%s requested, %s found%s, %s missing%s",nt+nf,nt,ts,nf,fs)
+ else
+ return nil
+ end
+end)
+
+-- moved from syst-lua.lua:
+
+local splitter = lpeg.tsplitter(lpeg.S(". "),tonumber)
+
+function commands.doifolderversionelse(one,two) -- one >= two
+ if not two then
+ one, two = environment.version, one
+ elseif one == "" then
+ one = environment.version
+ end
+ one = lpeg.match(splitter,one)
+ two = lpeg.match(splitter,two)
+ one = (one[1] or 0) * 10000 + (one[2] or 0) * 100 + (one[3] or 0)
+ two = (two[1] or 0) * 10000 + (two[2] or 0) * 100 + (two[3] or 0)
+ commands.testcase(one>=two)
+end
diff --git a/Master/texmf-dist/tex/context/base/file-mod.mkvi b/Master/texmf-dist/tex/context/base/file-mod.mkvi
new file mode 100644
index 00000000000..33d1004029c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-mod.mkvi
@@ -0,0 +1,250 @@
+%D \module
+%D [ file=file-mod, % 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 / Modules}
+
+\unprotect
+
+\registerctxluafile{file-mod}{1.001}
+
+%D \macros
+%D {usemodule}
+%D
+%D Most of \CONTEXT is preloaded in the format file. Some very
+%D domain specific typesetting topics are however dealt with in
+%D separate modules, e.g. typesetting of chemical structure
+%D formulas. These modules are loaded by:
+%D
+%D \showsetup{usemodule}
+%D
+%D More information on the specific modules can be found in
+%D their dedicated manuals. We use \type {\next} so that we
+%D can \type {\end} in modules.
+
+\def\usemodules
+ {\dotripleempty\strc_modules_use}
+
+\let\usemodule\usemodules
+
+% \def\strc_modules_use[#category][#name][#parameters]%
+% {\pushmacro\currentmodule
+% \pushmacro\currentmoduleparameters
+% \let\currentmoduleparameters\empty
+% \ifthirdargument
+% \singleexpandafter\strc_modules_use_a
+% \else\ifsecondargument
+% \doubleexpandafter\strc_modules_use_b
+% \else
+% \doubleexpandafter\strc_modules_use_c
+% \fi\fi
+% % here we load
+% \popmacro\currentmoduleparameters
+% \popmacro\currentmodule}
+%
+% \def\strc_modules_use_a[#category][#name][#parameters]%
+% {\doifsomething{#name}
+% {\def\currentmoduleparameters{#parameters}%
+% \processcommalist[#name]{\strc_modules_use_indeed{#category}}}}
+%
+% \def\strc_modules_use_b[#category][#name][#parameters]%
+% {\doifsomething{#name}
+% {\doifassignmentelse{#name}
+% {\def\currentmoduleparameters{#name}%
+% \processcommalist[#category]{\strc_modules_use_indeed\empty}}
+% {\processcommalist[#name]{\strc_modules_use_indeed{#category}}}}}
+%
+% \def\strc_modules_use_c[#category][#name][#parameters]%
+% {\processcommalist[#category]{\strc_modules_use_indeed\empty}}
+%
+% \def\strc_modules_use_indeed#category#name%
+% {\ctxcommand{usemodules("#category","#name","\truefilename{#name}")}}
+
+\def\strc_modules_use[#category][#name][#parameters]% category=t|m|x|p|...
+ {\pushmacro\currentmodule
+ \pushmacro\currentmodulecategory
+ \pushmacro\currentmoduleparameters
+ \ifthirdargument
+ \edef\currentmodulecategory {#category}%
+ \edef\currentmodule {#name}%
+ \def \currentmoduleparameters{#parameters}%
+ \else\ifsecondargument
+ \doifassignmentelse{#name}
+ {\let\currentmodulecategory \empty
+ \edef\currentmodule {#category}%
+ \edef\currentmoduleparameters{#name}}
+ {\edef\currentmodulecategory {#category}%
+ \edef\currentmodule {#name}%
+ \let \currentmoduleparameters\empty}%
+ \else
+ \let \currentmodulecategory \empty
+ \edef\currentmodule {#category}%
+ \let \currentmoduleparameters\empty
+ \fi\fi
+ \processcommacommand[\currentmodule]{\strc_modules_use_indeed\currentmodulecategory}%
+ \popmacro\currentmoduleparameters
+ \popmacro\currentmodulecategory
+ \popmacro\currentmodule}
+
+\def\strc_modules_use_indeed#category#name% truefilename moved to lua end
+ {\ctxcommand{usemodules("#category","#name")}} % ,"\truefilename{#name}")}}
+
+\installcorenamespace{module}
+
+\let\currentmoduleparameters\empty
+\let\currentmodule \s!unknown
+
+\unexpanded\def\startmodule
+ {\doifnextoptionalelse\syst_modules_start_yes\syst_modules_start_nop}
+
+\def\syst_modules_start_yes[#name]%
+ {\pushmacro\currentmodule
+ \pushmacro\currentmoduleparameters
+ \def\currentmodule{#name}}
+
+\def\syst_modules_start_nop#name %
+ {\syst_modules_start_yes[#name]}
+
+\unexpanded\def\stopmodule
+ {\popmacro\currentmoduleparameters
+ \popmacro\currentmodule}
+
+\unexpanded\def\setupmodule
+ {\dodoubleempty\syst_modules_setup}
+
+\def\syst_modules_setup[#name][#parameters]%
+ {\scratchtoks\expandafter{\currentmoduleparameters}%
+ \ifsecondargument
+ \getparameters[\??module#name:][#parameters]% internal (defaults)
+ \normalexpanded{\getparameters[\??module#name:][\the\scratchtoks]}% loadtime (user)
+ \else
+ \getparameters[\??module\currentmodule:][#name]% internal (defaults)
+ \normalexpanded{\getparameters[\??module\currentmodule:][\the\scratchtoks]}% loadtime (user)
+ \fi
+ \let\currentmoduleparameters\empty}
+
+% to be tested:
+%
+% \def\syst_modules_setup[#name][#parameters]%
+% {\ifsecondargument
+% \getparameters[\??module#name:][#parameters]% internal (defaults)
+% \normalexpanded{\getparameters[\??module#name:][\normalunexpanded\expandafter{\currentmoduleparameters}]}% loadtime (user)
+% \else
+% \getparameters[\??module\currentmodule:][#name]% internal (defaults)
+% \normalexpanded{\getparameters[\??module\currentmodule:][\normalunexpanded\expandafter{\currentmoduleparameters}]}% loadtime (user)
+% \fi
+% \let\currentmoduleparameters\empty}
+
+\def\moduleparameter#name#parameter%
+ {\csname\??module
+ \ifcsname\??module#name:#parameter\endcsname#name:#parameter\fi
+ \endcsname}
+
+\letvalue\??module\empty % so we default to empty as with all parameters
+
+\def\currentmoduleparameter{\moduleparameter\currentmodule} % no need for inlining
+
+\unexpanded\def\useluamodule [#name]{\ctxlua{dofile(resolvers.findctxfile("#name"))}}
+\unexpanded\def\luaenvironment #name {\ctxlua{dofile(resolvers.findctxfile("#name"))}}
+
+% \usemodule[newmml]
+% \usemodule[newmml][a=b]
+% \usemodule[x][newmml]
+% \usemodule[x][newmml][a=b]
+%
+% \startmodule [mathml]
+% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars will be set afterwards
+% \setupmodule[a=c] \relax [\currentmoduleparameter{a}] % user vars are now forgotten
+% \stopmodule
+
+% one can introduce test sections with:
+%
+% \enablemode[newmml:test:\currentmoduleparameter{test}]
+% \startmode[newmml:test:yes} ... \stopmode
+%
+% these will be ignored unless test=yes
+%
+% however, a better way is:
+
+\unexpanded\def\startmoduletestsection
+ {\begingroup
+ \setupmodule % we need to make sure that the vars are set
+ \doifelse{\currentmoduleparameter\v!test}\v!yes
+ {\endgroup
+ \writestatus\currentmodule{loading experimental code}}
+ {\endgroup
+ \writestatus\currentmodule{skipping experimental code}%
+ \gobbleuntil\stopmoduletestsection}}
+
+\let\stopmoduletestsection\donothing
+
+% will become file-run
+
+%D To save memory, we implement some seldomly used commands in a lazy way. Nota
+%D bene: such runtime definitions are to be defined global.
+%D
+%D \starttyping
+%D \fetchruntimecommand\showaccents{\f!colorprefix ...}
+%D \stoptyping
+
+\installcorenamespace{runtimeloaded}
+
+\unexpanded\def\fetchruntimecommand#1#2%
+ {\unexpanded\def#1{\dofetchruntimecommand#1{#2}}}
+
+\def\dofetchruntimecommand#1#2% actually a test on #1 being define would be ok as well
+ {\ifcsname\??runtimeloaded#2\endcsname
+ % already loaded
+ \else
+ \global\let#1\undefined
+ \startreadingfile
+ \startnointerference % \bgroup
+ \cleanupfeatures % better \setnormalcatcodes / test first
+ \readfile{#2.\mksuffix}\donothing\donothing
+ \stopnointerference % \egroup
+ \stopreadingfile
+ \letgvalue{\??runtimeloaded#2}\empty
+ \fi
+ \ifx#1\undefined
+ \writestatus\m!system{command \string#1 not found in file #2}%
+ \unexpanded\gdef#1{{\infofont[unknown command \string#1]}}%
+ \fi
+ #1}
+
+%D \macros
+%D {doifolderversionelse}
+%D
+%D We start with a macro specially for Aditya who wants to be able
+%D to use development versions of \MKIV\ for real documents.
+%D
+%D \starttyping
+%D \doifolderversionelse\contextversion{1010.10.10} {OLDER} {OKAY} => OLDER
+%D \doifolderversionelse\contextversion{2020.20.20} {OLDER} {OKAY} => OKAY
+%D \doifolderversionelse\contextversion{2020} {OLDER} {OKAY} => OKAY
+%D \stoptyping
+%D
+%D The version pattern is \type {yyyy.mm.dd} (with mm and dd being optional).
+
+\unexpanded\def\doifolderversionelse#parent#child{\ctxcommand{doifolderversionelse("#parent","#child")}}
+\unexpanded\def\doifoldercontextelse #child{\ctxcommand{doifolderversionelse("#child")}}
+
+% obsolete
+%
+% \def\documentresources{\@@erurl}
+%
+% \unexpanded\def\setupexternalresources
+% {\dodoubleargument\getparameters[\??er]}
+%
+% \setupexternalresources
+% [url=]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/file-res.lua b/Master/texmf-dist/tex/context/base/file-res.lua
new file mode 100644
index 00000000000..24b0f1cfca5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-res.lua
@@ -0,0 +1,110 @@
+if not modules then modules = { } end modules ['supp-fil'] = {
+ version = 1.001,
+ comment = "companion to supp-fil.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+local isfile = lfs.isfile
+
+local trace_files = false trackers.register("resolvers.readfile", function(v) trace_files = v end)
+local report_files = logs.reporter("files","readfile")
+
+resolvers.maxreadlevel = 2
+
+directives.register("resolvers.maxreadlevel", function(v) resolvers.maxreadlevel = tonumber(v) or resolvers.maxreadlevel end)
+
+local finders, loaders, openers = resolvers.finders, resolvers.loaders, resolvers.openers
+
+local found = { } -- can best be done in the resolver itself
+
+local function readfilename(specification,backtrack,treetoo)
+ local name = specification.filename
+ local fnd = name and found[name]
+ if not fnd then
+ if isfile(name) then
+ if trace_files then
+ report_files("found local: %s",name)
+ end
+ fnd = name
+ end
+ if not fnd and backtrack then
+ local fname = name
+ for i=1,backtrack,1 do
+ fname = "../" .. fname
+ if isfile(fname) then
+ if trace_files then
+ report_files("found by backtracking: %s",fname)
+ end
+ fnd = fname
+ break
+ elseif trace_files then
+ report_files("not found by backtracking: %s",fname)
+ end
+ end
+ end
+ if not fnd and treetoo then
+ fnd = resolvers.findtexfile(name) or ""
+ if trace_files then
+ if fnd ~= "" then
+ report_files("found by tree lookup: %s",fnd)
+ else
+ report_files("not found by tree lookup: %s",name)
+ end
+ end
+ end
+ found[name] = fnd
+ elseif trace_files then
+ if fnd ~= "" then
+ report_files("already found: %s",fnd)
+ else
+ report_files("already not found: %s",name)
+ end
+ end
+ return fnd or ""
+end
+
+--~ resolvers.readfilename = readfilename -- bonus use getreadfilename instead
+
+function finders.job(specification) return readfilename(specification,false, false) end -- current path, no backtracking
+function finders.loc(specification) return readfilename(specification,resolvers.maxreadlevel,false) end -- current path, backtracking
+function finders.sys(specification) return readfilename(specification,false, true ) end -- current path, obeys tex search
+function finders.fix(specification) return readfilename(specification,resolvers.maxreadlevel,false) end -- specified path, backtracking
+function finders.set(specification) return readfilename(specification,false, false) end -- specified path, no backtracking
+function finders.any(specification) return readfilename(specification,resolvers.maxreadlevel,true ) end -- loc job sys
+
+openers.job = openers.file loaders.job = loaders.file -- default anyway
+openers.loc = openers.file loaders.loc = loaders.file
+openers.sys = openers.file loaders.sys = loaders.file
+openers.fix = openers.file loaders.fix = loaders.file
+openers.set = openers.file loaders.set = loaders.file
+openers.any = openers.file loaders.any = loaders.file
+
+function getreadfilename(scheme,path,name) -- better do a split and then pass table
+ local fullname
+ if url.hasscheme(name) then
+ fullname = name
+ else
+ fullname = ((path == "") and format("%s:///%s",scheme,name)) or format("%s:///%s/%s",scheme,path,name)
+ end
+--~ print(">>>",fullname)
+ return resolvers.findtexfile(fullname) or "" -- can be more direct
+end
+
+resolvers.getreadfilename = getreadfilename
+
+function commands.getreadfilename(scheme,path,name)
+ context(getreadfilename(scheme,path,name))
+end
+
+-- a name belonging to the run but also honoring qualified
+
+function commands.locfilename(name)
+ context(getreadfilename("loc",".",name))
+end
+
+function commands.doiflocfileelse(name)
+ commands.doifelse(isfile(getreadfilename("loc",".",name)))
+end
diff --git a/Master/texmf-dist/tex/context/base/file-res.mkvi b/Master/texmf-dist/tex/context/base/file-res.mkvi
new file mode 100644
index 00000000000..5162e63bee3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-res.mkvi
@@ -0,0 +1,151 @@
+%D \module
+%D [ file=file-mod, % was supp-fil,
+%D version=20110701, % 1995.10.10,
+%D title=\CONTEXT\ File Macros,
+%D subtitle=Resolvers,
+%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 / Resolvers}
+
+\unprotect
+
+\registerctxluafile{file-res}{1.001}
+
+%D \macros
+%D {readfile,ReadFile}
+%D
+%D One cannot be sure if a file exists. When no file can be
+%D found, the \type{\input} primitive gives an error message
+%D and switches to interactive mode. The macro \type{\readfile}
+%D takes care of non||existing files. This macro has two faces.
+%D
+%D \starttyping
+%D \ReadFile {filename}
+%D \readfile {filename} {before loading} {not found}
+%D \stoptyping
+%D
+%D Many \TEX\ implementations have laid out some strategy for
+%D locating files. This can lead to unexpected results,
+%D especially when one loads files that are not found in the
+%D current directory. Let's give an example of this. In
+%D \CONTEXT\ illustrations can be defined in an external file.
+%D The resizing macro first looks if an illustration is defined
+%D in the local definitions file. When no such file is found,
+%D it searches for a global file and when this file is not
+%D found either, the illustration itself is scanned for
+%D dimensions. One can imagine what happens if an adapted,
+%D localy stored illustration, is scaled according to
+%D dimensions stored somewhere else.
+%D
+%D When some \TEX\ implementation starts looking for a file, it
+%D normally first looks in the current directory. When no file
+%D is found, \TEX\ starts searching on the path where format
+%D and|/|or style files are stored. Depending on the implementation
+%D this can considerably slow down processing speed.
+%D
+%D In \CONTEXT, we support a project||wise ordening of files.
+%D In such an approach it seems feasible to store common files
+%D in a lower directory. When for instance searching for a
+%D general layout file, we therefore have to backtrack.
+%D
+%D These three considerations have lead to a more advanced
+%D approach for loading files.
+%D
+%D We first present an earlier implementation of
+%D \type{\readfile}. This command backtracks parent
+%D directories, upto a predefined level. Users can change this
+%D level (on the commandline using a directive); we default to~3.
+%D
+%D We use \type{\normalinput} instead of \type{\input}
+%D because we want to be able to redefine the original
+%D \type{\input} when needed, for instance when loading third
+%D party libraries.
+
+\let\readfilename\empty
+
+\def\syst_files_read_file#protocol#path#name% #true #false
+ {\edef\readfilename{\ctxcommand{getreadfilename("#protocol","#path","#name")}}%
+ \ifx\readfilename\empty
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\syst_files_read_file_indeed
+ \fi}
+
+\def\syst_files_read_file_indeed#true#false%
+ {#true%
+ \relax
+ \normalinput{\readfilename}%
+ \relax}
+
+%D \macros
+%D {readjobfile,readlocfile,readsysfile,
+%D readfixfile,readsetfile}
+%D
+%D This implementation honnors the third situation, but we
+%D still can get unwanted files loaded and/or can get involved
+%D in extensive searching.
+%D
+%D Due to different needs, we decided to offer four alternative
+%D loading commands. With \type{\readjobfile} we load a local
+%D file and do no backtracking, while \type{\readlocfile}
+%D backtracks~\number\maxreadlevel\ directories, including the current
+%D one.
+%D
+%D System files can be anywhere and therefore
+%D \type{\readsysfile} is not bound to the current directory
+%D and obeys the \TEX\ implementation.
+%D
+%D Of the last two, \type{\readfixfile} searches on the
+%D directory specified and backtracks too, while
+%D \type{\readsetfile} does only search on the specified path.
+%D
+%D The most liberal is \type {\readfile}.
+
+\unexpanded\def\readjobfile #name{\syst_files_read_file{job} {.}{#name}} % current path, no backtracking
+\unexpanded\def\readlocfile #name{\syst_files_read_file{loc} {.}{#name}} % current path, backtracking
+\unexpanded\def\readsysfile #name{\syst_files_read_file{sys} {.}{#name}} % current path, obeys tex search
+\unexpanded\def\readfixfile#path#name{\syst_files_read_file{fix}{#path}{#name}} % specified path, backtracking
+\unexpanded\def\readsetfile#path#name{\syst_files_read_file{set}{#path}{#name}} % specified path, no backtracking
+\unexpanded\def\readfile #name{\syst_files_read_file{any} {.}{#name}}
+\unexpanded\def\ReadFile #name{\syst_files_read_file{any} {.}{#name}\donothing\donothing}
+
+%D So now we've got ourselves five file loading commands:
+%D
+%D \starttyping
+%D \readfile {filename} {before loading} {not found}
+%D
+%D \readjobfile {filename} {before loading} {not found}
+%D \readlocfile {filename} {before loading} {not found}
+%D \readfixfile {filename} {before loading} {not found}
+%D \readsysfile {directory} {filename} {before loading} {not found}
+%D \stoptyping
+
+\unexpanded\def\readtexfile#name#true#false%
+ {\pushcatcodetable
+ \catcodetable\ctxcatcodes
+ \readfile{#name}{#true}{#false}%
+ \popcatcodetable}
+
+\unexpanded\def\readxmlfile#name#true#false%
+ {\pushcatcodetable
+ \catcodetable\xmlcatcodes
+ \readfile{#name}{#true}{#false}%
+ \popcatcodetable}
+
+%D \macros
+%D {doiflocfileelse,locfilename}
+%D
+%D \starttyping
+%D \doiflocfileelse {filename} {before loading} {not found}
+%D \stoptyping
+
+\unexpanded\def\doiflocfileelse#name{\ctxcommand{doiflocfileelse([[#name]])}}
+ \def\locfilename #name{\ctxcommand{locfilename([[#name]])}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/file-syn.lua b/Master/texmf-dist/tex/context/base/file-syn.lua
new file mode 100644
index 00000000000..1be9fb4b12f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-syn.lua
@@ -0,0 +1,48 @@
+if not modules then modules = { } end modules ['file-syn'] = {
+ version = 1.001,
+ comment = "companion to file-syn.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local report_files = logs.reporter("files")
+
+environment.filesynonyms = environment.filesynonyms or { }
+local filesynonyms = environment.filesynonyms
+
+storage.register("environment/filesynonyms", filesynonyms, "environment.filesynonyms")
+
+local function truefilename(name)
+ local realname = filesynonyms[name] or name
+ if realname ~= name then
+ return truefilename(realname)
+ else
+ return realname
+ end
+end
+
+environment.truefilename = truefilename
+
+function commands.truefilename(name)
+ context(truefilename(name))
+end
+
+function commands.definefilesynonym(name,realname)
+ local synonym = filesynonyms[name]
+ if synonym then
+ interfaces.showmessage("files",1,{ name or "?", realname or "?", synonym or "?" })
+ end
+ filesynonyms[name] = realname
+end
+
+function commands.definefilefallback(name,alternatives)
+ local names = utilities.parser.settings_to_array(alternatives)
+ for i=1,#names do
+ local realname = resolvers.findfile(names[i])
+ if realname ~= "" then
+ filesynonyms[name] = realname
+ break
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/file-syn.mkvi b/Master/texmf-dist/tex/context/base/file-syn.mkvi
new file mode 100644
index 00000000000..b61bd8ae4d8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/file-syn.mkvi
@@ -0,0 +1,66 @@
+%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}{1.001}
+
+%D \macros
+%D {definefilesynonym,definefilefallback}
+%D
+%D One of the problems with loading files is that their names
+%D can depend on the interface language. We therefore need a
+%D method to define filesynonyms. The actual synonyms are
+%D 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
+
+\unexpanded\def\definefilesynonym {\dodoubleempty \syst_files_define_synonym }
+\unexpanded\def\definefilefallback{\dodoubleargument\syst_files_define_fallback} % still used?
+
+\def\syst_files_define_synonym [#name][#realname]{\ctxcommand{definefilesynonym ("#name","#realname")}}
+\def\syst_files_define_fallback[#name][#alternatives]{\ctxcommand{definefilefallback("#name","#alternatives")}}
+
+%D \macros
+%D {truefilename}
+%D
+%D At the system level such a filename can be called upon by
+%D saying:
+%D
+%D \starttyping
+%D \truefilename{filename/filesynonym}
+%D \stoptyping
+%D
+%D The implementation shows that nesting is supported.
+
+\def\truefilename#1{\ctxcommand{truefilename("#1")}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/filt-bas.mkii b/Master/texmf-dist/tex/context/base/filt-bas.mkii
index ca3bc3d7007..fedeb694b19 100644
--- a/Master/texmf-dist/tex/context/base/filt-bas.mkii
+++ b/Master/texmf-dist/tex/context/base/filt-bas.mkii
@@ -5,7 +5,7 @@
%D subtitle=A Base Collection,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/filt-ini.mkii b/Master/texmf-dist/tex/context/base/filt-ini.mkii
index 6e1a16e9ae6..f2f59349a51 100644
--- a/Master/texmf-dist/tex/context/base/filt-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/filt-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-afm.lua b/Master/texmf-dist/tex/context/base/font-afm.lua
index b719a9b3156..9d3d8ddd759 100644
--- a/Master/texmf-dist/tex/context/base/font-afm.lua
+++ b/Master/texmf-dist/tex/context/base/font-afm.lua
@@ -28,6 +28,7 @@ local next, type, tonumber = next, type, tonumber
local format, match, gmatch, lower, gsub, strip = string.format, string.match, string.gmatch, string.lower, string.gsub, string.strip
local abs = math.abs
local P, S, C, R, lpegmatch, patterns = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.match, lpeg.patterns
+local derivetable = table.derive
local fonts = fonts
local afm = { }
@@ -251,7 +252,7 @@ local function readafm(filename)
creator = "context mkiv",
},
properties = {
- italic_correction = false,
+ hasitalics = false,
},
goodies = {
},
@@ -768,9 +769,9 @@ local function copytotfm(data)
if data and data.descriptions then
local metadata = data.metadata
local resources = data.resources
- local properties = table.derive(data.properties)
- local descriptions = table.derive(data.descriptions)
- local goodies = table.derive(data.goodies)
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
local characters = { }
local parameters = { }
local unicodes = resources.unicodes
@@ -967,7 +968,8 @@ local function read_from_afm(specification)
if tfmdata then
tfmdata.properties.name = specification.name
tfmdata = constructors.scale(tfmdata, specification)
- constructors.applymanipulators("afm",tfmdata,specification.features.normal,trace_features,report_afm)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
fonts.loggers.register(tfmdata,'afm',specification)
end
return tfmdata
@@ -1102,7 +1104,7 @@ fonts.formats.pfb = "type1"
local function check_afm(specification,fullname)
local foundname = findbinfile(fullname, 'afm') or "" -- just to be sure
if foundname == "" then
- foundname = fonts.names.getfilename(fullname,"afm")
+ foundname = fonts.names.getfilename(fullname,"afm") or ""
end
if foundname == "" and afm.autoprefixed then
local encoding, shortname = match(fullname,"^(.-)%-(.*)$") -- context: encoding-name.*
diff --git a/Master/texmf-dist/tex/context/base/font-agl.lua b/Master/texmf-dist/tex/context/base/font-agl.lua
index a81d3503c42..6c1f387ba33 100644
--- a/Master/texmf-dist/tex/context/base/font-agl.lua
+++ b/Master/texmf-dist/tex/context/base/font-agl.lua
@@ -1,4 +1,4 @@
-if not modules then modules = { } end modules ['font-map'] = {
+if not modules then modules = { } end modules ['font-agl'] = {
version = 1.001,
comment = "companion to font-ini.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
diff --git a/Master/texmf-dist/tex/context/base/font-bfm.mkii b/Master/texmf-dist/tex/context/base/font-bfm.mkii
index 23e3176c4cd..0a25ec7422f 100644
--- a/Master/texmf-dist/tex/context/base/font-bfm.mkii
+++ b/Master/texmf-dist/tex/context/base/font-bfm.mkii
@@ -5,7 +5,7 @@
%D subtitle=Mixed Normal and Bold Math,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-chi.mkii b/Master/texmf-dist/tex/context/base/font-chi.mkii
index 0acf710d529..5e545722735 100644
--- a/Master/texmf-dist/tex/context/base/font-chi.mkii
+++ b/Master/texmf-dist/tex/context/base/font-chi.mkii
@@ -6,7 +6,7 @@
%D author=Hans Hagen,
%D date=\currentdate,
%D suggestions=Wang Lei,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-chk.lua b/Master/texmf-dist/tex/context/base/font-chk.lua
index e3679f06dba..04b49b02c5a 100644
--- a/Master/texmf-dist/tex/context/base/font-chk.lua
+++ b/Master/texmf-dist/tex/context/base/font-chk.lua
@@ -9,27 +9,43 @@ if not modules then modules = { } end modules ['font-chk'] = {
-- possible optimization: delayed initialization of vectors
-- move to the nodes namespace
-local report_fonts = logs.reporter("fonts","checking")
+local format = string.format
+local bpfactor = number.dimenfactors.bp
-local fonts = fonts
+local report_fonts = logs.reporter("fonts","checking")
-fonts.checkers = fonts.checkers or { }
-local checkers = fonts.checkers
+local fonts = fonts
-local fontdata = fonts.hashes.identifiers
-local is_character = characters.is_character
-local chardata = characters.data
-local tasks = nodes.tasks
+fonts.checkers = fonts.checkers or { }
+local checkers = fonts.checkers
-local glyph = node.id('glyph')
-local traverse_id = node.traverse_id
-local remove_node = nodes.remove
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local fontcharacters = fonthashes.characters
+
+local addprivate = fonts.helpers.addprivate
+local hasprivate = fonts.helpers.hasprivate
+local getprivatenode = fonts.helpers.getprivatenode
+
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
+
+local is_character = characters.is_character
+local chardata = characters.data
+
+local tasks = nodes.tasks
+local enableaction = tasks.enableaction
+local disableaction = tasks.disableaction
+
+local glyph_code = nodes.nodecodes.glyph
+local traverse_id = node.traverse_id
+local remove_node = nodes.remove
+local insert_node_after = node.insert_after
-- maybe in fonts namespace
-- deletion can be option
-checkers.enabled = false
-checkers.delete = false
+local action = false
-- to tfmdata.properties ?
@@ -54,46 +70,209 @@ end
fonts.loggers.onetimemessage = onetimemessage
+local mapping = { -- this is just an experiment to illustrate some principles elsewhere
+ lu = "placeholder uppercase red",
+ ll = "placeholder lowercase red",
+ lt = "placeholder uppercase red",
+ lm = "placeholder lowercase red",
+ lo = "placeholder lowercase red",
+ mn = "placeholder mark green",
+ mc = "placeholder mark green",
+ me = "placeholder mark green",
+ nd = "placeholder lowercase blue",
+ nl = "placeholder lowercase blue",
+ no = "placeholder lowercase blue",
+ pc = "placeholder punctuation cyan",
+ pd = "placeholder punctuation cyan",
+ ps = "placeholder punctuation cyan",
+ pe = "placeholder punctuation cyan",
+ pi = "placeholder punctuation cyan",
+ pf = "placeholder punctuation cyan",
+ po = "placeholder punctuation cyan",
+ sm = "placeholder lowercase magenta",
+ sc = "placeholder lowercase yellow",
+ sk = "placeholder lowercase yellow",
+ so = "placeholder lowercase yellow",
+}
+
+table.setmetatableindex(mapping,function(t,k) v = "placeholder unknown gray" t[k] = v return v end)
+
+local fakes = {
+ {
+ name = "lowercase",
+ code = ".025 -.175 m .425 -.175 l .425 .525 l .025 .525 l .025 -.175 l .025 0 l .425 0 l .025 -.175 m h S",
+ width = .45,
+ height = .55,
+ depth = .20,
+ },
+ {
+ name = "uppercase",
+ code = ".025 -.225 m .625 -.225 l .625 .675 l .025 .675 l .025 -.225 l .025 0 l .625 0 l .025 -.225 m h S",
+ width = .65,
+ height = .70,
+ depth = .25,
+ },
+ {
+ name = "mark",
+ code = ".025 .475 m .125 .475 l .125 .675 l .025 .675 l .025 .475 l h B",
+ width = .15,
+ height = .70,
+ depth = -.50,
+ },
+ {
+ name = "punctuation",
+ code = ".025 -.175 m .125 -.175 l .125 .525 l .025 .525 l .025 -.175 l h B",
+ width = .15,
+ height = .55,
+ depth = .20,
+ },
+ {
+ name = "unknown",
+ code = ".025 0 m .425 0 l .425 .175 l .025 .175 l .025 0 l h B",
+ width = .45,
+ height = .20,
+ depth = 0,
+ },
+}
+
+local variants = {
+ { tag = "gray", r = .6, g = .6, b = .6 },
+ { tag = "red", r = .6, g = 0, b = 0 },
+ { tag = "green", r = 0, g = .6, b = 0 },
+ { tag = "blue", r = 0, g = 0, b = .6 },
+ { tag = "cyan", r = 0, g = .6, b = .6 },
+ { tag = "magenta", r = .6, g = 0, b = .6 },
+ { tag = "yellow", r = .6, g = .6, b = 0 },
+}
+
+local package = "q %0.6f 0 0 %0.6f 0 0 cm %s %s %s rg %s %s %s RG 10 M 1 j 1 J 0.05 w %s Q"
+
+local cache = { } -- saves some tables but not that impressive
+
+local function addmissingsymbols(tfmdata)
+ local characters = tfmdata.characters
+ local size = tfmdata.parameters.size
+ local privates = tfmdata.properties.privates
+ local scale = size * bpfactor
+ for i=1,#variants do
+ local v = variants[i]
+ local tag, r, g, b = v.tag, v.r, v.g, v.b
+ for i =1, #fakes do
+ local fake = fakes[i]
+ local name = fake.name
+ local privatename = format("placeholder %s %s",name,tag)
+ if not hasprivate(tfmdata,privatename) then
+ local hash = format("%s_%s_%s_%s_%s_%s",name,tag,r,g,b,size)
+ local char = cache[hash]
+ if not char then
+ char = {
+ width = size*fake.width,
+ height = size*fake.height,
+ depth = size*fake.depth,
+ commands = { { "special", "pdf: " .. format(package,scale,scale,r,g,b,r,g,b,fake.code) } }
+ }
+ cache[hash] = char
+ end
+ addprivate(tfmdata, privatename, char)
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "missing",
+ description = "missing symbols",
+ manipulators = {
+ base = addmissingsymbols,
+ node = addmissingsymbols,
+ }
+}
+
+fonts.loggers.category_to_placeholder = mapping
+
function checkers.missing(head)
- if checkers.enabled then
- local lastfont, characters, found = nil, nil, nil
- for n in traverse_id(glyph,head) do
- local font, char = n.font, n.char
- if font ~= lastfont then
- characters = fontdata[font].characters
+ local lastfont, characters, found = nil, nil, nil
+ for n in traverse_id(glyph_code,head) do -- faster than while loop so we delay removal
+ local font = n.font
+ local char = n.char
+ if font ~= lastfont then
+ characters = fontcharacters[font]
+ end
+ if not characters[char] and is_character[chardata[char].category] then
+ if action == "remove" then
+ onetimemessage(font,char,"missing (will be deleted)")
+ elseif action == "replace" then
+ onetimemessage(font,char,"missing (will be flagged)")
+ else
+ onetimemessage(font,char,"missing")
end
- if not characters[char] and is_character[chardata[char].category] then
- if checkers.delete then
- onetimemessage(font,char,"missing (will be deleted)")
- else
- onetimemessage(font,char,"missing")
- end
- if not found then
- found = { n }
- else
- found[#found+1] = n
- end
+ if not found then
+ found = { n }
+ else
+ found[#found+1] = n
end
end
- if found and checkers.delete then
- for i=1,#found do
- head = remove_node(head,found[i],true)
+ end
+ if not found then
+ -- all well
+ elseif action == "remove" then
+ for i=1,#found do
+ head = remove_node(head,found[i],true)
+ end
+ elseif action == "replace" then
+ for i=1,#found do
+ local n = found[i]
+ local font = n.font
+ local char = n.char
+ local tfmdata = fontdata[font]
+ local properties = tfmdata.properties
+ local privates = properties.privates
+ local category = chardata[char].category
+ local fakechar = mapping[category]
+ local p = privates and privates[fakechar]
+ if not p then
+ addmissingsymbols(tfmdata)
+ p = properties.privates[fakechar]
+ end
+ if properties.lateprivates then -- .frozen
+ -- bad, we don't have them at the tex end
+ local fake = getprivatenode(tfmdata,fakechar)
+ insert_node_after(head,n,fake)
+ head = remove_node(head,n,true)
+ else
+ -- good, we have \definefontfeature[default][default][missing=yes]
+ n.char = p
end
end
+ else
+ -- maye write a report to the log
end
return head, false
end
trackers.register("fonts.missing", function(v)
- tasks.enableaction("processors", "fonts.checkers.missing") -- always on then
- checkers.enabled = v
+ if v then
+ enableaction("processors","fonts.checkers.missing")
+ else
+ disableaction("processors","fonts.checkers.missing")
+ end
+ if v == "replace" then
+ otffeatures.defaults.missing = true
+ end
+ action = v
end)
-function checkers.enable(delete)
- tasks.enableaction("processors", "fonts.checkers.missing") -- always on then
- if delete ~= nil then
- checkers.delete = delete
- end
- checkers.enabled = true
+function commands.checkcharactersinfont()
+ enableaction("processors","fonts.checkers.missing")
+end
+
+function commands.removemissingcharacters()
+ enableaction("processors","fonts.checkers.missing")
+ action = "remove"
end
+function commands.replacemissingcharacters()
+ enableaction("processors","fonts.checkers.missing")
+ action = "replace"
+ otffeatures.defaults.missing = true
+end
diff --git a/Master/texmf-dist/tex/context/base/font-col.lua b/Master/texmf-dist/tex/context/base/font-col.lua
index e0d2fed112d..f8add1e4e1d 100644
--- a/Master/texmf-dist/tex/context/base/font-col.lua
+++ b/Master/texmf-dist/tex/context/base/font-col.lua
@@ -11,6 +11,7 @@ if not modules then modules = { } end modules ['font-col'] = {
local gmatch, type = string.gmatch, type
local traverse_id = node.traverse_id
local lpegmatch = lpeg.match
+local fastcopy = table.fastcopy
local settings_to_hash = utilities.parsers.settings_to_hash
local trace_collecting = false trackers.register("fonts.collecting", function(v) trace_collecting = v end)
@@ -82,12 +83,14 @@ function collections.define(name,font,ranges,details)
end
end
details.font, details.start, details.stop = font, start, stop
- d[#d+1] = table.fastcopy(details)
+ d[#d+1] = fastcopy(details)
end
end
end
-function collections.stage_one(name)
+-- todo: provide a lua variant (like with definefont)
+
+function collections.registermain(name)
local last = font.current()
if trace_collecting then
report_fonts("def: registering font %s with name %s",last,name)
@@ -95,7 +98,7 @@ function collections.stage_one(name)
list[#list+1] = last
end
-function collections.stage_two(name)
+function collections.clonevector(name)
statistics.starttiming(fonts)
local d = definitions[name]
local t = { }
@@ -166,27 +169,29 @@ function collections.prepare(name)
report_fonts("def: applying collection %s to %s (file: %s)",name,current,filename)
end
list = { }
- context.dostartcloningfonts() -- move this to tex \dostart...
+ context.pushcatcodes("prt") -- context.unprotect()
+ context.font_fallbacks_start_cloning()
for i=1,#d do
local f = d[i]
local name = f.font
local scale = f.rscale or 1
if lpegmatch(okay,name) then
- context.doclonefonta(name,scale) -- define with unique specs
+ context.font_fallbacks_clone_unique(name,scale)
else
- context.doclonefontb(name,scale) -- define with inherited specs
+ context.font_fallbacks_clone_inherited(name,scale)
end
- context.doclonefontstageone(name) -- registering main font
+ context.font_fallbacks_register_main(name)
end
- context.doclonefontstagetwo(name) -- preparing clone vectors
- context.dostopcloningfonts()
+ context.font_fallbacks_prepare_clone_vectors(name)
+ context.font_fallbacks_stop_cloning()
+ context.popcatcodes() -- context.protect()
elseif trace_collecting then
local filename = file.basename(fontdata[current].properties.filename or "?")
report_fonts("def: error in applying collection %s to %s (file: %s)",name,current,filename)
end
end
-function collections.message(message)
+function collections.report(message)
if trace_collecting then
report_fonts("tex: %s",message)
end
@@ -220,3 +225,12 @@ function collections.process(head) -- this way we keep feature processing
return head, false
end
end
+
+-- interface
+
+commands.fontcollectiondefine = collections.define
+commands.fontcollectionreset = collections.reset
+commands.fontcollectionprepare = collections.prepare
+commands.fontcollectionreport = collections.report
+commands.fontcollectionregister = collections.registermain
+commands.fontcollectionclone = collections.clonevector
diff --git a/Master/texmf-dist/tex/context/base/font-col.mkiv b/Master/texmf-dist/tex/context/base/font-col.mkvi
index f4f9a9dc723..030e9aef7f2 100644
--- a/Master/texmf-dist/tex/context/base/font-col.mkiv
+++ b/Master/texmf-dist/tex/context/base/font-col.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Fallbacks (collections),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -29,75 +29,67 @@
\unprotect
-\unexpanded\def\definefontfallback
- {\doquadrupleempty\dodefinefontfallback}
+\unexpanded\def\definefontfallback{\doquadrupleempty\font_fallbacks_define}
+\unexpanded\def\resetfontfallback {\dodoubleempty \font_fallbacks_reset }
-\def\dodefinefontfallback[#1][#2][#3][#4]%
- {\ctxlua{fonts.collections.define("#1","#2",\!!bs#3\!!es,\!!bs#4\!!es)}}
+\def\font_fallbacks_define[#name][#font][#ranges][#settings]%
+ {\ctxcommand{fontcollectiondefine("#name","#font",\!!bs#ranges\!!es,\!!bs#settings\!!es)}}
-\def\resetfontfallback
- {\dodoubleempty\doresetfontfallback}
+\def\font_fallbacks_reset[#name][#font]%
+ {\ctxcommand{fontcollectionreset("#name","#font")}}
-\def\doresetfontfallback[#1][#2]%
- {\ctxlua{fonts.collections.reset("#1","#2")}}
-
-% add fallbacks to last font
-
-\def\dodefinefontfallbacks#1%
- {\ctxlua{fonts.collections.prepare("#1")}}
+\def\font_fallbacks_prepare#name%
+ {\ctxcommand{fontcollectionprepare("#name")}} % add fallbacks to last font
% we might as well move the handling to lua but then we need to pass the
% fallbacks, skewchar etc.
-\setfalse\doingfontfallbacks
+\newconditional\c_font_fallbacks_in_progress
-\def\dodefinefontfallbacksindeed#1%
+\def\font_fallbacks_prepare_indeed#fallbacks%
{\begingroup
- \settrue\doingfontfallbacks
+ \settrue\c_font_fallbacks_in_progress
\lastrawfontcall % sets current font id
- \dodefinefontfallbacks#1%
+ \font_fallbacks_prepare#fallbacks%
\endgroup}
+\let\m_font_fallbacks\empty % set in the font-ini
+
\appendtoks
- \ifconditional\doingfontfallbacks\else
- \ifx\@@fontfallbacks\empty
- \ifx\@@fontclassfallbacks\empty
+ \ifconditional\c_font_fallbacks_in_progress\else
+ \ifx\m_font_fallbacks\empty
+ \ifx\m_font_class_fallbacks\empty
\else
- \dodefinefontfallbacksindeed\@@fontclassfallbacks
+ \font_fallbacks_prepare_indeed\m_font_class_fallbacks
\fi
\else
- \dodefinefontfallbacksindeed\@@fontfallbacks
+ \font_fallbacks_prepare_indeed\m_font_fallbacks
\fi
\fi
\to\everydefinefont
-\def\dostartcloningfonts
- {\bgroup
+\def\font_fallbacks_start_cloning
+ {\begingroup
\let\savedfontspec\somefontspec}
-\def\dostopcloningfonts
- {\egroup}
+\def\font_fallbacks_stop_cloning
+ {\endgroup}
-\def\doclonefonta#1#2% kind of dododefinefont
- {\ctxlua{fonts.collections.message("defining #1 (relative scale: #2)")}% brrr
- \autofontsizefalse
+\def\font_fallbacks_clone_unique#specification#scale% kind of dododefinefont
+ {\ctxcommand{fontcollectionreport("defining #specification (relative scale: #scale)")}% brrr
+ \setfalse\c_font_auto_size
\let\lastfontidentifier\s!dummy
- \def\localrelativefontsize{#2}%
- \let\localabsolutefontsize\fontbody
- \lowleveldefinefont{#1}\rawfontidentifier
- \csname\rawfontidentifier\endcsname
- \autofontsizefalse
- %\setfontcharacteristics
- }%\the\everyfontswitch}
-
-\def\doclonefontb#1% #2
- {\doclonefonta{#1 \savedfontspec}}
-
-\def\doclonefontstageone#1%
- {\ctxlua{fonts.collections.stage_one("#1")}}
-
-\def\doclonefontstagetwo#1%
- {\ctxlua{fonts.collections.stage_two("#1")}}
+ \def\v_font_size_relative{#scale}%
+ \let\v_font_size_absolute\fontbody
+ \font_helpers_low_level_define{#specification}\v_font_identifier_basic
+ \csname\v_font_identifier_basic\endcsname
+ \setfalse\c_font_auto_size} % no \setfontcharacteristics and \the\everyfontswitch needed
+
+\def\font_fallbacks_clone_inherited#font% also a second argument
+ {\font_fallbacks_clone_unique{#font \savedfontspec}}
+
+\def\font_fallbacks_register_main #name{\ctxcommand{fontcollectionregister("#name")}}
+\def\font_fallbacks_prepare_clone_vectors#name{\ctxcommand{fontcollectionclone("#name")}}
% check : only replace when present in replacement font (default: no)
% force : force replacent even when basefont has glyph (default: yes)
diff --git a/Master/texmf-dist/tex/context/base/font-con.lua b/Master/texmf-dist/tex/context/base/font-con.lua
index 5d30842ef7f..92809968857 100644
--- a/Master/texmf-dist/tex/context/base/font-con.lua
+++ b/Master/texmf-dist/tex/context/base/font-con.lua
@@ -7,12 +7,15 @@ if not modules then modules = { } end modules ['font-con'] = {
}
+-- some names of table entries will be changed (no _)
+
local utf = unicode.utf8
local next, tostring, rawget = next, tostring, rawget
local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
local utfbyte = utf.byte
local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy
+local derivetable = table.derive
local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end)
@@ -25,32 +28,128 @@ local report_defining = logs.reporter("fonts","defining")
<p>Here we only implement a few helper functions.</p>
--ldx]]--
-local fonts = fonts
-local constructors = { }
-fonts.constructors = constructors
-local handlers = { }
-fonts.handlers = handlers
+local fonts = fonts
+local constructors = { }
+fonts.constructors = constructors
+local handlers = { }
+fonts.handlers = handlers
-local specifiers = fonts.specifiers
-local contextsetups = specifiers.contextsetups
-local contextnumbers = specifiers.contextnumbers
+local specifiers = fonts.specifiers
+local contextsetups = specifiers.contextsetups
+local contextnumbers = specifiers.contextnumbers
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
-- will be directives
-constructors.dontembed = allocate()
-constructors.mathactions = { }
-constructors.autocleanup = true
-constructors.namemode = "fullpath" -- will be a function
+constructors.dontembed = allocate()
+constructors.autocleanup = true
+constructors.namemode = "fullpath" -- will be a function
+
+constructors.version = 1.01
+constructors.cache = containers.define("fonts", "constructors", constructors.version, false)
+
+constructors.privateoffset = 0xF0000 -- 0x10FFFF
+
+-- Some experimental helpers (handy for tracing):
+--
+-- todo: extra:
+--
+-- extra_space => space.extra
+-- space => space.width
+-- space_stretch => space.stretch
+-- space_shrink => space.shrink
-constructors.version = 1.01
-constructors.cache = containers.define("fonts", "constructors", constructors.version, false)
+-- We do keep the x-height, extra_space, space_shrink and space_stretch
+-- around as these are low level official names.
-constructors.privateoffset = 0xF0000 -- 0x10FFFF
+constructors.keys = {
+ properties = {
+ encodingbytes = "number",
+ embedding = "number",
+ cidinfo = {
+ },
+ format = "string",
+ fontname = "string",
+ fullname = "string",
+ filename = "filename",
+ psname = "string",
+ name = "string",
+ virtualized = "boolean",
+ hasitalics = "boolean",
+ autoitalicamount = "basepoints",
+ nostackmath = "boolean",
+ noglyphnames = "boolean",
+ mode = "string",
+ hasmath = "boolean",
+ mathitalics = "boolean",
+ textitalics = "boolean",
+ finalized = "boolean",
+ },
+ parameters = {
+ mathsize = "number",
+ scriptpercentage = "float",
+ scriptscriptpercentage = "float",
+ units = "cardinal",
+ designsize = "scaledpoints",
+ expansion = {
+ stretch = "integerscale", -- might become float
+ shrink = "integerscale", -- might become float
+ step = "integerscale", -- might become float
+ auto = "boolean",
+ },
+ protrusion = {
+ auto = "boolean",
+ },
+ slantfactor = "float",
+ extendfactor = "float",
+ factor = "float",
+ hfactor = "float",
+ vfactor = "float",
+ size = "scaledpoints",
+ units = "scaledpoints",
+ scaledpoints = "scaledpoints",
+ slantperpoint = "scaledpoints",
+ spacing = {
+ width = "scaledpoints",
+ stretch = "scaledpoints",
+ shrink = "scaledpoints",
+ extra = "scaledpoints",
+ },
+ xheight = "scaledpoints",
+ quad = "scaledpoints",
+ ascender = "scaledpoints",
+ descender = "scaledpoints",
+ synonyms = {
+ space = "spacing.width",
+ spacestretch = "spacing.stretch",
+ spaceshrink = "spacing.shrink",
+ extraspace = "spacing.extra",
+ x_height = "xheight",
+ space_stretch = "spacing.stretch",
+ space_shrink = "spacing.shrink",
+ extra_space = "spacing.extra",
+ em = "quad",
+ ex = "xheight",
+ slant = "slantperpoint",
+ },
+ },
+ description = {
+ width = "basepoints",
+ height = "basepoints",
+ depth = "basepoints",
+ boundingbox = { },
+ },
+ character = {
+ width = "scaledpoints",
+ height = "scaledpoints",
+ depth = "scaledpoints",
+ italic = "scaledpoints",
+ },
+}
--- This might become an interface;
+-- This might become an interface:
local designsizes = allocate()
constructors.designsizes = designsizes
@@ -99,7 +198,7 @@ excessive memory usage in CJK fonts, we no longer pass the boundingbox.)</p>
-- The scaler is only used for otf and afm and virtual fonts. If
-- a virtual font has italic correction make sure to set the
--- italic_correction flag. Some more flags will be added in
+-- hasitalics flag. Some more flags will be added in
-- the future.
--[[ldx--
@@ -145,39 +244,75 @@ function constructors.calculatescale(tfmdata,scaledpoints)
return scaledpoints, scaledpoints / (parameters.units or 1000) -- delta
end
-function constructors.assignmathparameters(target,tfmdata)
+local unscaled = {
+ ScriptPercentScaleDown = true,
+ ScriptScriptPercentScaleDown = true,
+ RadicalDegreeBottomRaisePercent = true
+}
+
+function constructors.assignmathparameters(target,original) -- simple variant, not used in context
-- when a tfm file is loaded, it has already been scaled
- -- and it never enters the scaled so this is otf only
+ -- and it never enters the scaled so this is otf only and
+ -- even then we do some extra in the context math plugins
local mathparameters = original.mathparameters
if mathparameters and next(mathparameters) then
local targetparameters = target.parameters
+ local targetproperties = target.properties
local targetmathparameters = { }
- local factor = targetparameters.factor
+ local factor = targetproperties.math_is_scaled and 1 or targetparameters.factor
for name, value in next, mathparameters do
- if name == "RadicalDegreeBottomRaisePercent" then
+ if unscaled[name] then
targetmathparameters[name] = value
else
targetmathparameters[name] = value * factor
end
end
- if not targetmathparameters.AccentBaseHeight then
- targetmathparameters.AccentBaseHeight = nil -- safeguard, still needed?
- end
if not targetmathparameters.FractionDelimiterSize then
- targetmathparameters.FractionDelimiterSize = 0
+ targetmathparameters.FractionDelimiterSize = 1.01 * targetparameters.size
end
if not mathparameters.FractionDelimiterDisplayStyleSize then
- targetmathparameters.FractionDelimiterDisplayStyleSize = 0
+ targetmathparameters.FractionDelimiterDisplayStyleSize = 2.40 * targetparameters.size
end
target.mathparameters = targetmathparameters
end
end
+function constructors.beforecopyingcharacters(target,original)
+ -- can be used for additional tweaking
+end
+
+function constructors.aftercopyingcharacters(target,original)
+ -- can be used for additional tweaking
+end
+
+function constructors.enhanceparameters(parameters)
+ local xheight = parameters.x_height
+ local quad = parameters.quad
+ local space = parameters.space
+ local stretch = parameters.space_stretch
+ local shrink = parameters.space_shrink
+ local extra = parameters.extra_space
+ local slant = parameters.slant
+ parameters.xheight = xheight
+ parameters.spacestretch = stretch
+ parameters.spaceshrink = shrink
+ parameters.extraspace = extra
+ parameters.em = quad
+ parameters.ex = xheight
+ parameters.slantperpoint = slant
+ parameters.spacing = {
+ width = space,
+ stretch = stretch,
+ shrink = shrink,
+ extra = extra,
+ }
+end
+
function constructors.scale(tfmdata,specification)
local target = { } -- the new table
--
if tonumber(specification) then
- specification = { size = specification }
+ specification = { size = specification }
end
--
local scaledpoints = specification.size
@@ -194,10 +329,9 @@ function constructors.scale(tfmdata,specification)
local mathparameters = tfmdata.mathparameters or { }
--
local targetcharacters = { }
- local targetdescriptions = table.derive(descriptions)
- local targetparameters = table.derive(parameters)
- -- local targetmathparameters = table.fastcopy(mathparameters) -- happens elsewhere
- local targetproperties = table.derive(properties)
+ local targetdescriptions = derivetable(descriptions)
+ local targetparameters = derivetable(parameters)
+ local targetproperties = derivetable(properties)
local targetgoodies = goodies -- we need to loop so no metatable
target.characters = targetcharacters
target.descriptions = targetdescriptions
@@ -213,9 +347,10 @@ function constructors.scale(tfmdata,specification)
-- specification.textsize : natural (text)size
-- parameters.mathsize : 1=text 2=script 3=scriptscript >1000 enforced size (feature value other than yes)
--
- local mathsize = tonumber(specification.mathsize) or 0
- local textsize = tonumber(specification.textsize) or scaledpoints
- local forcedsize = tonumber(parameters.mathsize ) or 0
+ local mathsize = tonumber(specification.mathsize) or 0
+ local textsize = tonumber(specification.textsize) or scaledpoints
+ local forcedsize = tonumber(parameters.mathsize ) or 0
+ local extrafactor = tonumber(specification.factor ) or 1
if (mathsize == 2 or forcedsize == 2) and parameters.scriptpercentage then
scaledpoints = parameters.scriptpercentage * textsize / 100
elseif (mathsize == 3 or forcedsize == 3) and parameters.scriptscriptpercentage then
@@ -302,17 +437,17 @@ function constructors.scale(tfmdata,specification)
target.auto_protrude = protrusion.auto
end
-- widening
- local extend_factor = parameters.extend_factor or 0
- if extend_factor ~= 0 and extend_factor ~= 1 then
- hdelta = hdelta * extend_factor
- target.extend = extend_factor * 1000 -- extent ?
+ local extendfactor = parameters.extendfactor or 0
+ if extendfactor ~= 0 and extendfactor ~= 1 then
+ hdelta = hdelta * extendfactor
+ target.extend = extendfactor * 1000 -- extent ?
else
target.extend = 1000 -- extent ?
end
-- slanting
- local slant_factor = parameters.slant_factor or 0
- if slant_factor ~= 0 then
- target.slant = slant_factor * 1000
+ local slantfactor = parameters.slantfactor or 0
+ if slantfactor ~= 0 then
+ target.slant = slantfactor * 1000
else
target.slant = 0
end
@@ -324,19 +459,20 @@ function constructors.scale(tfmdata,specification)
targetparameters.units = units
targetparameters.scaledpoints = askedscaledpoints
--
- local isvirtual = properties.virtualized or tfmdata.type == "virtual"
- local hasquality = target.auto_expand or target.auto_protrude
- local hasitalic = properties.italic_correction
- local stackmath = not properties.no_stackmath
- local nonames = properties.noglyphnames
- local nodemode = properties.mode == "node"
+ local isvirtual = properties.virtualized or tfmdata.type == "virtual"
+ local hasquality = target.auto_expand or target.auto_protrude
+ local hasitalics = properties.hasitalics
+ local autoitalicamount = properties.autoitalicamount
+ local stackmath = not properties.nostackmath
+ local nonames = properties.noglyphnames
+ local nodemode = properties.mode == "node"
--
if changed and not next(changed) then
changed = false
end
--
target.type = isvirtual and "virtual" or "real"
- -- this will move to some subtable so that it is copied at once
+ --
target.postprocessors = tfmdata.postprocessors
--
local targetslant = (parameters.slant or parameters[1] or 0)
@@ -347,7 +483,7 @@ function constructors.scale(tfmdata,specification)
local targetquad = (parameters.quad or parameters[6] or 0)*hdelta
local targetextra_space = (parameters.extra_space or parameters[7] or 0)*hdelta
--
- targetparameters.slant = targetslant
+ targetparameters.slant = targetslant -- slantperpoint
targetparameters.space = targetspace
targetparameters.space_stretch = targetspace_stretch
targetparameters.space_shrink = targetspace_shrink
@@ -363,25 +499,27 @@ function constructors.scale(tfmdata,specification)
if descender then
targetparameters.descender = delta * descender
end
- -- copies, might disappear
- targetparameters.xheight = targetparameters.xheight or parameters.x_height
- targetparameters.extraspace = targetparameters.extraspace or parameters.extra_space
- targetparameters.spacestretch = targetparameters.spacestretch or parameters.space_stretch
- targetparameters.spaceshrink = targetparameters.spaceshrink or parameters.space_shrink
+ --
+ constructors.enhanceparameters(targetparameters) -- official copies for us
--
local protrusionfactor = (targetquad ~= 0 and 1000/targetquad) or 0
local scaledwidth = defaultwidth * hdelta
local scaledheight = defaultheight * vdelta
local scaleddepth = defaultdepth * vdelta
--
- local hasmath = (properties.has_math or next(mathparameters)) and true
+ if trace_defining then
+ report_defining("scaling by (%s,%s): name '%s', fullname: '%s', filename: '%s'",
+ hdelta,vdelta,name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ --
+ local hasmath = (properties.hasmath or next(mathparameters)) and true
if hasmath then
if trace_defining then
report_defining("math enabled for: name '%s', fullname: '%s', filename: '%s'",
name or "noname",fullname or "nofullname",filename or "nofilename")
end
constructors.assignmathparameters(target,tfmdata) -- does scaling and whatever is needed
- properties.has_math = true
+ properties.hasmath = true
target.nomath = false
target.MathConstants = target.mathparameters
else
@@ -389,29 +527,75 @@ function constructors.scale(tfmdata,specification)
report_defining("math disabled for: name '%s', fullname: '%s', filename: '%s'",
name or "noname",fullname or "nofullname",filename or "nofilename")
end
- properties.has_math = false
+ properties.hasmath = false
target.nomath = true
target.mathparameters = nil -- nop
end
--
- local sharedkerns = { }
+ local italickey = "italic"
+ --
+ -- some context specific trickery (this will move to a plugin)
+ --
+ if hasmath then
+ if properties.mathitalics then
+ italickey = "italic_correction"
+ if trace_defining then
+ report_defining("math italics disabled for: name '%s', fullname: '%s', filename: '%s'",
+ name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ end
+ autoitalicamount = false -- new
+ else
+ if properties.textitalics then
+ italickey = "italic_correction"
+ if trace_defining then
+ report_defining("text italics disabled for: name '%s', fullname: '%s', filename: '%s'",
+ name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ if properties.delaytextitalics then
+ autoitalicamount = false
+ end
+ end
+ end
+ --
+ -- end of context specific trickery
+ --
+ constructors.beforecopyingcharacters(target,tfmdata)
+ --
+ local sharedkerns = { }
+ --
+ -- we can have a dumb mode (basemode without math etc) that skips most
--
for unicode, character in next, characters do
- local chr, description, index
+ local chr, description, index, touni
if changed then
- -- basemode hack
+ -- basemode hack (we try to catch missing tounicodes, e.g. needed for ssty in math cambria)
local c = changed[unicode]
if c then
- description = descriptions[c] or character
+ description = descriptions[c] or descriptions[unicode] or character
character = characters[c] or character
index = description.index or c
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ if not touni then -- goodie
+ local d = descriptions[unicode] or characters[unicode]
+ local i = d.index or unicode
+ touni = tounicode[i] -- nb: index!
+ end
+ end
else
description = descriptions[unicode] or character
index = description.index or unicode
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ end
end
else
description = descriptions[unicode] or character
index = description.index or unicode
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ end
end
local width = description.width
local height = description.height
@@ -454,15 +638,12 @@ function constructors.scale(tfmdata,specification)
}
end
end
+ if touni then
+ chr.tounicode = touni
+ end
-- if trace_scaling then
-- report_defining("t=%s, u=%s, i=%s, n=%s c=%s",k,chr.tounicode or "",index or 0,description.name or '-',description.class or '-')
-- end
- if tounicode then
- local tu = tounicode[index] -- nb: index!
- if tu then
- chr.tounicode = tu
- end
- end
if hasquality then
-- we could move these calculations elsewhere (saves calculations)
local ve = character.expansion_factor
@@ -478,11 +659,21 @@ function constructors.scale(tfmdata,specification)
chr.right_protruding = protrusionfactor*width*vr
end
end
- -- todo: hasitalic
- if hasitalic then
- local vi = description.italic or character.italic
+ --
+ if autoitalicamount then
+ local vi = description.italic
+ if not vi then
+ local vi = description.boundingbox[3] - description.width + autoitalicamount
+ if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic
+ chr[italickey] = vi*hdelta
+ end
+ elseif vi ~= 0 then
+ chr[italickey] = vi*hdelta
+ end
+ elseif hasitalics then
+ local vi = description.italic
if vi and vi ~= 0 then
- chr.italic = vi*hdelta
+ chr[italickey] = vi*hdelta
end
end
-- to be tested
@@ -613,6 +804,9 @@ function constructors.scale(tfmdata,specification)
end
targetcharacters[unicode] = chr
end
+ --
+ constructors.aftercopyingcharacters(target,tfmdata)
+ --
return target
end
@@ -653,12 +847,12 @@ function constructors.finalize(tfmdata)
parameters.size = tfmdata.size
end
--
- if not parameters.extend_factor then
- parameters.extend_factor = tfmdata.extend or 0
+ if not parameters.extendfactor then
+ parameters.extendfactor = tfmdata.extend or 0
end
--
- if not parameters.slant_factor then
- parameters.slant_factor = tfmdata.slant or 0
+ if not parameters.slantfactor then
+ parameters.slantfactor = tfmdata.slant or 0
end
--
if not parameters.designsize then
@@ -711,8 +905,8 @@ function constructors.finalize(tfmdata)
-- tfmdata.fonts
-- tfmdata.unscaled
--
- if not properties.has_math then
- properties.has_math = not tfmdata.nomath
+ if not properties.hasmath then
+ properties.hasmath = not tfmdata.nomath
end
--
tfmdata.MathConstants = nil
@@ -997,7 +1191,7 @@ a helper function.</p>
function constructors.checkedfeatures(what,features)
local defaults = handlers[what].features.defaults
if features and next(features) then
- features = fastcopy(features) -- can be inherited
+ features = fastcopy(features) -- can be inherited (mt) but then no loops possible
for key, value in next, defaults do
if features[key] == nil then
features[key] = value
@@ -1031,7 +1225,7 @@ function constructors.initializefeatures(what,tfmdata,features,trace,report)
for i=1,#initializers do
local step = initializers[i]
local feature = step.name
--- we could intercept mode here .. needs a rewrite of this whole loop then btu it's cleaner that way
+-- we could intercept mode here .. needs a rewrite of this whole loop then but it's cleaner that way
local value = features[feature]
if not value then
-- disabled
@@ -1100,6 +1294,9 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report)
end
end
end
+ elseif trace then
+ report("no feature processors for mode %s for font %s",
+ mode or 'unknown', tfmdata.properties.fullname or 'unknown')
end
end
return processes
diff --git a/Master/texmf-dist/tex/context/base/font-ctx.lua b/Master/texmf-dist/tex/context/base/font-ctx.lua
index 887aa99841e..4b324a6db79 100644
--- a/Master/texmf-dist/tex/context/base/font-ctx.lua
+++ b/Master/texmf-dist/tex/context/base/font-ctx.lua
@@ -11,7 +11,8 @@ if not modules then modules = { } end modules ['font-ctx'] = {
local texcount, texsetcount = tex.count, tex.setcount
local format, gmatch, match, find, lower, gsub, byte = string.format, string.gmatch, string.match, string.find, string.lower, string.gsub, string.byte
-local concat, serialize, sort = table.concat, table.serialize, table.sort
+local concat, serialize, sort, fastcopy, mergedtable = table.concat, table.serialize, table.sort, table.fastcopy, table.merged
+local sortedhash, sortedkeys, sequenced = table.sortedhash, table.sortedkeys, table.sequenced
local settings_to_hash, hash_to_string = utilities.parsers.settings_to_hash, utilities.parsers.hash_to_string
local formatcolumns = utilities.formatters.formatcolumns
@@ -21,11 +22,14 @@ local round = math.round
local P, S, C, Cc, Cf, Cg, Ct, lpegmatch = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.match
-local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
-local trace_usage = false trackers.register("fonts.usage", function(v) trace_usage = v end)
-local trace_mapfiles = false trackers.register("fonts.mapfiles", function(v) trace_mapfiles = v end)
-local trace_automode = false trackers.register("fonts.automode", function(v) trace_automode = v end)
+local trace_features = false trackers.register("fonts.features", function(v) trace_features = v end)
+local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
+local trace_designsize = false trackers.register("fonts.designsize", function(v) trace_designsize = v end)
+local trace_usage = false trackers.register("fonts.usage", function(v) trace_usage = v end)
+local trace_mapfiles = false trackers.register("fonts.mapfiles", function(v) trace_mapfiles = v end)
+local trace_automode = false trackers.register("fonts.automode", function(v) trace_automode = v end)
+local report_features = logs.reporter("fonts","features")
local report_defining = logs.reporter("fonts","defining")
local report_status = logs.reporter("fonts","status")
local report_mapfiles = logs.reporter("fonts","mapfiles")
@@ -40,17 +44,24 @@ local definers = fonts.definers
local specifiers = fonts.specifiers
local constructors = fonts.constructors
local loggers = fonts.loggers
+local fontgoodies = fonts.goodies
local helpers = fonts.helpers
local hashes = fonts.hashes
local fontdata = hashes.identifiers
local currentfont = font.current
local texattribute = tex.attribute
+local designsizefilename = fontgoodies.designsizes.filename
+
local otffeatures = fonts.constructors.newfeatures("otf")
local registerotffeature = otffeatures.register
local baseprocessors = otffeatures.processors.base
local baseinitializers = otffeatures.initializers.base
+local sequencers = utilities.sequencers
+local appendgroup = sequencers.appendgroup
+local appendaction = sequencers.appendaction
+
specifiers.contextsetups = specifiers.contextsetups or { }
specifiers.contextnumbers = specifiers.contextnumbers or { }
specifiers.contextmerged = specifiers.contextmerged or { }
@@ -75,42 +86,76 @@ local nulldata = {
characters = { },
descriptions = { },
properties = { },
- parameters = { -- lmromanregular @ 12pt
- slant = 0, -- 1
- space = 256377, -- 2
- spacestretch = 128188, -- 3
- spaceshrink = 85459, -- 4
- xheight = 338952, -- 5
- quad = 786432, -- 6
- extraspace = 85459, -- 7
+ parameters = { -- lmromanregular @ 12pt
+ slant = 0, -- 1
+ space = 256377, -- 2
+ space_stretch = 128188, -- 3
+ space_shrink = 85459, -- 4
+ x_height = 338952, -- 5
+ quad = 786432, -- 6
+ extra_space = 85459, -- 7
},
}
+constructors.enhanceparameters(nulldata.parameters) -- official copies for us
+
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ fontloader.open = i_limiter.protect(fontloader.open)
+ fontloader.info = i_limiter.protect(fontloader.info)
+ limited = true
+ end
+ end
+end)
+
function definers.resetnullfont()
-- resetting is needed because tikz misuses nullfont
local parameters = nulldata.parameters
- parameters.slant = 0 -- 1
- parameters.space = 0 -- 2
- parameters.spacestretch = 0 -- 3
- parameters.spaceshrink = 0 -- 4
- parameters.xheight = 0 -- 5
- parameters.quad = 0 -- 6
- parameters.extraspace = 0 -- 7
+ --
+ parameters.slant = 0 -- 1
+ parameters.space = 0 -- 2
+ parameters.space_stretch = 0 -- 3
+ parameters.space_shrink = 0 -- 4
+ parameters.x_height = 0 -- 5
+ parameters.quad = 0 -- 6
+ parameters.extra_space = 0 -- 7
+ --
+ constructors.enhanceparameters(parameters) -- official copies for us
+ --
definers.resetnullfont = function() end
end
+commands.resetnullfont = definers.resetnullfont
+
setmetatableindex(fontdata, function(t,k) return nulldata end)
+-- we might make an font-hsh.lua
+
local chardata = allocate() -- chardata
+local descriptions = allocate()
local parameters = allocate()
+local properties = allocate()
+local resources = allocate()
+local quaddata = allocate() -- maybe also spacedata
+local markdata = allocate()
+local xheightdata = allocate()
local csnames = allocate() -- namedata
-local quaddata = allocate() -- quaddata
-local xheightdata = allocate() -- xheightdata
+local italicsdata = allocate()
hashes.characters = chardata
+hashes.descriptions = descriptions
hashes.parameters = parameters
+hashes.properties = properties
+hashes.resources = resources
hashes.quads = quaddata
+hashes.marks = markdata
hashes.xheights = xheightdata
+hashes.csnames = csnames
+hashes.italics = italicsdata
setmetatableindex(chardata, function(t,k)
local characters = fontdata[k].characters
@@ -118,12 +163,32 @@ setmetatableindex(chardata, function(t,k)
return characters
end)
+setmetatableindex(descriptions, function(t,k)
+ local descriptions = fontdata[k].descriptions
+ t[k] = descriptions
+ return descriptions
+end)
+
setmetatableindex(parameters, function(t,k)
local parameters = fontdata[k].parameters
t[k] = parameters
return parameters
end)
+setmetatableindex(properties, function(t,k)
+ local properties = fontdata[k].properties
+ t[k] = properties
+ return properties
+end)
+
+setmetatableindex(resources, function(t,k)
+ local shared = fontdata[k].shared
+ local rawdata = shared and shared.rawdata
+ local resources = rawdata and rawdata.resources
+ t[k] = resources or false -- better than resolving each time
+ return resources
+end)
+
setmetatableindex(quaddata, function(t,k)
local parameters = parameters[k]
local quad = parameters and parameters.quad or 0
@@ -131,6 +196,13 @@ setmetatableindex(quaddata, function(t,k)
return quad
end)
+setmetatableindex(markdata, function(t,k)
+ local resources = fontdata[k].resources or { }
+ local marks = resources.marks or { }
+ t[k] = marks
+ return marks
+end)
+
setmetatableindex(xheightdata, function(t,k)
local parameters = parameters[k]
local xheight = parameters and parameters.xheight or 0
@@ -138,6 +210,18 @@ setmetatableindex(xheightdata, function(t,k)
return quad
end)
+setmetatableindex(italicsdata, function(t,k) -- is test !
+ local properties = fontdata[k].properties
+ local hasitalics = properties and properties.hasitalics
+ if hasitalics then
+ hasitalics = chardata[k] -- convenient return
+ else
+ hasitalics = false
+ end
+ t[k] = hasitalics
+ return hasitalics
+end)
+
-- this cannot be a feature initializer as there is no auto namespace
-- so we never enter the loop then; we can store the defaults in the tma
-- file (features.gpos.mkmk = 1 etc)
@@ -148,42 +232,71 @@ local needsnodemode = {
gpos_mark2ligature = true,
}
-local function modechecker(tfmdata,features,mode) -- we cannot adapt features as they are shared!
- if mode == "auto" then
- local rawdata = tfmdata.shared.rawdata
- local resources = rawdata and rawdata.resources
- local sequences = resources.sequences
- if sequences and #sequences > 0 then
- local script = features.script or "dflt"
- local language = features.language or "dflt"
- for feature, value in next, features do
- if value then
- local found = false
- for i=1,#sequences do
- local sequence = sequences[i]
- local features = sequence.features
- if features then
- local scripts = features[feature]
- if scripts then
- local languages = scripts[script]
- if languages and languages[language] then
- if found then
- -- more than one lookup
- if trace_automode then
- report_defining("forcing node mode in font %s for feature %s, script %s, language %s (multiple lookups)",file.basename(tfmdata.properties.name),feature,script,language)
- end
- features.mode = "node"
- return "node"
- elseif needsnodemode[sequence.type] then
- if trace_automode then
- report_defining("forcing node mode in font %s for feature %s, script %s, language %s (no base support)",file.basename(tfmdata.properties.name),feature,script,language)
- end
- features.mode = "node"
- return "node"
- else
- -- at least one lookup
- found = true
+fonts.handlers.otf.tables.scripts.auto = "automatic fallback to latn when no dflt present"
+
+local privatefeatures = {
+ tlig = true,
+ trep = true,
+ anum = true,
+}
+
+local function checkedscript(tfmdata,resources,features)
+ local latn = false
+ local script = false
+ for g, list in next, resources.features do
+ for f, scripts in next, list do
+ if privatefeatures[f] then
+ -- skip
+ elseif scripts.dflt then
+ script = "dflt"
+ break
+ elseif scripts.latn then
+ latn = true
+ end
+ end
+ end
+ if not script then
+ script = latn and "latn" or "dflt"
+ end
+ if trace_automode then
+ report_defining("auto script mode: using script '%s' in font '%s'",script,file.basename(tfmdata.properties.name))
+ end
+ features.script = script
+ return script
+end
+
+local function checkedmode(tfmdata,resources,features)
+ local sequences = resources.sequences
+ if sequences and #sequences > 0 then
+ local script = features.script or "dflt"
+ local language = features.language or "dflt"
+ for feature, value in next, features do
+ if value then
+ local found = false
+ for i=1,#sequences do
+ local sequence = sequences[i]
+ local features = sequence.features
+ if features then
+ local scripts = features[feature]
+ if scripts then
+ local languages = scripts[script]
+ if languages and languages[language] then
+ if found then
+ -- more than one lookup
+ if trace_automode then
+ report_defining("forcing node mode in font %s for feature %s, script %s, language %s (multiple lookups)",file.basename(tfmdata.properties.name),feature,script,language)
end
+ features.mode = "node"
+ return "node"
+ elseif needsnodemode[sequence.type] then
+ if trace_automode then
+ report_defining("forcing node mode in font %s for feature %s, script %s, language %s (no base support)",file.basename(tfmdata.properties.name),feature,script,language)
+ end
+ features.mode = "node"
+ return "node"
+ else
+ -- at least one lookup
+ found = true
end
end
end
@@ -191,10 +304,32 @@ local function modechecker(tfmdata,features,mode) -- we cannot adapt features as
end
end
end
- return "base"
+ end
+ features.mode = "base" -- new, or is this wrong?
+ return "base"
+end
+
+definers.checkedscript = checkedscript
+definers.checkedmode = checkedmode
+
+local function modechecker(tfmdata,features,mode) -- we cannot adapt features as they are shared!
+ if trace_features then
+ report_features(serialize(features,"used"))
+ end
+ local rawdata = tfmdata.shared.rawdata
+ local resources = rawdata and rawdata.resources
+ local script = features.script
+ if resources then
+ if script == "auto" then
+ script = checkedscript(tfmdata,resources,features)
+ end
+ if mode == "auto" then
+ mode = checkedmode(tfmdata,resources,features)
+ end
else
- return mode
+ report_features("missing resources for font''%s'",file.basename(tfmdata.properties.name))
end
+ return mode
end
registerotffeature {
@@ -222,6 +357,38 @@ registerotffeature {
-- },
-- }
+local beforecopyingcharacters = sequencers.new {
+ name = "beforecopyingcharacters",
+ arguments = "target,original",
+}
+
+appendgroup(beforecopyingcharacters,"before") -- user
+appendgroup(beforecopyingcharacters,"system") -- private
+appendgroup(beforecopyingcharacters,"after" ) -- user
+
+function constructors.beforecopyingcharacters(original,target)
+ local runner = beforecopyingcharacters.runner
+ if runner then
+ runner(original,target)
+ end
+end
+
+local aftercopyingcharacters = sequencers.new {
+ name = "aftercopyingcharacters",
+ arguments = "target,original",
+}
+
+appendgroup(aftercopyingcharacters,"before") -- user
+appendgroup(aftercopyingcharacters,"system") -- private
+appendgroup(aftercopyingcharacters,"after" ) -- user
+
+function constructors.aftercopyingcharacters(original,target)
+ local runner = aftercopyingcharacters.runner
+ if runner then
+ runner(original,target)
+ end
+end
+
--[[ldx--
<p>So far we haven't really dealt with features (or whatever we want
to pass along with the font definition. We distinguish the following
@@ -346,7 +513,7 @@ local function contextnumber(name) -- will be replaced
else
local script, language = languages.association(lng)
if t.script ~= script or t.language ~= language then
- local s = table.fastcopy(t)
+ local s = fastcopy(t)
local n = #numbers + 1
setups[tag] = s
numbers[n] = tag
@@ -479,8 +646,11 @@ end
-- todo: support a,b,c
+-- we need a copy as we will add (fontclass) goodies to the features and
+-- that is bad for a shared table
+
local function splitcontext(features) -- presetcontext creates dummy here
- return setups[features] or (presetcontext(features,"","") and setups[features])
+ return fastcopy(setups[features] or (presetcontext(features,"","") and setups[features]))
end
--~ local splitter = lpeg.splitat("=")
@@ -527,7 +697,7 @@ end
specifiers.splitcontext = splitcontext
function specifiers.contexttostring(name,kind,separator,yes,no,strict,omit) -- not used
- return hash_to_string(table.merged(handlers[kind].features.defaults or {},setups[name] or {}),separator,yes,no,strict,omit)
+ return hash_to_string(mergedtable(handlers[kind].features.defaults or {},setups[name] or {}),separator,yes,no,strict,omit)
end
local function starred(features) -- no longer fallbacks here
@@ -592,8 +762,12 @@ local setsomefontname = context.fntsetsomename
local setemptyfontsize = context.fntsetnopsize
local setsomefontsize = context.fntsetsomesize
-function definers.stage_one(str)
+function commands.definefont_one(str)
statistics.starttiming(fonts)
+ if trace_defining then
+ report_defining("memory usage before: %s",statistics.memused())
+ report_defining("start stage one: %s",str)
+ end
local fullname, size = lpegmatch(splitpattern,str)
local lookup, name, sub, method, detail = getspecification(fullname)
if not name then
@@ -623,6 +797,9 @@ function definers.stage_one(str)
setemptyfontsize()
end
specification = definers.makespecification(str,lookup,name,sub,method,detail,size)
+ if trace_defining then
+ report_defining("stop stage one")
+ end
end
local n = 0
@@ -630,14 +807,34 @@ local n = 0
-- we can also move rscale to here (more consistent)
-- the argument list will become a table
-function definers.stage_two(global,cs,str,size,inheritancemode,classfeatures,fontfeatures,classfallbacks,fontfallbacks,
- mathsize,textsize,relativeid,classgoodies,goodies)
+local function nice_cs(cs)
+ return (gsub(cs,".->", ""))
+end
+
+function commands.definefont_two(global,cs,str,size,inheritancemode,classfeatures,fontfeatures,classfallbacks,fontfallbacks,
+ mathsize,textsize,relativeid,classgoodies,goodies,classdesignsize,fontdesignsize)
if trace_defining then
- report_defining("memory usage before: %s",statistics.memused())
+ report_defining("start stage two: %s (%s)",str,size)
end
-- name is now resolved and size is scaled cf sa/mo
local lookup, name, sub, method, detail = getspecification(str or "")
- -- asome settings can be overloaded
+ -- new (todo: inheritancemode)
+ local designsize = fontdesignsize ~= "" and fontdesignsize or classdesignsize or ""
+ local designname = designsizefilename(name,designsize,size)
+ if designname and designname ~= "" then
+ if trace_defining or trace_designsize then
+ report_defining("remapping name: %s, specification: %s, size: %s => designsize: %s",name,designsize,size,designname)
+ end
+ -- we don't catch detail here
+ local o_lookup, o_name, o_sub, o_method, o_detail = getspecification(designname)
+ if o_lookup and o_lookup ~= "" then lookup = o_lookup end
+ if o_method and o_method ~= "" then method = o_method end
+ if o_detail and o_detail ~= "" then detail = o_detail end
+ name = o_name
+ sub = o_sub
+ end
+ -- so far
+ -- some settings can have been overloaded
if lookup and lookup ~= "" then
specification.lookup = lookup
end
@@ -645,14 +842,14 @@ function definers.stage_two(global,cs,str,size,inheritancemode,classfeatures,fon
local id = tonumber(relativeid) or 0
specification.relativeid = id > 0 and id
end
- specification.name = name
- specification.size = size
- specification.sub = (sub and sub ~= "" and sub) or specification.sub
- specification.mathsize = mathsize
- specification.textsize = textsize
- specification.goodies = goodies
- specification.cs = cs
- specification.global = global
+ specification.name = name
+ specification.size = size
+ specification.sub = (sub and sub ~= "" and sub) or specification.sub
+ specification.mathsize = mathsize
+ specification.textsize = textsize
+ specification.goodies = goodies
+ specification.cs = cs
+ specification.global = global
if detail and detail ~= "" then
specification.method = method or "*"
specification.detail = detail
@@ -707,36 +904,42 @@ function definers.stage_two(global,cs,str,size,inheritancemode,classfeatures,fon
specification.fallbacks = fontfallbacks
end
end
- local tfmdata = definers.read(specification,size) -- id not yet known
- local cs = specification.cs
- if cs then
- csnames[cs] = tfmdata -- new (beware: locals can be forgotten)
- end
+ local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?)
if not tfmdata then
- report_defining("unable to define %s as \\%s",name,cs)
+ report_defining("unable to define %s as [%s]",name,nice_cs(cs))
texsetcount("global","lastfontid",-1)
context.letvaluerelax(cs) -- otherwise the current definition takes the previous one
elseif type(tfmdata) == "number" then
if trace_defining then
- report_defining("reusing %s with id %s as \\%s (features: %s/%s, fallbacks: %s/%s, goodies: %s/%s)",
- name,tfmdata,cs,classfeatures,fontfeatures,classfallbacks,fontfallbacks,classgoodies,goodies)
+ report_defining("reusing %s with id %s as [%s] (features: %s/%s, fallbacks: %s/%s, goodies: %s/%s, designsize: %s/%s)",
+ name,tfmdata,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,classgoodies,goodies,classdesignsize,fontdesignsize)
end
+ csnames[tfmdata] = specification.cs
tex.definefont(global,cs,tfmdata)
-- resolved (when designsize is used):
setsomefontsize(fontdata[tfmdata].parameters.size .. "sp")
texsetcount("global","lastfontid",tfmdata)
else
-tfmdata.characters[0] = nil -- we use char0 as signal
- -- local t = os.clock(t)
+ -- setting the extra characters will move elsewhere
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ -- we use char0 as signal
+ characters[0] = nil
+ -- cf the spec pdf can handle this (no char in slot)
+ -- characters[0x00A0] = { width = parameters.space }
+ -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure
+ -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period
+ --
local id = font.define(tfmdata)
- -- print(name,os.clock()-t)
+ csnames[id] = specification.cs
tfmdata.properties.id = id
definers.register(tfmdata,id) -- to be sure, normally already done
tex.definefont(global,cs,id)
constructors.cleanuptable(tfmdata)
constructors.finalize(tfmdata)
if trace_defining then
- report_defining("defining %s with id %s as \\%s (features: %s/%s, fallbacks: %s/%s)",name,id,cs,classfeatures,fontfeatures,classfallbacks,fontfallbacks)
+ report_defining("defining %s with id %s as [%s] (features: %s/%s, fallbacks: %s/%s)",
+ name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks)
end
-- resolved (when designsize is used):
setsomefontsize((tfmdata.parameters.size or 655360) .. "sp")
@@ -747,6 +950,7 @@ tfmdata.characters[0] = nil -- we use char0 as signal
end
if trace_defining then
report_defining("memory usage after: %s",statistics.memused())
+ report_defining("stop stage two")
end
statistics.stoptiming(fonts)
end
@@ -771,6 +975,10 @@ function definers.define(specification)
specification.method = specification.method or (method ~= "" and method) or "*"
specification.detail = specification.detail or (detail ~= "" and detail) or ""
--
+ if type(specification.size) == "string" then
+ specification.size = tex.sp(specification.size) or 655260
+ end
+ --
specification.specification = "" -- not used
specification.resolved = ""
specification.forced = ""
@@ -836,6 +1044,50 @@ function constructors.calculatescale(tfmdata,scaledpoints,relativeid)
return scaledpoints, delta
end
+-- We overload the (generic) resolver:
+
+local resolvers = definers.resolvers
+local hashfeatures = constructors.hashfeatures
+
+function definers.resolve(specification) -- overload function in font-con.lua
+ if not specification.resolved or specification.resolved == "" then -- resolved itself not per se in mapping hash
+ local r = resolvers[specification.lookup]
+ if r then
+ r(specification)
+ end
+ end
+ if specification.forced == "" then
+ specification.forced = nil
+ else
+ specification.forced = specification.forced
+ end
+ -- goodies are a context specific thing and not always defined
+ -- as feature, so we need to make sure we add them here before
+ -- hashing because otherwise we get funny goodies applied
+ local goodies = specification.goodies
+ if goodies and goodies ~= "" then
+ -- this adapts the features table so it has best be a copy
+ local normal = specification.features.normal
+ if not normal then
+ specification.features.normal = { goodies = goodies }
+ elseif not normal.goodies then
+ local g = normal.goodies
+ if g and g ~= "" then
+ normal.goodies = format("%s,%s",g,goodies)
+ else
+ normal.goodies = goodies
+ end
+ end
+ end
+ -- so far for goodie hacks
+ specification.hash = lower(specification.name .. ' @ ' .. hashfeatures(specification))
+ if specification.sub and specification.sub ~= "" then
+ specification.hash = specification.sub .. ' @ ' .. specification.hash
+ end
+ return specification
+end
+
+
-- soon to be obsolete:
local mappings = fonts.mappings
@@ -905,7 +1157,7 @@ helpers.nametoslot = nametoslot
function loggers.reportdefinedfonts()
if trace_usage then
local t, tn = { }, 0
- for id, data in table.sortedhash(fontdata) do
+ for id, data in sortedhash(fontdata) do
local properties = data.properties or { }
local parameters = data.parameters or { }
tn = tn + 1
@@ -918,7 +1170,7 @@ function loggers.reportdefinedfonts()
properties.psname or "",
properties.fullname or "",
}
-report_status("%s: %s",properties.name,concat(table.sortedkeys(data)," "))
+report_status("%s: %s",properties.name,concat(sortedkeys(data)," "))
end
formatcolumns(t," ")
report_status()
@@ -941,7 +1193,7 @@ function loggers.reportusedfeatures()
local setup = setups[name]
local n = setup.number
setup.number = nil -- we have no reason to show this
- t[i] = { i, name, table.sequenced(setup,false,true) } -- simple mode
+ t[i] = { i, name, sequenced(setup,false,true) } -- simple mode
setup.number = n -- restore it (normally not needed as we're done anyway)
end
formatcolumns(t," ")
@@ -1014,7 +1266,7 @@ function fonts.definetypeface(name,t)
context.definefontsynonym( { format("%sBoldItalic", Shape) }, { format("spec:%s-%s-italic-%s", fontname, boldweight, boldwidth ) } )
context.definefontsynonym( { format("%sItalic", Shape) }, { format("spec:%s-%s-italic-%s", fontname, normalweight, normalwidth) } )
context.stopfontclass()
- local settings = table.sequenced({ features= t.features },",")
+ local settings = sequenced({ features= t.features },",")
context.dofastdefinetypeface(name, shortcut, shape, size, settings)
end
@@ -1057,7 +1309,7 @@ function commands.nbfs(amount,precision)
end
function commands.featureattribute(tag)
- tex.write(contextnumber(tag))
+ context(contextnumber(tag))
end
function commands.setfontfeature(tag)
@@ -1199,17 +1451,15 @@ if environment.initex then
for what, handler in table.sortedpairs(handlers) do
local features = handler.features
if features then
- local t = { }
- t[#t+1] = "["
- t[#t+1] = what
- t[#t+1] = format("(base initializers: %s)",names(features.initializers.base))
- t[#t+1] = format("(base processors: %s)", names(features.processors .base))
- t[#t+1] = format("(base manipulators: %s)",names(features.manipulators.base))
- t[#t+1] = format("(node initializers: %s)",names(features.initializers.node))
- t[#t+1] = format("(node processors: %s)", names(features.processors .node))
- t[#t+1] = format("(node manipulators: %s)",names(features.manipulators.node))
- t[#t+1] = "]"
- l[#l+1] = concat(t, " ")
+ l[#l+1] = format("[%s (base initializers: %s) (base processors: %s) (base manipulators: %s) (node initializers: %s) (node processors: %s) (node manipulators: %s)]",
+ what,
+ names(features.initializers.base),
+ names(features.processors .base),
+ names(features.manipulators.base),
+ names(features.initializers.node),
+ names(features.processors .node),
+ names(features.manipulators.node)
+ )
end
end
return concat(l, " | ")
@@ -1279,3 +1529,15 @@ to scale virtual characters.</p>
-- end
-- end
-- end
+
+function commands.setfontofid(id)
+ context.getvalue(csnames[id])
+end
+
+-- more interfacing:
+
+commands.definefontfeature = fonts.specifiers.presetcontext
+
+function commands.featurelist(...)
+ context(fonts.specifiers.contexttostring(...))
+end
diff --git a/Master/texmf-dist/tex/context/base/font-def.lua b/Master/texmf-dist/tex/context/base/font-def.lua
index 182e543b006..96de480ac86 100644
--- a/Master/texmf-dist/tex/context/base/font-def.lua
+++ b/Master/texmf-dist/tex/context/base/font-def.lua
@@ -119,7 +119,7 @@ function definers.registersplit(symbol,action,verbosename)
end
end
-function definers.makespecification(specification, lookup, name, sub, method, detail, size)
+function definers.makespecification(specification,lookup,name,sub,method,detail,size)
size = size or 655360
if trace_defining then
report_defining("%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s",
@@ -170,13 +170,14 @@ end
function resolvers.name(specification)
local resolve = fonts.names.resolve
if resolve then
- local resolved, sub = fonts.names.resolve(specification.name,specification.sub)
- specification.resolved, specification.sub = resolved, sub
+ local resolved, sub = resolve(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
if resolved then
+ specification.resolved = resolved
+ specification.sub = sub
local suffix = file.suffix(resolved)
if fonts.formats[suffix] then
specification.forced = suffix
- specification.name = file.removesuffix(resolved)
+ specification.name = file.removesuffix(resolved)
else
specification.name = resolved
end
@@ -189,10 +190,12 @@ end
function resolvers.spec(specification)
local resolvespec = fonts.names.resolvespec
if resolvespec then
- specification.resolved, specification.sub = fonts.names.resolvespec(specification.name,specification.sub)
- if specification.resolved then
- specification.forced = file.extname(specification.resolved)
- specification.name = file.removesuffix(specification.resolved)
+ local resolved, sub = resolvespec(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
+ if resolved then
+ specification.resolved = resolved
+ specification.sub = sub
+ specification.forced = file.extname(resolved)
+ specification.name = file.removesuffix(resolved)
end
else
resolvers.name(specification)
@@ -211,17 +214,6 @@ function definers.resolve(specification)
else
specification.forced = specification.forced
end
- -- for the moment here (goodies set outside features)
- local goodies = specification.goodies
- if goodies and goodies ~= "" then
- local normal = specification.features.normal
- if not normal then
- specification.features.normal = { goodies = goodies }
- elseif not normal.goodies then
- normal.goodies = goodies
- end
- end
- --
specification.hash = lower(specification.name .. ' @ ' .. constructors.hashfeatures(specification))
if specification.sub and specification.sub ~= "" then
specification.hash = specification.sub .. ' @ ' .. specification.hash
@@ -245,25 +237,43 @@ features (esp in virtual fonts) so let's not do that now.</p>
specification yet.</p>
--ldx]]--
--- not in context, at least not now:
---
+-- very experimental:
+
+function definers.applypostprocessors(tfmdata)
+ local postprocessors = tfmdata.postprocessors
+ if postprocessors then
+ for i=1,#postprocessors do
+ local extrahash = postprocessors[i](tfmdata) -- after scaling etc
+ if type(extrahash) == "string" and extrahash ~= "" then
+ -- e.g. a reencoding needs this
+ extrahash = gsub(lower(extrahash),"[^a-z]","-")
+ tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash)
+ end
+ end
+ end
+ return tfmdata
+end
+
-- function definers.applypostprocessors(tfmdata)
--- local postprocessors = tfmdata.postprocessors
--- if postprocessors then
--- for i=1,#postprocessors do
--- local extrahash = postprocessors[i](tfmdata) -- after scaling etc
--- if type(extrahash) == "string" and extrahash ~= "" then
--- -- e.g. a reencoding needs this
--- extrahash = gsub(lower(extrahash),"[^a-z]","-")
--- tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash)
--- end
--- end
--- end
-- return tfmdata
-- end
-function definers.applypostprocessors(tfmdata)
- return tfmdata
+local function checkembedding(tfmdata)
+ local properties = tfmdata.properties
+ local embedding
+ if directive_embedall then
+ embedding = "full"
+ elseif properties and properties.filename and constructors.dontembed[properties.filename] then
+ embedding = "no"
+ else
+ embedding = "subset"
+ end
+ if properties then
+ properties.embedding = embedding
+ else
+ tfmdata.properties = { embedding = embedding }
+ end
+ tfmdata.embedding = embedding
end
function definers.loadfont(specification)
@@ -295,21 +305,8 @@ function definers.loadfont(specification)
end
end
if tfmdata then
- local properties = tfmdata.properties
- local embedding
- if directive_embedall then
- embedding = "full"
- elseif properties.filename and constructors.dontembed[properties.filename] then
- embedding = "no"
- else
- embedding = "subset"
- end
- if properties then
- properties.embedding = embedding
- else
- tfmdata.properties = { embedding = embedding }
- end
tfmdata = definers.applypostprocessors(tfmdata)
+ checkembedding(tfmdata) -- todo: general postprocessor
loadedfonts[hash] = tfmdata
designsizes[specification.hash] = tfmdata.parameters.designsize
end
@@ -395,14 +392,25 @@ function definers.read(specification,size,id) -- id can be optional, name can al
specification = definers.resolve(specification)
local hash = constructors.hashinstance(specification)
local tfmdata = definers.registered(hash) -- id
- if not tfmdata then
+ if tfmdata then
+ if trace_defining then
+ report_defining("already hashed: %s",hash)
+ end
+ else
tfmdata = definers.loadfont(specification) -- can be overloaded
if tfmdata then
---~ constructors.checkvirtualid(tfmdata) -- interferes
+ if trace_defining then
+ report_defining("loaded and hashed: %s",hash)
+ end
+ --~ constructors.checkvirtualid(tfmdata) -- interferes
tfmdata.properties.hash = hash
if id then
definers.register(tfmdata,id)
end
+ else
+ if trace_defining then
+ report_defining("not loaded and hashed: %s",hash)
+ end
end
end
lastdefined = tfmdata or id -- todo ! ! ! ! !
@@ -412,7 +420,7 @@ function definers.read(specification,size,id) -- id can be optional, name can al
local properties = tfmdata.properties or { }
local parameters = tfmdata.parameters or { }
report_defining("using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s",
- properties.type or "unknown",
+ properties.format or "unknown",
id or "?",
properties.name or "?",
parameters.size or "default",
diff --git a/Master/texmf-dist/tex/context/base/font-emp.mkvi b/Master/texmf-dist/tex/context/base/font-emp.mkvi
new file mode 100644
index 00000000000..65aa7a52074
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-emp.mkvi
@@ -0,0 +1,231 @@
+%D \module
+%D [ file=font-emp,
+%D version=20120106, % (moved from font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Emphasis,
+%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 / Emphasis}
+
+\unprotect
+
+%D \macros
+%D {em,emphasistypeface,emphasisboldface}
+%D
+%D The next macro started as a copy of Donald Arseneau's
+%D \type{\em} (\TUGNEWS\ Vol.~3, no.~1, 1994). His
+%D implementation was a bit more sophisticated version of the
+%D standard \LATEX\ one. We further enhanced the macro, so now
+%D it also adapts itself to boldface mode. Because we favor
+%D {\sl slanted} type over {\it italic}, we made the emphasis
+%D adaptable, for instance:
+%D
+%D \starttyping
+%D \def\emphasistypeface {\it}
+%D \def\emphasisboldface {\bi}
+%D \stoptyping
+%D
+%D But we prefer:
+%D
+%D \starttyping
+%D \unexpanded\def\emphasistypeface{\sl}
+%D \unexpanded\def\emphasisboldface{\bs}
+%D \stoptyping
+%D
+%D or even better:
+
+\let\m_font_emphasized_typeface\empty
+
+\def\font_emphasis_checked_typeface#slanted#italic%
+ {\edef\m_font_emphasized_typeface{\bodyfontvariable\s!em}%
+ \ifx\m_font_emphasized_typeface\v!slanted
+ #slanted%
+ \else\ifx\m_font_emphasized_typeface\v!italic
+ #italic%
+ \else\ifx\m_font_emphasized_typeface\empty
+ #slanted%
+ \else
+ \csname\m_font_emphasized_typeface\endcsname
+ \fi\fi\fi}
+
+\unexpanded\def\emphasistypeface{\font_emphasis_checked_typeface\sl\it}
+\unexpanded\def\emphasisboldface{\font_emphasis_checked_typeface\bs\bi}
+
+\unexpanded\def\normalboldface % public
+ {\relax\ifx\fontalternative\s!it\bi
+ \else \ifx\fontalternative\s!sl\bs
+ \else \bf\fi\fi}
+
+\unexpanded\def\normaltypeface % public
+ {\relax
+ \ifx\fontalternative\s!bi \it \else
+ \ifx\fontalternative\s!bs \sl \else
+ \tf \fi\fi}
+
+\unexpanded\def\swaptypeface % public
+ {\relax
+ \ifx\fontalternative\s!it \tf \else
+ \ifx\fontalternative\s!sl \tf \else
+ \ifx\fontalternative\s!bf \emphasisboldface \else
+ \ifx\fontalternative\s!bs \bf \else
+ \ifx\fontalternative\s!bi \bf \else
+ \emphasistypeface \fi\fi\fi\fi\fi}
+
+\let\typeface\normaltypeface % public
+\let\boldface\normalboldface % public
+\let\swapface\swaptypeface % public
+
+%D To be set with the default body font environment: \type
+%D {em} being \type {slanted} or \type {italic}.
+
+% maybe a \csname...\fontalternative\endcsname
+
+\newconditional\c_font_emphasis_needed
+
+\unexpanded\def\em
+ {\relax
+ \ifdim\slantperpoint>\zeropoint
+ \settrue\c_font_emphasis_needed
+ \else
+ \setfalse\c_font_emphasis_needed
+ \fi
+ \font_emphasis_set_emphasis_boldface % new
+ \ifx\fontalternative\s!it
+ \unexpanded\def\emphasistypeface{\it}\tf
+ \else\ifx\fontalternative\s!sl
+ \unexpanded\def\emphasistypeface{\sl}\tf
+ \else\ifx\fontalternative\s!bf
+ \emphasisboldface
+ \else\ifx\fontalternative\s!bs
+ \unexpanded\def\emphasisboldface{\bs}\bf
+ \else\ifx\fontalternative\s!bi
+ \unexpanded\def\emphasisboldface{\bi}\bf
+ \else
+ \emphasistypeface
+ \fi\fi\fi\fi\fi
+ \ifconditional\c_font_emphasis_needed\else
+ \expandafter\aftergroup
+ \fi
+ \emphasiscorrection}
+
+%D The next feature was not present in previous versions. It
+%D takes care of \type {\em \bf ...} situations.
+
+\def\font_emphasis_set_emphasis_boldface
+ {\let\font_emphasis_saved_emphasis_boldface\bf
+ \let\font_emphasis_set_emphasis_boldface\relax
+ \let\bf\font_emphasis_bold_bold}
+
+\unexpanded\def\font_emphasis_bold_bold
+ {%\relax
+ \let\bf\relax % new
+ \ifx\fontalternative\s!it
+ \bi
+ \else\ifx\fontalternative\s!sl
+ \bs
+ \else
+ \font_emphasis_saved_emphasis_boldface
+ \fi\fi
+ \let\bf\font_emphasis_saved_emphasis_boldface}
+
+%D Donald's (adapted) macros take the next character into
+%D account when placing italic correction. As a bonus we also
+%D look for something that looks like a dash, in which case we
+%D don't correct.
+
+\let\italiccorrection=\/ % tex primitive
+
+\def\emphasiscorrection % public, not in raw alignment groups, else omit problem
+ {\ifhmode\ifnum\currentgrouptype=\aligngroupcode\else
+ \expandafter\expandafter\expandafter\font_emphasis_look
+ \fi\fi}
+
+\def\font_emphasis_look
+ {\begingroup
+ \futurelet\nexttoken\font_emphasis_test}
+
+\def\font_emphasis_test
+ {\ifcat\noexpand\nexttoken,% still ok?
+ \expandafter\font_emphasis_a
+ \else
+ \expandafter\font_emphasis_b
+ \fi}
+
+\def\font_emphasis_a
+ {\futurelet\nexttoken\font_emphasis_correction}
+
+\def\font_emphasis_correction
+ {\setbox\scratchbox\hbox{\nexttoken}% tricky as next can be a macro
+ \ifdim\ht\scratchbox=\zeropoint % probably a space
+ \expandafter\font_emphasis_b
+ \else\ifdim\ht\scratchbox<.3\exheight
+ \expandafter\expandafter\expandafter\endgroup
+ \else
+ \expandafter\expandafter\expandafter\font_emphasis_b
+ \fi\fi}
+
+\def\font_emphasis_b
+ {\scratchskip\lastskip
+ \ifdim\scratchskip=\zeropoint\relax % == \ifzeropt\scratchskip
+ \italiccorrection\relax
+ \else
+ \unskip\italiccorrection\hskip\scratchskip
+ \fi
+ \endgroup}
+
+%D We end with some examples which show the behavior when
+%D some punctuation is met. We also show how the mechanism
+%D adapts itself to bold, italic and slanted typing.
+%D
+%D \startbuffer
+%D test {test}test \par
+%D test {\sl test}test \par
+%D test {\em test}test \par
+%D test {\em test}--test \par
+%D
+%D test {test}, test \par
+%D test {\em test}, test \par
+%D
+%D test {\em test {\em test {\em test} test} test} test \par
+%D test {\bf test {\em test {\em test} test} test} test \par
+%D test {\sl test {\em test {\em test} test} test} test \par
+%D test {\it test {\em test {\em test} test} test} test \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D We get:
+%D
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+
+%D \macros
+%D {emphbf,emphit,emphsl,emphtf}
+%D
+%D The next emphasis alternatives are for \THANH. They adapt
+%D their style as good as possible. These macros are obsolete
+%D 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}}{}}
+
+%D \startbuffer
+%D TEXT {\emphbf text \emphit text \emphtf text \emphsl text} TEXT
+%D TEXT \emphbf{text \emphit{text} \emphtf{text} \emphsl{text}} TEXT
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \startlines
+%D \getbuffer
+%D \stoplines
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-ext.lua b/Master/texmf-dist/tex/context/base/font-ext.lua
index 4ea9cf3caa0..331ffbdfa91 100644
--- a/Master/texmf-dist/tex/context/base/font-ext.lua
+++ b/Master/texmf-dist/tex/context/base/font-ext.lua
@@ -8,18 +8,18 @@ if not modules then modules = { } end modules ['font-ext'] = {
local utf = unicode.utf8
local next, type, byte = next, type, string.byte
-local gmatch, concat = string.gmatch, table.concat
+local gmatch, concat, format = string.gmatch, table.concat, string.format
local utfchar = utf.char
local getparameters = utilities.parsers.getparameters
-local allocate = utilities.storage.allocate
-
local trace_protrusion = false trackers.register("fonts.protrusion", function(v) trace_protrusion = v end)
local trace_expansion = false trackers.register("fonts.expansion", function(v) trace_expansion = v end)
local report_expansions = logs.reporter("fonts","expansions")
local report_protrusions = logs.reporter("fonts","protrusions")
+-- todo: byte(..) => 0xHHHH
+
--[[ldx--
<p>When we implement functions that deal with features, most of them
will depend of the font format. Here we define the few that are kind
@@ -27,6 +27,7 @@ of neutral.</p>
--ldx]]--
local fonts = fonts
+local fontdata = fonts.hashes.identifiers
local otffeatures = fonts.constructors.newfeatures("otf")
local registerotffeature = otffeatures.register
@@ -34,6 +35,10 @@ local registerotffeature = otffeatures.register
local afmfeatures = fonts.constructors.newfeatures("afm")
local registerafmfeature = afmfeatures.register
+local allocate = utilities.storage.allocate
+local settings_to_array = utilities.parsers.settings_to_array
+local setmetatableindex = table.setmetatableindex
+
-- -- -- -- -- --
-- shared
-- -- -- -- -- --
@@ -475,7 +480,7 @@ fonts.goodies.register("protrusions", function(...) return fonts.goodies.report(
-- -- --
local function initializenostackmath(tfmdata,value)
- tfmdata.properties.no_stackmath = value and true
+ tfmdata.properties.nostackmath = value and true
end
registerotffeature {
@@ -487,20 +492,16 @@ registerotffeature {
}
}
-local function initializeitlc(tfmdata,value)
+local function initializeitlc(tfmdata,value) -- hm, always value
if value then
- -- the magic 40 and it formula come from Dohyun Kim
+ -- the magic 40 and it formula come from Dohyun Kim but we might need another guess
local parameters = tfmdata.parameters
local italicangle = parameters.italicangle
if italicangle and italicangle ~= 0 then
- local uwidth = (parameters.uwidth or 40)/2
- for unicode, d in next, tfmdata.descriptions do
- local it = d.boundingbox[3] - d.width + uwidth
- if it ~= 0 then
- d.italic = it
- end
- end
- tfmdata.properties.italic_correction = true
+ local properties = tfmdata.properties
+ local factor = tonumber(value) or 1
+ properties.hasitalics = true
+ properties.autoitalicamount = factor * (parameters.uwidth or 40)/2
end
end
end
@@ -523,6 +524,30 @@ registerafmfeature {
}
}
+local function initializetextitalics(tfmdata,value) -- yes no delay
+ local delay = value == "delay"
+ tfmdata.properties.textitalics = delay and true or value
+ tfmdata.properties.delaytextitalics = delay
+end
+
+registerotffeature {
+ name = "textitalics",
+ description = "use alternative text italic correction",
+ initializers = {
+ base = initializetextitalics,
+ node = initializetextitalics,
+ }
+}
+
+registerafmfeature {
+ name = "textitalics",
+ description = "use alternative text italic correction",
+ initializers = {
+ base = initializetextitalics,
+ node = initializetextitalics,
+ }
+}
+
-- slanting
local function initializeslant(tfmdata,value)
@@ -534,7 +559,7 @@ local function initializeslant(tfmdata,value)
elseif value < -1 then
value = -1
end
- tfmdata.parameters.slant_factor = value
+ tfmdata.parameters.slantfactor = value
end
registerotffeature {
@@ -564,7 +589,7 @@ local function initializeextend(tfmdata,value)
elseif value < -10 then
value = -10
end
- tfmdata.parameters.extend_factor = value
+ tfmdata.parameters.extendfactor = value
end
registerotffeature {
@@ -585,6 +610,202 @@ registerafmfeature {
}
}
+-- For Wolfgang Schuster:
+--
+-- \definefontfeature[thisway][default][script=hang,language=zhs,dimensions={2,2,2}]
+-- \definedfont[file:kozminpr6nregular*thisway]
+--
+-- For the moment we don't mess with the descriptions.
+
+local function manipulatedimensions(tfmdata,key,value)
+ if type(value) == "string" and value ~= "" then
+ local characters = tfmdata.characters
+ local parameters = tfmdata.parameters
+ local emwidth = parameters.quad
+ local exheight = parameters.xheight
+ local spec = settings_to_array(value)
+ local width = (spec[1] or 0) * emwidth
+ local height = (spec[2] or 0) * exheight
+ local depth = (spec[3] or 0) * exheight
+ if width > 0 then
+ local resources = tfmdata.resources
+ local additions = { }
+ local private = resources.private
+ for unicode, old_c in next, characters do
+ local oldwidth = old_c.width
+ if oldwidth ~= width then
+ -- Defining the tables in one step is more efficient
+ -- than adding fields later.
+ private = private + 1
+ local new_c
+ local commands = {
+ { "right", (width - oldwidth) / 2 },
+ { "slot", 1, private },
+ }
+ if height > 0 then
+ if depth > 0 then
+ new_c = {
+ width = width,
+ height = height,
+ depth = depth,
+ commands = commands,
+ }
+ else
+ new_c = {
+ width = width,
+ height = height,
+ commands = commands,
+ }
+ end
+ else
+ if depth > 0 then
+ new_c = {
+ width = width,
+ depth = depth,
+ commands = commands,
+ }
+ else
+ new_c = {
+ width = width,
+ commands = commands,
+ }
+ end
+ end
+ setmetatableindex(new_c,old_c)
+ characters[unicode] = new_c
+ additions[private] = old_c
+ end
+ end
+ for k, v in next, additions do
+ characters[k] = v
+ end
+ resources.private = private
+ elseif height > 0 and depth > 0 then
+ for unicode, old_c in next, characters do
+ old_c.height = height
+ old_c.depth = depth
+ end
+ elseif height > 0 then
+ for unicode, old_c in next, characters do
+ old_c.height = height
+ end
+ elseif depth > 0 then
+ for unicode, old_c in next, characters do
+ old_c.depth = depth
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "dimensions",
+ description = "force dimensions",
+ manipulators = {
+ base = manipulatedimensions,
+ node = manipulatedimensions,
+ }
+}
+
+-- for zhichu chen (see mailing list archive): we might add a few more variants
+-- in due time
+--
+-- \definefontfeature[boxed][default][boundingbox=yes] % paleblue
+--
+-- maybe:
+--
+-- \definecolor[DummyColor][s=.75,t=.5,a=1] {\DummyColor test} \nopdfcompression
+--
+-- local gray = { "special", "pdf: /Tr1 gs .75 g" }
+-- local black = { "special", "pdf: /Tr0 gs 0 g" }
+
+local push = { "push" }
+local pop = { "pop" }
+local gray = { "special", "pdf: .75 g" }
+local black = { "special", "pdf: 0 g" }
+
+local downcache = { } -- handy for huge cjk fonts
+local rulecache = { } -- handy for huge cjk fonts
+
+setmetatableindex(downcache,function(t,d)
+ local v = { "down", d }
+ t[d] = v
+ return v
+end)
+
+setmetatableindex(rulecache,function(t,h)
+ local v = { }
+ t[h] = v
+ setmetatableindex(v,function(t,w)
+ local v = { "rule", h, w }
+ t[w] = v
+ return v
+ end)
+ return v
+end)
+
+local function showboundingbox(tfmdata,key,value)
+ if value then
+ local vfspecials = backends.pdf.tables.vfspecials
+ local gray = vfspecials and (vfspecials.rulecolors[value] or vfspecials.rulecolors.palegray) or gray
+ local characters = tfmdata.characters
+ local resources = tfmdata.resources
+ local additions = { }
+ local private = resources.private
+ for unicode, old_c in next, characters do
+ private = private + 1
+ local width = old_c.width or 0
+ local height = old_c.height or 0
+ local depth = old_c.depth or 0
+ local new_c
+ if depth == 0 then
+ new_c = {
+ width = width,
+ height = height,
+ commands = {
+ push,
+ gray,
+ rulecache[height][width],
+ black,
+ pop,
+ { "slot", 1, private },
+ }
+ }
+ else
+ new_c = {
+ width = width,
+ height = height,
+ depth = depth,
+ commands = {
+ push,
+ downcache[depth],
+ gray,
+ rulecache[height+depth][width],
+ black,
+ pop,
+ { "slot", 1, private },
+ }
+ }
+ end
+ setmetatableindex(new_c,old_c)
+ characters[unicode] = new_c
+ additions[private] = old_c
+ end
+ for k, v in next, additions do
+ characters[k] = v
+ end
+ resources.private = private
+ end
+end
+
+registerotffeature {
+ name = "boundingbox",
+ description = "show boundingbox",
+ manipulators = {
+ base = showboundingbox,
+ node = showboundingbox,
+ }
+}
+
-- -- historic stuff, move from font-ota (handled differently, typo-rep)
--
-- local delete_node = nodes.delete
@@ -651,3 +872,63 @@ registerafmfeature {
-- node = processformatters,
-- }
-- }
+
+-- a handy helper (might change or be moved to another namespace)
+
+local new_special = nodes.pool.special
+local new_glyph = nodes.pool.glyph
+local hpack_node = node.hpack
+
+function fonts.helpers.addprivate(tfmdata,name,characterdata)
+ local properties = tfmdata.properties
+ local privates = properties.privates
+ local lastprivate = properties.lastprivate
+ if lastprivate then
+ lastprivate = lastprivate + 1
+ else
+ lastprivate = 0xE000
+ end
+ if not privates then
+ privates = { }
+ properties.privates = privates
+ end
+ privates[name] = lastprivate
+ properties.lastprivate = lastprivate
+ tfmdata.characters[lastprivate] = characterdata
+ if properties.finalized then
+ properties.lateprivates = true
+ end
+ return lastprivate
+end
+
+function fonts.helpers.getprivatenode(tfmdata,name)
+ local properties = tfmdata.properties
+ local privates = properties and properties.privates
+ if privates then
+ local p = privates[name]
+ if p then
+ local char = tfmdata.characters[p]
+ local commands = char.commands
+ if commands then
+ local fake = hpack_node(new_special(commands[1][2]))
+ fake.width = char.width
+ fake.height = char.height
+ fake.depth = char.depth
+ return fake
+ else
+ -- todo: set current attribibutes
+ return new_glyph(properties.id,p)
+ end
+ end
+ end
+end
+
+function fonts.helpers.hasprivate(tfmdata,name)
+ local properties = tfmdata.properties
+ local privates = properties and properties.privates
+ return privates and privates[name] or false
+end
+
+function commands.getprivatechar(name)
+ context(fonts.helpers.getprivatenode(fontdata[font.current()],name))
+end
diff --git a/Master/texmf-dist/tex/context/base/font-fbk.lua b/Master/texmf-dist/tex/context/base/font-fbk.lua
index 6712fbe888e..89831e7c2a0 100644
--- a/Master/texmf-dist/tex/context/base/font-fbk.lua
+++ b/Master/texmf-dist/tex/context/base/font-fbk.lua
@@ -10,11 +10,13 @@ local cos, tan, rad, format = math.cos, math.tan, math.rad, string.format
local utfbyte, utfchar = utf.byte, utf.char
local trace_combining = false trackers.register("fonts.combining", function(v) trace_combining = v end)
-local trace_combining_all = false trackers.register("fonts.combining.all", function(v) trace_combining_all = v end)
+local trace_combining_all = false trackers.register("fonts.combining.all", function(v) trace_combining = v
+ trace_combining_all = v end)
local force_combining = false -- just for demo purposes (see mk)
-trackers.register("fonts.composing", "fonts.combining")
+trackers.register("fonts.composing", "fonts.combining")
+trackers.register("fonts.composing.all", "fonts.combining.all")
local report_combining = logs.reporter("fonts","combining")
@@ -71,7 +73,7 @@ local function composecharacters(tfmdata)
report_combining("using compose information from goodies file")
end
local done = false
- for i,c in next, unicodecharacters do -- loop over all characters ... not that efficient but a specials hash takes memory
+ for i, c in next, unicodecharacters do -- loop over all characters ... not that efficient but a specials hash takes memory
if force_combining or not characters[i] then
local s = c.specials
if s and s[1] == 'char' then
@@ -118,57 +120,104 @@ local function composecharacters(tfmdata)
local ab = descriptions[acc].boundingbox
-- todo: adapt height
if cb and ab then
- -- can be sped up for scale == 1
local c_llx, c_lly, c_urx, c_ury = scale*cb[1], scale*cb[2], scale*cb[3], scale*cb[4]
local a_llx, a_lly, a_urx, a_ury = scale*ab[1], scale*ab[2], scale*ab[3], scale*ab[4]
- local dx = (c_urx - a_urx - a_llx + c_llx)/2
- local dd = (c_urx - c_llx)*italicfactor
- if a_ury < 0 then
- if trace_combining then
- t.commands = { push, {"right", dx-dd}, red, acc_t, black, pop, chr_t }
- else
- t.commands = { push, {"right", dx-dd}, acc_t, pop, chr_t }
+ local done = false
+ if compose then
+ local i_compose = compose[i]
+ local i_anchored = i_compose and i_compose.anchored
+ if i_anchored then
+ local c_compose = compose[chr]
+ local a_compose = compose[acc]
+ local c_anchors = c_compose and c_compose.anchors
+ local a_anchors = a_compose and a_compose.anchors
+ if c_anchors and a_anchors then
+ local c_anchor = c_anchors[i_anchored]
+ local a_anchor = a_anchors[i_anchored]
+ if c_anchor and a_anchor then
+ local cx = c_anchor.x or 0
+ local cy = c_anchor.y or 0
+ local ax = a_anchor.x or 0
+ local ay = a_anchor.y or 0
+ local dx = cx - ax
+ local dy = cy - ay
+ if trace_combining_all then
+ report_combining("building U+%05X (%s) from U+%05X (%s) and U+%05X (%s)",i,utfchar(i),chr,utfchar(chr),acc,utfchar(acc))
+ report_combining(" boundingbox:")
+ report_combining(" chr: %3i %3i %3i %3i",unpack(cb))
+ report_combining(" acc: %3i %3i %3i %3i",unpack(ab))
+ report_combining(" anchors:")
+ report_combining(" chr: %3i %3i",cx,cy)
+ report_combining(" acc: %3i %3i",ax,ay)
+ report_combining(" delta:")
+ report_combining(" %s: %3i %3i",i_anchored,dx,dy)
+ end
+ if trace_combining then
+ t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, green, acc_t, black, pop, chr_t }
+ -- t.commands = {
+ -- push, {"right", scale*cx}, {"down", -scale*cy}, red, {"rule",10000,10000,10000}, pop,
+ -- push, {"right", scale*ax}, {"down", -scale*ay}, blue, {"rule",10000,10000,10000}, pop,
+ -- push, {"right", scale*dx}, {"down", -scale*dy}, green, acc_t, black, pop, chr_t
+ -- }
+ else
+ t.commands = { push, {"right", scale*dx}, {"down",-scale*dy}, acc_t, pop, chr_t }
+ end
+ done = true
+ end
+ end
end
- elseif c_ury > a_lly then -- messy test
- local dy
- if compose then
- -- experimental: we could use sx but all that testing
- -- takes time and code
- dy = compose[i]
- if dy then
- dy = dy.DY
+ end
+ if not done then
+ -- can be sped up for scale == 1
+ local dx = (c_urx - a_urx - a_llx + c_llx)/2
+ local dd = (c_urx - c_llx)*italicfactor
+ if a_ury < 0 then
+ if trace_combining then
+ t.commands = { push, {"right", dx-dd}, red, acc_t, black, pop, chr_t }
+ else
+ t.commands = { push, {"right", dx-dd}, acc_t, pop, chr_t }
end
- if not dy then
- dy = compose[acc]
+ elseif c_ury > a_lly then -- messy test
+ local dy
+ if compose then
+ -- experimental: we could use sx but all that testing
+ -- takes time and code
+ dy = compose[i]
if dy then
- dy = dy and dy.DY
+ dy = dy.DY
end
- end
- if not dy then
- dy = compose.DY
- end
- if not dy then
+ if not dy then
+ dy = compose[acc]
+ if dy then
+ dy = dy and dy.DY
+ end
+ end
+ if not dy then
+ dy = compose.DY
+ end
+ if not dy then
+ dy = - deltaxheight + extraxheight
+ elseif dy > -1.5 and dy < 1.5 then
+ -- we assume a fraction of (percentage)
+ dy = - dy * deltaxheight
+ else
+ -- we assume fontunits (value smaller than 2 make no sense)
+ dy = - dy * scale
+ end
+ else
dy = - deltaxheight + extraxheight
- elseif dy > -1.5 and dy < 1.5 then
- -- we assume a fraction of (percentage)
- dy = - dy * deltaxheight
+ end
+ if trace_combining then
+ t.commands = { push, {"right", dx+dd}, {"down", dy}, green, acc_t, black, pop, chr_t }
else
- -- we assume fontunits (value smaller than 2 make no sense)
- dy = - dy * scale
+ t.commands = { push, {"right", dx+dd}, {"down", dy}, acc_t, pop, chr_t }
end
else
- dy = - deltaxheight + extraxheight
- end
- if trace_combining then
- t.commands = { push, {"right", dx+dd}, {"down", dy}, green, acc_t, black, pop, chr_t }
- else
- t.commands = { push, {"right", dx+dd}, {"down", dy}, acc_t, pop, chr_t }
- end
- else
- if trace_combining then
- t.commands = { push, {"right", dx+dd}, blue, acc_t, black, pop, chr_t }
- else
- t.commands = { push, {"right", dx+dd}, acc_t, pop, chr_t }
+ if trace_combining then
+ t.commands = { push, {"right", dx+dd}, blue, acc_t, black, pop, chr_t }
+ else
+ t.commands = { push, {"right", dx+dd}, acc_t, pop, chr_t }
+ end
end
end
else
diff --git a/Master/texmf-dist/tex/context/base/font-fea.mkvi b/Master/texmf-dist/tex/context/base/font-fea.mkvi
new file mode 100644
index 00000000000..969e955759e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-fea.mkvi
@@ -0,0 +1,189 @@
+%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}
+
+\unexpanded\def\definefontfeature
+ {\dotripleargument\font_basics_define_font_feature}
+
+\def\font_basics_define_font_feature[#featureset][#parent][#settings]%
+ {\ctxcommand{definefontfeature("#featureset","#parent","#settings")}}
+
+\unexpanded\def\fontfeatureslist
+ {\dodoubleargument\font_basics_features_list}
+
+\def\font_basics_features_list[#name][#separator]% todo: arg voor type
+ {\cldcommand{featurelist("#name","otf","\luaescapestring{#separator}","yes","no",true,{"number"})}}
+
+\attribute\zerocount\zerocount % first in list, so fast match
+
+\let\currentfeature\empty
+
+% ! ! ! very experimental, some test code for idris advanced features ! ! !
+%
+% \startbuffer
+% \definefontfeature[smallcaps][smallcaps][script=latn]
+% \definefontfeature[oldstyle] [oldstyle] [script=latn]
+%
+% \definedfont[name:cambria at 15pt]
+%
+% Hello there {\setff{smallcaps}capped 123 \setff{oldstyle}123!} \blank
+% Hello there {\addff{smallcaps}capped 123 \addff{oldstyle}123!} \blank
+% Hello there {\addff{smallcaps}capped \subff{smallcaps}normal} \blank
+% \stopbuffer
+%
+% \typebuffer \getbuffer
+
+\unexpanded\def\featureattribute#feature{\ctxcommand{featureattribute("#feature")}}
+\unexpanded\def\setfontfeature #feature{\ctxcommand{setfontfeature("#feature")}\edef\currentfeature{#feature}}
+%unexpanded\def\resetfontfeature {\ctxcommand{resetfontfeature()}\let\currentfeature\empty} % initial value
+\unexpanded\def\resetfontfeature {\attribute\zerocount\zerocount \let\currentfeature\empty} % initial value
+
+\unexpanded\def\addfontfeaturetoset #feature{\ctxcommand{addfs("#feature")}} % merge
+\unexpanded\def\subtractfontfeaturefromset #feature{\ctxcommand{subfs("#feature")}} % merge
+\unexpanded\def\addfontfeaturetofont #feature{\ctxcommand{addff("#feature")}} % overload
+\unexpanded\def\subtractfontfeaturefromfont#feature{\ctxcommand{subff("#feature")}} % overload
+
+\let\setff\setfontfeature
+\let\addfs\addfontfeaturetoset
+\let\subfs\subtractfontfeaturefromset
+\let\addff\addfontfeaturetofont
+\let\subff\subtractfontfeaturefromfont
+
+%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]
+
+%unexpanded\def\sc{\setfontfeature{smallcaps}}
+\unexpanded\def\os{\setfontfeature{just-os}}
+
+% \doifelsecurrentfonthasfeature{smcp}{YES}{NO}
+% \doifelsecurrentfonthasfeature{crap}{YES}{NO}
+% \doifelsecurrentfonthasfeature{kern}{YES}{NO}
+
+\def\doifelsecurrentfonthasfeature#feature%
+ {\ctxcommand{doifelsecurrentfonthasfeature("#feature")}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-fil.mkvi b/Master/texmf-dist/tex/context/base/font-fil.mkvi
new file mode 100644
index 00000000000..dcb298619e6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-fil.mkvi
@@ -0,0 +1,391 @@
+%D \module
+%D [ file=font-fil,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Classes and Files,
+%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 / Classes and Files}
+
+\unprotect
+
+%D Personally I think that using \TEX\ macro packages is
+%D complicated by the way fonts are handled. Apart from the
+%D many encodings, we also deal with different naming schemes.
+%D Confronted with this problem, I decided to change the
+%D definitions into:
+%D
+%D \starttyping
+%D \definebodyfont [12pt] [rm] [tf=Times-Roman at 12pt]
+%D \stoptyping
+%D
+%D combined with for instance:
+%D
+%D \starttyping
+%D \definefontsynonym [Times-Roman] [tir]
+%D \stoptyping
+
+% \definetypeface[palatino][rm][serif][palatino,allbold][default]
+%
+% \startfontclass[palatino]
+% \definefontsynonym [Serif] [SerifBold]
+% \definefontsynonym [SerifItalic] [SerifBoldItalic]
+% \definefontsynonym [SerifSlanted] [SerifBoldSlanted]
+% \definefontsynonym [SerifCaps] [SerifBold]
+% \stopfontclass
+%
+% \setupbodyfont[palatino]
+
+\let\fontclass\empty
+
+\unexpanded\def\startfontclass
+ {\dosingleempty\font_basics_start_font_class}
+
+\def\font_basics_start_font_class[#class]%
+ {\pushmacro\fontclass
+ \doifelse{#class}\v!each
+ {\let\fontclass\empty}
+ {\doifsomething{#class}{\def\fontclass{#class}}}}
+
+\unexpanded\def\stopfontclass
+ {\popmacro\fontclass}
+
+\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
+%D \starttyping
+%D \definefontsynonym[Serif][Lucida-Bright]
+%D \definefontsynonym[Lucida-Bright][lbr][encoding=texnansi]
+%D \stoptyping
+
+\installcorenamespace {fontfile} % file synonyms
+
+\let\m_font_name\empty
+\let\m_font_file\empty
+
+\def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone
+\edef\nullfontname {\fontname\nullfont}
+
+\unexpanded\def\definefontsynonym[#name]#crap[#file]%
+ {\edef\m_font_name{#name}%
+ \edef\m_font_file{#file}%
+ \ifx\fontclass\empty
+ \expandafter\font_basics_define_font_synonym_nop
+ \else
+ \expandafter\font_basics_define_font_synonym_yes
+ \fi}
+
+\def\font_basics_define_font_synonym_nop
+ {\expandafter\let\csname\??fontfile\m_font_name\endcsname\m_font_file
+ \doifnextoptionalelse\font_basics_define_font_synonym_nop_opt\font_basics_define_font_synonym_nop_nil}
+
+\def\font_basics_define_font_synonym_yes
+ {\expandafter\let\csname\??fontfile\fontclass\m_font_name\endcsname\m_font_file
+ \doifnextoptionalelse\font_basics_define_font_synonym_yes_opt\font_basics_define_font_synonym_yes_nil}
+
+\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,]=,}
+
+\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,]=,}
+
+\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}%
+ \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}%
+ \expandafter\font_basics_get_font_parameter_yes
+ \fi}
+
+% helpers, some day these will be toks and counts
+
+% \def\fntsetdefname {\global\let\somefontname\defaultfontfile}
+% \def\fntsetsomename{\gdef\somefontname} % takes argument
+% \def\fntsetnopsize {\let\somefontsize\empty}
+% \def\fntsetsomesize{\def\somefontsize} % takes argument
+
+% happens later, else mkvi parsing gets into troubles
+
+% end of helpers
+
+% we could collect them in one macro (but no expansion)
+
+\def\font_basics_define_font_synonym_nop_nil
+ {\expandafter\let\csname\??fontfile\m_font_name\s!features \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!fallbacks \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!goodies \endcsname\undefined
+ \expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\undefined}
+
+\def\font_basics_define_font_synonym_yes_nil
+ {\global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\undefined
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\undefined
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\undefined
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!designsize\endcsname\undefined}
+
+\def\font_basics_get_font_parameter_nop_finish
+ {\expandafter\let\csname\??fontfile\m_font_name\s!features \endcsname\p_features
+ \expandafter\let\csname\??fontfile\m_font_name\s!fallbacks \endcsname\p_fallbacks
+ \expandafter\let\csname\??fontfile\m_font_name\s!goodies \endcsname\p_goodies
+ \expandafter\let\csname\??fontfile\m_font_name\s!designsize\endcsname\p_designsize}
+
+\def\font_basics_get_font_parameter_yes_finish
+ {\global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!features \endcsname\p_features
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!fallbacks \endcsname\p_fallbacks
+ \global\expandafter\let\csname\??fontfile\fontclass\m_font_name\s!goodies \endcsname\p_goodies
+ \global\expandafter\let\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
+ {\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}
+
+\def\dosetupfontsynonym[#name][#settings]% not yet supported, will do when needed
+ {}
+
+% todo: replace * by ... less messy with features
+
+\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\csname\??fontfile\fontclass#name\endcsname
+ \else
+ \expandafter\font_helpers_true_fontname_check\csname\??fontfile\fontclass#name\endcsname*#first#rest%
+ \fi
+ \else\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ \ifx#first\empty
+ \expandafter\truefontname\csname\??fontfile\defaultfontclass#name\endcsname
+ \else
+ \expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname*#first#rest%
+ \fi
+ \else\ifcsname\??fontfile#name\endcsname
+ \ifx#first\empty
+ \expandafter\truefontname\csname\??fontfile#name\endcsname
+ \else
+ \expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname*#first#rest%
+ \fi
+ \else
+ #name\ifx#first\empty\else*#first#rest\fi
+ \fi\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\csname\??fontfile\fontclass#name\endcsname
+ \else\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ \expandafter\font_helpers_true_fontname_check\csname\??fontfile\defaultfontclass#name\endcsname
+ \else\ifcsname\??fontfile#name\endcsname
+ \expandafter\font_helpers_true_fontname_check\csname\??fontfile#name\endcsname
+ \else
+ #name%
+ \fi\fi\fi}
+
+\def\expandfontsynonym#command#name% one level expansion
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ \expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\fontclass#name\endcsname}%
+ \else\ifcsname\??fontfile\defaultfontclass#2\endcsname
+ \expandafter\normaldef\expandafter#command\expandafter{\csname\??fontfile\defaultfontclass#name\endcsname}%
+ \fi\fi}
+
+\def\doifelsefontsynonym#name%
+ {\ifcsname\??fontfile\fontclass#name\endcsname
+ \singleexpandafter\firstoftwoarguments
+ \else\ifcsname\??fontfile\defaultfontclass#name\endcsname
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+%D \macros
+%D {tracedfontname}
+%D
+%D A goody:
+
+\def\tracedfontname#name%
+ {#name\ifcsname\??fontfile\fontclass#name\endcsname
+ \expandafter\tracedfontname\csname\??fontfile\fontclass#name\endcsname
+ \else\ifcsname\??fontfile#name\endcsname
+ \expandafter\tracedfontname\csname\??fontfile#name\endcsname
+ \fi\fi}
+
+%D \macros
+%D {fontclass, defaultfontclass}
+%D
+%D The fontclass model was introduced a while after we implement
+%D the basic font model and at that time we still defaulted to
+%D no model at all. Nowadays we default to the \type {modern}
+%D fontclass.
+
+\let\fontclass \empty
+\let\defaultfontclass\empty
+
+\def\fontclassname#class#name%
+ {\ifcsname\??fontfile#class#name\endcsname
+ \fontclassname{#class}{\csname\??fontfile#class#name\endcsname}%
+ \else\ifcsname\??fontfile#name\endcsname
+ \fontclassname{#class}{\csname\??fontfile#name\endcsname}%
+ \else
+ #2%
+ \fi\fi}
+
+%D Files or names can have properties and these need to be consulted
+%D at some point. 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.
+
+\def\font_helpers_update_font_class_parameters
+ {\edef\m_font_class_direction {\ifcsname\??fontclass\fontclass\fontstyle\s!direction \endcsname\csname\??fontclass\fontclass\fontstyle\s!direction \endcsname\fi}%
+ \edef\m_font_class_features {\ifcsname\??fontclass\fontclass\fontstyle\s!features \endcsname\csname\??fontclass\fontclass\fontstyle\s!features \endcsname\fi}%
+ \edef\m_font_class_fallbacks {\ifcsname\??fontclass\fontclass\fontstyle\s!fallbacks \endcsname\csname\??fontclass\fontclass\fontstyle\s!fallbacks \endcsname\fi}%
+ \edef\m_font_class_goodies {\ifcsname\??fontclass\fontclass\fontstyle\s!goodies \endcsname\csname\??fontclass\fontclass\fontstyle\s!goodies \endcsname\fi}%
+ \edef\m_font_class_designsize{\ifcsname\??fontclass\fontclass\fontstyle\s!designsize\endcsname\csname\??fontclass\fontclass\fontstyle\s!designsize\endcsname\fi}}
+
+% resolve
+
+\def\font_helpers_set_features_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!features \endcsname\expandafter\let\expandafter\m_font_features % class + symbolic_name
+ \csname\??fontfile\fontclass#name\s!features \endcsname\else
+ \ifcsname\??fontfile #name\s!features \endcsname\expandafter\let\expandafter\m_font_features % symbolic_name
+ \csname\??fontfile #name\s!features \endcsname\else
+ \ifcsname\??fontfile\fontclass #name\endcsname\expandafter\font_helpers_set_features_yes % class + parent_name
+ \csname\??fontfile\fontclass #name\endcsname\else
+ \ifcsname\??fontfile #name\endcsname\expandafter\font_helpers_set_features_yes % parent_name
+ \csname\??fontfile #name\endcsname\else
+ \let\m_font_features\empty\fi\fi\fi\fi}
+
+\def\font_helpers_set_fallbacks_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!fallbacks\endcsname\expandafter\let\expandafter\m_font_fallbacks
+ \csname\??fontfile\fontclass#name\s!fallbacks\endcsname\else
+ \ifcsname\??fontfile #name\s!fallbacks\endcsname\expandafter\let\expandafter\m_font_fallbacks
+ \csname\??fontfile #name\s!fallbacks\endcsname\else
+ \ifcsname\??fontfile\fontclass #name\endcsname\expandafter\font_helpers_set_fallbacks_yes
+ \csname\??fontfile\fontclass #name\endcsname\else
+ \ifcsname\??fontfile #name\endcsname\expandafter\font_helpers_set_fallbacks_yes
+ \csname\??fontfile #name\endcsname\else
+ \let\m_font_fallbacks\empty\fi\fi\fi\fi}
+
+\def\font_helpers_set_goodies_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!goodies \endcsname\expandafter\let\expandafter\m_font_goodies
+ \csname\??fontfile\fontclass#name\s!goodies \endcsname\else
+ \ifcsname\??fontfile #name\s!goodies \endcsname\expandafter\let\expandafter\m_font_goodies
+ \csname\??fontfile #name\s!goodies \endcsname\else
+ \ifcsname\??fontfile\fontclass #name\endcsname\expandafter\font_helpers_set_goodies_yes
+ \csname\??fontfile\fontclass #name\endcsname\else
+ \ifcsname\??fontfile #name\endcsname\expandafter\font_helpers_set_goodies_yes
+ \csname\??fontfile #name\endcsname\else
+ \let\m_font_goodies\empty\fi\fi\fi\fi}
+
+\def\font_helpers_set_designsize_yes#name%
+ {\ifcsname\??fontfile\fontclass#name\s!designsize\endcsname\expandafter\let\expandafter\m_font_designsize
+ \csname\??fontfile\fontclass#name\s!designsize\endcsname\else
+ \ifcsname\??fontfile #name\s!designsize\endcsname\expandafter\let\expandafter\m_font_designsize
+ \csname\??fontfile #name\s!designsize\endcsname\else
+ \ifcsname\??fontfile\fontclass #name\endcsname\expandafter\font_helpers_set_designsize_yes
+ \csname\??fontfile\fontclass #name\endcsname\else
+ \ifcsname\??fontfile #name\endcsname\expandafter\font_helpers_set_designsize_yes
+ \csname\??fontfile #name\endcsname\else
+ \let\m_font_designsize\empty\fi\fi\fi\fi}
+
+\def\font_helpers_set_features_nop#name%
+ {\ifcsname\??fontfile#name\s!features \endcsname\expandafter\let\expandafter\m_font_features
+ \csname\??fontfile#name\s!features \endcsname\else
+ \ifcsname\??fontfile #name\endcsname\expandafter\font_helpers_set_features_nop
+ \csname\??fontfile #name\endcsname\else
+ \let\m_font_features\empty\fi\fi}
+
+\def\font_helpers_set_fallbacks_nop#name%
+ {\ifcsname\??fontfile#name\s!fallbacks\endcsname\expandafter\let\expandafter\m_font_fallbacks
+ \csname\??fontfile#name\s!fallbacks\endcsname\else
+ \ifcsname\??fontfile #name\endcsname\expandafter\font_helpers_set_fallbacks_nop
+ \csname\??fontfile #name\endcsname\else
+ \let\m_font_fallbacks\empty\fi\fi}
+
+\def\font_helpers_set_goodies_nop#name%
+ {\ifcsname\??fontfile#name\s!goodies \endcsname\expandafter\let\expandafter\m_font_goodies
+ \csname\??fontfile#name\s!goodies \endcsname\else
+ \ifcsname\??fontfile #name\endcsname\expandafter\font_helpers_set_goodies_nop
+ \csname\??fontfile #name\endcsname\else
+ \let\m_font_goodies\empty\fi\fi}
+
+\def\font_helpers_set_designsize_nop#name%
+ {\ifcsname\??fontfile#name\s!designsize\endcsname\expandafter\let\expandafter\m_font_designsize
+ \csname\??fontfile#name\s!designsize\endcsname\else
+ \ifcsname\??fontfile #name\endcsname\expandafter\font_helpers_set_designsize_nop
+ \csname\??fontfile #name\endcsname\else
+ \let\m_font_designsize\empty\fi\fi}
+
+\def\font_helpers_update_font_parameters_yes
+ {\font_helpers_set_features_yes \somefontname
+ \font_helpers_set_fallbacks_yes \somefontname
+ \font_helpers_set_goodies_yes \somefontname
+ \font_helpers_set_designsize_yes\somefontname}
+
+\def\font_helpers_update_font_parameters_nop
+ {\font_helpers_set_features_nop \somefontname
+ \font_helpers_set_fallbacks_nop \somefontname
+ \font_helpers_set_goodies_nop \somefontname
+ \font_helpers_set_designsize_nop\somefontname}
+
+\def\font_helpers_update_font_parameters
+ {\ifx\fontclass\empty\font_helpers_update_font_parameters_nop\else\font_helpers_update_font_parameters_yes\fi}
+
+\installcorenamespace{fontclass}
+
+% we can pack them
+
+\unexpanded\def\savefontclassparameters#style#rscale#features#fallbacks#goodies#designsize#direction%
+ {\setxvalue{\??fontclass\fontclass#style\s!rscale }{#rscale}%
+ \setxvalue{\??fontclass\fontclass#style\s!features }{#features}%
+ \setxvalue{\??fontclass\fontclass#style\s!fallbacks }{#fallbacks}%
+ \setxvalue{\??fontclass\fontclass#style\s!goodies }{#goodies}%
+ \setxvalue{\??fontclass\fontclass#style\s!designsize}{#designsize}%
+ \setxvalue{\??fontclass\fontclass#style\s!direction }{#direction}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-gds.lua b/Master/texmf-dist/tex/context/base/font-gds.lua
index a5c60d252ab..3b87e4c772b 100644
--- a/Master/texmf-dist/tex/context/base/font-gds.lua
+++ b/Master/texmf-dist/tex/context/base/font-gds.lua
@@ -9,12 +9,16 @@ if not modules then modules = { } end modules ['font-gds'] = {
-- depends on ctx
local type, next = type, next
-local gmatch, format = string.gmatch, string.format
+local gmatch, format, lower, find, splitup = string.gmatch, string.format, string.lower, string.find, string.splitup
+local texsp = tex.sp
local fonts, nodes, attributes, node = fonts, nodes, attributes, node
-local trace_goodies = false trackers.register("fonts.goodies", function(v) trace_goodies = v end)
-local report_fonts = logs.reporter("fonts","goodies")
+local trace_goodies = false
+
+trackers.register("fonts.goodies", function(v) trace_goodies = v end)
+
+local report_goodies = logs.reporter("fonts","goodies")
local allocate = utilities.storage.allocate
@@ -46,12 +50,12 @@ function fontgoodies.report(what,trace,goodies)
if trace_goodies or trace then
local whatever = goodies[what]
if whatever then
- report_fonts("goodie '%s' found in '%s'",what,goodies.name)
+ report_goodies("goodie '%s' found in '%s'",what,goodies.name)
end
end
end
-local function getgoodies(filename) -- maybe a merge is better
+local function loadgoodies(filename) -- maybe a merge is better
local goodies = data[filename] -- we assume no suffix is given
if goodies ~= nil then
-- found or tagged unfound
@@ -61,15 +65,15 @@ local function getgoodies(filename) -- maybe a merge is better
fullname = resolvers.findfile(file.addsuffix(filename,"lua")) or "" -- fallback suffix
end
if fullname == "" then
- report_fonts("goodie file '%s.lfg' is not found",filename)
+ report_goodies("goodie file '%s.lfg' is not found",filename)
data[filename] = false -- signal for not found
else
goodies = dofile(fullname) or false
if not goodies then
- report_fonts("goodie file '%s' is invalid",fullname)
+ report_goodies("goodie file '%s' is invalid",fullname)
return nil
elseif trace_goodies then
- report_fonts("goodie file '%s' is loaded",fullname)
+ report_goodies("goodie file '%s' is loaded",fullname)
end
goodies.name = goodies.name or "no name"
for name, fnc in next, list do
@@ -86,7 +90,7 @@ function fontgoodies.register(name,fnc) -- will be a proper sequencer
list[name] = fnc
end
-fontgoodies.get = getgoodies
+fontgoodies.load = loadgoodies
-- register goodies file
@@ -98,8 +102,11 @@ local function setgoodies(tfmdata,value)
end
for filename in gmatch(value,"[^, ]+") do
-- we need to check for duplicates
- local ok = getgoodies(filename)
+ local ok = loadgoodies(filename)
if ok then
+ if trace_goodies then
+ report_goodies("assigning goodie '%s'",filename)
+ end
goodies[#goodies+1] = ok
end
end
@@ -141,7 +148,7 @@ function fontgoodies.prepare_features(goodies,name,set)
local n, s = fonts.specifiers.presetcontext(fullname,"",ff)
goodies.featuresets[name] = s -- set
if trace_goodies then
- report_fonts("feature set '%s' gets number %s and name '%s'",name,n,fullname)
+ report_goodies("feature set '%s' gets number %s and name '%s'",name,n,fullname)
end
return n
end
@@ -152,7 +159,7 @@ local function initialize(goodies,tfmdata)
local goodiesname = goodies.name
if featuresets then
if trace_goodies then
- report_fonts("checking featuresets in '%s'",goodies.name)
+ report_goodies("checking featuresets in '%s'",goodies.name)
end
for name, set in next, featuresets do
fontgoodies.prepare_features(goodies,name,set)
@@ -162,14 +169,13 @@ end
fontgoodies.register("featureset",initialize)
-local function setfeatureset(tfmdata,set)
+local function setfeatureset(tfmdata,set,features)
local goodies = tfmdata.goodies -- shared ?
if goodies then
- local features = tfmdata.shared.features
local properties = tfmdata.properties
local what
for i=1,#goodies do
- -- last one counts
+ -- last one wins
local g = goodies[i]
what = (g.featuresets and g.featuresets[set]) or what
end
@@ -179,13 +185,23 @@ local function setfeatureset(tfmdata,set)
features[feature] = value
end
end
- properties.mode = features.mode or properties.mode
+ properties.mode = what.mode or properties.mode
end
end
end
-- postprocessors (we could hash processor and share code)
+function fontgoodies.registerpostprocessor(tfmdata,f,prepend)
+ if not tfmdata.postprocessors then
+ tfmdata.postprocessors = { f }
+ elseif prepend then
+ table.insert(tfmdata.postprocessors,f,1)
+ else
+ table.insert(tfmdata.postprocessors,f)
+ end
+end
+
local function setpostprocessor(tfmdata,processor)
local goodies = tfmdata.goodies
if goodies and type(processor) == "string" then
@@ -204,7 +220,7 @@ local function setpostprocessor(tfmdata,processor)
end
end
end
- local postprocessors = { }
+ local postprocessors = tfmdata.postprocessors or { }
for i=1,#asked do
local a = asked[i]
local f = found[a]
@@ -218,23 +234,6 @@ local function setpostprocessor(tfmdata,processor)
end
end
--- fontgoodies.postprocessors = fontgoodies.postprocessors or { }
--- local postprocessors = fontgoodies.postprocessors
---
--- function postprocessors.apply(tfmdata)
--- local postprocessors = tfmdata.postprocessors
--- if postprocessors then
--- for i=1,#postprocessors do
--- postprocessors[i](tfmdata)
--- end
--- end
--- end
---
--- function definers.applypostprocessors(tfmdata)
--- fonts.goodies.postprocessors.apply(tfmdata) -- only here
--- return tfmdata
--- end
-
-- colorschemes
local colorschemes = { }
@@ -252,17 +251,42 @@ local function setcolorscheme(tfmdata,scheme)
local g = goodies[i]
what = (g.colorschemes and g.colorschemes[scheme]) or what
end
- if what then
+ if type(what) == "table" then
-- this is font bound but we can share them if needed
-- just as we could hash the conversions (per font)
- local hash, reverse = tfmdata.resources.unicodes, { }
+ local hash = tfmdata.resources.unicodes
+ local reverse = { }
+ local characters = tfmdata.characters
for i=1,#what do
local w = what[i]
for j=1,#w do
local name = w[j]
- local unicode = hash[name]
- if unicode then
- reverse[unicode] = i
+ if name == "*" then
+ -- inefficient but only used for tracing anyway
+ for _, unicode in next, hash do
+ reverse[unicode] = i
+ end
+ elseif type(name) == "number" then
+ reverse[name] = i
+ elseif find(name,":") then
+ local start, stop = splitup(name,":")
+ start = tonumber(start)
+ stop = tonumber(stop)
+ if start and stop then
+ -- limited usage: we only deal with non reassigned
+ -- maybe some day I'll also support the ones with a
+ -- tounicode in this range
+ for unicode=start,stop do
+ if characters[unicode] then
+ reverse[unicode] = i
+ end
+ end
+ end
+ else
+ local unicode = hash[name]
+ if unicode then
+ reverse[unicode] = i
+ end
end
end
end
@@ -446,6 +470,89 @@ fontgoodies.register("mathematics", initialize)
-- },
-- }
+-- math italics
+
+-- it would be nice to have a \noitalics\font option
+
+local function initialize(tfmdata)
+ local goodies = tfmdata.goodies
+ if goodies then
+ local shared = tfmdata.shared
+ for i=1,#goodies do
+ local mathgoodies = goodies[i].mathematics
+ local mathitalics = mathgoodies and mathgoodies.italics
+ if mathitalics then
+ local properties = tfmdata.properties
+ mathitalics = mathitalics[file.nameonly(properties.name)] or mathitalics
+ if mathitalics then
+ if trace_goodies then
+ report_goodies("loading mathitalics for font '%s'",properties.name)
+ end
+ local corrections = mathitalics.corrections
+ local defaultfactor = mathitalics.defaultfactor
+ local disableengine = mathitalics.disableengine
+ properties.hasitalics = true
+ properties.mathitalic_defaultfactor = defaultfactor -- we inherit outer one anyway (name will change)
+ if properties.mathitalics == nil then
+ properties.mathitalics = disableengine
+ end
+ if corrections then
+ -- As we want to set italic_correction (the context one) we need a
+ -- postprocessor instead of messing with the (unscaled) descriptions.
+ fontgoodies.registerpostprocessor(tfmdata, function(tfmdata) -- this is another tfmdata (a copy)
+ -- better make a helper so that we have less code being defined
+ local properties = tfmdata.properties
+ local parameters = tfmdata.parameters
+ local characters = tfmdata.characters
+ properties.hasitalics = true
+ properties.mathitalic_defaultfactor = defaultfactor
+ properties.mathitalic_defaultvalue = defaultfactor * parameters.quad
+ if properties.mathitalics == nil then
+ properties.mathitalics = disableengine
+ end
+ if trace_goodies then
+ report_goodies("assigning mathitalics for font '%s'",properties.name)
+ end
+ local mathitalics = properties.mathitalics
+ local quad = parameters.quad
+ local hfactor = parameters.hfactor
+ for k, v in next, corrections do
+ local c = characters[k]
+ if v > -1 and v < 1 then
+ v = v * quad
+ else
+ v = v * hfactor
+ end
+ c.italic_correction = v -- for context
+ if mathitalics then
+ c.italic = v -- for tex
+ else
+ c.italic = nil
+ end
+ end
+ end)
+ end
+ return -- maybe not as these can accumulate
+ end
+ end
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathitalics",
+ description = "additional math italic corrections",
+ -- default = true,
+ initializers = {
+ base = initialize,
+ node = initialize,
+ }
+}
+
+-- fontgoodies.register("mathitalics", initialize)
+
+-- files
+
local function initialize(goodies)
local files = goodies.files
if files then
@@ -498,6 +605,74 @@ end
fontgoodies.register("compositions", initialize)
+local designsizes = { }
+fontgoodies.designsizes = designsizes
+local designdata = allocate()
+designsizes.data = designdata
+
+local function initialize(goodies) -- design sizes are registered global
+ local gd = goodies.designsizes
+ if gd then
+ for name, data in next, gd do
+ local ranges = { }
+ for size, file in next, data do
+ if size ~= "default" then
+ ranges[#ranges+1] = { texsp(size), file } -- also lower(file)
+ end
+ end
+ table.sort(ranges,function(a,b) return a[1] < b[1] end)
+ designdata[lower(name)] = { -- overloads, doesn't merge!
+ default = data.default,
+ ranges = ranges,
+ }
+ end
+ end
+end
+
+fontgoodies.register("designsizes", initialize)
+
+function fontgoodies.designsizes.register(name,size,specification)
+ local d = designdata[name]
+ if not d then
+ d = {
+ ranges = { },
+ default = nil, -- so we have no default set
+ }
+ designdata[name] = d
+ end
+ if size == "default" then
+ d.default = specification
+ else
+ if type(size) == "string" then
+ size = texsp(size)
+ end
+ local ranges = d.ranges
+ ranges[#ranges+1] = { size, specification }
+ end
+end
+
+function fontgoodies.designsizes.filename(name,spec,size) -- returns nil of no match
+ if spec and spec ~= "" then
+ local data = designdata[lower(name)]
+ if data then
+ if spec == "default" then
+ return data.default
+ elseif spec == "auto" then
+ local ranges = data.ranges
+ if ranges then
+ for i=1,#ranges do
+ local r = ranges[i]
+ if r[1] >= size then -- todo: rounding so maybe size - 100
+ return r[2]
+ end
+ end
+ end
+ return data.default or (ranges and ranges[#ranges][2])
+ end
+ end
+ end
+end
+
-- The following file (husayni.lfg) is the experimental setup that we used
-- for Idris font. For the moment we don't store this in the cache and quite
-- probably these files sit in one of the paths:
@@ -507,3 +682,8 @@ fontgoodies.register("compositions", initialize)
-- tex/fonts/data/foundry/collection
--
-- see lfg files in distribution
+
+-- interface
+
+commands.loadfontgoodies = fontgoodies.load
+commands.enablefontcolorschemes = colorschemes.enable
diff --git a/Master/texmf-dist/tex/context/base/font-gds.mkiv b/Master/texmf-dist/tex/context/base/font-gds.mkiv
index 083cd9128ad..2305a0edd3b 100644
--- a/Master/texmf-dist/tex/context/base/font-gds.mkiv
+++ b/Master/texmf-dist/tex/context/base/font-gds.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Colorschemes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -17,9 +17,6 @@
\unprotect
-\def\loadfontgoodies[#1]%
- {\ctxlua{fonts.goodies.get("#1")}}
-
% this will become colorgroups and move to font-col or so
\definecolor[colorscheme:1:1][s=.75]
@@ -40,12 +37,16 @@
\definesystemattribute[colorscheme][public]
-\def\setfontcolorscheme
- {\ctxlua{fonts.goodies.colorschemes.enable()}%
- \xdef\setfontcolorscheme[##1]{\attribute\colorschemeattribute##1\relax}%
+\unexpanded\def\loadfontgoodies[#1]%
+ {\ctxcommand{loadfontgoodies("#1")}}
+
+\unexpanded\def\setfontcolorscheme % will move to the lua end
+ {\ctxcommand{enablefontcolorschemes()}%
+ \unexpanded\xdef\setfontcolorscheme[##1]{\attribute\colorschemeattribute##1\relax}%
\setfontcolorscheme}
-\edef\resetfontcolorscheme{\attribute\colorschemeattribute\attributeunsetvalue}
+\unexpanded\def\resetfontcolorscheme
+ {\attribute\colorschemeattribute\attributeunsetvalue}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-ini.mkii b/Master/texmf-dist/tex/context/base/font-ini.mkii
index 7b84125fa5a..2bee006370f 100644
--- a/Master/texmf-dist/tex/context/base/font-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/font-ini.mkii
@@ -6,7 +6,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-ini.mkiv b/Master/texmf-dist/tex/context/base/font-ini.mkiv
deleted file mode 100644
index 1c9cdcd321a..00000000000
--- a/Master/texmf-dist/tex/context/base/font-ini.mkiv
+++ /dev/null
@@ -1,4414 +0,0 @@
-%D \module
-%D [ file=font-ini,
-%D version=1998.09.11, % (second)
-%D version=2001.02.20, % (third)
-%D title=\CONTEXT\ Font Macros,
-%D subtitle=Initialization,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-% runtime commands will move to modules
-
-% todo: (so that we can delay font loading to \starttext
-
-% simplification ... we no longer deal with specific mmtfa specifications
-
-% todo: always fontclass, then less testing
-% todo: bodyfontvariable: parent
-
-% \definefontfeature[smallcaps][smcp=yes,script=latn]
-% \definefontfeature[smallcaps][SmallCapitals=yes,script=latn]
-% \definefontfeature[smallcaps][Small Capitals=yes,script=latn]
-% \definefontfeature[smallcaps][small capitals=yes,script=latn]
-% \definefontfeature[smallcaps][smallcapitals=yes,script=latn]
-%
-% \definedfont[cambria*smallcaps] test
-
-% \starttext
-% \definefontfeature[basekerned][default][mode=base]
-% \definefontfeature[nodekerned][default][mode=node]
-% \definefontfeature[nonekerned][default][mode=base,kern=no]
-% \setupcolors[state=start]
-% \startoverlay
-% {\vbox{\red \definedfont[Serif*nonekerned at 12pt]\input tufte }}
-% {\vbox{\blue \definedfont[Serif*basekerned at 12pt]\input tufte }}
-% {\vbox{\green\definedfont[Serif*nodekerned at 12pt]\input tufte }}
-% \stopoverlay
-% \stoptext
-
-% \enabletrackers[otf.kerns]
-%
-% \definefontfeature[withkern][default][mode=node]
-% \definefontfeature[nokern] [default][mode=node,kern=no]
-% \definefontfeature[single] [default][mode=node,cpsp=yes]
-% \definefontfeature[simple] [default][mode=node,cpsp=yes,kern=no]
-%
-% {\definedfont[Serif*default] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
-% {\definedfont[Serif*nokern] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
-% {\definedfont[Serif*single] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
-% {\definedfont[Serif*simple] [FGFGFGFGFGFGFGFGFGFGFGFGFG ABCDEFGHIJKLMNOPQRSTUVWXYZ] \par}
-
-% figure out why \fontbody is not expanded
-
-\writestatus{loading}{ConTeXt Font Macros / Initialization}
-
-\registerctxluafile{font-ini}{1.001}
-\registerctxluafile{font-log}{1.001}
-\registerctxluafile{font-con}{1.001}
-\registerctxluafile{font-enc}{1.001}
-%registerctxluafile{font-agl}{1.001} % loaded when needed, saves 100K in format
-\registerctxluafile{font-cid}{1.001} % cid maps
-\registerctxluafile{font-map}{1.001}
-\registerctxluafile{font-syn}{1.001}
-
-\registerctxluafile{font-tfm}{1.001}
-
-\registerctxluafile{font-afm}{1.001}
-
-\registerctxluafile{font-oti}{1.001} % otf initialization
-\registerctxluafile{font-ott}{1.001} % otf tables (first)
-\registerctxluafile{font-otf}{1.001} % otf main
-\registerctxluafile{font-otb}{1.001} % otf main base
-\registerctxluafile{node-inj}{1.001} % we might split it off
-\registerctxluafile{font-otn}{1.001} % otf main node
-\registerctxluafile{font-otd}{1.001} % otf dynamics (does an overload)
-\registerctxluafile{font-ota}{1.001} % otf analyzers (needs dynamics)
-\registerctxluafile{font-otp}{1.001} % otf pack
-\registerctxluafile{font-otc}{1.001} % otf context
-\registerctxluafile{font-oth}{1.001} % otf helpers
-
-\registerctxluafile{font-pat}{1.001} % patchers
-
-\registerctxluafile{node-fnt}{1.001} % here
-
-\registerctxluafile{font-lua}{1.001}
-
-\registerctxluafile{font-vf} {1.001}
-\registerctxluafile{font-enh}{1.001}
-
-\registerctxluafile{font-gds}{1.001} % currently only otf
-
-\registerctxluafile{font-def}{1.001}
-\registerctxluafile{font-ctx}{1.001} % after def as it overloads
-
-\registerctxluafile{font-ext}{1.001}
-\registerctxluafile{font-fbk}{1.001}
-\registerctxluafile{font-chk}{1.001}
-
-\registerctxluafile{font-aux}{1.001}
-
-\unprotect
-
-% \def\fontrange#1%
-% {\dofontrange{#1 =\bodyfontsize}}
-%
-% \def\dofontrange#1%
-% {\dodofontrange#1 \relax}% \fontstringA
-%
-% \def\dodofontrange#1 #2 %
-% {\ifdim\bodyfontsize#2%
-% #1\expandafter\gobbleuntilrelax
-% \else
-% \expandafter\dodofontrange
-% \fi}
-%
-% \definefont
-% [crap]
-% [\fontrange
-% {Regular <10pt
-% RegularBold <12pt
-% RegularSlanted <15pt
-% Regular} sa 1]
-%
-% may be better:
-%
-% \definefontrange
-% [crap]
-% [Regular <10pt
-% RegularBold <12pt
-% RegularSlanted <15pt]
-% [Regular sa 1]
-%
-%
-% \dostepwiserecurse{2}{15}{1}
-% {{\switchtobodyfont[\recurselevel pt]\crap test}\endgraf}
-
-% adapted, else wrong interlinespace
-
-\def\setfontparameters
- {\synchronizefontsfalse
- \the\everybodyfont
- \synchronizefontstrue}
-
-% handy
-
-\newcounter\pushedfont
-
-\def\savefont
- {\edef\savedfont{\the\font}%
- \pushmacro\savedfont}
-
-\def\restorefont
- {\popmacro\savedfont
- \savedfont}
-
-\def\pushcurrentfont
- {\edef\popcurrentfont
- {\noexpand\def\noexpand\fontbody{\fontbody}%
- \noexpand\def\noexpand\fontstyle{\fontstyle}%
- \noexpand\dosetcurrentfontalternative{\fontalternative}%
- \noexpand\dosetcurrentfontsize{\fontsize}%
- \noexpand\synchronizefont}}
-
-% \definetypeface[one][rm][serif][computer-roman][default]
-% \definetypeface[two][rm][serif][computer-roman][default][rscale=.9]
-%
-% {\one \bf test \two test}
-% {\one \bf test \pushcurrentfont \two \popcurrentfont test}
-
-%D \macros
-%D {definedfont,startfont,doiffontcharelse}
-%D
-%D A couple of relatively new macros:
-
-% \newtoks \everydefinedfont % not ot be confused with \everydefinefont
-
-\let\thedefinedfont\relax
-
-\def\dodefinedfont[#1]%
- {\featureinheritancemode\featureinheritancefontonly
- \iffirstargument\definefont[thedefinedfont][#1]\fi % we can speed this one up
- \thedefinedfont
- \the\everydefinedfont}
-
-\unexpanded\def\definedfont
- {\dosingleempty\dodefinedfont}
-
-\unexpanded\def\startfont
- {\bgroup\definedfont}
-
-\unexpanded\def\stopfont
- {\egroup}
-
-\def\doiffontcharelse#1#2%
- {\bgroup
- \definedfont[#1]%
- \iffontchar\font#2\relax
- \egroup\expandafter\firstoftwoarguments
- \else
- \egroup\expandafter\secondoftwoarguments
- \fi}
-
-%D For more detailed (and historic information) we refer to the file
-%D \type {font-ini.mkii}. Here we have a much simplified lower level
-%D implementation due to a different approach to math. Also the chapter
-%D on fonts in the reference manual explains a lot.
-
-%D \macros
-%D {rm,ss,tt,hw,cg}
-%D
-%D Fonts are defined in separate files. When we define a font,
-%D we distinguish between several styles. In most cases we will
-%D use:
-%D
-%D \startlinecorrection
-%D \starttable[|l||]
-%D \HL
-%D \NC roman regular serif \NC \type{\rm} \NC\FR
-%D \NC sansserif sans support \NC \type{\ss} \NC\MR
-%D \NC type teletype mono \NC \type{\tt} \NC\LR
-%D \HL
-%D \stoptable
-%D \stoplinecorrection
-%D
-%D The number of styles is not limited to these three. When
-%D using Lucida Bright we can for instance also define:
-%D
-%D \startlinecorrection
-%D \starttable[|l||]
-%D \HL
-%D \NC handwritten \NC \type{\hw} \NC\FR
-%D \NC calligraphic \NC \type{\cg} \NC\LR
-%D \HL
-%D \stoptable
-%D \stoplinecorrection
-%D
-%D Within such a font set (\type{cmr}) and style (\type{\rm})
-%D we can define a number of text font alternatives:
-%D
-%D \startlinecorrection
-%D \starttable[|l||]
-%D \HL
-%D \NC typeface \NC \type{\tf} \NC\FR
-%D \NC boldface \NC \type{\bf} \NC\MR
-%D \NC slanted \NC \type{\sl} \NC\MR
-%D \NC italic \NC \type{\it} \NC\MR
-%D \NC boldslanted \NC \type{\bs} \NC\MR
-%D \NC bolditalic \NC \type{\bi} \NC\MR
-%D \NC smallcaps \NC \type{\sc} \NC\LR
-%D \HL
-%D \stoptable
-%D \stoplinecorrection
-%D
-%D Internally fonts are stored as combination of size, style
-%D and alternative, e.g. \type{12pt}+\type{\ss}+\type{\bf}.
-%D Users are not confronted with sizes, but use the style or
-%D style+alternative to activate them.
-%D
-%D During the definition of a bodyfont one can also declare the
-%D available larger alternatives:
-%D
-%D \starttyping
-%D \tf \tfa \tfb \tfc ...
-%D \bf \bfa \bfb \bfc ...
-%D \sl \sla \slb \slc ...
-%D \stoptyping
-%D
-%D The smaller ones are automatically supplied and derived from
-%D the the bodyfont environment.
-%D
-%D \starttyping
-%D \tfx \tfxx
-%D \bfx \bfxx
-%D \slx \slxx
-%D \stoptyping
-%D
-%D There are only two smaller alternatives per style. The
-%D larger alternatives on the other hand have no limitations.
-%D
-%D These larger alternatives are mostly used in chapter and
-%D section titles or on title pages. When one switches to a
-%D larger alternative, the bold an other ones automatically
-%D adapt themselves:
-%D
-%D \startbuffer
-%D \tfd Hi \bf there\sl, here \tfb I \bf am
-%D \stopbuffer
-%D
-%S \startnarrower
-%D \typebuffer
-%S \stopnarrower
-%D
-%D therefore becomes:
-%D
-%D \startvoorbeeld
-%D \getbuffer
-%D \stopvoorbeeld
-%D
-%D Maybe this mechanism isn't always as logic, but as said
-%D before, we tried to make it as intuitive as possible.
-%D
-%D So a specific kind of glyph can be characterized by:
-%D
-%D \startnarrower
-%D family (cmr) + bodyfont (12pt) + style (rm) + alternative (bf) + size (a)
-%D \stopnarrower
-%D
-%D The last component (the size) is optional.
-%D
-%D We introduced \type{\tf} as command to call for the current
-%D normally sized typeface. This commands results in roman,
-%D sans serif, teletype or whatever style is in charge. Such
-%D rather massive switches of style sometimes take more
-%D processing time than comfortable. Of course there is a
-%D workaround for this: we can call fonts directly by means of
-%D commands like:
-%D
-%D \starttyping
-%D \rmtf \sssl \tttf \rmbsa
-%D \stoptyping
-%D
-%D One should realize that this fast calls have limitations,
-%D they lack for instance automatic super- and subscript
-%D support.
-%D
-%D This leaves us two more commands: \type{\tx} and
-%D \type{\txx}. These activate a smaller and even more smaller
-%D font than the current one and adapt themselves to the
-%D current alternative, so when \type{\bf} is active,
-%D \type{\tx} gives a smaller boldface, which in turn can be
-%D called directly by \type{\bfx}.
-%D
-%D These two smaller alternatives are specified by the bodyfont
-%D environment and therefore not necessarily have similar sizes
-%D as \type{\scriptsize} and \type{\scriptscriptsize}. The main
-%D reason for this incompatibility (which can easily be undone)
-%D lays in the fact that we often want a bit bigger characters
-%D than in math mode. In \CONTEXT\ for instance the \type{\tx}
-%D and \type{\txx} commands are used for surrogate
-%D \cap{smallcaps} which support both nesting and alternatives,
-%D like in {\bf\cap{a \cap{small} world}}, which was typeset by
-%D
-%D \starttyping
-%D \bf\cap{a \cap{small} world}
-%D \stoptyping
-%D
-%D And compare $\rm \scriptstyle THIS$ with the slightly larger
-%D \cap{THIS}: \ruledhbox{$\rm \scriptstyle scriptstyle: THIS$}
-%D or \ruledhbox{\cap{x style: THIS}} makes a big difference.
-%D
-%D The \type{x..d} sizes should be used grouped. If you
-%D don't group them, i.e. call them in a row, \CONTEXT\ will
-%D not be able to sort out your intention (\type {x} inside
-%D \type {d} inside \type {x}. etc.). The following table
-%D demonstrates this:
-%D
-%D \def\FontState{\setstrut\ruledhbox{\strut Hello}}
-%D
-%D \starttabulate[|||||]
-%D \HL
-%D \NC \rlap{\quad\bf grouped} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
-%D \HL
-%D \NC \type{\tfx} \NC \tfx \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState \NC \NR
-%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState \NC \NR
-%D \NC \type{\tf} \NC \tf \FontState \NC \tf \tx \FontState \NC \tf \txx \FontState \NC \NR
-%D \NC \type{\tfa} \NC \tfa \FontState \NC \tfa \tx \FontState \NC \tfa \txx \FontState \NC \NR
-%D \NC \type{\tfb} \NC \tfb \FontState \NC \tfb \tx \FontState \NC \tfb \txx \FontState \NC \NR
-%D \NC \type{\tfc} \NC \tfc \FontState \NC \tfc \tx \FontState \NC \tfc \txx \FontState \NC \NR
-%D \NC \type{\tfd} \NC \tfd \FontState \NC \tfd \tx \FontState \NC \tfd \txx \FontState \NC \NR
-%D \NC \type{\tfx} \NC \tfx \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState \NC \NR
-%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState \NC \NR
-%D \HL
-%D \stoptabulate
-%D
-%D \blank
-%D
-%D \starttabulate[|||||]
-%D \HL
-%D \NC \rlap{\quad\bf stacked} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
-%D \HL
-%D \NC \type{\tfx}
-%D \NC \tfx \FontState
-%D \NC \tfx \tx \FontState
-%D \NC \tfx \txx \FontState
-%D \NC \NR
-%D \NC \type{\tfxx}
-%D \NC \tfx\tfxx \FontState
-%D \NC \tfx\tfxx \tx \FontState
-%D \NC \tfx\tfxx \txx \FontState
-%D \NC \NR
-%D \NC \type{\tf}
-%D \NC \tfx\tfxx\tf \FontState
-%D \NC \tfx\tfxx\tf \tx \FontState
-%D \NC \tfx\tfxx\tf \txx \FontState
-%D \NC \NR
-%D \NC \type{\tfa}
-%D \NC \tfx\tfxx\tf\tfa \FontState
-%D \NC \tfx\tfxx\tf\tfa \tx \FontState
-%D \NC \tfx\tfxx\tf\tfa \txx \FontState
-%D \NC \NR
-%D \NC \type{\tfb}
-%D \NC \tfx\tfxx\tf\tfa\tfb \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb \tx \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb \txx \FontState
-%D \NC \NR
-%D \NC \type{\tfc}
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \tx \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \txx \FontState
-%D \NC \NR
-%D \NC \type{\tfd}
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \tx \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \txx \FontState
-%D \NC \NR
-%D \NC \type{\tfx}
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \tx \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \txx \FontState
-%D \NC \NR
-%D \NC \type{\tfxx}
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \tx \FontState
-%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \txx \FontState
-%D \NC \NR
-%D \HL
-%D \stoptabulate
-%D
-%D Remark: math support has changed a bit.
-
-%D \macros
-%D {uchar}
-%D
-%D This macro prepares \CONTEXT\ for \UNICODE\ support. By
-%D defining it here, we have at least an safeguard for utility
-%D file reading.
-
-\ifdefined\uchar\else \unexpanded\def\uchar#1#2{[#1,#2]} \fi
-
-%D We define some (very private) constants to improve speed,
-%D memory usage and consistency.
-
-\def\@size@ {@f@si@} % bodyfont size prefix (12pt etc)
-\def\@style@ {@f@st@} % full style prefix (roman etc)
-\def\@shortstyle@ {@f@sh@} % short style prefix (rm etc)
-\def\@letter@ {@f@le@} % first alternative typeface
-\def\@noletter@ {@f@no@} % second alternative typeface
-\def\@fontclass@ {@f@cl@} % fontclass
-
-%D \macros
-%D {fontclass, defaultfontclass}
-%D
-%D The fontclass model was introduced a while after we implement
-%D the basic font model and at that time we still defaulted to
-%D no model at all. Nowadays we default to the \type {modern}
-%D fontclass.
-
-\let\fontclass \empty
-\let\defaultfontclass\empty
-
-%D \macros
-%D {textonly}
-%D
-%D Traditionally math has a big impact on font definitions, mainly
-%D because we need to define alphabet variants using families and
-%D fonts. This means that one can easily get 10 fonts loaded per
-%D math size. In \MKIV\ we use a different approach: one family
-%D which has either a virtual font made of traditional fonts, or
-%D an \OPENTYPE\ font that has it all.
-%D
-%D We currently use only one math family but in the future we
-%D might consider using a second one for bold math. For the
-%D moment we keep the \MKII\ method of using a token register
-%D for definitions but we already dropped the text and symbols
-%D ones since they now live in the same family.
-
-\newtoks \mathstrategies
-
-\newif\ifsynchronizemathfonts \synchronizemathfontstrue
-
-\def\synchronizemath % math stuff in mmode
- {\ifsynchronizemathfonts\the\mathstrategies\fi}
-
-\def\textonly{\synchronizemathfontsfalse} % document this
-
-%D The main math font definer. We have removed some optimized
-%D code simply because we now always have a fontclass. We could
-%D check for fontclass being default or empty and save a few
-%D tests but it does not help us when no math is defined.
-
-\let\mrfam\zerocount % math regular
-\let\mbfam\plusone % math bold
-
-\unexpanded\def\mr{\ifmmode\fam\mrfam\else\setcurrentfontalternative\c!mr\fi}
-\unexpanded\def\mb{\ifmmode\fam\mbfam\else\setcurrentfontalternative\c!mb\fi}
-
-\def\mathtextsuffix {-text}
-\def\mathscriptsuffix {-script}
-\def\mathscriptscriptsuffix{-scriptscript}
-
-% \let\mathsizesuffix\empty
-
-\let\currentmathsize\empty
-
-\def\mathsizesuffix{\ifcase0\currentmathsize\or\mathtextsuffix\or\mathscriptsuffix\or\mathscriptscriptsuffix\fi}
-
-\def\dodosetmathfamily#1#2%
- {\ifcsname\fontclass \fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \autofontsizefalse
- \csname\fontclass \fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \else
- \ifcsname\fontclass \fontbody\c!mm\fontfamily \currentmathsize\endcsname \autofontsizetrue
- \csname\fontclass \fontbody\c!mm\fontfamily \currentmathsize\endcsname \else
- \dodosetmathfamilyx#1#2%
- \fi\fi
- #1#2\font}
-
-\def\dodosetmathfamilyx#1#2%
- {\ifcsname\defaultfontclass\fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \autofontsizefalse
- \csname\defaultfontclass\fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \else
- \ifcsname\defaultfontclass\fontbody\c!mm\fontfamily \currentmathsize\endcsname \autofontsizetrue
- \csname\defaultfontclass\fontbody\c!mm\fontfamily \currentmathsize\endcsname \else
- \dodosetmathfamilyxx#1#2%
- \fi\fi}
-
-\def\dodosetmathfamilyxx#1#2%
- {\ifcsname \fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \autofontsizefalse
- \csname \fontbody\c!mm\fontfamily\fontsize\currentmathsize\endcsname \else
- \ifcsname \fontbody\c!mm\fontfamily \currentmathsize\endcsname \autofontsizetrue
- \csname \fontbody\c!mm\fontfamily \currentmathsize\endcsname \else
- \nullfont \autofontsizetrue
- \fi\fi}
-
-\def\dosetmathfamily#1#2%
- {\let\savedfontbody\fontbody % op hoger plan
- \let\fontfamily#2%
- % new per 20100817
- \checkbodyfontenvironment[\scriptscriptface]%
- \checkbodyfontenvironment[\scriptface]%
- \checkbodyfontenvironment[\textface]%
- %
- \let\currentmathsize\!!plusthree\let\fontbody\scriptscriptface\dodosetmathfamily\scriptscriptfont#1%
- \let\currentmathsize\!!plustwo \let\fontbody\scriptface \dodosetmathfamily\scriptfont #1%
- \let\currentmathsize\!!plusone \let\fontbody\textface \dodosetmathfamily\textfont #1%
- \let\currentmathsize\empty
- \let\fontbody\savedfontbody
- \autofontsizefalse}
-
-\appendtoks
- \dosetmathfamily\mrfam\c!mr
-\to \mathstrategies
-
-% not official !
-
-\newconditional\boldmathmode % might change ... maybe \mathfontsupport 1 (normal) 2 (bold too)
-
-\def\enableboldmath {\settrue \boldmathmode} % todo: \setupbodyfont[boldmath,...]
-\def\disableboldmath{\setfalse\boldmathmode}
-
-\appendtoks
- \ifconditional\boldmathmode\dosetmathfamily\mbfam\c!mb\fi
-\to \mathstrategies
-
-%D All used styles, like rm, ss and tt, are saved in a comma
-%D separated list. Appart from practical limitations one can
-%D define as many styles as needed.
-
-\def\fontrelativesizelist{\s!text,\s!script,\s!scriptscript,\c!x,\c!xx,\c!big,\c!small}
-
-%D There are several ways to specify a font. Three of them are
-%D pure \TeX\ ones, the fourth one is new:
-%D
-%D \starttyping
-%D \font\name=cmr12
-%D \font\name=cmr12 at 10pt
-%D \font\name=cmr12 scaled 2
-%D \font\name=cmr12 sa 1.440
-%D \stoptyping
-%D
-%D The non||\TEX\ alternative \type{sa} stands for {\em scaled
-%D at}. This means as much as: scale the bodyfontsize with this
-%D factor. The scaled option is not that useful as one needs to
-%D know the design size.
-%D
-%D Because \type {sa} (scaled at) and \type {mo} (mapped on)
-%D are not low level \TEX\ supported alternatives, we have to
-%D test for it ourselves. In doing so, we need an auxiliary
-%D \DIMENSION. We cannot use \type{\scratchdimen} because font
-%D loading can happen at any moment due to postponed loading.
-%D We could instead have used dirty grouping tricks, but this
-%D one works too.
-
-% \enableexperiments[fonts.autorscale]
-%
-% \starttypescript[mscore]
-% \definetypeface [mscore] [rm] [serif] [mscoretimes] [default]
-% \definetypeface [mscore] [ss] [sans] [mscorearial] [default] [rscale=auto] % 0.860]
-% \definetypeface [mscore] [tt] [mono] [mscorecourier] [default] [rscale=auto] % 1.065]
-% \definetypeface [mscore] [mm] [math] [times] [default] [rscale=auto] % 1.020]
-% \stoptypescript
-%
-% \starttext
-% \setupbodyfont[mscore,12pt]
-% \startTEXpage
-% test \ss test \tt test
-% \stopTEXpage
-% \stoptext
-
-\let\defaultrelativefontsize \plusone
-\let\localrelativefontsize \plusone
-\def\localabsolutefontsize {\fontbody}
-
-\let\relativefontsize \defaultrelativefontsize
-
-% \def\saverelativefontsize#1#2% #1=rm|ss|.. #2=waarde
-% {\setxvalue{\fontclass#1\s!rscale}{#2}}
-
-\def\checkrelativefontid
- {\ifcsname\??tf\fontclass\s!rname\endcsname
- \@EA\let\@EA\relativefontid\csname\??tf\fontclass\s!rname\endcsname
- \else
- \@EA\xdef\csname\??tf\fontclass\s!rname\endcsname{\the\lastfontid}%
- \let\relativefontid\empty
- \fi}
-
-\def\checkrelativefontid % not yet supported as we then need to trigger \rm\tf or so first
- {\let\relativefontsize\minusone
- \let\relativefontsize\defaultrelativefontsize}
-
-\def\checkrelativefontsize#1%
- {\edef\relativefontsize
- {\ifcsname\fontclass#1\s!rscale\endcsname
- \csname\fontclass#1\s!rscale\endcsname
- \else\ifcsname\defaultfontclass#1\s!rscale\endcsname
- \csname\defaultfontclass#1\s!rscale\endcsname
- \else
- \defaultrelativefontsize
- \fi\fi}%
- \ifx\relativefontsize\v!auto
- \let\relativefontsize\plusone
- \checkrelativefontid
- \else
- \let\relativefontid\minusone
- \fi}
-
-%D Scaling macros:
-%D
-%D This system is somewhat complicated by two (possible conflicting)
-%D demands:
-%D
-%D \startitemize
-%D \item We support wildcards like \type {sa *} which will adapt
-%D to the current size. This is also the default specification.
-%D \item We support named scales like \type {sa d}; beware: \type
-%D {x} and \type {xx} are valid scales but they are not alway
-%D the same as the ones used in for instance \type {\bfx} because
-%D there the sized come from the bodyfont environment. In the
-%D future there maybe a switch that also honors the environment
-%D in named scales.
-%D \stopitemize
-
-%D Keep in mind that the smaller sizes are just for text super and
-%D subscripts while larger sizes can be used in titles where for
-%D instance math follows the size.
-
-% b:x{\definedfont[SerifBold sa b]x}{\bfb x $x^x$}\par
-% 1:x{\definedfont[SerifBold sa 1]x}{\bf x $x^x$}\par
-% x:x{\definedfont[SerifBold sa x]x}{\bfx x $x^x$}\par
-% xx:x{\definedfont[SerifBold sa xx]x}{\bfxx x $x^x$}\par
-%
-% *:x{\definedfont[Serif sa *]x}\par
-% 1:x{\definedfont[Serif sa 1]x}\par
-% 2:x{\definedfont[Serif sa 2]x}\par
-% 3:x{\definedfont[Serif sa 3]x}\par
-% 4:x{\definedfont[Serif sa 4]x}\par
-% 5:x{\definedfont[Serif sa 5]x}\par
-%
-% {\definedfont[cmbx10 at 10pt]x\definedfont[cmbx8 at 10pt]x}
-
-\def\safontscale{\number\dimexpr\localabsolutefontsize\relax}
-\def\mofontscale{\number\dimexpr\setmappedfontsize\localabsolutefontsize\relax}
-
-\let\somefontname\s!unknown
-\let\somefontspec\s!unknown
-\let\somefontsize\zerocount
-
-\newcount\scaledfontmode
-\newdimen\scaledfontsize
-\newtoks \everydefinefont
-\newcount\lastfontid
-
-\def\currentfontbodysize
- {\ifcsname\??ft\s!default\somefontsize\endcsname
- \csname\??ft\s!default\somefontsize\endcsname
- \else
- \somefontsize
- \fi}
-
-\let\relativefontid\empty
-
-% 0 = none
-% 1 = fontonly
-% 2 = classonly
-% 3 = fontfirst
-% 4 = classfirst
-
-\setnewconstant\featureinheritancefontnone \zerocount
-\setnewconstant\featureinheritancefontonly \plusone
-\setnewconstant\featureinheritanceclassonly \plustwo
-\setnewconstant\featureinheritancefontfirst \plusthree
-\setnewconstant\featureinheritanceclassfirst\plusfour
-
-\setnewconstant\featureinheritancedefault \featureinheritancefontfirst
-\setnewconstant\featureinheritancemode \featureinheritancedefault
-
-\unexpanded\def\lowleveldefinefont#1#2% #2 = cs
- {% we can now set more at the lua end
- \ctxlua{fonts.definers.stage_one("\luaescapestring{#1}")}% the escapestring catches at \somedimen
- % sets \scaledfontmode and \somefontname and \somefontsize
- \ifcase\scaledfontmode\relax
- % none, avoid the designsize if possible
- \scaledfontsize-1000\scaledpoint
- \or
- % at
- \scaledfontsize\somefontsize
- \or
- % sa
- \scaledfontsize\localabsolutefontsize\relax
- \scaledfontsize\currentfontbodysize\scaledfontsize
- \or
- % mo
- \scaledfontsize\setmappedfontsize\localabsolutefontsize
- \scaledfontsize\currentfontbodysize\scaledfontsize
- \or
- % scaled, don't use this one as it's unpredictable
- \scaledfontsize-\somefontsize\scaledpoint
- \fi
- \relax
- \scaledfontsize\localrelativefontsize\scaledfontsize
- \ifautofontsize
- \scaledfontsize\currentfontbodyscale\scaledfontsize
- \fi
- \edef\somefontspec{at \number\scaledfontsize sp}%
- \edef\somefontfile{\truefontname\somefontname}%
- \ifx\somefontfile\s!unknown
- \edef\somefontfile{\defaultfontfile}%
- \fi
- \updatefontparameters
- \updatefontclassparameters
- \ctxlua{fonts.definers.stage_two(
- \ifx\fontclass\empty false\else true\fi,
- "#2", % cs, trailing % is gone
- "\somefontfile",
- \number\scaledfontsize,
- \number\featureinheritancemode,
- "\@@fontclassfeatures",
- "\@@fontfeatures",
- "\@@fontclassfallbacks",
- "\@@fontfallbacks",
- 0\currentmathsize,
- \number\dimexpr\textface\relax,
- "\relativefontid", % experiment
- "\@@fontclassgoodies", % experiment (not yet used)
- "\@@fontgoodies" % experiment
- )}%
-% \edef\somefontspec{at \somefontsize}% we need the resolved designsize (for fallbacks)
- \edef\somefontspec{at \number\scaledfontsize sp}% we need the resolved designsize (for fallbacks)
- \expandafter\let\expandafter\lastrawfontcall\csname#2\endcsname
- \the\everydefinefont
- \featureinheritancemode\featureinheritancedefault}
-
-\def\updatefontclassparameters
- {\edef\@@fontclassfeatures {\ifcsname\fontclass\fontstyle\s!features \endcsname\csname\fontclass\fontstyle\s!features \endcsname\fi}%
- \edef\@@fontclassfallbacks{\ifcsname\fontclass\fontstyle\s!fallbacks\endcsname\csname\fontclass\fontstyle\s!fallbacks\endcsname\fi}%
- \edef\@@fontclassgoodies {\ifcsname\fontclass\fontstyle\s!goodies \endcsname\csname\fontclass\fontstyle\s!goodies \endcsname\fi}}
-
-% resolve
-
-\def\@@thefeaturesyes#1%
- {\ifcsname\??ff\fontclass#1\s!features \endcsname\@EA\let\@EA\@@fontfeatures \csname\??ff\fontclass#1\s!features \endcsname\else
- \ifcsname\??ff #1\s!features \endcsname\@EA\let\@EA\@@fontfeatures \csname\??ff #1\s!features \endcsname\else
- \ifcsname\??ff\fontclass #1\endcsname\@EA \@@thefeaturesyes \csname\??ff\fontclass #1\endcsname\else
- \ifcsname\??ff #1\endcsname\@EA \@@thefeaturesyes \csname\??ff #1\endcsname\else
- \let \@@fontfeatures \empty \fi\fi\fi\fi}
-
-\def\@@thefallbacksyes#1%
- {\ifcsname\??ff\fontclass#1\s!fallbacks\endcsname\@EA\let\@EA\@@fontfallbacks \csname\??ff\fontclass#1\s!fallbacks\endcsname\else
- \ifcsname\??ff #1\s!fallbacks\endcsname\@EA\let\@EA\@@fontfallbacks \csname\??ff #1\s!fallbacks\endcsname\else
- \ifcsname\??ff\fontclass #1\endcsname\@EA \@@thefallbacksyes\csname\??ff\fontclass #1\endcsname\else
- \ifcsname\??ff #1\endcsname\@EA \@@thefallbacksyes\csname\??ff #1\endcsname\else
- \let \@@fontfallbacks \empty \fi\fi\fi\fi}
-
-\def\@@thegoodiesyes#1%
- {\ifcsname\??ff\fontclass#1\s!goodies \endcsname\@EA\let\@EA\@@fontgoodies \csname\??ff\fontclass#1\s!goodies \endcsname\else
- \ifcsname\??ff #1\s!goodies \endcsname\@EA\let\@EA\@@fontgoodies \csname\??ff #1\s!goodies \endcsname\else
- \ifcsname\??ff\fontclass #1\endcsname\@EA \@@thegoodiesyes \csname\??ff\fontclass #1\endcsname\else
- \ifcsname\??ff #1\endcsname\@EA \@@thegoodiesyes \csname\??ff #1\endcsname\else
- \let \@@fontgoodies \empty \fi\fi\fi\fi}
-
-\def\@@thefeaturesnop#1%
- {\ifcsname\??ff#1\s!features \endcsname\@EA\let\@EA\@@fontfeatures \csname\??ff#1\s!features \endcsname\else
- \ifcsname\??ff #1\endcsname\@EA \@@thefeaturesnop \csname\??ff #1\endcsname\else
- \let \@@fontfeatures \empty \fi\fi}
-
-\def\@@thefallbacksnop#1%
- {\ifcsname\??ff#1\s!fallbacks\endcsname\@EA\let\@EA\@@fontfallbacks \csname\??ff#1\s!fallbacks\endcsname\else
- \ifcsname\??ff #1\endcsname\@EA \@@thefallbacksnop\csname\??ff #1\endcsname\else
- \let \@@fontfallbacks \empty \fi\fi}
-
-\def\@@thegoodiesnop#1%
- {\ifcsname\??ff#1\s!goodies \endcsname\@EA\let\@EA\@@fontgoodies \csname\??ff#1\s!goodies \endcsname\else
- \ifcsname\??ff #1\endcsname\@EA \@@thegoodiesnop \csname\??ff #1\endcsname\else
- \let \@@fontgoodies \empty \fi\fi}
-
-\def\updatefontparametersyes
- {\@@thefeaturesyes \somefontname
- \@@thefallbacksyes\somefontname
- \@@thegoodiesyes \somefontname}
-
-\def\updatefontparametersnop
- {\@@thefeaturesnop \somefontname
- \@@thefallbacksnop\somefontname
- \@@thegoodiesnop \somefontname}
-
-\def\updatefontparameters
- {\ifx\fontclass\empty\updatefontparametersnop\else\updatefontparametersyes\fi}
-
-\let\@@fontclassfeatures \empty
-\let\@@fontclassfallbacks\empty
-
-\let\@@fontfallbacks\empty
-\let\@@fontfeatures \empty
-\let\@@fontgoodies \empty
-
-\let\@@hyphenchar \empty % todo, will go to encoding
-
-%D This brings down maps processing from 466 to 309 seconds
-%D ($-33$\%) and mfonts from 42 to 34 seconds ($-15$\%).
-
-\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue
-
-%D When fontclasses are used, we define the font global,
-%D since namespaces are used. Otherwise we parse the specs
-%D each time.
-
-\let\fontfile\s!unknown
-
-% \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
-
-% \starttext
-% \definefont
-% [blabla]
-% [name:Latin Modern Something]
-% \definefont
-% [blabla]
-% [file:texnansi-lmr10]
-% \blabla test
-% \definefont
-% [blabla]
-% [texnansi-lmtt10]
-% \blabla test
-% \stoptext
-
-% \starttext
-%
-% \setupcolors[state=start]
-%
-% \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}
-%
-% \stoptext
-
-\def \defaultfontfile{\truefontname{Normal}} % was cmtt10, but that one is gone
-\edef\nullfontname {\fontname\nullfont}
-
-%D \macros
-%D {everyfont,everyfontswitch}
-%D
-%D For special purposes, we provide a hook.
-
-% \newevery \everyfont \relax
-% \newevery \everyfontswitch \relax
-
-%D We also accept \type{sa a}||\type{sa d} as specification.
-
-%D \macros
-%D {definefontsynonym, doifelsefontsynonym,
-%D expandfontsynonym, truefontname, truefontdata}
-%D
-%D While looking for fonts, fontsynonyms are used for accessing
-%D the files!
-%D
-%D \starttyping
-%D \definefontsynonym[Serif][Lucida-Bright]
-%D \definefontsynonym[Lucida-Bright][lbr][encoding=texnansi]
-%D \stoptyping
-
-\def\classfont#1#2{#1#2} % \definefont[whatever][\classfont{xx}{yy} at 10pt]
-
-% We need to move the feature into the filename else it may be
-% overloaded by another reference. For instance the definition of
-% a regular and caps variant can use the same font.
-
-% We could use an indirect method ... store in 'array' and refer to
-% slot.
-%
-% or nicer .. use parent chain
-
-\unexpanded\def\definefontsynonym[#1]#2[#3]%
- {\edef\@@fontname{#1}%
- \edef\@@fontfile{#3}%
- \ifx\fontclass\empty
- \expandafter\dodefinefontsynonymnop
- \else
- \expandafter\dodefinefontsynonymyes
- \fi}
-
-\def\dodefinefontsynonymnop
- {\@EA\let\csname\??ff\@@fontname\endcsname\@@fontfile % maybe just #1 #3, saves expansion
- \doifnextoptionalelse\dododefinefontsynonymnop\nonodefinefontsynonymnop}
-
-\def\dodefinefontsynonymyes
- {\@EA\let\csname\??ff\fontclass\@@fontname\endcsname\@@fontfile % maybe just #1 #3, saves expansion
- \doifnextoptionalelse\dododefinefontsynonymyes\nonodefinefontsynonymyes}
-
-\def\dododefinefontsynonymnop[#1]%
- {\let\@@ff@@features \undefined
- \let\@@ff@@fallbacks\undefined
- \let\@@ff@@goodies \undefined
- \expandafter\dogetfontparameternop#1,]=,}
-
-\def\dododefinefontsynonymyes[#1]%
- {\let\@@ff@@features \undefined
- \let\@@ff@@fallbacks\undefined
- \let\@@ff@@goodies \undefined
- \expandafter\dogetfontparameteryes#1,]=,}
-
-\def\dogetfontparameternop#1=#2,%
- {\if]#1%
- \dodododefinefontsynonymnop
- \else
- \expandafter\def\csname @@ff@@#1\endcsname{#2}%
- \expandafter\dogetfontparameternop
- \fi}
-
-\def\dogetfontparameteryes#1=#2,%
- {\if]#1%
- \dodododefinefontsynonymyes
- \else
- \expandafter\def\csname @@ff@@#1\endcsname{#2}%
- \expandafter\dogetfontparameteryes
- \fi}
-
-% helpers, some day these will be toks and counts
-
-\def\fntsetdefname {\global\let\somefontname\defaultfontfile}
-\def\fntsetsomename{\gdef\somefontname} % {#1}
-\def\fntsetnopsize {\let\somefontsize\empty}
-\def\fntsetsomesize{\def\somefontsize} % {#1}
-
-% end of helpers
-
-\def\nonodefinefontsynonymnop
- {\@EA\let\csname\??ff\@@fontname\s!features \endcsname\undefined
- \@EA\let\csname\??ff\@@fontname\s!fallbacks\endcsname\undefined
- \@EA\let\csname\??ff\@@fontname\s!goodies \endcsname\undefined}
-
-\def\nonodefinefontsynonymyes
- {\global\@EA\let\csname\??ff\fontclass\@@fontname\s!features \endcsname\undefined
- \global\@EA\let\csname\??ff\fontclass\@@fontname\s!fallbacks\endcsname\undefined
- \global\@EA\let\csname\??ff\fontclass\@@fontname\s!goodies \endcsname\undefined}
-
-\def\dodododefinefontsynonymnop
- {\@EA\let\csname\??ff\@@fontname\s!features \endcsname\@@ff@@features
- \@EA\let\csname\??ff\@@fontname\s!fallbacks\endcsname\@@ff@@fallbacks
- \@EA\let\csname\??ff\@@fontname\s!goodies \endcsname\@@ff@@goodies}
-
-\def\dodododefinefontsynonymyes
- {\global\@EA\let\csname\??ff\fontclass\@@fontname\s!features \endcsname\@@ff@@features
- \global\@EA\let\csname\??ff\fontclass\@@fontname\s!fallbacks\endcsname\@@ff@@fallbacks
- \global\@EA\let\csname\??ff\fontclass\@@fontname\s!goodies \endcsname\@@ff@@goodies}
-
-\let\definefontfile\definefontsynonym % dedicated to Taco Hoekwater
-
-\unexpanded\def\setupfontsynonym
- {\dodoubleempty\dosetupfontsynonym}
-
-\def\dosetupfontsynonym[#1][#2]% not yet supported, will do when needed
- {}
-
-\def\truefontname#1%
- {\@EA\dotruefontname#1*\empty*\relax}
-
-\def\dotruefontname#1*#2#3*#4\relax
- {\ifcsname\??ff\fontclass#1\endcsname
- \ifx#2\empty
- \@EA\truefontname\csname\??ff\fontclass#1\endcsname
- \else
- \@EA\redotruefontname\csname\??ff\fontclass#1\endcsname*#2#3%
- \fi
- \else\ifcsname\??ff\defaultfontclass#1\endcsname
- \ifx#2\empty
- \@EA\truefontname\csname\??ff\defaultfontclass#1\endcsname
- \else
- \@EA\redotruefontname\csname\??ff\defaultfontclass#1\endcsname*#2#3%
- \fi
- \else\ifcsname\??ff#1\endcsname
- \ifx#2\empty
- \@EA\truefontname\csname\??ff#1\endcsname
- \else
- \@EA\redotruefontname\csname\??ff#1\endcsname*#2#3%
- \fi
- \else
- #1\ifx#2\empty\else*#2#3\fi
- \fi\fi\fi}
-
-\def\redotruefontname#1%
- {\@EA\dodotruefontname#1*\relax}
-
-\def\dodotruefontname#1*#2\relax
- {\ifcsname\??ff\fontclass#1\endcsname
- \@EA\redotruefontname\csname\??ff\fontclass#1\endcsname
- \else\ifcsname\??ff\defaultfontclass#1\endcsname
- \@EA\redotruefontname\csname\??ff\defaultfontclass#1\endcsname
- \else\ifcsname\??ff#1\endcsname
- \@EA\redotruefontname\csname\??ff#1\endcsname
- \else
- #1%
- \fi\fi\fi}
-
-\def\expandfontsynonym#1#2% #2 := onelevelexpansion(#1)
- {\ifcsname\??ff\fontclass#2\endcsname
- \expandafter\def\expandafter#1\expandafter{\csname\??ff\fontclass#2\endcsname}%
- \else\ifcsname\??ff\defaultfontclass#2\endcsname
- \expandafter\def\expandafter#1\expandafter{\csname\??ff\defaultfontclass#2\endcsname}%
- \fi\fi}
-
-\def\doifelsefontsynonym#1%
- {\ifcsname\??ff\fontclass#1\endcsname
- \@EA\firstoftwoarguments
- \else\ifcsname\??ff\defaultfontclass#1\endcsname
- \@EAEAEA\firstoftwoarguments
- \else
- \@EAEAEA\secondoftwoarguments
- \fi\fi}
-
-% \definetypeface[palatino][rm][serif][palatino,allbold][default]
-%
-% \startfontclass[palatino]
-% \definefontsynonym [Serif] [SerifBold]
-% \definefontsynonym [SerifItalic] [SerifBoldItalic]
-% \definefontsynonym [SerifSlanted] [SerifBoldSlanted]
-% \definefontsynonym [SerifCaps] [SerifBold]
-% \stopfontclass
-%
-% \setupbodyfont[palatino]
-
-\unexpanded\def\startfontclass
- {\dosingleempty\dostartfontclass}
-
-\def\dostartfontclass[#1]%
- {\pushmacro\fontclass
- \doifelse{#1}\v!each
- {\let\fontclass\empty}
- {\doifsomething{#1}{\def\fontclass{#1}}}}
-
-\unexpanded\def\stopfontclass
- {\popmacro\fontclass}
-
-%D \macros
-%D {tracedfontname}
-%D
-%D A goody:
-
-\def\tracedfontname#1%
- {#1\ifcsname\??ff\fontclass#1\endcsname
- \@EA\tracedfontname\csname\??ff\fontclass#1\endcsname
- \else\ifcsname\??ff#1\endcsname
- \@EA\tracedfontname\csname\??ff#1\endcsname
- \fi\fi}
-
-%D \macros
-%D {definefont}
-%D
-%D Before we implement the main definition macro, we first show
-%D one for local use:
-%D
-%D \starttyping
-%D \definefont[Some][LucidaBright at 100pt] \Some some
-%D \definefont[More][LucidaBright scaled 3000] \More more
-%D \definefont[Nice][LucidaBright mo 2] \Nice nice
-%D \definefont[Text][LucidaBright sa 5.4] \Text last
-%D \stoptyping
-%D
-%D The implementation looks as follows:
-
-\unexpanded\def\definefont
- {\dotripleempty\dodefinefont}
-
-\def\dodefinefont[#1][#2][#3]% [name][spec][1.6 | line=10pt | setup_id]
- {\ifthirdargument
- \setuvalue{#1}{\redodefinefont{#1}{#2}{#3}}%
- \else
- \setuvalue{#1}{\dododefinefont{#1}{#2}}%
- \fi}
-
-\def\redodefinefont#1#2#3%
- {\dododefinefont{#1}{#2}%
- \doifsetupselse{#3}
- {\setups[#3]} % don't forget to document this !
- {\setuplocalinterlinespace[#3]%
- \setupspacing}} % needed ?
-
-\unexpanded\def\definefrozenfont
- {\dotripleempty\dodefinefrozenfont}
-
-\def\dodefinefrozenfont[#1][#2][#3]%
- {\dodefinefont[#1][#2][#3]%
- \expandafter\let\csname\lastfontidentifier\expandafter\endcsname\csname\rawfontidentifier\endcsname}
-
-%D The \type {*} makes the switch local, so that we can redefine a
-%D logical name and/or change the size in between.
-
-\newif\ifautofontsize \autofontsizetrue
-
-\let\lastfontidentifier\empty
-
-\def\rawfontidentifier{**\lastfontidentifier\fontsize\currentmathsize**}
-\def\newfontidentifier{*\fontclass\lastfontidentifier\fontsize\currentmathsize*}
-
-\let\oldrawfontidentifier\rawfontidentifier
-\let\oldnewfontidentifier\newfontidentifier
-
-\def\newfontidentifier{*\fontclass\lastfontidentifier\fontstyle\fontsize*}
-
-\def\dododefinefont#1#2%
- {\featureinheritancemode\featureinheritancefontonly
- \edef\lastfontidentifier{#1}%
- \let\localrelativefontsize\defaultrelativefontsize
- \let\localabsolutefontsize\fontbody
- \lowleveldefinefont{#2}\rawfontidentifier
- \csname\rawfontidentifier\endcsname
- \autofontsizefalse
- \setfontcharacteristics
- \the\everyfontswitch
- \let\rawfontidentifier\oldrawfontidentifier}
-
-\def\xxdododefinefont#1#2#3#4% \autofontsizetrue is set by calling routine
- {\edef\lastfontidentifier{#3}%
- \ifcsname\newfontidentifier\endcsname\else
- \def\localrelativefontsize{#1}%
- \def\localabsolutefontsize{#2}%
- \lowleveldefinefont{#4}\newfontidentifier
- \fi
- \csname\newfontidentifier\endcsname
- \autofontsizefalse
- %\edef\lastfontidentifier{#3}%
- \ifskipfontcharacteristics \else
- \setfontcharacteristics
- \the\everyfontswitch
- \fi
- \let\newfontidentifier\oldnewfontidentifier}
-
-%D \macros
-%D {mapfontsize}
-%D
-%D For special purposes, like in math, you may want to use
-%D slightly different sizes than the ones given. This happens
-%D for instance with the Math Times fonts. Mapped font sizes
-%D can be specified by using the \type {mo} key instead of
-%D \type {sa} in font definitions.
-%D
-%D \startbuffer
-%D \mapfontsize[10pt][11pt]
-%D \mapfontsize[11pt][12pt]
-%D \mapfontsize[12pt][13pt]
-%D
-%D \definefont[test][Serif]\test TEST \par
-%D \definefont[test][Serif sa 5]\test TEST \par
-%D \definefont[test][Serif mo 5]\test TEST \par
-%D \definefont[test][Serif sa d]\test TEST \par
-%D \definefont[test][Serif at 60pt]\test TEST \par
-%D \definefont[test][Serif scaled 6000]\test TEST \par
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \startpacked
-%D \getbuffer
-%D \stoppacked
-
-\def\mapfontsize
- {\dodoubleargument\domapfontsize}
-
-\def\domapfontsize[#1][#2]%
- {\setvalue{\??ft*\the\dimexpr#1\relax}{#2}}
-
-\def\setmappedfontsize#1%
- {\ifcsname\??ft*#1\endcsname
- \csname\??ft*#1\endcsname
- \else
- #1%
- \fi}
-
-%D \macros
-%D {getfontname}
-%D
-%D The names of the fonts can be called with the rather simple
-%D macro \type{\getfontname}. When for instance we pass
-%D \type{12ptrmtf} as argument, we get \getfontname{12ptrmtf}.
-
-\def\getfontname#1%
- {\csname\??ft#1\endcsname}
-
-%D To be documented.
-
-\let\fontsizelist \empty
-\let\fontalternativelist\empty
-\let\fontstylelist \empty
-
-\def\checkfontnamecombinations % we need to split math and text here ... todo (math only has mr and mb)
- {\def\docommand##1%
- {\def\dodocommand####1%
- {\def\dododocommand########1{\checkbodyfont{########1}{####1}{##1}}%
- \processcommacommand[\fontstylelist]\dododocommand}%
- \processcommacommand[\fontalternativelist]\dodocommand}%
- \processcommacommand[\fontsizelist]\docommand}
-
-\unexpanded\def\definefontsize[#1]% sneller met toks
- {\addtocommalist{#1}\fontsizelist
- \checkfontnamecombinations}
-
-\unexpanded\def\definefontalternative[#1]%
- {\addtocommalist{#1}\fontalternativelist
- \checkfontnamecombinations}
-
-%D \macros
-%D {currentfontscale,currentfontbodyscale}
-%D
-%D Sometimes we need to have access to the font scale
-%D including the \type{a}||\type{d} sizes. The next macro
-%D returns the current scaling factor. Take a look at
-%D \type {cont-log.tex} for an example of its use.
-
-\def\currentfontscale
- {\csname\??ft\s!default
- \ifcsname\??ft\s!default\xfontsize\endcsname \xfontsize \else
- \ifcsname\??ft\s!default\s!text \endcsname \s!text \fi\fi
- \endcsname}
-
-\def\currentfontbodyscale
- {\csname\??ft\s!default
- \ifcsname\??ft\s!default\fontsize\endcsname \fontsize \else
- \ifcsname\??ft\s!default\s!text \endcsname \s!text \fi\fi
- \endcsname}
-
-\setvalue{\??ft\s!default}{1}
-
-%D Both alternatives use \type {\xfontsize}, a macro that
-%D expands to the current size in terms of \type {a} \unknown
-%D \type {d}, nothing, or \type {x} \unknown \type {xx}.
-
-%D In the following macros we use \type{\currentxfontsize} to
-%D hold the current x||size of the font. This enables us to
-%D support for instance \type{\sl} inside a \type{\tx} switch.
-
-\newconstant\currentxfontsize
-
-\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\c!x\else\c!xx\fi}
-
-%D A typical use of this command is in commands that switch
-%D to another font bypassing the font mechanism:
-%D
-%D \starttyping
-%D \font\myfont=\truefontname{MyFont} at \the\dimexpr\currentfontscale\bodyfontsize\relax
-%D \stoptyping
-
-%D Now we enter the area of font switching. The switching
-%D mechanism has to take care of several situations, like:
-%D
-%D \startitemize[packed]
-%D \item changing the overal document fonts (including margins,
-%D headers and footers)
-%D \item changing local fonts (only the running text)
-%D \item smaller and even more smaller alternatives (super-
-%D and subscripts)
-%D \stopitemize
-%D
-%D \TEX\ offers a powerfull family mechanism for super- and
-%D subscripts in math mode. In text mode however, we don't use
-%D families for the smaller alternatives, and therefore have
-%D to take care of it otherwise.
-
-%D \macros
-%D {definebodyfontenvironment,setupbodyfontenvironment}
-%D
-%D The relationship between the several sizes of a font, is
-%D defined by:
-%D
-%D \showsetup{definebodyfontenvironment}
-%D
-%D Later on we will see how these parameters are used, so for
-%D the moment we stick with an example:
-%D
-%D \starttyping
-%D \definebodyfontenvironment
-%D [12pt]
-%D [ text=12pt,
-%D script=9pt,
-%D scriptscript=7pt,
-%D x=10pt,
-%D xx=8pt,
-%D big=12pt,
-%D small=10pt]
-%D \stoptyping
-%D
-%D The first argument specifies the bodyfont size to which the
-%D settings apply. All second parameters are specified in
-%D dimensions and tell us more about related sizes.
-%D
-%D Afterwards, one can change values with
-%D
-%D \showsetup{setupbodyfontenvironment}
-%D
-%D Due to the fact that \type{\c!text} and \type{\s!text} can
-%D have a similar meaning, and therefore can lead to an
-%D unwanted loop, we temporary redefine \type{\c!text}. For
-%D the moment this in only place that some trickery is needed
-%D to fool the multilingual interface. However, long ago
-%D we decided to stick to \s!text in definitions as it closely
-%D relates to the math model where text, script and scriptscript
-%D are used untranslated. Also, we are now english at the low
-%D level so it cannot go wrong anymore.
-%D
-%D When instead of a size the keyword \type{unknown} is
-%D passed, fractions (relations) are used instead of fixed
-%D sizes.
-
-\let\bodyfontenvironmentlist\empty
-
-\newcount\@@fontdefhack % check if this is still needed
-
-% \def\@@beginfontdef
-% {\ifcase\@@fontdefhack
-% \let\k!savedtext \k!text \let\k!text \s!text
-% \let\k!saveddefault \k!default \let\k!default \s!default
-% \fi
-% \advance\@@fontdefhack \plusone }
-
-% \def\@@endfontdef
-% {\advance\@@fontdefhack \minusone
-% \ifcase\@@fontdefhack
-% \let\k!default \k!saveddefault
-% \let\k!text \k!savedtext
-% \fi}
-
-%%%%%%%%%%%%%%%%%%%%%%%%
-
-% The problem is that the key in a getparameters is resolved
-% to the underlying interface language (english). But values
-% are kept as they are. However, some of the keys in a font
-% definition are used as values later on.
-%
-% The only place where this happens (for historical reason mostly)
-% is in the bodyfont definitions and setup, so we can use a limited
-% case.
-%
-% \let \c!big \v!big : expansion time (user)
-% \let \c!small \v!small : expansion time (user)
-% \let \c!text \s!text : definition time
-% % \c!script \s!script : definition time
-% % \c!scriptscript \s!scriptscript : definition time
-% % \c!em : definition time
-% % \c!interlineskip : definition time
-% \let \c!default \s!default : definition time
-% \let \k!default \s!default : definition time
-%
-% Doing the k! definitions local will save us 500 has entries.
-
-\letvalue{\k!prefix!\v!big }\c!big
-\letvalue{\k!prefix!\v!small }\c!small
-\letvalue{\k!prefix!\v!text }\s!text
-\letvalue{\k!prefix!\v!default}\s!default
-
-\let\normalc!big \c!big
-\let\normalc!small \c!small
-\let\normalc!text \c!text % should not happen as we expect text
-\let\normalc!default \c!default
-\let\normalk!default \k!default
-
-\newtoks\everybeginfontdef
-\newtoks\everyendfontdef
-
-\appendtoks
- \let\c!text \s!text
- \let\c!default\s!default
-\to \everybeginfontdef
-
-\appendtoks
- \let\c!text \normalc!text
- \let\c!default\normalc!default
-\to \everyendfontdef
-
-\def\@@beginfontdef
- {\ifcase\@@fontdefhack
- \the\everybeginfontdef
- \fi
- \advance\@@fontdefhack\plusone}
-
-\def\@@endfontdef
- {\advance\@@fontdefhack \minusone
- \ifcase\@@fontdefhack
- \the\everyendfontdef
- \fi}
-
-%%%%%%%%%%%%%%%%%%%%%%%%
-
-\unexpanded\def\definebodyfontenvironment
- {\dotripleempty\dodefinebodyfontenvironment}
-
-\def\dodefinebodyfontenvironment[#1][#2][#3]% class size settings
- {\ifthirdargument
- \@@beginfontdef
- \doifelse{#2}\s!default
- {\getparameters[\??ft\s!default][#3]}
- {\edef\tempbodyfontsize{\thenormalizedbodyfontsize{#2}}%
- \addtocommalist\tempbodyfontsize\bodyfontenvironmentlist
- \@EA\dododefinebodyfontenvironment\@EA[\tempbodyfontsize][#1][#3]}%
- \@@endfontdef
- \else
- \ifx\fontclass\empty\else
- \writestatus\m!fonts{beware: fontclass ignored (if needed use: [fontclass][size][settings])}%
- \fi
- \pushmacro\fontclass
- \let\fontclass\empty
- \definebodyfontenvironment[\fontclass][#1][#2]% change */*
- \popmacro\fontclass
- \fi}
-
-\def\dododefinebodyfontenvironment[#1][#2][#3]% size class settings
- {%\@@beginfontdef % \s!text goes wrong in testing because the 12pt alternative will called when typesetting the test (or so)
- \ifcsname\??ft#2#1\c!em\endcsname
- % we test for em as we assume it to be set
- \else
- % speeding this up saves 0.01 sec on a run (tested 20100817)
- % but some day we will clean this up anyway
- \def\docommand##1%
- {\scratchdimen\csname\??ft\s!default##1\endcsname\dimexpr#1\relax
- \edef\tempbodyfontsize{\thenormalizedbodyfontsize\scratchdimen}%
- \letvalue{\??ft#2#1##1}\tempbodyfontsize}%
- \processcommacommand[\fontrelativesizelist]\docommand
- \copyparameters
- [\??ft#2#1][\??ft\s!default]
- [\c!interlinespace,\c!em]%
- \fi
- \getparameters[\??ft#2#1][#3]%
- %\@@endfontdef
- % new code, see remark
- \ifproductionrun
- \ifcsname\@size@#1\endcsname
- % only once
- \else
- % prevent loop (hence \empty)
- \letvalueempty{\@size@#1}%
- \pushmacro\fontclass % new per 26102009
- \edef\fontclass{#2}% % new per 26102009
- \defineunknownfont{#1}%
- \popmacro\fontclass % new per 26102009
- \fi
- \fi
- % so far
- \setvalue{\@size@#1}{\docompletefontswitch[#1]}}
-
-%D {\bf Remark:} We need to cover the following cases,
-%D otherwise users can get confused:
-%D
-%D \starttyping
-%D \setupbodyfont[23pt]
-%D
-%D \definebodyfontenvironment[23pt]
-%D \setupbodyfont[23pt]
-%D
-%D \definebodyfontenvironment[23pt]
-%D \definebodyfont[23pt][rm,ss,tt][default]
-%D \setupbodyfont[23pt]
-%D \stoptyping
-
-%D Beware: while some font defs can be global, the bodyfont
-%D environment checks local. This means that multiple local
-%D checks resulting in definitions are not that efficient.
-%D So, apart from an occasional switch, one should define an
-%D environment at the outer level.
-
-% \def\checkbodyfontenvironment[#1]%
-% {\definebodyfontenvironment[\fontclass][#1][]}
-%
-% \def\checkbodyfontenvironment[#1]%
-% {\ifcsname\??ft\fontclass#1\c!em\endcsname
-% % we test for em as we assume it to be set
-% \else
-% \definebodyfontenvironment[\fontclass][#1][]%
-% \fi}
-%
-% will be adapted with parent chain:
-
-\def\checkbodyfontenvironment[#1]%
- {\ifcsname\??ft #1\c!em\endcsname\else\docheckbodyfontenvironment\empty {#1}\fi
- \ifcsname\??ft\fontclass#1\c!em\endcsname\else\docheckbodyfontenvironment\fontclass{#1}\fi}
-
-\def\docheckbodyfontenvironment#1#2% class size (simplified version of definebodyfontenvironment)
- {\@@beginfontdef
- \edef\tempbodyfontsize{\thenormalizedbodyfontsize{#2}}%
- \addtocommalist\tempbodyfontsize\bodyfontenvironmentlist
- \def\docommand##1% text script scriptscript x xx big small
- {\setevalue{\??ft#1\tempbodyfontsize##1}%
- {\thenormalizedbodyfontsize{\csname\??ft\s!default##1\endcsname\dimexpr\tempbodyfontsize\relax}}}%
- \processcommacommand[\fontrelativesizelist]\docommand
- \copyparameters % can inherit
- [\??ft#1\tempbodyfontsize][\??ft\s!default]
- [\c!interlinespace,\c!em]%
-% \ifproductionrun
- \ifcsname\@size@\tempbodyfontsize\endcsname \else
- \letvalueempty{\@size@\tempbodyfontsize}% prevent loop
- \pushmacro\fontclass
- \edef\fontclass{#1}%
- \normalexpanded{\defineunknownfont{\tempbodyfontsize}}% we can also inherit here
- \popmacro\fontclass
- \fi
-% \fi
- \setevalue{\@size@#1}{\noexpand\docompletefontswitch[#1]}%
- \@@endfontdef}
-
-% this one already catches both define/setup
-
-\let\setupbodyfontenvironment\definebodyfontenvironment
-
-%D Just a couple of interface macros:
-
-% todo:
-%
-% \letvalueempty{\??ft\s!empty}
-%
-% \def\currentbodyfontvariable#1%
-% {\csname\??ft
-% \ifcsname\??ft\fontclass#1\endcsname\fontclass#1\else
-% \ifcsname\??ft #1\endcsname #1\else \s!empty \fi
-% \fi}
-
-\def\bodyfontvariable#1%
- {\??ft\ifcsname\??ft\fontclass#1\endcsname\fontclass\fi#1}
-
-\def\bodyfontinterlinespecs
- {\bodyfontvariable{\normalizedbodyfontsize\c!interlinespace}}
-
-\def\bodyfontinterlinespace
- {\csname\bodyfontinterlinespecs\endcsname}
-
-%D We default all parameters to the main bodyfont size (begin
-%D \type{#1}), so the next setup is valid too:
-%D
-%D \starttyping
-%D \definebodyfontenvironment[24pt]
-%D \stoptyping
-%D
-%D All parameters can be redefined when needed, so one does
-%D not have to stick to the default ones.
-
-%D \macros
-%D {definebodyfont}
-%D
-%D The next step in defining a bodyfont involves the actual font
-%D files, which can be recognized by their extension
-%D \type{tfm}. Installing those file is often beyond the
-%D scope of the user and up to the system administrator.
-%D
-%D \showsetup{definebodyfont}
-%D
-%D This commands takes three arguments: a (series of) bodyfont
-%D size(s), the style group to which the definitions belong,
-%D and an alternative, as specified by the \TEX\ (math) families,
-%D extended with~a, b~\unknown.
-%D
-%D We show two examples, that show all the alternative
-%D scaling options. The \type{\tfa} alternatives can be
-%D extended with \type{\bfa}, \type{\slb}, etc. or even
-%D \type{e} and higher alternatives. The magic scaled
-%D values are derived from plain \TEX's \type {\magstep}:
-%D
-%D \starttyping
-%D \definebodyfont [12pt] [rm]
-%D [tf=cmr12,
-%D bf=cmbx12,
-%D it=cmti12,
-%D sl=cmsl12,
-%D bi=cmbxti10 at 12pt,
-%D bs=cmbxsl10 at 12pt,
-%D tfa=cmr12 scaled 1.200,
-%D tfb=cmr12 scaled 1.440,
-%D tfc=cmr12 scaled 1.728,
-%D tfd=cmr12 scaled 2.074,
-%D sc=cmcsc10 at 12pt]
-%D
-%D \definebodyfont [12pt,11pt,10pt,9pt,8pt] [rm]
-%D [tf=lbr sa 1,
-%D bf=lbd sa 1,
-%D it=lbi sa 1,
-%D sl=lbsl sa 1,
-%D bi=lbdi sa 1,
-%D bs=lbdi sa 1,
-%D tfa=lbr sa 1.200,
-%D tfb=lbr sa 1.440,
-%D tfc=lbr sa 1.728,
-%D tfd=lbr sa 2.074,
-%D sc=lbr sa 0.833]
-%D \stoptyping
-%D
-%D The second example shows that we can define more sizes at
-%D once. The main difference between these examples is that the
-%D Computer Modern Roman come in many design sizes. This means
-%D that there we cannot define them in bulk using \type{sa}.
-%D Instead of \type{rm} (roman) one can define \type{ss} (sans
-%D serif), \type{tt} (teletype), \type{hw} (hand written),
-%D \type{cg} (calygraphic) and whatever styles.
-%D
-%D The first argument may be a comma separated list. This,
-%D combined with specifications using \type{sa} can save a lot
-%D of typing. Although all arguments should be specified, we
-%D treat the second argument as optional.
-%D
-%D Defining a bodyfont involves two actions: defining the
-%D specific style related alternatives, like \type{\rma},
-%D \type{\bfa} and \type{\rmsla}, and storing the definitions
-%D of their bodyfont size related fonts. The first step is
-%D bodyfont independant but executed every time. This permits
-%D user definitions like \type{\tfw} or \type{\bfq} for real
-%D large alternatives.
-
-\unexpanded\def\definebodyfont
- {\doquadrupleempty\redefinebodyfont}
-
-\def\redefinebodyfont[#1][#2][#3][#4]%
- {\iffourthargument
- \processcommacommand[#1]{\reredefinebodyfont[#2][#3][#4]}%
- \else
- \dodefinebodyfont[#1][#2][#3]%
- \fi}
-
-\def\reredefinebodyfont[#1][#2][#3]#4%
- {\pushmacro\fontclass
- \doifelse{#4}\s!default
- {\let\fontclass\empty}
- {\def\fontclass{#4}}%
- \definebodyfont[#1][#2][#3]%
- \popmacro\fontclass}
-
-\def\dodefinebodyfont[#1][#2][#3]% body|identifier style defs|identifier
- {\ifthirdargument
- \doifnumberelse{#1}
- {\doifassignmentelse{#3}
- {% [12pt] [style] [settings]
- \ifcsname#2\endcsname\else\normalexpanded{\noexpand\definefontstyle[#2][#2]}\fi % new
- \processcommalist[#1]{\dododefinebodyfont{#2}{#3}}}
- {% [12pt] [style] [identifier]
- \dodefinedefaultbodyfont[#1][#2][#3]}} % body style identifier
- {% [identifier] [style] [settings] % see ***
- \setvalue{\s!default#1#2}##1##2{\normalexpanded{\noexpand\xdodefinebodyfont[##1][##2][#3]}}}%
- \else\ifsecondargument
- \definebodyfont[#1][\c!rm][#2]%
- \else
- % Maybe there are default dependencies defined which we can use ([unknown]) and
- % if not, then we have at least to make sure some basics are set up.
- \ifcsname\@size@#1\endcsname \else
- \defineunknownfont{#1}%
- \fi
- \ifcsname\@size@#1\endcsname \else
- \definebodyfont[#1][\c!rm][]%
- \fi
- \fi\fi}
-
-\def\xdodefinebodyfont[#1][#2][#3]% body|identifier style defs|identifier
- {\checkrelativefontsize{#2}% rather new, inherit from other defs
- \ifcsname#2\endcsname\else\normalexpanded{\noexpand\definefontstyle[#2][#2]}\fi % new
- \processcommalist[#1]{\dododefinebodyfont{#2}{#3}}%
- \let\relativefontsize\defaultrelativefontsize}
-
-\def\dododefinebodyfont#1#2#3% style defs body
- {\checkbodyfontenvironment[#3]% just to be sure; can probably be omited now
- \processcommalist[#2]{\dodododefinebodyfont{#1}{#3}}}
-
-\def\dodododefinebodyfont#1#2#3% style body def
- {\dododododefinebodyfont{#1}{#2}[#3]}
-
-\def\dododododefinebodyfont
- {\ifx\fontclass\empty
- \expandafter\dododododefinebodyfontnop
- \else
- \expandafter\dododododefinebodyfontyes
- \fi}
-
-\def\dododododefinebodyfontyes#1% style body def
- {\edef\askedbodyfontstyle{#1}%
- \ifx\askedbodyfontstyle\c!mm
- \expandafter\dodefinebodyfontyesmm
- \else
- \expandafter\dodefinebodyfontyesxx
- \fi\askedbodyfontstyle} % we can get rid of #1
-
-\def\dododododefinebodyfontnop#1% style body def
- {\edef\askedbodyfontstyle{#1}%
- \ifx\askedbodyfontstyle\c!mm
- \expandafter\dodefinebodyfontnopmm
- \else
- \expandafter\dodefinebodyfontnopxx
- \fi\askedbodyfontstyle} % we can get rid of #1
-
-\def\dodefinebodyfontnopxx#1#2[#3#4#5=#6]% style body def
- {\ifcsname#1#3#4#5\endcsname\else\checkbodyfont{#1}{#3#4}{#5}\fi% not \definefontsize[#5]
- \@EA\let\csname*#2#1#3#4#5*\endcsname\undefined
- \unexpanded\@EA\edef\csname#2#1#3#4#5\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#5}{\normalunexpanded{#6}}}}
-
-\def\dodefinebodyfontyesxx#1#2[#3#4#5=#6]% style body def
- {\ifcsname#1#3#4#5\endcsname\else\checkbodyfont{#1}{#3#4}{#5}\fi% not \definefontsize[#5]
- \global\@EA\let\csname*\fontclass#2#1#3#4#5*\endcsname\undefined
- \unexpanded\@EA\xdef\csname\fontclass#2#1#3#4#5\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#5}{\normalunexpanded{#6}}}}
-
-\def\dodefinebodyfontnopmm#1#2[#3#4#5=#6]% style body def
- {\ifcsname#1#3#4#5\endcsname\else\checkbodyfont{#1}{#3#4}{#5}\fi% not \definefontsize[#5]
- \@EA\let\csname*#2#1#3#4#51*\endcsname\undefined
- \@EA\let\csname*#2#1#3#4#52*\endcsname\undefined
- \@EA\let\csname*#2#1#3#4#53*\endcsname\undefined
- \unexpanded\@EA\edef\csname#2#1#3#4#51\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#51}{\normalunexpanded{#6}}}%
- \unexpanded\@EA\edef\csname#2#1#3#4#52\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#52}{\normalunexpanded{#6}}}%
- \unexpanded\@EA\edef\csname#2#1#3#4#53\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#53}{\normalunexpanded{#6}}}}
-
-\def\dodefinebodyfontyesmm#1#2[#3#4#5=#6]% style body def
- {\ifcsname#1#3#4#5\endcsname\else\checkbodyfont{#1}{#3#4}{#5}\fi% not \definefontsize[#5]
- \global\@EA\let\csname*\fontclass#2#1#3#4#51*\endcsname\undefined
- \global\@EA\let\csname*\fontclass#2#1#3#4#52*\endcsname\undefined
- \global\@EA\let\csname*\fontclass#2#1#3#4#53*\endcsname\undefined
- \unexpanded\@EA\xdef\csname\fontclass#2#1#3#4#51\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#51}{\normalunexpanded{#6}}}%
- \unexpanded\@EA\xdef\csname\fontclass#2#1#3#4#52\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#52}{\normalunexpanded{#6}}}%
- \unexpanded\@EA\xdef\csname\fontclass#2#1#3#4#53\endcsname{\noexpand\xxdododefinefont{\number\relativefontsize}{#2}{#2#1#3#4#53}{\normalunexpanded{#6}}}}
-
-\def\checkbodyfont#1% tests for ttsl mmbf
- {\edef\c!!mm{#1}%
- \ifx\c!!mm\c!mm % prevents \max and alike (re)defs
- \expandafter\checkmathbodyfont
- \else
- \expandafter\checktextbodyfont
- \fi{#1}} % no \c!!mm, not expanded later on
-
-% some day we can do an auto-fam if needed
-
-% \def\checkmathbodyfont#1#2#3% style alt size / gdef % #3 can be empty (checking needed as \bf is already defined)
-% {%\message{!m #1 #2 #3!}% #1 #2 #3 = signal
-% %ifcsname #2\endcsname\else\setugvalue {#2}{\setcurrentfontalternative {#2}}\fi % \mr \mb
-% \ifcsname #1\endcsname\else\setugvalue {#1}{\setcurrentfontstyle {#1}}\fi} % \mm
-
-% \def\checktextbodyfont#1#2#3% style alt size / gdef % #3 can be empty (checking needed as \bf is already defined)
-% {%\message{!t #1 #2 #3!}%
-% \ifcsname #1#3\endcsname\else\setugvalue {#1#3}{\setcurrentfontstylesize {#1}{#3}}\fi % \rma
-% \ifcsname #2#3\endcsname\else\setugvalue {#2#3}{\setcurrentfontalternativesize {#2}{#3}}\fi % \sla
-% \ifcsname #1#2#3\endcsname\else\setugvalue {#1#2#3}{\setcurrentfontstylealternativesize{#1}{#2}{#3}}\fi % \rmsla
-% \ifcsname #1\endcsname\else\setugvalue {#1}{\setcurrentfontstyle {#1}}\fi % \rm
-% \ifcsname #2\endcsname\else\setugvalue {#2}{\setcurrentfontalternative {#2}}\fi % \sl
-% \ifcsname #1\c!x\endcsname\else\setugvalue {#1\c!x}{\setcurrentfontxstylealternative {#1}}\fi % \rmx
-% \ifcsname#1\c!xx\endcsname\else\setugvalue{#1\c!xx}{\setcurrentfontxxstylealternative {#1}}\fi % \rmxx
-% \ifcsname #2\c!x\endcsname\else\setugvalue {#2\c!x}{\setcurrentfontxalternative {#2}}\fi % \slx
-% \ifcsname#2\c!xx\endcsname\else\setugvalue{#2\c!xx}{\setcurrentfontxxalternative {#2}}\fi % \slxx
-% \ifcsname #1#2\endcsname\else\setugvalue {#1#2}{\setcurrentfontstylealternative {#1}{#2}}\fi} % \rmsl
-
-\def\checkmathbodyfont#1#2#3% style alt size / gdef % #3 can be empty (checking needed as \bf is already defined)
- {%\message{!m #1 #2 #3!}% #1 #2 #3 = signal
- %setugvalue {#2}{\setcurrentfontalternative {#2}}% % \mr \mb
- \setugvalue {#1}{\setcurrentfontstyle {#1}}} % \mm
-
-\def\checktextbodyfont#1#2#3% style alt size / gdef % #3 can be empty (checking needed as \bf is already defined)
- {%\message{!t #1 #2 #3!}% % beware, some can be defined already
- \setugvalue {#1#3}{\setcurrentfontstylesize {#1}{#3}}% % \rma
- \setugvalue {#2#3}{\setcurrentfontalternativesize {#2}{#3}}% % \sla
- \setugvalue {#1#2#3}{\setcurrentfontstylealternativesize{#1}{#2}{#3}}% % \rmsla
- \ifcsname\s!normal#1\endcsname % text/math check
- \expandafter\let\csname#1\expandafter\endcsname\csname\s!normal#1\endcsname
- \else
- \setugvalue {#1}{\setcurrentfontstyle {#1}}% % \rm
- \fi
- \ifcsname\s!normal#2\endcsname % text/math check
- \expandafter\let\csname#2\expandafter\endcsname\csname\s!normal#2\endcsname
- \else
- \setugvalue {#2}{\setcurrentfontalternative {#2}}% % \sl
- \fi
- \setugvalue {#1\c!x}{\setcurrentfontxstylealternative {#1}}% % \rmx
- \setugvalue{#1\c!xx}{\setcurrentfontxxstylealternative {#1}}% % \rmxx
- \setugvalue {#2\c!x}{\setcurrentfontxalternative {#2}}% % \slx
- \setugvalue{#2\c!xx}{\setcurrentfontxxalternative {#2}}% % \slxx
- \setugvalue {#1#2}{\setcurrentfontstylealternative {#1}{#2}}} % \rmsl
-
-\def\dodefinedefaultbodyfont[#1][#2][#3]% sizes styles identifier
- {\def\dododefinedefaultbodyfont##1%
- {\def\dodododefinedefaultbodyfont####1%
- {\def\dododododefinedefaultbodyfont########1%
- {\ifcsname\s!default########1####1\endcsname
- % [12pt] [style] [identifier]
- \csname\s!default########1####1\endcsname{##1}{####1}%
- \fi}%
- \processcommalist[#3]\dododododefinedefaultbodyfont}%
- \processcommalist[#2]\dodododefinedefaultbodyfont}%
- \processcommalist[#1]\dododefinedefaultbodyfont}
-
-%D Unknown families are added to the family list! For the
-%D moment we also set the direct calls here. Some day a better
-%D solution will be implemented. The good news is that unknown
-%D fonts are defined automatically.
-
-\newif\ifdefiningunknownfont
-
-\def\dodefineunknownfont#1#2%
- {\ifcsname\??ft\s!default#2\endcsname
- \donetrue
- \edef\tempbodyfontsize{\thenormalizedbodyfontsize{\csname\??ft\s!default#2\endcsname\dimexpr#1\relax}}%
- \letvalue{\??ft#1#2}\tempbodyfontsize
- \fi}
-
-\def\dodefineunknownbodyfont#1#2% see ***
- {\ifcsname\s!default\s!default#2\endcsname % somehow related to */*
- \donetrue
- \csname\s!default\s!default#2\endcsname{#1}{#2}%
- \fi}
-
-\def\dodefineunknownsubfont#1#2%
- {\ifcsname\@size@\csname\??ft#1#2\endcsname\endcsname
- \else
- \donetrue
- \defineunknownfont{\csname\??ft#1#2\endcsname}%
- \fi}
-
-\let\c!savedtext\c!text
-
-\unexpanded\def\defineunknownfont#1%
- {\let\c!text\s!text
- \donefalse
- \processcommacommand[\fontrelativesizelist]{\dodefineunknownfont{#1}}%
- \let\c!text\c!savedtext
- \ifdone
- \donefalse
- \processcommacommand
- [\fontstylelist]
- {\dodefineunknownbodyfont{#1}}%
- \ifdone
- \donefalse
- \setvalue{\@size@#1}{\docompletefontswitch[#1]}%
- \ifdefiningunknownfont \else
- \definingunknownfonttrue
- \processcommacommand[\fontrelativesizelist]{\dodefineunknownsubfont{#1}}%
- \definingunknownfontfalse
- \fi
- \fi
- \ifdone
- \showmessage\m!fonts{14}{#1}%
- \fi
- \fi}
-
-%D These macros show that quite some definitions take place.
-%D Fonts are not loaded yet! This means that at format
-%D generation time, no font files are preloaded.
-
-%D \macros
-%D {everybodyfont,Everybodyfont,everyglobalbodyfont}
-%D
-%D Every change in bodyfont size has conseqences for the baseline
-%D distance and skips between paragraphs. These are initialized
-%D in other modules. Here we only provide the hooks that
-%D garantees their handling.
-
-%D At the system level one can initialize thing like:
-%D
-%D \starttyping
-%D \appendtoks \setupspacing \to \everybodyfont
-%D \stoptyping
-%D
-%D While users can add their own non standard commands like:
-%D
-%D \starttyping
-%D \EveryBodyFont{\message{changing to bodyfont \the\bodyfontsize}}
-%D \stoptyping
-%D
-%D Personnaly I never felt the need for such extensions, but
-%D at least its possible.
-
-%D \macros
-%D {globalbodyfontsize,localbodyfontsize}
-%D
-%D Next we'll do the tough job of font switching. Here we
-%D have to distinguish between the global (overal) bodyfont
-%D size and the local (sometimes in the textflow) size. We
-%D store these dimensions in two \DIMENSION\ registers.
-
-\ifdefined\globalbodyfontsize\else \newdimen\globalbodyfontsize \fi \globalbodyfontsize=12pt
-\ifdefined\localbodyfontsize \else \newdimen\localbodyfontsize \fi \localbodyfontsize =\globalbodyfontsize
-
-%D \macros
-%D {bodyfontsize}
-%D
-%D These two registers are not to be misused in calculations.
-%D For this purpose we keep a copy:
-
-\newdimen\bodyfontsize \bodyfontsize=\globalbodyfontsize
-
-%D \macros
-%D {bodyfontfactor,bodyfontpoints}
-%D
-%D For multiplication purposes we keep an auxiliary counter
-%D and macro (here the expansion is not explicitly needed):
-
-\newcount\bodyfontpoints \dimensiontocount\bodyfontsize\bodyfontpoints
-
-\edef\bodyfontfactor{\withoutpt\the\bodyfontsize}
-
-%D When we assign for instance 12pt to a \DIMENSION\ register
-%D the \type{\the}'d value comes out as 12.0pt, which is
-%D often not the way users specify the bodyfont size. Therefore
-%D we also store the normalized value.
-
-\setnewconstant\fontdigits\plustwo % was 1
-
-% \def\normalizebodyfontsize#1\to#2%
-% {\@EA\@EA\@EA\donormalizedbodyfontsize\@EA\WITHOUTPT\the\dimexpr#1+\ifcase\fontdigits.5\or.05\or.005\fi\points\relax000\to#2}
-%
-% \def\donormalizedbodyfontsize#1.#2#3#4#5\to#6% \points ?
-% {\edef#6% not \ifcase#2\else due to \relax adding
-% {#1%
-% \ifcase\fontdigits
-% \or \ifcase#2 \else .#2\fi % 1
-% \or \ifcase#2#3 \else .#2\ifcase#3 \else #3\fi\fi % 2
-% \else \ifcase#2#3#4 \else .#2\ifcase#4 \ifcase#3 \else#3\fi \else#3#4\fi\fi % 3
-% \fi
-% \s!pt}}
-
-\def\normalizebodyfontsize#1\to#2%
- {\edef#2{\ctxcommand{nbfs(\number\dimexpr#1\relax,\number\fontdigits)}}}
-
-\def\thenormalizedbodyfontsize#1%
- {\ctxcommand{nbfs(\number\dimexpr#1\relax,\number\fontdigits)}}
-
-\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize}
-\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
-\edef\normalizedbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
-
-%D \macros
-%D {fontstyle,fontalternative,fontsize}
-%D
-%D Within a bodyfont, fonts can come in different sizes. For
-%D instance \type{\tf} is accompanied by \type{\tfa},
-%D \type{\tfb} etc. The first two characters denote the
-%D alternative, while the third character in these sequences
-%D represents the size. The actual size is saved in a macro
-%D
-%D The style, being roman (\type{\rm}), sans serif (\type{\ss})
-%D etc. is also available in a macro in \type{rm}, \type{ss}
-%D etc. form:
-
-\let\defaultfontalternative = \c!tf
-\let\defaultfontstyle = \empty
-\let\defaultfontsize = \empty
-
-\let\fontalternative = \defaultfontalternative
-\let\fontstyle = \defaultfontstyle
-\let\fontsize = \defaultfontsize
-
-%D When \type {\loadfontfileoncetrue}, such files are
-%D only loaded once! This permits redundant loading, but at
-%D the same time forced grouping when we want continuously mix
-%D all kind of font, which of course is a kind of
-%D typographically sin. The \type{"} is made inactive if
-%D needed to prevent problems with loading files that use this
-%D character in numbers.
-
-% can be made faster (only used internally now)
-
-\def\doswitchpoints[#1]%
- {\normalexpanded{\dodoswitchpoints{#1}}}
-
-\unexpanded\def\dodoswitchpoints#1%
- {\ifcsname\@size@#1\endcsname \else
- \defineunknownfont{#1}%
- \fi%
- %\defineunknownfontstyles{#1}%
- \ifcsname\@size@#1\endcsname
- \csname\@size@#1\endcsname
- \localbodyfontsize#1\relax
- % \edef\fontbody{\fontbody}% to be tested but we can clean up mkiv further
- \edef\normalizedbodyfontsize{\thenormalizedbodyfontsize\localbodyfontsize}%
- \checkbodyfontenvironment[\normalizedbodyfontsize]%
- \else
- \showmessage\m!fonts4{#1}%
- \fi}
-
-\unexpanded\def\doswitchstyle[#1]%
- {\ifcsname\@style@#1\endcsname
- \csname\@style@#1\endcsname
- \edef\fontstyle{#1}%
- \ifmmode\mr\fi % in order to be compatible with \rm in math mode
- % \the\everybodyfont % cleaner, in setting size as well as style
- \else
- \showmessage\m!fonts5{#1}%
- \fi}
-
-%D \TEX\ loads font metric files like \type{cmr10.tfm} and
-%D \type{tir.tfm} only once. In \PLAIN\ \TEX\ some font files
-%D are {\em preloaded}. This means that the font files are
-%D loaded, but not accessible yet by name. This is accomplished
-%D by saying:
-%D
-%D \starttyping
-%D \font\preloaded=cmr10 at 11pt
-%D \stoptyping
-%D
-%D and using the name \type{\preloaded} again and again, so
-%D fonts are indeed loaded, but unnamed, and therefore
-%D unaccessible. In \CONTEXT\ we don't preload fonts, not even
-%D the \PLAIN\ \TEX\ ones, although users can access them. Now
-%D why is this done?
-
-%D Defining fonts using \type{\definebodyfont} takes time, so we
-%D prefer to predefine at least the Computer Modern Roman
-%D fonts. However, loading all those fonts at definition time
-%D would take both time and space. But even worse, once fonts
-%D are loaded into memory, their encoding vector is fixed,
-%D which is a handicap when we want to distribute the compact
-%D \type{fmt} files. So what we want to do is defining fonts in
-%D a way that postpones the loading. We accomplish this by only
-%D loading the fonts when we switch to another bodyfont size.
-%D Among the other alternatives, such as loading the font at
-%D the moment of activation and redefining the activation
-%D macro afterwards, this proved to be the most efficient
-%D alternative.
-%D
-%D The next few macros take care of the one exeption on this
-%D scheme. When at format generation time we load the default
-%D font file, the one that defines the Computer Modern Fonts,
-%D we don't want the fonts metrics to end up in the format
-%D file, so we temporary prohibit loading. This means that at
-%D runtime we have to load the default bodyfont size just before
-%D we start typesetting.
-%D
-%D Therefore we have to signal the font switching macros that
-%D we are preloading fonts.
-%D
-%D \macros
-%D {preloadfonts}
-%D
-%D Preloading is only called for once, during the startup
-%D sequence of a session. After the loading job is done, the
-%D macro relaxes itself and reset the signal.
-
-% \fontdimen1\nullfont 0\scaledpoint
-% \fontdimen2\nullfont 256377\scaledpoint
-% \fontdimen3\nullfont 128188\scaledpoint
-% \fontdimen4\nullfont 85459\scaledpoint
-% \fontdimen5\nullfont 338952\scaledpoint
-% \fontdimen6\nullfont 786432\scaledpoint
-% \fontdimen7\nullfont 85459\scaledpoint
-
-\fontslantperpoint \nullfont 0\scaledpoint
-\fontinterwordspace \nullfont 256377\scaledpoint
-\fontinterwordstretch\nullfont 128188\scaledpoint
-\fontinterwordshrink \nullfont 85459\scaledpoint
-\fontexheight \nullfont 338952\scaledpoint
-\fontemwidth \nullfont 786432\scaledpoint
-\fontextraspace \nullfont 85459\scaledpoint
-
-\fetchruntimecommand \showfontparameters {\f!fontprefix\s!run}
-
-\def\resetnullfont % this is needed because some macro packages (tikz) misuse \nullfont
- {\dorecurse7{\fontdimen\recurselevel\nullfont\zeropoint}%
- \ctxlua{fonts.definers.resetnullfont()}% in luatex 0.70 this will also do the previous
- \globallet\resetnullfont\relax}
-
-\def\preloaddefaultfonts
- {\resetpreloadfonts
- \setupbodyfont[modern,\fontstyle,\fontbody]%
- \showmessage\m!fonts6{fallback modern \fontstyle\normalspace\normalizedbodyfontsize}}
-
-\def\preloaddefaultfontsmm
- {\writestatus\m!fonts{preloading latin modern fonts (math)}%
- \definetypeface[\fontclass][\c!mm][\s!math][modern][\s!default]%
- \showmessage\m!fonts6{fallback modern mm \normalizedbodyfontsize}}
-
-\def\preloaddefaultfontstt
- {\writestatus\m!fonts{preloading latin modern fonts (mono)}%
- \definetypeface[\fontclass][\c!tt][\s!mono][modern][\s!default]%
- \showmessage\m!fonts6{fallback modern tt \normalizedbodyfontsize}}
-
-\def\resetpreloadfonts
- {\glet\preloaddefaultfonts \relax
- %\glet\preloaddefaultfontstt \relax
- %\glet\preloaddefaultfontsmm \relax
- \glet\zerostagepreloadfonts \relax
- \glet\firststagepreloadfonts \relax
- \glet\secondstagepreloadfonts\relax
- %\glet\thirdstagepreloadfonts \relax
- \glet\fourthstagepreloadfonts\relax
- \global\everyhbox\emptytoks
- \global\everyvbox\emptytoks
- \resetnullfont}
-
-\def\resetcheckedfonts
- {\glet\preloaddefaultfontstt \relax
- \glet\preloaddefaultfontsmm \relax
- \glet\thirdstagepreloadfonts \relax}
-
-\def\dozerostagepreloadfonts
- {\definedfont[\s!file:lmmono10-regular sa 1]}
-
-\def\zerostagepreloadfonts
- {\writestatus\m!fonts{beware: no fonts are loaded yet, using 'lm mono' in box}%
- \glet\zerostagepreloadfonts\dozerostagepreloadfonts
- \zerostagepreloadfonts}
-
-\appendtoks
- \everyhbox{\zerostagepreloadfonts}
- \everyvbox{\zerostagepreloadfonts}
-\to \everydump
-
-\def\firststagepreloadfonts % see core-def.mkiv
- {\doifmodeelse{*nofonts}
- {\writestatus\m!fonts{latin modern fonts are not preloaded}}
- {\preloaddefaultfonts
- \writestatus\m!fonts{preloading latin modern fonts (first stage)}}}
-
-\def\secondstagepreloadfonts % see core-def.mkiv
- {\writestatus\m!fonts{preloading latin modern fonts (second stage)}%
- \preloaddefaultfonts}
-
-\def\thirdstagepreloadfonts % always
- {\ifx\fontclass\empty
- \writestatus\m!fonts{preloading latin modern fonts (third stage)}%
- \preloaddefaultfonts
- \else
- \resetpreloadfonts
- \pushmacro\fontstyle
- \ifcsname\fontclass\c!mm\s!features\endcsname \else
- \preloaddefaultfontsmm
- \fi
- \ifcsname\fontclass\c!tt\s!features\endcsname \else
- \preloaddefaultfontstt
- \fi
- \popmacro\fontstyle
- \resetcheckedfonts % reset third, mm and tt
- \setupbodyfont[\fontstyle]%
- \fi}
-
-\def\fourthstagepreloadfonts
- {\begingroup
- %ifzeropt\fontcharwd\font\number`!\relax
- \setbox\scratchbox\hbox{context}%
- \ifzeropt\wd\scratchbox
- \writeline
- \writestatus\m!fonts{!! No bodyfont has been defined and no defaults have been}%
- \writestatus\m!fonts{!! loaded (maybe due to a missing \string\starttext).}%
- \writeline
- \fi
- \resetpreloadfonts
- \endgroup}
-
-%D Here comes the main font switching macros. These macros
-%D handle changes in size as well as returning to the global
-%D bodyfont size.
-
-\def\dosetfont#1#2% #1 = set/switch state
- {\doifelse{#2}\v!global
- {\restoreglobalbodyfont}
- {\processcommacommand[#2]{\dodocheckfontsize}%
- \processcommacommand[#2]{\dodosetfont{#1}}%
- \ifproductionrun
- \thirdstagepreloadfonts
- \doswitchpoints[\normalizedbodyfontsize]%
- \doswitchstyle[\fontstyle]%
- \ifx\defaultfontclass\empty
- \let\defaultfontclass\fontclass
- \fi
- \fi}%
- \currentxfontsize\zerocount}
-
-\def\dodocheckfontsize#1%
- {\doifnumberelse{#1}{\checkbodyfontenvironment[#1]}\donothing}
-
-\def\dodosetfont#1#2% #1 = set/switch state | check fo rempty, else space
- {\doifsomething{#2}{\dododosetfont{#1}{#2}{\showmessage\m!fonts4{#2}}}}
-
-\def\dododosetfont#1#2#3% #1 = set/switch state ! ! ! !could also be used for mkii
- {\doifnumberelse{#2}\dodododosetfont\redododosetfont{#1}{#2}{#3}}
-
-\def\redododosetfont#1#2#3% #1 = set/switch state ! ! ! !could also be used for mkii
- {\edef\expandedfontthing{#2}%
- \def\interfacedfontsize{\normalizedbodyfontsize\interfaced\expandedfontthing}%
- \ifcsname\??ft\interfacedfontsize\endcsname
- \edef\fontstep{\csname\bodyfontvariable\interfacedfontsize\endcsname}%
- \normalexpanded{\noexpand\dodododosetfont{#1}{\fontstep}}{#3}%
- \else\ifx\expandedfontthing\v!reset
- \let\fontstyle\empty % new 31/7/2006
- \let\fontsize \empty
- \else
- \ifcsname\@style@\expandedfontthing\endcsname
- \let\fontstyle\expandedfontthing
- \else
- \setcurrentfontclass\expandedfontthing
- \ifcase#1\relax
- \let\globalfontclass\globalfontclass
- \else
- \let\globalfontclass\fontclass
- \fi
- \ifx\fontclass\empty
- \let\fontstyle\c!rm
- \else\ifcsname\??tf\fontclass\s!default\endcsname
- \edef\fontstyle{\csname\??tf\fontclass\s!default\endcsname}%
- \else
- \let\fontstyle\c!rm
- \fi\fi
- \fi
- \fi\fi}
-
-\def\dodododosetfont#1#2#3% #1 = set/switch state
- {\edef\normalizedsetfont{\thenormalizedbodyfontsize{#2}}%
- \ifcsname\@size@\normalizedsetfont\endcsname \else
- \defineunknownfont{#2}%
- \fi
- \ifcsname\@size@\normalizedsetfont\endcsname
- \localbodyfontsize\normalizedsetfont
- \let\normalizedbodyfontsize\normalizedsetfont
- \else
- #3\dosetsubstitutefont{#1}{#2}%
- \fi}
-
-%D When users specify for instance a 13 point bodyfont while no
-%D such bodyfont is defined, the system automatically tries to
-%D find a best fit, that is the nearest smaller defined
-%D bodyfontzize. A smaller one is definitely better than a larger
-%D one, simply because otherwise a lot of overfull box messages
-%D are more probable to occur. By taking a value slightly
-%D smaller than half a point, we can use the next method.
-
-\def\dosetsubstitutefont#1#2% #1 = set/switch state
- {\scratchdimen#2\relax
- \advance\scratchdimen .499\points
- \dimensiontocount\scratchdimen\scratchcounter
- \advance\scratchcounter \minusone
- \ifnum\scratchcounter>\plusthree
- \dododosetfont{#1}{\the\scratchcounter\s!pt}{}%
- \fi}
-
-% The following bunch of macros deals with the (run time)
-% expansion of names onto the definitions made by \type
-% {\definebodyfont}.
-
-% \let\fontbody \empty % ... 10pt 11pt 12pt ...
-% \let\fontstyle \empty % rm ss tt mm hw cg ...
-% \let\fontalternative\empty % tf bf sl it bs bi sc ...
-% \let\fontsize \empty % xy-abcd ...
-
-\def\defaultfontbody{\normalizedbodyfontsize}
-
-\let\fontbody\defaultfontbody
-
-\let\fontclass\empty \let\globalfontclass\fontclass
-
-% we need to check the fontclass
-
-\def\registerfontclass#1%
- {\letgvalue{\@fontclass@#1}\v!yes} % global ?
-
-\edef\@no@fontclass@{\@fontclass@:?:}
-
-\def\setcurrentfontclass#1%
- {\ifcsname\@fontclass@#1\endcsname
- \edef\fontclass{#1}%
- \else\ifcsname\@no@fontclass@#1\endcsname
- % already tried
- \else\ifcase\currentgrouplevel
- \trycurrentfontclass{#1}%
- \fi\fi\fi}
-
-\def\savefontclassparameters#1#2#3#4#5% #1=rm|ss|.. rscale features fallbacks goodies
- {\setxvalue{\fontclass#1\s!rscale }{#2}%
- \setxvalue{\fontclass#1\s!features }{#3}%
- \setxvalue{\fontclass#1\s!fallbacks}{#4}%
- \setxvalue{\fontclass#1\s!goodies }{#5}}
-
-\settrue\autotypescripts
-
-\def\trycurrentfontclass#1%
- {\ifconditional\autotypescripts
- % try to load typescript #1
- \usetypescript[#1]%
- \ifcsname\@fontclass@#1\endcsname
- \edef\fontclass{#1}%
- \else
- % try to load type-#1.mkiv
- \usetypescriptfile[\f!typeprefix#1]%
- % try to load typescript #1
- \usetypescript[#1]%
- \ifcsname\@fontclass@#1\endcsname
- \edef\fontclass{#1}%
- \else
- % todo: message
- \letvalueempty{\@no@fontclass@#1}%
- \fi
- \fi
- \else
- % todo: message
- \letvalueempty{\@no@fontclass@#1}%
- \fi}
-
-\let\defaultfontstyle \c!rm
-\let\defaultfontalternative \c!tf
-\let\defaultfontsize \empty
-
-%D \macros
-%D {bigmath,nobigmath}
-%D
-%D We can inhibit this slow||downer with:
-
-% these can best be combined
-
-% 0=never 1=everymath 2=always
-
-\setnewconstant\synchronizebigmathflag\plusone
-
-\appendtoks
- \ifcase\synchronizebigmathflag
- % never
- \or
- \synchronizebigmath
- \or
- % always
- \fi
-\to \everymathematics
-
-\def\nobigmath {\synchronizebigmathflag\zerocount}
-\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath}
-\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath}
-
-\let\bigmathfontsize\empty
-
-\def\synchronizebigmath
- {\ifx\bigmathfontsize\fontsize
- % already in sync
- \else
- \let\bigmathfontsize\fontsize
- \synchronizemath
- \fi}
-
-\def\checkbigmathsynchronization
- {\ifcase\synchronizebigmathflag
- % never
- \or
- \ifmmode \synchronizebigmath \fi
- \or
- \synchronizebigmath
- \fi}
-
-%D So far for synchronisation. (We can inline the following macros.)
-
-\def\dosetcurrentfontsize#1%
- {\edef\fontsize{#1}%
- \checkbigmathsynchronization}
-
-\def\dosetcurrentfontalternative#1%
- {\edef\fontalternative{#1}}
-
-\def\setcurrentfont#1#2#3#4%
- {%\message{[1 #1 #2 #3 #4]}%
- \edef\fontbody{#1}%
- \edef\fontstyle{#2}%
- \dosetcurrentfontalternative{#3}%
- \dosetcurrentfontsize{#4}%
- \synchronizefont}
-
-\def\setcurrentfontbody#1%
- {%\message{[2 #1]}%
- \edef\fontbody{#1}%
- \synchronizefont}
-
-% For Taco: optional fall backs:
-
-\ifx\checkfontclass\undefined \let\checkfontclass\gobbleoneargument \fi % implemented in type-ini
-
-% \def\setcurrentfontstyle#1%
-% {%\message{[3 #1]}%
-% \checkfontclass{#1}%
-% \edef\fontstyle{#1}%
-% \ifmmode\mr\fi % otherwise \rm not downward compatible
-% \synchronizefont}
-
-\def\setcurrentfontstyle#1%
- {%\message{[3 #1]}%
- \edef\fontstyle{#1}%
- \checkfontclass\fontstyle
- \ifmmode\mr\fi % otherwise \rm not downward compatible
- \synchronizefont}
-
-\def\setcurrentfontbodyalternative#1#2%
- {%\message{[4 #1 #2]}%
- \edef\fontbody{#1}%
- \dosetcurrentfontalternative{#2}%
- \synchronizefont}
-
-\def\setcurrentfontalternative#1%
- {%\message{[5 #1]}%
- \dosetcurrentfontalternative{#1}%
- \synchronizefont}
-
-\def\setcurrentfontsize#1%
- {%\message{[6 #1]}%
- \dosetcurrentfontsize{#1}%
- \synchronizefont}
-
-\def\setcurrentfontstylealternative#1#2% \rmsl
- {%\message{[7 #1 #2]}%
- \edef\fontstyle{#1}%
- \dosetcurrentfontalternative{#2}%
- \synchronizefont}
-
-\def\setcurrentfontstylesize#1#2% \rmsla
- {%\message{[8 #1 #2]}%
- \edef\fontstyle{#1}%
- \dosetcurrentfontsize{#2}%
- \synchronizefont}
-
-\def\setcurrentfontalternativesize#1#2% \sla
- {%\message{[9 #1 #2]}%
- \dosetcurrentfontalternative{#1}%
- \dosetcurrentfontsize{#2}%
- \synchronizefont}
-
-\def\setcurrentfontstylealternativesize#1#2#3% \rmsla
- {%\message{[10 #1 #2 #3]}%
- \edef\fontstyle{#1}%
- \dosetcurrentfontalternative{#2}%
- \dosetcurrentfontsize{#3}%
- \synchronizefont}
-
-%D In principle one can assign alternative fallback routines.
-%D Some day we will.
-
-\newtoks\fontstrategies
-\newif\iftryingfont
-
-\let\fontstrategy\relax
-
-\def\synchronizefont % we can have dups i.e. no need to let fontstrategy
- {\tryingfonttrue
- \ifx\fontclass\empty
- \applyfontstrategies
- \else
- \applyfontclassstrategies
- \fi
- \autofontsizefalse
- \ifskipfontcharacteristics
- \setfontcharacteristics
- \the\everyfontswitch
- \fi}
-
-\def\fontclassstrategiesa % --- --- --- --- % pt tt bf a
- {\ifcsname\fontclass\fontbody \fontstyle \fontalternative \fontsize\endcsname
- \autofontsizefalse
- \csname\fontclass\fontbody \fontstyle \fontalternative \fontsize\endcsname
- \else
- \expandafter\fontclassstrategiesb
- \fi}
-
-\def\fontclassstrategiesb % --- --- --- def % pt tt bf
- {\ifcsname\fontclass\fontbody \fontstyle \fontalternative \defaultfontsize\endcsname
- \autofontsizetrue
- \csname\fontclass\fontbody \fontstyle \fontalternative \defaultfontsize\endcsname
- \else
- \expandafter\fontclassstrategiesc
- \fi}
-
-\def\fontclassstrategiesc % --- --- def --- % pt tt tf a
- {\ifcsname\fontclass\fontbody \fontstyle \defaultfontalternative \fontsize\endcsname
- \autofontsizetrue
- \csname\fontclass\fontbody \fontstyle \defaultfontalternative \fontsize\endcsname
- \else
- \expandafter\fontclassstrategiesd
- \fi}
-
-\def\fontclassstrategiesd % --- --- def def % pt tt tf
- {\ifcsname\fontclass\fontbody \fontstyle \defaultfontalternative \defaultfontsize\endcsname
- \autofontsizetrue
- \csname\fontclass\fontbody \fontstyle \defaultfontalternative \defaultfontsize\endcsname
- \else
- \expandafter\fontclassstrategiese
- \fi}
-
-\def\fontclassstrategiese % --- def def def % pt rm tf
- {\ifcsname\fontclass\fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
- \autofontsizefalse
- \csname\fontclass\fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
- \else
- \expandafter\fontclassstrategiesf
- \fi}
-
-\def\fontclassstrategiesf % def def def def % rm tf
- {\ifcsname\fontclass\defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
- \autofontsizetrue
- \csname\fontclass\defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
- \else
- \expandafter\fontstrategiesa
- \fi}
-
-% no class
-
-\def\fontstrategiesa % --- --- --- --- % pt tt bf a
- {\ifcsname\fontbody \fontstyle \fontalternative \fontsize\endcsname
- \autofontsizefalse
- \csname\fontbody \fontstyle \fontalternative \fontsize\endcsname
- \else
- \expandafter\fontstrategiesb
- \fi}
-
-\def\fontstrategiesb % --- --- --- --- % pt tt bf a
- {\ifcsname\fontbody \fontstyle \fontalternative \defaultfontsize\endcsname
- \autofontsizetrue
- \csname\fontbody \fontstyle \fontalternative \defaultfontsize\endcsname
- \else
- \expandafter\fontstrategiesc
- \fi}
-
-\def\fontstrategiesc % --- --- --- --- % pt tt bf a
- {\ifcsname\fontbody \fontstyle \defaultfontalternative \fontsize\endcsname
- \autofontsizetrue
- \csname\fontbody \fontstyle \defaultfontalternative \fontsize\endcsname
- \else
- \expandafter\fontstrategiesd
- \fi}
-
-\def\fontstrategiesd % --- --- --- --- % pt tt bf a
- {\ifcsname\fontbody \fontstyle \defaultfontalternative \defaultfontsize\endcsname
- \autofontsizetrue
- \csname\fontbody \fontstyle \defaultfontalternative \defaultfontsize\endcsname
- \else
- \expandafter\fontstrategiese
- \fi}
-
-\def\fontstrategiese % --- --- --- --- % pt tt bf a
- {\ifcsname\fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
- \autofontsizefalse
- \csname\fontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
- \else
- \expandafter\fontstrategiesf
- \fi}
-
-\def\fontstrategiesf % --- --- --- --- % pt tt bf a
- {\ifcsname\defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
- \autofontsizetrue
- \csname\defaultfontbody \defaultfontstyle \defaultfontalternative \defaultfontsize\endcsname
- \fi}
-
-\let\applyfontstrategies \fontstrategiesa
-\let\applyfontclassstrategies\fontclassstrategiesa
-
-%D Let's synchronize:
-
-\newif\ifsynchronizefonts \synchronizefontstrue
-
-\prependtoks
- \ifsynchronizefonts
- \synchronizemath
- \synchronizefont % problem: syncs last font
- \fi
-\to \everybodyfont
-
-%D Setting the normal sizes as well as the x and xx smaller
-%D sizes is accomplished by the next set of macros. When in
-%D math mode, the commands \type{\tx} and \type{\txx} are
-%D just a switch to the script and double script styles, but
-%D in text mode the values defined by the bodyfontenvironment are
-%D used. Here we also set \type{\currentxfontsize}.
-
-\def\dosetcurrentfontxxxalternative#1#2#3#4%
- {\currentxfontsize#2\relax
- \ifmmode
- #4%
- \else\ifcsname\bodyfontvariable{\normalizedbodyfontsize#3}\endcsname
- \setcurrentfontbodyalternative{\csname\bodyfontvariable\normalizedbodyfontsize#3\endcsname}{#1}%
- \fi\fi}
-
-\def\setcurrentfontxalternative#1%
- {\dosetcurrentfontxxxalternative{#1}1\c!x\scriptstyle
- \let\tx\txx}
-
-\def\setcurrentfontxxalternative#1%
- {\dosetcurrentfontxxxalternative{#1}2\c!xx\scriptscriptstyle
- \let\tx\empty
- \let\txx\empty}
-
-\def\checknestedxfontsize % option
- {\ifcase\currentxfontsize\else\ifx\fontsize\empty\else
- \currentxfontsize\zerocount
- \let\fontsize\empty
- \let\tx\normaltx
- \let\txx\normaltxx
- \fi\fi}
-
-\def\setcurrentfontxalternative#1%
- {\checknestedxfontsize
- \dosetcurrentfontxxxalternative{#1}1\c!x\scriptstyle
- \let\tx\txx}
-
-\def\setcurrentfontxxalternative#1%
- {\checknestedxfontsize
- \dosetcurrentfontxxxalternative{#1}2\c!xx\scriptscriptstyle
- \let\tx\empty
- \let\txx\empty}
-
-% This alterative is not really needed, but for old time's sake
-% we keep it there. We can speed it up when needed.
-
-\def\setcurrentfontxstylealternative #1{\csname#1\endcsname\tx}
-\def\setcurrentfontxxstylealternative#1{\csname#1\endcsname\txx}
-
-%D These macros also show us that when we call for \type{\tx},
-%D this macro is redefined to be \type{\txx}. Therefore calls
-%D like:
-%D
-%D \startbuffer
-%D {small \tx is \tx beautiful}
-%D {small \tx is \txx beautiful}
-%D {small \txx is \tx beautiful}
-%D {small \txx is \txx beautiful}
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D result in:
-%D
-%D \startvoorbeeld
-%D \startlines
-%D \getbuffer
-%D \stoplines
-%D \stopvoorbeeld
-%D
-%D Setting the main size involves the style list and therefore
-%D takes a bit more time. Keep in mind that the fontsize is
-%D represented by a character or empty.
-
-\unexpanded\def\tx {\setcurrentfontxalternative \fontalternative}
-\unexpanded\def\txx{\setcurrentfontxxalternative\fontalternative}
-
-\let\normaltx \tx
-\let\normaltxx\txx
-
-%D \macros
-%D {definefontstyle}
-%D
-%D When setting of switching the overall style we can use the
-%D short identifier like rm and ss, but when defined we can
-%D also use more verbose names like roman or sansserif. Such
-%D names are defined by:
-%D
-%D \starttyping
-%D \definefontstyle [serif,rm] [rm]
-%D \definefontstyle [sansserif,ss] [ss]
-%D \stoptyping
-
-\def\dodefinefontstyle[#1][#2]%
- {\rawdoifinsetelse{#2}{\fontstylelist}
- {%\debuggerinfo\m!fonts{unknown style #2}%
- }
- {%\debuggerinfo\m!fonts8{#2\space (#1)}%
- \addtocommalist{#2}\fontstylelist}%
- % check kan hier
- \def\docommand##1%
- {\setvalue{\@shortstyle@##1}{#2}%
- \setvalue{\@style@##1}{\csname#2\endcsname}}%
- \processcommalist[#1]\docommand}
-
-\unexpanded\def\definefontstyle
- {\dodoubleargument\dodefinefontstyle}
-
-\def\setfontstyle#1#2% #1:name (roman, romaan) #2:style (rm)
- {\edef\fontstyle{#1}%
- \checkfontnamecombinations
- \setcurrentfontstyle\normalizedbodyfontsize}
-
-%D When asking for a complete font switch, for instance from 10
-%D to 12~points, the next macro does the job. First we
-%D normalize the size, next we define the current range of
-%D text, script and scriptscript sizes, then we set the text
-%D fonts and the math families and finally we activate the
-%D default typeface and also set the font specific parameters
-%D assigned to \type{\everybodyfont}
-
-\def\dosetbodyfontface#1#2%
- {\edef#1{\csname\bodyfontvariable\normalizedbodyfontsize#2\endcsname}}
-
-\def\docompletefontswitch[#1]%
- {\bodyfontsize#1\relax
- \dimensiontocount\bodyfontsize\bodyfontpoints % rounded, still used in m-chart
- \edef\bodyfontfactor{\withoutpt\the\bodyfontsize}%
- \edef\normalizedbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize}%
- \dosetbodyfontface \textface \s!text
- \dosetbodyfontface \scriptface \s!script
- \dosetbodyfontface \scriptscriptface \s!scriptscript}
-
-\docompletefontswitch[12pt] % init
-
-%D \macros
-%D {setupbodyfont,switchtobodyfont}
-%D
-%D The next two macros are user ones. With \type{\setupbodyfont}
-%D one can set the document bodyfont size, font family, style
-%D and/or options defined in files, for example:
-%D
-%D \starttyping
-%D \setupbodyfont[modern,12pt,roman]
-%D \stoptyping
-%D
-%D This command affects the document as a whole: text, headers
-%D and footers. The second macro however affects only the text:
-%D
-%D \starttyping
-%D \switchtobodyfont[10pt]
-%D \stoptyping
-%D
-%D So we've got:
-%D
-%D \showsetup{setupbodyfont}
-%D \showsetup{switchtobodyfont}
-%D
-%D Both macros look alike. The second one also has to take
-%D all kind of keywords into account.
-
-\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi
-\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi
-
-% \newtoks \everysetupbodyfont
-% \newtoks \everyswitchtobodyfont
-
-\definecomplexorsimple\setupbodyfont
-
-\def\simplesetupbodyfont
- {\restoreglobalbodyfont
- \saveinterlinespace}
-
-\def\complexsetupbodyfont[#1]%
- {\doifsomething{#1}
- {\dosetfont1{#1}%
- \globalbodyfontsize\localbodyfontsize
- \edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\globalbodyfontsize}%
- \let\globalfontstyle\fontstyle
- \ifproductionrun
- \the\everybodyfont
- \the\everyglobalbodyfont
- \saveinterlinespace
- \fi
- \the\everysetupbodyfont}}
-
-\unexpanded\def\switchtobodyfont[#1]%
- {\doifsomething{#1}
- {\ifcsname\??ft\normalizedbodyfontsize\interfaced{#1}\endcsname
- \setbodyfontstep{#1}% so we have a fast [small] switch
- \else
- \dosetfont0{#1}%
- \fi
- \the\everybodyfont
- \the\everyswitchtobodyfont}}
-
-%D The following alternative is meant for math||to||text
-%D switching and will be optimized.
-
-\def\fastswitchtobodyfont#1%
- {\ifcsname\??ft\normalizedbodyfontsize#1\endcsname
- \edef\futurebodyfontsize{\csname\??ft\normalizedbodyfontsize#1\endcsname}%
- \ifcsname\@size@\futurebodyfontsize\endcsname
- \csname\@size@\futurebodyfontsize\endcsname
- \localbodyfontsize\futurebodyfontsize\relax
- \fi
- \fi
- \csname\@style@\fontstyle\endcsname
- \the\everybodyfont}
-
-%D \starttyping
-%D $\cases{& \ccaron}$ $x=\hbox{\ccaron $x=\hbox{\ccaron}$}$
-%D \stoptyping
-
-\def\setfontcharacteristics
- {\the\everyfont}
-
-%D Predefined:
-
-% \installfontfeature[otf][tlig]
-% \installfontfeature[otf][trep]
-
-%D Todo:
-
-% \def\os{\groupedcommand{\setfontfeature{oldstyle}}{}}
-
-%D Experimental:
-
-\unexpanded\def\definefontfeature
- {\dotripleargument\dodefinefontfeature}
-
-\def\dodefinefontfeature[#1][#2][#3]%
- {\global\expandafter\chardef\csname\??fq=#1\endcsname % beware () needed as we get two values returned
- \ctxsprint{((fonts.specifiers.presetcontext("#1","#2","#3")))}\relax}
-
-\definefontfeature % experiment, this might move to the lua code
- [always]
- [mode=auto,
- kern=yes,
- mark=yes,
- mkmk=yes,
- curs=yes]
-
-\definefontfeature
- [default]
- [always]
- [liga=yes,
- tlig=yes,
- trep=yes] % texligatures=yes,texquotes=yes
-
-\definefontfeature
- [smallcaps]
- [always]
- [smcp=yes,
- tlig=yes,
- trep=yes] % texligatures=yes,texquotes=yes
-
-\definefontfeature
- [oldstyle]
- [always]
- [onum=yes,
- liga=yes,
- tlig=yes,
- trep=yes] % texligatures=yes,texquotes=yes
-
-\definefontfeature % == default unless redefined
- [ligatures]
- [always]
- [liga=yes,
- tlig=yes,
- trep=yes]
-
-\definefontfeature % can be used for type1 fonts
- [complete]
- [always]
- [compose=yes,
- liga=yes,
- tlig=yes,
- trep=yes]
-
-\definefontfeature
- [none]
- [mode=none,
- features=no]
-
-\definefontfeature % might move
- [arabic]
- [mode=node,language=dflt,script=arab,ccmp=yes,
- init=yes,medi=yes,fina=yes,isol=yes,
- liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes,
- mark=yes,mkmk=yes,kern=yes,curs=yes]
-
-\definefontfeature % might move
- [simplearabic]
- [mode=node,language=dflt,script=arab,
- init=yes,medi=yes,fina=yes,calt=yes,
- rlig=yes,curs=yes,mark=yes,mkmk=yes]
-
-% symbols:
-
-\definefontfeature
- [dingbats]
- [mode=base,
- goodies=dingbats,
- unicoding=yes]
-
-% math:
-
-\definefontfeature
- [virtualmath]
- [mode=base,
- liga=yes,
- kern=yes,
- tlig=yes,
- trep=yes,
- language=dflt,
- script=math]
-
-\definefontfeature[math-text] [virtualmath][mathalternates=yes,ssty=no]
-\definefontfeature[math-script] [virtualmath][mathalternates=yes,ssty=1,mathsize=yes]
-\definefontfeature[math-scriptscript][virtualmath][mathalternates=yes,ssty=2,mathsize=yes]
-
-\definefontfeature [math-nostack-text] [math-text] [nostackmath=yes]
-\definefontfeature [math-nostack-script] [math-script] [nostackmath=yes]
-\definefontfeature [math-nostack-scriptscript][math-scriptscript][nostackmath=yes]
-
-% \definefontfeature[mathtext] [math-text]
-% \definefontfeature[mathscript] [math-script]
-% \definefontfeature[mathscriptscript] [math-scriptscript]
-
-%D Also new, handy for manuals:
-
-\unexpanded\def\fontchar#1{\ctxcommand{fontchar("#1")}}
-
-%D: We cannot yet inherit because no colors are predefined.
-
-\definecolor[trace:0][s=.6]
-\definecolor[trace:1][r=.6]
-\definecolor[trace:2][g=.6]
-\definecolor[trace:3][b=.6]
-\definecolor[trace:4][r=.6,g=.6]
-\definecolor[trace:5][r=.6,b=.6]
-\definecolor[trace:6][g=.6,b=.6]
-\definecolor[trace:7][r=.8,g=.4]
-\definecolor[trace:8][r=.8,b=.4]
-\definecolor[trace:9][g=.4,b=.8]
-
-\definecolor[font:init][r=.75]
-\definecolor[font:medi][g=.75]
-\definecolor[font:fina][b=.75]
-\definecolor[font:isol][r=.75,g=.75] % [y=.75]
-\definecolor[font:mark][r=.75,b=.75] % [m=.75]
-\definecolor[font:rest][g=.75,b=.75] % [c=.75]
-
-%D Experimental!
-
-\def\installfontfeature
- {\dodoubleargument\doinstallfontfeature}
-
-\def\doinstallfontfeature[#1][#2]%
- {\writestatus\m!fonts{installing font features was experimental}} % \ctxlua{fonts.install_feature("#1","#2")}}
-
-%D Not yet in \MKII.
-
-\def\fontfeatureslist
- {\dodoubleargument\dofontfeatureslist}
-
-\def\dofontfeatureslist[#1][#2]% todo: arg voor type
- {\ctxsprint{fonts.specifiers.contexttostring("#1","otf","\luaescapestring{#2}","yes","no",true,{"number"})}}
-
-\attribute\zerocount\zerocount % first in list, so fast match
-
-\let\currentfeature\empty
-
-% ! ! ! very experimental, some test code for idris advanced features ! ! !
-%
-% \startbuffer
-% \definefontfeature[smallcaps][smallcaps][script=latn]
-% \definefontfeature[oldstyle] [oldstyle] [script=latn]
-%
-% \definedfont[name:cambria at 15pt]
-%
-% Hello there {\setff{smallcaps}capped 123 \setff{oldstyle}123!} \blank
-% Hello there {\addff{smallcaps}capped 123 \addff{oldstyle}123!} \blank
-% Hello there {\addff{smallcaps}capped \subff{smallcaps}normal} \blank
-% \stopbuffer
-%
-% \typebuffer \getbuffer
-
-% \unexpanded\def\featureattribute#1{\ctxsprint{fonts.specifiers.contextnumber("#1"))}}
-% \unexpanded\def\setfontfeature #1{\edef\currentfeature{#1}\attribute\zerocount\featureattribute{#1}\relax}
-% \unexpanded\def\resetfontfeature#1{\let\currentfeature\empty\attribute\zerocount\zerocount} % initial value
-
-% \def\addfontfeaturetoset #1{\ctxlua{fonts.withset("#1", 1)}} % merge
-% \def\subtractfontfeaturefromset #1{\ctxlua{fonts.withset("#1",-1)}} % merge
-% \def\addfontfeaturetofont #1{\ctxlua{fonts.withfnt("#1", 2)}} % overload
-% \def\subtractfontfeaturefromfont#1{\ctxlua{fonts.withfnt("#1",-2)}} % overload
-
-\unexpanded\def\featureattribute#1{\ctxcommand{featureattribute("#1")}}
-\unexpanded\def\setfontfeature #1{\ctxcommand{setfontfeature("#1")}\edef\currentfeature{#1}}
-\unexpanded\def\resetfontfeature#1{\ctxcommand{resetfontfeature()}\let\currentfeature\empty} % initial value
-\unexpanded\def\resetfontfeature#1{\attribute\zerocount\zerocount\let\currentfeature\empty} % initial value
-
-\unexpanded\def\addfontfeaturetoset #1{\ctxcommand{addfs("#1")}} % merge
-\unexpanded\def\subtractfontfeaturefromset #1{\ctxcommand{subfs("#1")}} % merge
-\unexpanded\def\addfontfeaturetofont #1{\ctxcommand{addff("#1")}} % overload
-\unexpanded\def\subtractfontfeaturefromfont#1{\ctxcommand{subff("#1")}} % overload
-
-\let\setff\setfontfeature
-\let\addfs\addfontfeaturetoset
-\let\subfs\subtractfontfeaturefromset
-\let\addff\addfontfeaturetofont
-\let\subff\subtractfontfeaturefromfont
-
-%D The next auxilliary macro is an alternative to \type
-%D {\fontname}.
-
-\def\purefontname#1{\ctxlua{file.basename("\fontname#1"}} % will be function using id
-
-%D \macros
-%D {switchstyleonly}
-%D
-%D For switching a style but keeping the alternative, there
-%D is:
-%D
-%D \starttyping
-%D {\bf text \switchstyleonly\ss text}
-%D {\bf text \switchstyleonly[ss]text}
-%D {\sl text \switchstyleonly[sansserif]text}
-%D \stoptyping
-
-\definecomplexorsimple\switchstyleonly
-
-\def\simpleswitchstyleonly#1% stupid version
- {\complexswitchstyleonly[\checkedstrippedcsname#1]}
-
-\def\complexswitchstyleonly[#1]% todo : check
- {\setcurrentfontstyle{\csname\@shortstyle@#1\endcsname}%
- \the\everybodyfont} % needed ?
-
-%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]
-
-% \def\sc{\setfontfeature{smallcaps}}
-\unexpanded\def\os{\setfontfeature{just-os}}
-
-%D Code for switching to fraktur and script has also been
-%D changed. We now have an alphabet switcher.
-
-\ifx\mathtext\undefined \let\mathtext\hbox \fi
-
-%D \macros
-%D {definebodyfontswitch}
-%D
-%D \PLAIN\ \TEX\ defines some macro's like \type{\tenpoint}
-%D to switch to a specific bodyfontsize. Just for the sake of
-%D compatibility we can define them like:
-%D
-%D \starttyping
-%D \definebodyfontswitch [twelvepoint] [12pt]
-%D \stoptyping
-%D
-%D We don't support language specific synonyms here, mainly
-%D because \PLAIN\ \TEX\ is english anyway.
-
-\def\dodefinebodyfontswitch[#1][#2]%
- {\def\docommand##1{\setvalue{##1}{\switchtobodyfont[#2]}}%
- \processcommalist[#1]\docommand}
-
-\unexpanded\def\definebodyfontswitch
- {\dodoubleargument\dodefinebodyfontswitch}
-
-%D \macros
-%D {setsmallbodyfont,setmainbodyfont,setbigbodyfont}
-%D
-%D When we're typesetting at for instance 10pt, we can call for
-%D the \type{small} as well as the \type{big} alternative,
-%D related to this main size, using \type{\switchtobodyfont[small]}.
-%D The three alternatives can be activated by the next three
-%D system calls and are defined by the bodyfontenvironment.
-
-\let\fontstep\empty % we can use \fontstep for tracing purposes
-
-\def\setbodyfontstep#1%
- {\edef\fontstep{\csname\bodyfontvariable\normalizedbodyfontsize\interfaced{#1}\endcsname}%
- \doswitchpoints[\fontstep]%
- \doswitchstyle[\fontstyle]}
-
-\unexpanded\def\setsmallbodyfont{\setbodyfontstep\v!small\the\everybodyfont}
-\unexpanded\def\setbigbodyfont {\setbodyfontstep\v!big \the\everybodyfont}
-
-\unexpanded\def\setmainbodyfont
- {\doswitchpoints[\normalizedbodyfontsize]%
- \doswitchstyle[\fontstyle]%
- \the\everybodyfont
- \the\everyglobalbodyfont
- \saveinterlinespace}
-
-%D \macros
-%D {restoreglobalbodyfont}
-%D
-%D Users can set whatever font available while typesetting text.
-%D Pagenumbers, footers, headers etc. however must be typeset
-%D in the main bodyfont and style of the document. Returning to
-%D the global state can be done with the next macro:
-
-\let\globalfontstyle\c!rm
-
-\def\fullrestoreglobalbodyfont
- {\let\fontsize\defaultfontsize
- \let\fontbody\defaultfontbody
- \currentxfontsize\zerocount
- \let\fontclass\globalfontclass
- \doswitchpoints[\normalizedglobalbodyfontsize]%
- \doswitchstyle[\globalfontstyle]%
- \redoconvertfont % just in case a pagebreak occurs
- \tf
- \the\everybodyfont
- \the\everyglobalbodyfont
- \saveinterlinespace}
-
-\def\partialrestoreglobalbodyfont
- {\let\fontsize\defaultfontsize
- \let\fontbody\defaultfontbody
- \currentxfontsize\zerocount
- \redoconvertfont
- \tf
- \the\everybodyfont % indeed needed
- \the\everyglobalbodyfont % indeed needed
- \saveinterlinespace}
-
-\def\restoreglobalbodyfont % ook style etc
- {\ifx\fontclass\globalfontclass
- \ifx\fontstyle\globalfontstyle
- \ifx\normalizedbodyfontsize\normalizedglobalbodyfontsize
- \partialrestoreglobalbodyfont
- \else
- \fullrestoreglobalbodyfont
- \fi
- \else
- \fullrestoreglobalbodyfont
- \fi
- \else
- \fullrestoreglobalbodyfont
- \fi}
-
-% in case of troubles: \let\restorebodyfont\fullrestoreglobalbodyfont
-
-%D This macro has to be called when entering the pagebody
-%D handling routine as well as the footnote insert routine.
-%D Users can access this feature |<|for instance when one wants
-%D to typeset tables and alike in the main bodyfont and style
-%D while the running text is temporary set to a smaller one|>|
-%D by saying \type{\switchtobodyfont[global]}.
-
-%D \macros
-%D {rasterfont}
-%D
-%D There are (at the moment) two situations in which we want to
-%D have fast access to a particular font. When we are using
-%D \TEX\ to typeset rasters, we use small {\rasterfont.}'s
-%D (a rather small period indeed), the same as \PICTEX\ uses
-%D for drawing purposes.
-
-\definefont [rasterfont] [Serif at 5pt]
-
-%D \macros
-%D {infofont}
-%D
-%D The second situation occurs when we enable the info mode,
-%D and put all kind of status information in the margin. We
-%D don't want huge switches to the main bodyfont and style, so
-%D here too we use a direct method.
-
-\let\infofont\relax % satisfy dep checker
-
-\definefont [infofont] [Mono at 6pt] % todo \the\everybodyfont
-
-%D \macros
-%D {definealternativestyle}
-%D
-%D In the main modules we are going to implement lots of
-%D parameterized commands and one of these parameters will
-%D concern the font to use. To suit consistent use of fonts we
-%D here implement a mechanism for defining the keywords that
-%D present a particular style or alternative.
-%D
-%D \starttyping
-%D \definealternativestyle [keywords] [\style] [\nostyle]
-%D \stoptyping
-%D
-%D The first command is used in the normal textflow, while the
-%D second command takes care of headings and alike. Consider
-%D the next two definitions:
-%D
-%D \starttyping
-%D \definealternativestyle [bold] [\bf] []
-%D \definealternativestyle [cap] [\cap] [\cap]
-%D \stoptyping
-%D
-%D A change \type{\bf} in a heading which is to be set in
-%D \type{\tfd} does not look that well, so therefore we leave
-%D the second argument of \type{\definealternativestyle} empty.
-%D When we capatalize characters using the pseudo small cap
-%D command \type{\cap}, we want this to take effect in both
-%D text and headings, which is accomplished by assigning both
-%D arguments.
-
-% \def\dodefinealternativestyle[#1][#2][#3]%
-% {\def\docommand##1%
-% {\ifcsname##1\endcsname\else\setuvalue{##1}{\groupedcommand{#2}{}}\fi
-% \setvalue{\@letter@ ##1}{#2}%
-% \setvalue{\@noletter@##1}{#3}}%
-% \processcommalist[#1]\docommand}
-
-\setnewconstant \currentalternativestyleindex \plusone
-
-\def\dododefinealternativestyle#1#2#3%
- {\ifcsname#3\endcsname
- % no redefinition
- \else
- \setuvalue{#3}{\groupedcommand{#1}{}}%
- \fi
- \setvalue{\??ft:as:#3}{\doapplyalternativestyle{#1}{#2}}}%
-
-\def\dodefinealternativestyle[#1][#2][#3]%
- {\processcommalist[#1]{\dododefinealternativestyle{#2}{#3}}} % also gets {##1}
-
-\def\applyalternativestyle#1%
- {\ifcsname\??ft:as:#1\endcsname\csname\??ft:as:#1\expandafter\endcsname\fi}
-
-\def\doapplyalternativestyle
- {\ifcase\currentalternativestyleindex
- \expandafter\gobbletwoarguments
- \or
- \expandafter\firstoftwoarguments
- \or
- \expandafter\secondoftwoarguments
- \else
- \expandafter\firstoftwoarguments
- \fi}
-
-\unexpanded\def\definealternativestyle
- {\dotripleempty\dodefinealternativestyle}
-
-\unexpanded\def\definestyle{\definealternativestyle} % later redefined
-
-%D Maybe too geneneric, but probably ok is the following. (Maybe one
-%D day we will use a dedicated grouped command for styles.)
-
-\appendtoks
- \let\groupedcommand\thirdofthreearguments
-\to \simplifiedcommands
-
-%D This command also defines the keyword as command. This means
-%D that the example definition of \type{bold} we gave before,
-%D results in a command \type{\bold} which can be used as:
-%D
-%D \startbuffer
-%D He's a \bold{bold} man with a {\bold head}.
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D or
-%D
-%D \startvoorbeeld
-%D \definealternativestyle[bold][\bf][]\getbuffer
-%D \stopvoorbeeld
-%D
-%D Such definitions are of course unwanted for \type{\cap}
-%D because this would result in an endless recursive call.
-%D Therefore we check on the existance of both the command and
-%D the substitution. The latter is needed because for instance
-%D \type{\type} is an entirely diferent command. That command
-%D handles verbatim, while the style command would just switch
-%D to teletype font. This is just an example of a tricky
-%D naming coincidence.
-
-%D \macros
-%D {doconvertfont,noconvertfont,
-%D dontconvertfont,redoconvertfont}
-%D
-%D After having defined such keywords, we can call for them by
-%D using
-%D
-%D \starttyping
-%D \doconvertfont{keyword}{text}
-%D \stoptyping
-%D
-%D We deliberately pass an argument. This enables us to
-%D assign converters that handle one argument, like
-%D \type{\cap}.
-%D
-%D By default the first specification is used to set the style,
-%D exept when we say \type{\dontconvertfont}, after which the
-%D second specification is used. We can also directly call for
-%D \type{\noconvertfont}. In nested calls, we can restore the
-%D conversion by saying \type{\redoconvertfont}.
-
-% subtle ... \expandafter is needed else problems with lookahead caps
-%
-% this will be cleaned up
-%
-% beware: p!defined can contain crap like \edef crap {...} and such
-% so we need to pass #1 as well .. no longer needed in luatex
-
-% \def\@@dodoconvertfont{\csname\@letter@ \p!defined\expandafter\endcsname\gobbleoneargument}
-% \def\@@donoconvertfont{\csname\@noletter@\p!defined\endcsname}
-% \def\@@redoconvertfont{\csname \p!defined\expandafter\endcsname\gobbleoneargument}
-%
-% \unexpanded\def\dodoconvertfont#1% #2% we need the protection
-% {\edef\p!defined{#1}%
-% \ifx\p!defined\empty\else
-% \@EA\dododoconvertfont
-% \fi{#1}}
-%
-% \def\dododoconvertfont % #1 (detokenize no longer needed in luatex)
-% {\ifcsname\@letter@\detokenize\@EA{\p!defined}\endcsname
-% \@EA\@@dodoconvertfont
-% \else\ifcsname\detokenize\@EA{\p!defined}\endcsname
-% \@EAEAEA\@@redoconvertfont
-% \else
-% \@EAEAEA\firstofoneargument
-% \fi\fi} % {#1}
-%
-% \let\doconvertfont\dodoconvertfont
-%
-% \unexpanded\def\noconvertfont#1% #2%
-% {\edef\p!defined{#1}%
-% \ifx\p!defined\empty
-% \else
-% \@EA\nononoconvertfont
-% \fi}
-%
-% \def\nononoconvertfont
-% {\ifcsname\@noletter@\detokenize\@EA{\p!defined}\endcsname
-% \@EA\@@donoconvertfont
-% \fi}
-%
-% %D Extras:
-%
-% \unexpanded\def\dontconvertfont{\let\doconvertfont\noconvertfont}
-% \unexpanded\def\redoconvertfont{\let\doconvertfont\dodoconvertfont}
-
-%D These commands are not grouped! Grouping is most probably
-%D done by the calling macro's and would lead to unnecessary
-%D overhead.
-
-\unexpanded\def\doconvertfont#1% #2% we need the protection
- {\edef\currentconvertfont{#1}%
- \ifx\currentconvertfont\empty \else
- \@EA\dodoconvertfont
- \fi}
-
-\def\dodoconvertfont
- {\edef\dtcurrentconvertfont{\detokenize\@EA{\currentconvertfont}}%
- \ifcsname\??ft:as:\dtcurrentconvertfont\endcsname
- \csname\??ft:as:\dtcurrentconvertfont\expandafter\endcsname
- \else\ifcsname\dtcurrentconvertfont\endcsname
- \csname\dtcurrentconvertfont\expandafter\endcsname
- \else
- \@EAEAEA\currentconvertfont
- \fi\fi}
-
-%D Low level switches (downward compatible):
-
-\unexpanded\def\dontconvertfont{\currentalternativestyleindex\plustwo}
-\unexpanded\def\redoconvertfont{\currentalternativestyleindex\plusone}
-
-%D \macros
-%D {em,emphasistypeface,emphasisboldface}
-%D
-%D The next macro started as a copy of Donald Arseneau's
-%D \type{\em} (\TUGNEWS\ Vol.~3, no.~1, 1994). His
-%D implementation was a bit more sophisticated version of the
-%D standard \LATEX\ one. We furter enhanced the macro, so now
-%D it also adapts itself to boldface mode. Because we favor
-%D {\sl slanted} type over {\it italic}, we made the emphasis
-%D adaptable, for instance:
-%D
-%D \starttyping
-%D \def\emphasistypeface {\it}
-%D \def\emphasisboldface {\bi}
-%D \stoptyping
-%D
-%D But we prefer:
-
-\def\emphasistypeface {\sl}
-\def\emphasisboldface {\bs}
-
-%D or even better:
-
-\def\doemphasistypeface#1#2%
- {\edef\emphasizedtypeface{\csname\??ft\fontclass\normalizedbodyfontsize\c!em\endcsname}%
- \ifx\emphasizedtypeface\v!slanted
- #1%
- \else\ifx\emphasizedtypeface\v!italic
- #2%
- \else\ifx\emphasizedtypeface\v!empty
- \edef\emphasizedtypeface{\csname\??ft\normalizedbodyfontsize\c!em\endcsname}%
- \ifx\emphasizedtypeface\v!slanted
- #1%
- \else\ifx\emphasizedtypeface\v!italic
- #2%
- \else
- \getvalue\emphasizedtypeface
- \fi\fi
- \else
- \getvalue\emphasizedtypeface
- \fi\fi\fi}
-
-\unexpanded\def\emphasistypeface{\doemphasistypeface\sl\it}
-\unexpanded\def\emphasisboldface{\doemphasistypeface\bs\bi}
-
-\unexpanded\def\normalboldface
- {\relax\ifx\fontalternative\c!it \bi
- \else \ifx\fontalternative\c!sl \bs
- \else \bf \fi\fi}
-
-\unexpanded\def\normaltypeface
- {\relax
- \ifx\fontalternative\c!bi \it \else
- \ifx\fontalternative\c!bs \sl \else
- \tf \fi\fi}
-
-\unexpanded\def\swaptypeface
- {\relax
- \ifx\fontalternative\c!it \tf \else
- \ifx\fontalternative\c!sl \tf \else
- \ifx\fontalternative\c!bf \emphasisboldface \else
- \ifx\fontalternative\c!bs \bf \else
- \ifx\fontalternative\c!bi \bf \else
- \emphasistypeface \fi\fi\fi\fi\fi}
-
-\let\typeface\normaltypeface
-\let\boldface\normalboldface
-\let\swapface\swaptypeface
-
-%D To be set with the default body font environment: \type
-%D {em} being \type {slanted} or \type {italic}.
-
-% maybe a \csname...\fontalternative\endcsname
-
-\newconditional\emneeded
-
-\newtoks\everyemphasized
-
-\unexpanded\def\em
- {\relax
- \ifdim\slantperpoint>\zeropoint
- \settrue\emneeded
- \else
- \setfalse\emneeded
- \fi
- \setemphasisboldface % new
- \ifx\fontalternative\c!it
- \def\emphasistypeface{\it}\tf
- \else\ifx\fontalternative\c!sl
- \def\emphasistypeface{\sl}\tf
- \else\ifx\fontalternative\c!bf
- \emphasisboldface
- \else\ifx\fontalternative\c!bs
- \def\emphasisboldface{\bs}\bf
- \else\ifx\fontalternative\c!bi
- \def\emphasisboldface{\bi}\bf
- \else
- \emphasistypeface
- \fi\fi\fi\fi\fi
- \the\everyemphasized
- \ifconditional\emneeded\else
- \expandafter\aftergroup
- \fi
- \emphasiscorrection}
-
-% compare ...
-%
-% \appendtoks \red \to \everyemphasized
-% \setupbodyfontenvironment [default] [em={\italic\color[red]}]
-
-%D The next feature was not present in previous versions. It
-%D takes care of \type {\em \bf ...} situations.
-
-\def\setemphasisboldface
- {\let\savedemphasisboldface\bf
- \let\setemphasisboldface\relax
- \unexpanded\def\bf
- {%\relax
- \let\bf\relax % new
- \ifx\fontalternative\c!it
- \bi
- \else\ifx\fontalternative\c!sl
- \bs
- \else
- \savedemphasisboldface
- \fi\fi
- \let\bf\savedemphasisboldface}}
-
-%D Donald's (adapted) macros take the next character into
-%D account when placing italic correction. As a bonus we also
-%D look for something that looks like a dash, in which case we
-%D don't correct.
-
-\let\italiccorrection=\/ % tex primitive
-
-\def\emphasiscorrection % not in raw alignment groups, else omit problem
- {\ifhmode\ifnum\currentgrouptype=\@@aligngroup\else
- \expandafter\expandafter\expandafter\emphasislook
- \fi\fi}
-
-\def\emphasislook
- {\begingroup
- \futurelet\next\emphasistest}
-
-\def\emphasistest
- {\ifcat\noexpand\next,% still ok?
- \expandafter\doemphasiscorrection
- \else
- \expandafter\dododoemphasiscorrection
- \fi}
-
-\def\doemphasiscorrection
- {\futurelet\next\dodoemphasiscorrection}
-
-\def\dodoemphasiscorrection
- {\setbox\scratchbox\hbox{\next}%
- \ifdim\ht\scratchbox=\zeropoint % probably a space
- \expandafter\dododoemphasiscorrection
- \else\ifdim\ht\scratchbox<.3ex
- \expandafter\expandafter\expandafter\endgroup
- \else
- \expandafter\expandafter\expandafter\dododoemphasiscorrection
- \fi\fi}
-
-\def\dododoemphasiscorrection
- {\scratchskip\lastskip
- \ifdim\scratchskip=\zeropoint\relax % == \ifzeropt\scratchskip
- \italiccorrection\relax
- \else
- \unskip\italiccorrection\hskip\scratchskip
- \fi
- \endgroup}
-
-%D We end with some examples which show the behavior when
-%D some punctuation is met. We also show how the mechanism
-%D adapts itself to bold, italic and slanted typing.
-%D
-%D \startbuffer
-%D test {test}test \par
-%D test {\sl test}test \par
-%D test {\em test}test \par
-%D test {\em test}--test \par
-%D
-%D test {test}, test \par
-%D test {\em test}, test \par
-%D
-%D test {\em test {\em test {\em test} test} test} test \par
-%D test {\bf test {\em test {\em test} test} test} test \par
-%D test {\sl test {\em test {\em test} test} test} test \par
-%D test {\it test {\em test {\em test} test} test} test \par
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D We get:
-%D
-%D \startvoorbeeld
-%D \startpacked
-%D \getbuffer
-%D \stoppacked
-%D \stopvoorbeeld
-
-%D \macros
-%D {emphbf,emphit,emphsl,emphtf}
-%D
-%D The next emphasis alternatives are for \THANH. They adapt
-%D their style as good as possible.
-
-\def\emphbf{\groupedcommand{\bf\def\emphit{\bi}\def\emphsl{\bs}}{}}
-\def\emphit{\groupedcommand{\it\def\emphbf{\bi}\def\emphsl{\sl}}{}}
-\def\emphsl{\groupedcommand{\sl\def\emphbf{\bs}\def\emphit{\it}}{}}
-\def\emphtf{\groupedcommand{\tf\def\emphbf{\bf}\def\emphit{\it}\def\emphsl{\sl}}{}}
-
-%D \startbuffer
-%D TEXT {\emphbf text \emphit text \emphtf text \emphsl text} TEXT
-%D TEXT \emphbf{text \emphit{text} \emphtf{text} \emphsl{text}} TEXT
-%D \stopbuffer
-%D
-%D \typebuffer
-%D \startlines
-%D \getbuffer
-%D \stoplines
-
-%D \macros
-%D {setfont}
-%D
-%D Every now and then we want to define a font directly, for
-%D instance when we typeset title pages. The next macro saves
-%D some typing:
-
-\def\setfont% geen \dosetfont mogelijk
- {\def\next{\nextfont\setupinterlinespace}% hm, we need to use \setuplocalinterlinespace
- \afterassignment\next\font\nextfont=}
-
-%D One can call this macro as:
-%D
-%D \starttyping
-%D \setfont cmr10 at 60pt
-%D \stoptyping
-%D
-%D After which the font is active and the baselines and
-%D struts are set.
-
-%D \macros
-%D {showbodyfont}
-%D
-%D One can call for a rather simple overview of a bodyfont and the
-%D relations between its alternative fonts.
-%D
-%D \showsetup{showbodyfont}
-%D
-%D The current bodyfont (here we omitted the argument) looks like:
-%D
-%D \showbodyfont
-%D
-%D The implementation is rather straightforward in using
-%D \type{\halign}.
-
-\fetchruntimecommand \showbodyfont {\f!fontprefix\s!run}
-
-%D \macros
-%D {showfontstrip, testminimalbaseline, showminimalbaseline}
-%D
-%D The next command can come in handy when combining
-%D different fonts into a collection (typeface) and
-%D determining optimal baseline distances.
-%D
-%D \showfontstrip \blank \showminimalbaseline
-
-\fetchruntimecommand \showfontstrip {\f!fontprefix\s!run}
-\fetchruntimecommand \testminimalbaseline {\f!fontprefix\s!run}
-\fetchruntimecommand \showminimalbaseline {\f!fontprefix\s!run}
-
-%D \macros
-%D {showkerning}
-%D
-%D A goody is:
-%D
-%D \showkerning{Can you guess what kerning is?}
-
-\fetchruntimecommand \showkerning {\f!fontprefix\s!run}
-
-%D \macros
-%D {showbodyfontenvironment}
-%D
-%D The current bodyfontenvironment is:
-%D
-%D \showbodyfontenvironment
-%D
-%D This overview is generated using:
-%D
-%D \showsetup{showbodyfontenvironment}
-
-\fetchruntimecommand \showbodyfontenvironment {\f!fontprefix\s!run}
-
-%D \macros
-%D {showfont,showfontstyle,showligatures}
-%D
-%D The following command generates a fontmap:
-%D
-%D \startbuffer
-%D \showfont[SansBold at 12pt]
-%D \stopbuffer
-%D
-%D \typebuffer
-%D \getbuffer
-
-% to be internationalized
-
-\fetchruntimecommand \showfont {\f!fontprefix\s!run}
-\fetchruntimecommand \showfontstyle {\f!fontprefix\s!run}
-\fetchruntimecommand \showligature {\f!fontprefix\s!run}
-\fetchruntimecommand \showligatures {\f!fontprefix\s!run}
-\fetchruntimecommand \showcharratio {\f!fontprefix\s!run}
-
-%D \macros
-%D {getglyph, symbolicfont}
-%D
-%D Individual glyphs can be accessed by using
-%D
-%D \starttyping
-%D \getglyph{fontname}{character}
-%D \stoptyping
-%D
-%D This macro is used in for instance the symbol modules and
-%D as one can see, it does obey the small and even smaller
-%D sizes. The \type {\symbolicfont} macro can be used to
-%D switch to a font named \type {fontname} (see \type
-%D {cont-log} and \type {symb-eur} for examples of symbolic
-%D definitions.
-
-\def\fontstringA
- {\ifx\fontstyle\c!rm \s!Serif \else
- \ifx\fontstyle\c!ss \s!Sans \else
- \ifx\fontstyle\c!tt \s!Mono \else
- \s!Serif \fi\fi\fi}
-
-\def\fontstringB
- {\ifx\fontstyle\c!rm \s!Regular \else
- \ifx\fontstyle\c!ss \s!Support \else
- \ifx\fontstyle\c!tt \s!Type \else
- \s!Serif \fi\fi\fi}
-
-\def\fontstringC
- {\ifx\fontalternative\c!bf \s!Bold \else
- \ifx\fontalternative\c!sl \s!Slanted \else
- \ifx\fontalternative\c!it \s!Italic \else
- \ifx\fontalternative\c!bs \s!BoldSlanted \else
- \ifx\fontalternative\c!bi \s!BoldItalic \fi\fi\fi\fi\fi}
-
-\def\fontstringD % default fontstyle
- {\expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!rm \s!Serif \else
- \expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!ss \s!Sans \else
- \expandafter\ifx\csname\??tf\fontclass\s!default\endcsname\c!tt \s!Mono \else
- \s!Serif \fi\fi\fi}
-
-% potential generalization:
-
-% \letvalue{\??ff:t:\c!rm}\s!Serif
-% \letvalue{\??ff:t:\c!ss}\s!Sans
-% \letvalue{\??ff:t:\c!tt}\s!Mono
-%
-% \letvalue{\??ff:s:\c!bf}\s!Bold
-% \letvalue{\??ff:s:\c!sl}\s!Slanted
-% \letvalue{\??ff:s:\c!it}\s!Italic
-% \letvalue{\??ff:s:\c!bs}\s!BoldSlanted
-% \letvalue{\??ff:s:\c!bi}\s!BoldItalic
-%
-% \letvalue{\??ff:a:\c!rm}\s!Regular
-% \letvalue{\??ff:a:\c!ss}\s!Support
-% \letvalue{\??ff:a:\c!tt}\s!Type
-%
-% \def\fontstringA{\executeifdefined{\??ff:t:\fontstyle}\s!Serif}
-% \def\fontstringB{\executeifdefined{\??ff:a:\fontstyle}\s!Serif}
-% \def\fontstringC{\executeifdefined{\??ff:s:\fontstyle}\empty}
-% \def\fontstringD{\executeifdefined{\??ff:t:\csname\??tf\fontclass\s!default\endcsname}\s!Serif}
-
-\def\glyphfontfile#1%
- {#1%
- \ifcsname\??ff#1\fontstringA\fontstringC\endcsname
- \fontstringA\fontstringC
- \else\ifcsname\??ff#1\fontstringB\fontstringC\endcsname
- \fontstringB\fontstringC
- \else\ifcsname\??ff#1\fontstringA\endcsname
- \fontstringA
- \else\ifcsname\??ff#1\fontstringB\endcsname
- \fontstringB
- \else\ifcsname\??ff#1\fontstringC\endcsname
- \fontstringC
- \fi\fi\fi\fi\fi}
-
-%D The next macro can be used to make decisions based on the shape:
-
-\def\doifitalicelse#1#2%
- {\ifx\fontalternative\c!sl#1\else
- \ifx\fontalternative\c!it#1\else
- \ifx\fontalternative\c!bs#1\else
- \ifx\fontalternative\c!bi#1\else#2\fi\fi\fi\fi}
-
-%D For an example of usage of the following command,
-%D see \type {cont-log.tex}.
-%D
-%D \starttyping
-%D \def\symbolicfont#1{\definedfont[\glyphfontfile{#1} sa *]}
-%D \stoptyping
-%D
-%D Since we know what scaling it to be applied, we can
-%D implement a much faster alternative:
-
-\let\thedefinedfont\relax
-
-% \def\symbolicsizedfont#1#2#3%
-% {\scaledfontsize#1%
-% \scaledfontsize#2\scaledfontsize
-% \font\thedefinedfont=\truefontname{\glyphfontfile{#3}} at \currentfontbodyscale\scaledfontsize\relax
-% \thedefinedfont}
-%
-% \def\symbolicscaledfont
-% {\symbolicsizedfont\fontbody}
-%
-% \unexpanded\def\symbolicfont
-% {\symbolicsizedfont\fontbody\plusone}
-%
-% \unexpanded\def\getglyph#1#2% slow, faster, much faster
-% %{{\definefont[\s!dummy][\glyphfontfile{#1} sa \currentfontscale]\dummy#2}}
-% %{{\definefont[\s!dummy][\glyphfontfile{#1} sa *]\dummy#2}}
-% %{{\symbolicfont{#1}#2}}
-% {{\symbolicfont{#1}\doifnumberelse{#2}\char\donothing#2}}
-%
-% \unexpanded\def\getscaledglyph#1#2#3%
-% {{\symbolicscaledfont{#1}{#2}\doifnumberelse{#3}\char\donothing#3}}
-%
-% \unexpanded\def\getrawglyph#1#2% for simple symbols
-% {{\scaledfontsize\fontbody
-% \font\thedefinedfont=#1 at \currentfontbodyscale\scaledfontsize\relax
-% \thedefinedfont\doifnumberelse{#2}\char\donothing#2}}
-%
-% \unexpanded\def\getfontchar#1#2%
-% {{\symbolicfont{#1}\fontchar{#2}}}
-
-\def\setscaledstyledsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
- {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#3}} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
- \ifcsname\??ss->\askedsymbolfont\endcsname
- \csname\??ss->\askedsymbolfont\endcsname
- \else
- \dodefinesymbolicfont
- \fi}
-
-\def\setscaleddirectsymbolicfont#1#2#3% quite a slowdown, glyphfontfile
- {\edef\askedsymbolfont{\truefontname{#3} at \the\dimexpr#2\dimexpr\currentfontbodyscale\dimexpr#1}%
- \ifcsname\??ss->\askedsymbolfont\endcsname
- \csname\??ss->\askedsymbolfont\endcsname
- \else
- \dodefinesymbolicfont
- \fi}
-
-\def\setstyledsymbolicfont#1% quite a slowdown, glyphfontfile
- {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#1}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
- \ifcsname\??ss->\askedsymbolfont\endcsname
- \csname\??ss->\askedsymbolfont\endcsname
- \else
- \dodefinesymbolicfont
- \fi}
-
-\def\setdirectsymbolicfont#1%
- {\edef\askedsymbolfont{\truefontname{#1} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
- \ifcsname\??ss->\askedsymbolfont\endcsname
- \csname\??ss->\askedsymbolfont\endcsname
- \else
- \dodefinesymbolicfont
- \fi}
-
-\def\dodefinesymbolicfont
- {\definefont[currentsymbolfont][\askedsymbolfont]%
- \currentsymbolfont
- \global\expandafter\let\csname\??ss->\askedsymbolfont\endcsname\lastrawfontcall}
-
-\unexpanded\def\getnamedglyphstyled#1#2{{\setstyledsymbolicfont{#1}\ctxcommand{fontchar("#2")}}}
-\unexpanded\def\getnamedglyphdirect#1#2{{\setdirectsymbolicfont{#1}\ctxcommand{fontchar("#2")}}}
-\unexpanded\def\getglyphstyled #1#2{{\setstyledsymbolicfont{#1}\doifnumberelse{#2}\char\donothing#2}}
-\unexpanded\def\getglyphdirect #1#2{{\setdirectsymbolicfont{#1}\doifnumberelse{#2}\char\donothing#2}}
-\unexpanded\def\getscaledglyph #1#2#3{{\setscaledstyledsymbolicfont{#1}{#2}\doifnumberelse{#3}\char\donothing#3}}
-
-\let\getglyph \getglyphstyled % old
-\let\getrawglyph \getglyphdirect % old
-\let\symbolicsizedfont\setscaledstyledsymbolicfont % old
-\let\symbolicfont \setstyledsymbolicfont % old
-
-\unexpanded\def\symbolicscaledfont{\setsscaledstyledsymbolicfont\fontbody}
-\unexpanded\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody}
-
-%D The last implementation of \type {\getglyph} permits
-%D definitions like:
-%D
-%D \starttypings
-%D \definefontsynonym [EuroSans] [eurose]
-%D \definefontsynonym [EuroSansBold] [euroseb]
-%D \definefontsynonym [EuroSansItalic] [eurosei]
-%D \definefontsynonym [EuroSansSlanted] [eurosei]
-%D \definefontsynonym [EuroSansBoldItalic] [eurosebi]
-%D \definefontsynonym [EuroSansBoldSlanted] [eurosebi]
-%D
-%D \definesymbol [euro] [\getglyph{Euro}{\char160}]
-%D
-%D \def\euro{\symbol[euro]}
-%D \stoptyping
-%D
-%D These definitions guarantee that the next calls work okay:
-%D
-%D \starttyping
-%D \ss \tf\euro \bf\euro \sla\euro \itd\euro \bs\euro \bic\euro
-%D \stoptyping
-%D
-%D The shape as well as the size is adapted to the current
-%D environment.
-
-%D \macros
-%D {ss, SS, sz}
-%D
-%D We are going to redefine \type{\ss} but for those wo still
-%D want to have access to the german \SS, we save it's value in
-%D \type{\SS}. Ok, I should have used \type{\sf} instead of
-%D \type{\ss} in the first place.
-
-\ifx\undefined\SS \let\SS=\ss \fi
-\ifx\undefined\sz \let\sz=\ss \fi
-
-%D Personally I think that using \TEX\ macro packages is
-%D complicated by the way fonts are handled. Apart from the
-%D many encodings, we also deal with different naming schemes.
-%D Confronted with this problem, I decided to change the
-%D definitions into:
-%D
-%D \starttyping
-%D \definebodyfont [12pt] [rm] [tf=Times-Roman at 12pt]
-%D \stoptyping
-%D
-%D combined with for instance:
-%D
-%D \starttyping
-%D \definefontsynonym [Times-Roman] [tir]
-%D \stoptyping
-
-%D Now we're up to some definitions.
-
-\definebodyfontenvironment
- [\s!default]
- [ \s!text=1.0,
- \s!script=0.7,
- \s!scriptscript=0.5,
- \c!a=1.200,
- \c!b=1.440,
- \c!c=1.728,
- \c!d=2.074,
- *=\currentfontscale, % wildcard
- \c!x=0.8,
- \c!xx=0.6,
- \c!big=1.2,
- \c!small=0.8,
- \c!interlinespace=,
- \c!em=\v!slanted]
-
-\definebodyfontenvironment
- [20.7pt]
- [ \s!text=20.7pt,
- \s!script=\!!fourteenpointfour,
- \s!scriptscript=\!!twelvepoint,
- \c!x=17.3pt,
- \c!xx=\!!fourteenpointfour,
- \c!big=20.7pt, % !!!!
- \c!small=17.3pt]
-
-\definebodyfontenvironment
- [17.3pt]
- [ \s!text=17.3pt,
- \s!script=\!!twelvepoint,
- \s!scriptscript=\!!tenpoint,
- \c!x=\!!fourteenpointfour,
- \c!xx=\!!twelvepoint,
- \c!big=20.7pt,
- \c!small=\!!fourteenpointfour]
-
-\definebodyfontenvironment
- [\!!fourteenpointfour]
- [ \s!text=\!!fourteenpointfour,
- \s!script=\!!elevenpoint,
- \s!scriptscript=\!!ninepoint,
- \c!x=\!!twelvepoint,
- \c!xx=\!!tenpoint,
- \c!big=17.3pt,
- \c!small=\!!twelvepoint]
-
-\definebodyfontenvironment
- [\!!twelvepoint]
- [ \s!text=\!!twelvepoint,
- \s!script=\!!ninepoint,
- \s!scriptscript=\!!sevenpoint,
- \c!x=\!!tenpoint,
- \c!xx=\!!eightpoint,
- \c!big=\!!fourteenpointfour,
- \c!small=\!!tenpoint]
-
-\definebodyfontenvironment
- [\!!elevenpoint]
- [ \s!text=\!!elevenpoint,
- \s!script=\!!eightpoint,
- \s!scriptscript=\!!sixpoint,
- \c!x=\!!ninepoint,
- \c!xx=\!!sevenpoint,
- \c!big=\!!twelvepoint,
- \c!small=\!!ninepoint]
-
-\definebodyfontenvironment
- [\!!tenpoint]
- [ \s!text=\!!tenpoint,
- \s!script=\!!sevenpoint,
- \s!scriptscript=\!!fivepoint,
- \c!x=\!!eightpoint,
- \c!xx=\!!sixpoint,
- \c!big=\!!twelvepoint,
- \c!small=\!!eightpoint]
-
-\definebodyfontenvironment
- [\!!ninepoint]
- [ \s!text=\!!ninepoint,
- \s!script=\!!sevenpoint,
- \s!scriptscript=\!!fivepoint,
- \c!x=\!!sevenpoint,
- \c!xx=\!!fivepoint,
- \c!big=\!!elevenpoint,
- \c!small=\!!sevenpoint]
-
-\definebodyfontenvironment
- [\!!eightpoint]
- [ \s!text=\!!eightpoint,
- \s!script=\!!sixpoint,
- \s!scriptscript=\!!fivepoint,
- \c!x=\!!sixpoint,
- \c!xx=\!!fivepoint,
- \c!big=\!!tenpoint,
- \c!small=\!!sixpoint]
-
-\definebodyfontenvironment
- [\!!sevenpoint]
- [ \s!text=\!!sevenpoint,
- \s!script=\!!sixpoint,
- \s!scriptscript=\!!fivepoint,
- \c!x=\!!sixpoint,
- \c!xx=\!!fivepoint,
- \c!big=\!!ninepoint,
- \c!small=\!!fivepoint]
-
-\definebodyfontenvironment
- [\!!sixpoint]
- [ \s!text=\!!sixpoint,
- \s!script=\!!fivepoint,
- \s!scriptscript=\!!fivepoint,
- \c!x=\!!fivepoint,
- \c!xx=\!!fivepoint,
- \c!big=\!!eightpoint,
- \c!small=\!!fivepoint]
-
-\definebodyfontenvironment
- [\!!fivepoint]
- [ \s!text=\!!fivepoint,
- \s!script=\!!fivepoint,
- \s!scriptscript=\!!fivepoint,
- \c!x=\!!fivepoint,
- \c!xx=\!!fivepoint,
- \c!big=\!!sevenpoint,
- \c!small=\!!fivepoint]
-
-\definebodyfontenvironment
- [\!!fourpoint]
- [ \s!text=\!!fourpoint,
- \s!script=\!!fourpoint,
- \s!scriptscript=\!!fourpoint,
- \c!x=\!!fourpoint,
- \c!xx=\!!fourpoint,
- \c!big=\!!sixpoint,
- \c!small=\!!fourpoint]
-
-\definebodyfontswitch [fourteenpointfour] [\!!fourteenpointfour]
-\definebodyfontswitch [twelvepoint] [\!!twelvepoint]
-\definebodyfontswitch [elevenpoint] [\!!elevenpoint]
-\definebodyfontswitch [tenpoint] [\!!tenpoint]
-\definebodyfontswitch [ninepoint] [\!!ninepoint]
-\definebodyfontswitch [eightpoint] [\!!eightpoint]
-\definebodyfontswitch [sevenpoint] [\!!sevenpoint]
-\definebodyfontswitch [sixpoint] [\!!sixpoint]
-\definebodyfontswitch [fivepoint] [\!!fivepoint]
-\definebodyfontswitch [fourpoint] [\!!fourpoint]
-
-% \definebodyfontswitch [xii] [\!!twelvepoint]
-% \definebodyfontswitch [xi] [\!!elevenpoint]
-% \definebodyfontswitch [x] [\!!tenpoint]
-% \definebodyfontswitch [ix] [\!!ninepoint]
-% \definebodyfontswitch [viii] [\!!eightpoint]
-% \definebodyfontswitch [vii] [\!!sevenpoint]
-% \definebodyfontswitch [vi] [\!!sixpoint]
-
-%D So far.
-
-\definefontstyle [\c!mm] [\c!mm]
-\definefontstyle [\c!rm,\v!roman,\v!serif,\v!regular] [\c!rm]
-\definefontstyle [\c!ss,\v!sansserif,\v!sans,\v!support] [\c!ss]
-\definefontstyle [\c!tt,\v!teletype,\v!type,\v!mono] [\c!tt]
-\definefontstyle [\c!hw,\v!handwritten] [\c!hw]
-\definefontstyle [\c!cg,\v!calligraphic] [\c!cg]
-
-\definefontalternative[\c!tf]
-\definefontalternative[\c!bf]
-\definefontalternative[\c!it]
-\definefontalternative[\c!sl]
-\definefontalternative[\c!bs]
-\definefontalternative[\c!bi]
-\definefontalternative[\c!sc]
-
-\definefontsize[\c!a] \definefontsize[\c!b]
-\definefontsize[\c!c] \definefontsize[\c!d]
-
-\definealternativestyle [\v!mediaeval] [\os] []
-\definealternativestyle [\v!normal] [\tf] []
-\definealternativestyle [\v!bold] [\bf] []
-\definealternativestyle [\v!type] [\tt] []
-\definealternativestyle [\v!mono] [\tt] []
-\definealternativestyle [\v!slanted] [\sl] []
-\definealternativestyle [\v!italic] [\it] []
-\definealternativestyle [\v!boldslanted,\v!slantedbold] [\bs] []
-\definealternativestyle [\v!bolditalic,\v!italicbold] [\bi] []
-
-% \definealternativestyle [\v!small,\v!smallnormal] [\tfx] []
-% \definealternativestyle [\v!smallbold] [\bfx] []
-% \definealternativestyle [\v!smalltype] [\ttx] []
-% \definealternativestyle [\v!smallslanted] [\slx] []
-% \definealternativestyle [\v!smallboldslanted,\v!smallslantedbold] [\bsx] []
-% \definealternativestyle [\v!smallbolditalic,\v!smallitalicbold] [\bix] []
-
-\definealternativestyle [\v!small,\v!smallnormal] [\setsmallbodyfont\tf] []
-\definealternativestyle [\v!smallbold] [\setsmallbodyfont\bf] []
-\definealternativestyle [\v!smalltype] [\setsmallbodyfont\tt] []
-\definealternativestyle [\v!smallslanted] [\setsmallbodyfont\sl] []
-\definealternativestyle [\v!smallboldslanted,\v!smallslantedbold] [\setsmallbodyfont\bs] []
-\definealternativestyle [\v!smallbolditalic,\v!smallitalicbold] [\setsmallbodyfont\bi] []
-
-\definealternativestyle [\v!bigger] [\setbigbodyfont \tf] []
-\definealternativestyle [\v!smaller] [\setsmallbodyfont\tf] []
-
-\definealternativestyle [\v!sans,\v!sansserif] [\ss] []
-\definealternativestyle [\v!sansbold] [\ss\bf] []
-
-%D We can go on and on and on:
-%D
-%D \starttyping
-%D \setupbodyfontenvironment[default][p=0.8,q=0.6]
-%D \definefontsize[p]
-%D \definefontsize[q]
-%D \stoptyping
-
-%D Slow but handy:
-
-\definealternativestyle [\v!smallbodyfont] [\setsmallbodyfont] []
-\definealternativestyle [\v!bigbodyfont] [\setbigbodyfont] []
-
-%D We treat {\sc Small Caps} and \cap {Pseudo Caps} a bit
-%D different. We also provide an \WORD {uppercase} style.
-
-\definealternativestyle [\v!cap,\v!capital] [\smallcapped] [\smallcapped]
-\definealternativestyle [\v!smallcaps] [\sc] [\sc]
-\definealternativestyle [\v!WORD] [\WORD] [\WORD]
-
-%D \macros
-%D {fontstylesuffix}
-%D
-%D The next macro is used to map non latin fontnames on
-%D fonts. See \type {font-uni} for an example of its use.
-
-\def\fontstylesuffix% why the \s!Regular ? see \getglyph
- {\ifx\fontalternative\c!tf \s!Regular \else
- \ifx\fontalternative\c!bf \s!Bold \else
- \ifx\fontalternative\c!sl \s!Slanted \else
- \ifx\fontalternative\c!it \s!Italic \else
- \ifx\fontalternative\c!bs \s!BoldSlanted \else
- \ifx\fontalternative\c!bi \s!BoldItalic \else
- \ifx\fontalternative\c!sc \s!Caps \else
- \s!Regular \fi\fi\fi\fi\fi\fi\fi}%
-
-%D \macros
-%D {definefontvariant,fontvariant,variant}
-%D
-%D This command is obsolete in \MKIV\ as we have features. It might
-%D come back using the local features handlers.
-
-\unexpanded\def\definefontvariant{\dotripleargument\dodefinefontvariant}
-
-\def\dodefinefontvariant[#1][#2][#3]{}
-\def\variant [#1]{}
-
-\ifdefined\Var\else \let\Var\variant \fi
-
-%D By default we load the Computer Modern Roman fonts (but
-%D not yet at this moment) and activate the 12pt roman
-%D bodyfont. Sans serif and teletype are also available and
-%D can be called for by \type{\ss} and \type{\tt}. Loading
-%D takes place elsewhere.
-%D
-%D For tracing purposes we define:
-
-\definefont[tinyfont][Mono at 1ex]
-
-% \tracinglostchars=1
-
-% this needs some interfacing
-%
-% \setupfonts[check=...]
-
-\def\checkcharactersinfont {\ctxlua{fonts.checkers.enable()}}
-\def\removemissingcharacters{\ctxlua{fonts.checkers.enable(true)}}
-
-%D New commands (not yet interfaced):
-
-% \def\style[#1]% for inline usage, like \color
-% {\groupedcommand{\ifcsname#1\endcsname\csname#1\endcsname\else\definedfont[#1]\fi}{}}
-%
-% \unexpanded\def\startstyle[#1]%
-% {\begingroup
-% \ifcsname#1\endcsname\csname#1\endcsname\else\definedfont[#1]\fi}
-%
-% \unexpanded\def\stopstyle
-% {\endgroup}
-
-% definitions
-
-\def\definestyle
- {\dotripleargument\dodefinestyle}
-
-\def\dodefinestyle[#1][#2][#3]%
- {\doifassignmentelse{#2}\dododefinestyle\definealternativestyle[#1][#2][#3]}
-
-\def\dododefinestyle[#1][#2][#3]% no commalist and for the moment #3 is ignored
- {\getparameters[\??cf:#1][\c!style=,\c!color=,#2]%
- \setuvalue{\e!start#1}{\begingroup\dostartattributes{\??cf:#1}\c!style\c!color}%
- \setuvalue{\e!stop #1}{\dostopattributes\endgroup}%
- \setuvalue {#1}{\groupedcommand{\dostartattributes{\??cf:#1}\c!style\c!color}\dostopattributes}}
-
-\def\setupstyle
- {\dotripleargument\dosetupstyle}
-
-\def\dosetupstyle[#1][#2][#3]% no commalist and for the moment #3 is ignored
- {\ifcsname\??cf:#1\c!style\endcsname
- \getparameters[\??cf:#1][#2]%
- \else
- \getparameters[\??cf:#1][\c!style=,\c!color=,#2]% so we define but without commands (todo for all define related things)
- \fi}
-
-% commands
-
-\unexpanded\def\style[#1]%
- {\csname\ifcsname#1\endcsname n\else\ifcsname\??cf:#1\c!style\endcsname c\else d\fi\fi ostyle\endcsname{#1}}
-
-\def\nostyle#1{\csname#1\endcsname}
-\def\costyle#1{\groupedcommand{\dostartattributes{\??cf:#1}\c!style\c!color}\dostopattributes}
-\def\dostyle#1{\doifassignmentelse{#1}\dostyleassignment\dostyledirect{#1}}
-
-\def\dostyleassignment#1%
- {\groupedcommand
- {\getparameters[\??cf][\c!style=,\c!color=,#1]%
- \dostartattributes\??cf\c!style\c!color}
- {\dostopattributes}}
-
-\def\dostyledirect#1%
- {\groupedcommand
- {\definedfont[#1]}
- {}}
-
-% environments
-
-\unexpanded\def\startstyle[#1]%
- {\begingroup
- \csname\ifcsname#1\endcsname n\else\ifcsname\??cf:#1\c!style\endcsname c\else d\fi\fi ostyless\endcsname{#1}}
-
-\unexpanded\def\stopstyle
- {\dostopstyle
- \endgroup
- \autoinsertnextspace} % will be configurable, maybe also in \definestartstop
-
-\def\nostyless#1{\let\dostopstyle\donothing\csname#1\endcsname}
-\def\costyless#1{\let\dostopstyle\dostopattributes\dostartattributes{\??cf:#1}\c!style\c!color}
-\def\dostyless#1{\doifassignmentelse{#1}\dostylessassignment\dostylessdirect{#1}}
-
-\def\dostylessassignment#1%
- {\let\dostopstyle\dostopattributes
- \getparameters[\??cf][\c!style,\c!color=,#1]%
- \dostartattributes\??cf\c!style\c!color}
-
-\def\dostylessdirect#1%
- {\let\dostopstyle\donothing
- \definedfont[#1]\relax}
-
-%D Still experimental (might even go away).
-
-% \definestylecollection[mine]
-
-% \definestyleinstance[mine][default][sorry]
-% \definestyleinstance[mine][tt][bs][ttbs:\rm\sl]
-% \definestyleinstance[mine][tt][bf][ttbf:\rm\sl]
-% \definestyleinstance[mine][bf][\sl]
-% \definestyleinstance[mine][sl][\tt]
-
-% {\bf test \mine test \sl test \mine test \bs oeps \mine oeps {\tt test \mine \bf test}}
-
-\unexpanded\def\definestylecollection
- {\dosingleargument\dodefinestylecollection}
-
-\def\dodefinestylecollection[#1]%
- {\iffirstargument
- \setuvalue{#1}{\styleinstance[#1]}%
- \def\docommand##1%
- {\def\dodocommand####1{\letbeundefined{\??sx##1:####1:\commalistelement}}%
- \processcommacommand[\fontalternativelist,\s!default]\dodocommand}%
- \processcommacommand[\fontstylelist,\s!default]\docommand
- \fi}
-
-\unexpanded\def\definestyleinstance
- {\doquadrupleargument\dodefinestyleinstance}
-
-\def\dodefinestyleinstance[#1][#2][#3][#4]% [name] [rm|ss|tt|..] [sl|bf|...] [whatever]
- {\iffirstargument
- \ifcsname#1\endcsname\else\definestylecollection[#1]\fi
- \fi
- \iffourthargument
- \setvalue{\??sx#1:#2:#3}{#4}%
- \else\ifthirdargument
- \setvalue{\??sx#1::#2}{#3}%
- \else\ifsecondargument
- \letvalueempty{\??sx#1::#2}%
- \fi\fi\fi}
-
-\unexpanded\def\styleinstance[#1]% will be made faster
- {%\begingroup\normalexpanded{\noexpand\infofont[#1:\fontstyle:\fontalternative]}\endgroup
- \executeifdefined{\??sx#1:\fontstyle:\fontalternative}%
- {\executeifdefined{\??sx#1:\fontstyle:\s!default}%
- {\executeifdefined{\??sx#1::\fontalternative}
- {\getvalue {\??sx#1::\s!default}}}}}
-
-% \unexpanded\def\styleinstance[#1]%
-% {\csname\??sx#1%
-% \ifcsname:\fontstyle:\fontalternative\endcsname
-% :\fontstyle:\fontalternative
-% \else\ifcsname:\fontstyle:\s!default\endcsname
-% :\fontstyle:\s!default
-% \else\ifcsname::\fontalternative\endcsname
-% ::\fontalternative
-% \else\ifcsname::\s!default\endcsname
-% ::\s!default
-% \else
-% % nothing, \relax
-% \fi\fi\fi\fi
-% \endcsname}
-
-%D goodies:
-
-\unexpanded\def\showchardata#1{\ctxcommand{showchardata("#1")}}
-\unexpanded\def\showfontdata {\ctxcommand{showfontparameters()}}
-
-%D some low level helpers
-%D
-%D \starttyping
-%D \def\TestLookup#1%
-%D {\dolookupfontbyspec{#1}
-%D pattern: #1, found: \dolookupnoffound
-%D \blank
-%D \dorecurse {\dolookupnoffound} {%
-%D \recurselevel:~\dolookupgetkeyofindex{fontname}{\recurselevel}\quad
-%D }%
-%D \blank}
-%D
-%D \TestLookup{familyname=helveticaneue}
-%D \TestLookup{familyname=helveticaneue,weight=bold}
-%D \TestLookup{familyname=helveticaneue,weight=bold,style=italic}
-%D \stoptyping
-
-% we can also move the lookups to the fonts.namespace (of commands)
-
-\def\dolookupfontbyspec #1{\ctxcommand{fontlookupinitialize("#1")}}
-\def\dolookupnoffound {\ctxcommand{fontlookupnoffound()}}
-\def\dolookupgetkeyofindex#1#2{\ctxcommand{fontlookupgetkeyofindex("#1",#2)}}
-\def\dolookupgetkey #1{\ctxcommand{fontlookupgetkey("#1")}}
-\def\cleanfontname #1{\ctxcommand{cleanfontname("#1")}}
-
-% \doifelsecurrentfonthasfeature{smcp}{YES}{NO}
-% \doifelsecurrentfonthasfeature{crap}{YES}{NO}
-% \doifelsecurrentfonthasfeature{kern}{YES}{NO}
-
-\def\doifelsecurrentfonthasfeature#1%
- {\ctxcommand{doifelsecurrentfonthasfeature("#1")}}
-
-\protect \endinput
-
diff --git a/Master/texmf-dist/tex/context/base/font-ini.mkvi b/Master/texmf-dist/tex/context/base/font-ini.mkvi
new file mode 100644
index 00000000000..f581a1685f2
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-ini.mkvi
@@ -0,0 +1,2282 @@
+%D \module
+%D [ file=font-ini,
+%D version=1998.09.11, % (second)
+%D version=2001.02.20, % (third)
+%D title=\CONTEXT\ Font 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.
+
+% todo: < 3 pt => 3pt
+% todo: check where more class usage
+% todo: split font-nam (style/alternative/size)
+% todo: split font-dim (scales etc)
+% todo: reconsider defaultfontclass
+%
+
+%D Watch out: as we define inside macros in sometimes special ways,
+%D an occasional \type {\normaldef} is used in order to please the
+%D \MKVI\ parser.
+
+%D Beware, we use a special set of parameters here:
+%D
+%D \starttabulate[|l|l|]
+%D \NC system variable (fixed) \NC \type {\s!text} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!script} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!scriptscript} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!x} \NC \NR
+%D \NC system variable (fixed) \NC \type {\s!xx} \NC \NR
+%D \NC variable (value) \NC \type {\v!big} \NC \NR
+%D \NC variable (value) \NC \type {\v!small} \NC \NR
+%D \NC constant (regular key) \NC \type {\c!interlinespace} \NC \NR
+%D \NC constant (regular key) \NC \type {\c!em} \NC \NR
+%D \stoptabulate
+%D
+%D The math related ones are similar to the ones used in \TEX\ itself,
+%D the size related ones show up as keywords in the user interface
+%D when switching sizes, and the two constants are used in key|/|value
+%D situations.
+
+%D We should consider design sizes ... maybe kick 'm out which removes
+%D the size code and simplifies things considerably. After all, there
+%D will be no latin modern math in sizes.
+
+\writestatus{loading}{ConTeXt Font Macros / Initialization}
+
+%D Documentation is somewhat messy as it contains bits and pieces of
+%D previous versions.
+
+\unprotect
+
+%D There are several ways to specify a font. Three of them are
+%D pure \TeX\ ones, the fourth one is new:
+%D
+%D \starttyping
+%D \font\name=cmr12
+%D \font\name=cmr12 at 10pt
+%D \font\name=cmr12 scaled 2
+%D \font\name=cmr12 sa 1.440
+%D \stoptyping
+%D
+%D The non||\TEX\ alternative \type{sa} stands for {\em scaled
+%D at}. This means as much as: scale the bodyfontsize with this
+%D factor. The scaled option is not that useful as one needs to
+%D know the design size.
+%D
+%D Because \type {sa} (scaled at) and \type {mo} (mapped on)
+%D are not low level \TEX\ supported alternatives, we have to
+%D test for it ourselves. In doing so, we need an auxiliary
+%D \DIMENSION. We cannot use \type{\scratchdimen} because font
+%D loading can happen at any moment due to postponed loading.
+%D We could instead have used dirty grouping tricks, but this
+%D one works too.
+
+% \enableexperiments[fonts.autorscale]
+%
+% \starttypescript[mscore]
+% \definetypeface [mscore] [rm] [serif] [mscoretimes] [default]
+% \definetypeface [mscore] [ss] [sans] [mscorearial] [default] [rscale=auto] % 0.860]
+% \definetypeface [mscore] [tt] [mono] [mscorecourier] [default] [rscale=auto] % 1.065]
+% \definetypeface [mscore] [mm] [math] [times] [default] [rscale=auto] % 1.020]
+% \stoptypescript
+%
+% \starttext
+% \setupbodyfont[mscore,12pt]
+% \startTEXpage
+% test \ss test \tt test
+% \stopTEXpage
+% \stoptext
+
+% \definetypeface[one][rm][serif][computer-roman][default]
+% \definetypeface[two][rm][serif][computer-roman][default][rscale=.9]
+%
+% {\one \bf test \two test}
+% {\one \bf test \pushcurrentfont \two \popcurrentfont test}
+
+%D \macros
+%D {rm,ss,tt,hw,cg}
+%D
+%D Fonts are defined in separate files. When we define a font,
+%D we distinguish between several styles. In most cases we will
+%D use:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC roman regular serif \NC \type{\rm} \NC\FR
+%D \NC sansserif sans support \NC \type{\ss} \NC\MR
+%D \NC type teletype mono \NC \type{\tt} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D The number of styles is not limited to these three. When
+%D using Lucida Bright we can for instance also define:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC handwritten \NC \type{\hw} \NC\FR
+%D \NC calligraphic \NC \type{\cg} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Within such a font set (\type{cmr}) and style (\type{\rm})
+%D we can define a number of text font alternatives:
+%D
+%D \startlinecorrection
+%D \starttable[|l||]
+%D \HL
+%D \NC typeface \NC \type{\tf} \NC\FR
+%D \NC boldface \NC \type{\bf} \NC\MR
+%D \NC slanted \NC \type{\sl} \NC\MR
+%D \NC italic \NC \type{\it} \NC\MR
+%D \NC boldslanted \NC \type{\bs} \NC\MR
+%D \NC bolditalic \NC \type{\bi} \NC\MR
+%D \NC smallcaps \NC \type{\sc} \NC\LR
+%D \HL
+%D \stoptable
+%D \stoplinecorrection
+%D
+%D Internally fonts are stored as combination of size, style
+%D and alternative, e.g. \type{12pt}+\type{\ss}+\type{\bf}.
+%D Users are not confronted with sizes, but use the style or
+%D style+alternative to activate them.
+%D
+%D During the definition of a bodyfont one can also declare the
+%D available larger alternatives:
+%D
+%D \starttyping
+%D \tf \tfa \tfb \tfc ...
+%D \bf \bfa \bfb \bfc ...
+%D \sl \sla \slb \slc ...
+%D \stoptyping
+%D
+%D The smaller ones are automatically supplied and derived from
+%D the the bodyfont environment.
+%D
+%D \starttyping
+%D \tfx \tfxx
+%D \bfx \bfxx
+%D \slx \slxx
+%D \stoptyping
+%D
+%D There are only two smaller alternatives per style. The
+%D larger alternatives on the other hand have no limitations.
+%D
+%D These larger alternatives are mostly used in chapter and
+%D section titles or on title pages. When one switches to a
+%D larger alternative, the bold an other ones automatically
+%D adapt themselves:
+%D
+%D \startbuffer
+%D \tfd Hi \bf there\sl, here \tfb I \bf am
+%D \stopbuffer
+%D
+%S \startnarrower
+%D \typebuffer
+%S \stopnarrower
+%D
+%D therefore becomes:
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D Maybe this mechanism isn't always as logic, but as said
+%D before, we tried to make it as intuitive as possible.
+%D
+%D So a specific kind of glyph can be characterized by:
+%D
+%D \startnarrower
+%D family (cmr) + bodyfont (12pt) + style (rm) + alternative (bf) + size (a)
+%D \stopnarrower
+%D
+%D The last component (the size) is optional.
+%D
+%D We introduced \type{\tf} as command to call for the current
+%D normally sized typeface. This commands results in roman,
+%D sans serif, teletype or whatever style is in charge. Such
+%D rather massive switches of style sometimes take more
+%D processing time than comfortable. Of course there is a
+%D workaround for this: we can call fonts directly by means of
+%D commands like:
+%D
+%D \starttyping
+%D \rmtf \sssl \tttf \rmbsa
+%D \stoptyping
+%D
+%D One should realize that this fast calls have limitations,
+%D they lack for instance automatic super- and subscript
+%D support.
+%D
+%D This leaves us two more commands: \type{\tx} and
+%D \type{\txx}. These activate a smaller and even more smaller
+%D font than the current one and adapt themselves to the
+%D current alternative, so when \type{\bf} is active,
+%D \type{\tx} gives a smaller boldface, which in turn can be
+%D called directly by \type{\bfx}.
+%D
+%D These two smaller alternatives are specified by the bodyfont
+%D environment and therefore not necessarily have similar sizes
+%D as \type{\scriptsize} and \type{\scriptscriptsize}. The main
+%D reason for this incompatibility (which can easily be undone)
+%D lays in the fact that we often want a bit bigger characters
+%D than in math mode. In \CONTEXT\ for instance the \type{\tx}
+%D and \type{\txx} commands are used for surrogate
+%D \cap{smallcaps} which support both nesting and alternatives,
+%D like in {\bf\cap{a \cap{small} world}}, which was typeset by
+%D
+%D \starttyping
+%D \bf\cap{a \cap{small} world}
+%D \stoptyping
+%D
+%D And compare $\rm \scriptstyle THIS$ with the slightly larger
+%D \cap{THIS}: \ruledhbox{$\rm \scriptstyle scriptstyle: THIS$}
+%D or \ruledhbox{\cap{x style: THIS}} makes a big difference.
+%D
+%D The \type{x..d} sizes should be used grouped. If you
+%D don't group them, i.e. call them in a row, \CONTEXT\ will
+%D not be able to sort out your intention (\type {x} inside
+%D \type {d} inside \type {x}. etc.). The following table
+%D demonstrates this:
+%D
+%D \def\FontState{\setstrut\ruledhbox{\strut Hello}}
+%D
+%D \starttabulate[|||||]
+%D \HL
+%D \NC \rlap{\quad\bf grouped} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
+%D \HL
+%D \NC \type{\tfx} \NC \tfx \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState \NC \NR
+%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState \NC \NR
+%D \NC \type{\tf} \NC \tf \FontState \NC \tf \tx \FontState \NC \tf \txx \FontState \NC \NR
+%D \NC \type{\tfa} \NC \tfa \FontState \NC \tfa \tx \FontState \NC \tfa \txx \FontState \NC \NR
+%D \NC \type{\tfb} \NC \tfb \FontState \NC \tfb \tx \FontState \NC \tfb \txx \FontState \NC \NR
+%D \NC \type{\tfc} \NC \tfc \FontState \NC \tfc \tx \FontState \NC \tfc \txx \FontState \NC \NR
+%D \NC \type{\tfd} \NC \tfd \FontState \NC \tfd \tx \FontState \NC \tfd \txx \FontState \NC \NR
+%D \NC \type{\tfx} \NC \tfx \FontState \NC \tfx \tx \FontState \NC \tfx \txx \FontState \NC \NR
+%D \NC \type{\tfxx} \NC \tfxx \FontState \NC \tfxx\tx \FontState \NC \tfxx\txx \FontState \NC \NR
+%D \HL
+%D \stoptabulate
+%D
+%D \blank
+%D
+%D \starttabulate[|||||]
+%D \HL
+%D \NC \rlap{\quad\bf stacked} \NC \NC \type {\tx} \NC \type {\txx} \NC \NR
+%D \HL
+%D \NC \type{\tfx}
+%D \NC \tfx \FontState
+%D \NC \tfx \tx \FontState
+%D \NC \tfx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfxx}
+%D \NC \tfx\tfxx \FontState
+%D \NC \tfx\tfxx \tx \FontState
+%D \NC \tfx\tfxx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tf}
+%D \NC \tfx\tfxx\tf \FontState
+%D \NC \tfx\tfxx\tf \tx \FontState
+%D \NC \tfx\tfxx\tf \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfa}
+%D \NC \tfx\tfxx\tf\tfa \FontState
+%D \NC \tfx\tfxx\tf\tfa \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfb}
+%D \NC \tfx\tfxx\tf\tfa\tfb \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfc}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfd}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfd \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfx}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx \txx \FontState
+%D \NC \NR
+%D \NC \type{\tfxx}
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \tx \FontState
+%D \NC \tfx\tfxx\tf\tfa\tfb\tfc\tfx\tfxx \txx \FontState
+%D \NC \NR
+%D \HL
+%D \stoptabulate
+
+\fontslantperpoint \nullfont 0\scaledpoint
+\fontinterwordspace \nullfont 256377\scaledpoint
+\fontinterwordstretch\nullfont 128188\scaledpoint
+\fontinterwordshrink \nullfont 85459\scaledpoint
+\fontexheight \nullfont 338952\scaledpoint
+\fontemwidth \nullfont 786432\scaledpoint
+\fontextraspace \nullfont 85459\scaledpoint
+
+%D Tracing
+
+\newtoks\t_font_tracers_definitions
+
+\unexpanded\def\tracefontdefinitions
+ {\the\t_font_tracers_definitions}
+
+%D Some housekeeping macros:
+
+\unexpanded\def\setfontparameters
+ {\setfalse\c_font_synchronize
+ \the\everybodyfont
+ \settrue\c_font_synchronize}
+
+\unexpanded\def\savefont
+ {\edef\savedfont{\the\font}% gives \csname
+ \pushmacro\savedfont}
+
+\unexpanded\def\restorefont
+ {\popmacro\savedfont
+ \savedfont}
+
+\unexpanded\def\pushcurrentfont
+ {\edef\popcurrentfont
+ {\def\noexpand\fontbody {\fontbody}%
+ \def\noexpand\fontstyle {\fontstyle}%
+ \def\noexpand\fontalternative{\fontalternative}%
+ \def\noexpand\fontsize {\fontsize}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}}
+
+%D \macros{definedfont}
+
+\let\thedefinedfont\relax % not to be confused with \everydefinefont
+
+\unexpanded\def\definedfont
+ {\doifnextoptionalelse\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
+ \thedefinedfont
+ \the\everydefinedfont}
+
+%D \macros{startfont}
+
+\unexpanded\def\startfont{\begingroup\definedfont}
+\unexpanded\def\stopfont {\endgroup}
+
+%D \macros
+%D {everybodyfont,Everybodyfont,everyglobalbodyfont}
+%D
+%D Every change in bodyfont size has conseqences for the baseline
+%D distance and skips between paragraphs. These are initialized
+%D in other modules. Here we only provide the hooks that
+%D garantees their handling.
+
+%D At the system level one can initialize thing like:
+%D
+%D \starttyping
+%D \appendtoks \setupspacing \to \everybodyfont
+%D \stoptyping
+%D
+%D While users can add their own non standard commands like:
+%D
+%D \starttyping
+%D \EveryBodyFont{\message{changing to bodyfont \the\bodyfontsize}}
+%D \stoptyping
+%D
+%D Personnaly I never felt the need for such extensions, but
+%D at least its possible.
+
+%D \macros
+%D {globalbodyfontsize,localbodyfontsize,bodyfontsize}
+
+%D Here we have to distinguish between the global (overal) bodyfont
+%D size and the local (sometimes in the textflow) size. We store
+%D these dimensions in two \DIMENSION\ registers. These registers are
+%D not to be misused in calculations.
+
+\ifdefined\globalbodyfontsize\else \newdimen\globalbodyfontsize \fi \globalbodyfontsize=12pt
+\ifdefined\localbodyfontsize \else \newdimen\localbodyfontsize \fi \localbodyfontsize =\globalbodyfontsize
+\ifdefined\bodyfontsize \else \newdimen\bodyfontsize \fi \bodyfontsize =\globalbodyfontsize
+
+%D When we assign for instance 12pt to a \DIMENSION\ register the \type
+%D {\the}'d value comes out as 12.0pt, which is often not the way users
+%D specify the bodyfont size. Therefore we use normalized values. They
+%D are caches to save overhead in \LUA\ calls.
+
+\setnewconstant\fontdigits\plustwo
+
+\installcorenamespace{fontnormalizedbody}
+
+\def\normalizebodyfontsize#macro#body%
+ {\expandafter\let\expandafter#macro\csname\??fontnormalizedbody\number\fontdigits:\number\dimexpr#body\endcsname
+ \ifx#macro\relax
+ \normalizebodyfontsize_indeed#macro{#body}%
+ \fi}
+
+\def\normalizebodyfontsize_indeed#macro#body%
+ {\edef#macro{\ctxcommand{nbfs(\number\dimexpr#body,\number\fontdigits)}}%
+ \global\expandafter\let\csname\??fontnormalizedbody\number\fontdigits:\number\dimexpr#body\endcsname#macro}
+
+\def\thenormalizedbodyfontsize#body%
+ {\ctxcommand{nbfs(\number\dimexpr#body\relax,\number\fontdigits)}}
+
+\edef\normalizedglobalbodyfontsize{\thenormalizedbodyfontsize\bodyfontsize}
+\edef\normalizedlocalbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
+\edef\normalizedbodyfontsize {\thenormalizedbodyfontsize\bodyfontsize}
+
+%D \macros
+%D {mapfontsize}
+%D
+%D For special purposes, like in math, you may want to use
+%D slightly different sizes than the ones given. This happens
+%D for instance with the Math Times fonts. Mapped font sizes
+%D can be specified by using the \type {mo} key instead of
+%D \type {sa} in font definitions.
+%D
+%D \startbuffer
+%D \mapfontsize[10pt][11pt]
+%D \mapfontsize[11pt][12pt]
+%D \mapfontsize[12pt][13pt]
+%D
+%D \definefont[test][Serif]\test TEST \par
+%D \definefont[test][Serif sa 5]\test TEST \par
+%D \definefont[test][Serif mo 5]\test TEST \par
+%D \definefont[test][Serif sa d]\test TEST \par
+%D \definefont[test][Serif at 60pt]\test TEST \par
+%D \definefont[test][Serif scaled 6000]\test TEST \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startpacked
+%D \getbuffer
+%D \stoppacked
+
+\installcorenamespace{mappedfontsize}
+
+\unexpanded\def\mapfontsize
+ {\dodoubleargument\font_basics_map_fontsize}
+
+\def\font_basics_map_fontsize[#from][#to]%
+ {\setvalue{\??mappedfontsize\the\dimexpr#from\relax}{#to}}
+
+\def\font_basics_set_mapped_fontsize#from%
+ {\ifcsname\??mappedfontsize\the\dimexpr#from\relax\endcsname
+ \csname\??mappedfontsize\the\dimexpr#from\relax\endcsname\else#from%
+ \fi}
+
+\installcorenamespace{fontbodyknown}
+\installcorenamespace{fontclassyes} % fontclass
+\installcorenamespace{fontclassnop} % nofontclass
+
+\def\font_helpers_process_relative_size_list#command% could be a toks
+ {#command\v!big
+ #command\v!small}
+
+\let\v_font_size_relative \plusone
+\def\v_font_size_absolute {\fontbody}
+
+\let\v_font_rscale_default\!!plusone
+\let\p_font_rscale \v_font_rscale_default
+
+\def\font_helpers_check_relative_font_id % can be plugged in later
+ {\let\p_font_rscale\minusone
+ \let\p_font_rscale\v_font_rscale_default}
+
+\def\font_helpers_check_relative_font_size#style%
+ {\edef\p_font_rscale
+ {\ifcsname\??fontclass\fontclass#style\s!rscale\endcsname
+ \csname\??fontclass\fontclass#style\s!rscale\endcsname
+ \else\ifcsname\??fontclass\defaultfontclass#style\s!rscale\endcsname % brr
+ \csname\??fontclass\defaultfontclass#style\s!rscale\endcsname
+ \else
+ \v_font_rscale_default
+ \fi\fi}%
+ % move elsewhere
+ \ifx\p_font_rscale\v!auto
+ \let\p_font_rscale\plusone
+ \font_helpers_check_relative_font_id
+ \else
+ \let\relativefontid\minusone
+ \fi}
+
+\def\font_rscale_xx#style%
+ {\ifcsname\??fontclass\fontclass#style\s!rscale\endcsname
+ \csname\??fontclass\fontclass#style\s!rscale\endcsname
+ \else
+ \v_font_rscale_default
+ \fi}
+
+\def\font_rscale_mm
+ {\ifcsname\??fontclass\fontclass\s!mm\s!rscale\endcsname
+ \csname\??fontclass\fontclass\s!mm\s!rscale\endcsname
+ \else
+ \v_font_rscale_default
+ \fi}
+
+\def\font_helpers_register_fontbody#body%
+ {\expandafter\let\csname\??fontbodyknown#body\endcsname\empty}
+
+%D \macros
+%D {definefontstyle,definefontsize,definefontalternative}
+%D
+%D When setting of switching the overall style we can use the
+%D short identifier like rm and ss, but when defined we can
+%D also use more verbose names like roman or sansserif. Such
+%D names are defined by:
+%D
+%D \starttyping
+%D \definefontstyle [serif,rm] [rm]
+%D \definefontstyle [sansserif,ss] [ss]
+%D \stoptyping
+
+\installcorenamespace{fontstyle} % full style prefix (roman etc)
+\installcorenamespace{fontshortstyle} % short style prefix (rm etc)
+
+\installcorenamespace{fontstyleknown}
+\installcorenamespace{fontalternativeknown}
+\installcorenamespace{fontsizeknown}
+
+\newtoks\t_font_style_commands
+\newtoks\t_font_size_commands
+\newtoks\t_font_alternative_commands
+
+\setnewmacro\m_font_style_command \gobbleoneargument
+\setnewmacro\m_font_size_command \gobbleoneargument
+\setnewmacro\m_font_alternative_command\gobbleoneargument
+
+\def\font_helpers_process_style_list #command{\def\m_font_style_command {#command}\the\t_font_style_commands}
+\def\font_helpers_process_size_list #command{\def\m_font_size_command {#command}\the\t_font_size_commands}
+\def\font_helpers_process_alternative_list#command{\def\m_font_alternative_command{#command}\the\t_font_alternative_commands}
+
+\def\font_helpers_register_style #style{\expandafter\let\csname\??fontstyleknown #style\endcsname\empty}
+\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 ...
+ {\ifcsname\??fontstyleknown#style\endcsname \else % can be delayed till used (cg, hw)
+ \font_helpers_register_style{#style}%
+ \t_font_style_commands\expandafter{\the\t_font_style_commands
+ \m_font_style_command{#style}}%
+ \fi
+ \processcommalist[#commands]{\font_basics_define_fontstyle_indeed{#style}}}
+
+\def\font_basics_define_fontstyle_indeed#style#command%
+ {\setvalue{\??fontshortstyle#command}{#style}%
+ \setvalue{\??fontstyle #command}{\csname#style\endcsname}}
+
+\unexpanded\def\definefontsize[#size]%
+ {\ifcsname\??fontsizeknown#size\endcsname \else
+ \font_helpers_register_size{#size}%
+ \t_font_size_commands\expandafter{\the\t_font_size_commands
+ \m_font_size_command{#size}}%
+ \fi
+ \font_helpers_check_fontname_combinations}
+
+\unexpanded\def\definefontalternative[#alternative]%
+ {\ifcsname\??fontalternativeknown#alternative\endcsname \else
+ \font_helpers_register_alternative{#alternative}%
+ \t_font_alternative_commands\expandafter{\the\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)
+ {\font_helpers_process_style_list\font_helpers_check_fontname_combinations_s}
+
+\def\font_helpers_check_fontname_combinations_s#style%
+ {\font_helpers_process_alternative_list{\font_helpers_check_fontname_combinations_indeed_s_a{#style}}}
+
+\def\font_helpers_check_fontname_combinations_indeed_s_a#style#alternative%
+ {\font_helpers_process_size_list{\font_basics_check_fontname_combination{#style}{#alternative}}}
+
+\definefontstyle [\s!mm] [\s!mm]
+\definefontstyle [\s!rm] [\s!rm]
+\definefontstyle [\s!ss] [\s!ss]
+\definefontstyle [\s!tt] [\s!tt]
+
+%D We define all the font switching commands globally. After all they are part
+%D of the formal font interface once defined. The size can be empty (so
+%D checking is needed as \type {\bf} is already defined)
+
+%D The \type {\normal..} variants are available as extras for cases where
+%D the \type {..} is overloaded.
+
+\newmacro\m_font_mm
+
+\def\font_basics_check_fontname_combination#style% alternative size
+ {\edef\m_font_mm{#style}%
+ \ifx\m_font_mm\s!mm % prevents \max and alike (re)defs
+ \expandafter\font_basics_check_math_bodyfont
+ \else
+ \expandafter\font_basics_check_text_bodyfont
+ \fi{#style}} % no \m_font_mm, not expanded later on
+
+% \def\font_basics_check_math_bodyfont#style#alternative#size%
+% {%setugvalue{#alternative}{\font_helpers_set_current_font_alternative{#alternative}}% \mr \mb
+% \setugvalue{#style}{\font_helpers_set_current_font_style{#style}}}% \mm
+
+\def\font_basics_check_math_bodyfont#style#alternative#size%
+ {}
+
+\def\font_basics_check_text_bodyfont#style#alternative#size% size can be empty (checking needed as \bf is already defined)
+ {\setugvalue{#style#size}{\font_helpers_set_current_font_style_size{#style}{#size}}% \rma
+ \setugvalue{#alternative#size}{\font_helpers_set_current_font_alternative_size{#alternative}{#size}}% \sla
+ \setugvalue{#style#alternative#size}{\font_helpers_set_current_font_style_alternative_size{#style}{#alternative}{#size}}% \rmsla
+ \ifcsname\s!normal#style\endcsname % text/math check
+ \expandafter\let\csname#style\expandafter\endcsname\csname\s!normal#style\endcsname
+ \else
+ \setugvalue{#style}{\font_helpers_set_current_font_style{#style}}% \rm
+ \fi
+ \ifcsname\s!normal#alternative\endcsname % text/math check
+ \expandafter\let\csname#alternative\expandafter\endcsname\csname\s!normal#alternative\endcsname
+ \else
+ \setugvalue{#alternative}{\font_helpers_set_current_font_alternative{#alternative}}% \sl
+ \fi
+ \setugvalue{#style\s!x}{\font_helpers_set_current_font_x_style_alternative{#style}}% \rmx
+ \setugvalue{#style\s!xx}{\font_helpers_set_current_font_xx_style_alternative{#style}}% \rmxx
+ \setugvalue{#alternative\s!x}{\font_helpers_set_current_font_x_alternative{#alternative}}% \slx
+ \setugvalue{#alternative\s!xx}{\font_helpers_set_current_font_xx_alternative{#alternative}}% \slxx
+ \setugvalue{#style#alternative}{\font_helpers_set_current_font_style_alternative{#style}{#alternative}}}% \rmsl
+
+%D Scaling macros:
+%D
+%D This system is somewhat complicated by two (possible conflicting)
+%D demands:
+%D
+%D \startitemize
+%D \item We support wildcards like \type {sa *} which will adapt
+%D to the current size. This is also the default specification.
+%D \item We support named scales like \type {sa d}; beware: \type
+%D {x} and \type {xx} are valid scales but they are not alway
+%D the same as the ones used in for instance \type {\bfx} because
+%D there the sized come from the bodyfont environment. In the
+%D future there maybe a switch that also honors the environment
+%D in named scales.
+%D \stopitemize
+%D
+%D Keep in mind that the smaller sizes are just for text super and
+%D subscripts while larger sizes can be used in titles where for
+%D instance math follows the size.
+
+% b:x{\definedfont[SerifBold sa b]x}{\bfb x $x^x$}\par
+% 1:x{\definedfont[SerifBold sa 1]x}{\bf x $x^x$}\par
+% x:x{\definedfont[SerifBold sa x]x}{\bfx x $x^x$}\par
+% xx:x{\definedfont[SerifBold sa xx]x}{\bfxx x $x^x$}\par
+%
+% *:x{\definedfont[Serif sa *]x}\par
+% 1:x{\definedfont[Serif sa 1]x}\par
+% 2:x{\definedfont[Serif sa 2]x}\par
+% 3:x{\definedfont[Serif sa 3]x}\par
+% 4:x{\definedfont[Serif sa 4]x}\par
+% 5:x{\definedfont[Serif sa 5]x}\par
+
+\def\safontscale{\number\dimexpr\v_font_size_absolute\relax}
+\def\mofontscale{\number\dimexpr\font_basics_set_mapped_fontsize\v_font_size_absolute\relax}
+
+\let\somefontname\s!unknown
+\let\somefontspec\s!unknown
+\let\somefontsize\zerocount
+
+\newcount\scaledfontmode % also used at the lua end
+\newcount\lastfontid % also used at the lua end / tex end
+\newtoks \everydefinefont
+
+\let\relativefontid\minusone % todo, not yet used
+
+\let\c_font_feature_inheritance_fontnone \zerocount % none
+\let\c_font_feature_inheritance_fontonly \plusone % fontonly
+\let\c_font_feature_inheritance_classonly \plustwo % classonly
+\let\c_font_feature_inheritance_fontfirst \plusthree % fontfirst
+\let\c_font_feature_inheritance_classfirst\plusfour % classfirst
+
+\let\c_font_feature_inheritance_default \c_font_feature_inheritance_fontfirst
+
+\setnewconstant\c_font_feature_inheritance_mode \c_font_feature_inheritance_default
+
+\newdimen \d_font_scaled_text_face
+\newdimen \d_font_scaled_font_size
+\newconditional\c_font_body_scale
+\newfraction \f_font_body_scale
+
+\unexpanded\def\font_helpers_low_level_define#specification#csname%
+ {% we can now set more at the lua end
+ \ctxcommand{definefont_one(\!!bs\luaescapestring{#specification}\!!es)}% the escapestring catches at \somedimen
+ % sets \scaledfontmode and \somefontname and \somefontsize
+ \ifcase\fontface\relax
+ % \let\v_font_size_absolute\textface % fontbody
+ \or
+ \let\v_font_size_absolute\textface
+ \or
+ \let\v_font_size_absolute\scriptface
+ \or
+ \let\v_font_size_absolute\scriptscriptface
+ \or
+ \let\v_font_size_absolute\xtextface
+ \or
+ \let\v_font_size_absolute\xxtextface
+ \fi
+ %
+ \ifcase\scaledfontmode\relax
+ % none, avoid the designsize if possible
+ \d_font_scaled_font_size-\plusthousand\scaledpoint
+ \or
+ % at
+ \d_font_scaled_font_size\somefontsize
+ \or
+ % sa
+ \d_font_scaled_font_size\v_font_size_absolute\relax
+ \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size % uses \somefontsize set by lua
+ \or
+ % mo
+ \d_font_scaled_font_size\font_basics_set_mapped_fontsize\v_font_size_absolute
+ \d_font_scaled_font_size\currentfontbodysize\d_font_scaled_font_size
+ \or
+ % scaled, don't use this one as it's unpredictable
+ \d_font_scaled_font_size-\somefontsize\scaledpoint
+ \fi
+ \relax
+ \d_font_scaled_font_size\v_font_size_relative\d_font_scaled_font_size
+ \ifconditional\c_font_auto_size
+ \font_helpers_check_body_scale\fontsize
+ \ifconditional\c_font_body_scale
+ \d_font_scaled_font_size\f_font_body_scale\d_font_scaled_font_size
+ \d_font_scaled_text_face\f_font_body_scale\dimexpr\textface\relax
+ \else
+ \d_font_scaled_font_size\f_font_body_scale
+ \d_font_scaled_text_face\textface
+ \fi
+ \else
+ \d_font_scaled_text_face\textface
+ \fi
+ \edef\somefontspec{at \number\d_font_scaled_font_size sp}%
+ \edef\somefontfile{\truefontname\somefontname}%
+ \ifx\somefontfile\s!unknown
+ \edef\somefontfile{\defaultfontfile}%
+ \fi
+ \ifx\somefontfile\s!unknown
+ \edef\somefontfile{\defaultfontfile}%
+ \fi
+ \font_helpers_update_font_parameters
+ \font_helpers_update_font_class_parameters
+ % \writestatus{fonts}{low level define: #csname/\somefontfile/\number\d_font_scaled_font_size/\fontface/\number\d_font_scaled_text_face}%
+ \ctxcommand{definefont_two(
+ \ifx\fontclass\empty false\else true\fi,
+ "#csname",
+ \!!bs\somefontfile\!!es,
+ \number\d_font_scaled_font_size,
+ \number\c_font_feature_inheritance_mode,
+ "\m_font_class_features",
+ "\m_font_features",
+ "\m_font_class_fallbacks",
+ "\m_font_fallbacks",
+ \fontface, % 1/2/3: text script scriptscript 0/4/5: body x xx
+ \number\d_font_scaled_text_face,
+ "\number\relativefontid", % experiment
+ "\m_font_class_goodies", % experiment (not yet used)
+ "\m_font_goodies",
+ "\m_font_class_designsize",
+ "\m_font_designsize"
+ )}%
+ \edef\somefontspec{at \number\d_font_scaled_font_size sp}% we need the resolved designsize (for fallbacks)
+ \expandafter\let\expandafter\lastrawfontcall\csname#csname\endcsname
+ \the\everydefinefont
+ \c_font_feature_inheritance_mode\c_font_feature_inheritance_default}
+
+\def\font_helpers_check_body_scale#fontsize% gets character (x xx a etc)
+ {\ifcsname\??fontenvironments\fontclass\fontbody #fontsize\endcsname \setfalse\c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+ \csname\??fontenvironments\fontclass\fontbody #fontsize\endcsname \else
+ \ifcsname\??fontenvironments\fontclass\s!default#fontsize\endcsname \settrue \c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+ \csname\??fontenvironments\fontclass\s!default#fontsize\endcsname \else
+ \ifcsname\??fontenvironments \fontbody #fontsize\endcsname \setfalse\c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+ \csname\??fontenvironments \fontbody #fontsize\endcsname \else
+ \ifcsname\??fontenvironments \s!default#fontsize\endcsname \settrue \c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+ \csname\??fontenvironments \s!default#fontsize\endcsname \else
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname \settrue \c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+ \csname\??fontenvironments\fontclass\s!default\s!text \endcsname \else
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname \settrue \c_font_body_scale \expandafter\let\expandafter\f_font_body_scale
+ \csname\??fontenvironments \s!default\s!text \endcsname
+ \else
+ \settrue \c_font_body_scale
+ \let\f_font_body_scale\plusone
+ \fi\fi\fi\fi\fi\fi}
+
+%D The following macros are used at the \LUA\ end. Watch the \type {\normal}
+%D hackery: this makes the mkvi parser happy.
+
+\normaldef\fntsetdefname {\global\let\somefontname\defaultfontfile} % do before calling
+\normaldef\fntsetsomename{\normalgdef\somefontname} % takes argument
+\normaldef\fntsetnopsize {\let\somefontsize\empty} % do before calling
+\normaldef\fntsetsomesize{\normaldef\somefontsize} % takes argument
+
+\newif\ifskipfontcharacteristics \skipfontcharacteristicstrue
+
+%D When fontclasses are used, we define the font global, since namespaces are
+%D used. Otherwise we parse the specs each time.
+
+\let\fontfile\s!unknown
+
+%D \macros
+%D {everyfont,everyfontswitch}
+
+\ifdefined\everyfont \else \newtoks\everyfont \fi
+\ifdefined\everyfontswitch \else \newtoks\everyfontswitch \fi
+
+\def\setfontcharacteristics{\the\everyfont}
+
+%D \macros
+%D {definefont}
+%D
+%D We also accept \type{sa a}||\type{sa d} as specification.
+%D
+%D Before we implement the main definition macro, we first show
+%D one for local use:
+%D
+%D \starttyping
+%D \definefont[Some][LucidaBright at 100pt] \Some some
+%D \definefont[More][LucidaBright scaled 3000] \More more
+%D \definefont[Nice][LucidaBright mo 2] \Nice nice
+%D \definefont[Text][LucidaBright sa 5.4] \Text last
+%D \stoptyping
+%D
+%D The implementation looks as follows:
+
+\unexpanded\def\definefont % [name][spec][1.6 | line=10pt | setup_id]
+ {\dotripleempty\font_basics_define_font}
+
+\def\font_basics_define_font
+ {\ifthirdargument
+ \expandafter\font_basics_define_font_a
+ \else
+ \expandafter\font_basics_define_font_b
+ \fi}
+
+\def\font_basics_define_font_a[#name][#specification][#settings]% [name][spec][1.6 | line=10pt | setup_id]
+ {\doifsetupselse{#settings}%
+ {\setuvalue{#name}{\font_basics_define_font_with_setups {#name}{#specification}{#settings}}}
+ {\setuvalue{#name}{\font_basics_define_font_with_parameters{#name}{#specification}{#settings}}}}
+
+\def\font_basics_define_font_b[#name][#specification][#dummy]%
+ {\setuvalue{#name}{\font_basics_define_font_without_parameters{#name}{#specification}}}
+
+\def\font_basics_define_font_with_parameters#name#specification#settings%
+ {\font_basics_define_font_without_parameters{#name}{#specification}%
+ \setuplocalinterlinespace[#settings]%
+ \setupspacing\relax} % is this really needed ?
+
+\def\font_basics_define_font_with_setups#name#specification#settings%
+ {\font_basics_define_font_without_parameters{#name}{#specification}%
+ \setups[#settings]}
+
+%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\endgroup\expandafter\let\csname#name\endcsname\lastrawfontcall}
+
+%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.
+
+% todo: now mathsize twice in name (so it can go here)
+% todo: check when mathsize is needed
+
+\ifdefined\??fontinstanceready \else \installcorenamespace{fontinstanceready} \fi
+\ifdefined\??fontinstancebasic \else \installcorenamespace{fontinstancebasic} \fi
+\ifdefined\??fontinstanceclass \else \installcorenamespace{fontinstanceclass} \fi
+
+\newconditional\c_font_auto_size \settrue\c_font_auto_size
+
+\let\lastfontidentifier\empty
+
+\def\v_font_identifier_basic{\??fontinstancebasic \lastfontidentifier-\fontsize-\fontface}
+\def\v_font_identifier_class{\??fontinstanceclass\fontclass-\lastfontidentifier-\fontsize-\fontface}
+
+\let\v_font_identifier_basic_saved\v_font_identifier_basic
+\let\v_font_identifier_class_saved\v_font_identifier_class
+
+% \def\v_font_identifier_class{\??fontinstanceclass\fontclass-\lastfontidentifier-\fontstyle-\fontsize} % no \fontface
+
+\def\font_basics_define_font_without_parameters#identifier#2%
+ {\c_font_feature_inheritance_mode\c_font_feature_inheritance_fontonly
+ \edef\lastfontidentifier{#identifier}%
+ \let\v_font_size_relative\v_font_rscale_default
+ \let\v_font_size_absolute\fontbody
+ \font_helpers_low_level_define{#2}\v_font_identifier_basic
+ \csname\v_font_identifier_basic\endcsname
+ \setfalse\c_font_auto_size
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \let\v_font_identifier_basic\v_font_identifier_basic_saved}
+
+\unexpanded\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}%
+ \expandafter\font_helpers_trigger_reuse
+ \else
+ % \writestatus{fonts}{trigger: defining \v_font_identifier_class}%
+ \expandafter\font_helpers_trigger_define
+ \fi}
+
+\def\font_helpers_trigger_define#relative#absolute#specification%
+ {\def\v_font_size_relative{#relative}%
+ \def\v_font_size_absolute{#absolute}%
+ \font_helpers_low_level_define{#specification}\v_font_identifier_class
+ \csname\v_font_identifier_class\endcsname
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics \else
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi
+ \let\v_font_identifier_class\v_font_identifier_class_saved}
+
+\def\font_helpers_trigger_reuse#relative#absolute#specification%
+ {\csname\v_font_identifier_class\endcsname
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics \else
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi
+ \let\v_font_identifier_class\v_font_identifier_class_saved}
+
+%D \macros
+%D {currentfontbodyscale}
+%D
+%D Sometimes we need to have access to the font scale
+%D including the \type{a}||\type{d} sizes. The next macro
+%D returns the current scaling factor. Take a look at
+%D \type {cont-log.tex} for an example of its use.
+
+\installcorenamespace{fontenvironments}
+
+% \def\currentfontbodysize
+% {\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
+% \csname\??fontenvironments\s!default\somefontsize\endcsname
+% \else
+% \somefontsize
+% \fi}
+%
+% \def\currentfontbodyscale
+% {\csname\??fontenvironments\s!default
+% \ifcsname\??fontenvironments\s!default\fontsize\endcsname \fontsize \else
+% \ifcsname\??fontenvironments\s!default\s!text \endcsname \s!text \fi\fi
+% \endcsname}
+
+\def\currentfontbodysize % gets number (the normal sa 1 etc)
+ {\ifcsname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+ \csname\??fontenvironments\fontclass\s!default\somefontsize\endcsname
+ \else\ifcsname\??fontenvironments\s!default\somefontsize\endcsname
+ \csname\??fontenvironments\s!default\somefontsize\endcsname
+ \else
+ \somefontsize
+ \fi\fi}
+
+\def\currentfontbodyscale % gets character (x xx a etc)
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\s!default\fontsize\endcsname\fontclass\s!default\fontsize\else
+ \ifcsname\??fontenvironments \s!default\fontsize\endcsname \s!default\fontsize\else
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \else
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else
+ \s!default \fi\fi\fi\fi
+ \endcsname}
+
+\def\currentfontscale % used in default definition
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\s!default\xfontsize\endcsname\fontclass\s!default\fontsize\else
+ \ifcsname\??fontenvironments \s!default\xfontsize\endcsname \s!default\fontsize\else
+ \ifcsname\??fontenvironments\fontclass\s!default\s!text \endcsname\fontclass\s!default\s!text \else
+ \ifcsname\??fontenvironments \s!default\s!text \endcsname \s!default\s!text \else
+ \s!default \fi\fi\fi\fi
+ \endcsname}
+
+\setvalue{\??fontenvironments\s!default}{1}
+
+%D In the following macros we use \type{\currentxfontsize} to
+%D hold the current x||size of the font. This enables us to
+%D support for instance \type{\sl} inside a \type{\tx} switch.
+
+\newconstant\currentxfontsize
+
+\def\xfontsize{\ifcase\currentxfontsize\fontsize\or\s!x\else\s!xx\fi}
+
+%D Now we enter the area of font switching. The switching
+%D mechanism has to take care of several situations, like:
+%D
+%D \startitemize[packed]
+%D \item changing the overal document fonts (including margins,
+%D headers and footers)
+%D \item changing local fonts (only the running text)
+%D \item smaller and even more smaller alternatives (super-
+%D and subscripts)
+%D \stopitemize
+%D
+%D \TEX\ offers a powerfull family mechanism for super- and
+%D subscripts in math mode. In text mode however, we don't use
+%D families for the smaller alternatives, and therefore have
+%D to take care of it otherwise.
+
+%D \macros
+%D {definebodyfontenvironment,setupbodyfontenvironment}
+%D
+%D The relationship between the several sizes of a font, is
+%D defined by:
+%D
+%D \showsetup{definebodyfontenvironment}
+%D
+%D Later on we will see how these parameters are used, so for
+%D the moment we stick with an example:
+%D
+%D \starttyping
+%D \definebodyfontenvironment
+%D [12pt]
+%D [ text=12pt,
+%D script=9pt,
+%D scriptscript=7pt,
+%D x=10pt,
+%D xx=8pt,
+%D big=12pt,
+%D small=10pt]
+%D \stoptyping
+%D
+%D The first argument specifies the bodyfont size to which the
+%D settings apply. All second parameters are specified in
+%D dimensions and tell us more about related sizes.
+%D
+%D Afterwards, one can change values with
+%D
+%D \showsetup{setupbodyfontenvironment}
+%D
+%D When instead of a size the keyword \type{unknown} is
+%D passed, fractions (relations) are used instead of fixed
+%D sizes.
+
+%D {\bf Remark:} We need to cover the following cases, otherwise users can
+%D get confused:
+%D
+%D \starttyping
+%D \setupbodyfont[23pt]
+%D
+%D \definebodyfontenvironment[23pt]
+%D \setupbodyfont[23pt]
+%D
+%D \definebodyfontenvironment[23pt]
+%D \definebodyfont[23pt][rm,ss,tt][default]
+%D \setupbodyfont[23pt]
+%D \stoptyping
+%D
+%D Beware: while some font defs can be global, the bodyfont
+%D environment checks local. This means that multiple local
+%D checks resulting in definitions are not that efficient.
+%D So, apart from an occasional switch, one should define an
+%D environment at the outer level.
+
+% \definebodyfontenvironment[33pt]
+% \definebodyfontenvironment[dejavu][default][1=.5]
+% \definebodyfontenvironment[dejavu][default][x=1.2]
+% \definebodyfontenvironment[dejavu][default][a=5]
+% \definebodyfontenvironment[dejavu][33pt][x=100pt]
+
+% the lookup order is:
+%
+% [class] [dimension] [parameters]
+% [class] [default] [parameters] % factors
+% [dimension] [parameters]
+% [default] [parameters] % factors
+%
+% with defaults providing factors
+
+% todo: class:size
+% todo: make assignments global
+
+\letvalue\??fontenvironments\empty % so we default to empty
+
+\def\bodyfontvariable#parameter%
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname\fontclass\normalizedbodyfontsize#parameter\else
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\else
+ \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname \normalizedbodyfontsize#parameter\else
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi\fi\fi\fi
+ \endcsname}
+
+\def\bodyfontsizevariable#size#parameter%
+ {\csname\??fontenvironments
+ \ifcsname\??fontenvironments\fontclass#size#parameter\endcsname\fontclass#size#parameter\else
+ \ifcsname\??fontenvironments\fontclass #parameter\endcsname\fontclass #parameter\else
+ \ifcsname\??fontenvironments #size#parameter\endcsname #size#parameter\else
+ \ifcsname\??fontenvironments\s!default #parameter\endcsname\s!default #parameter\fi\fi\fi\fi
+ \endcsname}
+
+\def\bodyfontinterlinespace{\bodyfontvariable\c!interlinespace} % used elsewhere
+
+\def\bodyfontdimension#class#size#parameter#body%
+ {\the\dimexpr
+ \ifcsname\??fontenvironments #class#size#parameter\endcsname
+ \csname\??fontenvironments #class#size#parameter\endcsname \else
+ \ifcsname\??fontenvironments#class\s!default#parameter\endcsname
+ \csname\??fontenvironments#class\s!default#parameter\endcsname\dimexpr#body\relax\else % factor
+ \ifcsname\??fontenvironments #size#parameter\endcsname
+ \csname\??fontenvironments #size#parameter\endcsname \else
+ \csname\??fontenvironments \s!default#parameter\endcsname\dimexpr#body\relax\fi\fi\fi % factor
+ \relax}
+
+\unexpanded\def\definebodyfontenvironment
+ {\dotripleempty\font_basics_define_body_font_environment}
+
+\let\setupbodyfontenvironment\definebodyfontenvironment
+
+\installcorenamespace{fontenvironmentknown}
+
+\let\bodyfontenvironmentlist\empty % used in font-run (might change)
+
+\def\font_helpers_register_environment#class#body%
+ {\expandafter\let\csname\??fontenvironmentknown#class#body\endcsname\empty}
+
+\newmacro\m_font_body
+\newmacro\m_font_body_normalized
+
+\def\font_basics_define_body_font_environment
+ {\ifthirdargument
+ \singleexpandafter\font_basics_define_body_font_environment_class
+ \else\ifsecondargument
+ \doubleexpandafter\font_basics_define_body_font_environment_empty
+ \else
+ \doubleexpandafter\font_basics_define_body_font_environment_unset
+ \fi\fi}
+
+%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\font_basics_define_body_font_environment_class[#class][#body][#settings]%
+ {\edef\m_font_body{#body}%
+ \ifx\m_font_body\s!default
+ % these are the last resort within a class
+ \getrawparameters[\??fontenvironments#class\s!default][#settings]%
+ \else
+ \normalizebodyfontsize\m_font_body_normalized\m_font_body
+ \font_basics_define_body_font_environment_size[#class][\m_font_body_normalized][#settings]%
+ \addtocommalist\m_font_body_normalized\bodyfontenvironmentlist
+ \fi}
+
+%D The empty case uses the same code but needs to ignore the current class
+%D settings (just to be sure, as it's not really needed).
+
+\def\font_basics_define_body_font_environment_empty[#body][#settings][#dummy]%
+ {\pushmacro\fontclass
+ \let\fontclass\empty
+ \font_basics_define_body_font_environment_class[][#body][#settings]%
+ \popmacro\fontclass}
+
+\def\font_basics_define_body_font_environment_unset[#body][#dummya][#dummyb]%
+ {\pushmacro\fontclass
+ \let\fontclass\empty
+ \font_basics_define_body_font_environment_class[][#body][]%
+ \popmacro\fontclass}
+
+%D We don't check too soon as we can refer to later definitions.
+
+\newconditional\c_font_defining_environment_state % controls messages
+
+\def\font_basics_define_body_font_environment_size[#class][#normalizedbody][#settings]% normalized body
+ {\getrawparameters[\??fontenvironments#class#normalizedbody][#settings]%
+ \ifcsname\??fontenvironmentknown#class#normalizedbody\endcsname
+ % environment and size already defined
+ \else\ifproductionrun
+ \pushmacro\fontclass
+ \edef\fontclass{#class}%
+ \font_helpers_register_environment{#class}{#normalizedbody}%
+ \settrue\c_font_defining_environment_state
+ \font_helpers_define_unknown_font{#normalizedbody}% current class
+ \setfalse\c_font_defining_environment_state
+ \popmacro\fontclass
+ \fi\fi
+ \font_helpers_register_fontbody{#normalizedbody}}
+
+%D Checking
+
+\def\font_helpers_check_bodyfont_environment#normalizedbody#body%
+ {\ifcsname\??fontenvironmentknown\fontclass#normalizedbody\endcsname
+ % already defined
+ \else
+ \font_helpers_check_bodyfont_environment_indeed{#normalizedbody}{#body}%
+ \fi}
+
+\def\font_helpers_check_bodyfont_environment_indeed#normalizedbody#body%
+ {\font_helpers_register_environment\fontclass{#normalizedbody}%
+ \ifcsname\??fontbodyknown#normalizedbody\endcsname
+ \else
+ \font_helpers_define_unknown_font{#normalizedbody}%
+ \fi}
+
+%D We default all parameters to the main bodyfont size, so the next
+%D setup is valid too:
+%D
+%D \starttyping
+%D \definebodyfontenvironment[24pt]
+%D \stoptyping
+%D
+%D All parameters can be redefined when needed, so one doesnot have to
+%D stick to the default ones.
+
+%D \macros
+%D {definebodyfont}
+%D
+%D The next step in defining a bodyfont involves the actual font
+%D files, which can be recognized by their extension
+%D \type{tfm}. Installing those file is often beyond the
+%D scope of the user and up to the system administrator.
+%D
+%D \showsetup{definebodyfont}
+%D
+%D This commands takes three arguments: a (series of) bodyfont
+%D size(s), the style group to which the definitions belong,
+%D and an alternative, as specified by the \TEX\ (math) families,
+%D extended with~a, b~\unknown.
+%D
+%D We show two examples, that show all the alternative
+%D scaling options. The \type{\tfa} alternatives can be
+%D extended with \type{\bfa}, \type{\slb}, etc. or even
+%D \type{e} and higher alternatives. The magic scaled
+%D values are derived from plain \TEX's \type {\magstep}:
+%D
+%D \starttyping
+%D \definebodyfont [12pt] [rm]
+%D [tf=cmr12,
+%D bf=cmbx12,
+%D it=cmti12,
+%D sl=cmsl12,
+%D bi=cmbxti10 at 12pt,
+%D bs=cmbxsl10 at 12pt,
+%D tfa=cmr12 scaled 1.200,
+%D tfb=cmr12 scaled 1.440,
+%D tfc=cmr12 scaled 1.728,
+%D tfd=cmr12 scaled 2.074,
+%D sc=cmcsc10 at 12pt]
+%D
+%D \definebodyfont [12pt,11pt,10pt,9pt,8pt] [rm]
+%D [tf=lbr sa 1,
+%D bf=lbd sa 1,
+%D it=lbi sa 1,
+%D sl=lbsl sa 1,
+%D bi=lbdi sa 1,
+%D bs=lbdi sa 1,
+%D tfa=lbr sa 1.200,
+%D tfb=lbr sa 1.440,
+%D tfc=lbr sa 1.728,
+%D tfd=lbr sa 2.074,
+%D sc=lbr sa 0.833]
+%D \stoptyping
+%D
+%D The second example shows that we can define more sizes at
+%D once. The main difference between these examples is that the
+%D Computer Modern Roman come in many design sizes. This means
+%D that there we cannot define them in bulk using \type{sa}.
+%D Instead of \type{rm} (roman) one can define \type{ss} (sans
+%D serif), \type{tt} (teletype), \type{hw} (hand written),
+%D \type{cg} (calygraphic) and whatever styles.
+%D
+%D The first argument may be a comma separated list. This,
+%D combined with specifications using \type{sa} can save a lot
+%D of typing. Although all arguments should be specified, we
+%D treat the second argument as optional.
+%D
+%D Defining a bodyfont involves two actions: defining the
+%D specific style related alternatives, like \type{\rma},
+%D \type{\bfa} and \type{\rmsla}, and storing the definitions
+%D of their bodyfont size related fonts. The first step is
+%D bodyfont independant but executed every time. This permits
+%D user definitions like \type{\tfw} or \type{\bfq} for real
+%D large alternatives.
+
+%D If we move design size info to the lfg file (after all only lm
+%D has design sizes) we can get rid of much code .. 2012 or so.
+
+\installcorenamespace{fontdefinitions}
+
+% [class] [name] [rm,ss] [settings]
+% [class] [10pt,11pt] [rm,ss] [settings]
+% [class] [10pt,11pt] [rm,ss] [name]
+
+% [class] [name] [settings] == [name] [rm] [settings]
+% [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
+ \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%
+ {\pushmacro\fontclass
+ \doifelse{#4}\s!default
+ {\let\fontclass\empty}
+ {\def\fontclass{#4}}%
+ \definebodyfont[#1][#2][#3]%
+ \popmacro\fontclass}
+
+\def\font_basics_define_body_font_class_known
+ {\ifthirdargument
+ \singleexpandafter\font_basics_define_body_font_a
+ \else\ifsecondargument
+ \doubleexpandafter\font_basics_define_body_font_b
+ \else
+ \doubleexpandafter\font_basics_define_body_font_c
+ \fi\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[bwhatever][\s!rm][]}
+
+\unexpanded\def\font_basics_define_body_font_a[#whatever]%
+ {\doifnumberelse{#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]%
+ {\doifassignmentelse{#specification}
+ \font_basics_define_body_font_body_assignment
+ \font_basics_define_body_font_body_identifier
+ [#body][#style][#specification]}%
+
+\unexpanded\def\font_basics_define_body_font_name[#name][#style][#specification]%
+ {\doifassignmentelse{#specification}
+ \font_basics_define_body_font_name_assignment
+ \font_basics_define_body_font_name_identifier
+ [#name][#style][#specification]}%
+
+\unexpanded\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%
+ {\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%
+ {\edef\m_font_asked_style{#style}%
+ \processcommalist[#assignments]\font_basics_define_body_font_defs}
+
+\unexpanded\def\font_basics_define_body_font_defs
+ {\ifx\fontclass\empty
+ \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%
+ {\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%
+ {\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%
+ {\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
+ \else
+ \expandafter\font_basics_define_body_font_yes_xx
+ \fi[#assignment]}
+
+\unexpanded\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
+ \else
+ \expandafter\font_basics_define_body_font_nop_xx
+ \fi[#assignment]}
+
+\let\font_basics_define_body_font_defs_yes\font_basics_define_body_font_defs_yes_normal
+\let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_normal
+
+\appendtoks
+ \let\font_basics_define_body_font_defs_yes\font_basics_define_body_font_defs_yes_traced
+ \let\font_basics_define_body_font_defs_nop\font_basics_define_body_font_defs_nop_traced
+\to \t_font_tracers_definitions
+
+% We split into two characters (first part of spec) and the rest: the first two are the style and
+% the rest is a size, although in practice one will seldom define the 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
+% {\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\endcsname\undefined
+% \unexpanded\expandafter\normaledef\csname\??fontinstanceready\m_font_asked_body-\m_font_asked_style-#one#two-#rest\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_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
+ {\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
+ {\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
+ {\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}}}%
+ }
+
+% \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_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
+% \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest\endcsname\undefined
+% \unexpanded\expandafter\normalxdef\csname\??fontinstanceready\fontclass-\m_font_asked_body-\m_font_asked_style-#one#two-#rest\endcsname
+% {\font_helpers_trigger{\m_font_asked_body-\m_font_asked_style-#one#two#rest}{\number\p_font_rscale}{\m_font_asked_body}{\normalunexpanded{#value}}}%
+% }
+
+\unexpanded\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
+ \global\expandafter\let\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
+ {\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}}}%
+ \global\expandafter\let\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
+ {\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}}}%
+ \global\expandafter\let\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
+ {\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}}}%
+ }
+
+% \writestatus{fonts}{define \m_asked_style\space yes: {\expandafter\meaning\csname\fontclass\m_font_asked_body\m_font_asked_style#one#two#rest\endcsname}
+
+%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
+ {%\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
+ {\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
+ {%\ifcsname\s!mm\endcsname\else\font_basics_check_fontname_combination\s!mm{#one#two}{#rest}\fi
+ \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-1\endcsname\undefined
+ % \global\expandafter\let\csname\??fontinstanceclass\fontclass-\m_font_asked_body-\s!mm-#one#two#rest-2\endcsname\undefined
+ % \global\expandafter\let\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
+ {\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]%
+ {\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%
+ {\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%
+ {\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]%
+ {\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%
+ {%\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]%
+ {\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%
+ {%\writestatus\m!fonts{[#name:#style] => [##identifier:#style]}%
+ \ifcsname\csname\??fontdefinitions#name:#style\endcsname
+ \expandafter\let\csname\??fontdefinitions#name:#style\expandafter\endcsname\csname\??fontdefinitions#identifier:#style\endcsname
+ \else
+ \expandafter\def\csname\??fontdefinitions#name:#style\endcsname{\csname\??fontdefinitions#identifier:#style\endcsname}%
+ \fi}
+
+%D The unknown:
+
+\newconditional\c_font_defining_unknown
+\newconditional\c_font_defining_state
+
+\unexpanded\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}}%
+ \ifconditional\c_font_defining_state
+ \setfalse\c_font_defining_state
+ \font_helpers_process_style_list{\font_helpers_define_unknown_check_definitions{#body}}%
+ \ifconditional\c_font_defining_state
+ \ifconditional\c_font_defining_environment_state\else
+ \showmessage\m!fonts{14}{#body}% main
+ \fi
+ \setfalse\c_font_defining_state
+ \font_helpers_register_fontbody{#body}%
+ % needed ?
+ \ifconditional\c_font_defining_unknown
+ \else
+ \settrue\c_font_defining_unknown
+ \font_helpers_process_relative_size_list{\font_helpers_define_unknown_check_relatives{#body}}%
+ \setfalse\c_font_defining_unknown
+ \fi
+ \fi
+ \fi}
+
+\def\font_helpers_define_unknown_check_sizes#body#relativesize%
+ {\ifcsname\??fontenvironments\s!default#relativesize\endcsname % fontclass ?
+ \expandafter\normalizebodyfontsize\csname\??fontenvironments#body#relativesize\endcsname{\csname\??fontenvironments\s!default#relativesize\endcsname\dimexpr#body\relax}%
+ \settrue\c_font_defining_state
+ \fi}
+
+\def\font_helpers_define_unknown_check_definitions#body#style%
+ {\ifcsname\??fontdefinitions\s!default:#style\endcsname
+ \edef\m_font_asked_body{#body}%
+ \edef\m_font_asked_style{#style}%
+ \csname\??fontdefinitions\s!default:#style\endcsname % {#body}{#style}%
+ \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%
+ {\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]}%
+ \fi
+ \processcommalist[#assignments]\font_basics_define_body_font_defs
+ \let\p_font_rscale\v_font_rscale_default}
+
+%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%
+ {\ifcsname\??fontbodyknown#body\endcsname \else
+ % we need to check the relative sizes for this body
+ \font_helpers_define_unknown_font{#body}%
+ \fi%
+ \ifcsname\??fontbodyknown#body\endcsname % always true now
+ \font_basics_complete_switch{#body}%
+ \localbodyfontsize#body\relax
+ \normalizebodyfontsize\normalizedbodyfontsize\localbodyfontsize
+ \font_helpers_check_bodyfont_environment\normalizedbodyfontsize\normalizedbodyfontsize % !!
+ \else
+ \showmessage\m!fonts4{#body}%
+ \fi}
+
+\unexpanded\def\font_basics_switch_style#style%
+ {\ifcsname\??fontstyle#style\endcsname
+ \csname\??fontstyle#style\endcsname
+ \edef\fontstyle{#style}%
+ \ifmmode\mr\fi % in order to be compatible with \rm in math mode
+ % \the\everybodyfont % cleaner, in setting size as well as style
+ \else
+ \showmessage\m!fonts5{#style}%
+ \fi}
+
+%D Here comes the main font switching macros. These macros
+%D handle changes in size as well as returning to the global
+%D bodyfont size.
+
+\ifdefined\font_preloads_at_definition \else \let\font_preloads_at_definition\relax \fi
+
+\def\font_helpers_set_font#method#specification%
+ {\edef\m_font_specification{#specification}%
+ \ifx\m_font_specification\empty \else
+ \ifx\m_font_specification\v!global % we can have all kind of presets
+ \restoreglobalbodyfont
+ \else
+ \processcommacommand[\m_font_specification]{\font_helpers_set_font_check_size}%
+ \processcommacommand[\m_font_specification]{\font_helpers_set_font_set_font{#method}}%
+ \ifproductionrun
+ \font_preloads_at_definition
+ \font_basics_switch_points\normalizedbodyfontsize
+ \font_basics_switch_style\fontstyle
+ \ifx\defaultfontclass\empty
+ \let\defaultfontclass\fontclass
+ \fi
+ \fi
+ \fi
+ \currentxfontsize\zerocount
+ \fi}
+
+\def\font_helpers_set_font_check_size#option%
+ {\doifnumberelse{#option}{\font_helpers_check_bodyfont_environment{#option}{#option}}\donothing}
+
+\def\font_helpers_set_font_set_font#method#option% method=1: set, method=2: switch
+ {\doifsomething{#option}{\font_helpers_set_font_set_font_option{#method}{#option}}}
+
+\def\font_helpers_set_font_set_font_option#method#option%
+ {\doifnumberelse{#option}%
+ \font_helpers_set_font_set_font_option_body
+ \font_helpers_set_font_set_font_option_keyword
+ {#method}{#option}{#option}}
+
+\newmacro\m_font_keyword
+
+\unexpanded\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{\bodyfontvariable\m_font_keyword}%
+ \normalexpanded{\font_helpers_set_font_set_font_option_body{#method}{\m_font_step}{#message}}%
+ \else\ifx\m_font_keyword\v!reset
+ \let\fontstyle\empty % new 31/7/2006
+ \let\fontsize \empty
+ \else\ifcsname\??fontstyle\m_font_keyword\endcsname
+ \let\fontstyle\m_font_keyword
+ \else
+ \setcurrentfontclass\m_font_keyword
+ \ifcase#method\relax
+ \let\globalfontclass\globalfontclass
+ \else
+ \let\globalfontclass\fontclass
+ \fi
+ \font_helpers_set_fontstyle_of_fontclass
+ \fi\fi\fi}
+
+\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%
+ {\normalizebodyfontsize\normalizedsetfont{#body}% redundant for some calls
+ \ifcsname\??fontbodyknown\normalizedsetfont\endcsname \else
+ \font_helpers_define_unknown_font{#body}%
+ \fi
+ \ifcsname\??fontbodyknown\normalizedsetfont\endcsname
+ \localbodyfontsize\normalizedsetfont
+ \let\normalizedbodyfontsize\normalizedsetfont
+ \else
+ \showmessage\m!fonts4{#message}%
+ %\font_helpers_set_font_set_font_option_body_fallbacks{#method}{#body}%
+ \fi}
+
+% we need to check the fontclass
+
+\def\registerfontclass#class%
+ {\letgvalue{\??fontclassyes#class}\v!yes} % global ?
+
+\def\setcurrentfontclass#class%
+ {\ifcsname\??fontclassyes#class\endcsname
+ \edef\fontclass{#class}%
+ \else\ifcsname\??fontclassnop#class\endcsname
+ % already tried
+ \else % too messy: \ifcase\currentgrouplevel % (unpredictable)
+ \trycurrentfontclass{#class}%
+ \fi\fi} % \fi}
+
+\ifdefined\trycurrentfontclass \else
+
+ \unexpanded\def\trycurrentfontclass#typeface%
+ {\letvalueempty{\??fontclassnop#typeface}}
+
+\fi
+
+\let\defaultfontstyle \s!rm
+\let\defaultfontalternative\s!tf
+\let\defaultfontsize \empty
+
+%D So far for synchronisation. (We can inline the following macros.)
+
+\unexpanded\def\setcurrentfont#body#style#alternative#size% not used
+ {\edef\fontbody {#body}%
+ \edef\fontstyle {#style}%
+ \edef\fontalternative{#alternative}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\setcurrentfontbody#body% % not used
+ {\edef\fontbody{#body}%
+ \font_helpers_synchronize_font}
+
+% For Taco: optional fall backs:
+
+\ifdefined\font_typescripts_inherit_check \else
+ \let\font_typescripts_inherit_check\gobbleoneargument % implemented in type-ini
+\fi
+
+\unexpanded\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%
+ {\edef\fontface{#xsize}%
+ \edef\fontalternative{#alternative}%
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_alternative#alternative%
+ {\edef\fontalternative{#alternative}%
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_size#size%
+ {\edef\fontsize{#size}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}
+
+\unexpanded\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
+ {\edef\fontstyle{#style}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_set_current_font_alternative_size#alternative#size% \sla
+ {\edef\fontalternative{#alternative}%
+ \edef\fontsize {#size}%
+ \font_helpers_check_big_math_synchronization
+ \font_helpers_synchronize_font}
+
+\unexpanded\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
+ \font_helpers_synchronize_font}
+
+\unexpanded\def\font_helpers_synchronize_font % we can have dups i.e. no need to let fontstrategy
+ {\ifx\fontclass\empty
+ \applyfontstrategies
+ \else
+ \applyfontclassstrategies
+ \fi
+ \setfalse\c_font_auto_size
+ \ifskipfontcharacteristics
+ \setfontcharacteristics
+ \the\everyfontswitch
+ \fi}
+
+%D This is the resolver for special cases (sizes) and in practice it is not called that often
+%D so further optimization makes no sense.
+
+\def\font_helpers_check_strategy_class_a % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_class_b
+ \fi}
+
+\def\font_helpers_check_strategy_class_b % --- --- --- def % pt tt bf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_class_c
+ \fi}
+
+\def\font_helpers_check_strategy_class_c % --- --- def --- % pt tt tf a
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_class_d
+ \fi}
+
+\def\font_helpers_check_strategy_class_d % --- --- def def % pt tt tf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \csname\??fontinstanceready\fontclass-\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_class_e
+ \fi}
+
+\def\font_helpers_check_strategy_class_e % --- def def def % pt rm tf
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \csname\??fontinstanceready\fontclass-\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_class_f
+ % \expandafter\font_helpers_check_strategy_a
+ \fi}
+
+\def\font_helpers_check_strategy_class_f % def def def def % rm tf
+ {\ifcsname\??fontinstanceready\fontclass-\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \csname\??fontinstanceready\fontclass-\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_a
+ \fi}
+
+% no class
+
+\def\font_helpers_check_strategy_a % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \csname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\fontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_b
+ \fi}
+
+\def\font_helpers_check_strategy_b % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \csname\??fontinstanceready\fontbody-\fontstyle-\fontalternative-\defaultfontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_c
+ \fi}
+
+\def\font_helpers_check_strategy_c % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \csname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\fontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_d
+ \fi}
+
+\def\font_helpers_check_strategy_d % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \csname\??fontinstanceready\fontbody-\fontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_e
+ \fi}
+
+\def\font_helpers_check_strategy_e % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \setfalse\c_font_auto_size
+ \csname\??fontinstanceready\fontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \else
+ \expandafter\font_helpers_check_strategy_f
+ \fi}
+
+\def\font_helpers_check_strategy_f % --- --- --- --- % pt tt bf a
+ {\ifcsname\??fontinstanceready\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \settrue\c_font_auto_size
+ \csname\??fontinstanceready\defaultfontbody-\defaultfontstyle-\defaultfontalternative-\defaultfontsize-\fontface\endcsname
+ \fi}
+
+\let\applyfontstrategies \font_helpers_check_strategy_a
+\let\applyfontclassstrategies\font_helpers_check_strategy_class_a
+
+%D Let's synchronize:
+
+\newconditional\c_font_synchronize \settrue\c_font_synchronize
+
+\prependtoks
+ \ifconditional\c_font_synchronize
+ \font_helpers_synchronize_math
+ \font_helpers_synchronize_font % problem: syncs last font
+ \fi
+\to \everybodyfont
+
+%D Setting the normal sizes as well as the x and xx smaller
+%D sizes is accomplished by the next set of macros. When in
+%D math mode, the commands \type{\tx} and \type{\txx} are
+%D just a switch to the script and double script styles, but
+%D in text mode the values defined by the bodyfontenvironment are
+%D used. Here we also set \type{\currentxfontsize}.
+
+\def\font_helpers_set_current_font_xxx_alternative#alternative#xsize#scriptstyle%
+ {\ifmmode
+ #scriptstyle%
+ \else
+ \font_helpers_set_current_xsize_alternative{#xsize}{#alternative}%
+ \fi}
+
+\def\font_helpers_set_current_font_x_alternative#alternative%
+ {\font_helpers_set_current_font_xxx_alternative{#alternative}{4}\scriptstyle
+ \currentxfontsize\plusone
+ \let\tx\txx}
+
+\def\font_helpers_set_current_font_xx_alternative#alternative%
+ {\font_helpers_set_current_font_xxx_alternative{#alternative}{5}\scriptscriptstyle
+ \currentxfontsize\plustwo
+ \let\tx\empty
+ \let\txx\empty}
+
+\def\font_helpers_reset_x_fontsize
+ {\ifcase\currentxfontsize\else
+ \currentxfontsize\zerocount
+ \let\tx\normaltx
+ \let\txx\normaltxx
+ \fi}
+
+\def\font_helpers_check_nested_x_fontsize % option
+% {\ifcase\currentxfontsize\else\ifx\fontsize\empty\else
+% \currentxfontsize\zerocount
+% \let\fontsize\empty
+% \let\tx\normaltx
+% \let\txx\normaltxx
+% \fi\fi}
+ {}
+
+\def\font_helpers_set_current_font_x_alternative#alternative%
+ {\font_helpers_check_nested_x_fontsize
+ \font_helpers_set_current_font_xxx_alternative{#alternative}{4}\scriptstyle
+ \currentxfontsize\plusone
+ \let\tx\txx}
+
+\def\font_helpers_set_current_font_xx_alternative#alternative%
+ {\font_helpers_check_nested_x_fontsize
+ \font_helpers_set_current_font_xxx_alternative{#alternative}{5}\scriptscriptstyle
+ \currentxfontsize\plustwo
+ \let\tx\empty
+ \let\txx\empty}
+
+% This alterative is not really needed, but for old time's sake
+% we keep it there. We can speed it up when needed.
+
+\def\font_helpers_set_current_font_x_style_alternative #alternative{\csname#alternative\endcsname\tx}
+\def\font_helpers_set_current_font_xx_style_alternative#alternative{\csname#alternative\endcsname\txx}
+
+%D These macros also show us that when we call for \type{\tx},
+%D this macro is redefined to be \type{\txx}. Therefore calls
+%D like:
+%D
+%D \startbuffer
+%D {small \tx is \tx beautiful}
+%D {small \tx is \txx beautiful}
+%D {small \txx is \tx beautiful}
+%D {small \txx is \txx beautiful}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D result in:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D Setting the main size involves the style list and therefore
+%D takes a bit more time. Keep in mind that the fontsize is
+%D represented by a character or empty.
+
+\unexpanded\def\tx {\font_helpers_set_current_font_x_alternative \fontalternative}
+\unexpanded\def\txx{\font_helpers_set_current_font_xx_alternative\fontalternative}
+
+\let\normaltx \tx
+\let\normaltxx\txx
+
+%D When asking for a complete font switch, for instance from 10
+%D to 12~points, the next macro does the job. First we
+%D normalize the size, next we define the current range of
+%D text, script and scriptscript sizes, then we set the text
+%D fonts and the math families and finally we activate the
+%D default typeface and also set the font specific parameters
+%D assigned to \type{\everybodyfont}
+
+\def\textface {\currentbodyfontdimension\s!text }
+\def\scriptface {\currentbodyfontdimension\s!script }
+\def\scriptscriptface{\currentbodyfontdimension\s!scriptscript}
+\def\xtextface {\currentbodyfontdimension\s!x }
+\def\xxtextface {\currentbodyfontdimension\s!xx }
+
+% \unexpanded\def\font_basics_complete_switch#size%
+% {\bodyfontsize#size\relax
+% \normalizebodyfontsize\normalizedbodyfontsize\bodyfontsize
+% \edef\textface {\currentbodyfontdimension\s!text }%
+% \edef\scriptface {\currentbodyfontdimension\s!script }%
+% \edef\scriptscriptface{\currentbodyfontdimension\s!scriptscript}}%
+
+\installcorenamespace{fontbodyfaces}
+
+\unexpanded\def\font_basics_complete_switch#size%
+ {\bodyfontsize#size\relax
+ \normalizebodyfontsize\normalizedbodyfontsize\bodyfontsize
+ \expandafter\let\expandafter\font_basics_set_faces\csname\??fontbodyfaces\fontbody\endcsname
+ \ifx\font_basics_set_faces\relax
+ \font_basics_set_faces_preset
+ \fi
+ \font_basics_set_faces}
+
+\def\font_basics_set_faces_preset
+ {\edef\font_basics_set_faces{% 0.2 sec on 10K \tfa
+ \noexpand\edef\noexpand\textface {\currentbodyfontdimension\s!text }%
+ \noexpand\edef\noexpand\scriptface {\currentbodyfontdimension\s!script }%
+ \noexpand\edef\noexpand\scriptscriptface{\currentbodyfontdimension\s!scriptscript}%
+ \noexpand\edef\noexpand\xtextface {\currentbodyfontdimension\s!x }%
+ \noexpand\edef\noexpand\xxtextface {\currentbodyfontdimension\s!xx }%
+ }%
+ \global\expandafter\let\csname\??fontbodyfaces\fontbody\endcsname\font_basics_set_faces}
+
+\def\currentbodyfontdimension#parameter%
+ {\the\dimexpr
+ \ifcsname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname
+ \csname\??fontenvironments\fontclass\normalizedbodyfontsize#parameter\endcsname \else
+ \ifcsname\??fontenvironments\fontclass\s!default #parameter\endcsname
+ \csname\??fontenvironments\fontclass\s!default #parameter\endcsname
+ \dimexpr\normalizedbodyfontsize\relax \else % factor
+ \ifcsname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname
+ \csname\??fontenvironments \normalizedbodyfontsize#parameter\endcsname \else
+ \csname\??fontenvironments \s!default #parameter\endcsname
+ \dimexpr\normalizedbodyfontsize\relax \fi\fi\fi % factor
+ \relax}
+
+%D \macros
+%D {setupbodyfont,switchtobodyfont}
+%D
+%D The next two macros are user ones. With \type{\setupbodyfont}
+%D one can set the document bodyfont size, font family, style
+%D and/or options defined in files, for example:
+%D
+%D \starttyping
+%D \setupbodyfont[modern,12pt,roman]
+%D \stoptyping
+%D
+%D This command affects the document as a whole: text, headers
+%D and footers. The second macro however affects only the text:
+%D
+%D \starttyping
+%D \switchtobodyfont[10pt]
+%D \stoptyping
+%D
+%D So we've got:
+%D
+%D \showsetup{setupbodyfont}
+%D \showsetup{switchtobodyfont}
+%D
+%D Both macros look alike. The second one also has to take
+%D all kind of keywords into account.
+
+\ifx\saveinterlinespace \undefined \let\saveinterlinespace \relax \fi
+\ifx\restoreinterlinespace\undefined \let\restoreinterlinespace\relax \fi
+
+% \newtoks \everysetupbodyfont
+% \newtoks \everyswitchtobodyfont
+
+\unexpanded\def\setupbodyfont
+ {\doifnextoptionalelse\font_basics_setupbodyfont_yes\font_basics_setupbodyfont_nop}
+
+\def\font_basics_setupbodyfont_nop
+ {\restoreglobalbodyfont
+ \saveinterlinespace}
+
+\def\font_basics_setupbodyfont_yes[#specification]%
+ {\doifsomething{#specification}
+ {\font_helpers_set_font\plusone{#specification}%
+ \globalbodyfontsize\localbodyfontsize
+ \normalizebodyfontsize\normalizedglobalbodyfontsize\globalbodyfontsize
+ \let\globalfontstyle\fontstyle
+ \ifproductionrun
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace
+ \fi
+ \the\everysetupbodyfont}}
+
+\unexpanded\def\switchtobodyfont[#specification]%
+ {\doifsomething{#specification}
+ {\edef\m_font_step{\bodyfontvariable{#specification}}%
+ \ifx\m_font_step\empty
+ \font_helpers_set_font\zerocount{#specification}%
+ \else
+ \font_helpers_switch_bodyfont_step % so we have a fast [small] switch
+ \fi
+ \the\everybodyfont
+ \the\everyswitchtobodyfont}}
+
+\def\font_helpers_switch_bodyfont_step
+ {\font_basics_switch_points\m_font_step
+ \font_basics_switch_style \fontstyle}
+
+%D The following alternative is meant for math||to||text
+%D switching and will be optimized.
+
+\unexpanded\def\fastswitchtobodyfont#name%
+ {\ifcsname\??fontenvironments\normalizedbodyfontsize#name\endcsname
+ \edef\futurebodyfontsize{\csname\??fontenvironments\normalizedbodyfontsize#name\endcsname}%
+ \ifcsname\??fontbodyknown\futurebodyfontsize\endcsname
+ \font_basics_complete_switch\futurebodyfontsize
+ \localbodyfontsize\futurebodyfontsize\relax
+ \fi
+ \fi
+ \csname\??fontstyle\fontstyle\endcsname
+ \the\everybodyfont}
+
+%D \starttyping
+%D $\cases{& \ccaron}$ $x=\hbox{\ccaron $x=\hbox{\ccaron}$}$
+%D \stoptyping
+
+%D Handy for manuals:
+
+\unexpanded\def\fontchar#character%
+ {\ctxcommand{fontchar("#character")}}
+
+%D The next auxilliary macro is an alternative to \type
+%D {\fontname}.
+
+\def\purefontname#font{\ctxlua{file.basename("\fontname#font"}} % will be function using id
+
+%D \macros
+%D {switchstyleonly}
+%D
+%D For switching a style but keeping the alternative, there
+%D is:
+%D
+%D \starttyping
+%D {\bf text \switchstyleonly\ss text}
+%D {\bf text \switchstyleonly[ss]text}
+%D {\sl text \switchstyleonly[sansserif]text}
+%D \stoptyping
+
+\unexpanded\def\switchstyleonly
+ {\doifnextoptionalelse\font_basics_switch_style_only_opt\font_basics_switch_style_only_arg}
+
+\def\font_basics_switch_style_only_arg#name% stupid version
+ {\font_helpers_set_current_font_style{\csname\??fontshortstyle\checkedstrippedcsname#name\endcsname}%
+ \the\everybodyfont} % needed ?
+
+\def\font_basics_switch_style_only_opt[#name]% todo : check
+ {\font_helpers_set_current_font_style{\csname\??fontshortstyle#name\endcsname}%
+ \the\everybodyfont} % needed ?
+
+%D \macros
+%D {definebodyfontswitch}
+%D
+%D \PLAIN\ \TEX\ defines some macro's like \type{\tenpoint}
+%D to switch to a specific bodyfontsize. Just for the sake of
+%D compatibility we can define them like:
+%D
+%D \starttyping
+%D \definebodyfontswitch [twelvepoint] [12pt]
+%D \stoptyping
+%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)
+ {\setvalue{#command}{\switchtobodyfont[#specification]}}%
+
+%D \macros
+%D {setsmallbodyfont,setmainbodyfont,setbigbodyfont}
+%D
+%D When we're typesetting at for instance 10pt, we can call for
+%D the \type{small} as well as the \type{big} alternative,
+%D related to this main size, using \type{\switchtobodyfont[small]}.
+%D The three alternatives can be activated by the next three
+%D system calls and are defined by the bodyfontenvironment.
+
+\newmacro\m_font_step
+
+\def\font_helpers_set_bodyfont_step#step%
+ {\edef\m_font_step{\bodyfontvariable{#step}}% not always \cs
+ \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}
+
+\unexpanded\def\setmainbodyfont
+ {\font_basics_switch_points\normalizedbodyfontsize
+ \font_basics_switch_style\fontstyle
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+%D \macros
+%D {restoreglobalbodyfont}
+%D
+%D Users can set whatever font available while typesetting text.
+%D Pagenumbers, footers, headers etc. however must be typeset
+%D in the main bodyfont and style of the document. Returning to
+%D the global state can be done with the next macro:
+%D
+%D This macro has to be called when entering the pagebody
+%D handling routine as well as the footnote insert routine.
+%D Users can access this feature |<|for instance when one wants
+%D to typeset tables and alike in the main bodyfont and style
+%D while the running text is temporary set to a smaller one|>|
+%D by saying \type{\switchtobodyfont[global]}.
+
+\let\globalfontstyle\s!rm
+
+\unexpanded\def\fullrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \currentxfontsize\zerocount
+ \let\fontclass\globalfontclass
+ \font_basics_switch_points\normalizedglobalbodyfontsize
+ \font_basics_switch_style\globalfontstyle
+ \redoconvertfont % just in case a pagebreak occurs
+ \tf
+ \the\everybodyfont
+ \the\everyglobalbodyfont
+ \saveinterlinespace}
+
+\unexpanded\def\partialrestoreglobalbodyfont
+ {\let\fontsize\defaultfontsize
+ \let\fontbody\defaultfontbody
+ \currentxfontsize\zerocount
+ \redoconvertfont
+ \tf
+ \the\everybodyfont % indeed needed
+ \the\everyglobalbodyfont % indeed needed
+ \saveinterlinespace}
+
+\unexpanded\def\restoreglobalbodyfont % ook style etc
+ {\ifx\fontclass\globalfontclass
+ \ifx\fontstyle\globalfontstyle
+ \ifx\normalizedbodyfontsize\normalizedglobalbodyfontsize
+ \partialrestoreglobalbodyfont
+ \else
+ \fullrestoreglobalbodyfont
+ \fi
+ \else
+ \fullrestoreglobalbodyfont
+ \fi
+ \else
+ \fullrestoreglobalbodyfont
+ \fi}
+
+% in case of troubles: \let\restorebodyfont\fullrestoreglobalbodyfont
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-jap.mkii b/Master/texmf-dist/tex/context/base/font-jap.mkii
index 42480df43fa..b8aa3d8368d 100644
--- a/Master/texmf-dist/tex/context/base/font-jap.mkii
+++ b/Master/texmf-dist/tex/context/base/font-jap.mkii
@@ -6,7 +6,7 @@
%D author=Hans Hagen,
%D date=\currentdate,
%D suggestions=Wang Lei,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-lib.mkvi b/Master/texmf-dist/tex/context/base/font-lib.mkvi
new file mode 100644
index 00000000000..d9c04f0a23c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-lib.mkvi
@@ -0,0 +1,94 @@
+%D \module
+%D [ file=font-lib,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Libraries,
+%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 / Libraries}
+
+\unprotect
+
+\registerctxluafile{font-ini}{1.001}
+\registerctxluafile{font-log}{1.001}
+\registerctxluafile{font-con}{1.001}
+\registerctxluafile{font-enc}{1.001}
+%registerctxluafile{font-agl}{1.001} % loaded when needed, saves 100K in format
+\registerctxluafile{font-cid}{1.001} % cid maps
+\registerctxluafile{font-map}{1.001}
+\registerctxluafile{font-syn}{1.001}
+
+\registerctxluafile{font-tfm}{1.001}
+
+\registerctxluafile{font-afm}{1.001}
+
+\registerctxluafile{font-oti}{1.001} % otf initialization
+\registerctxluafile{font-ott}{1.001} % otf tables (first)
+\registerctxluafile{font-otf}{1.001} % otf main
+\registerctxluafile{font-otb}{1.001} % otf main base
+\registerctxluafile{node-inj}{1.001} % we might split it off
+\registerctxluafile{font-otn}{1.001} % otf main node
+\registerctxluafile{font-otd}{1.001} % otf dynamics (does an overload)
+\registerctxluafile{font-ota}{1.001} % otf analyzers (needs dynamics)
+\registerctxluafile{font-otp}{1.001} % otf pack
+\registerctxluafile{font-otc}{1.001} % otf context
+\registerctxluafile{font-oth}{1.001} % otf helpers
+
+\registerctxluafile{font-pat}{1.001} % patchers
+
+\registerctxluafile{node-fnt}{1.001} % here
+
+\registerctxluafile{font-lua}{1.001}
+
+\registerctxluafile{font-vf} {1.001}
+\registerctxluafile{font-enh}{1.001}
+
+\registerctxluafile{font-gds}{1.001} % currently only otf
+
+\registerctxluafile{font-def}{1.001}
+\registerctxluafile{font-ctx}{1.001} % after def as it overloads
+
+\registerctxluafile{font-ext}{1.001}
+\registerctxluafile{font-fbk}{1.001}
+\registerctxluafile{font-chk}{1.001}
+
+\registerctxluafile{font-aux}{1.001}
+
+%D Some low level helpers
+%D
+%D \starttyping
+%D \def\TestLookup#specification%
+%D {\dolookupfontbyspec{#specification}
+%D pattern: #specification, found: \dolookupnoffound
+%D \blank
+%D \dorecurse {\dolookupnoffound} {%
+%D \recurselevel:~\dolookupgetkeyofindex{fontname}{\recurselevel}\quad
+%D }%
+%D \blank}
+%D
+%D \TestLookup{familyname=helveticaneue}
+%D \TestLookup{familyname=helveticaneue,weight=bold}
+%D \TestLookup{familyname=helveticaneue,weight=bold,style=italic}
+%D \stoptyping
+
+% we can also move the lookups to the fonts.namespace (of commands)
+
+% these will be renamed but it needs synchronization with WS
+
+\def\dolookupfontbyspec #1{\ctxcommand{fontlookupinitialize("#1")}}
+\def\dolookupnoffound {\ctxcommand{fontlookupnoffound()}}
+\def\dolookupgetkeyofindex#1#2{\ctxcommand{fontlookupgetkeyofindex("#1",#2)}}
+\def\dolookupgetkey #1{\ctxcommand{fontlookupgetkey("#1")}}
+\def\cleanfontname #1{\ctxcommand{cleanfontname("#1")}}
+
+% new:
+
+\unexpanded\def\setfontofid#1{\ctxcommand{setfontofid(#1)}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-map.lua b/Master/texmf-dist/tex/context/base/font-map.lua
index 76733adeac6..7f5305f9a44 100644
--- a/Master/texmf-dist/tex/context/base/font-map.lua
+++ b/Master/texmf-dist/tex/context/base/font-map.lua
@@ -98,6 +98,15 @@ local function tounicode16sequence(unicodes)
return concat(t)
end
+local function fromunicode16(str)
+ if #str == 4 then
+ return tonumber(str,16)
+ else
+ local l, r = match(str,"(....)(....)")
+ return (tonumber(l,16)- 0xD800)*0x400 + tonumber(r,16) - 0xDC00
+ end
+end
+
--~ This is quite a bit faster but at the cost of some memory but if we
--~ do this we will also use it elsewhere so let's not follow this route
--~ now. I might use this method in the plain variant (no caching there)
@@ -122,6 +131,7 @@ mappings.loadlumtable = loadlumtable
mappings.makenameparser = makenameparser
mappings.tounicode16 = tounicode16
mappings.tounicode16sequence = tounicode16sequence
+mappings.fromunicode16 = fromunicode16
local separator = S("_.")
local other = C((1 - separator)^1)
@@ -177,7 +187,9 @@ function mappings.addtounicode(data,filename)
if unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
local unicode = lumunic and lumunic[name] or unicodevector[name]
if unicode then
- originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ originals[index] = unicode
+ tounicode[index] = tounicode16(unicode)
+ ns = ns + 1
end
-- cidmap heuristics, beware, there is no guarantee for a match unless
-- the chain resolves
@@ -186,7 +198,9 @@ function mappings.addtounicode(data,filename)
if foundindex then
unicode = cidcodes[foundindex] -- name to number
if unicode then
- originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ originals[index] = unicode
+ tounicode[index] = tounicode16(unicode)
+ ns = ns + 1
else
local reference = cidnames[foundindex] -- number to name
if reference then
@@ -194,16 +208,23 @@ function mappings.addtounicode(data,filename)
if foundindex then
unicode = cidcodes[foundindex]
if unicode then
- originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ originals[index] = unicode
+ tounicode[index] = tounicode16(unicode)
+ ns = ns + 1
end
end
if not unicode then
local foundcodes, multiple = lpegmatch(uparser,reference)
if foundcodes then
+ originals[index] = foundcodes
if multiple then
- originals[index], tounicode[index], nl, unicode = foundcodes, tounicode16sequence(foundcodes), nl + 1, true
+ tounicode[index] = tounicode16sequence(foundcodes)
+ nl = nl + 1
+ unicode = true
else
- originals[index], tounicode[index], ns, unicode = foundcodes, tounicode16(foundcodes), ns + 1, foundcodes
+ tounicode[index] = tounicode16(foundcodes)
+ ns = ns + 1
+ unicode = foundcodes
end
end
end
@@ -214,19 +235,8 @@ function mappings.addtounicode(data,filename)
-- a.whatever or a_b_c.whatever or a_b_c (no numbers)
if not unicode then
local split = lpegmatch(ligsplitter,name)
- local nplit = (split and #split) or 0
- if nplit == 0 then
- -- skip
- elseif nplit == 1 then
- local base = split[1]
- unicode = unicodes[base] or unicodevector[base]
- if unicode then
- if type(unicode) == "table" then
- unicode = unicode[1]
- end
- originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
- end
- else
+ local nplit = split and #split or 0
+ if nplit >= 2 then
local t, n = { }, 0
for l=1,nplit do
local base = split[l]
@@ -244,26 +254,39 @@ function mappings.addtounicode(data,filename)
if n == 0 then -- done then
-- nothing
elseif n == 1 then
- originals[index], tounicode[index], nl, unicode = t[1], tounicode16(t[1]), nl + 1, true
+ originals[index] = t[1]
+ tounicode[index] = tounicode16(t[1])
else
- originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true
+ originals[index] = t
+ tounicode[index] = tounicode16sequence(t)
end
+ nl = nl + 1
+ unicode = true
+ else
+ -- skip: already checked and we don't want privates here
end
end
- -- last resort
+ -- last resort (we might need to catch private here as well)
if not unicode then
local foundcodes, multiple = lpegmatch(uparser,name)
if foundcodes then
if multiple then
- originals[index], tounicode[index], nl, unicode = foundcodes, tounicode16sequence(foundcodes), nl + 1, true
+ originals[index] = foundcodes
+ tounicode[index] = tounicode16sequence(foundcodes)
+ nl = nl + 1
+ unicode = true
else
- originals[index], tounicode[index], ns, unicode = foundcodes, tounicode16(foundcodes), ns + 1, foundcodes
+ originals[index] = foundcodes
+ tounicode[index] = tounicode16(foundcodes)
+ ns = ns + 1
+ unicode = foundcodes
end
end
end
- if not unicode then
- originals[index], tounicode[index] = 0xFFFD, "FFFD"
- end
+ -- if not unicode then
+ -- originals[index] = 0xFFFD
+ -- tounicode[index] = "FFFD"
+ -- end
end
end
if trace_mapping then
diff --git a/Master/texmf-dist/tex/context/base/font-mat.mkvi b/Master/texmf-dist/tex/context/base/font-mat.mkvi
new file mode 100644
index 00000000000..7ef0f2b777a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-mat.mkvi
@@ -0,0 +1,414 @@
+%D \module
+%D [ file=font-mat,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Math,
+%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 / Math}
+
+\unprotect
+
+%D Be nice:
+
+\ifdefined\??fontinstanceready \else \installcorenamespace{fontinstanceready} \fi
+\ifdefined\??fontinstancebasic \else \installcorenamespace{fontinstancebasic} \fi
+\ifdefined\??fontinstanceclass \else \installcorenamespace{fontinstanceclass} \fi
+
+%D \macros
+%D {textonly}
+%D
+%D Traditionally math has a big impact on font definitions, mainly
+%D because we need to define alphabet variants using families and
+%D fonts. This means that one can easily get 10 fonts loaded per
+%D math size. In \MKIV\ we use a different approach: one family
+%D which has either a virtual font made of traditional fonts, or
+%D an \OPENTYPE\ font that has it all.
+%D
+%D We currently use only one math family but in the future we
+%D might consider using a second one for bold math. For the
+%D moment we keep the \MKII\ method of using a token register
+%D for definitions but we already dropped the text and symbols
+%D ones since they now live in the same family.
+
+\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
+ {\ifconditional\c_font_synchronize_math_fonts\the\t_font_math_strategies\fi}
+
+\unexpanded\def\textonly{\setfalse\c_font_synchronize_math_fonts} % document this
+
+%D The main math font definer. We have removed some optimized
+%D code simply because we now always have a fontclass. We could
+%D check for fontclass being default or empty and save a few
+%D tests but it does not help us when no math is defined.
+
+%D Because we want to keep mr=.. and mb=... settings (read: not
+%D break downward compatibility by enforcing mrlr etc) we need a
+%D bit more code that optimal.
+
+% todo: \c_font_fam_mr
+
+\let\c_font_fam_mr \zerocount % math regular
+\let\c_font_fam_mr_lr\plusone % math regular l2r
+\let\c_font_fam_mr_rl\plustwo % math regular r2l
+
+\let\c_font_fam_mb \plusthree % math bold
+\let\c_font_fam_mb_lr\plusfour % math bold l2r
+\let\c_font_fam_mb_rl\plusfive % math bold r2l
+
+\definesystemattribute[mathfamily][public]
+
+\newconditional\c_font_bidirectional_math_strategy % can be default, not that much overhead: \settrue\c_font_bidirectional_math_strategy
+\newconditional\c_font_complete_bold_math_strategy \settrue\c_font_complete_bold_math_strategy
+
+\def\mathtextsuffix {-text}
+\def\mathscriptsuffix {-script}
+\def\mathscriptscriptsuffix{-scriptscript}
+
+\def\mathsizesuffix{\ifcase\fontface\or\mathtextsuffix\or\mathscriptsuffix\or\mathscriptscriptsuffix\fi}
+
+% Beware: truefontname also does a fallback on defaultfontclass so there
+% can be some interference here, which is why we use a different method
+% for bold.
+
+\def\font_helpers_set_math_family_a
+ {\ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \csname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+ \ifcsname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \csname\??fontinstanceready\fontclass -\fontbody-\s!mm-\fontfamily \endcsname \else
+ \font_helpers_set_math_family_b
+ \fi\fi}
+
+\def\font_helpers_set_math_family_b
+ {\ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+ \ifcsname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \csname\??fontinstanceready\defaultfontclass-\fontbody-\s!mm-\fontfamily \endcsname \else
+ \font_helpers_set_math_family_c
+ \fi\fi}
+
+\def\font_helpers_set_math_family_c
+ {\ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \csname\??fontinstanceready \fontbody-\s!mm-\fontfamily-\fontsize\endcsname \else
+ \ifcsname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \csname\??fontinstanceready \fontbody-\s!mm-\fontfamily \endcsname \else
+ \nullfont \settrue \c_font_auto_size
+ \fi\fi}
+
+\def\font_helpers_set_math_family_indeed#mrtag#family% \fontface etc are also used later on
+ {\let\savedfontbody\fontbody
+ \let\fontfamily#family%
+ \let\fontface\!!plusthree\font_helpers_set_math_family_a\scriptscriptfont#mrtag\font
+ \let\fontface\!!plustwo \font_helpers_set_math_family_a\scriptfont #mrtag\font
+ \let\fontface\!!plusone \font_helpers_set_math_family_a\textfont #mrtag\font
+ \let\fontface\!!zerocount
+ \let\fontbody\savedfontbody
+ \setfalse\c_font_auto_size}
+
+\def\font_helpers_set_math_family_bold_a#font#mbfam#mrfam%
+ {\ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname \setfalse\c_font_auto_size
+ \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily-\fontsize\endcsname #font#mbfam\font \else
+ \ifcsname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname \settrue \c_font_auto_size
+ \csname\??fontinstanceready\fontclass-\fontbody-\s!mm-\fontfamily \endcsname #font#mbfam\font \else
+ #font#mbfam#font#mrfam%
+ \fi\fi}
+
+\def\font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam% \c_font_fam_mb \s!mb \c_font_fam_mr
+ {\let\savedfontclass\defaultfontclass
+ \let\defaultfontclass\fontclass % else truefontname falls back on the wrong one
+ \let\savedfontbody\fontbody
+ \let\fontfamily#familytag%
+ \let\fontface\!!plusthree\font_helpers_set_math_family_bold_a\scriptscriptfont#mbfam#mrfam%
+ \let\fontface\!!plustwo \font_helpers_set_math_family_bold_a\scriptfont #mbfam#mrfam%
+ \let\fontface\!!plusone \font_helpers_set_math_family_bold_a\textfont #mbfam#mrfam%
+ \let\fontface\!!zerocount
+ \let\fontbody\savedfontbody
+ \let\defaultfontclass\savedfontclass
+ \setfalse\c_font_auto_size}
+
+% optimized: math fonts are never changed (10K \bfa $x$: 3.2 => 2.5 (baseline 1.0))
+%
+% sort of tricky: we cannot reset in \everybeforedefinetypeface as we don't know
+% all sizes so we postpone the optimization to the first starttext
+%
+% pitfall: we should reset 'm when a fontclass name is reused
+
+\newconditional\optimizemathfontdefinitions \settrue\optimizemathfontdefinitions
+
+\def\font_helpers_set_math_family#mrfam#familytag%
+ {\ifconditional\optimizemathfontdefinitions
+ \ifcsname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname
+ % \writestatus{fonts}{math: reusing \fontclass\fontbody\s!mm#familytag\fontsize1}%
+ \font_helpers_preset_math_family_indeed#mrfam#familytag%
+ \else
+ % \writestatus{fonts}{math: defining \fontclass\fontbody\s!mm#familytag\fontsize1}%
+ \font_helpers_set_math_family_indeed#mrfam#familytag%
+ \fi
+ \else
+ \font_helpers_set_math_family_indeed#mrfam#familytag%
+ \fi}
+
+\def\font_helpers_set_math_family_bold#mbfam#familytag#mrfam%
+ {\ifconditional\optimizemathfontdefinitions
+ \ifcsname\??fontinstanceclass\fontclass-\textface-\s!mm-#familytag-\fontsize-1\endcsname
+ \font_helpers_preset_math_family_indeed#mbfam#familytag%
+ \else
+ \font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam%
+ \fi
+ \else
+ \font_helpers_set_math_family_bold_indeed#mbfam#familytag#mrfam%
+ \fi}
+
+\def\font_helpers_preset_math_family_indeed#fam#familytag%
+ {\scriptscriptfont#fam\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-3\endcsname
+ \scriptfont #fam\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-2\endcsname
+ \textfont #fam\csname\??fontinstanceclass\fontclass-\fontbody-\s!mm-#familytag-\fontsize-1\endcsname}
+
+\let\font_helpers_reset_fontclass_math_families\gobbleoneargument
+
+% It would be nice if characters could be defined in a neutral way (say fam 255) and
+% be mapped to a real family during noad list construction. However, this changes
+% tex in critical places so for the moment we simulate this using manipulation.
+
+% For tracing purposes we use three families but in l2r mode 1 and 2 are copies of 0
+% while in rl mode 0 is a copy of 1. There is no real overhead involved in this. This
+% also permits different font definitions for normal and mixed.
+
+\let\m_font_class_direction\empty
+\let\m_font_class_features \empty
+\let\m_font_class_fallbacks\empty
+\let\m_font_class_goodies \empty
+
+\let\m_font_direction\empty
+\let\m_font_features \empty
+\let\m_font_fallbacks\empty
+\let\m_font_goodies \empty
+
+\appendtoks % can be analyzed once
+ % why here ..
+ \edef\m_font_class_direction{\ifcsname\??fontclass\fontclass\s!mm\s!direction\endcsname\csname\??fontclass\fontclass\s!mm\s!direction\endcsname\fi}%
+ % ...
+ \ifx\m_font_class_direction\v!both
+ \settrue\c_font_bidirectional_math_strategy
+ \else
+ \setfalse\c_font_bidirectional_math_strategy
+ \fi
+\to \t_font_math_strategies
+
+\def\font_helpers_bidirectional_mathstrategy_yes
+ {\font_helpers_set_math_family\c_font_fam_mr_lr\s!mrlr
+ \font_helpers_set_math_family\c_font_fam_mr_rl\s!mrrl
+ \textfont \c_font_fam_mr\textfont \c_font_fam_mr_lr
+ \scriptfont \c_font_fam_mr\scriptfont \c_font_fam_mr_lr
+ \scriptscriptfont\c_font_fam_mr\scriptscriptfont\c_font_fam_mr_lr}
+
+\def\font_helpers_bidirectional_mathstrategy_nop
+ {\font_helpers_set_math_family\c_font_fam_mr\s!mr
+ \textfont \c_font_fam_mr_rl\textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mr_rl\scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mr_rl\scriptscriptfont\c_font_fam_mr
+ \textfont \c_font_fam_mr_lr\textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mr_lr\scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mr_lr\scriptscriptfont\c_font_fam_mr}
+
+\appendtoks
+ \ifconditional\c_font_bidirectional_math_strategy
+ \font_helpers_bidirectional_mathstrategy_yes
+ \else
+ \font_helpers_bidirectional_mathstrategy_nop
+ \fi
+\to \t_font_math_strategies
+
+\def\font_helpers_complete_bold_math_strategy_yes_bidi
+ {\font_helpers_set_math_family_bold\c_font_fam_mb_lr\s!mblr\c_font_fam_mr_lr
+ \font_helpers_set_math_family_bold\c_font_fam_mb_rl\s!mbrl\c_font_fam_mr_rl
+ \textfont \c_font_fam_mb\textfont \c_font_fam_mb_lr
+ \scriptfont \c_font_fam_mb\scriptfont \c_font_fam_mb_lr
+ \scriptscriptfont\c_font_fam_mb\scriptscriptfont\c_font_fam_mb_lr}
+
+\def\font_helpers_complete_bold_math_strategy_yes
+ {\font_helpers_set_math_family_bold\c_font_fam_mb\s!mb\c_font_fam_mr
+ \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mb
+ \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mb
+ \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mb
+ \textfont \c_font_fam_mb_lr\textfont \c_font_fam_mb
+ \scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mb
+ \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mb}
+
+\def\font_helpers_complete_bold_math_strategy_nop
+ {\textfont \c_font_fam_mb \textfont \c_font_fam_mr
+ \scriptfont \c_font_fam_mb \scriptfont \c_font_fam_mr
+ \scriptscriptfont\c_font_fam_mb \scriptscriptfont\c_font_fam_mr
+ \textfont \c_font_fam_mb_rl\textfont \c_font_fam_mr_rl
+ \scriptfont \c_font_fam_mb_rl\scriptfont \c_font_fam_mr_rl
+ \scriptscriptfont\c_font_fam_mb_rl\scriptscriptfont\c_font_fam_mr_rl
+ \textfont \c_font_fam_mb_lr\textfont \c_font_fam_mr_lr
+ \scriptfont \c_font_fam_mb_lr\scriptfont \c_font_fam_mr_lr
+ \scriptscriptfont\c_font_fam_mb_lr\scriptscriptfont\c_font_fam_mr_lr}
+
+\def\font_helpers_apply_complete_bold_math_strategy
+ {\ifconditional\c_font_complete_bold_math_strategy
+ \ifconditional\c_font_bidirectional_math_strategy
+ \font_helpers_complete_bold_math_strategy_yes_bidi
+ \else
+ \font_helpers_complete_bold_math_strategy_yes
+ \fi
+ \else
+ \font_helpers_complete_bold_math_strategynop
+ \fi}
+
+\appendtoks
+ \font_helpers_apply_complete_bold_math_strategy
+\to \t_font_math_strategies
+
+\ifdefined\defaultmathfamily \else
+ \setnewconstant\defaultmathfamily\zerocount
+\fi
+
+\appendtoks
+ \fam\defaultmathfamily % all characters and symbols are in this family
+\to \everymathematics
+
+\unexpanded\def\font_helpers_synchronize_math_family_mr
+ {\attribute\mathfamilyattribute\ifconditional\c_font_bidirectional_math_strategy
+ \ifconditional\c_math_right_to_left
+ \plustwo
+ \else
+ \plusone
+ \fi
+ \else
+ \zerocount
+ \fi}
+
+\unexpanded\def\font_helpers_synchronize_math_family_mb
+ {\attribute\mathfamilyattribute\ifconditional\c_font_bidirectional_math_strategy
+ \ifconditional\c_math_right_to_left
+ \ifconditional\c_font_pseudo_bold_math_state\pluseight\else\plusfive\fi
+ \else
+ \ifconditional\c_font_pseudo_bold_math_state\plusseven\else\plusfour\fi
+ \fi
+ \else
+ \ifconditional\c_font_pseudo_bold_math_state\plussix\else\plusthree\fi
+ \fi}
+
+\installcorenamespace{fontmathsynchronizer}
+\installcorenamespace{fontmathstoredstrategy}
+
+\letvalue{\??fontmathsynchronizer\s!tf }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!sl }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!it }\font_helpers_synchronize_math_family_mr
+\letvalue{\??fontmathsynchronizer\s!bf }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\s!bs }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\s!bi }\font_helpers_synchronize_math_family_mb
+\letvalue{\??fontmathsynchronizer\empty}\font_helpers_synchronize_math_family_mr
+
+\def\font_helpers_synchronize_math_family
+ {\csname\??fontmathsynchronizer\ifcsname\??fontmathsynchronizer\fontalternative\endcsname\fontalternative\fi\endcsname}
+
+\ifdefined \fontid % we need to keep this test for a while
+ \appendtoks
+ \ifnum\fontid\textfont\zerocount=\fontid\textfont\plusthree
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_partial_bold_strategy
+ \else
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_full_bold_strategy
+ \fi
+ \to \t_font_math_strategies
+\else
+ \appendtoks
+ \edef\currentmathfontmr{\fontname\textfont\zerocount}%
+ \edef\currentmathfontmb{\fontname\textfont\plusthree}%
+ \ifx\currentmathfontmr\currentmathfontmb
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_partial_bold_strategy
+ \else
+ \letvalue{\??fontmathstoredstrategy\fontclass}\font_helpers_set_math_full_bold_strategy
+ \fi
+ \to \t_font_math_strategies
+\fi
+
+\def\font_helpers_synchronize_math_bold_strategy{\csname\??fontmathstoredstrategy\fontclass\endcsname}
+
+\newconditional\c_font_pseudo_bold_math_state
+
+\def\font_helpers_set_math_partial_bold_strategy{\settrue \c_font_pseudo_bold_math_state}
+\def\font_helpers_set_math_full_bold_strategy {\setfalse\c_font_pseudo_bold_math_state}
+
+\appendtoks
+ \font_helpers_synchronize_math_bold_strategy
+\to \everymathematics
+
+% Bold is somewhat special as we might want both full-bold-math mixed
+% regular-math, as well as automatic adaption to outer bold (in titles
+% and inline text bold) so we will need explicit switches as well as
+% an automatic one. (We will use lucida as an example.)
+
+\unexpanded\def\mr
+ {\ifmmode
+ \font_helpers_synchronize_math_family_mr
+ \else
+ \font_helpers_set_current_font_alternative\s!mr
+ \fi}
+
+\unexpanded\def\mb
+ {\ifmmode
+ \font_helpers_synchronize_math_family_mb
+ \else
+ \font_helpers_set_current_font_alternative\s!mb
+ \fi}
+
+\appendtoks
+ \font_helpers_synchronize_math_family % auto bold
+\to \everymathematics
+
+%D \macros
+%D {bigmath,nobigmath}
+%D
+%D We can inhibit this slow||downer with:
+
+% these can best be combined
+
+% 0=never 1=everymath 2=always
+
+\setnewconstant\synchronizebigmathflag\plusone
+
+\appendtoks
+ \ifcase\synchronizebigmathflag
+ % never
+ \or
+ \synchronizebigmath
+ \or
+ % always
+ \fi
+\to \everymathematics
+
+\unexpanded\def\nobigmath {\synchronizebigmathflag\zerocount}
+\unexpanded\def\autobigmath{\synchronizebigmathflag\plusone\synchronizebigmath}
+\unexpanded\def\bigmath {\synchronizebigmathflag\plustwo\synchronizebigmath}
+
+\let\bigmathfontsize\empty
+
+\unexpanded\def\synchronizebigmath
+ {\ifx\bigmathfontsize\fontsize
+ % already in sync
+ \else
+ \let\bigmathfontsize\fontsize
+ \font_helpers_synchronize_math
+ \fi}
+
+\unexpanded\def\font_helpers_check_big_math_synchronization
+ {\ifcase\synchronizebigmathflag
+ % never
+ \or
+ \ifmmode \synchronizebigmath \fi
+ \or
+ \synchronizebigmath
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-mis.lua b/Master/texmf-dist/tex/context/base/font-mis.lua
index 198293ba132..e5971e524e1 100644
--- a/Master/texmf-dist/tex/context/base/font-mis.lua
+++ b/Master/texmf-dist/tex/context/base/font-mis.lua
@@ -22,7 +22,7 @@ local handlers = fonts.handlers
handlers.otf = handlers.otf or { }
local otf = handlers.otf
-otf.version = otf.version or 2.730
+otf.version = otf.version or 2.736
otf.cache = otf.cache or containers.define("fonts", "otf", otf.version, true)
function otf.loadcached(filename,format,sub)
diff --git a/Master/texmf-dist/tex/context/base/font-ota.lua b/Master/texmf-dist/tex/context/base/font-ota.lua
index 1bf73653198..c4663e1f4ed 100644
--- a/Master/texmf-dist/tex/context/base/font-ota.lua
+++ b/Master/texmf-dist/tex/context/base/font-ota.lua
@@ -163,7 +163,7 @@ registerotffeature {
methods.latn = analyzers.setstate
--- this info eventually will go into char-def adn we will have a state
+-- this info eventually will go into char-def and we will have a state
-- table for generic then
local zwnj = 0x200C
@@ -193,6 +193,12 @@ local isol_fina = {
[0x076C] = true, [0x0771] = true, [0x0773] = true, [0x0774] = true,
[0x0778] = true, [0x0779] = true, [0xFEF5] = true, [0xFEF7] = true,
[0xFEF9] = true, [0xFEFB] = true,
+
+ -- syriac
+
+ [0x0710] = true, [0x0715] = true, [0x0716] = true, [0x0717] = true,
+ [0x0718] = true, [0x0719] = true, [0x0728] = true, [0x072A] = true,
+ [0x072C] = true, [0x071E] = true,
}
local isol_fina_medi_init = {
@@ -230,10 +236,19 @@ local isol_fina_medi_init = {
[0x0772] = true, [0x0775] = true, [0x0776] = true, [0x0777] = true,
[0x077A] = true, [0x077B] = true, [0x077C] = true, [0x077D] = true,
[0x077E] = true, [0x077F] = true, [zwj] = true,
+
+ -- syriac
+
+ [0x0712] = true, [0x0713] = true, [0x0714] = true, [0x071A] = true,
+ [0x071B] = true, [0x071C] = true, [0x071D] = true, [0x071F] = true,
+ [0x0720] = true, [0x0721] = true, [0x0722] = true, [0x0723] = true,
+ [0x0725] = true, [0x0726] = true, [0x0727] = true, [0x0729] = true,
+ [0x072B] = true, [0x0724] = true, [0x0706] = true, [0x0707] = true,
}
local arab_warned = { }
+
-- todo: gref
local function warning(current,what)
@@ -351,6 +366,8 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr
return head, done
end
+methods.syrc = methods.arab
+
directives.register("otf.analyze.useunicodemarks",function(v)
analyzers.useunicodemarks = v
end)
diff --git a/Master/texmf-dist/tex/context/base/font-otb.lua b/Master/texmf-dist/tex/context/base/font-otb.lua
index 1a812c328cb..44639a80aa1 100644
--- a/Master/texmf-dist/tex/context/base/font-otb.lua
+++ b/Master/texmf-dist/tex/context/base/font-otb.lua
@@ -27,6 +27,8 @@ local otf = fonts.handlers.otf
local otffeatures = fonts.constructors.newfeatures("otf")
local registerotffeature = otffeatures.register
+otf.defaultbasealternate = "none" -- first last
+
local wildcard = "*"
local default = "dflt"
@@ -59,6 +61,22 @@ local function cref(feature,lookupname)
end
end
+local function report_alternate(feature,lookupname,descriptions,unicode,replacement,value,comment)
+ report_prepare("%s: base alternate %s => %s (%s => %s)",cref(feature,lookupname),
+ gref(descriptions,unicode),replacement and gref(descriptions,replacement) or "-",
+ tostring(value),comment)
+end
+
+local function report_substitution(feature,lookupname,descriptions,unicode,substitution)
+ report_prepare("%s: base substitution %s => %s",cref(feature,lookupname),
+ gref(descriptions,unicode),gref(descriptions,substitution))
+end
+
+local function report_ligature(feature,lookupname,descriptions,unicode,ligature)
+ report_prepare("%s: base ligature %s => %s",cref(feature,lookupname),
+ gref(descriptions,ligature),gref(descriptions,unicode))
+end
+
local basemethods = { }
local basemethod = "<unset>"
@@ -223,27 +241,47 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local lookuptypes = resources.lookuptypes
local ligatures = { }
+ local alternate = tonumber(value)
+ local defaultalt = otf.defaultbasealternate
+
+ local trace_singles = trace_baseinit and trace_singles
+ local trace_alternatives = trace_baseinit and trace_alternatives
+ local trace_ligatures = trace_baseinit and trace_ligatures
local actions = {
substitution = function(lookupdata,lookupname,description,unicode)
- if trace_baseinit and trace_singles then
- report_prepare("%s: base substitution %s => %s",cref(feature,lookupname),
- gref(descriptions,unicode),gref(descriptions,replacement))
+ if trace_singles then
+ report_substitution(feature,lookupname,descriptions,unicode,lookupdata)
end
changed[unicode] = lookupdata
end,
alternate = function(lookupdata,lookupname,description,unicode)
- local replacement = lookupdata[value] or lookupdata[#lookupdata]
- if trace_baseinit and trace_alternatives then
- report_prepare("%s: base alternate %s %s => %s",cref(feature,lookupname),
- tostring(value),gref(descriptions,unicode),gref(descriptions,replacement))
+ local replacement = lookupdata[alternate]
+ if replacement then
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
+ end
+ elseif defaultalt == "first" then
+ replacement = lookupdata[1]
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ elseif defaultalt == "last" then
+ replacement = lookupdata[#data]
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ else
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
+ end
end
- changed[unicode] = replacement
end,
ligature = function(lookupdata,lookupname,description,unicode)
- if trace_baseinit and trace_alternatives then
- report_prepare("%s: base ligature %s %s => %s",cref(feature,lookupname),
- tostring(value),gref(descriptions,lookupdata),gref(descriptions,unicode))
+ if trace_ligatures then
+ report_ligature(feature,lookupname,descriptions,unicode,lookupdata)
end
ligatures[#ligatures+1] = { unicode, lookupdata }
end,
@@ -409,6 +447,12 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local lookuptypes = resources.lookuptypes
local ligatures = { }
+ local alternate = tonumber(value)
+ local defaultalt = otf.defaultbasealternate
+
+ local trace_singles = trace_baseinit and trace_singles
+ local trace_alternatives = trace_baseinit and trace_alternatives
+ local trace_ligatures = trace_baseinit and trace_ligatures
for l=1,#lookuplist do
local lookupname = lookuplist[l]
@@ -416,20 +460,38 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local lookuptype = lookuptypes[lookupname]
for unicode, data in next, lookupdata do
if lookuptype == "substitution" then
- if trace_baseinit and trace_singles then
- report_prepare("%s: base substitution %s => %s",cref(feature,lookupname),
- gref(descriptions,unicode),gref(descriptions,data))
+ if trace_singles then
+ report_substitution(feature,lookupname,descriptions,unicode,data)
end
changed[unicode] = data
elseif lookuptype == "alternate" then
- local replacement = data[value] or data[#data]
- if trace_baseinit and trace_alternatives then
- report_prepare("%s: base alternate %s %s => %s",cref(feature,lookupname),
- tostring(value),gref(descriptions,unicode),gref(descriptions,replacement))
+ local replacement = data[alternate]
+ if replacement then
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
+ end
+ elseif defaultalt == "first" then
+ replacement = data[1]
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ elseif defaultalt == "last" then
+ replacement = data[#data]
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ else
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
+ end
end
- changed[unicode] = replacement
elseif lookuptype == "ligature" then
ligatures[#ligatures+1] = { unicode, data, lookupname }
+ if trace_ligatures then
+ report_ligature(feature,lookupname,descriptions,unicode,data)
+ end
end
end
end
@@ -454,13 +516,6 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,lookupname)
end
- if done then
- for lookupname, list in next, done do
- report_prepare("%s: base ligatures %s => %s",cref(feature,lookupname),
- tostring(value),gref(descriptions,done))
- end
- end
-
end
end
@@ -566,13 +621,13 @@ registerotffeature {
description = "features",
default = true,
initializers = {
---~ position = 1, -- after setscript (temp hack ... we need to force script / language to 1
+ -- position = 1, -- after setscript (temp hack ... we need to force script / language to 1
base = featuresinitializer,
}
}
-- independent : collect lookups independently (takes more runtime ... neglectable)
--- shared : shares lookups with node mode (takes more memory ... noticeable)
+-- shared : shares lookups with node mode (takes more memory unless also a node mode variant is used ... noticeable)
directives.register("fonts.otf.loader.basemethod", function(v)
if basemethods[v] then
diff --git a/Master/texmf-dist/tex/context/base/font-otc.lua b/Master/texmf-dist/tex/context/base/font-otc.lua
index 1b4983ce01a..ae463e750a2 100644
--- a/Master/texmf-dist/tex/context/base/font-otc.lua
+++ b/Master/texmf-dist/tex/context/base/font-otc.lua
@@ -51,7 +51,8 @@ local function addfeature(data,feature,specifications)
local unicodes = resources.unicodes
local lookuptypes = resources.lookuptypes
local splitter = lpeg.splitter(" ",unicodes)
- local done = 0
+ local done = 0
+ local skip = 0
if not specifications[1] then
-- so we accept a one entry specification
specifications = { specifications }
@@ -59,92 +60,113 @@ local function addfeature(data,feature,specifications)
-- subtables are tables themselves but we also accept flattened singular subtables
for s=1,#specifications do
local specification = specifications[s]
- local askedfeatures = specification.features or everywhere
- local subtables = specification.subtables or { specification.data } or { }
- local featuretype = types[specification.type or "substitution"]
- local featureflags = specification.flags or noflags
- local added = false
- local featurename = format("ctx_%s_%s",feature,s)
- local st = { }
- for t=1,#subtables do
- local list = subtables[t]
- local full = format("%s_%s",featurename,t)
- st[t] = full
- if featuretype == "gsub_ligature" then
- lookuptypes[full] = "ligature"
- for code, ligature in next, list do
- local unicode = tonumber(code) or unicodes[code]
- local description = descriptions[unicode]
- if description then
- local slookups = description.slookups
- if type(ligature) == "string" then
- ligature = { lpegmatch(splitter,ligature) }
- end
- if slookups then
- slookups[full] = ligature
- else
- description.slookups = { [full] = ligature }
+ local valid = specification.valid
+ if not valid or valid(data,specification,feature) then
+ local initialize = specification.initialize
+ if initialize then
+ -- when false is returned we initialize only once
+ specification.initialize = initialize(specification) and initialize or nil
+ end
+ local askedfeatures = specification.features or everywhere
+ local subtables = specification.subtables or { specification.data } or { }
+ local featuretype = types[specification.type or "substitution"]
+ local featureflags = specification.flags or noflags
+ local added = false
+ local featurename = format("ctx_%s_%s",feature,s)
+ local st = { }
+ for t=1,#subtables do
+ local list = subtables[t]
+ local full = format("%s_%s",featurename,t)
+ st[t] = full
+ if featuretype == "gsub_ligature" then
+ lookuptypes[full] = "ligature"
+ for code, ligature in next, list do
+ local unicode = tonumber(code) or unicodes[code]
+ local description = descriptions[unicode]
+ if description then
+ local slookups = description.slookups
+ if type(ligature) == "string" then
+ ligature = { lpegmatch(splitter,ligature) }
+ end
+ local present = true
+ for i=1,#ligature do
+ if not descriptions[ligature[i]] then
+ present = false
+ break
+ end
+ end
+ if present then
+ if slookups then
+ slookups[full] = ligature
+ else
+ description.slookups = { [full] = ligature }
+ end
+ done, added = done + 1, true
+ else
+ skip = skip + 1
+ end
end
- done, added = done + 1, true
end
- end
- elseif featuretype == "gsub_single" then
- lookuptypes[full] = "substitution"
- for code, replacement in next, list do
- local unicode = tonumber(code) or unicodes[code]
- local description = descriptions[unicode]
- if description then
- local slookups = description.slookups
- replacement = tonumber(replacement) or unicodes[replacement]
- if slookups then
- slookups[full] = replacement
- else
- description.slookups = { [full] = replacement }
+ elseif featuretype == "gsub_single" then
+ lookuptypes[full] = "substitution"
+ for code, replacement in next, list do
+ local unicode = tonumber(code) or unicodes[code]
+ local description = descriptions[unicode]
+ if description then
+ local slookups = description.slookups
+ replacement = tonumber(replacement) or unicodes[replacement]
+ if descriptions[replacement] then
+ if slookups then
+ slookups[full] = replacement
+ else
+ description.slookups = { [full] = replacement }
+ end
+ done, added = done + 1, true
+ end
end
- done, added = done + 1, true
end
end
end
- end
- if added then
- -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
- for k, v in next, askedfeatures do
- if v[1] then
- askedfeatures[k] = table.tohash(v)
+ if added then
+ -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
+ for k, v in next, askedfeatures do
+ if v[1] then
+ askedfeatures[k] = table.tohash(v)
+ end
end
- end
- sequences[#sequences+1] = {
- chain = 0,
- features = { [feature] = askedfeatures },
- flags = featureflags,
- name = featurename,
- subtables = st,
- type = featuretype,
- }
- -- register in metadata (merge as there can be a few)
- if not gsubfeatures then
- gsubfeatures = { }
- fontfeatures.gsub = gsubfeatures
- end
- local k = gsubfeatures[feature]
- if not k then
- k = { }
- gsubfeatures[feature] = k
- end
- for script, languages in next, askedfeatures do
- local kk = k[script]
- if not kk then
- kk = { }
- k[script] = kk
+ sequences[#sequences+1] = {
+ chain = 0,
+ features = { [feature] = askedfeatures },
+ flags = featureflags,
+ name = featurename,
+ subtables = st,
+ type = featuretype,
+ }
+ -- register in metadata (merge as there can be a few)
+ if not gsubfeatures then
+ gsubfeatures = { }
+ fontfeatures.gsub = gsubfeatures
end
- for language, value in next, languages do
- kk[language] = value
+ local k = gsubfeatures[feature]
+ if not k then
+ k = { }
+ gsubfeatures[feature] = k
+ end
+ for script, languages in next, askedfeatures do
+ local kk = k[script]
+ if not kk then
+ kk = { }
+ k[script] = kk
+ end
+ for language, value in next, languages do
+ kk[language] = value
+ end
end
end
end
end
- if done > 0 and trace_loading then
- report_otf("enhance: registering %s feature (%s glyphs affected)",feature,done)
+ if trace_loading then
+ report_otf("enhance: registering feature '%s', %s glyphs affected, %s glyphs skipped",feature,done,skip)
end
end
end
@@ -179,9 +201,9 @@ local tlig = {
local tlig_specification = {
type = "ligature",
- features = everywhere, -- { ["*"] = { ["*"] = true } },
+ features = everywhere,
data = tlig,
- flags = noflags, -- { },
+ flags = noflags,
}
otf.addfeature("tlig",tlig_specification)
@@ -201,9 +223,9 @@ local trep = {
local trep_specification = {
type = "substitution",
- features = everywhere, -- { ["*"] = { ["*"] = true } },
+ features = everywhere,
data = trep,
- flags = noflags, -- { },
+ flags = noflags,
}
otf.addfeature("trep",trep_specification)
@@ -213,6 +235,39 @@ registerotffeature {
description = 'tex replacements',
}
+-- tcom
+
+if characters.combined then
+
+ local tcom = { }
+
+ local function initialize()
+ characters.initialize()
+ for first, seconds in next, characters.combined do
+ for second, combination in next, seconds do
+ tcom[combination] = { first, second }
+ end
+ end
+ -- return false
+ end
+
+ local tcom_specification = {
+ type = "ligature",
+ features = everywhere,
+ data = tcom,
+ flags = noflags,
+ initialize = initialize,
+ }
+
+ otf.addfeature("tcom",tcom_specification)
+
+ registerotffeature {
+ name = 'tcom',
+ description = 'tex combinations',
+ }
+
+end
+
-- anum
local anum_arabic = {
@@ -241,22 +296,37 @@ local anum_persian = {
[0x0039] = 0x06F9,
}
+local function valid(data)
+ local features = data.resources.features
+ if features then
+ for k, v in next, features do
+ for k, v in next, v do
+ if v.arab then
+ return true
+ end
+ end
+ end
+ end
+end
+
local anum_specification = {
{
type = "substitution",
features = { arab = { URD = true, dflt = true } },
data = anum_arabic,
flags = noflags, -- { },
+ valid = valid,
},
{
type = "substitution",
features = { arab = { URD = true } },
data = anum_persian,
flags = noflags, -- { },
+ valid = valid,
},
}
-otf.addfeature("anum",anum_specification)
+otf.addfeature("anum",anum_specification) -- todo: only when there is already an arab script feature
registerotffeature {
name = 'anum',
diff --git a/Master/texmf-dist/tex/context/base/font-otd.lua b/Master/texmf-dist/tex/context/base/font-otd.lua
index b22889217cb..ebd4879599d 100644
--- a/Master/texmf-dist/tex/context/base/font-otd.lua
+++ b/Master/texmf-dist/tex/context/base/font-otd.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['font-otd'] = {
}
local match = string.match
+local sequenced = table.sequenced
local trace_dynamics = false trackers.register("otf.dynamics", function(v) trace_dynamics = v end)
local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end)
@@ -16,11 +17,14 @@ local report_process = logs.reporter("fonts","otf process")
local fonts = fonts
local otf = fonts.handlers.otf
-local fontdata = fonts.hashes.identifiers
+local hashes = fonts.hashes
local definers = fonts.definers
local constructors = fonts.constructors
local specifiers = fonts.specifiers
+local fontdata = hashes.identifiers
+----- fontresources = hashes.resources -- not yet defined
+
local contextsetups = specifiers.contextsetups
local contextnumbers = specifiers.contextnumbers
local contextmerged = specifiers.contextmerged
@@ -31,7 +35,7 @@ local otffeatures = fonts.constructors.newfeatures("otf")
local registerotffeature = otffeatures.register
local fontdynamics = { }
-fonts.hashes.dynamics = fontdynamics
+hashes.dynamics = fontdynamics
local a_to_script = { }
local a_to_language = { }
@@ -48,6 +52,10 @@ function otf.setdynamics(font,attribute)
local dynamics = fontdynamics[font]
local script = features.script or 'dflt'
local language = features.language or 'dflt'
+ if script == "auto" then
+ -- checkedscript and resources are defined later so we cannot shortcut them
+ script = definers.checkedscript(fontdata[font],hashes.resources[font],features)
+ end
local ds = dynamics[script] -- can be metatable magic (less testing)
if not ds then
ds = { }
@@ -77,10 +85,10 @@ function otf.setdynamics(font,attribute)
shared.features = { }
-- end of save
local set = constructors.checkedfeatures("otf",features)
-set.mode = "node" -- really needed
+ set.mode = "node" -- really needed
dsla = otf.setfeatures(tfmdata,set)
if trace_dynamics then
- report_otf("setting dynamics %s: attribute %s, script %s, language %s, set: %s",contextnumbers[attribute],attribute,script,language,table.sequenced(set))
+ report_otf("setting dynamics %s: attribute %s, script %s, language %s, set: %s",contextnumbers[attribute],attribute,script,language,sequenced(set))
end
-- we need to restore some values
properties.script = s_script
@@ -122,9 +130,9 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr
local features = sequence.features
if features then
for kind, scripts in next, features do
- local s_e = s_enabled and s_enabled[kind]
- local a_e = a_enabled and a_enabled[kind]
- local e_e = s_e or a_e
+ local s_e = s_enabled and s_enabled[kind] -- the value
+ local a_e = a_enabled and a_enabled[kind] -- the value
+ local e_e = s_e or a_e -- todo: when one of them is true and the other is a value
if e_e then
local languages = scripts[script] or scripts[wildcard]
if languages then
@@ -133,13 +141,13 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr
-- only first attribute match check, so we assume simple fina's
-- default can become a font feature itself
if languages[language] then
- valid = true
+ valid = e_e -- was true
what = language
-- elseif languages[default] then
-- valid = true
-- what = default
elseif languages[wildcard] then
- valid = true
+ valid = e_e -- was true
what = wildcard
end
if valid then
@@ -153,38 +161,45 @@ local function initialize(sequence,script,language,s_enabled,a_enabled,font,attr
"%s font: %03i, dynamic: %03i, kind: %s, script: %-4s, language: %-4s (%-4s), type: %s, action: %s, name: %s",
(valid and "+") or "-",font,attr or 0,kind,script,language,what,typ,action,sequence.name)
end
- return { valid, attribute, sequence.chain or 0, kind }
+ return { valid, attribute, sequence.chain or 0, kind, sequence }
end
end
end
end
- return false -- { valid, attribute, chain, "generic" } -- false anyway, could be flag instead of table
+ return false -- { valid, attribute, chain, "generic", sequence } -- false anyway, could be flag instead of table
else
- return false -- { false, false, chain } -- indirect lookup, part of chain (todo: make this a separate table)
+ return false -- { false, false, chain, false, sequence } -- indirect lookup, part of chain (todo: make this a separate table)
end
end
-function otf.dataset(tfmdata,sequences,font,attr)
+-- local contextresolved = { }
+--
+-- setmetatableindex(contextresolved, function(t,k)
+-- local v = contextsetups[contextnumbers[k]]
+-- t[k] = v
+-- return v
+-- end)
- local shared = tfmdata.shared
- local properties = tfmdata.properties
+function otf.dataset(tfmdata,sequences,font,attr) -- attr only when explicit (as in special parbuilder)
local script, language, s_enabled, a_enabled, dynamic
if attr and attr ~= 0 then
local features = contextsetups[contextnumbers[attr]] -- could be a direct list
+ -- local features = contextresolved[attr]
language = features.language or "dflt"
script = features.script or "dflt"
a_enabled = features
dynamic = contextmerged[attr] or 0
if dynamic == 2 or dynamic == -2 then
-- font based
- s_enabled = shared.features
+ s_enabled = tfmdata.shared.features
end
else
+ local properties = tfmdata.properties
language = properties.language or "dflt"
script = properties.script or "dflt"
- s_enabled = shared.features -- can be made local to the resolver
+ s_enabled = tfmdata.shared.features -- can be made local to the resolver
dynamic = 0
end
@@ -209,7 +224,7 @@ function otf.dataset(tfmdata,sequences,font,attr)
rl[attr] = ra
setmetatableindex(ra, function(t,k)
local v = initialize(sequences[k],script,language,s_enabled,a_enabled,font,attr,dynamic)
- t[k] = v
+ t[k] = v or false
return v
end)
end
diff --git a/Master/texmf-dist/tex/context/base/font-otf.lua b/Master/texmf-dist/tex/context/base/font-otf.lua
index 36d18a2365f..27a64e91712 100644
--- a/Master/texmf-dist/tex/context/base/font-otf.lua
+++ b/Master/texmf-dist/tex/context/base/font-otf.lua
@@ -12,6 +12,8 @@ if not modules then modules = { } end modules ['font-otf'] = {
-- to_table -> totable
-- ascent descent
+-- more checking against low level calls of functions
+
local utf = unicode.utf8
local utfbyte = utf.byte
@@ -22,7 +24,7 @@ local getn = table.getn
local lpegmatch = lpeg.match
local reversed, concat, remove = table.reversed, table.concat, table.remove
local ioflush = io.flush
-local fastcopy, tohash = table.fastcopy, table.tohash
+local fastcopy, tohash, derivetable = table.fastcopy, table.tohash, table.derive
local allocate = utilities.storage.allocate
local registertracker = trackers.register
@@ -47,7 +49,7 @@ local otf = fonts.handlers.otf
otf.glists = { "gsub", "gpos" }
-otf.version = 2.730 -- beware: also sync font-mis.lua
+otf.version = 2.736 -- beware: also sync font-mis.lua
otf.cache = containers.define("fonts", "otf", otf.version, true)
local fontdata = fonts.hashes.identifiers
@@ -114,15 +116,21 @@ local function showfeatureorder(rawdata,filename)
if features then
for feature, scripts in next, features do
local tt = { }
- for script, languages in next, scripts do
- local ttt = { }
- for language, _ in next, languages do
- ttt[#ttt+1] = language
+ if type(scripts) == "table" then
+ for script, languages in next, scripts do
+ local ttt = { }
+ for language, _ in next, languages do
+ ttt[#ttt+1] = language
+ end
+ tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
+ end
+ if trace_loading then
+ report_otf(" %s: %s",feature,concat(tt," "))
+ end
+ else
+ if trace_loading then
+ report_otf(" %s: %s",feature,tostring(scripts))
end
- tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
- end
- if trace_loading then
- report_otf(" %s: %s",feature,concat(tt," "))
end
end
end
@@ -291,11 +299,14 @@ end
-- patches.register("before","migrate metadata","cambria",function() end)
function patches.register(what,where,pattern,action)
- local ww = what[where]
- if ww then
- ww[pattern] = action
- else
- ww = { [pattern] = action}
+ local pw = patches[what]
+ if pw then
+ local ww = pw[where]
+ if ww then
+ ww[pattern] = action
+ else
+ pw[where] = { [pattern] = action}
+ end
end
end
@@ -336,8 +347,8 @@ function otf.load(filename,format,sub,featurefile)
local attr = lfs.attributes(name)
featurefiles[#featurefiles+1] = {
name = name,
- size = size,
- time = time,
+ size = attr and attr.size or 0,
+ time = attr and attr.modification or 0,
}
end
end
@@ -420,6 +431,9 @@ function otf.load(filename,format,sub,featurefile)
duplicates = {
-- alternative unicodes
},
+ variants = {
+ -- alternative unicodes (variants)
+ },
lookuptypes = {
},
},
@@ -444,6 +458,7 @@ function otf.load(filename,format,sub,featurefile)
if packdata then
if cleanup > 0 then
collectgarbage("collect")
+--~ lua.collectgarbage()
end
enhance("pack",data,filename,nil)
end
@@ -451,6 +466,7 @@ function otf.load(filename,format,sub,featurefile)
data = containers.write(otf.cache, hash, data)
if cleanup > 1 then
collectgarbage("collect")
+--~ lua.collectgarbage()
end
stoptiming(data)
if elapsedtime then -- not in generic
@@ -459,10 +475,12 @@ function otf.load(filename,format,sub,featurefile)
fontloader.close(fontdata) -- free memory
if cleanup > 3 then
collectgarbage("collect")
+--~ lua.collectgarbage()
end
data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
if cleanup > 2 then
collectgarbage("collect")
+--~ lua.collectgarbage()
end
else
data = nil
@@ -499,7 +517,7 @@ local mt = {
}
actions["prepare tables"] = function(data,filename,raw)
- data.properties.italic_correction = false
+ data.properties.hasitalics = false
end
actions["add dimensions"] = function(data,filename)
@@ -584,7 +602,7 @@ local function somecopy(old) -- fast one
end
end
--- not setting italic_correction and class (when nil) during
+-- not setting hasitalics and class (when nil) during
-- table cronstruction can save some mem
actions["prepare glyphs"] = function(data,filename,raw)
@@ -600,6 +618,7 @@ actions["prepare glyphs"] = function(data,filename,raw)
local unicodes = resources.unicodes -- name to unicode
local indices = resources.indices -- index to unicode
local duplicates = resources.duplicates
+ local variants = resources.variants
if rawsubfonts then
@@ -699,11 +718,28 @@ actions["prepare glyphs"] = function(data,filename,raw)
}
local altuni = glyph.altuni
if altuni then
- local d = { }
+ local d
for i=1,#altuni do
- d[#d+1] = altuni[i].unicode
+ local a = altuni[i]
+ local u = a.unicode
+ local v = a.variant
+ if v then
+ local vv = variants[v]
+ if vv then
+ vv[u] = unicode
+ else -- xits-math has some:
+ vv = { [u] = unicode }
+ variants[v] = vv
+ end
+ elseif d then
+ d[#d+1] = u
+ else
+ d = { u }
+ end
+ end
+ if d then
+ duplicates[unicode] = d
end
- duplicates[unicode] = d
end
else
report_otf("potential problem: glyph 0x%04X is used but empty",index)
@@ -725,9 +761,8 @@ actions["check encoding"] = function(data,filename,raw)
local properties = data.properties
local unicodes = resources.unicodes -- name to unicode
local indices = resources.indices -- index to unicodes
- local duplicates = resources.duplicates
- -- begin of messy (not needed whwn cidmap)
+ -- begin of messy (not needed when cidmap)
local mapdata = raw.map or { }
local unicodetoindex = mapdata and mapdata.map or { }
@@ -801,7 +836,6 @@ actions["add duplicates"] = function(data,filename,raw)
end
end
end
-
end
-- class : nil base mark ligature component (maybe we don't need it in description)
@@ -812,9 +846,9 @@ actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this
local resources = data.resources
local metadata = data.metadata
local properties = data.properties
- local italic_correction = false
+ local hasitalics = false
local widths = { }
- local marks = { }
+ local marks = { } -- always present (saves checking)
for unicode, description in next, descriptions do
local glyph = description.glyph
local italic = glyph.italic_correction
@@ -824,7 +858,7 @@ actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this
-- skip
else
description.italic = italic
- italic_correction = true
+ hasitalics = true
end
local width = glyph.width
widths[width] = (widths[width] or 0) + 1
@@ -837,7 +871,7 @@ actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this
end
end
-- flag italic
- properties.italic_correction = italic_correction
+ properties.hasitalics = hasitalics
-- flag marks
resources.marks = marks
-- share most common width for cjk fonts
@@ -959,6 +993,29 @@ actions["prepare tounicode"] = function(data,filename,raw)
fonts.mappings.addtounicode(data,filename)
end
+local g_directions = {
+ gsub_contextchain = 1,
+ gpos_contextchain = 1,
+ -- gsub_context = 1,
+ -- gpos_context = 1,
+ gsub_reversecontextchain = -1,
+ gpos_reversecontextchain = -1,
+}
+
+-- Research by Khaled Hosny has demonstrated that the font loader merges
+-- regular and AAT features and that these can interfere (especially because
+-- we dropped checking for valid features elsewhere. So, we just check for
+-- the special flag and drop the feature if such a tag is found.
+
+local function supported(features)
+ for i=1,#features do
+ if features[i].ismac then
+ return false
+ end
+ end
+ return true
+end
+
actions["reorganize subtables"] = function(data,filename,raw)
local resources = data.resources
local sequences = { }
@@ -971,72 +1028,72 @@ actions["reorganize subtables"] = function(data,filename,raw)
if dw then
for k=1,#dw do
local gk = dw[k]
- local typ = gk.type
- local chain =
- (typ == "gsub_contextchain" or typ == "gpos_contextchain") and 1 or
- (typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain") and -1 or 0
- --
- local subtables = gk.subtables
- if subtables then
- local t = { }
- for s=1,#subtables do
- t[s] = subtables[s].name
+ local features = gk.features
+-- if features and supported(features) then
+ if not features or supported(features) then -- not always features !
+ local typ = gk.type
+ local chain = g_directions[typ] or 0
+ local subtables = gk.subtables
+ if subtables then
+ local t = { }
+ for s=1,#subtables do
+ t[s] = subtables[s].name
+ end
+ subtables = t
end
- subtables = t
- end
- local flags, markclass = gk.flags, nil
- if flags then
- local t = { -- forcing false packs nicer
- (flags.ignorecombiningmarks and "mark") or false,
- (flags.ignoreligatures and "ligature") or false,
- (flags.ignorebaseglyphs and "base") or false,
- flags.r2l or false,
- }
- markclass = flags.mark_class
- if markclass then
- markclass = resources.markclasses[markclass]
+ local flags, markclass = gk.flags, nil
+ if flags then
+ local t = { -- forcing false packs nicer
+ (flags.ignorecombiningmarks and "mark") or false,
+ (flags.ignoreligatures and "ligature") or false,
+ (flags.ignorebaseglyphs and "base") or false,
+ flags.r2l or false,
+ }
+ markclass = flags.mark_class
+ if markclass then
+ markclass = resources.markclasses[markclass]
+ end
+ flags = t
end
- flags = t
- end
- --
- local name = gk.name
- --
- local features = gk.features
- if features then
- -- scripts, tag, ismac
- local f = { }
- for i=1,#features do
- local df = features[i]
- local tag = strip(lower(df.tag))
- local ft = f[tag] if not ft then ft = {} f[tag] = ft end
- local dscripts = df.scripts
- for i=1,#dscripts do
- local d = dscripts[i]
- local languages = d.langs
- local script = strip(lower(d.script))
- local fts = ft[script] if not fts then fts = {} ft[script] = fts end
- for i=1,#languages do
- fts[strip(lower(languages[i]))] = true
+ --
+ local name = gk.name
+ --
+ if features then
+ -- scripts, tag, ismac
+ local f = { }
+ for i=1,#features do
+ local df = features[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag] if not ft then ft = {} f[tag] = ft end
+ local dscripts = df.scripts
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
+ local fts = ft[script] if not fts then fts = {} ft[script] = fts end
+ for i=1,#languages do
+ fts[strip(lower(languages[i]))] = true
+ end
end
end
+ sequences[#sequences+1] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ markclass = markclass,
+ features = f,
+ }
+ else
+ lookups[name] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ subtables = subtables,
+ markclass = markclass,
+ }
end
- sequences[#sequences+1] = {
- type = typ,
- chain = chain,
- flags = flags,
- name = name,
- subtables = subtables,
- markclass = markclass,
- features = f,
- }
- else
- lookups[name] = {
- type = typ,
- chain = chain,
- flags = flags,
- subtables = subtables,
- markclass = markclass,
- }
end
end
end
@@ -1077,19 +1134,20 @@ end
local function t_hashed(t,cache)
if t then
- local h = { }
+ local ht = { }
for i=1,#t do
local ti = t[i]
- local h = cache[ti]
- if not h then
- h = { }
+ local tih = cache[ti]
+ if not tih then
+ tih = { }
for i=1,#ti do
- h[ti] = true
+ tih[ti[i]] = true
end
+ cache[ti] = tih
end
- cache[ti] = h
+ ht[i] = tih
end
- return h
+ return ht
else
return nil
end
@@ -1173,7 +1231,7 @@ actions["reorganize lookups"] = function(data,filename,raw)
for i=1,#current do
current[i] = current_class[current[i]] or { }
if lookups and not lookups[i] then
- lookups[i] = false
+ lookups[i] = false -- e.g. we can have two lookups and one replacement
end
end
rule.current = t_hashed(current,h_cache)
@@ -1270,8 +1328,6 @@ actions["reorganize lookups"] = function(data,filename,raw)
end
end
--- to be checked italic_correction
-
local function check_variants(unicode,the_variants,splitter,unicodes)
local variants = the_variants.variants
if variants then -- use splitter
@@ -1671,9 +1727,9 @@ local function copytotfm(data,cache_id)
if data then
local metadata = data.metadata
local resources = data.resources
- local properties = table.derive(data.properties)
- local descriptions = table.derive(data.descriptions)
- local goodies = table.derive(data.goodies)
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
local characters = { }
local parameters = { }
local mathparameters = { }
@@ -1799,6 +1855,11 @@ local function copytotfm(data,cache_id)
local fullname = metadata.fullname or fontname
local units = metadata.units_per_em or 1000
--
+ if units == 0 then -- catch bugs in fonts
+ units = 1000
+ metadata.units_per_em = 1000
+ end
+ --
parameters.slant = 0
parameters.space = spaceunits -- 3.333 (cmr10)
parameters.space_stretch = units/2 -- 500 -- 1.666 (cmr10)
@@ -1884,9 +1945,9 @@ local function otftotfm(specification)
tfmdata.shared = shared
end
shared.rawdata = rawdata
- shared.features = features -- default
+ -- shared.features = features -- default
shared.dynamics = { }
- shared.processes = { }
+ -- shared.processes = { }
tfmdata.changed = { }
shared.features = features
shared.processes = otf.setfeatures(tfmdata,features)
@@ -1905,7 +1966,8 @@ local function read_from_otf(specification)
tfmdata.properties.sub = specification.sub
--
tfmdata = constructors.scale(tfmdata,specification)
- constructors.applymanipulators("otf",tfmdata,specification.features.normal,trace_features,report_otf)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
constructors.setname(tfmdata,specification) -- only otf?
fonts.loggers.register(tfmdata,file.extname(specification.filename),specification)
end
@@ -1971,15 +2033,15 @@ local function check_otf(forced,specification,suffix,what)
if forced then
name = file.addsuffix(name,suffix,true)
end
- local fullname, tfmdata = findbinfile(name,suffix) or "", nil -- one shot
+ local fullname = findbinfile(name,suffix) or ""
if fullname == "" then
- fullname = fonts.names.getfilename(name,suffix)
+ fullname = fonts.names.getfilename(name,suffix) or ""
end
if fullname ~= "" then
- specification.filename, specification.format = fullname, what -- hm, so we do set the filename, then
- tfmdata = read_from_otf(specification) -- we need to do it for all matches / todo
+ specification.filename = fullname
+ specification.format = what
+ return read_from_otf(specification)
end
- return tfmdata
end
local function opentypereader(specification,suffix,what)
diff --git a/Master/texmf-dist/tex/context/base/font-otn.lua b/Master/texmf-dist/tex/context/base/font-otn.lua
index 81b3fd267cc..8e675974796 100644
--- a/Master/texmf-dist/tex/context/base/font-otn.lua
+++ b/Master/texmf-dist/tex/context/base/font-otn.lua
@@ -27,6 +27,7 @@ if not modules then modules = { } end modules ['font-otn'] = {
-- default features (per language, script)
-- handle positions (we need example fonts)
-- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
+-- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
--[[ldx--
<p>This module is a bit more split up that I'd like but since we also want to test
@@ -123,25 +124,27 @@ local random = math.random
local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
+local registertracker = trackers.register
+
local fonts = fonts
local otf = fonts.handlers.otf
-local trace_lookups = false trackers.register("otf.lookups", function(v) trace_lookups = v end)
-local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
-local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end)
-local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end)
-local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end)
-local trace_contexts = false trackers.register("otf.contexts", function(v) trace_contexts = v end)
-local trace_marks = false trackers.register("otf.marks", function(v) trace_marks = v end)
-local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
-local trace_cursive = false trackers.register("otf.cursive", function(v) trace_cursive = v end)
-local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
-local trace_bugs = false trackers.register("otf.bugs", function(v) trace_bugs = v end)
-local trace_details = false trackers.register("otf.details", function(v) trace_details = v end)
-local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end)
-local trace_steps = false trackers.register("otf.steps", function(v) trace_steps = v end)
-local trace_skips = false trackers.register("otf.skips", function(v) trace_skips = v end)
-local trace_directions = false trackers.register("otf.directions", function(v) trace_directions = v end)
+local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end)
+local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end)
+local trace_multiples = false registertracker("otf.multiples", function(v) trace_multiples = v end)
+local trace_alternatives = false registertracker("otf.alternatives", function(v) trace_alternatives = v end)
+local trace_ligatures = false registertracker("otf.ligatures", function(v) trace_ligatures = v end)
+local trace_contexts = false registertracker("otf.contexts", function(v) trace_contexts = v end)
+local trace_marks = false registertracker("otf.marks", function(v) trace_marks = v end)
+local trace_kerns = false registertracker("otf.kerns", function(v) trace_kerns = v end)
+local trace_cursive = false registertracker("otf.cursive", function(v) trace_cursive = v end)
+local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
+local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
+local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
+local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
+local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
+local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
+local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
local report_direct = logs.reporter("fonts","otf direct")
local report_subchain = logs.reporter("fonts","otf subchain")
@@ -149,15 +152,15 @@ local report_chain = logs.reporter("fonts","otf chain")
local report_process = logs.reporter("fonts","otf process")
local report_prepare = logs.reporter("fonts","otf prepare")
-trackers.register("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
-trackers.register("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
+registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
+registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
-trackers.register("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
-trackers.register("otf.positions","otf.marks,otf.kerns,otf.cursive")
-trackers.register("otf.actions","otf.replacements,otf.positions")
-trackers.register("otf.injections","nodes.injections")
+registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
+registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
+registertracker("otf.actions","otf.replacements,otf.positions")
+registertracker("otf.injections","nodes.injections")
-trackers.register("*otf.sample","otf.steps,otf.actions,otf.analyzing")
+registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
local insert_node_after = node.insert_after
local delete_node = nodes.delete
@@ -165,6 +168,7 @@ local copy_node = node.copy
local find_node_tail = node.tail or node.slide
local set_attribute = node.set_attribute
local has_attribute = node.has_attribute
+local flush_node_list = node.flush_list
local setmetatableindex = table.setmetatableindex
@@ -189,14 +193,21 @@ local ligature_code = glyphcodes.ligature
local privateattribute = attributes.private
+-- Something is messed up: we have two mark / ligature indices, one at the injection
+-- end and one here ... this is bases in KE's patches but there is something fishy
+-- there as I'm pretty sure that for husayni we need some connection (as it's much
+-- more complex than an average font) but I need proper examples of all cases, not
+-- of only some.
+
local state = privateattribute('state')
local markbase = privateattribute('markbase')
local markmark = privateattribute('markmark')
-local markdone = privateattribute('markdone')
+local markdone = privateattribute('markdone') -- assigned at the injection end
local cursbase = privateattribute('cursbase')
local curscurs = privateattribute('curscurs')
local cursdone = privateattribute('cursdone')
local kernpair = privateattribute('kernpair')
+local ligacomp = privateattribute('ligacomp') -- assigned here (ideally it should be combined)
local injections = nodes.injections
local setmark = injections.setmark
@@ -216,6 +227,8 @@ local registerotffeature = otffeatures.register
local onetimemessage = fonts.loggers.onetimemessage
+otf.defaultnodealternate = "none" -- first last
+
-- we share some vars here, after all, we have no nested lookups and
-- less code
@@ -318,21 +331,35 @@ end
local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
if start == stop then
start.char = char
+ return start
elseif discfound then
-- print("start->stop",nodes.tosequence(start,stop))
+ local components = start.components
+ if components then
+ flush_node_list(components)
+ start.components = nil
+ end
local lignode = copy_node(start)
- lignode.font, lignode.char, lignode.subtype = start.font, char, ligature_code
- local next, prev = stop.next, start.prev
+ lignode.font = start.font
+ lignode.char = char
+ lignode.subtype = ligature_code
+ local next = stop.next
+ local prev = start.prev
stop.next = nil
- lignode = node.do_ligature_n(start, stop, lignode)
+ start.prev = nil
+ lignode.components = start
+ -- print("lignode",nodes.tosequence(lignode))
+ -- print("components",nodes.tosequence(lignode.components))
prev.next = lignode
if next then
next.prev = lignode
end
- lignode.next, lignode.prev = next, prev
- start = lignode
+ lignode.next = next
+ lignode.prev = prev
-- print("start->end",nodes.tosequence(start))
- else -- start is the ligature
+ return lignode
+ else
+ -- start is the ligature
local deletemarks = markflag ~= "mark"
local n = copy_node(start)
local current
@@ -342,48 +369,46 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) --
if snext then
snext.prev = current
end
- start.prev, stop.next = nil, nil
- current.char, current.subtype, current.components = char, ligature_code, start
+ start.prev = nil
+ stop.next = nil
+ current.char = char
+ current.subtype = ligature_code
+ current.components = start
local head = current
- if deletemarks then
- if trace_marks then
- while start do
- if marks[start.char] then
- logwarning("%s: remove mark %s",pref(kind,lookupname),gref(start.char))
- end
- start = start.next
+ -- this is messy ... we should get rid of the components eventually
+ local i = 0 -- is index of base
+ while start do
+ if not marks[start.char] then
+ i = i + 1
+ elseif not deletemarks then -- quite fishy
+ set_attribute(start,ligacomp,i)
+ if trace_marks then
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
end
+ head, current = insert_node_after(head,current,copy_node(start))
end
- else
- local i = 0
- while start do
- if marks[start.char] then
- set_attribute(start,markdone,i)
- if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
- end
- head, current = insert_node_after(head,current,copy_node(start))
- else
- i = i + 1
- end
- start = start.next
- end
- start = current.next
- while start and start.id == glyph_code do
- if marks[start.char] then
- set_attribute(start,markdone,i)
- if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
- end
- else
- break
+ start = start.next
+ end
+ start = current.next
+ while start and start.id == glyph_code do
+ if marks[start.char] then
+ set_attribute(start,ligacomp,i)
+ if trace_marks then
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
end
- start = start.next
+ else
+ break
end
+ start = start.next
end
+ --
+ -- we do need components in funny kerning mode but maybe I can better reconstruct then
+ -- as we do have the font components info available; removing components makes the
+ -- previous code much simpler
+ --
+ -- flush_node_list(head.components)
return head
end
- return start
end
function handlers.gsub_single(start,kind,lookupname,replacement)
@@ -394,8 +419,12 @@ function handlers.gsub_single(start,kind,lookupname,replacement)
return start, true
end
-local function alternative_glyph(start,alternatives,kind,chainname,chainlookupname,lookupname) -- chainname and chainlookupname optional
- local value, choice, n = featurevalue or tfmdata.shared.features[kind], nil, #alternatives -- global value, brrr
+local function get_alternative_glyph(start,alternatives,value)
+ -- needs checking: (global value, brrr)
+ local choice = nil
+ local n = #alternatives
+ local char = start.char
+ --
if value == "random" then
local r = random(1,n)
value, choice = format("random, choice %s",r), alternatives[r]
@@ -408,23 +437,26 @@ local function alternative_glyph(start,alternatives,kind,chainname,chainlookupna
if type(value) ~= "number" then
value, choice = "default, choice 1", alternatives[1]
elseif value > n then
- value, choice = format("no %s variants, taking %s",value,n), alternatives[n]
+ local defaultalt = otf.defaultnodealternate
+ if defaultalt == "first" then
+ value, choice = format("no %s variants, taking %s",value,n), alternatives[n]
+ elseif defaultalt == "last" then
+ value, choice = format("no %s variants, taking %s",value,1), alternatives[1]
+ else
+ value, choice = format("no %s variants, ignoring",value), false
+ end
elseif value == 0 then
- value, choice = format("choice %s (no change)",value), start.char
+ value, choice = format("choice %s (no change)",value), char
elseif value < 1 then
value, choice = format("no %s variants, taking %s",value,1), alternatives[1]
else
value, choice = format("choice %s",value), alternatives[value]
end
end
- if not choice then
- logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(start.char))
- choice, value = start.char, format("no replacement instead of %s",value)
- end
- return choice, value
+ return choice
end
-local function multiple_glyphs(start,multiple)
+local function multiple_glyphs(start,multiple) -- marks ?
local nofmultiples = #multiple
if nofmultiples > 0 then
start.char = multiple[1]
@@ -452,11 +484,18 @@ local function multiple_glyphs(start,multiple)
end
function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence)
- local choice, index = alternative_glyph(start,alternative,kind,lookupname)
- if trace_alternatives then
- logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),index)
+ local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
+ local choice = get_alternative_glyph(start,alternative,value)
+ if choice then
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(char),gref(choice),choice)
+ end
+ start.char = choice
+ else
+ if trace_alternatives then
+ logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(char))
+ end
end
- start.char = choice
return start, true
end
@@ -619,18 +658,14 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
local markchar = start.char
if marks[markchar] then
local base = start.prev -- [glyph] [optional marks] [start=mark]
- local index = 1
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
local basechar = base.char
if marks[basechar] then
- index = index + 1
while true do
base = base.prev
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
basechar = base.char
- if marks[basechar] then
- index = index + 1
- else
+ if not marks[basechar] then
break
end
else
@@ -641,8 +676,7 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
end
end
end
- local i = has_attribute(start,markdone)
- if i then index = i end
+ local index = has_attribute(start,ligacomp)
local baseanchors = descriptions[basechar]
if baseanchors then
baseanchors = baseanchors.anchors
@@ -656,7 +690,7 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
if ma then
ba = ba[index]
if ba then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,index)
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma) -- index
if trace_marks then
logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)",
pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -687,46 +721,55 @@ end
function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence)
local markchar = start.char
if marks[markchar] then
---~ local alreadydone = markonce and has_attribute(start,markmark)
---~ if not alreadydone then
- local base = start.prev -- [glyph] [basemark] [start=mark]
- if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then -- subtype test can go
- local basechar = base.char
- local baseanchors = descriptions[basechar]
+ local base = start.prev -- [glyph] [basemark] [start=mark]
+ -- while base and has_attribute(base,ligacomp) and has_attribute(base,ligacomp) ~= has_attribute(start,ligacomp) do
+ -- base = base.prev -- KE: prevents mkmk for marks on different components of a ligature
+ -- end
+ local slc = has_attribute(start,ligacomp)
+ if slc then -- a rather messy loop ... needs checking with husayni
+ while base do
+ local blc = has_attribute(base,ligacomp)
+ if blc and blc ~= slc then
+ base = base.prev
+ else
+ break
+ end
+ end
+ end
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then -- subtype test can go
+ local basechar = base.char
+ local baseanchors = descriptions[basechar]
+ if baseanchors then
+ baseanchors = baseanchors.anchors
if baseanchors then
- baseanchors = baseanchors.anchors
+ baseanchors = baseanchors['basemark']
if baseanchors then
- baseanchors = baseanchors['basemark']
- if baseanchors then
- local al = anchorlookups[lookupname]
- for anchor,ba in next, baseanchors do
- if al[anchor] then
- local ma = markanchors[anchor]
- if ma then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)",
- pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return start,true
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)",
+ pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
end
+ return start,true
end
end
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar))
- end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar))
end
end
- else -- if trace_bugs then
- -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
- onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
end
- elseif trace_bugs then
- logwarning("%s: prev node is no mark",pref(kind,lookupname))
+ else -- if trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
+ onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
end
---~ elseif trace_marks and trace_details then
---~ logprocess("%s, mark %s is already bound (n=%s), ignoring mark2mark",pref(kind,lookupname),gref(markchar),alreadydone)
---~ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark",pref(kind,lookupname))
+ end
elseif trace_bugs then
logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
end
@@ -880,33 +923,6 @@ end
local logwarning = report_subchain
-function chainmores.chainsub(start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
- logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
- return start, false
-end
-
--- handled later:
---
--- function chainmores.gsub_single(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
--- return chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
--- end
-
-function chainmores.gsub_multiple(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
- logprocess("%s: gsub_multiple not yet supported",cref(kind,chainname,chainlookupname))
- return start, false
-end
-
-function chainmores.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
- logprocess("%s: gsub_alternate not yet supported",cref(kind,chainname,chainlookupname))
- return start, false
-end
-
--- handled later:
---
--- function chainmores.gsub_ligature(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
--- return chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
--- end
-
local function logprocess(...)
if trace_steps then
registermessage(...)
@@ -924,6 +940,11 @@ function chainprocs.chainsub(start,stop,kind,chainname,currentcontext,lookuphash
return start, false
end
+function chainmores.chainsub(start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
+ logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
+ return start, false
+end
+
-- The reversesub is a special case, which is why we need to store the replacements
-- in a bit weird way. There is no lookup and the replacement comes from the lookup
-- itself. It is meant mostly for dealing with Urdu.
@@ -955,17 +976,29 @@ example, the following is valid:</p>
<p>Therefore we we don't really do the replacement here already unless we have the
single lookup case. The efficiency of the replacements can be improved by deleting
-as less as needed but that would also mke the code even more messy.</p>
+as less as needed but that would also make the code even more messy.</p>
--ldx]]--
-local function delete_till_stop(start,stop,ignoremarks)
- if start ~= stop then
- -- todo keep marks
+local function delete_till_stop(start,stop,ignoremarks) -- keeps start
+ local n = 1
+ if start == stop then
+ -- done
+ elseif ignoremarks then
+ repeat -- start x x m x x stop => start m
+ local next = start.next
+ if not marks[next.char] then
+ delete_node(start,next)
+ end
+ n = n + 1
+ until next == stop
+ else -- start x x x stop => start
repeat
local next = start.next
delete_node(start,next)
+ n = n + 1
until next == stop
end
+ return n
end
--[[ldx--
@@ -975,10 +1008,6 @@ match.</p>
function chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
-- todo: marks ?
---~ if not chainindex then
---~ delete_till_stop(start,stop) -- ,currentlookup.flags[1]
---~ stop = start
---~ end
local current = start
local subtables = currentlookup.subtables
if #subtables > 1 then
@@ -1024,7 +1053,7 @@ the match.</p>
--ldx]]--
function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- delete_till_stop(start,stop)
+ delete_till_stop(start,stop) -- we could pass ignoremarks as #3 ..
local startchar = start.char
local subtables = currentlookup.subtables
local lookupname = subtables[1]
@@ -1049,36 +1078,54 @@ function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,looku
return start, false
end
+-- function chainmores.gsub_multiple(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
+-- logprocess("%s: gsub_multiple not yet supported",cref(kind,chainname,chainlookupname))
+-- return start, false
+-- end
+
+chainmores.gsub_multiple = chainprocs.gsub_multiple
+
--[[ldx--
<p>Here we replace start by new glyph. First we delete the rest of the match.</p>
--ldx]]--
+-- char_1 mark_1 -> char_x mark_1 (ignore marks)
+-- char_1 mark_1 -> char_x
+
+-- to be checked: do we always have just one glyph?
+-- we can also have alternates for marks
+-- marks come last anyway
+-- are there cases where we need to delete the mark
+
function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- -- todo: marks ?
- delete_till_stop(start,stop)
local current = start
local subtables = currentlookup.subtables
+ local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
while current do
- if current.id == glyph_code then
+ if current.id == glyph_code then -- is this check needed?
local currentchar = current.char
local lookupname = subtables[1]
local alternatives = lookuphash[lookupname]
if not alternatives then
if trace_bugs then
- logwarning("%s: no alternative hits",cref(kind,chainname,chainlookupname,lookupname))
+ logwarning("%s: no alternative hit",cref(kind,chainname,chainlookupname,lookupname))
end
else
alternatives = alternatives[currentchar]
- if not alternatives then
- if trace_bugs then
- logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar))
- end
- else
- local choice, index = alternative_glyph(current,alternatives,kind,chainname,chainlookupname,lookupname)
- current.char = choice
- if trace_alternatives then
- logprocess("%s: replacing single %s by alternative %s (%s)",cref(kind,chainname,chainlookupname,lookupname),index,gref(currentchar),gref(choice),index)
+ if alternatives then
+ local choice = get_alternative_glyph(current,alternatives,value)
+ if choice then
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %s (%s)",cref(kind,chainname,chainlookupname,lookupname),gref(char),gref(choice),choice)
+ end
+ start.char = choice
+ else
+ if trace_alternatives then
+ logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),tostring(value),gref(char))
+ end
end
+ elseif trace_bugs then
+ logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar))
end
end
return start, true
@@ -1091,6 +1138,13 @@ function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,look
return start, false
end
+-- function chainmores.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
+-- logprocess("%s: gsub_alternate not yet supported",cref(kind,chainname,chainlookupname))
+-- return start, false
+-- end
+
+chainmores.gsub_alternate = chainprocs.gsub_alternate
+
--[[ldx--
<p>When we replace ligatures we use a helper that handles the marks. I might change
this function (move code inline and handle the marks by a separate function). We
@@ -1241,18 +1295,14 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,
end
if markanchors then
local base = start.prev -- [glyph] [optional marks] [start=mark]
- local index = 1
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
local basechar = base.char
if marks[basechar] then
- index = index + 1
while true do
base = base.prev
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
basechar = base.char
- if marks[basechar] then
- index = index + 1
- else
+ if not marks[basechar] then
break
end
else
@@ -1264,8 +1314,7 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,
end
end
-- todo: like marks a ligatures hash
- local i = has_attribute(start,markdone)
- if i then index = i end
+ local index = has_attribute(start,ligacomp)
local baseanchors = descriptions[basechar].anchors
if baseanchors then
local baseanchors = baseanchors['baselig']
@@ -1277,7 +1326,7 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,
if ma then
ba = ba[index]
if ba then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,index)
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma) -- index
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)",
cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -1318,6 +1367,20 @@ function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,look
end
if markanchors then
local base = start.prev -- [glyph] [basemark] [start=mark]
+ -- while (base and has_attribute(base,ligacomp) and has_attribute(base,ligacomp) ~= has_attribute(start,ligacomp)) do
+ -- base = base.prev -- KE: prevents mkmk for marks on different components of a ligature
+ -- end
+ local slc = has_attribute(start,ligacomp)
+ if slc then -- a rather messy loop ... needs checking with husayni
+ while base do
+ local blc = has_attribute(base,ligacomp)
+ if blc and blc ~= slc then
+ base = base.prev
+ else
+ break
+ end
+ end
+ end
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then -- subtype test can go
local basechar = base.char
local baseanchors = descriptions[basechar].anchors
@@ -1534,36 +1597,40 @@ end
local function normal_handle_contextchain(start,kind,chainname,contexts,sequence,lookuphash)
-- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6]
- local flags, done = sequence.flags, false
- local skipmark, skipligature, skipbase = flags[1], flags[2], flags[3]
- local someskip = skipmark or skipligature or skipbase -- could be stored in flags for a fast test (hm, flags could be false !)
- local markclass = sequence.markclass -- todo, first we need a proper test
- local skipped = false
+ local flags = sequence.flags
+ local done = false
+ local skipmark = flags[1]
+ local skipligature = flags[2]
+ local skipbase = flags[3]
+ local someskip = skipmark or skipligature or skipbase -- could be stored in flags for a fast test (hm, flags could be false !)
+ local markclass = sequence.markclass -- todo, first we need a proper test
+ local skipped = false
for k=1,#contexts do
- local match, current, last = true, start, start
- local ck = contexts[k]
- local seq = ck[3]
- local s = #seq
+ local match = true
+ local current = start
+ local last = start
+ local ck = contexts[k]
+ local seq = ck[3]
+ local s = #seq
-- f..l = mid string
if s == 1 then
-- never happens
match = current.id == glyph_code and current.subtype<256 and current.font == currentfont and seq[1][current.char]
else
- -- todo: better space check (maybe check for glue)
+ -- maybe we need a better space check (maybe check for glue or category or combination)
+ -- we cannot optimize for n=2 because there can be disc nodes
local f, l = ck[4], ck[5]
-- current match
- if f == 1 and f == l then
+ if f == 1 and f == l then -- current only
-- already a hit
- match = true
- else
+ -- match = true
+ else -- before/current/after | before/current | current/after
-- no need to test first hit (to be optimized)
- local n = f + 1
- last = last.next
- -- we cannot optimize for n=2 because there can be disc nodes
- -- if not someskip and n == l then
- -- -- n=2 and no skips then faster loop
- -- match = last and last.id == glyph_code and last.subtype<256 and last.font == currentfont and seq[n][last.char]
- -- else
+ if f == l then -- new, else last out of sync (f is > 1)
+ -- match = true
+ else
+ local n = f + 1
+ last = last.next
while n <= l do
if last then
local id = last.id
@@ -1585,24 +1652,29 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
end
n = n + 1
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
- elseif id == disc_code then -- what to do with kerns?
+ elseif id == disc_code then
last = last.next
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
end
- -- end
+ end
end
-- before
if match and f > 1 then
@@ -1626,26 +1698,31 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
elseif seq[n][char] then
n = n -1
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
elseif id == disc_code then
-- skip 'm
elseif seq[n][32] then
n = n -1
else
- match = false break
+ match = false
+ break
end
prev = prev.prev
elseif seq[n][32] then -- somehat special, as zapfino can have many preceding spaces
n = n -1
else
- match = false break
+ match = false
+ break
end
end
elseif f == 2 then
@@ -1653,7 +1730,8 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
else
for n=f-1,1 do
if not seq[n][32] then
- match = false break
+ match = false
+ break
end
end
end
@@ -1681,26 +1759,31 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
elseif seq[n][char] then
n = n + 1
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
elseif id == disc_code then
-- skip 'm
elseif seq[n][32] then -- brrr
n = n + 1
else
- match = false break
+ match = false
+ break
end
current = current.next
elseif seq[n][32] then
n = n + 1
else
- match = false break
+ match = false
+ break
end
end
elseif s-l == 1 then
@@ -1708,7 +1791,8 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
else
for n=l+1,s do
if not seq[n][32] then
- match = false break
+ match = false
+ break
end
end
end
@@ -1734,11 +1818,15 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
if nofchainlookups == 1 then
local chainlookupname = chainlookups[1]
local chainlookup = lookuptable[chainlookupname]
- local cp = chainprocs[chainlookup.type]
- if cp then
- start, done = cp(start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
- else
- logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ if chainlookup then
+ local cp = chainprocs[chainlookup.type]
+ if cp then
+ start, done = cp(start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ else
+ logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ end
+ else -- shouldn't happen
+ logprocess("%s is not yet supported",cref(kind,chainname,chainlookupname))
end
else
local i = 1
@@ -1760,8 +1848,8 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
end
end
local chainlookupname = chainlookups[i]
- local chainlookup = lookuptable[chainlookupname]
- local cp = chainmores[chainlookup.type]
+ local chainlookup = lookuptable[chainlookupname] -- can be false (n matches, <n replacement)
+ local cp = chainlookup and chainmores[chainlookup.type]
if cp then
local ok, n
start, ok, n = cp(start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
@@ -1774,7 +1862,8 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
i = i + 1
end
else
- logprocess("%s: multiple subchains for %s are not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ -- is valid
+ -- logprocess("%s: multiple subchains for %s are not yet supported",cref(kind,chainname,chainlookupname),chainlookup and chainlookup.type or "?")
i = i + 1
end
start = start.next
@@ -1884,7 +1973,7 @@ local function initialize(sequence,script,language,enabled)
if valid then
local languages = scripts[script] or scripts[wildcard]
if languages and (languages[language] or languages[wildcard]) then
- return { valid, special_attributes[kind] or false, sequence.chain or 0, kind }
+ return { valid, special_attributes[kind] or false, sequence.chain or 0, kind, sequence }
end
end
end
@@ -1892,7 +1981,7 @@ local function initialize(sequence,script,language,enabled)
return false
end
-function otf.dataset(ftfmdata,sequences,font) -- generic variant, overloaded in context
+function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in context
local shared = tfmdata.shared
local properties = tfmdata.properties
local language = properties.language or "dflt"
@@ -1921,6 +2010,22 @@ function otf.dataset(ftfmdata,sequences,font) -- generic variant, overloaded in
return rl
end
+-- elseif id == glue_code then
+-- if p[5] then -- chain
+-- local pc = pp[32]
+-- if pc then
+-- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
+-- if ok then
+-- done = true
+-- end
+-- if start then start = start.next end
+-- else
+-- start = start.next
+-- end
+-- else
+-- start = start.next
+-- end
+
local function featuresprocessor(head,font,attr)
local lookuphash = lookuphashes[font] -- we can also check sequences here
@@ -1950,67 +2055,147 @@ local function featuresprocessor(head,font,attr)
local done = false
local datasets = otf.dataset(tfmdata,sequences,font,attr)
+ local dirstack = { } -- could move outside function
+
+ -- We could work on sub start-stop ranges instead but I wonder if there is that
+ -- much speed gain (experiments showed that it made not much sense) and we need
+ -- to keep track of directions anyway. Also at some point I want to play with
+ -- font interactions and then we do need the full sweeps.
+
for s=1,#sequences do
- local pardir, txtdir, success = 0, { }, false -- we could reuse txtdir and use a top pointer
- local sequence = sequences[s]
- local dataset = datasets[s] -- cache
- featurevalue = dataset and dataset[1] -- todo: pass to function instead of using a global
- if featurevalue then
- local attribute, chain, typ, subtables = dataset[2], dataset[3], sequence.type, sequence.subtables
---~ print(typ)
---~ table.print(table.keys(sequence))
- if chain < 0 then
- -- this is a limited case, no special treatments like 'init' etc
- local handler = handlers[typ]
- -- we need to get rid of this slide !
- local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
- while start do
- local id = start.id
- if id == glyph_code then
- if start.subtype<256 and start.font == font then
- local a = has_attribute(start,0)
- if a then
- a = a == attr
- else
- a = true
- end
- if a then
- for i=1,#subtables do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[start.char]
- if lookupmatch then
- start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
- if success then
- break
+ local dataset = datasets[s]
+ if dataset then
+ featurevalue = dataset[1] -- todo: pass to function instead of using a global
+ if featurevalue then
+ local sequence = sequences[s] -- also dataset[5]
+ local rlparmode = 0
+ local topstack = 0
+ local success = false
+ local attribute = dataset[2]
+ local chain = dataset[3] -- sequence.chain or 0
+ local typ = sequence.type
+ local subtables = sequence.subtables
+ if chain < 0 then
+ -- this is a limited case, no special treatments like 'init' etc
+ local handler = handlers[typ]
+ -- we need to get rid of this slide! probably no longer needed in latest luatex
+ local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
+ while start do
+ local id = start.id
+ if id == glyph_code then
+ if start.subtype<256 and start.font == font then
+ local a = has_attribute(start,0)
+ if a then
+ a = a == attr
+ else
+ a = true
+ end
+ if a then
+ for i=1,#subtables do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ if success then
+ break
+ end
end
+ else
+ report_missing_cache(typ,lookupname)
end
- else
- report_missing_cache(typ,lookupname)
end
+ if start then start = start.prev end
+ else
+ start = start.prev
end
- if start then start = start.prev end
else
start = start.prev
end
else
start = start.prev
end
- else
- start = start.prev
end
- end
- else
- local handler = handlers[typ]
- local ns = #subtables
- local start = head -- local ?
- rlmode = 0 -- to be checked ?
- if ns == 1 then
- local lookupname = subtables[1]
- local lookupcache = lookuphash[lookupname]
- if not lookupcache then
- report_missing_cache(typ,lookupname)
+ else
+ local handler = handlers[typ]
+ local ns = #subtables
+ local start = head -- local ?
+ rlmode = 0 -- to be checked ?
+ if ns == 1 then -- happens often
+ local lookupname = subtables[1]
+ local lookupcache = lookuphash[lookupname]
+ if not lookupcache then -- also check for empty cache
+ report_missing_cache(typ,lookupname)
+ else
+ while start do
+ local id = start.id
+ if id == glyph_code then
+ if start.subtype<256 and start.font == font then
+ local a = has_attribute(start,0)
+ if a then
+ a = (a == attr) and (not attribute or has_attribute(start,state,attribute))
+ else
+ a = not attribute or has_attribute(start,state,attribute)
+ end
+ if a then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ -- sequence kan weg
+ local ok
+ start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ success = true
+ end
+ end
+ if start then start = start.next end
+ else
+ start = start.next
+ end
+ else
+ start = start.next
+ end
+ elseif id == whatsit_code then -- will be function
+ local subtype = start.subtype
+ if subtype == dir_code then
+ local dir = start.dir
+ if dir == "+TRT" or dir == "+TLT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ elseif dir == "-TRT" or dir == "-TLT" then
+ topstack = topstack - 1
+ end
+ local newdir = dirstack[topstack]
+ if newdir == "+TRT" then
+ rlmode = -1
+ elseif newdir == "+TLT" then
+ rlmode = 1
+ else
+ rlmode = rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %s: txtdir=%s:%s, parmode=%s, txtmode=%s",dir,topstack,newdir or "unset",rlparmode,rlmode)
+ end
+ elseif subtype == localpar_code then
+ local dir = start.dir
+ if dir == "TRT" then
+ rlparmode = -1
+ elseif dir == "TLT" then
+ rlparmode = 1
+ else
+ rlparmode = 0
+ end
+ rlmode = rlparmode
+ if trace_directions then
+ report_process("directions after pardir %s: parmode=%s, txtmode=%s",dir,rlparmode,rlmode)
+ end
+ end
+ start = start.next
+ else
+ start = start.next
+ end
+ end
+ end
else
while start do
local id = start.id
@@ -2023,13 +2208,22 @@ local function featuresprocessor(head,font,attr)
a = not attribute or has_attribute(start,state,attribute)
end
if a then
- local lookupmatch = lookupcache[start.char]
- if lookupmatch then
- -- sequence kan weg
- local ok
- start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- success = true
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local ok
+ start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ success = true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
end
end
if start then start = start.next end
@@ -2039,54 +2233,39 @@ local function featuresprocessor(head,font,attr)
else
start = start.next
end
- -- elseif id == glue_code then
- -- if p[5] then -- chain
- -- local pc = pp[32]
- -- if pc then
- -- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
- -- if ok then
- -- done = true
- -- end
- -- if start then start = start.next end
- -- else
- -- start = start.next
- -- end
- -- else
- -- start = start.next
- -- end
elseif id == whatsit_code then
local subtype = start.subtype
if subtype == dir_code then
local dir = start.dir
if dir == "+TRT" or dir == "+TLT" then
- insert(txtdir,dir)
+ topstack = topstack + 1
+ dirstack[topstack] = dir
elseif dir == "-TRT" or dir == "-TLT" then
- remove(txtdir)
+ topstack = topstack - 1
end
- local d = txtdir[#txtdir]
- if d == "+TRT" then
+ local newdir = dirstack[topstack]
+ if newdir == "+TRT" then
rlmode = -1
- elseif d == "+TLT" then
+ elseif newdir == "+TLT" then
rlmode = 1
else
- rlmode = pardir
+ rlmode = rlparmode
end
if trace_directions then
- report_process("directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ report_process("directions after txtdir %s: txtdir=%s:%s, parmode=%s, txtmode=%s",dir,topstack,newdir or "unset",rlparmode,rlmode)
end
elseif subtype == localpar_code then
local dir = start.dir
if dir == "TRT" then
- pardir = -1
+ rlparmode = -1
elseif dir == "TLT" then
- pardir = 1
+ rlparmode = 1
else
- pardir = 0
+ rlparmode = 0
end
- rlmode = pardir
- --~ txtdir = { }
+ rlmode = rlparmode
if trace_directions then
- report_process("directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ report_process("directions after pardir %s: parmode=%s, txtmode=%s",dir,rlparmode,rlmode)
end
end
start = start.next
@@ -2095,105 +2274,13 @@ local function featuresprocessor(head,font,attr)
end
end
end
- else
- while start do
- local id = start.id
- if id == glyph_code then
- if start.subtype<256 and start.font == font then
- local a = has_attribute(start,0)
- if a then
- a = (a == attr) and (not attribute or has_attribute(start,state,attribute))
- else
- a = not attribute or has_attribute(start,state,attribute)
- end
- if a then
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[start.char]
- if lookupmatch then
- -- we could move all code inline but that makes things even more unreadable
- local ok
- start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- success = true
- break
- end
- end
- else
- report_missing_cache(typ,lookupname)
- end
- end
- if start then start = start.next end
- else
- start = start.next
- end
- else
- start = start.next
- end
- -- elseif id == glue_code then
- -- if p[5] then -- chain
- -- local pc = pp[32]
- -- if pc then
- -- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
- -- if ok then
- -- done = true
- -- end
- -- if start then start = start.next end
- -- else
- -- start = start.next
- -- end
- -- else
- -- start = start.next
- -- end
- elseif id == whatsit_code then
- local subtype = start.subtype
- if subtype == dir_code then
- local dir = start.dir
- if dir == "+TRT" or dir == "+TLT" then
- insert(txtdir,dir)
- elseif dir == "-TRT" or dir == "-TLT" then
- remove(txtdir)
- end
- local d = txtdir[#txtdir]
- if d == "+TRT" then
- rlmode = -1
- elseif d == "+TLT" then
- rlmode = 1
- else
- rlmode = pardir
- end
- if trace_directions then
- report_process("directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
- end
- elseif subtype == localpar_code then
- local dir = start.dir
- if dir == "TRT" then
- pardir = -1
- elseif dir == "TLT" then
- pardir = 1
- else
- pardir = 0
- end
- rlmode = pardir
- --~ txtdir = { }
- if trace_directions then
- report_process("directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
- end
- end
- start = start.next
- else
- start = start.next
- end
- end
end
- end
- if success then
- done = true
- end
- if trace_steps then -- ?
- registerstep(head)
+ if success then
+ done = true
+ end
+ if trace_steps then -- ?
+ registerstep(head)
+ end
end
end
end
@@ -2272,55 +2359,59 @@ local function prepare_lookups(tfmdata)
local description = descriptions[unicode]
- local lookups = description.slookups
- if lookups then
- for lookupname, lookupdata in next, lookups do
- action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash)
+ if description then
+
+ local lookups = description.slookups
+ if lookups then
+ for lookupname, lookupdata in next, lookups do
+ action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash)
+ end
end
- end
- local lookups = description.mlookups
- if lookups then
- for lookupname, lookuplist in next, lookups do
- local lookuptype = lookuptypes[lookupname]
- for l=1,#lookuplist do
- local lookupdata = lookuplist[l]
- action[lookuptype](lookupdata,lookupname,unicode,lookuphash)
+ local lookups = description.mlookups
+ if lookups then
+ for lookupname, lookuplist in next, lookups do
+ local lookuptype = lookuptypes[lookupname]
+ for l=1,#lookuplist do
+ local lookupdata = lookuplist[l]
+ action[lookuptype](lookupdata,lookupname,unicode,lookuphash)
+ end
end
end
- end
- local list = description.kerns
- if list then
- for lookup, krn in next, list do -- ref to glyph, saves lookup
- local target = lookuphash[lookup]
- if target then
- target[unicode] = krn
- else
- lookuphash[lookup] = { [unicode] = krn }
+ local list = description.kerns
+ if list then
+ for lookup, krn in next, list do -- ref to glyph, saves lookup
+ local target = lookuphash[lookup]
+ if target then
+ target[unicode] = krn
+ else
+ lookuphash[lookup] = { [unicode] = krn }
+ end
end
end
- end
- local list = description.anchors
- if list then
- for typ, anchors in next, list do -- types
- if typ == "mark" or typ == "cexit" then -- or entry?
- for name, anchor in next, anchors do
- local lookups = anchor_to_lookup[name]
- if lookups then
- for lookup, _ in next, lookups do
- local target = lookuphash[lookup]
- if target then
- target[unicode] = anchors
- else
- lookuphash[lookup] = { [unicode] = anchors }
+ local list = description.anchors
+ if list then
+ for typ, anchors in next, list do -- types
+ if typ == "mark" or typ == "cexit" then -- or entry?
+ for name, anchor in next, anchors do
+ local lookups = anchor_to_lookup[name]
+ if lookups then
+ for lookup, _ in next, lookups do
+ local target = lookuphash[lookup]
+ if target then
+ target[unicode] = anchors
+ else
+ lookuphash[lookup] = { [unicode] = anchors }
+ end
end
end
end
end
end
end
+
end
end
@@ -2502,7 +2593,7 @@ end
--~ end
local valid = {
- coverage = { chainsub = true, chainpos = true },
+ coverage = { chainsub = true, chainpos = true, contextsub = true },
reversecoverage = { reversesub = true },
glyphs = { chainsub = true, chainpos = true },
}
diff --git a/Master/texmf-dist/tex/context/base/font-ott.lua b/Master/texmf-dist/tex/context/base/font-ott.lua
index 800fd3c65e8..6c671d76ff4 100644
--- a/Master/texmf-dist/tex/context/base/font-ott.lua
+++ b/Master/texmf-dist/tex/context/base/font-ott.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['font-otf'] = {
license = "see context related readme files"
}
-local type, next, tonumber, tostring, rawget = type, next, tonumber, tostring, rawget
+local type, next, tonumber, tostring, rawget, rawset = type, next, tonumber, tostring, rawget, rawset
local gsub, lower, format, match = string.gsub, string.lower, string.format, string.match
local is_boolean = string.is_boolean
@@ -635,11 +635,18 @@ local baselines = allocate {
['romn'] = 'roman baseline'
}
+local acceptscripts = true directives.register("otf.acceptscripts", function(v) acceptscripts = v end)
+local acceptlanguages = true directives.register("otf.acceptlanguages", function(v) acceptlanguages = v end)
+
+local report_checks = logs.reporter("fonts","checks")
+
tables.scripts = scripts
tables.languages = languages
tables.features = features
tables.baselines = baselines
+-- hm, we overload the metatables
+
if otffeatures.features then
for k, v in next, otffeatures.features do
features[k] = v
@@ -670,7 +677,6 @@ local function resolve(t,k)
return v
end
end
- return "dflt"
end
setmetatableindex(verbosescripts, resolve)
@@ -678,20 +684,51 @@ setmetatableindex(verboselanguages, resolve)
setmetatableindex(verbosefeatures, resolve)
setmetatableindex(verbosebaselines, resolve)
-local function resolve(t,k)
+setmetatableindex(scripts, function(t,k)
if k then
k = lower(k)
- local v = rawget(t,k) or rawget(t,gsub(k," ",""))
+ if k == "dflt" then
+ return k
+ end
+ local v = rawget(t,k)
if v then
return v
end
+ k = gsub(k," ","")
+ v = rawget(t,v)
+ if v then
+ return v
+ elseif acceptscripts then
+ report_checks("registering extra script: %s",k)
+ rawset(t,k,k)
+ return k
+ end
end
return "dflt"
-end
+end)
-setmetatableindex(scripts, resolve)
-setmetatableindex(scripts, resolve)
-setmetatableindex(languages, resolve)
+setmetatableindex(languages, function(t,k)
+ if k then
+ k = lower(k)
+ if k == "dflt" then
+ return k
+ end
+ local v = rawget(t,k)
+ if v then
+ return v
+ end
+ k = gsub(k," ","")
+ v = rawget(t,v)
+ if v then
+ return v
+ elseif acceptlanguages then
+ report_checks("registering extra languages: %s",k)
+ rawset(t,k,k)
+ return k
+ end
+ end
+ return "dflt"
+end)
setmetatablenewindex(languages, "ignore")
setmetatablenewindex(baselines, "ignore")
@@ -741,22 +778,14 @@ local checkers = {
function otf.features.normalize(features) -- no longer 'lang'
if features then
local h = { }
- for k,v in next, features do
+ for k, v in next, features do
k = lower(k)
if k == "language" then
v = gsub(lower(v),"[^a-z0-9]","")
- if rawget(languages,v) then
- h.language = v
- else
- h.language = rawget(verboselanguages,v) or "dflt"
- end
+ h.language = rawget(verboselanguages,v) or (languages[v] and v) or "dflt" -- auto adds
elseif k == "script" then
v = gsub(lower(v),"[^a-z0-9]","")
- if rawget(scripts,v) then
- h.script = v
- else
- h.script = rawget(verbosescripts,v) or "dflt"
- end
+ h.script = rawget(verbosescripts,v) or (scripts[v] and v) or "dflt" -- auto adds
else
if type(v) == "string" then
local b = is_boolean(v)
diff --git a/Master/texmf-dist/tex/context/base/font-pre.mkiv b/Master/texmf-dist/tex/context/base/font-pre.mkiv
new file mode 100644
index 00000000000..9a2c451723a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-pre.mkiv
@@ -0,0 +1,486 @@
+%D \module
+%D [ file=font-pre,
+%D version=2012.01.04, % moved from font-ini
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Predefined,
+%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 / Predefined}
+
+\unprotect
+
+%D A basic set of features is defined here.
+
+\definefontfeature
+ [always]
+ [mode=auto,
+ script=auto,
+ kern=yes,
+ mark=yes,
+ mkmk=yes,
+ curs=yes]
+
+\definefontfeature
+ [default]
+ [always]
+ [liga=yes,
+ tlig=yes,
+ trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [smallcaps]
+ [always]
+ [smcp=yes,
+ tlig=yes,
+ trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature
+ [oldstyle]
+ [always]
+ [onum=yes,
+ liga=yes,
+ tlig=yes,
+ trep=yes] % texligatures=yes,texquotes=yes
+
+\definefontfeature % == default unless redefined
+ [ligatures]
+ [always]
+ [liga=yes,
+ tlig=yes,
+ trep=yes]
+
+\definefontfeature % can be used for type1 fonts
+ [complete]
+ [always]
+ [compose=yes,
+ liga=yes,
+ tlig=yes,
+ trep=yes]
+
+\definefontfeature
+ [none]
+ [mode=none,
+ features=no]
+
+\definefontfeature % might move
+ [arabic]
+ [mode=node,language=dflt,script=arab,ccmp=yes,
+ init=yes,medi=yes,fina=yes,isol=yes,
+ liga=yes,dlig=yes,rlig=yes,clig=yes,calt=yes,
+ mark=yes,mkmk=yes,kern=yes,curs=yes]
+
+\definefontfeature
+ [hebrew]
+ [arabic]
+ [script=hebr]
+
+\definefontfeature % might move
+ [simplearabic]
+ [mode=node,language=dflt,script=arab,
+ init=yes,medi=yes,fina=yes,calt=yes,
+ rlig=yes,curs=yes,mark=yes,mkmk=yes]
+
+\definefontfeature
+ [simplehebrew]
+ [simplearabic]
+ [script=hebr]
+
+% symbols:
+
+\definefontfeature
+ [dingbats]
+ [mode=base,
+ goodies=dingbats,
+ unicoding=yes]
+
+% math:
+
+\definefontfeature
+ [mathematics]
+ [mode=base,
+ liga=yes,
+ kern=yes,
+ tlig=yes,
+ trep=yes,
+ mathalternates=yes,
+ mathitalics=yes,
+ % nomathitalics=yes, % don't pass to tex, might become default
+ language=dflt,
+ script=math]
+
+\definefontfeature
+ [mathematics-l2r]
+ [mathematics]
+ []
+
+\definefontfeature
+ [mathematics-r2l]
+ [mathematics]
+ [language=ara,
+ rtlm=yes,
+ locl=yes]
+
+\definefontfeature[virtualmath] [mathematics] % downward compatibility
+\definefontfeature[virtualmath-l2r] [mathematics-l2r] % downward compatibility
+\definefontfeature[virtualmath-r2l] [mathematics-r2l] % downward compatibility
+
+\definefontfeature[math-text] [mathematics] [ssty=no]
+\definefontfeature[math-script] [mathematics] [ssty=1,mathsize=yes]
+\definefontfeature[math-scriptscript] [mathematics] [ssty=2,mathsize=yes]
+
+\definefontfeature[math-text-l2r] [mathematics-l2r] [ssty=no]
+\definefontfeature[math-script-l2r] [mathematics-l2r] [ssty=1,mathsize=yes]
+\definefontfeature[math-scriptscript-l2r] [mathematics-l2r] [ssty=2,mathsize=yes]
+
+\definefontfeature[math-text-r2l] [mathematics-r2l] [ssty=no]
+\definefontfeature[math-script-r2l] [mathematics-r2l] [ssty=1,mathsize=yes]
+\definefontfeature[math-scriptscript-r2l] [mathematics-r2l] [ssty=2,mathsize=yes]
+
+\definefontfeature[math-nostack-text] [math-text] [nostackmath=yes]
+\definefontfeature[math-nostack-script] [math-script] [nostackmath=yes]
+\definefontfeature[math-nostack-scriptscript][math-scriptscript][nostackmath=yes]
+
+% \definefontfeature[mathtext] [math-text]
+% \definefontfeature[mathscript] [math-script]
+% \definefontfeature[mathscriptscript] [math-scriptscript]
+
+%D We define some colors that are used in tracing (for instance \OPENTYPE\
+%D features). We cannot yet inherit because no colors are predefined.
+
+\definecolor[trace:0][s=.4]
+\definecolor[trace:1][r=.6]
+\definecolor[trace:2][g=.6]
+\definecolor[trace:3][b=.6]
+\definecolor[trace:4][r=.6,g=.6]
+\definecolor[trace:5][r=.6,b=.6]
+\definecolor[trace:6][g=.6,b=.6]
+\definecolor[trace:7][r=.8,g=.4]
+\definecolor[trace:8][r=.8,b=.4]
+\definecolor[trace:9][g=.4,b=.8]
+
+\definecolor[font:init][r=.75]
+\definecolor[font:medi][g=.75]
+\definecolor[font:fina][b=.75]
+\definecolor[font:isol][r=.75,g=.75] % [y=.75]
+\definecolor[font:mark][r=.75,b=.75] % [m=.75]
+\definecolor[font:rest][g=.75,b=.75] % [c=.75]
+
+%D Now we're up to some definitions.
+
+\definebodyfontenvironment
+ [\s!default]
+ [ \s!text=1.0,
+ \s!script=0.7,
+ \s!scriptscript=0.5,
+ \s!a=1.200,
+ \s!b=1.440,
+ \s!c=1.728,
+ \s!d=2.074,
+ *=\currentfontscale, % wildcard
+ \s!x=0.8,
+ \s!xx=0.6,
+ \v!big=1.2,
+ \v!small=0.8,
+ \c!interlinespace=,
+ \s!em=\v!slanted]
+
+\definebodyfontenvironment
+ [20.7pt]
+ [ \s!text=20.7pt,
+ \s!script=\!!fourteenpointfour,
+ \s!scriptscript=\!!twelvepoint,
+ \s!x=17.3pt,
+ \s!xx=\!!fourteenpointfour,
+ \v!big=20.7pt, % !!!!
+ \v!small=17.3pt]
+
+\definebodyfontenvironment
+ [17.3pt]
+ [ \s!text=17.3pt,
+ \s!script=\!!twelvepoint,
+ \s!scriptscript=\!!tenpoint,
+ \s!x=\!!fourteenpointfour,
+ \s!xx=\!!twelvepoint,
+ \v!big=20.7pt,
+ \v!small=\!!fourteenpointfour]
+
+\definebodyfontenvironment
+ [\!!fourteenpointfour]
+ [ \s!text=\!!fourteenpointfour,
+ \s!script=\!!elevenpoint,
+ \s!scriptscript=\!!ninepoint,
+ \s!x=\!!twelvepoint,
+ \s!xx=\!!tenpoint,
+ \v!big=17.3pt,
+ \v!small=\!!twelvepoint]
+
+\definebodyfontenvironment
+ [\!!twelvepoint]
+ [ \s!text=\!!twelvepoint,
+ \s!script=\!!ninepoint,
+ \s!scriptscript=\!!sevenpoint,
+ \s!x=\!!tenpoint,
+ \s!xx=\!!eightpoint,
+ \v!big=\!!fourteenpointfour,
+ \v!small=\!!tenpoint]
+
+\definebodyfontenvironment
+ [\!!elevenpoint]
+ [ \s!text=\!!elevenpoint,
+ \s!script=\!!eightpoint,
+ \s!scriptscript=\!!sixpoint,
+ \s!x=\!!ninepoint,
+ \s!xx=\!!sevenpoint,
+ \v!big=\!!twelvepoint,
+ \v!small=\!!ninepoint]
+
+\definebodyfontenvironment
+ [\!!tenpoint]
+ [ \s!text=\!!tenpoint,
+ \s!script=\!!sevenpoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!eightpoint,
+ \s!xx=\!!sixpoint,
+ \v!big=\!!twelvepoint,
+ \v!small=\!!eightpoint]
+
+\definebodyfontenvironment
+ [\!!ninepoint]
+ [ \s!text=\!!ninepoint,
+ \s!script=\!!sevenpoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!sevenpoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!elevenpoint,
+ \v!small=\!!sevenpoint]
+
+\definebodyfontenvironment
+ [\!!eightpoint]
+ [ \s!text=\!!eightpoint,
+ \s!script=\!!sixpoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!sixpoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!tenpoint,
+ \v!small=\!!sixpoint]
+
+\definebodyfontenvironment
+ [\!!sevenpoint]
+ [ \s!text=\!!sevenpoint,
+ \s!script=\!!sixpoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!sixpoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!ninepoint,
+ \v!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!sixpoint]
+ [ \s!text=\!!sixpoint,
+ \s!script=\!!fivepoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!fivepoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!eightpoint,
+ \v!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!fivepoint]
+ [ \s!text=\!!fivepoint,
+ \s!script=\!!fivepoint,
+ \s!scriptscript=\!!fivepoint,
+ \s!x=\!!fivepoint,
+ \s!xx=\!!fivepoint,
+ \v!big=\!!sevenpoint,
+ \v!small=\!!fivepoint]
+
+\definebodyfontenvironment
+ [\!!fourpoint]
+ [ \s!text=\!!fourpoint,
+ \s!script=\!!fourpoint,
+ \s!scriptscript=\!!fourpoint,
+ \s!x=\!!fourpoint,
+ \s!xx=\!!fourpoint,
+ \v!big=\!!sixpoint,
+ \v!small=\!!fourpoint]
+
+\definebodyfontswitch [fourteenpointfour] [\!!fourteenpointfour]
+\definebodyfontswitch [twelvepoint] [\!!twelvepoint]
+\definebodyfontswitch [elevenpoint] [\!!elevenpoint]
+\definebodyfontswitch [tenpoint] [\!!tenpoint]
+\definebodyfontswitch [ninepoint] [\!!ninepoint]
+\definebodyfontswitch [eightpoint] [\!!eightpoint]
+\definebodyfontswitch [sevenpoint] [\!!sevenpoint]
+\definebodyfontswitch [sixpoint] [\!!sixpoint]
+\definebodyfontswitch [fivepoint] [\!!fivepoint]
+\definebodyfontswitch [fourpoint] [\!!fourpoint]
+
+%D So far.
+
+\definefontstyle [\s!hw] [\s!hw]
+\definefontstyle [\s!cg] [\s!cg]
+
+\definefontstyle [\v!roman,\v!serif,\v!regular] [\s!rm]
+\definefontstyle [\v!sansserif,\v!sans,\v!support] [\s!ss]
+\definefontstyle [\v!teletype,\v!type,\v!mono] [\s!tt]
+\definefontstyle [\v!handwritten] [\s!hw]
+\definefontstyle [\v!calligraphic] [\s!cg]
+
+\definefontalternative[\s!tf]
+\definefontalternative[\s!bf]
+\definefontalternative[\s!it]
+\definefontalternative[\s!sl]
+\definefontalternative[\s!bs]
+\definefontalternative[\s!bi]
+\definefontalternative[\s!sc]
+
+\definefontsize[\s!a] \definefontsize[\s!b]
+\definefontsize[\s!c] \definefontsize[\s!d]
+
+\definealternativestyle [\v!mediaeval] [\os] []
+\definealternativestyle [\v!normal] [\tf] []
+\definealternativestyle [\v!bold] [\bf] []
+\definealternativestyle [\v!type] [\tt] []
+\definealternativestyle [\v!mono] [\tt] []
+\definealternativestyle [\v!slanted] [\sl] []
+\definealternativestyle [\v!italic] [\it] []
+\definealternativestyle [\v!boldslanted,\v!slantedbold] [\bs] []
+\definealternativestyle [\v!bolditalic,\v!italicbold] [\bi] []
+
+\definealternativestyle [\v!small,\v!smallnormal] [\setsmallbodyfont\tf] []
+\definealternativestyle [\v!smallbold] [\setsmallbodyfont\bf] []
+\definealternativestyle [\v!smalltype] [\setsmallbodyfont\tt] []
+\definealternativestyle [\v!smallslanted] [\setsmallbodyfont\sl] []
+\definealternativestyle [\v!smallboldslanted,\v!smallslantedbold] [\setsmallbodyfont\bs] []
+\definealternativestyle [\v!smallbolditalic,\v!smallitalicbold] [\setsmallbodyfont\bi] []
+
+\definealternativestyle [\v!bigger] [\setbigbodyfont \tf] []
+\definealternativestyle [\v!smaller] [\setsmallbodyfont\tf] []
+
+\definealternativestyle [\v!sans,\v!sansserif] [\ss] []
+\definealternativestyle [\v!sansbold] [\ss\bf] []
+
+% % maybe we need interface neutral as well (for use in cld):
+%
+% \letcscsname\mediaeval \csname\v!mediaeval \endcsname
+% \letcscsname\normal \csname\v!normal \endcsname
+% \letcscsname\bold \csname\v!bold \endcsname
+% \letcscsname\mono \csname\v!mono \endcsname
+% \letcscsname\slanted \csname\v!slanted \endcsname
+% \letcscsname\italic \csname\v!italic \endcsname
+% \letcscsname\boldslanted \csname\v!boldslanted \endcsname
+% \letcscsname\slantedbold \csname\v!slantedbold \endcsname
+% \letcscsname\bolditalic \csname\v!bolditalic \endcsname
+% \letcscsname\italicbold \csname\v!italicbold \endcsname
+%
+% \letcscsname\small \csname\v!small \endcsname
+% \letcscsname\smallnormal \csname\v!smallnormal \endcsname
+% \letcscsname\smallbold \csname\v!smallbold \endcsname
+% \letcscsname\smalltype \csname\v!smalltype \endcsname
+% \letcscsname\smallslanted \csname\v!smallslanted \endcsname
+% \letcscsname\smallboldslanted\csname\v!smallboldslanted\endcsname
+% \letcscsname\smallslantedbold\csname\v!smallslantedbold\endcsname
+% \letcscsname\smallbolditalic \csname\v!smallbolditalic \endcsname
+% \letcscsname\smallitalicbold \csname\v!smallitalicbold \endcsname
+%
+% \letcscsname\bigger \csname\v!bigger \endcsname
+% \letcscsname\smaller \csname\v!smaller \endcsname
+%
+% \letcscsname\sans \csname\v!sans \endcsname
+% \letcscsname\sansserif \csname\v!sansserif \endcsname
+% \letcscsname\sansbold \csname\v!sansbold \endcsname
+
+%D We can go on and on and on:
+%D
+%D \starttyping
+%D \setupbodyfontenvironment[default][p=0.8,q=0.6]
+%D \definefontsize[p]
+%D \definefontsize[q]
+%D \stoptyping
+
+%D Slow but handy:
+
+\definealternativestyle [\v!smallbodyfont] [\setsmallbodyfont] []
+\definealternativestyle [\v!bigbodyfont] [\setbigbodyfont] []
+
+%D We treat {\sc Small Caps} and \cap {Pseudo Caps} a bit
+%D different. We also provide an \WORD {uppercase} style.
+
+\definealternativestyle [\v!smallcaps] [\sc] [\sc]
+
+\definealternativestyle [\v!WORD] [{\setcharactercasing[\v!WORD ]}] [{\setcharactercasing[\v!WORD ]}]
+\definealternativestyle [\v!word] [{\setcharactercasing[\v!word ]}] [{\setcharactercasing[\v!word ]}]
+\definealternativestyle [\v!Word] [{\setcharactercasing[\v!Word ]}] [{\setcharactercasing[\v!Word ]}]
+\definealternativestyle [\v!Words] [{\setcharactercasing[\v!Words ]}] [{\setcharactercasing[\v!Words ]}]
+\definealternativestyle [\v!capital] [{\setcharactercasing[\v!capital]}] [{\setcharactercasing[\v!capital]}]
+\definealternativestyle [\v!Capital] [{\setcharactercasing[\v!Capital]}] [{\setcharactercasing[\v!Capital]}]
+
+\definealternativestyle [\v!cap] [{\setcharactercasing[\v!cap ]}] [{\setcharactercasing[\v!cap ]}]
+\definealternativestyle [\v!Cap] [{\setcharactercasing[\v!Cap ]}] [{\setcharactercasing[\v!Cap ]}]
+
+%D \macros
+%D {tinyfont}
+%D
+%D By default we load the Computer Modern Roman fonts (but
+%D not yet at this moment) and activate the 12pt roman
+%D bodyfont. Sans serif and teletype are also available and
+%D can be called for by \type{\ss} and \type{\tt}. Loading
+%D takes place elsewhere.
+%D
+%D For tracing purposes we define:
+
+\definefont[tinyfont][Mono at 1ex]
+
+%D \macros
+%D {infofont}
+%D
+%D The second situation occurs when we enable the info mode,
+%D and put all kind of status information in the margin. We
+%D don't want huge switches to the main bodyfont and style, so
+%D here too we use a direct method.
+
+\let\infofont\relax % satisfy dep checker
+
+\definefont [infofont] [Mono at 6pt] % todo \the\everybodyfont
+
+\protect \endinput
+
+% LM math vs CM math (analysis by Taco):
+%
+% Computer Modern Roman : Donald Knuth
+% Latin Modern : LM Font Revision Team
+%
+% lmex10.tfm % identical
+% lmmi5.tfm % identical
+% lmmi6.tfm % identical
+% lmmi7.tfm % identical
+% lmmi8.tfm % identical
+% lmmi9.tfm % identical
+% lmmi10.tfm % identical
+% lmmi12.tfm % identical
+% lmmib10.tfm % identical
+% lmsy5.tfm % extra chars: 254,255 (octal)
+% lmsy6.tfm % extra chars: 254,255 (octal)
+% lmsy7.tfm % extra chars: 254,255 (octal)
+% lmsy8.tfm % extra chars: 254,255 (octal)
+% lmsy9.tfm % extra chars: 254,255 (octal)
+% lmsy10.tfm % extra chars: 254,255 (octal)
+% lmbsy10.tfm % extra chars: 254,255 (octal)
+%
+% From the 'AMS' set:
+%
+% lmmib5.tfm % identical
+% lmmib7.tfm % identical
+% lmbsy5.tfm % extra chars: 254,255 (octal)
+% lmbsy7.tfm % extra chars: 254,255 (octal)
+%
+% The two extra characters are:
+%
+% /lessorequalslant
+% /greaterorequalslant
diff --git a/Master/texmf-dist/tex/context/base/font-run.mkii b/Master/texmf-dist/tex/context/base/font-run.mkii
index 0a0ddd05790..04fcd576a60 100644
--- a/Master/texmf-dist/tex/context/base/font-run.mkii
+++ b/Master/texmf-dist/tex/context/base/font-run.mkii
@@ -6,7 +6,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-run.mkiv b/Master/texmf-dist/tex/context/base/font-run.mkiv
index 7a6764ac8a0..b346de5e1c6 100644
--- a/Master/texmf-dist/tex/context/base/font-run.mkiv
+++ b/Master/texmf-dist/tex/context/base/font-run.mkiv
@@ -6,7 +6,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -77,14 +77,15 @@
\vbox
{\dosetshowfonttitle{#1}%
\def\next##1%
- {&&\getvalue{\bodyfontvariable{##1\s!text}}%
- &&\getvalue{\bodyfontvariable{##1\s!script}}%
- &&\getvalue{\bodyfontvariable{##1\s!scriptscript}}%
- &&\getvalue{\bodyfontvariable{##1\c!x}}%
- &&\getvalue{\bodyfontvariable{##1\c!xx}}%
- &&\getvalue{\bodyfontvariable{##1\interfaced\v!small}}%
- &&\getvalue{\bodyfontvariable{##1\interfaced\v!big}}%
- &&\edef\next{\getvalue{\bodyfontvariable{##1\c!interlinespace}}}\ifx\next\empty not set\else\next\fi&\cr
+ {&&\bodyfontsizevariable{##1}\s!text
+ &&\bodyfontsizevariable{##1}\s!script
+ &&\bodyfontsizevariable{##1}\s!scriptscript
+ &&\bodyfontsizevariable{##1}\s!x
+ &&\bodyfontsizevariable{##1}\s!xx
+ &&\bodyfontsizevariable{##1}\v!small
+ &&\bodyfontsizevariable{##1}\v!big
+ &&\bodyfontsizevariable{##1}\c!interlinespace
+ &\cr
\noalign{\hrule}}
\halign to \localhsize
{##&\vrule##\strut
@@ -97,7 +98,7 @@
&\multispan{17}{\vrule\hfil\tttf\strut\title\hfil}\vrule\cr
\noalign{\hrule}
&&\tttf\tx\s!text&&\tttf\tx\s!script&&\tttf\tx\s!scriptscript
- &&\tttf\tx\c!x&&\tttf\tx\c!xx&&\tttf\tx\v!small&&\tttf\tx\v!big
+ &&\tttf\tx\s!x&&\tttf\tx\s!xx&&\tttf\tx\v!small&&\tttf\tx\v!big
&&\tttf\tx\c!interlinespace&\cr
\noalign{\hrule}
\@EA\globalprocesscommalist\@EA[\bodyfontenvironmentlist]\next}}
@@ -209,24 +210,22 @@
\gdef\redoshowfontstyle {\dotripleempty \dododoshowfontstyle}
\gdef\redodoshowfontstyle{\doquadrupleempty\dodododoshowfontstyle}
+% no lists any more, so no 'all' any longer
+
\gdef\dodoshowfontstyle[#1][#2]%
- {\doifelse{#2}\v!all
- {\dodoshowfontstyle[#1][\c!rm,\c!ss,\c!tt,\c!mm]}
- {\doifelsenothing{#2}
- {\redoshowfontstyle[#1][\c!rm,\c!ss,\c!tt,\c!mm]}
- {\redoshowfontstyle[#1][#2]}}}
+ {\doifelsenothing{#2}
+ {\redoshowfontstyle[#1][\s!rm,\s!ss,\s!tt,\s!mm]}
+ {\redoshowfontstyle[#1][#2]}}
\gdef\dododoshowfontstyle[#1][#2][#3]%
- {\doifelse{#3}\v!all
- {\redodoshowfontstyle[#1][#2][\fontalternativelist]}
- {\doifelsenothing{#3}
- {\redodoshowfontstyle[#1][#2][\fontalternativelist]}
- {\redodoshowfontstyle[#1][#2][#3]}}}
+ {\doifelsenothing{#3}
+ {\redodoshowfontstyle[#1][#2][\s!tf,\s!bf,\s!it,\s!sl,\s!bs,\s!bi]}
+ {\redodoshowfontstyle[#1][#2][#3]}}
\gdef\dodododoshowfontstyle[#1][#2][#3][#4]%
- {\doifelsenothing{#4}
- {\doshowfontstyleindeed[#1][#2][#3][\v!all]}
- {\doshowfontstyleindeed[#1][#2][#3][#4]}}
+ {\doshowfontstyleindeed[#1][#2][#3][#4]}
+
+% so far
\gdef\doshowfontstyleindeed[#1][#2][#3][#4]%
{\bgroup
diff --git a/Master/texmf-dist/tex/context/base/font-set.mkvi b/Master/texmf-dist/tex/context/base/font-set.mkvi
new file mode 100644
index 00000000000..d692c6cc82f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-set.mkvi
@@ -0,0 +1,144 @@
+%D \module
+%D [ file=font-set,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Initial Loading,
+%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 / Initial Loading}
+
+\unprotect
+
+%D Defining fonts using \type{\definebodyfont} takes time, so we
+%D prefer to predefine at least the Computer Modern Roman
+%D fonts. However, loading all those fonts at definition time
+%D would take both time and space. But even worse, once fonts
+%D are loaded into memory, their encoding vector is fixed,
+%D which is a handicap when we want to distribute the compact
+%D \type{fmt} files. So what we want to do is defining fonts in
+%D a way that postpones the loading. We accomplish this by only
+%D loading the fonts when we switch to another bodyfont size.
+%D Among the other alternatives, such as loading the font at
+%D the moment of activation and redefining the activation
+%D macro afterwards, this proved to be the most efficient
+%D alternative.
+%D
+%D The next few macros take care of the one exeption on this
+%D scheme. When at format generation time we load the default
+%D font file, the one that defines the Computer Modern Fonts,
+%D we don't want the fonts metrics to end up in the format
+%D file, so we temporary prohibit loading. This means that at
+%D runtime we have to load the default bodyfont size just before
+%D we start typesetting.
+
+\def\fallbacktypeface{modern-designsize} % at some point we might prefer just modern
+
+\def\font_preloads_reset_nullfont % this is needed because some macro packages (tikz) misuse \nullfont
+ {\dorecurse\plusseven{\fontdimen\recurselevel\nullfont\zeropoint}% keep en eye on this as:
+ \ctxcommand{resetnullfont()}% in luatex 0.70 this will also do the previous
+ \globallet\font_preloads_reset_nullfont\relax}
+
+\def\font_preload_default_fonts
+ {\font_preloads_reset
+ \setupbodyfont[\fallbacktypeface,\fontstyle,\fontbody]%
+ \showmessage\m!fonts6{fallback modern \fontstyle\normalspace\normalizedbodyfontsize}}
+
+\def\font_preload_default_fonts_mm
+ {\writestatus\m!fonts{preloading latin modern fonts (math)}%
+ \definetypeface[\fontclass][\s!mm][\s!math][modern][\s!default]%
+ \showmessage\m!fonts6{fallback modern mm \normalizedbodyfontsize}}
+
+\def\font_preload_default_fonts_tt
+ {\writestatus\m!fonts{preloading latin modern fonts (mono)}%
+ \definetypeface[\fontclass][\s!tt][\s!mono][modern][\s!default]%
+ \showmessage\m!fonts6{fallback modern tt \normalizedbodyfontsize}}
+
+\def\font_preloads_reset
+ {\glet\font_preload_default_fonts \relax
+ %\glet\font_preload_default_fonts_tt\relax
+ %\glet\font_preload_default_fonts_mm\relax
+ \glet\font_preloads_zero_stage \relax
+ \glet\font_preloads_first_stage \relax
+ \glet\font_preloads_second_stage \relax
+ %\glet\font_preloads_third_stage \relax
+ \glet\fourthstagepreloadfonts \relax
+ \global\everyhbox\emptytoks
+ \global\everyvbox\emptytoks
+ \font_preloads_reset_nullfont}
+
+\def\font_preloads_reset_checked
+ {\glet\font_preload_default_fonts_tt\relax
+ \glet\font_preload_default_fonts_mm\relax
+ \glet\font_preloads_third_stage \relax}
+
+\def\font_preloads_zero_stage_indeed
+ {\definedfont[\s!file:lmmono10-regular sa 1]}
+
+\unexpanded\def\font_preloads_zero_stage
+ {\writestatus\m!fonts{beware: no fonts are loaded yet, using 'lm mono' in box}%
+ \glet\font_preloads_zero_stage\font_preloads_zero_stage_indeed
+ \font_preloads_zero_stage}
+
+\unexpanded\def\font_preloads_first_stage % % *nofonts -> *preloadfonts
+ {\doifmodeelse{*preloadfonts}
+ {\font_preload_default_fonts
+ \writestatus\m!fonts{preloading latin modern fonts (first stage)}}
+ {\writestatus\m!fonts{latin modern fonts are not preloaded}}}
+
+\unexpanded\def\font_preloads_second_stage
+ {\writestatus\m!fonts{preloading latin modern fonts (second stage)}%
+ \font_preload_default_fonts}
+
+\unexpanded\def\font_preloads_third_stage % always
+ {\ifx\fontclass\empty
+ \writestatus\m!fonts{preloading latin modern fonts (third stage)}%
+ \font_preload_default_fonts
+ \font_preloads_reset
+ \else
+ \font_preloads_reset
+ \pushmacro\fontstyle
+ \ifcsname\??fontclass\fontclass\s!mm\s!features\endcsname \else
+ \font_preload_default_fonts_mm
+ \fi
+ \ifcsname\??fontclass\fontclass\s!tt\s!features\endcsname \else
+ \font_preload_default_fonts_tt
+ \fi
+ \popmacro\fontstyle
+ \font_preloads_reset_checked % reset third, mm and tt
+ \setupbodyfont[\fontstyle]%
+ \fi}
+
+\unexpanded\def\font_preloads_fourth_stage
+ {\begingroup
+ %ifzeropt\fontcharwd\font\number`!\relax
+ \setbox\scratchbox\hbox{context}%
+ \ifzeropt\wd\scratchbox
+ \writeline
+ \writestatus\m!fonts{!! No bodyfont has been defined and no defaults have been}%
+ \writestatus\m!fonts{!! loaded (maybe due to a missing \string\starttext).}%
+ \writeline
+ \fi
+ \font_preloads_reset
+ \endgroup}
+
+\appendtoks
+ \everyhbox{\font_preloads_zero_stage}%
+ \everyvbox{\font_preloads_zero_stage}%
+\to \everydump
+
+\unexpanded\def\font_preloads_at_every_job {\font_preloads_first_stage }
+\unexpanded\def\font_preloads_at_start_text{\font_preloads_second_stage}
+\unexpanded\def\font_preloads_at_stop_text {\font_preloads_fourth_stage}
+\unexpanded\def\font_preloads_at_definition{\font_preloads_third_stage
+ \glet\font_preloads_at_definition\relax}
+
+% \unexpanded\def\checkpreloadedbodyfont % no \let here
+% {\font_preloads_at_start_text}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-sty.mkvi b/Master/texmf-dist/tex/context/base/font-sty.mkvi
new file mode 100644
index 00000000000..d8f01afa700
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-sty.mkvi
@@ -0,0 +1,386 @@
+%D \module
+%D [ file=font-sty,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Styles,
+%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 / Styles}
+
+\unprotect
+
+%D \macros
+%D {definealternativestyle}
+%D
+%D In the main modules we are going to implement lots of
+%D parameterized commands and one of these parameters will
+%D concern the font to use. To suit consistent use of fonts we
+%D here implement a mechanism for defining the keywords that
+%D present a particular style or alternative.
+%D
+%D \starttyping
+%D \definealternativestyle [keywords] [\style] [\nostyle]
+%D \stoptyping
+%D
+%D The first command is used in the normal textflow, while the
+%D second command takes care of headings and alike. Consider
+%D the next two definitions:
+%D
+%D \starttyping
+%D \definealternativestyle [bold] [\bf] []
+%D \definealternativestyle [cap] [\cap] [\cap]
+%D \stoptyping
+%D
+%D A change \type{\bf} in a heading which is to be set in
+%D \type{\tfd} does not look that well, so therefore we leave
+%D the second argument of \type{\definealternativestyle} empty.
+%D When we capatalize characters using the pseudo small cap
+%D command \type{\cap}, we want this to take effect in both
+%D text and headings, which is accomplished by assigning both
+%D arguments.
+
+\installcorenamespace{alternativestyles}
+
+\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]%
+ {\processcommalist[#commands]{\font_basics_define_alternative_style_indeed{#variantone}{#varianttwo}}}
+
+\let\definestyle\definealternativestyle % later redefined
+
+\def\font_basics_define_alternative_style_indeed#variantone#varianttwo#command%
+ {\ifcsname#command\endcsname
+ % no redefinition
+ \else
+ \setuvalue{#command}{\groupedcommand{#variantone}{}}%
+ \fi
+ \setvalue{\??alternativestyles#command}{\font_helpers_apply_alternative_style{#variantone}{#varianttwo}}}%
+
+\def\font_helpers_apply_alternative_style
+ {\ifcase\c_font_current_alternative_style_index
+ \expandafter\gobbletwoarguments
+ \or
+ \expandafter\firstoftwoarguments
+ \or
+ \expandafter\secondoftwoarguments
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\applyalternativestyle#name% public
+ {\ifcsname\??alternativestyles#name\endcsname\csname\??alternativestyles#name\expandafter\endcsname\fi}
+
+%D Maybe too geneneric, but probably ok is the following. (Maybe one
+%D day we will use a dedicated grouped command for styles.)
+
+% \appendtoks
+% \let\groupedcommand\thirdofthreearguments
+% \to \simplifiedcommands
+
+%D This command also defines the keyword as command. This means
+%D that the example definition of \type{bold} we gave before,
+%D results in a command \type{\bold} which can be used as:
+%D
+%D \startbuffer
+%D He's a \bold{bold} man with a {\bold head}.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or
+%D
+%D \startexample
+%D \definealternativestyle[bold][\bf][]\getbuffer
+%D \stopexample
+%D
+%D Such definitions are of course unwanted for \type{\cap}
+%D because this would result in an endless recursive call.
+%D Therefore we check on the existance of both the command and
+%D the substitution. The latter is needed because for instance
+%D \type{\type} is an entirely diferent command. That command
+%D handles verbatim, while the style command would just switch
+%D to teletype font. This is just an example of a tricky
+%D naming coincidence.
+
+%D \macros
+%D {doconvertfont,noconvertfont,
+%D dontconvertfont,redoconvertfont}
+%D
+%D After having defined such keywords, we can call for them by
+%D using
+%D
+%D \starttyping
+%D \doconvertfont{keyword}{text}
+%D \stoptyping
+%D
+%D We deliberately pass an argument. This enables us to
+%D assign converters that handle one argument, like
+%D \type{\cap}.
+%D
+%D By default the first specification is used to set the style,
+%D exept when we say \type{\dontconvertfont}, after which the
+%D second specification is used. We can also directly call for
+%D \type{\noconvertfont}. In nested calls, we can restore the
+%D conversion by saying \type{\redoconvertfont}.
+
+%D These commands are not grouped! Grouping is most probably
+%D done by the calling macro's and would lead to unnecessary
+%D overhead.
+
+\let\m_current_convert_font \empty
+\let\m_current_convert_font_dt\empty
+
+\unexpanded\def\doconvertfont#specification% takes second argument / this command is obsolete
+ {\edef\m_current_convert_font{#specification}%
+ \ifx\m_current_convert_font\empty
+ %\expandafter\firstofoneargument
+ \else
+ \expandafter\font_helpers_do_convert_font
+ \fi}
+
+\def\font_helpers_do_convert_font
+ {\edef\m_current_convert_font_dt{\detokenize\expandafter{\m_current_convert_font}}%
+ \ifcsname\??alternativestyles\m_current_convert_font_dt\endcsname
+ \csname\??alternativestyles\m_current_convert_font_dt\expandafter\endcsname
+ \else\ifcsname\m_current_convert_font_dt\endcsname
+ \csname\m_current_convert_font_dt\expandafter\endcsname
+ \else
+ \doubleexpandafter\m_current_convert_font
+ \fi\fi}
+
+%D Low level switches (downward compatible, but we keep them as one can use
+%D them in styles):
+%D
+%D \starttyping
+%D \usemodule[abr-02]
+%D \setuphead[chapter][style=\bfb]
+%D \setupfooter[style=\dontconvertfont\bf]
+%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
+
+%D The new one:
+
+\unexpanded\def\dousestyleparameter#value%
+ {\edef\currentstyleparameter{#value}%
+ \ifx\currentstyleparameter\empty\else
+ \expandafter\dousecurrentstyleparameter
+ \fi}
+
+\unexpanded\def\dousestylehashparameter#hash#parameter%
+ {\ifcsname#hash#parameter\endcsname
+ \expandafter\dousestyleparameter\csname#hash#parameter\endcsname
+ \fi}
+
+\unexpanded\def\dousecurrentstyleparameter % empty check outside here
+ {\edef\detokenizedstyleparameter{\detokenize\expandafter{\currentstyleparameter}}%
+ \settrue\fontattributeisset % reset is done elsewhere
+ \ifcsname\??alternativestyles\detokenizedstyleparameter\endcsname
+ \csname\??alternativestyles\detokenizedstyleparameter\endcsname
+ \else\ifcsname\detokenizedstyleparameter\endcsname
+ \csname\detokenizedstyleparameter\endcsname
+ \else
+ \currentstyleparameter
+ \fi\fi}
+
+\let\dosetfontattribute\dousestylehashparameter % for a while
+
+%D New commands (not yet interfaced):
+%D
+%D \startbuffer
+%D \definestyle[one][style=bold,color=darkblue]
+%D
+%D test \one{test} test
+%D test \style[one]{test} test
+%D test \style[color=red]{test} test
+%D test \style[Serif at 20pt]{test} test
+%D \stopbuffer
+%D
+%D \typebuffer \startlines \getbuffer \stoplines
+
+% definitions .. no tagging here
+
+\installcorenamespace{style}
+\installcorenamespace{stylecheck}
+
+\installcommandhandler \??style {style} \??style
+
+\appendtoks
+ \letvalue{\??stylecheck\currentstyle}\relax
+ \setuevalue{\e!start\currentstyle}{\font_styles_apply_start{\currentstyle}}%
+ \setuevalue{\e!stop \currentstyle}{\font_styles_apply_stop}%
+ \setuevalue {\currentstyle}{\font_styles_apply_grouped{\currentstyle}}% no longer groupedcommand here
+\to \everydefinestyle
+
+\unexpanded\def\font_styles_apply_start#name%
+ {\begingroup
+ \font_styles_use_defined{#name}}
+
+\unexpanded\def\font_styles_apply_stop
+ {\endgroup}
+
+\unexpanded\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%
+ {\edef\currentstyle{#name}%
+ \usestylestyleandcolor\c!style\c!color}
+
+\unexpanded\def\font_styles_use_generic#specification%
+ {\let\currentstyle\s!unknown % reasonable generic tag
+ \setupcurrentstyle[\c!style=,\c!color=,#specification]%
+ \usestylestyleandcolor\c!style\c!color}
+
+% commands
+
+\installcorenamespace{styleargument}
+
+\unexpanded\def\style[#name]% as this is can be a switch we use groupedcommand
+ {\csname\??styleargument
+ \ifcsname#name\endcsname1\else\ifcsname\??stylecheck#name\endcsname2\else3\fi\fi
+ \endcsname{#name}}
+
+\setvalue{\??styleargument1}#name%
+ {\csname#name\endcsname}
+
+\setvalue{\??styleargument2}#name%
+ {\groupedcommand{\font_styles_use_defined{#name}}{}}
+
+\setvalue{\??styleargument3}#specification%
+ {\doifassignmentelse{#specification}\font_styles_assignment\font_styles_direct{#specification}}
+
+\def\font_styles_assignment#specification{\groupedcommand{\font_styles_use_generic{#specification}}{}}
+\def\font_styles_direct #specification{\groupedcommand{\definedfont[#specification]}{}}
+
+% environments
+
+\installcorenamespace{styleenvironment}
+
+\unexpanded\def\startstyle[#name]%
+ {\begingroup
+ \csname\??styleenvironment
+ \ifcsname#name\endcsname1\else\ifcsname\??stylecheck#name\endcsname2\else3\fi\fi
+ \endcsname{#name}}
+
+\unexpanded\def\stopstyle
+ {\endgroup
+ \autoinsertnextspace} % will be configurable, maybe also in \definestartstop
+
+\setvalue{\??styleenvironment1}#name%
+ {\csname#name\endcsname}
+
+\setvalue{\??styleenvironment2}#name%
+ {\font_styles_use_defined{#name}}
+
+\setvalue{\??styleenvironment3}#specification%
+ {\doifassignmentelse{#specification}\font_styles_start_assignment\font_styles_start_direct{#specification}}
+
+\def\font_styles_start_assignment#specification{\usegenericstyle{#specification}}
+\def\font_styles_start_direct #specification{\definedfont[#specification]\relax}
+
+%D Still experimental (might even go away).
+
+% \definestylecollection[mine]
+
+% \definestyleinstance[mine][default][sorry]
+% \definestyleinstance[mine][tt][bs][ttbs:\rm\sl]
+% \definestyleinstance[mine][tt][bf][ttbf:\rm\sl]
+% \definestyleinstance[mine][bf][\sl]
+% \definestyleinstance[mine][sl][\tt]
+
+% {\bf test \mine test \sl test \mine test \bs oeps \mine oeps {\tt test \mine \bf test}}
+
+\installcorenamespace{stylecollection}
+
+\unexpanded\def\definestylecollection
+ {\dosingleargument\font_styles_define_style_collection}
+
+\def\font_styles_define_style_collection[#name]%
+ {\iffirstargument
+ \setuvalue{#name}{\styleinstance[#name]}%
+ \def\font_styles_define_style_collection_a#style%
+ {\def\font_styles_define_style_collection_b#alternative{\letbeundefined{\??stylecollection#name:#style:#alternative}}%
+ \font_helpers_process_alternative_list\font_styles_define_style_collection_b
+ \font_styles_define_style_collection_b\s!default}%
+ \font_helpers_process_style_list\font_styles_define_style_collection_a
+ \font_styles_define_style_collection_a\s!default
+ \fi}
+
+\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
+ \ifcsname#1\endcsname\else\font_styles_define_style_collection[#instance]\fi
+ \fi
+ \iffourthargument
+ \setvalue{\??stylecollection#instance:#2:#3}{#4}%
+ \else\ifthirdargument
+ \setvalue{\??stylecollection#instance::#2}{#3}%
+ \else\ifsecondargument
+ \letvalueempty{\??stylecollection#instance::#2}%
+ \fi\fi\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}}}}}
+
+\unexpanded\def\styleinstance[#instance]%
+ {\csname\??stylecollection#instance:%
+ \ifcsname\??stylecollection#instance:\fontstyle:\fontalternative\endcsname
+ \fontstyle:\fontalternative
+ \else\ifcsname\??stylecollection#instance:\fontstyle:\s!default\endcsname
+ \fontstyle:\s!default
+ \else\ifcsname\??stylecollection#instance::\fontalternative\endcsname
+ :\fontalternative
+ \else
+ :\s!default
+ \fi\fi\fi
+ \endcsname}
+
+%D Variant selectors
+%D
+%D \starttyping
+%D \mathematics {\vsone{\utfchar{"2229}}}
+%D \mathematics {\utfchar{"2229}\vsone{}}
+%D \stoptyping
+
+\unexpanded\edef\vsone#character{#character\utfchar{"FE00}} % used
+\unexpanded\edef\vstwo#character{#character\utfchar{"FE01}} % not used but handy for testing
+
+%D For historic reasons we keep the following around but they are no longer
+%D that relevant for \MKIV.
+
+\unexpanded\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%
+ {\begingroup % geen \bgroup, anders in mathmode lege \hbox
+ \dousestylehashparameter{#1}{#2}%
+ \dousecolorhashparameter{#1}{#3}}
+
+\let\dostopattributes\endgroup
+
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-sym.mkvi b/Master/texmf-dist/tex/context/base/font-sym.mkvi
new file mode 100644
index 00000000000..68237c07337
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-sym.mkvi
@@ -0,0 +1,242 @@
+%D \module
+%D [ file=font-mat,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Symbolic Access,
+%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 / Symbolic Access}
+
+\unprotect
+
+%D \macros
+%D {getglyph, symbolicfont}
+%D
+%D Individual glyphs can be accessed by using
+%D
+%D \starttyping
+%D \getglyph{fontname}{character}
+%D \stoptyping
+%D
+%D This macro is used in for instance the symbol modules and
+%D as one can see, it does obey the small and even smaller
+%D sizes. The \type {\symbolicfont} macro can be used to
+%D switch to a font named \type {fontname} (see \type
+%D {cont-log} and \type {symb-eur} for examples of symbolic
+%D definitions.
+
+\def\v_font_string_a
+ {\ifx\fontstyle\s!rm \s!Serif \else
+ \ifx\fontstyle\s!ss \s!Sans \else
+ \ifx\fontstyle\s!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+\def\v_font_string_b
+ {\ifx\fontstyle\s!rm \s!Regular \else
+ \ifx\fontstyle\s!ss \s!Support \else
+ \ifx\fontstyle\s!tt \s!Type \else
+ \s!Serif \fi\fi\fi}
+
+\def\v_font_string_c
+ {\ifx\fontalternative\s!bf \s!Bold \else
+ \ifx\fontalternative\s!sl \s!Slanted \else
+ \ifx\fontalternative\s!it \s!Italic \else
+ \ifx\fontalternative\s!bs \s!BoldSlanted \else
+ \ifx\fontalternative\s!bi \s!BoldItalic \fi\fi\fi\fi\fi}
+
+\let\v_font_string_d\s!Serif % default fontstyle (will be redefined in type-ini)
+
+% potential generalization:
+%
+% \letvalue{\??fontfile:t:\s!rm}\s!Serif
+% \letvalue{\??fontfile:t:\s!ss}\s!Sans
+% \letvalue{\??fontfile:t:\s!tt}\s!Mono
+%
+% \letvalue{\??fontfile:a:\s!rm}\s!Regular
+% \letvalue{\??fontfile:a:\s!ss}\s!Support
+% \letvalue{\??fontfile:a:\s!tt}\s!Type
+%
+% \letvalue{\??fontfile:s:\s!bf}\s!Bold
+% \letvalue{\??fontfile:s:\s!sl}\s!Slanted
+% \letvalue{\??fontfile:s:\s!it}\s!Italic
+% \letvalue{\??fontfile:s:\s!bs}\s!BoldSlanted
+% \letvalue{\??fontfile:s:\s!bi}\s!BoldItalic
+%
+% \def\v_font_string_a{\executeifdefined{\??fontfile:t:\fontstyle}\s!Serif}
+% \def\v_font_string_a{\executeifdefined{\??fontfile:t:\fontstyle}\s!Serif}
+% \def\v_font_string_b{\executeifdefined{\??fontfile:a:\fontstyle}\s!Serif}
+% \def\v_font_string_c{\executeifdefined{\??fontfile:s:\fontstyle}\empty}
+% \def\v_font_string_d{\executeifdefined{\??fontfile:t:\csname\??typescriptdefaultstyles\fontclass\endcsname}\s!Serif}
+
+%D \macros
+%D {fontstylesuffix}
+%D
+%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
+ {\ifx\fontalternative\s!tf \s!Regular \else
+ \ifx\fontalternative\s!bf \s!Bold \else
+ \ifx\fontalternative\s!sl \s!Slanted \else
+ \ifx\fontalternative\s!it \s!Italic \else
+ \ifx\fontalternative\s!bs \s!BoldSlanted \else
+ \ifx\fontalternative\s!bi \s!BoldItalic \else
+ \ifx\fontalternative\s!sc \s!Caps \else
+ \s!Regular \fi\fi\fi\fi\fi\fi\fi}%
+
+\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
+ \else\ifcsname\??fontfile#base\v_font_string_b\v_font_string_c\endcsname
+ \v_font_string_b\v_font_string_c
+ \else\ifcsname\??fontfile#base\v_font_string_a\endcsname
+ \v_font_string_a
+ \else\ifcsname\??fontfile#base\v_font_string_b\endcsname
+ \v_font_string_b
+ \else\ifcsname\??fontfile#base\v_font_string_c\endcsname
+ \v_font_string_c
+ \fi\fi\fi\fi\fi}
+
+%D The next macro can be used to make decisions based on the shape:
+
+\def\doifitalicelse#yes#nop%
+ {\ifx\fontalternative\s!sl#yes\else
+ \ifx\fontalternative\s!it#yes\else
+ \ifx\fontalternative\s!bs#yes\else
+ \ifx\fontalternative\s!bi#yes\else#nop\fi\fi\fi\fi}
+
+%D For an example of usage of the following command,
+%D see \type {cont-log.tex}.
+%D
+%D \starttyping
+%D \def\symbolicfont#specification{\definedfont[\glyphfontfile{#specification} sa *]}
+%D \stoptyping
+%D
+%D Since we know what scaling it to be applied, we can
+%D implement a much faster alternative:
+
+\installcorenamespace{symbolfont}
+
+\let\thedefinedfont\relax
+
+\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
+ \csname\??symbolfont\askedsymbolfont\endcsname
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\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
+ \csname\??symbolfont\askedsymbolfont\endcsname
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\setstyledsymbolicfont#fontname% quite a slowdown, glyphfontfile
+ {\edef\askedsymbolfont{\truefontname{\glyphfontfile{#fontname}} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \csname\??symbolfont\askedsymbolfont\endcsname
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\setdirectsymbolicfont#fontname%
+ {\edef\askedsymbolfont{\truefontname{#fontname} at \the\dimexpr\currentfontbodyscale\dimexpr\fontbody}%
+ \ifcsname\??symbolfont\askedsymbolfont\endcsname
+ \csname\??symbolfont\askedsymbolfont\endcsname
+ \else
+ \font_basics_define_symbolic_font
+ \fi}
+
+\def\font_basics_define_symbolic_font
+ {\definefont[currentsymbolfont][\askedsymbolfont]%
+ \currentsymbolfont
+ \global\expandafter\let\csname\??symbolfont\askedsymbolfont\endcsname\lastrawfontcall}
+
+\unexpanded\def\getnamedglyphstyled#fontname#character{{\setstyledsymbolicfont{#fontname}\ctxcommand{fontchar("#character")}}}
+\unexpanded\def\getnamedglyphdirect#fontname#character{{\setdirectsymbolicfont{#fontname}\ctxcommand{fontchar("#character")}}}
+\unexpanded\def\getglyphstyled #fontname#character{{\setstyledsymbolicfont{#fontname}\doifnumberelse{#character}\char\donothing#2}}
+\unexpanded\def\getglyphdirect #fontname#character{{\setdirectsymbolicfont{#fontname}\doifnumberelse{#character}\char\donothing#2}}
+
+% this one is wrong:
+
+\unexpanded\def\getscaledglyph#scale#name#content%
+ {{\setscaledstyledsymbolicfont\fontbody{#scale}{#name}\doifnumberelse{#content}\char\donothing#content}}
+
+\let\getglyph \getglyphstyled % old
+\let\getrawglyph \getglyphdirect % old
+\let\symbolicsizedfont\setscaledstyledsymbolicfont % old
+\let\symbolicfont \setstyledsymbolicfont % old
+
+\unexpanded\def\symbolicscaledfont{\setsscaledstyledsymbolicfont\fontbody}
+\unexpanded\def\symbolicscaledfont{\setscaledstyledsymbolicfont\fontbody}
+
+%D The last implementation of \type {\getglyph} permits
+%D definitions like:
+%D
+%D \starttyping
+%D \definefontsynonym [EuroSans] [eurose]
+%D \definefontsynonym [EuroSansBold] [euroseb]
+%D \definefontsynonym [EuroSansItalic] [eurosei]
+%D \definefontsynonym [EuroSansSlanted] [eurosei]
+%D \definefontsynonym [EuroSansBoldItalic] [eurosebi]
+%D \definefontsynonym [EuroSansBoldSlanted] [eurosebi]
+%D
+%D \definesymbol [euro] [\getglyph{Euro}{\char160}]
+%D
+%D \def\euro{\symbol[euro]}
+%D \stoptyping
+%D
+%D These definitions guarantee that the next calls work okay:
+%D
+%D \starttyping
+%D \ss \tf\euro \bf\euro \sla\euro \itd\euro \bs\euro \bic\euro
+%D \stoptyping
+%D
+%D The shape as well as the size is adapted to the current
+%D environment.
+
+%D \macros
+%D {setfont}
+%D
+%D Every now and then we want to define a font directly, for
+%D instance when we typeset title pages. The next macro saves
+%D some typing:
+
+\unexpanded\def\setfont% geen \font_helpers_set_font mogelijk
+ {\afterassignment\font_basics_set_font\font\nextfont=}
+
+\def\font_basics_set_font
+ {\nextfont\setupinterlinespace}% hm, we need to use \setuplocalinterlinespace
+
+%D One can call this macro as:
+%D
+%D \starttyping
+%D \setfont cmr10 at 60pt
+%D \stoptyping
+%D
+%D After which the font is active and the baselines and
+%D struts are set.
+
+%D \macros{doiffontcharelse}
+
+\unexpanded\def\doiffontcharelse#specification#unicode% this could be a direct lua call
+ {\begingroup
+ \font_basics_define_font_without_parameters{thedefinedfont}{#specification}%
+ \iffontchar\font#unicode\relax
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \endgroup\expandafter\secondoftwoarguments
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-syn.lua b/Master/texmf-dist/tex/context/base/font-syn.lua
index 1d444cdc705..c4f0e948b87 100644
--- a/Master/texmf-dist/tex/context/base/font-syn.lua
+++ b/Master/texmf-dist/tex/context/base/font-syn.lua
@@ -13,6 +13,7 @@ local next, tonumber = next, tonumber
local gsub, lower, match, find, lower, upper = string.gsub, string.lower, string.match, string.find, string.lower, string.upper
local find, gmatch = string.find, string.gmatch
local concat, sort, format = table.concat, table.sort, string.format
+local serialize = table.serialize
local lpegmatch = lpeg.match
local utfgsub, utflower = utf.gsub, utf.lower
local unpack = unpack or table.unpack
@@ -31,8 +32,6 @@ local report_names = logs.reporter("fonts","names")
using a table that has keys filtered from the font related files.</p>
--ldx]]--
-local texsprint = (tex and tex.sprint) or print
-
fonts = fonts or { } -- also used elsewhere
local names = { }
@@ -316,7 +315,7 @@ local function cleanname(name)
end
local function cleanfilename(fullname,defaultsuffix)
- local _, _, name, suffix = file.splitname(fullname)
+ local path, name, suffix = file.splitname(fullname)
name = gsub(lower(name),"[^%a%d]","")
if suffix and suffix ~= "" then
return name .. ".".. suffix
@@ -916,10 +915,12 @@ local function is_reloaded()
if not reloaded then
local data = names.data
if autoreload then
- local c_status = table.serialize(resolvers.datastate())
- local f_status = table.serialize(data.datastate)
+ local c_status = serialize(resolvers.datastate())
+ local f_status = serialize(data.datastate)
if c_status == f_status then
- report_names("font database has matching configuration and file hashes")
+ if trace_names then
+ report_names("font database has matching configuration and file hashes")
+ end
return
else
report_names("font database has mismatching configuration and file hashes")
@@ -1024,14 +1025,28 @@ function names.resolve(askedname,sub)
end
end
+-- function names.getfilename(askedname,suffix) -- last resort, strip funny chars
+-- names.load()
+-- local files = names.data.files
+-- askedname = files and files[cleanfilename(askedname,suffix)] or ""
+-- if askedname == "" then
+-- return ""
+-- else -- never entered
+-- return resolvers.findbinfile(askedname,suffix) or ""
+-- end
+-- end
+
function names.getfilename(askedname,suffix) -- last resort, strip funny chars
names.load()
local files = names.data.files
- askedname = files and files[cleanfilename(askedname,suffix)] or ""
- if askedname == "" then
- return ""
- else
- return resolvers.findbinfile(askedname,suffix) or ""
+ local cleanname = cleanfilename(askedname,suffix)
+ local found = files and files[cleanname] or ""
+ if found == "" and is_reloaded() then
+ files = names.data.files
+ found = files and files[cleanname] or ""
+ end
+ if found and found ~= "" then
+ return resolvers.findbinfile(found,suffix) or "" -- we still need to locate it
end
end
@@ -1240,7 +1255,7 @@ local function collect(stage,found,done,name,weight,style,width,variant,all)
report_names("resolving name '%s', weight '%s', style '%s', width '%s', variant '%s'",
name or "?",tostring(weight),tostring(style),tostring(width),tostring(variant))
end
- --~ print(name,table.serialize(family))
+ --~ print(name,serialize(family))
if weight and weight ~= "" then
if style and style ~= "" then
if width and width ~= "" then
diff --git a/Master/texmf-dist/tex/context/base/font-tfm.lua b/Master/texmf-dist/tex/context/base/font-tfm.lua
index 8f0a99d5aee..b1ec7c1dec2 100644
--- a/Master/texmf-dist/tex/context/base/font-tfm.lua
+++ b/Master/texmf-dist/tex/context/base/font-tfm.lua
@@ -63,6 +63,7 @@ local function read_from_tfm(specification)
local tfmdata = font.read_tfm(filename,size) -- not cached, fast enough
if tfmdata then
local features = specification.features and specification.features.normal or { }
+ local resources = tfmdata.resources or { }
local properties = tfmdata.properties or { }
local parameters = tfmdata.parameters or { }
local shared = tfmdata.shared or { }
@@ -76,9 +77,20 @@ local function read_from_tfm(specification)
shared.processes = next(features) and tfm.setfeatures(tfmdata,features) or nil
--
tfmdata.properties = properties
+ tfmdata.resources = resources
tfmdata.parameters = parameters
tfmdata.shared = shared
--
+ parameters.slant = parameters.slant or parameters[1] or 0
+ parameters.space = parameters.space or parameters[2] or 0
+ parameters.space_stretch = parameters.space_stretch or parameters[3] or 0
+ parameters.space_shrink = parameters.space_shrink or parameters[4] or 0
+ parameters.x_height = parameters.x_height or parameters[5] or 0
+ parameters.quad = parameters.quad or parameters[6] or 0
+ parameters.extra_space = parameters.extra_space or parameters[7] or 0
+ --
+ constructors.enhanceparameters(parameters) -- official copies for us
+ --
if constructors.resolvevirtualtoo then
fonts.loggers.register(tfmdata,file.extname(filename),specification) -- strange, why here
local vfname = findbinfile(specification.name, 'ovf')
@@ -95,9 +107,8 @@ local function read_from_tfm(specification)
end
end
--
- if next(features) then
- constructors.applymanipulators("tfm",tfmdata,specification.features.normal,trace_features,report_tfm)
- end
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("tfm",tfmdata,allfeatures.normal,trace_features,report_tfm)
if not features.encoding then
local encoding, filename = match(properties.filename,"^(.-)%-(.*)$") -- context: encoding-name.*
if filename and encoding and encodings.known[encoding] then
@@ -115,7 +126,7 @@ local function check_tfm(specification,fullname) -- we could split up like afm/o
foundname = findbinfile(fullname, 'ofm') or "" -- not needed in context
end
if foundname == "" then
- foundname = fonts.names.getfilename(fullname,"tfm")
+ foundname = fonts.names.getfilename(fullname,"tfm") or ""
end
if foundname ~= "" then
specification.filename = foundname
diff --git a/Master/texmf-dist/tex/context/base/font-tra.mkiv b/Master/texmf-dist/tex/context/base/font-tra.mkiv
index 37ea4541a0f..353d9e7a511 100644
--- a/Master/texmf-dist/tex/context/base/font-tra.mkiv
+++ b/Master/texmf-dist/tex/context/base/font-tra.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Tracing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -14,6 +14,80 @@
\unprotect
%D \macros
+%D {showbodyfont}
+%D
+%D One can call for a rather simple overview of a bodyfont and the
+%D relations between its alternative fonts.
+%D
+%D \showsetup{showbodyfont}
+%D
+%D The current bodyfont (here we omitted the argument) looks like:
+%D
+%D \showbodyfont
+%D
+%D The implementation is rather straightforward in using
+%D \type{\halign}.
+
+\fetchruntimecommand \showbodyfont {\f!fontprefix\s!run}
+
+%D \macros
+%D {showfontstrip, testminimalbaseline, showminimalbaseline}
+%D
+%D The next command can come in handy when combining
+%D different fonts into a collection (typeface) and
+%D determining optimal baseline distances.
+%D
+%D \showfontstrip \blank \showminimalbaseline
+
+\fetchruntimecommand \showfontstrip {\f!fontprefix\s!run}
+\fetchruntimecommand \testminimalbaseline {\f!fontprefix\s!run}
+\fetchruntimecommand \showminimalbaseline {\f!fontprefix\s!run}
+
+%D \macros
+%D {showkerning}
+%D
+%D A goody is:
+%D
+%D \showkerning{Can you guess what kerning is?}
+
+\fetchruntimecommand \showkerning {\f!fontprefix\s!run}
+
+%D \macros
+%D {showbodyfontenvironment,showfont,showfontstyle,showligatures}
+%D
+%D The current bodyfontenvironment is:
+%D
+%D \showbodyfontenvironment
+%D
+%D This overview is generated using:
+%D
+%D \showsetup{showbodyfontenvironment}
+
+\fetchruntimecommand \showbodyfontenvironment {\f!fontprefix\s!run}
+
+%D
+%D The following command generates a fontmap:
+%D
+%D \startbuffer
+%D \showfont[SansBold at 12pt]
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+\fetchruntimecommand \showfont {\f!fontprefix\s!run}
+\fetchruntimecommand \showfontstyle {\f!fontprefix\s!run}
+\fetchruntimecommand \showligature {\f!fontprefix\s!run}
+\fetchruntimecommand \showligatures {\f!fontprefix\s!run}
+\fetchruntimecommand \showcharratio {\f!fontprefix\s!run}
+\fetchruntimecommand \showfontparameters {\f!fontprefix\s!run}
+
+\unexpanded\def\checkcharactersinfont {\ctxcommand{checkcharactersinfont }}
+\unexpanded\def\removemissingcharacters{\ctxcommand{removemissingcharacters}}
+\unexpanded\def\showchardata #1{\ctxcommand{showchardata("#1")}}
+\unexpanded\def\showfontdata {\ctxcommand{showfontparameters()}}
+
+%D \macros
%D {doiffontpresentelse}
%D
%D \starttyping
@@ -50,6 +124,8 @@
{\begingroup
\tttf\language\minusone
\veryraggedright
+ \forgetparindent
+ \forgeteverypar
\hangindent1em
\hangafter\plusone
\dontleavehmode\hbox{\detokenize{#1}}\removeunwantedspaces
@@ -67,7 +143,11 @@
{\ctxlua{nodes.tracers.steppers.features()}}
\def\showotfsteps
- {\dontleavehmode\bgroup\tttf \language\minusone features: \showotfstepfeatures\egroup
+ {\begingroup
+ \veryraggedright
+ \forgetparindent
+ \forgeteverypar
+ \dontleavehmode\bgroup\tttf \language\minusone features: \showotfstepfeatures\egroup
\blank
\dontleavehmode\bgroup\tttf result:\egroup
\blank
@@ -84,14 +164,18 @@
\blank
\startlinecorrection
\ruledhbox % can be mode
- \bgroup\resetallattributes\showotfstepglyphs\recurselevel\egroup % reset is new, we don't want additional processing
+ \bgroup\resetallattributes\showotfstepglyphs\recurselevel\egroup % reset is new, we don't want additional processing
\stoplinecorrection
- \blank}}
+ \blank}%
+ \endgroup}
\unexpanded\def\startotfsample
{\enabletrackers[*otf.sample]% beware, kind of global
\startotfcollecting
- \begingroup}
+ \begingroup
+ \veryraggedright
+ \forgetparindent
+ \forgeteverypar}
\unexpanded\def\stopotfsample
{\endgroup
@@ -104,6 +188,9 @@
\def\showotfcomposition#1#2#3% {font*features at size}, rl=-1, text
{\begingroup
+ \veryraggedright
+ \forgetparindent
+ \forgeteverypar
\setupcolors[\c!state=\v!start]% can be option
\startotfsample
\global\setbox\otfcompositionbox\hbox{\definedfont[#1]\ifnum#2<0 \textdir TRT\else\ifnum#2>0 \textdir TLT\fi\fi\relax#3}%
diff --git a/Master/texmf-dist/tex/context/base/font-uni.mkii b/Master/texmf-dist/tex/context/base/font-uni.mkii
index 02ab6ce2cee..77eb680e20f 100644
--- a/Master/texmf-dist/tex/context/base/font-uni.mkii
+++ b/Master/texmf-dist/tex/context/base/font-uni.mkii
@@ -5,7 +5,7 @@
%D subtitle=\UNICODE,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-uni.mkiv b/Master/texmf-dist/tex/context/base/font-uni.mkiv
index 8fb5d099691..223d27606b7 100644
--- a/Master/texmf-dist/tex/context/base/font-uni.mkiv
+++ b/Master/texmf-dist/tex/context/base/font-uni.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\UNICODE,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-unk.mkii b/Master/texmf-dist/tex/context/base/font-unk.mkii
index 30f82478186..241369f6812 100644
--- a/Master/texmf-dist/tex/context/base/font-unk.mkii
+++ b/Master/texmf-dist/tex/context/base/font-unk.mkii
@@ -5,7 +5,7 @@
%D subtitle=Unknown Defaults,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/font-unk.mkiv b/Master/texmf-dist/tex/context/base/font-unk.mkiv
index bd699ef71c9..988e5df3d3c 100644
--- a/Master/texmf-dist/tex/context/base/font-unk.mkiv
+++ b/Master/texmf-dist/tex/context/base/font-unk.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Unknown Defaults,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -43,25 +43,11 @@
\definefontsynonym [MonoCaps] [unknown]
\definefontsynonym [MathRoman] [unknown]
-\definefontsynonym [MathExtension] [unknown]
-\definefontsynonym [MathItalic] [unknown]
-\definefontsynonym [MathSymbol] [unknown]
-
-\definefontsynonym [MathNoName] [unknown]
-
-\definefontsynonym [MathAlpha] [unknown]
-\definefontsynonym [MathBeta] [unknown]
-\definefontsynonym [MathGamma] [unknown]
-\definefontsynonym [MathDelta] [unknown]
-
-\definefontsynonym [MathRomanBold] [MathRoman] % todo:
-\definefontsynonym [MathExtensionBold] [MathExtension] % [MathRoman]
-\definefontsynonym [MathItalicBold] [MathItalic] % [MathRoman]
-\definefontsynonym [MathSymbolBold] [MathSymbol] % [MathRoman]
-\definefontsynonym [MathAlphaBold] [MathAlpha] % [MathRoman]
-\definefontsynonym [MathBetaBold] [MathBeta] % [MathRoman]
-\definefontsynonym [MathGammaBold] [MathGamma] % [MathRoman]
-\definefontsynonym [MathDeltaBold] [MathDelta] % [MathRoman]
+\definefontsynonym [MathRomanL2R] [MathRoman]
+\definefontsynonym [MathRomanR2L] [MathRoman]
+\definefontsynonym [MathRomanBold] [MathRoman]
+\definefontsynonym [MathRomanBoldL2R] [MathRomanBold]
+\definefontsynonym [MathRomanBoldR2L] [MathRomanBold]
\definefontsynonym [Handwriting] [unknown]
\definefontsynonym [Calligraphic] [unknown]
@@ -70,13 +56,13 @@
%D style (so, Bold may expand to SansBold or SerifBold, depending
%D on the default style in the typeface).
-\definefontsynonym[\s!Normal] [\noexpand\fontstringD]
-\definefontsynonym[\s!Bold] [\noexpand\fontstringD\noexpand\s!Bold]
-\definefontsynonym[\s!Italic] [\noexpand\fontstringD\noexpand\s!Italic]
-\definefontsynonym[\s!Slanted] [\noexpand\fontstringD\noexpand\s!Slanted]
-\definefontsynonym[\s!BoldItalic] [\noexpand\fontstringD\noexpand\s!BoldItalic]
-\definefontsynonym[\s!BoldSlanted][\noexpand\fontstringD\noexpand\s!BoldSlanted]
-\definefontsynonym[\s!Caps] [\noexpand\fontstringD\noexpand\s!Caps]
+\definefontsynonym[\s!Normal] [\noexpand\v_font_string_d]
+\definefontsynonym[\s!Bold] [\noexpand\v_font_string_d\noexpand\s!Bold]
+\definefontsynonym[\s!Italic] [\noexpand\v_font_string_d\noexpand\s!Italic]
+\definefontsynonym[\s!Slanted] [\noexpand\v_font_string_d\noexpand\s!Slanted]
+\definefontsynonym[\s!BoldItalic] [\noexpand\v_font_string_d\noexpand\s!BoldItalic]
+\definefontsynonym[\s!BoldSlanted][\noexpand\v_font_string_d\noexpand\s!BoldSlanted]
+\definefontsynonym[\s!Caps] [\noexpand\v_font_string_d\noexpand\s!Caps]
%D Also handy:
@@ -117,43 +103,45 @@
%D Next we define roman, sans and monospaced font sets.
\definebodyfont [default] [rm]
- [tf=Serif sa 1,
- bf=SerifBold sa 1,
- it=SerifItalic sa 1,
- sl=SerifSlanted sa 1,
- bi=SerifBoldItalic sa 1,
- bs=SerifBoldSlanted sa 1,
- sc=SerifCaps sa 1]
+ [\s!tf=Serif sa 1,
+ \s!bf=SerifBold sa 1,
+ \s!it=SerifItalic sa 1,
+ \s!sl=SerifSlanted sa 1,
+ \s!bi=SerifBoldItalic sa 1,
+ \s!bs=SerifBoldSlanted sa 1,
+ \s!sc=SerifCaps sa 1]
\definebodyfont [default] [ss]
- [tf=Sans sa 1,
- bf=SansBold sa 1,
- it=SansItalic sa 1,
- sl=SansSlanted sa 1,
- bi=SansBoldItalic sa 1,
- bs=SansBoldSlanted sa 1,
- sc=SansCaps sa 1]
+ [\s!tf=Sans sa 1,
+ \s!bf=SansBold sa 1,
+ \s!it=SansItalic sa 1,
+ \s!sl=SansSlanted sa 1,
+ \s!bi=SansBoldItalic sa 1,
+ \s!bs=SansBoldSlanted sa 1,
+ \s!sc=SansCaps sa 1]
\definebodyfont [default] [tt]
- [tf=Mono sa 1,
- bf=MonoBold sa 1,
- it=MonoItalic sa 1,
- sl=MonoSlanted sa 1,
- bi=MonoBoldItalic sa 1,
- bs=MonoBoldSlanted sa 1,
- sc=MonoCaps sa 1]
+ [\s!tf=Mono sa 1,
+ \s!bf=MonoBold sa 1,
+ \s!it=MonoItalic sa 1,
+ \s!sl=MonoSlanted sa 1,
+ \s!bi=MonoBoldItalic sa 1,
+ \s!bs=MonoBoldSlanted sa 1,
+ \s!sc=MonoCaps sa 1]
\definebodyfont [default] [mm]
- [mr=MathRoman mo 1]
-
-\definebodyfont [bfmath] [mm]
- [mr=MathRomanBold mo 1]
+ [\s!mr =MathRoman mo 1,
+ \s!mrlr=MathRomanL2R mo 1,
+ \s!mrrl=MathRomanR2L mo 1,
+ \s!mb =MathRomanBold mo 1,
+ \s!mblr=MathRomanBoldL2R mo 1,
+ \s!mbrl=MathRomanBoldR2L mo 1]
\definebodyfont [default] [hw]
- [tf=Handwriting sa 1]
+ [\s!tf=Handwriting sa 1]
\definebodyfont [default] [cg]
- [tf=Calligraphy sa 1]
+ [\s!tf=Calligraphy sa 1]
%D These definitions come into action as soon as names are
%D mapped onto real file names (or names that themselves are
diff --git a/Master/texmf-dist/tex/context/base/font-var.mkvi b/Master/texmf-dist/tex/context/base/font-var.mkvi
new file mode 100644
index 00000000000..e50c2bad458
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/font-var.mkvi
@@ -0,0 +1,53 @@
+%D \module
+%D [ file=font-var,
+%D version=2011.01.13, % (copied fron font-ini)
+%D title=\CONTEXT\ Font Macros,
+%D subtitle=Common Variables,
+%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 / Common Variables}
+
+\unprotect
+
+% some more will move here
+
+%D \macros
+%D {fontstyle,fontalternative,fontsize,fontbody}
+%D
+%D Within a bodyfont, fonts can come in different sizes. For instance
+%D \type {\tf} is accompanied by \type {\tfa}, \type {\tfb} etc. The
+%D first two characters denote the alternative, while the third
+%D character in these sequences represents the size. The actual size
+%D is saved in a macro. The styles, being roman (\type {\rm}), sans
+%D serif (\type {\ss}) etc. are also available in macros in \type {rm},
+%D \type {ss} etc. form.
+
+% fontclass % modern dejavu
+% fontbody % ... 10pt 11pt 12pt ...
+% fontstyle % rm ss tt mm hw cg ...
+% fontalternative % tf bf sl it bs bi sc ...
+% fontsize % a b c d ...
+% fontface % 0=normal 1=text 2=script 3=scriptscript 4=x 5=xx (math are temporary)
+
+\def\normalizedbodyfontsize{12pt}
+
+\def\defaultfontbody {\normalizedbodyfontsize}
+\let\defaultfontstyle \empty
+\let\defaultfontalternative \s!tf
+\let\defaultfontsize \empty
+
+\let\globalfontclass \empty
+\let\fontclass \empty
+\let\fontbody \defaultfontbody
+\let\fontstyle \defaultfontstyle
+\let\fontalternative \defaultfontalternative
+\let\fontsize \defaultfontsize
+\let\fontface \!!zerocount
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/font-xtx.mkii b/Master/texmf-dist/tex/context/base/font-xtx.mkii
index 9930124be20..e7a6c8d80cc 100644
--- a/Master/texmf-dist/tex/context/base/font-xtx.mkii
+++ b/Master/texmf-dist/tex/context/base/font-xtx.mkii
@@ -5,7 +5,7 @@
%D subtitle=\XETEX\ Hacks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/grph-epd.mkiv b/Master/texmf-dist/tex/context/base/grph-epd.mkiv
index b066e1adcbd..947128b6b5b 100644
--- a/Master/texmf-dist/tex/context/base/grph-epd.mkiv
+++ b/Master/texmf-dist/tex/context/base/grph-epd.mkiv
@@ -5,34 +5,36 @@
%D subtitle=Merging Goodies,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Graphic Macros / Merging Coodies}
+\writestatus{loading}{ConTeXt Graphic Macros / Merging Goodies}
\unprotect
\registerctxluafile{grph-epd}{1.001}
-\def\figurereference {\ctxlua{figures.tprint("status","reference")}}
+\def\figurereference{\ctxlua{figures.tprint("status","reference")}} % might become private
-\defineoverlay[epdf-overlay][\directsetup{epdf-overlay}]
+\defineoverlay[system:graphics:epdf][\directsetup{system:graphics:epdf}]
-\startsetups epdf-overlay
+\startsetups system:graphics:epdf
\ctxlua{figures.mergegoodies("\@@efinteraction")}%
\reference[\figurereference]{}% todo: dest area
\stopsetups
-\def\doaddpdffiguregoodies
+\def\grph_epdf_add_overlay
{\global\setbox\foundexternalfigure\vbox\bgroup
- \framed[\c!offset=\v!overlay,\c!background={\v!foreground,epdf-overlay}]{\box\foundexternalfigure}%
+ \framed[\c!offset=\v!overlay,\c!background={\v!foreground,system:graphics:epdf}]{\box\foundexternalfigure}%
\egroup}
\appendtoks
- \iflocation\doif\figurefiletype{pdf}{\doifnot\@@efinteraction\v!none\doaddpdffiguregoodies}\fi
+ \iflocation
+ \doif\figurefiletype{pdf}{\doifnot\@@efinteraction\v!none\grph_epdf_add_overlay}%
+ \fi
\to \externalfigurepostprocessors
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/grph-fig.mkii b/Master/texmf-dist/tex/context/base/grph-fig.mkii
index c7f990af276..c488ccc4f6c 100644
--- a/Master/texmf-dist/tex/context/base/grph-fig.mkii
+++ b/Master/texmf-dist/tex/context/base/grph-fig.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Inclusion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -285,7 +285,7 @@
\processcommalist[#1]\docommand}%
\global\setbox\colorbarbox\vbox
{\hskip2em\box\colorbarbox}%
- \global\wd\colorbarbox\zeropoint}
+ \wd\colorbarbox\zeropoint}
\def\placestartfigure[#1][#2][#3]#4\placestopfigure[#5]%
{\hbox
diff --git a/Master/texmf-dist/tex/context/base/grph-fig.mkiv b/Master/texmf-dist/tex/context/base/grph-fig.mkiv
index fad1c864a6f..1908e644522 100644
--- a/Master/texmf-dist/tex/context/base/grph-fig.mkiv
+++ b/Master/texmf-dist/tex/context/base/grph-fig.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Figure Inclusion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -33,27 +33,32 @@
\setfalse\externalfigurelevel
\settrue \externalfigureflush
+\installcorenamespace{externalfigures}
+
\def\doplaceexternalfigure[#1][#2][#3][#4][#5]%
{\doifsomething{#2}% catches \defineexternalfigure dummies
- {\doifundefinedelse{\??ef\??ef#2}
- {\dodoplaceexternalfigure[#1][#2][#3][#4][#5]}
- {\doifelse{#1}{#2}
- {\dodoplaceexternalfigure[#1][#2][#3][#4][#5]}
- {\getvalue{\??ef\??ef#2}[#5]}}}}
+ {\ifcsname\??externalfigures#2\endcsname
+ \doifelse{#1}{#2}
+ {\dodoplaceexternalfigure[#1][#2][#3][#4][#5]}
+ {\getvalue{\??externalfigures#2}[#5]}%
+ \else
+ \dodoplaceexternalfigure[#1][#2][#3][#4][#5]%
+ \fi}}
+
+\ifdefined\dotagfigure \else \let\dotagfigure\relax \fi
\def\dodoplaceexternalfigure[#1][#2][#3][#4][#5]%
{\bgroup
\dostarttagged\t!image\empty
\let\textunderscore\letterunderscore % {\string _} % space needed as _ is now letter in unprotected mode
\calculateexternalfigure[][#1][#2][#3][#4][#5]% [] is dummy dwcomp
+ \dotagfigure
\naturalvbox attr \imageattribute 2 {\box\foundexternalfigure}%
\dostoptagged
\egroup}
\def\externalfigurereplacement#1#2#3%
- {\setupcolors
- [\c!state=\v!local]%
- \normalexpanded{\localframed
+ {\normalexpanded{\localframed
[\??ef]
[\c!width=\figurewidth,
\c!height=\figureheight,
@@ -93,10 +98,7 @@
{\dodoubleargument\dodefineexternalfigure}
\def\dodefineexternalfigure[#1][#2]%
- {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][][][#2]}}
-
-\def\getexternalfigure#1% efef has 4 args already and take an 5th
- {\wait} % OBSOLETE
+ {\setvalue{\??externalfigures#1}{\doplaceexternalfigure[#1][][][#2]}}
% \useexternalfigure[alpha][koe]
% \useexternalfigure[beta] [koe] [breedte=1cm]
@@ -132,20 +134,6 @@
\def\useexternalfigure
{\doquadrupleempty\douseexternalfigure}
-% \def\douseexternalfigure[#1][#2][#3][#4]%
-% {\doifelsenothing{#1}
-% {\doifsomething{#2}
-% {\doifassignmentelse{#3}
-% {\setvalue{\??ef\??ef#2}{\doplaceexternalfigure[#2][#2][#3][#4]}}
-% {\setvalue{\??ef\??ef#2}{\doplaceexternalfigure[#2][#2][][#4]}}}}
-% {\doifelsenothing{#2}
-% {\doifassignmentelse{#3}
-% {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#1][][#3]}}
-% {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#1][#3][#4]}}}
-% {\doifassignmentelse{#3}
-% {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#2][][#3]}}
-% {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#2][#3][#4]}}}}}
-
\def\douseexternalfigure[#1][#2][#3][#4]%
{\doifelsenothing{#1}
{\doifsomething{#2}
@@ -161,7 +149,7 @@
{\dodouseexternalfigure{#1}{#2}{#3}{#4}}}}}
\def\dodouseexternalfigure#1#2#3#4%
- {\setvalue{\??ef\??ef#1}{\doplaceexternalfigure[#1][#2][#3][#4]}%
+ {\setvalue{\??externalfigures#1}{\doplaceexternalfigure[#1][#2][#3][#4]}%
\doanalyzeexternalfigurecollection[#2][#4]}
\newconditional\inexternalfigurecollection
@@ -229,135 +217,67 @@
\def\dosetefparameters#1#2#3% parent_id use_settings current_settings
{\doifelsenothing{#1} % inherit from parent
{\getparameters[\??ef][#2,#3]}
- {\doifdefinedelse{\??ef\??ef#1}
- {\pushmacro\doplaceexternalfigure
- \def\doplaceexternalfigure[##1][##2][##3][##4]{\getparameters[\??ef][##4,#2,#3]}%
- \getvalue{\??ef\??ef#1}%
- \popmacro\doplaceexternalfigure}
- {\getparameters[\??ef][#2,#3]}}}
+ {\ifcsname\??externalfigures#1\endcsname
+ \pushmacro\doplaceexternalfigure
+ \def\doplaceexternalfigure[##1][##2][##3][##4]{\getparameters[\??ef][##4,#2,#3]}%
+ \getvalue{\??externalfigures#1}%
+ \popmacro\doplaceexternalfigure
+ \else
+ \getparameters[\??ef][#2,#3]%
+ \fi}}
\unexpanded\def\externalfigure
{\dotripleempty\doexternalfigure}
+% \def\doexternalfigure[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings]
+% {\bgroup
+% \doifelsenothing{#1}
+% {\framed[\c!width=\defaultfigurewidth,\c!height=\defaultfigureheight]{external\\figure\\no name}}
+% {\ifcsname\??externalfigures#1\endcsname
+% \doifassignmentelse{#2}
+% {\getvalue{\??externalfigures#1}[#2]}%
+% {\getvalue{\??externalfigures#1}[#3]}%
+% \else
+% \useexternalfigure[\s!dummy][#1][#2][#3]%
+% \getvalue{\??externalfigures\s!dummy}[]% [] is dummy arg 5
+% \fi}%
+% \globallet\currentresourcecomment\empty
+% \egroup}
+
\def\doexternalfigure[#1][#2][#3]% [label][file][settings] | [file][settings] | [file][parent][settings]
- {\bgroup
- \doifelsenothing{#1}
- {\framed[\c!width=\defaultfigurewidth,\c!height=\defaultfigureheight]{external\\figure\\no name}}
- {\doifundefinedelse{\??ef\??ef#1}
- {\useexternalfigure[\s!dummy][#1][#2][#3]%
- \getvalue{\??ef\??ef\s!dummy}[]} % [] is dummy arg 5
- {\doifassignmentelse{#2}
- {\getvalue{\??ef\??ef#1}[#2]}%
- {\getvalue{\??ef\??ef#1}[#3]}}}%
+ {\bgroup % also catched #1 == empty ... scales nicer now
+ \ifcsname\??externalfigures#1\endcsname
+ \doifassignmentelse{#2}
+ {\getvalue{\??externalfigures#1}[#2]}%
+ {\getvalue{\??externalfigures#1}[#3]}%
+ \else
+ \useexternalfigure[\s!dummy][#1][#2][#3]%
+ \getvalue{\??externalfigures\s!dummy}[]% [] is dummy arg 5
+ \fi
\globallet\currentresourcecomment\empty
\egroup}
-\long\def\resourcecomment#1%
- {\long\gdef\currentresourcecomment{#1}}
+\def\resourcecomment#1%
+ {\gdef\currentresourcecomment{#1}}
-\long\unexpanded\def\startresourcecomment#1\stopresourcecomment
- {\long\gdef\currentresourcecomment{#1}}
+\unexpanded\def\startresourcecomment#1\stopresourcecomment
+ {\gdef\currentresourcecomment{#1}}
\let\currentresourcecomment\empty
-
-\def\showexternalfigures % maybe run time command is better, but no core-run, unless figs-run ...
+
+\unexpanded\def\showexternalfigures % maybe run time command is better, but no core-run, unless figs-run ...
{%\writestatus\m!system{for \string\showexternalfigures\space see \truefilename{x-res-20}.tex}
- \usemodule[res-20]\showexternalfigures} % so for the moment we do it this way
-
-\def\overlayfigure#1%
+ \usemodule[res-20]%
+ \showexternalfigures} % so for the moment we do it this way
+
+\unexpanded\def\overlayfigure#1%
{\externalfigure[#1][\c!width=\overlaywidth,\c!height=\overlayheight]}
-
-%D Still undocumented! No one uses it I think, better be done with layers.
-% when there is need for this i'll reimplement it
-%
-% \newcount\efreference
-% \newdimen\efxsteps
-% \newdimen\efysteps
-%
-% \def\calculateefsteps
-% {\ifnum0\@@exxmax=\zerocount
-% \ifnum0\@@exymax=\zerocount
-% \def\@@exymax{24}%
-% \fi
-% \efysteps\figureheight \divide\efysteps \@@exymax
-% \efxsteps\efysteps
-% \dimen0=\figurewidth
-% \advance\dimen0 \efysteps
-% \divide \dimen0 \efysteps
-% \edef\@@exxmax{\number\dimen0}%
-% \else
-% \efxsteps\figurewidth \divide\efxsteps \@@exxmax
-% \efysteps\figureheight \divide\efysteps \@@exymax
-% \fi}
-%
-% \def\efcomment#1(#2,#3)#4(#5,#6)% {kader}(x,y)(h,b)[...]{tekst}
-% {\def\complexefdocomment[##1]##2%
-% {\position(#2,#3)%
-% {\setnostrut
-% \framed
-% [\c!width=#5\efxsteps,
-% \c!height=#6\exysteps,
-% \c!offset=\v!none,
-% \c!frame=#1,
-% ##1]%
-% {##2}}}%
-% \complexorsimpleempty\efdocomment}
-%
-% \def\efnocomment(#1,#2)#3(#4,#5)% (x,y)(h,b)[...]{tekst}
-% {\def\complexefdonocomment[##1]##2{}%
-% \complexorsimpleempty\efdonocomment}
-%
-% \def\efdomarker(#1,#2)#3#4% (h,b){kader}{tekst}
-% {\framed
-% [\c!width=#1\efxsteps,
-% \c!height=#2\efysteps,
-% \c!offset=\v!none,
-% \c!frame=#3]%
-% {#4}}
-%
-% \def\effigure#1%
-% {\position(0,0){\getvalue{#1}}}
-%
-% \def\efdoarea(#1,#2)#3#4% (h,b){kader}{tekst}
-% {\bgroup
-% \setnostrut
-% \framed
-% [\c!width=#1\efxsteps,
-% \c!height=#2\efysteps,
-% \c!offset=\!!zeropoint,
-% \c!frame=#3]
-% {#4}%
-% \egroup}
-%
-% \def\efgoto(#1,#2)#3[#4]% (h,b)kader[ref]
-% {\setbox0=\vbox{\efdoarea(#1,#2)#3{}}%
-% \gotobox{\copy0}[#4]}
-%
-% \def\efmark(#1,#2)#3(#4,#5)#6[#7]%
-% {\advance\efreference \plusone
-% \position(#1,#2)
-% {\hbox{\the\efreference}}%
-% \position(#1,#2)
-% {\gotosomeinternal\s!vwb{#7}\realfolio
-% {\efdomarker(#4,#5)\v!on{\thisissomeinternal\s!vwa{#7}}}}}
-%
-% \def\eftext#1(#2,#3)#4(#5,#6)#7[#8]%
-% {\advance\efreference \plusone
-% \hbox
-% {\quad
-% \thisissomeinternal\s!vwb{#8}%
-% \gotosomeinternal \s!vwa{#8}\realfolio
-% {\hbox to 1.5em{\the\efreference\presetgoto\hfill}}%
-% \quad#1 (#2,#3) (#5,#6) [#8]\hfill}%
-% \endgraf}
-%
-% \def\efthisis(#1,#2)#3[#4]%
-% {\efdoarea(#1,#2){#3}{\pagereference[#4]}}
+%D Whatever
\newbox\colorbarbox
-\def\makecolorbar[#1]%
+\unexpanded\def\makecolorbar[#1]%
{\def\docommand##1%
{\color[##1]
{\blackrule
@@ -370,7 +290,7 @@
\processcommalist[#1]\docommand}%
\global\setbox\colorbarbox\vbox
{\hskip2em\box\colorbarbox}%
- \global\wd\colorbarbox\zeropoint}
+ \wd\colorbarbox\zeropoint}
\unexpanded\def\placestartfigure[#1][#2][#3]#4\placestopfigure[#5]%
{\hbox
@@ -407,7 +327,7 @@
{\teststartfigure[#1][#2][#3]#4\teststopfigure
\let\@@exframes\v!on}
{\let\@@exframes\v!off}%
- \setvalue{\??ef\??ef#1}%
+ \setvalue{\??externalfigures#1}%
{\dosingleempty{\placestartfigure[#1][#2][#3]#4\placestopfigure}}%
}% no longer \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}}
@@ -476,7 +396,7 @@
{\teststartfigure[#1][#2][#3]#4\teststopfigure
\let\@@exframe\v!on}
{\let\@@exframe\v!off}%
- \setvalue{\??ef\??ef#1}%
+ \setvalue{\??externalfigures#1}%
{\def\next{\placestartfigure[#1][#2][#3]#4\placestopfigure}%
\dosingleempty\next}%
}% no longer: \doifundefined{#1}{\setvalue{#1}{\getexternalfigure{#1}}}}
@@ -525,7 +445,7 @@
\def\dodotypesetbufferindeed#1%
{}
-
+
% for me only (manuals and such)
%
% \definetypesetting [name] [options] [settings-a]
@@ -540,17 +460,17 @@
% \typesetfile[oepsoeps.tex][width=10cm,frame=on]
% \stoptext
-\definesystemvariable{tz}
+\installcorenamespace{typesettingfile}
\unexpanded\def\definetypesetting{\dotripleempty\dodefinetypesetting}
\unexpanded\def\typesetfile {\dotripleempty\dotypesetfile}
\def\dodefinetypesetting[#1][#2][#3]% <name> options settings-a
- {\doifsomething{#1}{\setvalue{\??tz#1}{\dodotypesetfile{#2}{#3}}}}
+ {\doifsomething{#1}{\setvalue{\??typesettingfile#1}{\dodotypesetfile{#2}{#3}}}}
\def\dotypesetfile[#1][#2][#3]% <name> filename settings-b | filename options settings
- {\ifcsname\??tz#1\endcsname
- \csname\??tz#1\endcsname{#2}{#3}%
+ {\ifcsname\??typesettingfile#1\endcsname
+ \csname\??typesettingfile#1\endcsname{#2}{#3}%
\else\ifthirdargument % filename options settings
\dodotypesetfile{#2}{#3}{#1}{}%
\else\ifsecondargument % filename settings
@@ -570,7 +490,6 @@
\c!maxheight=\@@efheight,
\c!bodyfont=\bodyfontsize,
\c!directory=,
- \c!file=\f!utilityfilename.\f!figureextension,
\c!radius=.5\bodyfontsize,
\c!corner=\v!rectangular,
\c!frame=\v!off,
diff --git a/Master/texmf-dist/tex/context/base/grph-fil.lua b/Master/texmf-dist/tex/context/base/grph-fil.lua
index 0856f5b0854..1ec88b487fe 100644
--- a/Master/texmf-dist/tex/context/base/grph-fil.lua
+++ b/Master/texmf-dist/tex/context/base/grph-fil.lua
@@ -12,6 +12,8 @@ local trace_run = false trackers.register("graphic.runfile",function(v) trace_r
local report_run = logs.reporter("graphics","run")
+-- this code will move
+
local allocate = utilities.storage.allocate
local collected = allocate()
@@ -33,17 +35,20 @@ job.register('job.files.collected', tobesaved, initializer)
jobfiles.forcerun = false
-function jobfiles.run(name,command)
+function jobfiles.run(name,action)
local oldchecksum = collected[name]
local newchecksum = file.checksum(name)
if jobfiles.forcerun or not oldchecksum or oldchecksum ~= newchecksum then
if trace_run then
report_run("processing file, changes in '%s', processing forced",name)
end
- if command and command ~= "" then
- os.execute(command)
+ local ta = type(action)
+ if ta == "function" then
+ action(name)
+ elseif ta == "string" and action ~= "" then
+ os.execute(action)
else
- report_run("processing file, no command given for processing '%s'",name)
+ report_run("processing file, no action given for processing '%s'",name)
end
elseif trace_run then
report_run("processing file, no changes in '%s', not processed",name)
@@ -51,6 +56,8 @@ function jobfiles.run(name,command)
tobesaved[name] = newchecksum
end
+--
+
function jobfiles.context(name,options)
if type(name) == "table" then
local result = { }
diff --git a/Master/texmf-dist/tex/context/base/grph-inc.lua b/Master/texmf-dist/tex/context/base/grph-inc.lua
index 7dee63eaf5f..15aff892505 100644
--- a/Master/texmf-dist/tex/context/base/grph-inc.lua
+++ b/Master/texmf-dist/tex/context/base/grph-inc.lua
@@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['grph-inc'] = {
-- figures -> managers.figures
+-- todo: empty filename or only suffix always false (not found)
+
-- lowercase types
-- mps tex tmp svg
-- partly qualified
@@ -20,7 +22,7 @@ if not modules then modules = { } end modules ['grph-inc'] = {
--[[
The ConTeXt figure inclusion mechanisms are among the oldest code
-in ConTeXt and evolve dinto a complex whole. One reason is that we
+in ConTeXt and evolved into a complex whole. One reason is that we
deal with backend in an abstract way. What complicates matters is
that we deal with internal graphics as well: TeX code, MetaPost code,
etc. Later on figure databases were introduced, which resulted in
@@ -120,6 +122,8 @@ figures.used = allocate()
figures.found = allocate()
figures.suffixes = allocate()
figures.patterns = allocate()
+figures.resources = allocate()
+
figures.boxnumber = figures.boxnumber or 0
figures.defaultsearch = true
@@ -139,6 +143,7 @@ figures.programs = allocate() local programs = figures.programs
figures.localpaths = allocate {
".", "..", "../.."
}
+
figures.cachepaths = allocate {
prefix = "",
path = ".",
@@ -148,7 +153,7 @@ figures.cachepaths = allocate {
figures.paths = allocate(table.copy(figures.localpaths))
figures.order = allocate{
- "pdf", "mps", "jpg", "png", "jp2", "jbig", "svg", "eps", "gif", "mov", "buffer", "tex", "cld",
+ "pdf", "mps", "jpg", "png", "jp2", "jbig", "svg", "eps", "tif", "gif", "mov", "buffer", "tex", "cld",
}
figures.formats = allocate{
@@ -161,6 +166,7 @@ figures.formats = allocate{
["svg"] = { list = { "svg", "svgz" } },
["eps"] = { list = { "eps", "ai" } },
["gif"] = { list = { "gif" } },
+ ["tif"] = { list = { "tif", "tiff" } },
["mov"] = { list = { "mov", "flv", "mp4" } }, -- "avi" is not supported
["buffer"] = { list = { "tmp", "buffer", "buf" } },
["tex"] = { list = { "tex" } },
@@ -191,6 +197,12 @@ end
figures.setlookups()
+function figures.registerresource(t)
+ local n = #figures.resources + 1
+ figures.resources[n] = t
+ return n
+end
+
local function register(tag,target,what)
local data = figures.formats[target] -- resolver etc
if not data then
@@ -301,7 +313,7 @@ local function new() -- we could use metatables status -> used -> request but it
}
end
- -- use table.insert|remove
+-- use table.insert|remove
local lastfiguredata = nil -- will be topofstack or last so no { } (else problems with getfiguredimensions)
local callstack = { }
@@ -402,10 +414,12 @@ local function register(askedname,specification)
newformat = defaultformat
end
if trace_conversion then
- report_inclusion("checking conversion of '%s': old format '%s', new format '%s', conversion '%s', resolution '%s'",
- askedname,format,newformat,conversion or "default",resolution or "default")
+ report_inclusion("checking conversion of '%s' (%s): old format '%s', new format '%s', conversion '%s', resolution '%s'",
+ askedname,specification.fullname,format,newformat,conversion or "default",resolution or "default")
end
- local converter = (newformat ~= format) and converters[format]
+ -- quick hack
+ -- local converter = (newformat ~= format) and converters[format]
+ local converter = (newformat ~= format or resolution) and converters[format]
if converter then
if converter[newformat] then
converter = converter[newformat]
@@ -422,8 +436,7 @@ local function register(askedname,specification)
report_inclusion("no converter for '%s' -> '%s'",format,newformat)
end
if converter then
- -- local oldname = specification.fullname
- local oldname = specification.foundname
+ local oldname = specification.fullname
local newpath = file.dirname(oldname)
local oldbase = file.basename(oldname)
local newbase = file.removesuffix(oldbase)
@@ -435,7 +448,7 @@ local function register(askedname,specification)
end
if not file.is_writable(newpath) then
if trace_conversion then
- report_inclusion("[ath '%s'is not writable, forcing conversion path '.' ",newpath)
+ report_inclusion("path '%s'is not writable, forcing conversion path '.' ",newpath)
end
newpath = "."
end
@@ -459,23 +472,34 @@ local function register(askedname,specification)
local newtime = lfs.attributes(newname,'modification') or 0
if newtime == 0 or oldtime > newtime then
if trace_conversion then
- report_inclusion("converting '%s' from '%s' to '%s'",askedname,format,newformat)
+ report_inclusion("converting '%s' (%s) from '%s' to '%s'",askedname,oldname,format,newformat)
end
converter(oldname,newname,resolution or "")
else
if trace_conversion then
- report_inclusion("no need to convert '%s' from '%s' to '%s'",askedname,format,newformat)
+ report_inclusion("no need to convert '%s' (%s) from '%s' to '%s'",askedname,oldname,format,newformat)
end
end
- if io.exists(newname) then
+ if io.exists(newname) and io.size(newname) > 0 then
specification.foundname = oldname
specification.fullname = newname
specification.prefix = prefix
specification.subpath = subpath
specification.converted = true
format = newformat
+ if not figures.suffixes[format] then
+ -- maybe the new format is lowres.png (saves entry in suffixes)
+ -- so let's do thsi extra check
+ local suffix = file.suffix(newformat)
+ if figures.suffixes[suffix] then
+ if trace_figures then
+ report_inclusion("using suffix '%s' as format for '%s'",suffix,format)
+ end
+ format = suffix
+ end
+ end
elseif io.exists(oldname) then
- specification.fullname = newname
+ specification.fullname = oldname -- was newname
specification.converted = false
end
end
@@ -489,7 +513,7 @@ local function register(askedname,specification)
else
specification.found = true
if trace_figures then
- if validtypes[format] then
+ if validtypes[format] then -- format?
report_inclusion("format natively supported by backend: %s",format)
else
report_inclusion("format supported by output file format: %s",format)
@@ -508,7 +532,9 @@ end
local resolve_too = true -- urls
local function locate(request) -- name, format, cache
- local askedname = resolvers.cleanpath(request.name)
+ -- not resolvers.cleanpath(request.name) as it fails on a!b.pdf and b~c.pdf
+ -- todo: more restricted cleanpath
+ local askedname = request.name
local foundname = figures.found[askedname .. "->" .. (request.conversion or "default") .. "->" .. (request.resolution or "default")]
if foundname then
return foundname
@@ -556,10 +582,10 @@ local function locate(request) -- name, format, cache
if foundname then
return register(askedname, {
askedname = askedname,
- fullname = askedname,
+ fullname = foundname, -- askedname,
format = format,
cache = askedcache,
- foundname = foundname,
+--~ foundname = foundname,
conversion = askedconversion,
resolution = askedresolution,
})
@@ -571,10 +597,11 @@ local function locate(request) -- name, format, cache
end
if askedpath then
-- path and type given, todo: strip pieces of path
- if figures.exists(askedname,askedformat,resolve_too) then
+ local foundname = figures.exists(askedname,askedformat,resolve_too)
+ if foundname then
return register(askedname, {
askedname = askedname,
- fullname = askedname,
+ fullname = foundname, -- askedname,
format = askedformat,
cache = askedcache,
conversion = askedconversion,
@@ -625,10 +652,11 @@ local function locate(request) -- name, format, cache
for j=1,#list do
local suffix = list[j]
local check = file.addsuffix(askedname,suffix)
- if figures.exists(check,format,resolve_too) then
+ local foundname = figures.exists(check,format,resolve_too)
+ if foundname then
return register(askedname, {
askedname = askedname,
- fullname = check,
+ fullname = foundname, -- check,
format = format,
cache = askedcache,
conversion = askedconversion,
@@ -659,15 +687,18 @@ local function locate(request) -- name, format, cache
if trace_figures then
report_inclusion("warning: skipping path %s",path)
end
- elseif figures.exists(check,format,true) then
- return register(askedname, {
- askedname = askedname,
- fullname = check,
- format = format,
- cache = askedcache,
- conversion = askedconversion,
- resolution = askedresolution,
- })
+ else
+ local foundname = figures.exists(check,format,true)
+ if foundname then
+ return register(askedname, {
+ askedname = askedname,
+ fullname = foundname, -- check
+ format = format,
+ cache = askedcache,
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
+ end
end
end
end
@@ -686,10 +717,11 @@ local function locate(request) -- name, format, cache
for k=1,#list do
local suffix = list[k]
local check = path .. "/" .. file.replacesuffix(askedbase,suffix)
- if figures.exists(check,format,resolve_too) then
+ local foundname = figures.exists(check,format,resolve_too)
+ if foundname then
return register(askedname, {
askedname = askedname,
- fullname = check,
+ fullname = foudname, -- check,
format = format,
cache = askedcache,
conversion = askedconversion,
@@ -725,7 +757,10 @@ local function locate(request) -- name, format, cache
end
end
end
- return register(askedname)
+ return register(askedname, { -- these two are needed for hashing 'found'
+ conversion = askedconversion,
+ resolution = askedresolution,
+ })
end
-- -- -- plugins -- -- --
@@ -829,7 +864,10 @@ end
function checkers.generic(data)
local dr, du, ds = data.request, data.used, data.status
- local name, page, size, color = du.fullname or "unknown generic", du.page or dr.page, dr.size or "crop", dr.color or "natural"
+ local name = du.fullname or "unknown generic"
+ local page = du.page or dr.page
+ local size = dr.size or "crop"
+ local color = dr.color or "natural"
local mask = dr.mask or "none"
local conversion = dr.conversion
local resolution = dr.resolution
@@ -839,14 +877,14 @@ function checkers.generic(data)
if not resolution or resolution == "" then
resolution = "unknown"
end
- local hash = name .. "->" .. page .. "->" .. size .. "->" .. color .. "->" .. conversion .. "->" .. resolution
- .. "->" .. mask
+ local hash = name .. "->" .. page .. "->" .. size .. "->" .. color .. "->" .. conversion .. "->" .. resolution .. "->" .. mask
local figure = figures.loaded[hash]
if figure == nil then
figure = img.new {
- filename = name,
- page = page,
- pagebox = dr.size,
+ filename = name,
+ page = page,
+ pagebox = dr.size,
+ -- visiblefilename = "", -- this prohibits the full filename ending up in the file
}
codeinjections.setfigurecolorspace(data,figure)
codeinjections.setfiguremask(data,figure)
@@ -885,6 +923,11 @@ function includers.generic(data)
dr.height = du.height
local hash = figures.hash(data)
local figure = figures.used[hash]
+--~ figures.registerresource {
+--~ filename = du.fullname,
+--~ width = dr.width,
+--~ height = dr.height,
+--~ }
if figure == nil then
figure = ds.private
if figure then
@@ -1038,12 +1081,16 @@ local function makeoptions(options)
return (to == "table" and concat(options," ")) or (to == "string" and options) or ""
end
-local function runprogram(...)
- local command = format(...)
- if trace_conversion or trace_programs then
- report_inclusion("running %s",command)
+local function runprogram(template,binary,...)
+ local command = format(template,binary,...)
+ if os.which(binary) then
+ if trace_conversion or trace_programs then
+ report_inclusion("running: %s",command)
+ end
+ os.spawn(command)
+ else
+ report_inclusion("program '%s' is not installed, not running: %s",binary,command)
end
- os.spawn(command)
end
-- -- -- eps -- -- --
@@ -1115,12 +1162,12 @@ svgconverter.default = svgconverter.pdf
-- -- -- gif -- -- --
-local gifconverter = { }
+local gifconverter = { }
converters.gif = gifconverter
programs.convert = {
- command = "convert" -- imagemagick
- -- command = "gm convert" -- graphicmagick
+ -- command = "convert" -- imagemagick
+ command = "gm convert" -- graphicmagick
}
function gifconverter.pdf(oldname,newname)
@@ -1133,6 +1180,31 @@ end
gifconverter.default = gifconverter.pdf
+-- -- -- tif -- -- --
+
+-- http://sourceforge.net/projects/gnuwin32/files/tiff/3.8.2-1/tiff-3.8.2-1-bin.zip/download
+
+local tifconverter = { }
+converters.tif = tifconverter
+
+programs.convert = {
+--~ command = "convert" -- imagemagick
+ command = "gm convert" -- graphicmagick
+--~ command = "tiff2pdf"
+}
+
+function tifconverter.pdf(oldname,newname)
+ local convert = programs.convert
+ runprogram (
+ "%s %s %s %s",
+ convert.command, makeoptions(convert.options), oldname, newname
+--~ "%s %s -z -o %s %s",
+--~ convert.command, makeoptions(convert.options), newname, oldname
+ )
+end
+
+tifconverter.default = tifconverter.pdf
+
-- todo: lowres
-- -- -- bases -- -- --
@@ -1270,7 +1342,7 @@ function figures.applyratio(width,height,w,h) -- width and height are strings an
if not height or height == "" then
return figures.defaultwidth, figures.defaultheight
else
- height = string.todimen(height)
+ height = todimen(height)
if w and h then
return height * w/h, height
else
@@ -1278,7 +1350,7 @@ function figures.applyratio(width,height,w,h) -- width and height are strings an
end
end
else
- width = string.todimen(width)
+ width = todimen(width)
if not height or height == "" then
if w and h then
return width, width * h/w
@@ -1286,7 +1358,24 @@ function figures.applyratio(width,height,w,h) -- width and height are strings an
return width, figures.defaultheight
end
else
- return width, string.todimen(height)
+ return width, todimen(height)
end
end
end
+
+-- example of a simple plugin:
+--
+-- figures.converters.png = {
+-- png = function(oldname,newname,resolution)
+-- local command = string.format('gm convert -depth 1 "%s" "%s"',oldname,newname)
+-- logs.report(string.format("running command %s",command))
+-- os.execute(command)
+-- end,
+-- }
+
+
+-- local fig = figures.push { name = pdffile }
+-- figures.identify()
+-- figures.check()
+-- local nofpages = fig.used.pages
+-- figures.pop()
diff --git a/Master/texmf-dist/tex/context/base/grph-inc.mkii b/Master/texmf-dist/tex/context/base/grph-inc.mkii
index 1bd7544d8bc..33f11a2bc8f 100644
--- a/Master/texmf-dist/tex/context/base/grph-inc.mkii
+++ b/Master/texmf-dist/tex/context/base/grph-inc.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Inclusion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -660,8 +660,8 @@
\xdef\noffigurepages{\number\nofinsertpages}%
\fi
\fi
- \global\wd\foundexternalfigure\finalscaleboxwidth
- \global\ht\foundexternalfigure\finalscaleboxheight
+ \wd\foundexternalfigure\finalscaleboxwidth
+ \ht\foundexternalfigure\finalscaleboxheight
\global\let\lastfigureobjectname\externalfigurestamp
\doresetobjects} % clean up driver left overs
diff --git a/Master/texmf-dist/tex/context/base/grph-inc.mkiv b/Master/texmf-dist/tex/context/base/grph-inc.mkiv
index aa2157b9fa8..633130ea939 100644
--- a/Master/texmf-dist/tex/context/base/grph-inc.mkiv
+++ b/Master/texmf-dist/tex/context/base/grph-inc.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Figure Inclusion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,6 +19,8 @@
%D - alternative images
%D - a few more obscure things
+% use framedcommandhandler
+
\registerctxluafile{grph-inc}{1.001}
\registerctxluafile{grph-fil}{1.001}
\registerctxluafile{grph-u3d}{1.001} % this will change
@@ -98,9 +100,9 @@
\def\figurefullname {\ctxlua{figures.tprint("used","fullname")}}
\def\noffigurepages {\ctxlua{figures.tprint("used","pages",0)}}
-\def\figurefilepath {\ctxsprint{file.dirname (figures.get("used","fullname"))}}
-\def\figurefilename {\ctxsprint{file.nameonly(figures.get("used","fullname"))}}
-\def\figurefiletype {\ctxsprint{file.extname (figures.get("used","fullname"))}}
+\def\figurefilepath {\cldcontext{file.dirname (figures.get("used","fullname"))}}
+\def\figurefilename {\cldcontext{file.nameonly(figures.get("used","fullname"))}}
+\def\figurefiletype {\cldcontext{file.extname (figures.get("used","fullname"))}}
\let\naturalfigurewidth \figurenaturalwidth
\let\naturalfigureheight \figurenaturalheight
@@ -136,7 +138,7 @@
\appendtoks \resetexternalfigures \to \everyoverlay
\appendtoks \resetexternalfigures \to \everybeforepagebody % not really needed
-\def\resetfigureusersettings
+\def\resetfigureusersettings % if we use a command handler we can simply define a new instance
{%
\let\@@efmethod \empty
\let\@@eflabel \empty
@@ -225,8 +227,29 @@
\def\docheckfiguremps #1{\doprocessmpslikefigure{#1}}
\def\docheckfiguremprun #1#2{\doprocesstexlikefigure{\useMPrun{#1}{#2}}}
+% \def\doscalefigure
+% {\global\setbox\foundexternalfigure\vbox{\doscalebox\??ef{\dowithfigure{\box\foundexternalfigure}}}}
+
\def\doscalefigure
- {\global\setbox\foundexternalfigure\vbox{\doscalebox\??ef{\dowithfigure{\box\foundexternalfigure}}}}
+ {\global\setbox\foundexternalfigure\vbox{\scale[\v!figure]{\dowithfigure{\box\foundexternalfigure}}}}
+
+% quick hack: chaining \??ef via \s!parent happens when this is also a commandhandler
+
+\definescale
+ [\v!figure]
+ [\c!hfactor =\@@efhfactor ,
+ \c!wfactor =\@@efwfactor ,
+ \c!factor =\@@effactor ,
+ \c!maxwidth =\@@efmaxwidth ,
+ \c!maxheight=\@@efmaxheight,
+ \c!xscale =\@@efxscale ,
+ \c!yscale =\@@efyscale ,
+ \c!scale =\@@efscale ,
+ \c!sx =\@@efsx ,
+ \c!sy =\@@efsy ,
+ \c!width =\@@efwidth ,
+ \c!height =\@@efheight ,
+ \c!lines =\@@eflines ]
\newconditional\testexternalfigureonly
@@ -234,7 +257,7 @@
% \externalfigure[demo.svg]
% \externalfigure[demo.svg][conversion=png]
-\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current
+\unexpanded\def\calculateexternalfigure[#1][#2][#3][#4][#5][#6]% \cmd label filename parent_id preset current
{\dontcomplain
\restorecatcodes
\forgetall
@@ -267,6 +290,7 @@
height = "\@@efheight", % can be crap
} }%
\ctxlua{figures.identify()}%
+ % also mode: checkpresense only
\ifconditional\testexternalfigureonly
\ifcase\figurestatus \else
\ctxlua{figures.check()}%
@@ -300,7 +324,9 @@
\egroup
\egroup}
-\def\signalexternalfigure % global
+\newsystemmode\v!figure
+
+\def\signalexternalfigure % global (dup call to status)
{\ifcase\figurestatus
\global\resetsystemmode\v!figure % todo, also: \v!resource
\else
@@ -381,9 +407,21 @@
\let\getfiguredimensionsonly\getfiguredimensions
-\def\doiffigureelse#1%
+% \unexpanded\def\doiffigureelse#1%
+% {\getfiguredimensions[#1]% so data is available !
+% \ifdim\figurewidth=\zeropoint % todo: \figurestatus
+% \expandafter\secondoftwoarguments
+% \else
+% \expandafter\firstoftwoarguments
+% \fi}
+
+% \unexpanded\def\doiffigureelse#1% just low level call
+% {\getfiguredimensions[#1]% so data is available ! ... grouped so status is local
+% \doifmodeelse{*\v!figure}\firstoftwoarguments\secondoftwoarguments} % mode is set global
+
+\unexpanded\def\doiffigureelse#1%
{\getfiguredimensions[#1]% so data is available !
- \ifdim\figurewidth=\zeropoint % todo: \figurestatus
+ \ifcase\figurestatus
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
diff --git a/Master/texmf-dist/tex/context/base/grph-raw.mkiv b/Master/texmf-dist/tex/context/base/grph-raw.mkiv
index 426262b4f8e..5b488cf5837 100644
--- a/Master/texmf-dist/tex/context/base/grph-raw.mkiv
+++ b/Master/texmf-dist/tex/context/base/grph-raw.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Raw Bitmaps,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -45,14 +45,14 @@
\unexpanded\def\bitmapimage[#1]#2%
{\hbox\bgroup
- \getparameters[@@im][\c!color=rgb,\c!width=,\c!height=,\c!x=,\c!y=,#1]%
+ \getparameters[\??gb][\c!color=rgb,\c!width=,\c!height=,\c!x=,\c!y=,#1]%
\ctxlua{figures.bitmapimage {
data = \!!bs#2\!!es,
- xresolution = "\@@imx",
- yresolution = "\@@imy",
- colorspace = "\@@imcolor",
- width = "\@@imwidth",
- height = "\@@imheight"
+ xresolution = "\@@gbx",
+ yresolution = "\@@gby",
+ colorspace = "\@@gbcolor",
+ width = "\@@gbwidth",
+ height = "\@@gbheight"
}}%
\egroup}
diff --git a/Master/texmf-dist/tex/context/base/grph-trf.mkii b/Master/texmf-dist/tex/context/base/grph-trf.mkii
index 3e32395b480..bd9875806b9 100644
--- a/Master/texmf-dist/tex/context/base/grph-trf.mkii
+++ b/Master/texmf-dist/tex/context/base/grph-trf.mkii
@@ -5,7 +5,7 @@
%D subtitle=Transformations,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/grph-trf.mkiv b/Master/texmf-dist/tex/context/base/grph-trf.mkiv
index 9924a68e8e3..a33e5606dd8 100644
--- a/Master/texmf-dist/tex/context/base/grph-trf.mkiv
+++ b/Master/texmf-dist/tex/context/base/grph-trf.mkiv
@@ -1,53 +1,65 @@
%D \module
-%D [ file=grph-fig,
+%D [ file=grph-trf,
%D version=2006.08.26, % overhaul/split of 1997.03.31 core-fig
%D title=\CONTEXT\ Graphic Macros,
%D subtitle=Transformations,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 It may be that some functionality got lost. If it concerns
-%D defined features, let me know and it will be sorted out.
-
-%D We will move the calculations to lua.
-
\writestatus{loading}{ConTeXt Graphic Macros / Transformations}
\unprotect
-%D Scaling:
+%D We probably use too many dimens as the width calculations can
+%D go away. Some of this is an inheritance of limited backends
+%D (some supported fractions, some 1000's, some dimentions) so
+%D we calculate all of them. Nowadays scaling is always available
+%D so we could simplify the code. On the other hand, we now get
+%D some extra values for free.
+%D
+%D We could move the calculations to \LUA\ and clean up this
+%D lot anyway. On the other hand, there is some danger of messing
+%D up so it has a real low priority.
-\unexpanded\def\scale{\dodoubleempty\doscalenextbox[\??xy]}
+% local:
-% probably too many dimens / the width calculations can go
-% since we may assume scaling is available (was not true
-% long ago which is why we also calculate the width)
+\newdimen\d_grph_scale_x_size
+\newdimen\d_grph_scale_y_size
+\newdimen\d_grph_scale_x_offset
+\newdimen\d_grph_scale_y_offset
-\newdimen\scaleboxwidth
-\newdimen\scaleboxheight
-\newdimen\scaleboxdepth
+\newdimen\d_grph_scale_h_size
+\newdimen\d_grph_scale_v_size
-\newdimen\scaleboxsizex
-\newdimen\scaleboxsizey
-\newdimen\scaleboxoffsetx
-\newdimen\scaleboxoffsety
+\newconditional\c_grph_scale_done
+\newconditional\c_grph_scale_scaling_done
-\newdimen\scaleboxhsize
-\newdimen\scaleboxvsize
+\newdimen\d_grph_scale_wd
+\newdimen\d_grph_scale_ht
+\newdimen\d_grph_scale_dp
% global
-\newdimen\scaleboxdimx \let\figwid \scaleboxdimx
-\newdimen\scaleboxdimy \let\fighei \scaleboxdimy
-\newcount\scaleboxscax \let\figxsca\scaleboxscax
-\newcount\scaleboxscay \let\figysca\scaleboxscay
+\newdimen\d_grph_scale_used_x_size
+\newdimen\d_grph_scale_used_y_size
+
+\newcount\c_grph_scale_used_x_scale
+\newcount\c_grph_scale_used_y_scale
-\newdimen\scaleboxoutervsize % we cannot manipulate any global vsize !
+\newdimen\d_grph_scale_outer_v_size % we cannot manipulate any global vsize !
+
+% scratch:
+
+\let\m_grph_scale_temp \empty
+\let\m_grph_scale_temp_x\empty
+\let\m_grph_scale_temp_y\empty
+
+% public:
\let\finalscaleboxxscale \!!plusone
\let\finalscaleboxyscale \!!plusone
@@ -56,342 +68,420 @@
\let\finalscaleboxxfactor\!!hundred
\let\finalscaleboxyfactor\!!hundred
-\newconditional\scaleboxdone
-
-\def\doscalenextbox[#1][#2]%
+% we can let sx/sy win (first check)
+
+\installcorenamespace{scale}
+\installcorenamespace{scalegrid}
+\installcorenamespace{scalenorm}
+
+\installcommandhandler \??scale {scale} \??scale % we can have instances
+
+\setupscale
+ [\c!sx=1,
+ \c!sy=1,
+ %\c!scale=,
+ %\c!xscale=,
+ %\c!yscale=,
+ %\c!width=,
+ %\c!height=,
+ %\c!lines=,
+ %\c!factor=,
+ %\c!hfactor=,
+ %\c!wfactor=,
+ %\c!grid=,
+ %\c!equalwidth=,
+ %\c!equalheight=,
+ \c!maxwidth=\scaleparameter\c!width,
+ \c!maxheight=\scaleparameter\c!height]
+
+\unexpanded\def\scale{\dodoubleempty\grph_scale}
+
+% we could have: \freezeparameter\c!scale etc (less backtracking when used multiple)
+
+\def\grph_scale[#1][#2]%
{\bgroup
- \getparameters
- [#1]
- [\c!scale=,\c!xscale=,\c!yscale=,\c!width=,\c!height=,\c!lines=,
- \c!factor=,\c!hfactor=,\c!wfactor=,\c!grid=,\c!sx=1,\c!sy=1,
- \c!equalwidth=,\c!equalheight=,
- \c!maxwidth=\scaleparameter\c!width,\c!maxheight=\scaleparameter\c!height,
- #2]%
- \dowithnextbox{\dodoscalenextbox{#1}\egroup}\hbox}
-
-\def\doscalebox#1%
- {\bgroup\dowithnextbox{\dodoscalenextbox{#1}\egroup}\hbox}
-
-\let\currentscaletag\??xy
-
-\def\scaleparameter#1%
- {\csname\currentscaletag#1\endcsname}
-
-\def\setscaleparameter#1#2%
- {\setvalue{\currentscaletag#1}{#2}}
-
-\def\dodoscalenextbox#1%
- {\edef\currentscaletag{#1}%
- \doif{\scaleparameter\c!depth}\v!no{\setbox\nextbox\hbox{\raise\nextboxdp\box\nextbox}}% new
- \forgetall
- \dontshowcomposition
- \dontcomplain
- \doscaleboxcalculations
- \doscaleboxindeed
- \doscaleboxposition
- \flushnextbox}
-
-\def\doscaleboxindeed
- {\ifconditional\scaleboxdone
- \scaleboxwidth \finalscaleboxxscale\nextboxwd
- \scaleboxheight\finalscaleboxyscale\nextboxht
- \scaleboxdepth \finalscaleboxyscale\nextboxdp
- \setbox\nextbox\hbox
- {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
- \smashedbox\nextbox
- \dostopscaling}%
- \nextboxwd\scaleboxwidth
- \nextboxht\scaleboxheight
- \nextboxdp\scaleboxdepth
- \fi}
-
-\def\doscaleboxcalculations
- {\setfalse\scaleboxdone
- % initial final value
+ % this is quite common so we might make this a helper
+ \ifsecondargument
+ \edef\currentscale{#1}%
+ \setupcurrentscale[#2]%
+ \else\iffirstargument
+ \doifassignmentelse{#1}
+ {\let\currentscale\empty
+ \setupcurrentscale[#1]}
+ {\edef\currentscale{#1}}%
+ \else
+ \let\currentscale\empty
+ \fi\fi
+ %
+ \dowithnextboxcs\grph_scale_finish\hbox}
+
+\def\grph_scale_finish
+ {% todo: p_scale_
+ \edef\p_scale {\scaleparameter\c!scale }%
+ \edef\p_xscale {\scaleparameter\c!xscale }%
+ \edef\p_yscale {\scaleparameter\c!yscale }%
+ \edef\p_width {\scaleparameter\c!width }%
+ \edef\p_height {\scaleparameter\c!height }%
+ \edef\p_depth {\scaleparameter\c!depth }%
+ \edef\p_lines {\scaleparameter\c!lines }%
+ \edef\p_factor {\scaleparameter\c!factor }%
+ \edef\p_hfactor {\scaleparameter\c!hfactor }%
+ \edef\p_wfactor {\scaleparameter\c!wfactor }%
+ % \edef\p_grid {\scaleparameter\c!grid }% used once
+ \edef\p_maxwidth {\scaleparameter\c!maxwidth }%
+ \edef\p_maxheight {\scaleparameter\c!maxheight }%
+ \edef\p_sx {\scaleparameter\c!sx }%
+ \edef\p_sy {\scaleparameter\c!sy }%
+ \edef\p_equalwidth {\scaleparameter\c!equalwidth }%
+ \edef\p_equalheight{\scaleparameter\c!equalheight}%
+ %
+ \d_grph_scale_dp\dp\nextbox
+ \ifx\p_depth\v!no \ifzeropt\d_grph_scale_dp \else
+ \setbox\nextbox\hbox{\raise\d_grph_scale_dp\box\nextbox}% new
+ \d_grph_scale_dp\dp\nextbox
+ \fi \fi
+ \d_grph_scale_wd\wd\nextbox
+ \d_grph_scale_ht\ht\nextbox
+ \d_grph_scale_dp\dp\nextbox
+ %
\global\let\finalscaleboxxscale \!!plusone
\global\let\finalscaleboxyscale \!!plusone
- \xdef \finalscaleboxwidth {\the\nextboxwd}%
- \xdef \finalscaleboxheight{\the\nextboxht}%
+ \xdef \finalscaleboxwidth {\the\d_grph_scale_wd}%
+ \xdef \finalscaleboxheight{\the\d_grph_scale_ht}%
\global\let\finalscaleboxxfactor\!!hundred
\global\let\finalscaleboxyfactor\!!hundred
- \ifdim\nextboxht>\zeropoint \ifdim\nextboxwd>\zeropoint
- % hm, still useful? better in lua anyway
- \edef\scaleboxstampa % slow way [can be combined]
- {\scaleparameter\c!scale \scaleparameter\c!xscale \scaleparameter\c!yscale
- \scaleparameter\c!factor\scaleparameter\c!wfactor\scaleparameter\c!hfactor
- \scaleparameter\c!lines \scaleparameter\c!width \scaleparameter\c!height}%
- \edef\scaleboxstampb % fast way [just sx/sy]
- {\scaleparameter\c!sx
- \scaleparameter\c!sy}%
- \edef\scaleboxstampc
- {11}%
- \ifx\scaleboxstampa\empty
- \ifx\scaleboxstampb\scaleboxstampc
- % no scaling, but still check; new, gone again
-% wrong: scaled proportionally as side effect
-% \doifsomething{\scaleparameter\c!maxwidth }{\letvalue{\currentscaletag\c!factor}\v!fit}%
-% \doifsomething{\scaleparameter\c!maxheight}{\letvalue{\currentscaletag\c!factor}\v!fit}%
+ %
+ \forgetall
+ \dontcomplain
+ %
+ \setfalse\c_grph_scale_done
+ \grph_scale_calculate
+ \ifconditional\c_grph_scale_done
+ \grph_scale_apply
+ \fi
+ \grph_scale_position
+ %
+ \box\nextbox
+ \egroup}
+
+\def\grph_scale_apply
+ {\d_grph_scale_wd\finalscaleboxxscale\d_grph_scale_wd
+ \d_grph_scale_ht\finalscaleboxyscale\d_grph_scale_ht
+ \d_grph_scale_dp\finalscaleboxyscale\d_grph_scale_dp
+ \setbox\nextbox\hbox
+ {\dostartscaling \finalscaleboxxscale \finalscaleboxyscale
+ \smashedbox\nextbox
+ \dostopscaling}%
+ \wd\nextbox\d_grph_scale_wd
+ \ht\nextbox\d_grph_scale_ht
+ \dp\nextbox\d_grph_scale_dp}
+
+\def\m_grph_scale_stamp_c{11}
+
+\def\grph_scale_calculate
+ {\ifdim\d_grph_scale_ht>\zeropoint \ifdim\d_grph_scale_wd>\zeropoint
+ \edef\m_grph_scale_stamp_a{\p_scale\p_xscale\p_yscale\p_factor\p_wfactor\p_hfactor\p_lines\p_width\p_height}%
+ \edef\m_grph_scale_stamp_b{\p_sx\p_sy}%
+ \ifx\m_grph_scale_stamp_a\empty
+ \ifx\m_grph_scale_stamp_b\m_grph_scale_stamp_c
+ % no scaling, don't change this (previous attempts failed anyway)
\insidefloattrue % trick
- \dodoscaleboxcalculations
+ \grph_scale_calculations_yes
\else
- \dosetscalboxsxsy
- \nodoscaleboxcalculations
+ \grph_scale_check_sx_sy
+ \grph_scale_calculations_nop
\fi
\else
- \ifx\scaleboxstampb\empty
+ \ifx\m_grph_scale_stamp_b\empty
% no need to check further
\else
- \dosetscalboxsxsy
+ \grph_scale_check_sx_sy
\fi
- \dodoscaleboxcalculations
+ \grph_scale_calculations_yes
\fi
\fi \fi}
-\def\dosetscalboxsxsy
- {\ifdim\scaleparameter\c!sx\onepoint=\onepoint\else
- \setevalue{\currentscaletag\c!width }{\the\dimexpr\scaleparameter\c!sx\wd\nextbox\relax}%
- \fi
- \ifdim\scaleparameter\c!sy\onepoint=\onepoint\else
- \setevalue{\currentscaletag\c!height}{\the\dimexpr\scaleparameter\c!sy\ht\nextbox\relax}%
- \fi}
+\def\grph_scale_check_sx_sy
+ {\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\doscaleboxrounding#1.#2\relax{#1}
+\def\grph_scale_rounded#1%
+ {\expandafter\expandafter\expandafter\grph_scale_rounded_indeed
+ \expandafter\WITHOUTPT\the\dimexpr#1\points*100+32768sp\relax.\relax}
-\def\scaleboxrounding#1%
- {\@EA\@EA\@EA\doscaleboxrounding\@EA\WITHOUTPT\the\dimexpr#1\points*100+32768sp\relax.\relax}
+\def\grph_scale_rounded_indeed#1.#2\relax{#1}
-\def\nodoscaleboxcalculations
- {\settrue\scaleboxdone
- \xdef\finalscaleboxwidth {\the\dimexpr\scaleparameter\c!sx\wd\nextbox\relax}%
- \xdef\finalscaleboxheight {\the\dimexpr\scaleparameter\c!sy\ht\nextbox\relax}%
- \xdef\finalscaleboxxscale {\scaleparameter\c!sx}%
- \xdef\finalscaleboxyscale {\scaleparameter\c!sy}%
+\def\grph_scale_calculations_nop
+ {\settrue\c_grph_scale_done
+ \xdef\finalscaleboxwidth {\the\dimexpr\p_sx\d_grph_scale_wd\relax}%
+ \xdef\finalscaleboxheight{\the\dimexpr\p_sy\d_grph_scale_ht\relax}%
+ \glet\finalscaleboxxscale\p_sx
+ \glet\finalscaleboxyscale\p_sy
\ifx\finalscaleboxxscale\empty\let\finalscaleboxxscale\!!plusone\fi
\ifx\finalscaleboxyscale\empty\let\finalscaleboxyscale\!!plusone\fi
- \xdef\finalscaleboxxfactor{\scaleboxrounding\finalscaleboxxscale}%
- \xdef\finalscaleboxyfactor{\scaleboxrounding\finalscaleboxyscale}}
+ \xdef\finalscaleboxxfactor{\grph_scale_rounded\finalscaleboxxscale}%
+ \xdef\finalscaleboxyfactor{\grph_scale_rounded\finalscaleboxyscale}}
-\def\dodoscaleboxcalculations
- {\settrue\scaleboxdone
+\def\grph_scale_calculations_yes
+ {\settrue\c_grph_scale_done
% initial values
- \scaleboxoffsetx\zeropoint
- \scaleboxoffsety\zeropoint
- \scaleboxsizex \nextboxwd
- \scaleboxsizey \nextboxht % alleen ht wordt geschaald!
+ \d_grph_scale_x_offset\zeropoint
+ \d_grph_scale_y_offset\zeropoint
+ \d_grph_scale_x_size \d_grph_scale_wd
+ \d_grph_scale_y_size \d_grph_scale_ht % alleen ht wordt geschaald!
% final values
- \global\scaleboxdimx \zeropoint % see note * (core-fig)
- \global\scaleboxdimy \zeropoint % see note * (core-fig)
- \scaleboxscax \plusone % see note * (core-fig)
- \scaleboxscay \plusone % see note * (core-fig)
+ \global\d_grph_scale_used_x_size \zeropoint % see note * (core-fig)
+ \global\d_grph_scale_used_y_size \zeropoint % see note * (core-fig)
+ \c_grph_scale_used_x_scale \plusone % see note * (core-fig)
+ \c_grph_scale_used_y_scale \plusone % see note * (core-fig)
% preparations
- \setfalse\scaleboxscalingdone
- \checkscaleboxsettings
+ \setfalse\c_grph_scale_scaling_done
+ \grph_scale_check_parameters
% calculators
% beware, they operate in sequence, and calculate missing dimensions / messy
%setscaleboxbynature % when? needed?
- \ifconditional\scaleboxscalingdone\else\setscaleboxbyfactor \fi
- \ifconditional\scaleboxscalingdone\else\setscaleboxbyscale \fi
- \ifconditional\scaleboxscalingdone\else\setscaleboxbydimension\fi
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_factor \fi
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_scale \fi
+ \ifconditional\c_grph_scale_scaling_done\else\grph_scale_by_dimension\fi
% finalizers / to be done (no longer needed this way, clean up)
- \convertscaleboxinsertscale\scaleboxhsize\figx\scaleboxscax\scax
- \convertscaleboxinsertscale\scaleboxvsize\figy\scaleboxscay\scay
+ \grph_scale_convert_large_scale\d_grph_scale_h_size\figx\c_grph_scale_used_x_scale\m_grph_scale_temp_x
+ \grph_scale_convert_large_scale\d_grph_scale_v_size\figy\c_grph_scale_used_y_scale\m_grph_scale_temp_y
% used in actual scaling
- \xdef\finalscaleboxwidth {\the\scaleboxdimx}%
- \xdef\finalscaleboxheight {\the\scaleboxdimy}%
- \xdef\finalscaleboxxfactor{\the\scaleboxscax}%
- \xdef\finalscaleboxyfactor{\the\scaleboxscay}%
- \xdef\finalscaleboxxscale {\withoutpt\the\dimexpr\scax\points/\plushundred\relax}%
- \xdef\finalscaleboxyscale {\withoutpt\the\dimexpr\scay\points/\plushundred\relax}}
-
-\setvalue{\??xy:\c!grid:\v!yes }{\getnoflines \fighei\setevalue{\currentscaletag\c!height}{\the\noflines\lineheight}}
-\setvalue{\??xy:\c!grid:\v!height }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight+\strutdepth\relax}}
-\setvalue{\??xy:\c!grid:\v!depth }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight-\strutdepth\relax}}
-\setvalue{\??xy:\c!grid:\v!halfline}{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\dimexpr\noflines\lineheight+.5\lineheight\relax}}
-\setvalue{\??xy:\c!grid:\v!fit }{\getrawnoflines\fighei\setevalue{\currentscaletag\c!height}{\the\noflines\lineheight}}
-\letvalue{\??xy:\c!grid:\empty }\donothing
-
-\def\checkscaleboxsettings
- {\doifsomething{\scaleparameter\c!maxwidth }% can be defined in itself
- {\setevalue{\currentscaletag\c!maxwidth }{\the\dimexpr\scaleparameter\c!maxwidth \relax}}%
- \doifsomething{\scaleparameter\c!maxheight}% can be defined in itself
- {\setevalue{\currentscaletag\c!maxheight}{\the\dimexpr\scaleparameter\c!maxheight\relax}}%
- \doifsomething{\scaleparameter\c!lines}
- {\setevalue{\currentscaletag\c!height}{\the\dimexpr\scaleparameter\c!lines\lineheight\relax}}%
- \getvalue{\??xy:\c!grid:\scaleparameter\c!grid}}
-
-\def\setscaleboxbynature % where ! ! ! ! !
- {\doifsomething{\scaleparameter\c!width }{\global\scaleboxdimx\scaleparameter\c!width }%
- \doifsomething{\scaleparameter\c!height}{\global\scaleboxdimy\scaleparameter\c!height}%
- \doifsomething{\scaleparameter\c!scale } {\scaleboxscax\scaleparameter\c!scale
- \scaleboxscay\scaleparameter\c!scale }%
- \doifsomething{\scaleparameter\c!xscale} {\scaleboxscax\scaleparameter\c!xscale}%
- \doifsomething{\scaleparameter\c!yscale} {\scaleboxscay\scaleparameter\c!yscale}} % oeps, was x
+ \xdef\finalscaleboxwidth {\the\d_grph_scale_used_x_size}%
+ \xdef\finalscaleboxheight {\the\d_grph_scale_used_y_size}%
+ \xdef\finalscaleboxxfactor{\the\c_grph_scale_used_x_scale}%
+ \xdef\finalscaleboxyfactor{\the\c_grph_scale_used_y_scale}%
+ \xdef\finalscaleboxxscale {\withoutpt\the\dimexpr\m_grph_scale_temp_x\points/\plushundred\relax}%
+ \xdef\finalscaleboxyscale {\withoutpt\the\dimexpr\m_grph_scale_temp_y\points/\plushundred\relax}}
+
+\setvalue{\??scalegrid\v!yes }{\getnoflines \d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}}
+\setvalue{\??scalegrid\v!height }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+\strutdepth}}
+\setvalue{\??scalegrid\v!depth }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight-\strutdepth}}
+\setvalue{\??scalegrid\v!halfline}{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\dimexpr\noflines\lineheight+.5\lineheight}}
+\setvalue{\??scalegrid\v!fit }{\getrawnoflines\d_grph_scale_used_y_size\edef\p_height{\the\noflines\lineheight}}
+\letvalue{\??scalegrid\empty }\donothing
+
+\def\grph_scale_check_parameters % resolve self referencing loops
+ {\ifx\p_maxwidth \empty\else \edef\p_maxwidth {\the\dimexpr\p_maxwidth }\fi
+ \ifx\p_maxheight\empty\else \edef\p_maxheight{\the\dimexpr\p_maxheight }\fi
+ \ifx\p_lines \empty\else \edef\p_height {\the\dimexpr\p_lines\lineheight}\fi
+ \getvalue{\??scalegrid\scaleparameter\c!grid}}
+
+\def\grph_scale_by_nature % where ! ! ! ! !
+ {\ifx\p_width \empty\else \global\d_grph_scale_used_x_size\p_width \fi
+ \ifx\p_height\empty\else \global\d_grph_scale_used_y_size\p_height\fi
+ \ifx\p_scale \empty\else \c_grph_scale_used_x_scale\p_scale
+ \c_grph_scale_used_y_scale\p_scale \fi
+ \ifx\p_xscale\empty\else \c_grph_scale_used_x_scale\p_xscale\fi
+ \ifx\p_yscale\empty\else \c_grph_scale_used_y_scale\p_yscale\fi}
% \defineexternalfigure[width-6][factor=auto,maxwidth=\textheight,maxheight=\textwidth]
% \defineexternalfigure[width-7][factor=auto,maxwidth=\textwidth,maxheight=\textheight]
% \placefigure{none}{\rotate[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-6]}} \page
% \placefigure{none}{\framed[frame=on,offset=overlay]{\externalfigure[t:/sources/cow.pdf][width-7]}}
-\def\setscaleboxbyfactor
- {\doifinsetelse{\scaleparameter\c!factor}{\v!max,\v!fit,\v!broad,\v!auto}
- {\doapplyscaleboxsize
- \ifdim\scaleboxsizex>\scaleboxsizey
- \docalculatescaleboxnorm \scaleboxdimx\c!factor\c!maxwidth\hsize\scaleboxhsize
- \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
- \else
- \docalculatescaleboxnorm \scaleboxdimy\c!factor\c!maxheight\scaleboxoutervsize\scaleboxvsize
- \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
- \fi
- \donetrue}
- {\doifinsetelse{\scaleparameter\c!hfactor}{\v!max,\v!fit,\v!broad,\v!auto}
- {\doapplyscaleboxsize
- \docalculatescaleboxnorm \scaleboxdimy\c!hfactor\c!maxheight\scaleboxoutervsize\scaleboxvsize
- \docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex
- \donetrue}
- {\doifinsetelse{\scaleparameter\c!wfactor}{\v!max,\v!fit,\v!broad,\v!auto}
- {\doapplyscaleboxsize
- \docalculatescaleboxnorm \scaleboxdimx\c!wfactor\c!maxwidth\hsize\scaleboxhsize
- \docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey
- \donetrue}
- {\docalculatescaleboxnorm\scaleboxdimy\c!factor \c!height \textheight\scaleboxvsize
- \docalculatescaleboxnorm\scaleboxdimy\c!hfactor\c!height \textheight\scaleboxvsize
- \docalculatescaleboxnorm\scaleboxdimx\c!wfactor\c!width \hsize \hsize
- \donefalse}}}%
- \ifdone
- \settrue\scaleboxscalingdone
- \ifdim\scaleboxdimx>\scaleboxhsize
- \global\scaleboxdimy\zeropoint \global\scaleboxdimx\scaleboxhsize
- \else\ifdim\scaleboxdimy>\scaleboxvsize
- \global\scaleboxdimx\zeropoint \global\scaleboxdimy\scaleboxvsize
- \fi\fi
- \setscaleboxbydimension
+\def\m_grph_scale_factor_set{\v!max,\v!fit,\v!broad,\v!auto} % can be an \edef
+
+\def\grph_scale_by_factor
+ {\doifinsetelse\p_factor\m_grph_scale_factor_set
+ \grph_scale_by_factor_a
+ {\doifinsetelse\p_hfactor\m_grph_scale_factor_set
+ \grph_scale_by_factor_b
+ {\doifinsetelse\p_wfactor\m_grph_scale_factor_set
+ \grph_scale_by_factor_c
+ \grph_scale_by_factor_d}}}
+
+\def\grph_scale_by_factor_a
+ {\grph_scale_apply_size
+ \ifdim\d_grph_scale_x_size>\d_grph_scale_y_size
+ \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_factor\p_maxwidth\hsize\d_grph_scale_h_size
+ \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \else
+ \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_factor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size
+ \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \fi
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_b
+ {\grph_scale_apply_size
+ \grph_scale_calculate_norm \d_grph_scale_used_y_size\p_hfactor\p_maxheight\d_grph_scale_outer_v_size\d_grph_scale_v_size
+ \grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_c
+ {\grph_scale_apply_size
+ \grph_scale_calculate_norm \d_grph_scale_used_x_size\p_wfactor\p_maxwidth\hsize\d_grph_scale_h_size
+ \grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size
+ \grph_scale_by_factor_indeed}
+
+\def\grph_scale_by_factor_d
+ {\grph_scale_calculate_norm\d_grph_scale_used_y_size\p_factor \p_height \textheight\d_grph_scale_v_size
+ \grph_scale_calculate_norm\d_grph_scale_used_y_size\p_hfactor\p_height \textheight\d_grph_scale_v_size
+ \grph_scale_calculate_norm\d_grph_scale_used_x_size\p_wfactor\p_width \hsize \hsize}
+
+\def\grph_scale_by_factor_indeed
+ {\settrue\c_grph_scale_scaling_done
+ \ifdim\d_grph_scale_used_x_size>\d_grph_scale_h_size
+ \global\d_grph_scale_used_y_size\zeropoint
+ \global\d_grph_scale_used_x_size\d_grph_scale_h_size
+ \else\ifdim\d_grph_scale_used_y_size>\d_grph_scale_v_size
+ \global\d_grph_scale_used_x_size\zeropoint
+ \global\d_grph_scale_used_y_size\d_grph_scale_v_size
+ \fi\fi
+ \grph_scale_by_dimension}
+
+\def\grph_scale_by_scale
+ {\edef\m_grph_scale_temp{\p_scale\p_xscale\p_yscale}%
+ \ifx\m_grph_scale_temp\empty \else
+ \grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale
+ \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale
+ \global\d_grph_scale_used_x_size\zeropoint
+ \global\d_grph_scale_used_y_size\zeropoint
+ \ifx\p_maxwidth\empty
+ \ifx\p_maxheight\empty
+ \else
+ \ifdim\d_grph_scale_y_size>\p_maxheight\relax
+ \global\d_grph_scale_used_y_size\p_maxheight
+ \fi
+ \fi
+ \else
+ \ifdim\d_grph_scale_x_size>\p_maxwidth\relax
+ \global\d_grph_scale_used_x_size\p_maxwidth
+ \fi
+ \fi
\fi}
-\def\setscaleboxbyscale
- {\doifsomething{\scaleparameter\c!scale\scaleparameter\c!xscale\scaleparameter\c!yscale}
- {\doapplyscaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax\c!xscale
- \doapplyscaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay\c!yscale
- \global\scaleboxdimx\zeropoint
- \global\scaleboxdimy\zeropoint
- \doifelsenothing{\scaleparameter\c!maxwidth}
- {\doifsomething{\scaleparameter\c!maxheight}
- {\ifdim\scaleboxsizey>\scaleparameter\c!maxheight\relax
- \global\scaleboxdimy\scaleparameter\c!maxheight
- \fi}}
- {\ifdim\scaleboxsizex>\scaleparameter\c!maxwidth\relax
- \global\scaleboxdimx\scaleparameter\c!maxwidth
- \fi}}}
-
-\def\setscaleboxbydimension
- {\ifdim\scaleboxdimx>\zeropoint
- \ifdim\scaleboxdimy>\zeropoint
- \dosetdimensionscaleboxsize
- {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
- \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
- {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
- \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
- {\docalculatescaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay
- \docalculatescaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax}%
+\def\grph_scale_by_dimension
+ {\ifdim\d_grph_scale_used_x_size>\zeropoint
+ \ifdim\d_grph_scale_used_y_size>\zeropoint
+ \grph_scale_by_dimension_a
\else
- \dosetdimensionscaleboxsize
- {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
- {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
- {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
+ \grph_scale_by_dimension_b
\fi
\else
- \ifdim\scaleboxdimy>\zeropoint
- \dosetdimensionscaleboxsize
- {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
- {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
- {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ \ifdim\d_grph_scale_used_y_size>\zeropoint
+ \grph_scale_by_dimension_c
\else
- \dosetdimensionscaleboxsize
- {\doapplyscaleboxscale\scaleboxdimx\scaleboxsizex\scaleboxscax\c!xscale
- \doapplyscaleboxscale\scaleboxdimy\scaleboxsizey\scaleboxscay\c!yscale}%
- {\docalculatescaleboxscales\scaleboxdimx\scaleboxsizex\scaleboxdimy\scaleboxsizey}%
- {\docalculatescaleboxscales\scaleboxdimy\scaleboxsizey\scaleboxdimx\scaleboxsizex}%
+ \grph_scale_by_dimension_d
\fi
\fi}
-\def\dosetdimensionscaleboxsize#1#2#3%
+\def\grph_scale_by_dimension_a
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+ \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}%
+ {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+ \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}%
+ {\grph_scale_calculate_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale
+ \grph_scale_calculate_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale}}
+
+\def\grph_scale_by_dimension_b
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}}
+
+\def\grph_scale_by_dimension_c
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_d
+ {\grph_scale_by_dimension_indeed
+ {\grph_scale_apply_scale\d_grph_scale_used_x_size\d_grph_scale_x_size\c_grph_scale_used_x_scale\p_xscale
+ \grph_scale_apply_scale\d_grph_scale_used_y_size\d_grph_scale_y_size\c_grph_scale_used_y_scale\p_yscale}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_x_size\d_grph_scale_x_size\d_grph_scale_used_y_size\d_grph_scale_y_size}%
+ {\grph_scale_calculate_scales\d_grph_scale_used_y_size\d_grph_scale_y_size\d_grph_scale_used_x_size\d_grph_scale_x_size}}
+
+\def\grph_scale_by_dimension_indeed#1#2#3%
{#1\relax
- \doifsomething{\scaleparameter\c!maxwidth}
- {\ifdim\scaleboxdimx>\scaleparameter\c!maxwidth\relax
- \global\scaleboxdimx\scaleparameter\c!maxwidth
- #2\relax
- \fi}%
- \doifsomething{\scaleparameter\c!maxheight}
- {\ifdim\scaleboxdimy>\scaleparameter\c!maxheight\relax
- \global\scaleboxdimy\scaleparameter\c!maxheight
- #3\relax
- \fi}}
-
-\def\docalculatescaleboxnorm#1#2#3#4#5% 2 3 parameters (dodo:speedup)
- {\processaction
- [\scaleparameter#2]
- [ \v!max=>\global#1\dimexpr#4\relax,
- \v!fit=>\global#1\dimexpr#5\relax,
- \v!broad=>\global#1\dimexpr#5-4\@@exbodyfont\relax,
- \v!auto=>\doifsomething{\scaleparameter#3}{\global#1\dimexpr\scaleparameter#3\relax},
- \s!default=>\doifsomething{\scaleparameter#3}{\global#1\dimexpr\scaleparameter#3\relax},
- \s!unknown=>\global#1\dimexpr\scaleparameter#2\dimexpr\@@exbodyfont/10\relax\relax]}
-
-\def\docalculatescaleboxscales#1#2#3#4%
+ \ifx\p_maxwidth\empty \else
+ \ifdim\d_grph_scale_used_x_size>\p_maxwidth\relax
+ \global\d_grph_scale_used_x_size\p_maxwidth
+ #2\relax
+ \fi
+ \fi
+ \ifx\p_maxheight\empty \else
+ \ifdim\d_grph_scale_used_y_size>\p_maxheight\relax
+ \global\d_grph_scale_used_y_size\p_maxheight
+ #3\relax
+ \fi
+ \fi}
+
+\def\grph_scale_calculate_norm#1#2% todo: swap 1 and 2 and pass one less
+ {\csname\??scalenorm\ifcsname\??scalenorm#2\endcsname#2\else\s!unknown\fi\endcsname#1#2}
+
+\setvalue{\??scalenorm\v!max }#1#2#3#4#5{\global#1#4}
+\setvalue{\??scalenorm\v!fit }#1#2#3#4#5{\global#1#5}
+\setvalue{\??scalenorm\v!broad }#1#2#3#4#5{\global#1\dimexpr#5-4\@@exbodyfont\relax}
+\setvalue{\??scalenorm\s!unknown}#1#2#3#4#5{\global#1\dimexpr#2\dimexpr\@@exbodyfont/10\relax\relax} % brr ex
+\setvalue{\??scalenorm\v!auto }#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+\setvalue{\??scalenorm\empty }#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+\setvalue{\??scalenorm\s!default}#1#2#3#4#5{\ifx#3\empty\else\global#1#3\fi}
+
+\def\grph_scale_calculate_scales#1#2#3#4%
{\scratchdimen\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax
- \scaleboxscax\scratchdimen
- \scaleboxscay\scratchdimen
- #3\dimexpr\scaleboxscax\dimexpr#4/\plusthousand\relax\relax}
+ \c_grph_scale_used_x_scale\scratchdimen
+ \c_grph_scale_used_y_scale\scratchdimen
+ #3\dimexpr\c_grph_scale_used_x_scale\dimexpr#4/\plusthousand\relax\relax}
-\def\docalculatescaleboxscale#1#2#3%
+\def\grph_scale_calculate_scale#1#2#3%
{#3\dimexpr#1/\dimexpr#2/\plusthousand\relax\relax}
-\def\doapplyscaleboxscale#1#2#3#4% $4 = parameter / scale can be empty
- {\ifcase0\scaleparameter#4\relax
- \ifcase0\scaleparameter\c!scale\relax
+\def\grph_scale_apply_scale#1#2#3#4% #4 = parameter / scale can be empty
+ {\ifcase0#4\relax
+ \ifcase0\p_scale\relax
#3=\plusthousand
\else
- #3=\scaleparameter\c!scale
+ #3=\p_scale
\fi
\else
- #3=\scaleparameter#4%
+ #3=#4%
\fi
\relax % important ! still ?
\global#1\ifnum#3=\plusthousand#2\else\dimexpr#3\dimexpr#2/\plusthousand\relax\relax\fi
\relax}
-\def\doapplyscaleboxsize
- {\doifelsenothing{\scaleparameter\c!maxheight}
- {\scaleboxoutervsize\textheight
- \ifinner
- \scaleboxoutervsize \vsize % \textheight =\vsize
- \scratchdimen\vsize % \scratchdimen=\textheight
- \else\ifinsidefloat
- \scaleboxoutervsize \vsize % \textheight =\vsize
- \scratchdimen\vsize % \scratchdimen=\textheight
- \else\ifinpagebody
- \scaleboxoutervsize \vsize % \textheight =\vsize
- \scratchdimen\vsize % \scratchdimen=\textheight
- \else % hm, there should be an option to force this
- \ifdim\pagegoal<\maxdimen
- \ifdim\pagetotal<\pagegoal
- \scratchdimen\dimexpr\pagegoal-\pagetotal\relax
- \else
- \scratchdimen\scaleboxoutervsize % \textheight
- \fi
- \else
- \scratchdimen\scaleboxoutervsize % \textheight
- \fi
- \fi\fi\fi}
- {\scratchdimen\scaleparameter\c!maxheight
- \scaleboxoutervsize\scratchdimen}%
- \doifelsenothing{\scaleparameter\c!height}
- {\scaleboxvsize\scratchdimen}
- {\scaleboxvsize\scaleparameter\c!height}%
- \doifelsenothing{\scaleparameter\c!width}
- {\scaleboxhsize\hsize}
- {\scaleboxhsize\scaleparameter\c!width}}
-
-\def\convertscaleboxinsertscale#1#2#3#4%
+\def\grph_scale_apply_size
+ {\ifx\p_maxheight\empty
+ \d_grph_scale_outer_v_size\textheight
+ \ifinner
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinsidefloat
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else\ifinpagebody
+ \d_grph_scale_outer_v_size \vsize % \textheight =\vsize
+ \scratchdimen\vsize % \scratchdimen=\textheight
+ \else % hm, there should be an option to force this
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal<\pagegoal
+ \scratchdimen\dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \scratchdimen\d_grph_scale_outer_v_size % \textheight
+ \fi
+ \else
+ \scratchdimen\d_grph_scale_outer_v_size % \textheight
+ \fi
+ \fi\fi\fi
+ \else
+ \scratchdimen\p_maxheight
+ \d_grph_scale_outer_v_size\scratchdimen
+ \fi
+ \ifx\p_height\empty
+ \d_grph_scale_v_size\scratchdimen
+ \else
+ \d_grph_scale_v_size\p_height
+ \fi
+ \ifx\p_width\empty
+ \d_grph_scale_h_size\hsize
+ \else
+ \d_grph_scale_h_size\p_width
+ \fi}
+
+\def\grph_scale_convert_large_scale#1#2#3#4%
{\scratchdimen#1\relax
\ifnum#3=\plusthousand
% == scale 1
@@ -404,9 +494,11 @@
\edef#2{\the\scratchdimen}%
\scratchcounter#3\relax
\ifnum\scratchcounter>\plustenthousand
- \divide\scratchcounter\!!ten \scratchdimen\the\scratchcounter\points
+ \divide\scratchcounter\plusten
+ \scratchdimen\the\scratchcounter\points
\else
- \scratchdimen\the\scratchcounter\points \divide\scratchdimen\!!ten
+ \scratchdimen\the\scratchcounter\points
+ \divide\scratchdimen\plusten
\fi
\edef#4{\withoutpt\the\scratchdimen}}
@@ -415,18 +507,40 @@
% {\externalfigure[mill.png][frame=on,height=3cm,equalwidth=6cm]} {}
% \stopcombination
-\def\doscaleboxposition
- {\doifsomething{\scaleparameter\c!equalwidth}
- {\scratchdimen\scaleparameter\c!equalwidth\relax
- \ifdim\wd\nextbox<\scratchdimen
- \setbox\nextbox\hbox to \scratchdimen{\hss\box\nextbox\hss}%
- \fi}%
- \doifsomething{\scaleparameter\c!equalheight}
- {\scratchdimen\scaleparameter\c!equalheight\relax
- \ifdim\ht\nextbox<\scratchdimen
- \setbox\nextbox\vbox to \scratchdimen{\vss\box\nextbox\vss}%
- \fi}}
-
+\def\grph_scale_position
+ {\ifx\p_equalwidth\empty \else
+ \scratchdimen\p_equalwidth\relax
+ \ifdim\d_grph_scale_wd<\scratchdimen
+ \setbox\nextbox\hbox to \scratchdimen{\hss\box\nextbox\hss}%
+ \fi
+ \fi
+ \ifx\p_equalheight\empty \else
+ \scratchdimen\p_equalheight\relax
+ \ifdim\d_grph_scale_ht<\scratchdimen
+ \setbox\nextbox\vbox to \scratchdimen{\vss\box\nextbox\vss}%
+ \fi
+ \fi}
+
+\unexpanded\def\fastscale#1%
+ {\ifnum#1=1000\relax
+ \expandafter\grph_scale_fast_nop
+ \else
+ \expandafter\grph_scale_fast_yes
+ \fi{#1}}
+
+\def\grph_scale_fast_nop#1%
+ {\hbox}
+
+\def\grph_scale_fast_yes#1%
+ {\edef\finalscaleboxxscale{\withoutpt\the\dimexpr#1pt/1000\relax}% brrr
+ \let\finalscaleboxyscale\finalscaleboxxscale
+ \dowithnextboxcs\grph_scale_fast_finish\hbox}
+
+\def\grph_scale_fast_finish
+ {\grph_scale_apply
+ \box\nextbox
+ \endgroup}
+
%D \macros
%D {clip, setupclipping}
%D
@@ -461,66 +575,75 @@
\unexpanded\def\setupclipping
{\dodoubleargument\getparameters[\??cp]}
-\def\clip
- {\dosingleempty\doclip}
+\unexpanded\def\clip
+ {\dosingleempty\grph_clip}
-\def\doclip[#1]% nb top->bottom left->right
+\def\grph_clip[#1]% nb top->bottom left->right
{\bgroup
- \getparameters[\??cp][#1]%
- \doifelse\@@cpstate\v!start\dodoclip{\egroup\hbox}}
-
-\def\dodoclip
- {\dowithnextbox
- {\ifdim\@@cpwidth>\zeropoint
- \!!dimena\@@cpwidth
- \!!dimenc\@@cphoffset
- \else
- \!!dimena\nextboxwd
- \divide\!!dimena \@@cpnx
- \!!dimenc\@@cpx\!!dimena
- \advance\!!dimenc -\!!dimena
- \!!dimena\@@cpsx\!!dimena
- \fi
- \relax % sure
- \ifdim\@@cpheight>\zeropoint
- \!!dimenb\@@cpheight
- \!!dimend\nextboxht
- \advance\!!dimend -\@@cpvoffset
- \advance\!!dimend -\!!dimenb
- \else
- \!!dimenb\nextboxht
- \divide\!!dimenb \@@cpny
- \!!dimend-\@@cpy\!!dimenb
- \advance\!!dimend -\@@cpsy\!!dimenb
- \advance\!!dimend \!!dimenb
- \!!dimenb\@@cpsy\!!dimenb
- \advance\!!dimend \nextboxht % dimend !
- \fi
- \setbox\nextbox\hbox % old
- {\advance\!!dimenc -\@@cpleftoffset % new !
- \advance\!!dimend -\@@cpbottomoffset % new ! % - added
- \hskip-\!!dimenc\lower\!!dimend\flushnextbox}% old
- \nextboxwd\zeropoint
- \nextboxht\zeropoint
- \nextboxdp\zeropoint
- \setbox\nextbox\hbox
- {\advance\!!dimena \@@cpleftoffset % new !
- \advance\!!dimena \@@cprightoffset % new !
- \advance\!!dimenb \@@cpbottomoffset % new !
- \advance\!!dimenb \@@cptopoffset % new !
- \dostartclipping\@@cpmp\!!dimena\!!dimenb % old
- \flushnextbox
- \dostopclipping}%
- \setbox\nextbox\hbox % new !
- {\!!dimena-\@@cpleftoffset % new !
- \!!dimenb \@@cpbottomoffset % new ! % - removed
- \hskip\!!dimena\lower\!!dimenb\flushnextbox}% new !
- \nextboxwd\!!dimena
- \nextboxht\!!dimenb
- \nextboxdp\zeropoint
- \flushnextbox
- \egroup}%
- \hbox}
+ \iffirstargument
+ \getparameters[\??cp][#1]%
+ \fi
+ \dowithnextboxcs\grph_clip_finish\hbox}
+
+\def\grph_clip_finish
+ {\doifelse\@@cpstate\v!start
+ \grph_clip_yes_finish
+ \grph_clip_nop_finish}
+
+\def\grph_clip_yes_finish
+ {\ifdim\@@cpwidth>\zeropoint
+ \!!dimena\@@cpwidth
+ \!!dimenc\@@cphoffset
+ \else
+ \!!dimena\wd\nextbox
+ \divide\!!dimena \@@cpnx
+ \!!dimenc\@@cpx\!!dimena
+ \advance\!!dimenc -\!!dimena
+ \!!dimena\@@cpsx\!!dimena
+ \fi
+ \relax % sure
+ \ifdim\@@cpheight>\zeropoint
+ \!!dimenb\@@cpheight
+ \!!dimend\ht\nextbox
+ \advance\!!dimend -\@@cpvoffset
+ \advance\!!dimend -\!!dimenb
+ \else
+ \!!dimenb\ht\nextbox
+ \divide\!!dimenb \@@cpny
+ \!!dimend-\@@cpy\!!dimenb
+ \advance\!!dimend -\@@cpsy\!!dimenb
+ \advance\!!dimend \!!dimenb
+ \!!dimenb\@@cpsy\!!dimenb
+ \advance\!!dimend \ht\nextbox % dimend !
+ \fi
+ \setbox\nextbox\hbox % old
+ {\advance\!!dimenc -\@@cpleftoffset % new !
+ \advance\!!dimend -\@@cpbottomoffset % new ! % - added
+ \hskip-\!!dimenc\lower\!!dimend\box\nextbox}% old
+ \wd\nextbox\zeropoint
+ \ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \setbox\nextbox\hbox
+ {\advance\!!dimena \@@cpleftoffset % new !
+ \advance\!!dimena \@@cprightoffset % new !
+ \advance\!!dimenb \@@cpbottomoffset % new !
+ \advance\!!dimenb \@@cptopoffset % new !
+ \dostartclipping\@@cpmp\!!dimena\!!dimenb % old
+ \box\nextbox
+ \dostopclipping}%
+ \setbox\nextbox\hbox % new !
+ {\!!dimena-\@@cpleftoffset % new !
+ \!!dimenb \@@cpbottomoffset % new ! % - removed
+ \hskip\!!dimena\lower\!!dimenb\box\nextbox}% new !
+ \wd\nextbox\!!dimena
+ \ht\nextbox\!!dimenb
+ \dp\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
+
+\def\grph_clip_nop_finish
+ {\box\nextbox
+ \egroup}
\setupclipping
[\c!state=\v!start,
@@ -555,26 +678,338 @@
%D \stopbuffer
%D
%D \typebuffer \getbuffer
-
+
%D Mirroring.
-\def\domirrorbox % \hbox/\vbox/\vtop
+\unexpanded\def\mirror
{\bgroup
- \dowithnextbox
- {\dontshowcomposition
- \scratchdimen\nextboxwd
- % better use an hbox (if no \forgetall, leftskip etc may creep in)
- %\setbox\nextbox\vbox{\forgetall\dostartmirroring\hskip-\nextboxwd\flushnextbox\dostopmirroring}%
- \setbox\nextbox\hbox{\dostartmirroring\hskip-\nextboxwd\flushnextbox\dostopmirroring}%
- \nextboxwd\scratchdimen
- \flushnextbox
- \egroup}}
+ \dowithnextboxcs\grph_mirror_finish\hbox}
+
+\def\grph_mirror_finish
+ {\scratchdimen\wd\nextbox
+ % better use an hbox (if no \forgetall, leftskip etc may creep in)
+ %\setbox\nextbox\vbox{\forgetall\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
+ \setbox\nextbox\hbox{\dostartmirroring\hskip-\wd\nextbox\box\nextbox\dostopmirroring}%
+ \wd\nextbox\scratchdimen
+ \box\nextbox
+ \egroup}
+
+%D A couple of examples, demonstrating how the depth is
+%D taken care of:
+%D
+%D \startbuffer
+%D test\rotate[frame=on, rotation=0] {gans}%
+%D test\rotate[frame=on, rotation=90] {gans}%
+%D test\rotate[frame=on, rotation=180]{gans}%
+%D test\rotate[frame=on, rotation=270]{gans}%
+%D test
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
-\unexpanded\def\mirror
- {\domirrorbox\hbox}
+% When we rotate over arbitrary angles, we need to relocate the
+% resulting box because rotation brings that box onto the negative
+% axis. The calculations (mostly sin and cosine) need to be tuned for
+% the way a box is packages (i.e. the refence point). A typical example
+% of drawing, scribbling, and going back to the days of school math.
+%
+% We do a bit more calculations than needed, simply because that way
+% it's easier to debug the code.
+
+% Cleanup in progress ... todo: less boxing
+
+\installcorenamespace {rotate}
+\installcorenamespace {rotatelocation}
+\installcorenamespace {rotatepreset}
+
+% we can alias these to \d_layers-* to save some dimens or maybe have a generic
+% set of scratch variables
+
+% maybe just \rotation_...
+
+\newdimen\d_grph_rotate_x_size
+\newdimen\d_grph_rotate_y_size
+\newdimen\d_grph_rotate_x_offset
+\newdimen\d_grph_rotate_y_offset
+\newdimen\d_grph_rotate_x_position
+\newdimen\d_grph_rotate_y_position
+
+\newdimen\d_grph_rotate_used_height
+
+\let\d_grph_rotate_width \!!widtha
+\let\d_grph_rotate_height\!!heighta
+\let\d_grph_rotate_depth \!!deptha
+
+\let\d_grph_rotate_saved_width \!!widthb
+\let\d_grph_rotate_saved_height\!!heightb
+\let\d_grph_rotate_saved_depth \!!depthb
+
+\newconditional\c_grph_rotate_obey_depth
+\newconditional\c_grph_rotate_not_fit
+\newconditional\c_grph_rotate_center
+
+\installframedcommandhandler \??rotate {rotate} \??rotate
+
+\setuprotate
+ [\c!rotation=90,
+ \c!location=\v!normal,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off]
+
+\let\p_rotation_location\empty
+\let\p_rotation_rotation\empty
+
+\unexpanded\def\rotate % \bgroup: \rotate kan argument zijn
+ {\bgroup
+ \dosingleempty\grph_rotate}
+
+\def\grph_rotate[#1]%
+ {\iffirstargument
+ \setupcurrentrotate[#1]%
+ \fi
+ \edef\p_rotation_location{\rotateparameter\c!location}%
+ \edef\p_rotation_rotation{\rotateparameter\c!rotation}%
+ \csname\??rotatelocation
+ \ifcsname\??rotatelocation\p_rotation_location\endcsname\p_rotation_location\else\v!default\fi
+ \endcsname}
+
+\def\grph_rotate_framed
+ {\resetrotateparameter\c!location
+ \dowithnextboxcs\grph_rotate_finish\vbox
+ \inheritedrotateframed}
+
+\def\grph_rotate_normal
+ {\dowithnextboxcs\grph_rotate_finish\vbox}
+
+\def\grph_rotate_finish
+ {\grph_rotate_finish_indeed
+ \egroup}
+
+\setvalue{\??rotatelocation\v!depth}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!fit}%
+ {\settrue \c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!broad}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!high}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth
+ \grph_rotate_framed}
+
+\setvalue{\??rotatelocation\v!middle}%
+ {\setfalse\c_grph_rotate_not_fit
+ \settrue \c_grph_rotate_center
+ \setfalse\c_grph_rotate_obey_depth % hm, depth ?
+ \grph_rotate_normal}
+
+\setvalue{\??rotatelocation\v!default}%
+ {\setfalse\c_grph_rotate_not_fit
+ \setfalse\c_grph_rotate_center
+ \settrue \c_grph_rotate_obey_depth
+ \grph_rotate_framed}
+
+\unexpanded\def\dorotatebox#1% {angle} \hbox/\vbox/\vtop % a fast low level one
+ {\ifcase#1\relax
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\grph_rotate_box
+ \fi{#1}}
+
+\def\grph_rotate_box#1% {angle} \hbox/\vbox/\vtop
+ {\bgroup
+ \hbox\bgroup % compatibility hack
+ \edef\p_rotation_rotation{#1}%
+ \dowithnextboxcs\grph_rotate_finish_box}
+
+\def\grph_rotate_finish_box
+ {\setfalse\c_grph_rotate_not_fit % this is the same as broad but
+ \setfalse\c_grph_rotate_center % without the following grab as
+ \setfalse\c_grph_rotate_obey_depth % we call finish directly
+ \grph_rotate_finish_indeed
+ \egroup
+ \egroup}
+
+\def\grph_rotate_finish_indeed
+ {\hbox\bgroup
+ \ifx\p_rotation_rotation\empty
+ \grph_rotate_finish_nop
+ \else
+ \grph_rotate_finish_yes
+ \fi
+ \egroup}
+
+\def\grph_rotate_finish_nop
+ {\boxcursor\box\nextbox}
+
+\setvalue{\??rotatepreset\v!left}%
+ {\edef\p_rotation_rotation{\doifoddpageelse{90}{270}}}
+
+\setvalue{\??rotatepreset\v!right}%
+ {\edef\p_rotation_rotation{\doifoddpageelse{270}{90}}}
+
+\setvalue{\??rotatepreset\v!inner}%
+ {\signalrightpage
+ \doifrightpageelse{\def\p_rotation_rotation{270}}{\def\p_rotation_rotation{90}}}
+
+\setvalue{\??rotatepreset\v!outer}%
+ {\signalrightpage
+ \doifrightpageelse{\def\p_rotation_rotation{90}}{\def\p_rotation_rotation{270}}}
+
+\setvalue{\??rotatepreset\v!default}%
+ {\edef\p_rotation_rotation{\realnumber{\p_rotation_rotation}}}% get rid of leading zeros and spaces
+
+\def\grph_rotate_finish_yes
+ {\csname\??rotatepreset
+ \ifcsname\??rotatepreset\p_rotation_rotation\endcsname\p_rotation_rotation\else\v!default\fi
+ \endcsname
+ \setbox\nextbox\vbox{\box\nextbox}% not really needed
+ \dontcomplain
+ \ifconditional\c_grph_rotate_center
+ \d_grph_rotate_saved_width \wd\nextbox
+ \d_grph_rotate_saved_height\ht\nextbox
+ \d_grph_rotate_saved_depth \dp\nextbox
+ \setbox\nextbox\vbox{\vskip.5\ht\nextbox\hskip-.5\wd\nextbox\box\nextbox}%
+ \smashbox\nextbox
+ \fi
+ \d_grph_rotate_width \wd\nextbox
+ \d_grph_rotate_height\ht\nextbox
+ \d_grph_rotate_depth \dp\nextbox
+ \setbox\nextbox\vbox{\hbox{\raise\dp\nextbox\box\nextbox}}%
+ \d_grph_rotate_used_height \ht\nextbox
+ % much of the next happens in lua (all the sin and cos) so we can do that in
+ % one go if needed
+ \setcalculatedcos\cos\p_rotation_rotation
+ \setcalculatedsin\sin\p_rotation_rotation
+ \ifdim\sin\points>\zeropoint
+ \ifdim\cos\points>\zeropoint
+ \grph_rotate_calculate_a
+ \grph_rotate_apply
+ \else
+ \grph_rotate_calculate_b
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\sin\d_grph_rotate_depth\else\d_grph_rotate_x_size\fi
+ \fi
+ \else
+ \ifdim\cos\points<\zeropoint
+ \grph_rotate_calculate_c
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\negated\sin\d_grph_rotate_height\else\d_grph_rotate_x_size\fi
+ \else\ifdim\sin\points=\zeropoint
+ \grph_rotate_calculate_d
+ \grph_rotate_apply
+ % no wd ?
+ \else
+ \grph_rotate_calculate_e
+ \grph_rotate_apply
+ \wd\nextbox\ifconditional\c_grph_rotate_not_fit\negated\sin\d_grph_rotate_height\else\d_grph_rotate_x_size\fi
+ \fi\fi
+ \fi
+ \ifconditional\c_grph_rotate_center
+ \setbox\nextbox\vbox{\vskip-.5\d_grph_rotate_saved_height\hskip.5\d_grph_rotate_saved_height\box\nextbox}%
+ \wd\nextbox\d_grph_rotate_saved_width
+ \ht\nextbox\d_grph_rotate_saved_height
+ \dp\nextbox\d_grph_rotate_saved_depth
+ \fi
+ \boxcursor\box\nextbox}
+
+\def\grph_rotate_calculate_a
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\zeropoint
+ \d_grph_rotate_y_position\cos\d_grph_rotate_used_height
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr\negated\sin\d_grph_rotate_used_height+\sin\d_grph_rotate_depth\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\cos\d_grph_rotate_depth
+ \fi}
+
+\def\grph_rotate_calculate_b
+ {\d_grph_rotate_x_size\dimexpr\negated\cos\d_grph_rotate_width+\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\sin\d_grph_rotate_width+\negated\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\negated\cos\d_grph_rotate_width
+ \d_grph_rotate_y_position\zeropoint
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\sin\d_grph_rotate_depth\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\negated\cos\d_grph_rotate_height
+ \fi}
+
+\def\grph_rotate_calculate_c
+ {\d_grph_rotate_x_size\dimexpr\negated\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\negated\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\d_grph_rotate_x_size
+ \d_grph_rotate_y_position\negated\sin\d_grph_rotate_width
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\negated\sin\d_grph_rotate_height\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\dimexpr\d_grph_rotate_y_size+\cos\d_grph_rotate_depth\relax
+ \fi}
+
+\def\grph_rotate_calculate_d
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\zeropoint
+ \d_grph_rotate_y_position\d_grph_rotate_y_size
+ \d_grph_rotate_x_offset\zeropoint
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\d_grph_rotate_depth
+ \fi}
+
+\def\grph_rotate_calculate_e
+ {\d_grph_rotate_x_size\dimexpr\cos\d_grph_rotate_width+\negated\sin\d_grph_rotate_used_height\relax
+ \d_grph_rotate_y_size\dimexpr\negated\sin\d_grph_rotate_width+\cos\d_grph_rotate_used_height\relax
+ \d_grph_rotate_x_position\negated\sin\d_grph_rotate_used_height
+ \d_grph_rotate_y_position\d_grph_rotate_y_size
+ \ifconditional\c_grph_rotate_not_fit
+ \d_grph_rotate_x_offset\dimexpr-\d_grph_rotate_x_size+\negated\sin\d_grph_rotate_height\relax
+ \fi
+ \ifconditional\c_grph_rotate_obey_depth
+ \d_grph_rotate_y_offset\negated\sin\d_grph_rotate_depth
+ \fi}
-% \setbox0=\hbox{gans}
-% \ruledhbox{\copy0 \schaal[sx=2,sy=2]{\copy0}}
-% \mirror{\ruledhbox{\copy0 \schaal{\box0}}}
+\def\grph_rotate_apply
+ {\setbox\nextbox\vbox to \d_grph_rotate_y_size
+ {\vfill
+ \hbox to \d_grph_rotate_x_size
+ {\dostartrotation\p_rotation_rotation
+ \wd\nextbox\zeropoint
+ \ht\nextbox\zeropoint
+ \box\nextbox
+ \dostoprotation
+ \hfill}%
+ \kern\d_grph_rotate_y_position}%
+ \setbox\nextbox\hbox
+ {\kern\dimexpr\d_grph_rotate_x_position+\d_grph_rotate_x_offset\relax
+ \lower\d_grph_rotate_y_offset\box\nextbox}}
+
+% \dostepwiserecurse{0}{360}{10}
+% {\startlinecorrection[blank]
+% \hbox
+% {\expanded{\setuprotate[rotation=\recurselevel]}%
+% \traceboxplacementtrue
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=depth] {\ruledhbox{\bfb (depth)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=fit] {\ruledhbox{\bfb (fit)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=broad] {\ruledhbox{\bfb (broad)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=normal]{\ruledhbox{\bfb (normal)}}}}%
+% \hbox to .2\hsize{\hss\ruledhbox{\rotate[location=high] {\ruledhbox{\bfb (high)}}}}}
+% \stoplinecorrection}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/hand-def.mkii b/Master/texmf-dist/tex/context/base/hand-def.mkii
index 0a19ce270d1..ab0044a8eda 100644
--- a/Master/texmf-dist/tex/context/base/hand-def.mkii
+++ b/Master/texmf-dist/tex/context/base/hand-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Default Protruding Factors,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/hand-ini.mkii b/Master/texmf-dist/tex/context/base/hand-ini.mkii
index ac8a946961f..1d41c3adab7 100644
--- a/Master/texmf-dist/tex/context/base/hand-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/hand-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/hand-ini.mkiv b/Master/texmf-dist/tex/context/base/hand-ini.mkiv
index 7b973205992..450794d276f 100644
--- a/Master/texmf-dist/tex/context/base/hand-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/hand-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -39,36 +39,35 @@
%D New stuff.
-\unexpanded\def\setupfontexpansion {\dodoubleargument\dosetupfontexpansion }
-\unexpanded\def\setupfontprotrusion{\dodoubleargument\dosetupfontprotrusion}
+\unexpanded\def\setupfontexpansion {\dodoubleargument\font_expansion_setup }
+\unexpanded\def\setupfontprotrusion{\dodoubleargument\font_protrusion_setup}
-\def\dosetupfontexpansion [#1][#2]{\ctxcommand{setupfontexpansion ("#1","#2")}}
-\def\dosetupfontprotrusion[#1][#2]{\ctxcommand{setupfontprotrusion("#1","#2")}}
+\def\font_expansion_setup [#1][#2]{\ctxcommand{setupfontexpansion ("#1","#2")}}
+\def\font_protrusion_setup[#1][#2]{\ctxcommand{setupfontprotrusion("#1","#2")}}
% \setupfontprotrusion[quality-upright][vector=quality]
% \setupfontprotrusion[quality-slanted][vector=quality,right=1.5]
-%D Old stuff.
+\let\pdfadjustspacing\relax \newcount\pdfadjustspacing % a little bit protection
+\let\pdfprotrudechars\relax \newcount\pdfprotrudechars % a little bit protection
-\def\fonthandlingerror{\writestatus\m!fonts{font handling is replaced by features in mkiv}}
+\def\font_expansion_enable {\normalpdfadjustspacing\plustwo }
+\def\font_expansion_disable {\normalpdfadjustspacing\zerocount}
+\def\font_protruding_enable {\normalpdfprotrudechars\plustwo }
+\def\font_protruding_disable{\normalpdfprotrudechars\zerocount}
-\def\enableadjusting {\pdfadjustspacing\plustwo } \let\enableexpansion \enableadjusting
-\def\disableadjusting {\pdfadjustspacing\zerocount} \let\disableexpansion\disableadjusting
-\def\enableprotruding {\pdfprotrudechars\plustwo }
-\def\disableprotruding{\pdfprotrudechars\zerocount}
+\appendtoks \font_expansion_disable \to \everyforgetall % Here or not here?
+\appendtoks \font_protruding_disable \to \everyforgetall % Here or not here?
-\appendtoks \disableadjusting \to \everyforgetall % Here or not here?
-\appendtoks \disableprotruding \to \everyforgetall % Here or not here?
-
-\unexpanded\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen
-\unexpanded\def\definefonthandling {\dotripleempty\dodefinefonthandling}
-\unexpanded\def\setupfonthandling {\dodoubleempty\dosetupfonthandling }
-\def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror}
-\def\dosetupfonthandling [#1][#2]{\fonthandlingerror}
-\def\usehandling [#1]{\fonthandlingerror}
-
-%D Just to be sure, maybe users use it:
-
-\let\fonthandling\empty
+% \def\fonthandlingerror{\writestatus\m!fonts{font handling is replaced by features in mkiv}}
+%
+% \let\fonthandling\empty
+%
+% \unexpanded\def\startfonthandling #1{\fonthandlingerror\fonthandlingerror\gobbleuntil\stopfonthandling} % can't happen
+% \unexpanded\def\definefonthandling {\dotripleempty\dodefinefonthandling}
+% \unexpanded\def\setupfonthandling {\dodoubleempty\dosetupfonthandling }
+% \def\dodefinefonthandling[#1][#2][#3]{\fonthandlingerror}
+% \def\dosetupfonthandling [#1][#2]{\fonthandlingerror}
+% \def\usehandling [#1]{\fonthandlingerror}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/java-ans.mkii b/Master/texmf-dist/tex/context/base/java-ans.mkii
index 636c894f931..7e310baa495 100644
--- a/Master/texmf-dist/tex/context/base/java-ans.mkii
+++ b/Master/texmf-dist/tex/context/base/java-ans.mkii
@@ -5,7 +5,7 @@
%D subtitle=Answer Analization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-exa.mkii b/Master/texmf-dist/tex/context/base/java-exa.mkii
index f40f70f84df..584ee13512d 100644
--- a/Master/texmf-dist/tex/context/base/java-exa.mkii
+++ b/Master/texmf-dist/tex/context/base/java-exa.mkii
@@ -5,7 +5,7 @@
%D subtitle=Example Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-fil.mkii b/Master/texmf-dist/tex/context/base/java-fil.mkii
index 4d79a2ace9e..20376af44d6 100644
--- a/Master/texmf-dist/tex/context/base/java-fil.mkii
+++ b/Master/texmf-dist/tex/context/base/java-fil.mkii
@@ -5,7 +5,7 @@
%D subtitle=Filing and Printing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-fld.mkii b/Master/texmf-dist/tex/context/base/java-fld.mkii
index 93a90dc0afc..0a76cc93c12 100644
--- a/Master/texmf-dist/tex/context/base/java-fld.mkii
+++ b/Master/texmf-dist/tex/context/base/java-fld.mkii
@@ -5,7 +5,7 @@
%D subtitle=Field Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-imp-exa.mkiv b/Master/texmf-dist/tex/context/base/java-imp-exa.mkiv
index f40f70f84df..584ee13512d 100644
--- a/Master/texmf-dist/tex/context/base/java-imp-exa.mkiv
+++ b/Master/texmf-dist/tex/context/base/java-imp-exa.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Example Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-imp-fil.mkiv b/Master/texmf-dist/tex/context/base/java-imp-fil.mkiv
index 592e9460d45..808950f2807 100644
--- a/Master/texmf-dist/tex/context/base/java-imp-fil.mkiv
+++ b/Master/texmf-dist/tex/context/base/java-imp-fil.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Filing and Printing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-imp-fld.mkiv b/Master/texmf-dist/tex/context/base/java-imp-fld.mkiv
index a0909f59496..625bfce115a 100644
--- a/Master/texmf-dist/tex/context/base/java-imp-fld.mkiv
+++ b/Master/texmf-dist/tex/context/base/java-imp-fld.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Field Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-imp-rhh.mkiv b/Master/texmf-dist/tex/context/base/java-imp-rhh.mkiv
new file mode 100644
index 00000000000..5f057f55070
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/java-imp-rhh.mkiv
@@ -0,0 +1,34 @@
+%D \module
+%D [ file=java-rhh,
+%D version=2010.02.01,
+%D title=\CONTEXT\ JavaScript Macros,
+%D subtitle=Runtime Highlight Hack,
+%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 As hightlighting is rather intrusive it makes sense to turn it off when
+%D using nice appearances.
+
+% app.runtimeHighlightColor = [ "T" ] ;
+%
+% var SavedAlwaysShowFocus = app.alwaysShowFocus ;
+% app.alwaysShowFocus = true ;
+% "app.alwaysShowFocus = SavedAlwaysShowFocus ; "
+
+\startJSpreamble RuntimeHighlightHack used now
+ var SavedHighlightState = app.runtimeHighlight ;
+ var SavedFocusRectState = app.focusRect ;
+ app.runtimeHighlight = false ;
+ app.focusRect = true ;
+ this.setAction("WillClose",
+ "app.runtimeHighlight = SavedHighlightState ; " +
+ "app.focusRect = SavedFocusRectState ; "
+ ) ;
+\stopJSpreamble
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/java-imp-stp.mkiv b/Master/texmf-dist/tex/context/base/java-imp-stp.mkiv
index ebddd8cc6f6..8ac5d58b8b4 100644
--- a/Master/texmf-dist/tex/context/base/java-imp-stp.mkiv
+++ b/Master/texmf-dist/tex/context/base/java-imp-stp.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Stepping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-ini.lua b/Master/texmf-dist/tex/context/base/java-ini.lua
index b3b06667815..1e98de7173f 100644
--- a/Master/texmf-dist/tex/context/base/java-ini.lua
+++ b/Master/texmf-dist/tex/context/base/java-ini.lua
@@ -32,6 +32,9 @@ local codes, preambles, functions = javascripts.codes, javascripts.preambles, ja
local preambled = { }
local function storefunction(s,preamble)
+ if trace_javascript then
+ report_javascripts("found: function '%s'",s)
+ end
functions[s] = preamble
end
@@ -122,7 +125,7 @@ function javascripts.usepreamblenow(name) -- now later
end
end
-local splitter = lpeg.Ct(lpeg.splitat(lpeg.patterns.commaspacer))
+local splitter = lpeg.tsplitat(lpeg.patterns.commaspacer)
local used, reported = false, { } -- we can cache more
@@ -171,7 +174,7 @@ end
function javascripts.flushpreambles()
local t = { }
- if used then
+-- if used then -- we want to be able to enforce inclusion
for i=1,#preambles do
local preamble = preambles[i]
if preamble[2] == "now" then
@@ -181,24 +184,41 @@ function javascripts.flushpreambles()
t[#t+1] = { preamble[1], preamble[3] }
end
end
- end
+-- end
return t
end
local patterns = { "java-imp-%s.mkiv", "java-imp-%s.tex", "java-%s.mkiv", "java-%s.tex" }
+local function action(name,foundname)
+ context.startnointerference()
+ context.startreadingfile()
+ context.input(foundname)
+ status_javascripts("loaded: library '%s'",name)
+ context.stopreadingfile()
+ context.stopnointerference()
+end
+
+local function failure(name)
+ report_javascripts("unknown: library '%s'",name)
+end
+
function javascripts.usescripts(name)
- -- this will become pure lua, no context
if name ~= variables.reset then -- reset is obsolete
- commands.uselibrary(name,patterns,function(name,foundname)
- context.startnointerference()
- context.startreadingfile()
- context.input(foundname)
- status_javascripts("loaded: library '%s'",name)
- context.stopreadingfile()
- context.stopnointerference()
- end, function(name)
- report_javascripts("unknown: library '%s'",name)
- end)
+ commands.uselibrary {
+ name = name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
end
end
+
+-- interface
+
+commands.storejavascriptcode = interactions.javascripts.storecode
+commands.storejavascriptpreamble = interactions.javascripts.storepreamble
+commands.addtojavascriptpreamble = interactions.javascripts.addtopreamble
+commands.usejavascriptpreamble = interactions.javascripts.usepreamblenow
+commands.usejavascriptscripts = interactions.javascripts.usescripts
diff --git a/Master/texmf-dist/tex/context/base/java-ini.mkii b/Master/texmf-dist/tex/context/base/java-ini.mkii
index 68516ec4e8d..2e62ca166f4 100644
--- a/Master/texmf-dist/tex/context/base/java-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/java-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/java-ini.mkiv b/Master/texmf-dist/tex/context/base/java-ini.mkiv
index 4013d82af51..e4f0bf28b4c 100644
--- a/Master/texmf-dist/tex/context/base/java-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/java-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -110,10 +110,10 @@
\obeylualines
\obeyluatokens
\def\u{\letterbackslash u}%
- \dostartJScode}
+ \java_start_code}
-\long\def\dostartJScode#1\stopJScode
- {\normalexpanded{\endgroup\ctxlua{interactions.javascripts.storecode(\!!bs#1\!!es)}}}
+\def\java_start_code#1\stopJScode
+ {\normalexpanded{\endgroup\ctxcommand{storejavascriptcode(\!!bs#1\!!es)}}}
\let\stopJScode\relax
@@ -122,16 +122,15 @@
\obeylualines
\obeyluatokens
\def\u{\letterbackslash u}%
- \dostartJSpreamble}
+ \java_start_preamble}
-\long\def\dostartJSpreamble#1\stopJSpreamble
- {\normalexpanded{\endgroup\ctxlua{interactions.javascripts.storepreamble(\!!bs#1\!!es)}}}
+\def\java_start_preamble#1\stopJSpreamble
+ {\normalexpanded{\endgroup\ctxcommand{storejavascriptpreamble(\!!bs#1\!!es)}}}
\let\stopJSpreamble\relax
-\def\setJSpreamble #1#2{\ctxlua{interactions.javascripts.storepreamble ("#1",\!!bs#2\!!es)}}
-\def\addtoJSpreamble #1#2{\ctxlua{interactions.javascripts.addtopreamble ("#1",\!!bs#2\!!es)}}
-\def\douseJSpreamblenow#1{\ctxlua{interactions.javascripts.usepreamblenow("#1")}}
+\unexpanded\def\setJSpreamble #1#2{\ctxcommand{storejavascriptpreamble("#1",\!!bs#2\!!es)}}
+\unexpanded\def\addtoJSpreamble#1#2{\ctxcommand{addtojavascriptpreamble("#1",\!!bs#2\!!es)}}
%D \macros
%D {useJSscripts}
@@ -148,11 +147,11 @@
%D
%D The not so complicated implementation of this macro is:
-\def\douseJSscripts[#1][#2]%
- {\ctxlua{interactions.javascripts.usescripts(\!!bs#1\!!es)}%
- \douseJSpreamblenow{#2}}
-
\def\useJSscripts
- {\dodoubleempty\douseJSscripts}
+ {\dodoubleempty\java_use_scripts}
+
+\def\java_use_scripts[#1][#2]%
+ {\ctxcommand{usejavascriptscripts(\!!bs#1\!!es)}% two steps as this one calls tex code
+ \ctxcommand{usejavascriptpreamble("#2")}} % so this one comes later
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/java-stp.mkii b/Master/texmf-dist/tex/context/base/java-stp.mkii
index df4fbcc2f4e..7283c8ceb3d 100644
--- a/Master/texmf-dist/tex/context/base/java-stp.mkii
+++ b/Master/texmf-dist/tex/context/base/java-stp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Stepping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/l-aux.lua b/Master/texmf-dist/tex/context/base/l-aux.lua
deleted file mode 100644
index aa04951bfbf..00000000000
--- a/Master/texmf-dist/tex/context/base/l-aux.lua
+++ /dev/null
@@ -1,13 +0,0 @@
-if not modules then modules = { } end modules ['l-aux'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-aux = aux or { }
-
-require("util-int") for k, v in next, utilities.interfaces do aux[k] = v end
-require("util-tab") for k, v in next, utilities.tables do aux[k] = v end
-require("util-fmt") for k, v in next, utilities.formatters do aux[k] = v end
diff --git a/Master/texmf-dist/tex/context/base/l-boolean.lua b/Master/texmf-dist/tex/context/base/l-boolean.lua
index 3fff7c1263f..2d502f164e8 100644
--- a/Master/texmf-dist/tex/context/base/l-boolean.lua
+++ b/Master/texmf-dist/tex/context/base/l-boolean.lua
@@ -11,10 +11,6 @@ local type, tonumber = type, tonumber
boolean = boolean or { }
local boolean = boolean
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
function boolean.tonumber(b)
if b then return 1 else return 0 end -- test and return or return
end
diff --git a/Master/texmf-dist/tex/context/base/l-dir.lua b/Master/texmf-dist/tex/context/base/l-dir.lua
index 1d59b9220d9..71de3114e97 100644
--- a/Master/texmf-dist/tex/context/base/l-dir.lua
+++ b/Master/texmf-dist/tex/context/base/l-dir.lua
@@ -23,8 +23,6 @@ local attributes = lfs.attributes
local walkdir = lfs.dir
local isdir = lfs.isdir
local isfile = lfs.isfile
-local mkdir = lfs.mkdir
-local chdir = lfs.chdir
local currentdir = lfs.currentdir
-- handy
@@ -94,13 +92,13 @@ local function collectpattern(path,patt,recurse,result)
local ok, scanner
result = result or { }
if path == "/" then
- ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
else
- ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
end
if ok and type(scanner) == "function" then
if not find(path,"/$") then path = path .. '/' end
- for name in scanner do
+ for name in scanner, first do
local full = path .. name
local attr = attributes(full)
local mode = attr.mode
@@ -292,7 +290,7 @@ if onwindows then
pth = pth .. "/" .. s
end
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
return pth, (isdir(pth) == true)
@@ -335,7 +333,7 @@ else
pth = pth .. "/" .. s
end
if make_indeed and not first and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
else
@@ -343,7 +341,7 @@ else
for s in gmatch(str,"[^/]+") do
pth = pth .. "/" .. s
if make_indeed and not isdir(pth) then
- mkdir(pth)
+ lfs.mkdir(pth)
end
end
end
@@ -378,10 +376,10 @@ if onwindows then
first, last = match(str,"^([a-zA-Z]:)(.*)$")
if first and not find(last,"^/") then
local d = currentdir()
- if chdir(first) then
+ if lfs.chdir(first) then
first = dir.current()
end
- chdir(d)
+ lfs.chdir(d)
end
end
if not first then
diff --git a/Master/texmf-dist/tex/context/base/l-file.lua b/Master/texmf-dist/tex/context/base/l-file.lua
index 66a14dd5765..48f6a39fe8b 100644
--- a/Master/texmf-dist/tex/context/base/l-file.lua
+++ b/Master/texmf-dist/tex/context/base/l-file.lua
@@ -113,10 +113,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -146,6 +146,15 @@ end
--~ print(file.join("http:///a","/y"))
--~ print(file.join("//nas-1","/y"))
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
if lfs.isdir(name) then
name = name .. "/m_t_x_t_e_s_t.tmp"
@@ -155,19 +164,23 @@ function file.is_writable(name)
os.remove(name)
return true
end
- else
- local existing = lfs.isfile(name)
- f = io.open(name,"ab")
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
if f then
f:close()
- if not existing then os.remove(name) end
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
return true
end
end
return false
end
-
function file.is_readable(name)
local a = attributes(name)
return a and sub(a.permissions,1,1) == "r"
@@ -213,7 +226,7 @@ end
--~ variant. After some skyping we got it sort of compatible with the old
--~ one. After that the anchoring to currentdir was added in a better way.
--~ Of course there are some optimizations too. Finally we had to deal with
---~ windows drive prefixes and thinsg like sys://.
+--~ windows drive prefixes and things like sys://.
function file.collapsepath(str,anchor)
if anchor and not find(str,"^/") and not find(str,"^%a:") then
@@ -241,7 +254,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -415,10 +428,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
+
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
diff --git a/Master/texmf-dist/tex/context/base/l-io.lua b/Master/texmf-dist/tex/context/base/l-io.lua
index a740996c68c..4f27dc1dcd1 100644
--- a/Master/texmf-dist/tex/context/base/l-io.lua
+++ b/Master/texmf-dist/tex/context/base/l-io.lua
@@ -252,3 +252,8 @@ function io.readstring(f,n,m)
local str = gsub(f:read(n),"%z","")
return str
end
+
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
diff --git a/Master/texmf-dist/tex/context/base/l-lpeg.lua b/Master/texmf-dist/tex/context/base/l-lpeg.lua
index ce0cc67efe7..25d48ee75d7 100644
--- a/Master/texmf-dist/tex/context/base/l-lpeg.lua
+++ b/Master/texmf-dist/tex/context/base/l-lpeg.lua
@@ -6,9 +6,51 @@ if not modules then modules = { } end modules ['l-lpeg'] = {
license = "see context related readme files"
}
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
local lpeg = require("lpeg")
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+--~ local lpmatch = lpeg.match
+--~ local lpprint = lpeg.print
+--~ local lpp = lpeg.P
+--~ local lpr = lpeg.R
+--~ local lps = lpeg.S
+--~ local lpc = lpeg.C
+--~ local lpb = lpeg.B
+--~ local lpv = lpeg.V
+--~ local lpcf = lpeg.Cf
+--~ local lpcb = lpeg.Cb
+--~ local lpcg = lpeg.Cg
+--~ local lpct = lpeg.Ct
+--~ local lpcs = lpeg.Cs
+--~ local lpcc = lpeg.Cc
+--~ local lpcmt = lpeg.Cmt
+--~ local lpcarg = lpeg.Carg
+
+--~ function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
+
+--~ function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
+--~ function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
+--~ function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
+--~ function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
+--~ function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
+--~ function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
+--~ function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
+--~ function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
+--~ function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
+--~ function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
+--~ function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
+--~ function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
+--~ function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
+--~ function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
+
local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
-- Beware, we predefine a bunch of patterns here and one reason for doing so
-- is that we get consistent behaviour in some of the visualizers.
@@ -34,7 +76,7 @@ patterns.alwaysmatched = alwaysmatched
local digit, sign = R('09'), S('+-')
local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
+local newline = crlf + S("\r\n") -- cr + lf
local escaped = P("\\") * anything
local squote = P("'")
local dquote = P('"')
@@ -89,7 +131,7 @@ patterns.space = space
patterns.tab = P("\t")
patterns.spaceortab = patterns.space + patterns.tab
patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
patterns.newline = newline
patterns.emptyline = newline^1
patterns.nonspacer = 1 - patterns.spacer
@@ -115,16 +157,12 @@ patterns.unspacer = ((patterns.spacer^1)/"")^0
patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
patterns.beginline = #(1-newline)
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
---~ print(string.unquoted("test"))
---~ print(string.unquoted([["t\"est"]]))
---~ print(string.unquoted([["t\"est"x]]))
---~ print(string.unquoted("\'test\'"))
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
function lpeg.anywhere(pattern) --slightly adapted from website
return P { P(pattern) + 1 * V(1) } -- why so complex?
@@ -134,7 +172,14 @@ function lpeg.splitter(pattern, action)
return (((1-P(pattern))^1)/action+1)^0
end
-local splitters_s, splitters_m = { }, { }
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
local function splitat(separator,single)
local splitter = (single and splitters_s[separator]) or splitters_m[separator]
@@ -153,7 +198,24 @@ local function splitat(separator,single)
return splitter
end
-lpeg.splitat = splitat
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
--~ local p = splitat("->",false) print(match(p,"oeps->what->more")) -- oeps what more
--~ local p = splitat("->",true) print(match(p,"oeps->what->more")) -- oeps what->more
@@ -165,7 +227,7 @@ local cache = { }
function lpeg.split(separator,str)
local c = cache[separator]
if not c then
- c = Ct(splitat(separator))
+ c = tsplitat(separator)
cache[separator] = c
end
return match(c,str)
@@ -174,7 +236,7 @@ end
function string.split(str,separator)
local c = cache[separator]
if not c then
- c = Ct(splitat(separator))
+ c = tsplitat(separator)
cache[separator] = c
end
return match(c,str)
@@ -193,7 +255,7 @@ patterns.textline = content
--~ return match(linesplitter,str)
--~ end
-local linesplitter = Ct(splitat(newline))
+local linesplitter = tsplitat(newline)
patterns.linesplitter = linesplitter
@@ -201,12 +263,12 @@ function string.splitlines(str)
return match(linesplitter,str)
end
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
patterns.utflinesplitter = utflinesplitter
function string.utfsplitlines(str)
- return match(utflinesplitter,str)
+ return match(utflinesplitter,str or "")
end
--~ lpeg.splitters = cache -- no longer public
@@ -237,13 +299,11 @@ end
--~ from roberto's site:
-local f1 = string.byte
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
patterns.utf8byte = utf8byte
@@ -538,4 +598,159 @@ function lpeg.is_lpeg(p)
return p and lpegtype(p) == "pattern"
end
---~ Cf(Ct("") * (Cg(C(...) * "=" * Cs(...)))^0, rawset)
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
diff --git a/Master/texmf-dist/tex/context/base/l-math.lua b/Master/texmf-dist/tex/context/base/l-math.lua
index 48089957f71..43f60b56bee 100644
--- a/Master/texmf-dist/tex/context/base/l-math.lua
+++ b/Master/texmf-dist/tex/context/base/l-math.lua
@@ -29,6 +29,6 @@ if not math.sind then
end
if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
end
diff --git a/Master/texmf-dist/tex/context/base/l-os.lua b/Master/texmf-dist/tex/context/base/l-os.lua
index 91150623945..f9bd46e51c8 100644
--- a/Master/texmf-dist/tex/context/base/l-os.lua
+++ b/Master/texmf-dist/tex/context/base/l-os.lua
@@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['l-os'] = {
-- maybe build io.flush in os.execute
local os = os
-local find, format, gsub, upper = string.find, string.format, string.gsub, string.upper
+local find, format, gsub, upper, gmatch = string.find, string.format, string.gsub, string.upper, string.gmatch
local concat = table.concat
local random, ceil = math.random, math.ceil
local rawget, rawset, type, getmetatable, setmetatable, tonumber = rawget, rawset, type, getmetatable, setmetatable, tonumber
@@ -131,9 +131,9 @@ os.type = os.type or (io.pathseparator == ";" and "windows") or "unix"
os.name = os.name or (os.type == "windows" and "mswin" ) or "linux"
if os.type == "windows" then
- os.libsuffix, os.binsuffix = 'dll', 'exe'
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'dll', 'exe', { 'exe', 'cmd', 'bat' }
else
- os.libsuffix, os.binsuffix = 'so', ''
+ os.libsuffix, os.binsuffix, os.binsuffixes = 'so', '', { '' }
end
function os.launch(str)
@@ -368,3 +368,36 @@ function os.timezone(delta)
return 1
end
end
+
+local memory = { }
+
+local function which(filename)
+ local fullname = memory[filename]
+ if fullname == nil then
+ local suffix = file.suffix(filename)
+ local suffixes = suffix == "" and os.binsuffixes or { suffix }
+ for directory in gmatch(os.getenv("PATH"),"[^" .. io.pathseparator .."]+") do
+ local df = file.join(directory,filename)
+ for i=1,#suffixes do
+ local dfs = file.addsuffix(df,suffixes[i])
+ if io.exists(dfs) then
+ fullname = dfs
+ break
+ end
+ end
+ end
+ if not fullname then
+ fullname = false
+ end
+ memory[filename] = fullname
+ end
+ return fullname
+end
+
+os.which = which
+os.where = which
+
+-- print(os.which("inkscape.exe"))
+-- print(os.which("inkscape"))
+-- print(os.which("gs.exe"))
+-- print(os.which("ps2pdf"))
diff --git a/Master/texmf-dist/tex/context/base/l-pdfview.lua b/Master/texmf-dist/tex/context/base/l-pdfview.lua
index 6fd3ac24686..3f4a8bea5cf 100644
--- a/Master/texmf-dist/tex/context/base/l-pdfview.lua
+++ b/Master/texmf-dist/tex/context/base/l-pdfview.lua
@@ -8,35 +8,63 @@ if not modules then modules = { } end modules ['l-pdfview'] = {
-- Todo: figure out pdfopen/pdfclose on linux. Calling e.g. okular directly
-- doesn't work in linux when issued from scite as it blocks the editor (no
--- & possible or so).
+-- & possible or so). Unfortunately pdfopen keeps changing with not keeping
+-- downward compatibility (command line arguments and so).
+
+-- no 2>&1 any more, needs checking on windows
local format, concat = string.format, table.concat
pdfview = pdfview or { }
-local opencalls = {
- ['default'] = "pdfopen --ax --file", -- "pdfopen --back --file"
- ['xpdf'] = "xpdfopen",
-}
+local opencalls, closecalls, allcalls, runner
-local closecalls= {
- ['default'] = "pdfclose --ax --file",
- ['xpdf'] = nil,
-}
+if os.type == "windows" then
-local allcalls = {
- ['default'] = "pdfclose --ax --all",
- ['xpdf'] = nil,
-}
+ opencalls = {
+ ['default'] = "pdfopen --ax --file", -- --back --file --ax
+ ['acrobat'] = "pdfopen --ax --file", -- --back --file --ax
+ ['okular'] = 'start "test" "c:/data/system/kde/bin/okular.exe" --unique' -- todo!
+ }
+ closecalls= {
+ ['default'] = "pdfclose --ax --file", -- --ax
+ ['acrobat'] = "pdfclose --ax --file", -- --ax
+ ['okular'] = false,
+ }
+ allcalls = {
+ ['default'] = "pdfclose --ax --all", -- --ax
+ ['acrobat'] = "pdfclose --ax --all", -- --ax
+ ['okular'] = false,
+ }
+
+ pdfview.method = "acrobat"
+
+ runner = function(...)
+ os.execute(...)
+ end
-if os.type == "windows" then
- -- opencalls['okular'] = 'start "test" "c:/program files/kde/bin/okular.exe" --unique' -- todo: get focus
- opencalls['okular'] = 'start "test" "c:/data/system/kde/bin/okular.exe" --unique' -- todo: get focus
else
- opencalls['okular'] = 'okular --unique'
-end
-pdfview.method = "default"
+ opencalls = {
+ ['default'] = "pdfopen", -- we could pass the default here
+ ['okular'] = 'okular --unique'
+ }
+ closecalls= {
+ ['default'] = "pdfclose --file",
+ ['okular'] = false,
+ }
+ allcalls = {
+ ['default'] = "pdfclose --all",
+ ['okular'] = false,
+ }
+
+ pdfview.method = "okular"
+
+ runner = function(...)
+ os.spawn(...)
+ end
+
+end
directives.register("pdfview.method", function(v)
pdfview.method = (opencalls[v] and v) or 'default'
@@ -69,7 +97,7 @@ function pdfview.open(...)
for i=1,#t do
local name = fullname(t[i])
if io.exists(name) then
- os.execute(format('%s "%s" 2>&1', opencall, name))
+ runner(format('%s "%s"', opencall, name))
openedfiles[name] = true
end
end
@@ -83,7 +111,7 @@ function pdfview.close(...)
for i=1,#t do
local name = fullname(t[i])
if openedfiles[name] then
- os.execute(format('%s "%s" 2>&1', closecall, name))
+ runner(format('%s "%s"', closecall, name))
openedfiles[name] = nil
else
pdfview.closeall()
@@ -96,7 +124,7 @@ end
function pdfview.closeall()
local allcall = allcalls[pdfview.method]
if allcall then
- os.execute(format('%s 2>&1', allcall))
+ runner(format('%s', allcall))
end
openedfiles = { }
end
diff --git a/Master/texmf-dist/tex/context/base/l-table.lua b/Master/texmf-dist/tex/context/base/l-table.lua
index 8fdb36a7f71..337ce054a02 100644
--- a/Master/texmf-dist/tex/context/base/l-table.lua
+++ b/Master/texmf-dist/tex/context/base/l-table.lua
@@ -10,11 +10,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -357,6 +358,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -551,19 +554,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- -- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
- handle(format("%s [%q]=loadstring(%q),",depth,k,debug.getinfo(v).what == "C" and "C code" or dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -925,3 +929,35 @@ end
function table.has_one_entry(t)
return t and not next(t,next(t))
end
+
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
diff --git a/Master/texmf-dist/tex/context/base/l-unicode.lua b/Master/texmf-dist/tex/context/base/l-unicode.lua
index 2fa50282fe0..246171aecc6 100644
--- a/Master/texmf-dist/tex/context/base/l-unicode.lua
+++ b/Master/texmf-dist/tex/context/base/l-unicode.lua
@@ -218,7 +218,7 @@ local function utf16_to_utf8_be(t)
if right then
local now = 256*left + right
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -246,7 +246,7 @@ local function utf16_to_utf8_le(t)
if right then
local now = 256*right + left
if more > 0 then
- now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000
+ now = (more-0xD800)*0x400 + (now-0xDC00) + 0x10000 -- the 0x10000 smells wrong
more = 0
r = r + 1
result[r] = utfchar(now)
@@ -263,14 +263,14 @@ local function utf16_to_utf8_le(t)
return t
end
-local function utf32_to_utf8_be(str)
+local function utf32_to_utf8_be(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*256*256*a + 256*256*b
@@ -285,17 +285,17 @@ local function utf32_to_utf8_be(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
-local function utf32_to_utf8_le(str)
+local function utf32_to_utf8_le(t)
if type(t) == "string" then
- t = utfsplitlines(str)
+ t = utfsplitlines(t)
end
local result = { } -- we reuse result
for i=1,#t do
local r, more = 0, -1
- for a,b in bytepairs(str) do
+ for a,b in bytepairs(t[i]) do
if a and b then
if more < 0 then
more = 256*b + a
@@ -310,7 +310,7 @@ local function utf32_to_utf8_le(str)
end
t[i] = concat(result,"",1,r)
end
- return result
+ return t
end
unicode.utf32_to_utf8_be = utf32_to_utf8_be
@@ -380,12 +380,30 @@ end
--~ print(unicode.utfcodes(str))
local lpegmatch = lpeg.match
-local utftype = lpeg.patterns.utftype
+local patterns = lpeg.patterns
+local utftype = patterns.utftype
function unicode.filetype(data)
return data and lpegmatch(utftype,data) or "unknown"
end
+local toentities = lpeg.Cs (
+ (
+ patterns.utf8one
+ + (
+ patterns.utf8two
+ + patterns.utf8three
+ + patterns.utf8four
+ ) / function(s) local b = utfbyte(s) if b < 127 then return s else return format("&#%X;",b) end end
+ )^0
+)
+
+patterns.toentities = toentities
+
+function utf.toentities(str)
+ return lpegmatch(toentities,str)
+end
+
--~ local utfchr = { } -- 60K -> 2.638 M extra mem but currently not called that often (on latin)
--~
--~ setmetatable(utfchr, { __index = function(t,k) local v = utfchar(k) t[k] = v return v end } )
@@ -408,3 +426,40 @@ end
--~ end
--~ end
--~ print(os.clock()-t,collectgarbage("count")*1024-u)
+
+--~ local byte = string.byte
+--~ local utfchar = utf.char
+--~ local lpegmatch = lpeg.match, lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local P, C, R, Cs = lpeg.P, lpeg.C, lpeg.R, lpeg.Cs
+
+local one = P(1)
+local two = C(1) * C(1)
+local four = C(R(utfchar(0xD8),utfchar(0xFF))) * C(1) * C(1) * C(1)
+
+local pattern = P("\254\255") * Cs( (
+ four / function(a,b,c,d)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(a,b)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+ + P("\255\254") * Cs( (
+ four / function(b,a,d,c)
+ local ab = 0xFF * byte(a) + byte(b)
+ local cd = 0xFF * byte(c) + byte(d)
+ return utfchar((ab-0xD800)*0x400 + (cd-0xDC00) + 0x10000)
+ end
+ + two / function(b,a)
+ return utfchar(byte(a)*256 + byte(b))
+ end
+ + one
+ )^1 )
+
+function string.toutf(s)
+ return lpegmatch(pattern,s) or s -- todo: utf32
+end
diff --git a/Master/texmf-dist/tex/context/base/l-url.lua b/Master/texmf-dist/tex/context/base/l-url.lua
index ffd0ac5b54e..69f32cc3958 100644
--- a/Master/texmf-dist/tex/context/base/l-url.lua
+++ b/Master/texmf-dist/tex/context/base/l-url.lua
@@ -45,12 +45,19 @@ local nothing = Cc("")
local escaped = (plus / " ") + (percent * C(hexdigit * hexdigit) / tochar)
-- we assume schemes with more than 1 character (in order to avoid problems with windows disks)
+-- we also assume that when we have a scheme, we also have an authority
-local scheme = Cs((escaped+(1-colon-slash-qmark-hash))^2) * colon * slash * slash + nothing
-local authority = Cs((escaped+(1- slash-qmark-hash))^0) + nothing
-local path = slash * Cs((escaped+(1- qmark-hash))^0) + nothing
-local query = qmark * Cs((escaped+(1- hash))^0) + nothing
-local fragment = hash * Cs((escaped+(1- endofstring))^0) + nothing
+local schemestr = Cs((escaped+(1-colon-slash-qmark-hash))^2)
+local authoritystr = Cs((escaped+(1- slash-qmark-hash))^0)
+local pathstr = Cs((escaped+(1- qmark-hash))^0)
+local querystr = Cs((escaped+(1- hash))^0)
+local fragmentstr = Cs((escaped+(1- endofstring))^0)
+
+local scheme = schemestr * colon + nothing
+local authority = slash * slash * authoritystr + nothing
+local path = slash * pathstr + nothing
+local query = qmark * querystr + nothing
+local fragment = hash * fragmentstr + nothing
local validurl = scheme * authority * path * query * fragment
local parser = Ct(validurl)
@@ -71,11 +78,16 @@ local function split(str)
return (type(str) == "string" and lpegmatch(parser,str)) or str
end
+local isscheme = schemestr * colon * slash * slash -- this test also assumes authority
+
local function hasscheme(str)
- local scheme = lpegmatch(scheme,str) -- at least one character
- return scheme and scheme ~= ""
+ local scheme = lpegmatch(isscheme,str) -- at least one character
+ return scheme ~= "" and scheme or false
end
+--~ print(hasscheme("home:"))
+--~ print(hasscheme("home://"))
+
-- todo: cache them
local rootletter = R("az","AZ")
diff --git a/Master/texmf-dist/tex/context/base/l-utils.lua b/Master/texmf-dist/tex/context/base/l-utils.lua
deleted file mode 100644
index 30df04694c5..00000000000
--- a/Master/texmf-dist/tex/context/base/l-utils.lua
+++ /dev/null
@@ -1,12 +0,0 @@
-if not modules then modules = { } end modules ['l-utils'] = {
- version = 1.001,
- comment = "this module is replaced by the util-* ones",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-utils = utils or { }
-
-require("util-mrg") for k, v in next, utilities.merger do utils[k] = v end
-require("util-lua") for k, v in next, utilities.lua do utils[k] = v end
diff --git a/Master/texmf-dist/tex/context/base/lang-alt.mkii b/Master/texmf-dist/tex/context/base/lang-alt.mkii
index f65acbda3ba..1e49945d5fd 100644
--- a/Master/texmf-dist/tex/context/base/lang-alt.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-alt.mkii
@@ -5,7 +5,7 @@
%D subtitle=Altaic Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-ana.mkii b/Master/texmf-dist/tex/context/base/lang-ana.mkii
index c108655c474..f2dc4a17c00 100644
--- a/Master/texmf-dist/tex/context/base/lang-ana.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-ana.mkii
@@ -5,7 +5,7 @@
%D subtitle=Anatolian Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-art.mkii b/Master/texmf-dist/tex/context/base/lang-art.mkii
index e8be91630a6..20216b571bf 100644
--- a/Master/texmf-dist/tex/context/base/lang-art.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-art.mkii
@@ -5,7 +5,7 @@
%D subtitle=Artificial Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-bal.mkii b/Master/texmf-dist/tex/context/base/lang-bal.mkii
index 394e9d93c1f..4ab751a448d 100644
--- a/Master/texmf-dist/tex/context/base/lang-bal.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-bal.mkii
@@ -5,7 +5,7 @@
%D subtitle=Baltic Languages,
%D author=Marius AlekneviÄius,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-cel.mkii b/Master/texmf-dist/tex/context/base/lang-cel.mkii
index 4d93957f102..e6519497b3d 100644
--- a/Master/texmf-dist/tex/context/base/lang-cel.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-cel.mkii
@@ -5,7 +5,7 @@
%D subtitle=Celtic Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-chi.mkii b/Master/texmf-dist/tex/context/base/lang-chi.mkii
index 278e107456a..5d61281b0a2 100644
--- a/Master/texmf-dist/tex/context/base/lang-chi.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-chi.mkii
@@ -5,7 +5,7 @@
%D subtitle=Chinese,
%D author={Hans Hagen \& Wang Lei},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-ctx.mkii b/Master/texmf-dist/tex/context/base/lang-ctx.mkii
index 09f28dda1e3..2aecb918ee2 100644
--- a/Master/texmf-dist/tex/context/base/lang-ctx.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-ctx.mkii
@@ -5,7 +5,7 @@
%D subtitle=Generic Patterns,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-cyr.mkii b/Master/texmf-dist/tex/context/base/lang-cyr.mkii
index 470402bb10e..eed3ec80e68 100644
--- a/Master/texmf-dist/tex/context/base/lang-cyr.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-cyr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Cyrillic Languages,
%D author=see below,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-def.lua b/Master/texmf-dist/tex/context/base/lang-def.lua
index 78c8eecbdd9..80ff13beb6b 100644
--- a/Master/texmf-dist/tex/context/base/lang-def.lua
+++ b/Master/texmf-dist/tex/context/base/lang-def.lua
@@ -65,6 +65,15 @@ local setmetatableindex = table.setmetatableindex
local specifications = allocate {
{
+ ["description"] = "Dutch",
+ ["script"] = "latn",
+ -- ["bibliographical"] = "nld",
+ -- ["terminological"] = "nld",
+ ["context"] = "nl",
+ ["opentype"] = "nld",
+ ["variant"] = "nl",
+ },
+ {
["description"] = "Basque",
["script"] = "latn",
["bibliographical"] = "baq",
diff --git a/Master/texmf-dist/tex/context/base/lang-def.mkiv b/Master/texmf-dist/tex/context/base/lang-def.mkiv
index 359006fefb4..e838f60e1e9 100644
--- a/Master/texmf-dist/tex/context/base/lang-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/lang-def.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Languages Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -106,33 +106,33 @@
\installlanguage
[\s!nb]
- [spacing=packed,
- lefthyphenmin=2,
- righthyphenmin=2,
- leftsentence=\emdash,
- rightsentence=\emdash,
- leftsubsentence=\emdash,
- rightsubsentence=\emdash,
- leftquote=\upperleftsinglesixquote,
- rightquote=\upperrightsingleninequote,
- leftquotation=\leftguillemot,
- rightquotation=\rightguillemot,
- date={day,{.},\space,month,\space,year}]
+ [\c!spacing=\v!packed,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day,{.},\space,\v!month,\space,\v!year}]
\installlanguage
[\s!nn]
- [spacing=packed,
- lefthyphenmin=2,
- righthyphenmin=2,
- leftsentence=\emdash,
- rightsentence=\emdash,
- leftsubsentence=\emdash,
- rightsubsentence=\emdash,
- leftquote=\upperleftsinglesixquote,
- rightquote=\upperrightsingleninequote,
- leftquotation=\leftguillemot,
- rightquotation=\rightguillemot,
- date={day,{.},\space,month,\space,year}]
+ [\c!spacing=\v!packed,
+ \s!lefthyphenmin=2,
+ \s!righthyphenmin=2,
+ \c!leftsentence=\emdash,
+ \c!rightsentence=\emdash,
+ \c!leftsubsentence=\emdash,
+ \c!rightsubsentence=\emdash,
+ \c!leftquote=\upperleftsinglesixquote,
+ \c!rightquote=\upperrightsingleninequote,
+ \c!leftquotation=\leftguillemot,
+ \c!rightquotation=\rightguillemot,
+ \c!date={\v!day,{.},\space,\v!month,\space,\v!year}]
\installlanguage [\s!no] [\s!nb]
@@ -260,15 +260,13 @@
\c!rightquotation=\leftguillemot,
\c!date={\v!day,{.},\space,\v!month,\space,\v!year}]
-\installlanguage [polish] [\s!pl]
-\installlanguage [czech] [\s!cs]
-\installlanguage [slovak] [\s!sk]
-\installlanguage [croatian] [\s!hr]
-\installlanguage [slovenian] [\s!sl]
+\installlanguage [\s!polish] [\s!pl]
+\installlanguage [\s!czech] [\s!cs]
+\installlanguage [\s!slovak] [\s!sk]
+\installlanguage [\s!croatian] [\s!hr]
+\installlanguage [\s!slovenian] [\s!sl]
\installlanguage [slovene] [\s!sl] % both possible (mojca: still needed?)
-\installlanguage [cz] [\s!cs]
-
\def\doconvertsloveniancharacters{\dodoconvertcharacters{25}}
\def\sloveniancharacters{\doconvertsloveniancharacters\sloveniancharacter}
@@ -286,16 +284,16 @@
%D language is Slovenian. If you feel uncomfortable with this,
%D mail Mojca, since she promised to to take the heat.
-\defineconversion [sl] [character] [\sloveniancharacter]
-\defineconversion [sl] [Character] [\slovenianCharacter]
+\defineconversion [\s!sl] [character] [\sloveniancharacter]
+\defineconversion [\s!sl] [Character] [\slovenianCharacter]
-\defineconversion [sl] [characters] [\sloveniancharacters]
-\defineconversion [sl] [Characters] [\slovenianCharacters]
+\defineconversion [\s!sl] [characters] [\sloveniancharacters]
+\defineconversion [\s!sl] [Characters] [\slovenianCharacters]
-\defineconversion [sl] [a] [\sloveniancharacters]
-\defineconversion [sl] [A] [\slovenianCharacters]
-\defineconversion [sl] [AK] [\smallcapped\sloveniancharacters]
-\defineconversion [sl] [KA] [\smallcapped\sloveniancharacters]
+\defineconversion [\s!sl] [a] [\sloveniancharacters]
+\defineconversion [\s!sl] [A] [\slovenianCharacters]
+\defineconversion [\s!sl] [AK] [\smallcapped\sloveniancharacters]
+\defineconversion [\s!sl] [KA] [\smallcapped\sloveniancharacters]
\def\sloveniancharacters#1{\ctxcommand{alphabetic(\number#1,"sl")}}
\def\slovenianCharacters#1{\ctxcommand{Alphabetic(\number#1,"sl")}}
@@ -333,8 +331,8 @@
\c!date={\v!day,\space,\v!month,\space,\v!year},
\s!patterns=\s!uk]
-\installlanguage [russian] [\s!ru]
-\installlanguage [ukrainian] [\s!ua]
+\installlanguage [\s!russian] [\s!ru]
+\installlanguage [\s!ukrainian] [\s!ua]
% Uralic Languages: Cheremiss, Estonian, Finnish, Karelian, Laap,
% Mordvinian, Permian tongues, Hungarian, Ostyak, Vogul, Samoyed
@@ -365,8 +363,8 @@
\c!rightquotation=\upperrightdoubleninequote,
\c!date={\v!year,.,\space,\v!month,\space,\v!day,.}]
-\installlanguage [finish] [\s!fi]
-\installlanguage [hungarian] [\s!hu]
+\installlanguage [\s!finish] [\s!fi]
+\installlanguage [\s!hungarian] [\s!hu]
% Altaic Languages: Uigur, Uzbek, Azeri/Azerbaijani, Chuvash,
% Turkish, Turkmen, Kazakh, Kazar, Kireghiz, Noghay, Talar,
@@ -401,16 +399,13 @@
\s!lefthyphenmin=1,
\s!righthyphenmin=2]
-\installlanguage [turkish] [\s!tr]
-\installlanguage [turkmen] [\s!tk]
+\installlanguage [\s!turkish] [\s!tr]
+\installlanguage [\s!turkmen] [\s!tk]
% Anatolian Languages
% Arabic Languages
-\definesystemconstant {arabic}
-\definesystemvariable {ar}
-
\installlanguage
[\s!ar]
[\c!spacing=\v!broad,
@@ -473,16 +468,10 @@
\s!lefthyphenmin=2,
\s!righthyphenmin=2]
-\installlanguage [lithuanian] [\s!lt]
+\installlanguage [\s!lithuanian] [\s!lt]
% Celtic: Breton, Welsh, Irish, Manx, Scottish Gaelic
-% CJK
-
-\definesystemconstant {chinese} \definesystemconstant {cn}
-\definesystemconstant {japanese} \definesystemconstant {ja}
-\definesystemconstant {korean} \definesystemconstant {kr}
-
\installlanguage
[\s!cn]
[\c!leftsentence=——,
@@ -535,7 +524,7 @@
\c!date={\v!day\space\v!month\space\v!year},
\s!patterns=\s!agr] % ok?
-\installlanguage [greek] [\s!gr]
+\installlanguage [\s!greek] [\s!gr]
\installlanguage
[\s!agr]
@@ -545,8 +534,7 @@
\c!leftquotation=\upperleftdoublesixquote,
\c!rightquotation=\upperrightdoubleninequote]
-\installlanguage [ancientgreek] [\s!agr]
-\installlanguage [grk] [\s!agr]
+\installlanguage [\s!ancientgreek] [\s!agr]
% Indo-Iranian Languages: 34.
@@ -554,8 +542,8 @@
% Sardian, Catalan, French, Ladino, Portuguese, Proven\c{c}al,
% Spanish
-\ifx\guillemotspace\undefined \let\guillemotspace\empty \fi
-\ifx\sentencespace \undefined \let\sentencespace \empty \fi
+\ifdefined\guillemotspace \else \let\guillemotspace\empty \fi
+\ifdefined\sentencespace \else \let\sentencespace \empty \fi
\installlanguage
[\s!fr]
@@ -568,7 +556,7 @@
\c!rightquote=\rightguillemot,
\c!leftquotation=\leftguillemot,
\c!rightquotation=\rightguillemot,
- \c!date={\v!day+,\v!space,\v!month,\v!space,\v!year}]
+ \c!date={\v!day:mnem,\v!space,\v!month,\v!space,\v!year}]
\installlanguage
[\s!es]
@@ -581,7 +569,7 @@
\c!rightquote=\upperrightsingleninequote,
\c!leftquotation=\upperleftdoublesixquote,
\c!rightquotation=\upperrightdoubleninequote,
- \c!date={\v!day,\space,\v!month,\space,\v!year}]
+ \c!date={\v!day,{ de },\v!month,{ de },\v!year}]
\installlanguage [sp] [\s!es] % old times context
@@ -657,17 +645,15 @@
%D For compatibility reasons we also define:
-\installlanguage [fa] [\s!fr] % for dutchies only
-
-\installlanguage [french] [\s!fr]
-\installlanguage [spanish] [\s!es]
-\installlanguage [catalan] [\s!ca]
-\installlanguage [italian] [\s!it]
-\installlanguage [latin] [\s!la]
-\installlanguage [portuguese] [\s!pt]
-\installlanguage [romanian] [\s!ro]
+\installlanguage [\s!french] [\s!fr]
+\installlanguage [\s!spanish] [\s!es]
+\installlanguage [\s!catalan] [\s!ca]
+\installlanguage [\s!italian] [\s!it]
+\installlanguage [\s!latin] [\s!la]
+\installlanguage [\s!portuguese] [\s!pt]
+\installlanguage [\s!romanian] [\s!ro]
-\defineconversion [\s!fr] [\v!day+] [\frordinaldaynumber]
+\defineconversion [\s!fr] [\v!day:mnem] [\frordinaldaynumber]
% Vietnamese Language
@@ -684,6 +670,19 @@
\c!rightquotation=\quotedblright,
\c!date={{ },dd,{/},mm,{/},yy}]
-\installlanguage [vietnamese] [\s!vi]
+\installlanguage [\s!vietnamese] [\s!vi]
+
+%D Todo: generate this one from languages.data
+
+\installlanguage[nld][\s!nl]
+\installlanguage[deu][\s!de]
+\installlanguage[eng][\s!en]
+\installlanguage[fra][\s!fr]
+%installlanguage[grk][\s!agr]
+
+%D This might go:
+
+\installlanguage[cz][\s!cs]
+%installlanguage[fa][\s!fr] % for dutchies only
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/lang-dis.mkii b/Master/texmf-dist/tex/context/base/lang-dis.mkii
index f081bf4a9b2..213c5110f57 100644
--- a/Master/texmf-dist/tex/context/base/lang-dis.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-dis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Distribution Patterns,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-frd.mkii b/Master/texmf-dist/tex/context/base/lang-frd.mkii
index 6cc27080b78..be4e07b75df 100644
--- a/Master/texmf-dist/tex/context/base/lang-frd.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-frd.mkii
@@ -5,7 +5,7 @@
%D subtitle=Language Frequency Table Data,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-frq.mkii b/Master/texmf-dist/tex/context/base/lang-frq.mkii
index 773230e6c86..afeb5329c64 100644
--- a/Master/texmf-dist/tex/context/base/lang-frq.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-frq.mkii
@@ -5,7 +5,7 @@
%D subtitle=Frequency Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-ger.mkii b/Master/texmf-dist/tex/context/base/lang-ger.mkii
index 04551a891df..d33620cc7bc 100644
--- a/Master/texmf-dist/tex/context/base/lang-ger.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-ger.mkii
@@ -5,7 +5,7 @@
%D subtitle=Germanic Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-grk.mkii b/Master/texmf-dist/tex/context/base/lang-grk.mkii
index 862f3c5f41e..9fd59382a0c 100644
--- a/Master/texmf-dist/tex/context/base/lang-grk.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-grk.mkii
@@ -5,7 +5,7 @@
%D subtitle=Uralic Languages,
%D author=Apostolos Syropoulos
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-ind.mkii b/Master/texmf-dist/tex/context/base/lang-ind.mkii
index 9b6e5ff1dbe..bb33dacfd24 100644
--- a/Master/texmf-dist/tex/context/base/lang-ind.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-ind.mkii
@@ -5,7 +5,7 @@
%D subtitle=Indo Iranian Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-ini.lua b/Master/texmf-dist/tex/context/base/lang-ini.lua
index 525e0f17a12..97528097f15 100644
--- a/Master/texmf-dist/tex/context/base/lang-ini.lua
+++ b/Master/texmf-dist/tex/context/base/lang-ini.lua
@@ -20,9 +20,8 @@ local type, tonumber = type, tonumber
local utf = unicode.utf8
local utfbyte = utf.byte
local format, gsub = string.format, string.gsub
-local concat = table.concat
+local concat, sortedkeys, sortedpairs = table.concat, table.sortedkeys, table.sortedpairs
local lpegmatch = lpeg.match
-local texwrite = tex.write
local settings_to_array = utilities.parsers.settings_to_array
@@ -170,7 +169,7 @@ function languages.synonym(synonym,tag) -- convenience function
end
function languages.installed(separator)
- context(concat(table.sortedkeys(registered),separator or ","))
+ context(concat(sortedkeys(registered),separator or ","))
end
function languages.current(n)
@@ -219,7 +218,7 @@ if environment.initex then
end
function commands.languagenumber()
- texwrite(0)
+ context(0)
end
else
@@ -268,7 +267,7 @@ else
languages.getnumber = getnumber
function commands.languagenumber(tag,default,patterns)
- texwrite(getnumber(tag,default,patterns))
+ context(getnumber(tag,default,patterns))
end
end
@@ -320,10 +319,7 @@ languages.logger = languages.logger or { }
function languages.logger.report()
local result, r = { }, 0
- local sorted = table.sortedkeys(registered)
- for i=1,#sorted do
- local tag = sorted[i]
- local l = registered[tag]
+ 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)
diff --git a/Master/texmf-dist/tex/context/base/lang-ini.mkii b/Master/texmf-dist/tex/context/base/lang-ini.mkii
index 50a3689cfb3..6ad6f02e3ad 100644
--- a/Master/texmf-dist/tex/context/base/lang-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-ini.mkiv b/Master/texmf-dist/tex/context/base/lang-ini.mkiv
index 5dccab4dc82..150b68f702f 100644
--- a/Master/texmf-dist/tex/context/base/lang-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/lang-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,7 +13,7 @@
%D This module needs a further cleanup (real split between ii/iv).
-% \ctxlua{tex.sprint(languages.numbers[tex.count.mainlanguagenumber])}
+% \cldcontext{languages.numbers[tex.count.mainlanguagenumber]}
%D This module implements the (for the moment still simple)
%D multi||language support of \CONTEXT, which should not be
@@ -39,8 +39,8 @@
% \testlanguage[de] \testlanguage[de-de] \testlanguage[de-at] \testlanguage[de-ch] \page
% \testlanguage[en] \testlanguage[us] \testlanguage[en-us] \testlanguage[uk] \testlanguage[en-gb] \page
-\ifx\nonfrenchspacing\undefined \let\nonfrenchspacing\relax \fi
-\ifx\frenchspacing \undefined \let\frenchspacing \relax \fi
+\ifdefined\nonfrenchspacing\else \let\nonfrenchspacing\relax \fi
+\ifdefined\frenchspacing \else \let\frenchspacing \relax \fi
%D When loading hyphenation patterns, \TEX\ assign a number to
%D each loaded table, starting with~0. Switching to a specific
@@ -79,34 +79,42 @@
%D \macros
%D {defaultlanguage,languageparameter,specificlanguageparameter}
+%D We don't use the commandhandler here (yet) because we have
+%D a rather special fallback mechanism so quite some compatibility
+%D testing is needed.
+
+\installcorenamespace{language}
+\installcorenamespace{languagelinked}
+
\def\defaultlanguage#1%
- {\ifcsname\??la#1\s!default\endcsname
- \expandafter\defaultlanguage\csname\??la#1\s!default\endcsname
+ {\ifcsname\??language#1\s!default\endcsname
+ \expandafter\defaultlanguage\csname\??language#1\s!default\endcsname
\else
#1%
\fi}
\def\languageparameter#1%
- {\ifcsname\??la\currentlanguage#1\endcsname
- \csname\??la\currentlanguage#1\endcsname
- \else\ifcsname\??la\currentlanguage\s!default\endcsname
- \expandafter\specificlanguageparameter\csname\??la\currentlanguage\s!default\endcsname{#1}%
- \else\ifcsname\??la\s!default#1\endcsname
- \csname\??la\s!default#1\endcsname
+ {\ifcsname\??language\currentlanguage#1\endcsname
+ \csname\??language\currentlanguage#1\endcsname
+ \else\ifcsname\??language\currentlanguage\s!default\endcsname
+ \expandafter\specificlanguageparameter\csname\??language\currentlanguage\s!default\endcsname{#1}%
+ \else\ifcsname\??language\s!default#1\endcsname
+ \csname\??language\s!default#1\endcsname
\fi\fi\fi}
\def\specificlanguageparameter#1#2%
- {\ifcsname\??la#1#2\endcsname
- \csname\??la#1#2\endcsname
- \else\ifcsname\??la#1\s!default\endcsname
- \expandafter\specificlanguageparameter\csname\??la#1\s!default\endcsname{#2}%
- \else\ifcsname\??la\s!default#2\endcsname
- \csname\??la\s!default#2\endcsname
+ {\ifcsname\??language#1#2\endcsname
+ \csname\??language#1#2\endcsname
+ \else\ifcsname\??language#1\s!default\endcsname
+ \expandafter\specificlanguageparameter\csname\??language#1\s!default\endcsname{#2}%
+ \else\ifcsname\??language\s!default#2\endcsname
+ \csname\??language\s!default#2\endcsname
\fi\fi\fi}
-\unexpanded\def\setupcurrentlanguage[#1]{\setcurrentlanguage\currentmainlanguage{#1}}
+\unexpanded\def\setupcurrentlanguage[#1]%
+ {\setcurrentlanguage\currentmainlanguage{#1}}
-\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
+\unexpanded\def\setcurrentlanguage#1#2% sets modes: **id (currentmain) *id (current)
{\edef\xaskedlanguage{#1}% otherwise clash with \askedlanguage
\ifx\xaskedlanguage\empty \else
\ifx\currentmainlanguage\empty\else\resetsystemmode{\systemmodeprefix\currentmainlanguage}\fi
@@ -154,10 +162,6 @@
%D implementations support run time addition of patterns to a
%D preloaded format).
-% move to lua end
-
-\def\dodoinstalllanguage#1#2%
- {\ifcsname#1\endcsname\else\setuvalue{#1}{\complexlanguage[#2]}\fi}
%D \macros
%D {preloadlanguages}
@@ -172,43 +176,50 @@
\def\installedlanguages{\ctxlua{languages.installed()}}
-\def\doiflanguageelse#1{\doifdefinedelse{\??la#1\c!state}}
+\unexpanded\def\doiflanguageelse#1%
+ {\ifcsname\??language#1\c!state\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\def\reallanguagetag#1%
+ {\ifcsname\??languagelinked#1\endcsname\csname\??languagelinked#1\endcsname\else#1\fi}
-\def\doinstalllanguage[#1][#2]%
+% \language[#1] gave unwanted side effect of loading language specifics
+
+\unexpanded\def\installlanguage
+ {\dodoubleargument\lang_basics_install}
+
+\def\lang_basics_install[#1][#2]%
{\doifassignmentelse{#2}
{\doiflanguageelse{#1}
- {\getparameters[\??la#1][#2]}
- {\setvalue{\l!prefix!#1}{#1}%
- \dodoinstalllanguage{#1}{#1}%
- \getparameters[\??la#1][\c!state=\v!start,#2]}%
+ {\getparameters[\??language#1][#2]}
+ {\setvalue{\??languagelinked#1}{#1}%
+ \lang_basics_install_indeed{#1}{#1}%
+ \getparameters[\??language#1][\c!state=\v!start,#2]}%
\edef\currentsetuplanguage{#1}%
\ctxlua{languages.define("#1","\specificlanguageparameter{#1}\s!default")}%
\the\everysetuplanguage}
- {\setvalue{\l!prefix!#1}{#2}%
+ {\setvalue{\??languagelinked#1}{#2}%
\ctxlua{languages.synonym("#1","#2")}%
- %\getparameters[\??la#1][\s!default=#2]%
- \dodoinstalllanguage{#1}{#2}}}
+ \lang_basics_install_indeed{#1}{#2}}}
-\def\reallanguagetag#1%
- {\ifcsname\l!prefix!#1\endcsname\csname\l!prefix!#1\endcsname\else#1\fi}
-
-% \language[#1] gave unwanted side effect of loading language specifics
-
-\def\installlanguage
- {\dodoubleargument\doinstalllanguage}
+\def\lang_basics_install_indeed#1#2%
+ {\ifcsname#1\endcsname\else\setuvalue{#1}{\lang_basics_set_current[#2]}\fi}
%D When the second argument is a language identifier, a
%D synonym is created. This feature is present because we
%D used dutch mnemonics in the dutch version, but nowadays
%D conform a standard.
-\def\doifpatternselse#1%
- {\bgroup % will change
+\unexpanded\def\doifpatternselse#1%
+ {\begingroup % will change
\language[#1]%
\ifnum\normallanguage>\zerocount
- \bgroup\expandafter\firstoftwoarguments
+ \endgroup\expandafter\firstoftwoarguments
\else
- \bgroup\expandafter\secondoftwoarguments
+ \endgroup\expandafter\secondoftwoarguments
\fi}
%D \macros
@@ -221,25 +232,26 @@
%D Beware, this command can only be used when a language is installed.
\unexpanded\def\setuplanguage
- {\dodoubleempty\dosetuplanguage}
+ {\dodoubleempty\lang_basics_setup}
-\ifdefined\docomplexlanguage \else \let\docomplexlanguage\relax \fi
+\ifdefined\lang_basics_synchronize \else
+ \let\lang_basics_synchronize\relax % be nice for setups till we have one
+\fi
-\def\dosetuplanguage[#1][#2]%
+\def\lang_basics_setup[#1][#2]%
{\ifsecondargument
\pushmacro\currentlanguage % can be default
\edef\currentsetuplanguage{\reallanguagetag{#1}}%
- \getparameters[\??la\currentsetuplanguage][#2]%
+ \getparameters[\??language\currentsetuplanguage][#2]%
\the\everysetuplanguage
\popmacro\currentlanguage
%\doif\currentsetuplanguage\currentlanguage we can have influenced inheritance (default)
- \docomplexlanguage
\else
\let\currentsetuplanguage\currentlanguage
- \getparameters[\??la\currentsetuplanguage][#1]%
+ \getparameters[\??language\currentsetuplanguage][#1]%
\the\everysetuplanguage
- \docomplexlanguage
- \fi}
+ \fi
+ \lang_basics_synchronize}
\appendtoks
\ctxlua{languages.setdirty("\currentsetuplanguage")}%
@@ -257,6 +269,9 @@
\c!righthyphen=-,
\c!hyphen=-,
\c!spacing=\v!packed,
+ \c!compoundhyphen=\compoundhyphen,
+ \c!rightcompoundhyphen=\compoundhyphen,
+ \c!leftcompoundhyphen=,
\c!midsentence=---,
\c!leftsentence=---,
\c!rightsentence=---,
@@ -273,14 +288,6 @@
\c!date={\v!year,\ ,\v!month,\ ,\v!day},
\c!text=Ag]
-% rather new, split and per language
-
-\setuplanguage
- [\s!default]
- [\c!compoundhyphen=\compoundhyphen,
- \c!rightcompoundhyphen=\compoundhyphen,
- \c!leftcompoundhyphen=]
-
% to be tested:
%
% \setuplanguage
@@ -346,8 +353,8 @@
\newtoks \everylanguage
-\def\docomplexlanguage% assumes that \currentlanguage is set % % % use different name as complex
- {\normallanguage\ctxlua{commands.languagenumber(%
+\def\lang_basics_synchronize% assumes that \currentlanguage is set % % % use different name as complex
+ {\normallanguage\ctxcommand{languagenumber(%
"\currentlanguage",%
"\defaultlanguage\currentlanguage",%
"\languageparameter\s!patterns"%
@@ -363,6 +370,19 @@
\posthyphenchar\languageparameter\s!lefthyphenchar \relax
\to \everylanguage
+% \appendtoks
+% \setups[\languageparameter\c!setups]%
+% \to \everylanguage
+
+%D You can setup the 'default' language to reset settings.
+
+\appendtoks
+ \edef\currentlanguagesetups{\languageparameter\c!setups}%
+ \ifx\currentlanguagesetups\empty \else
+ \setups[\currentlanguagesetups]%
+ \fi
+\to \everylanguage
+
% this will move to core-spa !
\appendtoks
@@ -377,40 +397,40 @@
% The following may be a solution for the fact that one cannot
% change catcodes of characters like : and ; inside an environment.
-\def\complexlanguage[#1]%
+% we will also permit access by the other names
+
+\unexpanded\def\lang_basics_set_current[#1]%
{\edef\askedlanguage{#1}%
\ifx\askedlanguage\empty \else
- \ifcsname\l!prefix!\askedlanguage\endcsname
- \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
+ \ifcsname\??languagelinked\askedlanguage\endcsname
+ \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
\ifx\currentlanguage\askedlanguage \else
\setcurrentlanguage\currentmainlanguage\askedlanguage
- \docomplexlanguage
+ \lang_basics_synchronize
\fi
\else
\showmessage\m!languages6{#1}%
\fi
\fi}
-\let\simplelanguage\normallanguage
-
-\definecomplexorsimple\language
+\unexpanded\def\language
+ {\doifnextoptionalelse\lang_basics_set_current\normallanguage}
\newcount\mainlanguagenumber
-\def\mainlanguage[#1]%
+\unexpanded\def\mainlanguage[#1]%
{\edef\askedlanguage{#1}%
\ifx\askedlanguage\empty \else
- \ifcsname\l!prefix!\askedlanguage\endcsname
- \edef\askedlanguage{\csname\l!prefix!\askedlanguage\endcsname}%
+ \ifcsname\??languagelinked\askedlanguage\endcsname
+ \edef\askedlanguage{\csname\??languagelinked\askedlanguage\endcsname}%
\ifx\currentlanguage\askedlanguage
- \ifx\currentmainlanguage\askedlanguage
- \else
+ \ifx\currentmainlanguage\askedlanguage \else
\setcurrentlanguage\askedlanguage\askedlanguage
- \docomplexlanguage
+ \lang_basics_synchronize
\fi
\else
\setcurrentlanguage\askedlanguage\askedlanguage
- \docomplexlanguage
+ \lang_basics_synchronize
\fi
\fi
\fi
@@ -533,17 +553,15 @@
%D \stoptable
%D \protect
-\def\nopatterns{\normallanguage\minusone}
+\unexpanded\def\nopatterns{\normallanguage\minusone}
%D We default to the language belonging to the interface. This
%D is one of the few places outside the interface modules where
%D \type{\startinterface} is used.
-%D We default to english:
-
\setupcurrentlanguage[\s!en]
-\def\initializemainlanguage
+\unexpanded\def\initializemainlanguage
{\mainlanguage[\currentlanguage]%
\showmessage\m!languages9\currentlanguage}
@@ -554,7 +572,7 @@
\unexpanded\def\startexceptions
{\dosingleempty\dostartexceptions}
-\long\def\dostartexceptions[#1]#2\stopexceptions % multilingual or not?
+\def\dostartexceptions[#1]#2\stopexceptions % multilingual or not?
{\begingroup
\edef\askedlanguage{\reallanguagetag{#1}}%
\ifx\askedlanguage\empty
@@ -565,7 +583,7 @@
%D For the moment here:
-\uchyph = 1 % also treat uppercase
-\exhyphenchar=45 % to permit breaking at explicit hyphens
+\uchyph 1 % also treat uppercase
+\exhyphenchar 45 % to permit breaking at explicit hyphens
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/lang-ita.mkii b/Master/texmf-dist/tex/context/base/lang-ita.mkii
index 03efb0614fe..04acf3265c2 100644
--- a/Master/texmf-dist/tex/context/base/lang-ita.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-ita.mkii
@@ -5,7 +5,7 @@
%D subtitle=Italic Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-jap.mkii b/Master/texmf-dist/tex/context/base/lang-jap.mkii
index 05c9b1d411c..1417e8ec58c 100644
--- a/Master/texmf-dist/tex/context/base/lang-jap.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-jap.mkii
@@ -5,7 +5,7 @@
%D subtitle=Japanese,
%D author={Richard Gabriel},
%D date=\currentdate,
-%D copyright={PRAGMA / RG}]
+%D copyright={Richard Gabriel \& Hans Hagen}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
diff --git a/Master/texmf-dist/tex/context/base/lang-lab.lua b/Master/texmf-dist/tex/context/base/lang-lab.lua
index 1947616a99c..360f2aa11b5 100644
--- a/Master/texmf-dist/tex/context/base/lang-lab.lua
+++ b/Master/texmf-dist/tex/context/base/lang-lab.lua
@@ -61,56 +61,77 @@ if not modules then modules = { } end modules ['lang-lab'] = {
local format, find = string.format, string.find
local next, rawget, type = next, rawget, type
-local texsprint = tex.sprint
local prtcatcodes = tex.prtcatcodes
+local lpegmatch = lpeg.match
-languages.labels = languages.labels or { }
-
-local trace_labels = false trackers.register("languages.labels", function(v) trace_labels = v end)
+languages.labels = languages.labels or { }
+local trace_labels = false trackers.register("languages.labels", function(v) trace_labels = v end)
local report_labels = logs.reporter("languages","labels")
-function languages.labels.define()
- local variables = interfaces.variables
- local data = languages.data.labels
- local function define(command,list,prefixed)
- if list then
- for tag, data in next, list do
- if data.hidden then
- -- skip
- else
- for language, text in next, data.labels do
- if text == "" then
- -- skip
- elseif prefixed and rawget(variables,tag) then
- if type(text) == "table" then
- texsprint(prtcatcodes,format("\\%s[%s][\\v!%s={{%s},{%s}}]",command,language,tag,text[1],text[2]))
- else
- texsprint(prtcatcodes,format("\\%s[%s][\\v!%s={{%s},}]",command,language,tag,text))
- end
+local variables = interfaces.variables
+
+local splitter = lpeg.splitat(":")
+
+local function split(tag)
+ return lpegmatch(splitter,tag)
+end
+
+languages.labels.split = split
+
+local function definelanguagelabels(data,command,tag,rawtag)
+ for language, text in next, data.labels do
+ if text == "" then
+ -- skip
+ elseif type(text) == "table" then
+ context("\\%s[%s][%s={{%s},{%s}}]",command,language,tag,text[1],text[2])
+ if trace_labels then
+ report_labels("language '%s', defining label '%s' as '%s' and '%s'",language,rawtag,text[1],text[2])
+ end
+ else
+ context("\\%s[%s][%s={{%s},}]",command,language,tag,text)
+ if trace_labels then
+ report_labels("language '%s', defining label '%s' as '%s'",language,rawtag,text)
+ end
+ end
+ end
+end
+
+function languages.labels.define(command,name,prefixed)
+ local list = languages.data.labels[name]
+ if list then
+ report_labels("defining label set '%s'",name)
+ context.pushcatcodes(prtcatcodes) -- context.unprotect
+ for tag, data in next, list do
+ if data.hidden then
+ -- skip
+ elseif prefixed then
+ local first, second = lpegmatch(splitter,tag)
+ if second then
+ if rawget(variables,first) then
+ if rawget(variables,second) then
+ definelanguagelabels(data,command,format("\\v!%s:\\v!%s",first,second),tag)
else
- if type(text) == "table" then
- texsprint(prtcatcodes,format("\\%s[%s][%s={{%s},{%s}}]",command,language,tag,text[1],text[2]))
- else
- texsprint(prtcatcodes,format("\\%s[%s][%s={{%s},}]",command,language,tag,text))
- end
- end
- if trace_labels then
- if type(text) == "table" then
- report_labels("language '%s', defining label '%s' as '%s' and '%s'",language,tag,text[1],text[2])
- else
- report_labels("language '%s', defining label '%s' as '%s'",language,tag,text)
- end
+ definelanguagelabels(data,command,format("\\v!%s:%s",first,second),tag)
end
+ elseif rawget(variables,second) then
+ definelanguagelabels(data,command,format("%s:\\v!%s",first,second),tag)
+ else
+ definelanguagelabels(data,command,format("%s:%s",first,second),tag)
end
+ elseif rawget(variables,rawtag) then
+ definelanguagelabels(data,command,format("\\v!%s",tag),tag)
+ else
+ definelanguagelabels(data,command,tag,tag)
end
+ else
+ definelanguagelabels(data,command,tag,tag)
end
end
+ context.popcatcodes() -- context.protect
+ else
+ report_labels("unknown label set '%s'",name)
end
- define("setupheadtext", data.titles, true)
- define("setuplabeltext", data.texts, true)
- define("setupmathlabeltext", data.functions)
- define("setuptaglabeltext", data.tags)
end
--~ function languages.labels.check()
@@ -128,3 +149,6 @@ end
--~
--~ languages.labels.check()
+-- function commands.setstrippedtextprefix(str)
+-- context(string.strip(str))
+-- end
diff --git a/Master/texmf-dist/tex/context/base/lang-lab.mkii b/Master/texmf-dist/tex/context/base/lang-lab.mkii
index 269ac249bc0..1ff964615e0 100644
--- a/Master/texmf-dist/tex/context/base/lang-lab.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-lab.mkii
@@ -5,7 +5,7 @@
%D subtitle=Labels,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-lab.mkiv b/Master/texmf-dist/tex/context/base/lang-lab.mkiv
index 025958ade6a..a9744f69973 100644
--- a/Master/texmf-dist/tex/context/base/lang-lab.mkiv
+++ b/Master/texmf-dist/tex/context/base/lang-lab.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Labels,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -18,8 +18,9 @@
\unprotect
-%C The UPPERCASE variants are obsolete as we can now use \WORD
-%C in an non-interfering way.
+%D Left-overs:
+
+\ifdefined\sixperemspace \else \def\sixperemspace{ } \fi % \utfchar{2006"} % we could embed 0x2006 but it does not show up in a editor
%D In this module we deal with language dependant labels and
%D prefixes, like in {\em Figure~12} and {\em Chapter 1}. In
@@ -37,7 +38,6 @@
%D current implementation of labels supports two labels too.
\ifdefined\simplifiedcommands \else \newtoks\simplifiedcommands \fi
-\ifdefined\Word \else \let\Word\relax \fi
%D \macros
%D {setupheadtext, setuplabeltext}
@@ -61,12 +61,16 @@
%D
%D The last two cases concern the current language.
-\def\definelabelclass
- {\dodoubleempty\dodefinelabelclass}
+\installcorenamespace{label}
+
+\let\currentlabelcategory\empty
+
+\unexpanded\def\definelabelclass
+ {\dodoubleempty\lang_labels_define_class}
-\def\dodefinelabelclass[#1][#2]%
+\def\lang_labels_define_class[#1][#2]%
{\normalexpanded
- {\noexpand\dododefinelabelclass
+ {\lang_labels_define_class_indeed
{#1}%
{\ifsecondargument#2\else\zerocount\fi}%
\expandafter\noexpand\csname dogetupsome#1text\endcsname
@@ -77,41 +81,29 @@
\expandafter\noexpand\csname #1texts\endcsname
\expandafter\noexpand\csname #1text\endcsname}}
-\let\currentlabelcategory\empty
-
-\def\dododefinelabelclass#1#2#3#4#5#6#7#8#9%
- {\setuvalue{setup#1text}{\protecttextprefixes#2\def\currenttextprefixclass{#1}\dodoubleempty\dosetupsometextprefix}%
- \setuvalue{preset#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dodoubleempty\dosetupsometextprefix}%
+\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{start#1text}{\protecttextprefixes1\def\currenttextprefixclass{#1}\dotripleempty\lang_labels_text_prefix_start[#1]}%
+ \letvalue{stop#1text}\relax
\def#4{\reallanguagetag{\defaultlanguage\currentmainlanguage}}%
\ifnum#2=\plustwo
\def#3{#5#4}%
-% \def#5##1##2% ##1=language
-% {\ifcsname\??ml:#1:##1:##2\endcsname
-% \csname\??ml:#1:##1:##2\endcsname
-% \else\ifcsname\??la#4\s!default\endcsname
-% \expandafter#5\csname\??la#4\s!default\endcsname{##2}%
-% \else\ifcsname\??ml:#1:##2\endcsname
-% \csname\??ml:#1:##2\endcsname
-% \else\ifcsname\??ml:#1:\s!en:##2\endcsname
-% \csname\??ml:#1:\s!en:##2\endcsname
-% \else
-% ##2%
-% \fi\fi\fi\fi}%
\def#5##1##2% ##1=language
- {\ifcsname\??ml:\currentlabelcategory#1:##1:##2\endcsname
- \csname\??ml:\currentlabelcategory#1:##1:##2\endcsname
- \else\ifcsname\??ml:#1:##1:##2\endcsname
- \csname\??ml:#1:##1:##2\endcsname
- \else\ifcsname\??la#4\s!default\endcsname
- \expandafter#5\csname\??la#4\s!default\endcsname{##2}%
- \else\ifcsname\??ml:\currentlabelcategory#1:##2\endcsname
- \csname\??ml:\currentlabelcategory#1:##2\endcsname
- \else\ifcsname\??ml:#1:##2\endcsname
- \csname\??ml:#1:##2\endcsname
- \else\ifcsname\??ml:\currentlabelcategory#1:\s!en:##2\endcsname
- \csname\??ml:\currentlabelcategory#1:\s!en:##2\endcsname
- \else\ifcsname\??ml:#1:\s!en:##2\endcsname
- \csname\??ml:#1:\s!en:##2\endcsname
+ {\ifcsname\??label\currentlabelcategory#1:##1:##2\endcsname
+ \csname\??label\currentlabelcategory#1:##1:##2\endcsname
+ \else\ifcsname\??label#1:##1:##2\endcsname
+ \csname\??label#1:##1:##2\endcsname
+ \else\ifcsname\??language#4\s!default\endcsname
+ \expandafter#5\csname\??language#4\s!default\endcsname{##2}%
+ \else\ifcsname\??label\currentlabelcategory#1:##2\endcsname
+ \csname\??label\currentlabelcategory#1:##2\endcsname
+ \else\ifcsname\??label#1:##2\endcsname
+ \csname\??label#1:##2\endcsname
+ \else\ifcsname\??label\currentlabelcategory#1:\s!en:##2\endcsname
+ \csname\??label\currentlabelcategory#1:\s!en:##2\endcsname
+ \else\ifcsname\??label#1:\s!en:##2\endcsname
+ \csname\??label#1:\s!en:##2\endcsname
\else
##2%
\fi\fi\fi\fi\fi\fi\fi}%
@@ -122,14 +114,14 @@
\else
\unexpanded\def#3{#5#4}%
\unexpanded\def#5##1##2%
- {\ifcsname\??ml:#1:##1:##2\endcsname
- \expandafter\let\expandafter\thetextprefix\csname\??ml:#1:##1:##2\endcsname
- \else\ifcsname\??la#4\s!default\endcsname
- \expandafter#5\csname\??la#4\s!default\endcsname{##2}%
- \else\ifcsname\??ml:#1:##2\endcsname
- \expandafter\let\expandafter\thetextprefix\csname\??ml:#1:##2\endcsname
- \else\ifcsname\??ml:#1:\s!en:##2\endcsname
- \expandafter\let\expandafter\thetextprefix\csname\??ml:#1:\s!en:##2\endcsname
+ {\ifcsname\??label#1:##1:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??label#1:##1:##2\endcsname
+ \else\ifcsname\??language#4\s!default\endcsname
+ \expandafter#5\csname\??language#4\s!default\endcsname{##2}%
+ \else\ifcsname\??label#1:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??label#1:##2\endcsname
+ \else\ifcsname\??label#1:\s!en:##2\endcsname
+ \expandafter\let\expandafter\thetextprefix\csname\??label#1:\s!en:##2\endcsname
\else
\let\thetextprefix\dummytextprefix
\fi\fi\fi\fi}%
@@ -169,11 +161,6 @@
%D These macros enable us to automatically define head and label
%D texts without replacing predefined ones. They are internal macros.
-\definelabelclass [head] [0] % titles
-\definelabelclass [label] [0] % texts
-\definelabelclass [mathlabel] [0] % functions
-\definelabelclass [taglabel] [2] % tags
-
\appendtoks \let\labellanguage\currentlanguage \to \everycurrentdate
\newconstant\protecttextprefixes
@@ -181,55 +168,83 @@
\let\currenttextprefixtag \s!unknown
\let\currenttextprefixclass\s!unknown
-\def\dosetupsometextprefix[#1][#2]%
+\def\lang_labels_text_prefix_start[#1][#2][#3]% class language name
+ {\ifthirdargument
+ \edef\currenttextprefixtag{\reallanguagetag{#2}}%
+ \edef\currenttextprefixname{#3}%
+ \else
+ \edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
+ \edef\currenttextprefixname{#2}%
+ \fi
+ \grabuntil{stop#1text}\lang_labels_text_prefix_start_indeed}
+
+\def\lang_labels_text_prefix_start_indeed#1% text (not special checking done here yet, only for long texts anyway)
+ {\expandafter\edef\csname\??label\currenttextprefixclass:\currenttextprefixtag:\currenttextprefixname\endcsname{{\ctxlua{context(string.strip(\!!bs#1\!!es))}}\empty}}
+
+\def\lang_labels_text_prefix_setup[#1][#2]%
{\ifsecondargument
\edef\currenttextprefixtag{\reallanguagetag{#1}}%
- \processcommalist[#2]\dodosetupsometextprefix
+ \processcommalist[#2]\lang_labels_text_prefix_setup_indeed
\else
\edef\currenttextprefixtag{\reallanguagetag\currentmainlanguage}%
- \processcommalist[#1]\dodosetupsometextprefix
+ \processcommalist[#1]\lang_labels_text_prefix_setup_indeed
\fi}
-\def\dodosetupsometextprefix#1%
- {\dododosetupsometextprefix[#1]}
+\def\lang_labels_text_prefix_setup_indeed#1%
+ {\lang_labels_text_prefix_assign[#1]}
-\def\dododosetupsometextprefix[#1=#2]%
- {\doassignsometextprefix{#1}[#2,,]}
+\def\lang_labels_text_prefix_assign[#1=#2]%
+ {\lang_labels_text_prefix_assign_indeed{#1}[#2,,]}
-\def\doassignsometextprefix#1%
+\def\lang_labels_text_prefix_assign_indeed#1%
{\ifcase\protecttextprefixes
% no checking
- \expandafter\doassignsometextprefixyes
+ \expandafter\lang_labels_text_prefix_assign_yes
\or
% checking
- \ifcsname\??ml:\currenttextprefixclass:\currenttextprefixtag:#1\endcsname
- \expandafter\expandafter\expandafter\doassignsometextprefixnop
+ \ifcsname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname
+ \expandafter\expandafter\expandafter\lang_labels_text_prefix_assign_nop
\else
- \expandafter\expandafter\expandafter\doassignsometextprefixyes
+ \expandafter\expandafter\expandafter\lang_labels_text_prefix_assign_yes
\fi
\or
% simple assignment (a bit overkill but it fits in the whole)
- \expandafter\doassignsometextprefixdumb
+ \expandafter\lang_labels_text_prefix_assign_dumb
\fi{#1}}
-\def\doassignsometextprefixyes#1[#2,#3,#4]%
- {\edef\!!stringa{#2}%
- \edef\!!stringb{#3}%
- \ifx\!!stringb\empty
- \ifx\!!stringa\empty
- \expandafter\def\csname\??ml:\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{\empty\empty}%
+\let\m_lang_labels_left \empty
+\let\m_lang_labels_right\empty
+
+\def\lang_labels_text_prefix_assign_yes#1[#2,#3,#4]%
+ {\def\m_lang_labels_left {#2}% no longer an edef ... else \Word undefined expansion issues
+ \def\m_lang_labels_right{#3}% no longer an edef ... else \Word undefined expansion issues
+ \ifx\m_lang_labels_right\empty
+ \ifx\m_lang_labels_left\empty
+ \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{\empty\empty}%
\else
- \expandafter\def\csname\??ml:\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}\empty}%
+ \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}\empty}%
\fi
\else
- \expandafter\def\csname\??ml:\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}{#3}}%
+ \expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{{#2}{#3}}%
\fi}
-\def\doassignsometextprefixnop#1[#2]%
+\def\lang_labels_text_prefix_assign_nop#1[#2]%
{}
-\def\doassignsometextprefixdumb#1[#2,#3]%
- {\expandafter\def\csname\??ml:\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}}
+\def\lang_labels_text_prefix_assign_dumb#1[#2,#3]%
+ {\expandafter\def\csname\??label\currenttextprefixclass:\currenttextprefixtag:#1\endcsname{#2}}
+
+\definelabelclass [head] [0] % titles
+\definelabelclass [label] [0] % texts
+\definelabelclass [mathlabel] [0] % functions
+\definelabelclass [taglabel] [2] % tags
+
+\ctxlua{
+ languages.labels.define("setupheadtext","titles",true)%
+ languages.labels.define("setuplabeltext","texts",true)%
+ languages.labels.define("setupmathlabeltext","functions",false)%
+ languages.labels.define("setuptaglabeltext","tags",false)%
+}
%D \macros
%D {translate}
@@ -249,7 +264,10 @@
%D which expands to {\em something} or {\em iets}, depending on
%D de current language.
-\def\dotranslate[#1]%
+\unexpanded\def\translate
+ {\dosingleempty\lang_translate}
+
+\def\lang_translate[#1]%
{\getparameters[\??lg][#1]%
\ifcsname\??lg\currentlanguage\endcsname
\csname\??lg\currentlanguage\endcsname
@@ -259,9 +277,6 @@
[translation #1]%
\fi\fi}
-\unexpanded\def\translate
- {\dosingleempty\dotranslate}
-
%D When used without argument, the last defined values are
%D used. This enables repetitive use like
%D
@@ -283,12 +298,4 @@
{\getparameters[\??lg][#1]%
\edef#2{\csname\??lg\currentlanguage\endcsname}}
-%D Now we load the labels:
-
-\ifdefined\sixperemspace \else \def\sixperemspace{ } \fi % we could embed 0x2006 but it does not show up in a editor
-
-%D Now we can load the labels:
-
-\ctxlua{languages.labels.define()}
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/lang-mis.mkii b/Master/texmf-dist/tex/context/base/lang-mis.mkii
index eb7bb1a04dc..3923df3e8ae 100644
--- a/Master/texmf-dist/tex/context/base/lang-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Compounds,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-mis.mkiv b/Master/texmf-dist/tex/context/base/lang-mis.mkiv
index 231697c7ee7..ce23c0f60e8 100644
--- a/Master/texmf-dist/tex/context/base/lang-mis.mkiv
+++ b/Master/texmf-dist/tex/context/base/lang-mis.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Compounds,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,17 +13,10 @@
\writestatus{loading}{ConTeXt Language Macros / Compounds}
-%D \gdef\starttest
-%D {\blank
-%D \noindent
-%D \halign\bgroup\tt##\hskip2em&##\hskip2em&##\cr}
-%D
-%D \gdef\stoptest
-%D {\egroup
-%D \blank}
-%D
-%D \gdef\test#1%
-%D {\defconvertedargument\ascii{#1}\ascii&\hyphenatedword{#1}&#1\cr}
+%D More or less replaced.
+
+%D \gdef\starttest#1\stoptest{\starttabulate[|l|l|p|]#1\stoptabulate}
+%D \gdef\test #1{\NC\detokenize{#1}\NC\hyphenatedword{#1}\NC#1\NC\NR}
\unprotect
@@ -131,31 +124,30 @@
%D compound words is using \type{||}, which is installed by:
%D
%D \starttyping
-%D \installdiscretionaries || -
+%D \installdiscretionary | -
%D \stoptyping
%D
%D Some alternative definitions are:
%D
%D \startbuffer
-%D \installdiscretionaries ** -
-%D \installdiscretionaries ++ -
-%D \installdiscretionaries // -
-%D \installdiscretionaries ~~ -
+%D \installdiscretionary * -
+%D \installdiscretionary + -
+%D \installdiscretionary / -
+%D \installdiscretionary ~ -
%D \stopbuffer
%D
%D \typebuffer
%D
%D after which we can say:
%D
-%D \bgroup
-%D \getbuffer
+%D \start \getbuffer
%D \starttest
%D \test {test**test**test}
%D \test {test++test++test}
%D \test {test//test//test}
%D \test {test~~test~~test}
%D \stoptest
-%D \egroup
+%D \stop
%D \macros
%D {compoundhyphen,
@@ -165,10 +157,9 @@
%D In the main \CONTEXT\ modules these can be tuned by a setup
%D command. Watch the (maybe) better looking compound hyphen.
-\ifx\compoundhyphen \undefined \def\compoundhyphen{\hbox{-\kern-.25ex-}} \fi
-
-\ifx\beginofsubsentence \undefined \def\beginofsubsentence{\hbox{---}} \fi
-\ifx\endofsubsentence \undefined \def\endofsubsentence {\hbox{---}} \fi
+\ifx\compoundhyphen \undefined \def\compoundhyphen {\hbox{-\kern-.25ex-}} \fi
+\ifx\beginofsubsentence\undefined \def\beginofsubsentence{\hbox{---}} \fi
+\ifx\endofsubsentence \undefined \def\endofsubsentence {\hbox{---}} \fi
%D The last two variables are needed for subsentences
%D |<|like this one|>| which we did not yet mention.
@@ -177,11 +168,10 @@
%D compound characters like |-| or || to be separated from the
%D words. \TEX\ hackers will recognise the next two macro's:
-\ifx\prewordbreak \undefined \def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi
-%ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount \prewordbreak } \fi
-\ifx\postwordbreak \undefined \def\postwordbreak{\penalty\zerocount \hskip\zeropoint\relax} \fi
-
-\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667em} \fi % language specific
+\ifx\prewordbreak \undefined \def\prewordbreak {\penalty\plustenthousand\hskip\zeropoint\relax} \fi
+%ifx\postwordbreak\undefined \def\postwordbreak {\penalty\zerocount \prewordbreak } \fi
+\ifx\postwordbreak\undefined \def\postwordbreak {\penalty\zerocount \hskip\zeropoint\relax} \fi
+\ifx\hspaceamount \undefined \def\hspaceamount#1#2{.16667em} \fi % language specific
%D \macros
%D {beginofsubsentencespacing,endofsubsentencespacing}
@@ -206,20 +196,20 @@
%D |x_n-{1\over2}| &for ${1\over2}<x_n\le1$ \cr}}
%D \stopformula
-\def\@tmd@action@{@tmd@a@}
-\def\@tmd@text@ {@tmd@t@}
-\def\@tmd@math@ {@tmd@m@}
-\def\@tmd@both@ {@tmd@b@}
+\installcorenamespace{discretionaryaction}
+\installcorenamespace{discretionarytext}
+\installcorenamespace{discretionarymath}
+\installcorenamespace{discretionaryboth}
\def\installdiscretionary#1#2%
- {\setevalue{\@tmd@math@\detokenize{#1}}{\detokenize{#1}}%
- \setvalue {\@tmd@text@\detokenize{#1}}{#2}%
- \setvalue {\@tmd@both@\detokenize{#1}}{\discretionarycommand#1}%
+ {\setevalue{\??discretionarymath\detokenize{#1}}{\detokenize{#1}}% ?
+ \setvalue {\??discretionarytext\detokenize{#1}}{#2}%
+ \setvalue {\??discretionaryboth\detokenize{#1}}{\lang_discretionaries_command#1}%
\scratchcounter\expandafter`\detokenize{#1}%
- \@EA\uedcatcodecommand\@EA\ctxcatcodes\@EA\scratchcounter\csname\@tmd@both@\detokenize{#1}\endcsname}
+ \expandafter\uedcatcodecommand\expandafter\ctxcatcodes\expandafter\scratchcounter\csname\??discretionaryboth\detokenize{#1}\endcsname}
-\def\handlemathmodediscretionary#1{\executeifdefined{\@tmd@math@\detokenize{#1}}\donothing}
-\def\handletextmodediscretionary#1{\executeifdefined{\@tmd@text@\detokenize{#1}}\donothing}
+\def\handlemathmodediscretionary#1{\executeifdefined{\??discretionarymath\detokenize{#1}}\donothing}
+\def\handletextmodediscretionary#1{\executeifdefined{\??discretionarytext\detokenize{#1}}\donothing}
\def\installdiscretionaries#1#2{\writestatus\m!system{use \string \installdiscretionary}} % obsolete
@@ -228,24 +218,24 @@
\def\ignorediscretionaries
{\discretionarymode\zerocount}
-\def\discretionarycommand
+\def\lang_discretionaries_command
{% if direct if, we need \relax for lookahead in math mode
\csname
\ifcase\discretionarymode
- \strippedcsname\dononemodediscretionary
+ \strippedcsname\lang_discretionaries_process_none
\else\ifmmode
- \strippedcsname\domathmodediscretionary
+ \strippedcsname\lang_discretionaries_process_math
\else
- \strippedcsname\dotextmodediscretionary
+ \strippedcsname\lang_discretionaries_process_text
\fi\fi
\endcsname}
-\def\dononemodediscretionary#1%
+\def\lang_discretionaries_process_none#1%
{\detokenize{#1}}
-%D The macro \type{\checkbeforediscretionary} takes care of
-%D loners like \type{||word}, while it counterpart
-%D \type{\checkafterdiscretionary} is responsible for handling
+%D The macro \type{\lang_discretionaries_check_before} takes care
+%D of loners like \type{||word}, while it counterpart \type
+%D {\lang_discretionaries_check_after} is responsible for handling
%D the comma.
\newsignal\compoundbreakpoint
@@ -253,8 +243,10 @@
\newconditional\punctafterdiscretionary
\newconditional\spaceafterdiscretionary
-\def\checkbeforediscretionary
- {\ifvmode\dontleavehmode\fi
+\def\lang_discretionaries_check_before
+ {\ifvmode
+ \dontleavehmode
+ \fi
\ifhmode
\begingroup
\setbox\scratchbox\lastbox
@@ -265,7 +257,7 @@
\endgroup
\fi}
-\def\checkafterdiscretionary
+\def\lang_discretionaries_check_after
{\setfalse\punctafterdiscretionary
\setfalse\spaceafterdiscretionary
\ifx\blankspace\nextnext \settrue \spaceafterdiscretionary \else
@@ -275,9 +267,9 @@
\ifx :\nextnext \settrue \punctafterdiscretionary \else
\ifx ;\nextnext \settrue \punctafterdiscretionary \fi\fi\fi\fi\fi\fi}
-\let\domathmodediscretionary\handlemathmodediscretionary
+\let\lang_discretionaries_process_math\handlemathmodediscretionary
-\def\dotextmodediscretionary#1% grouped !
+\def\lang_discretionaries_process_text#1% grouped !
{\bgroup
\let\nextnextnext\egroup
\def\next##1#1%
@@ -288,11 +280,11 @@
\def\activedododotextmodediscretionary#1#2%
{\edef\discretionarytoken{\detokenize{#2}}%
\def\textmodediscretionary{\handletextmodediscretionary{#1}}%
- \checkafterdiscretionary
+ \lang_discretionaries_check_after
\ifx\discretionarytoken\empty
\ifx#1\nextnext % takes care of ||| and +++ and ......
- \ifcsname\@tmd@action@\string#1\endcsname
- \csname\@tmd@action@\string#1\endcsname
+ \ifcsname\??discretionaryaction\string#1\endcsname
+ \csname\??discretionaryaction\string#1\endcsname
\else\ifconditional\spaceafterdiscretionary
\prewordbreak\hbox{\string#1}\relax
\else\ifconditional\punctafterdiscretionary
@@ -302,12 +294,12 @@
\fi\fi\fi
\def\nextnextnext{\afterassignment\egroup\let\next=}%
\else
- \checkbeforediscretionary
+ \lang_discretionaries_check_before
% the next line has been changed (20050203)
% \prewordbreak\hbox{\textmodediscretionary\nextnext}\allowbreak\postwordbreak
% but an hbox blocks a possible \discretionary
- \ifcsname\@tmd@action@\endcsname
- \csname\@tmd@action@\endcsname
+ \ifcsname\??discretionaryaction\endcsname
+ \csname\??discretionaryaction\endcsname
\else\ifconditional\spaceafterdiscretionary
\prewordbreak\textmodediscretionary\relax
\else\ifconditional\punctafterdiscretionary
@@ -317,10 +309,10 @@
\fi\fi\fi
% \prewordbreak\textmodediscretionary\nextnext\allowbreak\postwordbreak
\fi
- \else\ifcsname\@tmd@action@\discretionarytoken\endcsname
- \csname\@tmd@action@\discretionarytoken\endcsname
+ \else\ifcsname\??discretionaryaction\discretionarytoken\endcsname
+ \csname\??discretionaryaction\discretionarytoken\endcsname
\else
- \checkbeforediscretionary
+ \lang_discretionaries_check_before
\ifconditional\spaceafterdiscretionary
\prewordbreak\hbox{#2}\relax
\else\ifconditional\punctafterdiscretionary
@@ -340,31 +332,31 @@
\def\directdiscretionary
{\csname
\ifcase\discretionarymode
- \strippedcsname\dononemodediscretionary
+ \strippedcsname\lang_discretionaries_process_none
\else
- \strippedcsname\dodirectdiscretionary
+ \strippedcsname\lang_discretionaries_process_direct
\fi
\endcsname}
\def\indirectdiscretionary
{\csname
\ifcase\discretionarymode
- \strippedcsname\dononemodediscretionary
+ \strippedcsname\lang_discretionaries_process_none
\else
- \strippedcsname\doindirectdiscretionary
+ \strippedcsname\lang_discretionaries_process_indirect
\fi
\endcsname}
-\unexpanded\def\dodirectdiscretionary#1%
+\unexpanded\def\lang_discretionaries_process_direct#1%
{\edef\discretionarytoken{\detokenize{#1}}%
\let\textmodediscretionary\compoundhyphen
- \executeifdefined{\@tmd@action@\discretionarytoken}{\indirectdiscretionary{#1}}}
+ \executeifdefined{\??discretionaryaction\discretionarytoken}{\indirectdiscretionary{#1}}}
-\unexpanded\def\doindirectdiscretionary#1%
+\unexpanded\def\lang_discretionaries_process_indirect#1%
{\prewordbreak\discretionary{\hbox{#1}}{}{\hbox{#1}}\allowbreak\postwordbreak}
\unexpanded\def\definetextmodediscretionary #1
- {\setvalue{\@tmd@action@\detokenize{#1}}}
+ {\setvalue{\??discretionaryaction\detokenize{#1}}}
% \start \hsize 1mm
% test |||test test|||, test\blank
@@ -383,7 +375,7 @@
% xxx3xxx
% xxx1<newline>2xxx
-\def\hyphenliketextmodediscretionary#1#2%
+\def\lang_discretionaries_hyphen_like#1#2%
{\ifconditional\spaceafterdiscretionary
\prewordbreak\hbox{#1}\relax
\else\ifconditional\punctafterdiscretionary
@@ -393,16 +385,16 @@
\fi\fi}
\definetextmodediscretionary {}
- {\hyphenliketextmodediscretionary\textmodehyphen\textmodehyphendiscretionary}
+ {\lang_discretionaries_hyphen_like\textmodehyphen\textmodehyphendiscretionary}
\definetextmodediscretionary -
- {\hyphenliketextmodediscretionary\normalhyphen\normalhyphendiscretionary}
+ {\lang_discretionaries_hyphen_like\normalhyphen\normalhyphendiscretionary}
\definetextmodediscretionary _
- {\hyphenliketextmodediscretionary\composedhyphen\composedhyphendiscretionary}
+ {\lang_discretionaries_hyphen_like\composedhyphen\composedhyphendiscretionary}
\definetextmodediscretionary )
- {\hyphenliketextmodediscretionary{)}{\discretionary{-)}{}{)}}}
+ {\lang_discretionaries_hyphen_like{)}{\discretionary{-)}{}{)}}}
\definetextmodediscretionary (
{\ifdim\lastskip>\zeropoint
@@ -447,7 +439,7 @@
% \ifx\normalcompound\undefined \let\normalcompound=| \fi
-%D \installdiscretionary | +
+%D \installdiscretionary | +
%D \installdiscretionary + =
\def\defaultdiscretionaryhyphen{\compoundhyphen}
@@ -466,10 +458,10 @@
%D \goto{Some||Long||Word}
%D \stoptyping
-\def\fakecompoundhyphen
- {\def\|{\mathortext\vert\dofakecompoundhyphen}}
+\unexpanded\def\fakecompoundhyphen
+ {\def\|{\mathortext\vert\lang_compounds_fake_hyphen}}
-\def\dofakecompoundhyphen
+\def\lang_compounds_fake_hyphen
{\def##1|%
{\doifelsenothing{##1}\compoundhyphen{##1}%
\kern\compoundbreakpoint\allowbreak}}
@@ -483,13 +475,13 @@
%D earlier, this one also looks ahead for spaces and grouping
%D tokens.
-\def\midworddiscretionary
- {\futurelet\next\domidworddiscretionary}
+\unexpanded\def\midworddiscretionary
+ {\futurelet\nexttoken\lang_discretionaries_mid_word}
-\def\domidworddiscretionary
- {\ifx\next\blankspace\else
- \ifx\next\bgroup \else
- \ifx\next\egroup \else
+\def\lang_discretionaries_mid_word
+ {\ifx\nexttoken\blankspace\else
+ \ifx\nexttoken\bgroup \else
+ \ifx\nexttoken\egroup \else
\discretionary{-}{}{}%
\fi\fi\fi}
@@ -533,10 +525,10 @@
%D mentioned earlier in this module. We take care of two
%D arguments, which complicates things a bit.
-\def\@nc@{@nc@} % normal character
-\def\@cc@{@cc@} % compound character
-\def\@cs@{@cs@} % compound characters
-\def\@cx@{@cx@} % compound definition
+\installcorenamespace{compoundnormal}
+\installcorenamespace{compoundsingle}
+\installcorenamespace{compoundmultiple}
+\installcorenamespace{compounddefinition}
%D When we started working on MK IV code, we needed a different
%D approach for defining the active character itself. In MK II as
@@ -544,39 +536,26 @@
\setnewconstant\compoundcharactermode\plusone
+\newcount\c_lang_compounds_character
+
\def\installcompoundcharacter #1#2#3 #4% {#4} no grouping
{\ifcase\compoundcharactermode
% ignore mode
\else
- \chardef\thecompoundcharacter`#1%
- \@EA\chardef\csname\@nc@\string#1\endcsname\thecompoundcharacter
+ \chardef\c_lang_compounds_character`#1%
+ \expandafter\chardef\csname\??compoundnormal\string#1\endcsname\c_lang_compounds_character
\def\!!stringa{#3}%
- \@EA\def\csname\ifx\!!stringa\empty\@cc@\else\@cs@\fi\detokenize{#1#2#3}\endcsname{#4}%
- \setevalue{\@cx@\detokenize{#1}}{\noexpand\handlecompoundcharacter{\detokenize{#1}}}% beter nr's
- \@EA\letcatcodecommand\@EA\ctxcatcodes\@EA\thecompoundcharacter\csname\@cx@\detokenize{#1}\endcsname
+ \expandafter\def\csname\ifx\!!stringa\empty\??compoundsingle\else\??compoundmultiple\fi\detokenize{#1#2#3}\endcsname{#4}%
+ \setevalue{\??compounddefinition\detokenize{#1}}{\noexpand\lang_compounds_handle_character{\detokenize{#1}}}% beter nr's
+ \expandafter\letcatcodecommand\expandafter\ctxcatcodes\expandafter\c_lang_compounds_character\csname\??compounddefinition\detokenize{#1}\endcsname
\fi}
-%D In order to serve the language specific well, we will introduce
-%D a namespace:
-
-% \ifx\currentlanguage\undefined
- \let\compoundcharacterclass\empty
-% \else
-% \def\compoundcharacterclass{\currentlanguage}
-% \fi
-
-\def\@cc@{@cc@\compoundcharacterclass} % compound character
-\def\@cs@{@cs@\compoundcharacterclass} % compound characters
-
%D We can also ignore definitions (needed in for instance \XML). Beware,
%D this macro is supposed to be used grouped!
\def\ignorecompoundcharacter
{\compoundcharactermode\zerocount}
-\let\restorecompoundcharacter \gobbleoneargument % obsolete
-\let\enableactivediscretionaries\relax % obsolete
-
%D In handling the compound characters we have to take care of
%D \type{\bgroup} and \type{\egroup} tokens, so we end up with
%D a multi||step interpretation macro. We look ahead for a
@@ -589,40 +568,41 @@
%D with \type{\futurelet} to prevent spaces from
%D disappearing.
-\def\handlecompoundcharacter#1%
- {\def\xhandlecompoundcharacter{\dohandlecompoundcharacter{#1}}%
- \futurelet\next\xhandlecompoundcharacter}
-
-\def\dohandlecompoundcharacter
- {\ifx\next\bgroup
- %\@EA\dodohandlecompoundcharacter % handle "{ee} -> \"ee
- %\@EA\gobbleoneargument % forget "{ee} -> ee
- \@EA\handlecompoundcharacterone % ignore "{ee} -> "ee
- \else\ifx\next\egroup
- \@EAEAEA\donohandlecompoundcharacter
- \else\ifx\next\blankspace
- \@EA\@EAEAEA\@EA\donohandlecompoundcharacter
+\def\lang_compounds_handle_character#1%
+ {\def\lang_compounds_handle_character_finish{\lang_compounds_handle_character_finish_indeed{#1}}%
+ \futurelet\nexttoken\xhandlecompoundcharacter}
+
+\def\lang_compounds_handle_character_finish_indeed
+ {\ifx\nexttoken\bgroup
+ %\expandafter\lang_compounds_handle_character_pickup % handle "{ee} -> \"ee
+ %\expandafter\gobbleoneargument % forget "{ee} -> ee
+ \expandafter\lang_compounds_handle_character_one % ignore "{ee} -> "ee
+ \else\ifx\nexttoken\egroup
+ \doubleexpandafter\lang_compounds_handle_character_normal
+ \else\ifx\nexttoken\blankspace
+ \tripleexpandafter\lang_compounds_handle_character_normal
\else
- \@EA\@EAEAEA\@EA\dodohandlecompoundcharacter
+ \tripleexpandafter\lang_compounds_handle_character_pickup
\fi\fi\fi}
-\def\donohandlecompoundcharacter#1{\csname\@nc@\string#1\endcsname}
+\def\lang_compounds_handle_character_normal#1%
+ {\csname\??compoundnormal\string#1\endcsname}
+
+\def\lang_compounds_handle_character_pickup#1#2% preserve space
+ {\def\lang_compounds_handle_character_finish{\lang_compounds_handle_character_finish_indeed#1#2}%
+ \futurelet\nexttoken\lang_compounds_handle_character_finish}
-\def\dododohandlecompoundcharacter
- {\ifx\next\bgroup
- \@EA\handlecompoundcharacterone
- \else\ifx\next\egroup
- \@EAEAEA\handlecompoundcharacterone
- \else\ifx\next\blankspace
- \@EA\@EAEAEA\@EA\handlecompoundcharacterone
+\def\lang_compounds_handle_character_finish_indeed
+ {\ifx\nexttoken\bgroup
+ \expandafter\lang_compounds_handle_character_one
+ \else\ifx\nexttoken\egroup
+ \doubleexpandafter\lang_compounds_handle_character_one
+ \else\ifx\nexttoken\blankspace
+ \tripleexpandafter\lang_compounds_handle_character_one
\else
- \@EA\@EAEAEA\@EA\handlecompoundcharactertwo
+ \tripleexpandafter\lang_compounds_handle_character_two
\fi\fi\fi}
-\def\dodohandlecompoundcharacter#1#2% preserve space
- {\def\xdodohandlecompoundcharacter{\dododohandlecompoundcharacter#1#2}%
- \futurelet\next\xdodohandlecompoundcharacter}
-
%D Besides taken care of the grouping and space tokens, we have
%D to deal with three situations. First we look if the next
%D character equals the first one, if so, then we just insert
@@ -636,25 +616,25 @@
%D
%D In later modules we will see how these commands are used.
-\long\def\handlecompoundcharacterone#1#2%
+\def\lang_compounds_handle_character_one#1#2%
{\if\string#1\string#2% was: \ifx#1#2%
- \def\next{\csname\@nc@\string#1\endcsname}%
- \else\ifcsname\@cc@\string#1\string#2\endcsname
- \def\next{\csname\@cc@\string#1\string#2\endcsname}%
+ \def\next{\csname\??compoundnormal\string#1\endcsname}%
+ \else\ifcsname\??compoundsingle\string#1\string#2\endcsname
+ \def\next{\csname\??compoundsingle\string#1\string#2\endcsname}%
\else
- \def\next{\csname\@nc@\string#1\endcsname#2}%
+ \def\next{\csname\??compoundnormal\string#1\endcsname#2}%
\fi\fi
\next}
-\long\def\handlecompoundcharactertwo#1#2#3%
+\def\lang_compounds_handle_character_two#1#2#3%
{\if\string#1\string#2%
- \def\next{\csname\@nc@\string#1\endcsname#3}%
- \else\ifcsname\@cs@\string#1\string#2\string#3\endcsname
- \def\next{\csname\@cs@\string#1\string#2\string#3\endcsname}%
- \else\ifcsname\@cc@\string#1\string#2\endcsname
- \def\next{\csname\@cc@\string#1\string#2\endcsname#3}%
+ \def\next{\csname\??compoundnormal\string#1\endcsname#3}%
+ \else\ifcsname\??compoundmultiple\string#1\string#2\string#3\endcsname
+ \def\next{\csname\??compoundmultiple\string#1\string#2\string#3\endcsname}%
+ \else\ifcsname\??compoundsingle\string#1\string#2\endcsname
+ \def\next{\csname\??compoundsingle\string#1\string#2\endcsname#3}%
\else
- \def\next{\csname\@nc@\string#1\endcsname#2#3}%
+ \def\next{\csname\??compoundnormal\string#1\endcsname#2#3}%
\fi\fi\fi
\next}
@@ -662,8 +642,8 @@
%D {lang-sla.tex}) we provide:
\def\simplifiedcompoundcharacter#1#2%
- {\ifcsname\@cc@\string#1\string#2\endcsname
- \@EA\@EA\@EA\firstofoneargument\csname\@cc@\string#1\string#2\endcsname
+ {\ifcsname\??compoundsingle\string#1\string#2\endcsname
+ \doubleexpandafter\firstofoneargument\csname\??compoundsingle\string#1\string#2\endcsname
\else
#2%
\fi}
@@ -682,6 +662,6 @@
%D
%D Handy in for instance XML. (Kind of obsolete)
-\ifx\normalcompound\undefined \let\normalcompound=| \fi
+\ifdefined\normalcompound \else \let\normalcompound=| \fi
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/lang-run.mkii b/Master/texmf-dist/tex/context/base/lang-run.mkii
index 4b332cfb975..320ee8dabf6 100644
--- a/Master/texmf-dist/tex/context/base/lang-run.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-sla.mkii b/Master/texmf-dist/tex/context/base/lang-sla.mkii
index 2834b652f6a..81f9a9bf711 100644
--- a/Master/texmf-dist/tex/context/base/lang-sla.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-sla.mkii
@@ -5,7 +5,7 @@
%D subtitle=Slavic Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-spa.mkii b/Master/texmf-dist/tex/context/base/lang-spa.mkii
index f6e22aa5190..313e5f3e6e7 100644
--- a/Master/texmf-dist/tex/context/base/lang-spa.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-spa.mkii
@@ -5,7 +5,7 @@
%D subtitle=Spacing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-spa.mkiv b/Master/texmf-dist/tex/context/base/lang-spa.mkiv
index 2cc88b84fcf..e7cb0025fd6 100644
--- a/Master/texmf-dist/tex/context/base/lang-spa.mkiv
+++ b/Master/texmf-dist/tex/context/base/lang-spa.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Spacing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-spe.mkii b/Master/texmf-dist/tex/context/base/lang-spe.mkii
index 7911b0c95b9..11c57af3f23 100644
--- a/Master/texmf-dist/tex/context/base/lang-spe.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-spe.mkii
@@ -5,7 +5,7 @@
%D subtitle=Specifics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-txt.lua b/Master/texmf-dist/tex/context/base/lang-txt.lua
index fc3a55170fd..f28cb18f12f 100644
--- a/Master/texmf-dist/tex/context/base/lang-txt.lua
+++ b/Master/texmf-dist/tex/context/base/lang-txt.lua
@@ -312,7 +312,7 @@ data.labels={
nb="",
nl="en",
nn="",
- pl="",
+ pl="i",
pt="",
ro="",
ru="",
@@ -422,7 +422,7 @@ data.labels={
nb="april",
nl="",
nn="april",
- pl="",
+ pl="kwi.",
pt="",
ro="",
ru="",
@@ -456,7 +456,7 @@ data.labels={
nb="på side ",
nl="op pagina ",
nn="på side ",
- pl="",
+ pl="na stronie ",
pt="",
ro="",
ru="на Ñтранице ",
@@ -529,7 +529,7 @@ data.labels={
nb="aug.",
nl="",
nn="aug.",
- pl="",
+ pl="sier.",
pt="",
ro="",
ru="",
@@ -672,7 +672,7 @@ data.labels={
nb="des.",
nl="",
nn="des.",
- pl="",
+ pl="gru.",
pt="",
ro="",
ru="",
@@ -744,7 +744,7 @@ data.labels={
nb="feb.",
nl="",
nn="feb.",
- pl="",
+ pl="lut.",
pt="",
ro="",
ru="",
@@ -889,7 +889,7 @@ data.labels={
nb="som vist over",
nl="hierboven",
nn="som vist over",
- pl="",
+ pl="jak pokazano wyżej",
pt="",
ro="",
ru="Ñм. выше",
@@ -923,7 +923,7 @@ data.labels={
nb="som vist under",
nl="hieronder",
nn="som vist under",
- pl="",
+ pl="jak pokazano niżej",
pt="",
ro="",
ru="Ñм. ниже",
@@ -1032,7 +1032,7 @@ data.labels={
nb="jan.",
nl="",
nn="jan.",
- pl="",
+ pl="sty.",
pt="",
ro="",
ru="",
@@ -1105,7 +1105,7 @@ data.labels={
nb="juli",
nl="",
nn="juli",
- pl="",
+ pl="lip.",
pt="",
ro="",
ru="",
@@ -1177,7 +1177,7 @@ data.labels={
nb="juni",
nl="",
nn="juni",
- pl="",
+ pl="czerw.",
pt="",
ro="",
ru="",
@@ -1322,7 +1322,7 @@ data.labels={
nb="mars",
nl="",
nn="mars",
- pl="",
+ pl="mar.",
pt="",
ro="",
ru="",
@@ -1395,7 +1395,7 @@ data.labels={
nb="mai",
nl="",
nn="mai",
- pl="",
+ pl="maja",
pt="",
ro="",
ru="",
@@ -1504,7 +1504,7 @@ data.labels={
nb="nov.",
nl="",
nn="nov.",
- pl="",
+ pl="lis.",
pt="",
ro="",
ru="",
@@ -1575,7 +1575,7 @@ data.labels={
nb="okt.",
nl="",
nn="okt.",
- pl="",
+ pl="paź.",
pt="",
ro="",
ru="",
@@ -1610,7 +1610,7 @@ data.labels={
nb="side ",
nl="pagina ",
nn="side ",
- pl="",
+ pl="strona ",
pt="",
ro="",
ru="Ñтраница ",
@@ -1647,7 +1647,7 @@ data.labels={
nb="Del",
nl="Deel ",
nn="Del",
- pl="Ustęp ",
+ pl="Część ",
pt="Parte ",
ro="Partea ",
ru="ЧаÑÑ‚ÑŒ ",
@@ -1757,7 +1757,7 @@ data.labels={
nb="se ",
nl="zie ",
nn="sjå ",
- pl="",
+ pl="patrz ",
pt="",
ro="",
ru="Ñм. ",
@@ -1829,7 +1829,7 @@ data.labels={
nb="sep.",
nl="",
nn="sep.",
- pl="",
+ pl="wrz.",
pt="",
ro="",
ru="",
@@ -1866,7 +1866,7 @@ data.labels={
nb="",
nl="",
nn="",
- pl="",
+ pl="Podpodrozdział ",
pt="",
ro="",
ru="",
@@ -1940,7 +1940,7 @@ data.labels={
nb="",
nl="",
nn="",
- pl="",
+ pl="", -- not used in Polish
pt="",
ro="",
ru="",
@@ -2164,7 +2164,7 @@ data.labels={
nb="Forkortelser",
nl="Afkortingen",
nn="Forkortingar",
- pl="Skrócenie",
+ pl="Wykaz skrótów",
pt="Abreviaturas",
ro="Abrevieri",
ru="СпиÑок Ñокращений",
@@ -2275,7 +2275,7 @@ data.labels={
nb="Bilde",
nl="Grafieken",
nn="Bilete",
- pl="Grafika",
+ pl="Grafiki",
pt="Gráficos",
ro="Grafice",
ru="СпиÑок графиков",
@@ -2419,7 +2419,7 @@ data.labels={
nb="",
nl="Literatuur",
nn="",
- pl="",
+ pl="Bibliografia",
pt="",
ro="",
ru="",
diff --git a/Master/texmf-dist/tex/context/base/lang-ura.mkii b/Master/texmf-dist/tex/context/base/lang-ura.mkii
index a2bcd3d2bf2..21bc8d94a74 100644
--- a/Master/texmf-dist/tex/context/base/lang-ura.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-ura.mkii
@@ -5,7 +5,7 @@
%D subtitle=Uralic Languages,
%D author=Hans Hagen / Tobias Burnus,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-url.lua b/Master/texmf-dist/tex/context/base/lang-url.lua
index e401e41484d..09a4e5d903f 100644
--- a/Master/texmf-dist/tex/context/base/lang-url.lua
+++ b/Master/texmf-dist/tex/context/base/lang-url.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['lang-url'] = {
local utf = unicode.utf8
local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
-local utfbyte, utfgsub = utf.byte, utf.gsub
+local utfbyte, utfchar, utfgsub = utf.byte, utf.char, utf.gsub
context = context
@@ -26,59 +26,69 @@ dealing with <l n='ascii'/> characters.</p>
commands.hyphenatedurl = commands.hyphenatedurl or { }
local hyphenatedurl = commands.hyphenatedurl
-hyphenatedurl.characters = utilities.storage.allocate {
- ["!"] = 1,
- ["\""] = 1,
- ["#"] = 1,
- ["$"] = 1,
- ["%"] = 1,
- ["&"] = 1,
- ["("] = 1,
- ["*"] = 1,
- ["+"] = 1,
- [","] = 1,
- ["-"] = 1,
- ["."] = 1,
- ["/"] = 1,
- [":"] = 1,
- [";"] = 1,
- ["<"] = 1,
- ["="] = 1,
- [">"] = 1,
- ["?"] = 1,
- ["@"] = 1,
- ["["] = 1,
- ["\\"] = 1,
- ["^"] = 1,
- ["_"] = 1,
- ["`"] = 1,
- ["{"] = 1,
- ["|"] = 1,
- ["~"] = 1,
-
- ["'"] = 2,
- [")"] = 2,
- ["]"] = 2,
- ["}"] = 2
+local characters = utilities.storage.allocate {
+ ["!"] = 1,
+ ["\""] = 1,
+ ["#"] = 1,
+ ["$"] = 1,
+ ["%"] = 1,
+ ["&"] = 1,
+ ["("] = 1,
+ ["*"] = 1,
+ ["+"] = 1,
+ [","] = 1,
+ ["-"] = 1,
+ ["."] = 1,
+ ["/"] = 1,
+ [":"] = 1,
+ [";"] = 1,
+ ["<"] = 1,
+ ["="] = 1,
+ [">"] = 1,
+ ["?"] = 1,
+ ["@"] = 1,
+ ["["] = 1,
+ ["\\"] = 1,
+ ["^"] = 1,
+ ["_"] = 1,
+ ["`"] = 1,
+ ["{"] = 1,
+ ["|"] = 1,
+ ["~"] = 1,
+
+ ["'"] = 2,
+ [")"] = 2,
+ ["]"] = 2,
+ ["}"] = 2,
}
+local mapping = utilities.storage.allocate {
+--~ [utfchar(0xA0)] = "~", -- nbsp (catch)
+}
+
+hyphenatedurl.characters = characters
+hyphenatedurl.mapping = mapping
hyphenatedurl.lefthyphenmin = 2
hyphenatedurl.righthyphenmin = 3
hyphenatedurl.discretionary = nil
-local chars = hyphenatedurl.characters
+-- more fun is to write nodes
-local function action(hyphenatedurl, str, left, right, disc)
+local function action(hyphenatedurl,str,left,right,disc)
local n = 0
local b = math.max( left or hyphenatedurl.lefthyphenmin, 2)
local e = math.min(#str-(right or hyphenatedurl.righthyphenmin)+2,#str)
local d = disc or hyphenatedurl.discretionary
for s in utfcharacters(str) do
n = n + 1
+ s = mapping[s] or s
+ if n > 1 then
+ context.s() -- can be option
+ end
if s == d then
context.d(utfbyte(s))
else
- local c = chars[s]
+ local c = characters[s]
if not c or n<=b or n>=e then
context.n(utfbyte(s))
elseif c == 1 then
@@ -92,13 +102,13 @@ end
-- hyphenatedurl.action = function(_,...) action(...) end -- sort of obsolete
-table.setmetatablecall(hyphenatedurl,action)
+table.setmetatablecall(hyphenatedurl,action) -- watch out: a caller
-- todo, no interface in mkiv yet
function hyphenatedurl.setcharacters(str,value) -- 1, 2 == before, after
for s in utfcharacters(str) do
- chars[s] = value or 1
+ characters[s] = value or 1
end
end
diff --git a/Master/texmf-dist/tex/context/base/lang-url.mkii b/Master/texmf-dist/tex/context/base/lang-url.mkii
index fdf530b45af..1f340ffb0e4 100644
--- a/Master/texmf-dist/tex/context/base/lang-url.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-url.mkii
@@ -5,7 +5,7 @@
%D subtitle=Language Options,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-url.mkiv b/Master/texmf-dist/tex/context/base/lang-url.mkiv
index cba013324c7..1bbe1683830 100644
--- a/Master/texmf-dist/tex/context/base/lang-url.mkiv
+++ b/Master/texmf-dist/tex/context/base/lang-url.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Language Options,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,6 +15,9 @@
\unprotect
+%D Traditionally this code is in the language namespace as
+%D hyphenation relates to languages.
+
%D \macros
%D {hyphenatedurl}
%D
@@ -55,32 +58,47 @@
\let|=\letterbar
\to \everyhyphenatedurl
-\def\hyphenatedurlseparator{} % \periodcentered
-
-\def\dohyphenatedurlafter #1{\char#1\discretionary{}{\hyphenatedurlseparator}{}}%
-\def\dohyphenatedurlbefore#1{\discretionary{\hyphenatedurlseparator}{}{}\char#1\relax}%
-\def\dohyphenatedurlnormal#1{\char#1\relax}%
-\def\dohyphenatedurldisc #1{\discretionary{}{}{}}
+\let\hyphenatedurlseparator \empty % \periodcentered
+\let\hyphenatedurldiscretionary\empty
-\def\sethyphenatedurlnormal #1{\ctxcommand{hyphenatedurl.setcharacters(\!!bs#1\!!es,0)}}
-\def\sethyphenatedurlbefore #1{\ctxcommand{hyphenatedurl.setcharacters(\!!bs#1\!!es,1)}}
-\def\sethyphenatedurlafter #1{\ctxcommand{hyphenatedurl.setcharacters(\!!bs#1\!!es,2)}}
+\setnewconstant\hyphenatedurllefthyphenmin \plusthree
+\setnewconstant\hyphenatedurlrighthyphenmin\plusthree
-\def\hyphenatedurldiscretionary{}
+\def\lang_url_space {\nobreak\hskip\zeropoint plus\onepoint\nobreak}
+\def\lang_url_after #1{\char#1\discretionary{}{\hyphenatedurlseparator}{}}
+\def\lang_url_before #1{\discretionary{\hyphenatedurlseparator}{}{}\char#1\relax}
+\def\lang_url_normal #1{\char#1\relax}
+\def\lang_url_disc #1{\discretionary{}{}{}}
+
+\def\lang_url_space_trace {\nobreak\begingroup\darkyellow\ruledhskip\zeropoint plus\onepoint\endgroup\nobreak}
+\def\lang_url_after_trace #1{\char#1\hsmash{\darkblue\vl}\discretionary{}{\hyphenatedurlseparator}{}}
+\def\lang_url_before_trace#1{\discretionary{\hyphenatedurlseparator}{}{}\hsmash{\darkred\vl}\char#1\relax}
+\def\lang_url_normal_trace#1{\char#1\relax}
+\def\lang_url_disc_trace #1{\discretionary{\hsmash{\darkgreen\vl}}{\hsmash{\darkgreen\vl}}{\hsmash{\darkgreen\vl}}}
+
+\def\showhyphenatedurlbreaks
+ {\let\lang_url_space \lang_url_space_trace
+ \let\lang_url_after \lang_url_after_trace
+ \let\lang_url_before\lang_url_before_trace
+ \let\lang_url_normal\lang_url_normal_trace
+ \let\lang_url_disc \lang_url_disc_trace}
+
+\def\sethyphenatedurlnormal#1{\ctxcommand{hyphenatedurl.setcharacters(\!!bs#1\!!es,0)}} % Lua names will change
+\def\sethyphenatedurlbefore#1{\ctxcommand{hyphenatedurl.setcharacters(\!!bs#1\!!es,1)}} % Lua names will change
+\def\sethyphenatedurlafter #1{\ctxcommand{hyphenatedurl.setcharacters(\!!bs#1\!!es,2)}} % Lua names will change
% \sethyphenatedurlafter{ABCDEF}
-\setnewconstant\hyphenatedurllefthyphenmin \plusthree
-\setnewconstant\hyphenatedurlrighthyphenmin\plusthree
-
\unexpanded \def\hyphenatedurl#1%
{\dontleavehmode
\begingroup
\the\everyhyphenatedurl
- \let\n\dohyphenatedurlnormal
- \let\b\dohyphenatedurlbefore
- \let\a\dohyphenatedurlafter
- \let\d\dohyphenatedurldisc
+ \normallanguage\zerocount
+ \let\s\lang_url_space
+ \let\a\lang_url_after
+ \let\b\lang_url_before
+ \let\n\lang_url_normal
+ \let\d\lang_url_disc
\normalexpanded{\noexpand\ctxcommand{hyphenatedurl(
\!!bs\noexpand\detokenize{#1}\!!es,
\number\hyphenatedurllefthyphenmin,
diff --git a/Master/texmf-dist/tex/context/base/lang-vn.mkii b/Master/texmf-dist/tex/context/base/lang-vn.mkii
index 27d2a48a16f..e564d989c70 100644
--- a/Master/texmf-dist/tex/context/base/lang-vn.mkii
+++ b/Master/texmf-dist/tex/context/base/lang-vn.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vietnamese,
%D author={Han The Thanh \& Adam Lindsay \& Hans Hagen},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lang-wrd.lua b/Master/texmf-dist/tex/context/base/lang-wrd.lua
index 558d5744faf..3d3cb6aec99 100644
--- a/Master/texmf-dist/tex/context/base/lang-wrd.lua
+++ b/Master/texmf-dist/tex/context/base/lang-wrd.lua
@@ -412,3 +412,9 @@ end
--~ namespace = languagehacks,
--~ processor = languagehacks.process
--~ }
+
+-- interface
+
+commands.enablespellchecking = words.enable
+commands.disablespellchecking = words.disable
+commands.loadspellchecklist = words.load
diff --git a/Master/texmf-dist/tex/context/base/lang-wrd.mkiv b/Master/texmf-dist/tex/context/base/lang-wrd.mkiv
index 22c234d0c6d..6824899121f 100644
--- a/Master/texmf-dist/tex/context/base/lang-wrd.mkiv
+++ b/Master/texmf-dist/tex/context/base/lang-wrd.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Checking,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -27,33 +27,28 @@
% \setupspellchecking[state=start,method=2]
% ...
% \typefile{\jobname.words}
+%
+% beware, maybe some day we will honour grouping
+%
+% 1: spell checking
+% 2: word counting
+% 3: language coloring
-\def\loadspellchecklist
- {\dodoubleempty\doloadspellchecklist}
-
-\def\doloadspellchecklist[#1][#2]%
- {\ctxlua{languages.words.load("#1","#2")}}
-
-\unexpanded\def\setupspellchecking
- {\dosingleargument\dosetupspellchecking}
-
-\newtoks\everysetupspellchecking
+\installcorenamespace{spell}
-\unexpanded\def\setupspellchecking[#1]% todo colors
- {\getparameters[\??wl][#1]%
- \the\everysetupspellchecking}
+\installdirectcommandhandler \??spell {spellchecking}
\appendtoks
- \doifelse\@@wlstate\v!start
- {\ctxlua{languages.words.enable { method = "\@@wlmethod", list = "\@@wllist" }}}
- {\ctxlua{languages.words.disable()}}%
+ \doifelse{\directspellcheckingparameter\c!state}\v!start
+ {\ctxcommand{enablespellchecking { method = "\directspellcheckingparameter\c!method", list = "\directspellcheckingparameter\c!list" }}}
+ {\ctxcommand{disablespellchecking()}}%
\to \everysetupspellchecking
-% beware, maybe some day we will honour grouping
+\unexpanded\def\loadspellchecklist
+ {\dodoubleempty\lang_spellchecking_load_list}
-% 1: spell checking
-% 2: word counting
-% 3: language coloring
+\def\lang_spellchecking_load_list[#1][#2]%
+ {\ctxcommand{loadspellchecklist("#1","#2")}}
\setupspellchecking
[\c!state=\v!stop,
diff --git a/Master/texmf-dist/tex/context/base/layo-ini.mkiv b/Master/texmf-dist/tex/context/base/layo-ini.mkiv
index 46361297851..9097265c9c4 100644
--- a/Master/texmf-dist/tex/context/base/layo-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/layo-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/lpdf-ano.lua b/Master/texmf-dist/tex/context/base/lpdf-ano.lua
index 9f452c34d12..4d0a55f806b 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-ano.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-ano.lua
@@ -6,9 +6,14 @@ if not modules then modules = { } end modules ['lpdf-ano'] = {
license = "see context related readme files"
}
+-- when using rotation: \disabledirectives[refences.sharelinks] (maybe flag links)
+
+-- todo: /AA << WC << ... >> >> : WillClose actions etc
+
local next, tostring = next, tostring
local rep, format = string.rep, string.format
local texcount = tex.count
+local lpegmatch = lpeg.match
local backends, lpdf = backends, lpdf
@@ -20,30 +25,31 @@ local report_reference = logs.reporter("backend","references")
local report_destination = logs.reporter("backend","destinations")
local report_bookmark = logs.reporter("backend","bookmarks")
-local variables = interfaces.variables
-local constants = interfaces.constants
+local variables = interfaces.variables
+local constants = interfaces.constants
-local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_array = utilities.parsers.settings_to_array
-local nodeinjections = backends.pdf.nodeinjections
-local codeinjections = backends.pdf.codeinjections
-local registrations = backends.pdf.registrations
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
-local javascriptcode = interactions.javascripts.code
+local javascriptcode = interactions.javascripts.code
-local references = structures.references
-local bookmarks = structures.bookmarks
+local references = structures.references
+local bookmarks = structures.bookmarks
-local runners = references.runners
-local specials = references.specials
-local handlers = references.handlers
-local executers = references.executers
+local runners = references.runners
+local specials = references.specials
+local handlers = references.handlers
+local executers = references.executers
+local getinnermethod = references.getinnermethod
-local nodepool = nodes.pool
+local nodepool = nodes.pool
-local pdfannotation_node = nodepool.pdfannotation
-local pdfdestination_node = nodepool.pdfdestination
-local latelua_node = nodepool.latelua
+local pdfannotation_node = nodepool.pdfannotation
+local pdfdestination_node = nodepool.pdfdestination
+local latelua_node = nodepool.latelua
local pdfdictionary = lpdf.dictionary
local pdfarray = lpdf.array
@@ -52,29 +58,26 @@ local pdfunicode = lpdf.unicode
local pdfconstant = lpdf.constant
local pdfflushobject = lpdf.flushobject
local pdfshareobjectreference = lpdf.shareobjectreference
-local pdfimmediateobject = lpdf.immediateobject
local pdfreserveobject = lpdf.reserveobject
local pdfpagereference = lpdf.pagereference
local pdfdelayedobject = lpdf.delayedobject
local pdfregisterannotation = lpdf.registerannotation
-local pdf_annot = pdfconstant("Annot")
-local pdf_uri = pdfconstant("URI")
-local pdf_gotor = pdfconstant("GoToR")
-local pdf_goto = pdfconstant("GoTo")
-local pdf_launch = pdfconstant("Launch")
-local pdf_javascript = pdfconstant("JavaScript")
-local pdf_link = pdfconstant("Link")
-local pdf_n = pdfconstant("N")
-local pdf_t = pdfconstant("T")
-local pdf_fit = pdfconstant("Fit")
-local pdf_named = pdfconstant("Named")
-
-- todo: 3dview
-local pdf_border = pdfarray { 0, 0, 0 }
+local pdf_annot = pdfconstant("Annot")
+local pdf_uri = pdfconstant("URI")
+local pdf_gotor = pdfconstant("GoToR")
+local pdf_goto = pdfconstant("GoTo")
+local pdf_launch = pdfconstant("Launch")
+local pdf_javascript = pdfconstant("JavaScript")
+local pdf_link = pdfconstant("Link")
+local pdf_n = pdfconstant("N")
+local pdf_t = pdfconstant("T")
+local pdf_fit = pdfconstant("Fit")
+local pdf_named = pdfconstant("Named")
-local getinnermethod = references.getinnermethod
+local pdf_border = pdfarray { 0, 0, 0 }
local cache = { }
@@ -146,7 +149,7 @@ local function link(url,filename,destination,page,actions)
pdf_fit,
}
}
- else
+ elseif trace_references then
report_reference("invalid page reference: %s",tostring(page))
end
end
@@ -181,7 +184,6 @@ end
local function pdfaction(actions)
local nofactions = #actions
- texcount.referencepagestate = 0 -- goodie, as we do all in the backend, we need to set it here too
if nofactions > 0 then
local a = actions[1]
local action = runners[a.kind]
@@ -245,7 +247,7 @@ local function use_normal_annotations()
end
--- evenrually we can do this for special refs only
+-- eventually we can do this for special refs only
local hashed, nofunique, nofused = { }, 0, 0
@@ -257,7 +259,7 @@ local function use_shared_annotations()
local h, v = pdf.h, pdf.v
local llx, lly = h*factor, (v - depth)*factor
local urx, ury = (h + width)*factor, (v + height)*factor
- local annot = format("<< /Type /Annot %s /Rect [%0.2f %0.2f %0.2f %0.2f] >>",prerolled,llx,lly,urx,ury)
+ local annot = format("<< /Type /Annot %s /Rect [%0.3f %0.3f %0.3f %0.3f] >>",prerolled,llx,lly,urx,ury)
local n = hashed[annot]
if not n then
n = pdfdelayedobject(annot)
@@ -283,7 +285,7 @@ local function use_shared_annotations()
statistics.register("pdf annotations", function()
if nofused > 0 then
-- table.print(hashed,"hashed_annotations")
- return string.format("%s embedded, %s unique",nofused,nofunique)
+ return format("%s embedded, %s unique",nofused,nofunique)
else
return nil
end
@@ -326,10 +328,15 @@ end
runners["inner"] = function(var,actions)
if getinnermethod() == "names" then
- local vir = var.i.references
- local internal = vir and vir.internal
- if internal then
- var.inner = "aut:" .. internal
+ local vi = var.i
+ if vi then
+ local vir = vi.references
+ if vir then
+ local internal = vir.internal
+ if internal then
+ var.inner = "aut:" .. internal
+ end
+ end
end
else
var.inner = nil
@@ -348,7 +355,7 @@ runners["outer"] = function(var,actions)
end
runners["outer with inner"] = function(var,actions)
- local file = references.checkedfile(var.f)
+ local file = references.checkedfile(var.outer) -- was var.f but fails ... why
return link(nil,file,var.inner,var.r,actions)
end
@@ -392,10 +399,12 @@ runners["special operation with arguments"] = runners["special"]
function specials.internal(var,actions) -- better resolve in strc-ref
local i = tonumber(var.operation)
- local v = references.internals[i]
+ local v = i and references.internals[i]
+--~ print(">>>>>>>",i)
+--~ inspect(v)
if not v then
-- error
- report_reference("no internal reference '%s'",var.operation)
+ report_reference("no internal reference '%s'",i or "?")
elseif getinnermethod() == "names" then
-- named
return link(nil,nil,"aut:"..i,v.references.realpage,actions)
@@ -423,8 +432,11 @@ function specials.page(var,actions)
if type(p) == "function" then -- double
p = p()
else
- p = tonumber(references.realpageofpage(tonumber(o)))
+ p = references.realpageofpage(tonumber(p))
end
+ -- if p then
+ -- var.r = p
+ -- end
end
return link(nil,nil,nil,p or var.operation,actions)
end
@@ -448,12 +460,42 @@ function specials.userpage(var,actions)
else
local p = var.r
if not p then -- todo: call special from reference code
- p = tonumber(references.realpageofpage(var.operation))
+ p = var.operation
+ if p then -- no function and special check here. only numbers
+ p = references.realpageofpage(tonumber(p))
+ end
+ -- if p then
+ -- var.r = p
+ -- end
end
+ return link(nil,nil,nil,p or var.operation,actions)
+ end
+end
+
+function specials.deltapage(var,actions)
+ local p = tonumber(var.operation)
+ if p then
+ p = references.checkedrealpage(p + texcount.realpageno)
return link(nil,nil,nil,p,actions)
end
end
+-- sections
+
+--~ function specials.section(var,actions)
+--~ local sectionname = var.operation
+--~ local destination = var.arguments
+--~ local internal = structures.sections.internalreference(sectionname,destination)
+--~ if internal then
+--~ var.special = "internal"
+--~ var.operation = internal
+--~ var.arguments = nil
+--~ specials.internal(var,actions)
+--~ end
+--~ end
+
+specials.section = specials.internal -- specials.section just need to have a value as it's checked
+
-- todo, do this in references namespace ordered instead (this is an experiment)
local splitter = lpeg.splitat(":")
@@ -462,7 +504,7 @@ function specials.order(var,actions) -- references.specials !
local operation = var.operation
if operation then
local kind, name, n = lpegmatch(splitter,operation)
- local order = lists.ordered[kind]
+ local order = structures.lists.ordered[kind]
order = order and order[name]
local v = order[tonumber(n)]
local r = v and v.references.realpage
@@ -563,9 +605,11 @@ function executers.submitform(arguments)
}
end
+local pdf_hide = pdfconstant("Hide")
+
function executers.hide(arguments)
return pdfdictionary {
- S = pdfconstant("Hide"),
+ S = pdf_hide,
H = true,
T = arguments,
}
@@ -573,7 +617,7 @@ end
function executers.show(arguments)
return pdfdictionary {
- S = pdfconstant("Hide"),
+ S = pdf_hide,
H = false,
T = arguments,
}
@@ -617,7 +661,7 @@ function specials.action(var)
end
--~ entry.A = pdfdictionary {
---~ S = pdfconstant("GoTo"),
+--~ S = pdf_goto,
--~ D = ....
--~ }
diff --git a/Master/texmf-dist/tex/context/base/lpdf-col.lua b/Master/texmf-dist/tex/context/base/lpdf-col.lua
index dc40e555c2f..0c2a49ebef2 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-col.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-col.lua
@@ -6,10 +6,29 @@ if not modules then modules = { } end modules ['lpdf-mis'] = {
license = "see context related readme files"
}
-local type = type
-local format, gsub = string.format, string.gsub
+local type, next, tostring = type, next, tostring
+local char, byte, format, gsub, rep, gmatch = string.char, string.byte, string.format, string.gsub, string.rep, string.gmatch
+local concat = table.concat
+local round = math.round
-local backends, lpdf = backends, lpdf
+local backends, lpdf, nodes = backends, lpdf, nodes
+
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local nodepool = nodes.pool
+local register = nodepool.register
+local pdfliteral = nodepool.pdfliteral
+
+local pdfconstant = lpdf.constant
+local pdfstring = lpdf.string
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfverbose = lpdf.verbose
+local pdfflushobject = lpdf.flushobject
+local pdfflushstreamobject = lpdf.flushstreamobject
local colors = attributes.colors
local transparencies = attributes.transparencies
@@ -19,6 +38,432 @@ local colorsvalue = colors.value
local transparenciesvalue = transparencies.value
local forcedmodel = colors.forcedmodel
+local c_transparency = pdfconstant("Transparency")
+
+local report_color = logs.reporter("colors","backend")
+
+-- page groups (might move to lpdf-ini.lua)
+
+local colorspaceconstants = { -- v_none is ignored
+ gray = pdfconstant("DeviceGray"),
+ rgb = pdfconstant("DeviceRGB"),
+ cmyk = pdfconstant("DeviceCMYK"),
+ all = pdfconstant("DeviceRGB"), -- brr
+}
+
+local transparencygroups = { }
+
+lpdf.colorspaceconstants = colorspaceconstants
+lpdf.transparencygroups = transparencygroups
+
+table.setmetatableindex(transparencygroups, function(transparencygroups,colormodel)
+ local cs = colorspaceconstants[colormodel]
+ if cs then
+ local g = pdfreference(pdfflushobject(pdfdictionary {
+ S = c_transparency,
+ CS = cs,
+ I = true,
+ }))
+ transparencygroups[colormodel] = g
+ return g
+ else
+ transparencygroups[colormodel] = false
+ return false
+ end
+end)
+
+local currentgroupcolormodel
+
+local function addpagegroup()
+ if currentgroupcolormodel then
+ local g = transparencygroups[currentgroupcolormodel]
+ if g then
+ lpdf.addtopageattributes("Group",g)
+ end
+ end
+end
+
+lpdf.registerpagefinalizer(addpagegroup,3,"pagegroup")
+
+local function synchronizecolormodel(model)
+ currentgroupcolormodel = model
+end
+
+backends.codeinjections.synchronizecolormodel = synchronizecolormodel
+commands.synchronizecolormodel = synchronizecolormodel
+
+-- injection code (needs a bit reordering)
+
+-- color injection
+
+function nodeinjections.rgbcolor(r,g,b)
+ return register(pdfliteral(format("%s %s %s rg %s %s %s RG",r,g,b,r,g,b)))
+end
+
+function nodeinjections.cmykcolor(c,m,y,k)
+ return register(pdfliteral(format("%s %s %s %s k %s %s %s %s K",c,m,y,k,c,m,y,k)))
+end
+
+function nodeinjections.graycolor(s) -- caching 0/1 does not pay off
+ return register(pdfliteral(format("%s g %s G",s,s)))
+end
+
+function nodeinjections.spotcolor(n,f,d,p)
+ if type(p) == "string" then
+ p = gsub(p,","," ") -- brr misuse of spot
+ end
+ return register(pdfliteral(format("/%s cs /%s CS %s SCN %s scn",n,n,p,p)))
+end
+
+function nodeinjections.transparency(n)
+ return register(pdfliteral(format("/Tr%s gs",n)))
+end
+
+-- a bit weird but let's keep it here for a while
+
+local effects = {
+ normal = 0,
+ inner = 0,
+ outer = 1,
+ both = 2,
+ hidden = 3,
+}
+
+local bp = number.dimenfactors.bp
+
+function nodeinjections.effect(effect,stretch,rulethickness)
+ -- always, no zero test (removed)
+ rulethickness = bp * rulethickness
+ effect = effects[effect] or effects['normal']
+ return register(pdfliteral(format("%s Tc %s w %s Tr",stretch,rulethickness,effect))) -- watch order
+end
+
+-- spot- and indexcolors
+
+local pdf_separation = pdfconstant("Separation")
+local pdf_indexed = pdfconstant("Indexed")
+local pdf_device_n = pdfconstant("DeviceN")
+local pdf_device_rgb = pdfconstant("DeviceRGB")
+local pdf_device_cmyk = pdfconstant("DeviceCMYK")
+local pdf_device_gray = pdfconstant("DeviceGray")
+local pdf_extgstate = pdfconstant("ExtGState")
+
+local pdf_rbg_range = pdfarray { 0, 1, 0, 1, 0, 1 }
+local pdf_cmyk_range = pdfarray { 0, 1, 0, 1, 0, 1, 0, 1 }
+local pdf_gray_range = pdfarray { 0, 1 }
+
+local rgb_function = "dup %s mul exch dup %s mul exch %s mul"
+local cmyk_function = "dup %s mul exch dup %s mul exch dup %s mul exch %s mul"
+local gray_function = "%s mul"
+
+local documentcolorspaces = pdfdictionary()
+
+local spotcolorhash = { } -- not needed
+local spotcolornames = { }
+local indexcolorhash = { }
+local delayedindexcolors = { }
+
+function registrations.spotcolorname(name,e)
+ spotcolornames[name] = e or name
+end
+
+function registrations.getspotcolorreference(name)
+ return spotcolorhash[name]
+end
+
+-- beware: xpdf/okular/evince cannot handle the spot->process shade
+
+-- This should become delayed i.e. only flush when used; in that case we need
+-- need to store the specification and then flush them when accesssomespotcolor
+-- is called. At this moment we assume that splotcolors that get defined are
+-- also used which keeps the overhad small anyway.
+
+local processcolors
+
+local function registersomespotcolor(name,noffractions,names,p,colorspace,range,funct)
+ noffractions = tonumber(noffractions) or 1 -- to be checked
+ if noffractions == 0 then
+ -- can't happen
+ elseif noffractions == 1 then
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = { 0, 1 },
+ Range = range,
+ }
+ local calculations = pdfflushstreamobject(format("{ %s }",funct),dictionary)
+ -- local calculations = pdfobject {
+ -- type = "stream",
+ -- immediate = true,
+ -- string = format("{ %s }",funct),
+ -- attr = dictionary(),
+ -- }
+ local array = pdfarray {
+ pdf_separation,
+ pdfconstant(spotcolornames[name] or name),
+ colorspace,
+ pdfreference(calculations),
+ }
+ local m = pdfflushobject(array)
+ local mr = pdfreference(m)
+ spotcolorhash[name] = m
+ documentcolorspaces[name] = mr
+ lpdf.adddocumentcolorspace(name,mr)
+ else
+ local cnames = pdfarray()
+ local domain = pdfarray()
+ local colorants = pdfdictionary()
+ for n in gmatch(names,"[^,]+") do
+ local name = spotcolornames[n] or n
+ if n == "cyan" then
+ name = "Cyan"
+ elseif n == "magenta" then
+ name = "Magenta"
+ elseif n == "yellow" then
+ name = "Yellow"
+ elseif n == "black" then
+ name = "Black"
+ else
+ local sn = spotcolorhash[name] or spotcolorhash[n]
+ if sn then
+ colorants[name] = pdfreference(sn)
+ else
+ report_color("unknown colorant %s, using black instead",name or n)
+ name = "Black"
+ end
+ end
+ cnames[#cnames+1] = pdfconstant(name)
+ domain[#domain+1] = 0
+ domain[#domain+1] = 1
+ end
+ if not processcolors then
+ local specification = pdfdictionary {
+ ColorSpace = pdfconstant("DeviceCMYK"),
+ Components = pdfarray {
+ pdfconstant("Cyan"),
+ pdfconstant("Magenta"),
+ pdfconstant("Yellow"),
+ pdfconstant("Black")
+ }
+ }
+ processcolors = pdfreference(pdfflushobject(specification))
+ end
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = domain,
+ Range = range,
+ }
+ local calculation = pdfflushstreamobject(format("{ %s %s }",rep("pop ",noffractions),funct),dictionary)
+ local channels = pdfdictionary {
+ Subtype = pdfconstant("NChannel"),
+ Colorants = colorants,
+ Process = processcolors,
+ }
+ local array = pdfarray {
+ pdf_device_n,
+ cnames,
+ colorspace,
+ pdfreference(calculation),
+ lpdf.shareobjectreference(tostring(channels)), -- optional but needed for shades
+ }
+ local m = pdfflushobject(array)
+ local mr = pdfreference(m)
+ spotcolorhash[name] = m
+ documentcolorspaces[name] = mr
+ lpdf.adddocumentcolorspace(name,mr)
+ end
+end
+
+-- wrong name
+
+local function registersomeindexcolor(name,noffractions,names,p,colorspace,range,funct)
+ noffractions = tonumber(noffractions) or 1 -- to be checked
+ local cnames = pdfarray()
+ local domain = pdfarray()
+ if names == "" then
+ names = name .. ",None"
+ else
+ names = names .. ",None"
+ end
+ for n in gmatch(names,"[^,]+") do
+ cnames[#cnames+1] = pdfconstant(spotcolornames[n] or n)
+ domain[#domain+1] = 0
+ domain[#domain+1] = 1
+ end
+ local dictionary = pdfdictionary {
+ FunctionType = 4,
+ Domain = domain,
+ Range = range,
+ }
+ local n = pdfflushstreamobject(format("{ %s %s }",rep("exch pop ",noffractions),funct),dictionary) -- exch pop
+ local a = pdfarray {
+ pdf_device_n,
+ cnames,
+ colorspace,
+ pdfreference(n),
+ }
+ if p == "" then
+ p = "1"
+ else
+ p = p .. ",1"
+ end
+ local pi = { }
+ for pp in gmatch(p,"[^,]+") do
+ pi[#pi+1] = tonumber(pp)
+ end
+ local vector, set, n = { }, { }, #pi
+ for i=255,0,-1 do
+ for j=1,n do
+ set[j] = format("%02X",round(pi[j]*i))
+ end
+ vector[#vector+1] = concat(set)
+ end
+ vector = pdfverbose { "<", concat(vector, " "), ">" }
+ local n = pdfflushobject(pdfarray{ pdf_indexed, a, 255, vector })
+ lpdf.adddocumentcolorspace(format("%s_indexed",name),pdfreference(n))
+ return n
+end
+
+-- actually, names (parent) is the hash
+
+local function delayindexcolor(name,names,func)
+ local hash = (names ~= "" and names) or name
+ delayedindexcolors[hash] = func
+end
+
+local function indexcolorref(name) -- actually, names (parent) is the hash
+ if not indexcolorhash[name] then
+ local delayedindexcolor = delayedindexcolors[name]
+ if type(delayedindexcolor) == "function" then
+ indexcolorhash[name] = delayedindexcolor()
+ delayedindexcolors[name] = true
+ end
+ end
+ return indexcolorhash[name]
+end
+
+function registrations.rgbspotcolor(name,noffractions,names,p,r,g,b)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,format(rgb_function,r,g,b))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rbg_range,format("%s %s %s",r,g,b))
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,format(rgb_function,r,g,b))
+ end)
+end
+
+function registrations.cmykspotcolor(name,noffractions,names,p,c,m,y,k)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format("%s %s %s %s",c,m,y,k))
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
+ end)
+end
+
+function registrations.grayspotcolor(name,noffractions,names,p,s)
+ if noffractions == 1 then
+ registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,format(gray_function,s))
+ else
+ registersomespotcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,s)
+ end
+ delayindexcolor(name,names,function()
+ return registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,format(gray_function,s))
+ end)
+end
+
+function registrations.rgbindexcolor(name,noffractions,names,p,r,g,b)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_rgb,pdf_rgb_range,format(rgb_function,r,g,b))
+end
+
+function registrations.cmykindexcolor(name,noffractions,names,p,c,m,y,k)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_cmyk,pdf_cmyk_range,format(cmyk_function,c,m,y,k))
+end
+
+function registrations.grayindexcolor(name,noffractions,names,p,s)
+ registersomeindexcolor(name,noffractions,names,p,pdf_device_gray,pdf_gray_range,gray_function)
+end
+
+function codeinjections.setfigurecolorspace(data,figure)
+ local color = data.request.color
+ if color then
+ local ref = indexcolorref(color)
+ if ref then
+ figure.colorspace = ref
+ data.used.color = color
+ end
+ end
+end
+
+-- transparency
+
+local transparencies = { [0] =
+ pdfconstant("Normal"),
+ pdfconstant("Normal"),
+ pdfconstant("Multiply"),
+ pdfconstant("Screen"),
+ pdfconstant("Overlay"),
+ pdfconstant("SoftLight"),
+ pdfconstant("HardLight"),
+ pdfconstant("ColorDodge"),
+ pdfconstant("ColorBurn"),
+ pdfconstant("Darken"),
+ pdfconstant("Lighten"),
+ pdfconstant("Difference"),
+ pdfconstant("Exclusion"),
+ pdfconstant("Hue"),
+ pdfconstant("Saturation"),
+ pdfconstant("Color"),
+ pdfconstant("Luminosity"),
+ pdfconstant("Compatible"), -- obsolete; 'Normal' is used in this case
+}
+
+local documenttransparencies = { }
+local transparencyhash = { } -- share objects
+
+local done, signaled = false, false
+
+function registrations.transparency(n,a,t)
+ if not done then
+ local d = pdfdictionary {
+ Type = pdf_extgstate,
+ ca = 1,
+ CA = 1,
+ BM = transparencies[1],
+ AIS = false,
+ }
+ local m = pdfflushobject(d)
+ local mr = pdfreference(m)
+ transparencyhash[0] = m
+ documenttransparencies[0] = mr
+ lpdf.adddocumentextgstate("Tr0",mr)
+ done = true
+ end
+ if n > 0 and not transparencyhash[n] then
+ local d = pdfdictionary {
+ Type = pdf_extgstate,
+ ca = tonumber(t),
+ CA = tonumber(t),
+ BM = transparencies[tonumber(a)] or transparencies[0],
+ AIS = false,
+ }
+ local m = pdfflushobject(d)
+ local mr = pdfreference(m)
+ transparencyhash[n] = m
+ documenttransparencies[n] = mr
+ lpdf.adddocumentextgstate(format("Tr%s",n),mr)
+ end
+end
+
+statistics.register("page group warning", function()
+ if done and not transparencygroups[currentgroupcolormodel] then
+ return format("transparencies are used but no pagecolormodel is set")
+ end
+end)
+
+
-- Literals needed to inject code in the mp stream, we cannot use attributes there
-- since literals may have qQ's, much may go away once we have mplib code in place.
--
@@ -59,6 +504,29 @@ end
lpdf.color = lpdfcolor
+function lpdf.colorspec(model,ca,default)
+ if ca and ca > 0 then
+ local cv = colors.value(ca)
+ if cv then
+ if model == 1 then
+ model = cv[1]
+ end
+ if model == 2 then
+ return pdfarray { cv[2] }
+ elseif model == 3 then
+ return pdfarray { cv[3],cv[4],cv[5] }
+ elseif model == 4 then
+ return pdfarray { cv[6],cv[7],cv[8],cv[9] }
+ elseif model == 5 then
+ return pdfarray { cv[13] }
+ end
+ end
+ end
+ if default then
+ return default
+ end
+end
+
function lpdf.pdfcolor(attribute) -- bonus, for pgf and friends
context(lpdfcolor(1,attribute))
end
@@ -214,6 +682,7 @@ function lpdf.transparencycode(a,t)
return ""
end
end
+
function lpdf.finishtransparencycode()
if transparencies.supported and intransparency then
intransparency = false
@@ -230,8 +699,21 @@ backends.pdf.tables.vfspecials = { -- todo: distinguish between glyph and rule c
red = { "special", 'pdf: 1 0 0 rg 1 0 0 RG' },
green = { "special", 'pdf: 0 1 0 rg 0 1 0 RG' },
blue = { "special", 'pdf: 0 0 1 rg 0 0 1 RG' },
+ gray = { "special", 'pdf: .75 g .75 G' },
black = { "special", 'pdf: 0 g 0 G' },
+ rulecolors = {
+ red = { "special", 'pdf: 1 0 0 rg' },
+ green = { "special", 'pdf: 0 1 0 rg' },
+ blue = { "special", 'pdf: 0 0 1 rg' },
+ gray = { "special", 'pdf: .5 g' },
+ black = { "special", 'pdf: 0 g' },
+ palered = { "special", 'pdf: 1 .75 .75 rg' },
+ palegreen = { "special", 'pdf: .75 1 .75 rg' },
+ paleblue = { "special", 'pdf: .75 .75 1 rg' },
+ palegray = { "special", 'pdf: .75 g' },
+ },
+
startslant = function(a) return { "special", format("pdf: q 1 0 %s 1 0 0 cm",a) } end,
stopslant = { "special", "pdf: Q" },
diff --git a/Master/texmf-dist/tex/context/base/lpdf-epa.lua b/Master/texmf-dist/tex/context/base/lpdf-epa.lua
index 17c55eb0c90..c8d23a61825 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-epa.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-epa.lua
@@ -10,7 +10,7 @@ if not modules then modules = { } end modules ['lpdf-epa'] = {
-- change.
local type, tonumber = type, tonumber
-local format = string.format
+local format, gsub = string.format, string.gsub
local trace_links = false trackers.register("figures.links", function(v) trace_links = v end)
@@ -171,12 +171,11 @@ function codeinjections.mergeviewerlayers(specification)
local layers = document.layers
if layers then
for i=1,layers.n do
- local tag = layers[i]
-tag = namespace .. string.gsub(tag," ",":")
-local title = tag
-if trace_links then
- report_link("using layer '%s'",tag)
-end
+ local tag = namespace .. gsub(layers[i]," ",":")
+ local title = tag
+ if trace_links then
+ report_link("using layer '%s'",tag)
+ end
attributes.viewerlayers.define { -- also does some cleaning
tag = tag, -- todo: #3A or so
title = title,
diff --git a/Master/texmf-dist/tex/context/base/lpdf-epd.lua b/Master/texmf-dist/tex/context/base/lpdf-epd.lua
index 19c1f9bd8d9..76d258cefdf 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-epd.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-epd.lua
@@ -23,8 +23,25 @@ if not modules then modules = { } end modules ['lpdf-epd'] = {
-- We cannot access all destinations in one run.
local setmetatable, rawset, rawget, tostring, tonumber = setmetatable, rawset, rawget, tostring, tonumber
-local lower, match, char = string.lower, string.match, string.char
+local lower, match, char, find, sub = string.lower, string.match, string.char, string.find, string.sub
local concat = table.concat
+local toutf = string.toutf
+
+-- a bit of protection
+
+local limited = false
+
+directives.register("system.inputmode", function(v)
+ if not limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ epdf.open = i_limiter.protect(epdf.open)
+ limited = true
+ end
+ end
+end)
+
+--
function epdf.type(o)
local t = lower(match(tostring(o),"[^ :]+"))
@@ -51,8 +68,10 @@ local function prepare(document,d,t,n,k)
--
else
c = checked_access[v:getTypeName()](v,document,r)
- document.cache[r] = c
- document.xrefs[c] = r
+ if c then
+ document.cache[r] = c
+ document.xrefs[c] = r
+ end
end
t[d:getKey(i)] = c
end
@@ -149,7 +168,7 @@ checked_access = {
return v:getNum()
end,
string = function(v)
- return v:getString()
+ return toutf(v:getString())
end,
boolean = function(v)
return v:getBool()
@@ -241,7 +260,8 @@ local function getpages(document)
local cata = data:getCatalog()
local xref = data:getXRef()
local pages = { }
- for pagenumber=1,cata:getNumPages() do
+ local nofpages = cata:getNumPages()
+ for pagenumber=1,nofpages do
local pagereference = cata:getPageRef(pagenumber).num
local pagedata = some_dictionary(xref:fetch(pagereference,0):getDict(),document,pagereference)
pagedata.number = pagenumber
@@ -249,6 +269,7 @@ local function getpages(document)
xrefs[pagedata] = pagereference
cache[pagereference] = pagedata
end
+ pages.n = nofpages
return pages
end
@@ -281,14 +302,16 @@ function lpdf.epdf.load(filename)
data = data,
}
local Catalog = some_dictionary(data:getXRef():getCatalog():getDict(),document)
+ local Info = some_dictionary(data:getXRef():getDocInfo():getDict(),document)
document.Catalog = Catalog
+ document.Info = Info
-- document.catalog = Catalog
-- a few handy helper tables
document.pages = delayed(document,"pages", function() return getpages(document) end)
- document.destinations = delayed(document,"destinations", function() return getnames(document,Catalog.Names.Dests) end)
- document.javascripts = delayed(document,"javascripts", function() return getnames(document,Catalog.Names.JS) end)
- document.widgets = delayed(document,"widgets", function() return getnames(document,Catalog.Names.AcroForm) end)
- document.embeddedfiles = delayed(document,"embeddedfiles",function() return getnames(document,Catalog.Names.EmbeddedFiles) end)
+ document.destinations = delayed(document,"destinations", function() return getnames(document,Catalog.Names and Catalog.Names.Dests) end)
+ document.javascripts = delayed(document,"javascripts", function() return getnames(document,Catalog.Names and Catalog.Names.JS) end)
+ document.widgets = delayed(document,"widgets", function() return getnames(document,Catalog.Names and Catalog.Names.AcroForm) end)
+ document.embeddedfiles = delayed(document,"embeddedfiles",function() return getnames(document,Catalog.Names and Catalog.Names.EmbeddedFiles) end)
document.layers = delayed(document,"layers", function() return getlayers(document) end)
else
document = false
diff --git a/Master/texmf-dist/tex/context/base/lpdf-fld.lua b/Master/texmf-dist/tex/context/base/lpdf-fld.lua
index 590aee1abe5..30052538d85 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-fld.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-fld.lua
@@ -18,6 +18,42 @@ if not modules then modules = { } end modules ['lpdf-fld'] = {
-- generated) MK behaviour built in. So ... hard to test. Unfortunately
-- not even the default appearance is generated. This will probably be
-- solved at some point.
+--
+-- Also, for some reason the viewer does not always show custom appearances
+-- when fields are being rolled over or clicked upon, and circles or checks
+-- pop up when you don't expect them. I fear that this kind of instability
+-- eventually will kill pdf forms. After all, the manual says: "individual
+-- annotation handlers may ignore this entry and provide their own appearances"
+-- and one might wonder what 'individual' means here, but effectively this
+-- renders the whole concept of appearances useless.
+--
+-- Okay, here is one observation. A pdf file contains objects and one might
+-- consider each one to be a static entity when read in. However, acrobat
+-- starts rendering and seems to manipulate (appearance streams) of objects
+-- in place (this is visible when the file is saved again). And, combined
+-- with some other caching and hashing, this might give side effects for
+-- shared objects. So, it seems that for some cases one can best be not too
+-- clever and not share but duplicate information. Of course this defeats the
+-- whole purpose of these objects. Of course I can be wrong.
+--
+-- A rarther weird side effect of the viewer is that the highlighting of fields
+-- obscures values, unless you uses one of the BS variants, and this makes
+-- custum appearances rather useless as there is no way to control this apart
+-- from changing the viewer preferences. It could of course be a bug but it would
+-- be nice if the highlighting was at least transparent. I have no clue why the
+-- built in shapes work ok (some xform based appearances are generated) while
+-- equally valid other xforms fail. It looks like acrobat appearances come on
+-- top (being refered to in the MK) while custom ones are behind the highlight
+-- rectangle. One can disable the "Show border hover color for fields" option
+-- in the preferences. If you load java-imp-rhh this side effect gets disabled
+-- and you get what you expect (it took me a while to figure out this hack).
+--
+-- When highlighting is enabled, those default symbols flash up, so it looks
+-- like we have some inteference between this setting and custom appearances.
+--
+-- Anyhow, the NeedAppearances is really needed in order to get a rendering
+-- for printing especially when highlighting (those colorfull foregrounds) is
+-- on.
local gmatch, lower, format = string.gmatch, string.lower, string.format
local lpegmatch = lpeg.match
@@ -53,7 +89,6 @@ local pdfstring = lpdf.string
local pdfconstant = lpdf.constant
local pdftoeight = lpdf.toeight
local pdfflushobject = lpdf.flushobject
-local pdfimmediateobject = lpdf.immediateobject
local pdfshareobjectreference = lpdf.shareobjectreference
local pdfshareobject = lpdf.shareobject
local pdfreserveobject = lpdf.reserveobject
@@ -72,7 +107,7 @@ local pdf_widget = pdfconstant("Widget")
local pdf_tx = pdfconstant("Tx")
local pdf_ch = pdfconstant("Ch")
local pdf_btn = pdfconstant("Btn")
-local pdf_yes = pdfconstant("Yes")
+----- pdf_yes = pdfconstant("Yes")
local pdf_off = pdfconstant("Off")
local pdf_p = pdfconstant("P") -- None Invert Outline Push
local pdf_n = pdfconstant("N") -- None Invert Outline Push
@@ -89,31 +124,40 @@ function codeinjections.setformsmethod(name)
submitoutputformat = formats[lower(name)] or formats.xml
end
-local flag = {
- MultiLine = 4096, -- 13
- NoToggleToOff = 16384, -- 15
- Radio = 32768, -- 16
- PushButton = 65536, -- 17
- PopUp = 131072, -- 18
- Edit = 262144, -- 19
- RadiosInUnison = 33554432, -- 26
- DoNotSpellCheck = 4194304, -- 23
- DoNotScroll = 8388608, -- 24
- ReadOnly = 1, -- 1
- Required = 2, -- 2
- NoExport = 4, -- 3
- Password = 8192, -- 14
- Sort = 524288, -- 20
- FileSelect = 1048576, -- 21
+local flag = { -- /Ff
+ ReadOnly = 1, -- 1
+ Required = 2, -- 2
+ NoExport = 4, -- 3
+ MultiLine = 4096, -- 13
+ Password = 8192, -- 14
+ NoToggleToOff = 16384, -- 15
+ Radio = 32768, -- 16
+ PushButton = 65536, -- 17
+ PopUp = 131072, -- 18
+ Edit = 262144, -- 19
+ Sort = 524288, -- 20
+ FileSelect = 1048576, -- 21
+ DoNotSpellCheck = 4194304, -- 23
+ DoNotScroll = 8388608, -- 24
+ Comb = 16777216, -- 25
+ RichText = 33554432, -- 26
+ RadiosInUnison = 33554432, -- 26
+ CommitOnSelChange = 67108864, -- 27
}
-local plus = {
- Invisible = 1, -- 1
- Hidden = 2, -- 2
- Printable = 4, -- 3
- NoView = 32, -- 6
- ToggleNoView = 256, -- 9
- AutoView = 256, -- 288 (6+9)
+local plus = { -- /F
+ Invisible = 1, -- 1
+ Hidden = 2, -- 2
+ Printable = 4, -- 3
+ Print = 4, -- 3
+ NoZoom = 8, -- 4
+ NoRotate = 16, -- 5
+ NoView = 32, -- 6
+ ReadOnly = 64, -- 7
+ Locked = 128, -- 8
+ ToggleNoView = 256, -- 9
+ LockedContents = 512, -- 10,
+ AutoView = 256, -- 288 (6+9)
}
-- todo: check what is interfaced
@@ -133,7 +177,7 @@ plus.auto = plus.AutoView
-- some day .. lpeg with function or table
-local function fieldflag(specification)
+local function fieldflag(specification) -- /Ff
local o, n = specification.option, 0
if o and o ~= "" then
for f in gmatch(o,"[^, ]+") do
@@ -143,13 +187,14 @@ local function fieldflag(specification)
return n
end
-local function fieldplus(specification)
+local function fieldplus(specification) -- /F
local o, n = specification.option, 0
if o and o ~= "" then
for p in gmatch(o,"[^, ]+") do
n = n + (plus[p] or 0)
end
end
+-- n = n + 4
return n
end
@@ -311,11 +356,17 @@ local function fieldappearances(specification)
N = registeredsymbol(n), R = registeredsymbol(r), D = registeredsymbol(d),
}
return pdfshareobjectreference(appearance)
+-- return pdfreference(pdfflushobject(appearance))
end
local YesorOn = "Yes" -- somehow On is not always working out well any longer (why o why this change)
-local function fieldstates(specification,forceyes,values,default)
+-- beware ... maybe we should have unique /Yes1 ... we will probably
+-- change this one too.
+--
+-- TODO: the same as radio .. play safe and use different names.
+
+local function fieldstates_check(specification,forceyes,values,default,yesdefault)
-- we don't use Opt here (too messy for radio buttons)
local values, default = values or specification.values, default or specification.default
if not values or values == "" then
@@ -354,13 +405,13 @@ local function fieldstates(specification,forceyes,values,default)
offn, offr, offd = off[1], off[2], off[3]
end
if not yesvalue then
- yesvalue = yesn
+ yesvalue = yesdefault or yesn
end
if not offvalue then
offvalue = offn
end
if forceyes == true then
- forceyes = forceyes and YesorOn -- spec likes Yes more but we've used On for ages now
+ forceyes = YesorOn -- spec likes Yes more but we've used On for ages now
else
-- false or string
end
@@ -369,12 +420,106 @@ local function fieldstates(specification,forceyes,values,default)
else
default = pdf_off
end
- local appearance = pdfdictionary { -- maybe also cache components
- N = pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) },
- R = pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) },
- D = pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }
- }
+ local appearance
+ if false then -- needs testing
+ appearance = pdfdictionary { -- maybe also cache components
+ N = pdfshareobjectreference(pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) }),
+ R = pdfshareobjectreference(pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) }),
+ D = pdfshareobjectreference(pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }),
+ }
+ else
+ appearance = pdfdictionary { -- maybe also cache components
+ N = pdfdictionary { [forceyes or yesn] = registeredsymbol(yesn), Off = registeredsymbol(offn) },
+ R = pdfdictionary { [forceyes or yesr] = registeredsymbol(yesr), Off = registeredsymbol(offr) },
+ D = pdfdictionary { [forceyes or yesd] = registeredsymbol(yesd), Off = registeredsymbol(offd) }
+ }
+ end
local appearanceref = pdfshareobjectreference(appearance)
+ -- local appearanceref = pdfreference(pdfflushobject(appearance))
+ return appearanceref, default, yesvalue
+end
+
+-- It looks like there is always a (MK related) symbol used and that
+-- the appearances are only used as ornaments behind a symbol. So,
+-- contrary to what we did when widgets showed up, we now limit
+-- ourself to more dumb definitions. Especially when highlighting is
+-- enabled weird interferences happen. So, we play safe (some nice code
+-- has been removed that worked well till recently).
+
+local function fieldstates_radio(specification,name,parent)
+ local values = values or specification.values
+ local default = default or parent.default -- specification.default
+ if not values or values == "" then
+ -- error
+ return
+ end
+ local v = settings_to_array(values)
+ local yes, off, yesn, yesr, yesd, offn, offr, offd
+ if #v == 1 then
+ yes, off = v[1], v[1]
+ else
+ yes, off = v[1], v[2]
+ end
+ -- yes keys might be the same in the three appearances within a field
+ -- but can best be different among fields ... don't ask why
+ local yessymbols, yesvalue = lpegmatch(splitter,yes) -- n,r,d=>x
+ if not (yessymbols and yesvalue) then
+ yessymbols = yes
+ end
+ if not yesvalue then
+ yesvalue = name
+ end
+ yessymbols = settings_to_array(yessymbols)
+ if #yessymbols == 1 then
+ yesn = yessymbols[1]
+ yesr = yesn
+ yesd = yesr
+ elseif #yessymbols == 2 then
+ yesn = yessymbols[1]
+ yesr = yessymbols[2]
+ yesd = yesr
+ else
+ yesn = yessymbols[1]
+ yesr = yessymbols[2]
+ yesd = yessymbols[3]
+ end
+ -- we don't care about names, as all will be /Off
+ local offsymbols = lpegmatch(splitter,off) or off
+ offsymbols = settings_to_array(offsymbols)
+ if #offsymbols == 1 then
+ offn = offsymbols[1]
+ offr = offn
+ offd = offr
+ elseif #offsymbols == 2 then
+ offn = offsymbols[1]
+ offr = offsymbols[2]
+ offd = offr
+ else
+ offn = offsymbols[1]
+ offr = offsymbols[2]
+ offd = offsymbols[3]
+ end
+ if default == name then
+ default = pdfconstant(name)
+ else
+ default = pdf_off
+ end
+ --
+ local appearance
+ if false then -- needs testing
+ appearance = pdfdictionary { -- maybe also cache components
+ N = pdfshareobjectreference(pdfdictionary { [name] = registeredsymbol(yesn), Off = registeredsymbol(offn) }),
+ R = pdfshareobjectreference(pdfdictionary { [name] = registeredsymbol(yesr), Off = registeredsymbol(offr) }),
+ D = pdfshareobjectreference(pdfdictionary { [name] = registeredsymbol(yesd), Off = registeredsymbol(offd) }),
+ }
+ else
+ appearance = pdfdictionary { -- maybe also cache components
+ N = pdfdictionary { [name] = registeredsymbol(yesn), Off = registeredsymbol(offn) },
+ R = pdfdictionary { [name] = registeredsymbol(yesr), Off = registeredsymbol(offr) },
+ D = pdfdictionary { [name] = registeredsymbol(yesd), Off = registeredsymbol(offd) }
+ }
+ end
+ local appearanceref = pdfshareobjectreference(appearance) -- pdfreference(pdfflushobject(appearance))
return appearanceref, default, yesvalue
end
@@ -425,14 +570,17 @@ local function todingbat(n)
end
end
+-- local zero_bc = pdfarray { 0, 0, 0 }
+-- local zero_bg = pdfarray { 1, 1, 1 }
+
local function fieldrendering(specification)
local bvalue = tonumber(specification.backgroundcolorvalue)
local fvalue = tonumber(specification.framecolorvalue)
local svalue = specification.fontsymbol
if bvalue or fvalue or (svalue and svalue ~= "") then
return pdfdictionary {
- BG = bvalue and pdfarray { lpdf.colorvalues(3,bvalue) } or nil,
- BC = fvalue and pdfarray { lpdf.colorvalues(3,fvalue) } or nil,
+ BG = bvalue and pdfarray { lpdf.colorvalues(3,bvalue) } or nil, -- or zero_bg,
+ BC = fvalue and pdfarray { lpdf.colorvalues(3,fvalue) } or nil, -- or zero_bc,
CA = svalue and pdfstring (svalue) or nil,
}
end
@@ -449,6 +597,30 @@ end
local fields, radios, clones, fieldsets, calculationset = { }, { }, { }, { }, nil
+local xfdftemplate = [[
+<?xml version='1.0' encoding='UTF-8'?>
+
+<xfdf xmlns='http://ns.adobe.com/xfdf/'>
+ <f href='%s.pdf'/>
+ <fields>
+%s
+ </fields>
+</xfdf>
+]]
+
+function codeinjections.exportformdata(name)
+ local result = { }
+ for k, v in table.sortedhash(fields) do
+ result[#result+1] = format(" <field name='%s'><value>%s</value></field>",v.name or k,v.default or "")
+ end
+ local base = file.basename(tex.jobname)
+ local xfdf = format(xfdftemplate,base,table.concat(result,"\n"))
+ if not name or name == "" then
+ name = base
+ end
+ io.savedata(file.addsuffix(name,"xfdf"),xfdf)
+end
+
function codeinjections.definefieldset(tag,list)
fieldsets[tag] = list
end
@@ -569,11 +741,11 @@ function codeinjections.clonefield(specification) -- obsolete
local p, c, v = specification.parent, specification.children, specification.alternative
if not p or not c then
if trace_fields then
- report_fields("invalid clone: children: '%s', parent '%s', alternative: '%s'",p or "?",c or "?", v or "?")
+ report_fields("invalid clone: children: '%s', parent '%s', alternative: '%s'",c or "?",p or "?", v or "?")
end
return
end
- local x = fields[p]
+ local x = fields[p] or radios[p]
if not x then
if trace_fields then
report_fields("cloning: unknown parent '%s'",p)
@@ -584,11 +756,11 @@ function codeinjections.clonefield(specification) -- obsolete
local f, r, c = fields[n], radios[n], clones[n]
if f or r or c then
if trace_fields then
- report_fields("already cloned: child: '%s', parent '%s', alternative: '%s'",p,n, v or "?")
+ report_fields("already cloned: child: '%s', parent '%s', alternative: '%s'",n,p,v or "?")
end
else
if trace_fields then
- report_fields("cloning: child: '%s', parent '%s', alternative: '%s'",p,n, v or "?")
+ report_fields("cloning: child: '%s', parent '%s', alternative: '%s'",n,p,v or "?")
end
clones[n] = specification
predefinesymbols(specification)
@@ -743,7 +915,10 @@ local function save_kid(field,specification,d,optname)
local kn = pdfreserveannotation()
field.kids[#field.kids+1] = pdfreference(kn)
if optname then
- field.opt[#field.opt+1] = optname
+ local opt = field.opt
+ if opt then
+ opt[#opt+1] = optname
+ end
end
local width, height, depth = specification.width or 0, specification.height or 0, specification.depth
local box = hpack_node(pdfannotation_node(width,height,depth,d(),kn))
@@ -812,7 +987,7 @@ function methods.line(name,specification)
end
function methods.text(name,specification)
- return makelinechine(name,enhance(specification,"MultiLine"))
+ return makelinechild(name,enhance(specification,"MultiLine"))
end
local function makechoiceparent(field,specification)
@@ -876,7 +1051,7 @@ end
local function makecheckparent(field,specification)
local d = pdfdictionary {
- T = pdfunicode(specification.title),
+ T = pdfunicode(specification.title), -- todo: when tracing use a string
F = fieldplus(specification),
Ff = fieldflag(specification),
OC = fieldlayer(specification),
@@ -927,7 +1102,7 @@ local function makecheckchild(name,specification)
d.MK = fieldrendering(specification)
return save_kid(parent,specification,d)
else
- local appearance, default, value = fieldstates(field,true)
+ local appearance, default, value = fieldstates_check(field,true)
d.AS = default
d.AP = appearance
return save_kid(parent,specification,d,value)
@@ -1002,18 +1177,78 @@ function methods.push(name,specification)
end
local function makeradioparent(field,specification)
- specification = enhance(specification,"Radio,RadiosInUnison")
+-- specification = enhance(specification,"Radio,RadiosInUnison")
+ specification = enhance(specification,"Radio,RadiosInUnison,Print,NoToggleToOff")
+-- specification = enhance(specification,"Radio,Print,NoToggleToOff")
local d = pdfdictionary {
T = field.name,
FT = pdf_btn,
- F = fieldplus(specification),
+-- F = fieldplus(specification),
Ff = fieldflag(specification),
- H = pdf_n,
+-- H = pdf_n,
V = fielddefault(field),
}
save_parent(field,specification,d,true)
end
+-- local function makeradiochild(name,specification)
+-- local field, parent = clones[name], nil
+-- if field then
+-- field = radios[field.parent]
+-- parent = fields[field.parent]
+-- if not parent.pobj then
+-- if trace_fields then
+-- report_fields("forcing parent radio '%s'",parent.name)
+-- end
+-- makeradioparent(parent,parent)
+-- end
+-- else
+-- field = radios[name]
+-- if not field then
+-- report_fields("there is some problem with field '%s'",name)
+-- return nil
+-- end
+-- parent = fields[field.parent]
+-- if not parent.pobj then
+-- if trace_fields then
+-- report_fields("using parent radio '%s'",name)
+-- end
+-- makeradioparent(parent,parent)
+-- end
+-- end
+-- if trace_fields then
+-- report_fields("using child radio '%s' with values '%s' and default '%s'",name,field.values or "?",field.default or "?")
+-- end
+-- local fontsymbol = specification.fontsymbol
+-- fontsymbol="star"
+-- local d = pdfdictionary {
+-- Subtype = pdf_widget,
+-- Parent = pdfreference(parent.pobj),
+-- F = fieldplus(specification),
+-- OC = fieldlayer(specification),
+-- AA = fieldactions(specification),
+-- H = pdf_n,
+-- }
+-- if fontsymbol and fontsymbol ~= "" then
+-- local appearance, default, value = fieldstates_radio(field,true,false,false,name) -- false is also ok
+-- specification.fontsymbol = todingbat(fontsymbol)
+-- specification.fontstyle = "symbol"
+-- specification.fontalternative = "dingbats"
+-- d.DA = fieldsurrounding(specification)
+-- d.MK = fieldrendering(specification)
+-- d.AS = pdfconstant(value) -- default -- mandate when AP but confuses viewers
+-- d.AP = appearance
+-- return save_kid(parent,specification,d,value)
+-- -- return save_kid(parent,specification,d,name)
+-- else
+-- -- local appearance, default, value = fieldstates_radio(field,true) -- false is also ok
+-- local appearance, default, value = fieldstates_radio(field,true,false,false,name) -- false is also ok
+-- d.AS = default -- mandate when AP but confuses viewers
+-- d.AP = appearance
+-- return save_kid(parent,specification,d,value)
+-- end
+-- end
+
local function makeradiochild(name,specification)
local field, parent = clones[name], nil
if field then
@@ -1025,9 +1260,12 @@ local function makeradiochild(name,specification)
end
makeradioparent(parent,parent)
end
- field = radios[name]
else
field = radios[name]
+ if not field then
+ report_fields("there is some problem with field '%s'",name)
+ return nil
+ end
parent = fields[field.parent]
if not parent.pobj then
if trace_fields then
@@ -1040,6 +1278,7 @@ local function makeradiochild(name,specification)
report_fields("using child radio '%s' with values '%s' and default '%s'",name,field.values or "?",field.default or "?")
end
local fontsymbol = specification.fontsymbol
+ -- fontsymbol = "circle"
local d = pdfdictionary {
Subtype = pdf_widget,
Parent = pdfreference(parent.pobj),
@@ -1054,13 +1293,11 @@ local function makeradiochild(name,specification)
specification.fontalternative = "dingbats"
d.DA = fieldsurrounding(specification)
d.MK = fieldrendering(specification)
- return save_kid(parent,specification,d)
- else
- local appearance, default, value = fieldstates(field,true) -- false is also ok
- d.AS = default -- needed ?
- d.AP = appearance
- return save_kid(parent,specification,d,value)
end
+ local appearance, default, value = fieldstates_radio(field,name,fields[field.parent])
+ d.AP = appearance
+ d.AS = default -- /Whatever
+ return save_kid(parent,specification,d,value)
end
function methods.sub(name,specification)
diff --git a/Master/texmf-dist/tex/context/base/lpdf-fmt.lua b/Master/texmf-dist/tex/context/base/lpdf-fmt.lua
index 017e28ebb23..8e118db1265 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-fmt.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-fmt.lua
@@ -10,6 +10,9 @@ if not modules then modules = { } end modules ['lpdf-fmt'] = {
-- context --directives="backend.format=PDF/X-1a:2001" --trackers=backend.format yourfile
+local lower, gmatch, format, find = string.lower, string.gmatch, string.format, string.find
+local concat, serialize = table.concat, table.serialize
+
local trace_format = false trackers.register("backend.format", function(v) trace_format = v end)
local trace_variables = false trackers.register("backend.variables", function(v) trace_variables = v end)
@@ -17,27 +20,28 @@ local report_backend = logs.reporter("backend","profiles")
local backends, lpdf = backends, lpdf
-local codeinjections = backends.pdf.codeinjections
+local codeinjections = backends.pdf.codeinjections
-local variables = interfaces.variables
-local viewerlayers = attributes.viewerlayers
-local colors = attributes.colors
-local transparencies = attributes.transparencies
+local variables = interfaces.variables
+local viewerlayers = attributes.viewerlayers
+local colors = attributes.colors
+local transparencies = attributes.transparencies
-local pdfdictionary = lpdf.dictionary
-local pdfarray = lpdf.array
-local pdfconstant = lpdf.constant
-local pdfreference = lpdf.reference
-local pdfflushobject = lpdf.flushobject
-local pdfstring = lpdf.string
-local pdfverbose = lpdf.verbose
-local pdfobject = lpdf.object
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfflushobject = lpdf.flushobject
+local pdfstring = lpdf.string
+local pdfverbose = lpdf.verbose
+local pdfflushstreamfileobject = lpdf.flushstreamfileobject
-local addtoinfo, injectxmpinfo, insertxmpinfo = lpdf.addtoinfo, lpdf.injectxmpinfo, lpdf.insertxmpinfo
+local addtoinfo = lpdf.addtoinfo
+local injectxmpinfo = lpdf.injectxmpinfo
+local insertxmpinfo = lpdf.insertxmpinfo
-local lower, gmatch, format, find = string.lower, string.gmatch, string.format, string.find
-local concat, serialize = table.concat, table.serialize
-local settings_to_array, settings_to_hash = utilities.parsers.settings_to_array, utilities.parsers.settings_to_hash
+local settings_to_array = utilities.parsers.settings_to_array
+local settings_to_hash = utilities.parsers.settings_to_hash
--[[
Comments by Peter:
@@ -434,14 +438,7 @@ local function handleinternalprofile(s,include)
elseif not channel then
report_backend("error, couldn't resolve channel entry for colorspace '%s'",colorspace)
else
- local a = pdfdictionary { N = channel }
- profile = pdfobject { -- does a flush too
- compresslevel = 0,
- immediate = true, -- !
- type = "stream",
- file = fullname,
- attr = a(),
- }
+ profile = pdfflushstreamfileobject(fullname,pdfdictionary{ N = channel },false) -- uncompressed
internalprofiles[tag] = profile
if trace_format then
report_backend("including '%s' color profile from '%s'",colorspace,fullname)
diff --git a/Master/texmf-dist/tex/context/base/lpdf-grp.lua b/Master/texmf-dist/tex/context/base/lpdf-grp.lua
index 2f7684a4da8..aba5771fd6d 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-grp.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-grp.lua
@@ -6,7 +6,9 @@ if not modules then modules = { } end modules ['lpdf-grp'] = {
license = "see context related readme files"
}
-local format = string.format
+local format, gsub = string.format, string.gsub
+local concat = table.concat
+local round = math.round
local backends, lpdf = backends, lpdf
@@ -61,29 +63,6 @@ function lpdf.linearshade(name,domain,color_a,color_b,n,colorspace,coordinates,s
shade(2,name,domain,color_a,color_b,n,colorspace,coordinates,separation)
end
-function lpdf.colorspec(model,ca,default)
- if ca and ca > 0 then
- local cv = colors.value(ca)
- if cv then
- if model == 1 then
- model = cv[1]
- end
- if model == 2 then
- return pdfarray { cv[2] }
- elseif model == 3 then
- return pdfarray { cv[3],cv[4],cv[5] }
- elseif model == 4 then
- return pdfarray { cv[6],cv[7],cv[8],cv[9] }
- elseif model == 5 then
- return pdfarray { cv[13] }
- end
- end
- end
- if default then
- return default
- end
-end
-
-- inline bitmaps but xform'd
--
-- we could derive the colorspace if we strip the data
@@ -101,7 +80,7 @@ function nodeinjections.injectbitmap(t)
local colorspace = t.colorspace
if colorspace ~= "rgb" and colorspace ~= "cmyk" and colorspace ~= "gray" then
-- not that efficient but ok
- local d = string.gsub(t.data,"[^0-9a-f]","")
+ local d = gsub(t.data,"[^0-9a-f]","")
local b = math.round(#d / (xresolution * yresolution))
if b == 2 then
colorspace = "gray"
@@ -111,13 +90,8 @@ function nodeinjections.injectbitmap(t)
colorspace = "cmyk"
end
end
- if colorspace == "gray" then
- colorspace = pdfconstant("DeviceGray")
- elseif colorspace == "rgb" then
- colorspace = pdfconstant("DeviceRGB")
- elseif colorspace == "cmyk" then
- colorspace = pdfconstant("DeviceCMYK")
- else
+ colorspace = lpdf.colorspaceconstants[colorspace]
+ if not colorspace then
return -- fatal error
end
local d = pdfdictionary {
@@ -126,6 +100,9 @@ function nodeinjections.injectbitmap(t)
CS = colorspace,
BPC = 8,
F = pdfconstant("AHx"),
+--~ CS = nil,
+--~ BPC = 1,
+--~ IM = true,
}
-- for some reasons it only works well if we take a 1bp boundingbox
local urx, ury = 1/basepoints, 1/basepoints
@@ -148,3 +125,120 @@ function nodeinjections.injectbitmap(t)
}
return img.node(image)
end
+
+-- general graphic helpers
+
+function codeinjections.setfigurealternative(data,figure)
+ local request = data.request
+ local display = request.display
+ if display and display ~= "" then
+ local nested = figures.push {
+ name = display,
+ page = request.page,
+ size = request.size,
+ prefix = request.prefix,
+ cache = request.cache,
+ width = request.width,
+ height = request.height,
+ }
+ figures.identify()
+ local displayfigure = figures.check()
+ if displayfigure then
+ -- figure.aform = true
+ img.immediatewrite(figure)
+ local a = pdfarray {
+ pdfdictionary {
+ Image = pdfreference(figure.objnum),
+ DefaultForPrinting = true,
+ }
+ }
+ local d = pdfdictionary {
+ Alternates = pdfreference(pdfflushobject(a)),
+ }
+ displayfigure.attr = d()
+ figures.pop()
+ return displayfigure, nested
+ else
+ figures.pop()
+ end
+ end
+end
+
+function codeinjections.getpreviewfigure(request)
+ local figure = figures.initialize(request)
+ if not figure then
+ return
+ end
+ figure = figures.identify(figure)
+ if not (figure and figure.status and figure.status.fullname) then
+ return
+ end
+ figure = figures.check(figure)
+ if not (figure and figure.status and figure.status.fullname) then
+ return
+ end
+ local image = figure.status.private
+ if image then
+ img.immediatewrite(image)
+ end
+ return figure
+end
+
+function codeinjections.setfiguremask(data,figure) -- mark
+ local request = data.request
+ local mask = request.mask
+ if mask and mask ~= "" then
+ figures.push {
+ name = mask,
+ page = request.page,
+ size = request.size,
+ prefix = request.prefix,
+ cache = request.cache,
+ width = request.width,
+ height = request.height,
+ }
+ figures.identify()
+ local maskfigure = figures.check()
+ if maskfigure then
+ local image = maskfigure.status.private
+ if image then
+ img.immediatewrite(image)
+ local d = pdfdictionary {
+ Interpolate = false,
+ SMask = pdfreference(image.objnum),
+ }
+ figure.attr = d()
+ end
+ end
+ figures.pop()
+ end
+end
+
+-- temp hack
+
+local factor = number.dimenfactors.bp
+
+function img.package(image) -- see lpdf-u3d **
+ local boundingbox = image.bbox
+ local imagetag = "Im" .. image.index
+ local resources = pdfdictionary {
+ ProcSet = pdfarray {
+ pdfconstant("PDF"),
+ pdfconstant("ImageC")
+ },
+ Resources = pdfdictionary {
+ XObject = pdfdictionary {
+ [imagetag] = pdfreference(image.objnum)
+ }
+ }
+ }
+ local width = boundingbox[3]
+ local height = boundingbox[4]
+ local xform = img.scan {
+ attr = resources(),
+ stream = format("%s 0 0 %s 0 0 cm /%s Do",width,height,imagetag),
+ bbox = { 0, 0, width/factor, height/factor },
+ }
+ img.immediatewrite(xform)
+ return xform
+end
diff --git a/Master/texmf-dist/tex/context/base/lpdf-ini.lua b/Master/texmf-dist/tex/context/base/lpdf-ini.lua
index 74ecb36de74..88999358ce1 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-ini.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-ini.lua
@@ -9,12 +9,9 @@ if not modules then modules = { } end modules ['lpdf-ini'] = {
local setmetatable, getmetatable, type, next, tostring, tonumber, rawset = setmetatable, getmetatable, type, next, tostring, tonumber, rawset
local char, byte, format, gsub, concat, match, sub, gmatch = string.char, string.byte, string.format, string.gsub, table.concat, string.match, string.sub, string.gmatch
local utfvalues = string.utfvalues
-local texset = tex.set
+local utfchar = utf.char
local sind, cosd = math.sind, math.cosd
-local lpegmatch = lpeg.match
-
---~ local pdfreserveobject = pdf and pdf.reserveobj or function() return 1 end -- for testing
---~ local pdfimmediateobject = pdf and pdf.immediateobj or function() return 2 end -- for testing
+local lpegmatch, P, C, R, S, Cc, Cs = lpeg.match, lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc, lpeg.Cs
local pdfreserveobject = pdf.reserveobj
local pdfimmediateobject = pdf.immediateobj
@@ -29,7 +26,7 @@ local trace_detail = false trackers.register("backend.detail", function
local report_objects = logs.reporter("backend","objects")
local report_finalizing = logs.reporter("backend","finalizing")
-local backends, context = backends, context
+local backends = backends
backends.pdf = backends.pdf or {
comment = "backend for directly generating pdf output",
@@ -42,7 +39,7 @@ backends.pdf = backends.pdf or {
lpdf = lpdf or { }
local lpdf = lpdf
-local function tosixteen(str)
+local function tosixteen(str) -- an lpeg might be faster
if not str or str == "" then
return "<feff>" -- not () as we want an indication that it's unicode
else
@@ -61,7 +58,7 @@ local function tosixteen(str)
end
end
-lpdf.tosixteen = tosixteen
+lpdf.tosixteen = tosixteen
-- lpeg is some 5 times faster than gsub (in test) on escaping
@@ -73,7 +70,7 @@ lpdf.tosixteen = tosixteen
-- ["("] = "\\(", [")"] = "\\)",
-- }
--
--- local escaped = lpeg.Cs(lpeg.Cc("(") * (lpeg.S("\\/#<>[]()")/escapes + lpeg.P(1))^0 * lpeg.Cc(")"))
+-- local escaped = Cs(Cc("(") * (S("\\/#<>[]()")/escapes + P(1))^0 * Cc(")"))
--
-- local function toeight(str)
-- if not str or str == "" then
@@ -237,7 +234,7 @@ local mt_f = { __lpdftype = "false", __tostring = tostring_f, __call = valu
local mt_r = { __lpdftype = "reference", __tostring = tostring_r, __call = value_r }
local mt_v = { __lpdftype = "verbose", __tostring = tostring_v, __call = value_v }
-local function pdfstream(t) -- we need to add attrbutes
+local function pdfstream(t) -- we need to add attributes
if t then
for i=1,#t do
t[i] = tostring(t[i])
@@ -288,7 +285,7 @@ for s in gmatch(forbidden,".") do
replacements[s] = format("#%02x",byte(s))
end
-local escaped = lpeg.Cs(lpeg.Cc("/") * (lpeg.S(forbidden)/replacements + lpeg.P(1))^0)
+local escaped = Cs(Cc("/") * (S(forbidden)/replacements + P(1))^0)
local function pdfconstant(str,default)
str = str or default or ""
@@ -374,14 +371,15 @@ function lpdf.reserveannotation()
return pdfreserveobject("annot")
end
-lpdf.immediateobject = pdfimmediateobject
-lpdf.object = pdfdeferredobject -- the table interface, todo: auto attr() and so
-lpdf.deferredobject = pdfdeferredobject
-lpdf.referenceobject = pdfreferenceobject
+-- lpdf.immediateobject = pdfimmediateobject
+-- lpdf.deferredobject = pdfdeferredobject
+-- lpdf.object = pdfdeferredobject
+-- lpdf.referenceobject = pdfreferenceobject
+
lpdf.pagereference = pdf.pageref or tex.pdfpageref
lpdf.registerannotation = pdf.registerannot
-function lpdf.delayedobject(data)
+function lpdf.delayedobject(data) -- we will get rid of this one
local n = pdfdeferredobject(data)
pdfreferenceobject(n)
return n
@@ -415,6 +413,35 @@ function lpdf.flushobject(name,data)
end
end
+
+function lpdf.flushstreamobject(data,dict,compressed) -- default compressed
+ if trace_objects then
+ report_objects("flushing stream object of %s bytes",#data)
+ end
+ local dtype = type(dict)
+ return pdfdeferredobject {
+ immediate = true,
+ compresslevel = compressed == false and 0 or nil,
+ type = "stream",
+ string = data,
+ attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil,
+ }
+end
+
+function lpdf.flushstreamfileobject(filename,dict,compressed) -- default compressed
+ if trace_objects then
+ report_objects("flushing stream file object '%s'",filename)
+ end
+ local dtype = type(dict)
+ return pdfdeferredobject {
+ immediate = true,
+ compresslevel = compressed == false and 0 or nil,
+ type = "stream",
+ file = filename,
+ attr = (dtype == "string" and dict) or (dtype == "table" and dict()) or nil,
+ }
+end
+
local shareobjectcache, shareobjectreferencecache = { }, { }
function lpdf.shareobject(content)
@@ -634,17 +661,6 @@ local function flushcolorspaces() if next(d_colorspaces) then trace_flush("color
local function flushpatterns () if next(d_patterns ) then trace_flush("patterns") pdfimmediateobject(r_patterns, tostring(d_patterns )) end end
local function flushshades () if next(d_shades ) then trace_flush("shades") pdfimmediateobject(r_shades, tostring(d_shades )) end end
---~ local collected = pdfdictionary {
---~ ExtGState = p_extgstates,
---~ ColorSpace = p_colorspaces,
---~ Pattern = p_patterns,
---~ Shading = p_shades,
---~ } ; collected = collected()
-
---~ function lpdf.collectedresources()
---~ context(collected)
---~ end
-
function lpdf.collectedresources()
local ExtGState = next(d_extgstates ) and p_extgstates
local ColorSpace = next(d_colorspaces) and p_colorspaces
@@ -658,7 +674,9 @@ function lpdf.collectedresources()
Shading = Shading,
-- ProcSet = pdfarray { pdfconstant("PDF") },
}
- context(collected())
+ return collected()
+ else
+ return ""
end
end
@@ -685,7 +703,7 @@ registerpagefinalizer(checkshades,3,"shades")
function lpdf.rotationcm(a)
local s, c = sind(a), cosd(a)
- context("%s %s %s %s 0 0 cm",c,s,-s,c)
+ return format("%s %s %s %s 0 0 cm",c,s,-s,c)
end
-- ! -> universaltime
@@ -706,7 +724,7 @@ function lpdf.id()
end
function lpdf.checkedkey(t,key,variant)
- local pn = t[key]
+ local pn = t and t[key]
if pn then
local tn = type(pn)
if tn == variant then
@@ -759,7 +777,7 @@ end
-- lpdf.addtoinfo("ConTeXt.Version", tex.contextversiontoks)
-- lpdf.addtoinfo("ConTeXt.Time", os.date("%Y.%m.%d %H:%M")) -- :%S
--- lpdf.addtoinfo("ConTeXt.Jobname", tex.jobname)
+-- lpdf.addtoinfo("ConTeXt.Jobname", environment.jobname)
-- lpdf.addtoinfo("ConTeXt.Url", "www.pragma-ade.com")
if not pdfreferenceobject then
diff --git a/Master/texmf-dist/tex/context/base/lpdf-mis.lua b/Master/texmf-dist/tex/context/base/lpdf-mis.lua
index 426c00286a9..174d17427fa 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-mis.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-mis.lua
@@ -16,40 +16,38 @@ if not modules then modules = { } end modules ['lpdf-mis'] = {
-- course there are a couple of more changes.
local next, tostring = next, tostring
-local format = string.format
+local format, gsub = string.format, string.gsub
local texset = tex.set
local backends, lpdf, nodes = backends, lpdf, nodes
-local nodeinjections = backends.pdf.nodeinjections
-local codeinjections = backends.pdf.codeinjections
-local registrations = backends.pdf.registrations
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
-local copy_node = node.copy
+local copy_node = node.copy
-local nodepool = nodes.pool
+local nodepool = nodes.pool
+local pdfliteral = nodepool.pdfliteral
+local register = nodepool.register
-local pdfliteral, register = nodepool.pdfliteral, nodepool.register
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfboolean = lpdf.boolean
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfverbose = lpdf.verbose
+local pdfstring = lpdf.string
+local pdfflushobject = lpdf.flushobject
+local pdfflushstreamobject = lpdf.flushstreamobject
-local pdfdictionary = lpdf.dictionary
-local pdfarray = lpdf.array
-local pdfboolean = lpdf.boolean
-local pdfconstant = lpdf.constant
-local pdfreference = lpdf.reference
-local pdfunicode = lpdf.unicode
-local pdfverbose = lpdf.verbose
-local pdfstring = lpdf.string
-local pdfflushobject = lpdf.flushobject
-local pdfimmediateobject = lpdf.immediateobject
+local variables = interfaces.variables
-local variables = interfaces.variables
-
---
-
-local positive = register(pdfliteral("/GSpositive gs"))
-local negative = register(pdfliteral("/GSnegative gs"))
-local overprint = register(pdfliteral("/GSoverprint gs"))
-local knockout = register(pdfliteral("/GSknockout gs"))
+local positive = register(pdfliteral("/GSpositive gs"))
+local negative = register(pdfliteral("/GSnegative gs"))
+local overprint = register(pdfliteral("/GSoverprint gs"))
+local knockout = register(pdfliteral("/GSknockout gs"))
local function initializenegative()
local a = pdfarray { 0, 1 }
@@ -59,10 +57,10 @@ local function initializenegative()
Range = a,
Domain = a,
}
- local negative = pdfdictionary { Type = g, TR = pdfreference(pdfimmediateobject("stream","1 exch sub",d())) }
+ local negative = pdfdictionary { Type = g, TR = pdfreference(pdfflushstreamobject("{ 1 exch sub }",d)) }
local positive = pdfdictionary { Type = g, TR = pdfconstant("Identity") }
lpdf.adddocumentextgstate("GSnegative", pdfreference(pdfflushobject(negative)))
- lpdf.adddocumentextgstate("GSPositive", pdfreference(pdfflushobject(positive)))
+ lpdf.adddocumentextgstate("GSpositive", pdfreference(pdfflushobject(positive)))
initializenegative = nil
end
@@ -95,15 +93,15 @@ end
--
-function codeinjections.addtransparencygroup()
- -- png: /CS /DeviceRGB /I true
- local d = pdfdictionary {
- S = pdfconstant("Transparency"),
- I = true,
- K = true,
- }
- lpdf.registerpagefinalizer(function() lpdf.addtopageattributes("Group",d) end) -- hm
-end
+-- function codeinjections.addtransparencygroup()
+-- -- png: /CS /DeviceRGB /I true
+-- local d = pdfdictionary {
+-- S = pdfconstant("Transparency"),
+-- I = true,
+-- K = true,
+-- }
+-- lpdf.registerpagefinalizer(function() lpdf.addtopageattributes("Group",d) end) -- hm
+-- end
-- actions (todo: store and update when changed)
@@ -162,47 +160,57 @@ function codeinjections.setupidentity(specification)
end
end
+local done = false -- using "setupidentity = function() end" fails as the meaning is frozen in register
+
local function setupidentity()
- local title = identity.title
- if not title or title == "" then
- title = tex.jobname
- end
- lpdf.addtoinfo("Title", pdfunicode(title), title)
- local subtitle = identity.subtitle or ""
- if subtitle ~= "" then
- lpdf.addtoinfo("Subject", pdfunicode(subtitle), subtitle)
- end
- local author = identity.author or ""
- if author ~= "" then
- lpdf.addtoinfo("Author", pdfunicode(author), author) -- '/Author' in /Info, 'Creator' in XMP
- end
- local creator = identity.creator or ""
- if creator ~= "" then
- lpdf.addtoinfo("Creator", pdfunicode(creator), creator) -- '/Creator' in /Info, 'CreatorTool' in XMP
- end
- lpdf.addtoinfo("CreationDate", pdfstring(lpdf.pdftimestamp(lpdf.timestamp())))
- local date = identity.date or ""
- local pdfdate = lpdf.pdftimestamp(date)
- if pdfdate then
- lpdf.addtoinfo("ModDate", pdfstring(pdfdate), date)
+ if not done then
+ local title = identity.title
+ if not title or title == "" then
+ title = tex.jobname
+ end
+ lpdf.addtoinfo("Title", pdfunicode(title), title)
+ local subtitle = identity.subtitle or ""
+ if subtitle ~= "" then
+ lpdf.addtoinfo("Subject", pdfunicode(subtitle), subtitle)
+ end
+ local author = identity.author or ""
+ if author ~= "" then
+ lpdf.addtoinfo("Author", pdfunicode(author), author) -- '/Author' in /Info, 'Creator' in XMP
+ end
+ local creator = identity.creator or ""
+ if creator ~= "" then
+ lpdf.addtoinfo("Creator", pdfunicode(creator), creator) -- '/Creator' in /Info, 'CreatorTool' in XMP
+ end
+ lpdf.addtoinfo("CreationDate", pdfstring(lpdf.pdftimestamp(lpdf.timestamp())))
+ local date = identity.date or ""
+ local pdfdate = lpdf.pdftimestamp(date)
+ if pdfdate then
+ lpdf.addtoinfo("ModDate", pdfstring(pdfdate), date)
+ else
+ -- users should enter the date in 2010-01-19T23:27:50+01:00 format
+ -- and if not provided that way we use the creation time instead
+ date = lpdf.timestamp()
+ lpdf.addtoinfo("ModDate", pdfstring(lpdf.pdftimestamp(date)), date)
+ end
+ local keywords = identity.keywords or ""
+ if keywords ~= "" then
+ keywords = gsub(keywords, "[%s,]+", " ")
+ lpdf.addtoinfo("Keywords",pdfunicode(keywords), keywords)
+ end
+ local id = lpdf.id()
+ lpdf.addtoinfo("ID", pdfstring(id), id) -- needed for pdf/x
+ done = true
else
- -- users should enter the date in 2010-01-19T23:27:50+01:00 format
- -- and if not provided that way we use the creation time instead
- date = lpdf.timestamp()
- lpdf.addtoinfo("ModDate", pdfstring(lpdf.pdftimestamp(date)), date)
- end
- local keywords = identity.keywords or ""
- if keywords ~= "" then
- keywords = string.gsub(keywords, "[%s,]+", " ")
- lpdf.addtoinfo("Keywords",pdfunicode(keywords), keywords)
+ -- no need for a message
end
- local id = lpdf.id()
- lpdf.addtoinfo("ID", pdfstring(id), id) -- needed for pdf/x
- setupidentity = function() end
end
lpdf.registerpagefinalizer(setupidentity,"identity")
+-- or when we want to be able to set things after pag e1:
+--
+-- lpdf.registerdocumentfinalizer(setupidentity,1,"identity")
+
local function flushjavascripts()
local t = interactions.javascripts.flushpreambles()
if #t > 0 then
@@ -212,7 +220,7 @@ local function flushjavascripts()
local name, script = t[i][1], t[i][2]
local j = pdfdictionary {
S = pdf_javascript,
- JS = pdfreference(pdfimmediateobject("stream",script)),
+ JS = pdfreference(pdfflushstreamobject(script)),
}
a[#a+1] = pdfstring(name)
a[#a+1] = pdfreference(pdfflushobject(j))
diff --git a/Master/texmf-dist/tex/context/base/lpdf-mov.lua b/Master/texmf-dist/tex/context/base/lpdf-mov.lua
new file mode 100644
index 00000000000..41db97e0c52
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/lpdf-mov.lua
@@ -0,0 +1,63 @@
+if not modules then modules = { } end modules ['lpdf-mov'] = {
+ version = 1.001,
+ comment = "companion to lpdf-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format = string.format
+
+local lpdf = lpdf
+
+local nodeinjections = backends.pdf.nodeinjections
+local pdfannotation_node = nodes.pool.pdfannotation
+local pdfconstant = lpdf.constant
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local write_node = node.write
+
+function nodeinjections.insertmovie(specification)
+ -- managed in figure inclusion: width, height, factor, repeat, controls, preview, label, foundname
+ local width = specification.width
+ local height = specification.height
+ local factor = specification.factor or number.dimenfactors.bp
+ local moviedict = pdfdictionary {
+ F = specification.foundname,
+ Aspect = pdfarray { factor * width, factor * height },
+ Poster = (specification.preview and true) or false,
+ }
+ local controldict = pdfdictionary {
+ ShowControls = (specification.controls and true) or false,
+ Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil,
+ }
+ local action = pdfdictionary {
+ Subtype = pdfconstant("Movie"),
+ Border = pdfarray { 0, 0, 0 },
+ T = format("movie %s",specification.label),
+ Movie = moviedict,
+ A = controldict,
+ }
+ write_node(pdfannotation_node(width,height,0,action())) -- test: context(...)
+end
+
+function nodeinjections.insertsound(specification)
+ -- rmanaged in interaction: repeat, label, foundname
+ local soundclip = interactions.soundclips.soundclip(specification.label)
+ if soundclip then
+ local controldict = pdfdictionary {
+ Mode = (specification["repeat"] and pdfconstant("Repeat")) or nil
+ }
+ local sounddict = pdfdictionary {
+ F = soundclip.filename
+ }
+ local action = pdfdictionary {
+ Subtype = pdfconstant("Movie"),
+ Border = pdfarray { 0, 0, 0 },
+ T = format("sound %s",specification.label),
+ Movie = sounddict,
+ A = controldict,
+ }
+ write_node(pdfannotation_node(0,0,0,action())) -- test: context(...)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/lpdf-nod.lua b/Master/texmf-dist/tex/context/base/lpdf-nod.lua
index 39bba2d6364..fe0c975f70e 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-nod.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-nod.lua
@@ -6,17 +6,24 @@ if not modules then modules = { } end modules ['lpdf-nod'] = {
license = "see context related readme files"
}
-local copy_node, new_node = node.copy, node.new
+local format = string.format
-local nodepool = nodes.pool
+local copy_node = node.copy
+local new_node = node.new
-local register = nodepool.register
+local nodepool = nodes.pool
+local register = nodepool.register
+local whatsitcodes = nodes.whatsitcodes
+local nodeinjections = backends.nodeinjections
-local pdfliteral = register(new_node("whatsit", 8)) pdfliteral.mode = 1
-local pdfdest = register(new_node("whatsit",19)) pdfdest.named_id = 1 -- xyz_zoom untouched
-local pdfannot = register(new_node("whatsit",15))
+local pdfliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) pdfliteral.mode = 1
+local pdfsave = register(new_node("whatsit", whatsitcodes.pdfsave))
+local pdfrestore = register(new_node("whatsit", whatsitcodes.pdfrestore))
+local pdfsetmatrix = register(new_node("whatsit", whatsitcodes.pdfsetmatrix))
+local pdfdest = register(new_node("whatsit", whatsitcodes.pdfdest)) pdfdest.named_id = 1 -- xyz_zoom untouched
+local pdfannot = register(new_node("whatsit", whatsitcodes.pdfannot))
-local variables = interfaces.variables
+local variables = interfaces.variables
local views = { -- beware, we do support the pdf keys but this is *not* official
xyz = 0, [variables.standard] = 0,
@@ -42,6 +49,24 @@ function nodepool.pdfdirect(str)
return t
end
+function nodepool.pdfsave()
+ return copy_node(pdfsave)
+end
+
+function nodepool.pdfrestore()
+ return copy_node(pdfrestore)
+end
+
+function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty)
+ local t = copy_node(pdfsetmatrix)
+ t.data = format("%s %s %s %s",rs or 0,sx or 0,sy or 0,rx or 0) -- todo: tx ty
+ return t
+end
+
+nodeinjections.save = nodepool.pdfsave
+nodeinjections.restore = nodepool.pdfrestore
+nodeinjections.transform = nodepool.pdfsetmatrix
+
function nodepool.pdfannotation(w,h,d,data,n)
local t = copy_node(pdfannot)
if w and w ~= 0 then t.width = w end
diff --git a/Master/texmf-dist/tex/context/base/lpdf-ren.lua b/Master/texmf-dist/tex/context/base/lpdf-ren.lua
index 54c78845ed4..e0c4b19731a 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-ren.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-ren.lua
@@ -12,7 +12,7 @@ local tostring, tonumber, next = tostring, tonumber, next
local format = string.format
local settings_to_array = utilities.parsers.settings_to_array
-local backends, lpdf = backends, lpdf
+local backends, lpdf, nodes, node = backends, lpdf, nodes, node
local nodeinjections = backends.pdf.nodeinjections
local codeinjections = backends.pdf.codeinjections
@@ -41,6 +41,10 @@ local pdfreference = lpdf.reference
local pdfflushobject = lpdf.flushobject
local pdfreserveobject = lpdf.reserveobject
+local nodepool = nodes.pool
+local register = nodepool.register
+local pdfliteral = nodepool.pdfliteral
+
local pdf_ocg = pdfconstant("OCG")
local pdf_ocmd = pdfconstant("OCMD")
local pdf_off = pdfconstant("OFF")
@@ -48,12 +52,56 @@ local pdf_on = pdfconstant("ON")
local pdf_toggle = pdfconstant("Toggle")
local pdf_setocgstate = pdfconstant("SetOCGState")
+local copy_node = node.copy
+
local lpdf_usage = pdfdictionary { Print = pdfdictionary { PrintState = pdf_off } }
-- We can have references to layers before they are places, for instance from
-- hide and vide actions. This is why we need to be able to force usage of layers
-- at several moments.
+-- injection
+
+local cache = { }
+
+function codeinjections.startlayer(name)
+ codeinjections.useviewerlayer(name)
+ return format("/OC /%s BDC",name)
+end
+
+function codeinjections.stoplayer(name)
+ return "EMC"
+end
+
+function nodeinjections.startlayer(name)
+ local c = cache[name]
+ if not c then
+ codeinjections.useviewerlayer(name)
+ c = register(pdfliteral(format("/OC /%s BDC",name)))
+ cache[name] = c
+ end
+ return copy_node(c)
+end
+
+local stop = register(pdfliteral("EMC"))
+
+function nodeinjections.stoplayer()
+ return copy_node(stop)
+end
+
+local cache = { }
+
+function nodeinjections.switchlayer(name) -- not used, optimization
+ local c = cache[name]
+ if not c then
+ codeinjections.useviewerlayer(name)
+ c = register(pdfliteral(format("EMC /OC /%s BDC",name)))
+ end
+ return copy_node(c)
+end
+
+-- management
+
local pdfln, pdfld = { }, { }
local textlayers, hidelayers, videlayers = pdfarray(), pdfarray(), pdfarray()
local pagelayers, pagelayersreference, cache = nil, nil, { }
@@ -70,42 +118,46 @@ function codeinjections.defineviewerlayer(specification)
end
end
-local function useviewerlayer(name)
- local specification = specifications[name]
- if not environment.initex and specification and not initialized[name] then
- specifications[name] = nil -- or not
- initialized [name] = true
- if not pagelayers then
- pagelayers = pdfdictionary()
- pagelayersreference = pdfreserveobject()
- end
- local tag = specification.tag
- -- todo: reserve
- local nn = pdfreserveobject()
- local nr = pdfreference(nn)
- local nd = pdfdictionary {
- Type = pdf_ocg,
- Name = specification.title or "unknown",
- Intent = ((specification.editable ~= v_no) and pdf_design) or nil, -- disable layer hiding by user
- Usage = ((specification.printable == v_no) and lpdf_usage) or nil, -- printable or not
- }
- cache[#cache+1] = { nn, nd }
- pdfln[tag] = nr -- was n
- local dn = pdfreserveobject()
- local dr = pdfreference(dn)
- local dd = pdfdictionary {
- Type = pdf_ocmd,
- OCGs = pdfarray { nr },
- }
- cache[#cache+1] = { dn, dd }
- pdfld[tag] = dr
- textlayers[#textlayers+1] = nr
- if specification.visible == v_start then
- videlayers[#videlayers+1] = nr
+local function useviewerlayer(name) -- move up so that we can use it as local
+ if not environment.initex and not initialized[name] then
+ local specification = specifications[name]
+ if specification then
+ specifications[name] = nil -- or not
+ initialized [name] = true
+ if not pagelayers then
+ pagelayers = pdfdictionary()
+ pagelayersreference = pdfreserveobject()
+ end
+ local tag = specification.tag
+ -- todo: reserve
+ local nn = pdfreserveobject()
+ local nr = pdfreference(nn)
+ local nd = pdfdictionary {
+ Type = pdf_ocg,
+ Name = specification.title or "unknown",
+ Intent = ((specification.editable ~= v_no) and pdf_design) or nil, -- disable layer hiding by user
+ Usage = ((specification.printable == v_no) and lpdf_usage) or nil, -- printable or not
+ }
+ cache[#cache+1] = { nn, nd }
+ pdfln[tag] = nr -- was n
+ local dn = pdfreserveobject()
+ local dr = pdfreference(dn)
+ local dd = pdfdictionary {
+ Type = pdf_ocmd,
+ OCGs = pdfarray { nr },
+ }
+ cache[#cache+1] = { dn, dd }
+ pdfld[tag] = dr
+ textlayers[#textlayers+1] = nr
+ if specification.visible == v_start then
+ videlayers[#videlayers+1] = nr
+ else
+ hidelayers[#hidelayers+1] = nr
+ end
+ pagelayers[tag] = dr -- check
else
- hidelayers[#hidelayers+1] = nr
+ -- todo: message
end
- pagelayers[tag] = dr -- check
end
end
diff --git a/Master/texmf-dist/tex/context/base/lpdf-swf.lua b/Master/texmf-dist/tex/context/base/lpdf-swf.lua
index 04825446c3e..4bbec8dbe84 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-swf.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-swf.lua
@@ -21,7 +21,7 @@ local pdfdictionary = lpdf.dictionary
local pdfarray = lpdf.array
local pdfnull = lpdf.null
local pdfreference = lpdf.reference
-local pdfimmediateobject = lpdf.immediateobject
+local pdfflushobject = lpdf.flushobject
local checkedkey = lpdf.checkedkey
@@ -30,6 +30,10 @@ local nodeinjections = backends.pdf.nodeinjections
local pdfannotation_node = nodes.pool.pdfannotation
+local trace_swf = false trackers.register("backend.swf", function(v) trace_swf = v end)
+
+local report_swf = logs.reporter("backend","swf")
+
local activations = {
click = "XA",
page = "PO",
@@ -56,7 +60,7 @@ local function insertswf(spec)
local resources = resources and parametersets[resources]
local display = display and parametersets[display]
- local controls = controls and parametersets[controls] -- not yet used
+ local controls = controls and parametersets[controls] -- not yet used
local preview = checkedkey(display,"preview","string")
local toolbar = checkedkey(display,"toolbar","boolean")
@@ -75,7 +79,7 @@ local function insertswf(spec)
},
}
- local flashreference = pdfreference(pdfimmediateobject(tostring(flash)))
+ local flashreference = pdfreference(pdfflushobject(flash))
local configuration = pdfdictionary {
Configurations = pdfarray { flashreference },
@@ -87,36 +91,103 @@ local function insertswf(spec)
},
}
+ -- todo: check op subpath figuur (relatief)
+
+ -- filename : ./test.swf (graphic)
+ -- root : .
+ -- prefix : ^%./
+ -- fullname : ./assets/whatever.xml
+ -- usedname : assets/whatever.xml
+ -- filename : assets/whatever.xml
+
+ local root = file.dirname(filename)
+ local relativepaths = nil
+ local paths = nil
+
if resources then
local names = configuration.Assets.Names
- local function add(filename)
- local filename = gsub(filename,"%./","")
- local embeddedreference = codeinjections.embedfile { file = filename, keepdir = true }
+ local prefix = false
+ if root ~= "" and root ~= "." then
+ prefix = format("^%s/",string.escapedpattern(root,true))
+ end
+ if prefix and trace_swf then
+ report_swf("using strip pattern '%s'",prefix)
+ end
+ local function add(fullname,strip)
+ local filename = gsub(fullname,"^%./","")
+ local usedname = strip and prefix and gsub(filename,prefix,"") or filename
+ local embeddedreference = codeinjections.embedfile {
+ file = fullname,
+ usedname = usedname,
+ keepdir = true,
+ }
names[#names+1] = pdfstring(filename)
names[#names+1] = embeddedreference
+ if trace_swf then
+ report_swf("embedding file '%s' as '%s'",fullname,usedname)
+ end
+ end
+ relativepaths = resources.relativepaths
+ if relativepaths then
+ if trace_swf then
+ report_swf("checking %s relative paths",#relativepaths)
+ end
+ for i=1,#relativepaths do
+ local relativepath = relativepaths[i]
+ if trace_swf then
+ report_swf("checking path '%s' relative to '%s'",relativepath,root)
+ end
+ local path = file.join(root == "" and "." or root,relativepath)
+ local files = dir.glob(path .. "/**")
+ for i=1,#files do
+ add(files[i],true)
+ end
+ end
end
- local paths = resources.paths
+ paths = resources.paths
if paths then
+ if trace_swf then
+ report_swf("checking absolute %s paths",#paths)
+ end
for i=1,#paths do
- local files = dir.glob(paths[i] .. "/**")
+ local path = paths[i]
+ if trace_swf then
+ report_swf("checking path '%s'",path)
+ end
+ local files = dir.glob(path .. "/**")
for i=1,#files do
- add(files[i])
+ add(files[i],false)
end
end
end
+ local relativefiles = resources.relativefiles
+ if relativefiles then
+ if trace_swf then
+ report_swf("checking %s relative files",#relativefiles)
+ end
+ for i=1,#relativefiles do
+ add(relativefiles[i],true)
+ end
+ end
local files = resources.files
if files then
+ if trace_swf then
+ report_swf("checking absolute %s files",#files)
+ end
for i=1,#files do
- add(files[i])
+ add(files[i],false)
end
end
end
- local configurationreference = pdfreference(pdfimmediateobject(tostring(configuration)))
+ local opendisplay = display and display.open or false
+ local closedisplay = display and display.close or false
+
+ local configurationreference = pdfreference(pdfflushobject(configuration))
local activation = pdfdictionary {
Type = pdfconstant("RichMediaActivation"),
- Condition = pdfconstant(activations[display.open]),
+ Condition = pdfconstant(activations[opendisplay]),
Configuration = flashreference,
Animation = pdfdictionary {
Subtype = pdfconstant("Linear"),
@@ -156,7 +227,7 @@ local function insertswf(spec)
local deactivation = pdfdictionary {
Type = pdfconstant("RichMediaDeactivation"),
- Condition = pdfconstant(deactivations[display.close]),
+ Condition = pdfconstant(deactivations[closedisplay]),
}
local richmediasettings = pdfdictionary {
@@ -165,15 +236,47 @@ local function insertswf(spec)
Deactivation = deactivation,
}
- local settingsreference = pdfreference(pdfimmediateobject(tostring(richmediasettings)))
+ local settingsreference = pdfreference(pdfflushobject(richmediasettings))
local appearance
if preview then
+ preview = gsub(preview,"%*",file.nameonly(filename))
local figure = codeinjections.getpreviewfigure { name = preview, width = width, height = height }
+ if relativepaths and not figure then
+ for i=1,#relativepaths do
+ local path = file.join(root == "" and "." or root,relativepaths[i])
+ if trace_swf then
+ report_swf("checking preview on relative path %s",path)
+ end
+ local p = file.join(path,preview)
+ figure = codeinjections.getpreviewfigure { name = p, width = width, height = height }
+ if figure then
+ preview = p
+ break
+ end
+ end
+ end
+ if paths and not figure then
+ for i=1,#paths do
+ local path = paths[i]
+ if trace_swf then
+ report_swf("checking preview on absolute path %s",path)
+ end
+ local p = file.join(path,preview)
+ figure = codeinjections.getpreviewfigure { name = p, width = width, height = height }
+ if figure then
+ preview = p
+ break
+ end
+ end
+ end
if figure then
local image = img.package(figure.status.private)
appearance = pdfdictionary { N = pdfreference(image.objnum) }
+ if trace_swf then
+ report_swf("using preview %s",preview)
+ end
end
end
@@ -199,5 +302,5 @@ function backends.pdf.nodeinjections.insertswf(spec)
-- factor = spec.factor,
-- label = spec.label,
}
- node.write(pdfannotation_node(spec.width,spec.height,0,annotation()))
+ context(pdfannotation_node(spec.width,spec.height,0,annotation())) -- the context wrap is probably also needed elsewhere
end
diff --git a/Master/texmf-dist/tex/context/base/lpdf-tag.lua b/Master/texmf-dist/tex/context/base/lpdf-tag.lua
index 06f3377bceb..0be9d3452be 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-tag.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-tag.lua
@@ -297,11 +297,14 @@ function nodeinjections.addtags(head)
return head, true
end
+-- this belongs elsewhere (export is not pdf related)
+
function codeinjections.enabletags(tg,lb)
structures.tags.handler = nodeinjections.addtags
tasks.enableaction("shipouts","structures.tags.handler")
tasks.enableaction("shipouts","nodes.handlers.accessibility")
tasks.enableaction("math","noads.handlers.tags")
+ -- maybe also textblock
if trace_tags then
report_tags("enabling structure tags")
end
diff --git a/Master/texmf-dist/tex/context/base/lpdf-u3d.lua b/Master/texmf-dist/tex/context/base/lpdf-u3d.lua
index f5a2bc2fa9a..ac603899722 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-u3d.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-u3d.lua
@@ -22,22 +22,23 @@ local cos, sin, sqrt, pi, atan2, abs = math.cos, math.sin, math.sqrt, math.pi, m
local backends, lpdf = backends, lpdf
-local nodeinjections = backends.pdf.nodeinjections
+local nodeinjections = backends.pdf.nodeinjections
-local pdfconstant = lpdf.constant
-local pdfboolean = lpdf.boolean
-local pdfnumber = lpdf.number
-local pdfunicode = lpdf.unicode
-local pdfdictionary = lpdf.dictionary
-local pdfarray = lpdf.array
-local pdfnull = lpdf.null
-local pdfreference = lpdf.reference
-local pdfimmediateobject = lpdf.immediateobject
+local pdfconstant = lpdf.constant
+local pdfboolean = lpdf.boolean
+local pdfnumber = lpdf.number
+local pdfunicode = lpdf.unicode
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfnull = lpdf.null
+local pdfreference = lpdf.reference
+local pdfflushstreamobject = lpdf.flushstreamobject
+local pdfflushstreamfileobject = lpdf.flushstreamfileobject
-local checkedkey = lpdf.checkedkey
-local limited = lpdf.limited
+local checkedkey = lpdf.checkedkey
+local limited = lpdf.limited
-local pdfannotation_node = nodes.pool.pdfannotation
+local pdfannotation_node = nodes.pool.pdfannotation
local schemes = table.tohash {
"Artwork", "None", "White", "Day", "Night", "Hard",
@@ -397,12 +398,12 @@ local function insert3d(spec) -- width, height, factor, display, controls, label
if js then
local jsref = stored_js[js]
if not jsref then
- jsref = pdfimmediateobject("streamfile",js)
+ jsref = pdfflushstreamfileobject(js)
stored_js[js] = jsref
end
attr.OnInstantiate = pdfreference(jsref)
end
- stored_3d[label] = pdfimmediateobject("streamfile",foundname,attr())
+ stored_3d[label] = pdfflushstreamfileobject(foundname,attr)
stream = 1
else
stream = stream + 1
@@ -436,14 +437,10 @@ local function insert3d(spec) -- width, height, factor, display, controls, label
width = width,
height = height
}
- -- local figure = img.immediatewrite {
- -- stream = ".5 .75 .75 rg 0 0 20 10 re f",
- -- bbox = { 0, 0, 20, 10 }
- -- }
ref = figure.objnum
stored_pr[tag] = ref
end
- if ref then
+ if ref then -- see back-pdf ** .. here we have a local /IM !
local zero, one = pdfnumber(0), pdfnumber(1) -- not really needed
local pw = pdfdictionary {
Type = pdfconstant("XObject"),
@@ -465,12 +462,7 @@ local function insert3d(spec) -- width, height, factor, display, controls, label
},
ProcSet = pdfarray { pdfconstant("PDF"), pdfconstant("ImageC") },
}
- local pwd = pdfimmediateobject(
- "stream",
- format("q /GS gs %s 0 0 %s 0 0 cm /IM Do Q",
- factor*width,factor*height),
- pw()
- )
+ local pwd = pdfflushstreamobject(format("q /GS gs %s 0 0 %s 0 0 cm /IM Do Q",factor*width,factor*height),pw)
annot.AP = pdfdictionary {
N = pdfreference(pwd)
}
diff --git a/Master/texmf-dist/tex/context/base/lpdf-wid.lua b/Master/texmf-dist/tex/context/base/lpdf-wid.lua
index d0247f49a73..13940be9c86 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-wid.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-wid.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['lpdf-wid'] = {
}
local gmatch, gsub, find, lower, format = string.gmatch, string.gsub, string.find, string.lower, string.format
+local stripstring = string.strip
local texbox, texcount = tex.box, tex.count
local settings_to_array = utilities.parsers.settings_to_array
local settings_to_hash = utilities.parsers.settings_to_hash
@@ -16,43 +17,44 @@ local report_attachment = logs.reporter("backend","attachment")
local backends, lpdf, nodes = backends, lpdf, nodes
-local nodeinjections = backends.pdf.nodeinjections
-local codeinjections = backends.pdf.codeinjections
-local registrations = backends.pdf.registrations
-
-local executers = structures.references.executers
-local variables = interfaces.variables
-
-local v_hidden = variables.hidden
-local v_normal = variables.normal
-local v_auto = variables.auto
-local v_embed = variables.embed
-local v_unknown = variables.unknown
-local v_max = variables.max
-
-local pdfconstant = lpdf.constant
-local pdfdictionary = lpdf.dictionary
-local pdfarray = lpdf.array
-local pdfreference = lpdf.reference
-local pdfunicode = lpdf.unicode
-local pdfstring = lpdf.string
-local pdfboolean = lpdf.boolean
-local pdfcolorspec = lpdf.colorspec
-local pdfflushobject = lpdf.flushobject
-local pdfreserveannotation = lpdf.reserveannotation
-local pdfreserveobject = lpdf.reserveobject
-local pdfimmediateobject = lpdf.immediateobject
-local pdfpagereference = lpdf.pagereference
-local pdfshareobjectreference = lpdf.shareobjectreference
-
-local nodepool = nodes.pool
-
-local pdfannotation_node = nodepool.pdfannotation
-
-local hpack_node = node.hpack
-local write_node = node.write
-
-local pdf_border = pdfarray { 0, 0, 0 } -- can be shared
+local nodeinjections = backends.pdf.nodeinjections
+local codeinjections = backends.pdf.codeinjections
+local registrations = backends.pdf.registrations
+
+local executers = structures.references.executers
+local variables = interfaces.variables
+
+local v_hidden = variables.hidden
+local v_normal = variables.normal
+local v_auto = variables.auto
+local v_embed = variables.embed
+local v_unknown = variables.unknown
+local v_max = variables.max
+
+local pdfconstant = lpdf.constant
+local pdfdictionary = lpdf.dictionary
+local pdfarray = lpdf.array
+local pdfreference = lpdf.reference
+local pdfunicode = lpdf.unicode
+local pdfstring = lpdf.string
+local pdfboolean = lpdf.boolean
+local pdfcolorspec = lpdf.colorspec
+local pdfflushobject = lpdf.flushobject
+local pdfflushstreamobject = lpdf.flushstreamobject
+local pdfflushstreamfileobject = lpdf.flushstreamfileobject
+local pdfreserveannotation = lpdf.reserveannotation
+local pdfreserveobject = lpdf.reserveobject
+local pdfpagereference = lpdf.pagereference
+local pdfshareobjectreference = lpdf.shareobjectreference
+
+local nodepool = nodes.pool
+
+local pdfannotation_node = nodepool.pdfannotation
+
+local hpack_node = node.hpack
+local write_node = node.write -- test context(...) instead
+
+local pdf_border = pdfarray { 0, 0, 0 } -- can be shared
-- symbols
@@ -198,12 +200,13 @@ end
lpdf.registerdocumentfinalizer(flushembeddedfiles,"embeddedfiles")
function codeinjections.embedfile(specification)
- local data = specification.data
- local filename = specification.file
- local name = specification.name or ""
- local title = specification.title or ""
- local hash = specification.hash or filename
- local keepdir = specification.keepdir -- can change
+ local data = specification.data
+ local filename = specification.file
+ local name = specification.name or ""
+ local title = specification.title or ""
+ local hash = specification.hash or filename
+ local keepdir = specification.keepdir -- can change
+ local usedname = specification.usedname
if filename == "" then
filename = nil
end
@@ -241,17 +244,18 @@ function codeinjections.embedfile(specification)
end
end
end
- local basename = keepdir == true and filename or file.basename(filename)
-local basename = string.gsub(basename,"%./","")
+ usedname = usedname ~= "" and usedname or filename
+ local basename = keepdir == true and usedname or file.basename(usedname)
+local basename = gsub(basename,"%./","")
local savename = file.addsuffix(name ~= "" and name or basename,"txt") -- else no valid file
local a = pdfdictionary { Type = pdfconstant("EmbeddedFile") }
local f
if data then
- f = pdfimmediateobject("stream",data,a())
+ f = pdfflushstreamobject(data,a)
specification.data = true -- signal that still data but already flushed
else
local foundname = specification.foundname or filename
- f = pdfimmediateobject("streamfile",foundname,a())
+ f = pdfflushstreamfileobject(foundname,a)
end
local d = pdfdictionary {
Type = pdfconstant("Filespec"),
@@ -269,10 +273,11 @@ function nodeinjections.attachfile(specification)
local registered = specification.registered or "<unset>"
local data = specification.data
local hash
+ local filename
if data then
hash = md5.HEX(data)
else
- local filename = specification.file
+ filename = specification.file
if not filename or filename == "" then
report_attachment("missing file specification: registered '%s', using registered instead",registered)
filename = registered
@@ -301,7 +306,7 @@ function nodeinjections.attachfile(specification)
title = ""
end
if author == "" then
- author = v_unknown
+ author = filename or "<unknown>"
end
if title == "" then
title = registered
@@ -377,7 +382,7 @@ end
function nodeinjections.comment(specification) -- brrr: seems to be done twice
nofcomments = nofcomments + 1
- local text = string.strip(specification.data or "")
+ local text = stripstring(specification.data or "")
if stripleading then
text = gsub(text,"[\n\r] *","\n")
end
@@ -442,7 +447,7 @@ end
-- object_2 -> <</Type /Rendition /S /MR /C << /Type /MediaClip ... >> >>
-- rendering -> <</Type /Rendition /S /MS [objref_1 objref_2]>>
--
--- we only work foreward here
+-- we only work foreward here (currently)
-- annotation is to be packed at the tex end
-- aiff audio/aiff
@@ -514,7 +519,12 @@ local function insertrenderingwindow(specification)
Border = pdf_border,
AA = actions,
}
- write_node(pdfannotation_node(specification.width or 0,specification.height or 0,0,d(),r)) -- save ref
+ local width = specification.width or 0
+ local height = specification.height or 0
+ if height == 0 or width == 0 then
+ -- todo: sound needs no window
+ end
+ write_node(pdfannotation_node(width,height,0,d(),r)) -- save ref
return pdfreference(r)
end
diff --git a/Master/texmf-dist/tex/context/base/lpdf-xmp.lua b/Master/texmf-dist/tex/context/base/lpdf-xmp.lua
index c9bead8a5b3..02d37342be9 100644
--- a/Master/texmf-dist/tex/context/base/lpdf-xmp.lua
+++ b/Master/texmf-dist/tex/context/base/lpdf-xmp.lua
@@ -10,20 +10,22 @@ if not modules then modules = { } end modules ['lpdf-xmp'] = {
local format, random, char, gsub, concat = string.format, math.random, string.char, string.gsub, table.concat
local xmlfillin = xml.fillin
-local trace_xmp = false trackers.register("backend.xmp", function(v) trace_xmp = v end)
+local trace_xmp = false trackers.register("backend.xmp", function(v) trace_xmp = v end)
+local trace_info = false trackers.register("backend.info", function(v) trace_info = v end)
-local report_xmp = logs.reporter("backend","xmp")
+local report_xmp = logs.reporter("backend","xmp")
+local report_info = logs.reporter("backend","info")
local backends, lpdf = backends, lpdf
-local codeinjections = backends.pdf.codeinjections -- normally it is registered
+local codeinjections = backends.pdf.codeinjections -- normally it is registered
-local pdfdictionary = lpdf.dictionary
-local pdfconstant = lpdf.constant
-local pdfreference = lpdf.reference
-local pdfobject = lpdf.object
+local pdfdictionary = lpdf.dictionary
+local pdfconstant = lpdf.constant
+local pdfreference = lpdf.reference
+local pdfflushstreamobject = lpdf.flushstreamobject
--- i wonder why this begin end is empty / w (no time now to look into it)
+-- I wonder why this begin end is empty / w (no time now to look into it)
local xpacket = [[
<?xpacket begin="" id="%s"?>
@@ -122,7 +124,11 @@ local addxmpinfo = lpdf.addxmpinfo
function lpdf.addtoinfo(tag,pdfvalue,strvalue)
addtoinfo(tag,pdfvalue)
- addxmpinfo(tag,strvalue or gsub(tostring(pdfvalue),"^%((.*)%)$","%1")) -- hack
+ local value = strvalue or gsub(tostring(pdfvalue),"^%((.*)%)$","%1") -- hack
+ if trace_info then
+ report_info("set '%s' to '%s'",tag,value)
+ end
+ addxmpinfo(tag,value)
end
-- for the do-it-yourselvers
@@ -182,13 +188,7 @@ local function flushxmpinfo()
if not verbose and tex.pdfcompresslevel > 0 then
blob = gsub(blob,">%s+<","><")
end
- local r = pdfobject {
- immediate = true,
- compresslevel = 0,
- type = "stream",
- string = blob,
- attr = md(),
- }
+ local r = pdfflushstreamobject(blob,md,false) -- uncompressed
lpdf.addtocatalog("Metadata",pdfreference(r))
commands.defrostrandomseed() -- hack
diff --git a/Master/texmf-dist/tex/context/base/luat-bas.mkiv b/Master/texmf-dist/tex/context/base/luat-bas.mkiv
index d5075b4cbd9..683c0e92f8a 100644
--- a/Master/texmf-dist/tex/context/base/luat-bas.mkiv
+++ b/Master/texmf-dist/tex/context/base/luat-bas.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Basic \LUA\ Libraries,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -14,11 +14,11 @@
\writestatus{loading}{ConTeXt Lua Macros / Basic Lua Libraries}
\registerctxluafile{l-string} {1.001}
+\registerctxluafile{l-table} {1.001}
\registerctxluafile{l-lpeg} {1.001}
\registerctxluafile{l-boolean}{1.001}
\registerctxluafile{l-number} {1.001}
\registerctxluafile{l-math} {1.001}
-\registerctxluafile{l-table} {1.001}
%registerctxluafile{l-aux} {1.001}
\registerctxluafile{l-io} {1.001}
\registerctxluafile{l-os} {1.001}
diff --git a/Master/texmf-dist/tex/context/base/luat-cbk.lua b/Master/texmf-dist/tex/context/base/luat-cbk.lua
index 031a24e0d85..6622c64cd8c 100644
--- a/Master/texmf-dist/tex/context/base/luat-cbk.lua
+++ b/Master/texmf-dist/tex/context/base/luat-cbk.lua
@@ -9,6 +9,7 @@ if not modules then modules = { } end modules ['luat-cbk'] = {
local insert, remove, find, format = table.insert, table.remove, string.find, string.format
local collectgarbage, type, next = collectgarbage, type, next
local round = math.round
+local sortedhash, tohash = table.sortedhash, table.tohash
local trace_checking = false trackers.register("memory.checking", function(v) trace_checking = v end)
@@ -48,7 +49,7 @@ if not callbacks.list then -- otherwise counters get reset
end
-local delayed = table.tohash {
+local delayed = tohash {
"buildpage_filter",
}
@@ -102,7 +103,7 @@ function callbacks.known(name)
end
function callbacks.report()
- for name, _ in table.sortedhash(list) do
+ for name, _ in sortedhash(list) do
local str = frozen[name]
if str then
report_callbacks("%s: %s -> %s",state(name),name,str)
@@ -115,7 +116,7 @@ end
function callbacks.table()
local NC, NR, verbatim = context.NC, context.NR, context.type
context.starttabulate { "|l|l|p|" }
- for name, _ in table.sortedhash(list) do
+ for name, _ in sortedhash(list) do
NC() verbatim(name) NC() verbatim(state(name)) NC() context(frozen[name] or "") NC() NR()
end
context.stoptabulate()
@@ -190,7 +191,7 @@ end
if trace_calls then
statistics.register("callback details", function()
local t = { } -- todo: pass function to register and quit at nil
- for name, n in table.sortedhash(list) do
+ for name, n in sortedhash(list) do
if n > 0 then
t[#t+1] = format("%s -> %s",name,n)
end
diff --git a/Master/texmf-dist/tex/context/base/luat-cod.lua b/Master/texmf-dist/tex/context/base/luat-cod.lua
index ab21fef09c6..b022f31c3e9 100644
--- a/Master/texmf-dist/tex/context/base/luat-cod.lua
+++ b/Master/texmf-dist/tex/context/base/luat-cod.lua
@@ -6,7 +6,7 @@ if not modules then modules = { } end modules ['luat-cod'] = {
license = "see context related readme files"
}
-local match, gsub, find = string.match, string.gsub, string.find
+local match, gsub, find, format = string.match, string.gsub, string.find, string.format
local texconfig, lua = texconfig, lua
@@ -57,7 +57,7 @@ function lua.registerfinalizer(f,comment)
if type(f) == "function" then
finalizers[#finalizers+1] = { action = f, comment = comment }
else
- print(string.format("fatal error: invalid finalizer, action: %s",finalizer.comment or "unknown"))
+ print(format("fatal error: invalid finalizer, action: %s",finalizer.comment or "unknown"))
os.exit()
end
end
@@ -77,9 +77,10 @@ end
environment = environment or { }
local environment = environment
-local sourcefile = arg and arg[1] or ""
-local sourcepath = gsub (sourcefile,"^\"(.*)\"$", "%1")
-sourcepath = find(sourcepath,"/") and gsub(sourcepath,"/[^/]+$","") or ""
+-- no string.unquoted yet
+
+local sourcefile = gsub(arg and arg[1] or "","^\"(.*)\"$","%1")
+local sourcepath = find(sourcefile,"/") and gsub(sourcefile,"/[^/]+$","") or ""
local targetpath = "."
-- delayed (via metatable):
diff --git a/Master/texmf-dist/tex/context/base/luat-cod.mkiv b/Master/texmf-dist/tex/context/base/luat-cod.mkiv
index 47a89844082..930532df97c 100644
--- a/Master/texmf-dist/tex/context/base/luat-cod.mkiv
+++ b/Master/texmf-dist/tex/context/base/luat-cod.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Code,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -15,12 +15,22 @@
\unprotect
+%D We have this one for a rather long time now but nowadays \ETEX\
+%D provides a command with the same name and different meaning. That
+%D one is available as \type {\normalexpanded}.
+
\long\def\expanded#1{\long\xdef\lastexpanded{\noexpand#1}\lastexpanded}
-%long\def\expanded#1{\normalexpanded{\noexpand#1}} % compatible ## mess
+
+%D We cannot use the following due to the fact that existing usage
+%D demanded duplicating hashes.
+%D
+%D \starttyping
+%D \def\expanded#1{\normalexpanded{\noexpand#1}} % ## mess
+%D \stoptyping
\newif\ifproductionrun
-%D Originally we compiled the lua files externally and loaded
+%D Originally we compiled the \LUA\ files externally and loaded
%D then at runtime, but when the amount grew, we realized that
%D we needed away to store them in the format, which is what
%D bytecode arrays do. And so the following is obsolete:
@@ -43,12 +53,16 @@
%D new functionality. We no longer support the hooks for initializing
%D code as this can be done at the \LUA\ end.
-\def\ctxdirectlua{\directlua\zerocount}
-\def\ctxlatelua {\latelua \zerocount}
-\def\ctxsprint #1{\directlua\zerocount{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens
-\def\ctxwrite #1{\directlua\zerocount{tex.write(#1)}} % saves tokens
-\def\ctxcommand#1{\directlua\zerocount{commands.#1}} % saves tokens
-\def\ctxreport #1{\directlua\zerocount{logs.writer[[#1]]}}
+% we can drop the \zerocount as it's default
+
+\def\ctxdirectlua {\directlua\zerocount}
+\def\ctxlatelua {\latelua \zerocount}
+\def\ctxsprint #1{\directlua\zerocount{tex.sprint(tex.ctxcatcodes,#1)}} % saves tokens
+\def\ctxwrite #1{\directlua\zerocount{tex.write(#1)}} % saves tokens
+\def\ctxcommand #1{\directlua\zerocount{commands.#1}} % saves tokens
+\def\ctxdirectcommand#1{\directlua\zerocount{commands.#1}} % saves tokens
+\def\ctxlatecommand #1{\latelua \zerocount{commands.#1}} % saves tokens
+\def\ctxreport #1{\directlua\zerocount{logs.writer[[#1]]}}
%D Take your choice \unknown
@@ -59,7 +73,7 @@
%D Reporting the version of \LUA\ that we use is done as follows:
-\edef\luaversion{\ctxlua{tex.print(_VERSION)}}
+\edef\luaversion{\ctxwrite{_VERSION}} % no context luaded yet
\def\registerctxluafile#1#2{\ctxlua{lua.registercode("#1","#2")}}
\def\ctxloadluafile #1{\ctxlua{lua.registercode("#1")}}
diff --git a/Master/texmf-dist/tex/context/base/luat-exe.lua b/Master/texmf-dist/tex/context/base/luat-exe.lua
index 42c17ded58d..0e9a943131f 100644
--- a/Master/texmf-dist/tex/context/base/luat-exe.lua
+++ b/Master/texmf-dist/tex/context/base/luat-exe.lua
@@ -17,8 +17,16 @@ resolvers.executers = resolvers.executers or { }
local executers = resolvers.executers
local permitted = { }
+
local osexecute = os.execute
+local osexec = os.exec
+local osspawn = os.spawn
+local iopopen = io.popen
+
local execute = osexecute
+local exec = osexec
+local spawn = osspawn
+local popen = iopopen
local function register(...)
local t = { ... }
@@ -28,33 +36,47 @@ local function register(...)
end
end
-local function finalize() -- todo: os.exec, todo: report ipv print
- execute = function(...)
- -- todo: make more clever first split
- local t, name, arguments = { ... }, "", ""
- local one = t[1]
- if #t == 1 then
- if type(one) == 'table' then
- name, arguments = one, concat(t," ",2,#t)
+local function prepare(...)
+ -- todo: make more clever first split
+ local t = { ... }
+ local one = t[1]
+ if #t == 1 then
+ if type(one) == 'table' then
+ return one, concat(t," ",2,#t)
+ else
+ local name, arguments = match(one,"^(.-)%s+(.+)$")
+ if name and arguments then
+ return name, arguments
else
- name, arguments = match(one,"^(.-)%s+(.+)$")
- if not (name and arguments) then
- name, arguments = one, ""
- end
+ return one, ""
end
- else
- name, arguments = one, concat(t," ",2,#t)
end
+ else
+ return one, concat(t," ",2,#t)
+ end
+end
+
+local function executer(action)
+ return function(...)
+ local name, arguments = prepare(...)
for k=1,#permitted do
local v = permitted[k]
if find(name,v) then
- osexecute(name .. " " .. arguments)
+ return action(name .. " " .. arguments)
-- print("executed: " .. name .. " " .. arguments)
else
report_executers("not permitted: %s %s",name,arguments)
end
end
+ return action("")
end
+end
+
+local function finalize() -- todo: os.exec, todo: report ipv print
+ execute = executer(osexecute)
+ exec = executer(osexec)
+ spawn = executer(osspawn)
+ popen = executer(iopopen)
finalize = function()
report_executers("already finalized")
end
@@ -62,11 +84,17 @@ local function finalize() -- todo: os.exec, todo: report ipv print
report_executers("already finalized, no registration permitted")
end
os.execute = execute
+ os.exec = exec
+ os.spawn = spawn
+ io.popen = popen
end
-executers.finalize = function(...) finalize(...) end
-executers.register = function(...) register(...) end
-executers.execute = function(...) execute (...) end
+executers.finalize = function(...) return finalize(...) end
+executers.register = function(...) return register(...) end
+executers.execute = function(...) return execute (...) end
+executers.exec = function(...) return exec (...) end
+executers.spawn = function(...) return spawn (...) end
+executers.popen = function(...) return popen (...) end
local execution_mode directives.register("system.executionmode", function(v) execution_mode = v end)
local execution_list directives.register("system.executionlist", function(v) execution_list = v end)
diff --git a/Master/texmf-dist/tex/context/base/luat-fio.lua b/Master/texmf-dist/tex/context/base/luat-fio.lua
index 5deb704f607..8e7988c4ee8 100644
--- a/Master/texmf-dist/tex/context/base/luat-fio.lua
+++ b/Master/texmf-dist/tex/context/base/luat-fio.lua
@@ -10,6 +10,8 @@ local texiowrite_nl = (texio and texio.write_nl) or print
local texiowrite = (texio and texio.write) or print
local format = string.format
+local concat = table.concat
+local sequenced = table.sequenced
texconfig.kpse_init = false
texconfig.shell_escape = 't'
@@ -36,6 +38,8 @@ if not resolvers.instance then
local register = callbacks.register
+ -- register('process_jobname' , function(name) return name end, true)
+
register('find_read_file' , function(id,name) return findtexfile(name) end, true)
register('open_read_file' , function( name) return opentexfile(name) end, true)
@@ -81,6 +85,34 @@ if not resolvers.instance then
end
-statistics.register("input load time", function()
- return format("%s seconds", statistics.elapsedtime(resolvers.instance))
+local report_system = logs.reporter("system","files")
+local report_files = logs.reporter("used files")
+
+luatex.registerstopactions(function()
+ local foundintrees = resolvers.instance.foundintrees
+ if #foundintrees > 0 then
+ logs.pushtarget("logfile")
+ logs.newline()
+ report_system("start used files")
+ logs.newline()
+ for i=1,#foundintrees do
+ report_files("%4i: %s",i,sequenced(foundintrees[i]))
+ end
+ logs.newline()
+ report_system("stop used files")
+ logs.newline()
+ logs.poptarget()
+ end
+end)
+
+statistics.register("resource resolver", function()
+ local scandata = resolvers.scandata()
+ return format("loadtime %s seconds, %s scans with scantime %s seconds, %s shared scans, %s found files, scanned paths: %s",
+ resolvers.loadtime(),
+ scandata.n,
+ scandata.time,
+ scandata.shared,
+ #resolvers.instance.foundintrees,
+ concat(scandata.paths," ")
+ )
end)
diff --git a/Master/texmf-dist/tex/context/base/luat-ini.lua b/Master/texmf-dist/tex/context/base/luat-ini.lua
index 9a8651a9cbd..204cc7bd175 100644
--- a/Master/texmf-dist/tex/context/base/luat-ini.lua
+++ b/Master/texmf-dist/tex/context/base/luat-ini.lua
@@ -8,12 +8,9 @@ if not modules then modules = { } end modules ['luat-ini'] = {
-- rather experimental down here ... will change with lua 5.2 --
---~ local ctxcatcodes = tex.ctxcatcodes
-
local debug = require "debug"
local string, table, lpeg, math, io, system = string, table, lpeg, math, io, system
local next, setfenv = next, setfenv or debug.setfenv
-local format = string.format
local mark = utilities.storage.mark
@@ -144,7 +141,7 @@ function lua.registername(name,message)
lua.numbers[name] = lnn
end
lua.name[lnn] = message
- tex.write(lnn)
+ context(lnn)
-- initialize once
if name ~= "isolateddata" then
protect_full(name or "shareddata")
@@ -180,7 +177,7 @@ function document.getargument(key,default)
v = (v and "yes") or "no"
document.arguments[key] = v
end
- tex.sprint(tex.ctxcatcodes,v or default or "")
+ context(v or default or "")
end
function document.setfilename(i,name)
@@ -188,5 +185,5 @@ function document.setfilename(i,name)
end
function document.getfilename(i)
- tex.sprint(tex.ctxcatcodes,document.files[i] or "")
+ context(document.files[i] or "")
end
diff --git a/Master/texmf-dist/tex/context/base/luat-ini.mkiv b/Master/texmf-dist/tex/context/base/luat-ini.mkiv
index a79ef6a02ac..46b2d1f7ffd 100644
--- a/Master/texmf-dist/tex/context/base/luat-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/luat-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -21,38 +21,42 @@
%D we keep outside the format. We will keep code outside \TEX\ files as
%D much as possible.
-\ifx\setnaturalcatcodes\undefined \let\setnaturalcatcodes\relax \fi
-\ifx\obeylualines \undefined \let\obeylualines \relax \fi
-\ifx\obeyluatokens \undefined \let\obeyluatokens \relax \fi
+\ifdefined\setnaturalcatcodes \else \let\setnaturalcatcodes\relax \fi
+\ifdefined\obeylualines \else \let\obeylualines \relax \fi
+\ifdefined\obeyluatokens \else \let\obeyluatokens \relax \fi
%D A few more goodies:
-\long\def\dostartlua
+\unexpanded\def\startlua {\luat_start_lua } \let\stoplua \relax % tex catcodes
+\unexpanded\def\startluacode{\luat_start_lua_code} \let\stopluacode\relax % lua catcodes
+
+% It might makes sense to have a \type {\directelua} so that we can avoid
+% the \type {\normalexpanded} around \type {\directlua}. Something to discuss
+% in the team.
+
+\def\luat_start_lua
{\begingroup
\obeylualines
- \dodostartlua}
+ \luat_start_lua_indeed}
-\long\def\dodostartlua#1\stoplua
+\def\luat_start_lua_indeed#1\stoplua
{\normalexpanded{\endgroup\noexpand\directlua\zerocount{#1}}}
-\long\def\dostartluacode
+\def\luat_start_lua_code
{\begingroup
\obeylualines
\obeyluatokens
- \dodostartluacode}
+ \luat_start_lua_code_indeed}
-\long\def\dodostartluacode#1\stopluacode
+\def\luat_start_lua_code_indeed#1\stopluacode
{\normalexpanded{\endgroup\noexpand\directlua\zerocount{#1}}}
-\unexpanded\def\startlua {\dostartlua } % tex catcodes
-\unexpanded\def\startluacode{\dostartluacode} % lua catcodes
-
%D Some delayed definitions:
-\ifx\obeylines \undefined \let\obeylines \relax \fi
-\ifx\obeyedline \undefined \let\obeyedline \relax \fi
-\ifx\obeyspaces \undefined \let\obeyspaces \relax \fi
-\ifx\obeyedspace \undefined \let\obeyedspace \relax \fi
+\ifdefined\obeylines \else \let\obeylines \relax \fi
+\ifdefined\obeyedline \else \let\obeyedline \relax \fi
+\ifdefined\obeyspaces \else \let\obeyspaces \relax \fi
+\ifdefined\obeyedspace \else \let\obeyedspace \relax \fi
\let\obeylualines\relax
@@ -91,7 +95,7 @@
\to \everyluacode
\def\obeyluatokens
- {\setcatcodetable \luacatcodes
+ {\setcatcodetable\luacatcodes
\the\everyluacode}
%D \macros
@@ -104,19 +108,19 @@
%D Beware: because \type {\expanded} is een convert command, the error
%D message will show \type{<inserted text>} as part of the message.
-\long\def\dostartnamedluacode#1%
+\def\luat_start_named_lua_code#1%
{\begingroup
\obeylualines
\obeyluatokens
- \csname dodostartnamed#1\v!code\endcsname}
+ \csname\??lu:c:#1\endcsname}
\unexpanded\def\definenamedlua[#1]#2[#3]% no optional arg handling here yet
- {\ifcsname dodostartnamed#1\v!code\endcsname\else
+ {\ifcsname\??lu:c:#1\endcsname \else
\scratchcounter\ctxlua{lua.registername("#1","#3")}%
- \normalexpanded{\long\edef\csname dodostartnamed#1\v!code\endcsname##1\csname\e!stop#1\v!code\endcsname}%
+ \normalexpanded{\edef\csname\??lu:c:#1\endcsname##1\csname\e!stop#1\v!code\endcsname}%
{\endgroup\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}%
- \long\expandafter\def \csname\e!start#1\v!code\endcsname {\dostartnamedluacode{#1}}%
- \long\expandafter\edef\csname #1\v!code\endcsname##1{\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}%
+ \expandafter\def \csname\e!start#1\v!code\endcsname {\luat_start_named_lua_code{#1}}%
+ \expandafter\edef\csname #1\v!code\endcsname##1{\noexpand\directlua\the\scratchcounter{protect("#1\s!data")##1}}%
\fi}
%D We predefine a few.
@@ -131,21 +135,21 @@
%D
%D \startbuffer
%D \startluacode
-%D tex.print("LUA")
+%D context("LUA")
%D \stopluacode
%D
%D \startusercode
-%D global.tex.print("USER 1")
-%D tex.print("USER 2")
+%D global.context("USER 1")
+%D context("USER 2")
%D if characters then
-%D tex.print("ACCESS")
+%D context("ACCESS")
%D else
-%D tex.print("NO ACCESS")
+%D context("NO ACCESS")
%D end
%D \stopusercode
%D \stopbuffer
%D
-%D \typebuffer \getbuffer
+%D \typebuffer
%D We need a way to pass strings safely to \LUA\ without the
%D need for tricky escaping. Compare:
@@ -192,13 +196,15 @@
{\begingroup
\obeylualines
\obeyluatokens
- \dostartluaparameterset{#1}}
+ \luat_start_lua_parameter_set{#1}}
-\long\def\dostartluaparameterset#1#2\stopluaparameterset
+\def\luat_start_lua_parameter_set#1#2\stopluaparameterset
{\ctxlua{parametersets["#1"]={#2}}%
\endgroup}
-\def\luaparameterset#1#2{\ctxlua{parametersets["#1"]={#2} tex.sprint("#1")}}
+\let\stopluaparameterset\relax
+
+\def\luaparameterset#1#2{\ctxlua{parametersets["#1"]={#2} context("#1")}}
% todo: \mergeparameterset
@@ -225,17 +231,19 @@
%D \ctxluacode{context("%0.5f",1/3)}
%D \stoptyping
-\long\def\ctxluacode
+\unexpanded\def\ctxluacode
{\begingroup
\obeylualines
\obeyluatokens
\catcode\leftbraceasciicode \plusone
\catcode\rightbraceasciicode\plustwo
- \afterassignment\doctxluacode
+ \afterassignment\luat_lua_code
\scratchtoks=}
-\def\doctxluacode
- {\normalexpanded{\endgroup\noexpand\directlua\zerocount\expandafter{\the\scratchtoks}}}
+% Hm, are we sure that the \* commands work out okay here? We could probably
+% use \setcatcodetable\luacatcodes instead of \obeyluatokens now.
+\def\luat_lua_code
+ {\normalexpanded{\endgroup\noexpand\directlua\zerocount\expandafter{\the\scratchtoks}}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/luat-iop.lua b/Master/texmf-dist/tex/context/base/luat-iop.lua
index 091639de231..5512b258edb 100644
--- a/Master/texmf-dist/tex/context/base/luat-iop.lua
+++ b/Master/texmf-dist/tex/context/base/luat-iop.lua
@@ -11,138 +11,185 @@ if not modules then modules = { } end modules ['luat-iop'] = {
-- we can feed back specific patterns and paths into the next
-- mechanism
-local lower, find, sub = string.lower, string.find, string.sub
+-- os.execute os.exec os.spawn io.fopen
+-- os.remove lfs.chdir lfs.mkdir
+-- io.open zip.open epdf.open mlib.new
-local allocate = utilities.storage.allocate
+-- cache
-local ioinp = io.inp if not ioinp then ioinp = { } io.inp = ioinp end
-local ioout = io.out if not ioout then ioout = { } io.out = ioout end
+local topattern, find = string.topattern, string.find
-ioinp.modes, ioout.modes = allocate(), allocate()
+local report_limiter = logs.reporter("system","limiter")
-local inp_blocked, inp_permitted = { }, { }
-local out_blocked, out_permitted = { }, { }
+-- the basic methods
-local function i_inhibit(name) inp_blocked [#inp_blocked +1] = name end
-local function o_inhibit(name) out_blocked [#out_blocked +1] = name end
-local function i_permit (name) inp_permitted[#inp_permitted+1] = name end
-local function o_permit (name) out_permitted[#out_permitted+1] = name end
-
-ioinp.inhibit, ioinp.permit = i_inhibit, o_permit
-ioout.inhibit, ioout.permit = o_inhibit, o_permit
-
-local blockedopeners = { } -- *.open(name,method)
-
-function io.registeropener(func)
- blockedopeners[#blockedopeners+1] = func
+local function match(ruleset,name)
+ local n = #ruleset
+ if n > 0 then
+ for i=1,n do
+ local r = ruleset[i]
+ if find(name,r[1]) then
+ return r[2]
+ end
+ end
+ return false
+ else
+ -- nothing defined (or any)
+ return true
+ end
end
-local function checked(name,blocked,permitted)
- local n = lower(name)
- for _,b in next, blocked do
- if find(n,b) then
- for _,p in next, permitted do
- if find(n,p) then
- return true
- end
- end
- return false
+local function protect(ruleset,proc)
+ return function(name,...)
+ if name == "" then
+ -- report_limiter("no access permitted: <no name>") -- can happen in mplib code
+ return nil, "no name given"
+ elseif match(ruleset,name) then
+ return proc(name,...)
+ else
+ report_limiter("no access permitted: %s",name)
+ return nil, name .. ": no access permitted"
end
end
- return true
end
-function io.finalizeopeners(func)
- if #out_blocked > 0 or #inp_blocked > 0 then
- local open = func -- why not directly?
- return function(name,method)
- if method and find(method,'[wa]') then
- if #out_blocked > 0 and not checked(name,out_blocked,out_permitted) then
- -- print("writing to " .. name .. " is not permitted")
- return nil
+function io.limiter(preset)
+ preset = preset or { }
+ local ruleset = { }
+ for i=1,#preset do
+ local p = preset[i]
+ local what, spec = p[1] or "", p[2] or ""
+ if spec == "" then
+ -- skip 'm
+ elseif what == "tree" then
+ resolvers.dowithpath(spec, function(r)
+ local spec = resolvers.resolve(r) or ""
+ if spec ~= "" then
+ ruleset[#ruleset+1] = { topattern(spec,true), true }
end
- else
- if #inp_blocked > 0 and not checked(name,inp_blocked,inp_permitted) then
- -- print("reading from " .. name .. " is not permitted")
- return nil
- end
- end
- return open(name,method)
+ end)
+ elseif what == "permit" then
+ ruleset[#ruleset+1] = { topattern(spec,true), true }
+ elseif what == "forbid" then
+ ruleset[#ruleset+1] = { topattern(spec,true), false }
end
+ end
+ if #ruleset > 0 then
+ return {
+ match = function(name) return match (ruleset,name) end,
+ protect = function(proc) return protect(ruleset,proc) end,
+ }
else
- return func
+ return {
+ match = function(name) return true end,
+ protect = proc,
+ }
end
end
---~ io.inp.inhibit('^%.')
---~ io.inp.inhibit('^/etc')
---~ io.inp.inhibit('/windows/')
---~ io.inp.inhibit('/winnt/')
---~ io.inp.permit('c:/windows/wmsetup.log')
-
---~ io.open = io.finalizeopeners(io.open)
+-- a few handlers
---~ f = io.open('.tex') print(f)
---~ f = io.open('tufte.tex') print(f)
---~ f = io.open('t:/sources/tufte.tex') print(f)
---~ f = io.open('/etc/passwd') print(f)
---~ f = io.open('c:/windows/crap.log') print(f)
---~ f = io.open('c:/windows/wmsetup.log') print(f)
+io.i_limiters = { }
+io.o_limiters = { }
--- restricted
-
-function ioinp.modes.restricted()
- i_inhibit('^%.[%a]')
+function io.i_limiter(v)
+ local i = io.i_limiters[v]
+ if i then
+ local i_limiter = io.limiter(i)
+ function io.i_limiter()
+ return i_limiter
+ end
+ return i_limiter
+ end
end
-function ioout.modes.restricted()
- o_inhibit('^%.[%a]')
+function io.o_limiter(v)
+ local o = io.o_limiters[v]
+ if o then
+ local o_limiter = io.limiter(o)
+ function io.o_limiter()
+ return o_limiter
+ end
+ return o_limiter
+ end
end
--- paranoid
+-- the real thing (somewhat fuzzy as we need to know what gets done)
-function ioinp.modes.paranoid()
- i_inhibit('.*')
- i_inhibit('%.%.')
- i_permit('^%./')
- i_permit('[^/]')
- resolvers.dowithpath('TEXMF',i_permit)
-end
+local i_opener, i_limited = io.open, false
+local o_opener, o_limited = io.open, false
-function ioout.modes.paranoid()
- o_inhibit('.*')
- resolvers.dowithpath('TEXMFOUTPUT',o_permit)
+local function i_register(v)
+ if not i_limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ local protect = i_limiter.protect
+ i_opener = protect(i_opener)
+ i_limited = true
+ report_limiter("input mode: %s",v)
+ end
+ end
end
--- handy
+local function o_register(v)
+ if not o_limited then
+ local o_limiter = io.o_limiter(v)
+ if o_limiter then
+ local protect = o_limiter.protect
+ o_opener = protect(o_opener)
+ o_limited = true
+ report_limiter("output mode: %s",v)
+ end
+ end
+end
-function ioinp.modes.handy()
- i_inhibit('%.%.')
- if os.type == 'windows' then
- i_inhibit('/windows/')
- i_inhibit('/winnt/')
+function io.open(name,method)
+ if method and find(method,"[wa]") then
+ return o_opener(name,method)
else
- i_inhibit('^/etc')
+ return i_opener(name,method)
end
end
-function ioout.modes.handy()
- o_inhibit('.*')
- o_permit('%./')
- o_permit('^%./')
- o_permit('[^/]')
+directives.register("system.inputmode", i_register)
+directives.register("system.outputmode", o_register)
+
+local i_limited = false
+local o_limited = false
+
+local function i_register(v)
+ if not i_limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ local protect = i_limiter.protect
+ lfs.chdir = protect(lfs.chdir) -- needs checking
+ i_limited = true
+ end
+ end
+end
+
+local function o_register(v)
+ if not o_limited then
+ local o_limiter = io.o_limiter(v)
+ if o_limiter then
+ local protect = o_limiter.protect
+ os.remove = protect(os.remove) -- rather okay
+ lfs.chdir = protect(lfs.chdir) -- needs checking
+ lfs.mkdir = protect(lfs.mkdir) -- needs checking
+ o_limited = true
+ end
+ end
end
-local input_mode directives.register("system.inputmode", function(v) input_mode = v end)
-local output_mode directives.register("system.outputmode", function(v) output_mode = v end)
+directives.register("system.inputmode", i_register)
+directives.register("system.outputmode", o_register)
+
+-- the definitions
+
+local limiters = resolvers.variable("limiters")
-function io.checkopeners()
- local inp = input_mode or resolvers.variable("input_mode") -- or ... will become obsolete
- local out = output_mode or resolvers.variable("output_mode") -- or ... will become obsolete
- inp = inp and ioinp.modes[inp]
- out = out and ioinp.modes[out]
- if inp then inp() end
- if out then out() end
+if limiters then
+ io.i_limiters = limiters.input or { }
+ io.o_limiters = limiters.output or { }
end
---~ io.checkopeners()
diff --git a/Master/texmf-dist/tex/context/base/luat-lib.mkiv b/Master/texmf-dist/tex/context/base/luat-lib.mkiv
index 83b96639b79..5a53b7ea231 100644
--- a/Master/texmf-dist/tex/context/base/luat-lib.mkiv
+++ b/Master/texmf-dist/tex/context/base/luat-lib.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Libraries,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/luat-lua.lua b/Master/texmf-dist/tex/context/base/luat-lua.lua
index 50492540d25..d319508f004 100644
--- a/Master/texmf-dist/tex/context/base/luat-lua.lua
+++ b/Master/texmf-dist/tex/context/base/luat-lua.lua
@@ -6,11 +6,13 @@ if not modules then modules = { } end modules ['luat-lua'] = {
license = "see context related readme files"
}
+local concat = table.concat
+
if lua then do
local delayed = { }
- local function flushdelayed(...)
+ function lua.flushdelayed(...)
local t = delayed
delayed = { }
for i=1, #t do
@@ -23,7 +25,7 @@ if lua then do
end
function lua.flush(...)
- tex.sprint("\\directlua{flushdelayed(",table.concat({...},','),")}")
+ context.directlua("lua.flushdelayed(%s)",concat({...},','))
end
end end
@@ -32,12 +34,14 @@ end end
--~
--~ function test(n)
--~ lua.delay(function(...)
---~ tex.sprint(string.format("pi: %s %s %s\\par",...))
+--~ context("pi: %s %s %s",...)
+--~ context.par()
--~ end)
--~ lua.delay(function(...)
---~ tex.sprint(string.format("more pi: %s %s %s\\par",...))
+--~ context("more pi: %s %s %s",...)
+--~ context.par()
--~ end)
---~ tex.sprint(string.format("\\setbox0=\\hbox{%s}",math.pi*n))
+--~ context("\\setbox0=\\hbox{%s}",math.pi*n)
--~ local box = tex.box[0]
--~ lua.flush(box.width,box.height,box.depth)
--~ end
diff --git a/Master/texmf-dist/tex/context/base/luat-mac.lua b/Master/texmf-dist/tex/context/base/luat-mac.lua
index 0dc6593c659..75d52781c93 100644
--- a/Master/texmf-dist/tex/context/base/luat-mac.lua
+++ b/Master/texmf-dist/tex/context/base/luat-mac.lua
@@ -6,6 +6,20 @@ if not modules then modules = { } end modules ['luat-mac'] = {
license = "see context related readme files"
}
+-- Sometimes we run into situations like:
+--
+-- \def\foo#1{\expandafter\def\csname#1\endcsname}
+--
+-- As this confuses the parser, the following should be used instead:
+--
+-- \def\foo#1{\expandafter\normaldef\csname#1\endcsname}
+
+-- todo:
+--
+-- \def\dosomething#content{%%%<= fine with “#1â€
+-- % { %%% Open unbalanced brace breaks macros.
+-- }
+
local P, V, S, R, C, Cs, Cmt, Carg = lpeg.P, lpeg.V, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.Cmt, lpeg.Carg
local lpegmatch, patterns = lpeg.match, lpeg.patterns
@@ -28,7 +42,7 @@ local function set(s)
local ns = #stack
local h = hashes[ns]
if not h then
- h = rep("#",ns)
+ h = rep("#",2^(ns-1))
hashes[ns] = h
end
m = h .. n
@@ -84,8 +98,8 @@ local csname = (R("AZ","az") + S("@?!_"))^1
local longname = (longleft/"") * (nolong^1) * (longright/"")
local variable = P("#") * Cs(name + longname)
local escapedname = escape * csname
-local definer = escape * (P("def") + P("egx") * P("def")) -- tex
-local setter = escape * P("set") * (P("u")^-1 * P("egx")^-1) * P("value") -- context specific
+local definer = escape * (P("def") + S("egx") * P("def")) -- tex
+local setter = escape * P("set") * (P("u")^-1 * S("egx")^-1) * P("value") -- context specific
--- + escape * P("install") * (1-P("handler"))^1 * P("handler") -- context specific
local startcode = P("\\starttexdefinition") -- context specific
local stopcode = P("\\stoptexdefinition") -- context specific
@@ -112,7 +126,7 @@ local poplocal = always / pop
local declaration = variable / set
local identifier = variable / get
-local argument = leftbrace * ((identifier + (1-rightbrace))^0) * rightbrace
+local argument = P { leftbrace * ((identifier + V(1) + (1 - leftbrace - rightbrace))^0) * rightbrace }
local function matcherror(str,pos)
report_macros("runaway definition at: %s",sub(str,pos-30,pos))
@@ -122,9 +136,9 @@ local grammar = { "converter",
texcode = pushlocal
* startcode
* spaces
- * name
- * spaces
- * (declaration + furthercomment + (1 - newline - space))^0
+ * (csname * spaces)^1 -- new: multiple, new:csname instead of name
+ -- * (declaration + furthercomment + (1 - newline - space))^0
+ * ((declaration * (space^0/""))^1 + furthercomment + (1 - newline - space))^0 -- accepts #a #b #c
* V("texbody")
* stopcode
* poplocal,
@@ -230,42 +244,90 @@ if resolvers.schemes then
end
---~ print(macros.preprocessed([[\def\bla#bla{bla#{bla}}]]))
---~ print(macros.preprocessed([[\def\bla#bla{#{bla}bla}]]))
---~ print(macros.preprocessed([[\def\blä#{blá}{blà:#{blá}}]]))
---~ print(macros.preprocessed([[\def\blä#bla{blà:#bla}]]))
---~ print(macros.preprocessed([[\setvalue{xx}#bla{blà:#bla}]]))
---~ print(macros.preprocessed([[\def\foo#bar{\setvalue{xx#bar}{#bar}}]]))
---~ print(macros.preprocessed([[\def\bla#bla{bla:#{bla}}]]))
---~ print(macros.preprocessed([[\def\bla_bla#bla{bla:#bla}]]))
---~ print(macros.preprocessed([[\def\test#oeps{test:#oeps}]]))
---~ print(macros.preprocessed([[\def\test_oeps#oeps{test:#oeps}]]))
---~ print(macros.preprocessed([[\def\test#oeps{test:#{oeps}}]]))
---~ print(macros.preprocessed([[\def\test#{oeps:1}{test:#{oeps:1}}]]))
---~ print(macros.preprocessed([[\def\test#{oeps}{test:#oeps}]]))
---~ print(macros.preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}]]))
---~ print(macros.preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}}]]))
---~ print(macros.preprocessed([[% test
---~ \def\test#oeps{#oeps} % {test}
---~ % test
---~
---~ % test
---~ two
---~ %test]]))
---~ print(macros.preprocessed([[
---~ \def\scrn_button_make_normal#namespace#current#currentparameter#text%
---~ {\ctxlua{structures.references.injectcurrentset(nil,nil)}%
---~ % \hbox attr \referenceattribute \lastreferenceattribute {\localframed[#namespace:#current]{#text}}}
---~ \hbox attr \referenceattribute \lastreferenceattribute {\directlocalframed[#namespace:#current]{#text}}}
---~ ]]))
---~
---~ print(macros.preprocessed([[
---~ \def\definefoo[#name]%
---~ {\setvalue{start#name}{\dostartfoo{#name}}}
---~ \def\dostartfoo#name%
---~ {\def\noexpand\next#content\expandafter\noexpand\csname stop#name\endcsname{#name : #content}%
---~ \next}
---~ \def\dostartfoo#name%
---~ {\normalexpanded{\def\noexpand\next#content\expandafter\noexpand\csname stop#name\endcsname}{#name : #content}%
---~ \next}
---~ ]]))
+-- print(macros.preprocessed(
+-- [[
+-- \starttexdefinition unexpanded test #aa #bb #cc
+-- test
+-- \stoptexdefinition
+-- ]]))
+
+-- print(macros.preprocessed([[\def\bla#bla{bla#{bla}}]]))
+-- print(macros.preprocessed([[\def\bla#bla{#{bla}bla}]]))
+-- print(macros.preprocessed([[\def\blä#{blá}{blà:#{blá}}]]))
+-- print(macros.preprocessed([[\def\blä#bla{blà:#bla}]]))
+-- print(macros.preprocessed([[\setvalue{xx}#bla{blà:#bla}]]))
+-- print(macros.preprocessed([[\def\foo#bar{\setvalue{xx#bar}{#bar}}]]))
+-- print(macros.preprocessed([[\def\bla#bla{bla:#{bla}}]]))
+-- print(macros.preprocessed([[\def\bla_bla#bla{bla:#bla}]]))
+-- print(macros.preprocessed([[\def\test#oeps{test:#oeps}]]))
+-- print(macros.preprocessed([[\def\test_oeps#oeps{test:#oeps}]]))
+-- print(macros.preprocessed([[\def\test#oeps{test:#{oeps}}]]))
+-- print(macros.preprocessed([[\def\test#{oeps:1}{test:#{oeps:1}}]]))
+-- print(macros.preprocessed([[\def\test#{oeps}{test:#oeps}]]))
+-- print(macros.preprocessed([[\def\x[#a][#b][#c]{\setvalue{\y{#a}\z{#b}}{#c}}]]))
+-- print(macros.preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}]]))
+-- print(macros.preprocessed([[\def\test#{oeps}{test:#oeps \halign{##\cr #oeps\cr}}]]))
+-- print(macros.preprocessed([[% test
+-- \def\test#oeps{#oeps} % {test}
+-- % test
+--
+-- % test
+-- two
+-- %test]]))
+-- print(macros.preprocessed([[
+-- \def\scrn_button_make_normal#namespace#current#currentparameter#text%
+-- {\ctxlua{structures.references.injectcurrentset(nil,nil)}%
+-- % \hbox attr \referenceattribute \lastreferenceattribute {\localframed[#namespace:#current]{#text}}}
+-- \hbox attr \referenceattribute \lastreferenceattribute {\directlocalframed[#namespace:#current]{#text}}}
+-- ]]))
+--
+-- print(macros.preprocessed([[
+-- \def\definefoo[#name]%
+-- {\setvalue{start#name}{\dostartfoo{#name}}}
+-- \def\dostartfoo#name%
+-- {\def\noexpand\next#content\expandafter\noexpand\csname stop#name\endcsname{#name : #content}%
+-- \next}
+-- \def\dostartfoo#name%
+-- {\normalexpanded{\def\noexpand\next#content\expandafter\noexpand\csname stop#name\endcsname}{#name : #content}%
+-- \next}
+-- ]]))
+
+-- Just an experiment:
+--
+-- \catcode\numexpr"10FF25=\commentcatcode %% > 110000 is invalid
+--
+-- We could have a push/pop mechanism but binding to txtcatcodes
+-- is okay too.
+
+local txtcatcodes = false -- also signal and yet unknown
+
+local commentsignal = utf.char(0x10FF25)
+
+local encodecomment = P("%%") / commentsignal --
+----- encodepattern = Cs(((1-encodecomment)^0 * encodecomment)) -- strips but not nice for verbatim
+local encodepattern = Cs((encodecomment + 1)^0)
+local decodecomment = P(commentsignal) / "%%%%" -- why doubles here?
+local decodepattern = Cs((decodecomment + 1)^0)
+
+function resolvers.macros.encodecomment(str)
+ if txtcatcodes and tex.catcodetable == txtcatcodes then
+ return lpegmatch(encodepattern,str) or str
+ else
+ return str
+ end
+end
+
+function resolvers.macros.decodecomment(str) -- normally not needed
+ return txtcatcodes and lpegmatch(decodepattern,str) or str
+end
+
+-- resolvers.macros.commentsignal = commentsignal
+-- resolvers.macros.encodecommentpattern = encodepattern
+-- resolvers.macros.decodecommentpattern = decodepattern
+
+function resolvers.macros.enablecomment(thecatcodes)
+ if not txtcatcodes then
+ txtcatcodes = thecatcodes or catcodes.numbers.txtcatcodes
+ utilities.sequencers.appendaction(resolvers.openers.helpers.textlineactions,"system","resolvers.macros.encodecomment")
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/luat-run.lua b/Master/texmf-dist/tex/context/base/luat-run.lua
index 51856640d2d..ce25d1f55a3 100644
--- a/Master/texmf-dist/tex/context/base/luat-run.lua
+++ b/Master/texmf-dist/tex/context/base/luat-run.lua
@@ -138,13 +138,14 @@ directives.register("system.synctex", function(v)
else
report_system("synctex functionality is disabled!")
end
- -- current this is bugged:
+ -- currently this is bugged:
tex.synctex = synctex and 1 or 0
-- so for the moment we need:
+ context.normalsynctex()
if synctex then
- tex.print("\\normalsynctex\\plusone")
+ context.plusone()
else
- tex.print("\\normalsynctex\\zerocount")
+ context.zerocount()
end
end)
diff --git a/Master/texmf-dist/tex/context/base/luat-sto.lua b/Master/texmf-dist/tex/context/base/luat-sto.lua
index 946ce375607..30bb7d5bb9b 100644
--- a/Master/texmf-dist/tex/context/base/luat-sto.lua
+++ b/Master/texmf-dist/tex/context/base/luat-sto.lua
@@ -6,9 +6,11 @@ if not modules then modules = { } end modules ['luat-sto'] = {
license = "see context related readme files"
}
-local type, next, setmetatable, getmetatable = type, next, setmetatable, getmetatable
+-- we could nil some function in the productionrun
+
+local type, next, setmetatable, getmetatable, collectgarbage = type, next, setmetatable, getmetatable, collectgarbage
local gmatch, format, write_nl = string.gmatch, string.format, texio.write_nl
-local serialize, concat = table.serialize, table.concat
+local serialize, concat, sortedhash = table.serialize, table.concat, table.sortedhash
local bytecode = lua.bytecode
local report_storage = logs.reporter("system","storage")
@@ -72,6 +74,22 @@ end
lua.registerfinalizer(dump,"dump storage")
+-- to be tested with otf caching:
+
+function lua.collectgarbage(threshold)
+ local current = collectgarbage("count")
+ local threshold = threshold or 256 * 1024
+ while true do
+ collectgarbage("collect")
+ local previous = collectgarbage("count")
+ if current - previous < threshold then
+ break
+ else
+ current = previous
+ end
+ end
+end
+
-- we also need to count at generation time (nicer for message)
--~ if lua.bytecode then -- from 0 upwards
@@ -97,20 +115,24 @@ end
function statistics.reportstorage(whereto)
whereto = whereto or "term and log"
write_nl(whereto," ","stored tables:"," ")
- for k,v in table.sortedhash(storage.data) do
+ for k,v in sortedhash(storage.data) do
write_nl(whereto,format("%03i %s",k,v[1]))
end
write_nl(whereto," ","stored modules:"," ")
- for k,v in table.sortedhash(lua.bytedata) do
+ for k,v in sortedhash(lua.bytedata) do
write_nl(whereto,format("%03i %s %s",k,v[2],v[1]))
end
write_nl(whereto," ","stored attributes:"," ")
- for k,v in table.sortedhash(attributes.names) do
+ for k,v in sortedhash(attributes.names) do
write_nl(whereto,format("%03i %s",k,v))
end
write_nl(whereto," ","stored catcodetables:"," ")
- for k,v in table.sortedhash(catcodes.names) do
- write_nl(whereto,format("%03i %s",k,table.concat(v," ")))
+ for k,v in sortedhash(catcodes.names) do
+ write_nl(whereto,format("%03i %s",k,concat(v," ")))
+ end
+ write_nl(whereto," ","used corenamespaces:"," ")
+ for k,v in sortedhash(interfaces.corenamespaces) do
+ write_nl(whereto,format("%03i %s",k,v))
end
write_nl(whereto," ")
end
diff --git a/Master/texmf-dist/tex/context/base/lxml-aux.lua b/Master/texmf-dist/tex/context/base/lxml-aux.lua
index 4798fe06a7a..7df6179a055 100644
--- a/Master/texmf-dist/tex/context/base/lxml-aux.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-aux.lua
@@ -18,10 +18,12 @@ local xml = xml
local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
+local xmlfilter = xml.filter
local type, setmetatable, getmetatable = type, setmetatable, getmetatable
-local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
-local gmatch, gsub = string.gmatch, string.gsub
+local insert, remove, fastcopy, concat = table.insert, table.remove, table.fastcopy, table.concat
+local gmatch, gsub, format = string.gmatch, string.gsub, string.format
+local utfbyte = utf.byte
local function report(what,pattern,c,e)
report_xml("%s element '%s' (root: '%s', position: %s, index: %s, pattern: %s)",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
@@ -166,7 +168,7 @@ local function xmltoelement(whatever,root)
end
local element
if type(whatever) == "string" then
- element = xmlinheritedconvert(whatever,root)
+ element = xmlinheritedconvert(whatever,root) -- beware, not really a root
else
element = whatever -- we assume a table
end
@@ -198,18 +200,30 @@ local function copiedelement(element,newparent)
end
function xml.delete(root,pattern)
- local collected = xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local p = e.__p__
- if p then
- if trace_manipulations then
- report('deleting',pattern,c,e)
+ if not pattern or pattern == "" then
+ local p = root.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',"--",c,root)
+ end
+ local d = p.dt
+ remove(d,root.ni)
+ redo_ni(d) -- can be made faster and inlined
+ end
+ else
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ local p = e.__p__
+ if p then
+ if trace_manipulations then
+ report('deleting',pattern,c,e)
+ end
+ local d = p.dt
+ remove(d,e.ni)
+ redo_ni(d) -- can be made faster and inlined
end
- local d = p.dt
- remove(d,e.ni)
- redo_ni(d) -- can be made faster and inlined
end
end
end
@@ -272,32 +286,39 @@ end
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k, rri = r.dt, e.ni, r.ri
- local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
- if edt then
- local be, af
- local cp = copiedelement(element,e)
- if prepend then
- be, af = cp, edt
- else
- be, af = edt, cp
- end
- local bn = #be
- for i=1,#af do
- bn = bn + 1
- be[bn] = af[i]
- end
- if rri then
- r.dt[rri].dt = be
- else
- d[k].dt = be
- end
- redo_ni(d)
+ local function inject_e(e)
+ local r = e.__p__
+ local d, k, rri = r.dt, e.ni, r.ri
+ local edt = (rri and d[rri].dt) or (d and d[k] and d[k].dt)
+ if edt then
+ local be, af
+ local cp = copiedelement(element,e)
+ if prepend then
+ be, af = cp, edt
+ else
+ be, af = edt, cp
+ end
+ local bn = #be
+ for i=1,#af do
+ bn = bn + 1
+ be[bn] = af[i]
+ end
+ if rri then
+ r.dt[rri].dt = be
+ else
+ d[k].dt = be
end
+ redo_ni(d)
+ end
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ inject_e(collected)
+ else
+ for c=1,#collected do
+ inject_e(collected[c])
end
end
end
@@ -305,16 +326,23 @@ end
local function insert_element(root,pattern,whatever,before) -- todo: element als functie
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
- if collected then
+ local function insert_e(e)
+ local r = e.__p__
+ local d, k = r.dt, e.ni
+ if not before then
+ k = k + 1
+ end
+ insert(d,k,copiedelement(element,r))
+ redo_ni(d)
+ end
+ if not collected then
+ -- nothing
+ elseif collected.tg then
+ -- first or so
+ insert_e(collected)
+ else
for c=1,#collected do
- local e = collected[c]
- local r = e.__p__
- local d, k = r.dt, e.ni
- if not before then
- k = k + 1
- end
- insert(d,k,copiedelement(element,r))
- redo_ni(d)
+ insert_e(collected[c])
end
end
end
@@ -516,6 +544,75 @@ function xml.remapname(root, pattern, newtg, newns, newrn)
end
--[[ldx--
+<p>Helper (for q2p).</p>
+--ldx]]--
+
+function xml.cdatatotext(e)
+ local dt = e.dt
+ if #dt == 1 then
+ local first = dt[1]
+ if first.tg == "@cd@" then
+ e.dt = first.dt
+ end
+ else
+ -- maybe option
+ end
+end
+
+xml.builtinentities = table.tohash { "amp", "quot", "apos", "lt", "gt" } -- used often so share
+
+local entities = characters and characters.entities or nil
+local builtinentities = xml.builtinentities
+
+function xml.addentitiesdoctype(root,option) -- we could also have a 'resolve' i.e. inline hex
+ if not entities then
+ require("char-ent")
+ entities = characters.entities
+ end
+ if entities and root and root.tg == "@rt@" and root.statistics then
+ local list = { }
+ local hexify = option == "hexadecimal"
+ for k, v in table.sortedhash(root.statistics.entities.names) do
+ if not builtinentities[k] then
+ local e = entities[k]
+ if not e then
+ e = format("[%s]",k)
+ elseif hexify then
+ e = format("&#%05X;",utfbyte(k))
+ end
+ list[#list+1] = format(" <!ENTITY %s %q >",k,e)
+ end
+ end
+ local dt = root.dt
+ local n = dt[1].tg == "@pi@" and 2 or 1
+ if #list > 0 then
+ insert(dt, n, { "\n" })
+ insert(dt, n, {
+ tg = "@dt@", -- beware, doctype is unparsed
+ dt = { format("Something [\n%s\n] ",concat(list)) },
+ ns = "",
+ special = true,
+ })
+ insert(dt, n, { "\n\n" })
+ else
+ -- insert(dt, n, { table.serialize(root.statistics) })
+ end
+ end
+end
+
+-- local str = [==[
+-- <?xml version='1.0' standalone='yes' ?>
+-- <root>
+-- <a>test &nbsp; test &#123; test</a>
+-- <b><![CDATA[oeps]]></b>
+-- </root>
+-- ]==]
+--
+-- local x = xml.convert(str)
+-- xml.addentitiesdoctype(x,"hexadecimal")
+-- print(x)
+
+--[[ldx--
<p>Here are a few synonyms.</p>
--ldx]]--
@@ -547,3 +644,50 @@ xml.inject_element = xml.inject obsolete.inject_eleme
xml.remap_tag = xml.remaptag obsolete.remap_tag = xml.remaptag
xml.remap_name = xml.remapname obsolete.remap_name = xml.remapname
xml.remap_namespace = xml.remapnamespace obsolete.remap_namespace = xml.remapnamespace
+
+-- new (probably ok)
+
+function xml.cdata(e)
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ return ""
+end
+
+function xml.finalizers.xml.cdata(collected)
+ if collected then
+ local e = collected[1]
+ if e then
+ local dt = e.dt
+ if dt and #dt == 1 then
+ local first = dt[1]
+ return first.tg == "@cd@" and first.dt[1] or ""
+ end
+ end
+ end
+ return ""
+end
+
+function xml.insertcomment(e,str,n) -- also insertcdata
+ table.insert(e.dt,n or 1,{
+ tg = "@cm@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ })
+end
+
+function xml.setcdata(e,str) -- also setcomment
+ e.dt = { {
+ tg = "@cd@",
+ ns = "",
+ special = true,
+ at = { },
+ dt = { str },
+ } }
+end
diff --git a/Master/texmf-dist/tex/context/base/x-css.lua b/Master/texmf-dist/tex/context/base/lxml-css.lua
index 1bf559d6627..112a5e75de0 100644
--- a/Master/texmf-dist/tex/context/base/x-css.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-css.lua
@@ -6,17 +6,23 @@ if not modules then modules = { } end modules ['lxml-css'] = {
license = "see context related readme files"
}
-local tonumber = tonumber
-local P, S, C, R, Cb, Cg, Carg = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.Cb, lpeg.Cg, lpeg.Carg
+local tonumber, rawset = tonumber, rawset
+local lower, format = string.lower, string.format
+local P, S, C, R, Cb, Cg, Carg, Ct, Cc, Cf = lpeg.P, lpeg.S, lpeg.C, lpeg.R, lpeg.Cb, lpeg.Cg, lpeg.Carg, lpeg.Ct, lpeg.Cc, lpeg.Cf
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local css = { }
-local moduledata = moduledata or { }
-moduledata.css = css
+xml.css = xml.css or { }
+local css = xml.css
-local dimenfactors = number.dimenfactors
+if not number.dimenfactors then
+ require("util-dim.lua")
+end
-local bpf, cmf, mmf, inf = 1/dimenfactors.bp, 1/dimenfactors.cm, 1/dimenfactors.mm, 1/dimenfactors["in"]
+local dimenfactors = number.dimenfactors
+local bpf = 1/dimenfactors.bp
+local cmf = 1/dimenfactors.cm
+local mmf = 1/dimenfactors.mm
+local inf = 1/dimenfactors["in"]
local validdimen = Cg(lpegpatterns.number,'a') * (
Cb('a') * P("pt") / function(s) return tonumber(s) * bpf end
@@ -73,22 +79,52 @@ css.padding = padding
-- print(padding("10pt 20pt 30pt",pixel,hsize,exheight,emwidth))
-- print(padding("10pt 20pt 30pt 40pt",pixel,hsize,exheight,emwidth))
-local currentfont = font.current
-local texdimen = tex.dimen
-local hashes = fonts.hashes
-local quads = hashes.quads
-local xheights = hashes.xheights
+-- print(padding("0",pixel,hsize,exheight,emwidth))
-local function padding(str)
- local font = currentfont()
- local exheight = xheights[font]
- local emwidth = quads[font]
- local hsize = texdimen.hsize/100
- local pixel = emwidth/100
- return padding(str,pixel,hsize,exheight,emwidth)
-end
+-- local currentfont = font.current
+-- local texdimen = tex.dimen
+-- local hashes = fonts.hashes
+-- local quads = hashes.quads
+-- local xheights = hashes.xheights
+--
+-- local function padding(str)
+-- local font = currentfont()
+-- local exheight = xheights[font]
+-- local emwidth = quads[font]
+-- local hsize = texdimen.hsize/100
+-- local pixel = emwidth/100
+-- return padding(str,pixel,hsize,exheight,emwidth)
+-- end
+--
+-- function css.simplepadding(str)
+-- context("%ssp",padding(str,pixel,hsize,exheight,emwidth))
+-- end
+
+local pattern = Cf( Ct("") * (
+ Cg(
+ Cc("style") * (
+ C("italic")
+ + C("oblique")
+ + C("slanted") / "oblique"
+ )
+ + Cc("variant") * (
+ (C("smallcaps") + C("caps")) / "small-caps"
+ )
+ + Cc("weight") *
+ C("bold")
+ + Cc("family") * (
+ (C("mono") + C("type")) / "monospace" -- just ignore the "space(d)"
+ + (C("sansserif") + C("sans")) / "sans-serif" -- match before serif
+ + C("serif")
+ )
+ ) + P(1)
+)^0 , rawset)
---~ function css.simplepadding(str)
---~ context("%ssp",padding(str,pixel,hsize,exheight,emwidth))
---~ end
+function css.fontspecification(str)
+ return str and lpegmatch(pattern,lower(str))
+end
+function css.colorspecification(str)
+ local c = str and attributes.colors.values[tonumber(str)]
+ return c and format("rgb(%s%%,%s%%,%s%%)",c[3]*100,c[4]*100,c[5]*100)
+end
diff --git a/Master/texmf-dist/tex/context/base/x-css.mkiv b/Master/texmf-dist/tex/context/base/lxml-css.mkiv
index cc7f8682a07..2174874d9e2 100644
--- a/Master/texmf-dist/tex/context/base/x-css.mkiv
+++ b/Master/texmf-dist/tex/context/base/lxml-css.mkiv
@@ -1,17 +1,17 @@
%D \module
-%D [ file=x-css,
+%D [ file=lxml-css,
%D version=2010.01.28,
%D title=\CONTEXT\ Modules,
%D subtitle=Css Helpers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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.
-\registerctxluafile{x-css}{}
+\registerctxluafile{lxml-css}{1.001}
\def\ctxmodulecss#1{\directlua\zerocount{moduledata.css.#1}}
diff --git a/Master/texmf-dist/tex/context/base/lxml-ctx.lua b/Master/texmf-dist/tex/context/base/lxml-ctx.lua
index 1f6f6ffd3b8..3319dc63838 100644
--- a/Master/texmf-dist/tex/context/base/lxml-ctx.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-ctx.lua
@@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['lxml-ctx'] = {
-- is this still used?
+local format, find = string.format, string.find
+
local xml = xml
xml.ctx = { }
@@ -21,7 +23,7 @@ function xml.ctx.enhancers.compound(root,lpath,before,tokens,after) -- todo lpeg
local after = after or "[%a%d][%a%d][%a%d]"
local pattern = "(" .. before .. ")(" .. tokens .. ")(" .. after .. ")"
local action = function(a,b,c)
- return a .. "<compound token=" .. string.format("%q",b) .. "/>" .. c
+ return a .. "<compound token=" .. format("%q",b) .. "/>" .. c
end
xml.enhance(root,lpath,pattern,action) -- still present?
end
@@ -38,7 +40,7 @@ function xml.ctx.tshow(specification)
local attribute = specification.attribute
if context then
local xmlpattern = pattern
- if not string.find(xmlpattern,"^[%a]+://") then
+ if not find(xmlpattern,"^[%a]+://") then
xmlpattern = "xml://" .. pattern
end
local parsed = xml.lpath(xmlpattern)
diff --git a/Master/texmf-dist/tex/context/base/lxml-ctx.mkiv b/Master/texmf-dist/tex/context/base/lxml-ctx.mkiv
index 73d082d0d51..530c29aa778 100644
--- a/Master/texmf-dist/tex/context/base/lxml-ctx.mkiv
+++ b/Master/texmf-dist/tex/context/base/lxml-ctx.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -20,45 +20,42 @@
\unprotect
-% the letterbar is a messy hack and is needed for the tabulate
+% The \let|=letterbar is a messy hack and is needed for the tabulate. We now use
+% \detokenize.
\settrue \xmllshowbuffer
\setfalse\xmllshowtitle
\settrue \xmllshowwarning
-\definehead[lshowtitle][subsubsubsubsubject]
-\setuphead[lshowtitle][style=\tta]
-
-% \unexpanded\def\setuplxmlshow[#1]%
-% {\dodoubleargument\getparameters[\??xl]}
-
-\def\xmllshow#1%
- {\begingroup
- \let|=\letterbar
- \ctxlua{xml.ctx.tshow {
- pattern = \!!bs#1\!!es,
- \ifconditional\xmllshowtitle
- title = "lshowtitle",
- \fi
- \ifconditional\xmllshowwarning
- warning = true,
- \fi
- } }%
- \endgroup}
-
-\def\xmllshowbuffer#1#2#3%
- {\begingroup
- \let|=\letterbar
- \ctxlua{xml.ctx.tshow {
- pattern = \!!bs#2\!!es,
- \ifconditional\xmllshowbuffer
- xmlroot = "#1",
- attribute = "#3",
- \fi
- \ifconditional\xmllshowwarning
- warning = true,
- \fi
- } }%
- \endgroup}
+\definehead
+ [lshowtitle]
+ [subsubsubsubsubject]
+
+\setuphead
+ [lshowtitle]
+ [\c!style=\tta]
+
+\unexpanded\def\xmllshow#1%
+ {\ctxlua{xml.ctx.tshow {
+ pattern = \!!bs\detokenize{#1}\!!es,
+ \ifconditional\xmllshowtitle
+ title = "lshowtitle",
+ \fi
+ \ifconditional\xmllshowwarning
+ warning = true,
+ \fi
+ } }}
+
+\unexpanded\def\xmllshowbuffer#1#2#3%
+ {\ctxlua{xml.ctx.tshow {
+ pattern = \!!bs\detokenize{#2}\!!es,
+ \ifconditional\xmllshowbuffer
+ xmlroot = "#1",
+ attribute = "#3",
+ \fi
+ \ifconditional\xmllshowwarning
+ warning = true,
+ \fi
+ } }}
\protect
diff --git a/Master/texmf-dist/tex/context/base/lxml-dir.lua b/Master/texmf-dist/tex/context/base/lxml-dir.lua
index 0924931c1b5..00375193f0f 100644
--- a/Master/texmf-dist/tex/context/base/lxml-dir.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-dir.lua
@@ -7,8 +7,6 @@ if not modules then modules = { } end modules ['lxml-dir'] = {
}
local format, gsub = string.format, string.gsub
-local getid = lxml.getid
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
--~ <?xml version="1.0" standalone="yes"?>
--~ <!-- demo.cdx -->
@@ -25,7 +23,9 @@ local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
--~ <directive attribute='cdx' value="*" element="cals:table" setup="cdx:cals:table:*"/>
--~ </directives>
-local lxml = lxml
+local lxml, context = lxml, context
+
+local getid = lxml.getid
lxml.directives = lxml.directives or { }
local directives = lxml.directives
@@ -84,14 +84,15 @@ local function handle_setup(category,root,attribute,element)
setup = setup[category]
end
if setup then
- texsprint(ctxcatcodes,"\\directsetup{",setup,"}")
+ context.directsetup(setup)
else
setup = data[format("%s::%s::*",element,attribute)]
if setup then
setup = setup[category]
end
if setup then
- texsprint(ctxcatcodes,"\\directsetup{",gsub(setup,'%*',value),"}")
+ setup = gsub(setup,'%*',value)
+ context.directsetup(setup)
end
end
end
diff --git a/Master/texmf-dist/tex/context/base/lxml-ent.lua b/Master/texmf-dist/tex/context/base/lxml-ent.lua
index 5b24d9d6846..be69dec00ee 100644
--- a/Master/texmf-dist/tex/context/base/lxml-ent.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-ent.lua
@@ -7,7 +7,6 @@ if not modules then modules = { } end modules ['lxml-ent'] = {
}
local type, next, tonumber = type, next, tonumber
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
local utf = unicode.utf8
local byte, format = string.byte, string.format
local utfupper, utfchar = utf.upper, utf.char
@@ -28,15 +27,11 @@ local report_xml = logs.reporter("xml")
local xml = xml
-xml.entities = xml.entities or { } -- xml.entity_handler == function
+xml.entities = xml.entities or { }
-storage.register("xml/entities",xml.entities,"xml.entities") -- this will move to lxml
+storage.register("xml/entities", xml.entities, "xml.entities" )
-local entities = xml.entities -- this is a shared hash
-
-xml.placeholders.unknown_any_entity = nil -- has to be per xml
-
-local parsedentity = xml.parsedentitylpeg
+local entities = xml.entities -- maybe some day properties
function xml.registerentity(key,value)
entities[key] = value
@@ -45,29 +40,19 @@ function xml.registerentity(key,value)
end
end
-function xml.resolvedentity(str)
- local e = entities[str]
- if e then
- local te = type(e)
- if te == "function" then
- e(str)
- elseif e then
- texsprint(ctxcatcodes,e)
- end
- else
- -- resolve hex and dec, todo: escape # & etc for ctxcatcodes
- -- normally this is already solved while loading the file
- local chr, err = lpegmatch(parsedentity,str)
- if chr then
- texsprint(ctxcatcodes,chr)
- elseif err then
- texsprint(ctxcatcodes,err)
+if characters and characters.entities then
+
+ function characters.registerentities(forcecopy)
+ if forcecopy then
+ table.setmetatableindex(entities,nil)
+ for name, value in next, characters.entities do
+ if not entities[name] then
+ entities[name] = value
+ end
+ end
else
- texsprint(ctxcatcodes,"\\xmle{",str,"}{",utfupper(str),"}") -- we need to use our own upper
+ table.setmetatableindex(entities,characters.entities)
end
end
-end
-entities.amp = function() tex.write("&") end
-entities.lt = function() tex.write("<") end
-entities.gt = function() tex.write(">") end
+end
diff --git a/Master/texmf-dist/tex/context/base/lxml-ini.mkiv b/Master/texmf-dist/tex/context/base/lxml-ini.mkiv
index a1d6b50a878..84ebc58233c 100644
--- a/Master/texmf-dist/tex/context/base/lxml-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/lxml-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -20,13 +20,12 @@
%registerctxluafile{lxml-xml}{1.001} % xml finalizers
%registerctxluafile{lxml-aux}{1.001} % extras using parser
%registerctxluafile{lxml-mis}{1.001} % extras independent of parser
+\registerctxluafile{char-ent}{1.001}
\registerctxluafile{lxml-ent}{1.001} % entity hacks
\registerctxluafile{lxml-tex}{1.001} % tex finalizers
\registerctxluafile{lxml-dir}{1.001} % ctx hacks
-\unprotect
-
-\def\c!entities{entities} % to be internationalized
+\unprotect % todo \!!bs \!!es where handy (slower)
\def\ctxlxml #1{\directlua\zerocount{lxml.#1}}
@@ -52,6 +51,8 @@
\def\xmlfunction #1#2{\ctxlxml{applyfunction("#1",\!!bs#2\!!es)}}
\def\xmlfirst #1#2{\ctxlxml{first("#1","#2")}}
\def\xmlflush #1{\ctxlxml{flush("#1")}}
+\def\xmlflushlinewise #1{\ctxlxml{flushlinewise("#1")}}
+\def\xmlflushspacewise #1{\ctxlxml{flushspacewise("#1")}}
%def\xmlcontent #1{\ctxlxml{content("#1")}}
%def\xmlflushstripped #1{\ctxlxml{strip("#1",true)}}
\def\xmldirect #1{\ctxlxml{direct("#1")}} % in loops, not dt but root
@@ -86,10 +87,10 @@
\def\xmldisplayverbatim #1{\ctxlxml{displayverbatim("#1")}}
\def\xmlinlineverbatim #1{\ctxlxml{inlineverbatim("#1")}}
-\def\xmlload #1#2{\ctxlxml{load("#1","#2","\@@xmentities","\@@xmcompress")}}
-\def\xmlloadbuffer #1#2{\ctxlxml{loadbuffer("#1","#2","\@@xmentities","\@@xmcompress")}}
-\def\xmlloaddata #1#2{\ctxlxml{loaddata("#1",\!!bs#2\!!es,"\@@xmentities","\@@xmcompress")}}
-\def\xmlloadregistered #1#2{\ctxlxml{loadregistered("#1","\@@xmentities","\@@xmcompress")}}
+\def\xmlload #1#2{\ctxlxml{load("#1","#2","\p_lxml_entities","\p_lxml_compress")}}
+\def\xmlloadbuffer #1#2{\ctxlxml{loadbuffer("#1","#2","\p_lxml_entities","\p_lxml_compress")}}
+\def\xmlloaddata #1#2{\ctxlxml{loaddata("#1",\!!bs#2\!!es,"\p_lxml_entities","\p_lxml_compress")}}
+\def\xmlloadregistered #1#2{\ctxlxml{loadregistered("#1","\p_lxml_entities","\p_lxml_compress")}}
\def\xmlloaddirectives #1{\ctxlxml{directives.load("any:///#1")}}
\def\xmlpos #1{\ctxlxml{pos("#1")}}
@@ -104,12 +105,12 @@
% todo: \xmldoifelseattribute
-\def\xmldoif #1#2{\ctxlxml{doif (\!!bs#1\!!es,\!!bs#2\!!es)}}
-\def\xmldoifnot #1#2{\ctxlxml{doifnot (\!!bs#1\!!es,\!!bs#2\!!es)}}
-\def\xmldoifelse #1#2{\ctxlxml{doifelse (\!!bs#1\!!es,\!!bs#2\!!es)}}
-\def\xmldoiftext #1#2{\ctxlxml{doiftext (\!!bs#1\!!es,\!!bs#2\!!es)}}
-\def\xmldoifnottext #1#2{\ctxlxml{doifnottext (\!!bs#1\!!es,\!!bs#2\!!es)}}
-\def\xmldoifelsetext #1#2{\ctxlxml{doifelsetext(\!!bs#1\!!es,\!!bs#2\!!es)}}
+\def\xmldoif #1#2{\ctxlxml{doif (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable
+\def\xmldoifnot #1#2{\ctxlxml{doifnot (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable
+\def\xmldoifelse #1#2{\ctxlxml{doifelse (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable
+\def\xmldoiftext #1#2{\ctxlxml{doiftext (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable
+\def\xmldoifnottext #1#2{\ctxlxml{doifnottext (\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable
+\def\xmldoifelsetext #1#2{\ctxlxml{doifelsetext(\!!bs#1\!!es,\!!bs#2\!!es)}} % expandable
%def\xmldoifelseempty #1#2{\ctxlxml{doifelseempty("#1","#2")}} % #2, "*" or "" == self not yet implemented
%def\xmldoifelseselfempty #1{\ctxlxml{doifelseempty("#1")}}
@@ -132,44 +133,44 @@
% todo: 1:xml:whatever always before 3:xml:something
-\def\xmlprependsetup #1{\ctxlxml{installsetup(1,"*","#1")}}
-\def\xmlappendsetup #1{\ctxlxml{installsetup(2,"*","#1")}}
-\def\xmlbeforesetup #1#2{\ctxlxml{installsetup(3,"*","#1","#2"))}}
-\def\xmlaftersetup #1#2{\ctxlxml{installsetup(4,"*","#1","#2"))}}
+\unexpanded\def\xmlprependsetup #1{\ctxlxml{installsetup(1,"*","#1")}}
+\unexpanded\def\xmlappendsetup #1{\ctxlxml{installsetup(2,"*","#1")}}
+\unexpanded\def\xmlbeforesetup #1#2{\ctxlxml{installsetup(3,"*","#1","#2")}}
+\unexpanded\def\xmlaftersetup #1#2{\ctxlxml{installsetup(4,"*","#1","#2")}}
-\def\xmlprependdocumentsetup #1#2{\ctxlxml{installsetup(1,"#1","#2")}}
-\def\xmlappenddocumentsetup #1#2{\ctxlxml{installsetup(2,"#1","#2")}}
-\def\xmlbeforedocumentsetup#1#2#3{\ctxlxml{installsetup(3,"#1","#2","#3"))}}
-\def\xmlafterdocumentsetup #1#2#3{\ctxlxml{installsetup(4,"#1","#2","#3"))}}
+\unexpanded\def\xmlprependdocumentsetup #1#2{\ctxlxml{installsetup(1,"#1","#2")}}
+\unexpanded\def\xmlappenddocumentsetup #1#2{\ctxlxml{installsetup(2,"#1","#2")}}
+\unexpanded\def\xmlbeforedocumentsetup#1#2#3{\ctxlxml{installsetup(3,"#1","#2","#3")}}
+\unexpanded\def\xmlafterdocumentsetup #1#2#3{\ctxlxml{installsetup(4,"#1","#2","#3")}}
-\def\xmlremovesetup #1{\ctxlxml{removesetup("*","#1")}}
-\def\xmlremovedocumentsetup #1#2{\ctxlxml{removesetup("#1","#2")}}
+\unexpanded\def\xmlremovesetup #1{\ctxlxml{removesetup("*","#1")}}
+\unexpanded\def\xmlremovedocumentsetup #1#2{\ctxlxml{removesetup("#1","#2")}}
-\def\xmlflushdocumentsetups #1#2{\ctxlxml{flushsetups("#1","*","#2")}} % #1 == id where to apply * and #2
-\def\xmlresetdocumentsetups #1{\ctxlxml{resetsetups("#1")}}
+\unexpanded\def\xmlflushdocumentsetups #1#2{\ctxlxml{flushsetups("#1","*","#2")}} % #1 == id where to apply * and #2
+\unexpanded\def\xmlresetdocumentsetups #1{\ctxlxml{resetsetups("#1")}}
\let\xmlregistersetup \xmlappendsetup
\let\xmlregisterdocumentsetup\xmlappenddocumentsetup
\def\xmldocument{main}
-\def\xmlregisteredsetups
+\unexpanded\def\xmlregisteredsetups
{\xmlstarttiming
\xmlflushsetups
\xmldefaulttotext\xmldocument % after include
\xmlstoptiming}
-\def\xmlregistereddocumentsetups#1#2% id setups
+\unexpanded\def\xmlregistereddocumentsetups#1#2% id setups
{\xmlstarttiming
% todo: test for duplicates !
\xmlflushdocumentsetups{#1}{#2}%
\xmldefaulttotext{#1}% after include
\xmlstoptiming}
-\def\xmlstarttiming{\ctxlua{statistics.starttiming(lxml)}}
-\def\xmlstoptiming {\ctxlua{statistics.stoptiming (lxml)}}
+\unexpanded\def\xmlstarttiming{\ctxlua{statistics.starttiming(lxml)}}
+\unexpanded\def\xmlstoptiming {\ctxlua{statistics.stoptiming (lxml)}}
-\def\doxmlprocess#1#2#3#4#5% flag \loader id name what initializersetup
+\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}%
@@ -181,10 +182,10 @@
%xmlpopdocument
\endgroup}
-\def\xmlprocessfile {\doxmlprocess\plusone \xmlload}
-\def\xmlprocessdata {\doxmlprocess\zerocount\xmlloaddata}
-\def\xmlprocessbuffer {\doxmlprocess\zerocount\xmlloadbuffer}
-\def\xmlprocessregistered{\doxmlprocess\zerocount\xmlloadregistered}
+\unexpanded\def\xmlprocessfile {\lxml_process\plusone \xmlload}
+\unexpanded\def\xmlprocessdata {\lxml_process\zerocount\xmlloaddata}
+\unexpanded\def\xmlprocessbuffer {\lxml_process\zerocount\xmlloadbuffer}
+\unexpanded\def\xmlprocessregistered{\lxml_process\zerocount\xmlloadregistered}
\let\xmlprocess \xmlprocessfile
\startxmlsetups xml:flush
@@ -196,7 +197,7 @@
\xmlmain{#1}
\stopxmlsetups
-\def\xmlloadonly#1#2#3%
+\unexpanded\def\xmlloadonly#1#2#3%
{\xmlload{#1}{#2}%
\xmlregistereddocumentsetups{#1}{#3}}
@@ -204,7 +205,7 @@
% instructions preceding the root element; well, in some
% sense that is the root
-\long\def\xmlconnect#1#2#3% inefficient
+\unexpanded\def\xmlconnect#1#2#3% inefficient
{\scratchcounter\xmlcount{#1}{#2}\relax
\ifcase\scratchcounter \or
\xmlall{#1}{#2}%
@@ -214,10 +215,10 @@
\xmlidx{#1}{#2}\recurselevel}%
\fi}
-\def\xmlcdataobeyedline {\obeyedline}
-\def\xmlcdataobeyedspace{\strut\obeyedspace}
-\def\xmlcdatabefore {\bgroup\tt}
-\def\xmlcdataafter {\egroup}
+\unexpanded\def\xmlcdataobeyedline {\obeyedline}
+\unexpanded\def\xmlcdataobeyedspace{\strut\obeyedspace}
+\unexpanded\def\xmlcdatabefore {\bgroup\tt}
+\unexpanded\def\xmlcdataafter {\egroup}
% verbatim (dodo:pre/post whitespace, maybe splot verbatim and
% cdata commands), experimental:
@@ -238,7 +239,6 @@
\unexpanded\def\startxmldisplayverbatim[#1]%
{\startpacked % \begingroup
- \let\currenttypingclass\??tp
\edef\currenttyping{xml:#1}%
\unexpanded\def\stopxmldisplayverbatim
{\endofverbatimlines
@@ -248,8 +248,7 @@
\unexpanded\def\startxmlinlineverbatim[#1]%
{\begingroup
- \let\currenttypingclass\??ty
- \edef\currenttyping{xml:#1}%
+ \edef\currenttype{xml:#1}%
\let\stopxmldisplayverbatim\endgroup
\doinitializeverbatim}
@@ -288,16 +287,18 @@
\newconstant\xmlprocessingmode % 0=unset, 1=text, 2=hidden
-\newtoks\everysetupxml
+\installcorenamespace{xml}
+\installcorenamespace{xmldefaults}
+\installcorenamespace{xmlmapvalue}
-\unexpanded\def\setupxml[#1]{\getparameters[\??xm][#1]\the\everysetupxml}
+\installdirectcommandhandler \??xml {xml}
-\letvalue{\??xm:\s!default:\v!normal}\zerocount
-\letvalue{\??xm:\s!default:\v!none }\zerocount
-\letvalue{\??xm:\s!default:\v!text }\plusone
-\letvalue{\??xm:\s!default:\v!hidden}\plustwo
+\letvalue{\??xmldefaults\v!normal}\zerocount
+\letvalue{\??xmldefaults\v!none }\zerocount
+\letvalue{\??xmldefaults\v!text }\plusone
+\letvalue{\??xmldefaults\v!hidden}\plustwo
-\def\xmldefaulttotext#1%
+\unexpanded\def\xmldefaulttotext#1%
{\ifcase\xmlprocessingmode
% unset
\or
@@ -309,20 +310,29 @@
\fi}
\appendtoks
- \xmlprocessingmode\executeifdefined{\??xm:\s!default:\@@xmdefault}\plusone
+ \xmlprocessingmode\executeifdefined{\??xmldefaults\directxmlparameter\c!default}\plusone
\to \everysetupxml
-\def\xmlinitialize{\the\everysetupxml}
+\unexpanded\def\xmlinitialize
+ {\the\everysetupxml}
+
+\let\p_lxml_entities\empty
+\let\p_lxml_compress\empty
+
+\appendtoks
+ \edef\p_lxml_entities{\directxmlparameter\c!entities}%
+ \edef\p_lxml_compress{\directxmlparameter\c!compress}%
+\to \everysetupxml
\setupxml
[\c!default=, % flush all
\c!compress=\v!no, % strip comment
\c!entities=\v!yes] % replace entities
-\def\xmlmapvalue #1#2#3{\setvalue{\??xm:v:#1:#2}{#3}} % keep #3 to grab spaces
-\def\xmlvalue #1#2#3{\executeifdefined{\??xm:v:#1:#2}{#3}}
-%def\xmlvalue #1#2{\ifcsname\??xm:v:#1:#2\endcsname\csname\??xm:v:#1:#2\expandafter\expandafter\gobbleoneargument\expandafter\endcsname\else\expandafter\firstofoneargument\fi}
-\def\xmldoifelsevalue #1#2{\ifcsname\??xm:v:#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+\def\xmlmapvalue #1#2#3{\setvalue{\??xmlmapvalue#1:#2}{#3}} % keep #3 to grab spaces
+\def\xmlvalue #1#2#3{\executeifdefined{\??xmlmapvalue#1:#2}{#3}}
+%def\xmlvalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\csname\??xmlmapvalue#1:#2\expandafter\expandafter\gobbleoneargument\expandafter\endcsname\else\expandafter\firstofoneargument\fi}
+\def\xmldoifelsevalue #1#2{\ifcsname\??xmlmapvalue#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
\let\xmlmapval\xmlmapvalue
\let\xmlval \xmlvalue
@@ -334,39 +344,37 @@
\def\xmlwithindex #1#2{\ctxlxml{withindex("\xmldocument","#1","#2")}}
\def\xmlreference #1#2{\string\xmlwithindex{#1}{#2}}
-%D Entities:
+%D Entities (might change):
\setnewconstant\xmlautoentities\plusone % 0=off, 1=upper, 2=upper,lower
-\let\isolatedentity\firstofoneargument
-
\def\xmlsetentity#1#2{\ctxlua{xml.registerentity('#1',\!!bs\detokenize{#2}\!!es)}}
-\def\xmltexentity#1#2{\ctxlua{xml.registerentity('#1',\!!bs\detokenize{\isolatedentity{#2}}\!!es)}}
+\def\xmltexentity#1#2{\ctxlua{lxml.registerentity('#1',\!!bs\detokenize{#2}\!!es)}}
% \xmlsetentity{tex}{\TEX{}} % {} needed
\unexpanded\def\xmle
{\ifcase\xmlautoentities
- \expandafter\xmle@none
+ \expandafter\lxml_e_none
\or
- \expandafter\xmle@upper
+ \expandafter\lxml_e_upper
\or
- \expandafter\xmle@upperlower
+ \expandafter\lxml_e_upperlower
\else
- \expandafter\xmle@none
+ \expandafter\lxml_e_none
\fi}
-\def\xmle@none#1#2% safe
+\def\lxml_e_none#1#2% safe
{#1}
-\def\xmle@upper#1#2% can be abbreviation
+\def\lxml_e_upper#1#2% can be abbreviation
{\ifcsname#2\endcsname
\csname#2\expandafter\endcsname
\else
#1%
\fi}
-\def\xmle@upperlower#1#2% can be anything, so unsafe
+\def\lxml_e_upperlower#1#2% can be anything, so unsafe
{\ifcsname#2\endcsname
\csname#2\expandafter\endcsname
\else\ifcsname#1\endcsname
@@ -375,6 +383,24 @@
#1%
\fi\fi}
+% handy helpers (analogue to MP and LUA and TEX and also MkII)
+
+\unexpanded\def\processXMLbuffer
+ {\dosingleempty\lxml_process_buffer}
+
+\def\lxml_process_buffer[#1]%
+ {\xmlprocessbuffer{temp}{#1}{}}
+
+\unexpanded\def\processXMLfile#1%
+ {\xmlprocessfile{temp}{#1}{}}
+
+\unexpanded\def\XMLdata#1%
+ {\xmlprocessdata{temp}{#1}{}}
+
+\let\processxmlbuffer\processXMLbuffer
+\let\processxmlfile \processXMLfile
+\let\xmldata \XMLdata
+
\protect \endinput
% \newcount\charactersactiveoffset \charactersactiveoffset="10000
diff --git a/Master/texmf-dist/tex/context/base/lxml-lpt.lua b/Master/texmf-dist/tex/context/base/lxml-lpt.lua
index aa0b0a22ecc..44dd971551a 100644
--- a/Master/texmf-dist/tex/context/base/lxml-lpt.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-lpt.lua
@@ -164,8 +164,8 @@ apply_axis['child'] = function(list)
c = c + 1
collected[c] = dk
dk.ni = k -- refresh
- en = en + 1
- dk.ei = en
+ en = en + 1
+ dk.ei = en
end
end
ll.en = en
@@ -193,6 +193,7 @@ local function collect(list,collected,c)
end
return c
end
+
apply_axis['descendant'] = function(list)
local collected, c = { }, 0
for l=1,#list do
@@ -514,6 +515,12 @@ local lp_or = P("|") / " or "
local lp_and = P("&") / " and "
local lp_builtin = P (
+ P("text") / "(ll.dt[1] or '')" + -- fragile
+ P("content") / "ll.dt" +
+ -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
+ P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
+ P("tag") / "ll.tg" +
+ P("position") / "l" + -- is element in finalizer
P("firstindex") / "1" +
P("lastindex") / "(#ll.__p__.dt or 1)" +
P("firstelement") / "1" +
@@ -521,15 +528,11 @@ local lp_builtin = P (
P("first") / "1" +
P("last") / "#list" +
P("rootposition") / "order" +
- P("position") / "l" + -- is element in finalizer
P("order") / "order" +
P("element") / "(ll.ei or 1)" +
P("index") / "(ll.ni or 1)" +
P("match") / "(ll.mi or 1)" +
- P("text") / "(ll.dt[1] or '')" +
- -- P("name") / "(ll.ns~='' and ll.ns..':'..ll.tg)" +
- P("name") / "((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)" +
- P("tag") / "ll.tg" +
+ -- P("namespace") / "ll.ns" +
P("ns") / "ll.ns"
) * ((spaces * P("(") * spaces * P(")"))/"")
@@ -553,11 +556,11 @@ local lp_function = C(R("az","AZ","__")^1) * P("(") / function(t) -- todo: bett
end
end
-local lparent = lpeg.P("(")
-local rparent = lpeg.P(")")
+local lparent = P("(")
+local rparent = P(")")
local noparent = 1 - (lparent+rparent)
-local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
-local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
+local nested = P{lparent * (noparent + V(1))^0 * rparent}
+local value = P(lparent * C((noparent + nested)^0) * rparent) -- P{"("*C(((1-S("()"))+V(1))^0)*")"}
local lp_child = Cc("expr.child(ll,'") * R("az","AZ","--","__")^1 * Cc("')")
local lp_number = S("+-") * R("09")^1
@@ -711,7 +714,10 @@ local special_1 = P("*") * Cc(register_auto_descendant) * Cc(register_all_nodes
local special_2 = P("/") * Cc(register_auto_self)
local special_3 = P("") * Cc(register_auto_self)
-local pathparser = Ct { "patterns", -- can be made a bit faster by moving pattern outside
+local no_nextcolon = P(-1) + #(1-P(":")) -- newer lpeg needs the P(-1)
+local no_nextlparent = P(-1) + #(1-P("(")) -- newer lpeg needs the P(-1)
+
+local pathparser = Ct { "patterns", -- can be made a bit faster by moving some patterns outside
patterns = spaces * V("protocol") * spaces * (
( V("special") * spaces * P(-1) ) +
@@ -740,10 +746,8 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
shortcuts = V("shortcuts_a") * (spaces * "/" * spaces * V("shortcuts_a"))^0,
s_descendant_or_self = (P("***/") + P("/")) * Cc(register_descendant_or_self), --- *** is a bonus
- -- s_descendant_or_self = P("/") * Cc(register_descendant_or_self),
s_descendant = P("**") * Cc(register_descendant),
- s_child = P("*") * #(1-P(":")) * Cc(register_child ),
--- s_child = P("*") * #(P("/")+P(-1)) * Cc(register_child ),
+ s_child = P("*") * no_nextcolon * Cc(register_child ),
s_parent = P("..") * Cc(register_parent ),
s_self = P("." ) * Cc(register_self ),
s_root = P("^^") * Cc(register_root ),
@@ -770,13 +774,13 @@ local pathparser = Ct { "patterns", -- can be made a bit faster by moving patter
expressions = expression / register_expression,
letters = R("az")^1,
- name = (1-lpeg.S("/[]()|:*!"))^1,
+ name = (1-S("/[]()|:*!"))^1, -- make inline
negate = P("!") * Cc(false),
nodefunction = V("negate") + P("not") * Cc(false) + Cc(true),
nodetest = V("negate") + Cc(true),
nodename = (V("negate") + Cc(true)) * spaces * ((V("wildnodename") * P(":") * V("wildnodename")) + (Cc(false) * V("wildnodename"))),
- wildnodename = (C(V("name")) + P("*") * Cc(false)) * #(1-P("(")),
+ wildnodename = (C(V("name")) + P("*") * Cc(false)) * no_nextlparent,
nodeset = spaces * Ct(V("nodename") * (spaces * P("|") * spaces * V("nodename"))^0) * spaces,
finalizer = (Cb("protocol") * P("/")^-1 * C(V("name")) * arguments * P(-1)) / register_finalizer,
@@ -940,7 +944,7 @@ local function profiled_apply(list,parsed,nofparsed,order)
elseif kind == "expression" then
collected = apply_expression(collected,pi.evaluator,order)
elseif kind == "finalizer" then
- collected = pi.finalizer(collected)
+ collected = pi.finalizer(collected) -- no check on # here
p.matched = p.matched + 1
p.finalized = p.finalized + 1
return collected
@@ -1103,9 +1107,9 @@ end
expressions.child = function(e,pattern)
return applylpath(e,pattern) -- todo: cache
end
-expressions.count = function(e,pattern)
+expressions.count = function(e,pattern) -- what if pattern == empty or nil
local collected = applylpath(e,pattern) -- todo: cache
- return (collected and #collected) or 0
+ return pattern and (collected and #collected) or 0
end
-- external
@@ -1114,7 +1118,7 @@ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
expressions.error = function(str)
- xml.errorhandler("unknown function in lpath expression",tostring(str or "?"))
+ xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?")))
return false
end
expressions.undefined = function(s)
@@ -1140,6 +1144,23 @@ expressions.lower = lower
expressions.number = tonumber
expressions.boolean = toboolean
+function expressions.contains(str,pattern)
+ local t = type(str)
+ if t == "string" then
+ if find(str,pattern) then
+ return true
+ end
+ elseif t == "table" then
+ for i=1,#str do
+ local d = str[i]
+ if type(d) == "string" and find(d,pattern) then
+ return true
+ end
+ end
+ end
+ return false
+end
+
-- user interface
local function traverse(root,pattern,handle)
diff --git a/Master/texmf-dist/tex/context/base/lxml-sor.lua b/Master/texmf-dist/tex/context/base/lxml-sor.lua
index a159fd4e00f..951017bcd3f 100644
--- a/Master/texmf-dist/tex/context/base/lxml-sor.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-sor.lua
@@ -6,9 +6,8 @@ if not modules then modules = { } end modules ['lxml-sor'] = {
license = "see context related readme files"
}
-local format, concat = string.format, table.concat
+local format, concat, rep = string.format, table.concat, string.rep
local lpegmatch = lpeg.match
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
local xml, lxml = xml, lxml
@@ -66,7 +65,7 @@ function lxml.sorters.show(name)
for i=1,#entries do
if #entries[i][2] > maxn then maxn = #entries[i][2] end
end
- context.starttabulate { "|Tr|Tr|" .. string.rep("Tlp|",maxn) }
+ context.starttabulate { "|Tr|Tr|" .. rep("Tlp|",maxn) }
NC() bold("n")
NC() bold("id")
if maxn > 1 then
diff --git a/Master/texmf-dist/tex/context/base/lxml-sor.mkiv b/Master/texmf-dist/tex/context/base/lxml-sor.mkiv
index a3fc83dd128..0ee1f16f3e2 100644
--- a/Master/texmf-dist/tex/context/base/lxml-sor.mkiv
+++ b/Master/texmf-dist/tex/context/base/lxml-sor.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Sorting,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,11 +19,11 @@
\unprotect
-\def\xmlresetsorter #1{\ctxlxml{sorters.reset("#1")}}
-\def\xmladdsortentry#1#2#3{\ctxlxml{sorters.add("#1","#2",\!!bs#3\!!es)}}
-\def\xmlshowsorter #1{\ctxlxml{sorters.show("#1")}}
-\def\xmlflushsorter #1#2{\ctxlxml{sorters.flush("#1","#2")}}
-\def\xmlsortentries #1{\ctxlxml{sorters.sort("#1")}}
+\unexpanded\def\xmlresetsorter #1{\ctxlxml{sorters.reset("#1")}}
+\unexpanded\def\xmladdsortentry#1#2#3{\ctxlxml{sorters.add("#1","#2",\!!bs#3\!!es)}}
+\unexpanded\def\xmlshowsorter #1{\ctxlxml{sorters.show("#1")}}
+\unexpanded\def\xmlflushsorter #1#2{\ctxlxml{sorters.flush("#1","#2")}}
+\unexpanded\def\xmlsortentries #1{\ctxlxml{sorters.sort("#1")}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/lxml-tab.lua b/Master/texmf-dist/tex/context/base/lxml-tab.lua
index 7d38a8d5abc..0a43f435274 100644
--- a/Master/texmf-dist/tex/context/base/lxml-tab.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-tab.lua
@@ -10,6 +10,10 @@ if not modules then modules = { } end modules ['lxml-tab'] = {
-- stripping spaces from e.g. cont-en.xml saves .2 sec runtime so it's not worth the
-- trouble
+-- todo: when serializing optionally remap named entities to hex (if known in char-ent.lua)
+-- maybe when letter -> utf, else name .. then we need an option to the serializer .. a bit
+-- of work so we delay this till we cleanup
+
local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_xml = logs and logs.reporter("xml","core") or function(...) print(format(...)) end
@@ -35,10 +39,11 @@ local xml = xml
--~ local xml = xml
+local utf = unicode.utf8
local concat, remove, insert = table.concat, table.remove, table.insert
local type, next, setmetatable, getmetatable, tonumber = type, next, setmetatable, getmetatable, tonumber
local format, lower, find, match, gsub = string.format, string.lower, string.find, string.match, string.gsub
-local utfchar = unicode.utf8.char
+local utfchar, utffind, utfgsub = utf.char, utf.find, utf.gsub
local lpegmatch = lpeg.match
local P, S, R, C, V, C, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.C, lpeg.Cs
@@ -151,9 +156,22 @@ element.</p>
local nsremap, resolvens = xml.xmlns, xml.resolvens
-local stack, top, dt, at, xmlns, errorstr, entities = { }, { }, { }, { }, { }, nil, { }
-local strip, cleanup, utfize, resolve, resolve_predefined, unify_predefined = false, false, false, false, false, false
-local dcache, hcache, acache = { }, { }, { }
+local stack = { }
+local top = { }
+local dt = { }
+local at = { }
+local xmlns = { }
+local errorstr = nil
+local entities = { }
+local strip = false
+local cleanup = false
+local utfize = false
+local resolve_predefined = false
+local unify_predefined = false
+
+local dcache = { }
+local hcache = { }
+local acache = { }
local mt = { }
@@ -319,7 +337,7 @@ local predefined_unified = {
[42] = "&quot;",
[47] = "&apos;",
[74] = "&lt;",
- [76] = "&gr;",
+ [76] = "&gt;",
}
local predefined_simplified = {
@@ -330,6 +348,58 @@ local predefined_simplified = {
[76] = ">", gt = ">",
}
+local nofprivates = 0xF0000 -- shared but seldom used
+
+local privates_u = { -- unescaped
+ [ [[&]] ] = "&amp;",
+ [ [["]] ] = "&quot;",
+ [ [[']] ] = "&apos;",
+ [ [[<]] ] = "&lt;",
+ [ [[>]] ] = "&gt;",
+}
+
+local privates_p = {
+}
+
+local privates_n = {
+ -- keeps track of defined ones
+}
+
+local function escaped(s)
+ if s == "" then
+ return ""
+ else -- if utffind(s,privates_u) then
+ return (utfgsub(s,".",privates_u))
+ -- else
+ -- return s
+ end
+end
+
+local function unescaped(s)
+ local p = privates_n[s]
+ if not p then
+ nofprivates = nofprivates + 1
+ p = utfchar(nofprivates)
+ privates_n[s] = p
+ s = "&" .. s .. ";" -- todo: use char-ent to map to hex
+ privates_u[p] = s
+ privates_p[p] = s
+ end
+ return p
+end
+
+local function unprivatized(s,resolve)
+ if s == "" then
+ return ""
+ else
+ return (utfgsub(s,".",privates_p))
+ end
+end
+
+xml.privatetoken = unescaped
+xml.unprivatized = unprivatized
+xml.privatecodes = privates_n
+
local function handle_hex_entity(str)
local h = hcache[str]
if not h then
@@ -371,7 +441,7 @@ local function handle_dec_entity(str)
if not n then
report_xml("utfize, ignoring dec entity &#%s;",str)
elseif trace_entities then
- report_xml("utfize, converting dec entity &#%s; into %s",str,h)
+ report_xml("utfize, converting dec entity &#%s; into %s",str,d)
end
else
if trace_entities then
@@ -392,34 +462,44 @@ local function handle_any_entity(str)
if not a then
a = resolve_predefined and predefined_simplified[str]
if a then
- -- one of the predefined
- elseif type(resolve) == "function" then
- a = resolve(str) or entities[str]
- else
- a = entities[str]
- end
- if a then
if trace_entities then
- report_xml("resolved entity &%s; -> %s (internal)",str,a)
+ report_xml("resolved entity &%s; -> %s (predefined)",str,a)
end
- a = lpegmatch(parsedentity,a) or a
else
- local unknown_any_entity = placeholders.unknown_any_entity
- if unknown_any_entity then
- a = unknown_any_entity(str) or ""
+ if type(resolve) == "function" then
+ a = resolve(str) or entities[str]
+ else
+ a = entities[str]
end
if a then
+ if type(a) == "function" then
+ if trace_entities then
+ report_xml("expanding entity &%s; (function)",str)
+ end
+ a = a(str) or ""
+ end
+ a = lpegmatch(parsedentity,a) or a -- for nested
if trace_entities then
- report_xml("resolved entity &%s; -> %s (external)",str,a)
+ report_xml("resolved entity &%s; -> %s (internal)",str,a)
end
else
- if trace_entities then
- report_xml("keeping entity &%s;",str)
+ local unknown_any_entity = placeholders.unknown_any_entity
+ if unknown_any_entity then
+ a = unknown_any_entity(str) or ""
end
- if str == "" then
- a = "&error;"
+ if a then
+ if trace_entities then
+ report_xml("resolved entity &%s; -> %s (external)",str,a)
+ end
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("keeping entity &%s;",str)
+ end
+ if str == "" then
+ a = "&error;"
+ else
+ a = "&" .. str .. ";"
+ end
end
end
end
@@ -434,18 +514,25 @@ local function handle_any_entity(str)
else
local a = acache[str]
if not a then
- if trace_entities then
- report_xml("found entity &%s;",str)
- end
a = resolve_predefined and predefined_simplified[str]
if a then
-- one of the predefined
acache[str] = a
+ if trace_entities then
+ report_xml("entity &%s; becomes %s",str,tostring(a))
+ end
elseif str == "" then
+ if trace_entities then
+ report_xml("invalid entity &%s;",str)
+ end
a = "&error;"
acache[str] = a
else
- a = "&" .. str .. ";"
+ if trace_entities then
+ report_xml("entity &%s; is made private",str)
+ end
+ -- a = "&" .. str .. ";"
+ a = unescaped(str)
acache[str] = a
end
end
@@ -495,7 +582,7 @@ local value = (squote * Cs((entity + (1 - squote))^0) * squote) + (dq
local endofattributes = slash * close + close -- recovery of flacky html
local whatever = space * name * optionalspace * equal
-local wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
+----- wrongvalue = C(P(1-whatever-close)^1 + P(1-close)^1) / attribute_value_error
----- wrongvalue = C(P(1-whatever-endofattributes)^1 + P(1-endofattributes)^1) / attribute_value_error
----- wrongvalue = C(P(1-space-endofattributes)^1) / attribute_value_error
local wrongvalue = Cs(P(entity + (1-space-endofattributes))^1) / attribute_value_error
@@ -530,6 +617,8 @@ local function normalentity(k,v ) entities[k] = v end
local function systementity(k,v,n) entities[k] = v end
local function publicentity(k,v,n) entities[k] = v end
+-- todo: separate dtd parser
+
local begindoctype = open * P("!DOCTYPE")
local enddoctype = close
local beginset = P("[")
@@ -537,17 +626,22 @@ local endset = P("]")
local doctypename = C((1-somespace-close)^0)
local elementdoctype = optionalspace * P("<!ELEMENT") * (1-close)^0 * close
+local basiccomment = begincomment * ((1 - endcomment)^0) * endcomment
+
local normalentitytype = (doctypename * somespace * value)/normalentity
local publicentitytype = (doctypename * somespace * P("PUBLIC") * somespace * value)/publicentity
local systementitytype = (doctypename * somespace * P("SYSTEM") * somespace * value * somespace * P("NDATA") * somespace * doctypename)/systementity
local entitydoctype = optionalspace * P("<!ENTITY") * somespace * (systementitytype + publicentitytype + normalentitytype) * optionalspace * close
-local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + space)^0 * optionalspace * endset
+-- we accept comments in doctypes
+
+local doctypeset = beginset * optionalspace * P(elementdoctype + entitydoctype + basiccomment + space)^0 * optionalspace * endset
local definitiondoctype= doctypename * somespace * doctypeset
local publicdoctype = doctypename * somespace * P("PUBLIC") * somespace * value * somespace * value * somespace * doctypeset
local systemdoctype = doctypename * somespace * P("SYSTEM") * somespace * value * somespace * doctypeset
local simpledoctype = (1-close)^1 -- * balanced^0
local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
+local somedoctype = C((somespace * (publicdoctype + systemdoctype + definitiondoctype + simpledoctype) * optionalspace)^0)
local instruction = (spacing * begininstruction * someinstruction * endinstruction) / function(...) add_special("@pi@",...) end
local comment = (spacing * begincomment * somecomment * endcomment ) / function(...) add_special("@cm@",...) end
@@ -579,17 +673,31 @@ local grammar_unparsed_text = P { "preamble",
children = unparsedtext + V("parent") + emptyelement + comment + cdata + instruction,
}
--- maybe we will add settinsg to result as well
+-- maybe we will add settings to result as well
-local function xmlconvert(data, settings)
- settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
- strip = settings.strip_cm_and_dt
- utfize = settings.utfize_entities
- resolve = settings.resolve_entities
+local function _xmlconvert_(data, settings)
+ settings = settings or { } -- no_root strip_cm_and_dt given_entities parent_root error_handler
+ --
+ strip = settings.strip_cm_and_dt
+ utfize = settings.utfize_entities
+ resolve = settings.resolve_entities
resolve_predefined = settings.resolve_predefined_entities -- in case we have escaped entities
- unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
- cleanup = settings.text_cleanup
- stack, top, at, xmlns, errorstr, entities = { }, { }, { }, { }, nil, settings.entities or { }
+ unify_predefined = settings.unify_predefined_entities -- &#038; -> &amp;
+ cleanup = settings.text_cleanup
+ entities = settings.entities or { }
+ --
+ if utfize == nil then
+ settings.utfize_entities = true
+ utfize = true
+ end
+ if resolve_predefined == nil then
+ settings.resolve_predefined_entities = true
+ resolve_predefined = true
+ end
+ --
+--~ inspect(settings)
+ --
+ stack, top, at, xmlns, errorstr = { }, { }, { }, { }, nil
acache, hcache, dcache = { }, { }, { } -- not stored
reported_attribute_errors = { }
if settings.parent_root then
@@ -627,7 +735,7 @@ local function xmlconvert(data, settings)
else
errorhandler = errorhandler or xml.errorhandler
if errorhandler then
- xml.errorhandler("load",errorstr)
+ xml.errorhandler(format("load error: %s",errorstr))
end
end
else
@@ -641,7 +749,7 @@ local function xmlconvert(data, settings)
local v = rdt[k]
if type(v) == "table" and not v.special then -- always table -)
result.ri = k -- rootindex
-v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
+ v.__p__ = result -- new, experiment, else we cannot go back to settings, we need to test this !
break
end
end
@@ -649,16 +757,42 @@ v.__p__ = result -- new, experiment, else we cannot go back to settings, we nee
if errorstr and errorstr ~= "" then
result.error = true
end
+ result.statistics = {
+ entities = {
+ decimals = dcache,
+ hexadecimals = hcache,
+ names = acache,
+ }
+ }
+ strip, utfize, resolve, resolve_predefined = nil, nil, nil, nil
+ unify_predefined, cleanup, entities = nil, nil, nil
+ stack, top, at, xmlns, errorstr = nil, nil, nil, nil, nil
+ acache, hcache, dcache = nil, nil, nil
+ reported_attribute_errors, mt, errorhandler = nil, nil, nil
return result
end
+-- Because we can have a crash (stack issues) with faulty xml, we wrap this one
+-- in a protector:
+
+function xmlconvert(data,settings)
+ local ok, result = pcall(function() return _xmlconvert_(data,settings) end)
+ if ok then
+ return result
+ else
+ return _xmlconvert_("")
+ end
+end
+
xml.convert = xmlconvert
-function xml.inheritedconvert(data,xmldata)
+function xml.inheritedconvert(data,xmldata) -- xmldata is parent
local settings = xmldata.settings
- settings.parent_root = xmldata -- to be tested
+ if settings then
+ settings.parent_root = xmldata -- to be tested
+ end
-- settings.no_root = true
- local xc = xmlconvert(data,settings)
+ local xc = xmlconvert(data,settings) -- hm, we might need to locate settings
-- xc.settings = nil
-- xc.entities = nil
-- xc.special = nil
@@ -687,7 +821,7 @@ function xml.is_valid(root)
return root and not root.error
end
-xml.errorhandler = report
+xml.errorhandler = report_xml
--[[ldx--
<p>We cannot load an <l n='lpeg'/> from a filehandle so we need to load
@@ -766,18 +900,15 @@ alternative.</p>
function xml.checkbom(root) -- can be made faster
if root.ri then
- local dt, found = root.dt, false
+ local dt = root.dt
for k=1,#dt do
local v = dt[k]
if type(v) == "table" and v.special and v.tg == "@pi@" and find(v.dt[1],"xml.*version=") then
- found = true
- break
+ return
end
end
- if not found then
- insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- insert(dt, 2, "\n" )
- end
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
@@ -788,14 +919,14 @@ and then handle the lot.</p>
-- new experimental reorganized serialize
-local function verbose_element(e,handlers)
+local function verbose_element(e,handlers) -- options
local handle = handlers.handle
local serialize = handlers.serialize
local ens, etg, eat, edt, ern = e.ns, e.tg, e.at, e.dt, e.rn
local ats = eat and next(eat) and { }
if ats then
for k,v in next, eat do
- ats[#ats+1] = format('%s=%q',k,v)
+ ats[#ats+1] = format('%s=%q',k,escaped(v))
end
end
if ern and trace_entities and ern ~= ens then
@@ -811,7 +942,7 @@ local function verbose_element(e,handlers)
for i=1,#edt do
local e = edt[i]
if type(e) == "string" then
- handle(e)
+ handle(escaped(e))
else
serialize(e,handlers)
end
@@ -832,11 +963,11 @@ local function verbose_element(e,handlers)
handle("<",etg,">")
end
for i=1,#edt do
- local ei = edt[i]
- if type(ei) == "string" then
- handle(ei)
+ local e = edt[i]
+ if type(e) == "string" then
+ handle(escaped(e)) -- option: hexify escaped entities
else
- serialize(ei,handlers)
+ serialize(e,handlers)
end
end
handle("</",etg,">")
@@ -871,7 +1002,7 @@ local function verbose_root(e,handlers)
end
local function verbose_text(e,handlers)
- handlers.handle(e)
+ handlers.handle(escaped(e))
end
local function verbose_document(e,handlers)
@@ -999,20 +1130,33 @@ local result
local xmlfilehandler = newhandlers {
name = "file",
- initialize = function(name) result = io.open(name,"wb") return result end,
- finalize = function() result:close() return true end,
- handle = function(...) result:write(...) end,
+ initialize = function(name)
+ result = io.open(name,"wb")
+ return result
+ end,
+ finalize = function()
+ result:close()
+ return true
+ end,
+ handle = function(...)
+ result:write(...)
+ end,
}
-- no checking on writeability here but not faster either
--
-- local xmlfilehandler = newhandlers {
--- initialize = function(name) io.output(name,"wb") return true end,
--- finalize = function() io.close() return true end,
+-- initialize = function(name)
+-- io.output(name,"wb")
+-- return true
+-- end,
+-- finalize = function()
+-- io.close()
+-- return true
+-- end,
-- handle = io.write,
-- }
-
function xml.save(root,name)
serialize(root,xmlfilehandler,name)
end
@@ -1021,28 +1165,34 @@ local result
local xmlstringhandler = newhandlers {
name = "string",
- initialize = function() result = { } return result end,
- finalize = function() return concat(result) end,
- handle = function(...) result[#result+1] = concat { ... } end
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
}
local function xmltostring(root) -- 25% overhead due to collecting
- if root then
- if type(root) == 'string' then
- return root
- else -- if next(root) then -- next is faster than type (and >0 test)
- return serialize(root,xmlstringhandler) or ""
- end
+ if not root then
+ return ""
+ elseif type(root) == 'string' then
+ return root
+ else -- if next(root) then -- next is faster than type (and >0 test)
+ return serialize(root,xmlstringhandler) or ""
end
- return ""
end
-local function xmltext(root) -- inline
+local function __tostring(root) -- inline
return (root and xmltostring(root)) or ""
end
initialize_mt = function(root) -- redefinition
- mt = { __tostring = xmltext, __index = root }
+ mt = { __tostring = __tostring, __index = root }
end
xml.defaulthandlers = handlers
@@ -1163,7 +1313,7 @@ xml.tocdata(e,"error")
--ldx]]--
function xml.tocdata(e,wrapper)
- local whatever = xmltostring(e.dt)
+ local whatever = type(e) == "table" and xmltostring(e.dt) or e or ""
if wrapper then
whatever = format("<%s>%s</%s>",wrapper,whatever,wrapper)
end
diff --git a/Master/texmf-dist/tex/context/base/lxml-tex.lua b/Master/texmf-dist/tex/context/base/lxml-tex.lua
index 26a8b29962e..22f98980528 100644
--- a/Master/texmf-dist/tex/context/base/lxml-tex.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-tex.lua
@@ -6,9 +6,13 @@ if not modules then modules = { } end modules ['lxml-tst'] = {
license = "see context related readme files"
}
+-- Because we split and resolve entities we use the direct printing
+-- interface and not the context one. If we ever do that there will
+-- be an cldf-xml helper library.
+
local utf = unicode.utf8
-local utfchar = utf.char
+local utfchar, utfupper = utf.char, utf.upper
local concat, insert, remove = table.concat, table.insert, table.remove
local format, sub, gsub, find, gmatch, match = string.format, string.sub, string.gsub, string.find, string.gmatch, string.match
local type, next, tonumber, tostring = type, next, tonumber, tostring
@@ -18,16 +22,18 @@ local P, S, C, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc
local tex, xml = tex, xml
local lowerchars, upperchars, lettered = characters.lower, characters.upper, characters.lettered
-lxml = lxml or { }
+lxml = lxml or { }
local lxml = lxml
-local texsprint, texprint, texwrite = tex.sprint, tex.print, tex.write
-local texcatcodes, ctxcatcodes, vrbcatcodes, notcatcodes = tex.texcatcodes, tex.ctxcatcodes, tex.vrbcatcodes, tex.notcatcodes
+local ctxcatcodes, notcatcodes = tex.ctxcatcodes, tex.notcatcodes
+
+local contextsprint = context.sprint -- with catcodes (here we use fast variants, but with option for tracing)
local xmlelements, xmlcollected, xmlsetproperty = xml.elements, xml.collected, xml.setproperty
local xmlwithelements = xml.withelements
local xmlserialize, xmlcollect, xmltext, xmltostring = xml.serialize, xml.collect, xml.text, xml.tostring
local xmlapplylpath = xml.applylpath
+local xmlunprivatized, xmlprivatetoken, xmlprivatecodes = xml.unprivatized, xml.privatetoken, xml.privatecodes
local variables = (interfaces and interfaces.variables) or { }
@@ -39,8 +45,95 @@ local trace_setups = false trackers.register("lxml.setups", function(v) tra
local trace_loading = false trackers.register("lxml.loading", function(v) trace_loading = v end)
local trace_access = false trackers.register("lxml.access", function(v) trace_access = v end)
local trace_comments = false trackers.register("lxml.comments", function(v) trace_comments = v end)
+local trace_entities = false trackers.register("xml.entities", function(v) trace_entities = v end)
local report_lxml = logs.reporter("xml","tex")
+local report_xml = logs.reporter("xml","tex")
+
+local forceraw, rawroot = false, nil
+
+-- tex entities
+--
+-- todo: unprivatize attributes
+
+lxml.entities = lxml.entities or { }
+
+storage.register("lxml/entities",lxml.entities,"lxml.entities")
+
+--~ xml.placeholders.unknown_any_entity = nil -- has to be per xml
+
+local xmlentities = xml.entities
+local texentities = lxml.entities
+local parsedentity = xml.parsedentitylpeg
+
+function lxml.registerentity(key,value)
+ texentities[key] = value
+ if trace_entities then
+ report_xml("registering tex entity '%s' as: %s",key,value)
+ end
+end
+
+function lxml.resolvedentity(str)
+ if forceraw then
+ if trace_entities then
+ report_xml("passing entity '%s' as &%s;",str,str)
+ end
+ context("&%s;",str)
+ else
+ local e = texentities[str]
+ if e then
+ local te = type(e)
+ if te == "function" then
+ if trace_entities then
+ report_xml("passing entity '%s' using function",str)
+ end
+ e(str)
+ elseif e then
+ if trace_entities then
+ report_xml("passing entity '%s' as '%s'using ctxcatcodes",str,e)
+ end
+ context(e)
+ end
+ return
+ end
+ local e = xmlentities[str]
+ if e then
+ local te = type(e)
+ if te == "function" then
+ e = e(str)
+ end
+ if e then
+ if trace_entities then
+ report_xml("passing entity '%s' as '%s' using notcatcodes",str,e)
+ end
+ contextsprint(notcatcodes,e)
+ return
+ end
+ end
+ -- resolve hex and dec, todo: escape # & etc for ctxcatcodes
+ -- normally this is already solved while loading the file
+ local chr, err = lpegmatch(parsedentity,str)
+ if chr then
+ if trace_entities then
+ report_xml("passing entity '%s' as '%s' using ctxcatcodes",str,chr)
+ end
+ context(chr)
+ elseif err then
+ if trace_entities then
+ report_xml("passing faulty entity '%s' as '%s'",str,err)
+ end
+ context(err)
+ else
+ local tag = utfupper(str)
+ if trace_entities then
+ report_xml("passing entity '%s' to \\xmle using tag '%s'",str,tag)
+ end
+ context.xmle(str,tag) -- we need to use our own upper
+ end
+ end
+end
+
+-- tex interface
lxml.loaded = lxml.loaded or { }
local loaded = lxml.loaded
@@ -55,112 +148,68 @@ local finalizers = xml.finalizers
finalizers.xml = finalizers.xml or { }
finalizers.tex = finalizers.tex or { }
--- this might look inefficient but it's actually rather efficient
--- because we avoid tokenization of leading spaces and xml can be
--- rather verbose (indented)
+-- serialization with entity handling
-local newline = lpeg.patterns.newline
-local space = lpeg.patterns.spacer
local ampersand = P("&")
local semicolon = P(";")
-local spacing = newline * space^0
-local content = C((1-spacing-ampersand)^1)
-local verbose = C((1-(space+newline))^1)
-local entity = ampersand * C((1-semicolon)^1) * semicolon
-
-local xmltextcapture = (
- space^0 * newline^2 * Cc("") / texprint + -- better ^-2 ?
- space^0 * newline * space^0 * Cc(" ") / texsprint +
- content / function(str) return texsprint(notcatcodes,str) end + -- was just texsprint, current catcodes regime is notcatcodes
- entity / xml.resolvedentity
-)^0
-
-local ctxtextcapture = (
- space^0 * newline^2 * Cc("") / texprint + -- better ^-2 ?
- space^0 * newline * space^0 * Cc(" ") / texsprint +
- content / function(str) return texsprint(ctxcatcodes,str) end + -- was just texsprint, current catcodes regime is notcatcodes
- entity / xml.resolvedentity
-)^0
-
-local forceraw, rawroot = false, nil
+local entity = ampersand * C((1-semicolon)^1) * semicolon / lxml.resolvedentity -- context.bold
-function lxml.startraw()
- forceraw = true
-end
+local _, xmltextcapture = context.newtexthandler {
+ exception = entity,
+ catcodes = notcatcodes,
+}
-function lxml.stopraw()
- forceraw = false
-end
+local _, xmlspacecapture = context.newtexthandler {
+ endofline = context.xmlcdataobeyedline,
+ emptyline = context.xmlcdataobeyedline,
+ simpleline = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ exception = entity,
+ catcodes = notcatcodes,
+}
-function lxml.rawroot()
- return rawroot
-end
+local _, xmllinecapture = context.newtexthandler {
+ endofline = context.xmlcdataobeyedline,
+ emptyline = context.xmlcdataobeyedline,
+ simpleline = context.xmlcdataobeyedline,
+ exception = entity,
+ catcodes = notcatcodes,
+}
---~ function lxml.rawpath(rootid)
---~ if rawroot and type(rawroot) == "table" then
---~ local text, path, rp
---~ if not rawroot.dt then
---~ text, path, rp = "text", "", rawroot[0]
---~ else
---~ path, rp = "tree", "", rawroot.__p__
---~ end
---~ while rp do
---~ local rptg = rp.tg
---~ if rptg then
---~ path = rptg .. "/" .. path
---~ end
---~ rp = rp.__p__
---~ end
---~ return { rootid, "/" .. path, text }
---~ end
---~ end
+local _, ctxtextcapture = context.newtexthandler {
+ exception = entity,
+ catcodes = ctxcatcodes,
+}
-- cdata
-local linecommand = "\\obeyedline"
-local spacecommand = "\\obeyedspace" -- "\\strut\\obeyedspace"
-local beforecommand = ""
-local aftercommand = ""
-
-local xmlverbosecapture = (
- newline / function( ) texsprint(texcatcodes,linecommand,"{}") end +
- verbose / function(s) texsprint(vrbcatcodes,s) end +
- space / function( ) texsprint(texcatcodes,spacecommand,"{}") end
-)^0
-
-local function toverbatim(str)
- if beforecommand then texsprint(texcatcodes,beforecommand,"{}") end
- lpegmatch(xmlverbosecapture,str)
- if aftercommand then texsprint(texcatcodes,aftercommand,"{}") end
-end
+local toverbatim = context.newverbosehandler {
+ line = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ before = context.xmlcdatabefore,
+ after = context.xmlcdataafter,
+}
-function lxml.setverbatim(before,after,obeyedline,obeyedspace)
- beforecommand, aftercommand, linecommand, spacecommand = before, after, obeyedline, obeyedspace
-end
+lxml.toverbatim = context.newverbosehandler {
+ line = context.xmlcdataobeyedline,
+ space = context.xmlcdataobeyedspace,
+ before = context.xmlcdatabefore,
+ after = context.xmlcdataafter,
+ strip = true,
+}
-local obeycdata = true
+-- raw flushing
-function lxml.setcdata()
- obeycdata = true
+function lxml.startraw()
+ forceraw = true
end
-function lxml.resetcdata()
- obeycdata = false
+function lxml.stopraw()
+ forceraw = false
end
--- cdata and verbatim
-
-lxml.setverbatim("\\xmlcdatabefore", "\\xmlcdataafter", "\\xmlcdataobeyedline", "\\xmlcdataobeyedspace")
-
--- local capture = (space^0*newline)^0 * capture * (space+newline)^0 * -1
-
-function lxml.toverbatim(str)
- if beforecommand then texsprint(texcatcodes,beforecommand,"{}") end
- -- todo: add this to capture
- str = gsub(str,"^[ \t]+[\n\r]+","")
- str = gsub(str,"[ \t\n\r]+$","")
- lpegmatch(xmlverbosecapture,str)
- if aftercommand then texsprint(texcatcodes,aftercommand,"{}") end
+function lxml.rawroot()
+ return rawroot
end
-- storage
@@ -303,22 +352,23 @@ end
function lxml.withindex(name,n,command) -- will change as name is always there now
local i, p = lpegmatch(splitter,n)
if p then
- texsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}")
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",n,"}")
else
- texsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}")
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",name,"::",n,"}")
end
end
function lxml.getindex(name,n) -- will change as name is always there now
local i, p = lpegmatch(splitter,n)
if p then
- texsprint(ctxcatcodes,n)
+ contextsprint(ctxcatcodes,n)
else
- texsprint(ctxcatcodes,name,"::",n)
+ contextsprint(ctxcatcodes,name,"::",n)
end
end
--- loading (to be redone, no overload)
+-- loading (to be redone, no overload) .. best use different methods and
+-- keep raw xml (at least as option)
xml.originalload = xml.originalload or xml.load
@@ -333,28 +383,29 @@ function xml.load(filename,settings)
return xmltable
end
-local entities = xml.entities
-
local function entityconverter(id,str)
- return entities[str] and "&"..str..";" -- feed back into tex end later
+ return xmlentities[str] or xmlprivatetoken(str) or "" -- roundtrip handler
end
function lxml.convert(id,data,entities,compress)
- local settings = {
- unify_predefined_entities = true,
+ local settings = { -- we're now roundtrip anyway
+ unify_predefined_entities = true,
+ utfize_entities = true,
+ resolve_predefined_entities = true,
+ resolve_entities = function(str) return entityconverter(id,str) end, -- needed for mathml
}
if compress and compress == variables.yes then
settings.strip_cm_and_dt = true
end
- if entities and entities == variables.yes then
- settings.utfize_entities = true
- settings.resolve_entities = function (str) return entityconverter(id,str) end
- end
+ -- if entities and entities == variables.yes then
+ -- settings.utfize_entities = true
+ -- -- settings.resolve_entities = function (str) return entityconverter(id,str) end
+ -- end
return xml.convert(data,settings)
end
function lxml.load(id,filename,compress,entities)
- filename = commands.preparedfile(filename)
+ filename = commands.preparedfile(filename) -- not commands!
if trace_loading then
report_lxml("loading file '%s' as '%s'",filename,id)
end
@@ -407,12 +458,9 @@ function xml.getbuffer(name,compress,entities) -- we need to make sure that comm
end
function lxml.loadbuffer(id,name,compress,entities)
- if not name or name == "" then
- name = tex.jobname
- end
starttiming(xml)
nofconverted = nofconverted + 1
- local data = buffers.getcontent(name or id)
+ local data = buffers.collectcontent(name or id) -- name can be list
local xmltable = lxml.convert(id,data,compress,entities)
lxml.store(id,xmltable)
stoptiming(xml)
@@ -469,10 +517,11 @@ local function tex_element(e,handlers)
addindex(rootname,false,true)
ix = e.ix
end
- texsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}")
+ -- faster than context.xmlw
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",rootname,"::",ix,"}")
else
report_lxml( "fatal error: no index for '%s'",command)
- texsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}")
+ contextsprint(ctxcatcodes,"\\xmlw{",command,"}{",ix or 0,"}")
end
elseif tc == "function" then
command(e)
@@ -495,7 +544,7 @@ pihandlers[#pihandlers+1] = function(str)
if str then
local a, b, c, d = lpegmatch(parser,str)
if d then
- texsprint(ctxcatcodes,"\\xmlcontextdirective{",a",}{",b,"}{",c,"}{",d,"}")
+ contextsprint(ctxcatcodes,"\\xmlcontextdirective{",a,"}{",b,"}{",c,"}{",d,"}")
end
end
end
@@ -507,6 +556,16 @@ local function tex_pi(e,handlers)
end
end
+local obeycdata = true
+
+function lxml.setcdata()
+ obeycdata = true
+end
+
+function lxml.resetcdata()
+ obeycdata = false
+end
+
local function tex_cdata(e,handlers)
if obeycdata then
toverbatim(e.dt[1])
@@ -514,16 +573,16 @@ local function tex_cdata(e,handlers)
end
local function tex_text(e)
+ e = xmlunprivatized(e)
lpegmatch(xmltextcapture,e)
end
-local function ctx_text(e)
+local function ctx_text(e) -- can be just context(e) as we split there
lpegmatch(ctxtextcapture,e)
end
local function tex_handle(...)
--- report_lxml( "error while flushing: %s", concat { ... })
- texsprint(...) -- notcatcodes is active anyway
+ contextsprint(ctxcatcodes,...) -- notcatcodes is active anyway
end
local xmltexhandler = xml.newhandlers {
@@ -543,6 +602,62 @@ local xmltexhandler = xml.newhandlers {
lxml.xmltexhandler = xmltexhandler
+-- begin of test
+
+local function tex_space(e)
+ e = xmlunprivatized(e)
+ lpegmatch(xmlspacecapture,e)
+end
+
+local xmltexspacehandler = xml.newhandlers {
+ name = "texspace",
+ handle = tex_handle,
+ functions = {
+ ["@dt@"] = tex_doctype,
+ ["@el@"] = tex_element,
+ ["@pi@"] = tex_pi,
+ ["@cm@"] = tex_comment,
+ ["@cd@"] = tex_cdata,
+ ["@tx@"] = tex_space,
+ }
+}
+
+local function tex_line(e)
+ e = xmlunprivatized(e)
+ lpegmatch(xmllinecapture,e)
+end
+
+local xmltexlinehandler = xml.newhandlers {
+ name = "texline",
+ handle = tex_handle,
+ functions = {
+ ["@dt@"] = tex_doctype,
+ ["@el@"] = tex_element,
+ ["@pi@"] = tex_pi,
+ ["@cm@"] = tex_comment,
+ ["@cd@"] = tex_cdata,
+ ["@tx@"] = tex_line,
+ }
+}
+
+function lxml.flushspacewise(id) -- keeps spaces and lines
+ id = getid(id)
+ local dt = id and id.dt
+ if dt then
+ xmlserialize(dt,xmltexspacehandler)
+ end
+end
+
+function lxml.flushlinewise(id) -- keeps lines
+ id = getid(id)
+ local dt = id and id.dt
+ if dt then
+ xmlserialize(dt,xmltexlinehandler)
+ end
+end
+
+-- end of test
+
function lxml.serialize(root)
xmlserialize(root,xmltexhandler)
end
@@ -550,22 +665,28 @@ end
function lxml.setaction(id,pattern,action)
local collected = xmlapplylpath(getid(id),pattern)
if collected then
- for c=1,#collected do
- collected[c].command = action
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ collected[c].command = action
+ end
end
end
end
-local function sprint(root)
+local function sprint(root) -- check rawroot usage
if root then
local tr = type(root)
if tr == "string" then -- can also be result of lpath
- -- rawroot = false
+ -- rawroot = false -- ?
+ root = xmlunprivatized(root)
lpegmatch(xmltextcapture,root)
elseif tr == "table" then
if forceraw then
rawroot = root
- texwrite(xmltostring(root))
+ -- contextsprint(ctxcatcodes,xmltostring(root)) -- goes wrong with % etc
+ root = xmlunprivatized(xmltostring(root))
+ lpegmatch(xmltextcapture,root) -- goes to toc
else
xmlserialize(root,xmltexhandler)
end
@@ -585,6 +706,7 @@ local function tprint(root) -- we can move sprint inline
end
end
elseif tr == "string" then
+ root = xmlunprivatized(root)
lpegmatch(xmltextcapture,root)
end
end
@@ -595,21 +717,24 @@ local function cprint(root) -- content
-- quit
elseif type(root) == 'string' then
-- rawroot = false
+ root = xmlunprivatized(root)
lpegmatch(xmltextcapture,root)
else
local rootdt = root.dt
if forceraw then
rawroot = root
- texwrite(xmltostring(rootdt or root))
+ -- contextsprint(ctxcatcodes,xmltostring(rootdt or root))
+ root = xmlunprivatized(xmltostring(root))
+ lpegmatch(xmltextcapture,root) -- goes to toc
else
xmlserialize(rootdt or root,xmltexhandler)
end
end
end
-xml.sprint = sprint local xmlsprint = sprint -- redo these names
-xml.tprint = tprint local xmltprint = tprint
-xml.cprint = cprint local xmlcprint = cprint
+xml.sprint = sprint local xmlsprint = sprint -- calls ct mathml -> will be replaced
+xml.tprint = tprint local xmltprint = tprint -- only used here
+xml.cprint = cprint local xmlcprint = cprint -- calls ct mathml -> will be replaced
-- now we can flush
@@ -720,7 +845,7 @@ function lxml.flushsetups(id,...)
if trace_loading then
report_lxml("applying setup %02i = %s to %s",k,v,document)
end
- texsprint(ctxcatcodes,"\\xmlsetup{",id,"}{",v,"}")
+ contextsprint(ctxcatcodes,"\\xmlsetup{",id,"}{",v,"}")
done[v] = true
end
end
@@ -756,40 +881,45 @@ function lxml.setsetup(id,pattern,setup)
if not setup or setup == "" or setup == "*" or setup == "-" or setup == "+" then
local collected = xmlapplylpath(getid(id),pattern)
if collected then
- if trace_setups then
- for c=1, #collected do
- local e = collected[c]
- local ix = e.ix or 0
- if setup == "-" then
- e.command = false
- report_lxml("lpath matched (a) %5i: %s = %s -> skipped",c,ix,setup)
- elseif setup == "+" then
- e.command = true
- report_lxml("lpath matched (b) %5i: %s = %s -> text",c,ix,setup)
- else
- local tg = e.tg
- if tg then -- to be sure
- e.command = tg
- local ns = e.rn or e.ns
- if ns == "" then
- report_lxml("lpath matched (c) %5i: %s = %s -> %s",c,ix,tg,tg)
- else
- report_lxml("lpath matched (d) %5i: %s = %s:%s -> %s",c,ix,ns,tg,tg)
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ local ix = e.ix or 0
+ if setup == "-" then
+ e.command = false
+ report_lxml("lpath matched (a) %5i: %s = %s -> skipped",c,ix,setup)
+ elseif setup == "+" then
+ e.command = true
+ report_lxml("lpath matched (b) %5i: %s = %s -> text",c,ix,setup)
+ else
+ local tg = e.tg
+ if tg then -- to be sure
+ e.command = tg
+ local ns = e.rn or e.ns
+ if ns == "" then
+ report_lxml("lpath matched (c) %5i: %s = %s -> %s",c,ix,tg,tg)
+ else
+ report_lxml("lpath matched (d) %5i: %s = %s:%s -> %s",c,ix,ns,tg,tg)
+ end
end
end
end
- end
- else
- for c=1, #collected do
- local e = collected[c]
- if setup == "-" then
- e.command = false
- elseif setup == "+" then
- e.command = true
- else
- e.command = e.tg
+ else
+ for c=1,nc do
+ local e = collected[c]
+ if setup == "-" then
+ e.command = false
+ elseif setup == "+" then
+ e.command = true
+ else
+ e.command = e.tg
+ end
end
end
+ elseif trace_setups then
+ report_lxml("zero lpath matches for %s",pattern)
end
elseif trace_setups then
report_lxml("no lpath matches for %s",pattern)
@@ -799,44 +929,49 @@ function lxml.setsetup(id,pattern,setup)
if a and b then
local collected = xmlapplylpath(getid(id),pattern)
if collected then
- if trace_setups then
- for c=1, #collected do
- local e = collected[c]
- local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
- if b == "-" then
- e.command = false
- if ns == "" then
- report_lxml("lpath matched (e) %5i: %s = %s -> skipped",c,ix,tg)
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
+ if b == "-" then
+ e.command = false
+ if ns == "" then
+ report_lxml("lpath matched (e) %5i: %s = %s -> skipped",c,ix,tg)
+ else
+ report_lxml("lpath matched (f) %5i: %s = %s:%s -> skipped",c,ix,ns,tg)
+ end
+ elseif b == "+" then
+ e.command = true
+ if ns == "" then
+ report_lxml("lpath matched (g) %5i: %s = %s -> text",c,ix,tg)
+ else
+ report_lxml("lpath matched (h) %5i: %s = %s:%s -> text",c,ix,ns,tg)
+ end
else
- report_lxml("lpath matched (f) %5i: %s = %s:%s -> skipped",c,ix,ns,tg)
+ e.command = a .. tg
+ if ns == "" then
+ report_lxml("lpath matched (i) %5i: %s = %s -> %s",c,ix,tg,e.command)
+ else
+ report_lxml("lpath matched (j) %5i: %s = %s:%s -> %s",c,ix,ns,tg,e.command)
+ end
end
- elseif b == "+" then
- e.command = true
- if ns == "" then
- report_lxml("lpath matched (g) %5i: %s = %s -> text",c,ix,tg)
- else
- report_lxml("lpath matched (h) %5i: %s = %s:%s -> text",c,ix,ns,tg)
- end
- else
- e.command = a .. tg
- if ns == "" then
- report_lxml("lpath matched (i) %5i: %s = %s -> %s",c,ix,tg,e.command)
+ end
+ else
+ for c=1,nc do
+ local e = collected[c]
+ if b == "-" then
+ e.command = false
+ elseif b == "+" then
+ e.command = true
else
- report_lxml("lpath matched (j) %5i: %s = %s:%s -> %s",c,ix,ns,tg,e.command)
+ e.command = a .. e.tg
end
end
end
- else
- for c=1, #collected do
- local e = collected[c]
- if b == "-" then
- e.command = false
- elseif b == "+" then
- e.command = true
- else
- e.command = a .. e.tg
- end
- end
+ elseif trace_setups then
+ report_lxml("zero lpath matches for %s",pattern)
end
elseif trace_setups then
report_lxml("no lpath matches for %s",pattern)
@@ -844,21 +979,26 @@ function lxml.setsetup(id,pattern,setup)
else
local collected = xmlapplylpath(getid(id),pattern)
if collected then
- if trace_setups then
- for c=1, #collected do
- local e = collected[c]
- e.command = setup
- local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
- if ns == "" then
- report_lxml("lpath matched (k) %5i: %s = %s -> %s",c,ix,tg,setup)
- else
- report_lxml("lpath matched (l) %5i: %s = %s:%s -> %s",c,ix,ns,tg,setup)
+ local nc = #collected
+ if nc > 0 then
+ if trace_setups then
+ for c=1,nc do
+ local e = collected[c]
+ e.command = setup
+ local ns, tg, ix = e.rn or e.ns, e.tg, e.ix or 0
+ if ns == "" then
+ report_lxml("lpath matched (k) %5i: %s = %s -> %s",c,ix,tg,setup)
+ else
+ report_lxml("lpath matched (l) %5i: %s = %s:%s -> %s",c,ix,ns,tg,setup)
+ end
+ end
+ else
+ for c=1,nc do
+ collected[c].command = setup
end
end
- else
- for c=1, #collected do
- collected[c].command = setup
- end
+ elseif trace_setups then
+ report_lxml("zero lpath matches for %s",pattern)
end
elseif trace_setups then
report_lxml("no lpath matches for %s",pattern)
@@ -872,81 +1012,111 @@ end
local finalizers = xml.finalizers.tex
local function first(collected)
- if collected then
+ if collected and #collected > 0 then
xmlsprint(collected[1])
end
end
local function last(collected)
if collected then
- xmlsprint(collected[#collected])
+ local nc = #collected
+ if nc > 0 then
+ xmlsprint(collected[nc])
+ end
end
end
local function all(collected)
if collected then
- for c=1,#collected do
- xmlsprint(collected[c])
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ xmlsprint(collected[c])
+ end
end
end
end
local function reverse(collected)
if collected then
- for c=#collected,1,-1 do
- xmlsprint(collected[c])
+ local nc = #collected
+ if nc >0 then
+ for c=nc,1,-1 do
+ xmlsprint(collected[c])
+ end
end
end
end
local function count(collected)
- texwrite((collected and #collected) or 0)
+ contextsprint(ctxcatcodes,(collected and #collected) or 0) -- why ctxcatcodes
end
local function position(collected,n)
-- todo: if not n then == match
if collected then
- n = tonumber(n) or 0
- if n < 0 then
- n = #collected + n + 1
- end
- if n > 0 then
- xmlsprint(collected[n])
+ local nc = #collected
+ if nc > 0 then
+ n = tonumber(n) or 0
+ if n < 0 then
+ n = nc + n + 1
+ end
+ if n > 0 then
+ local cn = collected[n]
+ if cn then
+ xmlsprint(cn)
+ return
+ end
+ end
end
end
end
local function match(collected) -- is match in preceding collected, never change, see bibxml
local m = collected and collected[1]
- texwrite(m and m.mi or 0)
+ contextsprint(ctxcatcodes,m and m.mi or 0) -- why ctxcatcodes
end
local function index(collected,n)
if collected then
- n = tonumber(n) or 0
- if n < 0 then
- n = #collected + n + 1
- end
- if n > 0 then
- texwrite(collected[n].ni or 0)
+ local nc = #collected
+ if nc > 0 then
+ n = tonumber(n) or 0
+ if n < 0 then
+ n = nc + n + 1 -- brrr
+ end
+ if n > 0 then
+ local cn = collected[n]
+ if cn then
+ contextsprint(ctxcatcodes,cn.ni or 0) -- why ctxcatcodes
+ return
+ end
+ end
end
end
+ contextsprint(ctxcatcodes,0) -- why ctxcatcodes
end
local function command(collected,cmd,otherwise)
local n = collected and #collected
if n and n > 0 then
- for c=1,n do
+ local wildcard = find(cmd,"%*")
+ for c=1,n do -- maybe optimize for n=1
local e = collected[c]
local ix = e.ix
+ local name = e.name
if not ix then
- lxml.addindex(e.name,false,true)
+ lxml.addindex(name,false,true)
ix = e.ix
end
- texsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",e.name,"::",ix,"}")
+ if wildcard then
+ contextsprint(ctxcatcodes,"\\xmlw{",(gsub(cmd,"%*",e.tg)),"}{",name,"::",ix,"}")
+ else
+ contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",name,"::",ix,"}")
+ end
end
elseif otherwise then
- texsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}")
+ contextsprint(ctxcatcodes,"\\xmlw{",otherwise,"}{#1}")
end
end
@@ -955,22 +1125,22 @@ local function attribute(collected,a,default)
local at = collected[1].at
local str = (at and at[a]) or default
if str and str ~= "" then
- texsprint(notcatcodes,str)
+ contextsprint(notcatcodes,str)
end
elseif default then
- texsprint(notcatcodes,default)
+ contextsprint(notcatcodes,default)
end
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
if at then
local a = at[arguments]
if a then
- texsprint(notcatcodes,a)
+ contextsprint(notcatcodes,a)
end
else
break -- error
@@ -983,7 +1153,9 @@ end
local function text(collected)
if collected then
local nc = #collected
- if nc == 1 then -- hardly any gain so this will go
+ if nc == 0 then
+ -- nothing
+ elseif nc == 1 then -- hardly any gain so this will go
cprint(collected[1])
else for c=1,nc do
cprint(collected[c])
@@ -993,71 +1165,80 @@ end
local function ctxtext(collected)
if collected then
- for c=1,#collected do
- texsprint(ctxcatcodes,collected[1].dt)
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,collected[c].dt)
+ end
end
end
end
---~ local str = xmltext(getid(id),pattern) or ""
---~ str = gsub(str,"^%s*(.-)%s*$","%1")
---~ if nolines then
---~ str = gsub(str,"%s+"," ")
---~ end
-
local function stripped(collected) -- tricky as we strip in place
if collected then
- for c=1,#collected do
- cprint(xml.stripelement(collected[c]))
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ cprint(xml.stripelement(collected[c]))
+ end
end
end
end
local function lower(collected)
- if collected then
- for c=1,#collected do
- texsprint(ctxcatcodes,lowerchars(collected[1].dt[1]))
+ if not collected then
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,lowerchars(collected[c].dt[1]))
+ end
end
end
end
local function upper(collected)
if collected then
- for c=1,#collected do
- texsprint(ctxcatcodes,upperchars(collected[1].dt[1]))
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,upperchars(collected[c].dt[1]))
+ end
end
end
end
local function number(collected)
- if collected then
- local n = 0
- for c=1,#collected do
+ local nc = collected and #collected or 0
+ local n = 0
+ if nc > 0 then
+ for c=1,nc do
n = n + tonumber(collected[c].dt[1] or 0)
end
- texwrite(n)
end
+ contextsprint(ctxcatcodes,n)
end
local function concatrange(collected,start,stop,separator,lastseparator,textonly) -- test this on mml
if collected then
local nofcollected = #collected
- local separator = separator or ""
- local lastseparator = lastseparator or separator or ""
- start, stop = (start == "" and 1) or tonumber(start) or 1, (stop == "" and nofcollected) or tonumber(stop) or nofcollected
- if stop < 0 then stop = nofcollected + stop end -- -1 == last-1
- for i=start,stop do
- if textonly then
- xmlcprint(collected[i])
- else
- xmlsprint(collected[i])
- end
- if i == nofcollected then
- -- nothing
- elseif i == nofcollected-1 and lastseparator ~= "" then
- texsprint(ctxcatcodes,lastseparator)
- elseif separator ~= "" then
- texsprint(ctxcatcodes,separator)
+ if nofcollected > 0 then
+ local separator = separator or ""
+ local lastseparator = lastseparator or separator or ""
+ start, stop = (start == "" and 1) or tonumber(start) or 1, (stop == "" and nofcollected) or tonumber(stop) or nofcollected
+ if stop < 0 then stop = nofcollected + stop end -- -1 == last-1
+ for i=start,stop do
+ if textonly then
+ xmlcprint(collected[i])
+ else
+ xmlsprint(collected[i])
+ end
+ if i == nofcollected then
+ -- nothing
+ elseif i == nofcollected-1 and lastseparator ~= "" then
+ contextsprint(ctxcatcodes,lastseparator)
+ elseif separator ~= "" then
+ contextsprint(ctxcatcodes,separator)
+ end
end
end
end
@@ -1090,37 +1271,44 @@ finalizers.default = all -- !!
local concat = table.concat
-function finalizers.tag(collected)
+function finalizers.tag(collected,n)
if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- texsprint(c.tg)
+ local nc = #collected
+ if nc > 0 then
+ n = tonumber(n) or 0
+ local c
+ if n == 0 then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if c then
+ contextsprint(ctxcatcodes,c.tg)
+ end
end
end
end
-function finalizers.name(collected)
+function finalizers.name(collected,n)
if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- texsprint(c.tg)
+ local nc = #collected
+ if nc > 0 then
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
else
- texsprint(c.ns,":",c.tg)
+ c = collected[nc-n+1]
+ end
+ if c then
+ if c.ns == "" then
+ contextsprint(ctxcatcodes,c.tg)
+ else
+ contextsprint(ctxcatcodes,c.ns,":",c.tg)
+ end
end
end
end
@@ -1128,13 +1316,16 @@ end
function finalizers.tags(collected,nonamespace)
if collected then
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- if nonamespace or ns == "" then
- texsprint(tg)
- else
- texsprint(ns,":",tg)
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ if nonamespace or ns == "" then
+ contextsprint(ctxcatcodes,tg)
+ else
+ contextsprint(ctxcatcodes,ns,":",tg)
+ end
end
end
end
@@ -1145,14 +1336,17 @@ end
local function verbatim(id,before,after)
local root = getid(id)
if root then
- if before then texsprint(ctxcatcodes,before,"[",root.tg or "?","]") end
+ if before then contextsprint(ctxcatcodes,before,"[",root.tg or "?","]") end
lxml.toverbatim(xmltostring(root.dt))
- if after then texsprint(ctxcatcodes,after) end
+--~ lxml.toverbatim(xml.totext(root.dt))
+ if after then contextsprint(ctxcatcodes,after) end
end
end
+
function lxml.inlineverbatim(id)
verbatim(id,"\\startxmlinlineverbatim","\\stopxmlinlineverbatim")
end
+
function lxml.displayverbatim(id)
verbatim(id,"\\startxmldisplayverbatim","\\stopxmldisplayverbatim")
end
@@ -1196,27 +1390,40 @@ end
function lxml.raw(id,pattern) -- the content, untouched by commands
local collected = (pattern and xmlapplylpath(getid(id),pattern)) or getid(id)
- if collected then
- texsprint(xmltostring(collected[1].dt))
+ if collected and #collected > 0 then
+ contextsprint(notcatcodes,xmltostring(collected[1].dt))
end
end
function lxml.context(id,pattern) -- the content, untouched by commands
if not pattern then
local collected = getid(id)
- -- texsprint(ctxcatcodes,collected.dt[1])
ctx_text(collected.dt[1])
else
local collected = xmlapplylpath(getid(id),pattern) or getid(id)
if collected and #collected > 0 then
- texsprint(ctxcatcodes,collected[1].dt)
+ contextsprint(ctxcatcodes,collected[1].dt)
+ end
+ end
+end
+
+function lxml.context(id,pattern) -- the content, untouched by commands
+ if pattern then
+ local collected = xmlapplylpath(getid(id),pattern) or getid(id)
+ if collected and #collected > 0 then
+ contextsprint(ctxcatcodes,collected[1].dt)
+ end
+ else
+ local collected = getid(id)
+ if collected and #collected > 0 then
+ ctx_text(collected.dt[1])
end
end
end
function lxml.text(id,pattern)
local collected = (pattern and xmlapplylpath(getid(id),pattern)) or getid(id)
- if collected then
+ if collected and #collected > 0 then
text(collected)
end
end
@@ -1224,17 +1431,11 @@ end
lxml.content = text
function lxml.position(id,pattern,n)
- local collected = xmlapplylpath(getid(id),pattern)
- if collected then
- position(collected,n)
- end
+ position(xmlapplylpath(getid(id),pattern),n)
end
function lxml.chainattribute(id,pattern,a,default)
- local collected = xmlapplylpath(getid(id),pattern)
- if collected then
- chainattribute(collected,a,default)
- end
+ chainattribute(xmlapplylpath(getid(id),pattern),a,default)
end
function lxml.concatrange(id,pattern,start,stop,separator,lastseparator,textonly) -- test this on mml
@@ -1253,7 +1454,7 @@ lxml.index = lxml.position
function lxml.pos(id)
local root = getid(id)
- texwrite((root and root.ni) or 0)
+ contextsprint(ctxcatcodes,(root and root.ni) or 0)
end
function lxml.att(id,a,default)
@@ -1262,10 +1463,10 @@ function lxml.att(id,a,default)
local at = root.at
local str = (at and at[a]) or default
if str and str ~= "" then
- texsprint(notcatcodes,str)
+ contextsprint(notcatcodes,str)
end
elseif default then
- texsprint(notcatcodes,default)
+ contextsprint(notcatcodes,default)
end
end
@@ -1273,23 +1474,23 @@ function lxml.name(id) -- or remapped name? -> lxml.info, combine
local r = getid(id)
local ns = r.rn or r.ns or ""
if ns ~= "" then
- texsprint(ns,":",r.tg)
+ contextsprint(ctxcatcodes,ns,":",r.tg)
else
- texsprint(r.tg)
+ contextsprint(ctxcatcodes,r.tg)
end
end
function lxml.match(id) -- or remapped name? -> lxml.info, combine
- texsprint(getid(id).mi or 0)
+ contextsprint(ctxcatcodes,getid(id).mi or 0)
end
function lxml.tag(id) -- tag vs name -> also in l-xml tag->name
- texsprint(getid(id).tg or "")
+ contextsprint(ctxcatcodes,getid(id).tg or "")
end
function lxml.namespace(id) -- or remapped name?
local root = getid(id)
- texsprint(root.rn or root.ns or "")
+ contextsprint(ctxcatcodes,root.rn or root.ns or "")
end
function lxml.flush(id)
@@ -1318,15 +1519,18 @@ function lxml.command(id,pattern,cmd)
local i, p = getid(id,true)
local collected = xmlapplylpath(getid(i),pattern)
if collected then
- local rootname = p or i.name
- for c=1,#collected do
- local e = collected[c]
- local ix = e.ix
- if not ix then
- addindex(rootname,false,true)
- ix = e.ix
+ local nc = #collected
+ if nc > 0 then
+ local rootname = p or i.name
+ for c=1,nc do
+ local e = collected[c]
+ local ix = e.ix
+ if not ix then
+ addindex(rootname,false,true)
+ ix = e.ix
+ end
+ contextsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}")
end
- texsprint(ctxcatcodes,"\\xmlw{",cmd,"}{",rootname,"::",ix,"}")
end
end
end
@@ -1434,8 +1638,11 @@ lxml.get_id = getid lxml.obsolete.get_id = getid
function xml.finalizers.tex.lettered(collected)
if collected then
- for c=1,#collected do
- texsprint(ctxcatcodes,lettered(collected[1].dt[1]))
+ local nc = #collected
+ if nc > 0 then
+ for c=1,nc do
+ contextsprint(ctxcatcodes,lettered(collected[c].dt[1]))
+ end
end
end
end
@@ -1443,7 +1650,7 @@ end
--~ function xml.finalizers.tex.apply(collected,what) -- to be tested
--~ if collected then
--~ for c=1,#collected do
---~ texsprint(ctxcatcodes,what(collected[1].dt[1]))
+--~ contextsprint(ctxcatcodes,what(collected[c].dt[1]))
--~ end
--~ end
--~ end
diff --git a/Master/texmf-dist/tex/context/base/lxml-xml.lua b/Master/texmf-dist/tex/context/base/lxml-xml.lua
index 89fcba871bd..7e7922cfb25 100644
--- a/Master/texmf-dist/tex/context/base/lxml-xml.lua
+++ b/Master/texmf-dist/tex/context/base/lxml-xml.lua
@@ -6,15 +6,17 @@ if not modules then modules = { } end modules ['lxml-xml'] = {
license = "see context related readme files"
}
-local concat = string.concat
+local concat = table.concat
+local find = string.find
local xml = xml
-local finalizers = xml.finalizers.xml
-local xmlfilter = xml.filter -- we could inline this one for speed
-local xmltostring = xml.tostring
-local xmlserialize = xml.serialize
-local xmlcollected = xml.collected
+local finalizers = xml.finalizers.xml
+local xmlfilter = xml.filter -- we could inline this one for speed
+local xmltostring = xml.tostring
+local xmlserialize = xml.serialize
+local xmlcollected = xml.collected
+local xmlnewhandlers = xml.newhandlers
local function first(collected) -- wrong ?
return collected and collected[1]
@@ -28,16 +30,21 @@ local function all(collected)
return collected
end
---~ local function reverse(collected)
---~ if collected then
---~ local reversed, r = { }, 0
---~ for c=#collected,1,-1 do
---~ r = r + 1
---~ reversed[r] = collected[c]
---~ end
---~ return reversed
---~ end
---~ end
+-- local function reverse(collected)
+-- if collected then
+-- local nc = #collected
+-- if nc > 0 then
+-- local reversed, r = { }, 0
+-- for c=nc,1,-1 do
+-- r = r + 1
+-- reversed[r] = collected[c]
+-- end
+-- return reversed
+-- else
+-- return collected
+-- end
+-- end
+-- end
local reverse = table.reversed
@@ -54,34 +61,37 @@ local function att(id,name)
end
local function count(collected)
- return (collected and #collected) or 0
+ return collected and #collected or 0
end
local function position(collected,n)
- if collected then
- n = tonumber(n) or 0
- if n < 0 then
- return collected[#collected + n + 1]
- elseif n > 0 then
- return collected[n]
- else
- return collected[1].mi or 0
- end
+ if not collected then
+ return 0
+ end
+ local nc = #collected
+ if nc == 0 then
+ return 0
+ end
+ n = tonumber(n) or 0
+ if n < 0 then
+ return collected[nc + n + 1]
+ elseif n > 0 then
+ return collected[n]
+ else
+ return collected[1].mi or 0
end
end
local function match(collected)
- return (collected and collected[1].mi) or 0 -- match
+ return collected and #collected > 0 and collected[1].mi or 0 -- match
end
local function index(collected)
- if collected then
- return collected[1].ni
- end
+ return collected and #collected > 0 and collected[1].ni or 0 -- 0 is new
end
local function attributes(collected,arguments)
- if collected then
+ if collected and #collected > 0 then
local at = collected[1].at
if arguments then
return at[arguments]
@@ -92,7 +102,7 @@ local function attributes(collected,arguments)
end
local function chainattribute(collected,arguments) -- todo: optional levels
- if collected then
+ if collected and #collected > 0 then
local e = collected[1]
while e do
local at = e.at
@@ -110,108 +120,169 @@ local function chainattribute(collected,arguments) -- todo: optional levels
return ""
end
-local function raw(collected) -- hybrid
- if collected then
+local function raw(collected) -- hybrid (not much different from text so it might go)
+ if collected and #collected > 0 then
local e = collected[1] or collected
- return (e and xmlserialize(e)) or "" -- only first as we cannot concat function
+ return e and xmltostring(e) or "" -- only first as we cannot concat function
else
return ""
end
end
+--
+
+local xmltexthandler = xmlnewhandlers {
+ name = "string",
+ initialize = function()
+ result = { }
+ return result
+ end,
+ finalize = function()
+ return concat(result)
+ end,
+ handle = function(...)
+ result[#result+1] = concat { ... }
+ end,
+ escape = false,
+}
+
+local function xmltotext(root)
+ local dt = root.dt
+ if not dt then
+ return ""
+ end
+ local nt = #dt -- string or table
+ if nt == 0 then
+ return ""
+ elseif nt == 1 and type(dt[1]) == "string" then
+ return dt[1] -- no escaping of " ' < > &
+ else
+ return xmlserialize(root,xmltexthandler) or ""
+ end
+end
+
+--
+
local function text(collected) -- hybrid
- if collected then
- local e = collected[1] or collected
- return (e and xmltostring(e.dt)) or ""
+ if collected then -- no # test here !
+ local e = collected[1] or collected -- why fallback to element, how about cdata
+ return e and xmltotext(e) or ""
else
return ""
end
end
local function texts(collected)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- if e and e.dt then
- n = n + 1
- t[n] = e.dt
- end
+ if not collected then
+ return { } -- why no nil
+ end
+ local nc = #collected
+ if nc == 0 then
+ return { } -- why no nil
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ if e and e.dt then
+ n = n + 1
+ t[n] = e.dt
end
- return t
end
+ return t
end
local function tag(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- return c and c.tg
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
end
+ return c and c.tg
end
local function name(collected,n)
- if collected then
- local c
- if n == 0 or not n then
- c = collected[1]
- elseif n > 1 then
- c = collected[n]
- else
- c = collected[#collected-n+1]
- end
- if c then
- if c.ns == "" then
- return c.tg
- else
- return c.ns .. ":" .. c.tg
- end
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local c
+ if n == 0 or not n then
+ c = collected[1]
+ elseif n > 1 then
+ c = collected[n]
+ else
+ c = collected[nc-n+1]
+ end
+ if not c then
+ -- sorry
+ elseif c.ns == "" then
+ return c.tg
+ else
+ return c.ns .. ":" .. c.tg
end
end
local function tags(collected,nonamespace)
- if collected then
- local t, n = { }, 0
- for c=1,#collected do
- local e = collected[c]
- local ns, tg = e.ns, e.tg
- n = n + 1
- if nonamespace or ns == "" then
- t[n] = tg
- else
- t[n] = ns .. ":" .. tg
- end
+ if not collected then
+ return
+ end
+ local nc = #collected
+ if nc == 0 then
+ return
+ end
+ local t, n = { }, 0
+ for c=1,nc do
+ local e = collected[c]
+ local ns, tg = e.ns, e.tg
+ n = n + 1
+ if nonamespace or ns == "" then
+ t[n] = tg
+ else
+ t[n] = ns .. ":" .. tg
end
- return t
end
+ return t
end
-local function empty(collected)
- if collected then
- for c=1,#collected do
- local e = collected[c]
- if e then
- local edt = e.dt
- if edt then
- local n = #edt
- if n == 1 then
- local edk = edt[1]
- local typ = type(edk)
- if typ == "table" then
- return false
- elseif edk ~= "" then -- maybe an extra tester for spacing only
- return false
- end
- elseif n > 1 then
+local function empty(collected,spacesonly)
+ if not collected then
+ return true
+ end
+ local nc = #collected
+ if nc == 0 then
+ return true
+ end
+ for c=1,nc do
+ local e = collected[c]
+ if e then
+ local edt = e.dt
+ if edt then
+ local n = #edt
+ if n == 1 then
+ local edk = edt[1]
+ local typ = type(edk)
+ if typ == "table" then
+ return false
+ elseif edk ~= "" then
+ return false
+ elseif spacesonly and not find(edk,"%S") then
return false
end
+ elseif n > 1 then
+ return false
end
end
end
@@ -266,14 +337,14 @@ function xml.raw(id,pattern)
end
end
-function xml.text(id,pattern)
+function xml.text(id,pattern) -- brrr either content or element (when cdata)
if pattern then
-- return text(xmlfilter(id,pattern))
local collected = xmlfilter(id,pattern)
- return (collected and xmltostring(collected[1].dt)) or ""
+ return collected and #collected > 0 and xmltotext(collected[1]) or ""
elseif id then
-- return text(id)
- return xmltostring(id.dt) or ""
+ return xmltotext(id) or ""
else
return ""
end
@@ -281,6 +352,8 @@ end
xml.content = text
+--
+
function xml.position(id,pattern,n) -- element
return position(xmlfilter(id,pattern),n)
end
@@ -289,8 +362,8 @@ function xml.match(id,pattern) -- number
return match(xmlfilter(id,pattern))
end
-function xml.empty(id,pattern)
- return empty(xmlfilter(id,pattern))
+function xml.empty(id,pattern,spacesonly)
+ return empty(xmlfilter(id,pattern),spacesonly)
end
xml.all = xml.filter
diff --git a/Master/texmf-dist/tex/context/base/m-arabtex.mkii b/Master/texmf-dist/tex/context/base/m-arabtex.mkii
index 61e56e93aca..dea1cae252d 100644
--- a/Master/texmf-dist/tex/context/base/m-arabtex.mkii
+++ b/Master/texmf-dist/tex/context/base/m-arabtex.mkii
@@ -5,7 +5,7 @@
%D subtitle=Arabic,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-barcodes.mkiv b/Master/texmf-dist/tex/context/base/m-barcodes.mkiv
index b6a54089f4f..0282f706dc0 100644
--- a/Master/texmf-dist/tex/context/base/m-barcodes.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-barcodes.mkiv
@@ -5,12 +5,14 @@
%D subtitle=Barcodes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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 You can best use m-zint instead of this one.
+
% \startTEXpage
% \startPSTRICKS
% \pspicture(-4mm,-1mm)(38mm,26mm)
@@ -65,7 +67,7 @@ function moduledata.barcodes.isbn_1(original)
code= code .. c
end
end
- tex.sprint(code)
+ context(code)
end
function moduledata.barcodes.isbn_2(original)
@@ -74,7 +76,7 @@ function moduledata.barcodes.isbn_2(original)
if t and #t == 12 then
original = original .. "-" .. c
end
- tex.sprint(original)
+ context(original)
end
\stopluacode
diff --git a/Master/texmf-dist/tex/context/base/m-chart.lua b/Master/texmf-dist/tex/context/base/m-chart.lua
new file mode 100644
index 00000000000..32de8a5ba57
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/m-chart.lua
@@ -0,0 +1,877 @@
+if not modules then modules = { } end modules ['x-flow'] = {
+ version = 1.001,
+ comment = "companion to m-flow.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- when we can resolve mpcolor at the lua end we will
+-- use metapost.graphic(....) directly
+
+-- todo: labels
+
+moduledata.charts = moduledata.charts or { }
+
+local gsub, match, find, format, lower = string.gsub, string.match, string.find, string.format, string.lower
+local setmetatableindex = table.setmetatableindex
+
+local P, S, C, Cc = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc
+local lpegmatch = lpeg.match
+
+local points = number.points
+
+local variables = interfaces.variables
+
+local v_yes = variables.yes
+local v_no = variables.no
+local v_none = variables.none
+local v_standard = variables.standard
+local v_start = variables.start
+local v_overlay = variables.overlay
+local v_round = variables.round
+local v_test = variables.test
+
+local defaults = {
+ chart = {
+ name = "",
+ option = "",
+ backgroundcolor = "",
+ width = 100*65436,
+ height = 50*65436,
+ dx = 30*65436,
+ dy = 30*65436,
+ offset = 0,
+ bodyfont = "",
+ dot = "",
+ hcompact = variables_no,
+ vcompact = variables_no,
+ autofocus = "",
+ focus = "",
+ labeloffset = 5*65436,
+ commentoffset = 5*65436,
+ exitoffset = 0,
+
+ },
+ shape = { -- FLOS
+ rulethickness = 65436,
+ default = "",
+ framecolor = "darkblue",
+ backgroundcolor = "lightgray",
+ },
+ focus = { -- FLOF
+ rulethickness = 65436,
+ framecolor = "darkred",
+ backgroundcolor = "gray",
+ },
+ line = { -- FLOL
+ rulethickness = 65436,
+ radius = 10*65436,
+ color = "darkgreen",
+ corner = "",
+ dash = "",
+ arrow = "",
+ offset = "",
+ },
+ set = { -- FLOX
+ },
+ split = {
+ nx = 3,
+ ny = 3,
+ command = "",
+ marking = "",
+ before = "",
+ after = "",
+ }
+}
+
+local validshapes = {
+ ["node"] = { kind = "shape", number = 0 },
+ ["action"] = { kind = "shape", number = 24 },
+ ["procedure"] = { kind = "shape", number = 5 },
+ ["product"] = { kind = "shape", number = 12 },
+ ["decision"] = { kind = "shape", number = 14 },
+ ["archive"] = { kind = "shape", number = 19 },
+ ["loop"] = { kind = "shape", number = 35 },
+ ["wait"] = { kind = "shape", number = 6 },
+ ["subprocedure"] = { kind = "shape", number = 20 },
+ ["singledocument"] = { kind = "shape", number = 32 },
+ ["multidocument"] = { kind = "shape", number = 33 },
+
+ ["right"] = { kind = "line", number = 66 },
+ ["left"] = { kind = "line", number = 67 },
+ ["up"] = { kind = "line", number = 68 },
+ ["down"] = { kind = "line", number = 69 },
+}
+
+local validlabellocations = {
+ l = "l", left = "l",
+ r = "r", right = "r",
+ t = "t", top = "t",
+ b = "b", bottom = "b",
+ lt = "lt",
+ rt = "rt",
+ lb = "lb",
+ rb = "rb",
+ tl = "tl",
+ tr = "tr",
+ bl = "bl",
+ br = "br",
+}
+
+local validcommentlocations = {
+ l = "l", left = "l",
+ r = "r", right = "r",
+ t = "t", top = "t",
+ b = "b", bottom = "b",
+ lt = "lt",
+ rt = "rt",
+ lb = "lb",
+ rb = "rb",
+ tl = "tl",
+ tr = "tr",
+ bl = "bl",
+ br = "br",
+}
+
+local validtextlocations = {
+ l = "l", left = "l",
+ r = "r", right = "r",
+ t = "t", top = "t",
+ b = "b", bottom = "b",
+ c = "c", center = "c",
+ m = "c", middle = "m",
+ lt = "lt",
+ rt = "rt",
+ lb = "lb",
+ rb = "rb",
+ tl = "lt",
+ tr = "rt",
+ bl = "lb",
+ br = "rb",
+}
+
+setmetatableindex(validshapes,function(t,k)
+ local l = gsub(lower(k)," ","")
+ local v = rawget(t,l)
+ if not v then
+ local n = tonumber(k)
+ if n then
+ v = { kind = "shape", number = n }
+ else
+ v = rawget(t,"action")
+ end
+ end
+ t[k] = v
+ return v
+end)
+
+local charts = { }
+
+local data, hash, temp, last_x, last_y, name
+
+function commands.flow_start_chart(chartname)
+ data = { }
+ hash = { }
+ last_x, last_y = 0, 0
+ name = chartname
+end
+
+function commands.flow_stop_chart()
+ charts[name] = {
+ data = data,
+ hash = hash,
+ last_x = last_x,
+ last_y = last_y,
+ }
+ data, hash, temp = nil, nil, nil
+end
+
+-- function commands.flow_set(chartname,chartdata)
+-- local hash = { }
+-- local data = { }
+-- charts[name] = {
+-- data = data,
+-- hash = hash,
+-- }
+-- for i=1,#chartdata do
+-- local di = data[i]
+-- local name = di.name or ""
+-- if name then
+-- data[#data+1] = {
+-- name = name,
+-- labels = di.labels or { },
+-- comments = di.comments or { },
+-- exits = di.exits or { },
+-- connections = di.connections or { },
+-- settings = di.settings or { },
+-- x = di.x or 1,
+-- y = di.y or 1,
+-- }
+-- hash[name] = i
+-- end
+-- end
+-- end
+
+function commands.flow_reset(chartname)
+ charts[name] = nil
+end
+
+function commands.flow_set_current_cell(n)
+ temp = data[tonumber(n)] or { }
+end
+
+function commands.flow_start_cell(settings)
+ temp = {
+ texts = { },
+ labels = { },
+ exits = { },
+ connections = { },
+ settings = settings,
+ x = 1,
+ y = 1,
+ name = "",
+ }
+end
+
+function commands.flow_stop_cell()
+ data[#data+1] = temp
+ hash[temp.name or #data] = temp
+end
+
+function commands.flow_set_name(str)
+ temp.name = str
+end
+
+function commands.flow_set_shape(str)
+ temp.shape = str
+end
+
+function commands.flow_set_destination(str)
+ temp.destination = str
+end
+
+function commands.flow_set_text(align,str)
+ temp.texts[#temp.texts+1] = {
+ location = align,
+ text = str,
+ }
+end
+
+function commands.flow_set_overlay(str)
+ temp.overlay = str
+end
+
+function commands.flow_set_focus(str)
+ temp.focus = str
+end
+
+function commands.flow_set_figure(str)
+ temp.figure = str
+end
+
+function commands.flow_set_label(location,text)
+ temp.labels[#temp.labels+1] = {
+ location = location,
+ text = text,
+ }
+end
+
+function commands.flow_set_comment(location,text)
+ local connections = temp.connections
+ if connections then
+ local connection = connections[#connections]
+ if connection then
+ local comments = connection.comments
+ if comments then
+ comments[#comments+1] = {
+ location = location,
+ text = text,
+ }
+ end
+ end
+ end
+end
+
+function commands.flow_set_exit(location,text)
+ temp.exits[#temp.exits+1] = {
+ location = location,
+ text = text,
+ }
+end
+
+function commands.flow_set_include(name,x,y,settings)
+ data[#data+1] = {
+ include = name,
+ x = x,
+ y = y,
+ -- settings = settings,
+ }
+end
+
+local function inject(includedata,data,hash)
+ local subchart = charts[includedata.include]
+ if not subchart then
+ return
+ end
+ local subdata = subchart.data
+ if not subdata then
+ return
+ end
+ local xoffset = (includedata.x or 1) - 1
+ local yoffset = (includedata.y or 1) - 1
+ local settings = includedata.settings
+ for i=1,#subdata do
+ local si = subdata[i]
+ if si.include then
+ inject(si,data,hash)
+ else
+ local t = {
+ x = si.x + xoffset,
+ y = si.y + yoffset,
+ settings = settings,
+ }
+ setmetatableindex(t,si)
+ data[#data+1] = t
+ hash[si.name or #data] = t
+ end
+ end
+end
+
+local function pack(data,field)
+ local list, max = { }, 0
+ for e=1,#data do
+ local d = data[e]
+ local f = d[field]
+ list[f] = true
+ if f > max then
+ max = f
+ end
+ end
+ for i=1,max do
+ if not list[i] then
+ for e=1,#data do
+ local d = data[e]
+ local f = d[field]
+ if f > i then
+ d[field] = f - 1
+ end
+ end
+ end
+ end
+end
+
+local function expanded(chart,chartsettings)
+ local expandeddata = { }
+ local expandedhash = { }
+ local expandedchart = {
+ data = expandeddata,
+ hash = expandedhash,
+ }
+ setmetatableindex(expandedchart,chart)
+ local data = chart.data
+ local hash = chart.hash
+ for i=1,#data do
+ local di = data[i]
+ if di.include then
+ inject(di,expandeddata,expandedhash)
+ else
+ expandeddata[#expandeddata+1] = di
+ expandedhash[di.name or #expandeddata] = di
+ end
+ end
+ --
+ expandedchart.settings = chartsettings or { }
+ -- make locals
+ chartsettings.shape = chartsettings.shape or { }
+ chartsettings.focus = chartsettings.focus or { }
+ chartsettings.line = chartsettings.line or { }
+ chartsettings.set = chartsettings.set or { }
+ chartsettings.split = chartsettings.split or { }
+ chartsettings.chart = chartsettings.chart or { }
+ setmetatableindex(chartsettings.shape,defaults.shape)
+ setmetatableindex(chartsettings.focus,defaults.focus)
+ setmetatableindex(chartsettings.line ,defaults.line )
+ setmetatableindex(chartsettings.set ,defaults.set )
+ setmetatableindex(chartsettings.split,defaults.split)
+ setmetatableindex(chartsettings.chart,defaults.chart)
+ --
+ if chartsettings.chart.vcompact == v_yes then
+ pack(expandeddata,"y")
+ end
+ if chartsettings.chart.hcompact == v_yes then
+ pack(expandeddata,"x")
+ end
+ --
+ for i=1,#expandeddata do
+ local cell = expandeddata[i]
+ local settings = cell.settings
+ if not settings then
+ cell.settings = chartsettings
+ else
+ settings.shape = settings.shape or { }
+ settings.focus = settings.focus or { }
+ settings.line = settings.line or { }
+ setmetatableindex(settings.shape,chartsettings.shape)
+ setmetatableindex(settings.focus,chartsettings.focus)
+ setmetatableindex(settings.line ,chartsettings.line)
+ end
+ end
+ return expandedchart
+end
+
+local splitter = lpeg.splitat(",")
+
+function commands.flow_set_location(x,y)
+ if type(x) == "string" and not y then
+ x, y = lpegmatch(splitter,x)
+ end
+ if not x or x == "" then
+ x = last_x
+ elseif type(x) == "number" then
+ -- ok
+ elseif x == "+" then
+ x = last_x + 1
+ elseif x == "-" then
+ x = last_x - 1
+ elseif find(x,"^[%+%-]") then
+ x = last_x + (tonumber(x) or 0)
+ else
+ x = tonumber(x)
+ end
+ if not y or y == "" then
+ y = last_y
+ elseif type(y) == "number" then
+ -- ok
+ elseif y == "+" then
+ y = last_y + 1
+ elseif x == "-" then
+ y = last_y - 1
+ elseif find(y,"^[%+%-]") then
+ y = last_y + (tonumber(y) or 0)
+ else
+ y = tonumber(y)
+ end
+ temp.x = x or 1
+ temp.y = y or 1
+ last_x = x or last_x
+ last_y = y or last_y
+end
+
+function commands.flow_set_connection(location,displacement,name)
+ local dx, dy = lpegmatch(splitter,displacement)
+ dx = tonumber(dx)
+ dy = tonumber(dy)
+ temp.connections[#temp.connections+1] = {
+ location = location,
+ dx = dx or 0,
+ dy = dy or 0,
+ name = name,
+ comments = { },
+ }
+end
+
+local function visible(chart,cell)
+ local x, y = cell.x, cell.y
+ return
+ x >= chart.from_x and x <= chart.to_x and
+ y >= chart.from_y and y <= chart.to_y and cell
+end
+
+local function process_cells(chart,xoffset,yoffset)
+ local data = chart.data
+ if not data then
+ return
+ end
+ local focus = utilities.parsers.settings_to_hash(chart.settings.chart.focus or "")
+ for i=1,#data do
+ local cell = visible(chart,data[i])
+ if cell then
+ local settings = cell.settings
+ local shapesettings = settings.shape
+ local shape = cell.shape
+ if not shape or shape == "" then
+ shape = shapesettings.default or "none"
+ end
+ if shape ~= v_none then
+ local shapedata = validshapes[shape]
+ context("flow_begin_sub_chart ;") -- when is this needed
+ if shapedata.kind == "line" then
+ local linesettings = settings.line
+ context("flow_shape_line_color := \\MPcolor{%s} ;", linesettings.color)
+ context("flow_shape_fill_color := \\MPcolor{%s} ;", linesettings.backgroundcolor)
+ context("flow_shape_line_width := %s ; ", points(linesettingsrulethickness))
+ elseif focus[cell.focus] or focus[cell.name] then
+ local focussettings = settings.focus
+ context("flow_shape_line_color := \\MPcolor{%s} ;", focussettings.framecolor)
+ context("flow_shape_fill_color := \\MPcolor{%s} ;", focussettings.backgroundcolor)
+ context("flow_shape_line_width := %s ; ", points(focussettings.rulethickness))
+ else
+ local shapesettings = settings.shape
+ context("flow_shape_line_color := \\MPcolor{%s} ;", shapesettings.framecolor)
+ context("flow_shape_fill_color := \\MPcolor{%s} ;", shapesettings.backgroundcolor)
+ context("flow_shape_line_width := %s ; " , points(shapesettings.rulethickness))
+ end
+ context("flow_peepshape := false ;") -- todo
+ context("flow_new_shape(%s,%s,%s) ;",cell.x+xoffset,cell.y+yoffset,shapedata.number)
+ context("flow_end_sub_chart ;")
+ end
+ end
+ end
+end
+
+-- todo : make lpeg for splitter
+
+local sign = S("+p") / "1"
+ + S("-m") / "-1"
+
+local full = C(P("left"))
+ + C(P("right"))
+ + C(P("top"))
+ + C(P("bottom"))
+
+local char = P("l") / "left"
+ + P("r") / "right"
+ + P("t") / "top"
+ + P("b") / "bottom"
+
+local space = P(" ")^0
+
+local what = space
+ * (sign + Cc("0"))
+ * space
+ * (full + char)
+ * space
+ * (sign + Cc("0"))
+ * space
+ * (full + char)
+ * space
+ * P(-1)
+
+-- print(lpegmatch(what,"lr"))
+-- print(lpegmatch(what,"+l+r"))
+-- print(lpegmatch(what,"+l"))
+-- print(lpegmatch(what,"+ left+r "))
+
+local function process_connections(chart,xoffset,yoffset)
+ local data = chart.data
+ local hash = chart.hash
+ if not data then
+ return
+ end
+ local settings = chart.settings
+ for i=1,#data do
+ local cell = visible(chart,data[i])
+ if cell then
+ local connections = cell.connections
+ for j=1,#connections do
+ local connection = connections[j]
+ local othername = connection.name
+ local othercell = hash[othername]
+ if othercell then -- and visible(chart,data[i]) then
+ local cellx, celly = cell.x, cell.y
+ local otherx, othery, location = othercell.x, othercell.y, connection.location
+ if otherx > 0 and othery > 0 and cellx > 0 and celly > 0 and connection.location then
+ local what_cell, where_cell, what_other, where_other = lpegmatch(what,location)
+ if what_cell and where_cell and what_other and where_other then
+ local linesettings = settings.line
+ context("flow_smooth := %s ;", linesettings.corner == v_round and "true" or "false")
+ context("flow_dashline := %s ;", linesettings.dash == v_yes and "true" or "false")
+ context("flow_arrowtip := %s ;", linesettings.arrow == v_yes and "true" or "false")
+ context("flow_touchshape := %s ;", linesettings.offset == v_none and "true" or "false")
+ context("flow_dsp_x := %s ; flow_dsp_y := %s ;",connection.dx or 0, connection.dy or 0)
+ context("flow_connection_line_color := \\MPcolor{%s} ;",linesettings.color)
+ context("flow_connection_line_width := 2pt ;",points(linesettings.rulethickness))
+ context("flow_connect_%s_%s (%s) (%s,%s,%s) (%s,%s,%s) ;",where_cell,where_other,j,cellx,celly,what_cell,otherx,othery,what_other)
+ context("flow_dsp_x := 0 ; flow_dsp_y := 0 ;")
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+local texttemplate = "\\setvariables[flowcell:text][x=%s,y=%s,text={%s},align={%s},figure={%s},destination={%s}]"
+
+local splitter = lpeg.splitat(":")
+
+local function process_texts(chart,xoffset,yoffset)
+ local data = chart.data
+ local hash = chart.hash
+ if not data then
+ return
+ end
+ for i=1,#data do
+ local cell = visible(chart,data[i])
+ if cell then
+ local x = cell.x or 1
+ local y = cell.y or 1
+ local texts = cell.texts
+ for i=1,#texts do
+ local text = texts[i]
+ local data = text.text
+ local align = validlabellocations[text.align or ""] or text.align or ""
+ local figure = i == 1 and cell.figure or ""
+ local destination = i == 1 and cell.destination or ""
+ context('flow_chart_draw_text(%s,%s,textext("%s")) ;',x,y,format(texttemplate,x,y,data,align,figure,destination))
+ end
+ local labels = cell.labels
+ for i=1,#labels do
+ local label = labels[i]
+ local text = label.text
+ local location = validlabellocations[label.location or ""] or label.location or ""
+ if text and location then
+ context('flow_chart_draw_label(%s,%s,"%s",textext("\\strut %s")) ;',x,y,location,text)
+ end
+ end
+ local exits = cell.exits
+ for i=1,#exits do
+ local exit = exits[i]
+ local text = exit.text
+ local location = validlabellocations[exit.location or ""]
+ if text and location then
+ -- maybe make autoexit an option
+ if location == "l" and x == chart.from_x + 1 or
+ location == "r" and x == chart.to_x - 1 or
+ location == "t" and y == chart.to_y - 1 or
+ location == "b" and y == chart.from_y + 1 then
+ context('flow_chart_draw_exit(%s,%s,"%s",textext("\\strut %s")) ;',x,y,location,text)
+ end
+ end
+ end
+ local connections = cell.connections
+ for i=1,#connections do
+ local comments = connections[i].comments
+ for j=1,#comments do
+ local comment = comments[j]
+ local text = comment.text
+ local location = comment.location or ""
+ local length = 0
+ -- "tl" "tl:*" "tl:0.5"
+ local loc, len = lpegmatch(splitter,location) -- do the following in lpeg
+ if len == "*" then
+ location = validcommentlocations[loc] or ""
+ if location == "" then
+ location = "*"
+ else
+ location = location .. ":*"
+ end
+ elseif loc then
+ location = validcommentlocations[loc] or "*"
+ length = tonumber(len) or 0
+ else
+ location = validcommentlocations[location] or ""
+ end
+ if text and location then
+ context('flow_chart_draw_comment(%s,%s,%s,"%s",%s,textext("\\strut %s")) ;',x,y,i,location,length,text)
+ end
+ end
+ end
+ end
+ end
+end
+
+local function getchart(settings)
+ if not settings then
+ print("no settings given")
+ return
+ end
+ local chartname = settings.chart.name
+ if not chartname then
+ print("no name given")
+ return
+ end
+ local chart = charts[chartname]
+ if not chart then
+ print("no such chart",chartname)
+ return
+ end
+ chart = expanded(chart,settings)
+ local cc_settings = chart.settings.chart
+ local autofocus = chart.settings.chart.autofocus
+ if autofocus then
+ autofocus = utilities.parsers.settings_to_hash(autofocus)
+ if not next(autofocus) then
+ autofocus = false
+ end
+ end
+ -- check natural window
+ local x = tonumber(cc_settings.x)
+ local y = tonumber(cc_settings.y)
+ local nx = tonumber(cc_settings.nx)
+ local ny = tonumber(cc_settings.ny)
+ --
+ local minx, miny, maxx, maxy = 0, 0, 0, 0
+ local data = chart.data
+ for i=1,#data do
+ local cell = data[i]
+ if not autofocus or autofocus[cell.name] then -- offsets probably interfere with autofocus
+ local x = cell.x
+ local y = cell.y
+ if minx == 0 or x < minx then minx = x end
+ if miny == 0 or y < miny then miny = y end
+ if minx == 0 or x > maxx then maxx = x end
+ if miny == 0 or y > maxy then maxy = y end
+ end
+ end
+-- print("1>",x,y,nx,ny)
+-- print("2>",minx, miny, maxx, maxy)
+ -- check of window should be larger (maybe autofocus + nx/ny?)
+ if autofocus then
+ -- x and y are ignored
+ if nx and nx > 0 then
+ maxx = minx + nx - 1
+ end
+ if ny and ny > 0 then
+ maxy = miny + ny - 1
+ end
+ else
+ if x and x > 0 then
+ minx = x
+ end
+ if y and y > 0 then
+ miny = y
+ end
+ if nx and nx > 0 then
+ maxx = minx + nx - 1
+ end
+ if ny and ny > 0 then
+ maxy = miny + ny - 1
+ end
+ end
+-- print("3>",minx, miny, maxx, maxy)
+ --
+ local nx = maxx - minx + 1
+ local ny = maxy - miny + 1
+ -- relocate cells
+ for i=1,#data do
+ local cell = data[i]
+ cell.x = cell.x - minx + 1
+ cell.y = cell.y - miny + 1
+ end
+ chart.from_x = 1
+ chart.from_y = 1
+ chart.to_x = nx
+ chart.to_y = ny
+ chart.nx = nx
+ chart.ny = ny
+ --
+ -- inspect(chart)
+ return chart
+end
+
+local function makechart(chart)
+ local settings = chart.settings
+ context.begingroup()
+ context.forgetall()
+ --
+ context.startMPcode()
+ context("if unknown context_flow : input mp-char.mpiv ; fi ;")
+ context("flow_begin_chart(0,%s,%s);",chart.nx,chart.ny)
+ --
+ if settings.chart.option == v_test or settings.chart.dot == v_yes then
+ context("flow_show_con_points := true ;")
+ context("flow_show_mid_points := true ;")
+ context("flow_show_all_points := true ;")
+ elseif settings.chart.dot ~= "" then -- no checking done, private option
+ context("flow_show_%s_points := true ;",settings.chart.dot)
+ end
+ --
+ local backgroundcolor = settings.chart.backgroundcolor
+ if backgroundcolor and backgroundcolor ~= "" then
+ context("flow_chart_background_color := \\MPcolor{%s} ;",backgroundcolor)
+ end
+ --
+ local shapewidth = settings.chart.width
+ local gridwidth = shapewidth + 2*settings.chart.dx
+ local shapeheight = settings.chart.height
+ local gridheight = shapeheight + 2*settings.chart.dy
+ local chartoffset = settings.chart.offset
+ local labeloffset = settings.chart.labeloffset
+ local exitoffset = settings.chart.exitoffset
+ local commentoffset = settings.chart.commentoffset
+ context("flow_grid_width := %s ;", points(gridwidth))
+ context("flow_grid_height := %s ;", points(gridheight))
+ context("flow_shape_width := %s ;", points(shapewidth))
+ context("flow_shape_height := %s ;", points(shapeheight))
+ context("flow_chart_offset := %s ;", points(chartoffset))
+ context("flow_label_offset := %s ;", points(labeloffset))
+ context("flow_exit_offset := %s ;", points(exitoffset))
+ context("flow_comment_offset := %s ;", points(commentoffset))
+ --
+ local radius = settings.line.radius
+ local rulethickness = settings.line.rulethickness
+ local dx = settings.chart.dx
+ local dy = settings.chart.dy
+ if radius < rulethickness then
+ radius = 2.5*rulethickness
+ if radius > dx then
+ radius = dx
+ end
+ if radius > dy then
+ radius = dy
+ end
+ end
+ context("flow_connection_line_width := %s ;", points(rulethickness))
+ context("flow_connection_smooth_size := %s ;", points(radius))
+ context("flow_connection_arrow_size := %s ;", points(radius))
+ context("flow_connection_dash_size := %s ;", points(radius))
+ --
+ local offset = settings.chart.offset -- todo: pass string
+ if offset == v_none or offset == v_overlay or offset == "" then
+ offset = -2.5 * radius -- or rulethickness?
+ elseif offset == v_standard then
+ offset = radius -- or rulethickness?
+ end
+ context("flow_chart_offset := %s ;",points(offset))
+ --
+ context("flow_reverse_y := true ;")
+ process_cells(chart,0,0)
+ process_connections(chart,0,0)
+ process_texts(chart,0,0)
+ -- context("clip_chart(%s,%s,%s,%s) ;",x,y,nx,ny) -- todo: draw lines but not shapes
+ context("flow_end_chart ;")
+ context.stopMPcode()
+ context.endgroup()
+end
+
+function commands.flow_make_chart(settings)
+ local chart = getchart(settings)
+ if chart then
+ local settings = chart.settings
+-- if settings.split.state == v_start then
+-- local nx = chart.settings.split.nx
+-- local ny = chart.settings.split.ny
+-- local x = 1
+-- while true do
+-- local y = 1
+-- while true do
+-- -- FLOTbefore
+-- -- doif @@FLOTmarking on -> cuthbox
+-- -- @@FLOTcommand
+-- chart.from_x = x
+-- chart.from_y = y
+-- chart.to_x = math.min(x + nx - 1,chart.nx)
+-- chart.to_y = math.min(x + ny - 1,chart.ny)
+-- makechart(chart)
+-- -- FLOTafter
+-- y = y + ny
+-- if y > chart.max_y then
+-- break
+-- else
+-- y = y - dy
+-- end
+-- end
+-- x = x + nx
+-- if x > chart.max_x then
+-- break
+-- else
+-- x = x - dx
+-- end
+-- end
+-- else
+ makechart(chart)
+-- end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/m-chart.mkii b/Master/texmf-dist/tex/context/base/m-chart.mkii
index bddd435efb5..13403966bea 100644
--- a/Master/texmf-dist/tex/context/base/m-chart.mkii
+++ b/Master/texmf-dist/tex/context/base/m-chart.mkii
@@ -5,7 +5,7 @@
%D subtitle=Flow Charts,
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -478,7 +478,7 @@
\resetMPdrawing
\doglobal\newcounter\FLOWcomment
\startMPdrawing
- if unknown context_char : input mp-char.mp ; fi ;
+ if unknown context_char : input mp-char.mpii ; fi ;
grid_width := \FLOWgridwidth ;
grid_height := \FLOWgridheight ;
shape_width := \FLOWshapewidth ;
diff --git a/Master/texmf-dist/tex/context/base/m-chart.mkiv b/Master/texmf-dist/tex/context/base/m-chart.mkiv
deleted file mode 100644
index 114e7d5530c..00000000000
--- a/Master/texmf-dist/tex/context/base/m-chart.mkiv
+++ /dev/null
@@ -1,2546 +0,0 @@
-%D \module
-%D [ file=m-chart,
-%D version=1998.10.10,
-%D title=\CONTEXT\ Modules,
-%D subtitle=Flow Charts,
-%D author={Hans Hagen \& Ton Otten},
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 will be reimplemented as it can be done much more
-%D simple now in mkiv,.
-
-
-% todo: \localpushmacro/\localpopmacro (dohandleflowchart etc)
-% todo: make mkiv variant
-% todo: use dimexpr/numspr
-
-% will be redone with layers and dimexpr or even better, by just using
-% textext .. a nice example of old code
-
-%D This is an experimental module. Pieces of code will be moved
-%D to other modules. More features are possible but will be
-%D interfaces later.
-%D
-%D When finished this module will be documented. The main macro
-%D is still a rather big one and there is some redundant and
-%D slow code that needs a clean up.
-
-% arrow, dash
-% crossing
-% \goto -> \normalgoto
-% class -> class:name (ref prefix)
-% c, automatisch geen overlap zoeken
-% eind eerder chart connecties
-% relateren aan korps
-% check op bestaan naam, bestaan shape
-% auto als extern figuur
-% subchart
-% pijlen
-% focus
-% ook nog \MPmessage
-% areapath -> krappe vlak
-% clippath -> gehele vlak
-%
-% offset : clip offset
-% breedte : breedte cel
-% hoogte : hoogte cel
-% dx : halve afstand in breedte (grid breedte = breedte + 2dx)
-% dy : halve afstand in hoogte (grid hoogte = hoogte + 2dy)
-% x : x offset (clipping)
-% y : y offset (clipping)
-% nx : minimaal aantal cellen horizontaal
-% ny : minimaal aantal cellen vertikaal
-%
-% shape none en geen equivalent maken
-%
-% kaderkleur achtergrondkleur
-% lijnkleur lijndikte
-% focus focuskaderkleur focusachtergrondkleur
-% richting
-%
-% focus koppelen aan kleur
-
-\unprotect
-
-\definesorting [flowchart] [flowcharts] [\v!none] % no access
-\setupsorting [flowchart] [\c!state=\v!stop] % off by default
-
-\def\@FLOW@{@FLOW@}
-\def\@FLOC@{@FLOC@}
-\def\@FLOX@{@FLOX@}
-
-\def\@@FLOW{@@FLOW}
-\def\@@FLOL{@@FLOL}
-\def\@@FLOS{@@FLOS}
-\def\@@FLOF{@@FLOF}
-\def\@@FLOT{@@FLOT}
-\def\@@FLOX{@@FLOX}
-
-\def\@@MPx {@@MPx}
-\def\@@MPy {@@MPy}
-
-\def\FLOWbufferprefix{flw-}
-
-\def\processFLOWbuffer#1{\getbuffer[\FLOWbufferprefix#1]}
-\def\typeFLOWbuffer #1{\typebuffer[\FLOWbufferprefix#1]}
-
-\def\setFLOWname#1#2% funny hack that makes sure that we get
- {\bgroup % names that are acceptable for METAPOST
- \lccode`0=`a\lccode`1=`b\lccode`2=`c\lccode`3=`d\lccode`4=`e%
- \lccode`5=`f\lccode`6=`g\lccode`7=`h\lccode`8=`i\lccode`9=`j%
- \lccode` =`\_\lccode`-=`\_\lccode`_=`\_%
- \lowercase{\gdef#1{#2}}% todo: make a ctxlua call of this
- \egroup}
-
-% een gobble als default is sneller, en dan alleen setten als
-% nodig
-
-\def\resetFLOWcell
- {% variables
- \global\let\FLOWname \empty
- \global\let\FLOWalign \empty
- \global\let\FLOWshape \empty
- \global\let\FLOWlocation \empty
- \global\let\FLOWtext \empty
- \global\let\FLOWhelp \empty
- \global\let\FLOWdestination\empty
- \global\let\FLOWoverlay \empty
- \global\let\FLOWfocus \empty
- \global\let\tFLOWlabel \empty
- \global\let\bFLOWlabel \empty
- \global\let\lFLOWlabel \empty
- \global\let\rFLOWlabel \empty
- \global\let\bcFLOWlabel \empty
- \global\let\tcFLOWlabel \empty
- \global\let\lcFLOWlabel \empty
- \global\let\rcFLOWlabel \empty
- \global\let\tFLOWexit \empty
- \global\let\bFLOWexit \empty
- \global\let\lFLOWexit \empty
- \global\let\rFLOWexit \empty
- % commands
- \let\name \doFLOWname
- \let\shape \doFLOWshape
- \let\destination\doFLOWdestination
- \let\location \doFLOWlocation
- \let\focus \doFLOWfocus
- \let\overlay \doFLOWoverlay
- \let\figure \doFLOWfigure
- \let\text \doFLOWtext
- \let\comment \doFLOWcomment
- \let\label \doFLOWlabel
- \let\help \doFLOWhelp
- \let\connection \doFLOWconnection
- \let\exit \doFLOWexit
- % convenience commands
- \let\locate \doFLOWlocate
- \let\connect \doFLOWconnect}
-
-\let\FLOWcell \s!unknown
-\let\FLOWshape \s!unknown
-\let\FLOWdestination\s!unknown
-\let\FLOWfocus \s!unknown
-\let\FLOWoverlay \empty
-\let\FLOWtext \empty
-
-\def\doFLOWname#1%
- {\def\FLOWcell{#1}\setFLOWname\FLOWname{name_#1}\ignorespaces}
-
-\def\doFLOWshape#1%
- {\gdef\FLOWshape{#1}\ignorespaces}
-
-\def\doFLOWdestination#1%
- {\gdef\FLOWdestination{#1}\ignorespaces}
-
-\def\doFLOWlocation#1%
- {\setFLOWlocation#1\end\ignorespaces}
-
-\def\doFLOWfocus#1%
- {\gdef\FLOWfocus{#1}\ignorespaces}
-
-\def\doFLOWoverlay#1%
- {\gdef\FLOWoverlay{#1}\ignorespaces}
-
-\def\doFLOWfigure#1%
- {\defineoverlay[\s!dummy][\overlayfigure{#1}]%
- \overlay\s!dummy}
-
-\def\doFLOWtext
- {\dosingleempty\dodoFLOWtext}
-
-\def\dodoFLOWtext[#1]% % #2%
- {\gdef\FLOWalign{#1}\gdef\FLOWtext}% {#2}}
-
-\def\doFLOWcomment[#1]#2%
- {\ignorespaces\dogobblesingleempty}
-
-\def\doFLOWlabel[#1]#2% wordt dit gebruikt ?
- {\setgvalue{#1FLOWlabel}{#2}\ignorespaces}
-
-\def\doFLOWhelp#1%
- {\gdef\FLOWhelp{#1}\ignorespaces}
-
-\def\doFLOWconnection
- {\dodoubleempty\dodoFLOWconnection}
-
-\def\dodoFLOWconnection[#1][#2]#3%
- {\ignorespaces}
-
-\def\doFLOWconnect
- {\connection}
-
-\def\doFLOWlocate
- {\location}
-
-\def\doFLOWexit[#1]#2%
- {\setgvalue{#1FLOWexit}{#2}\ignorespaces}
-
-\def\startFLOWchart
- {\bgroup
- \let\stopFLOWchart\egroup
- \obeylines % lelijk, buffers nog eens fatsoeneren
- \dodoubleempty\dostartFLOWchart}
-
-\def\dostartFLOWchart[#1][#2]%
- {\preparenextFLOWchart{#1}{#2}%
- \dostartbuffer[\FLOWbufferprefix\nofFLOWcharts][startFLOWchart][stopFLOWchart]}
-
-\def\defineFLOWchart%
- {\dodoubleempty\dodefineFLOWchart}
-
-\long\def\dodefineFLOWchart[#1][#2]#3%
- {\preparenextFLOWchart{#1}{#2}%
- \setbuffer[\FLOWbufferprefix\nofFLOWcharts]#3\endbuffer}
-
-\def\preparenextFLOWchart#1#2%
- {\doglobal\increment\nofFLOWcharts
- \flowchart{#1}%
- \setxvalue{\@FLOW@-#1}{\noexpand\dohandleflowchart[\nofFLOWcharts][#2]}}
-
-\def\setupFLOWcharts{\dodoubleargument\getparameters[\@@FLOW]}
-\def\setupFLOWlines {\dodoubleargument\getparameters[\@@FLOL]}
-\def\setupFLOWshapes{\dodoubleargument\getparameters[\@@FLOS]}
-\def\setupFLOWfocus {\dodoubleargument\getparameters[\@@FLOF]}
-\def\setupFLOWsets {\dodoubleargument\getparameters[\@@FLOX]}
-
-\setupFLOWcharts
- [\c!option=,
- \c!bodyfont=,
- \c!dot=, % private option
- \c!width=12\bodyfontsize,
- \c!height=7\bodyfontsize,
- \c!maxwidth=,
- \c!maxheight=,
- \c!offset=\v!standard, % == auto offset
- \c!dx=2\bodyfontsize,
- \c!dy=2\bodyfontsize,
- \c!nx=0, % 1,
- \c!ny=0, % 1,
- \c!x=1,
- \c!y=1,
- \c!autofocus=,
- \c!focus=,
- \c!background=, % \v!color,
- \c!backgroundcolor=\s!white,
- \c!rulethickness=\linewidth,
- \c!frame=\v!off,
- \c!framecolor=]
-
-\setupFLOWlines
- [\c!corner=\v!round,
- \c!arrow=\v!yes,
- \c!dash=\v!no,
- \c!radius=.375\bodyfontsize, % 2.5\c!rulethickness
- \c!color=FLOWlinecolor,
- \c!rulethickness=.15\bodyfontsize, % 2pt,
- \c!offset=\v!none]
-
-\setupFLOWshapes
- [\c!default=action,
- \c!framecolor=FLOWframecolor,
- \c!background=\v!color,
- \c!backgroundcolor=FLOWbackgroundcolor,
- \c!backgroundscreen=\@@rsscreen,
- \c!rulethickness=.15\bodyfontsize, % 2pt,
- \c!offset=.5\bodyfontsize]
-
-\setupFLOWfocus
- [\c!framecolor=FLOWfocuscolor,
- \c!background=\@@FLOSbackground,
- \c!backgroundcolor=\@@FLOSbackgroundcolor,
- \c!backgroundscreen=\@@FLOSbackgroundscreen,
- \c!rulethickness=\@@FLOSrulethickness,
- \c!offset=\@@FLOSoffset]
-
-\definecolor [FLOWfocuscolor] [s=.2]
-\definecolor [FLOWlinecolor] [s=.5]
-\definecolor [FLOWframecolor] [s=.7]
-\definecolor [FLOWbackgroundcolor] [s=.9]
-
-\newcounter\includeFLOWx
-\newcounter\includeFLOWy
-
-\def\includeFLOWchart
- {\dodoubleempty\doincludeFLOWchart}
-
-\def\doincludeFLOWchart[#1][#2]%
- {\pushmacro\includeFLOWx
- \pushmacro\includeFLOWy
- \getparameters[FLOWi][x=1,y=1,#2]%
- \increment(\includeFLOWx,0\FLOWix)\decrement\includeFLOWx
- \increment(\includeFLOWy,0\FLOWiy)\decrement\includeFLOWy
- \def\dodoincludeFLOWchart##1%
- {\doifdefined{\@FLOW@-##1}
- {\globalpushmacro\dohandleflowchart % was local
- \gdef\dohandleflowchart[####1][####2]%
- {\globalpopmacro\dohandleflowchart % was local
- \resetFLOWlocation
- \processFLOWbuffer{####1}}%
- \getvalue{\@FLOW@-##1}}}%
- \processcommalist[#1]\dodoincludeFLOWchart
- \popmacro\includeFLOWx
- \popmacro\includeFLOWy}
-
-\def\resetFLOWlocation
- {\globallet\lastFLOWx\!!zerocount
- \globallet\lastFLOWy\!!zerocount}
-
-\def\dosetFLOWlocation[#1#2]#3#4%
- {\processaction
- [#1#2]
- [ +=>\scratchcounter\numexpr#4+ 1+#3\relax,
- -=>\scratchcounter\numexpr#4- 1+#3\relax,
- +#2=>\scratchcounter\numexpr#4+#2+#3\relax,
- -#2=>\scratchcounter\numexpr#4-#2+#3\relax,
- \s!default=>\scratchcounter\numexpr#4 +#3\relax,
- \s!unknown=>\scratchcounter\numexpr0#1#2+#3\relax]%
- \xdef#4{\the\scratchcounter}}
-
-\def\setFLOWlocation#1,#2\end
- {\dosetFLOWlocation[#1\empty]\includeFLOWx\lastFLOWx
- \dosetFLOWlocation[#2\empty]\includeFLOWy\lastFLOWy
- \xdef\FLOWlocation{\lastFLOWx,\lastFLOWy}}
-
-\def\FLOWshapes
- {node, action, procedure, product, decision, archive,
- loop, wait, subprocedure, singledocument, multidocument,
- sub procedure, single document, multi document, up, down,
- left, right}
-
-\def\FLOWlines
- {up, down, left, right}
-
-\def\FLOWsetconnect#1%
- {\donefalse
- \let\cFLOWfrom\empty
- \let\cFLOWto\empty
- \let\zFLOWfrom\!!zerocount
- \let\zFLOWto\!!zerocount
- \handletokens#1\with\doFLOWsetconnect
- \ifx\cFLOWto\empty\let\cFLOWfrom\empty\fi}
-
-\def\doFLOWsetconnect#1%
- {\ifx #1p%
- \ifdone\def\zFLOWto{+1}\else\def\zFLOWfrom{+1}\fi
- \else\ifx#1+%
- \ifdone\def\zFLOWto{+1}\else\def\zFLOWfrom{+1}\fi
- \else\ifx#1n%
- \ifdone\def\zFLOWto{-1}\else\def\zFLOWfrom{-1}\fi
- \else\ifx#1-%
- \ifdone\def\zFLOWto{-1}\else\def\zFLOWfrom{-1}\fi
- \else\ifdone
- \edef\cFLOWto{\FLOWconnector#1}%
- \else
- \edef\cFLOWfrom{\FLOWconnector#1}%
- \donetrue
- \fi\fi\fi\fi\fi}
-
-\def\FLOWconnector#1%
- {\if#1bbottom\else\if#1ttop\else\if#1lleft\else\if#1rright\fi\fi\fi\fi}
-
-\newif\ifFLOWscaling \FLOWscalingtrue
-
-\def\@@FLOW@@offset{\@@FLOWoffset}
-
-\def\getFLOWchart
- {\dodoubleempty\dogetFLOWchart}
-
-\def\dogetFLOWchart[#1][#2]%
- {\doifundefinedelse{\@FLOW@-#1}
- {\writestatus{FLOW}{unknown chart #1}%
- \framed
- [\c!width=12\bodyfontsize,\c!height=8\bodyfontsize]
- {\tttf [chart #1]}}
- {\dodogetFLOWchart[#1][#2]}}
-
-\def\dodogetFLOWchart[#1][#2]% to be split a bit more
- {\vbox\bgroup
- \insidefloattrue
- \forgetall
- \dontcomplain
- % \offinterlineskip % we now explicitly use \nointerlineskip later on
- \def\dohandleflowchart[##1][##2]%
- {\def\currentFLOWnumber{##1}%
- \getparameters[\@@FLOW][##2]}%
- \getvalue{\@FLOW@-#1}%
- \getparameters[\@@FLOW][#2]% dubbelop ?
- \doifsomething{\@@FLOWautofocus}
- {\checkFLOWautofocus}%
- %\message{AUTOSHAPE 3: (\@@FLOWx,\@@FLOWy)->(\@@FLOWnx,\@@FLOWny)}\wait
- \global\let\FLOWwidth \@@FLOWnx
- \global\let\FLOWheight\@@FLOWny
- \let\startFLOWcell\startFLOWcellA
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber
- \ifcase\@@FLOWnx\relax \let\@@FLOWnx\FLOWwidth \fi
- \ifcase\@@FLOWny\relax \let\@@FLOWny\FLOWheight \fi
- \doifnothing{\@@FLOWmaxwidth\@@FLOWmaxheight}{\FLOWscalingfalse}%
- \ifFLOWscaling
- \doifnothing{\@@FLOWmaxwidth }{\let\@@FLOWmaxwidth \maxdimen}%
- \doifnothing{\@@FLOWmaxheight}{\let\@@FLOWmaxheight\maxdimen}%
- \scratchcounter\bodyfontpoints
- \doloop % NOG FONTSWITCH OM EX EN EM TE LATEN WERKEN
- {\ifnum\scratchcounter>1 % NU DIMENSIONS IN TERMS OF BODYFONTSIZE
- \bodyfontsize=\the\scratchcounter pt
- \dimen0=\@@FLOWmaxwidth
- \dimen2=\@@FLOWwidth
- \dimen4=\@@FLOWdx
- \advance\dimen2 2\dimen4
- \dimen2=\@@FLOWnx\dimen2
- \advance\dimen2 2\dimen4
- \ifdim\dimen2>\dimen0
- \advance\scratchcounter \minusone
- \else
- \dimen0=\@@FLOWmaxheight
- \dimen2=\@@FLOWheight
- \dimen4=\@@FLOWdy
- \advance\dimen2 2\dimen4
- \dimen2=\@@FLOWny\dimen2
- \advance\dimen2 2\dimen4
- \ifdim\dimen2>\dimen0
- \advance\scratchcounter \minusone
- \else
- \exitloop
- \fi
- \fi
- \else
- \exitloop
- \fi}%
- \expanded{\switchtobodyfont[\the\scratchcounter pt]}%
- \forgetall
- % \offinterlineskip % needed ?
- \else\ifx\@@FLOWbodyfont\empty\else
- \expanded{\switchtobodyfont[\@@FLOWbodyfont]}% \expanded ?
- \fi\fi
- \global\let\FLOWcells\empty
- \dimen0=\@@FLOWwidth
- \edef\FLOWshapewidth{\the\dimen0}%
- \dimen2=\@@FLOWdx
- \advance\dimen0 2\dimen2
- \edef\FLOWgridwidth{\the\dimen0}%
- \dimen0=\@@FLOWheight
- \edef\FLOWshapeheight{\the\dimen0}%
- \dimen2=\@@FLOWdy
- \advance\dimen0 2\dimen2
- \edef\FLOWgridheight{\the\dimen0}%
- \scratchdimen=\@@FLOSrulethickness
- \edef\@@FLOSrulethickness{\the\scratchdimen}%
- \scratchdimen=\@@FLOFrulethickness
- \edef\@@FLOFrulethickness{\the\scratchdimen}%
- \scratchdimen=\@@FLOLrulethickness
- \edef\@@FLOLrulethickness{\the\scratchdimen}%
- \ifdim\@@FLOLradius<2.5\scratchdimen
- \scratchdimen=2.5\scratchdimen
- \edef\@@FLOLradius{\the\scratchdimen}%
- \ifdim\@@FLOLradius>\@@FLOWdx
- \scratchdimen=\@@FLOWdx
- \edef\@@FLOLradius{\the\scratchdimen}%
- \fi
- \ifdim\@@FLOLradius>\@@FLOWdy
- \scratchdimen=\@@FLOWdy
- \edef\@@FLOLradius{\the\scratchdimen}%
- \fi
- \else
- \scratchdimen=\@@FLOLradius
- \edef\@@FLOLradius{\the\scratchdimen}%
- \fi
- \processaction % magic 2.5
- [\@@FLOWoffset]
- [ \v!none=>\scratchdimen=-2.5\scratchdimen,
- \v!overlay=>\scratchdimen=-2.5\scratchdimen,
- \v!standard=>\scratchdimen=\scratchdimen,
- \s!unknown=>\scratchdimen=\@@FLOWoffset,
- \s!default=>\scratchdimen=-2.5\scratchdimen]%
- \edef\@@FLOW@@offset{\the\scratchdimen}%
- \forgetall
- \offinterlineskip
- \resetMPdrawing
- \doglobal\newcounter\FLOWcomment
- \startMPdrawing
- if unknown context_char : input mp-char.mp ; fi ;
- grid_width := \FLOWgridwidth ;
- grid_height := \FLOWgridheight ;
- shape_width := \FLOWshapewidth ;
- shape_height := \FLOWshapeheight ;
- connection_line_width := \@@FLOLrulethickness ;
- connection_smooth_size := \@@FLOLradius ;
- connection_arrow_size := \@@FLOLradius ;
- connection_dash_size := \@@FLOLradius ;
- currentpicture := nullpicture ;
- begin_chart(0,\FLOWwidth,\FLOWheight);
- reverse_y := true ;
- chart_offset := \@@FLOW@@offset ;
- \stopMPdrawing
- \doifelsenothing\@@FLOWbackgroundcolor
- {\startMPdrawing
- chart_background_color := white ;
- \stopMPdrawing}
- {\startMPdrawing
- chart_background_color := \MPcolor{\@@FLOWbackgroundcolor} ;
- \stopMPdrawing}%
- \doif\@@FLOWoption\v!test
- {\startMPdrawing
- show_con_points := true ;
- show_mid_points := true ;
- show_all_points := true ;
- \stopMPdrawing}%
- \processaction % private
- [\@@FLOWdot]
- [ \v!yes=>\startMPdrawing
- show_con_points := true ;
- show_mid_points := true ;
- show_all_points := true ;
- \stopMPdrawing,
- \s!unknown=>\startMPdrawing
- show_\@@FLOWdot _points := true ;
- \stopMPdrawing]%
-\doglobal\newcounter\FLOWcomment
- \let\startFLOWcell\startFLOWcellB
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber
-\doglobal\newcounter\FLOWcomment
- \let\startFLOWcell\startFLOWcellC
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber
- \startMPdrawing
- clip_chart(\@@FLOWx,\@@FLOWy,\@@FLOWnx,\@@FLOWny) ;
- end_chart ;
- \stopMPdrawing
- \MPdrawingdonetrue
- \setbox0\hbox
- {\MPstaticgraphictrue
- \MPshiftdrawingfalse
- \getMPdrawing}%
- \def\MPmessage##1%
- {\writestatus{MP charts}{##1}}%
- \def\MPposition##1##2##3%
- {\setvalue{\@@MPx##1}{##2}\setvalue{\@@MPy##1}{##3}}%
- \def\MPclippath##1##2##3##4%
- {\def\clipMPllx{##1bp}\def\clipMPlly{##2bp}%
- \def\clipMPurx{##3bp}\def\clipMPury{##4bp}}%
- \def\MPareapath##1##2##3##4%
- {\def\areaMPllx{##1bp}\def\areaMPlly{##2bp}%
- \def\areaMPurx{##3bp}\def\areaMPury{##4bp}}%
- \getMPdata
- \doglobal\newcounter\FLOWcomment
- \let\startFLOWcell\startFLOWcellD
- \setbox2\vbox to \ht0
- {\forgetall % \offinterlineskip
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber\vss}%
- \setbox2\hbox
- {\hskip\@@FLOW@@offset\lower\@@FLOW@@offset\box2}%
- \wd2\wd0\ht2\ht0\dp2\dp0
- \let\startFLOWcell\startFLOWcellE
- \setbox4\vbox to \ht0
- {\forgetall % \offinterlineskip
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber\vss}%
- \setbox4\hbox
- {\hskip\@@FLOW@@offset\lower\@@FLOW@@offset\box4}%
- \wd4\wd0\ht4\ht0\dp4\dp0
- \doifelse\@@FLOWoption\v!test
- {\setbox6\vbox
- {\forgetall
- \vskip\@@FLOW@@offset
- \hskip\@@FLOW@@offset
- \basegrid
- [\c!x=\@@FLOWx,\c!nx=\@@FLOWnx,\c!dx=\withoutpt\FLOWgridwidth,
- \c!y=\@@FLOWy,\c!ny=\@@FLOWny,\c!dy=\withoutpt\FLOWgridheight,
- \c!xstep=1,\c!ystep=1,
- \c!unit=pt,\c!location=\v!middle]}%
- \wd6\wd0\ht6\ht0\dp6\dp0
- \setbox8\vbox
- {\forgetall
- \offinterlineskip
- \vskip\@@FLOW@@offset
- \dostepwiserecurse\@@FLOWy\@@FLOWny\plusone
- {\vbox to \FLOWgridheight
- {\vfill
- \hskip\@@FLOW@@offset
- \hbox
- {\dostepwiserecurse\@@FLOWx\@@FLOWnx\plusone
- {\hbox to \FLOWgridwidth
- {\hfill
- \framed
- [\c!framecolor=red,
- \c!width=\FLOWshapewidth,
- \c!height=\FLOWshapeheight]
- {}%
- \hfill}}}
- \vfill}}}%
- \wd8\wd0\ht8\ht0\dp8\dp0
- \framed
- [\c!offset=\v!overlay,\c!framecolor=green]
- {\hbox{\box4\hskip-\wd0\box0\hskip-\wd2\box2\hskip-\wd6\box6\hskip-\wd8\box8}}}
- {\framed
- [\c!offset=\v!overlay,
- \c!frame=\@@FLOWframe,
- \c!rulethickness=\@@FLOWrulethickness,
- \c!framecolor=\@@FLOWframecolor,
- \c!background=\@@FLOWbackground,
- \c!backgroundcolor=\@@FLOWbackgroundcolor]
- {\hbox{\box4\hskip-\wd0\box0\hskip-\wd2\box2}}}%
- %\message{[\FLOWcells]}\wait
- \egroup}
-
-% Pass A
-
-\long\def\startFLOWcellA#1\stopFLOWcell%
- {\resetFLOWcell
- \ignorespaces#1\unskip
- \expandafter\getFLOWlocationA\FLOWlocation\end
- \ignorespaces}
-
-\def\getFLOWlocationA#1,#2\end
- {\ifnum0#1>\FLOWwidth \xdef\FLOWwidth {#1}\fi
- \ifnum0#2>\FLOWheight\xdef\FLOWheight{#2}\fi}
-
-% Pass B
-%
-% beware: the - after \@FLOC@ is needed since name can be
-% empty and we don't want to redefine \@FLOC@ itself by
-% mistake
-
-\long\def\startFLOWcellB#1\stopFLOWcell
- {\resetFLOWcell\ignorespaces#1\unskip
- \setxvalue{\@FLOC@-\FLOWname}{\FLOWlocation}% kost veel cs's
- \ifx\FLOWshape\empty
- \global\let\FLOWshape\@@FLOSdefault
- \fi
- \doifnot\FLOWshape{none} % {\v!none}
- {\doifinsetelse\FLOWshape\FLOWshapes
- {\edef\FLOWshapetag{shape_ \FLOWshape}% beter \expanded
- \@EA\setFLOWname\@EA\FLOWshapetag\@EA{\FLOWshapetag}}
- {\doifnumberelse\FLOWshape
- {\let\FLOWshapetag\FLOWshape}
- {\let\FLOWshapetag\empty}}%
- \ifx\FLOWshapetag\empty \else
- \doifinsetelse\FLOWshape\FLOWlines
- {\chardef\FLOWstate0 }
- {\doifcommonelse{\FLOWcell,\FLOWfocus}\@@FLOWfocus
- {\chardef\FLOWstate1 }
- {\chardef\FLOWstate2 }}%
- \startMPdrawing
- begin_sub_chart ;
- \ifcase\FLOWstate
- shape_line_color := \MPcolor{\@@FLOLcolor} ;
- shape_fill_color := \MPcolor{\@@FLOLcolor} ;
- shape_line_width := \@@FLOLrulethickness ;
- \or
- shape_line_color := \MPcolor{\@@FLOFframecolor} ;
- shape_fill_color := \MPcolor{\@@FLOFbackgroundcolor} ;
- shape_line_width := \@@FLOFrulethickness ;
- \or
- shape_line_color := \MPcolor{\@@FLOSframecolor} ;
- shape_fill_color := \MPcolor{\@@FLOSbackgroundcolor} ;
- shape_line_width := \@@FLOSrulethickness ;
- \fi
- %\ifx\FLOWoverlay\empty
- % peepshape := false ;
- %\else
- % peepshape := true ;
- %\fi
- peepshape := \ifx\FLOWoverlay\empty false \else true \fi ;
- new_shape(\FLOWlocation,\FLOWshapetag) ;
- end_sub_chart ;
- \stopMPdrawing
- \fi}%
- \ignorespaces}
-
-% Pass C
-
-\long\def\startFLOWcellC#1\stopFLOWcell%
- {\resetFLOWcell
-\pushmacro\lastFLOWx
-\pushmacro\lastFLOWy
- \ignorespaces#1\unskip % makes sure that vars are set
-\popmacro\lastFLOWy
-\popmacro\lastFLOWx
- \let\connection\doFLOWconnectionC
- \ignorespaces#1\unskip}
-
-\def\FLOWorigin{0,0}
-
-\def\doFLOWdisplace[#1,#2,#3]% experiment
- {dsp_x := #1 ; dsp_y := #2 ;}
-
-\def\doFLOWconnectionC
- {\dodoubleempty\dodoFLOWconnectionC}
-
-\def\dodoFLOWconnectionC[#1][#2]#3%
- {\doglobal\increment\FLOWcomment
- \setFLOWname\otherFLOWname{name_#3}%
- \doifdefinedelse{\@FLOC@-\FLOWname}
- {\edef\FLOWfrom{\getvalue{\@FLOC@-\FLOWname}}}
- {\let \FLOWfrom \FLOWorigin}%
- \ifx\FLOWfrom\FLOWorigin \else
- \doifdefinedelse{\@FLOC@-\otherFLOWname}
- {\edef\FLOWto {\getvalue{\@FLOC@-\otherFLOWname}}}
- {\let \FLOWto \FLOWorigin}%
- \ifx\FLOWto\FLOWorigin \else
- \FLOWsetconnect{#1}%
- \ifx\cFLOWfrom\empty \else
- \doifelse\@@FLOLcorner\v!round
- {\startMPdrawing smooth := true ; \stopMPdrawing}
- {\startMPdrawing smooth := false ; \stopMPdrawing}%
- \doifelse\@@FLOLdash\v!yes
- {\startMPdrawing dashline := true ; \stopMPdrawing}
- {\startMPdrawing dashline := false ; \stopMPdrawing}%
- \doifelse\@@FLOLarrow\v!yes
- {\startMPdrawing arrowtip := true ; \stopMPdrawing}
- {\startMPdrawing arrowtip := false ; \stopMPdrawing}%
- \doifelse\@@FLOLoffset\v!none
- {\startMPdrawing touchshape := true ; \stopMPdrawing}
- {\startMPdrawing touchshape := false ; \stopMPdrawing}%
-%\doifsomething{#2}
-% {\startMPdrawing
-% \doFLOWdisplace[0#2,0,0]%
-% \stopMPdrawing}%
- \startMPdrawing
-\doFLOWdisplace[0#2,0,0]%
- connection_line_color := \MPcolor{\@@FLOLcolor} ;
- connection_line_width := \@@FLOLrulethickness ;
- connect_\cFLOWfrom _\cFLOWto (\FLOWfrom,\zFLOWfrom) (\FLOWto,\zFLOWto) ;
-\doFLOWdisplace[0,0,0]%
- \stopMPdrawing
- \fi
- \fi
- \fi
- \ignorespaces}
-
-% Pass D
-
-\long\def\startFLOWcellD#1\stopFLOWcell
- {\resetFLOWcell
-\pushmacro\lastFLOWx
-\pushmacro\lastFLOWy
- \ignorespaces#1\unskip % presets vars
-\popmacro\lastFLOWy
-\popmacro\lastFLOWx
- \let\doprocessFLOWcell\doprocessFLOWcellD
- \expandafter\doprocessFLOWcellD\FLOWlocation\end
- \let\connection\doFLOWconnectionD
- \let\comment\doFLOWcommentD
- \ignorespaces#1\unskip\ignorespaces}
-
-\def\doFLOWconnectionD
- {\dodoubleempty\dodoFLOWconnectionD}
-
-\def\dodoFLOWconnectionD[#1][#2]#3%
- {\doglobal\increment\FLOWcomment
- \ignorespaces}
-
-\def\doFLOWcommentD[#1]#2%
- {\bgroup
- \let\FLOW \middlebox
- \let\FLOWb \bottombox
- \let\FLOWbl\bottomleftbox
- \let\FLOWbr\bottomrightbox
- \let\FLOWt \topbox
- \let\FLOWtl\topleftbox
- \let\FLOWtr\toprightbox
- \let\FLOWl \leftbox
- \let\FLOWlt\lefttopbox
- \let\FLOWlb\leftbottombox
- \let\FLOWr \rightbox
- \let\FLOWrt\righttopbox
- \let\FLOWrb\rightbottombox
- \let\FLOWc \middlebox
-%\ifdefined{FLOW#1}%
- \ifcase0\getvalue{\@@MPx\FLOWcomment}\getvalue{\@@MPy\FLOWcomment}\relax
- \else
- \ifdim\getvalue{\@@MPx\FLOWcomment}\s!bp<\areaMPllx\relax\else
- \ifdim\getvalue{\@@MPx\FLOWcomment}\s!bp>\areaMPurx\relax\else
- \ifdim\getvalue{\@@MPy\FLOWcomment}\s!bp<\areaMPlly\relax\else
- \ifdim\getvalue{\@@MPy\FLOWcomment}\s!bp>\areaMPury\relax\else
- \dimen0=\getvalue{\@@MPx\FLOWcomment}\s!bp
- \advance\dimen0 -\@@FLOW@@offset
- \advance\dimen0 -\clipMPllx
- \dimen2=\clipMPury
- \advance\dimen2 -\@@FLOW@@offset
- \advance\dimen2 -\getvalue{\@@MPy\FLOWcomment}\s!bp
- \setbox\scratchbox\hbox{\strut#2}%
- \boxoffset.5\bodyfontsize
- \setbox\scratchbox\hbox{\hskip\dimen0\lower\dimen2\getvalue{FLOW#1}{\box\scratchbox}}%
- \smashbox\scratchbox
- \box\scratchbox
- \boxoffset\zeropoint
- \nointerlineskip % really needed
- \fi
- \fi
- \fi
- \fi
- \fi
-%\fi
- \egroup
- \ignorespaces}
-
-% pass D
-
-\def\dophaseoneFLOWcellX#1#2%
- {\!!counta#1\relax
- \!!countb#2\relax
- \!!countc\@@FLOWx
- \!!countd\@@FLOWy
- \advance\!!countc \@@FLOWnx
- \advance\!!countd \@@FLOWny
- \advance\!!countc \minusone
- \advance\!!countd \minusone
- \ifnum\!!counta<\@@FLOWx\relax \donefalse
- \else\ifnum\!!counta>\!!countc \donefalse
- \else\ifnum\!!countb<\@@FLOWy\relax \donefalse
- \else\ifnum\!!countb>\!!countd \donefalse
- \else \donetrue
- \fi\fi\fi\fi}
-
-\def\dophasetwoFLOWcellX
- {\advance\!!counta -\@@FLOWx
- \advance\!!counta \plusone
- \advance\!!countb -\@@FLOWy
- \advance\!!countb \plusone
- \dimen0=\FLOWgridwidth
- \dimen0=\!!counta\dimen0
- \advance\dimen0 -\FLOWgridwidth
- \dimen4=\FLOWgridwidth
- \advance\dimen4 -\FLOWshapewidth
- \advance\dimen0 .5\dimen4
- \dimen2=\FLOWgridheight
- \dimen2=\!!countb\dimen2
- \dimen4=\FLOWgridheight
- \advance\dimen4 -\FLOWshapeheight
- \advance\dimen2 -.5\dimen4
- \edef\FLOWdx{\the\dimen0}%
- \edef\FLOWdy{\the\dimen2}}
-
-\def\positionFLOWzero% assumes \FLOWdx and \FLOWdy are set
- {\setbox0\hbox{\hskip\FLOWdx\lower\FLOWdy\box0}%
- \smashbox0\box0
- \nointerlineskip} % new, needed since we somehow reset that
-
-\def\doFLOWtlabel#1#2#3%
- {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
- \setbox0\hbox{\hskip\dimen2\raise\scratchdimen
- \hbox{\raise\dimen4\hbox{#1{\strut#3}}}}%
- \positionFLOWzero}%
-
-\def\doFLOWblabel#1#2#3%
- {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
- \setbox0\hbox{\hskip\dimen2\raise-\scratchdimen
- \hbox{#1{\strut#3}}}%
- \positionFLOWzero}%
-
-\def\doFLOWllabel#1#2#3%
- {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
- \setbox0\hbox{\hskip-\scratchdimen\raise\dimen6
- \hbox{#1{\strut#3}}}%
- \positionFLOWzero}%
-
-\def\doFLOWrlabel#1#2#3%
- {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
- \setbox0\hbox{\hskip\dimen0\hskip\scratchdimen
- \hbox{\raise\dimen6\hbox{#1{\strut#3}}}}%
- \positionFLOWzero}
-
-\def\doprocessFLOWcellD#1,#2\end
- {\dophaseoneFLOWcellX{#1}{#2}%
- \ifdone
- \dophasetwoFLOWcellX
- \doglobal\addtocommalist\FLOWcell\FLOWcells
- \def\FLOWx{#1}%
- \def\FLOWy{#2}%
- \directsetup{flowcell}%
- \setbox0\hbox
- {\ifx\FLOWalign\empty\else
- \setupframed
- [\c!align=\v!normal,\c!bottom=\vfill,\c!top=\vfill]%
- \@EA\processallactionsinset\@EA
- [\FLOWalign]
- [t=>{\setupframed[\c!bottom=\vfill,\c!top=]},
- b=>{\setupframed[\c!bottom=,\c!top=\vfill]},
- l=>{\setupframed[\c!align=\v!right]},
- r=>{\setupframed[\c!align=\v!left]},
- m=>{\setupframed[\c!align=\v!middle]},
- c=>{\setupframed[\c!align=\v!middle]}]%
- \fi
- \doifelse\FLOWshape{none} % {\v!none}
- {\setupframed[\c!offset=\v!overlay]}
- {\setupframed[\c!offset=\@@FLOSoffset]}%
- \framed
- [\c!frame=\v!off,\c!background=flowcell,
- \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
- {\FLOWtext}}%
- \showFLOWhelp0
- \ifx\FLOWdestination\empty\else
- \setbox0\hbox
- {\setupinteraction[\c!color=,\c!contrastcolor=]%
- \gotobox{\box0}[\FLOWdestination]}%
- \fi
- \positionFLOWzero
- \dimen0=\FLOWshapewidth \dimen2=.5\dimen0
- \dimen4=\FLOWshapeheight\dimen6=.5\dimen4
- \boxoffset.5\bodyfontsize
- \doFLOWtlabel \righttopbox0\tFLOWlabel
- \doFLOWblabel\rightbottombox0\bFLOWlabel
- \doFLOWllabel \lefttopbox0\lFLOWlabel
- \doFLOWrlabel \righttopbox0\rFLOWlabel
- \doFLOWtlabel \topbox0\tcFLOWlabel % for me only
- \doFLOWblabel \bottombox0\bcFLOWlabel % for me only
- \doFLOWllabel \leftbox0\lcFLOWlabel % for me only
- \doFLOWrlabel \rightbox0\rcFLOWlabel % for me only
- \ifnum#1=\@@FLOWx\relax \doFLOWllabel \leftbox1\lFLOWexit \fi
- \ifnum#1=\!!countc \doFLOWrlabel \rightbox1\rFLOWexit \fi
- \ifnum#2=\@@FLOWy\relax \doFLOWtlabel \topbox1\tFLOWexit \fi
- \ifnum#2=\!!countd \doFLOWblabel \bottombox1\bFLOWexit \fi
- \boxoffset\zeropoint
- \fi}
-
-% For Willy Egger:
-%
-% \startsetups flowcell
-% \definelayer
-% [flowcell]
-% [width=\FLOWshapewidth,
-% height=\FLOWshapeheight]
-% \setlayerframed
-% [flowcell]
-% [preset=rightbottom,offset=1ex]
-% [frame=off]
-% {\tx(\FLOWx,\FLOWy)}
-% \stopsetups
-
-% Pass E
-
-\long\def\startFLOWcellE#1\stopFLOWcell
- {\resetFLOWcell
- \ignorespaces#1\unskip
- \let\doprocessFLOWcell\doprocessFLOWcellE
- \expandafter\doprocessFLOWcell\FLOWlocation\end}
-
-\def\doprocessFLOWcellE#1,#2\end % redundant
- {\ifx\FLOWoverlay\empty \else
- \dophaseoneFLOWcellX{#1}{#2}%
- \ifdone
- \dophasetwoFLOWcellX
- \edef\FLOWdx{\the\dimen0}%
- \edef\FLOWdy{\the\dimen2}%
- \setbox0\hbox
- {\framed
- [%\c!frame=\v!off,
- \c!background={\@@FLOWbackground,\FLOWoverlay},
- \c!backgroundcolor=\@@FLOSbackgroundcolor,
- \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
- {}}%
- \positionFLOWzero
- \fi
- \fi}
-
-% Pass F
-
-\def\checkFLOWautofocus
- {\def\@@FLOWminx{100}\let\@@FLOWminy\@@FLOWminx
- \def\@@FLOWmaxx {0}\let\@@FLOWmaxy\@@FLOWmaxx
- \def\@@FLOWabsx {0}\let\@@FLOWabsy\@@FLOWabsx
- \let\startFLOWcell\startFLOWcellF
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber
- %\message{AUTOSHAPE 1: (\@@FLOWminx,\@@FLOWminy)->(\@@FLOWmaxx,\@@FLOWmaxy)}%
- \ifnum\@@FLOWabsx<\@@FLOWmaxx\let\@@FLOWmaxx\@@FLOWabsx\fi
- \ifnum\@@FLOWabsy<\@@FLOWmaxy\let\@@FLOWmaxy\@@FLOWabsy\fi
- %\message{AUTOSHAPE 2: (\@@FLOWminx,\@@FLOWminy)->(\@@FLOWmaxx,\@@FLOWmaxy)}%
- \donetrue
- \ifnum\@@FLOWminx=100 \donefalse\fi
- \ifnum\@@FLOWminy=100 \donefalse\fi
- \ifnum\@@FLOWmaxx=0 \donefalse\fi
- \ifnum\@@FLOWmaxy=0 \donefalse\fi
- \doFLOWcheckF\@@FLOWx\@@FLOWminx\@@FLOWmaxx\@@FLOWnx
- \doFLOWcheckF\@@FLOWy\@@FLOWminy\@@FLOWmaxy\@@FLOWny}
-
-\def\startFLOWcellF#1\stopFLOWcell%
- {\resetFLOWcell
- \ignorespaces#1\unskip
- \expandafter\doFLOWlocationF\FLOWlocation\end}%
-
-\def\doFLOWlocationF#1,#2\end%
- {\ifnum#1>\@@FLOWabsx\def\@@FLOWabsx{#1}\fi
- \ifnum#2>\@@FLOWabsy\def\@@FLOWabsy{#2}\fi
- \doifinset\FLOWcell\@@FLOWautofocus
- {\dodoFLOWlocationF{#1}<-\@@FLOWminx
- \dodoFLOWlocationF{#1}>+\@@FLOWmaxx
- \dodoFLOWlocationF{#2}<-\@@FLOWminy
- \dodoFLOWlocationF{#2}>+\@@FLOWmaxy}}
-
-\def\dodoFLOWlocationF#1#2#3#4%
- {\ifnum#1#2#4\relax
- \!!counta=#1\advance\!!counta #31\relax
- \edef#4{\ifnum\!!counta<1 1\else\the\!!counta\fi}%
- \fi}
-
-\def\doFLOWcheckF#1#2#3#4%
- {\ifdone
- \let#1=#2%
- \!!counta=#3%
- \advance\!!counta \plusone\advance\!!counta -#2\relax
- \ifnum\!!counta<1 \!!counta=1 \fi
- \edef#4{\the\!!counta}%
- \else
- \let#1\!!plusone
- \let#4\!!zerocount % no {1}
- \fi}
-
-% \useFLOWchart[name][parent][setting,setting][additional settings]
-% \useFLOWchart[name][parent][additional settings]
-
-\let\currentFLOWchart\empty
-
-\def\useFLOWchart
- {\doquadrupleempty\douseFLOWchart}
-
-\def\douseFLOWchart[#1][#2][#3][#4]% name parent sets mainsettings
- {\iffourthargument
- \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][#3][#4,##1]}%
- \else
- \checkparameters[#3]%
- \ifparameters
- \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][][#3,##1]}%
- \else
- \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][#3][##1]}%
- \fi
- \fi}
-
-\def\setgetFLOWchart[#1][#2][#3]%
- {\def\docommand##1{}% cell line focus ?
- \processcommalist[#2]\docommand
- \getFLOWchart[#1][#3]}
-
-\def\doFLOWchart[#1][#2]%
- {\hbox\bgroup\vbox\bgroup % vmode suppresses spaces
-\def\currentFLOWchart{#1}%
- \doifundefinedelse{\@FLOW@--#1}
- {\getFLOWchart[#1][#2]}
- {\getvalue{\@FLOW@--#1}[#2]}%
- \egroup\egroup}
-
-\def\FLOWchart%
- {\dodoubleempty\doFLOWchart}
-
-%D A hook into the help system.
-
-% \def\showFLOWhelp#1%
-% {\doifhelpinfo\FLOWhelp
-% {\setbox#1=\hbox
-% {\setbox\scratchbox=\hbox{\lower\@@FLOWdy\hbox
-% {\helpbutton
-% [\c!width=\wd0,\c!color=,\c!height=\@@FLOWdy,\c!frame=\v!no]%
-% [\FLOWhelp]}}%
-% \smashbox\scratchbox
-% \setbox#1=\vbox
-% {\forgetall\offinterlineskip\box#1\box\scratchbox}%
-% \box#1}}}
-
-\def\showFLOWhelp#1%
- {}
-
-%D The next section is dedicated to splitting up charts.
-
-\def\getFLOWsize[#1]%
- {\bgroup\let\dodogetFLOWchart\dogetFLOWsize\FLOWchart[#1]\egroup}
-
-\def\dogetFLOWsize[#1][#2]%
- {\setbox\scratchbox=\vbox
- {\globallet\FLOWmaxwidth \!!zerocount
- \globallet\FLOWmaxheight\!!zerocount
- \def\getFLOWlocation##1,##2\end
- {\ifnum0##1>\FLOWmaxwidth \xdef\FLOWmaxwidth {##1}\fi
- \ifnum0##2>\FLOWmaxheight\xdef\FLOWmaxheight{##2}\fi}%
- \resetFLOWcell
- \long\def\startFLOWcell##1\stopFLOWcell
- {{##1\expandafter\getFLOWlocation\FLOWlocation\end}}%
- \def\dohandleflowchart[##1][##2]%
- {\resetFLOWlocation
- \processFLOWbuffer{##1}}%
- \getvalue{\@FLOW@-#1}}}
-
-\def\setupFLOWsplit%
- {\dodoubleargument\getparameters[\@@FLOT]}
-
-\setupFLOWsplit%
- [\c!nx=3,\c!ny=3,
- \c!dx=1,\c!dy=1,
- \c!command=,
- \c!marking=\v!on,
- \c!before=,\c!after=]
-
-\def\FLOWsplitx {1}
-\def\FLOWsplity {1}
-\def\FLOWsplitnx{1}
-\def\FLOWsplitny{1}
-
-\def\FLOWcharts%
- {\dodoubleempty\doFLOWcharts}
-
-%D While splitting, the following variables are available:
-%D
-%D \starttyping
-%D \FLOWsplitnx \FLOWsplitny \FLOWsplitx \FLOWsplity
-%D \stoptyping
-
-\def\doFLOWcharts[#1][#2]%
- {\bgroup
- \getFLOWsize[#1]%
- \dodoFLOWcharts\relax
- \global\let\FLOWsplitnx\FLOWsplitx
- \global\let\FLOWsplitny\FLOWsplity
- \dodoFLOWcharts{\dododoFLOWcharts[#1][#2]}%
- \egroup}
-
-\def\dodoFLOWcharts#1%
- {\def\@@FLOTx{1}%
- \global\let\FLOWsplitx\@@FLOTx
- \doloop
- {\def\@@FLOTy{1}%
- \global\let\FLOWsplity\@@FLOTy
- \doloop
- {\bgroup
- \scratchcounter\FLOWmaxwidth
- \advance\scratchcounter -\@@FLOTx
- \advance\scratchcounter \plusone
- \ifnum\scratchcounter<\@@FLOTnx\edef\@@FLOTnx{\the\scratchcounter}\fi
- \scratchcounter\FLOWmaxheight
- \advance\scratchcounter -\@@FLOTy
- \advance\scratchcounter \plusone
- \ifnum\scratchcounter<\@@FLOTny\edef\@@FLOTny{\the\scratchcounter}\fi
- #1% does something with the float, or not
- \egroup
- \increment(\@@FLOTy,\@@FLOTny)%
- \ifnum\@@FLOTy>\FLOWmaxheight
- \exitloop
- \else
- \doglobal\increment\FLOWsplity
- \decrement(\@@FLOTy,\@@FLOTdy)%
- \fi}%
- \increment(\@@FLOTx,\@@FLOTnx)%
- \ifnum\@@FLOTx>\FLOWmaxwidth
- \exitloop
- \else
- \doglobal\increment\FLOWsplitx
- \decrement(\@@FLOTx,\@@FLOTdx)%
- \fi}}
-
-\def\dododoFLOWcharts[#1][#2]%
- {\bgroup
- \@@FLOTbefore
- \doifnot\@@FLOTmarking\v!on{\let\cuthbox\hbox}%
- \cuthbox
- {\@@FLOTcommand
- {\FLOWchart[#1][#2,
- \c!x=\@@FLOTx,\c!nx=\@@FLOTnx,
- \c!y=\@@FLOTy,\c!ny=\@@FLOTny]}}%
- \@@FLOTafter
- \egroup}
-
-%D An example of splitting is given below:
-%D
-%D \starttyping
-%D \setupFLOWsplit
-%D [nx=5,ny=10,
-%D dx=0,dy=0,
-%D before=,
-%D after=\page]
-%D
-%D \FLOWcharts[mybigflow]
-%D \stoptyping
-%D
-%D Or, one can say:
-%D
-%D \starttyping
-%D \splitfloat
-%D {\placefigure{What a big flowchart this is!}}
-%D {\FLOWcharts[mybigflow]}
-%D \stoptyping
-
-%D \macros
-%D {typeFLOWchart}
-%D
-%D For documentation purposes the following macro is
-%D provided. Watch the use of the first and last line hooks,
-%D which is needed because the start and stop commands are
-%D not part of the buffer.
-
-\def\typeFLOWchart[#1]%
- {\bgroup
- \def\dohandleflowchart[##1][##2]{\typeFLOWbuffer{##1}}%
- \defconvertedargument\firstverbatimfileline{\startFLOWchart[#1]}%
- \defconvertedargument\lastverbatimfileline {\stopFLOWchart}%
- \getvalue{\@FLOW@-#1}
- \egroup}
-
-%D New:
-%D
-%D \starttyping
-%D \setupFLOWcharts[command=\Whow]
-%D
-%D \startFLOWset[convert-en] % [tag][convert-en]
-%D \subFLOWchart[a][x=1,y=1,nx=3,ny=3]
-%D \subFLOWchart[b][x=1,y=2,nx=3,ny=3]
-%D \subFLOWchart[c][x=2,y=1,nx=3,ny=3]
-%D \stopFLOWset
-%D
-%D \def\Whow#1%
-%D {\ifnum\currentFLOWset=1 \framed{Some Chart}\fi}
-%D
-%D \FLOWset[convert-en] % [tag]
-%D
-%D \def\Whow#1%
-%D {\setuphead[state=high]
-%D \startstandardmakeup
-%D \centerbox{#1}
-%D \stopstandardmakeup}
-%D
-%D \FLOWset[convert-en] % [tag]
-%D \stoptyping
-
-\def\startFLOWset
- {\dodoubleempty\dostartFLOWset}
-
-\def\dostartFLOWset[#1][#2]#3\stopFLOWset % tag name data
- {\ifsecondargument
- \long\setvalue{\@FLOX@#1}{\dohandleFLOWset{#1}{#2}{#3}}%
- \else
- \long\setvalue{\@FLOX@#1}{\dohandleFLOWset{#1}{#1}{#3}}%
- \fi}
-
-\long\def\dohandleFLOWset#1#2#3% tag name data
- {\bgroup
- \def\subFLOWchart
- {\dodoubleempty\dosubFLOWchart}%
- \def\dosubFLOWchart[##1][##2]% subtag settings
- {\ifsecondargument
- \dodohandleFLOWset{#1}{##1}{#2}{##2}%
- \else
- \subFLOWchart[][##1]%
- \fi}%
- #3%
- \egroup}
-
-\def\dodohandleFLOWset#1#2#3#4% tag subtag name settings
- {\increment\currentFLOWset
- \bgroup
- \@@FLOXcommand
- {\ifnum\currentFLOWset=1 \pagereference[#1]\fi
- \doifsomething{#2}
- {\setupreferencing[\c!prefix=]%
- \pagereference[#1:#2]% -:#1:#2
- \setupreferencing[\c!prefix=#1:#2]}%
- \FLOWchart[#3][#4]}%
- \egroup}
-
-\def\FLOWset[#1]%
- {\newcounter\currentFLOWset
- \doifdefinedelse{\@FLOX@#1}
- {\getvalue{\@FLOX@#1}}
- {\dodohandleFLOWset{#1}{}{#1}{}}}
-
-\newcounter\currentFLOWset
-
-\setupFLOWsets
- [\c!command=]
-
-%D This will be an option:
-
-% \def\startFLOWchart%
-% {\dodoubleempty\dostartFLOWchart}
-%
-% \long\def\dostartFLOWchart[#1][#2]#3\stopFLOWchart
-% {\preparenextFLOWchart{#1}{#2}%
-% \long\setgvalue{\FLOWbufferprefix\nofFLOWcharts}{#3}}
-%
-% \long\def\dodefineFLOWchart[#1][#2]#3%
-% {\preparenextFLOWchart{#1}{#2}%
-% \long\setgvalue{\FLOWbufferprefix\nofFLOWcharts}{#3}}
-%
-% \def\processFLOWbuffer#1{\getvalue{\FLOWbufferprefix#1}}
-% \def\typeFLOWbuffer #1{[Sorry, no verbatim chart #1 available.]}
-% todo: \localpushmacro/\localpopmacro (dohandleflowchart etc)
-% todo: make mkiv variant
-% todo: use dimexpr/numspr
-
-% will be redone with layers and dimexpr or even better, by just using
-% textext .. a nice example of old code
-
-%D This is an experimental module. Pieces of code will be moved
-%D to other modules. More features are possible but will be
-%D interfaces later.
-%D
-%D When finished this module will be documented. The main macro
-%D is still a rather big one and there is some redundant and
-%D slow code that needs a clean up.
-
-% arrow, dash
-% crossing
-% \goto -> \normalgoto
-% class -> class:name (ref prefix)
-% c, automatisch geen overlap zoeken
-% eind eerder chart connecties
-% relateren aan korps
-% check op bestaan naam, bestaan shape
-% auto als extern figuur
-% subchart
-% pijlen
-% focus
-% ook nog \MPmessage
-% areapath -> krappe vlak
-% clippath -> gehele vlak
-%
-% offset : clip offset
-% breedte : breedte cel
-% hoogte : hoogte cel
-% dx : halve afstand in breedte (grid breedte = breedte + 2dx)
-% dy : halve afstand in hoogte (grid hoogte = hoogte + 2dy)
-% x : x offset (clipping)
-% y : y offset (clipping)
-% nx : minimaal aantal cellen horizontaal
-% ny : minimaal aantal cellen vertikaal
-%
-% shape none en geen equivalent maken
-%
-% kaderkleur achtergrondkleur
-% lijnkleur lijndikte
-% focus focuskaderkleur focusachtergrondkleur
-% richting
-%
-% focus koppelen aan kleur
-
-\unprotect
-
-\definesorting [flowchart] [flowcharts] [\v!none] % no access
-\setupsorting [flowchart] [\c!state=\v!stop] % off by default
-
-\def\@FLOW@{@FLOW@}
-\def\@FLOC@{@FLOC@}
-\def\@FLOX@{@FLOX@}
-
-\def\@@FLOW{@@FLOW}
-\def\@@FLOL{@@FLOL}
-\def\@@FLOS{@@FLOS}
-\def\@@FLOF{@@FLOF}
-\def\@@FLOT{@@FLOT}
-\def\@@FLOX{@@FLOX}
-
-\def\@@MPx {@@MPx}
-\def\@@MPy {@@MPy}
-
-\def\FLOWbufferprefix{flw-}
-
-\def\processFLOWbuffer#1{\getbuffer[\FLOWbufferprefix#1]}
-\def\typeFLOWbuffer #1{\typebuffer[\FLOWbufferprefix#1]}
-
-\def\setFLOWname#1#2% funny hack that makes sure that we get
- {\bgroup % names that are acceptable for METAPOST
- \lccode`0=`a\lccode`1=`b\lccode`2=`c\lccode`3=`d\lccode`4=`e%
- \lccode`5=`f\lccode`6=`g\lccode`7=`h\lccode`8=`i\lccode`9=`j%
- \lccode` =`\_\lccode`-=`\_\lccode`_=`\_%
- \lowercase{\gdef#1{#2}}%
- \egroup}
-
-% een gobble als default is sneller, en dan alleen setten als
-% nodig
-
-\def\resetFLOWcell
- {% variables
- \global\let\FLOWname \empty
- \global\let\FLOWalign \empty
- \global\let\FLOWshape \empty
- \global\let\FLOWlocation \empty
- \global\let\FLOWtext \empty
- \global\let\FLOWhelp \empty
- \global\let\FLOWdestination\empty
- \global\let\FLOWoverlay \empty
- \global\let\FLOWfocus \empty
- \global\let\tFLOWlabel \empty
- \global\let\bFLOWlabel \empty
- \global\let\lFLOWlabel \empty
- \global\let\rFLOWlabel \empty
- \global\let\bcFLOWlabel \empty
- \global\let\tcFLOWlabel \empty
- \global\let\lcFLOWlabel \empty
- \global\let\rcFLOWlabel \empty
- \global\let\tFLOWexit \empty
- \global\let\bFLOWexit \empty
- \global\let\lFLOWexit \empty
- \global\let\rFLOWexit \empty
- % commands
- \let\name \doFLOWname
- \let\shape \doFLOWshape
- \let\destination\doFLOWdestination
- \let\location \doFLOWlocation
- \let\focus \doFLOWfocus
- \let\overlay \doFLOWoverlay
- \let\figure \doFLOWfigure
- \let\text \doFLOWtext
- \let\comment \doFLOWcomment
- \let\label \doFLOWlabel
- \let\help \doFLOWhelp
- \let\connection \doFLOWconnection
- \let\exit \doFLOWexit
- % convenience commands
- \let\locate \doFLOWlocate
- \let\connect \doFLOWconnect}
-
-\let\FLOWcell \s!unknown
-\let\FLOWshape \s!unknown
-\let\FLOWdestination\s!unknown
-\let\FLOWfocus \s!unknown
-\let\FLOWoverlay \empty
-\let\FLOWtext \empty
-
-\def\doFLOWname#1%
- {\def\FLOWcell{#1}\setFLOWname\FLOWname{name_#1}\ignorespaces}
-
-\def\doFLOWshape#1%
- {\gdef\FLOWshape{#1}\ignorespaces}
-
-\def\doFLOWdestination#1%
- {\gdef\FLOWdestination{#1}\ignorespaces}
-
-\def\doFLOWlocation#1%
- {\setFLOWlocation#1\end\ignorespaces}
-
-\def\doFLOWfocus#1%
- {\gdef\FLOWfocus{#1}\ignorespaces}
-
-\def\doFLOWoverlay#1%
- {\gdef\FLOWoverlay{#1}\ignorespaces}
-
-\def\doFLOWfigure#1%
- {\defineoverlay[\s!dummy][\overlayfigure{#1}]%
- \overlay\s!dummy}
-
-\def\doFLOWtext
- {\dosingleempty\dodoFLOWtext}
-
-\def\dodoFLOWtext[#1]% % #2%
- {\gdef\FLOWalign{#1}\gdef\FLOWtext}% {#2}}
-
-\def\doFLOWcomment[#1]#2%
- {\ignorespaces\dogobblesingleempty}
-
-\def\doFLOWlabel[#1]#2% wordt dit gebruikt ?
- {\setgvalue{#1FLOWlabel}{#2}\ignorespaces}
-
-\def\doFLOWhelp#1%
- {\gdef\FLOWhelp{#1}\ignorespaces}
-
-\def\doFLOWconnection
- {\dodoubleempty\dodoFLOWconnection}
-
-\def\dodoFLOWconnection[#1][#2]#3%
- {\ignorespaces}
-
-\def\doFLOWconnect
- {\connection}
-
-\def\doFLOWlocate
- {\location}
-
-\def\doFLOWexit[#1]#2%
- {\setgvalue{#1FLOWexit}{#2}\ignorespaces}
-
-\def\startFLOWchart
- {\bgroup
- \let\stopFLOWchart\egroup
- \obeylines % lelijk, buffers nog eens fatsoeneren
- \dodoubleempty\dostartFLOWchart}
-
-\def\dostartFLOWchart[#1][#2]%
- {\preparenextFLOWchart{#1}{#2}%
- \dostartbuffer[\FLOWbufferprefix\nofFLOWcharts][startFLOWchart][stopFLOWchart]}
-
-\def\defineFLOWchart%
- {\dodoubleempty\dodefineFLOWchart}
-
-\long\def\dodefineFLOWchart[#1][#2]#3%
- {\preparenextFLOWchart{#1}{#2}%
- \setbuffer[\FLOWbufferprefix\nofFLOWcharts]#3\endbuffer}
-
-\def\preparenextFLOWchart#1#2%
- {\doglobal\increment\nofFLOWcharts
- \flowchart{#1}%
- \setxvalue{\@FLOW@-#1}{\noexpand\dohandleflowchart[\nofFLOWcharts][#2]}}
-
-\def\setupFLOWcharts{\dodoubleargument\getparameters[\@@FLOW]}
-\def\setupFLOWlines {\dodoubleargument\getparameters[\@@FLOL]}
-\def\setupFLOWshapes{\dodoubleargument\getparameters[\@@FLOS]}
-\def\setupFLOWfocus {\dodoubleargument\getparameters[\@@FLOF]}
-\def\setupFLOWsets {\dodoubleargument\getparameters[\@@FLOX]}
-
-\setupFLOWcharts
- [\c!option=,
- \c!bodyfont=,
- \c!dot=, % private option
- \c!width=12\bodyfontsize,
- \c!height=7\bodyfontsize,
- \c!maxwidth=,
- \c!maxheight=,
- \c!offset=\v!standard, % == auto offset
- \c!dx=2\bodyfontsize,
- \c!dy=2\bodyfontsize,
- \c!nx=0, % 1,
- \c!ny=0, % 1,
- \c!x=1,
- \c!y=1,
- \c!autofocus=,
- \c!focus=,
- \c!background=, % \v!color,
- \c!backgroundcolor=\s!white,
- \c!rulethickness=\linewidth,
- \c!frame=\v!off,
- \c!framecolor=]
-
-\setupFLOWlines
- [\c!corner=\v!round,
- \c!arrow=\v!yes,
- \c!dash=\v!no,
- \c!radius=.375\bodyfontsize, % 2.5\c!rulethickness
- \c!color=FLOWlinecolor,
- \c!rulethickness=.15\bodyfontsize, % 2pt,
- \c!offset=\v!none]
-
-\setupFLOWshapes
- [\c!default=action,
- \c!framecolor=FLOWframecolor,
- \c!background=\v!color,
- \c!backgroundcolor=FLOWbackgroundcolor,
- \c!backgroundscreen=\@@rsscreen,
- \c!rulethickness=.15\bodyfontsize, % 2pt,
- \c!offset=.5\bodyfontsize]
-
-\setupFLOWfocus
- [\c!framecolor=FLOWfocuscolor,
- \c!background=\@@FLOSbackground,
- \c!backgroundcolor=\@@FLOSbackgroundcolor,
- \c!backgroundscreen=\@@FLOSbackgroundscreen,
- \c!rulethickness=\@@FLOSrulethickness,
- \c!offset=\@@FLOSoffset]
-
-\definecolor [FLOWfocuscolor] [s=.2]
-\definecolor [FLOWlinecolor] [s=.5]
-\definecolor [FLOWframecolor] [s=.7]
-\definecolor [FLOWbackgroundcolor] [s=.9]
-
-\newcounter\includeFLOWx
-\newcounter\includeFLOWy
-
-\def\includeFLOWchart
- {\dodoubleempty\doincludeFLOWchart}
-
-\def\doincludeFLOWchart[#1][#2]%
- {\pushmacro\includeFLOWx
- \pushmacro\includeFLOWy
- \getparameters[FLOWi][x=1,y=1,#2]%
- \increment(\includeFLOWx,0\FLOWix)\decrement\includeFLOWx
- \increment(\includeFLOWy,0\FLOWiy)\decrement\includeFLOWy
- \def\dodoincludeFLOWchart##1%
- {\doifdefined{\@FLOW@-##1}
- {\globalpushmacro\dohandleflowchart % was local
- \gdef\dohandleflowchart[####1][####2]%
- {\globalpopmacro\dohandleflowchart % was local
- \resetFLOWlocation
- \processFLOWbuffer{####1}}%
- \getvalue{\@FLOW@-##1}}}%
- \processcommalist[#1]\dodoincludeFLOWchart
- \popmacro\includeFLOWx
- \popmacro\includeFLOWy}
-
-\def\resetFLOWlocation
- {\globallet\lastFLOWx\!!zerocount
- \globallet\lastFLOWy\!!zerocount}
-
-\def\dosetFLOWlocation[#1#2]#3#4%
- {\processaction
- [#1#2]
- [ +=>\scratchcounter\numexpr#4+ 1+#3\relax,
- -=>\scratchcounter\numexpr#4- 1+#3\relax,
- +#2=>\scratchcounter\numexpr#4+#2+#3\relax,
- -#2=>\scratchcounter\numexpr#4-#2+#3\relax,
- \s!default=>\scratchcounter\numexpr#4 +#3\relax,
- \s!unknown=>\scratchcounter\numexpr0#1#2+#3\relax]%
- \xdef#4{\the\scratchcounter}}
-
-\def\setFLOWlocation#1,#2\end
- {\dosetFLOWlocation[#1\empty]\includeFLOWx\lastFLOWx
- \dosetFLOWlocation[#2\empty]\includeFLOWy\lastFLOWy
- \xdef\FLOWlocation{\lastFLOWx,\lastFLOWy}}
-
-\def\FLOWshapes
- {node, action, procedure, product, decision, archive,
- loop, wait, subprocedure, singledocument, multidocument,
- sub procedure, single document, multi document, up, down,
- left, right}
-
-\def\FLOWlines
- {up, down, left, right}
-
-\def\FLOWsetconnect#1%
- {\donefalse
- \let\cFLOWfrom\empty
- \let\cFLOWto\empty
- \let\zFLOWfrom\!!zerocount
- \let\zFLOWto\!!zerocount
- \handletokens#1\with\doFLOWsetconnect
- \ifx\cFLOWto\empty\let\cFLOWfrom\empty\fi}
-
-\def\doFLOWsetconnect#1%
- {\ifx #1p%
- \ifdone\def\zFLOWto{+1}\else\def\zFLOWfrom{+1}\fi
- \else\ifx#1+%
- \ifdone\def\zFLOWto{+1}\else\def\zFLOWfrom{+1}\fi
- \else\ifx#1n%
- \ifdone\def\zFLOWto{-1}\else\def\zFLOWfrom{-1}\fi
- \else\ifx#1-%
- \ifdone\def\zFLOWto{-1}\else\def\zFLOWfrom{-1}\fi
- \else\ifdone
- \edef\cFLOWto{\FLOWconnector#1}%
- \else
- \edef\cFLOWfrom{\FLOWconnector#1}%
- \donetrue
- \fi\fi\fi\fi\fi}
-
-\def\FLOWconnector#1%
- {\if#1bbottom\else\if#1ttop\else\if#1lleft\else\if#1rright\fi\fi\fi\fi}
-
-\newif\ifFLOWscaling \FLOWscalingtrue
-
-\def\@@FLOW@@offset{\@@FLOWoffset}
-
-\def\getFLOWchart
- {\dodoubleempty\dogetFLOWchart}
-
-\def\dogetFLOWchart[#1][#2]%
- {\doifundefinedelse{\@FLOW@-#1}
- {\writestatus{FLOW}{unknown chart #1}%
- \framed
- [\c!width=12\bodyfontsize,\c!height=8\bodyfontsize]
- {\tttf [chart #1]}}
- {\dodogetFLOWchart[#1][#2]}}
-
-\def\dodogetFLOWchart[#1][#2]% to be split a bit more
- {\vbox\bgroup
- \insidefloattrue
- \forgetall
- \dontcomplain
- % \offinterlineskip % we now explicitly use \nointerlineskip later on
- \def\dohandleflowchart[##1][##2]%
- {\def\currentFLOWnumber{##1}%
- \getparameters[\@@FLOW][##2]}%
- \getvalue{\@FLOW@-#1}%
- \getparameters[\@@FLOW][#2]% dubbelop ?
- \doifsomething{\@@FLOWautofocus}
- {\checkFLOWautofocus}%
- %\message{AUTOSHAPE 3: (\@@FLOWx,\@@FLOWy)->(\@@FLOWnx,\@@FLOWny)}\wait
- \global\let\FLOWwidth \@@FLOWnx
- \global\let\FLOWheight\@@FLOWny
- \let\startFLOWcell\startFLOWcellA
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber
- \ifcase\@@FLOWnx\relax \let\@@FLOWnx\FLOWwidth \fi
- \ifcase\@@FLOWny\relax \let\@@FLOWny\FLOWheight \fi
- \doifnothing{\@@FLOWmaxwidth\@@FLOWmaxheight}{\FLOWscalingfalse}%
- \ifFLOWscaling
- \doifnothing{\@@FLOWmaxwidth }{\let\@@FLOWmaxwidth \maxdimen}%
- \doifnothing{\@@FLOWmaxheight}{\let\@@FLOWmaxheight\maxdimen}%
- \scratchcounter\bodyfontpoints
- \doloop % NOG FONTSWITCH OM EX EN EM TE LATEN WERKEN
- {\ifnum\scratchcounter>1 % NU DIMENSIONS IN TERMS OF BODYFONTSIZE
- \bodyfontsize=\the\scratchcounter pt
- \dimen0=\@@FLOWmaxwidth
- \dimen2=\@@FLOWwidth
- \dimen4=\@@FLOWdx
- \advance\dimen2 2\dimen4
- \dimen2=\@@FLOWnx\dimen2
- \advance\dimen2 2\dimen4
- \ifdim\dimen2>\dimen0
- \advance\scratchcounter \minusone
- \else
- \dimen0=\@@FLOWmaxheight
- \dimen2=\@@FLOWheight
- \dimen4=\@@FLOWdy
- \advance\dimen2 2\dimen4
- \dimen2=\@@FLOWny\dimen2
- \advance\dimen2 2\dimen4
- \ifdim\dimen2>\dimen0
- \advance\scratchcounter \minusone
- \else
- \exitloop
- \fi
- \fi
- \else
- \exitloop
- \fi}%
- \expanded{\switchtobodyfont[\the\scratchcounter pt]}%
- \forgetall
- % \offinterlineskip % needed ?
- \else\ifx\@@FLOWbodyfont\empty\else
- \expanded{\switchtobodyfont[\@@FLOWbodyfont]}% \expanded ?
- \fi\fi
- \global\let\FLOWcells\empty
- \dimen0=\@@FLOWwidth
- \edef\FLOWshapewidth{\the\dimen0}%
- \dimen2=\@@FLOWdx
- \advance\dimen0 2\dimen2
- \edef\FLOWgridwidth{\the\dimen0}%
- \dimen0=\@@FLOWheight
- \edef\FLOWshapeheight{\the\dimen0}%
- \dimen2=\@@FLOWdy
- \advance\dimen0 2\dimen2
- \edef\FLOWgridheight{\the\dimen0}%
- \scratchdimen=\@@FLOSrulethickness
- \edef\@@FLOSrulethickness{\the\scratchdimen}%
- \scratchdimen=\@@FLOFrulethickness
- \edef\@@FLOFrulethickness{\the\scratchdimen}%
- \scratchdimen=\@@FLOLrulethickness
- \edef\@@FLOLrulethickness{\the\scratchdimen}%
- \ifdim\@@FLOLradius<2.5\scratchdimen
- \scratchdimen=2.5\scratchdimen
- \edef\@@FLOLradius{\the\scratchdimen}%
- \ifdim\@@FLOLradius>\@@FLOWdx
- \scratchdimen=\@@FLOWdx
- \edef\@@FLOLradius{\the\scratchdimen}%
- \fi
- \ifdim\@@FLOLradius>\@@FLOWdy
- \scratchdimen=\@@FLOWdy
- \edef\@@FLOLradius{\the\scratchdimen}%
- \fi
- \else
- \scratchdimen=\@@FLOLradius
- \edef\@@FLOLradius{\the\scratchdimen}%
- \fi
- \processaction % magic 2.5
- [\@@FLOWoffset]
- [ \v!none=>\scratchdimen=-2.5\scratchdimen,
- \v!overlay=>\scratchdimen=-2.5\scratchdimen,
- \v!standard=>\scratchdimen=\scratchdimen,
- \s!unknown=>\scratchdimen=\@@FLOWoffset,
- \s!default=>\scratchdimen=-2.5\scratchdimen]%
- \edef\@@FLOW@@offset{\the\scratchdimen}%
- \forgetall
- \offinterlineskip
- \resetMPdrawing
- \doglobal\newcounter\FLOWcomment
- \startMPdrawing
- if unknown context_char : input mp-char.mp ; fi ;
- grid_width := \FLOWgridwidth ;
- grid_height := \FLOWgridheight ;
- shape_width := \FLOWshapewidth ;
- shape_height := \FLOWshapeheight ;
- connection_line_width := \@@FLOLrulethickness ;
- connection_smooth_size := \@@FLOLradius ;
- connection_arrow_size := \@@FLOLradius ;
- connection_dash_size := \@@FLOLradius ;
- currentpicture := nullpicture ;
- begin_chart(0,\FLOWwidth,\FLOWheight);
- reverse_y := true ;
- chart_offset := \@@FLOW@@offset ;
- \stopMPdrawing
- \doifelsenothing\@@FLOWbackgroundcolor
- {\startMPdrawing
- chart_background_color := white ;
- \stopMPdrawing}
- {\startMPdrawing
- chart_background_color := \MPcolor{\@@FLOWbackgroundcolor} ;
- \stopMPdrawing}%
- \doif\@@FLOWoption\v!test
- {\startMPdrawing
- show_con_points := true ;
- show_mid_points := true ;
- show_all_points := true ;
- \stopMPdrawing}%
- \processaction % private
- [\@@FLOWdot]
- [ \v!yes=>\startMPdrawing
- show_con_points := true ;
- show_mid_points := true ;
- show_all_points := true ;
- \stopMPdrawing,
- \s!unknown=>\startMPdrawing
- show_\@@FLOWdot _points := true ;
- \stopMPdrawing]%
-\doglobal\newcounter\FLOWcomment
- \let\startFLOWcell\startFLOWcellB
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber
-\doglobal\newcounter\FLOWcomment
- \let\startFLOWcell\startFLOWcellC
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber
- \startMPdrawing
- clip_chart(\@@FLOWx,\@@FLOWy,\@@FLOWnx,\@@FLOWny) ;
- end_chart ;
- \stopMPdrawing
- \MPdrawingdonetrue
- \setbox0\hbox
- {\MPstaticgraphictrue
- \MPshiftdrawingfalse
- \getMPdrawing}%
- \def\MPmessage##1%
- {\writestatus{MP charts}{##1}}%
- \def\MPposition##1##2##3%
- {\setvalue{\@@MPx##1}{##2}\setvalue{\@@MPy##1}{##3}}%
- \def\MPclippath##1##2##3##4%
- {\def\clipMPllx{##1bp}\def\clipMPlly{##2bp}%
- \def\clipMPurx{##3bp}\def\clipMPury{##4bp}}%
- \def\MPareapath##1##2##3##4%
- {\def\areaMPllx{##1bp}\def\areaMPlly{##2bp}%
- \def\areaMPurx{##3bp}\def\areaMPury{##4bp}}%
- \getMPdata
- \doglobal\newcounter\FLOWcomment
- \let\startFLOWcell\startFLOWcellD
- \setbox2\vbox to \ht0
- {\forgetall % \offinterlineskip
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber\vss}%
- \setbox2\hbox
- {\hskip\@@FLOW@@offset\lower\@@FLOW@@offset\box2}%
- \wd2\wd0\ht2\ht0\dp2\dp0
- \let\startFLOWcell\startFLOWcellE
- \setbox4\vbox to \ht0
- {\forgetall % \offinterlineskip
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber\vss}%
- \setbox4\hbox
- {\hskip\@@FLOW@@offset\lower\@@FLOW@@offset\box4}%
- \wd4\wd0\ht4\ht0\dp4\dp0
- \doifelse\@@FLOWoption\v!test
- {\setbox6\vbox
- {\forgetall
- \vskip\@@FLOW@@offset
- \hskip\@@FLOW@@offset
- \basegrid
- [\c!x=\@@FLOWx,\c!nx=\@@FLOWnx,\c!dx=\withoutpt\FLOWgridwidth,
- \c!y=\@@FLOWy,\c!ny=\@@FLOWny,\c!dy=\withoutpt\FLOWgridheight,
- \c!xstep=1,\c!ystep=1,
- \c!unit=pt,\c!location=\v!middle]}%
- \wd6\wd0\ht6\ht0\dp6\dp0
- \setbox8\vbox
- {\forgetall
- \offinterlineskip
- \vskip\@@FLOW@@offset
- \dostepwiserecurse\@@FLOWy\@@FLOWny\plusone
- {\vbox to \FLOWgridheight
- {\vfill
- \hskip\@@FLOW@@offset
- \hbox
- {\dostepwiserecurse\@@FLOWx\@@FLOWnx\plusone
- {\hbox to \FLOWgridwidth
- {\hfill
- \framed
- [\c!framecolor=red,
- \c!width=\FLOWshapewidth,
- \c!height=\FLOWshapeheight]
- {}%
- \hfill}}}
- \vfill}}}%
- \wd8\wd0\ht8\ht0\dp8\dp0
- \framed
- [\c!offset=\v!overlay,\c!framecolor=green]
- {\hbox{\box4\hskip-\wd0\box0\hskip-\wd2\box2\hskip-\wd6\box6\hskip-\wd8\box8}}}
- {\framed
- [\c!offset=\v!overlay,
- \c!frame=\@@FLOWframe,
- \c!rulethickness=\@@FLOWrulethickness,
- \c!framecolor=\@@FLOWframecolor,
- \c!background=\@@FLOWbackground,
- \c!backgroundcolor=\@@FLOWbackgroundcolor]
- {\hbox{\box4\hskip-\wd0\box0\hskip-\wd2\box2}}}%
- %\message{[\FLOWcells]}\wait
- \egroup}
-
-% Pass A
-
-\long\def\startFLOWcellA#1\stopFLOWcell%
- {\resetFLOWcell
- \ignorespaces#1\unskip
- \expandafter\getFLOWlocationA\FLOWlocation\end
- \ignorespaces}
-
-\def\getFLOWlocationA#1,#2\end
- {\ifnum0#1>\FLOWwidth \xdef\FLOWwidth {#1}\fi
- \ifnum0#2>\FLOWheight\xdef\FLOWheight{#2}\fi}
-
-% Pass B
-%
-% beware: the - after \@FLOC@ is needed since name can be
-% empty and we don't want to redefine \@FLOC@ itself by
-% mistake
-
-\long\def\startFLOWcellB#1\stopFLOWcell
- {\resetFLOWcell\ignorespaces#1\unskip
- \setxvalue{\@FLOC@-\FLOWname}{\FLOWlocation}% kost veel cs's
- \ifx\FLOWshape\empty
- \global\let\FLOWshape\@@FLOSdefault
- \fi
- \doifnot\FLOWshape{none} % {\v!none}
- {\doifinsetelse\FLOWshape\FLOWshapes
- {\edef\FLOWshapetag{shape_\FLOWshape}% beter \expanded
- \@EA\setFLOWname\@EA\FLOWshapetag\@EA{\FLOWshapetag}}
- {\doifnumberelse\FLOWshape
- {\let\FLOWshapetag\FLOWshape}
- {\let\FLOWshapetag\empty}}%
- \ifx\FLOWshapetag\empty \else
- \doifinsetelse\FLOWshape\FLOWlines
- {\chardef\FLOWstate0 }
- {\doifcommonelse{\FLOWcell,\FLOWfocus}\@@FLOWfocus
- {\chardef\FLOWstate1 }
- {\chardef\FLOWstate2 }}%
- \startMPdrawing
- begin_sub_chart ;
- \ifcase\FLOWstate
- shape_line_color := \MPcolor{\@@FLOLcolor} ;
- shape_fill_color := \MPcolor{\@@FLOLcolor} ;
- shape_line_width := \@@FLOLrulethickness ;
- \or
- shape_line_color := \MPcolor{\@@FLOFframecolor} ;
- shape_fill_color := \MPcolor{\@@FLOFbackgroundcolor} ;
- shape_line_width := \@@FLOFrulethickness ;
- \or
- shape_line_color := \MPcolor{\@@FLOSframecolor} ;
- shape_fill_color := \MPcolor{\@@FLOSbackgroundcolor} ;
- shape_line_width := \@@FLOSrulethickness ;
- \fi
- %\ifx\FLOWoverlay\empty
- % peepshape := false ;
- %\else
- % peepshape := true ;
- %\fi
- peepshape := \ifx\FLOWoverlay\empty false \else true \fi ;
- new_shape(\FLOWlocation,\FLOWshapetag) ;
- end_sub_chart ;
- \stopMPdrawing
- \fi}%
- \ignorespaces}
-
-% Pass C
-
-\long\def\startFLOWcellC#1\stopFLOWcell%
- {\resetFLOWcell
-\pushmacro\lastFLOWx
-\pushmacro\lastFLOWy
- \ignorespaces#1\unskip % makes sure that vars are set
-\popmacro\lastFLOWy
-\popmacro\lastFLOWx
- \let\connection\doFLOWconnectionC
- \ignorespaces#1\unskip}
-
-\def\FLOWorigin{0,0}
-
-\def\doFLOWdisplace[#1,#2,#3]% experiment
- {dsp_x := #1 ; dsp_y := #2 ;}
-
-\def\doFLOWconnectionC
- {\dodoubleempty\dodoFLOWconnectionC}
-
-\def\dodoFLOWconnectionC[#1][#2]#3%
- {\doglobal\increment\FLOWcomment
- \setFLOWname\otherFLOWname{name_#3}%
- \doifdefinedelse{\@FLOC@-\FLOWname}
- {\edef\FLOWfrom{\getvalue{\@FLOC@-\FLOWname}}}
- {\let \FLOWfrom \FLOWorigin}%
- \ifx\FLOWfrom\FLOWorigin \else
- \doifdefinedelse{\@FLOC@-\otherFLOWname}
- {\edef\FLOWto {\getvalue{\@FLOC@-\otherFLOWname}}}
- {\let \FLOWto \FLOWorigin}%
- \ifx\FLOWto\FLOWorigin \else
- \FLOWsetconnect{#1}%
- \ifx\cFLOWfrom\empty \else
- \doifelse\@@FLOLcorner\v!round
- {\startMPdrawing smooth := true ; \stopMPdrawing}
- {\startMPdrawing smooth := false ; \stopMPdrawing}%
- \doifelse\@@FLOLdash\v!yes
- {\startMPdrawing dashline := true ; \stopMPdrawing}
- {\startMPdrawing dashline := false ; \stopMPdrawing}%
- \doifelse\@@FLOLarrow\v!yes
- {\startMPdrawing arrowtip := true ; \stopMPdrawing}
- {\startMPdrawing arrowtip := false ; \stopMPdrawing}%
- \doifelse\@@FLOLoffset\v!none
- {\startMPdrawing touchshape := true ; \stopMPdrawing}
- {\startMPdrawing touchshape := false ; \stopMPdrawing}%
-%\doifsomething{#2}
-% {\startMPdrawing
-% \doFLOWdisplace[0#2,0,0]%
-% \stopMPdrawing}%
- \startMPdrawing
-\doFLOWdisplace[0#2,0,0]%
- connection_line_color := \MPcolor{\@@FLOLcolor} ;
- connection_line_width := \@@FLOLrulethickness ;
- connect_\cFLOWfrom _\cFLOWto (\FLOWfrom,\zFLOWfrom) (\FLOWto,\zFLOWto) ;
-\doFLOWdisplace[0,0,0]%
- \stopMPdrawing
- \fi
- \fi
- \fi
- \ignorespaces}
-
-% Pass D
-
-\long\def\startFLOWcellD#1\stopFLOWcell
- {\resetFLOWcell
-\pushmacro\lastFLOWx
-\pushmacro\lastFLOWy
- \ignorespaces#1\unskip % presets vars
-\popmacro\lastFLOWy
-\popmacro\lastFLOWx
- \let\doprocessFLOWcell\doprocessFLOWcellD
- \expandafter\doprocessFLOWcellD\FLOWlocation\end
- \let\connection\doFLOWconnectionD
- \let\comment\doFLOWcommentD
- \ignorespaces#1\unskip\ignorespaces}
-
-\def\doFLOWconnectionD
- {\dodoubleempty\dodoFLOWconnectionD}
-
-\def\dodoFLOWconnectionD[#1][#2]#3%
- {\doglobal\increment\FLOWcomment
- \ignorespaces}
-
-\def\doFLOWcommentD[#1]#2%
- {\bgroup
- \let\FLOW \middlebox
- \let\FLOWb \bottombox
- \let\FLOWbl\bottomleftbox
- \let\FLOWbr\bottomrightbox
- \let\FLOWt \topbox
- \let\FLOWtl\topleftbox
- \let\FLOWtr\toprightbox
- \let\FLOWl \leftbox
- \let\FLOWlt\lefttopbox
- \let\FLOWlb\leftbottombox
- \let\FLOWr \rightbox
- \let\FLOWrt\righttopbox
- \let\FLOWrb\rightbottombox
- \let\FLOWc \middlebox
-%\ifdefined{FLOW#1}%
- \ifcase0\getvalue{\@@MPx\FLOWcomment}\getvalue{\@@MPy\FLOWcomment}\relax
- \else
- \ifdim\getvalue{\@@MPx\FLOWcomment}\s!bp<\areaMPllx\relax\else
- \ifdim\getvalue{\@@MPx\FLOWcomment}\s!bp>\areaMPurx\relax\else
- \ifdim\getvalue{\@@MPy\FLOWcomment}\s!bp<\areaMPlly\relax\else
- \ifdim\getvalue{\@@MPy\FLOWcomment}\s!bp>\areaMPury\relax\else
- \dimen0=\getvalue{\@@MPx\FLOWcomment}\s!bp
- \advance\dimen0 -\@@FLOW@@offset
- \advance\dimen0 -\clipMPllx
- \dimen2=\clipMPury
- \advance\dimen2 -\@@FLOW@@offset
- \advance\dimen2 -\getvalue{\@@MPy\FLOWcomment}\s!bp
- \setbox\scratchbox\hbox{\strut#2}%
- \boxoffset.5\bodyfontsize
- \setbox\scratchbox\hbox{\hskip\dimen0\lower\dimen2\getvalue{FLOW#1}{\box\scratchbox}}%
- \smashbox\scratchbox
- \box\scratchbox
- \boxoffset\zeropoint
- \nointerlineskip % really needed
- \fi
- \fi
- \fi
- \fi
- \fi
-%\fi
- \egroup
- \ignorespaces}
-
-% pass D
-
-\def\dophaseoneFLOWcellX#1#2%
- {\!!counta#1\relax
- \!!countb#2\relax
- \!!countc\@@FLOWx
- \!!countd\@@FLOWy
- \advance\!!countc \@@FLOWnx
- \advance\!!countd \@@FLOWny
- \advance\!!countc \minusone
- \advance\!!countd \minusone
- \ifnum\!!counta<\@@FLOWx\relax \donefalse
- \else\ifnum\!!counta>\!!countc \donefalse
- \else\ifnum\!!countb<\@@FLOWy\relax \donefalse
- \else\ifnum\!!countb>\!!countd \donefalse
- \else \donetrue
- \fi\fi\fi\fi}
-
-\def\dophasetwoFLOWcellX
- {\advance\!!counta -\@@FLOWx
- \advance\!!counta \plusone
- \advance\!!countb -\@@FLOWy
- \advance\!!countb \plusone
- \dimen0=\FLOWgridwidth
- \dimen0=\!!counta\dimen0
- \advance\dimen0 -\FLOWgridwidth
- \dimen4=\FLOWgridwidth
- \advance\dimen4 -\FLOWshapewidth
- \advance\dimen0 .5\dimen4
- \dimen2=\FLOWgridheight
- \dimen2=\!!countb\dimen2
- \dimen4=\FLOWgridheight
- \advance\dimen4 -\FLOWshapeheight
- \advance\dimen2 -.5\dimen4
- \edef\FLOWdx{\the\dimen0}%
- \edef\FLOWdy{\the\dimen2}}
-
-\def\positionFLOWzero% assumes \FLOWdx and \FLOWdy are set
- {\setbox0\hbox{\hskip\FLOWdx\lower\FLOWdy\box0}%
- \smashbox0\box0
- \nointerlineskip} % new, needed since we somehow reset that
-
-\def\doFLOWtlabel#1#2#3%
- {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
- \setbox0\hbox{\hskip\dimen2\raise\scratchdimen
- \hbox{\raise\dimen4\hbox{#1{\strut#3}}}}%
- \positionFLOWzero}%
-
-\def\doFLOWblabel#1#2#3%
- {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdy\fi
- \setbox0\hbox{\hskip\dimen2\raise-\scratchdimen
- \hbox{#1{\strut#3}}}%
- \positionFLOWzero}%
-
-\def\doFLOWllabel#1#2#3%
- {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
- \setbox0\hbox{\hskip-\scratchdimen\raise\dimen6
- \hbox{#1{\strut#3}}}%
- \positionFLOWzero}%
-
-\def\doFLOWrlabel#1#2#3%
- {\scratchdimen\ifcase#2 \zeropoint\else\@@FLOWdx\fi
- \setbox0\hbox{\hskip\dimen0\hskip\scratchdimen
- \hbox{\raise\dimen6\hbox{#1{\strut#3}}}}%
- \positionFLOWzero}
-
-\def\doprocessFLOWcellD#1,#2\end
- {\dophaseoneFLOWcellX{#1}{#2}%
- \ifdone
- \dophasetwoFLOWcellX
- \doglobal\addtocommalist\FLOWcell\FLOWcells
- \def\FLOWx{#1}%
- \def\FLOWy{#2}%
- \directsetup{flowcell}%
- \setbox0\hbox
- {\ifx\FLOWalign\empty\else
- \setupframed
- [\c!align=\v!normal,\c!bottom=\vfill,\c!top=\vfill]%
- \@EA\processallactionsinset\@EA
- [\FLOWalign]
- [t=>{\setupframed[\c!bottom=\vfill,\c!top=]},
- b=>{\setupframed[\c!bottom=,\c!top=\vfill]},
- l=>{\setupframed[\c!align=\v!right]},
- r=>{\setupframed[\c!align=\v!left]},
- m=>{\setupframed[\c!align=\v!middle]},
- c=>{\setupframed[\c!align=\v!middle]}]%
- \fi
- \doifelse\FLOWshape{none} % {\v!none}
- {\setupframed[\c!offset=\v!overlay]}
- {\setupframed[\c!offset=\@@FLOSoffset]}%
- \framed
- [\c!frame=\v!off,\c!background=flowcell,
- \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
- {\FLOWtext}}%
- \showFLOWhelp0
- \ifx\FLOWdestination\empty\else
- \setbox0\hbox
- {\setupinteraction[\c!color=,\c!contrastcolor=]%
- \gotobox{\box0}[\FLOWdestination]}%
- \fi
- \positionFLOWzero
- \dimen0=\FLOWshapewidth \dimen2=.5\dimen0
- \dimen4=\FLOWshapeheight\dimen6=.5\dimen4
- \boxoffset.5\bodyfontsize
- \doFLOWtlabel \righttopbox0\tFLOWlabel
- \doFLOWblabel\rightbottombox0\bFLOWlabel
- \doFLOWllabel \lefttopbox0\lFLOWlabel
- \doFLOWrlabel \righttopbox0\rFLOWlabel
- \doFLOWtlabel \topbox0\tcFLOWlabel % for me only
- \doFLOWblabel \bottombox0\bcFLOWlabel % for me only
- \doFLOWllabel \leftbox0\lcFLOWlabel % for me only
- \doFLOWrlabel \rightbox0\rcFLOWlabel % for me only
- \ifnum#1=\@@FLOWx\relax \doFLOWllabel \leftbox1\lFLOWexit \fi
- \ifnum#1=\!!countc \doFLOWrlabel \rightbox1\rFLOWexit \fi
- \ifnum#2=\@@FLOWy\relax \doFLOWtlabel \topbox1\tFLOWexit \fi
- \ifnum#2=\!!countd \doFLOWblabel \bottombox1\bFLOWexit \fi
- \boxoffset\zeropoint
- \fi}
-
-% For Willy Egger:
-%
-% \startsetups flowcell
-% \definelayer
-% [flowcell]
-% [width=\FLOWshapewidth,
-% height=\FLOWshapeheight]
-% \setlayerframed
-% [flowcell]
-% [preset=rightbottom,offset=1ex]
-% [frame=off]
-% {\tx(\FLOWx,\FLOWy)}
-% \stopsetups
-
-% Pass E
-
-\long\def\startFLOWcellE#1\stopFLOWcell
- {\resetFLOWcell
- \ignorespaces#1\unskip
- \let\doprocessFLOWcell\doprocessFLOWcellE
- \expandafter\doprocessFLOWcell\FLOWlocation\end}
-
-\def\doprocessFLOWcellE#1,#2\end % redundant
- {\ifx\FLOWoverlay\empty \else
- \dophaseoneFLOWcellX{#1}{#2}%
- \ifdone
- \dophasetwoFLOWcellX
- \edef\FLOWdx{\the\dimen0}%
- \edef\FLOWdy{\the\dimen2}%
- \setbox0\hbox
- {\framed
- [%\c!frame=\v!off,
- \c!background={\@@FLOWbackground,\FLOWoverlay},
- \c!backgroundcolor=\@@FLOSbackgroundcolor,
- \c!width=\FLOWshapewidth,\c!height=\FLOWshapeheight]
- {}}%
- \positionFLOWzero
- \fi
- \fi}
-
-% Pass F
-
-\def\checkFLOWautofocus
- {\def\@@FLOWminx{100}\let\@@FLOWminy\@@FLOWminx
- \def\@@FLOWmaxx {0}\let\@@FLOWmaxy\@@FLOWmaxx
- \def\@@FLOWabsx {0}\let\@@FLOWabsy\@@FLOWabsx
- \let\startFLOWcell\startFLOWcellF
- \resetFLOWlocation
- \processFLOWbuffer\currentFLOWnumber
- %\message{AUTOSHAPE 1: (\@@FLOWminx,\@@FLOWminy)->(\@@FLOWmaxx,\@@FLOWmaxy)}%
- \ifnum\@@FLOWabsx<\@@FLOWmaxx\let\@@FLOWmaxx\@@FLOWabsx\fi
- \ifnum\@@FLOWabsy<\@@FLOWmaxy\let\@@FLOWmaxy\@@FLOWabsy\fi
- %\message{AUTOSHAPE 2: (\@@FLOWminx,\@@FLOWminy)->(\@@FLOWmaxx,\@@FLOWmaxy)}%
- \donetrue
- \ifnum\@@FLOWminx=100 \donefalse\fi
- \ifnum\@@FLOWminy=100 \donefalse\fi
- \ifnum\@@FLOWmaxx=0 \donefalse\fi
- \ifnum\@@FLOWmaxy=0 \donefalse\fi
- \doFLOWcheckF\@@FLOWx\@@FLOWminx\@@FLOWmaxx\@@FLOWnx
- \doFLOWcheckF\@@FLOWy\@@FLOWminy\@@FLOWmaxy\@@FLOWny}
-
-\def\startFLOWcellF#1\stopFLOWcell%
- {\resetFLOWcell
- \ignorespaces#1\unskip
- \expandafter\doFLOWlocationF\FLOWlocation\end}%
-
-\def\doFLOWlocationF#1,#2\end%
- {\ifnum#1>\@@FLOWabsx\def\@@FLOWabsx{#1}\fi
- \ifnum#2>\@@FLOWabsy\def\@@FLOWabsy{#2}\fi
- \doifinset\FLOWcell\@@FLOWautofocus
- {\dodoFLOWlocationF{#1}<-\@@FLOWminx
- \dodoFLOWlocationF{#1}>+\@@FLOWmaxx
- \dodoFLOWlocationF{#2}<-\@@FLOWminy
- \dodoFLOWlocationF{#2}>+\@@FLOWmaxy}}
-
-\def\dodoFLOWlocationF#1#2#3#4%
- {\ifnum#1#2#4\relax
- \!!counta=#1\advance\!!counta #31\relax
- \edef#4{\ifnum\!!counta<1 1\else\the\!!counta\fi}%
- \fi}
-
-\def\doFLOWcheckF#1#2#3#4%
- {\ifdone
- \let#1=#2%
- \!!counta=#3%
- \advance\!!counta \plusone\advance\!!counta -#2\relax
- \ifnum\!!counta<1 \!!counta=1 \fi
- \edef#4{\the\!!counta}%
- \else
- \let#1\!!plusone
- \let#4\!!zerocount % no {1}
- \fi}
-
-% \useFLOWchart[name][parent][setting,setting][additional settings]
-% \useFLOWchart[name][parent][additional settings]
-
-\let\currentFLOWchart\empty
-
-\def\useFLOWchart
- {\doquadrupleempty\douseFLOWchart}
-
-\def\douseFLOWchart[#1][#2][#3][#4]% name parent sets mainsettings
- {\iffourthargument
- \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][#3][#4,##1]}%
- \else
- \checkparameters[#3]%
- \ifparameters
- \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][][#3,##1]}%
- \else
- \setvalue{\@FLOW@--#1}[##1]{\setgetFLOWchart[#2][#3][##1]}%
- \fi
- \fi}
-
-\def\setgetFLOWchart[#1][#2][#3]%
- {\def\docommand##1{}% cell line focus ?
- \processcommalist[#2]\docommand
- \getFLOWchart[#1][#3]}
-
-\def\doFLOWchart[#1][#2]%
- {\hbox\bgroup\vbox\bgroup % vmode suppresses spaces
-\def\currentFLOWchart{#1}%
- \doifundefinedelse{\@FLOW@--#1}
- {\getFLOWchart[#1][#2]}
- {\getvalue{\@FLOW@--#1}[#2]}%
- \egroup\egroup}
-
-\def\FLOWchart%
- {\dodoubleempty\doFLOWchart}
-
-%D The next section is dedicated to splitting up charts.
-
-\def\getFLOWsize[#1]%
- {\bgroup\let\dodogetFLOWchart\dogetFLOWsize\FLOWchart[#1]\egroup}
-
-\def\dogetFLOWsize[#1][#2]%
- {\setbox\scratchbox=\vbox
- {\globallet\FLOWmaxwidth \!!zerocount
- \globallet\FLOWmaxheight\!!zerocount
- \def\getFLOWlocation##1,##2\end
- {\ifnum0##1>\FLOWmaxwidth \xdef\FLOWmaxwidth {##1}\fi
- \ifnum0##2>\FLOWmaxheight\xdef\FLOWmaxheight{##2}\fi}%
- \resetFLOWcell
- \long\def\startFLOWcell##1\stopFLOWcell
- {{##1\expandafter\getFLOWlocation\FLOWlocation\end}}%
- \def\dohandleflowchart[##1][##2]%
- {\resetFLOWlocation
- \processFLOWbuffer{##1}}%
- \getvalue{\@FLOW@-#1}}}
-
-\def\setupFLOWsplit%
- {\dodoubleargument\getparameters[\@@FLOT]}
-
-\setupFLOWsplit%
- [\c!nx=3,\c!ny=3,
- \c!dx=1,\c!dy=1,
- \c!command=,
- \c!marking=\v!on,
- \c!before=,\c!after=]
-
-\def\FLOWsplitx {1}
-\def\FLOWsplity {1}
-\def\FLOWsplitnx{1}
-\def\FLOWsplitny{1}
-
-\def\FLOWcharts%
- {\dodoubleempty\doFLOWcharts}
-
-%D While splitting, the following variables are available:
-%D
-%D \starttyping
-%D \FLOWsplitnx \FLOWsplitny \FLOWsplitx \FLOWsplity
-%D \stoptyping
-
-\def\doFLOWcharts[#1][#2]%
- {\bgroup
- \getFLOWsize[#1]%
- \dodoFLOWcharts\relax
- \global\let\FLOWsplitnx\FLOWsplitx
- \global\let\FLOWsplitny\FLOWsplity
- \dodoFLOWcharts{\dododoFLOWcharts[#1][#2]}%
- \egroup}
-
-\def\dodoFLOWcharts#1%
- {\def\@@FLOTx{1}%
- \global\let\FLOWsplitx\@@FLOTx
- \doloop
- {\def\@@FLOTy{1}%
- \global\let\FLOWsplity\@@FLOTy
- \doloop
- {\bgroup
- \scratchcounter\FLOWmaxwidth
- \advance\scratchcounter -\@@FLOTx
- \advance\scratchcounter \plusone
- \ifnum\scratchcounter<\@@FLOTnx\edef\@@FLOTnx{\the\scratchcounter}\fi
- \scratchcounter\FLOWmaxheight
- \advance\scratchcounter -\@@FLOTy
- \advance\scratchcounter \plusone
- \ifnum\scratchcounter<\@@FLOTny\edef\@@FLOTny{\the\scratchcounter}\fi
- #1% does something with the float, or not
- \egroup
- \increment(\@@FLOTy,\@@FLOTny)%
- \ifnum\@@FLOTy>\FLOWmaxheight
- \exitloop
- \else
- \doglobal\increment\FLOWsplity
- \decrement(\@@FLOTy,\@@FLOTdy)%
- \fi}%
- \increment(\@@FLOTx,\@@FLOTnx)%
- \ifnum\@@FLOTx>\FLOWmaxwidth
- \exitloop
- \else
- \doglobal\increment\FLOWsplitx
- \decrement(\@@FLOTx,\@@FLOTdx)%
- \fi}}
-
-\def\dododoFLOWcharts[#1][#2]%
- {\bgroup
- \@@FLOTbefore
- \doifnot\@@FLOTmarking\v!on{\let\cuthbox\hbox}%
- \cuthbox
- {\@@FLOTcommand
- {\FLOWchart[#1][#2,
- \c!x=\@@FLOTx,\c!nx=\@@FLOTnx,
- \c!y=\@@FLOTy,\c!ny=\@@FLOTny]}}%
- \@@FLOTafter
- \egroup}
-
-%D An example of splitting is given below:
-%D
-%D \starttyping
-%D \setupFLOWsplit
-%D [nx=5,ny=10,
-%D dx=0,dy=0,
-%D before=,
-%D after=\page]
-%D
-%D \FLOWcharts[mybigflow]
-%D \stoptyping
-%D
-%D Or, one can say:
-%D
-%D \starttyping
-%D \splitfloat
-%D {\placefigure{What a big flowchart this is!}}
-%D {\FLOWcharts[mybigflow]}
-%D \stoptyping
-
-%D \macros
-%D {typeFLOWchart}
-%D
-%D For documentation purposes the following macro is
-%D provided. Watch the use of the first and last line hooks,
-%D which is needed because the start and stop commands are
-%D not part of the buffer.
-
-\def\typeFLOWchart[#1]%
- {\bgroup
- \def\dohandleflowchart[##1][##2]{\typeFLOWbuffer{##1}}%
- \defconvertedargument\firstverbatimfileline{\startFLOWchart[#1]}%
- \defconvertedargument\lastverbatimfileline {\stopFLOWchart}%
- \getvalue{\@FLOW@-#1}
- \egroup}
-
-%D New:
-%D
-%D \starttyping
-%D \setupFLOWcharts[command=\Whow]
-%D
-%D \startFLOWset[convert-en] % [tag][convert-en]
-%D \subFLOWchart[a][x=1,y=1,nx=3,ny=3]
-%D \subFLOWchart[b][x=1,y=2,nx=3,ny=3]
-%D \subFLOWchart[c][x=2,y=1,nx=3,ny=3]
-%D \stopFLOWset
-%D
-%D \def\Whow#1%
-%D {\ifnum\currentFLOWset=1 \framed{Some Chart}\fi}
-%D
-%D \FLOWset[convert-en] % [tag]
-%D
-%D \def\Whow#1%
-%D {\setuphead[state=high]
-%D \startstandardmakeup
-%D \centerbox{#1}
-%D \stopstandardmakeup}
-%D
-%D \FLOWset[convert-en] % [tag]
-%D \stoptyping
-
-\def\startFLOWset
- {\dodoubleempty\dostartFLOWset}
-
-\def\dostartFLOWset[#1][#2]#3\stopFLOWset % tag name data
- {\ifsecondargument
- \long\setvalue{\@FLOX@#1}{\dohandleFLOWset{#1}{#2}{#3}}%
- \else
- \long\setvalue{\@FLOX@#1}{\dohandleFLOWset{#1}{#1}{#3}}%
- \fi}
-
-\long\def\dohandleFLOWset#1#2#3% tag name data
- {\bgroup
- \def\subFLOWchart
- {\dodoubleempty\dosubFLOWchart}%
- \def\dosubFLOWchart[##1][##2]% subtag settings
- {\ifsecondargument
- \dodohandleFLOWset{#1}{##1}{#2}{##2}%
- \else
- \subFLOWchart[][##1]%
- \fi}%
- #3%
- \egroup}
-
-\def\dodohandleFLOWset#1#2#3#4% tag subtag name settings
- {\increment\currentFLOWset
- \bgroup
- \@@FLOXcommand
- {\ifnum\currentFLOWset=1 \pagereference[#1]\fi
- \doifsomething{#2}
- {\setupreferencing[\c!prefix=]%
- \pagereference[#1:#2]% -:#1:#2
- \setupreferencing[\c!prefix=#1:#2]}%
- \FLOWchart[#3][#4]}%
- \egroup}
-
-\def\FLOWset[#1]%
- {\newcounter\currentFLOWset
- \doifdefinedelse{\@FLOX@#1}
- {\getvalue{\@FLOX@#1}}
- {\dodohandleFLOWset{#1}{}{#1}{}}}
-
-\newcounter\currentFLOWset
-
-\setupFLOWsets
- [\c!command=]
-
-%D This will be an option:
-
-% \def\startFLOWchart%
-% {\dodoubleempty\dostartFLOWchart}
-%
-% \long\def\dostartFLOWchart[#1][#2]#3\stopFLOWchart
-% {\preparenextFLOWchart{#1}{#2}%
-% \long\setgvalue{\FLOWbufferprefix\nofFLOWcharts}{#3}}
-%
-% \long\def\dodefineFLOWchart[#1][#2]#3%
-% {\preparenextFLOWchart{#1}{#2}%
-% \long\setgvalue{\FLOWbufferprefix\nofFLOWcharts}{#3}}
-%
-% \def\processFLOWbuffer#1{\getvalue{\FLOWbufferprefix#1}}
-% \def\typeFLOWbuffer #1{[Sorry, no verbatim chart #1 available.]}
-
-\writestatus\m!system{The chart mkiv xml interface is not yet defined!}
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/m-chart.mkvi b/Master/texmf-dist/tex/context/base/m-chart.mkvi
new file mode 100644
index 00000000000..e94adeba2cb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/m-chart.mkvi
@@ -0,0 +1,492 @@
+%D \module
+%D [ file=m-chart,
+%D version=2011.10.1, % 1998.10.10,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Flow Charts,
+%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.
+
+% todo (if used):
+% flowsets
+% autoscaling (bodyfontsteps)
+% comment
+% overlay
+%
+% todo:
+% \useFLOWchart[name][parent][setting,setting][additional settings]
+% \useFLOWchart[name][parent][additional settings]
+% setups
+% mp instance with less files
+
+\registerctxluafile{m-chart}{}
+
+\unprotect
+
+% todo: figure out a nice way to define the lot: share current and
+% support current as name (nb: we need to set parent then)
+
+\def\??flch{@@flch} % chart
+\def\??flln{@@flln} % line
+\def\??flsh{@@flsh} % shape
+\def\??flfc{@@flfc} % focus
+\def\??flst{@@flst} % sets
+\def\??flsp{@@flsp} % split
+
+\installsimplecommandhandler \??flch {FLOWchart} \??flch
+\installsimplecommandhandler \??flln {FLOWline} \??flln
+\installsimplecommandhandler \??flsh {FLOWshape} \??flsh
+\installsimplecommandhandler \??flfc {FLOWfocus} \??flfc
+\installsimplecommandhandler \??flst {FLOWsets} \??flst
+\installsimplecommandhandler \??flsp {FLOWsplit} \??flsp
+
+\let\setupFLOWcharts\setupFLOWchart
+\let\setupFLOWlines \setupFLOWline
+\let\setupFLOWshapes\setupFLOWshape
+\let\setupFLOWsets \setupFLOWset
+
+\setupFLOWcharts
+ [\c!width=12\bodyfontsize,
+ \c!height=7\bodyfontsize,
+ \c!offset=\FLOWlineparameter\c!rulethickness,
+ \c!dx=2\bodyfontsize,
+ \c!dy=2\bodyfontsize,
+ \c!nx=0,
+ \c!ny=0,
+ \c!x=1,
+ \c!y=1,
+ \c!labeloffset=.5\bodyfontsize,
+ \c!commentoffset=.5\bodyfontsize,
+ \c!exitoffset=\zeropoint,
+ % \c!maxwidth=,
+ % \c!maxheight=,
+ % \c!option=,
+ % \c!bodyfont=,
+ % \c!dot=, % private option
+ % \c!autofocus=,
+ % \c!focus=,
+ % \c!background=,
+ % \c!framecolor=
+ % \c!backgroundcolor=, % \s!white
+ \c!rulethickness=.15\bodyfontsize, %\linewidth,
+ \c!frame=\v!off]
+
+\setupFLOWlines
+ [\c!corner=\v!round,
+ \c!arrow=\v!yes,
+ \c!dash=\v!no,
+ \c!radius=.375\bodyfontsize,
+ \c!color=FLOWlinecolor,
+ \c!rulethickness=.15\bodyfontsize,
+ \c!offset=\v!none]
+
+\setupFLOWshapes
+ [\c!default=action,
+ \c!framecolor=FLOWframecolor,
+ \c!background=\v!color,
+ \c!backgroundcolor=FLOWbackgroundcolor,
+ \c!rulethickness=.15\bodyfontsize,
+ \c!offset=.5\bodyfontsize]
+
+\setupFLOWfocus
+ [\c!framecolor=FLOWfocuscolor,
+ \c!background=\FLOWshapeparameter\c!background,
+ \c!backgroundcolor=\FLOWshapeparameter\c!backgroundcolor,
+ \c!backgroundscreen=\FLOWshapeparameter\c!backgroundscreen,
+ \c!rulethickness=\FLOWshapeparameter\c!rulethickness,
+ \c!offset=\FLOWshapeparameter\c!offset]
+
+\setupFLOWsplit
+ [\c!state=\v!stop,
+ \c!marking=\v!on,
+ % \c!command=,
+ % \c!before=,
+ % \c!after=,
+ \c!nx=3,
+ \c!ny=3]
+
+\definecolor [FLOWfocuscolor] [s=.2]
+\definecolor [FLOWlinecolor] [s=.5]
+\definecolor [FLOWframecolor] [s=.7]
+\definecolor [FLOWbackgroundcolor] [s=.9]
+
+\newtoks\everyFLOWchart
+
+\unexpanded\def\module_charts_process[#name]%
+ {\ctxcommand{flow_start_chart("#name")}}
+
+\unexpanded\def\startFLOWchart
+ {\startnointerference
+ \the\everyFLOWchart
+ \dosingleempty\module_charts_start_chart}
+
+\unexpanded\def\module_charts_start_chart[#name]%
+ {\ctxcommand{flow_start_chart("#name")}}
+
+\unexpanded\def\stopFLOWchart
+ {\ctxcommand{flow_stop_chart()}%
+ \stopnointerference}
+
+\unexpanded\def\defineFLOWchart % for old times sake
+ {\dodoubleempty\module_charts_FLOW_define}
+
+\unexpanded\def\module_charts_FLOW_define[#name][#settings]#cells% todo: save settings
+ {\startnointerference
+ \the\everyFLOWchart
+ \ctxcommand{flow_start_chart("#name")}%
+ #cells%
+ \ctxcommand{flow_stop_chart()}%
+ \stopnointerference}
+
+\unexpanded\def\startFLOWcell
+ {\dodoubleempty\module_charts_start_cell}
+
+\unexpanded\def\module_charts_start_cell[#1][#2]%
+ {\begingroup
+ \iffirstargument
+ \setupFLOWshape[#1]%
+ \fi
+ \ifsecondargument
+ \setupFLOWline[#2]%
+ \fi
+ \ctxcommand{flow_start_cell {
+ shape = {
+ rulethickness = \number\dimexpr\FLOWshapeparameter\c!rulethickness,
+ default = "\FLOWshapeparameter\c!default",
+ framecolor = "\FLOWshapeparameter\c!framecolor",
+ backgroundcolor = "\FLOWshapeparameter\c!backgroundcolor",
+ },
+ focus = {
+ rulethickness = \number\dimexpr\FLOWfocusparameter\c!rulethickness,
+ framecolor = "\FLOWfocusparameter\c!framecolor",
+ backgroundcolor = "\FLOWfocusparameter\c!backgroundcolor",
+ },
+ line = {
+ rulethickness = \number\dimexpr\FLOWlineparameter\c!rulethickness,
+ radius = \number\dimexpr\FLOWlineparameter\c!radius,
+ color = "\FLOWlineparameter\c!color",
+ corner = "\FLOWlineparameter\c!corner",
+ dash = "\FLOWlineparameter\c!dash",
+ arrow = "\FLOWlineparameter\c!arrow",
+ offset = "\FLOWlineparameter\c!offset",
+ },
+ } }%
+ \endgroup}
+
+\unexpanded\def\stopFLOWcell
+ {\ctxcommand{flow_stop_cell()}}
+
+\unexpanded\def\FLOWchart
+ {\dodoubleempty\module_charts_process}
+
+\def\module_charts_process[#name][#settings]%
+ {\vbox\bgroup
+ \insidefloattrue
+ \dontcomplain
+ \setupFLOWchart[#settings]%
+ \setupbodyfont[\FLOWchartparameter\c!bodyfont]%
+ \ctxcommand{flow_make_chart {
+ chart = {
+ name = "#name",
+ option = "\FLOWchartparameter\c!option",
+ backgroundcolor = "\FLOWchartparameter\c!backgroundcolor",
+ width = \number\dimexpr\FLOWchartparameter\c!width,
+ height = \number\dimexpr\FLOWchartparameter\c!height,
+ dx = \number\dimexpr\FLOWchartparameter\c!dx,
+ dy = \number\dimexpr\FLOWchartparameter\c!dy,
+ offset = \number\dimexpr\FLOWchartparameter\c!offset,
+ % bodyfont = "\FLOWchartparameter\c!bodyfont",
+ dot = "\FLOWchartparameter\c!dot", % private option
+ hcompact = "\FLOWchartparameter\c!hcompact", % undocumented option
+ vcompact = "\FLOWchartparameter\c!vcompact", % undocumented option
+ focus = "\FLOWchartparameter\c!focus",
+ autofocus = "\FLOWchartparameter\c!autofocus",
+ nx = "\FLOWchartparameter\c!nx",
+ ny = "\FLOWchartparameter\c!ny",
+ x = "\FLOWchartparameter\c!x",
+ y = "\FLOWchartparameter\c!y",
+ labeloffset = \number\dimexpr\FLOWchartparameter\c!labeloffset,
+ commentoffset = \number\dimexpr\FLOWchartparameter\c!commentoffset,
+ exitoffset = \number\dimexpr\FLOWchartparameter\c!exitoffset,
+ },
+ shape = {
+ rulethickness = \number\dimexpr\FLOWshapeparameter\c!rulethickness,
+ default = "\FLOWshapeparameter\c!default",
+ framecolor = "\FLOWshapeparameter\c!framecolor",
+ backgroundcolor = "\FLOWshapeparameter\c!backgroundcolor",
+ },
+ focus = {
+ rulethickness = \number\dimexpr\FLOWfocusparameter\c!rulethickness,
+ framecolor = "\FLOWfocusparameter\c!framecolor",
+ backgroundcolor = "\FLOWfocusparameter\c!backgroundcolor",
+ },
+ line = {
+ rulethickness = \number\dimexpr\FLOWlineparameter\c!rulethickness,
+ radius = \number\dimexpr\FLOWlineparameter\c!radius,
+ color = "\FLOWlineparameter\c!color",
+ corner = "\FLOWlineparameter\c!corner",
+ dash = "\FLOWlineparameter\c!dash",
+ arrow = "\FLOWlineparameter\c!arrow",
+ offset = "\FLOWlineparameter\c!offset",
+ },
+ set = {
+ },
+ split = {
+ state = "\FLOWsplitparameter\c!state",
+ nx = \number\FLOWsplitparameter\c!nx,
+ ny = \number\FLOWsplitparameter\c!ny,
+ command = "",
+ marking = "\FLOWsplitparameter\c!marking",
+ before = "",
+ after = "",
+ }
+ } }%
+ \egroup}
+
+\unexpanded\def\FLOWcharts
+ {\dodoubleempty\FLOW_charts}
+
+\def\FLOW_charts[#name][#settings]
+ {\begingroup
+ \setupFLOWsplit[\c!state=\v!start,#settings]%
+ \FLOW_chart[#name][]%
+ \endgroup}
+
+\appendtoks
+ \let\name \FLOW_name
+ \let\shape \FLOW_shape
+ \let\destination\FLOW_destination
+ \let\focus \FLOW_focus
+ \let\overlay \FLOW_overlay
+ \let\location \FLOW_location
+ \let\text \FLOW_text
+ \let\label \FLOW_label
+ \let\comment \FLOW_comment
+ \let\exit \FLOW_exit
+ \let\connection \FLOW_connection
+ \let\include \FLOW_include
+ \let\figure \FLOW_figure
+ %
+ \let\connect \FLOW_connection
+ \let\locate \FLOW_location
+ %
+ \let\includeFLOWchart\include
+\to \everyFLOWchart
+
+\unexpanded\def\FLOW_name #name{\ctxcommand{flow_set_name("#name")}\ignorespaces}
+\unexpanded\def\FLOW_shape #shape{\ctxcommand{flow_set_shape("#shape")}\ignorespaces}
+\unexpanded\def\FLOW_destination#destination{\ctxcommand{flow_set_destination("#destination")}\ignorespaces}
+\unexpanded\def\FLOW_focus #focus{\ctxcommand{flow_set_focus("#focus")}\ignorespaces}
+\unexpanded\def\FLOW_overlay #overlay{\ctxcommand{flow_set_overlay("#overlay")}\ignorespaces}
+\unexpanded\def\FLOW_location #location{\ctxcommand{flow_set_location("#location")}\ignorespaces}
+\unexpanded\def\FLOW_figure #figure{\ctxcommand{flow_set_figure("#figure")}\ignorespaces}
+
+\unexpanded\def\FLOW_text {\dosingleempty\module_charts_FLOW_text}
+\unexpanded\def\FLOW_label {\dosingleempty\module_charts_FLOW_label}
+\unexpanded\def\FLOW_comment {\dosingleempty\module_charts_FLOW_comment}
+\unexpanded\def\FLOW_exit {\dosingleempty\module_charts_FLOW_exit}
+\unexpanded\def\FLOW_connection{\dodoubleempty\module_charts_FLOW_connection}
+\unexpanded\def\FLOW_include {\dodoubleempty\module_charts_FLOW_include}
+
+\unexpanded\def\module_charts_FLOW_text [#align]#text{\ctxcommand{flow_set_text("#align",\!!bs\detokenize{#text}\!!es)}\ignorespaces}
+\unexpanded\def\module_charts_FLOW_label [#location]#text{\ctxcommand{flow_set_label("#location",\!!bs\detokenize{#text}\!!es)}\ignorespaces}
+\unexpanded\def\module_charts_FLOW_comment [#location]#text{\ctxcommand{flow_set_comment("#location",\!!bs\detokenize{#text}\!!es)}\ignorespaces}
+\unexpanded\def\module_charts_FLOW_exit [#location]#text{\ctxcommand{flow_set_exit("#location",\!!bs\detokenize{#text}\!!es)}\ignorespaces}
+\unexpanded\def\module_charts_FLOW_connection[#location][#offset]#name{\ctxcommand{flow_set_connection("#location","#offset","#name")}\ignorespaces}
+
+\unexpanded\def\module_charts_FLOW_include [#name][#settings]{%
+ \begingroup
+ \getparameters[FLOWi][x=1,y=1,#settings]%
+ \ctxcommand{flow_set_include("#name",\number\FLOWix,\number\FLOWiy,\!!bs\detokenize{#settings}\!!es)}%
+ \endgroup
+ \ignorespaces
+}
+
+\setvariables
+ [flowcell:text]
+ [x=1,
+ y=1,
+ text=,
+ align=,
+ set=\setups{flowcell:text:place}]
+
+% \c!background={\@@FLOWbackground,\FLOWoverlay},
+
+\defineoverlay
+ [flowcell:figure]
+ [\overlayfigure{\getvariable{flowcell:text}{figure}}]
+
+\startsetups flowcell:text:place
+ \begingroup
+ \iftrialtypesetting
+ \directsetup{flowcell:text:place:indeed}
+ \else \iflocation
+ \doifelsenothing {\getvariable{flowcell:text}{destination}} {
+ \directsetup{flowcell:text:place:indeed}
+ } {
+ % tricky: scaling and moving around is not taken into account
+ \setupinteraction[\c!color=,\c!contrastcolor=]
+ \gotobox{\directsetup{flowcell:text:place:indeed}}[\getvariable{flowcell:text}{destination}]
+ }
+ \else
+ \directsetup{flowcell:text:place:indeed}
+ \fi \fi
+ \endgroup
+\stopsetups
+
+\startsetups flowcell:text:place:indeed
+ \begingroup
+ \directsetup{flowcell:text:user}
+ \doifelsenothing {\getvariable{flowcell:text}{figure}} {
+ \expandcheckedcsname{flowcell:}{\getvariable{flowcell:text}{align}}\empty
+ {\getvariable{flowcell:text}{text}}
+ } {
+ \expandcheckedcsname{flowcell:}{\getvariable{flowcell:text}{align}}\empty
+ [\c!background=flowcell:figure]
+ {\getvariable{flowcell:text}{text}}
+ }
+ \endgroup
+\stopsetups
+
+\defineframed % to be discussed: shape or global
+ [flowcell:base]
+ [\c!offset=\v!overlay, % no strut ?
+ \c!frame=\FLOWchartparameter\c!frame,
+ \c!background=\FLOWchartparameter\c!background,
+ \c!backgroundcolor=\FLOWchartparameter\c!backgroundcolor,
+ %\c!foregroundcolor=\FLOWshapeparameter\c!foregroundcolor,
+ \c!align=\v!middle,
+ \c!bottom=\vfill,
+ \c!top=\vfill,
+ \c!width=\FLOWchartparameter\c!width,
+ \c!height=\FLOWchartparameter\c!height,
+ % \c!rulethickness=\FLOWchartparameter\c!rulethickness,
+ \c!rulethickness=\zeropoint, % comment for tracing
+ \c!framecolor=\FLOWchartparameter\c!framecolor]
+
+\defineframed[flowcell:] [flowcell:base]
+\defineframed[flowcell:l] [flowcell:base][\c!align=\v!flushleft]
+\defineframed[flowcell:r] [flowcell:base][\c!align=\v!flushright]
+\defineframed[flowcell:m] [flowcell:base][\c!align=\v!middle]
+\defineframed[flowcell:c] [flowcell:base][\c!align=\v!middle]
+
+\defineframed[flowcell:t] [flowcell:base][\c!top=]
+\defineframed[flowcell:b] [flowcell:base][\c!bottom=]
+
+\defineframed[flowcell:lt][flowcell:base][\c!top=,\c!align=\v!flushleft]
+\defineframed[flowcell:rt][flowcell:base][\c!top=,\c!align=\v!flushright]
+\defineframed[flowcell:mt][flowcell:base][\c!top=,\c!align=\v!middle]
+\defineframed[flowcell:ct][flowcell:base][\c!top=,\c!align=\v!middle]
+
+\defineframed[flowcell:lb][flowcell:base][\c!bottom=,\c!align=\v!flushleft]
+\defineframed[flowcell:rb][flowcell:base][\c!bottom=,\c!align=\v!flushright]
+\defineframed[flowcell:mb][flowcell:base][\c!bottom=,\c!align=\v!middle]
+\defineframed[flowcell:cb][flowcell:base][\c!bottom=,\c!align=\v!middle]
+
+% todo: each cell its own setup
+%
+% \startsetups flowcell
+% \definelayer
+% [flowcell]
+% [width=\FLOWshapewidth,
+% height=\FLOWshapeheight]
+% \setlayerframed
+% [flowcell]
+% [preset=rightbottom,offset=1ex]
+% [frame=off]
+% {\tx(\FLOWx,\FLOWy)}
+% \stopsetups
+
+%D \starttyping
+%D \setupFLOWsplit
+%D [nx=5,ny=10,
+%D dx=0,dy=0,
+%D before=,
+%D after=\page]
+%D
+%D \FLOWcharts[mybigflow]
+%D \stoptyping
+%D
+%D \starttyping
+%D \splitfloat
+%D {\placefigure{What a big flowchart this is!}}
+%D {\FLOWcharts[mybigflow]}
+%D \stoptyping
+
+\protect
+
+\continueifinputfile{m-chart.mkvi}
+
+\input chrt-xml.tex
+
+\usemodule[abr-01]
+
+\setupFLOWcharts[option=test]
+\setupFLOWcharts[frame=on]
+\setupinteraction[state=start]
+
+% \setupFLOWcharts[dx=30pt,dy=30pt]
+
+\startMPinclusions
+ predefined_shapes[101] := fullcircle ;
+\stopMPinclusions
+
+\startFLOWchart[demo]
+ \startFLOWcell[framecolor=darkgray]
+ \name {start}
+ \location {1,1}
+ \shape {action}
+ \text {start}
+ \connection [bl] {one}
+ \stopFLOWcell
+ \startFLOWcell[framecolor=darkred]
+ \name {one}
+% \destination{CloseDocument}
+ \location {2,2}
+% \shape {action}
+ \shape {101}
+ \text {first}
+% \label [b] {\bfx bottom}
+ \connection [rt] {two}
+% \exit [l] {exit l}
+% \exit [r] {exit r}
+% \exit [t] {exit t}
+% \exit [b] {exit b}
+ \stopFLOWcell
+ \setupFLOWshapes[framecolor=darkgray]
+ \startFLOWcell % [foregroundcolor=white]
+ \name {two}
+% \destination{CloseDocument}
+ \location {3,3}
+ \shape {action}
+ \text {second}
+ \figure {cow.pdf}
+% \label [l] {\bfx left}
+% \exit [l] {exit l}
+% \exit [r] {exit r}
+% \exit [t] {exit t}
+% \exit [b] {exit b}
+ \stopFLOWcell
+\stopFLOWchart
+
+\starttext
+
+\startTEXpage
+% \FLOWchart[convert-en]
+% \FLOWchart[conversion 1]
+% \FLOWchart[conversion 7]
+% \FLOWchart[conversion 9]
+% \FLOWchart[conversion 10]
+ \FLOWchart[demo]
+
+\stopTEXpage
+
+\startTEXpage
+ \FLOWchart[conversion 10]
+\stopTEXpage
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/m-chart.tex b/Master/texmf-dist/tex/context/base/m-chart.tex
deleted file mode 100644
index c4e279d5476..00000000000
--- a/Master/texmf-dist/tex/context/base/m-chart.tex
+++ /dev/null
@@ -1,18 +0,0 @@
-%D \module
-%D [ file=m-chart,
-%D version=1998.10.10,
-%D title=\CONTEXT\ Modules,
-%D subtitle=Flow Charts,
-%D author={Hans Hagen \& Ton Otten},
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 file will become obsolete.
-
-\loadmarkfile{m-chart}
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/m-chemic.mkii b/Master/texmf-dist/tex/context/base/m-chemic.mkii
index e6980e1ffea..0b3c98221a1 100644
--- a/Master/texmf-dist/tex/context/base/m-chemic.mkii
+++ b/Master/texmf-dist/tex/context/base/m-chemic.mkii
@@ -5,8 +5,8 @@
%D subtitle=\PPCHTEX\ (Plain Pictex Context cHemie \TEX),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten},
-%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten}]
+%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten},
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-chemic.mkiv b/Master/texmf-dist/tex/context/base/m-chemic.mkiv
index bd4cb093e4d..1dd403fae79 100644
--- a/Master/texmf-dist/tex/context/base/m-chemic.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-chemic.mkiv
@@ -5,8 +5,8 @@
%D subtitle=\PPCHTEX\ (Plain Pictex Context cHemie \TEX),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten},
-%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten}]
+%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten},
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-cweb.tex b/Master/texmf-dist/tex/context/base/m-cweb.tex
index c416c9b3663..bf80e229c14 100644
--- a/Master/texmf-dist/tex/context/base/m-cweb.tex
+++ b/Master/texmf-dist/tex/context/base/m-cweb.tex
@@ -5,7 +5,7 @@
%D subtitle=\CWEB\ Pretty Printing Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-database.lua b/Master/texmf-dist/tex/context/base/m-database.lua
index 8dde9690e96..b9ec3aa3691 100644
--- a/Master/texmf-dist/tex/context/base/m-database.lua
+++ b/Master/texmf-dist/tex/context/base/m-database.lua
@@ -10,7 +10,9 @@ local sub, gmatch, format = string.sub, string.gmatch, string.format
local concat = table.concat
local lpegpatterns, lpegmatch, lpegsplitat = lpeg.patterns, lpeg.match, lpeg.splitat
local lpegP, lpegC, lpegS, lpegCt = lpeg.P, lpeg.C, lpeg.S, lpeg.Ct
-local sprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+
+-- One also needs to enable context.trace, here we only plug in some code (maybe
+-- some day this tracker will also toggle the main context tracer.
local trace_flush = false trackers.register("module.database.flush", function(v) trace_flush = v end)
@@ -26,14 +28,8 @@ local separators = { -- not interfaced
spaces = lpegpatterns.space^1,
}
-local function tracedsprint(c,str)
- report_database("snippet: %s",str)
- sprint(c,str)
-end
-
function buffers.database.process(settings)
local data
- local sprint = trace_flush and tracedsprint or sprint
if settings.type == "file" then
local filename = resolvers.finders.byscheme("any",settings.database)
data = filename ~= "" and io.loaddata(filename)
@@ -42,6 +38,9 @@ function buffers.database.process(settings)
data = buffers.getlines(settings.database)
end
if data and #data > 0 then
+ if trace_flush then
+ context.pushlogger(report_database)
+ end
local separatorchar, quotechar, commentchar = settings.separator, settings.quotechar, settings.commentchar
local before, after = settings.before or "", settings.after or ""
local first, last = settings.first or "", settings.last or ""
@@ -70,38 +69,57 @@ function buffers.database.process(settings)
for i=1,#data do
local line = data[i]
if line ~= "" and (not checker or not lpegmatch(checker,line)) then
- local result, r = { }, 0 -- we collect as this is nicer in tracing
local list = lpegmatch(splitter,line)
if not found then
if setups ~= "" then
- sprint(ctxcatcodes,format("\\begingroup\\setups[%s]",setups))
+ context.begingroup()
+ context.setups { setups }
end
- sprint(ctxcatcodes,before)
+ context(before)
found = true
end
- r = r + 1 ; result[r] = first
- for j=1,#list do
- r = r + 1 ; result[r] = left
- if command == "" then
- r = r + 1 ; result[r] = list[j]
- else
- r = r + 1 ; result[r] = command
- r = r + 1 ; result[r] = "{"
- r = r + 1 ; result[r] = list[j]
- r = r + 1 ; result[r] = "}"
+ if trace_flush then
+ local result, r = { }, 0
+ r = r + 1 ; result[r] = first
+ for j=1,#list do
+ r = r + 1 ; result[r] = left
+ if command == "" then
+ r = r + 1 ; result[r] = list[j]
+ else
+ r = r + 1 ; result[r] = command
+ r = r + 1 ; result[r] = "{"
+ r = r + 1 ; result[r] = list[j]
+ r = r + 1 ; result[r] = "}"
+ end
+ r = r + 1 ; result[r] = right
end
- r = r + 1 ; result[r] = right
+ r = r + 1 ; result[r] = last
+ context(concat(result))
+ else
+ context(first)
+ for j=1,#list do
+ context(left)
+ if command == "" then
+ context(list[j])
+ else
+ context(command)
+ context(false,list[j])
+ end
+ context(right)
+ end
+ context(last)
end
- r = r + 1 ; result[r] = last
- sprint(ctxcatcodes,concat(result))
end
end
if found then
- sprint(ctxcatcodes,after)
+ context(after)
if setups ~= "" then
- sprint(ctxcatcodes,"\\endgroup")
+ context.endgroup()
end
end
+ if trace_flush then
+ context.poplogger()
+ end
else
-- message
end
diff --git a/Master/texmf-dist/tex/context/base/m-database.mkii b/Master/texmf-dist/tex/context/base/m-database.mkii
index 3bb050f142a..abb67986e02 100644
--- a/Master/texmf-dist/tex/context/base/m-database.mkii
+++ b/Master/texmf-dist/tex/context/base/m-database.mkii
@@ -5,8 +5,7 @@
%D subtitle=Database Thingies,
%D author=Hans Hagen\& Taco Hoekwater,
%D date=\currentdate,
-%D copyright=PRAGMA
-%D ]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
diff --git a/Master/texmf-dist/tex/context/base/m-database.mkiv b/Master/texmf-dist/tex/context/base/m-database.mkiv
index 0653bfa0e94..cef0aa81554 100644
--- a/Master/texmf-dist/tex/context/base/m-database.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-database.mkiv
@@ -5,8 +5,7 @@
%D subtitle=Database Thingies,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA
-%D ]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
@@ -23,34 +22,6 @@
\def\c!quotechar {quotechar}
\def\c!commentchar {commentchar}
-% \def\????db{@@@@db}
-%
-% \installparameterhandler \????db {database}
-% \installcommandhandler \????db {database} \????db % #3 == defaultroot
-% \installattributehandler \????db {database}
-%
-% or:
-%
-% \installnamespace{db} \installcommandhandler\????db{database}\????db
-%
-% \appendtoks
-% \getparameters
-% [\????db\currentdatabase]
-% [\c!separator={,},
-% \c!quotechar=,
-% \c!commentchar=,
-% \c!setups=,
-% \c!before=,
-% \c!after=,
-% \c!first=,
-% \c!last=,
-% \c!left=,
-% \c!right=,
-% \c!command=]%
-% \to \everypresetdatabase
-%
-% or:
-
\definenamespace
[db]
[type=module,
@@ -115,7 +86,7 @@
\def\dodefineseparatedlist[#1][#2]%
{\definedatabase[#1][#2]%
- \setuvalue{\e!start#1}{\dostartbuffer[#1][\e!start#1][\e!stop#1]}%
+ \setuvalue{\e!start#1}{\grabbufferdatadirect{#1}{\e!start#1}{\e!stop#1}}%
\setuvalue{\e!stop#1}{\processdatabasebuffer[#1][#1]}}
\def\processseparatedfile[#1][#2]%
@@ -123,7 +94,7 @@
\def\startseparatedlist[#1]% to be interfaced
{\def\stopseparatedlist{\processdatabasebuffer[#1][#1]}%
- \dostartbuffer[#1][startseparatedlist][stopseparatedlist]}
+ \grabbufferdatadirect{#1}{startseparatedlist}{stopseparatedlist}}
\protect
diff --git a/Master/texmf-dist/tex/context/base/m-datastrc.tex b/Master/texmf-dist/tex/context/base/m-datastrc.tex
index 4a6faa66b28..1fd5a9e42c4 100644
--- a/Master/texmf-dist/tex/context/base/m-datastrc.tex
+++ b/Master/texmf-dist/tex/context/base/m-datastrc.tex
@@ -5,7 +5,7 @@
%D subtitle=Database Support, % 2A
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-dratex.mkii b/Master/texmf-dist/tex/context/base/m-dratex.mkii
index 6c088daf98a..2b5f0be2a6f 100644
--- a/Master/texmf-dist/tex/context/base/m-dratex.mkii
+++ b/Master/texmf-dist/tex/context/base/m-dratex.mkii
@@ -5,7 +5,7 @@
%D subtitle=\DRATEX\ Loading Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-edtsnc.mkii b/Master/texmf-dist/tex/context/base/m-edtsnc.mkii
index 0926f44886a..0f66893e833 100644
--- a/Master/texmf-dist/tex/context/base/m-edtsnc.mkii
+++ b/Master/texmf-dist/tex/context/base/m-edtsnc.mkii
@@ -5,7 +5,7 @@
%D subtitle=Editor Synchronization,
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.edit for
diff --git a/Master/texmf-dist/tex/context/base/m-educat.tex b/Master/texmf-dist/tex/context/base/m-educat.tex
index ddfb72ff4ed..93b1a6c5db3 100644
--- a/Master/texmf-dist/tex/context/base/m-educat.tex
+++ b/Master/texmf-dist/tex/context/base/m-educat.tex
@@ -5,18 +5,18 @@
%D subtitle=Educational Extras,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
%D This module will collect a few macros cq.\ definitions
%D meant for educational use. Most of the code has been laying
%D around for some time and has been (or is still) used in
-%D \PRAGMA\ projects.
+%D \PRAGMA\ projects.
-\unprotect
+\unprotect
\definesystemvariable{iv}
@@ -28,10 +28,10 @@
[\c!location=\v!text,
\c!n=0,
\c!frame=\v!off,
- \c!framecolor=answerlinecolor,
+ \c!framecolor=answerlinecolor,
\c!rulethickness=2pt,
\c!background=\v!color,
- \c!backgroundcolor=answerareacolor,
+ \c!backgroundcolor=answerareacolor,
\c!alternative=2] % betweenline
% n=gedwongen
@@ -48,23 +48,23 @@
\dontcomplain
\setupanswerarea
[\c!n=0,\c!m=,#1,\c!location=\v!text]%
- \doifelsenothing{\backgroundvariable\c!m}
+ \doifelsenothing{\textbackgroundparameter\c!m}
{\expandafter\donoanswerspace}
{\expandafter\dodoanswerspace}%
[#1]}
\def\donoanswerspace[#1]#2%
{\setupthinrules
- [\c!alternative=\backgroundvariable\c!alternative,
- \c!color=\backgroundvariable\c!framecolor,
- \c!background=\backgroundvariable\c!background,
- \c!backgroundcolor=\backgroundvariable\c!backgroundcolor,
- \c!rulethickness=\backgroundvariable\c!rulethickness]%
- \doifelse{\backgroundvariable\c!n}{*}
+ [\c!alternative=\textbackgroundparameter\c!alternative,
+ \c!color=\textbackgroundparameter\c!framecolor,
+ \c!background=\textbackgroundparameter\c!background,
+ \c!backgroundcolor=\textbackgroundparameter\c!backgroundcolor,
+ \c!rulethickness=\textbackgroundparameter\c!rulethickness]%
+ \doifelse{\textbackgroundparameter\c!n}{*}
{\thinrule
\par}
- {\scratchcounter0\backgroundvariable\c!n\relax
- % tricky, guess
+ {\scratchcounter0\textbackgroundparameter\c!n\relax
+ % tricky, guess
\def\processisolatedword##1%
{\setbox\scratchbox=\hbox{##1}%
\vbox{\hsize\wd\scratchbox\thinrule
@@ -74,7 +74,7 @@
\vbox{\hsize\wd\scratchbox\thinrule}%
\fi}}%
\processisolatedwords{#2}\processisolatedword
- % so far
+ % so far
\ifcase\scratchcounter \else \ifnum\scratchcounter<3
\nobreak \vbox{\hsize\scratchcounter em\thinrule}%
\else % more
@@ -87,11 +87,11 @@
\def\dodoanswerspace[#1]#2% m case
{\getvalue{\e!start\v!answerarea}%
#2%
- \doifelse{\backgroundvariable\c!m}{*}
+ \doifelse{\textbackgroundparameter\c!m}{*}
{\hfill\strut
\getvalue{\e!stop\v!answerarea}%
\par}
- {\scratchcounter0\backgroundvariable\c!m\relax
+ {\scratchcounter0\textbackgroundparameter\c!m\relax
\ifcase\scratchcounter \else \ifnum\scratchcounter<3
\nobreak \hbox to \scratchcounter em{\strut\hss}%
\else % more
@@ -110,43 +110,43 @@
\dontcomplain
\setupanswerarea
[\c!n=0,\c!m=,#1,\c!location=\v!text]%
- \doifnot{\backgroundvariable\c!option}\v!joinedup\softbreak
- \doifelsenothing{\backgroundvariable\c!m}
+ \doifnot{\textbackgroundparameter\c!option}\v!joinedup\softbreak
+ \doifelsenothing{\textbackgroundparameter\c!m}
{\expandafter\donostartanswerlines}
{\expandafter\dodostartanswerlines}%
[#1]}
\def\donostartanswerlines[#1]%
{\setupthinrules
- [\c!alternative=\backgroundvariable\c!alternative,
- \c!color=\backgroundvariable\c!framecolor,
- \c!background=\backgroundvariable\c!background,
- \c!backgroundcolor=\backgroundvariable\c!backgroundcolor,
- \c!rulethickness=\backgroundvariable\c!rulethickness]%
- \thinrules[\c!n=\backgroundvariable\c!n]\par
+ [\c!alternative=\textbackgroundparameter\c!alternative,
+ \c!color=\textbackgroundparameter\c!framecolor,
+ \c!background=\textbackgroundparameter\c!background,
+ \c!backgroundcolor=\textbackgroundparameter\c!backgroundcolor,
+ \c!rulethickness=\textbackgroundparameter\c!rulethickness]%
+ \thinrules[\c!n=\textbackgroundparameter\c!n]\par
\endgroup
\grabuntil{\e!stop\e!answerlines}}
\def\dodostartanswerlines[#1]%
- {\begingroup
+ {\begingroup
\getvalue{\e!start\v!answerarea}%
\ignorespaces}
-\setvalue{\e!stop\e!answerlines}%
- {\scratchcounter0\backgroundvariable\c!m\relax
- % a \softbreak is more efficient in pos dan \par
+\setvalue{\e!stop\e!answerlines}%
+ {\scratchcounter0\textbackgroundparameter\c!m\relax
+ % a \softbreak is more efficient in pos dan \par
\ifcase\scratchcounter
% nothing
\or
- \softbreak
+ \softbreak
\else
- \softbreak
+ \softbreak
\advance \scratchcounter \minusone
\dorecurse\scratchcounter{\strut\hfill\strut\softbreak}%
\fi
\strut\hfill\strut
\getvalue{\e!stop\v!answerarea}%
- \par\endgroup\endgroup}
+ \par\endgroup\endgroup}
\setvalue\e!answerlines
{\dosingleempty\doanswerlines}
@@ -174,19 +174,19 @@ test test test \answerspace [n=10] {Whow}. test test test
test tets test test \answerspace [n=10] {Whow}. test test
test test tets test test \answerspace [n=10] {Whow}. test
test test test tets test test \answerspace [n=10] {Whow}.
-test test test test test test \answerspace [n=*] {Whow.}
+test test test test test test \answerspace [n=*] {Whow.}
test test test test test test test \startanswerlines
-[n=3] What A Junk Answer \stopanswerlines
+[n=3] What A Junk Answer \stopanswerlines
test test test test test test test \startanswerlines
-[n=3,alternative=0] What A Junk Answer \stopanswerlines
+[n=3,alternative=0] What A Junk Answer \stopanswerlines
test test test test test test test \startanswerlines
-[n=3,alternative=1] What A Junk Answer \stopanswerlines
+[n=3,alternative=1] What A Junk Answer \stopanswerlines
test test test test test test test \startanswerlines
-[n=3,alternative=2] What A Junk Answer \stopanswerlines
+[n=3,alternative=2] What A Junk Answer \stopanswerlines
\startitemize[paragraph]
\item \startanswerlines [option=seried,n=2] xxx \stopanswerlines
@@ -196,20 +196,20 @@ test test test \answerspace [m=10] {Whow}. test test test
test tets test test \answerspace [m=10] {Whow}. test test
test test tets test test \answerspace [m=10] {Whow}. test
test test test tets test test \answerspace [m=10] {Whow}.
-test test test test test test \answerspace [m=*] {Whow.}
+test test test test test test \answerspace [m=*] {Whow.}
test test test test test test test \startanswerlines
-[m=2] What A Junk Answer \stopanswerlines
+[m=2] What A Junk Answer \stopanswerlines
test test test test test test test \startanswerlines
-[m=2,alternative=0] What A Junk Answer \stopanswerlines
-
+[m=2,alternative=0] What A Junk Answer \stopanswerlines
+
test test test test test test test \startanswerlines
-[m=2,alternative=1] What A Junk Answer \stopanswerlines
+[m=2,alternative=1] What A Junk Answer \stopanswerlines
test test test test test test test \startanswerlines
-[m=2,alternative=2] What A Junk Answer \stopanswerlines
-
+[m=2,alternative=2] What A Junk Answer \stopanswerlines
+
\startitemize[paragraph]
\item \startanswerlines [option=seried,m=2] xxx \stopanswerlines
\stopitemize
diff --git a/Master/texmf-dist/tex/context/base/m-fields.mkiv b/Master/texmf-dist/tex/context/base/m-fields.mkiv
index cd840f377d4..46b77f8d39b 100644
--- a/Master/texmf-dist/tex/context/base/m-fields.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-fields.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Fields,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-format.tex b/Master/texmf-dist/tex/context/base/m-format.tex
index 0f274b236e1..e974e4a1101 100644
--- a/Master/texmf-dist/tex/context/base/m-format.tex
+++ b/Master/texmf-dist/tex/context/base/m-format.tex
@@ -5,7 +5,7 @@
%D subtitle=Ancient Formatting Code,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-graph.mkii b/Master/texmf-dist/tex/context/base/m-graph.mkii
index 69d1d3d57ef..8e28cf53724 100644
--- a/Master/texmf-dist/tex/context/base/m-graph.mkii
+++ b/Master/texmf-dist/tex/context/base/m-graph.mkii
@@ -5,7 +5,7 @@
%D subtitle=\METAPOST\ graph module support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-graph.mkiv b/Master/texmf-dist/tex/context/base/m-graph.mkiv
index e8aeb237519..db72927fbb4 100644
--- a/Master/texmf-dist/tex/context/base/m-graph.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-graph.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\METAPOST\ graph module support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -31,7 +31,7 @@
str = str:gsub("e(.-)$",strip)
str = ("\\mathematics{%s}"):format(str)
end
- tex.sprint(str)
+ context(str)
end
\stopluacode
@@ -98,19 +98,15 @@
\stopMPinclusions
-\doifnotmode {demo} {\endinput}
-
-\doiffileelse {agepop91.d} {} {\writestatus{graph}{no data files found}\wait\end}
-
-%D The test:
+\continueifinputfile{m-graph.mkiv}
\starttext
-% \startMPpage
-% draw begingraph(3in,2in);
-% gdraw "t:/metapost/grphdata/agepop91.d";
-% endgraph;
-% \stopMPpage
+\startMPpage
+draw begingraph(3in,2in);
+ gdraw "t:/metapost/grphdata/agepop91.d";
+endgraph;
+\stopMPpage
% \startMPpage
% draw begingraph(3in,2in);
diff --git a/Master/texmf-dist/tex/context/base/m-layout.tex b/Master/texmf-dist/tex/context/base/m-layout.tex
index 0ee71da474c..5ccf0e98731 100644
--- a/Master/texmf-dist/tex/context/base/m-layout.tex
+++ b/Master/texmf-dist/tex/context/base/m-layout.tex
@@ -5,7 +5,7 @@
%D subtitle=Additional Layouts,
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA ADE/ Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-level.mkii b/Master/texmf-dist/tex/context/base/m-level.mkii
index 67d5987332d..d758288d7ef 100644
--- a/Master/texmf-dist/tex/context/base/m-level.mkii
+++ b/Master/texmf-dist/tex/context/base/m-level.mkii
@@ -5,7 +5,7 @@
%D subtitle=Catching Nesting Errors,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-markdown.lua b/Master/texmf-dist/tex/context/base/m-markdown.lua
new file mode 100644
index 00000000000..1f9402f60e3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/m-markdown.lua
@@ -0,0 +1,824 @@
+if not modules then modules = { } end modules ['m-markdown'] = {
+ version = 1.002,
+ comment = "companion to m-markdown.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "see below",
+ license = "see context related readme files"
+}
+
+--[[
+Copyright (C) 2009 John MacFarlane / Khaled Hosny / Hans Hagen
+
+The main parser is derived from the lunamark parser written by John MacFarlane. You
+can download lunamark from:
+
+ http://github.com/jgm/lunamark.git
+
+Khaled Hosny provided the context writer for lunamark and that was used as starting
+point for the mapping. The original code can be fetched from the above location.
+
+While playing with the original code I got the feeling that lpeg could perform better.
+The slowdown was due to the fact that the parser's lpeg was reconstructed each time a
+nested parse was needed. After changing that code a bit I could bring down parsing of
+some test code from 2 seconds to less than 0.1 second so I decided to stick to this
+parser instead of writing my own. After all, the peg code looks pretty impressive and
+visiting Johns pandoc pages is worth the effort:
+
+ http://johnmacfarlane.net/pandoc/
+
+The code here is mostly meant for processing snippets embedded in a context
+documents and is no replacement for pandoc at all. Therefore an alternative is to use
+pandoc in combination with Aditya's filter module.
+
+As I changed (and optimized) the original code, it will be clear that all errors
+are mine. Eventually I might also adapt the parser code a bit more. When I ran into of
+closure stack limitations I decided to flatten the code. The following implementation
+seems to be a couple of hundred times faster than what I started with which is not that
+bad.
+
+This is a second rewrite. The mentioned speed gain largely depended on the kind of
+content: blocks, references and items can be rather demanding. Also, There were
+some limitations with respect to the captures. So, table storage has been removed in
+favor of strings, and nesting has been simplified. The first example at the end of this
+file now takes .33 seconds for 567KB code (resulting in over 1MB) so we're getting there.
+
+There will be a third rewrite eventually.
+]]--
+
+-- todo: we have better quote and tag scanners in ctx
+-- todo: provide an xhtml mapping
+-- todo: add a couple of extensions
+-- todo: check patches to the real peg
+
+local type, next, tonumber = type, next, tonumber
+local lower, upper, gsub, rep, gmatch, format, length = string.lower, string.upper, string.gsub, string.rep, string.gmatch, string.format, string.len
+local concat = table.concat
+local P, R, S, V, C, Ct, Cg, Cb, Cmt, Cc, Cf, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cg, lpeg.Cb, lpeg.Cmt, lpeg.Cc, lpeg.Cf, lpeg.Cs
+local lpegmatch = lpeg.match
+local utfbyte, utfchar = utf.byte, utf.char
+
+moduledata = moduledata or { }
+moduledata.markdown = moduledata.markdown or { }
+local markdown = moduledata.markdown
+
+local nofruns, nofbytes, nofhtmlblobs = 0, 0, 0
+
+---------------------------------------------------------------------------------------------
+
+local nestedparser
+local syntax
+
+nestedparser = function(str) return lpegmatch(syntax,str) end
+
+---------------------------------------------------------------------------------------------
+
+local asterisk = P("*")
+local dash = P("-")
+local plus = P("+")
+local underscore = P("_")
+local period = P(".")
+local hash = P("#")
+local ampersand = P("&")
+local backtick = P("`")
+local less = P("<")
+local more = P(">")
+local space = P(" ")
+local squote = P("'")
+local dquote = P('"')
+local lparent = P("(")
+local rparent = P(")")
+local lbracket = P("[")
+local rbracket = P("]")
+local slash = P("/")
+local equal = P("=")
+local colon = P(":")
+local semicolon = P(";")
+local exclamation = P("!")
+
+local digit = R("09")
+local hexdigit = R("09","af","AF")
+local alphanumeric = R("AZ","az","09")
+
+local doubleasterisks = P("**")
+local doubleunderscores = P("__")
+local fourspaces = P(" ")
+
+local any = P(1)
+local always = P("")
+
+local tab = P("\t")
+local spacechar = S("\t ")
+local spacing = S(" \n\r\t")
+local newline = P("\r")^-1 * P("\n")
+local spaceornewline = spacechar + newline
+local nonspacechar = any - spaceornewline
+local optionalspace = spacechar^0
+local spaces = spacechar^1
+local eof = - any
+local nonindentspace = space^-3
+local blankline = optionalspace * C(newline)
+local blanklines = blankline^0
+local skipblanklines = (optionalspace * newline)^0
+local linechar = P(1 - newline)
+local indent = fourspaces + (nonindentspace * tab) / ""
+local indentedline = indent /"" * C(linechar^1 * (newline + eof))
+local optionallyindentedline = indent^-1 /"" * C(linechar^1 * (newline + eof))
+local spnl = optionalspace * (newline * optionalspace)^-1
+local specialchar = S("*_`*&[]<!\\")
+local normalchar = any - (specialchar + spaceornewline)
+local line = C((any - newline)^0 * newline)
+ + C(any^1 * eof)
+local nonemptyline = (any - newline)^1 * newline
+
+---------------------------------------------------------------------------------------------
+
+local function lineof(c)
+ return (nonindentspace * (P(c) * optionalspace)^3 * newline * blankline^1)
+end
+
+local lineof_asterisks = lineof(asterisk)
+local lineof_dashes = lineof(dash)
+local lineof_underscores = lineof(underscore)
+
+local bullet = nonindentspace * (plus + (asterisk - lineof_asterisks) + (dash - lineof_dashes)) * spaces
+local enumerator = nonindentspace * digit^1 * period * spaces
+
+---------------------------------------------------------------------------------------------
+
+local openticks = Cg(backtick^1, "ticks")
+local closeticks = space^-1 * Cmt(C(backtick^1) * Cb("ticks"), function(s,i,a,b) return #a == #b and i end)
+local intickschar = (any - S(" \n\r`"))
+ + (newline * -blankline)
+ + (space - closeticks)
+ + (backtick^1 - closeticks)
+local inticks = openticks * space^-1 * C(intickschar^1) * closeticks
+
+---------------------------------------------------------------------------------------------
+
+local leader = space^-3
+local nestedbrackets = P { lbracket * ((1 - lbracket - rbracket) + V(1))^0 * rbracket }
+local tag = lbracket * C((nestedbrackets + 1 - rbracket)^0) * rbracket
+local url = less * C((1-more)^0) * more
+ + C((1-spacing- rparent)^1) -- sneaky: ) for resolver
+local title_s = squote * lpeg.C((1-squote )^0) * squote
+local title_d = dquote * lpeg.C((1-dquote )^0) * dquote
+local title_p = lparent * lpeg.C((1-rparent)^0) * rparent
+local title = title_s + title_d + title_p
+local optionaltitle = ((spacing^0 * title * spacechar^0) + lpeg.Cc(""))
+
+local references = { }
+
+local function register_link(tag,url,title)
+ tag = lower(gsub(tag, "[ \n\r\t]+", " "))
+ references[tag] = { url, title }
+end
+
+local function direct_link(label,url,title) -- title is typical html thing
+ return label, url, title
+end
+
+local function indirect_link(label,tag)
+ if tag == "" then
+ tag = label
+ end
+ tag = lower(gsub(tag, "[ \n\r\t]+", " "))
+ local r = references[tag]
+ if r then
+ return label, r[1], r[2]
+ else
+ return label, tag, ""
+ end
+end
+
+local define_reference_parser = (leader * tag * colon * spacechar^0 * url * optionaltitle) / register_link
+local direct_link_parser = tag * spacechar^0 * lparent * (url + Cc("")) * optionaltitle * rparent / direct_link
+local indirect_link_parser = tag * spacechar^0 * tag / indirect_link
+
+local rparser = (define_reference_parser+1)^0
+
+local function referenceparser(str)
+ references = { }
+ lpegmatch(rparser,str)
+end
+
+-- local reftest = [[
+-- [1]: <http://example.com/>
+-- [3]:http://example.com/ (Optional Title Here)
+-- [2]: http://example.com/ 'Optional Title Here'
+-- [a]: http://example.com/ "Optional *oeps* Title Here"
+-- ]]
+--
+-- local linktest = [[
+-- [This link] (http://example.net/)
+-- [an example] (http://example.com/ "Title")
+-- [an example][1]
+-- [an example] [2]
+-- ]]
+--
+-- lpeg.match((define_reference_parser+1)^0,reftest)
+--
+-- inspect(references)
+--
+-- lpeg.match((direct_link_parser/print + indirect_link_parser/print + 1)^0,linktest)
+
+---------------------------------------------------------------------------------------------
+
+local blocktags = table.tohash {
+ "address", "blockquote" , "center", "dir", "div", "p", "pre",
+ "li", "ol", "ul", "dl", "dd",
+ "form", "fieldset", "isindex", "menu", "noframes", "frameset",
+ "h1", "h2", "h3", "h4", "h5", "h6",
+ "hr", "ht", "script", "noscript",
+ "table", "tbody", "tfoot", "thead", "th", "td", "tr",
+}
+
+----- htmlattributevalue = squote * C((any - (blankline + squote))^0) * squote
+----- + dquote * C((any - (blankline + dquote))^0) * dquote
+----- + (any - S("\t >"))^1 -- any - tab - space - more
+----- htmlattribute = (alphanumeric + S("_-"))^1 * spnl * (equal * spnl * htmlattributevalue)^-1 * spnl
+----- htmlcomment = P("<!--") * (any - P("-->"))^0 * P("-->")
+
+----- htmltag = less * spnl * slash^-1 * alphanumeric^1 * spnl * htmlattribute^0 * slash^-1 * spnl * more
+-----
+----- blocktag = Cmt(C(alphanumeric^1), function(s,i,a) return blocktags[lower(a)] and i, a end)
+-----
+----- openblocktag = less * Cg(blocktag, "opentag") * spnl * htmlattribute^0 * more
+----- closeblocktag = less * slash * Cmt(C(alphanumeric^1) * Cb("opentag"), function(s,i,a,b) return lower(a) == lower(b) and i end) * spnl * more
+----- selfclosingblocktag = less * blocktag * spnl * htmlattribute^0 * slash * more
+-----
+----- displayhtml = Cs { "HtmlBlock",
+----- InBlockTags = openblocktag * (V("HtmlBlock") + (any - closeblocktag))^0 * closeblocktag,
+----- HtmlBlock = C(V("InBlockTags") + selfclosingblocktag + htmlcomment),
+----- }
+-----
+----- inlinehtml = Cs(htmlcomment + htmltag)
+
+-- There is no reason to support crappy html, so we expect proper attributes.
+
+local htmlattributevalue = squote * C((any - (blankline + squote))^0) * squote
+ + dquote * C((any - (blankline + dquote))^0) * dquote
+local htmlattribute = (alphanumeric + S("_-"))^1 * spnl * equal * spnl * htmlattributevalue * spnl
+
+local htmlcomment = P("<!--") * (any - P("-->"))^0 * P("-->")
+local htmlinstruction = P("<?") * (any - P("?>" ))^0 * P("?>" )
+
+-- We don't care too much about matching elements and there is no reason why display elements could not
+-- have inline elements so the above should be patched then. Well, markdown mixed with html is not meant
+-- for anything else than webpages anyway.
+
+local blocktag = Cmt(C(alphanumeric^1), function(s,i,a) return blocktags[lower(a)] and i, a end)
+
+local openelement = less * alphanumeric^1 * spnl * htmlattribute^0 * more
+local closeelement = less * slash * alphanumeric^1 * spnl * more
+local emptyelement = less * alphanumeric^1 * spnl * htmlattribute^0 * slash * more
+
+local displaytext = (any - less)^1
+local inlinetext = displaytext / nestedparser
+
+local displayhtml = #(less * blocktag * spnl * htmlattribute^0 * more)
+ * Cs { "HtmlBlock",
+ InBlockTags = openelement * (V("HtmlBlock") + displaytext)^0 * closeelement,
+ HtmlBlock = (V("InBlockTags") + emptyelement + htmlcomment + htmlinstruction),
+ }
+
+local inlinehtml = Cs { "HtmlBlock",
+ InBlockTags = openelement * (V("HtmlBlock") + inlinetext)^0 * closeelement,
+ HtmlBlock = (V("InBlockTags") + emptyelement + htmlcomment + htmlinstruction),
+ }
+
+---------------------------------------------------------------------------------------------
+
+local hexentity = ampersand * hash * S("Xx") * C(hexdigit ^1) * semicolon
+local decentity = ampersand * hash * C(digit ^1) * semicolon
+local tagentity = ampersand * C(alphanumeric^1) * semicolon
+
+---------------------------------------------------------------------------------------------
+
+-- --[[
+
+local escaped = {
+ ["{" ] = "",
+ ["}" ] = "",
+ ["$" ] = "",
+ ["&" ] = "",
+ ["#" ] = "",
+ ["~" ] = "",
+ ["|" ] = "",
+ ["%%"] = "",
+ ["\\"] = "",
+}
+
+for k, v in next, escaped do
+ escaped[k] = "\\char" .. utfbyte(k) .. "{}"
+end
+
+local function c_string(s) -- has to be done more often
+ return (gsub(s,".",escaped))
+end
+
+local c_linebreak = "\\crlf\n" -- is this ok?
+local c_space = " "
+
+local function c_paragraph(c)
+ return c .. "\n\n" -- { "\\startparagraph ", c, " \\stopparagraph\n" }
+end
+
+local function listitem(c)
+ return format("\n\\startitem\n%s\n\\stopitem\n",nestedparser(c))
+end
+
+local function c_tightbulletlist(c)
+ return format("\n\\startmarkdownitemize[packed]\n%s\\stopmarkdownitemize\n",c)
+end
+
+local function c_loosebulletlist(c)
+ return format("\n\\startmarkdownitemize\n\\stopmarkdownitemize\n",c)
+end
+
+local function c_tightorderedlist(c)
+ return format("\n\\startmarkdownitemize[n,packed]\n%s\\stopmarkdownitemize\n",c)
+end
+
+local function c_looseorderedlist(c)
+ return format("\n\\startmarkdownitemize[n]\n%s\\stopmarkdownitemize\n",c)
+end
+
+local function c_inline_html(content)
+ nofhtmlblobs = nofhtmlblobs + 1
+ return format("\\markdowninlinehtml{%s}",content)
+end
+
+local function c_display_html(content)
+ nofhtmlblobs = nofhtmlblobs + 1
+ return format("\\startmarkdowndisplayhtml\n%s\n\\stopmarkdowndisplayhtml",content)
+end
+
+local function c_emphasis(c)
+ return format("\\markdownemphasis{%s}",c)
+end
+
+local function c_strong(c)
+ return format("\\markdownstrong{%s}",c)
+end
+
+local function c_blockquote(c)
+ return format("\\startmarkdownblockquote\n%s\\stopmarkdownblockquote\n",nestedparser(c))
+end
+
+local function c_verbatim(c)
+ return format("\\startmarkdowntyping\n%s\\stopmarkdowntyping\n",c)
+end
+
+local function c_code(c)
+ return format("\\markdowntype{%s}",c)
+end
+
+local levels = { "", "", "", "", "", "" }
+
+local function c_start_document()
+ levels = { "", "", "", "", "", "" }
+ return ""
+end
+
+local function c_stop_document()
+ return concat(levels,"\n") or ""
+end
+
+local function c_heading(level,c)
+ if level > #levels then
+ level = #levels
+ end
+ local finish = concat(levels,"\n",level) or ""
+ for i=level+1,#levels do
+ levels[i] = ""
+ end
+ levels[level] = "\\stopstructurelevel"
+ return format("%s\\startstructurelevel[markdown][title={%s}]\n",finish,c)
+end
+
+local function c_hrule()
+ return "\\markdownrule\n"
+end
+
+local function c_link(lab,src,tit)
+ return format("\\goto{%s}[url(%s)]",nestedparser(lab),src)
+end
+
+local function c_image(lab,src,tit)
+ return format("\\externalfigure[%s]",src)
+end
+
+local function c_email_link(address)
+ return format("\\goto{%s}[url(mailto:%s)]",c_string(address),address)
+end
+
+local function c_url_link(url)
+ return format("\\goto{%s}[url(%s)]",c_string(url),url)
+end
+
+local function f_heading(c,n)
+ return c_heading(n,c)
+end
+
+local function c_hex_entity(s)
+ return utfchar(tonumber(s,16))
+end
+
+local function c_dec_entity(s)
+ return utfchar(tonumber(s))
+end
+
+local function c_tag_entity(s)
+ return s -- we can use the default resolver
+end
+
+--]]
+
+---------------------------------------------------------------------------------------------
+
+--[[
+
+local escaped = {
+ ["<"] = "&lt;",
+ [">"] = "&gt;",
+ ["&"] = "&amp;",
+ ['"'] = "&quot;",
+}
+
+local function c_string(s) -- has to be done more often
+ return (gsub(s,".",escaped))
+end
+
+local c_linebreak = "<br/>"
+local c_space = " "
+
+local function c_paragraph(c)
+ return format("<p>%s</p>\n", c)
+end
+
+local function listitem(c)
+ return format("<li>%s</li>",nestedparser(c))
+end
+
+local function c_tightbulletlist(c)
+ return format("<ul>\n%s\n</ul>\n",c)
+end
+
+local function c_loosebulletlist(c)
+ return format("<ul>\n%s\n</ul>\n",c)
+end
+
+local function c_tightorderedlist(c)
+ return format("<ol>\n%s\n</ol>\n",c)
+end
+
+local function c_looseorderedlist(c)
+ return format("<ol>\n%s\n</ol>\n",c)
+end
+
+local function c_inline_html(content)
+ nofhtmlblobs = nofhtmlblobs + 1
+ return content
+end
+
+local function c_display_html(content)
+ nofhtmlblobs = nofhtmlblobs + 1
+ return format("\n%s\n",content)
+end
+
+local function c_emphasis(c)
+ return format("<em>%s</em>",c)
+end
+
+local function c_strong(c)
+ return format("<strong>%s</strong>",c)
+end
+
+local function c_blockquote(c)
+ return format("<blockquote>\n%s\n</blockquote>",nestedparser(c))
+end
+
+local function c_verbatim(c)
+ return format("<pre><code>%s</code></pre>",c)
+end
+
+local function c_code(c)
+ return format("<code>%s</code>",c)
+end
+
+local c_start_document = ""
+local c_stop_document = ""
+
+local function c_heading(level,c)
+ return format("<h%d>%s</h%d>\n",level,c,level)
+end
+
+local function c_hrule()
+ return "<hr/>\n"
+end
+
+local function c_link(lab,src,tit)
+ local titattr = #tit > 0 and format(" title=%q",tit) or ""
+ return format("<a href=%q%s>%s</a>",src,titattr,nestedparser(lab))
+end
+
+local function c_image(lab,src,tit)
+ return format("<img href=%q title=%q>%s</a>",src,tit,nestedparser(lab))
+end
+
+local function c_email_link(address)
+ return format("<a href=%q>%s</a>","mailto:",address,c_escape(address))
+end
+
+local function c_url_link(url)
+ return format("<a href=%q>%s</a>",url,c_string(url))
+end
+
+local function f_heading(c,n)
+ return c_heading(n,c)
+end
+
+local function c_hex_entity(s)
+ return utfchar(tonumber(s,16))
+end
+
+local function c_dec_entity(s)
+ return utfchar(tonumber(s))
+end
+
+local function c_tag_entity(s)
+ return format("&%s;",s)
+end
+
+--]]
+
+---------------------------------------------------------------------------------------------
+
+local Str = normalchar^1 / c_string
+local Space = spacechar^1 / c_space
+local Symbol = specialchar / c_string
+local Code = inticks / c_code
+
+local HeadingStart = C(hash * hash^-5) / length
+local HeadingStop = optionalspace * hash^0 * optionalspace * newline * blanklines
+local HeadingLevel = equal^3 * Cc(1)
+ + dash ^3 * Cc(2)
+
+local NormalEndline = optionalspace * newline * -(
+ blankline
+ + more
+ + HeadingStart
+ + ( line * (P("===")^3 + P("---")^3) * newline )
+ ) / c_space
+
+local LineBreak = P(" ") * NormalEndline / c_linebreak
+
+local TerminalEndline = optionalspace * newline * eof / ""
+
+local Endline = LineBreak
+ + TerminalEndline
+ + NormalEndline
+
+local AutoLinkUrl = less * C(alphanumeric^1 * P("://") * (any - (newline + more))^1) * more / c_url_link
+local AutoLinkEmail = less * C((alphanumeric + S("-_+"))^1 * P("@") * (any - (newline + more))^1) * more / c_email_link
+
+local DirectLink = direct_link_parser / c_link
+local IndirectLink = indirect_link_parser / c_link
+
+local ImageLink = exclamation * (direct_link_parser + indirect_link_parser) / c_image -- we can combine this with image ... smaller lpeg
+
+local UlOrStarLine = asterisk^4
+ + underscore^4
+ + (spaces * S("*_")^1 * #spaces) / c_string
+
+local EscapedChar = P("\\") * C(P(1 - newline)) / c_string
+
+local InlineHtml = inlinehtml / c_inline_html
+local DisplayHtml = displayhtml / c_display_html
+local HtmlEntity = hexentity / c_hex_entity
+ + decentity / c_dec_entity
+ + tagentity / c_tag_entity
+
+local NestedList = Cs(optionallyindentedline - (bullet + enumerator))^1 / nestedparser
+
+local ListBlockLine = -blankline * -(indent^-1 * (bullet + enumerator)) * optionallyindentedline
+
+local Verbatim = Cs(blanklines * (indentedline - blankline)^1) / c_verbatim
+ * (blankline^1 + eof) -- not really needed, probably capture trailing? we can do that beforehand
+
+local Blockquote = Cs((
+ ((nonindentspace * more * space^-1)/"" * linechar^0 * newline)^1
+ * ((linechar - blankline)^1 * newline)^0
+ * blankline^0
+ )^1) / c_blockquote
+
+local HorizontalRule = (lineof_asterisks + lineof_dashes + lineof_underscores) / c_hrule
+
+local Reference = define_reference_parser / ""
+
+-- could be a mini grammar
+
+local ListBlock = line * ListBlockLine^0
+local ListContinuationBlock = blanklines * indent * ListBlock
+local ListItem = Cs(ListBlock * (NestedList + ListContinuationBlock^0)) / listitem
+
+---- LeadingLines = blankline^0 / ""
+---- TrailingLines = blankline^1 * #(any) / "\n"
+
+syntax = Cs { "Document",
+
+ Document = V("Display")^0,
+
+ Display = blankline -- ^1/"\n"
+ + Blockquote
+ + Verbatim
+ + Reference
+ + HorizontalRule
+ + HeadingStart * optionalspace * Cs((V("Inline") - HeadingStop)^1) * HeadingStop / c_heading
+ + Cs((V("Inline") - Endline)^1) * newline * HeadingLevel * newline * blanklines / f_heading
+ + Cs((bullet /"" * ListItem)^1) * blanklines * -bullet / c_tightbulletlist
+ + Cs((bullet /"" * ListItem * C(blanklines))^1) / c_loosebulletlist
+ + Cs((enumerator /"" * ListItem)^1) * blanklines * -enumerator / c_tightorderedlist
+ + Cs((enumerator /"" * ListItem * C(blanklines))^1) / c_looseorderedlist
+ + DisplayHtml
+ + nonindentspace * Cs(V("Inline")^1)* newline * blankline^1 / c_paragraph
+ + V("Inline")^1,
+
+ Inline = Str
+ + Space
+ + Endline
+ + UlOrStarLine -- still needed ?
+ + doubleasterisks * -spaceornewline * Cs((V("Inline") - doubleasterisks )^1) * doubleasterisks / c_strong
+ + doubleunderscores * -spaceornewline * Cs((V("Inline") - doubleunderscores)^1) * doubleunderscores / c_strong
+ + asterisk * -spaceornewline * Cs((V("Inline") - asterisk )^1) * asterisk / c_emphasis
+ + underscore * -spaceornewline * Cs((V("Inline") - underscore )^1) * underscore / c_emphasis
+ + ImageLink
+ + DirectLink
+ + IndirectLink
+ + AutoLinkUrl
+ + AutoLinkEmail
+ + Code
+ + InlineHtml
+ + HtmlEntity
+ + EscapedChar
+ + Symbol,
+
+}
+
+---------------------------------------------------------------------------------------------
+
+local function convert(str)
+ nofruns = nofruns + 1
+ nofbytes = nofbytes + #str
+ statistics.starttiming(markdown)
+ referenceparser(str)
+ local result = c_start_document() .. nestedparser(str) .. c_stop_document()
+ statistics.stoptiming(markdown)
+ return result
+end
+
+markdown.convert = convert
+
+function markdown.typesetstring(data)
+ if data and data ~= "" then
+ local result = convert(data)
+ context.viafile(result)
+ end
+end
+
+function markdown.typesetbuffer(name)
+ markdown.typesetstring(buffers.getcontent(name))
+end
+
+function markdown.typesetfile(name)
+ local fullname = resolvers.findctxfile(name)
+ if fullname and fullname ~= "" then
+ markdown.typesetstring(io.loaddata(fullname))
+ end
+end
+
+statistics.register("markdown",function()
+ if nofruns > 0 then
+ return format("%s bytes converted, %s runs, %s html blobs, %s seconds used",
+ nofbytes, nofruns, nofhtmlblobs, statistics.elapsedtime(markdown))
+ end
+end)
+
+---------------------------------------------------------------------------------------------
+
+--~ context.starttext()
+--~ moduledata.markdown.convert(str)
+--~ context.stoptext()
+
+if not tex.jobname then
+
+ local one = [[
+Test *123*
+==========
+
+<b>BOLD *BOLD* BOLD</b>
+
+<pre>PRE <b>PRE</b> PRE</pre>
+
+
+* Test
+** Test
+* Test1
+ * Test2
+* Test
+
+Test
+====
+
+> test
+> test **123** *123*
+> test `code`
+
+test
+
+Test
+====
+
+> test
+> test
+> test
+
+test
+oeps
+
+more
+
+ code
+ code
+
+oeps
+
+[an example][a]
+
+[an example] [2]
+
+[a]: http://example.com/ "Optional *oeps* Title Here"
+[2]: http://example.com/ 'Optional Title Here'
+[3]: http://example.com/ (Optional Title Here)
+
+[an example][a]
+
+[an example] [2]
+
+[an [tricky] example](http://example.com/ "Title")
+
+[This **xx** link](http://example.net/)
+ ]]
+
+-- This snippet takes some 4 seconds in the original parser (the one that is
+-- a bit clearer from the perspective of grammars but somewhat messy with
+-- respect to the captures. In the above parser it takes .1 second. Also,
+-- in the later case only memory is the limit.
+
+ local two = [[
+Test
+====
+* Test
+** Test
+* Test
+** Test
+* Test
+
+Test
+====
+
+> test
+> test
+> test
+
+test
+
+Test
+====
+
+> test
+> test
+> test
+
+test
+ ]]
+
+ local function test(str)
+ local n = 1 -- 000
+ local t = os.clock()
+ local one = convert(str)
+ -- print("runtime",1,#str,#one,os.clock()-t)
+ str = string.rep(str,n)
+ local t = os.clock()
+ local two = convert(str)
+ print(two)
+ -- print("runtime",n,#str,#two,os.clock()-t)
+ -- print(format("==============\n%s\n==============",one))
+ end
+
+ -- test(one)
+ -- test(two)
+ -- test(io.read("*all"))
+
+
+end
diff --git a/Master/texmf-dist/tex/context/base/m-markdown.mkiv b/Master/texmf-dist/tex/context/base/m-markdown.mkiv
new file mode 100644
index 00000000000..6e003651309
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/m-markdown.mkiv
@@ -0,0 +1,88 @@
+%D \module
+%D [ file=x-markdown,
+%D version=2011.07.19,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Processing MarkDown,
+%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 Modules / MarkDown Renderer}
+
+%D This module deals with markdown which is a document encoding that
+%D some \CONTEXT\ like much. It reminds me of the kind of minimal coding
+%D we used before we ran into \TEX\ and were using a somewhat simple
+%D rendering (pagination, etc) of documents. As I'm no user myself, it
+%D is up to others to provide documentation and examples.
+
+\registerctxluafile{m-markdown}{1.001}
+
+\unprotect
+
+% basic interface
+
+\definebuffer[markdown]
+
+\unexpanded\def\stopmarkdown
+ {\ctxlua{moduledata.markdown.typesetbuffer("\thedefinedbuffer{markdown}")}}
+
+\unexpanded\def\processmarkdownfile#1% maybe [] or both
+ {\ctxlua{moduledata.markdown.typesetfile("#1")}}
+
+\unexpanded\def\markdown#1% maybe [] or both
+ {\ctxlua{moduledata.markdown.typesetstring(\!!bs#1\!!es)}}
+
+% commands
+
+\defineitemgroup
+ [markdownitemize]
+
+\definetyping
+ [markdowntyping]
+
+\definetype
+ [markdowntype]
+
+\definetype
+ [markdowninlinehtml]
+
+\definetyping
+ [markdowndisplayhtml]
+
+\definedelimitedtext
+ [markdownblockquote]
+ [quotation]
+
+\definehighlight
+ [markdownemphasis]
+ [style=\em]
+
+\definehighlight
+ [markdownstrong]
+ [style=\bf]
+
+\definestructurelevels
+ [markdown]
+ [\v!chapter,
+ \v!section,
+ \v!subsection,
+ \v!subsubsection,
+ \v!subsubsubsection,
+ \v!subsubsubsubsection]
+
+\unexpanded\def\markdownrule
+ {\hairline\par}
+
+\protect
+
+\continueifinputfile{m-markdown.mkiv}
+
+\starttext
+ \startmarkdown
+ % some examples needed
+ \stopmarkdown
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/m-mathcrap.mkiv b/Master/texmf-dist/tex/context/base/m-mathcrap.mkiv
index 0c187155b79..25efd2d5de3 100644
--- a/Master/texmf-dist/tex/context/base/m-mathcrap.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-mathcrap.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Math Crap,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
@@ -36,9 +36,9 @@
\fi
\installanddefineactivecharacter "2070 {\mathunicodesupercrap 0}
-\installanddefineactivecharacter "00B9 {\mathunicodesupercrap 1}â‚€
-\installanddefineactivecharacter "00B2 {\mathunicodesupercrap 2}â‚€
-\installanddefineactivecharacter "00B3 {\mathunicodesupercrap 3}â‚€
+\installanddefineactivecharacter "00B9 {\mathunicodesupercrap 1}
+\installanddefineactivecharacter "00B2 {\mathunicodesupercrap 2}
+\installanddefineactivecharacter "00B3 {\mathunicodesupercrap 3}
\installanddefineactivecharacter "2074 {\mathunicodesupercrap 4}
\installanddefineactivecharacter "2075 {\mathunicodesupercrap 5}
\installanddefineactivecharacter "2076 {\mathunicodesupercrap 6}
diff --git a/Master/texmf-dist/tex/context/base/m-mkivhacks.mkiv b/Master/texmf-dist/tex/context/base/m-mkivhacks.mkiv
index 0e959110e0d..3ed002e1d50 100644
--- a/Master/texmf-dist/tex/context/base/m-mkivhacks.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-mkivhacks.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Temporary Compatilibility Hacks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-morse.mkvi b/Master/texmf-dist/tex/context/base/m-morse.mkvi
index d106acfdefb..aba83bb2d8a 100644
--- a/Master/texmf-dist/tex/context/base/m-morse.mkvi
+++ b/Master/texmf-dist/tex/context/base/m-morse.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Morse,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-narrowtt.tex b/Master/texmf-dist/tex/context/base/m-narrowtt.tex
index 2e11b99ad19..129bf270b9d 100644
--- a/Master/texmf-dist/tex/context/base/m-narrowtt.tex
+++ b/Master/texmf-dist/tex/context/base/m-narrowtt.tex
@@ -5,7 +5,7 @@
%D subtitle=Narrow Verbatim,
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-newmat.tex b/Master/texmf-dist/tex/context/base/m-newmat.tex
index 3fb75df5d3e..202fec76ff1 100644
--- a/Master/texmf-dist/tex/context/base/m-newmat.tex
+++ b/Master/texmf-dist/tex/context/base/m-newmat.tex
@@ -5,7 +5,7 @@
%D subtitle=AMS-like math extensions,
%D author={Taco Hoekwater \& Hans Hagen},
%D date=\currentdate,
-%D copyright={PRAGMA / Taco Hoekwater}]
+%D copyright={Taco Hoekwater \& Hans Hagen}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
diff --git a/Master/texmf-dist/tex/context/base/m-ntb-to-xtb.mkiv b/Master/texmf-dist/tex/context/base/m-ntb-to-xtb.mkiv
new file mode 100644
index 00000000000..55b4ab25926
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/m-ntb-to-xtb.mkiv
@@ -0,0 +1,5 @@
+\loadmkvifile{tabl-xnt}
+
+\mapTABLEtoxtable
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/m-pdfsnc.mkii b/Master/texmf-dist/tex/context/base/m-pdfsnc.mkii
index da59ab5d800..12e2e2d68ba 100644
--- a/Master/texmf-dist/tex/context/base/m-pdfsnc.mkii
+++ b/Master/texmf-dist/tex/context/base/m-pdfsnc.mkii
@@ -5,7 +5,7 @@
%D subtitle=Editor Synchronization,
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-pictex.tex b/Master/texmf-dist/tex/context/base/m-pictex.tex
index 71b0a78fe72..27dc6a43914 100644
--- a/Master/texmf-dist/tex/context/base/m-pictex.tex
+++ b/Master/texmf-dist/tex/context/base/m-pictex.tex
@@ -5,7 +5,7 @@
%D subtitle=\PICTEX\ Loading Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-pstricks.lua b/Master/texmf-dist/tex/context/base/m-pstricks.lua
index ab271908496..7f795feac6b 100644
--- a/Master/texmf-dist/tex/context/base/m-pstricks.lua
+++ b/Master/texmf-dist/tex/context/base/m-pstricks.lua
@@ -50,7 +50,7 @@ end
function moduledata.pstricks.process(n)
graphics = graphics + 1
- local name = string.format("%s-pstricks-%04i",tex.jobname,graphics)
+ local name = format("%s-pstricks-%04i",tex.jobname,graphics)
local data = buffers.collectcontent("def-"..n)
local tmpfile = name .. ".tmp"
local epsfile = name .. ".ps"
diff --git a/Master/texmf-dist/tex/context/base/m-pstricks.mkii b/Master/texmf-dist/tex/context/base/m-pstricks.mkii
index 3ada9e07ec7..bdcf13b24d6 100644
--- a/Master/texmf-dist/tex/context/base/m-pstricks.mkii
+++ b/Master/texmf-dist/tex/context/base/m-pstricks.mkii
@@ -5,7 +5,7 @@
%D subtitle=\PSTRICKS\ Connections,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-pstricks.mkiv b/Master/texmf-dist/tex/context/base/m-pstricks.mkiv
index c976982a6a0..421607aafe9 100644
--- a/Master/texmf-dist/tex/context/base/m-pstricks.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-pstricks.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\PSTRICKS\ Connections,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,18 +13,6 @@
\registerctxluafile{m-pstricks}{}
-%D \startbuffer
-%D \usePSTRICKSmodule[pst-barcode]
-%D
-%D \startPSTRICKS
-%D \pspicture(-4mm,-1mm)(38mm,26mm)
-%D \psbarcode{9781860742712}{includetext guardwhitespace}{ean13}%
-%D \endpspicture
-%D \stopPSTRICKS
-%D \stopbuffer
-%D
-%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
-
\unprotect
% best we can make a special colors module
@@ -63,4 +51,15 @@
\let\stopPSTRICKS\processPSTRICKS
+%D \starttyping
+%D \usemodule[pstricks]
+%D \usePSTRICKSmodule[pst-barcode]
+%D
+%D \startPSTRICKS
+%D \pspicture(-4mm,-1mm)(38mm,26mm)
+%D \psbarcode{9781860742712}{includetext guardwhitespace}{ean13}%
+%D \endpspicture
+%D \stopPSTRICKS
+%D \stoptyping
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/m-punk.mkiv b/Master/texmf-dist/tex/context/base/m-punk.mkiv
index 71158d2a638..23b477cb677 100644
--- a/Master/texmf-dist/tex/context/base/m-punk.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-punk.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Punk Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -174,7 +174,7 @@ fonts.definers.methods.install( "punkboldslanted", {
{ "metafont", "mfplain", "punkfont-boldslanted.mp", 10 },
} )
-typesetters.cases.actions[99] = function(current)
+typesetters.cases.register("RandomPunk", function(current)
local used = fontdata[current.font].variants
if used then
local f = math.random(1,#used)
@@ -183,7 +183,7 @@ typesetters.cases.actions[99] = function(current)
else
return current, false
end
-end
+end)
metapost.characters.flusher = flusher
@@ -206,7 +206,7 @@ statistics.register("metapost font loading",function()
end)
\stopluacode
-\unexpanded\def\EnableRandomPunk {\setcharactercasing[99]}
+\unexpanded\def\EnableRandomPunk {\setcharactercasing[RandomPunk]}
\unexpanded\def\RandomPunk {\groupedcommand\EnableRandomPunk\donothing}
\unexpanded\def\StartRandomPunk {\begingroup\EnableRandomPunk}
\unexpanded\def\StopRandomPunk {\endgroup}
diff --git a/Master/texmf-dist/tex/context/base/m-quest.tex b/Master/texmf-dist/tex/context/base/m-quest.tex
deleted file mode 100644
index d20c86c93b0..00000000000
--- a/Master/texmf-dist/tex/context/base/m-quest.tex
+++ /dev/null
@@ -1,232 +0,0 @@
-%D \module
-%D [ file=m-invull,
-%D version=1995.01.10,
-%D title=\CONTEXT\ Extra Modules,
-%D subtitle=Exercise,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-%I Invuloefeningen kunnen worden vormgegeven met het
-%I de commando's:
-%I
-%I \definieerinvulwoord[trefwoord]{woord,woord}
-%I \invulwoord[trefwoord]
-%I \invulwoord{woord,woord,...}
-%I
-%I Daarbij kan het een en ander worden ingesteld met
-%I
-%I \stelinvullenin[status=,nummer=,links=,rechts=,letter=]
-%P
-%I Er zijn drie manieren om woorden in te vullen. De meest
-%I eenvoudige is die waarbij de in te vullen woorden in de
-%I tekst staan.
-%I
-%I bla bla \invulwoord{een,alfa} bla bla bla bla bla bla
-%I bla bla bla bla bla bla bla bla \invulwoord{twee,beta}.
-%I
-%I De gezette tekst hangt af van de instellingen:
-%I
-%I [status=leeg] ________
-%I [status=vol,nummer=1] 'een' respectievelijk 'twee'
-%I [status=vol,nummer=2] 'alfa' respectievelijk 'beta'
-%I
-%I Het nummer heeft dus betrekking op het volgnummer in de
-%I opgegeven reeks.
-%P
-%I Bij de tweede manier worden eerste de alternatieven
-%I gedefinieerd:
-%I
-%I \definieerinvulwoord{een,alfa}
-%I \definieerinvulwoord{twee,beta}
-%I
-%I die vervolgens worden opgeroepen:
-%I
-%I bla \invulwoord[+] bla bla bla bla bla bla bla bla bla
-%I bla bla bla bla bla bla bla bla bla bla \invulwoord[+].
-%I
-%I De mogelijke instellingen komen overeen met die van de
-%I eerste manier.
-%P
-%I De derde manier is een variant op de tweede. Bij grote
-%I teksten kan men het overzicht kwijtraken. Het is daarom
-%I mogelijk 'logische' namen toe te kennen aan woorden.
-%I
-%I \definieerinvulwoord[a]{een,alfa}
-%I \definieerinvulwoord[b]{twee,beta}
-%I
-%I die vervolgens worden opgeroepen:
-%I
-%I bla \invulwoord[a] bla bla bla bla bla bla bla bla bla
-%I bla bla bla bla bla bla bla bla bla bla \invulwoord[b].
-%I
-%I Dit maakt het bovendien mogelijk woorden meerdere malen
-%I (in een willekeurige volgorde op te roepen:
-%I
-%I bla \invulwoord[a] bla \invulwoord[b] bla bla bla bla
-%I bla bla bla bla \invulwoord[b] bla bla \invulwoord[a].
-%P
-%I Bij [status=leeg] wordt een streep gezet die in breedte
-%I overeenkomt met het woord dat er eigenlijk hoort te
-%I staan. De ingevulde tekst komt visueel daardoor overeen
-%I met de in te vullen tekst, wat vergelijken vereenvoudigd.
-%I
-%I Met [status=reset] worden enkele tellers weer op 0 gezet.
-%I Dit kan nodig zijn als meerdere invuloefeningen in een
-%I tekst worden gezet.
-%I
-%I Als \versie[voorlopig] is ingesteld, worden bij invullers
-%I zonder logische namen tussen haakjes de volgnummers
-%I getoond.
-
-%S \startsetup
-%S \command
-%S [stelinvullenin]
-%S \type
-%S [\c!vars!]
-%S \variable
-%S [\c!letter]
-%S [\v!normaal,\v!vet,\v!schuin,\v!vetschuin,\v!type,\v!kap,
-%S \v!klein...,\c!command!]
-%S [\v!vet]
-%S \variable
-%S [\c!links]
-%S [\c!text!]
-%S []
-%S \variable
-%S [\c!rechts]
-%S [\c!text!]
-%S []
-%S \variable
-%S [\c!status]
-%S [\v!leeg,\v!vol,\v!reset]
-%S [\v!vol]
-%S \variable
-%S [\c!nummer]
-%S [\c!number!]
-%S [1]
-%S \variable
-%S [\c!lijn]
-%S [\v!aan,\v!uit]
-%S [\v!aan]
-%S \stopsetup
-
-%S \startsetup
-%S \command
-%S [invulwoord]
-%S \type
-%S [\c!ref!,\c!opt!\c!val!\c!opt!\c!args!]
-%S \value
-%S [\c!text!]
-%S \stopsetup
-
-%S \startsetup
-%S \command
-%S [definieerinvulwoord]
-%S \type
-%S [\c!ref!,\c!opt!\c!val!\c!args!]
-%S \value
-%S [\c!text!]
-%S \stopsetup
-
-% Mogelijke uitbreidingen
-%
-% - [breedte=<maat>,passend,ruim]
-% - invullijst met nummers
-% - weergeven lijst tijdens definitie blokkeren
-% - door elkaar definieren
-
-\unprotect
-
-\definesystemvariable {iv}
-
-\definereferenceconstant {fillin} {:iv:}
-
-\newcount\invulteller \newcount\invulput \newcount\invulget
-
-\def\stelinvullenin
- {\dosingleargument\dostelinvullenin}
-
-\def\dostelinvullenin[#1]%
- {\getparameters[\??iv][#1]%
- \doif\@@ivstate\v!reset
- {\global\invulput\zerocount
- \global\invulget\zerocount
- \let\@@ivstate\empty}}
-
-\def\definieerinvulwoord
- {\dosingleempty\dodefinieerinvulwoord}
-
-\def\dodefinieerinvulwoord[#1]#2%
- {\iffirstargument
- \setgvalue{\r!fillin#1}{\simpleinvulwoord{#2}}%
- \else
- \global\advance\invulput \plusone
- \setgvalue{\r!fillin\the\invulput}{\simpleinvulwoord{#2}}%
- \fi
- \doifconcepttracing
- {\ifnum\invulput>\zerocount
- \setbox\scratchbox\hbox{~\ttx(\the\invulput)}%
- \wd\scratchbox\zeropoint
- \box\scratchbox
- \par
- \fi}}
-
-\def\dosimpleinvulwoord#1%
- {\ifnum\@@ivnumber>\zerocount \advance\invulteller \plusone \fi
- \ifnum\invulteller=\@@ivnumber\relax
- \bgroup
- \doconvertfont\@@ivstyle
- {\@@ivleft
- \doifelse\@@ivstate\v!empty
- {\doifelse\@@ivrule\v!on\leeginvulwoord\geeninvulwoord}
- {\doifelse\@@ivrule\v!on\underbar \firstofoneargument}%
- {#1}%
- \@@ivright}%
- \egroup
- \fi}%
-
-\def\simpleinvulwoord#1%
- {\ifnum\@@ivnumber>0
- \invulteller\zerocount
- \processcommalist[#1]\dosimpleinvulwoord
- \else
- \dosimpleinvulwoord{#1}%
- \fi}
-
-\def\complexinvulwoord[#1]%
- {\bgroup
- \doifsomething{#1}
- {\global\advance\invulget \plusone
- \doconvertfont\@@ivstyle
- {\@@ivleft\getvalue{\r!fillin\the\invulget}\@@ivright}}
- {\doconvertfont\@@ivstyle
- {\@@ivleft\getvalue{\r!fillin #1}\@@ivright}}%
- \egroup}
-
-\definecomplexorsimple\invulwoord
-
-\def\leeginvulwoord#1%
- {{\let\redounderbar\dodounderbar
- \def\dodounderbar##1{\redounderbar{\hphantom{##1}}}%
- \underbar{#1}}}
-
-\def\geeninvulwoord#1%
- {{\def\dodounderbar##1{\hphantom{##1}}%
- \underbar{#1}}}
-
-% when nummer > 0, then commalist processing; beware of $(1,2)$, use { } there
-
-\stelinvullenin
- [\c!number=0,
- \c!style=\v!bold,
- \c!rule=\v!on,
- \c!left=,
- \c!right=,
- \c!state=]
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/m-r.tex b/Master/texmf-dist/tex/context/base/m-r.tex
index bf7b07a14d0..ac895905ce8 100644
--- a/Master/texmf-dist/tex/context/base/m-r.tex
+++ b/Master/texmf-dist/tex/context/base/m-r.tex
@@ -5,7 +5,7 @@
%D subtitle=R Support,
%D author={Johan Sandblom \& Hans Hagen},
%D date=\currentdate,
-%D copyright={PRAGMA / Johan Sandblom}]
+%D copyright={Johan Sandblom \& Hans Hagen}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
diff --git a/Master/texmf-dist/tex/context/base/m-spreadsheet.mkiv b/Master/texmf-dist/tex/context/base/m-spreadsheet.mkiv
index 49f59ded9ef..8392140960e 100644
--- a/Master/texmf-dist/tex/context/base/m-spreadsheet.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-spreadsheet.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Spreadsheets,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-steps.lua b/Master/texmf-dist/tex/context/base/m-steps.lua
new file mode 100644
index 00000000000..97759b79917
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/m-steps.lua
@@ -0,0 +1,227 @@
+if not modules then modules = { } end modules ['x-flow'] = {
+ version = 1.001,
+ comment = "companion to m-flow.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- when we can resolve mpcolor at the lua end we will use metapost.graphic(....) directly
+
+moduledata.steps = moduledata.steps or { }
+
+local points = number.points -- number.pt
+local variables = interfaces.variables
+
+local trace_charts = false
+
+local defaults = {
+ chart = {
+ dx = 10*65436,
+ dy = 10*65436,
+ },
+ cell = {
+ alternative = 1,
+ offset = 2*65436,
+ rulethickness = 65436,
+ framecolor = "blue",
+ backgroundcolor = "gray",
+ },
+ text = {
+ alternative = 1,
+ offset = 2*65436,
+ distance = 4*65436,
+ rulethickness = 65436,
+ framecolor = "red",
+ backgroundcolor = "gray",
+ },
+ line = {
+ alternative = 1,
+ rulethickness = 65436,
+ height = 30*65436,
+ distance = 10*65436,
+ offset = 5*65436,
+ color = "green",
+ },
+}
+
+-- todo : name (no name then direct)
+-- maybe: includes
+-- maybe: flush ranges
+
+local charts = { }
+local steps = { }
+
+function commands.step_start_chart(name)
+ name = name or ""
+ steps = { }
+ charts[name] = {
+ steps = steps,
+ }
+end
+
+function commands.step_stop_chart()
+end
+
+function commands.step_make_chart(settings)
+ local chartsettings = settings.chart
+ if not chartsettings then
+ print("no chart")
+ return
+ end
+ local chartname = chartsettings.name
+ if not chartname then
+ print("no name given")
+ return
+ end
+ local chart = charts[chartname]
+ if not chart then
+ print("no such chart",chartname)
+ return
+ end
+ local steps = chart.steps or { }
+ --
+ table.setmetatableindex(settings,defaults)
+ --
+ if trace_charts then
+ inspect(steps)
+ end
+ --
+ local textsettings = settings.text
+ local cellsettings = settings.cell
+ local linesettings = settings.line
+ --
+ context.startMPcode()
+ context("if unknown context_cell : input mp-step.mpiv ; fi ;")
+ context("step_begin_chart ;")
+ --
+ if chartsettings.alternative == variables.vertical then
+ context("chart_vertical := true ;")
+ end
+ --
+ context("text_line_color := \\MPcolor{%s} ;", textsettings.framecolor)
+ context("text_line_width := %s ;", points(textsettings.rulethickness))
+ context("text_fill_color := \\MPcolor{%s} ;", textsettings.backgroundcolor)
+ context("text_offset := %s ;", points(textsettings.offset))
+ context("text_distance_set := %s ;", points(textsettings.distance))
+ --
+ context("cell_line_color := \\MPcolor{%s} ;", cellsettings.framecolor)
+ context("cell_line_width := %s ;", points(cellsettings.rulethickness))
+ context("cell_fill_color := \\MPcolor{%s} ;", cellsettings.backgroundcolor)
+ context("cell_offset := %s ;", points(cellsettings.offset))
+ context("cell_distance_x := %s ;", points(cellsettings.dx))
+ context("cell_distance_y := %s ;", points(cellsettings.dy))
+ --
+ context("line_line_color := \\MPcolor{%s} ;", linesettings.color)
+ context("line_line_width := %s ;", points(linesettings.rulethickness))
+ context("line_distance := %s ;", points(linesettings.distance))
+ context("line_offset := %s ;", points(linesettings.offset))
+ --
+ for i=1,#steps do
+ local step = steps[i]
+ context("step_begin_cell ;")
+ if step.cell_top ~= "" then
+ context('step_cell_top("%s") ;',string.strip(step.cell_top))
+ end
+ if step.cell_bot ~= "" then
+ context('step_cell_bot("%s") ;',string.strip(step.cell_bot))
+ end
+ if step.text_top ~= "" then
+ context('step_text_top("%s") ;',string.strip(step.text_top))
+ end
+ if step.text_mid ~= "" then
+ context('step_text_mid("%s") ;',string.strip(step.text_mid))
+ end
+ if step.text_bot ~= "" then
+ context('step_text_bot("%s") ;',string.strip(step.text_bot))
+ end
+ context("step_end_cell ;")
+ end
+ --
+ context("step_end_chart ;")
+ context.stopMPcode()
+end
+
+function commands.step_cells(top,bot)
+ steps[#steps+1] = {
+ cell_top = top or "",
+ cell_bot = bot or "",
+ text_top = "",
+ text_mid = "",
+ text_bot = "",
+ }
+end
+
+function commands.step_texts(top,bot)
+ if #steps > 0 then
+ steps[#steps].text_top = top or ""
+ steps[#steps].text_bot = bot or ""
+ end
+end
+
+function commands.step_cell(top)
+ steps[#steps+1] = {
+ cell_top = top or "",
+ cell_bot = "",
+ text_top = "",
+ text_mid = "",
+ text_bot = "",
+ }
+end
+
+function commands.step_text(top)
+ if #steps > 0 then
+ steps[#steps].text_top = top or ""
+ end
+end
+
+function commands.step_textset(left,middle,right)
+ if #steps > 0 then
+ steps[#steps].text_top = left or ""
+ steps[#steps].text_mid = middle or ""
+ steps[#steps].text_bot = right or ""
+ end
+end
+
+function commands.step_start_cell()
+ steps[#steps+1] = {
+ cell_top = "",
+ cell_bot = "",
+ text_top = "",
+ text_mid = "",
+ text_bot = "",
+ }
+end
+
+function commands.step_stop_cell()
+end
+
+function commands.step_text_top(str)
+ if #steps > 0 then
+ steps[#steps].text_top = str or ""
+ end
+end
+
+function commands.step_text_mid(str)
+ if #steps > 0 then
+ steps[#steps].text_mid = str or ""
+ end
+end
+
+function commands.step_text_bot(str)
+ if #steps > 0 then
+ steps[#steps].text_bot = str or ""
+ end
+end
+
+function commands.step_cell_top(str)
+ if #steps > 0 then
+ steps[#steps].cell_top = str or ""
+ end
+end
+
+function commands.step_cell_bot(str)
+ if #steps > 0 then
+ steps[#steps].cell_bot = str or ""
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/m-steps.tex b/Master/texmf-dist/tex/context/base/m-steps.mkii
index 55e13b97d3b..e6bd45548c3 100644
--- a/Master/texmf-dist/tex/context/base/m-steps.tex
+++ b/Master/texmf-dist/tex/context/base/m-steps.mkii
@@ -5,7 +5,7 @@
%D subtitle=Step Charts \& Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
@@ -146,7 +146,7 @@
%D \def\startSTEPchart%
%D {\bgroup
%D \startMPdrawing
-%D input mp-step ; begin_step_chart ;
+%D input mp-step.mpii ; begin_step_chart ;
%D \stopMPdrawing
%D \initializeSTEP
%D \let\cells\stepchartcells \def\cell{\cells{}}%
@@ -208,7 +208,7 @@
%D \resetMPdrawing
%D \advance\noftabpositions\plusone % begin of preroll
%D \startMPdrawing
-%D input mp-step ;
+%D input mp-step.mpii ;
%D begin_step_chart ;
%D \stopMPdrawing
%D \initializeSTEP
@@ -401,7 +401,7 @@
\resetMPdrawing
\doglobal\increment\currentstepchart
\startMPdrawing
- input mp-step ;
+ input mp-step.mpii ;
begin_step_chart ;
\stopMPdrawing
\initializeSTEP
@@ -682,7 +682,7 @@
\pushMPdrawing
\doglobal\increment\currentsteptable
\startMPdrawing
- input mp-step ;
+ input mp-step.mpii ;
begin_step_table ;
\stopMPdrawing
\initializeSTEP
@@ -809,7 +809,9 @@
\@@STELalternative, get_step_table_line(\cellcounter),
\@@STELrulethickness, \MPcolor{\@@STELcolor} ) )}
-\protect \endinput
+\protect
+
+\continueifinputfile{m-steps.tex}
% A simple paragraph-flow test:
@@ -830,6 +832,6 @@
\startnarrower \getbuffer \stopnarrower
-\placefigure[left]{}{} \getbuffer
+\placefigure[left]{}{\getbuffer}
\stoptext
diff --git a/Master/texmf-dist/tex/context/base/m-steps.mkvi b/Master/texmf-dist/tex/context/base/m-steps.mkvi
new file mode 100644
index 00000000000..a07ece3ae8d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/m-steps.mkvi
@@ -0,0 +1,382 @@
+%D \module
+%D [ file=m-steps,
+%D version=2011.10.07, % 2001.05.28,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Step Charts \& 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.
+
+% multiple texts?
+
+\registerctxluafile{m-steps}{}
+
+\unprotect
+
+\installcorenamespace {stepcharts}
+\installcorenamespace {steptables}
+\installcorenamespace {stepcells}
+\installcorenamespace {steptexts}
+\installcorenamespace {steplines}
+
+\installsimplecommandhandler \??stepcharts {STEPchart} \??stepcharts
+\installsimplecommandhandler \??steptables {STEPtable} \??steptables
+\installsimplecommandhandler \??stepcells {STEPcell} \??stepcells
+\installsimplecommandhandler \??steptexts {STEPtext} \??steptexts
+\installsimplecommandhandler \??steplines {STEPline} \??steplines
+
+\let\setupSTEPcharts\setupSTEPchart
+\let\setupSTEPtables\setupSTEPtable
+\let\setupSTEPcells \setupSTEPcell
+\let\setupSTEPtexts \setupSTEPtext
+\let\setupSTEPlines \setupSTEPline
+
+% numeric text_text_distance ; text_text_distance := 20pt ;
+% numeric step_distance ; step_distance := 20pt ;
+
+\setupSTEPcharts
+ [\c!alternative=\v!horizontal,
+ \c!before=\blank,
+ \c!after=\blank]
+% \c!offset=.15\bodyfontsize
+% \c!height=2ex
+
+% \setupSTEPtables
+% [\c!before=\blank,
+% \c!after=\blank,
+% \c!distance=.25em,
+% \c!voffset=1ex,
+% \c!method=1,
+% \c!width=4em,
+% \c!offset=.15\bodyfontsize]
+
+\setupSTEPcells
+ [\c!alternative=1, % TODO
+% \c!style=,
+% \c!color=,
+ \c!dx=\bodyfontsize,
+ \c!dy=\bodyfontsize,
+ \c!background=\v!color,
+ \c!backgroundcolor=STEPbackgroundcolor,
+ \c!rulethickness=.1\bodyfontsize,
+ \c!framecolor=STEPframecolor,
+ \c!offset=.25\bodyfontsize]
+
+\setupSTEPtexts
+ [\c!alternative=1, % TODO
+% \c!style=\v!smallbodyfont,
+% \c!color=,
+ \c!background=\v!color,
+ \c!backgroundcolor=STEPbackgroundcolor,
+ \c!rulethickness=.1\bodyfontsize,
+ \c!framecolor=STEPframecolor,
+ \c!distance=.5\bodyfontsize,
+ \c!offset=.25\bodyfontsize]
+
+\setupSTEPlines
+ [\c!alternative=1, % TODO
+ \c!rulethickness=.15\bodyfontsize,
+ \c!height=3\bodyfontsize,
+ \c!distance=.5\bodyfontsize,
+ \c!offset=.25\bodyfontsize,
+ \c!color=STEPlinecolor]
+
+\definecolor [STEPlinecolor] [s=.5]
+\definecolor [STEPframecolor] [s=.7]
+\definecolor [STEPbackgroundcolor] [s=.9]
+
+\newtoks\everySTEPchart
+
+\unexpanded\def\startSTEPchart
+ {\begingroup
+ \dodoubleempty\module_steps_start_chart}
+
+\def\module_steps_start_chart[#name][#settings]%
+ {\startnointerference
+ \iffirstargument
+ \doifassignmentelse{#name}
+ {\let\currentSTEPchart\empty
+ \xdef\module_steps_flush_chart{\module_steps_chart[][#name]}}
+ {\edef\currentSTEPchart{#name}%
+ \glet\module_steps_flush_chart\relax}% settings are not stored
+ \else
+ \let\currentSTEPchart\empty
+ \gdef\module_steps_flush_chart{\module_steps_chart[][]}%
+ \fi
+ \the\everySTEPchart
+ \ctxcommand{step_start_chart("\currentSTEPchart")}}
+
+\unexpanded\def\stopSTEPchart
+ {\ctxcommand{step_stop_chart()}%
+ \stopnointerference
+ \module_steps_flush_chart
+ \endgroup}
+
+\unexpanded\def\startSTEPtable
+ {\begingroup
+ \setupSTEPchart[\c!alternative=\v!vertical]%
+ \dodoubleempty\module_steps_start_chart}
+
+\let\stopSTEPtable\stopSTEPchart
+
+\let\module_steps_flush_chart\relax
+
+\unexpanded\def\STEPchart
+ {\dodoubleempty\module_steps_chart}
+
+\unexpanded\def\module_steps_chart[#name][#settings]%
+ {\begingroup
+ \setupSTEPchart[#settings]%
+ \ifinsidefloat
+ \makeSTEPchart[#name]%
+ \else
+ \STEPchartparameter\c!before
+ \startbaselinecorrection
+ \setlocalhsize
+ \makeSTEPchart[#name]%
+ \stopbaselinecorrection
+ \STEPchartparameter\c!after
+ \fi
+ \endgroup}
+
+\unexpanded\def\makeSTEPchart[#name]%
+ {\ctxcommand{step_make_chart {
+ chart = {
+ name = "#name",
+ alternative = "\STEPchartparameter\c!alternative",
+ },
+ cell = {
+ alternative = "\STEPcellparameter\c!alternative", % TODO: shapes
+ offset = \number\dimexpr\STEPcellparameter\c!offset,
+ rulethickness = \number\dimexpr\STEPcellparameter\c!rulethickness,
+ framecolor = "\STEPcellparameter\c!framecolor",
+ backgroundcolor = "\STEPcellparameter\c!backgroundcolor",
+ dx = \number\dimexpr\STEPcellparameter\c!dx,
+ dy = \number\dimexpr\STEPcellparameter\c!dy,
+ },
+ text = {
+ alternative = "\STEPtextparameter\c!alternative", % TODO: shapes
+ offset = \number\dimexpr\STEPtextparameter\c!offset,
+ distance = \number\dimexpr\STEPtextparameter\c!distance,
+ rulethickness = \number\dimexpr\STEPtextparameter\c!rulethickness,
+ framecolor = "\STEPtextparameter\c!framecolor",
+ backgroundcolor = "\STEPtextparameter\c!backgroundcolor",
+ },
+ line = {
+ alternative = "\STEPlineparameter\c!alternative", % TODO: dash, arrow
+ rulethickness = \number\dimexpr\STEPlineparameter\c!rulethickness,
+ height = \number\dimexpr\STEPlineparameter\c!height,
+ distance = \number\dimexpr\STEPlineparameter\c!distance,
+ offset = \number\dimexpr\STEPlineparameter\c!offset,
+ color = "\STEPlineparameter\c!color",
+ },
+ }}}
+
+\unexpanded\def\startSTEPcell
+ {\ctxcommand{step_start_cell()}}
+
+\unexpanded\def\stopSTEPcell
+ {\ctxcommand{step_stop_cell()}}
+
+\unexpanded\def\module_steps_cells#top#bot%
+ {\ctxcommand{step_cells(\!!bs\detokenize{#top}\!!es,\!!bs\detokenize{#bot}\!!es)}}
+
+\unexpanded\def\module_steps_texts#top#bot%
+ {\ctxcommand{step_texts(\!!bs\detokenize{#top}\!!es,\!!bs\detokenize{#bot}\!!es)}}
+
+\unexpanded\def\module_steps_cell#str%
+ {\ctxcommand{step_cell(\!!bs\detokenize{#str}\!!es)}}
+
+\unexpanded\def\module_steps_text#str%
+ {\ctxcommand{step_text(\!!bs\detokenize{#str}\!!es)}}
+
+\unexpanded\def\module_steps_textset#left#middle#right%
+ {\ctxcommand{step_textset(\!!bs\detokenize{#left}\!!es,\!!bs\detokenize{#middle}\!!es,\!!bs\detokenize{#right}\!!es)}}
+
+\unexpanded\def\module_steps_toptext#top%
+ {\ctxcommand{step_text_top(\!!bs\detokenize{#top}\!!es)}}
+
+\unexpanded\def\module_steps_bottext#bot%
+ {\ctxcommand{step_text_bot(\!!bs\detokenize{#bot}\!!es)}}
+
+\unexpanded\def\module_steps_topcell#top%
+ {\ctxcommand{step_cell_top(\!!bs\detokenize{#top}\!!es)}}
+
+\unexpanded\def\module_steps_botcell#bot%
+ {\ctxcommand{step_cell_bot(\!!bs\detokenize{#bot}\!!es)}}
+
+\appendtoks
+ \let\cells \module_steps_cells
+ \let\texts \module_steps_texts
+ \let\cell \module_steps_cell
+ \let\text \module_steps_text
+ \let\textset\module_steps_textset
+ \let\toptext\module_steps_toptext
+ \let\bottext\module_steps_bottext
+ \let\topcell\module_steps_topcell
+ \let\botcell\module_steps_botcell
+\to \everySTEPchart
+
+% todo: mapping can be done in lua
+
+\startxmlsetups xml:step:define
+ \xmlsetsetup{#1} {stepchart|steptable} {xml:step:*}
+\stopxmlsetups
+
+\xmlregistersetup{xml:step:define}
+
+\startxmlsetups xml:step:stepchart
+ \startSTEPchart
+ \xmlfilter{#1}{/(cells|texts|stepcell|cell|text)/command(xml:step:*)}
+ \stopSTEPchart
+\stopxmlsetups
+
+\startxmlsetups xml:step:steptable
+ \startSTEPtable
+ \xmlfilter{#1}{/(cells|texts|stepcell|cell|text)/command(xml:step:*)}
+ \stopSTEPtable
+\stopxmlsetups
+
+\startxmlsetups xml:step:cells
+ \cells {\xmltext{#1}{/top}} {\xmltext{#1}{/bot}}
+\stopxmlsetups
+
+\startxmlsetups xml:step:texts
+ \texts {\xmltext{#1}{/top}} {\xmltext{#1}{/bot}}
+\stopxmlsetups
+
+\startxmlsetups xml:step:stepcell
+ \cells {\xmltext{#1}{/topcell}} {\xmltext{#1}{/botcell}}
+ \texts {\xmltext{#1}{/toptext}} {\xmltext{#1}{/bottext}}
+\stopxmlsetups
+
+\startxmlsetups xml:step:cell
+ \cell {\xmlflush{#1}}
+\stopxmlsetups
+
+\startxmlsetups xml:step:text
+ \text {\xmlflush{#1}}
+\stopxmlsetups
+
+\protect
+
+\continueifinputfile{m-steps.mkvi}
+
+\starttext
+
+\startbuffer
+<stepchart>
+ <cell> some cell </cell>
+ <text> some text </text>
+ <cell> some cell </cell>
+ <text> some text </text>
+ <cell> some cell </cell>
+</stepchart>
+\stopbuffer
+
+\typebuffer \processxmlbuffer
+
+
+\startbuffer
+<steptable>
+ <cell> some cell </cell>
+ <text> some text </text>
+ <cell> some cell </cell>
+ <text> some text </text>
+ <cell> some cell </cell>
+</steptable>
+\stopbuffer
+
+\typebuffer \processxmlbuffer
+
+\page
+
+\startSTEPchart
+ \cells {A} {B}
+ \cells {one} {five} \texts{$+2$}{$-2$}
+ \cells {two} {four} \texts{$+3$}{$-3$}
+ \cells {three} {three} \texts{$+4$}{$-4$}
+ \cells {four} {two} \texts{$+5$}{$-5$}
+ \cells {five} {one}
+\stopSTEPchart
+
+\startSTEPtable
+ \cell {one} \textset{$x$} {=}{$a+b+c$}
+ \cell {two} \textset{$c+d$}{=}{$y$}
+ \cell {three}
+\stopSTEPtable
+
+
+\page
+
+\startbuffer
+<stepchart>
+ <cells> <top> some text </top> <bot> some text </bot> </cells>
+ <texts> <top> text </top> <bot> text </bot> </texts>
+ <cells> <top> some text </top> <bot> some text </bot> </cells>
+</stepchart>
+\stopbuffer
+
+\processxmlbuffer
+
+\startbuffer
+<stepchart>
+ <cell> some text </cell>
+ <texts> <top> text </top> <bot> text </bot> </texts>
+ <cell> some text </cell>
+</stepchart>
+\stopbuffer
+
+\processxmlbuffer
+
+\page
+
+\startSTEPchart[second]
+ \startSTEPcell
+ \topcell {A}
+ \botcell {B}
+ \startSTEPcell
+ \topcell {one}
+ \botcell {five}
+ \toptext {$+2$}
+ \bottext {$-2$}
+ \stopSTEPcell
+ \startSTEPcell
+ \topcell {two}
+ \botcell {four}
+ \toptext {$+3$}
+ \bottext {$-3$}
+ \stopSTEPcell
+ \startSTEPcell
+ \topcell {three}
+ \botcell {three}
+ \toptext {$+4$}
+ \bottext {$-4$}
+ \stopSTEPcell
+ \startSTEPcell
+ \topcell {four}
+ \botcell {two}
+ \toptext {$+5$}
+ \bottext {$-5$}
+ \stopSTEPcell
+ \startSTEPcell
+ \topcell {five}
+ \botcell {one}
+ \stopSTEPcell
+\stopSTEPchart
+
+\STEPchart[first][alternative=horizontal]
+\STEPchart[first][alternative=vertical]
+
+\page
+
+\STEPchart[second][alternative=horizontal]
+\STEPchart[second][alternative=vertical]
+
+\page
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/m-streams.tex b/Master/texmf-dist/tex/context/base/m-streams.tex
index 9d7e8d7dd98..a8589a89c13 100644
--- a/Master/texmf-dist/tex/context/base/m-streams.tex
+++ b/Master/texmf-dist/tex/context/base/m-streams.tex
@@ -5,7 +5,7 @@
%D subtitle=Streams,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-subsub.tex b/Master/texmf-dist/tex/context/base/m-subsub.tex
index 4395ded8acb..88be1168000 100644
--- a/Master/texmf-dist/tex/context/base/m-subsub.tex
+++ b/Master/texmf-dist/tex/context/base/m-subsub.tex
@@ -5,7 +5,7 @@
%D subtitle=More Section Levels,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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. This module is not public.
diff --git a/Master/texmf-dist/tex/context/base/m-timing.mkiv b/Master/texmf-dist/tex/context/base/m-timing.mkiv
index a91891a1b2f..e5413ddb110 100644
--- a/Master/texmf-dist/tex/context/base/m-timing.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-timing.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Timing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
@@ -58,8 +58,8 @@ end
{\setbox\scratchbox\vbox\bgroup\startMPcode
begingroup ; save p, q, b, h, w ;
path p, q, b ; numeric h, w ;
- p := \ctxlua{tex.sprint(moduledata.progress.path("#1","#2"))} ;
-% p := p shifted -llcorner p ;
+ p := \cldcontext{moduledata.progress.path("#1","#2")} ;
+ % p := p shifted -llcorner p ;
if bbwidth(p) > 1 :
h := 100 ; w := 2 * h ;
w := \the\textwidth-3pt ; % correct for pen
@@ -69,8 +69,8 @@ end
draw b withcolor \MPcolor{usage:frame} ;
draw p withcolor \MPcolor{usage:line} ;
if ("#3" <> "") and ("#3" <> "#2") :
- q := \ctxlua{tex.sprint(moduledata.progress.path("#1","#3"))} ;
-% q := q shifted -llcorner q ;
+ q := \cldcontext{moduledata.progress.path("#1","#3")} ;
+ % q := q shifted -llcorner q ;
if bbwidth(q) > 1 :
q := q xstretched w ;
pickup pencircle scaled 1.5pt ; linecap := butt ;
@@ -85,9 +85,9 @@ end
\startlinecorrection
\box\scratchbox \endgraf
\hbox to \scratchdimen{\tttf\strut\detokenize{#2}\hss
- min:\ctxlua{tex.sprint(moduledata.progress.bot("#1","\detokenize{#2}"))}, %
- max:\ctxlua{tex.sprint(moduledata.progress.top("#1","\detokenize{#2}"))}, %
- pages:\ctxlua{tex.sprint(moduledata.progress.pages("#1"))}%
+ min:\cldcontext{moduledata.progress.bot("#1","\detokenize{#2}")}, %
+ max:\cldcontext{moduledata.progress.top("#1","\detokenize{#2}")}, %
+ pages:\cldcontext{moduledata.progress.pages("#1")}%
}%
\stoplinecorrection
\fi}
diff --git a/Master/texmf-dist/tex/context/base/m-translate.mkiv b/Master/texmf-dist/tex/context/base/m-translate.mkiv
index c0e4aad7240..ae4f3899ddb 100644
--- a/Master/texmf-dist/tex/context/base/m-translate.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-translate.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Translations,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-units.mkii b/Master/texmf-dist/tex/context/base/m-units.mkii
index 6a899736bb5..af4629d4860 100644
--- a/Master/texmf-dist/tex/context/base/m-units.mkii
+++ b/Master/texmf-dist/tex/context/base/m-units.mkii
@@ -5,7 +5,7 @@
%D subtitle=Scientific Units,
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/m-units.mkiv b/Master/texmf-dist/tex/context/base/m-units.mkiv
index a7653c56677..b0db8d54895 100644
--- a/Master/texmf-dist/tex/context/base/m-units.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-units.mkiv
@@ -5,12 +5,14 @@
%D subtitle=Scientific Units,
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Best use the built in unit handle!
+
%D Scientific units can be typeset in math mode pretty well,
%D but occasionally one has to take care of spacing.
%D Furthermore, entering these units is not that natural as
@@ -29,8 +31,6 @@
%D macro defined in the core modules. Let's say that this is
%D an upward compatibility issue.
-% \registerctxluafile{x-units}{}
-
\startmessages dutch library: units
title: eenheden
1: gebruik \string\Degrees\space\string\Celsius\space in plaats van \string\Celsius !
@@ -70,6 +70,19 @@
\unprotect
+\writestatus{\m!units}{The units module is obsolete because functionality is built into the core.}
+
+\let\unit\undefined
+
+\definesynonyms
+ [\v!unit]
+ [\v!units]
+ [\unitmeaning]
+
+\setupsynonyms
+ [\v!unit]
+ [\c!synonymcommand=\dimension]
+
\startmodule[units]
%D This runtime loadable module implements a way of defining
@@ -77,15 +90,9 @@
%D one that is able to cooperate with some other dimension
%D related macros. As said, this module enables user to enter:
%D
-%D \startbuffer
+%D \starttyping
%D some 10 \Square \Meter \Per \Second or more
-%D \stopbuffer
-%D
-%D \getbuffer
-%D
-%D as:
-%D
-%D \typebuffer
+%D \stoptyping
%D
%D The units itself are implemented as synonyms.
%D
@@ -115,7 +122,7 @@
%D The next useless examples show some of the cases we want
%D to handle in a proper way.
%D
-%D \startbuffer
+%D \starttyping
%D ... 10 \Square \Meter \Per \Volt \
%D ... 10 \Square \Meter \Volt \
%D ... 10 \Meter \Volt \
@@ -124,13 +131,7 @@
%D ... 10 \Meter \Times \Meter \
%D ... 10 \Square \Meter \Times \Meter \
%D ... 10 \Square \Milli \Meter \Times \Meter \
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D Becomes:
-%D
-%D \getbuffer
+%D \stoptyping
%D \macros
%D {mathematicstypeface, dimensiontypeface,
@@ -169,9 +170,8 @@
%D
%D The actual definition of \type {\dimension} overruled the
%D one in the core modules. The boolean can be used to
-%D force spacing between units. Vergelijk {\Newton \Meter}
-%D eens met {\spaceddimensionstrue \Newton \Meter}. The
-%D rather ugly test prevents problems with nested dimensions.
+%D force spacing between units. The rather ugly test prevents
+%D problems with nested dimensions.
\newif\ifspaceddimensions \spaceddimensionsfalse % user switch
\newif\iftextdimensions \textdimensionsfalse % user switch
diff --git a/Master/texmf-dist/tex/context/base/m-visual.tex b/Master/texmf-dist/tex/context/base/m-visual.mkii
index d784551901f..ae52f65718f 100644
--- a/Master/texmf-dist/tex/context/base/m-visual.tex
+++ b/Master/texmf-dist/tex/context/base/m-visual.mkii
@@ -5,7 +5,7 @@
%D subtitle=Visualization and Faking,
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -204,7 +204,7 @@
\framed
[\c!width=\dimen0,
\c!height=\dimen2,
- \c!frame=\ifincolor\v!off\else\v!on\fi,
+ \c!frame=\v!off,
\c!background=\v!color,
\c!backgroundcolor=fakeparindentcolor]
{\bf\white#1}}%
@@ -226,7 +226,6 @@
%D test \type{\bodyfontgrid}\space test
%D test \type{\emexgrid} \space test
-
\def\smashedgrid
{\dosingleempty\dosmashedgrid}
diff --git a/Master/texmf-dist/tex/context/base/m-visual.mkiv b/Master/texmf-dist/tex/context/base/m-visual.mkiv
new file mode 100644
index 00000000000..5d259f6abc9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/m-visual.mkiv
@@ -0,0 +1,252 @@
+%D \module
+%D [ file=m-visual,
+%D version=2000.01.10,
+%D title=\CONTEXT\ Extra Modules,
+%D subtitle=Visualization and Faking,
+%D author={Hans Hagen \& Ton Otten},
+%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.
+
+\unprotect
+
+%D This module collect a few more visual debugger features. I
+%D needed them for manuals and styles. The macros are documented
+%D in a my way document.
+
+\definecolor[fakerulecolor] [black]
+\definecolor[fakebaselinecolor] [green]
+\definecolor[fakeparindentcolor][blue]
+
+\newif\iffakebaseline \fakebaselinetrue
+
+\unexpanded\def\fakerule#1%
+ {\strut
+ \begingroup
+ \directcolored[fakerulecolor]%
+ \iffakebaseline
+ \vrule\!!height1.25ex\!!depth-.05ex\!!width#1%
+ \kern-#1%
+ \vrule\!!height-.05ex\!!depth .25ex\!!width#1%
+ \else
+ \vrule\!!height1.25ex\!!depth .25ex\!!width#1%
+ \fi
+ \endgroup
+ \allowbreak}
+
+\unexpanded\def\dorandomrecurse#1%
+ {\getrandomcount\scratchcounter{1}{#1}%
+ \dorecurse\scratchcounter}
+
+% can be used in hbox, so %'s are really needed
+
+\unexpanded\def\fakelines#1#2% min max / 3 10
+ {\fakeparindent
+ \scratchdimen\hsize
+ \ifindentation
+ \advance\scratchdimen -\parindent
+ \fi
+ \fakerule\scratchdimen\break
+ \getrandomcount\scratchcounter{\ifcase0#1 3\else#1\fi}{\ifcase0#2 10\else#2\fi}%
+ \dorecurse\scratchcounter{\fakerule\hsize}%
+ \getrandomdimen\scratchdimen{.25\hsize}\hsize
+ \fakerule\scratchdimen
+ \par} % indeed
+
+\unexpanded\def\fakewords
+ {\ifvmode\fakeparindent\fi\onlyfakewords}
+
+\definepalet
+ [fakerule]
+ [fr1c=darkred,
+ fr2c=darkgreen,
+ fr3c=darkblue,
+ fr4c=darkyellow,
+ fr5c=darkgray]
+
+\unexpanded\def\onlyfakewords#1#2% min max / 10 40
+ {\getrandomcount\scratchcounter{\ifcase0#1 10\else#1\fi}{\ifcase0#2 40\else#2\fi}%
+ \dofakewords\scratchcounter
+ } % no \par
+
+\unexpanded\def\fakenwords#1#2% words seed
+ {\fakeparindent
+ \getrandomseed\fakedwordseed
+ \setrandomseed{\ifcase0#2 #1\else#2\fi}%
+ \dofakewords{#1}%
+ \setrandomseed\fakedwordseed
+ } % no \par
+
+\def\dofakewords#1%
+ {\bgroup
+ \dorecurse{#1}
+ {\getrandomcount\scratchcounter{1}{5}%
+ \dorecurse\scratchcounter
+ {\getrandomdimen\scratchdimen{.5em}{1.25em}%
+ \fakerule\scratchdimen}%
+ \space}%
+ \removeunwantedspaces
+ \egroup}
+
+\def\doshowfakewords#1%
+ {\bgroup
+ \setuppalet[fakerule]%
+ \definecolor[fakerulecolor]%
+ \dorecurse{#1}
+ {\getrandomcount\scratchcounter{1}{5}%
+ \dorecurse\scratchcounter
+ {\getrandomdimen\scratchdimen{.5em}{1.25em}%
+ \color[fr\recurselevel c]{\fakerule\scratchdimen}}%
+ \space}%
+ \removeunwantedspaces
+ \egroup}
+
+\unexpanded\def\showfakewords
+ {\let\dofakewords\doshowfakewords}
+
+\unexpanded\def\fakeword
+ {\fakewords{1}{1}} % no \plusone
+
+\unexpanded\def\fakeparindent
+ {\noindent
+ \ifindentation
+ \ifx\dofakedroppedcaps\relax
+ {\fakeparindentcolor
+ \vrule
+ \!!height \strutheight % not longer .5ex
+ \!!depth \strutdepth % not longer 0pt
+ \!!width \parindent}%
+ \else
+ \dofakedroppedcaps \let\dofakedroppedcaps\relax
+ \fi
+% \else
+% \dontleavehmode
+ \fi}
+
+\let\dofakedroppedcaps\relax
+
+\unexpanded\def\fakedroppedcaps#1%
+ {\ifnum#1>0
+ \def\dofakedroppedcaps
+ {\setbox\scratchbox\hbox
+ {\setbox\scratchbox\hbox{W}%
+ \scratchdimen#1\lineheight
+ \advance\scratchdimen -\lineheight
+ \advance\scratchdimen \dp\strutbox
+ \vrule
+ \!!width#1\wd\scratchbox
+ \!!height\ht\scratchbox
+ \!!depth\scratchdimen}%
+ \ht\scratchbox\ht\strutbox
+ \dp\scratchbox\dp\strutbox
+ \hangindent\wd\scratchbox
+ \advance\hangindent .5em
+ \wd\scratchbox\hangindent
+ \hangafter-#1\noindent
+ \llap{\fakeparindentcolor\box\scratchbox}}%
+ \fi}
+
+\unexpanded\def\fakefigure
+ {\dodoubleempty\dofakefigure}
+
+\def\dofakefigure[#1][#2]#3#4#5#6% [] [] minwidth maxwidth minheight maxheight
+ {\getvalue{\e!place\v!figure}
+ [#1][#2]%
+ {\freezerandomseed
+ \let\endstrut\relax
+ \let\begstrut\relax
+ \doifinsetelse{#1}{\v!left,\v!right}
+ {\fakewords{2}{4}}
+ {\fakewords{4}{10}}}%
+ {\doifinset{#1}{\v!left,\v!right}
+ {\dimen0=.75\dimen0
+ \ifdim\dimen0>.6\hsize \dimen0=.5\hsize\fi
+ \ifdim\dimen0<.3\hsize \dimen0=.3\hsize\fi}%
+ \framed
+ [\c!width=\dimen0,
+ \c!height=\dimen2,
+ \c!frame=\v!off,
+ \c!background=\v!color,
+ \c!backgroundcolor=fakeparindentcolor]
+ {\bf\white#1}}%
+ \defrostrandomseed}
+
+\unexpanded\def\fakeimage#1#2#3#4%
+ {\getrandomdimen{\dimen0}{#1}{#3}%
+ \getrandomdimen{\dimen2}{#2}{#4}%
+ \framed
+ [\c!width=\dimen0,
+ \c!height=\dimen2,
+ \c!frame=\v!off,
+ \c!background=\v!color,
+ \c!backgroundcolor=fakeparindentcolor]
+ {}}
+
+\unexpanded\def\fakeformula
+ {\dimen0\zeropoint
+ \getrandomcount\scratchcounter{3}{6}%
+ \dorecurse\scratchcounter
+ {\getrandomdimen\scratchdimen{1em}{3em}%
+ \mathinner{\red\fakerule\scratchdimen}%
+ \ifnum\recurselevel<\scratchcounter+\fi
+ \advance\scratchdimen\dimen0}%
+ =\mathinner{\red\fakerule\scratchdimen}}
+
+\unexpanded\def\fakespacingformula
+ {\color[fakebaselinecolor]{\ruledbaseline}\fakeformula}
+
+%D test \type{\bodyfontgrid}\space test
+%D test \type{\emexgrid} \space test
+
+\unexpanded\def\smashedgrid
+ {\dosingleempty\dosmashedgrid}
+
+\def\dosmashedgrid[#1]%
+ {\hsmashed
+ {\setbox\scratchbox=\hbox
+ {\basegrid
+ [\c!nx=10,\c!ny=10,\c!dx=1,\c!dy=1,
+ \c!unit=\bodyfontsize,#1]}%
+ \hbox to \zeropoint
+ {\hss\lower.5\ht\scratchbox\box\scratchbox\hss}%
+ \hbox to \zeropoint
+ {\hss
+ \black\vrule\!!width6\linewidth\!!height3\linewidth\!!depth3\linewidth
+ \hss}}}
+
+\unexpanded\def\bodyfontgrid
+ {\hbox
+ {{\linewidth.1pt\yellow\smashedgrid[\c!nx=30,\c!ny=30,\c!scale=.3333]}%
+ {\linewidth.2pt\green \smashedgrid[\c!nx=20,\c!ny=20,\c!scale=.5]}%
+ {\linewidth.3pt\red \smashedgrid[\c!nx=10,\c!ny=10,\c!scale=1]}}}
+
+\unexpanded\def\emexgrid
+ {\hbox
+ {{\linewidth.15pt\green\smashedgrid[\c!nx=20,\c!ny=20,\c!unit=ex]}%
+ {\linewidth.15pt\red \smashedgrid[\c!nx=10,\c!ny=10,\c!unit=em]}}}
+
+%D For Mojca:
+
+\unexpanded\def\simplethesis
+ {\setupsystem[random=1234]
+ \title{\fakewords{3}{4}}
+ \placelist[chapter,section]
+ \dorecurse{6}
+ {\chapter{\fakewords{5}{10}}
+ \dorecurse{5}
+ {\section{\fakewords{2}{5}}
+ \dorecurse{2}
+ {\dorecurse{3}{\fakewords{100}{200}\endgraf}
+ \placefigure{\fakewords{8}{15}}{\fakeimage{5cm}{3cm}{10cm}{5cm}}
+ \dorecurse{2}{\fakewords{100}{200}\endgraf}}}}}
+
+\continueifinputfile{m-visual.mkiv}
+
+\starttext
+ \simplethesis
+\stoptext
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/m-zint.mkiv b/Master/texmf-dist/tex/context/base/m-zint.mkiv
index 3e6f7ab4366..95b265c5724 100644
--- a/Master/texmf-dist/tex/context/base/m-zint.mkiv
+++ b/Master/texmf-dist/tex/context/base/m-zint.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Zint Barcode Generator,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -47,6 +47,9 @@ local function numberofcode(code)
if not reverse then
local types = os.resultof(format("%s --types",zint)) or ""
local formats = lpeg.match(pattern,types)
+ if not formats or not next(formats) then
+ return code
+ end
reverse = table.swapped(formats) or { }
end
code = cleancode(code)
@@ -65,14 +68,15 @@ function moduledata.zint.generate(code,data,suffix,options)
local code = numberofcode(code)
logs.simple("using 'zint' to generate '%s'",base)
io.savedata(temp,data)
- os.execute(format('%s --barcode=%s --output="%s" --input="%s"',zint,code,name,temp,options or ""))
+ os.execute(format('%s --barcode=%s --output="%s" --input="%s" %s',zint,code,name,temp,options or ""))
+ os.remove(temp)
end
- return name
+ return name
end
\stopluacode
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{m-zint.mkiv}
\starttext
diff --git a/Master/texmf-dist/tex/context/base/math-act.lua b/Master/texmf-dist/tex/context/base/math-act.lua
index 03675933e8a..278d323c636 100644
--- a/Master/texmf-dist/tex/context/base/math-act.lua
+++ b/Master/texmf-dist/tex/context/base/math-act.lua
@@ -14,23 +14,23 @@ local mathematics = mathematics
local sequencers = utilities.sequencers
local appendgroup = sequencers.appendgroup
local appendaction = sequencers.appendaction
-local mathprocessor = nil
-local mathactions = sequencers.reset {
+local mathfontparameteractions = sequencers.new {
+ name = "mathparameters",
arguments = "target,original",
}
+appendgroup("mathparameters","before") -- user
+appendgroup("mathparameters","system") -- private
+appendgroup("mathparameters","after" ) -- user
+
function fonts.constructors.assignmathparameters(original,target)
- if mathactions.dirty then -- maybe use autocompile
- mathprocessor = sequencers.compile(mathactions)
+ local runner = mathfontparameteractions.runner
+ if runner then
+ runner(original,target)
end
- mathprocessor(original,target)
end
-appendgroup(mathactions,"before") -- user
-appendgroup(mathactions,"system") -- private
-appendgroup(mathactions,"after" ) -- user
-
function mathematics.initializeparameters(target,original)
local mathparameters = original.mathparameters
if mathparameters and next(mathparameters) then
@@ -38,16 +38,21 @@ function mathematics.initializeparameters(target,original)
end
end
-sequencers.appendaction(mathactions,"system","mathematics.initializeparameters")
+sequencers.appendaction("mathparameters","system","mathematics.initializeparameters")
local how = {
-- RadicalKernBeforeDegree = "horizontal",
-- RadicalKernAfterDegree = "horizontal",
+ ScriptPercentScaleDown = "unscaled",
+ ScriptScriptPercentScaleDown = "unscaled",
RadicalDegreeBottomRaisePercent = "unscaled"
}
function mathematics.scaleparameters(target,original)
if not target.properties.math_is_scaled then
+ -- print("\n",target.properties.fontname)
+ -- print(original.mathparameters.DisplayOperatorMinHeight)
+ -- print(target.mathparameters.DisplayOperatorMinHeight)
local mathparameters = target.mathparameters
if mathparameters and next(mathparameters) then
local parameters = target.parameters
@@ -57,44 +62,49 @@ function mathematics.scaleparameters(target,original)
for name, value in next, mathparameters do
local h = how[name]
if h == "unscaled" then
- mathparameters[name] = value
+ -- kept
elseif h == "horizontal" then
- mathparameters[name] = value * hfactor
+ value = value * hfactor
elseif h == "vertical"then
- mathparameters[name] = value * vfactor
+ value = value * vfactor
else
- mathparameters[name] = value * factor
+ value = value * factor
end
+ -- if name == "DisplayOperatorMinHeight" then
+ -- report_math("f: %s, p: %s, h: %s, b: %s, a: %s",target.properties.fontname,name,h or "scaled",mathparameters[name],value)
+ -- end
+ mathparameters[name] = value
end
end
+ -- print(mathparameters.DisplayOperatorMinHeight)
target.properties.math_is_scaled = true
end
end
-sequencers.appendaction(mathactions,"system","mathematics.scaleparameters")
+sequencers.appendaction("mathparameters","system","mathematics.scaleparameters")
function mathematics.checkaccentbaseheight(target,original)
local mathparameters = target.mathparameters
- if mathparameters then
- mathparameters.AccentBaseHeight = nil -- safeguard
+ if mathparameters and mathparameters.AccentBaseHeight == 0 then
+ mathparameters.AccentBaseHeight = target.parameters.x_height -- needs checking
end
end
-sequencers.appendaction(mathactions,"system","mathematics.checkaccentbaseheight")
+sequencers.appendaction("mathparameters","system","mathematics.checkaccentbaseheight")
function mathematics.checkprivateparameters(target,original)
local mathparameters = target.mathparameters
if mathparameters then
if not mathparameters.FractionDelimiterSize then
- mathparameters.FractionDelimiterSize = 0
+ mathparameters.FractionDelimiterSize = 1.01 * target.parameters.size
end
if not mathparameters.FractionDelimiterDisplayStyleSize then
- mathparameters.FractionDelimiterDisplayStyleSize = 0
+ mathparameters.FractionDelimiterDisplayStyleSize = 2.40 * target.parameters.size
end
end
end
-sequencers.appendaction(mathactions,"system","mathematics.checkprivateparameters")
+sequencers.appendaction("mathparameters","system","mathematics.checkprivateparameters")
function mathematics.overloadparameters(target,original)
local mathparameters = target.mathparameters
@@ -139,4 +149,56 @@ function mathematics.overloadparameters(target,original)
end
end
-sequencers.appendaction(mathactions,"system","mathematics.overloadparameters")
+sequencers.appendaction("mathparameters","system","mathematics.overloadparameters")
+
+local function applytweaks(when,target,original)
+ local goodies = original.goodies
+ if goodies then
+ for i=1,#goodies do
+ local goodie = goodies[i]
+ local mathematics = goodie.mathematics
+ local tweaks = mathematics and mathematics.tweaks
+ if tweaks then
+ tweaks = tweaks[when]
+ if tweaks then
+ if trace_defining then
+ report_math("tweaking math of '%s' @ %s (%s)",target.properties.fullname,target.parameters.size,when)
+ end
+ for i=1,#tweaks do
+ local tweak= tweaks[i]
+ local tvalue = type(tweak)
+ if tvalue == "function" then
+ tweak(target,original)
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function mathematics.tweakbeforecopyingfont(target,original)
+ local mathparameters = target.mathparameters -- why not hasmath
+ if mathparameters then
+ applytweaks("beforecopying",target,original)
+ end
+end
+
+function mathematics.tweakaftercopyingfont(target,original)
+ local mathparameters = target.mathparameters -- why not hasmath
+ if mathparameters then
+ applytweaks("aftercopying",target,original)
+ end
+end
+
+sequencers.appendaction("beforecopyingcharacters","system","mathematics.tweakbeforecopyingfont")
+sequencers.appendaction("aftercopyingcharacters", "system","mathematics.tweakaftercopyingfont")
+
+-- a couple of predefined tewaks:
+
+local tweaks = { }
+mathematics.tweaks = tweaks
+
+function tweaks.fixbadprime(target,original)
+ target.characters[0xFE325] = target.characters[0x2032]
+end
diff --git a/Master/texmf-dist/tex/context/base/math-ali.mkiv b/Master/texmf-dist/tex/context/base/math-ali.mkiv
index f83619a2271..94800b3ba8b 100644
--- a/Master/texmf-dist/tex/context/base/math-ali.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-ali.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Math Alignments,
%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -15,8 +15,20 @@
\unprotect
+% helpers .. will move
+
+\def\doxxdoubleempty#1#2%
+ {\ifx#2[\expandafter\dodoxxdoubleempty\else\expandafter\noxxdoubleempty\fi#1#2}
+
+\def\dodoxxdoubleempty#1[#2]#3%
+ {\ifx#3[\else\expandafter\nonoxxdoubleempty\fi#1[#2]#3}
+
+\def\noxxdoubleempty #1{#1[][]}
+\def\nonoxxdoubleempty#1[#2]{#1[#2][]}
+
%D The code here has been moved from other files. Beware: the \MKII\ and
-%D \MKIV\ code is not gathered in files with the same name.
+%D \MKIV\ code is not gathered in files with the same name. In the
+%D meantime this code has been adapted to \MKIV\ but mnore is possible.
%D \macros
%D {definemathalignment, setupmathalignment, startmathalignment}
@@ -26,102 +38,99 @@
% n>1 #### needed, strange # interaction in recurse
-\def\presetdisplaymath{\displ@y} % some day i will relocate the plain stuff
-
-\def\buildeqalign
+\def\math_build_eqalign
{\scratchtoks\emptytoks
\dorecurse{\mathalignmentparameter\c!m}
{\ifnum\recurselevel>\plusone
- \appendtoks
- \tabskip\mathalignmentparameter\c!distance&\tabskip\zeropoint
- \to\scratchtoks
+ %\appendtoks
+ % \tabskip\mathalignmentparameter\c!distance&\tabskip\zeropoint
+ %\to\scratchtoks
+ \scratchtoks\expandafter{\the\scratchtoks\tabskip\mathalignmentparameter\c!distance&\tabskip\zeropoint}%
\fi
\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksa}}%
\dorecurse{\numexpr\mathalignmentparameter\c!n-\plusone\relax}
{\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksb}}}}%
\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksc}}}
-\def\forgetalign
- {\tabskip\zeropoint\everycr\emptytoks}
-
-\let\firstineqalign\empty
-\let\nextineqalign \empty
-\let\leftofeqalign \empty
-\let\rightofeqalign\empty
+\def\math_math_in_eqalign#1{$\tabskip\zeropoint\everycr\emptytoks\displaystyle{{}#1{}}$}
+\def\math_text_in_eqalign#1{$\tabskip\zeropoint\everycr\emptytoks#1$}
-\def\mathineqalign#1{$\forgetalign\displaystyle{{}#1{}}$}
-\def\textineqalign#1{$\forgetalign#1$}
+\def\displayopenupvalue{.25\bodyfontsize}
\def\eqalign#1% why no halign here, probably because of displaywidth
- {\emptyhbox\,\vcenter
- {\openup.25\bodyfontsize% was: \openup\jot
+ {\emptyhbox
+ \mskip\thinmuskip
+ \vcenter
+ {\openup\displayopenupvalue % was: \openup\jot
\mathsurround\zeropoint
- \ialign{\strut\hfil$\displaystyle{##}$&$\displaystyle{{}##{}}$\hfil\crcr#1\crcr}%
- }\,}
+ \ialign{\strut\hfil$\displaystyle{##}$&$\displaystyle{{}##{}}$\hfil\crcr#1\crcr}}%
+ \mskip\thinmuskip}
% preamble is scanned for tabskips so we need the span to prevent an error message
\setnewconstant\eqalignmode\plusone
-\def\preparereqalignno
- {\!!toksa{\strut\firstineqalign\hfil\leftofeqalign\span\mathineqalign{##}\rightofeqalign\tabskip\zeropoint}%
- \!!toksb{&\nextineqalign\leftofeqalign\span\mathineqalign{##}\rightofeqalign\tabskip\zeropoint}%
+% use zeroskipplusfill
+
+\def\math_prepare_r_eqalign_no
+ {\!!toksa{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}%
+ \!!toksb{&\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}%
\ifnum\mathraggedstatus=\plusone
- \!!toksc{\hfil&\span\textineqalign{##}\tabskip\zeropoint}%
+ \!!toksc{\hfil&\span\math_text_in_eqalign{##}\tabskip\zeropoint}%
\else\ifnum\mathraggedstatus=\plusthree
- \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\span\textineqalign{##}\tabskip\zeropoint}%
+ \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\span\math_text_in_eqalign{##}\tabskip\zeropoint}%
\else
- \!!toksc{\hfil\tabskip\centering&\llap{\span\textineqalign{##}}\tabskip\zeropoint}%
+ \!!toksc{\hfil\tabskip\centering&\llap{\span\math_text_in_eqalign{##}}\tabskip\zeropoint}%
\fi\fi
\global\mathnumberstatus\zerocount
- \buildeqalign
- \presetdisplaymath
+ \math_build_eqalign
+ \the\mathdisplayaligntweaks
\tabskip\centering}
-\def\prepareleqalignno
- {\!!toksa{\strut\firstineqalign\hfil\leftofeqalign\span\mathineqalign{##}\rightofeqalign\tabskip\zeropoint}%
- \!!toksb{&\nextineqalign\leftofeqalign\span\mathineqalign{##}\rightofeqalign\tabskip\zeropoint}%
+\def\math_prepare_l_eqalign_no
+ {\!!toksa{\strut\math_first_in_eqalign\hfil\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}%
+ \!!toksb{&\math_next_in_eqalign\math_left_of_equalign\span\math_math_in_eqalign{##}\math_right_of_eqalign\tabskip\zeropoint}%
% problem: number is handled after rest and so ends up in the margin
\ifnum\mathraggedstatus=\plusone
- \!!toksc{\hfil&\kern-\displaywidth\rlap{\span\textineqalign{##}}\tabskip\displaywidth}%
+ \!!toksc{\hfil&\kern-\displaywidth\rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}%
\else\ifnum\mathraggedstatus=\plusthree
- \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\kern-\displaywidth\span\mrlap{\span\textineqalign{##}}\tabskip\displaywidth}%
+ \!!toksc{\hfil\tabskip\zeropoint\!!plus 1\!!fill&\kern-\displaywidth\span\math_rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}%
\else
- \!!toksc{\hfil\tabskip\centering&\kern-\displaywidth\rlap{\span\textineqalign{##}}\tabskip\displaywidth}%
+ \!!toksc{\hfil\tabskip\centering&\kern-\displaywidth\rlap{\span\math_text_in_eqalign{##}}\tabskip\displaywidth}%
\fi\fi
\global\mathnumberstatus\zerocount
- \buildeqalign
- \presetdisplaymath
+ \math_build_eqalign
+ \the\mathdisplayaligntweaks
\tabskip\centering}
-\def\dobotheqalignno#1#2%
+\def\math_both_eqalign_no#1#2%
{\ifmmode
- \displ@y % \let\doplaceformulanumber\relax % strange hack
+ \the\mathdisplayaligntweaks % \let\doplaceformulanumber\relax % strange hack
\vcenter\bgroup
- \let\finishalignno\egroup
+ \let\math_finish_eqalign_no\egroup
\else
- \let\finishalignno\relax
+ \let\math_finish_eqalign_no\relax
\fi
#1%
\halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA {\the\scratchtoks\crcr#2\crcr}%
- \finishalignno}
+ \math_finish_eqalign_no}
-\def\dobothaligneqalignno#1%
+\def\math_both_eqalign_no_aligned#1%
{\ifmmode
- \displ@y
+ \the\mathdisplayaligntweaks
\global\mathnumberstatus\plusone
\ifcase\mathraggedstatus
- \def\finishalignno{\crcr\egroup}%
+ \def\math_finish_eqalign_no{\crcr\egroup}%
\else
% we're in a mathbox
\vcenter\bgroup
- \def\finishalignno{\crcr\egroup\egroup}%
+ \def\math_finish_eqalign_no{\crcr\egroup\egroup}%
\fi
\fi
#1%
\halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA \bgroup\the\scratchtoks\crcr}
-\def\mrlap#1%
+\def\math_rlap#1%
{\setbox\scratchbox\hbox{#1}%
\ifdim\wd\scratchbox>\mathnumbercorrection
\xdef\mathnumbercorrection{\the\wd\scratchbox}%
@@ -129,130 +138,142 @@
\box\scratchbox
\global\mathnumberstatus\plustwo}
-% \def\dobothaligneqalignno#1%
-% {\ifmmode
-% \displ@y
-% \global\mathnumberstatus\plusone
-% we're in a mathbox
-% \vcenter\bgroup
-% \def\finishalignno{\crcr\egroup\egroup}%
-% \else
-% \def\finishalignno{\crcr\egroup}%
-% \fi
-% #1%
-% \halign \ifcase\eqalignmode \or to \displaywidth \fi \@EA \bgroup\the\scratchtoks\crcr}
-
-\def\reqalignno {\dobotheqalignno \preparereqalignno}
-\def\leqalignno {\dobotheqalignno \prepareleqalignno}
-\def\alignreqalignno{\dobothaligneqalignno\preparereqalignno}
-\def\alignleqalignno{\dobothaligneqalignno\prepareleqalignno}
-\def\finishalignno {\crcr\egroup}
-
-\let \equalignno \reqalignno
-\let\aligneqalignno\alignreqalignno
-
-%D Here we implement the user interface part.
-
-\unexpanded\def\setupmathalignment
- {\dodoubleempty\dosetupmathalignment}
-
-\def\dosetupmathalignment[#1][#2]%
- {\ifsecondargument
- \getparameters[\??eq#1][#2]%
- \else
- \getparameters[\??eq][#1]%
- \fi}
-
-\let\currentmathalignment\empty
-
-\def\mathalignmentparameter#1%
- {\executeifdefined{\??eq\currentmathalignment#1}{\executeifdefined{\??eq#1}\empty}}
-
-\setupmathalignment
- [\c!n=2,
- \c!m=1,
- \c!distance=1em]
+\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}
-\def\numberedeqalign
- {\doifelse{\formulaparameter\c!location}\v!left\alignleqalignno\alignreqalignno}
+\let \reqalignno \math_handle_eqalign_no_r_normal
+\let \leqalignno \math_handle_eqalign_no_l_normal
+\let\alignreqalignno \math_handle_eqalign_no_r_aligned
+\let\alignleqalignno \math_handle_eqalign_no_l_aligned
+\let \eqalignno \math_handle_eqalign_no_r_normal
+\let \aligneqalignno \math_handle_eqalign_no_r_aligned
-\def\doxxdoubleempty#1#2%
- {\ifx#2[\expandafter\dodoxxdoubleempty\else\expandafter\noxxdoubleempty\fi#1#2}
+%D Here we implement the user interface part. We start with basic math alignments:
-\def\dodoxxdoubleempty#1[#2]#3%
- {\ifx#3[\else\expandafter\nonoxxdoubleempty\fi#1[#2]#3}
+\newcount\c_math_eqalign_column
-\def\noxxdoubleempty #1{#1[][]}
-\def\nonoxxdoubleempty#1[#2]{#1[#2][]}
+\newtoks \everymathalignment
-\newcount\eqaligncolumn
+\def\math_alignment_NR_indeed[#1][#2]%
+ {\donestedformulanumber{#1}{#2}% to be tagged (better an attribute)
+ \crcr
+ \dostoptagged % finish row
+ \noalign{\glet\math_alignment_NC\math_alignment_NC_first}} % noalign used for change state, conditional does not work here
-\def\firstineqalign{\global\eqaligncolumn\plusone}
-\def\nextineqalign {\global\advance\eqaligncolumn\plusone}
-\def\leftofeqalign {\getvalue{\??eq:\v!left :\number\eqaligncolumn}}
-\def\rightofeqalign{\getvalue{\??eq:\v!right:\number\eqaligncolumn}}
+\def\math_alignment_NC_first
+ {\glet\math_alignment_NC\math_alignment_NC_rest}
-\def\doseteqaligncolumn#1%
- {\letvalueempty{\??eq:\v!left :\number\eqaligncolumn}%
- \letvalueempty{\??eq:\v!right:\number\eqaligncolumn}%
- \doif{#1}\v!left {\letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfill}%
- \doif{#1}\v!right {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfill}%
- \doif{#1}\v!middle{\letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfill
- \letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfill}}
+\def\math_alignment_NC_rest
+ {\aligntab}
-\def\dodoalignNC
- {\gdef\doalignNC##1{&##1}}
+\def\math_alignment_EQ
+ {\NC=}
-\def\doalignNR[#1][#2]%
- {\donestedformulanumber{#1}{#2}\crcr}
+\def\math_alignment_NR
+ {\aligntab
+ \dostoptagged % finish cell
+ \dodoubleempty\math_alignment_NR_indeed} % use xx from tabulate
-%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
+\appendtoks
+ \glet\math_alignment_NC\math_alignment_NC_first
+ \unexpanded\def\NC{\math_alignment_NC}% messy, due to lookahead (we cannot use a flag)
+ \let\EQ\math_alignment_EQ
+ \let\NR\math_alignment_NR
+\to \everymathalignment
-% todo: pop in cell
+\unexpanded\def\math_alignment_start#1%
+ {\edef\currentmathalignment{#1}%
+ \dosingleempty\math_alignment_start_indeed}
-\def\dostartmathalignment[#1][#2]%
+\def\math_alignment_start_indeed[#1]%
{% \begingroup not permitted ($$...assignments...\halign... )
- \pushmacro\doalignNC
- \edef\currentmathalignment{#1}%
- \doifassignmentelse{#2}{\setupmathalignment[#1][#2]}\donothing
- \def\NC{\doalignNC}%
- \global\let\doalignNC\dodoalignNC
- \def\EQ{&=}%
- \def\NR{&\global\let\doalignNC\dodoalignNC\doxxdoubleempty\doalignNR}%
- % amstex compatibility mode: (ugly, will disappear)
- \def\notag{\def\\{&\crcr}}%
- \doifelse{#2}{*}{\def\\{&\crcr}}{\def\\{&\doalignNR[+][]\crcr}}%
- % end of compatibility mode
- \eqaligncolumn\zerocount
+ \iffirstargument
+ \setupmathalignment[\currentmathalignment][#1]%
+ \fi
+ \the\everymathalignment
+ \c_math_eqalign_column\zerocount
\processcommacommand
[\mathalignmentparameter\c!align]
- {\advance\eqaligncolumn\plusone\doseteqaligncolumn}% takes argument
- % the real action
- \global\eqaligncolumn\plusone
+ {\advance\c_math_eqalign_column\plusone\doseteqaligncolumn}% takes argument
+ \global\c_math_eqalign_column\plusone
+ \dostarttagged\t!math\empty
+ \dostarttagged\t!mathtable\currentmathalignment
\numberedeqalign}
-\def\dostopmathalignment
- {\finishalignno
- \popmacro\doalignNC}
+\def\math_alignment_stop
+ {\math_finish_eqalign_no
+ \dostoptagged
+ \dostoptagged}
+
+\installcorenamespace{mathalignment}
+\installcorenamespace{mathalignmentvariant}
-\unexpanded\def\definemathalignment
- {\dodoubleempty\dodefinemathalignment}
+\installcommandhandler \??mathalignment {mathalignment} \??mathalignment
-\def\dodefinemathalignment[#1]% [#2]%
- {\setvalue{\e!start#1}{\dodoubleempty\dostartmathalignment[#1]}%
- \setvalue{\e!stop #1}{\dostopmathalignment}%
- \setupmathalignment[#1]}% [#2]
+\appendtoks
+ \setuevalue{\e!start\currentmathalignment}{\math_alignment_start{\currentmathalignment}}%
+ \setvalue {\e!stop \currentmathalignment}{\math_alignment_stop}%
+\to \everydefinemathalignment
-%D For the moment we only provide english commands.
+\setupmathalignment
+ [\c!n=2,
+ \c!m=1,
+ \c!distance=1em]
\definemathalignment[align] % default case (this is what amstex users expect)
\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing)
+\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_equalign
+ {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname
+ \ifcase\csname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname\or
+ \relax \or \hfill \or \hfill
+ \fi
+ \fi}
+
+\def\math_right_of_eqalign
+ {\ifcsname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname
+ \ifcase\csname\??mathalignmentvariant\number\c_math_eqalign_column\endcsname\or
+ \hfill \or \relax \or \hfill
+ \fi
+ \fi}
+
+\def\doseteqaligncolumn#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}
+
+\letvalue{\??mathalignmentvariant\v!normal}\zerocount
+\letvalue{\??mathalignmentvariant\v!left }\plusone
+\letvalue{\??mathalignmentvariant\v!right }\plustwo
+\letvalue{\??mathalignmentvariant\v!middle}\plusthree
+
+\def\math_align_NR_generic[#1][#2]%
+ {\donestedformulanumber{#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
@@ -292,17 +313,6 @@
%D
%D \startbuffer
%D \placeformula \startformula \startalign
-%D a &= b \\
-%D c &= d \notag \\
-%D &= e \notag \\
-%D &= f \\
-%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]
@@ -315,53 +325,6 @@
%D \typebuffer \getbuffer
%D
%D \startbuffer
-%D \placeformula \startformula \startalign[*]
-%D a &= b \\
-%D c &= d \\
-%D &= e \\
-%D &= f \\
-%D \stopalign \stopformula
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-%D
-%D \startbuffer
-%D \placeformula \startformula \startalign
-%D x &= y \\
-%D a &= b \\
-%D \stopalign \stopformula
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-%D
-%D \startbuffer
-%D \placeformula \startformula \startalign[m=3]
-%D x &= y & x &= y & z &= t \\
-%D a &= b & p &= q & w &= s \\
-%D \stopalign \stopformula
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-%D
-%D \startbuffer
-%D \placeformula \startformula \startalign[m=3,distance=0pt]
-%D x &= y &= x &= y &= z &= t \\
-%D a &= b &= p &= q &= w &= s \\
-%D \stopalign \stopformula
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-%D
-%D \startbuffer
-%D \placeformula \startformula \startalign[n=5,distance=0pt]
-%D x &= yy &= xx &= yy &= zz \\
-%D a &= b &= p &= q &= w \\
-%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
@@ -440,73 +403,64 @@
%D
%D Another wish \unknown
-\unexpanded\def\setupmathcases
- {\dodoubleempty\dosetupmathcases}
-
-\def\dosetupmathcases[#1][#2]%
- {\ifsecondargument
- \getparameters[\??ce#1][#2]%
- \else
- \getparameters[\??ce][#1]%
- \fi}
-
-\let\currentmathcases\empty
+\installcorenamespace{mathcases}
-\def\mathcasesparameter#1%
- {\executeifdefined{\??ce\currentmathcases#1}{\executeifdefined{\??ce#1}\empty}}
+\installcommandhandler \??mathcases {mathcases} \??mathcases
\setupmathcases
[\c!distance=1em,
\c!numberdistance=2.5em,
- \c!left={\left\{\,},
+ \c!left={\left\{\mskip\thinmuskip},
\c!right={\right.}]
-\def\dodocasesNC
- {\gdef\docasesNC{\endmath&}}
+\appendtoks
+ \setuevalue{\e!start\currentmathcases}{\math_cases_start{\currentmathcases}}%
+ \setvalue {\e!stop \currentmathcases}{\math_cases_stop}%
+\to \everydefinemathcases
-\let\docasesNR\doalignNR
-
-\def\dostartmathcases[#1][#2]%
+\unexpanded\def\math_cases_start#1%
{\begingroup
\edef\currentmathcases{#1}%
- \doifassignmentelse{#2}{\setupmathcases[#1][#2]}\donothing
+ \dosingleempty\math_cases_start_indeed}
+
+\unexpanded\def\math_cases_start_indeed[#1]%
+ {\iffirstargument
+ \setupcurrentmathcases[#1]%
+ \fi
\mathcasesparameter\c!left
\vcenter\bgroup
- \pushmacro\docasesNC
+ \pushmacro\math_cases_NC
\let\endmath\relax
- \def\NC{\docasesNC}%
- \def\MC{\docasesNC\ifmmode\else$\def\endmath{$}\fi}%
- \global\let\docasesNC\dodocasesNC
- \def\NR{\unskip\endmath&\global\let\docasesNC\dodocasesNC\doxxdoubleempty\docasesNR}%
+ \def\NC{\math_cases_NC}%
+ \def\MC{\math_cases_NC\ifmmode\else$\def\endmath{$}\fi}%
+ \global\let\math_cases_NC\math_cases_NC_indeed
+ \def\NR{\unskip\endmath&\global\let\math_cases_NC\math_cases_NC_indeed\doxxdoubleempty\math_cases_NR}%
\normalbaselines
\mathsurround\zeropoint
\everycr\emptytoks
\tabskip\zeropoint
- \global\eqaligncolumn\plusone
+ \global\c_math_eqalign_column\plusone
\halign\bgroup
$\mathcasesparameter\c!style##$\hfil
&\hskip\mathcasesparameter\c!distance\relax
- \popmacro\docasesNC##\hfil
+ \popmacro\math_cases_NC##\hfil
&\hskip\mathcasesparameter\c!numberdistance\relax
\let\formuladistance\!!zeropoint
- \span\textineqalign{##}%
+ \span\math_text_in_eqalign{##}%
\crcr} % todo: number
-\def\dostopmathcases
+\def\math_cases_stop
{\crcr
\egroup
- \popmacro\docasesNC
+ \popmacro\math_cases_NC
\egroup
\mathcasesparameter\c!right
\endgroup}
-\unexpanded\def\definemathcases
- {\dodoubleempty\dodefinemathcases}
+\def\math_cases_NC_indeed
+ {\gdef\math_cases_NC{\endmath&}}
-\def\dodefinemathcases[#1]% [#2]%
- {\setvalue{\e!start#1}{\dodoubleempty\dostartmathcases[#1]}%
- \setvalue{\e!stop #1}{\dostopmathcases}%
- \setupmathcases[#1]}% [#2]
+\let\math_cases_NR\math_align_NR_generic
\definemathcases[cases]
\definemathcases[\v!mathcases]
@@ -556,20 +510,9 @@
%D
%D Yet another one \unknown
-\unexpanded\def\setupmathmatrix
- {\dodoubleempty\dosetupmathmatrix}
-
-\def\dosetupmathmatrix[#1][#2]%
- {\ifsecondargument
- \getparameters[\??mx#1][#2]%
- \else
- \getparameters[\??mx][#1]%
- \fi}
-
-\let\currentmathmatrix\empty
+\installcorenamespace{mathmatrix}
-\def\mathmatrixparameter#1%
- {\executeifdefined{\??mx\currentmathmatrix#1}{\executeifdefined{\??mx#1}\empty}}
+\installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix
\setupmathmatrix
[\c!distance=1em,
@@ -577,127 +520,22 @@
\c!right=,
\c!align=\v!middle]
-\def\dosetmatrixcolumn#1% hh: todo: \definematrixalign
- {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfil
- \letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfil
- \doif{#1}\v!left {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\relax
- \letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfil}%
- \doif{#1}\v!right {\letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfil
- \letvalue{\??eq:\v!right:\number\eqaligncolumn}\relax }%
- \doif{#1}\v!middle{\letvalue{\??eq:\v!left :\number\eqaligncolumn}\hfil
- \letvalue{\??eq:\v!right:\number\eqaligncolumn}\hfil}}
-
-\def\buildmathmatrix % beware: etex only
- {\scratchtoks\emptytoks
- \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksa}}%
- \dorecurse{\numexpr\scratchcounter-\plusone\relax}
- {\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksb}}}%
- \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksc }}}
-
-\def\preparemathmatrix
- {\!!toksa{\strut \firstineqalign\leftofeqalign \span
- \textineqalign{\mathmatrixparameter\c!style ##}\rightofeqalign}%
- \!!toksb{&\hskip\mathmatrixparameter\c!distance
- \nextineqalign\leftofeqalign \span
- \textineqalign{\mathmatrixparameter\c!style ##}\rightofeqalign}%
- \!!toksc{&&\hskip\mathmatrixparameter\c!distance
- \leftofeqalign \span
- \textineqalign{\mathmatrixparameter\c!style ##}\rightofeqalign}%
- \buildmathmatrix
- \halign \@EA \bgroup\the\scratchtoks \crcr}
-
-\unexpanded\def\definemathmatrix
- {\dodoubleempty\dodefinemathmatrix}
-
-\def\dodefinemathmatrix[#1]% [#2]%
- {\setuvalue{\e!start#1}{\dodoubleempty\dostartmathmatrix[#1]}%
- \setvalue {\e!stop #1}{\dostopmathmatrix}% no u else lookahead problem
- \setupmathmatrix[#1]}% [#2]
-
-\definemathmatrix[matrix]
-\definemathmatrix[\v!mathmatrix]
-
-\unexpanded\def\dodomatrixNC
- {\gdef\domatrixNC{\endmath&}}
-
-\def\installmathmatrixhandler#1#2%
- {\setvalue{\??mx:#1}{#2}}
-
-% First alternative:
-%
-% \def\processlowhighmathmatrix#1%
-% {\def\mathmatrixleft
-% {\setbox\nextbox}
-% \def\mathmatrixright
-% {#1.5\dimexpr\nextboxdp-\nextboxht\relax
-% \hbox{$\mathmatrixparameter\c!left
-% \vcenter{\unvbox\nextbox}%
-% \mathmatrixparameter\c!right$}}%
-% \let\mathmatrixbox\vbox}
-%
-% \installmathmatrixhandler\v!high {\processlowhighmathmatrix\raise}
-% \installmathmatrixhandler\v!low {\processlowhighmathmatrix\lower}
-%
-% \installmathmatrixhandler\v!top {\processlowhighmathmatrix\raise}
-% \installmathmatrixhandler\v!bottom{\processlowhighmathmatrix\lower}
-%
-% \installmathmatrixhandler\v!lohi
-% {\def\mathmatrixleft {\mathmatrixparameter\c!left}%
-% \def\mathmatrixright{\mathmatrixparameter\c!right}%
-% \let\mathmatrixbox\vcenter}
-%
-% An alternative
-%
-% \let\mathmatrixleft \empty
-% \let\mathmatrixright\empty
-%
-% \def\processlowhighmathmatrix#1%
-% {\dowithnextbox
-% {#1.5\dimexpr\nextboxdp-\nextboxht\relax
-% \hbox{$\mathmatrixparameter\c!left
-% \vcenter{\unvbox\nextbox}%
-% \mathmatrixparameter\c!right$}}%
-% \vbox}
-%
-% \def\processlohimathmatrix
-% {\dowithnextbox
-% {\mathmatrixparameter\c!left
-% \vcenter{\unvbox\nextbox}%
-% \mathmatrixparameter\c!right}%
-% \vbox}
-%
-% \installmathmatrixhandler\v!high {\def\mathmatrixbox{\processlowhighmathmatrix\raise}}
-% \installmathmatrixhandler\v!low {\def\mathmatrixbox{\processlowhighmathmatrix\lower}}
-% \installmathmatrixhandler\v!top {\def\mathmatrixbox{\processlowhighmathmatrix\raise}}
-% \installmathmatrixhandler\v!bottom{\def\mathmatrixbox{\processlowhighmathmatrix\lower}}
-% \installmathmatrixhandler\v!lohi {\let\mathmatrixbox \processlohimathmatrix}
-%
-% Final version
-
-\let\mathmatrixleft \empty % experimental hook
-\let\mathmatrixright\empty % experimental hook
-
-\def\processlowhighmathmatrix#1#2%
- {\dowithnextbox
- {\scratchdimen\dimexpr(\nextboxdp-\nextboxht)/2 \ifcase#2\or+\mathaxisheight\textfont2\fi\relax
- \ifcase#1\relax\or\lower\scratchdimen\or\or\raise\scratchdimen\fi
- \hbox{$\mathmatrixparameter\c!left
- \vcenter{\unvbox\nextbox}%
- \mathmatrixparameter\c!right$}}%
- \vbox}
-
-\installmathmatrixhandler\v!top {\def\mathmatrixbox{\processlowhighmathmatrix\plusthree\plusone }}
-\installmathmatrixhandler\v!high {\def\mathmatrixbox{\processlowhighmathmatrix\plusthree\zerocount}}
-\installmathmatrixhandler\v!lohi {\def\mathmatrixbox{\processlowhighmathmatrix\plustwo \zerocount}}
-\installmathmatrixhandler\v!low {\def\mathmatrixbox{\processlowhighmathmatrix\plusone \zerocount}}
-\installmathmatrixhandler\v!bottom{\def\mathmatrixbox{\processlowhighmathmatrix\plusone \plusone }}
+\appendtoks
+ \setuevalue{\e!start\currentmathmatrix}{\math_matrix_start{\currentmathmatrix}}%
+ \setvalue {\e!stop \currentmathmatrix}{\math_matrix_stop}% no u else lookahead problem
+\to \everydefinemathmatrix
-\def\dostartmathmatrix[#1][#2]%
+\unexpanded\def\math_matrix_start#1%
{\begingroup
\edef\currentmathmatrix{#1}%
- \doifassignmentelse{#2}{\setupmathmatrix[#1][#2]}\donothing
+ \dosingleempty\math_matrix_start_indeed}
+
+\unexpanded\def\math_matrix_start_indeed[#1]%
+ {\iffirstargument
+ \setupcurrentmathmatrix[#1]%
+ \fi
\emptyhbox
- \executeifdefined{\??mx:\mathmatrixparameter\c!location}{\getvalue{\??mx:\v!lohi}}%
+ \math_matrix_align_method_analyze
\mathmatrixleft
\mathmatrixbox\bgroup
\pushmacro\domatrixNC
@@ -710,13 +548,15 @@
\mathsurround\zeropoint
\everycr\emptytoks
\tabskip\zeropoint
- \eqaligncolumn\zerocount % could be \scratchcounter
- \processcommacommand[\mathmatrixparameter\c!align]{\advance\eqaligncolumn\plusone\dosetmatrixcolumn}%
- \scratchcounter=\ifnum\eqaligncolumn>\zerocount \eqaligncolumn \else \plusone \fi
- \global\eqaligncolumn\plusone
- \preparemathmatrix } % uses scratchcounter
+ \c_math_eqalign_column\zerocount
+ \processcommacommand
+ [\mathmatrixparameter\c!align]
+ {\advance\c_math_eqalign_column\plusone\doseteqaligncolumn}% was \dosetmatrixcolumn
+ \scratchcounter=\ifnum\c_math_eqalign_column>\zerocount \c_math_eqalign_column \else \plusone \fi
+ \global\c_math_eqalign_column\plusone
+ \math_matrix_prepare}
-\def\dostopmathmatrix
+\def\math_matrix_stop
{\crcr
\mathstrut\crcr
\noalign{\kern-\baselineskip}%
@@ -726,6 +566,59 @@
\mathmatrixright
\endgroup}
+\definemathmatrix[matrix]
+\definemathmatrix[\v!mathmatrix]
+
+\def\math_matrix_prepare
+ {\!!toksa{\strut\math_first_in_eqalign\math_left_of_equalign\span
+ \math_text_in_eqalign{\mathmatrixparameter\c!style##}\math_right_of_eqalign}%
+ \!!toksb{&\hskip\mathmatrixparameter\c!distance
+ \math_next_in_eqalign\math_left_of_equalign\span
+ \math_text_in_eqalign{\mathmatrixparameter\c!style##}\math_right_of_eqalign}%
+ \!!toksc{&&\hskip\mathmatrixparameter\c!distance
+ \math_left_of_equalign\span
+ \math_text_in_eqalign{\mathmatrixparameter\c!style##}\math_right_of_eqalign}%
+ \scratchtoks\emptytoks
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksa}}%
+ \dorecurse{\numexpr\scratchcounter-\plusone\relax}
+ {\normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksb}}}%
+ \normalexpanded{\scratchtoks{\the\scratchtoks\the\!!toksc}}%
+ \halign \@EA \bgroup\the\scratchtoks \crcr}
+
+\unexpanded\def\dodomatrixNC
+ {\gdef\domatrixNC{\endmath&}}
+
+\installcorenamespace{mathmatrixalignmethod}
+
+\let\mathmatrixleft \empty % experimental hook
+\let\mathmatrixright\empty % experimental hook
+
+\def\math_matrix_process#1#2%
+ {\dowithnextbox
+ {\scratchdimen\dimexpr(\nextboxdp-\nextboxht)/2 \ifcase#2\or+\mathaxisheight\textfont2\fi\relax
+ \ifcase#1\relax\or\lower\scratchdimen\or\or\raise\scratchdimen\fi
+ \hbox{$\mathmatrixparameter\c!left
+ \vcenter{\unvbox\nextbox}%
+ \mathmatrixparameter\c!right$}}%
+ \vbox}
+
+\unexpanded\def\installmathmatrixalignmethod#1#2%
+ {\setvalue{\??mathmatrixalignmethod#1}{#2}}
+
+\def\math_matrix_align_method_analyze
+ {\csname\??mathmatrixalignmethod\ifcsname\??mathmatrixalignmethod\mathmatrixparameter\c!location\endcsname
+ \mathmatrixparameter\c!location
+ \else
+ \v!normal
+ \fi\endcsname}
+
+\installmathmatrixalignmethod\v!top {\def\mathmatrixbox{\math_matrix_process\plusthree\plusone }}
+\installmathmatrixalignmethod\v!high {\def\mathmatrixbox{\math_matrix_process\plusthree\zerocount}}
+\installmathmatrixalignmethod\v!lohi {\def\mathmatrixbox{\math_matrix_process\plustwo \zerocount}}
+\installmathmatrixalignmethod\v!low {\def\mathmatrixbox{\math_matrix_process\plusone \zerocount}}
+\installmathmatrixalignmethod\v!bottom{\def\mathmatrixbox{\math_matrix_process\plusone \plusone }}
+\installmathmatrixalignmethod\v!normal{\def\mathmatrixbox{\math_matrix_process\plustwo \zerocount}} % lohi
+
%D \startbuffer
%D \placeformula \startformula[-] \startmatrix
%D \NC 1 \NC x \NC a \NR
@@ -736,7 +629,7 @@
%D
%D \typebuffer \getbuffer
%D
-%D \definemathmatrix[bmatrix][left={\left[\,},right={\,\right]}]
+%D \definemathmatrix[bmatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}]
%D
%D \startbuffer
%D \placeformula \startformula[-] \startbmatrix
@@ -861,62 +754,21 @@
%D The intertext commands have to be expandable (in aligment lookahead) so
%D we cannot use \type {\unexpanded}.
-\let\stopintertext\relax
-
\def\startintertext#1\stopintertext
- {\noalign{\dointertext{#1}}}
+ {\noalign{\math_intertext{#1}}}
+
+\let\stopintertext\relax
\def\intertext#1%
- {\noalign{\dointertext{#1}}}
+ {\noalign{\math_intertext{#1}}}
-\unexpanded\def\dointertext#1%
+\unexpanded\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 \starttyping
-% %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 \stoptyping
-
-% \unexpanded\def\startsubstack
-% {\begingroup
-% \emptyhbox
-% \vcenter\bgroup
-% \pushmacro\domatrixNC
-% \let\stopmathmode\relax
-% \def\NC{\domatrixNC}%
-% \def\MC{\domatrixNC\startmathmode}%
-% \global\let\domatrixNC\dodomatrixNC
-% \def\NR
-% {\stopmathmode
-% \global\let\domatrixNC\dodomatrixNC
-% \crcr\noalign{\nointerlineskip}}%
-% \mathsurround\zeropoint
-% \everycr\emptytoks
-% \halign\bgroup\hfil$\scriptstyle\mathstrut##$\hfil\crcr}
-
-% \unexpanded\def\stopsubstack
-% {\crcr
-% \egroup
-% \popmacro\domatrixNC
-% \egroup
-% \endgroup}
-
%D \macros
%D {substack}
%D
@@ -967,7 +819,7 @@
\everycr\emptytoks
\halign\bgroup\hfil$\scriptstyle##$\hfil\crcr}
-\unexpanded\def\stopsubstack
+\def\stopsubstack
{\crcr
\egroup
\egroup
@@ -982,12 +834,12 @@
\ifx\mathparentwd\undefined \newdimen\mathparentwd \fi
-\let\normalbordermatrix\bordermatrix
+\let\normalbordermatrix\bordermatrix % move that code to here instead
\def\bordermatrix
{\begingroup
\setbox\scratchbox\hbox{\mr\char"239C}%
- \global\mathparentwd\wd\scratchbox\relax
+ \global\mathparentwd\wd\scratchbox
\endgroup
\normalbordermatrix}
@@ -1017,11 +869,11 @@
%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.
-%D These macros are a clearer version of \type{\binrel@} and
-%D \type{\binrel@@} macros in \AMSTEX\ packages.
-
-\def\preparebinrel#1%
+\def\math_binrel_apply#1%
{\begingroup
\setbox\scratchbox\hbox
{\thinmuskip 0mu
@@ -1030,48 +882,46 @@
\setbox\scratchbox\hbox{$#1\mathsurround\zeropoint$}%
\kern-\wd\scratchbox
${}#1{}\mathsurround\zeropoint$}%
- \normalexpanded
- {\endgroup
- \let\noexpand\currentbinrel
- \ifdim\wd\scratchbox<\zeropoint
- \mathbin
- \else\ifdim\wd\scratchbox>\zeropoint
- \mathrel
- \else
- \relax
- \fi\fi}}
+ \ifdim\wd\scratchbox<\zeropoint
+ \endgroup
+ \expandafter\mathbin
+ \else\ifdim\wd\scratchbox>\zeropoint
+ \endgroup
+ \expandafter\expandafter\expandafter\mathrel
+ \else
+ \endgroup
+ \expandafter\expandafter\expandafter\firstofoneargument
+ \fi\fi}
\unexpanded\def\overset#1#2%
- {\preparebinrel{#2}%
- \currentbinrel{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}}
+ {\math_binrel_apply{#2}{\mathop{\kern\zeropoint#2}\limits\normalsuperscript{#1}}}
\unexpanded\def\underset#1#2%
- {\preparebinrel{#2}%
- \currentbinrel{\mathop{\kern\zeropoint#2}\limits\normalsubscript{#1}}}
+ {\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
%D are also handled. The macros \type {\startinnermath} and
%D \type {\stopinnermath} can be overloaded in specialized
%D modules.
-\unexpanded\def\startinnermath
- {\getvalue{\e!start\??fm\formulaparameter\c!align}}
+\installcorenamespace{mathinnerstart}
+\installcorenamespace{mathinnerstop}
-\unexpanded\def\stopinnermath
- {\getvalue{\e!stop \??fm\formulaparameter\c!align}}
+\unexpanded\def\startinnermath{\csname\??mathinnerstart\formulaparameter\c!align\endcsname}
+\unexpanded\def\stopinnermath {\csname\??mathinnerstop \formulaparameter\c!align\endcsname}
-\def\mathinnerstrut
+\unexpanded\def\mathinnerstrut
{\doif{\formulaparameter\c!strut}\v!yes\strut}
-\long\unexpanded\def\defineinnermathhandler#1#2#3%
- {\setvalue{\e!start\??fm#1}{#2}%
- \setvalue{\e!stop \??fm#1}{#3}}
+\unexpanded\def\defineinnermathhandler#1#2#3%
+ {\setvalue{\??mathinnerstart#1}{#2}%
+ \setvalue{\??mathinnerstop #1}{#3}}
\newif\iftracemath
-\def\mathhbox
+\def\math_hbox
{\iftracemath\ruledhbox\else\hbox\fi}
\newconstant\mathraggedstatus % normal left center right
@@ -1079,40 +929,47 @@
\let\mathnumbercorrection\!!zeropoint
+\let\math_the_r_eq_no\empty
+\let\math_the_l_eq_no\empty
+
\unexpanded\def\startmathbox#1%
{\hsize\displaywidth
\global\mathnumberstatus\plusone
\mathraggedstatus#1\relax
\let\mathnumbercorrection\!!zeropoint
- \global\let\@eqno \empty \def\eqno {\gdef\@eqno }%
- \global\let\@leqno\empty \def\leqno{\gdef\@leqno}%
+ \global\let\math_the_r_eq_no\empty
+ \global\let\math_the_l_eq_no\empty
+ \def\reqno{\gdef\math_the_r_eq_no}%
+ \def\leqno{\gdef\math_the_l_eq_no}%
+ \let\eqno\reqno
% added
- \let\normalreqno\eqno
+ \let\normalreqno\reqno
\let\normalleqno\leqno
+ \let\normaleqno \eqno
% added
\doplaceformulanumber
- \setbox\scratchbox\mathhbox to \displaywidth\bgroup
+ \setbox\scratchbox\math_hbox to \displaywidth\bgroup
\mathinnerstrut
$%
\displaystyle
\ifcase\mathraggedstatus\or\hfill\or\hfill\fi}
-\def\llappedmathno
+\def\math_box_llapped_math_no
{\ifcase\mathraggedstatus\or
- \@eqno
+ \math_the_r_eq_no
\or
- \llap{\@eqno}%
+ \llap{\math_the_r_eq_no}%
\or
- \llap{\@eqno}%
+ \llap{\math_the_r_eq_no}%
\fi}
-\def\rlappedmathno
+\def\math_box_rlapped_math_no
{\ifcase\mathraggedstatus\or
- \rlap{\@leqno}%
+ \rlap{\math_the_l_eq_no}%
\or
- \rlap{\@leqno}%
+ \rlap{\math_the_l_eq_no}%
\or
- \@leqno
+ \math_the_l_eq_no
\fi}
\unexpanded\def\stopmathbox
@@ -1130,21 +987,21 @@
\ifcase\mathnumberstatus
\box\scratchbox
\or
- \ifx\@leqno\empty
- \ifx\@eqno\empty
+ \ifx\math_the_l_eq_no\empty
+ \ifx\math_the_r_eq_no\empty
\box\scratchbox
\else
\ifdone
- \vbox{\box\scratchbox\hbox to \displaywidth{\hss\llappedmathno}}%
+ \vbox{\box\scratchbox\hbox to \displaywidth{\hss\math_box_llapped_math_no}}%
\else
- \hss\box\scratchbox\llappedmathno % hss makes room for number
+ \hss\box\scratchbox\math_box_llapped_math_no % hss makes room for number
\fi
\fi
\else
\ifdone
- \vbox{\hbox to \displaywidth{\rlappedmathno\hss}\box\scratchbox}%
+ \vbox{\hbox to \displaywidth{\math_box_rlapped_math_no\hss}\box\scratchbox}%
\else
- \rlappedmathno\box\scratchbox\hss % hss makes room for number
+ \math_box_rlapped_math_no\box\scratchbox\hss % hss makes room for number
\fi
\fi
\or
@@ -1293,7 +1150,7 @@
% \NC 3 \NC z \NC c \NR
% \stopmatrix \stopformula
-% \definemathmatrix[bordermatrix][left={\left[\,},right={\,\right]}]
+% \definemathmatrix[bordermatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}]
% \placeformula \startformula[-] \startbordermatrix
% \NC 1 \NC x \NC a \NR
diff --git a/Master/texmf-dist/tex/context/base/math-ams.mkii b/Master/texmf-dist/tex/context/base/math-ams.mkii
index 83070d01a5a..c73a890c02f 100644
--- a/Master/texmf-dist/tex/context/base/math-ams.mkii
+++ b/Master/texmf-dist/tex/context/base/math-ams.mkii
@@ -5,7 +5,7 @@
%D subtitle=AMS Specials,
%D author={Hans Hagen \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-arr.mkii b/Master/texmf-dist/tex/context/base/math-arr.mkii
index 3b9abaa9108..71a833b8974 100644
--- a/Master/texmf-dist/tex/context/base/math-arr.mkii
+++ b/Master/texmf-dist/tex/context/base/math-arr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Arrows,
%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-arr.mkiv b/Master/texmf-dist/tex/context/base/math-arr.mkiv
index 31f8a66eba5..f18d6be2b27 100644
--- a/Master/texmf-dist/tex/context/base/math-arr.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-arr.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Arrows,
%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -15,9 +15,32 @@
\unprotect
-%D These will be generalized! Is it still needed in \MKIV?
-
-\def\exmthfont#1{\symbolicsizedfont#1\plusone{MathExtension}}
+%D These will be generalized! Is it still needed in \MKIV? Also, we need to
+%D to it using regular opentype math!
+
+% Plain code:
+%
+% \def\rightarrowfill
+% {$%
+% \mathsurround\zeropoint
+% \smash-%
+% \mkern-7mu%
+% \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+% \mkern-7mu%
+% \mathord\rightarrow
+% $}
+%
+% \def\leftarrowfill % brrr no longer in luated
+% {$%
+% \mathsurround\zeropoint
+% \mathord\leftarrow
+% \mkern-7mu%
+% \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
+% \mkern-7mu
+% \smash-$
+% $}
+
+\def\exmthfont#1{\mr} % \symbolicsizedfont#1\plusone{MathExtension}}
\def\domthfrac#1#2#3#4#5#6#7%
{\begingroup
@@ -26,7 +49,7 @@
\setbox2\hbox{$#1 #7$}%
\dimen0\wd0
\ifdim\wd2>\dimen0 \dimen0\wd2 \fi
- \setbox4\hbox to \dimen0{\exmthfont#2#3\leaders\hbox{#4}\hss#5}%
+ \setbox4\hbox to \dimen0{\leaders\hbox{#4}\hss#5}%
\mathord{\vcenter{{\offinterlineskip
\hbox to \dimen0{\hss\box0\hss}%
\kern \ht4%
@@ -76,6 +99,47 @@
\def\mtharrfactor{1}
\def\mtharrextra {0}
+% \def\domthxarr#1#2#3#4#5% hm, looks like we do a double mathrel
+% {\begingroup
+% \def\mtharrfactor{1}%
+% \def\mtharrextra {0}%
+% \processaction[#1] % will be sped up
+% [ \v!none=>\def\mtharrfactor{0},
+% \v!small=>\def\mtharrextra{10},
+% \v!medium=>\def\mtharrextra{15},
+% \v!big=>\def\mtharrextra{20},
+% \v!normal=>,
+% \v!default=>,
+% \v!unknown=>\doifnumberelse{#1}{\def\mtharrextra{#1}}\donothing]%
+% \mathsurround\zeropoint
+% \muskip0=\thirdoffourarguments #2mu
+% \muskip2=\fourthoffourarguments #2mu
+% \muskip4=\firstoffourarguments #2mu
+% \muskip6=\secondoffourarguments #2mu
+% \muskip0=\mtharrfactor\muskip0 \advance\muskip0 \mtharrextra mu
+% \muskip2=\mtharrfactor\muskip2 \advance\muskip2 \mtharrextra mu
+% \setbox0\hbox{$\scriptstyle
+% \mkern\muskip4\relax
+% \mkern\muskip0\relax
+% #5\relax
+% \mkern\muskip2\relax
+% \mkern\muskip6\relax
+% $}%
+% \setbox4\hbox{#3\displaystyle}%
+% \dimen0\wd0
+% \ifdim\wd4>\dimen0 \dimen0\wd4 \fi
+% \setbox2\hbox{$\scriptstyle
+% \mkern\muskip4\relax
+% \mkern\muskip0\relax
+% #4\relax
+% \mkern\muskip2\relax
+% \mkern\muskip6\relax
+% $}%
+% \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
+% \setbox4\hbox to \dimen0{#3\displaystyle}%
+% \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits\normalsuperscript{\box0}\normalsubscript{\box2}}%
+% \endgroup}
+
\def\domthxarr#1#2#3#4#5% hm, looks like we do a double mathrel
{\begingroup
\def\mtharrfactor{1}%
@@ -91,26 +155,24 @@
\mathsurround\zeropoint
\muskip0=\thirdoffourarguments #2mu
\muskip2=\fourthoffourarguments #2mu
- \muskip4=\firstoffourarguments #2mu
- \muskip6=\secondoffourarguments #2mu
- \muskip0=\mtharrfactor\muskip0 \advance\muskip0 \mtharrextra mu
- \muskip2=\mtharrfactor\muskip2 \advance\muskip2 \mtharrextra mu
+ \muskip0=\mtharrfactor\muskip0
+ \muskip2=\mtharrfactor\muskip2
+ \advance\muskip0 \mtharrextra mu
+ \advance\muskip2 \mtharrextra mu
+ \advance\muskip0 \firstoffourarguments #2mu
+ \advance\muskip2 \secondoffourarguments #2mu
\setbox0\hbox{$\scriptstyle
- \mkern\muskip4\relax
\mkern\muskip0\relax
#5\relax
\mkern\muskip2\relax
- \mkern\muskip6\relax
$}%
\setbox4\hbox{#3\displaystyle}%
\dimen0\wd0
\ifdim\wd4>\dimen0 \dimen0\wd4 \fi
\setbox2\hbox{$\scriptstyle
- \mkern\muskip4\relax
\mkern\muskip0\relax
#4\relax
\mkern\muskip2\relax
- \mkern\muskip6\relax
$}%
\ifdim\wd2>\dimen0 \dimen0\wd2 \fi
\setbox4\hbox to \dimen0{#3\displaystyle}%
@@ -122,6 +184,16 @@
%D There are some arrows which are created by stacking two arrows. The next
%D macro helps in defining such \quotation{double arrows}.
+% weird, we get a shift with the double ... but will become core luatex anyway
+%
+% \startchemicalformula
+% \chemical{S}
+% \chemical{+}
+% \chemical{O_2}
+% \chemical{EQUILIBRIUM}{boven}{onder}
+% \chemical{SO_2}
+% \stopchemicalformula
+
\def\domthxarrdouble#1#2#3#4#5#6#7% opt l r sp rs top bot
{\mathrel
{\scratchdimen.32ex\relax % was .22, todo: make configurable
diff --git a/Master/texmf-dist/tex/context/base/math-cow.mkii b/Master/texmf-dist/tex/context/base/math-cow.mkii
index f0fc811c871..04f659b4425 100644
--- a/Master/texmf-dist/tex/context/base/math-cow.mkii
+++ b/Master/texmf-dist/tex/context/base/math-cow.mkii
@@ -5,7 +5,7 @@
%D subtitle=Cow Math,
%D author={Hans Hagen \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-def.mkiv b/Master/texmf-dist/tex/context/base/math-def.mkiv
index a7e0df94030..43a511e434a 100644
--- a/Master/texmf-dist/tex/context/base/math-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-def.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Definitions,
%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -18,41 +18,25 @@
% this will be done at the lua end
\startluacode
- mathematics.define()
- mathematics.xml.registerentities()
+ mathematics.define(\number\defaultmathfamily)
+ -- mathematics.xml.registerentities()
\stopluacode
\activatemathcharacters
-% will be attributes
+% will go to math-ext (if used at all)
-\setfalse \automathpunctuation
-
-\def\enablemathpunctuation {\settrue \automathpunctuation}
-\def\disablemathpunctuation{\setfalse\automathpunctuation}
-
-\def\v!autopunctuation{autopunctuation}
-
-\appendtoks
- \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\enablemathpunctuation\disablemathpunctuation
-\to \everysetupmathematics
-
-% \appendtoks
-% \ifconditional\automathpunctuation\attribute\mathpunctuationattribute\plusone\fi
-% \to \everymathematics
-
-\setupmathematics[\v!autopunctuation=\v!yes]
-
-% will go to math-ext
-
-\Umathchardef\braceld=0 \mrfam "FF07A
-\Umathchardef\bracerd=0 \mrfam "FF07B
-\Umathchardef\bracelu=0 \mrfam "FF07C
-\Umathchardef\braceru=0 \mrfam "FF07D
+\Umathchardef\braceld=0 \defaultmathfamily "FF07A
+\Umathchardef\bracerd=0 \defaultmathfamily "FF07B
+\Umathchardef\bracelu=0 \defaultmathfamily "FF07C
+\Umathchardef\braceru=0 \defaultmathfamily "FF07D
% ctx specific
-\def\|{|} % still letter
+% \bgroup
+% \catcode`|=\othercatcode
+% \global\let\|=|
+% \egroup
% The \mfunction macro is an alternative for \hbox with a
% controlable font switch.
@@ -95,12 +79,12 @@
\definemathcommand [tanh] [nolop] {\mfunctionlabeltext{tanh}}
\definemathcommand [tan] [nolop] {\mfunctionlabeltext{tan}}
-\definemathcommand [integers] {{\mathblackboard Z}}
-\definemathcommand [reals] {{\mathblackboard R}}
-\definemathcommand [rationals] {{\mathblackboard Q}}
-\definemathcommand [naturalnumbers]{{\mathblackboard N}}
-\definemathcommand [complexes] {{\mathblackboard C}}
-\definemathcommand [primes] {{\mathblackboard P}}
+% \definemathcommand [integers] {{\mathblackboard Z}}
+% \definemathcommand [reals] {{\mathblackboard R}}
+% \definemathcommand [rationals] {{\mathblackboard Q}}
+% \definemathcommand [naturalnumbers]{{\mathblackboard N}}
+% \definemathcommand [complexes] {{\mathblackboard C}}
+% \definemathcommand [primes] {{\mathblackboard P}}
\let\normalmatharg\arg % todo: maybe automatically
@@ -122,6 +106,8 @@
\def\doleftbigmath #1{\ifx#1\relax\else\left#1\expandafter\doleftbigmath \fi}
\def\dorightbigmath#1{\ifx#1\relax\else\right.\expandafter\dorightbigmath\fi}
+\installcorenamespace{mathbig}
+
\def\choosemathbig#1#2% so we accent \big{||} as well
{{\hbox{$%
\ifcase\bigmathdelimitermethod
@@ -133,17 +119,17 @@
\dorightbigmath#2\relax
\else
\doleftbigmath#2\relax
- \vbox\!!to\getvalue{\??mm:b:\number#1}\bodyfontsize{}%
+ \vbox\!!to\getvalue{\??mathbig\number#1}\bodyfontsize{}%
\dorightbigmath#2\relax
\fi
\nulldelimiterspace\zeropoint\relax
\mathsurround\zeropoint
$}}}
-\definemathcommand [big] {\choosemathbig\plusone } \setvalue{\??mm:b:1}{0.85}
-\definemathcommand [Big] {\choosemathbig\plustwo } \setvalue{\??mm:b:2}{1.15}
-\definemathcommand [bigg] {\choosemathbig\plusthree} \setvalue{\??mm:b:3}{1.45}
-\definemathcommand [Bigg] {\choosemathbig\plusfour } \setvalue{\??mm:b:4}{1.75}
+\definemathcommand [big] {\choosemathbig\plusone } \setvalue{\??mathbig1}{0.85}
+\definemathcommand [Big] {\choosemathbig\plustwo } \setvalue{\??mathbig2}{1.15}
+\definemathcommand [bigg] {\choosemathbig\plusthree} \setvalue{\??mathbig3}{1.45}
+\definemathcommand [Bigg] {\choosemathbig\plusfour } \setvalue{\??mathbig4}{1.75}
\definemathcommand [bigl] [open] [one] {\big}
\definemathcommand [bigm] [rel] [one] {\big}
@@ -158,9 +144,7 @@
\definemathcommand [Biggm] [rel] [one] {\Bigg}
\definemathcommand [Biggr] [close] [one] {\Bigg}
-% special
-
-%AM: Optimize this! Add similar options for sums.
+%D This needs checking:
\def\setoperatorlimits#1#2% operator limits
{\savenormalmeaning{#1}%
@@ -176,7 +160,9 @@
\setoperatorlimits\ointclockwise \intlimits
\setoperatorlimits\ointctrclockwise \intlimits
-%D This is a temporary hack until we figure out how to do this correctly.
+%D This is a temporary hack until we figure out how to do this correctly,
+%D preferably using math parameters but we can also consider doing some
+%D node juggling here.
\unexpanded\def\implies {\mathrel{\;\Longrightarrow\;}}
\unexpanded\def\impliedby{\mathrel{\;\Longleftarrow\;}}
@@ -224,7 +210,7 @@
%D $\sqrt[3]{10}$
%D \stoptyping
-\def\rootradical{\Uroot 0 "221A } % can be done in char-def
+\def\rootradical{\Uroot \defaultmathfamily "221A } % can be done in char-def
\def\root#1\of{\rootradical{#1}} % #2
@@ -233,18 +219,9 @@
\def\rootwithdegree [#1]{\rootradical{#1}}
\def\rootwithoutdegree {\rootradical {}}
-\def\PLAINmatrix#1%
- {\emptyhbox\,\vcenter{\normalbaselines\mathsurround\zeropoint
- \ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
- \mathstrut\crcr\noalign{\kern-\baselineskip}
- #1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}\,}
-
\definemathcommand [mathstrut] {\vphantom{(}}
\definemathcommand [joinrel] {\mathrel{\mkern-3mu}}
-% \definemathcommand [matrix] {\PLAINmatrix}
-% \definemathcommand [over] {\normalover} % hack, to do
-
\unexpanded\def\{{\mathortext\lbrace\letterleftbrace }
\unexpanded\def\}{\mathortext\rbrace\letterrightbrace}
@@ -291,17 +268,9 @@
\definemathcommand [colonsep] {\mkern-1.2mu}
\definemathcommand [doublecolonsep] {\mkern-0.9mu}
-%D The next macro vertically centeres its contents.
-
-\def\@center@math#1%
- {\vcenter{\hbox{$\mathsurround\zeropoint#1$}}}
-
-\def\@center@colon
- {\mathpalette\@center@math{\colon}}
+%D Now we define all the colon relations .. needs checking with char-def.lua:
-%D Now we define all the colon relations.
-
-\definemathcommand [centercolon] [rel] {\@center@colon}
+\definemathcommand [centercolon] [rel] {\mathstylevcenteredhbox\colon}
\definemathcommand [colonminus] [rel] {\centercolon\colonsep\mathrel{-}}
\definemathcommand [minuscolon] [rel] {\mathrel{-}\colonsep\centercolon}
\definemathcommand [colonequals] [rel] {\centercolon\colonsep=}
@@ -323,15 +292,39 @@
%D Goodies. We might move this elsewhere.
-\def\underleftarrow #1{\mathop{\Uunderdelimiter 0 "2190 {#1}}}
-\def\overleftarrow #1{\mathop{\Uoverdelimiter 0 "2190 {#1}}}
-\def\underrightarrow#1{\mathop{\Uunderdelimiter 0 "2192 {#1}}}
-\def\overrightarrow #1{\mathop{\Uoverdelimiter 0 "2192 {#1}}}
-
-% todo: \Udelimiterover, \Udelimiterunder
-
-\def\normaldoublebrace {\Umathaccents 0 0 "23DE 0 0 "23DF }
-\def\normaldoubleparent{\Umathaccents 0 0 "23DC 0 0 "23DD }
+% Be careful in choosing what accents you take (the code below uses a
+% combining one):
+%
+% \startbuffer
+% % $\Umathaccent top 0 0 "20D7 {example}$
+% % $\Umathaccent top fixed 0 0 "20D7 {example}$
+% $\Umathaccent 0 0 "20D7 {example}$
+% $\Umathaccent fixed 0 0 "20D7 {example}$
+% $\Umathaccent bottom 0 0 "20D7 {example}$
+% $\Umathaccent bottom fixed 0 0 "20D7 {example}$
+% $\Umathaccent both 0 0 "20D7
+% 0 0 "20D7 {example}$
+% $\Umathaccent both fixed 0 0 "20D7
+% fixed 0 0 "20D7 {example}$
+% $\Umathaccent both 0 0 "20D7
+% fixed 0 0 "20D7 {example}$
+% $\Umathaccent both fixed 0 0 "20D7
+% 0 0 "20D7 {example}$
+% \stopbuffer
+%
+% \setupbodyfont[modern] \getbuffer
+% \setupbodyfont[xits] \getbuffer
+% \setupbodyfont[cambria] \getbuffer
+
+\unexpanded\def\underleftarrow #1{\mathop{\Uunderdelimiter \defaultmathfamily "2190 {#1}}}
+\unexpanded\def\overleftarrow #1{\mathop{\Uoverdelimiter \defaultmathfamily "2190 {#1}}}
+\unexpanded\def\underrightarrow#1{\mathop{\Uunderdelimiter \defaultmathfamily "2192 {#1}}}
+\unexpanded\def\overrightarrow #1{\mathop{\Uoverdelimiter \defaultmathfamily "2192 {#1}}}
+
+% watch out: here we have a class (zero):
+
+\unexpanded\def\normaldoublebrace {\Umathaccents 0 \defaultmathfamily "23DE 0 \defaultmathfamily "23DF }
+\unexpanded\def\normaldoubleparent{\Umathaccents 0 \defaultmathfamily "23DC 0 \defaultmathfamily "23DD }
\let\normaloverbrace \overbrace
\let\normalunderbrace \underbrace
@@ -356,14 +349,17 @@
\unexpanded\def\underrightarrow{\mathopwithlimits\normalunderrightarrow}
\unexpanded\def\overrightarrow {\mathopwithlimits\normaloverrightarrow }
+\let\lceil \lceiling
+\let\rceil \rceiling
+
\let\normalsurd\surd
\unexpanded\def\surd{\normalsurd{}}
% todo mathclass=punctuation ord
-% \Umathcode"02C="6 "0 "02C
-% \Umathcode"02E="0 "0 "02E
+% \Umathcode"02C="6 \defaultmathfamily "02C
+% \Umathcode"02E="0 \defaultmathfamily "02E
% tricky .. todo
diff --git a/Master/texmf-dist/tex/context/base/math-del.mkiv b/Master/texmf-dist/tex/context/base/math-del.mkiv
index 5ffda1919cb..569b4cd3def 100644
--- a/Master/texmf-dist/tex/context/base/math-del.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-del.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Delimiters,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -27,22 +27,24 @@
%D \fakerightdelimiter
%D \stoptyping
-\newcount\delimitercount
+% Actually we can do better now with lua hacks.
-\def\leftfakedelimiter {\advance\delimitercount\minusone\gobbleoneargument}%
-\def\rightfakedelimiter{\advance\delimitercount\plusone \gobbleoneargument}%
+\newcount\c_math_delimiter_nesting
+
+\def\leftfakedelimiter {\advance\c_math_delimiter_nesting\minusone\gobbleoneargument}
+\def\rightfakedelimiter{\advance\c_math_delimiter_nesting\plusone \gobbleoneargument}
\def\checkdelimiters#1%
- {\delimitercount\zerocount
+ {\c_math_delimiter_nesting\zerocount
\setbox\scratchbox\hbox\bgroup
\let\left \leftfakedelimiter
\let\right\rightfakedelimiter
$#1\expandafter$\expandafter
\egroup
- \expandafter\delimitercount\the\delimitercount\relax}
+ \expandafter\c_math_delimiter_nesting\the\c_math_delimiter_nesting\relax}
-\def\fakeleftdelimiter {\ifnum\delimitercount>\zerocount\left .\fi}
-\def\fakerightdelimiter{\ifnum\delimitercount<\zerocount\right.\fi}
+\def\fakeleftdelimiter {\ifnum\c_math_delimiter_nesting>\zerocount\left .\fi}
+\def\fakerightdelimiter{\ifnum\c_math_delimiter_nesting<\zerocount\right.\fi}
%D The following macros are used in the MathML interpreter, so
%D there is a good change of them never being documented for
@@ -51,11 +53,11 @@
\let\normalordelimiter\secondoftwoarguments
\let\normalorfiller \firstoftwoarguments
-\def\enabledelimiter {\let\normalordelimiter\secondoftwoarguments}
-\def\disabledelimiter{\let\normalordelimiter\firstoftwoarguments}
+\unexpanded\def\enabledelimiter {\let\normalordelimiter\secondoftwoarguments}
+\unexpanded\def\disabledelimiter{\let\normalordelimiter\firstoftwoarguments}
-\def\enablefiller {\let\normalorfiller\secondoftwoarguments}
-\def\disablefiller {\let\normalorfiller\firstoftwoarguments}
+\unexpanded\def\enablefiller {\let\normalorfiller\secondoftwoarguments}
+\unexpanded\def\disablefiller {\let\normalorfiller\firstoftwoarguments}
\def\mathopnolimits#1{\mathop{\mr#1}\nolimits} % was \rm, which follows text fonts (used in mml parser)
\def\mathopdolimits#1{\mathop{\mr#1}} % was \rm, which follows text fonts (used in mml parser)
diff --git a/Master/texmf-dist/tex/context/base/math-dim.lua b/Master/texmf-dist/tex/context/base/math-dim.lua
index 7b4b49f6860..d245bfb3aaf 100644
--- a/Master/texmf-dist/tex/context/base/math-dim.lua
+++ b/Master/texmf-dist/tex/context/base/math-dim.lua
@@ -22,171 +22,77 @@ if not modules then modules = { } end modules ['math-dim'] = {
local abs, next = math.abs, next
local defaults = {
- ['axis']={
- ['default']={ "AxisHeight", "axis_height" },
- },
- ['accent_base_height']={
- ['default']={ "AccentBaseHeight", "x_height" },
- },
- ['fraction_del_size']={
- ['default']={ "FractionDelimiterSize", "delim2" },
- ['cramped_display_style']={ "FractionDelimiterDisplayStyleSize", "delim1" },
- ['display_style']={ "FractionDelimiterDisplayStyleSize", "delim1" },
- },
- ['fraction_denom_down']={
- ['default']={ "FractionDenominatorShiftDown", "denom2" },
- ['cramped_display_style']={ "FractionDenominatorDisplayStyleShiftDown", "denom1" },
- ['display_style']={ "FractionDenominatorDisplayStyleShiftDown", "denom1" },
- },
- ['fraction_denom_vgap']={
- ['default']={ "FractionDenominatorGapMin", "default_rule_thickness" },
- ['cramped_display_style']={ "FractionDenominatorDisplayStyleGapMin", "3*default_rule_thickness" },
- ['display_style']={ "FractionDenominatorDisplayStyleGapMin", "3*default_rule_thickness" },
- },
- ['fraction_num_up']={
- ['default']={ "FractionNumeratorShiftUp", "num2" },
- ['cramped_display_style']={ "FractionNumeratorDisplayStyleShiftUp", "num1" },
- ['display_style']={ "FractionNumeratorDisplayStyleShiftUp", "num1" },
- },
- ['fraction_num_vgap']={
- ['default']={ "FractionNumeratorGapMin", "default_rule_thickness" },
- ['cramped_display_style']={ "FractionNumeratorDisplayStyleGapMin", "3*default_rule_thickness" },
- ['display_style']={ "FractionNumeratorDisplayStyleGapMin", "3*default_rule_thickness" },
- },
- ['fraction_rule']={
- ['default']={ "FractionRuleThickness", "default_rule_thickness" },
- },
- ['limit_above_bgap']={
- ['default']={ "UpperLimitBaselineRiseMin", "big_op_spacing3" },
- },
- ['limit_above_kern']={
- ['default']={ "0", "big_op_spacing5" },
- },
- ['limit_above_vgap']={
- ['default']={ "UpperLimitGapMin", "big_op_spacing1" },
- },
- ['limit_below_bgap']={
- ['default']={ "LowerLimitBaselineDropMin", "big_op_spacing4" },
- },
- ['limit_below_kern']={
- ['default']={ "0", "big_op_spacing5" },
- },
- ['limit_below_vgap']={
- ['default']={ "LowerLimitGapMin", "big_op_spacing2" },
- },
-
---~ ['....']={
---~ ['default']={ "DisplayOperatorMinHeight", "....." },
---~ },
-
- ['overbar_kern']={
- ['default']={ "OverbarExtraAscender", "default_rule_thickness" },
- },
- ['overbar_rule']={
- ['default']={ "OverbarRuleThickness", "default_rule_thickness" },
- },
- ['overbar_vgap']={
- ['default']={ "OverbarVerticalGap", "3*default_rule_thickness" },
- },
- ['quad']={
- ['default']={ "font_size(f)", "math_quad" },
- },
- ['radical_kern']={
- ['default']={ "RadicalExtraAscender", "default_rule_thickness" },
- },
- ['radical_rule']={
- ['default']={ "RadicalRuleThickness", "default_rule_thickness" },
- -- ['default']={ "surd_height(f)", "default_rule_thickness" },
- },
- ['radical_vgap']={
- ['default']={ "RadicalVerticalGap", "default_rule_thickness+(abs(default_rule_thickness)/4)" },
- ['display_style']={ "RadicalDisplayStyleVerticalGap", "default_rule_thickness+(abs(math_x_height)/4)" },
- },
- ['space_after_script']={
- ['default']={ "SpaceAfterScript", "script_space" },
- },
- ['stack_denom_down']={
- ['default']={ "StackBottomShiftDown", "denom2" },
- ['cramped_display_style']={ "StackBottomDisplayStyleShiftDown", "denom1" },
- ['display_style']={ "StackBottomDisplayStyleShiftDown", "denom1" },
- },
- ['stack_num_up']={
- ['default']={ "StackTopShiftUp", "num3" },
- ['cramped_display_style']={ "StackTopDisplayStyleShiftUp", "num1" },
- ['display_style']={ "StackTopDisplayStyleShiftUp", "num1" },
- },
- ['stack_vgap']={
- ['default']={ "StackGapMin", "3*default_rule_thickness" },
- ['cramped_display_style']={ "StackDisplayStyleGapMin", "7*default_rule_thickness" },
- ['display_style']={ "StackDisplayStyleGapMin", "7*default_rule_thickness" },
- },
- ['sub_shift_down']={
- ['default']={ "SubscriptShiftDown", "sub1" },
- },
- ['sub_shift_drop']={
- ['default']={ "SubscriptBaselineDropMin", "sub_drop" },
- },
- ['sub_sup_shift_down']={
- ['default']={ "SubscriptShiftDown", "sub2" }, -- todo
- },
- ['sub_top_max']={
- ['default']={ "SubscriptTopMax", "abs(math_x_height*4)/5" },
- },
- ['subsup_vgap']={
- ['default']={ "SubSuperscriptGapMin", "4*default_rule_thickness" },
- },
- ['sup_bottom_min']={
- ['default']={ "SuperscriptBottomMin", "abs(math_x_height)/4" },
- },
- ['sup_shift_drop']={
- ['default']={ "SuperscriptBaselineDropMax", "sup_drop" },
- },
- ['sup_shift_up']={
- ['cramped_display_style']={ "SuperscriptShiftUpCramped", "sup3" },
- ['cramped_script_script_style']={ "SuperscriptShiftUpCramped", "sup3" },
- ['cramped_script_style']={ "SuperscriptShiftUpCramped", "sup3" },
- ['cramped_text_style']={ "SuperscriptShiftUpCramped", "sup3" },
- ['display_style']={ "SuperscriptShiftUp", "sup1" },
- ['script_script_style']={ "SuperscriptShiftUp", "sup2" },
- ['script_style']={ "SuperscriptShiftUp", "sup2" },
- ['text_style']={ "SuperscriptShiftUp", "sup2" },
- },
- ['sup_sub_bottom_max']={
- ['default']={ "SuperscriptBottomMaxWithSubscript", "abs(math_x_height*4)/5" },
- },
- ['underbar_kern']={
- ['default']={ "UnderbarExtraDescender", "0" },
- },
- ['underbar_rule']={
- ['default']={ "UnderbarRuleThickness", "default_rule_thickness" },
- },
- ['underbar_vgap']={
- ['default']={ "UnderbarVerticalGap", "3*default_rule_thickness" },
- },
- ['connector_overlap_min']={
- ['default']={ "MinConnectorOverlap", "0.25*default_rule_thickness" },
- },
- ['over_delimiter_vgap']={
- ['default']={ "StretchStackGapBelowMin", "big_op_spacing1" },
- },
- ['over_delimiter_bgap']={
- ['default']={ "StretchStackTopShiftUp", "big_op_spacing3" },
- },
- ['under_delimiter_vgap']={
- ['default']={ "StretchStackGapAboveMin", "big_op_spacing2" },
- },
- ['under_delimiter_bgap']={
- ['default']={ "StretchStackBottomShiftDown", "big_op_spacing4" },
- },
- ['radical_degree_before']={
- ['default']={ "RadicalKernBeforeDegree", "(5/18)*quad" },
- },
- ['radical_degree_after']={
- ['default']={ "RadicalKernAfterDegree", "(-10/18)*quad" },
- },
- ['radical_degree_raise']={
- ['default']={ "RadicalDegreeBottomRaisePercent", "60" },
- },
+ axis = { default = { "AxisHeight", "axis_height" }, },
+ accent_base_height = { default = { "AccentBaseHeight", "x_height" }, },
+ fraction_del_size = { default = { "FractionDelimiterSize", "delim2" },
+ cramped_display_style = { "FractionDelimiterDisplayStyleSize", "delim1" },
+ display_style = { "FractionDelimiterDisplayStyleSize", "delim1" }, },
+ fraction_denom_down = { default = { "FractionDenominatorShiftDown", "denom2" },
+ cramped_display_style = { "FractionDenominatorDisplayStyleShiftDown", "denom1" },
+ display_style = { "FractionDenominatorDisplayStyleShiftDown", "denom1" }, },
+ fraction_denom_vgap = { default = { "FractionDenominatorGapMin", "default_rule_thickness" },
+ cramped_display_style = { "FractionDenominatorDisplayStyleGapMin", "3*default_rule_thickness" },
+ display_style = { "FractionDenominatorDisplayStyleGapMin", "3*default_rule_thickness" }, },
+ fraction_num_up = { default = { "FractionNumeratorShiftUp", "num2" },
+ cramped_display_style = { "FractionNumeratorDisplayStyleShiftUp", "num1" },
+ display_style = { "FractionNumeratorDisplayStyleShiftUp", "num1" }, },
+ fraction_num_vgap = { default = { "FractionNumeratorGapMin", "default_rule_thickness" },
+ cramped_display_style = { "FractionNumeratorDisplayStyleGapMin", "3*default_rule_thickness" },
+ display_style = { "FractionNumeratorDisplayStyleGapMin", "3*default_rule_thickness" }, },
+ fraction_rule = { default = { "FractionRuleThickness", "default_rule_thickness" }, },
+ limit_above_bgap = { default = { "UpperLimitBaselineRiseMin", "big_op_spacing3" }, },
+ limit_above_vgap = { default = { "UpperLimitGapMin", "big_op_spacing1" }, },
+ limit_above_kern = { default = { "0", "big_op_spacing5" }, },
+ limit_below_bgap = { default = { "LowerLimitBaselineDropMin", "big_op_spacing4" }, },
+ limit_below_vgap = { default = { "LowerLimitGapMin", "big_op_spacing2" }, },
+ limit_below_kern = { default = { "0", "big_op_spacing5" }, },
+ math_operator_size = { default = { "DisplayOperatorMinHeight", "math_x_height*3" }, }, -- 2
+ overbar_kern = { default = { "OverbarExtraAscender", "default_rule_thickness" }, },
+ overbar_rule = { default = { "OverbarRuleThickness", "default_rule_thickness" }, },
+ overbar_vgap = { default = { "OverbarVerticalGap", "3*default_rule_thickness" }, },
+ quad = { default = { "font_size(f)", "math_quad" }, },
+ radical_kern = { default = { "RadicalExtraAscender", "default_rule_thickness" }, },
+ radical_rule = { default = { "RadicalRuleThickness", "default_rule_thickness" }, },
+ -- default = { "surd_height(f)", "default_rule_thickness" },
+ radical_vgap = { default = { "RadicalVerticalGap", "default_rule_thickness+(abs(default_rule_thickness)/4)" },
+ display_style = { "RadicalDisplayStyleVerticalGap", "default_rule_thickness+(abs(math_x_height)/4)" }, },
+ space_after_script = { default = { "SpaceAfterScript", "script_space" }, },
+ stack_denom_down = { default = { "StackBottomShiftDown", "denom2" },
+ cramped_display_style = { "StackBottomDisplayStyleShiftDown", "denom1" },
+ display_style = { "StackBottomDisplayStyleShiftDown", "denom1" }, },
+ stack_num_up = { default = { "StackTopShiftUp", "num3" },
+ cramped_display_style = { "StackTopDisplayStyleShiftUp", "num1" },
+ display_style = { "StackTopDisplayStyleShiftUp", "num1" }, },
+ stack_vgap = { default = { "StackGapMin", "3*default_rule_thickness" },
+ cramped_display_style = { "StackDisplayStyleGapMin", "7*default_rule_thickness" },
+ display_style = { "StackDisplayStyleGapMin", "7*default_rule_thickness" }, },
+ sub_shift_down = { default = { "SubscriptShiftDown", "sub1" }, },
+ sub_shift_drop = { default = { "SubscriptBaselineDropMin", "sub_drop" }, },
+ sub_sup_shift_down = { default = { "SubscriptShiftDown", "sub2" }, },
+ sub_top_max = { default = { "SubscriptTopMax", "abs(math_x_height*4)/5" }, },
+ subsup_vgap = { default = { "SubSuperscriptGapMin", "4*default_rule_thickness" }, },
+ sup_bottom_min = { default = { "SuperscriptBottomMin", "abs(math_x_height)/4" }, },
+ sup_shift_drop = { default = { "SuperscriptBaselineDropMax", "sup_drop" }, },
+ sup_shift_up = { cramped_display_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_script_script_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_script_style = { "SuperscriptShiftUpCramped", "sup3" },
+ cramped_text_style = { "SuperscriptShiftUpCramped", "sup3" },
+ display_style = { "SuperscriptShiftUp", "sup1" },
+ script_script_style = { "SuperscriptShiftUp", "sup2" },
+ script_style = { "SuperscriptShiftUp", "sup2" },
+ text_style = { "SuperscriptShiftUp", "sup2" }, },
+ sup_sub_bottom_max = { default = { "SuperscriptBottomMaxWithSubscript", "abs(math_x_height*4)/5" }, },
+ underbar_kern = { default = { "UnderbarExtraDescender", "0" }, },
+ underbar_rule = { default = { "UnderbarRuleThickness", "default_rule_thickness" }, },
+ underbar_vgap = { default = { "UnderbarVerticalGap", "3*default_rule_thickness" }, },
+ connector_overlap_min = { default = { "MinConnectorOverlap", "0.25*default_rule_thickness" }, },
+ over_delimiter_vgap = { default = { "StretchStackGapBelowMin", "big_op_spacing1" }, },
+ over_delimiter_bgap = { default = { "StretchStackTopShiftUp", "big_op_spacing3" }, },
+ under_delimiter_vgap = { default = { "StretchStackGapAboveMin", "big_op_spacing2" }, },
+ under_delimiter_bgap = { default = { "StretchStackBottomShiftDown", "big_op_spacing4" }, },
+ radical_degree_before = { default = { "RadicalKernBeforeDegree", "(5/18)*quad" }, },
+ radical_degree_after = { default = { "RadicalKernAfterDegree", "(-10/18)*quad" }, },
+ radical_degree_raise = { default = { "RadicalDegreeBottomRaisePercent", "60" }, },
}
local styles = {
@@ -218,7 +124,7 @@ end
function mathematics.dimensions(dimens) -- beware, dimens get spoiled
if dimens.SpaceAfterScript then
- dimens.SubscriptShiftDownWithSuperscript = dimens.SubscriptShiftDown * 1.5
+ dimens.SubscriptShiftDownWithSuperscript = dimens.SubscriptShiftDown * 1.5 -- move this one
return table.fastcopy(dimens), { }
elseif dimens.AxisHeight or dimens.axis_height then
local t = { }
@@ -233,6 +139,7 @@ function mathematics.dimensions(dimens) -- beware, dimens get spoiled
dimens["7*default_rule_thickness"] = 7 * default_rule_thickness
dimens["(5/18)*quad"] = (math_quad * 5) / 18
dimens["(-10/18)*quad"] = - (math_quad * 10) / 18
+ dimens["math_x_height*3"] = math_x_height * 3 -- needs checking
dimens["abs(math_x_height*4)/5"] = abs(math_x_height * 4) / 5
dimens["default_rule_thickness+(abs(default_rule_thickness)/4)"] = default_rule_thickness+(abs(default_rule_thickness) / 4)
dimens["default_rule_thickness+(abs(math_x_height)/4)"] = default_rule_thickness+(abs(math_x_height) / 4)
@@ -262,7 +169,7 @@ function mathematics.dimensions(dimens) -- beware, dimens get spoiled
AccentBaseHeight = t . accent_base_height . text_style,
AxisHeight = t . axis . text_style,
-- DelimitedSubFormulaMinHeight
- -- DisplayOperatorMinHeight
+ DisplayOperatorMinHeight = t . math_operator_size . text_style, -- no longer let tex decide (weird values)
-- FlattenedAccentBaseHeight
FractionDenominatorDisplayStyleGapMin = t . fraction_denom_vgap . display_style,
FractionDenominatorDisplayStyleShiftDown = t . fraction_denom_down . display_style,
diff --git a/Master/texmf-dist/tex/context/base/math-dis.mkiv b/Master/texmf-dist/tex/context/base/math-dis.mkiv
index 3eed2b16234..5b70970f3cc 100644
--- a/Master/texmf-dist/tex/context/base/math-dis.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-dis.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Display,
%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-ent.lua b/Master/texmf-dist/tex/context/base/math-ent.lua
deleted file mode 100644
index 0eaa02939fe..00000000000
--- a/Master/texmf-dist/tex/context/base/math-ent.lua
+++ /dev/null
@@ -1,2103 +0,0 @@
-if not modules then modules = { } end modules ['math-ent'] = {
- version = 1.001,
- comment = "companion to math-ini.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "derived from the mathml 2.0 specification",
-}
-
--- this might go into char-def
-
-mathematics.xml.entities = utilities.storage.allocate {
- ["Aacute"]=0x000C1,
- ["aacute"]=0x000E1,
- ["Abreve"]=0x00102,
- ["abreve"]=0x00103,
- ["ac"]=0x0223E,
- ["acd"]=0x0223F,
- ["acE"]=0x0223E,
- ["Acirc"]=0x000C2,
- ["acirc"]=0x000E2,
- ["acute"]=0x000B4,
- ["Acy"]=0x00410,
- ["acy"]=0x00430,
- ["AElig"]=0x000C6,
- ["aelig"]=0x000E6,
- ["af"]=0x02061,
- ["Afr"]=0x1D504,
- ["afr"]=0x1D51E,
- ["Agrave"]=0x000C0,
- ["agrave"]=0x000E0,
- ["aleph"]=0x02135,
- ["alpha"]=0x003B1,
- ["Amacr"]=0x00100,
- ["amacr"]=0x00101,
- ["amalg"]=0x02A3F,
- ["amp"]=0x00026,
- ["And"]=0x02A53,
- ["and"]=0x02227,
- ["andand"]=0x02A55,
- ["andd"]=0x02A5C,
- ["andslope"]=0x02A58,
- ["andv"]=0x02A5A,
- ["ang"]=0x02220,
- ["ange"]=0x029A4,
- ["angle"]=0x02220,
- ["angmsd"]=0x02221,
- ["angmsdaa"]=0x029A8,
- ["angmsdab"]=0x029A9,
- ["angmsdac"]=0x029AA,
- ["angmsdad"]=0x029AB,
- ["angmsdae"]=0x029AC,
- ["angmsdaf"]=0x029AD,
- ["angmsdag"]=0x029AE,
- ["angmsdah"]=0x029AF,
- ["angrt"]=0x0221F,
- ["angrtvb"]=0x022BE,
- ["angrtvbd"]=0x0299D,
- ["angsph"]=0x02222,
- ["angst"]=0x0212B,
- ["angzarr"]=0x0237C,
- ["Aogon"]=0x00104,
- ["aogon"]=0x00105,
- ["Aopf"]=0x1D538,
- ["aopf"]=0x1D552,
- ["ap"]=0x02248,
- ["apacir"]=0x02A6F,
- ["apE"]=0x02A70,
- ["ape"]=0x0224A,
- ["apid"]=0x0224B,
- ["apos"]=0x00027,
- ["ApplyFunction"]=0x02061,
- ["approx"]=0x02248,
- ["approxeq"]=0x0224A,
- ["Aring"]=0x000C5,
- ["aring"]=0x000E5,
- ["Ascr"]=0x1D49C,
- ["ascr"]=0x1D4B6,
- ["Assign"]=0x02254,
- ["ast"]=0x0002A,
- ["asymp"]=0x02248,
- ["asympeq"]=0x0224D,
- ["Atilde"]=0x000C3,
- ["atilde"]=0x000E3,
- ["Auml"]=0x000C4,
- ["auml"]=0x000E4,
- ["awconint"]=0x02233,
- ["awint"]=0x02A11,
- ["backcong"]=0x0224C,
- ["backepsilon"]=0x003F6,
- ["backprime"]=0x02035,
- ["backsim"]=0x0223D,
- ["backsimeq"]=0x022CD,
- ["Backslash"]=0x02216,
- ["Barv"]=0x02AE7,
- ["barvee"]=0x022BD,
- ["Barwed"]=0x02306,
- ["barwed"]=0x02305,
- ["barwedge"]=0x02305,
- ["bbrk"]=0x023B5,
- ["bbrktbrk"]=0x023B6,
- ["bcong"]=0x0224C,
- ["Bcy"]=0x00411,
- ["bcy"]=0x00431,
- ["becaus"]=0x02235,
- ["Because"]=0x02235,
- ["because"]=0x02235,
- ["bemptyv"]=0x029B0,
- ["bepsi"]=0x003F6,
- ["bernou"]=0x0212C,
- ["Bernoullis"]=0x0212C,
- ["beta"]=0x003B2,
- ["beth"]=0x02136,
- ["between"]=0x0226C,
- ["Bfr"]=0x1D505,
- ["bfr"]=0x1D51F,
- ["bigcap"]=0x022C2,
- ["bigcirc"]=0x025EF,
- ["bigcup"]=0x022C3,
- ["bigodot"]=0x02A00,
- ["bigoplus"]=0x02A01,
- ["bigotimes"]=0x02A02,
- ["bigsqcup"]=0x02A06,
- ["bigstar"]=0x02605,
- ["bigtriangledown"]=0x025BD,
- ["bigtriangleup"]=0x025B3,
- ["biguplus"]=0x02A04,
- ["bigvee"]=0x022C1,
- ["bigwedge"]=0x022C0,
- ["bkarow"]=0x0290D,
- ["blacklozenge"]=0x029EB,
- ["blacksquare"]=0x025AA,
- ["blacktriangle"]=0x025B4,
- ["blacktriangledown"]=0x025BE,
- ["blacktriangleleft"]=0x025C2,
- ["blacktriangleright"]=0x025B8,
- ["blank"]=0x02423,
- ["blk12"]=0x02592,
- ["blk14"]=0x02591,
- ["blk34"]=0x02593,
- ["block"]=0x02588,
- ["bne"]=0x0003D,
- ["bnequiv"]=0x02261,
- ["bNot"]=0x02AED,
- ["bnot"]=0x02310,
- ["Bopf"]=0x1D539,
- ["bopf"]=0x1D553,
- ["bot"]=0x022A5,
- ["bottom"]=0x022A5,
- ["bowtie"]=0x022C8,
- ["boxbox"]=0x029C9,
- ["boxDL"]=0x02557,
- ["boxDl"]=0x02556,
- ["boxdL"]=0x02555,
- ["boxdl"]=0x02510,
- ["boxDR"]=0x02554,
- ["boxDr"]=0x02553,
- ["boxdR"]=0x02552,
- ["boxdr"]=0x0250C,
- ["boxH"]=0x02550,
- ["boxh"]=0x02500,
- ["boxHD"]=0x02566,
- ["boxHd"]=0x02564,
- ["boxhD"]=0x02565,
- ["boxhd"]=0x0252C,
- ["boxHU"]=0x02569,
- ["boxHu"]=0x02567,
- ["boxhU"]=0x02568,
- ["boxhu"]=0x02534,
- ["boxminus"]=0x0229F,
- ["boxplus"]=0x0229E,
- ["boxtimes"]=0x022A0,
- ["boxUL"]=0x0255D,
- ["boxUl"]=0x0255C,
- ["boxuL"]=0x0255B,
- ["boxul"]=0x02518,
- ["boxUR"]=0x0255A,
- ["boxUr"]=0x02559,
- ["boxuR"]=0x02558,
- ["boxur"]=0x02514,
- ["boxV"]=0x02551,
- ["boxv"]=0x02502,
- ["boxVH"]=0x0256C,
- ["boxVh"]=0x0256B,
- ["boxvH"]=0x0256A,
- ["boxvh"]=0x0253C,
- ["boxVL"]=0x02563,
- ["boxVl"]=0x02562,
- ["boxvL"]=0x02561,
- ["boxvl"]=0x02524,
- ["boxVR"]=0x02560,
- ["boxVr"]=0x0255F,
- ["boxvR"]=0x0255E,
- ["boxvr"]=0x0251C,
- ["bprime"]=0x02035,
- ["Breve"]=0x002D8,
- ["breve"]=0x002D8,
- ["brvbar"]=0x000A6,
- ["Bscr"]=0x0212C,
- ["bscr"]=0x1D4B7,
- ["bsemi"]=0x0204F,
- ["bsim"]=0x0223D,
- ["bsime"]=0x022CD,
- ["bsol"]=0x0005C,
- ["bsolb"]=0x029C5,
- ["bsolhsub"]=0x0005C,
- ["bull"]=0x02022,
- ["bullet"]=0x02022,
- ["bump"]=0x0224E,
- ["bumpE"]=0x02AAE,
- ["bumpe"]=0x0224F,
- ["Bumpeq"]=0x0224E,
- ["bumpeq"]=0x0224F,
- ["Cacute"]=0x00106,
- ["cacute"]=0x00107,
- ["Cap"]=0x022D2,
- ["cap"]=0x02229,
- ["capand"]=0x02A44,
- ["capbrcup"]=0x02A49,
- ["capcap"]=0x02A4B,
- ["capcup"]=0x02A47,
- ["capdot"]=0x02A40,
- ["CapitalDifferentialD"]=0x02145,
- ["caps"]=0x02229,
- ["caret"]=0x02041,
- ["caron"]=0x002C7,
- ["Cayleys"]=0x0212D,
- ["ccaps"]=0x02A4D,
- ["Ccaron"]=0x0010C,
- ["ccaron"]=0x0010D,
- ["Ccedil"]=0x000C7,
- ["ccedil"]=0x000E7,
- ["Ccirc"]=0x00108,
- ["ccirc"]=0x00109,
- ["Cconint"]=0x02230,
- ["ccups"]=0x02A4C,
- ["ccupssm"]=0x02A50,
- ["Cdot"]=0x0010A,
- ["cdot"]=0x0010B,
- ["cedil"]=0x000B8,
- ["Cedilla"]=0x000B8,
- ["cemptyv"]=0x029B2,
- ["cent"]=0x000A2,
- ["CenterDot"]=0x000B7,
- ["centerdot"]=0x000B7,
- ["Cfr"]=0x0212D,
- ["cfr"]=0x1D520,
- ["CHcy"]=0x00427,
- ["chcy"]=0x00447,
- ["check"]=0x02713,
- ["checkmark"]=0x02713,
- ["chi"]=0x003C7,
- ["cir"]=0x025CB,
- ["circ"]=0x002C6,
- ["circeq"]=0x02257,
- ["circlearrowleft"]=0x021BA,
- ["circlearrowright"]=0x021BB,
- ["circledast"]=0x0229B,
- ["circledcirc"]=0x0229A,
- ["circleddash"]=0x0229D,
- ["CircleDot"]=0x02299,
- ["circledR"]=0x000AE,
- ["circledS"]=0x024C8,
- ["CircleMinus"]=0x02296,
- ["CirclePlus"]=0x02295,
- ["CircleTimes"]=0x02297,
- ["cirE"]=0x029C3,
- ["cire"]=0x02257,
- ["cirfnint"]=0x02A10,
- ["cirmid"]=0x02AEF,
- ["cirscir"]=0x029C2,
- ["ClockwiseContourIntegral"]=0x02232,
- ["CloseCurlyDoubleQuote"]=0x0201D,
- ["CloseCurlyQuote"]=0x02019,
- ["clubs"]=0x02663,
- ["clubsuit"]=0x02663,
- ["Colon"]=0x02237,
- ["colon"]=0x0003A,
- ["Colone"]=0x02A74,
- ["colone"]=0x02254,
- ["coloneq"]=0x02254,
- ["comma"]=0x0002C,
- ["commat"]=0x00040,
- ["comp"]=0x02201,
- ["compfn"]=0x02218,
- ["complement"]=0x02201,
- ["complexes"]=0x02102,
- ["cong"]=0x02245,
- ["congdot"]=0x02A6D,
- ["Congruent"]=0x02261,
- ["Conint"]=0x0222F,
- ["conint"]=0x0222E,
- ["ContourIntegral"]=0x0222E,
- ["Copf"]=0x02102,
- ["copf"]=0x1D554,
- ["coprod"]=0x02210,
- ["Coproduct"]=0x02210,
- ["copy"]=0x000A9,
- ["copysr"]=0x02117,
- ["CounterClockwiseContourIntegral"]=0x02233,
- ["Cross"]=0x02A2F,
- ["cross"]=0x02717,
- ["Cscr"]=0x1D49E,
- ["cscr"]=0x1D4B8,
- ["csub"]=0x02ACF,
- ["csube"]=0x02AD1,
- ["csup"]=0x02AD0,
- ["csupe"]=0x02AD2,
- ["ctdot"]=0x022EF,
- ["cudarrl"]=0x02938,
- ["cudarrr"]=0x02935,
- ["cuepr"]=0x022DE,
- ["cuesc"]=0x022DF,
- ["cularr"]=0x021B6,
- ["cularrp"]=0x0293D,
- ["Cup"]=0x022D3,
- ["cup"]=0x0222A,
- ["cupbrcap"]=0x02A48,
- ["CupCap"]=0x0224D,
- ["cupcap"]=0x02A46,
- ["cupcup"]=0x02A4A,
- ["cupdot"]=0x0228D,
- ["cupor"]=0x02A45,
- ["cups"]=0x0222A,
- ["curarr"]=0x021B7,
- ["curarrm"]=0x0293C,
- ["curlyeqprec"]=0x022DE,
- ["curlyeqsucc"]=0x022DF,
- ["curlyvee"]=0x022CE,
- ["curlywedge"]=0x022CF,
- ["curren"]=0x000A4,
- ["curvearrowleft"]=0x021B6,
- ["curvearrowright"]=0x021B7,
- ["cuvee"]=0x022CE,
- ["cuwed"]=0x022CF,
- ["cwconint"]=0x02232,
- ["cwint"]=0x02231,
- ["cylcty"]=0x0232D,
- ["Dagger"]=0x02021,
- ["Dagger"]=0x02021,
- ["dagger"]=0x02020,
- ["dagger"]=0x02020,
- ["daleth"]=0x02138,
- ["Darr"]=0x021A1,
- ["dArr"]=0x021D3,
- ["darr"]=0x02193,
- ["dash"]=0x02010,
- ["Dashv"]=0x02AE4,
- ["dashv"]=0x022A3,
- ["dbkarow"]=0x0290F,
- ["dblac"]=0x002DD,
- ["Dcaron"]=0x0010E,
- ["dcaron"]=0x0010F,
- ["Dcy"]=0x00414,
- ["dcy"]=0x00434,
- ["DD"]=0x02145,
- ["dd"]=0x02146,
- ["ddagger"]=0x02021,
- ["ddarr"]=0x021CA,
- ["DDotrahd"]=0x02911,
- ["ddotseq"]=0x02A77,
- ["deg"]=0x000B0,
- ["Del"]=0x02207,
- ["Delta"]=0x00394,
- ["delta"]=0x003B4,
- ["demptyv"]=0x029B1,
- ["dfisht"]=0x0297F,
- ["Dfr"]=0x1D507,
- ["dfr"]=0x1D521,
- ["dHar"]=0x02965,
- ["dharl"]=0x021C3,
- ["dharr"]=0x021C2,
- ["DiacriticalAcute"]=0x000B4,
- ["DiacriticalDot"]=0x002D9,
- ["DiacriticalDoubleAcute"]=0x002DD,
- ["DiacriticalGrave"]=0x00060,
- ["DiacriticalTilde"]=0x002DC,
- ["diam"]=0x022C4,
- ["Diamond"]=0x022C4,
- ["diamond"]=0x022C4,
- ["diamondsuit"]=0x02666,
- ["diams"]=0x02666,
- ["die"]=0x000A8,
- ["DifferentialD"]=0x02146,
- ["digamma"]=0x003DD,
- ["disin"]=0x022F2,
- ["div"]=0x000F7,
- ["divide"]=0x000F7,
- ["divideontimes"]=0x022C7,
- ["divonx"]=0x022C7,
- ["DJcy"]=0x00402,
- ["djcy"]=0x00452,
- ["dlcorn"]=0x0231E,
- ["dlcrop"]=0x0230D,
- ["dollar"]=0x00024,
- ["Dopf"]=0x1D53B,
- ["dopf"]=0x1D555,
- ["Dot"]=0x000A8,
- ["dot"]=0x002D9,
- ["DotDot"]=0x020DC,
- ["doteq"]=0x02250,
- ["doteqdot"]=0x02251,
- ["DotEqual"]=0x02250,
- ["dotminus"]=0x02238,
- ["dotplus"]=0x02214,
- ["dotsquare"]=0x022A1,
- ["doublebarwedge"]=0x02306,
- ["DoubleContourIntegral"]=0x0222F,
- ["DoubleDot"]=0x000A8,
- ["DoubleDownArrow"]=0x021D3,
- ["DoubleLeftArrow"]=0x021D0,
- ["DoubleLeftRightArrow"]=0x021D4,
- ["DoubleLeftTee"]=0x02AE4,
- ["DoubleLongLeftArrow"]=0x027F8,
- ["DoubleLongLeftRightArrow"]=0x027FA,
- ["DoubleLongRightArrow"]=0x027F9,
- ["DoubleRightArrow"]=0x021D2,
- ["DoubleRightTee"]=0x022A8,
- ["DoubleUpArrow"]=0x021D1,
- ["DoubleUpDownArrow"]=0x021D5,
- ["DoubleVerticalBar"]=0x02225,
- ["DownArrow"]=0x02193,
- ["Downarrow"]=0x021D3,
- ["downarrow"]=0x02193,
- ["DownArrowBar"]=0x02913,
- ["DownArrowUpArrow"]=0x021F5,
- ["DownBreve"]=0x00311,
- ["downdownarrows"]=0x021CA,
- ["downharpoonleft"]=0x021C3,
- ["downharpoonright"]=0x021C2,
- ["DownLeftRightVector"]=0x02950,
- ["DownLeftTeeVector"]=0x0295E,
- ["DownLeftVector"]=0x021BD,
- ["DownLeftVectorBar"]=0x02956,
- ["DownRightTeeVector"]=0x0295F,
- ["DownRightVector"]=0x021C1,
- ["DownRightVectorBar"]=0x02957,
- ["DownTee"]=0x022A4,
- ["DownTeeArrow"]=0x021A7,
- ["drbkarow"]=0x02910,
- ["drcorn"]=0x0231F,
- ["drcrop"]=0x0230C,
- ["Dscr"]=0x1D49F,
- ["dscr"]=0x1D4B9,
- ["DScy"]=0x00405,
- ["dscy"]=0x00455,
- ["dsol"]=0x029F6,
- ["Dstrok"]=0x00110,
- ["dstrok"]=0x00111,
- ["dtdot"]=0x022F1,
- ["dtri"]=0x025BF,
- ["dtrif"]=0x025BE,
- ["duarr"]=0x021F5,
- ["duhar"]=0x0296F,
- ["dwangle"]=0x029A6,
- ["DZcy"]=0x0040F,
- ["dzcy"]=0x0045F,
- ["dzigrarr"]=0x027FF,
- ["Eacute"]=0x000C9,
- ["eacute"]=0x000E9,
- ["easter"]=0x02A6E,
- ["Ecaron"]=0x0011A,
- ["ecaron"]=0x0011B,
- ["ecir"]=0x02256,
- ["Ecirc"]=0x000CA,
- ["ecirc"]=0x000EA,
- ["ecolon"]=0x02255,
- ["Ecy"]=0x0042D,
- ["ecy"]=0x0044D,
- ["eDDot"]=0x02A77,
- ["Edot"]=0x00116,
- ["eDot"]=0x02251,
- ["edot"]=0x00117,
- ["ee"]=0x02147,
- ["efDot"]=0x02252,
- ["Efr"]=0x1D508,
- ["efr"]=0x1D522,
- ["eg"]=0x02A9A,
- ["Egrave"]=0x000C8,
- ["egrave"]=0x000E8,
- ["egs"]=0x02A96,
- ["egsdot"]=0x02A98,
- ["el"]=0x02A99,
- ["Element"]=0x02208,
- ["elinters"]=0x0FFFD,
- ["ell"]=0x02113,
- ["els"]=0x02A95,
- ["elsdot"]=0x02A97,
- ["Emacr"]=0x00112,
- ["emacr"]=0x00113,
- ["empty"]=0x02205,
- ["emptyset"]=0x02205,
- ["EmptySmallSquare"]=0x025FB,
- ["emptyv"]=0x02205,
- ["EmptyVerySmallSquare"]=0x025AB,
- ["emsp"]=0x02003,
- ["emsp13"]=0x02004,
- ["emsp14"]=0x02005,
- ["ENG"]=0x0014A,
- ["eng"]=0x0014B,
- ["ensp"]=0x02002,
- ["Eogon"]=0x00118,
- ["eogon"]=0x00119,
- ["Eopf"]=0x1D53C,
- ["eopf"]=0x1D556,
- ["epar"]=0x022D5,
- ["eparsl"]=0x029E3,
- ["eplus"]=0x02A71,
- ["epsi"]=0x003F5,
- ["epsiv"]=0x003B5,
- ["eqcirc"]=0x02256,
- ["eqcolon"]=0x02255,
- ["eqsim"]=0x02242,
- ["eqslantgtr"]=0x02A96,
- ["eqslantless"]=0x02A95,
- ["Equal"]=0x02A75,
- ["equals"]=0x0003D,
- ["EqualTilde"]=0x02242,
- ["equest"]=0x0225F,
- ["Equilibrium"]=0x021CC,
- ["equiv"]=0x02261,
- ["equivDD"]=0x02A78,
- ["eqvparsl"]=0x029E5,
- ["erarr"]=0x02971,
- ["erDot"]=0x02253,
- ["Escr"]=0x02130,
- ["escr"]=0x0212F,
- ["esdot"]=0x02250,
- ["Esim"]=0x02A73,
- ["esim"]=0x02242,
- ["eta"]=0x003B7,
- ["ETH"]=0x000D0,
- ["eth"]=0x000F0,
- ["Euml"]=0x000CB,
- ["euml"]=0x000EB,
- ["excl"]=0x00021,
- ["exist"]=0x02203,
- ["Exists"]=0x02203,
- ["expectation"]=0x02130,
- ["ExponentialE"]=0x02147,
- ["exponentiale"]=0x02147,
- ["fallingdotseq"]=0x02252,
- ["Fcy"]=0x00424,
- ["fcy"]=0x00444,
- ["female"]=0x02640,
- ["ffilig"]=0x0FB03,
- ["fflig"]=0x0FB00,
- ["ffllig"]=0x0FB04,
- ["Ffr"]=0x1D509,
- ["ffr"]=0x1D523,
- ["filig"]=0x0FB01,
- ["FilledSmallSquare"]=0x025FC,
- ["FilledVerySmallSquare"]=0x025AA,
- ["flat"]=0x0266D,
- ["fllig"]=0x0FB02,
- ["fltns"]=0x025B1,
- ["fnof"]=0x00192,
- ["Fopf"]=0x1D53D,
- ["fopf"]=0x1D557,
- ["ForAll"]=0x02200,
- ["forall"]=0x02200,
- ["fork"]=0x022D4,
- ["forkv"]=0x02AD9,
- ["Fouriertrf"]=0x02131,
- ["fpartint"]=0x02A0D,
- ["frac12"]=0x000BD,
- ["frac13"]=0x02153,
- ["frac14"]=0x000BC,
- ["frac15"]=0x02155,
- ["frac16"]=0x02159,
- ["frac18"]=0x0215B,
- ["frac23"]=0x02154,
- ["frac25"]=0x02156,
- ["frac34"]=0x000BE,
- ["frac35"]=0x02157,
- ["frac38"]=0x0215C,
- ["frac45"]=0x02158,
- ["frac56"]=0x0215A,
- ["frac58"]=0x0215D,
- ["frac78"]=0x0215E,
- ["frown"]=0x02322,
- ["Fscr"]=0x02131,
- ["fscr"]=0x1D4BB,
- ["gacute"]=0x001F5,
- ["Gamma"]=0x00393,
- ["gamma"]=0x003B3,
- ["Gammad"]=0x003DC,
- ["gammad"]=0x003DD,
- ["gap"]=0x02A86,
- ["Gbreve"]=0x0011E,
- ["gbreve"]=0x0011F,
- ["Gcedil"]=0x00122,
- ["Gcirc"]=0x0011C,
- ["gcirc"]=0x0011D,
- ["Gcy"]=0x00413,
- ["gcy"]=0x00433,
- ["Gdot"]=0x00120,
- ["gdot"]=0x00121,
- ["gE"]=0x02267,
- ["ge"]=0x02265,
- ["gEl"]=0x02A8C,
- ["gel"]=0x022DB,
- ["geq"]=0x02265,
- ["geqq"]=0x02267,
- ["geqslant"]=0x02A7E,
- ["ges"]=0x02A7E,
- ["gescc"]=0x02AA9,
- ["gesdot"]=0x02A80,
- ["gesdoto"]=0x02A82,
- ["gesdotol"]=0x02A84,
- ["gesl"]=0x022DB,
- ["gesles"]=0x02A94,
- ["Gfr"]=0x1D50A,
- ["gfr"]=0x1D524,
- ["Gg"]=0x022D9,
- ["gg"]=0x0226B,
- ["ggg"]=0x022D9,
- ["gimel"]=0x02137,
- ["GJcy"]=0x00403,
- ["gjcy"]=0x00453,
- ["gl"]=0x02277,
- ["gla"]=0x02AA5,
- ["glE"]=0x02A92,
- ["glj"]=0x02AA4,
- ["gnap"]=0x02A8A,
- ["gnapprox"]=0x02A8A,
- ["gnE"]=0x02269,
- ["gne"]=0x02A88,
- ["gneq"]=0x02A88,
- ["gneqq"]=0x02269,
- ["gnsim"]=0x022E7,
- ["Gopf"]=0x1D53E,
- ["gopf"]=0x1D558,
- ["grave"]=0x00060,
- ["GreaterEqual"]=0x02265,
- ["GreaterEqualLess"]=0x022DB,
- ["GreaterFullEqual"]=0x02267,
- ["GreaterGreater"]=0x02AA2,
- ["GreaterLess"]=0x02277,
- ["GreaterSlantEqual"]=0x02A7E,
- ["GreaterTilde"]=0x02273,
- ["Gscr"]=0x1D4A2,
- ["gscr"]=0x0210A,
- ["gsim"]=0x02273,
- ["gsime"]=0x02A8E,
- ["gsiml"]=0x02A90,
- ["Gt"]=0x0226B,
- ["gt"]=0x0003E,
- ["gtcc"]=0x02AA7,
- ["gtcir"]=0x02A7A,
- ["gtdot"]=0x022D7,
- ["gtlPar"]=0x02995,
- ["gtquest"]=0x02A7C,
- ["gtrapprox"]=0x02A86,
- ["gtrarr"]=0x02978,
- ["gtrdot"]=0x022D7,
- ["gtreqless"]=0x022DB,
- ["gtreqqless"]=0x02A8C,
- ["gtrless"]=0x02277,
- ["gtrsim"]=0x02273,
- ["gvertneqq"]=0x02269,
- ["gvnE"]=0x02269,
- ["Hacek"]=0x002C7,
- ["hairsp"]=0x0200A,
- ["half"]=0x000BD,
- ["hamilt"]=0x0210B,
- ["HARDcy"]=0x0042A,
- ["hardcy"]=0x0044A,
- ["hArr"]=0x021D4,
- ["harr"]=0x02194,
- ["harrcir"]=0x02948,
- ["harrw"]=0x021AD,
- ["Hat"]=0x0005E,
- ["hbar"]=0x0210F,
- ["Hcirc"]=0x00124,
- ["hcirc"]=0x00125,
- ["hearts"]=0x02665,
- ["heartsuit"]=0x02665,
- ["hellip"]=0x02026,
- ["hercon"]=0x022B9,
- ["Hfr"]=0x0210C,
- ["hfr"]=0x1D525,
- ["HilbertSpace"]=0x0210B,
- ["hksearow"]=0x02925,
- ["hkswarow"]=0x02926,
- ["hoarr"]=0x021FF,
- ["homtht"]=0x0223B,
- ["hookleftarrow"]=0x021A9,
- ["hookrightarrow"]=0x021AA,
- ["Hopf"]=0x0210D,
- ["hopf"]=0x1D559,
- ["horbar"]=0x02015,
- ["HorizontalLine"]=0x02500,
- ["Hscr"]=0x0210B,
- ["hscr"]=0x1D4BD,
- ["hslash"]=0x0210F,
- ["Hstrok"]=0x00126,
- ["hstrok"]=0x00127,
- ["HumpDownHump"]=0x0224E,
- ["HumpEqual"]=0x0224F,
- ["hybull"]=0x02043,
- ["hyphen"]=0x02010,
- ["Iacute"]=0x000CD,
- ["iacute"]=0x000ED,
- ["ic"]=0x02063,
- ["Icirc"]=0x000CE,
- ["icirc"]=0x000EE,
- ["Icy"]=0x00418,
- ["icy"]=0x00438,
- ["Idot"]=0x00130,
- ["IEcy"]=0x00415,
- ["iecy"]=0x00435,
- ["iexcl"]=0x000A1,
- ["iff"]=0x021D4,
- ["Ifr"]=0x02111,
- ["ifr"]=0x1D526,
- ["Igrave"]=0x000CC,
- ["igrave"]=0x000EC,
- ["ii"]=0x02148,
- ["iiiint"]=0x02A0C,
- ["iiint"]=0x0222D,
- ["iinfin"]=0x029DC,
- ["iiota"]=0x02129,
- ["IJlig"]=0x00132,
- ["ijlig"]=0x00133,
- ["Im"]=0x02111,
- ["Imacr"]=0x0012A,
- ["imacr"]=0x0012B,
- ["image"]=0x02111,
- ["ImaginaryI"]=0x02148,
- ["imagline"]=0x02110,
- ["imagpart"]=0x02111,
- ["imath"]=0x00131,
- ["imof"]=0x022B7,
- ["imped"]=0x001B5,
- ["Implies"]=0x021D2,
- ["in"]=0x02208,
- ["incare"]=0x02105,
- ["infin"]=0x0221E,
- ["infintie"]=0x029DD,
- ["inodot"]=0x00131,
- ["Int"]=0x0222C,
- ["int"]=0x0222B,
- ["intcal"]=0x022BA,
- ["integers"]=0x02124,
- ["Integral"]=0x0222B,
- ["intercal"]=0x022BA,
- ["Intersection"]=0x022C2,
- ["intlarhk"]=0x02A17,
- ["intprod"]=0x02A3C,
- ["InvisibleComma"]=0x02063,
- ["InvisibleTimes"]=0x02062,
- ["IOcy"]=0x00401,
- ["iocy"]=0x00451,
- ["Iogon"]=0x0012E,
- ["iogon"]=0x0012F,
- ["Iopf"]=0x1D540,
- ["iopf"]=0x1D55A,
- ["iota"]=0x003B9,
- ["iprod"]=0x02A3C,
- ["iquest"]=0x000BF,
- ["Iscr"]=0x02110,
- ["iscr"]=0x1D4BE,
- ["isin"]=0x02208,
- ["isindot"]=0x022F5,
- ["isinE"]=0x022F9,
- ["isins"]=0x022F4,
- ["isinsv"]=0x022F3,
- ["isinv"]=0x02208,
- ["it"]=0x02062,
- ["Itilde"]=0x00128,
- ["itilde"]=0x00129,
- ["Iukcy"]=0x00406,
- ["iukcy"]=0x00456,
- ["Iuml"]=0x000CF,
- ["iuml"]=0x000EF,
- ["Jcirc"]=0x00134,
- ["jcirc"]=0x00135,
- ["Jcy"]=0x00419,
- ["jcy"]=0x00439,
- ["Jfr"]=0x1D50D,
- ["jfr"]=0x1D527,
- ["jmath"]=0x0006A,
- ["Jopf"]=0x1D541,
- ["jopf"]=0x1D55B,
- ["Jscr"]=0x1D4A5,
- ["jscr"]=0x1D4BF,
- ["Jsercy"]=0x00408,
- ["jsercy"]=0x00458,
- ["Jukcy"]=0x00404,
- ["jukcy"]=0x00454,
- ["kappa"]=0x003BA,
- ["kappav"]=0x003F0,
- ["Kcedil"]=0x00136,
- ["kcedil"]=0x00137,
- ["Kcy"]=0x0041A,
- ["kcy"]=0x0043A,
- ["Kfr"]=0x1D50E,
- ["kfr"]=0x1D528,
- ["kgreen"]=0x00138,
- ["KHcy"]=0x00425,
- ["khcy"]=0x00445,
- ["KJcy"]=0x0040C,
- ["kjcy"]=0x0045C,
- ["Kopf"]=0x1D542,
- ["kopf"]=0x1D55C,
- ["Kscr"]=0x1D4A6,
- ["kscr"]=0x1D4C0,
- ["lAarr"]=0x021DA,
- ["Lacute"]=0x00139,
- ["lacute"]=0x0013A,
- ["laemptyv"]=0x029B4,
- ["lagran"]=0x02112,
- ["Lambda"]=0x0039B,
- ["lambda"]=0x003BB,
- ["Lang"]=0x0300A,
- ["lang"]=0x02329,
- ["langd"]=0x02991,
- ["langle"]=0x02329,
- ["lap"]=0x02A85,
- ["Laplacetrf"]=0x02112,
- ["laquo"]=0x000AB,
- ["Larr"]=0x0219E,
- ["lArr"]=0x021D0,
- ["larr"]=0x02190,
- ["larrb"]=0x021E4,
- ["larrbfs"]=0x0291F,
- ["larrfs"]=0x0291D,
- ["larrhk"]=0x021A9,
- ["larrlp"]=0x021AB,
- ["larrpl"]=0x02939,
- ["larrsim"]=0x02973,
- ["larrtl"]=0x021A2,
- ["lat"]=0x02AAB,
- ["lAtail"]=0x0291B,
- ["latail"]=0x02919,
- ["late"]=0x02AAD,
- ["lates"]=0x02AAD,
- ["lBarr"]=0x0290E,
- ["lbarr"]=0x0290C,
- ["lbbrk"]=0x03014,
- ["lbrace"]=0x0007B,
- ["lbrack"]=0x0005B,
- ["lbrke"]=0x0298B,
- ["lbrksld"]=0x0298F,
- ["lbrkslu"]=0x0298D,
- ["Lcaron"]=0x0013D,
- ["lcaron"]=0x0013E,
- ["Lcedil"]=0x0013B,
- ["lcedil"]=0x0013C,
- ["lceil"]=0x02308,
- ["lcub"]=0x0007B,
- ["Lcy"]=0x0041B,
- ["lcy"]=0x0043B,
- ["ldca"]=0x02936,
- ["ldquo"]=0x0201C,
- ["ldquor"]=0x0201E,
- ["ldrdhar"]=0x02967,
- ["ldrushar"]=0x0294B,
- ["ldsh"]=0x021B2,
- ["lE"]=0x02266,
- ["le"]=0x02264,
- ["LeftAngleBracket"]=0x02329,
- ["LeftArrow"]=0x02190,
- ["Leftarrow"]=0x021D0,
- ["leftarrow"]=0x02190,
- ["LeftArrowBar"]=0x021E4,
- ["LeftArrowRightArrow"]=0x021C6,
- ["leftarrowtail"]=0x021A2,
- ["LeftCeiling"]=0x02308,
- ["LeftDoubleBracket"]=0x0301A,
- ["LeftDownTeeVector"]=0x02961,
- ["LeftDownVector"]=0x021C3,
- ["LeftDownVectorBar"]=0x02959,
- ["LeftFloor"]=0x0230A,
- ["leftharpoondown"]=0x021BD,
- ["leftharpoonup"]=0x021BC,
- ["leftleftarrows"]=0x021C7,
- ["LeftRightArrow"]=0x02194,
- ["Leftrightarrow"]=0x021D4,
- ["leftrightarrow"]=0x02194,
- ["leftrightarrows"]=0x021C6,
- ["leftrightharpoons"]=0x021CB,
- ["leftrightsquigarrow"]=0x021AD,
- ["LeftRightVector"]=0x0294E,
- ["LeftTee"]=0x022A3,
- ["LeftTeeArrow"]=0x021A4,
- ["LeftTeeVector"]=0x0295A,
- ["leftthreetimes"]=0x022CB,
- ["LeftTriangle"]=0x022B2,
- ["LeftTriangleBar"]=0x029CF,
- ["LeftTriangleEqual"]=0x022B4,
- ["LeftUpDownVector"]=0x02951,
- ["LeftUpTeeVector"]=0x02960,
- ["LeftUpVector"]=0x021BF,
- ["LeftUpVectorBar"]=0x02958,
- ["LeftVector"]=0x021BC,
- ["LeftVectorBar"]=0x02952,
- ["lEg"]=0x02A8B,
- ["leg"]=0x022DA,
- ["leq"]=0x02264,
- ["leqq"]=0x02266,
- ["leqslant"]=0x02A7D,
- ["les"]=0x02A7D,
- ["lescc"]=0x02AA8,
- ["lesdot"]=0x02A7F,
- ["lesdoto"]=0x02A81,
- ["lesdotor"]=0x02A83,
- ["lesg"]=0x022DA,
- ["lesges"]=0x02A93,
- ["lessapprox"]=0x02A85,
- ["lessdot"]=0x022D6,
- ["lesseqgtr"]=0x022DA,
- ["lesseqqgtr"]=0x02A8B,
- ["LessEqualGreater"]=0x022DA,
- ["LessFullEqual"]=0x02266,
- ["LessGreater"]=0x02276,
- ["lessgtr"]=0x02276,
- ["LessLess"]=0x02AA1,
- ["lesssim"]=0x02272,
- ["LessSlantEqual"]=0x02A7D,
- ["LessTilde"]=0x02272,
- ["lfisht"]=0x0297C,
- ["lfloor"]=0x0230A,
- ["Lfr"]=0x1D50F,
- ["lfr"]=0x1D529,
- ["lg"]=0x02276,
- ["lgE"]=0x02A91,
- ["lHar"]=0x02962,
- ["lhard"]=0x021BD,
- ["lharu"]=0x021BC,
- ["lharul"]=0x0296A,
- ["lhblk"]=0x02584,
- ["LJcy"]=0x00409,
- ["ljcy"]=0x00459,
- ["Ll"]=0x022D8,
- ["ll"]=0x0226A,
- ["llarr"]=0x021C7,
- ["llcorner"]=0x0231E,
- ["Lleftarrow"]=0x021DA,
- ["llhard"]=0x0296B,
- ["lltri"]=0x025FA,
- ["Lmidot"]=0x0013F,
- ["lmidot"]=0x00140,
- ["lmoust"]=0x023B0,
- ["lmoustache"]=0x023B0,
- ["lnap"]=0x02A89,
- ["lnapprox"]=0x02A89,
- ["lnE"]=0x02268,
- ["lne"]=0x02A87,
- ["lneq"]=0x02A87,
- ["lneqq"]=0x02268,
- ["lnsim"]=0x022E6,
- ["loang"]=0x03018,
- ["loarr"]=0x021FD,
- ["lobrk"]=0x0301A,
- ["LongLeftArrow"]=0x027F5,
- ["Longleftarrow"]=0x027F8,
- ["longleftarrow"]=0x027F5,
- ["LongLeftRightArrow"]=0x027F7,
- ["Longleftrightarrow"]=0x027FA,
- ["longleftrightarrow"]=0x027F7,
- ["longmapsto"]=0x027FC,
- ["LongRightArrow"]=0x027F6,
- ["Longrightarrow"]=0x027F9,
- ["longrightarrow"]=0x027F6,
- ["looparrowleft"]=0x021AB,
- ["looparrowright"]=0x021AC,
- ["lopar"]=0x02985,
- ["Lopf"]=0x1D543,
- ["lopf"]=0x1D55D,
- ["loplus"]=0x02A2D,
- ["lotimes"]=0x02A34,
- ["lowast"]=0x02217,
- ["lowbar"]=0x0005F,
- ["LowerLeftArrow"]=0x02199,
- ["LowerRightArrow"]=0x02198,
- ["loz"]=0x025CA,
- ["lozenge"]=0x025CA,
- ["lozf"]=0x029EB,
- ["lpar"]=0x00028,
- ["lparlt"]=0x02993,
- ["lrarr"]=0x021C6,
- ["lrcorner"]=0x0231F,
- ["lrhar"]=0x021CB,
- ["lrhard"]=0x0296D,
- ["lrtri"]=0x022BF,
- ["Lscr"]=0x02112,
- ["lscr"]=0x1D4C1,
- ["Lsh"]=0x021B0,
- ["lsh"]=0x021B0,
- ["lsim"]=0x02272,
- ["lsime"]=0x02A8D,
- ["lsimg"]=0x02A8F,
- ["lsqb"]=0x0005B,
- ["lsquo"]=0x02018,
- ["lsquor"]=0x0201A,
- ["Lstrok"]=0x00141,
- ["lstrok"]=0x00142,
- ["Lt"]=0x0226A,
- ["lt"]=0x0003C,
- ["ltcc"]=0x02AA6,
- ["ltcir"]=0x02A79,
- ["ltdot"]=0x022D6,
- ["lthree"]=0x022CB,
- ["ltimes"]=0x022C9,
- ["ltlarr"]=0x02976,
- ["ltquest"]=0x02A7B,
- ["ltri"]=0x025C3,
- ["ltrie"]=0x022B4,
- ["ltrif"]=0x025C2,
- ["ltrPar"]=0x02996,
- ["lurdshar"]=0x0294A,
- ["luruhar"]=0x02966,
- ["lvertneqq"]=0x02268,
- ["lvnE"]=0x02268,
- ["macr"]=0x000AF,
- ["male"]=0x02642,
- ["malt"]=0x02720,
- ["maltese"]=0x02720,
- ["Map"]=0x02905,
- ["map"]=0x021A6,
- ["mapsto"]=0x021A6,
- ["mapstodown"]=0x021A7,
- ["mapstoleft"]=0x021A4,
- ["mapstoup"]=0x021A5,
- ["marker"]=0x025AE,
- ["mcomma"]=0x02A29,
- ["Mcy"]=0x0041C,
- ["mcy"]=0x0043C,
- ["mdash"]=0x02014,
- ["mDDot"]=0x0223A,
- ["measuredangle"]=0x02221,
- ["MediumSpace"]=0x0205F,
- ["Mellintrf"]=0x02133,
- ["Mfr"]=0x1D510,
- ["mfr"]=0x1D52A,
- ["mho"]=0x02127,
- ["micro"]=0x000B5,
- ["mid"]=0x02223,
- ["midast"]=0x0002A,
- ["midcir"]=0x02AF0,
- ["middot"]=0x000B7,
- ["minus"]=0x02212,
- ["minusb"]=0x0229F,
- ["minusd"]=0x02238,
- ["minusdu"]=0x02A2A,
- ["MinusPlus"]=0x02213,
- ["mlcp"]=0x02ADB,
- ["mldr"]=0x02026,
- ["mnplus"]=0x02213,
- ["models"]=0x022A7,
- ["Mopf"]=0x1D544,
- ["mopf"]=0x1D55E,
- ["mp"]=0x02213,
- ["Mscr"]=0x02133,
- ["mscr"]=0x1D4C2,
- ["mstpos"]=0x0223E,
- ["mu"]=0x003BC,
- ["multimap"]=0x022B8,
- ["mumap"]=0x022B8,
- ["nabla"]=0x02207,
- ["Nacute"]=0x00143,
- ["nacute"]=0x00144,
- ["nang"]=0x02220,
- ["nap"]=0x02249,
- ["napE"]=0x02A70,
- ["napid"]=0x0224B,
- ["napos"]=0x00149,
- ["napprox"]=0x02249,
- ["natur"]=0x0266E,
- ["natural"]=0x0266E,
- ["naturals"]=0x02115,
- ["nbsp"]=0x000A0,
- ["nbump"]=0x0224E,
- ["nbumpe"]=0x0224F,
- ["ncap"]=0x02A43,
- ["Ncaron"]=0x00147,
- ["ncaron"]=0x00148,
- ["Ncedil"]=0x00145,
- ["ncedil"]=0x00146,
- ["ncong"]=0x02247,
- ["ncongdot"]=0x02A6D,
- ["ncup"]=0x02A42,
- ["Ncy"]=0x0041D,
- ["ncy"]=0x0043D,
- ["ndash"]=0x02013,
- ["ne"]=0x02260,
- ["nearhk"]=0x02924,
- ["neArr"]=0x021D7,
- ["nearr"]=0x02197,
- ["nearrow"]=0x02197,
- ["nedot"]=0x02250,
- ["NegativeMediumSpace"]=0x0200B,
- ["NegativeThickSpace"]=0x0200B,
- ["NegativeThinSpace"]=0x0200B,
- ["NegativeVeryThinSpace"]=0x0200B,
- ["nequiv"]=0x02262,
- ["nesear"]=0x02928,
- ["nesim"]=0x02242,
- ["NestedGreaterGreater"]=0x0226B,
- ["NestedLessLess"]=0x0226A,
- ["NewLine"]=0x0000A,
- ["nexist"]=0x02204,
- ["nexists"]=0x02204,
- ["Nfr"]=0x1D511,
- ["nfr"]=0x1D52B,
- ["ngE"]=0x02267,
- ["nge"]=0x02271,
- ["ngeq"]=0x02271,
- ["ngeqq"]=0x02267,
- ["ngeqslant"]=0x02A7E,
- ["nges"]=0x02A7E,
- ["nGg"]=0x022D9,
- ["ngsim"]=0x02275,
- ["nGt"]=0x0226B,
- ["ngt"]=0x0226F,
- ["ngtr"]=0x0226F,
- ["nGtv"]=0x0226B,
- ["nhArr"]=0x021CE,
- ["nharr"]=0x021AE,
- ["nhpar"]=0x02AF2,
- ["ni"]=0x0220B,
- ["nis"]=0x022FC,
- ["nisd"]=0x022FA,
- ["niv"]=0x0220B,
- ["NJcy"]=0x0040A,
- ["njcy"]=0x0045A,
- ["nlArr"]=0x021CD,
- ["nlarr"]=0x0219A,
- ["nldr"]=0x02025,
- ["nlE"]=0x02266,
- ["nle"]=0x02270,
- ["nLeftarrow"]=0x021CD,
- ["nleftarrow"]=0x0219A,
- ["nLeftrightarrow"]=0x021CE,
- ["nleftrightarrow"]=0x021AE,
- ["nleq"]=0x02270,
- ["nleqq"]=0x02266,
- ["nleqslant"]=0x02A7D,
- ["nles"]=0x02A7D,
- ["nless"]=0x0226E,
- ["nLl"]=0x022D8,
- ["nlsim"]=0x02274,
- ["nLt"]=0x0226A,
- ["nlt"]=0x0226E,
- ["nltri"]=0x022EA,
- ["nltrie"]=0x022EC,
- ["nLtv"]=0x0226A,
- ["nmid"]=0x02224,
- ["NoBreak"]=0x02060,
- ["NonBreakingSpace"]=0x000A0,
- ["Nopf"]=0x02115,
- ["nopf"]=0x1D55F,
- ["Not"]=0x02AEC,
- ["not"]=0x000AC,
- ["NotCongruent"]=0x02262,
- ["NotCupCap"]=0x0226D,
- ["NotDoubleVerticalBar"]=0x02226,
- ["NotElement"]=0x02209,
- ["NotEqual"]=0x02260,
- ["NotEqualTilde"]=0x02242,
- ["NotExists"]=0x02204,
- ["NotGreater"]=0x0226F,
- ["NotGreaterEqual"]=0x02271,
- ["NotGreaterFullEqual"]=0x02266,
- ["NotGreaterGreater"]=0x0226B,
- ["NotGreaterLess"]=0x02279,
- ["NotGreaterSlantEqual"]=0x02A7E,
- ["NotGreaterTilde"]=0x02275,
- ["NotHumpDownHump"]=0x0224E,
- ["NotHumpEqual"]=0x0224F,
- ["notin"]=0x02209,
- ["notindot"]=0x022F5,
- ["notinE"]=0x022F9,
- ["notinva"]=0x02209,
- ["notinvb"]=0x022F7,
- ["notinvc"]=0x022F6,
- ["NotLeftTriangle"]=0x022EA,
- ["NotLeftTriangleBar"]=0x029CF,
- ["NotLeftTriangleEqual"]=0x022EC,
- ["NotLess"]=0x0226E,
- ["NotLessEqual"]=0x02270,
- ["NotLessGreater"]=0x02278,
- ["NotLessLess"]=0x0226A,
- ["NotLessSlantEqual"]=0x02A7D,
- ["NotLessTilde"]=0x02274,
- ["NotNestedGreaterGreater"]=0x02AA2,
- ["NotNestedLessLess"]=0x02AA1,
- ["notni"]=0x0220C,
- ["notniva"]=0x0220C,
- ["notnivb"]=0x022FE,
- ["notnivc"]=0x022FD,
- ["NotPrecedes"]=0x02280,
- ["NotPrecedesEqual"]=0x02AAF,
- ["NotPrecedesSlantEqual"]=0x022E0,
- ["NotReverseElement"]=0x0220C,
- ["NotRightTriangle"]=0x022EB,
- ["NotRightTriangleBar"]=0x029D0,
- ["NotRightTriangleEqual"]=0x022ED,
- ["NotSquareSubset"]=0x0228F,
- ["NotSquareSubsetEqual"]=0x022E2,
- ["NotSquareSuperset"]=0x02290,
- ["NotSquareSupersetEqual"]=0x022E3,
- ["NotSubset"]=0x02282,
- ["NotSubsetEqual"]=0x02288,
- ["NotSucceeds"]=0x02281,
- ["NotSucceedsEqual"]=0x02AB0,
- ["NotSucceedsSlantEqual"]=0x022E1,
- ["NotSucceedsTilde"]=0x0227F,
- ["NotSuperset"]=0x02283,
- ["NotSupersetEqual"]=0x02289,
- ["NotTilde"]=0x02241,
- ["NotTildeEqual"]=0x02244,
- ["NotTildeFullEqual"]=0x02247,
- ["NotTildeTilde"]=0x02249,
- ["NotVerticalBar"]=0x02224,
- ["npar"]=0x02226,
- ["nparallel"]=0x02226,
- ["nparsl"]=0x02AFD,
- ["npart"]=0x02202,
- ["npolint"]=0x02A14,
- ["npr"]=0x02280,
- ["nprcue"]=0x022E0,
- ["npre"]=0x02AAF,
- ["nprec"]=0x02280,
- ["npreceq"]=0x02AAF,
- ["nrArr"]=0x021CF,
- ["nrarr"]=0x0219B,
- ["nrarrc"]=0x02933,
- ["nrarrw"]=0x0219D,
- ["nRightarrow"]=0x021CF,
- ["nrightarrow"]=0x0219B,
- ["nrtri"]=0x022EB,
- ["nrtrie"]=0x022ED,
- ["nsc"]=0x02281,
- ["nsccue"]=0x022E1,
- ["nsce"]=0x02AB0,
- ["Nscr"]=0x1D4A9,
- ["nscr"]=0x1D4C3,
- ["nshortmid"]=0x02224,
- ["nshortparallel"]=0x02226,
- ["nsim"]=0x02241,
- ["nsime"]=0x02244,
- ["nsimeq"]=0x02244,
- ["nsmid"]=0x02224,
- ["nspar"]=0x02226,
- ["nsqsube"]=0x022E2,
- ["nsqsupe"]=0x022E3,
- ["nsub"]=0x02284,
- ["nsubE"]=0x02AC5,
- ["nsube"]=0x02288,
- ["nsubset"]=0x02282,
- ["nsubseteq"]=0x02288,
- ["nsubseteqq"]=0x02AC5,
- ["nsucc"]=0x02281,
- ["nsucceq"]=0x02AB0,
- ["nsup"]=0x02285,
- ["nsupE"]=0x02AC6,
- ["nsupe"]=0x02289,
- ["nsupset"]=0x02283,
- ["nsupseteq"]=0x02289,
- ["nsupseteqq"]=0x02AC6,
- ["ntgl"]=0x02279,
- ["Ntilde"]=0x000D1,
- ["ntilde"]=0x000F1,
- ["ntlg"]=0x02278,
- ["ntriangleleft"]=0x022EA,
- ["ntrianglelefteq"]=0x022EC,
- ["ntriangleright"]=0x022EB,
- ["ntrianglerighteq"]=0x022ED,
- ["nu"]=0x003BD,
- ["num"]=0x00023,
- ["numero"]=0x02116,
- ["numsp"]=0x02007,
- ["nvap"]=0x0224D,
- ["nVDash"]=0x022AF,
- ["nVdash"]=0x022AE,
- ["nvDash"]=0x022AD,
- ["nvdash"]=0x022AC,
- ["nvge"]=0x02265,
- ["nvgt"]=0x0003E,
- ["nvHarr"]=0x02904,
- ["nvinfin"]=0x029DE,
- ["nvlArr"]=0x02902,
- ["nvle"]=0x02264,
- ["nvlt"]=0x0003C,
- ["nvltrie"]=0x022B4,
- ["nvrArr"]=0x02903,
- ["nvrtrie"]=0x022B5,
- ["nvsim"]=0x0223C,
- ["nwarhk"]=0x02923,
- ["nwArr"]=0x021D6,
- ["nwarr"]=0x02196,
- ["nwarrow"]=0x02196,
- ["nwnear"]=0x02927,
- ["Oacute"]=0x000D3,
- ["oacute"]=0x000F3,
- ["oast"]=0x0229B,
- ["ocir"]=0x0229A,
- ["Ocirc"]=0x000D4,
- ["ocirc"]=0x000F4,
- ["Ocy"]=0x0041E,
- ["ocy"]=0x0043E,
- ["odash"]=0x0229D,
- ["Odblac"]=0x00150,
- ["odblac"]=0x00151,
- ["odiv"]=0x02A38,
- ["odot"]=0x02299,
- ["odsold"]=0x029BC,
- ["OElig"]=0x00152,
- ["oelig"]=0x00153,
- ["ofcir"]=0x029BF,
- ["Ofr"]=0x1D512,
- ["ofr"]=0x1D52C,
- ["ogon"]=0x002DB,
- ["Ograve"]=0x000D2,
- ["ograve"]=0x000F2,
- ["ogt"]=0x029C1,
- ["ohbar"]=0x029B5,
- ["ohm"]=0x02126,
- ["oint"]=0x0222E,
- ["olarr"]=0x021BA,
- ["olcir"]=0x029BE,
- ["olcross"]=0x029BB,
- ["olt"]=0x029C0,
- ["Omacr"]=0x0014C,
- ["omacr"]=0x0014D,
- ["Omega"]=0x003A9,
- ["omega"]=0x003C9,
- ["omid"]=0x029B6,
- ["ominus"]=0x02296,
- ["Oopf"]=0x1D546,
- ["oopf"]=0x1D560,
- ["opar"]=0x029B7,
- ["OpenCurlyDoubleQuote"]=0x0201C,
- ["OpenCurlyQuote"]=0x02018,
- ["operp"]=0x029B9,
- ["oplus"]=0x02295,
- ["Or"]=0x02A54,
- ["or"]=0x02228,
- ["orarr"]=0x021BB,
- ["ord"]=0x02A5D,
- ["order"]=0x02134,
- ["orderof"]=0x02134,
- ["ordf"]=0x000AA,
- ["ordm"]=0x000BA,
- ["origof"]=0x022B6,
- ["oror"]=0x02A56,
- ["orslope"]=0x02A57,
- ["orv"]=0x02A5B,
- ["oS"]=0x024C8,
- ["Oscr"]=0x1D4AA,
- ["oscr"]=0x02134,
- ["Oslash"]=0x000D8,
- ["oslash"]=0x000F8,
- ["osol"]=0x02298,
- ["Otilde"]=0x000D5,
- ["otilde"]=0x000F5,
- ["Otimes"]=0x02A37,
- ["otimes"]=0x02297,
- ["otimesas"]=0x02A36,
- ["Ouml"]=0x000D6,
- ["ouml"]=0x000F6,
- ["ovbar"]=0x0233D,
- ["OverBar"]=0x000AF,
- ["OverBrace"]=0x0FE37,
- ["OverBracket"]=0x023B4,
- ["OverParenthesis"]=0x0FE35,
- ["par"]=0x02225,
- ["para"]=0x000B6,
- ["parallel"]=0x02225,
- ["parsim"]=0x02AF3,
- ["parsl"]=0x02AFD,
- ["part"]=0x02202,
- ["PartialD"]=0x02202,
- ["Pcy"]=0x0041F,
- ["pcy"]=0x0043F,
- ["percnt"]=0x00025,
- ["period"]=0x0002E,
- ["permil"]=0x02030,
- ["perp"]=0x022A5,
- ["pertenk"]=0x02031,
- ["Pfr"]=0x1D513,
- ["pfr"]=0x1D52D,
- ["Phi"]=0x003A6,
- ["phi"]=0x003D5,
- ["phiv"]=0x003C6,
- ["phmmat"]=0x02133,
- ["phone"]=0x0260E,
- ["Pi"]=0x003A0,
- ["pi"]=0x003C0,
- ["pitchfork"]=0x022D4,
- ["piv"]=0x003D6,
- ["planck"]=0x0210F,
- ["planckh"]=0x0210E,
- ["plankv"]=0x0210F,
- ["plus"]=0x0002B,
- ["plusacir"]=0x02A23,
- ["plusb"]=0x0229E,
- ["pluscir"]=0x02A22,
- ["plusdo"]=0x02214,
- ["plusdu"]=0x02A25,
- ["pluse"]=0x02A72,
- ["PlusMinus"]=0x000B1,
- ["plusmn"]=0x000B1,
- ["plussim"]=0x02A26,
- ["plustwo"]=0x02A27,
- ["pm"]=0x000B1,
- ["Poincareplane"]=0x0210C,
- ["pointint"]=0x02A15,
- ["Popf"]=0x02119,
- ["popf"]=0x1D561,
- ["pound"]=0x000A3,
- ["Pr"]=0x02ABB,
- ["pr"]=0x0227A,
- ["prap"]=0x02AB7,
- ["prcue"]=0x0227C,
- ["prE"]=0x02AB3,
- ["pre"]=0x02AAF,
- ["prec"]=0x0227A,
- ["precapprox"]=0x02AB7,
- ["preccurlyeq"]=0x0227C,
- ["Precedes"]=0x0227A,
- ["PrecedesEqual"]=0x02AAF,
- ["PrecedesSlantEqual"]=0x0227C,
- ["PrecedesTilde"]=0x0227E,
- ["preceq"]=0x02AAF,
- ["precnapprox"]=0x02AB9,
- ["precneqq"]=0x02AB5,
- ["precnsim"]=0x022E8,
- ["precsim"]=0x0227E,
- ["Prime"]=0x02033,
- ["prime"]=0x02032,
- ["primes"]=0x02119,
- ["prnap"]=0x02AB9,
- ["prnE"]=0x02AB5,
- ["prnsim"]=0x022E8,
- ["prod"]=0x0220F,
- ["Product"]=0x0220F,
- ["profalar"]=0x0232E,
- ["profline"]=0x02312,
- ["profsurf"]=0x02313,
- ["prop"]=0x0221D,
- ["Proportion"]=0x02237,
- ["Proportional"]=0x0221D,
- ["propto"]=0x0221D,
- ["prsim"]=0x0227E,
- ["prurel"]=0x022B0,
- ["Pscr"]=0x1D4AB,
- ["pscr"]=0x1D4C5,
- ["Psi"]=0x003A8,
- ["psi"]=0x003C8,
- ["puncsp"]=0x02008,
- ["Qfr"]=0x1D514,
- ["qfr"]=0x1D52E,
- ["qint"]=0x02A0C,
- ["Qopf"]=0x0211A,
- ["qopf"]=0x1D562,
- ["qprime"]=0x02057,
- ["Qscr"]=0x1D4AC,
- ["qscr"]=0x1D4C6,
- ["quaternions"]=0x0210D,
- ["quatint"]=0x02A16,
- ["quest"]=0x0003F,
- ["questeq"]=0x0225F,
- ["quot"]=0x00022,
- ["rAarr"]=0x021DB,
- ["race"]=0x029DA,
- ["Racute"]=0x00154,
- ["racute"]=0x00155,
- ["radic"]=0x0221A,
- ["raemptyv"]=0x029B3,
- ["Rang"]=0x0300B,
- ["rang"]=0x0232A,
- ["rangd"]=0x02992,
- ["range"]=0x029A5,
- ["rangle"]=0x0232A,
- ["raquo"]=0x000BB,
- ["Rarr"]=0x021A0,
- ["rArr"]=0x021D2,
- ["rarr"]=0x02192,
- ["rarrap"]=0x02975,
- ["rarrb"]=0x021E5,
- ["rarrbfs"]=0x02920,
- ["rarrc"]=0x02933,
- ["rarrfs"]=0x0291E,
- ["rarrhk"]=0x021AA,
- ["rarrlp"]=0x021AC,
- ["rarrpl"]=0x02945,
- ["rarrsim"]=0x02974,
- ["Rarrtl"]=0x02916,
- ["rarrtl"]=0x021A3,
- ["rarrw"]=0x0219D,
- ["rAtail"]=0x0291C,
- ["ratail"]=0x0291A,
- ["ratio"]=0x02236,
- ["rationals"]=0x0211A,
- ["RBarr"]=0x02910,
- ["rBarr"]=0x0290F,
- ["rbarr"]=0x0290D,
- ["rbbrk"]=0x03015,
- ["rbrace"]=0x0007D,
- ["rbrack"]=0x0005D,
- ["rbrke"]=0x0298C,
- ["rbrksld"]=0x0298E,
- ["rbrkslu"]=0x02990,
- ["Rcaron"]=0x00158,
- ["rcaron"]=0x00159,
- ["Rcedil"]=0x00156,
- ["rcedil"]=0x00157,
- ["rceil"]=0x02309,
- ["rcub"]=0x0007D,
- ["Rcy"]=0x00420,
- ["rcy"]=0x00440,
- ["rdca"]=0x02937,
- ["rdldhar"]=0x02969,
- ["rdquo"]=0x0201D,
- ["rdquor"]=0x0201D,
- ["rdsh"]=0x021B3,
- ["Re"]=0x0211C,
- ["real"]=0x0211C,
- ["realine"]=0x0211B,
- ["realpart"]=0x0211C,
- ["reals"]=0x0211D,
- ["rect"]=0x025AD,
- ["reg"]=0x000AE,
- ["ReverseElement"]=0x0220B,
- ["ReverseEquilibrium"]=0x021CB,
- ["ReverseUpEquilibrium"]=0x0296F,
- ["rfisht"]=0x0297D,
- ["rfloor"]=0x0230B,
- ["Rfr"]=0x0211C,
- ["rfr"]=0x1D52F,
- ["rHar"]=0x02964,
- ["rhard"]=0x021C1,
- ["rharu"]=0x021C0,
- ["rharul"]=0x0296C,
- ["rho"]=0x003C1,
- ["rhov"]=0x003F1,
- ["RightAngleBracket"]=0x0232A,
- ["RightArrow"]=0x02192,
- ["Rightarrow"]=0x021D2,
- ["rightarrow"]=0x02192,
- ["RightArrowBar"]=0x021E5,
- ["RightArrowLeftArrow"]=0x021C4,
- ["rightarrowtail"]=0x021A3,
- ["RightCeiling"]=0x02309,
- ["RightDoubleBracket"]=0x0301B,
- ["RightDownTeeVector"]=0x0295D,
- ["RightDownVector"]=0x021C2,
- ["RightDownVectorBar"]=0x02955,
- ["RightFloor"]=0x0230B,
- ["rightharpoondown"]=0x021C1,
- ["rightharpoonup"]=0x021C0,
- ["rightleftarrows"]=0x021C4,
- ["rightleftharpoons"]=0x021CC,
- ["rightrightarrows"]=0x021C9,
- ["rightsquigarrow"]=0x0219D,
- ["RightTee"]=0x022A2,
- ["RightTeeArrow"]=0x021A6,
- ["RightTeeVector"]=0x0295B,
- ["rightthreetimes"]=0x022CC,
- ["RightTriangle"]=0x022B3,
- ["RightTriangleBar"]=0x029D0,
- ["RightTriangleEqual"]=0x022B5,
- ["RightUpDownVector"]=0x0294F,
- ["RightUpTeeVector"]=0x0295C,
- ["RightUpVector"]=0x021BE,
- ["RightUpVectorBar"]=0x02954,
- ["RightVector"]=0x021C0,
- ["RightVectorBar"]=0x02953,
- ["ring"]=0x002DA,
- ["risingdotseq"]=0x02253,
- ["rlarr"]=0x021C4,
- ["rlhar"]=0x021CC,
- ["rmoust"]=0x023B1,
- ["rmoustache"]=0x023B1,
- ["rnmid"]=0x02AEE,
- ["roang"]=0x03019,
- ["roarr"]=0x021FE,
- ["robrk"]=0x0301B,
- ["ropar"]=0x02986,
- ["Ropf"]=0x0211D,
- ["ropf"]=0x1D563,
- ["roplus"]=0x02A2E,
- ["rotimes"]=0x02A35,
- ["RoundImplies"]=0x02970,
- ["rpar"]=0x00029,
- ["rpargt"]=0x02994,
- ["rppolint"]=0x02A12,
- ["rrarr"]=0x021C9,
- ["Rrightarrow"]=0x021DB,
- ["Rscr"]=0x0211B,
- ["rscr"]=0x1D4C7,
- ["Rsh"]=0x021B1,
- ["rsh"]=0x021B1,
- ["rsqb"]=0x0005D,
- ["rsquo"]=0x02019,
- ["rsquor"]=0x02019,
- ["rthree"]=0x022CC,
- ["rtimes"]=0x022CA,
- ["rtri"]=0x025B9,
- ["rtrie"]=0x022B5,
- ["rtrif"]=0x025B8,
- ["rtriltri"]=0x029CE,
- ["RuleDelayed"]=0x029F4,
- ["ruluhar"]=0x02968,
- ["rx"]=0x0211E,
- ["Sacute"]=0x0015A,
- ["sacute"]=0x0015B,
- ["Sc"]=0x02ABC,
- ["sc"]=0x0227B,
- ["scap"]=0x02AB8,
- ["Scaron"]=0x00160,
- ["scaron"]=0x00161,
- ["sccue"]=0x0227D,
- ["scE"]=0x02AB4,
- ["sce"]=0x02AB0,
- ["Scedil"]=0x0015E,
- ["scedil"]=0x0015F,
- ["Scirc"]=0x0015C,
- ["scirc"]=0x0015D,
- ["scnap"]=0x02ABA,
- ["scnE"]=0x02AB6,
- ["scnsim"]=0x022E9,
- ["scpolint"]=0x02A13,
- ["scsim"]=0x0227F,
- ["Scy"]=0x00421,
- ["scy"]=0x00441,
- ["sdot"]=0x022C5,
- ["sdotb"]=0x022A1,
- ["sdote"]=0x02A66,
- ["searhk"]=0x02925,
- ["seArr"]=0x021D8,
- ["searr"]=0x02198,
- ["searrow"]=0x02198,
- ["sect"]=0x000A7,
- ["semi"]=0x0003B,
- ["seswar"]=0x02929,
- ["setminus"]=0x02216,
- ["setmn"]=0x02216,
- ["sext"]=0x02736,
- ["Sfr"]=0x1D516,
- ["sfr"]=0x1D530,
- ["sfrown"]=0x02322,
- ["sharp"]=0x0266F,
- ["SHCHcy"]=0x00429,
- ["shchcy"]=0x00449,
- ["SHcy"]=0x00428,
- ["shcy"]=0x00448,
- ["ShortDownArrow"]=0x02193,
- ["ShortLeftArrow"]=0x02190,
- ["shortmid"]=0x02223,
- ["shortparallel"]=0x02225,
- ["ShortRightArrow"]=0x02192,
- ["ShortUpArrow"]=0x02191,
- ["shy"]=0x000AD,
- ["Sigma"]=0x003A3,
- ["sigma"]=0x003C3,
- ["sigmav"]=0x003C2,
- ["sim"]=0x0223C,
- ["simdot"]=0x02A6A,
- ["sime"]=0x02243,
- ["simeq"]=0x02243,
- ["simg"]=0x02A9E,
- ["simgE"]=0x02AA0,
- ["siml"]=0x02A9D,
- ["simlE"]=0x02A9F,
- ["simne"]=0x02246,
- ["simplus"]=0x02A24,
- ["simrarr"]=0x02972,
- ["slarr"]=0x02190,
- ["SmallCircle"]=0x02218,
- ["smallsetminus"]=0x02216,
- ["smashp"]=0x02A33,
- ["smeparsl"]=0x029E4,
- ["smid"]=0x02223,
- ["smile"]=0x02323,
- ["smt"]=0x02AAA,
- ["smte"]=0x02AAC,
- ["smtes"]=0x02AAC,
- ["SOFTcy"]=0x0042C,
- ["softcy"]=0x0044C,
- ["sol"]=0x0002F,
- ["solb"]=0x029C4,
- ["solbar"]=0x0233F,
- ["Sopf"]=0x1D54A,
- ["sopf"]=0x1D564,
- ["spades"]=0x02660,
- ["spadesuit"]=0x02660,
- ["spar"]=0x02225,
- ["sqcap"]=0x02293,
- ["sqcaps"]=0x02293,
- ["sqcup"]=0x02294,
- ["sqcups"]=0x02294,
- ["Sqrt"]=0x0221A,
- ["sqsub"]=0x0228F,
- ["sqsube"]=0x02291,
- ["sqsubset"]=0x0228F,
- ["sqsubseteq"]=0x02291,
- ["sqsup"]=0x02290,
- ["sqsupe"]=0x02292,
- ["sqsupset"]=0x02290,
- ["sqsupseteq"]=0x02292,
- ["squ"]=0x025A1,
- ["Square"]=0x025A1,
- ["square"]=0x025A1,
- ["SquareIntersection"]=0x02293,
- ["SquareSubset"]=0x0228F,
- ["SquareSubsetEqual"]=0x02291,
- ["SquareSuperset"]=0x02290,
- ["SquareSupersetEqual"]=0x02292,
- ["SquareUnion"]=0x02294,
- ["squarf"]=0x025AA,
- ["squf"]=0x025AA,
- ["srarr"]=0x02192,
- ["Sscr"]=0x1D4AE,
- ["sscr"]=0x1D4C8,
- ["ssetmn"]=0x02216,
- ["ssmile"]=0x02323,
- ["sstarf"]=0x022C6,
- ["Star"]=0x022C6,
- ["star"]=0x02606,
- ["starf"]=0x02605,
- ["straightepsilon"]=0x003F5,
- ["straightphi"]=0x003D5,
- ["strns"]=0x000AF,
- ["Sub"]=0x022D0,
- ["sub"]=0x02282,
- ["subdot"]=0x02ABD,
- ["subE"]=0x02AC5,
- ["sube"]=0x02286,
- ["subedot"]=0x02AC3,
- ["submult"]=0x02AC1,
- ["subnE"]=0x02ACB,
- ["subne"]=0x0228A,
- ["subplus"]=0x02ABF,
- ["subrarr"]=0x02979,
- ["Subset"]=0x022D0,
- ["subset"]=0x02282,
- ["subseteq"]=0x02286,
- ["subseteqq"]=0x02AC5,
- ["SubsetEqual"]=0x02286,
- ["subsetneq"]=0x0228A,
- ["subsetneqq"]=0x02ACB,
- ["subsim"]=0x02AC7,
- ["subsub"]=0x02AD5,
- ["subsup"]=0x02AD3,
- ["succ"]=0x0227B,
- ["succapprox"]=0x02AB8,
- ["succcurlyeq"]=0x0227D,
- ["Succeeds"]=0x0227B,
- ["SucceedsEqual"]=0x02AB0,
- ["SucceedsSlantEqual"]=0x0227D,
- ["SucceedsTilde"]=0x0227F,
- ["succeq"]=0x02AB0,
- ["succnapprox"]=0x02ABA,
- ["succneqq"]=0x02AB6,
- ["succnsim"]=0x022E9,
- ["succsim"]=0x0227F,
- ["SuchThat"]=0x0220B,
- ["Sum"]=0x02211,
- ["sum"]=0x02211,
- ["sung"]=0x0266A,
- ["Sup"]=0x022D1,
- ["sup"]=0x02283,
- ["sup1"]=0x000B9,
- ["sup2"]=0x000B2,
- ["sup3"]=0x000B3,
- ["supdot"]=0x02ABE,
- ["supdsub"]=0x02AD8,
- ["supE"]=0x02AC6,
- ["supe"]=0x02287,
- ["supedot"]=0x02AC4,
- ["Superset"]=0x02283,
- ["SupersetEqual"]=0x02287,
- ["suphsol"]=0x02283,
- ["suphsub"]=0x02AD7,
- ["suplarr"]=0x0297B,
- ["supmult"]=0x02AC2,
- ["supnE"]=0x02ACC,
- ["supne"]=0x0228B,
- ["supplus"]=0x02AC0,
- ["Supset"]=0x022D1,
- ["supset"]=0x02283,
- ["supseteq"]=0x02287,
- ["supseteqq"]=0x02AC6,
- ["supsetneq"]=0x0228B,
- ["supsetneqq"]=0x02ACC,
- ["supsim"]=0x02AC8,
- ["supsub"]=0x02AD4,
- ["supsup"]=0x02AD6,
- ["swarhk"]=0x02926,
- ["swArr"]=0x021D9,
- ["swarr"]=0x02199,
- ["swarrow"]=0x02199,
- ["swnwar"]=0x0292A,
- ["szlig"]=0x000DF,
- ["Tab"]=0x00009,
- ["target"]=0x02316,
- ["tau"]=0x003C4,
- ["tbrk"]=0x023B4,
- ["Tcaron"]=0x00164,
- ["tcaron"]=0x00165,
- ["Tcedil"]=0x00162,
- ["tcedil"]=0x00163,
- ["Tcy"]=0x00422,
- ["tcy"]=0x00442,
- ["tdot"]=0x020DB,
- ["telrec"]=0x02315,
- ["Tfr"]=0x1D517,
- ["tfr"]=0x1D531,
- ["there4"]=0x02234,
- ["Therefore"]=0x02234,
- ["therefore"]=0x02234,
- ["Theta"]=0x00398,
- ["theta"]=0x003B8,
- ["thetav"]=0x003D1,
- ["thickapprox"]=0x02248,
- ["thicksim"]=0x0223C,
- ["ThickSpace"]=0x02009,
- ["thinsp"]=0x02009,
- ["ThinSpace"]=0x02009,
- ["thkap"]=0x02248,
- ["thksim"]=0x0223C,
- ["THORN"]=0x000DE,
- ["thorn"]=0x000FE,
- ["Tilde"]=0x0223C,
- ["tilde"]=0x002DC,
- ["TildeEqual"]=0x02243,
- ["TildeFullEqual"]=0x02245,
- ["TildeTilde"]=0x02248,
- ["times"]=0x000D7,
- ["timesb"]=0x022A0,
- ["timesbar"]=0x02A31,
- ["timesd"]=0x02A30,
- ["tint"]=0x0222D,
- ["toea"]=0x02928,
- ["top"]=0x022A4,
- ["topbot"]=0x02336,
- ["topcir"]=0x02AF1,
- ["Topf"]=0x1D54B,
- ["topf"]=0x1D565,
- ["topfork"]=0x02ADA,
- ["tosa"]=0x02929,
- ["tprime"]=0x02034,
- ["trade"]=0x02122,
- ["triangle"]=0x025B5,
- ["triangledown"]=0x025BF,
- ["triangleleft"]=0x025C3,
- ["trianglelefteq"]=0x022B4,
- ["triangleq"]=0x0225C,
- ["triangleright"]=0x025B9,
- ["trianglerighteq"]=0x022B5,
- ["tridot"]=0x025EC,
- ["trie"]=0x0225C,
- ["triminus"]=0x02A3A,
- ["TripleDot"]=0x020DB,
- ["triplus"]=0x02A39,
- ["trisb"]=0x029CD,
- ["tritime"]=0x02A3B,
- ["trpezium"]=0x0FFFD,
- ["Tscr"]=0x1D4AF,
- ["tscr"]=0x1D4C9,
- ["TScy"]=0x00426,
- ["tscy"]=0x00446,
- ["TSHcy"]=0x0040B,
- ["tshcy"]=0x0045B,
- ["Tstrok"]=0x00166,
- ["tstrok"]=0x00167,
- ["twixt"]=0x0226C,
- ["twoheadleftarrow"]=0x0219E,
- ["twoheadrightarrow"]=0x021A0,
- ["Uacute"]=0x000DA,
- ["uacute"]=0x000FA,
- ["Uarr"]=0x0219F,
- ["uArr"]=0x021D1,
- ["uarr"]=0x02191,
- ["Uarrocir"]=0x02949,
- ["Ubrcy"]=0x0040E,
- ["ubrcy"]=0x0045E,
- ["Ubreve"]=0x0016C,
- ["ubreve"]=0x0016D,
- ["Ucirc"]=0x000DB,
- ["ucirc"]=0x000FB,
- ["Ucy"]=0x00423,
- ["ucy"]=0x00443,
- ["udarr"]=0x021C5,
- ["Udblac"]=0x00170,
- ["udblac"]=0x00171,
- ["udhar"]=0x0296E,
- ["ufisht"]=0x0297E,
- ["Ufr"]=0x1D518,
- ["ufr"]=0x1D532,
- ["Ugrave"]=0x000D9,
- ["ugrave"]=0x000F9,
- ["uHar"]=0x02963,
- ["uharl"]=0x021BF,
- ["uharr"]=0x021BE,
- ["uhblk"]=0x02580,
- ["ulcorn"]=0x0231C,
- ["ulcorner"]=0x0231C,
- ["ulcrop"]=0x0230F,
- ["ultri"]=0x025F8,
- ["Umacr"]=0x0016A,
- ["umacr"]=0x0016B,
- ["uml"]=0x000A8,
- ["UnderBar"]=0x00332,
- ["UnderBrace"]=0x0FE38,
- ["UnderBracket"]=0x023B5,
- ["UnderParenthesis"]=0x0FE36,
- ["Union"]=0x022C3,
- ["UnionPlus"]=0x0228E,
- ["Uogon"]=0x00172,
- ["uogon"]=0x00173,
- ["Uopf"]=0x1D54C,
- ["uopf"]=0x1D566,
- ["UpArrow"]=0x02191,
- ["Uparrow"]=0x021D1,
- ["uparrow"]=0x02191,
- ["UpArrowBar"]=0x02912,
- ["UpArrowDownArrow"]=0x021C5,
- ["UpDownArrow"]=0x02195,
- ["Updownarrow"]=0x021D5,
- ["updownarrow"]=0x02195,
- ["UpEquilibrium"]=0x0296E,
- ["upharpoonleft"]=0x021BF,
- ["upharpoonright"]=0x021BE,
- ["uplus"]=0x0228E,
- ["UpperLeftArrow"]=0x02196,
- ["UpperRightArrow"]=0x02197,
- ["Upsi"]=0x003D2,
- ["upsi"]=0x003C5,
- ["Upsilon"]=0x003A5,
- ["upsilon"]=0x003C5,
- ["UpTee"]=0x022A5,
- ["UpTeeArrow"]=0x021A5,
- ["upuparrows"]=0x021C8,
- ["urcorn"]=0x0231D,
- ["urcorner"]=0x0231D,
- ["urcrop"]=0x0230E,
- ["Uring"]=0x0016E,
- ["uring"]=0x0016F,
- ["urtri"]=0x025F9,
- ["Uscr"]=0x1D4B0,
- ["uscr"]=0x1D4CA,
- ["utdot"]=0x022F0,
- ["Utilde"]=0x00168,
- ["utilde"]=0x00169,
- ["utri"]=0x025B5,
- ["utrif"]=0x025B4,
- ["uuarr"]=0x021C8,
- ["Uuml"]=0x000DC,
- ["uuml"]=0x000FC,
- ["uwangle"]=0x029A7,
- ["vangrt"]=0x0299C,
- ["varepsilon"]=0x003B5,
- ["varkappa"]=0x003F0,
- ["varnothing"]=0x02205,
- ["varphi"]=0x003C6,
- ["varpi"]=0x003D6,
- ["varpropto"]=0x0221D,
- ["vArr"]=0x021D5,
- ["varr"]=0x02195,
- ["varrho"]=0x003F1,
- ["varsigma"]=0x003C2,
- ["varsubsetneq"]=0x0228A,
- ["varsubsetneqq"]=0x02ACB,
- ["varsupsetneq"]=0x0228B,
- ["varsupsetneqq"]=0x02ACC,
- ["vartheta"]=0x003D1,
- ["vartriangleleft"]=0x022B2,
- ["vartriangleright"]=0x022B3,
- ["Vbar"]=0x02AEB,
- ["vBar"]=0x02AE8,
- ["vBarv"]=0x02AE9,
- ["Vcy"]=0x00412,
- ["vcy"]=0x00432,
- ["VDash"]=0x022AB,
- ["Vdash"]=0x022A9,
- ["vDash"]=0x022A8,
- ["vdash"]=0x022A2,
- ["Vdashl"]=0x02AE6,
- ["Vee"]=0x022C1,
- ["vee"]=0x02228,
- ["veebar"]=0x022BB,
- ["veeeq"]=0x0225A,
- ["vellip"]=0x022EE,
- ["Verbar"]=0x02016,
- ["verbar"]=0x0007C,
- ["Vert"]=0x02016,
- ["vert"]=0x0007C,
- ["VerticalBar"]=0x02223,
- ["VerticalLine"]=0x0007C,
- ["VerticalSeparator"]=0x02758,
- ["VerticalTilde"]=0x02240,
- ["VeryThinSpace"]=0x0200A,
- ["Vfr"]=0x1D519,
- ["vfr"]=0x1D533,
- ["vltri"]=0x022B2,
- ["vnsub"]=0x02282,
- ["vnsup"]=0x02283,
- ["Vopf"]=0x1D54D,
- ["vopf"]=0x1D567,
- ["vprop"]=0x0221D,
- ["vrtri"]=0x022B3,
- ["Vscr"]=0x1D4B1,
- ["vscr"]=0x1D4CB,
- ["vsubnE"]=0x02ACB,
- ["vsubne"]=0x0228A,
- ["vsupnE"]=0x02ACC,
- ["vsupne"]=0x0228B,
- ["Vvdash"]=0x022AA,
- ["vzigzag"]=0x0299A,
- ["Wcirc"]=0x00174,
- ["wcirc"]=0x00175,
- ["wedbar"]=0x02A5F,
- ["Wedge"]=0x022C0,
- ["wedge"]=0x02227,
- ["wedgeq"]=0x02259,
- ["weierp"]=0x02118,
- ["Wfr"]=0x1D51A,
- ["wfr"]=0x1D534,
- ["Wopf"]=0x1D54E,
- ["wopf"]=0x1D568,
- ["wp"]=0x02118,
- ["wr"]=0x02240,
- ["wreath"]=0x02240,
- ["Wscr"]=0x1D4B2,
- ["wscr"]=0x1D4CC,
- ["xcap"]=0x022C2,
- ["xcirc"]=0x025EF,
- ["xcup"]=0x022C3,
- ["xdtri"]=0x025BD,
- ["Xfr"]=0x1D51B,
- ["xfr"]=0x1D535,
- ["xhArr"]=0x027FA,
- ["xharr"]=0x027F7,
- ["Xi"]=0x0039E,
- ["xi"]=0x003BE,
- ["xlArr"]=0x027F8,
- ["xlarr"]=0x027F5,
- ["xmap"]=0x027FC,
- ["xnis"]=0x022FB,
- ["xodot"]=0x02A00,
- ["Xopf"]=0x1D54F,
- ["xopf"]=0x1D569,
- ["xoplus"]=0x02A01,
- ["xotime"]=0x02A02,
- ["xrArr"]=0x027F9,
- ["xrarr"]=0x027F6,
- ["Xscr"]=0x1D4B3,
- ["xscr"]=0x1D4CD,
- ["xsqcup"]=0x02A06,
- ["xuplus"]=0x02A04,
- ["xutri"]=0x025B3,
- ["xvee"]=0x022C1,
- ["xwedge"]=0x022C0,
- ["Yacute"]=0x000DD,
- ["yacute"]=0x000FD,
- ["YAcy"]=0x0042F,
- ["yacy"]=0x0044F,
- ["Ycirc"]=0x00176,
- ["ycirc"]=0x00177,
- ["Ycy"]=0x0042B,
- ["ycy"]=0x0044B,
- ["yen"]=0x000A5,
- ["Yfr"]=0x1D51C,
- ["yfr"]=0x1D536,
- ["YIcy"]=0x00407,
- ["yicy"]=0x00457,
- ["Yopf"]=0x1D550,
- ["yopf"]=0x1D56A,
- ["Yscr"]=0x1D4B4,
- ["yscr"]=0x1D4CE,
- ["YUcy"]=0x0042E,
- ["yucy"]=0x0044E,
- ["Yuml"]=0x00178,
- ["yuml"]=0x000FF,
- ["Zacute"]=0x00179,
- ["zacute"]=0x0017A,
- ["Zcaron"]=0x0017D,
- ["zcaron"]=0x0017E,
- ["Zcy"]=0x00417,
- ["zcy"]=0x00437,
- ["Zdot"]=0x0017B,
- ["zdot"]=0x0017C,
- ["zeetrf"]=0x02128,
- ["ZeroWidthSpace"]=0x0200B,
- ["zeta"]=0x003B6,
- ["Zfr"]=0x02128,
- ["zfr"]=0x1D537,
- ["ZHcy"]=0x00416,
- ["zhcy"]=0x00436,
- ["zigrarr"]=0x021DD,
- ["Zopf"]=0x02124,
- ["zopf"]=0x1D56B,
- ["Zscr"]=0x1D4B5,
- ["zscr"]=0x1D4CF,
-
- ["plusminus"]=0x000B1,
- ["minusplus"]=0x02213,
- ["cdots"]=0x2026,
-}
diff --git a/Master/texmf-dist/tex/context/base/math-eul.mkii b/Master/texmf-dist/tex/context/base/math-eul.mkii
index 7552957a866..f502445259c 100644
--- a/Master/texmf-dist/tex/context/base/math-eul.mkii
+++ b/Master/texmf-dist/tex/context/base/math-eul.mkii
@@ -5,7 +5,7 @@
%D subtitle=Virtual Euler Specials,
%D author={Hans Hagen \& Taco Hoekwater \& Adam Lindsay},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-for.mkiv b/Master/texmf-dist/tex/context/base/math-for.mkiv
index e33276d5385..aee6405720c 100644
--- a/Master/texmf-dist/tex/context/base/math-for.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-for.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Math Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -18,62 +18,31 @@
\unprotect
-\let\currentformula\s!unknown
-
-\def\formulaparameter #1{\csname\doformulaparameter{\??fm\currentformula}#1\endcsname}
-\def\formulaparameterhash#1{\doformulaparameterhash {\??fm\currentformula}#1}
-
-\def\doformulaparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doformulaparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\doformulaparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doformulaparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\detokenizedformulaparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??fm\currentformula#1\endcsname}}
-
-\def\doformulaparentparameter #1#2{\ifx#1\relax\s!empty\else\doformulaparameter #1#2\fi}
-\def\doformulaparentparameterhash#1#2{\ifx#1\relax \else\doformulaparameterhash#1#2\fi}
-
-\def\dosetformulaattributes#1#2% style color
- {\edef\fontattributehash {\formulaparameterhash#1}%
- \edef\colorattributehash{\formulaparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-\def\getformulaparameters{\getparameters[\??fm]}
-
-%D \macros
-%D {setupformulas}
-
-\newtoks \everysetupformulas
-
-\unexpanded\def\setupformulas
- {\dodoubleempty\dosetupformulas}
-
-\def\dosetupformulas[#1][#2]%
- {\ifsecondargument
- \edef\currentformula{#1}%
- \getparameters[\??fm#1][#2]%
- \else
-% \let\currentformula\v!formula % hm
- \let\currentformula\empty
- \getparameters[\??fm][#1]%
- \fi
- \the\everysetupformulas
- \let\currentformula\empty}
-
-%D Not yet cleanup up:
-
%D \macros
-%D {setuptextformulas}
-%D
-%D This command sets up in||line math. Most features deals
-%D with grid snapping and are experimental.
-
-\newtoks \everysetuptextformulas
-
-\unexpanded\def\setuptextformulas
- {\dosingleempty\dosetuptextformulas}
-
-\def\dosetuptextformulas[#1]%
- {\getparameters[\??mt][#1]%
- \the\everysetuptextformulas}
+%D {setupformulas,setupsubformulas}
+
+\installcorenamespace{formula}
+\installcorenamespace{subformula}
+
+\installcommandhandler \??formula {formula} \??formula
+\installcommandhandler \??subformula {subformula} \??subformula % maybe just setuphandler (no childs used yet)
+
+\let\setupformulas \setupformula
+\let\setupsubformulas\setupsubformula
+
+% D \macros
+% D {setuptextformulas}
+% D
+% D This command sets up in||line math. Most features deals
+% D with grid snapping and are experimental.
+
+% \newtoks \everysetuptextformulas
+%
+% \unexpanded\def\setuptextformulas
+% {\dosingleempty\dosetuptextformulas}
+%
+% \def\dosetuptextformulas[#1]%
+% {\getparameters[\??mt][#1]%
+% \the\everysetuptextformulas}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/math-fou.mkii b/Master/texmf-dist/tex/context/base/math-fou.mkii
index 8a72f128847..26b03d73ec9 100644
--- a/Master/texmf-dist/tex/context/base/math-fou.mkii
+++ b/Master/texmf-dist/tex/context/base/math-fou.mkii
@@ -5,7 +5,7 @@
%D subtitle=Fourier Specials,
%D author={Michel Biovani \& Hans Hagen},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-frc.mkii b/Master/texmf-dist/tex/context/base/math-frc.mkii
index 767c5ec5cea..b14c9377497 100644
--- a/Master/texmf-dist/tex/context/base/math-frc.mkii
+++ b/Master/texmf-dist/tex/context/base/math-frc.mkii
@@ -5,7 +5,7 @@
%D subtitle=Fractions,
%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-frc.mkiv b/Master/texmf-dist/tex/context/base/math-frc.mkiv
index f6331126f51..59bd588c0b5 100644
--- a/Master/texmf-dist/tex/context/base/math-frc.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-frc.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Fractions,
%D author={Hans Hagen \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -15,6 +15,8 @@
\unprotect
+% quite old ... still needed?
+
%D \macros
%D {frac, xfrac, xxfrac}
%D
@@ -66,10 +68,8 @@
%D So we stick to the next definitions (watch the local
%D overloading of \type {\xfrac}).
-% \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}}
-
-\def\dofrac#1#2#3{\relax\mathematics{\Ustack{{#1{#2}}\normalover{#1{#3}}}}}
-\def\nofrac #1#2{\relax\mathematics{\Ustack{{#1}\normalover{#2}}}}
+\def\math_fractions_forced#1#2#3{\relax\mathematics{\Ustack{{#1{#2}}\normalover{#1{#3}}}}}
+\def\math_fractions_auto #1#2{\relax\mathematics{\Ustack{{#1}\normalover{#2}}}}
% $\mathfracmode0 \frac{1}{2}$
% $\mathfracmode1 \frac{1}{2}$
@@ -82,30 +82,30 @@
\setnewconstant\mathfracmode\zerocount
-\unexpanded\def\frac
+\unexpanded\def\frac % overloaded later on
{\ifcase\mathfracmode
- \expandafter\nofrac
+ \expandafter\math_fractions_auto
\or
- \expandafter\dofrac\expandafter\displaystyle
+ \expandafter\math_fractions_forced\expandafter\displaystyle
\or
- \expandafter\dofrac\expandafter\textstyle
+ \expandafter\math_fractions_forced\expandafter\textstyle
\or
- \expandafter\dofrac\expandafter\scriptstyle
+ \expandafter\math_fractions_forced\expandafter\scriptstyle
\or
- \expandafter\dofrac\expandafter\scriptscriptstyle
+ \expandafter\math_fractions_forced\expandafter\scriptscriptstyle
\else
- \expandafter\dofrac\expandafter\mathstyle
+ \expandafter\math_fractions_forced\expandafter\mathstyle
\fi}
\unexpanded\def\xfrac#1#2%
{\begingroup
\let\xfrac\xxfrac
- \dofrac\scriptstyle{#1}{#2}%
+ \math_fractions_forced\scriptstyle{#1}{#2}%
\endgroup}
\unexpanded\def\xxfrac#1#2%
{\begingroup
- \dofrac\scriptscriptstyle{#1}{#2}%
+ \math_fractions_forced\scriptscriptstyle{#1}{#2}%
\endgroup}
%D The \type {xx} variant looks still ugly, so maybe it's
@@ -113,7 +113,7 @@
\unexpanded\def\xxfrac#1#2%
{\begingroup
- \dofrac\scriptscriptstyle{#1}{\raise.25ex\hbox{$\scriptscriptstyle#2$}}%
+ \math_fractions_forced\scriptscriptstyle{#1}{\raise.25ex\hbox{$\scriptscriptstyle#2$}}%
\endgroup}
%D Something low level for scientific calculator notation:
@@ -121,132 +121,12 @@
\unexpanded\def\scinot#1#2%
{#1\times10^{#2}}
-%D The next macro, \type {\ch}, is \PPCHTEX\ aware. In
-%D formulas one can therefore best use \type {\ch} instead of
-%D \type {\chemical}, especially in fractions.
-
-% let's see who complains ... \mathstyle is now a primitive
-%
-% \unexpanded\def\ch#1%
-% {\ifdefined\@@chemicalletter
-% \dosetsubscripts
-% \mathstyle{\@@chemicalletter{#1}}%
-% \doresetsubscripts
-% \else
-% \mathstyle{\rm#1}%
-% \fi}
-
-% \unexpanded\def\ch#1%
-% {\ifdefined\@@chemicalletter
-% \dosetsubscripts
-% \mathematics{\@@chemicalletter{#1}}%
-% \doresetsubscripts
-% \else
-% \mathematics{\rm#1}%
-% \fi}
-
-%D \macros
-%D {/}
-%D
-%D Just to be sure, we restore the behavior of some typical
-%D math characters.
-
-\bgroup
-
-\catcode`\/=\othercatcode \global \let\normalforwardslash/
-\catcode`\/=\activecatcode \doglobal\appendtoks\let/\normalforwardslash\to\everymathematics
-
-\egroup
-
-% to be checked:
-
-\unexpanded\def\exmthfont#1%
- {\symbolicsizedfont#1\plusone{MathExtension}}
-
-\def\domthfrac#1#2#3#4#5#6#7%
- {\begingroup
- \mathsurround\zeropoint
- \setbox0\hbox{$#1 #6$}%
- \setbox2\hbox{$#1 #7$}%
- \dimen0\wd0
- \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
- \setbox4\hbox to \dimen0{\exmthfont#2#3\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\domthsqrt#1#2#3#4#5%
- {\begingroup
- \mathsurround\zeropoint
- \setbox0\hbox{$#1 #5$}%
- \dimen0=1.05\ht0 \advance\dimen0 1pt \ht0 \dimen0
- \dimen0=1.05\dp0 \advance\dimen0 1pt \dp0 \dimen0
- \dimen0\wd0
- \setbox4\hbox to \dimen0{\exmthfont#2\leaders\hbox{#3}\hfill#4}%
- \delimitershortfall=0pt
- \nulldelimiterspace=0pt
- \setbox2\hbox{$\left\delimiter"0270370 \vrule height\ht0 depth \dp0 width0pt
- \right.$}%
- \mathord{\vcenter{\hbox{\copy2
- \rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}%
- \endgroup}
-
-\unexpanded\def\mthfrac#1#2#3#4#5{\mathchoice
- {\domthfrac\displaystyle \textface {#1}{#2}{#3}{#4}{#5}}
- {\domthfrac\textstyle \textface {#1}{#2}{#3}{#4}{#5}}
- {\domthfrac\scriptstyle \scriptface {#1}{#2}{#3}{#4}{#5}}
- {\domthfrac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}}
-
-\unexpanded\def\mthsqrt#1#2#3{\mathchoice
- {\domthsqrt\displaystyle \textface {#1}{#2}{#3}}
- {\domthsqrt\textstyle \textface {#1}{#2}{#3}}
- {\domthsqrt\scriptstyle \textface {#1}{#2}{#3}}
- {\domthsqrt\scriptscriptstyle\textface {#1}{#2}{#3}}}
+% 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.
-%D Moved from math-new.tex (not that new anyway):
-
-%D \macros
-%D {genfrac}
-%D
-%D [TH] The definition of \type {\genfrac} \& co. is not
-%D trivial, because it allows some flexibility. This is
-%D supposed to be a user||level command, but will fail quite
-%D desparately if called outside math mode (\CONTEXT\ redefines
-%D \type {\over})
-%D
-%D [HH] We clean up this macro a bit and (try) to make it
-%D understandable. The expansion is needed for generating
-%D the second argument to \type {\dogenfrac}, which is to
-%D be a control sequence like \type {\over}.
-
-\unexpanded\def\genfrac#1#2#3#4%
- {\edef\!!stringa
- {#1#2}%
- \expanded
- {\dogenfrac{#4}%
- \csname
- \ifx @#3@%
- \ifx\!!stringa\empty
- \strippedcsname\normalover
- \else
- \strippedcsname\normaloverwithdelims
- \fi
- \else
- \ifx\!!stringa\empty
- \strippedcsname\normalabove
- \else
- \strippedcsname\normalabovewithdelims
- \fi
- \fi
- \endcsname}%
- {#1#2#3}}
-
-\def\dogenfrac#1#2#3#4#5%
- {{#1{\begingroup#4\endgroup#2#3\relax#5}}}
+\unexpanded\def\mthfrac#1#2#3{[mthfrac: #1 #2 #3]}
+\unexpanded\def\mthsqrt#1#2#3{[mthsqrt: #1 #2 #3]}
%D \macros
%D {dfrac, tfrac, frac, dbinom, tbinom, binom}
@@ -257,21 +137,23 @@
%D \stopbuffer
%D
%D \typebuffer
-%D
%D \getbuffer
-\unexpanded\def\dfrac {\genfrac\empty\empty{}\displaystyle}
-\unexpanded\def\tfrac {\genfrac\empty\empty{}\textstyle}
-\unexpanded\def\frac {\genfrac\empty\empty{}\donothing}
+% extra {} after displaystyle etc are needed
-\unexpanded\def\dbinom{\genfrac()\zeropoint\displaystyle}
-\unexpanded\def\tbinom{\genfrac()\zeropoint\textstyle}
-\unexpanded\def\binom {\genfrac()\zeropoint\donothing}
+%unexpanded\def\frac #1#2{{ {{#1}\normalover {#2}}}}
+%unexpanded\def\xfrac #1#2{{\scriptstyle {{#1}\normalover {#2}}}}
+%unexpanded\def\xxfrac#1#2{{\scriptscriptstyle{{#1}\normalover {#2}}}}
+\unexpanded\def\dfrac #1#2{{\displaystyle {{#1}\normalover {#2}}}}
+\unexpanded\def\tfrac #1#2{{\textstyle {{#1}\normalover {#2}}}}
-\unexpanded\def\xfrac {\genfrac\empty\empty{}\scriptstyle}
-\unexpanded\def\xxfrac{\genfrac\empty\empty{}\scriptscriptstyle}
+%unexpanded\def\binom #1#2{{ {{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+\unexpanded\def\dbinom#1#2{{\displaystyle {{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+\unexpanded\def\tbinom#1#2{{\textstyle {{#1}\normalabovewithdelims()\zeropoint{#2}}}}
-\unexpanded\def\frac#1#2{\mathematics{\genfrac\empty\empty{}\donothing{#1}{#2}}}
+\unexpanded\def\binom #1#2{{\Ustack{{#1}\normalabovewithdelims()\zeropoint{#2}}}}
+
+% \let\frac\math_fractions_auto
%D \macros
%D {cfrac}
@@ -298,12 +180,13 @@
%D
%D \getbuffer
-\definecomplexorsimple\cfrac
+\unexpanded\def\cfrac
+ {\doifnextoptionalelse\math_cfrac_yes\math_cfrac_nop}
-\def\simplecfrac {\docfrac[cc]}
-\def\complexcfrac[#1]{\docfrac[#1cc]}
+\def\math_cfrac_nop {\math_cfrac_indeed[cc]}
+\def\math_cfrac_yes[#1]{\math_cfrac_indeed[#1cc]}
-\def\docfrac[#1#2#3]#4#5%
+\def\math_cfrac_indeed[#1#2#3]#4#5%
{{\displaystyle
\frac
{\strut
@@ -335,17 +218,13 @@
%D \typebuffer \getbuffer
%D
%D These macros are based on Michael J.~Downes posting on
-%D comp.text.tex on 2001/12/06
+%D comp.text.tex on 2001/12/06 but adapted a bit.
-\unexpanded\def\splitfrac#1#2%
- {\genfrac\empty\empty\zeropoint\textstyle%
- {\textstyle#1\quad\hfill}%
- {\textstyle\hfill\quad\mathstrut#2}}
+\unexpanded\def\splitfrac #1#2%
+ {{\textstyle {{\textstyle#1\quad\hfill}\normalabove\zeropoint{\textstyle\hfill\quad\mathstrut#2}}}}
\unexpanded\def\splitdfrac#1#2%
- {\genfrac\empty\empty\zeropoint\displaystyle%
- {#1\quad\hfill}
- {\hfill\quad\mathstrut #2}}
+ {{\displaystyle{{ #1\quad\hfill}\normalabove\zeropoint{ \hfill\quad\mathstrut#2}}}}
%D For thee moment here, but it might move:
@@ -359,11 +238,11 @@
\unexpanded\def\qedsymbol#1%
{\ifhmode
- \unskip~\hfill#1\par
+ \unskip\nobreakspace\hfill#1\par
\else\ifmmode
- \eqno#1\relax % Do we really need the \eqno here?
+ #1\relax % leading \eqno removed
\else
- \leavevmode\hbox{}\hfill#1\par
+ \dontleavehmode\emptyhbox\hfill#1\par
\fi\fi}
\definesymbol [qed] [\qedsymbol{\mathematics{\square}}]
@@ -378,21 +257,11 @@
\unexpanded\def\QED{\symbol[qed]}
%D \macros
-%D {mathhexbox}
-%D
-%D [TH] \type {\mathhexbox} is also user||level (already
-%D defined in Plain \TEX). It allows to get a math character
-%D inserted as if it was a text character.
-
-\unexpanded\def\mathhexbox#1#2#3%
- {\mathtext{$\mathsurround\zeropoint\mathchar"#1#2#3$}}
-
-%D \macros
%D {boxed}
%D
-%D [HH] Another macro that users expect (slightly adapted):
+%D [HH] Another macro that users might expect (slightly adapted):
-\unexpanded\def\boxed
+\unexpanded\def\boxed % maybe obsolete
{\ifmmode\expandafter\mframed\else\expandafter\framed\fi}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/math-ini.lua b/Master/texmf-dist/tex/context/base/math-ini.lua
index a122f722975..54452282bb0 100644
--- a/Master/texmf-dist/tex/context/base/math-ini.lua
+++ b/Master/texmf-dist/tex/context/base/math-ini.lua
@@ -8,9 +8,18 @@ if not modules then modules = { } end modules ['math-ext'] = {
-- if needed we can use the info here to set up xetex definition files
-- the "8000 hackery influences direct characters (utf) as indirect \char's
+--
+-- isn't characters.data loaded already ... shortcut it here
-local texsprint, format, utfchar, utfbyte = tex.sprint, string.format, utf.char, utf.byte
+local format, utfchar, utfbyte = string.format, utf.char, utf.byte
local setmathcode, setdelcode = tex.setmathcode, tex.setdelcode
+local texattribute = tex.attribute
+local floor = math.floor
+
+local context = context
+
+local contextsprint = context.sprint
+local contextfprint = context.fprint -- a bit inefficient
local allocate = utilities.storage.allocate
@@ -25,7 +34,8 @@ mathematics.extrabase = 0xFE000 -- here we push some virtuals
mathematics.privatebase = 0xFF000 -- here we push the ex
local families = allocate {
- tf = 0, it = 1, sl = 2, bf = 3, bi = 4, bs = 5, -- no longer relevant
+ mr = 0,
+ mb = 1,
}
local classes = allocate {
@@ -53,8 +63,20 @@ local classes = allocate {
nolop = 1, -- mathnolopcomm @@mathnolopcomm
}
-mathematics.families = families
+local codes = allocate {
+ ordinary = 0, [0] = "ordinary",
+ largeoperator = 1, [1] = "largeoperator",
+ binaryoperator = 2, [2] = "binaryoperator",
+ relation = 3, [3] = "relation",
+ openingsymbol = 4, [4] = "openingsymbol",
+ closingsymbol = 5, [5] = "closingsymbol",
+ punctuation = 6, [6] = "punctuation",
+ variable = 7, [7] = "variable",
+}
+
mathematics.classes = classes
+mathematics.codes = codes
+mathematics.families = families
classes.alphabetic = classes.alpha
classes.unknown = classes.nothing
@@ -98,14 +120,8 @@ end
local function mathtopaccent(class,family,slot)
return format('\\Umathaccent "%X "%X "%X ',0,family,slot) -- no class
end
-if tex.luatexversion > 65 then -- this will disappear at 0.70
- local function mathbotaccent(class,family,slot)
- return format('\\Umathaccent bottom "%X "%X "%X ',0,family,slot) -- no class
- end
-else
- local function mathbotaccent(class,family,slot)
- return format('\\Umathbotaccent "%X "%X "%X ',0,family,slot) -- no class
- end
+local function mathbotaccent(class,family,slot)
+ return format('\\Umathaccent bottom "%X "%X "%X ',0,family,slot) -- no class
end
local function mathtopdelimiter(class,family,slot)
return format('\\Udelimiterover "%X "%X ',family,slot) -- no class
@@ -118,16 +134,19 @@ local escapes = characters.filters.utf.private.escapes
local setmathcharacter, setmathsynonym, setmathsymbol -- once updated we will inline them
+-- beware ... we only set the math character once ... which is why we
+-- have the 'done' checking below
+
if setmathcode then
- setmathcharacter = function(class,family,slot,unicode,firsttime)
- if not firsttime and class <= 7 then
+ setmathcharacter = function(class,family,slot,unicode)
+ if class <= 7 then
setmathcode(slot,{class,family,unicode or slot})
end
end
- setmathsynonym = function(class,family,slot,unicode,firsttime)
- if not firsttime and class <= 7 then
+ setmathsynonym = function(class,family,slot,unicode,setcode)
+ if setcode and class <= 7 then
setmathcode(slot,{class,family,unicode})
end
if class == classes.open or class == classes.close then
@@ -137,69 +156,70 @@ if setmathcode then
setmathsymbol = function(name,class,family,slot) -- hex is nicer for tracing
if class == classes.accent then
- texsprint(format([[\unexpanded\gdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot))
+ contextsprint(format([[\unexpanded\gdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot))
elseif class == classes.topaccent then
- texsprint(format([[\unexpanded\gdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot))
+ contextsprint(format([[\unexpanded\gdef\%s{\Umathaccent 0 "%X "%X }]],name,family,slot))
elseif class == classes.botaccent then
- texsprint(format([[\unexpanded\gdef\%s{\Umathbotaccent 0 "%X "%X }]],name,family,slot))
+ contextsprint(format([[\unexpanded\gdef\%s{\Umathbotaccent 0 "%X "%X }]],name,family,slot))
elseif class == classes.over then
- texsprint(format([[\unexpanded\gdef\%s{\Udelimiterover "%X "%X }]],name,family,slot))
+ contextsprint(format([[\unexpanded\gdef\%s{\Udelimiterover "%X "%X }]],name,family,slot))
elseif class == classes.under then
- texsprint(format([[\unexpanded\gdef\%s{\Udelimiterunder "%X "%X }]],name,family,slot))
+ contextsprint(format([[\unexpanded\gdef\%s{\Udelimiterunder "%X "%X }]],name,family,slot))
elseif class == classes.open or class == classes.close then
setdelcode(slot,{family,slot,0,0})
- texsprint(format([[\unexpanded\gdef\%s{\Udelimiter "%X "%X "%X }]],name,class,family,slot))
+ contextsprint(format([[\unexpanded\gdef\%s{\Udelimiter "%X "%X "%X }]],name,class,family,slot))
elseif class == classes.delimiter then
setdelcode(slot,{family,slot,0,0})
- texsprint(format([[\unexpanded\gdef\%s{\Udelimiter 0 "%X "%X }]],name,family,slot))
+ contextsprint(format([[\unexpanded\gdef\%s{\Udelimiter 0 "%X "%X }]],name,family,slot))
elseif class == classes.radical then
- texsprint(format([[\unexpanded\gdef\%s{\Uradical "%X "%X }]],name,family,slot))
+ contextsprint(format([[\unexpanded\gdef\%s{\Uradical "%X "%X }]],name,family,slot))
else
-- beware, open/close and other specials should not end up here
- texsprint(format([[\unexpanded\gdef\%s{\Umathchar "%X "%X "%X }]],name,class,family,slot))
+-- contextsprint(format([[\unexpanded\gdef\%s{\Umathchar "%X "%X "%X }]],name,class,family,slot))
+ contextsprint(format([[\Umathchardef\%s "%X "%X "%X ]],name,class,family,slot))
end
end
else
- setmathcharacter = function(class,family,slot,unicode,firsttime)
- if not firsttime and class <= 7 then
- texsprint(mathcode(slot,class,family,unicode or slot))
+ setmathcharacter = function(class,family,slot,unicode)
+ if class <= 7 then
+ contextsprint(mathcode(slot,class,family,unicode or slot))
end
end
- setmathsynonym = function(class,family,slot,unicode,firsttime)
- if not firsttime and class <= 7 then
- texsprint(mathcode(slot,class,family,unicode))
+ setmathsynonym = function(class,family,slot,unicode,setcode)
+ if setcode and class <= 7 then
+ contextsprint(mathcode(slot,class,family,unicode))
end
if class == classes.open or class == classes.close then
- texsprint(delcode(slot,family,unicode))
+ contextsprint(delcode(slot,family,unicode))
end
end
setmathsymbol = function(name,class,family,slot)
if class == classes.accent then
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathaccent(class,family,slot)))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathaccent(class,family,slot)))
elseif class == classes.topaccent then
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathtopaccent(class,family,slot)))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathtopaccent(class,family,slot)))
elseif class == classes.botaccent then
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathbotaccent(class,family,slot)))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathbotaccent(class,family,slot)))
elseif class == classes.over then
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathtopdelimiter(class,family,slot)))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathtopdelimiter(class,family,slot)))
elseif class == classes.under then
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathbotdelimiter(class,family,slot)))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathbotdelimiter(class,family,slot)))
elseif class == classes.open or class == classes.close then
- texsprint(delcode(slot,family,slot))
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,delimiter(class,family,slot)))
+ contextsprint(delcode(slot,family,slot))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,delimiter(class,family,slot)))
elseif class == classes.delimiter then
- texsprint(delcode(slot,family,slot))
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,delimiter(0,family,slot)))
+ contextsprint(delcode(slot,family,slot))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,delimiter(0,family,slot)))
elseif class == classes.radical then
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,radical(family,slot)))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,radical(family,slot)))
else
-- beware, open/close and other specials should not end up here
- texsprint(format("\\unexpanded\\xdef\\%s{%s}",name,mathchar(class,family,slot)))
+ contextsprint(format([[\unexpanded\xdef\%s{%s}]],name,mathchar(class,family,slot)))
end
end
@@ -216,7 +236,7 @@ local function report(class,family,unicode,name)
end
end
--- there will be a combined \(math)chardef
+-- there will be a combined \(math)chardef (tracker)
function mathematics.define(family)
family = family or 0
@@ -224,6 +244,7 @@ function mathematics.define(family)
local data = characters.data
for unicode, character in next, data do
local symbol = character.mathsymbol
+ local setcode = true
if symbol then
local other = data[symbol]
local class = other.mathclass
@@ -232,7 +253,8 @@ function mathematics.define(family)
if trace_defining then
report(class,family,unicode,symbol)
end
- setmathsynonym(class,family,unicode,symbol)
+ setmathsynonym(class,family,unicode,symbol,setcode)
+ setcode = false
end
local spec = other.mathspec
if spec then
@@ -240,7 +262,8 @@ function mathematics.define(family)
local class = m.class
if class then
class = classes[class] or class -- no real checks needed
- setmathsynonym(class,family,unicode,symbol,i)
+ setmathsynonym(class,family,unicode,symbol,setcode)
+ setcode = false
end
end
end
@@ -271,7 +294,10 @@ function mathematics.define(family)
end
end
end
- setmathcharacter(class,family,unicode,unicode,i)
+ if setcode then
+ setmathcharacter(class,family,unicode,unicode)
+ setcode = false
+ end
end
end
end
@@ -303,37 +329,40 @@ end
-- needed for mathml analysis
-function mathematics.utfmathclass(chr, default)
+local function utfmathclass(chr, default)
local cd = characters.data[utfbyte(chr)]
return (cd and cd.mathclass) or default or "unknown"
end
-function mathematics.utfmathstretch(chr, default) -- "h", "v", "b", ""
+
+local function utfmathstretch(chr, default) -- "h", "v", "b", ""
local cd = characters.data[utfbyte(chr)]
return (cd and cd.mathstretch) or default or ""
end
-function mathematics.utfmathcommand(chr, default)
+
+local function utfmathcommand(chr, default)
local cd = characters.data[utfbyte(chr)]
local cmd = cd and cd.mathname
return cmd or default or ""
end
-function mathematics.utfmathfiller(chr, default)
+
+local function utfmathfiller(chr, default)
local cd = characters.data[utfbyte(chr)]
local cmd = cd and (cd.mathfiller or cd.mathname)
return cmd or default or ""
end
--- xml
+mathematics.utfmathclass = utfmathclass
+mathematics.utfmathstretch = utfmathstretch
+mathematics.utfmathcommand = utfmathcommand
+mathematics.utfmathfiller = utfmathfiller
-mathematics.xml = { entities = { } }
+-- interfaced
+
+function commands.utfmathclass (chr) context(utfmathclass (chr)) end
+function commands.utfmathstretch(chr) context(utfmathstretch(chr)) end
+function commands.utfmathcommand(chr) context(utfmathcommand(chr)) end
+function commands.utfmathfiller (chr) context(utfmathfiller (chr)) end
-function mathematics.xml.registerentities()
- local entities = xml.entities
- for name, unicode in next, mathematics.xml.entities do
- if not entities[name] then
- entities[name] = utfchar(unicode)
- end
- end
-end
-- helpers
@@ -365,3 +394,70 @@ function mathematics.big(tfmdata,unicode,n)
return unicode
end
+-- experimental
+
+-- local categories = { } -- indexed + hashed
+--
+-- local a_mathcategory = attributes.private("mathcategory")
+--
+-- local function registercategory(category,tag,data) -- always same data for tag
+-- local c = categories[category]
+-- if not c then
+-- c = { }
+-- categories[category] = c
+-- end
+-- local n = c[tag]
+-- if not n then
+-- n = #c + 1
+-- c[n] = data
+-- n = n * 1000 + category
+-- c[tag] = n
+-- end
+-- return n
+-- end
+--
+-- function mathematics.getcategory(n)
+-- local category = n % 1000
+-- return category, categories[category][floor(n/1000)]
+-- end
+--
+-- mathematics.registercategory = registercategory
+--
+-- function commands.taggedmathfunction(tag,label)
+-- if label then
+-- texattribute[a_mathcategory] = registercategory(1,tag,tag)
+-- context.mathlabeltext(tag)
+-- else
+-- texattribute[a_mathcategory] = 1
+-- context(tag)
+-- end
+-- end
+
+local categories = { }
+mathematics.categories = categories
+
+local a_mathcategory = attributes.private("mathcategory")
+
+local functions = storage.allocate()
+local noffunctions = 1000 -- offset
+
+categories.functions = functions
+
+function commands.taggedmathfunction(tag,label,apply)
+ local delta = apply and 1000 or 0
+ if label then
+ local n = functions[tag]
+ if not n then
+ noffunctions = noffunctions + 1
+ functions[noffunctions] = tag
+ functions[tag] = noffunctions
+ texattribute[a_mathcategory] = noffunctions + delta
+ else
+ texattribute[a_mathcategory] = n + delta
+ end
+ context.mathlabeltext(tag)
+ else
+ texattribute[a_mathcategory] = 1000 + delta
+ context(tag)
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/math-ini.mkii b/Master/texmf-dist/tex/context/base/math-ini.mkii
index 9f7ab49e5a1..d6d10feb323 100644
--- a/Master/texmf-dist/tex/context/base/math-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/math-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initializations,
%D author={Hans Hagen \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-ini.mkiv b/Master/texmf-dist/tex/context/base/math-ini.mkiv
index f778afa08c5..710a65f5b36 100644
--- a/Master/texmf-dist/tex/context/base/math-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initializations,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -27,20 +27,26 @@
\unprotect
-\ifx\v!compact\undefined \def\v!compact{compact} \fi
+\ifdefined\v!autopunctuation \else \def\v!autopunctuation{autopunctuation} \fi
+\ifdefined\v!integral \else \def\v!integral {integral} \fi
+
+\def\s!lcgreek {lcgreek}
+\def\s!ucgreek {ucgreek}
+\def\s!italics {italics}
+\def\s!integral{integral}
%D We move these definitions into the format:
-% test [[\char948 \ctxlua{tex.sprint(utf.char(948))}]]
-% test $[[\char948 \ctxlua{tex.sprint(utf.char(948))}]]$
+% test [[\char948 \cldcontext{utf.char(948)}]]
+% test $[[\char948 \cldcontext{utf.char(948)}]]$
\registerctxluafile{math-ini}{1.001}
\registerctxluafile{math-dim}{1.001}
\registerctxluafile{math-act}{1.001}
-\registerctxluafile{math-ent}{1.001}
\registerctxluafile{math-ext}{1.001}
\registerctxluafile{math-vfu}{1.001}
\registerctxluafile{math-map}{1.001}
+\registerctxluafile{math-ren}{1.001}
\registerctxluafile{math-noa}{1.001}
\registerctxluafile{math-tag}{1.001}
@@ -49,52 +55,133 @@
\definesystemattribute[mathpunctuation][public]
\definesystemattribute[mathgreek] [public]
\definesystemattribute[mathalternate] [public]
+\definesystemattribute[mathrendering] [public]
+\definesystemattribute[mathcategory] [public]
+\definesystemattribute[mathmode] [public]
+\definesystemattribute[mathitalics] [public]
-% experiment
+\appendtoks
+ \attribute\mathmodeattribute\plusone
+\to \everydisplay
-% Normally this is applied to only one character.
+\appendtoks
+ \attribute\mathmodeattribute\plusone
+\to \everybeforedisplayformula
+
+\setnewconstant\defaultmathfamily \zerocount % 255
+
+%D Some measures (maybe spac-mth):
+
+% \def\mathskipsmall {\mskip\thinmuskip}
+% \def\mathskipmedium{\mskip\medmuskip}
+% \def\mathskipbig {\mskip\thickmuskip}
+
+%D \macros
+%D {setupmathematics}
+%D
+%D Configuration for integrals. (If needed we can speed this up and make it
+%D installable; no processaction is needed then).
+
+% \newtoks\everysetupmathematics
%
-% $ABC$ $\cal ABC$ $\mathaltcal ABC$
+% \unexpanded\def\setupmathematics
+% {\dosingleargument\dosetupmathematics}
+%
+% \def\dosetupmathematics[#1]%
+% {\getparameters[\??mo][#1]%
+% \the\everysetupmathematics}
+%
+% \def\mathematicsparameter#1%
+% {\ifcsname\??mo#1\endcsname\csname\??mo#1\endcsname\fi}
+
+\installcorenamespace{mathematics}
+
+\installswitchcommandhandler \??mathematics {mathematics} \??mathematics
+
+\unexpanded\def\startmathematics % no grouping, if ever then also an optional second
+ {\doifnextoptionalelse\math_mathematics_start_yes\math_mathematics_start_nop}
+
+\unexpanded\def\math_mathematics_start_yes[#1]%
+ {\pushmacro\currentmathematics
+ \edef\currentmathematics{#1}% check for valid
+ \the\everyswitchmathematics}
-\def\mathalternate#1{\ctxlua{mathematics.setalternate(0,"#1")}} % fam 0
+\unexpanded\def\math_mathematics_start_nop
+ {\pushmacro\currentmathematics
+ \let\currentmathematics\empty
+ \the\everyswitchmathematics}
-\def\mathaltcal{\mathalternate{cal}\cal} % ss01 in xits
+\unexpanded\def\stopmathematics
+ {\popmacro\currentmathematics
+ \the\everyswitchmathematics}
+
+\definemathematics[\v!default] % not needed, but nicer when nesting back to normal
+
+% Normally this is applied to only one character.
+%
+% $ABC$ $\cal ABC$ $\mathaltcal ABC$
% todo: only in mmode
-\unexpanded\def\mathgreekupright{\attribute\mathgreekattribute22 }
-\unexpanded\def\mathgreekitalic {\attribute\mathgreekattribute33 }
-\unexpanded\def\mathgreekdefault{\attribute\mathgreekattribute\attributeunsetvalue}
+\unexpanded\def\mathgreekupright{\attribute\c_math_greek_attribute22 }
+\unexpanded\def\mathgreekitalic {\attribute\c_math_greek_attribute33 }
+\unexpanded\def\mathgreekdefault{\attribute\c_math_greek_attribute\attributeunsetvalue}
\let\mathgreeknormal\mathgreekupright
\let\mathgreeknone \mathgreekdefault
-\def\setmathattribute#1#2{\ifmmode\ctxlua{mathematics.syncboth ("#1","#2")}\fi}
-\def\setmathalphabet #1{\ifmmode\ctxlua{mathematics.syncname ("#1")}\fi}
-\def\setmathstyle #1{\ifmmode\ctxlua{mathematics.syncstyle("#1")}\fi}
+\unexpanded\def\setmathattribute#1#2{\ifmmode\ctxcommand{setmathattribute("#1","#2")}\fi}
+\unexpanded\def\setmathalphabet #1{\ifmmode\ctxcommand{setmathalphabet("#1")}\fi}
+\unexpanded\def\setmathstyle #1{\ifmmode\ctxcommand{setmathstyle("#1")}\fi}
+\unexpanded\def\setmathalternate #1{\ifmmode\ctxcommand{setmathalternate(\number\defaultmathfamily,"#1")}\fi}
-\unexpanded\def\mr {\setmathattribute{regular}{tf}}
+\installcorenamespace{mathstylealternate} % might become a setuphandler
-\unexpanded\def\mathdefault {\setmathattribute{regular}{it}}
-\unexpanded\def\mathscript {\setmathalphabet{script}}
-\unexpanded\def\mathfraktur {\setmathalphabet{fraktur}}
-\unexpanded\def\mathblackboard{\setmathalphabet{blackboard}}
+\unexpanded\def\setmathstylealterternate#1%
+ {\ifcsname\??mathstylealternate\fontclass:#1\endcsname
+ \expandafter\setmathalternate\csname\??mathstylealternate\fontclass:#1\endcsname
+ \else\ifcsname\??mathstylealternate#1\endcsname
+ \expandafter\setmathalternate\csname\??mathstylealternate#1\endcsname
+ \fi\fi}
-\unexpanded\def\mathrm{\setmathattribute{rm}{tf}}
-\unexpanded\def\mathss{\setmathattribute{ss}{tf}}
-\unexpanded\def\mathtt{\setmathattribute{tt}{tf}}
+\unexpanded\def\setupmathrendering % the name might change
+ {\dodoubleargument\math_setup_rendering}
-\unexpanded\def\mathtf{\setmathstyle{tf}}
-\unexpanded\def\mathbf{\setmathstyle{bf}}
-\unexpanded\def\mathsl{\setmathstyle{sl}}
-\unexpanded\def\mathit{\setmathstyle{it}}
-\unexpanded\def\mathbs{\setmathstyle{bs}}
-\unexpanded\def\mathbi{\setmathstyle{bi}}
+\def\math_setup_rendering[#1][#2]%
+ {\ifsecondargument
+ \getparameters[\??mathstylealternate#1:][#2]%
+ \else
+ \getparameters[\??mathstylealternate][#1]%
+ \fi}
+
+\unexpanded\def\mathaltcal{\setmathalternate{cal}\cal} % ss01 in xits
+
+\let\mathalternate\setmathalternate % obsolete
+
+\unexpanded\def\mr {\setmathattribute\s!regular\s!tf\setmathstylealterternate\s!tf}
+
+\unexpanded\def\mathdefault {\setmathattribute\s!regular\s!it\setmathstylealterternate\s!it}
+\unexpanded\def\mathscript {\setmathalphabet \s!script \setmathstylealterternate\s!script}
+\unexpanded\def\mathfraktur {\setmathalphabet \s!fraktur \setmathstylealterternate\s!fraktur}
+\unexpanded\def\mathblackboard{\setmathalphabet \s!blackboard \setmathstylealterternate\s!blackboard}
+
+\unexpanded\def\mathrm {\setmathattribute\s!rm\s!tf \setmathstylealterternate\s!tf}
+\unexpanded\def\mathss {\setmathattribute\s!ss\s!tf \setmathstylealterternate\s!tf}
+\unexpanded\def\mathtt {\setmathattribute\s!tt\s!tf \setmathstylealterternate\s!tf}
+
+\unexpanded\def\mathtf {\setmathstyle\s!tf \setmathstylealterternate\s!tf}
+\unexpanded\def\mathsl {\setmathstyle\s!it \setmathstylealterternate\s!it} % no sl
+\unexpanded\def\mathit {\setmathstyle\s!it \setmathstylealterternate\s!it}
+
+\unexpanded\def\mathbf {\setmathstyle\s!bf \setmathstylealterternate\s!bf}
+\unexpanded\def\mathbs {\setmathstyle\s!bi \setmathstylealterternate\s!bi} % no sl
+\unexpanded\def\mathbi {\setmathstyle\s!bi \setmathstylealterternate\s!bi}
\let\tfmath\mathtf % maybe a grouped command
-\let\bfmath\mathbf
\let\slmath\mathsl
\let\itmath\mathit
+
+\let\bfmath\mathbf
\let\bsmath\mathbs
\let\bimath\mathbi
@@ -113,14 +200,6 @@
\let\normalmr\mr
-% \prependtoks
-% \let\mr\normalmr
-% \let\rm\mathrm \let\ss\mathss \let\tt\mathtt
-% \let\tf\mathtf \let\bf\mathbf \let\it\mathit \let\sl\mathsl \let\bi\mathbi \let\bs\mathbs
-% \let\frak\mathfraktur \let\cal\mathscript \let\bbd\mathblackboard
-% \mathdefault
-% \to \everymathematics
-
\let\normaltf\tf \unexpanded\def\tf{\ifmmode\mathtf\else\normaltf\fi}
\let\normalbf\bf \unexpanded\def\bf{\ifmmode\mathbf\else\normalbf\fi}
\let\normalit\it \unexpanded\def\it{\ifmmode\mathit\else\normalit\fi}
@@ -134,13 +213,41 @@
\unexpanded\def\mr{\ifmmode \normalmr\fi}
\prependtoks
-% \let\mr\normalmr
-% \let\rm\mathrm \let\ss\mathss \let\tt\mathtt
-% \let\tf\mathtf \let\bf\mathbf \let\it\mathit \let\sl\mathsl \let\bi\mathbi \let\bs\mathbs
-% \let\frak\mathfraktur \let\cal\mathscript \let\bbd\mathblackboard
\mathdefault
\to \everymathematics
+%D We could set the rendering attribute at the \LUA\ end but as there
+%D can be many small math snippets we keep track of the state at the
+%D \TEX\ end (mapping is export safe).
+%D
+%D \starttyping
+%D \startformula
+%D \reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411}
+%D \stopformula
+%D
+%D \setupmathematics
+%D [symbolset=blackboard-to-bold]
+%D
+%D \startformula
+%D \reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411}
+%D \stopformula
+%D \stoptyping
+
+\newcount\c_math_renderings_attribute
+
+\appendtoks
+ \c_math_renderings_attribute\ctxcommand{mathrenderset("\mathematicsparameter\c!symbolset")}\relax
+\to \everysetupmathematics % only in mathematics
+
+\appendtoks
+ \ifcase\c_math_renderings_attribute\else
+ \attribute\mathrenderingattribute\c_math_renderings_attribute
+ \fi
+\to \everymathematics
+
+\setupmathematics
+ [\c!symbolset=]
+
%D \macros
%D {boldsymbol}
%D
@@ -148,93 +255,84 @@
\let\mathboldsymbol\relax % yet unsupported, will be
-\def\boldsymbol
+\unexpanded\def\boldsymbol
{\mathortext\mathboldsymbol\bold}
%D Helpers:
-\def\utfmathclass #1{\cldcontext{mathematics.utfmathclass (\!!bs#1\!!es)}}
-\def\utfmathstretch#1{\cldcontext{mathematics.utfmathstretch(\!!bs#1\!!es)}}
-\def\utfmathcommand#1{\cldcontext{mathematics.utfmathcommand(\!!bs#1\!!es)}}
-\def\utfmathfiller #1{\cldcontext{mathematics.utfmathfiller (\!!bs#1\!!es)}}
-
-% \def\utfmathclassdefault #1#2{\ctxlua{
-% tex.sprint(mathematics.utfmathclass("#1","#2"))
-% }}
-%
-% \def\utfmathcommanddefault#1#2#3{\ctxlua{
-% local cmd = mathematics.utfmathcommand("#1","") or ""
-% if cmd == "" then
-% commands.cs("#2","#3")
-% else
-% commands.cs(cmd)
-% end}}
-
-% % %
-
-\def\@@mathlimopcomm #1{\mathop{#1}} %no \limits
-\def\@@mathnolopcomm #1{\mathop{#1}\nolimits}
-\def\@@mathboxcomm #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath}
-\def\@@mathchoicecomm#1{[todo #1]}
-
-\setnewconstant\mathordcode 0 \let\mathordcomm \mathord
-\setnewconstant\mathopcode 1 \let\mathopcomm \mathop
-\setnewconstant\mathbincode 2 \let\mathbincomm \mathbin
-\setnewconstant\mathrelcode 3 \let\mathrelcomm \mathrel
-\setnewconstant\mathopencode 4 \let\mathopencomm \mathopen
-\setnewconstant\mathclosecode 5 \let\mathclosecomm \mathclose
-\setnewconstant\mathpunctcode 6 \let\mathpunctcomm \mathpunct
-\setnewconstant\mathalphacode 7 \let\mathalphacomm \firstofoneargument
-\setnewconstant\mathinnercode 0 \let\mathinnercomm \mathinner
-\setnewconstant\mathnothingcode 0 \let\mathnothingcomm \firstofoneargument
-\setnewconstant\mathlimopcode 1 \let\mathlimopcomm \@@mathlimopcomm
-\setnewconstant\mathnolopcode 1 \let\mathnolopcomm \@@mathnolopcomm
-\setnewconstant\mathchoicecode 0 \let\mathchoicecomm \@@mathchoicecomm
-\setnewconstant\mathboxcode 0 \let\mathboxcomm \@@mathboxcomm
-
-\setnewconstant\mathaccentcode 8
-\setnewconstant\mathradicalcode 9
-
-\def\puremathcode#1{\the\csname math#1code\endcsname}
-\def\puremathcomm#1{\csname math#1comm\endcsname}
+\def\utfmathclass #1{\ctxcommand{utfmathclass (\!!bs#1\!!es)}}
+\def\utfmathstretch#1{\ctxcommand{utfmathstretch(\!!bs#1\!!es)}}
+\def\utfmathcommand#1{\ctxcommand{utfmathcommand(\!!bs#1\!!es)}}
+\def\utfmathfiller #1{\ctxcommand{utfmathfiller (\!!bs#1\!!es)}}
+
+%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}
+
+\let\mathnothing\firstofoneunexpanded
+\let\mathalpha \firstofoneunexpanded
+
+\setnewconstant\mathordcode \zerocount \letvalue{\??mathcodecommand ord}\mathord
+\setnewconstant\mathopcode \plusone \letvalue{\??mathcodecommand op}\mathop
+\setnewconstant\mathbincode \plustwo \letvalue{\??mathcodecommand bin}\mathbin
+\setnewconstant\mathrelcode \plusthree \letvalue{\??mathcodecommand rel}\mathrel
+\setnewconstant\mathopencode \plusfour \letvalue{\??mathcodecommand open}\mathopen
+\setnewconstant\mathclosecode \plusfive \letvalue{\??mathcodecommand close}\mathclose
+\setnewconstant\mathpunctcode \plussix \letvalue{\??mathcodecommand punct}\mathpunct
+\setnewconstant\mathalphacode \plusseven \letvalue{\??mathcodecommand alpha}\mathalpha
+\setnewconstant\mathinnercode \zerocount \letvalue{\??mathcodecommand inner}\mathinner
+\setnewconstant\mathnothingcode \zerocount \letvalue{\??mathcodecommand nothing}\mathnothing
+\setnewconstant\mathlimopcode \plusone \letvalue{\??mathcodecommand limop}\mathlimop
+\setnewconstant\mathnolopcode \plusone \letvalue{\??mathcodecommand nolop}\mathnolop
+\setnewconstant\mathboxcode \zerocount \letvalue{\??mathcodecommand box}\mathbox
+\setnewconstant\mathchoicecode \zerocount %letvalue{\??mathcodecommand choice}\mathnothing
+
+\setnewconstant\mathaccentcode \pluseight
+\setnewconstant\mathradicalcode \plusnine
+
+ \def\mathcodenumber #1{\the\csname math#1code\endcsname}
+\unexpanded\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname}
% \startlines
% $\mathopnolimits{\rm d}x$
% $\mathopnolimits{\kern\zeropoint \rm d}x$
-% $\puremathcomm{nolop}{\rm d}x$
-% $\puremathcomm{nolop}{\kern\zeropoint\rm d}x$
+% $\mathcodecommand{nolop}{\rm d}x$
+% $\mathcodecommand{nolop}{\kern\zeropoint\rm d}x$
% \blank
-% $\puremathcomm{nolop}{\mr d}x$
-% $\puremathcomm{nolop}{\kern\zeropoint\mr d}x$
+% $\mathcodecommand{nolop}{\mr d}x$
+% $\mathcodecommand{nolop}{\kern\zeropoint\mr d}x$
% $\mathop{\kern\zeropoint\mr d}x$
% $\mathopnolimits{\kern\zeropoint d}x$
% \stoplines
-
-% this will be sorted out:
-
-\let\mathcharacter \getvalue
-\let\textcharacter \getvalue
-\unexpanded\def\definefamilysynonym {\dotripleempty\dodefinefamilysynonym}
-\def\dodefinefamilysynonym [#1][#2][#3]{}
-\unexpanded\def\definemathsymbol {\dosixtupleempty\dodefinemathsymbol}
-\def\dodefinemathsymbol [#1][#2][#3][#4][#5][#6]{}
-\unexpanded\def\definemathcharacter {\dosixtupleempty\dodefinemathcharacter}
-\def\dodefinemathcharacter [#1][#2][#3][#4][#5][#6]{}
+
+\installcorenamespace{mathcommand}
\unexpanded\def\definemathcommand
- {\dotripleempty\dodefinemathcommand}
+ {\dotripleempty\math_define_command}
-\def\dodefinemathcommand[#1][#2][#3]#4% command class args meaning
+\def\math_define_command[#1][#2][#3]#4% command class args meaning
{\ifthirdargument
- \processaction
- [#3]
- [one=>\setuvalue{#1}##1{\puremathcomm{#2}{#4{##1}}},
- two=>\setuvalue{#1}##1##2{\puremathcomm{#2}{#4{##1}{##2}}}]%
+ \edef\nofmathcommandarguments{#3}%
+ \ifx\nofmathcommandarguments\v!one
+ \setuvalue{\??mathcommand#1}##1{\mathcodecommand{#2}{#4{##1}}}%
+ \else\ifx\nofmathcommandarguments\v!two
+ \setuvalue{\??mathcommand#1}##1##2{\mathcodecommand{#2}{#4{##1}{##2}}}%
+ \else
+ \setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}%
+ \fi\fi
\else\ifsecondargument
- \setuvalue{#1}{\puremathcomm{#2}{#4}}%
+ \setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}%
\else
- \setuvalue{#1}{\puremathcomm{nothing}{#4}}%
- \fi\fi}
+ \setuvalue{\??mathcommand#1}{\mathcodecommand{nothing}{#4}}%
+ \fi\fi
+ \letcsnamecsname\csname#1\endcsname\csname\??mathcommand#1\endcsname}
+
+\unexpanded\def\mathcommand#1%
+ {\csname\??mathcommand#1\endcsname}
%D Moved from font-ini.mkiv:
%D
@@ -252,27 +350,84 @@
{\normalmathop
\bgroup
\let\rm\mf
- \let\next=}
+ \let\nexttoken=}
+
+% this one too: \letvalue{\??mathcodecommand op}\mathop ?
-\def\normalmbox
+\unexpanded\def\normalmbox
{\normalhbox\bgroup\mf
- \dowithnextbox{\flushnextbox\egroup}\normalhbox}
+ \dowithnextboxcs\math_mbox_finish\normalhbox}
+
+\def\math_mbox_finish
+ {\flushnextbox
+ \egroup}
-\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible
+\unexpanded\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible
{\ifmmode\normalmbox\else\normalhbox\fi}
\unexpanded\def\enablembox
- {\appendtoks
- \ifx\normalhbox\undefined\let\normalhbox\hbox\fi
- \let\hbox\mbox
- \to\everymathematics}
+ {\appendtoks\math_enable_mbox\to \everymathematics}
+ {\everymathematics\expandafter{\the\everymathematics\math_enable_mbox}}
+
+\def\math_enable_mbox
+ {\ifdefined\normalhbox\else\let\normalhbox\hbox\fi % ?
+ \let\hbox\mbox}
+
+%D The next hack is needed needed for sine, cosine etc.
+
+\let\mathfunction\firstofoneunexpanded
+
+\let\math_tags_function \firstofoneunexpanded
+\let\math_tags_functionlabeltext\mathlabeltext
+
+\let\math_tags_mo\firstofoneunexpanded
+\let\math_tags_mi\firstofoneunexpanded
+
+\unexpanded\def\math_tags_mn#1{\begingroup\mr#1\endgroup}
+\unexpanded\def\math_tags_ms#1{\begingroup\mr#1\endgroup}
-%D needed for sin, cos etc
+\unexpanded\def\mfunction #1{{\mr\math_tags_function{#1}}}
+\unexpanded\def\mfunctionlabeltext#1{{\mr\math_tags_functionlabeltext{#1}}}
-\let\mathfunction\firstofoneargument
+% Once this is stable we can store the number at the tex end which is
+% faster. Functions getnumbers >= 1000.
+
+\expanded\def\math_tags_mathfunction_indeed #1{\ctxcommand{taggedmathfunction("#1",false,\ifconditional\c_apply_function true\else false\fi)}}
+\expanded\def\math_tags_mathfunctionlabeltext_indeed#1{\ctxcommand{taggedmathfunction("#1",true ,\ifconditional\c_apply_function true\else false\fi)}}
+
+\expanded\def\math_tags_mo_indeed#1{\begingroup \attribute\mathcategoryattribute\plusone #1\endgroup}
+\expanded\def\math_tags_mi_indeed#1{\begingroup \attribute\mathcategoryattribute\plustwo #1\endgroup}
+\expanded\def\math_tags_mn_indeed#1{\begingroup\mr\attribute\mathcategoryattribute\plusthree#1\endgroup}
+\expanded\def\math_tags_ms_indeed#1{\begingroup\mr\attribute\mathcategoryattribute\plusfour #1\endgroup}
+
+\newconditional\c_apply_function
+
+\unexpanded\def\math_tags_apply#1#2%
+ {\begingroup
+ \settrue\c_apply_function
+ #1%
+ \endgroup
+ \begingroup
+ % todo: auto ()
+ #2%
+ \endgroup}
+
+\appendtoks
+ \let\math_tags_function \math_tags_mathfunction_indeed
+ \let\math_tags_functionlabeltext\math_tags_mathfunctionlabeltext_indeed
+ \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
+\to \everyenableelements
-\def\mfunction #1{{\mr#1}}
-\def\mfunctionlabeltext#1{{\mr\mathlabeltext{#1}}}
+\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
+\to\everymathematics
% \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}}
% \def\mnolimitsfunction#1{\mathnolopcomm{{\mr#1}}
@@ -282,18 +437,18 @@
\def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
-\unexpanded\def\do@mathopnolimits #1{\mathop{\mscaledtext{#1}}\nolimits}
-\unexpanded\def\do@mfunction #1{\mscaledtext{#1}}
-\unexpanded\def\do@mfunctionlabeltext#1{\mscaledtext{\mathlabeltext{#1}}}
+\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}}}
-\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed)
+\unexpanded\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed)
{\doifsomething{#1}
{\def\currentmscaledstyle{#1}%
- \let\mathopnolimits \do@mathopnolimits
- \let\mfunction \do@mfunction
- \let\mfunctionlabeltext\do@mfunctionlabeltext}}
+ \let\mathopnolimits \math_function_style_opnolimits
+ \let\mfunction \math_function_style_mfunction
+ \let\mfunctionlabeltext\math_function_style_mfunctionlabeltext}}
-\def\mscaledtext#1%
+\unexpanded\def\mscaledtext#1%
{\mathchoice
{\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
{\hbox{\csname\currentmscaledstyle\endcsname\tf #1}}
@@ -327,7 +482,7 @@
%D Some goodies:
-\def\Angstrom{\nomathematics{\Aring}}
+\unexpanded\def\Angstrom{\nomathematics{\Aring}}
%D \macros
%D {nonknuthmode, donknuthmode}
@@ -362,7 +517,7 @@
\def\activatemathcharacters
{\the\activatedmathcharacters}
-\setnewconstant\primeasciicode 39 % '
+% \setnewconstant\primeasciicode 39 % '
\activatemathcharacter\circumflexasciicode
\activatemathcharacter\underscoreasciicode
@@ -382,33 +537,108 @@
% \let_\activemathunderscore
% \to \everymathematics
% \egroup
+
+% Here follows some plain legacy: primes.
%
-% plain tex legacy:
+% The \let\prime\math_prime_indeed might become an obsolete as we have
+% \doubleprime and \tripleprime and collapsing can nicely handle the
+% script then.
+%
+% Collapsing to 0x2033 and 0x2034 happens elsewhere.
-\bgroup
- \catcode\primeasciicode\activecatcode
- \doglobal\appendtoks
- \let'\domathprime
- \to \everymathematics
-\egroup
+% \switchtobodyfont[modern]
+% \switchtobodyfont[cambria]
+% \switchtobodyfont[xits]
+% \switchtobodyfont[minion]
+% \setupbodyfont[dejavu]
+%
+% \startbuffer
+% \def\SampleLine#1{%
+% \NC#1
+% \NC\switchtobodyfont[#1]$f^2$ % 1
+% \NC\switchtobodyfont[#1]$f\prime^2$ % 2
+% \NC\switchtobodyfont[#1]$f\prime\prime^2$ % 3
+% \NC\switchtobodyfont[#1]$f\prime\prime\prime^2$ % 4
+% \NC\switchtobodyfont[#1]$f{\prime}^2$ % 5
+% \NC\switchtobodyfont[#1]$f{\prime\prime}^2$ % 6
+% \NC\switchtobodyfont[#1]$f{\prime\prime\prime}^2$ % 7
+% \NC\switchtobodyfont[#1]$f'(x)$ % 8
+% \NC\switchtobodyfont[#1]$f''(x)$ % 9
+% \NC\switchtobodyfont[#1]$f'''(x)$ % 10
+% \NC\NR
+% }
+%
+% \starttabulate[|Tl|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|]
+% \NC\NC1\NC2\NC3\NC4\NC5\NC6\NC7\NC8\NC9\NC10\NC\NR
+% \SampleLine{modern}
+% \SampleLine{cambria}
+% \SampleLine{xits}
+% \SampleLine{minion}
+% \stoptabulate
+% \stopbuffer
+%
+% \typebuffer \getbuffer
-\newtoks\everydonknuthmode
-\newtoks\everynonknuthmode
+% most math fonts have messed up primes, just test this: $\prime^{\prime^{\prime}}$
-\newconditional \knuthmode
+{ \catcode\circumflexasciicode\othercatcode \global\let\othercircumflextoken ^ }
+{ \catcode\circumflexasciicode\superscriptcatcode \global\let\superscriptcircumflextoken^ }
-\def\nonknuthmode
- {\pushcatcodetable
- \setcatcodetable\ctxcatcodes
- \the\everynonknuthmode
- \let\nonknuthmode\relax
- \popcatcodetable}
+\ifdefined \prime \else
+ \Umathchardef\prime "0 "0 "2032
+\fi
-\def\donknuthmode
- {\pushcatcodetable
- \setcatcodetable\ctxcatcodes
- \the\everydonknuthmode
- \popcatcodetable}
+\let\math_prime_indeed_normal\prime
+
+\appendtoks
+ \let\math_prime_indeed_normal\prime % gets defined later
+ \let\mathfontprime\prime % for tracing
+ \let\prime\math_prime_indeed % so this is needed
+\to \everydump
+
+\unexpanded\def\math_prime_indeed
+ {\iffontchar\textfont\zerocount"FE325\relax
+ ^\bgroup
+ \expandafter\math_prime_indeed_virtual % virtual mess (using funny signal)
+ \else
+% \expandafter\math_prime_indeed_normal % gets collapsed
+ \expandafter\math_prime_indeed_crapped % gets collapsed
+ \fi}
+
+\def\math_prime_indeed_crapped
+ {{^{\math_prime_indeed_normal}}}
+
+\let\prime\math_prime_indeed
+
+\def\math_prime_indeed_virtual
+ {\math_prime_indeed_normal
+ \futurelet\nexttoken\math_prime_indeed_choice}
+
+\installcorenamespace{mathprime}
+
+\def\math_prime_indeed_choice
+ {\csname\??mathprime
+ \ifx '\nexttoken a\else
+ \ifx \math_prime_indeed_normal\nexttoken a\else
+ \ifx \prime\nexttoken a\else
+ \ifx\superscriptcircumflextoken\nexttoken b\else
+ \ifx\othercircumflextoken \nexttoken b\else
+ c\fi\fi\fi\fi\fi
+ \endcsname}
+
+\setvalue{\??mathprime a}#1{\math_prime_indeed_virtual}
+\setvalue{\??mathprime b}#1#2{#2\egroup}
+\setvalue{\??mathprime c}{\egroup}
+
+\let\activemathprime\math_prime_indeed
+
+\bgroup
+
+ \catcode\primeasciicode\activecatcode
+
+ \global\everymathematics\expandafter{\the\everymathematics\let'\math_prime_indeed} % todo: do this at the lua end
+
+\egroup
\bgroup
@@ -416,95 +646,146 @@
\catcode\circumflexasciicode\activecatcode
\catcode\ampersandasciicode \activecatcode
- \global \everynonknuthmode {\appendtoks
- \let_\normalsubscript
- \let^\normalsuperscript
- \let&\normalmathaligntab % use \def when it's \aligntab
- \to \everymathematics}
+ \doglobal \appendtoks
+ \let _\normalsubscript
+ \let ^\normalsuperscript
+ \let &\normalmathaligntab % use \def when it's \aligntab
+ \to \everymathematics
\egroup
-\appendtoks
- \setfalse\knuthmode
- \catcode\underscoreasciicode\othercatcode
- \catcode\circumflexasciicode\othercatcode
- \catcode\ampersandasciicode \othercatcode
-\to \everynonknuthmode
-
-\appendtoks
- \settrue\knuthmode
- \catcode\underscoreasciicode\subscriptcatcode
- \catcode\circumflexasciicode\superscriptcatcode
- \catcode\ampersandasciicode \alignmentcatcode
-\to \everydonknuthmode
+\newtoks\everydonknuthmode
+\newtoks\everynonknuthmode
-\appendtoks
- \startextendcatcodetable\ctxcatcodes
- \catcode\underscoreasciicode\othercatcode
- \catcode\circumflexasciicode\othercatcode
- \catcode\ampersandasciicode \othercatcode
- \stopextendcatcodetable
-\to \everynonknuthmode
+\newconditional \knuthmode
-\appendtoks
- \startextendcatcodetable\ctxcatcodes
- \catcode\underscoreasciicode\subscriptcatcode
- \catcode\circumflexasciicode\superscriptcatcode
- \catcode\ampersandasciicode \alignmentcatcode
- \stopextendcatcodetable
-\to \everydonknuthmode
+\let\nonknuthmode\relax
+\let\donknuthmode\relax
-% \def\prefermathcatcodes
-% {\catcode\underscoreasciicode\subscriptcatcode
-% \catcode\circumflexasciicode\superscriptcatcode
-% \catcode\ampersandasciicode \alignmentcatcode}
+% \def\nonknuthmode
+% {\pushcatcodetable
+% \setcatcodetable\ctxcatcodes
+% \the\everynonknuthmode
+% \let\nonknuthmode\relax
+% \popcatcodetable}
+%
+% \def\donknuthmode
+% {\pushcatcodetable
+% \setcatcodetable\ctxcatcodes
+% \the\everydonknuthmode
+% \popcatcodetable}
+%
+% \bgroup
+%
+% \catcode\underscoreasciicode\activecatcode
+% \catcode\circumflexasciicode\activecatcode
+% \catcode\ampersandasciicode \activecatcode
+%
+% \global \everynonknuthmode {\appendtoks
+% \let_\normalsubscript
+% \let^\normalsuperscript
+% \let&\normalmathaligntab % use \def when it's \aligntab
+% \to \everymathematics}
+%
+% \egroup
+%
+% \appendtoks
+% \setfalse\knuthmode
+% \catcode\underscoreasciicode\othercatcode
+% \catcode\circumflexasciicode\othercatcode
+% \catcode\ampersandasciicode \othercatcode
+% \to \everynonknuthmode
+%
+% \appendtoks
+% \settrue\knuthmode
+% \catcode\underscoreasciicode\subscriptcatcode
+% \catcode\circumflexasciicode\superscriptcatcode
+% \catcode\ampersandasciicode \alignmentcatcode
+% \to \everydonknuthmode
+%
+% \appendtoks
+% \startextendcatcodetable\ctxcatcodes
+% \catcode\underscoreasciicode\othercatcode
+% \catcode\circumflexasciicode\othercatcode
+% \catcode\ampersandasciicode \othercatcode
+% \stopextendcatcodetable
+% \to \everynonknuthmode
+%
+% \appendtoks
+% \startextendcatcodetable\ctxcatcodes
+% \catcode\underscoreasciicode\subscriptcatcode
+% \catcode\circumflexasciicode\superscriptcatcode
+% \catcode\ampersandasciicode \alignmentcatcode
+% \stopextendcatcodetable
+% \to \everydonknuthmode
+
+%D Even more drastic (this code will move as nonknuthmode is default now)
+
+% \unexpanded\def\enableasciimode
+% {\ctxlua{resolvers.macros.enablecomment()}%
+% \glet\enableasciimode\relax}
+%
+% \unexpanded\def\asciimode
+% {\catcodetable\txtcatcodes
+% \enableasciimode
+% \nonknuthmode}
+%
+% \unexpanded\def\startasciimode
+% {\pushcatcodetable
+% \catcodetable\txtcatcodes
+% \enableasciimode
+% \nonknuthmode}
+%
+% \unexpanded\def\stopasciimode
+% {\popcatcodetable
+% \ifconditional\knuthmode\else\donknuthmode\fi}
-%D Even more drastic:
+\unexpanded\def\enableasciimode
+ {\ctxlua{resolvers.macros.enablecomment()}%
+ \glet\enableasciimode\relax}
\unexpanded\def\asciimode
{\catcodetable\txtcatcodes
- \nonknuthmode}
+ \enableasciimode}
\unexpanded\def\startasciimode
{\pushcatcodetable
\catcodetable\txtcatcodes
- \nonknuthmode}
+ \enableasciimode}
\unexpanded\def\stopasciimode
- {\popcatcodetable
- \ifconditional\knuthmode\else\donknuthmode\fi}
+ {\popcatcodetable}
%D Needed for unicode:
\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}}
-%D \macros
-%D {setupmathematics}
-%D
-%D Configuration for integrals. (If needed we can speed this up and make it
-%D installable; no processaction is needed then).
-
-\newtoks\everysetupmathematics
+%D Memory saver:
-\unexpanded\def\setupmathematics
- {\dosingleargument\dosetupmathematics}
+\appendtoks
+ \ifx\currentmathematics\empty
+ \doifelse{\mathematicsparameter\c!compact}\v!yes\enabledirectives\disabledirectives[math.virtual.optional]%
+ \fi
+\to \everysetupmathematics
-\def\dosetupmathematics[#1]%
- {\getparameters[\??mo][#1]%
- \the\everysetupmathematics}
+\setupmathematics
+ [\c!compact=no]
-\def\mathematicsparameter#1{\ifcsname\??mo#1\endcsname\csname\??mo#1\endcsname\fi}
+%D Arabic:
-%D Memory saver:
+\newconditional\c_math_right_to_left
\appendtoks
- \doifelse{\mathematicsparameter\v!compact}\v!yes
- {\ctxlua{fonts.handlers.vf.math.optional=true}}
- {\ctxlua{fonts.handlers.vf.math.optional=false}}%
-\to \everysetupmathematics
+ \doifelse{\mathematicsparameter\c!align}{r2l}\settrue\setfalse\c_math_right_to_left
+\to \everyswitchmathematics
-\setupmathematics
- [\v!compact=no]
+\unexpanded\def\math_basics_synchronize_direction
+ {\mathdir T\ifconditional\c_math_right_to_left R\else L\fi T}
+
+\appendtoks
+ \math_basics_synchronize_direction
+%to \everymathematics % comes too late and I'm not in the mood for a mixed mode kludge now
+\to \everyswitchmathematics
%D Delayed: greek.
%D
@@ -517,25 +798,86 @@
% [lc uc] normal (upright) = 2, italic = 3, none = 0/1
-\setevalue{\??mo:greek:\v!normal :\v!normal}{\attribute\mathgreekattribute22 }
-\setevalue{\??mo:greek:\v!normal :\v!italic}{\attribute\mathgreekattribute23 }
-\setevalue{\??mo:greek:\v!normal :\v!none }{\attribute\mathgreekattribute21 }
+% We can move the setting to the lua end and use abstract numbers instead
+% if funny ones here.
+
+\installcorenamespace{mathgreek}
-\setevalue{\??mo:greek:\v!italic :\v!normal}{\attribute\mathgreekattribute32 }
-\setevalue{\??mo:greek:\v!italic :\v!italic}{\attribute\mathgreekattribute33 }
-\setevalue{\??mo:greek:\v!italic :\v!none }{\attribute\mathgreekattribute31 }
+\newconstant\c_math_greek_attribute
-\setevalue{\??mo:greek:\v!none :\v!normal}{\attribute\mathgreekattribute12 }
-\setevalue{\??mo:greek:\v!none :\v!italic}{\attribute\mathgreekattribute13 }
-\setevalue{\??mo:greek:\v!none :\v!none }{\attribute\mathgreekattribute\attributeunsetvalue}
+\setvalue{\??mathgreek\v!normal :\v!normal}{22}
+\setvalue{\??mathgreek\v!normal :\v!italic}{23}
+\setvalue{\??mathgreek\v!normal :\v!none }{21}
+
+\setvalue{\??mathgreek\v!italic :\v!normal}{32}
+\setvalue{\??mathgreek\v!italic :\v!italic}{33}
+\setvalue{\??mathgreek\v!italic :\v!none }{31}
+
+\setvalue{\??mathgreek\v!none :\v!normal}{12}
+\setvalue{\??mathgreek\v!none :\v!italic}{13}
+\letvalue{\??mathgreek\v!none :\v!none }\attributeunsetvalue
+
+\appendtoks
+ \edef\p_lcgreek_ucgreek{\mathematicsparameter\s!lcgreek:\mathematicsparameter\s!ucgreek}%
+ \c_math_greek_attribute\csname\??mathgreek
+ \ifcsname\??mathgreek\p_lcgreek_ucgreek\endcsname\p_lcgreek_ucgreek\else\v!none\fi
+ \endcsname\relax
+\to \everyswitchmathematics
+
+\appendtoks
+ \attribute\mathgreekattribute\c_math_greek_attribute
+\to \everymathematics
+
+\setupmathematics
+ [\s!lcgreek=\v!italic,
+ \s!ucgreek=\v!normal] % was: none
+
+%D Math italics (experiment)
+
+% we need keys
+
+\installcorenamespace{mathitalics}
+
+\setnewconstant\c_math_italics_attribute\attributeunsetvalue
+
+\letvalue{\??mathitalics 1}\plusone % fontitalics
+\letvalue{\??mathitalics 2}\plustwo % fontdata
+\letvalue{\??mathitalics 3}\plusthree % quad based
+\letvalue{\??mathitalics 4}\plusfour % combination of 1 and 3
+\letvalue{\??mathitalics\v!none}\attributeunsetvalue
+
+\def\math_italics_initialize
+ {\ifnum\c_math_italics_attribute=\attributeunsetvalue \else
+ \ctxcommand{setmathitalics()}% one time
+ \global\let\math_italics_initialize\relax
+ \fi}
\appendtoks
- \csname\??mo:greek:\@@molcgreek:\@@moucgreek\endcsname
+ \edef\p_italics{\mathematicsparameter\s!italics}%
+ \c_math_italics_attribute\csname\??mathitalics
+ \ifcsname\??mathitalics\p_italics\endcsname\p_italics\else\v!none\fi
+ \endcsname\relax
+ \math_italics_initialize
+\to \everyswitchmathematics % only in mathematics
+
+\appendtoks
+ \attribute\mathitalicsattribute\c_math_italics_attribute
\to \everymathematics
\setupmathematics
- [lcgreek=\v!italic,
- ucgreek=\v!normal] % was: none
+ [\s!italics=]
+
+% looks nicer but can generate bogus csnames
+%
+% \setvalue{\??mathitalics1}{\math_italics_initialize\c_math_italics_attribute\plusone } % fontitalics
+% \setvalue{\??mathitalics2}{\math_italics_initialize\c_math_italics_attribute\plustwo } % fontdata
+% \setvalue{\??mathitalics3}{\math_italics_initialize\c_math_italics_attribute\plusthree} % quad based
+% \setvalue{\??mathitalics4}{\math_italics_initialize\c_math_italics_attribute\plusfour } % combination of 1 and 3
+%
+% \appendtoks
+% \c_math_italics_attribute\attributeunsetvalue
+% \csname\??mathitalics\mathematicsparameter\s!italics\endcsname
+% \to \everyswitchmathematics % only in mathematics
%D \macros
%D {enablemathpunctuation,disablemathpunctuation}
@@ -548,16 +890,14 @@
%D
%D \blank{\getbuffer}\blank
-\setfalse \automathpunctuation
-
-\def\enablemathpunctuation {\settrue \automathpunctuation}
-\def\disablemathpunctuation{\setfalse\automathpunctuation}
+\newconditional\automathpunctuation
-\ifx\v!autopunctuation\undefined \def\v!autopunctuation{autopunctuation} \fi
+\unexpanded\def\enablemathpunctuation {\settrue \automathpunctuation}
+\unexpanded\def\disablemathpunctuation{\setfalse\automathpunctuation}
\appendtoks
- \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\enablemathpunctuation\disablemathpunctuation
-\to \everysetupmathematics
+ \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\settrue\setfalse\automathpunctuation
+\to \everyswitchmathematics
\appendtoks
\ifconditional\automathpunctuation\attribute\mathpunctuationattribute\plusone\fi
@@ -565,7 +905,7 @@
\setupmathematics
[\v!autopunctuation=\v!no]
-
+
%D \macros
%D {mathstyle}
%D
@@ -630,14 +970,6 @@
% error
\fi}
-\def\cramped#1%
- {{\ifcase\normalmathstyle
- \crampeddisplaystyle \or \or % 0 -> 1
- \crampedtextstyle \or \or % 2 -> 3
- \crampedscriptstyle \or \or % 4 -> 5
- \crampedscriptscriptstyle \fi % 6 -> 7
- #1}}
-
\def\mathstylefont#1% #1 is number (\normalmathstyle)
{\ifcase#1\relax
\textfont \or
@@ -651,22 +983,59 @@
\textfont
\fi\zerocount}
+%D A plain inheritance:
+
+\def\mathpalette#1#2%
+ {\mathchoice
+ {#1\displaystyle {#2}}%
+ {#1\textstyle {#2}}%
+ {#1\scriptstyle {#2}}%
+ {#1\scriptscriptstyle{#2}}}
+
+%D Often we can use:
+%D
+%D \startbuffer
+%D $x^{\mathstylehbox{x^{\mathstylehbox{x}}}}$
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\unexpanded\def\mathstylehbox#1%
+ {\normalexpanded{\hbox\bgroup
+ $\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1$\egroup}
+
+\unexpanded\def\mathstylevbox#1%
+ {\normalexpanded{\vbox\bgroup
+ $\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1$\egroup}
+
+\unexpanded\def\mathstylevcenter#1%
+ {\normalexpanded{\vcenter\bgroup
+ $\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1$\egroup}
+
+\unexpanded\def\mathstylevcenteredhbox#1%
+ {\normalexpanded{\vcenter\bgroup\hbox\bgroup
+ $\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1$\egroup\egroup}
+
+\unexpanded\def\mathstylevcenteredvbox#1%
+ {\normalexpanded{\vcenter\bgroup\vbox\bgroup
+ $\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1$\egroup\egroup}
+
%D Something similar can be used in the (re|)|definition
%D of \type {\text}. This version is a variation on the one
%D in the math module (see \type{m-math} and|/|or \type
%D {m-newmat}).
\unexpanded\def\mathtext
- {\mathortext\domathtext\hbox}
+ {\mathortext\math_text_choice\hbox}
-\def\domathtext#1%
+\def\math_text_choice#1%
{\mathchoice
- {\dodomathtext\displaystyle\textface {#1}}%
- {\dodomathtext\textstyle \textface {#1}}%
- {\dodomathtext\textstyle \scriptface {#1}}%
- {\dodomathtext\textstyle \scriptscriptface{#1}}}
+ {\math_text_choice_indeed\displaystyle\textface {#1}}%
+ {\math_text_choice_indeed\textstyle \textface {#1}}%
+ {\math_text_choice_indeed\textstyle \scriptface {#1}}%
+ {\math_text_choice_indeed\textstyle \scriptscriptface{#1}}}
-\def\dodomathtext#1#2#3% no \everymath !
+\def\math_text_choice_indeed#1#2#3% no \everymath !
%{\hbox{\everymath{#1}\switchtobodyfont [#2]#3}} % 15 sec
{\hbox{\everymath{#1}\setcurrentfontbody{#2}#3}} % 3 sec (no math)
@@ -681,36 +1050,57 @@
\appendtoks \let\text\mathtext \to \everymathematics
-%D The next code is derived from plain \TEX.
+%D The next code is derived from plain \TEX. The names will change!
-\newcount\interdisplaylinepenalty \interdisplaylinepenalty=100
+\newcount\interdisplaylinepenalty \interdisplaylinepenalty\plushundred
-\newif\ifdt@p
+% Actually, not using an if saves one macro so there is no penalty
+% for splitting up this macro.
+%
+% \newif\ifdt@p
+%
+% \def\displ@y
+% {\global\dt@ptrue
+% \openup\displayopenupvalue % was \openup\jot
+% \everycr
+% {\noalign
+% {\ifdt@p
+% \global\dt@pfalse
+% \ifdim\prevdepth>-\thousandpoint
+% \vskip-\lineskiplimit
+% \vskip\normallineskiplimit
+% \fi
+% \else
+% \penalty\interdisplaylinepenalty
+% \fi}}}
+
+\newtoks\mathdisplayaligntweaks
+
+\appendtoks
+ \resetdisplaymatheq % moved to here
+\to \mathdisplayaligntweaks
-\def\displ@y
- {\global\dt@ptrue
+\unexpanded\def\math_display_align_hack % I don't like the global, maybe we should push and pop
+ {\global\let\math_display_align_hack_indeed\math_display_align_hack_remove_skip
\openup\displayopenupvalue % was \openup\jot
- \everycr
- {\noalign
- {\ifdt@p
- \global\dt@pfalse
- \ifdim\prevdepth>-\thousandpoint
- \vskip-\lineskiplimit
- \vskip\normallineskiplimit
- \fi
- \else
- \penalty\interdisplaylinepenalty
- \fi}}}
+ \everycr{\noalign{\math_display_align_hack_indeed}}}
-\let\normaldispl@y\displ@y
+\def\math_display_align_hack_remove_skip
+ {\ifdim\prevdepth>-\thousandpoint
+ \vskip\dimexpr-\lineskiplimit+\normallineskiplimit\relax
+ \fi
+ \global\let\math_display_align_hack_indeed\math_display_align_hack_insert_penalty}
-\def\displ@y{\resetdisplaymatheq\normaldispl@y}
+\def\math_display_align_hack_insert_penalty
+ {\penalty\interdisplaylinepenalty}
-\def\m@th{\mathsurround\zeropoint} % obsolete
+\appendtoks
+ \math_display_align_hack
+\to \mathdisplayaligntweaks
%D Text in math:
-\def\mathortext
+\unexpanded\def\mathortext
{\ifmmode
\expandafter\firstoftwoarguments
\else
@@ -721,14 +1111,12 @@
% force text mode, will be overloaded later
-\ifx\text\undefined \let\text\hbox \fi
+\ifdefined\text\else \let\text\hbox \fi
-\def\mathoptext#1{\mathop{\text{#1}}}
+\unexpanded\def\mathoptext#1{\mathop{\text{#1}}}
% for a while:
-\ifnum\luatexversion>65
- \def\Umathbotaccent{\Umathaccent bottom }
-\fi
+\def\Umathbotaccent{\Umathaccent bottom }
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/math-inl.mkiv b/Master/texmf-dist/tex/context/base/math-inl.mkiv
index 89de0242b09..2c7284458a5 100644
--- a/Master/texmf-dist/tex/context/base/math-inl.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-inl.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Inline,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -15,12 +15,8 @@
\unprotect
-% Obsolete, as we do snapping differently now.
-
-\def\snappedinlineformula {\dosingleempty\dosnappedinlineformula}
-\def\dosnappedinlineformula[#1]#2{\mathematics{#2}}
-\let\tform \mathematics
-\let\gform \snappedinlineformula
-\let\enableautomath \relax
+% The \MKII\ math grid snapping code has gone. A pity as it was rather effective
+% and worked quite well (for a couple of projects where it was demanded). Other code
+% might show up / move here.
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/math-int.mkiv b/Master/texmf-dist/tex/context/base/math-int.mkiv
index a99142a0423..84c51cb2477 100644
--- a/Master/texmf-dist/tex/context/base/math-int.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-int.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Scripts,
%D author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -16,14 +16,15 @@
\unprotect
%D \startbuffer
-%D $\int_a^b f(x) dx$ and also
-%D $\iint_a^b f(x,y) dxdy$, $\iiint_a^b f(x,y) dxdy$,
-%D $\iiiint_a^b f(x) dx$
+%D $\int _a^b f(x) dx $ and also
+%D $\iint _a^b f(x,y) dxdy$,
+%D $\iiint _a^b f(x,y) dxdy$,
+%D $\iiiint _a^b f(x) dx $.
%D \startformula
-%D \int_a^b f(x) dx \quad
-%D \iint_a^b f(x) dx \quad
-%D \iiint_a^b f(x) dx \quad
-%D \iiiint_a^b f(x) dx \quad
+%D \int _a^b f(x) dx \quad
+%D \iint _a^b f(x) dx \quad
+%D \iiint _a^b f(x) dx \quad
+%D \iiiint _a^b f(x) dx \quad
%D \stopformula
%D \stopbuffer
%D
@@ -33,81 +34,97 @@
%D
%D Limits: \setupmathematics[integral=limits] \getbuffer
+%D Adapted to mkiv by HH from code by AM.
+
+\installcorenamespace{mathintegral}
+
\newconstant\mathintlimitmode % 0 nolimits 1 displaylimits 2 limits
-\def\intlimits
- {\ifcase\mathintlimitmode \nolimits \or \displaylimits \or \limits \fi}
+\def\intlimits % also used elsewhere
+ {\ifcase\mathintlimitmode
+ \nolimits
+ \or
+ \displaylimits
+ \or
+ \limits
+ \fi}
-\ifx\v!integral\undefined \def\v!integral{integral} \fi
+\letvalue{\??mathintegral nolimits}\zerocount
+\letvalue{\??mathintegral displaylimits}\plusone
+\letvalue{\??mathintegral limits}\plustwo
\appendtoks
- \processaction
- [\mathematicsparameter\v!integral]
- [ nolimits=>\mathintlimitmode\zerocount,
- displaylimits=>\mathintlimitmode\plusone,
- limits=>\mathintlimitmode\plustwo]%
-\to \everysetupmathematics
+ \mathintlimitmode\executeifdefined{\??mathintegral\mathematicsparameter\s!integral}\zerocount
+\to \everyswitchmathematics
\setupmathematics
[\v!integral=nolimits]
-%D More integrals (AM):
-
-%def\integralrepeatsymbol{\intop}
-\def\integralrepeatsymbol{{\int}}
-
-% \def\repeatintegral#1%
-% {\scratchtoks\emptytoks
-% \let\dointlimits\donothing
-% \let\dodointlimits\intlimits
-% \dorecurse{#1}{\appendtoks \integralrepeatsymbol \dointkern \to \scratchtoks}%
-% \appendtoks \intop \dointlimits \dodointlimits \to \scratchtoks
-% \edef\dodorepeatintegral{\the\scratchtoks}%
-% \futurelet\next\dorepeatintegral}
-
-% \definemathcommand [iint] {\repeatintegral\plusone }
-% \definemathcommand [iiint] {\repeatintegral\plustwo }
-% \definemathcommand [iiiint] {\repeatintegral\plusthree}
-
-\def\fakerepeatintegral#1%
- {\scratchtoks\emptytoks
- \dorecurse{#1}{\appendtoks \integralrepeatsymbol \dointkern \to \scratchtoks}%
- \appendtoks \intop \dointlimits \dodointlimits \to \scratchtoks
- \edef\dodorepeatintegral{\the\scratchtoks}}
-
-\def\repeatintegral#1#2#3%
- {\let\dointlimits\donothing
- \let\dodointlimits\intlimits
+%D The following code is used for fallbacks and might become obsolete once
+%D we have enough \OPENTYPE\ math fonts.
+
+\def\math_repeated_integal_i
+ {\int}
+
+\def\math_repeated_integal_ii
+ {\math_repeated_integal_i
+ \math_repeated_integral_kern
+ \math_repeated_integal_i
+ \math_repeat_integral_finish
+ \intlimits}
+
+\def\math_repeated_integal_iii
+ {\math_repeated_integal_i
+ \math_repeated_integral_kern
+ \math_repeated_integal_ii}
+
+\def\math_repeated_integal_iiii
+ {\math_repeated_integal_i
+ \math_repeated_integral_kern
+ \math_repeated_integal_iii}
+
+\unexpanded\def\math_repeat_integral#1%
+ {\let\math_repeat_integral_finish\donothing
\iffontchar\textfont\zerocount#1\relax
- %\edef\dodorepeatintegral{\utfchar{#1}}%
- \let\dodorepeatintegral#2%
+ \expandafter\math_repeat_integral_real
\else
- \fakerepeatintegral{#3}%
- \fi
- \futurelet\next\dorepeatintegral}
+ \expandafter\math_repeat_integral_fake
+ \fi}
-% This is a temporary solution, as we will make a virtual glyph in lm.
+\def\math_repeat_integral_fake#1#2%
+ {\let\math_repeat_integral_fake_symbol#2%
+ \futurelet\next\math_repeat_integral_fake_indeed}
-\definemathcommand [iint] {\repeatintegral{"222B}\normaliint \plusone }
-\definemathcommand [iiint] {\repeatintegral{"222C}\normaliiint \plustwo }
-\definemathcommand [iiiint] {\repeatintegral{"222D}\normaliiiint\plusthree}
+\def\math_repeat_integral_real#1#2%
+ {#1}
-%D If the \type{\limits} option is used after \type{\iint}, use
-%D \type{\mathop} and fudge the left hand space a bit to make the
-%D subscript visually centered.
+\definemathcommand [iint] {\math_repeat_integral{"0222C}\normalint \math_repeated_integal_ii } % double
+\definemathcommand [iiint] {\math_repeat_integral{"0222D}\normaliint \math_repeated_integal_iii } % tripple
+\definemathcommand [iiiint] {\math_repeat_integral{"FFFFF}\normaliiint\math_repeated_integal_iiii} % quadruple
-\def\dointkern
+\def\math_repeated_integral_kern
{\mkern-6mu\mathchoice{\mkern-3mu}{}{}{}}
-\def\dorepeatintegral
- {\ifx\next\limits \dointlimitcorrection \else
- \ifx\next\displaylimits \dointlimitcorrection \else
- \ifx\next\nolimits \donothing \else
- \ifcase\mathintlimitmode\else \dointlimitcorrection \fi\fi\fi\fi
- \dodorepeatintegral}
-
-\def\dointlimitcorrection
+\def\math_repeat_integral_fake_indeed
+ {\ifx\next\limits
+ \math_repeated_integral_correction
+ \else\ifx\next\displaylimits
+ \math_repeated_integral_correction
+ \else\ifx\next\nolimits
+ % nothing
+ \else\ifcase\mathintlimitmode
+ % nothing
+ \else
+ \math_repeated_integral_correction
+ \fi\fi\fi\fi
+ \math_repeat_integral_fake_symbol}
+
+\def\math_repeated_integral_correction
{\mkern-7mu\mathchoice{\mkern-2mu}{}{}{}%
- \mathop\bgroup\mkern7mu\mathchoice{\mkern2mu}{}{}{}\let\dointlimits\egroup}
+ \mathop\bgroup\mkern7mu\mathchoice{\mkern2mu}{}{}{}\let\math_repeat_integral_finish\egroup}
+
+%D If the \type{\limits} option is used after \type {\iint}, use \type
+%D {\mathop} and fudge the left hand space a bit to make the subscript
+%D visually centered.
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/math-lan.mkiv b/Master/texmf-dist/tex/context/base/math-lan.mkiv
deleted file mode 100644
index 1d313257885..00000000000
--- a/Master/texmf-dist/tex/context/base/math-lan.mkiv
+++ /dev/null
@@ -1,67 +0,0 @@
-%D \module
-%D [ file=math-lan,
-%D version=2009.03.10,
-%D title=\CONTEXT\ Math Macros,
-%D subtitle=Language Support,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright=PRAGMA]
-%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 / Language Support}
-
-\unprotect
-
-\setupmathlabeltext [\s!en] [arccos=arccos]
-\setupmathlabeltext [\s!en] [arcsin=arcsin]
-\setupmathlabeltext [\s!en] [arctan=arctan]
-\setupmathlabeltext [\s!en] [arg=arg]
-\setupmathlabeltext [\s!en] [cosh=cosh]
-\setupmathlabeltext [\s!en] [cos=cos]
-\setupmathlabeltext [\s!en] [coth=coth]
-\setupmathlabeltext [\s!en] [cot=cot]
-\setupmathlabeltext [\s!en] [csc=csc]
-\setupmathlabeltext [\s!en] [deg=deg]
-\setupmathlabeltext [\s!en] [det=det]
-\setupmathlabeltext [\s!en] [dim=dim]
-\setupmathlabeltext [\s!en] [exp=exp]
-\setupmathlabeltext [\s!en] [gcd=gcd]
-\setupmathlabeltext [\s!en] [hom=hom]
-\setupmathlabeltext [\s!en] [inf=inf]
-\setupmathlabeltext [\s!en] [injlim=inj\,lim]
-\setupmathlabeltext [\s!en] [ker=ker]
-\setupmathlabeltext [\s!en] [lg=lg]
-\setupmathlabeltext [\s!en] [liminf=lim\,inf]
-\setupmathlabeltext [\s!en] [limsup=lim\,sup]
-\setupmathlabeltext [\s!en] [lim=lim]
-\setupmathlabeltext [\s!en] [ln=ln]
-\setupmathlabeltext [\s!en] [log=log]
-\setupmathlabeltext [\s!en] [median=median]
-\setupmathlabeltext [\s!en] [max=max]
-\setupmathlabeltext [\s!en] [min=min]
-\setupmathlabeltext [\s!en] [mod=mod]
-\setupmathlabeltext [\s!en] [projlim=proj\,lim]
-\setupmathlabeltext [\s!en] [Pr=Pr]
-\setupmathlabeltext [\s!en] [sec=sec]
-\setupmathlabeltext [\s!en] [sinh=sinh]
-\setupmathlabeltext [\s!en] [sin=sin]
-\setupmathlabeltext [\s!en] [sup=sup]
-\setupmathlabeltext [\s!en] [tanh=tanh]
-\setupmathlabeltext [\s!en] [tan=tan]
-
-\setupmathlabeltext [\s!pl] [tg=tg]
-\setupmathlabeltext [\s!pl] [cot=ctg]
-\setupmathlabeltext [\s!pl] [ctg=ctg]
-\setupmathlabeltext [\s!pl] [arcsin=arc\,sin]
-\setupmathlabeltext [\s!pl] [arccos=arc\,cos]
-\setupmathlabeltext [\s!pl] [arctan=arc\,tg]
-\setupmathlabeltext [\s!pl] [arctg=arc\,tg]
-\setupmathlabeltext [\s!pl] [arcctg=arc\,ctg]
-
-\setupmathlabeltext [\s!nl] [gcd=ggd]
-\setupmathlabeltext [\s!nl] [lcm=kgv]
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/math-lbr.mkii b/Master/texmf-dist/tex/context/base/math-lbr.mkii
index 6392c762e56..0aa1df66514 100644
--- a/Master/texmf-dist/tex/context/base/math-lbr.mkii
+++ b/Master/texmf-dist/tex/context/base/math-lbr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Lucida Specials,
%D author={Hans Hagen \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-map.lua b/Master/texmf-dist/tex/context/base/math-map.lua
index b6d57bff531..cd16736110b 100644
--- a/Master/texmf-dist/tex/context/base/math-map.lua
+++ b/Master/texmf-dist/tex/context/base/math-map.lua
@@ -19,12 +19,23 @@ if not modules then modules = { } end modules ['math-map'] = {
-- todo: alphabets namespace
-- maybe: script/scriptscript dynamic,
+-- to be looked into once the fonts are ready (will become font
+-- goodie):
+--
+-- (U+2202,U+1D715) : upright
+-- (U+2202,U+1D715) : italic
+-- (U+2202,U+1D715) : upright
+--
+-- plus add them to the regular vectors below so that they honor \it etc
+
local type, next = type, next
local floor, div = math.floor, math.div
+local merged = table.merged
-local allocate = utilities.storage.allocate
-
-local texattribute = tex.attribute
+local allocate = utilities.storage.allocate
+local texattribute = tex.attribute
+local otffeatures = fonts.constructors.newfeatures("otf")
+local registerotffeature = otffeatures.register
local trace_greek = false trackers.register("math.greek", function(v) trace_greek = v end)
@@ -33,250 +44,421 @@ local report_remapping = logs.reporter("mathematics","remapping")
mathematics = mathematics or { }
local mathematics = mathematics
+-- Unfortunately some alphabets have gaps (thereby troubling all applications that
+-- need to deal with math). Somewhat strange considering all those weird symbols that
+-- were added afterwards. The following trickery (and data) is only to be used for
+-- diagnostics and quick and dirty alphabet tracing (s-mat-10.mkiv) as we deal with
+-- it otherwise.
+
+mathematics.gaps = {
+ [0x1D455] = 0x0210E, -- H
+ [0x1D49D] = 0x0212C, -- script B
+ [0x1D4A0] = 0x02130, -- script E
+ [0x1D4A1] = 0x02131, -- script F
+ [0x1D4A3] = 0x0210B, -- script H
+ [0x1D4A4] = 0x02110, -- script I
+ [0x1D4A7] = 0x02112, -- script L
+ [0x1D4A8] = 0x02133, -- script M
+ [0x1D4AD] = 0x0211B, -- script R
+ [0x1D4BA] = 0x0212F, -- script e
+ [0x1D4BC] = 0x0210A, -- script g
+ [0x1D4C4] = 0x02134, -- script o
+ [0x1D506] = 0x0212D, -- fraktur C
+ [0x1D50B] = 0x0210C, -- fraktur H
+ [0x1D50C] = 0x02111, -- fraktur I
+ [0x1D515] = 0x0211C, -- fraktur R
+ [0x1D51D] = 0x02128, -- fraktur Z
+ [0x1D53A] = 0x02102, -- bb C
+ [0x1D53F] = 0x0210D, -- bb H
+ [0x1D545] = 0x02115, -- bb N
+ [0x1D547] = 0x02119, -- bb P
+ [0x1D548] = 0x0211A, -- bb Q
+ [0x1D549] = 0x0211D, -- bb R
+ [0x1D551] = 0x02124, -- bb Z
+}
+
+local function fillinmathgaps(tfmdata,key,value)
+ local mathgaps = mathematics.gaps
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ for gap, original in next, mathgaps do
+ if characters[original] and not characters[gap] then
+ characters [gap] = characters [original]
+ descriptions[gap] = descriptions[original]
+ end
+ end
+end
+
+registerotffeature {
+ name = "mathgaps",
+ description = "plug gaps in math alphabets",
+ comment = "regular document sources should not depend on this",
+ manipulators = {
+ base = fillinmathgaps,
+ node = fillinmathgaps,
+ }
+}
+
-- we could use one level less and have tf etc be tables directly but the
-- following approach permits easier remapping of a-a, A-Z and 0-9 to
-- fallbacks; symbols is currently mostly greek
-local alphabets = allocate {
- regular = {
- tf = {
- digits = 0x00030,
- ucletters = 0x00041,
- lcletters = 0x00061,
- ucgreek = {
- [0x0391]=0x0391, [0x0392]=0x0392, [0x0393]=0x0393, [0x0394]=0x0394, [0x0395]=0x0395,
- [0x0396]=0x0396, [0x0397]=0x0397, [0x0398]=0x0398, [0x0399]=0x0399, [0x039A]=0x039A,
- [0x039B]=0x039B, [0x039C]=0x039C, [0x039D]=0x039D, [0x039E]=0x039E, [0x039F]=0x039F,
- [0x03A0]=0x03A0, [0x03A1]=0x03A1, [0x03A3]=0x03A3, [0x03A4]=0x03A4, [0x03A5]=0x03A5,
- [0x03A6]=0x03A6, [0x03A7]=0x03A7, [0x03A8]=0x03A8, [0x03A9]=0x03A9,
- },
- lcgreek = {
- [0x03B1]=0x03B1, [0x03B2]=0x03B2, [0x03B3]=0x03B3, [0x03B4]=0x03B4, [0x03B5]=0x03B5,
- [0x03B6]=0x03B6, [0x03B7]=0x03B7, [0x03B8]=0x03B8, [0x03B9]=0x03B9, [0x03BA]=0x03BA,
- [0x03BB]=0x03BB, [0x03BC]=0x03BC, [0x03BD]=0x03BD, [0x03BE]=0x03BE, [0x03BF]=0x03BF,
- [0x03C0]=0x03C0, [0x03C1]=0x03C1, [0x03C2]=0x03C2, [0x03C3]=0x03C3, [0x03C4]=0x03C4,
- [0x03C5]=0x03C5, [0x03C6]=0x03C6, [0x03C7]=0x03C7, [0x03C8]=0x03C8, [0x03C9]=0x03C9,
- [0x03D1]=0x03D1, [0x03D5]=0x03D5, [0x03D6]=0x03D6, [0x03F0]=0x03F0, [0x03F1]=0x03F1,
- [0x03F4]=0x03F4, [0x03F5]=0x03F5,
- },
- symbols = {
- [0x2202]=0x2202, [0x2207]=0x2207,
- },
- },
- it = {
- ucletters = 0x1D434,
- lcletters = { -- H
- [0x00061]=0x1D44E, [0x00062]=0x1D44F, [0x00063]=0x1D450, [0x00064]=0x1D451, [0x00065]=0x1D452,
- [0x00066]=0x1D453, [0x00067]=0x1D454, [0x00068]=0x0210E, [0x00069]=0x1D456, [0x0006A]=0x1D457,
- [0x0006B]=0x1D458, [0x0006C]=0x1D459, [0x0006D]=0x1D45A, [0x0006E]=0x1D45B, [0x0006F]=0x1D45C,
- [0x00070]=0x1D45D, [0x00071]=0x1D45E, [0x00072]=0x1D45F, [0x00073]=0x1D460, [0x00074]=0x1D461,
- [0x00075]=0x1D462, [0x00076]=0x1D463, [0x00077]=0x1D464, [0x00078]=0x1D465, [0x00079]=0x1D466,
- [0x0007A]=0x1D467,
- },
- ucgreek = {
- [0x0391]=0x1D6E2, [0x0392]=0x1D6E3, [0x0393]=0x1D6E4, [0x0394]=0x1D6E5, [0x0395]=0x1D6E6,
- [0x0396]=0x1D6E7, [0x0397]=0x1D6E8, [0x0398]=0x1D6E9, [0x0399]=0x1D6EA, [0x039A]=0x1D6EB,
- [0x039B]=0x1D6EC, [0x039C]=0x1D6ED, [0x039D]=0x1D6EE, [0x039E]=0x1D6EF, [0x039F]=0x1D6F0,
- [0x03A0]=0x1D6F1, [0x03A1]=0x1D6F2, [0x03A3]=0x1D6F4, [0x03A4]=0x1D6F5, [0x03A5]=0x1D6F6,
- [0x03A6]=0x1D6F7, [0x03A7]=0x1D6F8, [0x03A8]=0x1D6F9, [0x03A9]=0x1D6FA,
- },
- lcgreek = {
- [0x03B1]=0x1D6FC, [0x03B2]=0x1D6FD, [0x03B3]=0x1D6FE, [0x03B4]=0x1D6FF, [0x03B5]=0x1D700,
- [0x03B6]=0x1D701, [0x03B7]=0x1D702, [0x03B8]=0x1D703, [0x03B9]=0x1D704, [0x03BA]=0x1D705,
- [0x03BB]=0x1D706, [0x03BC]=0x1D707, [0x03BD]=0x1D708, [0x03BE]=0x1D709, [0x03BF]=0x1D70A,
- [0x03C0]=0x1D70B, [0x03C1]=0x1D70C, [0x03C2]=0x1D70D, [0x03C3]=0x1D70E, [0x03C4]=0x1D70F,
- [0x03C5]=0x1D710, [0x03C6]=0x1D711, [0x03C7]=0x1D712, [0x03C8]=0x1D713, [0x03C9]=0x1D714,
- [0x03D1]=0x1D717, [0x03D5]=0x1D719, [0x03D6]=0x1D71B, [0x03F0]=0x1D718, [0x03F1]=0x1D71A,
- [0x03F4]=0x1D6F3, [0x03F5]=0x1D716,
- },
- symbols = {
- [0x2202]=0x1D715, [0x2207]=0x1D6FB,
- },
- },
- bf= {
- digits = 0x1D7CE,
- ucletters = 0x1D400,
- lcletters = 0x1D41A,
- ucgreek = {
- [0x0391]=0x1D6A8, [0x0392]=0x1D6A9, [0x0393]=0x1D6AA, [0x0394]=0x1D6AB, [0x0395]=0x1D6AC,
- [0x0396]=0x1D6AD, [0x0397]=0x1D6AE, [0x0398]=0x1D6AF, [0x0399]=0x1D6B0, [0x039A]=0x1D6B1,
- [0x039B]=0x1D6B2, [0x039C]=0x1D6B3, [0x039D]=0x1D6B4, [0x039E]=0x1D6B5, [0x039F]=0x1D6B6,
- [0x03A0]=0x1D6B7, [0x03A1]=0x1D6B8, [0x03A3]=0x1D6BA, [0x03A4]=0x1D6BB, [0x03A5]=0x1D6BC,
- [0x03A6]=0x1D6BD, [0x03A7]=0x1D6BE, [0x03A8]=0x1D6BF, [0x03A9]=0x1D6C0,
- },
- lcgreek = {
- [0x03B1]=0x1D6C2, [0x03B2]=0x1D6C3, [0x03B3]=0x1D6C4, [0x03B4]=0x1D6C5, [0x03B5]=0x1D6C6,
- [0x03B6]=0x1D6C7, [0x03B7]=0x1D6C8, [0x03B8]=0x1D6C9, [0x03B9]=0x1D6CA, [0x03BA]=0x1D6CB,
- [0x03BB]=0x1D6CC, [0x03BC]=0x1D6CD, [0x03BD]=0x1D6CE, [0x03BE]=0x1D6CF, [0x03BF]=0x1D6D0,
- [0x03C0]=0x1D6D1, [0x03C1]=0x1D6D2, [0x03C2]=0x1D6D3, [0x03C3]=0x1D6D4, [0x03C4]=0x1D6D5,
- [0x03C5]=0x1D6D6, [0x03C6]=0x1D6D7, [0x03C7]=0x1D6D8, [0x03C8]=0x1D6D9, [0x03C9]=0x1D6DA,
- [0x03D1]=0x1D6DD, [0x03D5]=0x1D6DF, [0x03D6]=0x1D6E1, [0x03F0]=0x1D6DE, [0x03F1]=0x1D6E0,
- [0x03F4]=0x1D6B9, [0x03F5]=0x1D6DC,
- },
- symbols = {
- [0x2202]=0x1D6DB, [0x2207]=0x1D6C1,
- },
- },
- bi = {
- ucletters = 0x1D468,
- lcletters = 0x1D482,
- ucgreek = {
- [0x0391]=0x1D71C, [0x0392]=0x1D71D, [0x0393]=0x1D71E, [0x0394]=0x1D71F, [0x0395]=0x1D720,
- [0x0396]=0x1D721, [0x0397]=0x1D722, [0x0398]=0x1D723, [0x0399]=0x1D724, [0x039A]=0x1D725,
- [0x039B]=0x1D726, [0x039C]=0x1D727, [0x039D]=0x1D728, [0x039E]=0x1D729, [0x039F]=0x1D72A,
- [0x03A0]=0x1D72B, [0x03A1]=0x1D72C, [0x03A3]=0x1D72E, [0x03A4]=0x1D72F, [0x03A5]=0x1D730,
- [0x03A6]=0x1D731, [0x03A7]=0x1D732, [0x03A8]=0x1D733, [0x03A9]=0x1D734,
- },
- lcgreek = {
- [0x03B1]=0x1D736, [0x03B2]=0x1D737, [0x03B3]=0x1D738, [0x03B4]=0x1D739, [0x03B5]=0x1D73A,
- [0x03B6]=0x1D73B, [0x03B7]=0x1D73C, [0x03B8]=0x1D73D, [0x03B9]=0x1D73E, [0x03BA]=0x1D73F,
- [0x03BB]=0x1D740, [0x03BC]=0x1D741, [0x03BD]=0x1D742, [0x03BE]=0x1D743, [0x03BF]=0x1D744,
- [0x03C0]=0x1D745, [0x03C1]=0x1D746, [0x03C2]=0x1D747, [0x03C3]=0x1D748, [0x03C4]=0x1D749,
- [0x03C5]=0x1D74A, [0x03C6]=0x1D74B, [0x03C7]=0x1D74C, [0x03C8]=0x1D74D, [0x03C9]=0x1D74E,
- [0x03D1]=0x1D751, [0x03D5]=0x1D753, [0x03D6]=0x1D755, [0x03F0]=0x1D752, [0x03F1]=0x1D754,
- [0x03F4]=0x1D72D, [0x03F5]=0x1D750,
- },
- symbols = {
- [0x2202]=0x1D74F, [0x2207]=0x1D735,
- },
+local function todigit(n) local t = { } for i=0, 9 do t[0x00030+i] = n+i end return t end
+local function toupper(n) local t = { } for i=0,26 do t[0x00041+i] = n+i end return t end
+local function tolower(n) local t = { } for i=0,26 do t[0x00061+i] = n+i end return t end
+
+local regular_tf = {
+ digits = todigit(0x00030),
+ ucletters = toupper(0x00041),
+ lcletters = tolower(0x00061),
+ ucgreek = {
+ [0x0391]=0x0391, [0x0392]=0x0392, [0x0393]=0x0393, [0x0394]=0x0394, [0x0395]=0x0395,
+ [0x0396]=0x0396, [0x0397]=0x0397, [0x0398]=0x0398, [0x0399]=0x0399, [0x039A]=0x039A,
+ [0x039B]=0x039B, [0x039C]=0x039C, [0x039D]=0x039D, [0x039E]=0x039E, [0x039F]=0x039F,
+ [0x03A0]=0x03A0, [0x03A1]=0x03A1, [0x03A3]=0x03A3, [0x03A4]=0x03A4, [0x03A5]=0x03A5,
+ [0x03A6]=0x03A6, [0x03A7]=0x03A7, [0x03A8]=0x03A8, [0x03A9]=0x03A9,
},
+ lcgreek = {
+ [0x03B1]=0x03B1, [0x03B2]=0x03B2, [0x03B3]=0x03B3, [0x03B4]=0x03B4, [0x03B5]=0x03B5,
+ [0x03B6]=0x03B6, [0x03B7]=0x03B7, [0x03B8]=0x03B8, [0x03B9]=0x03B9, [0x03BA]=0x03BA,
+ [0x03BB]=0x03BB, [0x03BC]=0x03BC, [0x03BD]=0x03BD, [0x03BE]=0x03BE, [0x03BF]=0x03BF,
+ [0x03C0]=0x03C0, [0x03C1]=0x03C1, [0x03C2]=0x03C2, [0x03C3]=0x03C3, [0x03C4]=0x03C4,
+ [0x03C5]=0x03C5, [0x03C6]=0x03C6, [0x03C7]=0x03C7, [0x03C8]=0x03C8, [0x03C9]=0x03C9,
+ [0x03D1]=0x03D1, [0x03D5]=0x03D5, [0x03D6]=0x03D6, [0x03F0]=0x03F0, [0x03F1]=0x03F1,
+ [0x03F4]=0x03F4, [0x03F5]=0x03F5,
},
- sansserif = {
- tf = {
- digits = 0x1D7E2,
- ucletters = 0x1D5A0,
- lcletters = 0x1D5BA,
- },
- it = {
- ucletters = 0x1D608,
- lcletters = 0x1D622,
- },
- bf = {
- digits = 0x1D7EC,
- ucletters = 0x1D5D4,
- lcletters = 0x1D5EE,
- ucgreek = {
- [0x0391]=0x1D756, [0x0392]=0x1D757, [0x0393]=0x1D758, [0x0394]=0x1D759, [0x0395]=0x1D75A,
- [0x0396]=0x1D75B, [0x0397]=0x1D75C, [0x0398]=0x1D75D, [0x0399]=0x1D75E, [0x039A]=0x1D75F,
- [0x039B]=0x1D760, [0x039C]=0x1D761, [0x039D]=0x1D762, [0x039E]=0x1D763, [0x039F]=0x1D764,
- [0x03A0]=0x1D765, [0x03A1]=0x1D766, [0x03A3]=0x1D768, [0x03A4]=0x1D769, [0x03A5]=0x1D76A,
- [0x03A6]=0x1D76B, [0x03A7]=0x1D76C, [0x03A8]=0x1D76D, [0x03A9]=0x1D76E,
- },
- lcgreek = {
- [0x03B1]=0x1D770, [0x03B2]=0x1D771, [0x03B3]=0x1D772, [0x03B4]=0x1D773, [0x03B5]=0x1D774,
- [0x03B6]=0x1D775, [0x03B7]=0x1D776, [0x03B8]=0x1D777, [0x03B9]=0x1D778, [0x03BA]=0x1D779,
- [0x03BB]=0x1D77A, [0x03BC]=0x1D77B, [0x03BD]=0x1D77C, [0x03BE]=0x1D77D, [0x03BF]=0x1D77E,
- [0x03C0]=0x1D77F, [0x03C1]=0x1D780, [0x03C2]=0x1D781, [0x03C3]=0x1D782, [0x03C4]=0x1D783,
- [0x03C5]=0x1D784, [0x03C6]=0x1D785, [0x03C7]=0x1D786, [0x03C8]=0x1D787, [0x03C9]=0x1D788,
- [0x03D1]=0x1D78B, [0x03D5]=0x1D78D, [0x03D6]=0x1D78F, [0x03F0]=0x1D78C, [0x03F1]=0x1D78E,
- [0x03F4]=0x1D767, [0x03F5]=0x1D78A,
- },
- symbols = {
- [0x2202]=0x1D789, [0x2207]=0x1D76F,
- },
- },
- bi = {
- ucletters = 0x1D63C,
- lcletters = 0x1D656,
- ucgreek = {
- [0x0391]=0x1D790, [0x0392]=0x1D791, [0x0393]=0x1D792, [0x0394]=0x1D793, [0x0395]=0x1D794,
- [0x0396]=0x1D795, [0x0397]=0x1D796, [0x0398]=0x1D797, [0x0399]=0x1D798, [0x039A]=0x1D799,
- [0x039B]=0x1D79A, [0x039C]=0x1D79B, [0x039D]=0x1D79C, [0x039E]=0x1D79D, [0x039F]=0x1D79E,
- [0x03A0]=0x1D79F, [0x03A1]=0x1D7A0, [0x03A3]=0x1D7A2, [0x03A4]=0x1D7A3, [0x03A5]=0x1D7A4,
- [0x03A6]=0x1D7A5, [0x03A7]=0x1D7A6, [0x03A8]=0x1D7A7, [0x03A9]=0x1D7A8,
- },
- lcgreek = {
- [0x03B1]=0x1D7AA, [0x03B2]=0x1D7AB, [0x03B3]=0x1D7AC, [0x03B4]=0x1D7AD, [0x03B5]=0x1D7AE,
- [0x03B6]=0x1D7AF, [0x03B7]=0x1D7B0, [0x03B8]=0x1D7B1, [0x03B9]=0x1D7B2, [0x03BA]=0x1D7B3,
- [0x03BB]=0x1D7B4, [0x03BC]=0x1D7B5, [0x03BD]=0x1D7B6, [0x03BE]=0x1D7B7, [0x03BF]=0x1D7B8,
- [0x03C0]=0x1D7B9, [0x03C1]=0x1D7BA, [0x03C2]=0x1D7BB, [0x03C3]=0x1D7BC, [0x03C4]=0x1D7BD,
- [0x03C5]=0x1D7BE, [0x03C6]=0x1D7BF, [0x03C7]=0x1D7C0, [0x03C8]=0x1D7C1, [0x03C9]=0x1D7C2,
- [0x03D1]=0x1D7C5, [0x03D5]=0x1D7C7, [0x03D6]=0x1D7C9, [0x03F0]=0x1D7C6, [0x03F1]=0x1D7C8,
- [0x03F4]=0x1D7A1, [0x03F5]=0x1D7C4,
- },
- symbols = {
- [0x2202]=0x1D7C3, [0x2207]=0x1D7A9,
- },
- },
+ symbols = {
+ [0x2202]=0x2202, [0x2207]=0x2207,
},
- monospaced = {
- tf = {
- digits = 0x1D7F6,
- ucletters = 0x1D670,
- lcletters = 0x1D68A,
- },
+}
+
+local regular_it = {
+ digits = regular_tf.digits,
+ ucletters = toupper(0x1D434),
+ lcletters = { -- H
+ [0x00061]=0x1D44E, [0x00062]=0x1D44F, [0x00063]=0x1D450, [0x00064]=0x1D451, [0x00065]=0x1D452,
+ [0x00066]=0x1D453, [0x00067]=0x1D454, [0x00068]=0x0210E, [0x00069]=0x1D456, [0x0006A]=0x1D457,
+ [0x0006B]=0x1D458, [0x0006C]=0x1D459, [0x0006D]=0x1D45A, [0x0006E]=0x1D45B, [0x0006F]=0x1D45C,
+ [0x00070]=0x1D45D, [0x00071]=0x1D45E, [0x00072]=0x1D45F, [0x00073]=0x1D460, [0x00074]=0x1D461,
+ [0x00075]=0x1D462, [0x00076]=0x1D463, [0x00077]=0x1D464, [0x00078]=0x1D465, [0x00079]=0x1D466,
+ [0x0007A]=0x1D467,
},
- blackboard = { -- ok
- tf = {
- digits = 0x1D7D8,
- ucletters = { -- C H N P Q R Z
- [0x00041]=0x1D538, [0x00042]=0x1D539, [0x00043]=0x02102, [0x00044]=0x1D53B, [0x00045]=0x1D53C,
- [0x00046]=0x1D53D, [0x00047]=0x1D53E, [0x00048]=0x0210D, [0x00049]=0x1D540, [0x0004A]=0x1D541,
- [0x0004B]=0x1D542, [0x0004C]=0x1D543, [0x0004D]=0x1D544, [0x0004E]=0x02115, [0x0004F]=0x1D546,
- [0x00050]=0x02119, [0x00051]=0x0211A, [0x00052]=0x0211D, [0x00053]=0x1D54A, [0x00054]=0x1D54B,
- [0x00055]=0x1D54C, [0x00056]=0x1D54D, [0x00057]=0x1D54E, [0x00058]=0x1D54F, [0x00059]=0x1D550,
- [0x0005A]=0x02124,
- },
- lcletters = 0x1D552,
- lcgreek = { -- gamma pi
- [0x03B3]=0x0213C, [0x03C0]=0x0213D,
- },
- ucgreek = { -- Gamma pi
- [0x0393]=0x0213E, [0x03A0]=0x0213F,
- },
- symbols = { -- sum
- [0x2211]=0x02140,
- },
+ ucgreek = {
+ [0x0391]=0x1D6E2, [0x0392]=0x1D6E3, [0x0393]=0x1D6E4, [0x0394]=0x1D6E5, [0x0395]=0x1D6E6,
+ [0x0396]=0x1D6E7, [0x0397]=0x1D6E8, [0x0398]=0x1D6E9, [0x0399]=0x1D6EA, [0x039A]=0x1D6EB,
+ [0x039B]=0x1D6EC, [0x039C]=0x1D6ED, [0x039D]=0x1D6EE, [0x039E]=0x1D6EF, [0x039F]=0x1D6F0,
+ [0x03A0]=0x1D6F1, [0x03A1]=0x1D6F2, [0x03A3]=0x1D6F4, [0x03A4]=0x1D6F5, [0x03A5]=0x1D6F6,
+ [0x03A6]=0x1D6F7, [0x03A7]=0x1D6F8, [0x03A8]=0x1D6F9, [0x03A9]=0x1D6FA,
},
+ lcgreek = {
+ [0x03B1]=0x1D6FC, [0x03B2]=0x1D6FD, [0x03B3]=0x1D6FE, [0x03B4]=0x1D6FF, [0x03B5]=0x1D700,
+ [0x03B6]=0x1D701, [0x03B7]=0x1D702, [0x03B8]=0x1D703, [0x03B9]=0x1D704, [0x03BA]=0x1D705,
+ [0x03BB]=0x1D706, [0x03BC]=0x1D707, [0x03BD]=0x1D708, [0x03BE]=0x1D709, [0x03BF]=0x1D70A,
+ [0x03C0]=0x1D70B, [0x03C1]=0x1D70C, [0x03C2]=0x1D70D, [0x03C3]=0x1D70E, [0x03C4]=0x1D70F,
+ [0x03C5]=0x1D710, [0x03C6]=0x1D711, [0x03C7]=0x1D712, [0x03C8]=0x1D713, [0x03C9]=0x1D714,
+ [0x03D1]=0x1D717, [0x03D5]=0x1D719, [0x03D6]=0x1D71B, [0x03F0]=0x1D718, [0x03F1]=0x1D71A,
+ [0x03F4]=0x1D6F3, [0x03F5]=0x1D716,
+ },
+ symbols = {
+ [0x2202]=0x1D715, [0x2207]=0x1D6FB,
},
- fraktur = { -- ok
- tf= {
- ucletters = { -- C H I R Z
- [0x00041]=0x1D504, [0x00042]=0x1D505, [0x00043]=0x0212D, [0x00044]=0x1D507, [0x00045]=0x1D508,
- [0x00046]=0x1D509, [0x00047]=0x1D50A, [0x00048]=0x0210C, [0x00049]=0x02111, [0x0004A]=0x1D50D,
- [0x0004B]=0x1D50E, [0x0004C]=0x1D50F, [0x0004D]=0x1D510, [0x0004E]=0x1D511, [0x0004F]=0x1D512,
- [0x00050]=0x1D513, [0x00051]=0x1D514, [0x00052]=0x0211C, [0x00053]=0x1D516, [0x00054]=0x1D517,
- [0x00055]=0x1D518, [0x00056]=0x1D519, [0x00057]=0x1D51A, [0x00058]=0x1D51B, [0x00059]=0x1D51C,
- [0x0005A]=0x02128,
- },
- lcletters = 0x1D51E,
+}
+
+local regular_bf= {
+ digits = todigit(0x1D7CE),
+ ucletters = toupper(0x1D400),
+ lcletters = tolower(0x1D41A),
+ ucgreek = {
+ [0x0391]=0x1D6A8, [0x0392]=0x1D6A9, [0x0393]=0x1D6AA, [0x0394]=0x1D6AB, [0x0395]=0x1D6AC,
+ [0x0396]=0x1D6AD, [0x0397]=0x1D6AE, [0x0398]=0x1D6AF, [0x0399]=0x1D6B0, [0x039A]=0x1D6B1,
+ [0x039B]=0x1D6B2, [0x039C]=0x1D6B3, [0x039D]=0x1D6B4, [0x039E]=0x1D6B5, [0x039F]=0x1D6B6,
+ [0x03A0]=0x1D6B7, [0x03A1]=0x1D6B8, [0x03A3]=0x1D6BA, [0x03A4]=0x1D6BB, [0x03A5]=0x1D6BC,
+ [0x03A6]=0x1D6BD, [0x03A7]=0x1D6BE, [0x03A8]=0x1D6BF, [0x03A9]=0x1D6C0,
},
- bf = {
- ucletters = 0x1D56C,
- lcletters = 0x1D586,
+ lcgreek = {
+ [0x03B1]=0x1D6C2, [0x03B2]=0x1D6C3, [0x03B3]=0x1D6C4, [0x03B4]=0x1D6C5, [0x03B5]=0x1D6C6,
+ [0x03B6]=0x1D6C7, [0x03B7]=0x1D6C8, [0x03B8]=0x1D6C9, [0x03B9]=0x1D6CA, [0x03BA]=0x1D6CB,
+ [0x03BB]=0x1D6CC, [0x03BC]=0x1D6CD, [0x03BD]=0x1D6CE, [0x03BE]=0x1D6CF, [0x03BF]=0x1D6D0,
+ [0x03C0]=0x1D6D1, [0x03C1]=0x1D6D2, [0x03C2]=0x1D6D3, [0x03C3]=0x1D6D4, [0x03C4]=0x1D6D5,
+ [0x03C5]=0x1D6D6, [0x03C6]=0x1D6D7, [0x03C7]=0x1D6D8, [0x03C8]=0x1D6D9, [0x03C9]=0x1D6DA,
+ [0x03D1]=0x1D6DD, [0x03D5]=0x1D6DF, [0x03D6]=0x1D6E1, [0x03F0]=0x1D6DE, [0x03F1]=0x1D6E0,
+ [0x03F4]=0x1D6B9, [0x03F5]=0x1D6DC,
+ },
+ symbols = {
+ [0x2202]=0x1D6DB, [0x2207]=0x1D6C1,
+ },
+}
+
+local regular_bi = {
+ digits = regular_bf.digits,
+ ucletters = toupper(0x1D468),
+ lcletters = tolower(0x1D482),
+ ucgreek = {
+ [0x0391]=0x1D71C, [0x0392]=0x1D71D, [0x0393]=0x1D71E, [0x0394]=0x1D71F, [0x0395]=0x1D720,
+ [0x0396]=0x1D721, [0x0397]=0x1D722, [0x0398]=0x1D723, [0x0399]=0x1D724, [0x039A]=0x1D725,
+ [0x039B]=0x1D726, [0x039C]=0x1D727, [0x039D]=0x1D728, [0x039E]=0x1D729, [0x039F]=0x1D72A,
+ [0x03A0]=0x1D72B, [0x03A1]=0x1D72C, [0x03A3]=0x1D72E, [0x03A4]=0x1D72F, [0x03A5]=0x1D730,
+ [0x03A6]=0x1D731, [0x03A7]=0x1D732, [0x03A8]=0x1D733, [0x03A9]=0x1D734,
},
+ lcgreek = {
+ [0x03B1]=0x1D736, [0x03B2]=0x1D737, [0x03B3]=0x1D738, [0x03B4]=0x1D739, [0x03B5]=0x1D73A,
+ [0x03B6]=0x1D73B, [0x03B7]=0x1D73C, [0x03B8]=0x1D73D, [0x03B9]=0x1D73E, [0x03BA]=0x1D73F,
+ [0x03BB]=0x1D740, [0x03BC]=0x1D741, [0x03BD]=0x1D742, [0x03BE]=0x1D743, [0x03BF]=0x1D744,
+ [0x03C0]=0x1D745, [0x03C1]=0x1D746, [0x03C2]=0x1D747, [0x03C3]=0x1D748, [0x03C4]=0x1D749,
+ [0x03C5]=0x1D74A, [0x03C6]=0x1D74B, [0x03C7]=0x1D74C, [0x03C8]=0x1D74D, [0x03C9]=0x1D74E,
+ [0x03D1]=0x1D751, [0x03D5]=0x1D753, [0x03D6]=0x1D755, [0x03F0]=0x1D752, [0x03F1]=0x1D754,
+ [0x03F4]=0x1D72D, [0x03F5]=0x1D750,
+ },
+ symbols = {
+ [0x2202]=0x1D74F, [0x2207]=0x1D735,
},
- script = {
- tf= {
- ucletters = { -- B E F H I L M R -- P 2118
- [0x00041]=0x1D49C, [0x00042]=0x0212C, [0x00043]=0x1D49E, [0x00044]=0x1D49F, [0x00045]=0x02130,
- [0x00046]=0x02131, [0x00047]=0x1D4A2, [0x00048]=0x0210B, [0x00049]=0x02110, [0x0004A]=0x1D4A5,
- [0x0004B]=0x1D4A6, [0x0004C]=0x02112, [0x0004D]=0x02133, [0x0004E]=0x1D4A9, [0x0004F]=0x1D4AA,
- [0x00050]=0x1D4AB, [0x00051]=0x1D4AC, [0x00052]=0x0211B, [0x00053]=0x1D4AE, [0x00054]=0x1D4AF,
- [0x00055]=0x1D4B0, [0x00056]=0x1D4B1, [0x00057]=0x1D4B2, [0x00058]=0x1D4B3, [0x00059]=0x1D4B4,
- [0x0005A]=0x1D4B5,
- },
- lcletters = { -- E G O -- L 2113
- [0x00061]=0x1D4B6, [0x00062]=0x1D4B7, [0x00063]=0x1D4B8, [0x00064]=0x1D4B9, [0x00065]=0x0212F,
- [0x00066]=0x1D4BB, [0x00067]=0x0210A, [0x00068]=0x1D4BD, [0x00069]=0x1D4BE, [0x0006A]=0x1D4BF,
- [0x0006B]=0x1D4C0, [0x0006C]=0x1D4C1, [0x0006D]=0x1D4C2, [0x0006E]=0x1D4C3, [0x0006F]=0x02134,
- [0x00070]=0x1D4C5, [0x00071]=0x1D4C6, [0x00072]=0x1D4C7, [0x00073]=0x1D4C8, [0x00074]=0x1D4C9,
- [0x00075]=0x1D4CA, [0x00076]=0x1D4CB, [0x00077]=0x1D4CC, [0x00078]=0x1D4CD, [0x00079]=0x1D4CE,
- [0x0007A]=0x1D4CF,
- }
+}
+
+local regular = {
+ tf = regular_tf,
+ it = regular_it,
+ bf = regular_bf,
+ bi = regular_bi,
+}
+
+local sansserif_tf = {
+ digits = todigit(0x1D7E2),
+ ucletters = toupper(0x1D5A0),
+ lcletters = tolower(0x1D5BA),
+ lcgreek = regular_tf.lcgreek,
+ ucgreek = regular_tf.ucgreek,
+ symbols = regular_tf.symbols,
+}
+
+local sansserif_it = {
+ digits = regular_tf.digits,
+ ucletters = toupper(0x1D608),
+ lcletters = tolower(0x1D622),
+ lcgreek = regular_tf.lcgreek,
+ ucgreek = regular_tf.ucgreek,
+ symbols = regular_tf.symbols,
+}
+
+local sansserif_bf = {
+ digits = todigit(0x1D7EC),
+ ucletters = toupper(0x1D5D4),
+ lcletters = tolower(0x1D5EE),
+ ucgreek = {
+ [0x0391]=0x1D756, [0x0392]=0x1D757, [0x0393]=0x1D758, [0x0394]=0x1D759, [0x0395]=0x1D75A,
+ [0x0396]=0x1D75B, [0x0397]=0x1D75C, [0x0398]=0x1D75D, [0x0399]=0x1D75E, [0x039A]=0x1D75F,
+ [0x039B]=0x1D760, [0x039C]=0x1D761, [0x039D]=0x1D762, [0x039E]=0x1D763, [0x039F]=0x1D764,
+ [0x03A0]=0x1D765, [0x03A1]=0x1D766, [0x03A3]=0x1D768, [0x03A4]=0x1D769, [0x03A5]=0x1D76A,
+ [0x03A6]=0x1D76B, [0x03A7]=0x1D76C, [0x03A8]=0x1D76D, [0x03A9]=0x1D76E,
},
- bf = {
- ucletters = 0x1D4D0,
- lcletters = 0x1D4EA,
+ lcgreek = {
+ [0x03B1]=0x1D770, [0x03B2]=0x1D771, [0x03B3]=0x1D772, [0x03B4]=0x1D773, [0x03B5]=0x1D774,
+ [0x03B6]=0x1D775, [0x03B7]=0x1D776, [0x03B8]=0x1D777, [0x03B9]=0x1D778, [0x03BA]=0x1D779,
+ [0x03BB]=0x1D77A, [0x03BC]=0x1D77B, [0x03BD]=0x1D77C, [0x03BE]=0x1D77D, [0x03BF]=0x1D77E,
+ [0x03C0]=0x1D77F, [0x03C1]=0x1D780, [0x03C2]=0x1D781, [0x03C3]=0x1D782, [0x03C4]=0x1D783,
+ [0x03C5]=0x1D784, [0x03C6]=0x1D785, [0x03C7]=0x1D786, [0x03C8]=0x1D787, [0x03C9]=0x1D788,
+ [0x03D1]=0x1D78B, [0x03D5]=0x1D78D, [0x03D6]=0x1D78F, [0x03F0]=0x1D78C, [0x03F1]=0x1D78E,
+ [0x03F4]=0x1D767, [0x03F5]=0x1D78A,
+ },
+ symbols = {
+ [0x2202]=0x1D789, [0x2207]=0x1D76F,
+ },
+}
+
+local sansserif_bi = {
+ digits = sansserif_bf.digits,
+ ucletters = toupper(0x1D63C),
+ lcletters = tolower(0x1D656),
+ ucgreek = {
+ [0x0391]=0x1D790, [0x0392]=0x1D791, [0x0393]=0x1D792, [0x0394]=0x1D793, [0x0395]=0x1D794,
+ [0x0396]=0x1D795, [0x0397]=0x1D796, [0x0398]=0x1D797, [0x0399]=0x1D798, [0x039A]=0x1D799,
+ [0x039B]=0x1D79A, [0x039C]=0x1D79B, [0x039D]=0x1D79C, [0x039E]=0x1D79D, [0x039F]=0x1D79E,
+ [0x03A0]=0x1D79F, [0x03A1]=0x1D7A0, [0x03A3]=0x1D7A2, [0x03A4]=0x1D7A3, [0x03A5]=0x1D7A4,
+ [0x03A6]=0x1D7A5, [0x03A7]=0x1D7A6, [0x03A8]=0x1D7A7, [0x03A9]=0x1D7A8,
},
+ lcgreek = {
+ [0x03B1]=0x1D7AA, [0x03B2]=0x1D7AB, [0x03B3]=0x1D7AC, [0x03B4]=0x1D7AD, [0x03B5]=0x1D7AE,
+ [0x03B6]=0x1D7AF, [0x03B7]=0x1D7B0, [0x03B8]=0x1D7B1, [0x03B9]=0x1D7B2, [0x03BA]=0x1D7B3,
+ [0x03BB]=0x1D7B4, [0x03BC]=0x1D7B5, [0x03BD]=0x1D7B6, [0x03BE]=0x1D7B7, [0x03BF]=0x1D7B8,
+ [0x03C0]=0x1D7B9, [0x03C1]=0x1D7BA, [0x03C2]=0x1D7BB, [0x03C3]=0x1D7BC, [0x03C4]=0x1D7BD,
+ [0x03C5]=0x1D7BE, [0x03C6]=0x1D7BF, [0x03C7]=0x1D7C0, [0x03C8]=0x1D7C1, [0x03C9]=0x1D7C2,
+ [0x03D1]=0x1D7C5, [0x03D5]=0x1D7C7, [0x03D6]=0x1D7C9, [0x03F0]=0x1D7C6, [0x03F1]=0x1D7C8,
+ [0x03F4]=0x1D7A1, [0x03F5]=0x1D7C4,
+ },
+ symbols = {
+ [0x2202]=0x1D7C3, [0x2207]=0x1D7A9,
+ },
+}
+
+local sansserif = {
+ tf = sansserif_tf,
+ it = sansserif_it,
+ bf = sansserif_bf,
+ bi = sansserif_bi,
+}
+
+local monospaced_tf = {
+ digits = todigit(0x1D7F6),
+ ucletters = toupper(0x1D670),
+ lcletters = tolower(0x1D68A),
+ lcgreek = sansserif_tf.lcgreek,
+ ucgreek = sansserif_tf.ucgreek,
+ symbols = sansserif_tf.symbols,
+}
+
+local monospaced = {
+ tf = monospaced_tf,
+ it = sansserif_tf,
+ bf = sansserif_tf,
+ bi = sansserif_bf,
+}
+
+local blackboard_tf = {
+ digits = todigit(0x1D7D8),
+ ucletters = { -- C H N P Q R Z
+ [0x00041]=0x1D538, [0x00042]=0x1D539, [0x00043]=0x02102, [0x00044]=0x1D53B, [0x00045]=0x1D53C,
+ [0x00046]=0x1D53D, [0x00047]=0x1D53E, [0x00048]=0x0210D, [0x00049]=0x1D540, [0x0004A]=0x1D541,
+ [0x0004B]=0x1D542, [0x0004C]=0x1D543, [0x0004D]=0x1D544, [0x0004E]=0x02115, [0x0004F]=0x1D546,
+ [0x00050]=0x02119, [0x00051]=0x0211A, [0x00052]=0x0211D, [0x00053]=0x1D54A, [0x00054]=0x1D54B,
+ [0x00055]=0x1D54C, [0x00056]=0x1D54D, [0x00057]=0x1D54E, [0x00058]=0x1D54F, [0x00059]=0x1D550,
+ [0x0005A]=0x02124,
+ },
+ lcletters = tolower(0x1D552),
+ lcgreek = { -- gamma pi
+ [0x03B3]=0x0213C, [0x03C0]=0x0213D,
},
+ ucgreek = { -- Gamma pi
+ [0x0393]=0x0213E, [0x03A0]=0x0213F,
+ },
+ symbols = { -- sum
+ [0x2211]=0x02140,
+ },
+}
+
+blackboard_tf.lcgreek = merged(regular_tf.lcgreek, blackboard_tf.lcgreek)
+blackboard_tf.ucgreek = merged(regular_tf.ucgreek, blackboard_tf.ucgreek)
+blackboard_tf.symbols = merged(regular_tf.symbols, blackboard_tf.symbols)
+
+local blackboard = {
+ tf = blackboard_tf,
+ it = blackboard_tf,
+ bf = blackboard_tf,
+ bi = blackboard_tf,
+}
+
+local fraktur_tf= {
+ digits = regular_tf.digits,
+ ucletters = { -- C H I R Z
+ [0x00041]=0x1D504, [0x00042]=0x1D505, [0x00043]=0x0212D, [0x00044]=0x1D507, [0x00045]=0x1D508,
+ [0x00046]=0x1D509, [0x00047]=0x1D50A, [0x00048]=0x0210C, [0x00049]=0x02111, [0x0004A]=0x1D50D,
+ [0x0004B]=0x1D50E, [0x0004C]=0x1D50F, [0x0004D]=0x1D510, [0x0004E]=0x1D511, [0x0004F]=0x1D512,
+ [0x00050]=0x1D513, [0x00051]=0x1D514, [0x00052]=0x0211C, [0x00053]=0x1D516, [0x00054]=0x1D517,
+ [0x00055]=0x1D518, [0x00056]=0x1D519, [0x00057]=0x1D51A, [0x00058]=0x1D51B, [0x00059]=0x1D51C,
+ [0x0005A]=0x02128,
+ },
+ lcletters = tolower(0x1D51E),
+ lcgreek = regular_tf.lcgreek,
+ ucgreek = regular_tf.ucgreek,
+ symbols = regular_tf.symbols,
+}
+
+local fraktur_bf = {
+ digits = regular_bf.digits,
+ ucletters = toupper(0x1D56C),
+ lcletters = tolower(0x1D586),
+ lcgreek = regular_bf.lcgreek,
+ ucgreek = regular_bf.ucgreek,
+ symbols = regular_bf.symbols,
+}
+
+local fraktur = { -- ok
+ tf = fraktur_tf,
+ bf = fraktur_bf,
+ it = fraktur_tf,
+ bi = fraktur_bf,
+}
+
+local script_tf = {
+ digits = regular_tf.digits,
+ ucletters = { -- B E F H I L M R -- P 2118
+ [0x00041]=0x1D49C, [0x00042]=0x0212C, [0x00043]=0x1D49E, [0x00044]=0x1D49F, [0x00045]=0x02130,
+ [0x00046]=0x02131, [0x00047]=0x1D4A2, [0x00048]=0x0210B, [0x00049]=0x02110, [0x0004A]=0x1D4A5,
+ [0x0004B]=0x1D4A6, [0x0004C]=0x02112, [0x0004D]=0x02133, [0x0004E]=0x1D4A9, [0x0004F]=0x1D4AA,
+ [0x00050]=0x1D4AB, [0x00051]=0x1D4AC, [0x00052]=0x0211B, [0x00053]=0x1D4AE, [0x00054]=0x1D4AF,
+ [0x00055]=0x1D4B0, [0x00056]=0x1D4B1, [0x00057]=0x1D4B2, [0x00058]=0x1D4B3, [0x00059]=0x1D4B4,
+ [0x0005A]=0x1D4B5,
+ },
+ lcletters = { -- E G O -- L 2113
+ [0x00061]=0x1D4B6, [0x00062]=0x1D4B7, [0x00063]=0x1D4B8, [0x00064]=0x1D4B9, [0x00065]=0x0212F,
+ [0x00066]=0x1D4BB, [0x00067]=0x0210A, [0x00068]=0x1D4BD, [0x00069]=0x1D4BE, [0x0006A]=0x1D4BF,
+ [0x0006B]=0x1D4C0, [0x0006C]=0x1D4C1, [0x0006D]=0x1D4C2, [0x0006E]=0x1D4C3, [0x0006F]=0x02134,
+ [0x00070]=0x1D4C5, [0x00071]=0x1D4C6, [0x00072]=0x1D4C7, [0x00073]=0x1D4C8, [0x00074]=0x1D4C9,
+ [0x00075]=0x1D4CA, [0x00076]=0x1D4CB, [0x00077]=0x1D4CC, [0x00078]=0x1D4CD, [0x00079]=0x1D4CE,
+ [0x0007A]=0x1D4CF,
+ },
+ lcgreek = regular_tf.lcgreek,
+ ucgreek = regular_tf.ucgreek,
+ symbols = regular_tf.symbols,
+}
+
+local script_bf = {
+ digits = regular_bf.digits,
+ ucletters = toupper(0x1D4D0),
+ lcletters = tolower(0x1D4EA),
+ lcgreek = regular_bf.lcgreek,
+ ucgreek = regular_bf.ucgreek,
+ symbols = regular_bf.symbols,
+}
+
+local script = {
+ tf = script_tf,
+ bf = script_bf,
+ it = script_tf,
+ bi = script_bf,
+}
+
+local alphabets = allocate {
+ regular = regular,
+ sansserif = sansserif,
+ monospaced = monospaced,
+ blackboard = blackboard,
+ fraktur = fraktur,
+ script = script,
}
mathematics.alphabets = alphabets
+local boldmap = { }
+
+local function remap(tf,bf)
+ for _, alphabet in next, alphabets do
+ local tfdata = alphabet[tf]
+ local bfdata = alphabet[bf]
+ if tfdata then
+ for k, tfd in next, tfdata do
+ if type(tfd) == "table" then
+ local bfd = bfdata[k]
+ if bfd then
+ for n, u in next, tfd do
+ local bn = bfd[n]
+ if bn then
+ boldmap[u] = bn
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+remap("tf","bf")
+remap("it","bi")
+
+mathematics.boldmap = boldmap
+
local mathremap = { }
-for alphabet, styles in next, alphabets do
+for alphabet, styles in next, alphabets do -- per 9/6/2011 we also have attr for missing
for style, data in next, styles do
-- let's keep the long names (for tracing)
local n = #mathremap + 1
@@ -290,65 +472,31 @@ end
-- beware, these are shared tables (no problem since they're not
-- in unicode)
-alphabets.regular.it.digits = alphabets.regular.tf.digits
-alphabets.regular.bi.digits = alphabets.regular.bf.digits
-
-alphabets.sansserif.tf.symbols = alphabets.regular.tf.symbols
-alphabets.sansserif.tf.lcgreek = alphabets.regular.tf.lcgreek
-alphabets.sansserif.tf.ucgreek = alphabets.regular.tf.ucgreek
-alphabets.sansserif.tf.digits = alphabets.regular.tf.digits
-alphabets.sansserif.it.symbols = alphabets.regular.tf.symbols
-alphabets.sansserif.it.lcgreek = alphabets.regular.tf.lcgreek
-alphabets.sansserif.it.ucgreek = alphabets.regular.tf.ucgreek
-alphabets.sansserif.bi.digits = alphabets.regular.bf.digits
-
-alphabets.monospaced.tf.symbols = alphabets.sansserif.tf.symbols
-alphabets.monospaced.tf.lcgreek = alphabets.sansserif.tf.lcgreek
-alphabets.monospaced.tf.ucgreek = alphabets.sansserif.tf.ucgreek
-alphabets.monospaced.it = alphabets.sansserif.tf
-alphabets.monospaced.bf = alphabets.sansserif.tf
-alphabets.monospaced.bi = alphabets.sansserif.bf
-
-alphabets.blackboard.tf.symbols = table.merged(alphabets.regular.tf.symbols, alphabets.blackboard.tf.symbols)
-alphabets.blackboard.tf.lcgreek = table.merged(alphabets.regular.tf.lcgreek, alphabets.blackboard.tf.lcgreek)
-alphabets.blackboard.tf.ucgreek = table.merged(alphabets.regular.tf.ucgreek, alphabets.blackboard.tf.ucgreek)
-
-alphabets.blackboard.it = alphabets.blackboard.tf
-alphabets.blackboard.bf = alphabets.blackboard.tf
-alphabets.blackboard.bi = alphabets.blackboard.bf
-
-alphabets.fraktur.tf.digits = alphabets.regular.tf.digits
-alphabets.fraktur.tf.symbols = alphabets.regular.tf.symbols
-alphabets.fraktur.tf.lcgreek = alphabets.regular.tf.lcgreek
-alphabets.fraktur.tf.ucgreek = alphabets.regular.tf.ucgreek
-alphabets.fraktur.bf.digits = alphabets.regular.bf.digits
-alphabets.fraktur.bf.symbols = alphabets.regular.bf.symbols
-alphabets.fraktur.bf.lcgreek = alphabets.regular.bf.lcgreek
-alphabets.fraktur.bf.ucgreek = alphabets.regular.bf.ucgreek
-alphabets.fraktur.it = alphabets.fraktur.tf
-alphabets.fraktur.bi = alphabets.fraktur.bf
-
-alphabets.script.tf.digits = alphabets.regular.tf.digits
-alphabets.script.tf.symbols = alphabets.regular.tf.symbols
-alphabets.script.tf.lcgreek = alphabets.regular.tf.lcgreek
-alphabets.script.tf.ucgreek = alphabets.regular.tf.ucgreek
-alphabets.script.bf.digits = alphabets.regular.bf.digits
-alphabets.script.bf.symbols = alphabets.regular.bf.symbols
-alphabets.script.bf.lcgreek = alphabets.regular.bf.lcgreek
-alphabets.script.bf.ucgreek = alphabets.regular.bf.ucgreek
-alphabets.script.it = alphabets.script.tf
-alphabets.script.bi = alphabets.script.bf
-
-alphabets.tt = alphabets.monospaced
-alphabets.ss = alphabets.sansserif
-alphabets.rm = alphabets.regular
-alphabets.bb = alphabets.blackboard
-alphabets.fr = alphabets.fraktur
-alphabets.sr = alphabets.script
-
-alphabets.serif = alphabets.regular
-alphabets.type = alphabets.monospaced
-alphabets.teletype = alphabets.monospaced
+alphabets.tt = monospaced
+alphabets.ss = sansserif
+alphabets.rm = regular
+alphabets.bb = blackboard
+alphabets.fr = fraktur
+alphabets.sr = script
+
+alphabets.serif = regular
+alphabets.type = monospaced
+alphabets.teletype = monospaced
+
+regular.normal = regular_tf
+regular.italic = regular_it
+regular.bold = regular_bf
+regular.bolditalic = regular_bi
+
+sansserif.normal = sansserif_tf
+sansserif.italic = sansserif_it
+sansserif.bold = sansserif_bf
+sansserif.bolditalic = sansserif_bi
+
+monospaced.normal = monospaced_tf
+monospaced.italic = monospaced_it
+monospaced.bold = monospaced_bf
+monospaced.bolditalic = monospaced_bi
function mathematics.tostyle(attribute)
local r = mathremap[attribute]
@@ -364,14 +512,26 @@ end
local mathalphabet = attributes.private("mathalphabet")
+function mathematics.getboth(alphabet,style)
+ local data = alphabets[alphabet or "regular"] or regular
+ data = data[style or "tf"] or data.tf
+ return data and data.attribute
+end
+
+function mathematics.getstyle(style)
+ local r = mathremap[texattribute[mathalphabet]]
+ local alphabet = r and r.alphabet or "regular"
+ local data = alphabets[alphabet][style]
+ return data and data.attribute
+end
+
function mathematics.syncboth(alphabet,style)
- local data = alphabets[alphabet or "regular"] or alphabets.regular
+ local data = alphabets[alphabet or "regular"] or regular
data = data[style or "tf"] or data.tf
texattribute[mathalphabet] = data and data.attribute or texattribute[mathalphabet]
end
function mathematics.syncstyle(style)
---~ local r = mathremap[mathalphabet]
local r = mathremap[texattribute[mathalphabet]]
local alphabet = r and r.alphabet or "regular"
local data = alphabets[alphabet][style]
@@ -386,9 +546,9 @@ function mathematics.syncname(alphabet)
texattribute[mathalphabet] = data and data.attribute or texattribute[mathalphabet]
end
-local issymbol = mathematics.alphabets.regular.tf.symbols
-local islcgreek = mathematics.alphabets.regular.tf.lcgreek
-local isucgreek = mathematics.alphabets.regular.tf.ucgreek
+local issymbol = regular.tf.symbols
+local islcgreek = regular.tf.lcgreek
+local isucgreek = regular.tf.ucgreek
local remapping = {
[1] = { what = "unchanged" }, -- upright
@@ -397,7 +557,7 @@ local remapping = {
}
function mathematics.remapalphabets(char,mathalphabet,mathgreek)
- if mathgreek > 0 then
+ if mathgreek and mathgreek > 0 then
local lc, uc = floor(mathgreek/10), mathgreek % 10 -- 2 == upright 3 == italic
if lc > 1 or uc > 1 then
local islc, isuc = islcgreek[char] and lc, isucgreek[char] and uc
@@ -419,7 +579,8 @@ function mathematics.remapalphabets(char,mathalphabet,mathgreek)
end
end
end
- if mathalphabet > 0 then
+ -- table test can go away
+ if mathalphabet and mathalphabet > 0 then
local newchar
local offset = mathremap[mathalphabet]
if not offset then
@@ -455,9 +616,14 @@ end
function mathematics.addfallbacks(main)
local characters = main.characters
- local regular = alphabets.regular
checkedcopy(characters,regular.bf.ucgreek,regular.tf.ucgreek)
checkedcopy(characters,regular.bf.lcgreek,regular.tf.lcgreek)
checkedcopy(characters,regular.bi.ucgreek,regular.it.ucgreek)
checkedcopy(characters,regular.bi.lcgreek,regular.it.lcgreek)
end
+
+-- interface
+
+commands.setmathattribute = mathematics.syncboth
+commands.setmathalphabet = mathematics.syncname
+commands.setmathstyle = mathematics.syncstyle
diff --git a/Master/texmf-dist/tex/context/base/math-noa.lua b/Master/texmf-dist/tex/context/base/math-noa.lua
index c298a8068ae..8caf21cc2cf 100644
--- a/Master/texmf-dist/tex/context/base/math-noa.lua
+++ b/Master/texmf-dist/tex/context/base/math-noa.lua
@@ -15,6 +15,9 @@ if not modules then modules = { } end modules ['math-noa'] = {
-- beware: names will change as we wil make noads.xxx.handler i.e. xxx
-- subnamespaces
+-- 20D6 -> 2190
+-- 20D7 -> 2192
+
local utf = unicode.utf8
local utfchar, utfbyte = utf.char, utf.byte
@@ -31,18 +34,43 @@ local trace_remapping = false trackers.register("math.remapping", functio
local trace_processing = false trackers.register("math.processing", function(v) trace_processing = v end)
local trace_analyzing = false trackers.register("math.analyzing", function(v) trace_analyzing = v end)
local trace_normalizing = false trackers.register("math.normalizing", function(v) trace_normalizing = v end)
+local trace_collapsing = false trackers.register("math.collapsing", function(v) trace_collapsing = v end)
+local trace_goodies = false trackers.register("math.goodies", function(v) trace_goodies = v end)
+local trace_variants = false trackers.register("math.variants", function(v) trace_variants = v end)
+local trace_italics = false trackers.register("math.italics", function(v) trace_italics = v end)
+local trace_families = false trackers.register("math.families", function(v) trace_families = v end)
+
+local check_coverage = true directives.register("math.checkcoverage", function(v) check_coverage = v end)
local report_processing = logs.reporter("mathematics","processing")
local report_remapping = logs.reporter("mathematics","remapping")
local report_normalizing = logs.reporter("mathematics","normalizing")
+local report_collapsing = logs.reporter("mathematics","collapsing")
+local report_goodies = logs.reporter("mathematics","goodies")
+local report_variants = logs.reporter("mathematics","variants")
+local report_italics = logs.reporter("mathematics","italics")
+local report_families = logs.reporter("mathematics","families")
local set_attribute = node.set_attribute
local has_attribute = node.has_attribute
local mlist_to_hlist = node.mlist_to_hlist
local font_of_family = node.family_font
+local insert_node_after = node.insert_after
+local free_node = node.free
+local new_node = node.new -- todo: pool: math_noad math_sub
+
+local new_kern = nodes.pool.kern
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
+local fontcharacters = fonthashes.characters
+local fontproperties = fonthashes.properties
+local fontitalics = fonthashes.italics
+local fontquads = fonthashes.quads
+
+local variables = interfaces.variables
+local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
noads = noads or { } -- todo: only here
local noads = noads
@@ -97,9 +125,13 @@ local function process(start,what,n,parent)
end
local proc = what[id]
if proc then
- local done, newstart = proc(start,what,n,parent or start.prev)
+ -- report_processing("start processing")
+ local done, newstart = proc(start,what,n,parent) -- prev is bugged: or start.prev
if newstart then
start = newstart
+ -- report_processing("stop processing (new start)")
+ else
+ -- report_processing("stop processing")
end
elseif id == math_char or id == math_textchar or id == math_delim then
break
@@ -110,7 +142,8 @@ local function process(start,what,n,parent)
noad = start.sup if noad then process(noad,what,n,start) end -- list
noad = start.sub if noad then process(noad,what,n,start) end -- list
elseif id == math_box or id == math_sub then
- local noad = start.list if noad then process(noad,what,n,start) end -- list
+ -- local noad = start.list if noad then process(noad,what,n,start) end -- list
+ local noad = start.head if noad then process(noad,what,n,start) end -- list
elseif id == math_fraction then
local noad = start.num if noad then process(noad,what,n,start) end -- list
noad = start.denom if noad then process(noad,what,n,start) end -- list
@@ -142,7 +175,17 @@ local function process(start,what,n,parent)
end
end
-noads.process = process
+local function processnoads(head,actions,banner)
+ if trace_processing then
+ report_processing("start '%s'",banner)
+ process(head,actions)
+ report_processing("stop '%s'",banner)
+ else
+ process(head,actions)
+ end
+end
+
+noads.process = processnoads
-- character remapping
@@ -158,34 +201,30 @@ end
local remapalphabets = mathematics.remapalphabets
local setnodecolor = nodes.tracers.colors.set
--- we can have a global famdata == fonts.famdata
-
--~ This does not work out well, as there are no fallbacks. Ok, we could
--~ define a poor mans simplify mechanism.
---~
---~ local function checked(pointer)
---~ local char = pointer.char
---~ local fam = pointer.fam
---~ local id = font_of_family(fam)
---~ local tfmdata = fontdata[id]
---~ local tc = tfmdata and tfmdata.characters
---~ if not tc[char] then
---~ local specials = characters.data[char].specials
---~ if specials and (specials[1] == "char" or specials[1] == "font") then
---~ newchar = specials[#specials]
---~ if trace_remapping then
---~ report_remap("fallback",id,char,newchar)
---~ end
---~ if trace_analyzing then
---~ setnodecolor(pointer,"font:isol")
---~ end
---~ pointer.char = newchar
---~ return true
---~ end
---~ end
---~ end
-local current_id, current_characters
+local function checked(pointer)
+ local char = pointer.char
+ local fam = pointer.fam
+ local id = font_of_family(fam)
+ local tc = fontcharacters[id]
+ if not tc[char] then
+ local specials = characters.data[char].specials
+ if specials and (specials[1] == "char" or specials[1] == "font") then
+ newchar = specials[#specials]
+ if trace_remapping then
+ report_remap("fallback",id,char,newchar)
+ end
+ if trace_analyzing then
+ setnodecolor(pointer,"font:isol")
+ end
+ set_attribute(pointer,exportstatus,char) -- testcase: exponentiale
+ pointer.char = newchar
+ return true
+ end
+ end
+end
processors.relocate[math_char] = function(pointer)
local g = has_attribute(pointer,mathgreek) or 0
@@ -202,15 +241,8 @@ processors.relocate[math_char] = function(pointer)
if newchar then
local fam = pointer.fam
local id = font_of_family(fam)
- --
- local tfmdata = fontdata[id]
- if tfmdata and tfmdata.characters[newchar] then
- -- -- to be tested:
- -- if id ~= current_id then
- -- current_id = id
- -- current_characters = fontdata[id].characters
- -- end
- -- if current_characters and current_characters[newchar] then
+ local characters = fontcharacters[id]
+ if characters and characters[newchar] then
if trace_remapping then
report_remap("char",id,char,newchar)
end
@@ -219,18 +251,19 @@ processors.relocate[math_char] = function(pointer)
end
pointer.char = newchar
return true
- elseif trace_remapping then
- report_remap("char",id,char,newchar," fails")
+ else
+ if trace_remapping then
+ report_remap("char",id,char,newchar," fails")
+ end
end
- else
- -- return checked(pointer)
end
- else
- -- return checked(pointer)
end
if trace_analyzing then
setnodecolor(pointer,"font:medi")
end
+ if check_coverage then
+ return checked(pointer)
+ end
end
processors.relocate[math_textchar] = function(pointer)
@@ -246,7 +279,41 @@ processors.relocate[math_delim] = function(pointer)
end
function handlers.relocate(head,style,penalties)
- process(head,processors.relocate)
+ processnoads(head,processors.relocate,"relocate")
+ return true
+end
+
+-- rendering (beware, not exported)
+
+local a_mathrendering = attributes.private("mathrendering")
+local a_exportstatus = attributes.private("exportstatus")
+
+processors.render = { }
+
+local rendersets = mathematics.renderings.numbers or { } -- store
+
+processors.render[math_char] = function(pointer)
+ local attr = has_attribute(pointer,a_mathrendering)
+ if attr and attr > 0 then
+ local char = pointer.char
+ local renderset = rendersets[attr]
+ if renderset then
+ local newchar = renderset[char]
+ if newchar then
+ local fam = pointer.fam
+ local id = font_of_family(fam)
+ local characters = fontcharacters[id]
+ if characters and characters[newchar] then
+ pointer.char = newchar
+ set_attribute(pointer,a_exportstatus,char)
+ end
+ end
+ end
+ end
+end
+
+function handlers.render(head,style,penalties)
+ processnoads(head,processors.render,"render")
return true
end
@@ -281,7 +348,7 @@ resize[math_fence] = function(pointer)
end
function handlers.resize(head,style,penalties)
- process(head,resize)
+ processnoads(head,resize,"resize")
return true
end
@@ -295,8 +362,9 @@ local chardata = characters.data
-- only [nd,ll,ul][po][nd,ll,ul]
-respace[math_noad] = function(pointer)
- if pointer.subtype == noad_ord then
+respace[math_char] = function(pointer,what,n,parent) -- not math_noad .. math_char ... and then parent
+ pointer = parent
+ if pointer and pointer.subtype == noad_ord then
local a = has_attribute(pointer,mathpunctuation)
if a and a > 0 then
set_attribute(pointer,mathpunctuation,0)
@@ -322,14 +390,14 @@ respace[math_noad] = function(pointer)
local lc = chardata[last_char]
lc = lc and lc.category
if lc == "nd" or lc == "ll" or lc == "lu" then
- local ord = node.new(math_noad) -- todo: pool
+ local ord = new_node(math_noad) -- todo: pool
ord.subtype, ord.nucleus, ord.sub, ord.sup, ord.attr = noad_ord, next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr
-- next_noad.nucleus, next_noad.sub, next_noad.sup, next_noad.attr = nil, nil, nil, nil
next_noad.nucleus, next_noad.sub, next_noad.sup = nil, nil, nil -- else crash with attributes ref count
--~ next_noad.attr = nil
ord.next = last_noad
pointer.next = ord
- node.free(next_noad)
+ free_node(next_noad)
end
end
end
@@ -343,7 +411,7 @@ respace[math_noad] = function(pointer)
end
function handlers.respace(head,style,penalties)
- process(head,respace)
+ processnoads(head,respace,"respace")
return true
end
@@ -357,34 +425,50 @@ local collapse = { } processors.collapse = collapse
local mathpairs = characters.mathpairs
-collapse[math_noad] = function(pointer)
- if pointer.subtype == noad_rel then
- local current_nucleus = pointer.nucleus
- if current_nucleus.id == math_char then
- local current_char = current_nucleus.char
- local mathpair = mathpairs[current_char]
- if mathpair then
- local next_noad = pointer.next
- if next_noad and next_noad.id == math_noad and next_noad.subtype == noad_rel then
- local next_nucleus = next_noad.nucleus
- if next_nucleus.id == math_char then
- local next_char = next_nucleus.char
- local newchar = mathpair[next_char]
- if newchar then
- local fam = current_nucleus.fam
- local id = font_of_family(fam)
- local tfmdata = fontdata[id]
- if tfmdata and tfmdata.characters[newchar] then
- -- print("!!!!!",current_char,next_char,newchar)
- current_nucleus.char = newchar
- local next_next_noad = next_noad.next
- if next_next_noad then
- pointer.next = next_next_noad
- next_next_noad.prev = pointer
- else
- pointer.next = nil
+mathpairs[0x2032] = { [0x2032] = 0x2033, [0x2033] = 0x2034 } -- (prime,prime) (prime,doubleprime)
+mathpairs[0x2033] = { [0x2032] = 0x2034 } -- (doubleprime,prime)
+
+local function collapsepair(pointer,what,n,parent) -- todo: switch to turn in on and off
+ if parent then
+ local subtype = parent.subtype
+ if subtype == noad_rel or subtype == noad_ord then -- ord is new
+ local current_nucleus = parent.nucleus
+ if not parent.sub and not parent.sup and current_nucleus.id == math_char then
+ local current_char = current_nucleus.char
+ local mathpair = mathpairs[current_char]
+ if mathpair then
+ local next_noad = parent.next
+ if next_noad and next_noad.id == math_noad then
+ local next_subtype = next_noad.subtype
+ if next_subtype == noad_rel or next_subtype == noad_ord then -- ord is new
+ local next_nucleus = next_noad.nucleus
+ if next_nucleus.id == math_char then
+ local next_char = next_nucleus.char
+ local newchar = mathpair[next_char]
+ if newchar then
+ local fam = current_nucleus.fam
+ local id = font_of_family(fam)
+ local characters = fontcharacters[id]
+ if characters and characters[newchar] then
+ if trace_collapsing then
+ report_collapsing("U+%05X + U+%05X => U+%05X",current_char,next_char,newchar)
+ end
+ current_nucleus.char = newchar
+ local next_next_noad = next_noad.next
+ if next_next_noad then
+ parent.next = next_next_noad
+ next_next_noad.prev = parent
+ else
+ parent.next = nil
+ end
+ parent.sup = next_noad.sup
+ parent.sub = next_noad.sub
+ next_noad.sup = nil
+ next_noad.sub = nil
+ free_node(next_noad)
+ collapsepair(pointer,what,n,parent)
+ end
end
- node.free(next_noad)
end
end
end
@@ -394,8 +478,10 @@ collapse[math_noad] = function(pointer)
end
end
+collapse[math_char] = collapsepair
+
function noads.handlers.collapse(head,style,penalties)
- process(head,collapse)
+ processnoads(head,collapse,"collapse")
return true
end
@@ -408,7 +494,8 @@ local subscripts = characters.subscripts
local replaced = { }
-local function replace(pointer)
+local function replace(pointer,what,n,parent)
+ pointer = parent -- we're following the parent list (chars trigger this)
local next = pointer.next
local start_super, stop_super, start_sub, stop_sub
local mode = "unset"
@@ -459,7 +546,7 @@ local function replace(pointer)
if start_super == stop_super then
pointer.sup = start_super.nucleus
else
- local list = node.new(math_sub) -- todo attr
+ local list = new_node(math_sub) -- todo attr
list.head = start_super
pointer.sup = list
end
@@ -472,7 +559,7 @@ local function replace(pointer)
if start_sub == stop_sub then
pointer.sub = start_sub.nucleus
else
- local list = node.new(math_sub) -- todo attr
+ local list = new_node(math_sub) -- todo attr
list.head = start_sub
pointer.sub = list
end
@@ -481,15 +568,13 @@ local function replace(pointer)
end
stop_sub.next = nil
end
+ -- we could return stop
end
- unscript[math_noad] = replace
--- unscript[math_accent] = replace
--- unscript[math_radical] = replace
--- unscript[math_fraction] = replace
+unscript[math_char] = replace -- not noads as we need to recurse
function handlers.unscript(head,style,penalties)
- process(head,unscript)
+ processnoads(head,unscript,"unscript")
return true
end
@@ -504,7 +589,8 @@ statistics.register("math script replacements", function()
end
end)
--- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$)
+-- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$)
+-- math alternates: (in lucidanova lgf: $ABC \mathalternate{italic} ABC$)
local function initializemathalternates(tfmdata)
local goodies = tfmdata.goodies
@@ -516,6 +602,9 @@ local function initializemathalternates(tfmdata)
local mathgoodies = goodies[i].mathematics
local alternates = mathgoodies and mathgoodies.alternates
if alternates then
+ if trace_goodies then
+ report_goodies("loading alternates for font '%s'",tfmdata.properties.name)
+ end
local lastattribute, attributes = 0, { }
for k, v in next, alternates do
lastattribute = lastattribute + 1
@@ -541,24 +630,24 @@ registerotffeature {
local getalternate = otf.getalternate
-local mathalternate = attributes.private("mathalternate")
+local a_mathalternate = attributes.private("mathalternate")
local alternate = { } -- processors.alternate = alternate
function mathematics.setalternate(fam,tag)
local id = font_of_family(fam)
local tfmdata = fontdata[id]
- local mathalternates = tfmdata.shared.mathalternates
+ local mathalternates = tfmdata.shared and tfmdata.shared.mathalternates
if mathalternates then
local m = mathalternates[tag]
- tex.attribute[mathalternate] = m and m.attribute or attributes.unsetvalue
+ tex.attribute[a_mathalternate] = m and m.attribute or unsetvalue
end
end
alternate[math_char] = function(pointer)
- local a = has_attribute(pointer,mathalternate)
+ local a = has_attribute(pointer,a_mathalternate)
if a and a > 0 then
- set_attribute(pointer,mathalternate,0)
+ set_attribute(pointer,a_mathalternate,0)
local tfmdata = fontdata[font_of_family(pointer.fam)] -- we can also have a famdata
local mathalternatesattributes = tfmdata.shared.mathalternatesattributes
if mathalternatesattributes then
@@ -572,7 +661,256 @@ alternate[math_char] = function(pointer)
end
function handlers.check(head,style,penalties)
- process(head,alternate)
+ processnoads(head,alternate,"check")
+ return true
+end
+
+-- experiment (when not present fall back to fam 0) -- needs documentation
+
+-- 0-2 regular
+-- 3-5 bold
+-- 6-8 pseudobold
+
+local families = { }
+local a_mathfamily = attributes.private("mathfamily")
+local boldmap = mathematics.boldmap
+
+local tracemap = { [0] =
+ "regular",
+ "regular",
+ "regular",
+ "bold",
+ "bold",
+ "bold",
+ "pseudobold",
+ "pseudobold",
+ "pseudobold",
+}
+
+families[math_char] = function(pointer)
+ if pointer.fam == 0 then
+ local a = has_attribute(pointer,a_mathfamily)
+ if a and a > 0 then
+ set_attribute(pointer,a_mathfamily,0)
+ if a > 5 then
+ local char = pointer.char
+ local bold = boldmap[char]
+ local newa = a - 3
+ if bold then
+ set_attribute(pointer,exportstatus,char)
+ pointer.char = bold
+ if trace_families then
+ report_families("replacing U+%05X by bold U+%05X, family %s (%s) becomes %s (%s)",
+ char,bold,a,tracemap[a],newa,tracemap[newa])
+ end
+ else
+ if trace_families then
+ report_families("no bold replacement for U+%05X, family %s (%s) becomes %s (%s)",
+ char,a,tracemap[a],newa,tracemap[newa])
+ end
+ end
+ pointer.fam = newa
+ else
+ if trace_families then
+ report_families("family of U+%05X becomes %s (%s)",
+ pointer.char,a,tracemap[a])
+ end
+ pointer.fam = a
+ end
+ else
+ -- pointer.fam = 0
+ end
+ end
+end
+
+families[math_delim] = function(pointer)
+ if pointer.small_fam == 0 then
+ local a = has_attribute(pointer,a_mathfamily)
+ if a and a > 0 then
+ set_attribute(pointer,a_mathfamily,0)
+ if a > 5 then
+ -- no bold delimiters in unicode
+ a = a - 3
+ end
+ pointer.small_fam = a
+ pointer.large_fam = a
+ else
+ pointer.small_fam = 0
+ pointer.large_fam = 0
+ end
+ end
+end
+
+families[math_textchar] = families[math_char]
+
+function handlers.families(head,style,penalties)
+ processnoads(head,families,"families")
+ return true
+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)
+
+local a_mathitalics = attributes.private("mathitalics")
+
+local italics = { }
+local default_factor = 1/20
+
+italics[math_char] = function(pointer,what,n,parent)
+ local method = has_attribute(pointer,a_mathitalics)
+ if method and method > 0 then
+ local char = pointer.char
+ local font = font_of_family(pointer.fam) -- todo: table
+ local correction
+ if method == 1 then
+ -- only font data triggered by fontitalics
+ local italics = fontitalics[font]
+ if italics then
+ local character = fontcharacters[font][char]
+ correction = character and character.italic_correction -- or character.italic (this one is for tex)
+ end
+ elseif method == 2 then
+ -- only font data triggered by fontdata
+ local character = fontcharacters[font][char]
+ correction = character and character.italic_correction -- or character.italic (this one is for tex)
+ elseif method == 3 then
+ -- only quad based by selective
+ local visual = chardata[char].visual
+ if not visual then
+ -- skip
+ elseif visual == "it" or visual == "bi" then
+ correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontquads[font]
+ end
+ elseif method == 4 then
+ -- combination of 1 and 3
+ local italics = fontitalics[font]
+ if italics then
+ local character = fontcharacters[font][char]
+ correction = character and character.italic_correction -- or character.italic (this one is for tex)
+ end
+ if not correction then
+ local visual = chardata[char].visual
+ if not visual then
+ -- skip
+ elseif visual == "it" or visual == "bi" then
+ correction = fontproperties[font].mathitalic_defaultvalue or default_factor*fontquads[font]
+ end
+ end
+ end
+ if correction and correction ~= 0 then
+ local next_noad = parent.next
+ if next_noad and next_noad.id == math_noad then
+ local next_subtype = next_noad.subtype
+ if next_subtype == noad_punct or next_subtype == noad_ord then
+ local next_nucleus = next_noad.nucleus
+ if next_nucleus.id == math_char then
+ local next_char = next_nucleus.char
+ if not chardata[next_char].italic then -- or category
+ if trace_italics then
+ report_italics("method %s: adding %s italic correction between %s (0x%05X) and %s (0x%05X)",
+ method,number.points(correction),utfchar(char),char,utfchar(next_char),next_char)
+ end
+ insert_node_after(parent,parent,new_kern(correction))
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+function handlers.italics(head,style,penalties)
+ processnoads(head,italics,"italics")
+ return true
+end
+
+local enable
+
+enable = function()
+ tasks.enableaction("math", "noads.handlers.italics")
+ if trace_italics then
+ report_italics("enabling math italics")
+ end
+ enable = false
+end
+
+-- best do this only on math mode (less overhead)
+
+function mathematics.setitalics(n)
+ if enable then
+ enable()
+ end
+ if n == variables.reset then
+ texattribute[a_mathitalics] = unsetvalue
+ else
+ texattribute[a_mathitalics] = tonumber(n) or unsetvalue
+ end
+end
+
+function mathematics.resetitalics()
+ texattribute[a_mathitalics] = unsetvalue
+end
+
+-- variants
+
+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[math_char] = function(pointer,what,n,parent) -- also set export value
+ local char = pointer.char
+ local selector = validvariants[char]
+ if selector then
+ local next = parent.next
+ if next and next.id == math_noad then
+ local nucleus = next.nucleus
+ if nucleus and nucleus.id == math_char and nucleus.char == selector then
+ local variant
+ local tfmdata = fontdata[font_of_family(pointer.fam)] -- we can also have a famdata
+ local mathvariants = tfmdata.resources.variants -- and variantdata
+ if mathvariants then
+ mathvariants = mathvariants[selector]
+ if mathvariants then
+ variant = mathvariants[char]
+ end
+ end
+ if variant then
+ pointer.char = variant
+ set_attribute(pointer,exportstatus,char) -- we don't export the variant as it's visual markup
+ if trace_variants then
+ report_variants("variant (U+%05X,U+%05X) replaced by U+%05X",char,selector,variant)
+ end
+ else
+ if trace_variants then
+ report_variants("no variant (U+%05X,U+%05X)",char,selector)
+ end
+ end
+ next.prev = pointer
+ parent.next = next.next
+ free_node(next)
+ end
+ end
+ end
+end
+
+function handlers.variants(head,style,penalties)
+ processnoads(head,variants,"unicode variant")
return true
end
@@ -596,12 +934,13 @@ end
tasks.new {
name = "math",
arguments = 2,
+ processor = utilities.sequencers.nodeprocessor,
sequence = {
"before",
"normalizers",
"builders",
"after",
- }
+ },
}
tasks.freezegroup("math", "normalizers") -- experimental
@@ -625,3 +964,9 @@ callbacks.register('mlist_to_hlist',processors.mlist_to_hlist,"preprocessing mat
statistics.register("math processing time", function()
return statistics.elapsedseconds(noads)
end)
+
+-- interface
+
+commands.setmathalternate = mathematics.setalternate
+commands.setmathitalics = mathematics.setitalics
+commands.resetmathitalics = mathematics.resetitalics
diff --git a/Master/texmf-dist/tex/context/base/math-pln.mkii b/Master/texmf-dist/tex/context/base/math-pln.mkii
index f2f3ff183c1..975869c702c 100644
--- a/Master/texmf-dist/tex/context/base/math-pln.mkii
+++ b/Master/texmf-dist/tex/context/base/math-pln.mkii
@@ -5,7 +5,7 @@
%D subtitle=Plain Helpers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-pln.mkiv b/Master/texmf-dist/tex/context/base/math-pln.mkiv
index 6deac5efb9e..b862bb4cb40 100644
--- a/Master/texmf-dist/tex/context/base/math-pln.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-pln.mkiv
@@ -5,150 +5,52 @@
%D subtitle=Plain Helpers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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 a temporary module, some of this code will move to
-%D the other math modules. Much is copied from Plain \TEX.
-
-% \points should become \bodyfontsize
+%D Here we collect some Plain \TEX\ leftovers.
\writestatus{loading}{ConTeXt Math Macros / Plain Helpers}
\unprotect
-\ifx\displ@y\undefined \let\displ@y\relax\fi
+% we need proper unicode:
+
+\def\relbar{\mathrel{\smash-}} % - has the same height as + .. no clue what this refers to
+
+% might change
+
+\unexpanded\def\hrulefill{\leaders\hrule\hfill}
+\unexpanded\def\dotfill {\cleaders\hbox{$\mathsurround\zeropoint\mkern1.5mu.\mkern1.5mu$}\hfill}
+
+% will move
\def\oalign#1%
{\leavevmode
\vtop
- {\baselineskip\zeroskip \lineskip.25ex%
+ {\baselineskip\zeroskip
+ \lineskip.25\exheight
\ialign{##\crcr#1\crcr}}}
-\def\o@lign
- {\lineskiplimit\zeropoint \oalign}
-
\def\ooalign % chars over each other
{\lineskiplimit-\maxdimen
\oalign}
-\def\sh@ft#1% kern by #1 times the current slant
- {\dimen@#1%
- \kern\expandafter\withoutpt\the\slantperpoint
- \dimen@}
-
-\def\dots
- {\relax\ifmmode\ldots\else$\mathsurround\zeropoint\ldots\,$\fi}
-
-\def\hrulefill
- {\leaders\hrule\hfill}
-
-\def\dotfill
- {\cleaders\hbox{$\mathsurround\zeropoint \mkern1.5mu.\mkern1.5mu$}\hfill}
-
-\def\rightarrowfill
- {$\mathsurround\zeropoint\smash-\mkern-7mu%
- \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
- \mkern-7mu\mathord\rightarrow$}
-
-\def\leftarrowfill
- {$\mathsurround\zeropoint\mathord\leftarrow\mkern-7mu%
- \cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
- \mkern-7mu\smash-$}
-
-% \let\sp=^ % obsolete
-% \let\sb=_ % obsolete
-
-\ifx\,\undefined \def\,{\mskip \thinmuskip } \fi
-\ifx\>\undefined \def\>{\mskip \medmuskip } \fi
-\ifx\;\undefined \def\;{\mskip \thickmuskip} \fi
-\ifx\!\undefined \def\!{\mskip-\thinmuskip } \fi
-\ifx\*\undefined \def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi
-
-{ \catcode\circumflexasciicode\othercatcode \global\let\othercircumflextoken ^ }
-{ \catcode\circumflexasciicode\superscriptcatcode \global\let\superscriptcircumflextoken^ }
-
-\def\domathprime{^\bgroup\dodomathprime}
-
-\def\dodomathprime
- {\prime\futurelet\nexttoken\dododomathprime}
-
-\def\dododomathprime
- {\csname domathprime@%
- \ifx '\nexttoken a\else
- \ifx\superscriptcircumflextoken\nexttoken b\else
- \ifx\othercircumflextoken \nexttoken b\else
- c\fi\fi\fi
- \endcsname}
-
-\def\domathprime@a #1{\dodomathprime}
-\def\domathprime@b#1#2{#2\egroup}
-\def\domathprime@c {\egroup}
-
-\let\activemathprime\domathprime
-
-% {\catcode`\_=\active \global\let_=\_} % _ in math is either subscript or \_
-
-\let\activemathunderscore\_
-
-\def\relbar {\mathrel{\smash-}} % - has the same height as +
-\def\Relbar {\mathrel=}
-
-\def\Longrightarrow {\Relbar\joinrel\Rightarrow} % beware, this overloades cambria native
-\def\longrightarrow {\relbar\joinrel\rightarrow}
-\def\longleftarrow {\leftarrow\joinrel\relbar}
-\def\Longleftarrow {\Leftarrow\joinrel\Relbar}
-\def\longmapsto {\mapstochar\longrightarrow}
-\def\longleftrightarrow{\leftarrow\joinrel\rightarrow}
-\def\Longleftrightarrow{\Leftarrow\joinrel\Rightarrow}
+% needs checking
\def\choose{\atopwithdelims()}
\def\brack {\atopwithdelims[]}
\def\brace {\atopwithdelims\{\}}
-\def\mathpalette#1#2%
- {\mathchoice
- {#1\displaystyle {#2}}%
- {#1\textstyle {#2}}%
- {#1\scriptstyle {#2}}%
- {#1\scriptscriptstyle{#2}}}
-
-\def\cong
- {\mathrel{\mathpalette\@vereq\sim}} % congruence sign
-
-\def\@vereq#1#2%
- {\lower.5\points\vbox{\lineskiplimit\maxdimen\lineskip-.5\points
- \ialign{$\mathsurround\zeropoint#1\hfil##\hfil$\crcr#2\crcr=\crcr}}}
+% needs checking
-\def\notin
- {\mathrel{\mathpalette\c@ncel\in}}
-
-\def\c@ncel#1#2%
- {\mathsurround\zeropoint\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
-
-\def\rightleftharpoons
- {\mathrel{\mathpalette\rlh@{}}}
-
-\def\rlh@#1%
- {\vcenter
- {\mathsurround\zeropoint
- \hbox
- {\ooalign
- {\raise2pt\hbox{$#1\rightharpoonup$}\crcr
- $#1\leftharpoondown$}}}}
-
-\def\buildrel#1\over#2%
+\unexpanded\def\buildrel#1\over#2%
{\mathrel{\mathop{\kern\zeropoint#2}\limits^{#1}}}
-\def\doteq
- {\buildrel\textstyle.\over=}
-
-\ifx\mfunction\undefined \def\mfunction#1{\mathbin{\rm#1}} \fi
-
-\def\bmod
+\unexpanded\def\bmod
{\nonscript
\mskip-\medmuskip
\mkern5mu
@@ -158,130 +60,46 @@
\nonscript
\mskip-\medmuskip}
-\def\pmod#1%
+\unexpanded\def\pmod#1%
{\allowbreak
\mkern18mu
- (\mfunction{mod}\,\,#1)}
+ (\mfunction{mod}\mskip\medmuskip#1)}
-\def\cases#1%
+\unexpanded\def\cases#1%
{\left\{%
- \,%
+ \mskip\thinmuskip
\vcenter
{\normalbaselines
\mathsurround\zeropoint
\ialign{$##\hfil$&\quad##\hfil\crcr#1\crcr}}%
\right.}
-\def\matrix#1%
+\unexpanded\def\matrix#1%
{\emptyhbox
- \,%
+ \mskip\thinmuskip
\vcenter
{\normalbaselines\mathsurround\zeropoint
\ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
\mathstrut\crcr\noalign{\kern-\baselineskip}
#1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}%
- \,}
+ \mskip\thinmuskip}
-\def\pmatrix#1%
+\unexpanded\def\pmatrix#1%
{\left(\matrix{#1}\right)}
-\newdimen\mathparentwd
-
-% \setbox0=\hbox{\tenex B} \mathparentwd=\wd0 % width of the big left (
+\unexpanded\def\openup
+ {\afterassignment\math_openup\scratchdimen=}
-\def\bordermatrix#1%
- {\begingroup
- \mathsurround\zeropoint
- \setbox\zerocount\vbox
- {\def\cr{\crcr\noalign{\kern2\points\global\let\cr\endline}}%
- \ialign{$##$\hfil\kern2\points\kern\mathparentwd&\thinspace\hfil$##$\hfil
- &&\quad\hfil$##$\hfil\crcr
- \omit\strut\hfil\crcr\noalign{\kern-\baselineskip}%
- #1\crcr\omit\strut\cr}}%
- \setbox\plustwo\vbox
- {\unvcopy\zerocount\global\setbox\plusone\lastbox}%
- \setbox\plustwo\hbox
- {\unhbox\plusone\unskip\global\setbox\plusone\lastbox}%
- \setbox\plustwo\hbox
- {$\kern\wd\plusone\kern-\mathparentwd\left(\kern-\wd\plusone
- \global\setbox\plusone\vbox{\box\plusone\kern2\points}%
- \vcenter{\kern-\ht\plusone\unvbox\zerocount\kern-\baselineskip}\,\right)$}%
- \emptyhbox
- \;%
- \vbox{\kern\ht\plusone\box\plustwo}%
- \endgroup}
-
-% \def\openup{\afterassignment\@penup\dimen@=}
-%
-% \def\@penup{\advance\lineskip\dimen@
-% \advance\baselineskip\dimen@
-% \advance\lineskiplimit\dimen@}
-
-\def\openup
- {\afterassignment\doopenup\scratchdimen=}
-
-\def\doopenup
+\def\math_openup
{\advance\lineskip \scratchdimen
\advance\baselineskip \scratchdimen
\advance\lineskiplimit\scratchdimen}
-% \def\jot{.25\bodyfontsize} % plain tex: 3 pt (todo: better name and configurable)
-
-\def\displayopenupvalue{.25\bodyfontsize}
-
-\def\eqalign#1%
- {\emptyhbox
- \,%
- \vcenter
- {\openup\displayopenupvalue % was \openup\jot
- \mathsurround\zeropoint
- \ialign
- {\strut\hfil$\displaystyle{##}$&$\displaystyle{{}##}$\hfil\crcr
- #1\crcr}}%
- \,}
-
-\def\@lign % restore inside \displ@y
- {\tabskip\zeroskip
- \everycr{}}
-
-\def\displaylines#1%
- {\displ@y
+\unexpanded\def\displaylines#1%
+ {\the\mathdisplayaligntweaks
\tabskip\zeroskip
\halign
- {\hbox to \displaywidth{$\@lign\hfil\displaystyle##\hfil$}\crcr
- #1\crcr}}
-
-\def\eqalignno#1%
- {\displ@y
- \tabskip\centering
- \halign to \displaywidth
- {\hfil$\@lign\displaystyle{##}$\tabskip\zeroskip
- &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
- &\llap{$\@lign##$}\tabskip\zeroskip\crcr
+ {\hbox to \displaywidth{$\tabskip\zeroskip\everycr\emptytoks\hfil\displaystyle##\hfil$}\crcr
#1\crcr}}
-\def\leqalignno#1%
- {\displ@y
- \tabskip\centering
- \halign to \displaywidth
- {\hfil$\@lign\displaystyle{##}$\tabskip\zeroskip
- &$\@lign\displaystyle{{}##}$\hfil\tabskip\centering
- &\kern-\displaywidth\rlap{$\@lign##$}\tabskip\displaywidth\crcr
- #1\crcr}}
-
-% temporary here (weird code)
-
-% \startcatcodetable \mthcatcodes
-% \setcatcodetable\ctxcatcodes
-% \catcode`\_ = 13
-% \catcode`\' = 13
-% \stopcatcodetable
-%
-% \letcatcodecommand \mthcatcodes `\_ \activemathunderscore
-% \letcatcodecommand \mthcatcodes `\' \activemathquote
-
-% \appendtoks \setcatcodetable\mthcatcodes \to \everymath : spoils xml
-
-% so far
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/math-ren.lua b/Master/texmf-dist/tex/context/base/math-ren.lua
new file mode 100644
index 00000000000..2e7dba13df9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/math-ren.lua
@@ -0,0 +1,69 @@
+if not modules then modules = { } end modules ['math-ren'] = {
+ version = 1.001,
+ comment = "companion to math-ren.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local next = next
+local gsub = string.gsub
+
+local settings_to_array = utilities.parsers.settings_to_array
+local allocate = storage.allocate
+
+local renderings = { }
+mathematics.renderings = renderings
+
+local mappings = allocate()
+renderings.mappings = mappings
+
+local numbers = allocate()
+renderings.numbers = numbers
+
+local sets = allocate()
+renderings.sets = sets
+
+mappings["blackboard-to-bold"] = {
+ [0x1D538] = 0x1D400, [0x1D539] = 0x1D401, [0x02102] = 0x1D402, [0x1D53B] = 0x1D403, [0x1D53C] = 0x1D404,
+ [0x1D53D] = 0x1D405, [0x1D53E] = 0x1D406, [0x0210D] = 0x1D407, [0x1D540] = 0x1D408, [0x1D541] = 0x1D409,
+ [0x1D542] = 0x1D40A, [0x1D543] = 0x1D40B, [0x1D544] = 0x1D40C, [0x02115] = 0x1D40D, [0x1D546] = 0x1D40E,
+ [0x02119] = 0x1D40F, [0x0211A] = 0x1D410, [0x0211D] = 0x1D411, [0x1D54A] = 0x1D412, [0x1D54B] = 0x1D413,
+ [0x1D54C] = 0x1D414, [0x1D54D] = 0x1D415, [0x1D54E] = 0x1D416, [0x1D54F] = 0x1D417, [0x1D550] = 0x1D418,
+ [0x02124] = 0x1D419,
+}
+
+local function renderset(list) -- order matters
+ local tag = gsub(list," ","")
+ local n = sets[tag]
+ if not n then
+ local list = settings_to_array(tag)
+ local mapping = { }
+ for i=1,#list do
+ local m = mappings[list[i]]
+ if m then
+ for k, v in next, m do
+ mapping[k] = v
+ end
+ end
+ end
+ if next(mapping) then
+ n = #numbers + 1
+ numbers[n] = mapping
+ else
+ n = attributes.unsetvalue
+ end
+ sets[tag] = n
+ end
+ return n
+end
+
+mathematics.renderset = renderset
+
+function commands.mathrenderset(list)
+ context(renderset(list))
+end
+
+-- function commands.setmatrendering(list)
+-- tex.setattribute(renderset(list))
+-- end
diff --git a/Master/texmf-dist/tex/context/base/math-run.mkii b/Master/texmf-dist/tex/context/base/math-run.mkii
index 6bc4bf4d5d1..79d08fbedb1 100644
--- a/Master/texmf-dist/tex/context/base/math-run.mkii
+++ b/Master/texmf-dist/tex/context/base/math-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen \& Ton Otten]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-scr.mkiv b/Master/texmf-dist/tex/context/base/math-scr.mkiv
index e17ce42f375..2decaa81fc5 100644
--- a/Master/texmf-dist/tex/context/base/math-scr.mkiv
+++ b/Master/texmf-dist/tex/context/base/math-scr.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Scripts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -15,62 +15,45 @@
\unprotect
-%D These macros were first needed by Frits Spijker (also
-%D known as Gajes) for typesetting the minus sign that is
-%D keyed into scientific calculators.
+%D These macros were first needed by Frits (Gajes) Spijker
+%D (of the Math4All project that we participate in), and used
+%D for typesetting the minus sign that is keyed into scientific
+%D calculators. We use the monospaced signs, that we also define
+%D as symbol, so that they can be overloaded.
-% This is the first alternative, which works okay for the
-% minus, but less for the plus.
-%
-% \def\dodoraisedmathord#1#2#3%
-% {\mathord{{#2\raise.#1ex\hbox{#2#3}}}}
-%
-% \def\doraisedmathord#1%
-% {\mathchoice
-% {\dodoraisedmathord5\tf #1}%
-% {\dodoraisedmathord5\tf #1}%
-% {\dodoraisedmathord4\tfx #1}%
-% {\dodoraisedmathord3\tfxx#1}}
-%
-% \def\negative{\doraisedmathord-}
-% \def\positive{\doraisedmathord+}
-%
-% So, now we use the monospaced signs, that we also
-% define as symbol, so that they can be overloaded.
+\def\math_scripts_raised_symbol#1%
+ {\mathchoice
+ {\math_scripts_raised_symbol_indeed5\tf {#1}}%
+ {\math_scripts_raised_symbol_indeed5\tf {#1}}%
+ {\math_scripts_raised_symbol_indeed4\tx {#1}}%
+ {\math_scripts_raised_symbol_indeed3\txx{#1}}}
-\def\dodoraisedmathord#1#2#3%
+\def\math_scripts_raised_symbol_indeed#1#2#3%
{\mathord{{#2\raise.#1ex\hbox{#2\symbol[#3]}}}}
-\def\doraisedmathord#1%
+\def\math_scripts_raised_number#1%
{\mathchoice
- {\dodoraisedmathord5\tf {#1}}%
- {\dodoraisedmathord5\tf {#1}}%
- {\dodoraisedmathord4\tx {#1}}%
- {\dodoraisedmathord3\txx{#1}}}
+ {\math_scripts_raised_number_indeed\tf {#1}}%
+ {\math_scripts_raised_number_indeed\tf {#1}}%
+ {\math_scripts_raised_number_indeed\tx {#1}}%
+ {\math_scripts_raised_number_indeed\txx{#1}}}
-\def\dodonumbermathord#1#2%
+\def\math_scripts_raised_number_indeed#1#2%
{\setbox\scratchbox\hbox{0}%
\mathord{\hbox to \wd\scratchbox{\hss#1\symbol[#2]\hss}}}
-\def\donumbermathord#1%
- {\mathchoice
- {\dodonumbermathord\tf {#1}}%
- {\dodonumbermathord\tf {#1}}%
- {\dodonumbermathord\tx {#1}}%
- {\dodonumbermathord\txx{#1}}}
-
\definesymbol[positive] [\getglyph{Mono}{+}]
\definesymbol[negative] [\getglyph{Mono}{-}]
\definesymbol[zeroamount][\getglyph{Mono}{-}]
-\def\negative {\doraisedmathord{negative}}
-\def\positive {\doraisedmathord{positive}}
-\def\zeroamount{\donumbermathord{zeroamount}}
+\unexpanded\def\negative {\math_scripts_raised_symbol{negative}}
+\unexpanded\def\positive {\math_scripts_raised_symbol{positive}}
+\unexpanded\def\zeroamount{\math_scripts_raised_number{zeroamount}}
%D How negative such a symbol looks is demonstrated in:
%D $\negative 10^{\negative 10^{\negative 10}}$.
-\setuptextformulas % why here
- [\c!size=\v!normal]
+% \setuptextformulas % why here
+% [\c!size=\v!normal]
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/math-tag.lua b/Master/texmf-dist/tex/context/base/math-tag.lua
index e5ad30be06e..0ac5b08975e 100644
--- a/Master/texmf-dist/tex/context/base/math-tag.lua
+++ b/Master/texmf-dist/tex/context/base/math-tag.lua
@@ -6,6 +6,9 @@ if not modules then modules = { } end modules ['math-tag'] = {
license = "see context related readme files"
}
+local find, match = string.find, string.match
+local insert, remove = table.insert, table.remove
+
local attributes, nodes = attributes, nodes
local get_attribute = nodes.getattribute
@@ -31,27 +34,40 @@ local math_fence_code = nodecodes.fence -- attr subtype
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
local a_tagged = attributes.private('tagged')
+local a_exportstatus = attributes.private('exportstatus')
+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 chardata = characters.data
+
+local getmathcode = tex.getmathcode
+local mathcodes = mathematics.codes
+local ordinary_code = mathcodes.ordinary
+local variable_code = mathcodes.variable
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.
local nucleus, sup, sub = start.nucleus, start.sup, start.sub
if sub then
if sup then
set_attribute(start,a_tagged,start_tagged("msubsup"))
process(nucleus)
- process(sup)
process(sub)
+ process(sup)
stop_tagged()
else
set_attribute(start,a_tagged,start_tagged("msub"))
@@ -69,25 +85,52 @@ local function processsubsup(start)
end
end
+-- todo: check function here and keep attribute the same
+
+-- todo: variants -> original
+
+local actionstack = { }
+
process = function(start) -- we cannot use the processor as we have no finalizers (yet)
while start do
local id = start.id
if id == math_char_code then
+ local char = start.char
-- check for code
- local ch = chardata[start.char]
- local mc = ch and ch.mathclass
- if mc == "number" then
- set_attribute(start,a_tagged,start_tagged("mn"))
- elseif mc == "variable" or not mc then -- variable is default
- set_attribute(start,a_tagged,start_tagged("mi"))
+ local a = get_attribute(start,a_mathcategory)
+ if a then
+ a = { detail = a }
+ end
+ local code = getmathcode(char)
+ if code then
+ code = code[1]
+ end
+ local tag
+ if code == ordinary_code or code == variable_code 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
- set_attribute(start,a_tagged,start_tagged("mo"))
+ tag = "mo"
end
+-- print(start,a,tag)
+ set_attribute(start,a_tagged,start_tagged(tag,a))
stop_tagged()
- break
+ break -- okay?
elseif id == math_textchar_code then
-- check for code
- set_attribute(start,a_tagged,start_tagged("ms"))
+ local a = get_attribute(start,a_mathcategory)
+ if a then
+ set_attribute(start,a_tagged,start_tagged("ms"),{ detail = a })
+ else
+ set_attribute(start,a_tagged,start_tagged("ms"))
+ end
stop_tagged()
break
elseif id == math_delim_code then
@@ -102,29 +145,30 @@ process = function(start) -- we cannot use the processor as we have no finalizer
elseif id == math_box_code or id == hlist_code or id == vlist_code then
-- keep an eye on math_box_code and see what ends up in there
local attr = get_attribute(start,a_tagged)
- local text = start_tagged("mtext")
- set_attribute(start,a_tagged,text)
- local list = start.list
- if not list then
- -- empty list
- elseif not attr then
- -- box comes from strange place
- set_attributes(list,a_tagged,text)
+ local last = attr and taglist[attr]
+ if last and find(last[#last],"formulacaption[:%-]") then
+ -- leave alone, will nicely move to the outer level
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.
- local tagdata = taglist[attr]
- local common = #tagdata + 1
- local function runner(list) -- quite inefficient
- local cache = { } -- we can have nested unboxed mess so best local to runner
- for n in traverse_nodes(list) do
- local id = n.id
- if id == hlist_code or id == vlist_code then
- runner(n.list)
- elseif id == glyph_code then
- local aa = get_attribute(n,a_tagged) -- only glyph needed
+ local text = start_tagged("mtext")
+ set_attribute(start,a_tagged,text)
+ local list = start.list
+ if not list then
+ -- empty list
+ elseif not attr then
+ -- box comes from strange place
+ set_attributes(list,a_tagged,text)
+ 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.
+ local tagdata = taglist[attr]
+ local common = #tagdata + 1
+ local function runner(list) -- quite inefficient
+ local cache = { } -- we can have nested unboxed mess so best local to runner
+ for n in traverse_nodes(list) do
+ local id = n.id
+ local aa = get_attribute(n,a_tagged)
if aa then
local ac = cache[aa]
if not ac then
@@ -132,7 +176,7 @@ process = function(start) -- we cannot use the processor as we have no finalizer
local extra = #tagdata
if common <= extra then
for i=common,extra do
- ac = start_tagged(tagdata[i]) -- can be made faster
+ ac = restart_tagged(tagdata[i]) -- can be made faster
end
for i=common,extra do
stop_tagged() -- can be made faster
@@ -146,18 +190,38 @@ process = function(start) -- we cannot use the processor as we have no finalizer
else
set_attribute(n,a_tagged,text)
end
+ if id == hlist_code or id == vlist_code then
+ runner(n.list)
+ end
end
end
+ runner(list)
end
- runner(list)
+ stop_tagged()
end
- stop_tagged()
elseif id == math_sub_code then
local list = start.list
if list then
- set_attribute(start,a_tagged,start_tagged("mrow"))
- process(list)
- stop_tagged()
+ local attr = get_attribute(start,a_tagged)
+ local last = attr and taglist[attr]
+ local action = last and match(last[#last],"maction:(.-)%-")
+ if action and action ~= "" then
+ if actionstack[#actionstack] == action then
+ set_attribute(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ else
+ insert(actionstack,action)
+ set_attribute(start,a_tagged,start_tagged("mrow",{ detail = action }))
+ process(list)
+ stop_tagged()
+ remove(actionstack)
+ end
+ else
+ set_attribute(start,a_tagged,start_tagged("mrow"))
+ process(list)
+ stop_tagged()
+ end
end
elseif id == math_fraction_code then
local num, denom, left, right = start.num, start.denom, start.left, start.right
@@ -191,17 +255,40 @@ process = function(start) -- we cannot use the processor as we have no finalizer
end
elseif id == math_fence_code then
local delim = start.delim
- if delim then
- set_attribute(start,a_tagged,start_tagged("mo"))
- process(delim)
+ local subtype = start.subtype
+ if subtype == 1 then
+ -- left
+ set_attribute(start,a_tagged,start_tagged("mfenced"))
+ if delim then
+ set_attribute(start,a_tagged,start_tagged("mleft"))
+ process(delim)
+ stop_tagged()
+ end
+ elseif subtype == 2 then
+ -- middle
+ if delim then
+ set_attribute(start,a_tagged,start_tagged("mmiddle"))
+ process(delim)
+ stop_tagged()
+ end
+ elseif subtype == 3 then
+ if delim then
+ set_attribute(start,a_tagged,start_tagged("mright"))
+ process(delim)
+ stop_tagged()
+ end
stop_tagged()
+ else
+ -- can't happen
end
elseif id == math_radical_code then
local left, degree = start.left, start.degree
if left then
- process(left) -- mrow needed ?
+ start_tagged("")
+ process(left) -- root symbol, ignored
+ stop_tagged()
end
- if degree then
+ if degree then -- not good enough, can be empty mlist
set_attribute(start,a_tagged,start_tagged("mroot"))
processsubsup(start)
process(degree)
@@ -215,27 +302,30 @@ process = function(start) -- we cannot use the processor as we have no finalizer
local accent, bot_accent = start.accent, start.bot_accent
if bot_accent then
if accent then
- set_attribute(start,a_tagged,start_tagged("munderover"))
- process(accent)
+ set_attribute(start,a_tagged,start_tagged("munderover",{ detail = "accent" }))
processsubsup(start)
process(bot_accent)
+ process(accent)
stop_tagged()
else
- set_attribute(start,a_tagged,start_tagged("munder"))
+ set_attribute(start,a_tagged,start_tagged("munder",{ detail = "accent" }))
processsubsup(start)
process(bot_accent)
stop_tagged()
end
elseif accent then
- set_attribute(start,a_tagged,start_tagged("mover"))
- process(accent)
+ set_attribute(start,a_tagged,start_tagged("mover",{ detail = "accent" }))
processsubsup(start)
+ process(accent)
stop_tagged()
else
processsubsup(start)
end
+ elseif id == glue_code then
+ set_attribute(start,a_tagged,start_tagged("mspace"))
+ stop_tagged()
else
- set_attribute(start,a_tagged,start_tagged("merror"))
+ set_attribute(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] } ))
stop_tagged()
end
start = start.next
@@ -243,8 +333,12 @@ process = function(start) -- we cannot use the processor as we have no finalizer
end
function noads.handlers.tags(head,style,penalties)
- set_attribute(head,a_tagged,start_tagged("math"))
- set_attribute(head,a_tagged,start_tagged("mrow"))
+ local v_math = start_tagged("math")
+ local v_mrow = start_tagged("mrow")
+ local v_mode = get_attribute(head,a_mathmode)
+ set_attribute(head,a_tagged,v_math)
+ set_attribute(head,a_tagged,v_mrow)
+ tags.setattributehash(v_math,"mode",v_mode == 1 and "display" or "inline")
process(head)
stop_tagged()
stop_tagged()
diff --git a/Master/texmf-dist/tex/context/base/math-tex.mkii b/Master/texmf-dist/tex/context/base/math-tex.mkii
index 8f34a190e22..e3dd634e6ef 100644
--- a/Master/texmf-dist/tex/context/base/math-tex.mkii
+++ b/Master/texmf-dist/tex/context/base/math-tex.mkii
@@ -4,7 +4,7 @@
%D subtitle=Plain Specials,
%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-tim.mkii b/Master/texmf-dist/tex/context/base/math-tim.mkii
index 3b9aea1030e..da7d17e7ba6 100644
--- a/Master/texmf-dist/tex/context/base/math-tim.mkii
+++ b/Master/texmf-dist/tex/context/base/math-tim.mkii
@@ -5,7 +5,7 @@
%D subtitle=Mathtime Specials,
%D author={Hans Hagen \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/math-uni.mkii b/Master/texmf-dist/tex/context/base/math-uni.mkii
index e8fd3f05def..5c75a9fb44b 100644
--- a/Master/texmf-dist/tex/context/base/math-uni.mkii
+++ b/Master/texmf-dist/tex/context/base/math-uni.mkii
@@ -5,7 +5,7 @@
%D subtitle=unicode support,
%D author={Nikolai Weibull \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright=PRAGMA]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
\unprotect
diff --git a/Master/texmf-dist/tex/context/base/math-vfu.lua b/Master/texmf-dist/tex/context/base/math-vfu.lua
index 49bf00ffe92..c3f23416622 100644
--- a/Master/texmf-dist/tex/context/base/math-vfu.lua
+++ b/Master/texmf-dist/tex/context/base/math-vfu.lua
@@ -8,15 +8,22 @@ if not modules then modules = { } end modules ['math-vfu'] = {
-- All these math vectors .. thanks to Aditya and Mojca they become
-- better and better. If you have problems with math fonts or miss
--- characters report it to the ConTeXt mailing list.
+-- characters report it to the ConTeXt mailing list. Also thanks to
+-- Boguslaw for finding a couple of errors.
+
+-- 20D6 -> 2190
+-- 20D7 -> 2192
local type, next = type, next
local max = math.max
+local format = string.format
local fonts, nodes, mathematics = fonts, nodes, mathematics
-local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end)
-local trace_timings = false trackers.register("math.timings", function(v) trace_timings = v end)
+local trace_virtual = false trackers.register("math.virtual", function(v) trace_virtual = v end)
+local trace_timings = false trackers.register("math.timings", function(v) trace_timings = v end)
+
+local add_optional = false directives.register("math.virtual.optional",function(v) add_optional = v end)
local report_virtual = logs.reporter("fonts","virtual math")
@@ -28,8 +35,6 @@ fonts.encodings.math = mathencodings -- better is then: fonts.encodings.vecto
local vfmath = allocate()
fonts.handlers.vf.math = vfmath
-vfmath.optional = false
-
local shared = { }
--~ local push, pop, back = { "push" }, { "pop" }, { "slot", 1, 0x2215 }
@@ -85,12 +90,12 @@ local function arrow(main,characters,id,size,unicode,arrow,minus,isleft)
elseif isleft then
chr.horiz_variants = {
{ extender = 0, glyph = arrow },
- { extender = 1, glyph = minus },
+ { extender = 1, glyph = minus },
}
else
chr.horiz_variants = {
- { extender = 0, glyph = minus },
- { extender = 1, glyph = arrow },
+ { extender = 1, glyph = minus },
+ { extender = 0, glyph = arrow },
}
end
end
@@ -136,7 +141,7 @@ local function make(main,characters,id,size,n,m)
end
end
-local function minus(main,characters,id,size,unicode)
+local function minus(main,characters,id,size,unicode) -- push/pop needed?
local minus = characters[0x002D]
if minus then
local mu = size/18
@@ -148,6 +153,47 @@ local function minus(main,characters,id,size,unicode)
end
end
+-- fails: pdf:page: pdf:direct: ... some funny displacement
+
+-- this does not yet work ... { "scale", 2, 0, 0, 3 } .. commented code
+--
+-- this does not work ... no interpretation going on here
+--
+-- local nodeinjections = backends.nodeinjections
+-- { "node", nodeinjections.save() },
+-- { "node", nodeinjections.transform(.7,0,0,.7) },
+-- commands[#commands+1] = { "node", nodeinjections.restore() }
+
+local done = { }
+
+local function raise(main,characters,id,size,unicode,private,n) -- this is a real fake mess
+ local raised = characters[private]
+ if raised then
+ if not done[unicode] then
+ report_virtual("temporary too large U+%05X due to issues in luatex backend",unicode)
+ done[unicode] = true
+ end
+ local up = 0.85 * main.parameters.x_height
+ local slot = { "slot", id, private }
+ local commands = {
+ push,
+ { "down", - up },
+ -- { "scale", .7, 0, 0, .7 },
+ slot,
+ }
+ for i=2,n do
+ commands[#commands+1] = slot
+ end
+ commands[#commands+1] = pop
+ characters[unicode] = {
+ width = .7 * n * raised.width,
+ height = .7 * (raised.height + up),
+ depth = .7 * (raised.depth - up),
+ commands = commands,
+ }
+ end
+end
+
local function dots(main,characters,id,size,unicode)
local c = characters[0x002E]
if c then
@@ -313,8 +359,8 @@ function vfmath.addmissing(main,id,size)
dots (main,characters,id,size,0x22F1) -- ddots
dots (main,characters,id,size,0x22F0) -- udots
minus (main,characters,id,size,0xFF501)
- arrow (main,characters,id,size,0x2190,0xFE190,0xFF501,true) -- left
- arrow (main,characters,id,size,0x2192,0xFE192,0xFF501,false) -- right
+ arrow (main,characters,id,size,0x2190,0x2190,0xFF501,true) -- left
+ arrow (main,characters,id,size,0x2192,0x2192,0xFF501,false) -- right
vertbar (main,characters,id,size,0x0007C,0.10,0xFF601) -- big : 0.85 bodyfontsize
vertbar (main,characters,id,size,0xFF601,0.30,0xFF602) -- Big : 1.15 bodyfontsize
vertbar (main,characters,id,size,0xFF602,0.30,0xFF603) -- bigg : 1.45 bodyfontsize
@@ -340,6 +386,19 @@ function vfmath.addmissing(main,id,size)
jointwo (main,characters,id,size,0x27FA,0x021D0,joinrelfactor,0x021D2) -- \Leftarrow\joinrel\Rightarrow
jointhree(main,characters,id,size,0x27FB,0x02190,joinrelfactor,0x0002D,0,0xFE324) -- \leftarrow\joinrel\relbar\mapsfromchar
jointhree(main,characters,id,size,0x27FC,0xFE321,0,0x0002D,joinrelfactor,0x02192) -- \mapstochar\relbar\joinrel\rightarrow
+ jointwo (main,characters,id,size,0x2254,0x03A,0,0x03D) -- := (≔)
+
+ -- raise (main,characters,id,size,0x02032,0xFE325,1) -- prime
+ -- raise (main,characters,id,size,0x02033,0xFE325,2) -- double prime
+ -- raise (main,characters,id,size,0x02034,0xFE325,3) -- triple prime
+
+ -- there are more (needs discussion first):
+
+ -- characters[0x20D6] = characters[0x2190]
+ -- characters[0x20D7] = characters[0x2192]
+
+ characters[0x02B9] = characters[0x2032] -- we're nice
+
end
local unique = 0 -- testcase: \startTEXpage \math{!\text{-}\text{-}\text{-}} \stopTEXpage
@@ -362,13 +421,13 @@ end)
function vfmath.define(specification,set,goodies)
local name = specification.name -- symbolic name
local size = specification.size -- given size
- local loaded, fontlist, main = { }, { }, nil
+ local loaded, fontlist, names, main = { }, { }, { }, nil
local start = (trace_virtual or trace_timings) and os.clock()
local okset, n = { }, 0
for s=1,#set do
local ss = set[s]
local ssname = ss.name
- if ss.optional and vfmath.optional then
+ if add_optional and ss.optional then
if trace_virtual then
report_virtual("loading font %s subfont %s with name %s at %s is skipped",name,s,ssname,size)
end
@@ -379,7 +438,17 @@ function vfmath.define(specification,set,goodies)
if ss.main then
main = s
end
- local f, id = fonts.constructors.readanddefine(ssname,size)
+ local alreadyloaded = names[ssname] -- for px we load one twice (saves .04 sec)
+ local f, id
+ if alreadyloaded then
+ f, id = alreadyloaded.f, alreadyloaded.id
+ if trace_virtual then
+ report_virtual("loading font %s subfont %s with name %s is reused",name,s,ssname)
+ end
+ else
+ f, id = fonts.constructors.readanddefine(ssname,size)
+ names[ssname] = { f = f, id = id }
+ end
if not f or id == 0 then
report_virtual("loading font %s subfont %s with name %s at %s is skipped, not found",name,s,ssname,size)
else
@@ -387,7 +456,9 @@ function vfmath.define(specification,set,goodies)
okset[n] = ss
loaded[n] = f
fontlist[n] = { id = id, size = size }
- if not shared[s] then shared[n] = { } end
+ if not shared[s] then
+ shared[n] = { }
+ end
if trace_virtual then
report_virtual("loading font %s subfont %s with name %s at %s as id %s using encoding %s",name,s,ssname,size,id,ss.vector or "none")
end
@@ -471,9 +542,9 @@ function vfmath.define(specification,set,goodies)
setmetatableindex(goodies,parent.goodies)
end
--
- properties.virtualized = true
- properties.italic_correction = true
- properties.has_math = true
+ properties.virtualized = true
+ properties.hasitalics = true
+ properties.hasmath = true
--
local fullname = properties.fullname -- parent via mt
if fullname then
@@ -494,7 +565,7 @@ function vfmath.define(specification,set,goodies)
local ss, fs = okset[s], loaded[s]
if not fs then
-- skip, error
- elseif ss.optional and vfmath.optional then
+ elseif add_optional and ss.optional then
-- skip, redundant
else
local newparameters = fs.parameters
@@ -534,6 +605,7 @@ function vfmath.define(specification,set,goodies)
local offset = 0xFF000
local vector = mathencodings[vectorname]
local rotcev = reverse[vectorname]
+ local isextension = ss.extension
if vector and rotcev then
local fc, fd, si = fs.characters, fs.descriptions, shared[s]
local skewchar = ss.skewchar
@@ -564,9 +636,10 @@ function vfmath.define(specification,set,goodies)
local kerns = fci.kerns
local width = fci.width
local italic = fci.italic
- -- if italic then
- -- width = width + italic -- old interpretation of otf math specs
- -- end
+ if italic and isextension then
+ -- int_a^b
+ width = width + italic
+ end
if kerns then
local krn = { }
for k, v in next, kerns do -- kerns is sparse
@@ -586,7 +659,7 @@ function vfmath.define(specification,set,goodies)
kerns = krn,
commands = ref,
}
- if skewchar and kerns then
+ if skewchar then
local k = kerns[skewchar]
if k then
t.top_accent = width/2 + k
@@ -602,9 +675,10 @@ function vfmath.define(specification,set,goodies)
commands = ref,
}
end
+--~ report_virtual("%05X %s %s",unicode,fci.height or "NO HEIGHT",fci.depth or "NO DEPTH")
end
end
- if ss.extension then
+ if isextension then
-- todo: if multiple ex, then 256 offsets per instance
local extension = mathencodings["large-to-small"]
local variants_done = fs.variants_done
@@ -615,11 +689,12 @@ function vfmath.define(specification,set,goodies)
ref = { { 'slot', s, index } }
si[index] = ref
end
+ local italic = fci.italic
local t = {
- width = fci.width,
+ width = fci.width + italic, -- watch this !
height = fci.height,
depth = fci.depth,
- italic = fci.italic,
+ italic = italic,
commands = ref,
}
local n = fci.next
@@ -665,6 +740,7 @@ function vfmath.define(specification,set,goodies)
if not fci then
-- do nothing
else
+ -- probably never entered
local ref = si[index]
if not ref then
ref = { { 'slot', s, index } }
@@ -723,6 +799,7 @@ function vfmath.define(specification,set,goodies)
fonts.constructors.assignmathparameters(main,main)
--
main.MathConstants = main.mathparameters -- we directly pass it to TeX (bypasses the scaler) so this is needed
+--~ inspect(main.MathConstants)
--
if trace_virtual or trace_timings then
report_virtual("loading and virtualizing font %s at size %s took %0.3f seconds",name,size,os.clock()-start)
@@ -783,20 +860,26 @@ mathencodings["large-to-small"] = {
[0x02044] = 0x0E, -- /
}
+-- Beware: these are (in cm/lm) below the baseline due to limitations
+-- in the tfm format bu the engien (combined with the mathclass) takes
+-- care of it. If we need them in textmode, we should make them virtual
+-- and move them up but we're in no hurry with that.
+
mathencodings["tex-ex"] = {
[0x0220F] = 0x51, -- prod
- [0x0222B] = 0x52, -- intop
[0x02210] = 0x60, -- coprod
[0x02211] = 0x50, -- sum
+ [0x0222B] = 0x52, -- intop
+ [0x0222E] = 0x48, -- ointop
[0x022C0] = 0x56, -- bigwedge
[0x022C1] = 0x57, -- bigvee
[0x022C2] = 0x54, -- bigcap
[0x022C3] = 0x53, -- bigcup
- [0x02A04] = 0x55, -- biguplus
- [0x02A02] = 0x4E, -- bigotimes
+ [0x02A00] = 0x4A, -- bigodot -- fixed BJ
[0x02A01] = 0x4C, -- bigoplus
- [0x02A03] = 0x4A, -- bigodot
- [0x0222E] = 0x48, -- ointop
+ [0x02A02] = 0x4E, -- bigotimes
+ -- [0x02A03] = , -- bigudot --
+ [0x02A04] = 0x55, -- biguplus
[0x02A06] = 0x46, -- bigsqcup
}
@@ -911,8 +994,10 @@ mathencodings["tex-mi"] = {
[0x021C1] = 0x2B, -- rightharpoondown
[0xFE322] = 0x2C, -- lhook (hook for combining arrows)
[0xFE323] = 0x2D, -- rhook (hook for combining arrows)
- [0x022B3] = 0x2E, -- triangleright (TODO: which one is right?)
- [0x022B2] = 0x2F, -- triangleleft (TODO: which one is right?)
+ [0x025B7] = 0x2E, -- triangleright : cf lmmath / BJ
+ [0x025C1] = 0x2F, -- triangleleft : cf lmmath / BJ
+ [0x022B3] = 0x2E, -- triangleright : cf lmmath this a cramped triangles / BJ / see *
+ [0x022B2] = 0x2F, -- triangleleft : cf lmmath this a cramped triangles / BJ / see *
-- [0x00041] = 0x30, -- 0
-- [0x00041] = 0x31, -- 1
-- [0x00041] = 0x32, -- 2
@@ -1044,7 +1129,7 @@ mathencodings["tex-sy"] = {
-- [0x02201] = 0x00, -- complement
-- [0x02206] = 0x00, -- increment
-- [0x02204] = 0x00, -- not exists
---~ [0x000B7] = 0x01, -- cdot
+-- [0x000B7] = 0x01, -- cdot
[0x022C5] = 0x01, -- cdot
[0x000D7] = 0x02, -- times
[0x0002A] = 0x03, -- *
@@ -1181,6 +1266,8 @@ mathencodings["tex-sy"] = {
[0x02661] = 0x7E, -- heartsuit
[0x02660] = 0x7F, -- spadesuit
[0xFE321] = 0x37, -- mapstochar
+
+ [0xFE325] = 0x30, -- prime 0x02032
}
-- The names in masm10.enc can be trusted best and are shown in the first
@@ -1193,11 +1280,11 @@ mathencodings["tex-ma"] = {
[0x022A0] = 0x02, -- squaremultiply \boxtimes
[0x025A1] = 0x03, -- square \square \Box
[0x025A0] = 0x04, -- squaresolid \blacksquare
- [0x000B7] = 0x05, -- squaresmallsolid \centerdot
+ [0x025AA] = 0x05, -- squaresmallsolid \centerdot
[0x022C4] = 0x06, -- diamond \Diamond \lozenge
- [0x029EB] = 0x07, -- diamondsolid \blacklozenge
- [0x021BA] = 0x08, -- clockwise \circlearrowright
- [0x021BB] = 0x09, -- anticlockwise \circlearrowleft
+ [0x02666] = 0x07, -- diamondsolid \blacklozenge
+ [0x021BB] = 0x08, -- clockwise \circlearrowright
+ [0x021BA] = 0x09, -- anticlockwise \circlearrowleft
[0x021CC] = 0x0A, -- harpoonleftright \rightleftharpoons
[0x021CB] = 0x0B, -- harpoonrightleft \leftrightharpoons
[0x0229F] = 0x0C, -- squareminus \boxminus
@@ -1255,9 +1342,10 @@ mathencodings["tex-ma"] = {
[0x02277] = 0x3F, -- greaterorless \gtrless
[0x0228F] = 0x40, -- squareimage \sqsubset
[0x02290] = 0x41, -- squareoriginal \sqsupset
- -- wrong:
- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright
- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft
+ -- wrong: see **
+ -- [0x022B3] = 0x42, -- triangleright \rhd \vartriangleright
+ -- [0x022B2] = 0x43, -- triangleleft \lhd \vartriangleleft
+ -- cf lm
[0x022B5] = 0x44, -- trianglerightequal \unrhd \trianglerighteq
[0x022B4] = 0x45, -- triangleleftequal \unlhd \trianglelefteq
--
@@ -1292,7 +1380,7 @@ mathencodings["tex-ma"] = {
[0x022D0] = 0x62, -- subsetdbl \Subset
[0x022D1] = 0x63, -- supersetdbl \Supset
[0x022D3] = 0x64, -- uniondbl \doublecup \Cup
- [0x00100] = 0x65, -- intersectiondbl \doublecap \Cap
+ [0x022D2] = 0x65, -- intersectiondbl \doublecap \Cap
[0x022CF] = 0x66, -- uprise \curlywedge
[0x022CE] = 0x67, -- downfall \curlyvee
[0x022CB] = 0x68, -- multiopenleft \leftthreetimes
@@ -1308,7 +1396,7 @@ mathencodings["tex-ma"] = {
[0x024C7] = 0x72, -- circleR \circledR
[0x024C8] = 0x73, -- circleS \circledS
[0x022D4] = 0x74, -- fork \pitchfork
- [0x02245] = 0x75, -- dotplus \dotplus
+ [0x02214] = 0x75, -- dotplus \dotplus
[0x0223D] = 0x76, -- revsimilar \backsim
[0x022CD] = 0x77, -- revasymptequal \backsimeq -- AM: Check this! I mapped it to simeq.
[0x0231E] = 0x78, -- rightanglesw \llcorner
@@ -1413,8 +1501,8 @@ mathencodings["tex-mb"] = {
[0x1D54F] = 0x58, -- X
[0x1D550] = 0x59, -- Y
[0x02124] = 0x5A, -- Z (blackboard Z)
- [0x02132] = 0x60, -- hatwide \Finv
- [0x02141] = 0x61, -- hatwider \Game
+ [0x02132] = 0x60, -- finv \Finv
+ [0x02141] = 0x61, -- fmir \Game
-- [0x0] = 0x62, tildewide
-- [0x0] = 0x63, tildewider
-- [0x0] = 0x64, Finv
diff --git a/Master/texmf-dist/tex/context/base/meta-clp.mkii b/Master/texmf-dist/tex/context/base/meta-clp.mkii
index be2506b196c..5c9206deee9 100644
--- a/Master/texmf-dist/tex/context/base/meta-clp.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-clp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Clipping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-dum.mkii b/Master/texmf-dist/tex/context/base/meta-dum.mkii
index bc19f3c5fa8..dae30ed695b 100644
--- a/Master/texmf-dist/tex/context/base/meta-dum.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-dum.mkii
@@ -5,7 +5,7 @@
%D subtitle=Dummy (External) Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-fig.mkii b/Master/texmf-dist/tex/context/base/meta-fig.mkii
index 3edd73b5749..31fe5fc0c0e 100644
--- a/Master/texmf-dist/tex/context/base/meta-fig.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-fig.mkii
@@ -5,7 +5,7 @@
%D subtitle=Stand Alone Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-fig.mkiv b/Master/texmf-dist/tex/context/base/meta-fig.mkiv
index adaad4647e0..bee88ffefa7 100644
--- a/Master/texmf-dist/tex/context/base/meta-fig.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-fig.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Stand Alone Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -41,45 +41,17 @@
%D definitions with the text flow, since all settings are
%D kept local. The page is clipped to the image size.
-\presetlocalframed[\??mg]
-
-\unexpanded\def\setupMPpage
- {\dodoubleargument\getparameters[\??mg]}
-
-% \def\startMPpage
-% {\dodoubleempty\dostartMPpage}
-%
-% \long\def\dostartMPpage[#1][#2]#3\stopMPpage % second arg gobbles space
-% {\dostartfittingpage[\??mg][#1]%
-% \processMPgraphic{#3}%
-% \dostopfittingpage}
-
-\def\startMPpage
- {\dosingleempty\dostartMPpage}
-
-\long\def\dostartMPpage[#1]#2\stopMPpage
- {\dostartfittingpage[\??mg][#1]%
- \processMPgraphic{#2}%
- \dostopfittingpage}
-
-\let\stopMPpage \relax % so that we can use it in \expanded
-
-\setupMPpage
- [\c!scale=1000,
- \c!pagestate=,
- \c!strut=\v!no,
- \c!align=,
- \c!offset=\v!overlay,
- \c!width=\v!fit,
- \c!height=\v!fit,
- \c!frame=\v!off]
+\definefittingpage
+ [MPpage]
+ [\c!align=,
+ \c!command=\meta_process_graphic]
%D \macros
%D {MPfigure}
%D
%D A bit out of place, here but nevertheless:
-\def\MPfigure#1#2% test for dup figure, can be replaced by a textext
+\unexpanded\def\MPfigure#1#2% test for dup figure, can be replaced by a textext
{\bgroup
\getfiguredimensionsonly[#1]% [\c!object=\v!no] already set
\startMPcode
diff --git a/Master/texmf-dist/tex/context/base/meta-fun.lua b/Master/texmf-dist/tex/context/base/meta-fun.lua
index 9a6d971baa6..7594d0c78d7 100644
--- a/Master/texmf-dist/tex/context/base/meta-fun.lua
+++ b/Master/texmf-dist/tex/context/base/meta-fun.lua
@@ -9,7 +9,6 @@ if not modules then modules = { } end modules ['meta-fun'] = {
-- very experimental, actually a joke ... see metafun manual for usage
local format, loadstring, type = string.format, loadstring, type
-local texwrite = tex.write
local metapost = metapost
@@ -17,42 +16,42 @@ metapost.metafun = metapost.metafun or { }
local metafun = metapost.metafun
function metafun.topath(t,connector)
- texwrite("(")
+ context("(")
if #t > 0 then
for i=1,#t do
if i > 1 then
- texwrite(connector or "..")
+ context(connector or "..")
end
local ti = t[i]
if type(ti) == "string" then
- texwrite(ti)
+ context(ti)
else
- texwrite(format("(%s,%s)",ti.x or ti[1] or 0,ti.y or ti[2] or 0))
+ context("(%s,%s)",ti.x or ti[1] or 0,ti.y or ti[2] or 0)
end
end
else
- texwrite("origin")
+ context("origin")
end
- texwrite(")")
+ context(")")
end
function metafun.interpolate(f,b,e,s,c)
local done = false
- texwrite("(")
+ context("(")
for i=b,e,(e-b)/s do
local d = loadstring(format("return function(x) return %s end",f))
if d then
d = d()
if done then
- texwrite(c or "...")
+ context(c or "...")
else
done = true
end
- texwrite(format("(%s,%s)",i,d(i)))
+ context("(%s,%s)",i,d(i))
end
end
if not done then
- texwrite("origin")
+ context("origin")
end
- texwrite(")")
+ context(")")
end
diff --git a/Master/texmf-dist/tex/context/base/meta-fun.mkiv b/Master/texmf-dist/tex/context/base/meta-fun.mkiv
index fbe91fd6a08..c3a4ce8d417 100644
--- a/Master/texmf-dist/tex/context/base/meta-fun.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-fun.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Goodies,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-imp-clp.mkiv b/Master/texmf-dist/tex/context/base/meta-imp-clp.mkiv
index be2506b196c..5c9206deee9 100644
--- a/Master/texmf-dist/tex/context/base/meta-imp-clp.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-imp-clp.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Clipping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-imp-dum.mkiv b/Master/texmf-dist/tex/context/base/meta-imp-dum.mkiv
index 60ab0a41d7c..a622d94f4d3 100644
--- a/Master/texmf-dist/tex/context/base/meta-imp-dum.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-imp-dum.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Dummy (External) Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -96,7 +96,7 @@
\let\normalexternalfigurereplacement\externalfigurereplacement
-\def\externalfigurereplacement#1#2#3%
+\unexpanded\def\externalfigurereplacement#1#2#3%
{\getpaletsize[placeholder]%
\ifx\figurereplacementcycle\relax
\getrandomnumber \figurereplacementcycle \!!plusone \paletsize
@@ -107,9 +107,6 @@
\ifnum\figurereplacementcycle>\paletsize
\globallet\figurereplacementcycle\!!plusone
\fi
- \weightGRAYfalse % monochrome anyway
- \MPcmykcolorsfalse
- \MPspotcolorsfalse
\defineoverlay
[\s!dummy]
[\useMPgraphic
@@ -128,20 +125,63 @@
\c!foregroundcolor=\s!white]}%
{\doif\@@eftext\v!yes
{\infofont \setupinterlinespace \dohyphens % \nohyphens
- \doifelse{#1}\s!dummy \!!doneafalse\!!doneatrue
- \doifelse{#2}\s!dummy \!!donebfalse\!!donebtrue
- \doifelse{#3}\s!unknown\!!donecfalse\!!donectrue
- \if!!donea
+ \edef\tempa{#1}\ifx\tempa\s!dummy\let\tempa\empty\fi
+ \edef\tempb{#2}\ifx\tempb\s!dummy\let\tempb\empty\fi
+ \edef\tempc{#3}\ifx\tempc\s!dummy\let\tempc\empty\fi
+ \ifx\tempa\empty\else
name: \expanded{\verbatimstring{#1}}\strut\endgraf
\fi
- \if!!doneb
- \if!!donea file: \else \if!!donec file: \fi \fi
+ \ifx\tempb\empty\else
+ \ifx\tempa\empty\ifx\tempc\empty\else file: \fi\else file: \fi
\expanded{\verbatimstring{#2}}\strut\endgraf
\fi
- \if!!donec
+ \ifx\tempc\empty\else
state: \expanded{\verbatimstring{#3}}\strut\endgraf
\fi}}}
-\def\dummyfigure{\externalfigure[placeholder]}
+\unexpanded\def\dummyfigure
+ {\externalfigure[placeholder]}
+
+%D \starttyping
+%D \externalfigure[mediashow.swf][comment={Alas, we have no nice preview},background=figure:comment]
+%D \externalfigure[mediashow.swf][comment={Alas, we have no nice preview},background=figure:dummy]
+%D \externalfigure[mediashow.swf][background=figure:dummy]
+%D \stoptyping
+
+\defineframed
+ [figurecomment]
+ [\c!background=\v!color,
+ \c!backgroundcolor=\v!gray,
+ \c!frame=\v!off,
+ \c!foregroundstyle=\ttbf,
+ \c!align={\v!middle,\v!lohi},
+ \c!height=\figureheight,
+ \c!width=\figurewidth]
+
+\defineframed
+ [figuredummy]
+ [\c!background=figure:placeholder,
+ \c!foregroundcolor=white,
+ \c!backgroundcolor=\v!gray,
+ \c!frame=\v!off,
+ \c!foregroundstyle=\ttbf,
+ \c!align={\v!middle,\v!lohi},
+ \c!height=\figureheight,
+ \c!width=\figurewidth]
+
+\defineoverlay
+ [figure:placeholder]
+ [\externalfigurereplacement{}{}{}]
+
+\defineoverlay
+ [figure:comment]
+ [\figurecomment{\@@efcomment}]
+
+\defineoverlay
+ [figure:dummy]
+ [\figuredummy{\@@efcomment}]
+
+\setupexternalfigures
+ [comment=]
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/meta-imp-fen.mkiv b/Master/texmf-dist/tex/context/base/meta-imp-fen.mkiv
new file mode 100644
index 00000000000..307a59b4db6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/meta-imp-fen.mkiv
@@ -0,0 +1,173 @@
+%D \module
+%D [ file=meta-imp-fen,
+%D version=2011.07.21,
+%D title=\METAPOST\ Graphics,
+%D subtitle=Fences,
+%D author=Wolfgang Schuster & 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 shape and background example code was posted by Wolfgang on the
+%D \CONTEXT\ list and due to request by Aditya has been turned into
+%D library.
+
+\startMPextensions
+ vardef BasicBraceSymbol (expr rotation) =
+ save p ; path p ;
+ z1 = (-233, 0) ;
+ z2 = (-220, 22) ;
+ z3 = (-155, 211) ;
+ z4 = (-200, 690) ;
+ z5 = (-142, 1033) ;
+ z6 = ( -97, 1106) ;
+ z7 = ( -71, 1125) ;
+ z8 = ( -61, 1104) ;
+ z9 = ( -80, 1077) ;
+ z10 = (-108, 1002) ;
+ z11 = (-129, 666) ;
+ z12 = (-117, 207) ;
+ z13 = (-197, 19) ;
+ z14 = (-208, 0) ;
+ z15 = (-197, -19) ;
+ z16 = (-117, -207) ;
+ z17 = (-129, -666) ;
+ z18 = (-108,-1026) ;
+ z19 = ( -80,-1077) ;
+ z20 = ( -61,-1104) ;
+ z21 = ( -71,-1125) ;
+ z22 = ( -97,-1106) ;
+ z23 = (-143,-1031) ;
+ z24 = (-199, -673) ;
+ z25 = (-155, -211) ;
+ z26 = (-220, -22) ;
+ p := z1 for i= 2 upto 14 : .. z[i] endfor
+ & z14 for j=15 upto 26 : .. z[j] endfor
+ .. z1
+ & cycle ;
+ p := p rotated rotation ;
+ p := p ysized 100 ;
+ p shifted - center p
+ enddef ;
+ vardef RawLeftBraceSymbol =
+ fill BasicBraceSymbol(0) ysized OverlayHeight withcolor OverlayColor ;
+ enddef ;
+ vardef RawRightBraceSymbol =
+ fill BasicBraceSymbol(180) ysized OverlayHeight withcolor OverlayColor ;
+ enddef ;
+ vardef RawTopBraceSymbol =
+ fill BasicBraceSymbol(270) xsized OverlayWidth withcolor OverlayColor ;
+ enddef ;
+ vardef RawBottomBraceSymbol =
+ fill BasicBraceSymbol(90) xsized OverlayWidth withcolor OverlayColor ;
+ enddef ;
+ vardef LeftBraceSymbol =
+ save p, b ; path p, b ; b := fullsquare xscaled OverlayWidth yscaled OverlayHeight ;
+ setbounds currentpicture to b ;
+ p := BasicBraceSymbol(0) ysized OverlayHeight ;
+ fill p shifted (-xpart lrcorner currentpicture + xpart lrcorner p,0) withcolor OverlayColor ;
+ setbounds currentpicture to b ;
+ enddef ;
+ vardef RightBraceSymbol =
+ save p, b ; path p, b ; b := fullsquare xscaled OverlayWidth yscaled OverlayHeight ;
+ setbounds currentpicture to b ;
+ p := BasicBraceSymbol(180) ysized OverlayHeight ;
+ fill p shifted (xpart lrcorner currentpicture - xpart lrcorner p,0) withcolor OverlayColor ;
+ setbounds currentpicture to b ;
+ enddef ;
+ vardef TopBraceSymbol =
+ save p, b ; path p, b ; b := fullsquare xscaled OverlayWidth yscaled OverlayHeight ;
+ setbounds currentpicture to b ;
+ p := BasicBraceSymbol(270) xsized OverlayWidth ;
+ fill p shifted (0,ypart ulcorner currentpicture - ypart ulcorner p) withcolor OverlayColor ;
+ setbounds currentpicture to b ;
+ enddef ;
+ vardef BottomBraceSymbol =
+ save p, b ; path p, b ; b := fullsquare xscaled OverlayWidth yscaled OverlayHeight ;
+ setbounds currentpicture to b ;
+ p := BasicBraceSymbol(90) xsized OverlayWidth ;
+ fill p shifted (0,ypart lrcorner currentpicture - ypart lrcorner p) withcolor OverlayColor ;
+ setbounds currentpicture to b ;
+ enddef ;
+\stopMPextensions
+
+\startuniqueMPgraphic{raw_brace_left} RawLeftBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{raw_brace_right} RawRightBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{raw_brace_top} RawTopBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{raw_brace_bottom} RawBottomBraceSymbol ; \stopuniqueMPgraphic
+
+\startuniqueMPgraphic{brace_left} LeftBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{brace_right} RightBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{brace_top} TopBraceSymbol ; \stopuniqueMPgraphic
+\startuniqueMPgraphic{brace_bottom} BottomBraceSymbol ; \stopuniqueMPgraphic
+
+\defineoverlay[leftbrace] [\uniqueMPgraphic{brace_left}]
+\defineoverlay[rightbrace] [\uniqueMPgraphic{brace_right}]
+\defineoverlay[topbrace] [\uniqueMPgraphic{brace_top}]
+\defineoverlay[bottombrace][\uniqueMPgraphic{brace_bottom}]
+
+\installleftframerenderer {brace}{\uniqueMPgraphic{raw_brace_left}}
+\installrightframerenderer {brace}{\uniqueMPgraphic{raw_brace_right}}
+\installtopframerenderer {brace}{\uniqueMPgraphic{raw_brace_top}}
+\installbottomframerenderer{brace}{\uniqueMPgraphic{raw_brace_bottom}}
+
+\continueifinputfile{meta-imp-fen.mkiv}
+
+\starttext
+
+\startTEXpage[offset=10pt]
+
+ \framed
+ [offset=1ex,
+ leftframe=brace,
+ rightframe=brace,
+ topframe=brace,
+ bottomframe=brace,
+ background=color,
+ backgroundcolor=red]
+ {OEPS}
+
+\stopTEXpage
+
+\startTEXpage \uniqueMPgraphic{brace_left} \stopTEXpage
+\startTEXpage \uniqueMPgraphic{brace_right} \stopTEXpage
+\startTEXpage \uniqueMPgraphic{brace_top} \stopTEXpage
+\startTEXpage \uniqueMPgraphic{brace_bottom} \stopTEXpage
+
+\framedtext
+ [frame=off,
+ offset=2em,
+ background={leftbrace,rightbrace,topbrace,bottombrace},
+ backgroundcolor=red]{\input{knuth}}
+
+\setupTABLE[frame=off,offset=1ex]
+\setupTABLE[row][each][align={middle,lohi}]
+
+\bTABLE
+ \bTR
+ \bTD[nr=3,background=leftbrace] drei \eTD
+ \bTD[nr=2,background=leftbrace] zwei \eTD
+ \bTD f \eTD
+ \bTD o \eTD
+ \bTD u \eTD
+ \bTD r \eTD
+ \bTD [nr=3,background=rightbrace] three \eTD
+ \eTR
+ \bTR
+ \bTD [background=leftbrace] eins \eTD
+ \bTD [background={topbrace,bottombrace}] null \eTD
+ \bTD [background=rightbrace] one \eTD
+ \bTD [nr=2,background=rightbrace] two \eTD
+ \eTR
+ \bTR
+ \bTD v \eTD
+ \bTD i \eTD
+ \bTD e \eTD
+ \bTD r \eTD
+ \eTR
+\eTABLE
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/meta-imp-mis.mkiv b/Master/texmf-dist/tex/context/base/meta-imp-mis.mkiv
index 29ab43007e7..e8282c381b8 100644
--- a/Master/texmf-dist/tex/context/base/meta-imp-mis.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-imp-mis.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Misc Test Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-imp-nav.mkiv b/Master/texmf-dist/tex/context/base/meta-imp-nav.mkiv
index 9c1cbb4dbb4..45a31ba5ecf 100644
--- a/Master/texmf-dist/tex/context/base/meta-imp-nav.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-imp-nav.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Navigational Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-imp-pre.mkiv b/Master/texmf-dist/tex/context/base/meta-imp-pre.mkiv
index cb861ff20d5..098be030b19 100644
--- a/Master/texmf-dist/tex/context/base/meta-imp-pre.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-imp-pre.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Predefined Goodies,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-imp-txt.mkiv b/Master/texmf-dist/tex/context/base/meta-imp-txt.mkiv
index 474253a4052..08373c0c4e9 100644
--- a/Master/texmf-dist/tex/context/base/meta-imp-txt.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-imp-txt.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Text Tricks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -29,7 +29,7 @@
\unprotect
\startMPextensions
- if unknown context_text: input mp-text; fi;
+ if unknown context_text: input "mp-text.mpiv" ; fi;
\stopMPextensions
%%%%%%%
diff --git a/Master/texmf-dist/tex/context/base/meta-ini.lua b/Master/texmf-dist/tex/context/base/meta-ini.lua
index 5150c38358f..bac1429ae1d 100644
--- a/Master/texmf-dist/tex/context/base/meta-ini.lua
+++ b/Master/texmf-dist/tex/context/base/meta-ini.lua
@@ -6,24 +6,97 @@ if not modules then modules = { } end modules ['meta-ini'] = {
license = "see context related readme files"
}
-local format = string.format
+local tonumber = tonumber
+local format, gmatch, match, gsub = string.format, string.gmatch, string.match, string.gsub
metapost = metapost or { }
-- for the moment downward compatible
-local report_metapost = logs.reporter ("metapost")
+local report_metapost = logs.reporter ("metapost")
local status_metapost = logs.messenger("metapost")
local patterns = { "meta-imp-%s.mkiv", "meta-imp-%s.tex", "meta-%s.mkiv", "meta-%s.tex" } -- we are compatible
-function metapost.uselibrary(name)
- commands.uselibrary(name,patterns,function(name,foundname)
- context.startreadingfile()
- status_metapost("loaded: library '%s'",name)
- context.input(foundname)
- context.stopreadingfile()
- end, function(name)
- report_metapost("unknown: library '%s'",name)
+local function action(name,foundname)
+ status_metapost("loaded: library '%s'",name)
+ context.startreadingfile()
+ context.input(foundname)
+ context.stopreadingfile()
+end
+
+local function failure(name)
+ report_metapost("unknown: library '%s'",name)
+end
+
+function commands.useMPlibrary(name)
+ commands.uselibrary {
+ name = name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
+end
+
+-- experimental
+
+local colorhash = attributes.list[attributes.private('color')]
+
+local validdimen = lpeg.patterns.validdimen * lpeg.P(-1)
+
+local lpegmatch = lpeg.match
+local textype = tex.type
+local MPcolor = context.MPcolor
+
+function commands.prepareMPvariable(v) -- slow but ok
+ if v == "" then
+ MPcolor("black")
+ else
+ local typ, var = match(v,"(.):(.*)")
+ if not typ then
+ -- parse
+ if colorhash[v] then
+ MPcolor(v)
+ elseif tonumber(v) then
+ context(v)
+ elseif lpegmatch(validdimen,v) then
+ return context("\\the\\dimexpr %s",v)
+ else
+ for s in gmatch(v,"\\(.-)") do
+ local t = textype(s)
+ if t == "dimen" then
+ return context("\\the\\dimexpr %s",v)
+ elseif t == "count" then
+ return context("\\the\\numexpr %s",v)
+ end
+ end
+ return context("\\number %s",v) -- 0.4 ...
+ end
+ elseif typ == "d" then
+ -- dimension
+ context("\\the\\dimexpr %s",var)
+ elseif typ == "n" then
+ -- number
+ context("\\the\\numexpr %s",var)
+ elseif typ == "s" then
+ -- string
+ context(var)
+ elseif typ == "c" then
+ -- color
+ MPcolor(var)
+ else
+ context(var)
+ end
+ end
+end
+
+function metapost.formatnumber(f,n) -- just lua format
+ f = gsub(f,"@(%d)","%%.%1")
+ f = gsub(f,"@","%%")
+ f = format(f,tonumber(n) or 0)
+ f = gsub(f,"e([%+%-%d]+)",function(s)
+ return format("\\times10^{%s}",tonumber(s) or s) -- strips leading zeros
end)
+ context.mathematics(f)
end
diff --git a/Master/texmf-dist/tex/context/base/meta-ini.mkii b/Master/texmf-dist/tex/context/base/meta-ini.mkii
index fd6ef9a6163..9780fecfadf 100644
--- a/Master/texmf-dist/tex/context/base/meta-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -33,12 +33,6 @@
\def\@@MPG{@MPG@}
-\startMPextensions
- if unknown context_tool: input mp-tool; fi;
- if unknown context_spec: input mp-spec; fi;
- if unknown context_grph: input mp-grph; fi;
-\stopMPextensions
-
%D Since we want lables to follow the document settings, we
%D also set the font related variables.
@@ -464,9 +458,9 @@
\startMPextensions
boolean collapse_data; collapse_data:=true;
- def data_mpd_file = "\MPdataMPDfile" enddef ;
- def data_mpo_file = "\MPdataMPOfile" enddef ;
- def data_mpy_file = "\MPdataMPYfile" enddef ;
+ def data_mpd_file="\MPdataMPDfile"; enddef ;
+ def data_mpo_file="\MPdataMPOfile"; enddef ;
+ def data_mpy_file="\MPdataMPYfile"; enddef ;
\stopMPextensions
\def\getMPdata
diff --git a/Master/texmf-dist/tex/context/base/meta-ini.mkiv b/Master/texmf-dist/tex/context/base/meta-ini.mkiv
index e95eb178604..d2f5cd6cb4c 100644
--- a/Master/texmf-dist/tex/context/base/meta-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -17,111 +17,126 @@
\unprotect
-%D Instead of sharing code with \MKII, I decided to copy
-%D the code. Otherwise maintainance becomes a pain and after all,
-%D the \MKII\ code will not change.
+\newtoks \t_meta_extensions % mp, once
+\newtoks \t_meta_initializations % tex, each
+\newtoks \t_meta_userinclusions % mp, user
-\let \useMETAFUNformattrue\relax \let \useMETAFUNformatfalse\relax
-\let \longMPlinestrue\relax \let \longMPlinesfalse\relax
-\let \runMPgraphicstrue\relax \let \runMPgraphicsfalse\relax
-\let \runMPTEXgraphicstrue\relax \let \runMPTEXgraphicsfalse\relax
-\let \MPstaticgraphictrue\relax \let \MPstaticgraphicfalse\relax
-\let\forceMPTEXgraphictrue\relax \let\forceMPTEXgraphicfalse\relax
+\newtoks \everyMPgraphic % mp % public or not ?
-\let \obeyMPlines\relax
-\let \forceMPTEXcheck\gobbleoneargument
-\let\maxnofMPgraphics\scratchcounter
+\appendtoks
+ \restoreendofline % see interferences-001.tex
+\to \everyMPgraphic
-\newtoks \MPextensions % mp, once
-\newtoks \MPinitializations % tex, each
-\newtoks \MPuserinclusions % mp, user
-\newtoks \MPfinalizations % mp, user
-\newtoks \everyMPgraphic % mp
-\newtoks \everyMPTEXgraphic % tex
+\def\MPruntimefile {mprun}
+\def\currentMPformat {metafun}
+\def\defaultMPinstance{metafun}
-\newif\ifMPrun
-\def\MPruntimefile{mprun}
+%installcorenamespace{graphicvariable} % todo
+\installcorenamespace{mpinstance}
+\installcorenamespace{mpinstancetokens}
+\installcorenamespace{mpgraphic}
+\installcorenamespace{mpstaticgraphic}
+\installcorenamespace{mpclip}
% The next command is, of course, dedicated to Mojca, who
% needs it for gnuplot. Anyway, the whole multiple engine
% mechanism is to keep her gnuplot from interfering.
-\def\startMPdefinitions
- {\dosinglegroupempty\dostartMPdefinitions}
+\unexpanded\def\startMPdefinitions
+ {\dosinglegroupempty\meta_start_definitions}
-\long\def\dostartMPdefinitions#1#2\stopMPdefinitions
- {\edef\currentMPgraphicinstance{#1}%
- \ifx\currentMPgraphicinstance\empty
- \let\currentMPgraphicinstance\defaultMPgraphicinstance
+\def\meta_start_definitions#1#2\stopMPdefinitions
+ {\edef\currentMPinstance{#1}%
+ \ifx\currentMPinstance\empty
+ \let\currentMPinstance\defaultMPinstance
\fi
- \global\MPinstancetoks\expandafter{\the\MPinstancetoks#2}}
+ \global\t_meta_instance\expandafter{\the\t_meta_instance#2}}
+
+\let\stopMPdefinitions\relax
-\long\def\startMPextensions#1\stopMPextensions
- {\global\MPextensions\expandafter{\the\MPextensions#1}}
+\unexpanded\def\startMPextensions#1\stopMPextensions
+ {\global\t_meta_extensions\expandafter{\the\t_meta_extensions#1}}
-\long\def\startMPinitializations#1\stopMPinitializations
- {\global\MPinitializations\expandafter{\the\MPinitializations#1}}
+\let\stopMPextensions\relax
-\long\def\startMPinclusions
- {\dosingleempty\dostartMPinclusions}
+\unexpanded\def\startMPinitializations#1\stopMPinitializations
+ {\global\t_meta_initializations\expandafter{\the\t_meta_initializations#1}}
-\long\def\dostartMPinclusions[#1]#2\stopMPinclusions
- {\doifnot{#1}{+}{\global\MPuserinclusions\emptytoks}%
- \global\MPuserinclusions\expandafter{\the\MPuserinclusions#2}}
+\let\stopMPinitializations\relax
-\def\MPinclusions
- {\dosingleempty\doMPinclusions}
+\unexpanded\def\startMPinclusions
+ {\dosingleempty\meta_start_inclusions}
+
+\def\meta_start_inclusions[#1]#2\stopMPinclusions
+ {\edef\m_meta_option{#1}%
+ \ifx\m_meta_option\!!plustoken \else
+ \global\t_meta_userinclusions\emptytoks
+ \fi
+ \global\t_meta_userinclusions\expandafter{\the\t_meta_userinclusions#2}}
-\long\def\doMPinclusions[#1]#2%
- {\doifnot{#1}{+}{\global\MPuserinclusions\emptytoks}%
- \global\MPuserinclusions\expandafter{\the\MPuserinclusions#2}}
+\let\stopMPinclusions\relax
-\def\presetMPdefinitions
+\unexpanded\def\MPinclusions
+ {\dosingleempty\meta_inclusions}
+
+\def\meta_inclusions[#1]#2%
+ {\edef\m_meta_option{#1}%
+ \ifx\m_meta_option\!!plustoken \else
+ \global\t_meta_userinclusions\emptytoks
+ \fi
+ \global\t_meta_userinclusions\expandafter{\the\t_meta_userinclusions#2}}
+
+\def\meta_preset_definitions
{\edef\overlaywidth {\overlaywidth \space}%
\edef\overlayheight {\overlayheight \space}%
\edef\overlaylinewidth{\overlaylinewidth\space}%
\edef\currentwidth {\the\hsize \space}%
\edef\currentheight {\the\vsize \space}}
-\def\currentMPformat{metafun}
+\def\t_meta_instance{\csname\??mpinstancetokens\currentMPinstance\endcsname} % token register
-\def\@@MPF{@MPF@}
+\installcommandhandler \??mpinstance {MPinstance} \??mpinstance
-\def\MPinstancetoks{\csname\@@MPF::\currentMPgraphicinstance\endcsname}
+\setupMPinstance
+ [\s!format=metafun,
+ \s!extensions=\v!no,
+ \s!initializations=\v!no,
+ \c!textstyle=,
+ \c!textcolor=]
-\unexpanded\def\defineMPinstance
- {\dodoubleargument\dodefineMPinstance}
+% \unexpanded\def\defineMPinstance
+% {\dodoubleargument\meta_define_instance}
-\def\dodefineMPinstance[#1][#2]%
- {\ifcsname\@@MPF::#1\endcsname\else\expandafter\newtoks\csname\@@MPF::#1\endcsname\fi
- \MPinstancetoks\emptytoks % in case we redefine
- \getparameters[\@@MPF#1][\s!format=mpost,\s!extensions=\v!no,\s!initializations=\v!no,#2]}
+% \def\meta_define_instance[#1][#2]%
+% {\ifcsname\??mpinstancetokens#1\endcsname\else\expandafter\newtoks\csname\??mpinstancetokens#1\endcsname\fi
+% \t_meta_instance\emptytoks % in case we redefine
+% \getparameters[\??mpinstance#1][\s!format=mpost,\s!extensions=\v!no,\s!initializations=\v!no,#2]}
-\def\resetMPinstance[#1]%
- {\writestatus\m!metapost{reset will be implemented when needed}}
+\appendtoks
+ \ifcsname\??mpinstancetokens\currentMPinstance\endcsname \else
+ \expandafter\newtoks\csname\??mpinstancetokens\currentMPinstance\endcsname
+ \fi
+ \t_meta_instance\emptytoks % in case we redefine
+\to \everydefineMPinstance
-\def\defaultMPgraphicinstance{metafun}
+\unexpanded\def\resetMPinstance[#1]%
+ {\writestatus\m!metapost{reset will be implemented when needed}}
-\def\splitMPgraphicname[#1]%
- {\dosplitMPgraphicname[#1::::]}
+\def\meta_analyze_graphicname[#1]%
+ {\meta_analyze_graphicname_indeed[#1::::]}
-\def\dosplitMPgraphicname[#1::#2::#3]% instance ::
+\def\meta_analyze_graphicname_indeed[#1::#2::#3]% instance ::
{\edef\currentMPgraphicname{#2}%
\ifx\currentMPgraphicname\empty
\edef\currentMPgraphicname{#1}%
- \let\currentMPgraphicinstance\defaultMPgraphicinstance
+ \let\currentMPinstance\defaultMPinstance
\else
- \edef\currentMPgraphicinstance{#1}%
+ \edef\currentMPinstance{#1}%
\fi
- \edef\currentMPgraphicformat
- {\ifcsname\@@MPF\currentMPgraphicinstance\s!format\endcsname
- \csname\@@MPF\currentMPgraphicinstance\s!format\endcsname
- \else
- \defaultMPgraphicinstance
- \fi}}
+ \edef\currentMPformat{\MPinstanceparameter\s!format}}
-\def\currentMPgraphicinstance{\defaultMPgraphicinstance}
-\def\currentMPgraphicformat {\currentMPgraphicinstance}
+\def\currentMPinstance{\defaultMPinstance}
+\def\currentMPformat {\currentMPinstance}
\defineMPinstance[metafun] [\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
\defineMPinstance[extrafun][\s!format=metafun,\s!extensions=\v!yes,\s!initializations=\v!yes]
@@ -129,54 +144,69 @@
\defineMPinstance[metapost][\s!format=mpost]
\defineMPinstance[nofun] [\s!format=mpost]
-\def\beginMPgraphicgroup#1%
+\newconditional\c_meta_include_extensions
+\newconditional\c_meta_include_initializations
+
+\def\meta_begin_graphic_group#1%
{\begingroup
- \splitMPgraphicname[#1]}
+ \meta_analyze_graphicname[#1]}
-\def\endMPgraphicgroup
+\def\meta_end_graphic_group
{\endgroup}
\def\MPaskedfigure{false}
-\def\currentMPinitializations
- {\ifconditional\includeMPinitializations\the\MPinitializations;\fi\theMPrandomseed;}
+\def\meta_flush_current_initializations
+ {\ifconditional\c_meta_include_initializations\the\t_meta_initializations;\fi\theMPrandomseed;}
-\def\currentMPpreamble
- {\ifconditional\includeMPextensions\the\MPextensions;\the\MPuserinclusions;\fi\the\MPinstancetoks;}
+\def\meta_flush_current_preamble
+ {\ifconditional\c_meta_include_extensions\the\t_meta_extensions;\the\t_meta_userinclusions;\fi\the\t_meta_instance;}
-\def\dostartcurrentMPgraphic
+\def\meta_start_current_graphic
{\begingroup
- \enableincludeMPgraphics
+ \meta_enable_include
\the\everyMPgraphic
- \presetMPdefinitions
+ \meta_preset_definitions
\setMPrandomseed % this has to change
% we need to preexpand the token lists
- \doifelsevalue{\@@MPF\currentMPgraphicinstance\s!extensions}\v!yes
- {\settrue \includeMPextensions\letgvalue{\@@MPF\currentMPgraphicinstance\s!extensions}\v!no}
- {\setfalse\includeMPextensions}%
- \doifelsevalue{\@@MPF\currentMPgraphicinstance\s!initializations}\v!yes
- {\settrue \includeMPinitializations}%
- {\setfalse\includeMPinitializations}}
-
-\def\dostopcurrentMPgraphic
- {\global\MPinstancetoks\emptytoks
+ \edef\p_extensions{\MPinstanceparameter\s!extensions}%
+ \ifx\p_extensions\v!yes
+ \settrue \c_meta_include_extensions
+ \global\letMPinstanceparameter\s!extensions\v!no % needs checking
+ \else
+ \setfalse\c_meta_include_extensions
+ \fi
+ \edef\p_initializations{\MPinstanceparameter\s!initializations}%
+ \ifx\p_initializations\v!yes
+ \settrue \c_meta_include_initializations
+ \else
+ \setfalse\c_meta_include_initializations
+ \fi
+ \edef\p_setups{\MPinstanceparameter\c!setups}%
+ \ifx\p_setups\empty \else
+ \setups[\p_setups]%
+ \fi
+ \useMPinstancestyleandcolor\c!textstyle\c!textcolor}
+
+\def\meta_stop_current_graphic
+ {\global\t_meta_instance\emptytoks
\endgroup}
-\unexpanded\long\def\processMPgraphic#1% todo: extensions and inclusions outside beginfig
- {\dostartcurrentMPgraphic
+\unexpanded\def\meta_process_graphic#1% todo: extensions and inclusions outside beginfig
+ {\meta_start_current_graphic
\forgetall
- \setbox\MPgraphicbox\hbox\bgroup % ; added 20100901 (as in mkii)
+ \setbox\b_meta_graphic\hbox\bgroup % ; added 20100901 (as in mkii)
\normalexpanded{\noexpand\ctxlua{metapost.graphic(
- "\currentMPgraphicinstance",
- "\currentMPgraphicformat",
+ "\currentMPinstance",
+ "\currentMPformat",
\!!bs#1;\!!es,
- \!!bs\currentMPinitializations;\!!es,
- \!!bs\currentMPpreamble;\!!es,
+ \!!bs\meta_flush_current_initializations;\!!es,
+ \!!bs\meta_flush_current_preamble;\!!es,
\MPaskedfigure
)}}%
\egroup
\placeMPgraphic
- \dostopcurrentMPgraphic}
+ \meta_stop_current_graphic}
\newif\ifsetMPrandomseed \setMPrandomseedtrue % false by default
@@ -187,105 +217,101 @@
\def\theMPrandomseed{randomseed:=\localMPseed}%
\fi\fi}
-%D To be integrated
-
-\def\@@MPG{@MPG@}
+%D Calling up previously defined graphics.
-\def\doifMPgraphicelse#1%
- {\ifcsname\@@MPG#1\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+\def\includeMPgraphic#1% gets expanded !
+ {\ifcsname\??mpgraphic#1\endcsname
+ \csname\??mpgraphic#1\endcsname ; % ; is safeguard
+ \fi}
-\def\includeMPgraphic#1%
- {\executeifdefined{\@@MPG#1};} % ; if not found
+\unexpanded\def\meta_enable_include % public
+ {\let\meta_handle_use_graphic \thirdofthreearguments
+ \let\meta_handle_reusable_graphic\thirdofthreearguments}
-\def\enableincludeMPgraphics
- {\let\handleuseMPgraphic \thirdofthreearguments
- \let\handlereusableMPgraphic\thirdofthreearguments}
+%D Drawings (stepwise built):
-\newif\ifMPdrawingdone \MPdrawingdonefalse
+\newif\ifMPdrawingdone \MPdrawingdonefalse
-\def\finalizeMPdrawing
+\unexpanded\def\finalizeMPdrawing
{\MPdrawingdonetrue}
\let\MPdrawingdata\empty
-\newif\ifMPshiftdrawing \MPshiftdrawingfalse
-
-\def\resetMPdrawing
- {\globallet\MPdrawingdata\empty
+\unexpanded\def\resetMPdrawing
+ {\global\let\MPdrawingdata\empty
\global\MPdrawingdonefalse}
-\def\pushMPdrawing
+\unexpanded\def\pushMPdrawing
{\globalpushmacro\MPdrawingdata
- \globallet\MPdrawingdata\empty}
+ \global\let\MPdrawingdata\empty}
-\def\popMPdrawing
+\unexpanded\def\popMPdrawing
{\globalpopmacro\MPdrawingdata}
-\def\getMPdrawing
+\unexpanded\def\getMPdrawing
{\ifMPdrawingdone
- \expandafter\processMPgraphic\expandafter{\MPdrawingdata}% is this expansion still needed?
+ \expandafter\meta_process_graphic\expandafter{\MPdrawingdata}% is this expansion still needed?
\fi}
\def\startMPdrawing
- {\dosingleempty\dostartMPdrawing}
+ {\dosingleempty\meta_start_drawing}
-\long\def\dostartMPdrawing[#1]#2\stopMPdrawing
+\def\meta_start_drawing[#1]#2\stopMPdrawing
{\relax
\bgroup
- \enableincludeMPgraphics
- \presetMPdefinitions % in case #2 has measures
- \doifelse{#1}{-}{\convertargument#2\to\asciia}{\long\def\asciia{#2}}%
- \long\xdef\MPdrawingdata{\MPdrawingdata\asciia}%
+ \meta_enable_include
+ \meta_preset_definitions % in case #2 has measures
+ \doifelse{#1}{-}{\convertargument#2\to\asciia}{\def\asciia{#2}}%
+ \xdef\MPdrawingdata{\MPdrawingdata\asciia}%
\egroup}
\let\stopMPdrawing\relax
-\long\def\MPdrawing#1%
+\def\MPdrawing#1%
{\relax
\bgroup
- \enableincludeMPgraphics
- \presetMPdefinitions
- \long\xdef\MPdrawingdata{\MPdrawingdata#1}%
+ \meta_enable_include
+ \meta_preset_definitions
+ \xdef\MPdrawingdata{\MPdrawingdata#1}%
\egroup}
-\let\stopMPclip\relax
+\unexpanded\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less
+ {\setgvalue{\??mpclip#1}{#2}}
-\long\def\startMPclip#1#2\stopMPclip % todo: store at the lua end or just store less
- {\long\setgvalue{MPC:#1}{#2}}
+\let\stopMPclip\relax
-\def\grabMPclippath#1#2#3#4#5% #5 is alternative
+\unexpanded\def\meta_grab_clip_path#1#2#3#4% #4 is alternative (called in backend code)
{\begingroup
- \edef\width {#3\space}\let\overlaywidth \width
- \edef\height{#4\space}\let\overlayheight\height
- \ifcsname MPC:#1\endcsname
- \dostartcurrentMPgraphic
+ \edef\width {#2\space}\let\overlaywidth \width
+ \edef\height{#3\space}\let\overlayheight\height
+ \ifcsname\??mpclip#1\endcsname
+ \meta_start_current_graphic
\xdef\MPclippath{\normalexpanded{\noexpand\ctxlua{metapost.theclippath(
- "\currentMPgraphicinstance",
- "\currentMPgraphicformat",
- \!!bs\getvalue{MPC:#1}\!!es,
- \!!bs\currentMPinitializations\!!es,
- \!!bs\currentMPpreamble\!!es
+ "\currentMPinstance",
+ "\currentMPformat",
+ \!!bs\getvalue{\??mpclip#1}\!!es,
+ \!!bs\meta_flush_current_initializations\!!es,
+ \!!bs\meta_flush_current_preamble\!!es
)}}}%
- \dostopcurrentMPgraphic
- \ifx\MPclippath\empty\xdef\MPclippath{#5}\fi
+ \meta_stop_current_graphic
+ \ifx\MPclippath\empty
+ \xdef\MPclippath{#4}%
+ \fi
\else
- \xdef\MPclippath{#5}%
+ \xdef\MPclippath{#4}%
\fi
- % #2 : method is obsolete, only pdf now, we can always
- % gsub the result to ps
\endgroup}
-%D Next we will use these support macros.
-
-\startMPextensions
- if unknown context_tool: input mp-tool; fi;
- if unknown context_spec: input mp-spec; fi;
- if unknown context_grph: input mp-grph; fi;
-\stopMPextensions
-
%D Since we want lables to follow the document settings, we
%D also set the font related variables.
+\unexpanded\def\MPfontsizehskip#1%
+ {\dontleavehmode
+ \begingroup
+ \definedfont[#1]%
+ \hskip\cldcontext{fonts.hashes.parameters[font.current()].designsize}sp\relax
+ \endgroup}
+
\startMPinitializations % scale is not yet ok
defaultfont:="\truefontname{Regular}";
defaultscale:=\the\bodyfontsize/10pt;
@@ -297,26 +323,13 @@
defaultfont:="rm-lmtt10";
\stopMPinitializations
-%D A signal that we're in combines \CONTEXT||\METAFUN mode:
+%D A signal that we're in combined \CONTEXT||\METAFUN mode:
\startMPextensions
string contextversion;
contextversion:="\contextversion";
\stopMPextensions
-%D Some safeguards:
-%D
-%D \starttyping
-%D \appendtoks \cleanupfeatures \to \everyMPgraphic
-%D \stoptyping
-%D
-%D No, we don't want that (else we loose UTF etc).
-
-%D Another one:
-
-\prependtoks \MPstaticgraphictrue \to \everyoverlay
-\prependtoks \MPstaticgraphictrue \to \everypagebody
-
%D \macros
%D {setupMPvariables}
%D
@@ -331,43 +344,102 @@
%D \setupMPvariables[meta:button][size=20pt]
%D \stoptyping
-\def\@@meta{meta:}
+% \startlines
+% \def\xxx{\lineheight} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{2pt} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{2} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{\scratchcounter} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{red} \doprepareMPvariable{xxx} \xxx
+% \def\xxx{0.4} \doprepareMPvariable{xxx} \xxx
+% \stoplines
+
+% currently the inheritance of backgrounds does not work and
+% we might drop it anyway (too messy)
+
+\newbox\b_meta_variable_box
+
+\let \currentmpvariableclass \empty
+\let \m_meta_current_variable \empty
+\let \m_meta_current_variable_template\empty
+
+\def \meta_prepare_variable_default {\MPcolor{black}} % just to be sure we use a color but ...
+\edef\meta_unknown_variable_template {\??gv:\s!unknown}
+
+\letvalue{\??gv:\s!unknown}\empty
\unexpanded\def\setupMPvariables
- {\dodoubleempty\dosetupMPvariables}
+ {\dodoubleempty\meta_setup_variables}
-\def\dosetupMPvariables[#1][#2]%
+\def\meta_setup_variables[#1][#2]%
{\ifsecondargument
- \getrawparameters[#1:][#2]% brr, todo: [\@@meta#1:]
+ \getrawparameters[\??gv#1:][#2]%
\else
- \getrawparameters[\@@meta][#1]%
+ \getrawparameters[\??gv:][#1]%
+ \fi}
+
+\unexpanded\def\presetMPvariable
+ {\dodoubleargument\meta_preset_variable}
+
+\def\meta_preset_variable[#1][#2=#3]%
+ {\ifcsname\??gv#1:#2\endcsname \else
+ \setvalue{\??gv#1:#2}{#3}%
\fi}
-\let\@@framed\s!unknown
+\def\MPrawvar#1#2% no checking
+ {\csname\??gv#1:#2\endcsname}
-\def\MPvariable#1%
- {\csname
- \ifcsname\@@framed\@@meta#1\endcsname\@@framed\fi\@@meta#1%
- \endcsname}
+\def\MPvariable#1% todo: could be a framed chain
+ {\csname\??gv\currentmpvariableclass:#1\endcsname}
-\let\MPvar\MPvariable
+\unexpanded\def\useMPvariables
+ {\dodoubleargument\meta_use_variables}
-\let\setMPvariables\setupMPvariables
+\def\meta_use_variables[#1][#2]%
+ {\edef\currentmpvariableclass{#1}%
+ \meta_prepare_variables{#2}}
-\def\MPrawvar#1#2{\csname#1:#2\endcsname}
+\unexpanded\def\meta_prepare_variables#1%
+ {\processcommalist[#1]\meta_prepare_variable}
-\def\presetMPvariable
- {\dodoubleargument\dopresetMPvariable}
+\unexpanded\def\meta_prepare_variable#1%
+ {\edef\m_meta_current_variable_template
+ {\??gv\currentmpvariableclass:#1}%
+ \edef\m_meta_current_variable
+ {\csname\ifcsname\m_meta_current_variable_template\endcsname
+ \m_meta_current_variable_template\else\meta_unknown_variable_template
+ \fi\endcsname}%
+ \ifx\m_meta_current_variable\empty
+ \expandafter\meta_prepare_variable_nop
+ \else
+ \expandafter\meta_prepare_variable_yes
+ \fi}
-\def\dopresetMPvariable[#1][#2=#3]%
- {\ifcsname#1:#2\endcsname\else\setvalue{#1:#2}{#3}\fi}
+\def\meta_prepare_variable_nop
+ {\expandafter \let\csname\m_meta_current_variable_template\endcsname\meta_prepare_variable_default}
-\def\useMPvariables
- {\dodoubleargument\douseMPvariables}
+\def\meta_prepare_variable_color
+ {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\MPcolor\m_meta_current_variable}}
-\def\douseMPvariables[#1][#2]%
- {\def\@@meta{#1:}%
- \prepareMPvariables{#2}}
+\def\meta_prepare_variable_number
+ {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\number\m_meta_current_variable}}% also accepts 0.number
+
+\def\meta_prepare_variable_dimension
+ {\expandafter\edef\csname\m_meta_current_variable_template\endcsname{\the\dimexpr\m_meta_current_variable}}
+
+\def\meta_prepare_variable_yes
+ {\defconvertedcommand\ascii\m_meta_current_variable % otherwise problems
+ \doifcolorelse \ascii % with 2\bodyfontsize
+ {\meta_prepare_variable_color}
+ {\begingroup
+ \setbox\b_meta_variable_box\hbox{\scratchdimen\m_meta_current_variable sp}%
+ \ifzeropt\wd\b_meta_variable_box
+ \endgroup\meta_prepare_variable_number
+ \else
+ \endgroup\meta_prepare_variable_dimension
+ \fi}}
+
+\let\MPvar \MPvariable
+\let\setMPvariables\setupMPvariables
%D \macros
%D {startuniqueMPgraphic, uniqueMPgraphic}
@@ -405,165 +477,161 @@
%D \uniqueMPgraphic{meta:hash}{gap=10pt,angle=30}
%D \stoptyping
-\newcount \MPobjectcounter
-\newbox \MPgraphicbox
-\newconstant\MPboxmode
+\newcount\c_meta_object_counter
+\newbox \b_meta_graphic
-\def\doobeyMPboxdepth % mode = 1
- {\setbox\MPgraphicbox\hbox{\hskip\MPllx\onebasepoint\raise\MPlly\onebasepoint\box\MPgraphicbox}}
+% hm, isn't this already done elsewhere?
+
+\unexpanded\def\meta_obey_box_depth
+ {\setbox\b_meta_graphic\hbox\bgroup
+ \raise\MPlly\box\b_meta_graphic
+ \egroup}
-\def\doignoreMPboxdepth % mode = 2
+\unexpanded\def\meta_ignore_box_depth
{\normalexpanded
- {\noexpand\doobeyMPboxdepth
- \wd\MPgraphicbox\the\wd\MPgraphicbox
- \ht\MPgraphicbox\the\ht\MPgraphicbox
- \dp\MPgraphicbox\the\dp\MPgraphicbox}}
-
-\def\obeyMPboxdepth {\MPboxmode\plusone}
-\def\ignoreMPboxdepth{\MPboxmode\plustwo}
-\def\normalMPboxdepth{\MPboxmode\zerocount}
-
-% compatibility hack:
-
-\let\MPshiftdrawingtrue \ignoreMPboxdepth
-\let\MPshiftdrawingfalse\normalMPboxdepth
-
-\unexpanded\def\placeMPgraphic
- {\ifcase\MPboxmode
- \or % 1
- \doobeyMPboxdepth
- \or % 2
- \doignoreMPboxdepth
- \fi
- \box\MPgraphicbox}
+ {\meta_obey_box_depth % hence the \unexpanded
+ \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
+ {\setbox\b_meta_graphic\hbox\bgroup
+ \hskip\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 }
+
+\let\meta_relocate_box\relax
-\def\reuseMPbox#1#2#3#4#5% space delimiting would save some tokens
- {\xdef\MPllx{#2}% but it's not worth the effort and looks
- \xdef\MPlly{#3}% ugly as well
- \xdef\MPurx{#4}%
- \xdef\MPury{#5}%
+\unexpanded\def\placeMPgraphic % 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
+ {\MPllx#2\MPlly#3\MPurx#4\MPury#5%
\hbox{\forcecolorhack\getobject{MP}{#1}}} % else no proper color intent
-\long\def\handleuniqueMPgraphic#1#2#3%
- {\begingroup
- \def\@@meta{#1:}%
+\def\meta_handle_unique_graphic#1#2#3% when there are too many, we can store data at the lua end, although,
+ {\begingroup % when there are that many they're probably not that unique anyway
+ \edef\currentmpvariableclass{#1}%
\extendMPoverlaystamp{#2}% incl prepare
- \ifcsname\@@MPG\overlaystamp:#1\endcsname\else
- \enableincludeMPgraphics % redundant
- \global\advance\MPobjectcounter\plusone
- \setobject{MP}{\number\MPobjectcounter}\hbox{\processMPgraphic{#3}}% was vbox, graphic must end up as hbox
- \setxvalue{\@@MPG\overlaystamp:#1}{\noexpand\reuseMPbox{\number\MPobjectcounter}{\MPllx}{\MPlly}{\MPurx}{\MPury}}%
+ \ifcsname\??mpgraphic\overlaystamp:#1\endcsname\else
+ \meta_enable_include % redundant
+ \global\advance\c_meta_object_counter\plusone
+ \setobject{MP}{\number\c_meta_object_counter}\hbox{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox
+ \setxvalue{\??mpgraphic\overlaystamp:#1}{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}%
\fi
- \getvalue{\@@MPG\overlaystamp:#1}%
+ \getvalue{\??mpgraphic\overlaystamp:#1}%
\endgroup}
-\long\unexpanded\def\startuniqueMPgraphic
- {\dodoublegroupempty\dostartuniqueMPgraphic}
+\unexpanded\def\startuniqueMPgraphic
+ {\dodoublegroupempty\meta_start_unique_graphic}
+
+\def\meta_start_unique_graphic#1#2#3\stopuniqueMPgraphic
+ {\setgvalue{\??mpgraphic#1}{\meta_handle_unique_graphic{#1}{#2}{#3}}}
-\long\def\dostartuniqueMPgraphic#1#2#3\stopuniqueMPgraphic%
- {\long\setgvalue{\@@MPG#1}{\handleuniqueMPgraphic{#1}{#2}{#3}}}
+\let\stopuniqueMPgraphic\relax
\unexpanded\def\uniqueMPgraphic
- {\dodoublegroupempty\douniqueMPgraphic}
+ {\dodoublegroupempty\meta_unique_graphic}
-\def\douniqueMPgraphic#1#2%
- {\beginMPgraphicgroup{#1}%
+\def\meta_unique_graphic#1#2%
+ {\meta_begin_graphic_group{#1}%
\setupMPvariables[\currentMPgraphicname][#2]%
- \getvalue{\@@MPG\currentMPgraphicname}\empty
- \endMPgraphicgroup}
+ \getvalue{\??mpgraphic\currentMPgraphicname}\empty
+ \meta_end_graphic_group}
-\let\stopuniqueMPcode \relax % so that we can use it in \expanded
-
-\long\def\handleuseMPgraphic#1#2#3%
+\def\meta_handle_use_graphic#1#2#3%
{\begingroup
- \def\@@meta{#1:}%
- \prepareMPvariables{#2}%
- \enableincludeMPgraphics % redundant
- \processMPgraphic{#3}%
+ \edef\currentmpvariableclass{#1}%
+ \meta_prepare_variables{#2}%
+ \meta_enable_include % redundant
+ \meta_process_graphic{#3}%
\endgroup}
-\long\unexpanded\def\startuseMPgraphic
- {\dodoublegroupempty\dostartuseMPgraphic}
+\unexpanded\def\startuseMPgraphic
+ {\dodoublegroupempty\meta_start_use_graphic}
+
+\def\meta_start_use_graphic#1#2#3\stopuseMPgraphic
+ {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
-\long\def\dostartuseMPgraphic#1#2#3\stopuseMPgraphic
- {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}{#3}}}
+\let\stopuseMPgraphic\relax
-\long\unexpanded\def\startusableMPgraphic % redundant but handy
- {\dodoublegroupempty\dostartusableMPgraphic}
+\unexpanded\def\startusableMPgraphic % redundant but handy
+ {\dodoublegroupempty\meta_start_usable_graphic}
-\long\def\dostartusableMPgraphic#1#2#3\stopusableMPgraphic
- {\long\setgvalue{\@@MPG#1}{\handleuseMPgraphic{#1}{#2}{#3}}}
+\def\meta_start_usable_graphic#1#2#3\stopusableMPgraphic
+ {\setgvalue{\??mpgraphic#1}{\meta_handle_use_graphic{#1}{#2}{#3}}}
-\let\stopuseMPgraphic \relax % so that we can use it in \expanded
-\let\stopusableMPgraphic \relax % so that we can use it in \expanded
+\let\stopusableMPgraphic\relax
-\long\def\handlereusableMPgraphic#1#2#3%
+\def\meta_handle_reusable_graphic#1#2#3%
{\begingroup
- \def\@@meta{#1:}%
- \prepareMPvariables{#2}%
- \enableincludeMPgraphics % redundant
- \global\advance\MPobjectcounter\plusone
- \setobject{MP}{\number\MPobjectcounter}\hbox{\processMPgraphic{#3}}% was vbox, graphic must end up as hbox
- \setxvalue{\@@MPG#1}{\noexpand\reuseMPbox{\number\MPobjectcounter}{\MPllx}{\MPlly}{\MPurx}{\MPury}}%
- \getvalue{\@@MPG#1}%
+ \edef\currentmpvariableclass{#1}%
+ \meta_prepare_variables{#2}%
+ \meta_enable_include % redundant
+ \global\advance\c_meta_object_counter\plusone
+ \setobject{MP}{\number\c_meta_object_counter}\hbox{\meta_process_graphic{#3}}% was vbox, graphic must end up as hbox
+ \setxvalue{\??mpgraphic#1}{\meta_reuse_box{\number\c_meta_object_counter}{\the\MPllx}{\the\MPlly}{\the\MPurx}{\the\MPury}}%
+ \getvalue{\??mpgraphic#1}%
\endgroup}
-\long\unexpanded\def\startreusableMPgraphic
- {\dodoublegroupempty\dostartreusableMPgraphic}
+\unexpanded\def\startreusableMPgraphic
+ {\dodoublegroupempty\meta_start_reusable_graphic}
-\long\def\dostartreusableMPgraphic#1#2#3\stopreusableMPgraphic
- {\long\setgvalue{\@@MPG#1}{\handlereusableMPgraphic{#1}{#2}{#3}}}
+\def\meta_start_reusable_graphic#1#2#3\stopreusableMPgraphic
+ {\setgvalue{\??mpgraphic#1}{\meta_handle_reusable_graphic{#1}{#2}{#3}}}
-\let\stopreusableMPgraphic \relax % so that we can use it in \expanded
+\let\stopreusableMPgraphic\relax
\unexpanded\def\useMPgraphic
- {\dodoublegroupempty\douseMPgraphic}
+ {\dodoublegroupempty\meta_use_graphic}
-\def\douseMPgraphic#1#2%
- {\beginMPgraphicgroup{#1}%
+\def\meta_use_graphic#1#2%
+ {\meta_begin_graphic_group{#1}%
\doifsomething{#2}{\setupMPvariables[\currentMPgraphicname][#2]}%
- \getvalue{\@@MPG\currentMPgraphicname}\empty
- \endMPgraphicgroup}
+ \getvalue{\??mpgraphic\currentMPgraphicname}\empty
+ \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
-\let\stopuseMPcode \relax % so that we can use it in \expanded
-\let\stopusableMPcode \relax % so that we can use it in \expanded
-\let\stopreusableMPcode \relax % so that we can use it in \expanded
-\let\stopuniqueMPcode \relax % so that we can use it in \expanded
-
-\def\enableincludeMPgraphics
- {\let\handleuseMPgraphic \thirdofthreearguments
- \let\handlereusableMPgraphic\thirdofthreearguments}
+\unexpanded\def\meta_enable_include
+ {\let\meta_handle_use_graphic \thirdofthreearguments
+ \let\meta_handle_reusable_graphic\thirdofthreearguments}
%D \macros
%D {startuniqueMPpagegraphic,uniqueMPpagegraphic}
%D
%D Experimental.
-\def\MPpageprefix{\doifoddpageelse oe:}
+\def\m_meta_page_prefix{\doifoddpageelse oe}
\def\overlaypagestamp
- {\MPpageprefix\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+ {\m_meta_page_prefix:\overlaywidth:\overlayheight:\overlaydepth:\MPcolor\overlaycolor:\MPcolor\overlaylinecolor}
+
+\unexpanded\def\startuniqueMPpagegraphic
+ {\dodoublegroupempty\meta_start_unique_page_graphic}
-\long\unexpanded\def\startuniqueMPpagegraphic
- {\dodoublegroupempty\dostartuniqueMPpagegraphic}
+\def\meta_start_unique_page_graphic#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
-\long\def\dostartuniqueMPpagegraphic#1#2#3\stopuniqueMPpagegraphic
- {\long\setgvalue{\@@MPG o:#1}{\handleuniqueMPgraphic{o:#1}{#2}{#3}}%
- \long\setgvalue{\@@MPG e:#1}{\handleuniqueMPgraphic{e:#1}{#2}{#3}}}
+\let\stopuniqueMPpagegraphic\relax
\unexpanded\def\uniqueMPpagegraphic
- {\dodoublegroupempty\douniqueMPpagegraphic}
+ {\dodoublegroupempty\meta_unique_page_graphic}
-\def\douniqueMPpagegraphic#1#2%
- {\beginMPgraphicgroup{#1}%
+\def\meta_unique_page_graphic#1#2%
+ {\meta_begin_graphic_group{#1}%
\let\overlaystamp\overlaypagestamp
- \setupMPvariables[\MPpageprefix\currentMPgraphicname][#2]% prefix is new here
- \getvalue{\@@MPG\MPpageprefix\currentMPgraphicname}{}%
- \endMPgraphicgroup}
-
+ \setupMPvariables[\m_meta_page_prefix:\currentMPgraphicname][#2]% prefix is new here
+ \getvalue{\??mpgraphic\m_meta_page_prefix:\currentMPgraphicname}{}%
+ \meta_end_graphic_group}
+
%D One way of defining a stamp is:
%D
%D \starttyping
@@ -576,59 +644,23 @@
%D Since we need to feed \METAPOST\ with expanded dimensions,
%D we introduce a dedicated expansion engine.
-\def\prepareMPvariable#1%
- {\ifcsname\@@framed\@@meta#1\endcsname
- \doprepareMPvariable{\@@framed\@@meta#1}%
- \else
- \doprepareMPvariable{\@@meta#1}%
- \fi}
-
-% \startlines
-% \def\xxx{\lineheight} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{2pt} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{2} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{\scratchcounter} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{red} \doprepareMPvariable{xxx} \xxx
-% \def\xxx{0.4} \doprepareMPvariable{xxx} \xxx
-% \stoplines
-
-\def\doprepareMPvariable#1%
- {\edef\theMPvariable{\getvalue{#1}}%
- \doifelsenothing\theMPvariable
- {\setevalue{#1}{\MPcolor{black}}}
- {\defconvertedcommand\ascii\theMPvariable % otherwise problems
- \doifcolorelse \ascii % with 2\bodyfontsize
- {\setevalue{#1}{\MPcolor\theMPvariable}}
- {% can be aux macro
- \setbox\scratchbox\hbox{\scratchdimen\theMPvariable sp}%
- \ifdim\wd\scratchbox=\zeropoint
- % \scratchcounter\theMPvariable
- % \setevalue{#1}{\the\scratchcounter}%
- % also accepts 0.number :
- \setevalue{#1}{\number\theMPvariable}%
- \else
- \scratchdimen\theMPvariable
- \setevalue{#1}{\the\scratchdimen}%
- \fi}}}
-
%D We redefine \type {\extendMPoverlaystamp} to preprocess
-%D variables using \type {\prepareMPvariable}.
-
-\def\doextendMPoverlaystamp#1%
- {\prepareMPvariable{#1}%
- \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}}
+%D variables using \type {\meta_prepare_variable}.
-\def\extendMPoverlaystamp#1%
- {\processcommalist[#1]\doextendMPoverlaystamp}
+\unexpanded\def\extendMPoverlaystamp#1%
+ {\processcommalist[#1]\meta_extend_overlay_stamp}
-\def\prepareMPvariables#1%
- {\processcommalist[#1]\prepareMPvariable}
+\def\meta_extend_overlay_stamp#1%
+ {\meta_prepare_variable{#1}%
+ \edef\overlaystamp{\overlaystamp:\MPvariable{#1}}}
%D \macros
%D {MPdatafile}
%D
%D We redefine a macro from \type {supp-mps.tex}:
+% This will change ...
+
\def\MPdataMPDfile{\jobname-mpgraph.mpd}
\def\MPdataMPOfile{\jobname-mpgraph.mpo}
\def\MPdataMPYfile{\jobname-mpgraph.mpy}
@@ -640,7 +672,7 @@
def data_mpy_file = "\MPdataMPYfile" enddef ;
\stopMPextensions
-\def\getMPdata
+\unexpanded\def\getMPdata
{\let\MPdata\secondoftwoarguments
\startreadingfile
% \startnointerference % no, else we need to do all data global
@@ -648,37 +680,24 @@
% \stopnointerference
\stopreadingfile}
-%D For the moment, the next one is a private macro:
-
-\def\processMPbuffer
- {\dosingleempty\doprocessMPbuffer}
-
-\def\doprocessMPbuffer[#1]%
- {\doifelsenothing{#1}
- {\dodoprocessMPbuffer{\jobname}}
- {\dodoprocessMPbuffer{#1}}}
+% We need this trick because we need to make sure that the tex scanner
+% sees newlines and does not quit. Also, we do need to flush the buffer
+% under a normal catcode regime in order to expand embedded tex macros.
+% As usual with buffers, \type {#1} can be a list.
-% we need to go via a toks because we have no multiline print in
-% luatex (i.e. tex.sprint does not interpret lines) and therefore
-% omits all after a comment token
+\unexpanded\def\processMPbuffer
+ {\dosingleempty\meta_process_buffer}
-\newtoks\mpbuffertoks
+\def\meta_process_buffer[#1]%
+ {\meta_begin_graphic_group{#1}%
+ \meta_process_graphic{\ctxcommand{feedback("\currentMPgraphicname")}}%
+ \meta_end_graphic_group}
-\def\doprocessMPbuffer[#1]%
- {\doifelsenothing{#1}
- {\doprocessMPbuffer[\jobname]}
- {\beginMPgraphicgroup{#1}%
- % we need this trick because tex.sprint does not interprets newlines and the scanner
- % stops at a newline; also, we do need to flush the buffer under a normal catcode
- % regime in order to expand embedded tex macros; #1 can be a list
- \processMPgraphic{\ctxcommand{feedback("\currentMPgraphicname")}}%
- \endMPgraphicgroup}}
+\unexpanded\def\runMPbuffer
+ {\dosingleempty\meta_run_buffer}
-\def\runMPbuffer
- {\dosingleempty\dorunMPbuffer}
-
-\def\dorunMPbuffer[#1]% processing only
- {\startnointerference\doprocessMPbuffer[#1]\stopnointerference}
+\def\meta_run_buffer[#1]% processing only
+ {\startnointerference\meta_process_buffer[#1]\stopnointerference}
%D \macros
%D {startMPenvironment, resetMPenvironment}
@@ -686,25 +705,43 @@
%D In order to synchronize the main \TEX\ run and the runs
%D local to \METAPOST, environments can be passed.
-\ifx\everyMPTEXgraphic\undefined
- \newtoks\everyMPTEXgraphic
-\fi
-
-%D A more general way of passing environments is:
-
-\def\startMPenvironment % second arg gobbles spaces, so that reset gives \emptytoks
- {\dodoubleempty\dostartMPenvironment}
-
-\long\def\dostartMPenvironment[#1][#2]#3\stopMPenvironment
- {\doif{#1}\s!reset\resetMPenvironment % reset mp toks
- \doif{#1}\v!global{#3}% % use in main doc too
- \doif{#1}+{#3}% % use in main doc too
- \ctxlua{metapost.tex.set(\!!bs\detokenize{#3}\!!es)}}
-
-\def\resetMPenvironment
+% \unexpanded\def\startMPenvironment % second arg gobbles spaces, so that reset gives \emptytoks
+% {\dodoubleempty\dostartMPenvironment}
+
+% \def\dostartMPenvironment[#1][#2]#3\stopMPenvironment
+% {\edef\m_meta_option{#1}
+% \ifx\m_meta_option\s!reset
+% \resetMPenvironment % reset mp toks
+% \else\ifx\m_meta_option\v!global
+% #3% % use in main doc too
+% \else\ifx\m_meta_option\!!plustoken
+% #3% % use in main doc too
+% \fi\fi\fi
+% \ctxlua{metapost.tex.set(\!!bs\detokenize{#3}\!!es)}}
+
+\unexpanded\def\startMPenvironment
+ {\begingroup
+ \catcode\endoflineasciicode \ignorecatcode
+ \dosingleempty\dostartMPenvironment}
+
+\def\dostartMPenvironment[#1]#2\stopMPenvironment
+ {\endgroup
+ \edef\m_meta_option{#1}
+ \ifx\m_meta_option\s!reset
+ \resetMPenvironment % reset mp toks
+ \else\ifx\m_meta_option\v!global
+ #2% % use in main doc too
+ \else\ifx\m_meta_option\!!plustoken
+ #2% % use in main doc too
+ \fi\fi\fi
+ \ctxlua{metapost.tex.set(\!!bs\detokenize{#2}\!!es)}}
+
+\let\stopMPenvironment\relax
+
+\unexpanded\def\resetMPenvironment
{\ctxlua{metapost.tex.reset()}}
-\def\useMPenvironmentbuffer[#1]%
+\unexpanded\def\useMPenvironmentbuffer[#1]%
{\ctxlua{metapost.tex.set(buffers.content("#1"))}}
%D This command takes \type {[reset]} as optional
@@ -722,41 +759,45 @@
%D
%D The most simple case:
-\def\startMPcode{\dosinglegroupempty\dostartMPcode}
+\unexpanded\def\startMPcode
+ {\dosinglegroupempty\meta_start_code}
-\def\dostartMPcode
+\def\meta_start_code
{\iffirstargument
- \expandafter\dodostartMPcode
+ \expandafter\meta_start_code_instance
\else
- \expandafter\nodostartMPcode
+ \expandafter\meta_start_code_standard
\fi}
-\def\dodostartMPcode#1#2\stopMPcode
- {\beginMPgraphicgroup{#1::\s!dummy}% name does not matter
- \processMPgraphic{#2}%
- \endMPgraphicgroup}
+\def\meta_start_code_instance#1#2\stopMPcode
+ {\meta_begin_graphic_group{#1::\s!dummy}% name does not matter
+ \meta_enable_include
+ \meta_process_graphic{#2}%
+ \meta_end_graphic_group}
-\def\nodostartMPcode#1#2\stopMPcode
- {\processMPgraphic{#2}}
+\def\meta_start_code_standard#1#2\stopMPcode
+ {\let\currentMPinstance\defaultMPinstance
+ \meta_process_graphic{#2}}
\let\stopMPcode\relax
-\def\MPcode{\dosinglegroupempty\doMPcode}
+\unexpanded\def\MPcode
+ {\dosinglegroupempty\meta_code}
-\def\doMPcode
+\def\meta_code
{\iffirstargument
- \expandafter\dodoMPcode
+ \expandafter\meta_code_instance
\else
- \expandafter\nodoMPcode
+ \expandafter\meta_code_standard
\fi}
-\def\dodoMPcode#1#2%
- {\beginMPgraphicgroup{#1::\s!dummy}% name does not matter
- \processMPgraphic{#2}%
- \endMPgraphicgroup}
+\def\meta_code_instance#1#2%
+ {\meta_begin_graphic_group{#1::\s!dummy}% name does not matter
+ \meta_process_graphic{#2}%
+ \meta_end_graphic_group}
-\def\nodoMPcode#1#2%
- {\processMPgraphic{#2}}
+\def\meta_code_standard#1% #2
+ {\meta_process_graphic}
% a bit nasty (also needed for compatibility:
@@ -766,9 +807,9 @@
% \startMPrun{mprun} input mp-www.mp ; \stopMPrun % instance
% \externalfigure[mprun.4][width=10cm,height=8cm]
-\let\MPruninstance\defaultMPgraphicinstance
+\let\MPruninstance\defaultMPinstance
-\def\useMPrun#1#2% name n
+\unexpanded\def\useMPrun#1#2% name n
{\begingroup
\def\MPaskedfigure{#2}%
\doifelsenothing{#1}
@@ -776,34 +817,17 @@
{\useMPgraphic{#1}}%
\endgroup}
-\def\startMPrun
- {\dosinglegroupempty\dostartMPrun}
+\unexpanded\def\startMPrun
+ {\dosinglegroupempty\meta_start_run}
-\long\def\dostartMPrun#1#2\stopMPrun
+\def\meta_start_run#1#2\stopMPrun
{\iffirstargument
\startuseMPgraphic{#1}#2\stopuseMPgraphic
\else
\startuseMPgraphic{mprun}#2\stopuseMPgraphic
\fi}
-% for old time sake
-
-\def\dostartMPgraphic
- {\iffirstargument
- \expandafter\dodostartMPgraphic
- \else
- \expandafter\nodostartMPgraphic
- \fi}
-
-\def\dodostartMPgraphic#1#2\stopMPgraphic
- {\beginMPgraphicgroup{#1::\s!dummy}% name does not matter
- \processMPgraphic{#2}%
- \endMPgraphicgroup}
-
-\def\nodostartMPgraphic#1#2\stopMPcode
- {\processMPgraphic{#2}}
-
-\let\stopMPcode\relax
+\let\stopMPrun\relax
%D The \type {\resetMPenvironment} is a quick way to erase
%D the token list.
@@ -830,7 +854,7 @@
%D Loading specific \METAPOST\ related definitions is
%D accomplished by:
-\unexpanded\def\useMPlibrary[#1]{\ctxlua{metapost.uselibrary(\!!bs#1\!!es)}}
+\unexpanded\def\useMPlibrary[#1]{\ctxcommand{useMPlibrary(\!!bs#1\!!es)}}
%D \macros
%D {setMPtext, MPtext, MPstring, MPbetex}
@@ -845,34 +869,32 @@
%D \MPbetex {identifier}
%D \stoptyping
-\def\@@MPT{@MPT@}
+\installcorenamespace{mptext}
-\def\forceMPTEXgraphic
- {\long\def\checkMPTEXgraphic##1{\global\MPTEXgraphictrue}}
+\unexpanded\def\setMPtext#1#2% todo : #1 must be made : safe
+ {\defconvertedargument\ascii{#2}%
+ \dodoglobal\letvalue{\??mptext#1}\ascii}
-\def\setMPtext#1#2% todo : #1 must be made : safe
- {%\forceMPTEXgraphic
- \defconvertedargument\ascii{#2}%
- \dodoglobal\letvalue{\@@MPT#1}\ascii}
+\def\MPtext #1{\executeifdefined{\??mptext#1}\empty}
+\def\MPstring#1{"\executeifdefined{\??mptext#1}\empty"}
+\def\MPbetex #1{btex \executeifdefined{\??mptext#1}\empty\space etex}
-\def\MPtext #1{\executeifdefined{\@@MPT#1}\empty}
-\def\MPstring #1{"\executeifdefined{\@@MPT#1}\empty"}
-\def\MPbetex #1{btex \executeifdefined{\@@MPT#1}\empty\space etex}
+%D In order to communicate conveniently with the \TEX\
+%D engine, we introduce some typesetting variables.
-%D Unfortunately \METAPOST\ does not have \CMYK\ support
-%D built in, but by means of specials we can supply the
-%D information needed to handle them naturaly.
+% \setupcolors[state=stop,conversion=never] % quite tricky ... type mismatch
-% \newif\ifMPcmykcolors \MPcmykcolorstrue
-% \newif\ifMPspotcolors \MPspotcolorstrue
+% A dirty trick, ** in colo-ini.lua (mpcolor).
-\startMPinitializations
- cmykcolors:=\ifMPcmykcolors true\else false\fi;
- spotcolors:=\ifMPspotcolors true\else false\fi;
-\stopMPinitializations
+% \def\m_meta_colo_initializations{%
+% OverlayLineColor:=\MPcolor{\overlaylinecolor};
+% OverlayColor:=\MPcolor{\overlaycolor};
+% }
-%D In order to communicate conveniently with the \TEX\
-%D engine, we introduce some typesetting variables.
+\def\m_meta_colo_initializations{%
+ vardef OverlayLineColor=\MPcolor{\overlaylinecolor} enddef;
+ vardef OverlayColor=\MPcolor{\overlaycolor} enddef;
+}
\startMPextensions
color OverlayColor,OverlayLineColor;
@@ -883,9 +905,13 @@
OverlayWidth:=\overlaywidth;
OverlayHeight:=\overlayheight;
OverlayDepth:=\overlayheight;
- OverlayColor:=\MPcolor{\overlaycolor};
OverlayLineWidth:=\overlaylinewidth;
- OverlayLineColor:=\MPcolor{\overlaylinecolor};
+ %
+ \m_meta_colo_initializations
+% OverlayLineColor:=\MPcolor{\overlaylinecolor};
+% OverlayColor:=\MPcolor{\overlaycolor};
+% vardef OverlayLineColor=\MPcolor{\overlaylinecolor} enddef;
+% vardef OverlayColor=\MPcolor{\overlaycolor} enddef;
%
BaseLineSkip:=\the\baselineskip;
LineHeight:=\the\baselineskip;
@@ -911,10 +937,9 @@
\disablecompoundcharacters
\to \everyMPgraphic
-\appendtoks % before color
- %\normalexpanded{\noexpand\definecolor[currentcolor][\currentcolorname]}%
- \doregistercolor{currentcolor}\currentcolorname
-\to \everyMPgraphic
+% \appendtoks % before color, inefficient, replace by low level copy
+% \doregistercolor{currentcolor}\currentcolorname
+% \to \everyMPgraphic
% \color[green]{abc \startMPcode
% fill fullcircle scaled 3cm withoutcolor;
@@ -922,10 +947,6 @@
% fill fullcircle scaled 1cm withcolor \MPcolor{red} ;
% \stopMPcode def}
-% \appendtoks
-% \doactivatecolor\s!black\forcecolorhack % we can also move this to the backend
-% \to \everyMPgraphic
-
\appendtoks
\baselineskip1\baselineskip
\lineheight 1\lineheight
@@ -999,26 +1020,20 @@
%D can occur. One took me over a day to uncover when
%D processing the screen version of the \METAFUN\ manual.
-%D For my eyes only:
+\def\doifelseMPgraphic#1%
+ {\ifcsname\??mpgraphic #1\endcsname \expandafter \firstoftwoarguments \else
+ \ifcsname\??mpgraphic o:#1\endcsname \doubleexpandafter\firstoftwoarguments \else
+ \ifcsname\??mpgraphic e:#1\endcsname \tripleexpandafter\firstoftwoarguments \else
+ \tripleexpandafter\secondoftwoarguments \fi\fi\fi}
-\def\doifelseMPgraphic#1{\doifdefinedelse{\@@MPG#1}}
-
-%D \macros
-%D {startMPcolor}
-
-\long\unexpanded\def\startMPcolor#1\stopMPcolor
- {\writestatus \m!metapost % eventually this placeholder will go away
- {\string\startMPcolor...\stopMPcolor\space is obsolete,\space
- use \string\defineintermediatecolor\space instead}}
-
-\let\stopMPcolor\relax
+\let\doifMPgraphicelse\doifelseMPgraphic
%D New:
\definelayerpreset % no dx,dy - else nasty non-mp placement
[mp]
- [\c!y=-\MPury bp,
- \c!x=\MPllx bp,
+ [\c!y=-\MPury,
+ \c!x=\MPllx,
\c!method=\v!fit]
\definelayer
@@ -1085,38 +1100,27 @@
%D
%D \typebuffer \getbuffer
-\def\usestaticMPfigure
- {\dodoubleempty\dousestaticMPfigure}
-
-\def\dousestaticMPfigure[#1][#2]%
- {\ifsecondargument
- \scale[#2]{\reuseMPgraphic{\@@MPG#1@S@}}%
- \else
- \reuseMPgraphic{\@@MPG#1@S@}%
- \fi}
-
\unexpanded\def\startstaticMPfigure#1#2\stopstaticMPfigure
- {\startreusableMPgraphic{\@@MPG#1@S@}#2\stopreusableMPgraphic}
+ {\startreusableMPgraphic{\??mpstaticgraphic#1}#2\stopreusableMPgraphic}
-\long\unexpanded\def\startstaticMPgraphic
- {\dodoublegroupempty\dostartstaticMPgraphic}
+\unexpanded\def\startstaticMPgraphic
+ {\dodoublegroupempty\meta_start_static_graphic}
-\long\def\dostartstaticMPgraphic#1#2#3\stopstaticMPgraphic
- {\long\setgvalue{\@@MPG#1@S@}{\handlereusableMPgraphic{#1}{#2}{#3}}}
+\def\meta_start_static_graphic#1#2#3\stopstaticMPgraphic
+ {\startreusableMPgraphic{\??mpstaticgraphic#1}{#2}#3\stopreusableMPgraphic}
-%D New:
-
-\newconditional\manyMPspecials % when set to true, > 1000 specials can be used
-
-\settrue \manyMPspecials % per 1/4/2006
-
-\prependtoks
- _special_div_ := 1000\ifconditional\manyMPspecials0\fi ;
-\to \MPextensions
+\let\stopstaticMPfigure \relax
+\let\stopstaticMPgraphic\relax
-%D Needed too.
+\unexpanded\def\usestaticMPfigure
+ {\dodoubleempty\meta_use_static_figure}
-\let\initializeMPgraphics\relax
+\def\meta_use_static_figure[#1][#2]%
+ {\ifsecondargument
+ \scale[#2]{\reuseMPgraphic{\??mpstaticgraphic#1}}%
+ \else
+ \reuseMPgraphic{\??mpstaticgraphic#1}%
+ \fi}
%D Goody for preventing overflows:
@@ -1160,10 +1164,8 @@
\newconstant\MPcolormethod
-% can be faster, just
-
\appendtoks
- \ctxlua{metapost.setoutercolor(\number\MPcolormethod,\number\currentcolormodel,\number\dogetattribute{color},\number\dogetattribute{transparency})}%
+ \ctxlua{metapost.setoutercolor(\number\MPcolormethod,\number\attribute\colormodelattribute,\number\attribute\colorattribute,\number\dogetattribute{transparency})}%
\to \everyMPgraphic
\startMPinitializations
@@ -1175,7 +1177,7 @@
%D
%D Here is a generic setup command:
-\newtoks \everysetupMPgraphics
+\newtoks\everysetupMPgraphics
\unexpanded\def\setupMPgraphics[#1]%
{\getparameters[\??mp][#1]%
diff --git a/Master/texmf-dist/tex/context/base/meta-mis.mkii b/Master/texmf-dist/tex/context/base/meta-mis.mkii
index 29ab43007e7..e8282c381b8 100644
--- a/Master/texmf-dist/tex/context/base/meta-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Misc Test Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-nav.mkii b/Master/texmf-dist/tex/context/base/meta-nav.mkii
index 9c1cbb4dbb4..45a31ba5ecf 100644
--- a/Master/texmf-dist/tex/context/base/meta-nav.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-nav.mkii
@@ -5,7 +5,7 @@
%D subtitle=Navigational Graphics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-pag.mkii b/Master/texmf-dist/tex/context/base/meta-pag.mkii
index 000e56a2eb5..82a525a0820 100644
--- a/Master/texmf-dist/tex/context/base/meta-pag.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-pag.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-pag.mkiv b/Master/texmf-dist/tex/context/base/meta-pag.mkiv
index ef3817721be..6cea270e3c9 100644
--- a/Master/texmf-dist/tex/context/base/meta-pag.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-pag.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,72 +19,68 @@
\unprotect
-\startMPextensions
- if unknown context_page: input mp-page; fi;
-\stopMPextensions
-
%D The next few macros tell \METAPOST\ how the \CONTEXT\
%D pagebody looks.
\startMPextensions
- boolean PageStateAvailable,OnRightPage,InPageBody;
- PageStateAvailable:=true;
+ boolean PageStateAvailable,OnRightPage,InPageBody;
+ PageStateAvailable:=true;
\stopMPextensions
\startMPinitializations
- OnRightPage:=true;
- InPageBody:=\ifinpagebody true \else false \fi;
+ OnRightPage:=true;
+ InPageBody:=\ifinpagebody true \else false \fi;
\stopMPinitializations
\startMPinitializations
- def LoadPageState =
- OnRightPage:=\MPonrightpage;
- OnOddPage:=\MPonoddpage;
- RealPageNumber:=\the\realpageno;
- PageNumber:=\the\pageno;
- NOfPages:=\lastpage;
- PaperHeight:=\the\paperheight;
- PaperWidth:=\the\paperwidth;
- PrintPaperHeight:=\the\printpaperheight;
- PrintPaperWidth:=\the\printpaperwidth;
- TopSpace:=\the\topspace;
- BottomSpace:=\the\bottomspace;
- BackSpace:=\the\backspace;
- CutSpace:=\the\cutspace;
- MakeupHeight:=\the\makeupheight;
- MakeupWidth:=\the\makeupwidth;
- TopHeight:=\the\topheight;
- TopDistance:=\the\topdistance;
- HeaderHeight:=\the\headerheight;
- HeaderDistance:=\the\headerdistance;
- TextHeight:=\the\textheight;
- FooterDistance:=\the\footerdistance;
- FooterHeight:=\the\footerheight;
- BottomDistance:=\the\bottomdistance;
- BottomHeight:=\the\bottomheight;
- LeftEdgeWidth:=\the\leftedgewidth;
- LeftEdgeDistance:=\the\leftedgedistance;
- LeftMarginWidth:=\the\leftmarginwidth;
- LeftMarginDistance:=\the\leftmargindistance;
- TextWidth:=\the\textwidth ;
- RightMarginDistance:=\the\rightmargindistance;
- RightMarginWidth:=\the\rightmarginwidth;
- RightEdgeDistance:=\the\rightedgedistance;
- RightEdgeWidth:=\the\rightedgewidth;
- InnerMarginDistance:=\the\innermargindistance;
- InnerMarginWidth:=\the\innermarginwidth;
- OuterMarginDistance:=\the\outermargindistance;
- OuterMarginWidth:=\the\outermarginwidth;
- InnerEdgeDistance:=\the\inneredgedistance;
- InnerEdgeWidth:=\the\inneredgewidth;
- OuterEdgeDistance:=\the\outeredgedistance;
- OuterEdgeWidth:=\the\outeredgewidth;
- PageOffset:=\the\pageoffset;
- PageDepth:=\the\pagedepth;
- LayoutColumns:=\the\layoutcolumns;
- LayoutColumnDistance:=\the\layoutcolumndistance;
- LayoutColumnWidth:=\the\layoutcolumnwidth;
- enddef;
+ def LoadPageState =
+ OnRightPage:=\MPonrightpage;
+ OnOddPage:=\MPonoddpage;
+ RealPageNumber:=\the\realpageno;
+ PageNumber:=\the\pageno;
+ NOfPages:=\lastpage;
+ PaperHeight:=\the\paperheight;
+ PaperWidth:=\the\paperwidth;
+ PrintPaperHeight:=\the\printpaperheight;
+ PrintPaperWidth:=\the\printpaperwidth;
+ TopSpace:=\the\topspace;
+ BottomSpace:=\the\bottomspace;
+ BackSpace:=\the\backspace;
+ CutSpace:=\the\cutspace;
+ MakeupHeight:=\the\makeupheight;
+ MakeupWidth:=\the\makeupwidth;
+ TopHeight:=\the\topheight;
+ TopDistance:=\the\topdistance;
+ HeaderHeight:=\the\headerheight;
+ HeaderDistance:=\the\headerdistance;
+ TextHeight:=\the\textheight;
+ FooterDistance:=\the\footerdistance;
+ FooterHeight:=\the\footerheight;
+ BottomDistance:=\the\bottomdistance;
+ BottomHeight:=\the\bottomheight;
+ LeftEdgeWidth:=\the\leftedgewidth;
+ LeftEdgeDistance:=\the\leftedgedistance;
+ LeftMarginWidth:=\the\leftmarginwidth;
+ LeftMarginDistance:=\the\leftmargindistance;
+ TextWidth:=\the\textwidth ;
+ RightMarginDistance:=\the\rightmargindistance;
+ RightMarginWidth:=\the\rightmarginwidth;
+ RightEdgeDistance:=\the\rightedgedistance;
+ RightEdgeWidth:=\the\rightedgewidth;
+ InnerMarginDistance:=\the\innermargindistance;
+ InnerMarginWidth:=\the\innermarginwidth;
+ OuterMarginDistance:=\the\outermargindistance;
+ OuterMarginWidth:=\the\outermarginwidth;
+ InnerEdgeDistance:=\the\inneredgedistance;
+ InnerEdgeWidth:=\the\inneredgewidth;
+ OuterEdgeDistance:=\the\outeredgedistance;
+ OuterEdgeWidth:=\the\outeredgewidth;
+ PageOffset:=\the\pageoffset;
+ PageDepth:=\the\pagedepth;
+ LayoutColumns:=\the\layoutcolumns;
+ LayoutColumnDistance:=\the\layoutcolumndistance;
+ LayoutColumnWidth:=\the\layoutcolumnwidth;
+ enddef;
\stopMPinitializations
\def\MPonrightpage{true}
@@ -94,130 +90,28 @@
{\edef\MPonrightpage{\doifbothsides {tru}{tru}{fals}e}%
\edef\MPonoddpage {\doifoddpageelse {tru}{fals}e}}
-\let\freezeMPlayout\relax % obsolete
-
%D We need to freeze the pagelayout before the backgrounds
%D are build, because the overlay will temporarily become
%D zero (overlay).
\appendtoks
- \freezeMPpagelayout
+ \freezeMPpagelayout
\to \everybeforepagebody
%D By freezing these value every graphic, we can use layout
%D variables that change halfways a page, whatever use that
%D has.
-\prependtoks
- \calculatereducedvsizes % this is really needed
- \freezeMPpagelayout
- \freezeMPlayout % to be used grouped
-\to \everyMPgraphic
-
-%D The next feature provides information about for instance
-%D column positions. This is an experimental feature,
-%D introduced when we needed backgrounds in columns (fill||in
-%D questions as implemented in a private module).
-%D
-%D See \type {mp-page.mp} for the definition of the macros:
-%D
-%D \starttabulate[|tl|l|p|]
-%D \NC ResetTextAreas \NC no arguments \NC
-%D reset areas on page \NC \NR
-%D \NC RegisterTextArea \NC x, y, w, h \NC
-%D adds area to the list \NC \NR
-%D \NC TextAreaX,Y,W,H,XY,WH \NC x and/or y \NC
-%D reports offsets and dimensions \NC \NR
-%D \stoptabulate
-%D
-%D The \type {TextArea*} macros can be used to determine
-%D overlap.
-
-\newcount\currentMPtextareadata
-
-\newtoks\MPsavedtextareadata
-\newtoks\MPtextareadata
-\newtoks\MPlocaltextareadata
-
-% optimaliseren voor herhaling
-
-\def\registerMPtextarea#1%
- {\ifpositioning
- \bgroup
- \global\advance\currentMPtextareadata\plusone
- %\hpos{gbd:\the\currentMPtextareadata}{#1}%
- \hpos{gbd:\the\currentMPtextareadata}%
- {\iftracetextareas\boxrulewidth1.5pt\ruledhbox\fi{#1}}%
- \edef\!!stringa{gbd:\the\currentMPtextareadata}%
- \edef\!!stringa{RegisterTextArea(%
- \MPx\!!stringa,\MPy\!!stringa,%
- \MPw\!!stringa,\MPh\!!stringa,\MPd\!!stringa);}%
- \@EA \doglobal \@EA \appendtoks \!!stringa \to \MPtextareadata
- \egroup
- \else
- \hbox{#1}%
- \fi}
-
-\def\registerMPlocaltextarea#1%
- {\ifpositioning
- \bgroup
- \global\advance\currentMPtextareadata\plusone
- %\hpos{gbd:\the\currentMPtextareadata}{#1}%
- \hpos{gbd:\the\currentMPtextareadata}%
- {\iftracetextareas\boxrulewidth3pt\ruledhbox\fi{#1}}%
- \edef\!!stringa{gbd:\the\currentMPtextareadata}%
- \edef\!!stringa{RegisterLocalTextArea(%
- \MPx\!!stringa,\MPy\!!stringa,%
- \MPw\!!stringa,\MPh\!!stringa,\MPd\!!stringa);}%
- \global\MPlocaltextareadata\@EA{\!!stringa}%
- \egroup
- \else
- \hbox{#1}%
- \fi}
-
-% better, so that we can force a key and share with e.g. renumbering
-%
-% \let\namedtextarea\empty
+% obsolete (but keep the code)
%
-% \def\registerMPlocaltextarea#1%
-% {\ifpositioning
-% \bgroup
-% \ifx\namedtextarea\empty
-% \global\advance\currentMPtextareadata\plusone
-% \edef\namedtextarea{gbd:\the\currentMPtextareadata}%
-% \fi
-% \hpos\namedtextarea{\iftracetextareas\boxrulewidth3pt\ruledhbox\fi{#1}}%
-% \edef\ascii{RegisterLocalTextArea(%
-% \MPx\namedtextarea,\MPy\namedtextarea,%
-% \MPw\namedtextarea,\MPh\namedtextarea,\MPd\namedtextarea);}%
-% \global\MPlocaltextareadata\@EA{\ascii}%
-% \egroup
-% \else
-% \hbox{#1}%
-% \fi}
-
-\def\resetMPlocaltextarea
- {\global\MPlocaltextareadata\emptytoks}
-
-\startMPextensions
- path PlainTextArea;
-\stopMPextensions
+% \prependtoks
+% \calculatereducedvsizes % this is really needed
+% \freezeMPpagelayout
+% \freezeMPlayout % to be used grouped
+% \to \everyMPgraphic
-\startMPinitializations
- ResetTextAreas;
- \the\MPsavedtextareadata;
- SaveTextAreas;
- ResetTextAreas;
- \the\MPtextareadata;
- \the\MPlocaltextareadata;
- PlainTextArea:=boundingbox(\MPxy{text:\realfolio}--\MPxy{text:\realfolio}
- shifted (\MPw{text:\realfolio},\MPh{text:\realfolio}));
-\stopMPinitializations
-
-\appendtoks
- \global\MPsavedtextareadata\MPtextareadata
- \global\MPtextareadata \emptytoks
- \global\MPlocaltextareadata\emptytoks
-\to \everyshipout
+\prependtoks
+ \calculatereducedvsizes % this is really needed
+\to \everyMPgraphic
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/meta-pdf.lua b/Master/texmf-dist/tex/context/base/meta-pdf.lua
index b554810ee93..13d39e445ea 100644
--- a/Master/texmf-dist/tex/context/base/meta-pdf.lua
+++ b/Master/texmf-dist/tex/context/base/meta-pdf.lua
@@ -131,7 +131,7 @@ function mps.newpath()
end
function mps.boundingbox(llx, lly, urx, ury)
- context.MPSboundingbox(llx,lly,urx,ury)
+ context.setMPboundingbox(llx,lly,urx,ury)
end
function mps.moveto(x,y)
@@ -228,7 +228,7 @@ function mps.textext(font, scale, str) -- old parser
dx, dy = m_stack_path[1][1], m_stack_path[1][2]
end
flushconcat()
- context.MPStextext(font,scale,str,dx,dy)
+ context.MPtextext(font,scale,str,dx,dy)
resetpath()
end
diff --git a/Master/texmf-dist/tex/context/base/meta-pdf.mkii b/Master/texmf-dist/tex/context/base/meta-pdf.mkii
index 0ba3fb9799d..e1311339878 100644
--- a/Master/texmf-dist/tex/context/base/meta-pdf.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-pdf.mkii
@@ -5,7 +5,7 @@
%D subtitle=Conversion to \PDF,
%D author=Hans Hagen \& others (see text),
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-pdf.mkiv b/Master/texmf-dist/tex/context/base/meta-pdf.mkiv
index 4d5e5232add..a8fdaff42eb 100644
--- a/Master/texmf-dist/tex/context/base/meta-pdf.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-pdf.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Conversion to \PDF,
%D author=Hans Hagen \& others (see text),
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -13,8 +13,6 @@
\registerctxluafile{meta-pdf}{1.003}
-%D We will clean up the color mess later.
-
\writestatus{loading}{MetaPost Graphics / MPS to PDF}
\unprotect
@@ -22,417 +20,41 @@
%D \macros
%D {convertMPtoPDF}
%D
-%D The next set of macros implements \METAPOST\ to \PDF\
-%D conversion. The traditional method is in the MkII file.
-%D
-%D The main conversion command is:
+%D The next set of macros implements \METAPOST\ to \PDF\ conversion. The
+%D traditional method is in the MkII files and the older \MKIV\ method is
+%D kept in meta-pdh files. The main conversion command is still the same
+%D but the scale parameters are ignored in \MKIV:
%D
%D \starttyping
%D \convertMPtoPDF {filename} {x scale} {y scale}
%D \stoptyping
%D
-%D The dimensions are derived from the bounding box. So we
-%D only have to say:
-%D
-%D \starttyping
-%D \convertMPtoPDF{mp-pra-1.eps}{1}{1}
-%D \convertMPtoPDF{mp-pra-1.eps}{.5}{.5}
-%D \stoptyping
-
-\def\PDFMPformoffset
- {\ifdefined\objectoffset\objectoffset\else\zeropoint\fi}
+%D Much code has gone due to the fact that we now use pre and post scripts
+%D and no specials. This also means that you should use a modern \METAPOST\
+%D or reprocess graphics. The color control flags are also gone as we now
+%D integrate into the regular colorspace handling (i.e.\ no longer independent
+%D configurations.)
-%D The main macro:
+\def\PDFMPformoffset{\ifdefined\objectoffset\objectoffset\else\zeropoint\fi} % obsolete, will go
-\def\convertMPtoPDF#1#2#3% scaling no longer supported at this level (so #2 & #3 ignored)
- {\vbox\bgroup
+\def\convertMPtoPDF#1#2#3% scaling no longer supported at this level (so #2 & #3 are ignored)
+ {\dostarttagged\t!mpgraphic\empty
+ \naturalvbox attr \imageattribute 1 \bgroup
\message{[MP to PDF]}%
\xdef\MPfilename{#1}%
- \glet\MPwidth \!!zeropoint
- \glet\MPheight\!!zeropoint
- \glet\MPllx \!!zerocount
- \glet\MPlly \!!zerocount
- \glet\MPurx \!!zerocount
- \glet\MPury \!!zerocount
+ \resetMPboundingbox
\forgetall
\offinterlineskip
- \setbox\scratchbox\vbox\bgroup
- \ctxlua{metapost.mptopdf.convertmpstopdf("\MPfilename")}\removeunwantedspaces
- \egroup
- \setbox\scratchbox\hbox\bgroup
- \hskip-\MPllx\onebasepoint
- \raise-\MPlly\onebasepoint
- \box\scratchbox
+ \setbox\MPbox\vbox\bgroup
+ \ctxlua{metapost.mptopdf.convertmpstopdf("\MPfilename")}%
+ \removeunwantedspaces % not that needed
\egroup
- \setbox\scratchbox\vbox to \MPheight\bgroup
- \vfill
- \hsize\MPwidth
- \smashbox\scratchbox
- \box\scratchbox
- \egroup
- \wd\scratchbox\MPwidth
- \ht\scratchbox\MPheight
- \dopackageMPgraphic\scratchbox
- \egroup}
-
-%D Objects (move all to backend)
-
-% \def\dopackageMPgraphic#1% #1 = boxregister
-% {\scratchdimen\PDFMPformoffset\relax
-% \ifdim\scratchdimen>\zeropoint % compensate for error
-% \setbox#1\vbox spread 2\scratchdimen
-% {\forgetall\vss\hbox spread 2\scratchdimen{\hss\box#1\hss}\vss}%
-% \fi
-% \setMPPDFobject{#1}%
-% \ifdim\scratchdimen>\zeropoint % compensate for error
-% \vbox to \MPheight
-% {\forgetall\vss\hbox to \MPwidth{\hss\getMPPDFobject\hss}\vss}%
-% \else
-% \getMPPDFobject
-% \fi}
-%
-% \def\setMPPDFobject#1% boxnumber
-% {\the\pdfbackendeveryxform
-% \finalizeobjectbox{#1}%
-% \immediate\pdfxform resources{\pdfcurrentresources}#1%
-% \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}}
-%
-% \let\getMPPDFobject\relax
-
-% we don't need to package as each page has all resources anyway
-
-\let\dopackageMPgraphic\box
-
-%D \macros
-%D {deleteMPgraphic,
-%D startMPresources,
-%D stopMPresources}
-
-\ifx\deleteMPgraphic\undefined
- \def\deleteMPgraphic#1{}
-\fi
-
-\ifx\startMPresources\undefined
- \let\startMPresources\relax
- \let\stopMPresources\relax
-\fi
-
-%D We implement extensions by using the \METAPOST\ special
-%D mechanism. Opposite to \TEX's specials, the \METAPOST\ ones
-%D are flushed before or after the graphic data, but thereby
-%D are no longer connected to a position.
-%D
-%D We implement specials by overloading the \type {fill}
-%D operator. By counting the fills, we can let the converter
-%D treat the appropriate fill in a special way. The
-%D specification of the speciality can have two forms,
-%D determined by the setting of a boolean variable:
-%D
-%D \starttyping
-%D _inline_specials_ := false ; % comment like code (default)
-%D _inline_specials_ := true ; % command like code
-%D \stoptyping
-%D
-%D When the specification is embedded as comment, it looks
-%D like:
-%D
-%D \starttyping
-%D %%MetaPostSpecial <size> <data> <number> <identifier>
-%D \stoptyping
-%D
-%D The in||line alternative is more tuned for \POSTSCRIPT,
-%D since it permits us to define a macro \type {special}.
-%D
-%D \starttyping
-%D inline : <data> <number> <identifier> <size> special
-%D \stoptyping
-%D
-%D The \type {identifier} determines what to do, and the data
-%D can be used to accomplish this. A type~2 shading function
-%D has identifier~2. Alltogether, the number of parameters is
-%D specified in \type {size}. The \type {number} is the number
-%D of the fill that needs the special treatment. For a type~2
-%D and~3 shaded fill, the datablock contains the following
+ \finalizeMPbox
+ \box\MPbox
+ \egroup
+ \dostoptagged}
-%D data:
-%D
-%D \starttyping
-%D from to n inner_r g b x y outer_r g b x y
-%D from to n inner_r g b x y radius outer_r g b x y radius
-%D \stoptyping
-
-\newconditional\manyMPspecials \settrue\manyMPspecials
-
-%D Since colors are not subjected to transformations, we can
-%D only use colors as signal. In our case, we use a dummy colored
-%D path with a red color component of \type {0.n}, so \type
-%D {0.001} is the first path and \type {0.010} the tenth. Since
-%D \METAPOST strips trailing zeros, we have to padd the string.
-
-\newif\ifMPcmykcolors
-\newif\ifMPspotcolors
-
-%D We support specials but assume that the files are somewhat simple
-%D ones wo we have dropped a few. The reason is that runtime \METAPOST\
-%D processing now uses \MPLIB\ so we only need to deal with the
-%D conversion here. See meta-pdh.mkiv (and older files) for more
-%D details. Here we just give a few examples.
-%D
-%D \startbuffer[mp]
-%D fill fullcircle xyscaled (3cm,1cm) withcolor \MPcolor{test} ;
-%D \stopbuffer
-%D
-%D \startbuffer[cmyk]
-%D \startcombination[4*1]
-%D {\definecolor[test][c=1,y=.3,k=.3] \processMPbuffer[mp]} {c=1 y=.3 k=.3}
-%D {\definecolor[test][c=.9,y=.15] \processMPbuffer[mp]} {c=.9 y=.15}
-%D {\definecolor[test][c=.25,y=.8] \processMPbuffer[mp]} {c=.25 y=.8}
-%D {\definecolor[test][c=.45,y=.1] \processMPbuffer[mp]} {c=.45 y=.1}
-%D \stopcombination
-%D \stopbuffer
-%D
-%D \placefigure
-%D {\CMYK\ support disabled,
-%D conversion to \RGB.}
-%D {\setupcolors[cmyk=nee,state=start]\getbuffer[cmyk]}
-%D
-%D \placefigure
-%D {\CMYK\ support enabled,
-%D no support in \METAPOST.}
-%D {\setupcolors[cmyk=ja,mpcmyk=nee,state=start]\getbuffer[cmyk]}
-%D
-%D \placefigure
-%D {\CMYK\ support enabled,
-%D no conversion to \RGB,
-%D support in \METAPOST}
-%D {\setupcolors[cmyk=ja,state=start]\getbuffer[cmyk]}
-%D
-%D Transparency support used specials 60 (rgb) and 61
-%D (cmyk).
-%D
-%D \startbuffer
-%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
-%D
-%D fill p rotated 90 withcolor transparent(1,.5,yellow) ;
-%D fill p rotated 210 withcolor transparent(1,.5,green) ;
-%D fill p rotated 330 withcolor transparent(1,.5,blue) ;
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \startlinecorrection \processMPbuffer \stoplinecorrection
-%D
-%D One can also communicate colors between \CONTEXT\ and
-%D \METAPOST:
-%D
-%D \startbuffer
-%D \definecolor[tcyan] [c=1,k=.2,t=.5]
-%D \definecolor[tmagenta][m=1,k=.2,t=.5]
-%D \definecolor[tyellow] [y=1,k=.2,t=.5]
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-%D
-%D \startbuffer
-%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
-%D
-%D fill p rotated 90 withcolor \MPcolor{tcyan} ;
-%D fill p rotated 210 withcolor \MPcolor{tmagenta} ;
-%D fill p rotated 330 withcolor \MPcolor{tyellow} ;
-%D \stopbuffer
-%D
-%D \startlinecorrection \processMPbuffer \stoplinecorrection
-%D
-%D Shading is an example of a more advanced graphic feature,
-%D but users will seldom encounter those complications. Here
-%D we only show a few simple examples, but many other
-%D alternatives are possible by setting up the functions built
-%D in \PDF\ in the appropriate way.
-%D
-%D Shading has to do with interpolation between two or more
-%D points or user supplied ranges. In \PDF, the specifications
-%D of a shade has to be encapsulated in objects and passed on
-%D as resources. This is a \PDF\ level 1.3. feature. One can
-%D simulate three dimensional shades as well and define simple
-%D functions using a limited set of \POSTSCRIPT\ primitives.
-%D Given the power of \METAPOST\ and these \PDF\ features, we
-%D can achieve superb graphic effects.
-%D
-%D Since everything is hidden in \TEX\ and \METAPOST\ graphics,
-%D we can stick to high level \CONTEXT\ command, as shown in
-%D the following exmples.
-%D
-%D \startbuffer
-%D \startuniqueMPgraphic{CircularShade}
-%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
-%D circular_shade(p,0,.2red,.9red) ;
-%D \stopuniqueMPgraphic
-%D
-%D \startuniqueMPgraphic{LinearShade}
-%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
-%D linear_shade(p,0,.2blue,.9blue) ;
-%D \stopuniqueMPgraphic
-%D
-%D \startuniqueMPgraphic{DuotoneShade}
-%D path p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
-%D linear_shade(p,2,.5green,.5red) ;
-%D \stopuniqueMPgraphic
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-%D
-%D These graphics can be hooked into the overlay mechanism,
-%D which is available in many commands.
-%D
-%D \startbuffer
-%D \defineoverlay[demo 1][\uniqueMPgraphic{CircularShade}]
-%D \defineoverlay[demo 2][\uniqueMPgraphic {LinearShade}]
-%D \defineoverlay[demo 3][\uniqueMPgraphic {DuotoneShade}]
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-%D
-%D These backgrounds can for instance be applied to \type
-%D {\framed}:
-%D
-%D \startbuffer
-%D \setupframed[width=3cm,height=2cm,frame=off]
-%D \startcombination[3*1]
-%D {\framed[backgroundachtergrond=demo 1]{\bfd \white Demo 1}} {}
-%D {\framed[backgroundachtergrond=demo 2]{\bfd \white Demo 2}} {}
-%D {\framed[backgroundachtergrond=demo 3]{\bfd \white Demo 3}} {}
-%D \stopcombination
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \startlinecorrection
-%D \getbuffer
-%D \stoplinecorrection
-%D
-%D There are a few more alternatives, determined by the second
-%D parameter passed to \type {circular_shade} and alike.
-%D
-%D \def\SomeShade#1#2#3#4#5%
-%D {\startuniqueMPgraphic{Shade-#1}
-%D width := \overlaywidth ;
-%D height := \overlayheight ;
-%D path p ; p := unitsquare xscaled width yscaled height ;
-%D #2_shade(p,#3,#4,#5) ;
-%D \stopuniqueMPgraphic
-%D \defineoverlay[Shade-#1][\uniqueMPgraphic{Shade-#1}]%
-%D \framed[backgroundachtergrond=Shade-#1,width=2cm,height=2cm,frame=off]{}}
-%D
-%D \startlinecorrection
-%D \startcombination[5*1]
-%D {\SomeShade{10}{circular}{0}{.3blue}{.9blue}} {circular 0}
-%D {\SomeShade{11}{circular}{1}{.3blue}{.9blue}} {circular 1}
-%D {\SomeShade{12}{circular}{2}{.3blue}{.9blue}} {circular 2}
-%D {\SomeShade{13}{circular}{3}{.3blue}{.9blue}} {circular 3}
-%D {\SomeShade{14}{circular}{4}{.3blue}{.9blue}} {circular 4}
-%D \stopcombination
-%D \stoplinecorrection
-%D
-%D \startlinecorrection
-%D \startcombination[5*1]
-%D {\SomeShade{20}{circular}{0}{.9green}{.3green}} {circular 0}
-%D {\SomeShade{21}{circular}{1}{.9green}{.3green}} {circular 1}
-%D {\SomeShade{22}{circular}{2}{.9green}{.3green}} {circular 2}
-%D {\SomeShade{23}{circular}{3}{.9green}{.3green}} {circular 3}
-%D {\SomeShade{24}{circular}{4}{.9green}{.3green}} {circular 4}
-%D \stopcombination
-%D \stoplinecorrection
-%D
-%D \startlinecorrection
-%D \startcombination[4*1]
-%D {\SomeShade{30}{linear}{0}{.3red}{.9red}} {linear 0}
-%D {\SomeShade{31}{linear}{1}{.3red}{.9red}} {linear 1}
-%D {\SomeShade{32}{linear}{2}{.3red}{.9red}} {linear 2}
-%D {\SomeShade{33}{linear}{3}{.3red}{.9red}} {linear 3}
-%D \stopcombination
-%D \stoplinecorrection
-%D
-%D These macros closely cooperate with the \METAPOST\ module
-%D \type {mp-spec.mp}, which is part of the \CONTEXT\
-%D distribution.
-%D
-%D The low level (\PDF) implementation is based on the \TEX\
-%D based \METAPOST\ to \PDF\ converter. Shading is supported
-%D by overloading the \type {fill} operator as implemented
-%D earlier. In \PDF\ type~2 and~3 shading functions are
-%D specified in terms of:
-%D
-%D \starttabulate[|Tl|l|]
-%D \NC /Domain \NC sort of meeting range \NC \NR
-%D \NC /C0 \NC inner shade \NC \NR
-%D \NC /C1 \NC outer shade \NC \NR
-%D \NC /N \NC smaller values, bigger inner circles \NC \NR
-%D \stoptabulate
-%D
-%D An example of using both special features is the
-%D following.
-%D
-%D \starttyping
-%D \startMPpage
-%D externalfigure "hakker1b.png" scaled 22cm rotated 10 shifted (-2cm,0cm);
-%D externalfigure "hakker1b.png" scaled 10cm rotated -10 ;
-%D externalfigure "hakker1b.png" scaled 7cm rotated 45 shifted (8cm,12cm) ;
-%D path p ; p := unitcircle xscaled 15cm yscaled 20cm;
-%D path q ; q := p rotatedaround(center p,90) ;
-%D path r ; r := buildcycle(p,q) ; clip currentpicture to r ;
-%D path s ; s := boundingbox currentpicture enlarged 5mm ;
-%D picture c ; c := currentpicture ; currentpicture := nullpicture ;
-%D circular_shade(s,0,.2red,.9red) ;
-%D addto currentpicture also c ;
-%D \stopMPpage
-%D \stoptyping
-
-\startMPinitializations
- mp_shade_version := 2 ;
-\stopMPinitializations
-
-%D This is done much cleaner in \MPLIB.
-
-% %D A common hook.
-%
-% \let\MPfshowcommand\empty
-%
-% \def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
-% {\def\MPtextdata{#3}% % delegate the splitter to lua + redesign
-% \def\MPtextsize{#2}%
-% \def\lastMPmoveX{#4}%
-% \def\lastMPmoveY{#5}%
-% \defconvertedcommand\MPtextdata\MPtextdata % no edef
-% \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
-% \executeifdefined{handleMPtext\MPtexttag}
-% {\setbox\scratchbox\hbox
-% {\font\temp=#1\space at #2\onebasepoint
-% \let\c\char
-% \temp
-% \MPfshowcommand{#3}}%
-% \setbox\scratchbox\hbox
-% {\hskip#4\onebasepoint
-% \raise#5\onebasepoint
-% \box\scratchbox}%
-% \smashbox\scratchbox
-% \box\scratchbox}}
-
-\unexpanded\def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
- {\setbox\scratchbox\hbox
- {\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}%
- \setbox\scratchbox\hbox
- {\hskip#4\onebasepoint \raise#5\onebasepoint \box\scratchbox}%
- \smashbox\scratchbox
- \box\scratchbox}
-
-%D The boundingbox.
-
-\def\MPSboundingbox#1#2#3#4%
- {\xdef\MPllx{#1}\xdef\MPlly{#2}\xdef\MPurx{#3}\xdef\MPury{#4}%
- \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
- \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}
-
-\MPSboundingbox0000
+\protect \endinput
%D Test code:
%D
@@ -470,5 +92,3 @@
%D \stopbuffer
%D
%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/meta-pdh.lua b/Master/texmf-dist/tex/context/base/meta-pdh.lua
index 117300f8019..5040715c4f9 100644
--- a/Master/texmf-dist/tex/context/base/meta-pdh.lua
+++ b/Master/texmf-dist/tex/context/base/meta-pdh.lua
@@ -6,7 +6,9 @@ if not modules then modules = { } end modules ['meta-pdf'] = {
license = "see context related readme files"
}
-os.exit()
+if true then
+ return -- or os.exit()
+end
-- This file contains the history of the converter. We keep it around as it
-- relates to the development of luatex.
@@ -25,7 +27,6 @@ os.exit()
-- only needed for mp output on disk
local concat, format, find, gsub, gmatch = table.concat, string.format, string.find, string.gsub, string.gmatch
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
local tostring, tonumber, select = tostring, tonumber, select
local lpegmatch = lpeg.match
@@ -155,11 +156,11 @@ end
-- from lua to tex
function mptopdf.pdfcode(str)
- texsprint(ctxcatcodes,"\\pdfliteral{" .. str .. "}") -- \\MPScode
+ context.pdfliteral(str) -- \\MPScode
end
function mptopdf.texcode(str)
- texsprint(ctxcatcodes,str)
+ context(str)
end
-- auxiliary functions
@@ -229,7 +230,7 @@ function mptopdf.convertmpstopdf(name)
mptopdf.reset()
statistics.stoptiming(mptopdf)
else
- tex.print("file " .. name .. " not found")
+ context("file " .. name .. " not found")
end
end
diff --git a/Master/texmf-dist/tex/context/base/meta-pdh.mkiv b/Master/texmf-dist/tex/context/base/meta-pdh.mkiv
index 978128f3a2d..6d85a8dc151 100644
--- a/Master/texmf-dist/tex/context/base/meta-pdh.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-pdh.mkiv
@@ -5,15 +5,18 @@
%D subtitle=Conversion to \PDF,
%D author=Hans Hagen \& others (see text),
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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.
+\endinput
+
%D Formerly known as supp-pdf.tex and supp-mpe.tex and meta-pdf.mkiv.
%D
-%D Beware: this file is not used but kept for historic purposed!
+%D Beware: this file is not used but kept for historic purposed! Never
+%D mix this one into mkiv again as it uses other variables.
% \useMPgraphic{1}
% \testfeatureonce{250}{\setbox0\hbox{\convertMPtoPDF{test-mps-mpgraph.1}{1}{1}}}
@@ -652,16 +655,6 @@
%D \setMPlayer [test] [somepos-2] {Whatever we need there!}
%D \stoptyping
-% \defineMPspecial{50} % x y width height label
-% {\dosavepositionwhd
-% {\gMPs5}%
-% {0}%
-% {\the\dimexpr-\MPllx\onebasepoint+\gMPs1\onebasepoint\relax}
-% {\the\dimexpr\gMPs2\onebasepoint-\scratchdimen+\MPury\onebasepoint\relax}% scratchdimen ?
-% {\the\dimexpr\gMPs3\onebasepoint\relax}%
-% {\the\dimexpr\gMPs4\onebasepoint\relax}%
-% {0pt}}
-
\startMPinitializations
mp_shade_version := 2 ;
\stopMPinitializations
diff --git a/Master/texmf-dist/tex/context/base/meta-pre.mkii b/Master/texmf-dist/tex/context/base/meta-pre.mkii
index cb861ff20d5..098be030b19 100644
--- a/Master/texmf-dist/tex/context/base/meta-pre.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-pre.mkii
@@ -5,7 +5,7 @@
%D subtitle=Predefined Goodies,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-tex.mkii b/Master/texmf-dist/tex/context/base/meta-tex.mkii
index 190a694d9b1..ab0f244570f 100644
--- a/Master/texmf-dist/tex/context/base/meta-tex.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-tex.mkii
@@ -5,7 +5,7 @@
%D subtitle=\METAPOST\ fast text insertion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-tex.mkiv b/Master/texmf-dist/tex/context/base/meta-tex.mkiv
index 2496440c700..4defd260cea 100644
--- a/Master/texmf-dist/tex/context/base/meta-tex.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-tex.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\METAPOST\ fast text insertion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -16,127 +16,87 @@
\unprotect
% Ok, we support this in MkIV because Mojca kept the pressure on. It
-% looks a bit like a hack.
+% looks a bit like a hack. But in fact this method is obsolete and
+% eventually might go away.
-\long\def\startTeXtexts#1\stopTeXtexts
+\installcorenamespace{graphictextext}
+\installcorenamespace{graphictexdepth}
+\installcorenamespace{graphictexarguments}
+
+\unexpanded\def\startTeXtexts#1\stopTeXtexts
{#1}
-\long\def\TeXtext
- {\dosingleempty\doTeXtext}
+\let\stopTeXtexts\relax
+
+\def\TeXtext
+ {\dosingleempty\meta_textext}
-\long\def\doTeXtext[#1]#2#3% contrary to mkii we don't process yet but we do expand
- {\long\setxvalue{@@st@@::#2}{\noexpand\dodoTeXtext{#1}{#3}}}
+\def\meta_textext[#1]#2#3% contrary to mkii we don't process yet but we do expand
+ {\setxvalue{\??graphictextext#2}{\meta_textext_indeed{#1}{#3}}}
-\long\def\dodoTeXtext#1#2%
+\unexpanded\def\meta_textext_indeed#1#2%
{\begingroup
- \setbox\nextbox\hbox{\executeifdefined{textext@@#1}\firstofoneargument{#2}}%
- \executeifdefined{textext::#1}{\getvalue{textext::depth}}%
+ \setbox\nextbox\hbox{#2}%
+ \executeifdefined{\??graphictexdepth#1}{\getvalue{\??graphictexdepth\s!depth}}%
\box\nextbox
\endgroup}
\def\getTeXtext#1%
- {\getvalue{@@st@@::#1}}
+ {\getvalue{\??graphictextext#1}}
-\setvalue{textext::d}{\setbox\nextbox\hbox{\lower\dp\nextbox\box\nextbox}} % unchecked
-\setvalue{textext::n}{} % unchecked
+\setvalue{\??graphictexdepth d}{\setbox\nextbox\hbox{\lower\dp\nextbox\box\nextbox}} % unchecked
+\letvalue{\??graphictexdepth n}\donothing % unchecked
-\setvalue {textext::depth}{\getvalue{textext::d}}
-\setvalue{textext::nodepth}{\getvalue{textext::n}}
+\setvalue{\??graphictexdepth\s!depth }{\getvalue{\??graphictexdepth d}}
+\letvalue{\??graphictexdepth\s!nodepth}\donothing
% \definetextext[framed]{\framed}
%
% \startMPcode
% draw \sometxt[framed]{black} rotated 45 ;
% \stopMPcode
-
-% \unexpanded\def\definetextext[#1]#2{\setvalue{@@st@@[#1]}{#2}\setvalue{@@st@@[#1] }{#2}} % we don't grab spaces after [#1]
-% \long\def\sometxt #1#{\dosometxt{#1}} % grab optional [args]
-% \long\def\dosometxt #1#2{textext.drt("\ifcsname @@st@@#1\endcsname\csname @@st@@#1\endcsname{#2}\else#2\fi")}
-
+%
% But Mojca wanted more! Two arguments.
%
% \definetextext[framed]{\framed}
%
% \startMPcode
% draw \sometxt{This is for} rotated 45 ;
-% draw \sometxt[framed][ss,16pt]{Mojca's};
+% draw \sometxt[framed][foregroundstyle=bold]{Mojca's};
% draw \sometxt[framed]{eyes only!} rotated -45 ;
% \stopMPcode
-% a tex one:
-%
-% \unexpanded\def\definetextext [#1]#2{\setvalue{@@st@@#1}{#2}}
-% \def\sometxt #1#{\dosometxt{#1}}
-% \def\dosometxt #1#2{textext.drt("\dodosometxt#1{#2}")}
-%
-% \unexpanded\def\dodosometxt {\doifnextoptionalelse\dododosometxt\relax}
-% \def\dododosometxt [#1]{\dodododosometxt{#1}}
-% \def\dodododosometxt #1{\doifnextoptionalelse{\dododododosometxt{#1}}{\getsometxt{#1}}}
-% \def\dododododosometxt #1[#2]{\switchtobodyfont[#2]\getsometxt{#1}}
-% \def\getsometxt #1#2{\csname @@st@@#1\endcsname{#2}}
-%
-% or:
-%
-% \unexpanded\def\dodosometxt {\dodoubleempty\dododosometxt}
-% \def\dododosometxt {\ifsecondargument
-% \expandafter\dododosometxtA
-% \else\iffirstargument
-% \expandafter\expandafter\expandafter\dododosometxtB
-% \else
-% \expandafter\expandafter\expandafter\dododosometxtC
-% \fi\fi}
-% \def\dododosometxtA[#1][#2]#3{\getsometxt{#1}{\switchtobodyfont[#2]#3}}
-% \def\dododosometxtB[#1][#2]#3{\getsometxt{#1}{#3}}
-% \def\dododosometxtC[#1][#2]#3{#3}
-% \def\getsometxt #1#2{\csname @@st@@#1\endcsname{#2}}
-%
-% a nicer variant:
-
\unexpanded\def\definetextext[#1]%
{\def\currenttextext{#1}%
- \dosingleempty\dodefinetextext}
+ \doifnextoptionalelse\meta_textext_define_one\meta_textext_define_zero}
-\def\dodefinetextext
- {\iffirstargument
- \expandafter\dodefinetextextone
- \else
- \expandafter\dodefinetextextzero
- \fi}
+\def\meta_textext_define_one {\setvalue{\??graphictexarguments1:\currenttextext}}
+\def\meta_textext_define_zero{\setvalue{\??graphictexarguments0:\currenttextext}}
-\def\dodefinetextextone {\setvalue{@@st@@one\currenttextext}}
-\def\dodefinetextextzero[#1]{\setvalue{@@st@@zero\currenttextext}}
+\def\sometxt#1#{\meta_some_txt{#1}}
-\def\sometxt#1#%
- {\dosometxt{#1}}
+\def\meta_some_txt#1#2% we need to capture embedded quotes (a bit messy as later on textext is filtered
+ {textext.drt("\mpsometxt#1{\ctxlua{metapost.escaped(\!!bs#2\!!es)}}")}
-\def\dosometxt#1#2% we need to capture embedded quotes (a bit messy as later on textext is filtered
- {textext.drt("\dodosometxt#1{\ctxlua{metapost.escaped(\!!bs#2\!!es)}}")}
+\unexpanded\def\mpsometxt % no _ catcode
+ {\doifnextoptionalelse\meta_some_txt_indeed_yes\meta_some_txt_indeed_nop}
-\unexpanded\def\dodosometxt
- {\dosingleempty\dododosometxt}
-
-\def\dododosometxt
- {\iffirstargument
- \expandafter\dosometxtsome
- \else
- \expandafter\dosometxtzero
- \fi}
-
-\def\dosometxtsome[#1]%
+\def\meta_some_txt_indeed_yes[#1]%
{\def\currenttextext{#1}%
- \csname @@st@@%
- \ifcsname @@st@@one#1\endcsname one\else
- \ifcsname @@st@@zero#1\endcsname zero\else
- none\fi\fi
+ \csname\??graphictexarguments
+ \ifcsname\??graphictexarguments0:#1\endcsname0\else
+ \ifcsname\??graphictexarguments1:#1\endcsname1\else
+ ?\fi\fi
\endcsname}
-\def\dosometxtzero[#1]%
+\def\meta_some_txt_indeed_nop
{}
-\def\@@st@@one {\dosingleempty\do@@st@@one}
-\def\do@@st@@one{\csname @@st@@one\currenttextext\endcsname}
-\def\@@st@@zero {\csname @@st@@zero\currenttextext\endcsname}
-\def\@@st@@none {}
+\setvalue{\??graphictexarguments ?}{}
+\setvalue{\??graphictexarguments 0}{\csname\??graphictexarguments\currenttextext\endcsname}
+\setvalue{\??graphictexarguments 1}{\dosingleempty\meta_gx_one}
+
+\def\meta_gx_one{\csname\??graphictexarguments1:\currenttextext\endcsname}
% \definetextext[framed][#1]#2{\framed[width=4cm]{\switchtobodyfont[#1]#2}}
% \definetextext[simple]{\framed[width=8cm]}
@@ -145,7 +105,7 @@
%
% \startMPcode
% draw \sometxt{This is for} rotated 45 ;
-% draw \sometxt [framed] [ss,16pt] {Mojca's};
+% draw \sometxt[framed][ss,16pt] {Mojca's};
% draw \sometxt[framed]{eyes only!} rotated -45 ;
% draw \sometxt[simple]{Quotes "indeed" work!} rotated 180 ;
% \stopMPcode
diff --git a/Master/texmf-dist/tex/context/base/meta-txt.mkii b/Master/texmf-dist/tex/context/base/meta-txt.mkii
index 474253a4052..dc8bb7ca83b 100644
--- a/Master/texmf-dist/tex/context/base/meta-txt.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-txt.mkii
@@ -5,7 +5,7 @@
%D subtitle=Text Tricks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-xml.mkii b/Master/texmf-dist/tex/context/base/meta-xml.mkii
index f6f81f767b0..71708a0f9a5 100644
--- a/Master/texmf-dist/tex/context/base/meta-xml.mkii
+++ b/Master/texmf-dist/tex/context/base/meta-xml.mkii
@@ -5,7 +5,7 @@
%D subtitle=XML Hacks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/meta-xml.mkiv b/Master/texmf-dist/tex/context/base/meta-xml.mkiv
index 6ce9612ccf9..bd93bda8c5b 100644
--- a/Master/texmf-dist/tex/context/base/meta-xml.mkiv
+++ b/Master/texmf-dist/tex/context/base/meta-xml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=XML Hacks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/metatex.tex b/Master/texmf-dist/tex/context/base/metatex.tex
index cb965dc48b4..b5f54c4eef1 100644
--- a/Master/texmf-dist/tex/context/base/metatex.tex
+++ b/Master/texmf-dist/tex/context/base/metatex.tex
@@ -5,7 +5,7 @@
%D subtitle=\METATEX\ Format Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen / \CONTEXT\ Development Team]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mlib-ctx.lua b/Master/texmf-dist/tex/context/base/mlib-ctx.lua
index 1a5ce2a2419..493a4524853 100644
--- a/Master/texmf-dist/tex/context/base/mlib-ctx.lua
+++ b/Master/texmf-dist/tex/context/base/mlib-ctx.lua
@@ -9,7 +9,6 @@ if not modules then modules = { } end modules ['mlib-ctx'] = {
-- todo
local format, concat = string.format, table.concat
-local sprint = tex.sprint
local report_metapost = logs.reporter("metapost")
@@ -69,7 +68,7 @@ function metapost.theclippath(...)
local result = metapost.getclippath(...)
if result then -- we could just print the table
result = concat(metapost.flushnormalpath(result),"\n")
- sprint(result)
+ context(result)
end
end
diff --git a/Master/texmf-dist/tex/context/base/mlib-ctx.mkiv b/Master/texmf-dist/tex/context/base/mlib-ctx.mkiv
index 6f56b7e685c..75ff4548829 100644
--- a/Master/texmf-dist/tex/context/base/mlib-ctx.mkiv
+++ b/Master/texmf-dist/tex/context/base/mlib-ctx.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Basics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mlib-pdf.lua b/Master/texmf-dist/tex/context/base/mlib-pdf.lua
index 8000d5a282e..7a23ba94772 100644
--- a/Master/texmf-dist/tex/context/base/mlib-pdf.lua
+++ b/Master/texmf-dist/tex/context/base/mlib-pdf.lua
@@ -64,14 +64,24 @@ function metapost.convert(result, trialrun, flusher, multipass, askedfig)
return true -- done
end
-metapost.flushers = { }
+metapost.flushers = { }
metapost.flushers.pdf = { }
-local savedliterals = nil
+-- \def\MPLIBtoPDF#1{\ctxlua{metapost.flushliteral(#1)}}
+
+local savedliterals = nil -- needs checking
local mpsliteral = nodes.pool.register(node.new("whatsit",8)) -- pdfliteral
-function metapost.flushliteral(d) -- \def\MPLIBtoPDF#1{\ctxlua{metapost.flush_literal(#1)}}
+local pdfliteral = function(s)
+ local literal = copy_node(mpsliteral)
+ literal.data = s
+ return literal
+end
+
+local experiment = true -- uses context(node) that already does delayed nodes
+
+function metapost.flushliteral(d)
if savedliterals then
local literal = copy_node(mpsliteral)
literal.data = savedliterals[d]
@@ -88,13 +98,17 @@ end
function metapost.flushers.pdf.comment(message)
if message then
message = format("%% mps graphic %s: %s", metapost.n, message)
- if savedliterals then
- local last = #savedliterals + 1
- savedliterals[last] = message
- context.MPLIBtoPDF(last)
+ if experiment then
+ context(pdfliteral(message))
else
- savedliterals = { message }
- context.MPLIBtoPDF(1)
+ if savedliterals then
+ local last = #savedliterals + 1
+ savedliterals[last] = message
+ context.MPLIBtoPDF(last)
+ else
+ savedliterals = { message }
+ context.MPLIBtoPDF(1)
+ end
end
end
end
@@ -115,20 +129,24 @@ end
function metapost.flushers.pdf.flushfigure(pdfliterals) -- table
if #pdfliterals > 0 then
pdfliterals = concat(pdfliterals,"\n")
- if savedliterals then
- local last = #savedliterals + 1
- savedliterals[last] = pdfliterals
- context.MPLIBtoPDF(last)
+ if experiment then
+ context(pdfliteral(pdfliterals))
else
- savedliterals = { pdfliterals }
- context.MPLIBtoPDF(1)
+ if savedliterals then
+ local last = #savedliterals + 1
+ savedliterals[last] = pdfliterals
+ context.MPLIBtoPDF(last)
+ else
+ savedliterals = { pdfliterals }
+ context.MPLIBtoPDF(1)
+ end
end
end
end
function metapost.flushers.pdf.textfigure(font,size,text,width,height,depth) -- we could save the factor
text = gsub(text,".","\\hbox{%1}") -- kerning happens in metapost (i have to check if this is true for mplib)
- context.MPLIBtextext(font,size,text,0,-number.dimenfactors.bp*depth)
+ context.MPtextext(font,size,text,0,-number.dimenfactors.bp*depth)
end
local bend_tolerance = 131/65536
@@ -256,9 +274,10 @@ function metapost.flush(result,flusher,askedfig)
local figures = result.fig
if figures then
flusher = flusher or metapost.flushers.pdf
- local resetplugins = metapost.resetplugins or ignore
- local processplugins = metapost.processplugins or ignore
- local pluginactions = metapost.pluginactions or ignore
+ local resetplugins = metapost.resetplugins or ignore -- before figure
+ local processplugins = metapost.processplugins or ignore -- each object
+ local synchronizeplugins = metapost.synchronizeplugins or ignore
+ local pluginactions = metapost.pluginactions or ignore -- before / after
local startfigure = flusher.startfigure
local stopfigure = flusher.stopfigure
local flushfigure = flusher.flushfigure
@@ -267,7 +286,7 @@ function metapost.flush(result,flusher,askedfig)
local figure = figures[f]
local objects = getobjects(result,figure,f)
local fignum = figure:charcode() or 0
- if not askedfig or (askedfig == fignum) then
+ if askedfig == "direct" or askedfig == "all" or askedfig == fignum then
local t = { }
local miterlimit, linecap, linejoin, dashed = -1, -1, -1, false
local bbox = figure:boundingbox()
@@ -284,8 +303,7 @@ function metapost.flush(result,flusher,askedfig)
startfigure(fignum,llx,lly,urx,ury,"begin",figure)
t[#t+1] = "q"
if objects then
- resetplugins() -- we should move the colorinitializer here
- t[#t+1] = metapost.colorinitializer()
+ resetplugins(t) -- we should move the colorinitializer here
for o=1,#objects do
local object = objects[o]
local objecttype = object.type
@@ -309,6 +327,9 @@ function metapost.flush(result,flusher,askedfig)
else
-- we use an indirect table as we want to overload
-- entries but this is not possible in userdata
+ --
+ -- can be optimized if no path
+ --
local original = object
local object = { }
setmetatable(object, {
@@ -416,7 +437,7 @@ function metapost.flush(result,flusher,askedfig)
flushfigure(t)
stopfigure("end")
end
- if askedfig then
+ if askedfig ~= "all" then
break
end
end
@@ -429,11 +450,11 @@ function metapost.parse(result,askedfig)
if result then
local figures = result.fig
if figures then
- local analyzeplugins = metapost.analyzeplugins
+ local analyzeplugins = metapost.analyzeplugins -- each object
for f=1, #figures do
local figure = figures[f]
local fignum = figure:charcode() or 0
- if not askedfig or (askedfig == fignum) then
+ if askedfig == "direct" or askedfig == "all" or askedfig == fignum then
local bbox = figure:boundingbox()
local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack
metapost.llx = llx
@@ -452,7 +473,9 @@ function metapost.parse(result,askedfig)
analyzeplugins(objects[o])
end
end
- break
+ if askedfig ~= "all" then
+ break
+ end
end
end
end
diff --git a/Master/texmf-dist/tex/context/base/mlib-pdf.mkiv b/Master/texmf-dist/tex/context/base/mlib-pdf.mkiv
index 8506b3b15e6..b9871eeadae 100644
--- a/Master/texmf-dist/tex/context/base/mlib-pdf.mkiv
+++ b/Master/texmf-dist/tex/context/base/mlib-pdf.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Conversion to PDF,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -13,84 +13,140 @@
\unprotect
+% We use bit more code that needed because we want to limit the
+% amount of boxing.
+
\registerctxluafile{mlib-pdf}{1.001}
-\def\MPLIBtoPDF#1{\ctxlua{metapost.flushliteral(#1)}}
+%D Some code is shared between MPLIB and MPS. The following variables
+%D are also available for introspection and other purposes.
-\def\MPLIBboundingbox#1#2#3#4%
- {\xdef\MPllx{#1}%
- \xdef\MPlly{#2}%
- \xdef\MPurx{#3}%
- \xdef\MPury{#4}%
- \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
- \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}
+\newdimen\MPwidth
+\newdimen\MPheight
-\def\startMPLIBtoPDF#1#2#3#4% watch the transparency reset
- {\dostarttagged\t!mpgraphic\empty
- \naturalhbox attr \imageattribute 1 \bgroup
- \doactivatecolor\s!black\forcecolorhack
- \MPLIBboundingbox{#1}{#2}{#3}{#4}%
- %\forgetall % done already elsewhere
- \setbox\scratchbox\vbox\bgroup
- \noindent % this is really needed in order to force tex into proper cm's
- \startMPresources}
-
-\def\stopMPLIBtoPDF % watch the transparency reset
- {%\dohandleMPresettransparency % not needed
- \stopMPresources
- \egroup
- \setbox\scratchbox\hbox\bgroup
- \hskip-\MPllx\onebasepoint
- \raise-\MPlly\onebasepoint
- \box\scratchbox
- \egroup
- \setbox\scratchbox\vbox to \MPheight\bgroup
+\newdimen\MPllx
+\newdimen\MPlly
+\newdimen\MPurx
+\newdimen\MPury
+
+\newbox \MPbox
+
+\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
+ \global\MPury #4\onebasepoint
+ \global\MPwidth \dimexpr\MPurx-\MPllx\relax
+ \global\MPheight\dimexpr\MPury-\MPlly\relax}
+
+\def\resetMPboundingbox
+ {\global\MPwidth \zeropoint
+ \global\MPheight\zeropoint
+ \global\MPllx \zeropoint
+ \global\MPlly \zeropoint
+ \global\MPurx \zeropoint
+ \global\MPury \zeropoint}
+
+\def\repositionMPboxindeed
+ {\setbox\MPbox\hbox\bgroup
+ \hskip-\MPllx
+ \raise-\MPlly
+ \box\MPbox
+ \egroup}
+
+\def\repositionMPbox
+ {\ifzeropt\MPllx
+ \ifzeropt\MPlly
+ % okay
+ \else
+ \repositionMPboxindeed
+ \fi
+ \else
+ \repositionMPboxindeed
+ \fi}
+
+\def\finalizeMPbox
+ {\repositionMPbox
+ \setbox\MPbox\vbox to \MPheight\bgroup
\vfill
\hsize\MPwidth
- \smashbox\scratchbox
- \box\scratchbox
- \egroup
- \wd\scratchbox\MPwidth
- \ht\scratchbox\MPheight
- \dopackageMPgraphic\scratchbox
+ \smashbox\MPbox
+ \box\MPbox
\egroup
- \dostoptagged}
+ \wd\MPbox\MPwidth
+ \ht\MPbox\MPheight}
-% \def\MPLIBtextext#1#2#3#4#5%
-% {\begingroup
-% \def\MPtextdata{#3}% delegate the splitter to lua
-% \defconvertedcommand\MPtextdata\MPtextdata % no edef
-% \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
-% \executeifdefined{handleMPtext\MPtexttag}
-% {\setbox\scratchbox\hbox
-% {\font\temp=#1\space at #2\onebasepoint
-% \let\c\char
-% \temp
-% \MPfshowcommand{#3}}%
-% \setbox\scratchbox\hbox
-% {\hskip#4\onebasepoint
-% \raise#5\onebasepoint
-% \box\scratchbox}%
-% \smashbox\scratchbox
-% \box\scratchbox}%
-% \endgroup}
-
-\def\MPLIBtextext#1#2#3#4#5%
+\def\MPtextext#1#2#3#4#5% beware: we use a different method now (see mlib-pps)
{\begingroup
- \setbox\scratchbox\hbox
- {\font\temp=#1\space at #2\onebasepoint
- \let\c\char
- \temp
- #3}%
- \setbox\scratchbox\hbox
- {\hskip#4\onebasepoint
- \raise#5\onebasepoint
- \box\scratchbox}%
- \smashbox\scratchbox
- \box\scratchbox
+ \setbox\MPbox\hbox{\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}%
+ \MPllx-#4\onebasepoint
+ \MPlly-#5\onebasepoint
+ \repositionMPbox
+ \smashbox\MPbox
+ \box\MPbox
\endgroup}
-\def\MPLIBflushreset
+% MPLIB specific:
+
+\def\MPLIBtoPDF#1{\ctxlua{metapost.flushliteral(#1)}}
+
+\def\startMPLIBtoPDF#1#2#3#4%
+ {\dostarttagged\t!mpgraphic\empty
+ \naturalhbox attr \imageattribute 1 \bgroup
+ \dousecolorparameter\s!black\forcecolorhack
+ \setMPboundingbox{#1}{#2}{#3}{#4}%
+ \setbox\MPbox\vbox\bgroup
+ % \forgetall % already done elsewhere
+ \noindent} % forces the proper cm in the backend
+
+\def\stopMPLIBtoPDF
+ {\egroup
+ \finalizeMPbox
+ \box\MPbox
+ \egroup
+ \dostoptagged}
+
+\def\MPLIBflushreset % This can (will) move to the Lua end.
{\ctxlua{metapost.flushreset()}}
+%D Kind of special:
+%
+% test.mp:
+%
+% beginfig(1) fill fullcircle scaled 10cm withcolor red ; endfig ;
+% beginfig(2) draw fullcircle scaled 5cm withcolor blue ; endfig ;
+% beginfig(3) draw textext("just some text") ; endfig ;
+%
+% standalone pages:
+%
+% \starttext
+% \directMPgraphic{input "test.mp" ;}
+% \stoptext
+
+\let\normalstartMPLIBtoPDF\startMPLIBtoPDF
+\let\normalstopMPLIBtoPDF \stopMPLIBtoPDF
+
+\def\directstartMPLIBtoPDF{\startTEXpage\normalstartMPLIBtoPDF}
+\def\directstopMPLIBtoPDF {\normalstopMPLIBtoPDF\stopTEXpage}
+
+\unexpanded\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
+ \meta_start_current_graphic
+ \forgetall
+ \normalexpanded{\noexpand\ctxlua{metapost.graphic(
+ "\currentMPinstance",
+ "\currentMPformat",
+ \!!bs#2;\!!es,
+ \!!bs\meta_flush_current_initializations;\!!es,
+ \!!bs\meta_flush_current_preamble;\!!es,
+ "all"
+ )}}%
+ \meta_stop_current_graphic
+ \meta_end_graphic_group}
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mlib-pps.lua b/Master/texmf-dist/tex/context/base/mlib-pps.lua
index 27269a14e49..7821b3dbf24 100644
--- a/Master/texmf-dist/tex/context/base/mlib-pps.lua
+++ b/Master/texmf-dist/tex/context/base/mlib-pps.lua
@@ -6,14 +6,9 @@ if not modules then modules = { } end modules ['mlib-pps'] = {
license = "see context related readme files",
}
--- pps: prescript, postscripts and specials (although specials are dropped)
---
--- current limitation: if we have textext as well as a special color then due to
--- prescript/postscript overload we can have problems
---
-- todo: report max textexts
-local format, gmatch, match = string.format, string.gmatch, string.match
+local format, gmatch, match, split = string.format, string.gmatch, string.match, string.split
local tonumber, type = tonumber, type
local round = math.round
local insert, concat = table.insert, table.concat
@@ -31,6 +26,7 @@ local sortedhash = table.sortedhash
local starttiming = statistics.starttiming
local stoptiming = statistics.stoptiming
+local trace_runs = false trackers.register("metapost.runs", function(v) trace_runs = v end)
local trace_textexts = false trackers.register("metapost.textexts", function(v) trace_textexts = v end)
local trace_scripts = false trackers.register("metapost.scripts", function(v) trace_scripts = v end)
@@ -103,9 +99,9 @@ end
--~
-local specificationsplitter = Ct(lpeg.splitat(" "))
-local colorsplitter = Ct(lpeg.splitter(":",tonumber)) -- no need for :
-local domainsplitter = Ct(lpeg.splitter(" ",tonumber))
+local specificationsplitter = lpeg.tsplitat(" ")
+local colorsplitter = lpeg.tsplitter(":",tonumber) -- no need for :
+local domainsplitter = lpeg.tsplitter(" ",tonumber)
local centersplitter = domainsplitter
local coordinatesplitter = domainsplitter
@@ -142,11 +138,13 @@ local function spotcolorconverter(parent, n, d, p)
return pdfcolor(colors.model,registercolor(nil,'spot',parent,n,d,p)), outercolor
end
+local commasplitter = lpeg.tsplitat(",")
+
local function checkandconvertspot(n_a,f_a,c_a,v_a,n_b,f_b,c_b,v_b)
-- must be the same but we don't check
local name = format("MpSh%s",nofshades)
- local ca = string.split(v_a,",")
- local cb = string.split(v_b,",")
+ local ca = lpegmatch(commasplitter,v_a)
+ local cb = lpegmatch(commasplitter,v_b)
if #ca == 0 or #cb == 0 then
return { 0 }, { 1 }, "DeviceGray", name
else
@@ -463,14 +461,14 @@ local function sxsy(wd,ht,dp) -- helper for text
return (wd ~= 0 and factor/wd) or 0, (hd ~= 0 and factor/hd) or 0
end
-local no_trial_run = "_trial_run_ := false ;"
-local do_trial_run = "if unknown _trial_run_ : boolean _trial_run_ fi ; _trial_run_ := true ;"
-local text_data_template = "_tt_w_[%i]:=%f;_tt_h_[%i]:=%f;_tt_d_[%i]:=%f;"
-local do_begin_fig = "; beginfig(1); "
+local no_trial_run = "mfun_trial_run := false ;"
+local do_trial_run = "if unknown mfun_trial_run : boolean mfun_trial_run fi ; mfun_trial_run := true ;"
+local text_data_template = "mfun_tt_w[%i] := %f ; mfun_tt_h[%i] := %f ; mfun_tt_d[%i] := %f ;"
+local do_begin_fig = "; beginfig(1) ; "
local do_end_fig = "; endfig ;"
local do_safeguard = ";"
-function metapost.texttextsdata()
+function metapost.textextsdata()
local t, nt, n = { }, 0, 0
for n, box in next, textexts do
if box then
@@ -495,8 +493,28 @@ metapost.method = 1 -- 1:dumb 2:clever
-- maybe we can latelua the texts some day
+local nofruns = 0 -- askedfig: "all", "first", number
+
+local function checkaskedfig(askedfig) -- return askedfig, wrappit
+ if not askedfig then
+ return "direct", true
+ elseif askedfig == "all" then
+ return "all", false
+ elseif askedfig == "direct" then
+ return "all", true
+ else
+ askedfig = tonumber(askedfig)
+ if askedfig then
+ return askedfig, false
+ else
+ return "direct", true
+ end
+ end
+end
+
function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,askedfig)
- local nofig = (askedfig and "") or false
+ nofruns = nofruns + 1
+ local askedfig, wrappit = checkaskedfig(askedfig)
local done_1, done_2, forced_1, forced_2
str, done_1, forced_1 = checktexts(str)
if not preamble or preamble == "" then
@@ -508,16 +526,18 @@ function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,asked
metapost.multipass = false -- no needed here
current_format, current_graphic, current_initializations = mpsformat, str, initializations or ""
if metapost.method == 1 or (metapost.method == 2 and (done_1 or done_2)) then
+ if trace_runs then
+ report_metapost("first run of job %s (asked: %s)",nofruns,tostring(askedfig))
+ end
-- first true means: trialrun, second true means: avoid extra run if no multipass
local flushed = metapost.process(mpsformat, {
preamble,
- nofig or do_begin_fig,
+ wrappit and do_begin_fig or "",
do_trial_run,
current_initializations,
do_safeguard,
current_graphic,
- nofig or do_end_fig
- -- }, true, nil, true )
+ wrappit and do_end_fig or "",
}, true, nil, not (forced_1 or forced_2), false, askedfig)
if metapost.intermediate.needed then
for _, action in next, metapost.intermediate.actions do
@@ -527,32 +547,38 @@ function metapost.graphic_base_pass(mpsformat,str,initializations,preamble,asked
if not flushed or not metapost.optimize then
-- tricky, we can only ask once for objects and therefore
-- we really need a second run when not optimized
- context.MPLIBextrapass(askedfig or "false")
+ context.MPLIBextrapass(askedfig)
end
else
+ if trace_runs then
+ report_metapost("running job %s (asked: %s)",nofruns,tostring(askedfig))
+ end
metapost.process(mpsformat, {
preamble,
- nofig or do_begin_fig,
+ wrappit and do_begin_fig or "",
no_trial_run,
current_initializations,
do_safeguard,
current_graphic,
- nofig or do_end_fig
+ wrappit and do_end_fig or "",
}, false, nil, false, false, askedfig )
end
end
function metapost.graphic_extra_pass(askedfig)
- local nofig = (askedfig and "") or false
+ if trace_runs then
+ report_metapost("second run of job %s (asked: %s)",nofruns,tostring(askedfig))
+ end
+ local askedfig, wrappit = checkaskedfig(askedfig)
metapost.process(current_format, {
- nofig or do_begin_fig,
+ wrappit and do_begin_fig or "",
no_trial_run,
- concat(metapost.texttextsdata()," ;\n"),
+ concat(metapost.textextsdata()," ;\n"),
current_initializations,
do_safeguard,
current_graphic,
- nofig or do_end_fig
- }, false, nil, false, true, askedfig )
+ wrappit and do_end_fig or "",
+ }, false, nil, false, true, askedfig)
context.MPLIBresettexts() -- must happen afterwards
end
@@ -594,17 +620,17 @@ local sequencers = utilities.sequencers
local appendgroup = sequencers.appendgroup
local appendaction = sequencers.appendaction
-local resetter = nil
-local analyzer = nil
-local processor = nil
+local resetter = nil
+local analyzer = nil
+local processor = nil
-local resetteractions = sequencers.reset { arguments = "" }
-local analyzeractions = sequencers.reset { arguments = "object,prescript" }
-local processoractions = sequencers.reset { arguments = "object,prescript,before,after" }
+local resetteractions = sequencers.new { arguments = "t" }
+local analyzeractions = sequencers.new { arguments = "object,prescript" }
+local processoractions = sequencers.new { arguments = "object,prescript,before,after" }
-appendgroup(resetteractions, "system")
-appendgroup(analyzeractions, "system")
-appendgroup(processoractions,"system")
+appendgroup(resetteractions, "system")
+appendgroup(analyzeractions, "system")
+appendgroup(processoractions, "system")
-- later entries come first
@@ -628,12 +654,12 @@ local function splitscript(script)
return hash
end
-function metapost.pluginactions(what,t,flushfigure) -- to be checked: too many 0 g 0 G
+function metapost.pluginactions(what,t,flushfigure) -- before/after object, depending on what
for i=1,#what do
local wi = what[i]
if type(wi) == "function" then
-- assume injection
- flushfigure(t)
+ flushfigure(t) -- to be checked: too many 0 g 0 G
t = { }
wi()
else
@@ -643,18 +669,23 @@ function metapost.pluginactions(what,t,flushfigure) -- to be checked: too many 0
return t
end
-function metapost.resetplugins()
- resetter()
+function metapost.resetplugins(t) -- intialize plugins, before figure
+ -- plugins can have been added
+ resetter = resetteractions .runner
+ analyzer = analyzeractions .runner
+ processor = processoractions .runner
+ -- let's apply one runner
+ resetter(t)
end
-function metapost.analyzeplugins(object)
+function metapost.analyzeplugins(object) -- each object (first pass)
local prescript = object.prescript -- specifications
if prescript and #prescript > 0 then
return analyzer(object,splitscript(prescript))
end
end
-function metapost.processplugins(object) -- maybe environment table
+function metapost.processplugins(object) -- each object (second pass)
local prescript = object.prescript -- specifications
if prescript and #prescript > 0 then
local before = { }
@@ -674,7 +705,7 @@ end
local basepoints = number.dimenfactors["bp"]
-local cm = function(object)
+local function cm(object)
local op = object.path
local first, second, fourth = op[1], op[2], op[4]
local tx, ty = first.x_coord , first.y_coord
@@ -685,6 +716,12 @@ local cm = function(object)
return sx,rx,ry,sy,tx,ty
end
+-- color
+
+local function cl_reset(t)
+ t[#t+1] = metapost.colorinitializer() -- only color
+end
+
-- text
local tx_done = { }
@@ -710,24 +747,24 @@ local function tx_analyze(object,prescript) -- todo: hash content and reuse them
-- no color
elseif #c == 1 then
if a and t then
- s = format("\\colored[s=%f,a=%f,t=%f]%s",c[1],a,t,s)
+ s = format("\\directcolored[s=%f,a=%f,t=%f]%s",c[1],a,t,s)
else
- s = format("\\colored[s=%f]%s",c[1],s)
+ s = format("\\directcolored[s=%f]%s",c[1],s)
end
elseif #c == 3 then
if a and t then
- s = format("\\colored[r=%f,g=%f,b=%f,a=%f,t=%f]%s",c[1],c[2],c[3],a,t,s)
+ s = format("\\directcolored[r=%f,g=%f,b=%f,a=%f,t=%f]%s",c[1],c[2],c[3],a,t,s)
else
- s = format("\\colored[r=%f,g=%f,b=%f]%s",c[1],c[2],c[3],s)
+ s = format("\\directcolored[r=%f,g=%f,b=%f]%s",c[1],c[2],c[3],s)
end
elseif #c == 4 then
if a and t then
- s = format("\\colored[c=%f,m=%f,y=%f,k=%f,a=%f,t=%f]%s",c[1],c[2],c[3],c[4],a,t,s)
+ s = format("\\directcolored[c=%f,m=%f,y=%f,k=%f,a=%f,t=%f]%s",c[1],c[2],c[3],c[4],a,t,s)
else
- s = format("\\colored[c=%f,m=%f,y=%f,k=%f]%s",c[1],c[2],c[3],c[4],s)
+ s = format("\\directcolored[c=%f,m=%f,y=%f,k=%f]%s",c[1],c[2],c[3],c[4],s)
end
end
- context.MPLIBsettext(tx_number,s)
+ context.MPLIBsettext(tx_number,s) -- combine colored in here, saves call
metapost.multipass = true
end
end
@@ -742,17 +779,19 @@ local function tx_process(object,prescript,before,after)
if trace_textexts then
report_textexts("processing %s (second pass)",tx_number)
end
- before[#before+1] = format("q %f %f %f %f %f %f cm",cm(object))
+ -- before[#before+1] = format("q %f %f %f %f %f %f cm",cm(object))
+ local sx,rx,ry,sy,tx,ty = cm(object)
before[#before+1] = function()
-- flush always happens, we can have a special flush function injected before
local box = textexts[tx_number]
if box then
- context.MPLIBgettextscaled(tx_number,sxsy(box.width,box.height,box.depth))
+ -- context.MPLIBgettextscaled(tx_number,sxsy(box.width,box.height,box.depth))
+ context.MPLIBgettextscaledcm(tx_number,sx,rx,ry,sy,tx,ty,sxsy(box.width,box.height,box.depth))
else
report_textexts("unknown %s",tx_number)
end
end
- before[#before+1] = "Q"
+ -- before[#before+1] = "Q"
if not trace_textexts then
object.path = false -- else: keep it
end
@@ -806,17 +845,24 @@ local function sh_process(object,prescript,before,after)
local value_a, components_a, fractions_a, name_a
local value_b, components_b, fractions_b, name_b
for i=1,#prescript do
+ -- { "sh_color_a", "1" },
+ -- { "sh_color", "into" },
+ -- { "sh_radius_b", "0" },
+ -- { "sh_radius_a", "141.73225" },
+ -- { "sh_center_b", "425.19676 141.73225" },
+ -- { "sh_center_a", "425.19676 0" },
+ -- { "sh_factor", "1" },
local tag = prescript[i][1]
if not name_a and tag == "sh_color_a" then
- value_a = prescript[i-4][2]
- components_a = prescript[i-3][2]
- fractions_a = prescript[i-2][2]
- name_a = prescript[i-1][2]
+ value_a = prescript[i-5][2]
+ components_a = prescript[i-4][2]
+ fractions_a = prescript[i-3][2]
+ name_a = prescript[i-2][2]
elseif not name_b and tag == "sh_color_b" then
- value_b = prescript[i-4][2]
- components_b = prescript[i-3][2]
- fractions_b = prescript[i-2][2]
- name_b = prescript[i-1][2]
+ value_b = prescript[i-5][2]
+ components_b = prescript[i-4][2]
+ fractions_b = prescript[i-3][2]
+ name_b = prescript[i-2][2]
end
if name_a and name_b then
break
@@ -846,7 +892,10 @@ local function sh_process(object,prescript,before,after)
-- fatal error
end
before[#before+1], after[#after+1] = "q /Pattern cs", format("W n /%s sh Q",name)
- object.color, object.type, object.grouped = false, false, true -- not nil, otherwise mt
+ -- false, not nil, else mt triggered
+ object.colored = false
+ object.type = false
+ object.grouped = true
end
end
@@ -886,6 +935,7 @@ local function ps_process(object,prescript,before,after)
before[#before+1] = function()
context.MPLIBpositionwhd(ps_label,x,y,w,h)
end
+ object.path = false
end
end
@@ -894,7 +944,7 @@ end
local function fg_process(object,prescript,before,after)
local fg_name = prescript.fg_name
if fg_name then
- before[#before+1] = format("q %f %f %f %f %f %f cm",cm(object))
+ before[#before+1] = format("q %f %f %f %f %f %f cm",cm(object)) -- beware: does not use the cm stack
before[#before+1] = function()
context.MPLIBfigure(fg_name,prescript.fg_mask or "")
end
@@ -911,35 +961,77 @@ local value = Cs ( (
+ P(","))^1
)
+-- should be codeinjections
+
+local t_list = attributes.list[attributes.private('transparency')]
+local c_list = attributes.list[attributes.private('color')]
+
local function tr_process(object,prescript,before,after)
-- before can be shortcut to t
local tr_alternative = prescript.tr_alternative
if tr_alternative then
tr_alternative = tonumber(tr_alternative)
local tr_transparency = tonumber(prescript.tr_transparency)
- before[#before+1], after[#after+1] = format("/Tr%s gs",registertransparency(nil,tr_alternative,tr_transparency,true)), "/Tr0 gs" -- outertransparency
+ before[#before+1] = format("/Tr%s gs",registertransparency(nil,tr_alternative,tr_transparency,true))
+ after[#after+1] = "/Tr0 gs" -- outertransparency
end
local cs = object.color
if cs and #cs > 0 then
- local sp_name = prescript.sp_name
- local b, a
- if sp_name then
+ local c_b, c_a
+ local sp_type = prescript.sp_type
+ if not sp_type then
+ c_b, c_a = colorconverter(cs)
+ elseif sp_type == "spot" or sp_type == "multitone" then
+ local sp_name = prescript.sp_name or "black"
local sp_fractions = prescript.sp_fractions or 1
local sp_components = prescript.sp_components or ""
local sp_value = prescript.sp_value or "1"
local cf = cs[1]
if cf ~= 1 then
-- beware, we do scale the spotcolors but not the alternative representation
- sp_value = lpeg.match(value,sp_value,1,cf) or sp_value
+ sp_value = lpegmatch(value,sp_value,1,cf) or sp_value
end
- -- should be codeinjections
- b, a = spotcolorconverter(sp_name,sp_fractions,sp_components,sp_value)
- else
- -- should be codeinjections
- b, a = colorconverter(cs)
+ c_b, c_a = spotcolorconverter(sp_name,sp_fractions,sp_components,sp_value)
+ elseif sp_type == "named" then
+ -- we might move this to another namespace .. also, named can be a spotcolor
+ -- so we need to check for that too ... also we need to resolve indirect
+ -- colors so we might need the second pass for this (draw dots with \MPcolor)
+ local sp_name = prescript.sp_name or "black"
+ if not tr_alternative then
+ -- todo: sp_name is not yet registered at this time
+ local t = t_list[sp_name] -- string or attribute
+ local v = t and attributes.transparencies.value(t)
+ if v then
+ before[#before+1] = format("/Tr%s gs",registertransparency(nil,v[1],v[2],true))
+ after[#after+1] = "/Tr0 gs" -- outertransparency
+ end
+ end
+ local c = c_list[sp_name] -- string or attribute
+ local v = c and attributes.colors.value(c)
+ if v then
+ -- all=1 gray=2 rgb=3 cmyk=4
+ local colorspace = v[1]
+ local f = cs[1]
+ if colorspace == 2 then
+ local s = f*v[2]
+ c_b, c_a = checked_color_pair(format("%.3f g %.3f G",s,s))
+ elseif colorspace == 3 then
+ local r, g, b = f*v[3], f*v[4], f*v[5]
+ c_b, c_a = checked_color_pair(format("%.3f %.3f %.3f rg %.3f %.3f %.3f RG",r,g,b,r,g,b))
+ elseif colorspace == 4 or colorspace == 1 then
+ local c, m, y, k = f*v[6], f*v[7], f*v[8], f*v[9]
+ c_b, c_a = checked_color_pair(format("%.3f %.3f %.3f %.3f k %.3f %.3f %.3f %.3f K",c,m,y,k,c,m,y,k))
+ else
+ local s = f*v[2]
+ c_b, c_a = checked_color_pair(format("%.3f g %.3f G",s,s))
+ end
+ end
+ --
+ end
+ if c_a and c_b then
+ before[#before+1] = c_b
+ after[#after+1] = c_a
end
- before[#before+1] = b
- after[#after+1] = a
end
end
@@ -953,12 +1045,47 @@ local function la_process(object,prescript,before,after)
end
end
+-- groups
+
+local types = {
+ isolated
+}
+
+local function gr_process(object,prescript,before,after)
+ local gr_state = prescript.gr_state
+ if gr_state then
+ if gr_state == "start" then
+ local gr_type = utilities.parsers.settings_to_hash(prescript.gr_type)
+ before[#before+1] = function()
+ context.MPLIBstartgroup(
+ gr_type.isolated and 1 or 0,
+ gr_type.knockout and 1 or 0,
+ prescript.gr_llx,
+ prescript.gr_lly,
+ prescript.gr_urx,
+ prescript.gr_ury
+ )
+ end
+ elseif gr_state == "stop" then
+ after[#after+1] = function()
+ context.MPLIBstopgroup()
+ end
+ end
+ object.path = false
+ object.color = false
+ object.grouped = true
+ end
+end
+
-- definitions
-appendaction(resetteractions,"system",tx_reset)
+appendaction(resetteractions, "system",cl_reset)
+appendaction(resetteractions, "system",tx_reset)
+
+appendaction(processoractions,"system",gr_process)
-appendaction(analyzeractions,"system",tx_analyze)
-appendaction(analyzeractions,"system",gt_analyze)
+appendaction(analyzeractions, "system",tx_analyze)
+appendaction(analyzeractions, "system",gt_analyze)
appendaction(processoractions,"system",sh_process)
-- (processoractions,"system",gt_process)
@@ -970,8 +1097,8 @@ appendaction(processoractions,"system",tr_process) -- last, as color can be rese
appendaction(processoractions,"system",la_process)
--- no auto here
+-- we're nice and set them already
-resetter = sequencers.compile(resetteractions )
-analyzer = sequencers.compile(analyzeractions )
-processor = sequencers.compile(processoractions)
+resetter = resetteractions .runner
+analyzer = analyzeractions .runner
+processor = processoractions.runner
diff --git a/Master/texmf-dist/tex/context/base/mlib-pps.mkiv b/Master/texmf-dist/tex/context/base/mlib-pps.mkiv
index 357f85b1a1f..cb6120066af 100644
--- a/Master/texmf-dist/tex/context/base/mlib-pps.mkiv
+++ b/Master/texmf-dist/tex/context/base/mlib-pps.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Basics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -17,44 +17,132 @@
%D Todo: catch nested graphics like external figures with dummies.
-% \newtoks\everyMPLIBtext % not yet used
+% todo: figure out why this is shifted
+%
+% \setupbodyfont[palatino]
+%
+% \starttext
+% \startMPpage
+% draw textext("123") ;
+% \stopMPpage
+% \stoptext
+%
+% A slightly larger picture works ok so maybe there is some kind
+% of interference with the page builder.
-% \appendtoks
-% \let\handleuseMPgraphic \thirdofthreearguments
-% \let\handlereusableMPgraphic\thirdofthreearguments
-% \to \everyMPLIBtext
+\newbox \MPtextbox
+\newtoks\everyMPLIBsettext % not used
-% this will move !
+\newconditional\MPLIBtextgetdone
-% Instead of preallocated boxes we now use a table of lists so that we
-% have no limitation. Typically an example of a next version solution
-% due to \LUATEX\ evolving.
+% \def\MPLIBsettext#1% #2%
+% {\dowithnextbox{\ctxlua{metapost.settext(\number\nextbox,#1)}}\hbox}
-\newbox \MPtextbox
-\newtoks\everyMPLIBsettext
+\def\MPLIBsettext#1% #2%
+ {\ifconditional\MPLIBtextgetdone
+ \else
+ \cldcontext{metapost.tex.get()}% MPenvironments are depricated
+ \settrue\MPLIBtextgetdone % no \global needed
+ \fi
+ \dowithnextbox{\ctxlua{metapost.settext(\number\nextbox,#1)}}\hbox}
+
+\def\MPLIBgettextscaled#1#2#3% why a copy .. can be used more often
+ {\ctxlua{metapost.gettext(\number\MPtextbox,#1)}%
+ \vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[\c!sx=#2,\c!sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\forcecolorhack\hss}}}
\def\MPLIBfigure#1#2%
{\setbox\scratchbox\hbox{\externalfigure[#1][\c!mask=#2]}%
\ctxlua{metapost.edefsxsy(\number\wd\scratchbox,\number\ht\scratchbox,0)}%
\vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[\c!sx=\sx,\c!sy=\sy]{\box\scratchbox}\hss}}}
-\def\MPLIBsettext#1% #2%
- {\dowithnextbox{\ctxlua{metapost.settext(\number\nextbox,#1)}}\hbox}
-
-\def\MPLIBgettextscaled#1#2#3% why a copy .. can be used more often
- {\ctxlua{metapost.gettext(\number\MPtextbox,#1)}% we need the colorhack or else the color backend does not sync
- \vbox to \zeropoint{\vss\hbox to \zeropoint{\scale[\c!sx=#2,\c!sy=#3]{\raise\dp\MPtextbox\box\MPtextbox}\forcecolorhack\hss}}}
-
-\def\MPLIBgraphictext#1%
+% horrible:
+
+\def\MPLIBgettextscaledcm#1#2#3#4#5#6#7#8#9% 2-7: sx,rx,ry,sy,tx,ty
+ {\ctxlua{metapost.gettext(\number\MPtextbox,#1)}%
+ \setbox\MPbox\hbox\bgroup
+ \dotransformnextbox{#2}{#3}{#4}{#5}{#6}{#7}% does push pop
+ \vbox to \zeropoint\bgroup
+ \vss
+ \hbox to \zeropoint \bgroup
+ \scale[\c!sx=#8,\c!sy=#9]{\raise\dp\MPtextbox\box\MPtextbox}%
+ \forcecolorhack % needed ? already in the scale macro
+ % % This gives: LuaTeX warning: Misplaced \pdfrestore .. don't ask me why.
+ %
+ % \dostartscaling{#8}{#9}%
+ % \raise\dp\MPtextbox\box\MPtextbox
+ % \dostopscaling
+ \hss
+ \egroup
+ \egroup
+ \egroup
+ \smashbox\MPbox
+ \box\MPbox}
+
+\def\MPLIBgraphictext#1% use at mp end
{\startTEXpage[\c!scale=10000]#1\stopTEXpage}
-\def\MPLIBpositionwhd#1#2#3#4#5%
- {\dosavepositionwhd{#1}{0}{#2sp}{#3sp}{#4sp}{#5sp}{0sp}}
+%D \startbuffer
+%D \definelayer[test]
+%D
+%D \setlayerframed
+%D [test]
+%D [x=\MPx{somepos-1},y=\MPy{somepos-1}]
+%D [width=\MPw{somepos-1},height=\MPh{somepos-1}]
+%D {Whatever we want here!}
+%D
+%D \setlayerframed
+%D [test]
+%D [x=\MPx{somepos-2},y=\MPy{somepos-2}]
+%D [width=\MPw{somepos-2},height=\MPh{somepos-2}]
+%D {Whatever we need there!}
+%D
+%D \startuseMPgraphic{oeps}
+%D draw fullcircle scaled 6cm withcolor red ;
+%D register ("somepos-1",5cm,1cm,center currentpicture) ;
+%D register ("somepos-2",4cm,3cm,(-1cm,-2cm)) ;
+%D \stopuseMPgraphic
+%D
+%D \framed[background=test,offset=overlay]{\useMPgraphic{oeps}}
+%D \stopbuffer
+%D
+%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
+
+\def\MPLIBpositionwhd#1#2#3#4#5% bp !
+ {\dosavepositionwhd{#1}\zerocount{#2\onebasepoint}{#3\onebasepoint}{#4\onebasepoint}{#5\onebasepoint}\zeropoint}
\def\MPLIBextrapass#1%
- {\ctxlua{metapost.graphic_extra_pass(#1)}}
+ {\ctxlua{metapost.graphic_extra_pass("#1")}}
+
+% \def\MPLIBresettexts
+% {\ctxlua{metapost.resettextexts()}}
\def\MPLIBresettexts
- {\ctxlua{metapost.resettextexts()}}
+ {\ctxlua{metapost.resettextexts()}%$
+ \setfalse\MPLIBtextgetdone}
+
+%D Experiment
+
+\def\doMPLIBstopgroup#1#2#3#4#5#6% some day this might happen elsewhere
+ {\egroup
+ \setbox\scratchbox\hbox{\hskip\onebasepoint\box\scratchbox}% weird correction
+ \wd\scratchbox \dimexpr#5\onebasepoint-#3\onebasepoint+2\onebasepoint\relax
+ \ht\scratchbox #6\onebasepoint
+ \dp\scratchbox-#4\onebasepoint
+ \pdfxform
+ attr {/Group << /S /Transparency /I \ifnum#1=1 true \else false \fi /K \ifnum#1=1 true \else false \fi >>}
+ resources {\pdfbackendcurrentresources}
+ \scratchbox
+ \setbox\scratchbox\hbox\bgroup\hskip-\onebasepoint\pdfrefxform\pdflastxform\egroup
+ \setbox\scratchbox\hbox\bgroup\hskip-\onebasepoint\pdfrefxform\pdflastxform\egroup
+ \wd\scratchbox\zeropoint
+ \ht\scratchbox\zeropoint
+ \dp\scratchbox\zeropoint
+ \box\scratchbox
+ \endgroup}
+
+\def\MPLIBstartgroup#1#2#3#4#5#6% isolated 0/1, knockout 0/1 llx lly urx ury
+ {\begingroup
+ \setbox\scratchbox\hbox\bgroup
+ \def\MPLIBstopgroup{\doMPLIBstopgroup{#1}{#2}{#3}{#4}{#5}{#6}}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mlib-run.lua b/Master/texmf-dist/tex/context/base/mlib-run.lua
index 72c16775d4f..f42b5359438 100644
--- a/Master/texmf-dist/tex/context/base/mlib-run.lua
+++ b/Master/texmf-dist/tex/context/base/mlib-run.lua
@@ -36,6 +36,7 @@ local report_metapost = logs.reporter("metapost")
local texerrormessage = logs.texerrormessage
local format, gsub, match, find = string.format, string.gsub, string.match, string.find
+local emptystring = string.is_empty
local starttiming, stoptiming = statistics.starttiming, statistics.stoptiming
@@ -57,30 +58,63 @@ function metapost.resetlastlog()
metapost.lastlog = ""
end
-local function finder(name, mode, ftype) -- we can use the finder to intercept btex/etex
+-- local function realfinder(name, mode, ftype)
+-- if mode == "w" then
+-- return name
+-- elseif file.is_qualified_path(name) then
+-- return name
+-- else
+-- return resolvers.findfile(name,ftype)
+-- end
+-- end
+
+local function i_finder(name, mode, ftype) -- fake message for mpost.map and metafun.mpvi
+ name = file.is_qualified_path(name) and name or resolvers.findfile(name,ftype)
+ if not (find(name,"/metapost/context/base/") or find(name,"/metapost/context/") or find(name,"/metapost/base/")) then
+ local data, found, forced = metapost.checktexts(io.loaddata(name) or "")
+ if found then
+ local temp = luatex.registertempfile(name,true)
+ io.savedata(temp,data)
+ name = temp
+ end
+ end
+ return name
+end
+
+local function o_finder(name, mode, ftype)
+ return name
+end
+
+local function finder(name, mode, ftype)
if mode == "w" then
- return name
- elseif file.is_qualified_path(name) then
- return name
+ return o_finder(name, mode, ftype)
else
- return resolvers.findfile(name,ftype)
+ return i_finder(name, mode, ftype)
end
end
-local function finder(name, mode, ftype) -- we use the finder to intercept btex/etex
- if mode ~= "w" then
- name = file.is_qualified_path(name) and name or resolvers.findfile(name,ftype)
- if not (find(name,"/metapost/context/base/") or find(name,"/metapost/context/") or find(name,"/metapost/base/")) then
- local data, found, forced = metapost.checktexts(io.loaddata(name) or "")
- if found then
- local temp = luatex.registertempfile(name,true)
- io.savedata(temp,data)
- name = temp
- end
+local i_limited = false
+local o_limited = false
+
+directives.register("system.inputmode", function(v)
+ if not i_limited then
+ local i_limiter = io.i_limiter(v)
+ if i_limiter then
+ i_finder = i_limiter.protect(i_finder)
+ i_limited = true
end
end
- return name
-end
+end)
+
+directives.register("system.outputmode", function(v)
+ if not o_limited then
+ local o_limiter = io.o_limiter(v)
+ if o_limiter then
+ o_finder = o_limiter.protect(o_finder)
+ o_limited = true
+ end
+ end
+end)
-- -- --
@@ -223,7 +257,7 @@ else
if not mpx then
result = { status = 99, error = "out of memory"}
else
- result = mpx:execute(format(preamble, file.replacesuffix(name,"mp")))
+ result = mpx:execute(format(preamble, file.addsuffix(name,"mp")))
end
stoptiming(mplib)
metapost.reporterror(result)
@@ -232,14 +266,31 @@ else
function metapost.checkformat(mpsinput)
local mpsversion = environment.version or "unset version"
- local mpsinput = file.addsuffix(mpsinput or "metafun", "mp")
- report_metapost("loading '%s' (experimental metapost version two)",mpsinput)
- local mpx, result = metapost.load(mpsinput)
- if mpx then
- return mpx
+ local mpsinput = mpsinput or "metafun"
+ local foundfile = ""
+ if file.suffix(mpsinput) ~= "" then
+ foundfile = finder(mpsinput) or ""
+ end
+ if foundfile == "" then
+ foundfile = finder(file.replacesuffix(mpsinput,"mpvi")) or ""
+ end
+ if foundfile == "" then
+ foundfile = finder(file.replacesuffix(mpsinput,"mpiv")) or ""
+ end
+ if foundfile == "" then
+ foundfile = finder(file.replacesuffix(mpsinput,"mp")) or ""
+ end
+ if foundfile == "" then
+ report_metapost("loading '%s' fails, format not found",mpsinput)
else
- report_metapost("error in loading '%s'",mpsinput)
- metapost.reporterror(result)
+ report_metapost("loading '%s': %s",mpsinput,foundfile)
+ local mpx, result = metapost.load(foundfile)
+ if mpx then
+ return mpx
+ else
+ report_metapost("error in loading '%s'",mpsinput)
+ metapost.reporterror(result)
+ end
end
end
@@ -287,8 +338,10 @@ end
local mp_inp, mp_log, mp_tag = { }, { }, 0
+-- key/values
+
function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass, askedfig)
- local converted, result = false, {}
+ local converted, result = false, { }
if type(mpx) == "string" then
mpx = metapost.format(mpx) -- goody
end
@@ -323,7 +376,7 @@ function metapost.process(mpx, data, trialrun, flusher, multipass, isextrapass,
if not metapost.reporterror(result) then
if metapost.showlog then
local str = (result.term ~= "" and result.term) or "no terminal output"
- if not string.is_empty(str) then
+ if not emptystring(str) then
metapost.lastlog = metapost.lastlog .. "\n" .. str
report_metapost("log: %s",str)
end
diff --git a/Master/texmf-dist/tex/context/base/mtx-context-arrange.tex b/Master/texmf-dist/tex/context/base/mtx-context-arrange.tex
index b3d8a4df116..49920293fe6 100644
--- a/Master/texmf-dist/tex/context/base/mtx-context-arrange.tex
+++ b/Master/texmf-dist/tex/context/base/mtx-context-arrange.tex
@@ -5,7 +5,7 @@
%D subtitle=Arrange Files,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -25,15 +25,20 @@
% --marking : add cutmarks
% --addempty=list : add empty pages at/after (comma separated list)
% --printformat : 2UP, etc
+% --paperformat=spec : paper*print or paperxprint
+%
+% example: context --extra=arrange --printformat=2UP --paperformat=A4,A3,landscape myfile
%
% end help
+\input mtx-context-common.tex
+
\doifdocumentargument {paperoffset} {
\definepapersize
[offset=\getdocumentargument{paperoffset}]
}
-\doifdocumentargumentelse {noduplex} {yes} {
+\doifdocumentargumentelse {noduplex} {
\setuppagenumbering
[alternative=doublesided]
\setdocumentargument{sided}{doublesided}
@@ -41,9 +46,19 @@
\setdocumentargument{sided}{singlesided}
}
-\setdefaultdocumentargument {textwidth} {0cm}
-\setdefaultdocumentargument {backspace} {0cm}
-\setdefaultdocumentargument {topspace} {0cm}
+\setuppapersize
+ [\getdocumentargument{paperformat_paper}]
+ [\getdocumentargument{paperformat_print}]
+
+% todo: autopapersize
+%
+% \setuppapersize
+% [A4]
+% [A3,landscape]
+
+\setdocumentargumentdefault {textwidth} {0cm}
+\setdocumentargumentdefault {backspace} {0cm}
+\setdocumentargumentdefault {topspace} {0cm}
\setuplayout
[backspace=\getdocumentargument{backspace},
diff --git a/Master/texmf-dist/tex/context/base/mtx-context-combine.tex b/Master/texmf-dist/tex/context/base/mtx-context-combine.tex
index 8a861ab833b..05e31d80087 100644
--- a/Master/texmf-dist/tex/context/base/mtx-context-combine.tex
+++ b/Master/texmf-dist/tex/context/base/mtx-context-combine.tex
@@ -5,7 +5,7 @@
%D subtitle=Combine Files,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -44,16 +44,16 @@
}
+\setuppapersize
+ [\getdocumentargument{paperformat_paper}]
+ [\getdocumentargument{paperformat_print}]
+
\setuplayout
[header=0pt,
footer=0pt,
width=middle,
height=middle]
-\setuppapersize
- [\getdocumentargument{paperformat_paper}]
- [\getdocumentargument{paperformat_print}]
-
\doifnotdocumentargument {bannerheight} {
\setuplayout
[footer=1cm]
diff --git a/Master/texmf-dist/tex/context/base/mtx-context-common.tex b/Master/texmf-dist/tex/context/base/mtx-context-common.tex
index 8327dd28d59..2db0a5be2ae 100644
--- a/Master/texmf-dist/tex/context/base/mtx-context-common.tex
+++ b/Master/texmf-dist/tex/context/base/mtx-context-common.tex
@@ -5,7 +5,7 @@
%D subtitle=Common Stuff,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -29,7 +29,7 @@
\startluacode
local paperformat = document.arguments['paperformat'] or 'A4*A4'
- paperformat = string.upper(paperformat)
+ -- paperformat = string.upper(paperformat) -- no, as we don't want to uppercase 'landscape'
local f, t = string.match(paperformat,"^(.-)%s*[%*xX]%s*(.-)$")
if not f then
f, t = "A4", "A4"
diff --git a/Master/texmf-dist/tex/context/base/mtx-context-ideas.tex b/Master/texmf-dist/tex/context/base/mtx-context-ideas.tex
index 24d11a5b5c7..d10eefc7684 100644
--- a/Master/texmf-dist/tex/context/base/mtx-context-ideas.tex
+++ b/Master/texmf-dist/tex/context/base/mtx-context-ideas.tex
@@ -5,7 +5,7 @@
%D subtitle=Placeholder File,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mtx-context-listing.tex b/Master/texmf-dist/tex/context/base/mtx-context-listing.tex
index 0cbd73784c8..d69db993405 100644
--- a/Master/texmf-dist/tex/context/base/mtx-context-listing.tex
+++ b/Master/texmf-dist/tex/context/base/mtx-context-listing.tex
@@ -5,7 +5,7 @@
%D subtitle=Listing Files,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mtx-context-markdown.tex b/Master/texmf-dist/tex/context/base/mtx-context-markdown.tex
new file mode 100644
index 00000000000..1bd57945f21
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mtx-context-markdown.tex
@@ -0,0 +1,92 @@
+%D \module
+%D [ file=mtx-context-markdown,
+%D version=2011.07.24,
+%D title=\CONTEXT\ Extra Trickry,
+%D subtitle=Rendering Markdown Files,
+%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.
+
+% begin help
+%
+% usage: context --extra=markdown [options] list-of-files
+%
+% --sort : sort filenames first
+% --paperoffset=dimension : left-top-offset
+% --duplex : doublesided (singlesided is default)
+% --backspace=dimension : extra left offset
+% --topspace=dimension : extra top offset
+% --bodyfont=specification : additional bodyfont specification
+% --contents : add table of contents
+%
+% end help
+
+\usemodule[markdown]
+
+\doifdocumentargument {paperoffset} {
+ \definepapersize
+ [offset=\getdocumentargument{paperoffset}]
+}
+
+\doifdocumentargument{duplex} {
+ \setuppagenumbering
+ [alternative=doublesided]
+} {
+ \setuppagenumbering
+ [alternative=singlesided]
+}
+
+\setdocumentargumentdefault {textwidth} {middle}
+\setdocumentargumentdefault {backspace} {2cm}
+\setdocumentargumentdefault {topspace} {2cm}
+\setdocumentargumentdefault {bodyfont} {}
+
+\setuptolerance
+ [verytolerant,stretch]
+
+\setuplayout
+ [width=middle,
+ height=middle,
+ backspace=\getdocumentargument{backspace},
+ topspace=\getdocumentargument{topspace},
+ footer=0pt]
+
+\setupbodyfont
+ [dejavu,10pt,\getdocumentargument{bodyfont}]
+
+\setupwhitespace
+ [big]
+
+% \enabletrackers[context.trace]
+
+\setuplist
+ [chapter,section,subsection]
+ [aligntitle=yes,
+ width=4em]
+
+\starttext
+
+\doifdocumentargument{contents} {
+ \starttitle[title={Table of contents}]
+ \placelist[chapter,section,subsection] % todo: levels
+ \stoptitle
+}
+
+
+\startluacode
+ if #document.files > 0 then
+ if document.arguments.sort then
+ table.sort(document.files)
+ end
+ for i=1,#document.files do
+ context.processmarkdownfile(document.files[i])
+ context.page()
+ end
+ end
+\stopluacode
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/mtx-context-select.tex b/Master/texmf-dist/tex/context/base/mtx-context-select.tex
index 8a02bdff729..7d6535119e7 100644
--- a/Master/texmf-dist/tex/context/base/mtx-context-select.tex
+++ b/Master/texmf-dist/tex/context/base/mtx-context-select.tex
@@ -7,7 +7,7 @@
%D subtitle=Listing Files,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mtx-context-timing.tex b/Master/texmf-dist/tex/context/base/mtx-context-timing.tex
index b788d4b6379..1bc5b47762c 100644
--- a/Master/texmf-dist/tex/context/base/mtx-context-timing.tex
+++ b/Master/texmf-dist/tex/context/base/mtx-context-timing.tex
@@ -5,7 +5,7 @@
%D subtitle=Timing Runs,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mult-aux.lua b/Master/texmf-dist/tex/context/base/mult-aux.lua
index cbecd2df1d5..e0fd87a024c 100644
--- a/Master/texmf-dist/tex/context/base/mult-aux.lua
+++ b/Master/texmf-dist/tex/context/base/mult-aux.lua
@@ -67,7 +67,7 @@ function namespaces.define(namespace,settings)
end
local style = ns.style
if style == v_yes then
- context.installattributehandler(self,name)
+ context.installstyleandcolorhandler(self,name)
if trace_namespaces then
report_namespaces("installing attribute handler for '%s'",name)
end
@@ -108,6 +108,13 @@ function namespaces.define(namespace,settings)
report_namespaces("installing set/let/reset command for '%s' (multiple)",name)
end
end
+ local frame = ns.frame
+ if frame == v_yes then
+ context.installinheritedframed(name)
+ if trace_namespaces then
+ report_namespaces("installing framed command for '%s'",name)
+ end
+ end
context.protect()
end
diff --git a/Master/texmf-dist/tex/context/base/mult-aux.mkii b/Master/texmf-dist/tex/context/base/mult-aux.mkii
index f06833bffc3..3869a95db2e 100644
--- a/Master/texmf-dist/tex/context/base/mult-aux.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-aux.mkii
@@ -5,7 +5,7 @@
%D subtitle=helpers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mult-aux.mkiv b/Master/texmf-dist/tex/context/base/mult-aux.mkiv
index 1dfe6fb8efd..b4c6ad03960 100644
--- a/Master/texmf-dist/tex/context/base/mult-aux.mkiv
+++ b/Master/texmf-dist/tex/context/base/mult-aux.mkiv
@@ -5,16 +5,21 @@
%D subtitle=helpers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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.
+% todo: setupxxx and setupxxxs (so a plural for the root setup and
+% we can consider blocking the root)
+
%D A generalization of \MKIV-like inheritance. Just something to play
%D with (interface might change). The code here evolved in an email
%D exchange between me and Wolgang Schuster.
+% todo: doifelse<whatever>
+
\writestatus{loading}{ConTeXt Multilingual Macros / Helpers}
\registerctxluafile{mult-aux}{1.001}
@@ -25,18 +30,18 @@
%D \unprotect
%D \def\????aa{@@@@aa}
%D
-%D \installparameterhandler \????aa {whatever}
-%D \installsetuphandler \????aa {whatever}
-%D \installdefinehandler \????aa {whatever} \????aa % #3 == defaultroot
-%D \installattributehandler \????aa {whatever}
+%D \installparameterhandler \????aa {whatever}
+%D \installsetuphandler \????aa {whatever}
+%D \installdefinehandler \????aa {whatever} \????aa % #3 == defaultroot
+%D \installfontandcolorhandler\????aa {whatever}
%D
-%D % \installcommandhandler \????aa {whatever} \????aa
+%D % \installcommandhandler \????aa {whatever} \????aa
%D \protect
%D
%D % \whateverparameter \c!test
%D % \whateverparameterhash \c!test
%D % \namedwhateverparameter \mycurrentwhatever \c!test
-%D % \dosetwhateverattributes \c!style \c!color
+%D % \dosetwhateverstyleandcolor \c!style \c!color
%D % \everydefinewhatever (sets \currentwhatever)
%D % \everypresetwhatever (can be used to reset parameters as we can redefine)
%D % \everysetupwhatever (sets \currentwhatever)
@@ -62,148 +67,583 @@
% watch the push/pop and predefinition of current .. this is needed for nested
% definitions and overloaded defines using the predefined one
-\unexpanded\def\doinstallparameterhandler#1#2#3#4#5#6#7%
- {\ifx#2\relax\let#2\empty\fi
- \def#3##1{\csname#4{#1#2}{##1}\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\s!empty\else#4{##1}{##2}\fi}%
- \def#6##1##2{\csname#4{#1##1}{##2}\endcsname}%
- \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}} % always root
+% todo: add (relaxed) postsetup and postdefine hooks, just after the everys
+
+% Start of experimental code: especially tables can have many assignments
+% and although most time is spent in the typesetting anyway, we can squeeze
+% out a little bit. Of course having 500 rows of 50 columns each with some
+% setting does not happen that often. One should keep in mind that in the
+% average document having some 500 assignments is no exception but there we're
+% talking of neglectable runtime for them. Of course in the definitions below
+% there is no real gain, only in the generated \setup* commands. Another
+% situation with many assignments is \XML\ where we can pass attributes
+% and normally don't do testing of them making sense.
+%
+% \testfeatureonce{100000}{\getparameters[bla][a=111,b=222,c=333]}% 1.669s
+% \testfeatureonce{100000}{\mult_interfaces_get_parameters{bla} [a=111,b=222,c=333]}% 1.529s
+% \testfeatureonce{100000}{\def\m_mult_interfaces_namespace{bla}\mult_interfaces_get_parameters_indeed[a=111,b=222,c=333]}% 1.466s
+
+\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% we can assume that the test already happened
+% {\def\m_mult_interfaces_namespace{#1}%
+% \mult_interfaces_get_parameters_indeed}
+
+\def\mult_interfaces_get_parameters_indeed#1]% namespace already set
+ {\mult_interfaces_get_parameters_item#1,],\@relax@}
+
+\def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before ,
+ {\if,#1,% dirty trick for testing #1=empty
+ \expandafter\mult_interfaces_get_parameters_item
+ \else\if]#1%
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \mult_interfaces_get_parameters_assign#1==\empty\@relax@
+ \doubleexpandafter\mult_interfaces_get_parameters_item
+ \fi\fi#2}
+
+\def\mult_interfaces_get_parameters_error#1#2#3%
+ {\showassignerror{#2}{\the\inputlineno\space(#1)}}
+
+\def\mult_interfaces_get_parameters_assign#1=#2=#3#4\@relax@
+ {\ifx\empty#1\empty
+ \expandafter\mult_interfaces_get_parameters_error
+ \else\ifx#3\empty
+ \doubleexpandafter\mult_interfaces_get_parameters_error
+ \else
+ \doubleexpandafter\dosetvalue
+ \fi\fi
+ \m_mult_interfaces_namespace{#1}{#2}}
+
+\newif\ifassignment
+
+\def\mult_check_for_assignment#1=#2#3\_end_
+ {\expandafter\if\detokenize{#2}@\assignmentfalse\else\assignmenttrue\fi}
+
+% usage: \mult_check_for_assignment##1=@@_end_
+
+% End of experimental code.
+
+\unexpanded\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#4{#1#2}{##1}\endcsname}%
+ \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\s!empty\else#4{##1}{##2}\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{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}%
+ \def#9##1{\csname#1#2:##1\endcsname}}
\unexpanded\def\installparameterhandler#1#2%
{\normalexpanded
- {\doinstallparameterhandler
+ {\mult_interfaces_install_parameter_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname current#2\endcsname
\expandafter\noexpand\csname #2parameter\endcsname
- \expandafter\noexpand\csname do#2parameter\endcsname
- \expandafter\noexpand\csname do#2parentparameter\endcsname
+ \expandafter\noexpand\csname do#2parameter\endcsname % or : #2_parameter_hash
+ \expandafter\noexpand\csname do#2parentparameter\endcsname % or : #2_parent_parameter_hash
\expandafter\noexpand\csname named#2parameter\endcsname
- \expandafter\noexpand\csname detokenized#2parameter\endcsname}}
+ \expandafter\noexpand\csname detokenized#2parameter\endcsname
+ \expandafter\noexpand\csname strict#2parameter\endcsname % checked
+ \expandafter\noexpand\csname direct#2parameter\endcsname}} % unchecked
-\unexpanded\def\doinstallparameterhashhandler#1#2#3#4#5%
+\unexpanded\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{\csname\ifcsname#1:##1\endcsname#1:##1\else\s!empty\fi\endcsname}}
+
+\unexpanded\def\installrootparameterhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_root_parameter_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname detokenizedroot#2parameter\endcsname
+ \expandafter\noexpand\csname root#2parameter\endcsname}}
+
+\unexpanded\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{#4{#1#2}{##1}}%
- \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#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#6{#1#2:}%
+ \def#7##1{#1##1:}%
+ \def#8{\ifx#2\empty\else\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi\fi}%
+ \unexpanded\def#9##1{\expandafter\edef\csname#1##1:\s!parent\endcsname{#1#2}}}
\unexpanded\def\installparameterhashhandler#1#2%
- {\normalexpanded
- {\doinstallparameterhashhandler
+ {\expandafter\let\csname#2namespace\endcsname#1%
+ \normalexpanded
+ {\mult_interfaces_install_parameter_hash_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname current#2\endcsname
\expandafter\noexpand\csname #2parameterhash\endcsname
- \expandafter\noexpand\csname do#2parameterhash\endcsname
- \expandafter\noexpand\csname do#2parentparameterhash\endcsname}}
+ \expandafter\noexpand\csname do#2parameterhash\endcsname % or : #2_parameter_hash
+ \expandafter\noexpand\csname do#2parentparameterhash\endcsname % or : #2_parent_parameter_hash
+ \expandafter\noexpand\csname current#2hash\endcsname
+ \expandafter\noexpand\csname named#2hash\endcsname
+ \expandafter\noexpand\csname check#2parent\endcsname
+ \expandafter\noexpand\csname chaintocurrent#2\endcsname}}
+
+% In \MKIV\ we can probably use the english variant for all other
+% languages too.
-\unexpanded\def\doinstallparametersethandler#1#2#3#4#5%
+\unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6% we can speed this up for english
{\ifx#2\relax\let#2\empty\fi
- \def#3{\dosetvalue{#1#2}}% ##1 {##2} (braces are mandate)
- \def#4{\doletvalue{#1#2}}% ##1 ##2
- \def#5{\doletvalue{#1#2}\empty}}% ##1
+ \unexpanded\def#3{\dosetvalue {#1#2:}}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#4{\dosetevalue{#1#2:}}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#5{\doletvalue {#1#2:}}% ##1 ##2
+ \unexpanded\def#6{\doletvalue {#1#2:}\empty}}% ##1
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
+ {\ifx#2\relax\let#2\empty\fi
+ \unexpanded\def#3##1{\expandafter \def\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#4##1{\expandafter\edef\csname#1#2:##1\endcsname}% ##1 {##2} (braces are mandate)
+ \unexpanded\def#5##1{\expandafter \let\csname#1#2:##1\endcsname}% ##1 ##2
+ \unexpanded\def#6##1{\expandafter \let\csname#1#2:##1\endcsname\empty}}% ##1
+
+\stopinterface
\unexpanded\def\installparametersethandler#1#2%
{\normalexpanded
- {\doinstallparametersethandler
+ {\mult_interfaces_install_parameter_set_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname current#2\endcsname
\expandafter\noexpand\csname set#2parameter\endcsname
+ \expandafter\noexpand\csname setexpanded#2parameter\endcsname
\expandafter\noexpand\csname let#2parameter\endcsname
\expandafter\noexpand\csname reset#2parameter\endcsname}}
-\unexpanded\def\doinstallattributehandler#1#2#3% #1 not used here
- {\def#2##1##2% style color
- {\edef\fontattributehash {#3{##1}}%
- \edef\colorattributehash{#3{##2}}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash {##1}\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash{##2}\fi}}
+\let\dousecurrentstyleparameter\relax
+\let\dousecurrentcolorparameter\relax
+
+\let\currentstyleparameter\empty
+\let\currentcolorparameter\empty
-\unexpanded\def\installattributehandler#1#2%
+\unexpanded\def\mult_interfaces_install_style_and_color_handler#1#2#3#4%
+ {\unexpanded\def#2##1##2% style color
+ {\edef\currentstyleparameter{#1{##1}}% this name is public
+ \edef\currentcolorparameter{#1{##2}}% this name is public
+ \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi
+ \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}%
+ \unexpanded\def#3##1% style
+ {\edef\currentstyleparameter{#1{##1}}% this name is public
+ \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi}%
+ \unexpanded\def#4##1% color
+ {\edef\currentcolorparameter{#1{##1}}% this name is public
+ \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}}
+
+\unexpanded\def\installstyleandcolorhandler#1#2%
{\normalexpanded
- {\doinstallattributehandler
- {\noexpand#1}% \??aa
- \expandafter\noexpand\csname doset#2attributes\endcsname
- \expandafter\noexpand\csname #2parameterhash\endcsname}}
+ {\mult_interfaces_install_style_and_color_handler
+ \expandafter\noexpand\csname #2parameter\endcsname
+ \expandafter\noexpand\csname use#2styleandcolor\endcsname % maybe an alias use#2styleandcolorparameters
+ \expandafter\noexpand\csname use#2styleparameter\endcsname
+ \expandafter\noexpand\csname use#2colorparameter\endcsname}}
\let\definehandlerparent\empty
-\unexpanded\def\doinstalldefinehandler#1#2#3#4#5#6#7#8%
+\unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9%
{\ifx#4\relax\let#4\empty\fi
\unexpanded\def#2{\dotripleempty#5}%
\newtoks#6%
\newtoks#7%
\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
- {\let\saveddefinewhatever#4%
+ {\let#9#4%
\edef#4{##1}%
\the#6% predefine
\ifthirdargument
\edef#8{##2}%
- \getparameters[#1#4][\s!parent=#1##2,##3]%
+ \mult_interfaces_get_parameters{#1#4:}[\s!parent=#1##2,##3]%
\else\ifsecondargument
- \doifassignmentelse{##2}
- {\let#8\empty
- \getparameters[#1#4][\s!parent=#3,##2]}
- {\edef#8{##2}%
- \getparameters[#1#4][\s!parent=#1##2]}%
+ \mult_check_for_assignment##2=@@\_end_
+ \ifassignment
+ \let#8\empty
+ \mult_interfaces_get_parameters{#1#4:}[\s!parent=#3,##2]%
+ \else
+ \edef#8{##2}%
+ \mult_interfaces_get_parameters{#1#4:}[\s!parent=#1##2]%
+ \fi
\else
\let#8\empty
- \getparameters[#1#4][\s!parent=#3]%
+ \mult_interfaces_get_parameters{#1#4:}[\s!parent=#3]%
\fi\fi
\the#7%
- \let#4\saveddefinewhatever}}
+ \let#4#9}}
\unexpanded\def\installdefinehandler#1#2#3%
{\normalexpanded
- {\doinstalldefinehandler
+ {\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 d@define#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 current#2parent\endcsname
+ \expandafter\noexpand\csname saved_defined_#2\endcsname}}
-\unexpanded\def\doinstallsetuphandler#1#2#3#4#5#6%
+\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8%
{\ifx#3\relax\let#3\empty\fi
\unexpanded\def#2{\dodoubleempty#4}%
- \unexpanded\def#6{\getparameters[#1#3]}%
+ \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
\newtoks#5%
+ \newtoks#8%
\def#4[##1][##2]% maybe helper
- {\let\savedsetupwhatever#3%
+ {\let#7#3%
\ifsecondargument
- \def\docommand####1% we will have a simple one as well
+ \def\mult_interfaces_with_comma_list_element####1% we will have a simple one as well
{\edef#3{####1}%
- \getparameters[#1#3][##2]%
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
\the#5}%
- \processcommalist[##1]\docommand
+ \processcommalist[##1]\mult_interfaces_with_comma_list_element
\else
\let#3\empty
- \getparameters[#1][##1]%
+ \mult_interfaces_get_parameters{#1:}[##1]%
\the#5%
\fi
- \let#3\savedsetupwhatever}}
+ \let#3#7%
+ \the#8}}
\unexpanded\def\installsetuphandler#1#2%
{\normalexpanded
- {\doinstallsetuphandler
+ {\mult_interfaces_install_setup_handler
{\noexpand#1}% \??aa
\expandafter\noexpand\csname setup#2\endcsname
\expandafter\noexpand\csname current#2\endcsname
- \expandafter\noexpand\csname d@setup#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 setupcurrent#2\endcsname
+ \expandafter\noexpand\csname saved_setup_current#2\endcsname
+ \expandafter\noexpand\csname everysetup#2root\endcsname}}
-\unexpanded\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+\let\doingrootsetupnamed\plusone % \setuplayout[name][key=value]
+\let\doingrootsetuproot \plustwo % \setuplayout [key=value]
+\let\doingrootsetnamed \plusthree % \setuplayout[name]
+\let\doingrootsetroot \plusfour % \setuplayout
+
+\unexpanded\def\mult_interfaces_install_switch_setup_handler_a#1#2#3#4#5%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#2{\dodoubleempty#4}%
+ \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}}
+
+\unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
+ {\newtoks#5%
+ \newconstant#2%
+ \newtoks#8%
+ \newtoks#9%
+ \ifx#6\relax\let#6\empty\fi
+ \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]%
+ \the#5%
+ \ifx#3#6\the#8\fi % only switchsetups if previous == current
+ \let#3#7%
+ \else\iffirstargument
+ \mult_check_for_assignment##1=@@\_end_ % \docheckassignment{##1}%
+ \ifassignment
+ % \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%
+ \else
+ % \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
+ \fi
+ \else
+ % \setuplayout
+ \let#6#3% % previous becomes current
+ \let#3\empty % current becomes empty
+ #2\doingrootsetroot
+ \the#5%
+ \the#8% switchsetups
+ \fi\fi
+ #2\zerocount % mode is always zero at the end
+ \the#9}}
+
+\unexpanded\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 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}}
+
+\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8%
+ {\ifx#3\relax\let#3\empty\fi
+ \unexpanded\def#2{\dotripleempty#4}%
+ \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}%
+ \newtoks#5%
+ \def#4[##1][##2][##3]%
+ {\let#8#3%
+ \ifthirdargument
+ \def\mult_interfaces_with_comma_list_element####1%
+ {\edef#3{####1}%
+ \mult_interfaces_get_parameters{#1#3:}[\s!parent=#1##2,##3]% always sets parent
+ \the#5}%
+ \processcommalist[##1]\mult_interfaces_with_comma_list_element
+ \else\ifsecondargument
+ \def\mult_interfaces_with_comma_list_element####1%
+ {\edef#3{####1}%
+ #7% checks parent and sets if needed
+ \mult_interfaces_get_parameters{#1#3:}[##2]%
+ \the#5}%
+ \processcommalist[##1]\mult_interfaces_with_comma_list_element
+ \else
+ \let#3\empty
+ \mult_interfaces_get_parameters{#1:}[##1]%
+ \the#5%
+ \fi\fi
+ \let#3#8}}
+
+\unexpanded\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}}
+
+\unexpanded\def\installbasicparameterhandler#1#2%
{\installparameterhandler {#1}{#2}%
\installparameterhashhandler{#1}{#2}%
\installparametersethandler {#1}{#2}%
- \installdefinehandler {#1}{#2}{#3}%
- \installsetuphandler {#1}{#2}%
- \installattributehandler {#1}{#2}}
+ \installrootparameterhandler{#1}{#2}}
+
+\unexpanded\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installautosetuphandler {#1}{#2}}
+
+\unexpanded\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self)
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installswitchsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installautocommandhandler#1#2#3% automatically defined cloned setups
+ {\installbasicparameterhandler{#1}{#2}%
+ \installdefinehandler {#1}{#2}{#3}%
+ \installautosetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+\unexpanded\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining
+ {\installbasicparameterhandler{#1}{#2}%
+ \installsetuphandler {#1}{#2}%
+ \installstyleandcolorhandler {#1}{#2}}
+
+%D Many mechanisms have some kind of inheritance in place, and these are
+%D the speed||critical ones. Therefore there is no reason to stick to
+%D \type {\@@xxkey} for the sake of performance. For this reason we also
+%D provide a direct variant. This permits a more consistent treatment of
+%D namespaces. A \type {\whateverparameter} call is three times slower
+%D and a \type {\directwhateverparameter} call two times but for some
+%D 100K expansions we only loose some .1 second which is neglectable
+%D given the small amount of expansions in real runs.
+
+%D We don't need colons for such simple cases.
+
+\unexpanded\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4%
+ {\def#2##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
+ \def#3##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
+ \def#4##1{\csname#1##1\endcsname}}
+
+\unexpanded\def\installdirectparameterhandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_direct_parameter_handler
+ {\noexpand#1}%
+ \expandafter\noexpand\csname #2parameter\endcsname
+ \expandafter\noexpand\csname detokenized#2parameter\endcsname
+ \expandafter\noexpand\csname direct#2parameter\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4%
+ {\unexpanded\def#2{\dosingleempty#3}%
+ \newtoks#4%
+ \def#3[##1]%
+ {\mult_interfaces_get_parameters#1[##1]%
+ \the#4}}
+
+\unexpanded\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 everysetup#2\endcsname}}
+
+\unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
+ {\unexpanded\def#2{\dosetvalue #1}%
+ \unexpanded\def#3{\dosetevalue#1}%
+ \unexpanded\def#4{\doletvalue #1}%
+ \unexpanded\def#5{\doletvalue #1\empty}}%
+
+\startinterface english
+
+ \unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
+ {\unexpanded\def#2##1{\expandafter \def\csname#1##1\endcsname}%
+ \unexpanded\def#3##1{\expandafter\edef\csname#1##1\endcsname}%
+ \unexpanded\def#4##1{\expandafter \let\csname#1##1\endcsname}%
+ \unexpanded\def#5##1{\expandafter \let\csname#1##1\endcsname\empty}}%
+
+\stopinterface
+
+\unexpanded\def\installdirectparametersethandler#1#2%
+ {\normalexpanded
+ {\mult_interfaces_install_direct_parameter_set_handler
+ {\noexpand#1}% \??aa
+ \expandafter\noexpand\csname set#2parameter\endcsname
+ \expandafter\noexpand\csname setexpanded#2parameter\endcsname
+ \expandafter\noexpand\csname let#2parameter\endcsname
+ \expandafter\noexpand\csname reset#2parameter\endcsname}}
+
+\let\installdirectstyleandcolorhandler\installstyleandcolorhandler
+
+\unexpanded\def\installdirectcommandhandler#1#2%
+ {\installdirectparameterhandler {#1}{#2}%
+ \installdirectsetuphandler {#1}{#2}%
+ \installdirectparametersethandler {#1}{#2}%
+ \installdirectstyleandcolorhandler{#1}{#2}}
+
+\unexpanded\def\installsetuponlycommandhandler#1#2%
+ {\installdirectparameterhandler{#1}{#2}%
+ \installdirectsetuphandler {#1}{#2}%
+ }% maybe \installdirectparametersethandler {#1}{#2}%
-\unexpanded\def\installnamespace#1%
- {\setvalue{????#1}{@@@@#1}}
+% Experiment:
+
+% \installcorenamespace {one}
+% \installcorenamespace {two}
+%
+% \installcommandhandler \??one {one} \??one
+% \installcommandhandler \??two {two} \??two
+%
+% \defineone[test] \setupone[test][alpha=first]
+% \definetwo[test] \setuptwo[test][beta=second]
+%
+% \protect
+%
+% \def\currentone{test}
+% \def\currenttwo{test}
+%
+% \relateparameterhandlers {two} {test} {one} {test}
+%
+% yes:\oneparameter{alpha}\par
+% nop:\oneparameter{beta}\par
+% yes:\twoparameter{alpha}\par
+% yes:\twoparameter{beta}\par
+
+\unexpanded\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance}
+ {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}}
+
+% First we had, in tune with the regular system variables:
+%
+% \starttyping
+% \unexpanded\def\installnamespace#1{\setvalue{????#1}{@@@@#1}}
+% \stoptyping
+%
+% The following variant is nicer and in principle faster but that gets
+% unnoticed unless lots of expansion happens. Also, we can use long tags
+% but the internal expansion will be relatively small (and unlikely more
+% than 4 characters). For instance, \??xx used to expand to @@xx but now
+% becomes for instance 123::. This is one character more but in quite some
+% cases we had : after such a tag in the old situation. In the new situation
+% we create more namespaces and don't need that : any more, so we end up
+% with on the average the same amount of tokens and definitely less when
+% we consider cases like \??xx:\c!align: which now is just \??somealign and
+% therefore has length 5 now (instead of 4+1+5+1=10).
+%
+% Eventualy we will have a verbose \blablanamespace and the difference between
+% core and regular can go ... after all, \xxxparameter can already clash between
+% the two prefix groups .. if users use this mechanism a lot they should use
+% verbose names anyway (the old two character names were mostly an optimization
+% as they also expanded to these characters).
+
+% todo: register namespaces at lua end for logging and reverse resolve
+% todo: move this to syst-ini so that we can use it real early
+
+\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{\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\else\ifnum\c_mult_interfaces_n_of_namespaces<\plushundred0\fi\fi
+ \number\c_mult_interfaces_n_of_namespaces>}
+
+\def\v_interfaces_prefix_template % consistently %03i>
+ {\number\c_mult_interfaces_n_of_namespaces>}
+
+\unexpanded\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}%
+ \fi}
+
+\unexpanded\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}%
+ \ctxcommand{registernamespace(\number\c_mult_interfaces_n_of_namespaces,"#1")}%
+ \fi}
+
+% We install two core namespaces here, as we want nice error messages. Maybe
+% we will reserve the first 9.
+
+\installcorenamespace{fontinstanceready}
+\installcorenamespace{fontinstancebasic}
+\installcorenamespace{fontinstanceclass}
+
+% Maybe a \definecorenamespace[name][directparameter,directsetup][parent]
+% but we don't gain much. Actually we might just inline all definitions.
% \enabletrackers[interfaces.namespaces,context.flush]
%
@@ -240,11 +680,13 @@
% “\testparameter{text}â€
%
% \stoptext
+%
+% This is a user (module) command:
\unexpanded\def\definenamespace
- {\dodoubleargument\dodefinenamespace}
+ {\dodoubleargument\mult_interfaces_define_name_space}
-\def\dodefinenamespace[#1][#2]% namespace settings
+\def\mult_interfaces_define_name_space[#1][#2]% namespace settings
{\ctxlua{interfaces.namespaces.define(\!!bs#1\!!es,\!!bs#2\!!es)}}
\def\listnamespaces
@@ -256,14 +698,29 @@
%D \showparentchain{@@am}{left}
%D \stoptyping
-\def\doshowparentchain#1%
+\unexpanded\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\doshowparentchain\csname#1\s!parent\endcsname
+ \ifcsname#1:\s!parent\endcsname
+ \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
\fi}
-\def\showparentchain#1#2%
- {\writestatus\m!system{chain: [ \doshowparentchain{#1#2}]}}
+%D Conventions:
+%D
+%D \starttyping
+%D \newcount \c_class_whatever
+%D \newconditional \c_class_whatever
+%D \newconstant \c_class_whatever
+%D \newdimen \d_class_whatever
+%D \newskip \s_class_whatever
+%D \newmuskip \s_class_whatever
+%D \newbox \b_class_whatever
+%D \newtoks \t_class_whatever
+%D
+%D \edef\p_class_whatever{\classparameter\c!whatever}
+%D \edef\m_class_whatever{whatever}
+%D \stoptyping
\protect
-
diff --git a/Master/texmf-dist/tex/context/base/mult-chk.lua b/Master/texmf-dist/tex/context/base/mult-chk.lua
index 4b1ba12ee3e..43e7c51218e 100644
--- a/Master/texmf-dist/tex/context/base/mult-chk.lua
+++ b/Master/texmf-dist/tex/context/base/mult-chk.lua
@@ -9,7 +9,6 @@ if not modules then modules = { } end modules ['mult-chk'] = {
local format = string.format
local lpegmatch = lpeg.match
local type = type
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
local make_settings_to_hash_pattern, settings_to_set = utilities.parsers.make_settings_to_hash_pattern, utilities.parsers.settings_to_set
local allocate = utilities.storage.allocate
@@ -48,15 +47,18 @@ function interfaces.addvalidkeys(category,list)
end
end
--- weird code, looks incomplete ... probbably an experiment
+-- weird code, looks incomplete ... probably an experiment
local prefix, category, keys
+local setsomevalue = context.setsomevalue
+local invalidkey = interfaces.invalidkey
+
local function set(key,value)
if keys and not keys[key] then
- interfaces.invalidkey(category,key)
+ invalidkey(category,key)
else
- context.setsomevalue(prefix,key,value)
+ setsomevalue(prefix,key,value)
end
end
diff --git a/Master/texmf-dist/tex/context/base/mult-chk.mkii b/Master/texmf-dist/tex/context/base/mult-chk.mkii
index 60f568a1ee4..cde00fd44c4 100644
--- a/Master/texmf-dist/tex/context/base/mult-chk.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-chk.mkii
@@ -5,7 +5,7 @@
%D subtitle=Checking,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mult-chk.mkiv b/Master/texmf-dist/tex/context/base/mult-chk.mkiv
index cf38daf6700..9260d204066 100644
--- a/Master/texmf-dist/tex/context/base/mult-chk.mkiv
+++ b/Master/texmf-dist/tex/context/base/mult-chk.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Checking,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -35,38 +35,38 @@
\registerctxluafile{mult-chk}{1.001}
-\def\setvalidparameterkeys{\dodoubleargument\dosetvalidparameterkeys}
-\def\addvalidparameterkeys{\dodoubleargument\doaddvalidparameterkeys}
+\def\setvalidparameterkeys{\dodoubleargument\mult_checkers_set_valid_parameter_keys}
+\def\addvalidparameterkeys{\dodoubleargument\mult_checkers_add_valid_parameter_keys}
-\def\dosetvalidparameterkeys[#1][#2]{\ctxlua{interfaces.setvalidkeys("#1",\!!bs#2\!!es)}}
-\def\doaddvalidparameterkeys[#1][#2]{\ctxlua{interfaces.addvalidkeys("#1",\!!bs#2\!!es)}}
+\def\mult_checkers_set_valid_parameter_keys[#1][#2]{\ctxlua{interfaces.setvalidkeys("#1",\!!bs#2\!!es)}}
+\def\mult_checkers_add_valid_parameter_keys[#1][#2]{\ctxlua{interfaces.addvalidkeys("#1",\!!bs#2\!!es)}}
-\def\getcheckedparametersyes[#1]#2[#3]#4[#5%
+\def\mult_checkers_get_checked_parameters_yes[#1]#2[#3]#4[#5%
{\if\noexpand#5]%
\expandafter\gobblethreearguments
\else
- \let\setsomevalue\dosetvalue
- \expandafter\dogetcheckedparametersyes
+ \let\setsomevalue\dosetvalue % used at the lua end
+ \expandafter\mult_checkers_get_checked_parameters_yes_indeed
\fi{#1}{#3}#5}
-\def\dogetcheckedparametersyes#1#2#3]%
+\def\mult_checkers_get_checked_parameters_yes_indeed#1#2#3]%
%{\ctxlua{_igcp_("#1","#2",\!!bs\detokenize{#3}\!!es)}}
{\ctxlua{interfaces.getcheckedparameters("#1","#2",\!!bs\detokenize{#3}\!!es)}}
-\def\getcheckedparametersnop[#1]#2[#3]#4[#5%
+\def\mult_checkers_get_checked_parameters_nop[#1]#2[#3]#4[#5%
{\if\noexpand#5]%
\expandafter\gobbletwoarguments
\else
- \let\setsomevalue\dosetvalue
- \expandafter\dogetcheckedparametersnop
+ \let\setsomevalue\dosetvalue % used at the lua end
+ \expandafter\mult_checkers_get_checked_parameters_nop_indeed
\fi{#3}#5}
-\def\dogetcheckedparametersnop#1#2]%
+\def\mult_checkers_get_checked_parameters_nop_indeed#1#2]%
{\def\p!dogetparameter{\p!doassign#1}%
\xprocesscommaitem#2,],\@relax@}
-\def\disablecheckparameters{\let\getcheckedparameters\getcheckedparametersnop}
-\def\enablecheckparameters {\let\getcheckedparameters\getcheckedparametersyes}
+\def\disablecheckparameters{\let\getcheckedparameters\mult_checkers_get_checked_parameters_nop}
+\def\enablecheckparameters {\let\getcheckedparameters\mult_checkers_get_checked_parameters_yes}
\disablecheckparameters
diff --git a/Master/texmf-dist/tex/context/base/mult-com.mkii b/Master/texmf-dist/tex/context/base/mult-com.mkii
index 1186168377b..600819b7ebc 100644
--- a/Master/texmf-dist/tex/context/base/mult-com.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-com.mkii
@@ -5,7 +5,7 @@
%D subtitle=Commands,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 licen-en.pdf for
diff --git a/Master/texmf-dist/tex/context/base/mult-con.mkii b/Master/texmf-dist/tex/context/base/mult-con.mkii
index 62e97d5671a..7d0a47bd0a6 100644
--- a/Master/texmf-dist/tex/context/base/mult-con.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-con.mkii
@@ -5,7 +5,7 @@
%D subtitle=Constants,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mult-de.mkii b/Master/texmf-dist/tex/context/base/mult-de.mkii
index 6d6b04dcaf0..ecc77ea8221 100644
--- a/Master/texmf-dist/tex/context/base/mult-de.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-de.mkii
@@ -4,6 +4,8 @@
%
\setinterfacevariable{Addition}{Zusatz}
\setinterfacevariable{Balloon}{Ballon}
+\setinterfacevariable{Cap}{Kap}
+\setinterfacevariable{Capital}{Versalien}
\setinterfacevariable{Character}{Buchstabe}
\setinterfacevariable{Characters}{Buchstaben}
\setinterfacevariable{CloseDocument}{SchliesseDokument}
@@ -61,6 +63,9 @@
\setinterfacevariable{ViewerHelp}{ViewerHilfe}
\setinterfacevariable{WEEKDAY}{WOCHENTAG}
\setinterfacevariable{WORD}{WORT}
+\setinterfacevariable{WORDS}{WOERTER}
+\setinterfacevariable{Word}{Wort}
+\setinterfacevariable{Words}{Woerter}
\setinterfacevariable{abbreviation}{abkuerzung}
\setinterfacevariable{abbreviations}{abkuerzungen}
\setinterfacevariable{absolute}{absolut}
@@ -72,11 +77,11 @@
\setinterfacevariable{answerarea}{answerarea}
\setinterfacevariable{appendices}{anhaenge}
\setinterfacevariable{appendix}{anhang}
-\setinterfacevariable{april}{April}
+\setinterfacevariable{april}{april}
\setinterfacevariable{atmargin}{amrand}
\setinterfacevariable{atpage}{aufseite}
\setinterfacevariable{attachment}{attachment}
-\setinterfacevariable{august}{August}
+\setinterfacevariable{august}{august}
\setinterfacevariable{author}{autor}
\setinterfacevariable{auto}{auto}
\setinterfacevariable{autointro}{autointro}
@@ -134,7 +139,7 @@
\setinterfacevariable{cutspace}{cutspace}
\setinterfacevariable{date}{datum}
\setinterfacevariable{day}{tag}
-\setinterfacevariable{december}{Dezember}
+\setinterfacevariable{december}{dezember}
\setinterfacevariable{default}{default}
\setinterfacevariable{depth}{tiefe}
\setinterfacevariable{description}{beschreibung}
@@ -154,7 +159,7 @@
\setinterfacevariable{even}{gerade}
\setinterfacevariable{external}{extern}
\setinterfacevariable{fact}{gegeben}
-\setinterfacevariable{february}{Februar}
+\setinterfacevariable{february}{februar}
\setinterfacevariable{figure}{abbildung}
\setinterfacevariable{figures}{abbildungen}
\setinterfacevariable{file}{datei}
@@ -232,10 +237,10 @@
\setinterfacevariable{item}{pos}
\setinterfacevariable{itemize}{aufzaehlung}
\setinterfacevariable{its}{its}
-\setinterfacevariable{january}{Januar}
+\setinterfacevariable{january}{januar}
\setinterfacevariable{joinedup}{keinabstand}
-\setinterfacevariable{july}{Juli}
-\setinterfacevariable{june}{Juni}
+\setinterfacevariable{july}{juli}
+\setinterfacevariable{june}{juni}
\setinterfacevariable{keep}{behalte}
\setinterfacevariable{knockout}{knockout}
\setinterfacevariable{label}{label}
@@ -268,19 +273,20 @@
\setinterfacevariable{ls}{ls}
\setinterfacevariable{makeup}{umbruch}
\setinterfacevariable{mar}{mar}
-\setinterfacevariable{march}{Maerz}
+\setinterfacevariable{march}{maerz}
\setinterfacevariable{margin}{marginalie}
\setinterfacevariable{marginedge}{marginalkante}
\setinterfacevariable{margintitle}{marginaltitel}
\setinterfacevariable{marking}{beschriftung}
\setinterfacevariable{mathalignment}{mathalignment}
\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathematics}{mathematik}
\setinterfacevariable{mathmatrix}{mathmatrix}
\setinterfacevariable{max}{max}
\setinterfacevariable{maxdepth}{maxdepth}
\setinterfacevariable{maxheight}{maxheight}
\setinterfacevariable{maxwidth}{maxwidth}
-\setinterfacevariable{may}{Mai}
+\setinterfacevariable{may}{mai}
\setinterfacevariable{mediaeval}{mittelalterlich}
\setinterfacevariable{medium}{mittel}
\setinterfacevariable{middle}{mittig}
@@ -317,12 +323,12 @@
\setinterfacevariable{note}{note}
\setinterfacevariable{nothanging}{nothanging}
\setinterfacevariable{nothyphenated}{nothyphenated}
-\setinterfacevariable{november}{November}
+\setinterfacevariable{november}{november}
\setinterfacevariable{nowhere}{nirgens}
\setinterfacevariable{nowhite}{keinweiss}
\setinterfacevariable{number}{nummer}
\setinterfacevariable{numbers}{ziffern}
-\setinterfacevariable{october}{Oktober}
+\setinterfacevariable{october}{oktober}
\setinterfacevariable{odd}{ungerade}
\setinterfacevariable{off}{aus}
\setinterfacevariable{offset}{offset}
@@ -356,6 +362,7 @@
\setinterfacevariable{previousoddpage}{vorigeungeradeseite}
\setinterfacevariable{previouspage}{vorigeseite}
\setinterfacevariable{previoussubpage}{vorigeunterseite}
+\setinterfacevariable{print}{print}
\setinterfacevariable{printable}{druckbar}
\setinterfacevariable{process}{process}
\setinterfacevariable{product}{produkt}
@@ -363,6 +370,7 @@
\setinterfacevariable{project}{projekt}
\setinterfacevariable{protected}{geschuetzt}
\setinterfacevariable{quadruple}{viertel}
+\setinterfacevariable{quarterline}{quarterline}
\setinterfacevariable{quotation}{zitat}
\setinterfacevariable{quote}{zitieren}
\setinterfacevariable{ran}{ran}
@@ -402,7 +410,7 @@
\setinterfacevariable{sectionblockenvironment}{sectionblockenvironment}
\setinterfacevariable{sectionnumber}{abschnittsnummer}
\setinterfacevariable{see}{sieh}
-\setinterfacevariable{september}{September}
+\setinterfacevariable{september}{september}
\setinterfacevariable{serif}{serif}
\setinterfacevariable{serried}{kleinerabstand}
\setinterfacevariable{setups}{impostazioni}
@@ -497,6 +505,8 @@
\setinterfacevariable{unavailable}{nichtverfuegbar}
\setinterfacevariable{underbar}{unterstrichen}
\setinterfacevariable{underbars}{unterstreichen}
+\setinterfacevariable{understrike}{understrike}
+\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unit}{einheit}
\setinterfacevariable{units}{einheiten}
\setinterfacevariable{unknown}{unbekannt}
@@ -516,6 +526,7 @@
\setinterfacevariable{white}{weiss}
\setinterfacevariable{wide}{breit}
\setinterfacevariable{width}{breite}
+\setinterfacevariable{word}{wort}
\setinterfacevariable{xml}{xml}
\setinterfacevariable{year}{jahr}
\setinterfacevariable{yes}{ja}
@@ -533,6 +544,7 @@
\setinterfaceconstant{alignsymbol}{alignsymbol}
\setinterfaceconstant{aligntitle}{titelausrichten}
\setinterfaceconstant{alternative}{alternative}
+\setinterfaceconstant{anchor}{anchor}
\setinterfaceconstant{andtext}{andtext}
\setinterfaceconstant{apa}{apa}
\setinterfaceconstant{arrow}{pfeil}
@@ -552,6 +564,8 @@
\setinterfaceconstant{autohang}{autohang}
\setinterfaceconstant{autostrut}{autostrut}
\setinterfaceconstant{autowidth}{autobreite}
+\setinterfaceconstant{availableheight}{availableheight}
+\setinterfaceconstant{availablewidth}{availablewidth}
\setinterfaceconstant{axis}{achsen}
\setinterfaceconstant{background}{hintergrund}
\setinterfaceconstant{backgroundcolor}{hintergrundfarbe}
@@ -571,6 +585,7 @@
\setinterfaceconstant{blank}{blanko}
\setinterfaceconstant{blockway}{blockauf}
\setinterfaceconstant{bodyfont}{fliesstext}
+\setinterfaceconstant{boffset}{boffset}
\setinterfaceconstant{bookmark}{bookmark}
\setinterfaceconstant{bottom}{unten}
\setinterfaceconstant{bottomafter}{bottomafter}
@@ -602,6 +617,8 @@
\setinterfaceconstant{commandafter}{zumbefehl}
\setinterfaceconstant{commandbefore}{vorbefehl}
\setinterfaceconstant{commands}{befehle}
+\setinterfaceconstant{commentoffset}{commentoffset}
+\setinterfaceconstant{compact}{compact}
\setinterfaceconstant{component}{component}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
@@ -615,6 +632,7 @@
\setinterfaceconstant{coupling}{verknuepfung}
\setinterfaceconstant{couplingway}{verkopplungsart}
\setinterfaceconstant{criterium}{kriterium}
+\setinterfaceconstant{css}{css}
\setinterfaceconstant{current}{aktuell}
\setinterfaceconstant{cutspace}{cutspace}
\setinterfaceconstant{dash}{strich}
@@ -643,11 +661,13 @@
\setinterfaceconstant{editoretallimit}{editoretallimit}
\setinterfaceconstant{editoretaltext}{editoretaltext}
\setinterfaceconstant{empty}{leer}
+\setinterfaceconstant{entities}{entities}
\setinterfaceconstant{entries}{entries}
\setinterfaceconstant{equalheight}{equalheight}
\setinterfaceconstant{equalwidth}{equalwidth}
\setinterfaceconstant{escape}{escape}
\setinterfaceconstant{evenmargin}{geraderand}
+\setinterfaceconstant{exitoffset}{labeloffset}
\setinterfaceconstant{expansion}{expansion}
\setinterfaceconstant{export}{export}
\setinterfaceconstant{extras}{extras}
@@ -684,6 +704,7 @@
\setinterfaceconstant{global}{global}
\setinterfaceconstant{grid}{gritter}
\setinterfaceconstant{hang}{haengend}
+\setinterfaceconstant{hcompact}{hcompact}
\setinterfaceconstant{headalign}{headalign}
\setinterfaceconstant{headcolor}{kopffarbe}
\setinterfaceconstant{headcommand}{headcommand}
@@ -712,6 +733,7 @@
\setinterfaceconstant{inner}{innen}
\setinterfaceconstant{innermargin}{innermargin}
\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{insidesection}{insidesection}
\setinterfaceconstant{intent}{intent}
\setinterfaceconstant{interaction}{interaktion}
\setinterfaceconstant{interlinespace}{zeilenabstande}
@@ -724,8 +746,10 @@
\setinterfaceconstant{keys}{keys}
\setinterfaceconstant{keyword}{keyword}
\setinterfaceconstant{label}{label}
+\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{links}
\setinterfaceconstant{leftcolor}{linkerfarbe}
\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
@@ -754,6 +778,7 @@
\setinterfaceconstant{listtext}{listtext}
\setinterfaceconstant{local}{lokal}
\setinterfaceconstant{location}{platz}
+\setinterfaceconstant{loffset}{loffset}
\setinterfaceconstant{logo}{logo}
\setinterfaceconstant{logos}{logos}
\setinterfaceconstant{marcolor}{beschrfarbe}
@@ -830,6 +855,7 @@
\setinterfaceconstant{page}{seite}
\setinterfaceconstant{pageboundaries}{seitenbegrenzung}
\setinterfaceconstant{pagecolor}{seitenfarbe}
+\setinterfaceconstant{pagecolormodel}{pagecolormodel}
\setinterfaceconstant{pagecommand}{seitenbefehl}
\setinterfaceconstant{pageconversion}{pageconversion}
\setinterfaceconstant{pageconversionset}{pageconversionset}
@@ -870,6 +896,7 @@
\setinterfaceconstant{preview}{vorschau}
\setinterfaceconstant{previous}{vorige}
\setinterfaceconstant{previousnumber}{vorigenummer}
+\setinterfaceconstant{printable}{druckbar}
\setinterfaceconstant{process}{process}
\setinterfaceconstant{profile}{profile}
\setinterfaceconstant{pubsep}{pubsep}
@@ -882,6 +909,7 @@
\setinterfaceconstant{reference}{referenz}
\setinterfaceconstant{referenceprefix}{referenceprefix}
\setinterfaceconstant{referencing}{referieren}
+\setinterfaceconstant{region}{region}
\setinterfaceconstant{regionin}{regionin}
\setinterfaceconstant{regionout}{regionaus}
\setinterfaceconstant{repeat}{wiederholen}
@@ -906,9 +934,11 @@
\setinterfaceconstant{rightsubsentence}{rechtersubsatz}
\setinterfaceconstant{righttext}{rechtertext}
\setinterfaceconstant{rightwidth}{rechterbreite}
+\setinterfaceconstant{roffset}{roffset}
\setinterfaceconstant{rotation}{rotation}
\setinterfaceconstant{rule}{linie}
\setinterfaceconstant{rulecolor}{linienfarbe}
+\setinterfaceconstant{rulecommand}{rulecommand}
\setinterfaceconstant{rulethickness}{liniendicke}
\setinterfaceconstant{samepage}{selbeseite}
\setinterfaceconstant{sample}{muster}
@@ -966,6 +996,7 @@
\setinterfaceconstant{subtitle}{untertitel}
\setinterfaceconstant{suffix}{suffix}
\setinterfaceconstant{suffixseparator}{suffixseparator}
+\setinterfaceconstant{suffixstopper}{suffixstopper}
\setinterfaceconstant{surnamesep}{surnamesep}
\setinterfaceconstant{sx}{sx}
\setinterfaceconstant{sy}{sy}
@@ -983,6 +1014,7 @@
\setinterfaceconstant{textcolor}{textfarbe}
\setinterfaceconstant{textcommand}{textbefehl}
\setinterfaceconstant{textdistance}{textdistance}
+\setinterfaceconstant{textheight}{texthoehe}
\setinterfaceconstant{textlayer}{textlayer}
\setinterfaceconstant{textmargin}{textmargin}
\setinterfaceconstant{textmethod}{textmethod}
@@ -1000,6 +1032,7 @@
\setinterfaceconstant{titleright}{titleright}
\setinterfaceconstant{titlestyle}{titelstil}
\setinterfaceconstant{to}{zu}
+\setinterfaceconstant{toffset}{toffset}
\setinterfaceconstant{tolerance}{toleranz}
\setinterfaceconstant{top}{oben}
\setinterfaceconstant{topdistance}{obenabstand}
@@ -1016,6 +1049,8 @@
\setinterfaceconstant{validate}{validieren}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vbefehl}
+\setinterfaceconstant{vcompact}{vcompact}
+\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{kopfoffset}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{voffset}{voffset}
@@ -1025,6 +1060,7 @@
\setinterfaceconstant{white}{weiss}
\setinterfaceconstant{width}{breite}
\setinterfaceconstant{xfactor}{xfaktor}
+\setinterfaceconstant{xhtml}{xhtml}
\setinterfaceconstant{xmax}{xmax}
\setinterfaceconstant{xoffset}{xoffset}
\setinterfaceconstant{xscale}{xformat}
@@ -1042,8 +1078,6 @@
\setinterfaceelement{complete}{vollende}
\setinterfaceelement{coupled}{verknuepft}
\setinterfaceelement{currentlocal}{aktuelllokal}
-\setinterfaceelement{emptyone}{vuoto}
-\setinterfaceelement{emptytwo}{leer}
\setinterfaceelement{end}{ende}
\setinterfaceelement{endsetup}{ein}
\setinterfaceelement{get}{get}
@@ -1156,7 +1190,7 @@
\setinterfacecommand{defineframedtext}{definiereumrahmtertext}
\setinterfacecommand{definehbox}{definierehbox}
\setinterfacecommand{definehead}{definiereueberschrift}
-\setinterfacecommand{defineindenting}{definiereeinzug}
+\setinterfacecommand{defineindentedtext}{defineindentedtext}
\setinterfacecommand{defineinmargin}{defineinmargin}
\setinterfacecommand{defineinteractionmenu}{definiereinteraktionsmenue}
\setinterfacecommand{defineitemgroup}{defineitemgroup}
@@ -1352,7 +1386,6 @@
\setinterfacecommand{pagenumber}{seitenummer}
\setinterfacecommand{pageoffset}{pageoffset}
\setinterfacecommand{pagereference}{seitenreferenz}
-\setinterfacecommand{pagetype}{seitentyp}
\setinterfacecommand{paperheight}{papierhoehe}
\setinterfacecommand{paperwidth}{papierbreite}
\setinterfacecommand{periods}{punkt}
@@ -1468,7 +1501,7 @@
\setinterfacecommand{setupheads}{stelleueberschriftenein}
\setinterfacecommand{setupheadtext}{stelleueberschrifttextein}
\setinterfacecommand{setuphyphenmark}{stellebindestrichein}
-\setinterfacecommand{setupindentations}{stelleeinzuegein}
+\setinterfacecommand{setupindentedtext}{setupindentedtext}
\setinterfacecommand{setupindenting}{stelleeinziehenein}
\setinterfacecommand{setupinmargin}{stelleinmarginalieein}
\setinterfacecommand{setupinteraction}{stelleinteraktionein}
diff --git a/Master/texmf-dist/tex/context/base/mult-def.lua b/Master/texmf-dist/tex/context/base/mult-def.lua
index 8499dd43b29..4ca05c32831 100644
--- a/Master/texmf-dist/tex/context/base/mult-def.lua
+++ b/Master/texmf-dist/tex/context/base/mult-def.lua
@@ -920,15 +920,9 @@ return {
["pe"]="تعریÙ‌سر",
["ro"]="definesteantet",
},
- ["defineindenting"]={
- ["cs"]="definujodsazovani",
- ["de"]="definiereeinzug",
- ["en"]="defineindenting",
- ["fr"]="definitcompoalinea",
- ["it"]="definiscirientro",
- ["nl"]="doorspringen",
- ["pe"]="تعریÙ‌تورÙتگی",
- ["ro"]="definestealiat",
+ ["defineindentedtext"]={
+ ["en"]="defineindentedtext",
+ ["nl"]="definieeringesprongentext",
},
["defineinmargin"]={
["cs"]="defineinmargin",
@@ -2880,16 +2874,6 @@ return {
["pe"]="مرجع‌صÙحه",
["ro"]="referintapagina",
},
- ["pagetype"]={
- ["cs"]="typstrany",
- ["de"]="seitentyp",
- ["en"]="pagetype",
- ["fr"]="tapepage",
- ["it"]="tipopagina",
- ["nl"]="soortpagina",
- ["pe"]="نوع‌صÙحه",
- ["ro"]="tippagina",
- },
["paperheight"]={
["cs"]="vyskapapiru",
["de"]="papierhoehe",
@@ -4040,15 +4024,9 @@ return {
["pe"]="بارگذاری‌نشانه‌شکستن",
["ro"]="seteazaliniesilabe",
},
- ["setupindentations"]={
- ["cs"]="nastavodsazeni",
- ["de"]="stelleeinzuegein",
- ["en"]="setupindentations",
- ["fr"]="reglealineas",
- ["it"]="impostarientri",
- ["nl"]="steldoorspringenin",
- ["pe"]="بارگذاری‌تورÙتگیها",
- ["ro"]="seteazaaliniate",
+ ["setupindentedtext"]={
+ ["en"]="setupindentedtext",
+ ["nl"]="stelingesprongentextin",
},
["setupindenting"]={
["cs"]="nastavodsazovani",
@@ -6471,6 +6449,47 @@ return {
},
},
["constants"]={
+ ["anchor"]={
+ ["en"]="anchor",
+ ["nl"]="anker",
+ },
+ ["buffer"]={
+ ["en"]="buffer",
+ },
+ ["dash"]={
+ ["en"]="dash",
+ ["nl"]="streep",
+ },
+ ["export"] = {
+ ["en"]="export",
+ },
+ ["css"] = {
+ ["en"]="css",
+ },
+ ["xhtml"] = {
+ ["en"]="xhtml",
+ },
+ ["entities"]={
+ ["en"]="entities",
+ ["nl"]="entities",
+ },
+ ["labeloffset"]={
+ ["en"]="labeloffset",
+ },
+ ["exitoffset"]={
+ ["en"]="labeloffset",
+ },
+ ["commentoffset"]={
+ ["en"]="commentoffset",
+ },
+ ["hcompact"]={
+ ["en"]="hcompact",
+ ["nl"]="hcomprimeer",
+ },
+ ["vcompact"]={
+ ["en"]="vcompact",
+ ["nl"]="vcomprimeer",
+ },
["keys"]={
["en"]="keys",
["nl"]="sleutels", -- brrr
@@ -6484,6 +6503,11 @@ return {
},
["order"]={
["en"]="order",
+ ["nl"]="volgorde",
+ },
+ ["compact"]={
+ ["en"]="compact",
+ ["nl"]="compact",
},
["headalign"]={
["en"]="headalign",
@@ -6585,6 +6609,10 @@ return {
["en"]="values",
["nl"]="waarden",
},
+ ["layout"]={
+ ["en"]="layout",
+ ["nl"]="layout",
+ },
["action"]={
["cs"]="akce",
["de"]="aktion",
@@ -6911,6 +6939,10 @@ return {
["en"]="beforesection",
["nl"]="voorsectie",
},
+ ["insidesection"]={
+ ["en"]="insidesection",
+ ["nl"]="binnensectie",
+ },
["beforehead"]={
["cs"]="predhlavickou",
["de"]="vorkopf",
@@ -7501,7 +7533,7 @@ return {
["en"]="directory",
["fr"]="repertoire",
["it"]="directory",
- ["nl"]="gebied",
+ ["nl"]="directory",
["pe"]="پوشه",
["ro"]="director",
},
@@ -7752,6 +7784,14 @@ return {
["filtercommand"]={
["en"]="filtercommand",
},
+ ["availablewidth"]={
+ ["en"]="availablewidth",
+ ["nl"]="beschikbarebreedte",
+ },
+ ["availableheight"]={
+ ["en"]="availableheight",
+ ["nl"]="beschikbarehoogte",
+ },
["focus"]={
["cs"]="zaostreni",
["de"]="focus",
@@ -9123,6 +9163,18 @@ return {
["pe"]="Ø¢Ùست",
["ro"]="offset",
},
+ ["loffset"]={
+ ["en"]="loffset",
+ },
+ ["roffset"]={
+ ["en"]="roffset",
+ },
+ ["toffset"]={
+ ["en"]="toffset",
+ },
+ ["boffset"]={
+ ["en"]="boffset",
+ },
["openaction"]={
["cs"]="otevriakci",
["de"]="oeffenaktion",
@@ -9227,6 +9279,10 @@ return {
["pe"]="رنگ‌صÙحه",
["ro"]="culoarepagina",
},
+ ["pagecolormodel"]={
+ ["en"]="pagecolormodel",
+ ["nl"]="paginakleurmodel",
+ },
["pagecommand"]={
["cs"]="strankovyprikaz",
["de"]="seitenbefehl",
@@ -9459,6 +9515,16 @@ return {
["pe"]="شماره‌قبلی",
["ro"]="numarprecedent",
},
+ ["printable"]={
+ ["cs"]="tisknutelne",
+ ["de"]="druckbar",
+ ["en"]="printable",
+ ["fr"]="editable",
+ ["it"]="stampabile",
+ ["nl"]="printbaar", -- afdrukbaar
+ ["pe"]="قابل‌چاپ",
+ ["ro"]="tiparibil",
+ },
["process"]={
["cs"]="process",
["de"]="process",
@@ -9539,6 +9605,10 @@ return {
["pe"]="مراجعه",
["ro"]="referinta",
},
+ ["region"]={
+ ["en"]="region",
+ ["nl"]="gebied",
+ },
["regionin"]={
["cs"]="oblastuvnitr",
["de"]="regionin",
@@ -9799,6 +9869,10 @@ return {
["pe"]="خط",
["ro"]="rigla",
},
+ ["rulecommand"]={
+ ["en"]="rulecommand",
+ ["nl"]="lijncommando",
+ },
["rulecolor"]={
["cs"]="barvalinky",
["de"]="linienfarbe",
@@ -10277,6 +10351,10 @@ return {
["en"]="suffixseparator",
["nl"]="suffixscheider",
},
+ ["suffixstopper"]={
+ ["en"]="suffixstopper",
+ ["nl"]="suffixafsluiter",
+ },
["sx"]={
["cs"]="sx",
["de"]="sx",
@@ -10507,6 +10585,16 @@ return {
["pe"]="سبک‌متن",
["ro"]="stiltext",
},
+ ["textheight"]={
+ ["cs"]="vyskatextu",
+ ["de"]="texthoehe",
+ ["en"]="textheight",
+ ["fr"]="hauteurtexte",
+ ["it"]="altezzatesto",
+ ["nl"]="teksthoogte",
+ ["pe"]="ارتÙاع‌متن",
+ ["ro"]="inaltimetext",
+ },
["textwidth"]={
["cs"]="sirkatextu",
["de"]="textbreite",
@@ -10740,6 +10828,10 @@ return {
["pe"]="vcommand",
["ro"]="comandav",
},
+ ["vector"]={
+ ["en"]="vector",
+ ["nl"]="vector",
+ },
["veroffset"]={
["cs"]="offsethlavicky",
["de"]="kopfoffset",
@@ -10972,26 +11064,6 @@ return {
["pe"]="موضعی‌جاری",
["ro"]="localcurent",
},
- ["emptyone"]={
- ["cs"]="leer",
- ["de"]="vuoto",
- ["en"]="empty",
- ["fr"]="vide",
- ["it"]="prazdne",
- ["nl"]="leeg",
- ["pe"]="یک‌خالی",
- ["ro"]="gol",
- },
- ["emptytwo"]={
- ["cs"]="prazdne",
- ["de"]="leer",
- ["en"]="empty",
- ["fr"]="vide",
- ["it"]="vuoti",
- ["nl"]="lege",
- ["pe"]="دوخالی",
- ["ro"]="gol",
- },
["end"]={
["cs"]="konec",
["de"]="ende",
@@ -11262,6 +11334,12 @@ return {
["pe"]="میله‌ها‌رو",
["ro"]="supralinie",
},
+ ["understrike"]={
+ ["en"]="understrike",
+ },
+ ["understrikes"]={
+ ["en"]="understrikes",
+ },
["overstrike"]={
["cs"]="preskrtnuto",
["de"]="durchgestrichen",
@@ -11917,6 +11995,46 @@ return {
["pe"]="کلمه",
["ro"]="CUVANT",
},
+ ["WORDS"]={
+ ["cs"]="SLOVA",
+ ["de"]="WOERTER",
+ ["en"]="WORDS",
+ ["fr"]="MOTS",
+ ["it"]="PAROLE",
+ ["nl"]="WOORDEN",
+ ["pe"]="WORDS",
+ ["ro"]="CUVINTE",
+ },
+ ["word"]={
+ ["cs"]="slovo",
+ ["de"]="wort",
+ ["en"]="word",
+ ["fr"]="mot",
+ ["it"]="parola",
+ ["nl"]="woord",
+ ["pe"]="word",
+ ["ro"]="cuvant",
+ },
+ ["Word"]={
+ ["cs"]="Slovo",
+ ["de"]="Wort",
+ ["en"]="Word",
+ ["fr"]="Mot",
+ ["it"]="Parola",
+ ["nl"]="Woord",
+ ["pe"]="Word",
+ ["ro"]="Cuvant",
+ },
+ ["Words"]={
+ ["cs"]="Slova",
+ ["de"]="Woerter",
+ ["en"]="Words",
+ ["fr"]="Mots",
+ ["it"]="Parole",
+ ["nl"]="Woorden",
+ ["pe"]="Words",
+ ["ro"]="Cuvinte",
+ },
["abbreviation"]={
["cs"]="zkratka",
["de"]="abkuerzung",
@@ -12029,8 +12147,8 @@ return {
},
["april"]={
["cs"]="duben",
- ["de"]="April",
- ["en"]="April",
+ ["de"]="april",
+ ["en"]="april",
["fr"]="avril",
["it"]="aprile",
["nl"]="april",
@@ -12063,8 +12181,8 @@ return {
},
["august"]={
["cs"]="srpen",
- ["de"]="August",
- ["en"]="August",
+ ["de"]="august",
+ ["en"]="august",
["fr"]="août",
["it"]="agosto",
["nl"]="augustus",
@@ -12351,6 +12469,16 @@ return {
["pe"]="cap",
["ro"]="cap",
},
+ ["Cap"]={
+ ["cs"]="Kap",
+ ["de"]="Kap",
+ ["en"]="Cap",
+ ["fr"]="Cap",
+ ["it"]="Cap",
+ ["nl"]="Kap",
+ ["pe"]="Cap",
+ ["ro"]="Cap",
+ },
["capital"]={
["cs"]="kapitalky",
["de"]="versalien",
@@ -12361,6 +12489,16 @@ return {
["pe"]="capital",
["ro"]="majuscula",
},
+ ["Capital"]={
+ ["cs"]="Kapitalky",
+ ["de"]="Versalien",
+ ["en"]="Capital",
+ ["fr"]="Capitale",
+ ["it"]="Maiuscolo",
+ ["nl"]="Kapitaal",
+ ["pe"]="Capital",
+ ["ro"]="Majuscula",
+ },
["center"]={
["cs"]="center",
["de"]="center",
@@ -12577,8 +12715,8 @@ return {
},
["december"]={
["cs"]="prosinec",
- ["de"]="Dezember",
- ["en"]="December",
+ ["de"]="dezember",
+ ["en"]="december",
["fr"]="decembre",
["it"]="dicembre",
["nl"]="december",
@@ -12747,8 +12885,8 @@ return {
},
["february"]={
["cs"]="unor",
- ["de"]="Februar",
- ["en"]="February",
+ ["de"]="februar",
+ ["en"]="february",
["fr"]="fevrier",
["it"]="febbraio",
["nl"]="februari",
@@ -13145,6 +13283,10 @@ return {
["pe"]="نیم‌خط",
["ro"]="jumatatelinie",
},
+ ["quarterline"]={
+ ["en"]="quarterline",
+ ["nl"]="kwartregel",
+ },
["handwritten"]={
["cs"]="rukopisne",
["de"]="handschrift",
@@ -13527,8 +13669,8 @@ return {
},
["january"]={
["cs"]="leden",
- ["de"]="Januar",
- ["en"]="January",
+ ["de"]="januar",
+ ["en"]="january",
["fr"]="janvier",
["it"]="gennaio",
["nl"]="januari",
@@ -13547,8 +13689,8 @@ return {
},
["july"]={
["cs"]="cervenec",
- ["de"]="Juli",
- ["en"]="July",
+ ["de"]="juli",
+ ["en"]="july",
["fr"]="juillet",
["it"]="luglio",
["nl"]="juli",
@@ -13557,8 +13699,8 @@ return {
},
["june"]={
["cs"]="cerven",
- ["de"]="Juni",
- ["en"]="June",
+ ["de"]="juni",
+ ["en"]="june",
["fr"]="juin",
["it"]="giugno",
["nl"]="juni",
@@ -13887,8 +14029,8 @@ return {
},
["march"]={
["cs"]="brezen",
- ["de"]="Maerz",
- ["en"]="March",
+ ["de"]="maerz",
+ ["en"]="march",
["fr"]="mars",
["it"]="marzo",
["nl"]="maart",
@@ -13935,6 +14077,16 @@ return {
["pe"]="نشانه‌گذاری",
["ro"]="marcaje",
},
+ ["mathematics"]={
+ ["cs"]="mathematika",
+ ["de"]="mathematik",
+ ["en"]="mathematics",
+ ["fr"]="mathematique",
+ ["it"]="matematica",
+ ["nl"]="wiskunde",
+ ["pe"]="ریاضی",
+ ["ro"]="matematica",
+ },
["mathalignment"]={
["cs"]="mathalignment",
["de"]="mathalignment",
@@ -13977,8 +14129,8 @@ return {
},
["may"]={
["cs"]="kveten",
- ["de"]="Mai",
- ["en"]="May",
+ ["de"]="mai",
+ ["en"]="may",
["fr"]="mai",
["it"]="maggio",
["nl"]="mei",
@@ -14330,8 +14482,8 @@ return {
},
["november"]={
["cs"]="listopad",
- ["de"]="November",
- ["en"]="November",
+ ["de"]="november",
+ ["en"]="november",
["fr"]="novembre",
["it"]="novembre",
["nl"]="november",
@@ -14380,8 +14532,8 @@ return {
},
["october"]={
["cs"]="rijen",
- ["de"]="Oktober",
- ["en"]="October",
+ ["de"]="oktober",
+ ["en"]="october",
["fr"]="octobre",
["it"]="ottobre",
["nl"]="oktober",
@@ -14678,13 +14830,17 @@ return {
["pe"]="زیرصÙحه‌قبلی",
["ro"]="subpaginaanterioara",
},
+ ["print"]={
+ ["en"]="print",
+ ["nl"]="print", -- afdruk
+ },
["printable"]={
["cs"]="tisknutelne",
["de"]="druckbar",
["en"]="printable",
["fr"]="editable",
["it"]="stampabile",
- ["nl"]="printbaar",
+ ["nl"]="printbaar", -- afdrukbaar
["pe"]="قابل‌چاپ",
["ro"]="tiparibil",
},
@@ -15140,8 +15296,8 @@ return {
},
["september"]={
["cs"]="zari",
- ["de"]="September",
- ["en"]="September",
+ ["de"]="september",
+ ["en"]="september",
["fr"]="septembre",
["it"]="settembre",
["nl"]="september",
diff --git a/Master/texmf-dist/tex/context/base/mult-def.mkii b/Master/texmf-dist/tex/context/base/mult-def.mkii
index 0e1a7dee71f..a75ef993f55 100644
--- a/Master/texmf-dist/tex/context/base/mult-def.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mult-def.mkiv b/Master/texmf-dist/tex/context/base/mult-def.mkiv
index a273fa18a03..f6f50ae7252 100644
--- a/Master/texmf-dist/tex/context/base/mult-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/mult-def.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,17 +13,17 @@
\unprotect
-\setvalue{@interface@czech@}{cs}
-\setvalue{@interface@german@}{de}
-\setvalue{@interface@english@}{en}
-\setvalue{@interface@french@}{fr}
-\setvalue{@interface@italian@}{it}
-\setvalue{@interface@dutch@}{nl}
-\setvalue{@interface@persian@}{pe}
-\setvalue{@interface@romanian@}{ro}
+\setvalue{\??mi :czech}{cs}
+\setvalue{\??mi :german}{de}
+\setvalue{\??mi :english}{en}
+\setvalue{\??mi :french}{fr}
+\setvalue{\??mi :italian}{it}
+\setvalue{\??mi :dutch}{nl}
+\setvalue{\??mi :persian}{pe}
+\setvalue{\??mi:romanian}{ro}
-\def\userinterfacetag{\ifcsname @interface@\currentinterface @\endcsname\csname @interface@\currentinterface @\endcsname\else en\fi}
-\def\userresponsestag{\ifcsname @interface@\currentresponses @\endcsname\csname @interface@\currentresponses @\endcsname\else en\fi}
+\def\userinterfacetag{\ifcsname\??mi:\currentinterface\endcsname\csname\??mi:\currentinterface\endcsname\else en\fi}
+\def\userresponsestag{\ifcsname\??mi:\currentresponses\endcsname\csname\??mi:\currentresponses\endcsname\else en\fi}
% \input mult-\userinterfacetag \relax
% \input mult-m\userresponsestag \relax
diff --git a/Master/texmf-dist/tex/context/base/mult-dim.mkvi b/Master/texmf-dist/tex/context/base/mult-dim.mkvi
new file mode 100644
index 00000000000..0889b411e92
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mult-dim.mkvi
@@ -0,0 +1,126 @@
+%D \module
+%D [ file=core-gen,
+%D version=1995.10.10,
+%D title=\CONTEXT\ Core Macros,
+%D subtitle=General,
+%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 / General}
+
+\unprotect
+
+%D \macros
+%D {assigndimension,assignalfadimension}
+%D
+%D The following commands are used to process keyword based
+%D dimension setters.
+%D
+%D \starttyping
+%D \assigndimension
+%D {<value>|small|medium|big|-small|-medium|-big|none}
+%D {\dimension}
+%D {value small}
+%D {value medium}
+%D {value big}
+%D \stoptyping
+%D
+%D The given keyword determines the result.
+
+\installcorenamespace{dimensionnormal}
+
+\setvalue{\??dimensionnormal \v!none }#value#dimension#small#medium#big{#dimension\zeropoint}
+\setvalue{\??dimensionnormal \v!small }#value#dimension#small#medium#big{#dimension=#small\relax}
+\setvalue{\??dimensionnormal \v!medium}#value#dimension#small#medium#big{#dimension=#medium\relax}
+\setvalue{\??dimensionnormal \v!big }#value#dimension#small#medium#big{#dimension=#big\relax}
+\setvalue{\??dimensionnormal-\v!small }#value#dimension#small#medium#big{#dimension=-#small\relax}
+\setvalue{\??dimensionnormal-\v!medium}#value#dimension#small#medium#big{#dimension=-#medium\relax}
+\setvalue{\??dimensionnormal-\v!big }#value#dimension#small#medium#big{#dimension=-#big\relax}
+\setvalue{\??dimensionnormal\s!unknown}#value#dimension#small#medium#big{#dimension=#value\relax}
+
+\unexpanded\def\assigndimension#value%
+ {\csname\??dimensionnormal\ifcsname\??dimensionnormal#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+
+%D The next variant assigns to a macro instead of a dimension.
+%D
+%D \starttyping
+%D \assignalfadimension
+%D {<value>|small|medium|big|none}
+%D {\macro}
+%D {value small}
+%D {value medium}
+%D {value big}
+%D \stoptyping
+%D
+%D This one is used for factors.
+
+\installcorenamespace{dimensionalfa}
+
+\setvalue{\??dimensionalfa\v!none }#value#macro#small#medium#big{\let #macro\!!zerocount}
+\setvalue{\??dimensionalfa\v!small }#value#macro#small#medium#big{\edef#macro{#small}}
+\setvalue{\??dimensionalfa\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}}
+\setvalue{\??dimensionalfa\v!big }#value#macro#small#medium#big{\edef#macro{#big}}
+\setvalue{\??dimensionalfa\s!unknown}#value#macro#small#medium#big{\edef#macro{#value}}
+
+\unexpanded\def\assignalfadimension#value%
+ {\csname\??dimensionalfa\ifcsname\??dimensionalfa#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+
+%D \macros
+%D {assignvalue}
+%D
+%D A variant that does not assume dimenions ios the following:
+%D
+%D \starttyping
+%D \assignvalue
+%D {<value>|small|medium|big}
+%D {\macro}
+%D {value small}
+%D {value medium}
+%D {value big}
+%D \stoptyping
+
+\installcorenamespace{dimensionvalue}
+
+\setvalue{\??dimensionvalue\v!small }#value#macro#small#medium#big{\edef#macro{#small}}
+\setvalue{\??dimensionvalue\v!medium }#value#macro#small#medium#big{\edef#macro{#medium}}
+\setvalue{\??dimensionvalue\v!big }#value#macro#small#medium#big{\edef#macro{#big}}
+\setvalue{\??dimensionvalue\s!unknown}#value#macro#small#medium#big{\edef#macro{#value}}
+
+\unexpanded\def\assignvalue#value%
+ {\csname\??dimensionvalue\ifcsname\??dimensionvalue#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+
+%D \macros
+%D {assignwidth}
+%D
+%D Een breedte van een opgegeven tekst kan worden berekend en
+%D toegekend aan een \DIMENSION\ met:
+%D
+%D \starttyping
+%D \assignwidth
+%D {<value>|fit|broad}
+%D {\dimension}
+%D {text}
+%D {extra}
+%D \stoptyping
+
+\installcorenamespace{dimensionwidth}
+
+\newbox\b_assign_width
+
+\setvalue{\??dimensionwidth }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width
+ \setbox\b_assign_width\emptybox}
+\setvalue{\??dimensionwidth\v!fit }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\wd\b_assign_width
+ \setbox\b_assign_width\emptybox}
+\setvalue{\??dimensionwidth\v!broad }#value#dimension#content#extra{\setbox\b_assign_width\hbox{#content}#dimension\dimexpr\wd\b_assign_width+#extra\relax
+ \setbox\b_assign_width\emptybox}
+\setvalue{\??dimensionwidth\v!unknown}#value#dimension#content#extra{#dimension=#value\relax}
+
+\unexpanded\def\assignwidth#value%
+ {\csname\??dimensionwidth\ifcsname\??dimensionwidth#value\endcsname#value\else\s!unknown\fi\endcsname{#value}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mult-en.mkii b/Master/texmf-dist/tex/context/base/mult-en.mkii
index a40f341c63d..1aab52a2675 100644
--- a/Master/texmf-dist/tex/context/base/mult-en.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-en.mkii
@@ -4,6 +4,8 @@
%
\setinterfacevariable{Addition}{Addition}
\setinterfacevariable{Balloon}{Balloon}
+\setinterfacevariable{Cap}{Cap}
+\setinterfacevariable{Capital}{Capital}
\setinterfacevariable{Character}{Character}
\setinterfacevariable{Characters}{Characters}
\setinterfacevariable{CloseDocument}{CloseDocument}
@@ -61,6 +63,9 @@
\setinterfacevariable{ViewerHelp}{ViewerHelp}
\setinterfacevariable{WEEKDAY}{WEEKDAY}
\setinterfacevariable{WORD}{WORD}
+\setinterfacevariable{WORDS}{WORDS}
+\setinterfacevariable{Word}{Word}
+\setinterfacevariable{Words}{Words}
\setinterfacevariable{abbreviation}{abbreviation}
\setinterfacevariable{abbreviations}{abbreviations}
\setinterfacevariable{absolute}{absolute}
@@ -72,11 +77,11 @@
\setinterfacevariable{answerarea}{answerarea}
\setinterfacevariable{appendices}{appendices}
\setinterfacevariable{appendix}{appendix}
-\setinterfacevariable{april}{April}
+\setinterfacevariable{april}{april}
\setinterfacevariable{atmargin}{atmargin}
\setinterfacevariable{atpage}{atpage}
\setinterfacevariable{attachment}{attachment}
-\setinterfacevariable{august}{August}
+\setinterfacevariable{august}{august}
\setinterfacevariable{author}{author}
\setinterfacevariable{auto}{auto}
\setinterfacevariable{autointro}{autointro}
@@ -134,7 +139,7 @@
\setinterfacevariable{cutspace}{cutspace}
\setinterfacevariable{date}{date}
\setinterfacevariable{day}{day}
-\setinterfacevariable{december}{December}
+\setinterfacevariable{december}{december}
\setinterfacevariable{default}{default}
\setinterfacevariable{depth}{depth}
\setinterfacevariable{description}{description}
@@ -154,7 +159,7 @@
\setinterfacevariable{even}{even}
\setinterfacevariable{external}{external}
\setinterfacevariable{fact}{fact}
-\setinterfacevariable{february}{February}
+\setinterfacevariable{february}{february}
\setinterfacevariable{figure}{figure}
\setinterfacevariable{figures}{figures}
\setinterfacevariable{file}{file}
@@ -232,10 +237,10 @@
\setinterfacevariable{item}{item}
\setinterfacevariable{itemize}{itemize}
\setinterfacevariable{its}{its}
-\setinterfacevariable{january}{January}
+\setinterfacevariable{january}{january}
\setinterfacevariable{joinedup}{joinedup}
-\setinterfacevariable{july}{July}
-\setinterfacevariable{june}{June}
+\setinterfacevariable{july}{july}
+\setinterfacevariable{june}{june}
\setinterfacevariable{keep}{keep}
\setinterfacevariable{knockout}{knockout}
\setinterfacevariable{label}{label}
@@ -268,19 +273,20 @@
\setinterfacevariable{ls}{ls}
\setinterfacevariable{makeup}{makeup}
\setinterfacevariable{mar}{mar}
-\setinterfacevariable{march}{March}
+\setinterfacevariable{march}{march}
\setinterfacevariable{margin}{margin}
\setinterfacevariable{marginedge}{marginedge}
\setinterfacevariable{margintitle}{margintitle}
\setinterfacevariable{marking}{marking}
\setinterfacevariable{mathalignment}{mathalignment}
\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathematics}{mathematics}
\setinterfacevariable{mathmatrix}{mathmatrix}
\setinterfacevariable{max}{max}
\setinterfacevariable{maxdepth}{maxdepth}
\setinterfacevariable{maxheight}{maxheight}
\setinterfacevariable{maxwidth}{maxwidth}
-\setinterfacevariable{may}{May}
+\setinterfacevariable{may}{may}
\setinterfacevariable{mediaeval}{mediaeval}
\setinterfacevariable{medium}{medium}
\setinterfacevariable{middle}{middle}
@@ -317,12 +323,12 @@
\setinterfacevariable{note}{note}
\setinterfacevariable{nothanging}{nothanging}
\setinterfacevariable{nothyphenated}{nothyphenated}
-\setinterfacevariable{november}{November}
+\setinterfacevariable{november}{november}
\setinterfacevariable{nowhere}{nowhere}
\setinterfacevariable{nowhite}{nowhite}
\setinterfacevariable{number}{number}
\setinterfacevariable{numbers}{numbers}
-\setinterfacevariable{october}{October}
+\setinterfacevariable{october}{october}
\setinterfacevariable{odd}{odd}
\setinterfacevariable{off}{off}
\setinterfacevariable{offset}{offset}
@@ -356,6 +362,7 @@
\setinterfacevariable{previousoddpage}{previousoddpage}
\setinterfacevariable{previouspage}{previouspage}
\setinterfacevariable{previoussubpage}{previoussubpage}
+\setinterfacevariable{print}{print}
\setinterfacevariable{printable}{printable}
\setinterfacevariable{process}{process}
\setinterfacevariable{product}{product}
@@ -363,6 +370,7 @@
\setinterfacevariable{project}{project}
\setinterfacevariable{protected}{protected}
\setinterfacevariable{quadruple}{quadruple}
+\setinterfacevariable{quarterline}{quarterline}
\setinterfacevariable{quotation}{quotation}
\setinterfacevariable{quote}{quote}
\setinterfacevariable{ran}{ran}
@@ -402,7 +410,7 @@
\setinterfacevariable{sectionblockenvironment}{sectionblockenvironment}
\setinterfacevariable{sectionnumber}{sectionnumber}
\setinterfacevariable{see}{see}
-\setinterfacevariable{september}{September}
+\setinterfacevariable{september}{september}
\setinterfacevariable{serif}{serif}
\setinterfacevariable{serried}{serried}
\setinterfacevariable{setups}{setups}
@@ -497,6 +505,8 @@
\setinterfacevariable{unavailable}{unavailable}
\setinterfacevariable{underbar}{underbar}
\setinterfacevariable{underbars}{underbars}
+\setinterfacevariable{understrike}{understrike}
+\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unit}{unit}
\setinterfacevariable{units}{units}
\setinterfacevariable{unknown}{unknown}
@@ -516,6 +526,7 @@
\setinterfacevariable{white}{white}
\setinterfacevariable{wide}{wide}
\setinterfacevariable{width}{width}
+\setinterfacevariable{word}{word}
\setinterfacevariable{xml}{xml}
\setinterfacevariable{year}{year}
\setinterfacevariable{yes}{yes}
@@ -533,6 +544,7 @@
\setinterfaceconstant{alignsymbol}{alignsymbol}
\setinterfaceconstant{aligntitle}{aligntitle}
\setinterfaceconstant{alternative}{alternative}
+\setinterfaceconstant{anchor}{anchor}
\setinterfaceconstant{andtext}{andtext}
\setinterfaceconstant{apa}{apa}
\setinterfaceconstant{arrow}{arrow}
@@ -552,6 +564,8 @@
\setinterfaceconstant{autohang}{autohang}
\setinterfaceconstant{autostrut}{autostrut}
\setinterfaceconstant{autowidth}{autowidth}
+\setinterfaceconstant{availableheight}{availableheight}
+\setinterfaceconstant{availablewidth}{availablewidth}
\setinterfaceconstant{axis}{axis}
\setinterfaceconstant{background}{background}
\setinterfaceconstant{backgroundcolor}{backgroundcolor}
@@ -571,6 +585,7 @@
\setinterfaceconstant{blank}{blank}
\setinterfaceconstant{blockway}{blockway}
\setinterfaceconstant{bodyfont}{bodyfont}
+\setinterfaceconstant{boffset}{boffset}
\setinterfaceconstant{bookmark}{bookmark}
\setinterfaceconstant{bottom}{bottom}
\setinterfaceconstant{bottomafter}{bottomafter}
@@ -602,6 +617,8 @@
\setinterfaceconstant{commandafter}{commandafter}
\setinterfaceconstant{commandbefore}{commandbefore}
\setinterfaceconstant{commands}{commands}
+\setinterfaceconstant{commentoffset}{commentoffset}
+\setinterfaceconstant{compact}{compact}
\setinterfaceconstant{component}{component}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
@@ -615,6 +632,7 @@
\setinterfaceconstant{coupling}{coupling}
\setinterfaceconstant{couplingway}{couplingway}
\setinterfaceconstant{criterium}{criterium}
+\setinterfaceconstant{css}{css}
\setinterfaceconstant{current}{current}
\setinterfaceconstant{cutspace}{cutspace}
\setinterfaceconstant{dash}{dash}
@@ -643,11 +661,13 @@
\setinterfaceconstant{editoretallimit}{editoretallimit}
\setinterfaceconstant{editoretaltext}{editoretaltext}
\setinterfaceconstant{empty}{empty}
+\setinterfaceconstant{entities}{entities}
\setinterfaceconstant{entries}{entries}
\setinterfaceconstant{equalheight}{equalheight}
\setinterfaceconstant{equalwidth}{equalwidth}
\setinterfaceconstant{escape}{escape}
\setinterfaceconstant{evenmargin}{evenmargin}
+\setinterfaceconstant{exitoffset}{labeloffset}
\setinterfaceconstant{expansion}{expansion}
\setinterfaceconstant{export}{export}
\setinterfaceconstant{extras}{extras}
@@ -684,6 +704,7 @@
\setinterfaceconstant{global}{global}
\setinterfaceconstant{grid}{grid}
\setinterfaceconstant{hang}{hang}
+\setinterfaceconstant{hcompact}{hcompact}
\setinterfaceconstant{headalign}{headalign}
\setinterfaceconstant{headcolor}{headcolor}
\setinterfaceconstant{headcommand}{headcommand}
@@ -712,6 +733,7 @@
\setinterfaceconstant{inner}{inner}
\setinterfaceconstant{innermargin}{innermargin}
\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{insidesection}{insidesection}
\setinterfaceconstant{intent}{intent}
\setinterfaceconstant{interaction}{interaction}
\setinterfaceconstant{interlinespace}{interlinespace}
@@ -724,8 +746,10 @@
\setinterfaceconstant{keys}{keys}
\setinterfaceconstant{keyword}{keyword}
\setinterfaceconstant{label}{label}
+\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{left}
\setinterfaceconstant{leftcolor}{leftcolor}
\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
@@ -754,6 +778,7 @@
\setinterfaceconstant{listtext}{listtext}
\setinterfaceconstant{local}{local}
\setinterfaceconstant{location}{location}
+\setinterfaceconstant{loffset}{loffset}
\setinterfaceconstant{logo}{logo}
\setinterfaceconstant{logos}{logos}
\setinterfaceconstant{marcolor}{marcolor}
@@ -830,6 +855,7 @@
\setinterfaceconstant{page}{page}
\setinterfaceconstant{pageboundaries}{pageboundaries}
\setinterfaceconstant{pagecolor}{pagecolor}
+\setinterfaceconstant{pagecolormodel}{pagecolormodel}
\setinterfaceconstant{pagecommand}{pagecommand}
\setinterfaceconstant{pageconversion}{pageconversion}
\setinterfaceconstant{pageconversionset}{pageconversionset}
@@ -870,6 +896,7 @@
\setinterfaceconstant{preview}{preview}
\setinterfaceconstant{previous}{previous}
\setinterfaceconstant{previousnumber}{previousnumber}
+\setinterfaceconstant{printable}{printable}
\setinterfaceconstant{process}{process}
\setinterfaceconstant{profile}{profile}
\setinterfaceconstant{pubsep}{pubsep}
@@ -882,6 +909,7 @@
\setinterfaceconstant{reference}{reference}
\setinterfaceconstant{referenceprefix}{referenceprefix}
\setinterfaceconstant{referencing}{referencing}
+\setinterfaceconstant{region}{region}
\setinterfaceconstant{regionin}{regionin}
\setinterfaceconstant{regionout}{regionout}
\setinterfaceconstant{repeat}{repeat}
@@ -906,9 +934,11 @@
\setinterfaceconstant{rightsubsentence}{rightsubsentence}
\setinterfaceconstant{righttext}{righttext}
\setinterfaceconstant{rightwidth}{rightwidth}
+\setinterfaceconstant{roffset}{roffset}
\setinterfaceconstant{rotation}{rotation}
\setinterfaceconstant{rule}{rule}
\setinterfaceconstant{rulecolor}{rulecolor}
+\setinterfaceconstant{rulecommand}{rulecommand}
\setinterfaceconstant{rulethickness}{rulethickness}
\setinterfaceconstant{samepage}{samepage}
\setinterfaceconstant{sample}{sample}
@@ -966,6 +996,7 @@
\setinterfaceconstant{subtitle}{subtitle}
\setinterfaceconstant{suffix}{suffix}
\setinterfaceconstant{suffixseparator}{suffixseparator}
+\setinterfaceconstant{suffixstopper}{suffixstopper}
\setinterfaceconstant{surnamesep}{surnamesep}
\setinterfaceconstant{sx}{sx}
\setinterfaceconstant{sy}{sy}
@@ -983,6 +1014,7 @@
\setinterfaceconstant{textcolor}{textcolor}
\setinterfaceconstant{textcommand}{textcommand}
\setinterfaceconstant{textdistance}{textdistance}
+\setinterfaceconstant{textheight}{textheight}
\setinterfaceconstant{textlayer}{textlayer}
\setinterfaceconstant{textmargin}{textmargin}
\setinterfaceconstant{textmethod}{textmethod}
@@ -1000,6 +1032,7 @@
\setinterfaceconstant{titleright}{titleright}
\setinterfaceconstant{titlestyle}{titlestyle}
\setinterfaceconstant{to}{to}
+\setinterfaceconstant{toffset}{toffset}
\setinterfaceconstant{tolerance}{tolerance}
\setinterfaceconstant{top}{top}
\setinterfaceconstant{topdistance}{topdistance}
@@ -1016,6 +1049,8 @@
\setinterfaceconstant{validate}{validate}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vcommand}
+\setinterfaceconstant{vcompact}{vcompact}
+\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{veroffset}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{voffset}{voffset}
@@ -1025,6 +1060,7 @@
\setinterfaceconstant{white}{white}
\setinterfaceconstant{width}{width}
\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xhtml}{xhtml}
\setinterfaceconstant{xmax}{xmax}
\setinterfaceconstant{xoffset}{xoffset}
\setinterfaceconstant{xscale}{xscale}
@@ -1042,8 +1078,6 @@
\setinterfaceelement{complete}{complete}
\setinterfaceelement{coupled}{coupled}
\setinterfaceelement{currentlocal}{currentlocal}
-\setinterfaceelement{emptyone}{empty}
-\setinterfaceelement{emptytwo}{empty}
\setinterfaceelement{end}{end}
\setinterfaceelement{endsetup}{}
\setinterfaceelement{get}{get}
@@ -1156,7 +1190,7 @@
\setinterfacecommand{defineframedtext}{defineframedtext}
\setinterfacecommand{definehbox}{definehbox}
\setinterfacecommand{definehead}{definehead}
-\setinterfacecommand{defineindenting}{defineindenting}
+\setinterfacecommand{defineindentedtext}{defineindentedtext}
\setinterfacecommand{defineinmargin}{defineinmargin}
\setinterfacecommand{defineinteractionmenu}{defineinteractionmenu}
\setinterfacecommand{defineitemgroup}{defineitemgroup}
@@ -1352,7 +1386,6 @@
\setinterfacecommand{pagenumber}{pagenumber}
\setinterfacecommand{pageoffset}{pageoffset}
\setinterfacecommand{pagereference}{pagereference}
-\setinterfacecommand{pagetype}{pagetype}
\setinterfacecommand{paperheight}{paperheight}
\setinterfacecommand{paperwidth}{paperwidth}
\setinterfacecommand{periods}{periods}
@@ -1468,7 +1501,7 @@
\setinterfacecommand{setupheads}{setupheads}
\setinterfacecommand{setupheadtext}{setupheadtext}
\setinterfacecommand{setuphyphenmark}{setuphyphenmark}
-\setinterfacecommand{setupindentations}{setupindentations}
+\setinterfacecommand{setupindentedtext}{setupindentedtext}
\setinterfacecommand{setupindenting}{setupindenting}
\setinterfacecommand{setupinmargin}{setupinmargin}
\setinterfacecommand{setupinteraction}{setupinteraction}
diff --git a/Master/texmf-dist/tex/context/base/mult-fr.mkii b/Master/texmf-dist/tex/context/base/mult-fr.mkii
index 875d92bbcef..fd36c4f8b30 100644
--- a/Master/texmf-dist/tex/context/base/mult-fr.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-fr.mkii
@@ -4,6 +4,8 @@
%
\setinterfacevariable{Addition}{Ajout}
\setinterfacevariable{Balloon}{Ballon}
+\setinterfacevariable{Cap}{Cap}
+\setinterfacevariable{Capital}{Capitale}
\setinterfacevariable{Character}{Caratere}
\setinterfacevariable{Characters}{Caracteres}
\setinterfacevariable{CloseDocument}{FermeDocument}
@@ -61,6 +63,9 @@
\setinterfacevariable{ViewerHelp}{AideVisualisateur}
\setinterfacevariable{WEEKDAY}{JOURSEMAINE}
\setinterfacevariable{WORD}{MOT}
+\setinterfacevariable{WORDS}{MOTS}
+\setinterfacevariable{Word}{Mot}
+\setinterfacevariable{Words}{Mots}
\setinterfacevariable{abbreviation}{abreviation}
\setinterfacevariable{abbreviations}{abreviations}
\setinterfacevariable{absolute}{absolute}
@@ -275,6 +280,7 @@
\setinterfacevariable{marking}{marquage}
\setinterfacevariable{mathalignment}{mathalignment}
\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathematics}{mathematique}
\setinterfacevariable{mathmatrix}{mathmatrix}
\setinterfacevariable{max}{max}
\setinterfacevariable{maxdepth}{maxdepth}
@@ -356,6 +362,7 @@
\setinterfacevariable{previousoddpage}{pageimpaireprecedente}
\setinterfacevariable{previouspage}{pageprecedente}
\setinterfacevariable{previoussubpage}{souspageprecedente}
+\setinterfacevariable{print}{print}
\setinterfacevariable{printable}{editable}
\setinterfacevariable{process}{process}
\setinterfacevariable{product}{produit}
@@ -363,6 +370,7 @@
\setinterfacevariable{project}{projet}
\setinterfacevariable{protected}{protege}
\setinterfacevariable{quadruple}{quadruple}
+\setinterfacevariable{quarterline}{quarterline}
\setinterfacevariable{quotation}{citation}
\setinterfacevariable{quote}{citer}
\setinterfacevariable{ran}{cours}
@@ -497,6 +505,8 @@
\setinterfacevariable{unavailable}{indisponible}
\setinterfacevariable{underbar}{souslignetout}
\setinterfacevariable{underbars}{sousligne}
+\setinterfacevariable{understrike}{understrike}
+\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unit}{unite}
\setinterfacevariable{units}{unites}
\setinterfacevariable{unknown}{inconnu}
@@ -516,6 +526,7 @@
\setinterfacevariable{white}{blanc}
\setinterfacevariable{wide}{ample}
\setinterfacevariable{width}{largeur}
+\setinterfacevariable{word}{mot}
\setinterfacevariable{xml}{xml}
\setinterfacevariable{year}{annee}
\setinterfacevariable{yes}{oui}
@@ -533,6 +544,7 @@
\setinterfaceconstant{alignsymbol}{alignsymbol}
\setinterfaceconstant{aligntitle}{alignementtitre}
\setinterfaceconstant{alternative}{alternative}
+\setinterfaceconstant{anchor}{anchor}
\setinterfaceconstant{andtext}{andtext}
\setinterfaceconstant{apa}{apa}
\setinterfaceconstant{arrow}{fleche}
@@ -552,6 +564,8 @@
\setinterfaceconstant{autohang}{autohang}
\setinterfaceconstant{autostrut}{autostrut}
\setinterfaceconstant{autowidth}{autolargeur}
+\setinterfaceconstant{availableheight}{availableheight}
+\setinterfaceconstant{availablewidth}{availablewidth}
\setinterfaceconstant{axis}{axe}
\setinterfaceconstant{background}{arriereplan}
\setinterfaceconstant{backgroundcolor}{couleurarriereplan}
@@ -571,6 +585,7 @@
\setinterfaceconstant{blank}{vide}
\setinterfaceconstant{blockway}{blockway}
\setinterfaceconstant{bodyfont}{policecorps}
+\setinterfaceconstant{boffset}{boffset}
\setinterfaceconstant{bookmark}{marquepage}
\setinterfaceconstant{bottom}{inf}
\setinterfaceconstant{bottomafter}{bottomafter}
@@ -602,6 +617,8 @@
\setinterfaceconstant{commandafter}{commandeapres}
\setinterfaceconstant{commandbefore}{commandeavant}
\setinterfaceconstant{commands}{commandes}
+\setinterfaceconstant{commentoffset}{commentoffset}
+\setinterfaceconstant{compact}{compact}
\setinterfaceconstant{component}{composant}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
@@ -615,6 +632,7 @@
\setinterfaceconstant{coupling}{couplage}
\setinterfaceconstant{couplingway}{modecouplage}
\setinterfaceconstant{criterium}{critere}
+\setinterfaceconstant{css}{css}
\setinterfaceconstant{current}{courant}
\setinterfaceconstant{cutspace}{cutspace}
\setinterfaceconstant{dash}{pointille}
@@ -643,11 +661,13 @@
\setinterfaceconstant{editoretallimit}{editoretallimit}
\setinterfaceconstant{editoretaltext}{editoretaltext}
\setinterfaceconstant{empty}{vide}
+\setinterfaceconstant{entities}{entities}
\setinterfaceconstant{entries}{entries}
\setinterfaceconstant{equalheight}{equalheight}
\setinterfaceconstant{equalwidth}{equalwidth}
\setinterfaceconstant{escape}{escape}
\setinterfaceconstant{evenmargin}{margepaire}
+\setinterfaceconstant{exitoffset}{labeloffset}
\setinterfaceconstant{expansion}{expansion}
\setinterfaceconstant{export}{export}
\setinterfaceconstant{extras}{extras}
@@ -684,6 +704,7 @@
\setinterfaceconstant{global}{global}
\setinterfaceconstant{grid}{grille}
\setinterfaceconstant{hang}{suspend}
+\setinterfaceconstant{hcompact}{hcompact}
\setinterfaceconstant{headalign}{headalign}
\setinterfaceconstant{headcolor}{couleurtete}
\setinterfaceconstant{headcommand}{commandetete}
@@ -712,6 +733,7 @@
\setinterfaceconstant{inner}{interieur}
\setinterfaceconstant{innermargin}{margeinterieure}
\setinterfaceconstant{inputfile}{fichierentree}
+\setinterfaceconstant{insidesection}{insidesection}
\setinterfaceconstant{intent}{intent}
\setinterfaceconstant{interaction}{interaction}
\setinterfaceconstant{interlinespace}{espaceinterligne}
@@ -724,8 +746,10 @@
\setinterfaceconstant{keys}{keys}
\setinterfaceconstant{keyword}{motcle}
\setinterfaceconstant{label}{etiquette}
+\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{gauche}
\setinterfaceconstant{leftcolor}{couleurgauche}
\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
@@ -754,6 +778,7 @@
\setinterfaceconstant{listtext}{texteliste}
\setinterfaceconstant{local}{local}
\setinterfaceconstant{location}{emplacement}
+\setinterfaceconstant{loffset}{loffset}
\setinterfaceconstant{logo}{logo}
\setinterfaceconstant{logos}{logos}
\setinterfaceconstant{marcolor}{couleurmarquage}
@@ -830,6 +855,7 @@
\setinterfaceconstant{page}{page}
\setinterfaceconstant{pageboundaries}{limitespage}
\setinterfaceconstant{pagecolor}{couleurpage}
+\setinterfaceconstant{pagecolormodel}{pagecolormodel}
\setinterfaceconstant{pagecommand}{commandepage}
\setinterfaceconstant{pageconversion}{pageconversion}
\setinterfaceconstant{pageconversionset}{pageconversionset}
@@ -870,6 +896,7 @@
\setinterfaceconstant{preview}{previsualisation}
\setinterfaceconstant{previous}{precedent}
\setinterfaceconstant{previousnumber}{numeroprecedent}
+\setinterfaceconstant{printable}{editable}
\setinterfaceconstant{process}{process}
\setinterfaceconstant{profile}{profile}
\setinterfaceconstant{pubsep}{pubsep}
@@ -882,6 +909,7 @@
\setinterfaceconstant{reference}{reference}
\setinterfaceconstant{referenceprefix}{referenceprefix}
\setinterfaceconstant{referencing}{referencing}
+\setinterfaceconstant{region}{region}
\setinterfaceconstant{regionin}{entreregion}
\setinterfaceconstant{regionout}{regionexterieure}
\setinterfaceconstant{repeat}{repete}
@@ -906,9 +934,11 @@
\setinterfaceconstant{rightsubsentence}{sousphrasedroite}
\setinterfaceconstant{righttext}{textedroit}
\setinterfaceconstant{rightwidth}{largeurdroite}
+\setinterfaceconstant{roffset}{roffset}
\setinterfaceconstant{rotation}{rotation}
\setinterfaceconstant{rule}{ligne}
\setinterfaceconstant{rulecolor}{couleurligne}
+\setinterfaceconstant{rulecommand}{rulecommand}
\setinterfaceconstant{rulethickness}{epaisseurligne}
\setinterfaceconstant{samepage}{memepage}
\setinterfaceconstant{sample}{echantillon}
@@ -966,6 +996,7 @@
\setinterfaceconstant{subtitle}{soustitre}
\setinterfaceconstant{suffix}{suffix}
\setinterfaceconstant{suffixseparator}{suffixseparator}
+\setinterfaceconstant{suffixstopper}{suffixstopper}
\setinterfaceconstant{surnamesep}{surnamesep}
\setinterfaceconstant{sx}{sx}
\setinterfaceconstant{sy}{sy}
@@ -983,6 +1014,7 @@
\setinterfaceconstant{textcolor}{couleurtexte}
\setinterfaceconstant{textcommand}{commandetexte}
\setinterfaceconstant{textdistance}{distancetexte}
+\setinterfaceconstant{textheight}{hauteurtexte}
\setinterfaceconstant{textlayer}{calquetexte}
\setinterfaceconstant{textmargin}{margetexte}
\setinterfaceconstant{textmethod}{textmethod}
@@ -1000,6 +1032,7 @@
\setinterfaceconstant{titleright}{titleright}
\setinterfaceconstant{titlestyle}{styletitre}
\setinterfaceconstant{to}{vers}
+\setinterfaceconstant{toffset}{toffset}
\setinterfaceconstant{tolerance}{tolerance}
\setinterfaceconstant{top}{sup}
\setinterfaceconstant{topdistance}{distancesup}
@@ -1016,6 +1049,8 @@
\setinterfaceconstant{validate}{valider}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vcommande}
+\setinterfaceconstant{vcompact}{vcompact}
+\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{veroffset}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{voffset}{voffset}
@@ -1025,6 +1060,7 @@
\setinterfaceconstant{white}{blanc}
\setinterfaceconstant{width}{largeur}
\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xhtml}{xhtml}
\setinterfaceconstant{xmax}{xmax}
\setinterfaceconstant{xoffset}{xoffset}
\setinterfaceconstant{xscale}{xscale}
@@ -1042,8 +1078,6 @@
\setinterfaceelement{complete}{complete}
\setinterfaceelement{coupled}{couple}
\setinterfaceelement{currentlocal}{localcourant}
-\setinterfaceelement{emptyone}{vide}
-\setinterfaceelement{emptytwo}{vide}
\setinterfaceelement{end}{fin}
\setinterfaceelement{endsetup}{}
\setinterfaceelement{get}{obtient}
@@ -1156,7 +1190,7 @@
\setinterfacecommand{defineframedtext}{defineframedtext}
\setinterfacecommand{definehbox}{definithbox}
\setinterfacecommand{definehead}{definittete}
-\setinterfacecommand{defineindenting}{definitcompoalinea}
+\setinterfacecommand{defineindentedtext}{defineindentedtext}
\setinterfacecommand{defineinmargin}{definitdansmarge}
\setinterfacecommand{defineinteractionmenu}{definitmenuinteraction}
\setinterfacecommand{defineitemgroup}{defineitemgroup}
@@ -1352,7 +1386,6 @@
\setinterfacecommand{pagenumber}{numeropage}
\setinterfacecommand{pageoffset}{pageoffset}
\setinterfacecommand{pagereference}{referencepage}
-\setinterfacecommand{pagetype}{tapepage}
\setinterfacecommand{paperheight}{hauteurpapier}
\setinterfacecommand{paperwidth}{largeurpapier}
\setinterfacecommand{periods}{periodes}
@@ -1468,7 +1501,7 @@
\setinterfacecommand{setupheads}{regletetes}
\setinterfacecommand{setupheadtext}{regletextetete}
\setinterfacecommand{setuphyphenmark}{reglemarquagehyphenation}
-\setinterfacecommand{setupindentations}{reglealineas}
+\setinterfacecommand{setupindentedtext}{setupindentedtext}
\setinterfacecommand{setupindenting}{reglecomposeenalinea}
\setinterfacecommand{setupinmargin}{regledansmarge}
\setinterfacecommand{setupinteraction}{regleinteraction}
diff --git a/Master/texmf-dist/tex/context/base/mult-fst.mkii b/Master/texmf-dist/tex/context/base/mult-fst.mkii
index e655e3d26d0..36c3f181f22 100644
--- a/Master/texmf-dist/tex/context/base/mult-fst.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-fst.mkii
@@ -5,7 +5,7 @@
%D subtitle=Speed Up,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mult-fst.mkiv b/Master/texmf-dist/tex/context/base/mult-fst.mkiv
deleted file mode 100644
index 11558b557c6..00000000000
--- a/Master/texmf-dist/tex/context/base/mult-fst.mkiv
+++ /dev/null
@@ -1,41 +0,0 @@
-%D \module
-%D [ file=mult-fst,
-%D version=2006.08.16,
-%D title=\CONTEXT\ Multilingual Macros,
-%D subtitle=Speed Up,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-% And so, after a few years of keeping this potentially dangerous
-% speedup in cont-exp, we now move it to the kernel: the next
-% patch is 30\% faster on main interface (seconds) (9->7 sec on
-% 1 million calls). Another speed up is still under testing.
-
-\unprotect
-
-\startinterface english
-
- \def\dosetvalue #1#2{\@EA\def \csname#1#2\endcsname}
- \def\dosetevalue #1#2{\@EA\edef\csname#1#2\endcsname}
- \def\dosetgvalue #1#2{\@EA\gdef\csname#1#2\endcsname}
- \def\dosetxvalue #1#2{\@EA\gdef\csname#1#2\endcsname}
- \def\docopyvalue#1#2#3{\@EA\def \csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}}
-
- \def\setinterfaceconstant#1#2%
- {\ctxlua{interfaces.setconstant("#1","#2")}%
- \setvalue{\c!prefix!#1}{#1}}
-
- \def\setinterfacevariable#1#2%
- {\ctxlua{interfaces.setvariable("#1","#2")}%
- \setvalue{\v!prefix!#1}{#2}}
-
- \def\interfaced#1{#1}
-
-\stopinterface
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mult-ini.lua b/Master/texmf-dist/tex/context/base/mult-ini.lua
index 4156e813d38..d14f38ad5f6 100644
--- a/Master/texmf-dist/tex/context/base/mult-ini.lua
+++ b/Master/texmf-dist/tex/context/base/mult-ini.lua
@@ -12,23 +12,25 @@ local serialize = table.serialize
local allocate = utilities.storage.allocate
local mark = utilities.storage.mark
-local texsprint = tex.sprint
+local contextsprint = context.sprint
local setmetatableindex = table.setmetatableindex
local report_interface = logs.reporter("interface","initialization")
-interfaces = interfaces or { }
-interfaces.constants = mark(interfaces.constants or { })
-interfaces.variables = mark(interfaces.variables or { })
-interfaces.elements = mark(interfaces.elements or { })
-interfaces.formats = mark(interfaces.formats or { })
-interfaces.translations = mark(interfaces.translations or { })
-
-storage.register("interfaces/constants", interfaces.constants, "interfaces.constants")
-storage.register("interfaces/variables", interfaces.variables, "interfaces.variables")
-storage.register("interfaces/elements", interfaces.elements, "interfaces.elements")
-storage.register("interfaces/formats", interfaces.formats, "interfaces.formats")
-storage.register("interfaces/translations", interfaces.translations, "interfaces.translations")
+interfaces = interfaces or { }
+interfaces.constants = mark(interfaces.constants or { })
+interfaces.variables = mark(interfaces.variables or { })
+interfaces.elements = mark(interfaces.elements or { })
+interfaces.formats = mark(interfaces.formats or { })
+interfaces.translations = mark(interfaces.translations or { })
+interfaces.corenamespaces = mark(interfaces.corenamespaces or { })
+
+storage.register("interfaces/constants", interfaces.constants, "interfaces.constants")
+storage.register("interfaces/variables", interfaces.variables, "interfaces.variables")
+storage.register("interfaces/elements", interfaces.elements, "interfaces.elements")
+storage.register("interfaces/formats", interfaces.formats, "interfaces.formats")
+storage.register("interfaces/translations", interfaces.translations, "interfaces.translations")
+storage.register("interfaces/corenamespaces", interfaces.corenamespaces, "interfaces.corenamespaces")
interfaces.interfaces = {
"cs", "de", "en", "fr", "it", "nl", "ro", "pe",
@@ -54,12 +56,13 @@ end
setmetatableindex(complete, resolve)
-local constants = interfaces.constants
-local variables = interfaces.variables
-local elements = interfaces.elements
-local formats = interfaces.formats
-local translations = interfaces.translations
-local reporters = { } -- just an optimization
+local constants = interfaces.constants
+local variables = interfaces.variables
+local elements = interfaces.elements
+local formats = interfaces.formats
+local translations = interfaces.translations
+local corenamespaces = interfaces.corenamespaces
+local reporters = { } -- just an optimization
local function valueiskey(t,k) -- will be helper
t[k] = k
@@ -72,6 +75,10 @@ setmetatableindex(elements, valueiskey)
setmetatableindex(formats, valueiskey)
setmetatableindex(translations, valueiskey)
+function commands.registernamespace(n,namespace)
+ corenamespaces[n] = namespace
+end
+
local function resolve(t,k)
local v = logs.reporter(k)
t[k] = v
@@ -147,8 +154,11 @@ local splitter = lpeg.splitat(",")
function interfaces.showmessage(category,tag,arguments)
local r = reporters[category]
local f = formats[fulltag(category,tag)]
- if type(arguments) == "string" and #arguments > 0 then
+ local t = type(arguments)
+ if t == "string" and #arguments > 0 then
r(f,lpegmatch(splitter,arguments))
+ elseif t == "table" then
+ r(f,unpack(arguments))
elseif arguments then
r(f,arguments)
else
@@ -176,9 +186,9 @@ logs.setmessenger(context.verbatim.ctxreport)
-- status
-function commands.writestatus(category,message)
+function commands.writestatus(category,message,...)
local r = reporters[category]
- r(message)
+ r(message,...)
end
-- initialization
@@ -191,28 +201,28 @@ function interfaces.setuserinterface(interface,response)
for given, constant in next, complete.constants do
constant = constant[interface] or constant.en or given
constants[constant] = given -- breedte -> width
- texsprint("\\do@sicon{",given,"}{",constant,"}")
+ contextsprint("\\do@sicon{",given,"}{",constant,"}")
nofconstants = nofconstants + 1
end
local nofvariables = 0
for given, variable in next, complete.variables do
variable = variable[interface] or variable.en or given
variables[given] = variable -- ja -> yes
- texsprint("\\do@sivar{",given,"}{",variable,"}")
+ contextsprint("\\do@sivar{",given,"}{",variable,"}")
nofvariables = nofvariables + 1
end
local nofelements = 0
for given, element in next, complete.elements do
element = element[interface] or element.en or given
elements[element] = given
- texsprint("\\do@siele{",given,"}{",element,"}")
+ contextsprint("\\do@siele{",given,"}{",element,"}")
nofelements = nofelements + 1
end
local nofcommands = 0
for given, command in next, complete.commands do
command = command[interface] or command.en or given
if command ~= given then
- texsprint("\\do@sicom{",given,"}{",command,"}")
+ contextsprint("\\do@sicom{",given,"}{",command,"}")
end
nofcommands = nofcommands + 1
end
@@ -226,7 +236,7 @@ function interfaces.setuserinterface(interface,response)
translations[given] = translation[interface] or translation.en or given
noftranslations = noftranslations + 1
end
- report_interface("definitions: %s constants, %s variables, %s elements, %s commands, % formats, %s translations",
+ report_interface("definitions: %s constants, %s variables, %s elements, %s commands, %s formats, %s translations",
nofconstants,nofvariables,nofelements,nofcommands,nofformats,noftranslations)
end
end
diff --git a/Master/texmf-dist/tex/context/base/mult-ini.mkii b/Master/texmf-dist/tex/context/base/mult-ini.mkii
index c2bb40861e1..76f6d69f2b8 100644
--- a/Master/texmf-dist/tex/context/base/mult-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mult-ini.mkiv b/Master/texmf-dist/tex/context/base/mult-ini.mkiv
index afddf692e94..f0d47103dc4 100644
--- a/Master/texmf-dist/tex/context/base/mult-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/mult-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -40,13 +40,10 @@
%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{\k!prefix!} \NC k! \NC constant (indirect) \NC\MR
-%D \NC \type{\l!prefix!} \NC l! \NC language \NC\MR
-%D \NC \type{\m!prefix!} \NC m! \NC age \NC\MR
-%D \NC \type{\p!prefix!} \NC p! \NC procedure \NC\MR
-%D \NC \type{\r!prefix!} \NC r! \NC reference \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
@@ -54,12 +51,16 @@
%D \stoplinecorrection
%D
%D In the single||lingual version we used \type{!}, \type{!!},
-%D \type{!!!} and \type{!!!!}.
+%D \type{!!!} and \type{!!!!}. In the meantime some of these
+%D are obsolete (we had some 12 originally).
-\def\c!prefix!{c!} \def\e!prefix!{e!} \def\f!prefix!{f!}
-\def\k!prefix!{k!} \def\l!prefix!{l!} \def\m!prefix!{m!}
-\def\p!prefix!{p!} \def\r!prefix!{r!} \def\s!prefix!{s!}
-\def\v!prefix!{v!} \def\t!prefix!{t!}
+\def\c!prefix!{c!}
+\def\k!prefix!{k!}
+\def\e!prefix!{e!}
+\def\f!prefix!{f!} % for the moment we keep this one
+\def\m!prefix!{m!}
+\def\s!prefix!{s!}
+\def\v!prefix!{v!}
%D \macros
%D [constants,variables,commands]
@@ -123,7 +124,7 @@
\edef\!!TLT{\detokenize{TLT}}
\edef\!!TRT{\detokenize{TRT}}
-
+
%D \macros
%D {defineinterfaceconstant,
%D defineinterfacevariable,
@@ -131,7 +132,6 @@
%D definesystemvariable,
%D definesystemconstant,
%D definemessageconstant,
-%D definereferenceconstant,
%D definefileconstant}
%D
%D The first part of this module is dedicated to dealing with
@@ -162,23 +162,17 @@
%D \def\e!name{meaning}
%D \stoptyping
-\unexpanded\def\defineinterfaceconstant #1#2{\setvalue{\c!prefix!#1}{#2}}
-\unexpanded\def\defineinterfacevariable #1#2{\setvalue{\v!prefix!#1}{#2}}
-\unexpanded\def\defineinterfaceelement #1#2{\setvalue{\e!prefix!#1}{#2}}
+\unexpanded\def\defineinterfaceconstant #1#2{\expandafter\def\csname\c!prefix!#1\endcsname{#2}}
+\unexpanded\def\defineinterfacevariable #1#2{\expandafter\def\csname\v!prefix!#1\endcsname{#2}}
+\unexpanded\def\defineinterfaceelement #1#2{\expandafter\def\csname\e!prefix!#1\endcsname{#2}}
%D Next come some interface independant constants:
%D
%D \starttyping
-%D \definereferenceconstant {name} {meaning}
%D \definefileconstant {name} {meaning}
%D \stoptyping
-\unexpanded\def\definereferenceconstant #1#2{\setvalue{\r!prefix!#1}{#2}}
-\unexpanded\def\definefileconstant #1#2{\setvalue{\f!prefix!#1}{#2}}
-
-%D A new one:
-
-\unexpanded\def\definetypescriptconstant#1#2{\setvalue{\t!prefix!#1}{#2}}
+\unexpanded\def\definefileconstant #1#2{\expandafter\def\csname\f!prefix!#1\endcsname{#2}}
%D And finaly we have the one argument, space saving constants
%D
@@ -187,8 +181,8 @@
%D \definemessageconstant {name}
%D \stoptyping
-\unexpanded\def\definesystemconstant #1{\setvalue{\s!prefix!#1}{#1}}
-\unexpanded\def\definemessageconstant #1{\setvalue{\m!prefix!#1}{#1}}
+\unexpanded\def\definesystemconstant #1{\expandafter\def\csname\s!prefix!#1\endcsname{#1}}
+\unexpanded\def\definemessageconstant #1{\expandafter\def\csname\m!prefix!#1\endcsname{#1}}
%D In a parameter driven system, some parameters are shared
%D by more system components. In \CONTEXT\ we can distinguish
@@ -199,7 +193,7 @@
%D \definesystemvariable {name}
%D \stoptyping
-\unexpanded\def\definesystemvariable#1{\setevalue{\??prefix#1}{\@@prefix#1}}
+\unexpanded\def\definesystemvariable#1{\expandafter\edef\csname\??prefix#1\endcsname{\@@prefix#1}}
\definesystemvariable{ms}
@@ -218,39 +212,39 @@
%D not ask for interface specifications when these are already
%D defined (like in cont-nl.tex and alike).
-\ifx\defaultinterface\undefined
+\ifdefined\defaultinterface
+
+ \def\selectinterface
+ {\writestatus{interface}{defining \currentinterface\space interface}%
+ \writeline
+ \writestatus{interface}{using \currentresponses\space messages}%
+ \writeline
+ \let\selectinterface\relax}
+
+\else
\def\defaultinterface{english}
\def\selectinterface
- {\def\docommand##1##2%
+ {\def\selectinterface##1##2%
{\bgroup
\endlinechar\minusone
\global\read16 to ##1
\egroup
\doifnothing\currentinterface{\let##1=##2}%
\doifundefined{\s!prefix!##1}{\let##1=##2}}%
- \docommand\currentinterface\defaultinterface
+ \selectinterface\currentinterface\defaultinterface
\writestatus{interface}{defining \currentinterface\space interface}%
\writeline
- \docommand\currentresponses\currentinterface
+ \selectinterface\currentresponses\currentinterface
\writestatus{interface}{using \currentresponses\space messages}%
\writeline
\let\selectinterface\relax}
-\else
-
- \def\selectinterface
- {\writestatus{interface}{defining \currentinterface\space interface}%
- \writeline
- \writestatus{interface}{using \currentresponses\space messages}%
- \writeline
- \let\selectinterface\relax}
-
\fi
-\ifx\currentinterface\undefined \let\currentinterface\defaultinterface \fi
-\ifx\currentresponses\undefined \let\currentresponses\defaultinterface \fi
+\ifdefined\currentinterface \else \let\currentinterface\defaultinterface \fi
+\ifdefined\currentresponses \else \let\currentresponses\defaultinterface \fi
%D \macros
%D {startinterface}
@@ -363,28 +357,27 @@
\unexpanded\def\startmessages #1 library: #2 %
{\bgroup
\ifcsname\m!prefix!#2\endcsname\else\setgvalue{\m!prefix!#2}{#2}\fi
- \catcode13=\activecatcode
- \doifinsetelse{#1}{\currentresponses,all}\dostartmessages\nostartmessages{#2}}
+ \catcode\endoflineasciicode\activecatcode
+ \doifinsetelse{#1}{\currentresponses,all}\mult_messages_start_yes\mult_messages_start_nop{#2}}
-\def\dostartmessages#1#2\stopmessages
+\def\mult_messages_start_yes#1#2\stopmessages
{\ctxlua{interfaces.setmessages("#1",\!!bs#2\!!es)}%
\egroup}
-\def\nostartmessages#1#2\stopmessages
+\def\mult_messages_start_nop#1#2\stopmessages
{\egroup}
-\def\setinterfacemessage#1#2#3%
+\let\stopmessages\relax
+
+\unexpanded\def\setinterfacemessage#1#2#3%
{\ifcsname\m!prefix!#1\endcsname\else\setgvalue{\m!prefix!#1}{#1}\fi
\ctxlua{interfaces.setmessage("#1","#2",\!!bs#3\!!es)}}
-\unexpanded\def\setmessagetext #1#2{\edef\currentmessagetext{\ctxsprint{interfaces.getmessage("#1","#2")}}}
-\unexpanded\def\getmessage #1#2{\ctxsprint{interfaces.getmessage("#1","#2")}}
-
-%D Till here.
-
-\unexpanded\def\doifelsemessage #1#2{\ctxlua{interfaces.doifelsemessage("#1","#2")}}
-\unexpanded\def\showmessage #1#2#3{\ctxlua{interfaces.showmessage("#1","#2",\!!bs#3\!!es)}}
-\unexpanded\def\writestatus #1#2{\ctxcommand{writestatus("#1",\!!bs#2\!!es)}}
+\unexpanded\def\setmessagetext #1#2{\edef\currentmessagetext{\cldcontext{interfaces.getmessage("#1","#2")}}}
+\unexpanded\def\getmessage #1#2{\cldcontext{interfaces.getmessage("#1","#2")}}
+\unexpanded\def\doifelsemessage #1#2{\ctxlua{interfaces.doifelsemessage("#1","#2")}}
+\unexpanded\def\showmessage #1#2#3{\ctxlua{interfaces.showmessage("#1","#2",\!!bs#3\!!es)}}
+\unexpanded\def\writestatus #1#2{\ctxcommand{writestatus("#1",\!!bs#2\!!es)}}
%D \macros
%D {ifshowwarnings, ifshowmessages}
@@ -408,14 +401,14 @@
\let\normalshowmessage\showmessage
-\def\showwarning
+\unexpanded\def\showwarning
{\ifshowwarnings
\expandafter\showmessage
\else
\expandafter\gobblethreearguments
\fi}
-\def\showmessage
+\unexpanded\def\showmessage
{\ifshowmessages
\expandafter\normalshowmessage
\else
@@ -428,29 +421,50 @@
%D We already defined these auxiliary macros in the system
%D modules. Starting with this module however, we have to take
%D multi||linguality a bit more serious.
-%D
-%D The additional \type {\c!internal!n} prefixing is no longer
-%D needed as we now have separate interface files when dealing
-%D with setups (quick ref docs) and no longer reload the whole
-%D interface. (We no longer need the link back to the main
-%D internal interface.)
-\def\doresetvalue #1#2{\dosetvalue{#1}{#2}{}}
-\def\doignorevalue#1#2#3{\dosetvalue{#1}{#2}{}}
+%D In due time, when we exclusively use the parameter handler code, we can drop
+%D the backmapping (\type{\c!k...}) and make \type {\c!c...} similar to
+%D \type {\v!...}. In that case we can simply the following setters.
+
+\unexpanded\def\doletvalue #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\dosetvalue #1#2{\expandafter\def \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\dosetevalue #1#2{\expandafter\edef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\dosetgvalue #1#2{\expandafter\gdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\dosetxvalue #1#2{\expandafter\xdef\csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname}
+\unexpanded\def\doresetvalue #1#2{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+\unexpanded\def\doignorevalue#1#2#3{\expandafter\let \csname#1\ifcsname\k!prefix!#2\endcsname\csname\k!prefix!#2\endcsname\else#2\fi\endcsname\empty}
+
+\unexpanded\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
+
+ \unexpanded\def\doletvalue #1#2{\expandafter \let\csname#1#2\endcsname}
+ \unexpanded\def\dosetvalue #1#2{\expandafter \def\csname#1#2\endcsname}
+ \unexpanded\def\dosetevalue #1#2{\expandafter\edef\csname#1#2\endcsname}
+ \unexpanded\def\dosetgvalue #1#2{\expandafter\gdef\csname#1#2\endcsname}
+ \unexpanded\def\dosetxvalue #1#2{\expandafter\xdef\csname#1#2\endcsname}
+ \unexpanded\def\doresetvalue #1#2{\expandafter \let\csname#1#2\endcsname\empty}
+ \unexpanded\def\doignorevalue#1#2#3{\expandafter \let\csname#1#2\endcsname\empty}
+
+ \unexpanded\def\docopyvalue#1#2#3%
+ {\expandafter\def\csname#1#3\expandafter\endcsname\expandafter
+ {\csname#2#3\endcsname}}
-\def\doletvalue #1#2{\@EA \let\csname#1#2\endcsname}
-\def\dosetvalue #1#2{\@EA \def\csname#1#2\endcsname}
-\def\dosetevalue #1#2{\@EA\edef\csname#1#2\endcsname}
-\def\dosetgvalue #1#2{\@EA\gdef\csname#1#2\endcsname}
-\def\dosetxvalue #1#2{\@EA\xdef\csname#1#2\endcsname}
-\def\docopyvalue#1#2#3{\@EA \def\csname#1#3\@EA\endcsname\@EA{\csname#2#3\endcsname}}
+\stopinterface
%D We can now redefine some messages that will be
%D introduced in the multi||lingual system module.
-\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}\waitonfatalerror}
-\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}\waitonfatalerror}
-\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}\waitonfatalerror}
+\unexpanded\def\showassignerror #1#2{\showmessage\m!check1{#1,#2}\waitonfatalerror}
+\unexpanded\def\showargumenterror#1#2{\showmessage\m!check2{#1,#2}\waitonfatalerror}
+\unexpanded\def\showdefinederror #1#2{\showmessage\m!check3{#1,#2}\waitonfatalerror}
%D \CONTEXT\ is a parameter driven package. This means that
%D users instruct the system by means of variables, values and
@@ -708,13 +722,13 @@
% temporary mkiv hack (we can best just store the whole table in memory)
-\def\setinterfaceconstant#1#2%
+\unexpanded\def\setinterfaceconstant#1#2%
{\ctxlua{interfaces.setconstant("#1","#2")}%
- \setvalue{\c!prefix!#1}{#1}}
+ \expandafter\def\csname\c!prefix!#1\endcsname{#1}}
-\def\setinterfacevariable#1#2%
+\unexpanded\def\setinterfacevariable#1#2%
{\ctxlua{interfaces.setvariable("#1","#2")}%
- \setvalue{\v!prefix!#1}{#2}}
+ \expandafter\def\csname\v!prefix!#1\endcsname{#2}}
%D \macros
%D {defineinterfaceconstant}
@@ -725,7 +739,7 @@
%D documentation purposes the x||alternative comes in handy.
\unexpanded\def\defineinterfaceconstant#1#2%
- {\setvalue{\c!prefix!#1}{#2}}
+ {\expandafter\def\csname\c!prefix!#1\endcsname{#2}}
%D \macros
%D {startelements}
@@ -741,7 +755,7 @@
%D problem, because we just define two elements. When no second
%D part is needed, we use a \type{-}:
-\def\setinterfaceelement#1#2%
+\unexpanded\def\setinterfaceelement#1#2%
{\ctxlua{interfaces.setelement("#1","#2")}%
\ifcsname\e!prefix!#1\endcsname
\doifnotvalue{\e!prefix!#1}{#2}{\setvalue{\e!prefix!#1}{#2}}%
@@ -749,51 +763,40 @@
\setvalue{\e!prefix!#1}{#2}%
\fi}
-\def\setinterfacecommand#1#2%
- {\doifnot{#1}{#2}{\@EA\def\csname#2\@EA\endcsname\@EA{\csname#1\endcsname}}}% or just \let ?
+\unexpanded\def\setinterfacecommand#1#2%
+ {\doifnot{#1}{#2}% todo: let when already defined
+ {\expandafter\def\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}}
%D We just ignore these:
-\unexpanded\def\startvariables{\gobbleuntil\stopvariables}
-\unexpanded\def\startconstants{\gobbleuntil\stopconstants}
-\unexpanded\def\startelements {\gobbleuntil\stopelements}
-\unexpanded\def\startcommands {\gobbleuntil\stopcommands}
+\unexpanded\def\startvariables{\gobbleuntil\stopvariables} \let\stopvariables\relax
+\unexpanded\def\startconstants{\gobbleuntil\stopconstants} \let\stopconstants\relax
+\unexpanded\def\startelements {\gobbleuntil\stopelements } \let\stopelements \relax
+\unexpanded\def\startcommands {\gobbleuntil\stopcommands } \let\stopcommands \relax
%D For at the \LUA\ end (experiment):
-\def\do@sicon#1#2{\@EA\gdef\csname\c!prefix!#1\endcsname{#1}}
-\def\do@sivar#1#2{\@EA\gdef\csname\v!prefix!#1\endcsname{#2}}
-\def\do@siele#1#2{\@EA\gdef\csname\e!prefix!#1\endcsname{#2}}
-\def\do@sicom#1#2{\@EA\gdef\csname#2\@EA\endcsname\@EA{\csname#1\endcsname}}
+\def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}%
+ \expandafter\gdef\csname\k!prefix!#2\endcsname{#1}} % backmapping from non english
+\def\do@sivar#1#2{\expandafter\gdef\csname\v!prefix!#1\endcsname{#2}}
+\def\do@siele#1#2{\expandafter\gdef\csname\e!prefix!#1\endcsname{#2}}
+\def\do@sicom#1#2{\expandafter\gdef\csname#2\expandafter\endcsname\expandafter{\csname#1\endcsname}}
-%D \macros
-%D {interfaced}
-%D
-%D The setup commands translate the constants automatically.
-%D When we want to translate 'by hand' we can use the simple
-%D but effective command:
-%D
-%D \starttyping
-%D \interfaced {something}
-%D \stoptyping
-%D
-%D Giving \type{\interfaced{breedte}} results in \type{width}
-%D or, when not defined, in \type{breedte} itself. This
-%D macro is used in the font switching mechanism.
+\startinterface english
-\def\interfaced#1%
- {\ifcsname\k!prefix!#1\endcsname
- \csname\k!prefix!#1\endcsname
- \else
- #1%
- \fi}
+ \def\do@sicon#1#2{\expandafter\gdef\csname\c!prefix!#1\endcsname{#1}}
+
+\stopinterface
%D So much for the basic multi||lingual interface commands. The
%D macro's can be enhanced with more testing facilities, but
%D for the moment they suffice.
+\ifdefined\zwnj \else \edef\zwnj{\directlua{utf.char(\number"200C)}} \fi % needed for cont-pe % maybe to char-utf.mkiv
+\ifdefined\zwj \else \edef\zwj {\directlua{utf.char(\number"200D)}} \fi % needed for cont-pe % maybe to char-utf.mkiv
+
%D Out of convenience we define the banners here. This might move
-%D to the Lua end.
+%D to the \LUA\ end.
\def\contextbanner
{ConTeXt \space
@@ -801,7 +804,7 @@
fmt: \formatversion \space \space
int: \currentinterface/\currentresponses}
-\def\showcontextbanner
+\unexpanded\def\showcontextbanner
{\writeline\writebanner{\contextbanner}\writeline}
\edef\formatversion
diff --git a/Master/texmf-dist/tex/context/base/mult-it.mkii b/Master/texmf-dist/tex/context/base/mult-it.mkii
index 3823e651c08..a8f1ff7b646 100644
--- a/Master/texmf-dist/tex/context/base/mult-it.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-it.mkii
@@ -4,6 +4,8 @@
%
\setinterfacevariable{Addition}{Aggiunta}
\setinterfacevariable{Balloon}{Pallone}
+\setinterfacevariable{Cap}{Cap}
+\setinterfacevariable{Capital}{Maiuscolo}
\setinterfacevariable{Character}{Lettera}
\setinterfacevariable{Characters}{Lettere}
\setinterfacevariable{CloseDocument}{ChiudiDocumento}
@@ -61,6 +63,9 @@
\setinterfacevariable{ViewerHelp}{AiutoVisualizzatore}
\setinterfacevariable{WEEKDAY}{GIORNOSETTIMANA}
\setinterfacevariable{WORD}{PAROLA}
+\setinterfacevariable{WORDS}{PAROLE}
+\setinterfacevariable{Word}{Parola}
+\setinterfacevariable{Words}{Parole}
\setinterfacevariable{abbreviation}{abbreviazione}
\setinterfacevariable{abbreviations}{abbreviazioni}
\setinterfacevariable{absolute}{assoluto}
@@ -275,6 +280,7 @@
\setinterfacevariable{marking}{marcatura}
\setinterfacevariable{mathalignment}{mathalignment}
\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathematics}{matematica}
\setinterfacevariable{mathmatrix}{mathmatrix}
\setinterfacevariable{max}{max}
\setinterfacevariable{maxdepth}{maxdepth}
@@ -356,6 +362,7 @@
\setinterfacevariable{previousoddpage}{paginadispariprecedente}
\setinterfacevariable{previouspage}{paginaprecedente}
\setinterfacevariable{previoussubpage}{sottopaginaprecedente}
+\setinterfacevariable{print}{print}
\setinterfacevariable{printable}{stampabile}
\setinterfacevariable{process}{process}
\setinterfacevariable{product}{prodotto}
@@ -363,6 +370,7 @@
\setinterfacevariable{project}{progetto}
\setinterfacevariable{protected}{protetto}
\setinterfacevariable{quadruple}{quadruplo}
+\setinterfacevariable{quarterline}{quarterline}
\setinterfacevariable{quotation}{citazione}
\setinterfacevariable{quote}{menzione}
\setinterfacevariable{ran}{corse}
@@ -497,6 +505,8 @@
\setinterfacevariable{unavailable}{nondisponibile}
\setinterfacevariable{underbar}{sottolinea}
\setinterfacevariable{underbars}{sottolinee}
+\setinterfacevariable{understrike}{understrike}
+\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unit}{unita}
\setinterfacevariable{units}{unita}
\setinterfacevariable{unknown}{ignoto}
@@ -516,6 +526,7 @@
\setinterfacevariable{white}{bianco}
\setinterfacevariable{wide}{ampio}
\setinterfacevariable{width}{ampiezza}
+\setinterfacevariable{word}{parola}
\setinterfacevariable{xml}{xml}
\setinterfacevariable{year}{anno}
\setinterfacevariable{yes}{si}
@@ -533,6 +544,7 @@
\setinterfaceconstant{alignsymbol}{alignsymbol}
\setinterfaceconstant{aligntitle}{allineatitolo}
\setinterfaceconstant{alternative}{alternativa}
+\setinterfaceconstant{anchor}{anchor}
\setinterfaceconstant{andtext}{andtext}
\setinterfaceconstant{apa}{apa}
\setinterfaceconstant{arrow}{freccia}
@@ -552,6 +564,8 @@
\setinterfaceconstant{autohang}{autohang}
\setinterfaceconstant{autostrut}{autostrut}
\setinterfaceconstant{autowidth}{autoampiezza}
+\setinterfaceconstant{availableheight}{availableheight}
+\setinterfaceconstant{availablewidth}{availablewidth}
\setinterfaceconstant{axis}{asse}
\setinterfaceconstant{background}{sfondo}
\setinterfaceconstant{backgroundcolor}{coloresfondo}
@@ -571,6 +585,7 @@
\setinterfaceconstant{blank}{rigovuoto}
\setinterfaceconstant{blockway}{blockway}
\setinterfaceconstant{bodyfont}{fonttesto}
+\setinterfaceconstant{boffset}{boffset}
\setinterfaceconstant{bookmark}{segnalibro}
\setinterfaceconstant{bottom}{fondo}
\setinterfaceconstant{bottomafter}{bottomafter}
@@ -602,6 +617,8 @@
\setinterfaceconstant{commandafter}{comdandodopo}
\setinterfaceconstant{commandbefore}{comandoprima}
\setinterfaceconstant{commands}{comandi}
+\setinterfaceconstant{commentoffset}{commentoffset}
+\setinterfaceconstant{compact}{compact}
\setinterfaceconstant{component}{component}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
@@ -615,6 +632,7 @@
\setinterfaceconstant{coupling}{accoppiamento}
\setinterfaceconstant{couplingway}{modoaccoppiamento}
\setinterfaceconstant{criterium}{criterio}
+\setinterfaceconstant{css}{css}
\setinterfaceconstant{current}{corrente}
\setinterfaceconstant{cutspace}{cutspace}
\setinterfaceconstant{dash}{dash}
@@ -643,11 +661,13 @@
\setinterfaceconstant{editoretallimit}{editoretallimit}
\setinterfaceconstant{editoretaltext}{editoretaltext}
\setinterfaceconstant{empty}{vuoto}
+\setinterfaceconstant{entities}{entities}
\setinterfaceconstant{entries}{entries}
\setinterfaceconstant{equalheight}{equalheight}
\setinterfaceconstant{equalwidth}{equalwidth}
\setinterfaceconstant{escape}{escape}
\setinterfaceconstant{evenmargin}{marginepari}
+\setinterfaceconstant{exitoffset}{labeloffset}
\setinterfaceconstant{expansion}{espansione}
\setinterfaceconstant{export}{export}
\setinterfaceconstant{extras}{extras}
@@ -684,6 +704,7 @@
\setinterfaceconstant{global}{globale}
\setinterfaceconstant{grid}{griglia}
\setinterfaceconstant{hang}{sospendi}
+\setinterfaceconstant{hcompact}{hcompact}
\setinterfaceconstant{headalign}{headalign}
\setinterfaceconstant{headcolor}{coloretesta}
\setinterfaceconstant{headcommand}{headcommand}
@@ -712,6 +733,7 @@
\setinterfaceconstant{inner}{interno}
\setinterfaceconstant{innermargin}{margineinterno}
\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{insidesection}{insidesection}
\setinterfaceconstant{intent}{intent}
\setinterfaceconstant{interaction}{interazione}
\setinterfaceconstant{interlinespace}{interlinea}
@@ -724,8 +746,10 @@
\setinterfaceconstant{keys}{keys}
\setinterfaceconstant{keyword}{parolachiave}
\setinterfaceconstant{label}{etichetta}
+\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{sinistra}
\setinterfaceconstant{leftcolor}{coloresinistra}
\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
@@ -754,6 +778,7 @@
\setinterfaceconstant{listtext}{listtext}
\setinterfaceconstant{local}{locale}
\setinterfaceconstant{location}{luogo}
+\setinterfaceconstant{loffset}{loffset}
\setinterfaceconstant{logo}{logo}
\setinterfaceconstant{logos}{loghi}
\setinterfaceconstant{marcolor}{coloremarcatura}
@@ -830,6 +855,7 @@
\setinterfaceconstant{page}{pagina}
\setinterfaceconstant{pageboundaries}{limitipagina}
\setinterfaceconstant{pagecolor}{colorepagina}
+\setinterfaceconstant{pagecolormodel}{pagecolormodel}
\setinterfaceconstant{pagecommand}{comandopagina}
\setinterfaceconstant{pageconversion}{pageconversion}
\setinterfaceconstant{pageconversionset}{pageconversionset}
@@ -870,6 +896,7 @@
\setinterfaceconstant{preview}{anteprima}
\setinterfaceconstant{previous}{precedente}
\setinterfaceconstant{previousnumber}{numeroprecedente}
+\setinterfaceconstant{printable}{stampabile}
\setinterfaceconstant{process}{process}
\setinterfaceconstant{profile}{profile}
\setinterfaceconstant{pubsep}{pubsep}
@@ -882,6 +909,7 @@
\setinterfaceconstant{reference}{riferimento}
\setinterfaceconstant{referenceprefix}{referenceprefix}
\setinterfaceconstant{referencing}{referencing}
+\setinterfaceconstant{region}{region}
\setinterfaceconstant{regionin}{entraregione}
\setinterfaceconstant{regionout}{esciregione}
\setinterfaceconstant{repeat}{ripeti}
@@ -906,9 +934,11 @@
\setinterfaceconstant{rightsubsentence}{sottofrasedestra}
\setinterfaceconstant{righttext}{testodestro}
\setinterfaceconstant{rightwidth}{ampiezzadestra}
+\setinterfaceconstant{roffset}{roffset}
\setinterfaceconstant{rotation}{rotazione}
\setinterfaceconstant{rule}{linea}
\setinterfaceconstant{rulecolor}{colorelinea}
+\setinterfaceconstant{rulecommand}{rulecommand}
\setinterfaceconstant{rulethickness}{spessorelinea}
\setinterfaceconstant{samepage}{stessapagina}
\setinterfaceconstant{sample}{campione}
@@ -966,6 +996,7 @@
\setinterfaceconstant{subtitle}{sottotitolo}
\setinterfaceconstant{suffix}{suffix}
\setinterfaceconstant{suffixseparator}{suffixseparator}
+\setinterfaceconstant{suffixstopper}{suffixstopper}
\setinterfaceconstant{surnamesep}{surnamesep}
\setinterfaceconstant{sx}{sx}
\setinterfaceconstant{sy}{sy}
@@ -983,6 +1014,7 @@
\setinterfaceconstant{textcolor}{coloretesto}
\setinterfaceconstant{textcommand}{comandotesto}
\setinterfaceconstant{textdistance}{distanzatesto}
+\setinterfaceconstant{textheight}{altezzatesto}
\setinterfaceconstant{textlayer}{textlayer}
\setinterfaceconstant{textmargin}{textmargin}
\setinterfaceconstant{textmethod}{textmethod}
@@ -1000,6 +1032,7 @@
\setinterfaceconstant{titleright}{titleright}
\setinterfaceconstant{titlestyle}{stiletitolo}
\setinterfaceconstant{to}{verso}
+\setinterfaceconstant{toffset}{toffset}
\setinterfaceconstant{tolerance}{tolleranza}
\setinterfaceconstant{top}{cima}
\setinterfaceconstant{topdistance}{distanzacima}
@@ -1016,6 +1049,8 @@
\setinterfaceconstant{validate}{verifica}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vcomando}
+\setinterfaceconstant{vcompact}{vcompact}
+\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{veroffset}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{voffset}{voffset}
@@ -1025,6 +1060,7 @@
\setinterfaceconstant{white}{bianco}
\setinterfaceconstant{width}{ampiezza}
\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xhtml}{xhtml}
\setinterfaceconstant{xmax}{xmax}
\setinterfaceconstant{xoffset}{xoffset}
\setinterfaceconstant{xscale}{xscale}
@@ -1042,8 +1078,6 @@
\setinterfaceelement{complete}{completo}
\setinterfaceelement{coupled}{accoppiato}
\setinterfaceelement{currentlocal}{correntelocale}
-\setinterfaceelement{emptyone}{prazdne}
-\setinterfaceelement{emptytwo}{vuoti}
\setinterfaceelement{end}{fine}
\setinterfaceelement{endsetup}{}
\setinterfaceelement{get}{prendi}
@@ -1156,7 +1190,7 @@
\setinterfacecommand{defineframedtext}{definiscitestoincorniciato}
\setinterfacecommand{definehbox}{definiscihbox}
\setinterfacecommand{definehead}{definiscitesta}
-\setinterfacecommand{defineindenting}{definiscirientro}
+\setinterfacecommand{defineindentedtext}{defineindentedtext}
\setinterfacecommand{defineinmargin}{defineinmargin}
\setinterfacecommand{defineinteractionmenu}{definiscimenuinterazione}
\setinterfacecommand{defineitemgroup}{defineitemgroup}
@@ -1352,7 +1386,6 @@
\setinterfacecommand{pagenumber}{numeropagina}
\setinterfacecommand{pageoffset}{pageoffset}
\setinterfacecommand{pagereference}{riferimentopagina}
-\setinterfacecommand{pagetype}{tipopagina}
\setinterfacecommand{paperheight}{altezzacarta}
\setinterfacecommand{paperwidth}{ampiezzacarta}
\setinterfacecommand{periods}{punti}
@@ -1468,7 +1501,7 @@
\setinterfacecommand{setupheads}{impostateste}
\setinterfacecommand{setupheadtext}{impostatestointestazioni}
\setinterfacecommand{setuphyphenmark}{impostasegnosillabazione}
-\setinterfacecommand{setupindentations}{impostarientri}
+\setinterfacecommand{setupindentedtext}{setupindentedtext}
\setinterfacecommand{setupindenting}{impostarientro}
\setinterfacecommand{setupinmargin}{impostainmargine}
\setinterfacecommand{setupinteraction}{impostainterazione}
diff --git a/Master/texmf-dist/tex/context/base/mult-low.lua b/Master/texmf-dist/tex/context/base/mult-low.lua
new file mode 100644
index 00000000000..743f851c483
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mult-low.lua
@@ -0,0 +1,250 @@
+if not modules then modules = { } end modules ['mult-low'] = {
+ version = 1.001,
+ comment = "companion to mult-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- for syntax highlighters, only the ones that are for users (boring to collect them)
+
+return {
+ ["constants"] = {
+ --
+ "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive",
+ "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred",
+ "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard",
+ "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint",
+ "points", "halfpoint",
+ "zeroskip",
+ "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi",
+ "normalpagebox",
+ -- --
+ "endoflinetoken", "outputnewlinechar",
+ --
+ "emptytoks", "empty", "undefined",
+ --
+ "voidbox", "emptybox", "emptyvbox", "emptyhbox",
+ --
+ "bigskipamount", "medskipamount", "smallskipamount",
+ --
+ "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion",
+ "luatexengine", "pdftexengine", "xetexengine", "unknownengine",
+ "etexversion", "pdftexversion", "xetexversion", "xetexrevision",
+ --
+ "activecatcode",
+ --
+ "bgroup", "egroup",
+ "endline",
+ --
+ "conditionaltrue", "conditionalfalse",
+ --
+ "attributeunsetvalue",
+ --
+ "uprotationangle", "rightrotationangle", "downrotationangle", "leftrotationangle",
+ --
+ "inicatcodes",
+ "ctxcatcodes", "texcatcodes", "notcatcodes", "txtcatcodes", "vrbcatcodes",
+ "prtcatcodes", "nilcatcodes", "luacatcodes", "tpacatcodes", "tpbcatcodes",
+ "xmlcatcodes",
+ --
+ "escapecatcode", "begingroupcatcode", "endgroupcatcode", "mathshiftcatcode", "alignmentcatcode",
+ "endoflinecatcode", "parametercatcode", "superscriptcatcode", "subscriptcatcode", "ignorecatcode",
+ "spacecatcode", "lettercatcode", "othercatcode", "activecatcode", "commentcatcode", "invalidcatcode",
+ --
+ "tabasciicode", "newlineasciicode", "formfeedasciicode", "endoflineasciicode", "endoffileasciicode",
+ "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode",
+ "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode",
+ "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode",
+ "lessthanasciicode", "morethanasciicode", "doublecommentsignal",
+ "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode",
+ "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode",
+ "primeasciicode",
+ --
+ "activemathcharcode",
+ --
+ "activetabtoken", "activeformfeedtoken", "activeendoflinetoken",
+ --
+ "batchmodecode", "nonstopmodecode", "scrollmodecode", "errorstopmodecode",
+ --
+ "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode",
+ "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode",
+ "discretionarygroupcode", "insertgroupcode", "vcentergroupcode", "mathchoicegroupcode",
+ "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "vadjustgroupcode",
+ --
+ "charnodecode", "hlistnodecode", "vlistnodecode", "rulenodecode", "insertnodecode", "marknodecode",
+ "adjustnodecode", "ligaturenodecode", "discretionarynodecode", "whatsitnodecode", "mathnodecode",
+ "gluenodecode", "kernnodecode", "penaltynodecode", "unsetnodecode", "mathsnodecode",
+ --
+ "charifcode", "catifcode", "numifcode", "dimifcode", "oddifcode", "vmodeifcode", "hmodeifcode",
+ "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode",
+ "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode",
+ --
+ "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink",
+ "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint",
+ "interwordspace", "interwordstretch", "interwordshrink", "exheight", "emwidth", "extraspace",
+ "mathsupdisplay", "mathsupnormal", "mathsupcramped", "mathsubnormal", "mathsubcombined", "mathaxisheight",
+ --
+ -- maybe a different class
+ --
+ "startmode", "stopmode", "startnotmode", "stopnotmode", "startmodeset", "stopmodeset",
+ "doifmode", "doifmodeelse", "doifnotmode",
+ "startallmodes", "stopallmodes", "startnotallmodes", "stopnotallmodes", "doifallmodes", "doifallmodeselse", "doifnotallmodes",
+ "startenvironment", "stopenvironment", "environment",
+ "startcomponent", "stopcomponent", "component",
+ "startproduct", "stopproduct", "product",
+ "startproject", "stopproject", "project",
+ "starttext", "stoptext", "startdocument", "stopdocument", "documentvariable",
+ "startmodule", "stopmodule", "usemodule",
+ --
+ "startTEXpage", "stopTEXpage",
+ -- "startMPpage", "stopMPpage", -- already catched by nested lexer
+ --
+ "enablemode", "disablemode", "preventmode", "pushmode", "popmode",
+ --
+ "typescriptone", "typescripttwo", "typescriptthree", "mathsizesuffix",
+ --
+ "mathordcode", "mathopcode", "mathbincode", "mathrelcode", "mathopencode", "mathclosecode",
+ "mathpunctcode", "mathalphacode", "mathinnercode", "mathnothingcode", "mathlimopcode",
+ "mathnolopcode", "mathboxcode", "mathchoicecode", "mathaccentcode", "mathradicalcode",
+ --
+ "constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument",
+ --
+ "continueifinputfile",
+ },
+ ["helpers"] = {
+ --
+ "startsetups", "stopsetups",
+ "startxmlsetups", "stopxmlsetups",
+ "startluasetups", "stopluasetups",
+ "starttexsetups", "stoptexsetups",
+ "startrawsetups", "stoprawsetups",
+ "startlocalsetups", "stoplocalsetups",
+ "starttexdefinition", "stoptexdefinition",
+ "starttexcode", "stoptexcode",
+ --
+ "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup",
+ --
+ "newmode", "setmode", "resetmode",
+ "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode",
+ "booleanmodevalue",
+ --
+ "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif",
+ "newlanguage", "newfamily", "newfam", "newhelp", -- not used
+ --
+ "then",
+ --
+ "donothing", "dontcomplain",
+ --
+ "donetrue", "donefalse",
+ --
+ "htdp",
+ "unvoidbox",
+ "vfilll",
+ --
+ "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha",
+ --
+ "currentcatcodetable", "defaultcatcodetable", "catcodetablename",
+ "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable",
+ "pushcatcodetable", "popcatcodetable", "restorecatcodes",
+ "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand",
+ --
+ "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg",
+ --
+ "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg",
+ "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg",
+ "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter",
+ "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern",
+ "ruledhglue", "ruledvglue", "normalhglue", "normalvglue",
+ "ruledpenalty",
+ --
+ "scratchcounter", "globalscratchcounter",
+ "scratchdimen", "globalscratchdimen",
+ "scratchskip", "globalscratchskip",
+ "scratchmuskip", "globalscratchmuskip",
+ "scratchtoks", "globalscratchtoks",
+ "scratchbox", "globalscratchbox",
+ --
+ "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs",
+ --
+ "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance",
+ "scratchhsize", "scratchvsize",
+ --
+ "scratchcounterone", "scratchcountertwo", "scratchcounterthree",
+ "scratchdimenone", "scratchdimentwo", "scratchdimenthree",
+ "scratchskipone", "scratchskiptwo", "scratchskipthree",
+ "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree",
+ "scratchtoksone", "scratchtokstwo", "scratchtoksthree",
+ "scratchboxone", "scratchboxtwo", "scratchboxthree",
+ --
+ "doif", "doifnot", "doifelse",
+ "doifinset", "doifnotinset", "doifinsetelse",
+ "doifnextcharelse", "doifnextoptionalelse", "doifnextbgroupelse", "doifnextparenthesiselse", "doiffastoptionalcheckelse",
+ "doifundefinedelse", "doifdefinedelse", "doifundefined", "doifdefined",
+ "doifelsevalue", "doifvalue", "doifnotvalue",
+ "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse",
+ "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing",
+ "doifdimensionelse", "doifnumberelse",
+ "doifcommonelse", "doifcommon", "doifnotcommon",
+ "doifinstring", "doifnotinstring", "doifinstringelse",
+ "doifassignmentelse",
+ --
+ "tracingall", "tracingnone", "loggingall",
+ --
+ "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to",
+ --
+ "endgraf", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "normalspace",
+ --
+ "executeifdefined",
+ --
+ "singleexpandafter", "doubleexpandafter", "tripleexpandafter",
+ --
+ "dontleavehmode", "removelastspace", "removeunwantedspaces",
+ --
+ "wait", "writestatus", "define", "redefine",
+ --
+ "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "measure",
+ --
+ "getvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue",
+ "resetvalue", "undefinevalue", "ignorevalue",
+ "setuvalue", "setuevalue", "setugvalue", "setuxvalue",
+ "globallet", "glet",
+ "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters",
+ --
+ "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist",
+ "processaction", "processallactions", "processfirstactioninset", "processallactionsinset",
+ --
+ "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect",
+ --
+ "firstofoneargument",
+ "firstoftwoarguments", "secondoftwoarguments",
+ "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments",
+ "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments",
+ "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments",
+ "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments",
+ --
+ "firstofoneunexpanded",
+ --
+ "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments",
+ "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals",
+ --
+ "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs",
+ --
+ "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant",
+ "newmacro", "setnewmacro", "newfraction",
+ --
+ "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty",
+ "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument",
+ "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty",
+ --
+ "nopdfcompression", "maximumpdfcompression", "normalpdfcompression",
+ --
+ "modulonumber", "dividenumber",
+ --
+ "getfirstcharacter", "doiffirstcharelse",
+ --
+ "startnointerference", "stopnointerference",
+ --
+ "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "begstrut", "endstrut",
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mult-mes.lua b/Master/texmf-dist/tex/context/base/mult-mes.lua
index cdd6d5ad21a..473c86d3547 100644
--- a/Master/texmf-dist/tex/context/base/mult-mes.lua
+++ b/Master/texmf-dist/tex/context/base/mult-mes.lua
@@ -1097,14 +1097,15 @@ return {
no = "ulovlig referanse %s",
ro = "referinta eronata %s",
},
- ["references:5"] = {
- en = "number of unknown references: %s",
- },
+ -- ["number of unknown references: %s"] = {
+ -- },
["references:6"] = {
en = "number of illegal references: %s",
},
- ["start: '%s'"] = {},
- ["stop: '%s'"] = {},
+ ["start: '%s'"] = {
+ },
+ ["stop: '%s'"] = {
+ },
["stored: preamble '%s', state '%s', order '%s'"] = {
nl = "opgeslagen: preamble '%s', status '%s', volgorde '%s'",
},
diff --git a/Master/texmf-dist/tex/context/base/mult-mps.lua b/Master/texmf-dist/tex/context/base/mult-mps.lua
new file mode 100644
index 00000000000..2f2c419742e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mult-mps.lua
@@ -0,0 +1,112 @@
+return {
+ tex = {
+ "btex", "etex", "verbatimtex",
+ },
+ shortcuts = {
+ "..", "...", "--", "---", "&",
+ },
+ primitives = { -- to be checked
+ "charcode", "day", "linecap", "linejoin", "miterlimit", "month", "pausing",
+ "prologues", "showstopping", "time", "tracingcapsules", "tracingchoices", "mpprocset",
+ "tracingcommands", "tracingequations", "tracinglostchars",
+ "tracingmacros", "tracingonline", "tracingoutput", "tracingrestores",
+ "tracingspecs", "tracingstats", "tracingtitles", "truecorners",
+ "warningcheck", "year",
+ "false", "nullpicture", "pencircle", "true",
+ "and", "angle", "arclength", "arctime", "ASCII", "boolean", "bot",
+ "char", "color", "cosd", "cycle", "decimal", "directiontime", "floor", "fontsize",
+ "hex", "infont", "intersectiontimes", "known", "length", "llcorner",
+ "lrcorner", "makepath", "makepen", "mexp", "mlog", "normaldeviate", "not",
+ "numeric", "oct", "odd", "or", "path", "pair", "pen", "penoffset", "picture", "point",
+ "postcontrol", "precontrol", "reverse", "rotated", "scaled",
+ "shifted", "sind", "slanted", "sqrt", "str", "string", "subpath", "substring",
+ "transform", "transformed", "ulcorner", "uniformdeviate", "unknown",
+ "urcorner", "xpart", "xscaled", "xxpart", "xypart", "ypart", "yscaled", "yxpart",
+ "yypart", "zscaled",
+ "addto", "clip", "input", "interim", "let", "newinternal", "save", "setbounds",
+ "shipout", "show", "showdependencies", "showtoken", "showvariable",
+ "special",
+ "begingroup", "endgroup", "of", "curl", "tension", "and", "controls",
+ "interpath", "on", "off",
+ "def", "vardef", "enddef", "expr", "suffix", "text", "primary", "secondary",
+ "tertiary", "primarydef", "secondarydef", "tertiarydef",
+ "randomseed", "also", "contour", "doublepath",
+ "withcolor", "withpen", "dashed", "if", "else", "elseif", "fi", "for", "endfor", "forever", "exitif",
+ "forsuffixes", "downto", "upto", "step", "until",
+ "charlist", "extensible", "fontdimen", "headerbyte", "kern", "ligtable",
+ "boundarychar", "chardp", "charext", "charht", "charic", "charwd", "designsize",
+ "fontmaking", "charexists",
+ "cullit", "currenttransform", "gfcorners", "grayfont", "hround",
+ "imagerules", "lowres_fix", "nodisplays", "notransforms", "openit",
+ "displaying", "currentwindow", "screen_rows", "screen_cols",
+ "pixels_per_inch", "cull", "display", "openwindow", "numspecial",
+ "totalweight", "autorounding", "fillin", "proofing", "tracingpens",
+ "xoffset", "chardx", "granularity", "smoothing", "turningcheck", "yoffset",
+ "chardy", "hppp", "tracingedges", "vppp",
+ "extra_beginfig", "extra_endfig", "mpxbreak",
+ "endinput",
+ "message", "delimiters", "turningnumber", "errmessage",
+ "readstring", "scantokens", "end", "outer", "inner", "write", "to", "readfrom",
+ "withprescript", "withpostscript",
+ "top", "bot", "lft", "rt", "ulft", "urt", "llft", "lrt",
+ --
+ "redpart", "greenpart", "bluepart", "cyanpart", "magentapart", "yellowpart", "blackpart", "greypart",
+ "rgbcolor", "cmykcolor", "greycolor", "graycolor",
+ "colormodel", "graypart",
+ "expandafter",
+ },
+ commands = {
+ "beginfig", "endfig",
+ "rotatedaround", "reflectedabout",
+ "arrowhead",
+ "currentpen", "currentpicture", "cuttings",
+ "defaultfont", "extra_beginfig", "extra_endfig",
+ "ditto", "EOF", "down",
+ "evenly", "fullcircle", "halfcircle", "identity", "in", "left",
+ "origin", "pensquare", "quartercircle", "right",
+ "unitsquare", "up", "withdots",
+ "abs", "bbox", "ceiling", "center", "cutafter", "cutbefore", "dir",
+ "directionpoint", "div", "dotprod", "intersectionpoint", "inverse", "mod",
+ "round", "unitvector", "whatever",
+ "cutdraw", "draw", "drawarrow", "drawdblarrow", "fill", "filldraw", "drawdot",
+ "loggingall", "interact", "tracingall", "tracingnone",
+ "pickup",
+ "undraw", "unfill", "unfilldraw",
+ "buildcycle", "dashpattern", "decr", "dotlabel", "dotlabels", "drawoptions",
+ "incr", "label", "labels", "max", "min", "thelabel", "z",
+ "beginchar", "blacker", "capsule_end", "change_width",
+ "define_blacker_pixels", "define_corrected_pixels",
+ "define_good_x_pixels", "define_good_y_pixels",
+ "define_horizontal_corrected_pixels", "define_pixels",
+ "define_whole_blacker_pixels", "define_whole_pixels",
+ "define_whole_vertical_blacker_pixels",
+ "define_whole_vertical_pixels", "endchar", "extra_beginchar",
+ "extra_endchar", "extra_setup", "font_coding_scheme",
+ "clearxy", "clearit", "clearpen", "shipit",
+ "font_extra_space",
+ "exitunless",
+ "relax", "hide", "gobble", "gobbled", "stop",
+ "blankpicture",
+ "counterclockwise", "tensepath", "takepower", "direction",
+ "softjoin", -- "magstep",
+ "makelabel", -- "laboff",
+ "rotatedabout", "flex", "superellipse", "erase", "image",
+ "nullpen", "savepen", "clearpen", "penpos", "penlabels", -- "clear_pen_memory",
+ "range", "numtok", "thru",
+ "z", "laboff",
+ "bye",
+ --
+ "red", "green", "blue", "cyan", "magenta", "yellow", "black", "white", "background",
+ "graypart", "graycolor",
+ --
+ "mm", "pt", "dd", "bp", "cm", "pc", "cc", "in",
+ },
+ internals = { -- we need to remove duplicates above
+ --
+ "mitered", "rounded", "beveled", "butt", "squared",
+ "eps", "epsilon", "infinity",
+ "bboxmargin", "ahlength", "ahangle", "labeloffset", "dotlabeldiam", "defaultpen", "defaultscale", "join_radius",
+ --
+ "pen_lft", "pen_rt", "pen_top", "pen_bot", -- "pen_count_",
+ },
+}
diff --git a/Master/texmf-dist/tex/context/base/mult-nl.mkii b/Master/texmf-dist/tex/context/base/mult-nl.mkii
index a5b62ad3347..b199039dd6d 100644
--- a/Master/texmf-dist/tex/context/base/mult-nl.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-nl.mkii
@@ -4,6 +4,8 @@
%
\setinterfacevariable{Addition}{Toevoeging}
\setinterfacevariable{Balloon}{Ballon}
+\setinterfacevariable{Cap}{Kap}
+\setinterfacevariable{Capital}{Kapitaal}
\setinterfacevariable{Character}{Letter}
\setinterfacevariable{Characters}{Letters}
\setinterfacevariable{CloseDocument}{SluitDocument}
@@ -61,6 +63,9 @@
\setinterfacevariable{ViewerHelp}{ViewerHelp}
\setinterfacevariable{WEEKDAY}{WEEKDAG}
\setinterfacevariable{WORD}{WOORD}
+\setinterfacevariable{WORDS}{WOORDEN}
+\setinterfacevariable{Word}{Woord}
+\setinterfacevariable{Words}{Woorden}
\setinterfacevariable{abbreviation}{afkorting}
\setinterfacevariable{abbreviations}{afkortingen}
\setinterfacevariable{absolute}{absoluut}
@@ -275,6 +280,7 @@
\setinterfacevariable{marking}{markering}
\setinterfacevariable{mathalignment}{wiskundeuitlijnen}
\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathematics}{wiskunde}
\setinterfacevariable{mathmatrix}{wiskundematrix}
\setinterfacevariable{max}{max}
\setinterfacevariable{maxdepth}{maxdepth}
@@ -356,6 +362,7 @@
\setinterfacevariable{previousoddpage}{vorigeonevenpagina}
\setinterfacevariable{previouspage}{vorigepagina}
\setinterfacevariable{previoussubpage}{vorigesubpagina}
+\setinterfacevariable{print}{print}
\setinterfacevariable{printable}{printbaar}
\setinterfacevariable{process}{proces}
\setinterfacevariable{product}{produkt}
@@ -363,6 +370,7 @@
\setinterfacevariable{project}{project}
\setinterfacevariable{protected}{beschermd}
\setinterfacevariable{quadruple}{viertal}
+\setinterfacevariable{quarterline}{kwartregel}
\setinterfacevariable{quotation}{citaat}
\setinterfacevariable{quote}{citeer}
\setinterfacevariable{ran}{ran}
@@ -497,6 +505,8 @@
\setinterfacevariable{unavailable}{nietbeschikbaar}
\setinterfacevariable{underbar}{onderstreep}
\setinterfacevariable{underbars}{onderstrepen}
+\setinterfacevariable{understrike}{understrike}
+\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unit}{eenheid}
\setinterfacevariable{units}{eenheden}
\setinterfacevariable{unknown}{onbekend}
@@ -516,6 +526,7 @@
\setinterfacevariable{white}{wit}
\setinterfacevariable{wide}{breed}
\setinterfacevariable{width}{breedte}
+\setinterfacevariable{word}{woord}
\setinterfacevariable{xml}{xml}
\setinterfacevariable{year}{jaar}
\setinterfacevariable{yes}{ja}
@@ -533,6 +544,7 @@
\setinterfaceconstant{alignsymbol}{alignsymbol}
\setinterfaceconstant{aligntitle}{titeluitlijnen}
\setinterfaceconstant{alternative}{variant}
+\setinterfaceconstant{anchor}{anker}
\setinterfaceconstant{andtext}{andtext}
\setinterfaceconstant{apa}{apa}
\setinterfaceconstant{arrow}{pijl}
@@ -552,6 +564,8 @@
\setinterfaceconstant{autohang}{autohang}
\setinterfaceconstant{autostrut}{autostrut}
\setinterfaceconstant{autowidth}{autobreedte}
+\setinterfaceconstant{availableheight}{beschikbarehoogte}
+\setinterfaceconstant{availablewidth}{beschikbarebreedte}
\setinterfaceconstant{axis}{assenstelsel}
\setinterfaceconstant{background}{achtergrond}
\setinterfaceconstant{backgroundcolor}{achtergrondkleur}
@@ -571,6 +585,7 @@
\setinterfaceconstant{blank}{blanko}
\setinterfaceconstant{blockway}{blokwijze}
\setinterfaceconstant{bodyfont}{korps}
+\setinterfaceconstant{boffset}{boffset}
\setinterfaceconstant{bookmark}{bookmark}
\setinterfaceconstant{bottom}{onder}
\setinterfaceconstant{bottomafter}{bottomafter}
@@ -602,6 +617,8 @@
\setinterfaceconstant{commandafter}{nacommando}
\setinterfaceconstant{commandbefore}{voorcommando}
\setinterfaceconstant{commands}{commandos}
+\setinterfaceconstant{commentoffset}{commentoffset}
+\setinterfaceconstant{compact}{compact}
\setinterfaceconstant{component}{component}
\setinterfaceconstant{compoundhyphen}{koppelteken}
\setinterfaceconstant{compress}{comprimeren}
@@ -615,6 +632,7 @@
\setinterfaceconstant{coupling}{koppeling}
\setinterfaceconstant{couplingway}{koppelwijze}
\setinterfaceconstant{criterium}{criterium}
+\setinterfaceconstant{css}{css}
\setinterfaceconstant{current}{huidige}
\setinterfaceconstant{cutspace}{snijwit}
\setinterfaceconstant{dash}{streep}
@@ -628,7 +646,7 @@
\setinterfaceconstant{depth}{diepte}
\setinterfaceconstant{depthcorrection}{dieptecorrectie}
\setinterfaceconstant{direction}{richting}
-\setinterfaceconstant{directory}{gebied}
+\setinterfaceconstant{directory}{directory}
\setinterfaceconstant{display}{scherm}
\setinterfaceconstant{distance}{afstand}
\setinterfaceconstant{dot}{punt}
@@ -643,11 +661,13 @@
\setinterfaceconstant{editoretallimit}{editoretallimit}
\setinterfaceconstant{editoretaltext}{editoretaltext}
\setinterfaceconstant{empty}{leeg}
+\setinterfaceconstant{entities}{entities}
\setinterfaceconstant{entries}{ingangen}
\setinterfaceconstant{equalheight}{equalheight}
\setinterfaceconstant{equalwidth}{equalwidth}
\setinterfaceconstant{escape}{escape}
\setinterfaceconstant{evenmargin}{evenmarge}
+\setinterfaceconstant{exitoffset}{labeloffset}
\setinterfaceconstant{expansion}{expansie}
\setinterfaceconstant{export}{exporteer}
\setinterfaceconstant{extras}{extras}
@@ -684,6 +704,7 @@
\setinterfaceconstant{global}{globaal}
\setinterfaceconstant{grid}{grid}
\setinterfaceconstant{hang}{hang}
+\setinterfaceconstant{hcompact}{hcomprimeer}
\setinterfaceconstant{headalign}{kopuitlijnen}
\setinterfaceconstant{headcolor}{kopkleur}
\setinterfaceconstant{headcommand}{kopcommando}
@@ -712,6 +733,7 @@
\setinterfaceconstant{inner}{binnen}
\setinterfaceconstant{innermargin}{binnenmarge}
\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{insidesection}{binnensectie}
\setinterfaceconstant{intent}{intent}
\setinterfaceconstant{interaction}{interactie}
\setinterfaceconstant{interlinespace}{interlinie}
@@ -724,8 +746,10 @@
\setinterfaceconstant{keys}{sleutels}
\setinterfaceconstant{keyword}{trefwoord}
\setinterfaceconstant{label}{label}
+\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{links}
\setinterfaceconstant{leftcolor}{linkerkleur}
\setinterfaceconstant{leftcompoundhyphen}{linkerkoppelteken}
@@ -754,6 +778,7 @@
\setinterfaceconstant{listtext}{lijsttekst}
\setinterfaceconstant{local}{lokaal}
\setinterfaceconstant{location}{plaats}
+\setinterfaceconstant{loffset}{loffset}
\setinterfaceconstant{logo}{logo}
\setinterfaceconstant{logos}{logos}
\setinterfaceconstant{marcolor}{markleur}
@@ -821,7 +846,7 @@
\setinterfaceconstant{openpage}{openpagina}
\setinterfaceconstant{openpageaction}{openpaginaactie}
\setinterfaceconstant{option}{optie}
-\setinterfaceconstant{order}{order}
+\setinterfaceconstant{order}{volgorde}
\setinterfaceconstant{orientation}{orientatie}
\setinterfaceconstant{otherstext}{otherstext}
\setinterfaceconstant{outermargin}{buitenmarge}
@@ -830,6 +855,7 @@
\setinterfaceconstant{page}{pagina}
\setinterfaceconstant{pageboundaries}{paginaovergangen}
\setinterfaceconstant{pagecolor}{paginakleur}
+\setinterfaceconstant{pagecolormodel}{paginakleurmodel}
\setinterfaceconstant{pagecommand}{paginacommando}
\setinterfaceconstant{pageconversion}{pageconversion}
\setinterfaceconstant{pageconversionset}{pageconversionset}
@@ -870,6 +896,7 @@
\setinterfaceconstant{preview}{preview}
\setinterfaceconstant{previous}{vorige}
\setinterfaceconstant{previousnumber}{vorigenummer}
+\setinterfaceconstant{printable}{printbaar}
\setinterfaceconstant{process}{proces}
\setinterfaceconstant{profile}{profile}
\setinterfaceconstant{pubsep}{pubsep}
@@ -882,6 +909,7 @@
\setinterfaceconstant{reference}{verwijzing}
\setinterfaceconstant{referenceprefix}{referenceprefix}
\setinterfaceconstant{referencing}{refereren}
+\setinterfaceconstant{region}{gebied}
\setinterfaceconstant{regionin}{gebiedin}
\setinterfaceconstant{regionout}{gebieduit}
\setinterfaceconstant{repeat}{herhaal}
@@ -906,9 +934,11 @@
\setinterfaceconstant{rightsubsentence}{rechtersubzin}
\setinterfaceconstant{righttext}{rechtertekst}
\setinterfaceconstant{rightwidth}{rechterbreedte}
+\setinterfaceconstant{roffset}{roffset}
\setinterfaceconstant{rotation}{rotatie}
\setinterfaceconstant{rule}{lijn}
\setinterfaceconstant{rulecolor}{lijnkleur}
+\setinterfaceconstant{rulecommand}{lijncommando}
\setinterfaceconstant{rulethickness}{lijndikte}
\setinterfaceconstant{samepage}{zelfdepagina}
\setinterfaceconstant{sample}{monster}
@@ -966,6 +996,7 @@
\setinterfaceconstant{subtitle}{subtitel}
\setinterfaceconstant{suffix}{suffix}
\setinterfaceconstant{suffixseparator}{suffixscheider}
+\setinterfaceconstant{suffixstopper}{suffixafsluiter}
\setinterfaceconstant{surnamesep}{surnamesep}
\setinterfaceconstant{sx}{sx}
\setinterfaceconstant{sy}{sy}
@@ -983,6 +1014,7 @@
\setinterfaceconstant{textcolor}{tekstkleur}
\setinterfaceconstant{textcommand}{tekstcommando}
\setinterfaceconstant{textdistance}{tekstafstand}
+\setinterfaceconstant{textheight}{teksthoogte}
\setinterfaceconstant{textlayer}{tekstlaag}
\setinterfaceconstant{textmargin}{tekstmarge}
\setinterfaceconstant{textmethod}{tekstmethode}
@@ -1000,6 +1032,7 @@
\setinterfaceconstant{titleright}{titelrechts}
\setinterfaceconstant{titlestyle}{titelletter}
\setinterfaceconstant{to}{aan}
+\setinterfaceconstant{toffset}{toffset}
\setinterfaceconstant{tolerance}{tolerantie}
\setinterfaceconstant{top}{boven}
\setinterfaceconstant{topdistance}{bovenafstand}
@@ -1016,6 +1049,8 @@
\setinterfaceconstant{validate}{valideer}
\setinterfaceconstant{values}{waarden}
\setinterfaceconstant{vcommand}{vcommando}
+\setinterfaceconstant{vcompact}{vcomprimeer}
+\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{kopoffset}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{voffset}{voffset}
@@ -1025,6 +1060,7 @@
\setinterfaceconstant{white}{wit}
\setinterfaceconstant{width}{breedte}
\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xhtml}{xhtml}
\setinterfaceconstant{xmax}{xmax}
\setinterfaceconstant{xoffset}{xoffset}
\setinterfaceconstant{xscale}{xschaal}
@@ -1042,8 +1078,6 @@
\setinterfaceelement{complete}{volledige}
\setinterfaceelement{coupled}{gekoppelde}
\setinterfaceelement{currentlocal}{huidigelokale}
-\setinterfaceelement{emptyone}{leeg}
-\setinterfaceelement{emptytwo}{lege}
\setinterfaceelement{end}{eindvan}
\setinterfaceelement{endsetup}{in}
\setinterfaceelement{get}{haal}
@@ -1156,7 +1190,7 @@
\setinterfacecommand{defineframedtext}{definieerkadertekst}
\setinterfacecommand{definehbox}{definieerhbox}
\setinterfacecommand{definehead}{definieerkop}
-\setinterfacecommand{defineindenting}{doorspringen}
+\setinterfacecommand{defineindentedtext}{definieeringesprongentext}
\setinterfacecommand{defineinmargin}{definieerinmarge}
\setinterfacecommand{defineinteractionmenu}{definieerinteractiemenu}
\setinterfacecommand{defineitemgroup}{definieeritemgroep}
@@ -1352,7 +1386,6 @@
\setinterfacecommand{pagenumber}{paginanummer}
\setinterfacecommand{pageoffset}{paginaoffset}
\setinterfacecommand{pagereference}{paginareferentie}
-\setinterfacecommand{pagetype}{soortpagina}
\setinterfacecommand{paperheight}{papierhoogte}
\setinterfacecommand{paperwidth}{papierbreedte}
\setinterfacecommand{periods}{punten}
@@ -1468,7 +1501,7 @@
\setinterfacecommand{setupheads}{stelkoppenin}
\setinterfacecommand{setupheadtext}{stelkoptekstin}
\setinterfacecommand{setuphyphenmark}{stelkoppeltekenin}
-\setinterfacecommand{setupindentations}{steldoorspringenin}
+\setinterfacecommand{setupindentedtext}{stelingesprongentextin}
\setinterfacecommand{setupindenting}{stelinspringenin}
\setinterfacecommand{setupinmargin}{stelinmargein}
\setinterfacecommand{setupinteraction}{stelinteractiein}
diff --git a/Master/texmf-dist/tex/context/base/mult-pe.mkii b/Master/texmf-dist/tex/context/base/mult-pe.mkii
index 284fa40e8b0..5f38eb9285d 100644
--- a/Master/texmf-dist/tex/context/base/mult-pe.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-pe.mkii
@@ -4,6 +4,8 @@
%
\setinterfacevariable{Addition}{جمع}
\setinterfacevariable{Balloon}{بادکنک}
+\setinterfacevariable{Cap}{Cap}
+\setinterfacevariable{Capital}{Capital}
\setinterfacevariable{Character}{Character}
\setinterfacevariable{Characters}{Characters}
\setinterfacevariable{CloseDocument}{بستن‌نوشتار}
@@ -61,6 +63,9 @@
\setinterfacevariable{ViewerHelp}{کمک‌نمایشگر}
\setinterfacevariable{WEEKDAY}{روزهÙته}
\setinterfacevariable{WORD}{کلمه}
+\setinterfacevariable{WORDS}{WORDS}
+\setinterfacevariable{Word}{Word}
+\setinterfacevariable{Words}{Words}
\setinterfacevariable{abbreviation}{اختصار}
\setinterfacevariable{abbreviations}{اختصارات}
\setinterfacevariable{absolute}{قطعی}
@@ -275,6 +280,7 @@
\setinterfacevariable{marking}{نشانه‌گذاری}
\setinterfacevariable{mathalignment}{تنظیم‌ریاضی}
\setinterfacevariable{mathcases}{حالتهای‌ریاضی}
+\setinterfacevariable{mathematics}{ریاضی}
\setinterfacevariable{mathmatrix}{ماتریش‌ریاضی}
\setinterfacevariable{max}{بیشترین}
\setinterfacevariable{maxdepth}{maxdepth}
@@ -356,6 +362,7 @@
\setinterfacevariable{previousoddpage}{صÙحه‌Ùردقبلی}
\setinterfacevariable{previouspage}{صÙحه‌قبلی}
\setinterfacevariable{previoussubpage}{زیرصÙحه‌قبلی}
+\setinterfacevariable{print}{print}
\setinterfacevariable{printable}{قابل‌چاپ}
\setinterfacevariable{process}{پردازش}
\setinterfacevariable{product}{محصول}
@@ -363,6 +370,7 @@
\setinterfacevariable{project}{پروژه}
\setinterfacevariable{protected}{Ø­Ùاظت‌شده}
\setinterfacevariable{quadruple}{quadruple}
+\setinterfacevariable{quarterline}{quarterline}
\setinterfacevariable{quotation}{نقل‌قول}
\setinterfacevariable{quote}{نقل}
\setinterfacevariable{ran}{برد}
@@ -497,6 +505,8 @@
\setinterfacevariable{unavailable}{غیرموجود}
\setinterfacevariable{underbar}{میله‌زیر}
\setinterfacevariable{underbars}{میله‌‌های‌زیر}
+\setinterfacevariable{understrike}{understrike}
+\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unit}{واحد}
\setinterfacevariable{units}{واحدها}
\setinterfacevariable{unknown}{ناشناس}
@@ -516,6 +526,7 @@
\setinterfacevariable{white}{سÙید}
\setinterfacevariable{wide}{گسترده}
\setinterfacevariable{width}{عرض}
+\setinterfacevariable{word}{word}
\setinterfacevariable{xml}{xml}
\setinterfacevariable{year}{سال}
\setinterfacevariable{yes}{بله}
@@ -533,6 +544,7 @@
\setinterfaceconstant{alignsymbol}{alignsymbol}
\setinterfaceconstant{aligntitle}{عنوان‌تنظیم}
\setinterfaceconstant{alternative}{جایگزین}
+\setinterfaceconstant{anchor}{anchor}
\setinterfaceconstant{andtext}{andtext}
\setinterfaceconstant{apa}{apa}
\setinterfaceconstant{arrow}{پیکان}
@@ -552,6 +564,8 @@
\setinterfaceconstant{autohang}{آویزان‌خودکار}
\setinterfaceconstant{autostrut}{بست‌خودکار}
\setinterfaceconstant{autowidth}{عرض‌خودکار}
+\setinterfaceconstant{availableheight}{availableheight}
+\setinterfaceconstant{availablewidth}{availablewidth}
\setinterfaceconstant{axis}{محورها}
\setinterfaceconstant{background}{پس‌زمینه}
\setinterfaceconstant{backgroundcolor}{رنگ‌پس‌زمینه}
@@ -571,6 +585,7 @@
\setinterfaceconstant{blank}{خالی}
\setinterfaceconstant{blockway}{راه‌بلوک}
\setinterfaceconstant{bodyfont}{قلم‌بدنه}
+\setinterfaceconstant{boffset}{boffset}
\setinterfaceconstant{bookmark}{چوبخط}
\setinterfaceconstant{bottom}{پایین}
\setinterfaceconstant{bottomafter}{bottomafter}
@@ -602,6 +617,8 @@
\setinterfaceconstant{commandafter}{Ùرمان‌بعداز}
\setinterfaceconstant{commandbefore}{Ùرمان‌قبل‌از}
\setinterfaceconstant{commands}{Ùرمانها}
+\setinterfaceconstant{commentoffset}{commentoffset}
+\setinterfaceconstant{compact}{compact}
\setinterfaceconstant{component}{مولÙÙ‡}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{Ùشردن}
@@ -615,6 +632,7 @@
\setinterfaceconstant{coupling}{تزویج}
\setinterfaceconstant{couplingway}{روش‌تزویج}
\setinterfaceconstant{criterium}{criterium}
+\setinterfaceconstant{css}{css}
\setinterfaceconstant{current}{جاری}
\setinterfaceconstant{cutspace}{Ùضای‌برش}
\setinterfaceconstant{dash}{دش}
@@ -643,11 +661,13 @@
\setinterfaceconstant{editoretallimit}{editoretallimit}
\setinterfaceconstant{editoretaltext}{editoretaltext}
\setinterfaceconstant{empty}{تهی}
+\setinterfaceconstant{entities}{entities}
\setinterfaceconstant{entries}{entries}
\setinterfaceconstant{equalheight}{ارتÙاع‌یکسان}
\setinterfaceconstant{equalwidth}{عرض‌یکسان}
\setinterfaceconstant{escape}{Ùرار}
\setinterfaceconstant{evenmargin}{حاشیه‌زوج}
+\setinterfaceconstant{exitoffset}{labeloffset}
\setinterfaceconstant{expansion}{گسترش}
\setinterfaceconstant{export}{export}
\setinterfaceconstant{extras}{extras}
@@ -684,6 +704,7 @@
\setinterfaceconstant{global}{سراسری}
\setinterfaceconstant{grid}{توری}
\setinterfaceconstant{hang}{بیاویز}
+\setinterfaceconstant{hcompact}{hcompact}
\setinterfaceconstant{headalign}{headalign}
\setinterfaceconstant{headcolor}{رنگ‌سر}
\setinterfaceconstant{headcommand}{Ùرمان‌سر}
@@ -712,6 +733,7 @@
\setinterfaceconstant{inner}{داخلی}
\setinterfaceconstant{innermargin}{حاشیه‌داخلی}
\setinterfaceconstant{inputfile}{پرونده‌ورودی}
+\setinterfaceconstant{insidesection}{insidesection}
\setinterfaceconstant{intent}{intent}
\setinterfaceconstant{interaction}{پانل}
\setinterfaceconstant{interlinespace}{Ùضای‌بین‌خط}
@@ -724,8 +746,10 @@
\setinterfaceconstant{keys}{keys}
\setinterfaceconstant{keyword}{کلید‌واژه}
\setinterfaceconstant{label}{برچسب}
+\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{Ú†Ù¾}
\setinterfaceconstant{leftcolor}{رنگ‌چپ}
\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
@@ -754,6 +778,7 @@
\setinterfaceconstant{listtext}{متن‌لیست}
\setinterfaceconstant{local}{موضعی}
\setinterfaceconstant{location}{مکان}
+\setinterfaceconstant{loffset}{loffset}
\setinterfaceconstant{logo}{آرم}
\setinterfaceconstant{logos}{آرمها}
\setinterfaceconstant{marcolor}{رنگ‌حاش}
@@ -830,6 +855,7 @@
\setinterfaceconstant{page}{صÙحه}
\setinterfaceconstant{pageboundaries}{مرزهای‌صÙحه}
\setinterfaceconstant{pagecolor}{رنگ‌صÙحه}
+\setinterfaceconstant{pagecolormodel}{pagecolormodel}
\setinterfaceconstant{pagecommand}{Ùرمان‌صÙحه}
\setinterfaceconstant{pageconversion}{pageconversion}
\setinterfaceconstant{pageconversionset}{pageconversionset}
@@ -870,6 +896,7 @@
\setinterfaceconstant{preview}{پیش‌دید}
\setinterfaceconstant{previous}{قبلی}
\setinterfaceconstant{previousnumber}{شماره‌قبلی}
+\setinterfaceconstant{printable}{قابل‌چاپ}
\setinterfaceconstant{process}{پردازش}
\setinterfaceconstant{profile}{profile}
\setinterfaceconstant{pubsep}{pubsep}
@@ -882,6 +909,7 @@
\setinterfaceconstant{reference}{مرجع}
\setinterfaceconstant{referenceprefix}{referenceprefix}
\setinterfaceconstant{referencing}{مراجعه}
+\setinterfaceconstant{region}{region}
\setinterfaceconstant{regionin}{ناحیه‌درون}
\setinterfaceconstant{regionout}{ناحیه‌بیرون}
\setinterfaceconstant{repeat}{تکرار}
@@ -906,9 +934,11 @@
\setinterfaceconstant{rightsubsentence}{زیرجمله‌راست}
\setinterfaceconstant{righttext}{متن‌راست}
\setinterfaceconstant{rightwidth}{عرض‌راست}
+\setinterfaceconstant{roffset}{roffset}
\setinterfaceconstant{rotation}{دوران}
\setinterfaceconstant{rule}{خط}
\setinterfaceconstant{rulecolor}{رنگ‌خط}
+\setinterfaceconstant{rulecommand}{rulecommand}
\setinterfaceconstant{rulethickness}{ضخامت‌خط}
\setinterfaceconstant{samepage}{همان‌صÙحه}
\setinterfaceconstant{sample}{نمونه}
@@ -966,6 +996,7 @@
\setinterfaceconstant{subtitle}{زیرعنوان}
\setinterfaceconstant{suffix}{پسوند}
\setinterfaceconstant{suffixseparator}{suffixseparator}
+\setinterfaceconstant{suffixstopper}{suffixstopper}
\setinterfaceconstant{surnamesep}{surnamesep}
\setinterfaceconstant{sx}{sx}
\setinterfaceconstant{sy}{sy}
@@ -983,6 +1014,7 @@
\setinterfaceconstant{textcolor}{رنگ‌متن}
\setinterfaceconstant{textcommand}{Ùرمان‌متن}
\setinterfaceconstant{textdistance}{Ùاصله‌متن}
+\setinterfaceconstant{textheight}{ارتÙاع‌متن}
\setinterfaceconstant{textlayer}{لایه‌متن}
\setinterfaceconstant{textmargin}{حاشیه‌متن}
\setinterfaceconstant{textmethod}{روش‌متن}
@@ -1000,6 +1032,7 @@
\setinterfaceconstant{titleright}{عنوان‌راست}
\setinterfaceconstant{titlestyle}{سبک‌عنوان}
\setinterfaceconstant{to}{به}
+\setinterfaceconstant{toffset}{toffset}
\setinterfaceconstant{tolerance}{بردباری}
\setinterfaceconstant{top}{بالا}
\setinterfaceconstant{topdistance}{Ùاصله‌بالا}
@@ -1016,6 +1049,8 @@
\setinterfaceconstant{validate}{تاییداعتبار}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{vcommand}
+\setinterfaceconstant{vcompact}{vcompact}
+\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{Ø¢Ùست‌عم}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{voffset}{Ø¢Ùست‌ع}
@@ -1025,6 +1060,7 @@
\setinterfaceconstant{white}{سÙید}
\setinterfaceconstant{width}{عرض}
\setinterfaceconstant{xfactor}{Ùاکتورایکس}
+\setinterfaceconstant{xhtml}{xhtml}
\setinterfaceconstant{xmax}{xmax}
\setinterfaceconstant{xoffset}{Ø¢Ùست‌ایکس}
\setinterfaceconstant{xscale}{مقیاس‌ایکس}
@@ -1042,8 +1078,6 @@
\setinterfaceelement{complete}{کامل}
\setinterfaceelement{coupled}{مزدوج}
\setinterfaceelement{currentlocal}{موضعی‌جاری}
-\setinterfaceelement{emptyone}{یک‌خالی}
-\setinterfaceelement{emptytwo}{دوخالی}
\setinterfaceelement{end}{انتها}
\setinterfaceelement{endsetup}{انتهای‌بارگذاری}
\setinterfaceelement{get}{بگیر}
@@ -1156,7 +1190,7 @@
\setinterfacecommand{defineframedtext}{تعریÙ‌متن‌قالبی}
\setinterfacecommand{definehbox}{تعریÙ‌جعبه‌‌اÙÙ‚ÛŒ}
\setinterfacecommand{definehead}{تعریÙ‌سر}
-\setinterfacecommand{defineindenting}{تعریÙ‌تورÙتگی}
+\setinterfacecommand{defineindentedtext}{defineindentedtext}
\setinterfacecommand{defineinmargin}{تعریÙ‌درون‌حاشیه}
\setinterfacecommand{defineinteractionmenu}{تعریÙ‌منوی‌پانل}
\setinterfacecommand{defineitemgroup}{تعریÙ‌گروه‌آیتم}
@@ -1352,7 +1386,6 @@
\setinterfacecommand{pagenumber}{شماره‌صÙحه}
\setinterfacecommand{pageoffset}{Ø¢Ùست‌صÙحه}
\setinterfacecommand{pagereference}{مرجع‌صÙحه}
-\setinterfacecommand{pagetype}{نوع‌صÙحه}
\setinterfacecommand{paperheight}{ارتÙاع‌برگ}
\setinterfacecommand{paperwidth}{عرض‌برگ}
\setinterfacecommand{periods}{نقطه‌ها}
@@ -1468,7 +1501,7 @@
\setinterfacecommand{setupheads}{بارگذاری‌سرها}
\setinterfacecommand{setupheadtext}{بارگذاری‌متن‌سر}
\setinterfacecommand{setuphyphenmark}{بارگذاری‌نشانه‌شکستن}
-\setinterfacecommand{setupindentations}{بارگذاری‌تورÙتگیها}
+\setinterfacecommand{setupindentedtext}{setupindentedtext}
\setinterfacecommand{setupindenting}{بارگذاری‌تورÙتگی}
\setinterfacecommand{setupinmargin}{بارگذاری‌درون‌حاشیه}
\setinterfacecommand{setupinteraction}{بارگذاری‌پانل}
diff --git a/Master/texmf-dist/tex/context/base/mult-prm.lua b/Master/texmf-dist/tex/context/base/mult-prm.lua
new file mode 100644
index 00000000000..1775fe0bc5c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mult-prm.lua
@@ -0,0 +1,1114 @@
+return {
+ ["aleph"]={
+ "AlephVersion",
+ "Alephminorversion",
+ "Alephrevision",
+ "Alephversion",
+ "Omegaminorversion",
+ "Omegarevision",
+ "Omegaversion",
+ "boxdir",
+ "pagebottomoffset",
+ "pagerightoffset",
+ },
+ ["etex"]={
+ "botmarks",
+ "clubpenalties",
+ "currentgrouplevel",
+ "currentgrouptype",
+ "currentifbranch",
+ "currentiflevel",
+ "currentiftype",
+ "detokenize",
+ "dimexpr",
+ "displaywidowpenalties",
+ "eTeXVersion",
+ "eTeXminorversion",
+ "eTeXrevision",
+ "eTeXversion",
+ "everyeof",
+ "firstmarks",
+ "fontchardp",
+ "fontcharht",
+ "fontcharic",
+ "fontcharwd",
+ "glueexpr",
+ "glueshrink",
+ "glueshrinkorder",
+ "gluestretch",
+ "gluestretchorder",
+ "gluetomu",
+ "ifcsname",
+ "ifdefined",
+ "iffontchar",
+ "interactionmode",
+ "interlinepenalties",
+ "lastlinefit",
+ "lastnodetype",
+ "marks",
+ "muexpr",
+ "mutoglue",
+ "numexpr",
+ "pagediscards",
+ "parshapedimen",
+ "parshapeindent",
+ "parshapelength",
+ "predisplaydirection",
+ "protected",
+ "readline",
+ "savinghyphcodes",
+ "savingvdiscards",
+ "scantokens",
+ "showgroups",
+ "showifs",
+ "showtokens",
+ "splitbotmarks",
+ "splitdiscards",
+ "splitfirstmarks",
+ "topmarks",
+ "tracingassigns",
+ "tracinggroups",
+ "tracingifs",
+ "tracingnesting",
+ "tracingscantokens",
+ "unexpanded",
+ "unless",
+ "widowpenalties",
+ },
+ ["luatex"]={
+ "Udelcode",
+ "Udelcodenum",
+ "Udelimiter",
+ "Udelimiterover",
+ "Udelimiterunder",
+ "Umathaccent",
+ "Umathaccents",
+ "Umathaxis",
+ "Umathbinbinspacing",
+ "Umathbinclosespacing",
+ "Umathbininnerspacing",
+ "Umathbinopenspacing",
+ "Umathbinopspacing",
+ "Umathbinordspacing",
+ "Umathbinpunctspacing",
+ "Umathbinrelspacing",
+ "Umathbotaccent",
+ "Umathchar",
+ "Umathchardef",
+ "Umathcharnum",
+ "Umathclosebinspacing",
+ "Umathcloseclosespacing",
+ "Umathcloseinnerspacing",
+ "Umathcloseopenspacing",
+ "Umathcloseopspacing",
+ "Umathcloseordspacing",
+ "Umathclosepunctspacing",
+ "Umathcloserelspacing",
+ "Umathcode",
+ "Umathcodenum",
+ "Umathconnectoroverlapmin",
+ "Umathfractiondelsize",
+ "Umathfractiondenomdown",
+ "Umathfractiondenomvgap",
+ "Umathfractionnumup",
+ "Umathfractionnumvgap",
+ "Umathfractionrule",
+ "Umathinnerbinspacing",
+ "Umathinnerclosespacing",
+ "Umathinnerinnerspacing",
+ "Umathinneropenspacing",
+ "Umathinneropspacing",
+ "Umathinnerordspacing",
+ "Umathinnerpunctspacing",
+ "Umathinnerrelspacing",
+ "Umathlimitabovebgap",
+ "Umathlimitabovekern",
+ "Umathlimitabovevgap",
+ "Umathlimitbelowbgap",
+ "Umathlimitbelowkern",
+ "Umathlimitbelowvgap",
+ "Umathopbinspacing",
+ "Umathopclosespacing",
+ "Umathopenbinspacing",
+ "Umathopenclosespacing",
+ "Umathopeninnerspacing",
+ "Umathopenopenspacing",
+ "Umathopenopspacing",
+ "Umathopenordspacing",
+ "Umathopenpunctspacing",
+ "Umathopenrelspacing",
+ "Umathoperatorsize",
+ "Umathopinnerspacing",
+ "Umathopopenspacing",
+ "Umathopopspacing",
+ "Umathopordspacing",
+ "Umathoppunctspacing",
+ "Umathoprelspacing",
+ "Umathordbinspacing",
+ "Umathordclosespacing",
+ "Umathordinnerspacing",
+ "Umathordopenspacing",
+ "Umathordopspacing",
+ "Umathordordspacing",
+ "Umathordpunctspacing",
+ "Umathordrelspacing",
+ "Umathoverbarkern",
+ "Umathoverbarrule",
+ "Umathoverbarvgap",
+ "Umathoverdelimiterbgap",
+ "Umathoverdelimitervgap",
+ "Umathpunctbinspacing",
+ "Umathpunctclosespacing",
+ "Umathpunctinnerspacing",
+ "Umathpunctopenspacing",
+ "Umathpunctopspacing",
+ "Umathpunctordspacing",
+ "Umathpunctpunctspacing",
+ "Umathpunctrelspacing",
+ "Umathquad",
+ "Umathradicaldegreeafter",
+ "Umathradicaldegreebefore",
+ "Umathradicaldegreeraise",
+ "Umathradicalkern",
+ "Umathradicalrule",
+ "Umathradicalvgap",
+ "Umathrelbinspacing",
+ "Umathrelclosespacing",
+ "Umathrelinnerspacing",
+ "Umathrelopenspacing",
+ "Umathrelopspacing",
+ "Umathrelordspacing",
+ "Umathrelpunctspacing",
+ "Umathrelrelspacing",
+ "Umathspaceafterscript",
+ "Umathstackdenomdown",
+ "Umathstacknumup",
+ "Umathstackvgap",
+ "Umathsubshiftdown",
+ "Umathsubshiftdrop",
+ "Umathsubsupshiftdown",
+ "Umathsubsupvgap",
+ "Umathsubtopmax",
+ "Umathsupbottommin",
+ "Umathsupshiftdrop",
+ "Umathsupshiftup",
+ "Umathsupsubbottommax",
+ "Umathunderbarkern",
+ "Umathunderbarrule",
+ "Umathunderbarvgap",
+ "Umathunderdelimiterbgap",
+ "Umathunderdelimitervgap",
+ "Uoverdelimiter",
+ "Uradical",
+ "Uroot",
+ "Ustack",
+ "Ustartdisplaymath",
+ "Ustartmath",
+ "Ustopdisplaymath",
+ "Ustopmath",
+ "Usubscript",
+ "Usuperscript",
+ "Uunderdelimiter",
+ "alignmark",
+ "aligntab",
+ "attribute",
+ "attributedef",
+ "catcodetable",
+ "clearmarks",
+ "crampeddisplaystyle",
+ "crampedscriptscriptstyle",
+ "crampedscriptstyle",
+ "crampedtextstyle",
+ "fontid",
+ "formatname",
+ "gleaders",
+ "ifabsdim",
+ "ifabsnum",
+ "ifprimitive",
+ "initcatcodetable",
+ "latelua",
+ "luaescapestring",
+ "luastartup",
+ "luatexdatestamp",
+ "luatexrevision",
+ "luatexversion",
+ "mathstyle",
+ "nokerns",
+ "noligs",
+ "outputbox",
+ "pageleftoffset",
+ "pagetopoffset",
+ "postexhyphenchar",
+ "posthyphenchar",
+ "preexhyphenchar",
+ "prehyphenchar",
+ "primitive",
+ "savecatcodetable",
+ "scantextokens",
+ "suppressfontnotfounderror",
+ "suppressifcsnameerror",
+ "suppresslongerror",
+ "suppressoutererror",
+ "synctex",
+ },
+ ["omega"]={
+ "OmegaVersion",
+ "bodydir",
+ "chardp",
+ "charht",
+ "charit",
+ "charwd",
+ "leftghost",
+ "localbrokenpenalty",
+ "localinterlinepenalty",
+ "localleftbox",
+ "localrightbox",
+ "mathdir",
+ "odelcode",
+ "odelimiter",
+ "omathaccent",
+ "omathchar",
+ "omathchardef",
+ "omathcode",
+ "oradical",
+ "pagedir",
+ "pageheight",
+ "pagewidth",
+ "pardir",
+ "rightghost",
+ "textdir",
+ },
+ ["pdftex"]={
+ "efcode",
+ "expanded",
+ "ifincsname",
+ "ifpdfabsdim",
+ "ifpdfabsnum",
+ "ifpdfprimitive",
+ "leftmarginkern",
+ "letterspacefont",
+ "lpcode",
+ "pdfadjustspacing",
+ "pdfannot",
+ "pdfcatalog",
+ "pdfcolorstack",
+ "pdfcolorstackinit",
+ "pdfcompresslevel",
+ "pdfcopyfont",
+ "pdfcreationdate",
+ "pdfdecimaldigits",
+ "pdfdest",
+ "pdfdestmargin",
+ "pdfdraftmode",
+ "pdfeachlinedepth",
+ "pdfeachlineheight",
+ "pdfendlink",
+ "pdfendthread",
+ "pdffirstlineheight",
+ "pdffontattr",
+ "pdffontexpand",
+ "pdffontname",
+ "pdffontobjnum",
+ "pdffontsize",
+ "pdfgamma",
+ "pdfgentounicode",
+ "pdfglyphtounicode",
+ "pdfhorigin",
+ "pdfignoreddimen",
+ "pdfimageapplygamma",
+ "pdfimagegamma",
+ "pdfimagehicolor",
+ "pdfimageresolution",
+ "pdfincludechars",
+ "pdfinclusioncopyfonts",
+ "pdfinclusionerrorlevel",
+ "pdfinfo",
+ "pdfinsertht",
+ "pdflastannot",
+ "pdflastlinedepth",
+ "pdflastlink",
+ "pdflastobj",
+ "pdflastxform",
+ "pdflastximage",
+ "pdflastximagecolordepth",
+ "pdflastximagepages",
+ "pdflastxpos",
+ "pdflastypos",
+ "pdflinkmargin",
+ "pdfliteral",
+ "pdfmapfile",
+ "pdfmapline",
+ "pdfminorversion",
+ "pdfnames",
+ "pdfnoligatures",
+ "pdfnormaldeviate",
+ "pdfobj",
+ "pdfobjcompresslevel",
+ "pdfoptionpdfminorversion",
+ "pdfoutline",
+ "pdfoutput",
+ "pdfpageattr",
+ "pdfpagebox",
+ "pdfpageheight",
+ "pdfpageref",
+ "pdfpageresources",
+ "pdfpagesattr",
+ "pdfpagewidth",
+ "pdfpkmode",
+ "pdfpkresolution",
+ "pdfprimitive",
+ "pdfprotrudechars",
+ "pdfpxdimen",
+ "pdfrandomseed",
+ "pdfrefobj",
+ "pdfrefxform",
+ "pdfrefximage",
+ "pdfreplacefont",
+ "pdfrestore",
+ "pdfretval",
+ "pdfsave",
+ "pdfsavepos",
+ "pdfsetmatrix",
+ "pdfsetrandomseed",
+ "pdfstartlink",
+ "pdfstartthread",
+ "pdftexbanner",
+ "pdftexrevision",
+ "pdftexversion",
+ "pdfthread",
+ "pdfthreadmargin",
+ "pdftracingfonts",
+ "pdftrailer",
+ "pdfuniformdeviate",
+ "pdfuniqueresname",
+ "pdfvorigin",
+ "pdfxform",
+ "pdfxformattr",
+ "pdfxformname",
+ "pdfxformresources",
+ "pdfximage",
+ "pdfximagebbox",
+ "quitvmode",
+ "rightmarginkern",
+ "rpcode",
+ "tagcode",
+ },
+ ["tex"]={
+ "-",
+ "/",
+ "AlephVersion",
+ "Alephminorversion",
+ "Alephrevision",
+ "Alephversion",
+ "OmegaVersion",
+ "Omegaminorversion",
+ "Omegarevision",
+ "Omegaversion",
+ "Udelcode",
+ "Udelcodenum",
+ "Udelimiter",
+ "Udelimiterover",
+ "Udelimiterunder",
+ "Umathaccent",
+ "Umathaccents",
+ "Umathaxis",
+ "Umathbinbinspacing",
+ "Umathbinclosespacing",
+ "Umathbininnerspacing",
+ "Umathbinopenspacing",
+ "Umathbinopspacing",
+ "Umathbinordspacing",
+ "Umathbinpunctspacing",
+ "Umathbinrelspacing",
+ "Umathbotaccent",
+ "Umathchar",
+ "Umathchardef",
+ "Umathcharnum",
+ "Umathclosebinspacing",
+ "Umathcloseclosespacing",
+ "Umathcloseinnerspacing",
+ "Umathcloseopenspacing",
+ "Umathcloseopspacing",
+ "Umathcloseordspacing",
+ "Umathclosepunctspacing",
+ "Umathcloserelspacing",
+ "Umathcode",
+ "Umathcodenum",
+ "Umathconnectoroverlapmin",
+ "Umathfractiondelsize",
+ "Umathfractiondenomdown",
+ "Umathfractiondenomvgap",
+ "Umathfractionnumup",
+ "Umathfractionnumvgap",
+ "Umathfractionrule",
+ "Umathinnerbinspacing",
+ "Umathinnerclosespacing",
+ "Umathinnerinnerspacing",
+ "Umathinneropenspacing",
+ "Umathinneropspacing",
+ "Umathinnerordspacing",
+ "Umathinnerpunctspacing",
+ "Umathinnerrelspacing",
+ "Umathlimitabovebgap",
+ "Umathlimitabovekern",
+ "Umathlimitabovevgap",
+ "Umathlimitbelowbgap",
+ "Umathlimitbelowkern",
+ "Umathlimitbelowvgap",
+ "Umathopbinspacing",
+ "Umathopclosespacing",
+ "Umathopenbinspacing",
+ "Umathopenclosespacing",
+ "Umathopeninnerspacing",
+ "Umathopenopenspacing",
+ "Umathopenopspacing",
+ "Umathopenordspacing",
+ "Umathopenpunctspacing",
+ "Umathopenrelspacing",
+ "Umathoperatorsize",
+ "Umathopinnerspacing",
+ "Umathopopenspacing",
+ "Umathopopspacing",
+ "Umathopordspacing",
+ "Umathoppunctspacing",
+ "Umathoprelspacing",
+ "Umathordbinspacing",
+ "Umathordclosespacing",
+ "Umathordinnerspacing",
+ "Umathordopenspacing",
+ "Umathordopspacing",
+ "Umathordordspacing",
+ "Umathordpunctspacing",
+ "Umathordrelspacing",
+ "Umathoverbarkern",
+ "Umathoverbarrule",
+ "Umathoverbarvgap",
+ "Umathoverdelimiterbgap",
+ "Umathoverdelimitervgap",
+ "Umathpunctbinspacing",
+ "Umathpunctclosespacing",
+ "Umathpunctinnerspacing",
+ "Umathpunctopenspacing",
+ "Umathpunctopspacing",
+ "Umathpunctordspacing",
+ "Umathpunctpunctspacing",
+ "Umathpunctrelspacing",
+ "Umathquad",
+ "Umathradicaldegreeafter",
+ "Umathradicaldegreebefore",
+ "Umathradicaldegreeraise",
+ "Umathradicalkern",
+ "Umathradicalrule",
+ "Umathradicalvgap",
+ "Umathrelbinspacing",
+ "Umathrelclosespacing",
+ "Umathrelinnerspacing",
+ "Umathrelopenspacing",
+ "Umathrelopspacing",
+ "Umathrelordspacing",
+ "Umathrelpunctspacing",
+ "Umathrelrelspacing",
+ "Umathspaceafterscript",
+ "Umathstackdenomdown",
+ "Umathstacknumup",
+ "Umathstackvgap",
+ "Umathsubshiftdown",
+ "Umathsubshiftdrop",
+ "Umathsubsupshiftdown",
+ "Umathsubsupvgap",
+ "Umathsubtopmax",
+ "Umathsupbottommin",
+ "Umathsupshiftdrop",
+ "Umathsupshiftup",
+ "Umathsupsubbottommax",
+ "Umathunderbarkern",
+ "Umathunderbarrule",
+ "Umathunderbarvgap",
+ "Umathunderdelimiterbgap",
+ "Umathunderdelimitervgap",
+ "Uoverdelimiter",
+ "Uradical",
+ "Uroot",
+ "Ustack",
+ "Ustartdisplaymath",
+ "Ustartmath",
+ "Ustopdisplaymath",
+ "Ustopmath",
+ "Usubscript",
+ "Usuperscript",
+ "Uunderdelimiter",
+ "above",
+ "abovedisplayshortskip",
+ "abovedisplayskip",
+ "abovewithdelims",
+ "accent",
+ "adjdemerits",
+ "advance",
+ "afterassignment",
+ "aftergroup",
+ "alignmark",
+ "aligntab",
+ "atop",
+ "atopwithdelims",
+ "attribute",
+ "attributedef",
+ "badness",
+ "baselineskip",
+ "batchmode",
+ "begingroup",
+ "belowdisplayshortskip",
+ "belowdisplayskip",
+ "binoppenalty",
+ "bodydir",
+ "botmark",
+ "botmarks",
+ "box",
+ "boxdir",
+ "boxmaxdepth",
+ "brokenpenalty",
+ "catcode",
+ "catcodetable",
+ "char",
+ "chardef",
+ "chardp",
+ "charht",
+ "charit",
+ "charwd",
+ "cleaders",
+ "clearmarks",
+ "closein",
+ "closeout",
+ "clubpenalties",
+ "clubpenalty",
+ "copy",
+ "count",
+ "countdef",
+ "cr",
+ "crampeddisplaystyle",
+ "crampedscriptscriptstyle",
+ "crampedscriptstyle",
+ "crampedtextstyle",
+ "crcr",
+ "csname",
+ "currentgrouplevel",
+ "currentgrouptype",
+ "currentifbranch",
+ "currentiflevel",
+ "currentiftype",
+ "day",
+ "deadcycles",
+ "def",
+ "defaulthyphenchar",
+ "defaultskewchar",
+ "delcode",
+ "delimiter",
+ "delimiterfactor",
+ "delimitershortfall",
+ "detokenize",
+ "dimen",
+ "dimendef",
+ "dimexpr",
+ "directlua",
+ "discretionary",
+ "displayindent",
+ "displaylimits",
+ "displaystyle",
+ "displaywidowpenalties",
+ "displaywidowpenalty",
+ "displaywidth",
+ "divide",
+ "doublehyphendemerits",
+ "dp",
+ "dump",
+ "eTeXVersion",
+ "eTeXminorversion",
+ "eTeXrevision",
+ "eTeXversion",
+ "edef",
+ "efcode",
+ "else",
+ "emergencystretch",
+ "end",
+ "endcsname",
+ "endgroup",
+ "endinput",
+ "endlinechar",
+ "eqno",
+ "errhelp",
+ "errmessage",
+ "errorcontextlines",
+ "errorstopmode",
+ "escapechar",
+ "everycr",
+ "everydisplay",
+ "everyeof",
+ "everyhbox",
+ "everyjob",
+ "everymath",
+ "everypar",
+ "everyvbox",
+ "exhyphenchar",
+ "exhyphenpenalty",
+ "expandafter",
+ "expanded",
+ "fam",
+ "fi",
+ "finalhyphendemerits",
+ "firstmark",
+ "firstmarks",
+ "floatingpenalty",
+ "font",
+ "fontchardp",
+ "fontcharht",
+ "fontcharic",
+ "fontcharwd",
+ "fontdimen",
+ "fontid",
+ "fontname",
+ "formatname",
+ "futurelet",
+ "gdef",
+ "gleaders",
+ "global",
+ "globaldefs",
+ "glueexpr",
+ "glueshrink",
+ "glueshrinkorder",
+ "gluestretch",
+ "gluestretchorder",
+ "gluetomu",
+ "halign",
+ "hangafter",
+ "hangindent",
+ "hbadness",
+ "hbox",
+ "hfil",
+ "hfill",
+ "hfilneg",
+ "hfuzz",
+ "hoffset",
+ "holdinginserts",
+ "hrule",
+ "hsize",
+ "hskip",
+ "hss",
+ "ht",
+ "hyphenation",
+ "hyphenchar",
+ "hyphenpenalty",
+ "if",
+ "ifabsdim",
+ "ifabsnum",
+ "ifcase",
+ "ifcat",
+ "ifcsname",
+ "ifdefined",
+ "ifdim",
+ "ifeof",
+ "iffalse",
+ "iffontchar",
+ "ifhbox",
+ "ifhmode",
+ "ifincsname",
+ "ifinner",
+ "ifmmode",
+ "ifnum",
+ "ifodd",
+ "ifpdfabsdim",
+ "ifpdfabsnum",
+ "ifpdfprimitive",
+ "ifprimitive",
+ "iftrue",
+ "ifvbox",
+ "ifvmode",
+ "ifvoid",
+ "ifx",
+ "ignorespaces",
+ "immediate",
+ "indent",
+ "initcatcodetable",
+ "input",
+ "inputlineno",
+ "insert",
+ "insertpenalties",
+ "interactionmode",
+ "interlinepenalties",
+ "interlinepenalty",
+ "jobname",
+ "kern",
+ "language",
+ "lastbox",
+ "lastkern",
+ "lastlinefit",
+ "lastnodetype",
+ "lastpenalty",
+ "lastskip",
+ "latelua",
+ "lccode",
+ "leaders",
+ "left",
+ "leftghost",
+ "lefthyphenmin",
+ "leftmarginkern",
+ "leftskip",
+ "leqno",
+ "let",
+ "letterspacefont",
+ "limits",
+ "linepenalty",
+ "lineskip",
+ "lineskiplimit",
+ "localbrokenpenalty",
+ "localinterlinepenalty",
+ "localleftbox",
+ "localrightbox",
+ "long",
+ "looseness",
+ "lower",
+ "lowercase",
+ "lpcode",
+ "luaescapestring",
+ "luastartup",
+ "luatexdatestamp",
+ "luatexrevision",
+ "luatexversion",
+ "mag",
+ "mark",
+ "marks",
+ "mathaccent",
+ "mathbin",
+ "mathchar",
+ "mathchardef",
+ "mathchoice",
+ "mathclose",
+ "mathcode",
+ "mathdir",
+ "mathinner",
+ "mathop",
+ "mathopen",
+ "mathord",
+ "mathpunct",
+ "mathrel",
+ "mathstyle",
+ "mathsurround",
+ "maxdeadcycles",
+ "maxdepth",
+ "meaning",
+ "medmuskip",
+ "message",
+ "middle",
+ "mkern",
+ "month",
+ "moveleft",
+ "moveright",
+ "mskip",
+ "muexpr",
+ "multiply",
+ "muskip",
+ "muskipdef",
+ "mutoglue",
+ "newlinechar",
+ "noalign",
+ "noboundary",
+ "noexpand",
+ "noindent",
+ "nokerns",
+ "noligs",
+ "nolimits",
+ "nolocaldirs",
+ "nolocalwhatsits",
+ "nonscript",
+ "nonstopmode",
+ "nulldelimiterspace",
+ "nullfont",
+ "number",
+ "numexpr",
+ "odelcode",
+ "odelimiter",
+ "omathaccent",
+ "omathchar",
+ "omathchardef",
+ "omathcode",
+ "omit",
+ "openin",
+ "openout",
+ "or",
+ "oradical",
+ "outer",
+ "output",
+ "outputbox",
+ "outputpenalty",
+ "over",
+ "overfullrule",
+ "overline",
+ "overwithdelims",
+ "pagebottomoffset",
+ "pagedepth",
+ "pagedir",
+ "pagediscards",
+ "pagefilllstretch",
+ "pagefillstretch",
+ "pagefilstretch",
+ "pagegoal",
+ "pageheight",
+ "pageleftoffset",
+ "pagerightoffset",
+ "pageshrink",
+ "pagestretch",
+ "pagetopoffset",
+ "pagetotal",
+ "pagewidth",
+ "par",
+ "pardir",
+ "parfillskip",
+ "parindent",
+ "parshape",
+ "parshapedimen",
+ "parshapeindent",
+ "parshapelength",
+ "parskip",
+ "patterns",
+ "pausing",
+ "pdfadjustspacing",
+ "pdfannot",
+ "pdfcatalog",
+ "pdfcolorstack",
+ "pdfcolorstackinit",
+ "pdfcompresslevel",
+ "pdfcopyfont",
+ "pdfcreationdate",
+ "pdfdecimaldigits",
+ "pdfdest",
+ "pdfdestmargin",
+ "pdfdraftmode",
+ "pdfeachlinedepth",
+ "pdfeachlineheight",
+ "pdfendlink",
+ "pdfendthread",
+ "pdffirstlineheight",
+ "pdffontattr",
+ "pdffontexpand",
+ "pdffontname",
+ "pdffontobjnum",
+ "pdffontsize",
+ "pdfgamma",
+ "pdfgentounicode",
+ "pdfglyphtounicode",
+ "pdfhorigin",
+ "pdfignoreddimen",
+ "pdfimageapplygamma",
+ "pdfimagegamma",
+ "pdfimagehicolor",
+ "pdfimageresolution",
+ "pdfincludechars",
+ "pdfinclusioncopyfonts",
+ "pdfinclusionerrorlevel",
+ "pdfinfo",
+ "pdfinsertht",
+ "pdflastannot",
+ "pdflastlinedepth",
+ "pdflastlink",
+ "pdflastobj",
+ "pdflastxform",
+ "pdflastximage",
+ "pdflastximagecolordepth",
+ "pdflastximagepages",
+ "pdflastxpos",
+ "pdflastypos",
+ "pdflinkmargin",
+ "pdfliteral",
+ "pdfmapfile",
+ "pdfmapline",
+ "pdfminorversion",
+ "pdfnames",
+ "pdfnoligatures",
+ "pdfnormaldeviate",
+ "pdfobj",
+ "pdfobjcompresslevel",
+ "pdfoptionpdfminorversion",
+ "pdfoutline",
+ "pdfoutput",
+ "pdfpageattr",
+ "pdfpagebox",
+ "pdfpageheight",
+ "pdfpageref",
+ "pdfpageresources",
+ "pdfpagesattr",
+ "pdfpagewidth",
+ "pdfpkmode",
+ "pdfpkresolution",
+ "pdfprimitive",
+ "pdfprotrudechars",
+ "pdfpxdimen",
+ "pdfrandomseed",
+ "pdfrefobj",
+ "pdfrefxform",
+ "pdfrefximage",
+ "pdfreplacefont",
+ "pdfrestore",
+ "pdfretval",
+ "pdfsave",
+ "pdfsavepos",
+ "pdfsetmatrix",
+ "pdfsetrandomseed",
+ "pdfstartlink",
+ "pdfstartthread",
+ "pdftexbanner",
+ "pdftexrevision",
+ "pdftexversion",
+ "pdfthread",
+ "pdfthreadmargin",
+ "pdftracingfonts",
+ "pdftrailer",
+ "pdfuniformdeviate",
+ "pdfuniqueresname",
+ "pdfvorigin",
+ "pdfxform",
+ "pdfxformattr",
+ "pdfxformname",
+ "pdfxformresources",
+ "pdfximage",
+ "pdfximagebbox",
+ "penalty",
+ "postdisplaypenalty",
+ "postexhyphenchar",
+ "posthyphenchar",
+ "predisplaydirection",
+ "predisplaypenalty",
+ "predisplaysize",
+ "preexhyphenchar",
+ "prehyphenchar",
+ "pretolerance",
+ "prevdepth",
+ "prevgraf",
+ "primitive",
+ "protected",
+ "quitvmode",
+ "radical",
+ "raise",
+ "read",
+ "readline",
+ "relax",
+ "relpenalty",
+ "right",
+ "rightghost",
+ "righthyphenmin",
+ "rightmarginkern",
+ "rightskip",
+ "romannumeral",
+ "rpcode",
+ "savecatcodetable",
+ "savinghyphcodes",
+ "savingvdiscards",
+ "scantextokens",
+ "scantokens",
+ "scriptfont",
+ "scriptscriptfont",
+ "scriptscriptstyle",
+ "scriptspace",
+ "scriptstyle",
+ "scrollmode",
+ "setbox",
+ "setlanguage",
+ "sfcode",
+ "shipout",
+ "show",
+ "showbox",
+ "showboxbreadth",
+ "showboxdepth",
+ "showgroups",
+ "showifs",
+ "showlists",
+ "showthe",
+ "showtokens",
+ "skewchar",
+ "skip",
+ "skipdef",
+ "spacefactor",
+ "spaceskip",
+ "span",
+ "special",
+ "splitbotmark",
+ "splitbotmarks",
+ "splitdiscards",
+ "splitfirstmark",
+ "splitfirstmarks",
+ "splitmaxdepth",
+ "splittopskip",
+ "string",
+ "suppressfontnotfounderror",
+ "suppressifcsnameerror",
+ "suppresslongerror",
+ "suppressoutererror",
+ "synctex",
+ "tabskip",
+ "tagcode",
+ "textdir",
+ "textfont",
+ "textstyle",
+ "the",
+ "thickmuskip",
+ "thinmuskip",
+ "time",
+ "toks",
+ "toksdef",
+ "tolerance",
+ "topmark",
+ "topmarks",
+ "topskip",
+ "tracingassigns",
+ "tracingcommands",
+ "tracinggroups",
+ "tracingifs",
+ "tracinglostchars",
+ "tracingmacros",
+ "tracingnesting",
+ "tracingonline",
+ "tracingoutput",
+ "tracingpages",
+ "tracingparagraphs",
+ "tracingrestores",
+ "tracingscantokens",
+ "tracingstats",
+ "uccode",
+ "uchyph",
+ "underline",
+ "unexpanded",
+ "unhbox",
+ "unhcopy",
+ "unkern",
+ "unless",
+ "unpenalty",
+ "unskip",
+ "unvbox",
+ "unvcopy",
+ "uppercase",
+ "vadjust",
+ "valign",
+ "vbadness",
+ "vbox",
+ "vcenter",
+ "vfil",
+ "vfill",
+ "vfilneg",
+ "vfuzz",
+ "voffset",
+ "vrule",
+ "vsize",
+ "vskip",
+ "vsplit",
+ "vss",
+ "vtop",
+ "wd",
+ "widowpenalties",
+ "widowpenalty",
+ "write",
+ "xdef",
+ "xleaders",
+ "xspaceskip",
+ "year",
+ },
+ ["xetex"]={
+ "XeTeXversion",
+ },
+} \ No newline at end of file
diff --git a/Master/texmf-dist/tex/context/base/mult-prm.mkiv b/Master/texmf-dist/tex/context/base/mult-prm.mkiv
new file mode 100644
index 00000000000..7e5bc1edda7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mult-prm.mkiv
@@ -0,0 +1,63 @@
+\startluacode
+
+ context.starttext()
+
+ function table.sorted(t)
+ table.sort(t)
+ return t
+ end
+
+ local missing = {
+ tex = {
+ "def", "catcode", "futurelet", "chardef",
+ "voffset", "hoffset",
+ "numexpr", "dimexpr",
+ "write", "dump", "skipdef,"
+ },
+ etex = {
+ "savingvdiscards",
+ },
+ pdftex = {
+ },
+ luatex = {
+ },
+ aleph = {
+ },
+ omega = {
+ },
+ xetex = {
+ "XeTeXversion",
+ },
+ plain = {
+ "TeX",
+ "bgroup", "egroup", "endgraf", "space", "empty", "null",
+ "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newhelp", "newread", "newwrite", "newfam", "newlanguage", "newinsert", "newif",
+ "maxdimen", "magstephalf", "magstep",
+ "frenchspacing", "nonfrenchspacing", "normalbaselines", "obeylines", "obeyspaces", "raggedright", "ttraggedright",
+ "thinspace", "negthinspace", "enspace", "enskip", "quad", "qquad",
+ "smallskip", "medskip", "bigskip", "removelastskip", "topglue", "vglue", "hglue",
+ "break", "nobreak", "allowbreak", "filbreak", "goodbreak", "smallbreak", "medbreak", "bigbreak",
+ "line", "leftline", "rightline", "centerline", "rlap", "llap", "underbar", "strutbox", "strut",
+ "cases", "matrix", "pmatrix", "bordermatrix", "eqalign", "displaylines", "eqalignno", "leqalignno",
+ "pageno", "folio", "tracingall", "showhyphens", "fmtname", "fmtversion",
+ "hphantom", "vphantom", "phantom", "smash",
+ },
+ }
+
+ local primitives = {
+ tex = table.sorted( table.merged( missing.tex , table.fromhash(tex.primitives()) ) ),
+ etex = table.sorted( table.merged( missing.etex , tex.extraprimitives('etex') ) ),
+ pdftex = table.sorted( table.merged( missing.pdftex, tex.extraprimitives('pdftex') ) ),
+ luatex = table.sorted( table.merged( missing.luatex, tex.extraprimitives('luatex') ) ),
+ aleph = table.sorted( table.merged( missing.aleph , tex.extraprimitives('aleph') ) ),
+ omega = table.sorted( table.merged( missing.omega , tex.extraprimitives('omega') ) ),
+ xetex = table.sorted( table.merged( missing.xetex , { } ) ),
+ }
+
+ -- table.remove(primitives.tex,1) -- get rid of \-
+
+ io.savedata("mult-prm.lua",table.serialize(primitives,true,{ reduce = true, inline = false }))
+
+ context.stoptext()
+
+\stopluacode
diff --git a/Master/texmf-dist/tex/context/base/mult-ro.mkii b/Master/texmf-dist/tex/context/base/mult-ro.mkii
index 474cf7c43e0..4b05da390d9 100644
--- a/Master/texmf-dist/tex/context/base/mult-ro.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-ro.mkii
@@ -4,6 +4,8 @@
%
\setinterfacevariable{Addition}{Adaugare}
\setinterfacevariable{Balloon}{Balon}
+\setinterfacevariable{Cap}{Cap}
+\setinterfacevariable{Capital}{Majuscula}
\setinterfacevariable{Character}{Caracter}
\setinterfacevariable{Characters}{Caractere}
\setinterfacevariable{CloseDocument}{InchideDocument}
@@ -61,6 +63,9 @@
\setinterfacevariable{ViewerHelp}{AjutorVizualizator}
\setinterfacevariable{WEEKDAY}{ZISAPTAMANA}
\setinterfacevariable{WORD}{CUVANT}
+\setinterfacevariable{WORDS}{CUVINTE}
+\setinterfacevariable{Word}{Cuvant}
+\setinterfacevariable{Words}{Cuvinte}
\setinterfacevariable{abbreviation}{abreviere}
\setinterfacevariable{abbreviations}{abrevieri}
\setinterfacevariable{absolute}{absolut}
@@ -275,6 +280,7 @@
\setinterfacevariable{marking}{marcaje}
\setinterfacevariable{mathalignment}{mathalignment}
\setinterfacevariable{mathcases}{mathcases}
+\setinterfacevariable{mathematics}{matematica}
\setinterfacevariable{mathmatrix}{mathmatrix}
\setinterfacevariable{max}{max}
\setinterfacevariable{maxdepth}{maxdepth}
@@ -356,6 +362,7 @@
\setinterfacevariable{previousoddpage}{paginaimparaprecedenta}
\setinterfacevariable{previouspage}{paginaanterioara}
\setinterfacevariable{previoussubpage}{subpaginaanterioara}
+\setinterfacevariable{print}{print}
\setinterfacevariable{printable}{tiparibil}
\setinterfacevariable{process}{process}
\setinterfacevariable{product}{produs}
@@ -363,6 +370,7 @@
\setinterfacevariable{project}{proiect}
\setinterfacevariable{protected}{protejat}
\setinterfacevariable{quadruple}{cvadrupul}
+\setinterfacevariable{quarterline}{quarterline}
\setinterfacevariable{quotation}{citat}
\setinterfacevariable{quote}{minicitat}
\setinterfacevariable{ran}{rulat}
@@ -497,6 +505,8 @@
\setinterfacevariable{unavailable}{nedisponibil}
\setinterfacevariable{underbar}{sublinie}
\setinterfacevariable{underbars}{sublinii}
+\setinterfacevariable{understrike}{understrike}
+\setinterfacevariable{understrikes}{understrikes}
\setinterfacevariable{unit}{unitate}
\setinterfacevariable{units}{unitati}
\setinterfacevariable{unknown}{necunoscut}
@@ -516,6 +526,7 @@
\setinterfacevariable{white}{alb}
\setinterfacevariable{wide}{larg}
\setinterfacevariable{width}{latime}
+\setinterfacevariable{word}{cuvant}
\setinterfacevariable{xml}{xml}
\setinterfacevariable{year}{an}
\setinterfacevariable{yes}{da}
@@ -533,6 +544,7 @@
\setinterfaceconstant{alignsymbol}{alignsymbol}
\setinterfaceconstant{aligntitle}{alinieretitlu}
\setinterfaceconstant{alternative}{alternativ}
+\setinterfaceconstant{anchor}{anchor}
\setinterfaceconstant{andtext}{andtext}
\setinterfaceconstant{apa}{apa}
\setinterfaceconstant{arrow}{sageata}
@@ -552,6 +564,8 @@
\setinterfaceconstant{autohang}{autohang}
\setinterfaceconstant{autostrut}{autostrut}
\setinterfaceconstant{autowidth}{autolatime}
+\setinterfaceconstant{availableheight}{availableheight}
+\setinterfaceconstant{availablewidth}{availablewidth}
\setinterfaceconstant{axis}{axa}
\setinterfaceconstant{background}{fundal}
\setinterfaceconstant{backgroundcolor}{culoarefundal}
@@ -571,6 +585,7 @@
\setinterfaceconstant{blank}{blanc}
\setinterfaceconstant{blockway}{blockway}
\setinterfaceconstant{bodyfont}{fonttext}
+\setinterfaceconstant{boffset}{boffset}
\setinterfaceconstant{bookmark}{semncarte}
\setinterfaceconstant{bottom}{jos}
\setinterfaceconstant{bottomafter}{bottomafter}
@@ -602,6 +617,8 @@
\setinterfaceconstant{commandafter}{comandadupa}
\setinterfaceconstant{commandbefore}{comandainainte}
\setinterfaceconstant{commands}{comenzi}
+\setinterfaceconstant{commentoffset}{commentoffset}
+\setinterfaceconstant{compact}{compact}
\setinterfaceconstant{component}{component}
\setinterfaceconstant{compoundhyphen}{compoundhyphen}
\setinterfaceconstant{compress}{compress}
@@ -615,6 +632,7 @@
\setinterfaceconstant{coupling}{cuplare}
\setinterfaceconstant{couplingway}{modcuplare}
\setinterfaceconstant{criterium}{criteriu}
+\setinterfaceconstant{css}{css}
\setinterfaceconstant{current}{curent}
\setinterfaceconstant{cutspace}{cutspace}
\setinterfaceconstant{dash}{dash}
@@ -643,11 +661,13 @@
\setinterfaceconstant{editoretallimit}{editoretallimit}
\setinterfaceconstant{editoretaltext}{editoretaltext}
\setinterfaceconstant{empty}{gol}
+\setinterfaceconstant{entities}{entities}
\setinterfaceconstant{entries}{entries}
\setinterfaceconstant{equalheight}{equalheight}
\setinterfaceconstant{equalwidth}{equalwidth}
\setinterfaceconstant{escape}{escape}
\setinterfaceconstant{evenmargin}{marginepara}
+\setinterfaceconstant{exitoffset}{labeloffset}
\setinterfaceconstant{expansion}{expansiune}
\setinterfaceconstant{export}{export}
\setinterfaceconstant{extras}{extras}
@@ -684,6 +704,7 @@
\setinterfaceconstant{global}{global}
\setinterfaceconstant{grid}{grid}
\setinterfaceconstant{hang}{suspenda}
+\setinterfaceconstant{hcompact}{hcompact}
\setinterfaceconstant{headalign}{headalign}
\setinterfaceconstant{headcolor}{culoaretitlu}
\setinterfaceconstant{headcommand}{headcommand}
@@ -712,6 +733,7 @@
\setinterfaceconstant{inner}{intern}
\setinterfaceconstant{innermargin}{innermargin}
\setinterfaceconstant{inputfile}{inputfile}
+\setinterfaceconstant{insidesection}{insidesection}
\setinterfaceconstant{intent}{intent}
\setinterfaceconstant{interaction}{interactiune}
\setinterfaceconstant{interlinespace}{spatiereinterliniara}
@@ -724,8 +746,10 @@
\setinterfaceconstant{keys}{keys}
\setinterfaceconstant{keyword}{keyword}
\setinterfaceconstant{label}{eticheta}
+\setinterfaceconstant{labeloffset}{labeloffset}
\setinterfaceconstant{lastnamesep}{lastnamesep}
\setinterfaceconstant{lastpubsep}{lastpubsep}
+\setinterfaceconstant{layout}{layout}
\setinterfaceconstant{left}{stanga}
\setinterfaceconstant{leftcolor}{culoarestanga}
\setinterfaceconstant{leftcompoundhyphen}{leftcompoundhyphen}
@@ -754,6 +778,7 @@
\setinterfaceconstant{listtext}{listtext}
\setinterfaceconstant{local}{local}
\setinterfaceconstant{location}{locatie}
+\setinterfaceconstant{loffset}{loffset}
\setinterfaceconstant{logo}{logo}
\setinterfaceconstant{logos}{logos}
\setinterfaceconstant{marcolor}{culoaremarcaj}
@@ -830,6 +855,7 @@
\setinterfaceconstant{page}{pagina}
\setinterfaceconstant{pageboundaries}{marginipagina}
\setinterfaceconstant{pagecolor}{culoarepagina}
+\setinterfaceconstant{pagecolormodel}{pagecolormodel}
\setinterfaceconstant{pagecommand}{comandapagina}
\setinterfaceconstant{pageconversion}{pageconversion}
\setinterfaceconstant{pageconversionset}{pageconversionset}
@@ -870,6 +896,7 @@
\setinterfaceconstant{preview}{previzualizare}
\setinterfaceconstant{previous}{precendent}
\setinterfaceconstant{previousnumber}{numarprecedent}
+\setinterfaceconstant{printable}{tiparibil}
\setinterfaceconstant{process}{process}
\setinterfaceconstant{profile}{profile}
\setinterfaceconstant{pubsep}{pubsep}
@@ -882,6 +909,7 @@
\setinterfaceconstant{reference}{referinta}
\setinterfaceconstant{referenceprefix}{referenceprefix}
\setinterfaceconstant{referencing}{referinta}
+\setinterfaceconstant{region}{region}
\setinterfaceconstant{regionin}{regiuneintrare}
\setinterfaceconstant{regionout}{regiuneiesire}
\setinterfaceconstant{repeat}{repeta}
@@ -906,9 +934,11 @@
\setinterfaceconstant{rightsubsentence}{subpropozitiedreapta}
\setinterfaceconstant{righttext}{textdreapta}
\setinterfaceconstant{rightwidth}{marginedreapta}
+\setinterfaceconstant{roffset}{roffset}
\setinterfaceconstant{rotation}{rotatie}
\setinterfaceconstant{rule}{rigla}
\setinterfaceconstant{rulecolor}{culoarerigla}
+\setinterfaceconstant{rulecommand}{rulecommand}
\setinterfaceconstant{rulethickness}{grosimerigla}
\setinterfaceconstant{samepage}{aceeasipagina}
\setinterfaceconstant{sample}{exemplu}
@@ -966,6 +996,7 @@
\setinterfaceconstant{subtitle}{subtitlu}
\setinterfaceconstant{suffix}{suffix}
\setinterfaceconstant{suffixseparator}{suffixseparator}
+\setinterfaceconstant{suffixstopper}{suffixstopper}
\setinterfaceconstant{surnamesep}{surnamesep}
\setinterfaceconstant{sx}{sx}
\setinterfaceconstant{sy}{sy}
@@ -983,6 +1014,7 @@
\setinterfaceconstant{textcolor}{culoaretext}
\setinterfaceconstant{textcommand}{comandatext}
\setinterfaceconstant{textdistance}{textdistance}
+\setinterfaceconstant{textheight}{inaltimetext}
\setinterfaceconstant{textlayer}{textlayer}
\setinterfaceconstant{textmargin}{textmargin}
\setinterfaceconstant{textmethod}{textmethod}
@@ -1000,6 +1032,7 @@
\setinterfaceconstant{titleright}{titleright}
\setinterfaceconstant{titlestyle}{stiltitlu}
\setinterfaceconstant{to}{catre}
+\setinterfaceconstant{toffset}{toffset}
\setinterfaceconstant{tolerance}{toleranta}
\setinterfaceconstant{top}{sus}
\setinterfaceconstant{topdistance}{distantasus}
@@ -1016,6 +1049,8 @@
\setinterfaceconstant{validate}{verifica}
\setinterfaceconstant{values}{values}
\setinterfaceconstant{vcommand}{comandav}
+\setinterfaceconstant{vcompact}{vcompact}
+\setinterfaceconstant{vector}{vector}
\setinterfaceconstant{veroffset}{veroffset}
\setinterfaceconstant{vfil}{vfil}
\setinterfaceconstant{voffset}{voffset}
@@ -1025,6 +1060,7 @@
\setinterfaceconstant{white}{alb}
\setinterfaceconstant{width}{latime}
\setinterfaceconstant{xfactor}{xfactor}
+\setinterfaceconstant{xhtml}{xhtml}
\setinterfaceconstant{xmax}{xmax}
\setinterfaceconstant{xoffset}{xoffset}
\setinterfaceconstant{xscale}{xscala}
@@ -1042,8 +1078,6 @@
\setinterfaceelement{complete}{complet}
\setinterfaceelement{coupled}{cuplat}
\setinterfaceelement{currentlocal}{localcurent}
-\setinterfaceelement{emptyone}{gol}
-\setinterfaceelement{emptytwo}{gol}
\setinterfaceelement{end}{sfarsit}
\setinterfaceelement{endsetup}{}
\setinterfaceelement{get}{get}
@@ -1156,7 +1190,7 @@
\setinterfacecommand{defineframedtext}{definestetextinconjurat}
\setinterfacecommand{definehbox}{definestehbox}
\setinterfacecommand{definehead}{definesteantet}
-\setinterfacecommand{defineindenting}{definestealiat}
+\setinterfacecommand{defineindentedtext}{defineindentedtext}
\setinterfacecommand{defineinmargin}{defineinmargin}
\setinterfacecommand{defineinteractionmenu}{definestemeniuinteractiune}
\setinterfacecommand{defineitemgroup}{defineitemgroup}
@@ -1352,7 +1386,6 @@
\setinterfacecommand{pagenumber}{numarpagina}
\setinterfacecommand{pageoffset}{pageoffset}
\setinterfacecommand{pagereference}{referintapagina}
-\setinterfacecommand{pagetype}{tippagina}
\setinterfacecommand{paperheight}{inaltimehartie}
\setinterfacecommand{paperwidth}{latimehartie}
\setinterfacecommand{periods}{puncte}
@@ -1468,7 +1501,7 @@
\setinterfacecommand{setupheads}{seteazatitluri}
\setinterfacecommand{setupheadtext}{seteazatexttitlu}
\setinterfacecommand{setuphyphenmark}{seteazaliniesilabe}
-\setinterfacecommand{setupindentations}{seteazaaliniate}
+\setinterfacecommand{setupindentedtext}{setupindentedtext}
\setinterfacecommand{setupindenting}{seteazaaliniat}
\setinterfacecommand{setupinmargin}{seteazamarginal}
\setinterfacecommand{setupinteraction}{seteazainteractiunea}
diff --git a/Master/texmf-dist/tex/context/base/mult-sys.mkii b/Master/texmf-dist/tex/context/base/mult-sys.mkii
index 1484acecca5..1961fdf11b1 100644
--- a/Master/texmf-dist/tex/context/base/mult-sys.mkii
+++ b/Master/texmf-dist/tex/context/base/mult-sys.mkii
@@ -5,7 +5,7 @@
%D subtitle=System,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/mult-sys.mkiv b/Master/texmf-dist/tex/context/base/mult-sys.mkiv
index 4e3138c8634..4ec4c222109 100644
--- a/Master/texmf-dist/tex/context/base/mult-sys.mkiv
+++ b/Master/texmf-dist/tex/context/base/mult-sys.mkiv
@@ -5,7 +5,7 @@
%D subtitle=System,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -44,7 +44,8 @@
\definesystemconstant {catalan} \definesystemconstant {ca}
\definesystemconstant {chinese} \definesystemconstant {cn}
\definesystemconstant {croatian} \definesystemconstant {hr}
-\definesystemconstant {czech} \definesystemconstant {cs} \definesystemconstant {cz}
+\definesystemconstant {czech} \definesystemconstant {cs}
+ \definesystemconstant {cz}
\definesystemconstant {danish} \definesystemconstant {da}
\definesystemconstant {dutch} \definesystemconstant {nl}
\definesystemconstant {english} \definesystemconstant {en}
@@ -55,7 +56,8 @@
\definesystemconstant {italian} \definesystemconstant {it}
\definesystemconstant {latin} \definesystemconstant {la}
\definesystemconstant {lithuanian} \definesystemconstant {lt}
-\definesystemconstant {bokmal} \definesystemconstant {nb} \definesystemconstant {norwegian} \definesystemconstant {no}
+\definesystemconstant {bokmal} \definesystemconstant {nb}
+\definesystemconstant {norwegian} \definesystemconstant {no}
\definesystemconstant {nynorsk} \definesystemconstant {nn}
\definesystemconstant {polish} \definesystemconstant {pl}
\definesystemconstant {persian} \definesystemconstant {pe}
@@ -69,12 +71,14 @@
\definesystemconstant {swedish} \definesystemconstant {sv}
\definesystemconstant {turkish} \definesystemconstant {tr}
\definesystemconstant {turkmen} \definesystemconstant {tk}
-\definesystemconstant {gbenglish} \definesystemconstant {gb} \definesystemconstant {ukenglish} \definesystemconstant {uk}
+\definesystemconstant {gbenglish} \definesystemconstant {gb}
+\definesystemconstant {ukenglish} \definesystemconstant {uk}
\definesystemconstant {usenglish} \definesystemconstant {us}
\definesystemconstant {ukrainian} \definesystemconstant {ua}
\definesystemconstant {greek} \definesystemconstant {gr}
\definesystemconstant {ancientgreek} \definesystemconstant {agr}
-\definesystemconstant {vietnamese} \definesystemconstant {vi} \definesystemconstant {vn}
+\definesystemconstant {vietnamese} \definesystemconstant {vi}
+ \definesystemconstant {vn}
\definesystemconstant {chinese} \definesystemconstant {cn}
\definesystemconstant {japanese} \definesystemconstant {ja}
\definesystemconstant {korean} \definesystemconstant {kr}
@@ -90,32 +94,52 @@
\definesystemconstant {Slanted}
\definesystemconstant {Unicode}
-\definesystemconstant {Serif} \definesystemconstant {Regular}
-\definesystemconstant {Sans} \definesystemconstant {Support}
-\definesystemconstant {Mono} \definesystemconstant {Type}
+\definesystemconstant {Serif}
+\definesystemconstant {Sans}
+\definesystemconstant {Mono}
\definesystemconstant {Math}
\definesystemconstant {Handwriting}
\definesystemconstant {Calligraphy}
\definesystemconstant {Casual}
-\definesystemconstant {SerifBold} \definesystemconstant {SansBold} \definesystemconstant {MonoBold}
-\definesystemconstant {SerifItalic} \definesystemconstant {SansItalic} \definesystemconstant {MonoItalic}
-\definesystemconstant {SerifBoldItalic} \definesystemconstant {SansBoldItalic} \definesystemconstant {MonoBoldItalic}
-\definesystemconstant {SerifSlanted} \definesystemconstant {SansSlanted} \definesystemconstant {MonoSlanted}
-\definesystemconstant {SerifBoldSlanted} \definesystemconstant {SansBoldSlanted} \definesystemconstant {MonoBoldSlanted}
-\definesystemconstant {SerifCaps} \definesystemconstant {SansCaps} \definesystemconstant {MonoCaps}
-
+\definesystemconstant {Regular}
+\definesystemconstant {Support}
+\definesystemconstant {Type}
+
+\definesystemconstant {SerifBold}
+\definesystemconstant {SerifItalic}
+\definesystemconstant {SerifBoldItalic}
+\definesystemconstant {SerifSlanted}
+\definesystemconstant {SerifBoldSlanted}
+\definesystemconstant {SerifCaps}
+% \definesystemconstant {SerifCapsSlanted}
+
+\definesystemconstant {SansBold}
+\definesystemconstant {SansItalic}
+\definesystemconstant {SansBoldItalic}
+\definesystemconstant {SansSlanted}
+\definesystemconstant {SansBoldSlanted}
+\definesystemconstant {SansCaps}
+% \definesystemconstant {SansCapsSlanted}
+
+\definesystemconstant {MonoBold}
+\definesystemconstant {MonoItalic}
+\definesystemconstant {MonoBoldItalic}
+\definesystemconstant {MonoSlanted}
+\definesystemconstant {MonoBoldSlanted}
+\definesystemconstant {MonoCaps}
+% \definesystemconstant {MonoCapsSlanted}
+% \definesystemconstant {MonoVariable}
+
+\definesystemconstant {DefaultFont}
+
+\definesystemconstant {MathRoman}
+\definesystemconstant {MathRomanBold}
+
+\definesystemconstant {Simple}
\definesystemconstant {Normal}
\definesystemconstant {Caps}
-\definesystemconstant {mnem} % kind of generic short tag
-
-\definesystemconstant {file}
-\definesystemconstant {name}
-\definesystemconstant {spec}
-
-\definesystemconstant {attribute}
-
\definesystemconstant {serif}
\definesystemconstant {sans}
\definesystemconstant {mono}
@@ -127,38 +151,72 @@
\definesystemconstant {fallback}
+%definesystemconstant {mnem} % kind of generic short tag
+
+\definesystemconstant {file}
+\definesystemconstant {name}
+\definesystemconstant {spec}
+
+\definesystemconstant {both}
+
+\definesystemconstant {attribute}
+
\definesystemconstant {none}
+\definesystemconstant {auto}
\definesystemconstant {default}
\definesystemconstant {smallcaps}
-%D As the name of their define command states, the next set of
-%D constants is used in the message macro's.
-
-\definemessageconstant {check}
-\definemessageconstant {colors}
-\definemessageconstant {columns}
-\definemessageconstant {regimes}
-\definemessageconstant {figures}
-\definemessageconstant {fields}
-\definemessageconstant {files}
-\definemessageconstant {floatblocks}
-\definemessageconstant {fonts}
-\definemessageconstant {handlings}
-\definemessageconstant {interactions}
-\definemessageconstant {javascripts}
-\definemessageconstant {layouts}
-\definemessageconstant {languages}
-\definemessageconstant {references}
-\definemessageconstant {structures}
-\definemessageconstant {symbols}
-\definemessageconstant {system}
-\definemessageconstant {lua}
-\definemessageconstant {textblocks}
-\definemessageconstant {verbatims}
-\definemessageconstant {versions}
-\definemessageconstant {metapost}
-\definemessageconstant {chemicals}
-\definemessageconstant {publications}
+\definesystemconstant {regular}
+\definesystemconstant {script}
+\definesystemconstant {fraktur}
+\definesystemconstant {blackboard}
+
+\definesystemconstant {tf}
+\definesystemconstant {sl}
+\definesystemconstant {it}
+\definesystemconstant {bf}
+\definesystemconstant {bs}
+\definesystemconstant {bi}
+
+\definesystemconstant {rm}
+\definesystemconstant {ss}
+\definesystemconstant {tt}
+\definesystemconstant {hw}
+\definesystemconstant {cg}
+\definesystemconstant {mm}
+
+\definesystemconstant {x}
+\definesystemconstant {xx}
+\definesystemconstant {em}
+
+\definesystemconstant {a}
+\definesystemconstant {b}
+\definesystemconstant {c}
+\definesystemconstant {d}
+\definesystemconstant {e}
+\definesystemconstant {f}
+
+\definesystemconstant {mr}
+\definesystemconstant {mb}
+\definesystemconstant {mrlr}
+\definesystemconstant {mrrl}
+\definesystemconstant {mblr}
+\definesystemconstant {mbrl}
+
+\definesystemconstant {tf}
+\definesystemconstant {bf}
+\definesystemconstant {bs}
+\definesystemconstant {bi}
+\definesystemconstant {sl}
+\definesystemconstant {it}
+\definesystemconstant {sc}
+
+\definesystemconstant {small}
+\definesystemconstant {big}
+
+\definesystemconstant {first}
+\definesystemconstant {second}
+\definesystemconstant {third}
%D Net come some \CONTEXT\ constants, used in the definition
%D of private commands:
@@ -187,12 +245,14 @@
\definesystemconstant {font}
\definesystemconstant {link}
\definesystemconstant {parent}
+\definesystemconstant {child}
\definesystemconstant {clone}
-\definesystemconstant {section} \let\v!sectionlevel\s!section % for old times sake
+\definesystemconstant {section}
\definesystemconstant {handler}
\definesystemconstant {counter}
\definesystemconstant {single}
\definesystemconstant {multi}
+\definesystemconstant {indeed}
\definesystemconstant {hasnumber}
\definesystemconstant {hastitle}
@@ -201,7 +261,6 @@
\definesystemconstant {mkiv}
\definesystemconstant {mkii}
-\definesystemconstant {entities}
\definesystemconstant {normal}
\definesystemconstant {bold}
@@ -211,19 +270,14 @@
\definesystemconstant {default}
\definesystemconstant {smallcaps}
-\definesystemconstant {text}
-\definesystemconstant {page}
-\definesystemconstant {leftpage}
-\definesystemconstant {rightpage}
-\definesystemconstant {somewhere}
-
-%D A more experienced \TEX\ user will recognize the next four
-%D constants. We need these because font-definitions are
-%D partially english.
-
\definesystemconstant {run}
-\definesystemconstant {fam}
+\definesystemconstant {mode}
+\definesystemconstant {setup}
+\definesystemconstant {environment}
+\definesystemconstant {document}
+
+%definesystemconstant {fam}
\definesystemconstant {text}
\definesystemconstant {script}
\definesystemconstant {scriptscript}
@@ -233,39 +287,86 @@
\definesystemconstant {lefthyphenchar}
\definesystemconstant {righthyphenchar}
-\definesystemconstant {skewchar}
-\definesystemconstant {hyphenchar}
+%definesystemconstant {skewchar}
+%definesystemconstant {hyphenchar}
\definesystemconstant {catcodes}
-\definesystemconstant {encoding}
-\definesystemconstant {resource}
-\definesystemconstant {mapping}
+%definesystemconstant {encoding}
+%definesystemconstant {entities}
+%definesystemconstant {resource}
+%definesystemconstant {mapping}
\definesystemconstant {language}
\definesystemconstant {patterns}
\definesystemconstant {rname}
\definesystemconstant {rscale}
-\definesystemconstant {handling}
+%definesystemconstant {handling}
\definesystemconstant {features}
+\definesystemconstant {direction}
\definesystemconstant {fallbacks}
\definesystemconstant {goodies}
-\definesystemconstant {background}
-\definesystemconstant {ucmap}
-
-\definesystemconstant {property}
-\definesystemconstant {overprint}
-\definesystemconstant {layer}
-\definesystemconstant {effect}
-\definesystemconstant {negative}
-\definesystemconstant {color}
-\definesystemconstant {transparency}
+\definesystemconstant {designsize}
+%definesystemconstant {background}
+%definesystemconstant {ucmap}
+
+%definesystemconstant {property}
+%definesystemconstant {overprint}
+%definesystemconstant {layer}
+\definesystemconstant {effect} % todo s
+%definesystemconstant {negative}
+%definesystemconstant {color}
+%definesystemconstant {transparency}
\definesystemconstant {black}
\definesystemconstant {white}
+\definesystemconstant {system} % not yet interfaces messages
+\definesystemconstant {user}
+\definesystemconstant {check}
+\definesystemconstant {reset}
+\definesystemconstant {set}
+\definesystemconstant {empty}
+
+\definesystemconstant {realpage}
+\definesystemconstant {userpage}
+\definesystemconstant {subpage}
+
+\definesystemconstant {page}
+\definesystemconstant {subpage}
+\definesystemconstant {leftpage}
+\definesystemconstant {rightpage}
+\definesystemconstant {somewhere}
+
+\definesystemconstant {userdata}
+\definesystemconstant {command}
+\definesystemconstant {simple}
+
+\definesystemconstant {full}
+\definesystemconstant {text}
+\definesystemconstant {paragraph}
+\definesystemconstant {margintext}
+\definesystemconstant {line}
+
+\definesystemconstant {number}
+\definesystemconstant {symbol}
\definesystemconstant {format}
+\definesystemconstant {data}
+\definesystemconstant {float}
\definesystemconstant {extensions}
\definesystemconstant {initializations}
-\definesystemconstant {system} % not yet interfaces messages
+\definesystemconstant {rgb}
+\definesystemconstant {cmyk}
+\definesystemconstant {gray}
+\definesystemconstant {spot}
+\definesystemconstant {all}
+\definesystemconstant {dtp}
+\definesystemconstant {none}
+
+\definesystemconstant {map}
+\definesystemconstant {special}
+\definesystemconstant {size}
+
+\definesystemconstant {depth}
+\definesystemconstant {nodepth}
%D Just to be complete we define the standard \TEX\ units.
@@ -284,450 +385,215 @@
\definesystemconstant {nd}
\definesystemconstant {nc}
-%D These constants are used for internal and utility
-%D commands.
-
-\definesystemconstant {check}
-\definesystemconstant {reset}
-\definesystemconstant {set}
-
-\definesystemconstant {entrya}
-\definesystemconstant {entryb}
-\definesystemconstant {entryc}
-\definesystemconstant {entryd}
-\definesystemconstant {entry}
-\definesystemconstant {see}
-\definesystemconstant {from}
-\definesystemconstant {to}
-\definesystemconstant {line}
-\definesystemconstant {page}
-\definesystemconstant {realpage}
-\definesystemconstant {userpage}
-\definesystemconstant {subpage}
-
-\definesystemconstant {synonym}
-
-\definesystemconstant {reference}
-\definesystemconstant {main}
-
-\definesystemconstant {list}
-
-\definesystemconstant {item}
-\definesystemconstant {itemcount}
-
-\definesystemconstant {number}
-\definesystemconstant {references}
-\definesystemconstant {between}
-\definesystemconstant {format}
-\definesystemconstant {old}
-
-\definesystemconstant {thisisblock}
-\definesystemconstant {thiswasblock}
-
-\definesystemconstant {figurepreset}
-
-\definesystemconstant {empty}
-
-%D Some \CONTEXT\ commands take a two||pass aproach to
-%D optimize the typesetting. Each two||pass object has its
-%D own tag.
-
-\definesystemconstant {pass}
-
-\definesystemconstant {data}
-\definesystemconstant {float}
-\definesystemconstant {list}
-\definesystemconstant {page}
-\definesystemconstant {subpage}
-\definesystemconstant {margin}
-\definesystemconstant {profile}
-\definesystemconstant {versionbegin}
-\definesystemconstant {versionend}
-\definesystemconstant {cross}
-\definesystemconstant {paragraph}
+%D As the name of their define command states, the next set of
+%D constants is used in the message macro's.
-%D A lot of macros use tags to distinguish between different
-%D objects, e.g. lists and registers.
-
-\definesystemconstant {prt} % part (deel)
-\definesystemconstant {chp} % chapter (hoofdstuk)
-\definesystemconstant {sec} % section (paragraaf)
-\definesystemconstant {tit} % title (titel)
-\definesystemconstant {sub} % subject (onderwerp)
-\definesystemconstant {mar} % margin (marge)
-\definesystemconstant {num} % number (doornummeren)
-\definesystemconstant {def} % definition (doordefinieren)
-\definesystemconstant {for} % formula (formule)
-\definesystemconstant {fnt} % footnote (voetnoot)
-\definesystemconstant {ind} % index (register)
-\definesystemconstant {lin} % linked index
-\definesystemconstant {lst} % list (opsomming)
-\definesystemconstant {flt} % float (plaatsblok)
-\definesystemconstant {pag} % page (pagina)
-\definesystemconstant {txt} % text (tekst)
-\definesystemconstant {ref} % reference (verwijzing)
-\definesystemconstant {lab} % label (label)
-\definesystemconstant {aut} % automatic (inhoud, index)
-\definesystemconstant {vwa} % automatic (illustrations)
-\definesystemconstant {vwb} % automatic (illustrations)
-
-\definesystemconstant {kop} % kop % still dutch
-
-%D Reference labels can be tagged by users, for instance by
-%D means of \type{tag:}. The reference mechanism itself uses
-%D some tags too. These are definitely not to be used by users.
-%D Here they are:
-
-\definereferenceconstant {cross} {:c:} % cross reference
-\definereferenceconstant {view} {:v:} % view reference
-\definereferenceconstant {viewa} {:a:} % view reference test a
-\definereferenceconstant {viewb} {:b:} % view reference test b
-\definereferenceconstant {page} {:p:} % page referece
-\definereferenceconstant {list} {:l:} % list reference
-\definereferenceconstant {exec} {:e:} % execution reference
-\definereferenceconstant {form} {:m:} % form reference
-\definereferenceconstant {syst} {:s:} % system reference
-
-\definereferenceconstant {from} {:f:} % from list reference
-\definereferenceconstant {to} {:t:} % to list reference
-
-\definereferenceconstant {object} {:o:} % object reference
-\definereferenceconstant {driver} {:d:} % driver object reference
-\definereferenceconstant {widget} {:w:} % field chain reference
-
-\definereferenceconstant {java} {:j:} % java scripts
+\definemessageconstant {check}
+\definemessageconstant {colors}
+\definemessageconstant {columns}
+\definemessageconstant {regimes}
+\definemessageconstant {figures}
+\definemessageconstant {fields}
+\definemessageconstant {files}
+\definemessageconstant {floatblocks}
+\definemessageconstant {fonts}
+\definemessageconstant {handlings}
+\definemessageconstant {interactions}
+\definemessageconstant {javascripts}
+\definemessageconstant {layouts}
+\definemessageconstant {languages}
+\definemessageconstant {references}
+\definemessageconstant {structures}
+\definemessageconstant {symbols}
+\definemessageconstant {system}
+\definemessageconstant {lua}
+\definemessageconstant {textblocks}
+\definemessageconstant {verbatims}
+\definemessageconstant {versions}
+\definemessageconstant {metapost}
+\definemessageconstant {chemicals}
+\definemessageconstant {publications}
%D When we use numbers and dimensions the same applies as
%D with the keywords like \type{width} and \type{plus}
%D mentioned earlier.
-\def\!!ten {10}
-\def\!!twelve {12}
-\def\!!hundred {100}
-\def\!!thousand {1000}
-\def\!!tenthousand {10000}
-\def\!!maxcard {65536}
-\def\!!medcard {32768}
-
-\def\!!zeropoint {0pt}
-\def\!!onepoint {1pt}
-\def\!!twopoint {2pt}
-\def\!!threepoint {3pt}
-\def\!!fourpoint {4pt}
-\def\!!fivepoint {5pt}
-\def\!!sixpoint {6pt}
-\def\!!sevenpoint {7pt}
-\def\!!eightpoint {8pt}
-\def\!!ninepoint {9pt}
-\def\!!tenpoint {10pt}
-\def\!!elevenpoint {11pt}
-\def\!!twelvepoint {12pt}
+\def\!!ten {10}
+\def\!!twelve {12}
+\def\!!hundred {100}
+\def\!!thousand {1000}
+\def\!!tenthousand {10000}
+\def\!!maxcard {65536}
+\def\!!medcard {32768}
+
+\def\!!zeropoint {0pt}
+\def\!!onepoint {1pt}
+\def\!!twopoint {2pt}
+\def\!!threepoint {3pt}
+\def\!!fourpoint {4pt}
+\def\!!fivepoint {5pt}
+\def\!!sixpoint {6pt}
+\def\!!sevenpoint {7pt}
+\def\!!eightpoint {8pt}
+\def\!!ninepoint {9pt}
+\def\!!tenpoint {10pt}
+\def\!!elevenpoint {11pt}
+\def\!!twelvepoint {12pt}
\def\!!fourteenpointfour {14.4pt}
-\let\onerealpoint\onepoint % needed for latex
+\def\!!plustoken {+}
+\def\!!minustoken {-}
-% D Another optimization is:
-%
-% \let\points\onepoint
-
-%D A rough test is:
-%D
-%D \starttyping
-%D \def\TestMe % 7.75 sec on a P4/2G
-%D {\dimen0=10\points\dimen0=10\points\dimen0=10\points\dimen0=10\points\dimen0=10\points
-%D \dimen0=10\points\dimen0=10\points\dimen0=10\points\dimen0=10\points\dimen0=10\points}
-%D
-%D \def\TestMe % 11.5 sec on a P4/2G
-%D {\dimen0=10pt\dimen0=10pt\dimen0=10pt\dimen0=10pt\dimen0=10pt%
-%D \dimen0=10pt\dimen0=10pt\dimen0=10pt\dimen0=10pt\dimen0=10pt}
-%D
-%D \def\TestMe % 12.5 sec on a P4/2G
-%D {\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt%
-%D \dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt\dimen0=10\s!pt}
-%D
-%D \testfeatureonce {500000}{\TestMe}
-%D \stoptyping
+\def\__unknown__ {\string\\//} % unlikely value
%D Variables are composed of a command specific tag and a user
%D supplied variable (system constant). The first tag \type{ag}
%D for instance is available as \type{\??ag} and expands to
%D \type{@@ag} in composed variables.
-% vervallen : hd hr hm vt vr vm tr tn te br bm bo on om or
-
\definesystemvariable {ab} % AlignedBoxes
\definesystemvariable {ac} % ACcent
\definesystemvariable {ae} % AttributEs
-\definesystemvariable {ag} % AchterGrond
\definesystemvariable {al} % ALinea's
-\definesystemvariable {am} % interActieMenu
\definesystemvariable {an} % ANchor
\definesystemvariable {as} % AlignmentSwitch
-\definesystemvariable {at} % ATtachments
-\definesystemvariable {ba} % synchronisatieBAlk
-\definesystemvariable {bc} % BaCkend
-\definesystemvariable {be} % startstop (BeginEnd)
-\definesystemvariable {bj} % BlokJe
-\definesystemvariable {bk} % Blokken (floats)
-\definesystemvariable {bl} % BLanko
\definesystemvariable {bg} % BleedinG
\definesystemvariable {bm} % BookMark
-\definesystemvariable {bo} % BlankO (definitions)
\definesystemvariable {bp} % BreakPoint
-\definesystemvariable {br} % sideBaR
-\definesystemvariable {bs} % SelecteerBlokken
-\definesystemvariable {bt} % BuTton
-\definesystemvariable {bu} % BUffer
-\definesystemvariable {bv} % Brieven
-\definesystemvariable {by} % Per
+\definesystemvariable {bx} % BackendExport
\definesystemvariable {cb} % CollectBox
-\definesystemvariable {cc} % Comment
-\definesystemvariable {ce} % CasEs
-\definesystemvariable {cf} % Style (ColorFont)
-\definesystemvariable {ch} % CHaracterspacing
-\definesystemvariable {ci} % CItaat
-\definesystemvariable {ck} % Character Kerning
-\definesystemvariable {cl} % kleur (CoLor setup)
-\definesystemvariable {cn} % CollumN
\definesystemvariable {cm} % CheMical
-\definesystemvariable {co} % COmbinaties
\definesystemvariable {cp} % CliP
-\definesystemvariable {cr} % kleur (ColoR)
-\definesystemvariable {cs} % kleur (ColorSeparation
-\definesystemvariable {cv} % ConVersie
-\definesystemvariable {cy} % CrYteria
\definesystemvariable {da} % DAte
\definesystemvariable {db} % Labels
-\definesystemvariable {dc} % DroppedCaps
\definesystemvariable {dd} % DoorDefinieren
\definesystemvariable {de} % DEel
\definesystemvariable {di} % DIrections
\definesystemvariable {dl} % DunneLijnen
\definesystemvariable {dn} % DoorNummeren
\definesystemvariable {dm} % DefineMeasure
-\definesystemvariable {do} % DefinieerOpmaak
\definesystemvariable {du} % DUmmy
-\definesystemvariable {ds} % DoorSpringen
\definesystemvariable {ef} % ExternFiguur
-\definesystemvariable {ec} % EnCoding
-\definesystemvariable {el} % Elements
\definesystemvariable {en} % ENvironments
-\definesystemvariable {ep} % ExternfiguurPreset
-\definesystemvariable {eq} % EQalign
-\definesystemvariable {er} % external resources
+%definesystemvariable {er} % external resources
\definesystemvariable {et} % EffecT
\definesystemvariable {ex} % ExterneFiguren
-\definesystemvariable {fa} % font feature
-\definesystemvariable {fb} % FieldBody
\definesystemvariable {fc} % FramedContent
-\definesystemvariable {fd} % FielDgroup
-\definesystemvariable {fe} % FoxetExtensions
-\definesystemvariable {ff} % FontFile
-\definesystemvariable {fg} % FiGuurmaten
-\definesystemvariable {fi} % FIle
-\definesystemvariable {fl} % Floats
-\definesystemvariable {fm} % ForMules
-\definesystemvariable {fn} % subformulas
-\definesystemvariable {fo} % xml FO
-\definesystemvariable {fp} % FilegroeP
-\definesystemvariable {fq} % Features
-\definesystemvariable {fr} % ForM
-\definesystemvariable {fs} % FileSynonym
-\definesystemvariable {ft} % FonTs
+\definesystemvariable {fi} % FIle Once
+\definesystemvariable {fo} % xml FO (xtag)
\definesystemvariable {fu} % FontSolution
-\definesystemvariable {fv} % FontVariant
\definesystemvariable {fw} % simpleFonts by Wolfgang
\definesystemvariable {fx} % FoXet
-\definesystemvariable {gr} % GRid
+\definesystemvariable {gb} % Graphic Bitmaps
+\definesystemvariable {gv} % Graphic Variable
\definesystemvariable {ha} % HAng
-\definesystemvariable {hs} % HSpace
-\definesystemvariable {ht} % HiddenText
-\definesystemvariable {ia} % Interactie
-\definesystemvariable {ib} % InteractieBalk
-\definesystemvariable {ic} % ICc profiles
\definesystemvariable {id} % Index
-\definesystemvariable {ig} % ItemGroup
\definesystemvariable {ih} % InHoudsopgave
-\definesystemvariable {ii} % stelIndexIn
\definesystemvariable {il} % stelInvulRegelsin
-\definesystemvariable {im} % InMarge
-\definesystemvariable {in} % INspringen
\definesystemvariable {ip} % InsertPages
\definesystemvariable {is} % Items
\definesystemvariable {it} % stelInTerliniein
\definesystemvariable {iv} % stelInvulLijnenin
\definesystemvariable {ka} % KAntlijn
-\definesystemvariable {kd} % KaDerteksten
-\definesystemvariable {kj} % KopJes (floats)
-\definesystemvariable {kk} % Kapitalen
\definesystemvariable {kl} % KoLommen
\definesystemvariable {km} % KenMerk
-\definesystemvariable {ko} % KOp(pen)
\definesystemvariable {kp} % KopPelteken
-\definesystemvariable {kr} % KoRps
\definesystemvariable {ks} % KolomSpan
\definesystemvariable {kt} % KonTakten
\definesystemvariable {kw} % KontaktWaarde
-\definesystemvariable {la} % LAnguage
-\definesystemvariable {lb} % LaBels
-\definesystemvariable {ld} % LegenDa
\definesystemvariable {le} % LinetablE
\definesystemvariable {lf} % LocalFigures
\definesystemvariable {lg} % taal (LanGuage)
-\definesystemvariable {li} % LIjst
\definesystemvariable {lk} % LinK
\definesystemvariable {ll} % Layers
-\definesystemvariable {lx} % LayerteXt
-\definesystemvariable {ln} % LijNen
-\definesystemvariable {lo} % LOgos
-\definesystemvariable {lt} % LiTeratuur
\definesystemvariable {lr} % LayeR
-\definesystemvariable {ls} % languageScript
-\definesystemvariable {ly} % LaYout
+\definesystemvariable {lu} % LUacode
+\definesystemvariable {lx} % LayerteXt
\definesystemvariable {ma} % MargeAchtergrond
-\definesystemvariable {mb} % MargeBlokken
-\definesystemvariable {mc} % MarginCategory
-\definesystemvariable {md} % MoDule
-\definesystemvariable {me} % MultilingualElement (tags)
-\definesystemvariable {mf} % MarginFramed
-\definesystemvariable {mg} % Metapost paGe
-\definesystemvariable {mh} % MultilingualHead
-\definesystemvariable {mk} % MarKering
+\definesystemvariable {mc} % MultiColumn
+\definesystemvariable {mi} % MultilingualInterface
\definesystemvariable {ml} % MultilingualLabel
\definesystemvariable {mm} % MultilingualMath
\definesystemvariable {mt} % inline MaTh
+\definesystemvariable {mt} % multi column (!!! double usage)
\definesystemvariable {mo} % Math Options
\definesystemvariable {mp} % MetaPost
-\definesystemvariable {mx} % MatriX
-\definesystemvariable {ng} % parbuilders
-\definesystemvariable {nh} % new heads (structure)
\definesystemvariable {nn} % structurenumbering
\definesystemvariable {nm} % Nummering
\definesystemvariable {np} % NaastPlaatsen
\definesystemvariable {nr} % Nummeren
-\definesystemvariable {of} % OFfset
+\definesystemvariable {ob} % OBjects
\definesystemvariable {oi} % OmlijndInstellingen
\definesystemvariable {ol} % OmLijnd
\definesystemvariable {od} % Omlijnd Defaults (simple)
-\definesystemvariable {on} % ONderstreep
-\definesystemvariable {oo} % OpsOmmingen
-\definesystemvariable {op} % OPsomming
-\definesystemvariable {or} % OtpfilteR
-\definesystemvariable {os} % OffSet
-\definesystemvariable {ot} % OTpsequence
-\definesystemvariable {ov} % OVerlay
\definesystemvariable {ox} % OffsetBox
-\definesystemvariable {pa} % PAlet
\definesystemvariable {pb} % PuBlication
\definesystemvariable {pc} % PageComment
-\definesystemvariable {pe} % PagEhandler
-\definesystemvariable {pf} % ProFiel
-\definesystemvariable {pg} % KoppelPagina
\definesystemvariable {ph} % ParagrapH
-\definesystemvariable {pl} % PLaats
\definesystemvariable {pn} % PaginaNummer
-\definesystemvariable {po} % PrOcessor
-\definesystemvariable {pp} % PaPier
\definesystemvariable {pr} % PRogrammas
\definesystemvariable {ps} % PoSitioneren
-\definesystemvariable {pt} % PageshifT
\definesystemvariable {px} % Parallel
\definesystemvariable {py} % PropertYs
\definesystemvariable {pv} % PublicationVariable
-\definesystemvariable {ra} % RAise
-\definesystemvariable {rd} % RenDering
-\definesystemvariable {rf} % ReFereren
-\definesystemvariable {rg} % ReGel
-\definesystemvariable {rl} % ReferentieLijst
+\definesystemvariable {ql} % catcode table let % already defined
+\definesystemvariable {qd} % catcode table def % already defined
+\definesystemvariable {qu} % catcode table ued % already defined
+\definesystemvariable {qm} % catcode table meaning % already defined
+\definesystemvariable {rf} % ReFerencing
\definesystemvariable {rn} % RegelNummer
-\definesystemvariable {ro} % ROteren
-\definesystemvariable {rr} % linenotes
\definesystemvariable {rs} % RaSters
\definesystemvariable {rt} % RoosTers
-\definesystemvariable {rv} % ReserVeerfiguur
\definesystemvariable {rw} % RenderingWindow
-\definesystemvariable {sa} % ScAle
\definesystemvariable {sb} % SectieBlok
-\definesystemvariable {sc} % SCherm
\definesystemvariable {sd} % SounD
\definesystemvariable {se} % SEctie
-\definesystemvariable {sf} % SpeciFics
-\definesystemvariable {sg} % SpacinG
\definesystemvariable {sh} % ShapeText
\definesystemvariable {si} % SplIt
-\definesystemvariable {sk} % SectieKop
-\definesystemvariable {sl} % SmalLer
-\definesystemvariable {sm} % SynonieMen
-\definesystemvariable {sn} % SubNummer
-\definesystemvariable {so} % SOrteren
\definesystemvariable {sp} % SelecteerPapier
-\definesystemvariable {sr} % SpacehandleR
-\definesystemvariable {ss} % Symbool
\definesystemvariable {st} % STickers
-\definesystemvariable {su} % SetUp
-\definesystemvariable {sv} % SysteemVariabelen
-\definesystemvariable {sw} % SectionWorld
\definesystemvariable {sx} % Selector
-\definesystemvariable {sy} % SYnchronisatie
\definesystemvariable {ta} % TAb
\definesystemvariable {tb} % TekstBlokken
-\definesystemvariable {td} % TextbackgrounDs
\definesystemvariable {te} % TEmplate
-\definesystemvariable {tf} % TypeFace
-\definesystemvariable {tg} % Tex paGe
\definesystemvariable {ti} % TabelInstellingen
-\definesystemvariable {tk} % Teksten
\definesystemvariable {tl} % TekstLijnen
-\definesystemvariable {tm} % TypesynonyM
-\definesystemvariable {to} % TOlerance
-\definesystemvariable {tp} % TyPen
-\definesystemvariable {tr} % TRacer
-\definesystemvariable {ts} % TypeScript
\definesystemvariable {tt} % TabulaTe
\definesystemvariable {tx} % TeXtflow
-\definesystemvariable {ty} % TYpe
-\definesystemvariable {uc} % Unicode
-\definesystemvariable {ui} % UItvoer
\definesystemvariable {ur} % URl
-\definesystemvariable {up} % Utility Program
-\definesystemvariable {va} % VspAce
-\definesystemvariable {ve} % VErsie
\definesystemvariable {vn} % VoetNoten
-\definesystemvariable {vs} % VSpacing
-\definesystemvariable {vt} % VerTical
-\definesystemvariable {wl} % WordList
-\definesystemvariable {wr} % WitRuimte
-\definesystemvariable {xf} % XML File
-\definesystemvariable {xl} % lxml (mkiv)
-\definesystemvariable {wl} % WidgetLabel
-\definesystemvariable {wc} % WidgetContent
-\definesystemvariable {wt} % WidgetTotal
-\definesystemvariable {ws} % WidgetStack
-\definesystemvariable {wh} % WidgetHelp
-\definesystemvariable {wp} % WidgetPopuphelp
-\definesystemvariable {xm} % xml (mkiv)
-\definesystemvariable {xp} % XML Processing
-\definesystemvariable {xy} % schaal
-\definesystemvariable {za} % ZetspiegelAanpassing
+\definesystemvariable {xf} % XML File (xtag)
+\definesystemvariable {xp} % XML Processing (xtag, so still needed)
+\definesystemvariable {za} % layout adapt % ZetspiegelAanpassing
+\definesystemvariable {zc} % columns
+
+% still used but defined locally
+
+\definesystemvariable {cs} % CharacterSpacing
+\definesystemvariable {ts} % TypeScript
+\definesystemvariable {kk} % Kapitalen
+
+% obsolete but kept for a while (core-obs)
+
+\definesystemvariable {fr} % Division
%D Next we define some language independant one letter
-%D variables and keywords.
-
-\defineinterfaceconstant {x} {x} % x offset
-\defineinterfaceconstant {y} {y} % y offset
-\defineinterfaceconstant {w} {w} % width
-\defineinterfaceconstant {h} {h} % height
-\defineinterfaceconstant {s} {s} % size
-\defineinterfaceconstant {t} {t} % title
-\defineinterfaceconstant {c} {c} % creator
-\defineinterfaceconstant {e} {e} % extension
-\defineinterfaceconstant {f} {f} % file
-
-\defineinterfaceconstant {a} {a} % kunnen weg
-\defineinterfaceconstant {b} {b} % kunnen weg
-\defineinterfaceconstant {c} {c} % kunnen weg
-\defineinterfaceconstant {d} {d} % kunnen weg
-\defineinterfaceconstant {e} {e} % kunnen weg
+%D variables and keywords. We can actually make these
+%D 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}
@@ -740,19 +606,17 @@
\defineinterfaceconstant {a} {a} % alternative
\defineinterfaceconstant {t} {t} % transparency
\defineinterfaceconstant {p} {p} % percentage
-
-\defineinterfaceconstant {t} {t}
\defineinterfaceconstant {h} {h}
-\defineinterfaceconstant {b} {b}
+\defineinterfaceconstant {s} {s}
+\defineinterfaceconstant {v} {v}
\defineinterfaceconstant {rgb} {rgb}
-\defineinterfacevariable {rgb} {rgb}
-
\defineinterfaceconstant {cmyk} {cmyk}
-\defineinterfacevariable {cmyk} {cmyk}
+\defineinterfaceconstant {mp} {mp}
-\defineinterfaceconstant {mp} {mp}
-\defineinterfacevariable {mp} {mp}
+\defineinterfacevariable {rgb} {rgb}
+\defineinterfacevariable {cmyk} {cmyk}
+\defineinterfacevariable {mp} {mp}
\defineinterfacevariable {s} {s}
@@ -770,17 +634,16 @@
%D be recognized by the first two characters of the extension:
%D \type{tu}.
-\definefileconstant {utilityfilename} {texutil}
-
-\definefileconstant {blockextension} {tub}
-\definefileconstant {figureextension} {tuf}
-\definefileconstant {inputextension} {tui}
-\definefileconstant {outputextension} {tuo} % tup for previous run
+%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 {patternsextension} {pat}
+%definefileconstant {hyphensextension} {hyp}
+%definefileconstant {fontmapextension} {map}
\definefileconstant {bibextension} {bbl}
%D These files are loaded at start||up. They may contain system
@@ -794,104 +657,66 @@
\definefileconstant {locfilename} {cont-loc}
\definefileconstant {expfilename} {cont-exp}
-%D Handy for typescripts (we could use s! instead:
-
-\definetypescriptconstant {name} {name}
-\definetypescriptconstant {default} {default}
-\definetypescriptconstant {map} {map}
-\definetypescriptconstant {special} {special}
-\definetypescriptconstant {size} {size}
-
-
%D The setup files for the language, font, color and special
%D subsystems have a common prefix. This means that we have at
%D most three characters for unique filenames.
\definefileconstant {colorprefix} {colo-}
-\definefileconstant {encodingprefix} {enco-}
-\definefileconstant {filterprefix} {filt-}
+%definefileconstant {encodingprefix} {enco-}
+%definefileconstant {filterprefix} {filt-}
\definefileconstant {fontprefix} {font-}
%definefileconstant {handlingprefix} {hand-}
%definefileconstant {javascriptprefix} {java-}
%definefileconstant {languageprefix} {lang-}
-\definefileconstant {mathprefix} {math-}
-\definefileconstant {metapostprefix} {meta-}
+%definefileconstant {mathprefix} {math-}
+%definefileconstant {metapostprefix} {meta-}
%definefileconstant {regimeprefix} {regi-}
%definefileconstant {specialprefix} {spec-}
\definefileconstant {symbolprefix} {symb-}
\definefileconstant {typeprefix} {type-}
-\definefileconstant {xtagprefix} {xtag-}
+%definefileconstant {xtagprefix} {xtag-}
%definefileconstant {propprefix} {prop-}
%definefileconstant {unicprefix} {unic-}
%definefileconstant {sortprefix} {sort-}
%definefileconstant {prettyprefix} {pret-}
-\definefileconstant {moduleprefix} {m-}
-\definefileconstant {styleprefix} {s-}
-\definefileconstant {xstyleprefix} {x-}
-\definefileconstant {privateprefix} {p-}
-\definefileconstant {thirdprefix} {t-}
+%definefileconstant {moduleprefix} {m-}
+%definefileconstant {styleprefix} {s-}
+%definefileconstant {xstyleprefix} {x-}
+%definefileconstant {privateprefix} {p-}
+%definefileconstant {thirdprefix} {t-}
%definefileconstant {beforeprefix} {b-}
%definefileconstant {afterprefix} {a-}
-%D \CONTEXT\ follows different strategies for finding files.
-%D The macros that are responsible for this 'clever' searching
-%D make use of two (very important) path specifiers.
-
-\definefileconstant {pathseparator} {/}
-\definefileconstant {currentpath} {.}
-\definefileconstant {parentpath} {..}
-
-%D The way fonts are defined and called upon is language
-%D independant. We follow the scheme laid down by Knuth in
-%D Plain \TEX. We'll explain their meaning later.
-
-\defineinterfaceconstant {tf} {tf}
-\defineinterfaceconstant {bf} {bf}
-\defineinterfaceconstant {bs} {bs}
-\defineinterfaceconstant {bi} {bi}
-\defineinterfaceconstant {sl} {sl}
-\defineinterfaceconstant {it} {it}
-\defineinterfaceconstant {sc} {sc}
-\defineinterfaceconstant {rm} {rm}
-\defineinterfaceconstant {ss} {ss}
-\defineinterfaceconstant {tt} {tt}
-\defineinterfaceconstant {hw} {hw}
-\defineinterfaceconstant {cg} {cg}
-\defineinterfaceconstant {os} {os}
-\defineinterfaceconstant {mm} {mm}
-\defineinterfaceconstant {i} {i}
-\defineinterfaceconstant {nn} {nn}
-
-\defineinterfaceconstant {x} {x}
-\defineinterfaceconstant {xx} {xx}
-
-\defineinterfaceconstant {em} {em}
-
-\defineinterfaceconstant {mi} {mi}
-\defineinterfaceconstant {sy} {sy}
-\defineinterfaceconstant {ex} {ex}
-\defineinterfaceconstant {mr} {mr}
-
-\defineinterfaceconstant {ma} {ma}
-\defineinterfaceconstant {mb} {mb}
-\defineinterfaceconstant {mc} {mc}
-
-%D For figure inclusion we need:
-
-\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}
-\defineinterfaceconstant {tmp} {tmp}
-\defineinterfaceconstant {cld} {cld}
+% for old times sake:
+
+% \defineinterfaceconstant {x} {x}
+% \defineinterfaceconstant {xx} {xx}
+% \defineinterfaceconstant {em} {em} % will go
+
+% \defineinterfaceconstant {tf} {tf}
+% \defineinterfaceconstant {bf} {bf}
+% \defineinterfaceconstant {bs} {bs}
+% \defineinterfaceconstant {bi} {bi}
+% \defineinterfaceconstant {sl} {sl}
+% \defineinterfaceconstant {it} {it}
+% \defineinterfaceconstant {sc} {sc} % keep, used elsewhere (or define in mult-def)
+
+%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
%D \type{mult-ini} we defined \type{\selectinterface}. We were
diff --git a/Master/texmf-dist/tex/context/base/node-acc.lua b/Master/texmf-dist/tex/context/base/node-acc.lua
index 53740592102..d91bb921b69 100644
--- a/Master/texmf-dist/tex/context/base/node-acc.lua
+++ b/Master/texmf-dist/tex/context/base/node-acc.lua
@@ -14,40 +14,69 @@ local tasks = nodes.tasks
local traverse_nodes = node.traverse
local traverse_id = node.traverse_id
local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
local copy_node = node.copy
local free_nodelist = node.flush_list
local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
+local a_characters = attributes.private("characters")
+
+local threshold = 65536
+
+-- todo: nbsp etc
+-- todo: collapse kerns
+
local function injectspaces(head)
local p
- for n in traverse_nodes(head) do
+ local n = head
+ while n do
local id = n.id
if id == glue_code then -- todo: check for subtype related to spacing (13/14 but most seems to be 0)
- -- local at = has_attribute(n,attribute)
- -- if at then
- if p and p.id == glyph_code then
- local g = copy_node(p)
- local c = g.components
- if c then -- it happens that we copied a ligature
- free_nodelist(c)
- g.components = nil
- g.subtype = 256
- end
- local s = copy_node(n.spec)
- g.char, n.spec = 32, s
- p.next, g.prev = g, p
- g.next, n.prev = n, g
- s.width = s.width - g.width
+--~ if n.spec.width > 0 then -- threshold
+ if p and p.id == glyph_code then
+ local g = copy_node(p)
+ local c = g.components
+ if c then -- it happens that we copied a ligature
+ free_nodelist(c)
+ g.components = nil
+ g.subtype = 256
end
- -- end
+ local a = has_attribute(n,a_characters)
+ local s = copy_node(n.spec)
+ g.char, n.spec = 32, s
+ p.next, g.prev = g, p
+ g.next, n.prev = n, g
+ s.width = s.width - g.width
+ if a then
+ set_attribute(g,a_characters,a)
+ end
+ set_attribute(s,a_characters,0)
+ set_attribute(n,a_characters,0)
+ end
+--~ end
elseif id == hlist_code or id == vlist_code then
injectspaces(n.list,attribute)
+ -- elseif id == kern_code then -- the backend already collapses
+ -- local first = n
+ -- while true do
+ -- local nn = n.next
+ -- if nn and nn.id == kern_code then
+ -- -- maybe we should delete kerns but who cares at this stage
+ -- first.kern = first.kern + nn.kern
+ -- nn.kern = 0
+ -- n = nn
+ -- else
+ -- break
+ -- end
+ -- end
end
p = n
+ n = n.next
end
return head, true
end
diff --git a/Master/texmf-dist/tex/context/base/node-aux.lua b/Master/texmf-dist/tex/context/base/node-aux.lua
index 0b44f77248d..43624adfd3a 100644
--- a/Master/texmf-dist/tex/context/base/node-aux.lua
+++ b/Master/texmf-dist/tex/context/base/node-aux.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['node-aux'] = {
license = "see context related readme files"
}
+-- todo: n1 .. n2 : __concat metatable
+
local type, tostring = type, tostring
local nodes, node = nodes, node
@@ -37,6 +39,8 @@ local slide_nodes = node.slide
local insert_node_after = node.insert_after
local isnode = node.is_node
+local current_font = font.current()
+
local texbox = tex.box
function nodes.repackhlist(list,...)
@@ -308,6 +312,8 @@ local function link(head,tail,list,currentfont,currentattr)
tail = n
end
end
+ else
+ -- permitting nil is convenient
end
end
return head, tail
@@ -317,3 +323,39 @@ function nodes.link(...)
local currentfont = font.current
return link(nil,nil,{...},currentfont,currentattr)
end
+
+local function locate(start,wantedid,wantedsubtype)
+ for n in traverse_nodes(start) do
+ local id = n.id
+ if id == wantedid then
+ if not wantedsubtype or n.subtype == wantedsubtype then
+ return n
+ end
+ elseif id == hlist_code or id == vlist_code then
+ local found = locate(n.list,wantedid,wantedsubtype)
+ if found then
+ return found
+ end
+ end
+ end
+end
+
+nodes.locate = locate
+
+function nodes.concat(list) -- no slide !
+ local head, tail
+ for i=1,#list do
+ local li = list[i]
+ if not li then
+ -- skip
+ elseif head then
+ tail.next = li
+ li.prev = tail
+ tail = li
+ else
+ head = li
+ tail = li
+ end
+ end
+ return head, tail
+end
diff --git a/Master/texmf-dist/tex/context/base/node-bck.lua b/Master/texmf-dist/tex/context/base/node-bck.lua
index e1e4d46525e..a0044eb7898 100644
--- a/Master/texmf-dist/tex/context/base/node-bck.lua
+++ b/Master/texmf-dist/tex/context/base/node-bck.lua
@@ -31,7 +31,7 @@ local a_transparency = attributes.private('transparency')
local a_colorspace = attributes.private('colormodel')
local a_background = attributes.private('background')
-local function add_backgrounds(head) -- boxes, inline will be done too
+local function add_backgrounds(head)
local id = head.id
if id == vlist_code or id == hlist_code then
local current = head.list
diff --git a/Master/texmf-dist/tex/context/base/node-bck.mkiv b/Master/texmf-dist/tex/context/base/node-bck.mkiv
index 88fb390a9ed..858bd40b76f 100644
--- a/Master/texmf-dist/tex/context/base/node-bck.mkiv
+++ b/Master/texmf-dist/tex/context/base/node-bck.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Backgrounds,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -20,53 +20,70 @@
\registerctxluafile{node-bck}{1.001}
-\def\doinitializeboxbackgrounds
+\def\node_backgrounds_boxes_initialize % will move to lua
{\ctxlua{nodes.tasks.enableaction("shipouts","nodes.handlers.backgrounds")}%
- \glet\doinitializeboxbackgrounds\donothing}
-
-%D Box helpers:
+ \glet\node_backgrounds_boxes_initialize\donothing}
% \backgroundvbox[green] {\input tufte } \par
% \backgroundvbox[blue] {\input ward } \par
% \backgroundvbox[red] {\input knuth } \par
% \backgroundhbox[yellow]{\rotate[rotation=45]{hello world}} \par
-\def\doaddbackgroundtobox#1[#2]%
- {\begingroup\doinitializeboxbackgrounds\faststartcolor[#2]%
- \normalexpanded{\noexpand\faststopcolor\endgroup#1
- attr \backgroundattribute \plusone
- attr \colormodelattribute \the\attribute\colormodelattribute
- attr \colorattribute \the\attribute\colorattribute
- attr \transparencyattribute \the\attribute\transparencyattribute}}
-
-\def\backgroundvbox{\doaddbackgroundtobox\vbox}
-\def\backgroundvtop{\doaddbackgroundtobox\vtop}
-\def\backgroundhbox{\doaddbackgroundtobox\hbox}
-
\def\colorattr#1%
- {\ifcsname(cs:\currentpalet#1)\endcsname
- \thecolorattr{\currentpalet#1}%
- \else\ifcsname(cs:#1)\endcsname
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \thecolorattr{\currentcolorprefix#1}%
+ \else\ifcsname\??colorattribute#1\endcsname
\thecolorattr{#1}%
\fi\fi}
\def\thecolorattr#1%
{attr \colormodelattribute \attribute\colormodelattribute
- attr \colorattribute \csname(cs:#1)\endcsname
- attr \transparencyattribute \csname(ts:#1)\endcsname}
+ attr \colorattribute \csname\??colorattribute #1\endcsname
+ attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized
\def\backgroundcolorattr#1%
- {\ifcsname(cs:\currentpalet#1)\endcsname
- \thebackgroundcolorattr{\currentpalet#1}%
- \else\ifcsname(cs:#1)\endcsname
+ {\ifcsname\??colorattribute\currentcolorprefix#1\endcsname
+ \thebackgroundcolorattr{\currentcolorprefix#1}%
+ \else\ifcsname\??colorattribute#1\endcsname
\thebackgroundcolorattr{#1}%
\fi\fi}
\def\thebackgroundcolorattr#1%
{attr \backgroundattribute \plusone
attr \colormodelattribute \attribute\colormodelattribute
- attr \colorattribute \csname(cs:#1)\endcsname
- attr \transparencyattribute \csname(ts:#1)\endcsname}
+ attr \colorattribute \csname\??colorattribute#1\endcsname
+ attr \transparencyattribute \thetransparencyattribute{#1} } % can be optimized
+
+\unexpanded\def\backgroundhbox{\node_backgrounds_boxes_add\hbox}
+\unexpanded\def\backgroundvbox{\node_backgrounds_boxes_add\vbox}
+\unexpanded\def\backgroundvtop{\node_backgrounds_boxes_add\vtop}
+
+% \def\node_backgrounds_boxes_add#1[#2]%
+% {\begingroup
+% \node_backgrounds_boxes_initialize
+% \dousecolorparameter{#2}%
+% \normalexpanded{\endgroup#1
+% attr \backgroundattribute \plusone
+% attr \colormodelattribute \the\attribute\colormodelattribute
+% attr \colorattribute \the\attribute\colorattribute
+% attr \transparencyattribute \the\attribute\transparencyattribute}}
+%
+% more efficient:
+
+\def\node_backgrounds_boxes_add#1[#2]%
+ {\node_backgrounds_boxes_initialize
+ #1\backgroundcolorattr{#2}}
+
+% less argument carry over:
+%
+% \def\node_backgrounds_boxes_add#1[#2]%
+% {\node_backgrounds_boxes_initialize#1%
+% \ifcsname\??colorattribute\currentcolorprefix#2\endcsname
+% \thebackgroundcolorattr{\currentcolorprefix#2}%
+% \else\ifcsname\??colorattribute#2\endcsname
+% \thebackgroundcolorattr{#2}%
+% \fi\fi}
+
% \def\backgroundvbox[#1]{\vbox \backgroundcolorattr{#1}}
% \def\backgroundvtop[#1]{\vtop \backgroundcolorattr{#1}}
diff --git a/Master/texmf-dist/tex/context/base/node-fin.mkiv b/Master/texmf-dist/tex/context/base/node-fin.mkiv
index ffa4b8bf554..09bac6c087d 100644
--- a/Master/texmf-dist/tex/context/base/node-fin.mkiv
+++ b/Master/texmf-dist/tex/context/base/node-fin.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Finalizing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -18,16 +18,17 @@
\unprotect
+\registerctxluafile{node-shp}{1.001}
\registerctxluafile{node-fin}{1.001} % we might generalize this one
-\definesystemattribute[trigger][public]
+% we might have two variants at some point (efficiency)
-\def\finalizeobjectbox #1{\ctxlua{nodes.handlers.finalize(tex.box[\number#1])}}
-\def\finalizeshipoutbox#1{\ctxlua{nodes.handlers.finalize(tex.box[\number#1])}}
+\def\finalizeobjectbox #1{\ctxcommand{finalizebox(\number#1)}}
+\def\finalizeshipoutbox#1{\ctxcommand{finalizebox(\number#1)}}
-% tricky stuff:
+% Tricky stuff: this might become obsolete.
-% THIS MIGHT BECOME OBSOLETE.
+\definesystemattribute[trigger][public]
\newcount\attributeboxcount
diff --git a/Master/texmf-dist/tex/context/base/node-fnt.lua b/Master/texmf-dist/tex/context/base/node-fnt.lua
index 7ceb96f80ad..66cd9916fe5 100644
--- a/Master/texmf-dist/tex/context/base/node-fnt.lua
+++ b/Master/texmf-dist/tex/context/base/node-fnt.lua
@@ -9,7 +9,7 @@ if not modules then modules = { } end modules ['node-fnt'] = {
if not context then os.exit() end -- generic function in node-dum
local next, type = next, type
-local concat = table.concat
+local concat, keys = table.concat, table.keys
local nodes, node, fonts = nodes, node, fonts
@@ -96,7 +96,9 @@ function handlers.characters(head)
end
end
for n in traverse_id(glyph_code,head) do
- local font, attr = n.font, has_attribute(n,0) or 0 -- zero attribute is reserved for fonts in context
+-- if n.subtype<256 then
+ local font = n.font
+ local attr = has_attribute(n,0) or 0 -- zero attribute is reserved for fonts in context
if font ~= prevfont or attr ~= prevattr then
if attr > 0 then
local used = attrfonts[font]
@@ -111,6 +113,8 @@ function handlers.characters(head)
if d then
used[attr] = d
a = a + 1
+ else
+ -- can't happen ... otherwise best use nil/false distinction
end
end
end
@@ -121,17 +125,20 @@ function handlers.characters(head)
if fp then
usedfonts[font] = fp
u = u + 1
+ else
+ -- can't happen ... otherwise best use nil/false distinction
end
end
end
prevfont = font
prevattr = attr
end
+-- end
end
if trace_fontrun then
report_fonts()
- report_fonts("statics : %s",(u > 0 and concat(table.keys(usedfonts)," ")) or "none")
- report_fonts("dynamics: %s",(a > 0 and concat(table.keys(attrfonts)," ")) or "none")
+ report_fonts("statics : %s",(u > 0 and concat(keys(usedfonts)," ")) or "none")
+ report_fonts("dynamics: %s",(a > 0 and concat(keys(attrfonts)," ")) or "none")
report_fonts()
end
-- we could combine these and just make the attribute nil
diff --git a/Master/texmf-dist/tex/context/base/node-ini.lua b/Master/texmf-dist/tex/context/base/node-ini.lua
index eb70fa6e6d1..0ed17a1b5ef 100644
--- a/Master/texmf-dist/tex/context/base/node-ini.lua
+++ b/Master/texmf-dist/tex/context/base/node-ini.lua
@@ -15,9 +15,10 @@ modules.</p>
local utf = unicode.utf8
local next, type = next, type
-local format, concat, match, gsub = string.format, table.concat, string.match, string.gsub
+local format, match, gsub = string.format, string.match, string.gsub
+local concat, remove = table.concat, table.remove
+local sortedhash, sortedkeys, swapped, tohash = table.sortedhash, table.sortedkeys, table.swapped, table.tohash
local utfchar = utf.char
-local swapped = table.swapped
local lpegmatch = lpeg.match
local formatcolumns = utilities.formatters.formatcolumns
@@ -93,6 +94,12 @@ local skipcodes = allocate {
[18] = "thickmuskip",
}
+local penaltycodes = allocate { -- unfortunately not used
+ [ 0] = "userpenalty",
+}
+
+table.setmetatableindex(penaltycodes,function(t,k) return "userpenalty" end) -- not used anyway
+
local noadcodes = allocate {
[ 0] = "ord",
[ 1] = "opdisplaylimits",
@@ -157,25 +164,27 @@ end
local nodecodes = simplified(node.types())
local whatcodes = simplified(node.whatsits())
-skipcodes = allocate(swapped(skipcodes, skipcodes ))
-noadcodes = allocate(swapped(noadcodes, noadcodes ))
-nodecodes = allocate(swapped(nodecodes, nodecodes ))
-whatcodes = allocate(swapped(whatcodes, whatcodes ))
-listcodes = allocate(swapped(listcodes, listcodes ))
-glyphcodes = allocate(swapped(glyphcodes,glyphcodes))
-kerncodes = allocate(swapped(kerncodes, kerncodes ))
-mathcodes = allocate(swapped(mathcodes, mathcodes ))
-fillcodes = allocate(swapped(fillcodes, fillcodes ))
-
-nodes.skipcodes = skipcodes nodes.gluecodes = skipcodes -- more official
-nodes.noadcodes = noadcodes
-nodes.nodecodes = nodecodes
-nodes.whatcodes = whatcodes nodes.whatsitcodes = whatcodes -- more official
-nodes.listcodes = listcodes
-nodes.glyphcodes = glyphcodes
-nodes.kerncodes = kerncodes
-nodes.mathcodes = mathcodes
-nodes.fillcodes = fillcodes
+skipcodes = allocate(swapped(skipcodes, skipcodes ))
+noadcodes = allocate(swapped(noadcodes, noadcodes ))
+nodecodes = allocate(swapped(nodecodes, nodecodes ))
+whatcodes = allocate(swapped(whatcodes, whatcodes ))
+listcodes = allocate(swapped(listcodes, listcodes ))
+glyphcodes = allocate(swapped(glyphcodes, glyphcodes))
+kerncodes = allocate(swapped(kerncodes, kerncodes ))
+penaltycodes = allocate(swapped(penaltycodes, penaltycodes ))
+mathcodes = allocate(swapped(mathcodes, mathcodes ))
+fillcodes = allocate(swapped(fillcodes, fillcodes ))
+
+nodes.skipcodes = skipcodes nodes.gluecodes = skipcodes -- more official
+nodes.noadcodes = noadcodes
+nodes.nodecodes = nodecodes
+nodes.whatcodes = whatcodes nodes.whatsitcodes = whatcodes -- more official
+nodes.listcodes = listcodes
+nodes.glyphcodes = glyphcodes
+nodes.kerncodes = kerncodes
+nodes.penaltycodes = kerncodes
+nodes.mathcodes = mathcodes
+nodes.fillcodes = fillcodes
listcodes.row = listcodes.alignment
listcodes.column = listcodes.alignment
@@ -196,8 +205,8 @@ nodes.codes = allocate {
function nodes.showcodes()
local t = { }
- for name, codes in table.sortedhash(nodes.codes) do
- local sorted = table.sortedkeys(codes)
+ 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
@@ -213,7 +222,7 @@ end
local whatsit_node = nodecodes.whatsit
-local messyhack = table.tohash { -- temporary solution
+local messyhack = tohash { -- temporary solution
nodecodes.attributelist,
nodecodes.attribute,
nodecodes.gluespec,
@@ -229,7 +238,7 @@ function nodes.fields(n)
if messyhack[id] then
for i=1,#t do
if t[i] == "subtype" then
- table.remove(t,i)
+ remove(t,i)
break
end
end
diff --git a/Master/texmf-dist/tex/context/base/node-ini.mkiv b/Master/texmf-dist/tex/context/base/node-ini.mkiv
index 8d048122f5d..79e02ff46e4 100644
--- a/Master/texmf-dist/tex/context/base/node-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/node-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -15,7 +15,7 @@
\unprotect
-\newcount\filterstate \filterstate\plusone
+\newcount\filterstate \filterstate\plusone % hm, public
\registerctxluafile{node-ini}{1.001}
\registerctxluafile{node-res}{1.001}
@@ -26,21 +26,22 @@
\registerctxluafile{node-tsk}{1.001}
\registerctxluafile{node-tex}{1.001}
\registerctxluafile{node-pro}{1.001}
-\registerctxluafile{node-shp}{1.001}
+%registerctxluafile{node-shp}{1.001} % moved to node-fin.mkiv
\registerctxluafile{node-ser}{1.001}
\registerctxluafile{node-ext}{1.001}
%registerctxluafile{node-inj}{1.001} % we might split it off
-\registerctxluafile{node-typ}{1.001} % experimental
\registerctxluafile{node-acc}{1.001} % experimental
-\newcount\shownodescounter
+\newcount\c_node_tracers_show_box % box number
-\def\shownextnodes {\afterassignment\doshownodes\shownextnodescounter}
-\def\showflatnodes {\afterassignment\doshownodes\showflatnodescounter}
-\def\doshownextnodes {\ctxlua{texio.write_nl('log',nodes.serializebox(\number\shownodescounter,false,true))}}
-\def\doshowflatnodes {\ctxlua{texio.write_nl('log',nodes.serializebox(\number\shownodescounter,true, true))}}
-\def\visualizenextnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,false,true)}}}
-\def\visualizeflatnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,true,true)}}}
+\unexpanded\def\shownextnodes{\afterassignment\node_tracers_show_next\c_node_tracers_show_box}
+\unexpanded\def\showflatnodes{\afterassignment\node_tracers_show_flat\c_node_tracers_show_box}
+
+\def\node_tracers_show_next{\ctxlua{texio.write_nl('log',nodes.serializebox(\number\c_node_tracers_show_box,false,true))}}
+\def\node_tracers_show_flat{\ctxlua{texio.write_nl('log',nodes.serializebox(\number\c_node_tracers_show_box,true, true))}}
+
+\unexpanded\def\visualizenextnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,false,true)}}}
+\unexpanded\def\visualizeflatnodes{\dowithnextbox{\ctxlua{nodes.visualizebox(\number\nextbox,true,true)}}}
\unexpanded\def\starttracingnodes[#1]{\ctxlua{nodes.tracers.characters.start("#1")}}
\unexpanded\def\stoptracingnodes {\ctxlua{nodes.tracers.characters.stop()}}
diff --git a/Master/texmf-dist/tex/context/base/node-inj.lua b/Master/texmf-dist/tex/context/base/node-inj.lua
index b9ef9188f94..246aaade2c0 100644
--- a/Master/texmf-dist/tex/context/base/node-inj.lua
+++ b/Master/texmf-dist/tex/context/base/node-inj.lua
@@ -34,6 +34,7 @@ local traverse_id = node.traverse_id
local unset_attribute = node.unset_attribute
local has_attribute = node.has_attribute
local set_attribute = node.set_attribute
+local copy_node = node.copy
local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
@@ -44,17 +45,38 @@ local cursbase = attributes.private('cursbase')
local curscurs = attributes.private('curscurs')
local cursdone = attributes.private('cursdone')
local kernpair = attributes.private('kernpair')
+local ligacomp = attributes.private('ligacomp')
+local fontkern = attributes.private('fontkern')
+
+if context then
+
+ local kern = nodes.pool.register(newkern())
+
+ set_attribute(kern,fontkern,1) -- we can have several, attributes are shared
+
+ newkern = function(k)
+ local c = copy_node(kern)
+ c.kern = k
+ return c
+ end
+
+end
+
+-- This injector has been tested by Idris Samawi Hamid (several arabic fonts as well as
+-- the rather demanding Husayni font), Khaled Hosny (latin and arabic) and Kaj Eigner
+-- (arabic, hebrew and thai) and myself (whatever font I come across). I'm pretty sure
+-- that this code is not 100% okay but examples are needed to figure things out.
local cursives = { }
local marks = { }
local kerns = { }
--- currently we do gpos/kern in a bit inofficial way but when we
--- have the extra fields in glyphnodes to manipulate ht/dp/wd
--- explicitly i will provide an alternative; also, we can share
--- tables
+-- Currently we do gpos/kern in a bit inofficial way but when we have the extra fields in
+-- glyphnodes to manipulate ht/dp/wd explicitly I will provide an alternative; also, we
+-- can share tables.
--- for the moment we pass the r2l key ... volt/arabtype tests
+-- For the moment we pass the r2l key ... volt/arabtype tests .. idris: this needs
+-- checking with husayni (volt and fontforge).
function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
local dx, dy = factor*(exit[1]-entry[1]), factor*(exit[2]-entry[2])
@@ -97,14 +119,16 @@ function injections.setkern(current,factor,rlmode,x,tfmchr)
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,index) --ba=baseanchor, ma=markanchor
- local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
- local bound = has_attribute(base,markbase)
+function injections.setmark(start,base,factor,rlmode,ba,ma,index) -- ba=baseanchor, ma=markanchor
+ local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2]) -- the index argument is no longer used but when this
+ local bound = has_attribute(base,markbase) -- fails again we should pass it
+local index = 1
if bound then
local mb = marks[bound]
if mb then
- if not index then index = #mb + 1 end
- mb[index] = { dx, dy }
+ -- if not index then index = #mb + 1 end
+index = #mb + 1
+ mb[index] = { dx, dy, rlmode }
set_attribute(start,markmark,bound)
set_attribute(start,markdone,index)
return dx, dy, bound
@@ -112,6 +136,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,index) --ba=baseancho
report_injections("possible problem, U+%05X is base mark without data (id: %s)",base.char,bound)
end
end
+-- index = index or 1
index = index or 1
bound = #marks + 1
set_attribute(base,markbase,bound)
@@ -158,7 +183,7 @@ local function trace(head)
end
else
m = m[1]
- report_injections(" markmark: bound=%s, dx=%s, dy=%s",mm,m[1] or "?",m[2] or "?")
+ report_injections(" markmark: bound=%s, dx=%s, dy=%s",mm,m and m[1] or "?",m and m[2] or "?")
end
end
if cb then
@@ -176,7 +201,8 @@ end
-- todo: reuse tables (i.e. no collection), but will be extra fields anyway
-- todo: check for attribute
--- we can have a fast test on a font being processed, so we can check faster for marks etc
+-- We can have a fast test on a font being processed, so we can check faster for marks etc
+-- but I'll make a context variant anyway.
function injections.handler(head,where,keep)
local has_marks, has_cursives, has_kerns = next(marks), next(cursives), next(kerns)
@@ -314,6 +340,7 @@ function injections.handler(head,where,keep)
local p_markbase = has_attribute(p,markbase)
if p_markbase then
local mrks = marks[p_markbase]
+ local nofmarks = #mrks
for n in traverse_id(glyph_code,p.next) do
local n_markmark = has_attribute(n,markmark)
if p_markbase == n_markmark then
@@ -327,7 +354,7 @@ function injections.handler(head,where,keep)
-- that makes sense but we no longer do that so as a
-- consequence the sign of p.width was changed (we need
-- to keep an eye on it as we don't have that many fonts
- -- that enter this branch .. i'm still not sure if this
+ -- that enter this branch .. I'm still not sure if this
-- one is right
local k = wx[p]
if k then
@@ -350,9 +377,14 @@ function injections.handler(head,where,keep)
else
n.yoffset = n.yoffset + p.yoffset + d[2]
end
+ if nofmarks == 1 then
+ break
+ else
+ nofmarks = nofmarks - 1
+ end
end
else
- break
+ -- KE: there can be <mark> <mkmk> <mark> sequences in ligatures
end
end
end
@@ -364,23 +396,32 @@ function injections.handler(head,where,keep)
-- todo : combine
if next(wx) then
for n, k in next, wx do
- -- only w can be nil, can be sped up when w == nil
- local rl, x, w, r2l = k[1], k[2] or 0, k[4] or 0, k[6]
- local wx = w - x
- if r2l then
- if wx ~= 0 then
- insert_node_before(head,n,newkern(wx))
- end
- if x ~= 0 then
- insert_node_after (head,n,newkern(x))
- end
- else
- if x ~= 0 then
- insert_node_before(head,n,newkern(x))
- end
- if wx ~= 0 then
- insert_node_after(head,n,newkern(wx))
+ -- only w can be nil (kernclasses), can be sped up when w == nil
+ local x, w = k[2] or 0, k[4]
+ if w then
+ local rl = k[1] -- r2l = k[6]
+ local wx = w - x
+ if rl < 0 then -- KE: don't use r2l here
+ if wx ~= 0 then
+ insert_node_before(head,n,newkern(wx))
+ end
+ if x ~= 0 then
+ insert_node_after (head,n,newkern(x))
+ end
+ else
+ if x ~= 0 then
+ insert_node_before(head,n,newkern(x))
+ end
+ if wx ~= 0 then
+ insert_node_after(head,n,newkern(wx))
+ end
end
+ elseif x ~= 0 then
+ -- this needs checking for rl < 0 but it is unlikely that a r2l script
+ -- uses kernclasses between glyphs so we're probably safe (KE has a
+ -- problematic font where marks interfere with rl < 0 in the previous
+ -- case)
+ insert_node_before(head,n,newkern(x))
end
end
end
@@ -419,9 +460,9 @@ function injections.handler(head,where,keep)
end
if w then
-- copied from above
- local r2l = kk[6]
+ -- local r2l = kk[6]
local wx = w - x
- if r2l then
+ if rl < 0 then -- KE: don't use r2l here
if wx ~= 0 then
insert_node_before(head,n,newkern(wx))
end
diff --git a/Master/texmf-dist/tex/context/base/node-mig.lua b/Master/texmf-dist/tex/context/base/node-mig.lua
index 620cb3c0e55..1384f6024d0 100644
--- a/Master/texmf-dist/tex/context/base/node-mig.lua
+++ b/Master/texmf-dist/tex/context/base/node-mig.lua
@@ -28,7 +28,7 @@ local trace_migrations = false trackers.register("nodes.migrations", function(v)
local report_nodes = logs.reporter("nodes","migrations")
-local migrate_inserts, migrate_marks
+local migrate_inserts, migrate_marks, inserts_too
local t_inserts, t_marks, t_sweeps = 0, 0, 0
@@ -38,7 +38,7 @@ local function locate(head,first,last,ni,nm)
local id = current.id
if id == vlist_code or id == hlist_code then
current.list, first, last, ni, nm = locate(current.list,first,last,ni,nm)
- current= current.next
+ current = current.next
elseif migrate_inserts and id == insert_code then
local insert
head, current, insert = remove_nodes(head,current)
@@ -69,10 +69,15 @@ end
function nodes.handlers.migrate(head,where)
local done = false
if head then
+ if trace_migrations then
+ report_nodes("migration sweep '%s'",where)
+ end
local current = head
while current do
local id = current.id
- if id == vlist_code or id == hlist_code and not has_attribute(current,migrated) then
+ -- inserts_too is a temp hack, we should only do them when it concerns
+ -- newly placed (flushed) inserts
+ if id == vlist_code or id == hlist_code or (inserts_too and id == insert_code) and not has_attribute(current,migrated) then
set_attribute(current,migrated,1)
t_sweeps = t_sweeps + 1
local h = current.list
@@ -87,7 +92,8 @@ function nodes.handlers.migrate(head,where)
if first then
t_inserts, t_marks = t_inserts + ni, t_marks + nm
if trace_migrations and (ni > 0 or nm > 0) then
- report_nodes("sweep %s, %s inserts and %s marks migrated outwards",t_sweeps,ni,nm)
+ report_nodes("sweep %s, container %s, %s inserts and %s marks migrated outwards during '%s'",
+ t_sweeps,nodecodes[id],ni,nm,where)
end
-- inserts after head
local n = current.next
@@ -120,6 +126,13 @@ experiments.register("inserts.migrate", function(v)
migrate_inserts = v
end)
+experiments.register("inserts.migrate.nested", function(v)
+ if v then
+ tasks.enableaction("mvlbuilders", "nodes.handlers.migrate")
+ end
+ inserts_too = v
+end)
+
statistics.register("node migrations", function()
if trace_migrations and t_sweeps > 0 then
return format("%s sweeps, %s inserts moved, %s marks moved",t_sweeps,t_inserts,t_marks)
diff --git a/Master/texmf-dist/tex/context/base/node-mig.mkiv b/Master/texmf-dist/tex/context/base/node-mig.mkiv
index c07f5ed5b78..143fd4466e5 100644
--- a/Master/texmf-dist/tex/context/base/node-mig.mkiv
+++ b/Master/texmf-dist/tex/context/base/node-mig.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Inserts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -42,15 +42,15 @@
\registerctxluafile{node-mig}{1.001}
-\newtoks \everyautomigratefootnotes
-\newtoks \everyautomigratemarks
+\newtoks\everyautomigratefootnotes
+\newtoks\everyautomigratemarks
\def\automigrateinserts{\the\everyautomigratefootnotes} % soon default but does not work (yet) for notes in captions (themselves inserts)
\def\automigratemarks {\the\everyautomigratemarks}
\appendtoks
\let\postponenotes\relax
- \enableexperiments[inserts.migrate]%
+ \enableexperiments[inserts.migrate,inserts.migrate.nested]%
\to \everyautomigratefootnotes
\appendtoks
diff --git a/Master/texmf-dist/tex/context/base/node-pag.mkiv b/Master/texmf-dist/tex/context/base/node-pag.mkiv
index 487901ad043..b8ed197fe64 100644
--- a/Master/texmf-dist/tex/context/base/node-pag.mkiv
+++ b/Master/texmf-dist/tex/context/base/node-pag.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Page Building,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/node-par.lua b/Master/texmf-dist/tex/context/base/node-par.lua
index b0879c7506b..8eafd1f6e52 100644
--- a/Master/texmf-dist/tex/context/base/node-par.lua
+++ b/Master/texmf-dist/tex/context/base/node-par.lua
@@ -89,7 +89,9 @@ end
-- pre and post hooks and only one parbuilder makes sense, so no:
--
-- local actions = nodes.tasks.actions("parbuilders")
-
+--
+-- yet (maybe some day).
+--
-- todo: enable one as main
local actions = constructors.handler
diff --git a/Master/texmf-dist/tex/context/base/node-par.mkiv b/Master/texmf-dist/tex/context/base/node-par.mkiv
index 2e9efde1f3c..685167e8a90 100644
--- a/Master/texmf-dist/tex/context/base/node-par.mkiv
+++ b/Master/texmf-dist/tex/context/base/node-par.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Paragraph Building,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -36,26 +36,30 @@
% management (enable/disable) is global and will move to lua
-\newcount\nofparbuilders
+\installcorenamespace {parbuilder}
+
+\newcount\c_node_paragraphs_n_of_builders
+
+\let\m_node_paragraphs_current_builder\empty
\unexpanded\def\defineparbuilder[#1]%
- {\global\advance\nofparbuilders\plusone
- \ctxlua{builders.paragraphs.constructors.register("#1",\number\nofparbuilders)}%
- \setxvalue{\??ng:#1}{\attribute\parbuilderattribute\nofparbuilders}}
+ {\global\advance\c_node_paragraphs_n_of_builders\plusone
+ \ctxlua{builders.paragraphs.constructors.register("#1",\number\c_node_paragraphs_n_of_builders)}%
+ \setxvalue{\??parbuilder#1}{\attribute\parbuilderattribute\number\c_node_paragraphs_n_of_builders}}
\unexpanded\def\startparbuilder[#1]%
- {\edef\@@currentparbuilder{\number\attribute\parbuilderattribute}%
- \globalpushmacro\@@currentparbuilder
- \getvalue{\??ng:#1}%
- \checkparbuilders}
+ {\edef\m_node_paragraphs_current_builder{\number\attribute\parbuilderattribute}%
+ \globalpushmacro\m_node_paragraphs_current_builder
+ \getvalue{\??parbuilder#1}\relax
+ \node_paragraphs_builders_check}
\unexpanded\def\stopparbuilder
{\ifhmode\par\fi
- \globalpopmacro\@@currentparbuilder
- \attribute\parbuilderattribute\@@currentparbuilder\relax
- \checkparbuilders}
+ \globalpopmacro\m_node_paragraphs_current_builder
+ \attribute\parbuilderattribute\m_node_paragraphs_current_builder\relax
+ \node_paragraphs_builders_check}
-\def\setmainparbuilder[#1]%
+\unexpanded\def\setmainparbuilder[#1]%
{\ctxlua{builders.paragraphs.constructors.set("#1")}}
% no high level interface, after all implementing a linebreaker is not something that
@@ -68,7 +72,7 @@
\def\enableparbuilders {\ctxlua{builders.paragraphs.constructors.enable ()}}
\def\disableparbuilders{\ctxlua{builders.paragraphs.constructors.disable()}}
-\def\checkparbuilders % can be more efficient as we don't want to do this to often
+\def\node_paragraphs_builders_check % can be made more efficient as we don't want to do this too often
{\ifcase\attribute\parbuilderattribute
\disableparbuilders
\else
diff --git a/Master/texmf-dist/tex/context/base/node-pro.lua b/Master/texmf-dist/tex/context/base/node-pro.lua
index 2d04a4d7185..73d22697e05 100644
--- a/Master/texmf-dist/tex/context/base/node-pro.lua
+++ b/Master/texmf-dist/tex/context/base/node-pro.lua
@@ -16,15 +16,16 @@ local report_nodes = logs.reporter("nodes","processors")
local nodes, node = nodes, node
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
-local tasks = nodes.tasks
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local tasks = nodes.tasks
-local free_node = node.free
-local first_glyph = node.first_glyph or node.first_character
+local free_node = node.free
+local first_glyph = node.first_glyph or node.first_character
+local has_attribute = node.has_attribute
-nodes.processors = nodes.processors or { }
-local processors = nodes.processors
+nodes.processors = nodes.processors or { }
+local processors = nodes.processors
-- vbox: grouptype: vbox vtop output split_off split_keep | box_type: exactly|aditional
-- hbox: grouptype: hbox adjusted_hbox(=hbox_in_vmode) | box_type: exactly|aditional
diff --git a/Master/texmf-dist/tex/context/base/node-ref.lua b/Master/texmf-dist/tex/context/base/node-ref.lua
index 19d602ed673..dc14102827f 100644
--- a/Master/texmf-dist/tex/context/base/node-ref.lua
+++ b/Master/texmf-dist/tex/context/base/node-ref.lua
@@ -16,6 +16,8 @@ if not modules then modules = { } end modules ['node-bck'] = {
-- is grouplevel still used?
+local format = string.format
+
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
local cleanupreferences, cleanupdestinations = false, true
@@ -102,7 +104,7 @@ end
local function inject_range(head,first,last,reference,make,stack,parent,pardir,txtdir)
local width, height, depth = dimensions(parent,first,last)
- if pardir == "TRT" or txtdir == "+TRT" then
+ if txtdir == "+TRT" or (txtdir == "===" and pardir == "TRT") then -- KH: textdir == "===" test added
width = - width
end
local result, resolved = make(width,height,depth,reference)
@@ -178,6 +180,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
width = - width
end
local result, resolved = make(width,height,depth,reference)
+ -- todo: only when width is ok
if result and resolved then
if trace_backend then
report_area("box: %04i %s %s: w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",width,height,depth,resolved)
@@ -220,7 +223,7 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
elseif id == glue_code and current.subtype == leftskip_code then -- any glue at the left?
--
elseif id == hlist_code or id == vlist_code then
--- somehow reference is true so teh following fails (second one not done) in
+-- somehow reference is true so the following fails (second one not done) in
-- test \goto{test}[page(2)] test \gotobox{test}[page(2)]
-- so let's wait till this fails again
-- if not reference and r and (not skip or r > skip) then -- > or ~=
@@ -294,7 +297,6 @@ end
-- tracing
-
local nodepool = nodes.pool
local new_rule = nodepool.rule
@@ -310,7 +312,7 @@ local u_transparency = nil
local u_colors = { }
local force_gray = true
-local function colorize(width,height,depth,n)
+local function colorize(width,height,depth,n,reference,what)
if force_gray then n = 0 end
u_transparency = u_transparency or transparencies.register(nil,2,.65)
local ucolor = u_colors[n]
@@ -328,11 +330,12 @@ local function colorize(width,height,depth,n)
u_colors[n] = u_color
end
if width == 0 then
- report_area("reference %s has no horizontal dimensions: width=%s, height=%s, depth=%s",reference,width,height,depth)
+ -- probably a strut as placeholder
+ report_area("%s %s has no horizontal dimensions: width=%s, height=%s, depth=%s",what,reference,width,height,depth)
width = 65536
end
if height + depth <= 0 then
- report_area("reference %s has no vertical dimensions: width=%s, height=%s, depth=%s",reference,width,height,depth)
+ report_area("%s %s has no vertical dimensions: width=%s, height=%s, depth=%s",what,reference,n,width,height,depth)
height = 65536/2
depth = height
end
@@ -374,11 +377,10 @@ nodes.references = {
-- todo: get rid of n (n is just a number, can be used for tracing, obsolete)
-local function setreference(n,h,d,r)
+local function setreference(h,d,r)
topofstack = topofstack + 1
-- the preroll permits us to determine samepage (but delayed also has some advantages)
-- so some part of the backend work is already done here
---~ stack[topofstack] = { n, h, d, codeinjections.prerollreference(r) }
stack[topofstack] = { r, h, d, codeinjections.prerollreference(r) }
-- texattribute[attribute] = topofstack -- todo -> at tex end
texcount.lastreferenceattribute = topofstack
@@ -406,7 +408,7 @@ local function makereference(width,height,depth,reference)
local result, current
if trace_references then
local step = 65536
- result = hpack_list(colorize(width,height-step,depth-step,2,reference)) -- step subtracted so that we can see seperate links
+ result = hpack_list(colorize(width,height-step,depth-step,2,reference,"reference")) -- step subtracted so that we can see seperate links
result.width = 0
current = result
end
@@ -475,7 +477,7 @@ local function makedestination(width,height,depth,reference)
width, height, depth = 5*step, 5*step, 0
end
for n=1,#name do
- local rule = hpack_list(colorize(width,height,depth,3,reference))
+ local rule = hpack_list(colorize(width,height,depth,3,reference,"destination"))
rule.width = 0
if not result then
result, current = rule, rule
@@ -531,14 +533,14 @@ function references.inject(prefix,reference,h,d,highlight,newwindow,layer) -- to
else
-- check
set.highlight, set.newwindow,set.layer = highlight, newwindow, layer
- setreference(tex.currentgrouplevel,h,d,set) -- sets attribute / todo: for set[*].error
+ setreference(h,d,set) -- sets attribute / todo: for set[*].error
end
end
function references.injectcurrentset(h,d) -- used inside doifelse
local currentset = references.currentset
if currentset then
- setreference(tex.currentgrouplevel,h,d,currentset) -- sets attribute / todo: for set[*].error
+ setreference(h,d,currentset) -- sets attribute / todo: for set[*].error
end
end
@@ -560,7 +562,7 @@ end
statistics.register("interactive elements", function()
if nofreferences > 0 or nofdestinations > 0 then
- return string.format("%s references, %s destinations",nofreferences,nofdestinations)
+ return format("%s references, %s destinations",nofreferences,nofdestinations)
else
return nil
end
diff --git a/Master/texmf-dist/tex/context/base/node-res.lua b/Master/texmf-dist/tex/context/base/node-res.lua
index 7f737ea7040..4522bef98ea 100644
--- a/Master/texmf-dist/tex/context/base/node-res.lua
+++ b/Master/texmf-dist/tex/context/base/node-res.lua
@@ -28,6 +28,7 @@ local pool = nodes.pool
local whatsitcodes = nodes.whatsitcodes
local skipcodes = nodes.skipcodes
+local kerncodes = nodes.kerncodes
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
@@ -75,7 +76,8 @@ function pool.usage()
end
local disc = register_node(new_node("disc"))
-local kern = register_node(new_node("kern",1))
+local kern = register_node(new_node("kern",kerncodes.userkern))
+local fontkern = register_node(new_node("kern",kerncodes.fontkern))
local penalty = register_node(new_node("penalty"))
local glue = register_node(new_node("glue")) -- glue.spec = nil
local glue_spec = register_node(new_node("glue_spec"))
@@ -83,6 +85,7 @@ local glyph = register_node(new_node("glyph",0))
local textdir = register_node(new_node("whatsit",whatsitcodes.dir))
local rule = register_node(new_node("rule"))
local latelua = register_node(new_node("whatsit",whatsitcodes.latelua))
+local special = register_node(new_node("whatsit",whatsitcodes.special))
local user_n = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_n.type = 100 -- 44
local user_l = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_l.type = 110 -- 44
local user_s = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_s.type = 115 -- 44
@@ -126,6 +129,12 @@ function pool.kern(k)
return n
end
+function pool.fontkern(k)
+ local n = copy_node(fontkern)
+ n.kern = k
+ return n
+end
+
function pool.gluespec(width,stretch,shrink,stretch_order,shrink_order)
local s = copy_node(glue_spec)
if width then s.width = width end
@@ -363,8 +372,14 @@ function pool.usertokens(id,tokens)
return n
end
+function pool.special(str)
+ local n = copy_node(special)
+ n.data = str
+ return n
+end
+
statistics.register("cleaned up reserved nodes", function()
- return format("%s nodes, %s lists of %s", pool.cleanup(tex.count["lastallocatedbox"]))
+ return format("%s nodes, %s lists of %s", pool.cleanup(tex.count["c_syst_last_allocated_box"]))
end) -- \topofboxstack
statistics.register("node memory usage", function() -- comes after cleanup !
diff --git a/Master/texmf-dist/tex/context/base/node-rul.lua b/Master/texmf-dist/tex/context/base/node-rul.lua
index 4cbd1ad0c5f..7f49edffc79 100644
--- a/Master/texmf-dist/tex/context/base/node-rul.lua
+++ b/Master/texmf-dist/tex/context/base/node-rul.lua
@@ -74,8 +74,6 @@ local a_color = attributes.private('color')
local a_transparency = attributes.private('transparency')
local a_colorspace = attributes.private('colormodel')
-local texwrite = tex.write
-
local insert_before = node.insert_before
local insert_after = node.insert_after
local striprange = nodes.striprange
@@ -234,7 +232,7 @@ local data = nodes.rules.data
function nodes.rules.define(settings)
data[#data+1] = settings
- texwrite(#data)
+ context(#data)
end
local a_viewerlayer = attributes.private("viewerlayer")
@@ -340,7 +338,7 @@ local data = nodes.shifts.data
function nodes.shifts.define(settings)
data[#data+1] = settings
- texwrite(#data)
+ context(#data)
end
local function flush_shifted(head,first,last,data,level,parent,strip) -- not that fast but acceptable for this purpose
diff --git a/Master/texmf-dist/tex/context/base/node-rul.mkiv b/Master/texmf-dist/tex/context/base/node-rul.mkiv
index 90bcd9e403f..1f1ac20ec01 100644
--- a/Master/texmf-dist/tex/context/base/node-rul.mkiv
+++ b/Master/texmf-dist/tex/context/base/node-rul.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Bars,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,8 +15,6 @@
\writestatus{loading}{ConTeXt Core Macros / Bars}
-%D The name of this file might change.
-
%D \macros
%D {underbar,underbars,
%D overbar,overbars,
@@ -36,11 +34,9 @@
%D
%D \typebuffer
%D
-%D \startvoorbeeld
%D \startlines
%D \getbuffer
%D \stoplines
-%D \stopvoorbeeld
%D
%D The next macros are derived from the \PLAIN\ \TEX\ one, but
%D also supports nesting. The \type{$} keeps us in horizontal
@@ -54,9 +50,15 @@
%D \showsetup{overstrikes}
%D
%D \showsetup{setupunderbar}
+%D
+%D Nested bars can be configured by appending \type {:<index>} to the
+%D category.
-%D todo: mkvi this file ... no redefine, just pass all parameters, too messy now
-%D (due to grouping) so better hash settings at the lua end
+%D As with many early usage of \LUA\ in \MKIV\ this mechanism explores a way
+%D to deal with local settings at the \TEX\ end and remembering parameters
+%D at the \LUA\ end. We might do things differently now, but as settings normally
+%D don't change that often, we're not in a hurry to do that now. The problem at
+%D the \LUA\ end is that we don't know when to clean up.
\unprotect
@@ -65,40 +67,42 @@
\registerctxluafile{node-rul}{1.001}
-\installcommandhandler \??on {bar} \??on
+\installcorenamespace{bar}
+\installcorenamespace{barindex}
+\installcorenamespace{barattribute}
+\installcorenamespace{barstack}
+
+\installcommandhandler \??bar {bar} \??bar
-\newtoks\checkalldefinedbars
+\newtoks\t_node_rules_checklist
+
+\let\c_node_rules_index\relax % temporary synonym
+\let\p_node_rules_color\empty
\let\setupbars\setupbar
\appendtoks
- \ifsecondargument
- \dodefinebarindeed\currentbar
- \else
- \the\checkalldefinedbars
- \fi
+ \ifsecondargument
+ \node_rules_define
+ \else
+ \the\t_node_rules_checklist
+ \fi
\to \everysetupbar
\appendtoks
- \ifcsname\??on:\currentbar:c\endcsname
- \csname\??on:\currentbar:c\endcsname\zerocount
- \else
- \expandafter\newcount\csname\??on:\currentbar:c\endcsname
- \fi
- \normalexpanded{\checkalldefinedbars{\doredefinebar{\currentbar}\the\checkalldefinedbars}}%
- \dodefinebarindeed\currentbar
- \setuevalue\currentbar{\doruled{\currentbar}}%
+ \ifcsname\??barindex\currentbar\endcsname
+ \csname\??barindex\currentbar\endcsname\zerocount
+ \else
+ \expandafter\newcount\csname\??barindex\currentbar\endcsname
+ \fi
+ \normalexpanded{\t_node_rules_checklist{\node_rules_redefine{\currentbar}\the\t_node_rules_checklist}}%
+ \node_rules_define
+ \setuevalue\currentbar{\node_rules_direct{\currentbar}}%
\to \everydefinebar
-\unexpanded\def\dodefinebarindeed#1%
- {\begingroup
- \edef\currentbar{#1}%
- \doifsomethingelse{\barparameter\c!color}
- {\donetrue\colored[\barparameter\c!color]}
- {\donefalse}%
- \normalexpanded
- {\endgroup
- \scratchcounter\ctxlua{nodes.rules.define {
+\unexpanded\def\node_rules_define
+ {\edef\p_node_rules_color{\barparameter\c!color}%
+ \setevalue{\??barattribute\currentbar}{\number\ctxlua{nodes.rules.define {
method = \barparameter\c!method,
offset = \barparameter\c!offset,
continue = "\barparameter\c!continue",
@@ -107,50 +111,51 @@
unit = "\barparameter\c!unit",
order = "\barparameter\c!order",
max = \barparameter\c!max,
- ma = \ifdone\the\attribute\colormodelattribute \else0\fi,
- ca = \ifdone\the\attribute\colorattribute \else0\fi,
- ta = \ifdone\the\attribute\transparencyattribute\else0\fi
- }}}%
- \setevalue{\??on#1:a}{\the\scratchcounter}}
-
-\let\doredefinebar\dodefinebarindeed
-
-\unexpanded\def\doruled#1%
- {\groupedcommand{\dodoruled{#1}}\relax}
-
-\def\dodoruled
- {\ctxlua{nodes.rules.enable()}%
- \glet\dodoruled\dodoruledindeed
- \dodoruled}
-
-\def\dodoruledindeed#1% maybe reverse the 1000
- {\advance\csname\??on:#1:c\endcsname\plusone % local ?
- \scratchcounter\csname\??on:#1:c\endcsname
+ ma = \thecolormodelattribute,
+ ca = \thecolorattribute\p_node_rules_color,
+ ta = \thetransparencyattribute\p_node_rules_color
+ }}}}
+
+\unexpanded\def\node_rules_redefine#1%
+ {\def\currentbar{#1}\node_rules_define}
+
+\unexpanded\def\node_rules_direct#1%
+ {\groupedcommand{\node_rules_set{#1}}\relax}
+
+\def\node_rules_set
+ {\ctxlua{nodes.rules.enable()}% will be moved to lua
+ \glet\node_rules_set\node_rules_set_indeed
+ \node_rules_set}
+
+\def\node_rules_set_indeed#1% maybe reverse the 1000 (also maybe use more attributes instead of settings)
+ {\edef\currentbar{#1}%
+ \expandafter\let\expandafter\c_node_rules_index\csname\??barindex#1\endcsname
+ \advance\c_node_rules_index\plusone
+ \usebarstyleandcolor\c!foregroundstyle\c!foregroundcolor
\attribute\ruledattribute\numexpr
- 1000*\scratchcounter
- +\csname\??on#1\ifcsname\??on#1:\number\scratchcounter\s!parent\endcsname:\number\scratchcounter\fi:a\endcsname
+ \plusthousand*\c_node_rules_index
+ +\csname\??barattribute#1\ifcsname\??bar#1:\number\c_node_rules_index\s!parent\endcsname:\number\c_node_rules_index\fi\endcsname
\relax}
-% ungrouped
-
\unexpanded\def\startbar[#1]%
{\begingroup
- \dodoruled{#1}}
+ \node_rules_set{#1}}
\unexpanded\def\stopbar
{\endgroup}
-\newcount\currentbarnesting % todo: same as colors
+% ungrouped
+
+\newcount\c_node_rules_nesting % todo: same as colors
\unexpanded\def\pushbar[#1]%
- {\global\advance\currentbarnesting\plusone
- \expandafter\edef\csname\??on:s:\number\currentbarnesting\endcsname
- {\attribute\ruledattribute\the\attribute\ruledattribute}% stack
- \dodoruled{#1}}
+ {\global\advance\c_node_rules_nesting\plusone
+ \expandafter\edef\csname\??barstack\number\c_node_rules_nesting\endcsname{\attribute\ruledattribute\the\attribute\ruledattribute}%
+ \node_rules_set{#1}}
\unexpanded\def\popbar
- {\csname\??on:s:\number\currentbarnesting\endcsname
- \global\advance\currentbarnesting\minusone}
+ {\csname\??barstack\number\c_node_rules_nesting\endcsname
+ \global\advance\c_node_rules_nesting\minusone}
\setupbars
[\c!method=0, % new: 0=center nested, 1=stack nested
@@ -158,6 +163,7 @@
\c!offset=0, % upwards, replaces: topoffset bottomoffset
\c!dy=0,
\c!max=3,
+ \c!style=,
\c!rulethickness=.1,
\c!order=\v!foreground,
\c!unit=ex, % so now we are relative
@@ -166,13 +172,23 @@
% \definebar[touchbar] [\c!method=0,\c!dy=-0.4,\c!offset=-0.0]
% \definebar[touchbars] [touchbar] [\c!continue=\v!yes]
-\definebar[\v!overstrike] [\c!method=0,\c!dy= 0.4,\c!offset= 0.5,\c!continue=\v!yes]
-\definebar[\v!underbar] [\c!method=1,\c!dy=-0.4,\c!offset=-0.3,\c!continue=\v!yes]
-\definebar[\v!overbar] [\c!method=1,\c!dy= 0.4,\c!offset= 1.8,\c!continue=\v!yes]
+\definebar[\v!overstrike][\c!method=0,\c!dy=0.4,\c!offset=0.5,\c!continue=\v!yes]
+\definebar[\v!underbar] [\c!method=1,\c!dy=-0.4,\c!offset=-0.3,\c!continue=\v!yes]
+\definebar[\v!overbar] [\c!method=1,\c!dy=0.4,\c!offset=1.8,\c!continue=\v!yes]
+
+\definebar
+ [\v!understrike]
+ [\c!method=0,
+ \c!offset=1.375,
+ \c!rulethickness=2.5,
+ \c!continue=\v!yes,
+ \c!order=\v!background,
+ \c!color=lightgray]
\definebar[\v!overstrikes] [\v!overstrike] [\c!continue=\v!no]
\definebar[\v!underbars] [\v!underbar] [\c!continue=\v!no]
\definebar[\v!overbars] [\v!overbar] [\c!continue=\v!no]
+\definebar[\v!understrikes][\v!understrike][\c!continue=\v!no]
% we want these always so ...
@@ -188,82 +204,75 @@
%D This will move: (a bit duplicated)
-\installcommandhandler \??ra {shift} \??ra
+\installcorenamespace{shift}
+\installcorenamespace{shiftindex}
+\installcorenamespace{shiftattribute}
+
+\installcommandhandler \??shift {shift} \??shift
+
+\newtoks\t_node_shifts_checklist
-\newtoks\checkalldefinedshifts
+\let\c_node_shifts_index\relax % temporary synonym
\let\setupshifts\setupshift
\appendtoks
- \ifsecondargument
- \dodefineshiftindeed\currentshift
- \else
- \the\checkalldefinedshifts
- \fi
+ \ifsecondargument
+ \node_shifts_define
+ \else
+ \the\t_node_shifts_checklist
+ \fi
\to \everysetupshift
\appendtoks
- \ifcsname\??ra:\currentshift:c\endcsname
- \csname\??ra:\currentshift:c\endcsname\zerocount
- \else
- \expandafter\newcount\csname\??ra:\currentshift:c\endcsname
- \fi
- \normalexpanded{\checkalldefinedshifts{\doredefineshift{\currentshift}\the\checkalldefinedshifts}}%
- \dodefineshiftindeed{\currentshift}%
- \setuevalue\currentshift{\doshifted{\currentshift}}%
+ \ifcsname\??shiftindex\currentshift\endcsname
+ \csname\??shiftindex\currentshift\endcsname\zerocount
+ \else
+ \expandafter\newcount\csname\??shiftindex\currentshift\endcsname
+ \fi
+ \normalexpanded{\t_node_shifts_checklist{\node_shifts_redefine{\currentshift}\the\t_node_shifts_checklist}}%
+ \node_shifts_define
+ \setuevalue\currentshift{\node_shifts_direct{\currentshift}}%
\to \everydefineshift
-\unexpanded\def\dodefineshiftindeed#1%
- {\begingroup
- \edef\currentshift{#1}%
- \normalexpanded
- {\endgroup
- \scratchcounter\ctxlua{nodes.shifts.define {
+\unexpanded\def\node_shifts_define
+ {\setevalue{\??shiftattribute\currentshift}{\number\ctxlua{nodes.shifts.define {
method = \shiftparameter\c!method,
continue = "\shiftparameter\c!continue",
dy = \shiftparameter\c!dy,
unit = "\shiftparameter\c!unit",
- }}}%
- \setevalue{\??ra#1:a}{\the\scratchcounter}}
-
-\let\doredefineshift\dodefineshiftindeed
+ }}}}
-% \unexpanded\def\doshifted#1%
-% {\groupedcommand{\dodoshifted{#1}}\relax}
+\unexpanded\def\node_shifts_redefine#1%
+ {\def\currentshift{#1}\node_shifts_define}
-\def\dodoshifted
+\unexpanded\def\node_shifts_set
{\ctxlua{nodes.shifts.enable()}%
- \glet\dodoshifted\dodoshiftedindeed
- \dodoshifted}
+ \glet\node_shifts_set\node_shifts_set_indeed
+ \node_shifts_set}
-\def\dostartisolation{\signalcharacter}
-\def\dostopisolation {\signalcharacter}
-\def\doisolator {\signalcharacter}
+% \unexpanded\def\node_shifts_direct#1%
+% {\doisolatedgroupedalign{\node_shifts_set{#1}}\donothing}
-\def\doisolatedgroupedalign#1#2%
+\unexpanded\def\node_shifts_direct#1%
{\groupedcommand
- {\begingroup\dostartisolation\begingroup#1}
- {#2\endgroup\dostopisolation\endgroup}}
+ {\begingroup\dostartisolation\begingroup\node_shifts_set{#1}}
+ {\endgroup\dostopisolation\endgroup}}
-\def\dosetupisolatedalign#1%
- {\doisolator
- \setupalign[#1]\relax}
-
-\def\dodoshiftedindeed#1%
+\def\node_shifts_set_indeed#1% todo: check parent !
{\def\currentshift{#1}%
- \advance\csname\??ra:#1:c\endcsname\plusone
- \scratchcounter\csname\??ra:#1:c\endcsname
- \attribute\shiftedattribute\numexpr1000*\scratchcounter
- +\csname\??ra#1\ifcsname\??ra#1:\number\scratchcounter\s!parent\endcsname:\number\scratchcounter\fi:a\endcsname
- \dosetshiftattributes\c!style\c!color
+ \expandafter\let\expandafter\c_node_shifts_index\csname\??shiftindex#1\endcsname
+ \advance\c_node_shifts_index\plusone
+ \attribute\shiftedattribute\numexpr
+ \plusthousand*\c_node_shifts_index
+ +\csname\??shiftattribute#1\ifcsname\??shift#1:\number\c_node_shifts_index\s!parent\endcsname:\number\c_node_shifts_index\fi\endcsname
+ \relax
+ \useshiftstyleandcolor\c!style\c!color
\dosetupisolatedalign{\shiftparameter\c!align}}
-\unexpanded\def\doshifted#1%
- {\doisolatedgroupedalign{\dodoshifted{#1}}{}}
-
\unexpanded\def\startshift[#1]%
{\begingroup
- \dodoshifted{#1}}
+ \node_shifts_set{#1}}
\unexpanded\def\stopshift
{\endgroup}
@@ -288,13 +297,19 @@
\expandafter\let\expandafter\shiftup \csname\v!shiftup \endcsname
\expandafter\let\expandafter\shiftdown \csname\v!shiftdown \endcsname
-\protect \endinput
+% This is a weird helper:
-% obsolete:
+\unexpanded\def\dostartisolation{\signalcharacter}
+\unexpanded\def\dostopisolation {\signalcharacter}
+\unexpanded\def\doisolator {\signalcharacter}
-\setupunderbar
- [\c!alternative=a,
- \c!rulethickness=\linewidth,
- \c!bottomoffset=1.5pt,
- \c!topoffset=2.5pt,
- \c!rulecolor=]
+\unexpanded\def\dosetupisolatedalign#1%
+ {\doisolator
+ \setupalign[#1]\relax}
+
+\unexpanded\def\doisolatedgroupedalign#1#2%
+ {\groupedcommand
+ {\begingroup\dostartisolation\begingroup#1}
+ {#2\endgroup\dostopisolation\endgroup}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/node-ser.lua b/Master/texmf-dist/tex/context/base/node-ser.lua
index aa4615626e9..63690d00ade 100644
--- a/Master/texmf-dist/tex/context/base/node-ser.lua
+++ b/Master/texmf-dist/tex/context/base/node-ser.lua
@@ -9,7 +9,8 @@ if not modules then modules = { } end modules ['node-ser'] = {
-- beware, some field names will change in a next releases
-- of luatex; this is pretty old code that needs an overhaul
-local type, format, concat, rep = type, string.format, table.concat, string.rep
+local type, format, rep = type, string.format, string.rep
+local concat, tohash, sortedkeys = table.concat, table.tohash, table.sortedkeys
local allocate = utilities.storage.allocate
@@ -23,7 +24,7 @@ local nodefields = nodes.fields
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist
-local expand = allocate ( table.tohash {
+local expand = allocate ( tohash {
"list", -- list_ptr & ins_ptr & adjust_ptr
"pre", --
"post", --
@@ -43,13 +44,13 @@ local expand = allocate ( table.tohash {
-- page_insert: "height", "last_ins_ptr", "best_ins_ptr"
-- split_insert: "height", "last_ins_ptr", "best_ins_ptr", "broken_ptr", "broken_ins"
-local ignore = allocate ( table.tohash {
+local ignore = allocate ( tohash {
"page_insert",
"split_insert",
"ref_count",
} )
-local dimension = allocate ( table.tohash {
+local dimension = allocate ( tohash {
"width", "height", "depth", "shift",
"stretch", "shrink",
"xoffset", "yoffset",
@@ -93,7 +94,7 @@ end
-- under construction:
-local function totable(n,flat,verbose)
+local function totable(n,flat,verbose) -- todo: no attributes
-- todo: no local function
local function to_table(n,flat,verbose)
local f = nodefields(n)
@@ -178,7 +179,7 @@ local function serialize(root,name,handle,depth,m)
if root.id then
fld = nodefields(root) -- we can cache these (todo)
else
- fld = table.sortedkeys(root)
+ fld = sortedkeys(root)
end
if type(root) == 'table' and root['type'] then -- userdata or table
handle(format("%s %s=%q,",depth,'type',root['type']))
@@ -234,14 +235,6 @@ function nodes.serializebox(n,flat,verbose,name)
return nodes.serialize(nodes.totable(tex.box[n],flat,verbose),name)
end
--- keep:
---
--- function nodes.visualizebox(...)
--- tex.print(ctxcatcodes,"\\starttyping")
--- tex.print(nodes.serializebox(...))
--- tex.print("\\stoptyping")
--- end
-
function nodes.visualizebox(...) -- to be checked .. will move to module anyway
context.starttyping()
context.pushcatcodes("verbatim")
@@ -256,7 +249,7 @@ function nodes.list(head,n) -- name might change to nodes.type -- to be checked
end
while head do
local id = head.id
- tex.write(rep(" ",n or 0) .. tostring(head) .. "\n")
+ 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
diff --git a/Master/texmf-dist/tex/context/base/node-shp.lua b/Master/texmf-dist/tex/context/base/node-shp.lua
index 75177a4edde..6fad0f495fb 100644
--- a/Master/texmf-dist/tex/context/base/node-shp.lua
+++ b/Master/texmf-dist/tex/context/base/node-shp.lua
@@ -18,6 +18,8 @@ local mark_code = nodecodes.mark
local kern_code = nodecodes.kern
local glue_code = nodecodes.glue
+local texbox = tex.box
+
local free_node = node.free
local remove_node = node.remove
@@ -60,3 +62,9 @@ function nodes.handlers.finalize(head) -- problem, attr loaded before node, todo
end
--~ nodes.handlers.finalize = actions
+
+-- interface
+
+function commands.finalizebox(n)
+ actions(texbox[n])
+end
diff --git a/Master/texmf-dist/tex/context/base/node-spl.lua b/Master/texmf-dist/tex/context/base/node-spl.lua
index 0fe3f759d1d..3b208e0e787 100644
--- a/Master/texmf-dist/tex/context/base/node-spl.lua
+++ b/Master/texmf-dist/tex/context/base/node-spl.lua
@@ -170,7 +170,7 @@ function splitters.define(name,parameters)
local l = less and settings_to_array(less)
local m = more and settings_to_array(more)
if goodies then
- goodies = fonts.goodies.get(goodies) -- also in tfmdata
+ goodies = fonts.goodies.load(goodies) -- also in tfmdata
if goodies then
local featuresets = goodies.featuresets
local solution = solution and goodies.solutions[solution]
@@ -217,7 +217,7 @@ function splitters.define(name,parameters)
more = more_set or { },
settings = settings, -- for tracing
}
- tex.write(nofsolutions)
+ context(nofsolutions)
end
local nofwords, noftries, nofadapted, nofkept, nofparagraphs = 0, 0, 0, 0, 0
diff --git a/Master/texmf-dist/tex/context/base/node-spl.mkiv b/Master/texmf-dist/tex/context/base/node-spl.mkiv
index 8ad6795a5e0..3630212af3b 100644
--- a/Master/texmf-dist/tex/context/base/node-spl.mkiv
+++ b/Master/texmf-dist/tex/context/base/node-spl.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Splitters,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/node-tra.lua b/Master/texmf-dist/tex/context/base/node-tra.lua
index 38855f65934..70e4639b896 100644
--- a/Master/texmf-dist/tex/context/base/node-tra.lua
+++ b/Master/texmf-dist/tex/context/base/node-tra.lua
@@ -63,8 +63,6 @@ local whatsit_code = nodecodes.whatsit
local localpar_code = whatcodes.localpar
local dir_code = whatcodes.dir
-local userskip_code = skipcodes.userskip
-
local nodepool = nodes.pool
local new_glyph = nodepool.glyph
@@ -218,7 +216,7 @@ function step_tracers.reset()
end
function step_tracers.nofsteps()
- return tex.write(#collection)
+ return context(#collection)
end
function step_tracers.glyphs(n,i)
@@ -541,15 +539,27 @@ end
nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end
-function nodes.listtoutf(h,joiner)
- local joiner = (joiner ==true and utfchar(0x200C)) or joiner -- zwnj
+local function listtoutf(h,joiner,textonly)
+ local joiner = (joiner == true and utfchar(0x200C)) or joiner -- zwnj
local w = { }
while h do
- if h.id == glyph_code then -- always true
+ local id = h.id
+ if id == glyph_code then -- always true
w[#w+1] = utfchar(h.char)
if joiner then
w[#w+1] = joiner
end
+ elseif id == disc_code then
+ local pre, rep, pos = h.pre, h.replace, h.post
+ w[#w+1] = format("[%s|%s|%s]",
+ pre and listtoutf(pre,joiner,textonly) or "",
+ rep and listtoutf(rep,joiner,textonly) or "",
+ mid and listtoutf(mid,joiner,textonly) or ""
+ )
+ elseif textonly then
+ if id == glue_code and h.width > 0 then
+ w[#w+1] = " "
+ end
else
w[#w+1] = "[-]"
end
@@ -558,6 +568,8 @@ function nodes.listtoutf(h,joiner)
return concat(w)
end
+nodes.listtoutf = listtoutf
+
local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" }
local function showboxes(n,symbol,depth)
@@ -612,7 +624,7 @@ local function toutf(list,result,nofresult,stopcriterium)
--~ result[nofresult] = " "
--~ end
result, nofresult = toutf(n.list,result,nofresult)
- elseif id == glue_code and n.subtype == userskip_code and n.spec.width > threshold then
+ elseif id == glue_code then
if nofresult > 0 and result[nofresult] ~= " " then
nofresult = nofresult + 1
result[nofresult] = " "
@@ -628,6 +640,10 @@ local function toutf(list,result,nofresult,stopcriterium)
end
end
end
+ if nofresult > 0 and result[nofresult] == " " then
+ result[nofresult] = nil
+ nofresult = nofresult - 1
+ end
return result, nofresult
end
@@ -636,22 +652,48 @@ function nodes.toutf(list,stopcriterium)
return concat(result)
end
--- might move elsewhere
+-- this will move elsewhere
local ptfactor = number.dimenfactors.pt
local bpfactor = number.dimenfactors.bp
local stripper = lpeg.patterns.stripzeros
local points = function(n)
- return lpegmatch(stripper,format("%.5fpt",n*ptfactor))
+ if not n or n == 0 then
+ return "0pt"
+ else
+ return lpegmatch(stripper,format("%.5fpt",n*ptfactor))
+ end
end
local basepoints = function(n)
- return lpegmatch(stripper,format("%.5fbp",n*bpfactor))
+ if not n or n == 0 then
+ return "0bp"
+ else
+ return lpegmatch(stripper,format("%.5fbp",n*bpfactor))
+ end
+end
+
+local pts = function(n)
+ if not n or n == 0 then
+ return "0pt"
+ else
+ return format("%.5fpt",n*ptfactor)
+ end
+end
+
+local nopts = function(n)
+ if not n or n == 0 then
+ return "0"
+ else
+ return format("%.5f",n*ptfactor)
+ end
end
number.points = points
number.basepoints = basepoints
+number.pts = pts
+number.nopts = nopts
--~ function nodes.thespec(s)
--~ local stretch_order = s.stretch_order
diff --git a/Master/texmf-dist/tex/context/base/node-tsk.lua b/Master/texmf-dist/tex/context/base/node-tsk.lua
index 29a665ff031..efc51913c12 100644
--- a/Master/texmf-dist/tex/context/base/node-tsk.lua
+++ b/Master/texmf-dist/tex/context/base/node-tsk.lua
@@ -10,22 +10,26 @@ if not modules then modules = { } end modules ['node-tsk'] = {
-- we already have dirty flags as well. On the other hand, nodes are
-- rather specialized and here we focus on node related tasks.
+local format = string.format
+
local trace_tasks = false trackers.register("tasks.creation", function(v) trace_tasks = v end)
local report_tasks = logs.reporter("tasks")
local allocate = utilities.storage.allocate
-local nodes = nodes
+local nodes = nodes
-nodes.tasks = nodes.tasks or { }
-local tasks = nodes.tasks
+nodes.tasks = nodes.tasks or { }
+local tasks = nodes.tasks
-local tasksdata = { } -- no longer public
+local tasksdata = { } -- no longer public
-local sequencers = utilities.sequencers
+local sequencers = utilities.sequencers
+local compile = sequencers.compile
+local nodeprocessor = sequencers.nodeprocessor
-local frozengroups = "no"
+local frozengroups = "no"
function tasks.freeze(kind)
frozengroups = kind or "tolerant" -- todo: hook into jobname
@@ -36,13 +40,16 @@ function tasks.new(specification) -- was: name,arguments,list
local arguments = specification.arguments or 0
local sequence = specification.sequence
if name and sequence then
- local tasklist = sequencers.reset()
+ local tasklist = sequencers.new {
+ -- we can move more to the sequencer now .. todo
+ }
tasksdata[name] = {
list = tasklist,
runner = false,
arguments = arguments,
-- sequence = sequence,
frozen = { },
+ processor = specification.processor or nodeprocessor
}
for l=1,#sequence do
sequencers.appendgroup(tasklist,sequence[l])
@@ -152,7 +159,7 @@ end
function tasks.showactions(name,group,action,where,kind)
local data = valid(name)
if data then
- report_tasks("task %s, list:\n%s",name,sequencers.nodeprocessor(data.list))
+ report_tasks("task %s, list:\n%s",name,nodeprocessor(data.list))
end
end
@@ -165,14 +172,12 @@ local created, total = 0, 0
statistics.register("node list callback tasks", function()
if total > 0 then
- return string.format("%s unique task lists, %s instances (re)created, %s calls",table.count(tasksdata),created,total)
+ return format("%s unique task lists, %s instances (re)created, %s calls",table.count(tasksdata),created,total)
else
return nil
end
end)
-local compile, nodeprocessor = sequencers.compile, sequencers.nodeprocessor
-
function tasks.actions(name) -- we optimize for the number or arguments (no ...)
local data = tasksdata[name]
if data then
@@ -186,7 +191,7 @@ function tasks.actions(name) -- we optimize for the number or arguments (no ...)
if trace_tasks then
report_tasks("creating runner '%s'",name)
end
- runner = compile(data.list,nodeprocessor,0)
+ runner = compile(data.list,data.processor,0)
data.runner = runner
end
return runner(head)
@@ -200,7 +205,7 @@ function tasks.actions(name) -- we optimize for the number or arguments (no ...)
if trace_tasks then
report_tasks("creating runner '%s' with 1 extra arguments",name)
end
- runner = compile(data.list,nodeprocessor,1)
+ runner = compile(data.list,data.processor,1)
data.runner = runner
end
return runner(head,one)
@@ -214,7 +219,7 @@ function tasks.actions(name) -- we optimize for the number or arguments (no ...)
if trace_tasks then
report_tasks("creating runner '%s' with 2 extra arguments",name)
end
- runner = compile(data.list,nodeprocessor,2)
+ runner = compile(data.list,data.processor,2)
data.runner = runner
end
return runner(head,one,two)
@@ -228,7 +233,7 @@ function tasks.actions(name) -- we optimize for the number or arguments (no ...)
if trace_tasks then
report_tasks("creating runner '%s' with 3 extra arguments",name)
end
- runner = compile(data.list,nodeprocessor,3)
+ runner = compile(data.list,data.processor,3)
data.runner = runner
end
return runner(head,one,two,three)
@@ -242,7 +247,7 @@ function tasks.actions(name) -- we optimize for the number or arguments (no ...)
if trace_tasks then
report_tasks("creating runner '%s' with 4 extra arguments",name)
end
- runner = compile(data.list,nodeprocessor,4)
+ runner = compile(data.list,data.processor,4)
data.runner = runner
end
return runner(head,one,two,three,four)
@@ -256,7 +261,7 @@ function tasks.actions(name) -- we optimize for the number or arguments (no ...)
if trace_tasks then
report_tasks("creating runner '%s' with 5 extra arguments",name)
end
- runner = compile(data.list,nodeprocessor,5)
+ runner = compile(data.list,data.processor,5)
data.runner = runner
end
return runner(head,one,two,three,four,five)
@@ -270,7 +275,7 @@ function tasks.actions(name) -- we optimize for the number or arguments (no ...)
if trace_tasks then
report_tasks("creating runner '%s' with n extra arguments",name)
end
- runner = compile(data.list,nodeprocessor,"n")
+ runner = compile(data.list,data.processor,"n")
data.runner = runner
end
return runner(head,...)
@@ -313,6 +318,7 @@ end
tasks.new {
name = "processors",
arguments = 4,
+ processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
@@ -327,6 +333,7 @@ tasks.new {
tasks.new {
name = "finalizers",
arguments = 1,
+ processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
@@ -341,6 +348,7 @@ tasks.new {
tasks.new {
name = "shipouts",
arguments = 0,
+ processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
@@ -352,6 +360,7 @@ tasks.new {
tasks.new {
name = "mvlbuilders",
arguments = 1,
+ processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
@@ -362,6 +371,7 @@ tasks.new {
tasks.new {
name = "vboxbuilders",
arguments = 5,
+ processor = nodeprocessor,
sequence = {
"before", -- for users
"normalizers",
@@ -369,22 +379,24 @@ tasks.new {
}
}
---~ tasks.new {
---~ name = "parbuilders",
---~ arguments = 1,
---~ sequence = {
---~ "before", -- for users
---~ "lists",
---~ "after", -- for users
---~ }
---~ }
-
---~ tasks.new {
---~ name = "pagebuilders",
---~ arguments = 5,
---~ sequence = {
---~ "before", -- for users
---~ "lists",
---~ "after", -- for users
---~ }
---~ }
+-- tasks.new {
+-- name = "parbuilders",
+-- arguments = 1,
+-- processor = nodeprocessor,
+-- sequence = {
+-- "before", -- for users
+-- "lists",
+-- "after", -- for users
+-- }
+-- }
+
+-- tasks.new {
+-- name = "pagebuilders",
+-- arguments = 5,
+-- processor = nodeprocessor,
+-- sequence = {
+-- "before", -- for users
+-- "lists",
+-- "after", -- for users
+-- }
+-- }
diff --git a/Master/texmf-dist/tex/context/base/node-typ.lua b/Master/texmf-dist/tex/context/base/node-typ.lua
index 684fc94ba6f..5f8df2b4443 100644
--- a/Master/texmf-dist/tex/context/base/node-typ.lua
+++ b/Master/texmf-dist/tex/context/base/node-typ.lua
@@ -6,28 +6,44 @@ if not modules then modules = { } end modules ['node-typ'] = {
license = "see context related readme files"
}
--- this will be replaced by blob-ini cum suis so typesetters will go away
+local utfvalues = string.utfvalues
-local utfvalues = string.utfvalues
+local currentfont = font.current
+local fontparameters = fonts.hashes.parameters
-local hpack = node.hpack
-local vpack = node.vpack
+local hpack = node.hpack
+local vpack = node.vpack
-local nodepool = nodes.pool
+local nodepool = nodes.pool
-local new_glyph = nodepool.glyph
-local new_glue = nodepool.glue
+local newglyph = nodepool.glyph
+local newglue = nodepool.glue
typesetters = typesetters or { }
-local function tonodes(str,fontid,spacing) -- don't use this
+local function tonodes(str,fontid,spacing) -- quick and dirty
local head, prev = nil, nil
- for s in utfvalues(str) do
+ if not fontid then
+ fontid = currentfont()
+ end
+ local fp = fontparameters[fontid]
+ local s, p, m
+ if spacing then
+ s, p, m = spacing, 0, 0
+ else
+ s, p, m = fp.space, fp.space_stretch, fp,space_shrink
+ end
+ local spacedone = false
+ for c in utfvalues(str) do
local next
- if spacing and s == 32 then
- next = newglue(spacing or 64*1024*10)
+ if c == 32 then
+ if not spacedone then
+ next = newglue(s,p,m)
+ spacedone = true
+ end
else
- next = newglyph(fontid or 1,s)
+ next = newglyph(fontid or 1,c)
+ spacedone = false
end
if not head then
head = next
@@ -43,7 +59,7 @@ end
typesetters.tonodes = tonodes
function typesetters.hpack(str,fontid,spacing)
- return hpack(tonodes(str,fontid,spacing))
+ return hpack(tonodes(str,fontid,spacing),"exactly")
end
function typesetters.vpack(str,fontid,spacing)
diff --git a/Master/texmf-dist/tex/context/base/norm-alo.mkii b/Master/texmf-dist/tex/context/base/norm-alo.mkii
index d47f49037d7..d359cf7e88f 100644
--- a/Master/texmf-dist/tex/context/base/norm-alo.mkii
+++ b/Master/texmf-dist/tex/context/base/norm-alo.mkii
@@ -5,7 +5,7 @@
%D subtitle=\ALEPH\ and \OMEGA,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/norm-ctx.mkii b/Master/texmf-dist/tex/context/base/norm-ctx.mkii
index 707705d89eb..b1a4c7d3593 100644
--- a/Master/texmf-dist/tex/context/base/norm-ctx.mkii
+++ b/Master/texmf-dist/tex/context/base/norm-ctx.mkii
@@ -5,7 +5,7 @@
%D subtitle=\ALEPH\ and \OMEGA,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/norm-ctx.mkiv b/Master/texmf-dist/tex/context/base/norm-ctx.mkiv
index 707705d89eb..ff16767433c 100644
--- a/Master/texmf-dist/tex/context/base/norm-ctx.mkiv
+++ b/Master/texmf-dist/tex/context/base/norm-ctx.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\ALEPH\ and \OMEGA,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -13,4 +13,6 @@
%D A few more might end up here (like the weird ones in syst-ini).
-\let\normalreqno = \normaleqno
+\let\normalreqno\normaleqno
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/norm-etx.mkii b/Master/texmf-dist/tex/context/base/norm-etx.mkii
index 3edd8e7ef1f..bd244e4d1e9 100644
--- a/Master/texmf-dist/tex/context/base/norm-etx.mkii
+++ b/Master/texmf-dist/tex/context/base/norm-etx.mkii
@@ -5,7 +5,7 @@
%D subtitle=\ETEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/norm-ltx.mkii b/Master/texmf-dist/tex/context/base/norm-ltx.mkii
index a779735dd53..cd02cffec95 100644
--- a/Master/texmf-dist/tex/context/base/norm-ltx.mkii
+++ b/Master/texmf-dist/tex/context/base/norm-ltx.mkii
@@ -5,7 +5,7 @@
%D subtitle=\LUATEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/norm-ptx.mkii b/Master/texmf-dist/tex/context/base/norm-ptx.mkii
index 352a884f014..14a57aeec1b 100644
--- a/Master/texmf-dist/tex/context/base/norm-ptx.mkii
+++ b/Master/texmf-dist/tex/context/base/norm-ptx.mkii
@@ -5,7 +5,7 @@
%D subtitle=\PDFTEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/norm-tex.mkii b/Master/texmf-dist/tex/context/base/norm-tex.mkii
index 61f9740efe4..0bd54f71a99 100644
--- a/Master/texmf-dist/tex/context/base/norm-tex.mkii
+++ b/Master/texmf-dist/tex/context/base/norm-tex.mkii
@@ -5,7 +5,7 @@
%D subtitle=\TEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/norm-xtx.mkii b/Master/texmf-dist/tex/context/base/norm-xtx.mkii
index 3da94465624..851b90b310c 100644
--- a/Master/texmf-dist/tex/context/base/norm-xtx.mkii
+++ b/Master/texmf-dist/tex/context/base/norm-xtx.mkii
@@ -5,7 +5,7 @@
%D subtitle=\XETEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/pack-bar.mkiv b/Master/texmf-dist/tex/context/base/pack-bar.mkiv
index 05afd32d02e..6967173e2e8 100644
--- a/Master/texmf-dist/tex/context/base/pack-bar.mkiv
+++ b/Master/texmf-dist/tex/context/base/pack-bar.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Bars,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/pack-bck.mkvi b/Master/texmf-dist/tex/context/base/pack-bck.mkvi
new file mode 100644
index 00000000000..38750f590d8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/pack-bck.mkvi
@@ -0,0 +1,256 @@
+%D \module
+%D [ file=pack-bck, % moved from pack-rul,
+%D version=20111115, % 1998.10.16,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=Simple Backgrounds,
+%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 Packaging Macros / Simple Backgrounds}
+
+%D The code here is already pretty old and is used for simple
+%D backgrounds. As it is still used WS adapted the code to the
+%D new command handler methods so that it gets a second life. So
+%D it made sense to mkvi ir as well. Some more code is moved here
+%D too.
+
+%D \macros
+%D {setupbackground,startbackground,background}
+%D
+%D The section deals with backgrounds in the running text. This
+%D means that texts is to be collected and split over pages. To
+%D show what can be done, we provide this part of the
+%D documentation with some gray background and a red frame.
+%D Both the background and frame can have all characteristics
+%D of \type{\framed}.
+%D
+%D \starttyping
+%D \setupbackground
+%D [backgroundoffset=4pt,
+%D background=screen,
+%D frame=on,
+%D framecolor=red,
+%D leftoffset=2pt]
+%D \stoptyping
+%D
+%D The implementation is not that sophisticated, but suffices.
+%D The main problem with this kind of functionality is to get
+%D the spacing all right.
+%D
+%D Specifying the background is more or less the same as
+%D specifying a framed box.
+%D
+%D \showsetup{setupbackground}
+%D
+%D {\em This mechanism is sort of obsolete and textbackgrounds should
+%D be used instead.}
+
+\unprotect
+
+\installcorenamespace {background}
+
+\installframedcommandhandler \??background {background} \??background
+
+% The mode is not that public an dmostlu an initial mode:
+%
+% 0 : no split
+% 1 : no split, honoring leftskip (messy)
+% 2 : split
+% 3 : split, honoring leftskip (messy)
+%
+% While processing the modes will change from 3->1 or 2->0. Don't
+% depend on the mode being public currently as it could become a
+% key.
+
+\setnewconstant\backgroundsplitmode\plusthree
+
+\appendtoks
+ \setuevalue{\e!start\currentbackground}{\pack_backgrounds_start [\currentbackground]}%
+ \setuevalue{\e!stop \currentbackground}{\pack_backgrounds_stop }%
+ \setuevalue {\currentbackground}{\pack_backgrounds_direct[\currentbackground]}%
+\to \everydefinebackground
+
+\unexpanded\def\pack_backgrounds_start[#tag]%
+ {\endgraf
+ \begingroup
+ \def\currentbackground{#tag}%
+ \doifelse{\backgroundparameter\c!state}\v!start
+ {\dosingleempty\pack_backgrounds_start_indeed}
+ {\dosingleempty\pack_backgrounds_start_ignore}}
+
+\def\pack_backgrounds_start_indeed[#settings]%
+ {\setupcurrentbackground[#settings,\c!state=\v!start,\c!offset=\v!overlay]%
+ \let\pack_backgrounds_stop\pack_backgrounds_stop_indeed
+ \setbox0\vbox\bgroup
+ \vbox to \lineheight{}\vskip\zeropoint
+ \blank[\v!disable]
+ \leftskip \backgroundparameter\c!leftoffset
+ \rightskip\backgroundparameter\c!rightoffset}
+
+\def\pack_backgrounds_start_ignore[#settings]%
+ {\let\pack_backgrounds_stop\pack_backgrounds_stop_ignore}
+
+\let\pack_backgrounds_stop\relax
+
+\unexpanded\def\pack_backgrounds_stop_indeed
+ {\endgraf
+ \removelastskip
+ \egroup
+ \dimen2\leftskip % new **
+ \forgetall
+ \ifinsidefloat
+ \backgroundsplitmode\zerocount
+ \fi
+ \ifcase\backgroundsplitmode
+ \inheritedbackgroundframed{\box0}%
+ \or
+ \hskip\dimen2
+ \inheritedbackgroundframed{\box0}%
+ \else
+ \splitmaxdepth\boxmaxdepth
+ \splittopskip\topskip
+ \setbox2\vsplit0 to \lineheight % get rid of fake line
+ \doloop
+ {\ifdim\pagetotal=\zeropoint % empty page
+ \scratchdimen\textheight
+ \backgroundsplitmode\plusone % split to max height
+ \else
+ \setbox2\vbox{\backgroundparameter\c!before}%
+ \scratchdimen\dimexpr\pagegoal-\ht2-\pagetotal\relax
+ \backgroundsplitmode\plustwo % split to partial height
+ \fi
+ \advance\scratchdimen\dimexpr-\backgroundparameter\c!topoffset-\backgroundparameter\c!bottomoffset\relax
+ \ifdim\scratchdimen>2\lineheight\relax % reasonable, will be configurable
+ \ifdim\ht0>\scratchdimen % larger than page
+ \setbox2\vsplit0 to \scratchdimen
+ \else
+ \setbox2\box0
+ \backgroundsplitmode\zerocount % no split
+ \fi
+ \setbox2\vbox \ifcase\backgroundsplitmode\or to \textheight \fi % max split
+ {\vskip\backgroundparameter\c!topoffset
+ \unvcopy2
+ \prevdepth\dp2
+ \obeydepth
+ \vskip\backgroundparameter\c!bottomoffset
+ \vfill}
+ \backgroundparameter\c!before
+ \ifcase\backgroundsplitmode\or\or % partial split
+ \ifdim\pagegoal<\maxdimen
+ \pagegoal=1.2\pagegoal % be a bit more tolerant
+ \fi
+ \fi
+ \startlinecorrection
+ \ifnum\backgroundsplitmode=\plusthree
+ \hskip\dimen2 % new **
+ \fi
+ \inheritedbackgroundframed{\box2}%
+ \stoplinecorrection
+ \ifcase\backgroundsplitmode % no split
+ \backgroundparameter\c!after
+ \else % some split
+ \page_otr_fill_and_eject_page % no \page !
+ \fi
+ \else
+ \page
+ \fi
+ \ifdim\ht0>\zeropoint \else
+ \exitloop
+ \fi}%
+ \fi
+ \endgroup
+ \endgraf}
+
+\unexpanded\def\pack_backgrounds_stop_ignore
+ {\endgroup
+ \endgraf}
+
+\unexpanded\def\pack_backgrounds_direct[#tag]%
+ {\begingroup
+ \def\currentbackground{#tag}%
+ \doifelse{\backgroundparameter\c!state}\c!start
+ \pack_backgrounds_direct_indeed
+ \pack_backgrounds_direct_ignore}
+
+\def\pack_backgrounds_direct_indeed
+ {\dowithnextboxcs\pack_backgrounds_direct_finish\vbox}
+
+\def\pack_backgrounds_direct_finish
+ {\setupcurrentbackground[\c!offset=\v!overlay]%
+ \inheritedbackgroundframed{\flushnextbox}%
+ \endgroup}
+
+\def\pack_backgrounds_direct_ignore
+ {\endgroup}
+
+\definebackground[\v!background]
+
+\ifdefined\startbackground \else
+ \expandafter\let\startbackground\csname\e!start\v!background\endcsname
+ \expandafter\let\stopbackground \csname\e!stop \v!background\endcsname
+ \expandafter\let\background \csname \v!background\endcsname
+\fi
+
+\setupbackground
+ [\c!leftoffset=.5\bodyfontsize,
+ \c!rightoffset=\backgroundparameter\c!leftoffset,
+ \c!topoffset=\!!zeropoint,
+ \c!bottomoffset=\backgroundparameter\c!topoffset,
+ \c!state=\v!start,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ \c!frame=\v!off,
+ \c!color=,
+ \c!depth=\!!zeropoint,
+ \c!background=\v!screen,
+ \c!backgroundcolor=\backgroundparameter\c!color,
+ \c!screen=\@@rsscreen,
+ \c!before=,
+ \c!after=]
+
+%D \startbuffer
+%D \setupbackground[state=start,frame=on]
+%D
+%D \startbackground
+%D \input ward
+%D \stopbackground
+%D
+%D \background{\input ward\par}
+%D
+%D \setupbackground[state=stop]
+%D
+%D \startbackground
+%D \input ward
+%D \stopbackground
+%D
+%D \background{\input ward\par}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+%D \macros
+%D {backgroundline}
+%D
+%D For the moment an undocumented feature, but a candidate
+%D for going public.
+
+\unexpanded\def\backgroundline[#color]%
+ {\dontleavehmode
+ \dowithnextbox{\pack_backgrounds_add_to_nextbox{#color}}\hbox}
+
+\unexpanded\def\pack_backgrounds_add_to_nextbox#color% handy helper
+ {\hbox
+ {\dousecolorparameter{#color}%
+ \vrule
+ \!!width \nextboxwd
+ \!!height\nextboxht
+ \!!depth \nextboxdp
+ \hskip-\nextboxwd
+ \flushnextbox}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/pack-box.mkii b/Master/texmf-dist/tex/context/base/pack-box.mkii
index f27d8b4fd83..1752e2b9122 100644
--- a/Master/texmf-dist/tex/context/base/pack-box.mkii
+++ b/Master/texmf-dist/tex/context/base/pack-box.mkii
@@ -5,7 +5,7 @@
%D subtitle=Boxes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -234,7 +234,7 @@
{\lower\ht\collectorbox\box\collectorbox}%
% just to be sure
\ifdim\wd\collectorbox<\@@layerxsiz
- \global\wd\collectorbox\@@layerxsiz
+ \wd\collectorbox\@@layerxsiz
\fi}
\def\flushcollector[#1]%
@@ -260,7 +260,7 @@
\def\adaptcollector
{\dodoubleargument\doadaptcollector}
-\def\doadaptcollector[#1][#2]%
+\def\doadaptcollector[#1][#2]% % a typical case where \global\wd looks better in the code
{\bgroup
\def\currentcollector{#1}%
\mathchardef\collectorbox\csname\@@collectorbox#1\endcsname
@@ -572,14 +572,17 @@
{\dowithnextbox{\setlayer[#1][#2]{\flushnextbox}}%
\hbox\framed[#3]}
+% \def\dosetlayerframedS[#1][#2][#3]%
+% {\dowithnextbox
+% {\setlayer[#1][\c!width=\nextboxwd,\c!height=\nextboxht,\c!offset=\!!zeropoint,#2]{\flushnextbox}}%
+% \hbox\framed[\c!location=\v!normal,#2]}
+%
+% better (2011-09-06)
+
\def\dosetlayerframedS[#1][#2][#3]%
{\dowithnextbox
- {\setlayer
- [#1]
- [\c!width=\nextboxwd,\c!height=\nextboxht,
- \c!offset=\!!zeropoint,#2]
- {\flushnextbox}}%
- \hbox\framed[\c!location=\v!normal,#2]}
+ {\setlayer[#1][\c!width=\nextboxwd,\c!height=\nextboxht,#2,\c!offset=\!!zeropoint]{\flushnextbox}}%
+ \hbox\framed[\c!location=\v!normal,#2]}
\def\setlayertext
{\dotripleempty\dosetlayertext}
diff --git a/Master/texmf-dist/tex/context/base/pack-box.mkiv b/Master/texmf-dist/tex/context/base/pack-box.mkiv
index fa771b4855a..41a17953bb1 100644
--- a/Master/texmf-dist/tex/context/base/pack-box.mkiv
+++ b/Master/texmf-dist/tex/context/base/pack-box.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Boxes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,6 +13,8 @@
\writestatus{loading}{ConTeXt Packaging Macros / Boxes}
+% to be cleaned up
+
%D This module contains all kind of macros for moving content
%D around. Many macros here come from other modules, but
%D depencies made it more clear to isolate them.
@@ -21,106 +23,187 @@
\unprotect
-% \definelayer[\v!tekst-2][\c!positie=\v!ja]
-% \definelayer[\v!tekst-1][\c!positie=\v!ja]
-% \definelayer[\v!tekst+1][\c!positie=\v!ja]
-% \definelayer[\v!tekst+2][\c!positie=\v!ja]
-
% we need to set the size, else we get dimensions depending
-% on the content, which in itsel fis ok, but can lead to loops
+% on the content, which in itself is ok, but can lead to loops
% due to rounding errors (happened in demo-obv)
-\definelayer[\v!text-2][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
-\definelayer[\v!text-1][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
-\definelayer[\v!text+1][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
-\definelayer[\v!text+2][\c!position=\v!yes,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text-2][\c!position=\v!yes,\c!region=,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text-1][\c!position=\v!yes,\c!region=,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text+1][\c!position=\v!yes,\c!region=,\c!width=\overlaywidth,\c!height=\overlayheight]
+\definelayer[\v!text+2][\c!position=\v!yes,\c!region=,\c!width=\overlaywidth,\c!height=\overlayheight]
+
+% \unexpanded\def\positionregionlayer#1#2%
+% {\composedlayer{#2}}
+%
+% \def\internaltextoverlay#1% will become more generic and installable
+% {\startoverlay % i.e. probably an overlay by itself
+% {\positionregionoverlay\textanchor{\v!text#1}}% see later
+% {\positionregionlayer \textanchor{\v!text#1}}%
+% \stopoverlay}
\def\internaltextoverlay#1% will become more generic and installable
{\startoverlay % i.e. probably an overlay by itself
- {\positionoverlay{\v!text#1}} % see later
- {\composedlayer {\v!text#1}}
+ {\positionregionoverlay\textanchor{\v!text#1}}% see later
+ {\composedlayer {\v!text#1}}%
\stopoverlay}
-%\def\internaltextoverlay#1%
-% {\hbox to \zeropoint{\positionoverlay{\v!tekst#1}\hss}%
-% \composedlayer{\v!tekst#1}}
-
-% todo: share info, so that tuo will be smaller
-
\defineoverlay[\v!text-2][\internaltextoverlay{-2}]
\defineoverlay[\v!text-1][\internaltextoverlay{-1}]
\defineoverlay[\v!text+1][\internaltextoverlay{+1}]
\defineoverlay[\v!text+2][\internaltextoverlay{+2}]
-
+
% to be documented
-\definelayer[anchor]
+% \definelayer[anchor]
+%
+% \unexpanded\def\defineanchor
+% {\doquadrupleempty\dodefineanchor}
+%
+% \def\dodefineanchor[#1][#2][#3][#4]%
+% {\setvalue{\??an#1}{\dodefinedanchor[#2][#3][#4]}}
+%
+% \def\dodefinedanchor[#1][#2][#3]%
+% {\def\docommand[##1][##2]%
+% {\ifsecondargument
+% \def\next{\dodoanchorT[#1][#2,##1][#3,##2]}%
+% \else\iffirstargument
+% \def\next{\dodoanchorT[#1][#2,##1][#2,##1]}%
+% \else
+% \def\next{\dodoanchorT[#1][#2][#3]}%
+% \fi\fi
+% \next}%
+% \dodoubleempty\docommand}
+%
+% \unexpanded\def\anchor
+% {\dosingleargument\pack_anchor}
+%
+% \def\pack_anchor[#1]%
+% {\ifcsname\??an#1\endcsname\@EA\nonoanchor\else\@EA\dodoanchor\fi[#1]}
+%
+% \def\nonoanchor[#1]%
+% {\csname\??an#1\endcsname}
+%
+% \def\dodoanchor[#1]%
+% {\dotripleempty\dododoanchor[#1]}
+%
+% \def\dododoanchor
+% {\ifthirdargument
+% \expandafter\dodoanchorT
+% \else
+% \expandafter\dodoanchorS
+% \fi}
+%
+% \def\dodoanchorS[#1][#2][#3]%
+% {\dodoanchorT[#1][#2][#2]}
+%
+% \def\dodoanchorT[#1][#2][#3]% brrr: we need to apply offset only once .. a bit messy
+% {\dowithnextbox
+% {\bgroup
+% % \checktextbackgrounds
+% \setbox\scratchbox\emptyhbox
+% \wd\scratchbox\nextboxwd
+% \ht\scratchbox\nextboxht
+% \dp\scratchbox\nextboxdp
+% \setlayer
+% [anchor]
+% [\c!width=\wd\scratchbox,
+% \c!height=\ht\scratchbox,
+% \c!offset=\!!zeropoint,
+% #2,#3]
+% {\setlayer[#1]{\flushnextbox}}%
+% \framed
+% [#2,
+% \c!background=anchor,
+% \c!offset=\v!overlay,
+% \c!frame=\v!off,
+% #3]
+% {\box\scratchbox}%
+% \egroup}%
+% \vbox}
+
+\installcorenamespace {anchor}
+
+\unexpanded\def\defineanchor
+ {\doquadrupleempty\pack_anchors_define}
+
+\def\pack_anchors_define[#1][#2][#3][#4]% name targetlayer layersetting framedsetting
+ {\setvalue{\??anchor#1}{\pack_anchors_process_defined{#2}{#3}{#4}}}
-\def\anchor
- {\dosingleargument\doanchor}
+\def\pack_anchors_process_defined#1#2#3%
+ {\def\pack_anchors_process_defined_indeed[##1][##2]%
+ {\ifsecondargument
+ \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#3,##2}}%
+ \else\iffirstargument
+ \def\next{\pack_anchors_process_indeed{#1}{#2,##1}{#2,##1}}%
+ \else
+ \def\next{\pack_anchors_process_indeed{#1}{#2}{#3}}%
+ \fi\fi
+ \next}%
+ \dodoubleempty\pack_anchors_process_defined_indeed}
-\def\doanchor[#1]%
- {\ifcsname\??an#1\endcsname\@EA\nonoanchor\else\@EA\dodoanchor\fi[#1]}
+\unexpanded\def\anchor[#1]%
+ {\begingroup
+ \edef\currentanchor{#1}%
+ \ifcsname\??anchor\currentanchor\endcsname
+ \expandafter\pack_anchor_predefined
+ \else
+ \expandafter\pack_anchor_notdefined
+ \fi}
-\def\nonoanchor[#1]%
- {}
+\def\pack_anchor_predefined
+ {\csname\??anchor\currentanchor\endcsname}
-\def\dodoanchor[#1]%
- {\dotripleempty\dododoanchor[#1]}
+\def\pack_anchor_notdefined
+ {\dodoubleempty\pack_anchor_notdefined_indeed}
-\def\dododoanchor
- {\ifthirdargument
- \expandafter\dodoanchorT
+\def\pack_anchor_notdefined_indeed
+ {\ifsecondargument
+ \expandafter\pack_anchor_notdefined_two
\else
- \expandafter\dodoanchorS
+ \expandafter\pack_anchor_notdefined_one
\fi}
-\def\dodoanchorS[#1][#2][#3]%
- {\dodoanchorT[#1][#2][#2]}
-
-\def\dodoanchorT[#1][#2][#3]%
- {\dowithnextbox
- {\bgroup
- \checktextbackgrounds
- \setbox\scratchbox\emptyhbox
- \wd\scratchbox\nextboxwd
- \ht\scratchbox\nextboxht
- \dp\scratchbox\nextboxdp
- \setlayer
- [anchor]
- [\c!width=\wd\scratchbox,
- \c!height=\ht\scratchbox,
- \c!offset=\!!zeropoint,
- #2,#3]
- {\setlayer[#1]{\flushnextbox}}%
- \framed
- [#2,
- \c!background=anchor,
- \c!offset=\v!overlay,
- \c!frame=\v!off,
- #3]
- {\box\scratchbox}%
- \egroup}%
- \vbox}
+\def\pack_anchor_notdefined_one[#1][#2]{\pack_anchors_process_indeed\currentanchor{#1}{#1}}
+\def\pack_anchor_notdefined_two[#1][#2]{\pack_anchors_process_indeed\currentanchor{#1}{#2}}
-\unexpanded\def\defineanchor
- {\doquadrupleempty\dodefineanchor}
+\def\pack_anchors_process_indeed#1#2#3%
+ {\dowithnextbox{\pack_anchors_process_finish{#1}{#2}{#3}}\vbox}
-\def\dodefineanchor[#1][#2][#3][#4]%
- {\setvalue{\??an#1}{\dodefinedanchor[#2][#3][#4]}}
+\newbox \b_pack_anchors
+\newdimen\d_pack_anchors_width
+\newdimen\d_pack_anchors_height
+\newdimen\d_pack_anchors_depth
+
+\definelayer[anchor] % \defineoverlay[anchor][\ruledhbox{\flushlayer[anchor]}]
+
+\def\pack_anchors_process_finish#1#2#3% brrr: we need to apply offset only once .. a bit messy
+ {\checkpositionoverlays
+ % for the moment we ignore the depth
+ \setbox\b_pack_anchors\box\nextbox
+ \d_pack_anchors_width \wd\b_pack_anchors
+ \d_pack_anchors_height\ht\b_pack_anchors
+ \d_pack_anchors_depth \dp\b_pack_anchors
+ \setbox\scratchbox\emptyhbox
+ \wd\scratchbox\d_pack_anchors_width
+ \ht\scratchbox\d_pack_anchors_height
+ \dp\scratchbox\d_pack_anchors_depth
+ \setlayer
+ [anchor]
+ [\c!width=\d_pack_anchors_width,
+ \c!height=\d_pack_anchors_height,
+ \c!offset=\zeropoint,
+ #2,#3]
+ {\setlayer[#1]{\box\b_pack_anchors}}% % #1 uses ovelaywidth/height
+ \framed
+ [\c!background=anchor,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
+ #3]
+ {\box\scratchbox}%
+ \endgroup}
+
+% collectors
-\def\dodefinedanchor[#1][#2][#3]%
- {\def\docommand[##1][##2]%
- {\ifsecondargument
- \def\next{\dodoanchorT[#1][#2,##1][#3,##2]}%
- \else\iffirstargument
- \def\next{\dodoanchorT[#1][#2,##1][#2,##1]}%
- \else
- \def\next{\dodoanchorT[#1][#2][#3]}%
- \fi\fi
- \next}%
- \dodoubleempty\docommand}
-
\def\@@collectorbox{@@collectorbox}
\unexpanded\def\definecollector
@@ -168,62 +251,62 @@
{\def\currentcollector{#1}%
\chardef\collectorbox\csname\@@collectorbox#1\endcsname
\getparameters[\??cb#1][#2]%
- \@@layerxsiz\wd\collectorbox
- \@@layerysiz\ht\collectorbox
+ \d_pack_layers_x_size\wd\collectorbox
+ \d_pack_layers_y_size\ht\collectorbox
\doifvaluesomething{\??cb#1\c!rotation}
{\setbox\nextbox\hbox
{\rotate
[\c!location=\v!high,
\c!rotation=\collectorparameter\c!rotation]
{\flushnextbox}}}%
- \advance\@@layerysiz\dp\collectorbox
- \@@layerxpos\collectorparameter\c!x
- \advance\@@layerxpos\collectorparameter\c!hoffset
- \@@layerypos\collectorparameter\c!y
- \advance\@@layerypos\collectorparameter\c!voffset
+ \advance\d_pack_layers_y_size\dp\collectorbox
+ \d_pack_layers_x_position\collectorparameter\c!x
+ \advance\d_pack_layers_x_position\collectorparameter\c!hoffset
+ \d_pack_layers_y_position\collectorparameter\c!y
+ \advance\d_pack_layers_y_position\collectorparameter\c!voffset
\doifelse\v!middle{\collectorparameter\c!corner}
- {\ifdim\@@layerxsiz>\zeropoint
- \advance\@@layerxpos.5\@@layerxsiz
+ {\ifdim\d_pack_layers_x_size>\zeropoint
+ \advance\d_pack_layers_x_position.5\d_pack_layers_x_size
\fi
- \ifdim\@@layerysiz>\zeropoint
- \advance\@@layerypos.5\@@layerysiz
+ \ifdim\d_pack_layers_y_size>\zeropoint
+ \advance\d_pack_layers_y_position.5\d_pack_layers_y_size
\fi}%
{\normalexpanded{\noexpand\doifinset{\v!bottom}{\collectorparameter\c!corner}}
- {\ifdim\@@layerysiz>\zeropoint
- \advance\@@layerypos-\@@layerysiz
- \@@layerypos-\@@layerypos
+ {\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}%
\normalexpanded{\noexpand\doifinset{\v!right}{\collectorparameter\c!corner}}
- {\ifdim\@@layerxsiz>\zeropoint
- \advance\@@layerxpos-\@@layerxsiz
- \@@layerxpos-\@@layerxpos
+ {\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}}%
\setbox\nextbox\hbox
{\alignedbox[\collectorparameter\c!location]\vbox{\flushnextbox}}%
\boxmaxdepth\zeropoint % really needed, nice example
- \global\advance\boxhdisplacement\@@layerxpos
+ \global\advance\boxhdisplacement\d_pack_layers_x_position
\ifdim\boxhdisplacement<\zeropoint
\global\setbox\collectorbox\hbox
{\hskip-\boxhdisplacement
\box\collectorbox}%
\fi
- \global\advance\boxvdisplacement\@@layerypos
+ \global\advance\boxvdisplacement\d_pack_layers_y_position
\ifdim\boxvdisplacement<\zeropoint
\global\setbox\collectorbox\hbox
{\lower-\boxvdisplacement
\box\collectorbox}%
\fi
- \@@layerxsiz\wd\collectorbox
- \@@layerysiz\ht\collectorbox
- \advance\@@layerysiz\dp\collectorbox
+ \d_pack_layers_x_size\wd\collectorbox
+ \d_pack_layers_y_size\ht\collectorbox
+ \advance\d_pack_layers_y_size\dp\collectorbox
\global\setbox\collectorbox\hbox
{\box\collectorbox
- \hskip-\@@layerxsiz
- \hskip\@@layerxpos\relax
+ \hskip-\d_pack_layers_x_size
+ \hskip\d_pack_layers_x_position\relax
\ifdim\boxhdisplacement<\zeropoint
\hskip-\boxhdisplacement
\fi
- \lower\@@layerypos\hbox
+ \lower\d_pack_layers_y_position\hbox
{\ifdim\boxvdisplacement<\zeropoint
\lower-\boxvdisplacement\flushnextbox
\else
@@ -233,8 +316,8 @@
\global\setbox\collectorbox\hbox
{\lower\ht\collectorbox\box\collectorbox}%
% just to be sure
- \ifdim\wd\collectorbox<\@@layerxsiz
- \global\wd\collectorbox\@@layerxsiz
+ \ifdim\wd\collectorbox<\d_pack_layers_x_size
+ \wd\collectorbox\d_pack_layers_x_size
\fi}
\def\flushcollector[#1]%
@@ -260,7 +343,7 @@
\def\adaptcollector
{\dodoubleargument\doadaptcollector}
-\def\doadaptcollector[#1][#2]%
+\def\doadaptcollector[#1][#2]% % a typical case where \global\wd looks better in the code
{\bgroup
\def\currentcollector{#1}%
\chardef\collectorbox\csname\@@collectorbox#1\endcsname
@@ -281,7 +364,7 @@
% [corner={right,bottom},location={left,top}]
% {\framed{gans}}
%\composedcollector{test}
-
+
\definecollector
[caption]
@@ -296,11 +379,12 @@
{\flushnextbox}%
\setcollector
[caption][#1]
- {\getparameters[\??du][#2]%
- \dosetfontattribute\??du\c!style\setupinterlinespace
+ {\getparameters[\??du][\c!style=,\c!color=,#2]%
+ \dousestyleparameter\@@dustyle
+ \setupinterlinespace
\framed % watch the special setting of kader/overlay
- [\c!frame=\v!overlay,#2]
- {\doattributes\??du\c!style\c!color{#3}}}%
+ [\c!frame=\v!overlay,\c!foregroundcolor=\@@ducolor,\c!foregroundstyle=\@@dustyle,#2]
+ {#3}}%
\composedcollector{caption}%
\egroup}%
\hbox}
@@ -323,37 +407,110 @@
% {gans}
% {\externalfigure[koe][width=3cm]}
-\definelayer
- [caption]
+% lean and mean:
+%
+% \installcorenamespace {layeredtext}
+%
+% \newdimen\d_pack_layeredtexts_width
+% \newdimen\d_pack_layeredtexts_height
+%
+% \definelayer
+% [\??layeredtextlayer]
+%
+% \setuplayer
+% [\??layeredtextlayer]%
+% [\c!width=\d_pack_layeredtexts_width,\c!height=\d_pack_layeredtexts_height]%
+%
+% \unexpanded\def\layeredtext
+% {\dodoubleempty\dolayeredtext}
+%
+% \def\dolayeredtext[#1][#2]#3%
+% {\bgroup
+% \dowithnextbox
+% {\d_pack_layeredtexts_width \wd\nextbox
+% \d_pack_layeredtexts_height\ht\nextbox
+% \begingroup % preserve \nextbox
+% \setlayer
+% [\??layeredtextlayer]%
+% [#1]%
+% {\getparameters[\??du][\c!style=,\c!color=,#2]%
+% \dousestyleparameter\@@dustyle
+% \setupinterlinespace
+% \framed
+% [\c!frame=\v!overlay,\c!foregroundcolor=\@@ducolor,\c!foregroundstyle=\@@dustyle,#2]%
+% {#3}}%
+% \endgroup
+% \framed
+% [\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]%
+% {\flushnextbox}%
+% \egroup}%
+% \hbox}
+%
+% maybe faster but more code:
+
+\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]
-\def\layeredtext
- {\dodoubleempty\dolayeredtext}
+\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]
-\def\dolayeredtext[#1][#2]#3%
+\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]
+
+\unexpanded\def\layeredtext
+ {\bgroup
+ \let\currentlayeredtext\empty
+ \dodoubleempty\pack_layeredtexts_place}
+
+\unexpanded\def\placelayeredtext[#1]%
{\bgroup
+ \edef\currentlayeredtext{#1}%
+ \dodoubleempty\pack_layeredtexts_place}
+
+\def\pack_layeredtexts_place[#1][#2]#3% layersettings content(framed)settings content
+ {\setupcurrentlayeredtext[#2]%
\dowithnextbox
- {\!!widtha \nextboxwd
- \!!heighta\nextboxht
- \bgroup % preserve \nextbox
- \setuplayer
- [caption]
- [\c!width=\!!widtha,\c!height=\!!heighta]%
+ {\d_pack_layeredtexts_width \wd\nextbox
+ \d_pack_layeredtexts_height\ht\nextbox
+ \begingroup % preserve \nextbox
\setlayer
- [caption]
- [#1]
- {\getparameters[\??du][#2]%
- \dosetfontattribute\??du\c!style\setupinterlinespace
- \framed
- [\c!frame=\v!overlay,,#2]
- {\doattributes\??du\c!style\c!color{#3}}}%
- \egroup
- \framed
- [\c!offset=\v!overlay,
- \c!frame=\v!off,
- \c!background={\v!foreground,caption},
- \c!width=\!!widtha,
- \c!height=\!!heighta]
- {\flushnextbox}%
+ [\??layeredtextlayer]%
+ [#1]%
+ {\setfalse\fontattributeisset
+ \uselayeredtextstyleparameter\c!style
+ \ifconditional\fontattributeisset
+ \setupinterlinespace
+ \fi
+ \inheritedlayeredtextframed{#3}}%
+ \endgroup
+ \placeframed[\??layeredtextframed]{\flushnextbox}%
\egroup}%
\hbox}
@@ -444,12 +601,12 @@
\c!hoffset=\@@bgoffset]
\unexpanded\def\bleed
- {\dosingleempty\dobleed}
+ {\dosingleempty\pack_boxes_bleed}
\def\bleedwidth {\the\hsize}%
\def\bleedheight{\the\vsize}%
-\def\dobleed[#1]#2%
+\def\pack_boxes_bleed[#1]#2%
{\hbox\bgroup
\xdef\bleedwidth {\the\hsize}%
\xdef\bleedheight{\the\vsize}%
@@ -553,33 +710,41 @@
% 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 ...
+
\def\setlayerframed
- {\dotripleempty\dosetlayerframed}
+ {\dotripleempty\pack_layers_set_framed}
-\def\dosetlayerframed
+\def\pack_layers_set_framed
{\ifthirdargument
- \expandafter\dosetlayerframedT
+ \singleexpandafter\pack_layers_set_framed_t
+ \else\ifsecondargument
+ \doubleexpandafter\pack_layers_set_framed_d
\else
- \expandafter\dosetlayerframedS
- \fi}
+ \doubleexpandafter\pack_layers_set_framed_s
+ \fi\fi}
-\def\dosetlayerframedT[#1][#2][#3]%
- {\dowithnextbox{\setlayer[#1][#2]{\flushnextbox}}%
- \hbox\framed[#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]} % diffrent 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]} % diffrent kind of location
+
+\def\pack_layers_set_framed_t[#1][#2][#3]%
+ {\setlayer[#1][#2]%
+ \normalframedwithsettings[#3]}
-\def\dosetlayerframedS[#1][#2][#3]%
- {\dowithnextbox % we could use a local setlayer command (no doif..empty) which also saves a nextbox
- {\setlayer[#1][\c!width=\nextboxwd,\c!height=\nextboxht,\c!offset=\!!zeropoint,#2]{\flushnextbox}}%
- \hbox\framed[\c!location=\v!normal,#2]}
-
\def\setlayertext
- {\dotripleempty\dosetlayertext}
+ {\dotripleempty\pack_layers_set_text}
-\def\dosetlayertext[#1][#2][#3]%
+\def\pack_layers_set_text[#1][#2][#3]%
{\bgroup
\getparameters
[\??lx]
@@ -591,12 +756,12 @@
\dowithnextboxcontent
{\forgetall
\hsize\@@lxwidth
- \expanded{\setupalign[\@@lxalign]}%
- \dosetfontattribute\??lx\c!style}
- {\setlayer[#1][#2]{\strut\color[\@@lxcolor]{\flushnextbox}}%
+ \normalexpanded{\setupalign[\@@lxalign]}%
+ \dousestyleparameter\@@lxstyle}
+ {\setlayer[#1][#2]{\strut\dousecolorparameter\@@lxcolor\flushnextbox}%
\egroup}%
\vtop}
-
+
% \setupbackgrounds
% [page]
% [background=pagefigures]
@@ -670,159 +835,145 @@
\definelayerpreset
[\v!middle\v!right]
[\c!location=\v!left,\c!corner=\v!right,\c!dy=.5\layerheight]
-
-\def\alignedbox
- {\dodoubleempty\doalignedbox[]}
-% \def\doalignedbox[#1][#2]%
-% {\bgroup
-% %\let\iftraceboxplacement\iftracelayers % ugly
-% \dowithnextbox
-% {\let\next\middlebox
-% \processaction
-% [#2]
-% [ t=>\let\next\topbox , b=>\let\next\bottombox ,
-% l=>\let\next\leftbox , r=>\let\next\rightbox ,
-% bl=>\let\next\bottomleftbox,br=>\let\next\bottomrightbox,
-% tl=>\let\next\topleftbox ,tr=>\let\next\toprightbox ,
-% lt=>\let\next\lefttopbox ,lb=>\let\next\leftbottombox ,
-% rt=>\let\next\righttopbox ,rb=>\let\next\rightbottombox]%
-% \next{\flushnextbox}%
-% \egroup}#1}
-
-\def\doalignedbox[#1][#2]%
- {\bgroup
- %\let\iftraceboxplacement\iftracelayers % ugly
- \dowithnextbox
- {\serializecommalist[#2]%
- \executeifdefined{\??ab\??ab\serializedcommalist}\middlebox{\flushnextbox}%
- \egroup}#1}
-
-\setvalue{\??ab\??ab }{\middlebox}
-\setvalue{\??ab\??ab\v!middle }{\middlebox}
-\setvalue{\??ab\??ab\v!left }{\leftbox }
-\setvalue{\??ab\??ab\v!right }{\rightbox }
-\setvalue{\??ab\??ab\v!bottom }{\bottombox}
-\setvalue{\??ab\??ab\v!top }{\topbox }
-
-\setvalue{\??ab\??ab\v!middle\v!middle}{\middlebox}
-\setvalue{\??ab\??ab\v!left \v!top }{\lefttopbox}
-\setvalue{\??ab\??ab\v!left \v!bottom}{\leftbottombox}
-\setvalue{\??ab\??ab\v!right \v!top }{\righttopbox}
-\setvalue{\??ab\??ab\v!right \v!bottom}{\rightbottombox}
-\setvalue{\??ab\??ab\v!top \v!left }{\topleftbox}
-\setvalue{\??ab\??ab\v!bottom\v!left }{\bottomleftbox}
-\setvalue{\??ab\??ab\v!top \v!right }{\toprightbox}
-\setvalue{\??ab\??ab\v!bottom\v!right }{\bottomrightbox}
-
-\setvalue{\??ab\??ab c}{\middlebox}
-\setvalue{\??ab\??ab l}{\leftbox}
-\setvalue{\??ab\??ab r}{\rightbox}
-\setvalue{\??ab\??ab b}{\bottombox}
-\setvalue{\??ab\??ab t}{\topbox}
-
-\setvalue{\??ab\??ab lt}{\lefttopbox}
-\setvalue{\??ab\??ab lb}{\leftbottombox}
-\setvalue{\??ab\??ab rt}{\righttopbox}
-\setvalue{\??ab\??ab rb}{\rightbottombox}
-\setvalue{\??ab\??ab tl}{\topleftbox}
-\setvalue{\??ab\??ab bl}{\bottomleftbox}
-\setvalue{\??ab\??ab tr}{\toprightbox}
-\setvalue{\??ab\??ab br}{\bottomrightbox}
-
-\setvalue{\??ab\??ab m}{\middlebox}
-
-% The next ones were desparately needed by Vit Zyka (see
-% \type {supp-box} for definitions).
-
-\setvalue{\??ab\??ab g}{\baselinemiddlebox}
-\setvalue{\??ab\??ab gl}{\baselineleftbox}
-\setvalue{\??ab\??ab gc}{\baselinemiddlebox}
-\setvalue{\??ab\??ab gr}{\baselinerightbox}
-
-\setvalue{\??ab\??ab \v!line }{\baselinemiddlebox} % \v!grid is taken
-\setvalue{\??ab\??ab \v!line\v!left }{\baselineleftbox}
-\setvalue{\??ab\??ab \v!line\v!middle}{\baselinemiddlebox}
-\setvalue{\??ab\??ab \v!line\v!right }{\baselinerightbox}
-
-\unexpanded\def\offsetbox
- {\dodoubleempty\dooffsetbox[]}
+% 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}
+
+\unexpanded\def\alignedbox{\dosingleempty\pack_boxes_aligned_box}
+\unexpanded\def\aligned {\dosingleempty\pack_boxes_aligned}
+
+\def\pack_boxes_aligned_box[#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish}
+\def\pack_boxes_aligned [#1]{\bgroup\serializecommalist[#1]\dowithnextboxcs\pack_boxes_aligned_finish\hbox}
+
+\def\pack_boxes_aligned_finish
+ {\csname\??alignedboxes
+ \ifcsname\??alignedboxes\serializedcommalist\endcsname\serializedcommalist\else\v!middle\fi
+ \endcsname{\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
-\def\dooffsetbox[#1][#2]%
- {\bgroup
- \dowithnextbox
- {\getparameters[\??ox]
- [\c!x=\zeropoint,
- \c!y=\zeropoint,
- \c!width=\nextboxwd,
- \c!height=\nextboxht,
- \c!depth=\nextboxdp,
- \c!location=,
- \c!leftoffset=\zeropoint,
- \c!rightoffset=\zeropoint,
- \c!topoffset=\zeropoint,
- \c!bottomoffset=\zeropoint,
- \c!method=,
- #2]%
- \donefalse
- \ifdim\@@oxleftoffset =\zeropoint\else\donetrue\fi
- \ifdim\@@oxrightoffset=\zeropoint\else\donetrue\fi
- \ifdim\@@oxtopoffset =\zeropoint\else\donetrue\fi
- \ifdim\@@oxbottomoffset =\zeropoint\else\donetrue\fi
- \ifdone
- \doif\@@oxmethod\v!fixed % new
- {\ifdim\@@oxleftoffset=\zeropoint
- \ifdim\@@oxrightoffset=\zeropoint \else
- \scratchdimen-\@@oxrightoffset
- \edef\@@oxx{\the\scratchdimen}%
- \let\@@oxrightoffset\zeropoint
- \fi
- \else
- \let\@@oxx\@@oxleftoffset
- \let\@@oxleftoffset\zeropoint
- \fi
- \ifdim\@@oxtopoffset=\zeropoint
- \ifdim\@@oxbottomoffset=\zeropoint \else
- \scratchdimen-\@@oxbottomoffset
- \edef\@@oxy{\the\scratchdimen}%
- \let\@@oxbottomoffset\zeropoint
- \fi
- \else
- \let\@@oxy\@@oxtopoffset
- \let\@@oxtopoffset\zeropoint
- \fi
- \donefalse}%
- \fi
- \ifdone
- \setbox\nextbox\vbox
- {\forgetall\offinterlineskip
- \vskip\@@oxtopoffset
- \hbox
- {\hskip\@@oxleftoffset
- \flushnextbox
- \hskip\@@oxrightoffset}%
- \vskip\@@oxbottomoffset}%
- \scratchdimen\nextboxht
- \advance\scratchdimen\nextboxdp
- \nextboxht\scratchdimen
- \nextboxdp\zeropoint
- \fi
- \freezedimenmacro\@@oxwidth
- \freezedimenmacro\@@oxheight
- \freezedimenmacro\@@oxdepth
- \setbox\nextbox\hbox
- {\hskip\@@oxx\lower\@@oxy\hbox
- {\doifelsenothing\@@oxlocation
- {\flushnextbox}
- {\alignedbox[\@@oxlocation]\hbox{\flushnextbox}}}}%
- \nextboxwd\@@oxwidth
- \nextboxht\@@oxheight
- \nextboxdp\@@oxdepth
- \flushnextbox
- \egroup}#1}
+\unexpanded\def\offsetbox{\dosingleempty\pack_boxes_offset_box}
+\unexpanded\def\offset {\dosingleempty\pack_boxes_offset}
+
+\def\pack_boxes_offset_box[#1]{\bgroup\dowithnextbox{\pack_boxes_offsetfinish{#1}}}
+\def\pack_boxes_offset [#1]{\bgroup\dowithnextbox{\pack_boxes_offsetfinish{#1}}\hbox}
+
+\def\pack_boxes_offsetfinish#1%
+ {\getparameters[\??ox]
+ [\c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!width=\nextboxwd,
+ \c!height=\nextboxht,
+ \c!depth=\nextboxdp,
+ \c!location=,
+ \c!leftoffset=\zeropoint,
+ \c!rightoffset=\zeropoint,
+ \c!topoffset=\zeropoint,
+ \c!bottomoffset=\zeropoint,
+ \c!method=,
+ #1]%
+ \donefalse
+ \ifdim\@@oxleftoffset =\zeropoint\else\donetrue\fi
+ \ifdim\@@oxrightoffset =\zeropoint\else\donetrue\fi
+ \ifdim\@@oxtopoffset =\zeropoint\else\donetrue\fi
+ \ifdim\@@oxbottomoffset=\zeropoint\else\donetrue\fi
+ \ifdone
+ \doif\@@oxmethod\v!fixed % new
+ {\ifdim\@@oxleftoffset=\zeropoint
+ \ifdim\@@oxrightoffset=\zeropoint \else
+ \edef\@@oxx{\the\dimexpr-\@@oxrightoffset}%
+ \let\@@oxrightoffset\zeropoint
+ \fi
+ \else
+ \let\@@oxx\@@oxleftoffset
+ \let\@@oxleftoffset\zeropoint
+ \fi
+ \ifdim\@@oxtopoffset=\zeropoint
+ \ifdim\@@oxbottomoffset=\zeropoint \else
+ \edef\@@oxy{\the\dimexpr-\@@oxbottomoffset}%
+ \let\@@oxbottomoffset\zeropoint
+ \fi
+ \else
+ \let\@@oxy\@@oxtopoffset
+ \let\@@oxtopoffset\zeropoint
+ \fi
+ \donefalse}%
+ \fi
+ \ifdone
+ \setbox\nextbox\vbox
+ {\forgetall % already done
+ \offinterlineskip
+ \vskip\@@oxtopoffset
+ \hbox
+ {\hskip\@@oxleftoffset
+ \box\nextbox
+ \hskip\@@oxrightoffset}%
+ \vskip\@@oxbottomoffset}%
+ \ht\nextbox\htdp\nextbox
+ \dp\nextbox\zeropoint
+ \fi
+ \freezedimenmacro\@@oxwidth
+ \freezedimenmacro\@@oxheight
+ \freezedimenmacro\@@oxdepth
+ \setbox\nextbox\hbox
+ {\hskip\@@oxx\lower\@@oxy\hbox
+ {\doifelsenothing\@@oxlocation
+ {\box\nextbox}
+ {\alignedbox[\@@oxlocation]\hbox{\box\nextbox}}}}%
+ \wd\nextbox\@@oxwidth
+ \ht\nextbox\@@oxheight
+ \dp\nextbox\@@oxdepth
+ \box\nextbox
+ \egroup}
% \useMPlibrary[pre] \setupbackgrounds[page][background=pagegrid]
%
@@ -834,73 +985,43 @@
% \input tufte
% \placefigure[left,none]{}{\offset[bottomoffset=1cm]{\externalfigure[koe][breedte=3cm]}}
% \input tufte
-
-\unexpanded\def\offset {\dodoubleempty\dooffsetbox [\hbox]} % yes or no
-\unexpanded\def\aligned{\dosingleempty\doalignedbox[\hbox]} % yes or no
%\ruledhbox{\offsetbox[x=-1cm,y=-1cm,location=c]
% {\framed[width=4cm,height=4cm]{x}}}
-
-\def\dotabbed#1#2#3#4%
+
+% 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
- \bgroup
+ \begingroup
\setbox\scratchbox\hbox{#3}%
\hbox to \wd\scratchbox{#1#4#2}%
- \egroup}
+ \endgroup}
+
+\unexpanded\def\ltabbed{\pack_boxes_tabbed\relax\hss}
+\unexpanded\def\rtabbed{\pack_boxes_tabbed\hss \relax}
+\unexpanded\def\ctabbed{\pack_boxes_tabbed\hss \hss}
+
+\let\mtabbed\ctabbed
-\unexpanded\def\ltabbed{\dotabbed\relax\hss}
-\unexpanded\def\rtabbed{\dotabbed\hss \relax}
-\unexpanded\def\ctabbed{\dotabbed\hss \hss} \let\mtabbed\ctabbed
-
-% \ltabbed{\romeins{3}}{\romeins{1}} test \endgraf
-% \ltabbed{\romeins{3}}{\romeins{2}} test \endgraf
-% \ltabbed{\romeins{3}}{\romeins{3}} test \endgraf
-%
-% \rtabbed{\romeins{3}}{\romeins{1}} test \endgraf
-% \rtabbed{\romeins{3}}{\romeins{2}} test \endgraf
-% \rtabbed{\romeins{3}}{\romeins{3}} test \endgraf
-%
-% \ctabbed{\romeins{3}}{\romeins{1}} test \endgraf
-% \ctabbed{\romeins{3}}{\romeins{2}} test \endgraf
-% \ctabbed{\romeins{3}}{\romeins{3}} test \endgraf
-
-% alternative, if done, then other name
-%
-% \def\dotabbed#1#2#3#4%
-% {\dontleavehmode
-% \bgroup
-% \scratchdimen\zeropoint
-% \def\docommand##1%
-% {\setbox\scratchbox\hbox{##1}%
-% \ifdim\wd\scratchbox>\scratchdimen
-% \scratchdimen\wd\scratchbox
-% \fi}%
-% \processcommalist[#3]\docommand
-% \hbox to \scratchdimen{#1#4#2}%
-% \egroup}
-%
-% \def\ltabbed{\dotabbed\relax\hss}
-% \def\rtabbed{\dotabbed\hss \relax}
-% \def\ctabbed{\dotabbed\hss \hss} \let\mtabbed\ctabbed
-%
-% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
-% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
-% \ltabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
-%
-% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
-% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
-% \rtabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
-%
-% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{10}} test \endgraf
-% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{15}} test \endgraf
-% \ctabbed{\romeins{10},\romeins{2000},\romeins{15}}{\romeins{2000}} test \endgraf
-
% to be documented
-\unexpanded\def\phantombox[#1]%
+\unexpanded\def\phantombox[#1]% == \framed[\c!empty=\v!yes,\c!offset=\v!overlay,#1]{}
{\hbox\bgroup
\getparameters
- [\??ol]
+ [\??ol] % brrr
[\c!width=\zeropoint,%
\c!height=\zeropoint,%
\c!depth=\zeropoint,#1]%
@@ -910,39 +1031,41 @@
\dp\scratchbox\@@oldepth
\box\scratchbox
\egroup}
-
+
% \backgroundimage{1}{\hsize}{\vsize}{\externalfigure[cow][\c!width=3cm]}
\unexpanded\def\backgroundimage#1#2#3% repeat hsize vsize
{\bgroup
\forgetall
- \dowithnextbox
- {\offinterlineskip
- \ifcase#1\relax
- % just one
- \else
- \scratchdimen#2\divide\scratchdimen\nextboxwd\count0\scratchdimen\advance\count0\plusone
- \scratchdimen#3\divide\scratchdimen\nextboxht\count2\scratchdimen\advance\count2\plusone
- % to be considered, probably methods
- \ifcase#1\or % x and y
- \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
- \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
- \or % x
- \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
- \or % y
- \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
- \fi
- \fi
- \ifdim\nextboxwd>#2\relax
- \setbox\nextbox\hbox to #2{\hss\flushnextbox\hss}%
- \setbox\nextbox\hbox{\expanded{\clip[\c!width=#2,\c!height=\the\nextboxht]{\flushnextbox}}}%
- \fi
- \ifdim\nextboxht>#3\relax
- \setbox\nextbox\vbox to #3{\vss\flushnextbox\vss}%
- \setbox\nextbox\hbox{\expanded{\clip[\c!width=\the\nextboxwd,\c!height=#3]{\flushnextbox}}}%
- \fi
- \flushnextbox
- \egroup}%
- \hbox}
-
+ \dowithnextbox{\pack_boxes_background_image{#1}{#2}{#3}}\hbox}
+
+\def\pack_boxes_background_image#1#2#3%
+ {\offinterlineskip
+ \ifcase#1\relax
+ % just one
+ \else
+ \scratchdimen#2\divide\scratchdimen\wd\nextbox\count0\scratchdimen\advance\count0\plusone
+ \scratchdimen#3\divide\scratchdimen\ht\nextbox\count2\scratchdimen\advance\count2\plusone
+ % to be considered: methods
+ \ifcase#1%
+ \or % x and y
+ \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
+ \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
+ \or % x
+ \setbox\nextbox\hbox{\dorecurse{\count0}{\copy\nextbox}}%
+ \or % y
+ \setbox\nextbox\vbox{\dorecurse{\count2}{\copy\nextbox\endgraf}}%
+ \fi
+ \fi
+ \ifdim\wd\nextbox>#2\relax
+ \setbox\nextbox\hbox to #2{\hss\box\nextbox\hss}%
+ \setbox\nextbox\hbox{\normalexpanded{\clip[\c!width=#2,\c!height=\the\ht\nextbox]{\box\nextbox}}}%
+ \fi
+ \ifdim\ht\nextbox>#3\relax
+ \setbox\nextbox\vbox to #3{\vss\box\nextbox\vss}%
+ \setbox\nextbox\hbox{\normalexpanded{\clip[\c!width=\the\wd\nextbox,\c!height=#3]{\box\nextbox}}}%
+ \fi
+ \box\nextbox
+ \egroup}
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/pack-com.mkiv b/Master/texmf-dist/tex/context/base/pack-com.mkiv
new file mode 100644
index 00000000000..4d50bf7c70c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/pack-com.mkiv
@@ -0,0 +1,798 @@
+%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
+%D mechanisms but as it has served us well for ages we keep
+%D this one. The code has been cleaned up a bit 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
+%D only window dressing:
+%D
+%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
+%D 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
+ \global\resetsystemmode{combination}%
+\to \everyinsidefloat
+
+\newcount\c_pack_combinations_x
+\newcount\c_pack_combinations_n
+\newcount\c_pack_combinations_max
+\newbox \b_pack_combinations_captions
+\newbox \b_pack_combinations_content
+\newbox \b_pack_combinations_caption
+\newbox \b_pack_combinations_temp % global
+
+\installcorenamespace{combination}
+
+\installcommandhandler \??combination {combination} \??combination
+
+\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}
+
+\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}
+
+\unexpanded\def\startcombination
+ {\bgroup % so we can grab a group
+ \dodoubleempty\pack_combinations_start}
+
+% formally ok:
+%
+% \unexpanded\def\stopcombination
+% {\egroup
+% \egroup}
+%
+% more robust:
+%
+% \unexpanded\def\stopcombination
+% {{}{}{}{}{}{}{}{}% catches (at most 4) missing entries
+% \egroup
+% \egroup}
+%
+% even better:
+%
+% \unexpanded\def\stopcombination
+% {\bgroup
+% \scratchtoks{{}}%
+% \dorecurse\c_pack_combinations_n
+% {\scratchtoks\expandafter{\the\scratchtoks{}{}}}%
+% \expandafter\egroup\the\scratchtoks
+% \egroup
+% \dostoptagged
+% \egroup}
+%
+% faster
+
+\unexpanded\def\stopcombination
+ {\bgroup\normalexpanded{\egroup{}\ctxcommand{ntimes("{}{}",\number\c_pack_combinations_n)}}%
+ \dostoptagged
+ \egroup
+ \egroup}
+
+\def\pack_combinations_start[#1][#2]% needs a cleanup, also nx ny (pretty old, this one)
+ {\global\setsystemmode{combination}%
+ %
+ \edef\currentcombination{#1}%
+ \edef\currentcombinationspec{#2}%
+ \ifx\currentcombinationspec\empty
+ \doifinstringelse{*}\currentcombination
+ {\edef\currentcombinationspec{\currentcombination*\plusone*}%
+ \let\currentcombination\empty}
+ {\doifnumberelse\currentcombination
+ {\edef\currentcombinationspec{\currentcombination*\plusone*}%
+ \let\currentcombination\empty}
+ {\edef\currentcombinationspec{\combinationparameter\c!nx*\combinationparameter\c!ny*}}}%
+ \else
+ \edef\currentcombinationspec{\currentcombinationspec*\plusone*}%
+ \fi
+ %
+ \forgetall
+ %
+ \let\startcontent\bgroup
+ \let\stopcontent \egroup
+ \let\startcaption\bgroup
+ \let\stopcaption \egroup
+ %
+ \edef\p_height {\combinationparameter\c!height}%
+ \edef\p_width {\combinationparameter\c!width}%
+ \edef\p_location{\combinationparameter\c!location}%
+ \edef\p_align {\combinationparameter\c!align}%
+ \edef\p_distance{\combinationparameter\c!distance}%
+ %
+ \pack_combinations_location_reset
+ \rawprocesscommacommand[\p_location]\pack_combinations_location_step
+ %
+ \dostarttagged\t!combination\currentcombination
+ \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]}}
+
+\unexpanded\def\pack_combinations_start_indeed[#1*#2*#3]%
+ {\global\c_pack_combinations_x#1\relax
+ \global\c_pack_combinations_n#2\relax
+ \dotagcombination
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \global\c_pack_combinations_max\c_pack_combinations_x
+ \multiply\c_pack_combinations_n\c_pack_combinations_x
+ \tabskip\zeropoint
+ \halign \ifx\p_width\v!fit\else to \p_width \fi \bgroup
+ \aligntab
+ \m_pack_combinations_leftfiller
+ \alignmark\alignmark
+ \m_pack_combinations_rightfiller
+ \aligntab
+ \tabskip\zeropoint \!!plus 1fill
+ \alignmark\alignmark
+ \cr
+ \pack_combinations_pickup}
+
+\def\pack_combinations_pickup % we want to add struts but still ignore an empty box
+ {\dostarttagged\t!combinationpair\empty
+ \dostarttagged\t!combinationcontent\empty
+ \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
+ \dowithnextboxcs\pack_combinations_pickup_caption\vtop\bgroup
+ \afterassignment\pack_combinations_caption_first
+ \let\nexttoken=}
+
+\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
+ \else
+ \hsize\wd\b_pack_combinations_content
+ \ifx\p_align\empty\else\setupalign[\p_align]\fi
+ \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{\copy\b_pack_combinations_content}%
+ % we need to save the caption for a next alignment line
+ \pack_combinations_save_caption}%
+ \ifnum\c_pack_combinations_n>\plusone
+ \global\advance\c_pack_combinations_n\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
+ \hskip\p_distance
+ \aligntab
+ \pack_combinations_pickup}
+
+\def\pack_combinations_pickup_package_pair_c
+ {\cr
+ \pack_combinations_flush_captions
+ \egroup}
+
+\def\pack_combinations_save_caption
+ {\global\setbox\b_pack_combinations_captions\hbox
+ {\hbox{\box\b_pack_combinations_caption}%
+ \unhbox\b_pack_combinations_captions}}
+
+\def\pack_combinations_flush_captions
+ {\noalign
+ {\ifdim\ht\b_pack_combinations_captions>\zeropoint
+ \nointerlineskip % indeed
+ \combinationparameter\c!inbetween
+ \global\c_pack_combinations_x\c_pack_combinations_max
+ \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_yes
+ \else
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \globallet\pack_combinations_flush_captions_indeed\pack_combinations_flush_captions_nop
+ \fi}%
+ \pack_combinations_flush_captions_indeed
+ \crcr}
+
+\def\pack_combinations_flush_captions_yes
+ {\global\setbox\b_pack_combinations_captions\hbox
+ {\unhbox\b_pack_combinations_captions
+ \global\setbox\b_pack_combinations_temp\lastbox}%
+ \box\b_pack_combinations_temp
+ \global\advance\c_pack_combinations_x\minusone\relax
+ \ifnum\c_pack_combinations_x>\zerocount
+ \expandafter\pack_combinations_flush_captions_yes_followup
+ \else
+ \global\setbox\b_pack_combinations_captions\emptybox
+ \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
+
+\unexpanded\def\startfloatcombination
+ {\dodoubleempty\pack_combinations_start_float}
+
+\let\stopfloatcombination\relax
+
+\def\pack_combinations_start_float[#1][#2]%
+ {\vbox\bgroup
+ %\insidecolumnstrue % trick, forces no centering, todo: proper switch/feature
+ \postcenterfloatmethod\zerocount
+ \forcelocalfloats
+ \unexpanded\def\stopfloatcombination{\pack_combinations_stop_float{#1}}}
+
+\def\pack_combinations_stop_float#1%
+ {\scratchtoks\emptytoks
+ \dorecurse\noflocalfloats
+ {\appendetoks{\noexpand\getlocalfloat{\recurselevel}}{}\to\scratchtoks}% brrr
+ \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
+%D legend is just an instance, are primarily meant for
+%D typesetting some text alongside an illustration. Although
+%D there is quite some variation possible, the functionality is
+%D kept simple, if only because in most cases such pairs are
+%D typeset sober.
+%D
+%D The location specification accepts a pair, where the first
+%D keyword specifies the arrangement, and the second one the
+%D alignment. The first key of the location pair is one of
+%D \type {left}, \type {right}, \type {top} or \type {bottom},
+%D while the second key can also be \type {middle}.
+%D
+%D The first box is just collected in an horizontal box, but
+%D the second one is a vertical box that gets passed the
+%D bodyfont and alignment settings.
+
+%D In many cases the table builders can be used instead, but as
+%D this mechanism is a traditional \CONTEXT\ one we keep it
+%D around.
+
+%D \macros
+%D {setuplegend, placelegend}
+%D
+%D It makes sense to typeset a legend to a figure in \TEX\
+%D and not in a drawing package. The macro \type {\placelegend}
+%D combines a figure (or something else) and its legend. This
+%D command is just a paired box.
+%D
+%D The legend is placed according to \type {location}, being
+%D \type {bottom} or \type {right}. The macro macro is used as
+%D 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
+ \global\resetsystemmode{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
+
+\unexpanded\def\placepairedbox[#1]%
+ {\bgroup
+ \edef\currentpairedbox{#1}%
+ \doifnextoptionalelse\pack_pairedboxes_place\pack_pairedboxes_place_indeed}
+
+\unexpanded\def\startplacepairedbox[#1]%
+ {\bgroup
+ \edef\currentpairedbox{#1}%
+ \doifnextoptionalelse\pack_pairedboxes_place\pack_pairedboxes_place_indeed}
+
+\unexpanded\def\stopplacepairedbox
+ {}
+
+\def\pack_pairedboxes_place[#1]%
+ {\setupcurrentpairedbox[#1]%
+ \pack_pairedboxes_place_indeed}
+
+\def\pack_pairedboxes_place_indeed
+ {\pairedboxparameter\c!before
+ \bgroup
+ \edef\p_location{\pairedboxparameter\c!location}%
+ \edef\p_n {\pairedboxparameter\c!n}%
+ %
+ \let\startcontent\bgroup
+ \let\stopcontent \egroup
+ \let\startcaption\bgroup
+ \let\stopcaption \egroup
+ %
+ \global\setsystemmode{pairedbox}%
+ \pack_pairedboxes_before
+ \dowithnextboxcs\pack_pairedboxes_first\hbox}
+
+\def\pack_pairedboxes_first
+ {\pack_pairedboxes_between
+ \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
+ \hskip\pairedboxparameter\c!distance
+ \box\b_pack_pairedboxes_first}
+
+\def\pack_pairedboxes_flush_right
+ {\box\b_pack_pairedboxes_first
+ \hskip\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\hss
+ \let\pack_pairedboxes_align_b\hss}
+
+\setvalue{\??pairedboxalign\v!bottom}{\getvalue{\??pairedboxalign\v!low }}
+\setvalue{\??pairedboxalign \v!top}{\getvalue{\??pairedboxalign\v!high}}
+
+\def\pack_pairedbox_valign#1{\setbox#1\vbox to \s_pack_pairedboxes_size{\pack_pairedboxes_align_t\box#1\pack_pairedboxes_align_b}}
+\def\pack_pairedbox_halign#1{\setbox#1\hbox 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
+ {\switchtobodyfont[\pairedboxparameter\c!bodyfont]% split under same regime
+ \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
+ {\hsize\wd\b_pack_pairedboxes_first % trick
+ \hsize\pairedboxparameter\c!width % can be \hsize
+ \scratchdimen\dimexpr\wd\b_pack_pairedboxes_first+\pairedboxparameter\c!distance\relax
+ \ifdim\dimexpr\hsize+\scratchdimen\relax>\pairedboxparameter\c!maxwidth\relax
+ \hsize\dimexpr\pairedboxparameter\c!maxwidth-\scratchdimen\relax
+ \fi}
+
+\def\pack_pairedboxes_between_vertical
+ {\hsize\wd\b_pack_pairedboxes_first
+ \hsize\pairedboxparameter\c!width % can be \hsize
+ \ifdim\hsize>\pairedboxparameter\c!maxwidth\relax
+ \hsize\pairedboxparameter\c!maxwidth % can be \hsize
+ \fi}
+
+\def\pack_pairedboxes_after
+ {\setbox\b_pack_pairedboxes_second\vbox
+ {\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
+ {\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
+ {\vbox\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\vbox 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}}
+
+\definepairedbox[\v!legend]
+
+\unexpanded\def\placeontopofeachother{\bgroup\dowithnextboxcs\pack_topofeachother_one\hbox}
+\unexpanded\def\placesidebyside {\bgroup\dowithnextboxcs\pack_sidebyside_one \hbox}
+
+\def\pack_topofeachother_one{\bgroup\setbox0\box\nextbox\dowithnextboxcs\pack_topofeach_two \hbox}
+\def\pack_sidebyside_one {\bgroup\setbox0\box\nextbox\dowithnextboxcs\pack_sidebyside_two\hbox}
+
+\def\pack_topofeachother_two{\setbox2\box\nextbox\halign{\hss####\hss\cr\box0\cr\box2\cr}\egroup\egroup}
+\def\pack_sidebyside_two {\setbox2\box\nextbox\valign{\vss####\vss\cr\box0\cr\box2\cr}\egroup\egroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/pack-fen.mkiv b/Master/texmf-dist/tex/context/base/pack-fen.mkiv
new file mode 100644
index 00000000000..575c4684931
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/pack-fen.mkiv
@@ -0,0 +1,97 @@
+%D \module
+%D [ file=pack-fen,
+%D version=2011.07.21,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle= Fences for Ruled Content,
+%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 / Fences for Ruled Content}
+
+%D \startbuffer
+%D \useMPlibrary[meta-imp-hooks.mkiv]
+%D
+%D \framed[frame=off,bottomframe=righthook]{Bottom right hook}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
+
+\unprotect
+
+\def\installleftframerenderer#1#2%
+ {\setvalue{\??framedleft\v!on#1}{\whateverleftframe{#2}}%
+ \expandafter\let\csname\??framedleft\v!off#1\expandafter\endcsname\csname\??framedleft\v!on#1\endcsname}
+
+\def\installrightframerenderer#1#2%
+ {\setvalue{\??framedright\v!on#1}{\whateverrightframe{#2}}%
+ \expandafter\let\csname\??framedright\v!off#1\expandafter\endcsname\csname\??framedright\v!on#1\endcsname}
+
+\def\installtopframerenderer#1#2%
+ {\setvalue{\??framedtop\v!on#1}{\whatevertopframe{#2}}%
+ \expandafter\let\csname\??framedtop\v!off#1\expandafter\endcsname\csname\??framedtop\v!on#1\endcsname}
+
+\def\installbottomframerenderer#1#2%
+ {\setvalue{\??framedbottom\v!on#1}{\whateverbottomframe{#2}}%
+ \expandafter\let\csname\??framedbottom\v!off#1\expandafter\endcsname\csname\??framedbottom\v!on#1\endcsname}
+
+\ifdefined \pack_framed_overlay_initialize_indeed
+
+ \let\installedframedimensions\pack_framed_overlay_initialize_indeed
+
+\else
+
+ \def\setinstalledframedimensions
+ {\edef\overlaywidth {\the\frameddimenwd\space}%
+ \edef\overlayheight {\the\dimexpr\frameddimenht+\frameddimendp\relax\space}%
+ \edef\overlaydepth {\the\frameddimendp\space}%
+ \edef\overlaycolor {\framedparameter\c!backgroundcolor}%
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}%
+ \edef\overlaylinewidth{\the\ruledlinewidth}}
+
+\fi
+
+\newbox\b_framed_rendered
+
+\def\whateverleftframe#1%
+ {\setinstalledframedimensions
+ \setbox\b_framed_rendered\vbox to \overlayheight{\vss#1\vss}%
+ \setbox\b_framed_rendered\hbox to \zeropoint{\box\b_framed_rendered\hss}%
+ \ht\b_framed_rendered\zeropoint
+ \dp\b_framed_rendered\zeropoint
+ \box\b_framed_rendered}
+
+\def\whateverrightframe#1%
+ {\setinstalledframedimensions
+ \setbox\b_framed_rendered\vbox to \overlayheight{\vss#1\vss}%
+ \setbox\b_framed_rendered\hbox to \zeropoint{\hss\box\b_framed_rendered}%
+ \ht\b_framed_rendered\zeropoint
+ \dp\b_framed_rendered\zeropoint
+ \box\b_framed_rendered}
+
+\def\whatevertopframe#1%
+ {\setinstalledframedimensions
+ \setbox\b_framed_rendered\hbox to \overlaywidth{\hss#1\hss}%
+ \setbox\b_framed_rendered\vbox to \zeropoint{\box\b_framed_rendered\vss}%
+ \ht\b_framed_rendered\zeropoint
+ \dp\b_framed_rendered\zeropoint
+ \box\b_framed_rendered
+ \nointerlineskip}
+
+\def\whateverbottomframe#1%
+ {\setinstalledframedimensions
+ \setbox\b_framed_rendered\hbox to \overlaywidth{\hss#1\hss}%
+ \setbox\b_framed_rendered\vbox to \zeropoint{\vss\box\b_framed_rendered}%
+ \ht\b_framed_rendered\zeropoint
+ \dp\b_framed_rendered\zeropoint
+ \box\b_framed_rendered}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/pack-lyr.mkii b/Master/texmf-dist/tex/context/base/pack-lyr.mkii
index 85549bccbdb..1b0c0fd63f2 100644
--- a/Master/texmf-dist/tex/context/base/pack-lyr.mkii
+++ b/Master/texmf-dist/tex/context/base/pack-lyr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Layers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/pack-lyr.mkiv b/Master/texmf-dist/tex/context/base/pack-lyr.mkiv
index 5242b56de21..5b23a255d42 100644
--- a/Master/texmf-dist/tex/context/base/pack-lyr.mkiv
+++ b/Master/texmf-dist/tex/context/base/pack-lyr.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Layers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -23,92 +23,174 @@
% displacement. Should be an option, on by default
% (compatibility).
-% positie=forceer == ja maar dan ook in status=herhaal
-
%D The layering mechanism implemented here is independent of
%D the output routine, but future extensions may depend on a
%D more close cooperation.
-%D First we overload a macro from \type {core-rul}. From now on
+%D First we overload a macro from \type {pack-rul}. From now on
%D we accept a (optional) argument: the specific layer it
%D will go in. This means that we can move an overlay from one
%D background to the other using the dimensions of the parent.
-\ifx\undefined\defineoverlay \message{loaded to early} \wait \fi
+\ifdefined\defineoverlay \else \message{loaded to early} \wait \fi
\unexpanded\def\defineoverlay
- {\dotripleempty\dodefineoverlay}
+ {\dotripleempty\pack_framed_define_overlay}
-\def\dodefineoverlay[#1][#2][#3]% overlay [layer] content
+\def\pack_framed_define_overlay[#1][#2][#3]% overlay [layer] content
{\ifthirdargument
%\writestatus{BEWARE}{This (overlay definition) has changed!}% temp
- \def\docommand##1{\setvalue{\??ov##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}
+ \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\setlayer[#2]{\executedefinedoverlay{##1}{#3}}}}%
\else
- \def\docommand##1{\setvalue{\??ov##1}{\executedefinedoverlay{##1}{#2}}}%
+ \def\pack_framed_define_overlay_indeed##1{\setvalue{\??overlay##1}{\executedefinedoverlay{##1}{#2}}}%
\fi
- \processcommalist[#1]\docommand}
-
-%D When tracing is turned on, a couple of boxes will
-%D show up as well as the reference point.
-
-\newif\iftracelayers % \tracelayerstrue
+ \processcommalist[#1]\pack_framed_define_overlay_indeed}
-%D This handy constant saved some string memory.
+%D We use the command handler code. The previous, more direct parameter
+%D handling was 25\% faster when no parameters were passed when adding
+%D content to a layer. However, when we pass for instance a preset, the
+%D new methos is some 10\% faster and it happens that in most cases we
+%D do pass some parameters. It would be interesting to see if we can push
+%D the preset in between the regular chain but it could also lead to
+%D unwanted side effects when nesting layer placement.
-\def\@@layerbox{@@layerbox}
+\installcorenamespace{layer}
+\installcorenamespace{layerbox}
+\installcorenamespace{layerpreset}
+\installcorenamespace{layerposition} % brr, unreadable
%D \macros
-%D {definelayer}
+%D {definelayer,setuplayer}
%D
%D Each layer gets its own (global) box. This also means that
%D the data that goes into a layer, is typeset immediately.
%D Each layer automatically gets an associated overlay,
%D which can be used in any background assignment.
+%D
+%D After a layer is defined, you can change its
+%D characteristics.
-% todo : links/rechts
-
-\unexpanded\def\definelayer
- {\dodoubleargument\dodefinelayer}
-
-\def\dodefinelayer[#1][#2]% \zeropoint ipv \!!zeropoint
- {\setuplayer
- [#1]
- [\c!doublesided=,\c!preset=,
- \c!state=\v!start,\c!direction=\v!normal,\c!option=,
- \c!x=\zeropoint,\c!y=\zeropoint,\c!position=\v!no,
- \c!line=0,\c!column=0,
- \c!width=\nextboxwd,\c!height=\nextboxht,
- \c!offset=\zeropoint,\c!rotation=, % geen 0 !
- \c!hoffset=\zeropoint,\c!voffset=\zeropoint,
- \c!dx=\zeropoint,\c!dy=\zeropoint,
- \c!location=rb,\c!position=\v!no,\c!page=,
- \c!method=\v!overlay,
- \c!sx=1,\c!sy=1,\c!corner=,#2]%
- \doifvalue{\??ll#1\c!doublesided}\v!yes
- {\dopresetlayerbox{\v!left #1}%
- \dopresetlayerbox{\v!right#1}}%
- \dopresetlayerbox{#1}%
- \defineoverlay[#1][\composedlayer{#1}]}
-
-\def\dopresetlayerbox#1%
- {\ifcsname\@@layerbox#1\endcsname
+\installcommandhandler \??layer {layer} \??layer
+
+\setuplayer
+ [\c!state=\v!start,
+ %\c!doublesided=,
+ %\c!preset=,
+ %\c!option=,
+ %\c!corner=,
+ %\c!page=,
+ %\c!rotation=, % geen 0 !
+ \c!direction=\v!normal,
+ \c!position=\v!no,
+ \c!method=\v!overlay,
+ \c!x=\zeropoint,
+ \c!y=\zeropoint,
+ \c!line=0,
+ \c!column=0,
+ \c!width=\wd\nextbox, % don't change this globally
+ \c!height=\ht\nextbox, % don't change this globally
+ \c!offset=\zeropoint,
+ \c!hoffset=\zeropoint,
+ \c!voffset=\zeropoint,
+ \c!dx=\zeropoint,
+ \c!dy=\zeropoint,
+ \c!location=rb,
+ \c!sx=1,
+ \c!sy=1,
+ \c!region=\layeranchor]
+
+\def\layeranchor{\currentlayer:\the\realpageno}
+
+\unexpanded\def\anch_mark_anchor_box#1%
+ {\ctxcommand{markregionbox(\number#1,"\layeranchor")}} % needs an hbox
+
+\let\p_pack_layers_doublesided\empty
+\let\p_pack_layers_state \empty
+\let\p_pack_layers_option \empty
+\let\p_pack_layers_method \empty
+\let\p_pack_layers_preset \empty
+\let\p_pack_layers_rotation \empty
+\let\p_pack_layers_position \empty
+\let\p_pack_layers_hoffset \empty
+\let\p_pack_layers_voffset \empty
+\let\p_pack_layers_offset \empty
+\let\p_pack_layers_dx \empty
+\let\p_pack_layers_dy \empty
+\let\p_pack_layers_sx \empty
+\let\p_pack_layers_sy \empty
+\let\p_pack_layers_x \empty
+\let\p_pack_layers_y \empty
+\let\p_pack_layers_corner \empty
+\let\p_pack_layers_location \empty
+\let\p_pack_layers_line \empty
+\let\p_pack_layers_column \empty
+\let\p_pack_layers_width \empty
+\let\p_pack_layers_height \empty
+\let\p_pack_layers_direction \empty
+\let\p_pack_layers_region \empty
+
+\let\m_pack_layers_page \empty
+\let\m_pack_layers_target \empty
+\let\m_pack_layers_region \empty
+\let\m_pack_layers_anchor \empty
+
+\newconditional\c_pack_layers_repeated
+\newconditional\c_pack_layers_trace
+\newcount \c_pack_layers_current_data
+
+\newbox\b_layers
+
+\newdimen\d_pack_layers_x_size
+\newdimen\d_pack_layers_y_size
+\newdimen\d_pack_layers_x_offset
+\newdimen\d_pack_layers_y_offset
+\newdimen\d_pack_layers_x_position
+\newdimen\d_pack_layers_y_position
+
+\newdimen\layerwidth
+\newdimen\layerheight
+
+\let\lastlayerxpos\!!zeropoint
+\let\lastlayerypos\!!zeropoint
+\let\lastlayerwd \!!zeropoint
+\let\lastlayerht \!!zeropoint
+\let\lastlayerdp \!!zeropoint
+
+\appendtoks
+ \edef\p_pack_layers_doublesided{\layerparameter\c!doublesided}%
+ \ifx\p_pack_layers_doublesided\v!yes
+ \relateparameterhandlers{layer}{\v!left \currentlayer}{layer}\currentlayer % permits left*
+ \relateparameterhandlers{layer}{\v!right\currentlayer}{layer}\currentlayer % permits right*
+ \pack_layers_preset_box{\v!left \currentlayer}%
+ \pack_layers_preset_box{\v!right\currentlayer}%
+ \fi
+ \pack_layers_preset_box\currentlayer
+ \normalexpanded{\defineoverlay[\currentlayer][\noexpand\composedlayer{\currentlayer}]}%
+\to \everydefinelayer
+
+\def\pack_layers_preset_box#1%
+ {\ifcsname\??layerbox#1\endcsname
\resetlayer[#1]%
\else
- \expandafter\newbox\csname\@@layerbox#1\endcsname
+ \expandafter\newbox\csname\??layerbox#1\endcsname
\fi}
%D \macros
-%D {setuplayer}
+%D {resetlayer}
%D
-%D After a layer is defined, you can change its
-%D characteristics.
+%D This macro hardly needs an explanation (but is seldom
+%D needed anyway).
-\unexpanded\def\setuplayer
- {\dodoubleargument\dosetuplayer}
+\def\pack_layers_reset_box#1%
+ {\ifcsname\??layerbox#1\endcsname
+ \global\setbox\csname\??layerbox#1\endcsname\emptybox
+ \fi}
-\def\dosetuplayer[#1][#2]%
- {\def\docommand##1{\getparameters[\??ll##1][#2]}%
- \processcommalist[#1]\docommand}
+\def\resetlayer[#1]%
+ {\pack_layers_reset_box{#1}%
+ \pack_layers_reset_box{\v!left #1}%
+ \pack_layers_reset_box{\v!right#1}%
+ \pack_layers_reset_box{#1:\the\realpageno}}
%D \macros
%D {setlayer}
@@ -122,178 +204,199 @@
%D \setlayer [identifier] [optional parameters] {data}
%D \stoptyping
-\newcount\currentlayerdata
-
-\let\currentlayerwidth \!!zeropoint
-\let\currentlayerheight\!!zeropoint
-
\def\setcurrentlayerdimensions
- {\dodoubleempty\dosetcurrentlayerdimensions}
+ {\dodoubleempty\pack_layers_set_current_dimensions}
-\def\dosetcurrentlayerdimensions[#1][#2]% name left|right
+\def\pack_layers_set_current_dimensions[#1][#2]% name left|right
{\edef\currentlayerwidth {\thelayerwidth {#2#1}}%
\edef\currentlayerheight{\thelayerheight{#2#1}}}
-\def\thelayerwidth #1{\the\wd\executeifdefined{\@@layerbox#1}\emptybox}
-\def\thelayerheight#1{\the\ht\executeifdefined{\@@layerbox#1}\emptybox}
+% \def\thelayerwidth #1{\the\wd\executeifdefined{\??layerbox#1}\emptybox}
+% \def\thelayerheight#1{\the\ht\executeifdefined{\??layerbox#1}\emptybox}
-\def\setlayer
- {\dotripleempty\dosetlayer}
+\def\thelayerwidth #1{\the\ifcsname\??layerbox#1\endcsname\wd\csname\??layerbox#1\endcsname\else\zeropoint\fi}
+\def\thelayerheight#1{\the\ifcsname\??layerbox#1\endcsname\ht\csname\??layerbox#1\endcsname\else\zeropoint\fi}
-\def\dosetlayer[#1][#2][#3]% #4 == box do \fi is ok
- {\doifelsevalue{\??ll#1\c!state}\v!stop
- {\dowithnextbox\donothing\hbox}
- {\ifthirdargument
- \dodosetlayer[#1][#2][#3]%
- \else
- \doifassignmentelse{#2}
- {\dodosetlayer[#1][][#2]}%
- {\dodosetlayer[#1][#2][]}%
- \fi}}
+\unexpanded\def\setlayer
+ {\dotripleempty\pack_layers_set}
-\def\dodosetlayer[#1][#2][#3]% #2 = links/rechts
+\def\pack_layers_set[#1][#2][#3]% #4 == box do \fi is ok
{\bgroup
- \recalculatebackgrounds % brrr
- \global\advance\currentlayerdata\plusone
+ \edef\currentlayer{#1}%
+ \edef\p_pack_layers_state{\layerparameter{#1}\c!state}%
+ \ifx\p_pack_layers_state\v!stop
+ \dowithnextboxcs\egroup\hbox
+ \else\ifthirdargument
+ \pack_layers_set_indeed[#1][#2][#3]%
+ \else
+ \doifassignmentelse{#2}
+ {\pack_layers_set_indeed[#1][][#2]}%
+ {\pack_layers_set_indeed[#1][#2][]}%
+ \fi\fi}
+
+\def\pack_layers_set_indeed[#1][#2][#3]% #2 = links/rechts
+ {\page_backgrounds_recalculate % brrr
+ \global\advance\c_pack_layers_current_data\plusone
\forgetall
\dontcomplain
- \doifvalue{\??ll#1\c!option}\v!test\tracelayerstrue
- \iftracelayers\traceboxplacementtrue\fi
- \dowithnextbox{\dodosetlayerindeed{#1}{#2}{#3}\egroup}\hbox}
-
-\def\dodosetlayerindeed#1#2#3% #2 = links/rechts
- {\ifcsname\@@layerbox#1\endcsname % nb: odd/even discard, left/right not
- \edef\@@layerloc{#2}%
- \ifx\@@layerloc\v!even
+ \edef\p_pack_layers_option{\layerparameter\c!option}%
+ \ifx\p_pack_layers_option\v!test
+ \settrue\c_pack_layers_trace
+ \traceboxplacementtrue
+ \fi
+ \edef\m_pack_layers_target{#2}%
+ \dowithnextbox{\pack_layers_set_finish{#3}}\hbox}
+
+\def\pack_layers_set_finish#1%
+ {\ifcsname\??layerbox\currentlayer\endcsname % can move up
+ \ifx\m_pack_layers_target\v!even
\ifodd\realpageno
- % discard nextbox
+ % discard nextbox
\else
- \dododosetlayer[#1][\v!left][#3]%
+ \let\m_pack_layers_target\v!left
+ \pack_layers_set_content{#1}%
\fi
- \else\ifx\@@layerloc\v!odd
+ \else\ifx\m_pack_layers_target\v!odd
\ifodd\realpageno
- \dododosetlayer[#1][\v!right][#3]%
- %\else
- % discard nextbox
+ \let\m_pack_layers_target\v!right
+ \pack_layers_set_content{#1}%
+ \else
+ % discard nextbox
\fi
\else
- \dododosetlayer[#1][#2][#3]%
+ \pack_layers_set_content{#1}%
\fi\fi
\else
- \writestatus{layer}{unknown layer #1}%
- \fi}
-
-\newbox\layerbox
-
-\newdimen\@@layerxsiz
-\newdimen\@@layerysiz
-\newdimen\@@layerxoff
-\newdimen\@@layeryoff
-\newdimen\@@layerxpos
-\newdimen\@@layerypos
-
-\let\lastlayerxpos\!!zeropoint
-\let\lastlayerypos\!!zeropoint
-\let\lastlayerwd \!!zeropoint
-\let\lastlayerht \!!zeropoint
-\let\lastlayerdp \!!zeropoint
+ \writestatus{layer}{unknown layer \currentlayer}%
+ \fi
+ \egroup}
% todo left/right
-\def\setlastlayerpos#1%
- {\edef\layerpage{\MPp{lyr:\the\currentlayerdata}}%
- \xdef\lastlayerxpos{\the\dimexpr-\MPx{lyr:#1:\layerpage}+\MPx{lyr:\the\currentlayerdata}\relax}%
- \xdef\lastlayerypos{\the\dimexpr \MPy{lyr:#1:\layerpage}-\MPy{lyr:\the\currentlayerdata}\relax}}
+% todo: get position data in one go
+
+% \def\pack_layers_set_last_position_yes
+% {\edef\m_pack_layers_page{\MPp{\??layerposition\the\c_pack_layers_current_data}}%
+% \xdef\lastlayerxpos{\the\dimexpr-\MPx{\??layerposition\m_pack_layers_target\currentlayer:\m_pack_layers_page}+\MPx{\??layerposition\the\c_pack_layers_current_data}\relax}%
+% \xdef\lastlayerypos{\the\dimexpr \MPy{\??layerposition\m_pack_layers_target\currentlayer:\m_pack_layers_page}-\MPy{\??layerposition\the\c_pack_layers_current_data}\relax}%}
+% \d_pack_layers_x_position\lastlayerxpos
+% \d_pack_layers_y_position\lastlayerypos
+% \begingroup
+% \edef\currentlayer{\currentlayer\m_pack_layers_page}%
+% \global\letlayerparameter\c!position\v!yes
+% \endgroup
+% \global\letlayerparameter\c!state\v!start % needed ?
+% \setbox\b_layers\vbox to \d_pack_layers_y_size{\hbox to \d_pack_layers_x_size{\xypos{\??layerposition\the\c_pack_layers_current_data}\hss}\vss}}
+
+\def\pack_layers_set_last_position_yes % target: left|right
+ {% this will become one call
+ \edef\m_pack_layers_anchor{\??layerposition\the\c_pack_layers_current_data}%
+ \edef\m_pack_layers_page {\MPp\m_pack_layers_anchor}%
+ \edef\m_pack_layers_region{\MPr\m_pack_layers_anchor}%
+ \d_pack_layers_x_position \dimexpr-\MPx\m_pack_layers_region+\MPx\m_pack_layers_anchor\relax
+ \d_pack_layers_y_position \dimexpr \MPy\m_pack_layers_region-\MPy\m_pack_layers_anchor+\MPh\m_pack_layers_region\relax
+ \xdef\lastlayerxpos{\the\d_pack_layers_x_position}%
+ \xdef\lastlayerypos{\the\d_pack_layers_y_position}%
+ % \writestatus{region}{\m_pack_layers_region -> (\MPx\m_pack_layers_region,\MPy\m_pack_layers_region)}%
+ % \writestatus{self} {\m_pack_layers_anchor -> (\MPx\m_pack_layers_anchor,\MPy\m_pack_layers_anchor)}%
+ % \writestatus{delta} {(\lastlayerxpos,\lastlayerypos)}%
+ % \begingroup
+ % \edef\currentlayer{\currentlayer\m_pack_layers_page}%
+ % \global\letlayerparameter\c!position\v!yes
+ % \endgroup
+ \global\letlayerparameter\c!state\v!start % needed ?
+ \setbox\b_layers\vbox to \d_pack_layers_y_size
+ {\hbox to \d_pack_layers_x_size
+ {\xypos\m_pack_layers_anchor\hss}%
+ \vss}}
+
+\def\pack_layers_set_last_position_nop
+ {\setbox\b_layers\emptybox
+ \globallet\lastlayerxpos\!!zeropoint
+ \globallet\lastlayerypos\!!zeropoint
+ \doifinset\v!bottom\p_pack_layers_corner\pack_layers_set_bottom_positions
+ \doifinset\v!right \p_pack_layers_corner\pack_layers_set_right_positions
+ \doifinset\v!middle\p_pack_layers_corner\pack_layers_set_middle_positions
+ \edef\m_pack_layers_page{\layerparameter\c!page}}
\unexpanded\def\definelayerpreset
- {\dodoubleargument\dodefinelayerpreset}
-
-% \def\dodefinelayerpreset[#1][#2]%
-% {\setvalue{\??ll\??ll#1}{\dopresetlayer{#2}}}
-%
-% more fun: \definelayerpreset[whatever][lefttop]
+ {\dodoubleargument\pack_layers_define_preset}
-\def\dodefinelayerpreset[#1][#2]%
+\def\pack_layers_define_preset[#1][#2]%
{\doifassignmentelse{#2}
- {\setvalue{\??ll\??ll#1}{\dopresetlayer{#2}}}
- {\setvalue{\??ll\??ll#1}{\csname\??ll\??ll#2\endcsname}}}
-
-\def\dopresetlayer#1#2#3% #1=list #2=tag #3=list
- {\getparameters[\??ll#2][#1,#3]}
-
-\letempty\currentlayer
-
-\def\layerparameter#1{\csname\??ll\currentlayer#1\endcsname}
-
-\newdimen\layerwidth
-\newdimen\layerheight
-
-\def\dododosetlayer[#1][#2][#3]% will be sped up
- {% we use the global width, never change this
- \def\currentlayer{#1}%
- \@@layerxsiz\layerparameter\c!width
- \@@layerysiz\layerparameter\c!height
- \layerwidth \@@layerxsiz
- \layerheight\@@layerysiz
- % preroll
- \getparameters[\??ll\currentlayer][#3]%
+ {\setvalue{\??layerpreset#1}{\setupcurrentlayer[#2]}}
+ {\setvalue{\??layerpreset#1}{\csname\??layerpreset#2\endcsname}}}
+
+\def\pack_layers_set_content#1%
+ {\layerwidth \layerparameter\c!width % global (local later)
+ \layerheight\layerparameter\c!height % global (local later)
+ \d_pack_layers_x_size\layerwidth
+ \d_pack_layers_y_size\layerheight
%
- % \executeifdefined{\??ll\??ll\layerparameter\c!preset}\gobbletwoarguments\currentlayer{#3}%
+ \setupcurrentlayer[#1]% preroll
%
- \edef\@@currentlayerpreset{\layerparameter\c!preset}%
- \ifcsname\??ll\??ll\@@currentlayerpreset\endcsname\csname\??ll\??ll\@@currentlayerpreset\endcsname\currentlayer{#3}\fi
+ \edef\p_pack_layers_preset {\layerparameter\c!preset }%
%
- \doif{\layerparameter\c!position}\v!overlay % slow, use \dosetvalue instead
- {\getparameters[\??ll\currentlayer][\c!width=\zeropoint,\c!height=\zeropoint,\c!position=\v!yes]}%
- \doifsomething{\layerparameter\c!rotation}% todo: use direct lowlevel call
- {\setbox\nextbox\hbox{\rotate[\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]{\flushnextbox}}}%
- % no, not local
- % \@@layerxsiz\layerparameter\c!width
- % \@@layerysiz\layerparameter\c!height
- % never change that
- \@@layerxpos\layerparameter\c!x
- \@@layerypos\layerparameter\c!y
- \doifelse{\layerparameter\c!hoffset}\v!max{\@@layerxoff\@@layerxsiz}{\@@layerxoff\layerparameter\c!hoffset}%
- \doifelse{\layerparameter\c!voffset}\v!max{\@@layeryoff\@@layerysiz}{\@@layeryoff\layerparameter\c!voffset}%
- % dx/dy are internal context ones and can be used in preset
- \advance\@@layerxoff\dimexpr\layerparameter\c!offset+\layerparameter\c!dx\relax
- \advance\@@layeryoff\dimexpr\layerparameter\c!offset+\layerparameter\c!dy\relax
- \@@layerxpos\layerparameter\c!sx\@@layerxpos
- \@@layerypos\layerparameter\c!sy\@@layerypos
- \@@layerxoff\layerparameter\c!sx\@@layerxoff
- \@@layeryoff\layerparameter\c!sy\@@layeryoff
- \edef\@@currentlayerposition{\layerparameter\c!position}%
- \ifx\@@currentlayerposition\v!yes % combine ^
- \setlastlayerpos{#2\currentlayer}% sets \layerpage; todo l/r %%%%%%%%%%%%
- \@@layerxpos\lastlayerxpos
- \@@layerypos\lastlayerypos
- \letgvalue{\??ll\currentlayer\layerpage\c!position}\v!yes
- \letgvalue{\??ll\currentlayer\c!state}\v!start % needed ?
- \setbox\layerbox\vbox to \@@layerysiz{\hbox to \@@layerxsiz{\xypos{lyr:\the\currentlayerdata}\hss}\vss}%
+ \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
+ \csname\??layerpreset\p_pack_layers_preset\endcsname
+ \setupcurrentlayer[#1]% postroll
+ \fi
+ %
+ \edef\p_pack_layers_rotation {\layerparameter\c!rotation }%
+ \edef\p_pack_layers_position {\layerparameter\c!position }%
+ \edef\p_pack_layers_hoffset {\layerparameter\c!hoffset }%
+ \edef\p_pack_layers_voffset {\layerparameter\c!voffset }%
+ \edef\p_pack_layers_offset {\layerparameter\c!offset }%
+ \edef\p_pack_layers_dx {\layerparameter\c!dx }%
+ \edef\p_pack_layers_dy {\layerparameter\c!dy }%
+ \edef\p_pack_layers_sx {\layerparameter\c!sx }%
+ \edef\p_pack_layers_sy {\layerparameter\c!sy }%
+ \edef\p_pack_layers_x {\layerparameter\c!x }%
+ \edef\p_pack_layers_y {\layerparameter\c!y }%
+ \edef\p_pack_layers_corner {\layerparameter\c!corner }%
+ \edef\p_pack_layers_location {\layerparameter\c!location }%
+ \edef\p_pack_layers_line {\layerparameter\c!line }%
+ \edef\p_pack_layers_column {\layerparameter\c!column }%
+ \edef\p_pack_layers_width {\layerparameter\c!width }% local ones
+ \edef\p_pack_layers_height {\layerparameter\c!height }% local ones
+ \edef\p_pack_layers_direction{\layerparameter\c!direction}%
+ %
+ \ifx\p_pack_layers_position\v!overlay
+ \let\p_pack_layers_width \zeropoint
+ \let\p_pack_layers_height \zeropoint
+ \let\p_pack_layers_position\v!yes
+ \fi
+ \ifx\p_pack_layers_rotation\empty \else
+ % use direct call
+ \setbox\nextbox\hbox{\rotate[\c!location=\v!high,\c!rotation=\layerparameter\c!rotation]{\box\nextbox}}%
+ \fi
+ \d_pack_layers_x_offset\p_pack_layers_sx\dimexpr
+ \ifx\p_pack_layers_hoffset\v!max\d_pack_layers_x_size\else\p_pack_layers_hoffset\fi+\p_pack_layers_offset+\p_pack_layers_dx
+ \relax
+ \d_pack_layers_y_offset\p_pack_layers_sy\dimexpr
+ \ifx\p_pack_layers_voffset\v!max\d_pack_layers_y_size\else\p_pack_layers_voffset\fi+\p_pack_layers_offset+\p_pack_layers_dy
+ \relax
+ \d_pack_layers_x_position\p_pack_layers_sx\dimexpr\p_pack_layers_x\relax
+ \d_pack_layers_y_position\p_pack_layers_sy\dimexpr\p_pack_layers_y\relax
+ \ifx\p_pack_layers_position\v!yes
+ \pack_layers_set_last_position_yes
\else
- \setbox\layerbox\emptybox
- \globallet\lastlayerxpos\!!zeropoint
- \globallet\lastlayerypos\!!zeropoint
- \normalexpanded{\noexpand\doifinset{\v!bottom}{\layerparameter\c!corner}}\dosetlayerbottompositions
- \normalexpanded{\noexpand\doifinset{\v!right }{\layerparameter\c!corner}}\dosetlayerrightpositions
- \normalexpanded{\noexpand\doifinset{\v!middle}{\layerparameter\c!corner}}\dosetlayermiddlepositions
- \edef\layerpage{\layerparameter\c!page}%
+ \pack_layers_set_last_position_nop
\fi
- \ifx\layerpage\empty \else % is expanded
- \edef\layerpage{:\layerpage}%
- \ifcsname\@@layerbox#2\currentlayer\layerpage\endcsname \else
- \expandafter\newbox\csname\@@layerbox#2\currentlayer\layerpage\endcsname
+ %
+ \ifx\m_pack_layers_page\empty \else % is expanded
+ \edef\m_pack_layers_page{:\m_pack_layers_page}%
+ \ifcsname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname \else
+ \expandafter\newbox\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname
\fi
\fi
- \chardef\layerpagebox\csname\@@layerbox#2\currentlayer\layerpage\endcsname
+ \chardef\layerpagebox\csname\??layerbox\m_pack_layers_target\currentlayer\m_pack_layers_page\endcsname
\ifvoid\layerpagebox
\gsetboxllx\layerpagebox\zeropoint
\gsetboxlly\layerpagebox\zeropoint
\fi
\global\setbox\layerpagebox\vbox %to \layerparameter\c!height % new, otherwise no negative y possible
{\offinterlineskip
- %postpone, to after nextboxwd correction % \hsize\layerparameter\c!width % new, keep box small
- %\ifvoid\csname\@@layerbox\currentlayer\layerpage\endcsname\else % why not #2#1
\ifvoid\layerpagebox
\let\lastlayerwidth \zeropoint
\let\lastlayerheight\zeropoint
@@ -303,87 +406,89 @@
\ht\layerpagebox\zeropoint
\dp\layerpagebox\zeropoint
\wd\layerpagebox\zeropoint
- \doifnot{\layerparameter\c!direction}\v!reverse{\box\layerpagebox}%
+ \ifx\p_pack_layers_direction\v!reverse\else
+ \box\layerpagebox
+ \fi
\fi
% don't move
- \xdef\lastlayerwd{\the\nextboxwd}%
- \xdef\lastlayerht{\the\nextboxht}% % not entirely ok when grid !
- \xdef\lastlayerdp{\the\nextboxdp}% % not entirely ok when grid !
+ \xdef\lastlayerwd{\the\wd\nextbox}%
+ \xdef\lastlayerht{\the\ht\nextbox}% % not entirely ok when grid !
+ \xdef\lastlayerdp{\the\dp\nextbox}% % not entirely ok when grid !
% this code
- \doifelse{\layerparameter\c!location}\v!grid\donetrue\donefalse
- \ifdone
- \nextboxht\strutheight
- \nextboxdp\strutdepth
+ \ifx\p_pack_layers_location\v!grid
+ \ht\nextbox\strutheight
+ \dp\nextbox\strutdepth
\else
- \setbox\nextbox\hbox{\alignedbox[\layerparameter\c!location]\vbox{\flushnextbox}}%
+ \setbox\nextbox\hbox{\alignedbox[\p_pack_layers_location]\vbox{\box\nextbox}}%
\fi
- \ifnum\layerparameter\c!line=\zerocount\else % no \ifcase, can be negative
- \advance\@@layerypos\dimexpr\layerparameter\c!line\lineheight+\topskip-\lineheight-\nextboxht\relax
+ \ifnum\p_pack_layers_line=\zerocount\else % no \ifcase, can be negative
+ \advance\d_pack_layers_y_position\dimexpr\p_pack_layers_line\lineheight+\topskip-\lineheight-\ht\nextbox\relax
\fi
- \ifnum\layerparameter\c!column=\zerocount\else % no \ifcase, can be negative
- \advance\@@layerxpos\layoutcolumnoffset{\layerparameter\c!column}%
+ \ifnum\p_pack_layers_column=\zerocount\else % no \ifcase, can be negative
+ \advance\d_pack_layers_x_position\layoutcolumnoffset\p_pack_layers_column\relax
\fi
- \ifdone
- \setbox\nextbox\hbox{\alignedbox[rb]\vbox{\flushnextbox}}%
+ \ifx\p_pack_layers_location\v!grid
+ \setbox\nextbox\hbox{\alignedbox[rb]\vbox{\box\nextbox}}%
\fi
% ll registration
- \scratchdimen\@@layerxpos
- \advance\scratchdimen\@@layerxoff
+ \scratchdimen\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
\ifdim\scratchdimen<\getboxllx\layerpagebox
\gsetboxllx\layerpagebox\scratchdimen
\fi
- \advance\scratchdimen\nextboxwd
- \nextboxwd\ifdim\scratchdimen>\lastlayerwidth \scratchdimen \else \lastlayerwidth \fi
- \scratchdimen\dimexpr\@@layerypos+\@@layeryoff\relax
+ \advance\scratchdimen\wd\nextbox
+ \wd\nextbox\ifdim\scratchdimen>\lastlayerwidth \scratchdimen \else \lastlayerwidth \fi
+ \scratchdimen\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
\ifdim\scratchdimen<\getboxlly\layerpagebox
\gsetboxlly\layerpagebox\scratchdimen
\fi
% ll compensation
- \advance\scratchdimen\dimexpr\nextboxht+\nextboxdp\relax
- \nextboxht\ifdim\scratchdimen>\lastlayerheight \scratchdimen \else \lastlayerheight \fi
- \nextboxdp\zeropoint
+ \advance\scratchdimen\dimexpr\ht\nextbox+\dp\nextbox\relax
+ \ht\nextbox\ifdim\scratchdimen>\lastlayerheight \scratchdimen \else \lastlayerheight \fi
+ \dp\nextbox\zeropoint
% placement
- \hsize\layerparameter\c!width % new, keep box small
- \vbox to \layerparameter\c!height \bgroup
+ \hsize\p_pack_layers_width
+ \vbox to \p_pack_layers_height \bgroup
\smashbox\nextbox
- \vskip\dimexpr\@@layerypos+\@@layeryoff\relax
- \hskip\dimexpr\@@layerxpos+\@@layerxoff\relax
- \flushnextbox
+ \vskip\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
+ \hskip\dimexpr\d_pack_layers_x_position+\d_pack_layers_x_offset\relax
+ \box\nextbox
\ifvoid\layerpagebox
% already flushed
\else
% the reverse case % check !
- \vskip-\dimexpr\@@layerypos+\@@layeryoff\relax
+ \vskip-\dimexpr\d_pack_layers_y_position+\d_pack_layers_y_offset\relax
\box\layerpagebox
\fi
\egroup}%
% when position is true, the layerbox holds the compensation and needs
% to be placed; never change this !
- \ifvoid\layerbox\else\box\layerbox\fi}
+ \ifvoid\b_layers \else
+ \box\b_layers
+ \fi}
-\def\dosetlayerbottompositions
- {\ifnum\layerparameter\c!line=\zerocount\else % can be < 0
- \setevalue{\??ll\currentlayer\c!line}{\the\numexpr-\layerparameter\c!line+\layoutlines+\plusone\relax}%
+\def\pack_layers_set_bottom_positions
+ {\ifnum\p_pack_layers_line=\zerocount\else % can be < 0
+ \edef\p_pack_layers_line{\the\numexpr-\p_pack_layers_line+\layoutlines+\plusone\relax}% use counter instead ?
\fi
- \ifdim\@@layerysiz>\zeropoint
- \advance\@@layerypos-\@@layerysiz
- \@@layerypos-\@@layerypos
- \@@layeryoff-\@@layeryoff
+ \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
+ \d_pack_layers_y_offset-\d_pack_layers_y_offset
\fi}
-\def\dosetlayerrightpositions
- {\ifnum\layerparameter\c!column=\zerocount\else % can be < 0
- \setevalue{\??ll\currentlayer\c!column}{\the\numexpr-\layerparameter\c!column+\layoutcolumns+\plusone\relax}%
+\def\pack_layers_set_right_positions
+ {\ifnum\p_pack_layers_column=\zerocount\else % can be < 0
+ \edef\p_pack_layers_column{\the\numexpr-\layerparameter\c!column+\layoutcolumns+\plusone\relax}% use counter instead ?
\fi
- \ifdim\@@layerxsiz>\zeropoint
- \advance\@@layerxpos-\@@layerxsiz
- \@@layerxpos-\@@layerxpos
- \@@layerxoff-\@@layerxoff
+ \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
+ \d_pack_layers_x_offset-\d_pack_layers_x_offset
\fi}
-\def\dosetlayermiddlepositions
- {\ifdim\@@layerxsiz>\zeropoint \advance\@@layerxpos.5\@@layerxsiz \fi
- \ifdim\@@layerysiz>\zeropoint \advance\@@layerypos.5\@@layerysiz \fi}
+\def\pack_layers_set_middle_positions
+ {\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}
%D Given the task to be accomplished, the previous macro is
%D not even that complicated. It mainly comes down to skipping
@@ -395,14 +500,14 @@
%D {doifelselayerdata}
\def\doifelselayerdata#1%
- {\ifcsname\@@layerbox#1\endcsname
- \ifvoid\csname\@@layerbox#1\endcsname
- \@EAEAEA\secondoftwoarguments
+ {\ifcsname\??layerbox#1\endcsname
+ \ifvoid\csname\??layerbox#1\endcsname
+ \doubleexpandafter\secondoftwoarguments
\else
- \@EAEAEA\firstoftwoarguments
+ \doubleexpandafter\firstoftwoarguments
\fi
\else
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
%D \macros
@@ -415,114 +520,195 @@
% todo: setups before flush, handy hook
-\unexpanded\def\flushlayer[#1]% quite core, so optimized
+\unexpanded\def\flushlayer[#1]% quite core, so optimized (todo: check for void)
{\begingroup
\forgetall
\edef\currentlayer{#1}%
- \edef\@@currentlayerstate{\csname\??ll\currentlayer\c!state\endcsname}%
- \ifx\@@currentlayerstate\v!stop
+ \edef\p_pack_layers_state{\layerparameter\c!state}%
+ \ifx\p_pack_layers_state\v!stop
% nothing
- \else\ifx\@@currentlayerstate\v!next
- \global\expandafter\let\csname\??ll\currentlayer\c!state\endcsname\v!start % dangerous, stack-built-up
- \else\ifx\@@currentlayerstate\v!continue
- \global\expandafter\let\csname\??ll\currentlayer\c!state\endcsname\v!repeat % dangerous, stack-built-up
+ \else\ifx\p_pack_layers_state\v!next
+ \global\letlayerparameter\c!state\v!start % dangerous, stack-built-up
+ \else\ifx\p_pack_layers_state\v!continue
+ \global\letlayerparameter\c!state\v!repeat % dangerous, stack-built-up
\else
- \edef\@@currentlayerdoublesided{\csname\??ll\currentlayer\c!doublesided\endcsname}%
- \ifx\@@currentlayerdoublesided\v!yes
- \ifcsname\@@layerbox#1\endcsname
+ \edef\p_pack_layers_doublesided{\layerparameter\c!doublesided}%
+ \ifx\p_pack_layers_doublesided\v!yes
+ \ifcsname\??layerbox#1\endcsname
% we can make a dedicated one for this
- \doifbothsidesoverruled{\dodoflushlayerB\v!left}{\dodoflushlayerB\v!right}{\dodoflushlayerB\v!left}%
+ \doifbothsidesoverruled
+ {\pack_layers_flush_double\v!left }%
+ {\pack_layers_flush_double\v!right}%
+ {\pack_layers_flush_double\v!left }%
\else
- \dodoflushlayerA
+ \pack_layers_flush_single
\fi
\else
- \dodoflushlayerA
+ \pack_layers_flush_single
\fi
\fi\fi\fi
\endgroup}
% \ifcase#1\else\writestatus{layer}{unknown layer #3}\fi
-\def\dodoflushlayerA
+\def\pack_layers_flush_single
{\startoverlay
- {\ifcsname\@@layerbox\currentlayer \endcsname\dodoflushlayer\plusone \currentlayer \fi}%
- {\ifcsname\@@layerbox\currentlayer:\realfolio\endcsname\dodoflushlayer\zerocount{\currentlayer:\realfolio}\fi}%
+ {\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\dodoflushlayerB#1%
+\def\pack_layers_flush_double#1%
{\startoverlay
- {\ifcsname\@@layerbox \currentlayer \endcsname\dodoflushlayer\plusone \currentlayer \fi}%
- {\ifcsname\@@layerbox \currentlayer:\realfolio\endcsname\dodoflushlayer\zerocount {\currentlayer:\realfolio}\fi}%
- {\ifcsname\@@layerbox#1\currentlayer \endcsname\dodoflushlayer\plusone {#1\currentlayer }\fi}%
- {\ifcsname\@@layerbox#1\currentlayer:\realfolio\endcsname\dodoflushlayer\zerocount{#1\currentlayer:\realfolio}\fi}%
+ {\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}
-\def\dodoflushlayer#1#2% quite core, so optimized
+% \def\pack_layers_flush_indeed#1#2% quite core, so optimized
+% {\begingroup % already grouped
+% \offinterlineskip
+% \edef\p_pack_layers_preset{\layerparameter\c!preset}%
+% \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
+% \csname\??layerpreset\p_pack_layers_preset\endcsname
+% \fi
+% \edef\p_pack_layers_method{\layerparameter\c!method}%
+% \edef\p_pack_layers_option{\layerparameter\c!option}%
+% \ifx\p_pack_layers_option\v!test
+% \settrue\c_pack_layers_trace
+% \traceboxplacementtrue
+% \fi
+% \ifcase#1\relax
+% \setfalse\c_pack_layers_repeated
+% \else
+% \edef\p_pack_layers_position{\layerparameter\c!position}%
+% \ifx\p_pack_layers_position\v!yes
+% \setfalse\c_pack_layers_repeated
+% \else
+% \edef\p_pack_layers_repeat{\layerparameter\c!repeat}%
+% \ifx\p_pack_layers_repeat\v!yes
+% \settrue\c_pack_layers_repeated
+% \else\ifx\p_pack_layers_state\v!repeat
+% \settrue\c_pack_layers_repeated
+% \else
+% \setfalse\c_pack_layers_repeated
+% \fi\fi
+% \fi
+% \fi
+% \chardef\b_layers\csname\??layerbox#2\endcsname % trick
+% % we need to copy in order to retain the negative offsets for a next
+% % stage of additions, i.e. llx/lly accumulate in repeat mode and the
+% % compensation may differ each flush depending on added content
+% \setbox\nextbox
+% \ifx\p_pack_layers_method\v!fit
+% \pack_layers_positioned_box_yes
+% \else
+% \pack_layers_positioned_box_nop
+% \fi
+% % todo: method=offset => overlayoffset right/down (handy for backgrounds with offset)
+% \doifoverlayelse{#2}%
+% {\setlayoutcomponentattribute{\v!layer:#2}}%
+% \resetlayoutcomponentattribute
+% \ifx\p_pack_layers_option\v!test \ruledvbox \else \vbox \fi \ifx\p_pack_layers_method\v!overlay to \overlayheight \fi \layoutcomponentboxattribute
+% {\hbox \ifx\p_pack_layers_method\v!overlay to \overlaywidth \fi
+% {\edef\currentlayer{#2\the\realpageno}% local
+% \edef\p_pack_layers_position{\layerparameter\c!position}% local
+% \ifx\p_pack_layers_position\v!yes
+% \xypos{\??layerposition#2:\the\realpageno}%
+% \fi
+% \box\nextbox
+% \hss}%
+% \vss}%
+% \ifconditional\c_pack_layers_repeated\else
+% \gsetboxllx\b_layers\zeropoint
+% \gsetboxlly\b_layers\zeropoint
+% \fi
+% \endgroup}
+
+\let\pack_layers_top_fill \relax
+\let\pack_layers_bottom_fill\vss
+
+\def\pack_layers_flush_indeed#1#2% quite core, so optimized
{\begingroup % already grouped
\offinterlineskip
- \edef\@@currentlayermethod{\csname\??ll\currentlayer\c!method\endcsname}%
- \edef\@@currentlayeroption{\csname\??ll\currentlayer\c!option\endcsname}%
- % needed because we need to handle method but we should find a way to
- % speed this up
- \edef\@@currentlayerpreset{\csname\??ll\currentlayer\c!preset\endcsname}%
- \ifcsname\??ll\??ll\@@currentlayerpreset\endcsname\csname\??ll\??ll\@@currentlayerpreset\endcsname\currentlayer{}\fi
- %
- \ifx\@@currentlayeroption\v!test
- \tracelayerstrue
+ \edef\p_pack_layers_preset{\layerparameter\c!preset}%
+ \ifcsname\??layerpreset\p_pack_layers_preset\endcsname
+ \csname\??layerpreset\p_pack_layers_preset\endcsname
\fi
- \iftracelayers
+ \edef\p_pack_layers_method{\layerparameter\c!method}%
+ \edef\p_pack_layers_option{\layerparameter\c!option}%
+ \ifx\p_pack_layers_option\v!test
+ \settrue\c_pack_layers_trace
\traceboxplacementtrue
\fi
- \!!doneafalse
- \!!donebfalse
- \ifx\@@currentlayermethod\v!overlay\!!doneatrue\fi
- \ifx\@@currentlayermethod\v!fit \!!donebtrue\fi
- \!!donectrue
- \ifcase#1\else
- \edef\@@currentlayerposition{\csname\??ll\currentlayer\c!position\endcsname}%
- \ifx\@@currentlayerposition\v!yes \else
- \edef\@@currentlayerrepeat{\csname\??ll\currentlayer\c!repeat\endcsname}%
- % \edef\@@currentlayerstate {\csname\??ll\currentlayer\c!state\endcsname}% actually this is already set
- \ifx\@@currentlayerrepeat\v!yes
- \!!donecfalse
- \else\ifx\@@currentlayerstate\v!repeat
- \!!donecfalse
+ \ifcase#1\relax
+ \setfalse\c_pack_layers_repeated
+ \else
+ \edef\p_pack_layers_position{\layerparameter\c!position}%
+ \ifx\p_pack_layers_position\v!yes
+ \setfalse\c_pack_layers_repeated
+ \else
+ \edef\p_pack_layers_repeat{\layerparameter\c!repeat}%
+ \ifx\p_pack_layers_repeat\v!yes
+ \settrue\c_pack_layers_repeated
+ \else\ifx\p_pack_layers_state\v!repeat
+ \settrue\c_pack_layers_repeated
+ \else
+ \setfalse\c_pack_layers_repeated
\fi\fi
\fi
\fi
- \chardef\layerbox\csname\@@layerbox#2\endcsname % \@@layerbox\currentlayer
+ \chardef\b_layers\csname\??layerbox#2\endcsname % trick
% we need to copy in order to retain the negative offsets for a next
% stage of additions, i.e. llx/lly accumulate in repeat mode and the
% compensation may differ each flush depending on added content
\setbox\nextbox
- \if!!doneb
- \therepositionededlayerbox
+ \ifx\p_pack_layers_method\v!fit
+ \pack_layers_positioned_box_yes
\else
- \if!!donec\box\else\copy\fi\layerbox % sorry for the delay due to copying
+ \pack_layers_positioned_box_nop
\fi
% todo: method=offset => overlayoffset right/down (handy for backgrounds with offset)
- \doifoverlayelse{#2}{\setlayoutcomponentattribute\v!layer{#2}}\resetlayoutcomponentattribute
- \iftracelayers \ruledvbox \else \vbox \fi \if!!donea to \overlayheight \fi \layoutcomponentboxattribute
- {\hbox \if!!donea to \overlaywidth \fi
- {\edef\@@currentlayerpageposition{\csname\??ll#2\realfolio\c!position\endcsname}%
- \ifx\@@currentlayerpageposition\v!yes\xypos{lyr:#2:\realfolio}\fi
- \box\nextbox
+ \doifoverlayelse{#2}%
+ {\setlayoutcomponentattribute{\v!layer:#2}}%
+ \resetlayoutcomponentattribute
+ % we have conflicting demands: some mechanisms want ll anchoring .. I need to figure this out
+ % an dmaybe we will have 'origin=bottom' or so
+ \setbox\nextbox
+ \ifx\p_pack_layers_option\v!test \ruledvbox \else \vbox \fi \ifx\p_pack_layers_method\v!overlay to \overlayheight \fi \layoutcomponentboxattribute
+ {\pack_layers_top_fill
+ \hbox \ifx\p_pack_layers_method\v!overlay to \overlaywidth \fi
+ {\box\nextbox
\hss}%
- \vss}%
- \if!!donec
- \gsetboxllx\layerbox\zeropoint
- \gsetboxlly\layerbox\zeropoint
+ \pack_layers_bottom_fill}%
+ %
+ % \edef\currentlayer{#2}% :\the\realpageno}% local .. check \anchor
+ % \edef\p_pack_layers_position{\layerparameter\c!position}% local
+ \ifx\p_pack_layers_position\v!yes
+ \edef\p_pack_layers_region{\layerparameter\c!region}%
+ \ifx\p_pack_layers_region\empty \else
+ \anch_mark_anchor_box\nextbox
+ \fi
+ \fi
+ \box\nextbox
+ %
+ \ifconditional\c_pack_layers_repeated\else
+ \gsetboxllx\b_layers\zeropoint
+ \gsetboxlly\b_layers\zeropoint
\fi
\endgroup}
-\def\therepositionededlayerbox % assumes that \if!!donec is set (todo: use dedicated flags)
+\def\pack_layers_positioned_box_yes
{\vbox
- {\vskip-\getboxlly\layerbox
- \hskip-\getboxllx\layerbox
- \hsize-\dimexpr\getboxllx\layerbox-\wd\layerbox\relax
- \if!!donec\box\else\copy\fi\layerbox}}
+ {\vskip-\getboxlly\b_layers
+ \hskip-\getboxllx\b_layers
+ \hsize-\dimexpr\getboxllx\b_layers-\wd\b_layers\relax
+ \ifconditional\c_pack_layers_repeated\copy\else\box\fi\b_layers}}
-% \definelayer[test][method=fit] \setupcolors[state=start] \tracelayerstrue
+\def\pack_layers_positioned_box_nop
+ {\ifconditional\c_pack_layers_repeated\copy\else\box\fi\b_layers}
+
+% \definelayer[test][method=fit] \setupcolors[state=start,option=test]
%
% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=10pt]{g}\flushlayer[test]}
% \framed[framecolor=red,offset=overlay]{\setlayer[test]{aa}\setlayer[test][x=-10pt]{bb}\flushlayer[test]}
@@ -536,11 +722,9 @@
%D when we use it as parameter. This name also suits better
%D to other layering commands.
-\def\composedlayer#1{\flushlayer[#1]}
-
-\let\placelayer\flushlayer
+\unexpanded\def\composedlayer#1{\flushlayer[#1]}
-\def\tightlayer[#1]%
+\unexpanded\def\tightlayer[#1]%
{\hbox
{\def\currentlayer{#1}% todo: left/right
\setbox\nextbox\emptybox % hoogte/breedte are \wd\nextbox/\ht\nextbox
@@ -548,23 +732,7 @@
\vsize\layerparameter\c!height % \overlaywheight = \vsize
\composedlayer{#1}}}
-%D \macros
-%D {resetlayer}
-%D
-%D This macro hardly needs an explanation (and is seldom
-%D needed as well).
-
-\def\doresetlayer#1%
- {\ifcsname\@@layerbox#1\endcsname
- \global\setbox\csname\@@layerbox#1\endcsname\emptybox
- \fi}
-
-\def\resetlayer[#1]%
- {\doresetlayer{#1}%
- \doifvalue{\??ll#1\c!doublesided}\v!yes % kind of redundant test
- {\doresetlayer{\v!left #1}%
- \doresetlayer{\v!right#1}}%
- \doresetlayer{#1:\realfolio}}
+\let\placelayer\flushlayer
%D \macros
%D {setMPlayer}
@@ -597,31 +765,28 @@
%D {\useMPgraphic{oeps}}
%D \stoptyping
-\def\setMPlayer
- {\dotripleempty\dosetMPlayer}
+\unexpanded\def\setMPlayer
+ {\dotripleempty\pack_layers_set_MP}
\def\MPlayerwidth {\hsize}
\def\MPlayerheight{\vsize}
-\def\dosetMPlayer[#1][#2][#3]%
+\def\pack_layers_set_MP[#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]}
-\def\getMPlayer
- {\dodoubleempty\dogetMPlayer}
+\unexpanded\def\getMPlayer
+ {\dodoubleempty\pack_layers_get_MP}
-\def\dogetMPlayer[#1][#2]%
- {\framed
- [\c!background={\v!foreground,#1},
- \c!frame=\v!off,
- \c!offset=\v!overlay,#2]}
+\def\pack_layers_get_MP[#1][#2]%
+ {\framed[\c!background={\v!foreground,#1},\c!frame=\v!off,\c!offset=\v!overlay,#2]} % takes argument
%D Watch out, a redefinition:
-\ifx\settextpagecontent\undefined \writestatus\m!system{error in page-lyr.tex} \wait \fi
-
-\let\normalsettextpagecontent\settextpagecontent
+\ifdefined\settextpagecontent \else
+ \writestatus\m!system{error in page-lyr.tex} \wait
+\fi
\definelayer
[OTRTEXT]
@@ -631,9 +796,9 @@
[\c!width=\innermakeupwidth,
\c!height=\textheight]
-% will be overloaded in page-spr
+\let\normalsettextpagecontent\settextpagecontent % will be overloaded in page-spr
-\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+\unexpanded\def\settextpagecontent#1#2#3% #2 and #3 will disappear
{\doifelselayerdata{OTRTEXT}
{\setbox#1\hbox to \makeupwidth
{\startoverlay
diff --git a/Master/texmf-dist/tex/context/base/pack-mis.mkvi b/Master/texmf-dist/tex/context/base/pack-mis.mkvi
index ab6d2b3343d..978cc120c96 100644
--- a/Master/texmf-dist/tex/context/base/pack-mis.mkvi
+++ b/Master/texmf-dist/tex/context/base/pack-mis.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Miscelaneous,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -22,7 +22,9 @@
% \placement [name][settings]
% \place<name> [settings]
-\installcommandhandler \??pl {placement} \??pl
+\installcorenamespace{placement}
+
+\installcommandhandler \??placement {placement} \??placement
\appendtoks
\setuevalue{\e!place\currentplacement}{\pack_placement{\currentplacement}}%
@@ -44,13 +46,14 @@
\unexpanded\def\pack_placement#tag%
{\bgroup
\edef\currentplacement{#tag}%
- \dosingleempty\pack_placement_indeed}
+ \doifnextoptionalelse\pack_placement_yes\pack_placement_nop}
-\def\pack_placement_indeed[#settings]% set test can be sped up but non critical
- {\iffirstargument
- \setupcurrentplacement[#settings]%
- \fi
- \dowithnextboxcontent{\forgetall}{\pack_placement_flush\egroup}\vbox}
+\def\pack_placement_yes[#settings]%
+ {\setupcurrentplacement[#settings]%
+ \pack_placement_nop}
+
+\def\pack_placement_nop
+ {\dowithnextboxcontentcs\forgetall\pack_placement_flush\vbox}
\def\pack_placement_flush
{\setlocalhsize
@@ -61,24 +64,48 @@
{\placementparameter\c!left
\flushnextbox
\placementparameter\c!right}%
- \ifinsidefloat \else
- \addlocalbackgroundtobox\nextbox
- \fi
+ %\ifinsidefloat \else
+ % \page_backgrounds_add_local_to_box\nextbox
+ %\fi
\ifgridsnapping
- \doifinset{\placementparameter\c!margin}{\v!standard,\v!yes}\noindent % unchecked
- \doifelsenothing{\placementparameter\c!grid}
- {\snaptogrid[\v!middle]}
- {\snaptogrid[\placementparameter\c!grid]}%
- \hbox{\flushnextbox}%
+ \pack_placement_flush_grid_yes
\else
- \doif{\placementparameter\c!linecorrection}\v!on \startbaselinecorrection
- \doifinset{\placementparameter\c!margin}{\v!standard,\v!yes}\noindent
- \flushnextbox
- \doif{\placementparameter\c!depthcorrection}\v!on\baselinecorrection
- \doif{\placementparameter\c!linecorrection }\v!on\stopbaselinecorrection
+ \pack_placement_flush_grid_nop
\fi
\endgroup
- \placementparameter\c!after}
+ \placementparameter\c!after
+ \egroup}
+
+\def\pack_placement_flush_grid_yes
+ {\edef\p_grid{\placementparameter\c!grid}%
+ \ifx\p_grid\empty
+ \let\p_grid\v!middle
+ \fi
+ \pack_placement_flush_grid_noindent
+ \snaptogrid[\p_grid]\hbox{\box\nextbox}}
+
+\def\pack_placement_flush_grid_nop
+ {\edef\p_linecorrection {\placementparameter\c!linecorrection}%
+ \edef\p_depthcorrection{\placementparameter\c!depthcorrection}%
+ \ifx\p_linecorrection\v!on
+ \startbaselinecorrection
+ \fi
+ \pack_placement_flush_grid_noindent
+ \box\nextbox
+ \ifx\p_depthcorrection\v!on
+ \baselinecorrection
+ \fi
+ \ifx\p_linecorrection\v!on
+ \stopbaselinecorrection
+ \fi}
+
+\def\pack_placement_flush_grid_noindent
+ {\edef\p_margin{\placementparameter\c!margin}%
+ \ifx\p_margin\v!standard
+ \noindent
+ \else\ifx\p_margin\v!yes
+ \noindent
+ \fi\fi}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/pack-mrl.mkiv b/Master/texmf-dist/tex/context/base/pack-mrl.mkiv
new file mode 100644
index 00000000000..f3f3d11d9a8
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/pack-mrl.mkiv
@@ -0,0 +1,870 @@
+%D \module
+%D [ file=pack-mrl, % was pack-rul/core-rul,
+%D version=1998.10.16,
+%D title=\CONTEXT\ Packaging Macros,
+%D subtitle=More Rules,
+%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 / More Rules}
+
+%D This module needs an overhaul.
+
+\unprotect
+
+%D \macros
+%D {setupblackrules,blackrule}
+%D
+%D The graphic capabilities of \TEX\ do not go beyond simple
+%D filled rules, except of course when using specials. Let's
+%D start with a warning: using this commands is far more slower
+%D than using the \TEX\ primitives \type{\hrule} and
+%D \type{\vrule}, but they save us some tokens. The
+%D characteristics of these rule drawing command can be set by:
+%D
+%D \showsetup{setupblackrules}
+%D
+%D The simple command draws only one rule. Its optional
+%D argument can be used to specify the dimensions. By setting
+%D the width, height or depth to \type {max}, one gets the
+%D natural dimensions.
+%D
+%D \showsetup{blackrule}
+
+\installcorenamespace{blackrules}
+
+\installsimplecommandhandler \??blackrules {blackrules}
+
+\unexpanded\def\blackrule
+ {\hbox\bgroup
+ \doifnextoptionalelse\pack_black_rule_pickup\pack_black_rule_indeed}
+
+\def\pack_black_rule_pickup[#1]%
+ {\setupcurrentblackrules[#1]%
+ \pack_black_rule_indeed}
+
+\def\pack_black_rule_indeed
+ {\edef\p_width {\directblackrulesparameter\c!width }%
+ \edef\p_height{\directblackrulesparameter\c!height}%
+ \edef\p_depth {\directblackrulesparameter\c!depth }%
+ \ifx\p_height\v!max
+ \setstrut
+ \else\ifx\p_depth\v!max
+ \setstrut
+ \fi\fi
+ \useblackrulesstyleandcolor\c!style\c!color
+ \vrule
+ \!!width \ifx\p_width \v!max\emwidth\else\p_width \fi
+ \!!height\ifx\p_height\v!max\strutht\else\p_height\fi
+ \!!depth \ifx\p_depth \v!max\strutdp\else\p_depth \fi
+ \egroup}
+
+\setupblackrules
+ [\c!width=\emwidth,
+ \c!height=\exheight,
+ \c!depth=\zeropoint,
+ \c!color=]
+
+%D \macros
+%D {blackrules}
+%D
+%D One can call for a sequence of black rules, if needed
+%D equally spaced over the given width.
+%D
+%D \showsetup{blackrules}
+%D
+%D The two alternative calls are therefore:
+%D
+%D \startbuffer
+%D Tell me, is this according to the \blackrules[n=6]?
+%D These \blackrules[alternativevariant=b,n=10,distance=.2em,width=4cm] are quite clear.
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D or:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D We could of course have implemented this macro using
+%D \type{\leaders}, but this would probably have taken more
+%D tokens.
+
+\unexpanded\def\blackrules % probably never used
+ {\hbox\bgroup
+ \doifnextoptionalelse\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
+ \scratchheight \directblackrulesparameter\c!height
+ \scratchdepth \directblackrulesparameter\c!depth
+ \scratchdistance\directblackrulesparameter\c!distance
+ \scratchcounter \directblackrulesparameter\c!n
+ \edef\p_alternative{\blackrulesparameter\c!alternative}%
+ \ifx\p_alternative\c!b
+ \ifnum\scratchcounter=\plusone
+ \scratchdistance\zeropoint
+ \else
+ \scratchwidth\dimexpr(\scratchwidth-\scratchcounter\scratchdistance+\scratchdistance)/\scratchcounter\relax
+ \fi
+ \fi
+ \useblackrulesstyleandcolor\c!style\c!color
+ \dorecurse\scratchcounter % a typical case of where we can use a simple loop
+ {\vrule
+ \!!width \scratchwidth
+ \!!height\scratchheight
+ \!!depth \scratchdepth
+ \hskip\scratchdistance}%
+ \unskip
+ \egroup}
+
+\setupblackrules
+ [\c!n=3,
+ \c!alternative=\c!a,
+ \c!distance=.25\emwidth,
+ \c!color=]
+
+%D Marginrules will either become obsolete or be redone.
+
+%D The next commands can be used to draw margin rules. We
+%D support two methods: \marginrule{one for in||line use} and
+%D one that acts on a paragraph. Drawing a margin rule is
+%D rather straightforward because we can use the commands that
+%D put text in the margin.
+
+\def\dodrawmarginrule
+ {\setbox\scratchbox\hbox
+ {\vrule\!!depth\strutdepth\!!height\strutheight\!!width\@@karulethickness}%
+ \smashbox\scratchbox % no \vsmash !!!
+ \box\scratchbox}
+
+\def\drawmarginrule
+ {\strut\inleft{\dodrawmarginrule}}
+
+%D \macros
+%D {marginrule}
+%D
+%D The first method gobbles words and simply puts a bar in the
+%D margin. This method is not entirely robust.
+%D
+%D \showsetup{marginrule}
+
+\definecomplexorsimple\marginrule
+
+\def\simplemarginrule
+ {\let\processword\drawmarginrule
+ \processwords}
+
+\def\complexmarginrule[#1]%
+ {\ifnum#1<\@@kalevel\relax \else
+ \def\@@kadefaultwidth{#1}%
+ \expandafter\simplemarginrule
+ \fi}
+
+%D We need an auxiliary variable
+
+\def\@@kadefaultwidth{1}
+
+%D \macros
+%D {setupmarginrules}
+%D
+%D This macro definitions show us that we can pass an optional
+%D level, which is matched against the previous set one. The
+%D level can be set up with
+%D
+%D \showsetup{setupmarginrules}
+
+\unexpanded\def\setupmarginrules
+ {\dodoubleargument\getparameters[\??ka]}
+
+%D \macros
+%D {startmarginrule}
+%D
+%D The second method collects text and reformats it afterwards,
+%D using the shapebox macros. We prevent local margin rules.
+%D
+%D \showsetup{startmarginrule}
+
+\definecomplexorsimple\startmarginrule
+
+\def\simplestartmarginrule
+ {\bgroup
+ \let\drawmarginrule\relax
+ \let\stopmarginrule\dostopmarginrule
+ \beginofshapebox}
+
+\def\complexstartmarginrule[#1]%
+ {\bgroup
+ \let\drawmarginrule\relax
+ \ifnum#1<\@@kalevel\relax
+ \let\stopmarginrule\egroup
+ \else
+ \def\@@kadefaultwidth{#1}%
+ \let\stopmarginrule\dostopmarginrule
+ \expandafter\beginofshapebox
+ \fi}
+
+\def\dostopmarginrule
+ {\endofshapebox
+ \reshapebox
+ {\hbox{\inleftmargin{\dodrawmarginrule}\box\shapebox}}%
+ \flushshapebox
+ \egroup}
+
+%D \startbuffer
+%D \setupmarginrules[level=5]
+%D
+%D \startmarginrule[1]
+%D First we set the level at~5. Next we typeset this first
+%D paragraph as a level~1 one. As expected no rule show up.
+%D \stopmarginrule
+%D
+%D \startmarginrule[5]
+%D The second paragraph is a level~5 one. As we can see here,
+%D the marginal rule gets a width according to its level.
+%D \stopmarginrule
+%D
+%D \startmarginrule[8]
+%D It will of course be no surprise that this third paragraph
+%D has a even thicker margin rule. This behavior can be
+%D overruled by specifying the width explictly.
+%D \stopmarginrule
+%D \stopbuffer
+%D
+%D In next example we show most features. Watch the rule
+%D thickness adapting itself to the level.
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D We just said:
+%D
+%D \typebuffer
+
+%D \macros
+%D {vl, hl}
+%D
+%D The command \type{\vl} draws a vertical rule \vl\ with strut
+%D dimensions, multiplied with the factor specified in the
+%D optional argument. The height and depth are clipped \vl[3]
+%D to the baselinedistance. Its horizontal counterpart
+%D \type{\hl} draws a horizontal rule \hl\ with a width of 1em,
+%D multiplied with the optional factor. The horizontal rule is
+%D drawn on top of the baseline.
+%D
+%D \showsetup{vl}
+%D \showsetup{hl}
+
+\unexpanded\def\dovlwdhtdp#1#2#3% used elsewhere
+ {\bgroup
+ \setbox\scratchbox\hbox
+ {\vrule
+ \!!width #1\linewidth
+ \!!height#2\strutht
+ \!!depth #3\strutdp}%
+ \dp\scratchbox\strutdp
+ \ht\scratchbox\strutht
+ \box\scratchbox
+ \egroup}
+
+\def\complexvl[#1]%
+ {\dovlwdhtdp\plusone{#1}{#1}}
+
+\def\complexhl[#1]%
+ {\hbox
+ {\vrule
+ \!!width #1\emwidth
+ \!!height\linewidth
+ \!!depth \zeropoint}}
+
+\definecomplexorsimple\vl \def\simplevl{\complexvl[\plusone]}
+\definecomplexorsimple\hl \def\simplehl{\complexhl[\plusone]}
+
+%D \macros
+%D {hairline, thinrule, thinrules, setupthinrules}
+%D
+%D Drawing thin lines can of course easily be accomplished by
+%D the \TEX\ primitives \type{\hrule} and \type{\vrule}. The
+%D next few macros however free us from some specifications.
+%D
+%D \startbuffer
+%D some text
+%D
+%D \hairline
+%D
+%D some more text
+%D
+%D \thinrule
+%D
+%D more and more text
+%D
+%D hi \thinrule\ there
+%D
+%D and then the final text
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D becomes
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D So we've got
+%D
+%D \showsetup{hairline}
+%D \showsetup{thinrule}
+%D
+%D Both can be set up with:
+%D
+%D \showsetup{setupthinrules}
+%D
+%D We also have
+%D
+%D \showsetup{thinrules}
+%D
+%D which looks like: \thinrules[n=2]
+
+\newconstant\ruletype
+
+\def\thinrule
+ {\strut
+ \bgroup
+ \ruletype\plusone
+ \processaction
+ [\@@dlalternative]
+ [ \v!a=>\ruletype\zerocount,% no line
+ %\v!b=>\ruletype\plusone ,% height/depth
+ \v!c=>\ruletype\plustwo ,% topheight/botdepth
+ % 11=>\ruletype\plusone ,% fallback for backgrounds
+ 0=>\ruletype\zerocount,% compatible with backgrounds
+ % 1=>\ruletype\plusone ,% compatible with backgrounds
+ 2=>\ruletype\plustwo ]% compatible with backgrounds
+ \doifsomething\@@dlrulethickness
+ {\linewidth\@@dlrulethickness}%
+ \ifdim\linewidth=\zeropoint
+ \ruletype\zerocount
+ \else
+ \doifnot\@@dlframe\v!on{\ruletype\zerocount}%
+ \fi
+ \ifnum\ruletype=\plusone
+ \doif\@@dlheight\v!max{\let\@@dlheight\!!plusone}%
+ \doif\@@dldepth \v!max{\let\@@dldepth \!!plusone}%
+ \else
+ \let\@@dlheight\!!plusone
+ \let\@@dldepth\!!plusone
+ \fi
+ \freezedimensionwithunit\@@dlheight\strutht
+ \freezedimensionwithunit\@@dldepth\strutdp
+ \divide\linewidth \plustwo
+ \doifelse\@@dlbackground\v!color
+ {\startcolor[\@@dlbackgroundcolor]%
+ \ifnum\ruletype=\plustwo % prevent overshoot due to rounding
+ \leaders
+ \hrule
+ \!!height\dimexpr\@@dlheight-.5\linewidth\relax
+ \!!depth \dimexpr\@@dldepth -.5\linewidth\relax
+ \hfill
+ \else
+ \leaders
+ \hrule
+ \!!height\@@dlheight
+ \!!depth \@@dldepth
+ \hfill
+ \fi
+ \stopcolor
+ \ifcase\ruletype
+ % no rule
+ \or
+ \startcolor[\@@dlcolor]%
+ \hfillneg
+ \leaders\hrule\!!height\linewidth\!!depth\linewidth\hfill
+ \stopcolor
+ \or
+ \startcolor[\@@dlcolor]%
+ \hfillneg\leaders\hrule\!!height\dimexpr-\@@dldepth+\linewidth\relax\!!depth\@@dldepth\hfill
+ \hfillneg\leaders\hrule\!!height\@@dlheight\!!depth\dimexpr-\@@dlheight+\linewidth\relax\hfill
+ \stopcolor
+ \fi}
+ {\ifcase\ruletype \else
+ \startcolor[\@@dlcolor]%
+ \leaders\hrule\!!height\@@dlheight\!!depth\@@dldepth\hfill
+ \stopcolor
+ \fi}%
+ \strut
+ \carryoverpar\egroup}
+
+\def\hairline
+ {\endgraf
+ \thinrule
+ \endgraf}
+
+\def\dosetupthinrules[#1]%
+ {\getparameters[\??dl][#1]}
+
+\unexpanded\def\setupthinrules
+ {\dosingleargument\dosetupthinrules}
+
+\def\dothinrules[#1]%
+ {\bgroup
+ \dosetupthinrules[#1]%
+ \@@dlbefore
+ \assignvalue\@@dlinterlinespace\@@dlinterlinespace{1.0}{1.5}{2.0}%
+ \spacing\@@dlinterlinespace
+ \dorecurse\@@dln
+ {\ifnum\recurselevel=\@@dln \dothinrulesnobreak \else
+ \ifnum\recurselevel=2 \dothinrulesnobreak \fi\fi
+ \thinrule
+ \ifnum\recurselevel<\@@dln\relax
+ % test needed, else messed up whitespace
+ \ifx\@@dlinbetween\empty
+ \softbreak
+ \else
+ \endgraf
+ \nowhitespace
+ \@@dlinbetween
+ \fi
+ \fi}%
+ \doifelsenothing\@@dlafter
+ {\carryoverpar\egroup}
+ {\@@dlafter\egroup}}
+
+\def\thinrules
+ {\dosingleempty\dothinrules}
+
+%D A couple of examples are given below.
+%D
+%D \startbuffer
+%D \setupthinrules[n=3,inbetween=,color=gray]
+%D
+%D test test \thinrules\ test test \par
+%D test test \thinrules [color=green] test test \par
+%D test test \thinrules [height=max, depth=max] test test \par
+%D
+%D \setupthinrules[height=.9,depth=.9]
+%D
+%D test test \thinrules\ test test \par
+%D test test \thinrules [alternativevariant=b] test test \par
+%D test test \thinrules [alternativevariant=c] test test \par
+%D test test \thinrules [alternativevariant=c,inbetween=\vskip2ex] test test \par
+%D \stopbuffer
+%D
+%D \typebuffer {\getbuffer}
+%D
+%D There are a couple of alternative ways to visualize rules
+%D using backgrounds. At first sight these may look strange,
+%D but they make sense in educational settings. The
+%D alternatives are more or less compatible with the more
+%D advanced \METAPOST\ based implementation.
+%D
+%D \startbuffer[a]
+%D \setupthinrules
+%D [n=2,
+%D backgroundcolor=gray ,
+%D rulethickness=1pt,
+%D colorkleur=donkerblauw,
+%D after=\blank,
+%D before=\blank]
+%D \stopbuffer
+%D
+%D \typebuffer[a]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a]
+%D \thinrules[alternativevariant=b]
+%D \thinrules[alternativevariant=c]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a,background=color]
+%D \thinrules[alternativevariant=b,background=color]
+%D \thinrules[alternativevariant=c,background=color]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+%D
+%D \startbuffer[b]
+%D \thinrules[alternativevariant=a,height=.8,depth=.8,background=color]
+%D \thinrules[alternativevariant=b,height=.8,depth=.8,background=color]
+%D \thinrules[alternativevariant=c,height=.8,depth=.8,background=color]
+%D \stopbuffer
+%D
+%D \typebuffer[b] \getbuffer[a,b]
+
+%D \macros
+%D {optimizethinrules}
+%D
+%D By saying \type {\thinrulestrue} or \type {-false}, we
+%D can influence the way dangling lines are handled.
+
+\newif\ifoptimizethinrules \optimizethinrulestrue
+
+\def\dothinrulesnobreak
+ {\ifoptimizethinrules\penalty500\fi}
+
+%D \macros
+%D {textrule, starttextrule, setuptextrules}
+%D
+%D Putting rules before and after a paragraph is very space
+%D sensitive, but the next command handles that quite well. It
+%D comes in two disguises:
+%D
+%D \startbuffer
+%D \textrule[top]{fragments}
+%D \input reich
+%D \textrule
+%D \stopbuffer
+%D
+%D \start \typebuffer \getbuffer \stop
+%D
+%D \startbuffer
+%D \setuptextrules
+%D [width=90pt,distance=12pt,rulecolor=blue,
+%D bodyfont=small,style=\sc,color=red]
+%D
+%D \starttextrule{Ship Building Tools}
+%D \nl \setuptolerance[tolerant] \input materie
+%D \stoptextrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D \startbuffer
+%D \setuptextrules
+%D [location=inmargin,
+%D bodyfont=small,style=slantedbold]
+%D
+%D \starttextrule{wonderful}
+%D \input tufte
+%D \stoptextrule
+%D \stopbuffer
+%D
+%D \bgroup \typebuffer \getbuffer \egroup
+%D
+%D The formal definition of these commands is:
+%D
+%D \showsetup{textrule}
+%D \showsetup{starttextrule}
+%D \showsetup{setuptextrules}
+%D
+%D The implementation looks a bit complicated due to the
+%D optional arguments.
+
+\unexpanded\def\setuptextrules
+ {\dodoubleargument\getparameters[\??tl]}
+
+\def\complextextrule[#1]% if needed we can make it installable
+ {\let\next\dobottomtextrule
+ \processaction
+ [#1]
+ [ \v!top=>\let\next\dotoptextrule,
+ \v!middle=>\let\next\domiddletextrule,
+ \v!bottom=>\let\next\dobottomtextrule]%
+ \dosinglegroupempty\next}
+
+\definecomplexorsimple\textrule
+
+\def\simpletextrule
+ {\dosinglegroupempty\dounknowntextrule}
+
+\def\docomplextextrule#1%
+ {\bgroup
+ \advance\hsize\dimexpr-\rightskip-\leftskip\relax
+ \setbox\scratchbox\hbox to \hsize
+ {\dimen4\dimexpr .5ex+.5\linewidth\relax
+ \dimen6\dimexpr-.5ex+.5\linewidth\relax
+ \doifsomething{#1}
+ {\doifelse\@@tllocation\v!inmargin
+ {\llap
+ {\dousestyleparameter\@@tlstyle
+ \dousecolorparameter\@@tlcolor
+ #1%
+ \hskip\leftmargindistance}}
+ {\color[\@@tlrulecolor]
+ {\vrule\!!height\dimen4\!!depth\dimen6\!!width\@@tlwidth}%
+ \hbox spread 2\dimexpr\@@tldistance\relax
+ {\hss
+ \dousestyleparameter\@@tlstyle
+ \dousecolorparameter\@@tlcolor
+ \strut#1%
+ \hss}}}%
+ \color[\@@tlrulecolor]
+ {\leaders\hrule\!!height\dimen4\!!depth\dimen6\hfill}}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \noindent\box\scratchbox
+%\nobreak\verticalstrut\kern-\struttotal
+% evt \witruimte
+ \egroup}
+
+\def\dotoptextrule#1%
+ {\page[\v!preference] % interferes
+ %\whitespace % no
+ \@@tlbefore
+ \docomplextextrule{#1}%
+% todo, option: \doifnothing{#1}{\ruledvskip-.5ex}
+ \nowhitespace
+ \@@tlinbetween
+ \endgraf}
+
+\def\dodobottomtextrule#1#2%
+ {\ifhmode
+ \endgraf
+ \fi
+ \dimen0\strutdp
+ \ifdim\prevdepth>\strutdp\else % was <\strutdp
+ \ifdim\prevdepth>\zeropoint
+ \advance\dimen0 -\prevdepth
+ \fi
+ \fi
+ \advance\dimen0 .5ex
+ \vskip\dimen0
+% ==
+% \vskip\dimexpr \strutdp + .5ex
+% \ifdim\prevdepth>\strutdp\else\ifdim\prevdepth>\zeropoint-\prevdepth\fi\fi\relax
+%
+ \@@tlinbetween
+ \doifelsenothing{#2}
+ {\bgroup
+ \advance\hsize\dimexpr-\rightskip-\leftskip\relax
+ \nointerlineskip
+ \moveleft-\leftskip\vbox
+ {\color[\@@tlrulecolor]
+ {\hrule\!!depth\linewidth\!!height\zeropoint\!!width\hsize}}%
+ \egroup}
+ {\docomplextextrule{#2}}%
+ \ifvmode\prevdepth\zeropoint\fi
+ #1%
+ \page[\v!preference]}
+
+\def\dobottomtextrule
+ {\dodobottomtextrule\@@tlafter}
+
+\def\domiddletextrule
+ {\dodobottomtextrule\@@tlinbetween}
+
+\def\dounknowntextrule
+ {\iffirstargument
+ \@EA\dotoptextrule
+ \else
+ \@EA\dobottomtextrule\@EA\empty
+ \fi}
+
+%D The grouped commands also supports bodyfont switching:
+
+\unexpanded\def\starttextrule#1%
+ {\bgroup
+ \def\dounknowntextrule{\domiddletextrule}
+ \dotoptextrule{#1}
+ \bgroup
+ \doifsomething\@@tlbodyfont{\switchtobodyfont[\@@tlbodyfont]}}
+
+\unexpanded\def\stoptextrule
+ {\par
+ \egroup
+ \dobottomtextrule\empty
+ \egroup}
+
+%D \macros
+%D {fillinrules, setupfillinrules}
+%D
+%D The next few commands do not really deserve a place in a
+%D core module, because they deal with specific typography.
+%D Nevertheless I decided to make them part of the core,
+%D because they permit us to make questionaires. Let's start
+%D with some examples.
+%D
+%D \fillinrules[n=2,width=fit]{first}
+%D \fillinrules[n=2,width=broad]{first}
+%D \fillinrules[n=2,width=3cm]{first}
+%D \fillinrules[n=2,width=3cm,distance=.5em,separator=:]{first}
+%D \fillinrules[n=2]{first}{last}
+%D \fillintext{first}{last} \input reich \par
+%D
+%D The main command is \type{\fillinrules}. This command takes
+%D one and an optional second argument and sets a paragraph with
+%D empty visualized lines.
+%D
+%D \showsetup{fillinrules}
+%D \showsetup{setupfillinrules}
+
+\unexpanded\def\setupfillinrules
+ {\dodoubleargument\getparameters[\??il]}
+
+\definecomplexorsimpleempty\fillinrules
+
+\def\complexfillinrules[#1]%
+ {\def\docomplexfillinrules##1##2%
+ {\dodocomplexfillinrules[#1]{##1}{##2}{\thinrules
+ [\c!n=\@@iln,\c!interlinespace=\@@ilinterlinespace,\c!before=,\c!after=]}}%
+ \dodoublegroupempty\docomplexfillinrules}
+
+\def\dodocomplexfillinrules[#1]#2#3#4%
+ {\endgraf
+ \@@ilbefore
+ \begingroup
+ \setupfillinrules[#1]%
+ \noindent
+ \doifsomething{#2}
+ {\doifelse\@@ilwidth\v!fit
+ {\let\@@ildistance\!!zeropoint
+ \hbox}
+ {\doifelse\@@ilwidth\v!broad
+ {\hbox}
+ {\hbox to \@@ilwidth}}%
+ \bgroup
+ \dousestyleparameter\@@ilstyle
+ \dousecolorparameter\@@ilcolor
+ \strut#2\hfill\@@ilseparator\hskip\@@ildistance
+ \egroup}%
+ %\hangindent=\wd0\relax % tzt hang=yes,n
+ %\parindent=\hangindent
+ %\box0\relax
+ \setupwhitespace[\v!big]%
+ \ignorespaces
+ #4%
+ \doifsomething{#3}
+ {\kern\@@ildistance
+ \dousestyleparameter\@@ilstyle
+ \dousecolorparameter\@@ilcolor
+ #3\strut}%
+ \endgroup
+ \endgraf
+ \@@ilafter}
+
+%D \macros
+%D {fillintext}
+%D
+%D To provide compatible layouts when texts and lines are
+%D mixed, one can typeset a paragraph by using the command
+%D \type{\fillintext}.
+%D
+%D \showsetup{fillintext}
+
+\definecomplexorsimpleempty\fillintext
+
+\def\complexfillintext[#1]% rather rough, using an \unhbox is suboptimal
+ {\def\docomplexfillintext##1##2%
+ {\dowithnextbox
+ {\dodocomplexfillinrules[#1]{##1}{\hfill##2}{\unhbox\nextbox\unskip}}%
+ \hbox\bgroup\let\par\egroup\ignorespaces}%
+ \dodoublegroupempty\docomplexfillintext}
+
+%D \macros
+%D {fillinline, setupfillinlines}
+%D
+%D Another member of the family takes care of putting a (often
+%D small) rule after a piece of text, like
+%D
+%D \startbuffer
+%D \fillinline \input reich \par
+%D \fillinline[margin=0cm] \input reich \par
+%D \stopbuffer
+%D
+%D \startexample
+%D \getbuffer
+%D \stopexample
+%D
+%D which was typeset by saying:
+%D
+%D \typebuffer
+%D
+%D The two commands that take care of this are:
+%D
+%D \showsetup{fillinline}
+%D \showsetup{setupfillinlines}
+
+\unexpanded\def\setupfillinlines
+ {\dodoubleargument\getparameters[\??iv]}
+
+\definecomplexorsimpleempty\fillinline
+
+\def\complexfillinline[#1]%
+ {%\endgraf % interferes with \definedescription cum suis
+ \@@ivbefore
+ \begingroup
+ \setupfillinlines[#1]%
+ \advance\rightskip \@@ivmargin
+ \parfillskip\zeropoint
+ \def\par % very dangerous
+ {\let\par\endgraf % -)
+ \ifhmode\unskip\hfill\fi
+ \scratchdimen\dimexpr\@@ivwidth-\@@ivdistance\relax
+ \ifdim\scratchdimen>\@@ivmargin\else\expandafter\rlap\fi
+ {\kern\@@ivdistance
+ \vrule
+ \!!width \scratchdimen
+ \!!height.5\linewidth
+ \!!depth .5\linewidth}%
+ \endgraf % !
+ \endgroup
+ \endgraf % !
+ \@@ilafter}}
+
+%D Will move up:
+
+\setupmarginrules
+ [\c!level=0,
+ \c!rulethickness=\@@kadefaultwidth\linewidth]
+
+\setupthinrules
+ [\c!interlinespace=\v!small,
+ \c!n=3,
+ \c!before=,
+ \c!inbetween={\blank[\v!white]},
+ \c!after=,
+ \c!color=,
+ \c!height=.5\linewidth,
+ \c!depth=.5\linewidth,
+ \c!frame=\v!on, % compatible with textbackgrounds
+ \c!alternative=\v!b,
+ \c!backgroundcolor=,
+ \c!background=,
+ \c!rulethickness=]
+
+\setuptextrules
+ [\c!location=\v!left,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!inbetween=,
+ \c!width=2em,
+ \c!style=\v!bold,
+ \c!color=,
+ \c!rulecolor=,
+ \c!bodyfont=,
+ \c!distance=.5em]
+
+\setupfillinrules
+ [\c!width=\v!broad,
+ \c!distance=1em,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!n=1,
+ \c!interlinespace=\v!small,
+ \c!separator=,
+ \c!style=\v!normal,
+ \c!color=]
+
+\setupfillinlines
+ [\c!width=3cm,
+ \c!margin=\@@ivwidth,
+ \c!distance=1em,
+ \c!before=\blank,
+ \c!after=\blank]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/pack-obj.lua b/Master/texmf-dist/tex/context/base/pack-obj.lua
index 2dabfa7846a..c580aaa6287 100644
--- a/Master/texmf-dist/tex/context/base/pack-obj.lua
+++ b/Master/texmf-dist/tex/context/base/pack-obj.lua
@@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['pack-obj'] = {
reusable components.</p>
--ldx]]--
-local texsprint, texcount = tex.sprint, tex.count
+local texcount = tex.count
local allocate = utilities.storage.allocate
local collected = allocate()
@@ -46,12 +46,12 @@ end
function jobobjects.number(tag,default)
local o = collected[tag] or tobesaved[tag]
- texsprint((o and o[1]) or default)
+ context((o and o[1]) or default)
end
function jobobjects.page(tag,default)
local o = collected[tag] or tobesaved[tag]
- texsprint((o and o[2]) or default)
+ context((o and o[2]) or default)
end
function jobobjects.doifelse(tag)
diff --git a/Master/texmf-dist/tex/context/base/pack-obj.mkii b/Master/texmf-dist/tex/context/base/pack-obj.mkii
index 6971ad04ff6..81523d52564 100644
--- a/Master/texmf-dist/tex/context/base/pack-obj.mkii
+++ b/Master/texmf-dist/tex/context/base/pack-obj.mkii
@@ -5,7 +5,7 @@
%D subtitle=Objects,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/pack-obj.mkiv b/Master/texmf-dist/tex/context/base/pack-obj.mkiv
index 3d87f52b57d..6c9848a0135 100644
--- a/Master/texmf-dist/tex/context/base/pack-obj.mkiv
+++ b/Master/texmf-dist/tex/context/base/pack-obj.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Objects,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -224,13 +224,13 @@
\def\objectplaceholder{NOT YET FLUSHED}%
\def\presetobject#1#2% \global added
- {\ifcsname\r!object#1::#2\endcsname\else
- \global\@EA\let\csname\r!object#1::#2\endcsname\objectplaceholder
+ {\ifcsname\??ob:#1::#2\endcsname\else
+ \global\@EA\let\csname\??ob:#1::#2\endcsname\objectplaceholder
\fi}
\def\dosetobject#1#2#3% \initializepaper this will move to \everyshipout
{% \initializepaper
- \ifcsname\r!object#2::#3\endcsname
+ \ifcsname\??ob:#2::#3\endcsname
\expandafter\gobblefivearguments
\else % tzt, overload internal referenced objects to save entries
\expandafter\dodosetobject
@@ -238,7 +238,7 @@
{#1}{#2}{#3}}
\def\resetobject#1#2%
- {\letbeundefined{\r!object#1::#2}}
+ {\letbeundefined{\??ob:#1::#2}}
%D \macros
%D {finalizeobjectbox}
@@ -265,65 +265,40 @@
{\globalpopmacro\crossreferenceobject
\dododosetobject{#1}{#2}{#3}\egroup}}
-\ifnum\luatexversion<66
-
- \def\dododosetobject#1#2#3% this is a hack: luatex adds 1bp around each side
- {\begingroup
- \dontshowcomposition % rather fuzzy in \setxvalue ... \hbox
- \ifcase#1\relax
- \scratchdimen-\onebasepoint % compensates auto 1 bp
- \else\ifdim\objectoffset>\zeropoint
- \scratchdimen \objectoffset
- \else
- \scratchdimen-\onebasepoint % compensates auto 1 bp
- \fi\fi
- \@EA\xdef\csname\r!object#2::#3\endcsname
- {\noexpand\dohandleobject{#2}{#3}%
- {\ifhbox\nextbox\hbox\else\vbox\fi}%
- {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}%
- {\number\scratchdimen}}%
- \expanded % freeze the dimensions since \dostartobject may use \nextbox
- {\dostartobject{#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}%
- \setbox\nextbox\vbox spread 2\scratchdimen
- {\forgetall \offinterlineskip
- \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}%
- \flushnextbox
- \dostopobject
- \endgroup}
-
-\else
-
- \def\dododosetobject#1#2#3%
- {\begingroup
- \dontshowcomposition % rather fuzzy in \setxvalue ... \hbox
- \scratchdimen\objectoffset
- \@EA\xdef\csname\r!object#2::#3\endcsname
- {\noexpand\dohandleobject{#2}{#3}%
- {\ifhbox\nextbox\hbox\else\vbox\fi}%
- {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}%
- {\number\scratchdimen}}%
- \expanded % freeze the dimensions since \dostartobject may use \nextbox
- {\dostartobject{#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}%
- \ifcase#1\relax\else \ifdim\objectoffset>\zeropoint
- \setbox\nextbox\vbox spread 2\scratchdimen
- {\forgetall \offinterlineskip
- \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}%
- \fi \fi
- \flushnextbox
- \dostopobject
- \endgroup}
+% in luatex version < 66 we had a 1bp compensation (hardcoded in luatex)
-\fi
+\def\dododosetobject#1#2#3%
+ {\begingroup
+ \scratchdimen\objectoffset
+ \@EA\xdef\csname\??ob:#2::#3\endcsname
+ {\noexpand\dohandleobject{#2}{#3}%
+ {\ifhbox\nextbox\hbox\else\vbox\fi}%
+ {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}%
+ {\number\scratchdimen}}%
+ \expanded % freeze the dimensions since \dostartobject may use \nextbox
+ {\dostartobject{#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}%
+ \ifcase#1\relax\else \ifdim\objectoffset>\zeropoint
+ \setbox\nextbox\vbox spread 2\scratchdimen
+ {\forgetall \offinterlineskip
+ \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}%
+ \fi \fi
+ \flushnextbox
+ \dostopobject
+ \endgroup}
\def\getobject#1#2%
- {\begingroup
- \let\dohandleobject\dogetobject
- \csname\r!object#1::#2\endcsname}
+ {\ifcsname\??ob:#1::#2\endcsname
+ \begingroup
+ \let\dohandleobject\dogetobject
+ \csname\??ob:#1::#2\expandafter\endcsname
+ \else
+ {\infofont[object #1::#2]}%
+ \fi}
\def\dogetobject#1#2#3#4#5#6#7% don't change this, should work for dvi & pdf
{% \initializepaper
\forgetall
- \dontshowcomposition
+ % todo: if no attr then faster
\setbox\scratchbox\vbox attr \viewerlayerattribute \attribute\viewerlayerattribute
{\doinsertobject{#1}{#2}}%
\setbox\scratchbox#3%
@@ -336,7 +311,6 @@
%\vss\box\scratchbox
\vss\hbox to #4\scaledpoint{\box\scratchbox\hss}% fix Chof
\fi\fi}}%
-% \forcecolorhack % needed in order to use layers etc
\box\scratchbox
\endgroup}
@@ -360,7 +334,7 @@
\let\objectwidth \!!zeropoint
\let\objectheight\!!zeropoint
\let\objectdepth \!!zeropoint
- \csname\r!object#1::#2\endcsname}
+ \csname\??ob:#1::#2\endcsname}
%D Apart from this kind of objects, that have typeset content,
%D we can have low level driver specific objects. Both types
@@ -420,7 +394,7 @@
%D \stoptyping
\def\doifobjectfoundelse#1#2%
- {\ifcsname\r!object#1::#2\endcsname
+ {\ifcsname\??ob:#1::#2\endcsname
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
diff --git a/Master/texmf-dist/tex/context/base/pack-pos.mkiv b/Master/texmf-dist/tex/context/base/pack-pos.mkiv
index 42a80b5ae27..fab73bc4a3b 100644
--- a/Master/texmf-dist/tex/context/base/pack-pos.mkiv
+++ b/Master/texmf-dist/tex/context/base/pack-pos.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Positioning,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -15,7 +15,7 @@
\unprotect
-% An old but still usefull mechanism (updated in mkiv):
+% An old but still usefull mechanism:
%
% \ruledvbox{\startpositioning
% \position(1,1){test}
@@ -60,21 +60,6 @@
\vfill}%
\egroup}
-% \def\resetpositioning
-% {\getparameters[\??ps]
-% [\c!state=\v!start,
-% \c!unit=\s!cm,
-% \c!factor=\plusone,
-% \c!scale=\plusone,
-% \c!xfactor=\@@psfactor,
-% \c!yfactor=\@@psfactor,
-% \c!xscale=\@@psscale,
-% \c!yscale=\@@psscale,
-% \c!xstep=\v!absolute,
-% \c!ystep=\v!absolute,
-% \c!xoffset=\zeropoint,
-% \c!yoffset=\zeropoint]}
-
\def\resetpositioning
{\let\@@psstate \v!start
\let\@@psunit \s!cm
diff --git a/Master/texmf-dist/tex/context/base/pack-rul.lua b/Master/texmf-dist/tex/context/base/pack-rul.lua
index 181bff2343f..cd2e809e725 100644
--- a/Master/texmf-dist/tex/context/base/pack-rul.lua
+++ b/Master/texmf-dist/tex/context/base/pack-rul.lua
@@ -17,52 +17,68 @@ local texdimen, texcount = tex.dimen, tex.count
-- fastrepack
function commands.doreshapeframedbox(n)
- local box, noflines, firstheight, lastdepth, lastlinelength = texbox[n], 0, nil, nil, 0
+ local box = texbox[n]
+ local noflines = 0
+ local firstheight = nil
+ local lastdepth = nil
+ local lastlinelength = 0
+ local minwidth = 0
+ local maxwidth = 0
+ local totalwidth = 0
if box.width ~= 0 then
local list = box.list
if list then
- local width, done = 0, false
for h in traverse_id('hlist',list) do -- no dir etc needed
if not firstheight then
firstheight = h.height
end
lastdepth = h.depth
+ noflines = noflines + 1
local l = h.list
if l then
- done = true
local p = hpack(copy(l))
lastlinelength = p.width
- if lastlinelength > width then
- width = lastlinelength
+ if lastlinelength > maxwidth then
+ maxwidth = lastlinelength
+ end
+ if lastlinelength < minwidth or minwidth == 0 then
+ minwidth = lastlinelength
end
+ totalwidth = totalwidth + lastlinelength
free(p)
end
end
- if done then
- if width ~= 0 then
+ if firstheight then
+ if maxwidth ~= 0 then
for h in traverse_id('hlist',list) do
local l = h.list
if l then
- -- if h.width ~= width then -- else no display math handling (uses shift)
- h.list = hpack(l,width,'exactly',h.dir)
+ -- if h.width ~= maxwidth then -- else no display math handling (uses shift)
+ h.list = hpack(l,maxwidth,'exactly',h.dir)
h.shift = 0 -- needed for display math
- h.width = width
+ h.width = maxwidth
-- end
end
end
end
- box.width = width
+ box.width = maxwidth
end
end
end
---~ print("reshape", noflines, firstheight or 0, lastdepth or 0)
- texsetcount("global","framednoflines", noflines)
- texsetdimen("global","framedfirstheight", firstheight or 0)
- texsetdimen("global","framedlastdepth", lastdepth or 0)
+ -- print("reshape", noflines, firstheight or 0, lastdepth or 0)
+ texsetcount("global","framednoflines", noflines)
+ texsetdimen("global","framedfirstheight", firstheight or 0)
+ texsetdimen("global","framedlastdepth", lastdepth or 0)
+ texsetdimen("global","framedminwidth", minwidth)
+ texsetdimen("global","framedmaxwidth", maxwidth)
+ texsetdimen("global","framedaveragewidth", noflines > 0 and totalwidth/noflines or 0)
end
function commands.doanalyzeframedbox(n)
- local box, noflines, firstheight, lastdepth = texbox[n], 0, nil, nil
+ local box = texbox[n]
+ local noflines = 0
+ local firstheight = nil
+ local lastdepth = nil
if box.width ~= 0 then
local list = box.list
if list then
@@ -75,7 +91,7 @@ function commands.doanalyzeframedbox(n)
end
end
end
---~ print("analyze", noflines, firstheight or 0, lastdepth or 0)
+ -- print("analyze", noflines, firstheight or 0, lastdepth or 0)
texsetcount("global","framednoflines", noflines)
texsetdimen("global","framedfirstheight", firstheight or 0)
texsetdimen("global","framedlastdepth", lastdepth or 0)
diff --git a/Master/texmf-dist/tex/context/base/pack-rul.mkii b/Master/texmf-dist/tex/context/base/pack-rul.mkii
index 055094547c2..7399cacd811 100644
--- a/Master/texmf-dist/tex/context/base/pack-rul.mkii
+++ b/Master/texmf-dist/tex/context/base/pack-rul.mkii
@@ -5,7 +5,7 @@
%D subtitle=Ruled Content,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -871,7 +871,7 @@
\edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}%
\ifx\framedforegroundcolor\empty\else\docolorframebox\fi
\edef\overlaylinecolor{\framedparameter\c!framecolor}%
- \edef\overlaylinewidth{\the\ruledlinewidth}%
+ \def \overlaylinewidth{\the\ruledlinewidth}% no edef
\edef\@@localframing {\framedparameter\c!frame}%
\ifx\@@localframing\v!overlay \else \ifx\@@localframing\v!none \else
\edef\framedrulethickness{\framedparameter\c!rulethickness}%
diff --git a/Master/texmf-dist/tex/context/base/pack-rul.mkiv b/Master/texmf-dist/tex/context/base/pack-rul.mkiv
index c137aea01a2..f65641b96ca 100644
--- a/Master/texmf-dist/tex/context/base/pack-rul.mkiv
+++ b/Master/texmf-dist/tex/context/base/pack-rul.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Ruled Content,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,28 +13,19 @@
\writestatus{loading}{ConTeXt Packaging Macros / Ruled Content}
-%D redo framedtexts like framedcontent (parameter stuff)
+%D The code here is expanded lots of time as framed is used in
+%D many places. This is why the code here is (and gets) optimized
+%D as much as possible. Also, by avoiding packaging and expansion
+%D we also keep tracing reasonable. For instance, multiple stacked
+%D backgrounds can slow down a run if not optimized this way.
-%D After a few months testing this solution is now added
-%D to the core. This introduces a possible incompatibility
-%D between \MKII\ and \MKIV\ but for the better.
+% eventually this will use the commandhandler code (same trick as
+% with itemize)
\registerctxluafile{pack-rul}{1.001}
-% old off new
-% 4 lines oeps : 3.6 2.8 3.0
-% tufte 7.5 4.1 4.3
-
\unprotect
-%D We have removed the rather old and out dated raster methods. They
-%D have not been used for ages. You can still find the old code in
-%D the \MKII\ counterpart of this module.
-
-%D This module is rather optimized so sometimes readability has been
-%D sacrisfied for speed. This is because the framing mechanism is used
-%D all over the place.
-
%D \macros
%D {linewidth, setuplinewidth}
%D
@@ -50,101 +41,276 @@
\newdimen\linewidth
-\def\dosetuplinewidth[#1]%
- {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
-
\unexpanded\def\setuplinewidth
- {\dosingleargument\dosetuplinewidth}
-
-%D \macros
-%D {ruledlinewidth, inheritruledlinewidth}
-%D
-%D Inside framed boxed we will use a private dimensions. As
-%D an option one can let the linewidth inherit its value from
-%D this one.
+ {\dosingleargument\pack_framed_setup_line_width}
-\newdimen\ruledlinewidth \newif\ifinheritruledlinewidth
+\def\pack_framed_setup_line_width[#1]%
+ {\assigndimension{#1}\linewidth{.2\points}{.4\points}{.6\points}}
%D \macros
%D {setupscreens}
%D
-%D The previous macro uses a predefined constant
-%D \type{\@@rsfactor}. This factor can be set by:
+%D Sort of obsolete:
%D
%D \showsetup{setupscreens}
\unexpanded\def\setupscreens
{\dodoubleargument\getparameters[\??rs]}
-%D We will communicate through module specific variables, current
-%D framed parameters and some reserved dimension registers.
+%D The parameter handler:
-\newdimen \frameddimenwd
-\newdimen \frameddimenht
-\newdimen \frameddimendp
+\installcorenamespace{framed}
+\installcorenamespace{framedtop}
+\installcorenamespace{framedbottom}
+\installcorenamespace{framedleft}
+\installcorenamespace{framedright}
-%D We don't have to stick to a \TEX\ drawn rule, but
-%D also can use rounded or even fancier shapes, as we will
-%D see later on.
+\let\currentframed\s!unknown % brrr must have a value
-\def\dofilledbox
- {\bgroup
- \edef\@@framedfilledmod{\framedparameter\c!backgroundcorner}%
- \ifx\@@framedfilledmod\v!rectangular
- \dofilledlinedbox
- \else\ifzeropt\dimexpr\framedparameter\c!backgroundradius\relax % just in case of .x\bodyfontsize
- \dofilledlinedbox
- \else
- \dofilledroundbox
- \fi\fi
- \egroup}
+% \def\framedparameter #1{\csname\doframedparameter\currentframed{#1}\endcsname}
+% \def\framedparameterhash#1{\doframedparameterhash \currentframed#1}
-\def\dophantombox
- {\hphantom{\dofilledbox}}
+\def\framedparameter #1{\csname\ifcsname\currentframed#1\endcsname\currentframed#1\else\expandafter\doframedparentparameter\csname\currentframed\s!parent\endcsname{#1}\fi\endcsname}
+\def\framedparameterhash#1{\ifcsname\currentframed#1\endcsname\currentframed\else\expandafter\doframedparentparameterhash\csname\currentframed\s!parent\endcsname#1\fi}
-\def\dofilledlinedbox
- {\vrule\!!width\frameddimenwd\!!height\frameddimenht\!!depth\frameddimendp\relax}%
+\def\doframedparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedparentparameter \csname#1\s!parent\endcsname{#2}\fi}
+\def\doframedparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doframedparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-\def\dostrokedroundbox
- {\doif{\framedparameter\c!frame}\v!on\dodostrokedroundbox}
+\def\doframedparentparameter #1#2{\ifx#1\relax\s!empty\else\doframedparameter #1{#2}\fi}
+\def\doframedparentparameterhash#1#2{\ifx#1\relax \else\doframedparameterhash#1#2\fi}
-\def\dodostrokedroundbox
- {\bgroup
- \edef\ovalmod{\framedparameter\c!framecorner}%
- \ifx\ovalmod\v!round
- \let\ovalmod\!!zerocount
+\def\doframedparentparameter#1#2{\ifx#1\relax\doframedrootparameter#2\else\doframedparameter#1{#2}\fi}
+\def\doframedrootparameter #1{\ifcsname\??framed#1\endcsname\??framed#1\else\s!empty\fi}
+
+\def\useframedstyleandcolor#1#2% style color
+ {\edef\currentstyleparameter{\framedparameter#1}%
+ \edef\currentcolorparameter{\framedparameter#2}%
+ \ifx\currentstyleparameter\empty\else\dousestyleparameter\currentstyleparameter\fi
+ \ifx\currentcolorparameter\empty\else\dousecolorparameter\currentcolorparameter\fi}
+
+\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax}
+
+% \unexpanded\def\installsomebackground#1#2{\inheritlocalframed[\??ma#1#2][\??od]}
+
+\let\normalframedparameter \framedparameter
+\let\normalframedparameterhash\framedparameterhash
+
+\def\pack_framed_initialize#1% will be inlined
+ {\inframedtrue
+ \edef\currentframed{#1}%
+ \let\framedparameter \normalframedparameter
+ \let\framedparameterhash\normalframedparameterhash}
+
+\def\installinheritedframed#1%
+ {\normalexpanded{\doinstallinheritedframed
+ \expandafter\noexpand\csname current#1\endcsname
+ \expandafter\noexpand\csname #1parameter\endcsname
+ \expandafter\noexpand\csname #1parameterhash\endcsname
+ \expandafter\noexpand\csname do#1parameter\endcsname
+ \expandafter\noexpand\csname do#1parentparameter\endcsname
+ \expandafter\noexpand\csname do#1rootparameter\endcsname
+ \expandafter\noexpand\csname inherited#1framed\endcsname
+ \noexpand\??framed}} % if needed we can have a variant
+
+\unexpanded\def\doinstallinheritedframed#1#2#3#4#5#6#7#8%
+ {\def#5##1##2{\ifx##1\relax#6{##2}\else#4##1{##2}\fi}%
+ \def#6##1{\ifcsname#8##1\endcsname#8##1\else\s!empty\fi}%
+ \unexpanded\def#7%
+ {\bgroup
+ \bgroup
+ \inframedtrue
+ \let\currentframed #1% not used (more for tracing)
+ \let\framedparameter #2%
+ \let\framedparameterhash#3%
+ \pack_framed_process_indeed}}
+
+\unexpanded\def\installframedcommandhandler#1#2#3%
+ {\installcommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+\unexpanded\def\installframedautocommandhandler#1#2#3%
+ {\installautocommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+\unexpanded\def\installsimpleframedcommandhandler#1#2#3%
+ {\installsimplecommandhandler{#1}{#2}{#3}%
+ \installinheritedframed{#2}}
+
+% for regular framed
+
+\getparameters
+ [\??framed]
+ [\c!width=\v!fit,
+ \c!height=\v!broad,
+ %\c!lines=,
+ \c!offset=0.25ex, % \defaultframeoffset
+ \c!empty=\v!no,
+ \c!frame=\v!on,
+ %\c!topframe=,
+ %\c!bottomframe=,
+ %\c!leftframe=,
+ %\c!rightframe=,
+ \c!radius=.5\bodyfontsize,
+ \c!rulethickness=\linewidth,
+ \c!corner=\v!rectangular,
+ \c!depth=\zeropoint,
+ %\c!foregroundcolor=,
+ %\c!foregroundstyle=,
+ %\c!background=,
+ %\c!backgroundscreen=,
+ %\c!backgroundcolor=,
+ \c!backgroundoffset=\zeropoint,
+ %\c!framecolor=,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner,
+ \c!backgroundradius=\framedparameter\c!radius,
+ \c!backgrounddepth=\framedparameter\c!depth,
+ \c!framecorner=\framedparameter\c!corner,
+ \c!frameradius=\framedparameter\c!radius,
+ \c!framedepth=\framedparameter\c!depth,
+ %\c!component=,
+ %\c!region=,
+ %\c!align=,
+ \c!bottom=\vss,
+ %\c!top=,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!yes,
+ \c!location=\v!normal,
+ %\c!orientation=,
+ \c!autowidth=\v!yes,
+ %\c!setups=
+ \c!loffset=\zeropoint,
+ \c!roffset=\zeropoint,
+ \c!toffset=\zeropoint,
+ \c!boffset=\zeropoint]
+
+% for backgrounds
+
+\getparameters
+ [\??od] % for fast version
+ [\c!frame=\v!off,
+ \c!depth=\zeropoint,
+ \c!offset=\v!overlay,
+ %\c!component=,
+ %\c!region=,
+ \c!radius=.5\bodyfontsize,
+ \c!rulethickness=\linewidth,
+ \c!corner=\v!rectangular,
+ \c!backgroundoffset=\zeropoint,
+ \c!frameoffset=\zeropoint,
+ \c!backgroundcorner=\framedparameter\c!corner,
+ \c!backgroundradius=\framedparameter\c!radius,
+ \c!backgrounddepth=\framedparameter\c!depth,
+ \c!framecorner=\framedparameter\c!corner,
+ \c!frameradius=\framedparameter\c!radius,
+ \c!framedepth=\framedparameter\c!depth,
+ \c!location=\v!normal,
+ \c!loffset=\zeropoint,
+ \c!roffset=\zeropoint,
+ \c!toffset=\zeropoint,
+ \c!boffset=\zeropoint]
+
+%D We will communicate through module specific variables, current
+%D framed parameters and some reserved dimension registers.
+
+\newdimen\d_framed_target_wd
+\newdimen\d_framed_target_ht
+\newdimen\d_framed_target_dp
+\newdimen\d_framed_linewidth
+
+\let\p_framed_frame \empty % \framedparameter\c!frame
+\let\p_framed_backgroundoffset\empty
+\let\p_framed_foregroundstyle \empty
+\let\p_framed_autostrut \empty
+\let\p_framed_location \empty
+\let\p_framed_orientation \empty
+\let\p_framed_autowidth \empty
+\let\p_framed_franalyze \empty
+\let\p_framed_backgroundcorner\empty
+\let\p_framed_backgroundradius\empty
+\let\p_framed_framecorner \empty
+\let\p_framed_frameradius \empty
+\let\p_framed_lines \empty
+\let\p_framed_empty \empty
+\let\p_framed_backgroundcolor \empty
+\let\p_framed_backgroundscreen\empty
+\let\p_framed_framecolor \empty
+\let\p_framed_component \empty
+\let\p_framed_region \empty
+\let\p_framed_background \empty
+\let\p_framed_rulethickness \empty
+\let\p_framed_foregroundcolor \empty
+\let\p_framed_setups \empty
+
+%D We don't have to stick to a \TEX\ drawn rule, but also can use rounded
+%D or even fancier shapes, as we will see later on.
+
+\def\pack_framed_filled_box
+ {\edef\p_framed_backgroundcorner{\framedparameter\c!backgroundcorner}%
+ \ifx\p_framed_backgroundcorner\v!rectangular
+ \pack_framed_filled_box_normal
\else
- \edef\ovalmod{\number\ovalmod}%
- \fi
- \edef\ovalwid{\the\frameddimenwd}%
- \edef\ovalhei{\the\frameddimenht}%
- \edef\ovaldep{\the\frameddimendp}%
- \edef\ovallin{\the\dimexpr\ruledlinewidth}%
- \edef\ovalrad{\the\dimexpr\framedparameter\c!frameradius}%
- \let\ovalstr\!!plusone
- \let\ovalfil\!!zerocount
-% \forcecolorhack
- \doovalbox\ovalwid\ovalhei\ovaldep\ovallin\ovalrad\ovalstr\ovalfil\ovalmod
- \egroup}
+ \pack_framed_filled_box_radius
+ \fi}
-\def\dofilledroundbox
- {\bgroup
- \edef\ovalmod{\framedparameter\c!backgroundcorner}%
- \ifx\ovalmod\v!round
- \let\ovalmod\!!zerocount
+\def\pack_framed_filled_box_normal
+ {\vrule
+ \!!width \d_framed_target_wd
+ \!!height\d_framed_target_ht
+ \!!depth \d_framed_target_dp
+ \relax}
+
+\def\pack_framed_filled_box_radius
+ {\edef\p_framed_backgroundradius{\framedparameter\c!backgroundradius}%
+ \ifzeropt\dimexpr\p_framed_backgroundradius\relax % just in case of .x\bodyfontsize
+ \pack_framed_filled_box_normal
\else
- \edef\ovalmod{\number\ovalmod}%
- \fi
- \edef\ovalwid{\the\frameddimenwd}%
- \edef\ovalhei{\the\frameddimenht}%
- \edef\ovaldep{\the\frameddimendp}%
- \edef\ovallin{\the\dimexpr\ruledlinewidth\relax}%
- \edef\ovalrad{\the\dimexpr\framedparameter\c!backgroundradius\relax}%
- \let\ovalstr\!!zerocount
- \let\ovalfil\!!plusone
-% \forcecolorhack
- \doovalbox\ovalwid\ovalhei\ovaldep\ovallin\ovalrad\ovalstr\ovalfil\ovalmod
- \egroup}
+ \pack_framed_filled_box_round
+ \fi}
+
+\def\pack_framed_filled_box_round
+ {\normalexpanded{\doovalbox
+ {\the\d_framed_target_wd}%
+ {\the\d_framed_target_ht}%
+ {\the\d_framed_target_dp}%
+ {\the\dimexpr\d_framed_linewidth\relax}%
+ {\the\dimexpr\p_framed_backgroundradius\relax}%
+ {0}%
+ {1}%
+ {\ifx\p_framed_backgroundcorner\v!round0\else\number\p_framed_backgroundcorner\fi}%
+ }}
+
+\def\pack_framed_stroked_box
+ {\edef\p_framed_framecorner{\framedparameter\c!framecorner}%
+ \ifx\p_framed_framecorner\v!rectangular
+ \pack_framed_stroked_box_normal
+ \else
+ \pack_framed_stroked_box_radius
+ \fi}
+
+\def\pack_framed_stroked_box_radius
+ {\edef\p_framed_frameradius{\framedparameter\c!frameradius}%
+ \ifzeropt\dimexpr\p_framed_frameradius\relax % just in case of .x\bodyfontsize
+ \pack_framed_stroked_box_normal
+ \else
+ \ifx\p_framed_frame\v!on
+ \pack_framed_stroked_box_round
+ \fi
+ \fi}
+
+% \pack_framed_stroked_box_normal % later
+
+\def\pack_framed_stroked_box_round
+ {\normalexpanded{\doovalbox
+ {\the\d_framed_target_wd}%
+ {\the\d_framed_target_ht}%
+ {\the\d_framed_target_dp}%
+ {\the\dimexpr\d_framed_linewidth\relax}%
+ {\the\dimexpr\p_framed_frameradius\relax}%
+ {1}%
+ {0}%
+ {\ifx\p_framed_framecorner\v!round0\else\number\p_framed_framecorner\fi}%
+ }}
% a lot of weird corners
%
@@ -195,30 +361,27 @@
%D The oval box is drawn using a special macro, depending on
%D the driver in use.
-\def\dograybox % avoid black rules when no gray
- {\doifelsenothing{\framedparameter\c!backgroundscreen}
- {\dophantombox}
- {\raster[\framedparameter\c!backgroundscreen]{\dofilledbox}}}
+\def\pack_framed_background_box_gray % avoid black rules when no gray
+ {\edef\p_framed_backgroundscreen{\framedparameter\c!backgroundscreen}%
+ \ifx\p_framed_backgroundscreen\empty \else
+ \pack_framed_background_box_gray_indeed
+ \fi}
+
+\def\pack_framed_background_box_gray_indeed % can be more direct but who cares, just compatibility
+ {\colored[s=\p_framed_backgroundscreen]{\pack_framed_filled_box}}
%D It won't be a surprise that we not only provide gray boxes,
%D but also colored ones. Here it is:
-\def\dobackgroundcolorbox
- {\hbox{\faststartcolor[\framedbackgroundcolor]\dofilledbox\faststopcolor}}
- %{\hbox{\doactivatecolor\framedbackgroundcolor\dofilledbox}}
-
-\def\docolorbox % can be more of \color[] -> \faststartcolor in mkiv
- {\ifincolor
- \edef\framedbackgroundcolor{\framedparameter\c!backgroundcolor}%
- \ifx\framedbackgroundcolor\empty
- \dophantombox
- \else
- \doifcolorelse\framedbackgroundcolor\dobackgroundcolorbox\dophantombox
- \fi
- \else
- \dophantombox
+\def\pack_framed_background_box_color
+ {\edef\p_framed_backgroundcolor{\framedparameter\c!backgroundcolor}%
+ \ifx\p_framed_backgroundcolor\empty \else
+ \doifcolor\p_framed_backgroundcolor\pack_framed_background_box_color_indeed
\fi}
+\def\pack_framed_background_box_color_indeed
+ {\hbox{\dousecolorparameter\p_framed_backgroundcolor\pack_framed_filled_box}}
+
%D \macros
%D {defineoverlay, doifoverlayelse, overlayoffset,
%D overlaywidth, overlayheight, overlaydepth,
@@ -279,11 +442,11 @@
\def\overlaywidth {\the\hsize\space} % We preset the variables
\def\overlayheight {\the\vsize\space} % to some reasonable default
-\let\overlaydepth \!!zeropoint % values. The attributes
-\let\overlayoffset \!!zeropoint % of the frame can be (are)
-\let\overlaycolor \empty % set somewhere else.
-\let\overlaylinewidth \!!zeropoint %
-\let\overlaylinecolor \empty %
+\def\overlaydepth {0pt } % values. The attributes
+\let\overlayoffset \overlaydepth % of the frame can be (are)
+\let\overlaylinewidth \overlaydepth % set somewhere else.
+\let\overlaycolor \empty
+\let\overlaylinecolor \empty
%D The next register is used to initialize overlays.
@@ -293,148 +456,182 @@
%D can contain text and be executed under an regime where
%D interlineskip is off).
-\appendtoks \oninterlineskip \to \everyoverlay
-
-\unexpanded\def\defineoverlay
- {\dodoubleargument\dodefineoverlay}
+\installcorenamespace{overlay}
+\installcorenamespace{overlaybuiltin}
-\def\dodefineoverlay[#1][#2]%
- {\def\docommand##1{\setvalue{\??ov##1}{\executedefinedoverlay{##1}{#2}}}%
- \processcommalist[#1]\docommand}
+\appendtoks
+ \oninterlineskip
+\to \everyoverlay
\prependtoks
- \hsize\overlaywidth
- \vsize\overlayheight
-\to\everyoverlay
+ \hsize\overlaywidth
+ \vsize\overlayheight
+\to \everyoverlay
-\long\def\executedefinedoverlay#1#2%
- {\bgroup
- \setlayoutcomponentattribute\v!overlay{#1}%
- \edef\overlaywidth {\the\frameddimenwd\space}%
- \edef\overlayheight{\the\dimexpr\frameddimenht+\frameddimendp\relax\space}%
- \edef\overlaydepth {\the\frameddimendp\space}%
- \edef\overlaycolor {\framedparameter\c!backgroundcolor}%
- %\edef\overlaycorner{\framedparameter\c!backgroundcorner}%
- %\edef\overlayradius{\framedparameter\c!backgroundradius}%
- \let\overlayoffset\backgroundoffset % we steal this one
- \setbox\scratchbox\hbox{\lower\overlaydepth\hbox{\the\everyoverlay#2}}%
+\unexpanded\def\defineoverlay
+ {\dodoubleargument\pack_framed_define_overlay}
+
+\def\pack_framed_define_overlay[#1][#2]%
+ {\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
+ {\bgroup % redundant grouping
+ \setbox\scratchbox\hbox\bgroup
+ \ifzeropt\d_framed_target_dp
+ \the\everyoverlay#2% saves wrapping (and lua call)
+ \else
+ \lower\d_framed_target_dp
+ \hbox{\the\everyoverlay#2}%
+ \fi
+ \egroup
+ \setlayoutcomponentattribute{\v!overlay:#1}%
\setbox\scratchbox\hbox \layoutcomponentboxattribute
- {\hskip-.5\dimexpr\wd\scratchbox-\overlaywidth \relax
- \raise-.5\dimexpr\ht\scratchbox-\frameddimenht\relax % not overlayheight !
+ {\kern -.5\dimexpr\wd\scratchbox-\d_framed_target_wd\relax % was \overlaywidth
+ \raise-.5\dimexpr\ht\scratchbox-\d_framed_target_ht\relax % not \overlayheight !
\box\scratchbox}%
- \wd\scratchbox\frameddimenwd
- \ht\scratchbox\frameddimenht
- \dp\scratchbox\frameddimendp
+ \wd\scratchbox\d_framed_target_wd
+ \ht\scratchbox\d_framed_target_ht
+ \dp\scratchbox\d_framed_target_dp
\box\scratchbox
\egroup}
%D \macros
%D {overlayfakebox}
-\def\overlayfakebox
+\unexpanded\def\overlayfakebox
{\hbox
{\setbox\scratchbox\emptyhbox
\wd\scratchbox\overlaywidth
\ht\scratchbox\overlayheight
\box\scratchbox}}
-%D The empty case is:
-
-\let\executeoverlay\gobblesevenarguments
-
%D For testing we provide:
-\def\doifoverlayelse#1%
- {\ifcsname\??ov#1\endcsname
+\def\doifoverlayelse#1% only tests external overlays
+ {\ifcsname\??overlay#1\endcsname
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-%D We predefine two already familiar backgrounds:
-
-\setvalue{\??ov\v!screen}{\dograybox }
-\setvalue{\??ov\v!color }{\docolorbox}
-
-% %D After all these preparations, the background macro does no
-% %D bring to many surprises. One has to keep in mind that this
-% %D macro starts up a call chain, depending on the background
-% %D one needs:
-% %D
-% %D \startitemize[packed]
-% %D \item a raster, color or user defined shape
-% %D \item square or round corners
-% %D \item a \TEX\ or driver based method
-% %D \stopitemize
-% %D
-% %D The macro can be extended by adding commands to the token
-% %D list register \type {\everybackgroundbox}. For this
-% %D purpose, the name of the current background is available in
-% %D \type {\currentbackgound}.
-
%D The content of the box will be (temporary) saved in a box. We
%D also have an extra box for backgrounds.
-\newbox\framebox
-\newbox\extraframebox
+\newbox\b_framed_normal
+\newbox\b_framed_extra
\newtoks\everybackgroundbox
\let\currentbackground\empty
-\def\dodobackgroundbox
+\def\pack_framed_process_background
+ {\ifcsname\??overlaybuiltin\currentbackground\endcsname
+ \pack_framed_process_background_indeed_internal
+ \else\ifcsname\??overlay\currentbackground\endcsname
+ \pack_framed_process_background_indeed_external
+ \fi\fi}
+
+\def\pack_framed_process_background_indeed_internal % : in name
{\bgroup
- \ifcsname\??ov\currentbackground\endcsname
- \the\everybackgroundbox
- \setbox\extraframebox\hbox{\vbox{\moveleft\backgroundoffset\hbox{\csname\??ov\currentbackground\endcsname}}}%
- \wd\extraframebox\zeropoint % \backgroundwidth
- \ht\extraframebox\backgroundheight
- \dp\extraframebox\backgrounddepth
- \box\extraframebox % \hskip-\backgroundwidth
- \fi
+ \setbox\b_framed_extra\hbox{%\bgroup
+ \ifzeropt\framedbackgroundoffset
+ \csname\??overlaybuiltin\currentbackground\endcsname
+ \else
+ \kern-\framedbackgroundoffset
+ \hbox{\csname\??overlaybuiltin\currentbackground\endcsname}%
+ \fi
+ }%\egroup
+ \wd\b_framed_extra\zeropoint
+ \ht\b_framed_extra\framedbackgroundheight
+ \dp\b_framed_extra\framedbackgrounddepth
+ \box\b_framed_extra
+ \egroup}
+
+\def\pack_framed_process_background_indeed_external
+ {\pack_framed_overlay_initialize
+ \bgroup
+ \setbox\b_framed_extra\hbox{%\bgroup
+ \ifzeropt\framedbackgroundoffset
+ \csname\??overlay\currentbackground\endcsname
+ \else
+ \kern-\framedbackgroundoffset
+ \hbox{\csname\??overlay\currentbackground\endcsname}%
+ \fi
+ }%\egroup
+ \wd\b_framed_extra\zeropoint
+ \ht\b_framed_extra\framedbackgroundheight
+ \dp\b_framed_extra\framedbackgrounddepth
+ \box\b_framed_extra
\egroup}
-\def\dododobackgroundbox#1,#2% #2 gobbles spaces
+\def\pack_framed_process_backgrounds#1,#2% #2 gobbles spaces (we could avoid one catch if we have nextbackground)
{\edef\currentbackground{#1}%
- \ifx\currentbackground\s!unknown\else % use $ instead of s!unknown
- \dodobackgroundbox\expandafter\dododobackgroundbox
+ \ifx\currentbackground\s!unknown\else
+ \pack_framed_process_background
+ \expandafter\pack_framed_process_backgrounds
\fi#2}
-\let\backgroundoffset\!!zeropoint
-\let\backgrounddepth \!!zeropoint
-\def\backgroundwidth {\the\hsize}
-\def\backgroundheight{\the\vsize}
+% beware, a backgroundbox can be empty which is another reason
+% why we set the width to zero instead of back-skipping
-\def\normalforegroundbox% fuzzy but needed hack, this \vss, otherwise
- {\vbox to \backgroundheight{\vss\box\framebox\vss}}% vertical shift
+\newdimen\framedbackgroundwidth
+\newdimen\framedbackgroundheight
+\newdimen\framedbackgrounddepth
+\newdimen\framedbackgroundoffset
-\def\dobackedbox
- {\setbox\framebox\vbox
- {\framedforgetall
+\def\pack_framed_background_box_content% fuzzy but needed hack, this \vss, otherwise
+ {\vbox to \framedbackgroundheight{\vss\box\b_framed_normal\vss}} % vertical shift \backgroundheight
+
+\def\pack_framed_add_region % experiment
+ {\anch_mark_region_box\b_framed_normal}
+
+\def\pack_framed_add_background
+ {\setbox\b_framed_normal\hbox % was vbox
+ {\pack_framed_forgetall % can be relaxed
\boxmaxdepth\maxdimen
- \frameddimenwd\dimexpr\wd\framebox+2\!!framedbackgroundoffset\relax
- \frameddimenht\dimexpr\ht\framebox+ \!!framedbackgroundoffset\relax
- \frameddimendp\dimexpr\dp\framebox+ \!!framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax
- \edef\backgroundoffset{\the\!!framedbackgroundoffset}%
- \edef\backgroundwidth {\the\wd\framebox}%
- \edef\backgroundheight{\the\ht\framebox}%
- \edef\backgrounddepth {\the\dp\framebox}%
- %\edef\foregroundbox{\box#1}%
- \edef\component{\framedparameter\c!component}%
- \ifx\component\empty
+ \framedbackgroundoffset\d_framed_backgroundoffset
+ \framedbackgroundwidth \wd\b_framed_normal
+ \framedbackgroundheight\ht\b_framed_normal
+ \framedbackgrounddepth \dp\b_framed_normal
+ \d_framed_target_wd\dimexpr\framedbackgroundwidth +2\framedbackgroundoffset\relax
+ \d_framed_target_ht\dimexpr\framedbackgroundheight+ \framedbackgroundoffset\relax
+ \d_framed_target_dp\dimexpr\framedbackgrounddepth + \framedbackgroundoffset+\framedparameter\c!backgrounddepth\relax
+ \let\pack_framed_overlay_initialize\pack_framed_overlay_initialize_indeed
+ \ifx\p_framed_component\empty
\resetlayoutcomponentattribute
\else
- \setlayoutcomponentattribute\v!background\component
+ \setlayoutcomponentattribute{\v!background:\p_framed_component}%
\fi
- \let\foregroundbox\normalforegroundbox
- \hbox \layoutcomponentboxattribute to \backgroundwidth % width in case 'foreground' is used as overlay
- {\expandafter\dododobackgroundbox\framedbackground,\s!unknown,\relax % hm, messy .. look into it
- \box\framebox\hss}}}
+ \let\foregroundbox\pack_framed_background_box_content
+ \hbox \layoutcomponentboxattribute to \framedbackgroundwidth\bgroup % width in case 'foreground' is used as overlay
+ \the\everybackgroundbox % moved
+ \expandafter\pack_framed_process_backgrounds\p_framed_background,\s!unknown,\relax % hm, messy .. look into it
+ \box\b_framed_normal
+ \hss
+ \egroup}}
+
+\def\pack_framed_overlay_initialize_indeed
+ {%\writestatus{!!!!}{<<<<<}%
+ \edef\overlaywidth {\the\d_framed_target_wd\space}%
+ \edef\overlayheight {\the\dimexpr\d_framed_target_ht+\d_framed_target_dp\relax\space}%
+ \edef\overlaydepth {\the\d_framed_target_dp\space}%
+ \edef\overlaycolor {\framedparameter\c!backgroundcolor}% let ?
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}% only needed for layers
+ \edef\overlaylinewidth{\the\d_framed_linewidth\space}%
+ %\edef\overlaycorner {\framedparameter\c!backgroundcorner}%
+ %\edef\overlayradius {\framedparameter\c!backgroundradius}%
+ \edef\overlayoffset {\the\framedbackgroundoffset\space}% \backgroundoffset % we steal this one
+ \let\pack_framed_overlay_initialize\relax}
%D One can explictly insert the foreground box. For that
%D purpose we introduce the overlay \type {foreground}.
+%D
+%D We predefine two already familiar backgrounds:
-\defineoverlay[\v!foreground][\foregroundbox]
+\letvalue{\??overlaybuiltin\v!screen }\pack_framed_background_box_gray
+\letvalue{\??overlaybuiltin\v!color }\pack_framed_background_box_color
+\letvalue{\??overlaybuiltin\v!foreground}\pack_framed_background_box_content % replaces: \defineoverlay[\v!foreground][\foregroundbox]
%D We can specify overlays as a comma separated list of
%D overlays, a sometimes handy feature.
@@ -445,122 +642,94 @@
%D by \TEX\ itself, the latter one depends on the driver. This
%D macro also support a negative offset.
-\def\dooutlinebox % we needed to move the color command in order to apply attributes properly
- {\setbox\framebox\vbox % rules on top of box
- {\frameddimenwd\dimexpr\wd\framebox+2\!!framedframeoffset\relax
- \frameddimenht\dimexpr\ht\framebox+ \!!framedframeoffset\relax
- \frameddimendp\dimexpr\dp\framebox+ \!!framedframeoffset+\framedparameter\c!framedepth\relax
- \ifdim\frameddimendp<\zeropoint
- \advance\frameddimenht \frameddimendp
- \scratchdimen-\frameddimendp
- \frameddimendp\zeropoint
+\def\pack_framed_add_outline
+ {\setbox\b_framed_normal\hbox % rules on top of box
+ {\d_framed_target_wd\dimexpr\wd\b_framed_normal+2\d_framed_frameoffset\relax
+ \d_framed_target_ht\dimexpr\ht\b_framed_normal+ \d_framed_frameoffset\relax
+ \d_framed_target_dp\dimexpr\dp\b_framed_normal+ \d_framed_frameoffset+\framedparameter\c!framedepth\relax
+ \ifdim\d_framed_target_dp<\zeropoint
+ \advance\d_framed_target_ht \d_framed_target_dp
+ \scratchdimen-\d_framed_target_dp
+ \d_framed_target_dp\zeropoint
\else
\scratchdimen\zeropoint
\fi
- \setbox\extraframebox\hbox
- {\doifsomething{\framedparameter\c!framecolor}{\color[\framedparameter\c!framecolor]}{\dostrokedbox}}%
- \setbox\extraframebox\hbox
- {\raise\scratchdimen\vbox
- {\moveleft\!!framedframeoffset
- \box\extraframebox}}%
- \wd\extraframebox\wd\framebox
- \ht\extraframebox\ht\framebox
- \dp\extraframebox\dp\framebox
- \hbox{\box\framebox\hskip-\wd\extraframebox\box\extraframebox}}}
-
-\def\dostrokedbox
- {\edef\@@framedcornermod{\framedparameter\c!framecorner}%
- \ifx\@@framedcornermod\v!rectangular
- \dostrokedlinedbox
- \else\ifzeropt\dimexpr\framedparameter\c!frameradius\relax % just in case of .x\bodyfontsize
- \dostrokedlinedbox
- \else
- \dostrokedroundbox
- \fi\fi}
-
-\def\dostrokedlinedbox
+ \edef\overlaylinecolor{\framedparameter\c!framecolor}% twice, also in background
+ \setbox\b_framed_extra\hbox
+ {\kern-\d_framed_frameoffset
+ \raise\scratchdimen
+ \hbox{\ifx\overlaylinecolor\empty\else\dousecolorparameter\overlaylinecolor\fi\pack_framed_stroked_box}}%
+ \wd\b_framed_extra\wd\b_framed_normal
+ \ht\b_framed_extra\ht\b_framed_normal
+ \dp\b_framed_extra\dp\b_framed_normal
+ \wd\b_framed_normal\zeropoint
+ \box\b_framed_normal
+ \box\b_framed_extra}}
+
+\def\pack_framed_stroked_box_normal
{\setbox\scratchbox\emptyhbox
- \wd\scratchbox\frameddimenwd
- \ht\scratchbox\frameddimenht
- \dp\scratchbox\frameddimendp
+ \wd\scratchbox\d_framed_target_wd
+ \ht\scratchbox\d_framed_target_ht
+ \dp\scratchbox\d_framed_target_dp
\setbox\scratchbox\vbox \bgroup
- \csname t\@@frame@@\framedparameter\c!frame\framedparameter\c!topframe \endcsname
+ \csname \??framedtop\p_framed_frame\framedparameter\c!topframe \endcsname
+ \nointerlineskip % new (needed for fences)
\hbox \bgroup
- \csname l\@@frame@@\framedparameter\c!frame\framedparameter\c!leftframe \endcsname
+ \csname \??framedleft\p_framed_frame\framedparameter\c!leftframe \endcsname
\box\scratchbox
- \csname r\@@frame@@\framedparameter\c!frame\framedparameter\c!rightframe \endcsname
+ \csname \??framedright\p_framed_frame\framedparameter\c!rightframe \endcsname
\egroup
- \csname b\@@frame@@\framedparameter\c!frame\framedparameter\c!bottomframe\endcsname
+ \nointerlineskip % new (needed for fences)
+ \csname \??framedbottom\p_framed_frame\framedparameter\c!bottomframe\endcsname
\egroup
- \wd\scratchbox\frameddimenwd
- \ht\scratchbox\frameddimenht
- \dp\scratchbox\frameddimendp
+ \wd\scratchbox\d_framed_target_wd
+ \ht\scratchbox\d_framed_target_ht
+ \dp\scratchbox\d_framed_target_dp
\box\scratchbox}
-\def\@@frame@@{@@frame@@}
-
-% \setvalue{t\@@frame@@\v!on \v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
-% \setvalue{t\@@frame@@\v!off\v!on}{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
-% \setvalue{t\@@frame@@\v!on }{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
-% \setvalue{b\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
-% \setvalue{b\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
-% \setvalue{b\@@frame@@\v!on }{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
-% \setvalue{l\@@frame@@\v!on \v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
-% \setvalue{l\@@frame@@\v!off\v!on}{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
-% \setvalue{l\@@frame@@\v!on }{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
-% \setvalue{r\@@frame@@\v!on \v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
-% \setvalue{r\@@frame@@\v!off\v!on}{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
-% \setvalue{r\@@frame@@\v!on }{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
-
-\def\@@frame@@trule{\hrule\!!height\ruledlinewidth\kern-\ruledlinewidth}
-\def\@@frame@@brule{\kern-\ruledlinewidth\hrule\!!height\ruledlinewidth}
-\def\@@frame@@rrule{\kern-\ruledlinewidth\vrule\!!width\ruledlinewidth}
-\def\@@frame@@lrule{\vrule\!!width\ruledlinewidth\kern-\ruledlinewidth}
-
-\letvalue{t\@@frame@@\v!on \v!on}\@@frame@@trule
-\letvalue{t\@@frame@@\v!off\v!on}\@@frame@@trule
-\letvalue{t\@@frame@@\v!on }\@@frame@@trule
-
-\letvalue{b\@@frame@@\v!on \v!on}\@@frame@@brule
-\letvalue{b\@@frame@@\v!off\v!on}\@@frame@@brule
-\letvalue{b\@@frame@@\v!on }\@@frame@@brule
-
-\letvalue{l\@@frame@@\v!on \v!on}\@@frame@@lrule
-\letvalue{l\@@frame@@\v!off\v!on}\@@frame@@lrule
-\letvalue{l\@@frame@@\v!on }\@@frame@@lrule
-
-\letvalue{r\@@frame@@\v!on \v!on}\@@frame@@rrule
-\letvalue{r\@@frame@@\v!off\v!on}\@@frame@@rrule
-\letvalue{r\@@frame@@\v!on }\@@frame@@rrule
+\def\pack_framed_t_rule{\hrule\!!height\d_framed_linewidth\kern-\d_framed_linewidth}
+\def\pack_framed_b_rule{\kern-\d_framed_linewidth\hrule\!!height\d_framed_linewidth}
+\def\pack_framed_r_rule{\kern-\d_framed_linewidth\vrule\!!width\d_framed_linewidth}
+\def\pack_framed_l_rule{\vrule\!!width\d_framed_linewidth\kern-\d_framed_linewidth}
-% no overlapping rules
+\letvalue{\??framedtop \v!on \v!on}\pack_framed_t_rule
+\letvalue{\??framedtop \v!off\v!on}\pack_framed_t_rule
+\letvalue{\??framedtop \v!on }\pack_framed_t_rule
+
+\letvalue{\??framedbottom\v!on \v!on}\pack_framed_b_rule
+\letvalue{\??framedbottom\v!off\v!on}\pack_framed_b_rule
+\letvalue{\??framedbottom\v!on }\pack_framed_b_rule
-\def\@@frame@@trules{\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}\nointerlineskip\kern-\ruledlinewidth}
-\def\@@frame@@brules{\kern-\ruledlinewidth\nointerlineskip\hbox{\kern\ruledlinewidth\vrule\!!width\dimexpr\frameddimenwd-2\ruledlinewidth\relax\!!height\ruledlinewidth}}
-\def\@@frame@@rrules{\kern-\ruledlinewidth\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth}
-\def\@@frame@@lrules{\vrule\!!height\dimexpr\frameddimenht-\ruledlinewidth\relax\!!depth-\ruledlinewidth\!!width\ruledlinewidth\kern-\ruledlinewidth}
+\letvalue{\??framedleft \v!on \v!on}\pack_framed_l_rule
+\letvalue{\??framedleft \v!off\v!on}\pack_framed_l_rule
+\letvalue{\??framedleft \v!on }\pack_framed_l_rule
-% small is relatively new
+\letvalue{\??framedright \v!on \v!on}\pack_framed_r_rule
+\letvalue{\??framedright \v!off\v!on}\pack_framed_r_rule
+\letvalue{\??framedright \v!on }\pack_framed_r_rule
-\letvalue{t\@@frame@@\v!small\v!small}\@@frame@@trules
-\letvalue{t\@@frame@@\v!off \v!small}\@@frame@@trules
-\letvalue{t\@@frame@@\v!small }\@@frame@@trules
+% no overlapping rules
-\letvalue{b\@@frame@@\v!small\v!small}\@@frame@@brules
-\letvalue{b\@@frame@@\v!off \v!small}\@@frame@@brules
-\letvalue{b\@@frame@@\v!small }\@@frame@@brules
+\def\pack_framed_t_rules{\hbox{\kern\d_framed_linewidth\vrule\!!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\!!height\d_framed_linewidth}\nointerlineskip\kern-\d_framed_linewidth}
+\def\pack_framed_b_rules{\kern-\d_framed_linewidth\nointerlineskip\hbox{\kern\d_framed_linewidth\vrule\!!width\dimexpr\d_framed_target_wd-2\d_framed_linewidth\relax\!!height\d_framed_linewidth}}
+\def\pack_framed_r_rules{\kern-\d_framed_linewidth\vrule\!!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\!!depth-\d_framed_linewidth\!!width\d_framed_linewidth}
+\def\pack_framed_l_rules{\vrule\!!height\dimexpr\d_framed_target_ht-\d_framed_linewidth\relax\!!depth-\d_framed_linewidth\!!width\d_framed_linewidth\kern-\d_framed_linewidth}
-\letvalue{l\@@frame@@\v!small\v!small}\@@frame@@lrules
-\letvalue{l\@@frame@@\v!off \v!small}\@@frame@@lrules
-\letvalue{l\@@frame@@\v!small }\@@frame@@lrules
+\letvalue{\??framedtop \v!small\v!small}\pack_framed_t_rules
+\letvalue{\??framedtop \v!off \v!small}\pack_framed_t_rules
+\letvalue{\??framedtop \v!small }\pack_framed_t_rules
-\letvalue{r\@@frame@@\v!small\v!small}\@@frame@@rrules
-\letvalue{r\@@frame@@\v!off \v!small}\@@frame@@rrules
-\letvalue{r\@@frame@@\v!small }\@@frame@@rrules
+\letvalue{\??framedbottom\v!small\v!small}\pack_framed_b_rules
+\letvalue{\??framedbottom\v!off \v!small}\pack_framed_b_rules
+\letvalue{\??framedbottom\v!small }\pack_framed_b_rules
-%D I condidered using the low level support command
-%D \type{\ruledhbox}, but this would slow down processing by a
-%D factor~3.
+\letvalue{\??framedleft \v!small\v!small}\pack_framed_l_rules
+\letvalue{\??framedleft \v!off \v!small}\pack_framed_l_rules
+\letvalue{\??framedleft \v!small }\pack_framed_l_rules
+
+\letvalue{\??framedright \v!small\v!small}\pack_framed_r_rules
+\letvalue{\??framedright \v!off \v!small}\pack_framed_r_rules
+\letvalue{\??framedright \v!small }\pack_framed_r_rules
% \framed
% [width=4cm,height=3cm,rulethickness=3mm,
@@ -581,20 +750,18 @@
%D start with defining some booleans. These give an impression
%D of what we are going to take into account.
-\newif\ifboxhasoffset
-\newif\ifboxhaswidth
-\newif\ifboxhasheight
-\newif\ifboxhasformat
-\newif\ifboxhasstrut
-\newif\ifboxisoverlaid
-\newif\ifboxhasframe
-\newif\ifdelayedstrut
-\newif\ifboxhasextraoffset
-
-%D We also need a few \DIMENSIONS:
+% todo : \c_framed_hasoffset
+% faster : \let\c_framed_hasoffset\falseconditional
-\newdimen\@@localoffset
-\newdimen\@@globalwidth
+\newconditional\c_framed_has_offset
+\newconditional\c_framed_has_width
+\newconditional\c_framed_has_height
+\newconditional\c_framed_has_format
+\newconditional\c_framed_has_strut
+\newconditional\c_framed_is_overlaid
+\newconditional\c_framed_has_frame
+\newconditional\c_framed_has_extra_offset
+\newconditional\c_framed_text_location_none
%D \macros
%D {framed, setupframed}
@@ -616,9 +783,8 @@
\def\defaultframeoffset{.25ex}
-\def\presetlocalframed [#1]{\letvalue{#1\s!parent}\??oi}
-\def\inheritlocalframed[#1]#2[#3]{\letvalue{#1\s!parent}#3}
-\def\copylocalframed [#1]#2[#3]{\setvalue{#1\s!parent}{#3}}
+\def\presetlocalframed [#1]{\letvalue {#1\s!parent}\??framed}
+\def\inheritlocalframed[#1]#2[#3]{\setevalue{#1\s!parent}{#3}}
\presetlocalframed[\??ol]
@@ -628,17 +794,28 @@
{\bgroup
\advance\framednesting\plusone
\expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol
- \dodoubleempty\dolocalframed[\??ol:\the\framednesting]}
+ \dodoubleempty\pack_framed_process[\??ol:\the\framednesting]}
+
+\unexpanded\def\startframed
+ {\dosingleempty\pack_framed_start_framed}
+
+\def\pack_framed_start_framed[#1]%
+ {\bgroup
+ \advance\framednesting\plusone
+ \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol
+ \pack_framed_process[\??ol:\the\framednesting][#1]%
+ \bgroup}
+
+\let\stopframed\egroup
\unexpanded\def\setupframed
{\dodoubleempty\dosetupframed}
-% \def\dosetupframed
-% {\ifsecondargument
-% \@EA\dodoublesetupframed
-% \else
-% \@EA\dosinglesetupframed
-% \fi}
+\unexpanded\def\normalframedwithsettings
+ {\bgroup
+ \advance\framednesting\plusone
+ \expandafter\let\csname\??ol:\the\framednesting\s!parent\endcsname\??ol
+ \pack_framed_process[\??ol:\the\framednesting]}
% we can consider setting the parent of the regular framed to
% something else in the otr so that we isolate it there
@@ -650,17 +827,6 @@
\getparameters[\??ol][#1]%
\fi}
-% \def\dosinglesetupframed[#1][#2]%
-% {\getparameters[\??ol][#1]}
-
-% \def\dodoublesetupframed[#1][#2]%
-% {\bgroup
-% \let\dodoubleempty\empty
-% \def\doframed[##1]{\gdef\globalredefinedframed{\dodoubleempty\doframed[##1,#2]}}%
-% \getvalue{#1}%
-% \egroup
-% \letvalue{#1}\globalredefinedframed}
-
%D \startbuffer
%D \setupframed [framecolor=yellow] \framed{A}
%D \defineframed[myframed] [framecolor=blue] \myframed{B}
@@ -695,257 +861,145 @@
\unexpanded\def\fastlocalframed[#1]#2[#3]#4% 3-4
{\bgroup
- \inframedtrue
- \edef\@@framed{#1}%
- \setbox\framebox\hbox{#4}%
- \getparameters[\@@framed][#3]% no \expanded !
- \!!framedframeoffset\framedparameter\c!frameoffset
- \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}%
- \ifx\@@framedbackgroundoffset\v!frame
- \!!framedbackgroundoffset\!!framedframeoffset
- \else
- \!!framedbackgroundoffset\@@framedbackgroundoffset
+ \pack_framed_initialize{#1}%
+ \setbox\b_framed_normal\hbox{#4}%
+ \edef\p_framed_region{\framedparameter\c!region}%
+ \ifx\p_framed_region\v!yes % maybe later named
+ \pack_framed_add_region
\fi
+ \getparameters[\currentframed][#3]% no \expanded !
+ \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}%
+ \edef\p_framed_background{\framedparameter\c!background}%
% not here, in calling macro: setups
- \removeframedboxdepth
-% \edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}%
-% \ifx\framedforegroundcolor\empty\else\docolorframebox\fi
- \edef\overlaylinecolor{\framedparameter\c!framecolor}%
- \edef\overlaylinewidth{\the\ruledlinewidth}%
- \edef\@@localframing {\framedparameter\c!frame}%
- \ifx\@@localframing\v!overlay \else \ifx\@@localframing\v!none \else
- \edef\framedrulethickness{\framedparameter\c!rulethickness}%
- \ifx\framedrulethickness\empty\else
- \ruledlinewidth\framedrulethickness\relax
- \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi
+ \pack_framed_remove_depth
+ \ifx\p_framed_frame\v!overlay \else \ifx\p_framed_frame\v!none \else
+ \ifx\p_framed_rulethickness\empty\else
+ \d_framed_linewidth\p_framed_rulethickness\relax
\fi
- \dooutlinebox % real or invisible frame
+ \pack_framed_add_outline % real or invisible frame
\fi \fi
- \edef\framedbackground{\framedparameter\c!background}%
- \ifx\framedbackground\empty\else\dobackedbox\fi
- \restoreframedboxdepth
- \box\framebox
+ \fi
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
+ \edef\p_framed_component{\framedparameter\c!component}%
+ \pack_framed_add_background
+ \fi
+ \pack_framed_restore_depth
+ \box\b_framed_normal
\egroup}
-%D Here is another fast one:
-
-\def\localbackgroundframed#1#2#3#4% tag box wd ht
- {\setbox#2\vbox\bgroup
- \inframedtrue
- \edef\@@framed{\??ma#1}%
- \expandafter\def\csname\??ma#1\c!component\endcsname{#1}%
- \expandafter\def\csname\??ma#1\c!width \endcsname{#3}%
- \expandafter\def\csname\??ma#1\c!height \endcsname{#4}%
- \!!framedframeoffset\framedparameter\c!frameoffset
- \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}%
- \ifx\@@framedbackgroundoffset\v!frame
- \!!framedbackgroundoffset\!!framedframeoffset
- \else
- \!!framedbackgroundoffset\@@framedbackgroundoffset
+%D The next macro uses a box and takes its natural width and
+%D height so these can better be correct.
+
+\def\localbackgroundframed#1#2#3% namespace component box
+ {\bgroup
+ \pack_framed_initialize{#1}%
+ \setbox\b_framed_normal\box#3%
+ \edef\p_framed_region{\framedparameter\c!region}%
+ \ifx\p_framed_region\v!yes % maybe later named
+ \pack_framed_add_region
\fi
- \setbox\framebox\box#2%
- \dp\framebox\zeropoint
-% \removeframedboxdepth
-% \edef\framedforegroundcolor{\framedparameter\c!foregroundcolor}%
-% \ifx\framedforegroundcolor\empty\else\docolorframebox\fi
- \edef\overlaylinecolor{\framedparameter\c!framecolor}%
- \edef\overlaylinewidth{\the\ruledlinewidth}%
- \edef\@@localframing {\framedparameter\c!frame}%
- \ifx\@@localframing\v!overlay \else \ifx\@@localframing\v!none \else
- \edef\framedrulethickness{\framedparameter\c!rulethickness}%
- \ifx\framedrulethickness\empty\else
- \ruledlinewidth\framedrulethickness\relax
- \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi
+ \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}%
+ \edef\p_framed_background{\framedparameter\c!background}%
+ \ifx\p_framed_frame\v!overlay \else \ifx\p_framed_frame\v!none \else
+ \ifx\p_framed_rulethickness\empty \else
+ \d_framed_linewidth\p_framed_rulethickness\relax
\fi
- \dooutlinebox % real or invisible frame
+ \pack_framed_add_outline % real or invisible frame
\fi \fi
- \edef\framedbackground{\framedparameter\c!background}%
- \ifx\framedbackground\empty\else\dobackedbox\fi
-% \restoreframedboxdepth
- \box\framebox
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
+ \edef\p_framed_component{#2}%
+ \pack_framed_add_background
+ \fi
+ \box\b_framed_normal
\egroup}
-%D Before we go into details, we present (and implement) the
-%D main framing routine. I saw no real reason for splitting the
-%D next two macros into smaller pieces. The content will be
-%D collected in a horizontal or vertical box with fixed or free
-%D dimensions and specific settings concerning aligment and
-%D offsets.
-%D
-%D In the first few lines, we pre||expand the frame and
-%D background offsets. We do so, because the can be defined in
-%D terms of the main offset. However, see for instance page
-%D backgrounds, when \type {#2} sets the offset to \type
-%D {overlay}, both offsets become invalid.
-%D
-%D Because it is used so often the he next macro is (and
-%D looks) rather optimized.
-
-% \def\s!root{root} % maybe configurable
-
\let\postprocessframebox\relax
-\let\@@framed\s!unknown
-
-% \def\framedparameter #1{\csname\doframedparameter\@@framed#1\endcsname}
-% \def\framedparameterhash#1{\doframedparameterhash \@@framed#1}
-%
-% \def\doframedparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedparentparameter \csname#1\s!parent\endcsname#2\fi}
-% \def\doframedparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doframedparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-%
-% \def\doframedparentparameter #1#2{\ifx#1\relax\s!empty\else\doframedparameter #1#2\fi}
-% \def\doframedparentparameterhash#1#2{\ifx#1\relax \else\doframedparameterhash#1#2\fi}
-%
-% \def\doframedparentparameter#1#2{\ifx#1\relax\doframedrootparameter#2\else\doframedparameter#1#2\fi}
-% \def\doframedrootparameter #1{\ifcsname\??oi#1\endcsname\??oi#1\else\s!empty\fi}
-
-\def\framedparameter #1{\csname\doframedparameter\@@framed{#1}\endcsname}
-\def\framedparameterhash#1{\doframedparameterhash \@@framed#1}
-
-\def\doframedparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedparentparameter \csname#1\s!parent\endcsname{#2}\fi}
-\def\doframedparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doframedparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\doframedparentparameter #1#2{\ifx#1\relax\s!empty\else\doframedparameter #1{#2}\fi}
-\def\doframedparentparameterhash#1#2{\ifx#1\relax \else\doframedparameterhash#1#2\fi}
-
-\def\doframedparentparameter#1#2{\ifx#1\relax\doframedrootparameter#2\else\doframedparameter#1{#2}\fi}
-\def\doframedrootparameter #1{\ifcsname\??oi#1\endcsname\??oi#1\else\s!empty\fi}
-
-\def\frameddimension#1{\the\dimexpr\framedparameter{#1}\relax}
-
-\def\dosetframedattributes#1#2% style color
- {\edef\fontattributehash {\framedparameterhash#1}%
- \edef\colorattributehash{\framedparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-% defaults, kind of isolated now
-
-\getparameters
- [\??oi]
- [\c!width=\v!fit,
- \c!height=\v!broad,
- %\c!lines=,
- \c!offset=0.25ex, % \defaultframeoffset
- \c!empty=\v!no,
- \c!frame=\v!on,
- %\c!topframe=,
- %\c!bottomframe=,
- %\c!leftframe=,
- %\c!rightframe=,
- \c!radius=.5\bodyfontsize,
- \c!rulethickness=\linewidth,
- \c!corner=\v!rectangular,
- \c!depth=\zeropoint,
- %\c!foregroundcolor=,
- %\c!foregroundstyle=,
- %\c!background=,
- %\c!backgroundscreen=,
- %\c!backgroundcolor=,
- \c!backgroundoffset=\zeropoint,
- %\c!framecolor=,
- \c!frameoffset=\zeropoint,
- \c!backgroundcorner=\framedparameter\c!corner,
- \c!backgroundradius=\framedparameter\c!radius,
- \c!backgrounddepth=\framedparameter\c!depth,
- \c!framecorner=\framedparameter\c!corner,
- \c!frameradius=\framedparameter\c!radius,
- \c!framedepth=\framedparameter\c!depth,
- %\c!component=,
- %\c!align=,
- \c!bottom=\vss,
- %\c!top=,
- \c!strut=\v!yes,
- \c!autostrut=\v!yes,
- \c!location=\v!normal,
- %\c!orientation=,
- \c!autowidth=\v!yes,
- %\c!setups=
-]
-
-\getparameters
- [\??od] % for fast version
- [\c!frame=\v!off,
- \c!depth=\zeropoint,
- \c!offset=\v!overlay,
- %\c!component=,
- \c!radius=.5\bodyfontsize,
- \c!rulethickness=\linewidth,
- \c!corner=\v!rectangular,
- \c!backgroundoffset=\zeropoint,
- \c!frameoffset=\zeropoint,
- \c!backgroundcorner=\framedparameter\c!corner,
- \c!backgroundradius=\framedparameter\c!radius,
- \c!backgrounddepth=\framedparameter\c!depth,
- \c!framecorner=\framedparameter\c!corner,
- \c!frameradius=\framedparameter\c!radius,
- \c!framedepth=\framedparameter\c!depth,
- \c!location=\v!normal]
-
-% so far
-
-\newdimen\!!framedwidth
-\newdimen\!!framedheight
-\newdimen\!!framedscratch % so that users can use \scratchdimen
-\newdimen\!!framedframeoffset
-\newdimen\!!framedbackgroundoffset
+%D A nice example by Aditya:
+%D
+%D \starttyping
+%D \setupframed
+%D [loffset=\framedparameter{hoffset},
+%D roffset=\framedparameter{hoffset},
+%D hoffset=\zeropoint]
+%D
+%D \defineframed[test][hoffset=1cm]
+%D \stoptyping
-\let\setextraframedoffsets \relax
-\let\applyextraframedoffsets\relax
+\newdimen\d_framed_width
+\newdimen\d_framed_height
+\newdimen\d_framed_frameoffset
+\newdimen\d_framed_backgroundoffset
+\newdimen\d_framed_local_offset
% todo: protect local \framednames
\unexpanded\def\localframed
{\bgroup
- \dodoubleempty\dolocalframed}
+ \dodoubleempty\pack_framed_process}
-\unexpanded\def\dolocalframed[#1][#2]% assumes a \dodoubleempty (slows down), also should have leading \bgroup
+\unexpanded\def\pack_framed_process[#1][#2]% assumes a \dodoubleempty (slows down), also should have leading \bgroup
{\bgroup
- \inframedtrue
- \edef\@@framed{#1}%
+ \pack_framed_initialize{#1}%
\ifsecondargument % faster
- \getparameters[\@@framed][#2]% here !
+ \getparameters[\currentframed][#2]% here !
\fi
- \dodolocalframed}
+ \pack_framed_process_indeed}
\unexpanded\def\directlocalframed[#1]% no optional
{\bgroup
\bgroup
- \inframedtrue
- \edef\@@framed{#1}%
- \dodolocalframed}
+ \pack_framed_initialize{#1}%
+ \pack_framed_process_indeed}
\unexpanded\def\localframedwithsettings[#1][#2]% no checking (so no spaces between)
{\bgroup
\bgroup
- \inframedtrue
- \edef\@@framed{#1}%
- \getparameters[\@@framed][#2]% here !
- \dodolocalframed}
+ \pack_framed_initialize{#1}%
+ \getparameters[\currentframed][#2]% here !
+ \pack_framed_process_indeed}
+
+% done
\def\c!fr!analyze{fr:analyze} % private option
% we can make macros for the offset, width, and height branches or do an \csname
-\unexpanded\def\dodolocalframed
- {\!!framedframeoffset\framedparameter\c!frameoffset
- \edef\@@framedbackgroundoffset{\framedparameter\c!backgroundoffset}%
- \ifx\@@framedbackgroundoffset\v!frame
- \!!framedbackgroundoffset\!!framedframeoffset
- \else
- \!!framedbackgroundoffset\@@framedbackgroundoffset
- \fi
+\unexpanded\def\pack_framed_process_indeed
+ {\d_framed_frameoffset\framedparameter\c!frameoffset
+ \edef\p_framed_backgroundoffset{\framedparameter\c!backgroundoffset}%
+ \d_framed_backgroundoffset
+ \ifx\p_framed_backgroundoffset\v!frame
+ \d_framed_frameoffset
+ \else
+ \p_framed_backgroundoffset
+ \fi
% new, experimental dirty hook
\framedparameter\c!extras
% to get the right spacing
- \edef\fontattributehash{\framedparameterhash\c!foregroundstyle}%
- \ifx\fontattributehash\empty\else\dosetfontattribute\fontattributehash\c!foregroundstyle\fi
+ \edef\p_framed_foregroundstyle{\framedparameter\c!foregroundstyle}%
+ \ifx\p_framed_foregroundstyle\empty\else\dousestyleparameter\p_framed_foregroundstyle\fi
% beware, both the frame and background offset can be overruled
%
- \edef\doframedsetups{\framedparameter\c!setups}%
- \ifx\doframedsetups\empty\else
- \edef\doframedsetups{\noexpand\setups[\doframedsetups]}%
- \fi
+ \edef\p_framed_setups{\framedparameter\c!setups}%
% the next macros are visible
\edef\localoffset{\framedparameter\c!offset}%
\edef\localwidth {\framedparameter\c!width}%
@@ -953,130 +1007,132 @@
\edef\localformat{\framedparameter\c!align}%
\edef\localstrut {\framedparameter\c!strut}%
% these are not
- \edef\@@localautostrut {\framedparameter\c!autostrut}%
- \edef\@@localframing {\framedparameter\c!frame}%
- \edef\@@locallocation {\framedparameter\c!location}%
- \edef\@@localorientation{\framedparameter\c!orientation}%
+ \edef\p_framed_autostrut {\framedparameter\c!autostrut}%
+ \edef\p_framed_frame {\framedparameter\c!frame}%
+ \edef\p_framed_location {\framedparameter\c!location}%
+ \edef\p_framed_orientation{\framedparameter\c!orientation}%
%
- \edef\@@localautowidth {\framedparameter\c!autowidth}%
- \edef\@@localfranalyze {\framedparameter\c!fr!analyze}% experimental option
+ \edef\p_framed_autowidth {\framedparameter\c!autowidth}%
+ \edef\p_framed_franalyze {\framedparameter\c!fr!analyze}% experimental option
%
- \ifx\@@localframing\v!overlay % no frame, no offset, no framewidth
- \boxhasframefalse
+ \ifx\p_framed_frame\v!overlay % no frame, no offset, no framewidth
+ \setfalse\c_framed_has_frame
\let\localoffset\v!overlay
- \else\ifx\@@localframing\v!none % no frame, no framewidth
- \boxhasframefalse
+ \else\ifx\p_framed_frame\v!none % no frame, no framewidth
+ \setfalse\c_framed_has_frame
\else
- \boxhasframetrue
+ \settrue\c_framed_has_frame
\fi\fi
- \ifboxhasframe
- \edef\framedrulethickness{\framedparameter\c!rulethickness}%
- \ifx\framedrulethickness\empty\else
- \ruledlinewidth\framedrulethickness\relax
- \ifinheritruledlinewidth\linewidth\ruledlinewidth\fi
+ \ifconditional\c_framed_has_frame
+ \edef\p_framed_rulethickness{\framedparameter\c!rulethickness}%
+ \ifx\p_framed_rulethickness\empty\else
+ \d_framed_linewidth\p_framed_rulethickness\relax
\fi
\else
- \ruledlinewidth\zeropoint
+ \d_framed_linewidth\zeropoint
\fi
\ifx\localformat\empty
- \boxhasformatfalse
+ \setfalse\c_framed_has_format
\else
- \boxhasformattrue
- \dosetraggedcommand\localformat
- \edef\dobeforeframedbox{\raggedtopcommand\framedparameter\c!top}%
- \edef\doafterframedbox {\framedparameter\c!bottom\raggedbottomcommand}%
+ \settrue\c_framed_has_format
+ \dosetraggedcommand\localformat % not that fast
\fi
\ifx\localoffset\v!none
- \boxhasoffsetfalse
- \boxhasstrutfalse
- \boxisoverlaidfalse
- \@@localoffset\ruledlinewidth
+ \setfalse\c_framed_has_offset
+ \setfalse\c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
+ \d_framed_local_offset\d_framed_linewidth
\else\ifx\localoffset\v!overlay
- % \ifx\@@localframing\v!no \boxhasframefalse \fi % test first
- \boxhasoffsetfalse
- \boxhasstrutfalse
- \boxisoverlaidtrue
- \@@localoffset\zeropoint
+ % \ifx\p_framed_frame\v!no \setfalse\c_framed_has_frame \fi % test first
+ \setfalse\c_framed_has_offset
+ \setfalse\c_framed_has_strut
+ \settrue \c_framed_is_overlaid
+ \d_framed_local_offset\zeropoint
+% \else\ifx\localoffset\v!strut
+% \setfalse\c_framed_has_offset
+% \settrue \c_framed_has_strut
+% \settrue \c_framed_is_overlaid
+% \d_framed_local_offset\zeropoint
\else
- \boxhasoffsettrue
- \boxhasstruttrue
- \boxisoverlaidfalse
+ \settrue \c_framed_has_offset
+ \settrue \c_framed_has_strut
+ \setfalse\c_framed_is_overlaid
\ifx\localoffset\v!default % new per 2-6-2000
\let\localoffset\defaultframeoffset
- \expandafter\let\csname\@@framed\c!offset\endcsname\defaultframeoffset
+ \letframedparameter\c!offset\defaultframeoffset % brrr
\else
\let\defaultframeoffset\localoffset
\fi
- \@@localoffset\dimexpr\localoffset+\ruledlinewidth\relax
- \fi\fi
- \!!framedheight\zeropoint
- \!!framedwidth \zeropoint
+ \d_framed_local_offset\dimexpr\localoffset+\d_framed_linewidth\relax
+ \fi\fi % \fi
+ \d_framed_height\zeropoint
+ \d_framed_width \zeropoint
\ifx\localwidth\empty % fallback to fit
- \ifboxhasformat
- \boxhaswidthtrue
- \!!framedwidth\hsize
+ \ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
\else
- \boxhaswidthfalse
+ \setfalse\c_framed_has_width
\fi
\else\ifx\localwidth\v!fit
- \ifboxhasformat
- \boxhaswidthtrue
- \!!framedwidth\hsize
+ \ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
\else
- \boxhaswidthfalse
+ \setfalse\c_framed_has_width
\fi
\else\ifx\localwidth\v!fixed % equals \v!fit but no shapebox
- \ifboxhasformat
- \boxhaswidthtrue
- \!!framedwidth\hsize
+ \ifconditional\c_framed_has_format
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
\else
- \boxhaswidthfalse
+ \setfalse\c_framed_has_width
\fi
\else\ifx\localwidth\v!broad
- \boxhaswidthtrue
- \!!framedwidth\hsize
+ \settrue\c_framed_has_width
+ \d_framed_width\hsize
\else\ifx\localwidth\v!local
- \boxhaswidthtrue
+ \settrue\c_framed_has_width
\setlocalhsize
- \!!framedwidth\localhsize
+ \d_framed_width\localhsize
\else
- \boxhaswidthtrue
- \!!framedwidth\localwidth
+ \settrue\c_framed_has_width
+ \d_framed_width\localwidth
\fi\fi\fi\fi\fi
\ifx\localheight\empty % fallback to fit
- \boxhasheightfalse
+ \setfalse\c_framed_has_height
\else\ifx\localheight\v!fit
- \boxhasheightfalse % no longer: \boxhasstrutfalse
+ \setfalse\c_framed_has_height
\else\ifx\localheight\v!broad
- \boxhasheightfalse
+ \setfalse\c_framed_has_height
\else
- \boxhasheighttrue
- \!!framedheight\localheight
+ \settrue\c_framed_has_height
+ \d_framed_height\localheight
\fi\fi\fi
- \ifboxhasheight
+ \ifconditional\c_framed_has_height
% obey user set height, also downward compatible
\else
- \edef\@@framedlines{\framedparameter\c!lines}%
- \ifx\@@framedlines\empty\else
- \ifcase\@@framedlines\else
- \!!framedheight\@@framedlines\lineheight
- \edef\localheight{\the\!!framedheight}%
- \boxhasheighttrue
+ \edef\p_framed_lines{\framedparameter\c!lines}%
+ \ifx\p_framed_lines\empty\else
+ \ifcase\p_framed_lines\else
+ \d_framed_height\p_framed_lines\lineheight
+ \edef\localheight{\the\d_framed_height}%
+ \settrue\c_framed_has_height
\fi
\fi
\fi
% this is now an option: width=local
%
- % \ifdim\!!framedwidth=\hsize
+ % \ifdim\d_framed_width=\hsize
% \parindent\zeropoint
% \setlocalhsize
- % \!!framedwidth\localhsize
+ % \d_framed_width\localhsize
% \fi
% i.e. disable (colsetbackgroundproblemintechniek)
- \advance\!!framedwidth -2\@@localoffset
- \advance\!!framedheight -2\@@localoffset
+ \advance\d_framed_width -2\d_framed_local_offset
+ \advance\d_framed_height -2\d_framed_local_offset
\ifx\localstrut\v!no
- \boxhasstrutfalse
+ \setfalse\c_framed_has_strut
\else\ifx\localstrut\v!global
\setstrut
\else\ifx\localstrut\v!local
@@ -1084,7 +1140,7 @@
\else
\setstrut
\fi\fi\fi
- \ifboxhasstrut
+ \ifconditional\c_framed_has_strut
\let\localbegstrut\begstrut
\let\localendstrut\endstrut
\let\localstrut \strut
@@ -1092,12 +1148,12 @@
\let\localbegstrut\pseudobegstrut % was: \relax
\let\localendstrut\pseudoendstrut % was: \relax
\let\localstrut \pseudostrut % was: \relax
- %\ifboxhasheight\ifdim\!!framedheight<\strutht % saveguard
+ %\ifconditional\c_framed_has_height\ifdim\d_framed_height<\strutht % saveguard
% \let\localbegstrut\relax % but not that
% \let\localstrut \relax % save after all
%\fi\fi
\fi
- \ifx\@@localautostrut\v!yes
+ \ifx\p_framed_autostrut\v!yes
\let\delayedbegstrut\relax
\let\delayedendstrut\relax
\let\delayedstrut \relax
@@ -1109,64 +1165,66 @@
\let\localendstrut \relax
\let\localstrut \relax
\fi
- \ifboxhasheight
- \let\\\vboxednewline
- \ifboxhaswidth
- \let\hairline\vboxedhairline
- \ifboxhasformat
- \let\next\doformatboxSomeFormat
+ \ifconditional\c_framed_has_height
+ \let\\\pack_framed_vboxed_newline
+ \ifconditional\c_framed_has_width
+ \let\hairline\pack_framed_vboxed_hairline
+ \ifconditional\c_framed_has_format
+ \let\next\pack_framed_format_format_yes
\else
- \let\next\doformatboxNoFormat
+ \let\next\pack_framed_format_format_nop
\fi
\else
- \let\hairline\hboxedhairline
- \ifboxhasformat
- \let\next\doformatboxHeight
+ \let\hairline\pack_framed_hboxed_hairline
+ \ifconditional\c_framed_has_format
+ \let\next\pack_framed_format_format_height
\else
- \let\next\doformatboxVSize
+ \let\next\pack_framed_format_format_vsize
\fi
\fi
\else
- \ifboxhaswidth
- \ifboxhasformat
- \let\hairline\vboxedhairline
- \let\\\vboxednewline
- \let\next\doformatboxWidth
+ \ifconditional\c_framed_has_width
+ \ifconditional\c_framed_has_format
+ \let\hairline\pack_framed_vboxed_hairline
+ \let\\\pack_framed_vboxed_newline
+ \let\next\pack_framed_format_format_width
\else
- \let\hairline\hboxedhairline
- \let\\\hboxednewline
- \let\next\doformatboxHSize
+ \let\hairline\pack_framed_hboxed_hairline
+ \let\\\pack_framed_hboxed_newline
+ \let\next\pack_framed_format_format_hsize
\fi
\else
- \let\hairline\hboxedhairline
- \let\\\hboxednewline
- \let\next\doformatboxNoSize
+ \let\hairline\pack_framed_hboxed_hairline
+ \let\\\pack_framed_hboxed_newline
+ \let\next\pack_framed_format_format_no_size
\fi
\fi
- \setextraframedoffsets
- \edef\framedbackground{\framedparameter\c!background}%
- \ifx\framedbackground\empty
- \let\framedforgetall\forgetall
+ \pack_framed_check_extra_offsets
+ \edef\p_framed_background{\framedparameter\c!background}%
+ \ifx\p_framed_background\empty
+ \let\pack_framed_forgetall\forgetall
\else
- \let\framedforgetall\relax
+ \let\pack_framed_forgetall\relax
\forgetall
\fi
- \edef\framedwidth {\ifdim\!!framedwidth >\zeropoint\the\!!framedwidth \else\!!zeropoint\fi}% a new feature, visible for user
- \edef\framedheight{\ifdim\!!framedheight>\zeropoint\the\!!framedheight\else\!!zeropoint\fi}% a new feature, visible for user
- \edef\framedoffset{\the\dimexpr\ifboxhasoffset\localoffset\else\zeropoint\fi}%
- \@@startframedorientation
- \afterassignment\dodowithframebox
- \setbox\framebox\next}
+ \edef\framedwidth {\ifdim\d_framed_width >\zeropoint\the\d_framed_width \else\!!zeropoint\fi}% a new feature, visible for user
+ \edef\framedheight{\ifdim\d_framed_height>\zeropoint\the\d_framed_height\else\!!zeropoint\fi}% a new feature, visible for user
+ \edef\framedoffset{\the\dimexpr\ifconditional\c_framed_has_offset\localoffset\else\zeropoint\fi}%
+ \ifx\p_framed_orientation\empty
+ \let\pack_framed_stop_orientation\relax
+ \else
+ \pack_framed_start_orientation
+ \fi
+ \afterassignment\pack_framed_restart
+ \setbox\b_framed_normal\next}
-\def\dowithframebox
- {% moved : \let\postprocessframebox\relax
- \finishlocalframed}
+\let\pack_framed_stop_orientation\relax
-\def\dodowithframebox
- {\aftergroup\dowithframebox}
+\def\pack_framed_restart
+ {\aftergroup\pack_framed_finish}
-\let\doafterframedbox \relax
-\let\dobeforeframedbox\relax
+\def\pack_framed_do_top {\raggedtopcommand\framedparameter\c!top}
+\def\pack_framed_do_bottom{\framedparameter\c!bottom\raggedbottomcommand}
%D Carefull analysis of this macro will learn us that not all
%D branches in the last conditionals can be encountered, that
@@ -1175,7 +1233,7 @@
%D future extensions.
%D \macros
-%D {\doassigncheckedframeoffset}
+%D {doassigncheckedframeoffset}
%D
%D Offset helper (see menus):
@@ -1217,122 +1275,150 @@
%D ...,bottom=\kern0pt,...
%D \stoptyping
-% experiment ... \@@localfranalyze -> we could support 'first' as location key
+% experiment ... \p_framed_franalyze -> we could support 'first' as location key
% option but then we will always do an analysis and reimplement the location
% options (btw, beware of location settings of derived functionality that bleed
% into this
-\def\finishlocalframeda
+\def\pack_framed_finish_a
{\ifreshapeframebox
- \doreshapeframedbox
- \else\ifx\@@localfranalyze\v!yes
- \doanalyzeframedbox
+ \pack_framed_reshape_process
+ \else\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
\else
- \resetshapeframebox
+ \pack_framed_reshape_reset
\fi\fi
- \boxhaswidthfalse}
+ \setfalse\c_framed_has_width}
-\def\finishlocalframedb
- {\ifx\@@localfranalyze\v!yes
- \doanalyzeframedbox
+\def\pack_framed_finish_b
+ {\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
\else
- \resetshapeframebox
+ \pack_framed_reshape_reset
\fi
- \boxhaswidthfalse}
+ \setfalse\c_framed_has_width}
-\def\finishlocalframedc
- {\ifx\@@localfranalyze\v!yes
- \doanalyzeframedbox
+\def\pack_framed_finish_c
+ {\ifx\p_framed_franalyze\v!yes
+ \pack_framed_reshape_analyze
\else
- \resetshapeframebox
+ \pack_framed_reshape_reset
\fi}
-\unexpanded\def\finishlocalframed
- {\dontshowcomposition
- \@@stopframedorientation % hm, wrong place ! should rotate the result (after reshape)
- \handleframedlocator\c!before\@@locallocation
- \ifboxhasformat
- \ifx\@@localautowidth\v!force
- \finishlocalframeda
+\unexpanded\def\pack_framed_finish
+ {\pack_framed_stop_orientation % hm, wrong place ! should rotate the result (after reshape)
+ \pack_framed_locator_before\p_framed_location
+ \ifconditional\c_framed_has_format
+ \ifx\p_framed_autowidth\v!force
+ \pack_framed_finish_a
\else\ifx\localwidth\v!fit
- \ifx\@@localautowidth\v!yes
- \finishlocalframeda
+ \ifx\p_framed_autowidth\v!yes
+ \pack_framed_finish_a
\else
- \finishlocalframedb
+ \pack_framed_finish_b
\fi
\else\ifx\localwidth\v!fixed
- \finishlocalframedb
+ \pack_framed_finish_b
\else
- \finishlocalframedc
+ \pack_framed_finish_c
\fi\fi\fi
\ifconditional\boxcontentneedsprocessing
- \mkdoprocessboxcontents\framebox
+ \mkdoprocessboxcontents\b_framed_normal
\fi
\else
- \finishlocalframedc
+ \pack_framed_finish_c
+ \fi
+ \ifconditional\c_framed_has_width
+ \wd\b_framed_normal\d_framed_width
\fi
- \ifboxhaswidth
- \wd\framebox\!!framedwidth
+ \ifconditional\c_framed_has_height
+ \ht\b_framed_normal\d_framed_height
\fi
- \ifboxhasheight
- \ht\framebox\!!framedheight
+ \edef\p_framed_empty{\framedparameter\c!empty}%
+ \ifx\p_framed_empty\v!yes
+ \pack_framed_fake_box
\fi
- \doif{\framedparameter\c!empty}\v!yes\dosetfakedframebox
- \ifboxhasextraoffset
- \applyextraframedoffsets
+ \iftrialtypesetting \else
+ \edef\p_framed_region{\framedparameter\c!region}%
+ \ifx\p_framed_region\v!yes % maybe later named
+ \pack_framed_add_region
+ \fi
\fi
- \ifboxhasoffset
- \dooffsetframebox
+ \d_framed_applied_offset
+ \ifconditional\c_framed_is_overlaid
+ \zeropoint
+ \else
+ \d_framed_linewidth
+ \fi
+ \ifconditional\c_framed_has_offset
+ \advance\d_framed_applied_offset\localoffset
\fi
- \ifboxisoverlaid \else
- \dolocateframebox
+ \ifconditional\c_framed_has_extra_offset
+ \pack_framed_apply_extra_offsets % includes \d_framed_applied_offset
+ \else
+ \ifzeropt\d_framed_applied_offset
+ \else
+ \pack_framed_widen_box
+ \fi
\fi
+ %
\ifx\postprocessframebox\relax \else
\let\next\postprocessframebox
\let\postprocessframebox\relax % prevent nesting
- \next\framebox
+ \next\b_framed_normal
\fi
- \edef\overlaylinecolor{\framedparameter\c!framecolor}%
- \edef\overlaylinewidth{\the\ruledlinewidth}% \@@...
- \ifboxhasframe % real or invisible frame
- \dooutlinebox
+ \iftrialtypesetting
+ % new
+ \else
+ \ifconditional\c_framed_has_frame % real or invisible frame
+ \pack_framed_add_outline
+ \fi
+ \ifx\p_framed_background\empty \else
+ \edef\p_framed_component{\framedparameter\c!component}%
+ \pack_framed_add_background
+ \fi
\fi
- \ifx\framedbackground\empty\else\dobackedbox\fi
- \handleframedlocator\c!after\@@locallocation
- \box\framebox
+ \pack_framed_locator_after\p_framed_location
+ \box\b_framed_normal
+ \global\frameddimensionstate % global so to be used directly afterwards !
+ \ifconditional\c_framed_has_width
+ \ifconditional\c_framed_has_height \plusthree \else \plusone \fi
+ \else
+ \ifconditional\c_framed_has_height \plustwo \else \zerocount \fi
+ \fi
\egroup
\egroup}
-\def\dosetfakedframebox
- {\setbox\scratchbox\emptyhbox
- \wd\scratchbox\wd\framebox
- \ht\scratchbox\ht\framebox
- \dp\scratchbox\dp\framebox
- \setbox\framebox\box\scratchbox}
+\installcorenamespace{framedlocatorbefore}
+\installcorenamespace{framedlocatorafter}
-% test: (saves one forgetall)
-%
-% \edef\framedbackground{\framedparameter\c!background}%
-% \ifx\framedbackground\empty
-% \let\framedforgetall\forgetall
-% \else
-% \let\framedforgetall\relax
-% \forgetall
-% \fi
+\newconstant\frameddimensionstate % global state: 0=unknown 1=width 2=height 3=both
+
+\def\pack_framed_fake_box
+ {\setbox\scratchbox\emptyhbox
+ \wd\scratchbox\wd\b_framed_normal
+ \ht\scratchbox\ht\b_framed_normal
+ \dp\scratchbox\dp\b_framed_normal
+ \setbox\b_framed_normal\box\scratchbox}
\def\installframedlocator#1#2#3%
- {\setvalue{\??oi:\c!location:\c!before:#1}{#2}%
- \setvalue{\??oi:\c!location:\c!after :#1}{#3}}
+ {\setvalue{\??framedlocatorbefore#1}{#2}%
+ \setvalue{\??framedlocatorafter #1}{#3}}
-\def\handleframedlocator#1#2%
- {\csname\??oi:\c!location:#1:#2\endcsname}
+\def\pack_framed_locator_before#1{\csname\??framedlocatorbefore#1\endcsname}
+\def\pack_framed_locator_after #1{\csname\??framedlocatorafter #1\endcsname}
-\def\doprelocframedbox#1%
- {\scratchdimen\dimexpr#1+\ruledlinewidth\relax
- \ifboxhasoffset
- \advance\scratchdimen \framedparameter\c!offset
- \fi
- \scratchskip\dimexpr\ht\framebox-\scratchdimen\relax}
+\newdimen\d_framed_locator_ht
+\newdimen\d_framed_locator_dp
+
+\def\pack_framed_locater_set#1%
+ {\d_framed_locator_ht\dimexpr
+ #1+\d_framed_linewidth
+ \ifconditional\c_framed_has_offset
+ +\framedparameter\c!offset
+ \fi
+ \relax
+ \d_framed_locator_dp\dimexpr\ht\b_framed_normal-\d_framed_locator_ht\relax}
% \ruledhbox
% {A
@@ -1358,99 +1444,100 @@
\installframedlocator \v!hanging % best with strut=no
{}
- {\dp\framebox\ht\framebox
- \ht\framebox\zeropoint}
+ {\dp\b_framed_normal\ht\b_framed_normal
+ \ht\b_framed_normal\zeropoint}
\installframedlocator \v!depth
{}
- {\ht\framebox\dimexpr\ht\framebox-\strutdp\relax
- \dp\framebox\strutdp
- \box\framebox}
+ {\ht\b_framed_normal\dimexpr\ht\b_framed_normal-\strutdp\relax
+ \dp\b_framed_normal\strutdp
+ \box\b_framed_normal}
\installframedlocator \v!height
{}
- {\dp\framebox\dimexpr\ht\framebox-\strutht\relax
- \ht\framebox\strutht
- \box\framebox}
+ {\dp\b_framed_normal\dimexpr\ht\b_framed_normal-\strutht\relax
+ \ht\b_framed_normal\strutht
+ \box\b_framed_normal}
\installframedlocator \v!high
{}
- {\doprelocframedbox\strutht
- \setbox\framebox\hbox{\lower\scratchskip\box\framebox}%
- \ht\framebox\strutht
- \dp\framebox\strutdp
- \hbox{\box\framebox}}
+ {\pack_framed_locater_set\strutht
+ \setbox\b_framed_normal\hbox{\lower\d_framed_locator_dp\box\b_framed_normal}%
+ \ht\b_framed_normal\strutht
+ \dp\b_framed_normal\strutdp
+ \hbox{\box\b_framed_normal}}
\installframedlocator \v!line
{}
- {\setbox\framebox\hbox{\lower.5\ht\framebox\box\framebox}%
- \ht\framebox.5\lineheight
- \dp\framebox.5\lineheight
- \hbox{\box\framebox}}
+ {\setbox\b_framed_normal\hbox{\lower.5\ht\b_framed_normal\box\b_framed_normal}%
+ \ht\b_framed_normal.5\lineheight
+ \dp\b_framed_normal.5\lineheight
+ \hbox{\box\b_framed_normal}}
\installframedlocator \v!low
{}
- {\doprelocframedbox\strutdp
- \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
- \ht\framebox\strutht
- \dp\framebox\strutdp
- \box\framebox}
+ {\pack_framed_locater_set\strutdp
+ \setbox\b_framed_normal\hbox{\lower\d_framed_locator_ht\box\b_framed_normal}%
+ \ht\b_framed_normal\strutht
+ \dp\b_framed_normal\strutdp
+ \box\b_framed_normal}
\installframedlocator \v!top
{}
- {\doprelocframedbox\strutht
- \setbox\framebox\hbox{\lower\scratchskip\box\framebox}%
- \ht\framebox\scratchdimen
- \dp\framebox\scratchskip
- \hbox{\box\framebox}}
+ {\pack_framed_locater_set\strutht
+ \setbox\b_framed_normal\hbox{\lower\d_framed_locator_dp\box\b_framed_normal}%
+ \ht\b_framed_normal\d_framed_locator_ht
+ \dp\b_framed_normal\d_framed_locator_dp
+ \hbox{\box\b_framed_normal}}
\installframedlocator \v!middle
{}
- {\scratchdimen.5\ht\framebox
- \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
- \ht\framebox\scratchdimen
- \dp\framebox\scratchdimen
- \hbox{\box\framebox}}
+ {\scratchdimen.5\ht\b_framed_normal
+ \setbox\b_framed_normal\hbox{\lower\scratchdimen\box\b_framed_normal}%
+ \ht\b_framed_normal\scratchdimen
+ \dp\b_framed_normal\scratchdimen
+ \hbox{\box\b_framed_normal}}
\installframedlocator \v!lohi
- {\handleframedlocator\c!before\v!middle}
- {\handleframedlocator\c!after \v!middle}
+ {\pack_framed_locator_before\v!middle}
+ {\pack_framed_locator_after \v!middle}
\installframedlocator \v!bottom
{}
- {\doprelocframedbox\strutdp
- \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
- \ht\framebox\scratchskip
- \dp\framebox\scratchdimen
- \hbox{\box\framebox}}
+ {\pack_framed_locater_set\strutdp
+ \setbox\b_framed_normal\hbox{\lower\d_framed_locator_ht\box\b_framed_normal}%
+ \ht\b_framed_normal\d_framed_locator_dp
+ \dp\b_framed_normal\d_framed_locator_ht
+ \hbox{\box\b_framed_normal}}
\installframedlocator \v!keep % retains height/depth
- {\removeframedboxdepth}
- {\restoreframedboxdepth}
+ {\pack_framed_remove_depth}
+ {\pack_framed_restore_depth}
% also used in fastlocalframed
-\newdimen\originalframedwd
-\newdimen\originalframedht
-\newdimen\originalframeddp
-
-\def\removeframedboxdepth
- {\originalframedwd\wd\framebox
- \originalframedht\ht\framebox
- \originalframeddp\dp\framebox
- \ifzeropt\originalframeddp\else\setbox\framebox\hbox{\raise\originalframeddp\box\framebox}\fi
- \wd\framebox\originalframedwd
- \ht\framebox\dimexpr\originalframedht+\originalframeddp\relax
- \dp\framebox\zeropoint}
+\newdimen\d_framed_original_wd
+\newdimen\d_framed_original_ht
+\newdimen\d_framed_original_dp
-\def\restoreframedboxdepth
- {\ifzeropt\originalframeddp\else\setbox\framebox\hbox{\lower\originalframeddp\box\framebox}\fi
- \wd\framebox\originalframedwd
- \ht\framebox\originalframedht
- \dp\framebox\originalframeddp}
+\def\pack_framed_remove_depth
+ {\d_framed_original_wd\wd\b_framed_normal
+ \d_framed_original_ht\ht\b_framed_normal
+ \d_framed_original_dp\dp\b_framed_normal
+ \ifzeropt\d_framed_original_dp\else
+ \setbox\b_framed_normal\hbox{\raise\d_framed_original_dp\box\b_framed_normal}%
+ \fi
+ \wd\b_framed_normal\d_framed_original_wd
+ \ht\b_framed_normal\dimexpr\d_framed_original_ht+\d_framed_original_dp\relax
+ \dp\b_framed_normal\zeropoint}
-% \let\@@startframedorientation\relax
-% \let\@@stopframedorientation \relax
+\def\pack_framed_restore_depth
+ {\ifzeropt\d_framed_original_dp \else
+ \setbox\b_framed_normal\hbox{\lower\d_framed_original_dp\box\b_framed_normal}%
+ \fi
+ \wd\b_framed_normal\d_framed_original_wd
+ \ht\b_framed_normal\d_framed_original_ht
+ \dp\b_framed_normal\d_framed_original_dp}
% \framed[width=12cm,height=3cm,orientation=0]{\input ward\relax}
% \framed[width=12cm,height=3cm,orientation=90]{\input ward\relax}
@@ -1460,53 +1547,47 @@
% \framed[width=12cm,height=3cm,orientation=-180]{\input ward\relax}
% \framed[width=12cm,height=3cm,orientation=-270]{\input ward\relax}
-\def\@@startframedorientation
- {\let\@@stopframedorientation \relax
- \ifx\@@localorientation\empty\else
- \ifcase\@@localorientation\else
- \scratchcounter\@@localorientation
- \divide\scratchcounter\plustwo
- \ifodd\scratchcounter
- \swapmacros\framedwidth \framedheight
- \swapmacros\localwidth \localheight
- \swapdimens\!!framedheight\!!framedwidth
- \def\@@stopframedorientation{\@@dostopframedorientation\plusone}%
- \else
- \def\@@stopframedorientation{\@@dostopframedorientation\zerocount}%
- \fi
+\def\pack_framed_start_orientation
+ {\ifcase\p_framed_orientation
+ \let\pack_framed_stop_orientation\relax
+ \else
+ \scratchcounter\p_framed_orientation % weird .. why
+ \divide\scratchcounter\plustwo
+ \ifodd\scratchcounter
+ \let\pack_framed_stop_orientation\pack_framed_stop_orientation_odd
+ \else
+ \let\pack_framed_stop_orientation\pack_framed_stop_orientation_even
\fi
\fi}
-\def\@@dostopframedorientation#1%
- {\ifcase#1\else
- \swapmacros\framedwidth \framedheight
- \swapmacros\localwidth \localheight
- \swapdimens\!!framedheight\!!framedwidth
- \fi
- \setbox\framebox\hbox{\dorotatebox\@@localorientation\hbox{\box\framebox}}}
+\def\pack_framed_stop_orientation_odd
+ {\swapmacros\framedwidth\framedheight
+ \swapmacros\localwidth\localheight
+ \swapdimens\d_framed_height\d_framed_width
+ \pack_framed_stop_orientation_even}
+
+\def\pack_framed_stop_orientation_even
+ {\setbox\b_framed_normal\hbox{\dorotatebox\p_framed_orientation\hbox{\box\b_framed_normal}}}
%D The last conditional takes care of the special situation of
%D in||line \inframed[height=3cm]{framed} boxes. Such boxes have
%D to be \inframed{aligned} with the running text.
-\def\doinframed[#1]% we could omit #1] but readibility ...
- {\framed[\c!location=\v!low,#1]}
-
\unexpanded\def\inframed
- {\dosingleempty\doinframed}
+ {\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,}
%D When we set \type{empty} to \type{yes}, we get
%D ourselves a frame and/or background, but no content, so
%D actually we have a sort of phantom framed box.
-%D Because color marks and specials can interfere with
-%D spacing, we provide a way to specify a foregroundcolor.
-
-\def\docolorframebox
- {\doifcolor\framedforegroundcolor
- {\setbox\framebox\hbox{\faststartcolor[\framedforegroundcolor]\box\framebox\faststopcolor}}}
- %{\setbox\framebox\hbox{\doactivatecolor\framedforegroundcolor\box\framebox}}}
-
%D \macros
%D {mframed, minframed}
%D
@@ -1547,25 +1628,54 @@
%D Still better is the next alternative, if only because it
%D takes care of setting the super- and subscripts styles
-\newcount\mframedstyle
+\newcount\c_framed_mstyle
-\def\doinlinemframed[#1]#2%
- {\begingroup
- \mframedstyle\mathstyle\relax
- \inframed[#1]{\Ustartmath\triggermathstyle\mframedstyle#2\Ustopmath}%
- \endgroup}
+\unexpanded\def\pack_framed_math_strut
+ {\Ustartmath
+ \triggermathstyle\c_framed_mstyle
+ \vphantom{(}%
+ \Ustopmath}
-\def\funnymathstrut{\Ustartmath\triggermathstyle\mframedstyle\vphantom{(}\Ustopmath}
+% \unexpanded\def\mframed {\dosingleempty\pack_framed_math_display}
+% \unexpanded\def\inmframed{\dosingleempty\pack_framed_math_inline }
+%
+% \def\pack_framed_math_inline[#1]#2%
+% {\begingroup
+% \c_framed_mstyle\mathstyle
+% \inframed[#1]{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}%
+% \endgroup}
+%
+% \def\pack_framed_math_display[#1]#2%
+% {\begingroup
+% \c_framed_mstyle\mathstyle
+% \let\normalstrut\pack_framed_math_strut
+% \framed[#1]{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}%
+% \endgroup}
+
+\installcorenamespace{mathframed}
+
+\installframedcommandhandler \??mathframed {mathframed} \??mathframed
-\def\dodisplaymframed[#1]#2%
+\appendtoks
+ \setuevalue{\currentmathframed}{\pack_framed_mathframed{\currentmathframed}}%
+\to \everydefinemathframed
+
+\unexpanded\def\pack_framed_mathframed#1%
{\begingroup
- \mframedstyle\mathstyle\relax
- \let\normalstrut\funnymathstrut
- \framed[#1]{\Ustartmath\triggermathstyle\mframedstyle#2\Ustopmath}%
+ \edef\currentmathframed{#1}%
+ \dosingleempty\pack_framed_mathframed_indeed}
+
+\def\pack_framed_mathframed_indeed[#1]#2% no fancy nesting supported here
+ {\iffirstargument
+ \setupcurrentmathframed[#1]%
+ \fi
+ \c_framed_mstyle\mathstyle
+ \doifnot{\mathframedparameter\c!location}\v!low{\let\normalstrut\pack_framed_math_strut}%
+ \inheritedmathframedframed{\Ustartmath\triggermathstyle\c_framed_mstyle#2\Ustopmath}%
\endgroup}
-\def\mframed {\dosingleempty\dodisplaymframed}
-\def\inmframed{\dosingleempty\doinlinemframed }
+\definemathframed[mframed]
+\definemathframed[inmframed][\c!location=\v!low]
%D So instead of the rather versatile \type {\framed}, we ue
%D the \type {\mframed}.
@@ -1577,12 +1687,9 @@
%D \stopformula
%D \stopbuffer
%D
-%D \typebuffer
-%D
-%D \getbuffer
+%D \typebuffer \getbuffer
%D
-%D However, we got into troubles when we want to nest sub- and
-%D superscripts, like in
+%D And:
%D
%D \startbuffer
%D \startformula
@@ -1590,23 +1697,7 @@
%D \stopformula
%D \stopbuffer
%D
-%D \typebuffer
-%D
-%D \getbuffer
-%D
-%D Therefore, we can best use \type {\super} and \type {\suber}
-%D instead of \type {^} and \type {_}. Both commands take care
-%D of proper font switching.
-%D
-%D \startbuffer
-%D \startformula
-%D x \times \mframed{y} \times y\super{\mframed{z}\suber{\mframed{z}}}
-%D \stopformula
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \getbuffer
+%D \typebuffer \getbuffer
%D
%D As usual, one can specify in what way the text should be
%D framed. One should be aware of the fact that, inorder to
@@ -1616,13 +1707,11 @@
%D
%D \startbuffer
%D \startformula
-%D x \times y\super{\mframed[framecolor=red]{z}\suber{z}}
+%D x \times y^{\mframed[framecolor=red]{z}_{z}}
%D \stopformula
%D \stopbuffer
%D
-%D \typebuffer
-%D
-%D \getbuffer
+%D \typebuffer \getbuffer
%D
%D For inline use, we also provide the \type {\inmframed}
%D alternative: we want $x \times \inmframed{y}$ in inline
@@ -1632,12 +1721,43 @@
%D putting rules around boxes, inserting offsets and aligning
%D text. Each step is handled by separate macros.
-\def\dowidenframebox#1%
- {\setbox\framebox\vbox
- {\kern#1\hbox{\kern#1\box\framebox\kern#1}\kern#1}}
+\newdimen\d_framed_applied_offset
+\newdimen\d_framed_loffset
+\newdimen\d_framed_roffset
+\newdimen\d_framed_toffset
+\newdimen\d_framed_boffset
+
+\def\pack_framed_check_extra_offsets
+ {\setfalse\c_framed_has_extra_offset
+ \d_framed_loffset\framedparameter\c!loffset\relax
+ \d_framed_roffset\framedparameter\c!roffset\relax
+ \d_framed_toffset\framedparameter\c!toffset\relax
+ \d_framed_boffset\framedparameter\c!boffset\relax
+ \ifzeropt\d_framed_loffset\else \advance\d_framed_width -\d_framed_loffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_roffset\else \advance\d_framed_width -\d_framed_roffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_toffset\else \advance\d_framed_height-\d_framed_toffset \settrue\c_framed_has_extra_offset \fi
+ \ifzeropt\d_framed_boffset\else \advance\d_framed_height-\d_framed_boffset \settrue\c_framed_has_extra_offset \fi}
+
+\def\pack_framed_apply_extra_offsets
+ {\setbox\b_framed_normal\vbox\bgroup
+ \advance\d_framed_toffset\d_framed_applied_offset
+ \advance\d_framed_boffset\d_framed_applied_offset
+ \advance\d_framed_loffset\d_framed_applied_offset
+ \advance\d_framed_roffset\d_framed_applied_offset
+ \kern\d_framed_toffset
+ \hbox\bgroup
+ \kern\d_framed_loffset
+ \box\b_framed_normal
+ \kern\d_framed_roffset
+ \egroup
+ \kern\d_framed_boffset
+ \egroup}
-\def\dooffsetframebox{\dowidenframebox\localoffset}
-\def\dolocateframebox{\dowidenframebox\ruledlinewidth}
+\def\pack_framed_widen_box
+ {\setbox\b_framed_normal\vbox
+ {\kern\d_framed_applied_offset
+ \hbox{\kern\d_framed_applied_offset\box\b_framed_normal\kern\d_framed_applied_offset}%
+ \kern\d_framed_applied_offset}}
%D Let's hope that the next few examples show us enough of
%D what needs to be done by the auxiliary macros.
@@ -1724,55 +1844,79 @@
\fi}
\def\dodoformatonelinerbox
- {\dowithnextboxcontent
- {\ignorespaces}
- {\hbox to \hsize
- {\ifcase\raggedstatus\or\hss\or\hss\fi
- \unhbox\nextbox \removeunwantedspaces
- \ifcase\raggedstatus\or \or\hss\or\hss\fi}%
- \egroup}
- \hbox}
+ {\afterassignment\redoformatonelinerbox
+ \setbox\nextbox\hbox}
+
+\def\redoformatonelinerbox
+ {\aftergroup\dododoformatonelinerbox
+ \ignorespaces}
+
+\def\dododoformatonelinerbox
+ {\hbox to \hsize
+ {\ifcase\raggedstatus\or\hss\or\hss \fi
+ \unhbox\nextbox \removeunwantedspaces
+ \ifcase\raggedstatus\or \or\hss\or\hss\fi}%
+ \egroup}
\def\nodoformatonelinerbox % grabs {
{\let\next=}
%D The handlers:
-\def\framedforgetall{\forgetall}
+\def\pack_framed_forgetall{\forgetall}
+
+% test: (saves one forgetall)
+%
+% \edef\framedbackground{\framedparameter\c!background}%
+% \ifx\framedbackground\empty
+% \let\pack_framed_forgetall\forgetall
+% \else
+% \let\pack_framed_forgetall\relax
+% \forgetall
+% \fi
+
+\def\pack_framed_set_foregroundcolor
+ {\edef\p_framed_foregroundcolor{\framedparameter\c!foregroundcolor}%
+ \ifx\p_framed_foregroundcolor\empty\else\dousecolorparameter\p_framed_foregroundcolor\fi}
-\def\setframedforegroundcolor
- {\edef\colorattributehash{\framedparameterhash\c!foregroundcolor}%
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash\c!foregroundcolor\fi}
+\def\pack_framed_do_setups
+ {\ifx\p_framed_setups\empty \else
+ \setups[\p_framed_setups]% \texsetup
+ \fi}
-\def\doformatboxSomeFormat
- {\vbox to \!!framedheight
+\def\pack_framed_format_format_yes
+ {\vbox to \d_framed_height
\bgroup
\let\postprocessframebox\relax
- \framedforgetall
- \setframedforegroundcolor
+ \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
\oninterlineskip
- \hsize\!!framedwidth
- \vsize\!!framedheight
- \doframedsetups
+ \hsize\d_framed_width
+ \vsize\d_framed_height
+ \pack_framed_do_setups
\raggedcommand
- \dobeforeframedbox
+ \pack_framed_do_top
\bgroup
\localbegstrut
\aftergroup\localendstrut
- \aftergroup\doafterframedbox
+ \aftergroup\pack_framed_do_bottom
\aftergroup\egroup
\doformatonelinerbox}
-\def\doformatboxNoFormat
- {\vbox to \!!framedheight
+\def\pack_framed_format_format_nop
+ {\vbox to \d_framed_height
\bgroup
\let\postprocessframebox\relax
- \framedforgetall
- \setframedforegroundcolor
+ \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
\oninterlineskip
- \hsize\!!framedwidth
- \vsize\!!framedheight
- \doframedsetups
+ \hsize\d_framed_width
+ \vsize\d_framed_height
+ \pack_framed_do_setups
\raggedcenter
\vss
\bgroup
@@ -1782,14 +1926,16 @@
\aftergroup\egroup
\doformatonelinerbox}
-\def\doformatboxHeight
- {\vbox to \!!framedheight
+\def\pack_framed_format_format_height
+ {\vbox to \d_framed_height
\bgroup
\let\postprocessframebox\relax
- \framedforgetall
- \setframedforegroundcolor
+ \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
\oninterlineskip
- \doframedsetups
+ \pack_framed_do_setups
\raggedcommand
\vss
\bgroup
@@ -1799,32 +1945,36 @@
\localbegstrut
\doformatonelinerbox}
-\def\doformatboxWidth
+\def\pack_framed_format_format_width
{\vbox
\bgroup
\let\postprocessframebox\relax
- \framedforgetall
- \setframedforegroundcolor
+ \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
\oninterlineskip
- \hsize\!!framedwidth
- \doframedsetups
+ \hsize\d_framed_width
+ \pack_framed_do_setups
\raggedcommand
- \dobeforeframedbox
+ \pack_framed_do_top
\bgroup
\localbegstrut
\aftergroup\localendstrut
- \aftergroup\doafterframedbox
+ \aftergroup\pack_framed_do_bottom
\aftergroup\egroup
\doformatonelinerbox}
-\def\doformatboxVSize
- {\vbox to \!!framedheight
+\def\pack_framed_format_format_vsize
+ {\vbox to \d_framed_height
\bgroup
\let\postprocessframebox\relax
- \framedforgetall
- \setframedforegroundcolor
- \vsize\!!framedheight
- \doframedsetups
+ \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \vsize\d_framed_height
+ \pack_framed_do_setups
\vss
\bgroup
\aftergroup\vss
@@ -1835,13 +1985,15 @@
\localstrut
\doformatonelinerbox}
-\def\doformatboxHSize
- {\hbox to \!!framedwidth
+\def\pack_framed_format_format_hsize
+ {\hbox to \d_framed_width
\bgroup
\let\postprocessframebox\relax
- \framedforgetall
- \setframedforegroundcolor
- \doframedsetups
+ \pack_framed_forgetall
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
+ \pack_framed_do_setups
\hss
\localstrut
\bgroup
@@ -1849,17 +2001,17 @@
\aftergroup\egroup
\doformatonelinerbox}
-\def\doformatboxNoSize
+\def\pack_framed_format_format_no_size
{\hbox
\bgroup
- \setframedforegroundcolor
+ \iftrialtypesetting \else
+ \pack_framed_set_foregroundcolor
+ \fi
\let\postprocessframebox\relax
- \doframedsetups
+ \pack_framed_do_setups
\localstrut
\doformatonelinerbox}
-\let\doframedsetups\relax
-
%D On the next page we show some examples of how these macros
%D come into action. The examples show us how
%D \type {fit}, \type {broad} dimensions influence the
@@ -1870,44 +2022,49 @@
%D \bgroup
%D \showstruts
%D \dontcomplain
-%D \startlinecorrection
-%D \halign{#\enskip&#\enskip&#\enskip&#\enskip&#\enskip&#\cr
-%D \framed[width=.2\hsize, height=.2\hsize, align=] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=broad, align=] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=fit, align=] {a\par b\par c}&
-%D \framed[width=fit, height=.2\hsize, align=] {a\par b\par c}&
-%D \framed[width=fit, height=broad, align=] {a\par b\par c}&
-%D \framed[width=fit, height=fit, align=] {a\par b\par c}\cr
-%D \noalign{\vskip1em}
-%D \framed[width=.2\hsize, height=.2\hsize, align=yes] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=broad, align=yes] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=fit, align=yes] {a\par b\par c}&
-%D \framed[width=fit, height=.2\hsize, align=yes] {a\par b\par c}&
-%D \framed[width=fit, height=broad, align=yes] {a\par b\par c}&
-%D \framed[width=fit, height=fit, align=yes] {a\par b\par c}\cr
-%D \noalign{\vskip1em}
-%D \framed[width=.2\hsize, height=.2\hsize, align=right] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=broad, align=right] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=fit, align=right] {a\par b\par c}&
-%D \framed[width=fit, height=.2\hsize, align=right] {a\par b\par c}&
-%D \framed[width=fit, height=broad, align=right] {a\par b\par c}&
-%D \framed[width=fit, height=fit, align=right] {a\par b\par c}\cr
-%D \noalign{\vskip1em}
-%D \framed[width=.2\hsize, height=.2\hsize, align=left] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=broad, align=left] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=fit, align=left] {a\par b\par c}&
-%D \framed[width=fit, height=.2\hsize, align=left] {a\par b\par c}&
-%D \framed[width=fit, height=broad, align=left] {a\par b\par c}&
-%D \framed[width=fit, height=fit, align=left] {a\par b\par c}\cr
-%D \noalign{\vskip1em}
-%D \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=broad, align=middle] {a\par b\par c}&
-%D \framed[width=.2\hsize, height=fit, align=middle] {a\par b\par c}&
-%D \framed[width=fit, height=.2\hsize, align=middle] {a\par b\par c}&
-%D \framed[width=fit, height=broad, align=middle] {a\par b\par c}&
-%D \framed[width=fit, height=fit, align=middle] {a\par b\par c}\cr}
-%D \stoplinecorrection
-%D \blank[2*big]
+%D \starttabulate[|c|c|c|c|c|c|]
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=yes] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=yes] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=right] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=right] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=left] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=left] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \NC \framed[width=.2\hsize, height=.2\hsize, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=broad, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=.2\hsize, height=fit, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=.2\hsize, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=broad, align=middle] {a\endgraf b\endgraf c}
+%D \NC \framed[width=fit, height=fit, align=middle] {a\endgraf b\endgraf c}
+%D \NC \NR
+%D % \HL
+%D \stoptabulate
%D \egroup
%D \stoppostponing
@@ -1921,18 +2078,20 @@
\newcount\framednoflines
\newdimen\framedfirstheight
\newdimen\framedlastdepth
+\newdimen\framedminwidth
+\newdimen\framedmaxwidth
+\newdimen\framedaveragewidth
-\def\resetshapeframebox
- {\framednoflines \zerocount
- \framedfirstheight\zeropoint
- \framedlastdepth \zeropoint}
+\def\pack_framed_reshape_reset
+ {\framednoflines \zerocount
+ \framedfirstheight \zeropoint
+ \framedlastdepth \zeropoint
+ \framedminwidth \zeropoint
+ \framedmaxwidth \zeropoint
+ \framedaveragewidth\zeropoint}
-\let\framedboxwidth \!!zeropoint
-\let\framedboxheight\!!zeropoint
-\let\framedboxdepth \!!zeropoint
-
-\def\doreshapeframedbox{\ifvbox\framebox\ctxcommand{doreshapeframedbox(\number\framebox)}\fi}
-\def\doanalyzeframedbox{\ifvbox\framebox\ctxcommand{doanalyzeframedbox(\number\framebox)}\fi}
+\def\pack_framed_reshape_process{\ifvbox\b_framed_normal\ctxcommand{doreshapeframedbox(\number\b_framed_normal)}\fi}
+\def\pack_framed_reshape_analyze{\ifvbox\b_framed_normal\ctxcommand{doanalyzeframedbox(\number\b_framed_normal)}\fi}
% torture test / strange case (much depth) / method 2 needed
%
@@ -2002,41 +2161,6 @@
%D \egroup
%D \stoppostponing
-%D When typesetting the framed box inline, we have to keep the
-%D baseline intact outside as well as inside the framed box.
-
-\def\doinlineframedbox
- {\scratchdimen\dimexpr\strutdp+\ruledlinewidth\relax
- \ifboxhasoffset
- \advance\scratchdimen \framedparameter\c!offset
- \fi
- \setbox\framebox\hbox{\lower\scratchdimen\box\framebox}%
- \ht\framebox\strutht
- \dp\framebox\strutdp
- \box\framebox}
-
-%D We can also lower the box over the natural depth of the
-%D line.
-
-\def\doloweredframedbox
- {\ht\framebox\dimexpr\ht\framebox+\dp\framebox-\strutdp\relax
- \dp\framebox\strutdp
- \box\framebox}
-
-%D Hanging the content is mainly meant for cases like the
-%D following:
-%D
-%D \starttyping
-%D \framed[strut=no]
-%D {\framed[height=2cm,location=hanging]{test}%
-%D \framed[height=1cm,location=hanging]{test}}
-%D \stoptyping
-
-\def\dohangingframedbox % best with strut=no
- {\scratchdimen\dimexpr\ht\framebox+\dp\framebox\relax
- \ht\framebox\zeropoint
- \dp\framebox\scratchdimen}
-
%D We can draw lines from left to right and top to bottom by
%D using the normal \type{\hairline} command. Both directions
%D need a different treatment.
@@ -2057,32 +2181,55 @@
%D possible to the circumstances and act as natural as
%D possible.
-\def\vboxedhairline
- {\bgroup
- \dimen2=\ifboxhasoffset \localoffset \else \zeropoint \fi
- \dimen4=\dimexpr\dimen2+\ruledlinewidth\relax
- \setbox0\vbox
- {\advance\hsize 2\dimen4
- \vskip\dimen2
- \hrule
- \!!height\ruledlinewidth
- \!!depth\zeropoint
- \!!width\hsize
- \vskip\dimen2}%
- %\endgraf\nointerlineskip\endgraf
- %\moveleft\dimen4\box0
- %\endgraf\nointerlineskip\localbegstrut
- \endgraf\obeydepth\nointerlineskip
- \moveleft\dimen4\box0
- \endgraf\nointerlineskip\localbegstrut % beware, we might kill it in a style using \vskip\lineheight
- \egroup} % so this must not be changed
-
-\def\hboxedhairline % use framed dimen
+% \unexpanded\def\pack_framed_vboxed_hairline
+% {\bgroup
+% \dimen2=\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
+% \dimen4=\dimexpr\dimen2+\d_framed_linewidth\relax
+% \setbox0\vbox
+% {\advance\hsize 2\dimen4
+% \vskip\dimen2
+% \hrule
+% \!!height\d_framed_linewidth
+% \!!depth\zeropoint
+% \!!width\hsize
+% \vskip\dimen2}%
+% \endgraf\obeydepth\nointerlineskip
+% \moveleft\dimen4\box0
+% \endgraf\nointerlineskip\localbegstrut % beware, we might kill it in a style using \vskip\lineheight
+% \egroup} % so this must not be changed
+
+\unexpanded\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
+ \par
+ \nointerlineskip
+ \kern\scratchoffset
+ \dontleavehmode
+ \hrule\!!height\d_framed_linewidth\!!depth\zeropoint
+ \par
+ \kern-\d_framed_linewidth
+ \dontleavehmode
+ \hbox to \zeropoint{\normalhss\vrule\!!height\d_framed_linewidth\!!depth\zeropoint\!!width\scratchwidth}%
+ \hfill
+ \hbox to \zeropoint{\vrule\!!height\d_framed_linewidth\!!depth\zeropoint\!!width\scratchwidth\normalhss}%
+ \par
+ \nointerlineskip
+ \kern\scratchoffset
+ \nointerlineskip
+ \endgraf
+ \nointerlineskip
+ \localbegstrut
+ \endgroup}
+
+% todo:
+
+\unexpanded\def\pack_framed_hboxed_hairline % use framed dimen
{\bgroup
- \dimen2=\ifboxhasoffset \localoffset \else \zeropoint \fi
- \ifboxhasheight
- \dimen4\dimexpr\localheight/2+\strutdp-2\ruledlinewidth\relax
- \dimen6\dimexpr\localheight/2-\strutdp+2\ruledlinewidth\relax
+ \dimen2=\ifconditional\c_framed_has_offset \localoffset \else \zeropoint \fi
+ \ifconditional\c_framed_has_height
+ \dimen4\dimexpr\localheight/2+\strutdp-2\d_framed_linewidth\relax
+ \dimen6\dimexpr\localheight/2-\strutdp+2\d_framed_linewidth\relax
\else
\dimen4\dimexpr\strutht+\dimen2\relax
\dimen6\dimexpr\strutdp+\dimen2\relax
@@ -2090,7 +2237,7 @@
\unskip
\setbox\scratchbox\hbox
{\hskip\dimen2
- \vrule\!!height\dimen4\!!depth\dimen6\!!width\ruledlinewidth
+ \vrule\!!height\dimen4\!!depth\dimen6\!!width\d_framed_linewidth
\hskip\dimen2}%
\ht\scratchbox\strutht
\dp\scratchbox\strutdp
@@ -2102,10 +2249,10 @@
%D sort of newline signal. In horizontal boxes it expands to a
%D space.
-\unexpanded\def\vboxednewline
+\unexpanded\def\pack_framed_vboxed_newline
{\endgraf\ignorespaces}
-\unexpanded\def\hboxednewline
+\unexpanded\def\pack_framed_hboxed_newline
{\unskip\normalspace\ignorespaces}
%D We can set each rule on or off. The default setting is
@@ -2149,487 +2296,6 @@
%D \egroup
%D \macros
-%D {setupblackrules}
-%D
-%D The graphic capabilities of \TEX\ do not go beyond simple
-%D filled rules, except of course when using specials. Let's
-%D start with a warning: using this commands is far more slower
-%D than using the \TEX\ primitives \type{\hrule} and
-%D \type{\vrule}, but they save us some tokens. The
-%D characteristics of these rule drawing command can be set by:
-%D
-%D \showsetup{setupblackrules}
-
-\unexpanded\def\setupblackrules
- {\dodoubleargument\getparameters[\??bj]}
-
-%D \macros
-%D {blackrule}
-%D
-%D The simple command draws only one rule. Its optional
-%D argument can be used to specify the dimensions. By setting
-%D the width, height or depth to \type {max}, one gets the
-%D natural dimensions.
-%D
-%D \showsetup{blackrule}
-
-\definecomplexorsimple\blackrule
-
-\unexpanded\def\complexblackrule[#1]%
- {\hbox\bgroup\getparameters[\??bj][#1]\domakeblackrule\egroup}
-
-\unexpanded\def\simpleblackrule
- {\hbox\bgroup\domakeblackrule\egroup}
-
-\def\domakeblackrule
- {\doif\@@bjwidth \v!max{\def\@@bjwidth {1em}}%
- \doif\@@bjheight\v!max{\setstrut\let\setstrut\relax\def\@@bjheight{\strutht}}%
- \doif\@@bjdepth \v!max{\setstrut\def\@@bjdepth {\strutdp}}%
- \startcolor[\@@bjcolor]% can be made faster, just direct attr
- \vrule
- \!!width \@@bjwidth
- \!!height\@@bjheight
- \!!depth \@@bjdepth
- \stopcolor}
-
-%D \macros
-%D {blackrules}
-%D
-%D One can call for a sequence of black rules, if needed
-%D equally spaced over the given width.
-%D
-%D \showsetup{blackrules}
-%D
-%D The two alternative calls are therefore:
-%D
-%D \startbuffer
-%D Tell me, is this according to the \blackrules[n=6]?
-%D These \blackrules[alternativevariant=b,n=10,distance=.2em,width=4cm] are quite clear.
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D or:
-%D
-%D \startvoorbeeld
-%D \startlines
-%D \getbuffer
-%D \stoplines
-%D \stopvoorbeeld
-%D
-%D We could of course have implemented this macro using
-%D \type{\leaders}, but this would probably have taken more
-%D tokens.
-
-\def\doblackrules[#1]%
- {\hbox\bgroup
- \getparameters[\??bj][#1]%
- \!!widtha\@@bjwidth
- \!!widthb\@@bjdistance
- \doif\@@bjalternative\c!b
- {\scratchcounter\@@bjn
- \ifnum\scratchcounter=\plusone
- \!!widthb\zeropoint
- \else
- \advance\scratchcounter \minusone
- \advance\!!widtha -\scratchcounter\!!widthb
- \divide \!!widtha \@@bjn
- \fi}%
- \startcolor[\@@bjcolor]%
- \dorecurse\@@bjn
- {\vrule
- \!!width \!!widtha
- \!!height\@@bjheight
- \!!depth \@@bjdepth
- \hskip\!!widthb}%
- \unskip
- \stopcolor
- \egroup}
-
-\unexpanded\def\blackrules
- {\dosingleempty\doblackrules}
-
-%D The next commands can be used to draw margin rules. We
-%D support two methods: \marginrule{one for in||line use} and
-%D one that acts on a paragraph. Drawing a margin rule is
-%D rather straightforward because we can use the commands that
-%D put text in the margin.
-
-\def\dodrawmarginrule
- {\setbox\scratchbox\hbox
- {\vrule\!!depth\strutdepth\!!height\strutheight\!!width\@@karulethickness}%
- \smashbox\scratchbox % no \vsmash !!!
- \box\scratchbox}
-
-\def\drawmarginrule
- {\strut\inleft{\dodrawmarginrule}}
-
-%D \macros
-%D {marginrule}
-%D
-%D The first method gobbles words and simply puts a bar in the
-%D margin. This method is not entirely robust.
-%D
-%D \showsetup{marginrule}
-
-\definecomplexorsimple\marginrule
-
-\def\simplemarginrule
- {\let\processword\drawmarginrule
- \processwords}
-
-\def\complexmarginrule[#1]%
- {\ifnum#1<\@@kalevel\relax \else
- \def\@@kadefaultwidth{#1}%
- \expandafter\simplemarginrule
- \fi}
-
-%D We need an auxiliary variable
-
-\def\@@kadefaultwidth{1}
-
-%D \macros
-%D {setupmarginrules}
-%D
-%D This macro definitions show us that we can pass an optional
-%D level, which is matched against the previous set one. The
-%D level can be set up with
-%D
-%D \showsetup{setupmarginrules}
-
-\unexpanded\def\setupmarginrules
- {\dodoubleargument\getparameters[\??ka]}
-
-%D \macros
-%D {startmarginrule}
-%D
-%D The second method collects text and reformats it afterwards,
-%D using the shapebox macros. We prevent local margin rules.
-%D
-%D \showsetup{startmarginrule}
-
-\definecomplexorsimple\startmarginrule
-
-\def\simplestartmarginrule
- {\bgroup
- \let\drawmarginrule\relax
- \let\stopmarginrule\dostopmarginrule
- \beginofshapebox}
-
-\def\complexstartmarginrule[#1]%
- {\bgroup
- \let\drawmarginrule\relax
- \ifnum#1<\@@kalevel\relax
- \let\stopmarginrule\egroup
- \else
- \def\@@kadefaultwidth{#1}%
- \let\stopmarginrule\dostopmarginrule
- \expandafter\beginofshapebox
- \fi}
-
-\def\dostopmarginrule
- {\endofshapebox
- \reshapebox
- {\hbox{\inleftmargin{\dodrawmarginrule}\box\shapebox}}%
- \flushshapebox
- \egroup}
-
-%D \startbuffer
-%D \setupmarginrules[level=5]
-%D
-%D \startmarginrule[1]
-%D First we set the level at~5. Next we typeset this first
-%D paragraph as a level~1 one. As expected no rule show up.
-%D \stopmarginrule
-%D
-%D \startmarginrule[5]
-%D The second paragraph is a level~5 one. As we can see here,
-%D the marginal rule gets a width according to its level.
-%D \stopmarginrule
-%D
-%D \startmarginrule[8]
-%D It will of course be no surprise that this third paragraph
-%D has a even thicker margin rule. This behavior can be
-%D overruled by specifying the width explictly.
-%D \stopmarginrule
-%D \stopbuffer
-%D
-%D In next example we show most features. Watch the rule
-%D thickness adapting itself to the level.
-%D
-%D \startvoorbeeld
-%D \getbuffer
-%D \stopvoorbeeld
-%D
-%D We just said:
-%D
-%D \typebuffer
-
-%D \macros
-%D {vl, hl}
-%D
-%D The command \type{\vl} draws a vertical rule \vl\ with strut
-%D dimensions, multiplied with the factor specified in the
-%D optional argument. The height and depth are clipped \vl[3]
-%D to the baselinedistance. Its horizontal counterpart
-%D \type{\hl} draws a horizontal rule \hl\ with a width of 1em,
-%D multiplied with the optional factor. The horizontal rule is
-%D drawn on top of the baseline.
-%D
-%D \showsetup{vl}
-%D \showsetup{hl}
-
-\def\dovlwdhtdp#1#2#3%
- {\bgroup
- \setbox\scratchbox\hbox
- {\vrule
- \!!width #1\linewidth
- \!!height#2\strutht
- \!!depth #3\strutdp}%
- \dp\scratchbox\strutdp
- \ht\scratchbox\strutht
- \box\scratchbox
- \egroup}
-
-\def\complexvl[#1]%
- {\dovlwdhtdp\plusone{#1}{#1}}
-
-\def\complexhl[#1]%
- {\hbox
- {\vrule
- \!!width #1\s!em
- \!!height\linewidth
- \!!depth \zeropoint}}
-
-\definecomplexorsimple\vl \def\simplevl{\complexvl[1]}
-\definecomplexorsimple\hl \def\simplehl{\complexhl[1]}
-
-%D \macros
-%D {hairline, thinrule, thinrules, setupthinrules}
-%D
-%D Drawing thin lines can of course easily be accomplished by
-%D the \TEX\ primitives \type{\hrule} and \type{\vrule}. The
-%D next few macros however free us from some specifications.
-%D
-%D \startbuffer
-%D some text
-%D
-%D \hairline
-%D
-%D some more text
-%D
-%D \thinrule
-%D
-%D more and more text
-%D
-%D hi \thinrule\ there
-%D
-%D and then the final text
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D becomes
-%D
-%D \startvoorbeeld
-%D \getbuffer
-%D \stopvoorbeeld
-%D
-%D So we've got
-%D
-%D \showsetup{hairline}
-%D \showsetup{thinrule}
-%D
-%D Both can be set up with:
-%D
-%D \showsetup{setupthinrules}
-%D
-%D We also have
-%D
-%D \showsetup{thinrules}
-%D
-%D which looks like: \thinrules[n=2]
-
-\newconstant\ruletype
-
-\def\thinrule
- {\strut
- \bgroup
- \ruletype\plusone
- \processaction
- [\@@dlalternative]
- [ \v!a=>\ruletype\zerocount,% no line
- %\v!b=>\ruletype\plusone ,% height/depth
- \v!c=>\ruletype\plustwo ,% topheight/botdepth
- % 11=>\ruletype\plusone ,% fallback for backgrounds
- 0=>\ruletype\zerocount,% compatible with backgrounds
- % 1=>\ruletype\plusone ,% compatible with backgrounds
- 2=>\ruletype\plustwo ]% compatible with backgrounds
- \doifsomething\@@dlrulethickness
- {\linewidth\@@dlrulethickness}%
- \ifdim\linewidth=\zeropoint
- \ruletype\zerocount
- \else
- \doifnot\@@dlframe\v!on{\ruletype\zerocount}%
- \fi
- \ifnum\ruletype=\plusone
- \doif\@@dlheight\v!max{\let\@@dlheight\!!plusone}%
- \doif\@@dldepth \v!max{\let\@@dldepth \!!plusone}%
- \else
- \let\@@dlheight\!!plusone
- \let\@@dldepth\!!plusone
- \fi
- \freezedimensionwithunit\@@dlheight\strutht
- \freezedimensionwithunit\@@dldepth\strutdp
- \divide\linewidth \plustwo
- \doifelse\@@dlbackground\v!color
- {\startcolor[\@@dlbackgroundcolor]%
- \ifnum\ruletype=\plustwo % prevent overshoot due to rounding
- \leaders
- \hrule
- \!!height\dimexpr\@@dlheight-.5\linewidth\relax
- \!!depth \dimexpr\@@dldepth -.5\linewidth\relax
- \hfill
- \else
- \leaders
- \hrule
- \!!height\@@dlheight
- \!!depth \@@dldepth
- \hfill
- \fi
- \stopcolor
- \ifcase\ruletype
- % no rule
- \or
- \startcolor[\@@dlcolor]%
- \hfillneg
- \leaders\hrule\!!height\linewidth\!!depth\linewidth\hfill
- \stopcolor
- \or
- \startcolor[\@@dlcolor]%
- \hfillneg\leaders\hrule\!!height\dimexpr-\@@dldepth+\linewidth\relax\!!depth\@@dldepth\hfill
- \hfillneg\leaders\hrule\!!height\@@dlheight\!!depth\dimexpr-\@@dlheight+\linewidth\relax\hfill
- \stopcolor
- \fi}
- {\ifcase\ruletype \else
- \startcolor[\@@dlcolor]%
- \leaders\hrule\!!height\@@dlheight\!!depth\@@dldepth\hfill
- \stopcolor
- \fi}%
- \strut
- \carryoverpar\egroup}
-
-\def\hairline
- {\endgraf
- \thinrule
- \endgraf}
-
-\def\dosetupthinrules[#1]%
- {\getparameters[\??dl][#1]}
-
-\unexpanded\def\setupthinrules
- {\dosingleargument\dosetupthinrules}
-
-\def\dothinrules[#1]%
- {\bgroup
- \dosetupthinrules[#1]%
- \@@dlbefore
- \assignvalue\@@dlinterlinespace\@@dlinterlinespace{1.0}{1.5}{2.0}%
- \spacing\@@dlinterlinespace
- \dorecurse\@@dln
- {\ifnum\recurselevel=\@@dln \dothinrulesnobreak \else
- \ifnum\recurselevel=2 \dothinrulesnobreak \fi\fi
- \thinrule
- \ifnum\recurselevel<\@@dln\relax
- % test needed, else messed up whitespace
- \ifx\@@dlinbetween\empty
- \softbreak
- \else
- \endgraf
- \nowhitespace
- \@@dlinbetween
- \fi
- \fi}%
- \doifelsenothing\@@dlafter
- {\carryoverpar\egroup}
- {\@@dlafter\egroup}}
-
-\def\thinrules
- {\dosingleempty\dothinrules}
-
-%D A couple of examples are given below.
-%D
-%D \startbuffer
-%D \setupthinrules[n=3,inbetween=,color=gray]
-%D
-%D test test \thinrules\ test test \par
-%D test test \thinrules [color=green] test test \par
-%D test test \thinrules [height=max, depth=max] test test \par
-%D
-%D \setupthinrules[height=.9,depth=.9]
-%D
-%D test test \thinrules\ test test \par
-%D test test \thinrules [alternativevariant=b] test test \par
-%D test test \thinrules [alternativevariant=c] test test \par
-%D test test \thinrules [alternativevariant=c,inbetween=\vskip2ex] test test \par
-%D \stopbuffer
-%D
-%D \typebuffer {\getbuffer}
-%D
-%D There are a couple of alternative ways to visualize rules
-%D using backgrounds. At first sight these may look strange,
-%D but they make sense in educational settings. The
-%D alternatives are more or less compatible with the more
-%D advanced \METAPOST\ based implementation.
-%D
-%D \startbuffer[a]
-%D \setupthinrules
-%D [n=2,
-%D backgroundcolor=gray ,
-%D rulethickness=1pt,
-%D colorkleur=donkerblauw,
-%D after=\blank,
-%D before=\blank]
-%D \stopbuffer
-%D
-%D \typebuffer[a]
-%D
-%D \startbuffer[b]
-%D \thinrules[alternativevariant=a]
-%D \thinrules[alternativevariant=b]
-%D \thinrules[alternativevariant=c]
-%D \stopbuffer
-%D
-%D \typebuffer[b] \getbuffer[a,b]
-%D
-%D \startbuffer[b]
-%D \thinrules[alternativevariant=a,background=color]
-%D \thinrules[alternativevariant=b,background=color]
-%D \thinrules[alternativevariant=c,background=color]
-%D \stopbuffer
-%D
-%D \typebuffer[b] \getbuffer[a,b]
-%D
-%D \startbuffer[b]
-%D \thinrules[alternativevariant=a,height=.8,depth=.8,background=color]
-%D \thinrules[alternativevariant=b,height=.8,depth=.8,background=color]
-%D \thinrules[alternativevariant=c,height=.8,depth=.8,background=color]
-%D \stopbuffer
-%D
-%D \typebuffer[b] \getbuffer[a,b]
-
-%D \macros
-%D {optimizethinrules}
-%D
-%D By saying \type {\thinrulestrue} or \type {-false}, we
-%D can influence the way dangling lines are handled.
-
-\newif\ifoptimizethinrules \optimizethinrulestrue
-
-\def\dothinrulesnobreak
- {\ifoptimizethinrules\penalty500\fi}
-
-%D \macros
%D {startframedtext, setupframedtexts, defineframedtext}
%D
%D The general framing command we discussed previously, is not
@@ -2713,11 +2379,12 @@
%D
%D The next definition shows the defaults.
-\installcommandhandler \??kd {framedtext} \??kd
+\installcorenamespace{framedtext}
+\installcorenamespace{framedtextlocation}
-\let\setupframedtexts\setupframedtext
+\installframedcommandhandler \??framedtext {framedtext} \??framedtext
-\presetlocalframed[\??kd]
+\let\setupframedtexts\setupframedtext
\setupframedtext
[\c!width=0.75\hsize,
@@ -2753,119 +2420,120 @@
\c!margin=\v!standard]
\appendtoks
- \setuevalue{\e!start\currentframedtext}{\dostartframedtext{\currentframedtext}}%
- \setuevalue{\e!stop \currentframedtext}{\dostopframedtext }%
- \setuevalue {\currentframedtext}{\doframedtext {\currentframedtext}}%
+ \setuevalue{\e!start\currentframedtext}{\pack_framed_text_start {\currentframedtext}}%
+ \setuevalue{\e!stop \currentframedtext}{\pack_framed_text_stop }%
+ \setuevalue {\currentframedtext}{\pack_framed_text_direct{\currentframedtext}}%
\to \everydefineframedtext
-\unexpanded\def\dostartframedtext#1%
+\setvalue{\??framedtextlocation\v!left }{\letframedtextparameter\c!left \relax
+ \letframedtextparameter\c!right\hfill}
+
+\setvalue{\??framedtextlocation\v!right }{\letframedtextparameter\c!left \hfill
+ \letframedtextparameter\c!right\relax}
+
+\setvalue{\??framedtextlocation\v!middle}{\letframedtextparameter\c!left \hfill
+ \letframedtextparameter\c!right\hfill}
+
+\setvalue{\??framedtextlocation\v!none }{\letframedtextparameter\c!left \relax
+ \letframedtextparameter\c!right\relax
+ \settrue\c_framed_text_location_none}
+
+\unexpanded\def\pack_framed_text_start#1%
{\bgroup
\edef\currentframedtext{#1}%
- \dodoubleempty\dodostartframedtext}
+ \dodoubleempty\pack_framed_text_start_indeed}
-\def\dodostartframedtext[#1][#2]%
+\def\pack_framed_text_start_indeed[#1][#2]%
{\doifassignmentelse{#1}
- {\dododostartframedtext[][#1]}
- {\dododostartframedtext[#1][#2]}}
+ {\pack_framed_text_start_continue\empty{#1}}
+ {\pack_framed_text_start_continue{#1}{#2}}}
-\def\dododostartframedtext[#1][#2]% #2 only passed to framed, not to framedtext
+\def\pack_framed_text_start_continue#1#2%
{\setupframedtexts[\currentframedtext][#2]%
\doifsomething{#1}{\setframedtextparameter\c!location{#1}}% does not listen to #3
- \setfalse\framedtextlocationnone
- % somewhat messy ... needs to be redone
- \processaction % \v!low en \v!depth are already taken !
- [\framedtextparameter\c!location]
- [ \v!left=>\letframedtextparameter\c!left \relax
- \letframedtextparameter\c!right\hfill,
- \v!right=>\letframedtextparameter\c!left \hfill
- \letframedtextparameter\c!right\relax,
- \v!middle=>\letframedtextparameter\c!left \hfill
- \letframedtextparameter\c!right\hfill,
- \v!none=>\letframedtextparameter\c!left \relax % new
- \letframedtextparameter\c!right\relax % new
- \settrue\framedtextlocationnone]%
+ \setfalse\c_framed_text_location_none
+ \csname\??framedtextlocation\framedtextparameter\c!location\endcsname
\resetframedtextparameter\c!location
- % removed 06/2001
- % \forgetparindent
- % added 06/2001 [see demo-bbv]
- \localhsize\hsize \checkframedtext
- % so far
- \setbox\framebox\vbox
+ \pack_framed_text_check
+ \setbox\b_framed_normal\vbox
\startboxedcontent
\hsize\localhsize
% \insidefloattrue % ? better
- \normalexpanded{\noexpand\switchtobodyfont[\framedtextparameter\c!bodyfont]}%
- \startcolor[\framedtextparameter\c!color]%
- \localframed[\??kd\currentframedtext][\c!strut=\v!no]% todo: use delayedstrut
- \bgroup
+ \normalexpanded{\switchtobodyfont[\framedtextparameter\c!bodyfont]}%
+% \startcolor[\framedtextparameter\c!color]%
+ \letframedtextparameter\c!strut\v!no
+ \inheritedframedtextframed\bgroup
\let\\=\endgraf
\framedtextparameter\c!inner % oud spul
- \doif{\framedtextparameter\c!depthcorrection}\v!on\doftstartdepthcorrection
- \doinhibitblank % \blank[\v!disable]% plaatst signal
+ \doif{\framedtextparameter\c!depthcorrection}\v!on\pack_framed_text_start_depth_correction
+ \doinhibitblank
\setupindenting[\framedtextparameter\c!indenting]%
- %\doconvertfont{\framedtextparameter\c!style}\empty} %%%%% todo: attr setter
- \dosetframedtextattributes\c!style\c!color}
+ \useframedtextstyleandcolor\c!style\c!color}
%D The \type {none} option is handy for nested usage, as
%D in the presentation styles, where we don't want
%D interference.
-\defineplacement[\??kd][\s!parent=\??kd\currentframedtext]
+\defineplacement[\??framedtext][\s!parent=\??framedtext\currentframedtext]
-\unexpanded\def\dostopframedtext % no \baselinecorrection, see faq docs
+\unexpanded\def\pack_framed_text_stop % no \baselinecorrection, see faq docs
{\endgraf
\removelastskip
- \doif{\framedtextparameter\c!depthcorrection}\v!on\doftstopdepthcorrection
+ \doif{\framedtextparameter\c!depthcorrection}\v!on\pack_framed_text_stop_depth_correction
\stopboxedcontent
- \stopcolor
- \ifconditional\framedtextlocationnone
+% \stopcolor
+ \ifconditional\c_framed_text_location_none
\egroup
- \box\framebox
+ \box\b_framed_normal
\else\ifinsidefloat
\egroup
- \box\framebox
+ \box\b_framed_normal
\else
\egroup
- \placement[\??kd][\c!depthcorrection=\v!off]{\box\framebox}%
+ \placement[\??framedtext][\c!depthcorrection=\v!off]{\box\b_framed_normal}%
\fi\fi
\egroup}
%D We define the general (and original) case by just saying:
-\setfalse\framedtextlocationnone
-
-\def\checkframedtext % messy dependency
- {\ifinsidefloat
- \localhsize\hsize
- \else\ifdim\sidefloatvsize>\zeropoint % will be proper handle
+\def\pack_framed_text_check % messy dependency
+ {\localhsize\hsize
+ \ifinsidefloat \else \ifdim\d_page_sides_vsize>\zeropoint % also possible: \c_page_sides_checks_done>\zeropoint
% \strut % rather clean way to invoke the sidefloat OTR
% \setbox0=\lastbox % and get the widths set, so from now on we
% \setlocalhsize % can have framed texts alongside sidefloats
\checksidefloat
\setlocalhsize
- \else
- \localhsize\hsize
- \fi\fi}
+ \fi \fi}
-\def\doftstartdepthcorrection
+\def\pack_framed_text_start_depth_correction
{\bgroup
- \verticalstrut
- % we need \nowhitespace in case of setups setting whitespace
- % nb, not safe, text vs \vbox as next
- \vskip-\struttotal
- \nowhitespace} % na vskip ! new 20/05/2004, fails with next content being box (\scale{..})
-
-\def\doftstopdepthcorrection
- {\forgetall
- \vskip-\struttotal
- \verticalstrut
- \egroup
- \forgetall % brrr too often
- \vskip-\lineheight
- % will be an option, not default
- % \setbaselinecorrections
- % \donegbotbaselinecorrection
- \verticalstrut}
+ \ifhmode
+ \par
+ \fi
+ \ifvmode
+ \verticalstrut
+ % we need \nowhitespace in case of setups setting whitespace
+ % nb, not safe, text vs \vbox as next
+ \vskip-\struttotal
+ \nowhitespace
+ \fi} % na vskip ! new 20/05/2004, fails with next content being box (\scale{..})
+
+\def\pack_framed_text_stop_depth_correction
+ {\ifhmode
+ \par
+ \fi
+ \ifvmode
+ \forgetall
+ \vskip-\struttotal
+ \verticalstrut
+ \egroup
+ \forgetall % brrr too often
+ \vskip-\lineheight
+ \verticalstrut
+ \else
+ \egroup
+ \fi}
%D Placement can be ignored:
%D
@@ -2885,26 +2553,28 @@
%D The simple brace (or group) delimited case is typeset
%D slightly different and is not aligned.
-\unexpanded\def\doframedtext#1%
+\unexpanded\def\pack_framed_text_direct#1%
{\bgroup
\edef\currentframedtext{#1}%
- \dosingleempty\dodoframedtext}
+ \dosingleempty\pack_framed_text_start_direct}
-\def\dodoframedtext[#1]% beware!
- {\normalexpanded{\noexpand\switchtobodyfont[\\framedtextparameter\c!bodyfont]}%
- \localframed[\??kd\currentframedtext][\c!strut=\v!no,#1]%
+\def\pack_framed_text_start_direct[#1]%
+ {\normalexpanded{\switchtobodyfont[\framedtextparameter\c!bodyfont]}%
+ \letframedtextparameter\c!strut\v!no
+ \iffirstargument
+ \setupcurrentframedtext[#1]%
+ \fi
+ \inheritedframedtextframed\bgroup
+ \blank[\v!disable]%
+ \let\\=\endgraf
+ \framedtextparameter\c!inner
+ \useframedtextstyleandcolor\c!style\c!color
\bgroup
- \blank[\v!disable]%
- \let\\=\endgraf
- \framedtextparameter\c!inner
- \dosetframedtextattributes\c!style\c!color
- \bgroup
- \aftergroup\docloseframedtext
- \let\next=}
+ \aftergroup\pack_framed_text_stop_direct
+ \let\next=}
-\def\docloseframedtext
+\def\pack_framed_text_stop_direct
{\removelastskip
- \dostopattributes
\egroup
\egroup}
@@ -2922,24 +2592,44 @@
%D also simplified the \type {\setupframed} command. There are
%D certainly more places where such improvements can be made.
-\def\defineframed
- {\dodoubleempty\dodefineframed}
+% actually, this can be another command handler .. todo
-\def\dodefineframed[#1][#2]%
+\unexpanded\def\defineframed
+ {\dotripleempty\pack_framed_define}
+
+\def\pack_framed_define[#1][#2][#3]%
{\ifcsname\??ol:#1\endcsname
% already defined, keeps settings
\else
\expandafter\newcount\csname\??ol:#1\endcsname % \the\everypresetframed
\fi
- \getparameters[\??ol#1][\s!parent=\??ol,#2]%
- \setuvalue{#1}{\doframed[#1]}}% % \the\everydefineframed
+ \ifsecondargument
+ \doifassignmentelse{#2}
+ {\getparameters[\??ol#1][\s!parent=\??ol,#2]}%
+ {\ifcsname#2\endcsname
+ \getparameters[\??ol#1][\s!parent=\??ol#2,#3]%
+ \else
+ \getparameters[\??ol#1][\s!parent=\??ol,#3]%
+ \fi}%
+ \else
+ \getparameters[\??ol#1][\s!parent=\??ol,#2]%
+ \fi
+ \setuvalue{#1}{\pack_framed_defined_process[#1]}}% % \the\everydefineframed
+
+\newcount\c_framed_crap
-\def\doframed[#1]%
+\unexpanded\def\pack_framed_defined_process[#1]% official (not much checking, todo: parent)
{\bgroup
- \expandafter\let\expandafter\tempframedcount\csname\??ol:#1\endcsname
- \advance\tempframedcount\plusone
- \expandafter\def\csname\??ol#1:\the\tempframedcount\s!parent\endcsname{\??ol#1}% \copylocalframed
- \dodoubleempty\dolocalframed[\??ol#1:\the\tempframedcount]}
+ \ifcsname\??ol:#1\endcsname
+ \expandafter\let\expandafter\c_framed_temp\csname\??ol:#1\endcsname
+ \else
+ \let\c_framed_temp\c_framed_crap
+ \fi
+ \advance\c_framed_temp\plusone
+ \expandafter\def\csname\??ol#1:\the\c_framed_temp\s!parent\endcsname{\??ol#1}% \inheritlocalframed
+ \dodoubleempty\pack_framed_process[\??ol#1:\the\c_framed_temp]}
+
+\let\placeframed\pack_framed_defined_process % new per 2012/04/23
%D We can do:
%D
@@ -2949,464 +2639,6 @@
%D
%D but the existing one is ok as well (less csname messy too).
-%D \macros
-%D {textrule, starttextrule, setuptextrules}
-%D
-%D Putting rules before and after a paragraph is very space
-%D sensitive, but the next command handles that quite well. It
-%D comes in two disguises:
-%D
-%D \startbuffer
-%D \textrule[top]{fragments}
-%D \input reich
-%D \textrule
-%D \stopbuffer
-%D
-%D \bgroup \typebuffer \getbuffer \egroup
-%D
-%D \startbuffer
-%D \setuptextrules
-%D [width=90pt,distance=12pt,rulecolor=blue,
-%D bodyfont=small,style=\sc,color=red]
-%D
-%D \starttextrule{Ship Building Tools}
-%D \nl \setuptolerance[tolerant] \input materie
-%D \stoptextrule
-%D \stopbuffer
-%D
-%D \bgroup \typebuffer \getbuffer \egroup
-%D
-%D \startbuffer
-%D \setuptextrules
-%D [location=inmargin,
-%D bodyfont=small,style=slantedbold]
-%D
-%D \starttextrule{wonderful}
-%D \input tufte
-%D \stoptextrule
-%D \stopbuffer
-%D
-%D \bgroup \typebuffer \getbuffer \egroup
-%D
-%D The formal definition of these commands is:
-%D
-%D \showsetup{textrule}
-%D \showsetup{starttextrule}
-%D \showsetup{setuptextrules}
-%D
-%D The implementation looks a bit complicated due to the
-%D optional arguments.
-
-\unexpanded\def\setuptextrules
- {\dodoubleargument\getparameters[\??tl]}
-
-\def\complextextrule[#1]% if needed we can make it installable
- {\let\next\dobottomtextrule
- \processaction
- [#1]
- [ \v!top=>\let\next\dotoptextrule,
- \v!middle=>\let\next\domiddletextrule,
- \v!bottom=>\let\next\dobottomtextrule]%
- \dosinglegroupempty\next}
-
-\definecomplexorsimple\textrule
-
-\def\simpletextrule
- {\dosinglegroupempty\dounknowntextrule}
-
-\def\docomplextextrule#1%
- {\bgroup
- \advance\hsize\dimexpr-\rightskip-\leftskip\relax
- \setbox\scratchbox\hbox to \hsize
- {\dimen4\dimexpr .5ex+.5\linewidth\relax
- \dimen6\dimexpr-.5ex+.5\linewidth\relax
- \doifsomething{#1}
- {\doifelse\@@tllocation\v!inmargin
- {\llap{\doattributes\??tl\c!style\c!color{#1}\hskip\leftmargindistance}}
- {\color[\@@tlrulecolor]
- {\vrule\!!height\dimen4\!!depth\dimen6\!!width\@@tlwidth}%
- \hbox spread 2\dimexpr\@@tldistance\relax
- {\hss\doattributes\??tl\c!style\c!color{\strut#1}\hss}}}%
- \color[\@@tlrulecolor]
- {\leaders\hrule\!!height\dimen4\!!depth\dimen6\hfill}}%
- \ht\scratchbox\strutht
- \dp\scratchbox\strutdp
- \noindent\box\scratchbox
-%\nobreak\verticalstrut\kern-\struttotal
-% evt \witruimte
- \egroup}
-
-\def\dotoptextrule#1%
- {\page[\v!preference] % interferes
- %\whitespace % no
- \@@tlbefore
- \docomplextextrule{#1}%
-% todo, option: \doifnothing{#1}{\ruledvskip-.5ex}
- \nowhitespace
- \@@tlinbetween
- \endgraf}
-
-\def\dodobottomtextrule#1#2%
- {\ifhmode
- \endgraf
- \fi
- \dimen0\strutdp
- \ifdim\prevdepth>\strutdp\else % was <\strutdp
- \ifdim\prevdepth>\zeropoint
- \advance\dimen0 -\prevdepth
- \fi
- \fi
- \advance\dimen0 .5ex
- \vskip\dimen0
-% ==
-% \vskip\dimexpr \strutdp + .5ex
-% \ifdim\prevdepth>\strutdp\else\ifdim\prevdepth>\zeropoint-\prevdepth\fi\fi\relax
-%
- \@@tlinbetween
- \doifelsenothing{#2}
- {\bgroup
- \advance\hsize\dimexpr-\rightskip-\leftskip\relax
- \nointerlineskip
- \moveleft-\leftskip\vbox
- {\color[\@@tlrulecolor]
- {\hrule\!!depth\linewidth\!!height\zeropoint\!!width\hsize}}%
- \egroup}
- {\docomplextextrule{#2}}%
- \ifvmode\prevdepth\zeropoint\fi
- #1%
- \page[\v!preference]}
-
-\def\dobottomtextrule
- {\dodobottomtextrule\@@tlafter}
-
-\def\domiddletextrule
- {\dodobottomtextrule\@@tlinbetween}
-
-\def\dounknowntextrule
- {\iffirstargument
- \@EA\dotoptextrule
- \else
- \@EA\dobottomtextrule\@EA\empty
- \fi}
-
-%D The grouped commands also supports bodyfont switching:
-
-\unexpanded\def\starttextrule#1%
- {\bgroup
- \def\dounknowntextrule{\domiddletextrule}
- \dotoptextrule{#1}
- \bgroup
- \doifsomething\@@tlbodyfont{\switchtobodyfont[\@@tlbodyfont]}}
-
-\unexpanded\def\stoptextrule
- {\par
- \egroup
- \dobottomtextrule\empty
- \egroup}
-
-%D \macros
-%D {fillinrules, setupfillinrules}
-%D
-%D The next few commands do not really deserve a place in a
-%D core module, because they deal with specific typography.
-%D Nevertheless I decided to make them part of the core,
-%D because they permit us to make questionaires. Let's start
-%D with some examples.
-%D
-%D \fillinrules[n=2,width=fit]{first}
-%D \fillinrules[n=2,width=broad]{first}
-%D \fillinrules[n=2,width=3cm]{first}
-%D \fillinrules[n=2,width=3cm,distance=.5em,separator=:]{first}
-%D \fillinrules[n=2]{first}{last}
-%D \fillintext{first}{last} \input reich \par
-%D
-%D The main command is \type{\fillinrules}. This command takes
-%D one and an optional second argument and sets a paragraph with
-%D empty visualized lines.
-%D
-%D \showsetup{fillinrules}
-%D \showsetup{setupfillinrules}
-
-\unexpanded\def\setupfillinrules
- {\dodoubleargument\getparameters[\??il]}
-
-\definecomplexorsimpleempty\fillinrules
-
-\def\complexfillinrules[#1]%
- {\def\docomplexfillinrules##1##2%
- {\dodocomplexfillinrules[#1]{##1}{##2}{\thinrules
- [\c!n=\@@iln,\c!interlinespace=\@@ilinterlinespace,\c!before=,\c!after=]}}%
- \dodoublegroupempty\docomplexfillinrules}
-
-\def\dodocomplexfillinrules[#1]#2#3#4%
- {\endgraf
- \@@ilbefore
- \begingroup
- \setupfillinrules[#1]%
- \noindent
- \doifsomething{#2}
- {\doifelse\@@ilwidth\v!fit
- {\let\@@ildistance\!!zeropoint
- \hbox}
- {\doifelse\@@ilwidth\v!broad
- {\hbox}
- {\hbox to \@@ilwidth}}%
- \bgroup
- \doattributes\??il\c!style\c!color{\strut#2\hfill\@@ilseparator}%
- \hskip\@@ildistance
- \egroup}%
- %\hangindent=\wd0\relax % tzt hang=yes,n
- %\parindent=\hangindent
- %\box0\relax
- \setupwhitespace[\v!big]%
- \ignorespaces
- #4%
- \doifsomething{#3}
- {\kern\@@ildistance
- \doattributes\??il\c!style\c!color{#3\strut}}%
- \endgroup
- \endgraf
- \@@ilafter}
-
-%D \macros
-%D {fillintext}
-%D
-%D To provide compatible layouts when texts and lines are
-%D mixed, one can typeset a paragraph by using the command
-%D \type{\fillintext}.
-%D
-%D \showsetup{fillintext}
-
-\definecomplexorsimpleempty\fillintext
-
-\def\complexfillintext[#1]% rather rough, using an \unhbox is suboptimal
- {\def\docomplexfillintext##1##2%
- {\dowithnextbox
- {\dodocomplexfillinrules[#1]{##1}{\hfill##2}{\unhbox\nextbox\unskip}}%
- \hbox\bgroup\let\par\egroup\ignorespaces}%
- \dodoublegroupempty\docomplexfillintext}
-
-%D \macros
-%D {fillinline, setupfillinlines}
-%D
-%D Another member of the family takes care of putting a (often
-%D small) rule after a piece of text, like
-%D
-%D \startbuffer
-%D \fillinline \input reich \par
-%D \fillinline[margin=0cm] \input reich \par
-%D \stopbuffer
-%D
-%D \startvoorbeeld
-%D \getbuffer
-%D \stopvoorbeeld
-%D
-%D which was typeset by saying:
-%D
-%D \typebuffer
-%D
-%D The two commands that take care of this are:
-%D
-%D \showsetup{fillinline}
-%D \showsetup{setupfillinlines}
-
-\unexpanded\def\setupfillinlines
- {\dodoubleargument\getparameters[\??iv]}
-
-\definecomplexorsimpleempty\fillinline
-
-\def\complexfillinline[#1]%
- {%\endgraf % interferes with \definedescription cum suis
- \@@ivbefore
- \begingroup
- \setupfillinlines[#1]%
- \advance\rightskip \@@ivmargin
- \parfillskip\zeropoint
- \def\par % very dangerous
- {\let\par\endgraf % -)
- \ifhmode\unskip\hfill\fi
- \scratchdimen\dimexpr\@@ivwidth-\@@ivdistance\relax
- \ifdim\scratchdimen>\@@ivmargin\else\expandafter\rlap\fi
- {\kern\@@ivdistance
- \vrule
- \!!width \scratchdimen
- \!!height.5\linewidth
- \!!depth .5\linewidth}%
- \endgraf % !
- \endgroup
- \endgraf % !
- \@@ilafter}}
-
-%D \stopdocumentation
-%D \bgroup
-%D
-%D \setupframedtexts
-%D [setuptext]
-%D [background=color,backgroundcolor=white]
-%D
-%D \startbuffer
-%D \setupbackground
-%D [backgroundoffset=4pt,
-%D background=screen,
-%D frame=on,
-%D framecolor=red,
-%D leftoffset=2pt]
-%D \stopbuffer
-%D
-%D \getbuffer
-%D
-%D \startbackground
-%D
-%D \macros
-%D {setupbackground,startbackground,background}
-%D
-%D The section deals with backgrounds in the running text. This
-%D means that texts is to be collected and split over pages. To
-%D show what can be done, we provide this part of the
-%D documentation with some gray background and a red frame.
-%D Both the background and frame can have all characteristics
-%D of \type{\framed}. This time we used the setting:
-%D
-%D \typebuffer
-%D
-%D The implementation is not that sophisticated, but suffices.
-%D The main problem with this kind of functionality is to get
-%D the spacing all right.
-
-%D Specifying the background is more or less the same as
-%D specifying a framed box.
-%D
-%D \showsetup{setupbackground}
-
-\presetlocalframed[\??ag]
-
-\def\dosetupbackground[#1]%
- {\getparameters[\??ag][#1]%
- \doifelse\@@agstate\v!start
- {\let\startbackground\dostartbackground
- \let\stopbackground \dostopbackground
- \let\background \dobackground}
- {\let\startbackground\relax
- \let\stopbackground \relax
- \let\background \relax}}
-
-\unexpanded\def\setupbackground
- {\dosingleargument\dosetupbackground}
-
-%D Actually typesetting the background is implemented rather
-%D straightforward. We need to handle some spacing as well as
-%D the (often) a bit smaller horizontal size.
-%D
-%D \showsetup{startbackground}
-%D
-%D Although we could have used a scratch one, we first
-%D declare a boolean.
-
-% 0=no-split, 1=no-split+indent, 2=split, 3=split+indent
-
-\setnewconstant\backgroundsplitmode\plusthree
-
-%D The \type{\vbox to \lineheight{}\vskip\zeropoint}
-%D construction gives the first real line a decent height by
-%D adding a dummy line.
-
-\def\dostartbackground
- {\endgraf
- \bgroup
- \setbox0\vbox\bgroup
- \vbox to \lineheight{}\vskip\zeropoint
- \blank[\v!disable]
- % \advance\hsize -\@@agleftoffset
- % \advance\hsize -\@@agrightoffset
- \leftskip \@@agleftoffset % new **
- \rightskip\@@agrightoffset} % new **
-
-%D This dummy line is removed by \type{\setbox2=\vsplit0 to
-%D \lineheight}. That way \type{\topskip} takes care of the
-%D lineheight. I'll probably forget to apply this trick
-%D elsewhere.
-
-\def\dostopbackground % improved version (i hope)
- {\endgraf
- \removelastskip
- \egroup
- \dimen2\leftskip % new **
- \forgetall
- \ifinsidefloat
- \backgroundsplitmode\zerocount
- \fi
- \ifcase\backgroundsplitmode
- \localframed[\??ag][\c!offset=\v!overlay]{\box0}%
- \or
- \hskip\dimen2
- \localframed[\??ag][\c!offset=\v!overlay]{\box0}%
- \else
- \splitmaxdepth\boxmaxdepth
- \splittopskip\topskip
- \setbox2\vsplit0 to \lineheight % get rid of fake line
- \loop
- \ifdim\pagetotal=\zeropoint % empty page
- \scratchdimen\textheight
- \backgroundsplitmode\plusone % split to max height
- \else
- \setbox\scratchbox\vbox{\@@agbefore}%
- \scratchdimen\dimexpr\pagegoal-\ht\scratchbox-\pagetotal\relax
- \backgroundsplitmode\plustwo % split to partial height
- \fi
- \advance\scratchdimen\dimexpr-\@@agtopoffset-\@@agbottomoffset\relax
- \ifdim\scratchdimen>2\lineheight\relax % reasonable, will be configurable
- \ifdim\ht0>\scratchdimen % larger than page
- \setbox2\vsplit0 to \scratchdimen
- \else
- \setbox2\box0
- \backgroundsplitmode\zerocount % no split
- \fi
- \setbox2\vbox \ifcase\backgroundsplitmode\or to \textheight \fi % max split
- {\vskip\@@agtopoffset
- \unvcopy2
- \prevdepth\dp2
- \obeydepth
- \vskip\@@agbottomoffset
- \vfill}
- \@@agbefore
- \ifcase\backgroundsplitmode\or\or % partial split
- \ifdim\pagegoal<\maxdimen
- \pagegoal=1.2\pagegoal % be a bit more tolerant
- \fi
- \fi
- \startlinecorrection
- %\localframed[\??ag][\c!offset=\v!overlay]{\hskip\@@agleftoffset\box2\hskip\@@agrightoffset}%
- \ifnum\backgroundsplitmode=\plusthree \hskip\dimen2 \fi %
- \localframed[\??ag][\c!offset=\v!overlay]{\box2}% new **
- \stoplinecorrection
- \ifcase\backgroundsplitmode % no split
- \@@agafter
- \else % some split
- \vfill\eject % geen \page !
- \fi
- \else
- \page
- \fi
- \ifdim\ht0>\zeropoint \repeat
- \fi
- \egroup
- \endgraf}
-
-%D As a bonus we also have a short command, that is of not
-%D much use, but kept there for historic reasons.
-%D
-%D \showsetup{background}
-
-\def\dobackground
- {\bgroup
- \dowithnextbox
- {\localframed[\??ag][\c!offset=\v!overlay]{\flushnextbox}\egroup}
- \vbox}
-
-%D \stopdocumentation
-%D \stopbackground
-%D \egroup
-
%D New, for the moment private; let's see when GB finds out
%D about this one and its obscure usage. It's used in:
%D
@@ -3442,9 +2674,12 @@
%D
%D \typebuffer
-\def\framedcontentparameter #1{\csname\doframedcontentparameter{\??fc\@@framedcontent}#1\endcsname}
+% to be redone
+
+\def\framedcontentparameter #1{\csname\doframedcontentparameter{\??fc\currentframedcontent}#1\endcsname}
\def\doframedcontentparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doframedcontentparentparameter\csname#1\s!parent\endcsname#2\fi}
\def\doframedcontentparentparameter#1#2{\ifx#1\relax\s!empty\else\doframedcontentparameter#1#2\fi}
+\def\letframedcontentparameter #1{\expandafter\let\csname\??fc\currentframedcontent#1\endcsname}
\presetlocalframed[\??fc]
@@ -3461,9 +2696,6 @@
%\c!width=\v!fit,
\c!offset=\v!overlay]
-\def\letframedcontentparameter#1%
- {\letvalue{\??fc\@@framedcontent#1}}
-
\unexpanded\def\defineframedcontent
{\dodoubleempty\dodefineframedcontent}
@@ -3478,17 +2710,20 @@
\processcommacommand[#1]\docommand}
\unexpanded\def\startframedcontent
- {\dosingleempty\dostartframedcontent}
+ {\dosingleempty\pack_framed_start_content}
-\def\dostartframedcontent[#1]%
+\def\pack_framed_start_content[#1]%
{\bgroup
- \edef\@@framedcontent{#1}%
- \let\stopframedcontent\egroup
- \doifnot{#1}\v!off{\dodostartframedcontent{#1}}}
+ \edef\currentframedcontent{#1}%
+ \ifx\currentframedcontent\v!off
+ \let\stopframedcontent\egroup
+ \else
+ \let\stopframedcontent\pack_framed_stop_content_indeed
+ \expandafter\pack_framed_start_content_indeed
+ \fi}
-\def\dodostartframedcontent#1%
- {\unexpanded\def\stopframedcontent{\dostopframedcontent{#1}}%
- \setbox\framebox\hbox\bgroup
+\def\pack_framed_start_content_indeed
+ {\setbox\b_framed_normal\hbox\bgroup
\setlocalhsize
\hsize\localhsize
\advance\hsize\dimexpr-\framedcontentparameter\c!leftoffset-\framedcontentparameter\c!rightoffset \relax
@@ -3500,7 +2735,7 @@
\forgetall
\blank[\v!disable]}
-\def\dostopframedcontent#1%
+\def\pack_framed_stop_content_indeed
{\removelastskip
\egroup
\vskip\framedcontentparameter\c!bottomoffset
@@ -3517,46 +2752,12 @@
% plaats ?
\ifdone\startlinecorrection\fi
\framedcontentparameter\c!left % new
- \localframed[\??fc#1]{\box\framebox}%
+ \localframed[\??fc\currentframedcontent]{\box\b_framed_normal}% hm
\framedcontentparameter\c!right % new
\ifdone\stoplinecorrection\fi
\egroup}
-%D \macros
-%D {backgroundline}
-%D
-%D For the moment an undocumented feature, but a cancidate
-%D for going public.
-
-\def\backgroundline[#1]%
- %{\doifsomething{#1}{\dobackgroundline{#1}}\hbox}
- {\doifcolorelse{#1}{\dobackgroundline{#1}\hbox}\hbox}
-
-% \def\backgroundline[#1]%
-% {\doifcolor{#1}{\dobackgroundline{#1}}\hbox}
-
-\def\dobackgroundline#1%
- {\dowithnextbox
- {\hbox
- {\startcolor[#1]%
- \vrule
- \!!width \nextboxwd
- \!!height\nextboxht
- \!!depth \nextboxdp
- \stopcolor
- \hskip-\nextboxwd
- \flushnextbox}}}
-
-%D \macros
-%D {encircled}
-%D
-%D Some not so robust left||overs (borrowed from Knuth,
-%D \TEX Book\ page 356):
-
-\def\encircled#1%
- {{\ooalign{\hfil\raise0.07ex\hbox{{\tx#1}}\hfil\crcr\mathhexbox20D}}}
-
-\let\omcirkeld\encircled
+% A shared setting.
\setuplinewidth
[\v!medium]
@@ -3567,163 +2768,51 @@
\setupframed
[\c!width=\v!fit,
\c!height=\v!broad,
- \c!lines=,
+ %\c!lines=,
\c!offset=0.25ex, % \defaultframeoffset
\c!empty=\v!no,
\c!frame=\v!on,
- \c!topframe=,
- \c!bottomframe=,
- \c!leftframe=,
- \c!rightframe=,
+ %\c!topframe=,
+ %\c!bottomframe=,
+ %\c!leftframe=,
+ %\c!rightframe=,
\c!radius=.5\bodyfontsize,
\c!rulethickness=\linewidth,
\c!corner=\v!rectangular,
\c!depth=\zeropoint,
- \c!foregroundcolor=,
- \c!foregroundstyle=,
- \c!background=,
+ %\c!foregroundcolor=,
+ %\c!foregroundstyle=,
+ %\c!background=,
\c!backgroundscreen=\@@rsscreen,
- \c!backgroundcolor=,
+ %\c!backgroundcolor=,
\c!backgroundoffset=\zeropoint,
- \c!framecolor=,
+ %\c!framecolor=,
\c!frameoffset=\zeropoint,
+ % somewhat messy
\c!backgroundcorner=\framedparameter\c!corner,
\c!backgroundradius=\framedparameter\c!radius,
\c!backgrounddepth=\framedparameter\c!depth,
\c!framecorner=\framedparameter\c!corner,
\c!frameradius=\framedparameter\c!radius,
\c!framedepth=\framedparameter\c!depth,
- \c!component=,
- \c!align=,
+ %
+ %\c!component=,
+ %\c!region=,
+ %\c!align=,
\c!bottom=\vss,
- \c!top=,
+ %\c!top=,
\c!autostrut=\v!yes,
\c!location=\v!normal,
- \c!orientation=,
+ %\c!orientation=,
\c!autowidth=\v!yes,
- \c!setups=,
- \c!strut=\v!yes]
+ %\c!setups=,
+ \c!strut=\v!yes,
+ %\c!loffset=\zeropoint,
+ %\c!roffset=\zeropoint,
+ %\c!toffset=\zeropoint,
+ ]%\c!boffset=\zeropoint]
\setupscreens
- [%\c!factor=1.0, % obsolete
- %\c!method=\v!external, % obsolete
- \c!screen=0.95]
-
-\setupblackrules
- [\c!n=3,
- \c!width=1em,
- \c!height=1ex,
- \c!depth=\!!zeropoint,
- \c!alternative=\c!a,
- \c!distance=.25ex,
- \c!color=]
-
-\setupmarginrules
- [\c!level=0,
- \c!rulethickness=\@@kadefaultwidth\linewidth]
-
-\setupthinrules
- [\c!interlinespace=\v!small,
- \c!n=3,
- \c!before=,
- \c!inbetween={\blank[\v!white]},
- \c!after=,
- \c!color=,
- \c!height=.5\linewidth,
- \c!depth=.5\linewidth,
- \c!frame=\v!on, % compatible with textbackgrounds
- \c!alternative=\v!b,
- \c!backgroundcolor=,
- \c!background=,
- \c!rulethickness=]
-
-\setuptextrules
- [\c!location=\v!left,
- \c!before=\blank,
- \c!after=\blank,
- \c!inbetween=,
- \c!width=2em,
- \c!style=\v!bold,
- \c!color=,
- \c!rulecolor=,
- \c!bodyfont=,
- \c!distance=.5em]
-
-\setupfillinrules
- [\c!width=\v!broad,
- \c!distance=1em,
- \c!before=\blank,
- \c!after=\blank,
- \c!n=1,
- \c!interlinespace=\v!small,
- \c!separator=,
- \c!style=\v!normal,
- \c!color=]
-
-\setupfillinlines
- [\c!width=3cm,
- \c!margin=\@@ivwidth,
- \c!distance=1em,
- \c!before=\blank,
- \c!after=\blank]
-
-\setupbackground
- [\c!leftoffset=.5\bodyfontsize,
- \c!rightoffset=\@@agleftoffset,
- \c!topoffset=\!!zeropoint,
- \c!bottomoffset=\@@agtopoffset,
- \c!state=\v!start,
- \c!radius=.5\bodyfontsize,
- \c!corner=\v!rectangular,
- \c!frame=\v!off,
- \c!color=,
- \c!depth=\!!zeropoint,
- \c!background=\v!screen,
- \c!backgroundcolor=\@@agcolor,
- \c!screen=\@@rsscreen,
- \c!before=,
- \c!after=]
-
-% Experimental extension:
-
-\def\c!loffset{loffset}
-\def\c!roffset{roffset}
-\def\c!toffset{toffset}
-\def\c!boffset{boffset}
-
-\getparameters
- [\??oi]
- [\c!loffset=\zeropoint,
- \c!roffset=\zeropoint,
- \c!toffset=\zeropoint,
- \c!boffset=\zeropoint]
-
-\newdimen\!!framedloffset
-\newdimen\!!framedroffset
-\newdimen\!!framedtoffset
-\newdimen\!!framedboffset
-
-\def\setextraframedoffsets
- {\boxhasextraoffsetfalse
- \!!framedloffset\framedparameter\c!loffset
- \!!framedroffset\framedparameter\c!roffset
- \!!framedtoffset\framedparameter\c!toffset
- \!!framedboffset\framedparameter\c!boffset
- \relax
- \ifzeropt\!!framedloffset\else \advance\!!framedwidth -\!!framedloffset \boxhasextraoffsettrue \fi
- \ifzeropt\!!framedroffset\else \advance\!!framedwidth -\!!framedroffset \boxhasextraoffsettrue \fi
- \ifzeropt\!!framedtoffset\else \advance\!!framedheight-\!!framedtoffset \boxhasextraoffsettrue \fi
- \ifzeropt\!!framedboffset\else \advance\!!framedheight-\!!framedboffset \boxhasextraoffsettrue \fi}
-
-\def\applyextraframedoffsets
- {\setbox\framebox\vbox\bgroup
- \vskip\!!framedtoffset
- \hbox\bgroup
- \hskip\!!framedloffset
- \box\framebox
- \hskip\!!framedroffset
- \egroup
- \vskip\!!framedboffset
- \egroup}
+ [\c!screen=0.95]
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-app.mkii b/Master/texmf-dist/tex/context/base/page-app.mkii
index e5c149aa0c7..75e0cf87467 100644
--- a/Master/texmf-dist/tex/context/base/page-app.mkii
+++ b/Master/texmf-dist/tex/context/base/page-app.mkii
@@ -5,7 +5,7 @@
%D subtitle=Independent page building,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-app.mkiv b/Master/texmf-dist/tex/context/base/page-app.mkiv
index b42eef05403..df9607daaca 100644
--- a/Master/texmf-dist/tex/context/base/page-app.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-app.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Independent page building,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,106 +17,127 @@
\unprotect
+\installcorenamespace{fittingpage}
+
+\installframedcommandhandler \??fittingpage {fittingpage} \??fittingpage
+
+\newdimen\d_page_fitting_width
+\newdimen\d_page_fitting_height
+\newbox \b_page_fitting
+
\definepapersize
- [\??fp\s!dummy]
- [\c!width=\fittingwd,
- \c!height=\fittinght]
+ [fittingpage]
+ [\c!width=\d_page_fitting_width,
+ \c!height=\d_page_fitting_height]
+
+\definemakeup
+ [fittingpage]
+ [\c!textstate=\v!empty,
+ \c!doublesided=\v!no,
+ \c!pagestate=\fittingpageparameter\c!pagestate]%
\definelayout
- [\??fp\s!dummy]
- [\c!width=\fittingwd,\c!height=\fittinght,\c!location=\v!middle,
- \c!topspace=\!!zeropoint,\c!backspace=\!!zeropoint,
- \c!cutspace=\!!zeropoint,\c!bottomspace=\!!zeropoint,
- \c!textdistance=\!!zeropoint,\c!lines=0,\c!grid=\v!no,
- \c!top=\!!zeropoint,\c!bottom=\!!zeropoint,
- \c!margin=\!!zeropoint,\c!edge=\!!zeropoint,
- \c!leftmargin=\!!zeropoint,\c!leftedge=\!!zeropoint,
- \c!rightmargin=\!!zeropoint,\c!rightedge=\!!zeropoint,
- \c!header=\!!zeropoint,\c!footer=\!!zeropoint]
-
-\def\dostartfittingpage[#1][#2]%
+ [fittingpage]
+ [\v!page]
+ [\c!width=\d_page_fitting_width,
+ \c!height=\d_page_fitting_height,
+ \c!location=\v!middle]
+
+\appendtoks
+ \setuevalue{\e!start\currentfittingpage}{\startfittingpage[\currentfittingpage]}%
+ \setuevalue{\e!stop \currentfittingpage}{\stopfittingpage}%
+\to \everydefinefittingpage
+
+\unexpanded\def\startfittingpage
+ {\dodoubleempty\page_fitting_start}
+
+\def\page_fitting_start[#1][#2]%
{\page % this is kind of tricky! there can be preceding page refs
\autostarttext
\bgroup % resulting in a zero height page; test fig-make !
+ \setupinterlinespace[\v!top=0]% no topskip
\def\currentfittingpage{#1}%
\dontcomplain
% runs under current page regime, i.e. page variables passed to mp
- \getparameters[\currentfittingpage][\c!paper=,#2]% auto or size or nothing
- \setbox\scratchbox\hbox
- \bgroup
- % needed later \getparameters[\currentfittingpage][\c!paper=,#2]% auto or size or nothing
- \doifvalue{\currentfittingpage\c!margin}\v!page % undocumented
- {\offsetbox
+ \setupcurrentfittingpage[\c!paper=,#2]% auto or size or nothing
+ \doifelsenothing{\fittingpageparameter\c!command}
+ \page_fitting_start_normal
+ \page_fitting_start_command}
+
+\def\page_fitting_start_command
+ {\grabuntil{\e!stop\currentfittingpage}\page_fitting_stop_command}
+
+\def\page_fitting_stop_command#1%
+ {\page_fitting_start_normal
+ \fittingpageparameter\c!command{#1}%
+ \page_fitting_stop_normal}
+
+\def\page_fitting_start_normal
+ {\setbox\b_page_fitting\hbox
+ \bgroup
+ \inheritedfittingpageframed
+ \bgroup
+ \gobblespacetokens}
+
+\unexpanded\def\page_fitting_stop_normal % todo: figure out why a small mp image gets shifted
+ {\removeunwantedspaces
+ \egroup
+ \egroup
+ % finalize
+ \doif{\fittingpageparameter\c!margin}\v!page
+ {\setbox\b_page_fitting\hbox\bgroup
+ \offsetbox
[\c!leftoffset=\backspace,
\c!rightoffset=\cutspace,
\c!topoffset=\topspace,
- \c!bottomoffset=\bottomspace]\hbox}%
- \bgroup
- \scale[\c!scale=\getvalue{\currentfittingpage\c!scale}]%
- \bgroup\localframed[\currentfittingpage]%
- \bgroup}
-
-\def\dostopfittingpage
- {\egroup % localframed
- \egroup % scale
- \egroup % offsetbox
- \egroup % scratchbox
- \edef\fittingwd{\the\wd\scratchbox}%
- \edef\fittinght{\the\ht\scratchbox}%
- \startlocallayout
- \ifdim\fittinght<\lineheight
- % write status : too small
- \setbox\scratchbox\vbox to \lineheight{\vss\box\scratchbox\vss}%
- \edef\fittinght{\the\lineheight}%
+ \c!bottomoffset=\bottomspace]
+ {\box\b_page_fitting}%
+ \egroup}%
+ \doifsomething{\fittingpageparameter\c!scale}
+ {\setbox\b_page_fitting\hbox\bgroup
+ \scale[\c!scale=\fittingpageparameter\c!scale]{\box\b_page_fitting}%
+ \egroup}%
+ \ifdim\ht\b_page_fitting=\zeropoint
+ \ht\b_page_fitting\onepoint
+ \fi
+ \ifdim\wd\b_page_fitting=\zeropoint
+ \wd\b_page_fitting\onepoint
\fi
+ \d_page_fitting_width \wd\b_page_fitting
+ \d_page_fitting_height\ht\b_page_fitting
+ \startlocallayout % still valid?
\let\checkcurrentlayout\relax % else interference with odd/even layout
\processaction
- [\getvalue{\currentfittingpage\c!paper}]
+ [\fittingpageparameter\c!paper]
[ \v!auto=>\def\fittingpapersize{\printpapersize},
\s!unknown=>\let\fittingpapersize\commalistelement,
- \s!default=>\def\fittingpapersize{\??fp\s!dummy}]%
- \expanded{\setuppapersize[\??fp\s!dummy][\fittingpapersize]}%
- \definelayout
- [\v!page]%
- [\c!location=\v!middle,
- \c!width=\fittingwd,
- \c!height=\fittinght]%
- \setuplayout
- [\v!page]%
- \startmakeup[\v!standard][\c!textstate=\v!empty,\c!doublesided=\v!no,\c!pagestate=\getvalue{\currentfittingpage\c!pagestate}]%
- \centerbox{\box\scratchbox}%
+ \s!default=>\def\fittingpapersize{fittingpage}]%
+ \expanded{\setuppapersize[fittingpage][\fittingpapersize]}%
+ \startmakeup[fittingpage]%
+ \box\b_page_fitting
\stopmakeup
- \stoplocallayout
+ \stoplocallayout % still valid?
\egroup
\autostoptext}
-%D \TEX\ pages (for \METAPOST\ pages, see \type {meta-fig}):
-
-\presetlocalframed[\??tg]
-
-\unexpanded\def\setupTEXpage
- {\dodoubleargument\getparameters[\??tg]}
-
-\unexpanded\def\startTEXpage
- {\dosingleempty\dostartTEXpage}
-
-\def\dostartTEXpage[#1]%
- {\dostartfittingpage[\??tg][#1]\gobblespacetokens}
+\let\stopfittingpage\page_fitting_stop_normal
-\unexpanded\def\stopTEXpage
- {\removelastspace
- \dostopfittingpage}
-
-\setupTEXpage
- [\c!scale=1000,
- \c!pagestate=,
+\setupfittingpage
+ [%\c!scale=1000,
+ %\c!pagestate=,
\c!strut=\v!no,
- \c!align=\v!normal, % needed, else problems !
+ \c!align=\v!normal,
\c!offset=\v!overlay,
\c!width=\v!fit,
\c!height=\v!fit,
\c!frame=\v!off]
+%D \TEX\ pages (for \METAPOST\ pages, see \type {meta-fig}):
+
+\definefittingpage
+ [TEXpage]
+ [\c!align=\v!normal] % needed, else problems !
+
%D For Mojca:
%D
%D \starttyping
@@ -127,17 +148,17 @@
%D maybe I should support stream=yes in framed.
\unexpanded\def\startTEXstream
- {\dosingleempty\dostartTEXstream}
+ {\dosingleempty\page_streams_TEX_start}
-\def\dostartTEXstream[#1]% old code, to be redone
+\def\page_streams_TEX_start[#1]% old code, to be redone
{\page
- \defineoutputstream[tex]%
- \enableoutputstream[tex]%
- \unexpanded\def\stopTEXstream
- {\disableoutputstream
- \startTEXpage
- \outputstreamunvbox[tex]%
- \stopTEXpage}}
+ \enableoutputstream[tex]}
+
+\unexpanded\def\stopTEXstream
+ {\disableoutputstream
+ \startTEXpage
+ \outputstreamunvbox[tex]%
+ \stopTEXpage}
%D Application pages, a quick \MKIV\ hack:
@@ -148,7 +169,7 @@
\def\TEXapplicationfilename{\jobname-texapplication.tex}
-\def\stopTEXapplication
+\unexpanded\def\stopTEXapplication
{\savebuffer[\thedefinedbuffer{TEXapplication}][\TEXapplicationfilename]%
\typesetfile[TEXapplication][\TEXapplicationfilename]\relax}
@@ -160,9 +181,9 @@
%D \stoptyping
\unexpanded\def\startpagefigure
- {\dodoubleempty\dostartpagefigure}
+ {\dodoubleempty\page_figures_start}
-\def\dostartpagefigure[#1][#2]%
+\def\page_figures_start[#1][#2]%
{\bgroup
\getparameters[\??ex][\c!offset=\v!overlay,#2]%
\startTEXpage[\c!offset=\@@exoffset]%
@@ -173,9 +194,9 @@
\egroup}
\def\pagefigure
- {\dodoubleempty\dopagefigure}
+ {\dodoubleempty\page_figure}
-\def\dopagefigure[#1][#2]%
- {\dostartpagefigure[#1][#2]\stoppagefigure}
+\def\page_figure[#1][#2]%
+ {\page_figures_start[#1][#2]\stoppagefigure}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-bck.mkii b/Master/texmf-dist/tex/context/base/page-bck.mkii
index 0b4ad779afa..4c636d29e34 100644
--- a/Master/texmf-dist/tex/context/base/page-bck.mkii
+++ b/Master/texmf-dist/tex/context/base/page-bck.mkii
@@ -5,7 +5,7 @@
%D subtitle=Backgrounds,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-bck.mkiv b/Master/texmf-dist/tex/context/base/page-bck.mkiv
index 81392f5af87..100c186ddce 100644
--- a/Master/texmf-dist/tex/context/base/page-bck.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-bck.mkiv
@@ -5,35 +5,22 @@
%D subtitle=Backgrounds,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 / Backgrounds}
+% todo: ma:r:c
+%
+% 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 ares do support foreground order change.
-% todo \fastlocalframed -> \localbackgroundframed
+\writestatus{loading}{ConTeXt Page Macros / Backgrounds}
\unprotect
-%D \macros
-%D {recalculatebackgrounds}
-%D
-%D We use a couple of switches so that we can minimize the
-%D amount of background calculations. The main switch is set
-%D by the recalculate directive.
-%D
-%D \starttyping
-%D \recalculatebackgrounds
-%D \stoptyping
-%D
-%D Other modules may not directly set the switches
-%D themselves.
-
-\newif\ifnewbackground
-\newif\ifsomebackground
-
%D For special purposes, users can question the \type
%D {*background} mode. This mode is only available when
%D typesetting the pagebody.
@@ -42,102 +29,103 @@
%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
- \ifsomebackground \ifnewbackground \setsystemmode\v!background \fi \fi
+ \ifconditional\c_page_backgrounds_some
+ \ifconditional\c_page_backgrounds_new
+ \setsystemmode\v!background
+ \fi
+ \fi
\to \everybeforepagebody
-%D \macros
-%D {addmainbackground, addtextbackground,
-%D addpagebackground, addprintbackground}
-%D
-%D Apart from the previously mentioned directive, the
-%D interface between this module and the other modules
-%D is made up by four macros that add background to parts of
-%D the layout.
-%D
-%D \starttyping
-%D \addmainbackground <box>
-%D \addtextbackground <box>
-%D \addpagebackground <box>
-%D \addprintbackground <box>
-%D \stoptyping
+%D We keep calculations and checks to a minimum and also
+%D try to minimize the amount of tracing due to expansion.
-%D To minimize calculations, we keep track of the state of the
-%D background of each area. A previous implementation did
-%D check each call to the background calculation macro, but
-%D using an intermediate usage flag instead of testing each
-%D time saves about 3\% on a run with a couple of backgrounds.
-%D (On the 824 pages maps bibliography runtime went down from
-%D 309 to 299 seconds.)
+\let\currentotrbackground\empty
-% \let\currentotrbackground\empty
-%
-% \def\@@docheckbackground#1#2%
-% {\ifcsname\currentotrbackground#1\endcsname
-% \edef\!!stringa{\csname\currentotrbackground#1\endcsname}\ifx\!!stringa#2\!!doneatrue\fi
-% \fi}
-%
-% \def\@@nocheckbackground#1#2%
-% {\ifcsname\currentotrbackground#1\endcsname
-% \edef\!!stringa{\csname\currentotrbackground#1\endcsname}\ifx\!!stringa#2\else\!!doneatrue\fi
-% \fi}
-%
-% \def\checkbackground#1%
-% {\edef\currentotrbackground{\??ma#1}%
-% \begingroup
-% \!!doneafalse
-% \if!!donea\else\@@nocheckbackground\c!background \empty
-% \if!!donea\else\@@docheckbackground\c!frame \v!on
-% \if!!donea\else\@@nocheckbackground\c!foregroundcolor\empty
-% \if!!donea\else\@@docheckbackground\c!leftframe \v!on
-% \if!!donea\else\@@docheckbackground\c!rightframe \v!on
-% \if!!donea\else\@@docheckbackground\c!topframe \v!on
-% \if!!donea\else\@@docheckbackground\c!bottomframe \v!on \fi\fi\fi\fi\fi\fi\fi
-% \if!!donea
-% \endgroup\setusage \currentotrbackground
-% \else
-% \endgroup\resetusage\currentotrbackground
-% \fi}
-%
-% \def\ifsomebackgroundfound#1%
-% {\ifusage{\??ma#1}}
-%
-% \def\doifsomebackgroundelse#1%
-% {\ifusage{\??ma#1}%
-% \expandafter\firstoftwoarguments
-% \else
-% \expandafter\secondoftwoarguments
-% \fi}
+\def\page_backgrounds_set_yes{\expandafter\let\csname\currentotrbackground\endcsname\relax }
+\def\page_backgrounds_set_nop{\expandafter\let\csname\currentotrbackground\endcsname\undefined}
-\let\currentotrbackground\empty
+\def\page_backgrounds_check_background
+ {\ifcsname\currentotrbackground\c!background\endcsname
+ \edef\page_background_temp{\csname\currentotrbackground\c!background\endcsname}%
+ \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\@@docheckbackground#1#2%
- {\ifcsname\currentotrbackground#1\endcsname
- \edef\!!stringa{\csname\currentotrbackground#1\endcsname}\ifx\!!stringa#2\!!doneatrue\fi
+\def\page_backgrounds_check_frame
+ {\ifcsname\currentotrbackground\c!frame\endcsname
+ \edef\page_background_temp{\csname\currentotrbackground\c!frame\endcsname}%
+ \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\@@nocheckbackground#1#2%
- {\ifcsname\currentotrbackground#1\endcsname
- \edef\!!stringa{\csname\currentotrbackground#1\endcsname}\ifx\!!stringa#2\else\!!doneatrue\fi
+\def\page_backgrounds_check_leftframe
+ {\ifcsname\currentotrbackground\c!leftframe\endcsname
+ \edef\page_background_temp{\csname\currentotrbackground\c!leftframe\endcsname}%
+ \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\checkbackground#1% here we need an \ifempty primitive
- {\edef\currentotrbackground{\??ma#1}%
- \begingroup
- \!!doneafalse
- \if!!donea\else\@@nocheckbackground\c!background \empty
- \if!!donea\else\@@docheckbackground\c!frame \v!on
- \if!!donea\else\@@nocheckbackground\c!foregroundcolor\empty
- \if!!donea\else\@@docheckbackground\c!leftframe \v!on
- \if!!donea\else\@@docheckbackground\c!rightframe \v!on
- \if!!donea\else\@@docheckbackground\c!topframe \v!on
- \if!!donea\else\@@docheckbackground\c!bottomframe \v!on \fi\fi\fi\fi\fi\fi\fi
- \if!!donea
- \endgroup\expandafter\let\csname\currentotrbackground\endcsname\relax
+\def\page_backgrounds_check_rightframe
+ {\ifcsname\currentotrbackground\c!rightframe\endcsname
+ \edef\page_background_temp{\csname\currentotrbackground\c!rightframe\endcsname}%
+ \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\currentotrbackground\c!topframe\endcsname
+ \edef\page_background_temp{\csname\currentotrbackground\c!topframe\endcsname}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \expandafter\expandafter\expandafter\page_backgrounds_check_bottomframe
+ \fi
\else
- \endgroup\expandafter\let\csname\currentotrbackground\endcsname\undefined
+ \expandafter\page_backgrounds_check_bottomframe
\fi}
+\def\page_backgrounds_check_bottomframe
+ {\ifcsname\currentotrbackground\c!bottomframe\endcsname
+ \edef\page_background_temp{\csname\currentotrbackground\c!bottomframe\endcsname}%
+ \ifx\page_background_temp\v!on
+ \page_backgrounds_set_yes
+ \else
+ \page_backgrounds_set_nop
+ \fi
+ \else
+ \page_backgrounds_set_nop
+ \fi}
+
+\def\page_backgrounds_check#1%
+ {\edef\currentotrbackground{\??ma#1}%
+ \page_backgrounds_check_background}
+
\def\ifsomebackgroundfound#1%
{\ifcsname\??ma#1\endcsname}
@@ -159,42 +147,40 @@
%D macro. This means that all normal frame and overlay
%D features can be used.
-% \def\addsomebackground#1#2#3#4% area box width height / zero test added
-% {\ifsomebackgroundfound#1\ifdim#3>\zeropoint\ifdim#4>\zeropoint
-% \ifcsname\??ma#1\c!setups\endcsname % to be done
-% \doprocesslocalsetups{\csname\??ma#1\c!setups\endcsname}% should not produce funny spaces !
-% \fi
-% \setbox#2\vbox\fastlocalframed % maybe \superfastlocalframed{tag}{w}{h}
-% [\??ma#1]%
-% [\c!component=#1,\c!width=#3,\c!height=#4]% are width and height used?
-% {\dp#2\zeropoint\box#2}%
-% \fi\fi\fi}
-
-\def\addsomebackground#1#2#3#4% area box width height / zero test added
- {\ifsomebackgroundfound#1\ifdim#3>\zeropoint\ifdim#4>\zeropoint
- \ifcsname\??ma#1\c!setups\endcsname % to be done
- \doprocesslocalsetups{\csname\??ma#1\c!setups\endcsname}% should not produce funny spaces !
- \fi
- \localbackgroundframed{#1}{#2}{#3}{#4}%
- \fi\fi\fi}
+\def\page_backgrounds_add_to_box#1% area
+ {\ifcsname\??ma#1\endcsname
+ \expandafter\page_backgrounds_add_to_box_indeed
+ \else
+ \expandafter\gobblefourarguments
+ \fi#1}
+
+% we don't need the dimensions here as this is a real framed but the question is: do we indeed
+% need a real framed or can we use a fake (i.e. no foreground, only for hidden)
+
+\def\page_backgrounds_add_to_box_indeed#1#2#3#4% area box width height / always non zero
+ {\ifcsname\??ma#1\c!setups\endcsname % to be done
+ \doprocesslocalsetups{\csname\??ma#1\c!setups\endcsname}% should not produce funny spaces !
+ \fi
+ % #2 has the right dimensions already
+ \setbox#2\hbox{\localbackgroundframed{\??ma#1}#1#2}}% a real framed (including foreground)
%D There are quite some backgrounds. At the bottom layer,
%D there is the {\em paper} background. This one is only
%D used for special purposes, like annotations to documents.
-\def\addprintbackground#1%
- {\addsomebackground\v!paper#1\printpaperwidth\printpaperheight}
+\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
%D page}, the {\em right page} or {\em each page}. As with
%D the paper background, these are calculated on each page.
-\def\addpagebackground#1%
+\def\page_backgrounds_add_to_paper#1%
{\doifbothsidesoverruled
- {\addsomebackground\v!rightpage#1\paperwidth\paperheight}
- {\addsomebackground\v!rightpage#1\paperwidth\paperheight}
- {\addsomebackground\v!leftpage #1\paperwidth\paperheight}%
- \addsomebackground\v!page #1\paperwidth\paperheight}
+ {\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
%D top, header, text, footer, bottom} times {\em left edge,
@@ -202,29 +188,20 @@
%D only recalculated when they change or when the \type
%D {status} is set to \type {repeat}.
-\newbox\leftbackground
-\newbox\rightbackground
-
-\def\addmainbackground#1% todo: dimension spec
- {\ifsomebackground
- \ifnewbackground \setbackgroundboxes \fi
- \setbox#1\vbox
- {\offinterlineskip
- \doifmarginswapelse{\copy\leftbackground}{\copy\rightbackground}%
- \box#1}%
- \fi}
+\newbox\leftbackground % todo: rename
+\newbox\rightbackground % todo: rename
%D Finaly there is an aditional {\em text} background, again
%D useful for special purposes only. This one is calculated
%D each time. The hidden backgrounds are not meant for users!
-\newconditional\hiddenbackgroundenabled
+\newconditional\c_page_backgrounds_hidden_enabled
-\def\addtextbackground#1%
- {\ifconditional\hiddenbackgroundenabled
- \addsomebackground\v!hidden#1\makeupwidth\textheight % mine !
+\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
- \addsomebackground\v!text#1\makeupwidth\textheight}
+ \page_backgrounds_add_to_box\v!text#1\makeupwidth\textheight}
%D The next couple of macros implement the area backgrounds.
%D As said, these are cached in dedicated boxes. The offsets
@@ -233,63 +210,61 @@
\newdimen\pageoffset % bleed
\newdimen\pagedepth
-% \def\setbackgroundboxes
-% {\showmessage\m!layouts8\empty
-% \setbackgroundbox\leftbackground\relax
-% \ifdoublesided
-% \setbackgroundbox\rightbackground\doswapmargins
-% \fi
-% \doifnot\@@mastatus\v!herhaal{\global\newbackgroundfalse}}
-
%D We need a bit more clever mechanism in order to handle
%D layers well. This means that we cannot calculate both
%D background at the same time since something may have
%D changed halfway a page.
-\newconditional\newrightbackground
-\newconditional\newleftbackground
+%D Margin swapping has been simplified: see mkii code in case of
+%D regression. Calculation is delayed till the page anyway so the
+%D state is known.
-\def\recalculatebackgrounds
- {\global\newbackgroundtrue}
+\def\page_backgrounds_recalculate
+ {\global\settrue\c_page_backgrounds_new}
-\def\setbackgroundboxes
- {\ifnewbackground
- \dosetbackgroundboxesr
+\def\page_backgrounds_set_boxes
+ {\ifconditional\c_page_backgrounds_new
+ \page_backgrounds_set_boxes_r
\fi
- \doifbothsides\dosetbackgroundboxesa\dosetbackgroundboxesb\dosetbackgroundboxesc
- \ifx\@@mastate\v!repeat\else\global\newbackgroundfalse\fi}
+ \doifbothsides
+ \page_backgrounds_set_boxes_a
+ \page_backgrounds_set_boxes_b
+ \page_backgrounds_set_boxes_c
+ \ifx\@@mastate\v!repeat\else
+ \global\setfalse\c_page_backgrounds_new
+ \fi}
-\def\dosetbackgroundboxesr
- {\global\settrue\newrightbackground
- \global\settrue\newleftbackground
+\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\dosetbackgroundboxesa
- {\ifconditional\newleftbackground
+\def\page_backgrounds_set_boxes_a
+ {\ifconditional\c_page_backgrounds_new_left
% \showmessage\m!layouts8\empty
- \setbackgroundbox\leftbackground\relax
- \global\setfalse\newleftbackground
- \global\setfalse\newrightbackground
+ \page_backgrounds_set_box\leftbackground % \conditionalfalse
+ \global\setfalse\c_page_backgrounds_new_left
+ \global\setfalse\c_page_backgrounds_new_right
\fi}
-\def\dosetbackgroundboxesb
- {\ifconditional\newleftbackground
+\def\page_backgrounds_set_boxes_b
+ {\ifconditional\c_page_backgrounds_new_left
% \showmessage\m!layouts8\empty
- \setbackgroundbox\leftbackground\relax
- \global\setfalse\newleftbackground
+ \page_backgrounds_set_box\leftbackground % \conditionalfalse
+ \global\setfalse\c_page_backgrounds_new_left
\fi}
-\def\dosetbackgroundboxesc
- {\ifconditional\newrightbackground
+\def\page_backgrounds_set_boxes_c
+ {\ifconditional\c_page_backgrounds_new_right
% \showmessage\m!layouts8\empty
- \setbackgroundbox\rightbackground\doswapmargins
- \global\setfalse\newrightbackground
+ \page_backgrounds_set_box\rightbackground % \conditionaltrue
+ \global\setfalse\c_page_backgrounds_new_right
\fi}
-\def\addmainbackground#1% todo: dimension spec
- {\ifsomebackground
- \setbackgroundboxes
+\def\page_backgrounds_add_to_main#1% todo: dimension spec
+ {\ifconditional\c_page_backgrounds_some
+ \page_backgrounds_set_boxes
\setbox#1\vbox
{\offinterlineskip
\doifmarginswapelse{\copy\leftbackground}{\copy\rightbackground}%
@@ -299,34 +274,61 @@
\newdimen\pagebackgroundhoffset % THESE WILL BECOME OBSOLETE
\newdimen\pagebackgroundvoffset
\newdimen\pagebackgrounddepth
-\newdimen\pagebackgroundoffset
-
-\def\setbackgroundoffsets % used in menus (we can use ifcsname's here)
- {\ifsomebackground \ifnewbackground
- \global\pagebackgroundhoffset\zeropoint
- \global\pagebackgroundvoffset\zeropoint
- \global\pagebackgrounddepth \zeropoint
- \doifsomebackgroundelse{\v!text\v!text}\donetrue\donefalse
- \ifdone\else\doifsomebackgroundelse\v!text\donetrue\donothing\fi
- \ifdone
- \begingroup
- \scratchdimen\csname\??ma\v!page\c!offset\endcsname
- \doifsomebackgroundelse{\v!top\v!text}\donothing
- {\doifsomebackgroundelse{\v!bottom\v!text}\donothing
- {\global\pagebackgroundhoffset\scratchdimen}}%
- \doifsomebackgroundelse{\v!text\v!rightedge}\donothing
- {\doifsomebackgroundelse{\v!text\v!leftedge}\donothing
- {\global\pagebackgroundvoffset\scratchdimen
- \global\pagebackgrounddepth\csname\??ma\v!page\c!depth\endcsname}}%
- \endgroup
- \fi
+\newdimen\pagebackgroundcompensation
+
+\newdimen\pagebackgroundoffset % used elsewhere
+
+\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}
-\appendtoks \setbackgroundoffsets \to \everybeforepagebody
+\def\page_backgrounds_set_offsets_indeed
+ {\ifcsname\??ma\v!text\v!text\endcsname
+ \page_backgrounds_set_offsets_yes
+ \else\ifcsname\??ma\v!text\endcsname
+ \page_backgrounds_set_offsets_yes
+ \else
+ \page_backgrounds_set_offsets_nop
+ \fi\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\pagebackgroundcompensation\csname\??ma\v!page\c!offset\endcsname\relax
+ \ifzeropt\pagebackgroundcompensation
+ \page_backgrounds_set_offsets_nop
+ \else
+ \ifcsname\??ma\v!top\v!text\endcsname
+ \global\pagebackgroundhoffset\zeropoint
+ \else\ifcsname\??ma\v!bottom\v!text\endcsname
+ \global\pagebackgroundhoffset\zeropoint
+ \else
+ \global\pagebackgroundhoffset\pagebackgroundcompensation
+ \fi\fi
+ \ifcsname\??ma\v!text\v!rightedge\endcsname
+ \global\pagebackgroundvoffset\zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \else\ifcsname\??ma\v!text\v!leftedge\endcsname
+ \global\pagebackgroundvoffset\zeropoint
+ \global\pagebackgrounddepth \zeropoint
+ \else
+ \global\pagebackgroundvoffset\pagebackgroundcompensation
+ \global\pagebackgrounddepth \csname\??ma\v!page\c!depth\endcsname\relax
+ \fi\fi
+ \fi}
+
+\appendtoks
+ \page_backgrounds_set_offsets
+\to \everybeforepagebody
\newconditional\swapbackgroundmargins \settrue\swapbackgroundmargins
-\def\setbackgroundbox#1#2%
+\def\page_backgrounds_set_box#1% #2%
{\global\setbox#1\vbox
{\dontcomplain
\swapmargins
@@ -337,60 +339,101 @@
\fi
\calculatereducedvsizes
\offinterlineskip
- #2\relax
- \vskip\dimexpr-\topheight-\topdistance\relax
- \dodopagebodybackground\v!top\topheight
- \vskip\topdistance
- \dodopagebodybackground\v!header\headerheight
- \vskip\headerdistance
- \dodopagebodybackground\v!text\textheight
- \vskip\footerdistance
- \dodopagebodybackground\v!footer\footerheight
- \vskip\bottomdistance
- \dodopagebodybackground\v!bottom\bottomheight
+ % \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\dodopagebodybackground#1#2% maybe helper
- {\ifdim#2>\zeropoint % added, faster
- \setbox\scratchbox\vbox to #2
- \bgroup\hbox\bgroup
- % \swapmargins
- \goleftonpage
- \dododopagebodybackground\leftedgewidth #2#1\v!leftedge
- \hskip\leftedgedistance
- \dododopagebodybackground\leftmarginwidth #2#1\v!leftmargin
- \hskip\leftmargindistance
- \dododopagebodybackground\makeupwidth #2#1\v!text
- \hskip\rightmargindistance
- \dododopagebodybackground\rightmarginwidth#2#1\v!rightmargin
- \hskip\rightedgedistance
- \dododopagebodybackground\rightedgewidth #2#1\v!rightedge
- \egroup\egroup
- \wd\scratchbox\zeropoint
- \box\scratchbox\relax
- \fi}
-
-\def\dododopagebodybackground#1#2#3#4% width height pos pos % maybe helper
- {\ifsomebackgroundfound{#3#4}%
- \ifdim#2>\zeropoint\relax
- \ifdim#1>\zeropoint\relax
- \ifcsname\??ma#3#4\c!setups\endcsname % to be done
- \doprocesslocalsetups{\csname\??ma#3#4\c!setups\endcsname}% should not produce funny spaces !
+ \smashbox#1}
+
+\def\page_backgrounds_set_box_row#1#2% maybe helper
+ {\setbox\scratchbox\vbox to #2
+ \bgroup\hbox\bgroup
+ \goleftonpage
+ \ifdim\leftedgewidth>\zeropoint
+ \ifcsname\??ma#1\v!leftedge\endcsname
+ \page_backgrounds_set_box_cell#1\v!leftedge\leftedgewidth#2%
+ \else
+ \kern\leftedgewidth
\fi
- \fastlocalframed
- [\??ma#3#4]%
- [\c!component=#3-#4]%
- {\vbox to #2{\vss\hbox to#1{\hss\csname\??ma#3#4\c!command\endcsname\hss}\vss}}%
+ \kern\leftedgedistance
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ \ifcsname\??ma#1\v!leftmargin\endcsname
+ \page_backgrounds_set_box_cell#1\v!leftmargin\leftmarginwidth#2%
+ \else
+ \kern\leftmarginwidth
+ \fi
+ \kern\leftmargindistance
+ \fi
+ \ifcsname\??ma#1\v!text\endcsname
+ \page_backgrounds_set_box_cell#1\v!text\makeupwidth#2%
\else
- \hskip#1%
+ \kern\makeupwidth
\fi
- \else
- \hskip#1%
- \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ \kern\rightmargindistance
+ \ifcsname\??ma#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\??ma#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
+ \ifcsname\??ma#1#2\c!setups\endcsname
+ \doprocesslocalsetups{\csname\??ma#1#2\c!setups\endcsname}% should not produce funny spaces !
+ \fi
+ \ifcsname\??ma#1#2\c!command\endcsname
+ \expandafter\page_backgrounds_set_box_cell_nop
\else
- \hskip#1%
- \fi}
+ \expandafter\page_backgrounds_set_box_cell_yes
+ \fi#1#2#3#4%
+ \localbackgroundframed{\??ma#1#2}{#1:#2}\scratchbox
+ \endgroup}
+
+\def\page_backgrounds_set_box_cell_nop#1#2#3#4%
+ {\setbox\scratchbox\emptyvbox
+ \wd\scratchbox#3%
+ \ht\scratchbox#4}
+
+\def\page_backgrounds_set_box_cell_yes#1#2#3#4%
+ {\setbox\scratchbox\vbox to #4{\vss\hbox to#3{\hss\csname\??ma#1#2\c!command\endcsname\hss}\vss}%
+ \dp\scratchbox\zeropoint}
%D The background mechanism is quite demanding in terms or
%D resources. We used to delay these definitions till runtime
@@ -408,30 +451,22 @@
%D Because the number of arguments runs from one to three,
%D we need to check for it.
+\newtoks\everybackgroundssetup
+
\unexpanded\def\setupbackgrounds
- {\dotripleempty\dosetupbackgrounds}
+ {\dotripleempty\page_backgrounds_setup}
-\def\dosetupbackgrounds[#1][#2][#3]%
+\def\page_backgrounds_setup[#1][#2][#3]%
{\ifthirdargument
- \global\somebackgroundtrue
- \def\docommand##1%
- {\doifinsetelse{##1}{\v!paper,\v!page,\v!leftpage,\v!rightpage}
- {\getparameters[\??ma##1][#3]\checkbackground{##1}}
- {\def\dodocommand####1{\getparameters[\??ma##1####1][#3]\checkbackground{##1####1}}%
- \processcommalist[#2]\dodocommand}}%
- \processcommalist[#1]\docommand
+ \page_backgrounds_setup_double{#1}{#2}{#3}%
\else\ifsecondargument
- \global\somebackgroundtrue
- \doifcommonelse{#1}{\v!text,\v!hidden,\v!paper,\v!page,\v!leftpage,\v!rightpage}
- {\def\docommand##1{\getparameters[\??ma##1][#2]\checkbackground{##1}}%
- \processcommalist[#1]\docommand}%
- {\setupbackgrounds
- [#1]%
- [\v!leftedge,\v!leftmargin,\v!text,\v!rightmargin,\v!rightedge]%
- [#2]}%
+ \page_backgrounds_setup_single{#1}{#2}%
\else\iffirstargument
- \getparameters[\??ma][#1]%
+ \page_backgrounds_setup_basics{#1}%
\fi\fi\fi
+ \the\everybackgroundssetup}
+
+\appendtoks
\doifelsevalue{\??ma\v!page\c!offset}\v!overlay
{\global\pageoffset\zeropoint}
{\global\pageoffset\csname\??ma\v!page\c!offset\endcsname}%
@@ -439,13 +474,44 @@
\global\pagebackgroundoffset\pageoffset
\global\pagebackgrounddepth\pagedepth
\doifelse\@@mastate\v!stop
- {\global\newbackgroundfalse}
- {\global\newbackgroundtrue }}
+ {\global\setfalse\c_page_backgrounds_new}
+ {\global\settrue \c_page_backgrounds_new}%
+\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}
+
+\def\page_backgrounds_setup_double#1#2#3%
+ {\global\settrue\c_page_backgrounds_some
+ \def\docommand##1%
+ {\doifinsetelse{##1}\v_page_backgrounds_double_set
+ {\page_backgrounds_setup_and_check{##1}{#3}}
+ {\def\dodocommand####1{\page_backgrounds_setup_and_check{##1####1}{#3}}%
+ \processcommalist[#2]\dodocommand}}%
+ \processcommalist[#1]\docommand}
+
+\def\page_backgrounds_setup_single#1#2%
+ {\global\settrue\c_page_backgrounds_some
+ \doifcommonelse{#1}\v_page_backgrounds_single_set
+ {\def\docommand##1{\page_backgrounds_setup_and_check{##1}{#2}}%
+ \processcommalist[#1]\docommand}%
+ {\page_backgrounds_setup_double{#1}\v_page_backgrounds_common_set{#2}}}
+
+\def\page_backgrounds_setup_basics#1%
+ {\getparameters[\??ma][#1]}
+
+\def\page_backgrounds_setup_and_check#1#2% tag settings
+ {\edef\currentotrbackground{\??ma#1}%
+ \getparameters[\currentotrbackground][#2]%
+ \page_backgrounds_check_background}
%D Each areas (currently there are $1+3+25+1=30$ of them)
%D has its own low level framed object associated.
-\def\installsomebackground#1#2{\inheritlocalframed[\??ma#1#2][\??od]}
+% hm, we can delay them
+
+\unexpanded\def\installsomebackground#1#2{\inheritlocalframed[\??ma#1#2][\??od]}
\installsomebackground \v!paper \empty
\installsomebackground \v!page \empty
@@ -502,49 +568,60 @@
% spread-2 .. spread+2 achter spread -> spread (repeat 2 times)
\def\enablehiddenbackground
- {\global\settrue\hiddenbackgroundenabled
- \global\somebackgroundtrue
- \recalculatebackgrounds}
+ {\global\settrue\c_page_backgrounds_hidden_enabled
+ \global\settrue\c_page_backgrounds_some
+ \page_backgrounds_recalculate}
\def\disablehiddenbackground
- {\global\setfalse\hiddenbackgroundenabled}
+ {\global\setfalse\c_page_backgrounds_hidden_enabled}
-\def\hiddenbackground
+\def\hiddenbackgroundlist
{\v!text-2,\v!text-1,\v!foreground,\v!text+1,\v!text+2}
+% \defineoverlay[\v!text-2][\positionoverlay{\v!text-2}]
+% \defineoverlay[\v!text-1][\positionoverlay{\v!text-1}]
+% \defineoverlay[\v!text+1][\positionoverlay{\v!text+1}]
+% \defineoverlay[\v!text+2][\positionoverlay{\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=\hiddenbackground]
+ [\c!background=\hiddenbackgroundlist]
% The next series is used in local (for instance floating)
% backgrounds.
-\installsomebackground \v!local \empty % not really a background, invisible for users
-
-\getparameters
- [\??ma\v!local]
- [\c!component=local,
- \c!background=\localbackground]
-
-\def\localbackground
- {\v!local-2,\v!local-1,\v!foreground,\v!local+1,\v!local+2}
-
-\defineoverlay[\v!local-2][\positionoverlay{\v!local-2}]
-\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\addlocalbackgroundtobox
- {\ifconditional\hiddenbackgroundenabled
- \expandafter\doaddlocalbackground
- \else
- \resetglobal \expandafter\gobbleoneargument
- \fi}
-
-\def\doaddlocalbackground#1%
- {\dodoglobal\setbox#1\hbox{\fastlocalframed[\??ma\v!local][]{\registerMPlocaltextarea{\box#1}}}%
- \resetglobal % redundant
- \doglobal\increment\localpositionnumber\relax} % afterwards !
+% \installsomebackground \v!local \empty % not really a background, invisible for users
+%
+% \getparameters
+% [\??ma\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{\??ma\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:
%
@@ -559,6 +636,6 @@
%D Because we haven't really set up backgrounds yet, we set
%D the main efficiency switch to false.
-\somebackgroundfalse
+\setfalse\c_page_backgrounds_some
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-box.mkvi b/Master/texmf-dist/tex/context/base/page-box.mkvi
new file mode 100644
index 00000000000..42db40e5f62
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-box.mkvi
@@ -0,0 +1,309 @@
+%D \module
+%D [ file=page-box,
+%D version=2011.12.05, % moved from other page-* files
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Page Boxing,
+%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 / Boxing}
+
+\unprotect
+
+%D The often two step approach (_indeed) saves skippign tokens
+%D which is nicer for tracing.
+
+%D Centering the paper area on the print area is determined
+%D by the \type {top}, \type {bottom}, \type {left} and \type
+%D {right} parameters.
+
+\def\page_boxes_apply_center#box% we could test for a difference (saves packing)
+ {\printpaperwidth \v_page_target_scale\printpaperwidth \relax
+ \printpaperheight\v_page_target_scale\printpaperheight\relax
+ \ifdim\printpaperheight>\ht#box\relax
+ \page_boxes_apply_center_indeed#box%
+ \else\ifdim\printpaperwidth>\wd#box\relax
+ \page_boxes_apply_center_indeed#box%
+ \fi\fi}
+
+\def\page_boxes_apply_center_indeed_l_r#box%
+ {\v_page_target_left
+ \v_page_target_left_fill
+ \box#box%
+ \v_page_target_right_fill
+ \v_page_target_right}
+
+\def\page_boxes_apply_center_indeed_r_l#box%
+ {\v_page_target_right
+ \v_page_target_right_fill
+ \box#box%
+ \v_page_target_left_fill
+ \v_page_target_left}
+
+\def\page_boxes_apply_center_indeed#box% we could test for a difference (saves packing)
+ {\setbox#box\vbox to \printpaperheight
+ {\v_page_target_top
+ \v_page_target_top_fill
+ \hbox to \printpaperwidth
+ {\ifconditional\c_page_target_print_doublesided
+ \doifbothsides
+ {\page_boxes_apply_center_indeed_l_r#box}%
+ {\page_boxes_apply_center_indeed_l_r#box}%
+ {\page_boxes_apply_center_indeed_r_l#box}%
+ \else
+ \page_boxes_apply_center_indeed_l_r#box%
+ \fi}%
+ \par
+ \v_page_target_bottom_fill
+ \v_page_target_bottom}}
+
+\def\page_boxes_apply_offset % #box
+ {\ifdim\topoffset=\zeropoint
+ \ifdim\backoffset=\zeropoint
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \doubleexpandafter\page_boxes_apply_offset_indeed
+ \fi
+ \else
+ \expandafter\page_boxes_apply_offset_indeed
+ \fi}
+
+\def\page_boxes_apply_offset_indeed#box%
+ {\scratchwidth \wd#box%
+ \scratchheight\ht#box%
+ \scratchdepth \dp#box%
+ \setbox#box\vbox
+ {\offinterlineskip
+ \vskip\topoffset
+ \hskip\doifbothsides\backoffset\backoffset{-\backoffset}%
+ \box#box}%
+ \wd#box\scratchwidth
+ \ht#box\scratchheight
+ \dp#box\scratchdepth}
+
+\def\page_boxes_apply_replicate
+ {\ifnum\layoutparameter\c!nx>\plusone
+ \expandafter\page_boxes_apply_replicate_indeed
+ \else\ifnum\layoutparameter\c!ny>\plusone
+ \doubleexpandafter\page_boxes_apply_replicate_indeed
+ \else
+ \doubleexpandafter\gobbleoneargument
+ \fi\fi}
+
+\def\page_boxes_apply_replicate_indeed#box%
+ {\setbox#box\vbox
+ {\offinterlineskip
+ \dorecurse{\layoutparameter\c!ny}
+ {\hbox{\dorecurse{\layoutparameter\c!nx}{\copy#box\hskip\layoutparameter\c!dx}\unskip}%
+ \vskip\layoutparameter\c!dy}
+ \unskip}}
+
+\def\page_boxes_apply_orientate_paper#box%
+ {\ifnum\number\c_page_target_paper_orientation\number\c_page_target_paper_reverse>\zerocount
+ \page_boxes_apply_orientate_indeed\c_page_target_paper_orientation\c_page_target_paper_reverse{#box}%
+ \fi}
+
+\def\page_boxes_apply_orientate_print#box%
+ {\ifnum\number\c_page_target_print_orientation\number\c_page_target_print_reverse>\zerocount
+ \page_boxes_apply_orientate_indeed\c_page_target_print_orientation\c_page_target_print_reverse{#box}%
+ \fi}
+
+\def\page_boxes_apply_orientate_indeed#odd#even#box%
+ {\setbox#box\vbox
+ {\edef\somerotation{\number\ifdoublesided\ifodd\realpageno#odd\else#even\fi\else#odd\fi}%
+ \dorotatebox\somerotation\hbox{\box#box}}}
+
+\def\page_boxes_apply_mirror#box%
+ {\setbox#box\vbox{\mirror{\box#box}}}
+
+\def\page_boxes_apply_mirror_paper#box{\ifconditional\c_page_target_paper_mirror\page_boxes_apply_mirror{#box}\fi}
+\def\page_boxes_apply_mirror_print#box{\ifconditional\c_page_target_print_mirror\page_boxes_apply_mirror{#box}\fi}
+
+\let\page_boxes_apply_negate\negatecolorbox
+
+\def\page_boxes_apply_negate_print#box%
+ {\ifconditional\c_page_target_print_negate
+ \page_boxes_apply_negate#box%
+ \else\ifconditional\c_page_target_paper_negate
+ \page_boxes_apply_negate#box%
+ \fi\fi}
+
+\def\page_boxes_apply_scale#box%
+ {\edef\p_page_layouts_scale{\layoutparameter\c!scale}%
+ \ifdim\p_page_layouts_scale\points=\onepoint
+ \edef\p_page_layouts_sx{\layoutparameter\c!sx}%
+ \edef\p_page_layouts_sy{\layoutparameter\c!sy}%
+ \ifdim\p_page_layouts_sx\points=\onepoint
+ \ifdim\layoutparameter\c!sy\points=\onepoint
+ % no scaling done (and no copying either)
+ \else
+ \page_boxes_apply_scale_indeed\p_page_layouts_sx\p_page_layouts_sy{#box}%
+ \fi
+ \else
+ \page_boxes_apply_scale_indeed\p_page_layouts_sx\p_page_layouts_sy{#box}%
+ \fi
+ \else
+ \page_boxes_apply_scale_indeed\p_page_layouts_scale\p_page_layouts_scale{#box}%
+ \fi}
+
+\def\page_boxes_apply_scale_indeed#sx#sy#box%
+ {\setbox#box\vbox{\scale[\c!sx=#sx,\c!sy=#sy]{\box#box}}% can be a fast one
+ \paperwidth #sx\paperwidth
+ \paperheight#sy\paperheight}
+
+% \setuppagenumbering[alternative=doublesided]
+% \setupcolors[state=start]
+% \setuppapersize[A4][A4,oversized]
+% \setuplayout[location=middle,clipoffset=5mm]
+% \setupbackgrounds
+% [page]
+% [frame=on,rulethickness=1mm,
+% backgroundoffset=10mm,background=color,backgroundcolor=red]
+% \starttext \dorecurse{10}{\input tufte \par} \stoptext
+
+\newconditional\c_page_boxes_clip_print \settrue\c_page_boxes_clip_print
+
+\def\page_boxes_apply_clip_print_left % box
+ {\ifconditional\c_page_boxes_clip_print
+ \expandafter\page_boxes_apply_clip_print_indeed\expandafter\conditionalfalse
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\page_boxes_apply_clip_print_right % box
+ {\ifconditional\c_page_boxes_clip_print
+ \expandafter\page_boxes_apply_clip_print_indeed\expandafter\conditionaltrue
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\page_boxes_apply_clip_print_indeed#right#box% can be made more efficient, see other clipper
+ {\scratchoffset\pagebackgroundoffset % can be zero which is valid % maybe another variable
+ \scratchwidth \wd#box%
+ \scratchheight\ht#box%
+ \scratchdepth \dp#box%
+ \setbox#box\hbox
+ {\advance\scratchheight\dimexpr\scratchdepth+2\scratchoffset\relax
+ \advance\scratchwidth \scratchoffset
+ \ifconditional#right\relax
+ \scratchdimen-\scratchoffset
+ \hskip\scratchdimen
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \lower\scratchoffset\hbox
+ {\clip
+ [\c!hoffset=\scratchdimen,
+ \c!voffset=-\scratchoffset,
+ \c!width=\scratchwidth,
+ \c!height=\scratchheight]%
+ {\box#box}}}%
+ \wd#box\scratchwidth
+ \ht#box\scratchheight
+ \dp#box\scratchdepth}
+
+\def\page_boxes_apply_clip_paper
+ {\scratchoffset\layoutparameter\c!clipoffset\relax
+ \ifdim\scratchoffset>\zeropoint
+ \expandafter\page_boxes_apply_clip_paper_indeed
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
+\def\page_boxes_apply_clip_paper_indeed#box%
+ {\scratchwidth \wd#box%
+ \scratchheight\ht#box%
+ \scratchdepth \dp#box%
+ \setbox#box\hbox
+ {\advance\scratchheight\dimexpr\scratchdepth+2\scratchoffset\relax
+ \advance\scratchwidth \scratchoffset
+ \doifbothsides
+ {\advance\scratchwidth\scratchoffset
+ \scratchdimen-\scratchoffset
+ \hskip\scratchdimen}%
+ {\scratchdimen\zeropoint}
+ {\scratchdimen-\scratchoffset
+ \hskip\scratchdimen}%
+ \lower\scratchoffset\hbox
+ {\clip
+ [\c!hoffset=\scratchdimen,
+ \c!voffset=-\scratchoffset,
+ \c!width=\scratchwidth,
+ \c!height=\scratchheight]%
+ {\box#box}}}%
+ \wd#box\scratchwidth
+ \ht#box\scratchheight
+ \dp#box\scratchdepth}
+
+% nearly always some displacement so no speedup test needed
+
+\def\page_boxes_apply_offsets#1%
+ {\setbox#1\vbox to \paperheight
+ {\hsize\paperwidth
+ \vskip\topspace
+ \doifbothsides
+ {\hskip\backspace}
+ {\hskip\backspace}
+ {\hskip\dimexpr\paperwidth-\backspace-\makeupwidth\relax}%
+ \box#1}%
+ \dp#1\zeropoint}
+
+% \let\page_boxes_apply_clip_paper \gobbleoneargument
+% \let\page_boxes_apply_clip_print_left \gobbleoneargument
+% \let\page_boxes_apply_clip_print_right\gobbleoneargument
+
+%D This is rather specialized:
+
+\newconditional\c_page_areas_enabled
+\newbox \b_page_areas_registered
+
+\def\enabletextarearegistration
+ {\global\settrue\c_page_areas_enabled}
+
+\def\page_areas_registered_box
+ {\ifconditional\c_page_areas_enabled
+ \expandafter\page_areas_registered_box_indeed
+ \else
+ \expandafter\page_areas_registered_box_forget
+ \fi}
+
+\def\page_areas_registered_box_forget#1#2#3% #1=lower-dp #2=correct-ht #3=box
+ {\box#3}
+
+\def\page_areas_registered_box_indeed#1#2#3% #1=lower-dp #2=correct-ht #3=box
+ {\anch_mark_flow_box{#3}}
+
+\def\page_areas_register_boxed#1%
+ {\begingroup
+ \setbox\scratchbox\vbox{#1}%
+ \wd\scratchbox\makeupwidth % somehow a space creeps in
+ \vbox{\page_areas_registered_box00\scratchbox}% 0 0 will go
+ \endgroup}
+
+% \def\page_areas_register_direct#1%
+% {\xypos{pbd:\realfolio:b}% we could save bytes by only saving the y
+% \endgraf
+% \begingroup
+% \scratchdimen\dimexpr\MPy{pbd:\realfolio:b}-\MPy{pbd:\realfolio:e}\relax
+% \setbox\scratchbox\emptyhbox
+% \wd\scratchbox\makeupwidth
+% \ht\scratchbox\scratchdimen
+% \vsmash{\page_areas_registered_box00\scratchbox}%
+% \endgroup
+% #1%
+% \endgraf
+% \xypos{pbd:\realfolio:e}}
+
+\def\page_areas_register_direct#1#2%
+ {\scratchdepth\dp#2%
+ \dp#2\strutdepth
+ \anch_mark_flow_only{#2}%
+ \dp#2\scratchdepth
+ #1#2}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-brk.mkiv b/Master/texmf-dist/tex/context/base/page-brk.mkiv
new file mode 100644
index 00000000000..72255676097
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-brk.mkiv
@@ -0,0 +1,410 @@
+%D \module
+%D [ file=page-brk, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Breaks,
+%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 / Breaks}
+
+\unprotect
+
+\ifdefined\resetcurrentstructuremarkswithpage \else \let\resetcurrentstructuremarkswithpage\relax \fi
+\ifdefined\noheaderandfooterlines \else \let\noheaderandfooterlines \relax \fi
+
+%D Page breaks.
+
+% \definepagebreak
+% [chapter]
+% [yes,header,right]
+%
+% \setuphead
+% [chapter]
+% [page=chapter,
+% header=empty,
+% footer=chapter]
+%
+% \definepagebreak % untested
+% [lastpage]
+% [left,{empty,right},{empty,left}]
+
+% public page handler, beware: definepage already in use (core-ref)
+%
+% \definepagebreak[instance][forsure]
+% \definepagebreak[forsure][yes,+4]
+
+\newconditional\c_page_breaks_enabled \settrue\c_page_breaks_enabled
+\newcount \c_page_breaks_prevpage
+
+\newtoks\everybeforepagebreak
+\newtoks\everyafterpagebreak
+
+\let\page_breaks_current_option \empty
+\let\page_breaks_current_options\empty
+
+\installcorenamespace{pagebreakmethod}
+\installcorenamespace{pagebreaks}
+
+\def\page_breaks_handle#1%
+ {\edef\page_breaks_current_options{#1}% handy for tracing
+ \processcommacommand[\page_breaks_current_options]\page_breaks_handle_indeed}
+
+\def\page_breaks_handle_indeed#1%
+ {\edef\page_breaks_current_option{#1}% can be used in handler
+ \ifcsname\??pagebreakmethod\page_breaks_current_option\endcsname
+ \csname\??pagebreakmethod\page_breaks_current_option\endcsname
+ \else\ifcsname\??pagebreaks\page_breaks_current_option\endcsname
+ \expandafter\page_breaks_handle\csname\??pagebreaks\page_breaks_current_option\endcsname
+ \else
+ \csname\??pagebreakmethod\s!unknown\endcsname
+ \fi\fi}
+
+\def\page_breaks_handle_direct#1%
+ {\csname\??pagebreakmethod#1\endcsname}
+
+\unexpanded\def\installpagebreakmethod#1#2% low level definer
+ {\setvalue{\??pagebreakmethod#1}{#2}}
+
+\let\installpagebreakhandler\installpagebreakmethod % will go
+
+\unexpanded\def\definepagebreak
+ {\dodoubleargument\page_breaks_define}
+
+\def\page_breaks_define[#1][#2]%
+ {\setvalue{\??pagebreaks#1}{#2}}
+
+\unexpanded\def\pagebreak
+ {\dosingleempty\page_breaks_process}
+
+\let\page\pagebreak
+
+\appendtoks
+ \flushnotes
+\to \everybeforepagebreak
+
+\def\page_breaks_process[#1]% so, page ornaments are reset after a pagebreak command, unless set
+ {\par % always before group so that we clear hangs etc (as in side floats)
+ \ifvmode % extra check
+ \begingroup
+ \the\everybeforepagebreak
+ \c_page_breaks_prevpage\realpageno
+ \ifcase\pageornamentstate \or
+ % disable reset after shipout
+ \global\pageornamentstate\plustwo
+ \fi
+ \iffirstargument % or if empty i.e. []
+ \page_breaks_handle{#1}%
+ \else % so, no pagebreak when \pagebreak[] ! ! !
+ \page_breaks_handle_direct\v!yes
+ \fi
+ \relax
+ \ifnum\c_page_breaks_prevpage<\realpageno
+ \global\pageornamentstate\zerocount
+ \fi
+ \the\everyafterpagebreak
+ \endgroup
+ \fi}
+
+\def\resetpagebreak % used elsewhere too
+ {\global\settrue\c_page_breaks_enabled}
+
+\def\simplifypagebreak % to be used grouped !
+ {\def\page_breaks_process[##1]{\goodbreak}}
+
+\def\disablepagebreaks % to be used grouped !
+ {\def\page_breaks_process[##1]{}}
+
+\installpagebreakmethod \s!dummy
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \page_otr_insert_dummy_page}
+
+\installpagebreakmethod \v!frame
+ {\page
+ \begingroup
+ \showframe
+ \page[\v!empty]
+ \endgroup}
+
+\installpagebreakmethod \s!unknown
+ {\doifinstringelse{+}\page_breaks_current_option
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \dorecurse\page_breaks_current_option\page_otr_insert_dummy_page}
+ {\doifnumberelse\page_breaks_current_option
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \doloop
+ {\ifnum\userpageno<\page_breaks_current_option\relax
+ \page_otr_insert_dummy_page
+ \else
+ \exitloop
+ \fi}}
+ {}}}
+
+\installpagebreakmethod \s!default
+ {} % do nothing if empty
+
+\installpagebreakmethod \v!reset
+ {% better not: \global\pageornamentstate\zerocount
+ \resetpagebreak}
+
+\installpagebreakmethod \v!disable
+ {\global\setfalse\c_page_breaks_enabled}
+
+\installpagebreakmethod \v!yes
+ {\ifconditional\c_page_breaks_enabled
+ \page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \ifinsidecolumns % this will move to MUL
+ \page_otr_eject_page % otherwise sometimes no change
+ \fi
+ \fi}
+
+\installpagebreakmethod \v!makeup
+ {\ifconditional\c_page_breaks_enabled
+ \page_otr_fill_and_eject_page
+ \fi}
+
+\installpagebreakmethod \v!blank
+ {\ifcase\pageornamentstate
+ \global\pageornamentstate\plusone
+ \fi}
+
+\installpagebreakmethod \v!no
+ {\ifconditional\c_page_breaks_enabled
+ \dosomebreak\nobreak
+ \fi}
+
+\installpagebreakmethod \v!preference
+ {\ifconditional\c_page_breaks_enabled
+ \ifinsidecolumns % this will move to MUL
+ \dosomebreak\goodbreak
+ \else
+ \testpage[3][\zeropoint]%
+ \fi
+ \fi}
+
+\installpagebreakmethod \v!bigpreference
+ {\ifconditional\c_page_breaks_enabled
+ \ifinsidecolumns % this will move to MUL
+ \dosomebreak\goodbreak
+ \else
+ \testpage[5][\zeropoint]%
+ \fi
+ \fi}
+
+% \installpagebreakmethod \v!empty {} % defined in page-txt.mkiv
+% \installpagebreakmethod \v!header{} % defined in page-txt.mkiv
+% \installpagebreakmethod \v!footer{} % defined in page-txt.mkiv
+
+\def\page_reset_marks_and_insert_dummy
+ {\resetcurrentstructuremarkswithpage\page_otr_insert_dummy_page}
+
+\installpagebreakmethod \v!left
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page_and_inserts
+ \doifbothsidesoverruled\donothing\page_reset_marks_and_insert_dummy\donothing}
+
+\installpagebreakmethod \v!right
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page_and_inserts
+ \doifbothsidesoverruled\donothing\donothing\page_reset_marks_and_insert_dummy}
+
+\installpagebreakmethod \v!even
+ {\page
+ \doifoddpageelse\page_reset_marks_and_insert_dummy\donothing}
+
+\installpagebreakmethod \v!odd
+ {\page
+ \doifoddpageelse\donothing\page_reset_marks_and_insert_dummy}
+
+\installpagebreakmethod \v!quadruple % not yet ok inside columnsets
+ {\ifdoublesided
+ \ifnum\numexpr\realpageno/4\relax=\numexpr\realpageno/2\relax\else
+ \page_breaks_handle_direct\v!yes
+ \page_breaks_handle_direct\v!empty
+ \page_breaks_handle_direct\v!empty
+ \fi
+ \fi}
+
+\installpagebreakmethod \v!last
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page_and_inserts
+ \relax
+ \doifbothsidesoverruled
+ \page_facings_flush % hm
+ \donothing
+ {\noheaderandfooterlines
+ \page_otr_insert_dummy_page}%
+ \filluparrangedpages}
+
+\installpagebreakmethod \v!lastpage % handy for backpage preceded by empty pages
+ {\page_breaks_handle_direct\v!yes
+ \ifdoublesided
+ \page_breaks_handle_direct\v!left
+ \page_breaks_handle_direct\v!empty
+ \page_breaks_handle_direct\v!empty
+ \fi}
+
+\installpagebreakmethod \v!start {\global\settrue \c_otr_shipout_enabled}
+\installpagebreakmethod \v!stop {\global\setfalse\c_otr_shipout_enabled}
+
+% Column breaks.
+
+\installcorenamespace{columnbreakmethod}
+\installcorenamespace{columnbreaks}
+
+\newtoks\everybeforecolumnbreak
+\newtoks\everyaftercolumnbreak
+
+\let\page_breaks_columns_current_option \empty
+\let\page_breaks_columns_current_options\empty
+
+\def\page_breaks_columns_handle#1%
+ {\edef\page_breaks_columns_current_options{#1}%
+ \processcommacommand[#1]\page_breaks_columns_handle_indeed}
+
+\def\page_breaks_columns_handle_indeed#1%
+ {\edef\page_breaks_columns_current_option{#1}%
+ \ifcsname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
+ \csname\??columnbreakmethod\currentoutputroutine:\page_breaks_columns_current_option\endcsname
+ \else\ifcsname\??columnbreaks\page_breaks_columns_current_option\endcsname
+ \expandafter\csname\page_breaks_columns_handle\??columnbreaks\page_breaks_columns_current_option\endcsname
+ \else
+ \csname\??columnbreakmethod\currentoutputroutine:\s!unknown\endcsname
+ \fi\fi}
+
+\def\page_breaks_columns_handle_direct#1%
+ {\csname\??columnbreakmethod\currentoutputroutine:#1\endcsname}
+
+\unexpanded\def\installcolumnbreakmethod#1#2#3% #1=otr-id #2=tag #3=action
+ {\setvalue{\??columnbreakmethod#1:#2}{#3}}
+
+\let\installcolumnbreakhandler\installcolumnbreakmethod % will go
+
+\unexpanded\def\definecolumnbreak
+ {\dodoubleargument\page_break_columns_define}
+
+\def\page_break_columns_define[#1][#2]%
+ {\setvalue{\??columnbreaks#1}{#2}}
+
+\unexpanded\def\columnbreak
+ {\dosingleempty\page_breaks_columns_process}
+
+\let\column\columnbreak
+
+\def\page_breaks_columns_process[#1]% so, page ornaments are reset after a pagebreak command, unless set
+ {\begingroup
+ \the\everybeforecolumnbreak
+ \iffirstargument
+ \page_breaks_columns_handle{#1}%
+ \else
+ \page_breaks_columns_handle_direct\v!yes
+ \fi
+ \relax
+ \the\everyaftercolumnbreak
+ \endgroup}
+
+%D Test page breaks.
+
+\newdimen \d_page_tests_test
+\newconstant\c_page_tests_mode
+
+\newconstant\testpagemethod % todo: \testnewpage[method=,lines=,voffset=]
+\newconstant\testpagetrigger
+
+\unexpanded\def\testpage {\c_page_tests_mode\plusone \dodoubleempty\page_tests_test} %
+\unexpanded\def\testpageonly{\c_page_tests_mode\plustwo \dodoubleempty\page_tests_test} % no penalties added to the mvl
+\unexpanded\def\testpagesync{\c_page_tests_mode\plusthree\dodoubleempty\page_tests_test} % force sync
+
+\def\page_tests_test[#1][#2]% don't change, only add more methods
+ {\relax % needed before \if
+ \ifconditional\c_page_breaks_enabled
+ % new from here
+ \ifcase\testpagetrigger
+ \endgraf
+ \or\ifvmode
+ \dosomebreak\allowbreak
+ \else % indeed?
+ \vadjust{\allowbreak}%
+ \endgraf
+ \fi\fi
+ % till here
+ \ifdim\pagegoal<\maxdimen \relax
+ \ifdim\pagetotal<\pagegoal \relax
+ \d_page_tests_test\dimexpr
+ #1\lineheight
+ +\pagetotal
+ \ifdim\lastskip<\parskip+\parskip\fi
+ \ifsecondargument+#2\fi
+ \relax
+ \ifcase\testpagemethod
+ \ifdim\d_page_tests_test>.99\pagegoal
+ \penalty-\plustenthousand
+ \fi
+ \or
+ \ifdim\dimexpr\d_page_tests_test-\pagegoal\relax>-\lineheight
+ \penalty-\plustenthousand
+ \fi
+ \or
+ \getnoflines\pagegoal
+ \ifdim\dimexpr\d_page_tests_test-\noflines\lineheight\relax>-\lineheight
+ \penalty-\plustenthousand
+ \fi
+ \or % same as 0 but more accurate
+ \ifdim\dimexpr\d_page_tests_test-10\scaledpoint\relax>\pagegoal
+ \penalty-\plustenthousand
+ \fi
+ \fi
+ \else\ifnum\c_page_tests_mode=\plusthree
+ \page_tests_flush_so_far
+ \fi\fi
+ \else\ifnum\c_page_tests_mode=\plusone
+ \goodbreak
+ \fi\fi
+ \else
+ \endgraf
+ \fi}
+
+\def\page_tests_flush_so_far
+ {\endgraf
+ \ifdim\pagetotal>\pagegoal
+ \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal
+ \goodbreak
+ \else
+ \page
+ \fi
+ \fi}
+
+%D Test column breaks.
+
+\def\testcolumn
+ {\dodoubleempty\page_tests_columns_test}
+
+\def\page_tests_columns_test[#1][#2]%
+ {\endgraf
+ \ifdim\pagegoal<\maxdimen
+ \ifdim\pagetotal<\pagegoal
+ \d_page_tests_test\dimexpr
+ \pagegoal
+ -\pagetotal
+ \ifdim\lastskip<\parskip+\parskip\fi
+ \ifsecondargument+#2\fi
+ \relax
+ \getrawnoflines\d_page_tests_test % (raw)
+ \ifnum#1>\noflines
+ \column
+ \fi
+ \else
+ \penalty-\plustenthousand % (untested)
+ \fi
+ \fi}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-col.mkiv b/Master/texmf-dist/tex/context/base/page-col.mkiv
new file mode 100644
index 00000000000..50a05d3510c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-col.mkiv
@@ -0,0 +1,156 @@
+%D \module
+%D [ file=page-col, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Column 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.
+
+\writestatus{loading}{ConTeXt Page Macros / Column Helpers}
+
+%D Here we implement a coouple of helpers for dealing with
+%D columns. For the moment we keep the names.
+
+\unprotect
+
+%D The next two registers can be used to store pre column
+%D material as well as footnotes or so.
+
+\newbox\precolumnbox \newdimen\precolumnboxheight
+\newbox\postcolumnbox \newdimen\postcolumnboxheight
+
+%D We reserve a counter for the number of columns as well as
+%D the current column. Both are not to be changed by users!
+
+\newcount\nofcolumns \nofcolumns = 1
+\newcount\mofcolumns \mofcolumns = 1
+
+\setnewconstant\maxnofcolumns 50
+\setnewconstant\allocatednofcolumns 0
+
+%D The next dimensions reports the final column height
+
+\newdimen\finalcolumnheights
+\newcount\finalcolumnlines
+
+%D This register can be used as a temporary storage for page
+%D content.
+
+\newbox\restofpage
+
+%D A few more (some might go away):
+
+\newif\ifintermediatefootnotes
+\newif\ifcarryoverfootnotes %\carryoverfootnotestrue
+\newif\iflastcolumnfootnotes %\lastcolumnfootnotestrue
+\newif\ifbalancecolumns %\balancecolumnstrue
+\newif\ifbalancetoheight %\balancetoheighttrue
+\newif\ifforcecolumngrid \forcecolumngridtrue
+\newif\ifstretchcolumns \stretchcolumnsfalse
+\newif\ifinheritcolumns \inheritcolumnsfalse
+\newif\ifheightencolumns \heightencolumnsfalse
+
+\newif\ifbalancingcolumns
+\newif\ifcollectingcontent
+\newif\ifcolumnoverflow
+
+\newdimen\intercolumnwidth
+\newdimen\localcolumnwidth
+\newdimen\savedpagetotal
+
+\newconstant\columndirection % 0:lr 1:rl
+
+\def\minbalancetoplines {1}
+\def\minfreecolumnlines {2}
+
+\newif\ifrecentercolumnbox \recentercolumnboxtrue
+\newif\ifrerecentercolumnbox \rerecentercolumnboxtrue
+\newif\ifpackcolumnfloats \packcolumnfloatstrue
+
+%D During initialization the temporary boxes are allocated.
+%D This enables us to use as much columns as we want, without
+%D exhausting the pool of boxes too fast. We could have packed
+%D them in one box, but we've got enough boxes.
+%D
+%D Two sets of boxes are declared, the txtboxes are used for
+%D the text, the topboxes are for moved column floats.
+
+\def\initializecolumns#1%
+ {\ifnum#1>\maxnofcolumns
+ \showmessage\m!columns1\maxnofcolumns
+ \nofcolumns\maxnofcolumns
+ \else
+ \nofcolumns#1\relax
+ \fi
+ \ifnum\nofcolumns>\allocatednofcolumns
+ \dorecurse\nofcolumns
+ {\ifnum\recurselevel>\allocatednofcolumns\relax
+ % \newbox\next \letgvalue{\??zc-\recurselevel-t}=\next
+ \expandafter\newbox\csname\??zc-\recurselevel-t\endcsname % text
+ \expandafter\newbox\csname\??zc-\recurselevel-f\endcsname % foot
+ \expandafter\newbox\csname\??zc-\recurselevel-h\endcsname % top insert
+ \expandafter\newbox\csname\??zc-\recurselevel-l\endcsname % top insert
+ \fi}%
+ \global\allocatednofcolumns\nofcolumns
+ \fi}
+
+\def\firstcolumnbox {\columntextbox\plusone}
+\def\currentcolumnbox {\columntextbox\mofcolumns}
+\def\lastcolumnbox {\columntextbox\nofcolumns}
+
+\def\firsttopcolumnbox {\columntopbox \plusone}
+\def\currenttopcolumnbox {\columntopbox \mofcolumns}
+\def\lasttopcolumnbox {\columntopbox \nofcolumns}
+
+\def\columntextbox #1{\csname\??zc-\number#1-t\endcsname}
+\def\columnfootbox #1{\csname\??zc-\number#1-f\endcsname}
+\def\columntopbox #1{\csname\??zc-\number#1-h\endcsname}
+\def\columnbotbox #1{\csname\??zc-\number#1-l\endcsname}
+
+\def\columnsettextbox {\global\setbox\columntextbox}
+\def\columnsetfootbox {\global\setbox\columnfootbox}
+\def\columnsettopbox {\global\setbox\columntopbox}
+\def\columnsetbotbox {\global\setbox\columnbotbox}
+
+\def\columngettextbox {\copy\columntextbox}
+\def\columngetfootbox {\copy\columnfootbox}
+\def\columngettopbox {\copy\columntopbox}
+\def\columngetbotbox {\copy\columnbotbox}
+
+\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}}
+\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}}
+\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}}
+\def\columnerasebotboxes {\dorecurse\allocatednofcolumns{\columnsetbotbox \recurselevel\emptybox}}
+
+%D Without going in details we present two macro's which handle
+%D the columns. The action which is transfered by the the first
+%D and only parameter can do something with \type
+%D {\currentcolumnbox}. In case of the mid columns, \type
+%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled
+%D outside these macro's.
+
+\def\dohandlecolumn#1%
+ {\mofcolumns\recurselevel
+ \let\currentcolumn\recurselevel
+ #1\relax}
+
+\def\dohandleallcolumns#1%
+ {\dorecurse\nofcolumns{\dohandlecolumn{#1}}}
+
+\def\dohandlerevcolumns#1%
+ {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}}
+
+\def\dohandlemidcolumns#1%
+ {\dohandleallcolumns
+ {\ifnum\recurselevel>\plusone
+ \ifnum\recurselevel<\nofcolumns
+ \dohandlecolumn{#1}%
+ \fi
+ \fi}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-com.mkiv b/Master/texmf-dist/tex/context/base/page-com.mkiv
index dbb160058c1..80012dd1454 100644
--- a/Master/texmf-dist/tex/context/base/page-com.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-com.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Page Comments,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -103,7 +103,7 @@
\setvalue{\e!start\v!pagecomment}%
{\global\pagecommenttrue
- \dostartbuffer[\v!pagecomment][\e!start\v!pagecomment][\e!stop\v!pagecomment]}
+ \grabbufferdatadirect\v!pagecomment{\e!start\v!pagecomment}{\e!stop\v!pagecomment}}
\setuppagecomment
[\c!state=, % \v!stop would invoke background calculation
diff --git a/Master/texmf-dist/tex/context/base/page-fac.mkiv b/Master/texmf-dist/tex/context/base/page-fac.mkiv
new file mode 100644
index 00000000000..fef1cd5ac35
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-fac.mkiv
@@ -0,0 +1,77 @@
+%D \module
+%D [ file=page-fac, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Facing Pages,
+%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 / Facing Pages}
+
+\unprotect
+
+%D \macros
+%D {setupoppositeplacing,startopposite}
+%D
+%D \starttyping
+%D \starttext
+%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
+%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
+%D \stoptext
+%D \stoptyping
+
+\newbox\b_page_facings_content
+
+\unexpanded\def\setupoppositeplacing
+ {\dodoubleargument\getparameters[\??np]}
+
+\unexpanded\def\startopposite
+ {\dowithnextboxcontent
+ {\hsize\makeupwidth}%
+ {\global\setbox\b_page_facings_content\vbox
+ {\ifvoid\b_page_facings_content
+ \@@npbefore
+ \else
+ \@@npinbetween
+ \unvbox\b_page_facings_content
+ \fi
+ \box\nextbox}}%
+ \vbox\bgroup}
+
+\unexpanded\def\stopopposite
+ {\egroup}
+
+\def\page_facings_finish
+ {\ifvoid\b_page_facings_content\else
+ \global\setbox\b_page_facings_content\vbox to \makeupheight
+ {\unvbox\b_page_facings_content
+ \@@npafter
+ \vss}%
+ \fi}
+
+\def\page_facings_flush
+ {\doif\@@npstate\v!start
+ {\ifvoid\b_page_facings_content\else
+ \ifnum\realpageno>\plusone
+ \begingroup
+ \pageornamentstate\plusone % tricky
+ \page_facings_finish
+ \page_boxes_shipout{\page_boxes_constructed_page\box\b_page_facings_content}%
+ \endgroup
+ \else
+ \global\setbox\b_page_facings_content\emptybox
+ \fi
+ \fi}}
+
+\setupoppositeplacing
+ [\c!state=\v!start,
+ \c!before=,
+ \c!inbetween=\blank,
+ \c!after=]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-flt.lua b/Master/texmf-dist/tex/context/base/page-flt.lua
index b691dbd45c1..ecd7004ae9f 100644
--- a/Master/texmf-dist/tex/context/base/page-flt.lua
+++ b/Master/texmf-dist/tex/context/base/page-flt.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['page-flt'] = {
}
-- floats -> managers.floats
+-- some functions are a tex/lua mix so we need a separation
local insert, remove = table.insert, table.remove
local find = string.find
@@ -46,10 +47,6 @@ function floats.stacked(which) -- floats.thenofstacked
return #stacks[which or default]
end
-function floats.thestacked(which)
- return context(#stacks[which or default])
-end
-
function floats.push()
insert(pushed,stacks)
stacks = initialize()
@@ -164,13 +161,6 @@ function floats.flush(which,n,bylabel)
end
end
-function floats.thevar(name,default)
- local value = last and last.data[name] or default
- if value and value ~= "" then
- context(value)
- end
-end
-
function floats.consult(which,n)
which = which or default
local stack = stacks[which]
@@ -213,60 +203,83 @@ function floats.collect(which,maxwidth,distance)
setcount("global","nofcollectedfloats",m)
end
-function commands.doifsavedfloatelse(which)
- local stack = stacks[which or default]
- commands.doifelse(#stack>0)
+function floats.getvariable(name,default)
+ local value = last and last.data[name] or default
+ return value ~= "" and value
end
-function floats.thecheckedpagefloat(packed)
- local result = ""
+function floats.checkedpagefloat(packed)
if structures.pages.is_odd() then
if #stacks.rightpage > 0 then
- result = "rightpage"
+ return "rightpage"
elseif #stacks.page > 0 then
- result = "page"
+ return "page"
elseif #stacks.leftpage > 0 then
if packed then
- result = "leftpage"
- else
- result = "empty"
+ return "leftpage"
end
end
else
if #stacks.leftpage > 0 then
- result = "leftpage"
+ return "leftpage"
elseif #stacks.page > 0 then
- result = "page"
+ return "page"
elseif #stacks.rightpage > 0 then
if packed then
- result = "rightpage"
- else
- result = "empty"
+ return "rightpage"
end
end
end
- context(result)
+end
+
+function floats.nofstacked()
+ return #stacks[which or default] or 0
end
local method = C((1-S(", :"))^1)
local position = P(":") * C((1-S("*,"))^1) * P("*") * C((1-S(","))^1)
local label = P(":") * C((1-S(",*: "))^0)
-local pattern = method * (label * position + C("") * position + label + C("") * C("") * C(""))
+local pattern = method * (
+ label * position
+ + C("") * position
+ + label
+ + C("") * C("") * C("")
+) + C("") * C("") * C("") * C("")
+
--- table.print { lpeg.match(pattern,"somewhere:blabla,crap") }
--- table.print { lpeg.match(pattern,"somewhere:1*2") }
--- table.print { lpeg.match(pattern,"somewhere:blabla:1*2") }
--- table.print { lpeg.match(pattern,"somewhere::1*2") }
--- table.print { lpeg.match(pattern,"somewhere,") }
--- table.print { lpeg.match(pattern,"somewhere") }
+-- inspect { lpegmatch(pattern,"somewhere:blabla,crap") }
+-- inspect { lpegmatch(pattern,"somewhere:1*2") }
+-- inspect { lpegmatch(pattern,"somewhere:blabla:1*2") }
+-- inspect { lpegmatch(pattern,"somewhere::1*2") }
+-- inspect { lpegmatch(pattern,"somewhere,") }
+-- inspect { lpegmatch(pattern,"somewhere") }
+-- inspect { lpegmatch(pattern,"") }
function floats.analysemethod(str)
- if str ~= "" then -- extra check, already done at the tex end
- local method, label, row, column = lpegmatch(pattern,str)
- context.setvalue("floatmethod",method or "")
- context.setvalue("floatlabel", label or "")
- context.setvalue("floatrow", row or "")
- context.setvalue("floatcolumn",column or "")
- end
+ return lpegmatch(pattern,str or "")
+end
+
+-- interface
+
+commands.flushfloat = floats.flush
+commands.savefloat = floats.save
+commands.resavefloat = floats.resave
+commands.pushfloat = floats.push
+commands.popfloat = floats.pop
+commands.consultfloat = floats.consult
+commands.collectfloat = floats.collect
+
+function commands.getfloatvariable (...) local v = floats.getvariable(...) if v then context(v) end end
+function commands.checkedpagefloat (...) local v = floats.checkedpagefloat(...) if v then context(v) end end
+
+function commands.nofstackedfloats (...) context(floats.nofstacked(...)) end
+function commands.doifelsesavedfloat(...) commands.doifelse(floats.nofstacked(...)>0) end
+
+function commands.analysefloatmethod(str)
+ local method, label, row, column = floats.analysemethod(str)
+ context.setvalue("floatmethod",method)
+ context.setvalue("floatlabel", label )
+ context.setvalue("floatrow", row )
+ context.setvalue("floatcolumn",column)
end
diff --git a/Master/texmf-dist/tex/context/base/page-flt.mkiv b/Master/texmf-dist/tex/context/base/page-flt.mkiv
index 6d23891767c..18c0ad263c6 100644
--- a/Master/texmf-dist/tex/context/base/page-flt.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-flt.mkiv
@@ -1,11 +1,11 @@
%D \module
%D [ file=page-flt,
-%D version=2010.04,08,
+%D version=2010.04.08,
%D title=\CONTEXT\ Page Macros,
%D subtitle=Float Management,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -72,52 +72,49 @@
\to \everyfloatscheck
\def\dofloatsflush#1#2%
- {\ctxlua{floats.flush("#1",\number#2)}%
+ {\ctxcommand{flushfloat("#1",\number#2)}%
\the\everyfloatscheck}
\def\dofloatsflushbylabel#1#2%
- {\ctxlua{floats.flush("#1","#2",true)}%
+ {\ctxcommand{flushfloat("#1","#2",true)}%
\the\everyfloatscheck}
\def\dofloatssave#1%
- {\ctxlua{floats.save("#1")}%
+ {\ctxcommand{savefloat("#1")}%
\the\everyfloatscheck}
\def\dofloatsresave#1%
- {\ctxlua{floats.resave("#1")}%
+ {\ctxcommand{resavefloat("#1")}%
\the\everyfloatscheck}
\def\dopushsavedfloats
- {\ctxlua{floats.push()}%
+ {\ctxcommand{pushfloat()}%
\the\everyfloatscheck}
\def\dopopsavedfloats
- {\ctxlua{floats.pop()}%
+ {\ctxcommand{popfloat()}%
\the\everyfloatscheck}
\def\dofloatsgetinfo#1%
- {\ctxlua{floats.consult("#1")}}
+ {\ctxcommand{consultfloat("#1")}}
-\def\doifsavedfloatelse#1%
- {\ctxcommand{doifsavedfloatelse("#1")}}
+\def\doifelsesavedfloat#1%
+ {\ctxcommand{doifelsesavedfloat("#1")}}
\def\dofloatscollect#1#2#3%
- {\ctxlua{floats.collect("#1",\number\dimexpr#2,\number\dimexpr#3)}}
+ {\ctxcommand{collectfloat("#1",\number\dimexpr#2,\number\dimexpr#3)}}
-\def\dofloatsnofstacked#1%
- {\ctxlua{floats.thestacked("#1")}}
-
-\def\dofloatsgetvariable#1%
- {\ctxlua{floats.thevar("specification")}}
+\def\nofstackedfloatincategory#1%
+ {\ctxcommand{nofstackedfloats("#1")}}
\let\dopushcolumnfloats\dopushsavedfloats
\let\dopopcolumnfloats \dopopsavedfloats
\def\dofloatssavepagefloat#1#2%
- {\ctxlua{floats.save("#1", { specification = "#2" })}}
+ {\ctxcommand{savefloat("#1", { specification = "#2" })}}
\def\dofloatssavesomewherefloat#1#2% #1=method
- {\ctxlua{floats.save("#1", { specification = "#2", label = "\floatlabel" })}}
+ {\ctxcommand{savefloat("#1", { specification = "#2", label = "\floatlabel" })}}
%D This is an experimental new feature (for Alan Braslau), a prelude to more:
%D
@@ -146,11 +143,36 @@
\exitloop
\else
\def\currentfloat{#1}%
- \blank[\@@bkspacebefore]%
+ \blank[\rootfloatparameter\c!spacebefore]%
\box\floatbox
- \blank[\@@bkspaceafter]
+ \blank[\rootfloatparameter\c!spaceafter]
\fi}}
+% \setupcaption [figure] [align=flushleft]
+% \setupcaption [figure-1] [align=flushleft,leftmargin=10mm]
+% \setupcaption [figure-2] [align=flushleft,leftmargin=10mm,rightmargin=-10mm,width=\textwidth]
+%
+% \startsetups somefigure
+% \ifdim\floatsetupwidth>\textwidth
+% \placesetupfloat[figure-2]
+% \else
+% \placesetupfloat[figure-1]
+% \fi
+% \stopsetups
+%
+% \placefloatwithsetups[somefigure]{}{\externalfigure[dummy][width=5cm,height=2cm]}
+
+\def\placefloatwithsetups
+ {\dotripleempty\doplacefloatwithsetups}
+
+\long\def\doplacefloatwithsetups[#1][#2][#3]#4%
+ {\def\floatsetupcaption {#4}%
+ \def\floatsetupcontent {\copy\nextbox}%
+ \def\floatsetupwidth {\wd\nextbox}%
+ \def\floatsetupheight {\ht\nextbox}%
+ \def\placesetupfloat[##1]{\placefloat[##1][#2][#3]{#4}{\floatsetupcontent}}% #4 and not \floatsetupcaption (unexpanded)
+ \dowithnextbox{\setups[#1]}\vbox}
+
%D The following code is in transition as we don't want to break the
%D current single column, multi column, and columnset mechanism.
%D
@@ -166,7 +188,7 @@
% retain special alignments
\ifinsidecolumns
\ifdim\wd\floatbox>\makeupwidth
- \global\wd\floatbox\makeupwidth
+ \wd\floatbox\makeupwidth
\fi
\fi
\fi
@@ -186,10 +208,10 @@
\def\doreversesavefloat
{\dofloatsresave\s!text}
-\def\doflushsavedfloats % simplified \OTRONEdodoflushfloats
+\def\doflushsavedfloats
{\doloop
{\ifsomefloatwaiting
- \docheckiffloatfits
+ \page_otr_command_check_if_float_fits
\ifroomforfloat
\dogetfloat
\doplacefloatbox
@@ -197,7 +219,11 @@
\exitloop
\fi
\else
- \exitloop
+% \ifconditional\c_page_margin_blocks_present % not here, here just as many floats as fit
+% \page_otr_command_flush_margin_blocks
+% \else
+ \exitloop
+% \fi
\fi}}
%D Page floats use different stacks.
@@ -206,44 +232,25 @@
\def\doflushsomepagefloat#1% future releases can do more clever things
{\dofloatsflush{#1}{1}%
- \edef\floatspecification{\dofloatsgetvariable{specification}}%
+ \edef\floatspecification{\ctxcommand{getfloatvariable("specification")}}% Is this okay?
\the\everybeforeflushedpagefloat
\vbox to \textheight
{\doifnotinset\v!high\floatspecification\vfill
\box\floatbox
\doifnotinset\v!low\floatspecification\vfill}%
- \vfill\eject}
-
-% \def\doflushpagefloats
-% {\doifoddpageelse
-% {\ifnum\dofloatsnofstacked\s!rightpage>\zerocount
-% \doflushsomepagefloat\s!rightpage
-% \else\ifnum\dofloatsnofstacked\s!page>\zerocount
-% \doflushsomepagefloat\s!page
-% \else\ifnum\dofloatsnofstacked\s!leftpage>\zerocount
-% \emptyhbox\vfill\eject
-% %\doflushsomepagefloat\s!leftpage
-% \fi\fi\fi}
-% {\ifnum\dofloatsnofstacked\s!leftpage>\zerocount
-% \doflushsomepagefloat\s!leftpage
-% \else\ifnum\dofloatsnofstacked\s!page>\zerocount
-% \doflushsomepagefloat\s!page
-% \else\ifnum\dofloatsnofstacked\s!rightpage>\zerocount
-% \emptyhbox\vfill\eject
-% %\doflushsomepagefloat\s!rightpage
-% \fi\fi\fi}}
+ \page_otr_fill_and_eject_page}
\def\doflushpagefloats
- {\edef\checkedpagefloat{\ctxlua{floats.thecheckedpagefloat()}}% (true) for packed
- \ifx\checkedpagefloat\empty
+ {\edef\m_page_otf_checked_page_float{\ctxcommand{checkedpagefloat()}}% (true) for packed
+ \ifx\m_page_otf_checked_page_float\empty
% nothing
- \else\ifx\checkedpagefloat\v!empty
- \emptyhbox\vfill\eject
+ \else\ifx\m_page_otf_checked_page_float\v!empty
+ \emptyhbox \page_otr_fill_and_eject_page % why not dummy_page
\else
- \doflushsomepagefloat\checkedpagefloat
+ \doflushsomepagefloat\m_page_otf_checked_page_float
\fi\fi}
-\def\uncenteredfloatbox
+\def\uncenteredfloatbox % hm, where is this one used (was in save/restore, see old implementation)
{\ifcenterfloatbox
\ifhbox\floatbox\relax % remove centering
\ifdim\wd\floatbox=\hsize
@@ -266,9 +273,6 @@
\box\floatbox
\fi}
-\ifdefined\doflushfloats\else \let\doflushfloats\relax \fi
-\ifdefined\flushfloatbox\else \let\flushfloatbox\relax \fi
-
% temp hack, needed to prevent floatbox being forgotten during
% output, this will change to using another box for flushing
%
@@ -281,6 +285,7 @@
\appendtoks
\global\setbox\savedfloatbox\box\floatbox
\to \everybeforeoutput
+
\appendtoks
\global\setbox\floatbox\box\savedfloatbox
\to \everyafteroutput
diff --git a/Master/texmf-dist/tex/context/base/page-flw.mkii b/Master/texmf-dist/tex/context/base/page-flw.mkii
index 3eb867a78f4..ba8fd3eabaf 100644
--- a/Master/texmf-dist/tex/context/base/page-flw.mkii
+++ b/Master/texmf-dist/tex/context/base/page-flw.mkii
@@ -5,7 +5,7 @@
%D subtitle=Text Flows,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-flw.mkiv b/Master/texmf-dist/tex/context/base/page-flw.mkiv
index 81b4fedcbfd..9afacf5845f 100644
--- a/Master/texmf-dist/tex/context/base/page-flw.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-flw.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Text Flows,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
@@ -53,8 +53,7 @@
\bgroup
\unvbox\textflowcollector{#1}%
\hsize\textflowparameter{#1}\c!width
- \doifsomething{\textflowparameter{#1}\c!style}%
- {\doconvertfont{\textflowparameter{#1}\c!style}}%
+ \dousestyleparameter{\textflowparameter{#1}\c!style}%
\unexpanded\def\stoptextflow{\endgraf\egroup}}
{\let\stoptextflow\relax}}
diff --git a/Master/texmf-dist/tex/context/base/page-grd.mkiv b/Master/texmf-dist/tex/context/base/page-grd.mkiv
new file mode 100644
index 00000000000..e882978ca38
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-grd.mkiv
@@ -0,0 +1,85 @@
+%D \module
+%D [ file=page-grd, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Grids,
+%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 / Grids}
+
+\unprotect
+
+\definepalet
+ [layout]
+ [grid=red,
+ page=green]
+
+\newconstant\c_page_grids_location
+\newconstant\c_page_grids_line_mode
+\newconstant\c_page_grids_lineno_mode
+
+\unexpanded\def\showgrid
+ {\dosingleempty\page_grids_show}
+
+\def\page_grids_show[#1]%
+ {\c_page_grids_location \plusone % downward compatible default
+ \c_page_grids_line_mode \plusone
+ \c_page_grids_lineno_mode\plusone
+ \processallactionsinset
+ [#1]%
+ [ \v!reset=>\c_page_grids_location \zerocount,
+ \v!bottom=>\c_page_grids_location \plusone,
+ \v!top=>\c_page_grids_location \plustwo,
+ \v!none=>\c_page_grids_line_mode \zerocount,
+ \v!all=>\c_page_grids_line_mode \plusone,
+ \v!lines=>\c_page_grids_line_mode \plustwo,
+ \v!frame=>\c_page_grids_line_mode \plusthree,
+ \v!nonumber=>\c_page_grids_lineno_mode\zerocount,
+ \v!right=>\c_page_grids_lineno_mode\plusone,
+ \v!left=>\c_page_grids_lineno_mode\plustwo,
+ \v!outer=>\c_page_grids_lineno_mode\plusthree]%
+ \ifcase\c_page_grids_location
+ \let\page_grids_add_to_box\gobbleoneargument
+ \else % 1=bottom 2=top
+ \let\page_grids_add_to_box\page_grids_add_to_box_indeed
+ \fi}
+
+% if really needed for speed we can cache the grid
+
+\let\page_grids_add_to_box\gobbleoneargument
+
+\def\page_grids_add_to_box_indeed#1% to be checked for color and layer ..... use mp
+ {\startcolor[layout:grid]%
+ \gridboxlinemode \c_page_grids_line_mode
+ \gridboxlinenomode\c_page_grids_lineno_mode
+ \setgridbox\scratchbox\makeupwidth\textheight % todo: check color
+ \global\setbox#1\hbox % global ?
+ {\ifcase\c_page_grids_location\or\or\box#1\hskip-\makeupwidth\fi
+ \begingroup % color
+ \ifcase\layoutcolumns\else
+ \gray
+ \setlayoutcomponentattribute{\v!grid:\v!columns}%
+ \hbox \layoutcomponentboxattribute to \makeupwidth
+ {\dorecurse\layoutcolumns
+ {\hskip\layoutcolumnwidth
+ \ifnum\recurselevel<\layoutcolumns
+ \vrule
+ \!!height\ht\scratchbox
+ \!!depth\dp\scratchbox
+ \!!width\layoutcolumndistance
+ \fi}}%
+ \hskip-\makeupwidth
+ \fi
+ \setlayoutcomponentattribute{\v!grid:\v!lines}%
+ \hbox \layoutcomponentboxattribute{\box\scratchbox}%
+ \endgroup
+ \ifcase\c_page_grids_location\or\hskip-\makeupwidth\box#1\fi}%
+ \stopcolor}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-imp.mkii b/Master/texmf-dist/tex/context/base/page-imp.mkii
index 4c22d4d2d6d..bf10504b48c 100644
--- a/Master/texmf-dist/tex/context/base/page-imp.mkii
+++ b/Master/texmf-dist/tex/context/base/page-imp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Pagebody Building (Imposition),
%D author=Hans Hagen & Willi Egger,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -138,24 +138,14 @@
\newbox\postponedcontent
-% \def\flushatshipout
-% {\dowithnextbox
-% {\global\setbox\postponedcontent\hbox to \zeropoint
-% {%\hskip-\maxdimen % niet hier, gaat mis in acrobat (clipt)
-% \box\postponedcontent\flushnextbox}%
-% \global\ht\postponedcontent\zeropoint
-% \global\dp\postponedcontent\zeropoint
-% \global\wd\postponedcontent\zeropoint}%
-% \hbox}
-
\def\flushatshipout
{\dowithnextbox
{\global\setbox\postponedcontent\hbox to \zeropoint
{%\hskip-\maxdimen % niet hier, gaat mis in acrobat (clipt)
\unhbox\postponedcontent\unhbox\nextbox}%
- \global\ht\postponedcontent\zeropoint
- \global\dp\postponedcontent\zeropoint
- \global\wd\postponedcontent\zeropoint}%
+ \ht\postponedcontent\zeropoint
+ \dp\postponedcontent\zeropoint
+ \wd\postponedcontent\zeropoint}%
\hbox}
% \starttypen
@@ -548,15 +538,15 @@
\fi}
\def\handlearrangedpageSIDE
- {\global\wd\arrangedpageA\paperwidth
- \global\wd\arrangedpageB\paperwidth
+ {\wd\arrangedpageA\paperwidth
+ \wd\arrangedpageB\paperwidth
\global\setbox\arrangedpageA\hbox
{\box\arrangedpageA\box\arrangedpageB}%
- \global\ht\arrangedpageA\paperheight}
+ \ht\arrangedpageA\paperheight}
\def\handlearrangedpageTOP
- {\global\ht\arrangedpageA\paperheight
- \global\ht\arrangedpageB\paperheight
+ {\ht\arrangedpageA\paperheight
+ \ht\arrangedpageB\paperheight
\global\setbox\arrangedpageA\vbox
{\forgetall\offinterlineskip\vskip\paperheight
\box\arrangedpageA\box\arrangedpageB}%
@@ -585,13 +575,13 @@
\clippedprintbox1\arrangedpageA}%
\swaparrangedtrue
\fi
- \global\ht\arrangedpageA\paperheight
+ \ht\arrangedpageA\paperheight
\global\setbox\arrangedpageB\box\scratchbox}
\def\handlearrangedpageTWODOWN
{\splitoffarrangedpagesTWO
- \global\ht\arrangedpageA\paperheight
- \global\ht\arrangedpageB\paperheight
+ \ht\arrangedpageA\paperheight
+ \ht\arrangedpageB\paperheight
\ifswaparranged
\global\setbox\arrangedpageA\vbox
{\forgetall\offinterlineskip\vskip\paperheight
diff --git a/Master/texmf-dist/tex/context/base/page-imp.mkiv b/Master/texmf-dist/tex/context/base/page-imp.mkiv
index b6fa75c8ba6..71c30a7e19e 100644
--- a/Master/texmf-dist/tex/context/base/page-imp.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-imp.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Pagebody Building (Imposition),
%D author=Hans Hagen & Willi Egger,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,144 +17,124 @@
\unprotect
-% sizing bug:
-%
-% \setuppapersize[A4][A4,landscape] \setuparranging[2UP] \showframe
-%
-% \starttext \dorecurse{10}{\input tufte \par} \stoptext
-
-\newif\ifclipprintbox \clipprintboxtrue % todo: conditional
-%newif\ifclippagebox \clippageboxtrue
-
-\def\clippedprintbox#1#2% can be made more efficient, see other clipper
- {\ifclipprintbox
- \!!widthc \pagebackgroundoffset
- \!!widtha \dimexpr\paperwidth + \!!widthc\relax
- \!!heighta\dimexpr\paperheight+2\!!widthc\relax
- \setbox#2\vbox to \paperheight{\vfill\box#2}%
- \ht#2\paperheight
- \wd#2\paperwidth
- \setbox#2\vbox
- {\framed
- [\c!offset=\!!widthc,\c!strut=\v!no,\c!frame=\v!off]
- {\box#2}}%
- \setbox#2\hbox to \paperwidth
- {\ifcase#1\relax
- \!!widthb\zeropoint
- \hskip-\!!widthc
- \else
- \!!widthb\!!widthc
- \fi
- \lower\!!widthc\hbox
- {\clip
- [\c!width=\!!widtha,\c!height=\!!heighta,
- \c!hoffset=\!!widthb,\c!voffset=\zeropoint]
- {\box#2}}}%
- \wd#2\paperwidth
- \ht#2\paperheight
- \fi
- \box#2\relax}
-
-\let\clippagebox \gobbleoneargument
-\let\clipprintbox\gobbleoneargument
-
-% \setuppagenumbering[alternative=doublesided]
-% \setupcolors[state=start]
-% \setuppapersize[A4][A4,oversized]
-% \setuplayout[location=middle,clipoffset=5mm]
-% \setupbackgrounds
-% [page]
-% [frame=on,rulethickness=1mm,
-% backgroundoffset=10mm,background=color,backgroundcolor=red]
-% \starttext \dorecurse{10}{\input tufte \par} \stoptext
-
-\def\clippagebox % skip fast over false
- {\ifdim\@@lyclipoffset>\zeropoint
- \expandafter\doclippagebox
- \else
- \expandafter\gobbleoneargument
- \fi}
-
-\def\doclippagebox#1%
- {\!!widtha \wd#1%
- \!!heighta\ht#1%
- \!!deptha \dp#1%
- \setbox#1\hbox
- {\!!widthb \@@lyclipoffset
- \advance\!!heighta\dimexpr\!!deptha+2\!!widthb\relax
- \advance\!!widtha \!!widthb
- \doifbothsides
- {\advance\!!widtha\!!widthb \!!widthc-\!!widthb \hskip\!!widthc}%
- {\!!widthc\zeropoint}
- {\!!widthc-\!!widthb \hskip\!!widthc}%
- \lower\!!widthb\hbox
- {\clip
- [\c!hoffset=\!!widthc,
- \c!voffset=-\!!widthb,
- \c!width=\!!widtha,
- \c!height=\!!heighta]%
- {\box#1}}}%
- \wd#1\!!widtha
- \ht#1\!!heighta
- \dp#1\!!deptha}
-
%D \macros
%D {starttextdata}
%D
%D This is a user macro (appending to every last shipout is not
-%D really user friendly.
+%D really user friendly).
+
+\newtoks\t_page_text_data
-\newtoks\collectedtextdata
+\unexpanded\def\starttextdata#1\stoptextdata
+ {\global\let\page_shipouts_flush_text_data\page_shipouts_flush_text_data_indeed
+ \globaladdtotoks\t_page_text_data{#1}}
-\long\unexpanded\def\starttextdata#1\stoptextdata
- {\doglobal\appendtoks#1\to\collectedtextdata}
+\let\stoptextdata\relax
-\def\flushtextdata
- {\vsmashed{\the\collectedtextdata}% all dimensions zero
- \global\collectedtextdata\emptytoks
- \globallet\flushtextdata\donothing}
+\def\page_shipouts_flush_text_data_indeed
+ {\vsmashed{\the\t_page_text_data}%
+ \global\t_page_text_data\emptytoks
+ \global\let\page_shipouts_flush_text_data\relax}
-\prependtoks \flushtextdata \to \everylastshipout
+\let\page_shipouts_flush_text_data\relax
+
+\prependtoks
+ \page_shipouts_flush_text_data
+\to \everylastshipout
-\def\installpagehandler#1#2% % a handler takes one argument: something to be boxed
- {\setgvalue{\??pp:\c!method:#1}##1{#2{##1}}} % and shipped out (don't depend on the exact package)
-
-\installpagehandler\v!normal
- {\ifarrangingpages\expandafter\actualarrange\else\expandafter\actualshipout\fi}
-
-\def\myshipout#1%
- {\beforeshipout % voor de pagebody dus !
- \dontshowcomposition
- \dontcomplain
- \executeifdefined{\??pp:\c!method:\@@ppmethod}\gobbleoneargument{#1}%
- \setnextrealpageno
- \aftershipout}
-
-\newbox\postponedcontent
-
-\def\flushatshipout
- {\dowithnextbox
- {\global\setbox\postponedcontent\hbox to \zeropoint
- {%\hskip-\maxdimen % niet hier, gaat mis in acrobat (clipt)
- \unhbox\postponedcontent\unhbox\nextbox}% was \box
- \global\ht\postponedcontent\zeropoint
- \global\dp\postponedcontent\zeropoint
- \global\wd\postponedcontent\zeropoint}%
- \hbox}
+% Problem: we need to apply the finalizers to a to be shipped out page (as
+% we can have positioning involved). However, we can also add stuff in the
+% imposition, like cropmarks. Fortunately we do that with metapost so
+% colors etc are dealt with at that end.
% \starttypen
% \def\pagestoshipout{1,3,5}
% \stoptypen
-\newcount\shippedoutpages
-\newcount\combinedpagescounter
+\installcorenamespace{shipoutmethod}
+\installcorenamespace{layoutarranger}
+\installcorenamespace{layoutarrangeoption}
+
+\newcount \shippedoutpages
+\newcount \combinedpagescounter
-\let\pagestoshipout\empty % {1,3,6}
-\newconstant\whichpagetoshipout % 0=all 1=odd 2=even
+\let \pagestoshipout\empty % {1,3,6}
+\newconstant \whichpagetoshipout % 0=all 1=odd 2=even
-\newbox\shipoutscratchbox
+\newbox \shipoutscratchbox
-\def\actualshipout#1% todo: less callbacks
+\setnewconstant\shipoutfinalizemethod\plusone % this will be default (we will have two finalizers)
+
+\unexpanded\def\installshipoutmethod#1#2% % a handler takes one argument: something to be boxed
+ {\setgvalue{\??shipoutmethod#1}##1{#2{##1}}} % and shipped out (don't depend on the exact package)
+
+\let\installpagehandler\installshipoutmethod % will go
+
+\unexpanded\def\invokepagehandler#1%
+ {\expandcheckedcsname{\??shipoutmethod}{#1}\v!normal}
+
+\def\page_shipouts_handle
+ {\csname\??shipoutmethod\ifcsname\??shipoutmethod\v_page_target_method\endcsname
+ \v_page_target_method
+ \else
+ \v!none
+ \fi\endcsname}
+
+\installshipoutmethod \v!normal
+ {\ifarrangingpages
+ \expandafter\page_shipouts_arrange
+ \else
+ \expandafter\page_shipouts_normal
+ \fi}
+
+\installshipoutmethod \v!none
+ {\page_shipouts_ignore}
+
+\def\page_boxes_shipout#1% or: \page_shipouts_apply
+ {\dontcomplain % redundant
+ \the\everybeforeshipout
+ \ifcase\shipoutfinalizemethod
+ \page_shipouts_handle{#1}%
+ \else
+ \setbox\shipoutscratchbox\hbox{#1}% just in case there are objects there, hook for testing (will go away)
+ \finalizeshipoutbox\shipoutscratchbox
+ \page_shipouts_handle{\box\shipoutscratchbox}%
+ \fi
+ \setnextrealpageno % so this comes before \everyaftershipout so in fact:
+ \the\everyaftershipout} % at this point we're already on the next realpage
+
+\def\page_shipouts_ignore#1%
+ {\begingroup
+ \message
+ {[\ifarrangingpages arranged \fi page
+ \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace
+ not flushed]}%
+ \setbox\scratchbox\hbox{#1}%
+ \deadcycles\zerocount
+ \endgroup}
+
+\def\page_otr_flush_every_stuff
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {% before the main one !
+ \ifcase\realfolio \or
+ \the\everyfirstshipout
+ \global\everyfirstshipout\emptytoks
+ \fi
+ % the main one
+ \the\everyshipout\relax
+ % always last (and after the main one)
+ \ifnum\realpageno=\lastpage\relax
+ \the\everylastshipout
+ \global\everylastshipout\emptytoks
+ \fi}%
+ \smashbox\scratchbox
+ \box\scratchbox
+ \endgroup}
+
+\newdimen\d_page_shipouts_offset \d_page_shipouts_offset=-1in
+
+\def\page_shipouts_normal#1%
{\global\advance\shippedoutpages\plusone
% this is not resource safe!
\ifx\pagestoshipout\empty
@@ -168,50 +148,36 @@
\donetrue
\fi
\else % testen, aangepast / expanded nodig ?
- \normalexpanded{\noexpand\doifinsetelse{\the\shippedoutpages}{\pagestoshipout}}%
+ \normalexpanded{\doifinsetelse{\the\shippedoutpages}{\pagestoshipout}}%
\donetrue\donefalse
\fi
\ifdone
- \begingroup
- \setbox\shipoutscratchbox\hbox{#1}% just in case there are objects there, hook for testing
- \finalizeshipoutbox\shipoutscratchbox
- \setbox\scratchbox\hbox
- {% before the main one !
- \ifcase\realfolio \or
- \the\everyfirstshipout
- \global\everyfirstshipout\emptytoks
- \fi
- % the main one
- \the\everyshipout\relax
- % always last (and after the main one)
- \ifnum\realpageno=\lastpage\relax
- \the\everylastshipout
- \global\everylastshipout\emptytoks
- \fi}%
- \smashbox\scratchbox
- \shipout\vbox
+ \setbox\shipoutscratchbox\hbox{#1}%
+ \ifcase\shipoutfinalizemethod
+ \finalizeshipoutbox\shipoutscratchbox
+ \fi
+ \normalshipout\vbox
{\offinterlineskip
- \scratchdimen-1in % to be done in luatex: zero that one
- \vskip\scratchdimen
- \hskip\scratchdimen
- \hbox % \setbox0=\box.. is nicer
- {\box\scratchbox
- \ifvoid\postponedcontent\else\box\postponedcontent\fi % evt ver naar links !
+ \vskip\d_page_shipouts_offset
+ \hskip\d_page_shipouts_offset
+ \hbox
+ {\page_otr_flush_every_stuff
+ \page_otr_flush_special_content
\box\shipoutscratchbox}}%
- \endgroup
\else
- \message
- {[\ifarrangingpages arranged \fi page
- \ifarrangingpages\the\arrangeno\else\the\realpageno\fi\normalspace
- not flushed]}%
- \setbox0\hbox{#1}%
- \deadcycles\zerocount
+ \page_shipouts_ignore{#1}%
\fi}
-\def\actualarrange#1%
- {\setbox0\hbox{#1}%
- \pusharrangedpage0%
- \deadcycles\zerocount}
+\def\page_shipouts_arrange#1%
+ {% \global\advance\shippedoutpages\plusone
+ \begingroup
+ \setbox\scratchbox\hbox
+ {\page_otr_flush_every_stuff
+ \page_otr_flush_special_content
+ \box\shipoutscratchbox}%
+ \pusharrangedpage\scratchbox
+ \deadcycles\zerocount
+ \endgroup}
%D We need a couple of boxes for duplex printing \unknown
@@ -237,17 +203,17 @@
\newcount\arrangedpageX \arrangedpageX\plusone
\newcount\arrangedpageY \arrangedpageY\plusone
-\def\calculatepaperoffsets#1%
- {\global\paperoffset\getvalue{\??pp#1\c!offset}%
+\def\page_paper_set_offsets
+ {\global\paperoffset\v_page_target_offset
\global\advance\paperwidth -2\dimexpr\paperoffset/\arrangedpageX\relax
\global\advance\paperheight-2\dimexpr\paperoffset/\arrangedpageY\relax}
\def\doinstallarrangedoption#1#2%
- {\setvalue{\??pp=>#1}{#2}}
+ {\setvalue{\??layoutarrangeoption#1}{#2}}
\def\doinstalledarrangedoption#1%
- {\ifcsname\??pp=>#1\endcsname
- \csname\??pp=>#1\endcsname
+ {\ifcsname\??layoutarrangeoption#1\endcsname
+ \csname\??layoutarrangeoption#1\endcsname
\else
\checkinstalledpagearrangement{#1}% this installs the arranger
\fi}
@@ -270,12 +236,12 @@
\doinstallarrangedoption\v!rotated
{\gdef\arrangedrotationO {90}%
\gdef\arrangedrotationE{270}%
- \swapcounts\horizontalcutmarks\verticalcutmarks}
+ \swapcounts\c_page_marks_nx\c_page_marks_ny}
\doinstallarrangedoption{90}
{\gdef\arrangedrotationO {90}%
\gdef\arrangedrotationE{270}%
- \swapcounts\horizontalcutmarks\verticalcutmarks}
+ \swapcounts\c_page_marks_nx\c_page_marks_ny}
\doinstallarrangedoption{180}
{\gdef\arrangedrotationO{180}%
@@ -284,7 +250,7 @@
\doinstallarrangedoption{270}
{\gdef\arrangedrotationO{270}%
\gdef\arrangedrotationE {90}%
- \swapcounts\horizontalcutmarks\verticalcutmarks}
+ \swapcounts\c_page_marks_nx\c_page_marks_ny}
\doinstallarrangedoption\s!reset
{\global\arrangingpagesfalse}
@@ -307,20 +273,27 @@
\global\arrangingpagesfalse
\fi
\setuppapersize
+ \ifarrangingpages
+ \ctxlua{job.disablesave()}%
+ %\disabledirective[job.save]%
+ \fi
\fi}
\def\installpagearrangement #1 % will lchange, no space
- {\setgvalue{\??pp\??pp#1}}
+ {\setgvalue{\??layoutarranger#1}}
\def\checkinstalledpagearrangement#1% can be empty: aaa,,bbb
- {\executeifdefined{\??pp\??pp#1}\donothing}
+ {\executeifdefined{\??layoutarranger#1}\donothing}
+
+\let\poparrangedpages\relax
+\let\pusharrangedpage\relax
\def\dosetuparrangement#1#2#3#4#5#6#7#8%
{\global\arrangedpageX #1%
\global\arrangedpageY #2%
\global\arrangedpageT #3%
- \global\horizontalcutmarks #4%
- \global\verticalcutmarks #5%
+ \global\c_page_marks_nx #4%
+ \global\c_page_marks_ny #5%
\global\let\pusharrangedpage #6%
\global\let\poparrangedpages #7%
\global\let\handlearrangedpage#8}
@@ -383,7 +356,7 @@
\ifcase\scratchcounter\else
\advance\scratchcounter \plusone
\dostepwiserecurse\scratchcounter\arrangedpageT\plusone
- {\noheaderandfooterlines\ejectdummypage}%
+ {\noheaderandfooterlines\page_otr_insert_dummy_page}%
\fi
\fi}
@@ -403,7 +376,7 @@
\def\pagecutmarksymbol{\the\arrangeno}}
\def\outputarrangedbox#1%
- {\bgroup
+ {\begingroup
\forgetall % somehow we're back and need to redo this
\gotonextarrangepage
\ifnum\arrangedrotationO\arrangedrotationE>\zerocount
@@ -419,15 +392,24 @@
\fi}%
\fi
\ifconditional\arrangedmirrorstate
- \setbox#1\vbox{\domirrorbox\vbox{\box#1}}%
+ \page_boxes_apply_mirror{#1}%
\fi
\ifconditional\arrangednegatestate
- \negatecolorbox{#1}%
+ \page_boxes_apply_negate{#1}%
\fi
- \finishpagebox#1%
- \ifconditional\arrangedbackgroundstate\addprintbackground#1\fi
- \actualshipout{\box#1}%
- \egroup}
+ \page_marks_add_more #1%
+ \page_boxes_apply_center #1%
+ \page_boxes_apply_mirror_print #1%
+ \page_boxes_apply_orientate_print#1%
+ \page_boxes_apply_offset #1%
+ \page_boxes_apply_negate_print #1%
+ %
+ \ifconditional\arrangedbackgroundstate
+ \page_backgrounds_add_to_print#1%
+ \fi
+ %
+ \page_shipouts_normal{\box#1}%
+ \endgroup}
%D The format file can be 16K smaller when we postpone the
%D real arrangments. Some day ...
@@ -552,15 +534,15 @@
\fi}
\def\handlearrangedpageSIDE
- {\global\wd\arrangedpageA\paperwidth
- \global\wd\arrangedpageB\paperwidth
+ {\wd\arrangedpageA\paperwidth
+ \wd\arrangedpageB\paperwidth
\global\setbox\arrangedpageA\hbox
{\box\arrangedpageA\box\arrangedpageB}%
- \global\ht\arrangedpageA\paperheight}
+ \ht\arrangedpageA\paperheight}
\def\handlearrangedpageTOP
- {\global\ht\arrangedpageA\paperheight
- \global\ht\arrangedpageB\paperheight
+ {\ht\arrangedpageA\paperheight
+ \ht\arrangedpageB\paperheight
\global\setbox\arrangedpageA\vbox
{\offinterlineskip\vskip\paperheight
\box\arrangedpageA\box\arrangedpageB}%
@@ -580,22 +562,22 @@
{\splitoffarrangedpagesTWO
\ifconditional\arrangedswapstate
\global\setbox\arrangedpageA\hbox
- {\clippedprintbox\zerocount\arrangedpageA
- \clippedprintbox\plusone \arrangedpageB}%
+ {\page_boxes_apply_clip_print_left \arrangedpageA\box\arrangedpageA
+ \page_boxes_apply_clip_print_right\arrangedpageB\box\arrangedpageB}%
\setfalse\arrangedswapstate
\else
\global\setbox\arrangedpageA\hbox
- {\clippedprintbox\zerocount\arrangedpageB
- \clippedprintbox\plusone \arrangedpageA}%
+ {\page_boxes_apply_clip_print_left \arrangedpageB\box\arrangedpageB
+ \page_boxes_apply_clip_print_right\arrangedpageA\box\arrangedpageA}%
\settrue\arrangedswapstate
\fi
- \global\ht\arrangedpageA\paperheight
+ \ht\arrangedpageA\paperheight
\global\setbox\arrangedpageB\box\scratchbox}
\def\handlearrangedpageTWODOWN
{\splitoffarrangedpagesTWO
- \global\ht\arrangedpageA\paperheight
- \global\ht\arrangedpageB\paperheight
+ \ht\arrangedpageA\paperheight
+ \ht\arrangedpageB\paperheight
\ifconditional\arrangedswapstate
\global\setbox\arrangedpageA\vbox
{\offinterlineskip\vskip\paperheight
@@ -1117,22 +1099,30 @@
{\advancearrangedpageN
\global\advance\arrangedpageM\plusone
\reportarrangedpage\arrangedpageN
- \global\setbox\arrangedpageB\hbox \ifdim\@@ppwidth>\zeropoint to \@@ppwidth \fi
+ \global\setbox\arrangedpageB\hbox \ifdim\v_page_target_width>\zeropoint to \v_page_target_width \fi
{\ifvoid\arrangedpageB\else
\unhbox\arrangedpageB
- \ifdim\@@ppdx>\zeropoint \else \hss\fi
- \hskip\@@ppdx
- \ifdim\@@ppdx>\zeropoint \else \hss\fi
+ \ifdim\v_page_target_dx>\zeropoint
+ \hskip\v_page_target_dx
+ \else
+ \hss
+ \hskip\v_page_target_dx
+ \hss
+ \fi
\fi
\box#1}%
\ifnum\arrangedpageM<\arrangedpageX\else
- \global\setbox\arrangedpageA\vbox \ifdim\@@ppheight>\zeropoint to \@@ppheight \fi
+ \global\setbox\arrangedpageA\vbox \ifdim\v_page_target_height>\zeropoint to \v_page_target_height \fi
{\offinterlineskip
\ifvoid\arrangedpageA\else
\unvbox\arrangedpageA
- \ifdim\@@ppdy>\zeropoint \else \vss\fi
- \vskip\@@ppdy
- \ifdim\@@ppdy>\zeropoint \else \vss\fi
+ \ifdim\v_page_target_dy>\zeropoint
+ \vskip\v_page_target_dy
+ \else
+ \vss
+ \vskip\v_page_target_dy
+ \vss
+ \fi
\fi
\box\arrangedpageB}%
\global\arrangedpageM\zerocount
@@ -1151,19 +1141,42 @@
\fi}
\installpagearrangement XY
- {\dosetuparrangement\@@ppnx\@@ppny\@@ppxy\!!zerocount\!!zerocount
+ {\dosetuparrangement
+ \v_page_target_nx
+ \v_page_target_ny
+ \v_page_target_xy
+ \zerocount
+ \zerocount
\pusharrangedpageXY\poparrangedpagesXY\relax}
%D A crazy definition, don't guess who pushed me for the landscape option.
+\def\page_imposition_xy_height
+ {\dimexpr
+ \dimexpr
+ \v_page_target_height
+ -\numexpr\v_page_target_ny-1\relax\v_page_target_dy
+ \relax
+ /\v_page_target_ny
+ \relax}
+
+\def\page_imposition_xy_width
+ {\dimexpr
+ \dimexpr
+ \v_page_target_width
+ -\numexpr\v_page_target_nx-1\relax\v_page_target_dx
+ \relax
+ /\v_page_target_nx
+ \relax}
+
\definepapersize
[XY]
- [\c!height=\dimexpr\dimexpr\@@ppheight-\numexpr\@@ppny-1\relax\dimexpr\@@ppdy\relax\relax/\@@ppny\relax,
- \c!width =\dimexpr\dimexpr\@@ppwidth -\numexpr\@@ppnx-1\relax\dimexpr\@@ppdx\relax\relax/\@@ppnx\relax]
+ [\c!height=\page_imposition_xy_height,
+ \c!width =\page_imposition_xy_width]
\setuppaper
- [\c!width =\dimexpr\printpaperwidth -2\dimexpr\@@ppbackspace\relax\relax,
- \c!height=\dimexpr\printpaperheight-2\dimexpr\@@pptopspace \relax\relax]
+ [\c!width =\dimexpr\printpaperwidth -2\v_page_target_backspace\relax,
+ \c!height=\dimexpr\printpaperheight-2\v_page_target_topspace \relax]
% \definepageshift[test][horizontal][10pt,20pt,30pt,40pt,50pt]
% \definepageshift[test][vertical] [10pt,20pt,30pt,40pt,50pt]
@@ -1180,53 +1193,73 @@
% #1=name #2=horizontal|vertical #3=shiftlist
+% this will move to lua
+
+\installcorenamespace {pageshift}
+
\unexpanded\def\definepageshift
- {\dotripleargument\dodefinepageshift}
+ {\dotripleargument\page_boxes_define_shift}
-\def\dodefinepageshift[#1][#2][#3]%
- {\setvalue{\??pt#2:#1}{#3}}
+\def\page_boxes_define_shift[#1][#2][#3]%
+ {\setvalue{\??pageshift#2:#1}{#3}}
-\letempty\hpageshifts \newcount\nofhpageshifts
-\letempty\vpageshifts \newcount\nofvpageshifts
+\let\page_boxes_h_shifts\empty
+\let\page_boxes_v_shifts\empty
-\def\dogetpageshift#1#2#3% #1=\dimenx #2=\xpageshifts #3=\nofxpageshifts
- {\ifx#2\empty % we could do this in lua
- #1\zeropoint
- \else
+\newcount\c_page_boxes_h_shifts
+\newcount\c_page_boxes_v_shifts
+
+\newdimen\d_page_boxes_h_shifts
+\newdimen\d_page_boxes_v_shifts
+
+\let\page_boxes_apply_shift_print\gobbleoneargument
+\let\page_boxes_apply_shift_paper\gobbleoneargument
+
+\def\page_boxes_filter_shift#1#2#3% #1=\dimenx #2=\xpageshifts #3=\nofxpageshifts
+ {#1\zeropoint
+ \ifx#2\empty \else
\global\advance#3\plusone
\getfromcommacommand[#2][#3]%
\ifx\commalistelement\empty
\global#3\plusone % we cycle
\getfromcommacommand[#2][#3]%
\fi
- \ifx\commalistelement\empty
- #1\zeropoint
- \else
- #1=\commalistelement
- \donetrue
+ \ifx\commalistelement\empty \else
+ #1\commalistelement\relax % the relax is really needed as there is an \if later on
\fi
\fi}
-\def\shiftpagebox#1%
- {\donefalse
- \dogetpageshift{\dimen0}\hpageshifts\nofhpageshifts
- \dogetpageshift{\dimen2}\vpageshifts\nofvpageshifts
- \ifdone % see also layout offsets, maybe \movebox
- \edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
- \setbox#1\vbox
- {\offinterlineskip\vskip\dimen2\hskip\dimen0\box#1}%
- \next
+\def\page_boxes_apply_shift#1%
+ {\page_boxes_filter_shift\d_page_boxes_h_shifts\page_boxes_h_shifts\c_page_boxes_h_shifts
+ \page_boxes_filter_shift\d_page_boxes_v_shifts\page_boxes_v_shifts\c_page_boxes_v_shifts
+ \ifzeropt\d_page_boxes_h_shifts
+ \ifzeropt\d_page_boxes_v_shifts
+ % nothing to shift
+ \else
+ \page_boxes_apply_shift_indeed#1%
+ \fi
+ \else
+ \page_boxes_apply_shift_indeed#1%
\fi}
+\def\page_boxes_apply_shift_indeed#1%
+ {\edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
+ \setbox#1\vbox
+ {\offinterlineskip
+ \vskip\d_page_boxes_v_shifts
+ \hskip\d_page_boxes_h_shifts
+ \box#1}%
+ \next}
+
\unexpanded\def\setuppageshift
- {\dotripleempty\dosetuppageshift}
-
-\def\dosetuppageshift[#1][#2][#3]% page|paper horizontal vertical
- {\ifthirdargument % paper=arrange
- \edef\hpageshifts{\ifcsname\??pt\v!horizontal:#2\endcsname\csname\??pt\v!horizontal:#2\endcsname\fi}%
- \edef\vpageshifts{\ifcsname\??pt\v!vertical :#3\endcsname\csname\??pt\v!vertical :#3\endcsname\fi}%
- \doifelse{#1}\v!page {\let\shiftprintpagebox\shiftpagebox}{\let\shiftprintpagebox\gobbleoneargument}%
- \doifelse{#1}\v!paper{\let\shiftpaperpagebox\shiftpagebox}{\let\shiftpaperpagebox\gobbleoneargument}%
+ {\dotripleempty\page_boxes_setup_shift}
+
+\def\page_boxes_setup_shift[#1][#2][#3]% page|paper horizontal vertical
+ {\ifthirdargument % paper=arrange
+ \edef\page_boxes_h_shifts{\ifcsname\??pageshift\v!horizontal:#2\endcsname\csname\??pageshift\v!horizontal:#2\endcsname\fi}%
+ \edef\page_boxes_v_shifts{\ifcsname\??pageshift\v!vertical :#3\endcsname\csname\??pageshift\v!vertical :#3\endcsname\fi}%
+ \doifelse{#1}\v!page {\let\page_boxes_apply_shift_print\page_boxes_apply_shift}{\let\page_boxes_apply_shift_print\gobbleoneargument}%
+ \doifelse{#1}\v!paper{\let\page_boxes_apply_shift_paper\page_boxes_apply_shift}{\let\page_boxes_apply_shift_paper\gobbleoneargument}%
\else\ifsecondargument
\doifinsetelse{#1}{\v!page,\v!paper}
{\setuppageshift[#1][#2][#2]}
@@ -1235,5 +1268,4 @@
\setuppageshift[\v!page][#1][#1]%
\fi\fi\fi}
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-inf.mkiv b/Master/texmf-dist/tex/context/base/page-inf.mkiv
new file mode 100644
index 00000000000..6c220fb310c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-inf.mkiv
@@ -0,0 +1,106 @@
+%D \module
+%D [ file=page-inf, % moved from page-ini
+%D version=2011.12.07, % 2000.10.20,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Tracing Info,
+%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 / Tracing Info}
+
+% this needs a real cleanup .. will be a more detailed list
+
+\unprotect
+
+\installcorenamespace{layoutinfo}
+
+\newtoks\everyresetversion
+\newtoks\everysetupversion
+
+\let\currentversioninfo\empty
+
+\def\setupversion
+ {\dosingleargument\page_info_setup}
+
+\let\version\setupversion
+
+\let\page_info_add_to_box\gobbleoneargument
+
+\def\page_info_setup[#1]%
+ {\the\everyresetversion
+ \ifcsname\??layoutinfo#1\endcsname
+ \edef\currentversioninfo{#1}%
+ \let\page_info_add_to_box\page_info_add_to_box_indeed
+ \else
+ \let\currentversioninfo\empty
+ \let\page_info_add_to_box\gobbleoneargument
+ \fi
+ \the\everysetupversion}
+
+\unexpanded\def\page_info_place_info % at the bottom of the page
+ {\csname\??layoutinfo\currentversioninfo\endcsname}
+
+\unexpanded\def\installversioninfo#1#2%
+ {\setvalue{\??layoutinfo#1}{#2}}
+
+\unexpanded\def\includeversioninfo#1%
+ {\csname\??layoutinfo#1\endcsname}
+
+\installversioninfo\v!concept
+ {\vskip\!!sixpoint
+ \hbox to \makeupwidth
+ {\infofont
+ \v!concept:\space\currentdate
+ \hss
+ \page_adapts_status_info}}
+
+\installversioninfo\v!file
+ {\vskip\!!sixpoint
+ \hbox to \makeupwidth
+ {\infofont
+ \getmessage\m!system{27}:\space\currentdate\space
+ \donefalse
+ \ifx\currentproject \empty \else \space\v!project :\space\currentproject \space \donetrue \fi
+ \ifx\currentproduct \empty \else \space\v!product :\space\currentproduct \space \donetrue \fi
+ \ifx\currentcomponent\empty \else \space\v!component:\space\currentcomponent\space \donetrue \fi
+ \ifdone \else \space\v!file :\space\jobname \space \fi
+ \hss
+ \page_adapts_status_info}}
+
+\installversioninfo\v!temporary
+ {\includeversioninfo\v!file}
+
+\appendtoks
+ \overfullrule\zeropoint
+\to \everyresetversion
+
+\appendtoks
+ \ifx\currentversioninfo\v!temporary
+ \overfullrule5\points
+ \fi
+\to \everysetupversion
+
+\newbox\b_page_versions
+
+\def\page_info_add_to_box_indeed#1%
+ {\scratchdimen\wd#1%
+ \setbox\b_page_versions\vbox to \ht#1%
+ {\vfill
+ \settexthoffset
+ \hsize\dimexpr\scratchdimen-2\texthoffset\relax
+ \hskip\texthoffset % brrrr
+ \vbox to \zeropoint{\vss\page_info_place_info}%
+ \vskip\bodyfontsize}%
+ \dp\b_page_versions\zeropoint
+ \wd\b_page_versions\scratchdimen
+ \setbox#1\hbox{\box#1\hskip-\scratchdimen\box\b_page_versions}}
+
+\setupversion % resets
+ [\v!final]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-ini.mkii b/Master/texmf-dist/tex/context/base/page-ini.mkii
index 816b7d94497..bc4aab60f89 100644
--- a/Master/texmf-dist/tex/context/base/page-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/page-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initializations,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-ini.mkiv b/Master/texmf-dist/tex/context/base/page-ini.mkiv
index 7969e4f3e46..aad08ef3e61 100644
--- a/Master/texmf-dist/tex/context/base/page-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initializations,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,1505 +13,220 @@
\writestatus{loading}{ConTeXt Page Macros / Initializations}
-% still a dutch/english mess
+%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 This class of modules implements the output routines and
-%D floating body support. Although the modules are relatively
-%D new, the code herein is rather old. This reordering was
-%D needed when column sets were implemented and sharing code
-%D started to make sense.
-
-%D The history shows from the code, since both column
-%D mechanism use a different way of looping over columns.
+%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
-
-\def\m!otr{otr}
-
-% \setnewconstant\normalpagebox 255 % already set
-
-\newbox\pagebox
-
-\ifx\recalculatelayout\undefined
-
- \let \recalculatelayout \relax
-
-\fi
-
-\ifx\recalculatebackgrounds\undefined
-
- \let \recalculatebackgrounds \relax
- \let \addmainbackground \gobbleoneargument % <box>
- \let \addtextbackground \gobbleoneargument % <box>
- \let \addpagebackground \gobbleoneargument % <box>
- \let \addprintbackground \gobbleoneargument % <box>
- \let \addstatusinfo \gobbleoneargument % <box>
-
-\fi
-\ifx\realpageno\undefined
-
- \countdef\realpageno = 0 \realpageno = 1
- \countdef\userpageno = 1 \userpageno = 1
- \countdef\subpageno = 2 \subpageno = 0 % !!
- \countdef\arrangeno = 3 \arrangeno = 0 % !!
-
- \let\pageno\userpageno
-
-\fi
-
-\ifx\realfolio\undefined
-
- \def\realfolio{\the\realpageno}
-
-\fi
+%D Shipout control.
\newcount\nofshipouts
\appendtoks
- \global\advance\nofshipouts\plusone
+ \global\advance\nofshipouts\plusone
\to \everyaftershipout
-% principle:
-%
-% multiple otr's
-%
-% (1) single column, simple routine (old one)
-% (2) multi column, collect and split routine (old one)
-% (3) multi column, page by page (new one, needed for taco)
-% (4) single column, spread handling (for fun)
-% (5) multi column, page by page, spread handling (as challenge)
-%
-% common components
-%
-% (1) float placement
-% (2) float flushing
-% (3) page body building
-% (4) ...
-%
-% ort
-%
-% + balancing
-% - mixed / one / multi / balancetofit
-% + backgrounds
-% + pre / post
-% + distances / heights
-% + ragged / baseline / normal
-% - pos sync
-% - last page
-%
-% - itemize / subtexts -> old mechanism
-%
-% floats
-%
-% - top / bottom / side / page / column / spead
-% - flush / packed flush / current page / next page / area
-%
-% footnotes
-%
-% + carry over pre column / local to column
-% + last column / pre last column / each column
-% - multiple classes
-% - area / page / end
-%
-% areas
-%
-% - top / bottom / mid in spread
-%
-% IMPORTANT
-%
-% switchtobodyfont in between ivm top
-
-% floats:
-%
-% tricky in balancing mode, a la huidige multi columns
-
-\ifx\dosetuplayout\undefined % overloaded in page-lay !
-
- \unexpanded\def\setuplayout{\dodoubleempty\getparameters[\??ly]}
-
-\fi
-
-\ifx\mkprocesscolumncontents\undefined\let\mkprocesscolumncontents\gobbleoneargument\fi
-\ifx\mkprocesspagecontents \undefined\let\mkprocesspagecontents \gobbleoneargument\fi
-\ifx\mkprocessboxcontents \undefined\let\mkprocessboxcontents \gobbleoneargument\fi
-
-\def\normalejectpenalty{-\plustenthousand } \let\ejectpenalty\normalejectpenalty
-\def\normalsuperpenalty{-\plustwentythousand} \let\superpenalty\normalsuperpenalty
-
-%D In case we're not running \ETEX, we need to bypass a
-%D couple of primitives.
-
-% ONE = single column
-% MUL = multi column
-% SET = columns sets
-
-\def\@@OTR{OTR}
-
-\let\OTRdefault\empty
-
-% obsolete
-
-\def\installotr#1% andere naam, beter \connectotr of zo
- {\def\OTRidentifier{#1}}
-
-% \def\OTRcommand#1%
-% {\csname\@@OTR
-% \ifcsname\@@OTR\OTRidentifier\strippedcsname#1\endcsname
-% \OTRidentifier
-% \else\ifcsname\@@OTR\OTRdefault\strippedcsname#1\endcsname % fallback
-% \OTRdefault
-% \fi\fi
-% \strippedcsname#1\endcsname}
-%
-% maybe faster but at least less tracing:
-
-\def\OTRcommand#1%
- {\csname\@@OTR
- \ifcsname\@@OTR\OTRidentifier\expandafter\gobbleoneargument\string#1\endcsname
- \OTRidentifier
- \else\ifcsname\@@OTR\OTRdefault\expandafter\gobbleoneargument\string#1\endcsname % fallback
- \OTRdefault
- \fi\fi
- \expandafter\gobbleoneargument\string#1\endcsname}
-
-\def\activateotr#1#2%
- {\def\OTRidentifier{#1}%
- \def\OTRdefault {#2}}
-
-% variant that does a preset:
-
-\newtoks\registeredotrcommands
-
-\def\registerotrcommand#1%
- {\appendtoks\dowithotrcommand#1\to\registeredotrcommands}
-
-\def\dopresetotrcommand#1%
- {\expandafter\let\expandafter#1\csname\@@OTR
- \ifcsname\@@OTR\OTRidentifier\expandafter\gobbleoneargument\string#1\endcsname
- \OTRidentifier
- \else\ifcsname\@@OTR\OTRdefault\expandafter\gobbleoneargument\string#1\endcsname % fallback
- \OTRdefault
- \fi\fi
- \expandafter\gobbleoneargument\string#1\endcsname}
-
-\def\activateotr#1#2%
- {\def\OTRidentifier{#1}%
- \def\OTRdefault {#2}%
- \let\dowithotrcommand\dopresetotrcommand
- \the\registeredotrcommands}
-
-\appendtoks
- \activateotr{ONE}{}%
-\to\everydump
-
-%D The initialization of the \type {\hsize} and \type {\vsize}
-%D depends on the OTR used.
-
-% todo: \registerotrcommand\output, is a toks
+\newconditional\c_otr_shipout_enabled \settrue\c_otr_shipout_enabled
-\registerotrcommand\setvsize % \def\setvsize {\OTRcommand\setvsize}
-\registerotrcommand\sethsize % \def\sethsize {\OTRcommand\sethsize}
-\registerotrcommand\finalsidefloatoutput % \def\finalsidefloatoutput {\OTRcommand\finalsidefloatoutput}
-\registerotrcommand\dopagecontents % \def\dopagecontents {\OTRcommand\dopagecontents}
-\registerotrcommand\dosettopinserts % \def\dosettopinserts {\OTRcommand\dosettopinserts}
-\registerotrcommand\dosetbotinserts % \def\dosetbotinserts {\OTRcommand\dosetbotinserts}
-\registerotrcommand\dotopinsertions % \def\dotopinsertions {\OTRcommand\dotopinsertions}
-\registerotrcommand\dobotinsertions % \def\dobotinsertions {\OTRcommand\dobotinsertions}
-\registerotrcommand\dosetbothinserts % \def\dosetbothinserts {\OTRcommand\dosetbothinserts}
-\registerotrcommand\doflushfloats % \def\doflushfloats {\OTRcommand\doflushfloats}
-\registerotrcommand\flushfloatbox % \def\flushfloatbox {\OTRcommand\flushfloatbox}
-\registerotrcommand\docheckiffloatfits % \def\docheckiffloatfits {\OTRcommand\docheckiffloatfits}
-\registerotrcommand\flushsavedfloats % \def\flushsavedfloats {\OTRcommand\flushsavedfloats}
-\registerotrcommand\synchronizehsize % \def\synchronizehsize {\OTRcommand\synchronizehsize}
-\registerotrcommand\gotonextpage % \def\gotonextpage {\OTRcommand\gotonextpage }
-\registerotrcommand\gotonextpageX % \def\gotonextpageX {\OTRcommand\gotonextpageX} % will become obsolete
-
-% wrong, will be redone
-%
-% \registerotrcommand\someherefloat % \def\someherefloat {\OTRcommand\someherefloat}
-% \registerotrcommand\somefixdfloat % \def\somefixdfloat {\OTRcommand\somefixdfloat}
-% \registerotrcommand\somepagefloat % \def\somepagefloat {\OTRcommand\somepagefloat}
-% \registerotrcommand\sometopsfloat % \def\sometopsfloat {\OTRcommand\sometopsfloat}
-% \registerotrcommand\somebotsfloat % \def\somebotsfloat {\OTRcommand\somebotsfloat}
-% \registerotrcommand\somesidefloat % \def\somesidefloat {\OTRcommand\somesidefloat}
-
-% beter een \installotr#1 met #1 = macro en auto test
-
-\newif \iftraceotr
-\newif \ifinotr
-\newtoks \mainoutput
-\newcount\otrlevel
-
-% When issuing two \par\penalty-\plustenthousand's, only the first
-% triggers the otr; obscure feature or optimization?
-
-\newcount\outputcounter \outputcounter=-100010 % -10010
-
-\def\doinvokeoutput
- {\iftraceotr
- \expandafter\dodotracedoutput
- \else
- \expandafter\dodoinvokeoutput
- \fi}
-
-\def\doshowoutputmessage#1#2#3%
- {\writestatus\m!otr{#1 #2 \number#3}}
-
-\def\dodoinvokeoutput#1%
- {\bgroup\par\penalty#1\egroup}
-
-\def\dodotracedoutput#1%
- {\doshowoutputmessage+{traced}{#1/\the\outputpenalty}%
- \writestatus\m!otr{c:\number\mofcolumns,v:\the\vsize,g:\the\pagegoal,t:\the\pagetotal}%
- \dodoinvokeoutput{#1}%
- \writestatus\m!otr{c:\number\mofcolumns,v:\the\vsize,g:\the\pagegoal,t:\the\pagetotal}%
- \doshowoutputmessage-{traced}{#1/\the\outputpenalty}}
-
-\def\installoutput#1#2% \invoke \action
- {\global\advance\outputcounter\minusone
- \edef#1{\noexpand\doinvokeoutput{\number\outputcounter}}%
- \setvalue{\@@OTR\number\outputcounter}{#2}}
-
-\def\invoketracedoutputroutine
- {\doshowoutputmessage+{trying}\outputpenalty
- \ifcsname\@@OTR\the\outputpenalty\endcsname
- \doshowoutputmessage+{special}\outputpenalty
- \csname\@@OTR\the\outputpenalty\endcsname
- \doshowoutputmessage-{special}\outputpenalty
+\unexpanded\def\page_otr_shipout
+ {\ifconditional\c_otr_shipout_enabled
+ \expandafter\page_otr_shipout_yes
\else
- \doshowoutputmessage+{normal}\outputpenalty
- \the\OTRcommand\output
- \doshowoutputmessage-{normal}\outputpenalty
- \fi
- \doshowoutputmessage-{trying}\outputpenalty}
-
-\def\invokenormaloutputroutine
- {\ifcsname\@@OTR\the\outputpenalty\endcsname
- \csname\@@OTR\the\outputpenalty\endcsname
- \else
- \the\OTRcommand\output
+ \expandafter\page_otr_shipout_nop
\fi}
-\def\invokeoutputroutine
- {\iftraceotr
- \expandafter\invoketracedoutputroutine
- \else
- \expandafter\invokenormaloutputroutine
- \fi}
+\let\page_otr_shipout_yes\normalshipout
-\mainoutput{\invokeoutputroutine}
-
-%D Some hooks:
-
-\def\setoutputroutine#1%
- {\global\output{\inotrtrue\the\everybeforeoutput#1\the\everyafteroutput}}
-
-\setoutputroutine{\the\mainoutput}
-
-\ifx\pagediscards\undefined \let\pagediscards\relax \fi
-
-\installoutput\synchronizeoutput % maybe add pagediscards
- {\ifvoid\normalpagebox\else
- \unvbox\normalpagebox
- \pagediscards % maybe not needed ?
- \fi}
-
-\installoutput\discardpage
- {\setbox\scratchbox\box\normalpagebox}
-
-%D In order to force consistent use of variables, we
-%D predefine a lot of them here.
-
-%D The next two registers can be used to store pre column
-%D material as well as footnotes or so.
-
-\newbox\precolumnbox \newdimen\precolumnboxheight
-\newbox\postcolumnbox \newdimen\postcolumnboxheight
-
-%D We reserve a counter for the number of columns as well as
-%D the current column. Both are not to be changed by users!
-
-\newcount\nofcolumns \nofcolumns = 1
-\newcount\mofcolumns \mofcolumns = 1
-
-\setnewconstant\maxnofcolumns 50
-\setnewconstant\allocatednofcolumns 0
-
-%D The next dimensions reports the final column height
-
-\newdimen\finalcolumnheights
-\newcount\finalcolumnlines
-
-%D During initialization the temporary boxes are allocated.
-%D This enables us to use as much columns as we want, without
-%D exhausting the pool of boxes too fast. We could have packed
-%D them in one box, but we've got enough boxes.
-%D
-%D Two sets of boxes are declared, the txtboxes are used for
-%D the text, the topboxes are for moved column floats.
-
-\def\@col@{@col@}
-
-\def\initializecolumns#1%
- {\ifnum#1>\maxnofcolumns
- \showmessage\m!columns1\maxnofcolumns
- \nofcolumns\maxnofcolumns
- \else
- \nofcolumns#1\relax
- \fi
- \ifnum\nofcolumns>\allocatednofcolumns
- \dorecurse\nofcolumns
- {\ifnum\recurselevel>\allocatednofcolumns\relax
- % \newbox\next \letgvalue{\@col@-\recurselevel-t}=\next
- \@EA\newbox\csname\@col@-\recurselevel-t\endcsname % text
- \@EA\newbox\csname\@col@-\recurselevel-f\endcsname % foot
- \@EA\newbox\csname\@col@-\recurselevel-h\endcsname % top insert
- \@EA\newbox\csname\@col@-\recurselevel-l\endcsname % top insert
- \fi}%
- \global\allocatednofcolumns\nofcolumns
- \fi}
-
-\def\firstcolumnbox {\columntextbox\plusone}
-\def\currentcolumnbox {\columntextbox\mofcolumns}
-\def\lastcolumnbox {\columntextbox\nofcolumns}
-
-\def\firsttopcolumnbox {\columntopbox \plusone}
-\def\currenttopcolumnbox{\columntopbox \mofcolumns}
-\def\lasttopcolumnbox {\columntopbox \nofcolumns}
-
-\def\columntextbox#1{\csname\@col@-\number#1-t\endcsname}
-\def\columnfootbox#1{\csname\@col@-\number#1-f\endcsname}
-\def\columntopbox #1{\csname\@col@-\number#1-h\endcsname}
-\def\columnbotbox #1{\csname\@col@-\number#1-l\endcsname}
-
-\def\columnsettextbox{\global\setbox\columntextbox}
-\def\columnsetfootbox{\global\setbox\columnfootbox}
-\def\columnsettopbox {\global\setbox\columntopbox}
-\def\columnsetbotbox {\global\setbox\columnbotbox}
-
-\def\columngettextbox{\copy\columntextbox}
-\def\columngetfootbox{\copy\columnfootbox}
-\def\columngettopbox {\copy\columntopbox}
-\def\columngetbotbox {\copy\columnbotbox}
-
-\def\columnerasetextboxes{\dorecurse\allocatednofcolumns{\columnsettextbox\recurselevel\emptybox}}
-\def\columnerasefootboxes{\dorecurse\allocatednofcolumns{\columnsetfootbox\recurselevel\emptybox}}
-\def\columnerasetopboxes {\dorecurse\allocatednofcolumns{\columnsettopbox \recurselevel\emptybox}}
-\def\columnerasebotboxes {\dorecurse\allocatednofcolumns{\columnsetbotbox \recurselevel\emptybox}}
-
-%D Without going in details we present two macro's which handle
-%D the columns. The action which is transfered by the the first
-%D and only parameter can do something with \type
-%D {\currentcolumnbox}. In case of the mid columns, \type
-%D {\firstcolumnbox} and \type {\lastcolumnbox} are handled
-%D outside these macro's.
-
-\def\dohandlecolumn#1%
- {\mofcolumns\recurselevel
- \let\currentcolumn\recurselevel
- #1\relax}
-
-\def\dohandleallcolumns#1%
- {\dorecurse\nofcolumns{\dohandlecolumn{#1}}}
-
-\def\dohandlerevcolumns#1%
- {\dostepwiserecurse\nofcolumns\plusone\minusone{\dohandlecolumn{#1}}}
-
-\def\dohandlemidcolumns#1%
- {\dohandleallcolumns
- {\ifnum\recurselevel>\plusone
- \ifnum\recurselevel<\nofcolumns
- \dohandlecolumn{#1}%
- \fi
- \fi}}
-
-%D This register can be used as a temporary storage for page
-%D content.
-
-\newbox\restofpage
-
-%D Features.
-
-\newif\ifintermediatefootnotes
-\newif\ifcarryoverfootnotes %\carryoverfootnotestrue
-\newif\iflastcolumnfootnotes %\lastcolumnfootnotestrue
-\newif\ifbalancecolumns %\balancecolumnstrue
-\newif\ifbalancetoheight %\balancetoheighttrue
-\newif\ifforcecolumngrid \forcecolumngridtrue
-\newif\ifstretchcolumns \stretchcolumnsfalse
-\newif\ifinheritcolumns \inheritcolumnsfalse
-\newif\ifheightencolumns \heightencolumnsfalse
-
-\newif\ifbalancingcolumns
-\newif\ifcollectingcontent
-\newif\ifcolumnoverflow
-
-\newdimen\intercolumnwidth
-\newdimen\localcolumnwidth
-\newdimen\savedpagetotal
-
-\newconstant\columndirection % 0:lr 1:rl
-
-\def\minbalancetoplines {1}
-\def\minfreecolumnlines {2}
-
-\newif\ifrecentercolumnbox \recentercolumnboxtrue
-\newif\ifrerecentercolumnbox \rerecentercolumnboxtrue
-\newif\ifpackcolumnfloats \packcolumnfloatstrue
-
-\newbox\collectedpagefloats
-\newbox\collectedleftpagefloats
-\newbox\collectedrightpagefloats
-
-%D The \type {\ifdim} test is needed, because otherwise the
-%D last line of a text end up on top of the baseline instead of
-%D on the baseline, as is the case with preceding pages.
-%D Also, a \type {\vfil} better than a \type {\vfill}.
-
-% to be replaced by \page[now] \page[final] / merged
+\unexpanded\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}}
-% \def\eject {\par\penalty-\plustenthousand } % == {\par\break} % plain
-% \def\supereject {\par\penalty-\plustwentythousand} % also plain
+% We don't support direct user \shipouts (weird: this does not work, bug?)
+%
+% \let\shipout\page_otr_shipout_nop
-\def\eject {\par\ifvmode\penalty\ejectpenalty\fi\resetpagebreak} % == {\par\break} % plain
-\def\supereject {\par\ifvmode\penalty\superpenalty\fi\resetpagebreak} % also plain
+%D Building pages.
-\def\doejectpage {\par\ifvmode\ifdim\pagetotal>\pagegoal\else\normalvfil\fi\fi} % pg set to \textheight
-\def\ejectpage {\doejectpage\eject}
-\def\superejectpage{\doejectpage\supereject}
+\newbox\pagebox
-\ifx\bye\undefined \def\bye{\par\vfill\supereject\end} \fi % plain tex command
+\ifx\mkprocesscolumncontents\undefined\let\mkprocesscolumncontents\gobbleoneargument\fi
+\ifx\mkprocesspagecontents \undefined\let\mkprocesspagecontents \gobbleoneargument\fi
+\ifx\mkprocessboxcontents \undefined\let\mkprocessboxcontents \gobbleoneargument\fi
-% floats
+%D Floats.
-\def\ejectinsert
+\def\page_otr_flush_all_floats
{%\flushnotes already done
- \bgroup
- \noftopfloats\plusthousand
- \nofbotfloats\zerocount
- % this is needed in case a float that has been stored
- % ends up at the current page; this border case occurs when
- % the calculated room is 'eps' smaller that the room available
- % when just flushing; so now we have (maybe optional):
- \pagebaselinecorrection
- % alas, this is tricky but needed (first surfaced in prikkels)
- \doflushfloats
- \egroup}
+ \ifsomefloatwaiting
+ \begingroup
+ \noftopfloats\plusthousand
+ \nofbotfloats\zerocount
+ % this is needed in case a float that has been stored
+ % ends up at the current page; this border case occurs when
+ % the calculated room is 'eps' smaller that the room available
+ % when just flushing; so now we have (maybe optional):
+ \pagebaselinecorrection % hm, needs checking, not needed when no floats
+ % alas, this is tricky but needed (first surfaced in prikkels)
+ \page_otr_command_flush_floats
+ \endgroup
+ \fi}
-\def\ejectdummypage
- {\endgraf \ifvmode
- \ejectinsert
+\def\page_otr_insert_dummy_page
+ {\par
+ \ifvmode
+ \page_otr_flush_all_floats
\fixedspace
\vfill
- \gotonextpage
+ \page_otr_command_next_page
\fi}
-\def\beforefinaloutput
- {}
-
-\def\afterfinaloutput
- {%\forgetall
- \vskip\zeropoint\relax
+\def\page_otr_flush_pending_content
+ {\vskip\zeropoint\relax % brrr .. get rid of this
\ifvoid\normalpagebox \else
\unvbox\normalpagebox
\penalty\outputpenalty
- \fi
- % not really needed, replaced by \flushsavedfloats
- \ifnum\outputpenalty>\superpenalty \else % better use a proper otr signal
- \dosupereject
- \fi
- % but does not hurt either (we're still in the otr!)
- \inpagebodytrue % needed for enabling \blank !
- \flushsavedfloats % was \dosetbothinserts; only otr one !
- \setvsize} % this is needed for interacting components, like floats and multicolumns
-
-\def\dofinaloutput#1#2% \vbox: prevents spurious spaces in every..pagebody
- {\forgetall
- \beforefinaloutput
- \the\everybeforeshipout % brrr not in shipout
- \the\pageboundsettings
- \myshipout{\hbox{\vbox{\dopagebody#1#2}}}% is this hbox needed
- \the\everyaftershipout
- \afterfinaloutput}
+ \fi}
-\def\donofinaloutput#1#2%
+\def\page_otr_construct_and_shipout#1#2%
{\forgetall
- \beforefinaloutput
- \the\everybeforeshipout
- \message{[-\the\realpageno]}%
- \setbox\scratchbox\hbox{\dopagebody#1#2}%
- \deadcycles\zerocount
- \setnextrealpageno
- \the\everyaftershipout
- \afterfinaloutput}
-
-% beware: \ifprocessingpages is in use
-
-\ifdefined\doflushspread\else \let\doflushspread\relax \fi % todo
-
-\def\finaloutput#1#2%
- {\ifprocessingpages
- \ifpageselected
- \@EAEAEA\dofinaloutput
- \else
- \@EAEAEA\donofinaloutput
- \fi
- \else
- \ifpageselected
- \@EAEAEA\donofinaloutput
- \else
- \@EAEAEA\dofinaloutput
- \fi
- \fi#1#2%
- \resetselectiepagina
+ \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
+ \page_otr_command_flush_saved_floats
+ \page_otr_command_set_vsize % this is needed for interacting components, like floats and multicolumns
\doincrementpageboundcounters % should hook into an every
- \checkpagedimensions
- \ifnum\outputpenalty>\superpenalty \else
- \dosupereject
- \fi
+ \page_adapts_synchronize
+ \page_otr_check_for_pending_inserts
\doflushspread
- \doflushpostponedcontent}
-
-\def\dooutput
- {\finaloutput\unvbox\normalpagebox}
+ \page_postponed_blocks_flush}
-\maxdeadcycles=1000
+% Can't we get rid of this hackery? It's used in some widgets
+% stuff so probably not.
-% this needs a real cleanup
+\newbox\b_page_otr_special
-\def\doplaceversiontext#1#2%
- {\doifsomething{#2}
- {\defconvertedcommand\ascii{#2}%
- \space#1:\space\ascii\space
- \!!doneatrue}}
-
-\unexpanded\def\placeversioninfo % nog engels maken
- {\ifcase\conceptmode
- % 0 : nothing
- \or
- % 1 : simple
- \vskip\!!sixpoint
- \hbox to \makeupwidth
- {\infofont
- \v!concept:\space\currentdate
- \hss\reportpagedimensions}%
- \else
- % 2/3 : extensive
- \vskip\!!sixpoint
- \hbox to \makeupwidth
- {\infofont
- \getmessage\m!system{27}:\space\currentdate\space
- \doplaceversiontext\v!project \currentproject
- \doplaceversiontext\v!product \currentproduct
- \doplaceversiontext\v!component\currentcomponent
- \if!!donea\else\space\v!file:\space\jobname\fi
- \hss\reportpagedimensions}%
+\def\page_otr_flush_special_content
+ {\ifvoid\b_page_otr_special \else
+ \box\b_page_otr_special
\fi}
-% tot hier
+\def\page_otr_add_special_content
+ {\dowithnextboxcs\page_otr_add_special_content_indeed\hbox}
-\def\doversion[#1]%
- {\conceptmode\zerocount
- \overfullrule\zeropoint
- \processaction % \v!final=>
- [#1]
- [ \v!concept=>\conceptmode\plusone, % simple banner
- \v!file=>\conceptmode\plustwo, % full banner
- \v!temporary=>\conceptmode\plusthree % full banner plus
- \overfullrule5\points]} % info in the margin
-
-\def\version
- {\dosingleargument\doversion}
-
-\def\addstatusinfo
- {\ifcase\conceptmode
- \@EA\gobbleoneargument
- \else
- \@EA\doaddstatusinfo
- \fi}
+\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
-\def\doaddstatusinfo#1%
- {\setbox#1\vbox to \paperheight
- {\vsmashbox#1\box#1%
- \offinterlineskip
- \vskip\topspace
- \hsize\paperwidth
- %\hfill\hbox{\placetestinfo\hskip.5cm}\vss % obsolete
- \settexthoffset\hskip\texthoffset % brrrr
- \vbox to 1cm{\vss\placeversioninfo\vss}}}
+\let\flushatshipout\page_otr_add_special_content
-\def\dotestinfo#1#2#3%
- {\ifinpagebody\else\ifnum\conceptmode=\plusthree
- \begingroup
- \defconvertedcommand\ascii{#3}%
- \xdef\extratestinfo
- {#2\space\ascii}%
- \gdef\totaltestinfo
- {\global\setbox#1\vbox
- {\unvbox#1\relax
- \infofont \setupinterlinespace
- \hbox
- {\strut
- \expanded{\doboundtext{\extratestinfo}{12em}{..}}%
- \quad}}}%
- \endgroup
- \ifinner
- \aftergroup\totaltestinfo
- \else
- \totaltestinfo
- \fi
- \fi\fi}
-
-\version[\v!final]
-
-% bewaren tvb documentatie
-%
-% \hbox to \hsize
-% {\en
-% \switchnaarkorps[5pt]%
-% \emergencystretch2em
-% \dimen0=\baselineskip
-% \baselineskip=\dimen0 plus 1pt
-% \hsize=.2\hsize
-% \vsize=2\hsize
-% \ruledvbox to \vsize{\input tufte \par}\hss
-% \ruledvbox to \vsize{\input tufte \par\kern-\prevdepth}\hss
-% \ruledvbox to \vsize{\input tufte \par\kern0pt}\hss
-% \ruledvbox to \vsize{\input tufte \par\vfill}\hss
-% \ruledvbox to \vsize{\input tufte \par\kern-\prevdepth\vfill}}
-%
-% \hbox to \hsize
-% {\en
-% \switchnaarkorps[5pt]%
-% \emergencystretch2em
-% \dimen0=\baselineskip
-% \baselineskip=\dimen0 plus 1pt
-% \hsize=.18\hsize
-% \vsize=2.5\hsize
-% \setbox0=\vbox{\input tufte\relax}%
-% \ruledvbox to \vsize{\unvcopy0}\hss
-% \ruledvbox to \vsize{\unvcopy0\kern-\dp0}\hss
-% \ruledvbox to \vsize{\unvcopy0\kern0pt}\hss
-% \ruledvbox to \vsize{\unvcopy0\vfill}\hss
-% \ruledvbox to \vsize{\unvcopy0\kern-\dp0\vfill}}
+\maxdeadcycles=1000
\newtoks\afterpage \newtoks\aftereverypage
\newtoks\beforepage \newtoks\beforeeverypage
-\newconstant\showgridstate
-
-\unexpanded\def\showgrid
- {\dosingleempty\doshowgrid}
-
-\def\doshowgrid[#1]%
- {\showgridstate \plusone % downward compatible default
- \gridboxlinemode \plusone
- \gridboxlinenomode\plusone
- \processallactionsinset
- [#1]%
- [ \v!reset=>\showgridstate \zerocount,
- \v!bottom=>\showgridstate \plusone,
- \v!top=>\showgridstate \plustwo,
- \v!none=>\gridboxlinemode \zerocount,
- \v!all=>\gridboxlinemode \plusone,
- \v!lines=>\gridboxlinemode \plustwo,
- \v!frame=>\gridboxlinemode \plusthree,
- \v!nonumber=>\gridboxlinenomode\zerocount,
- \v!right=>\gridboxlinenomode\plusone,
- \v!left=>\gridboxlinenomode\plustwo,
- \v!outer=>\gridboxlinenomode\plusthree]%
- \ifcase\showgridstate
- \let\addtextgridlayer\gobbleoneargument
- \else % 1=bottom 2=top
- \let\addtextgridlayer\doaddtextgridlayer
- \fi}
-
-\definepalet
- [layout]
- [grid=red,
- page=green]
-
-% if really needed for speed we can cache the grid
-
-\let\addtextgridlayer\gobbleoneargument
-
-\def\doaddtextgridlayer#1% to be checked for color and layer
- {\startcolor[layout:grid]%
- \setgridbox\scratchbox\makeupwidth\textheight % todo: check color
- \global\setbox#1\hbox
- {\ifcase\showgridstate\or\or\box#1\hskip-\makeupwidth\fi
- \bgroup % color
- \ifcase\layoutcolumns\else
- \gray
- \setlayoutcomponentattribute\v!grid\v!columns
- \hbox \layoutcomponentboxattribute to \makeupwidth
- {\dorecurse\layoutcolumns
- {\hskip\layoutcolumnwidth
- \ifnum\recurselevel<\layoutcolumns
- \vrule
- \!!height\ht\scratchbox
- \!!depth\dp\scratchbox
- \!!width\layoutcolumndistance
- \fi}}%
- \hskip-\makeupwidth
- \fi
- \setlayoutcomponentattribute\v!grid\v!lines
- \hbox \layoutcomponentboxattribute{\box\scratchbox}%
- \egroup
- \ifcase\showgridstate\or\hskip-\makeupwidth\box#1\fi}%
- \stopcolor}
-
-\def\buildpagebox#1%
- {\setbox#1\vbox to \paperheight
- {\hsize\paperwidth
- \vskip\topspace
- \doifbothsides
- {\hskip\backspace}
- {\hskip\backspace}
- {\hskip\paperwidth \hskip-\backspace \hskip-\makeupwidth}%
- \box#1}%
- \dp#1\zeropoint}
-
-% \newif\ifpagebodyornaments \pagebodyornamentstrue
-%
-% \appendtoks
-% \global\pagebodyornamentstrue
-% \to \everyaftershipout
-
-\newif\ifarrangingpages \arrangingpagesfalse
+\newif\ifarrangingpages \arrangingpagesfalse
\newconstant\pageornamentstate % 0=on 1=one-off 2=always-off
-\def\pagebodyornamentstrue {\pageornamentstate\zerocount} % for a while
-\def\pagebodyornamentsfalse{\pageornamentstate\plusone} % for a while
-
\appendtoks
- \ifcase\pageornamentstate\or
- \pageornamentstate\zerocount
- \fi
+ \ifcase\pageornamentstate \or
+ \pageornamentstate\zerocount
+ \fi
\to \everyaftershipout
-\let\poparrangedpages\relax
-\let\pusharrangedpage\relax
-
-\ifdefined\shiftprintpagebox \else
- \let\shiftprintpagebox\gobbleoneargument
- \let\shiftpaperpagebox\gobbleoneargument
-\fi
-
-\ifdefined\registerpageposition \else
- \let\registerpageposition\gobbleoneargument
-\fi
+% Mark synchronization
-\newif\ifsavepagebody \newbox\savedpagebody
+\newconditional\c_page_marks_building_successive_pages \settrue\c_page_marks_building_successive_pages
-% beware, \??ly is used before defined, i.e. bad module design
+\def\page_marks_synchronize_page#1% box
+ {\strc_markings_synchronize[\v!page][#1][\ifconditional\c_page_marks_building_successive_pages\v!keep\fi]}
-\setuplayout[\c!method=\v!normal]
-
-\def\docolumnpagebodymarks#1#2#3#4% first last column box
+\def\page_marks_synchronize_column#1#2#3#4% first last column box
{\ifnum#3=#1\relax
- \dosynchronizemarking[\number#3,\v!column:\number#3,\v!first,\v!column:\v!first][#4]%
+ \strc_markings_synchronize[\number#3,\v!column:\number#3,\v!first,\v!column:\v!first][#4][]%
\else\ifnum#3=#2\relax
- \dosynchronizemarking[\number#3,\v!column:\number#3,\v!last, \v!column:\v!last ][#4]%
+ \strc_markings_synchronize[\number#3,\v!column:\number#3,\v!last, \v!column:\v!last ][#4][]%
\else
- \dosynchronizemarking[\number#3,\v!column:\number#3 ][#4]%
+ \strc_markings_synchronize[\number#3,\v!column:\number#3 ][#4][]%
\fi\fi}
-\def\buildpagebody#1#2%
- {\ifsavepagebody\global\setbox\savedpagebody\fi
- \vbox
- {%\pushcatcodetable
- %\forgetall % igv problemen, check: \boxmaxdepth\maxdimen
+% 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 \vbox \bgroup
\boxmaxdepth\maxdimen % new
\dontcomplain
- % marks get done here
- \dosynchronizemarking[\v!page][#2]%
- % the following plugin uses and sets pagebox; beware: this
- % will change and is for my (hh) personal experiments
- \executeifdefined{\??ly\c!method\@@lymethod}{\getvalue{\??ly\c!method\v!normal}}#1#2%
- % the finishing touch
+ \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
- \addpagebackground \pagebox
+ \page_backgrounds_add_to_paper \pagebox
\fi
- \registerpageposition\pagebox
+ \anch_positions_register_page \pagebox
\ifarrangingpages
- \shiftpaperpagebox \pagebox % \v!paper
+ \page_boxes_apply_shift_paper \pagebox % \v!paper
\else
- \clippagebox \pagebox
- \doifelse\@@lymarking\v!page
- {\replicatepagebox \pagebox
- \addpagecutmarks \pagebox}
- {\addpagecutmarks \pagebox
- \replicatepagebox \pagebox}%
- \scalepagebox \pagebox
- \mirrorpaperbox \pagebox
- \orientpaperbox \pagebox
- \addpagecolormarks \pagebox
- \centerpagebox \pagebox
- \addprintbackground\pagebox
- \mirrorprintbox \pagebox
- \orientprintbox \pagebox
- \shiftprintpagebox \pagebox % \v!page
- \offsetprintbox \pagebox
- \negateprintbox \pagebox
+ \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
- }% \popcatcodetable
- \ifsavepagebody\copy\savedpagebody\fi}
-
-\setvalue{\??ly\c!method\v!normal}#1#2%
- {\setbox\pagebox\vbox
- {\offinterlineskip
- \ifcase\pageornamentstate
- \bgroup % else footnotes get inconsistent font/baseline
- \dostartattributes\??ly\c!style\c!color\empty
- \offinterlineskip
- \gettextboxes
- \dostopattributes
- \egroup
- \fi
- \getmainbox#1#2}% including footnotes
- \ifcase\pageornamentstate
- \addmainbackground \pagebox
- \fi
- \buildpagebox \pagebox
- \addstatusinfo \pagebox}
+ \egroup \ifconditional\c_page_boxes_save_page_body \copy\b_page_boxes_saved_page_body \fi}
-\def\finishpagebox#1%
- {\ifarrangingpages
- \addpagecutmarks #1%
- \addpagecolormarks#1%
- \centerpagebox #1%
- \mirrorprintbox #1%
- \orientprintbox #1%
- \offsetprintbox #1%
- \negateprintbox #1%
- \fi}
-
-\appendtoks \restoreouterspacing \to \everybeforepagebody
\appendtoks \restoreglobalbodyfont \to \everybeforepagebody
-%appendtoks \restoreouterspacing \to \everybeforepagebody
-
-\ifx\nestednewbox\undefined \newbox\nestednextbox \fi
-
-\prependtoks \let\nextbox\nestednextbox \to \everybeforepagebody
-
-\def\dopagebody#1#2%
- {\the\everybeforepagebody
- \starttextproperties
-% \setnextsubpageno % nog eens: als in pagina (tbv standaard opmaak)
- \dontshowboxes % dan hier blokkeren en verderop resetten
-% \shipoutfacingpage
- \checkmarginblocks
- \the\beforeeverypage
- \normalexpanded{\global\beforepage\emptytoks\the\beforepage}% \scratchtoks\beforepage\global\beforepage\emptytoks\the\scratchtoks % was \flushtoks\beforepage
- \inpagebodytrue\buildpagebody#1#2%
- \normalexpanded{\global\afterpage \emptytoks\the\afterpage }% \scratchtoks\afterpage \global\afterpage \emptytoks\the\scratchtoks % was \flushtoks\afterpage
- \the\aftereverypage
- \resetpagebreak
- %updatelistreferences % now in aftereverypage
- \resetlayouttextlines % will go to \aftereverypage
- \stoptextproperties
- \the\everyafterpagebody}
-
-\newtoks\pageboundsettings
-
-% \prependtoks \initializepaper \to \pageboundsettings
-
-% not here
-
-\newif\ifpagebreakdisabled \pagebreakdisabledfalse
-
-\newconstant\testpagemethod % todo: \testnewpage[method=,lines=,voffset=]
-\newconstant\testpagetrigger
-
-\def\testpage {\dotripleempty\dotestpage[\plusone ]} %
-\def\testpageonly{\dotripleempty\dotestpage[\plustwo ]} % no penalties added to the mvl
-\def\testpagesync{\dotripleempty\dotestpage[\plusthree]} % force sync
-
-\def\dotestpage[#1][#2][#3]% don't change, only add more methods
- {\relax % needed before \if
- \ifpagebreakdisabled
- \endgraf
- \else
- % new from here
- \ifcase\testpagetrigger
- \endgraf
- \or
- \ifvmode
- \dosomebreak\allowbreak
- \else % indeed?
- \vadjust{\allowbreak}%
- \endgraf
- \fi
- \fi
- % till here
- \ifdim\pagegoal<\maxdimen \relax
- \ifdim\pagetotal<\pagegoal \relax
- \scratchdimen\lineheight
- \multiply\scratchdimen#2\relax
- \advance\scratchdimen \pagetotal
- \ifdim\lastskip<\parskip
- \advance\scratchdimen \parskip
- \fi
- \ifthirdargument
- \advance\scratchdimen#3\relax
- \fi
- \ifcase\testpagemethod
- \ifdim\scratchdimen>.99\pagegoal
- \penalty-\!!tenthousand\relax
- \fi
- \or
- \advance\scratchdimen-\pagegoal
- \ifdim\scratchdimen>-\lineheight
- \penalty-\!!tenthousand\relax
- \fi
- \or
- \getnoflines\pagegoal
- \advance\scratchdimen-\noflines\lineheight \relax
- \ifdim\scratchdimen>-\lineheight
- \penalty-\!!tenthousand\relax
- \fi
- \or % same as 0 but more accurate
- \advance\scratchdimen-10\s!sp\relax
- \ifdim\scratchdimen>\pagegoal
- \penalty-\!!tenthousand\relax
- \fi
- \fi
- \else
- \ifnum#1=\plusthree
- \flushpagesofar
- \fi
- \fi
- \else
- \ifnum#1=\plusone\goodbreak\fi
- \fi
- \fi}
-
-\def\flushpagesofar
- {\endgraf
- \ifdim\pagetotal>\pagegoal
- \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal
- \goodbreak % \penalty0
- \else
- \page
- \fi
- \else
- \fi}
-
-\def\testcolumn
- {\dodoubleempty\dotestcolumn}
-
-\def\dotestcolumn[#1][#2]%
- {%\relax % needed before \if !
- \endgraf
- \ifdim\pagegoal<\maxdimen \ifdim\pagetotal<\pagegoal % \relax
- \scratchdimen\pagegoal
- \advance\scratchdimen-\pagetotal
- \ifdim\lastskip<\parskip
- \advance\scratchdimen \parskip
- \fi
- \ifsecondargument
- \advance\scratchdimen#2%
- \fi
- \getrawnoflines\scratchdimen % raw !
- % \message{[\number#1>\number\noflines ?}\wait
- \ifnum#1>\noflines
- \column
- \fi
- \else
- \penalty-\!!tenthousand % untested ! ! \column
- \fi \fi}
-
-\ifdefined\resetcurrentstructuremarkswithpage \else
- \let\resetcurrentstructuremarkswithpage\relax
-\fi
-
-\def\page{\pagebreak} % the short form of \pagebreak (mult-com one)
-
-\def\resetpagebreak
- {\global\pagebreakdisabledfalse}
-
-\def\simplifypagebreak
- {\def\dopagebreak[##1]{\goodbreak}}
-
-\def\disablepagebreaks
- {\def\dopagebreak[##1]{}}
-
-\def\executepagebreakhandler#1%
- {\edef\@@pagespecification{#1}%
- \ifcsname\??pe:\@@pagespecification\endcsname
- \csname\??pe:\@@pagespecification\endcsname
- \else\ifcsname\??pe::\@@pagespecification\endcsname
- \executepagebreakhandlers{\csname\??pe::\@@pagespecification\endcsname}%
- \else
- \csname\??pe:\s!unknown\endcsname
- \fi\fi}
-
-\long\def\installpagebreakhandler#1#2%
- {\long\setvalue{\??pe:#1}{#2}}
-
-\unexpanded\def\pagebreak
- {\dosingleempty\dopagebreak}
-
-\def\dopagebreak[#1]% so, page ornaments are reset after a pagebreak command, unless set
- {\bgroup
- \flushnotes
- \edef\prevrealpageno{\the\realpageno}%
- \ifcase\pageornamentstate \or
- % disable reset after shipout
- \global\pageornamentstate\plustwo
- \fi
- \iffirstargument % or if empty i.e. []
- \executepagebreakhandlers{#1}%
- \else % so, no pagebreak when \pagebreak[] ! ! !
- \executepagebreakhandler\v!yes
- \fi
- \ifnum\prevrealpageno<\realpageno
- % there must have been a reason why i added the ifcase
- % but it fails on tests/mkiv/pages/ornaments-001.tex
- % as WS found out so we have to wait till the next side
- % effect shows up
- % \ifcase\pageornamentstate\or
- \global\pageornamentstate\zerocount
- % \fi
- \fi
- \egroup}
-
-\def\executepagebreakhandlers#1%
- {\processcommacommand[#1]\executepagebreakhandler}
-
-\installpagebreakhandler \s!dummy
- {\ejectinsert
- \gotonextpage
- \ejectdummypage}
-
-\installpagebreakhandler \v!frame
- {\page\bgroup\showframe\page[\v!empty]\egroup}
-
-\installpagebreakhandler \s!unknown
- {\doifinstringelse{+}\@@pagespecification
- {\ejectinsert
- \gotonextpage
- \dorecurse\@@pagespecification\ejectdummypage}
- {\doifnumberelse\@@pagespecification
- {\ejectinsert
- \gotonextpage
- \doloop
- {\ifnum\userpageno<\@@pagespecification\relax
- \ejectdummypage
- \else
- \exitloop
- \fi}}
- {}}}
-
-\installpagebreakhandler \s!default
- {} % do nothing if empty
-
-\installpagebreakhandler \v!reset
- {% better not: \global\pageornamentstate\zerocount
- \resetpagebreak}
-
-\installpagebreakhandler \v!disable
- {\global\pagebreakdisabledtrue}
-
-\installpagebreakhandler \v!yes
- {\ifpagebreakdisabled\else
- \ejectinsert
- \gotonextpage
- \ifinsidecolumns % this will move to MUL
- \ejectpage % anders soms geen overgang
- \fi
- \fi}
-
-\installpagebreakhandler \v!makeup % ??
- {\ifpagebreakdisabled\else
- \eject
- \fi}
-
-\installpagebreakhandler \v!blank
- {\ifcase\pageornamentstate
- \global\pageornamentstate\plusone
- \fi}
-
-\installpagebreakhandler \v!no
- {\ifpagebreakdisabled\else
- \dosomebreak\nobreak
- \fi}
-
-\installpagebreakhandler \v!preference
- {\ifpagebreakdisabled\else
- \ifinsidecolumns % this will move to MUL
- \dosomebreak\goodbreak
- \else
- \testpage[3][\zeropoint]%
- \fi
- \fi}
-
-\installpagebreakhandler \v!bigpreference
- {\ifpagebreakdisabled\else
- \ifinsidecolumns % this will move to MUL
- \dosomebreak\goodbreak
- \else
- \testpage[5][\zeropoint]%
- \fi
- \fi}
-
-\installpagebreakhandler \v!empty
- {\ejectinsert
- \gotonextpage
- \doifnotvalue{\??tk\v!header\c!state}\v!stop{\setupheader[\c!state=\v!empty]}%
- \doifnotvalue{\??tk\v!footer\c!state}\v!stop{\setupfooter[\c!state=\v!empty]}%
- \ejectdummypage}
-
-\installpagebreakhandler \v!left
- {\ejectinsert
- \gotonextpageX % will become \gotonextpage
- \doifbothsidesoverruled{}{\resetcurrentstructuremarkswithpage\ejectdummypage}{}}
-
-\installpagebreakhandler \v!right
- {\ejectinsert
- \gotonextpageX % will become \gotonextpage
- \doifbothsidesoverruled{}{}{\resetcurrentstructuremarkswithpage\ejectdummypage}}
-
-\installpagebreakhandler \v!even
- {\page
- \doifoddpageelse{\resetcurrentstructuremarkswithpage\ejectdummypage}\donothing}
-
-\installpagebreakhandler \v!odd
- {\page
- \doifoddpageelse\donothing{\resetcurrentstructuremarkswithpage\ejectdummypage}}
-
-\installpagebreakhandler \v!quadruple % not yet ok inside columnsets
- {\ifdoublesided
- \!!counta\realpageno
- \!!countb\realpageno
- \divide\!!counta 4
- \divide\!!countb 2
- \ifnum\!!counta=\!!countb
- \else
- \executepagebreakhandler\v!yes
- \executepagebreakhandler\v!empty
- \executepagebreakhandler\v!empty
- \fi
- \fi}
-
-\installpagebreakhandler \v!last
- {\ejectinsert
- \gotonextpageX % will become \gotonextpage
- \relax
- \doifbothsidesoverruled
- {\shipoutfacingpage}
- {}
- {\noheaderandfooterlines \ejectdummypage}%
- \filluparrangedpages}
-
-\installpagebreakhandler \v!lastpage % handy for backpage preceded by empty pages
- {\executepagebreakhandler\v!yes
- \ifdoublesided
- \executepagebreakhandler\v!left
- \executepagebreakhandler\v!empty
- \executepagebreakhandler\v!empty
- \fi}
-
-\installpagebreakhandler \v!start
- {\globallet\shipout\normalshipout}
-
-\installpagebreakhandler \v!stop
- {\globallet\shipout\noshipout}
-
-% nb: \executepagebreakhandler\v!hoofd in other ones
-
-\installpagebreakhandler \v!header
- {\doifnotvalue{\??tk\v!header\c!state}\v!stop{\setupheader[\c!state=\v!empty]}}
-
-\installpagebreakhandler \v!footer
- {\doifnotvalue{\??tk\v!footer\c!state}\v!stop{\setupfooter[\c!state=\v!empty]}}
-
-% \definepagebreak
-% [chapter]
-% [yes,header,right]
-%
-% \setuphead
-% [chapter]
-% [page=chapter,
-% header=empty,
-% footer=chapter]
-%
-% \definepagebreak % untested
-% [lastpage]
-% [left,{empty,right},{empty,left}]
-% public page handler, beware: definepage already in use (core-ref)
-%
-% \definepagebreak[instance][forsure]
-% \definepagebreak[forsure][yes,+4]
-
-\unexpanded\def\definepagebreak
- {\dodoubleargument\dodefinepagebreak}
-
-\def\dodefinepagebreak[#1][#2]% non recursive, meant for simple mappings
- {\setvalue{\??pe::#1}{#2}}
-
-% don't change this / test case:
-%
-% \setupbackgrounds[state=repeat]
-% \setupbackgrounds[text][text][background=whatever]
-% \couplepage[chapter][before={\defineoverlay[whatever][ON]}]
-% \setuphead[chapter][before={\pagetype[chapter]}]
-% \chapter{First} \page test \chapter{second} \page test
-
-\long\def\installcolumnbreakhandler#1#2#3% #1=otr-id #2=tag
- {\long\setvalue{\??cn:#1:#2}{#3}}
-
-\unexpanded\def\definecolumnbreak
- {\dodoubleargument\dodefinecolumnbreak}
-
-\def\dodefinecolumnbreak[#1][#2]% non recursive, meant for simple mappings
- {\setvalue{\??cn::#1}{#2}}
-
-%\def\columnbreak
-% {\dosingleempty\docolumnbreak}
-%
-%\def\docolumnbreak[#1]%
-% {\expanded{\nextcolumn[\executeifdefined{\??cn::#1}{#1}]}}
-
-\definecomplexorsimple\columnbreak
-
-\def\simplecolumnbreak
- {\executecolumnbreakhandler\v!yes}
-
-\def\complexcolumnbreak[#1]% if empty, do nothing and avoid processing
- {\doifsomething{#1}{\executecolumnbreakhandlers{#1}}}
-
-\def\executecolumnbreakhandlers#1%
- {\processcommacommand[#1]\executecolumnbreakhandler}
-
-\def\executecolumnbreakhandler#1% here no commalist
- {\edef\@@columnspecification{#1}%
- \doifdefinedelse{\??cn:\OTRidentifier:\@@columnspecification}
- {\getvalue{\??cn:\OTRidentifier:\@@columnspecification}}
- {\doifdefinedelse{\??cn::\@@columnspecification}
- {\executecolumnbreakhandlers{\getvalue{\??cn::\@@columnspecification}}}
- {\getvalue{\??cn:\OTRidentifier:\s!unknown}}}}
-
-%let\nextcolumn\columnbreak
-\let\column \columnbreak
-
-% We don't want spurious last pages (due to left over marks):
-
-\def\noshipout
- {\writestatus\m!system{ignoring further shipouts}%
- \global\advance\realpageno\minusone % else no flush of resources
- \dowithnextbox{\deadcycles\zerocount}}
-
-% \def\doignorerestoftext
-% {\ifarrangingpages \else \ifnum\textlevel>\zerocount \else
-% \globallet\shipout\noshipout
-% \fi \fi}
-%
-% better:
-
-\def\doignorerestoftext
- {\ifarrangingpages \else \ifnum\textlevel=\plusone
- \globallet\shipout\noshipout
- \fi \fi}
-
-\let\ignorerestoftext\donothing
-
-\prependtoks % only ignore in a symmetrical doc
- \globallet\ignorerestoftext\doignorerestoftext
-\to \everystarttext
-
-% \appendtoks
-% \ignorerestoftext
-% \to \everylastshipout
-
-\newif\ifpageselected \pageselectedtrue
-\newif\ifselectingpages \selectingpagesfalse
-\newif\ifprocessingpages\processingpagestrue
-
-\let\pageselection \empty
-\let\currentpageselection\empty
-\let\aftershipout \relax
-\let\beforeshipout \relax
-
-\def\dodobeforeshipout#1%
- {\global\let\beforeshipout\relax
- \csname\??pg#1\c!before\endcsname}
-
-\def\dobeforeshipout
- {\doifsomething\currentpageselection
- {\processcommacommand[\currentpageselection]\dodobeforeshipout}}
-
-\def\dododoaftershipout#1%
- {\global\let\aftershipout\relax
- \global\let\currentpageselection\empty
- \csname\??pg#1\c!after\endcsname}
-
-\def\dodoaftershipout#1%
- {\doifelsevalue{\??pg#1\c!option}\v!doublesided
- {\doifbothsidesoverruled
- {\dododoaftershipout{#1}}
- {\dododoaftershipout{#1}}
- {}}
- {\dododoaftershipout{#1}}}
-
-\def\doaftershipout
- {\doifsomething\currentpageselection
- {\processcommacommand[\currentpageselection]\dodoaftershipout}}
-
-% Dit wordt eigenlijk nooit en moet worden vervangen door
-% het meer algemene mechanisme.
-
-\def\dopagetype[#1]%
- {\edef\desoortpagina{#1}%
- \ifx\desoortpagina\empty \else
- \@EA\doglobal\@EA\addtocommalist\@EA{\desoortpagina}\currentpageselection
- \ifselectingpages
- \fullexpandtwoargsafter\doifcommon\desoortpagina\pageselection
- {\global\pageselectedtrue}%
- \fi
- \gdef\beforeshipout{\dobeforeshipout}%
- \gdef\aftershipout {\doaftershipout}%
- \fi}
-
-\def\pagetype
- {\dosingleargument\dopagetype}
-
-\def\docouplepage[#1][#2]%
- {\getparameters
- [\??pg]
- [\c!before=,
- \c!after=,
- \c!option=,
- #2]%
- \def\docommand##1%
- {\getparameters
- [\??pg##1]
- [\c!before=\@@pgbefore,
- \c!after=\@@pgafter,
- \c!option=\@@pgoption]}%
- \processcommalist[#1]\docommand}%
-
-\def\couplepage
- {\dodoubleargument\docouplepage}
-
-\def\doprocesspage[#1][#2]%
- {\processaction
- [#2]
- [\v!yes=>\global\processingpagestrue,
- \v!no=>\global\processingpagesfalse]%
- \gdef\pageselection{#1}%
- \global\selectingpagestrue
- \global\pageselectedfalse}
-
-\def\processpage
- {\dodoubleargument\doprocesspage}
-
-\def\resetselectiepagina
- {\ifselectingpages
- \doifbothsidesoverruled{\global\pageselectedfalse}{}{\global\pageselectedfalse}%
- \fi}
-
-\newif\ifregistertextareas
-\newif\iftracetextareas
-
-\newbox\registertextbox
-
-% \def\registeredtextarea#1#2#3% #1=lower-dp #2=correct-ht #3=box
-% {\hbox{\box#3}}
-
-\def\enabletextarearegistration{\global\registertextareastrue}
-
-\def\registeredtextarea#1#2#3% #1=lower-dp #2=correct-ht #3=box
- {\hbox\bgroup
- \ifregistertextareas \ifx\registerMPtextarea\undefined \else
- \setbox\registertextbox\emptyhbox
- \wd\registertextbox\wd#3%
- \ht\registertextbox\ht#3%
- \dp\registertextbox\dp#3%
- \ifcase#1\or % 1
- \setbox\registertextbox\hbox{\lower\strutdp\box\registertextbox}%
- \fi
- \ifcase#2\or % 1
- \setbox\registertextbox\hbox{\raise\topskip\hbox{\lower\strutht\box\registertextbox}}%
- \dp\registertextbox\strutdp
- \fi
- \dp\registertextbox\strutdp % needed
- %\setbox\registertextbox\hbox
- % {\iftracetextareas\gray\boxrulewidth2pt\ruledhbox\fi
- % {\registerMPtextarea{\box\registertextbox}}}%
- \setbox\registertextbox\hbox
- {\registerMPtextarea{\box\registertextbox}}%
- \smashbox\registertextbox
- \box\registertextbox
- \fi \fi
- \box#3%
+\ifdefined\nestednewbox \else \newbox\nestednextbox \fi % hm, still needed?
+
+\prependtoks
+ \let\nextbox\nestednextbox
+\to \everybeforepagebody
+
+\def\page_boxes_constructed_page#1#2%
+ {\vbox\bgroup % intercept spurious spaces
+ \the\everybeforepagebody
+ \starttextproperties
+ \dontshowboxes
+ \checkmarginblocks
+ \the\beforeeverypage
+ \normalexpanded{\global\beforepage\emptytoks\the\beforepage}%
+ \inpagebodytrue
+ \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}
-%D \macros
-%D {setupoppositeplacing,startopposite}
-%D
-%D \starttyping
-%D \starttext
-%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
-%D test \startopposite \blackrule[width=3cm,height=4cm] \stopopposite test
-%D \stoptext
-%D \stoptyping
-
-% Moved from page-mar.tex, made english, cleaned up, but still to be
-% redesigned
-
-\newbox\facingpage
-
-\unexpanded\def\setupoppositeplacing
- {\dodoubleargument\getparameters[\??np]}
-
-\unexpanded\def\startopposite
- {\dowithnextboxcontent
- {\hsize\makeupwidth}%
- {\global\setbox\facingpage\vbox
- {\ifvoid\facingpage
- \@@npbefore
- \else
- \@@npinbetween
- \unvbox\facingpage
- \fi
- \box\nextbox}}%
- \vbox\bgroup}
-
-\unexpanded\def\stopopposite
- {\egroup}
-
-\def\finishfacingpage
- {\ifvoid\facingpage\else
- \global\setbox\facingpage\vbox to \makeupheight
- {\unvbox\facingpage
- \@@npafter
- \vss}%
- \fi}
-
-\def\shipoutfacingpage
- {\doif\@@npstate\v!start
- {\ifvoid\facingpage\else
- \ifnum\realpageno>\plusone
- \bgroup
- \pageornamentstate\plusone
- \finishfacingpage
- \myshipout{\buildpagebody\box\facingpage}%
- \egroup
- \else
- \global\setbox\facingpage\emptybox
- \fi
- \fi}}
-
-\setupoppositeplacing
- [\c!state=\v!start,
- \c!before=,
- \c!inbetween=\blank,
- \c!after=]
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-ins.mkii b/Master/texmf-dist/tex/context/base/page-ins.mkii
index 069153434ad..ce0f51d7282 100644
--- a/Master/texmf-dist/tex/context/base/page-ins.mkii
+++ b/Master/texmf-dist/tex/context/base/page-ins.mkii
@@ -5,7 +5,7 @@
%D subtitle=Insertions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-ins.mkiv b/Master/texmf-dist/tex/context/base/page-ins.mkiv
index 3e12bfcf003..793e28d4c4b 100644
--- a/Master/texmf-dist/tex/context/base/page-ins.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-ins.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Insertions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -38,7 +38,6 @@
\appendtoks\doprocessinsert#1\to\@@insertionlist
\fi}
-
\def\synchronizeinsertions
{\def\doprocessinsert##1{\ifvoid##1\else\insert##1{\unvbox##1}\fi}%
\processinsertions}
diff --git a/Master/texmf-dist/tex/context/base/page-lay.mkii b/Master/texmf-dist/tex/context/base/page-lay.mkii
index d40e1ccb7b9..61ff8764f38 100644
--- a/Master/texmf-dist/tex/context/base/page-lay.mkii
+++ b/Master/texmf-dist/tex/context/base/page-lay.mkii
@@ -5,7 +5,7 @@
%D subtitle=Layout Specification,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-lay.mkiv b/Master/texmf-dist/tex/context/base/page-lay.mkiv
index 812f3a3aca8..78839ea705a 100644
--- a/Master/texmf-dist/tex/context/base/page-lay.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-lay.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Layout Specification,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -24,18 +24,12 @@
\unprotect
-%D First we get rid of the funny \TEX\ offset defaults of one
-%D inch by setting them to zero.
-
-\voffset = 0pt % setting this to -1in let's go metapost crazy
-\hoffset = 0pt % setting this to -1in let's go metapost crazy
-
%D The dimensions related to layout areas are represented by
%D real dimensions.
\newdimen\paperheight \paperheight = 297mm
\newdimen\paperwidth \paperwidth = 210mm
-\newdimen\paperoffset \paperoffset = 0mm
+\newdimen\paperoffset \paperoffset = \zeropoint
\newdimen\printpaperheight \printpaperheight = \paperheight
\newdimen\printpaperwidth \printpaperwidth = \paperwidth
@@ -48,13 +42,13 @@
\newdimen\topspace \topspace = 2cm
\newdimen\backspace \backspace = \topspace
-\newdimen\cutspace \cutspace = 0pt
-\newdimen\bottomspace \bottomspace = 0pt
+\newdimen\cutspace \cutspace = \zeropoint
+\newdimen\bottomspace \bottomspace = \zeropoint
\newdimen\headerheight \headerheight = 2cm
\newdimen\footerheight \footerheight = \headerheight
-\newdimen\topoffset \topoffset = 0pt
+\newdimen\topoffset \topoffset = \zeropoint
\newdimen\backoffset \backoffset = \topoffset
\newdimen\leftmarginwidth \leftmarginwidth = 3cm
@@ -63,46 +57,23 @@
\newdimen\leftedgewidth \leftedgewidth = 3cm
\newdimen\rightedgewidth \rightedgewidth = \leftedgewidth
-\newdimen\topheight \topheight = 0cm
+\newdimen\topheight \topheight = \zeropoint
\newdimen\bottomheight \bottomheight = \topheight
-\newcount\layoutlines \layoutlines = 0
-\newcount\layoutcolumns \layoutcolumns = 0
-\newdimen\layoutcolumndistance \layoutcolumndistance = 0pt
-\newdimen\layoutcolumnwidth \layoutcolumnwidth = 0pt
-
-%D We can save some tokens and fuzzy parameters by using a
-%D symbolic name for the current set of layout parameters.
-
-\let\currentlayout\empty
-
-\def\layoutparameter#1%
- {\csname\??ly\ifcsname
- \??ly\currentlayout#1\endcsname\currentlayout
- \fi#1\endcsname}
+\newcount\layoutlines \layoutlines = \zerocount
+\newcount\layoutcolumns \layoutcolumns = \zerocount
+\newdimen\layoutcolumndistance \layoutcolumndistance = \zeropoint
+\newdimen\layoutcolumnwidth \layoutcolumnwidth = \zeropoint
-\def\namedlayoutparameter#1#2%
- {\csname\??ly\ifcsname\??ly #1#2\endcsname#1\else
- \ifcsname\??ly\currentlayout#2\endcsname\currentlayout
- \fi\fi#2\endcsname}
-
-%D Beause normal \TEX\ has at most 256 dimensions (of which a
-%D substantial part is already in use), we provide a way to
-%D generate a format with macro based alternatives. For a long
-%D time, this used to be the default case. Beware: only fixed
-%D dimensions can be used in calculations! By the way, the
-%D gain in speed can hardly be called impressive and is roughly
-%D 1 second on a 35 second run of 850 empty pages with a
-%D couple of backgrounds only (which is far less than one
-%D percent on a normal document).
+\newdimen\totaltextwidth
%D The next series of dimensions are complemented by left
%D and rights ones.
-\newdimen \margindistance
-\newdimen \edgedistance
-\newdimen \marginwidth
-\newdimen \edgewidth
+\newdimen\margindistance
+\newdimen\edgedistance
+\newdimen\marginwidth
+\newdimen\edgewidth
%D Because a distance does not really makes sense when there
%D is no area, we use a zero distance in case there is no
@@ -110,17 +81,17 @@
%D The horizontal distances are:
-\newdimen \leftedgedistance
-\newdimen \rightedgedistance
-\newdimen \leftmargindistance
-\newdimen \rightmargindistance
+\newdimen\leftedgedistance
+\newdimen\rightedgedistance
+\newdimen\leftmargindistance
+\newdimen\rightmargindistance
%D The vertical distances are:
-\newdimen \topdistance
-\newdimen \headerdistance
-\newdimen \footerdistance
-\newdimen \bottomdistance
+\newdimen\topdistance
+\newdimen\headerdistance
+\newdimen\footerdistance
+\newdimen\bottomdistance
%D We need to calculate the extra distances:
@@ -137,9 +108,62 @@
\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{\strictlayoutparameter\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 ?
+ \global\let\currentlayout\currentlayout % global
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \or % \setuplayout (reverts to main layout)
+ \letlayoutparameter\c!state\v!normal % global ? still needed ?
+ \global\let\currentlayout\empty % global
+ \page_layouts_synchronize
+ \page_layouts_check_next
+ \fi
+\to \everysetuplayout
+
+\def\doiflayoutdefinedelse#1%
+ {\ifcsname\namedlayouthash{#1}\c!state\endcsname % maybe a helper
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
\def\layoutdistance#1#2{\ifdim\zeropoint<#1#2\else\zeropoint\fi}
-\def\setlayoutdimensions
+\def\page_layouts_set_dimensions
{\global\naturalmarginwidth \layoutparameter\c!margin
\global\naturaledgewidth \layoutparameter\c!edge
\global\naturalmargindistance \layoutparameter\c!margindistance
@@ -153,22 +177,22 @@
\global\naturalfooterdistance \layoutparameter\c!footerdistance
\global\naturalbottomdistance \layoutparameter\c!bottomdistance
%
- \global\marginwidth \naturalmarginwidth
- \global\edgewidth \naturaledgewidth
- \global\margindistance \naturalmargindistance
- \global\edgedistance \naturaledgedistance
+ \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\footerdistance \layoutdistance\footerheight \naturalfooterdistance
- \global\bottomdistance \layoutdistance\bottomheight \naturalbottomdistance
- }
-
-\def\setlayoutdistances % local in \setreducedvsize
+ \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\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}
@@ -187,31 +211,31 @@
\def\outerspacewidth {\rightorleftpageaction\cutspace\backspace}
\def\innerspacewidth {\rightorleftpageaction\backspace\cutspace}
-\newtoks\extralayoutcalculations \def\calculatelayoutextras{\the\extralayoutcalculations}
+\newtoks\extralayoutcalculations
-% \appendtoks
-% non etex calculations used to go here
-% \to \extralayoutcalculations
+\def\page_layouts_calculate_extras
+ {\the\extralayoutcalculations}
\newtoks\everyswapmargins % watch the order !
\appendtoks
- \swapdimens\leftmargindistance\rightmargindistance
- \swapdimens\leftedgedistance \rightedgedistance
- \swapdimens\leftmarginwidth \rightmarginwidth
- \swapdimens\leftedgewidth \rightedgewidth
+ \swapdimens\leftmargindistance\rightmargindistance
+ \swapdimens\leftedgedistance \rightedgedistance
+ \swapdimens\leftmarginwidth \rightmarginwidth
+ \swapdimens\leftedgewidth \rightedgewidth
+ %
+ \swapmacros\leftmargintotal \rightmargintotal
+ \swapmacros\leftedgetotal \rightedgetotal
+ \swapmacros\leftsidetotal \rightsidetotal
+ \swapmacros\leftcombitotal \rightcombitotal
+ \swapmacros\innermargintotal \outermargintotal
+ \swapmacros\inneredgetotal \outeredgetotal
+ \swapmacros\innercombitotal \outercombitotal
+ \swapmacros\innersidetotal \outersidetotal
\to \everyswapmargins
-\appendtoks
- \swapmacros\leftmargintotal \rightmargintotal
- \swapmacros\leftedgetotal \rightedgetotal
- \swapmacros\leftsidetotal \rightsidetotal
- \swapmacros\leftcombitotal \rightcombitotal
- \swapmacros\innermargintotal\outermargintotal
- \swapmacros\inneredgetotal \outeredgetotal
- \swapmacros\innercombitotal \outercombitotal
- \swapmacros\innersidetotal \outersidetotal
-\to \everyswapmargins
+%D The papersize macros have a long history and we don't want
+%D to change the commands so they keep looking a bit complex.
%D \macros
%D {definepapersize}
@@ -222,39 +246,7 @@
%D which case the second argument is an assignment.
%D
%D \showsetup{definepapersize}
-
-\unexpanded\def\definepapersize
- {\dodoubleempty\dodefinepapersize}
-
-\unexpanded\def\definepapersize
- {\dotripleempty\dodefinepapersize}
-
-\def\dodefinepapersize[#1][#2][#3]%
- {\ifsecondargument
- \doifsomething{#1} % to be sure
- {\doifassignmentelse{#2}
- {\getparameters
- [\??pp#1] % geen \c!scale, scheelt hash ruimte
- [\c!width=\@@ppwidth,\c!height=\@@ppheight,\c!offset=\@@ppoffset,#2]}
- {\setvalue{\??pp:1:#1}{#2}%
- \setvalue{\??pp:2:#1}{#3}}}%
- \else
- \getparameters[\??pp][#1]%
- \setuppapersize % hm. this will freeze !
- \fi}
-
-%D For the moment we need to fake this macro.
-
-\ifx\setuppapersize\undefined
- \let\setuppapersize\relax
-\fi
-
-%D We set the defaults to the dimensions of an A4 sheet of
-%D paper.
-
-\definepapersize
- [\c!width=210mm,\c!height=297mm,\c!offset=\zeropoint]
-
+%D
%D Yet undocumented, let's see if it gets noticed.
%D
%D \starttyping
@@ -275,7 +267,7 @@
%D Page 6. \page
%D \stoptext
%D \stoptyping
-
+%D
%D \macros
%D {setuppaper,setuppapersize}
%D
@@ -287,121 +279,288 @@
%D We keep track of these features with the following
%D variables.
-\newconditional\papermirror \newconditional\printmirror
-\newconstant \paperorientation \newconstant \printorientation
-\newconstant \paperreverse \newconstant \printreverse
-\newconditional\paperlandscape \newconditional\printlandscape
+\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}
+
+% Normally we will not use this command directly but for now it
+% works out okay. In 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]
+
+\unexpanded\def\definepapersize
+ {\dotripleempty\page_paper_define_size}
+
+\def\page_paper_define_size[#1][#2][#3]%
+ {\edef\currentlayouttarget{#1}%
+ \ifx\currentlayouttarget\empty
+ % invalid target
+ \else
+ \doifassignmentelse{#2}
+ {\definelayouttarget[#1][#2]}
+ {\setevalue{\??layoutpaper#1}{#2}%
+ \setevalue{\??layoutprint#1}{#3}}%
+ \fi}
-\let\papersize\empty \let\printpapersize\empty
+\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\paperscale{1} \newif\ifnegateprintbox
+% \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
-\unexpanded\def\setuppaper[#1]%
- {\getparameters[\??pp][\c!paper=,\c!page=,#1]%
- \edef\@@ppxy{\the\numexpr\@@ppnx*\@@ppny\relax}%
- \doifelsenothing\@@pppage
- {\doifelsenothing\@@pppaper
- {} % {\setuppapersize} % added, removed, no need for, too tricky, mag-01 (fixed by freezing pp's)
- {\dodosetuppapersize[\papersize][\@@pppaper]}}
- {\doifelsenothing\@@pppaper
- {\dodosetuppapersize[\@@pppage][\printpapersize]}
- {\dodosetuppapersize[\@@pppage][\@@pppaper]}}}
+\let\page_paper_reinstate\relax
+\let\page_paper_restore \relax
\unexpanded\def\setuppapersize
- {\dodoubleempty\dosetuppapersize}
-
-\def\dosetuppapersize[#1][#2]%
- {\doifassignmentelse{#1}
- {\setuppaper[#1]}
- {\doifelsenothing{#2}
- {\expanded{\dodosetuppapersize
- [\executeifdefined{\??pp:1:#1}{#1}]%
-% [\executeifdefined{\??pp:2:#1}{\v!default}]}}
- [\executeifdefined{\??pp:2:#1}{#1}]}}
- {\doifassignmentelse{#2}
- {\getparameters[\??pp\executeifdefined{\??pp:1:#1}{#1}][#2]}
- {\expanded{\dodosetuppapersize
- [\executeifdefined{\??pp:1:#1}{#1}]%
- [\executeifdefined{\??pp:1:#2}{#2}]}}}}}
-
-\let\reinstatepapersize\relax
-
-\def\adaptpapersize
- {\global\let\reinstatepapersize\restorepapersize
+ {\dodoubleempty\page_paper_setup_size}
+
+\unexpanded\def\page_paper_setup_size[#1][#2]%
+ {\iffirstargument
+ \doifassignmentelse{#1}
+ {\page_paper_setup_size_settings[#1]}
+ {\doifassignmentelse{#2}
+ {\page_paper_setup_size_settings_by_name[#1][#2]}
+ {\page_paper_setup_size_change_size[#1][#2]}}%
+ \else
+ \page_paper_restore
+ \fi}
+
+\unexpanded\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}
+
+\unexpanded\def\page_paper_setup_size_settings_by_name[#1][#2]%
+ {\def\currentlayouttarget{\page_paper_the_paper_size{#1}}%
+ \setuplayouttarget[#2]}
+
+\unexpanded\def\page_paper_setup_size_change_size[#1][#2]%
+ {\doifelsenothing{#2}
+ {\page_paper_set_current[#1][#1]}
+ {\page_paper_set_current[#1][#2]}}
+
+\let\setuppaper\page_paper_setup_size_settings
+
+\unexpanded\def\adaptpapersize
+ {\global\let\page_paper_reinstate\page_paper_reinstate_indeed
\setuppapersize}
+\unexpanded\def\page_paper_reinstate_indeed
+ {\page_paper_restore
+ \global\let\page_paper_reinstate\relax}
+
\appendtoks
- \reinstatepapersize
- \global\let\reinstatepapersize\relax
+ \page_paper_reinstate
\to \everyaftershipout
-\def\dodosetuppapersize[#1][#2]%
- {\ifsecondargument
- \expanded{\dododosetuppapersize[#1][#2]}%
- \calculatehsizes
- \calculatevsizes
- \recalculatebackgrounds
- \recalculatelayout
- \else\iffirstargument
- \setuppapersize[#1][#2]%
- \else\ifx\papersize\undefined\else
- \restorepapersize
- \fi\fi\fi}
-
-% dimen freeze is a bit tricky, but catches local redundant calls
-% with values where e.g width is defined in terms of \paperwidth
-
-\def\dododosetuppapersize[#1][#2]%
- {\xdef\restorepapersize{\noexpand\setuppapersize[#1][#2]}%
- \dosetuppaperorientation{#1}\paperlandscape\paperorientation\paperreverse\papermirror
- \dosetuppaperorientation{#2}\printlandscape\printorientation\printreverse\printmirror
- \def\docommand##1%
- {\doifsomething{##1}{\doifdefined{\??pp##1\c!width}
- {\global\paperwidth \getvalue{\??pp##1\c!width}%
- \global\paperheight\getvalue{\??pp##1\c!height}%
- \ifinpagebody
- \setevalue{\??pp##1\c!height}{\the\paperheight}%
- \setevalue{\??pp##1\c!width }{\the\paperwidth }%
- \fi
- \calculatepaperoffsets{##1}%
- \xdef\papersize{##1}}}}%
- \processcommacommand[#1]\docommand
- \doifdefinedelse{\??pp#1\c!scale}
- {\edef\paperscale{\getvalue{\??pp#1\c!scale}}}
- {\edef\paperscale{1}}%
- \def\docommand##1%
- {\doifsomething{##1}{\doifdefined{\??pp##1\c!width}
- {\global\printpaperwidth \getvalue{\??pp##1\c!width}%
- \global\printpaperheight\getvalue{\??pp##1\c!height}%
- \ifinpagebody
- \setevalue{\??pp##1\c!height}{\the\printpaperheight}%
- \setevalue{\??pp##1\c!width }{\the\printpaperwidth}%
- \fi
- \xdef\printpapersize{##1}}}}%
- \processcommacommand[#2]\docommand
- \global\setdimentoatleast\paperwidth \onepoint
- \global\setdimentoatleast\paperheight \onepoint
- \global\setdimentoatleast\printpaperwidth \onepoint
- \global\setdimentoatleast\printpaperheight\onepoint
- \ifconditional\paperlandscape
+\unexpanded\def\page_paper_set_restore#1#2%
+ {\xdef\page_paper_restore{\page_paper_set_current_indeed[#1][#2]}}
+
+\unexpanded\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}]}}
+
+\setvalue{\??layoutpaper\v!reset }{\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}
+\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!reset }{\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}
+\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}
+
+\unexpanded\def\page_paper_identify_target#1%
+ {\ifcsname\??layoutcurrent#1\endcsname
+ \edef\currentlayouttarget{#1}%
+ \fi}
+
+\unexpanded\def\page_paper_set_current_indeed[#1][#2]%
+ {\edef\m_page_asked_paper{\v!reset,#1}% can be the restores
+ \edef\m_page_asked_print{\v!reset,#2}%
+ %
+ \page_paper_set_restore\m_page_asked_paper\m_page_asked_print
+ %
+ % locate page target
+ \let\currentlayouttarget\empty
+ \processcommacommand[\m_page_asked_paper]\page_paper_identify_target
+ \ifx\currentlayouttarget\empty
+ \let\currentlayouttarget\currentpage
+ \fi
+ \global\let\papersize\currentlayouttarget
+ \processcommacommand[\m_page_asked_paper]\page_paper_handle_page_option
+ \global\paperwidth \layouttargetparameter\c!width \relax
+ \global\paperheight\layouttargetparameter\c!height\relax
+ \ifdim\paperwidth<\onepoint
+ \global\paperwidth\onepoint
+ \fi
+ \ifdim\paperheight<\onepoint
+ \global\paperheight\onepoint
+ \fi
+ \ifconditional\c_page_target_paper_landscape
\doglobal\swapdimens\paperwidth\paperheight
\fi
- \ifconditional\printlandscape
- \doglobal\swapdimens\printpaperwidth\printpaperheight
+ \ifinpagebody % local freeze
+ \normalexpanded{\setlayouttargetparemeter\c!height{\the\paperheight}}%
+ \normalexpanded{\setlayouttargetparemeter\c!width {\the\paperwidth }}%
+ \fi
+ %
+ \page_paper_set_offsets
+ % locate paper target
+ \processcommacommand[\m_page_asked_print]\page_paper_identify_target
+ \global\let\printpapersize\currentlayouttarget
+ \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
+ \globalswapdimens\printpaperwidth\printpaperheight
\fi
% this check can be confusing, so we've added the possibility
% to bypass this test: \setuppapersize[option=fit]
- \doif\@@ppoption\v!max % \v!fit is
- {\bgroup
+ \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\paperorientation=\rightrotatioangle
+ \ifnum\c_page_target_paper_orientation=\rightrotationangle
\swapdimens\paperwidth\paperheight
- \else\ifnum\paperorientation=\leftrotatioangle
+ \else\ifnum\c_page_target_paper_orientation=\leftrotationangle
\swapdimens\paperwidth\paperheight
\fi\fi
- \ifnum\printorientation=\rightrotatioangle
+ \ifnum\c_page_target_print_orientation=\rightrotationangle
\swapdimens\printpaperwidth\printpaperheight
- \else\ifnum\printorientation=\leftrotatioangle
+ \else\ifnum\c_page_target_print_orientation=\leftrotationangle
\swapdimens\printpaperwidth\printpaperheight
\fi\fi
\ifdim\paperheight>\printpaperheight
@@ -412,63 +571,28 @@
\global\printpaperwidth\paperwidth
\writestatus\m!system{print width forced to paper width}%
\fi
- \egroup}}
-
-\def\dosetuppaperorientation#1#2#3#4#5%
- {\global\setfalse#2%
- \global\setfalse#5%
- \global#3\uprotationangle
- \global#4\uprotationangle
- \global\negateprintboxfalse
- \processallactionsinset
- [#1]
- [ \v!landscape=>\global\settrue#2,
- \v!mirrored=>\global\settrue#5,
- \v!rotated=>\global#3\rightrotatioangle
- \global#4\leftrotatioangle,
- \v!negative=>\global\negateprintboxtrue,
- 90=>\global#3\rightrotatioangle
- \global#4\leftrotatioangle,
- 180=>\global#3\downrotatioangle
- \global#4\zerocount,
- 270=>\global#3\leftrotatioangle
- \global#4\rightrotatioangle]}
-
-\ifx\calculatepaperoffsets\undefined
-
- \def\calculatepaperoffsets#1%
- {\scratchdimen\getvalue{\??pp#1\c!offset}%
- \global\advance\paperwidth -2\scratchdimen
- \global\advance\paperheight-2\scratchdimen}
-
-\fi
-
-\let\restorepapersize\relax
+ \endgroup
+ \fi
+ %\writestatus{layout target}{(\the\paperwidth,\the\paperheight) -> (\the\printpaperwidth,\the\printpaperheight)}%
+ \page_layouts_synchronize}
-% \def\docheckforems#1%
-% {\beforesplitstring#1\at em\to\asciia
-% \doifnot\asciia{#1}
-% {\aftersplitstring\asciia\at=\to\asciia
-% \doifsomething\asciia{\showmessage\m!system{10}{#1}}}}
-%
-% \def\checkforems[#1]%
-% {\processcommalist[#1]\docheckforems}
+\ifx\page_paper_set_offsets\undefined
-\ifx\setups\undefined \unexpanded\def\setups[#1]{\setdefaultpenalties} \fi
+ \def\page_paper_set_offsets % will move
+ {\global\paperoffset\v_page_target_offset
+ \global\advance\paperwidth -2\paperoffset
+ \global\advance\paperheight-2\paperoffset}
-% \newtoks \everybeforelayout \relax
-% \newtoks \everyafterlayout \relax
+\fi
-\def\recalculatelayout
- {\doifsomething{\layoutparameter\c!page\layoutparameter\c!paper}
- {\expanded{\dododosetuppapersize[\layoutparameter\c!page][\layoutparameter\c!paper]}}%
- \dorecalculatelayout}
+\ifdefined\setups \else \unexpanded\def\setups[#1]{\setdefaultpenalties} \fi % still needed?
+\ifdefined\synchronizegridsnapping \else \let\synchronizegridsnapping\relax \fi
-\ifdefined\docheckgridsnapping \else \let\docheckgridsnapping\relax \fi
+\let\p_page_layouts_width \empty
+\let\p_page_layouts_height\empty
-\def\dorecalculatelayout
- {%\the\everybeforelayout
- \setups[\layoutparameter\c!preset]%
+\def\page_layouts_synchronize
+ {\setups[\layoutparameter\c!preset]%
\global\leftmarginwidth \layoutparameter\c!leftmargin
\global\rightmarginwidth\layoutparameter\c!rightmargin
\global\leftedgewidth \layoutparameter\c!leftedge
@@ -479,43 +603,45 @@
\global\topheight \layoutparameter\c!top
\global\backspace \layoutparameter\c!backspace
\global\topspace \layoutparameter\c!topspace
- \setlayoutdimensions % the rest of the `dimensions'
- \docheckgridsnapping
+ \page_layouts_set_dimensions
+ \synchronizegridsnapping
\doprocesslocalsetups{\layoutparameter\c!setups}% depends on gridsnapping !
- \simplesetupwhitespace
- \simplesetupblank
+ \synchronizewhitespace
+ \synchronizeblank
\setupinterlinespace[\v!reset]% \synchronizegloballinespecs
- \global\cutspace\layoutparameter\c!cutspace
- \relax
- \doifelse{\layoutparameter\c!width}\v!middle
- {\ifdim\cutspace=\zeropoint
- \global\cutspace\backspace
- \fi
- \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax}
- {\doifelse{\layoutparameter\c!width}\v!fit
- {\ifdim\cutspace=\zeropoint
- \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}
- {\global\makeupwidth\layoutparameter\c!width\relax
- \ifdim\cutspace=\zeropoint
- \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}}%
+ \global\cutspace\layoutparameter\c!cutspace\relax
+ \edef\p_page_layouts_width{\layoutparameter\c!width}%
+ \ifx\p_page_layouts_width\v!middle
+ \ifdim\cutspace=\zeropoint
+ \global\cutspace\backspace
+ \fi
+ \global\makeupwidth\dimexpr\paperwidth-\backspace-\cutspace\relax
+ \else\ifx\p_page_layouts_width\v!fit
+ \ifdim\cutspace=\zeropoint
+ \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
+ \ifdim\cutspace=\zeropoint
+ \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\fi
\scratchdimen\layoutparameter\c!bottomspace\relax
%\ifdim\scratchdimen=\zeropoint
% \scratchdimen\topspace
@@ -523,27 +649,30 @@
\global\bottomspace\layoutparameter\c!bottomspace\relax
\global\layoutlines0\number\layoutparameter\c!lines\relax % may be empty
\ifcase\layoutlines
- \doifelse{\layoutparameter\c!height}\v!middle
- {\ifdim\bottomspace=\zeropoint
- \global\bottomspace\topspace
- \fi
- \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax}
- {\doifelse{\layoutparameter\c!height}\v!fit
- {\ifdim\bottomspace=\zeropoint
- \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}
- {\global\makeupheight\layoutparameter\c!height\relax
- \ifdim\bottomspace=\zeropoint
- \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax
- \else
- % inconsistent specification
- \fi}}%
+ \edef\p_page_layouts_height{\layoutparameter\c!height}%
+ \ifx\p_page_layouts_height\v!middle
+ \ifdim\bottomspace=\zeropoint
+ \global\bottomspace\topspace
+ \fi
+ \global\makeupheight\dimexpr\paperheight-\topspace-\bottomspace\relax
+ \else\ifx\p_page_layouts_height\v!fit
+ \ifdim\bottomspace=\zeropoint
+ \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
+ \ifdim\bottomspace=\zeropoint
+ \global\bottomspace\dimexpr\paperheight-\makeupheight-\topspace\relax
+ % \else
+ % inconsistent specification
+ \fi
+ \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
@@ -553,38 +682,56 @@
\layoutparameter\c!lines\lineheight-\strutheight+\topskip+
\headerdistance+\headerheight+\footerdistance+\footerheight\relax
\fi
- \backoffset\layoutparameter\c!horoffset
- \topoffset \layoutparameter\c!veroffset
- \global\setdimentoatleast\makeupwidth\onepoint
- \global\setdimentoatleast\makeupheight \onepoint
- % \checkcurrentlayout % here ?
- % \the\everyafterlayout
- \calculatelayoutextras
+ \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_calculate_extras
+ \page_target_check_centering
\calculatehsizes
\calculatevsizes
- \calculatepseudocolumns
- \recalculatebackgrounds}
+ \page_layouts_check_pseudo_columns
+ \page_backgrounds_recalculate}
-\def\calculatepseudocolumns
+\def\page_layouts_check_pseudo_columns
{\global\layoutcolumns\layoutparameter\c!columns
\global\layoutcolumndistance\layoutparameter\c!columndistance
\global\layoutcolumnwidth\dimexpr\makeupwidth-\layoutcolumns\layoutcolumndistance+\layoutcolumndistance\relax
- \global\divide\layoutcolumnwidth\layoutcolumns
- \dorecurse\layoutcolumns
- {\setxvalue{\??ly:c:\recurselevel}%
- {\the\numexpr\recurselevel-\plusone\relax\dimexpr\layoutcolumnwidth+\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}}
-%\dorecurse\layoutcolumns
-% {\setxvalue{\??ly:c:\recurselevel}{\the\dimexpr
-% (\numexpr(\recurselevel-1)\dimexpr(\layoutcolumnwidth+\layoutcolumndistance))}}
+\letvalue{\??layoutcolumn0}\zeropoint
\def\layoutcolumnoffset#1%
- {\executeifdefined{\??ly:c:#1}\zeropoint}
+ {\csname\??layoutcolumn\ifcsname\??layoutcolumn#1\endcsname#1\else0\fi\endcsname}
-\def\checklayout
- {\ifdim\makeupheight=\layoutlines\lineheight \else \recalculatelayout \fi}
+\def\page_layouts_synchronize_at_start
+ {\ifdim\makeupheight=\layoutlines\lineheight \else % weird check
+ \page_layouts_synchronize
+ \fi}
-\appendtoks \checklayout \to \everystarttext
+\appendtoks
+ \page_layouts_synchronize_at_start % still needed?
+\to \everystarttext
% document:
%
@@ -592,46 +739,100 @@
%
% \startstandardmakeup[page=blank] ... \stopstandardmakeup
-\def\changetolayout#1%
+\ifdefined\lastpage \else \let\lastpage\!!plusone \fi
+
+\def\page_layouts_change#1%
{%\writestatus\m!layouts{changing to layout #1}%
- \xdef\currentlayout{#1}\recalculatelayout}
+ \xdef\currentlayout{#1}%
+ \page_layouts_synchronize}
-\def\checkcurrentoddlayout
- {\ifcsname\??ly\v!odd\c!state\endcsname
- \doifvalue{\??ly\v!odd\c!state}\v!start{\changetolayout\v!odd}%
- \fi}
+\let\changetolayout\page_layouts_change % also public
-\def\checkcurrentevenlayout
- {\ifcsname\??ly\v!even\c!state\endcsname
- \doifvalue{\??ly\v!even\c!state}\v!start{\changetolayout\v!even}%
+\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}
-\ifx\lastpage\undefined \def\lastpage{1} \fi
+\let\v_real_page_current\v!current
-\def\reverserealfolio
- {\ifnum\lastpage>\plusone
- \ifnum\lastpage=\realfolio
- \v!last
- \else\ifnum\plusone=\realfolio
- \v!first
- \else
- \the\numexpr\realfolio-\lastpage\relax
- \fi\fi
+\def\v_real_page_named
+ {\ifnum\lastpage=\realpageno
+ \v!last
+ \else\ifnum\plusone=\realpageno
+ \v!first
\else
- \!!zerocount
- \fi}
+ \__unknown__
+ \fi\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
+ \global\let\v_page_layouts_pre_check\currentlayout
+ \global\let\currentlayout\m_page_check
+ \page_layouts_synchronize
+ \else\ifx\m_page_state\v!repeat
+ \global\let\v_page_layouts_pre_check\relax
+ \global\let\currentlayout\m_page_check
+ \page_layouts_synchronize
+ \fi\fi}
+
+\def\page_layouts_check_revert
+ {\global\let\currentlayout\v_page_layouts_pre_check
+ \global\let\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
+ \else\ifcsname\namedlayouthash\v_real_page_reverse\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_reverse
+ \else\ifcsname\namedlayouthash\v_real_page_named\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_named
+ \else\ifcsname\namedlayouthash\v_real_page_current\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_current
+ \else\ifcsname\namedlayouthash\v_real_page_odd_or_even\c!state\endcsname
+ \page_layouts_check_default_indeed\v_real_page_odd_or_even
+ \else\ifx\v_page_layouts_pre_check\relax
+ % okay
+ \else
+ \page_layouts_check_revert
+ \fi\fi\fi\fi\fi\fi}
+
+\def\installlayoutmethod#1#2%
+ {\setgvalue{\??layoutmethod#1}{#2}}
+
+\installlayoutmethod\v!default{\page_layouts_check_default}
+\installlayoutmethod\v!normal {\page_layouts_check_default}
-\def\checkcurrentlayout % public and used in naw, so keep this name
- {\ifcsname\??ly\realfolio\c!state\endcsname
- \doifvalue{\??ly\realfolio\c!state}\v!start{\changetolayout\realfolio}%
- \else\ifcsname\??ly\reverserealfolio\c!state\endcsname
- \doifvalue{\??ly\reverserealfolio\c!state}\v!start{\changetolayout\reverserealfolio}%
- \else\ifcsname\??ly\v!current\c!state\endcsname
- \changetolayout\v!current % no start test ?
+\def\page_layouts_check_next
+ {\csname\??layoutmethod\ifcsname\??layoutmethod\layoutparameter\c!method\endcsname
+ \layoutparameter\c!method
\else
- \doifoddpageelse\checkcurrentoddlayout\checkcurrentevenlayout
- \fi\fi\fi}
+ \v!normal
+ \fi\endcsname}
+\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]
@@ -650,354 +851,173 @@
% \dorecurse{20} {\input knuth \endgraf \input tufte \endgraf}
% \stoptext
-%appendtoks \checkcurrentlayout \to \everyaftershipout % no
-\appendtoks \checkcurrentlayout \to \everystarttext
-
-\appendtoks
- \dochecknextlayout
-\to \everyaftershipout
-
-% \def\dochecknextlayout
-% {\ifx\currentlayout\v!current
-% % prevent redundant calculations
-% \else
-% \globallet\currentlayout\empty
-% \global\letbeundefined{\??ly\v!current\c!state}%
-% \checkcurrentlayout
-% \fi}
-%
-% this breaks after a standardmakeup
-
-\def\dochecknextlayout{\checkcurrentlayout}
-
-\newif\ifdoublesidedprint
-
-\newconditional\page_location_is_set
-
-\def\page_location_reset
- {\setfalse\page_location_is_set
- \let\page_location_left_fill \relax
- \let\page_location_right_fill \relax
- \let\page_location_top_fill \relax
- \let\page_location_bottom_fill\relax}
-
-\page_location_reset
-
-\setvalue{\??ly:\c!location:\v!right }{\settrue\page_location_is_set
- \let\page_location_left_fill \hss}
-\setvalue{\??ly:\c!location:\v!left }{\settrue\page_location_is_set
- \let\page_location_right_fill \hss}
-\setvalue{\??ly:\c!location:\v!bottom }{\settrue\page_location_is_set
- \let\page_location_top_fill \vss}
-\setvalue{\??ly:\c!location:\v!top }{\settrue\page_location_is_set
- \let\page_location_bottom_fill\vss}
-\setvalue{\??ly:\c!location:\v!middle }{\settrue\page_location_is_set
- \let\page_location_left_fill \hss
- \let\page_location_right_fill \hss
- \let\page_location_top_fill \vss
- \let\page_location_bottom_fill\vss}
-\setvalue{\??ly:\c!location:\empty }{\setfalse\page_location_is_set % default also signal to scrn_
- \let\page_location_right_fill \hss
- \let\page_location_bottom_fill\hss}
-\setvalue{\??ly:\c!location:\v!doublesided}{\doublesidedprinttrue}
-\setvalue{\??ly:\c!location:\v!singlesided}{\doublesidedprintfalse}
-
-\def\dopresetcenterpagebox#1%
- {\ifcsname\??ly:\c!location:#1\endcsname\csname\??ly:\c!location:#1\endcsname\fi}
-
-\def\presetcenterpagebox
- {\doublesidedprintfalse
- \page_location_reset
- \processcommacommand[\@@lylocation]\dopresetcenterpagebox}
-
-\unexpanded\def\definelayout
- {\dodoubleargument\dodefinelayout}
-
-\def\dodefinelayout[#1][#2]%
- {\getparameters[\??ly#1][\c!state=\v!start,#2]}
-
-\def\dodosetuplayout[#1][#2]%
- {\doifnot{#2}\v!reset{\getparameters[\??ly#1][#2]}}
-
-% global needed for non-doublesided standardmakeup
-
-\unexpanded\def\setuplayout
- {\dodoubleempty\dosetuplayout}
-
-\def\dosetuplayout[#1][#2]%
- {\globallet\currentlayout\empty
- \ifsecondargument
- \dodosetuplayout[#1][#2]%
- \else\iffirstargument
- \doifassignmentelse{#1}
- {\dodosetuplayout[][#1]}
- {\doifelse{#1}\v!reset
- {\let\@@lymethod\v!normal}% hardcodes, assumes a definition
- {\xdef\currentlayout{#1}}}%
- \fi\fi
- \recalculatelayout
- %\checkcurrentlayout % here?
- \dochecknextlayout % here?
- \presetcenterpagebox}
-
-\def\installlayouthandler#1#2%
- {\setgvalue{\??ly:\c!method:#1}{#2}}
-
-\installlayouthandler\v!default
- {\checkcurrentlayout}
-
-\installlayouthandler\v!normal
- {\checkcurrentlayout}
-
-\def\dochecknextlayout
- {\executeifdefined{\??ly:\c!method:\@@lymethod}\checkcurrentlayout}
-
-\let\@@zaheight\!!zeropoint
-
-\def\dopushpagedimensions
- {\xdef\oldtextheight {\the\textheight }%
- \xdef\oldfooterheight{\the\footerheight}%
- \global\let\@@zaheight\@@zaheight}
-
-\def\dopoppagedimensions
- {\global\textheight \oldtextheight
- \global\footerheight\oldfooterheight
- \recalculatelayout
- \global\let\pushpagedimensions\dopushpagedimensions
- \global\let\poppagedimensions\relax}
-
-\let\poppagedimensions \relax
-\let\pushpagedimensions\dopushpagedimensions
-
-% Elke \csname ... \endcsname wordt ook aangemaakt, dus ook
-% in een test met \doifdefined. Bij veel bladzijden kan dit
-% te veel macro's kosten. Vandaar de set \adaptedpages. Het
-% kost tijd, maar scheelt macro's.
-
-\let\adaptedpages\empty
-
-\def\adaptpagedimensions
- {\ifx\adaptedpages\empty\else
- \adaptpagedimensionsindeed
- \fi}
-
-\def\adaptpagedimensionsindeed
- {\rawdoifinset\realfolio\adaptedpages
- {\removefromcommalist\realfolio\adaptedpages
- \getvalue{\??za\realfolio}%
- \letbeundefined{\??za\realfolio}}}
-
-\def\checkpagedimensions
- {\poppagedimensions
- \adaptpagedimensions}
-
-\def\reportpagedimensions
- {\ifx\poppagedimensions\relax \else
- \space\the\dimexpr\@@zaheight\relax\space-\space
- \fi
- \realfolio}
-
-\def\dodoadaptlayout[#1]%
- {\getparameters[\??za][\c!height=,\c!lines=0,#1]%
- \pushpagedimensions
- \ifcase\@@zalines\relax
- \showmessage\m!layouts1{\@@zaheight,\realfolio}%
+% 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
+
+\def\page_layouts_location_reset % we start in the left top and mirror right pages
+ {\setfalse\c_page_layouts_location_is_set
+ \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
+ \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
+ \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
+ \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
+ \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
+ \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_
+ \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}
+
+\unexpanded\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
+
+\def\installlayoutalternative#1#2%
+ {\setgvalue{\??layoutalternative#1}{#2}}
+
+\def\page_boxes_construct_content_default#1#2#3% targetbox flusher box
+ {\setbox#1\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
- \showmessage\m!layouts1{\@@zalines\space\v!lines,\realfolio}%
- \def\@@zaheight{\@@zalines\openlineheight}%
- \fi
- \doifelse\@@zaheight\v!max
- {\balancedimensions\textheight\footerheight\footerheight}
- {\balancedimensions\textheight\footerheight\@@zaheight}%
- \ifdim\footerheight<\zeropoint
- \global\advance\textheight \footerheight
- \global\footerheight\zeropoint
- \global\xdef\@@zaheight{\layoutparameter\c!footer\space(\v!max)}%
- \fi
- \setvsize
- \global\pagegoal\vsize % nog corrigeren voor insertions ?
- \recalculatebackgrounds
- \global\let\pushpagedimensions\relax
- \global\let\poppagedimensions\dopoppagedimensions}
-
-\def\doadaptlayout[#1][#2]%
- {\doifelsenothing{#2}
- {\dodoadaptlayout[#1]}
- {\def\docommand##1%
- {\addtocommalist{##1}\adaptedpages
- \setgvalue{\??za##1}{\dodoadaptlayout[#2]}}%
- \processcommalist[#1]\docommand
- \adaptpagedimensions}}
-
-\def\adaptlayout
- {\dodoubleempty\doadaptlayout}
-
-% describe interface
-
-%D Centering the paper area on the print area is determined
-%D by the \type {top}, \type {bottom}, \type {left} and \type
-%D {right} parameters.
-
-\def\centerpagebox#1% we could test for a difference (saves packing)
- {\printpaperwidth \paperscale\printpaperwidth
- \printpaperheight\paperscale\printpaperheight
- \ifdim\printpaperheight>\ht#1\relax
- \donetrue
- \else\ifdim\printpaperwidth>\wd#1\relax
- \donetrue
- \else
- \donefalse
- \fi\fi
- \ifdone
- \setbox#1\vbox to \printpaperheight
- {\@@pptop
- \page_location_top_fill
- \hbox to \printpaperwidth
- {\ifdoublesidedprint
- \doifbothsides
- {\@@ppleft \page_location_left_fill \box#1\page_location_right_fill\@@ppright}%
- {\@@ppleft \page_location_left_fill \box#1\page_location_right_fill\@@ppright}%
- {\@@ppright\page_location_right_fill\box#1\page_location_left_fill \@@ppleft }%
- \else
- \@@ppleft \page_location_left_fill \box#1\page_location_right_fill\@@ppright
- \fi}%
- \par
- \page_location_bottom_fill
- \@@ppbottom}%
- \fi}
-
-\def\offsetprintbox#1%
- {\ifdim\topoffset=\zeropoint % \relax
- \ifdim\backoffset=\zeropoint
- \donefalse
- \else
- \donetrue
- \fi
- \else
- \donetrue
- \fi
- \ifdone
- \edef\next{\wd#1\the\wd#1\ht#1\the\ht#1\dp#1\the\dp#1}%
- \setbox#1\vbox
- {\offinterlineskip
- \vskip\topoffset
- \hskip\doifbothsides\backoffset\backoffset{-\backoffset}%
- \box#1}%
- \next
- \fi}
-
-\def\replicatepagebox#1%
- {\ifnum\@@lynx>\plusone
- \donetrue
- \else\ifnum\@@lyny>\plusone
- \donetrue
- \else
- \donefalse
- \fi\fi
- \ifdone
- \setbox#1\vbox
- {\offinterlineskip
- \dorecurse\@@lyny
- {\hbox{\dorecurse\@@lynx{\copy#1\hskip\@@lydx}\unskip}%
- \vskip\@@lydy}
- \unskip}%
- \fi}
+ \v!normal
+ \fi\endcsname}
-\def\orientpagebodybox#1#2#3%
- {\ifnum\number#1\number#2>\zerocount
- \setbox#3\vbox
- {\edef\somerotation{\number\ifdoublesided\ifodd\realpageno#1\else#2\fi\else#1\fi}%
- \dorotatebox\somerotation\hbox{\box#3}}%
- \fi}
+%D \macros
+%D {adaptlayout}
-\def\orientpaperbox{\orientpagebodybox\paperorientation\paperreverse}
-\def\orientprintbox{\orientpagebodybox\printorientation\printreverse}
+\installcorenamespace{pageadaptations}
-\def\mirrorpagebodybox#1#2%
- {\ifconditional#1\relax
- \setbox#2\vbox{\domirrorbox\vbox{\box#2}}%
- \fi}
+\newdimen\d_page_adepts_pushed_text_height
+\newdimen\d_page_adepts_pushed_footer_height
+\newdimen\d_page_adepts_height
-\def\mirrorpaperbox{\mirrorpagebodybox\papermirror}
-\def\mirrorprintbox{\mirrorpagebodybox\printmirror}
+\unexpanded\def\adaptlayout
+ {\dodoubleempty\page_adapts_layout}
-\def\scalepagebox#1%
- {\ifdim\@@lyscale\points=\onepoint
- \ifdim\@@lysx\points=\onepoint
- \ifdim\@@lysy\points=\onepoint
- \else
- \doscalepagebox{#1}\@@lysx\@@lysy
- \fi
- \else
- \doscalepagebox{#1}\@@lysx\@@lysy
- \fi
+\def\page_adapts_layout[#1][#2]%
+ {\ifsecondargument
+ \processcommalist[#1]{\page_adapts_layout_register{#2}}%
+ \page_adapts_check
\else
- \doscalepagebox{#1}\@@lyscale\@@lyscale
- \fi}
-
-\def\doscalepagebox#1#2#3%
- {\setbox#1\vbox{\scale[\c!sx=#2,\c!sy=#3]{\box#1}}%
- \paperwidth #2\paperwidth
- \paperheight#3\paperheight}
-
-\def\negateprintbox#1%
- {\ifnegateprintbox
- \negatecolorbox{#1}%
+ \page_adapts_layout_indeed{#1}%
\fi}
-\def\pagecutmarksymbol {\the\realpageno}
-\def\pagecutmarklength {.5cm}
-\let\pagecutmarktoptext \empty
-\let\pagecutmarkbottomtext \empty
+\def\page_adapts_layout_register#1#2%
+ {\setgvalue{\??pageadaptations#2}{\page_adapts_layout_indeed{#1}}}
-\def\extrapagecutmarkbottomtext
- {\rlap{\jobname}\hfill\currentdate\space-\space\currenttime\hfill\llap{\realfolio}}
+\def\page_adapts_layout_indeed#1%
+ {\getparameters[\??za][\c!height=\zeropoint,\c!lines=0,#1]%
+ \page_adepts_push
+ \doifelse\@@zaheight\v!max
+ {\global\d_page_adepts_height\footerheight}
+ {\global\d_page_adepts_height\dimexpr
+ \ifnum\@@zalines=\zerocount
+ \@@zaheight
+ \else
+ \@@zalines\openlineheight
+ \fi
+ \relax
+ \ifdim\d_page_adepts_height>\footerheight
+ \global\d_page_adepts_height\footerheight
+ \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
+ \global\pagegoal\vsize
+ %
+ \page_backgrounds_recalculate
+ \global\let\page_adepts_push\relax
+ \global\let\page_adepts_pop\page_adepts_pop_indeed}
-\def\makepagecutbox % #1
- {\let\cutmarksymbol \pagecutmarksymbol
- \let\cutmarklength \pagecutmarklength
- \let\cutmarktoptext \pagecutmarktoptext
- \let\cutmarkbottomtext\pagecutmarkbottomtext
- \makecutbox}
+\def\page_adapts_check
+ {\ifcsname\??pageadaptations\the\realpageno\endcsname
+ \page_adapts_check_indeed
+ \fi}
-\setvalue{\??ly:n:\c!marking:\v!on}%
- {\makepagecutbox}
+\def\page_adapts_check_indeed
+ {\getvalue{\??pageadaptations\the\realpageno}%
+ \letvalue{\??pageadaptations\the\realpageno}\relax}
-\setvalue{\??ly:n:\c!marking:\v!page}% only at outer when nx/ny > 0
- {\makepagecutbox}
+\def\page_adepts_push_indeed
+ {\global\d_page_adepts_pushed_text_height \textheight
+ \global\d_page_adepts_pushed_footer_height\footerheight}
-\setvalue{\??ly:n:\c!marking:\v!empty}%
- {\let\pagecutmarksymbol\empty
- \let\pagecutmarktoptext\empty
- \let\pagecutmarkbottomtext\empty
- \makepagecutbox}
+\def\page_adepts_pop_indeed
+ {\global\textheight \d_page_adepts_pushed_text_height
+ \global\footerheight\d_page_adepts_pushed_footer_height
+ \page_layouts_synchronize
+ \global\let\page_adepts_push\page_adepts_push_indeed
+ \global\let\page_adepts_pop\relax}
-\setvalue{\??ly:n:\c!marking:\v!text}%
- {\let\pagecutmarksymbol\empty
- \let\pagecutmarkbottomtext\extrapagecutmarkbottomtext
- \makepagecutbox}
+\let\page_adepts_pop \relax
+\let\page_adepts_push\page_adepts_push_indeed
-\setvalue{\??ly:c:\c!marking:\v!color}%
- {\doaddpagecolormarks\colormarkbox}
+\unexpanded\def\page_adapts_synchronize % used elsewhere
+ {\page_adepts_pop
+ \page_adapts_check}
-\setvalue{\??ly:c:\c!marking:\v!screen}%
- {\doaddpagecolormarks\rastermarkbox}
+\def\page_adapts_status_info % used elsewhere
+ {\ifx\page_adepts_pop\relax \else
+ \space(adept: \the\d_page_adepts_height)\space
+ \fi
+ \the\realpageno}
-\letvalue{\??ly:c:\c!marking:\v!unknown}\gobbleoneargument
-\letvalue{\??ly:n:\c!marking:\v!unknown}\gobbleoneargument
+%D \macros
+%D {startlayout,stoplayout}
-% \def\addpagecutmarks {\executeifdefined{\??ly:n:\c!marking:\@@lymarking}\gobbleoneargument}
-% \def\addpagecolormarks{\executeifdefined{\??ly:c:\c!marking:\@@lymarking}\gobbleoneargument}
+\unexpanded\def\startlayout[#1]%
+ {\page
+ \pushmacro\currentlayout
+ \doiflayoutdefinedelse{#1}{\setuplayout[#1]}\donothing} % {\setuplayout[\currentlayout]}}
-\def\addpagecutmarks {\expandcheckedcsname{\??ly:n:\c!marking:}\@@lymarking\s!unknown}
-\def\addpagecolormarks{\expandcheckedcsname{\??ly:c:\c!marking:}\@@lymarking\s!unknown}
+\unexpanded\def\stoplayout
+ {\page
+ \popmacro\currentlayout
+ \setuplayout[\currentlayout]}
-\def\doaddpagecolormarks#1#2%
- {\makepagecutbox{#2}%
- \ifnum\horizontalcutmarks>\plustwo \def\colormarkoffset{\plusfour}\fi
- \ifnum\verticalcutmarks >\plustwo \def\colormarkoffset{\plusfour}\fi
- #1{#2}}
-
% NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET
\ifx\doifelselayoutsomeline\undefined % defined in page-txt
@@ -1009,25 +1029,10 @@
\def\globalcompensatevsizeheader{\global\advance\textheight-\dimexpr\headerheight+\headerdistance\relax}
\def\globalcompensatevsizefooter{\global\advance\textheight-\dimexpr\footerheight+\footerdistance\relax}
-\def\compensatevsizeheaderzero{\headerheight\zeropoint\setlayoutdistances}
-\def\compensatevsizefooterzero{\footerheight\zeropoint\setlayoutdistances}
-
-\def\calculatevsizes
- {\textheight\makeupheight
- \doifelselayoutsomeline\v!header\compensatevsizeheader\donothing
- \doifelselayoutsomeline\v!footer\compensatevsizefooter\donothing
- \setvsizemodes
- \resetglobal
- \setvsize}
-
-\def\calculateglobalvsizes
- {\global\textheight\makeupheight
- \doifelselayoutsomeline\v!header\globalcompensatevsizeheader\donothing
- \doifelselayoutsomeline\v!footer\globalcompensatevsizefooter\donothing
- \setvsizemodes
- \setvsize}
+\def\compensatevsizeheaderzero{\headerheight\zeropoint\page_layouts_set_distances}
+\def\compensatevsizefooterzero{\footerheight\zeropoint\page_layouts_set_distances}
-\def\setvsizemodes
+\def\page_layouts_set_modes
{\ifzeropt\headerheight
\resetsystemmode\v!header
\else
@@ -1039,7 +1044,22 @@
\setsystemmode\v!footer
\fi}
-\def\calculatereducedvsizes
+\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}
+
+\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}
+
+\def\calculatereducedvsizes % name will change
{\textheight\makeupheight
\doifelselayoutsomeline\v!header\compensatevsizeheader\compensatevsizeheaderzero
\doifelselayoutsomeline\v!footer\compensatevsizefooter\compensatevsizefooterzero}
@@ -1052,25 +1072,28 @@
\def\compensatedinnermakeupmargin
{\dimexpr\ifconditional\innermakeupcompensation+\innermakeupmargin\else\zeropoint\fi\relax}
-\def\freezetextwidth % \makeupwidth may be set to \textwidth
- {\textwidth\makeupwidth % which is a tricky but valid value
- \doifsomething{\layoutparameter\c!textwidth}
- {\textwidth\layoutparameter\c!textwidth}% % local
+\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
- \doifelsenothing{\layoutparameter\c!textmargin}
- {\global\innermakeupmargin\zeropoint}
- {\global\innermakeupmargin\layoutparameter\c!textmargin}%
- \global\advance\innermakeupwidth-\dimexpr\innermakeupmargin+\innermakeupmargin\relax
- \advance\textwidth-\dimexpr\innermakeupmargin+\innermakeupmargin\relax} % local
+ \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
-\def\calculatehsizes
+\def\calculatehsizes % name will change
{\freezetextwidth
- \sethsize}
-
-% De onderstaande macro voert commando's uit, afhankelijk van
-% het karakter van het paginanummer.
-%
-% \doifoddpageelse{then-commando}{else-commando}
+ \page_otr_command_set_hsize}
+
+% The next few are better off in page-ini.mkiv
%D When we start at an even page, we need to swap the layout
%D differently. We cannot adapt the real page number, since
@@ -1080,6 +1103,8 @@
% We could use nested if here plus some \@EAEAEA's but but the
% next variant has less expansion which is nicer in tracing.
+% #single #left #right
+
\def\doifoddpageelse {\ifodd\pagenoshift\expandafter\doifoddpageelseyes \else\expandafter\doifoddpageelsenop \fi}
\def\doifoddpageelseyes{\ifodd\realpageno \expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments \fi}
\def\doifoddpageelsenop{\ifodd\realpageno \expandafter\firstoftwoarguments \else\expandafter\secondoftwoarguments\fi}
@@ -1111,7 +1136,7 @@
\newdimen\texthoffset
-\def\settexthoffset
+\def\settexthoffset % name will change
{\texthoffset\doifbothsides\backspace\backspace{\dimexpr\paperwidth-\backspace-\makeupwidth\relax}}
% The next hack is too tricky as we may shipout more pages:
@@ -1137,21 +1162,21 @@
% \prependtoks
% \freezepagestatechecks
% \to \everybeforeshipout
-
-\def\goleftonpage
+
+\def\goleftonpage % name will change (we could cache)
{\hskip-\dimexpr\leftmargindistance+\leftmarginwidth+\leftedgedistance+\leftedgewidth\relax}
\def\doifmarginswapelse#1#2%
{\doifbothsides{#1}{#1}{#2}}
-\def\swapmargins
+\def\swapmargins % name will change
{\doifmarginswapelse\relax\doswapmargins}
-\def\doswapmargins
+\def\doswapmargins % name will change
{\let\swapmargins \relax % to prevent local swapping
\let\doswapmargins\relax % to prevent local swapping
\the\everyswapmargins}
-
+
\def\rightorleftpageaction
{\ifdoublesided
\expandafter\rightorleftpageactionindeed
@@ -1210,15 +1235,15 @@
%D versions.
\unexpanded\def\startlocallayout
- {\globalpushmacro\restorepapersize
+ {\globalpushmacro\page_paper_restore
\globalpushmacro\currentlayout}
\unexpanded\def\stoplocallayout
{\globalpopmacro\currentlayout
- \globalpopmacro\restorepapersize
- \restorepapersize
- \setuplayout}
-
+ \globalpopmacro\page_paper_restore
+ \page_paper_restore
+ \setuplayout\relax}
+
%D \macros
%D {showprint, showframe, showlayout, showsetups}
%D
@@ -1250,25 +1275,6 @@
%D since they could change while going to a new page,
%D depending on the current font setting.
-\setuppaper % (size) % only used in XY imposition
- [\c!width=\zeropoint,
- \c!height=\zeropoint,
- \c!topspace=\zeropoint,
- \c!backspace=\zeropoint,
- \c!dx=\zeropoint,
- \c!dy=\zeropoint,
- \c!nx=1,
- \c!ny=1,
- \c!method=\v!normal]
-
-\setuppapersize
- [\c!option=\v!max,
- \c!top=,
- \c!bottom=,
- \c!left=,
- \c!right=,
- \c!location=]
-
\setuplayout
[ \c!topspace=.08417508418\paperheight, % 2.5cm
\c!top=\zeropoint,
@@ -1305,6 +1311,7 @@
\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,
@@ -1319,7 +1326,7 @@
\c!lines=0,
\c!paper=, % for foxet
\c!page=, % for foxet
- \c!columns=1,
+ \c!columns=\plusone,
\c!columndistance=\zeropoint]
%D First we define a whole range of (DIN) papersizes,
@@ -1374,13 +1381,15 @@
%D a bunch of sizes with $4:3$ ratios. The \type {S6} size is
%D nearly as wide as a sheet of \type {A4} 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 [SW] [\c!width=800pt,\c!height=450pt]
-\definepapersize [SM] [\c!width=720pt,\c!height=450pt]
+\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 [SW] [\c!width=800pt,\c!height=450pt]
+\definepapersize [SM] [\c!width=720pt,\c!height=450pt]
+\definepapersize [HD] [\c!width=1920pt,\c!height=1080pt]
+\definepapersize [HD+] [\c!width=1920pt,\c!height=1200pt]
%D These are handy too:
@@ -1468,6 +1477,11 @@
\c!height=\dimexpr\paperheight+1.5cm\relax]
\definepapersize
+ [undersized]
+ [ \c!width=\dimexpr\paperwidth -1.5cm\relax,
+ \c!height=\dimexpr\paperheight-1.5cm\relax]
+
+\definepapersize
[doublesized]
[ \c!width=\dimexpr \paperwidth \relax,
\c!height=\dimexpr2\paperheight\relax]
@@ -1481,19 +1495,15 @@
% [A4][A4]
\setuppapersize
- [A4][samesized]
+ [A4] % [samesized]
%D A few goodies:
-%D For orthogonality:
-
-\definepapersize
- [undersized]
- [ \c!width=\dimexpr\paperwidth -1.5cm\relax,
- \c!height=\dimexpr\paperheight-1.5cm\relax]
-
\definelayout
[\v!page]
+
+\setuplayout
+ [\v!page]
[\c!backspace=\zeropoint,
\c!cutspace=\zeropoint,
\c!topspace=\zeropoint,
diff --git a/Master/texmf-dist/tex/context/base/page-lin.lua b/Master/texmf-dist/tex/context/base/page-lin.lua
index 676a4c7f656..b830dbbb9ec 100644
--- a/Master/texmf-dist/tex/context/base/page-lin.lua
+++ b/Master/texmf-dist/tex/context/base/page-lin.lua
@@ -85,7 +85,8 @@ function lines.finalize(t)
local getnumber = lines.number
for _,p in next, t do
for _,r in next, p do
- if r.metadata.kind == "line" then
+ local m = r.metadata
+ if m and m.kind == "line" then
local e = r.entries
local u = r.userdata
e.linenumber = getnumber(e.text or 0) -- we can nil e.text
@@ -205,6 +206,10 @@ function boxed.stage_zero(n)
return identify(texbox[n].list)
end
+-- reset ranges per page
+-- store first and last per page
+-- maybe just set marks directly
+
function boxed.stage_one(n,nested)
current_list = { }
local head = texbox[n]
diff --git a/Master/texmf-dist/tex/context/base/page-lin.mkii b/Master/texmf-dist/tex/context/base/page-lin.mkii
index a04804ce6b8..c6b352ae73c 100644
--- a/Master/texmf-dist/tex/context/base/page-lin.mkii
+++ b/Master/texmf-dist/tex/context/base/page-lin.mkii
@@ -5,7 +5,7 @@
%D subtitle=Line Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-lin.mkiv b/Master/texmf-dist/tex/context/base/page-lin.mkiv
index 4f2226f6e33..7b1cbcd94aa 100644
--- a/Master/texmf-dist/tex/context/base/page-lin.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-lin.mkiv
@@ -5,14 +5,16 @@
%D subtitle=Line Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
% generic or not ... maybe not bother too much and simplify to mkiv only
-% get rid of \mk*
+% get rid of \mk* (left over from experimental times)
+%
+% to be redone (was experiment) .. can be hooked into margin code
\writestatus{loading}{ConTeXt Core Macros / Line Numbering}
@@ -68,7 +70,7 @@
{\setbox\linenumberscratchbox\vbox
{\forgetall
\offinterlineskip
- \ctxlua{nodes.lines.boxed.stage_one(\number#1,\ifcase\linenumbernesting false\else true\fi)}}%
+ \ctxlua{nodes.lines.boxed.stage_one(\number#1,\ifcase\linenumbernesting false\else true\fi)}}% #2
\ctxlua{nodes.lines.boxed.stage_two(\number#1,\number\linenumberscratchbox)}}% can move to lua code
% id nr shift width leftskip dir
@@ -93,7 +95,7 @@
{continue = "\linenumberparameter\c!continue"}
\def\mkdefinetextlinenumbering
- {\setxvalue{ln:c:\currentlinenumbering}{\number\ctxlua{tex.sprint(nodes.lines.boxed.register({\mklinenumberparameters}))}}}
+ {\setxvalue{ln:c:\currentlinenumbering}{\number\cldcontext{nodes.lines.boxed.register({\mklinenumberparameters})}}}
\def\mkupdatetextlinenumbering
{\ctxlua{nodes.lines.boxed.setup(\getvalue{ln:c:\currentlinenumbering},{\mklinenumberupdateparameters})}}
@@ -129,7 +131,7 @@
\attribute\linereferenceattribute\linerefcounter
#3%
% for the moment we use a simple system i.e. no prefixes etc .. todo: store as number
- \expanded{\dodosetreference{line}{#2}{conversion=\linenumberparameter\c!conversion}{\the\linerefcounter}}% kind labels userdata text
+ \expanded{\strc_references_set_named_reference{line}{#2}{conversion=\linenumberparameter\c!conversion}{\the\linerefcounter}}% kind labels userdata text
\endgroup}
\def\mkstartlinereference#1{\mksomelinereference{#1}{lr:b:#1}{}\ignorespaces}
@@ -176,11 +178,14 @@
\fi
\mksetuptextlinenumbering}
+% some day commandhandler
+
\def\linenumberparameter#1%
{\csname\??rn\ifcsname\??rn\currentlinenumbering#1\endcsname\currentlinenumbering\fi#1\endcsname}
-\def\linenumberattributes
- {\doattributes{\??rn\ifcsname\??rn\currentlinenumbering\c!style\endcsname\currentlinenumbering\fi}}
+\unexpanded\def\dolinenumberattributes#1#2%
+ {\dousestyleparameter{\linenumberparameter#1}%
+ \dousecolorparameter{\linenumberparameter#2}}
\setuplinenumbering
[\c!conversion=\v!numbers,
@@ -261,7 +266,7 @@
\the\aftereverylinenumbering
\endgroup}
-% number placement
+% number placement .. will change into (the new) margin code
\def\mkdoinnerlinenumber{\doifoddpageelse\mkdoleftlinenumber\mkdorightlinenumber}
\def\mkdoouterlinenumber{\doifoddpageelse\mkdorightlinenumber\mkdoleftlinenumber}
@@ -459,11 +464,11 @@
\ifconditional\faketextlinenumber
% we need to reserve space
\else
- \linenumberattributes\c!style\c!color
- {\linenumberparameter\c!command
- {\linenumberparameter\c!left
- \convertnumber{\linenumberparameter\c!conversion}{#3}%
- \linenumberparameter\c!right}}%
+ \dolinenumberattributes\c!style\c!color
+ \linenumberparameter\c!command
+ {\linenumberparameter\c!left
+ \convertnumber{\linenumberparameter\c!conversion}{#3}%
+ \linenumberparameter\c!right}%
\fi
\ifcase\linenumberlocation
\hss % middle
diff --git a/Master/texmf-dist/tex/context/base/page-log.mkii b/Master/texmf-dist/tex/context/base/page-log.mkii
index 18c7991b1b7..c64c27bce03 100644
--- a/Master/texmf-dist/tex/context/base/page-log.mkii
+++ b/Master/texmf-dist/tex/context/base/page-log.mkii
@@ -5,7 +5,7 @@
%D subtitle=Logos,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-mak.mkii b/Master/texmf-dist/tex/context/base/page-mak.mkii
index 2087a68400b..3a513137fe8 100644
--- a/Master/texmf-dist/tex/context/base/page-mak.mkii
+++ b/Master/texmf-dist/tex/context/base/page-mak.mkii
@@ -5,7 +5,7 @@
%D subtitle=Simple MakeUp,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-mak.mkiv b/Master/texmf-dist/tex/context/base/page-mak.mkiv
deleted file mode 100644
index ea285bcb8bc..00000000000
--- a/Master/texmf-dist/tex/context/base/page-mak.mkiv
+++ /dev/null
@@ -1,225 +0,0 @@
-%D \module
-%D [ file=page-mak, % copied from main-001,
-%D version=1997.03.31,
-%D title=\CONTEXT\ Page Macros,
-%D subtitle=Simple MakeUp,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 / MakeUp}
-
-\unprotect
-
-%D \macros
-%D {definemakeup, setupmakeup, startmakeup}
-%D
-%D A makeup is a separate page, like a title page or colofon.
-%D There is one standard makeup page, but you can define more
-%D if needed.
-%D
-%D \starttyping
-%D \startstandardmakeup
-%D My Fancy Title
-%D \stopstandardmakeup
-%D \stoptyping
-%D
-%D The associated commands are:
-%D
-%D \showsetup{definemakeup}
-%D \showsetup{setupmakeup}
-%D \showsetup{startmakeup}
-
-\unexpanded\def\definemakeup
- {\dodoubleargument\dodefinemakeup}
-
-\def\dodefinemakeup[#1][#2]%
- {\getparameters
- [\??do#1]%
- [\c!width=\innermakeupwidth, % example in manual / was \makeupwidth
- \c!height=\textheight, % example in manual
- \c!commands=,
- \c!setups=,
- \c!page=\v!right,
- \c!doublesided=\v!empty,
- \c!before=,
- \c!top=\vss,
- \c!bottom=\vss,
- \c!after=,
- \c!bottomstate=\v!normal,
- \c!topstate=\v!normal,
- \c!textstate=\v!normal,
- \c!headerstate=\v!stop,
- \c!footerstate=\v!stop,
- \c!pagestate=\v!stop, % in manual ! ! !
- \c!color=,
- \c!align=,
- #2]%
- \setvalue{\e!start#1\e!makeup}{\startmakeup[#1]}%
- \setvalue{\e!stop #1\e!makeup}{\stopmakeup}}
-
-\unexpanded\def\setupmakeup
- {\dodoubleargument\dosetupmakeup}
-
-\def\dosetupmakeup[#1]%
- {\getparameters[\??do#1]}
-
-%D This will save us some 375 bytes in the format file.
-
-\def\makeupparameter#1{\getvalue{\??do\currentmakeup#1}}
-
-%D The \type{\start}||\type{\stop} macros are used for both
-%D the direct and indirect way. The parameterless call will
-%D build a simple box.
-
-\newtoks\everymakeup
-
-\let\currentmakeup\empty
-
-\unexpanded\def\startmakeup
- {\dodoubleempty\dostartmakeup}
-
-\def\dostartmakeup[#1][#2]%
- {\bgroup
- \edef\currentmakeup{#1}%
- \the\everymakeup
- \iffirstargument
- \setupmakeup[\currentmakeup][#2]%
- \let\stopmakeup\dodostopmakeup
- \expandafter \dodostartmakeup
- \else
- \let\stopmakeup\donostopmakeup
- \expandafter \donostartmakeup
- \fi}
-
-%D The simple case:
-
-\def\donostartmakeup % textwidth ?
- {\page
- \setupheader[\c!state=\v!empty]%
- \setupfooter[\c!state=\v!empty]%
- \setsystemmode\v!makeup
- \vbox to \textheight\bgroup\hsize\textwidth}
-
-\def\donostopmakeup
- {\egroup
- \page
- \egroup}
-
-%D The normal one:
-
-\newbox\makeupbox
-
-\def\dodostartmakeup
- {\doifvaluesomething{\??do\currentmakeup\c!page}
- {\page[\makeupparameter\c!page]}%
- \pagetype[\currentmakeup]%
- \setsystemmode\v!makeup
- \setupmakeuplayout
- \makeupparameter\c!commands % hm, what is this one doing here ?
- \forgetall % else indented flush
- \global\setbox\makeupbox\vbox to \makeupparameter\c!height
- \bgroup
- \doifsomething{\makeupparameter\c!color}{\startcolor[\makeupparameter\c!color]}% can be made faster
- \doprocesslocalsetups{\makeupparameter\c!setups}%
- \hsize\makeupparameter\c!width
- \doifsomething{\makeupparameter\c!align}
- {\setupalign[\makeupparameter\c!align]}%
- \makeupparameter\c!top}
-
-\def\dodostopmakeup
- {\endgraf
- \makeupparameter\c!bottom
- \doifsomething{\makeupparameter\c!color}{\stopcolor}%
- \egroup
- \doflushmakeup
- \egroup
- \calculatehsizes
- \calculatevsizes}
-
-%D Selective page processing is handled here. (Why?)
-
-\def\doflushmakeup
- {\ifprocessingpages
- \ifpageselected
- \doshipoutmakeup
- \fi
- \else
- \ifpageselected \else
- \doshipoutmakeup
- \fi
- \fi
- \ifselectingpages
- \global\pageselectedfalse
- \fi}
-
-% \def\pushpagestate{\globalpushmacro\@@pnstate}
-% \def\poppagestate {\globalpopmacro \@@pnstate}
-
-\def\doshipoutmakeup
- {\pushpagestate % new
- \makeupparameter\c!before
- \setbox\makeupbox\vbox{\hbox{\color[\makeupparameter\c!color]{\box\makeupbox}}}%
- % \ifgridsnapping
- % new per 22/6/2006
- \ifdim\ht\makeupbox>\vsize
- \ht\makeupbox\vsize
- \fi
- % \fi
- \box\makeupbox
- \setuppagenumber[\c!state=\makeupparameter\c!pagestate]%
- \setupmakeuplayout
- \page
- \makeupparameter\c!after
- \relax % voor fi
- \ifdoublesided \ifodd\realpageno\else
- \processaction
- [\makeupparameter\c!doublesided]
- [ \v!yes=>\emptyhbox
- \page,
- \v!empty=>{\setupmakeuplayout
- \page[\v!blank]%
- \emptyhbox
- \page}]%
- \fi \fi
- \poppagestate} % new
-
-%D The text surrounding the main body text can be influenced
-%D by setting their associated status variables. The
-%D connection between them is made by the following macro
-
-\unexpanded\def\setupmakeuplayout
- {\setupfooter[\c!state=\makeupparameter\c!footerstate]%
- \setupheader[\c!state=\makeupparameter\c!headerstate]%
- \setuptext [\c!state=\makeupparameter\c!textstate]%
- \setupbottom[\c!state=\makeupparameter\c!bottomstate]%
- \setuptop [\c!state=\makeupparameter\c!topstate]%
- % this is needed, but no \setuplayout here; fails in texexec --fig=c
- \recalculatelayout}
-
-%D The standard page template is defined as follows:
-
-\definemakeup
- [\v!standard]
- [\c!width=\innermakeupwidth,
- \c!height=\textheight,
- \c!page=\v!right,
- \c!doublesided=\v!empty]
-
-\definemakeup
- [\v!text]
- [\c!topstate=\v!start,
- \c!headerstate=\v!start,
- \c!textstate=\v!start,
- \c!footerstate=\v!start,
- \c!bottomstate=\v!start,
- \c!doublesided=\v!no,
- \c!page=\v!yes,
- \c!top=\pseudostrut\ignorespaces,
- \c!bottom=\obeydepth\vss]
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-mak.mkvi b/Master/texmf-dist/tex/context/base/page-mak.mkvi
new file mode 100644
index 00000000000..f37c4f6135a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-mak.mkvi
@@ -0,0 +1,210 @@
+%D \module
+%D [ file=page-mak, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Simple MakeUp,
+%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 / MakeUp}
+
+\unprotect
+
+%D \macros
+%D {definemakeup, setupmakeup, startmakeup}
+%D
+%D A makeup is a separate page, like a title page or colofon.
+%D There is one standard makeup page, but you can define more
+%D if needed.
+%D
+%D \starttyping
+%D \startstandardmakeup
+%D My Fancy Title
+%D \stopstandardmakeup
+%D \stoptyping
+%D
+%D The associated commands are:
+%D
+%D \showsetup{definemakeup}
+%D \showsetup{setupmakeup}
+%D \showsetup{startmakeup}
+
+%D New is that we have a layout with the same name so one can set
+%D up a special layout tthat then gets used.
+
+\installcorenamespace{makeup}
+\installcorenamespace{makeupdoublesided}
+
+\installcommandhandler \??makeup {makeup} \??makeup
+
+\appendtoks
+ \setuevalue{\e!start\currentmakeup\e!makeup}{\startmakeup[\currentmakeup]}%
+ \setuevalue{\e!stop \currentmakeup\e!makeup}{\stopmakeup}%
+ \doiflayoutdefinedelse\currentmakeup\donothing{\definelayout[\currentmakeup]}% new
+\to \everydefinemakeup
+
+%D The \type{\start}||\type{\stop} macros are used for both
+%D the direct and indirect way. The parameterless call will
+%D build a simple box.
+
+\unexpanded\def\startmakeup
+ {\dodoubleempty\page_makeup_start}
+
+\let\stopmakeup\relax
+
+\def\page_makeup_start
+ {\iffirstargument
+ \expandafter\page_makeup_start_yes
+ \else
+ \expandafter\page_makeup_start_nop
+ \fi}
+
+%D The simple case: just a box with text dimensions.
+
+\unexpanded\def\page_makeup_start_nop[#name][#settings]% dummies
+ {\page
+ \setupheader[\c!state=\v!empty]%
+ \setupfooter[\c!state=\v!empty]%
+ \bgroup
+ \forgetall % else indented flush
+ \dontcomplain
+ \vbox to \textheight \bgroup
+ \setsystemmode\v!makeup
+ \hsize\textwidth
+ \let\stopmakeup\page_makeup_stop_nop}
+
+\unexpanded\def\page_makeup_stop_nop
+ {\egroup
+ \egroup
+ \page}
+
+%D The normal variant.
+
+\newbox \b_page_makeup
+\newtoks\t_page_makeup_every_setup
+
+\def\page_makeup_start_yes[#name][#settings]%
+ {\doifelsenothing{\namedmakeupparameter{#name}\c!page}
+ {\page}% new, so best not have dangling mess here like references (we could capture then and flush embedded)
+ {\page[\namedmakeupparameter{#name}\c!page]}%
+ \startlayout[#name]% includes \page
+ \bgroup
+ \edef\currentmakeup{#name}%
+ \setupcurrentmakeup[#settings]%
+ \setsystemmode\v!makeup
+ \the\t_page_makeup_every_setup
+ \makeupparameter\c!commands % hm, what is this one doing here ?
+ \forgetall % else indented flush
+ \dontcomplain
+ \global\setbox\b_page_makeup\vbox to \makeupparameter\c!height \bgroup
+ \usemakeupstyleandcolor\c!style\c!color
+ \hsize\makeupparameter\c!width
+ \setupalign[\makeupparameter\c!align]%
+ \doprocesslocalsetups{\makeupparameter\c!setups}% lua(..),xml(...,..),tex(..)
+ \makeupparameter\c!top
+ \let\stopmakeup\page_makeup_stop_yes}
+
+\unexpanded\def\page_makeup_stop_yes
+ {\endgraf
+ \makeupparameter\c!bottom
+ \egroup
+ \pushpagestate % new
+ \makeupparameter\c!before
+ \relax % to be sure we don't enter the \if
+ \ifdim\ht\b_page_makeup>\vsize
+ \ht\b_page_makeup\vsize % is already set to \textheight (maybe set dp to 0)
+ \fi
+ \setuppagenumber[\c!state=\makeupparameter\c!pagestate]%
+ \box\b_page_makeup
+ \the\t_page_makeup_every_setup
+ \page
+ \makeupparameter\c!after
+ \relax % to be sure we don't enter the \if
+ \ifdoublesided \ifodd\realpageno \else
+ \getvalue{\??makeupdoublesided\makeupparameter\c!doublesided}%
+ \fi \fi
+ \poppagestate % new
+ \egroup
+ \stoplayout} % includes \page
+
+\setvalue{\??makeupdoublesided\v!yes}%
+ {\emptyhbox
+ \page}
+
+\setvalue{\??makeupdoublesided\v!empty}%
+ {\the\t_page_makeup_every_setup
+ % == \page[\v!dummy]
+ \page[\v!blank]%
+ \emptyhbox
+ \page}
+
+%D The text surrounding the main body text can be influenced
+%D by setting their associated status variables. The
+%D connection between them is made by the following macro
+
+\appendtoks % this might need a revision
+ \setupfooter[\c!state=\makeupparameter\c!footerstate]%
+ \setupheader[\c!state=\makeupparameter\c!headerstate]%
+ \setuptext [\c!state=\makeupparameter\c!textstate]%
+ \setupbottom[\c!state=\makeupparameter\c!bottomstate]%
+ \setuptop [\c!state=\makeupparameter\c!topstate]%
+\to \t_page_makeup_every_setup
+
+%D The standard page template is defined as follows:
+
+\setupmakeup
+ [\c!width=\innermakeupwidth, % example in manual / was \makeupwidth
+ \c!height=\textheight, % example in manual
+ %\c!commands=,
+ %\c!setups=,
+ %\c!color=,
+ %\c!align=,
+ %\c!before=,
+ %\c!after=,
+ \c!page=\v!right,
+ \c!doublesided=\v!empty,
+ \c!top=\vss,
+ \c!bottom=\vss,
+ \c!bottomstate=\v!normal,
+ \c!topstate=\v!normal,
+ \c!textstate=\v!normal,
+ \c!headerstate=\v!stop,
+ \c!footerstate=\v!stop,
+ \c!pagestate=\v!stop] % in manual ! ! !
+
+\definemakeup
+ [\v!standard]
+ [\c!width=\innermakeupwidth,
+ \c!height=\textheight,
+ \c!page=\v!right,
+ \c!doublesided=\v!empty]
+
+\definemakeup
+ [\v!text]
+ [\c!topstate=\v!start,
+ \c!headerstate=\v!start,
+ \c!textstate=\v!start,
+ \c!footerstate=\v!start,
+ \c!bottomstate=\v!start,
+ \c!doublesided=\v!no,
+ \c!page=\v!yes,
+ \c!top=\pseudostrut\ignorespaces,
+ \c!bottom=\obeydepth\vss]
+
+\definemakeup
+ [\v!page]
+ []
+
+\definemakeup
+ [\v!middle]
+ [\v!standard]
+
+% \definelayout[standard]
+% \definelayout[text]
+
+\protect
diff --git a/Master/texmf-dist/tex/context/base/page-mar.mkii b/Master/texmf-dist/tex/context/base/page-mar.mkii
index 96223bafecf..d386d8ab93b 100644
--- a/Master/texmf-dist/tex/context/base/page-mar.mkii
+++ b/Master/texmf-dist/tex/context/base/page-mar.mkii
@@ -5,7 +5,7 @@
%D subtitle=Marginal Things,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-mar.mkiv b/Master/texmf-dist/tex/context/base/page-mar.mkiv
deleted file mode 100644
index 433364a0638..00000000000
--- a/Master/texmf-dist/tex/context/base/page-mar.mkiv
+++ /dev/null
@@ -1,808 +0,0 @@
-%D \module
-%D [ file=page-mar, % moved here from main-001
-%D version=1997.03.31,
-%D title=\CONTEXT\ Page Macros,
-%D subtitle=Marginal Things,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-\endinput % obsolete, also commented code in anch-pgr.mkiv
-
-%D Support for margin words is one of the reasons for writing
-%D \CONTEXT. Over time support for marginal content has been
-%D extended en enhanced. Therefore it's always good to watch
-%D out for unexpected side effects.
-
-%D TODO: use parents etc
-
-\writestatus{loading}{ConTeXt Page Macros / Marginal Things}
-
-\unprotect
-
-%D There are three categories and their historically grown meaning is
-%D as follows:
-%D
-%D marginlines: these are flushed relative to the start of a line and
-%D need to be invoked there.
-%D
-%D marginwords: these can be issued in the text flow and will migrate
-%D sidewards; in spite of the name, it can be a paragraph of text as
-%D well, but normally it's words.
-%D
-%D margintexts: these can be set beforehand and are flushed at the
-%D next paragraph of text (of header)
-%D
-%D While these mechanisms were rather separated, they now are slightly
-%D more integrated. Instead of low level instances we now have a mechanism
-%D for defining additional ones.
-
-%D \macros
-%D {inleftedge,inleftmargin,inrightmargin,inrightedge}
-%D
-%D The fast and clean way of putting things in the margin is
-%D using \type{\rlap} or \type{\llap}. Unfortunately these
-%D macro's don't handle indentation, left and right skips. We
-%D therefore embed them in some macro's that (force and)
-%D remove the indentation and restore it afterwards.
-
-\unexpanded\def\definemarginline
- {\dodoubleargument\dodefinemarginline}
-
-\def\dodefinemarginline[#1][#2]%
- {\getparameters
- [\??im\??im#1]
- [\c!location=\v!left,
- \c!distance=\zeropoint,
- \c!width=\leftmarginwidth,
- \c!hoffset=\leftmargindistance,
- \c!command=,
- #2]%
- \setuvalue{#1}{\dohandlemarginline{#1}}}
-
-\def\marginlineparameter#1{\csname\??im\??im\currentmarginline#1\endcsname}
-
-\def\marginlineexecuter#1#2%
- {\dostarttagged\t!margintext\currentmarginline
- \executeifdefined{\??im\??im\currentmarginline#1}{#2}%
- \dostoptagged}
-
-\def\dohandlemarginline#1%#2%
- {\def\currentmarginline{#1}%
- \csname\s!do\??im\??im\executeifdefined{\??im\??im#1\c!location}\v!left\endcsname{#1}}% {#2}
-
-\def\doleftmarginline#1#2% #1 is redundant (we can remove it when we group dohandlemarginline; maybe ...
- {\pushindentation
- \llap
- {\def\currentmarginline{#1}%
- \postsignalrightpage
- \hsize\marginlineparameter\c!width\relax
- \marginlineexecuter\c!command\firstofoneargument{#2}\relax
- \hskip\dimexpr
- +\leftskip
- +\compensatedinnermakeupmargin
- +\marginlineparameter\c!hoffset
- +\marginlineparameter\c!distance
- \relax}%
- \popindentation
- \ignorespaces}
-
-\def\dorightmarginline#1#2% #1 is redundant
- {\pushindentation
- \rlap
- {\def\currentmarginline{#1}%
- \postsignalrightpage
- \hskip\dimexpr
- +\hsize
- -\rightskip
- +\compensatedinnermakeupmargin
- +\marginlineparameter\c!hoffset
- +\marginlineparameter\c!distance
- \relax
- \hsize\marginlineparameter\c!width
- \marginlineexecuter\c!command\firstofoneargument{#2}}%
- \popindentation
- \ignorespaces}
-
-\long\def\installmarginlinehandler#1#2{\setvalue{\s!do\??im\??im#1}{#2}}
-
-\installmarginlinehandler \v!left {\doleftmarginline}
-\installmarginlinehandler \v!right {\dorightmarginline}
-\installmarginlinehandler \v!inner {\presignalrightpage\doifrightpageelse\doleftmarginline \dorightmarginline}
-\installmarginlinehandler \v!outer {\presignalrightpage\doifrightpageelse\dorightmarginline\doleftmarginline }
-
-\definemarginline[inleftmargin] [\c!location=\v!left, \c!width=\leftmarginwidth, \c!distance=\leftmargindistance, \c!hoffset=\zeropoint]
-\definemarginline[inrightmargin][\c!location=\v!right,\c!width=\rightmarginwidth,\c!distance=\rightmargindistance,\c!hoffset=\zeropoint]
-\definemarginline[inleftedge] [\c!location=\v!left, \c!width=\leftedgewidth, \c!distance=\leftedgedistance, \c!hoffset=\leftmargintotal]
-\definemarginline[inrightedge] [\c!location=\v!right,\c!width=\rightedgewidth, \c!distance=\rightedgedistance, \c!hoffset=\rightmargintotal]
-
-\definemarginline[inoutermargin][\c!location=\v!outer,\c!width=\outermarginwidth,\c!distance=\outermargindistance,\c!hoffset=\zeropoint]
-\definemarginline[ininnermargin][\c!location=\v!inner,\c!width=\innermarginwidth,\c!distance=\innermargindistance,\c!hoffset=\zeropoint]
-\definemarginline[inouteredge] [\c!location=\v!outer,\c!width=\outeredgewidth, \c!distance=\outeredgedistance, \c!hoffset=\outermargintotal]
-\definemarginline[ininneredge] [\c!location=\v!inner,\c!width=\inneredgewidth, \c!distance=\inneredgedistance, \c!hoffset=\innermargintotal]
-
-\definemarginline[atleftmargin] [\c!location=\v!left, \c!command=\lrlap,\c!width=\zeropoint,\c!distance=\zeropoint,\c!hoffset=\zeropoint]
-\definemarginline[atrightmargin][\c!location=\v!right,\c!command=\rllap,\c!width=\zeropoint,\c!distance=\zeropoint,\c!hoffset=\zeropoint]
-
-\def\lrlap#1{\llap{\rlap{#1}}}
-\def\rllap#1{\rlap{\hskip\hsize\llap{#1}}}
-
-%D We want to keep things efficient and therefore only handle
-%D situations like:
-%D
-%D \startbuffer
-%D \inleftedge {fine} some text \par
-%D \strut \inleftmargin {fine} some text \par
-%D \noindent \inrightmargin {fine} some text \par
-%D \noindent \strut \inrightedge {fine} some text \par
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D which looks like:
-%D
-%D \bgroup
-%D \getbuffer
-%D \parindent 30pt
-%D \getbuffer
-%D \egroup
-%D
-%D A torture test:
-%D
-%D \starttyping
-%D \def\TestLine#1#2{\backgroundline[#1]{\strut\white\tttf#2~\recurselevel}}
-%D
-%D \startbuffer
-%D \inleftmargin {\TestLine{red} {lm}} test test test \par
-%D \inrightmargin{\TestLine{green} {rm}} test test test \par
-%D \inleftedge {\TestLine{red} {le}} test test test \par
-%D \inrightedge {\TestLine{green} {re}} test test test \par
-%D \inoutermargin{\TestLine{blue} {om}} test test test \par
-%D \ininnermargin{\TestLine{yellow}{im}} test test test \par
-%D \inouteredge {\TestLine{blue} {oe}} test test test \par
-%D \ininneredge {\TestLine{yellow}{ie}} test test test \par
-%D \atleftmargin {\TestLine{red} {alm}} \hfill test \par
-%D \atrightmargin{\TestLine{green} {arm}} test \hfill \par
-%D \stopbuffer
-%D
-%D \dorecurse{40}\getbuffer \page
-%D \stoptyping
-
-%D New, yet undocumented:
-%D
-%D used for pascal:
-%D
-%D \starttyping
-%D \index {test} test \index {west} west \index {rest} rest
-%D
-%D \startnarrower
-%D \placeregister[index][alternative=b,command=\atleftmargin]
-%D \stopnarrower
-%D \stoptyping
-
-% todo: compensate distance when setuplayout[textwidth=..]
-% todo: generalize margin/edge model, now too much duplication
-
-%D The next bunch of macros looks messy which is due to its
-%D multi-purpose character.
-
-\setnewconstant\margincontentdisplacement \zerocount
-\let \margincontentdistance \!!zeropoint
-\let \margincontenthoffset \!!zeropoint
-\def \margincontentlines {1}
-\def \margincontenttag {0}
-\let \margincontentseparator \empty
-\def \margincontentstrutheight {\strutht}
-
-\newcount\margincontentlevel
-\newdimen\margincontentheight
-
-% \installparameterhandler \??im{inmargin}
-% \installparameterhashhandler\??im{inmargin}
-
-\unexpanded\def\setupinmargin
- {\dodoubleempty\dosetupinmargin}
-
-\def\dosetupinmargin[#1][#2]%
- {\ifsecondargument
- \processcommalist[#1]{\dodosetupinmargin[#2]}% becomes [#2]{##1}
- \else
- \getparameters[\??im][#1]%
- \fi}
-
-\def\dodosetupinmargin[#1]#2% [settings]{class}
- {\checkinmargin[#2]%
- \getparameters[\??im#2][#1]%
- % will become an \everyinmarginsetup thing
- \ifcase\executeifdefined{\??im#2\c!sidemethod}{0}\else
- \enableparpositions
- \fi}
-
-\def\checkinmargin[#1]%
- {\ifcsname\??im#1\c!offset\endcsname\else % this offset is related to framed !
- \addtocommalist{#1}\inmargintaglist
- \presetmargintext[#1]%
- \fi}
-
-\def\presetmargintext[#1]%
- {\presetlocalframed
- [\??im#1]%
- \getparameters
- [\??im#1]
- [\c!frame=\v!off,
- \c!offset=\v!overlay,
- \c!line=1,
- \c!separator=,
- \c!width=\v!broad,
- \c!distance=, % empty = signal
- \c!hoffset=\zeropoint,
- \c!style=\@@imstyle,
- \c!color=\@@imcolor,
- \c!strut=\@@imstrut,
- \c!location=\@@imlocation,
- \c!align=\@@imalign,
- \c!before=\@@imbefore,
- \c!after=\@@imafter]}
-
-\newdimen\naturalmargincontentheight
-
-\def\makemargintextblock#1#2#3% width l r content
- {\bgroup
- \forgetall % added, else problems with 'center' and nested itemize
- \dontcomplain
- \hsize\getvalue{\??im#1\c!width}\relax
- \doifnumberelse\margincontenttag
- {\ifcase\margincontenttag\relax
- \edef\margincontenttag{#1}% first one is setups id as well
- \fi}
- \donothing
- \doifnumberelse\margincontenttag
- {\ifnum\margincontenttag>25 % to be translated
- \writestatus\m!system{potential margin stack overflow (\margincontenttag)}%
- \fi}
- \donothing
- % we need to preserve {a,b,c} kind of settings
- \let\margincontentalign#1%
- \processallactionsinset
- [\getvalue{\??im\margincontenttag\c!align}]
- [ \v!yes=>\let\margincontentalign#1,
- \v!no=>\let\margincontentalign\v!normal,
- \v!inner=>\let\margincontentalign#1,
- \v!outer=>\let\margincontentalign#2,
- \v!flushright=>\let\margincontentalign\v!left,
- \v!left=>\let\margincontentalign\v!left,
- \v!middle=>\let\margincontentalign\v!middle,
- \v!flushleft=>\let\margincontentalign\v!right,
- \v!right=>\let\margincontentalign\v!right]%
- \doifvaluesomething{\??im\margincontenttag\c!align} % watch {} around set
- {\edef\margincontentalign{{\getvalue{\??im\margincontenttag\c!align},\margincontentalign}}}%
- %
- \expanded{\getparameters[\??im\margincontenttag][\c!align=\margincontentalign]}%
- %
- \edef\margincontentstrut{\getvalue{\??im\margincontenttag\c!strut}}%
- \savestrut %
- \setbox\scratchbox\vbox\localframed
- [\??im\margincontenttag]
- [\c!strut=\v!no,\c!offset=\v!overlay] % strut handled internally
- {\decrement\margincontentlines
- \dorecurse\margincontentlines{\savedstrut\endgraf\nointerlineskip}% ! savedstrut
- \@@imbefore
- \dostartattributes{\??im\margincontenttag}\c!style\c!color\empty
- \dosetupstrut[\margincontentstrut]% was: \setstrut % yes or no
- \dostarttagged\t!margintextblock\currentmargincontent % margincontenttag
- \begstrut#3\endstrut\endgraf
- \dostoptagged
- \xdef\margincontentstrutheight{\the\strutht}% so that it's known outside the framed
- \dostopattributes
- \@@imafter}%
- \global \naturalmargincontentheight\ht\scratchbox
- \global\advance\naturalmargincontentheight\dp\scratchbox
- \doif\@@imstack\v!yes
- {\def\overlappingmargin{-20\scaledpoint}% test value, maybe .25\strutboxdp, maybe configurable
- \setbox\scratchbox\vbox{\stackeddown\vbox{\box\scratchbox}}}% new
- \ht\scratchbox\strutht
- \dp\scratchbox\strutdp % nieuw
- \box\scratchbox
- \egroup}
-
-%D The stacker permits constructs like:
-%D
-%D \starttyping
-%D \setupinmargin[stack=yes]
-%D
-%D \inleft{test 1}test\break
-%D \inleft{test 2}test\break
-%D \inleft{test 1}
-%D \input tufte
-%D \inleft{test 1}
-%D \inleft{test 2}
-%D \inleft{test 3}
-%D \input tufte
-%D \inleft{test 1}
-%D \inleft{test 2\endgraf test 3}
-%D \inleft{test 4}
-%D \input tufte
-%D \inleft{test 1}
-%D \inleft{test 2\endgraf test 3}
-%D \inleft{test 4\endgraf test 5\endgraf test 6}
-%D \inleft{test 7\endgraf test 8\endgraf test 9}
-%D \input tufte
-%D \stoptyping
-
-%D This approach permits us to implement a better mechanism
-%D later. We need the \type {\graphicvadjust} in order to
-%D handle:
-%D
-%D \starttyping
-%D \inleft{test} {\red \dorecurse{40}{test }\par}
-%D {\red \inleft{test} \dorecurse{40}{test }\par}
-%D \stoptyping
-%D
-%D The outer margin color is either black or color set as
-%D main text color.
-
-\newif\ifrightmargin % documenteren
-
-\ifx\dopositionmarginbox\undefined
- \def\dopositionmarginbox#1{\graphicvadjust{\box#1}}
-\fi
-
-% watch out, margin dimensions are swapped locally (\swapmargins)
-
-% with \margincontentmethod one can control pagebreaks
-%
-% 0 no break
-% 1 each entry is one line
-% 2 only natural height
-% 3 also stack height
-
-\setnewconstant\margincontentmethod \plusthree % beware: 1 = old method
-\setnewconstant\marginpagecheckmethod \plusone
-\setnewconstant\marginrepositionmethod\plusone
-
-\def\margincontentextralines{1} % old method, play safe
-\def\nofmargincontentlines {0}
-
-\def\doplacemargintext#1#2#3#4%
- {\dontcomplain
- \strut
- \doifsomething{#1}
- {\def\margincontenttag{#1}}%
- \doifinsetelse{\margincontenttag}{\v!left,\v!right} % ugly hack
- {\let \margincontentdistance \empty % signal
- \let \margincontenthoffset \zeropoint}
- {\edef\margincontentdistance{\executeifdefined{\??im\margincontenttag\c!distance }\empty }% signal
- \edef\margincontenthoffset {\executeifdefined{\??im\margincontenttag\c!hoffset }\zeropoint}}%
- \edef\margincontentlines {\executeifdefined{\??im\margincontenttag\c!line }\plusone }%
- \edef\margincontentseparator {\executeifdefined{\??im\margincontenttag\c!separator}\donothing}%
- \setbox\scratchbox\hbox{#4}% % todo: make sure that color stack works
- \ifcase\margincontentmethod
- \scratchdimen\zeropoint
- \or % old method
- \scratchdimen\ht\scratchbox
- \advance\scratchdimen\dp\scratchbox
- \or
- \scratchdimen\naturalmargincontentheight
- \or
- \scratchdimen\naturalmargincontentheight
- \ifx\laststackvmove\undefined\else\global\advance\scratchdimen\laststackvmove\fi
- \fi
- \ifdim\scratchdimen>\margincontentheight
- \global\margincontentheight\scratchdimen
- \fi
- \setbox\scratchbox\hbox
- {#2{\hskip#3\strut
- \ifcase\margincontentdisplacement
- % normal, move strutheight up
- \scratchdimen\strutdp
- \advance\scratchdimen \margincontentstrutheight
- \advance\scratchdimen -\strutht
- \raise\scratchdimen
- \or
- % low, obey vadjust
- \fi
- \box\scratchbox}}%
- \ht\scratchbox\zeropoint
- \dp\scratchbox\zeropoint
- \gdef\margincontentstrutheight{\the\strutht}%
- %\graphicvadjust{\box\scratchbox}} % fails in high math lines, let it be
- %\hbox{\lower\strutdp\box\scratchbox}} % alas, wrong lapping, therefore useless
- \dopositionmarginbox\scratchbox}
-
-\def\domarginblockskip#1%
- {\doifelsenothing\margincontentdistance
- {\hskip\dimexpr
- +\margincontenthoffset
- +\compensatedinnermakeupmargin
- +\csname\??im#1\c!distance\endcsname
- \relax}
- {\hskip\dimexpr
- +\margincontenthoffset
- +\compensatedinnermakeupmargin
- +\margincontentdistance
- \relax}%
- \relax}
-
-\def\doleftmarginblock#1#2%
- {\doplacemargintext{#1}\llap\zeropoint
- {\llap{\placemargincontentseparator}%
- \makemargintextblock\v!left\v!right{#2}%
- \domarginblockskip\v!left}}
-
-\def\dorightmarginblock#1#2%
- {\doplacemargintext{#1}\rlap\hsize
- {\hskip\textwidth\hskip-\hsize % new: hsize correction
- \domarginblockskip\v!right
- \makemargintextblock\v!right\v!left{#2}%
- \rlap{\placemargincontentseparator}}}
-
-\unexpanded\def\placemargincontentseparator
- {\ifnum\margincontentlevel>\zerocount
- \ifx\margincontentseparator\empty\else
- \bgroup
- \scratchdimen\margincontentlines\lineheight
- \advance\scratchdimen -\lineheight
- \lower\scratchdimen\hbox{\margincontentseparator}%
- \egroup
- \fi
- \fi}
-
-\newbox\marginconstructbox
-
-\def\doinmarginswapped#1#2#3#4%
- {\iffirstsidefloatparagraph\nowhitespace\fi % zo laat mogelijk
- \setbox\marginconstructbox\hbox\bgroup % prevents page break in the middle of construction
- \startsignalrightpage
- \doifswappedrightpageelse
- {\rightmargintrue #2}
- {\rightmarginfalse#1}
- {#3}% setups
- {#4}% content
- \stopsignalrightpage
- \egroup
- \unhbox\marginconstructbox}
-
-% history made this a bit complicated, the +/- was needed before
-% we had enough mem/hash to do the page correction
-
-\edef\inmargintaglist{+,-,\v!low,\v!left,\v!right,\v!inner,\v!outer}
-
-% the problem is that we need to keep downward compatibility
-% with respect to the first argument thing a reference or a
-% directive; the alternative is to force users to pass a
-% directive along with a reference; anyhow, as long as one
-% does not use references that have the same name as a
-% directive we can use the (slow) alternative
-
-\def\doinmargin[#1][#2][#3][#4][#5]% #6 #7
- {\expanded{\doifinsetelse{#4}{\inmargintaglist}}
- {\dodoinmargin[#1][#2][#3][#4][#5]}
- {\dodoinmargin[#1][#2][#3][][#4]}}
-
-\unexpanded\def\defineinmargin
- {\doquadrupleempty\dodefineinmargin}
-
-\def\dodefineinmargin[#1][#2][#3][#4]%
- {\doifassignmentelse{#4}
- {\setupinmargin[#1][#4]%
- \setvalue{#1}{\indentation\doquintupleempty\doinmargin[#2][#3][#1]}}
- {\setvalue{#1}{\indentation\doquintupleempty\doinmargin[#2][#3][#4]}}}
-
-\defineinmargin [inleft] [\v!left] [\v!normal] % takes left settings
-\defineinmargin [inright] [\v!right] [\v!normal] % takes right settings
-\defineinmargin [ininner] [\v!inner] [\v!normal] % takes left/right settings
-\defineinmargin [inouter] [\v!outer] [\v!normal] % takes left/right settings
-\defineinmargin [inmargin] [\@@imlocation] [\v!normal] % takes left/right settings
-\defineinmargin [inother] [\@@imlocation] [\v!reverse] % takes left/right settings
-
-\def\inothermargin{\inother}
-
-%D This permits definitions like:
-%D
-%D \starttyping
-%D \defineinmargin [SomePlace] [inner] [normal] [distance=1cm]
-%D \defineinmargin [SomePlace] [inner] [normal] [SomePlace] \setupinmargin[SomePlace][distance=1cm]
-%D \defineinmargin [MyPlace] [inner] [normal] [SomePlace]
-%D \defineinmargin [YourPlace] [inner] [normal] [SomePlace]
-%D \stoptyping
-%D
-%D A torture test:
-%D
-%D \starttyping
-%D \startbuffer
-%D \inleft {\TestLine{red} {l}} test test test \par
-%D \inright {\TestLine{green} {r}} test test test \par
-%D \inmargin {\TestLine{blue} {m}} test test test \par
-%D \inothermargin{\TestLine{yellow} {x}} test test test \par
-%D \ininner {\TestLine{cyan} {i}} test test test \par
-%D \inouter {\TestLine{magenta}{o}} test test test \par
-%D \stopbuffer
-%D
-%D \dorecurse{80}\getbuffer \page
-%D \stoptyping
-%D
-%D and
-%D
-%D \starttyping
-%D \defineinmargin [InOuterA] [outer] [normal] [distance=0cm]
-%D \defineinmargin [InOuterB] [outer] [normal] [distance=1cm]
-%D \defineinmargin [InOuterC] [outer] [normal] [distance=2cm,line=2]
-%D
-%D \startbuffer
-%D \InOuterA{\TestLine{red} {A}} test test test \par
-%D \InOuterB{\TestLine{green}{B}} test test test \par
-%D \InOuterC{\TestLine{blue} {C}} test test test \par
-%D \stopbuffer
-%D
-%D \dorecurse{80}\getbuffer \page
-%D
-%D \dorecurse{10}{\inleft {one} test \inleft {two} test } \page
-%D
-%D \start
-%D \margintext {one} \margintext {two} \input thuan \par
-%D \setupinmargin[1][line=3,distance=1cm]
-%D \margintext [1]{one}
-%D \margintext [2]{two}
-%D \input thuan \page
-%D \stop
-%D
-%D \setupinmargin[3][location=inner,distance=1cm]
-%D \setupinmargin[4][location=outer,distance=2cm]
-%D
-%D % \setupinmargin[left] [line=2]
-%D % \setupinmargin[right][line=2]
-%D
-%D \dorecurse
-%D {10}
-%D {\margintext {\kern3cm\TestLine{blue}{none}}
-%D \margintext[3] {\TestLine{darkgray}{3}}
-%D \margintext[4] {\TestLine{darkgray}{4}}
-%D \margintext[left] {\TestLine{red} {left}}
-%D \margintext[right]{\TestLine{green} {right}}
-%D \margintext[inner]{\TestLine{cyan} {inner}}
-%D \margintext[outer]{\TestLine{magenta} {outer}}
-%D \input thuan \endgraf}
-%D
-%D \dorecurse{10}{\margintext{test\\test\\test} \input thuan \endgraf}
-%D \stoptyping
-
-% Test case:
-%
-% \setuppagenumbering[alternative=doublesided] \setupwhitespace[medium]
-%
-% \placefigure[right]{}{\externalfigure[dummy][width=2cm]}
-% \input tufte \inothermargin{test} \input tufte
-
-% test first
-%
-% setupsystem[random=1235]
-%
-% \setupinmargin[left][sidemethod=3]
-% \dorecurse{10}{test \fakewords{20}{40} test \inleft{test\\test} test \fakewords{20}{40} \par}
-% \page
-% \setupinmargin[left][sidemethod=4]
-% \dorecurse{40}{test \fakewords{50}{80} test \inleft{test\\test} \par}
-% \page
-
-\def\dodoinmargin[#1][#2][#3][#4][#5]#6%
- {\bgroup
- % old stuff, a bit tricky, but now interfaced
- \edef\currentmargincontent{#1}%
- \marginrepositionmethod\executeifdefined{\??im\currentmargincontent\c!sidemethod }\plusone
- \margincontentmethod \executeifdefined{\??im\currentmargincontent\c!textmethod }\plusthree
- \marginpagecheckmethod \executeifdefined{\??im\currentmargincontent\c!splitmethod}\plusone
- % so far
- \forgetall % otherwise sidefloat problems, added 2005/07/20, maybe dangerous
- \postponenotes % group is (somehow) needed
- \doifinsetelse\v!low{#4}
- {\margincontentdisplacement\plusone}
- {\margincontentdisplacement\zerocount}%
- \doif\v!reverse{#2}
- {\swapmacros\dorightmarginblock\doleftmarginblock}%
- \processaction
- [#1]
- [ \v!left=>\let\next\doleftmarginblock, % no swapping
- \v!right=>\let\next\dorightmarginblock, % no swapping
- \v!inner=>\def\next{\doinmarginswapped\dorightmarginblock\doleftmarginblock },
- \v!outer=>\def\next{\doinmarginswapped\doleftmarginblock \dorightmarginblock},
- \s!unknown=>\ifdoublesided
- \doifcommonelse{+,-}{#4}
- {\def\next{\doinmarginswapped\dorightmarginblock\doleftmarginblock }}
- {\def\next{\doinmarginswapped\doleftmarginblock \dorightmarginblock}}%
- \else
- \let\next\doleftmarginblock
- \fi]%
- \next{#3}{#6}%
- \pagereference[#5]% naar binnen ! ! ! !
- \flushnotes
- \egroup % don't forget the group
- \ignorespaces}
-
-% dit zijn voorlopig lokale commando's / vervallen
-%
-% \def\woordinmarge {\indentation\doquintupleempty\doinmargin[\@@implaats][\inleftmargin][\inrightmarge]}
-%
-% \def\woordinlinker {\inleftmargin } % vervallen
-% \def\woordinrechter{\inrechtermarge} % vervallen
-
-% Some day: \definemarking[\v!margetitel]
-
-%D Now come the margin text collectors. The collected content is
-%D flushed at every paragraph by the following macro. Note for
-%D myself: here the location (plaats) is no longer a tag (number).
-
-%D These are now all the same (long ago they had different
-%D implementations, somewhere in Sork time if I remember
-%D right).
-
-\def\margintext {\dodoubleempty\domargincontent}
-\def\marginword {\margintext}
-\def\margintitle{\margintext} % txt mark as well
-
-\newtoks\collectedmargintexts % so .. delayed!
-\newconditional\margintextcollected
-
-\def\domargincontent[#1][#2]#3% we used to check for #2/#1 being number, no longer now
- {\global\settrue\margintextcollected
- \global\let\flushmargincontents\doflushmargincontents
- \edef\margincontenttag{#1}%
- \ifx\margincontenttag\empty
- \global\advance\margincontentlevel\plusone
- \edef\margincontenttag{\number\margincontentlevel}%
- \fi
- \checkinmargin[\margincontenttag]%
- \doglobal \appendetoks
- \noexpand \checkinmargin[\margincontenttag]%
- \noexpand \doinmargin[\executeifdefined{\??im\margincontenttag\c!location}\@@imlocation][\v!normal][\margincontenttag][\margincontenttag][#2]%
- \to \collectedmargintexts
- \doglobal \appendtoks
- {#3}% argument to previously appended \doinmargin
- \to \collectedmargintexts}
-
-\def\doflushmargincontents % plural
- {\ifconditional\margintextcollected
- \expandafter\flushmargincontentsindeed
- \fi}
-
-\let\flushmargincontents\relax
-
-\def\flushmargincontentsindeed % links + rechts
- {\bgroup
- \forgetall
- \global\margincontentheight\zeropoint
- \startsignalrightpage
- \the\collectedmargintexts
- \signalrightpage
- \stopsignalrightpage
- \resetmargincontent
- % dirty tricks
- \ifcase\margincontentmethod
- \donefalse
- \else\ifinsidecolumns % brrrr
- \donetrue % how fuzzy
- \else\ifdim\margincontentheight>\lineheight\relax
- \donetrue % how dirty
- \else
- \donefalse % how needed
- \fi\fi\fi
- \savemargincontentlines
- \ifdone
- \advance\margincontentheight \margincontentextralines\lineheight
- \ifdim\pagegoal>\pagetotal
- \bgroup % preserve \margincontentheight
- \advance\margincontentheight \pagetotal
- \ifdim\margincontentheight>\pagegoal
- \egroup
- \ifcase\marginpagecheckmethod
- % disabled
- \or
- \setmargincontentpenalties
- \or
- % potentially dangerous, maybe better a \goodbreak; the problem is that
- % there can be a penalty there, which we then overload and we also introduce
- % nasty side effects, so, we drop this option
- % \vadjust pre {\page}%
- \fi
- \else
- \egroup
- \fi
- \fi
- \else % We need the above because interlinepenalties overrule vadjusted \nobreaks.
- % a bit dangerous
- \vadjust{\nobreak}%
- \fi
- \global\let\flushmargincontents\relax
- \egroup}
-
-\def\setmargincontentpenalties
- {\getnoflines\margincontentheight
- \keeplinestogether\noflines}
-
-\def\savemargincontentlines
- {\bgroup
- \advance\margincontentheight \margincontentextralines\lineheight % 1 by default
- \getnoflines\margincontentheight
- \xdef\nofmargincontentlines{\the\noflines}%
- \egroup}
-
-\def\fillupmargincontentlines % etex ! ! !
- {\endgraf
- \begingroup
- \scratchcounter\numexpr\nofmargincontentlines-\prevgraf\relax\relax
- \ifnum\scratchcounter>\zerocount
- \forgetall\dorecurse\scratchcounter{\nobreak\crlf}%
- \fi
- \endgroup}
-
-% Yet undocumented, for a manual flush in for instance headers.
-
-\def\resetmargincontent
- {\global\margincontentlevel\zerocount
- \global\setfalse\margintextcollected
- \global\collectedmargintexts\emptytoks}
-
-\unexpanded\def\placemargincontent
- {\ifconditional\margintextcollected % was level check
- \bgroup
- \redoconvertfont % !!
- %\setfalse\graphicvadjustmode % not used
- \flushmargincontentsindeed
- \egroup
- \fi}
-
-% For old times sake (i use it in project styles) we provide
-
-\unexpanded\def\placemargintexts {\placemargincontent}
-\def\resetmargetitels {\resetmargincontent}
-\def\margewoordpositie{\margewoord} % obsolete, now no longer range
-
-% but never use them yourself since they may disappear.
-
-\def\oplinker#1%
- {\strut
- \graphicvadjust
- {\dontcomplain
- \setbox\scratchbox\vtop{\forgetall\strut#1}%
- \getboxheight\scratchdimen\of\box\scratchbox
- \vskip-\scratchdimen % waarom stond hier een \ ?
- \box\scratchbox}}
-
-\setupinmargin
- [\c!style=\v!bold,
- \c!color=,
- \c!strut=\v!auto,
- \c!location=\v!both,
- \c!align=\v!inner,
- \c!stack=\v!no,
- \c!before=,
- \c!after=]
-
-\setupinmargin
- [\v!left]
- [\c!distance=\leftmargindistance,
- \c!width=\leftmarginwidth,
- %\c!align=\v!left, % no
- \c!location=\v!left]
-
-\setupinmargin
- [\v!right]
- [\c!distance=\rightmargindistance,
- \c!width=\rightmarginwidth,
- %\c!align=\v!right, % no
- \c!location=\v!right]
-
-% bonus needed when [inner/outer] is used as tag
-
-\setupinmargin[\v!inner][\c!location=\v!inner,\c!align=\v!inner]
-\setupinmargin[\v!outer][\c!location=\v!outer,\c!align=\v!inner]
-
-% more efficient (5K less fotmat file)
-%
-% \letvalue{\??im\v!inner\c!location}\v!inner \letvalue{\??im\v!inner\c!align}\v!inner
-% \letvalue{\??im\v!outer\c!location}\v!outer \letvalue{\??im\v!outer\c!align}\v!inner
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-mbk.mkvi b/Master/texmf-dist/tex/context/base/page-mbk.mkvi
new file mode 100644
index 00000000000..eb8061bf319
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-mbk.mkvi
@@ -0,0 +1,250 @@
+%D \module
+%D [ file=page-mbk, % was part of page-mis.mkiv / 2008.11.17
+%D version=2011.11.23, % was part of page-flt.tex / 2000.10.20
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Margin Floats,
+%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 / Margin Floats}
+
+\unprotect
+
+%D This is an old mechanism that is quite independent of other
+%D floats. There is for instance no save/restore used here. When
+%D there is need (and demand) we can use the float cache and then
+%D flush them in the text when they are left over. On the other
+%D hand, margin float are somewhat manual so it does not make too
+%D much sense to complicate the code. As an alternative users can
+%D fall back on margin texts: they do stack but don't float.
+%D
+%D \starttyping
+%D \dorecurse{9} {
+%D \placefigure[margin]{#1}{}
+%D \input ward
+%D }
+%D \page \null % will flush them
+%D \stoptyping
+
+% status=start: in margin
+% status=stop : in text
+%
+% todo: flush margin floats at end of text
+% todo: separate boxes for left and right
+
+\installcorenamespace{marginblock}
+\installcorenamespace{marginblocklocation}
+
+\installcommandhandler \??marginblock {marginblock} \??marginblock
+
+\let\setupmarginblocks\setupmarginblock
+
+\newconditional\c_page_margin_blocks_enabled % not really needed as we can check each time
+\newconditional\c_page_margin_blocks_present
+
+\newbox \b_page_margin_blocks
+\newbox \b_page_margin_blocks_prepared
+
+\appendtoks
+ \doifelse{\rootmarginblockparameter\c!state}\v!start
+ \settrue\setfalse\c_page_margin_blocks_enabled
+\to \everysetupmarginblock
+
+\setupmarginblocks
+ [\c!state=\v!start,
+ \c!location=\v!inmargin,
+ \c!width=\rightmarginwidth,
+ %\c!style=,
+ %\c!color=,
+ %\c!align=,
+ %\c!left=,
+ %\c!right=,
+ %\c!top=,
+ %\c!before=,
+ %\c!after=,
+ \c!inbetween=\blank,
+ \c!bottom=\vfill]
+
+\unexpanded\def\startmarginblock
+ {\dosingleempty\page_margin_blocks_start_block}
+
+\unexpanded\def\stopmarginblock
+ {\page_margin_blocks_stop_block}
+
+\def\page_margin_blocks_start_block[#tag]%
+ {\begingroup
+ \edef\currentmarginblock{#tag}%
+ \doifelse{\marginblockparameter\c!state}\v!start
+ \page_margin_blocks_start_block_yes
+ \page_margin_blocks_start_block_nop}
+
+\def\page_margin_blocks_stop_block
+ {\doifelse{\marginblockparameter\c!state}\v!start
+ \page_margin_blocks_stop_block_yes
+ \page_margin_blocks_stop_block_nop
+ \endgroup}
+
+\def\page_margin_blocks_start_block_yes % 2 maal \vbox ivm \unvbox elders
+ {\showmessage\m!layouts4\empty
+ \global\settrue\c_page_margin_blocks_present
+ \global\setbox\b_page_margin_blocks\vtop\bgroup\vbox\bgroup
+ \hsize\marginblockparameter\c!width
+ \ifvoid\b_page_margin_blocks\else
+ \unvbox\b_page_margin_blocks
+ \marginblockparameter\c!inbetween
+ \fi
+ \setupalign[\marginblockparameter\c!align]%
+ \usemarginblockstyleandcolor\c!style\c!color
+ \begstrut
+ \ignorespaces}
+
+\def\page_margin_blocks_stop_block_yes
+ {\removeunwantedspaces
+ \endstrut
+ \egroup
+ \egroup}
+
+\def\page_margin_blocks_start_block_nop
+ {\showmessage\m!layouts5\empty
+ \marginblockparameter\c!before
+ \bgroup
+ \usemarginblockstyleandcolor\c!style\c!color}
+
+\def\page_margin_blocks_stop_block_nop
+ {\egroup
+ \marginblockparameter\c!after}
+
+\def\page_margin_blocks_reshape
+ {\ifdim\ht\b_page_margin_blocks_prepared>\zeropoint
+ \beginofshapebox
+ \unvbox\b_page_margin_blocks_prepared
+ \endofshapebox
+ \reshapebox
+ {\box\shapebox}%
+ \setbox\b_page_margin_blocks_prepared\vbox to \textheight
+ {\marginblockparameter\c!top
+ \flushshapebox
+ \marginblockparameter\c!bottom}%
+ \fi}
+
+\unexpanded\def\checkmarginblocks
+ {\ifvoid\b_page_margin_blocks
+ \global\setfalse\c_page_margin_blocks_present
+ \else
+ \page_margin_blocks_check_indeed
+ \fi}
+
+\def\page_margin_blocks_check_indeed
+ {\ifcsname\??marginblocklocation\marginblockparameter\c!location\endcsname
+ \page_margin_blocks_prepare_box
+ \csname\??marginblocklocation\marginblockparameter\c!location\endcsname
+ \else
+ \global\setbox\b_page_margin_blocks\emptybox
+ \global\setfalse\c_page_margin_blocks_present
+ \fi}
+
+\def\page_margin_blocks_prepare_box
+ {\setbox\b_page_margin_blocks_prepared\vbox
+ {\forgetall
+ \splittopskip\topskip
+ \ifvoid\b_page_margin_blocks\else
+ \ifdim\ht\b_page_margin_blocks>\textheight
+ \vsplit\b_page_margin_blocks to \textheight
+ \else
+ \unvbox\b_page_margin_blocks
+ \fi
+ \fi}%
+ \page_margin_blocks_reshape
+ \setbox\b_page_margin_blocks_prepared\vbox
+ {\marginblockparameter\c!before
+ \box\b_page_margin_blocks_prepared
+ \marginblockparameter\c!after}}
+
+% inner outer
+
+\setvalue{\??marginblocklocation\v!left }{\page_margin_blocks_set_l_box}
+\setvalue{\??marginblocklocation\v!right }{\page_margin_blocks_set_r_box}
+\setvalue{\??marginblocklocation\v!inmargin}{\doifbothsidesoverruled
+ \page_margin_blocks_set_r_box
+ \page_margin_blocks_set_r_box
+ \page_margin_blocks_set_l_box}
+\setvalue{\??marginblocklocation\v!middle }{\doifbothsidesoverruled
+ \page_margin_blocks_set_r_box
+ \page_margin_blocks_set_l_box
+ \page_margin_blocks_set_r_box}
+
+\unexpanded\def\page_margin_blocks_place_r_yes
+ {\setbox\b_page_margin_blocks_prepared\hbox to \rightmarginwidth
+ {\marginblockparameter\c!left
+ \box\b_page_margin_blocks_prepared
+ \marginblockparameter\c!right}%
+ \vsmashbox\b_page_margin_blocks_prepared
+ \box\b_page_margin_blocks_prepared}
+
+\unexpanded\def\page_margin_blocks_place_l_yes
+ {\setbox\b_page_margin_blocks_prepared\hbox to \leftmarginwidth
+ {\marginblockparameter\c!right
+ \box\b_page_margin_blocks_prepared
+ \marginblockparameter\c!left}%
+ \vsmashbox\b_page_margin_blocks_prepared
+ \box\b_page_margin_blocks_prepared}
+
+\unexpanded\def\page_margin_blocks_place_r_nop{\hskip\rightmarginwidth}
+\unexpanded\def\page_margin_blocks_place_l_nop{\hskip\leftmarginwidth}
+
+\let\placerightmarginblock\page_margin_blocks_place_r_nop
+\let\placeleftmarginblock \page_margin_blocks_place_l_nop
+
+\def\page_margin_blocks_set_r_box{\let\placerightmarginblock\page_margin_blocks_place_r_yes}
+\def\page_margin_blocks_set_l_box{\let\placeleftmarginblock \page_margin_blocks_place_l_yes}
+
+% margin floats (keyword 'margin' in option list)
+
+\unexpanded\def\page_margin_blocks_process_float
+ {\doifelse{\marginblockparameter\c!state}\v!start
+ \page_margin_blocks_process_float_yes
+ \page_margin_blocks_process_float_nop}
+
+\def\page_margin_blocks_process_float_yes
+ {\global\setbox\b_page_margin_blocks\vbox
+ {\hsize\marginblockparameter\c!width
+ \unvcopy\b_page_margin_blocks
+ \ifvoid\b_page_margin_blocks\else
+ \expandafter\marginblockparameter\expandafter\c!inbetween
+ \fi
+ \box\floatbox
+ \filbreak}%
+ \ifdim\ht\b_page_margin_blocks>\textheight
+ % \dosavefloatinfo % no saving done anyway
+ \else
+ \doinsertfloatinfo
+ \fi}
+
+\def\page_margin_blocks_process_float_nop
+ {\handlefloatmethod\v!here}
+
+\def\page_margin_blocks_float_before
+ {\ifconditional\c_page_margin_blocks_enabled
+ \doifinset\v!margin\floatlocation\endgraf
+ \fi}
+
+\def\page_margin_blocks_float_set_hsize
+ {\ifconditional\c_page_margin_blocks_enabled
+ \doifinset\v!margin\floatlocation{\hsize\rootmarginblockparameter\c!width}%
+ \fi}
+
+\appendtoks
+ \ifvoid\b_page_margin_blocks \else
+ \writestatus\m!layouts{beware: there are left-over margin floats!}%
+ \fi
+\to \everystoptext
+
+\unexpanded\def\flushmarginblocks
+ {\page_otr_command_flush_margin_blocks}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-mis.lua b/Master/texmf-dist/tex/context/base/page-mis.lua
new file mode 100644
index 00000000000..4f9d3c3e208
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-mis.lua
@@ -0,0 +1,77 @@
+if not modules then modules = { } end modules ['page-mis'] = {
+ version = 1.001,
+ comment = "companion to page-mis.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: adapt message
+
+local sortedkeys = table.sortedkeys
+
+local cache = { }
+
+local function flush(page)
+ local c = cache[page]
+ if c then
+ for i=1,#c do
+ context.viafile(c[i])
+ end
+ cache[page] = nil
+ end
+end
+
+local function setnextpage()
+ local n = next(cache) and sortedkeys(cache)[1]
+ if not n then
+ n = 0 -- nothing in the cache
+ elseif n == 0 then
+ n = -1 -- generic buffer (0)
+ elseif n > 0 then
+ -- upcoming page (realpageno)
+ end
+ tex.setcount("global","c_page_postponed_blocks_next_page",n)
+end
+
+function commands.flushpostponedblocks(page)
+ -- we need to flush previously pending pages as well and the zero
+ -- slot is the generic one so that one is always flushed
+ local t = sortedkeys(cache)
+ local p = tonumber(page) or tex.count.realpageno or 0
+ for i=1,#t do
+ local ti = t[i]
+ if ti <= p then
+ flush(ti)
+ else
+ break
+ end
+ end
+ setnextpage()
+end
+
+function commands.registerpostponedblock(page)
+ if type(page) == "string" then
+ if string.find(page,"^+") then
+ page = tex.count.realpageno + (tonumber(page) or 1) -- future delta page
+ else
+ page = tonumber(page) or 0 -- preferred page or otherwise first possible occasion
+ end
+ end
+ if not page then
+ page = 0
+ end
+ local c = cache[page]
+ if not c then
+ c = { }
+ cache[page] = c
+ end
+ c[#c+1] = buffers.raw("postponedblock")
+ buffers.erase("postponedblock")
+ if page == 0 then
+ interfaces.showmessage("layouts",3,#c)
+ else
+ interfaces.showmessage("layouts",3,string.format("%s (realpage: %s)",#c,page))
+ end
+ setnextpage()
+end
diff --git a/Master/texmf-dist/tex/context/base/page-mis.mkii b/Master/texmf-dist/tex/context/base/page-mis.mkii
index bd029f896b2..a61b2435baf 100644
--- a/Master/texmf-dist/tex/context/base/page-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/page-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Misc Float Things,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-mis.mkiv b/Master/texmf-dist/tex/context/base/page-mis.mkiv
index 02083d1814e..6137bb462c9 100644
--- a/Master/texmf-dist/tex/context/base/page-mis.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-mis.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Misc Float Things,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,130 +13,11 @@
\writestatus{loading}{ConTeXt Page Macros / Misc Float Things}
+\registerctxluafile{page-mis}{1.001}
+
\unprotect
-\newif\ifmarginblocks
-
-\def\dosetupmarginblocks[#1]%
- {\getparameters[\??mb][#1]%
- \doifelse\@@mbstate\v!start
- {\showmessage\m!layouts4\empty
- \marginblockstrue
- \let\somenextfloat\dosomenextfloat
- \let\startmarginblock\dostartmarginblock
- \let\stopmarginblock\dostopmarginblock}%
- {\showmessage\m!layouts5\empty
- \marginblocksfalse
- \def\somenextfloat[##1]%
- {\someelsefloat[##1,\v!here]}%
- \let\startmarginblock\dontstartmargeblok
- \let\stopmarginblock\dontstopmargeblok}}
-
-\unexpanded\def\setupmarginblocks
- {\dosingleargument\dosetupmarginblocks}
-
-\newbox\marginbox
-
-\def\dosomenextfloat[#1]%
- {\global\setbox\marginbox\vbox
- {\hsize\@@mbwidth
- \unvcopy\marginbox
- \ifvoid\marginbox\else\expandafter\@@mbinbetween\fi
- \box\floatbox\filbreak}%
- \ifdim\ht\marginbox>\textheight
- % \dosavefloatinfo
- \else
- \doinsertfloatinfo
- \fi}
-
-\newbox\preparedmarginbox
-
-\def\reshapemargin
- {\ifdim\ht\preparedmarginbox>\zeropoint
- \beginofshapebox
- \unvbox\preparedmarginbox
- \endofshapebox
- \reshapebox
- {\box\shapebox}%
- \setbox\preparedmarginbox\vbox to \textheight
- {\@@mbtop
- \flushshapebox
- \@@mbbottom}%
- \fi}
-
-\unexpanded\def\placerightmarginblock
- {\hskip\rightmarginwidth}
-
-\unexpanded\def\placeleftmarginblock
- {\hskip\leftmarginwidth}
-
-\def\checkmarginblocks
- {\ifvoid\marginbox\else\docheckmarginblocks\fi}
-
-\def\docheckmarginblocks % erg inefficient
- {\setbox\preparedmarginbox\vbox
- {\forgetall
- \splittopskip\topskip
- \ifvoid\marginbox\else
- \ifdim\ht\marginbox>\textheight
- \vsplit\marginbox to \textheight
- \else
- \unvbox\marginbox
- \fi
- \fi}%
- \reshapemargin
- \setbox\preparedmarginbox\vbox
- {\@@mbbefore\box\preparedmarginbox\@@mbafter}%
- \def\rightmarginbox
- {\unexpanded\def\placerightmarginblock
- {\setbox\preparedmarginbox\hbox to \rightmarginwidth
- {\@@mbleft\box\preparedmarginbox\@@mbright}%
- \vsmashbox\preparedmarginbox
- \box\preparedmarginbox}}%
- \def\leftmarginbox
- {\unexpanded\def\placeleftmarginblock
- {\setbox\preparedmarginbox\hbox to \leftmarginwidth
- {\@@mbright\box\preparedmarginbox\@@mbleft}%
- \vsmashbox\preparedmarginbox
- \box\preparedmarginbox}}%
- \processaction % traag
- [\@@mblocation]
- [ \v!inmargin=>\doifbothsidesoverruled\rightmarginbox\rightmarginbox\leftmarginbox,
- \v!middle=>\doifbothsidesoverruled\rightmarginbox\leftmarginbox\rightmarginbox,
- \v!left=>\leftmarginbox,
- \v!right=>\rightmarginbox,
- \s!unknown=>\setbox\preparedmarginbox\emptyhbox]}
-
-\def\dostartmarginblock % 2 maal \vbox ivm \unvbox elders
- {\global\setbox\marginbox\vtop\bgroup\vbox\bgroup
- \hsize\@@mbwidth
- \ifvoid\marginbox\else
- \unvbox\marginbox
- \@@mbinbetween
- \fi
- \setupalign[\@@mbalign]%
- \dostartattributes\??mb\c!style\c!color{}%
- \begstrut\ignorespaces}
-
-\def\dostopmarginblock
- {\unskip\endstrut
- \dostopattributes
- \egroup
- \egroup}
-
-\def\dontstartmargeblok
- {\@@mbbefore
- \bgroup
- \dostartattributes\??mb\c!style\c!color\empty}
-
-\def\dontstopmargeblok
- {\dostopattributes
- \egroup
- \@@mbafter}
-
-\newcount\nofpostponedblocks
-
-\newif\ifinpostponing
+% postponing
\newevery\everytopofpage\relax
@@ -159,81 +40,56 @@
%
% \starttext \dorecurse{4}{\input tufte \page} \stoptext
-\newtoks \postponedpageblocks
-\newcount \nofpostponedpageblocks
-
-% \ifinpostponing: handhaven, want gebruikt in stijlen ! ! ! ! !
-
-\def\dodoflushpostponedblocks
- {\bgroup % we need the font switch, else problems inside split verbatim
- \setnormalcatcodes % postponing in verbatim
- \restoreglobalbodyfont
- \global\pagetotal\zeropoint
- \global\inpostponingtrue
- \the\postponedpageblocks
- \dorecurse\nofpostponedblocks
- {\getbuffer[pbuf-\recurselevel]}%
- \doflushfloats % new but potential dangerous
- \global\nofpostponedblocks\zerocount
- \global\inpostponingfalse
- \egroup}
-
-\def\doflushpostponedblocks
- {\ifinpostponing \else
- \ifcase\nofpostponedblocks \else \dodoflushpostponedblocks \fi
- \ifcase\nofpostponedpageblocks \else \dodoflushpostponedblocks \fi
- \fi}
-
-\def\doflushpostponedcontent
- {\bgroup
- \setsystemmode\v!postponing
- \the\everytopofpage
- %\flushrestfloats
- \doflushpagefloats
- \doflushpostponedblocks
- \egroup}
-
-\def\getpostponedblock#1#2%
- {\doif{#1}\realfolio{\getbuffer[rbuf-#2]}} % no \ifnum, avoid \fi
+%D There is no real need to use \LUA\ here but the bookkeeping
+%D is somewhat easier and we also can erase buffers easier when
+%D we keep a local cache, especially as we can flush per page.
-% beware, \dosingleempty conflicts with buffers (feeds back the \par)
+\newif \ifinpostponing % prevents nesting
+\newcount\c_page_postponed_blocks_next_page % set at the lua end
-\setvalue{\e!start\v!postponing}%
+\unexpanded\setvalue{\e!start\v!postponing}%
{\bgroup
\obeylines
- \doifnextoptionalelse{\egroup\nodostartpostponing}{\egroup\dodostartpostponing}}
-
-\def\nodostartpostponing[#1]%
- {\global\advance\nofpostponedpageblocks\plusone % hm, never reset?
- \bgroup % a little bit of misusing grouping
- \doifinstring{+}{#1}\advance \realpageno#1\relax % ugly but efficient
- \doglobal\appendetoks\noexpand\getpostponedblock
- {\realfolio}{\number\nofpostponedpageblocks}\to\postponedpageblocks
- \egroup
- \showmessage\m!layouts3{\number\nofpostponedpageblocks}%
- \dostartbuffer[rbuf-\number\nofpostponedpageblocks]%
- [\e!start\v!postponing][\e!stop\v!postponing]}
-
-\def\dodostartpostponing
- {\global\advance\nofpostponedblocks\plusone
- \showmessage\m!layouts3{\number\nofpostponedblocks}%
- \expanded{\dostartbuffer[pbuf-\number\nofpostponedblocks][\e!start\v!postponing][\e!stop\v!postponing]}}
-
-% Setups:
-
-\setupmarginblocks
- [\c!state=\v!start,
- \c!location=\v!inmargin,
- \c!width=\rightmarginwidth,
- \c!style=,
- \c!color=,
- \c!align=,
- \c!left=,
- \c!right=,
- \c!top=,
- \c!inbetween=\blank,
- \c!bottom=\vfill,
- \c!before=,
- \c!after=]
+ \doifnextoptionalelse{\egroup\page_postponed_blocks_start}{\egroup\page_postponed_blocks_start[0]}}
+
+\unexpanded\setvalue{\e!stop\v!postponing}%
+ {\ctxcommand{registerpostponedblock("\currentpostponedpage")}\relax}
+
+\def\page_postponed_blocks_start[#1]%
+ {\edef\currentpostponedpage{#1}%
+ \grabbufferdatadirect{postponedblock}{\e!start\v!postponing}{\e!stop\v!postponing}}
+
+% officially we should flush again after a flush as there can be new future pages
+% but that will be looked into when we run into it
+
+\unexpanded\def\page_postponed_blocks_flush_indeed
+ {\begingroup
+ \setsystemmode\v!postponing
+ \inpostponingtrue % for old times sake
+ \global\pagetotal\zeropoint % here? still needed? (was after flush pagefloats)
+ \the\everytopofpage\relax
+ %\flushrestfloats
+ \doflushpagefloats
+ \setnormalcatcodes % postponing in verbatim
+ \restoreglobalbodyfont % otherwise problems inside split verbatim
+ \ctxcommand{flushpostponedblocks()}%
+ \relax
+ \page_otr_command_flush_floats % new but potential dangerous, maybe we need a classification
+ \endgroup} % of blocks: with and without flush
+
+\def\page_postponed_blocks_flush
+ {\ifinpostponing
+ % probably a nested flush
+ \else\ifnum\c_page_postponed_blocks_next_page=\zerocount
+ % nothing in cache
+ \else\ifnum\c_page_postponed_blocks_next_page<\zerocount
+ % generic cache
+ \page_postponed_blocks_flush_indeed
+ \else\ifnum\c_page_postponed_blocks_next_page>\realpageno
+ % future content
+ \else
+ % pending content
+ \page_postponed_blocks_flush_indeed
+ \fi\fi\fi\fi}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-mrk.mkiv b/Master/texmf-dist/tex/context/base/page-mrk.mkiv
new file mode 100644
index 00000000000..5f8d332c56f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-mrk.mkiv
@@ -0,0 +1,202 @@
+%D \module
+%D [ file=page-mrk,
+%D version=2011.05.23, % moved from page-lay
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Cutmarks and Colorbars,
+%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 / Cutmarks and Colorbars}
+
+%D This module depends on \METAPOST.
+
+\unprotect
+
+% \def\pagecutmarksymbol {\the\realpageno}
+% \let\pagecutmarktoptext \empty
+% \let\pagecutmarkbottomtext \empty
+
+\def\pagecutmarklength {5mm}
+\def\pagecutmarkoffset {3mm} % slightly larger than before, and now a fixed size
+\def\pagecutmarkmargin{10cm}
+
+\newconditional\c_page_marks_add_more_color
+\newconditional\c_page_marks_add_more_marking
+\newconditional\c_page_marks_add_more_lines
+\newconditional\c_page_marks_add_page_lines
+\newconditional\c_page_marks_add_more_number
+
+\newcount\c_page_marks_nx
+\newcount\c_page_marks_ny
+
+\startuniqueMPgraphic{print:color}{w,h,l,o}
+ if unknown context_crop : input mp-crop.mpiv ; fi ;
+ page_marks_add_color(\MPvar w,\MPvar h,\MPvar l,\MPvar o) ;
+\stopuniqueMPgraphic
+
+\startuniqueMPgraphic{print:marking}{w,h,l,o}
+ if unknown context_crop : input mp-crop.mpiv ; fi ;
+ page_marks_add_marking(\MPvar w,\MPvar h,\MPvar l,\MPvar o) ;
+\stopuniqueMPgraphic
+
+\startuniqueMPgraphic{print:lines}{w,h,l,o,x,y}
+ if unknown context_crop : input mp-crop.mpiv ; fi ;
+ page_marks_add_lines(\MPvar w,\MPvar h,\MPvar l,\MPvar o,\MPvar x,\MPvar y) ;
+\stopuniqueMPgraphic
+
+\startuseMPgraphic{print:number}{w,h,l,o,n}
+ if unknown context_crop : input mp-crop.mpiv ; fi ;
+ page_marks_add_number(\MPvar w,\MPvar h,\MPvar l,\MPvar o,\MPvar n) ;
+\stopuseMPgraphic
+
+\def\page_marks_add_color
+ {\setlayoutcomponentattribute{\v!print:\v!color}%
+ \setbox\scratchbox\hbox \layoutcomponentboxattribute\bgroup
+ \uniqueMPgraphic
+ {print:color}%
+ {w=\the\scratchwidth,h=\the\scratchheight,%
+ l=\pagecutmarklength,o=\pagecutmarkoffset}%
+ \egroup
+ \wd\scratchbox\scratchwidth\ht\scratchbox\scratchheight\dp\scratchbox\scratchdepth
+ \hskip-\scratchwidth\box\scratchbox}
+
+\def\page_marks_add_marking
+ {\setlayoutcomponentattribute{\v!print:\v!marking}%
+ \setbox\scratchbox\hbox \layoutcomponentboxattribute\bgroup
+ \uniqueMPgraphic
+ {print:marking}%
+ {w=\the\scratchwidth,h=\the\scratchheight,%
+ l=\pagecutmarklength,o=\pagecutmarkoffset}%
+ \egroup
+ \wd\scratchbox\scratchwidth\ht\scratchbox\scratchheight\dp\scratchbox\scratchdepth
+ \hskip-\scratchwidth\box\scratchbox}
+
+\def\page_marks_add_lines
+ {\setlayoutcomponentattribute{\v!print:\v!lines}%
+ \setbox\scratchbox\hbox \layoutcomponentboxattribute\bgroup
+ \uniqueMPgraphic
+ {print:lines}%
+ {w=\the\scratchwidth,h=\the\scratchheight,%
+ l=\pagecutmarklength,o=\pagecutmarkoffset,%
+ x=\the\c_page_marks_nx,y=\the\c_page_marks_ny}%
+ \egroup
+ \wd\scratchbox\scratchwidth\ht\scratchbox\scratchheight\dp\scratchbox\scratchdepth
+ \hskip-\scratchwidth\box\scratchbox}
+
+\def\page_marks_add_number
+ {\setlayoutcomponentattribute{\v!print:\v!number}%
+ \setbox\scratchbox\hbox \layoutcomponentboxattribute\bgroup
+ \useMPgraphic
+ {print:number}%
+ {w=\the\scratchwidth ,h=\the\scratchheight,%
+ l=\pagecutmarklength,o=\pagecutmarkoffset,%
+ n=\number\ifcase\arrangeno\realpageno\else\arrangeno\fi}%
+ \egroup
+ \wd\scratchbox\scratchwidth\ht\scratchbox\scratchheight\dp\scratchbox\scratchdepth
+ \hskip-\scratchwidth\box\scratchbox}
+
+\def\page_marks_add_page_indeed#1%
+ {\setbox#1\hbox\bgroup
+ \let\objectoffset\pagecutmarkmargin
+ %\infofont
+ \scratchwidth \wd#1%
+ \scratchheight\ht#1%
+ \scratchdepth \dp#1%
+ \box#1\relax
+ \ifconditional\c_page_marks_add_page_lines
+ \page_marks_add_lines
+ \fi
+ \egroup}
+
+\def\page_marks_add_more_indeed#1%
+ {\setbox#1\hbox\bgroup
+ \let\objectoffset\pagecutmarkmargin
+ \infofont
+ \scratchwidth \wd#1% these can move out
+ \scratchheight\ht#1%
+ \scratchdepth \dp#1%
+ \box#1\relax
+ \ifconditional\c_page_marks_add_more_color
+ \page_marks_add_color
+ \fi
+ \ifconditional\c_page_marks_add_more_marking
+ \page_marks_add_marking
+ \fi
+ \ifconditional\c_page_marks_add_more_lines
+ \page_marks_add_lines
+ \fi
+ \ifconditional\c_page_marks_add_more_number
+ \page_marks_add_number
+ \fi
+ \egroup}
+
+\let\page_marks_add_page\gobbleoneargument
+\let\page_marks_add_more\gobbleoneargument
+
+\installcorenamespace{layoutmarking}
+
+\def\installpagecutmark#1#2%
+ {\setvalue{\??layoutmarking#1}{#2}}
+
+% \installpagecutmark\v!off
+% {}
+
+% \installpagecutmark\v!text
+% {\settrue\c_page_marks_add_more_lines
+% \settrue\c_page_marks_add_more_number
+% \let\pagecutmarksymbol\empty
+% \let\pagecutmarkbottomtext\extrapagecutmarkbottomtext}
+
+\installpagecutmark\v!on
+ {\settrue\c_page_marks_add_page_lines
+ \settrue\c_page_marks_add_more_lines
+ \settrue\c_page_marks_add_more_number}
+
+\installpagecutmark\v!page % todo
+ {\settrue\c_page_marks_add_more_lines
+ \settrue\c_page_marks_add_more_number}
+
+\installpagecutmark\v!empty
+ {\settrue\c_page_marks_add_page_lines
+ \settrue\c_page_marks_add_more_lines}
+
+\installpagecutmark\v!color
+ {\settrue\c_page_marks_add_page_lines
+ \settrue\c_page_marks_add_more_lines
+ \settrue\c_page_marks_add_more_color
+ \settrue\c_page_marks_add_more_marking
+ \settrue\c_page_marks_add_more_number}
+
+\appendtoks
+ \setfalse\c_page_marks_add_more_color
+ \setfalse\c_page_marks_add_more_marking
+ \setfalse\c_page_marks_add_more_lines
+ \setfalse\c_page_marks_add_more_number
+ \csname\??layoutmarking\layoutparameter\c!marking\endcsname
+ \ifconditional\c_page_marks_add_page_lines
+ \let\page_marks_add_page\page_marks_add_page_indeed
+ \else
+ \let\page_marks_add_page\gobbleoneargument
+ \fi
+ \ifconditional\c_page_marks_add_more_lines
+ \let\page_marks_add_more\page_marks_add_more_indeed
+ \else\ifconditional\c_page_marks_add_more_color
+ \let\page_marks_add_more\page_marks_add_more_indeed
+ \else\ifconditional\c_page_marks_add_more_marking
+ \let\page_marks_add_more\page_marks_add_more_indeed
+ \else\ifconditional\c_page_marks_add_more_number
+ \let\page_marks_add_more\page_marks_add_more_indeed
+ \else
+ \let\page_marks_add_more\gobbleoneargument
+ \fi\fi\fi\fi
+\to \everysetuplayout
+
+\setuplayout
+ [\c!marking=\v!off]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-mul.mkii b/Master/texmf-dist/tex/context/base/page-mul.mkii
index 801ae5d657a..decf784f04e 100644
--- a/Master/texmf-dist/tex/context/base/page-mul.mkii
+++ b/Master/texmf-dist/tex/context/base/page-mul.mkii
@@ -5,7 +5,7 @@
%D subtitle=Multi Column Output,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -615,11 +615,11 @@
\postprocesscolumns
\dohandleallcolumns % \hbox i.v.m. \showcomposition
{\global\setbox\currentcolumnbox\hbox to \localcolumnwidth
- {\box\currentcolumnbox
- \global\wd\currentcolumnbox\localcolumnwidth
- \ifheightencolumns
- \global\ht\currentcolumnbox\fixedcolumnheight
- \fi}}%
+ {\box\currentcolumnbox}%
+ \wd\currentcolumnbox\localcolumnwidth
+ \ifheightencolumns
+ \ht\currentcolumnbox\fixedcolumnheight
+ \fi}%
\setmaxcolumndimensions
\overlaycolumnfootnotes
\setbox\columnpagebox\vbox
@@ -1007,7 +1007,7 @@
\vfill
\fi}}%
\dohandleallcolumns
- {\global\ht\currentcolumnbox\dimen0}%
+ {\ht\currentcolumnbox\dimen0}% redundant
\fi
\setbox\precolumnbox\vbox{\flushcolumnedpage\zerocount}%
\finaloutput\box\precolumnbox
diff --git a/Master/texmf-dist/tex/context/base/page-mul.mkiv b/Master/texmf-dist/tex/context/base/page-mul.mkiv
index 581ba5a598a..3792f06ee25 100644
--- a/Master/texmf-dist/tex/context/base/page-mul.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-mul.mkiv
@@ -5,12 +5,16 @@
%D subtitle=Multi Column Output,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
+% SEE PAGE-MUL-NEW.MKIV
+
+% BEWARE: TEMPORARY ISSUES WITH VSIZE AND HSIZE BUT WILL BE REDONE
+
\writestatus{loading}{ConTeXt Page Macros / Simple Multi Column}
%D This module is mostly a copy from the original multi column
@@ -22,163 +26,57 @@
\unprotect
-% TO DO !
+\unexpanded\def\page_mul_command_side_float_output
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
-\let\OTRMULsetvsize \OTRONEsetvsize
-\let\OTRMULsethsize \OTRONEsethsize
-\let\OTRMULdopagecontents \OTRONEdopagecontents
-\let\OTRMULfinalsidefloatoutput\OTRONEfinalsidefloatoutput % ???
-\let\OTRMULflushfloatbox \OTRONEflushfloatbox
+\unexpanded\def\page_mul_command_flush_side_floats
+ {\page_sides_forget_floats}
-\let\OTRMULdosettopinserts \relax
-\let\OTRMULdosetbotinserts \relax
-\let\OTRMULdotopinsertions \relax
-\let\OTRMULdobotinsertions \relax
-\let\OTRMULdosetbothinserts \relax
-\let\OTRMULflushsavedfloats \relax
+\unexpanded\def\page_mul_command_synchronize_side_floats
+ {\page_sides_forget_floats}
-\let\OTRMULflushsidefloats \forgetsidefloats % \relax
-\let\OTRMULsynchronizesidefloats\forgetsidefloats % \relax
+\unexpanded\def\page_mul_command_next_page
+ {\page_otr_eject_page}
-\newtoks \OTRMULoutput
+\unexpanded\def\page_mul_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
-\def\OTRMULgotonextpage
- {\ejectpage}
-
-\def\OTRMULgotonextpageX % will become obsolete
- {\superejectpage}
-
% check \count<insert> multiplications
-% some day try this in balancing routine
-%
-% \ifdim\pagetotal>\pagegoal
-% \eject
-% \else
-% \goodbreak
-% \fi
-
-%D The following macro's implement a multi||column output
-%D routine. The original implementation was based on Donald
-%D Knuth's implementation, which was adapted by Craig Platt to
-%D support balancing of the last page. I gradually adapted
-%D Platt's version to our needs but under certain
-%D circumstances things still went wrong. I considered all
-%D calls to Platt's \type{\balancingerror} as undesirable.
-
-%D This completely new implementation can handle enough
-%D situations for everyday documents, but is still far from
-%D perfect. While at the moment the routine doesn't support
-%D all kind of floats, it does support:
+%D The following macro's implement a multi||column output routine. The original
+%D implementation was based on Donald Knuth's implementation, which was adapted by
+%D Craig Platt to support balancing of the last page. I gradually adapted Platt's
+%D version to our needs but under certain circumstances things still went wrong. I
+%D considered all calls to Platt's \type{\balancingerror} as undesirable.
+%D
+%D This completely new implementation can handle enough situations for everyday
+%D documents, but is still far from perfect. While at the moment the routine doesn't
+%D support all kind of floats, it does support:
%D
%D \startitemize[packed]
%D \item an unlimitted number of columns
%D \item ragged or not ragged bottoms
%D \item optional balancing without \type{\balancingerrors}
-%D \item different \type{\baselineskips}, \type{\spacing},
-%D \type{\topskip} and \type{\maxdepth}
+%D \item different \type{\baselineskips}, \type{\spacing}, \type {\topskip} and
+%D \type {\maxdepth}
%D \item left- and right indentation, e.g. within lists
%D \item moving columns floats to the next column or page
%D \item handling of floats that are to wide for a columns
%D \stopitemize
%D
-%D One could wonder why single and multi||columns modes are
-%D still separated. One reason for this is that \TeX\ is not
-%D suited well for handling multi||columns. As a result, the
-%D single columns routines are more robust. Handling one
-%D column as a special case of multi||columns is posible but at
-%D the cost of worse float handling, worse page breaking,
-%D worse etc. Complicated multi||column page handling should
-%D be done in \cap{DTP}||systems anyway.
+%D One could wonder why single and multi||columns modes are still separated. One
+%D reason for this is that \TeX\ is not suited well for handling multi||columns. As
+%D a result, the single columns routines are more robust. Handling one column as a
+%D special case of multi||columns is posible but at the cost of worse float
+%D handling, worse page breaking, worse etc. Complicated multi||column page handling
+%D should be done in \cap{DTP}||systems anyway.
%D
-%D There are three commands provided for entering and leaving
-%D multi||column mode and for going to the next column:
+%D There are three commands provided for entering and leaving multi||column mode and
+%D for going to the next column:
%D
%D \interface \type{\beginmulticolumns} \\ \\
%D \interface \type{\endmulticolumns} \\ \\
%D \interface \type{\ejectcolumn} \\ \\
-%D
-%D This routines are sort of stand||alone. They communicate
-%D with the rest of \CONTEXT\ by means of some interface
-%D macro's, which we only mention.
-%D
-%D \interface \type{\nofcolumns} \\
-%D the number of columns \\
-%D \interface \type{\minbalancetoplines} \\
-%D the minimum number op balanced top lines \\
-%D \interface \type{\betweencolumns} \\
-%D the stuff between columns \\
-%D \interface \type{\finaloutput{action}{box}} \\
-%D some kind of \type{\pagebody} and \type{\shipout} \\
-%D
-%D \interface \type{\ifbalancecolumns} \\
-%D balancing the colums or not \\
-%D \interface \type{\ifstretchcolumns} \\
-%D ragging the bottom or not \\
-%D
-%D \interface \type{\ifheightencolumns} \\
-%D fix the heigh tor not \\
-%D \interface \type{\fixedcolumnheight} \\
-%D the optional fixed height \\
-%D
-%D \interface \type{\ifinheritcolumns} \\
-%D handle ragging or not \\
-%D \interface \type{\ifr@ggedbottom} \\
-%D use ragged bottoms \\
-%D \interface \type{\ifb@selinebottom} \\
-%D put the bottom line on the baseline \\
-%D \interface \type{\ifnormalbottom} \\
-%D put the bottom line at the baseline \\
-%D
-%D \interface \type{\ifreversecolumns} \\
-%D reverse the order in wich columns are flushed \\
-%D
-%D \interface \type{\usercolumnwidth} \\
-%D the calculated width of a column \\
-%D \interface \type{\columntextwidth} \\
-%D the maximum width of a column \\
-%D \interface \type{\columntextheight} \\
-%D the minimum width of a column \\
-%D
-%D \interface \type{\spacingfactor} \\
-%D the spacing factor \\
-%D \interface \type{\bodyfontsize} \\
-%D the (local) bodyfontsize \\
-%D \interface \type{\openlineheight} \\
-%D the lineheight (including \type{\spacing}) \\
-%D
-%D \interface \type{\EveryBodyFont} \\
-%D communication channel to font switching routines \\
-%D
-%D \interface \type{\global\settopskip} \\
-%D set \type{\topskip} \\
-%D \interface \type{\setvsize} \\
-%D set \type{\vsize} and \type{\pagegoal} \\
-%D \interface \type{\sethsize} \\
-%D set \type{\hsize} \\
-%D
-%D \interface \type{\flushcolumnfloats} \\
-%D push saved column floats (next page) \\
-%D \interface \type{\flushcolumnfloat} \\
-%D push saved column floats (next column) \\
-%D \interface \type{\setcolumnfloats} \\
-%D initialize column floats \\
-%D
-%D \interface \type{\finishcolumnbox} \\
-%D do something special (a hook) \\
-%D \interface \type{\postprocesscolumnpagebox} \\
-%D do something with each columnbox (also a hook) \\
-%D \interface \type{\postprocesscolumnbox} \\
-%D do something with each columnbox (also a hook) \\
-%D \interface \type{\postprocesscolumnline} \\
-%D do something with each columnline (also a hook) \\
-%D \interface \type{\currentcolumn} \\
-%D the current column \\
-%D
-%D These interface macro's are called upon or initialized
-%D by the multi||column macro's.
-
-%D A lot of footnote stuff added!
\def\finalcolumntextwidth {\makeupwidth}
\def\finalcolumntextheight {\textheight}
@@ -195,23 +93,11 @@
\let\flushcolumnfloat \relax % in CONTEXT used for floats
\let\finishcolumnbox \relax % in CONTEXT used for backgrounds
-% %D In fact, the column height and width are set by means of
-% %D two macro's. One can change their meaning if needed:
-%
-% \def\setcolumntextheight
-% {\def\columntextheight{\teksthoogte}}
-%
-% \def\setcolumntextwidth
-% {\def\columntextwidth{\zetbreedte}}
-
-%D Both macros are redefined in \CONTEXT\ when backgrounds
-%D are applied to columns. The final values are used when
-%D flushing the columns.
+%D Both macros are redefined in \CONTEXT\ when backgrounds are applied to
+%D columns. The final values are used when flushing the columns.
-\newtoks\singlecolumnout % remove that one
-
-%D It's more convenient to use \type {\columnwidth} instead
-%D of messing around with boxes each time.
+%D It's more convenient to use \type {\columnwidth} instead of messing around
+%D with boxes each time.
\newdimen\columnwidth
\newdimen\gutterwidth
@@ -219,54 +105,31 @@
\def\determinecolumnwidth
{\bgroup
\setbox\scratchbox\hbox
- {\setcolumnhsize
+ {\page_mul_command_set_hsize
\global\columnwidth\usercolumnwidth
\global\gutterwidth\intercolumnwidth}%
\egroup}
-%D Going to a new columns is done by means of a
-%D \type{\ejectcolumn}. The following definition does not
-%D always work.
+%D Going to a new columns is done by means of a \type {\ejectcolumn}. The
+%D following definition does not always work.
\def\ejectcolumn
- {\goodbreak\showmessage\m!columns2\empty}
-
-%D The next macro should never be called so let's deal with it.
-%D There were several solutions to these kind of errors. First
-%D we check for a good breakpoint before firing up the
-%D multi||column routine (\type{\break} or \type{\allowbreak}).
-%D We do the same at the end of the routine
-%D (\type{\allowbreak}). These allowances are definitely
-%D needed!
-%D
-%D Some on first sight redundant calls to for instance
-%D \type{\setvsize} in the flushing, splitting and balancing
-%D macro's can definitely not be omitted! Some are just there
-%D to handle situations that only few times arise. One of
-%D those can be that the output routine is invoked before
-%D everything is taken care of. This happens when we
-%D flush (part of) the current page with an \type{\unvbox}
-%D with a \type{\pagetotal}~$\approx$ \type{\pagegoal}. One
-%D simply cannot balance columns that are just balanced.
-%D
-%D I hope one never sees the following message. Because it
-%D took me a lot of time to develop the multi||columns
-%D routines, every (although seldom) warning gives me the
-%D creeps!
+ {\goodbreak
+ \showmessage\m!columns2\empty}
\def\balancingerror
{\showmessage\m!columns3\empty
- \finaloutput\unvbox\normalpagebox}
+ \page_otr_construct_and_shipout\unvbox\normalpagebox}
-\def\OTRMULsometopsfloat{\showmessage\m!columns4\empty \someherefloat}
-\def\OTRMULsomebotsfloat{\showmessage\m!columns5\empty \someherefloat}
+\def\page_mul_place_float_top {\showmessage\m!columns4\empty\page_one_place_float_here}
+\def\page_mul_place_float_bottom{\showmessage\m!columns5\empty\page_one_place_float_here}
+\def\page_mul_place_float_here {\page_one_place_float_here}
+\def\page_mul_place_float_force {\page_one_place_float_force}
-\def\OTRMULsomeherefloat{\OTRONEsomeherefloat}
+%D The local column width is available in the dimension register \type
+%D {\localcolumnwidth}, which is calculated as:
-%D The local column width is available in the dimension
-%D register \type{\localcolumnwidth}, which is calculated as:
-
-\def\setcolumnhsize % beware, this one is available for use in macros
+\unexpanded\def\page_mul_command_set_hsize % beware, this one is available for use in macros
{\setbox\scratchbox\hbox{\parindent\zeropoint\betweencolumns}%
\intercolumnwidth\wd\scratchbox
\localcolumnwidth\columntextwidth
@@ -350,15 +213,14 @@
%D \getbuffer
%D \stop
-%D One should be aware that when font related dimensions are
-%D used in typesetting the in||between material, these
-%D dimensions are influenced by bodyfont switches inside
+%D One should be aware that when font related dimensions are used in typesetting the
+%D in||between material, these dimensions are influenced by bodyfont switches inside
%D multi||column mode.
\newdimen\mcscratchdimen
\newcount\nofcolumnlines
-\newconstant\multicolumnlinemethod % 0: overshoot (old default), 1: tight
+\setnewconstant\multicolumnlinemethod\plusone % 0: overshoot (old default), 1: tight
\def\getmulticolumnlines
{\mcscratchdimen-\columntextoffset
@@ -381,29 +243,49 @@
\def\multicolumnovershootratio{.5} % {\ifgridsnapping0\else.5\fi}
-\def\setcolumnvsize
- {\getmulticolumnlines
+\unexpanded\def\page_mul_command_set_vsize
+ {\page_one_command_set_vsize % indeed?
+ \getmulticolumnlines
\mcscratchdimen\nofcolumnlines\openlineheight
\advance\mcscratchdimen \multicolumnovershootratio\openlineheight % collect enough data
\global\vsize\nofcolumns\mcscratchdimen
\global\pagegoal\vsize} % let's do it only here
-%D It really starts here. After some checks and initializations
-%D we change the output routine to continous multi||column
-%D mode. This mode handles columns that fill the current and
-%D next full pages. The method used is (more or less)
-%D multiplying \type{\vsize} and dividing \type{\hsize} by
-%D \type{\nofcolumns}. More on this can be found in the
-%D \TeX book. We save the top of the current page in box
+%D It really starts here. After some checks and initializations we change the output
+%D routine to continous multi||column mode. This mode handles columns that fill the
+%D current and next full pages. The method used is (more or less) multiplying \type
+%D {\vsize} and dividing \type {\hsize} by \type {\nofcolumns}. More on this can be
+%D found in the \TeX book. We save the top of the current page in box
%D \type{\precolumnbox}.
%D
-%D We manipulate \type{\topskip} a bit, just to be shure that
-%D is has no flexibility. This has te be done every time a
-%D font switch takles place, because \type{\topskip} can depend
-%D on this.
-%D
-%D Watch the trick with the \type{\vbox}. This way we get the
-%D right interlining and white space.
+%D We manipulate \type {\topskip} a bit, just to be shure that is has no
+%D flexibility. This has te be done every time a font switch takles place, because
+%D \type{\topskip} can depend on this.
+
+\newconstant\c_page_mul_routine
+
+\setnewconstant\c_page_mul_routine_regular \zerocount
+\setnewconstant\c_page_mul_routine_intercept \plusone
+\setnewconstant\c_page_mul_routine_continuous \plustwo
+\setnewconstant\c_page_mul_routine_balanced \plusthree
+\setnewconstant\c_page_mul_routine_error \plusfour
+
+\unexpanded\def\page_mul_command_routine
+ {\ifcase\c_page_mul_routine
+ \page_one_command_routine
+ \or
+ \interceptmulticolumnsout
+ \or
+ \continuousmulticolumnsout
+ \or
+ \balancedmulticolumnsout
+ \or
+ \balancingerror
+ \fi}
+
+\def\interceptmulticolumnsout
+ {\global\setbox\precolumnbox\vbox
+ {\page_otr_command_flush_top_insertions\unvbox\normalpagebox}}
\def\beginmulticolumns
{\par
@@ -418,7 +300,6 @@
\leftskip\zeropoint
\rightskip\zeropoint
%
- \dontshowcomposition
%\setcolumntextwidth\relax
%\setcolumntextheight\relax
\widowpenalty\zerocount % is gewoon beter
@@ -442,39 +323,29 @@
\vskip-\struttotal
\fi
\global\savedpagetotal\pagetotal
- \global\singlecolumnout\output % hm
- %\global\output{\global\setbox\precolumnbox\vbox{\unvbox\normalpagebox}}%
- %\global\output{\global\setbox\precolumnbox\vbox{\dotopinsertions\unvbox\normalpagebox}}%
- \setoutputroutine{\global\setbox\precolumnbox\vbox{\dotopinsertions\unvbox\normalpagebox}}%
- \eject % no \holdinginserts=1, can make footnote disappear !
+ \setupoutputroutine[\s!multicolumn]%
+ \c_page_mul_routine\c_page_mul_routine_intercept
+ \page_otr_trigger_output_routine % no \holdinginserts=1, can make footnote disappear !
\global\precolumnboxheight\ht\precolumnbox
- %\global\output{\continuousmulticolumnsout}%
- \setoutputroutine{\continuousmulticolumnsout}%
+ \c_page_mul_routine\c_page_mul_routine_continuous
\setcolumnfloats
- \dohandleallcolumns
- {\global\setbox\currenttopcolumnbox\emptybox}%
+ \dohandleallcolumns{\global\setbox\currenttopcolumnbox\emptybox}%
\checkbegincolumnfootnotes
- \activateotr{MUL}{ONE}% todo ! ! ! !
- \let\sethsize\setcolumnhsize
- \let\setvsize\setcolumnvsize
- \sethsize
- \setvsize
- \showcomposition}
-
-%D When we leave the multi||column mode, we have to process the
-%D not yet shipped out part of the columns. When we don't
-%D balance, we simply force a continuous output, but a balanced
-%D output is more tricky.
-
-%D First we try to fill up the page and when all or something
-%D is left we try to balance things. This is another useful
-%D adaption of the ancesters of these macro's. It takes some
-%D reasoning to find out what happens and maybe I'm making
+ \page_otr_command_set_hsize
+ \page_otr_command_set_vsize}
+
+%D When we leave the multi||column mode, we have to process the not yet shipped out
+%D part of the columns. When we don't balance, we simply force a continuous output,
+%D but a balanced output is more tricky.
+%D
+%D First we try to fill up the page and when all or something is left we try to
+%D balance things. This is another useful adaption of the ancesters of these
+%D macro's. It takes some reasoning to find out what happens and maybe I'm making
%D some mistake, but it works.
%D
-%D Voiding box \type{\precolumnbox} is sometimes necessary,
-%D e.g. when there is no text given between \type{\begin..}
-%D and \type{\end..}. The \type{\par} is needed!
+%D Voiding box \type {\precolumnbox} is sometimes necessary, e.g. when there is no
+%D text given between \type {\begin..} and \type {\end..}. The \type {\par} is
+%D needed!
\setnewconstant\multicolumnendsyncmethod\plusone % 1: old sync 2: new sync (cont-loc/project) / may fail ! ! ! !
@@ -487,43 +358,42 @@
\vskip\lineheight
\vskip-\lineheight % take footnotes into account
\fi
- \dontshowcomposition
\doflushcolumnfloat % added recently
%\doflushcolumnfloats % no, since it results in wrong top floats
\flushnotes % before start of columns
\par
\ifbalancecolumns
\ifnum\multicolumnendsyncmethod=\plusone
- %\global\output{\continuousmulticolumnsout}%
- \setoutputroutine{\continuousmulticolumnsout}%
+ \c_page_mul_routine\c_page_mul_routine_continuous
\goodbreak
\fi
- %\global\output{\balancedmulticolumnsout}%
- \setoutputroutine{\balancedmulticolumnsout}%
+ \c_page_mul_routine\c_page_mul_routine_balanced
\else
\goodbreak
\fi
- \eject % the prevdepth is important, try e.g. toclist in
+ % still the multi column routine
+ \page_otr_trigger_output_routine % the prevdepth is important, try e.g. toclist in
\prevdepth\zeropoint % columns before some noncolumned text text
- %\global\output\singlecolumnout
- \setoutputroutine{\singlecolumnout}%
- %\global\output{\the\mainoutput}% % % % % todo
- \setoutputroutine{\the\mainoutput}% % % % % todo
+ %
+ \c_page_mul_routine\c_page_mul_routine_regular
+% \page_otf_set_engine_output_routine{\singlecolumnout}%
+% \page_otf_set_engine_output_routine{\page_otr_triggered_output_routine}%
+ %
\ifvoid\precolumnbox\else
\unvbox\precolumnbox
\fi
\global\precolumnboxheight\zeropoint
\endgroup % here
\nofcolumns\plusone
- \setvsize % the outer one!
+ \page_otr_command_set_vsize % the outer vsize (NEEDS CHECKING)
\synchronizeoutput % new may 2004 / we need to: \pagegoal\vsize
\checkendcolumnfootnotes
\dosomebreak\allowbreak
\dopopcolumnfloats}
-
-%D Because some initializations happen three times, we
-%D defined a macro for them. Erasing \type{\everypar} is
-%D needed because we don't want anything to interfere.
+
+%D Because some initializations happen three times, we defined a macro for
+%D them. Erasing \type{\everypar} is needed because we don't want anything
+%D to interfere.
\def\setmulticolumnsout
{\everypar\emptytoks
@@ -536,27 +406,22 @@
\boxmaxdepth\maxdepth % dangerous
\emergencystretch\zeropoint\relax} % sometimes needed !
-%D Flushing the page comes to pasting the columns together and
-%D appending the result to box \type{\precolumnbox}, if not
-%D void. I've seen a lot of implementations in which some skip
-%D was put between normal text and multi||column text. When we
-%D don't want this, the baselines can be messed up. I hope the
-%D seemingly complicated calculation of a correction
-%D \type{\kern} is adequate to overcome this. Although not
-%D watertight, spacing is taken into account and even multiple
-%D mode changes on one page go well. But cross your fingers and
-%D don't blame me.
+%D Flushing the page comes to pasting the columns together and appending the result
+%D to box \type {\precolumnbox}, if not void. I've seen a lot of implementations in
+%D which some skip was put between normal text and multi||column text. When we don't
+%D want this, the baselines can be messed up. I hope the seemingly complicated
+%D calculation of a correction \type {\kern} is adequate to overcome this. Although
+%D not watertight, spacing is taken into account and even multiple mode changes on
+%D one page go well. But cross your fingers and don't blame me.
%D
-%D One of the complications of flushing out the boxes is that
-%D \type{\precolumnbox} needs to be \type{\unvbox}'ed, otherwise
-%D there is too less flexibility in the page when using
-%D \type{\r@ggedbottom}. It took a lot of time before these
-%D kind of problems were overcome. Using \type{\unvbox} at the
-%D wrong moment can generate \type{\balancingerror}'s.
+%D One of the complications of flushing out the boxes is that \type {\precolumnbox}
+%D needs to be \type {\unvbox}'ed, otherwise there is too less flexibility in the
+%D page when using \type {\raggedbottom}. It took a lot of time before these kind of
+%D problems were overcome. Using \type {\unvbox} at the wrong moment can generate
+%D \type {\balancingerror}'s.
%D
-%D One can use the macros \type {\maxcolumnheight} and \type
-%D {\maxcolumndepth} when generating material between columns
-%D as well as postprocessing column lines.
+%D One can use the macros \type {\maxcolumnheight} and \type {\maxcolumndepth} when
+%D generating material between columns as well as postprocessing column lines.
\let\maxcolumnheight=\zeropoint
\let\maxcolumndepth =\zeropoint
@@ -600,20 +465,19 @@
\fi
\forgetall
\setmulticolumnsout
- \showcomposition
\setmaxcolumndimensions
\dohandleallcolumns
{\mkprocesscolumncontents\currentcolumnbox}%
\dohandleallcolumns
- {\docolumnpagebodymarks\plusone\nofcolumns\mofcolumns\currentcolumnbox}%
+ {\page_marks_synchronize_column\plusone\nofcolumns\mofcolumns\currentcolumnbox}%
\postprocesscolumns
- \dohandleallcolumns % \hbox i.v.m. \showcomposition
+ \dohandleallcolumns
{\global\setbox\currentcolumnbox\hbox to \localcolumnwidth
- {\box\currentcolumnbox
- \global\wd\currentcolumnbox\localcolumnwidth
- \ifheightencolumns
- \global\ht\currentcolumnbox\fixedcolumnheight
- \fi}}%
+ {\box\currentcolumnbox}%
+ \wd\currentcolumnbox\localcolumnwidth
+ \ifheightencolumns
+ \ht\currentcolumnbox\fixedcolumnheight
+ \fi}%
\setmaxcolumndimensions
\overlaycolumnfootnotes
\setbox\columnpagebox\vbox
@@ -624,9 +488,12 @@
\else
\@EA\dohandleallcolumns
\fi
- {\finishcolumnbox{\hbox
- {\ifx\finishcolumnbox\relax\else\strut\fi
- \box\currentcolumnbox}}%
+ {\finishcolumnbox
+ {\setbox\scratchbox\hbox
+ {\ifx\finishcolumnbox\relax\else\strut\fi
+ \strut\box\currentcolumnbox}%
+ \anch_mark_column_box\scratchbox
+ \box\scratchbox}%
\hfil}%
\unskip
\hskip\colrightskip}}% new
@@ -662,7 +529,7 @@
\fi \fi
\fi
\global\precolumnboxheight\zeropoint
- \setvsize
+ \page_otr_command_set_vsize
\dosomebreak\nobreak % hm, only needed when topstuff
\ifgridsnapping
\else
@@ -672,28 +539,28 @@
\or
% \input tufte \startcolumns \showbaselines \input tufte \stopcolumns \input tufte
\ifconditional\someprecolumncontent
-% \scratchdimen\topskip
-% \advance\scratchdimen -\openstrutheight
-% \nointerlineskip
-% \vskip-\scratchdimen
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
\nointerlineskip
\vskip\dimexpr\openstrutheight-\topskip\relax
\fi
\or
-% \scratchdimen\topskip
-% \advance\scratchdimen -\openstrutheight
-% \nointerlineskip
-% \vskip-\scratchdimen
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
\nointerlineskip
\vskip\dimexpr\openstrutheight-\topskip\relax
\or
% untested but maybe handy
-% \scratchdimen\topskip
-% \advance\scratchdimen -\openstrutheight
-% \nointerlineskip
-% \vskip-\scratchdimen
-% \vskip-\lineheight
-% \vbox{\strut}%
+ % \scratchdimen\topskip
+ % \advance\scratchdimen -\openstrutheight
+ % \nointerlineskip
+ % \vskip-\scratchdimen
+ % \vskip-\lineheight
+ % \vbox{\strut}%
\nointerlineskip
\vskip\dimexpr\openstrutheight-\topskip-\lineheight\relax
\vbox{\strut}%
@@ -715,8 +582,12 @@
\vskip-\scratchdimen}%
\scratchdimen\noflines\openlineheight
\advance\scratchdimen-\openstrutdepth
- \advance\scratchdimen-\openlineheight
- \advance\scratchdimen\topskip
+ \ifgridsnapping
+ % quick hack (at least it works with itemize)
+ \else
+ \advance\scratchdimen-\openlineheight
+ \advance\scratchdimen\topskip
+ \fi
\ht\columnpagebox\scratchdimen
\dp\columnpagebox\openstrutdepth
% end of mess
@@ -724,13 +595,11 @@
\box\columnpagebox
\egroup}
-%D In case one didn't notice, finaly \type{\finishcolumnbox} is
-%D applied to all boxes. One can use these hooks for special
-%D purposes.
+%D In case one didn't notice, finaly \type{\finishcolumnbox} is applied to
+%D all boxes. One can use these hooks for special purposes.
%D
-%D Once upon a time I wanted to manipulate the individual lines
-%D in a column. This feature is demonstrated in the two examples
-%D below.
+%D Once upon a time I wanted to manipulate the individual lines in a column.
+%D This feature is demonstrated in the two examples below.
%D
%D \startbuffer
%D \def\postprocesscolumnline#1% or \postprocesscolumnbox
@@ -809,21 +678,18 @@
%D \macros
%D {reversecolumnstrue}
%D
-%D We can force the macro that takes care of combining
-%D the columns, to flush them in the revere order. Of
-%D course, by default we don't reverse.
+%D We can force the macro that takes care of combining the columns, to
+%D flush them in the revere order. Of course, by default we don't reverse.
\newif\ifreversecolumns
-%D Here comes the simple splitting routine. It's a bit
-%D longer than expected because of ragging bottoms or not.
-%D This part can be a bit shorter but I suppose that I will
-%D forget what happens. The splitting takes some already
-%D present material (think of floats) into account!
+%D Here comes the simple splitting routine. It's a bit longer than expected because
+%D of ragging bottoms or not. This part can be a bit shorter but I suppose that I
+%D will forget what happens. The splitting takes some already present material
+%D (think of floats) into account!
%D
-%D First we present some auxiliary routines. Any material,
-%D like for instance floats, that is already present in the
-%D boxes is preserved.
+%D First we present some auxiliary routines. Any material, like for instance floats,
+%D that is already present in the boxes is preserved.
\def\splitcolumn#1from \box#2to \dimen#3 top \box#4%
{\bgroup
@@ -844,7 +710,7 @@
\fuzzysnappedbox\unvbox0
\fakecolumnfootnotes{#1}}%
\else
- \ifcase\clevernotes
+ \ifcase\c_strc_notes_page_location
\global\setbox#1\vsplit#2 to \dimen#3%
\global\setbox#1\vbox
{\fuzzysnappedbox\unvbox{#1}}% % or \box ?
@@ -874,7 +740,7 @@
\def\fakecolumnfootnotes#1%
{\relax
- \ifcase\clevernotes\else
+ \ifcase\c_strc_notes_page_location\else
\ifnum#1=\lastcolumnbox
\fakenotes
\fi
@@ -882,7 +748,7 @@
\def\columnfootnotecorrection#1#2%
{\relax
- \ifcase\clevernotes
+ \ifcase\c_strc_notes_page_location
% page notes
\or
\ifnum#1=\firstcolumnbox\relax
@@ -898,64 +764,69 @@
\def\overlaycolumnfootnotes
{\relax
- \ifcase\clevernotes
- % page notes
- \else
- \checknotepresence
- \ifnotespresent
- % the note box has the depth of the notefont
- % because a column (i.e. first column has no depth,
- % we need to anchor top down)
- \bgroup
- \ifcase\clevernotes\or
- \getmulticolumnlines
- \advance\nofcolumnlines \minustwo
- \scratchdimen\nofcolumnlines\lineheight
- \advance\scratchdimen \topskip
- \setbox0\hbox
- {\lower\scratchdimen\vbox{\placenoteinserts}}%
- \ht0=\openstrutheight % \strutht
- \dp0=\openstrutdepth % \strutdp
- \wd0=\zeropoint
- \scratchdimen\ht\firstcolumnbox
- \global\setbox\firstcolumnbox\vbox to \scratchdimen
- {\box\firstcolumnbox
- \vskip-\scratchdimen
- \box0}%
- \else
- % maybe here also \getmulticolumnlines
- \scratchdimen\ht\firstcolumnbox
- \advance\scratchdimen -\openstrutdepth % \strutdp
- \getnoflines\scratchdimen
- \advance\noflines \minustwo
- \scratchdimen\noflines\lineheight
- \advance\scratchdimen \topskip
- \setbox0\hbox
- {\lower\scratchdimen\vbox{\placenoteinserts}}%
- \ht0=\openstrutheight % \strutht
- \dp0=\openstrutdepth % \strutdp
- \wd0=\zeropoint
- \scratchdimen\ht\lastcolumnbox
- \global\setbox\lastcolumnbox\vbox to \scratchdimen
- {\box\lastcolumnbox
- \vskip-\scratchdimen
- \box0}%
- \fi
- \egroup
- \fi
+ \ifcase\c_strc_notes_page_location
+ % page
+ \or
+ \checknotepresence \ifnotespresent \page_mul_notes_flush_first_column \fi
+ \or
+ \checknotepresence \ifnotespresent \page_mul_notes_flush_last_column \fi
\fi}
-%D Here comes the routine that splits the long box in columns.
-%D The macro \type{\flushcolumnfloats} can be used to flush
-%D either floats that were present before the multi||column
-%D mode was entered, or floats that migrate to next columns.
+\newbox\b_page_mul_notes
+
+\def\page_mul_notes_flush_first_column
+ {\begingroup
+ \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
+ \ifzeropt\ht\b_page_mul_notes
+ % can't happen as we already checked
+ \else
+ \getmulticolumnlines
+ \advance\nofcolumnlines \minustwo
+ \scratchdimen\dimexpr\nofcolumnlines\lineheight+\topskip\relax
+ \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \ht\b_page_mul_notes\openstrutheight
+ \dp\b_page_mul_notes\openstrutdepth
+ \wd\b_page_mul_notes\zeropoint
+ \scratchdimen\ht\firstcolumnbox
+ \global\setbox\firstcolumnbox\vbox to \scratchdimen
+ {\box\firstcolumnbox
+ \vskip-\scratchdimen
+ \box\b_page_mul_notes}%
+ \fi
+ \endgroup}
+
+\def\page_mul_notes_flush_last_column
+ {\begingroup
+ \setbox\b_page_mul_notes\vbox{\placenoteinserts}%
+ \ifzeropt\ht\b_page_mul_notes
+ % can't happen as we already checked
+ \else
+ % maybe here also \getmulticolumnlines
+ \scratchdimen\dimexpr\ht\firstcolumnbox-\openstrutdepth\relax % \strutdp
+ \getnoflines\scratchdimen
+ \advance\noflines \minustwo
+ \scratchdimen\dimexpr\noflines\lineheight+\topskip\relax
+ \setbox\b_page_mul_notes\hbox{\lower\scratchdimen\box\b_page_mul_notes}%
+ \ht\b_page_mul_notes\openstrutheight
+ \dp\b_page_mul_notes\openstrutdepth
+ \wd\b_page_mul_notes\zeropoint
+ \scratchdimen\ht\lastcolumnbox
+ \global\setbox\lastcolumnbox\vbox to \scratchdimen
+ {\box\lastcolumnbox
+ \vskip-\scratchdimen
+ \box\b_page_mul_notes}%
+ \fi
+ \endgroup}
+
+%D Here comes the routine that splits the long box in columns. The macro \type
+%D {\flushcolumnfloats} can be used to flush either floats that were present before
+%D the multi||column mode was entered, or floats that migrate to next columns.
%D Flushing floats is a delicate process.
\def\continuousmulticolumnsout
{\bgroup
\forgetall
\setmulticolumnsout
- \dontshowcomposition
% \dimen0=\columntextheight
% \advance\dimen0 -\precolumnboxheight
% \settotalinsertionheight
@@ -970,7 +841,8 @@
{\splitcurrentcolumn from \box\normalpagebox to \dimen0}%
\setbox\restofpage\vbox{\unvbox\normalpagebox}%
\ifinheritcolumns
- \ifr@ggedbottom % vreemd
+ \ifcase\bottomraggednessmode
+ % 0 = ragged
\dohandleallcolumns
{\global\setbox\currentcolumnbox\vbox to \ht\firstcolumnbox
{\dimen0\dp\currentcolumnbox
@@ -979,17 +851,18 @@
\vskip\openstrutdepth % \strutdp
\prevdepth\openstrutdepth % \strutdp
\vfill}}%
- \ifbottomnotes \else
+ \strc_notes_check_if_bottom_present
+ \ifconditional\c_notes_bottom_present \else
\dimen0\ht\firstcolumnbox
\fi
- \fi
- \ifn@rmalbottom
+ \or
+ % 1 = normal
\advance\dimen0 \maxdepth
\dohandleallcolumns
{\global\setbox\currentcolumnbox\vbox to \dimen0
{\unvbox\currentcolumnbox}}%
- \fi
- \ifb@selinebottom
+ \or
+ % 2 = baseline
% the columns are on top of the baseline
\fi
\else
@@ -1002,31 +875,28 @@
\vfill
\fi}}%
\dohandleallcolumns
- {\global\ht\currentcolumnbox\dimen0}%
+ {\ht\currentcolumnbox\dimen0}% redundant
\fi
\setbox\precolumnbox\vbox{\flushcolumnedpage\zerocount}%
- \finaloutput\box\precolumnbox
- \sethsize
- \setvsize
+ \page_otr_construct_and_shipout\box\precolumnbox
+ \page_otr_command_set_hsize
+ \page_otr_command_set_vsize
\flushcolumnfloats
\unvbox\restofpage
% \penalty\outputpenalty % gaat gruwelijk mis in opsommingen
\egroup}
-%D And this is the balancing stuff. Again, part of the routine
-%D is dedicated to handling ragged bottoms, but here we also
-%D see some handling concerning the stretching of columns.
-%D We set \type{\widowpenalty} at~0, which enables us to
-%D balance columns with few lines. The use of \type{\box2} and
-%D \type{\box4} garantees a more robust check when skips are
-%D used.
+%D And this is the balancing stuff. Again, part of the routine is dedicated to
+%D handling ragged bottoms, but here we also see some handling concerning the
+%D stretching of columns. We set \type {\widowpenalty} at~0, which enables us to
+%D balance columns with few lines. The use of \type {\box2} and \type {\box4}
+%D garantees a more robust check when skips are used.
\def\multicolumnsbalancemax{250} % 100 is too small when floats are involved
\def\balancedmulticolumnsout
{\bgroup
\setmulticolumnsout
- \dontshowcomposition
\widowpenalty\zerocount
\setbox0\vbox{\unvbox\normalpagebox}%
\ifdim\ht0>\openlineheight % at least one line
@@ -1056,7 +926,7 @@
\dohandleallcolumns
{\advance\dimen0 \ht\currenttopcolumnbox}%
\divide\dimen0 \nofcolumns
- \vbadness\!!tenthousand\relax
+ \vbadness\plustenthousand
\count255=\zerocount
\bgroup
\ifgridsnapping
@@ -1164,22 +1034,21 @@
\showmessage\m!columns{10}\empty
\global\setbox\firstcolumnbox\vbox{\unvbox0}%
\fi
- %\global\output{\balancingerror}%
- \setoutputroutine{\balancingerror}%
- \b@selinebottomtrue % forces depth in separation rule
+ \c_page_mul_routine\c_page_mul_routine_error
+ \baselinebottom % forces depth in separation rule
\flushcolumnedpage\plusone
\multicolumnseject
\egroup}
\def\multicolumnseject
{%\ifdim\pagetotal>\textheight
- % \eject % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point)
+ % \page_otr_trigger_output_routine % new, but wrong as fails on mixed-001.tex (wrong pagetotal at this point)
%\else
\allowbreak
}%\fi}
-%D The multicolumn mechanism is incorporated in a \CONTEXT\
-%D interface, which acts like:
+%D The multicolumn mechanism is incorporated in a \CONTEXT\ interface,
+%D which acts like:
%D
%D \starttyping
%D \startcolumns[n=4,balance=no]
@@ -1187,8 +1056,8 @@
%D \stopcolumns
%D \stoptyping
%D
-%D The setup is optional. The default behaviour of columns
-%D can be set up with:
+%D The setup is optional. The default behaviour of columns can be set
+%D up with:
%D
%D \starttyping
%D \setupcolumns
@@ -1196,31 +1065,24 @@
%D balance=yes]
%D \stoptyping
%D
-%D In this case, stretching is according to the way it's
-%D done outside columns (\type{\inheritcolumnstrue}). Also
-%D we can setup the \type{tolerance} within a column, the
-%D \type{distance} between columns and the fixed
-%D \type{height} of a column.
-
-%D Multi||column output: the float routines
+%D In this case, stretching is according to the way it's done outside columns
+%D (\type{\inheritcolumnstrue}). Also we can setup the \type{tolerance} within a
+%D column, the \type{distance} between columns and the fixed \type{height} of a
+%D column.
%D
-%D Here come the routines that handle the placement of column
-%D floats. Floats that are to big migrate to the next
-%D column. Floats that are too wide, migrate to the top of the
-%D next page, where they span as much columns as needed.
-%D Floats that are left over from outside the multi||column
-%D mode are flushed first. In macro \type{\finaloutput} the
-%D topfloats that are left from previous text should be set.
+%D Here come the routines that handle the placement of column floats. Floats that
+%D are to big migrate to the next column. Floats that are too wide, migrate to the
+%D top of the next page, where they span as much columns as needed. Floats that are
+%D left over from outside the multi||column mode are flushed first. In macro
+%D \type{\page_otr_construct_and_shipout} the topfloats that are left from previous
+%D text should be set.
%D
-%D When there are some floats in the queue, we inhibit the
-%D flushing of floats on top of columns. The number of
-%D waiting floats is preswent in \type{\savednoftopfloats} and
-%D is saved. As long as there are floats waiting, the topfloats
-%D are places as if we are outside multi||column mode. This is
-%D neccessary for e.g. multicolumn lists.
+%D When there are some floats in the queue, we inhibit the flushing of floats on top
+%D of columns. The number of waiting floats is preswent in \type{\savednoftopfloats}
+%D and is saved. As long as there are floats waiting, the topfloats are places as if
+%D we are outside multi||column mode. This is neccessary for e.g. multicolumn lists.
%D
-%D When all those floats are flushed, we switch to the local
-%D flushing routine.
+%D When all those floats are flushed, we switch to the local flushing routine.
\def\dopushcolumnfloats
{\ifsomefloatwaiting
@@ -1251,10 +1113,29 @@
\newconditional\onlylocalcolumnfloats % temp hack as we will redo floats (grid snapping is also messy now)
-\def\OTRMULdocheckiffloatfits{\ifconditional\onlylocalcolumnfloats\docolumnroomfloat \else\relax \fi}
-\def\OTRMULdosetbothinserts {\ifconditional\onlylocalcolumnfloats\relax \else\OTRONEdosetbothinserts\fi}
-\def\OTRMULdotopinsertions {\ifconditional\onlylocalcolumnfloats\relax \else\OTRONEdotopinsertions \fi}
-\def\OTRMULdoflushfloats {\ifconditional\onlylocalcolumnfloats\doflushcolumnfloats\else\OTRONEdoflushfloats \fi}
+\unexpanded\def\page_mul_command_flush_floats
+ {\ifconditional\onlylocalcolumnfloats
+ \doflushcolumnfloats
+ \else
+ \page_one_command_flush_floats
+ \fi}
+
+\unexpanded\def\page_mul_command_check_if_float_fits
+ {\ifconditional\onlylocalcolumnfloats
+ \docolumnroomfloat
+ \fi}
+
+\unexpanded\def\page_mul_command_flush_saved_floats
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_saved_floats
+ \fi}
+
+\unexpanded\def\page_mul_command_flush_top_insertions
+ {\ifconditional\onlylocalcolumnfloats\relax
+ \else
+ \page_one_command_flush_top_insertions
+ \fi}
\newtoks\everylocalcolumnfloatspar
@@ -1280,7 +1161,7 @@
{\bgroup
\xdef\localsavednoffloats{\the\savednoffloats}%
\global\savednoffloats\globalsavednoffloats
- \dotopinsertions
+ \page_otr_command_flush_top_insertions
\xdef\globalsavenoffloats{\the\savednoffloats}%
\ifnum\globalsavednoffloats=\zerocount
\setlocalcolumnfloats
@@ -1288,14 +1169,12 @@
\global\savednoffloats\localsavednoffloats
\egroup}
-%D We need to calculate the amount of free space in a columns.
-%D When there is not enough room, we migrate the float to the
-%D next column. These macro's are alternatives (and
-%D look||alikes) of \type{\doroomfloat}. When a float is to
-%D wide, for one column, it is moved to the top of the next
-%D page. Of course such moved floats have to be taken into
-%D account when we calculate the available space. It's a pitty
-%D that such things are no integral part of \TEX.
+%D We need to calculate the amount of free space in a columns. When there is not
+%D enough room, we migrate the float to the next column. These macro's are
+%D alternatives (and look||alikes) of \type {\doroomfloat}. When a float is to wide,
+%D for one column, it is moved to the top of the next page. Of course such moved
+%D floats have to be taken into account when we calculate the available space. It's
+%D a pitty that such things are no integral part of \TEX.
\def\getcolumnstatus\column#1\total#2\goal#3\\%
{\dimen0=\ifdim\pagegoal<\maxdimen \pagetotal \else \zeropoint \fi
@@ -1341,7 +1220,7 @@
\getcolumnstatus\column\count255\total\dimen0\goal\dimen2\\%
\dofloatsgetinfo\s!text
\setbox\scratchbox\vbox % tricky met objecten ?
- {\blank[\@@bkspacebefore]
+ {\blank[\rootfloatparameter\c!spacebefore]
\snaptogrid\vbox{\vskip\floatheight}}% copy?
\advance\dimen0\dimexpr\ht\scratchbox+2\openlineheight+.5\lineheight\relax\relax % needed because goal a bit higher
\ifdim\dimen0>\dimen2
@@ -1355,78 +1234,79 @@
\fi
\egroup
\fi\fi}
-
-%D Flushing one float is done as soon as possible, i.e.
-%D \type{\everypar}. This means that (at the moment)
-%D sidefloats are not supported (overulled)!
+
+%D Flushing one float is done as soon as possible, i.e. \type {\everypar}.
+%D This means that (at the moment) sidefloats are not supported (overulled)!
\newif\ifflushingcolumnfloats \flushingcolumnfloatstrue
\def\doflushcolumnfloat
- {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifprocessingverbatim\else\ifsomefloatwaiting
- \bgroup
- \forgetall
- \let\doflushcolumnfloat\relax
- \getcolumnstatus\column\mofcolumns\total\dimen0\goal\dimen2\\%
- \ifdim\dimen0>\zeropoint
- \dofloatsgetinfo\s!text
- \ifdim\floatwidth>\hsize
- % dropped ?
- \else
- \setbox2\vbox
- {\blank[\@@bkspacebefore]
- \snaptogrid\vbox{\vskip\floatheight}}%
- \advance\dimen0 \ht2
- \ifdim\dimen0>\dimen2
- \ifnum\mofcolumns<\nofcolumns
- \advance\mofcolumns \plusone
- \ifdim\ht\currenttopcolumnbox=\zeropoint
- \dofloatsflush\s!text{1}%
- \global\setbox\currenttopcolumnbox\vbox
- {\snaptogrid\vbox{\box\floatbox}
- \whitespace % nodig ?
- \blank[\@@bkspaceafter]}%
- \dimen4=\htdp\currenttopcolumnbox
- \global\advance\vsize -\dimen4
- \advance\dimen4 -\pagegoal
- \global\pagegoal-\dimen4
- \showmessage\m!columns{12}a%
- \else
- \showmessage\m!columns{12}b%
- \fi
+ {\ifpostponecolumnfloats\else\ifflushingcolumnfloats\ifsomefloatwaiting
+ \doflushcolumnfloatindeed
+ \fi\fi\fi}
+
+\def\doflushcolumnfloatindeed
+ {\bgroup
+ \forgetall
+ \let\doflushcolumnfloat\relax
+ \getcolumnstatus\column\mofcolumns\total\dimen0\goal\dimen2\\%
+ \ifdim\dimen0>\zeropoint
+ \dofloatsgetinfo\s!text
+ \ifdim\floatwidth>\hsize
+ % dropped ?
+ \else
+ \setbox2\vbox
+ {\blank[\rootfloatparameter\c!spacebefore]
+ \snaptogrid\vbox{\vskip\floatheight}}%
+ \advance\dimen0 \ht2
+ \ifdim\dimen0>\dimen2
+ \ifnum\mofcolumns<\nofcolumns
+ \advance\mofcolumns \plusone
+ \ifdim\ht\currenttopcolumnbox=\zeropoint
+ \dofloatsflush\s!text{1}%
+ \global\setbox\currenttopcolumnbox\vbox
+ {\snaptogrid\vbox{\box\floatbox}
+ \whitespace % nodig ?
+ \blank[\rootfloatparameter\c!spaceafter]}%
+ \dimen4=\htdp\currenttopcolumnbox
+ \global\advance\vsize -\dimen4
+ \advance\dimen4 -\pagegoal
+ \global\pagegoal-\dimen4
+ \showmessage\m!columns{12}a%
\else
- \showmessage\m!columns{12}c%
+ \showmessage\m!columns{12}b%
\fi
\else
- \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen
- \par
- \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte
- \nobreak
- \blank[\@@bkspacebefore]
- \nobreak
- \fi
- \dofloatsflush\s!text{1}%
- \flushfloatbox
- \blank[\@@bkspaceafter]
+ \showmessage\m!columns{12}c%
+ \fi
+ \else
+ \ifhmode{\setbox0\lastbox}\fi% waar is die er in geslopen
+ \par
+ \ifdim\prevdepth<\zeropoint \else % anders bovenaan kolom witruimte
+ \nobreak
+ \blank[\rootfloatparameter\c!spacebefore]
+ \nobreak
\fi
+ \dofloatsflush\s!text{1}%
+ \page_otr_command_flush_float_box
+ \blank[\rootfloatparameter\c!spaceafter]
\fi
\fi
- \egroup
- \fi\fi\fi\fi}
+ \fi
+ \egroup}
-%D This one looks complicated. Upto \type{\nofcolumns} floats
-%D are placed, taking the width of a float into account. This
-%D routine can be improved on different ways:
+%D This one looks complicated. Upto \type{\nofcolumns} floats are placed,
+%D taking the width of a float into account. This routine can be improved
+%D on different ways:
%D
%D \startitemize[intro,packed]
-%D \item taking into account some imaginary baseline, just to
-%D get the captions in line
-%D \item multipass flushing until as many floats are displaced
-%D as possible
+%D \item taking into account some imaginary baseline, just to get the
+%D captions in line
+%D \item multipass flushing until as many floats are displaced as possible
%D \stopitemize
%D
-%D When handling lots of (small) floats spacing can get worse
-%D because of lining out the columns.
+%D When handling lots of (small) floats spacing can get worse because of
+%D lining out the columns.
\def\doflushcolumnfloats
{\ifpostponecolumnfloats\else
@@ -1444,7 +1324,7 @@
{\copy\currenttopcolumnbox
\hbox{\vphantom{\vskip\floatheight}}}% known from previous
\whitespace % nodig ?
- \blank[\@@bkspaceafter]}%
+ \blank[\rootfloatparameter\c!spaceafter]}%
\else
\dofloatsgetinfo\s!text
\ifdim\floatwidth>\hsize
@@ -1462,7 +1342,7 @@
\global\setbox\floatbox\hbox to \finalcolumntextwidth{\hss\box\floatbox\hss}%
\fi % otherwise the graphic may disappear
\global\setbox\floatbox\hbox to \dimen0
- {\processaction[\@@bklocation] % how easy to forget
+ {\processaction[\rootfloatparameter\c!location] % how easy to forget
[ \v!left=>\box\floatbox\hss,
\v!right=>\hss\box\floatbox,
\s!default=>\hss\box\floatbox\hss,
@@ -1482,7 +1362,7 @@
{\box\currenttopcolumnbox % was copy
\box\floatbox}
\whitespace % nodig ?
- \blank[\@@bkspaceafter]}%
+ \blank[\rootfloatparameter\c!spaceafter]}%
\fi
\dimen6\htdp\currenttopcolumnbox
\fi
@@ -1492,17 +1372,17 @@
\advance\dimen8 \dimen6
\advance\count2 \minusone
\advance\count0 \minusone }%
- \setvsize
+ \page_otr_command_set_vsize
\global\advance\vsize -\dimen8
\global\pagegoal\vsize
\else
- %\doflushfloats % does not snap!
+ % \page_mul_command_flush_floats % does not snap!
\fi
\egroup
\fi}
-%D The next macro can be used to flush floats in the current
-%D stream. No width checking is (yet) done.
+%D The next macro can be used to flush floats in the current stream. No
+%D width checking is (yet) done.
\def\insertcolumnfloats
{\doloop
@@ -1511,19 +1391,19 @@
\forgetall
% no check for width
\dogetfloat
- \blank[\@@bkspacebefore]
+ \blank[\rootfloatparameter\c!spacebefore]
\snaptogrid\vbox{\copy\floatbox}
- \blank[\@@bkspaceafter]
+ \blank[\rootfloatparameter\c!spaceafter]
\egroup
\else
\exitloop
\fi}}
-%D This were the multi||column routines. They can and need to
-%D be improved but at the moment their behaviour is acceptable.
+%D This were the multi||column routines. They can and need to be improved
+%D but at the moment their behaviour is acceptable.
%D
-%D One inprovement can be to normalize the height of floats
-%D to $n\times$\type{\lineheight} with a macro like:
+%D One inprovement can be to normalize the height of floats to $ n \times $
+%D \type {\lineheight} with a macro like:
%D
%D \starttyping
%D \normalizevbox{...}
@@ -1532,13 +1412,11 @@
% border case, should fit on one page
%
% \startcolumns
-%
-% 1 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{1}}
-% 2 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{2}}
-% 3 \input tufte \par \plaatsfiguur{}{\omlijnd[breedte=\hsize,hoogte=3cm]{3}}
-%
+% 1 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{1}}
+% 2 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{2}}
+% 3 \input tufte \par \placefigure{}{\framed[width=\hsize,height=3cm]{3}}
% \stopcolumns
-
+
\unexpanded\def\setupcolumns
{\dosingleempty\dosetupcolumns}
@@ -1564,7 +1442,9 @@
\hskip.5\dimen0
\vrule
\!!width\linewidth
- \ifb@selinebottom\!!depth\strutdepth\fi
+ \ifnum\bottomraggednessmode=\plustwo % baselinebottom
+ \!!depth\strutdepth
+ \fi
\hskip.5\dimen0\relax
\stoptextproperties
\egroup}
@@ -1589,6 +1469,12 @@
\definecomplexorsimpleempty\startcolumns
+% to be reconsidered ... (in any case they need to be unexpandable sinze 2011.12.30)
+
+\unexpanded\def\page_columns_align_option_yes {\stretchcolumnstrue \inheritcolumnsfalse}% todo: new key
+\unexpanded\def\page_columns_align_option_no {\stretchcolumnsfalse\inheritcolumnsfalse}% todo: new key
+\unexpanded\def\page_columns_align_option_text{\stretchcolumnsfalse\inheritcolumnstrue }%
+
\def\complexstartcolumns[#1]% %% \startcolumns
{\bgroup
\let\stopcolumns\egroup
@@ -1613,23 +1499,18 @@
\doifelse\@@klbalance\v!yes
\balancecolumnstrue
\balancecolumnsfalse
- \installalign\v!yes {\stretchcolumnstrue \inheritcolumnsfalse}% todo: new key
- \installalign\v!no {\stretchcolumnsfalse\inheritcolumnsfalse}% todo: new key
- \installalign\v!text{\stretchcolumnsfalse\inheritcolumnstrue }%
+ \installalign\v!yes {\page_columns_align_option_yes }%
+ \installalign\v!no {\page_columns_align_option_no }%
+ \installalign\v!text{\page_columns_align_option_text}%
\stretchcolumnsfalse
\inheritcolumnstrue
\doifsomething\@@klalign{\expanded{\setupalign[\@@klalign]}}%
- \nofcolumns=\@@kln
- %
- % probably more is needed, and how about nesting save's
- %
- \saveouterspacing
- %
+ \nofcolumns\@@kln
\edef\fixedcolumnheight{\@@klheight}%
\edef\minbalancetoplines{\@@klntop}%
\setuptolerance[\@@kltolerance]% %% \startcolumns
\setupblank[\@@klblank]%
- \ifdim\ctxparskip>\zeropoint\relax
+ \ifdim\s_spac_whitespace_parskip>\zeropoint\relax
\setupwhitespace[\@@klblank]%
\fi
\unexpanded\def\stopcolumns
@@ -1641,20 +1522,19 @@
\beginmulticolumns
\fi
\fi}
-
-\installcolumnbreakhandler {MUL} \v!preference
+
+\installcolumnbreakmethod \s!multicolumn \v!preference
{\goodbreak}
-\installcolumnbreakhandler {MUL} \v!yes
+\installcolumnbreakmethod \s!multicolumn \v!yes
{\par % todo: since
{\testrulewidth\zeropoint\ruledvskip\textheight} % we misuse a
\penalty-200 % side effect
\vskip-\textheight
}% bugged : \prevdepth-\thousandpoint} % signals top of column to \blank
-
-%D New: only at start of columns; may change ! Rather
-%D interwoven and therefore to be integrated when the multi
-%D column modules are merged. (moved from cont-new.tex)
+
+%D New: only at start of columns; may change ! Rather interwoven and therefore
+%D to be integrated when the multi column modules are merged.
\unexpanded\def\setupcolumnspan[#1]%
{\getparameters[\??ks][#1]}
@@ -1667,7 +1547,7 @@
\c!offset=\v!overlay,
\c!frame=\v!off]
-\newbox\columnspanbox \let\postprocesscolumnspanbox\gobbleoneargument
+\newbox\b_page_columns_span \let\postprocesscolumnspanbox\gobbleoneargument
\def\dostartcolumnspan[#1]%
{\bgroup
@@ -1678,50 +1558,51 @@
\hsize\@@ksn\hsize
\advance\hsize -\intercolumnwidth
\fi
- \dowithnextbox
- {\setbox\columnspanbox\flushnextbox
- \ifinsidecolumns\wd\columnspanbox\hsize\fi
- \postprocesscolumnspanbox\columnspanbox
- \scratchdimen\ht\columnspanbox
- \setbox\columnspanbox\hbox % depth to be checked, probably option!
- {\localframed[\??ks][\c!offset=\v!overlay]{\box\columnspanbox}}%
- \ht\columnspanbox\scratchdimen
- \dp\columnspanbox\strutdp
- \wd\columnspanbox\hsize
- \ifinsidecolumns
- \ifnum\@@ksn>1
- \setvsize
- \dohandleallcolumns
- {\ifnum\currentcolumn>\@@ksn\else
- \global\setbox\currenttopcolumnbox=\vbox
- {\ifnum\currentcolumn=1
- \snaptogrid\vbox{\copy\columnspanbox}
- \else
- \snaptogrid\vbox{\vphantom{\copy\columnspanbox}}
- \fi}%
- \wd\currenttopcolumnbox\hsize
- \global\advance\vsize -\ht\currenttopcolumnbox
- \fi}
- \global\pagegoal\vsize
- \else
- \snaptogrid\vbox{\box\columnspanbox}
- \fi
- \else
- \snaptogrid\vbox{\box\columnspanbox}
- \fi
- \endgraf
- \ifvmode\prevdepth\strutdp\fi
- \egroup}
- \vbox\bgroup
- %\topskipcorrection % becomes an option !
- \EveryPar{\begstrut\EveryPar{}}} % also !
+ \dowithnextboxcs\dofinishcolumnsetspan\vbox\bgroup
+ %\topskipcorrection % becomes an option !
+ \EveryPar{\begstrut\EveryPar{}}} % also !
+
+\def\dofinishcolumnsetspan
+ {\setbox\b_page_columns_span\flushnextbox
+ \ifinsidecolumns\wd\b_page_columns_span\hsize\fi
+ \postprocesscolumnspanbox\b_page_columns_span
+ \scratchdimen\ht\b_page_columns_span
+ \setbox\b_page_columns_span\hbox % depth to be checked, probably option!
+ {\localframed[\??ks][\c!offset=\v!overlay]{\box\b_page_columns_span}}%
+ \ht\b_page_columns_span\scratchdimen
+ \dp\b_page_columns_span\strutdp
+ \wd\b_page_columns_span\hsize
+ \ifinsidecolumns
+ \ifnum\@@ksn>1
+ \page_otr_command_set_vsize
+ \dohandleallcolumns
+ {\ifnum\currentcolumn>\@@ksn\else
+ \global\setbox\currenttopcolumnbox=\vbox
+ {\ifnum\currentcolumn=1
+ \snaptogrid\vbox{\copy\b_page_columns_span}
+ \else
+ \snaptogrid\vbox{\vphantom{\copy\b_page_columns_span}}
+ \fi}%
+ \wd\currenttopcolumnbox\hsize
+ \global\advance\vsize -\ht\currenttopcolumnbox
+ \fi}
+ \global\pagegoal\vsize
+ \else
+ \snaptogrid\vbox{\box\b_page_columns_span}
+ \fi
+ \else
+ \snaptogrid\vbox{\box\b_page_columns_span}
+ \fi
+ \endgraf
+ \ifvmode\prevdepth\strutdp\fi
+ \egroup}
\unexpanded\def\startcolumnspan
{\dosingleempty\dostartcolumnspan}
\unexpanded\def\stopcolumnspan
{\egroup}
-
+
\setupcolumns
[\c!n=2,
\c!ntop=1,
@@ -1737,7 +1618,7 @@
\c!option=,
\c!rulethickness=\linewidth,
\c!offset=.5\bodyfontsize]
-
+
%D Undocumented and still under development.
\unexpanded\def\startsimplecolumns
@@ -1760,4 +1641,36 @@
\rigidcolumnbalance\scratchbox
\egroup}
+\unexpanded\def\setsimplecolumnshsize[#1]%
+ {\getparameters[\??kl][\c!width=\hsize,\c!distance=1.5\bodyfontsize,\c!n=2,\c!lines=0,#1]%
+ \let\rigidcolumnlines\@@kllines
+ \setrigidcolumnhsize\@@klwidth\@@kldistance\@@kln}
+
+\let\page_mul_command_package_contents\page_one_command_package_contents
+\let\page_mul_command_flush_float_box \page_one_command_flush_float_box
+
+\defineoutputroutine
+ [\s!multicolumn]
+ [\s!page_otr_command_routine =\page_mul_command_routine,
+ \s!page_otr_command_package_contents =\page_mul_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_mul_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_mul_command_set_hsize,
+ \s!page_otr_command_next_page =\page_mul_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_mul_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_mul_command_synchronize_hsize,
+ % \s!page_otr_command_set_top_insertions =\page_mul_command_set_top_insertions,
+ % \s!page_otr_command_set_bottom_insertions =\page_mul_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions =\page_mul_command_flush_top_insertions,
+ % \s!page_otr_command_flush_bottom_insertions =\page_mul_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_mul_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_mul_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_mul_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats =\page_mul_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_mul_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_mul_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_mul_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_mul_command_flush_saved_floats
+ % \s!page_otr_command_flush_margin_blocks =\page_mul_command_flush_margin_blocks, % not used
+ ]
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-not.mkii b/Master/texmf-dist/tex/context/base/page-not.mkii
index 9c67f18f16b..7bb9824307c 100644
--- a/Master/texmf-dist/tex/context/base/page-not.mkii
+++ b/Master/texmf-dist/tex/context/base/page-not.mkii
@@ -5,7 +5,7 @@
%D subtitle=Footnotes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-not.mkiv b/Master/texmf-dist/tex/context/base/page-not.mkiv
index 95229f9d054..06e2f387589 100644
--- a/Master/texmf-dist/tex/context/base/page-not.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-not.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Footnotes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -23,7 +23,7 @@
\unprotect
\def\checkbegincolumnfootnotes % should happen inside otr
- {\ifcase\clevernotes
+ {\ifcase\c_strc_notes_page_location
\erasenotebackup
\else
\flushnotes
@@ -33,7 +33,7 @@
\def\checkendcolumnfootnotes
{\restorenotedata
- \ifcase\clevernotes\else
+ \ifcase\c_strc_notes_page_location\else
\restorenotecontent
\fi}
@@ -50,7 +50,7 @@
% hm
\def\checkbegincolumnfootnotes % should happen inside otr
- {\ifcase\clevernotes
+ {\ifcase\c_strc_notes_page_location
\erasenotebackup
\else
\flushnotes
@@ -61,7 +61,7 @@
\def\checkendcolumnfootnotes
{\restorenotedata
\ifinsidecolumns
- \ifcase\clevernotes\else
+ \ifcase\c_strc_notes_page_location\else
\restorenotecontent
\fi
\fi}
diff --git a/Master/texmf-dist/tex/context/base/page-one.mkii b/Master/texmf-dist/tex/context/base/page-one.mkii
index 1affc24d0e9..fe4b285cb91 100644
--- a/Master/texmf-dist/tex/context/base/page-one.mkii
+++ b/Master/texmf-dist/tex/context/base/page-one.mkii
@@ -5,7 +5,7 @@
%D subtitle=Default Routine,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-one.mkiv b/Master/texmf-dist/tex/context/base/page-one.mkiv
index babaf4f5ddb..89fd7d4a8a3 100644
--- a/Master/texmf-dist/tex/context/base/page-one.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-one.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Default Routine,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -20,22 +20,21 @@
% OTRONE: basic single column
-\activateotr{ONE}{} % the default one
+\newdimen\d_page_one_saved_vsize
-\newtoks\OTRONEoutput
+\unexpanded\def\page_one_command_next_page
+ {\page_otr_eject_page}
-\def\OTRONEgotonextpage
- {\ejectpage}
+\unexpanded\def\page_one_command_next_page_and_inserts
+ {\page_otr_eject_page_and_flush_inserts}
-\def\OTRONEgotonextpageX % will become obsolete
- {\superejectpage}
-
-\def\OTRONEsethsize
+\unexpanded\def\page_one_command_set_hsize
{\global\hsize\textwidth}
-\newdimen\oldvsize
+\unexpanded\def\page_one_command_set_float_hsize
+ {\global\hsize\textwidth}
-\def\OTRONEsetvsize
+\unexpanded\def\page_one_command_set_vsize
{\ifgridsnapping
\ifcase\layoutlines
\getrawnoflines\textheight
@@ -47,147 +46,180 @@
\global\vsize\textheight
\fi
\ifdim\pagegoal<\maxdimen
- \ifdim\oldvsize=\vsize
+ \ifdim\d_page_one_saved_vsize=\vsize
% let's assume that the layout didn't change
\else
- \bgroup
- \global\oldvsize\vsize
- \advance\vsize-\topinserted
- \advance\vsize-\botinserted
- \global\pagegoal\vsize
- \egroup
+ \global\d_page_one_saved_vsize\vsize
+ \global\pagegoal\dimexpr\vsize-\topinserted-\botinserted\relax
+% \bgroup
+% \global\d_page_one_saved_vsize\vsize
+% \advance\vsize-\topinserted
+% \advance\vsize-\botinserted
+% \global\pagegoal\vsize
+% \egroup
\fi
\fi}
-% can we avoind the extra vboxing here?
+% 1 = partial page, 2 = whole page, 3 = partial page
-\def\OTRONEregisteredtextarea#1%
- {\ifregistertextareas
- \setbox0\vbox{#1}%
- \wd0\makeupwidth % somehow a space creeps in
- \vbox{\registeredtextarea000}%
+\setnewconstant\kindofpagetextareas\plustwo % \plusone can become default some day
+
+\def\page_one_registered_text_area_a % two arguments: (un)vbox n
+ {\ifconditional\c_page_areas_enabled
+ \expandafter\page_one_registered_text_area_a_indeed
\else
- #1%
+ \expandafter\firstofoneargument
\fi}
-\def\doOTRONEregisteredtextareaA#1%
- {\ifregistertextareas
- \xypos{pbd:\realfolio:b}% we could save bytes by only saving the y
- \endgraf
- \begingroup
- \scratchdimen\dimexpr\MPy{pbd:\realfolio:b}-\MPy{pbd:\realfolio:e}\relax
- \setbox\scratchbox\emptyhbox
- \wd\scratchbox\makeupwidth
- \ht\scratchbox\scratchdimen
- \vsmash{\registeredtextarea00\scratchbox}%
- \endgroup
- #1%
- \endgraf
- \xypos{pbd:\realfolio:e}%
+\def\page_one_registered_text_area_b % one arguments: content
+ {\ifconditional\c_page_areas_enabled
+ \expandafter\page_one_registered_text_area_b_indeed
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\page_one_registered_text_area_a_indeed % two arguments: (un)vbox n
+ {\ifcase\kindofpagetextareas
+ \expandafter\firstofoneargument
+ \or % partial page (experimental)
+ \expandafter\page_areas_register_direct
+ \or % whole page (default)
+ \expandafter\firstofoneargument
\else
- #1%
+ \expandafter\firstofoneargument
\fi}
-\def\doOTRONEregisteredtextareaB#1%
- {\ifregistertextareas
- \setbox0\vbox{#1}%
- \wd0\makeupwidth % somehow a space creeps in
- \vbox{\registeredtextarea000}%
+\def\page_one_registered_text_area_b_indeed % one arguments: content
+ {\ifcase\kindofpagetextareas
+ % \expandafter\firstofoneargument
+ \or % partial page (experimental)
+ % \expandafter\firstofoneargument
+ \or % whole page (default)
+ \expandafter\page_areas_register_boxed
\else
- #1%
+ % \expandafter\firstofoneargument
\fi}
-\let\OTRONEregisteredtextareaA\firstofoneargument
-\let\OTRONEregisteredtextareaB\firstofoneargument
+\newdimen\d_page_one_natural_depth
+\newbox \b_page_one_bottom_notes
+\newbox \b_page_one_contents
-% 1 = partial page, 2 = whole page, 3 = partial page
+\let\page_one_command_package_show_state\relax
-\setnewconstant\kindofpagetextareas\plustwo
+% \fakepagenotes ... needs checking
+%
+% we can also have bottom notes on top of bottom insertions
-\def\OTRONEdopagecontents#1#2% \box<n> \unvbox<n>
- {\bgroup % niet breedte zetten, kan fractie zijn!
- \ifcase\kindofpagetextareas
- \or % partial page (experimental)
- \let\OTRONEregisteredtextareaA\doOTRONEregisteredtextareaA
- \or % whole page (default)
- \let\OTRONEregisteredtextareaB\doOTRONEregisteredtextareaB
- \or % partial page (only works well with no stretch!)
- \let\OTRONEregisteredtextareaA\doOTRONEregisteredtextareaB
- \fi
- \setbox0\vbox \ifbottomnotes to \textheight \fi
- {\edef\currentpagedepth{\the\dp#2}% still to be derived from #1
- \dotopinsertions
+\unexpanded\def\page_one_command_package_contents#1#2% \box<n> \unvbox<n> % this one will be redone (checked)
+ {\bgroup
+ \strc_notes_check_if_bottom_present
+ \d_page_one_natural_depth\dp#2\relax
+ % we need to set the height as otherwise the shrink will not kick in so the following
+ % no longer applies:
+ %
+ % \setbox\b_page_one_contents\vbox \ifconditional\c_notes_bottom_present to \textheight \fi
+ %
+ \setbox\b_page_one_contents\vbox to \textheight
+ {\page_otr_command_flush_top_insertions
+ % this is messy ... we will provide a more tight area (no big deal as we can
+ % do that at the lua end)
+ \page_one_registered_text_area_a#1#2% \unvbox <box>
+ %
\ifgridsnapping
- \OTRONEregisteredtextareaA{#1#2}%
- \vskip-\currentpagedepth\vskip\openstrutdepth
+ \vskip\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax
\prevdepth\openstrutdepth
- \dobotinsertions
+ \page_otr_command_flush_bottom_insertions
\vfil
- \else\ifr@ggedbottom
- \OTRONEregisteredtextareaA{#1#2}%
- \vskip-\currentpagedepth\vskip\openstrutdepth
+ \else\ifcase\bottomraggednessmode
+ % ragged (default)
+ \vskip\dimexpr\openstrutdepth-\d_page_one_natural_depth\relax
\prevdepth\openstrutdepth
- \dobotinsertions
+ \page_otr_command_flush_bottom_insertions
\vfil
- \else\ifb@selinebottom
- \OTRONEregisteredtextareaA{#1#2}%
- \kern-\currentpagedepth\kern\maxdepth
- \dobotinsertions
- \else
- \OTRONEregisteredtextareaA{#1#2}%
- \dobotinsertions % added
- \fi\fi\fi
- \fakepagenotes}% was \fakenotes, but wrong! (check with \setupalign[height])
- \ifbottomnotes
+ \or
+ % align (normal)
+ \page_otr_command_flush_bottom_insertions
+ \or
+ % baseline
+ \kern\dimexpr\maxdepth-\d_page_one_natural_depth\relax
+ \page_otr_command_flush_bottom_insertions
+ \fi\fi
+ \fakepagenotes}%
+ \page_one_command_package_show_state
+ \ifconditional\c_notes_bottom_present
\ifgridsnapping
- \ifcase\layoutlines % todo: make macro of this
+ \ifcase\layoutlines
\getrawnoflines\textheight
\else
\noflines\layoutlines
- \fi
- \advance\noflines \minusone
- \scratchdimen\noflines\lineheight
- \advance\scratchdimen \topskip
+ \fi
+ \scratchoffset\dimexpr\numexpr\noflines-\plusone\relax\lineheight+\topskip\relax
\else
- \scratchdimen\ht0
+ \scratchoffset\ht\b_page_one_contents
\fi
+ \setbox\b_page_one_bottom_notes\hbox
+ {\checksinglecolumnfootnotes % why this check? ***
+ \lower\scratchoffset\vbox{\placebottomnotes\par\kern\zeropoint}}% kerns makes notes sit on bottom
+ \smashbox\b_page_one_bottom_notes
+ \ht\b_page_one_contents\zeropoint
+ \page_one_registered_text_area_b
+ {\vbox to \textheight
+ {\box\b_page_one_contents
+ \box\b_page_one_bottom_notes}}%
\else
- \scratchdimen\zeropoint
- \fi
- \setbox2\hbox
- {\checksinglecolumnfootnotes
- \lower\scratchdimen\vbox{\placebottomnotes}}%
- \smashbox2% % needed here
- \ifbottomnotes
- \ht0\zeropoint
+ \ht\b_page_one_contents\textheight
+ \page_one_registered_text_area_b
+ {\box\b_page_one_contents}%
\fi
- \OTRONEregisteredtextareaB
- {\vbox to \textheight
- {\box0\box2\ifbottomnotes\else\vfill\fi}}%
\egroup}
-\def\OTRONEfinalsidefloatoutput
- {\finaloutput\unvbox\normalpagebox}
+\unexpanded\def\page_one_command_side_float_output
+ {\page_otr_construct_and_shipout\unvbox\normalpagebox}
-\OTRONEoutput
- {\sidefloatoutput}
+\unexpanded\def\page_one_command_routine
+ {\page_sides_output_routine}
%D Insertions
-\newif\iftopofinsert
+\newconditional\c_page_one_top_of_insert
+\newconditional\c_page_one_correct_top_insert \settrue\c_page_one_correct_top_insert % false moves up (tight)
+\newskip \s_page_one_between_top_insert
+
+\def\page_one_prepare_top_float
+ {\ifdim\topinserted=\zeropoint
+ \settrue\c_page_one_top_of_insert
+ \else
+ \setfalse\c_page_one_top_of_insert
+ \fi
+ \s_page_one_between_top_insert\ifdim\floattopskip>\floatbottomskip\floattopskip\else\floatbottomskip\fi\relax
+ \global\advance\topinserted\dimexpr\ht\floatbox+\dp\floatbox+\s_page_one_between_top_insert\relax}
+
+\def\page_one_insert_top_float % maybe remember last beforeskip
+ {\insert\topins
+ {\forgetall
+ \ifconditional\c_page_one_top_of_insert
+ \ifconditional\c_page_one_correct_top_insert
+ \topskipcorrection % [xx] new: see icare topbleed
+ \kern-\lineskip
+ \par
+ \prevdepth\maxdimen
+ \fi
+ \fi
+ \page_otr_command_flush_float_box
+ \vskip\s_page_one_between_top_insert}}
-\def\OTRONEdosettopinserts
+\unexpanded\def\page_one_command_set_top_insertions
{\bgroup
\ifsomefloatwaiting
\noffloatinserts\zerocount
\let\totaltopinserted\!!zeropoint
- \OTRONEdodosettopinserts
- \ifnum\@@bknbottom=\zerocount
- \ifnum\@@bknlines>\zerocount
+ \page_one_command_set_top_insertions_indeed
+ \ifnum\rootfloatparameter\c!nbottom=\zerocount
+ \ifnum\rootfloatparameter\c!nlines>\zerocount
\ifdim\totaltopinserted>\zeropoint\relax
- \ifdim\dimexpr\@@bknlines\lineheight+\totaltopinserted\relax>\textheight
- \showmessage\m!floatblocks8\@@bknlines
- \vfilll\eject
+ \ifdim\dimexpr\rootfloatparameter\c!nlines\lineheight+\totaltopinserted\relax>\textheight
+ \showmessage\m!floatblocks8{\rootfloatparameter\c!nlines}%
+ \page_otr_fill_and_eject_page % was tripple: vfilll
\fi
\fi
\fi
@@ -195,29 +227,13 @@
\fi
\egroup}
-\def\OTRONEdodosettopinserts
+\def\page_one_command_set_top_insertions_indeed
{\ifnum\noffloatinserts<\noftopfloats
\dogetfloat
- \ifdim\topinserted=\zeropoint
- \topofinserttrue
- \else
- \topofinsertfalse
- \fi
- \global\advance\topinserted\dimexpr\ht\floatbox+\dp\floatbox+\floatbottomskip\relax
+ \page_one_prepare_top_float
\ifdim\topinserted<\textheight\relax
\xdef\totaltopinserted{\the\topinserted}%
- \insert\topins
- {\forgetall
- \iftopofinsert
- \topskipcorrection % [xx] new: see icare topbleed
- \kern-\lineskip\par
- \prevdepth\maxdimen
- \else
- %\blank[-\@@bkspaceafter,\@@bkspacebefore]% inserts can't look back
- \betweenfloatblanko
- \fi
- \flushfloatbox
- \blank[\@@bkspaceafter]}%
+ \page_one_insert_top_float
\ifsomefloatwaiting
\advance\noffloatinserts \plusone
\else
@@ -232,19 +248,19 @@
\ifsomefloatwaiting
\showmessage\m!floatblocks6{\the\noftopfloats}%
\fi
- \let\OTRONEdodosettopinserts\relax
+ \let\page_one_command_set_top_insertions_indeed\relax
\fi
- \OTRONEdodosettopinserts}
+ \page_one_command_set_top_insertions_indeed}
-\def\OTRONEdosetbotinserts
+\unexpanded\def\page_one_command_set_bottom_insertions
{\bgroup
\ifsomefloatwaiting
\noffloatinserts\zerocount
- \OTRONEdodosetbotinserts
+ \page_one_command_set_bottom_insertions_indeed
\fi
\egroup}
-\def\OTRONEdodosetbotinserts
+\def\page_one_command_set_bottom_insertions_indeed
{\ifnum\noffloatinserts<\nofbotfloats\relax
\dogetfloat
\global\advance\botinserted \ht\floatbox\relax
@@ -253,8 +269,8 @@
\ifdim\botinserted<\pagegoal\relax
\insert\botins
{\forgetall
- \blank[\@@bkspacebefore]%
- \flushfloatbox}%
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box}%
\ifsomefloatwaiting
\advance\noffloatinserts \plusone
\else
@@ -270,24 +286,13 @@
\ifsomefloatwaiting
\showmessage\m!floatblocks7{\the\nofbotfloats}%
\fi
- \let\OTRONEdodosetbotinserts\relax
+ \let\page_one_command_set_bottom_insertions_indeed\relax
\fi
- \OTRONEdodosetbotinserts}
-
-\def\OTRONEdosetbothinserts
- {\global\topinserted\zeropoint
- \global\botinserted\zeropoint
- \ifflushingfloats \else
- \OTRONEdosettopinserts
- \OTRONEdosetbotinserts
- \ifsomefloatwaiting
- \doif\@@bkcache\v!no\doflushfloats
- \fi
- \fi}
+ \page_one_command_set_bottom_insertions_indeed}
\newconstant\topinserttopskipmode % 1 = no topskip
-\def\OTRONEdotopinsertions
+\unexpanded\def\page_one_command_flush_top_insertions
{\ifvoid\topins\else
\ifgridsnapping
\box\topins
@@ -306,7 +311,7 @@
\fi
\global\topinserted\zeropoint}
-\def\OTRONEdobotinsertions
+\unexpanded\def\page_one_command_flush_bottom_insertions
{\ifvoid\botins\else
\ifgridsnapping
% \floatparameter\c!bottombefore
@@ -321,37 +326,40 @@
\global\botinserted\zeropoint
\global\nofloatpermittedfalse}
-\def\OTRONEdoflushfloats
+\unexpanded\def\page_one_command_flush_floats
{\global\flushingfloatstrue
\ifsomefloatwaiting
\par
% if kept, then option and definitely off in gridmode ! ! ! !
% \ifvmode \prevdepth\maxdimen \fi % prevents whitespace; problematic in icare tests
- \OTRONEdodoflushfloats
+ \page_one_command_flush_floats_indeed
\fi
\global\savednoffloats\zerocount
\global\somefloatwaitingfalse
\global\flushingfloatsfalse}
-\def\OTRONEflushfloatbox % nog verder doorvoeren en meer info in marge
+\unexpanded\def\page_one_command_flush_float_box
{\ifcenterfloatbox \ifdim\wd\floatbox<\hsize
\global\setbox\floatbox\hbox to \hsize{\hss\box\floatbox\hss}%
\fi \fi
\snaptogrid\hbox{\iftestfloatbox\ruledhbox\fi{\box\floatbox}}} % was copy
-\def\OTRONEdodoflushfloats % much in common with OTRSET
+\def\page_one_command_flush_floats_indeed % much in common with OTRSET
{\ifsomefloatwaiting
\ifpackflushedfloats
\centerfloatboxfalse % not needed as we do call directly
\dofloatscollect\s!text{\hsize}{1em}%
- \OTRONEsetvsize
+ %% no longer (interferes with footnotes):
+ %%
+ %% \page_one_command_set_vsize % test 2011.06.24.001
+ %%
\global\setbox\floatbox\hbox to \hsize
{\hfil
\dorecurse\nofcollectedfloats
{\ifcase\columndirection % nog document wide
\dofloatsflush\s!text{1}%
\else
- \dofloatsflushn\s!text{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}%
+ \dofloatsflush\s!text{\the\numexpr\nofcollectedfloats-\recurselevel+1\relax}%
\fi
\ifdim\wd\floatbox>\makeupwidth % \hsize
\hbox to \makeupwidth{\hss\box\floatbox\hss}%
@@ -369,10 +377,23 @@
% fits on a page where it was first rejected, in which case
% the prevdepth is -maxdimen and we cannot obey the grid
\doplacefloatbox
- \expandafter\OTRONEdodoflushfloats
+ \expandafter\page_one_command_flush_floats_indeed
+ \fi}
+
+\unexpanded\def\page_one_command_flush_margin_blocks
+ {\ifconditional\c_page_margin_blocks_present % \ifvoid\b_page_margin_blocks \else
+ \ifdim\pagetotal=\zeropoint
+ \null % \fixedspace
+ \fi
+ \page_otr_command_next_page % \page
+ \ifvoid\b_page_margin_blocks
+ \global\setfalse\c_page_margin_blocks_present
+ \else
+ \doubleexpandafter\page_one_command_flush_margin_blocks
+ \fi
\fi}
-\def\OTRONEdocheckiffloatfits % vervangen ivm downward comp
+\unexpanded\def\page_one_command_check_if_float_fits
{\ifnofloatpermitted
\global\roomforfloatfalse
\else
@@ -404,131 +425,174 @@
\fi
\fi}
-\def\OTRONEflushsavedfloats
- {\dosetbothinserts}
-
-% TODO: TEST FIRST, NO CORRECTION NEEDED IN GRID MODE, EVT OPTION
+\unexpanded\def\page_one_command_flush_saved_floats
+ {\global\topinserted\zeropoint
+ \global\botinserted\zeropoint
+ \ifflushingfloats \else
+ \page_one_command_set_top_insertions
+ \page_one_command_set_bottom_insertions
+ \ifsomefloatwaiting
+ \doif{\rootfloatparameter\c!cache}\v!no\page_one_command_flush_floats % could be _otr_
+ \else\ifconditional\c_page_margin_blocks_present
+ \page_one_command_flush_floats
+ \fi\fi
+ \fi}
-\def\OTRONEsomeherefloat[#1]% spacing between two successive must be better
- {\baselinecorrection % not really needed in grid mode:
- %\ifgridsnapping \else \baselinecorrection \fi % ! ! ! test test test ! ! ! !
+\def\page_one_place_float_here_indeed
+ {%\ifgridsnapping \else
+ \baselinecorrection
+ %\fi
\doplacefloatbox
\doinsertfloatinfo
\dohandlenextfloatindent}
-% \def\OTRONEsomefixdfloat % [#1]
-% {\docheckiffloatfits
-% \ifroomforfloat\else
-% \goodbreak
-% \fi
-% \showmessage\m!floatblocks9\empty
-% \someherefloat} % [#1]
-%
-% better:
-%
-% \dorecurse{50}
-% {[before normal] \input thuan
-% \placefigure{normal}{\framed[height=1cm,width=8cm]{}}
-% \placefigure{normal}{\framed[height=2cm,width=8cm]{}}
-% [before force] \input thuan
-% \placefigure[force]{force}{\framed[height=8cm,width=8cm]{}}}
-
-\setnewconstant\fixedfloatmethod\plusthree
-
-% \def\OTRONEsomefixdfloat % [#1]
-% {\docheckiffloatfits
-% \ifroomforfloat\else
-% \ifzeropt\pagetotal
-% % let's assume that there is room
-% \else
-% \ifcase\fixedfloatmethod
-% % disabled
-% \or % 1 (old method)
-% \goodbreak
-% \or % 2 (safe method)
-% \page
-% \or % 3 (keeps in stream)
-% \vskip\textheight
-% \vskip-\textheight
-% \or % 4 (also keeps in place)
-% \dosomebreak\nobreak
-% \fi
-% \fi
-% \fi
-% \showmessage\m!floatblocks9\empty
-% \someherefloat} % [#1]
-
-\def\OTRONEsomefixdfloat % [#1]
- {% there is (in mkii) no good way to prevent a break
- % so better fail than mess, we can get loose from
- % heads, so be it
- \showmessage\m!floatblocks9\empty
- \OTRONEsomeherefloat} % [#1]
-
-\def\OTRONEsomesidefloat[#1]% links, rechts NOG TESTEN EN AANPASSEN
- {\ifinsidecolumns
- \someelsefloat[\v!here]%
- \else
- %\checkwaitingfloats{#1}%
- \def\logsidefloat
- {\doinsertfloatinfo}%
- \setbox\floatbox\vbox{\box\floatbox}%
- \wd\floatbox\floatwidth
- \processfirstactioninset
- [#1]
- [ \v!left=>\leftfloat {\box\floatbox},
- \v!right=>\rightfloat {\box\floatbox},
- \v!inleft=>\leftmarginfloat {\box\floatbox},
- \v!inright=>\rightmarginfloat{\box\floatbox},
- \v!leftmargin=>\leftmarginfloat {\box\floatbox},
- \v!rightmargin=>\rightmarginfloat{\box\floatbox},
- \v!leftedge=>\leftedgefloat {\box\floatbox},
- \v!rightedge=>\rightedgefloat {\box\floatbox},
- \v!backspace=>\backspacefloat {\box\floatbox},
- \v!cutspace=>\cutspacefloat {\box\floatbox},
- \v!inmargin=>\cutspacefloat {\box\floatbox}]%
- \doifinset\v!tall{#1}\flushsidefloatsafterpar
- \fi}
+\def\page_one_place_float_force
+ {\showmessage\m!floatblocks9\empty
+ \page_one_place_float_here_indeed}
+
+\def\page_one_place_float_side_indeed#1%
+ {\setbox\floatbox\vbox{\box\floatbox}% ? can go
+ \wd\floatbox\floatwidth
+ #1{\box\floatbox}%
+ \doifinset\v!tall\floatlocationmethod\page_sides_flush_floats_after_par}
+
+\def\page_one_place_float_left {\page_one_place_float_side_indeed\page_sides_process_float_left\presetindentation}
+\def\page_one_place_float_right {\page_one_place_float_side_indeed\page_sides_process_float_right}
+\def\page_one_place_float_leftmargin {\page_one_place_float_side_indeed\page_sides_process_float_leftmargin}
+\def\page_one_place_float_rightmargin{\page_one_place_float_side_indeed\page_sides_process_float_rightmargin}
+\def\page_one_place_float_leftedge {\page_one_place_float_side_indeed\page_sides_process_float_leftedge}
+\def\page_one_place_float_rightedge {\page_one_place_float_side_indeed\page_sides_process_float_rightedge}
+\def\page_one_place_float_inmargin {\page_one_place_float_side_indeed\page_sides_process_float_cutspace}
+\def\page_one_place_float_backspace {\page_one_place_float_side_indeed\page_sides_process_float_backspace}
+\def\page_one_place_float_cutspace {\page_one_place_float_side_indeed\page_sides_process_float_cutspace}
+
+%def\page_one_place_float_margin {\page_one_place_float_side_indeed\page_sides_process_float_margin\nonoindentation} % wil be overloaded
+\def\page_one_place_float_margin {\page_margin_blocks_process_float}
+
+\def\page_one_place_float_page {\dofloatssavepagefloat \s!page \floatlocationmethod}
+\def\page_one_place_float_leftpage {\dofloatssavepagefloat \s!leftpage \floatlocationmethod}
+\def\page_one_place_float_rightpage {\dofloatssavepagefloat \s!rightpage\floatlocationmethod}
+\def\page_one_place_float_somewhere {\dofloatssavesomewherefloat\s!somewhere\floatlocationmethod}
+
+\def\page_one_place_float_here {\page_one_place_float_otherwise_here}
+\def\page_one_place_float_auto {\page_one_place_float_otherwise}
+\def\page_one_place_float_top {\page_one_place_float_otherwise\nonoindentation}
+\def\page_one_place_float_bottom {\page_one_place_float_otherwise}
+
+\def\page_one_place_float_otherwise
+ {\doifinsetelse\v!here\floatlocationmethod
+ \page_one_place_float_otherwise_here
+ \page_one_place_float_otherwise_else}
+
+\def\page_one_place_float_otherwise_here
+ {\doifinsetelse\v!always\floatlocationmethod
+ {\page[\v!preference]%
+ \page_otr_command_check_if_float_fits
+ \ifroomforfloat
+ \page_one_place_float_here_indeed
+ \else
+ \showmessage\m!floatblocks9\empty
+ \doreversesavefloat
+ \fi}
+ {\ifsomefloatwaiting
+ \dosavefloat
+ \else
+ \page[\v!preference]%
+ \page_otr_command_check_if_float_fits
+ \ifroomforfloat
+ \page_one_place_float_here_indeed
+ \else
+ \dosavefloat
+ \fi
+ \fi}}
-\def\OTRONEsomepagefloat [#1]{\dofloatssavepagefloat {\s!page} {#1}}
-\def\OTRONEsomeleftpagefloat [#1]{\dofloatssavepagefloat {\s!leftpage} {#1}}
-\def\OTRONEsomerightpagefloat[#1]{\dofloatssavepagefloat {\s!rightpage}{#1}}
+\def\page_one_place_float_otherwise_else
+ {\doifinsetelse\v!always\floatlocationmethod
+ {\page_otr_command_check_if_float_fits
+ \ifroomforfloat
+ \page_one_place_float_auto_top_bottom
+ \else
+ \showmessage\m!floatblocks9\empty
+ \doreversesavefloat
+ \fi}
+ {\page_otr_command_check_if_float_fits
+ \ifroomforfloat
+ \page_one_place_float_auto_top_bottom
+ \else
+ \dosavefloat
+ \fi}}
-%def\OTRONEsomesoemwherefloat[#1]{\dofloatssavesomewherefloat{\s!somewhere}{#1}}
+\def\floatautofactor{.5}
-\def\OTRONEsometopsfloat[#1]%
- {\ifdim\topinserted=\zeropoint
- \topofinserttrue
+\def\page_one_place_float_auto_top_bottom
+ {\ifx\floatmethod\v!auto
+ \ifdim\pagetotal<\floatautofactor\pagegoal % when empty page, maxdimen
+ \page_one_place_float_top_indeed
+ \else
+ \page_one_place_float_bottom_indeed
+ \fi
\else
- \topofinsertfalse
- \fi
- \global\advance\topinserted\dimexpr\ht\floatbox+\dp\floatbox+\floatbottomskip\relax
- \insert\topins
- {\forgetall
- \iftopofinsert
- \topskipcorrection % [xx] new: see icare topbleed
- \kern-\lineskip\par\prevdepth\maxdimen
- \else
- %\blank[-\@@bkspaceafter,\@@bkspacebefore]% inserts can't look back
- \betweenfloatblanko
- \fi
- \flushfloatbox
- \blank[\@@bkspaceafter]}%
+ \ifx\floatmethod\v!top
+ \page_one_place_float_top_indeed
+ \else\ifx\floatmethod\v!bottom
+ \page_one_place_float_bottom_indeed
+ \else
+ \page_one_place_float_here_indeed
+ \fi\fi
+ \fi}
+
+\def\page_one_place_float_top_indeed % maybe remember last beforeskip
+ {\page_one_prepare_top_float
+ \page_one_insert_top_float
\doinsertfloatinfo}
-\def\OTRONEsomebotsfloat[#1]%
+\def\page_one_place_float_bottom_indeed
{\global\advance\botinserted\dimexpr\ht\floatbox+\dp\floatbox+\floattopskip\relax
\insert\botins
{\forgetall
- \blank[\@@bkspacebefore]%
- \flushfloatbox}%
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box}%
%\global\nofloatpermittedtrue
\doinsertfloatinfo}
-\def\OTRONEsomefacefloat[#1]% untested
- {\startopposite\flushfloatbox\stopopposite}
-
-\def\OTRONEnextcolumn[#1]%
- {}
+\def\page_one_place_float_face % links, rechts, midden, hoog, midden, laag
+ {%\checkwaitingfloats{#1}%
+ \startopposite
+ \page_otr_command_flush_float_box
+ \stopopposite
+ }%\doinsertfloatinfo}
+
+\unexpanded\def\page_one_command_flush_side_floats
+ {\page_sides_flush_floats}
+
+\unexpanded\def\page_one_command_synchronize_side_floats
+ {\page_sides_synchronize_floats}
+
+\defineoutputroutine
+ [\s!singlecolumn]
+ [\s!page_otr_command_routine =\page_one_command_routine,
+ \s!page_otr_command_package_contents =\page_one_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_one_command_set_vsize,
+ \s!page_otr_command_set_hsize =\page_one_command_set_hsize,
+ \s!page_otr_command_next_page =\page_one_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_one_command_next_page_and_inserts,
+ % \s!page_otr_command_synchronize_hsize =\page_one_command_synchronize_hsize,
+ \s!page_otr_command_set_top_insertions =\page_one_command_set_top_insertions,
+ \s!page_otr_command_set_bottom_insertions =\page_one_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions =\page_one_command_flush_top_insertions,
+ \s!page_otr_command_flush_bottom_insertions=\page_one_command_flush_bottom_insertions,
+ % \s!page_otr_command_set_float_hsize =\page_one_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_one_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_one_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats=\page_one_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_one_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_one_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_one_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_one_command_flush_saved_floats,
+ \s!page_otr_command_flush_margin_blocks =\page_one_command_flush_margin_blocks
+ ]
+
+% \setupoutputroutine
+% [\s!singlecolumn]
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-otr.mkvi b/Master/texmf-dist/tex/context/base/page-otr.mkvi
new file mode 100644
index 00000000000..19c308c32af
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-otr.mkvi
@@ -0,0 +1,290 @@
+%D \module
+%D [ file=page-otr,
+%D version=2012.01.25,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Output Routines,
+%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 / Output Routines}
+
+%D This module will get some of the code from other modules. At the
+%D same time we provide a bit more control.
+
+% When issuing two \par\penalty-\plustenthousand's, only the first
+% triggers the otr. Is this an obscure feature or an optimization?
+
+\unprotect
+
+\def\m!otr{otr} % todo
+
+\installcorenamespace{outputroutine}
+
+\installswitchcommandhandler \??outputroutine {outputroutine} \??outputroutine
+
+\newtoks\t_page_otr_commands
+\newtoks\t_page_otr_tracers
+
+\unexpanded\def\defineoutputroutinecommand[#name]% doing multiple on one go saves syncing
+ {\processcommalist[#name]\page_otr_commands_define}
+
+\unexpanded\def\page_otr_commands_define#name%
+ {\ifcsname#name\endcsname \else
+ \expandafter\let\csname#name\endcsname\relax
+ \normalexpanded{\t_page_otr_commands{\the\t_page_otr_commands\noexpand\page_otr_commands_process{#name}}}%
+ \fi}
+
+\let\page_otr_commands_process\gobbleoneargument
+
+\appendtoks
+ \let\page_otr_commands_process\page_otr_specifics_preset
+ \the\t_page_otr_commands
+ \let\page_otr_commands_process\gobbleoneargument
+\to \everyswitchoutputroutine
+
+\unexpanded\def\page_otr_specifics_preset#1%
+ {\edef\page_otr_specifics_command{\strictoutputroutineparameter{#1}}% no inheritance of commands
+ \ifx\page_otr_specifics_command\empty
+ \writestatus{\currentoutputroutine}{- \expandafter\strippedcsname\csname#1\endcsname}%
+ \expandafter\let\csname#1\endcsname\relax
+ \else
+ \writestatus{\currentoutputroutine}{+ \expandafter\strippedcsname\csname#1\endcsname}%
+ \expandafter\let\csname#1\expandafter\endcsname\page_otr_specifics_command
+ \fi}
+
+\unexpanded\def\page_otr_specifics_preset_normal#1%
+ {\edef\page_otr_specifics_command{\strictoutputroutineparameter{#1}}% no inheritance of commands
+ \ifx\page_otr_specifics_command\empty
+ \expandafter\let\csname#1\endcsname\relax
+ \else
+ \expandafter\let\csname#1\expandafter\endcsname\page_otr_specifics_command
+ \fi}
+
+\unexpanded\def\page_otr_specifics_preset_traced#1%
+ {\edef\page_otr_specifics_command{\strictoutputroutineparameter{#1}}% no inheritance of commands
+ \ifx\page_otr_specifics_command\empty
+ \writestatus{\currentoutputroutine}{preset: - \expandafter\strippedcsname\csname#1\endcsname}%
+ \expandafter\let\csname#1\endcsname\relax
+ \else
+ \writestatus{\currentoutputroutine}{preset: + \expandafter\strippedcsname\csname#1\endcsname}%
+ \expandafter\let\csname#1\expandafter\endcsname\page_otr_specifics_command
+ \fi}
+
+\let\page_otr_specifics_preset\page_otr_specifics_preset_normal
+
+\unexpanded\def\traceoutputroutines
+ {\the\t_page_otr_tracers}
+
+\appendtoks
+ \let\page_otr_specifics_preset\page_otr_specifics_preset_traced
+\to \t_page_otr_tracers
+
+%D We have a couple of output routines and the default one is
+%D the single column routine. Then there is a multicolumn variant
+%D that can be used mixed, and a columnset variant that is more
+%D exclusive.
+
+\installcorenamespace{otrtriggers}
+
+\newconstant\c_page_otr_eject_penalty \c_page_otr_eject_penalty -\plustenthousand
+\newconstant\c_page_otr_super_penalty \c_page_otr_super_penalty -\plustwentythousand
+\newcount \c_page_otf_trigger_penalty \c_page_otf_trigger_penalty -100010
+
+\newif \ifinotr % we keep this (name) for old times sake
+
+\unexpanded\def\page_otr_message_b{\page_otr_message_s+}
+\unexpanded\def\page_otr_message_e{\page_otr_message_s-}
+
+\unexpanded\def\page_otr_message_s#1#2%
+ {\writestatus
+ \currentoutputroutine
+ {#1\space \space
+ #2\space \space
+ p:\the\outputpenalty,\space
+ r:\the\realpageno ,\space
+ c:\number\mofcolumns,\space
+ v:\the\vsize ,\space
+ g:\the\pagegoal ,\space
+ t:\the\pagetotal ,\space
+ \ifdim\pagetotal>\pagegoal
+ d:\the\dimexpr\pagetotal-\pagegoal\relax
+ \fi}}
+
+\unexpanded\def\page_otr_trigger#1%
+ {\begingroup
+ \par
+ \penalty#1%
+ \endgroup}
+
+\unexpanded\def\installoutputroutine#1#2% \invoke \action
+ {\global\advance\c_page_otf_trigger_penalty\minusone
+ \edef#1{\page_otr_trigger{\number\c_page_otf_trigger_penalty}}%
+ \setvalue{\??otrtriggers\number\c_page_otf_trigger_penalty}{#2}}
+
+\unexpanded\def\page_otr_triggered_output_routine_traced
+ {\ifcsname\??otrtriggers\the\outputpenalty\endcsname
+ \page_otr_message_b{special}%
+ \csname\??otrtriggers\the\outputpenalty\endcsname
+ \page_otr_message_e{special}%
+ \else
+ \page_otr_message_b{normal}%
+ \page_otr_command_routine
+ \page_otr_message_e{normal}%
+ \fi}
+
+\unexpanded\def\page_otr_triggered_output_routine_normal
+ {\ifcsname\??otrtriggers\the\outputpenalty\endcsname
+ \csname\??otrtriggers\the\outputpenalty\endcsname
+ \else
+ \page_otr_command_routine
+ \fi}
+
+\let\page_otr_triggered_output_routine\page_otr_triggered_output_routine_normal
+
+\appendtoks
+ \let\page_otr_triggered_output_routine\page_otr_triggered_output_routine_traced
+\to \t_page_otr_tracers
+
+%D The real routine handler:
+
+\ifdefined\everybeforeoutput \else \newtoks\everybeforeoutput \fi
+\ifdefined\everyafteroutput \else \newtoks\everyafteroutput \fi
+
+\def\page_otf_set_engine_output_routine#1%
+ {\global\output
+ {\inotrtrue
+ \the\everybeforeoutput
+ #1\relax
+ \the\everyafteroutput}}
+
+\page_otf_set_engine_output_routine\page_otr_triggered_output_routine
+
+\installoutputroutine\synchronizeoutput
+ {\ifvoid\normalpagebox\else
+ \unvbox\normalpagebox
+ \pagediscards
+ \fi}
+
+\installoutputroutine\discardpage
+ {\setbox\scratchbox\box\normalpagebox}
+
+% todo: \resetpagebreak -> everyejectpage
+
+\def\page_otr_trigger_output_routine
+ {\par
+ \ifvmode
+ \penalty\c_page_otr_eject_penalty
+ \fi
+ \resetpagebreak}
+
+\def\page_otr_fill_and_eject_page
+ {\par
+ \ifvmode
+ \vfill
+ \penalty\c_page_otr_eject_penalty
+ \fi
+ \resetpagebreak}
+
+\def\page_otr_eject_page
+ {\par
+ \ifvmode
+ \ifdim\pagetotal>\pagegoal \else
+ \normalvfil
+ \fi
+ \penalty\c_page_otr_eject_penalty
+ \fi
+ \resetpagebreak}
+
+\def\page_otr_eject_page_and_flush_inserts % can be an installed one
+ {\par
+ \ifvmode
+ \ifdim\pagetotal>\pagegoal \else
+ \normalvfil
+ \fi
+ \penalty\c_page_otr_super_penalty
+ \fi
+ \resetpagebreak}
+
+\def\page_otr_check_for_pending_inserts
+ {\ifnum\outputpenalty>\c_page_otr_super_penalty \else
+ \ifnum\insertpenalties>\zerocount
+ % something is being held over so we force a new page
+ \page_otr_force_another_page
+ \fi
+ \fi}
+
+\def\page_otr_force_another_page
+ {% we should actually remove the dummy line in the otr
+ \hbox to \hsize{}%
+ \kern-\topskip
+ \nobreak
+ \vfill
+ \penalty\c_page_otr_super_penalty
+ \resetpagebreak}
+
+%D For those who've read the plain \TEX\ book, we provide the next
+%D macro:
+
+\unexpanded\def\bye
+ {\writestatus\m!system{Sorry, you're not done yet, so no goodbye!}}
+
+%D We define a few constants because that (1) provides some checking
+%D and (2) is handier when aligning definitions (checks nicer).
+
+\definesystemconstant{page_otr_command_routine}
+\definesystemconstant{page_otr_command_package_contents}
+\definesystemconstant{page_otr_command_set_vsize}
+\definesystemconstant{page_otr_command_set_hsize}
+\definesystemconstant{page_otr_command_synchronize_hsize}
+\definesystemconstant{page_otr_command_next_page}
+\definesystemconstant{page_otr_command_next_page_and_inserts}
+\definesystemconstant{page_otr_command_set_top_insertions}
+\definesystemconstant{page_otr_command_set_bottom_insertions}
+\definesystemconstant{page_otr_command_flush_top_insertions}
+\definesystemconstant{page_otr_command_flush_bottom_insertions}
+\definesystemconstant{page_otr_command_check_if_float_fits}
+\definesystemconstant{page_otr_command_set_float_hsize}
+\definesystemconstant{page_otr_command_flush_float_box}
+\definesystemconstant{page_otr_command_side_float_output}
+\definesystemconstant{page_otr_command_synchronize_side_floats}
+\definesystemconstant{page_otr_command_flush_floats}
+\definesystemconstant{page_otr_command_flush_side_floats}
+\definesystemconstant{page_otr_command_flush_saved_floats}
+\definesystemconstant{page_otr_command_flush_margin_blocks}
+
+\definesystemconstant{singlecolumn}
+\definesystemconstant{multicolumn}
+\definesystemconstant{columnset}
+
+\defineoutputroutinecommand
+ [\s!page_otr_command_routine,
+ \s!page_otr_command_package_contents,
+ \s!page_otr_command_set_vsize,
+ \s!page_otr_command_set_hsize,
+ \s!page_otr_command_synchronize_hsize, % for columns of different width
+ \s!page_otr_command_next_page,
+ \s!page_otr_command_next_page_and_inserts,
+ \s!page_otr_command_set_top_insertions,
+ \s!page_otr_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions,
+ \s!page_otr_command_flush_bottom_insertions,
+ \s!page_otr_command_check_if_float_fits,
+ \s!page_otr_command_set_float_hsize,
+ \s!page_otr_command_flush_float_box,
+ \s!page_otr_command_side_float_output, % name will change as will hooks
+ \s!page_otr_command_synchronize_side_floats,
+ \s!page_otr_command_flush_floats,
+ \s!page_otr_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats,
+ \s!page_otr_command_flush_margin_blocks]
+
+\appendtoks
+ \setupoutputroutine[\s!singlecolumn]%
+\to \everydump
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-par.mkii b/Master/texmf-dist/tex/context/base/page-par.mkii
index a5dea2e635d..9b5e0b6ebfa 100644
--- a/Master/texmf-dist/tex/context/base/page-par.mkii
+++ b/Master/texmf-dist/tex/context/base/page-par.mkii
@@ -5,7 +5,7 @@
%D subtitle=Line Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-par.mkiv b/Master/texmf-dist/tex/context/base/page-par.mkiv
index c687c424dbf..26e306ef50f 100644
--- a/Master/texmf-dist/tex/context/base/page-par.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-par.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Line Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -34,7 +34,10 @@
\def\dodoshowparagraphnumber
{\global\advance\internalparagraphnumber \plusone
\inleftmargin % \tf normalizes em
- {\tf{\doattributes\??ph\c!style\c!color{\the\internalparagraphnumber}}%
+ {\tf
+ \dousestyleparameter\@phstyle
+ \dousecolorparameter\@phcolor
+ \the\internalparagraphnumber
\kern\@@phdistance}}
\def\doshowparagraphnumberA
diff --git a/Master/texmf-dist/tex/context/base/page-plg.mkii b/Master/texmf-dist/tex/context/base/page-plg.mkii
index 3203b923cbf..3c3255f4c70 100644
--- a/Master/texmf-dist/tex/context/base/page-plg.mkii
+++ b/Master/texmf-dist/tex/context/base/page-plg.mkii
@@ -5,7 +5,7 @@
%D subtitle=Page Setup,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-plg.mkiv b/Master/texmf-dist/tex/context/base/page-plg.mkiv
index 83c3e77f114..004b9204d38 100644
--- a/Master/texmf-dist/tex/context/base/page-plg.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-plg.mkiv
@@ -5,13 +5,13 @@
%D subtitle=Page Setup,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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.
-\ifx\pageareabox\undefined \else \endinput \fi
+% \ifx\pageareabox\undefined \else \endinput \fi
\writestatus{loading}{ConTeXt Page Macros / Extra Page Building}
@@ -110,67 +110,64 @@
\unprotect
-\setvalue{\??ly\c!method\v!makeup}#1#2%
- {\setbox\pagebox\hbox
+\def\page_boxes_construct_content_makeup#1#2#3% targetbox flusher box
+ {\setbox#1\hbox
{\vbox to \textheight
{\offinterlineskip
- % optie
- \vskip\dimexpr-1\topskip+\strutheight\relax
- %
+ \vskip\dimexpr-1\topskip+\strutheight\relax % could be an option
\textwidth\makeupwidth
\hsize\textwidth
\boxmaxdepth\maxdepth
\noindent
- \dopagecontents#1#2}}%
- \wd\pagebox\makeupwidth
- \ht\pagebox\textheight
- \dp\pagebox\zeropoint
+ \page_otr_command_package_contents#2#3}}%
+ \wd#1\makeupwidth
+ \ht#1\textheight
+ \dp#1\zeropoint
\hsize\paperwidth
\vsize\paperheight
- \setbox\pagebox\vbox
- {\doifbothsidesoverruled
- {\let\!!stringa\v!page}
- {\let\!!stringa\v!rightpage}
- {\let\!!stringa\v!leftpage}%
- \getvalue{\??ly\c!method:\!!stringa}}%
- \wd\pagebox\paperwidth
- \ht\pagebox\paperheight
- \dp\pagebox\zeropoint}
+ \setbox#1\vbox{\csname\??layoutmethod\doifbothsidesoverruled\v!page\v!rightpage\v!leftpage\endcsname}%
+ \wd#1\paperwidth
+ \ht#1\paperheight
+ \dp#1\zeropoint}
+
+\installlayoutalternative\v!makeup{\page_boxes_construct_content_makeup}
\newbox\pageareabox
-\def\pagearea
- {\dotripleempty\dopagearea}
+\unexpanded\def\pagearea
+ {\dotripleempty\page_area}
-\def\dopagearea[#1][#2][#3]%
+\def\page_area[#1][#2][#3]%
{\ifthirdargument
\doifelse{#3}\v!left
- {\dodopagearea{#1}{#2}\c!lefttext}
+ {\page_area_indeed{#1}{#2}\c!lefttext}
{\doifelse{#3}\v!right
- {\dodopagearea{#1}{#2}\c!righttext}
- {\dodopagearea{#1}{#2}\c!middletext}}%
+ {\page_area_indeed{#1}{#2}\c!righttext}
+ {\page_area_indeed{#1}{#2}\c!middletext}}%
\else\ifsecondargument
\doifbothsidesoverruled
- {\dodopagearea{#1}{#2}\c!righttext}
- {\dodopagearea{#1}{#2}\c!righttext}
- {\dodopagearea{#1}{#2}\c!lefttext }%
+ {\page_area_indeed{#1}{#2}\c!righttext}
+ {\page_area_indeed{#1}{#2}\c!righttext}
+ {\page_area_indeed{#1}{#2}\c!lefttext }%
\else
\doif{#1}\v!text % copy due to trial runs in TABLE
{\iftrialtypesetting
- \copy\pagebox
+% \copy\pagebox
+ \fakebox\pagebox
\else
- \localpositioningfalse
- \addtextbackground\pagebox
- \addtextgridlayer\pagebox
+% \localpositioningfalse
+ \page_backgrounds_add_to_text\pagebox
+ \page_grids_add_to_box\pagebox
\box\pagebox
\fi}%
\fi\fi}
-\def\dodopagearea#1#2#3%
- {\setbox\pageareabox\vbox{\getvalue{\??tk#1#2#3}}%
+\def\page_area_indeed#1#2#3%
+ {\setbox\pageareabox\vbox{\getspecificlayouttext{#1}{#2}{#3}}%
\ifsomebackgroundfound{#1#2}%
\iftrialtypesetting
- \box\pageareabox
+% \box\pageareabox
+ \fakebox\pageareabox
\else
\localframed
[\??ma#1#2]
@@ -183,16 +180,20 @@
\box\pageareabox
\fi}
-\setvalue{\??ly\c!method:\v!leftpage }{\getvalue{\??ly\c!method:\v!page}}
-\setvalue{\??ly\c!method:\v!rightpage}{\getvalue{\??ly\c!method:\v!page}}
+% to be done nicely (proper namespacing)
+
+\setvalue{\??layoutmethod\v!leftpage }{\csname\??layoutmethod\v!page\endcsname}
+\setvalue{\??layoutmethod\v!rightpage}{\csname\??layoutmethod\v!page\endcsname}
-% \long\unexpanded\def\startpagelayout[#1]#2\stoppagelayout
-% {\long\setvalue{\??ly\c!method:#1}{#2}}
+\unexpanded\def\startpagelayout
+ {\bgroup
+ \catcode\endoflineasciicode\ignorecatcode
+ \page_layouts_start_layout}
-\long\unexpanded\def\startpagelayout
- {\bgroup\catcode\endoflineasciicode\ignorecatcode\dostartpagelayout}
+\let\stoppagelayout\relax
-\long\def\dostartpagelayout[#1]#2\stoppagelayout
- {\egroup\long\setvalue{\??ly\c!method:#1}{#2}}
+\def\page_layouts_start_layout[#1]#2\stoppagelayout
+ {\egroup
+ \setvalue{\??layoutmethod#1}{#2}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-run.mkii b/Master/texmf-dist/tex/context/base/page-run.mkii
index ae5af81e94c..b128c192d87 100644
--- a/Master/texmf-dist/tex/context/base/page-run.mkii
+++ b/Master/texmf-dist/tex/context/base/page-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-run.mkiv b/Master/texmf-dist/tex/context/base/page-run.mkiv
index cce746c742f..62b1030ee11 100644
--- a/Master/texmf-dist/tex/context/base/page-run.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-run.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,122 +15,125 @@
\unprotect
-\gdef\doshowprint[#1][#2][#3]%
- {\framed
- [\c!offset=\v!overlay,
- \c!strut=\v!no]
- {\forgetall
- \dontcomplain
- \globaldefs\minusone
- \dimen\zerocount\pagegoal
- \definepapersize[X][\c!width=4em, \c!height=6em]%
- \definepapersize[Y][\c!width=12em,\c!height=14em]%
- \setuppapersize[#1,X][#2,Y]%
- \setuplayout[#3]%
- \setbox\zerocount\vbox
- {\framed
+\gdef\showprint
+ {\dotripleempty\page_layouts_show_print}
+
+\gdef\page_layouts_show_print[#1][#2][#3]% only english
+ {\setbuffer[crap]%
+ \unprotect
+ \definepapersize[X][\c!width=4em, \c!height=6em]
+ \definepapersize[Y][\c!width=12em,\c!height=14em]
+ \setuppapersize[X,#1][Y,#2]
+ \setuplayout[#3]
+ \setuplayout[\v!page]
+ \framed
[\c!offset=\v!overlay,\c!strut=\v!no,
\c!width=\paperwidth,\c!height=\paperheight]
- {\ss ABC\par DEF}}%
- \doublesidedfalse
- \def\cutmarklength{.5em}%
- \addpagecutmarks \zerocount
- \replicatepagebox\zerocount
- \scalepagebox \zerocount
- \mirrorpaperbox \zerocount
- \orientpaperbox \zerocount
- \centerpagebox \zerocount
- \mirrorprintbox \zerocount
- \orientprintbox \zerocount
- \offsetprintbox \zerocount
- \pagegoal\dimen\zerocount
- \box0}}
-
-\gdef\showprint
- {\dotripleempty\doshowprint}
+ {\ss ABC\par DEF}%
+ \protect
+ \endbuffer
+ \framed[\c!offset=\v!overlay,\c!strut=\v!no]{\typesetbuffer[crap]}}
-% \switchnaarkorps[8pt]
+% \switchtobodyfont[8pt]
%
-% \startcombinatie[4*4]
-% {\toonprint} {\strut}
-% {\toonprint[][][plaats=midden]} {\type{plaats=midden}}
-% {\toonprint[][][plaats=midden,markering=aan]} {\type{markering=aan}\break
-% \type{plaats=midden}}
-% {\toonprint[][][plaats=midden,markering=aan,nx=2]} {\type{markering=aan}\break
-% \type{plaats=midden}\break
-% \type{nx=2}}
-% {\toonprint[][][plaats=links]} {\type{plaats=links}}
-% {\toonprint[][][plaats=rechts]} {\type{plaats=rechts}}
-% {\toonprint[][][plaats={links,onder}]} {\type{plaats={links,onder}}}
-% {\toonprint[][][plaats={rechts,onder}]} {\type{plaats={rechts,onder}}}
-% {\toonprint[][][nx=2,ny=1]} {\type{nx=2,ny=1}}
-% {\toonprint[][][nx=1,ny=2]} {\type{nx=1,ny=2}}
-% {\toonprint[][][nx=2,ny=2]} {\type{nx=2,ny=2}}
-% {\toonprint[][][nx=2,ny=2,plaats=midden]} {\type{nx=2,ny=2}\break
-% \type{plaats=midden}}
-% {\toonprint[][][rugoffset=3pt]} {\type{rugoffset=.5cm}}
-% {\toonprint[][][kopoffset=3pt]} {\type{kopoffset=.5cm}}
-% {\toonprint[][][schaal=1.5]} {\type{schaal=1.5}}
-% {\toonprint[][][schaal=0.8]} {\type{schaal=0.8}}
-% \stopcombinatie
+% \startcombination[4*4]
+% {\showprint} {\strut}
+% {\showprint[][][location=middle]} {\type{location=middle}}
+% {\showprint[][][location=middle,marking=on]} {\type{markering=aan}\break\type{location=middle}}
+% {\showprint[][][location=middle,marking=on,nx=2]} {\type{markering=aan}\break\type{location=middle}\break\type{nx=2}}
+% {\showprint[][][location=left]} {\type{location=left}}
+% {\showprint[][][location=right]} {\type{location=right}}
+% {\showprint[][][location={left,bottom}]} {\type{location={left,bottom}}}
+% {\showprint[][][location={right,bottom}]} {\type{location={right,bottom}}}
+% {\showprint[][][nx=2,ny=1]} {\type{nx=2,ny=1}}
+% {\showprint[][][nx=1,ny=2]} {\type{nx=1,ny=2}}
+% {\showprint[][][nx=2,ny=2]} {\type{nx=2,ny=2}}
+% {\showprint[][][nx=2,ny=2,location=middle]} {\type{nx=2,ny=2}\break\type{location=middle}}
+% {\showprint[][][backoffset=3pt]} {\type{rugoffset=.5cm}}
+% {\showprint[][][topoffset=3pt]} {\type{kopoffset=.5cm}}
+% {\showprint[][][scale=1.5]} {\type{schaal=1.5}}
+% {\showprint[][][scale=0.8]} {\type{schaal=0.8}}
+% \stopcombination
%
-% \startcombinatie[3*4]
-% {\toonprint[liggend][][plaats=midden]} {\type{liggend}}
-% {\toonprint[][liggend][plaats=midden]} {\strut\break\type{liggend}}
-% {\toonprint[liggend][liggend][plaats=midden]} {\type{liggend}\break\type{liggend}}
-% {\toonprint[90][][plaats=midden]} {\type{90}}
-% {\toonprint[][90][plaats=midden]} {\strut\break\type{90}}
-% {\toonprint[90][90][plaats=midden]} {\type{90}\break\type{90}}
-% {\toonprint[180][][plaats=midden]} {\type{180}}
-% {\toonprint[][180][plaats=midden]} {\strut\break\type{180}}
-% {\toonprint[180][180][plaats=midden]} {\type{180}\break\type{180}}
-% {\toonprint[gespiegeld][][plaats=midden]} {\type{gespiegeld}}
-% {\toonprint[][gespiegeld][plaats=midden]} {\strut\break\type{gespiegeld}}
-% {\toonprint[gespiegeld][gespiegeld][plaats=midden]} {\type{gespiegeld}\break\type{gespiegeld}}
-% \stopcombinatie
+% \startcombination[3*4]
+% {\showprint[landscape][] [location=middle]} {\type{landscape}}
+% {\showprint[] [landscape][location=middle]} {\strut\break\type{landscape}}
+% {\showprint[landscape][landscape][location=middle]} {\type{landscape}\break\type{landscape}}
+% {\showprint[90] [] [location=middle]} {\type{90}}
+% {\showprint[] [90] [location=middle]} {\strut\break\type{90}}
+% {\showprint[90] [90] [location=middle]} {\type{90}\break\type{90}}
+% {\showprint[180] [] [location=middle]} {\type{180}}
+% {\showprint[] [180] [location=middle]} {\strut\break\type{180}}
+% {\showprint[180] [180] [location=middle]} {\type{180}\break\type{180}}
+% {\showprint[mirrored] [] [location=middle]} {\type{mirrored}}
+% {\showprint[] [mirrored] [location=middle]} {\strut\break\type{mirrored}}
+% {\showprint[mirrored] [mirrored] [location=middle]} {\type{mirrored}\break\type{mirrored}}
+% \stopcombination
% maybe we will have page-run.lua
\startluacode
+local format, concat = string.format, table.concat
+
local function todimen(name,unit,fmt)
return number.todimen(tex.dimen[name],unit,fmt)
end
-local function showdimension(name)
- context.NC()
- context.tex(interfaces.interfacedcommand(name))
- context.NC()
- context(todimen(name,"pt","%0.4fpt"))
- context.NC()
- context(todimen(name,"cm","%0.4fcm"))
- context.NC()
- context(todimen(name,"bp","%0.4fbp"))
- context.NC()
- context(todimen(name,"dd","%0.4fdd"))
- context.NC()
- context.NR()
-end
+function commands.showlayoutvariables(options)
-local function showmacro(name)
- context.NC()
- context.tex(interfaces.interfacedcommand(name))
- context.NC()
- context.getvalue(name)
- context.NC()
- context.NR()
-end
+ if options == "" then
+ options = "pt,cm"
+ end
-local function reportdimension(name)
- commands.writestatus("layout",string.format("%-24s %12s %12s %12s %12s",
- interfaces.interfacedcommand(name),
- todimen(name,"pt","%0.4fpt"),
- todimen(name,"cm","%0.4fcm"),
- todimen(name,"bp","%0.4fbp"),
- todimen(name,"dd","%0.4fdd")
- ))
-end
+ local options = utilities.parsers.settings_to_hash(options)
+
+ local dimensions = { "pt", "bp", "cm", "mm", "dd", "cc", "pc", "nd", "nc", "sp", "in" }
+
+ local n = 0
+ for i=1,#dimensions do
+ if options[dimensions[i]] then
+ n = n + 1
+ end
+ end
+
+ if n == 0 then
+ options.pt = true
+ n = 1
+ end
-function commands.showlayoutvariables()
+ local function showdimension(name)
+ context.NC()
+ context.tex(interfaces.interfacedcommand(name))
+ context.NC()
+ for i=1,#dimensions do
+ local d = dimensions[i]
+ if options[d] then
+ context("%s%s",todimen(name,d,"%0.4f"),d)
+ context.NC()
+ end
+ end
+ context.NR()
+ end
+
+ local function showmacro(name)
+ context.NC()
+ context.tex(interfaces.interfacedcommand(name))
+ context.NC()
+ context.getvalue(name)
+ context.NC()
+ context.NR()
+ end
+
+ local function reportdimension(name)
+ local result = { }
+ for i=1,#dimensions do
+ local d = dimensions[i]
+ if options[d] then
+ result[#result+1] = format("%12s%s",todimen(name,d,"%0.4f"),d)
+ end
+ end
+ commands.writestatus("layout",format("%-24s %s",interfaces.interfacedcommand(name),concat(result," ")))
+ end
if tex.count.textlevel == 0 then
@@ -167,7 +170,7 @@ function commands.showlayoutvariables()
else
- context.starttabulate { "|l|Tr|Tr|Tr|Tr|" }
+ context.starttabulate { "|l|" .. string.rep("Tr|",n) }
showdimension("paperheight")
showdimension("paperwidth")
@@ -210,11 +213,11 @@ function commands.showlayoutvariables()
end
-function commands.showlayout()
+function commands.showlayout(options)
if tex.count.textlevel == 0 then
- commands.showlayoutvariables()
+ commands.showlayoutvariables(options)
else
@@ -223,7 +226,7 @@ function commands.showlayout()
context.showframe()
context.setuplayout { marking = interfaces.variables.on }
for i=1,4 do
- commands.showlayoutvariables()
+ commands.showlayoutvariables(options)
context.page()
end
context.egroup()
@@ -233,7 +236,7 @@ function commands.showlayout()
end
\stopluacode
-\gdef\doshowframe[#1][#2]%
+\gdef\page_layouts_show_frame[#1][#2]%
{\ifsecondargument
\setupbackgrounds
[\v!page]
@@ -266,16 +269,17 @@ end
\setupbackgrounds
[\c!state=\v!repeat]}
-\gdef\showframe
- {\dodoubleempty\doshowframe}
+\gdef\page_layouts_show_setups[#1]%
+ {\ctxcommand{showlayoutvariables("#1")}}
-\gdef\showsetups
- {\ctxcommand{showlayoutvariables()}}
+\gdef\page_layouts_show_layout[#1]%
+ {\ctxcommand{showlayout("#1")}}
-\gdef\showlayout % interfereert lelijk met een \typefile er na
- {\ctxcommand{showlayout()}}
+\unexpanded\gdef\showframe {\dodoubleempty\page_layouts_show_frame }
+\unexpanded\gdef\showsetups{\dosingleempty\page_layouts_show_setups}
+\unexpanded\gdef\showlayout{\dosingleempty\page_layouts_show_layout}
-\gdef\showmargins
+\unexpanded\gdef\showmargins
{\starttabulate
\NC asynchrone \NC \doifoddpageelse {odd} {even} \NC \NR
\NC synchrone \NC \doifrightpageelse {right} {left} \NC \NR
@@ -284,5 +288,5 @@ end
\NC outer margin \NC \the\outermarginwidth \NC \NR
\NC inner margin \NC \the\innermarginwidth \NC \NR
\stoptabulate}
-
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-sel.mkiv b/Master/texmf-dist/tex/context/base/page-sel.mkiv
index 9192d143053..1e706aa2220 100644
--- a/Master/texmf-dist/tex/context/base/page-sel.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-sel.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Page Selection,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-set.mkii b/Master/texmf-dist/tex/context/base/page-set.mkii
index e4817066dc1..3c8c87e5c40 100644
--- a/Master/texmf-dist/tex/context/base/page-set.mkii
+++ b/Master/texmf-dist/tex/context/base/page-set.mkii
@@ -5,7 +5,7 @@
%D subtitle=Column Sets,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -259,7 +259,7 @@
\dostepwiserecurse{#3}\!!counte\plusone
{\OTRSETsetgridcell\!!countf\recurselevel#1}}%
\dostepwiserecurse{#3}\!!counte\plusone
- {\global\wd\OTRSETgridcell{#2}\recurselevel\hsize}%
+ {\wd\OTRSETgridcell{#2}\recurselevel\hsize}%
\OTRSETsetgridcell{#2}\!!counte#6}
\def\OTRSETsetgridcells
@@ -1719,7 +1719,7 @@
\chardef\OTRSETbalancemethod\plusone
\OTRSETreducegridbox
\global\setbox\OTRfinalpagebox\OTRSETmakegridbox
- \global\ht\OTRfinalpagebox\textheight % signals output that there is content
+ \ht\OTRfinalpagebox\textheight % signals output that there is content
\OTRSETdofinaloutput
\globallet\OTRSETbalht\zeropoint
\egroup}
@@ -1927,7 +1927,7 @@
%
% \installoutput\OTRSETflushpreposttext
% {\global\setbox\precolumnbox\vbox{\unvbox\normalpagebox}%
-% \global\dp\precolumnbox\strutdepth
+% \dp\precolumnbox\strutdepth
% \ifcarryoverfootnotes \else
% \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
% \fi}
@@ -1951,7 +1951,7 @@
\global\setbox\precolumnbox\hbox
{\lower\strutdepth\box\precolumnbox}%
\fi
- \global\dp\precolumnbox\strutdepth
+ \dp\precolumnbox\strutdepth
\ifcarryoverfootnotes \else
\global\setbox\postcolumnbox\vbox{\placebottomnotes}%
\fi}
diff --git a/Master/texmf-dist/tex/context/base/page-set.mkiv b/Master/texmf-dist/tex/context/base/page-set.mkiv
index 8c3566bc087..467f22493cb 100644
--- a/Master/texmf-dist/tex/context/base/page-set.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-set.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Column Sets,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -54,8 +54,11 @@
\def\OTRSETmakeupwidth{\innermakeupwidth}
-\let\OTRSETflushsidefloats \forgetsidefloats % \relax
-\let\OTRSETsynchronizesidefloats\forgetsidefloats % \relax
+\unexpanded\def\page_set_command_flush_side_floats
+ {\page_sides_forget_floats}
+
+\unexpanded\def\page_set_command_synchronize_side_floats
+ {\page_sides_forget_floats}
\def\OTRSETgridcell #1#2{\csname \@otr@:\number#1:\number#2\endcsname}
\def\OTRSETgetgridcell#1#2{\box\csname \@otr@:\number#1:\number#2\endcsname}
@@ -237,7 +240,7 @@
\dostepwiserecurse{#3}\!!counte\plusone
{\OTRSETsetgridcell\!!countf\recurselevel#1}}%
\dostepwiserecurse{#3}\!!counte\plusone
- {\global\wd\OTRSETgridcell{#2}\recurselevel\hsize}%
+ {\wd\OTRSETgridcell{#2}\recurselevel\hsize}%
\OTRSETsetgridcell{#2}\!!counte#6}
\def\OTRSETsetgridcells
@@ -437,7 +440,7 @@
\vss
\fi}%
\wd\scratchbox\localcolumnwidth % \textwidth
- \docolumnpagebodymarks{#1}{#2}\recurselevel\scratchbox
+ \page_marks_synchronize_column{#1}{#2}\recurselevel\scratchbox
\ifcase\columndirection
\hskip\OTRSETgetparameter\c!distance\recurselevel\box\scratchbox
\else
@@ -500,7 +503,6 @@
\fi
\doglobal\increment\columnsetpage
\OTRSETinitializecolumns
- %\OTRSETdoflushfloats
\OTRSETstartnextpage
\initializecolumntextareas
\fi}
@@ -520,16 +522,16 @@
\def\OTRSETdofinaloutput
{\ifdim\ht\OTRfinalpagebox=\textheight
- \bgroup % \let\OTRSETsetvsize\relax % prevents useless search for gap
+ \bgroup
\ifcase\OTRSETbalancemethod
- \finaloutput\box\OTRfinalpagebox
+ \page_otr_construct_and_shipout\box\OTRfinalpagebox
\else\ifdim\OTRSETbalht>\zeropoint
% catch a bordercase
\scratchdimen\OTRSETbalht
\advance\scratchdimen\lineheight\relax
\ifdim\scratchdimen>\textheight
% full page
- \finaloutput\box\OTRfinalpagebox
+ \page_otr_construct_and_shipout\box\OTRfinalpagebox
\else
% same page
\global\setbox\OTRfinalpagebox \iftracecolumnset\ruledvbox\else\vbox\fi to \OTRSETbalht
@@ -538,14 +540,12 @@
\snaptogrid\vbox{\vskip\OTRSETbalht}% hack
\fi
\else
- \finaloutput\box\OTRfinalpagebox
+ \page_otr_construct_and_shipout\box\OTRfinalpagebox
\fi \fi
\globallet\OTRSETbalht\zeropoint
- \egroup
+ \egroup
\fi}
-
-\definesystemvariable {mc}
-\definesystemvariable {mt}
+
\definesystemconstant {colset}
\definetwopasslist\s!colset
@@ -554,8 +554,6 @@
\newdimen \OTRSETtextsheight
\let \OTRSETidentifier=\empty
-\newtoks \OTRSEToutput
-
\def\OTRSETgetparameter#1#2{\csname\??mc\OTRSETidentifier\number#2#1\endcsname}
\def\OTRSETsetparameter#1#2{\setvalue{\??mc\OTRSETidentifier\number#2#1}}
@@ -570,9 +568,10 @@
\emptybox
\fi}
-\def\OTRSETsetvsize % snap per sectie (gap here?)
+\unexpanded\def\page_set_command_set_vsize % snap per sectie (gap here?)
{\ifcollectingcontent \else % can be assigndimen
-\OTRSETskipstart % not that well tested
+ \OTRSETsetcolumnmaxcells % layout can be changed
+ \OTRSETskipstart % not that well tested
\OTRSETcheckinsert % added
\OTRSETsetfreecells\mofcolumns\columnfirstcell
\ifsomefreecolumncells
@@ -586,12 +585,12 @@
\synchronizenotes
\fi}
-\def\OTRSETsethsize % of course this does not migrate outside the otr
+\def\page_set_command_set_hsize % of course this does not migrate outside the otr
{\localcolumnwidth\OTRSETlocalwidth\mofcolumns
\textwidth\localcolumnwidth
\hsize\localcolumnwidth}
-\def\OTRSETsynchronizehsize
+\unexpanded\def\page_set_command_synchronize_hsize
{\ifcase0\getvalue{\??mc\??mc\c!width}\else % some width set
\bgroup
\scratchdimen\OTRSETlocalwidth\mofcolumns
@@ -599,12 +598,13 @@
\egroup
\else
% only if change in width and \column/\break
- \egroup \OTRSETsethsize
+ \egroup
+ \page_set_command_set_hsize
\fi
\fi}
\def\OTRSETcheckfreelines
- {\OTRSETsetvsize}
+ {\page_set_command_set_vsize}
\def\doOTRSETcolumnseparator
{\hbox to \zeropoint{\hss\red\vl\hss}}
@@ -614,34 +614,6 @@
\def\showbreaks
{\let\OTRSETcolumnseparator\doOTRSETcolumnseparator}
-% \installcolumnbreakhandler {SET} \v!ja
-% {% hmmm:
-% \ifhmode
-% \bgroup
-% \removeunwantedspaces
-% \parfillskip\zeropoint
-% \OTRSETcolumnseparator
-% \par
-% \egroup
-% \fi
-% % brrr:
-% \ejectinsert
-% \ejectpage
-% \OTRSETsynchronizehsize} % no \OTRSETsethsize, can be mid smaller (like tabulate)
-%
-% \installcolumnbreakhandler {SET} \v!forceer
-% {\OTRSETgotocolumn[\v!forceer]}
-% \installcolumnbreakhandler {SET} \v!eerste
-% {\OTRSETgotocolumn[\v!eerste]}
-% \installcolumnbreakhandler {SET} \v!laatste
-% {\OTRSETgotocolumn[\v!laatste]}
-%
-% \installcolumnbreakhandler {SET} \v!pagina
-% {\simplepagebreak % \flushnotes \executepagebreakhandler\v!ja
-% \ifnum\mofcolumns>\plusone
-% \OTRSETgotocolumn[\v!laatste,\v!forceer]%
-% \fi}
-
\def\OTRSETcolumnhbreak
{\ifhmode
\bgroup
@@ -652,26 +624,26 @@
\egroup
\fi}
-\installcolumnbreakhandler {SET} \v!local
+\installcolumnbreakmethod \s!columnset \v!local
{\OTRSETcolumnhbreak
- \ejectinsert
- \ejectpage % brrr
- % no \OTRSETsethsize, can be mid smaller (like tabulate)
+ \page_otr_flush_all_floats
+ \page_otr_eject_page
+ % no \page_set_command_set_hsize, can be mid smaller (like tabulate)
% also, this one should be executed at the outer level
% (setting hsize inside otr does not work)
- \OTRSETsynchronizehsize}
+ \page_set_command_synchronize_hsize}
% We need to make sure that we really leave the column; mid
% column we may end up in an empty gap, and we don't want to
% stay there (basically such a gap is a small empty page
% then).
-\installcolumnbreakhandler {SET} \v!yes
+\installcolumnbreakmethod \s!columnset \v!yes
{\OTRSETcolumnhbreak
\edef\savedmofcolumns{\the\mofcolumns}%
\edef\savedrealpageno{\the\realpageno}%
- \ejectinsert
- \ejectpage % brrr
+ \page_otr_flush_all_floats
+ \page_otr_eject_page
\doloop
{\ifnum\savedmofcolumns=\mofcolumns
\ifnum\savedrealpageno=\realpageno
@@ -682,20 +654,19 @@
\else
\exitloop
\fi}%
- \OTRSETsynchronizehsize}
+ \page_set_command_synchronize_hsize}
-\installcolumnbreakhandler {SET} \s!unknown
+\installcolumnbreakmethod \s!columnset \s!unknown
{\expanded{\OTRSETgotocolumn[\@@columnspecification]}}
-\installcolumnbreakhandler {SET} \v!page
- {\vfill\eject % \doejectpage\eject
- \OTRSETgotonextpage}
+\installcolumnbreakmethod \s!columnset \v!page
+ {\page_otr_fill_and_eject_page}
\newtoks\OTRSETeverystartofcolumn
\newbox\OTRSETsavedfootnotes
-% \installoutput\OTRSETflushtextsofar % spacing goes wrong
+% \installoutputroutine\OTRSETflushtextsofar % spacing goes wrong
%\def\OTRSETflushtextsofar
% {\ifvoid\normalpagebox \else
@@ -718,7 +689,7 @@
\newconstant\OTRSETflushtextmode % will be replaced
-\def\OTRSETflushtextsofar
+\def\OTRSETflushtextsofar % needs renaming
{\ifcase\OTRSETflushtextmode
% don't mess around
\or
@@ -734,7 +705,7 @@
\newskip\lastskipinotr
-\installoutput\doOTRSETflushtextsofar % experimental
+\installoutputroutine\doOTRSETflushtextsofar % experimental
{\ifvoid\normalpagebox\else
\scratchdimen\dp\normalpagebox
\setbox\scratchbox\vbox
@@ -760,7 +731,7 @@
\else
% we should not discard skips after here; tricky
\fi
- \OTRSETsetvsize
+ \page_set_command_set_vsize
\fi}
\def\OTRSETplacebottomnotes
@@ -816,7 +787,7 @@
\doOTRSETsetgridcells
{\copy\placeholderboxf}
\mofcolumns\columnfirstcell\plusone\noflines
- {\registeredtextarea1\columnfirstcell\scratchbox}% == \hbox / tricky htcorr == \columnfirstcell
+ {\page_areas_registered_box1\columnfirstcell\scratchbox}% == \hbox / tricky htcorr == \columnfirstcell
\global\columnlastcell\columnfirstcell
\global\advance\columnlastcell \noflines
\global\lastcolumnlastcell\columnlastcell
@@ -831,8 +802,8 @@
% we cannot adapt the hsize since it may have changed (like
% inside a tabulate) so we only change it when there is a
% reason to do so
- \OTRSETsynchronizehsize
- \OTRSETsetvsize}
+ \page_set_command_synchronize_hsize
+ \page_set_command_set_vsize}
\def\OTRSETfindnextgap
{\OTRSETsetfreecells\mofcolumns\columnlastcell
@@ -844,7 +815,7 @@
\OTRSETdoflush
\global\columnlastcell\plusone
\global\columnfirstcell\zerocount
- \OTRSETdoflushfloats
+ \page_set_command_flush_floats
\else
\the\OTRSETeverystartofcolumn
\global\columnlastcell\plusone
@@ -937,7 +908,7 @@
\ifenoughcolumncells
\OTRSETsetgridcells\mofcolumns\columnfirstcell\columnhcells\columnvcells
{\hbox{\copy#1}}%
- \OTRSETsetvsize
+ \page_set_command_set_vsize
\else
\OTRSETsavebox{#1}%
\fi}
@@ -954,7 +925,7 @@
\ifenoughcolumncells
\OTRSETsetgridcells\mofcolumns\columnlastcell\columnhcells\columnvcells{\copy#1}%
\OTRSETfillgapsbetweencells\mofcolumns\savedcolumnlastcell % -)
- \OTRSETsetvsize
+ \page_set_command_set_vsize
\else
\columnlastcell\savedcolumnlastcell
\OTRSETsavebox{#1}%
@@ -1169,7 +1140,7 @@
\OTRSETstoreincolumnslotindeed
\mofcolumns\mofcolumns+\currenthcell
\noflines\columnmaxcells+\currentvcell{#2}%
- \OTRSETsetvsize}
+ \page_set_command_set_vsize}
\def\OTRSETcheckprefered
{\ifnum\preferedcolumn<\mofcolumns
@@ -1247,7 +1218,7 @@
\else
%\message{[flt]}% float
\fi
- \OTRSETsetvsize
+ \page_set_command_set_vsize
%\message{[fnt]}% float
\else
%\message{[rej]}% save box
@@ -1292,7 +1263,7 @@
\egroup
\fi}
-\def\OTRSETdocheckiffloatfits % eigenlijk moet else float anders
+\unexpanded\def\page_set_command_check_if_float_fits
{\global\ifnofloatpermitted\roomforfloatfalse\else\roomforfloattrue\fi}
\def\OTRSETunpreparebox#1%
@@ -1314,10 +1285,10 @@
{\OTRSETunpreparebox{#1}%
\dofloatsresave\s!text}
-\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
+\unexpanded\def\page_set_command_flush_float_box
{\iftestfloatbox\ruledhbox\fi{\box\floatbox}}
-\def\OTRSETdoflushfloats
+\unexpanded\def\page_set_command_flush_floats
{\bgroup
\def\OTRSETsavebox##1{\!!doneafalse}%
\doloop
@@ -1488,8 +1459,8 @@
\definecolumnset[\s!default][\c!n=2] % fallback
-\def\OTRSETgotonextpage
- {\vfill\eject
+\unexpanded\def\page_set_command_next_page
+ {\page_otr_fill_and_eject_page
\relax\ifnum\mofcolumns>\plusone
\OTRSETgotocolumn[\v!last]%
\ifnum\mofcolumns>\plusone
@@ -1497,7 +1468,8 @@
\fi
\fi}
-\let\OTRSETgotonextpageX\OTRSETgotonextpage % will become obsolete
+\let\page_set_command_next_page_and_inserts\page_set_command_next_page
+
\def\OTRSETgotocolumn
{\dosingleempty\doOTRSETgotocolumn}
@@ -1515,7 +1487,7 @@
\def\doOTRSETgotoCOLUMN#1%
{\ifnum\mofcolumns=#1\else
- \vfill\eject % \doejectpage\eject
+ \page_otr_fill_and_eject_page
\doloop
{\ifnum\mofcolumns=#1\relax
\exitloop \else \OTRSETdummycolumn
@@ -1536,7 +1508,7 @@
\dorecurse\scratchcounter{\line{\strut}}%
\fi
\fi
- \OTRSETsetvsize}
+ \page_set_command_set_vsize}
\def\doOTRSETgotocolumn[#1]% yes|force|first|last|<number>|<number>*<number>
{\processallactionsinset
@@ -1584,7 +1556,7 @@
% \fi
% \fi
% \fi
-% \OTRSETsetvsize}
+% \page_set_command_set_vsize}
\def\OTRSETgotocell#1#2% obsolete: now \column[#1*#2]
{\endgraf
@@ -1594,8 +1566,7 @@
\def\OTRSETdummycolumn
{\verticalstrut
\vskip-\struttotal
- \vfill
- \eject}
+ \page_otr_fill_and_eject_page}
\newcounter\columnsetlevel
\let\currentcolumnset\empty
@@ -1615,16 +1586,17 @@
\globallet\columnsetpage\!!plusone
\def\currentcolumnset{#2}%
\insidecolumnstrue % will be different flag in addition
- \activateotr{SET}{ONE}% andere naam, activate or so
+ \setupoutputroutine[\s!columnset]%
\doifelsenothing{#1}
{\globallet\OTRSETlist\s!default}
{\xdef\OTRSETlist{#1}}%
\OTRSETstartnextpage
\OTRSETassignwidths
- \OTRSETsethsize
+ \page_set_command_set_hsize
\else
\bgroup
- \fi}
+ \fi
+ \begingroup} % extra grouping needed ... else weird issue with ungrouped font switch (e.g. \ss)
% \setuplayout[grid=yes] \definecolumnset[example] \showgrid
@@ -1644,14 +1616,15 @@
\OTRSETbalancemethod\plusone
\OTRSETreducegridbox
\global\setbox\OTRfinalpagebox\OTRSETmakegridbox
- \global\ht\OTRfinalpagebox\textheight % signals output that there is content
+ \ht\OTRfinalpagebox\textheight % signals output that there is content
\OTRSETdofinaloutput
\globallet\OTRSETbalht\zeropoint
\egroup}
{}}
\unexpanded\def\stopcolumnset
- {\relax
+ {\endgraf
+ \endgroup % ends extra grouping
\ifnum\columnsetlevel=\plusone
\endgraf % needed, else wrong vsize in one par case
\global\settrue\OTRSETfinish
@@ -1659,8 +1632,8 @@
\dostopcolumnset
\egroup
\global\notelimittrue % brrr, untested and fuzzy
- \setvsize
- \sethsize
+ \page_otr_command_set_vsize
+ \page_otr_command_set_hsize
\ifvoid\OTRfinalpagebox\else
% probably balanced
\ifdim\ht\OTRfinalpagebox<\textheight
@@ -1670,7 +1643,11 @@
\fi
\fi
\global\setfalse\OTRSETfinish
- \ifsomefloatwaiting \setvsize \pagebreak \setvsize \fi
+ \ifsomefloatwaiting
+ \page_otr_command_set_vsize
+ \pagebreak
+ \page_otr_command_set_vsize
+ \fi
\OTRSETflushleftovers
\else
\egroup
@@ -1719,7 +1696,7 @@
% inhibit flush of floats !
% todo: nothing if no footnotes, else empty page
\dostepwiserecurse\mofcolumns\nofcolumns\plusone
- {\vskip-\struttotal\verticalstrut\vfill\eject}%
+ {\vskip-\struttotal\verticalstrut\page_otr_fill_and_eject_page}%
\else
\ifnum\mofcolumns>\plusone
\donetrue
@@ -1734,8 +1711,7 @@
\else
% probably todo
\fi
- \vfill
- \eject
+ \page_otr_fill_and_eject_page
% brr, may result in empty page after nicely fit text
% or if left, then lost of first column only text
\ifnum\mofcolumns>\plusone
@@ -1761,13 +1737,13 @@
\OTRSETinitializecolumns
\OTRSETcheckinsert
\OTRSETcheckgrid
- \OTRSETsetvsize
- \OTRSETsethsize % or local ?
+ \page_set_command_set_vsize
+ \page_set_command_set_hsize % or local ?
\OTRSETsetplaceholders
\OTRSEThandlepreposttext
\initializecolumntextareas % name !
\OTRSETcheckstartcells
- \OTRSETsetvsize}
+ \page_set_command_set_vsize}
\def\OTRSETcheckstartcells
{\dorecurse\nofcolumns
@@ -1780,12 +1756,12 @@
\donothing{\OTRSETsetgridcell\mofcolumns\recurselevel\copy\placeholderboxe}}%
\egroup}}
-\OTRSEToutput
+\unexpanded\def\page_set_command_routine
{\dontcomplain % new, get rid of overfull message (to be sorted out)
\doloop
{\OTRSETnaturalflush
%\OTRSETstartnextpage % no
- \OTRSETdoflushfloats % actually belongs in \flushsavedfloats (but goes wrong)
+ \page_set_command_flush_floats
\OTRSETcheckfreelines
\ifsomefreecolumncells
\exitloop
@@ -1794,10 +1770,13 @@
\fi}%
\OTRSETchecksidefloat}
+\def\OTRSETsetcolumnmaxcells
+ {\getrawnoflines\textheight\xdef\columnmaxcells{\the\noflines}}
+
\def\OTRSETinitializefeatures
{% number of lines
% new: raw
- \getrawnoflines\textheight\xdef\columnmaxcells{\the\noflines}%
+ \OTRSETsetcolumnmaxcells
% direction
\doifelsevalue{\??mc\OTRSETidentifier\c!direction}\v!right
{\columndirection\zerocount}
@@ -1823,7 +1802,7 @@
\ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi
-\installoutput\OTRSETflushpreposttext
+\installoutputroutine\OTRSETflushpreposttext
{\global\setbox\precolumnbox\vbox
{\unvbox\normalpagebox
\global\lastskipinotr\lastskip}%
@@ -1831,7 +1810,7 @@
\global\setbox\precolumnbox\hbox
{\lower\strutdepth\box\precolumnbox}%
\fi
- \global\dp\precolumnbox\strutdepth
+ \dp\precolumnbox\strutdepth
\ifcarryoverfootnotes \else
\global\setbox\postcolumnbox\vbox{\placebottomnotes}%
\fi}
@@ -1871,8 +1850,8 @@
\def\OTRSETchecksidefloat
{} % {\sidefloatoutput}
-\def\OTRSETfinalsidefloatoutput
- {}
+\unexpanded\def\page_set_command_side_float_output
+ {} % nothing, reset anyway
\def\OTRSETcheckgrid
{\topskip1\topskip
@@ -1907,12 +1886,11 @@
\ifcase\columnsetlevel\relax
\mofcolumns\plusone
\OTRSETinitializecolumns
- \OTRSETassignwidths
- \OTRSETsethsize
+ \OTRSETassignwidths % already done
+ \page_set_command_set_hsize
\fi
\!!counta#2\!!countb#3\docalculatecolumnsetspan
- \expandafter\egroup\expandafter\edef\expandafter
- #4\expandafter{\the\!!widtha}}
+ \expandafter\egroup\expandafter\edef\expandafter#4\expandafter{\the\!!widtha}}
% interface to footnotes
@@ -1994,21 +1972,22 @@
% page contents
-\def\OTRSETdopagecontents#1#2% takes two args: \box<n> \unvbox<n>
+% \def\OTRSETdopagecontents#1#2% takes two args: \box<n> \unvbox<n>
+\unexpanded\def\page_set_command_package_contents#1#2% \box<n> \unvbox<n> % this one will be redone (checked)
{\vbox to \textheight{\forgetall#1#2}}
-
-\def\OTRSETsomepagefloat {\def\floatmethod{PAGE}\OTRSETsomeslotfloat} % check
-\def\OTRSETsomeherefloat {\def\floatmethod{HERE}\OTRSETsomeslotfloat} % check
-\def\OTRSETsomeelsefloat {\def\floatmethod{HERE}\OTRSETsomeslotfloat} % check
-\def\OTRSETsomefixdfloat {\def\floatmethod{FIXD}\OTRSETsomeslotfloat} % check
-\def\OTRSETsometopfloat {\def\floatmethod{TOPS}\OTRSETsomeslotfloat} % check
-\def\OTRSETsomebottomfloat{\def\floatmethod{BOTS}\OTRSETsomeslotfloat} % check
+
+\def\page_set_place_float_page {\def\floatmethod{PAGE}\page_set_place_float_slot} % check
+\def\page_set_place_float_here {\def\floatmethod{HERE}\page_set_place_float_slot} % check
+\def\page_set_place_float_else {\def\floatmethod{HERE}\page_set_place_float_slot} % check / not used
+\def\page_set_place_float_force {\def\floatmethod{FIXD}\page_set_place_float_slot} % check
+\def\page_set_place_float_top {\def\floatmethod{TOPS}\page_set_place_float_slot} % check
+\def\page_set_place_float_bottom{\def\floatmethod{BOTS}\page_set_place_float_slot} % check
\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
{\iftestfloatbox\ruledhbox\fi{\box\floatbox}}
-\def\OTRSETsomeslotfloat[#1]%
- {\setbox\floatbox\vbox{\flushfloatbox}%
+\def\page_set_place_float_slot
+ {\setbox\floatbox\vbox{\page_otr_command_flush_float_box}%
\dp\floatbox\strutdp
\@EA\uppercasestring\floatmethod\to\floatmethod
\OTRSETstoreincolumnslot\floatmethod\floatbox
@@ -2016,21 +1995,23 @@
% kind of new, looks much like OTRONE, but not entirely
-\def\OTRSETdosettopinserts
+\newconditional\c_page_set_top_of_insert
+
+\unexpanded\def\page_set_command_set_top_insertions
{\bgroup
\ifsomefloatwaiting
\noffloatinserts\zerocount
\let\totaltopinserted\!!zeropoint
\OTRSETdodosettopinserts
- \ifnum\@@bknbottom=\zerocount
- \ifnum\@@bknlines>\zerocount
+ \ifnum\rootfloatparameter\c!nbottom=\zerocount
+ \ifnum\rootfloatparameter\c!nlines>\zerocount
\ifdim\totaltopinserted>\zeropoint\relax
\dimen0\lineheight
- \dimen0=\@@bknlines\dimen0
+ \dimen0=\rootfloatparameter\c!nlines\dimen0
\advance\dimen0 \totaltopinserted\relax
\ifdim\dimen0>\textheight % \vsize %%%%%%%%% \textheight
- \showmessage\m!floatblocks8{\@@bknlines}%
- \vfilll\eject
+ \showmessage\m!floatblocks8{\rootfloatparameter\c!nlines}%
+ \page_otr_fill_and_eject_page % was triple: vfilll
\fi
\fi
\fi
@@ -2042,21 +2023,21 @@
{\ifnum\noffloatinserts<\noftopfloats
\dogetfloat
\ifdim\topinserted=\zeropoint\relax
- \topofinserttrue
+ \settrue\c_page_set_top_of_insert
\else
- \topofinsertfalse
+ \setfalse\c_page_set_top_of_insert
\fi
\setbox\scratchbox\vbox % kan beter !
{\forgetall
- \iftopofinsert
- \ifdim\OTRSETtopoffset=\zeropoint
- \moveongrid[\v!top]
- \fi
+ \ifconditional\c_page_set_top_of_insert
+ %\ifdim\OTRSETtopoffset=\zeropoint
+ % \moveongrid[\v!top]
+ %\fi
\else
\betweenfloatblanko % inserts can't look back
\fi
- \flushfloatbox
- \blank[\@@bkspaceafter]}%
+ \page_otr_command_flush_float_box
+ \blank[\rootfloatparameter\c!spaceafter]}%
\global\advance\topinserted \ht\scratchbox\relax
\ifdim\topinserted>\vsize % was \textheight\relax
\OTRSETresavebox\floatbox
@@ -2081,7 +2062,7 @@
\fi
\OTRSETdodosettopinserts}
-\def\OTRSETdosetbotinserts
+\unexpanded\def\page_set_command_set_bottom_insertions
{\bgroup
\ifsomefloatwaiting
\noffloatinserts\zerocount
@@ -2098,8 +2079,8 @@
\ifdim\botinserted<\pagegoal\relax
\insert\botins
{\forgetall
- \blank[\@@bkspacebefore]%
- \flushfloatbox}%
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box}%
\ifsomefloatwaiting
\advance\noffloatinserts \plusone
\else
@@ -2119,9 +2100,7 @@
\fi
\OTRSETdodosetbotinserts}
-\let\OTRSETdosetbothinserts\relax
-
-\def\OTRSETdotopinsertions
+\unexpanded\def\page_set_command_flush_top_insertions
{\ifvoid\topins\else
\ifvoid\columntopbox\mofcolumns
\columnsettopbox\mofcolumns\box\topins
@@ -2135,7 +2114,7 @@
\fi
\global\topinserted\zeropoint\relax} % goes away
-\def\OTRSETdobotinsertions
+\unexpanded\def\page_set_command_flush_bottom_insertions
{\ifvoid\botins \else
\columnsetbotbox\mofcolumns\box\botins
% \else
@@ -2275,7 +2254,7 @@
\def\flushcolumntextareas
{\initializecolumntextareas
- \setvsize}
+ \page_otr_command_set_vsize} % set ?
\def\columntextlastbackspace{\backspace}
@@ -2406,6 +2385,14 @@
\def\setcolumnsetspanhsize#1#2% x nx / uses counta/b
{\!!counta#1\!!countb#2\docalculatecolumnsetspan
\edef\columnsetspanhsize{\the\!!widtha}}
+
+\unexpanded\def\page_set_command_set_float_hsize
+ {\hsize % maybe checking optional
+ \ifdim\tempfloatwidth>\makeupwidth
+ \makeupwidth
+ \else
+ \tempfloatwidth
+ \fi}
\unexpanded\def\definecolumnsetspan
{\dodoubleempty\dodefinecolumnsetspan}
@@ -2480,7 +2467,7 @@
\setcolumnsetspanhsize\mofcolumns\!!countc % a/b used
\hsize\columnsetspanhsize
\setbox\scratchbox\vbox\bgroup
- \dostartframedtext[cs:#1][\v!none]% geen nils placement
+ \pack_framed_text_start{cs:#1}[\v!none]% geen nils placement
% spoils spacing : \vskip-\struttotal\par\verticalstrut\par
\ifnum\columnsetlevel>\zerocount
\namedframedtextparameter{cs:#1}\c!before
@@ -2499,7 +2486,7 @@
\else
\endgraf
\fi
- \dostopframedtext
+ \pack_framed_text_stop
\egroup
\setbox\scratchbox\frozenhbox to \hsize
{\dontcomplain
@@ -2526,7 +2513,6 @@
\@EA\uppercasestring\floatmethod\to\floatmethod
% todo : \v!here -> here enzovoorts
\OTRSETstoreincolumnslot\floatmethod\scratchbox
- % watch out: no \dochecknextindentation{tag}
\checknextindentation[\namedframedtextparameter{cs:#1}\c!indentnext]%
\else
% of course we needed a one-column fall back for tm; brrr, the box has now too
@@ -2550,7 +2536,42 @@
% \startcolumnsetspan[two] \emptylines[5] \stopcolumnsetspan
% \startcolumnsetspan[two] \input tufte \stopcolumnsetspan
% \stopcolumnset
-
+
+\unexpanded\def\page_set_command_flush_saved_floats % rather similar to _one_ ut this might change
+ {\global\topinserted\zeropoint
+ \global\botinserted\zeropoint
+ \ifflushingfloats \else
+ \page_set_command_set_top_insertions
+ \page_set_command_set_bottom_insertions
+ \ifsomefloatwaiting
+ \doif{\rootfloatparameter\c!cache}\v!no\page_set_command_flush_floats % could be _otr_
+ \fi
+ \fi}
+
+\defineoutputroutine
+ [\s!columnset]
+ [\s!page_otr_command_routine =\page_set_command_routine,
+ \s!page_otr_command_package_contents =\page_set_command_package_contents,
+ \s!page_otr_command_set_vsize =\page_set_command_set_vsize,
+ % \s!page_otr_command_set_hsize =\page_one_command_set_hsize, % tricky, goes wrong
+ \s!page_otr_command_next_page =\page_set_command_next_page,
+ \s!page_otr_command_next_page_and_inserts =\page_set_command_next_page_and_inserts,
+ \s!page_otr_command_synchronize_hsize =\page_set_command_synchronize_hsize,
+ \s!page_otr_command_set_top_insertions =\page_set_command_set_top_insertions,
+ \s!page_otr_command_set_bottom_insertions =\page_set_command_set_bottom_insertions,
+ \s!page_otr_command_flush_top_insertions =\page_set_command_flush_top_insertions,
+ \s!page_otr_command_flush_bottom_insertions =\page_set_command_flush_bottom_insertions,
+ \s!page_otr_command_set_float_hsize =\page_set_command_set_float_hsize,
+ \s!page_otr_command_check_if_float_fits =\page_set_command_check_if_float_fits,
+ \s!page_otr_command_flush_float_box =\page_set_command_flush_float_box,
+ \s!page_otr_command_synchronize_side_floats =\page_set_command_synchronize_side_floats,
+ \s!page_otr_command_side_float_output =\page_set_command_side_float_output,
+ \s!page_otr_command_flush_floats =\page_set_command_flush_floats,
+ \s!page_otr_command_flush_side_floats =\page_set_command_flush_side_floats,
+ \s!page_otr_command_flush_saved_floats =\page_set_command_flush_saved_floats
+ % \s!page_otr_command_flush_margin_blocks =\page_set_command_flush_margin_blocks, % not used
+ ]
+
\protect \endinput
% extreme examples (1)
diff --git a/Master/texmf-dist/tex/context/base/page-sid.mkii b/Master/texmf-dist/tex/context/base/page-sid.mkii
index 806acc6f133..6c3447e1ca0 100644
--- a/Master/texmf-dist/tex/context/base/page-sid.mkii
+++ b/Master/texmf-dist/tex/context/base/page-sid.mkii
@@ -5,7 +5,7 @@
%D subtitle=Side Floats,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -621,8 +621,8 @@
% todo: maybe rounding problem here
% \global\setbox\floatbox\hbox{\lower\lineheight\box\floatbox}%
\global\setbox\floatbox\hbox{\lower\strutdepth\box\floatbox}%
- \global\ht\floatbox\scratchdimen
- \global\dp\floatbox\zeropoint
+ \ht\floatbox\scratchdimen
+ \dp\floatbox\zeropoint
\fi
\ifcase\sidefloatalign \else
\global\sidefloattopskip\zeropoint
diff --git a/Master/texmf-dist/tex/context/base/page-sid.mkiv b/Master/texmf-dist/tex/context/base/page-sid.mkiv
index 9365f7508b5..4a24794eb06 100644
--- a/Master/texmf-dist/tex/context/base/page-sid.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-sid.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Side Floats,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,24 +15,6 @@
\unprotect
-% problem: when too small, side effects; we need to determine the
-% shift earlier so that we can act when shift < size
-%
-% \definefloat[edgefigure]
-% \setupfloat
-% [edgefigure]
-% [rightmargindistance=-\rightmargintotal,
-% leftmargindistance=-\rightmargintotal,
-% default=outer]
-% \starttext
-% \placeedgefigure{}{\framed[width=12cm]{}} \input tufte
-% \placeedgefigure{}{\framed[width=5cm]{}} \input tufte
-% \placeedgefigure{}{\framed[width=4cm]{}} \input tufte
-% \placeedgefigure{}{\framed[width=2cm]{}} \input tufte
-% \stoptext
-
-% todo: dimexpr an dnumexpr
-
% These macro deal with side floats. We started with Daniel
% Comenetz macros as published in TUGBoat Volume 14 (1993),
% No.\ 1: Anchored Figures at Either Margin. I extended and
@@ -40,90 +22,113 @@
% messy module. Therefore, this module badly needs an update
% because it's now a mixture of old and new macros.
-% afhankelijke variabelen
+% Interesting cases where it goes wrong:
%
-% \overgap vervangen door \floatsidetopskip
-% \sidegap vervangen door \floatsideskip
-% \undergap vervangen door \floatsidebottomskip
+% \placefigure[left]{}{} \dorecurse{3}{\input ward } {\par} \input ward
%
-% \prskp vervangen door \ctxparskip
-
-% toegevoegde macro's/aanroepen
-%
-% \logsidefloat : loginformatie
-% \flushsidefloats : nodig voor koppen
-
-% recente wijzigingen:
+% Here we get an unwanted carried over hangindent and parindent. A
+% solution is to associate it with the local par node instead. This
+% is something to discuss with Taco as it could be a new luatex
+% feature: explicitly set par properties.
+
+% Maybe I should just rewrite the lot.
+
+\newdimen \d_page_sides_height % includes the topskip
+\newdimen \d_page_sides_width
+\newdimen \d_page_sides_hsize
+\newdimen \d_page_sides_vsize
+\newdimen \d_page_sides_vsize_reset \d_page_sides_vsize_reset -\onepoint % could be a \let
+\newdimen \d_page_sides_progress
+\newdimen \d_page_sides_page_total
+\newdimen \d_page_sides_saved_depth
+\newdimen \d_page_sides_grid_shift
+
+\newbox \b_page_sides_bottom
+
+\newcount \c_page_sides_lines_done
+\newcount \c_page_sides_checks_done
+\newcount \c_page_sides_n_of_lines
+\newcount \c_page_sides_n_of_hang
+\newconstant \c_page_sides_float_type
+
+\newconditional \c_page_sides_short
+\newconditional \c_page_sides_flag
+
+\newconditional \c_page_sides_r_eq % messy, needs checking anyway
+\newconditional \c_page_sides_l_eq % messy, needs checking anyway
+
+\newdimen \d_page_sides_shift
+\newdimen \d_page_sides_extrashift
+\newdimen \d_page_sided_leftshift
+\newdimen \d_page_sided_rightshift
+\newdimen \d_page_sides_leftskip
+\newdimen \d_page_sides_rightskip
+\newdimen \d_page_sides_maximum
+\newdimen \d_page_sides_topskip
+\newdimen \d_page_sides_bottomskip
+\newdimen \d_page_sides_downshift
+
+\setnewconstant \c_page_sides_align \zerocount
+\setnewconstant \c_page_sides_method \plusone % 0=raw 1=safe (.99) 2=tight (-1pt)
+
+% begin of public variables, this will change
%
-% namen aangepast: \float... enz. i.p.v. \pic
-
-% Pas op: \EveryPar{\EveryPar{}\margetitel{whatever}}
-% \plaatsfiguur[links]{}{} moet goed gaan. In dat geval
-% begint de tekst terecht wat lager.
-
-\newdimen\sidefloatheight % includes the topskip
-\newdimen\sidefloatwidth
-\newdimen\sidefloathsize
-\newdimen\sidefloatshift
-\newdimen\sidefloatextrashift
-\newdimen\sidefloatvsize \def\nofloatvsize{-1pt }
-\newdimen\sidefloatprogress
-\newdimen\sidefloatpagetotal
-
-\newbox\floatbottom
-
-\newcount\sidefloatsidelines
-\newcount\sidefloatlinesdone
-
-% 1 = backspace
-% 2 = leftedge
-% 3 = leftmargin
-% 4 = leftside
-% 5 = rightside
-% 6 = rightmargin
-% 7 = rightedge
-% 8 = cutspace
-
-\newconstant\sidefloattype
-
-\def\backspacefloat {\global\sidefloattype1 \putsidefloat}
-\def\leftedgefloat {\global\sidefloattype2 \putsidefloat}
-\def\leftmarginfloat {\global\sidefloattype3 \putsidefloat}
-\def\leftfloat {\global\sidefloattype4 \putsidefloat}
-\def\rightfloat {\global\sidefloattype5 \putsidefloat}
-\def\rightmarginfloat {\global\sidefloattype6 \putsidefloat}
-\def\rightedgefloat {\global\sidefloattype7 \putsidefloat}
-\def\cutspacefloat {\global\sidefloattype8 \putsidefloat}
-
-\let\marginfloat \cutspacefloat
-
-\newif\ifroomforfloat
-\newif\iffloatshort
-\newif\iffloatflag
-\newif\iffloatrighteqo
-\newif\iffloatlefteqo
-
-\newdimen\sidefloatleftskip
-\newdimen\sidefloatrightskip
-\newdimen\sidefloatmaximum
-
-\def\checksidefloatshift
- {\ifdim\sidefloatmaximum>\zeropoint
- \ifcase\sidefloattype
+% we need a setter and resetter .. or maybe a \placesidefloat[settings] to
+% keep variables separated
+
+\let\sidefloatshift \d_page_sides_shift
+\let\sidefloatextrashift\d_page_sides_extrashift
+\let\sidefloatleftshift \d_page_sided_leftshift
+\let\sidefloatrightshift\d_page_sided_rightshift
+\let\sidefloatleftskip \d_page_sides_leftskip
+\let\sidefloatrightskip \d_page_sides_rightskip
+\let\sidefloatmaximum \d_page_sides_maximum
+\let\sidefloattopskip \d_page_sides_topskip
+\let\sidefloatbottomskip\d_page_sides_bottomskip
+\let\sidefloatdownshift \d_page_sides_downshift
+
+\let\sidefloatsidelines \c_page_sides_n_of_lines
+
+\let\sidefloatalign \c_page_sides_align
+\let\sidefloatmethod \c_page_sides_method
+
+\def\page_sides_process_float_backspace {\global\c_page_sides_float_type\plusone \page_sides_handle_float}
+\def\page_sides_process_float_leftedge {\global\c_page_sides_float_type\plustwo \page_sides_handle_float}
+\def\page_sides_process_float_leftmargin {\global\c_page_sides_float_type\plusthree\page_sides_handle_float}
+\def\page_sides_process_float_left {\global\c_page_sides_float_type\plusfour \page_sides_handle_float}
+\def\page_sides_process_float_right {\global\c_page_sides_float_type\plusfive \page_sides_handle_float}
+\def\page_sides_process_float_rightmargin{\global\c_page_sides_float_type\plussix \page_sides_handle_float}
+\def\page_sides_process_float_rightedge {\global\c_page_sides_float_type\plusseven\page_sides_handle_float}
+\def\page_sides_process_float_cutspace {\global\c_page_sides_float_type\pluseight\page_sides_handle_float}
+\def\page_sides_process_float_margin {\global\c_page_sides_float_type\pluseight\page_sides_handle_float}
+
+\let\logsidefloat \relax
+
+\newif\ifroomforfloat % shared (will change)
+\newif\iftracesidefloats % public (might change)
+
+% end of public variables
+
+\def\page_sides_insert_info
+ {\doinsertfloatinfo}
+
+\def\page_sides_apply_horizontal_shift
+ {\ifdim\d_page_sides_maximum>\zeropoint
+ \ifcase\c_page_sides_float_type
% invalid
\or
% backspace
\or
- \global\sidefloatshift\dimexpr
- -\sidefloatmaximum
+ \global\d_page_sides_shift\dimexpr
+ -\d_page_sides_maximum
-\rightorleftpageaction \leftedgedistance \rightedgedistance
-\rightorleftpageaction \leftmarginwidth \rightmarginwidth
-\rightorleftpageaction \leftmargindistance \rightmargindistance
-\compensatedinnermakeupmargin
\relax
\or
- \global\sidefloatshift\dimexpr
- -\sidefloatmaximum
+ \global\d_page_sides_shift\dimexpr
+ -\d_page_sides_maximum
-\rightorleftpageaction \leftmargindistance \rightmargindistance
-\compensatedinnermakeupmargin
\relax
@@ -132,14 +137,14 @@
\or
% right
\or
- \global\sidefloatshift\dimexpr
- -\sidefloatmaximum
+ \global\d_page_sides_shift\dimexpr
+ -\d_page_sides_maximum
-\rightorleftpageaction \leftmargindistance \rightmargindistance
-\compensatedinnermakeupmargin
\relax
\or
- \global\sidefloatshift\dimexpr
- -\sidefloatmaximum
+ \global\d_page_sides_shift\dimexpr
+ -\d_page_sides_maximum
-\rightorleftpageaction \leftedgedistance \rightedgedistance
-\rightorleftpageaction \leftmarginwidth \rightmarginwidth
-\rightorleftpageaction \leftmargindistance \rightmargindistance
@@ -148,433 +153,444 @@
\or
% cutspace
\fi
+ \fi
+ \ifdim\d_page_sides_shift=\zeropoint \relax
+ \ifnum\c_page_sides_float_type=\plusfour
+ \global\advance\d_page_sides_shift\d_page_sides_extrashift
+ \global\d_page_sides_extrashift\zeropoint
+ \else\ifnum\c_page_sides_float_type=\plusfive
+ \global\advance\d_page_sides_shift\d_page_sides_extrashift
+ \global\d_page_sides_extrashift\zeropoint
+ \fi\fi
+ \else
+ \ifnum\c_page_sides_float_type<\plusfour
+ \global\c_page_sides_float_type\plusfour
+ \else\ifnum\c_page_sides_float_type>\plusfive
+ \global\c_page_sides_float_type\plusfive
+ \fi\fi
\fi}
-\def\setsidefloatskips
- {\global\sidefloatrightskip\zeropoint
- \global\sidefloatleftskip \zeropoint
- \ifcase\sidefloattype
+\def\page_sides_set_skips
+ {\global\d_page_sides_rightskip\zeropoint
+ \global\d_page_sides_leftskip \zeropoint
+ \ifcase\c_page_sides_float_type
\or % backspace
- \global\sidefloatleftskip\dimexpr
+ \global\d_page_sides_leftskip\dimexpr
+\rightorleftpageaction \backspace \cutspace
+\compensatedinnermakeupmargin
\relax
\or % leftedge
- \global\sidefloatleftskip\dimexpr
+ \global\d_page_sides_leftskip\dimexpr
+\rightorleftpageaction \leftmargindistance \rightmargindistance
+\rightorleftpageaction \leftmarginwidth \rightmarginwidth
+\rightorleftpageaction \leftedgedistance \rightedgedistance
+\compensatedinnermakeupmargin
\relax
\or % leftmargin
- \global\sidefloatleftskip\dimexpr
+ \global\d_page_sides_leftskip\dimexpr
+\rightorleftpageaction \leftmargindistance \rightmargindistance
+\compensatedinnermakeupmargin
\relax
\or % leftside
\or % rightside
\or % rightmargin
- \global\sidefloatrightskip\dimexpr
+ \global\d_page_sides_rightskip\dimexpr
+\rightorleftpageaction \rightmargindistance \leftmargindistance
+\compensatedinnermakeupmargin
\relax
\or % rightedge
- \global\sidefloatrightskip\dimexpr
+ \global\d_page_sides_rightskip\dimexpr
+\rightorleftpageaction \rightmargindistance \leftmargindistance
+\rightorleftpageaction \rightmarginwidth \leftmarginwidth
+\rightorleftpageaction \rightedgedistance \leftedgedistance
+\compensatedinnermakeupmargin
\relax
\or % cutspace
- \global\sidefloatrightskip\dimexpr
+ \global\d_page_sides_rightskip\dimexpr
+\rightorleftpageaction \cutspace \backspace
+\compensatedinnermakeupmargin
\relax
\fi
- \ifdim\sidefloatrightskip>\zeropoint \doglobal\advance\sidefloatrightskip\rightskip \fi
- \ifdim\sidefloatleftskip >\zeropoint \doglobal\advance\sidefloatleftskip \leftskip \fi}
-
-% eq is still crap
+ \ifdim\d_page_sides_rightskip>\zeropoint \doglobal\advance\d_page_sides_rightskip\rightskip \fi
+ \ifdim\d_page_sides_leftskip >\zeropoint \doglobal\advance\d_page_sides_leftskip \leftskip \fi}
-\ifx\normalleqno\undefined
-
- \let\floatrighteqo=\eqno
- \let\floatleftleqo=\leqno
-
-\else
-
- \let\floatrighteqo=\normaleqno
- \let\floatleftleqo=\normalleqno
-
-\fi
-
-% Watch it even more! In inner, gaat't mis omdat daar
-% pagetotal enz niet zijn aangepast. Inner kan overigens niet
-% betrouwbaar worden getest!
-
-\newif\iftracesidefloats
-
-\def\flushsidefloats
+\def\page_sides_flush_floats
{\par
- \!!heighta\sidefloatvsize
- \advance\!!heighta -\pagetotal
- \ifnum\!!heighta>\zeropoint
- \global\advance\sidefloatvsize -\sidefloatbottomskip
- \ifdim\!!heighta>\zeropoint
- \bgroup
- \let\flushsidefloats\relax
- \forgetall
- \doloop
- {\strut
- \iftracesidefloats
- \color[darkgray]%
- {\baselinerulefalse
- \boxrulewidth.5\points
- \ruledhbox{\strut\kern\sidefloatwidth}}%
- \fi
- \par
- \!!heighta\sidefloatvsize
- \advance\!!heighta -\pagetotal
- \ifdim\!!heighta>\zeropoint
- \ifnum\recurselevel>\plushundred
- \exitloop
- \fi
- \else
- \exitloop
- \fi}%
- \egroup
- \ifdim\parskip>\zeropoint
- \ifdim\sidefloatbottomskip>\parskip
- \nowhitespace
- \vskip\sidefloatbottomskip
- \fi
- \fi
- \else\ifdim\sidefloatbottomskip>\parskip
- \vskip\sidefloatbottomskip
- \fi\fi
+ \ifnum\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint
+ \page_sides_flush_floats_indeed
\fi
- % not entirely the same as \forgetsidefloats
- \global\sidefloatvsize\nofloatvsize
- % \global\sidefloatsidelines\zerocount % no, we flush before a side float
- \global\floatshortfalse % so this will get lost
% also here if used at all \global\holdinginserts\zerocount
- \global\floatflagfalse}
+ \global\d_page_sides_vsize\d_page_sides_vsize_reset
+ \global\setfalse\c_page_sides_short
+ \global\setfalse\c_page_sides_flag}
+
+\def\page_sides_flush_floats_indeed
+ {\global\advance\d_page_sides_vsize-\d_page_sides_bottomskip
+ \begingroup
+ \let\page_sides_flush_floats\relax
+ \forgetall
+ \doloop
+ {\strut
+ \iftracesidefloats
+ \color[darkgray]%
+ {\baselinerulefalse
+ \boxrulewidth.5\points
+ \ruledhbox{\strut\kern\d_page_sides_width}}%
+ \fi
+ \par
+ \ifdim\dimexpr\d_page_sides_vsize-\pagetotal\relax>\zeropoint
+ \ifnum\recurselevel>\plushundred % safeguard, sort of deadcycles
+ \exitloop
+ \fi
+ \else
+ \exitloop
+ \fi}%
+ \endgroup
+ \ifdim\parskip>\zeropoint % why this test ?
+ \ifdim\d_page_sides_bottomskip>\parskip
+ \nowhitespace
+ \vskip\d_page_sides_bottomskip
+ \fi
+ \fi}
-\def\dochecksidefloatafterpar
- {\dochecksidefloat
+\def\page_sides_check_floats_after_par
+ {\page_sides_check_floats_indeed
\ifdim\oldpagetotal=\pagetotal \else
- \global\let\checksidefloat\dochecksidefloat
- \flushsidefloats
- \global\sidefloatsidelines\zerocount % here !
+ \global\let\page_sides_check_floats\page_sides_check_floats_indeed
+ \page_sides_flush_floats
+ \global\c_page_sides_n_of_lines\zerocount % here !
\fi}
-\def\flushsidefloatsafterpar
+\unexpanded\def\page_sides_flush_floats_after_par
{\xdef\oldpagetotal{\the\pagetotal}%
- \global\let\checksidefloat\dochecksidefloatafterpar}
+ \global\let\page_sides_check_floats\page_sides_check_floats_after_par}
-\def\forgetsidefloats
- {\global\sidefloatvsize\nofloatvsize
- \global\sidefloatsidelines\zerocount
+\unexpanded\def\page_sides_forget_floats
+ {\global\d_page_sides_vsize\d_page_sides_vsize_reset
+ \global\c_page_sides_n_of_lines\zerocount
% also here if used at all \global\holdinginserts\zerocount
- \global\floatshortfalse
- \global\floatflagfalse}
-
-\let\logsidefloat=\relax
-
-\def\pushpenalties % needed ? and right
- {\widowpenalty\plusone
- \clubpenalty\plustwo
- \brokenpenalty\plusone
- \let\pushpenalties\relax
- \edef\poppenalties
- {\widowpenalty \the\widowpenalty
- \clubpenalty \the\clubpenalty
- \brokenpenalty\the\brokenpenalty
- \let\poppenalties\relax}}
-
-% shouldn;t that be:
+ \global\setfalse\c_page_sides_short
+ \global\setfalse\c_page_sides_flag}
+
+\let\page_otr_sides_pop_penalties \relax
+\let\page_otr_sides_push_penalties\relax
+
+% \def\page_otr_sides_push_penalties % needed ? and right
+% {\widowpenalty\plusone
+% \clubpenalty\plustwo
+% \brokenpenalty\plusone
+% \let\page_otr_sides_push_penalties\relax
+% \edef\page_otr_sides_pop_penalties
+% {\widowpenalty \the\widowpenalty
+% \clubpenalty \the\clubpenalty
+% \brokenpenalty\the\brokenpenalty
+% \let\page_otr_sides_pop_penalties\relax}}
+%
+% shouldn't that be:
%
-% \def\pushpenalties % needed?
-% {\let\pushpenalties\relax
-% \edef\poppenalties
+% \def\page_otr_sides_push_penalties % needed?
+% {\let\page_otr_sides_push_penalties\relax
+% \edef\page_otr_sides_pop_penalties
% {\widowpenalty \the\widowpenalty
% \clubpenalty \the\clubpenalty
% \brokenpenalty\the\brokenpenalty
-% \let\poppenalties\relax}%
+% \let\page_otr_sides_pop_penalties\relax}%
% \widowpenalty\plusone
% \clubpenalty\plustwo
% \brokenpenalty\plusone}
-\let\poppenalties=\relax
-
-\def\restorepenalties
- {\ifnum\outputpenalty=\!!tenthousand\else
+\def\page_sides_restore_output_penalty
+ {\ifnum\outputpenalty=\plustenthousand \else
\penalty\outputpenalty
\fi}
-\def\sidefloatoutput
- {\iffloatshort
- \unvbox\normalpagebox
- \setbox\floatbottom\lastbox
- \ifdim\wd\floatbottom>\sidefloathsize
- \penalty-201
- \box\floatbottom
- \else
- \ifvoid\floatbottom
+\def\page_sides_output_routine
+ {\ifconditional\c_page_sides_short
+ \page_sides_output_routine_yes
+ \else
+ \page_sides_output_routine_nop
+ \fi}
+
+\def\page_sides_output_routine_nop
+ {\page_otr_command_side_float_output % otr specific
+ \global\d_page_sides_vsize\d_page_sides_vsize_reset
+ \global\c_page_sides_n_of_lines\zerocount
+ % we can end up in fig lock, so \global\holdinginserts\zerocount here too ?
+ \page_otr_sides_pop_penalties}
+
+\def\page_sides_output_routine_yes % we need to rework this ... add pagediscards and such
+ {\unvbox\normalpagebox
+ \setbox\b_page_sides_bottom\lastbox
+ \ifdim\wd\b_page_sides_bottom>\d_page_sides_hsize
+ \penalty-201
+ \box\b_page_sides_bottom
+ \else\ifvoid\b_page_sides_bottom
+ \else
+ \page_sides_restore_left_indent
+ \ifdim\wd\b_page_sides_bottom<\d_page_sides_hsize
+ \parskip\zeropoint
+ %\noindent
+ \ifinner\else\vadjust{\penalty\minusone}\fi
+ \ifconditional\c_page_sides_l_eq
+ \global\setfalse\c_page_sides_l_eq
\else
- \restoreleftindent
- \ifdim\wd\floatbottom<\sidefloathsize
- \parskip\zeropoint
- %\noindent
- \ifinner\else\vadjust{\penalty\minusone}\fi
- \iffloatlefteqo
- \global\floatlefteqofalse
- \else
- \global\advance\sidefloathsize -\wd\floatbottom
- \iffloatrighteqo
- \global\floatrighteqofalse
- \else
- \global\divide\sidefloathsize \plustwo
- \fi
- \hskip\sidefloathsize
- \fi
+ \global\advance\d_page_sides_hsize -\wd\b_page_sides_bottom
+ \ifconditional\c_page_sides_r_eq
+ \global\setfalse\c_page_sides_r_eq
+ \else
+ \global\divide\d_page_sides_hsize \plustwo
\fi
- \box\floatbottom
- \restorepenalties
+ \hskip\d_page_sides_hsize % \kern
\fi
\fi
- % why was this \global\holdinginserts\zerocount
- \global\floatshortfalse
- \else
- \finalsidefloatoutput % new
- \global\sidefloatvsize\nofloatvsize
- \global\sidefloatsidelines\zerocount
- % we can end up in fig lock, so \global\holdinginserts\zerocount here too ?
- \poppenalties
- \fi}
-
-\def\finalsidefloatoutput% new
- {\finaloutput\unvbox\normalpagebox}
+ \box\b_page_sides_bottom
+ \page_sides_restore_output_penalty
+ \fi\fi
+ % why was this \global\holdinginserts\zerocount
+ \global\setfalse\c_page_sides_short}
-\def\restoreleftindent
- {\relax \ifnum\sidefloattype>4 \else
+\def\page_sides_restore_left_indent
+ {\relax
+ \ifnum\c_page_sides_float_type>\plusfour \else
\parskip\zeropoint % here ?
- \ifdim\sidefloatwidth>\zeropoint % new, see prikkels
+ \ifdim\d_page_sides_width>\zeropoint % new, see prikkels
\noindent
- \ifinner\else\vadjust{\penalty\minusone}\fi
- \hskip\sidefloatwidth\relax
+ \ifinner \else
+ \vadjust{\penalty\minusone}%
+ \fi
+ \hskip\d_page_sides_width\relax % \kern
%\else
% we have a margin or edge float
\fi
\fi}
-\ifx\normaleqno\undefined
-
- \def\normaleqno
- {\iffloatshort
- \global\floatrighteqotrue
- \fi
- \floatrighteqo}
-
-\else
-
- \def\eqno
- {\iffloatshort
- \global\floatrighteqotrue
- \fi
- \floatrighteqo}
-
-\fi
-
-% externfiguur -> grid =ja|hoogte|diepte|halveregel|passend -> helemaal in details
-% stelplaatsblokin -> zijuitlijnen=hoogte|diepte|regel|halveregel|grid -> halveregel in 'details'
-
-% replacement for below
+% The clean way:
%
-% \global\setbox\floatbox\hbox % no \hskip, but \kern here
-% {\ifcase\sidefloattype
-% \vbox{#1}%
-% \or % 1
-% \hskip\sidefloatleftshift
-% \hskip\sidefloatshift
-% \vbox{#1}%
-% \kern-\sidefloatextrashift
-% \or % 2
-% \hskip\sidefloatshift
-% \vbox{#1}%
-% \kern-\sidefloatextrashift
-% \or % 3
-% \hskip\sidefloatshift
-% \vbox{#1}%
-% \kern-\sidefloatextrashift
-% \or % 4
-% \hskip\sidefloatleftshift
-% \hskip\sidefloatshift
-% \vbox{#1\removedepth}%
-% \kern-\sidefloatextrashift
-% \or % 5
-% \hskip-\sidefloatextrashift
-% \vbox{#1}%
-% \kern\sidefloatshift
-% \kern\sidefloatrightshift
-% \or % 6
-% \hskip-\sidefloatextrashift
-% \vbox{#1}%
-% \kern\sidefloatshift
-% \or % 7
-% \hskip-\sidefloatextrashift
-% \vbox{#1}%
-% \kern\sidefloatshift
-% \or % 8
-% \hskip-\sidefloatextrashift
-% \vbox{#1}%
-% \kern\sidefloatshift
-% \kern\sidefloatrightshift
-% \fi}%
+% \global\setbox\floatbox\hbox
+% {\ifcase\c_page_sides_float_type
+% \vbox{#1}%
+% \or % 1
+% \kern\d_page_sided_leftshift
+% \kern\d_page_sides_shift
+% \vbox{#1}%
+% \kern-\d_page_sides_extrashift
+% \or % 2
+% \kern\d_page_sides_shift
+% \vbox{#1}%
+% \kern-\d_page_sides_extrashift
+% \or % 3
+% \kern\d_page_sides_shift
+% \vbox{#1}%
+% \kern-\d_page_sides_extrashift
+% \or % 4
+% \kern\d_page_sided_leftshift
+% \kern\d_page_sides_shift
+% \vbox{#1\removedepth}%
+% \kern-\d_page_sides_extrashift
+% \or % 5
+% \kern-\d_page_sides_extrashift
+% \vbox{#1}%
+% \kern\d_page_sides_shift
+% \kern\d_page_sided_rightshift
+% \or % 6
+% \kern-\d_page_sides_extrashift
+% \vbox{#1}%
+% \kern\d_page_sides_shift
+% \or % 7
+% \kern-\d_page_sides_extrashift
+% \vbox{#1}%
+% \kern\d_page_sides_shift
+% \or % 8
+% \kern-\d_page_sides_extrashift
+% \vbox{#1}%
+% \kern\d_page_sides_shift
+% \kern\d_page_sided_rightshift
+% \fi}
%
-% keep this ^
-
-\def\repositionsidefloat#1%
- {\global\setbox\floatbox\hbox % no \hskip, but \kern here
- {\ifnum\sidefloattype=\plusfour
- \hskip\sidefloatleftshift
- \else\ifnum\sidefloattype=\plusone
- \hskip\sidefloatleftshift
+% The compact way:
+
+\def\page_sides_relocate_float#1%
+ {\global\setbox\floatbox\hbox
+ {\ifnum\c_page_sides_float_type=\plusfour
+ \kern\d_page_sided_leftshift
+ \else\ifnum\c_page_sides_float_type=\plusone
+ \kern\d_page_sided_leftshift
\fi\fi
- \ifnum\sidefloattype>\plusfour
- \hskip-\sidefloatextrashift
+ \ifnum\c_page_sides_float_type>\plusfour
+ \kern-\d_page_sides_extrashift
\else
- \hskip\sidefloatshift
+ \kern\d_page_sides_shift
\fi
- \vbox{#1\ifnum\sidefloatalign=\plusfour \removedepth\fi}%
- \ifnum\sidefloattype>\plusfour
- \kern\sidefloatshift
+ \vbox{#1\ifnum\c_page_sides_align=\plusfour \removedepth\fi}%
+ \ifnum\c_page_sides_float_type>\plusfour
+ \kern\d_page_sides_shift
\else
- \kern-\sidefloatextrashift
+ \kern-\d_page_sides_extrashift
\fi
- \ifnum\sidefloattype=8
- \kern\sidefloatrightshift
- \else\ifnum\sidefloattype=\plusfive
- \kern\sidefloatrightshift
+ \ifnum\c_page_sides_float_type=\pluseight
+ \kern\d_page_sided_rightshift
+ \else\ifnum\c_page_sides_float_type=\plusfive
+ \kern\d_page_sided_rightshift
\fi\fi}}
-\def\putsidefloat#1% grid (4) is rather experimental
- {\par
- \whitespace
- % moved here dec 2001
- {\everypar\emptytoks\forgetall\verticalstrut\vskip-\struttotal}% moved
- \checksidefloatshift
- \ifdim\sidefloatshift=\zeropoint \relax
- \ifnum\sidefloattype=\plusfour
- \global\advance\sidefloatshift\sidefloatextrashift
- \global\sidefloatextrashift\zeropoint
- \else\ifnum\sidefloattype=\plusfive
- \global\advance\sidefloatshift\sidefloatextrashift
- \global\sidefloatextrashift\zeropoint
- \fi\fi
- \else
- \ifnum\sidefloattype<\plusfour
- \global\sidefloattype\plusfour
- \else\ifnum\sidefloattype>\plusfive
- \global\sidefloattype\plusfive
- \fi\fi
- \fi
- \previoussidefloat
- \stallsidefloat
- \repositionsidefloat{#1}%
- \ifnum\sidefloatalign=\plusfour
+\def\page_sides_apply_vertical_shift
+ {\ifnum\c_page_sides_align=\plusfour
\getnoflines{\ht\floatbox}%
- \scratchdimen\noflines\lineheight
- \advance\scratchdimen-\strutdepth
- \getrawnoflines\sidefloattopskip
+ \scratchdimen\dimexpr\noflines\lineheight-\strutdepth\relax
+ \getrawnoflines\d_page_sides_topskip
\advance\scratchdimen\noflines\lineheight
% todo: maybe rounding problem here
% \global\setbox\floatbox\hbox{\lower\lineheight\box\floatbox}%
\global\setbox\floatbox\hbox{\lower\strutdepth\box\floatbox}%
- \global\ht\floatbox\scratchdimen
- \global\dp\floatbox\zeropoint
+ \ht\floatbox\scratchdimen
+ \dp\floatbox\zeropoint
\fi
- \ifcase\sidefloatalign \else
- \global\sidefloattopskip\zeropoint
+ \ifcase\c_page_sides_align \else
+ \global\d_page_sides_topskip\zeropoint
\fi
\scratchdimen
- \ifnum\sidefloattype<\plusfour
- \sidefloattopskip
- \else\ifnum\sidefloattype>\plusfive
- \sidefloattopskip
+ \ifnum\c_page_sides_float_type<\plusfour
+ \d_page_sides_topskip
+ \else\ifnum\c_page_sides_float_type>\plusfive
+ \d_page_sides_topskip
\else
\zeropoint
\fi\fi
% the top of the box is at the previous baseline
- \ifcase\sidefloatalign
+ \ifcase\c_page_sides_align
% 0 normal
- \advance\scratchdimen\strutdepth % == \sidefloattopoffset
+ \advance\scratchdimen\strutdepth % or \openstrutdepth
\or % 1 height
- \advance\scratchdimen\strutdepth % == \sidefloattopoffset
+ \advance\scratchdimen\strutdepth % or \openstrutdepth
\or % 2 line
\or % 3 depth
- \advance\scratchdimen\lineheight
- \advance\scratchdimen\strutdepth
+ \advance\scratchdimen\lineheight % or \openlineheight
+ \advance\scratchdimen\strutdepth % or \openstrutdepth
\or % 4 grid
\scratchdimen\zeropoint
\or
- \advance\scratchdimen\strutheight
+ \advance\scratchdimen\strutheight % or \openstrutheight
\fi
% new
- \global\sidefloatlinesdone\zerocount
- \ifnum\sidefloatsidelines>\zerocount
- \advance\scratchdimen\sidefloatsidelines\lineheight
+ \global\c_page_sides_lines_done\zerocount
+ \ifnum\c_page_sides_n_of_lines>\zerocount
+ \advance\scratchdimen\c_page_sides_n_of_lines\lineheight
\fi
- % new
- \global\setbox\floatbox\hbox
+ \global\setbox\floatbox\hbox % why extra box
{\vbox
{\vskip\scratchdimen
\nointerlineskip
\box\floatbox
- \ifnum\sidefloatalign=\plusfive \vskip-\lineheight \fi}}%
- \ifnum\sidefloattype<\plusfour
- \global\sidefloattopskip\zeropoint
- \else\ifnum\sidefloattype>\plusfive
- \global\sidefloattopskip\zeropoint
+ \ifnum\c_page_sides_align=\plusfive \vskip-\lineheight \fi}}%
+ \ifnum\c_page_sides_float_type<\plusfour
+ \global\d_page_sides_topskip\zeropoint
+ \else\ifnum\c_page_sides_float_type>\plusfive
+ \global\d_page_sides_topskip\zeropoint
\fi\fi
- \global\sidefloatdownshift\zeropoint
- \measuresidefloat
- \ifroomforfloat \else
- \vfill\eject % inline \tosssidefloat
- \measuresidefloat
- \stallsidefloat
+ \global\d_page_sides_downshift\zeropoint}
+
+\def\page_sides_place_float
+ {\ifnum\c_page_sides_float_type=\plusfour \kern\d_page_sides_topskip \fi
+ \ifnum\c_page_sides_float_type=\plusfive \kern\d_page_sides_topskip \fi
+ \d_page_sides_saved_depth\prevdepth
+ \nointerlineskip
+ \ifgridsnapping
+ \page_sides_place_float_grid
+ \else
+ \page_sides_place_float_normal
+ \fi
+ \par
+ \kern-\d_page_sides_height
+ \penalty10001 % oeps, this will change
+ \normalbaselines
+ \prevdepth\d_page_sides_saved_depth}
+
+\def\page_sides_place_float_normal
+ {\d_page_sides_grid_shift\zeropoint % be nice
+ \page_sides_push_float_inline\firstofoneargument}
+
+% The following needs some more work .. consider this a quick hack. We
+% probably need an mkiv hanging grid option.
+
+\def\page_sides_place_snap_to_grid#1%
+ {\snaptogrid[\v!line,\v!offset:\the\d_page_sides_grid_shift]\hbox{#1}}
+
+% this will be a grid option in float placement:
+
+\newconstant\c_page_sides_place_grid_shift \c_page_sides_place_grid_shift\plustwo
+
+\def\page_sides_place_float_grid
+ {\getrawnoflines\d_page_sides_height % raw ?
+ \d_page_sides_height\noflines\lineheight
+ \d_page_sides_grid_shift\the\dimexpr \plustwo\lineheight
+ \ifcase\c_page_sides_place_grid_shift
+ -3\lineheight % high
+ \or
+ -2.5\lineheight % half (does not work currently)
+ \else
+ -2\lineheight % low
+ \fi
+ \relax
+ \page_sides_push_float_inline\page_sides_place_snap_to_grid}
+
+\def\page_sides_push_float_inline#1%
+ {\begingroup
+ \everypar\emptytoks % needed !
+ \parskip\zeropoint % needed !
+ \page_sides_set_skips
+ \page_sides_insert_info
+ \relax
+ \lefttoright % \textdir TLT\relax % or \ifconditional\displaylefttoright below (more work)
+ \ifcase\c_page_sides_float_type
+ % invalid
+ \or % backspace
+ \noindent#1{\llap{\rlap{\box\floatbox}\kern\d_page_sides_leftskip}}\hfill
+ \or % leftedge
+ \noindent#1{\llap{\box\floatbox\kern\d_page_sides_leftskip}}\hfill
+ \or % leftmargin
+ \noindent#1{\llap{\box\floatbox\kern\d_page_sides_leftskip}}\hfill
+ \or % leftside
+ \noindent#1{\box\floatbox}\hfill
+ \or % rightside
+ \hfill#1{\box\floatbox}%
+ \or % rightmargin
+ \hfill#1{\rlap{\kern\d_page_sides_rightskip\box\floatbox}}%
+ \or % rightedge
+ \hfill#1{\rlap{\kern\d_page_sides_rightskip\box\floatbox}}%
+ \or % cutspace
+ \hfill#1{\rlap{\kern\d_page_sides_rightskip\llap{\box\floatbox}}}%
\fi
- \setsidefloat}
-
-\def\progresssidefloat
- {\sidefloatprogress\sidefloatvsize
- \advance\sidefloatprogress-\iffloatflag\sidefloatpagetotal\global\floatflagfalse\else\pagetotal\fi}
-
-\def\measuresidefloat
- {\global\floatflagtrue
- \global\sidefloatpagetotal \pagetotal % global
- \ifnum\sidefloattype<\plusfour
- \global \sidefloatwidth \zeropoint
- \else\ifnum\sidefloattype>\plusfive
- \global \sidefloatwidth \zeropoint
+ \endgroup}
+
+\def\page_sides_analyse_progress
+ {\d_page_sides_progress\d_page_sides_vsize
+ \ifconditional\c_page_sides_flag
+ \advance\d_page_sides_progress-\d_page_sides_page_total
+ \global\setfalse\c_page_sides_flag
+ \else
+ \advance\d_page_sides_progress-\pagetotal
+ \fi}
+
+\def\page_sides_analyse_space
+ {\global\settrue\c_page_sides_flag
+ \global\d_page_sides_page_total \pagetotal % global
+ \ifnum\c_page_sides_float_type<\plusfour
+ \global\d_page_sides_width \zeropoint
+ \else\ifnum\c_page_sides_float_type>\plusfive
+ \global\d_page_sides_width\zeropoint
\else
- \global \sidefloatwidth \wd\floatbox
- \global\advance\sidefloatwidth \floatsideskip
+ \global\d_page_sides_width\dimexpr\wd\floatbox+\floatsideskip\relax
\fi\fi
- \ifdim\sidefloatwidth<\zeropoint
- \global\sidefloatwidth\zeropoint
+ \ifdim\d_page_sides_width<\zeropoint
+ \global\d_page_sides_width\zeropoint
\fi
- \global \sidefloathsize \hsize
- \global\advance\sidefloathsize -\sidefloatwidth
- \global \sidefloatheight \ht\floatbox
- \global\advance\sidefloatheight \dp\floatbox
- \global\advance\sidefloatheight \sidefloattopskip
- \global \sidefloatvsize \sidefloatheight
- \global\advance\sidefloatvsize \sidefloatpagetotal
- \dimen0\sidefloatvsize
+ \global\d_page_sides_hsize \dimexpr\hsize-\d_page_sides_width\relax
+ \global\d_page_sides_height\dimexpr\ht\floatbox+\dp\floatbox+\d_page_sides_topskip\relax
+ \global\d_page_sides_vsize \dimexpr\d_page_sides_height+\d_page_sides_page_total\relax
+ \dimen0\d_page_sides_vsize
\dimen2\pagegoal
\relax
- \ifcase\sidefloatmethod
+ \ifcase\c_page_sides_method
% method 0 : raw
\or
% method 1 : safe
@@ -587,209 +603,194 @@
\ifdim\dimen0>\dimen2
\global\roomforfloatfalse
\else
- \dimen0=\pagegoal
- \advance\dimen0 -\sidefloatvsize
- \ifdim\dimen0<\sidefloatbottomskip
- \global\advance\sidefloatvsize \dimen0
- \global\floatshorttrue
- \pushpenalties
+ \ifdim\dimexpr\pagegoal-\d_page_sides_vsize\relax<\d_page_sides_bottomskip
+ \global\advance\d_page_sides_vsize \dimen0
+ \global\settrue\c_page_sides_short
+ \page_otr_sides_push_penalties
% why was this \global\holdinginserts\plusone
\else
- \global\advance\sidefloatvsize \sidefloatbottomskip
- \global\floatshortfalse
+ \global\advance\d_page_sides_vsize \d_page_sides_bottomskip
+ \global\setfalse\c_page_sides_short
\fi
\global\roomforfloattrue
\fi}
-\def\setsidefloat% nilling everypar saves time and redudant pos's
- {% removed here dec 2001
- % {\everypar\emptytoks\forgetall\verticalstrut\vskip-\struttotal}%
- \ifnum\sidefloattype=\plusfour \kern\sidefloattopskip \fi
- \ifnum\sidefloattype=\plusfive \kern\sidefloattopskip \fi
- \edef\presidefloatdepth{\the\prevdepth}%
- \nointerlineskip
- \bgroup
+\def\page_sides_prepare_space
+ {\par
+ \whitespace
+ \begingroup
\everypar\emptytoks
- \parskip\zeropoint
- \setsidefloatskips
- \logsidefloat
- \relax
- \ifcase\sidefloattype
- % invalid
- \or % backspace
- \noindent\llap{\rlap{\box\floatbox}\hskip\sidefloatleftskip}\hfill
- \or % leftedge
- \noindent\llap{\box\floatbox\hskip\sidefloatleftskip}\hfill
- \or % leftmargin
- \noindent\llap{\box\floatbox\hskip\sidefloatleftskip}\hfill
- \or % leftside
- \noindent\box\floatbox\hfill
- \or % rightside
- \hfill\box\floatbox
- \or % rightmargin
- \hfill\rlap{\hskip\sidefloatrightskip\box\floatbox}%
- \or % rightedge
- \hfill\rlap{\hskip\sidefloatrightskip\box\floatbox}%
- \or % cutspace
- \hfill\rlap{\hskip\sidefloatrightskip\llap{\box\floatbox}}%
+ \forgetall
+ \verticalstrut
+ \vskip-\struttotal
+ \endgroup}
+
+\def\page_sides_handle_float#1% grid (4) is rather experimental
+ {\page_sides_prepare_space
+ \page_sides_apply_horizontal_shift
+ \page_sides_check_previous_float
+ \page_sides_inject_dummy_lines
+ \page_sides_relocate_float{#1}%
+ \page_sides_apply_vertical_shift
+ \page_sides_analyse_space
+ \ifroomforfloat \else
+ \page_otr_fill_and_eject_page
+ \page_sides_analyse_space
+ \page_sides_inject_dummy_lines
\fi
- \egroup
- \par
-\ifgridsnapping
- \getrawnoflines\sidefloatheight
- \sidefloatheight=\noflines\lineheight
-\fi
- \kern-\sidefloatheight
- \penalty10001 % oeps, this will change
- \normalbaselines
- \prevdepth\presidefloatdepth
- % \noindent
- \resetsidefloatparagraph
+ \page_sides_place_float
+ \page_sides_check_floats_reset
\ignorespaces} % not really needed
-
-\newcount\sidefloatparagraph
-\def\iffirstsidefloatparagraph
- {\ifcase\sidefloatparagraph\or}
+\def\page_sides_check_floats_indeed
+ {\page_sides_analyse_progress
+ \ifdim\d_page_sides_progress>\zeropoint
+ \page_sides_check_floats_set
+ \else
+ \page_sides_check_floats_reset
+ \fi
+ \parskip\s_spac_whitespace_parskip}
-% without sidefloat lines
-%
-% \def\setsidefloatparagraph
-% {%\advance\sidefloatprogress \sidefloatbottomskip
-% %\!!counta\sidefloatprogress
-% \scratchdimen\sidefloatprogress
-% \advance\scratchdimen \strutht
-% \advance\scratchdimen -\roundingeps % new, needed in prikkels, prevent rounding errors
-% \!!counta\scratchdimen
-% \divide\!!counta \baselineskip
-% \ifnum\!!counta>0
-% \hangindent \ifnum\sidefloattype>4 -\fi\sidefloatwidth
-% \hangafter-\!!counta
-% \fi
-% \global\advance\sidefloatparagraph \plusone
-% \iftracesidefloats
-% \hskip-\sidefloatwidth
-% \color[darkgray]%
-% {\vrule\!!height.5\points\!!depth.5\points\!!width\sidefloatwidth
-% %\hskip-.25\bodyfontsize\showstruts\strut\hskip.25\bodyfontsize}%
-% \llap{\showstruts\strut\hskip.25\bodyfontsize}}%
-% \fi}
+\let\page_sides_check_floats\page_sides_check_floats_indeed
-\def\setsidefloatparagraph
- {%\advance\sidefloatprogress \sidefloatbottomskip
- %\!!counta\sidefloatprogress
- \scratchdimen\sidefloatprogress
- \advance\scratchdimen \strutht
- \advance\scratchdimen -\roundingeps % new, needed in prikkels, prevent rounding errors
- \!!counta\scratchdimen
- \divide\!!counta \baselineskip\relax
- \ifnum\!!counta>0
- % new from here
- \ifcase\sidefloatsidelines\else
- \ifcase\sidefloatlinesdone
- \global\sidefloatlinesdone\!!counta
+\def\iffirstsidefloatparagraph
+ {\ifcase\c_page_sides_checks_done\or}
+
+\unexpanded\def\page_sides_check_floats_set
+ {\scratchdimen\dimexpr\d_page_sides_progress+\strutht-\roundingeps\relax
+ \c_page_sides_n_of_hang\scratchdimen
+ \divide\c_page_sides_n_of_hang \baselineskip\relax
+ \ifnum\c_page_sides_n_of_hang>\zerocount
+ % new from here (needs test case, old code)
+ \ifcase\c_page_sides_n_of_lines
+ \else
+ \ifcase\c_page_sides_lines_done
+ \global\c_page_sides_lines_done\c_page_sides_n_of_hang
\else
- \scratchcounter\sidefloatlinesdone
- \advance\scratchcounter-\!!counta
- \global\advance\sidefloatsidelines-\scratchcounter
+ \scratchcounter\c_page_sides_lines_done
+ \advance\scratchcounter-\c_page_sides_n_of_hang
+ \global\advance\c_page_sides_n_of_lines-\scratchcounter
\fi
\fi
- \ifnum\sidefloatsidelines>\zerocount
+ % hm, when do we get the parshape branch? needs testing
+ \ifnum\c_page_sides_n_of_lines>\zerocount
\scratchtoks\emptytoks
- \scratchcounter\sidefloatsidelines
- \scratchdimen\hsize
- \advance\scratchdimen-\sidefloatwidth
- \dorecurse\sidefloatsidelines
+ \scratchcounter\c_page_sides_n_of_lines
+ \scratchdimen\dimexpr\hsize-\d_page_sides_width\relax
+ \dorecurse\c_page_sides_n_of_lines
{\appendtoks \zeropoint \hsize \to \scratchtoks}%
- \ifnum\!!counta>\sidefloatsidelines
- \advance\!!counta -\sidefloatsidelines\relax
- \advance\scratchcounter\!!counta
- \dorecurse\!!counta
- {\ifnum\sidefloattype>\plusfour
- \appendtoks \zeropoint \scratchdimen \to \scratchtoks
+ \ifnum\c_page_sides_n_of_hang>\c_page_sides_n_of_lines
+ \advance\c_page_sides_n_of_hang -\c_page_sides_n_of_lines\relax
+ \advance\scratchcounter\c_page_sides_n_of_hang
+ \dorecurse\c_page_sides_n_of_hang % weird, shouldn't that be scratchcounter
+ {\ifnum\c_page_sides_float_type>\plusfour
+ \appendtoks \zeropoint \scratchdimen \to \scratchtoks
\else
- \appendtoks \sidefloatwidth \scratchdimen \to \scratchtoks
+ \appendtoks \d_page_sides_width\scratchdimen \to \scratchtoks
\fi}%
\fi
- \advance\scratchcounter \plusone
- \parshape \scratchcounter \the\scratchtoks \zeropoint \hsize\relax
+ \parshape
+ \numexpr\scratchcounter+\plusone\relax
+ \the\scratchtoks % \scratchcounter
+ \zeropoint \hsize % \plusone
+ \relax
\else
% new till here
- \hangindent \ifnum\sidefloattype>\plusfour -\fi\sidefloatwidth
- \hangafter-\!!counta
+ \hangindent \ifnum\c_page_sides_float_type>\plusfour -\fi\d_page_sides_width
+ \hangafter-\c_page_sides_n_of_hang
\fi
\fi
- \global\advance\sidefloatparagraph \plusone
+ \global\advance\c_page_sides_checks_done \plusone
\iftracesidefloats
- \hskip-\sidefloatwidth
+ \hskip-\d_page_sides_width % kern
\color[darkgray]%
- {\vrule\!!height.5\points\!!depth.5\points\!!width\sidefloatwidth
- %\hskip-.25\bodyfontsize\showstruts\strut\hskip.25\bodyfontsize}%
- \llap{\showstruts\strut\hskip.25\bodyfontsize}}%
+ {\vrule\!!height.5\points\!!depth.5\points\!!width\d_page_sides_width
+ \llap{\showstruts\strut\kern.25\bodyfontsize}}%
\fi}
-\def\resetsidefloatparagraph
- {\global\sidefloatparagraph\zerocount}
-
-\def\dochecksidefloat
- {\progresssidefloat
- \ifdim\sidefloatprogress>\zeropoint
- \setsidefloatparagraph
- \else
- \resetsidefloatparagraph
- \fi
- \parskip\ctxparskip}
-
-\let\checksidefloat\dochecksidefloat
+\unexpanded\def\page_sides_check_floats_reset
+ {\global\c_page_sides_checks_done\zerocount}
-\def\synchronizesidefloats
- {\ifinner \else \checksidefloat \fi}
-
-\def\doadjustsidefloatdisplaylines
- {\par
- % not in mkiv: \vskip-\parskip
- \noindent
- \ignorespaces}
-
-\def\adjustsidefloatdisplaylines
- {\aftergroup\doadjustsidefloatdisplaylines}
+\unexpanded\def\page_sides_synchronize_floats
+ {\ifinner \else
+ \page_sides_check_floats
+ \fi}
-\def\previoussidefloat
- {\progresssidefloat
- \ifdim\sidefloatprogress>\zeropoint \relax
- \iffloatshort
- \global\floatshortfalse
- \vfill\eject % inline \tosssidefloat
+\unexpanded\def\page_sides_check_previous_float
+ {\page_sides_analyse_progress
+ \ifdim\d_page_sides_progress>\zeropoint \relax
+ \ifconditional\c_page_sides_short
+ \global\setfalse\c_page_sides_short
+ \page_otr_fill_and_eject_page
\else
- \kern\sidefloatprogress
+ \kern\d_page_sides_progress
\fi
\fi}
-\def\stallsidefloat
- {\!!counta\pageshrink
- \divide\!!counta \baselineskip
- \advance\!!counta \plusone
+\def\page_sides_inject_dummy_lines
+ {\scratchcounter\pageshrink
+ \divide\scratchcounter \baselineskip
+ \advance\scratchcounter \plusone
\parskip\zeropoint
- \dorecurse\!!counta{\line{}}%
- \kern-\!!counta\baselineskip
- \penalty\zerocount }
+ \dorecurse\scratchcounter{\hbox to \hsize{}}%
+ \kern-\scratchcounter\baselineskip
+ \penalty\zerocount}
-% We need to hook it into the other otr's. This code will move.
+% Display math
+%
+% If we need this, it will be redone but redefining
+% these macros does not really work out in the current
+% situation.
+%
+% \ifx\normalleqno\undefined
+%
+% \let\floatrighteqo=\eqno
+% \let\floatleftleqo=\leqno
+%
+% \else
+%
+% \let\floatrighteqo=\normaleqno
+% \let\floatleftleqo=\normalleqno
+%
+% \fi
+%
+% \ifx\normaleqno\undefined
+%
+% \def\normaleqno
+% {\ifconditional\c_page_sides_short
+% \global\settrue\c_page_sides_r_eq
+% \fi
+% \floatrighteqo}
+%
+% \else
+%
+% \def\eqno
+% {\ifconditional\c_page_sides_short
+% \global\settrue\c_page_sides_r_eq
+% \fi
+% \floatrighteqo}
+%
+% \fi
-\let\OTRONEflushsidefloats \flushsidefloats
-\let\OTRONEsynchronizesidefloats\synchronizesidefloats
+\def\adjustsidefloatdisplaylines % public, will change
+ {\aftergroup\page_sides_adjust_display_lines}
-% page-set
-%
-% \let\OTRSETflushsidefloats \forgetsidefloats
-% \let\OTRSETsynchronizesidefloats\forgetsidefloats
+\def\page_sides_adjust_display_lines
+ {\par
+ \noindent
+ \ignorespaces}
-% page-mul
-%
-% \let\OTRMULflushsidefloats \forgetsidefloats
-% \let\OTRMULsynchronizesidefloats\forgetsidefloats
+% We need to hook it into the other otr's. This code will be adapted
+% once we rename the callers.
+
+% \def as they can be redefined!
+
+% some will become obsolete
-\registerotrcommand\synchronizesidefloats % \def\synchronizesidefloats{\OTRcommand\synchronizesidefloats}
-\registerotrcommand\flushsidefloats % \def\flushsidefloats {\OTRcommand\flushsidefloats}
+\def\checksidefloat {\page_sides_check_floats}
+%def\flushsidefloats {\page_sides_flush_floats}
+\def\flushsidefloatsafterpar{\page_sides_flush_floats_after_par}
+%def\forgetsidefloats {\page_sides_forget_floats}
+%def\synchronizesidefloats {\page_sides_synchronize_floats}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-spr.mkii b/Master/texmf-dist/tex/context/base/page-spr.mkii
index 06947a36a09..65e435d7c2f 100644
--- a/Master/texmf-dist/tex/context/base/page-spr.mkii
+++ b/Master/texmf-dist/tex/context/base/page-spr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Spreading,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-spr.mkiv b/Master/texmf-dist/tex/context/base/page-spr.mkiv
index fd01e584ca6..f4768d4e95a 100644
--- a/Master/texmf-dist/tex/context/base/page-spr.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-spr.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Spreading,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -26,14 +26,14 @@
\def\normalsettextpagecontent#1#2#3% #2 and #3 will disappear
{\setbox#1\hbox
- {\setlayoutcomponentattribute\v!page\v!text
+ {\setlayoutcomponentattribute{\v!page:\v!text}%
\vbox \layoutcomponentboxattribute to \textheight
{\offinterlineskip
\freezetextwidth
\hsize\textwidth % local variant of \sethsize
\boxmaxdepth\maxdepth
\noindent % content can be < \hsize
- \dopagecontents#2#3}}%
+ \page_otr_command_package_contents#2#3}}%
\dp#1\zeropoint
\setbox#1\hbox to \makeupwidth
{\ifinspread
diff --git a/Master/texmf-dist/tex/context/base/page-str.lua b/Master/texmf-dist/tex/context/base/page-str.lua
index 7ce0f3c0fa6..48edd4cfe87 100644
--- a/Master/texmf-dist/tex/context/base/page-str.lua
+++ b/Master/texmf-dist/tex/context/base/page-str.lua
@@ -10,7 +10,7 @@ if not modules then modules = { } end modules ['page-str'] = {
-- work in progresss .. unfinished
-local concat = table.concat
+local concat, insert, remove = table.concat, table.insert, table.remove
local find_tail, write_node, free_node, copy_nodelist = node.slide, node.write, node.free, node.copy_list
local vpack_nodelist, hpack_nodelist = node.vpack, node.hpack
@@ -48,12 +48,12 @@ function streams.disable()
end
function streams.start(newname)
- table.insert(stack,name)
+ insert(stack,name)
name = newname
end
function streams.stop(newname)
- name = table.remove(stack)
+ name = remove(stack)
end
function streams.collect(head,where)
diff --git a/Master/texmf-dist/tex/context/base/page-str.mkii b/Master/texmf-dist/tex/context/base/page-str.mkii
index 71d76484e6e..df0cc5aa2fd 100644
--- a/Master/texmf-dist/tex/context/base/page-str.mkii
+++ b/Master/texmf-dist/tex/context/base/page-str.mkii
@@ -5,7 +5,7 @@
%D subtitle=Page Streams,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-str.mkiv b/Master/texmf-dist/tex/context/base/page-str.mkiv
index 8cce9945f26..f14f2f716b1 100644
--- a/Master/texmf-dist/tex/context/base/page-str.mkiv
+++ b/Master/texmf-dist/tex/context/base/page-str.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Page Streams,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -40,7 +40,7 @@
\newtoks \everyenableoutputstream
\appendtoks
- \flushsidefloats
+ \page_otr_command_flush_side_floats
\to \everyenableoutputstream
\def\initializeoutputstreams
diff --git a/Master/texmf-dist/tex/context/base/page-txt.mkii b/Master/texmf-dist/tex/context/base/page-txt.mkii
index 9fe73bec199..dd643b1b4e6 100644
--- a/Master/texmf-dist/tex/context/base/page-txt.mkii
+++ b/Master/texmf-dist/tex/context/base/page-txt.mkii
@@ -5,7 +5,7 @@
%D subtitle=Texts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/page-txt.mkiv b/Master/texmf-dist/tex/context/base/page-txt.mkiv
deleted file mode 100644
index dc516a94e33..00000000000
--- a/Master/texmf-dist/tex/context/base/page-txt.mkiv
+++ /dev/null
@@ -1,794 +0,0 @@
-%D \module
-%D [ file=page-txt, % copied from main-001,
-%D version=1997.03.31,
-%D title=\CONTEXT\ Page Macros,
-%D subtitle=Texts,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-% where we can do some mkiv cleanup
-
-% \setuplayouttext in manual
-
-\writestatus{loading}{ConTeXt Page Macros / Texts}
-
-\unprotect
-
-%D Interfacing between this and other modules is handled by
-%D the following macros. The current state of a text line
-%D (header, footer, etc.) is checked by:
-%D
-%D \starttyping
-%D \resetlayouttextlines
-%D \stoptyping
-%D
-%D The main text box is finished by the following macro:
-%D
-%D \starttyping
-%D \getmainbox <box> <\vbox|\unvbox>
-%D \stoptyping
-%D
-%D The text lines are collected with:
-%D
-%D \starttyping
-%D \gettextboxes
-%D \stoptyping
-%D
-%D It is possible to extens the default content of the text
-%D areas by appending content to the following token list
-%D registers:
-
-\newtoks\toptextcontent \newtoks\leftedgetextcontent
-\newtoks\headertextcontent \newtoks\leftmargintextcontent
-\newtoks\footertextcontent \newtoks\rightmargintextcontent
-\newtoks\bottomtextcontent \newtoks\rightedgetextcontent
-
-\newtoks\texttextcontent
-
-%D \macros
-%D {setuptop, setupheader, setuptext,
-%D setupfooter, setupbottom}
-%D
-%D The macros in this module sometimes look a bit more complicated
-%D than needed, which is a direct result of the fact that their
-%D ancestors are quite old and upward compatibility is a must.
-%D
-%D \showsetup{setuptop}
-%D \showsetup{setupheader}
-%D \showsetup{setuptext}
-%D \showsetup{setupfooter}
-%D \showsetup{setupbottom}
-
-\unexpanded\def\setuplayouttext
- {\dotripleempty\dosetuplayouttext}
-
-\def\dosetuplayouttext[#1][#2][#3]% beware, non global
- {\ifthirdargument
- \getparameters[\??tk#1#2][#3]%
- \else
- %\getparameters[\??tk#1\v!text][#2]%
- \edef\previoustextstate{\csname\??tk#1\c!state\endcsname}%
- \getparameters[\??tk#1][#2]%
- \edef\currenttextstate{\csname\??tk#1\c!state\endcsname}%
- \ifx\currenttextstate\previoustextstate
- % no change in state
- \else
- %\checkcurrentlayout % no
- % speed optimization (calculating backgrounds takes time)
- \doifcommon{\previoustextstate,\currenttextstate}{\v!high,\v!none}
- {\calculatevsizes
- \recalculatebackgrounds}%
- \fi
- \fi}
-
-\unexpanded\def\setuptop {\dotripleempty\dosetuplayouttext[\v!top]}
-\unexpanded\def\setupheader {\dotripleempty\dosetuplayouttext[\v!header]}
-\unexpanded\def\setuptext {\dotripleempty\dosetuplayouttext[\v!text]}
-\unexpanded\def\setupfooter {\dotripleempty\dosetuplayouttext[\v!footer]}
-\unexpanded\def\setupbottom {\dotripleempty\dosetuplayouttext[\v!bottom]}
-
-%D \macros
-%D {noheaderandfooterlines,notopandbottomlines}
-%D
-%D Although not really needed, the following shortcuts
-%D sometimes come in handy.
-%D
-%D \showsetup{noheaderandfooterlines}
-%D \showsetup{notopandbottomlines}
-
-\def\noheaderandfooterlines
- {\setupheader[\c!state=\v!empty]%
- \setupfooter[\c!state=\v!empty]}
-
-\def\notopandbottomlines
- {\setuptop [\c!state=\v!empty]%
- \setupbottom[\c!state=\v!empty]}
-
-%D \macros
-%D {setuptoptexts, setupheadertexts, setuptexttexts,
-%D setupfootertexts, setupbottomtexts}
-%D
-%D The next macros take one or more arguments. The exact setup
-%D depends on the number of arguments. Although not that
-%D intuitive, the current scheme evolved out of the original.
-%D When margin and edge texts as well as middle texts showed
-%D up, the current odd|/|even scheme surfaced.
-%D
-%D \showsetup{setuptoptexts}
-%D \showsetup{setupheadertexts}
-%D \showsetup{setuptexttexts}
-%D \showsetup{setupfootertexts}
-%D \showsetup{setupbottomtexts}
-
-\unexpanded\def\setuptoptexts {\dosixtupleempty\dosetuptexts[\v!top ]}
-\unexpanded\def\setupheadertexts {\dosixtupleempty\dosetuptexts[\v!header ]}
-\unexpanded\def\setuptexttexts {\dosixtupleempty\dosetuptexts[\v!text ]}
-\unexpanded\def\setupfootertexts {\dosixtupleempty\dosetuptexts[\v!footer ]}
-\unexpanded\def\setupbottomtexts {\dosixtupleempty\dosetuptexts[\v!bottom ]}
-
-%D The left, right and center variables can also be set
-%D directly using the previously discussed macros.
-
-\def\dosetuptexts[#1][#2][#3][#4][#5][#6]%
- {\ifsixthargument
- \setvalue{\??tk#1#2\c!lefttext}%
- {\dodoubletexts{#1}{#2}%
- {\c!leftstyle \c!leftcolor \c!leftwidth }{#3}%
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#6}}%
- \setvalue{\??tk#1#2\c!righttext}%
- {\dodoubletexts{#1}{#2}%
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}%
- {\c!leftstyle \c!leftcolor \c!leftwidth }{#5}}%
- \else\iffifthargument
- \setvalue{\??tk#1\v!text\c!lefttext}%
- {\dodoubletexts{#1}\v!text
- {\c!leftstyle \c!leftcolor \c!leftwidth }{#2}%
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#5}}%
- \setvalue{\??tk#1\v!text\c!righttext}%
- {\dodoubletexts{#1}\v!text
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}%
- {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}}%
- \else\iffourthargument
- \setvalue{\??tk#1#2\c!lefttext}%
- {\dodoubletexts{#1}{#2}
- {\c!leftstyle\c!leftcolor\c!leftwidth}{#3}%
- {\c!leftstyle\c!leftcolor\c!leftwidth}{#3}}%
- \setvalue{\??tk#1#2\c!righttext}%
- {\dodoubletexts{#1}{#2}
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}%
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}}%
- \else\ifthirdargument
- \setvalue{\??tk#1\v!text\c!lefttext}%
- {\dodoubletexts{#1}\v!text
- {\c!leftstyle\c!leftcolor\c!leftwidth}{#2}%
- {\c!leftstyle\c!leftcolor\c!leftwidth}{#2}}%
- \setvalue{\??tk#1\v!text\c!righttext}%
- {\dodoubletexts{#1}\v!text
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}%
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}}%
- \else\ifsecondargument % new
- \letvalueempty{\??tk#1\v!text\c!lefttext}%
- \letvalueempty{\??tk#1\v!text\c!righttext}%
- \setvalue{\??tk#1\v!text\c!middletext}{\dosingletexts{#1}\v!text\c!style\c!color\c!width{#2}}%
- \else
- \dosixtupleempty\dosetuptexts[#1][\v!text ][][][][]%
- \dosixtupleempty\dosetuptexts[#1][\v!margin][][][][]%
- \dosixtupleempty\dosetuptexts[#1][\v!edge ][][][][]%
- \fi\fi\fi\fi\fi}
-
-%D Left and right texts are swapped on odd and even pages, but
-%D only when double sided typesetting is enabled.
-
-\def\dodoubletexts{\doifoddpageelse\dodoubletextsodd\dodoubletextseven}
-
-\def\dodoubletextsodd #1#2#3#4#5#6{\dosingletexts{#1}{#2}#3{#4}} % #3 => provides three arguments
-\def\dodoubletextseven#1#2#3#4#5#6{\dosingletexts{#1}{#2}#5{#6}} % #5 => provides three arguments
-
-%D The next macro will be cleaned up and made less messy and
-%D dependent.
-
-\unexpanded\def\placetextlinestrut#1%
- {\doifvalue{#1\c!strut}\v!yes{\setstrut\strut}}
-
-\def\dosingletexts#1#2#3#4#5#6%
- {\bgroup
- \defconvertedargument\ascii{#6}% no longer \defconvertedargument, this also does not permit \v!pagenumber (i.e. v!)
- \ifx\ascii\empty\else
- \dostartattributes{\??tk#1#2}#3#4\empty
- \placetextlinestrut{\??tk#1}% here !
- \doifelsemarking\ascii
- {\dolimitatetexts{\??tk#1#2#5}{\getmarking[\ascii][\v!first]}}%
- {\ifcsname\??tk->\ascii\endcsname
- \csname\??tk->\ascii\endcsname
- \else
- % #6{}{}{} -> {} needed for macros that look
- % ahead, like \uniqueMPgraphic
- \ignorecrlf\dolimitatetexts{\??tk#1#2#5}{#6{}{}{}}%
- \fi}%
- \dostopattributes
- \fi
- \egroup}
-
-\setvalue{\??tk->\v!pagenumber}{\placelocationpagenumber}
-\setvalue{\??tk->\v!date }{\currentdate}
-
-%D When specified, the texts are automatically limited in
-%D length.
-
-\def\dolimitatetexts#1#2%
- {\doifelsevaluenothing{#1}{#2}{\limitatetext{#2}{\csname#1\endcsname}{\unknown}}}
-
-%D The placement of text is hooked into the token lists
-%D associated to the area at hand.
-
-\appendtoks \placelayouttextline\v!top \topheight \to \toptextcontent
-\appendtoks \placelayouttextline\v!header\headerheight \to \headertextcontent
-\appendtoks \placelayouttextline\v!text \textheight \to \texttextcontent
-\appendtoks \placelayouttextline\v!footer\footerheight \to \footertextcontent
-\appendtoks \placelayouttextline\v!bottom\bottomheight \to \bottomtextcontent
-
-%D Texts can be disabled, moved up and ignored, depending in
-%D the \type {status} variable. This is handled by the next
-%D couple of macros.
-
-% \def\settextlinestatus#1%
-% {\edef\textlinestatus{\csname\??tk#1\c!state\endcsname}}
-
-\def\settextlinestatus#1%
- {\ifcase0\csname\??tk#1\c!n\endcsname\relax
- \edef\textlinestatus{\csname\??tk#1\c!state\endcsname}%
- \else
- \setxvalue{\??tk#1\c!n}{\the\numexpr\csname\??tk#1\c!n\endcsname-1}%
- \let\textlinestatus\v!stop
- \fi}
-
-\appendtoks
- \doifinset\v!header\floatspecification{\setxvalue{\??tk\v!header\c!n}{1}}%
- \doifinset\v!footer\floatspecification{\setxvalue{\??tk\v!footer\c!n}{1}}%
-\to \everybeforeflushedpagefloat
-
-\def\resettextlinestatus#1% postpone
- {\expandafter\gdef\csname\??tk#1\s!reset\endcsname{\global\expandafter\let\csname\??tk#1\c!state\endcsname\v!normal}}
-
-\unexpanded\def\placelayouttextline#1% #2
- {\settextlinestatus#1%
- \csname\??tk::\ifcsname\??tk::\textlinestatus\endcsname\textlinestatus\else\s!unknown\fi\endcsname#1} % {#2}
-
-\def\doifelselayouttextline#1% shown or not
- {\edef\!!stringa{\csname\??tk#1\c!state\endcsname}%
- \ifx\!!stringa\v!normal
- \@EA\firstoftwoarguments
- \else\ifx\!!stringa\v!start
- \@EAEAEA\firstoftwoarguments
- \else
- \@EAEAEA\secondoftwoarguments
- \fi\fi}
-
-\def\doifelselayoutsomeline#1% present or not
- {\edef\!!stringa{\csname\??tk#1\c!state\endcsname}%
- \ifx\!!stringa\v!none
- \@EA\secondoftwoarguments
- \else\ifx\!!stringa\v!high
- \@EAEAEA\secondoftwoarguments
- \else
- \@EAEAEA\firstoftwoarguments
- \fi\fi}
-
-% \doplacelayouttextline does the actual placement (when a non-zero height)
-
-\newconditional\resyncaftertextline
-
-% there is no need for {#1} etc since we use symbolic names
-
-\setvalue{\??tk::\v!normal}{\doplacelayouttextline}
-\setvalue{\??tk::\empty }{\doplacelayouttextline}
-
-\setvalue{\??tk::\v!none }#1#2{}
-\setvalue{\??tk::\v!stop }#1#2{}
-
-\setvalue{\??tk::\v!high}#1#2%
- {\global\settrue\resyncaftertextline
- \resettextlinestatus#1}
-
-\setvalue{\??tk::\v!empty}#1#2%
- {\resettextlinestatus#1}
-
-\setvalue{\??tk::\v!start}#1#2%
- {\resettextlinestatus#1%
- \doplacelayouttextline#1#2}
-
-\setvalue{\??tk::\v!nomarking}#1#2%
- {\bgroup
- \resettextlinestatus#1%
- \settrue\inhibitgetmarking
- \let\dogetmarking\nogetmarking % obsolete in new marking mechanism
- \doplacelayouttextline#1#2%
- \egroup}
-
-\setvalue{\??tk::\s!unknown}#1#2%
- {\global\settrue\resyncaftertextline
- \bgroup % new
- \resettextlinestatus#1%
- \csname\??tk#1\textlinestatus\endcsname
- \csname\??tk#1\v!text \textlinestatus\endcsname
- \csname\??tk#1\v!margin\textlinestatus\endcsname
- \csname\??tk#1\v!edge \textlinestatus\endcsname
- \doplacelayouttextline#1#2%
- \egroup}
-
-%D The following macro has to be called after a page
-%D is flushed.
-
-\def\resetlayouttextline#1%
- {\csname\??tk#1\s!reset\endcsname
- \global\expandafter\let\csname\??tk#1\s!reset\endcsname\relax}
-
-\def\resetlayouttextlines
- {\resetlayouttextline\v!top
- \resetlayouttextline\v!header
- \resetlayouttextline\v!text
- \resetlayouttextline\v!footer
- \resetlayouttextline\v!bottom
- \ifconditional\resyncaftertextline
- \calculateglobalvsizes
- \recalculatebackgrounds
- \global\setfalse\resyncaftertextline
- \fi}
-
-% \settext[header][text][middle][xxx][yyy]
-
-\def\settextcontent
- {\doquintupleempty\dosettextcontent}
-
-\def\dosettextcontent[#1][#2][#3][#4][#5]% header text middle text/text
- {\iffifthargument
- \setvalue{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}%
- {\dodoubletexts{\??tk#1}{#2}%
- {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}%
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#5}}%
- \else\iffourthargument
- \setvalue{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}%
- {\dodoubletexts{\??tk#1}{#2}%
- {\c!leftstyle \c!leftcolor \c!leftwidth }{#4}%
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#4}}%
- \else\ifthirdargument
- \setvalue{\??tk#1#2\c!middletext}%
- {\dodoubletexts{\??tk#1}{#2}%
- {\c!leftstyle \c!leftcolor \c!leftwidth }{#3}%
- {\c!rightstyle\c!rightcolor\c!rightwidth}{#3}}%
- \fi\fi\fi}
-
-\def\resettextcontent
- {\dotripleempty\doresettextcontent}
-
-\def\doresettextcontent[#1][#2][#3]% header text middle
- {\ifthirdargument
- \letvalueempty{\??tk#1#2\executeifdefined{:\c!text:#3:}\c!middletext}%
- \else\ifsecondargument
- \letvalueempty{\??tk#1#2\c!lefttext}%
- \letvalueempty{\??tk#1#2\c!middletext}%
- \letvalueempty{\??tk#1#2\c!righttext}%
- \fi\fi}
-
-\let\settext \settextcontent % downward compatibility
-\let\resettext\resettextcontent % downward compatibility
-
-\letvalue{:\c!middle:\c!text:}\c!middletext
-\letvalue{:\c!left :\c!text:}\c!lefttext
-\letvalue{:\c!right :\c!text:}\c!righttext
-
-%D The next series of macros is not that easy to read,
-%D because they hook into the main page building macros. By
-%D using token list registers for the text content, we can
-%D easily hook in other code, like menu generators.
-%D
-%D Beware: the token lists are always expanded, also when the
-%D height of an area is zero. This is because reset actions can
-%D be part of them.
-
-\newbox\scratchpagebox
-
-% \newbox\collectedprepagecontent % only for delayed stuff
-
-% \def\flushcollectedpagecontent
-% {\ifvoid\collectedprepagecontent \else
-% \smashbox\collectedprepagecontent
-% \box\collectedprepagecontent
-% \fi}
-
-% \def\delaytillpageisflushhed#1%
-% {\global\setbox\collectedprepagecontent\hbox
-% {\ifvoid\collectedprepagecontent \else
-% \unhbox\collectedprepagecontent
-% \fi % ignore and remove not really needed
-% \ignorespaces#1\removeunwantedspaces}}
-
-\def\gettextboxes
- {\setbox\scratchpagebox\vbox
- {\dontcomplain
- \calculatereducedvsizes
- \swapmargins
- \offinterlineskip
-% \flushcollectedpagecontent
- \vskip\dimexpr-\topheight-\topdistance\relax
- \the\toptextcontent
- \vskip\dimexpr\topheight+\topdistance\relax
- \the\headertextcontent
- \vskip\dimexpr\headerheight+\headerdistance\relax
- \placepositionanchors
- \vskip-\textheight
- \the\texttextcontent
- \vskip\textheight
- \the\everyendoftextbody
- \vskip\footerdistance
- \the\footertextcontent
- \vskip\dimexpr\footerheight+\bottomdistance\relax
- \the\bottomtextcontent
- \vskip\bottomheight
- \vfilll}%
- \smashbox\scratchpagebox
- \box\scratchpagebox}
-
-\def\getmainbox#1#2%
- {\setbox\scratchpagebox\vbox
- {\offinterlineskip % na \paginaletter !
- \calculatereducedvsizes
- \calculatehsizes
- \swapmargins
- \vskip\dimexpr\headerheight+\headerdistance+\layoutparameter\c!textdistance\relax
- \hbox to \makeupwidth
- {\bgroup
- \swapmargins
- \goleftonpage
- \ifdim\leftedgewidth>\zeropoint
- \the\leftedgetextcontent
- \hskip\leftedgewidth
- \fi
- \hskip\leftedgedistance
- \ifdim\leftmarginwidth>\zeropoint
- \the\leftmargintextcontent
- \hskip\leftmarginwidth
- \fi
- \hskip\leftmargindistance
- \egroup
- \mkprocesspagecontents{#2}%
- \settextpagecontent\scratchpagebox{#1}{#2}%
- \addtextbackground\scratchpagebox
- \addtextgridlayer\scratchpagebox
- \box\scratchpagebox
- \bgroup
- \hskip\rightmargindistance
- \ifdim\rightmarginwidth>\zeropoint
- \the\rightmargintextcontent
- \hskip\rightmarginwidth
- \fi
- \hskip\rightedgedistance
- \ifdim\rightedgewidth>\zeropoint
- \the\rightedgetextcontent
- \hskip\rightedgewidth
- \fi
- \egroup
- \hss}}%
- \smashbox\scratchpagebox
- \box\scratchpagebox}
-
-%D The main text area has to be combined with some additional
-%D (tracing) information.
-
-% will be stored as normal and overloaded in page-lyr and later in
-% page-spr we overload the the stored version .. evenatually i will
-% clear up the experimental mess
-
-\def\settextpagecontent#1#2#3% #2 and #3 will disappear
- {\setbox#1\hbox to \makeupwidth
- {\hss % so don't change this
- \setlayoutcomponentattribute\v!page\v!text
- \vbox \layoutcomponentboxattribute to \textheight
- {\offinterlineskip
- \freezetextwidth
- \hsize\textwidth % local variant of \sethsize
- \boxmaxdepth\maxdepth
- \noindent % content can be < \hsize
- \dopagecontents#2#3}%
- \hss}%
- \dp#1\zeropoint}
-
-%D The placement of a whole line is handled by the next two
-%D macros. These are hooked into the general purpose token
-%D list registers mentioned before.
-
-\def\ignoredlinebreak{\unskip\space\ignorespaces}
-
-\def\doplacelayouttextline#1#2%
- {\let\currentlayouttextline#1%
- \ifdim#2>\zeropoint\relax % prevents pagenumbers when zero height
- \doplacelayouttextlineindeed{#2}%
- \fi}
-
-\def\doplacelayouttextlineindeed#1%
- {\goleftonpage
- \hbox
- {\setbox\scratchpagebox\vbox to #1
- {\vsize#1\relax
- \normalbaselines
- \let\\\ignoredlinebreak
- \let\crlf\ignoredlinebreak
- \csname\??tk\currentlayouttextline\c!before\endcsname
- \doifbothsidesoverruled\dodoplacelayouttextlineright\dodoplacelayouttextlineright\dodoplacelayouttextlineleft
- \csname\??tk\currentlayouttextline\c!after\endcsname
- \kern\zeropoint}% keep the \dp, beware of \vtops, never change this!
- \dp\scratchpagebox\zeropoint
- \box\scratchpagebox}%
- \vskip-#1\relax}
-
-\def\dodoplacelayouttextlineright{\dodoplacelayouttextline\c!lefttext \c!middletext\c!righttext\zerocount\plusone}
-\def\dodoplacelayouttextlineleft {\dodoplacelayouttextline\c!righttext\c!middletext\c!lefttext \plusone\zerocount}
-
-\def\dodoplacelayouttextline#1#2#3#4#5% \hsize toegevoegd, \hss's niet meer wijzigen
- {\hbox
- {\ifdim\leftedgewidth>\zeropoint
- \dododoplacelayouttextline\leftedgewidth\currentlayouttextline\v!edge{\thelayoutleftedgeline#1}%
- \hskip\leftedgedistance
- \fi
- \ifdim\leftmarginwidth>\zeropoint
- \dododoplacelayouttextline\leftmarginwidth\currentlayouttextline\v!margin{\thelayoutleftmarginline#1#4}%
- \hskip\leftmargindistance
- \fi
- \ifdim\makeupwidth>\zeropoint
- \dododoplacelayouttextline\makeupwidth\currentlayouttextline\v!text{\thelayouttextline#1#2#3#4#5}%
- \fi
- \ifdim\rightmarginwidth>\zeropoint
- \hskip\rightmargindistance
- \dododoplacelayouttextline\rightmarginwidth\currentlayouttextline\v!margin{\thelayoutrightmarginline#3#5}%
- \fi
- \ifdim\rightedgewidth>\zeropoint
- \hskip\rightedgedistance
- \dododoplacelayouttextline\rightedgewidth\currentlayouttextline\v!edge{\thelayoutrightedgeline#3}%
- \fi}}
-
-\def\thelayoutleftedgeline#1%
- {\hss\csname\??tk\currentlayouttextline\v!edge#1\endcsname}%
-
-\def\thelayoutrightedgeline#1%
- {\csname\??tk\currentlayouttextline\v!edge#1\endcsname\hss}
-
-\def\thelayoutleftmarginline#1#2%
- {\hbox to \leftmarginwidth{\hss\csname\??tk\currentlayouttextline\v!margin#1\endcsname}%
- \hskip-\leftmarginwidth
- \hbox to \leftmarginwidth{\hss\ifcase#2\or\csname\??tk\currentlayouttextline\v!margin\c!margintext\endcsname\fi}}
-
-\def\thelayoutrightmarginline#1#2%
- {\hbox to \rightmarginwidth{\csname\??tk\currentlayouttextline\v!margin#1\endcsname\hss}%
- \hskip-\rightmarginwidth
- \hbox to \rightmarginwidth{\ifcase#2\or\csname\??tk\currentlayouttextline\v!margin\c!margintext\endcsname\fi\hss}}
-
-\def\thelayoutedgetextline{\csname\??tk\currentlayouttextline\v!text\c!marginedgetext\endcsname}
-
-\def\thelayouttextline#1#2#3#4#5%
- {\hbox to \makeupwidth{\ifcase#4\or\@@nmpre\thelayoutedgetextline\fi\csname\??tk\currentlayouttextline\v!text#1\endcsname\hss}%
- \hskip-\makeupwidth
- \hbox to \makeupwidth{\hss\csname\??tk\currentlayouttextline\v!text#2\endcsname\hss}%
- \hskip-\makeupwidth
- \hbox to \makeupwidth{\hss\csname\??tk\currentlayouttextline\v!text#3\endcsname\ifcase#5\or\@@nmpos\thelayoutedgetextline\fi}}
-
-\def\dododoplacelayouttextline#1#2#3#4%
- {\vbox % to \vsize
- {\hsize#1\relax
- \csname\??tk#2#3\c!before\endcsname
- \setlayoutcomponentattribute#2#3%
- \hbox \layoutcomponentboxattribute to #1{#4}%
- \csname\??tk#2#3\c!after\endcsname}}
-
-%D Although it is far better to use backgrounds for this
-%D purpose, one can add a rule in the following way. This
-%D method makes the rules disappear in case of an empty text
-%D line. Consider this a feature.
-%D
-%D \starttyping
-%D \setupheadertexts[left][right]
-%D
-%D \setupheader[text][after=\hrule,style=bold]
-%D
-%D \starttext
-%D \input tufte \page
-%D \setupheader[state=empty]
-%D \input tufte \page
-%D \stoptext
-%D \stoptyping
-
-%D The next twosome will be done differently (using an
-%D existing auxiliary macro).
-
-% \def\@@nmpre#1{\setbox0\hbox{#1}\ifdim\wd0=\zeropoint\else\unhbox0\tfskip\fi}
-% \def\@@nmpos#1{\setbox0\hbox{#1}\ifdim\wd0=\zeropoint\else\tfskip\unhbox0\fi}
-
-% cleaner
-%
-% \def\@@nmpre#1{\doiftext{#1}{{#1}\tfskip}}
-% \def\@@nmpos#1{\doiftext{#1}{\tfskip{#1}}}
-%
-% newer
-%
-% \def\@@nmprepos#1#2#3#4#5%
-% {\doifelsenothing\@@nmwidth
-% {\doiftext{#5}{#1{#5}#2}}
-% {\doiftext{#5}{\hbox to \@@nmwidth{#3{#5}#4}}}}
-%
-% \def\@@nmpre{\@@nmprepos\empty\tfskip\relax\hss}
-% \def\@@nmpos{\@@nmprepos\tfskip\empty\hss\relax}
-%
-% faster
-
-\def\@@nmpre#1%
- {\begingroup
- \setbox\scratchbox\normalhbox{\settrialtypesetting\ignorespaces#1\removeunwantedspaces}%
- \ifzeropt\wd\scratchbox\else
- \doifelsenothing\@@nmwidth
- {\box\scratchbox\tfskip}
- {\hbox to \@@nmwidth{\box\scratchbox\hss}}%
- \fi
- \endgroup}
-
-\def\@@nmpos#1%
- {\begingroup
- \setbox\scratchbox\normalhbox{\settrialtypesetting\ignorespaces#1\removeunwantedspaces}%
- \ifzeropt\wd\scratchbox\else
- \doifelsenothing\@@nmwidth
- {\tfskip\box\scratchbox}
- {\hbox to \@@nmwidth{\hss\box\scratchbox}}%
- \fi
- \endgroup}
-
-%D This code will move to \type {page-flt.tex}.
-
-\appendtoks \placerightmarginblock \hskip-\rightmarginwidth \to \rightmargintextcontent
-\appendtoks \placeleftmarginblock \hskip-\leftmarginwidth \to \leftmargintextcontent
-
-%D The next hook will later be used for keeping track of
-%D positions, i.e.\ it will provide a proper (page
-%D dependent) reference point.
-
-\ifx\undefined\placepositionanchors
- \unexpanded\def\placepositionanchors{\vskip\textheight}
-\fi
-
-%D \macros
-%D {definetext}
-%D
-%D Some macros ago, we implemented the \type {status} option
-%D \type {unknown}. This one is used to take care of
-%D symbolic texts handlers.
-%D
-%D \showsetup{definetext}
-%D
-%D The next example demonstrates how we can use this
-%D mechanism to provide page (event) dependent text lines.
-%D
-%D \starttyping
-%D \definetext[chapter][footer][pagenumber]
-%D \setuphead[chapter][header=high,footer=chapter]
-%D \setupheadertexts[pagenumber]
-%D \setupfootertexts[left][right]
-%D \chapter{eerste} \dorecurse{20}{\input tufte \relax}
-%D \chapter{tweede} \dorecurse{20}{\input tufte \relax}
-%D \stoptyping
-
-\unexpanded\def\definetext
- {\doseventupleempty\dodefinetext}
-
-\def\dodefinetext[#1][#2][#3][#4][#5][#6][#7]%
- {\ifseventhargument
- \setvalue{\??tk#2#3#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5][#6][#7]}%
- \else\ifsixthargument
- \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5][#6]}%
- \else\iffifthargument
- \setvalue{\??tk#2#3#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4][#5]}%
- \else\iffourthargument
- \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3][#4]}%
- \else
- \setvalue{\??tk #2#1}{\dosixtupleempty\dosetuptexts[#2][#3]}%
- \fi\fi\fi\fi}
-
-%D The rest of this file is dedicated to setting up the
-%D texts. This code is not that impressive.
-
-\setupheadertexts [\v!text] [] []
-\setupheadertexts [\v!margin] [] []
-\setupheadertexts [\v!edge] [] []
-
-\setupfootertexts [\v!text] [] []
-\setupfootertexts [\v!margin] [] []
-\setupfootertexts [\v!edge] [] []
-
-\setuptexttexts [\v!text] [] []
-\setuptexttexts [\v!margin] [] []
-\setuptexttexts [\v!edge] [] []
-
-\setupbottomtexts [\v!text] [] []
-\setupbottomtexts [\v!margin] [] []
-\setupbottomtexts [\v!edge] [] []
-
-\setuptoptexts [\v!text] [] []
-\setuptoptexts [\v!margin] [] []
-\setuptoptexts [\v!edge] [] []
-
-% alternative
-%
-% \def\resetlayouttekst%
-% {\dodoubleempty\doresetlayouttekst}
-%
-% \def\doresetlayouttekst[#1][#2]%
-% {\ifsecondargument
-% \dodoresetlayouttekst[#1][#2]%
-% \else
-% \dodoresetlayouttekst[#1][\v!tekst]%
-% \fi}
-%
-% \def\dodoresetlayouttekst[#1][#2]%
-% {...}
-%
-% \def\docommand#1%
-% {\resetlayouttekst[#1][\v!tekst]%
-% \resetlayouttekst[#1][\v!marge]%
-% \resetlayouttekst[#1][\v!rand]}
-
-%D We combine a lot of similar settings in a macro that
-%D we will later dispose.
-
-\def\dodocommand[#1][#2]%
- {\getparameters
- [\??tk#1#2]
- [%\c!state=\v!normal, % moved
- \c!before=,% both global and local are used
- \c!after=,% both global and local are used
- \c!strut=,% the local one, not (yet) used
- \c!style=\csname\??tk#1\c!style\endcsname,% hm, got lost
- \c!color=\csname\??tk#1\c!color\endcsname,% hm, got lost
- \c!lefttext=,
- \c!middletext=,
- \c!righttext=,
- \c!marginedgetext=,
- \c!margintext=,
- \c!width=]%
- \inheritparameter[\??tk#1#2][\c!leftstyle ][\c!style ]%
- \inheritparameter[\??tk#1#2][\c!rightstyle][\c!style ]%
- \inheritparameter[\??tk#1#2][\c!leftcolor ][\c!color ]%
- \inheritparameter[\??tk#1#2][\c!rightcolor][\c!color ]%
- \inheritparameter[\??tk#1#2][\c!leftwidth ][\c!width]%
- \inheritparameter[\??tk#1#2][\c!rightwidth][\c!width]}
-
-\def\docommand#1%
- {\dodocommand[#1][\v!text]%
- \dodocommand[#1][\v!margin]%
- \dodocommand[#1][\v!edge]}
-
-\docommand\v!top
-\docommand\v!header
-\docommand\v!footer
-\docommand\v!text
-\docommand\v!bottom
-
-\let\docommand \relax
-\let\dodocommand\relax
-
-%D While the header and footer lines are moved away from the
-%D main text, the top and bottom lines are centered.
-
-\setuptop [\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
-\setupheader[\c!state=\v!normal,\c!n=0,\c!before=, \c!after=\vss,\c!strut=\v!yes]
-\setuptext [\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
-\setupfooter[\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=, \c!strut=\v!yes]
-\setupbottom[\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
-
-\setuptop [\c!style=,\c!color=]
-\setupheader[\c!style=,\c!color=]
-\setuptext [\c!style=,\c!color=]
-\setupfooter[\c!style=,\c!color=]
-\setupbottom[\c!style=,\c!color=]
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/page-txt.mkvi b/Master/texmf-dist/tex/context/base/page-txt.mkvi
new file mode 100644
index 00000000000..c86597338ca
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-txt.mkvi
@@ -0,0 +1,885 @@
+% macros=mkvi
+
+%D \module
+%D [ file=page-txt, % copied from main-001,
+%D version=1997.03.31,
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Texts,
+%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 / Texts}
+
+\unprotect
+
+\newtoks\toptextcontent \newtoks\leftedgetextcontent
+\newtoks\headertextcontent \newtoks\leftmargintextcontent
+\newtoks\footertextcontent \newtoks\rightmargintextcontent
+\newtoks\bottomtextcontent \newtoks\rightedgetextcontent
+
+\newtoks\texttextcontent
+
+%D \macros
+%D {setuptop, setupheader, setuptext,
+%D setupfooter, setupbottom}
+%D
+%D The macros in this module sometimes look a bit more complicated
+%D than needed, which is a direct result of the fact that their
+%D ancestors are quite old and upward compatibility is a must.
+%D
+%D \showsetup{setuptop}
+%D \showsetup{setupheader}
+%D \showsetup{setuptext}
+%D \showsetup{setupfooter}
+%D \showsetup{setupbottom}
+
+\installcorenamespace{layouttexts}
+\installcorenamespace{layouttextsline}
+\installcorenamespace{layouttextsreset}
+\installcorenamespace{layouttextssynchronize}
+\installcorenamespace{layouttextstrut}
+\installcorenamespace{layouttextspecial}
+\installcorenamespace{layouttextcontent}
+
+\installcommandhandler \??layouttexts {layoutelement} \??layouttexts
+
+% \appendtoks
+% \resetlayoutelementparameter\c!lefttext % resolves better
+% \resetlayoutelementparameter\c!middletext
+% \resetlayoutelementparameter\c!righttext
+% \to \everydefinelayoutelement
+
+\definelayoutelement[\v!top ]
+\definelayoutelement[\v!header]
+\definelayoutelement[\v!text ]
+\definelayoutelement[\v!footer]
+\definelayoutelement[\v!bottom]
+
+\definelayoutelement[\v!top :\v!text] [\v!top ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!header:\v!text] [\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!text :\v!text] [\v!text ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!footer:\v!text] [\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!bottom:\v!text] [\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]
+
+\definelayoutelement[\v!top :\v!margin][\v!top ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!header:\v!margin][\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!text :\v!margin][\v!text ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!footer:\v!margin][\v!footer][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!bottom:\v!margin][\v!bottom][\c!lefttext=,\c!middletext=,\c!righttext=]
+
+\definelayoutelement[\v!top :\v!edge] [\v!top ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!header:\v!edge] [\v!header][\c!lefttext=,\c!middletext=,\c!righttext=]
+\definelayoutelement[\v!text :\v!edge] [\v!text ][\c!lefttext=,\c!middletext=,\c!righttext=]
+\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
+ \setuplayoutelement[#vertical:#horizontal][#settings]%
+ \else
+ \setuplayoutelement[#vertical][#horizontal]%
+ \fi}
+
+\appendtoks
+ \ifx\currentlayoutelement\empty\else
+ \page_layouts_synchronize_element\currentlayoutelement % brr, can be vertical:horizontal
+ \fi
+\to \everysetuplayoutelement
+
+\def\page_layouts_reset_element_status#vertical%
+ {\expandafter\normalgdef\csname\??layouttextsreset#vertical\endcsname{\page_layouts_set_element_status_normal#vertical}}
+
+\def\page_layouts_set_element_status_normal#vertical%
+ {\global\expandafter\let\csname\namedlayoutelementhash#vertical\c!state\endcsname\v!normal
+ \global\expandafter\let\csname\??layouttextsreset#vertical\endcsname\relax
+ \page_layouts_synchronize_element{#vertical}}
+
+\def\page_layouts_synchronize_element#vertical%
+ {\xdef\previoustextstate{\csname\??layouttextssynchronize#vertical\endcsname}% can be a let
+ \edef\currenttextstate {\namedlayoutelementparameter{#vertical}\c!state}%
+ %\writestatus{>>}{[#vertical:\currenttextstate/\previoustextstate]}%
+ \ifx\currenttextstate\previoustextstate \else
+ \page_layouts_synchronize_element_indeed{#vertical}%
+ \fi}
+
+\def\page_layouts_synchronize_element_indeed#vertical%
+ {\ifx\currenttextstate \v!high \calculatevsizes\page_backgrounds_recalculate \else
+ \ifx\previoustextstate\v!high \calculatevsizes\page_backgrounds_recalculate \else
+ \ifx\currenttextstate \v!none \calculatevsizes\page_backgrounds_recalculate \else
+ \ifx\previoustextstate\v!none \calculatevsizes\page_backgrounds_recalculate \fi\fi\fi\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]}
+
+%D We inherit some settings:
+
+\setuplayoutelement
+ [ \c!leftstyle=\layoutelementparameter\c!style,
+ \c!rightstyle=\layoutelementparameter\c!style,
+ \c!leftcolor=\layoutelementparameter\c!color,
+ \c!rightcolor=\layoutelementparameter\c!color,
+ \c!leftwidth=\layoutelementparameter\c!width,
+ \c!rightwidth=\layoutelementparameter\c!width]
+
+%D \macros
+%D {noheaderandfooterlines,notopandbottomlines}
+%D
+%D Although not really needed, the following shortcuts
+%D sometimes come in handy.
+%D
+%D \showsetup{noheaderandfooterlines}
+%D \showsetup{notopandbottomlines}
+
+\def\noheaderandfooterlines
+ {\setuplayoutelement[\v!header][\c!state=\v!empty]%
+ \setuplayoutelement[\v!footer][\c!state=\v!empty]}
+
+\def\notopandbottomlines
+ {\setuplayoutelement[\v!top ][\c!state=\v!empty]%
+ \setuplayoutelement[\v!bottom][\c!state=\v!empty]}
+
+%D \macros
+%D {setuptoptexts, setupheadertexts, setuptexttexts,
+%D setupfootertexts, setupbottomtexts}
+%D
+%D The next macros take one or more arguments. The exact setup
+%D depends on the number of arguments. Although not that
+%D intuitive, the current scheme evolved out of the original.
+%D When margin and edge texts as well as middle texts showed
+%D up, the current odd|/|even scheme surfaced.
+%D
+%D \showsetup{setuptoptexts}
+%D \showsetup{setupheadertexts}
+%D \showsetup{setuptexttexts}
+%D \showsetup{setupfootertexts}
+%D \showsetup{setupbottomtexts}
+
+\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 ]}
+
+% todo: \setuplayoutelementtext
+
+% An alternative approach is to have more variables but that does not
+% make the code less complex (probably more).
+
+\def\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c][#d]%
+ {\ifsixthargument
+ \edef\currentlayoutelement{#vertical:#horizontal}%
+ \setlayoutelementparameter\c!lefttext
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#a}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#d}}%
+ \setlayoutelementparameter\c!righttext
+ {\page_layouts_process_element_double
+ \c!rightstyle\c!rightcolor\c!rightwidth{#b}%
+ \c!leftstyle \c!leftcolor \c!leftwidth {#c}}%
+ \else\iffifthargument
+ \edef\currentlayoutelement{#vertical:\v!text}%
+ \setlayoutelementparameter\c!lefttext
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#horizontal}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#c}}%
+ \setlayoutelementparameter\c!righttext
+ {\page_layouts_process_element_double
+ \c!rightstyle\c!rightcolor\c!rightwidth{#a}%
+ \c!leftstyle \c!leftcolor \c!leftwidth {#b}}%
+ \else\iffourthargument
+ \edef\currentlayoutelement{#vertical:#horizontal}%
+ \doifelsenothing{\detokenize{#a}}
+ {\resetlayoutelementparameter\c!lefttext}
+ {\setlayoutelementparameter\c!lefttext
+ {\page_layouts_process_element_double
+ \c!leftstyle\c!leftcolor\c!leftwidth{#a}%
+ \c!leftstyle\c!leftcolor\c!leftwidth{#a}}}%
+ \doifelsenothing{\detokenize{#b}}
+ {\resetlayoutelementparameter\c!righttext}
+ {\setlayoutelementparameter\c!righttext
+ {\page_layouts_process_element_double
+ \c!rightstyle\c!rightcolor\c!rightwidth{#b}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#b}}}%
+ \else\ifthirdargument
+ \edef\currentlayoutelement{#vertical:\v!text}%
+ \doifelsenothing{\detokenize{#horizontal}}
+ {\resetlayoutelementparameter\c!lefttext}
+ {\setlayoutelementparameter\c!lefttext
+ {\page_layouts_process_element_double
+ \c!leftstyle\c!leftcolor\c!leftwidth{#horizontal}%
+ \c!leftstyle\c!leftcolor\c!leftwidth{#horizontal}}}%
+ \doifelsenothing{\detokenize{#a}}
+ {\resetlayoutelementparameter\c!righttext}
+ {\setlayoutelementparameter\c!righttext
+ {\page_layouts_process_element_double
+ \c!rightstyle\c!rightcolor\c!rightwidth{#a}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#a}}}%
+ \else\ifsecondargument
+ \edef\currentlayoutelement{#vertical:\v!text}%
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!righttext
+ \doifelsenothing{\detokenize{#horizontal}}
+ {\resetlayoutelementparameter\c!middletext}
+ {\setlayoutelementparameter\c!middletext
+ {\page_layouts_process_element_single\c!style\c!color\c!width{#horizontal}}}%
+ \else
+ \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
+ \fi\fi\fi\fi\fi}
+
+%D Left and right texts are swapped on odd and even pages, but
+%D only when double sided typesetting is enabled.
+
+\unexpanded\def\page_layouts_process_element_double
+ {\doifoddpageelse
+ \page_layouts_process_element_double_odd
+ \page_layouts_process_element_double_even}
+
+\def\page_layouts_process_element_double_odd #lstyle#lcolor#lwidth#lcontent#rstyle#rcolor#rwidth#rcontent%
+ {\page_layouts_process_element_single#lstyle#lcolor#lwidth{#lcontent}}
+
+\def\page_layouts_process_element_double_even#lstyle#color#lwidth#lcontent#rstyle#rcolor#rwidth#rcontent%
+ {\page_layouts_process_element_single#rstyle#rcolor#rwidth{#rcontent}}
+
+%D The next macro will be cleaned up and made less messy and
+%D dependent.
+
+\let\m_page_layouts_element_content\empty
+
+\unexpanded\def\page_layouts_process_element_single#style#color#width#content%
+ {\edef\m_page_layouts_element_content{\detokenize{#content}}%
+ \ifx\m_page_layouts_element_content\empty
+ % should not happen too often
+ \else
+ \page_layouts_process_element_single_indeed#style#color#width{#content}%
+ \fi}
+
+\setvalue{\??layouttextstrut\v!yes}{\setstrut\strut} % maybe more variants
+
+\def\page_layouts_process_element_single_indeed#style#color#width#content%
+ {\begingroup
+ \uselayoutelementstyleandcolor#style#color%
+ \csname\??layouttextstrut\layoutelementparameter\c!strut\endcsname
+ \ifcsname\??layouttextspecial\m_page_layouts_element_content\endcsname
+ \csname\??layouttextspecial\m_page_layouts_element_content\endcsname
+ \else
+ \edef\currentlayoutelementwidth{\layoutelementparameter#width}%
+ \ifx\currentlayoutelementwidth\empty
+ \expandafter\page_layouts_process_element_single_normal
+ \else
+ \expandafter\page_layouts_process_element_single_limited
+ \fi{#content}%
+ \fi
+ \endgroup}
+
+% {}{}{} prevents lookahead issues ... this will go away
+
+\def\page_layouts_process_element_single_normal#content%
+ {\doifelsemarking\m_page_layouts_element_content
+ {\getmarking[\m_page_layouts_element_content][\v!first]}
+ {\ignorecrlf#content{}{}{}}}
+
+\def\page_layouts_process_element_single_limited#content%
+ {\doifelsemarking\m_page_layouts_element_content
+ {\limitatetext{\getmarking[\m_page_layouts_element_content][\v!first]}\currentlayoutelementwidth\unknown}
+ {\ignorecrlf\limitatetext{#content{}{}{}}\currentlayoutelementwidth\unknown}}
+
+\setvalue{\??layouttextspecial\v!pagenumber}{\page_layouts_place_page_number}
+\setvalue{\??layouttextspecial\v!date }{\currentdate}
+
+%D When specified, the texts are automatically limited in
+%D length.
+
+% % where used ?
+%
+% \def\page_layouts_limitate_element_text#width%
+% {\edef\currentlayoutelementwidth{\layoutelementparameter#width}%
+% \ifx\currentlayoutelementwidth\empty
+% \expandafter\firstofoneargument
+% \else
+% \expandafter\page_layouts_limitate_element_text_indeed
+% \fi}
+%
+% \def\page_layouts_limitate_element_text_indeed#content%
+% {\limitatetext{#content}\currentlayoutelementwidth\unknown}
+
+%D The placement of text is hooked into the token lists
+%D associated to the area at hand.
+
+\appendtoks \page_layouts_place_text_line\v!top \topheight \to \toptextcontent
+\appendtoks \page_layouts_place_text_line\v!header\headerheight \to \headertextcontent
+\appendtoks \page_layouts_place_text_line\v!text \textheight \to \texttextcontent
+\appendtoks \page_layouts_place_text_line\v!footer\footerheight \to \footertextcontent
+\appendtoks \page_layouts_place_text_line\v!bottom\bottomheight \to \bottomtextcontent
+
+%D Texts can be disabled, moved up and ignored, depending in
+%D the \type {status} variable. This is handled by the next
+%D couple of macros.
+
+\newcount\c_page_layouts_element_state_n
+
+\def\page_layouts_set_element_status#vertical%
+ {\c_page_layouts_element_state_n=0\namedlayoutelementparameter#vertical\c!n\relax
+ \ifcase\c_page_layouts_element_state_n
+ \edef\textlinestatus{\namedlayoutelementparameter#vertical\c!state}%
+ \else
+ \setxvalue{\namedlayoutelementhash#vertical\c!n}{\the\numexpr\c_page_layouts_element_state_n+\minusone}%
+ \let\textlinestatus\v!stop
+ \fi}
+
+\appendtoks
+ \doifinset\v!header\floatspecification{\setxvalue{\namedlayoutelementhash\v!header\c!n}{1}}%
+ \doifinset\v!footer\floatspecification{\setxvalue{\namedlayoutelementhash\v!footer\c!n}{1}}%
+\to \everybeforeflushedpagefloat
+
+\unexpanded\def\page_layouts_place_text_line#vertical%
+ {\page_layouts_set_element_status#vertical%
+ \csname\??layouttextsline\ifcsname\??layouttextsline\textlinestatus\endcsname\textlinestatus\else\s!unknown\fi\endcsname#vertical}
+
+\unexpanded\def\doifelselayouttextline#vertical% shown or not
+ {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
+ \ifx\currentlayoutelementstate\v!normal
+ \expandafter\firstoftwoarguments
+ \else\ifx\currentlayoutelementstate\v!start
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\secondoftwoarguments
+ \fi\fi}
+
+\unexpanded\def\doifelselayoutsomeline#vertical% present or not
+ {\edef\currentlayoutelementstate{\namedlayoutelementparameter{#vertical}\c!state}%
+ \ifx\currentlayoutelementstate\v!none
+ \expandafter\secondoftwoarguments
+ \else\ifx\currentlayoutelementstate\v!high
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi\fi}
+
+\newconditional\resyncaftertextline
+
+\setvalue{\??layouttextsline\v!normal}{\page_layouts_place_text_line_indeed}
+\setvalue{\??layouttextsline\empty }{\page_layouts_place_text_line_indeed}
+
+\letvalue{\??layouttextsline\v!none}\gobbletwoarguments
+\letvalue{\??layouttextsline\v!stop}\gobbletwoarguments
+
+\setvalue{\??layouttextsline\v!high}#vertical#height%
+ {\global\settrue\resyncaftertextline
+ \page_layouts_reset_element_status#vertical}
+
+\setvalue{\??layouttextsline\v!empty}#vertical#height%
+ {\page_layouts_reset_element_status#vertical}
+
+\setvalue{\??layouttextsline\v!start}#vertical#height%
+ {\page_layouts_reset_element_status#vertical%
+ \page_layouts_place_text_line_indeed#vertical#height}
+
+\setvalue{\??layouttextsline\v!nomarking}#vertical#height%
+ {\bgroup
+ \page_layouts_reset_element_status#vertical%
+ \settrue\inhibitgetmarking
+ \page_layouts_place_text_line_indeed#vertical#height%
+ \egroup}
+
+\setvalue{\??layouttextsline\s!unknown}#vertical#height%
+ {\global\settrue\resyncaftertextline
+ \begingroup % new
+ \page_layouts_reset_element_status#vertical%
+ \csname\namedlayoutelementhash#vertical\textlinestatus\endcsname
+ \csname\namedlayoutelementhash#vertical\v!text \textlinestatus\endcsname
+ \csname\namedlayoutelementhash#vertical\v!margin\textlinestatus\endcsname
+ \csname\namedlayoutelementhash#vertical\v!edge \textlinestatus\endcsname
+ \page_layouts_place_text_line_indeed#vertical#height%
+ \endgroup}
+
+%D The following macro has to be called after a page
+%D is flushed.
+
+\def\resetlayouttextlines % public
+ {\csname\??layouttextsreset\v!top \endcsname
+ \csname\??layouttextsreset\v!header\endcsname
+ \csname\??layouttextsreset\v!text \endcsname
+ \csname\??layouttextsreset\v!footer\endcsname
+ \csname\??layouttextsreset\v!bottom\endcsname
+ \ifconditional\resyncaftertextline
+ \calculateglobalvsizes
+ \page_backgrounds_recalculate
+ \global\setfalse\resyncaftertextline
+ \fi}
+
+% \settext[header][text][middle][xxx][yyy]
+
+\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}\executeifdefined{\??layouttextcontent\c!text:#one}\c!middletext}%
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#two}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#three}}%
+ \else\iffourthargument
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\executeifdefined{\??layouttextcontent\c!text:#one}\c!middletext}%
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#two}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#two}}%
+ \else\ifthirdargument
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}\c!middletext}%
+ {\page_layouts_process_element_double
+ \c!leftstyle \c!leftcolor \c!leftwidth {#one}%
+ \c!rightstyle\c!rightcolor\c!rightwidth{#one}}%
+ \fi\fi\fi}
+
+\def\resettextcontent
+ {\dotripleempty\page_layouts_reset_text_content}
+
+\def\page_layouts_reset_text_content[#vertical][#horizontal][#tag]% header text middle
+ {\edef\currentlayoutelement{#vertical:#horizontal}%
+ \ifthirdargument
+ \letvalueempty{\layoutelementhash\executeifdefined{\??layouttextcontent\c!text:#tag}\c!middletext}%
+ \else\ifsecondargument
+ \resetlayoutelementparameter\c!lefttext
+ \resetlayoutelementparameter\c!middletext
+ \resetlayoutelementparameter\c!righttext
+ \fi\fi}
+
+\letvalue{\??layouttextcontent\c!middle:\c!text}\c!middletext
+\letvalue{\??layouttextcontent\c!left :\c!text}\c!lefttext
+\letvalue{\??layouttextcontent\c!right :\c!text}\c!righttext
+
+%D The placement of a whole line is handled by the next two
+%D macros. These are hooked into the general purpose token
+%D list registers mentioned before.
+
+\def\ignoredlinebreak{\unskip\space\ignorespaces}
+
+\def\page_layouts_place_text_line_indeed#vertical#height%
+ {\let\currentlayouttextline#vertical%
+ \ifdim#height>\zeropoint\relax % prevents pagenumbers when zero height
+ \page_layouts_place_text_line_left_or_right{#height}%
+ \fi}
+
+\def\page_layouts_place_text_line_left_or_right#height%
+ {\goleftonpage
+ \setbox\b_page_layouts_element\vbox to #height
+ {\vsize#height\relax
+ %\hsize\zeropoint % hack so that e.g. after=\hairline gives predictable results
+ \hsize\totaltextwidth
+ \normalbaselines
+ \let\\\ignoredlinebreak
+ \let\crlf\ignoredlinebreak
+ \namedlayoutelementparameter\currentlayouttextline\c!before
+ \doifbothsidesoverruled
+ \page_layouts_place_text_line_right
+ \page_layouts_place_text_line_right
+ \page_layouts_place_text_line_left
+ \namedlayoutelementparameter\currentlayouttextline\c!after
+ \kern\zeropoint}% keep the \dp, beware of \vtops, never change this!
+ \dp\b_page_layouts_element\zeropoint
+ \box\b_page_layouts_element
+ \vskip-#height\relax}
+
+\let\page_layouts_extra_at_margin_left \plusone
+\let\page_layouts_extra_at_margin_right\plustwo
+
+\let\page_layouts_place_extra_text_left \relax % historic
+\let\page_layouts_place_extra_text_right\relax % historic
+
+\def\page_layouts_place_text_line_right
+ {\hbox
+ {\ifdim\leftedgewidth>\zeropoint
+ \page_layouts_left_edge_element\c!lefttext
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ %\page_layouts_left_margin_element\c!lefttext\page_layouts_extra_at_margin_left
+ \page_layouts_left_margin_element\c!lefttext\page_layouts_extra_at_margin_right
+ \fi
+ \ifdim\makeupwidth>\zeropoint
+ \page_layouts_text_body_element\c!lefttext\c!middletext\c!righttext\page_layouts_extra_at_margin_left
+ \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ %\page_layouts_right_margin_element\c!righttext\page_layouts_extra_at_margin_left
+ \page_layouts_right_margin_element\c!righttext\page_layouts_extra_at_margin_right
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ %\page_layouts_right_edge_element\c!lefttext
+ \page_layouts_right_edge_element\c!righttext
+ \fi}}
+
+\def\page_layouts_place_text_line_left
+ {\hbox
+ {\ifdim\leftedgewidth>\zeropoint
+ \page_layouts_left_edge_element\c!righttext
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ %\page_layouts_left_margin_element\c!righttext\page_layouts_extra_at_margin_right
+ \page_layouts_left_margin_element\c!righttext\page_layouts_extra_at_margin_left
+ \fi
+ \ifdim\makeupwidth>\zeropoint
+ \page_layouts_text_body_element\c!righttext\c!middletext\c!lefttext\page_layouts_extra_at_margin_right
+ \fi
+ \ifdim\rightmarginwidth>\zeropoint
+ %\page_layouts_right_margin_element\c!lefttext\page_layouts_extra_at_margin_right
+ \page_layouts_right_margin_element\c!lefttext\page_layouts_extra_at_margin_left
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ %\page_layouts_right_edge_element\c!righttext
+ \page_layouts_right_edge_element\c!lefttext
+ \fi}}
+
+\def\page_layouts_left_edge_element#parameter%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}%
+ \page_layouts_place_element_indeed\leftedgewidth
+ {\hss\layoutelementparameter#parameter}%
+ \hskip\leftedgedistance}
+
+\def\page_layouts_left_margin_element#parameter#extrastate%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}%
+ \page_layouts_place_element_indeed\leftmarginwidth
+ {\hbox to \leftmarginwidth{\hss\layoutelementparameter#parameter}%
+ \ifnum#extrastate=\page_layouts_extra_at_margin_left
+ \hskip-\leftmarginwidth
+ \hbox to \leftmarginwidth{\hss\layoutelementparameter\c!margintext}%
+ \fi}%
+ \hskip\leftmargindistance}
+
+\def\page_layouts_text_body_element#left#middle#right#extrastate%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!text}%
+ \page_layouts_place_element_indeed\makeupwidth
+ {\hbox to \makeupwidth{\ifnum#extrastate=\page_layouts_extra_at_margin_left\page_layouts_place_extra_text_left\fi\layoutelementparameter#left\hss}%
+ \hskip-\makeupwidth
+ \hbox to \makeupwidth{\hss\layoutelementparameter#middle\hss}%
+ \hskip-\makeupwidth
+ \hbox to \makeupwidth{\hss\layoutelementparameter#right\ifnum#extrastate=\page_layouts_extra_at_margin_right\page_layouts_place_extra_text_right\fi}}}
+
+\def\page_layouts_right_margin_element#parameter#extrastate%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!margin}%
+ \hskip\rightmargindistance
+ \page_layouts_place_element_indeed\rightmarginwidth
+ {\hbox to \rightmarginwidth{\layoutelementparameter#parameter\hss}%
+ \ifnum#extrastate=\page_layouts_extra_at_margin_right
+ \hskip-\rightmarginwidth
+ \hbox to \rightmarginwidth{\layoutelementparameter\c!margintext\hss}%
+ \fi}}
+
+\def\page_layouts_right_edge_element#parameter%
+ {\edef\currentlayoutelement{\currentlayouttextline:\v!edge}%
+ \hskip\rightedgedistance
+ \page_layouts_place_element_indeed\rightedgewidth
+ {\layoutelementparameter#parameter\hss}}
+
+\def\page_layouts_place_element_indeed#width#content%
+ {\vbox % to \vsize
+ {\hsize#width\relax
+ \layoutelementparameter\c!before
+ \setlayoutcomponentattribute\currentlayoutelement
+ \hbox \layoutcomponentboxattribute to #width{#content}%
+ \layoutelementparameter\c!after}}
+
+%D Although it is far better to use backgrounds for this
+%D purpose, one can add a rule in the following way. This
+%D method makes the rules disappear in case of an empty text
+%D line. Consider this a feature.
+%D
+%D \starttyping
+%D \setupheadertexts[left][right]
+%D
+%D \setupheader[text][after=\hrule,style=bold]
+%D
+%D \starttext
+%D \input tufte \page
+%D \setupheader[state=empty]
+%D \input tufte \page
+%D \stoptext
+%D \stoptyping
+
+%D This code will move to \type {page-flt.tex}.
+
+\appendtoks \placerightmarginblock \hskip-\rightmarginwidth \to \rightmargintextcontent
+\appendtoks \placeleftmarginblock \hskip-\leftmarginwidth \to \leftmargintextcontent
+
+%D \macros
+%D {definetext}
+%D
+%D Some macros ago, we implemented the \type {status} option
+%D \type {unknown}. This one is used to take care of
+%D symbolic texts handlers.
+%D
+%D \showsetup{definetext}
+%D
+%D The next example demonstrates how we can use this
+%D mechanism to provide page (event) dependent text lines.
+%D
+%D \starttyping
+%D \definetext[chapter][footer][pagenumber]
+%D \setuphead[chapter][header=high,footer=chapter]
+%D \setupheadertexts[pagenumber]
+%D \setupfootertexts[left][right]
+%D \chapter{eerste} \dorecurse{20}{\input tufte \relax}
+%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}%
+ {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c][#d]}%
+ \else\ifsixthargument
+ \setvalue{\namedlayoutelementhash{#vertical}#tag}%
+ {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b][#c]}%
+ \else\iffifthargument
+ \setvalue{\namedlayoutelementhash{#vertical:#horizontal}#tag}%
+ {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a][#b]}%
+ \else\iffourthargument
+ \setvalue{\namedlayoutelementhash{#vertical}#tag}%
+ {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal][#a]}%
+ \else
+ \setvalue{\namedlayoutelementhash{#vertical}#tag}%
+ {\dosixtupleempty\page_layouts_setup_texts[#vertical][#horizontal]}%
+ \fi\fi\fi\fi}
+
+%D A few more page breakers:
+
+\installpagebreakmethod \v!empty
+ {\page_otr_flush_all_floats
+ \page_otr_command_next_page
+ \doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}%
+ \doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}%
+ \page_otr_insert_dummy_page}
+
+\installpagebreakmethod \v!header
+ {\doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}}
+
+\installpagebreakmethod \v!footer
+ {\doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}}
+
+%D While the header and footer lines are moved away from the
+%D main text, the top and bottom lines are centered.
+
+\setuplayoutelement[\v!top ][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+\setuplayoutelement[\v!header][\c!state=\v!normal,\c!n=0,\c!before=, \c!after=\vss,\c!strut=\v!yes]
+\setuplayoutelement[\v!text ][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+\setuplayoutelement[\v!footer][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=, \c!strut=\v!yes]
+\setuplayoutelement[\v!bottom][\c!state=\v!normal,\c!n=0,\c!before=\vss,\c!after=\vss,\c!strut=]
+
+%D Moved here from strc-pag:
+
+% We reset a previous location but only when it has a pagenumber
+% associated. This is a rather messy test but better than the MkII
+% way where we use states and keep settings.
+
+\let\m_page_layouts_page_number_location_ \relax
+\let\m_page_layouts_page_number_location__v\relax
+\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
+ {\placelocationpagenumber} % test below fails
+
+\def\page_layouts_reset_page_number_location
+ {\ifx\m_page_layouts_page_number_location__v\relax\else
+ \edef\currentlayoutelement{\m_page_layouts_page_number_location__v:\m_page_layouts_page_number_location__h}%
+ \edef\page_layouts_previous_page_number_locator{\detokenizedlayoutelementparameter\m_page_layouts_page_number_location__x}%
+ \doif{\meaning\page_layouts_previous_page_number_locator}{\meaning\page_layouts_place_page_number}
+ {\resetlayoutelementparameter\m_page_layouts_page_number_location__x}%
+ \fi}
+
+\def\page_layouts_set_page_number_location
+ {\edef\currentlayoutelement{\m_page_layouts_page_number_location__v:\m_page_layouts_page_number_location__h}%
+ \letlayoutelementparameter\m_page_layouts_page_number_location__x\page_layouts_place_page_number
+ \ifx\m_page_layouts_page_number_location__x\c!marginedgetext
+ \let\page_layouts_place_extra_text_left \page_layouts_place_page_number_left
+ \let\page_layouts_place_extra_text_right\page_layouts_place_page_number_right
+ \else
+ \let\page_layouts_place_extra_text_left \relax
+ \let\page_layouts_place_extra_text_right\relax
+ \fi}
+
+\def\page_layouts_identify_page_number_location
+ {\let\m_page_layouts_page_number_location__v\v!footer
+ \let\m_page_layouts_page_number_location__h\v!text
+ \let\m_page_layouts_page_number_location__x\c!middletext
+ \processallactionsinset[\@@nmlocation]
+ [ \v!header=>\let\m_page_layouts_page_number_location__v\v!header,
+ \v!footer=>\let\m_page_layouts_page_number_location__v\v!footer,
+ \v!middle=>\let\m_page_layouts_page_number_location__h\v!text
+ \let\m_page_layouts_page_number_location__x\c!middletext,
+ \v!left=>\let\m_page_layouts_page_number_location__h\v!text
+ \let\m_page_layouts_page_number_location__x\c!lefttext,
+ \v!right=>\let\m_page_layouts_page_number_location__h\v!text
+ \let\m_page_layouts_page_number_location__x\c!righttext,
+ \v!inleft=>\let\m_page_layouts_page_number_location__h\v!margin
+ \let\m_page_layouts_page_number_location__x\c!lefttext,
+ \v!inright=>\let\m_page_layouts_page_number_location__h\v!margin
+ \let\m_page_layouts_page_number_location__x\c!righttext,
+ \v!inmargin=>\let\m_page_layouts_page_number_location__h\v!margin
+ \def\m_page_layouts_page_number_location__x{\ifdoublesided\c!margintext\else\c!righttext\fi},
+ \v!margin=>\let\m_page_layouts_page_number_location__h\v!margin
+ \def\m_page_layouts_page_number_location__x{\ifdoublesided\c!margintext\else\c!righttext\fi},
+ \v!atmargin=>\let\m_page_layouts_page_number_location__h\v!text
+ \let\m_page_layouts_page_number_location__x\c!marginedgetext,
+ \v!marginedge=>\let\m_page_layouts_page_number_location__h\v!text
+ \let\m_page_layouts_page_number_location__x\c!marginedgetext]}
+
+\unexpanded\def\dosetpagenumberlocation
+ {\ifx\@@nmlocation\m_page_layouts_page_number_location_
+ % unchanged
+ \else
+ \let\m_page_layouts_page_number_location_\@@nmlocation
+ \page_layouts_reset_page_number_location
+ \ifx\@@nmlocation\empty
+ % set otherwise
+ \else
+ \page_layouts_identify_page_number_location
+ \page_layouts_set_page_number_location
+ \fi
+ \fi}
+
+\def\page_layouts_place_page_number_left % historic
+ {\begingroup
+ \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox\else
+ \doifelsenothing\@@nmwidth
+ {\box\scratchbox\tfskip}
+ {\hbox to \@@nmwidth{\box\scratchbox\hss}}%
+ \fi
+ \endgroup}
+
+\def\page_layouts_place_page_number_right % historic
+ {\begingroup
+ \setbox\scratchbox\hbox{\ignorespaces\layoutelementparameter\c!marginedgetext\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox\else
+ \doifelsenothing\@@nmwidth
+ {\tfskip\box\scratchbox}
+ {\hbox to \@@nmwidth{\hss\box\scratchbox}}%
+ \fi
+ \endgroup}
+
+\dosetpagenumberlocation
+
+% will go to page-box.mkiv
+
+% the next macros will be redone (less boxing)
+
+\newbox\b_page_layouts_element
+
+\def\page_layouts_insert_elements
+ {\ifcase\pageornamentstate
+ \page_layouts_place_elements_indeed
+ \fi}
+
+\def\page_layouts_place_elements_indeed
+ {\setbox\b_page_layouts_element\vbox
+ {\dontcomplain
+ \calculatereducedvsizes
+ \swapmargins
+ \offinterlineskip
+ \vskip\dimexpr-\topheight-\topdistance\relax
+ \the\toptextcontent
+ \vskip\dimexpr\topheight+\topdistance\relax
+ \the\headertextcontent
+ \vskip\dimexpr\headerheight+\headerdistance\relax
+ \anch_positions_place_anchors
+ \vskip-\textheight
+ \the\texttextcontent
+ \vskip\textheight
+ \the\everyendoftextbody
+ \vskip\footerdistance
+ \the\footertextcontent
+ \vskip\dimexpr\footerheight+\bottomdistance\relax
+ \the\bottomtextcontent
+ \vskip\bottomheight
+ \vfilll}%
+ \smashbox\b_page_layouts_element
+ \box\b_page_layouts_element}
+
+\def\page_insert_body#1#2%
+ {\setbox\b_page_layouts_element\vbox
+ {\offinterlineskip
+ \calculatereducedvsizes
+ \calculatehsizes
+ \swapmargins
+ \vskip\dimexpr\headerheight+\headerdistance+\layoutparameter\c!textdistance\relax
+ \dontleavehmode
+ \hbox to \makeupwidth
+ {\begingroup
+ \swapmargins
+ \goleftonpage
+ \ifdim\leftedgewidth>\zeropoint
+ \the\leftedgetextcontent
+ \kern\dimexpr\leftedgewidth+\leftedgedistance\relax
+ \fi
+ \ifdim\leftmarginwidth>\zeropoint
+ \the\leftmargintextcontent
+ \kern\dimexpr\leftmarginwidth+\leftmargindistance\relax
+ \fi
+ \endgroup
+ \mkprocesspagecontents{#2}%
+ \settextpagecontent\b_page_layouts_element{#1}{#2}%
+ \page_backgrounds_add_to_text\b_page_layouts_element
+ \page_grids_add_to_box\b_page_layouts_element
+ \box\b_page_layouts_element
+ \begingroup
+ \ifdim\rightmarginwidth>\zeropoint
+ \kern\rightmargindistance
+ \the\rightmargintextcontent
+ \kern\rightmarginwidth
+ \fi
+ \ifdim\rightedgewidth>\zeropoint
+ \kern\rightedgedistance
+ \the\rightedgetextcontent
+ \kern\rightedgewidth
+ \fi
+ \endgroup
+ \hss}}%
+ \smashbox\b_page_layouts_element
+ \box\b_page_layouts_element}
+
+%D The main text area has to be combined with some additional
+%D (tracing) information.
+
+% will be stored as normal and overloaded in page-lyr and later in
+% page-spr we overload the the stored version .. evenatually i will
+% clear up the experimental mess
+
+\def\settextpagecontent#1#2#3% #2 and #3 will disappear
+ {\setbox#1\hbox to \makeupwidth
+ {\hss % so don't change this
+ \setlayoutcomponentattribute{\v!page:\v!text}%
+ \vbox \layoutcomponentboxattribute to \textheight
+ {\offinterlineskip
+ \freezetextwidth
+ \hsize\textwidth % local variant of \sethsize <<< in columns?
+ \boxmaxdepth\maxdepth
+ \noindent % content can be < \hsize
+ \dopagecontents#2#3}%
+ \hss}%
+ \dp#1\zeropoint}
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/page-var.mkiv b/Master/texmf-dist/tex/context/base/page-var.mkiv
new file mode 100644
index 00000000000..1c7fd5b252d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/page-var.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=page-var,
+%D version=2011.12.05, % moved from other page-* files
+%D title=\CONTEXT\ Page Macros,
+%D subtitle=Variables,
+%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 / Variables}
+
+\unprotect
+
+% just for temporary moved variables
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/pdfr-ec.mkii b/Master/texmf-dist/tex/context/base/pdfr-ec.mkii
index b6604984cf8..e2208aa3657 100644
--- a/Master/texmf-dist/tex/context/base/pdfr-ec.mkii
+++ b/Master/texmf-dist/tex/context/base/pdfr-ec.mkii
@@ -5,7 +5,7 @@
%D subtitle=EC encoding,
%D author={Vladimir Volovich / Taco Hoekwater},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/pdfr-il2.mkii b/Master/texmf-dist/tex/context/base/pdfr-il2.mkii
index 70bcb25da38..81f9c42acca 100644
--- a/Master/texmf-dist/tex/context/base/pdfr-il2.mkii
+++ b/Master/texmf-dist/tex/context/base/pdfr-il2.mkii
@@ -5,7 +5,7 @@
%D subtitle=ISO Latin 2,
%D author={Ondrej Koala Vacha, Hans Hagen},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/phys-dim.lua b/Master/texmf-dist/tex/context/base/phys-dim.lua
new file mode 100644
index 00000000000..c47821b1c3e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/phys-dim.lua
@@ -0,0 +1,878 @@
+if not modules then modules = { } end modules ['phys-dim'] = {
+ version = 1.001,
+ comment = "companion to phys-dim.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This is pretty old code that I found back, but let's give it a try
+-- in practice. It started out as m-units.lua but as we want to keep that
+-- module around we moved the code to the dimensions module.
+--
+-- todo: maybe also an sciunit command that converts to si units (1 inch -> 0.0254 m)
+-- etc .. typical something to do when listening to a news whow or b-movie
+--
+-- todo: collect used units for logging (and list of units, but then we need
+-- associations too).
+
+-- The lists have been checked and completed by Robin Kirkham.
+
+-- dubious/wrong
+
+-- Atom = [[u]], -- should be amu (atomic mass unit)
+-- Bell = [[B]], -- should be bel
+-- Sterant = [[sr]], -- should be steradian
+-- Equivalent = [[eql]], -- qualifier?
+-- At = [[at]], -- qualifier?
+-- Force = [[f]], -- qualifier?
+-- eVolt = [[eV]],
+-- -- AC or DC voltages should be qualified in the text
+-- VoltAC = [[V\unitsbackspace\unitslower{ac}]],
+-- VoltDC = [[V\unitsbackspace\unitslower{dc}]],
+-- AC = [[V\unitsbackspace\unitslower{ac}]],
+-- DC = [[V\unitsbackspace\unitslower{dc}]],
+-- -- probably not harmful but there are better alternatives
+-- -- e.g., revolution per second (rev/s)
+-- RPS = [[RPS]],
+-- RPM = [[RPM]],
+-- RevPerSec = [[RPS]],
+-- RevPerMin = [[RPM]],
+
+local V, P, S, R, C, Cc, Cs, matchlpeg = lpeg.V, lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.match
+local format, lower = string.format, string.lower
+local appendlpeg = lpeg.append
+local mergetable, mergedtable, keys, loweredkeys = table.merge, table.merged, table.keys, table.loweredkeys
+local setmetatablenewindex = table.setmetatablenewindex
+local utfchar = utf.char
+
+physics = physics or { }
+physics.units = physics.units or { }
+
+local variables = interfaces.variables
+local v_reverse = variables.reverse
+local allocate = utilities.storage.allocate
+
+local trace_units = false
+local report_units = logs.reporter("units")
+
+trackers.register("physics.units", function(v) trace_units = v end)
+
+-- digits parser (todo : use patterns)
+
+local math_one = Cs((P("$") /"") * (1-P("$"))^1 * (P("$")/"")) / context.m
+local math_two = Cs((P("\\m {")/"") * (1-P("}"))^1 * (P("}")/"")) / context.m -- watch the space after \m
+
+local digit = R("09")
+local sign = S("+-")
+local power = S("^e")
+local digitspace = S("~@_")
+local comma = P(",")
+local period = P(".")
+local semicolon = P(";")
+local colon = P(":")
+local signspace = P("/")
+local positive = P("++") -- was p
+local negative = P("--") -- was n
+local highspace = P("//") -- was s
+local padding = P("=")
+local plus = P("+")
+local minus = P("-")
+local space = P(" ")
+local lparent = P("(")
+local rparent = P(")")
+
+local digits = digit^1
+
+local ddigitspace = digitspace / "" / context.digitsspace
+local ddigit = digits / context.digitsdigit
+local dsemicomma = semicolon / "" / context.digitsseparatorspace
+local dsemiperiod = colon / "" / context.digitsseparatorspace
+local dfinalcomma = comma / "" / context.digitsfinalcomma
+local dfinalperiod = period / "" / context.digitsfinalperiod
+local dintercomma = comma / "" / context.digitsintermediatecomma
+local dinterperiod = period / "" / context.digitsintermediateperiod
+local dskipcomma = comma / "" / context.digitsseparatorspace
+local dskipperiod = period / "" / context.digitsseparatorspace
+local dsignspace = signspace / "" / context.digitssignspace
+local dpositive = positive / "" / context.digitspositive
+local dnegative = negative / "" / context.digitsnegative
+local dhighspace = highspace / "" / context.digitshighspace
+local dsomesign = plus / "" / context.digitsplus
+ + minus / "" / context.digitsminus
+local dpower = power / "" * (
+ plus * C(digits) / context.digitspowerplus
+ + minus * C(digits) / context.digitspowerminus
+ + C(digits) / context.digitspower
+ )
+local dpadding = padding / "" / context.digitszeropadding -- todo
+
+local dleader = (dpositive + dnegative + dhighspace + dsomesign + dsignspace)^0
+local dtrailer = dpower^0
+local dfinal = P(-1) + #P(1 - comma - period - semicolon - colon)
+local dnumber = (ddigitspace + ddigit)^1
+
+-- ___,000,000 ___,___,000 ___,___,__0 000,000,000 000.00 000,000,000.00 000,000,000.==
+
+-- : ; for the moment not used, maybe for invisible fraction . , when no leading number
+
+local c_p = (ddigitspace^1 * dskipcomma)^0 -- ___,
+ * (ddigitspace^0 * ddigit * dintercomma)^0 -- _00, 000,
+ * ddigitspace^0 * ddigit^0 -- _00 000
+ * (
+ dfinalperiod * ddigit -- .00
+ + dskipperiod * dpadding^1 -- .==
+ + dsemiperiod * ddigit -- :00
+ + dsemiperiod * dpadding^1 -- :==
+ )^0
+ + ddigit -- 00
+
+local p_c = (ddigitspace^1 * dskipperiod)^0 -- ___.
+ * (ddigitspace^0 * ddigit * dinterperiod)^0 -- _00. 000.
+ * ddigitspace^0 * ddigit^0 -- _00 000
+ * (
+ dfinalcomma * ddigit -- ,00
+ + dskipcomma * dpadding^1 -- ,==
+ + dsemicomma * ddigit -- :00
+ + dsemicomma * dpadding^1 -- :==
+ )^0
+ + ddigit -- 00
+
+local p_c_dparser = math_one + math_two + dleader * p_c * dtrailer * dfinal
+local c_p_dparser = math_one + math_two + dleader * c_p * dtrailer * dfinal
+
+function commands.digits(str,p_c)
+ if p_c == v_reverse then
+ matchlpeg(p_c_dparser,str)
+ else
+ matchlpeg(c_p_dparser,str)
+ end
+end
+
+-- tables:
+
+local long_prefixes = {
+
+ -- Le Système international d'unités (SI) 8e édition (Table 5)
+
+ Yocto = "yocto", -- 10^{-24}
+ Zepto = "zepto", -- 10^{-21}
+ Atto = "atto", -- 10^{-18}
+ Femto = "femto", -- 10^{-15}
+ Pico = "pico", -- 10^{-12}
+ Nano = "nano", -- 10^{-9}
+ Micro = "micro", -- 10^{-6}
+ Milli = "milli", -- 10^{-3}
+ Centi = "centi", -- 10^{-2}
+ Deci = "deci", -- 10^{-1}
+
+ Deca = "deca", -- 10^{1}
+ Hecto = "hecto", -- 10^{2}
+ Kilo = "kilo", -- 10^{3}
+ Mega = "mega", -- 10^{6}
+ Giga = "giga", -- 10^{9}
+ Tera = "tera", -- 10^{12}
+ Peta = "peta", -- 10^{15}
+ Exa = "exa", -- 10^{18}
+ Zetta = "zetta", -- 10^{21}
+ Yotta = "yotta", -- 10^{24}
+
+ -- IEC 60027-2: 2005, third edition, Part 2
+
+ Kibi = "kibi", -- 2^{10} (not ki)
+ Mebi = "mebi", -- 2^{20}
+ Gibi = "gibi", -- 2^{30}
+ Tebi = "tebi", -- 2^{40}
+ Pebi = "pebi", -- 2^{50}
+ Exbi = "exbi", -- 2^{60}
+
+ -- not standard
+
+ Zebi = "zebi", -- binary
+ Yobi = "yobi", -- binary
+
+ Micro = "micro",
+ Root = "root",
+}
+
+local long_units = {
+
+ -- Le Système international d'unités (SI) 8e édition (except synonyms)
+ -- SI base units (Table 1)
+
+ Meter = "meter",
+ Gram = "gram",
+ Second = "second",
+ Ampere = "ampere",
+ Kelvin = "kelvin",
+ Mole = "mole",
+ Candela = "candela",
+
+ -- synonyms
+
+ Mol = "mole",
+ Metre = "meter",
+
+ -- SI derived units with special names (Table 3)
+
+ Radian = "radian",
+ Steradian = "steradian",
+ Hertz = "hertz",
+ Newton = "newton",
+ Pascal = "pascal",
+ Joule = "joule",
+ Watt = "watt",
+ Coulomb = "coulomb",
+ Volt = "volt",
+ Farad = "farad",
+ Ohm = "ohm",
+ Siemens = "siemens",
+ Weber = "weber",
+ Tesla = "tesla",
+ Henry = "henry",
+ Celsius = "celsius",
+ Lumen = "lumen",
+ Lux = "lux",
+ Bequerel = "bequerel",
+ Gray = "gray",
+ Sievert = "sievert",
+ Katal = "katal",
+
+ -- non SI units accepted for use with SI (Table 6)
+
+ Minute = "minute",
+ Hour = "hour",
+ Day = "day",
+
+ -- (degree, minute, second of arc are treated specially later)
+
+ Gon = "gon",
+ Grad = "grad",
+ Hectare = "hectare",
+ Liter = "liter",
+
+ Tonne = "tonne",
+
+ -- synonyms
+
+ ["Metric Ton"] = "tonne",
+ Litre = "liter",
+
+ -- non-SI units whose values must be obtained experimentally (Table 7)
+
+ ["Electron Volt"] = "electronvolt",
+ Dalton = "dalton",
+ ["Atomic Mass Unit"] = "atomicmassunit",
+ ["Astronomical Unit"] = "astronomicalunit",
+
+ -- special cases (catch doubles, okay, a bit over the top)
+
+ ["Degrees Celsius"] = "celsius",
+ ["Degrees Fahrenheit"] = "fahrenheit",
+ ["Degree Celsius"] = "celsius",
+ ["Degree Fahrenheit"] = "fahrenheit",
+
+ -- too late as we already have connected symbols catched:
+ --
+ -- ["° Celsius"] = "celsius",
+ -- ["° Fahrenheit"] = "fahrenheit",
+ -- ["°Celsius"] = "celsius",
+ -- ["°Fahrenheit"] = "fahrenheit",
+
+ -- the "natural units" and "atomic units" are omitted for now
+ -- synonyms
+
+ eV = "electronvolt",
+ AMU = "atomicmassunit",
+
+ -- other non-SI units (Table 8)
+
+ Bar = "bar",
+ Hg = "mercury",
+ -- ["Millimetre Of Mercury"] = [[mmHg]],
+ Angstrom = "angstrom", -- strictly Ångström
+ ["Nautical Mile"] = "nauticalmile",
+ Barn = "barn",
+ Knot = "knot",
+ Neper = "neper",
+ Bel = "bel", -- in practice only decibel used
+
+ -- other non-SI units from CGS system (Table 9)
+
+ Erg = "erg",
+ Dyne = "dyne",
+ Poise = "poise",
+ Stokes = "stokes",
+ Stilb = "stilb",
+ Phot = "phot",
+ Gal = "gal",
+ Maxwell = "maxwell",
+ Gauss = "gauss",
+ Oersted = "oersted",
+
+ -- end of SI
+
+ -- data: for use with the binary prefixes (except Erlang)
+
+ Bit = "bit",
+ Byte = "byte" ,
+ Baud = "baud",
+ Erlang = "erlang",
+
+ -- common units, not part of SI
+
+ Atmosphere = "atmosphere",
+ Revolution = "revolution",
+
+ -- synonyms
+
+ Atm = "atmosphere",
+ Rev = "revolution",
+
+ -- imperial units (very incomplete)
+
+ Fahrenheit = "fahrenheit",
+ Foot = "foot",
+ Inch = "inch",
+ Calorie = "calorie",
+
+ -- synonyms
+
+ Cal = "calorie",
+
+}
+
+local long_operators = {
+
+ Times = "times",
+ Solidus = "solidus",
+ Per = "per",
+ OutOf = "outof",
+
+}
+
+local long_suffixes = {
+
+ Linear = "linear",
+ Square = "square",
+ Cubic = "cubic",
+ Inverse = "inverse",
+ ILinear = "ilinear",
+ ISquare = "isquare",
+ ICubic = "icubic",
+
+}
+
+local short_prefixes = {
+
+ y = "yocto",
+ z = "zetto",
+ a = "atto",
+ f = "femto",
+ p = "pico",
+ n = "nano",
+ u = "micro",
+ m = "milli",
+ c = "centi",
+ d = "deci",
+ da = "deca",
+ h = "hecto",
+ k = "kilo",
+ M = "mega",
+ G = "giga",
+ T = "tera",
+ P = "peta",
+ E = "exa",
+ Z = "zetta",
+ Y = "yotta",
+
+}
+
+local short_units = { -- I'm not sure about casing
+
+ m = "meter",
+ Hz = "hertz",
+ hz = "hertz",
+ B = "bel",
+ b = "bel",
+ lx = "lux",
+ -- da = "dalton",
+ h = "hour",
+ s = "second",
+ g = "gram",
+ n = "newton",
+ v = "volt",
+ t = "tonne",
+ l = "liter",
+ -- w = "watt",
+ W = "watt",
+ -- a = "ampere",
+ A = "ampere",
+
+ [utfchar(0x2103)] = "celsius",
+ [utfchar(0x2109)] = "fahrenheit",
+}
+
+local short_operators = {
+ ["."] = "times",
+ ["*"] = "times",
+ ["/"] = "solidus",
+ [":"] = "outof",
+}
+
+local short_suffixes = { -- maybe just raw digit match
+ ["1"] = "linear",
+ ["2"] = "square",
+ ["3"] = "cubic",
+ ["+1"] = "linear",
+ ["+2"] = "square",
+ ["+3"] = "cubic",
+ ["-1"] = "inverse",
+ ["-1"] = "ilinear",
+ ["-2"] = "isquare",
+ ["-3"] = "icubic",
+ ["^1"] = "linear",
+ ["^2"] = "square",
+ ["^3"] = "cubic",
+ ["^+1"] = "linear",
+ ["^+2"] = "square",
+ ["^+3"] = "cubic",
+ ["^-1"] = "inverse",
+ ["^-1"] = "ilinear",
+ ["^-2"] = "isquare",
+ ["^-3"] = "icubic",
+}
+
+local symbol_units = {
+ Degrees = "degree",
+ Degree = "degree",
+ -- Deg = "degree",
+ ["°"] = "degree",
+ ArcMinute = "arcminute",
+ ["′"] = "arcminute", -- 0x2032
+ ArcSecond = "arcsecond",
+ ["″"] = "arcsecond", -- 0x2033
+ Percent = "percent",
+ ["%"] = "percent",
+ Promille = "permille",
+ Permille = "permille",
+}
+
+local packaged_units = {
+ Micron = "micron",
+ mmHg = "millimetermercury",
+}
+
+-- rendering:
+
+local unitsPUS = context.unitsPUS
+local unitsPU = context.unitsPU
+local unitsPS = context.unitsPS
+local unitsP = context.unitsP
+local unitsUS = context.unitsUS
+local unitsU = context.unitsU
+local unitsS = context.unitsS
+local unitsO = context.unitsO
+local unitsN = context.unitsN
+local unitsC = context.unitsC
+local unitsQ = context.unitsQ
+local unitsNstart = context.unitsNstart
+local unitsNstop = context.unitsNstop
+local unitsNspace = context.unitsNspace
+
+local labels = languages.data.labels
+
+labels.prefixes = {
+ yocto = { labels = { en = [[y]] } }, -- 10^{-24}
+ zepto = { labels = { en = [[z]] } }, -- 10^{-21}
+ atto = { labels = { en = [[a]] } }, -- 10^{-18}
+ femto = { labels = { en = [[f]] } }, -- 10^{-15}
+ pico = { labels = { en = [[p]] } }, -- 10^{-12}
+ nano = { labels = { en = [[n]] } }, -- 10^{-9}
+ micro = { labels = { en = [[\mu]] } }, -- 10^{-6}
+ milli = { labels = { en = [[m]] } }, -- 10^{-3}
+ centi = { labels = { en = [[c]] } }, -- 10^{-2}
+ deci = { labels = { en = [[d]] } }, -- 10^{-1}
+ deca = { labels = { en = [[da]] } }, -- 10^{1}
+ hecto = { labels = { en = [[h]] } }, -- 10^{2}
+ kilo = { labels = { en = [[k]] } }, -- 10^{3}
+ mega = { labels = { en = [[M]] } }, -- 10^{6}
+ giga = { labels = { en = [[G]] } }, -- 10^{9}
+ tera = { labels = { en = [[T]] } }, -- 10^{12}
+ peta = { labels = { en = [[P]] } }, -- 10^{15}
+ exa = { labels = { en = [[E]] } }, -- 10^{18}
+ zetta = { labels = { en = [[Z]] } }, -- 10^{21}
+ yotta = { labels = { en = [[Y]] } }, -- 10^{24}
+ kibi = { labels = { en = [[Ki]] } }, -- 2^{10} (not ki)
+ mebi = { labels = { en = [[Mi]] } }, -- 2^{20}
+ gibi = { labels = { en = [[Gi]] } }, -- 2^{30}
+ tebi = { labels = { en = [[Ti]] } }, -- 2^{40}
+ pebi = { labels = { en = [[Pi]] } }, -- 2^{50}
+ exbi = { labels = { en = [[Ei]] } }, -- 2^{60}
+ zebi = { labels = { en = [[Zi]] } }, -- binary
+ yobi = { labels = { en = [[Yi]] } }, -- binary
+ micro = { labels = { en = [[µ]] } }, -- 0x00B5 \textmu
+ root = { labels = { en = [[√]] } }, -- 0x221A
+}
+
+labels.units = {
+ meter = { labels = { en = [[m]] } },
+ gram = { labels = { en = [[g]] } }, -- strictly kg is the base unit
+ second = { labels = { en = [[s]] } },
+ ampere = { labels = { en = [[A]] } },
+ kelvin = { labels = { en = [[K]] } },
+ mole = { labels = { en = [[mol]] } },
+ candela = { labels = { en = [[cd]] } },
+ mol = { labels = { en = [[mol]] } },
+ radian = { labels = { en = [[rad]] } },
+ steradian = { labels = { en = [[sr]] } },
+ hertz = { labels = { en = [[Hz]] } },
+ newton = { labels = { en = [[N]] } },
+ pascal = { labels = { en = [[Pa]] } },
+ joule = { labels = { en = [[J]] } },
+ watt = { labels = { en = [[W]] } },
+ coulomb = { labels = { en = [[C]] } },
+ volt = { labels = { en = [[V]] } },
+ farad = { labels = { en = [[F]] } },
+ ohm = { labels = { en = [[Ω]] } }, -- 0x2126 \textohm
+ siemens = { labels = { en = [[S]] } },
+ weber = { labels = { en = [[Wb]] } },
+ mercury = { labels = { en = [[Hg]] } },
+ millimetermercury = { labels = { en = [[mmHg]] } }, -- connected
+ tesla = { labels = { en = [[T]] } },
+ henry = { labels = { en = [[H]] } },
+ celsius = { labels = { en = [[\checkedtextcelsius]] } }, -- 0x2103
+ lumen = { labels = { en = [[lm]] } },
+ lux = { labels = { en = [[lx]] } },
+ bequerel = { labels = { en = [[Bq]] } },
+ gray = { labels = { en = [[Gr]] } },
+ sievert = { labels = { en = [[Sv]] } },
+ katal = { labels = { en = [[kat]] } },
+ minute = { labels = { en = [[min]] } },
+ hour = { labels = { en = [[h]] } },
+ day = { labels = { en = [[d]] } },
+ gon = { labels = { en = [[gon]] } },
+ grad = { labels = { en = [[grad]] } },
+ hectare = { labels = { en = [[ha]] } },
+ liter = { labels = { en = [[l]] } }, -- symbol l or L
+ tonne = { labels = { en = [[t]] } },
+ electronvolt = { labels = { en = [[eV]] } },
+ dalton = { labels = { en = [[Da]] } },
+ atomicmassunit = { labels = { en = [[u]] } },
+ astronomicalunit = { labels = { en = [[ua]] } },
+ bar = { labels = { en = [[bar]] } },
+ angstrom = { labels = { en = [[Å]] } }, -- strictly Ångström
+ nauticalmile = { labels = { en = [[M]] } },
+ barn = { labels = { en = [[b]] } },
+ knot = { labels = { en = [[kn]] } },
+ neper = { labels = { en = [[Np]] } },
+ bel = { labels = { en = [[B]] } }, -- in practice only decibel used
+ erg = { labels = { en = [[erg]] } },
+ dyne = { labels = { en = [[dyn]] } },
+ poise = { labels = { en = [[P]] } },
+ stokes = { labels = { en = [[St]] } },
+ stilb = { labels = { en = [[sb]] } },
+ phot = { labels = { en = [[phot]] } },
+ gal = { labels = { en = [[gal]] } },
+ maxwell = { labels = { en = [[Mx]] } },
+ gauss = { labels = { en = [[G]] } },
+ oersted = { labels = { en = [[Oe]] } }, -- strictly Å’rsted
+ bit = { labels = { en = [[bit]] } },
+ byte = { labels = { en = [[B]] } },
+ baud = { labels = { en = [[Bd]] } },
+ erlang = { labels = { en = [[E]] } },
+ atmosphere = { labels = { en = [[atm]] } },
+ revolution = { labels = { en = [[rev]] } },
+ fahrenheit = { labels = { en = [[\checkedtextfahrenheit]] } }, -- 0x2109
+ foot = { labels = { en = [[ft]] } },
+ inch = { labels = { en = [[inch]] } },
+ calorie = { labels = { en = [[cal]] } },
+ --
+ degree = { labels = { en = [[°]]} },
+ arcminute = { labels = { en = [[\checkedtextprime]] } }, -- ′ 0x2032
+ arcsecond = { labels = { en = [[\checkedtextdoubleprime]] } }, -- ″ 0x2033
+ percent = { labels = { en = [[\percent]] } },
+ permille = { labels = { en = [[\promille]] } },
+ --
+ micron = { labels = { en = [[\textmu m]] } },
+}
+
+labels.operators = {
+ times = { labels = { en = [[\unitsTIMES]] } },
+ solidus = { labels = { en = [[\unitsSOLIDUS]] } },
+ per = { labels = { en = [[\unitsSOLIDUS]] } },
+ outof = { labels = { en = [[\unitsOUTOF]] } },
+}
+
+labels.suffixes = {
+ linear = { labels = { en = [[1]] } },
+ square = { labels = { en = [[2]] } },
+ cubic = { labels = { en = [[3]] } },
+ inverse = { labels = { en = [[-1]] } },
+ ilinear = { labels = { en = [[-1]] } },
+ isquare = { labels = { en = [[-2]] } },
+ icubic = { labels = { en = [[-3]] } },
+}
+
+local function dimpus(p,u,s)
+ if trace_units then
+ report_units("p: [%s], u: [%s], s: [%s]",p or "?",u or "?",s or "?")
+ end --
+ if p ~= "" then
+ if u ~= "" then
+ if s ~= "" then
+ unitsPUS(p,u,s)
+ else
+ unitsPU(p,u)
+ end
+ elseif s ~= "" then
+ unitsPS(p,s)
+ else
+ unitsP(p)
+ end
+ else
+ if u ~= "" then
+ if s ~= "" then
+ unitsUS(u,s)
+ -- elseif c then
+ -- unitsC(u)
+ else
+ unitsU(u)
+ end
+ elseif s ~= "" then
+ unitsS(s)
+ else
+ unitsP(p)
+ end
+ end
+end
+
+local function dimspu(s,p,u)
+ return dimpus(p,u,s)
+end
+
+local function dimop(o)
+ if trace_units then
+ report_units("o: [%s]",o or "?")
+ end
+ if o then
+ unitsO(o)
+ end
+end
+
+local function dimsym(s)
+ if trace_units then
+ report_units("s: [%s]",s or "?")
+ end
+ s = symbol_units[s] or s
+ if s then
+ unitsC(s)
+ end
+end
+
+local function dimpre(p)
+ if trace_units then
+ report_units("p: [%s]",p or "?")
+ end
+ p = packaged_units[p] or p
+ if p then
+ unitsU(p)
+ end
+end
+
+-- patterns:
+--
+-- space inside Cs else funny captures and args to function
+--
+-- square centi meter per square kilo seconds
+
+-- todo 0x -> rm
+
+local function update_parsers() -- todo: don't remap utf sequences
+
+ local all_long_prefixes = { }
+ local all_long_units = { }
+ local all_long_operators = { }
+ local all_long_suffixes = { }
+ local all_symbol_units = { }
+ local all_packaged_units = { }
+
+ for k, v in next, long_prefixes do all_long_prefixes [k] = v all_long_prefixes [lower(k)] = v end
+ for k, v in next, long_units do all_long_units [k] = v all_long_units [lower(k)] = v end
+ for k, v in next, long_operators do all_long_operators[k] = v all_long_operators[lower(k)] = v end
+ for k, v in next, long_suffixes do all_long_suffixes [k] = v all_long_suffixes [lower(k)] = v end
+ for k, v in next, symbol_units do all_symbol_units [k] = v all_symbol_units [lower(k)] = v end
+ for k, v in next, packaged_units do all_packaged_units[k] = v all_packaged_units[lower(k)] = v end
+
+ local somespace = P(" ")^0/""
+
+ local p_long_prefix = appendlpeg(all_long_prefixes,nil,true)
+ local p_long_unit = appendlpeg(all_long_units,nil,true)
+ local p_long_operator = appendlpeg(all_long_operators,nil,true)
+ local p_long_suffix = appendlpeg(all_long_suffixes,nil,true)
+ local p_symbol = appendlpeg(all_symbol_units,nil,true)
+ local p_packaged = appendlpeg(all_packaged_units,nil,true)
+
+ local p_short_prefix = appendlpeg(short_prefixes)
+ local p_short_unit = appendlpeg(short_units)
+ local p_short_operator = appendlpeg(short_operators)
+ local p_short_suffix = appendlpeg(short_suffixes)
+
+ -- we can can cleanup some space issues here (todo)
+
+ local unitparser = P { "unit",
+ --
+ longprefix = Cs(V("somespace") * p_long_prefix),
+ shortprefix = Cs(V("somespace") * p_short_prefix),
+ longsuffix = Cs(V("somespace") * p_long_suffix),
+ shortsuffix = Cs(V("somespace") * p_short_suffix),
+ shortunit = Cs(V("somespace") * p_short_unit),
+ longunit = Cs(V("somespace") * p_long_unit),
+ longoperator = Cs(V("somespace") * p_long_operator),
+ shortoperator = Cs(V("somespace") * p_short_operator),
+ packaged = Cs(V("somespace") * p_packaged),
+ --
+ nothing = Cc(""),
+ somespace = somespace,
+ nospace = (1-somespace)^1, -- was 0
+ -- ignore = P(-1),
+ --
+ qualifier = Cs(V("somespace") * (lparent/"") * (1-rparent)^1 * (rparent/"")),
+ --
+ somesymbol = V("somespace")
+ * (p_symbol/dimsym)
+ * V("somespace"),
+ somepackaged = V("somespace")
+ * (V("packaged") / dimpre)
+ * V("somespace"),
+ -- someunknown = V("somespace")
+ -- * (V("nospace")/unitsU)
+ -- * V("somespace"),
+ --
+ combination = V("longprefix") * V("longunit") -- centi meter
+ + V("nothing") * V("longunit")
+ + V("shortprefix") * V("shortunit") -- c m
+ + V("nothing") * V("shortunit")
+ + V("longprefix") * V("shortunit") -- centi m
+ + V("shortprefix") * V("longunit"), -- c meter
+ dimension = V("somespace")
+ * (
+ V("packaged") / dimpre
+ + (V("longsuffix") * V("combination")) / dimspu
+ + (V("combination") * (V("shortsuffix") + V("nothing"))) / dimpus
+ )
+ * (V("qualifier") / unitsQ)^-1
+ * V("somespace"),
+ operator = V("somespace")
+ * ((V("longoperator") + V("shortoperator")) / dimop)
+ * V("somespace"),
+ snippet = V("dimension")
+ + V("somesymbol"),
+ unit = (
+ V("snippet")
+ * (V("operator") * V("snippet"))^0
+ + V("somepackaged")
+ )^1,
+ }
+
+
+ -- local number = lpeg.patterns.number
+
+ local number = Cs( P("$") * (1-P("$"))^1 * P("$")
+ + P([[\m{]]) * (1-P("}"))^1 * P("}")
+ + (1-R("az","AZ")-P(" "))^1 -- todo: catch { } -- not ok
+ ) / unitsN
+
+ local start = Cc(nil) / unitsNstart
+ local stop = Cc(nil) / unitsNstop
+ local space = Cc(nil) / unitsNspace
+
+ local p_c_combinedparser = P { "start",
+ number = start * dleader * (p_c_dparser + number) * stop,
+ rule = V("number")^-1 * unitparser,
+ space = space,
+ start = V("rule") * (V("space") * V("rule"))^0 + V("number")
+ }
+
+ local c_p_combinedparser = P { "start",
+ number = start * dleader * (c_p_dparser + number) * stop,
+ rule = V("number")^-1 * unitparser,
+ space = space,
+ start = V("rule") * (V("space") * V("rule"))^0 + V("number")
+ }
+
+ return p_c_combinedparser, c_p_combinedparser
+end
+
+local p_c_parser = nil
+local c_p_parser = nil
+local dirty = true
+
+function commands.unit(str,p_c)
+ if dirty then
+ if trace_units then
+ report_units("initializing parser")
+ end
+ p_c_parser, c_p_parser = update_parsers()
+ dirty = false
+ end
+ local ok
+ if p_c == v_reverse then
+ ok = matchlpeg(p_c_parser,str)
+ else
+ ok = matchlpeg(c_p_parser,str)
+ end
+ if not ok then
+ report_units("unable to parse: %s",str)
+ context(str)
+ end
+end
+
+local function trigger(t,k,v)
+ rawset(t,k,v)
+ dirty = true
+end
+
+local t_units = {
+ prefixes = setmetatablenewindex(long_prefixes,trigger),
+ units = setmetatablenewindex(long_units,trigger),
+ operators = setmetatablenewindex(long_operators,trigger),
+ suffixes = setmetatablenewindex(long_suffixes,trigger),
+ symbols = setmetatablenewindex(symbol_units,trigger),
+ packaged = setmetatablenewindex(packaged_units,trigger),
+}
+
+local t_shortcuts = {
+ prefixes = setmetatablenewindex(short_prefixes,trigger),
+ units = setmetatablenewindex(short_units,trigger),
+ operators = setmetatablenewindex(short_operators,trigger),
+ suffixes = setmetatablenewindex(short_suffixes,trigger),
+}
+
+physics.units.tables = {
+ units = t_units,
+ shortcuts = t_shortcuts,
+}
+
+local mapping = {
+ prefix = "prefixes",
+ unit = "units",
+ operator = "operators",
+ suffixe = "suffixes",
+ symbol = "symbols",
+ packaged = "packaged",
+}
+
+function commands.registerunit(category,list)
+ if not list or list == "" then
+ list = category
+ category = "unit"
+ end
+ local t = t_units[mapping[category]]
+ if t then
+ for k, v in next, utilities.parsers.settings_to_hash(list or "") do
+ t[k] = v
+ end
+ end
+ -- inspect(tables)
+end
diff --git a/Master/texmf-dist/tex/context/base/phys-dim.mkiv b/Master/texmf-dist/tex/context/base/phys-dim.mkiv
new file mode 100644
index 00000000000..84c3c7a2a05
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/phys-dim.mkiv
@@ -0,0 +1,751 @@
+%D \module
+%D [ file=phys-dim,
+%D version=2011-06-13, % was digits and units 1997.03.19,
+%D title=\CONTEXT\ Physics,
+%D subtitle=Digits and Units,
+%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.
+
+\registerctxluafile{phys-dim}{}
+
+% TAGGING NEEDS CHECKING ... WILL DO WHEN PARSER IS OK
+
+\unprotect
+
+%D \macros
+%D {digits, setdigitmode, setdigitsign}
+%D
+%D This is an update of the \MKII\ digits mechanism. Beware,
+%D space delimited mode is now resticted!
+%D
+%D Depending on the digit mode the command \type {\digits}
+%D normalizes number patterns depending on the language set.
+%D
+%D \starttyping
+%D This will never be a \digits{1.000.000} seller.
+%D \stoptyping
+%D
+%D We still support the space delimited case but this is only for special
+%D purposes. When used in the text, you'd better use the argument variant.
+%D
+%D \startbuffer
+%D 1 \setdigitmode {1} \setdigitorder{0} \digits {12.345,90}
+%D 2 \setdigitmode {2} \setdigitorder{0} \digits {12.345,90}
+%D 3 \setdigitmode {3} \setdigitorder{0} \digits {12.345,90}
+%D 4 \setdigitmode {4} \setdigitorder{0} \digits {12.345,90}
+%D 5 \setdigitmode {5} \setdigitorder{0} \digits {12.345,90}
+%D 6 \setdigitmode {6} \setdigitorder{0} \digits {12.345,90}
+%D 1 \setdigitmode {1} \setdigitorder{1} \digits {12.345,90}
+%D 2 \setdigitmode {2} \setdigitorder{1} \digits {12.345,90}
+%D 3 \setdigitmode {3} \setdigitorder{1} \digits {12.345,90}
+%D 4 \setdigitmode {4} \setdigitorder{1} \digits {12.345,90}
+%D 5 \setdigitmode {5} \setdigitorder{1} \digits {12.345,90}
+%D 6 \setdigitmode {6} \setdigitorder{1} \digits {12.345,90}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This is typeset as:
+%D
+%D \startlines \getbuffer \stoplines
+%D
+%D The sign can be typeset as is or within the space of a
+%D digit.
+%D
+%D \startbuffer
+%D \setdigitsign 0 \digits {+12.345,90}
+%D \setdigitsign 1 \digits {+12.345,90}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D This is typset as:
+%D
+%D \startlines
+%D \getbuffer
+%D \stoplines
+%D
+%D The digit modes are:
+%D
+%D \startitemize[n,packed]
+%D \item periods/comma
+%D \item commas/period
+%D \item thinmuskips/comma
+%D \item thinmuskips/period
+%D \item thickmuskips/comma
+%D \item thickmuskips/period
+%D \stopitemize
+%D
+%D The digit parser handles a bunch of special characters as
+%D well as different formats. We strongly suggest you to use
+%D the grouped call.
+%D
+%D \starttabulate[|l|l|l|]
+%D \starttabulate[|l|l|l|]
+%D \NC \type{.} \NC , . \NC comma or period \NC \NR
+%D \NC \type{,} \NC , . \NC comma or period \NC \NR
+%D \NC \type{:} \NC \NC invisible period \NC \NR
+%D \NC \type{;} \NC \NC invisible comma \NC \NR
+%D \NC \type{_} \NC \NC invisible space \NC \NR
+%D \NC \type{/} \NC \NC invisible sign \NC \NR
+%D \NC \type{-} \NC $-$ \NC minus sign \NC \NR
+%D \NC \type{+} \NC $+$ \NC plus sign \NC \NR
+%D \NC \type{//} \NC \NC invisible high sign \NC \NR
+%D \NC \type{--} \NC $\negative$ \NC high minus sign \NC \NR
+%D \NC \type{++} \NC $\positive$ \NC high plus sign \NC \NR
+%D \NC \type{=} \NC $\zeroamount$ \NC zero padding \NC \NR
+%D \stoptabulate
+%D \stoptabulate
+%D
+%D These triggers are used in the following examples.
+%D
+%D \starttabulate[|l|r|]
+%D \NC \type{1} \NC \ruledhbox{\strut\digits{1}} \NC \NR
+%D \NC \type{12} \NC \ruledhbox{\strut\digits{12}} \NC \NR
+%D \NC \type{12.34} \NC \ruledhbox{\strut\digits{12.34}} \NC \NR
+%D \NC \type{123,456} \NC \ruledhbox{\strut\digits{123,456}} \NC \NR
+%D \NC \type{123,456.78} \NC \ruledhbox{\strut\digits{123,456.78}} \NC \NR
+%D \NC \type{12,34} \NC \ruledhbox{\strut\digits{12,34}} \NC \NR
+%D \NC \type{.1234} \NC \ruledhbox{\strut\digits{.1234}} \NC \NR
+%D \NC \type{1234} \NC \ruledhbox{\strut\digits{1234}} \NC \NR
+%D \NC \type{123,456.78^9} \NC \ruledhbox{\strut\digits{123,456.78^9}} \NC \NR
+%D \NC \type{123,456.78e9} \NC \ruledhbox{\strut\digits{123,456.78e9}} \NC \NR
+%D \NC \type{/123,456.78e-9} \NC \ruledhbox{\strut\digits{/123,456.78e-9}} \NC \NR
+%D \NC \type{-123,456.78e-9} \NC \ruledhbox{\strut\digits{-123,456.78e-9}} \NC \NR
+%D \NC \type{+123,456.78e-9} \NC \ruledhbox{\strut\digits{+123,456.78e-9}} \NC \NR
+%D \NC \type{//123,456.78e-9} \NC \ruledhbox{\strut\digits{//123,456.78e-9}} \NC \NR
+%D \NC \type{--123,456.78e-9} \NC \ruledhbox{\strut\digits{--123,456.78e-9}} \NC \NR
+%D \NC \type{++123,456.78e-9} \NC \ruledhbox{\strut\digits{++123,456.78e-9}} \NC \NR
+%D \NC \type{___,___,123,456,789.00} \NC \ruledhbox{\strut\digits{___,___,123,456,789.00}} \NC \NR
+%D \NC \type{___,___,_12,345,678.==} \NC \ruledhbox{\strut\digits{___,___,_12,345,678.==}} \NC \NR
+%D \stoptabulate
+
+\newconstant\c_phys_digits_order
+\newconstant\c_phys_digits_method
+\newconstant\c_phys_digits_sign % we has sized (text script scriptscript)
+
+\unexpanded\def\setdigitmethod#1{\c_phys_digits_method #1\relax}
+\unexpanded\def\setdigitsign #1{\c_phys_digits_sign #1\relax}
+\unexpanded\def\setdigitorder #1{\c_phys_digits_order #1\relax}
+
+\let\setdigitmode\setdigitmethod % compatibility
+
+\def\phys_digits_normalized % we could calculate once and remember
+ {\ifcase\c_phys_digits_sign
+ \expandafter\secondoftwoarguments
+ \else\ifmmode
+ \expandafter\expandafter\expandafter\phys_digits_normalized_math
+ \else
+ \expandafter\expandafter\expandafter\phys_digits_normalized_text
+ \fi\fi}
+
+\def\phys_digits_normalized_math#1#2%
+ {\setbox\scratchbox\hbox{$\Ustack{#1}$}%
+ \hbox to \wd\scratchbox{\hss{$\Ustack{#2}$}\hss}}
+
+\def\phys_digits_normalized_text#1#2%
+ {\setbox\scratchbox\hbox{#1}%
+ \hbox to \wd\scratchbox{\hss#2\hss}}
+
+\def\phys_digits_raised
+ {\ifmmode
+ \expandafter\normalsuperscript
+ \else
+ \expandafter\high
+ \fi}
+
+\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}}}
+\unexpanded\def\digitsnegative {\phys_digits_normalized{0}{\mathematics{\negative}}}
+\unexpanded\def\digitspositive {\phys_digits_normalized{0}{\mathematics{\positive}}}
+\unexpanded\def\digitsminus {\phys_digits_normalized{0}{\mathematics{-}}}
+\unexpanded\def\digitsplus {\phys_digits_normalized{0}{\mathematics{+}}}
+\unexpanded\def\digitsspace {\hphantom{0}}
+\unexpanded\def\digitsseparatorspace{\hphantom{.}}
+\unexpanded\def\digitssignspace {\hphantom{\digitsminus}}
+\unexpanded\def\digitshighspace {\hphantom{\digitspositive}}
+\unexpanded\def\digitspower #1{\times10\phys_digits_raised{#1}}
+\unexpanded\def\digitspowerplus #1{\times10\phys_digits_raised{\digitsplus#1}}
+\unexpanded\def\digitspowerminus #1{\times10\phys_digits_raised{\digitsminus#1}}
+\unexpanded\def\digitsdigit #1{#1}
+
+\unexpanded\def\normaldigitscommasymbol {,}
+\unexpanded\def\normaldigitsperiodsymbol{.}
+
+\let\normaldigitsseparatorspace\digitsseparatorspace
+
+\installcorenamespace{digitscomma}
+\installcorenamespace{digitsperiod}
+\installcorenamespace{digitsspace}
+
+\letvalue{\??digitscomma 0}\normaldigitscommasymbol
+\letvalue{\??digitsperiod0}\normaldigitsperiodsymbol
+\letvalue{\??digitsspace 0}\normaldigitsseparatorspace
+
+\letvalue{\??digitscomma 1}\normaldigitsperiodsymbol
+\letvalue{\??digitsperiod1}\normaldigitscommasymbol
+\letvalue{\??digitsspace 1}\normaldigitsseparatorspace
+
+\letvalue{\??digitscomma 2}\normaldigitscommasymbol
+\letvalue{\??digitsperiod2}\normaldigitsperiodsymbol
+\letvalue{\??digitsspace 2}\normaldigitsseparatorspace
+
+\letvalue{\??digitscomma 3}\thinspace
+\letvalue{\??digitsperiod3}\normaldigitscommasymbol
+\letvalue{\??digitsspace 3}\thinspace
+
+\letvalue{\??digitscomma 4}\thinspace
+\letvalue{\??digitsperiod4}\normaldigitsperiodsymbol
+\letvalue{\??digitsspace 4}\thinspace
+
+\letvalue{\??digitscomma 5}\thickspace
+\letvalue{\??digitsperiod5}\normaldigitscommasymbol
+\letvalue{\??digitsspace 5}\thickspace
+
+\letvalue{\??digitscomma 6}\thickspace
+\letvalue{\??digitsperiod6}\normaldigitsperiodsymbol
+\letvalue{\??digitsspace 6}\thickspace
+
+\unexpanded\def\digitscommasymbol {\csname\??digitscomma \number\c_phys_digits_method\endcsname}
+\unexpanded\def\digitsperiodsymbol {\csname\??digitsperiod\number\c_phys_digits_method\endcsname}
+\unexpanded\def\digitsseparatorspace {\csname\??digitsspace \number\c_phys_digits_method\endcsname}
+
+\unexpanded\def\digitsfinalcomma {\digitscommasymbol } % more for tracing
+\unexpanded\def\digitsfinalperiod {\digitsperiodsymbol} % more for tracing
+\unexpanded\def\digitsintermediatecomma {\digitscommasymbol } % more for tracing
+\unexpanded\def\digitsintermediateperiod {\digitsperiodsymbol} % more for tracing
+
+%D The user macro:
+
+\unexpanded\def\phys_digits_indeed#1%
+ {\dontleavehmode
+ \begingroup
+ \ctxcommand{digits(\!!bs\detokenize{#1}\!!es,"\ifcase\c_phys_digits_order \v!normal\else\v!reverse\fi")}%
+ \endgroup
+ \settrue\c_phys_units_dospace}
+
+\unexpanded\def\digits
+ {\doifnextbgroupelse\phys_digits_argument\phys_digits_spaced}
+
+\def\phys_digits_argument#1%
+ {\phys_digits_indeed{#1}}
+
+\def\phys_digits_spaced#1 % space delimited
+ {\phys_digits_indeed{#1}}
+
+%D \macros
+%D {unit}
+%D
+%D We have been using the units module (and its predecessor) for over a decade
+%D now but when we moved on to \LUATEX\ a variant was prototyped that permits a
+%D less texie coding. I finally picked up that thread and cleaned up the code a
+%D bit so users can now play with it. (The main reason was that I wanted to
+%D test exporting.)
+%D
+%D \startbuffer
+%D 01: $10\unit{km/h}$
+%D 02: $\unit{10 km/h}$
+%D 03: \unit{km/h}
+%D 04: \unit{10 km/h}
+%D 05: \unit{10 km/h}
+%D 06: \unit{~1 km/h}
+%D 07: 10\unit{km/h}
+%D 08: 10 \unit{km/h}
+%D 09: $10 \unit{km/h}$
+%D 10: 10 \unit{KiloMeter/Hour}
+%D 11: 10 \unit{kilometer/hour}
+%D 12: 10 \unit{km/h}
+%D 13: 10 \unit{kilometer per hour}
+%D 14: 10 \unit{km / h}
+%D 15: 10 \unit{ km / h }
+%D 16: 10 \unit{km/ms2}
+%D 17: 10 \unit{meter per second}
+%D 18: 10 \unit{cubic meter}
+%D 19: 10 \unit{cubic meter per second}
+%D 21: 10 \unit{cubic meter / second}
+%D 22: $10 \unit{cubic meter / second}$
+%D 23: 30 \unit{kilo pascal }
+%D 24: 30 \unit{kilo pascal square meter / second}
+%D 25: 30 \unit{kilo pascal square meter / kelvin second}
+%D 26: \unit{30 kilo pascal square meter / kelvin second}
+%D 27: $30 \unit{kilo pascal square meter / kelvin second }$
+%D 28: 30 \unit{crap}
+%D 29: 30 \unit{AC}
+%D 30: $\frac{10 \unit{m/s}}{20 \unit{m/s}} $
+%D 31: {\ss 30 \unit{kilo pascal square meter / second kelvin}}
+%D 32: \unit{123.22^-3 km/s}
+%D 33: \unit{123.22e-3 km/s}
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Result: \startlines \getbuffer \stoplines
+%D
+%D Depending on needs we can add more tweaks (also depends on to what
+%D extent we need to be compatible with \MKII.
+%D
+%D Formatting is supported too:
+%D
+%D \startbuffer
+%D \starttabulate[|l|l|l|]
+%D \HL
+%D \NC \unit{10 kilo gram} \NC \digits{10} \NC \unit{10} \NC \NR
+%D \NC \unit{1 kilogram} \NC \digits{1} \NC \unit{1} \NC \NR
+%D \NC \unit{0.1 kilogram} \NC \digits{0.1} \NC \unit{0.1} \NC \NR
+%D \NC \unit{1.1 kilogram} \NC \digits{1.1} \NC \unit{1.1} \NC \NR
+%D \NC \unit{11 kilogram} \NC \digits{11} \NC \unit{11} \NC \NR
+%D \HL
+%D \NC \unit{00,000.10 kilogram} \NC \digits{00,000.10} \NC \unit{00,000.10} \NC \NR
+%D \NC \unit{@@,@@0.10 kilogram} \NC \digits{@@,@@0.10} \NC \unit{@@,@@0.10} \NC \NR
+%D \NC \unit{__,___.10 kilogram} \NC \digits{__,___.10} \NC \unit{__,___.10} \NC \NR
+%D \NC \unit{__,__0:10 kilogram} \NC \digits{__,__0:10} \NC \unit{__,__0:10} \NC \NR
+%D \NC \unit{__,___:10 kilogram} \NC \digits{__,___:10} \NC \unit{__,___:10} \NC \NR
+%D \HL
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Punctuation can be configures usiing \type {method}:
+%D
+%D \startbuffer
+%D \starttabulate[|l|l|l|]
+%D \HL
+%D \NC \NC \setupunits[method=0]\unit{00,000.10 kilogram} \NC \setupunits[method=0]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 1 \NC \setupunits[method=1]\unit{00,000.10 kilogram} \NC \setupunits[method=1]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 2 \NC \setupunits[method=2]\unit{00,000.10 kilogram} \NC \setupunits[method=2]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 3 \NC \setupunits[method=3]\unit{00,000.10 kilogram} \NC \setupunits[method=3]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 4 \NC \setupunits[method=4]\unit{00,000.10 kilogram} \NC \setupunits[method=4]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 5 \NC \setupunits[method=5]\unit{00,000.10 kilogram} \NC \setupunits[method=5]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \NC 6 \NC \setupunits[method=6]\unit{00,000.10 kilogram} \NC \setupunits[method=6]\unit{@@,@@0.10 kilogram} \NC \NR
+%D \HL
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% only a space when a number is part of the unit
+
+\installcorenamespace {unit}
+\installcorenamespace {unitseparator}
+\installcorenamespace {unitspace}
+
+\installcommandhandler \??unit {unit} \??unit
+
+\setupunit
+ [\c!alternative=, % done: text
+ \c!separator=\v!normal, % done: cdot|big|medium|space
+ \s!language=\currentlanguage, % done: (no interface yet)
+ \c!order=\v!normal, % ,. (reverse: .,)
+ \c!method=0,
+ %\c!grid=\v!yes, % (maybe)
+ %\c!style=..., % done
+ %\c!color=..., % done
+ %\c!space=..., % (maybe) small medium big
+ ]
+
+\let\setupunits\setupunit
+
+\newconstant \c_phys_units_mode % 0=text 1=math 2=textinmath 3=mathintext
+\newconstant \c_phys_units_state % 0=start 1=suffix 2=operator 3=unit 4=prefix 5=number
+\newconditional\c_phys_units_quantity
+\newconditional\c_phys_units_number
+\newconditional\c_phys_units_dospace
+
+% [\unit {micro ohm}]\par % no space before unit
+% [10\unit {micro ohm}]\par % no space before unit
+% [10 \unit{micro ohm}]\par % space before unit
+% [ \unit {micro ohm}]\par % space before unit
+% [\unit{10 micro ohm}]\par % space before unit
+
+\unexpanded\def\unitssmallspace {\thinspace}
+\unexpanded\def\unitsmediumspace{\medspace}
+\unexpanded\def\unitsbigspace {\thickspace}
+\unexpanded\def\unitsbackspace {\negthinspace}
+
+\unexpanded\def\installunitsseparator#1#2%
+ {\setvalue{\??unitseparator#1}{#2}}
+
+\unexpanded\def\phys_units_separator
+ {\edef\currentunitsseparator{\unitparameter\c!separator}%
+ \csname\??unitseparator
+ \ifcsname\??unitseparator\currentunitsseparator\endcsname\currentunitsseparator\else\v!normal\fi
+ \endcsname}
+
+\installunitsseparator\v!normal {\cdot}
+\installunitsseparator\v!big {\unitsbigspace}
+\installunitsseparator\v!medium {\unitsmediumspace}
+\installunitsseparator\v!small {\unitssmallspace}
+\installunitsseparator\v!none {}
+
+\unexpanded\def\installunitsspace#1#2%
+ {\setvalue{\??unitspace#1}{#2}}
+
+\unexpanded\def\phys_units_space
+ {\unskip % weird, why is unskip needed
+ \edef\currentunitsspace{\unitparameter\c!space}%
+ \csname\??unitspace
+ \ifcsname\??unitspace\currentunitsspace\endcsname\currentunitsspace\else\v!normal\fi
+ \endcsname}
+
+\installunitsspace\v!normal {\unitsmediumspace}
+\installunitsspace\v!big {\unitsbigspace}
+\installunitsspace\v!medium {\unitsmediumspace}
+\installunitsspace\v!small {\unitssmallspace}
+\installunitsspace\v!none {}
+
+\newtoks \everyunits % we keep the old \units command so we need a longer one
+
+\appendtoks
+ \setuevalue\currentunit{\phys_units_direct{\currentunit}}
+\to \everydefineunit
+
+\unexpanded\def\phys_units_direct#1%
+ {\begingroup
+ \ifdim\lastskip>\zeropoint
+ \settrue\c_phys_units_dospace
+ \removelastskip
+ \fi
+ \c_phys_digits_method\unitparameter\c!method\relax
+ \ifmmode\else\dontleavehmode\fi
+ \edef\currentunit{#1}%
+ \edef\unitlanguage{\unitparameter\s!language}%
+ \let\prefixlanguage\unitlanguage
+ \let\operatorlanguage\unitlanguage
+ \the\everyunits
+ %\removeunwantedspaces % not ok yet
+ \useunitstyleandcolor\c!style\c!color
+ \edef\currentunitsalternative{\unitparameter\c!alternative}%
+ \ifmmode
+ \ifx\currentunitsalternative\v!text
+ \expandafter\expandafter\expandafter\phys_units_direct_text_in_math
+ \else
+ \expandafter\expandafter\expandafter\phys_units_direct_math
+ \fi
+ \else
+ \ifx\currentunitsalternative\v!mathematics
+ \expandafter\expandafter\expandafter\phys_units_direct_math_in_text
+ \else
+ \expandafter\expandafter\expandafter\phys_units_direct_text
+ \fi
+ \fi}
+
+\unexpanded\def\phys_units_direct_text_in_math#1%
+ {\mathtext{%
+ \c_phys_units_mode\plustwo
+ \phys_units_indeed{#1}%
+ \phys_units_finish
+ }%
+ \endgroup}
+
+\unexpanded\def\phys_units_direct_math#1%
+ {\c_phys_units_mode\plusone
+ \rm\tf % slow
+ \mathtf
+ \phys_units_indeed{#1}%
+ \phys_units_finish
+ \endgroup}
+
+\unexpanded\def\phys_units_direct_text#1%
+ {\phys_units_indeed{#1}%
+ \phys_units_finish
+ \endgroup}
+
+\unexpanded\def\phys_units_direct_math_in_text#1%
+ {\removeunwantedspaces % brr
+ \startimath
+ \c_phys_units_mode\plusthree
+ \rm\tf
+ \mathtf
+ \phys_units_indeed{#1}%
+ \phys_units_finish
+ \stopimath
+ \endgroup}
+
+\unexpanded\def\phys_units_direct_nested#1#2%
+ {\phys_units_indeed{#2}}
+
+\appendtoks
+ \let\phys_units_direct\phys_units_direct_nested
+\to \everyunits
+
+\unexpanded\def\phys_units_indeed#1%
+ {\ctxcommand{unit(\!!bs\detokenize{#1}\!!es,"\unitparameter\c!order")}}
+
+\unexpanded\def\unitsPUS#1#2#3{\phys_units_next\prefixtext{#1}\unittext{#2}\unitsraise{\suffixtext{#3}}\c_phys_units_state\plusone} % suffix
+\unexpanded\def\unitsPU #1#2{\phys_units_next\prefixtext{#1}\unittext{#2}\c_phys_units_state\plusthree} % unit
+\unexpanded\def\unitsPS #1#2{\phys_units_next\prefixtext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix
+\unexpanded\def\unitsUS #1#2{\phys_units_next\unittext{#1}\unitsraise{\suffixtext{#2}}\c_phys_units_state\plusone} % suffix
+\unexpanded\def\unitsP #1{\phys_units_next\prefixtext{#1}1\c_phys_units_state\plusfour} % prefix
+\unexpanded\def\unitsU #1{\phys_units_next\unittext{#1}\c_phys_units_state\plusthree} % unit
+\unexpanded\def\unitsS #1{\phys_units_start{}\unitsraise{\suffixtext{#1}}\c_phys_units_state\plusone} % suffix
+\unexpanded\def\unitsO #1{\phys_units_start\operatortext{#1}\c_phys_units_state\plustwo} % operator
+\unexpanded\def\unitsN #1{\phys_units_start#1\c_phys_units_state\plusfive} % number
+\unexpanded\def\unitsC #1{\removeunwantedspaces\unittext{#1}\c_phys_units_state\plussix} % connected
+\unexpanded\def\unitsQ #1{\removeunwantedspaces\unitslower{#1}\c_phys_units_state\zerocount} %
+
+% Fonts can have a celsius and lack a fahrenheit symbol and as we want
+% to be consistent so we check for the counterparts as well. It's slow
+% but ok. Of course we could go virtual instead.
+
+\def\phys_units_text_prime {\textacute}
+\def\phys_units_text_doubleprime{\textacute\kern-.25em\textacute}
+\def\phys_units_text_celsius {°C}
+\def\phys_units_text_fahrenheit {°F}
+
+\unexpanded\def\checkedtextprime
+ {\iffontchar\font"2032\relax\iffontchar\font"2033\relax
+ ′\else\phys_units_text_prime\fi\else\phys_units_text_prime
+ \fi}
+
+\unexpanded\def\checkedtextdoubleprime
+ {\iffontchar\font"2033\relax\iffontchar\font"2032\relax
+ ″\else\phys_units_text_doubleprime\fi\else\phys_units_text_doubleprime
+ \fi}
+
+\unexpanded\def\checkedtextcelsius
+ {\iffontchar\font"2103\relax\iffontchar\font"2109\relax
+ ℉\else\phys_units_text_celsius\fi\else\phys_units_text_celsius
+ \fi}
+
+\unexpanded\def\checkedtextfahrenheit
+ {\iffontchar\font"2109\relax\iffontchar\font"2103\relax
+ ℉\else\phys_units_text_fahrenheit\fi\else\phys_units_text_fahrenheit
+ \fi}
+
+\setelementnature[unit] [mixed]
+\setelementnature[quantity][mixed]
+
+\let\phys_units_finish\relax
+
+\unexpanded\def\unitsNstart
+ {\ifmmode \else
+ \settrue\c_phys_units_quantity
+ \dostarttagged\t!quantity\empty
+ \settrue\c_phys_units_number
+ \dostarttagged\t!number\empty
+ \fi}
+
+\unexpanded\def\unitsNstop
+ {\ifconditional\c_phys_units_number
+ \setfalse\c_phys_units_number
+ \dostoptagged
+ \fi
+ \c_phys_units_state\plusfive}
+
+\unexpanded\def\unitsNspace
+ {\space}
+
+\unexpanded\def\unitsN#1%
+ {\unitsNstart#1\unitsNstop}
+
+\def\phys_units_start
+ {\ifmmode
+ \dostarttagged\t!mathaction\t!unit
+ \bgroup % make an mrow
+ \else
+ \dostarttagged\t!unit\empty
+ \fi
+ \let\phys_units_finish\phys_units_stop
+ \let\phys_units_start\relax}
+
+\def\phys_units_stop
+ {\ifconditional\c_phys_units_number
+ \setfalse\c_phys_units_number
+ \dostoptagged
+ \fi
+ \ifconditional\c_phys_units_quantity
+ \setfalse\c_phys_units_quantity
+ \dostoptagged
+ \fi
+ \dostoptagged
+ \ifmmode
+ \egroup
+ \fi}
+
+\def\unitsraise
+ {\ifcase\c_phys_units_mode
+ \expandafter\high
+ \or
+ \expandafter\normalsuperscript
+ \or
+ \expandafter\high
+ \or
+ \expandafter\normalsuperscript
+ \fi}
+
+\def\unitslower
+ {\ifcase\c_phys_units_mode
+ \expandafter\low
+ \or
+ \expandafter\normalsubscript
+ \or
+ \expandafter\low
+ \or
+ \expandafter\normalsubscript
+ \fi}
+
+\unexpanded\def\phys_units_next
+ {\ifcase\c_phys_units_state % start
+ \ifconditional\c_phys_units_dospace
+ % \ifdim\lastskip=\zeropoint
+ \phys_units_space
+ % \else
+ % % too tricky ... we could remove and add
+ % \fi
+ \fi
+ \or % 1: suffix
+ {\phys_units_separator}%
+ \or % 2: operator
+ \or % 3: unit
+ {\phys_units_separator}%
+ \or % 4: prefix
+ \or % 5: number
+ \phys_units_space
+ \or % 6: symbol (connected)
+ \fi
+ \setfalse\c_phys_units_dospace
+ \phys_units_start}
+
+\unexpanded\def\unitsTIMES
+ {\ifnum\c_phys_units_state=\plusone % suffix
+ \else
+ \unitssmallspace
+ \fi
+ \cdot} % or \times
+
+\unexpanded\def\unitsOUTOF
+ {\ifnum\c_phys_units_state=\plusone % suffix
+ \else
+ \unitssmallspace
+ \fi
+ :}
+
+\unexpanded\def\unitsSOLIDUS
+ {\ifnum\c_phys_units_state=\plusone % suffix
+ \unitsbackspace
+ \fi
+ {/}%
+ }%\unitsbackspace}
+
+\definelabelclass [unit] [2]
+\definelabelclass [operator] [2]
+\definelabelclass [prefix] [2]
+\definelabelclass [suffix] [2] % This is only a label because we want to show them in a table.
+
+\ctxlua{
+ languages.labels.define("setupprefixtext","prefixes")%
+ languages.labels.define("setupunittext","units")%
+ languages.labels.define("setupoperatortext","operators")%
+ languages.labels.define("setupsuffixtext","suffixes")%
+}
+
+%D You can define additional units:
+%D
+%D \starttyping
+%D \registerunit
+%D [unit]
+%D [point=point,
+%D basepoint=basepoint,
+%D scaledpoint=scaledpoint,
+%D didot=didot,
+%D cicero=cicero]
+%D \stoptyping
+%D
+%D Possible categories are: \type {prefix}, \type {unit}, \type {operator},
+%D \type {suffix}, \type {symbol},\type {packaged}. You also need to define
+%D labels:
+%D
+%D \starttyping
+%D \setupunittext
+%D [point=pt,
+%D basepoint=bp,
+%D scaledpoint=sp,
+%D didot=dd,
+%D cicero=cc]
+%D \stoptyping
+
+\unexpanded\def\registerunit
+ {\dodoubleempty\phys_units_register}
+
+\def\phys_units_register[#1][#2]%
+ {\ctxcommand{registerunit(\!!bs#1\!!es,\!!bs#2\!!es)}}
+
+%D You can generate a list as follows:
+%D
+%D \starttyping
+%D \usemodule[phy-01]
+%D
+%D \ShowUnitsTable % [prefixes]
+%D \stoptyping
+
+%D Now we define the standard units command:
+
+\defineunit
+ [unit]
+
+%D Example:
+%D
+%D \startbuffer[definitions]
+%D \startluacode
+%D languages.data.labels.prefixes.whatever = {
+%D Kilo = "olik"
+%D }
+%D
+%D languages.data.labels.units.whatever = {
+%D Meter = "retem",
+%D Second = "dnoces",
+%D }
+%D
+%D languages.data.labels.operators.whatever = {
+%D Solidus = " rep "
+%D }
+%D \stopluacode
+%D \stopbuffer
+%D
+%D \startbuffer[sample]
+%D \startlines
+%D \lunit{10 km/s}
+%D \lunit{10 Kilo Meter/s}
+%D \lunit{10 kilo Meter/s}
+%D \lunit{10 Kilo m/s}
+%D \lunit{10 k Meter/s}
+%D \stoplines
+%D \stopbuffer
+%D
+%D \typebuffer[definitions] \getbuffer[definitions]
+%D
+%D \startbuffer
+%D \typebuffer[sample]
+%D
+%D \defineunits[lunit] \getbuffer[sample]
+%D \defineunits[lunit][label=test] \getbuffer[sample]
+%D \defineunits[lunit][label=whatever] \getbuffer[sample]
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+%D
+%D Another example:
+%D
+%D \starttyping
+%D \startluacode
+%D languages.data.labels.units.foo = {
+%D Liter = "l"
+%D }
+%D languages.data.labels.units.bar = {
+%D Liter = "L"
+%D }
+%D \stopluacode
+%D
+%D \defineunits[lunit] \lunit{10 l/s}\par
+%D \defineunits[funit][label=foo] \funit{10 l/s}\par
+%D \defineunits[bunit][label=bar] \bunit{10 l/s}\par
+%D \stoptyping
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/ppchtex.mkii b/Master/texmf-dist/tex/context/base/ppchtex.mkii
index 045e9808b6b..d1209cd97e5 100644
--- a/Master/texmf-dist/tex/context/base/ppchtex.mkii
+++ b/Master/texmf-dist/tex/context/base/ppchtex.mkii
@@ -5,8 +5,8 @@
%D subtitle=\PPCHTEX\ (Plain Pictex Context cHemie \TEX),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten},
-%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten}]
+%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten}.
+%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
diff --git a/Master/texmf-dist/tex/context/base/ppchtex.mkiv b/Master/texmf-dist/tex/context/base/ppchtex.mkiv
index 1162c1fcf6a..a14578cebdb 100644
--- a/Master/texmf-dist/tex/context/base/ppchtex.mkiv
+++ b/Master/texmf-dist/tex/context/base/ppchtex.mkiv
@@ -1,17 +1,19 @@
%D \module
-%D [ file=ppchtex (m-chemie),
+%D [ file=ppchtex,
%D version=1997.03.19,
%D title=\CONTEXT\ Extra Modules,
%D subtitle=\PPCHTEX\ (Plain Pictex Context cHemie \TEX),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten},
-%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten}]
+%D suggestions={Tobias Burnus, Dirk Kuypers \& Ton Otten},
+%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.
+\endinput
+
% option=test => boxes
% dummy => file
% final => file / local run
@@ -75,7 +77,6 @@
% gebruiken. De eerste module laad of efficiente wijze PiCTeX
% en de tweede module koppelt het PSTRICKS kleurmechanisme
% aan dat van \CONTEXT.
-%
% PSTricks: {-\chemicalangle} instead of {*0}, which produces
% faulty ps code when \chemicalangle=0
@@ -472,7 +473,7 @@
\endpspicture
\or
\resetchemicalcoordinates
- \setbox2\hbox{\MPshiftdrawingtrue\MPstaticgraphictrue\getMPdrawing}%
+ \setbox2\hbox{\ignoreMPboxdepth\getMPdrawing}%
\wd2=\!!zeropoint
\ht2=\!!zeropoint
\dp2=\!!zeropoint
@@ -513,7 +514,7 @@
\put {\box\chemicalsymbols} at 0 0 % elders
\ifMPdrawingdone
\resetchemicalcoordinates
- \setbox2\hbox{\MPshiftdrawingtrue\MPstaticgraphictrue\getMPdrawing}%
+ \setbox2\hbox{\ignoreMPboxdepth\getMPdrawing}%
\wd2=\!!zeropoint
\ht2=\!!zeropoint
\dp2=\!!zeropoint
@@ -1721,7 +1722,7 @@
\let\chemicaltwintiparrow = \chemicaltwintipouterarrow
\fi
\disablechemicalspecials
- \unexpandedprocessallactionsinset
+ \processallactionsinset
[#1]
[ HIGH=>\sethighsubscripts,
LOW=>\setlowsubscripts,
@@ -2072,7 +2073,7 @@
\@@chemicalpostponed}
{\getpredefinedchemical{#1}}]}
-\newcount\chemicalstack % tzt \newwounter
+\newcount\chemicalstack
\setvalue{\s!chemical\c!x1}{0}
\setvalue{\s!chemical\c!y1}{0}
@@ -3397,11 +3398,11 @@ RT##3##4##5=>\processchemicaltextelement{RN}{##3##4##5}{#1}{0}{},
drawoptions (\chemicalattributes) ;
\stopMPdrawing}
-\def\@@dochemicalcolor
- {\doifsomething\@@chemicalcolor{\color[\@@chemicalcolor]}}
+\unexpanded\def\@@dochemicalcolor
+ {\dousecolorparameter\@@chemicalcolor}
-\def\@@dochemicalstyle
- {\doconvertfont\@@chemicalstyle}
+\unexpanded\def\@@dochemicalstyle
+ {\dousestyleparameter\@@chemicalstyle}
\setupchemical
[\c!rulethickness=\linewidth,
diff --git a/Master/texmf-dist/tex/context/base/prop-ini.mkii b/Master/texmf-dist/tex/context/base/prop-ini.mkii
index 035a40c9337..11efd036234 100644
--- a/Master/texmf-dist/tex/context/base/prop-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/prop-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/prop-ini.mkiv b/Master/texmf-dist/tex/context/base/prop-ini.mkiv
index 3cb5d2a6f5a..d8d2ea2f4ad 100644
--- a/Master/texmf-dist/tex/context/base/prop-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/prop-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -20,41 +20,45 @@
\unprotect
-\def\propertyobsoletemessage
+\installcorenamespace{propertytypes}
+\installcorenamespace{propertydefiners}
+\installcorenamespace{propertystarters}
+
+\def\properties_obsolete_message
{\writestatus\m!system{properties are obsolete, use dedicated commands}%
- \glet\propertyobsoletemessage\donothing}
+ \glet\properties_obsolete_message\donothing}
-\setvalue{\??py:d:\v!layer }[#1][#2][#3]{\defineviewerlayer[#1][#3]}
-\setvalue{\??py:d:\s!effect }[#1][#2][#3]{\defineeffect [#1][#3]}
-\setvalue{\??py:d:\v!negative}[#1][#2][#3]{}
+\setvalue{\??propertydefiners\v!layer }[#1][#2][#3]{\defineviewerlayer[#1][#3]}
+\setvalue{\??propertydefiners\s!effect }[#1][#2][#3]{\defineeffect [#1][#3]}
+\setvalue{\??propertydefiners\v!negative}[#1][#2][#3]{}
\unexpanded\def\defineproperty
- {\dotripleempty\dodefineproperty}
+ {\dotripleempty\properties_define}
-\def\dodefineproperty[#1][#2][#3]%
- {\propertyobsoletemessage
- \setevalue{\??py#1\c!type}{#2}%
- \getvalue{\??py:d:#2}[#1][#2][#3]}
+\def\properties_define[#1][#2][#3]%
+ {\properties_obsolete_message
+ \setevalue{\??propertytypes#1e}{#2}%
+ \getvalue{\??propertydefiners#2}[#1][#2][#3]}
-\setvalue{\??py:s:\v!layer }#1{\let\dostopproperty\stopviewerlayer\startviewerlayer[#1]}
-\setvalue{\??py:s:\s!effect }#1{\let\dostopproperty\stopeffect \starteffect [#1]}
-\setvalue{\??py:s:\v!negative}#1{\let\dostopproperty\stopnegative \startnegative }
+\setvalue{\??propertystarters\v!layer }#1{\let\properties_stop\stopviewerlayer\startviewerlayer[#1]}
+\setvalue{\??propertystarters\s!effect }#1{\let\properties_stop\stopeffect \starteffect [#1]}
+\setvalue{\??propertystarters\v!negative}#1{\let\properties_stop\stopnegative \startnegative }
\unexpanded\def\property[#1]%
- {\groupedcommand{\dostartproperty{#1}}\dostopproperty}
+ {\groupedcommand{\properties_start{#1}}\properties_stop}
\unexpanded\def\startproperty[#1]%
- {\dostartproperty{#1}}
+ {\properties_start{#1}}
\unexpanded\def\stopproperty
- {\dostopproperty}
+ {\properties_stop}
-\unexpanded\def\dostartproperty#1%
- {\pushmacro\dostopproperty
- \getvalue{\??py:s:\getvalue{\??py#1\c!type}}{#1}}
+\unexpanded\def\properties_start#1%
+ {\pushmacro\properties_stop
+ \getvalue{\??propertystarters\getvalue{\??propertytypes#1}}{#1}}
-\unexpanded\def\dostopproperty
- {\dostopproperty
- \popmacro\dostopproperty}
+\unexpanded\def\properties_stop
+ {\properties_stop
+ \popmacro\properties_stop}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/prop-lay.mkii b/Master/texmf-dist/tex/context/base/prop-lay.mkii
index aeec94bb296..77c48ca6ed2 100644
--- a/Master/texmf-dist/tex/context/base/prop-lay.mkii
+++ b/Master/texmf-dist/tex/context/base/prop-lay.mkii
@@ -5,7 +5,7 @@
%D subtitle=Layers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/prop-mis.mkii b/Master/texmf-dist/tex/context/base/prop-mis.mkii
index d8e9ab17393..47fb9ea0661 100644
--- a/Master/texmf-dist/tex/context/base/prop-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/prop-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Miscelaneous,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-1.mkii b/Master/texmf-dist/tex/context/base/regi-8859-1.mkii
index c291b029ad2..00439ae9e3e 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-1.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-1.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-1 (West European),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-10.mkii b/Master/texmf-dist/tex/context/base/regi-8859-10.mkii
index 79d74d952ac..6646860342a 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-10.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-10.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-10 (Nordic),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-13.mkii b/Master/texmf-dist/tex/context/base/regi-8859-13.mkii
index a6dbe376f01..f1b1dbe7870 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-13.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-13.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-13 (Baltic),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-15.mkii b/Master/texmf-dist/tex/context/base/regi-8859-15.mkii
index cf788d3f3b3..1455161c30e 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-15.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-15.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-15 (West European),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-16.mkii b/Master/texmf-dist/tex/context/base/regi-8859-16.mkii
index 96f0a15d462..f284c4116e7 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-16.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-16.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-16 (Romanian),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-2.mkii b/Master/texmf-dist/tex/context/base/regi-8859-2.mkii
index 81fe8419ed5..9efc27a7968 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-2.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-2.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-2 (East European),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-3.mkii b/Master/texmf-dist/tex/context/base/regi-8859-3.mkii
index dcb8be67f24..99fa66ac313 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-3.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-3.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-3 (South European),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-4.mkii b/Master/texmf-dist/tex/context/base/regi-8859-4.mkii
index 3ebe66a137e..c7adf34710e 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-4.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-4.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-4 (North European),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-5.mkii b/Master/texmf-dist/tex/context/base/regi-8859-5.mkii
index 531226433c1..807d74640b4 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-5.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-5.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-5 (Cyrillic),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-7.mkii b/Master/texmf-dist/tex/context/base/regi-8859-7.mkii
index 80259be6508..1c8197a4270 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-7.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-7.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-7 (Greek),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-8859-9.mkii b/Master/texmf-dist/tex/context/base/regi-8859-9.mkii
index 8460d739b1c..60757b2e684 100644
--- a/Master/texmf-dist/tex/context/base/regi-8859-9.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-8859-9.mkii
@@ -5,7 +5,7 @@
%D subtitle=iso-8859-9 (Turkish),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-cp1250.mkii b/Master/texmf-dist/tex/context/base/regi-cp1250.mkii
index b92eb5e31a2..c13ee53e2c1 100644
--- a/Master/texmf-dist/tex/context/base/regi-cp1250.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-cp1250.mkii
@@ -5,7 +5,7 @@
%D subtitle=cp1250 (East European),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-cp1251.mkii b/Master/texmf-dist/tex/context/base/regi-cp1251.mkii
index 60f04170b31..66576bd16be 100644
--- a/Master/texmf-dist/tex/context/base/regi-cp1251.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-cp1251.mkii
@@ -5,7 +5,7 @@
%D subtitle=cp1251 (Cyrillic),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-cp1252.mkii b/Master/texmf-dist/tex/context/base/regi-cp1252.mkii
index 9a54f178f3e..316d694a67e 100644
--- a/Master/texmf-dist/tex/context/base/regi-cp1252.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-cp1252.mkii
@@ -5,7 +5,7 @@
%D subtitle=cp1252 (West European),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-cp1253.mkii b/Master/texmf-dist/tex/context/base/regi-cp1253.mkii
index 24ec45eac5e..05d53c1298e 100644
--- a/Master/texmf-dist/tex/context/base/regi-cp1253.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-cp1253.mkii
@@ -5,7 +5,7 @@
%D subtitle=cp1253 (Greek),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-cp1254.mkii b/Master/texmf-dist/tex/context/base/regi-cp1254.mkii
index 4dd509b9d69..73f8f270820 100644
--- a/Master/texmf-dist/tex/context/base/regi-cp1254.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-cp1254.mkii
@@ -5,7 +5,7 @@
%D subtitle=cp1254 (Turkish),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-cp1257.mkii b/Master/texmf-dist/tex/context/base/regi-cp1257.mkii
index 0790ef7344d..4c9cb56f059 100644
--- a/Master/texmf-dist/tex/context/base/regi-cp1257.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-cp1257.mkii
@@ -5,7 +5,7 @@
%D subtitle=cp1257 (Windows Baltic),
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-cyp.mkii b/Master/texmf-dist/tex/context/base/regi-cyp.mkii
index 7d134df50be..3f45ace2307 100644
--- a/Master/texmf-dist/tex/context/base/regi-cyp.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-cyp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Cyrillic Plus,
%D author=...,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-cyr.mkii b/Master/texmf-dist/tex/context/base/regi-cyr.mkii
index 1e84b9cba87..1910c0e7cb3 100644
--- a/Master/texmf-dist/tex/context/base/regi-cyr.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-cyr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Cyrillic,
%D author=...,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-def.mkii b/Master/texmf-dist/tex/context/base/regi-def.mkii
index e26709c77e7..3af0c9d3c5d 100644
--- a/Master/texmf-dist/tex/context/base/regi-def.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Default Character Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen \& Ton Otten]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-ibm.mkii b/Master/texmf-dist/tex/context/base/regi-ibm.mkii
index 1fad9545aa9..5756e77054f 100644
--- a/Master/texmf-dist/tex/context/base/regi-ibm.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-ibm.mkii
@@ -5,7 +5,7 @@
%D subtitle=The Good Old MSDOS IBM codepage,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-ini.lua b/Master/texmf-dist/tex/context/base/regi-ini.lua
index a440b65771a..ec6f812ccb1 100644
--- a/Master/texmf-dist/tex/context/base/regi-ini.lua
+++ b/Master/texmf-dist/tex/context/base/regi-ini.lua
@@ -12,11 +12,13 @@ if not modules then modules = { } end modules ['regi-ini'] = {
runtime.</p>
--ldx]]--
-local utfchar = utf.char
+local utfchar, utfgsub = utf.char, utf.gsub
local char, gsub, format = string.char, string.gsub, string.format
local next = next
local insert, remove = table.insert, table.remove
+
+local allocate = utilities.storage.allocate
local sequencers = utilities.sequencers
local textlineactions = resolvers.openers.helpers.textlineactions
local setmetatableindex = table.setmetatableindex
@@ -33,10 +35,15 @@ local report_translating = logs.reporter("regimes","translating")
regimes = regimes or { }
local regimes = regimes
-local mapping = {
+local mapping = allocate {
utf = false
}
+local backmapping = allocate {
+}
+
+-- regimes.mapping = mapping
+
local synonyms = { -- backward compatibility list
["windows-1250"] = "cp1250",
@@ -109,7 +116,17 @@ local function loadregime(mapping,regime)
return vector
end
-setmetatableindex(mapping, loadregime)
+local function loadreverse(t,k)
+ local t = { }
+ for k, v in next, mapping[k] do
+ t[v] = k
+ end
+ backmapping[k] = t
+ return t
+end
+
+setmetatableindex(mapping, loadregime)
+setmetatableindex(backmapping, loadreverse)
local function translate(line,regime)
if line and #line > 0 then
@@ -121,6 +138,19 @@ local function translate(line,regime)
return line
end
+local function toregime(vector,str,default) -- toregime('8859-1',"abcde Ä","?")
+ local t = backmapping[vector]
+ local m = getmetatable(t)
+ setmetatableindex(t, function(t,k)
+ local v = default or "?"
+ t[k] = v
+ return v
+ end)
+ str = utfgsub(str,".",t)
+ setmetatable(t,m)
+ return str
+end
+
local function disable()
currentregime = "utf"
sequencers.disableaction(textlineactions,"regimes.process")
@@ -136,6 +166,7 @@ local function enable(regime)
end
end
+regimes.toregime = toregime
regimes.translate = translate
regimes.enable = enable
regimes.disable = disable
@@ -145,8 +176,8 @@ regimes.disable = disable
local level = 0
-function regimes.process(str)
- if level == 0 then
+function regimes.process(str,filename,currentline,noflines,coding)
+ if level == 0 and coding ~= "utf-8" then
str = translate(str,currentregime)
if trace_translating then
report_translating("utf: %s",str)
@@ -213,6 +244,8 @@ end
-- return regime and synonyms[regime] or regime or currentregime
-- end
--
+-- commands.setregimesynonym = regimes.setsynonym
+--
-- function commands.trueregimename(regime)
-- context(regimes.truename(regime))
-- end
diff --git a/Master/texmf-dist/tex/context/base/regi-ini.mkii b/Master/texmf-dist/tex/context/base/regi-ini.mkii
index 3cdfe2763c2..1122ce18ac9 100644
--- a/Master/texmf-dist/tex/context/base/regi-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-ini.mkiv b/Master/texmf-dist/tex/context/base/regi-ini.mkiv
index 41f00142663..651e2f13cb1 100644
--- a/Master/texmf-dist/tex/context/base/regi-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/regi-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Regime Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -34,7 +34,7 @@
% {\dodoubleargument\dodefineregimesynonym}
%
% \def\dodefineregimesynonym[#1][#2]%
-% {\ctxlua{regimes.setsynonym("#1","#2")}}
+% {\ctxcommand{setregimesynonym("#1","#2")}}
%
% \def\trueregimename#1%
% {\ctxcommand{trueregimename("#1")}}
diff --git a/Master/texmf-dist/tex/context/base/regi-mac.mkii b/Master/texmf-dist/tex/context/base/regi-mac.mkii
index b3c281ec0b0..30f57ab18cb 100644
--- a/Master/texmf-dist/tex/context/base/regi-mac.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-mac.mkii
@@ -5,7 +5,7 @@
%D subtitle=Mac Encoding,
%D author={Michel Bovani \& Adam Lindsay \& Hans Hagen},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-syn.mkii b/Master/texmf-dist/tex/context/base/regi-syn.mkii
index 7a8a9c146ca..09fd59deeb5 100644
--- a/Master/texmf-dist/tex/context/base/regi-syn.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-syn.mkii
@@ -5,7 +5,7 @@
%D subtitle=Synonyms,
%D author=Mojca Miklavec \& Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-uni.mkii b/Master/texmf-dist/tex/context/base/regi-uni.mkii
index c4d9521e9d0..fe2f99a4f2d 100644
--- a/Master/texmf-dist/tex/context/base/regi-uni.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-uni.mkii
@@ -5,7 +5,7 @@
%D subtitle=Unicode,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/regi-utf.mkii b/Master/texmf-dist/tex/context/base/regi-utf.mkii
index b3423b15af5..09926a17231 100644
--- a/Master/texmf-dist/tex/context/base/regi-utf.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-utf.mkii
@@ -5,7 +5,7 @@
%D subtitle=UTF-8,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -29,7 +29,7 @@
% Ññ
% ÒÓÔÕÖòóôõö
% Øø
-% ÙÚÛÜùúû
+% ÙÚÛÜùúûü
% Ãýÿ
% ß
% Ţţ
diff --git a/Master/texmf-dist/tex/context/base/regi-vis.mkii b/Master/texmf-dist/tex/context/base/regi-vis.mkii
index d1071354f96..1807bdc93df 100644
--- a/Master/texmf-dist/tex/context/base/regi-vis.mkii
+++ b/Master/texmf-dist/tex/context/base/regi-vis.mkii
@@ -5,7 +5,7 @@
%D subtitle=viscii,
%D author=script-generated,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-abr-01.tex b/Master/texmf-dist/tex/context/base/s-abr-01.tex
index e4927814cea..d6685bd71ad 100644
--- a/Master/texmf-dist/tex/context/base/s-abr-01.tex
+++ b/Master/texmf-dist/tex/context/base/s-abr-01.tex
@@ -5,7 +5,7 @@
%D subtitle=General Abbreviations 1,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -24,6 +24,8 @@
\logo [MKIII] {MkIII} % joke
\logo [MKIV] {MkIV}
\logo [MKVI] {MkVI}
+\logo [MPII] {MpII}
+\logo [MPIV] {MpIV}
%logo [FGA] {fga}
%logo [FGBBS] {fgbbs}
@@ -45,6 +47,7 @@
\logo [BMP] {bmp}
\logo [BSD] {bsd}
\logo [CCODE] {C}
+\logo [CPLUSPLUS] {C\high{++}}
\logo [CALCMATH] {CalcMath}
\logo [CD] {cd}
\logo [CPU] {cpu}
@@ -134,6 +137,7 @@
\logo [LATEX] {\LaTeX}
\logo [LATEXTE] {\LaTeX2e}
\logo [LATEXTN] {\LaTeX2.09}
+\logo [LCD] {lcd}
\logo [LINUX] {linux}
\logo [LISP] {Lisp}
\logo [LPEG] {lpeg}
@@ -159,7 +163,7 @@
\logo [MPTOPDF] {mptopdf}
\logo [MPLIB] {mplib}
\logo [MSDOS] {msdos}
-\logo [MICROSOFT] {MicroSoft}
+\logo [MICROSOFT] {Microsoft}
\logo [MSWINDOWS] {MS~Windows}
\logo [MTXRUN] {mtxrun}
\logo [MTXTOOLS] {mtxtools}
@@ -176,6 +180,8 @@
\logo [OVF] {ovf}
\logo [PASCAL] {Pascal}
\logo [PCTEX] {pc\TeX}
+\logo [PFA] {pfa}
+\logo [PFB] {pfb}
\logo [PDF] {pdf}
\logo [PDFETEX] {pdfe\TeX}
\logo [PDFTEX] {pdf\TeX}
@@ -244,6 +250,7 @@
\logo [TPIC] {tpic}
\logo [TPM] {tpm}
\logo [TRUETYPE] {TrueType}
+\logo [TTC] {ttc}
\logo [TTF] {ttf}
\logo [TUG] {tug}
\logo [TUGBOAT] {Tug\-Boat}
@@ -257,7 +264,7 @@
\logo [USA] {usa}
\logo [USENET] {usenet}
\logo [UTF] {utf}
-\logo [UTF] {utf}
+\logo [USB] {usb}
\logo [VF] {vf}
\logo [WDT] {wdt}
\logo [WEB] {web}
@@ -267,6 +274,7 @@
\logo [WINNT] {WinNT}
\logo [WINNX] {Win9x}
\logo [WWW] {www}
+\logo [WTHREEC] {W3C}
\logo [WYSIWYG] {wysiwyg}
\logo [XDVI] {Xdvi}
\logo [XETEX] {\XeTeX}
diff --git a/Master/texmf-dist/tex/context/base/s-abr-02.tex b/Master/texmf-dist/tex/context/base/s-abr-02.tex
index 005559ef366..8bb6a28986a 100644
--- a/Master/texmf-dist/tex/context/base/s-abr-02.tex
+++ b/Master/texmf-dist/tex/context/base/s-abr-02.tex
@@ -5,7 +5,7 @@
%D subtitle=General Abbreviations 2,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-abr-03.tex b/Master/texmf-dist/tex/context/base/s-abr-03.tex
index 43068b9a5f6..8247b68a916 100644
--- a/Master/texmf-dist/tex/context/base/s-abr-03.tex
+++ b/Master/texmf-dist/tex/context/base/s-abr-03.tex
@@ -5,7 +5,7 @@
%D subtitle=General Abbreviations 3,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-abr-04.tex b/Master/texmf-dist/tex/context/base/s-abr-04.tex
index 98e76c86fc3..ab3dc94cdc9 100644
--- a/Master/texmf-dist/tex/context/base/s-abr-04.tex
+++ b/Master/texmf-dist/tex/context/base/s-abr-04.tex
@@ -5,7 +5,7 @@
%D subtitle=General Abbreviations 1,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-art-01.mkiv b/Master/texmf-dist/tex/context/base/s-art-01.mkiv
new file mode 100644
index 00000000000..10b4de9ab1c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/s-art-01.mkiv
@@ -0,0 +1,36 @@
+\startmodule[art-01]
+
+% \showframe
+
+\setuplayout
+ [\c!topspace=2cm,
+ \c!bottomspace=2.5cm,
+ \c!width=\v!middle,
+ \c!height=\v!middle,
+ \c!footer=0pt]
+
+\setupbodyfont
+ [dejavu]
+
+\setupwhitespace
+ [\v!big]
+
+\setuphead
+ [\v!chapter]
+ [\c!style=\bfc,
+ \c!headerstate=\v!high]
+
+\setuphead
+ [\v!section]
+ [\c!style=\bfb]
+
+\setuphead
+ [\v!subsection]
+ [\c!style=\bfa]
+
+\setuphead
+ [\v!subsubsection]
+ [\c!style=\bf,
+ \c!after=]
+
+\stopmodule
diff --git a/Master/texmf-dist/tex/context/base/s-cdr-01.tex b/Master/texmf-dist/tex/context/base/s-cdr-01.tex
index 164d812856a..b0bced9da09 100644
--- a/Master/texmf-dist/tex/context/base/s-cdr-01.tex
+++ b/Master/texmf-dist/tex/context/base/s-cdr-01.tex
@@ -5,7 +5,7 @@
%D subtitle=CDROM Cover,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-chi-00.mkii b/Master/texmf-dist/tex/context/base/s-chi-00.mkii
index bec86f6d2f0..fb8d47603be 100644
--- a/Master/texmf-dist/tex/context/base/s-chi-00.mkii
+++ b/Master/texmf-dist/tex/context/base/s-chi-00.mkii
@@ -6,7 +6,7 @@
%D author=Hans Hagen,
%D date=\currentdate,
%D suggestions=Wang Lei,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-def-01.mkiv b/Master/texmf-dist/tex/context/base/s-def-01.mkiv
index c54cee764f3..1c8ee9469d2 100644
--- a/Master/texmf-dist/tex/context/base/s-def-01.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-def-01.mkiv
@@ -3,7 +3,7 @@
\unprotect
\startsetups defaults:frontpart:pagenumbers:roman
- \definestructureconversionset[\c!frontpart:\c!pagenumber][][romannumerals]
+ \defineconversionset[\c!frontpart:\c!pagenumber][][romannumerals]
\setupuserpagenumber[\c!way=\v!byblock]
\stopsetups
diff --git a/Master/texmf-dist/tex/context/base/s-faq-00.tex b/Master/texmf-dist/tex/context/base/s-faq-00.tex
index 11859936c8d..84055491f29 100644
--- a/Master/texmf-dist/tex/context/base/s-faq-00.tex
+++ b/Master/texmf-dist/tex/context/base/s-faq-00.tex
@@ -5,7 +5,7 @@
%D subtitle=FAQ Common Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-faq-01.tex b/Master/texmf-dist/tex/context/base/s-faq-01.tex
index 8c116e0f78e..f6ee3ce0618 100644
--- a/Master/texmf-dist/tex/context/base/s-faq-01.tex
+++ b/Master/texmf-dist/tex/context/base/s-faq-01.tex
@@ -5,7 +5,7 @@
%D subtitle=FAQ Interactive Version,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-faq-02.tex b/Master/texmf-dist/tex/context/base/s-faq-02.tex
index 02287bde413..92aa1eca2de 100644
--- a/Master/texmf-dist/tex/context/base/s-faq-02.tex
+++ b/Master/texmf-dist/tex/context/base/s-faq-02.tex
@@ -5,7 +5,7 @@
%D subtitle=FAQ Paper Version,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-faq-03.tex b/Master/texmf-dist/tex/context/base/s-faq-03.tex
index 4f556f71348..b1e1ef2c2e0 100644
--- a/Master/texmf-dist/tex/context/base/s-faq-03.tex
+++ b/Master/texmf-dist/tex/context/base/s-faq-03.tex
@@ -5,7 +5,7 @@
%D subtitle=FAQ General Framework,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-01.mkii b/Master/texmf-dist/tex/context/base/s-fnt-01.mkii
index 69c8efab966..aedcf913d97 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-01.mkii
+++ b/Master/texmf-dist/tex/context/base/s-fnt-01.mkii
@@ -5,7 +5,7 @@
%D subtitle=Font Environment 1,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-10.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-10.mkiv
index 07f5d47299c..0d4a608a485 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-10.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-10.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Listing Glyphs in Large Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -124,7 +124,7 @@ end
\font\TestFontB=#1 at #2
\setuplayout[style=\TestFontA]
\setupheadertexts[]
- \setupfootertexts[#1 -- \pagenumber]
+ \setupfootertexts[#1\space\endash\space\pagenumber]
\setuplayout[width=middle,height=middle,topspace=1cm,backspace=1cm,header=1cm,footer=2cm]
\TestFontB \setupinterlinespace[line=1.2\dimexpr#2\relax] \raggedcenter
\nonknuthmode
@@ -135,15 +135,16 @@ end
\page
\egroup}
-% \doifnotmode{demo} {\endinput}
+\doifnotmode{demo} {\endinput}
\starttext
-\ShowCompleteFont{name:dejavusansmono}{10pt}{1}
+% \ShowCompleteFont{name:dejavusansmono}{10pt}{1}
% \ShowCompleteFont{name:dejavuserif}{10pt}{2}
% \ShowCompleteFont{name:officinasansbookitcregular}{10pt}{2}
% \ShowCompleteFont{name:officinaserifbookitcregular}{10pt}{2}
% \ShowCompleteFont{name:serpentineserifeflight}{10pt}{2}
+\ShowCompleteFont{name:lmroman10-regular}{10pt}{1}
% \ShowCompleteFont{name:lmtypewriter10-regular}{10pt}{2}
% \ShowCompleteFont{lt55485}{10pt}{2}
% \ShowCompleteFont{lmr10}{10pt}{2}
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-11.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-11.mkiv
index f2171ecd05a..a91e069ea64 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-11.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-11.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Listing Installed Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-20.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-20.mkiv
index a57c0ba4758..a78f62555c6 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-20.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-20.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Tracing Feature Application (1),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -21,7 +21,8 @@
% font=husayni,
% sample={ببب بببب ببببب بببببب}]
-\def\checkedfeature#1#2{\ifnum\featureattribute{#1}=\zerocount#2\else#1\fi}
+\def\checkedotftrackerfeature #1{otftracker-\ifnum\featureattribute{otftracker-#1}=\zerocount default\else#1\fi}
+\def\checkedotftrackerdirection#1{\csname otftracker-direction-\ifcsname otftracker-direction-#1\endcsname#1\else default\fi\endcsname}
% we can consider adding a dir key to features
@@ -49,7 +50,7 @@
\definefontfeature
[otftracker-husayni]
[analyze=yes,mode=node,
- language=dflt,script=arab,ccmp=no,
+ language=dflt,script=arab,
init=yes,medi=yes,fina=yes,
rlig=yes,
ccmp=yes,
@@ -57,12 +58,13 @@
ss05=yes, % full Jiim stacking
ss09=yes, % full Haa stacking
ss10=yes, % partial dipped Miim
- % ss11=yes, % full dipped Miim
ss13=yes, % full stacked Miim
ss15=yes, % full stacked Laam-on-Miim
ss17=yes, % full stacked Ayn-on-Miim
ss19=yes, % LM_im
- ss24=yes,ss25=yes,ss26=yes, % BX, LH_im, full Yaa.final specials
+ ss24=yes, % BX specials
+ ss25=yes, % LH_im specials
+ ss26=yes, % full Yaa.final specials
ss27=yes, % partial thin Miim.final
ss31=yes, % partial Raa.final contexts
ss34=yes, % partial Raa.final contexts
@@ -73,10 +75,7 @@
ss39=yes, % high and low Baa strings
ss40=yes, % diagonal entry
ss41=yes, % initial alternates
- % js06=yes,js08=yes,js10=yes,js11=yes,js17=yes,
- % ttwl=yes,
- mark=yes,mkmk=yes,
- kern=yes,curs=yes]
+ mark=yes,mkmk=yes,kern=yes,curs=yes]
\definefontfeature
[otftracker-simplenaskhi]
@@ -84,21 +83,22 @@
language=dflt,script=arab,
init=yes,medi=yes,fina=yes,calt=yes,
rlig=yes,liga=yes,dlig=yes,
- mark=yes,mkmk=yes,curs=yes]
+ mark=yes,mkmk=yes,kern=yes,curs=yes]
\setvalue{otftracker-direction-arabtype}{-1}
\setvalue{otftracker-direction-husayni}{-1}
\setvalue{otftracker-direction-simplenaskhi}{-1}
+\setvalue{otftracker-direction-default}{0}
\setvariables
[otftracker]
[font=Serif,
- features=\checkedfeature{otftracker-\getvariable{otftracker}{font}}{otftracker-default},
+ features=\checkedotftrackerfeature{\getvariable{otftracker}{font}},
+ direction=\checkedotftrackerdirection{\getvariable{otftracker}{font}},
size=48pt,
figure=,
title=Feature Check,
sample=no sample,
- direction=\executeifdefined{otftracker-direction-\getvariable{otftracker}{font}}{0},
set=\setups{otftracker}]
\setuplayout
@@ -138,3 +138,23 @@
{\getvariable{otftracker}{sample}}
\stoptext
\stopsetups
+
+\continueifinputfile{s-fnt-20.mkiv}
+
+\usemodule[art-01]
+
+\setupbodyfont
+% [cambria]
+ [dejavu]
+
+\starttext
+
+\setvariables
+ [otftracker]
+ [font=Serif,
+ size=48pt,
+ figure=,
+ title=Feature Check,
+ sample={affiliation}]
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-21.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-21.mkiv
index dd8de398d0b..a488546794f 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-21.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-21.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Tracing Feature Application (2),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-23.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-23.mkiv
index 1dc7367a462..17fc5463d86 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-23.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-23.mkiv
@@ -5,24 +5,23 @@
%D subtitle=Tracing Feature Application (3),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
-% last_data was written wrong so it needs checking
-
\startluacode
- local fontdata = fonts.hashes.identifiers
- local otfhandler = fonts.handlers.otf --- will be moduledata
+ moduledata.fonts = moduledata.fonts or { }
- local last_data = nil
+ local fontdata = fonts.hashes.identifiers
- local format = string.format
+ local last_data = nil -- still relevant
+ local format = string.format
- function otfhandler.show_shape(n)
+ function moduledata.fonts.show_shape(n)
local tfmdata = fontdata[font.current()]
+ -- local _, tfmdata = fonts.definers.define { name = fontname, size = fontsize }
last_data = tfmdata
local charnum = tonumber(n)
if not charnum then
@@ -200,21 +199,23 @@
context("no such shape: %s",n)
end
end
- function otfhandler.show_all_shapes(start,stop)
+
+ function moduledata.fonts.show_all_shapes()
local tfmdata = fontdata[font.current()]
+ -- local _, tfmdata = fonts.definers.define { name = fontname, size = fontsize }
last_data = tfmdata
- start, stop = start or "\\startTEXpage\\gobbleoneargument", stop or "\\stopTEXpage"
local unicodes, descriptions = tfmdata.unicodes, tfmdata.descriptions
for unicode, description in fonts.iterators.descriptions(tfmdata) do
local name = description.name
- context("%s{%s}%%",start,unicode)
- context("\\writestatus{glyph}{U+%04X -> %s}%%",unicode,name)
- otfhandler.show_shape(unicode)
- context(stop)
+ context.StartShowGlyphShape(unicode)
+ moduledata.fonts.show_shape(unicode)
+ context.StopShowGlyphShape()
end
end
- function otfhandler.show_shape_field(unicode,name)
+
+ function moduledata.fonts.show_shape_field(unicode,name)
local tfmdata = last_data or fontdata[font.current()]
+ -- local _, tfmdata = fonts.definers.define { name = fontname, size = fontsize }
local d = tfmdata.descriptions[unicode]
if d then
if name == "unicode" then
@@ -229,15 +230,14 @@
end
\stopluacode
-\setupcolors
- [state=start]
+% we can move all to lua (cld)
\def\GetGlyphField#1#2%
- {\ctxlua{fonts.handlers.otf.show_shape_field(#1,"#2")}}
+ {\ctxlua{moduledata.fonts.show_shape_field(#1,"#2")}}
\def\StartShowGlyphShape#1%
{\startTEXpage
- \nonknuthmode
+ \nonknuthmode % default anyway
\def\GlyphUnicode{#1}}
\def\StopShowGlyphShape
@@ -249,20 +249,20 @@
{\begingroup
\definedfont[#1 at #2]%
\obeyMPboxdepth
- \ctxlua{fonts.handlers.otf.show_shape("#3")}%
+ \ctxlua{moduledata.fonts.show_shape("#3")}%
\endgroup}
\def\ShowAllGlyphShapes#1#2% name size
{\begingroup
- \nonknuthmode
+ \nonknuthmode % default anyway
\definedfont[#1 at #2]%
- \ctxlua{fonts.handlers.otf.show_all_shapes("\\StartShowGlyphShape","\\StopShowGlyphShape")}%
+ \ctxlua{moduledata.fonts.show_all_shapes()}%
\endgroup}
\setupcolors
[state=start]
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-fnt-23.mkiv}
\starttext
@@ -276,15 +276,15 @@
\switchtobodyfont[cambria,10pt]
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math} {40bp}{0x00066} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math} {40bp}{0x1D453} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math} {40bp}{0x1D43F} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math}{100bp}{0x1D444} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math}{100bp}{0x1D447} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math}{100bp}{0x02112} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math}{100bp}{0x1D432} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math}{100bp}{0x1D43D} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math}{100bp}{0x1D44A} \stopTEXpage
-\startTEXpage[offset=10pt] \ShowGlyphShape{name:cambria-math}{100bp}{0x1D45D} \stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math} {40bp}{0x00066}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math} {40bp}{0x1D453}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math} {40bp}{0x1D43F}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{100bp}{0x1D444}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{100bp}{0x1D447}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{100bp}{0x02112}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{100bp}{0x1D432}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{100bp}{0x1D43D}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{100bp}{0x1D44A}\stopTEXpage
+\startTEXpage[offset=0pt]\ShowGlyphShape{name:cambria-math}{100bp}{0x1D45D}\stopTEXpage
\stoptext
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-24.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-24.mkiv
index de485557b91..2c0022e5c46 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-24.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-24.mkiv
@@ -5,7 +5,7 @@
%D subtitle=CJK Glyph Combination Testing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-25.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-25.mkiv
deleted file mode 100644
index 159d8325d50..00000000000
--- a/Master/texmf-dist/tex/context/base/s-fnt-25.mkiv
+++ /dev/null
@@ -1,198 +0,0 @@
-%D \module
-%D [ file=s-fnt-25,
-%D version=2009.01.25,
-%D title=\CONTEXT\ Style File,
-%D subtitle=Math Glyph Checking,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ macro||package and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-\def\enableshowmathfontvirtual
- {\ctxlua{fonts.constructors.autocleanup=false}}
-
-\def\showmathfontcharacters
- {\dodoubleempty\doshowmathfontcharacters}
-
-\def\doshowmathfontcharacters[#1][#2]%
- {\begingroup
- \dontcomplain
- \doifelsenothing{#1}
- {\definedfont[MathRoman*math-text]}
- {\definedfont[#1]}%
- \doifelsenothing{#2}
- {\ctxlua{document.showmathfont(font.current())}}
- {\def\dodoshowmathfontcharacters##1{\ctxlua{document.showmathfont(font.current(),##1)}}%
- \processcommalist[#2]\dodoshowmathfontcharacters}%
- \endgroup}
-
-\def\startmathfontlist
- {\startpacked}
-
-\def\stopmathfontlist
- {\stoppacked}
-
-\def\startmathfontlistentry
- {\blank
- \begingroup}
-
-\def\stopmathfontlistentry
- {\endgroup
- \blank}
-
-\def\mathfontlistentryhexdectit#1#2#3%
- {#1: \char#2\enspace\ruledhbox{\char#2}\enspace#3\par
- \advance\leftskip 1em\relax}
-
-\def\mathfontlistentrywdhtdpic#1#2#3#4%
- {width: #1, height: #2, depth: #3, italic: #4\par}
-
-\def\mathfontlistentryresource#1%
- {virtual: #1\par}
-
-\def\mathfontlistentrynext#1#2%
- {#1~\ruledhbox{\char#2}}
-
-\def\mathfontlistentrynextlist#1%
- {next: #1\par}
-
-\def\fontlistentryvariants#1#2%
- {#1~\ruledhbox{\char#2}}
-
-\def\mathfontlistentryvariantslist#1%
- {variants: #1\par}
-
-\def\mathfontlistentrynextvariantslist#1#2%
- {next: #1 => variants: #2\par}
-
-\def\mathfontlistentryclassname#1#2%
- {mathclass: #1, mathname: #2\par}
-
-\def\mathfontlistentrysymbol#1#2%
- {mathsymbol: #1~\ruledhbox{\char#2}\par}
-
-\startluacode
-local concat = table.concat
-local format, lower = string.format, string.lower
-
-local fontdata = fonts.hashes.identifiers
-
-function document.showmathfont(id,slot)
- local data = characters.data
- local tfmdata = fontdata[id]
- local characters = tfmdata.characters
- local sorted = (slot and { slot }) or table.sortedkeys(characters)
- local virtual, names = tfmdata.properties.virtualized, { }
- if virtual then
- for k, v in ipairs(tfmdata.fonts) do
- local id = v.id
- local name = fontdata[id].properties.name
- names[k] = (name and file.basename(name)) or id
- end
- end
- local round = math.round
- local limited = true
- for _, s in next, sorted do
- if not limited or s < 0xF0000 then
- local char = characters[s]
- if char then
- local info = data[s]
- local cnext, cvert_variants, choriz_variants = char.next, char.vert_variants, char.horiz_variants
- context.startmathfontlistentry()
- context.mathfontlistentryhexdectit(format("U+%05X",s),s,lower(info.description or "no description, private to font"))
- context.mathfontlistentrywdhtdpic(round(char.width or 0),round(char.height or 0),round(char.depth or 0),round(char.italic or 0))
- if virtual then
- local commands = char.commands
- if commands then
- local t = { }
- for i=1,#commands do
- local ci = commands[i]
- if ci[1] == "slot" then
- local fnt, idx = ci[2], ci[3]
- t[#t+1] = format("%s/%0X",names[fnt] or fnt,idx)
- end
- end
- if #t > 0 then
- context.mathfontlistentryresource(concat(t,", "))
- end
- end
- end
- if info.mathclass then
- context.mathfontlistentryclassname(info.mathclass,info.mathname or "no name")
- end
- if info.mathspec then
- for i=1,#info.mathspec do
- context.mathfontlistentryclassname(info.mathspec[i].class,info.mathspec[i].name or "no name")
- end
- end
- if info.mathsymbol then
- context.mathfontlistentrysymbol(format("U+%05X",info.mathsymbol),info.mathsymbol)
- end
- if cnext then
- local t, done = { }, { }
- while cnext do
- if done[cnext] then
- t[#t+1] = "CYCLE"
- break
- else
- done[cnext] = true
- t[#t+1] = context.nested.mathfontlistentrynext(format("U+%05X",cnext),cnext)
- cnext = characters[cnext]
- cvert_variants = cnext.vert_variants or cvert_variants
- choriz_variants = cnext.horiz_variants or choriz_variants
- if cnext then
- cnext = cnext.next
- end
- end
- end
- cnext = t
- end
- if cvert_variants then
- local t = { }
- for k, v in next, cvert_variants do
- t[#t+1] = context.nested.fontlistentryvariants(format("U+%05X",v.glyph),v.glyph)
- end
- cvert_variants = t
- end
- if choriz_variants then
- local t = { }
- for k, v in next, choriz_variants do
- t[#t+1] = context.nested.fontlistentryvariants(format("U+%05X",v.glyph),v.glyph)
- end
- choriz_variants = t
- end
- local cvariants = choriz_variants or cvert_variants
- if cvariants and cnext then
- context.mathfontlistentrynextvariantslist(concat(cnext," => "),concat(cvariants," => "))
- else
- if cnext then
- context.mathfontlistentrynextlist(concat(cnext," => "))
- end
- if cvariants then
- context.mathfontlistentryvariantslist(concat(cvariants," "))
- end
- end
- context.stopmathfontlistentry()
- end
- end
- end
-end
-\stopluacode
-
-\doifnotmode{demo}{\endinput}
-
-\starttext
- \setupbodyfont[cambria, 12pt] \showmathfontcharacters
-% \setupbodyfont[lmvirtual,12pt] \showmathfontcharacters
-% \setupbodyfont[pxvirtual,12pt] \showmathfontcharacters
-% \setupbodyfont[txvirtual,12pt] \showmathfontcharacters
-% \setupbodyfont[palatino, 10pt] \showmathfontcharacters
-% \setupbodyfont[mathtimes,12pt] \showmathfontcharacters
-% \setupbodyfont[stix, 12pt] \showmathfontcharacters
-% \setupbodyfont[xits, 12pt] \showmathfontcharacters
-% \setupbodyfont[lucida, 12pt] \showmathfontcharacters
-\stoptext
-
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-26.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-26.mkiv
index 18d1d657333..904091f0671 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-26.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-26.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Goodies Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -14,7 +14,7 @@
\startluacode
function document.show_goodies_stylistics(name)
- local goodies = fonts.goodies.get(name)
+ local goodies = fonts.goodies.load(name)
local stylistics = goodies and goodies.stylistics
if stylistics then
local col, row, type = context.NC, context.NR, context.type
@@ -28,7 +28,7 @@
end
function document.show_goodies_featuresets(name)
- local goodies = fonts.goodies.get(name)
+ local goodies = fonts.goodies.load(name)
local featuresets = goodies and goodies.featuresets
if featuresets then
local col, row, type = context.NC, context.NR, context.type
@@ -47,7 +47,7 @@
end
function document.show_goodies_colorschemes(name)
- local goodies = fonts.goodies.get(name)
+ local goodies = fonts.goodies.load(name)
local colorschemes = goodies and goodies.colorschemes
if colorschemes then
local col, row, type = context.NC, context.NR, context.type
@@ -71,4 +71,12 @@
\def\showgoodiesfeaturesets #1{\ctxlua{document.show_goodies_featuresets ("#1")}}
\def\showgoodiescolorschemes#1{\ctxlua{document.show_goodies_colorschemes("#1")}}
-\endinput
+\continueifinputfile{s-fnt-26.mkiv}
+
+\starttext
+
+ \showgoodiesstylistics {husayni}
+ \showgoodiesfeaturesets {husayni}
+ \showgoodiescolorschemes{husayni}
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-28.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-28.mkiv
index 839c7d4ae44..039cc6ca8ea 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-28.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-28.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Tracing Names,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -13,7 +13,7 @@
\startluacode
function fonts.tracers.files(goodyfile)
- local goodies = fonts.goodies.get(goodyfile)
+ local goodies = fonts.goodies.load(goodyfile)
if goodies then
local files = goodies.files
if files and files.list then
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-29.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-29.mkiv
index 0b63635b2ae..0378550e86a 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-29.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-29.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Tracing Shapes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-30.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-30.mkiv
index c824b2b6ccf..1de27aed378 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-30.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-30.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Showing Character Data,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-31.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-31.mkiv
index 3cd689d9719..171f991db97 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-31.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-31.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Comparing Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -45,18 +45,25 @@ function fonts.tracers.coverage(fontfiles,pattern) -- todo: patterns
names[i] = fontname
end
+ local t = { }
+
context.starttabulate {"|Tr" .. string.rep("|l",#names) .. "|" }
- for i=1,#names do
+ for i=1,#fontfiles do
+ local file = fontfiles[i]
+ t[#t+1] = i .. "=" .. file
context.NC()
context(i)
context.NC()
- -- context.getvalue(names[i])
- context.type(fontfiles[i])
+ context.type(file)
context.NC()
context.NR()
end
context.stoptabulate()
+ context.setupfootertexts {
+ table.concat(t," ")
+ }
+
context.starttabulate {"|Tl" .. string.rep("|c",#names) .. "|Tl|" }
context.NC()
context.type("unicode")
@@ -91,10 +98,13 @@ end
\stopluacode
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-fnt-31.mkiv}
\setupbodyfont[10pt]
+\setupfootertexts
+ [style=\ttx]
+
\setuplayout
[backspace=1cm,
topspace=1cm,
@@ -150,15 +160,19 @@ end
% }
% \stopluacode
-\loadfontgoodies[px-math]
-\loadfontgoodies[lm-math]
+% \loadfontgoodies[px-math]
+% \loadfontgoodies[lm-math]
\startluacode
fonts.tracers.coverage {
"cambria.ttc(Cambria Math)",
"xits-math.otf",
- "LMMath10-Regular@lmroman10-math",
- "pxmath@px-math",
+ "stixmath-regular.otf",
+ "lmmath-regular",
+ -- "LMMath10-Regular@lmroman10-math",
+ -- "pxmath@px-math",
+ -- "lucida-math.otf",
+ -- "lucida-math-demi.otf",
-- "LinLibertine_Re-4.7.5.otf",
}
\stopluacode
diff --git a/Master/texmf-dist/tex/context/base/s-fnt-32.mkiv b/Master/texmf-dist/tex/context/base/s-fnt-32.mkiv
index ea55e9e7458..5ffbb2ac5d8 100644
--- a/Master/texmf-dist/tex/context/base/s-fnt-32.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-fnt-32.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Unicode Math Scripts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-fonts-missing.mkiv b/Master/texmf-dist/tex/context/base/s-fonts-missing.mkiv
new file mode 100644
index 00000000000..ef45383a01a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/s-fonts-missing.mkiv
@@ -0,0 +1,79 @@
+%D \module
+%D [ file=s-fonts-missing,
+%D version=2011.10.30,
+%D title=\CONTEXT\ Style File,
+%D subtitle=Some Missing Character Info,
+%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.
+
+\startluacode
+
+ moduledata.fonts = moduledata.fonts or { }
+ moduledata.fonts.tracers = moduledata.fonts.tracers or { }
+ moduledata.fonts.tracers.missing = moduledata.fonts.tracers.missing or { }
+
+ function moduledata.fonts.tracers.missing.legend()
+ local c = fonts.hashes.identifiers[font.current()]
+ local p = c.properties.privates
+ if p then
+ context.starttabulate { "|Tl|c|c|" }
+ context.NC()
+ context.bold("name")
+ context.NC()
+ context.bold("character")
+ context.NC()
+ context.bold("node")
+ context.NC()
+ context.NR()
+ for k, v in table.sortedhash(p) do
+ context.NC()
+ context(k)
+ context.NC()
+ context.dontleavehmode()
+ context.char(v)
+ context.NC()
+ context.dontleavehmode()
+ commands.getprivatechar(k)
+ context.NC()
+ context.NR()
+ end
+ context.stoptabulate()
+ end
+ end
+
+\stopluacode
+
+\def\ModuleFontsTracersMissingLegend
+ {\ctxlua{moduledata.fonts.tracers.missing.legend()}}
+
+\continueifinputfile{s-fonts-missing.mkiv}
+
+\enabletrackers[fonts.missing=replace] % the sooner, the more efficient
+
+% \usemodule[art-01]
+
+% \definefontfeature[default][default][missing=yes] % automatically when enabled
+
+\starttext
+
+ \ModuleFontsTracersMissingLegend
+
+ ½ ⅓ ¼ ⅕ ⅙ ⅛
+
+ \startluacode
+ for i=1,1000 do
+ local c = characters.data[i]
+ if c then
+ context.char(c.unicodeslot)
+ context.space()
+ end
+ end
+ \stopluacode
+
+\stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/s-fonts-tables.lua b/Master/texmf-dist/tex/context/base/s-fonts-tables.lua
new file mode 100644
index 00000000000..dcf189f3206
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/s-fonts-tables.lua
@@ -0,0 +1,319 @@
+if not modules then modules = { } end modules ['s-fonts-tables'] = {
+ version = 1.001,
+ comment = "companion to s-fonts-tables.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local setmetatableindex = table.setmetatableindex
+local sortedhash = table.sortedhash
+local sortedkeys = table.sortedkeys
+local format = string.format
+local concat = table.concat
+
+moduledata.fonts = moduledata.fonts or { }
+moduledata.fonts.tracers = moduledata.fonts.tracers or { }
+moduledata.fonts.tracers.tables = moduledata.fonts.tracers.tables or { }
+
+local tabletracers = moduledata.fonts.tracers.tables
+
+local digits = {
+ dflt = {
+ dflt = "1234567890 1/2",
+ },
+}
+
+local punctuation = {
+ dflt = {
+ dflt = ". , : ; ? ! ‹ › « »",
+ },
+}
+
+local symbols = {
+ dflt = {
+ dflt = "@ # $ % & * () [] {} <> + - = / |",
+ },
+}
+
+local LATN = "abcdefghijklmnopqrstuvwxyz"
+
+local uppercase = {
+ latn = {
+ dflt = LATN,
+ fra = LATN .. " ÀÃÂÈÉÊÒÓÔÙÚÛÆÇ",
+ },
+ grek = {
+ dftl = "ΑΒΓΔΕΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩ",
+ },
+ cyrl= {
+ dflt = "ÐБВГДЕЖЗИІЙКЛМÐОПРСТУФХЦЧШЩЪЫЬѢЭЮЯѲ"
+ },
+}
+
+local latn = "abcdefghijklmnopqrstuvwxyz"
+
+local lowercase = {
+ latn = {
+ dftl = latn,
+ nld = latn .. " ïèéë",
+ deu = latn .. " äöüß",
+ fra = latn .. " àáâèéêòóôùúûæç",
+ },
+ grek = {
+ dftl = "αβγδεηθικλμνξοπÏστυφχψω",
+ },
+ cyrl= {
+ dflt = "абвгдежзиійклмнопрÑтуфхцчшщъыьѣÑÑŽÑѳ"
+ },
+}
+
+local samples = {
+ digits = digits,
+ punctuation = punctuation,
+ symbols = symbols,
+ uppercase = uppercase,
+ lowercase = lowercase,
+}
+
+tabletracers.samples = samples
+
+setmetatableindex(uppercase, function(t,k) return rawget(t,"latn") end)
+setmetatableindex(lowercase, function(t,k) return rawget(t,"latn") end)
+setmetatableindex(digits, function(t,k) return rawget(t,"dflt") end)
+setmetatableindex(symbols, function(t,k) return rawget(t,"dflt") end)
+setmetatableindex(punctuation, function(t,k) return rawget(t,"dflt") end)
+
+setmetatableindex(uppercase.latn, function(t,k) return rawget(t,"dflt") end)
+setmetatableindex(uppercase.grek, function(t,k) return rawget(t,"dflt") end)
+setmetatableindex(uppercase.cyrl, function(t,k) return rawget(t,"dflt") end)
+
+setmetatableindex(lowercase.latn, function(t,k) return rawget(t,"dflt") end)
+setmetatableindex(lowercase.grek, function(t,k) return rawget(t,"dflt") end)
+setmetatableindex(lowercase.cyrl, function(t,k) return rawget(t,"dflt") end)
+
+setmetatableindex(digits.dflt, function(t,k) return rawget(t,"dflt") end)
+setmetatableindex(symbols.dflt, function(t,k) return rawget(t,"dflt") end)
+setmetatableindex(punctuation.dflt, function(t,k) return rawget(t,"dflt") end)
+
+local function typesettable(t,keys,synonyms,nesting,prefix)
+ if t then
+ if not prefix then
+ context.starttabulate { "|Tl|Tl|Tl|" }
+ end
+ for k, v in sortedhash(keys) do
+ if k == "synonyms" then
+ elseif type(v) ~= "table" then
+ context.NC()
+ if prefix then
+ context("%s.%s",prefix,k)
+ else
+ context(k)
+ end
+ context.NC()
+ local tk = t[k]
+ if v == "boolean" then
+ context(tostring(tk or false))
+ elseif not tk then
+ context("<unset>")
+ elseif v == "filename" then
+ context(file.basename(tk))
+ elseif v == "basepoints" then
+ context("%sbp",tk)
+ elseif v == "scaledpoints" then
+ context(number.points(tk))
+ elseif v == "table" then
+ context("<table>")
+ else -- if v == "integerscale" then
+ context(tostring(tk))
+ end
+ context.NC()
+ local synonym = (not prefix and synonyms[k]) or (prefix and synonyms[format("%s.%s",prefix,k)])
+ if synonym then
+ context(format("(%s)",concat(synonym," ")))
+ end
+ context.NC()
+ context.NR()
+ elseif nesting == false then
+ context("<table>")
+ else -- true or nil
+ typesettable(t[k],v,synonyms,nesting,k)
+ end
+ end
+ if not prefix then
+ context.stoptabulate()
+ end
+ end
+end
+
+local function typeset(t,keys,nesting,prefix)
+ local synonyms = keys.synonyms or { }
+ local collected = { }
+ for k, v in next, synonyms do
+ local c = collected[v]
+ if not c then
+ c = { }
+ collected[v] = c
+ end
+ c[#c+1] = k
+ end
+ for k, v in next, collected do
+ table.sort(v)
+ end
+ typesettable(t,keys,collected,nesting,prefix)
+end
+
+tabletracers.typeset = typeset
+
+function tabletracers.properties(nesting)
+ local tfmdata = fonts.hashes.identifiers[font.current()]
+ typeset(tfmdata.properties,fonts.constructors.keys.properties,nesting)
+end
+
+function tabletracers.parameters(nesting)
+ local tfmdata = fonts.hashes.identifiers[font.current()]
+ typeset(tfmdata.parameters,fonts.constructors.keys.parameters,nesting)
+end
+
+function tabletracers.positionalfeatures()
+ local tfmdata = fonts.hashes.identifiers[font.current()]
+ local resources = tfmdata.resources
+ if resources then
+ local features = resources.features
+ if features then
+ local gpos = features.gpos
+ if gpos and next(gpos) then
+ context.starttabulate { "|Tl|Tl|Tlp|" }
+ for feature, scripts in sortedhash(gpos) do
+ for script, languages in sortedhash(scripts) do
+ context.NC()
+ context(feature)
+ context.NC()
+ context(script)
+ context.NC()
+ context(concat(sortedkeys(languages)," "))
+ context.NC()
+ context.NR()
+ end
+ end
+ context.stoptabulate()
+ else
+ context("no entries")
+ context.par()
+ end
+ end
+ end
+end
+
+local dynamics = true
+
+function tabletracers.substitutionfeatures()
+ local tfmdata = fonts.hashes.identifiers[font.current()]
+ local resources = tfmdata.resources
+ if resources then
+ local features = resources.features
+ if features then
+ local gsub = features.gsub
+ if gsub then
+ local makes_sense = { }
+ for feature, scripts in sortedhash(gsub) do
+ for script, languages in sortedhash(scripts) do
+ for language in sortedhash(languages) do
+ local tag = format("dummy-%s-%s-%s",feature,script,language)
+ local fnt = format("file:%s*%s",file.basename(tfmdata.properties.filename),tag)
+ context.definefontfeature (
+ { tag },
+ {
+ mode = "node",
+ script = script,
+ language = language,
+ [feature] = "yes"
+ }
+ )
+ if not dynamics then
+ context.definefont( { fnt }, { fnt } )
+ end
+ makes_sense[#makes_sense+1] = {
+ feature = feature,
+ tag = tag,
+ script = script,
+ language = language,
+ fontname = fnt,
+ }
+ end
+ end
+ end
+ if #makes_sense > 0 then
+ context.starttabulate { "|Tl|Tl|Tl|p|" }
+ for i=1,#makes_sense do
+ local data = makes_sense[i]
+ local script = data.script
+ local language = data.language
+ context.NC()
+ context(data.feature)
+ context.NC()
+ context(script)
+ context.NC()
+ context(language)
+ context.NC()
+ if not dynamics then
+ context.startfont { data.fontname }
+ else
+ context.addff(data.tag)
+ end
+ context.verbatim(samples.lowercase [script][language]) context.par()
+ context.verbatim(samples.uppercase [script][language]) context.par()
+ context.verbatim(samples.digits [script][language]) context.par()
+ context.verbatim(samples.punctuation[script][language]) context.quad()
+ context.verbatim(samples.symbols [script][language])
+ if not dynamics then
+ context.stopfont()
+ end
+ context.NC()
+ context.NR()
+ end
+ context.stoptabulate()
+ else
+ context("no entries")
+ context.par()
+ end
+ end
+ end
+ end
+end
+
+function tabletracers.all(settings) -- not interfaced
+
+ if type(settings) == "string" then
+ settings = utilities.parsers.settings_to_hash(settings)
+ end
+
+ local title = settings and settings.title or ""
+
+ if title == "" then title = false end
+
+ if title then
+ context.starttitle { title = title }
+ end
+
+ context.startsubject { title = "Properties" }
+ tabletracers.properties()
+ context.stopsubject()
+
+ context.startsubject { title = "Parameters" }
+ tabletracers.parameters()
+ context.stopsubject()
+
+ context.startsubject { title = "Positional features" }
+ tabletracers.positionalfeatures()
+ context.stopsubject()
+
+ context.startsubject { title = "Substitution features" }
+ tabletracers.substitutionfeatures()
+ context.stopsubject()
+
+ if title then
+ context.stoptitle()
+ end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/s-fonts-tables.mkiv b/Master/texmf-dist/tex/context/base/s-fonts-tables.mkiv
new file mode 100644
index 00000000000..efe1500fb5b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/s-fonts-tables.mkiv
@@ -0,0 +1,30 @@
+%D \module
+%D [ file=s-fonts-tables,
+%D version=2011.10.10,
+%D title=\CONTEXT\ Style File,
+%D subtitle=Basic Font Data 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.
+
+% todo: make a mtxrun --script --font <name> option
+
+\registerctxluafile{s-fonts-tables}{}
+
+\def\ModuleFontsTracersTablesAll[#1]%
+ {\ctxlua{moduledata.fonts.tracers.tables.all("#1")}}
+
+\continueifinputfile{s-fonts-tables.mkiv}
+
+\usemodule[art-01]
+
+\setupbodyfont
+ [cambria]
+
+\starttext
+ \ModuleFontsTracersTablesAll[title=Cambria]
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/s-grk-00.mkii b/Master/texmf-dist/tex/context/base/s-grk-00.mkii
index ec5ddf1f7f2..f76d0c220b8 100644
--- a/Master/texmf-dist/tex/context/base/s-grk-00.mkii
+++ b/Master/texmf-dist/tex/context/base/s-grk-00.mkii
@@ -6,7 +6,7 @@
%D author=Hans Hagen,
%D date=\currentdate,
%D suggestions=Giuseppe Bilotta,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-inf-01.mkvi b/Master/texmf-dist/tex/context/base/s-inf-01.mkvi
index 4792e739a66..51d3cbac824 100644
--- a/Master/texmf-dist/tex/context/base/s-inf-01.mkvi
+++ b/Master/texmf-dist/tex/context/base/s-inf-01.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Information 1 (\MKII/\MKIV\ usage),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -46,7 +46,7 @@
local function collect(list,suffix,n)
local path = document.arguments.basepath or file.dirname(resolvers.find_file("context.mkiv"),".")
- local pattern = path .. "/*." .. suffix
+ local pattern = path .. "/*." .. suffix .. "$" -- avoid bla.tex~
local texfiles = dir.glob(pattern)
for _, name in ipairs(texfiles) do
local base = file.basename(name)
diff --git a/Master/texmf-dist/tex/context/base/s-inf-02.mkiv b/Master/texmf-dist/tex/context/base/s-inf-02.mkiv
index 77a3f650c51..cf8d572bca2 100644
--- a/Master/texmf-dist/tex/context/base/s-inf-02.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-inf-02.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Information 2 (filenames),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-inf-03.mkiv b/Master/texmf-dist/tex/context/base/s-inf-03.mkiv
index 85440f0db97..1ff4cd0d094 100644
--- a/Master/texmf-dist/tex/context/base/s-inf-03.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-inf-03.mkiv
@@ -1,6 +1,6 @@
% \nopdfcompression
-% \enablemode[ipad]
+\enablemode[ipad]
\doifmodeelse {ipad} {
@@ -10,13 +10,19 @@
\definefont
[TitlePageFont]
- [MonoBold at 20pt]
+ [MonoBold at 18pt]
+
+ \setupbodyfont
+ [tt,10pt]
} {
\definefont
[TitlePageFont]
- [MonoBold at 26pt]
+ [MonoBold at 24pt]
+
+ \setupbodyfont
+ [tt]
}
@@ -41,9 +47,6 @@
[xtitle]
[color=darkgreen]
-\setupbodyfont
- [tt]
-
\setupfootertexts
[\llap{\goto{\hbox to 5cm{\hss previous}}[previouspage]}%
\quad\pagenumber\quad
@@ -108,14 +111,11 @@ end
backgroundcolor=darkgray,
backgroundoffset=2mm]
-\setuplayout
- [page]
-
-\startstandardmakeup
+\startpagemakeup
\vfill
\pagereference[global]
- \startnarrower[5mm]
- \raggedcenter
+ \startnarrower[10mm]
+ \setupalign[nothyhenated,middle,broad]
\TitlePageFont \setupinterlinespace
\getbuffer % luabuffer
\par
@@ -126,9 +126,7 @@ end
\par
% \hskip10mm\scale[width=\dimexpr\paperwidth-20mm\relax]{\white \strut Lua infrastructure \emdash\ \currentdate}
\vfill
-\stopstandardmakeup
-
-\setuplayout
+\stoppagemakeup
\setupbackgrounds
[page]
diff --git a/Master/texmf-dist/tex/context/base/s-jap-00.mkii b/Master/texmf-dist/tex/context/base/s-jap-00.mkii
index 28cb6c2415a..5eec2f72594 100644
--- a/Master/texmf-dist/tex/context/base/s-jap-00.mkii
+++ b/Master/texmf-dist/tex/context/base/s-jap-00.mkii
@@ -6,7 +6,7 @@
%D author=Hans Hagen,
%D date=\currentdate,
%D suggestions=Richard Gabriel,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-lan-03.mkiv b/Master/texmf-dist/tex/context/base/s-lan-03.mkiv
index b8d24539b52..a490261f47a 100644
--- a/Master/texmf-dist/tex/context/base/s-lan-03.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-lan-03.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Language Environment 3,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-lan-04.mkiv b/Master/texmf-dist/tex/context/base/s-lan-04.mkiv
index 3fb57529911..80283bfd47f 100644
--- a/Master/texmf-dist/tex/context/base/s-lan-04.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-lan-04.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Language Environment 4,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-mag-01.tex b/Master/texmf-dist/tex/context/base/s-mag-01.tex
index da4e027f4af..b90dceb66ce 100644
--- a/Master/texmf-dist/tex/context/base/s-mag-01.tex
+++ b/Master/texmf-dist/tex/context/base/s-mag-01.tex
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Magazine Base Style,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -178,7 +178,7 @@
[palatino,10pt]
\setuptolerance
- [verytolerant]
+ [verytolerant,stretch]
\appendtoks\setups[papershift]\to\beforeeverypage
@@ -248,6 +248,8 @@
\startstandardmakeup[doublesided=no]
+ \dontcomplain
+
\definelayer
[makeup]
[width=\textwidth,
@@ -286,7 +288,7 @@
[makeup]
[corner={right,bottom},location={left,top}]
[frame=off,
- align=normal, % left,
+ align=normal,
width=.8\textwidth,
foregroundcolor=MainColor]
{\getbuffer[abstract]}
@@ -307,7 +309,11 @@
\setupheadertexts[][] \setupheadertexts[source code of this document]
\setupfootertexts[][] \setupfootertexts[]
- \typefile[TEX]{\inputfilename} % \jobname
+ \start \dontcomplain
+
+ \typefile[TEX]{\inputfilename}
+
+ \stop
\stopsetups
diff --git a/Master/texmf-dist/tex/context/base/s-map-10.mkiv b/Master/texmf-dist/tex/context/base/s-map-10.mkiv
index 22ceeb16158..e9ef436f94f 100644
--- a/Master/texmf-dist/tex/context/base/s-map-10.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-map-10.mkiv
@@ -1,12 +1,11 @@
-%\module [
-% file=s-map-se,
-% version=2005.02.03,
-% title=\CONTEXT\ Style File,
-% subtitle=\MAPS\ basis stijl,
-% author={Hans Hagen, Taco Hoekwater and Siep Kroonenberg},
-% date=\currentdate,
-% copyright={NTG / MAPS}%
-%]
+%D \module
+%D [file=s-map-10,
+%D version=2011.06.28,
+%D title=\CONTEXT\ Style File,
+%D subtitle=\MAPS\ basis stijl,
+%D author={Hans Hagen, Taco Hoekwater and Siep Kroonenberg},
+%D date=\currentdate,
+%D copyright=NTG/MAPS]
% This module re-implements the MAPS style for use with the Context
% macro package. The original MAPS layout was designed and
@@ -20,24 +19,22 @@
% 3. one column, with wide left margin (option asym)
% - font sizes deviate from TeX's usual geometric progression
% - use of sans-serif for headers and various details
-% - option realfonts uses Bitstream Charter, Euler Math and Latin Modern.
+% - option realfonts uses Linux Libertine, Euler Math and Inconsolata.
% This is used for final typesetting.
% The default font setup, intended for authors, uses Computer
-% Modern.
+% Modern Math instead of Euler Math (which is still in beta),
+% and LM Mono instead of Inconsolata.
% A mode nosubsub defines only two levels of sectioning. If you
% don't need more and use the two-column layout, then this option
% will probably improve the looks of your paper.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%% pdftex support
\newif\ifMapsInColumns
\doifmode{asym}{\enablemode[onecolumn]} % implies onecolumn
\doifnotmode{onecolumn}{\MapsInColumnstrue}
-\enablemode[realfonts]
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% fonts
@@ -107,25 +104,20 @@
\usetypescriptfile[type-inconsolata]
-\startmode[mkii]
-\starttypescript [maps] [ec]
-\definetypeface [maps] [mm] [math] [euler] [default] [encoding=default,rscale=0.9]
-\usemathcollection[euler]
-\definetypeface [maps] [tt] [mono] [inconsolata] [default] [encoding=ec,rscale=0.92]
-\definetypeface [maps] [ss] [sans] [default] [default] [encoding=ec,rscale=0.95]
-\definetypeface [maps] [rm] [serif] [libertine] [default] [encoding=ec]
+\starttypescript [maps]
+\definetypeface [maps] [rm] [serif] [modern] [default] [rscale=0.95]
+\definetypeface [maps] [mm] [math] [modern] [latin-modern]
+\definetypeface [maps] [tt] [mono] [modern] [default] [rscale=0.90]
+\definetypeface [maps] [ss] [sans] [modern] [default] [rscale=0.95]
\stoptypescript
-\usetypescript[maps] [ec]
-\stopmode
-\startmode[mkiv]
+\startmode[realfonts]
\starttypescript [maps]
+\definetypeface [maps] [rm] [serif] [libertine] [default]
\definetypeface [maps] [mm] [math] [euler] [default] [rscale=0.9]
\definetypeface [maps] [tt] [mono] [inconsolata] [default] [rscale=0.92]
\definetypeface [maps] [ss] [sans] [modern] [default] [rscale=0.95]
-\definetypeface [maps] [rm] [serif] [libertine] [default]
\stoptypescript
-\usetypescript[maps]
\stopmode
\setupbodyfont[maps,10pt,rm]
@@ -137,10 +129,6 @@
\setupalign[hanging]
-% \usetypescript[map][texnansi]
-
-% \setupbodyfont [map,10pt]
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% additional general typographic details
@@ -269,36 +257,14 @@
%%% floats
\setupfloats [location=center, before={\ss}]
-\setupcaptions [headstyle={\ss},style={\ssx},
- stopper=.,distance=6pt,
+\setupcaptions [headstyle={\ssbf},style={\ssx},
+ suffix=.,distance=6pt,
inbetween={\blank[halfline]}]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% various document elements
-%\startnotmode[realfonts]
-\def\ChkBox{%
- \hbox {\boxrulewidth=.4pt \raise.2ex\ruledvbox
- {\phantom{\vrule width .85ex height .85ex%
-}}}}
-
-\startmode[mkii]
-\pdfmapline{stmary10 stmary10 <stmary10.pfb}
-\def\ChkBox{\definedfont[stmary10]{\char "40}}
-\stopmode
-
-\startmode[mkiv]
-\def\ChkBox{\definedfont[file:stmary10]{\char "40}} % doesnt work
-\def\ChkBox{%
- \hbox {\boxrulewidth=.4pt \raise.2ex\ruledvbox
- {\phantom{\vrule width .85ex height .85ex%
-}}}}
-\stopmode
-%\stopnotmode
-%\startmode[realfonts]
-%\def\ChkBox{\raise.12ex\hbox{\ws \char50}}
-%\stopmode
-\definesymbol [1][\ChkBox]
+\definesymbol [1][\getnamedglyphdirect{file:stmary10}{boxempty}]
\setupitemize[1][packed]
@@ -328,7 +294,6 @@
\unexpanded\def\smalltyping{%
\switchtobodyfont[tt]%
-% \setuplocalinterlinespace[line=11pt]%
\parindent=0pt
}
@@ -345,13 +310,12 @@
indentnext=no%
]
-\def\footnum#1{#1.}
+\def\footnum#1{#1.}
\setupfootnotes
[location=none,
width=\textwidth,
-% bodyfont={rm,9pt},
- before=,
+ before={\blank},
numbercommand=,
command=\footnum]
@@ -404,14 +368,23 @@
Page=1,
Title=,
Author=,
- Period=VOORJAAR,
- Number=40,
- Year=2010,
+ Period=,
+ Number=,
+ Year=,
#1]%
- \doifinstringelse{oorjaar}{\MapsPeriod}{\def\MapsPeriod{VOORJAAR}}{}%
- \doifinstringelse{pring}{\MapsPeriod}{\def\MapsPeriod{VOORJAAR}}{}%
- \doifinstringelse{ajaar}{\MapsPeriod}{\def\MapsPeriod{NAJAAR}}{}%
- \doifinstringelse{utumn}{\MapsPeriod}{\def\MapsPeriod{NAJAAR}}{}%
+ \doifnothing{\MapsPeriod}{%
+ \ifnum \normalmonth<6 \gdef\MapsPeriod{VOORJAAR}\else \gdef\MapsPeriod{NAJAAR}\fi}
+ \doifinstringelse{oorjaar}{\MapsPeriod}{\gdef\MapsPeriod{VOORJAAR}}{}%
+ \doifinstringelse{pring}{\MapsPeriod}{\gdef\MapsPeriod{VOORJAAR}}{}%
+ \doifinstringelse{ajaar}{\MapsPeriod}{\gdef\MapsPeriod{NAJAAR}}{}%
+ \doifinstringelse{utumn}{\MapsPeriod}{\gdef\MapsPeriod{NAJAAR}}{}%
+ \doifnothing{\MapsYear}{\gdef\MapsYear{\the\year}}%
+ \doifnothing{\MapsNumber}{%
+ \ifnum \normalmonth<6
+ \xdef\MapsNumber{\the\numexpr (\the\year-1990)*2\relax}%
+ \else
+ \xdef\MapsNumber{\the\numexpr (\the\year-1990)*2+1\relax}%
+ \fi }%
\doifnothing\MapsRunningAuthor
{\global\let\MapsRunningAuthor\MapsAuthor}%
\doifnothing\MapsRunningTitle
@@ -420,8 +393,7 @@
\def\dostartArticle[#1]{%
\MapsBibData[#1]
\pageno=\MapsPage
- \count0=\MapsPage
- \setuppagenumber[number=\MapsPage]
+ \setupuserpagenumber[start=\MapsPage]
\startbaselinecorrection
\bgroup
\hsize = 457pt
@@ -430,7 +402,7 @@
\switchtobodyfont[24pt]
\setupalign[right]
{\noindent\bf\MapsTitle\par}
- \ifx\MapsSubTitle\empty
+ \ifx\MapsSubTitle\empty
\blank[30pt]
\else
\bgroup
@@ -453,8 +425,6 @@
\fi
}
-\definecolumnset[mapsset][n=2,grid=on]
-
\def\startArticle{\dosingleempty\dostartArticle}
\def\signArticle{%
@@ -473,14 +443,10 @@
\page
}
-\installpagebreakhandler{last}{}
+\installpagebreakmethod{last}{}
%%% `logos' %%%%%%%%%%%%%%%%%%%%%%%%%%
-% don't do this for the proceedings because it is a TUGboat also
-%\def\LATEX{\LaTeX}
-%\def\TEX{\TeX}
-
\unexpanded\def\LaTeX % requested by erik frambach
{{\setbox\scratchbox\hbox{L}%
\scratchdimen\ht\scratchbox
@@ -539,19 +505,6 @@
\def\fulltextwidth{457pt}
-%\MapsBibData
-% []
-
-%\abovedisplayskip = 12pt
-%\abovedisplayshortskip = 6pt
-
-\newdimen\iabovedisplayskip
-\newdimen\iabovedisplayshortskip
-%\let\abovedisplayskip\iabovedisplayskip
-%\let\abovedisplayshortskip\iabovedisplayshortskip
-
-%\protect
-
\def\startdescription
{\blank
\bgroup
diff --git a/Master/texmf-dist/tex/context/base/s-mat-10.mkiv b/Master/texmf-dist/tex/context/base/s-mat-10.mkiv
new file mode 100644
index 00000000000..384371c186f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/s-mat-10.mkiv
@@ -0,0 +1,245 @@
+%D \module
+%D [ file=s-mat-10.mkiv, % was: s-fnt-25
+%D version=2009.01.25,
+%D title=\CONTEXT\ Style File,
+%D subtitle=Math Glyph Checking,
+%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 base module will be cleaned up and extended.
+
+\def\enableshowmathfontvirtual
+ {\ctxlua{fonts.constructors.autocleanup=false}}
+
+\def\showmathfontcharacters
+ {\dodoubleempty\doshowmathfontcharacters}
+
+\def\doshowmathfontcharacters[#1][#2]%
+ {\begingroup
+ \dontcomplain
+ \doifelsenothing{#1}
+ {\definedfont[MathRoman*math-text]}
+ {\definedfont[#1]}%
+ \doifelsenothing{#2}
+ {\ctxlua{document.showmathfont(font.current())}}
+ {\def\dodoshowmathfontcharacters##1{\ctxlua{document.showmathfont(font.current(),##1)}}%
+ \processcommalist[#2]\dodoshowmathfontcharacters}%
+ \endgroup}
+
+% the interface might (and will) change
+
+\let\startmathfontlist \relax
+\let\stopmathfontlist \relax
+\let\mathfontlistreference \gobbleoneargument
+\let\startmathfontlistentry \relax
+\let\stopmathfontlistentry \relax
+\let\mathfontlistentryhexdectit \gobblethreearguments
+\let\mathfontlistentrywdhtdpic \gobblefourarguments
+\let\mathfontlistentryresource \gobbleoneargument
+\let\startmathfontlistnext \relax
+\let\mathfontlistnextentry \gobblethreearguments
+\let\mathfontlistnextcycle \gobbleonearguments
+\let\stopmathfontlistnext \relax
+\let\startmathfontlisthvariants \relax
+\let\mathfontlisthvariantsentry \gobblethreearguments
+\let\stopmathfontlisthvariants \relax
+\let\startmathfontlistvvariants \startmathfontlisthvariants
+\let\mathfontlistvvariantsentry \mathfontlisthvariantsentry
+\let\stopmathfontlistvvariants \stopmathfontlisthvariants
+\let\mathfontlistbetweennextandvariants\relax
+\let\startmathfontlistentryclassspec \relax
+\let\stopmathfontlistentryclassspec \relax
+\let\mathfontlistentryclassname \gobbletwoarguments
+\let\mathfontlistentrysymbol \gobbletwoarguments
+\let\startmathfontlookupvariants \relax
+\let\stopmathfontlookupvariants \relax
+\let\mathfontlookupvariant \gobblefourarguments
+
+\startluacode
+local concat = table.concat
+local format, lower = string.format, string.lower
+local utfchar = utf.char
+local round = math.round
+
+local fontdata = fonts.hashes.identifiers
+local chardata = characters.data
+
+local no_description = "no description, private to font"
+
+local limited = true
+local fillinthegaps = true
+local upperlimit = 0x0007F
+local upperlimit = 0xF0000
+
+function document.showmathfont(id,slot)
+ local tfmdata = fontdata[id]
+ local characters = tfmdata.characters
+ local descriptions = tfmdata.descriptions
+ local resources = tfmdata.resources
+ local lookuptypes = resources.lookuptypes
+ local virtual = tfmdata.properties.virtualized
+ local names = { }
+ local gaps = mathematics.gaps
+ local sorted = { }
+ if slot then
+ sorted = { slot }
+ elseif fillinthegaps then
+ sorted = table.keys(characters)
+ for k, v in next, gaps do
+ if characters[v] then
+ sorted[#sorted+1] = k
+ end
+ end
+ table.sort(sorted)
+ else
+ sorted = table.sortedkeys(characters)
+ end
+ if virtual then
+ for k, v in ipairs(tfmdata.fonts) do
+ local id = v.id
+ local name = fontdata[id].properties.name
+ names[k] = (name and file.basename(name)) or id
+ end
+ end
+ context.startmathfontlist()
+ for _, unicode in next, sorted do
+ if not limited or unicode < upperlimit then
+ local code = gaps[unicode] or unicode
+ local char = characters[code]
+ local desc = descriptions[code]
+ local info = chardata[code]
+ if char then
+ local next_sizes = char.next
+ local v_variants = char.vert_variants
+ local h_variants = char.horiz_variants
+ local commands = char.commands
+ local slookups = desc.slookups
+ local mlookups = desc.mlookups
+ local mathclass = info.mathclass
+ local mathspec = info.mathspec
+ local mathsymbol = info.mathsymbol
+ local description = info.description or no_description
+ context.startmathfontlistentry()
+ context.mathfontlistreference(format("U+%05X",unicode))
+ context.mathfontlistentryhexdectit(format("U+%05X",code),code,lower(description))
+ context.mathfontlistentrywdhtdpic(round(char.width or 0),round(char.height or 0),round(char.depth or 0),round(char.italic or 0))
+ if virtual and commands then
+ local t = { }
+ for i=1,#commands do
+ local ci = commands[i]
+ if ci[1] == "slot" then
+ local fnt, idx = ci[2], ci[3]
+ t[#t+1] = format("%s/%0X",names[fnt] or fnt,idx)
+ end
+ end
+ if #t > 0 then
+ context.mathfontlistentryresource(concat(t,", "))
+ end
+ end
+ if mathclass or mathspec then
+ context.startmathfontlistentryclassspec()
+ if mathclass then
+ context.mathfontlistentryclassname(mathclass,info.mathname or "no name")
+ end
+ if mathspec then
+ for i=1,#mathspec do
+ local mi = mathspec[i]
+ context.mathfontlistentryclassname(mi.class,mi.name or "no name")
+ end
+ end
+ context.stopmathfontlistentryclassspec()
+ end
+ if mathsymbol then
+ context.mathfontlistentrysymbol(format("U+%05X",mathsymbol),mathsymbol)
+ end
+ if next_sizes then
+ local n, done = 0, { }
+ context.startmathfontlistnext()
+ while next_sizes do
+ n = n + 1
+ if done[next_sizes] then
+ context.mathfontlistnextcycle(n)
+ break
+ else
+ done[next_sizes] = true
+ context.mathfontlistnextentry(n,format("U+%05X",next_sizes),next_sizes)
+ next_sizes = characters[next_sizes]
+ v_variants = next_sizes.vert_variants or v_variants
+ h_variants = next_sizes.horiz_variants or h_variants
+ if next_sizes then
+ next_sizes = next_sizes.next
+ end
+ end
+ end
+ context.stopmathfontlistnext()
+ if h_variants or v_variants then
+ context.mathfontlistbetweennextandvariants()
+ end
+ end
+ if h_variants then
+ context.startmathfontlisthvariants()
+ for i=1,#h_variants do -- we might go top-down in the original
+ local vi = h_variants[i]
+ context.mathfontlisthvariantsentry(i,format("U+%05X",vi.glyph),vi.glyph)
+ end
+ context.stopmathfontlisthvariants()
+ elseif v_variants then
+ context.startmathfontlistvvariants()
+ for i=1,#v_variants do
+ local vi = v_variants[#v_variants-i+1]
+ context.mathfontlistvvariantsentry(i,format("U+%05X",vi.glyph),vi.glyph)
+ end
+ context.stopmathfontlistvvariants()
+ end
+ if slookups or mlookups then
+ local variants = { }
+ if slookups then
+ for lookupname, lookupdata in next, slookups do
+ local lookuptype = lookuptypes[lookupname]
+ if lookuptype == "substitution" then
+ variants[lookupdata] = "sub"
+ elseif lookuptype == "alternate" then
+ for i=1,#lookupdata do
+ variants[lookupdata[i]] = "alt"
+ end
+ end
+ end
+ end
+ if mlookups then
+ for lookupname, lookuplist in next, mlookups do
+ local lookuptype = lookuptypes[lookupname]
+ for i=1,#lookuplist do
+ local lookupdata = lookuplist[i]
+ local lookuptype = lookuptypes[lookupname]
+ if lookuptype == "substitution" then
+ variants[lookupdata] = "sub"
+ elseif lookuptype == "alternate" then
+ for i=1,#lookupdata do
+ variants[lookupdata[i]] = "alt"
+ end
+ end
+ end
+ end
+ end
+ context.startmathfontlookupvariants()
+ local i = 0
+ for variant, lookuptype in table.sortedpairs(variants) do
+ i = i + 1
+ context.mathfontlookupvariant(i,format("U+%05X",variant),variant,lookuptype)
+ end
+ context.stopmathfontlookupvariants()
+ end
+ context.stopmathfontlistentry()
+ end
+ end
+ end
+ context.stopmathfontlist()
+end
+\stopluacode
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/s-mat-11.mkiv b/Master/texmf-dist/tex/context/base/s-mat-11.mkiv
new file mode 100644
index 00000000000..3939e9f2248
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/s-mat-11.mkiv
@@ -0,0 +1,106 @@
+\usemodule[s][mat-10]
+
+% layout
+
+\setuplayout
+ [width=middle,
+ height=middle,
+ topspace=15mm,
+ backspace=15mm,
+ bottomspace=15mm,
+ header=1cm,
+ headerdistance=0.5cm,
+ footer=0pt]
+
+% rendering
+
+\def\startmathfontlist
+ {}
+
+\def\stopmathfontlist
+ {}
+
+\def\startmathfontlistentry
+ {\blank
+ \begingroup}
+
+\def\stopmathfontlistentry
+ {\endgroup
+ \blank}
+
+\def\mathfontlistentryhexdectit#1#2#3%
+ {#1: \char#2\enspace\ruledhbox{\char#2}\enspace#3\par
+ \advance\leftskip 1em\relax}
+
+\def\mathfontlistentrywdhtdpic#1#2#3#4%
+ {width: #1, height: #2, depth: #3, italic: #4\par}
+
+\def\mathfontlistentryresource#1%
+ {virtual: #1\par}
+
+\def\startmathfontlistnext
+ {next: }
+
+\def\mathfontlistnextentry#1#2#3%
+ {\ifnum#1>1 \space=>\space\fi#2~\ruledhbox{\char#3}}
+
+\def\mathfontlistnextcycle#1%
+ {\ifnum#1>1 \space=>\space\fi cycle}
+
+\def\stopmathfontlistnext
+ {\par}
+
+\def\startmathfontlisthvariants
+ {variants: }
+
+\def\mathfontlisthvariantsentry#1#2#3%
+ {\ifnum#1>1 \space=>\space\fi#2~\ruledhbox{\char#3}}
+
+\def\stopmathfontlisthvariants
+ {\par}
+
+\def\startmathfontlistvvariants{\startmathfontlisthvariants}
+\def\mathfontlistvvariantsentry{\mathfontlisthvariantsentry}
+\def\stopmathfontlistvvariants {\stopmathfontlisthvariants }
+
+\def\mathfontlistbetweennextandvariants
+ {\space=>\space}
+
+\def\startmathfontlistentryclassspec
+ {}
+
+\def\stopmathfontlistentryclassspec
+ {}
+
+\def\mathfontlistentryclassname#1#2%
+ {mathclass: #1, mathname: #2\par}
+
+\def\mathfontlistentrysymbol#1#2%
+ {mathsymbol: #1~\ruledhbox{\char#2}\par}
+
+\def\startmathfontlookupvariants
+ {lookupvariants: }
+
+\def\stopmathfontlookupvariants
+ {\par}
+
+\def\mathfontlookupvariant#1#2#3#4%
+ {\ifnum#1>1 ,\space\fi#2:~\char#3 (#4)}
+
+% done
+
+\continueifinputfile{s-mat-11.mkiv}
+
+\starttext
+% \setupbodyfont[cambria, 12pt] \showmathfontcharacters
+% \setupbodyfont[lmvirtual,12pt] \showmathfontcharacters
+% \setupbodyfont[pxvirtual,12pt] \showmathfontcharacters
+% \setupbodyfont[txvirtual,12pt] \showmathfontcharacters
+% \setupbodyfont[palatino, 10pt] \showmathfontcharacters
+% \setupbodyfont[mathtimes,12pt] \showmathfontcharacters
+% \setupbodyfont[stix, 12pt] \showmathfontcharacters
+% \setupbodyfont[xits, 12pt] \showmathfontcharacters
+% \setupbodyfont[lucida, 12pt] \showmathfontcharacters
+ \setupbodyfont[lucidanova, 12pt] \showmathfontcharacters
+\stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/s-mat-12.mkiv b/Master/texmf-dist/tex/context/base/s-mat-12.mkiv
new file mode 100644
index 00000000000..deb28975cb3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/s-mat-12.mkiv
@@ -0,0 +1,406 @@
+\usemodule[s][mat-10]
+
+% \enabletrackers[pages.timing]
+
+% todo: mode for screen
+% todo: variant for HD with one menu at the right (with include menu)
+
+% layout
+
+\definecolor[backgroundcolor] [r=.6,g=.6]
+\definecolor[backgroundcolorx][r=.6]
+\definecolor[backgroundcolory][g=.6]
+\definecolor[baselinecolor] [a=1,t=.5,s=.6]
+\definecolor[charactercolor] [b=.6]
+\definecolor[pagecolor] [s=.1]
+\definecolor[nonecolor] [s=.5]
+\definecolor[textcolor] [s=.9]
+
+% \setuppapersize[HD]
+%
+% \setuplayout
+% [page]
+
+\setuppapersize[HD+]
+
+\setuplayout
+ [backspace=0pt,
+ topspace=0pt,
+ bottomspace=120pt, %1200-1080
+ bottom=24pt,
+ bottomdistance=5mm,
+ header=0pt,
+ footer=0pt,
+ width=middle,
+ height=middle]
+
+\definelayer
+ [page]
+
+\setuplayer
+ [page]
+ [width=\textwidth,
+ height=\textheight]
+
+\setupbackgrounds
+ [page]
+ [background=color,
+ backgroundcolor=pagecolor]
+
+\setupbackgrounds
+ [text][text]
+ [bottomframe=on,framecolor=textcolor,rulethickness=0.025ex]
+
+\setupmakeup
+ [standard]
+ [pagestate=start]
+
+\setupinteraction
+ [state=start,
+ menu=on]
+
+\defineinteractionmenu
+ [ALPHABETS]
+ [bottom]
+
+\defineinteractionmenu
+ [alphabets]
+ [bottom]
+
+\defineinteractionmenu
+ [symbols]
+ [bottom]
+
+\setupinteractionmenu
+ [bottom]
+ [before=\vfill,
+ after=\vfill,
+ left=\hfill,
+ right=\hfill,
+ style=\tt\bf,
+ distance=0pt,
+ color=textcolor,
+ contrastcolor=nonecolor]
+
+\startinteractionmenu[bottom]
+ \startgot [firstpage] first \stopgot \quad
+ \startgot [deltapage(-100)] -100 \stopgot \quad
+ \startgot [deltapage(-10)] -10 \stopgot \quad
+ \startgot [previouspage] previous \stopgot \quad
+ \startgot [nextpage] next \stopgot \quad
+ \startgot [deltapage(+10)] +10 \stopgot \quad
+ \startgot [deltapage(+100)] +100 \stopgot \quad
+ \startgot [lastpage] last \stopgot
+\stopinteractionmenu
+
+\startinteractionmenu[ALPHABETS]
+ \startgot [U+00041] NORMAL \stopgot \quad
+ \startgot [U+1D400] BOLD \stopgot \quad
+ \startgot [U+1D434] ITALIC \stopgot \quad
+ \startgot [U+1D468] BOLDITALIC \stopgot \quad
+ \startgot [U+1D49C] SCRIPT \stopgot \quad
+ \startgot [U+1D4D0] BOLDSCRIPT \stopgot \quad
+ \startgot [U+1D504] FRAKTUR \stopgot \quad
+ \startgot [U+1D538] DOUBLESTRUCK \stopgot \quad
+ \startgot [U+1D56C] BOLDFRAKTUR \stopgot \quad
+ \startgot [U+1D5A0] SS NORMAL \stopgot \quad
+ \startgot [U+1D5D4] SS BOLD \stopgot \quad
+ \startgot [U+1D608] SS ITALIC \stopgot \quad
+ \startgot [U+1D63C] SS BOLDITALIC \stopgot \quad
+ \startgot [U+1D670] MONOSPACE \stopgot \quad
+ \startgot [U+00391] GRK NORMAL \stopgot \quad
+ \startgot [U+1D6A8] GRK BOLD \stopgot \quad
+ \startgot [U+1D6E2] GRK ITALIC \stopgot \quad
+ \startgot [U+1D71C] GRK BOLDITALIC \stopgot \quad
+ \startgot [U+1D756] GRK SS BOLD \stopgot \quad
+ \startgot [U+1D790] GRK SS BOLDITALIC \stopgot
+\stopinteractionmenu
+
+\startinteractionmenu[alphabets]
+ \startgot [U+00061] normal \stopgot \quad
+ \startgot [U+1D41A] bold \stopgot \quad
+ \startgot [U+1D44E] italic \stopgot \quad
+ \startgot [U+1D482] bolditalic \stopgot \quad
+ \startgot [U+1D4B6] script \stopgot \quad
+ \startgot [U+1D4EA] boldscript \stopgot \quad
+ \startgot [U+1D51E] fraktur \stopgot \quad
+ \startgot [U+1D552] doublestruck \stopgot \quad
+ \startgot [U+1D586] boldfraktur \stopgot \quad
+ \startgot [U+1D5BA] ss normal \stopgot \quad
+ \startgot [U+1D5EE] ss bold \stopgot \quad
+ \startgot [U+1D622] ss italic \stopgot \quad
+ \startgot [U+1D656] ss bolditalic \stopgot \quad
+ \startgot [U+1D68A] monospace \stopgot \quad
+ \startgot [U+003B1] grk normal \stopgot \quad
+ \startgot [U+1D6C2] grk bold \stopgot \quad
+ \startgot [U+1D6FC] grk italic \stopgot \quad
+ \startgot [U+1D736] grk bolditalic \stopgot \quad
+ \startgot [U+1D770] grk ss bold \stopgot \quad
+ \startgot [U+1D7AA] grk ss bolditalic \stopgot
+\stopinteractionmenu
+
+\startinteractionmenu[symbols]
+ \startgot [U+00030] dig normal \stopgot \quad
+ \startgot [U+1D7CE] dig bold \stopgot \quad
+ \startgot [U+1D7D8] dig doublestruck \stopgot \quad
+ \startgot [U+1D7E2] dig ss normal \stopgot \quad
+ \startgot [U+1D7EC] dig ss bold \stopgot \quad
+ \startgot [U+1D7F6] dig monospace \stopgot \quad
+ \startgot [U+02200] operators \stopgot \quad
+ \startgot [U+02701] symbols a \stopgot \quad
+ \startgot [U+02901] symbols b \stopgot \quad
+ \startgot [U+02A00] supplemental \stopgot
+\stopinteractionmenu
+
+\defineframed
+ [somedata]
+ [background=color,
+ backgroundcolor=textcolor,
+ %framecolor=charactercolor,
+ %rulethickness=1pt,
+ frame=off,
+ offset=1ex]
+
+% helpers
+
+\def\mathfontlisttxt#1%
+ {{\tttf#1}}
+
+\def\mathfontlistchr#1#2%
+ {\iffontchar\font#2\relax
+ \scale
+ [sx=#1,sy=#1]
+ {\dontleavehmode
+ \begingroup
+ \setbox\scratchbox\hbox{\charactercolor\char#2}%
+ \scratchdimen\wd\scratchbox
+ \ifdim\scratchdimen>\zeropoint
+ \backgroundline[backgroundcolor]{\box\scratchbox}%
+ \else\ifdim\scratchdimen<\zeropoint
+ \scratchdimen-\scratchdimen
+ \setbox\scratchbox\hbox to \scratchdimen{\hss\charactercolor\char#2}%
+ \backgroundline[backgroundcolorx]{\box\scratchbox}%
+ \else
+ \setbox\scratchbox\hbox to 1em{\hss\charactercolor\char#2}%
+ \scratchdimen\wd\scratchbox
+ \backgroundline[backgroundcolory]{\box\scratchbox}%
+ \fi\fi
+ \hskip-\scratchdimen
+ \baselinecolor\vrule width \scratchdimen height .05ex depth .05ex
+ \endgroup}%
+ \fi}
+
+\def\mathfontlistmth#1#2%
+ {\setbox\scratchbox\hbox{\mathfontlistchr{#1}{#2}}%
+ \ht\scratchbox\strutht
+ \dp\scratchbox\strutdp
+ \box\scratchbox}
+
+\let\mathfontlistbodyfonts\empty
+
+\def\mathfontlistbodyfontentry#1#2%
+ {\somedata
+ [align={none,middle},background=,height=5cm]
+ {\begingroup
+ \switchtobodyfont[#2,12pt]%
+ \definedfont[MathRoman*math-text]%
+ \mathfontlistmth{10}{#1}%
+ \endgroup
+ \vfilll
+ \doifmodeelse{crosslink}
+ {\goto{\strut\textcolor\mathfontlisttxt{#2}}[#2::#1]}%
+ {\strut\textcolor\mathfontlisttxt{#2}}}%
+ \hskip1ex}
+
+\def\setmathfontlistbodyfonts#1%
+ {\edef\mathfontlistbodyfonts{#1}%
+ \def\dosetmathfontlistbodyfonts##1%
+ {\setupbodyfont[##1,12pt]}%
+ \processcommacommand[\mathfontlistbodyfonts]\dosetmathfontlistbodyfonts}
+
+\def\mathfontlistbodyfontschars#1%
+ {\processcommacommand[\mathfontlistbodyfonts]{\mathfontlistbodyfontentry{#1}}}
+
+% main
+
+\def\startmathfontlist
+ {\starttext
+ \startstandardmakeup % we use baselinecolor so that we have a transparency on page 1
+ \setupalign[middle]
+ \vfil
+ \dontleavehmode \scale[height=.3\textheight]{\strut\color[textcolor]{\fontclass}}
+ \vfil
+ \dontleavehmode \scale[height=.1\textheight]{\strut\color[baselinecolor]{\currentdate}}
+ \vfil
+ \vfil
+ \stopstandardmakeup}
+
+\def\stopmathfontlist
+ {\stoptext}
+
+% entry
+
+\def\startmathfontlistentry
+ {\startstandardmakeup}
+
+\def\stopmathfontlistentry
+ {\tightlayer[page]
+ \stopstandardmakeup}
+
+\def\mathfontlistreference#1%
+ {\setlayer[page]{\pagereference[#1]}}
+
+\def\mathfontlistentryhexdectit#1#2#3%
+ {\setlayer
+ [page]
+ [preset=middletop,voffset=5mm]
+ {\somedata[height=1cm]{\mathfontlisttxt{#1}}}
+ \setlayer
+ [page]
+ [preset=middle,y=2cm]
+ {\mathfontlistmth{25}{#2}}
+ \setlayer
+ [page]
+ [preset=righttop,offset=5mm]
+ {\somedata[height=1cm]{\mathfontlisttxt{#3}}}
+ \doifsomething\mathfontlistbodyfonts
+ {\setlayer
+ [page]
+ [preset=middlebottom,voffset=5mm]
+ {\mathfontlistbodyfontschars{#2}}}}
+
+% dimensions
+
+\def\mathfontlistentrywdhtdpic#1#2#3#4%
+ {\setlayer
+ [page]
+ [preset=leftbottom,offset=5mm]
+ {\somedata[align=normal,width=5cm]
+ {\strut width \hfill \the\dimexpr#1sp\par
+ \strut height\hfill \the\dimexpr#2sp\par
+ \strut depth \hfill \the\dimexpr#3sp\par
+ \strut italic\hfill \the\dimexpr#4sp}}}
+
+\def\mathfontlistentryresource#1%
+ {} % {virtual: #1\par}
+
+% next
+
+\def\startmathfontlistnext
+ {\setlayer
+ [page]
+ [preset=middleleft,hoffset=5mm]
+ \bgroup\vbox\bgroup}
+
+\def\stopmathfontlistnext
+ {\egroup\egroup}
+
+\def\mathfontlistnextentry#1#2#3%
+ {\ifnum#1>1 \vskip1ex \fi
+ \dontleavehmode\somedata
+ [align=normal,width=4cm]
+ {\strut\mathfontlisttxt{#2}\hfill\mathfontlistchr{2}{#3}}\par}
+
+\def\mathfontlistnextcycle#1%
+ {\ifnum#1>1 \vskip1ex \fi
+ \dontleavehmode\somedata
+ [align=normal,width=4cm]
+ {\strut\mathfontlisttxt{cycle}}\par}
+
+% variants
+
+\def\startmathfontlistvvariants
+ {\setlayer
+ [page]
+ [preset=lefttop,offset=5mm]
+ \bgroup\vbox\bgroup}
+
+\def\startmathfontlisthvariants
+ {\setlayer
+ [page]
+ [preset=lefttop,offset=5mm]
+ \bgroup\hbox\bgroup}
+
+\def\mathfontlistvvariantsentry#1#2#3%
+ {\ifnum#1>1 \vskip1ex \fi
+ \dontleavehmode\somedata
+ [align=middle,width=4cm]
+ {\strut\mathfontlisttxt{#2}\hfilll\mathfontlistchr{2}{#3}}}
+
+\def\mathfontlisthvariantsentry#1#2#3%
+ {\ifnum#1>1 \hskip1ex \else \dontleavehmode \fi
+ \somedata
+ [align={none,middle},height=2cm]
+ {\strut\mathfontlisttxt{#2}\vfilll\mathfontlistchr{2}{#3}}}
+
+\def\stopmathfontlistvvariants
+ {\egroup\egroup}
+
+\def\stopmathfontlisthvariants
+ {\egroup\egroup}
+
+\def\mathfontlistbetweennextandvariants
+ {}
+
+% classes
+
+\def\startmathfontlistentryclassspec
+ {\setlayer
+ [page]
+ [preset=rightbottom,offset=5mm]
+ \bgroup\somedata[align=normal,width=8cm]\bgroup}
+
+\def\stopmathfontlistentryclassspec
+ {\egroup\egroup}
+
+\def\mathfontlistentryclassname#1#2%
+ {\strut{\mathfontlisttxt#1}\hfill\mathfontlisttxt{#2}\par}
+
+% symbols
+
+\def\mathfontlistentrysymbol#1#2%
+ {\setlayer
+ [page]
+ [preset=leftbottom,hoffset=5mm,voffset=50mm]
+ {\somedata
+ [align=normal,width=5cm]
+ {\mathfontlisttxt{#1}\hfill\mathfontlistchr{4}{#2}}}}
+
+% alternates
+
+\def\startmathfontlookupvariants
+ {\setlayer
+ [page]
+ [preset=middleright,hoffset=5mm]
+ \bgroup\vbox\bgroup}
+
+\def\stopmathfontlookupvariants
+ {\egroup\egroup}
+
+\def\mathfontlookupvariant#1#2#3#4%
+ {\ifnum#1>1 \vskip1ex \fi
+ \somedata
+ [align=normal,width=7cm]
+ {\mathfontlisttxt{#4:} \mathfontlisttxt{#2}\hfill\mathfontlistchr{4}{#3}}}
+
+% done
+
+\continueifinputfile{s-mat-12.mkiv}
+
+\setmathfontlistbodyfonts{lucidanova,cambria,xits,modern,pagella}
+
+\starttext
+% \setupbodyfont[cambria, 12pt] \showmathfontcharacters
+% \setupbodyfont[modern, 12pt] \showmathfontcharacters
+% \setupbodyfont[lmvirtual,12pt] \showmathfontcharacters
+% \setupbodyfont[pxvirtual,12pt] \showmathfontcharacters
+% \setupbodyfont[txvirtual,12pt] \showmathfontcharacters
+% \setupbodyfont[palatino, 10pt] \showmathfontcharacters
+% \setupbodyfont[mathtimes,12pt] \showmathfontcharacters
+% \setupbodyfont[stix, 12pt] \showmathfontcharacters
+% \setupbodyfont[xits, 12pt] \showmathfontcharacters
+% \setupbodyfont[lucida, 12pt] \showmathfontcharacters
+% \setupbodyfont[lucidanova, 12pt] \showmathfontcharacters
+ \setupbodyfont[pagella, 12pt] \showmathfontcharacters
+\stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/s-mod-00.mkii b/Master/texmf-dist/tex/context/base/s-mod-00.mkii
index e2d07200c6a..a81406a7346 100644
--- a/Master/texmf-dist/tex/context/base/s-mod-00.mkii
+++ b/Master/texmf-dist/tex/context/base/s-mod-00.mkii
@@ -5,7 +5,7 @@
%D subtitle=Documentation Base Environment,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -37,7 +37,7 @@
% nog eens \interface \\ \\ verder doorvoeren
-\def\resetmodule
+\def\resetmoduledocumentation
{\getrawparameters
[Module]
[ file=\jobname,
@@ -51,24 +51,18 @@
copyright=Unknown Copyright,
suggestions=]}
-\resetmodule
+\resetmoduledocumentation
-\def\dostartmodule[#1]%
+\def\dostartmoduledocumentation[#1]%
{\newcounter\ParagraphNumber
- \resetmodule
+ \resetmoduledocumentation
\getrawparameters[Module][type=tex,#1]}
-\def\startmodule
+\def\startmoduledocumentation
{\starttext
- \dosingleempty\dostartmodule}
+ \dosingleempty\dostartmoduledocumentation}
-\def\complexmodule[#1]%
- {\startglobal % i.v.m. \bgroup in \startdocumentation
- \getrawparameters[Module][#1]
- \stopglobal % i.v.m. \bgroup in \startdocumentation
- \moduletitle}
-
-\def\stopmodule
+\def\stopmoduledocumentation
{\page
\placeregister
[\v!index]
@@ -77,10 +71,16 @@
\c!criterium=\v!text]
\stoptext}
-\def\simplemodule#1%
- {\type{#1}}
-
-\definecomplexorsimple\module
+% \def\complexmodule[#1]%
+% {\startglobal % i.v.m. \bgroup in \startdocumentation
+% \getrawparameters[Module][#1]
+% \stopglobal % i.v.m. \bgroup in \startdocumentation
+% \moduletitle}
+%
+% \def\simplemodule#1%
+% {\type{#1}}
+%
+% \definecomplexorsimple\module
% \startmode[atpragma]
%
diff --git a/Master/texmf-dist/tex/context/base/s-mod-00.mkiv b/Master/texmf-dist/tex/context/base/s-mod-00.mkiv
index f6b6f7ba2e2..94f6edcb6f0 100644
--- a/Master/texmf-dist/tex/context/base/s-mod-00.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-mod-00.mkiv
@@ -5,477 +5,14 @@
%D subtitle=Documentation Base Environment,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 looks like crap, is not documented, will
-%D change, and used to be called modu-*.tex.
-
-% now split in mkii/mkiv so we will cleanup
-
-\mainlanguage[en] % better not here
-
-\usemodule[units]
-
\unprotect
-% beter:
-%
-% group -> title
-% title -> category
-% subtitle -> subtitle
-
-% herzien ivm fonts
-
-% nog eens \interface \\ \\ verder doorvoeren
-
-\def\resetmodule
- {\getrawparameters
- [Module]
- [ file=\jobname,
- type=,
- version={\currentdate[\v!year,{.},\v!month,{.},\v!day]},
- system=\CONTEXT,
- title=Unknown Title,
- subtitle=,
- author=Unknown Author,
- date=\currentdate,
- copyright=Unknown Copyright,
- suggestions=]}
-
-\resetmodule
-
-\def\dostartmodule[#1]%
- {\newcounter\ParagraphNumber
- \resetmodule
- \getrawparameters[Module][type=tex,#1]}
-
-\def\startmodule
- {\starttext
- \dosingleempty\dostartmodule}
-
-\def\complexmodule[#1]%
- {\startglobal % i.v.m. \bgroup in \startdocumentation
- \getrawparameters[Module][#1]
- \stopglobal % i.v.m. \bgroup in \startdocumentation
- \moduletitle}
-
-\def\stopmodule
- {\page
- \placeregister
- [\v!index]
- [\c!balance=\v!yes,
- \c!indicator=\v!no,
- \c!criterium=\v!text]
- \stoptext}
-
-\def\simplemodule#1%
- {\type{#1}}
-
-\definecomplexorsimple\module
-
-\startuseMPgraphic{titlepage}
-
- width := PaperWidth ;
- height := PaperHeight ;
-
- color local_red, local_white, local_blue ;
-
- local_white := white ;
-
- local_blue := local_white randomized (.6,.8) ;
- local_red := local_white randomized (.3,.4) ;
-
- u := width/400 ;
-
- def a_module (expr dx, dy) =
- picture p ; p := image
- ( ddy := 0 ; sx := 60u ;
- for i=1 upto (4 randomized 2) :
- sy := 7u randomized 3u ;
- fill unitsquare xyscaled(sx,sy) shifted (0,ddy)
- withcolor local_red ;
- ddy := ddy + sy + 4u ;
- endfor ) ;
- p := p shifted (dx,dy) shifted - center p ;
- fill boundingbox p enlarged 8u withcolor local_white ;
- fill boundingbox p enlarged 4u withcolor local_blue ;
- draw p ;
- enddef ;
-
- set_grid(width, height, width/15, height/15) ;
- forever:
- if new_on_grid(uniformdeviate width,uniformdeviate height):
- a_module(dx,dy) ;
- fi ;
- exitif grid_full ;
- endfor ;
-
- clip currentpicture to unitsquare xyscaled(width,height) ;
-\stopuseMPgraphic
-
-\defineoverlay
- [titlepage]
- [\useMPgraphic{titlepage}]
-
-\doifmode{atpragma}{\readfile{s-mod-04.tex}{}{}}
-
-\defineframed
- [TitleFrame]
- [\c!background=\v!color,
- \c!backgroundcolor=white,
- \c!align=\v!right,
- \c!offset=12pt,
- \c!strut=\v!no,
- \c!frame=\v!off,
- \c!bottom=]
-
-\definelayout
- [titlepage]
- [\c!backspace=0pt,
- \c!topspace=0pt,
- \c!header=0pt,
- \c!footer=0pt,
- \c!height=\v!middle,
- \c!width=\v!middle]
-
-\def\moduletitle
- {\setuplayout[titlepage]
- \ifx\ModuleNumber\undefined \else
- \ifnum\ModuleNumber<10
- \edef\ModuleNumber{00\ModuleNumber}
- \else\ifnum\ModuleNumber<100
- \edef\ModuleNumber{0\ModuleNumber}
- \fi\fi
- \setupbackgrounds
- [\v!page]
- [\c!background=titlepage]
- \fi
- \startmakeup[\v!standard][\c!headerstate=\v!none,\c!footerstate=\v!none]
- \switchtobodyfont[14.4pt,ss]
- \bgroup
- \def\CONTEXT {Con\kern-.15em\TeX t}
- \def\TEXUTIL {\TeX Util}
- \def\PPCHTEX {PPCH\TeX}
- \def\METAPOST{MetaPost}
- \hfill
- {\definedfont[SansBold at 96pt]\setstrut
- \TitleFrame{\Modulesystem}}
- \vfill
- \definetabulate[temp][|l|l|]%
- \switchtobodyfont[17.3pt,ss]
- \hfill
- {\bf\setstrut
- \TitleFrame
- {\insidefloattrue\setuptabulate[\c!before=,\c!after=]%
- \starttemp
- \doifsomething{\Moduletitle}
- {\NC title \EQ \Moduletitle \NC\NR}%
- \doifsomething{\Modulesubtitle}
- {\NC subtitle \EQ \Modulesubtitle \NC\NR}%
- \doifsomething{\Moduleauthor}
- {\NC author \EQ \Moduleauthor \NC\NR}%
- \NC date \EQ \currentdate \NC\NR
- %\doifsomething{\Modulesuggestions} % todo: generates space
- % {\NC suggestions \NC \Modulesuggestions \NC\NR}%
- \stoptemp}}
- \egroup
- \stopmakeup
- \ifx\ModuleNumber\undefined \else
- \setupbackgrounds
- [\v!page]
- [\c!background=]
- \fi
- \setuplayout}
-
-\let\stopdocumentation=\relax
-
-\def\startdocumentation
- {\bgroup
- \doglobal\newcounter\NOfMarginLines
- \def\stopdocumentation{\par\egroup}}
-
-\newif\ifcompressdefinitions
-
-\def\startcompressdefinitions {\global\compressdefinitionstrue}
-\def\stopcompressdefinitions {\global\compressdefinitionsfalse}
-
-\gdef\CompressDefinitions%
- {\ifcompressdefinitions
- \switchtobodyfont[\v!small]%
- \fi}
-
-\startnotmode[nocode]
-
- \definetyping
- [definition]
-
- \setuptyping
- [definition]
- [\c!before={\page[\v!preference]}\blank\PresetParagraphNumber\CompressDefinitions,
- \c!after=\ResetParagraphNumber\blank,
- \c!option=\Moduletype]
-
-\stopnotmode
-
-\startmode[nocode]
-
- \long\def\startdefinition#1\stopdefinition{}
-
-\stopmode
-
-\definetyping [PL] [\c!option=PL, \c!margin=\v!standard]
-\definetyping [JV] [\c!option=JV, \c!margin=\v!standard]
-\definetyping [MP] [\c!option=MP, \c!margin=\v!standard]
-\definetyping [TEX] [\c!option=TEX,\c!margin=\v!standard]
-
-\setuptyping [\v!typing] [\c!margin=\v!standard]
-\setuptyping [\v!file] [\c!margin=\v!standard]
-\setuptyping [definition] [\c!margin=0pt]
-
-\newcounter\NOfMarginLines
-\newcounter\ParagraphNumber
-
-\def\ResetParagraphNumber
- {\egroup}
-
-\def\PresetParagraphNumber
- {\bgroup
- \xdef\NOfTextLines%
- {\the\prevgraf}%
- \doglobal\decrement\NOfMarginLines
- \doglobal\increment\ParagraphNumber
- \message{.}%
- \gdef\ShowParagraphNumber%
- {\llap{\slx\ParagraphNumber\hskip\leftmargindistance}}%
- \gdef\ShowParagraphNumberA%
- {\ifnum\NOfMarginLines>\NOfTextLines\relax
- \doglobal\increment\NOfTextLines
- \else
- \ShowParagraphNumber
- \global\let\ShowParagraphNumberA=\relax
- \global\let\ShowParagraphNumberB=\ShowParagraphNumber
- \doglobal\newcounter\NOfMarginLines
- \fi}%
- \gdef\ShowParagraphNumberB%
- {}%
- \EveryLine
- {\ShowParagraphNumberA}%
- \EveryPar
- {\vadjust{\nobreak}%
- \ShowParagraphNumberB}}
-
-\EveryPar % skip one
- {\EveryPar
- {\doglobal\newcounter\NOfMarginLines}}
-
-\def\dodomargeaanduidingen[#1]#2%
- {\def\docommand##1%
- {\indent\hbox
- {\ifx#2\relax
- \index{##1}%
- \else
- \index{#2{##1}}%
- \fi
- #2{\doboundtext{##1}{\leftmarginwidth}{..}}}%
- \doglobal\increment\NOfMarginLines
- \endgraf}%
- \processcommalist[#1]\docommand}
-
-\def\margeaanduidingen#1[#2]%
- {\def\domargeaanduidingen##1##2%
- {\margintitle[#2]%
- {\switchtobodyfont[\v!small]%
- \doglobal\newcounter\NOfMarginLines
- \dodomargeaanduidingen[##1]#1%
- \scratchcounter=\NOfMarginLines
- \multiply\scratchcounter by 10
- \divide\scratchcounter by 12
- \advance\scratchcounter by 1
- \xdef\NOfMarginLines{\the\scratchcounter}%
- \processcommalist[##2]\index}}%
- \dodoublegroupempty\domargeaanduidingen}
-
-\def\complexmacros{\margeaanduidingen\tex }
-\def\complexextras{\margeaanduidingen\relax}
-
-\def\complexelements
- {\margeaanduidingen\someelement}
-
-\def\someelement#1{\type{<#1>}}
-
-\definecomplexorsimpleempty\macros
-\definecomplexorsimpleempty\extras
-\definecomplexorsimpleempty\elements
-
-\def\showelements{\dodoubleempty\doshowelements}
-
-\def\doshowelements[#1][#2]
- {\bgroup
- \processXMLbuffer
- \typebuffer
- \setupcolors[\c!state=\v!stop]
- \showXSDcomponent[#1][#2]
- \egroup}
-
-% \macros{a,b}
-% \macros{a,b}{b}
-% \macros[a]{a,b}{b}
-
-% weg ermee
-
-\defineparagraphs [interface] [\c!n=2]
-\setupparagraphs [interface] [1] [\c!width=4cm]
-
-\def\startexample{\par\startnarrower} \let\startvoorbeeld\startexample
-\def\stopexample {\stopnarrower} \let\stopvoorbeeld \stopexample
-
-\gdef\VisualizeLastSpace{\ifdim\lastskip>0pt\unskip\tttf\char32\fi}
-
-\gdef\ShowHeadText #1{\tttf#1\VL\mainlanguage[\currentlanguage]\headtext {#1}\VisualizeLastSpace}
-\gdef\ShowLabelText#1{\tttf#1\VL\mainlanguage[\currentlanguage]\labeltext{#1}\VisualizeLastSpace}
-
-\startbuffer[lang-a]
-\starttable[|l|l|]
- \HL
- \VL \bf head key \VL \bf current value \VL\SR
- \HL
- \VL \ShowHeadText \v!abbreviations \VL\FR
- \VL \ShowHeadText \v!units \VL\MR
- \VL \ShowHeadText \v!figures \VL\MR
- \VL \ShowHeadText \v!graphics \VL\MR
- \VL \ShowHeadText \v!index \VL\MR
- \VL \ShowHeadText \v!content \VL\MR
- \VL \ShowHeadText \v!intermezzi \VL\MR
- \VL \ShowHeadText \v!logos \VL\MR
- \VL \ShowHeadText \v!tables \VL\LR
- \HL
-\stoptable
-\stopbuffer
-
-\startbuffer[lang-b]
-\starttable[|l|l|]
- \HL
- \VL \bf label key \VL \bf current value \VL\SR
- \HL
- \VL \ShowLabelText \v!table \VL\FR
- \VL \ShowLabelText \v!figure \VL\MR
- \VL \ShowLabelText \v!intermezzo \VL\MR
- \VL \ShowLabelText \v!graphic \VL\MR
- \VL \ShowLabelText \v!chapter \VL\MR
- \VL \ShowLabelText \v!section \VL\MR
- \VL \ShowLabelText \v!subsection \VL\MR
- \VL \ShowLabelText \v!subsubsection \VL\MR
- \VL \ShowLabelText \v!appendix \VL\MR
- \VL \ShowLabelText \v!part \VL\MR
- \VL \ShowLabelText \v!line \VL\MR
- \VL \ShowLabelText \v!lines \VL\LR
- \HL
-\stoptable
-\stopbuffer
-
-\startbuffer[lang-c]
-\starttable[|l|l|]
- \HL
- \VL \bf label key \VL \bf current value \VL\SR
- \HL
- \VL \ShowLabelText \v!january \VL\FR
- \VL \ShowLabelText \v!february \VL\MR
- \VL \ShowLabelText \v!march \VL\MR
- \VL \ShowLabelText \v!april \VL\MR
- \VL \ShowLabelText \v!may \VL\MR
- \VL \ShowLabelText \v!june \VL\MR
- \VL \ShowLabelText \v!july \VL\MR
- \VL \ShowLabelText \v!august \VL\MR
- \VL \ShowLabelText \v!september \VL\MR
- \VL \ShowLabelText \v!october \VL\MR
- \VL \ShowLabelText \v!november \VL\MR
- \VL \ShowLabelText \v!december \VL\LR
- \HL
-\stoptable
-\stopbuffer
-
-\startbuffer[lang-d]
-\starttable[|l|l|]
- \HL
- \VL \bf label key \VL \bf current value \VL\SR
- \HL
- \VL \ShowLabelText \v!sunday \VL\FR
- \VL \ShowLabelText \v!monday \VL\MR
- \VL \ShowLabelText \v!tuesday \VL\MR
- \VL \ShowLabelText \v!wednesday \VL\MR
- \VL \ShowLabelText \v!thursday \VL\MR
- \VL \ShowLabelText \v!friday \VL\MR
- \VL \ShowLabelText \v!saturday \VL\LR
- \HL
-\stoptable
-\stopbuffer
-
-\gdef\ShowTextsValues[#1][#2]%
- {\vbox\bgroup
- \language[#1]%
- \setbox\scratchbox\hbox to \hsize{\hss\bfb#2 language defaults\hss}
- \dp\scratchbox\zeropoint
- \box\scratchbox
- \vskip1em
- \hrule
- \vskip2em
- \halign
- {\hss##\hss&##\hskip1em&\hss##\hss\cr
- $\vcenter{\getbuffer[lang-a]}$&&$\vcenter{\getbuffer[lang-b]}$\cr
- \noalign{\vskip1em}
- $\vcenter{\getbuffer[lang-c]}$&&$\vcenter{\getbuffer[lang-d]}$\cr}%
- \egroup}
-
-\gdef\ShowLanguageValues[#1][#2]#3#4%
- {\hbox to \hsize
- {\hss
- \vbox
- \bgroup
- \language[#1]%
- \let\normalbar=|
- \starttable[||||]
- \HL
- \VL \THREE{\bf subsentence symbol and quotes} \VL\SR
- \HL
- \VL \quotation{#3 #4} \VL \quote{#2} \VL \let|=\normalbar |<||<|#3|>|#4|>| \VL\FR
- \VL \quotation{#3 #4} \VL \quote{#2} \VL |<||<|#3|>|#4|>| \VL\LR
- \HL
- \stoptable
- \egroup
- \hss}}
-
-\gdef\doShowAllLanguageValues[#1][#2]#3#4%
- {\vbox
- {\ShowTextsValues[#1][#2]
- \vskip2em
- \ShowLanguageValues[#1][#2]{#3}{#4}}
- \protect
- \page}
-
-\gdef\ShowAllLanguageValues
- {\page
- \unprotect
- \dodoubleargument\doShowAllLanguageValues}
-
-\protect
-
-%D Command references:
-
-\usemodule[int-load] \loadsetups
-
-\unprotect
-
-\def\showsetup#1%
- {{\def\y##1{\writestatus{setups}{warning: remove y! from #1}}%
- \setup{#1}}}
-
-\setupframedtexts
- [setuptext]
- [\c!background=\v!screen,
- \c!frame=\v!off]
+% gone
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/s-mod-01.mkii b/Master/texmf-dist/tex/context/base/s-mod-01.mkii
index 64b533d0316..7e32a5b8797 100644
--- a/Master/texmf-dist/tex/context/base/s-mod-01.mkii
+++ b/Master/texmf-dist/tex/context/base/s-mod-01.mkii
@@ -5,7 +5,7 @@
%D subtitle=Documentation Paper Environment,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-mod-01.mkiv b/Master/texmf-dist/tex/context/base/s-mod-01.mkiv
index ed87346d6f5..ae119a7eed8 100644
--- a/Master/texmf-dist/tex/context/base/s-mod-01.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-mod-01.mkiv
@@ -2,37 +2,271 @@
%D [ file=s-mod-01,
%D version=very-old,
%D title=\CONTEXT\ Style File,
-%D subtitle=Documentation Paper Environment,
-%D author=Hans Hagen,
+%D subtitle=Module Documentation,
+%D author={Hans Hagen \& Luigi Scarso},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 looks like crap, is not documented, will
-%D change, and used to be called modu-*.tex.
+\unprotect
-% now split in mkii/mkiv so we will cleanup
+%D Usage:
+%D
+%D \starttyping
+%D context --ctx=s-mod somefile.mkiv
+%D \stoptyping
+%D
+%D In due time there will be a \type {mtx-context-module} as well.
+%D
+%D Luigi Scarso coordinates the processing of modules so best contact
+%D him when you run into problems. Bugs in this style can be sent to
+%D Hans.
+
+\setvariables
+ [document]
+ [ file=\jobname,
+ type=unknown,
+ version={\currentdate[\v!year,{.},\v!month,{.},\v!day]},
+ system=\CONTEXT,
+ title=Unknown Title,
+ subtitle=,
+ author=Unknown Author,
+ date=\currentdate,
+ copyright=Unknown Copyright,
+ suggestions=]
-\usemodule[mod-00,abr-01]
+\let\module\setupdocument
-\dontcomplain
+\definepalet [module:unknown] [localone=black,localtwo=white]
-\unprotect
+\definepalet [module:tex] [localone=blue,localtwo=green]
+\definepalet [module:mkii] [localone=blue,localtwo=green]
+\definepalet [module:mkiv] [localone=blue,localtwo=green]
+\definepalet [module:mkvi] [localone=blue,localtwo=green]
-\setupbodyfont
- [10pt]
+\definepalet [module:lua] [localone=red,localtwo=green]
+\definepalet [module:cld] [localone=red,localtwo=green]
+
+\definepalet [module:mp] [localone=red,localtwo=blue]
+\definepalet [module:mpii] [localone=red,localtwo=blue]
+\definepalet [module:mpiv] [localone=red,localtwo=blue]
+\definepalet [module:metapost][localone=red,localtwo=blue]
+
+\setuppalet
+ [module:unknown]
+
+\startuseMPgraphic{page}
+
+ StartPage ;
+
+ color local_white ; local_white := .8white ;
+ color local_one ; local_one := \MPcolor{localone} randomized (.6,.8) ;
+ color local_two ; local_two := \MPcolor{localtwo} randomized (.3,.4) ;
+
+ color local_one ; local_one := .75[\MPcolor{localone},white] ;
+ color local_two ; local_two := .75[\MPcolor{localtwo},white] ;
+
+ numeric width ; width := bbwidth Page ;
+ numeric height ; height := bbheight Page ;
+
+ u := width/400 ;
+
+ def a_module (expr dx, dy) =
+ picture p ; p := image (
+ ddy := 0 ; sx := 60u ;
+ for i=1 upto (4 randomized 2) :
+ sy := 7u randomized 3u ;
+ fill unitsquare xyscaled(sx,sy) shifted (0,ddy) withcolor local_two ;
+ ddy := ddy + sy + 4u ;
+ endfor ;
+ ) ;
+ p := p shifted (dx,dy) shifted - center p ;
+ fill boundingbox p enlarged 8u withcolor local_white ;
+ fill boundingbox p enlarged 4u withcolor local_one ;
+ draw p ;
+ enddef ;
+
+ set_grid(width, height, width/15, height/15) ;
+
+ forever:
+ if new_on_grid(uniformdeviate width,uniformdeviate height):
+ a_module(dx,dy) ;
+ fi ;
+ exitif grid_full ;
+ endfor ;
+
+ picture p ;
+
+ draw image (
+ draw anchored.urt(textext("\bf\strut\documentvariable{system}") ysized 5.0cm,urcorner Page shifted (-1cm,- 1cm)) ;
+ draw anchored.urt(textext("\bf\strut\documentvariable{title}") ysized 1.5cm,urcorner Page shifted (-1cm,- 8cm)) ;
+ draw anchored.urt(textext("\bf\strut\documentvariable{subtitle}") ysized 1.5cm,urcorner Page shifted (-1cm,-10cm)) ;
+ draw anchored.urt(textext("\bf\strut\documentvariable{author}") ysized 1.5cm,lrcorner Page shifted (-1cm, 5cm)) ;
+ draw anchored.urt(textext("\bf\strut\currentdate") ysized 1.5cm,lrcorner Page shifted (-1cm, 3cm)) ;
+ ) withcolor .25white ;
+
+ StopPage ;
+
+\stopuseMPgraphic
+
+\startsetups[document:start]
+
+ \setuppalet
+ [module:\documentvariable{type}]
+
+ \startTEXpage
+ \useMPgraphic{page}
+ \stopTEXpage
+
+ \page[right]
+
+\stopsetups
+
+\startsetups[document:stop]
+
+ \page
+
+ \placeregister
+ [\v!index]
+ [\c!balance=\v!yes,
+ \c!indicator=\v!no,
+ \c!criterium=\v!text]
+
+\stopsetups
+
+% In order to be able to typeset this one too, we need to avoid
+% direct backslashed names.
+
+\starttexdefinition startmoduledocumentation
+ \starttext
+ \page
+ \begingroup
+ \startdocument
+\stoptexdefinition
+
+\starttexdefinition stopmoduledocumentation
+ \stopdocument
+ \page
+ \endgroup
+ \stoptext
+\stoptexdefinition
+
+\starttexdefinition startdocumentation
+ \par
+ \bgroup
+\stoptexdefinition
+
+\starttexdefinition stopdocumentation
+ \par
+ \egroup
+\stoptexdefinition
+
+\definetyping
+ [definition]
+
+\starttexdefinition startcompressdefinitions
+ \blank
+ \begingroup
+ \setuptyping[definition][bodyfont=small]
+\stoptexdefinition
+
+\starttexdefinition stopcompressdefinitions
+ \blank
+ \endgroup
+\stoptexdefinition
+
+\definetyping [PL] [\c!option=PL]
+\definetyping [JV] [\c!option=JV]
+\definetyping [MP] [\c!option=MP]
+\definetyping [TEX] [\c!option=TEX]
+\definetyping [LUA] [\c!option=LUA]
+
+\setuptyping [\v!typing] [\c!margin=\v!standard]
+\setuptyping [\v!file] [\c!margin=\v!standard]
+\setuptyping [definition] [\c!margin=0pt,\c!numbering=\v!line,\c!continue=\v!yes] % this continue wins
+
+\setuplinenumbering
+ [definition]
+ [\c!style=\ttx,
+ \c!distance=\leftmargindistance,
+ \c!align=\v!flushright]
+
+% This will be cleaned up.
+
+\unexpanded\def\domodulemarginstuff#1#2%
+ {\marginstuff
+ {\ifx#1\relax
+ \index{#2}%
+ \else
+ \index{#1{#2}}%
+ \fi
+ #1{\doboundtext{#2}{\leftmarginwidth}{..}}}}
+
+\unexpanded\def\modulemarginstuff#1#2% to be renamed
+ {\processcommalist[#2]{\domodulemarginstuff#1}}
+
+\definemargindata
+ [marginstuff]
+ [left]
+ [stack=yes,
+ hoffset=2em,
+ style=\ttxx]
+
+\unexpanded\def\macros {\modulemarginstuff\tex }
+\unexpanded\def\extras {\modulemarginstuff\relax}
+\unexpanded\def\elements{\modulemarginstuff\someelement}
-\definetypeface [narrowtt] [tt] [mono] [modern-cond] [default]
+\unexpanded\def\someelement#1{\type{<#1>}}
-\setuptyping[\v!typing][\c!style=\narrowtt]
-\setuptype [\v!type] [\c!style=\narrowtt]
+% [index]{command}
+
+% \macros{a,b}
+% \macros{a,b}{b}
+% \macros[a]{a,b}{b}
+
+% weg ermee (indeed):
+%
+% \defineparagraphs [interface] [\c!n=2]
+% \setupparagraphs [interface] [1] [\c!width=4cm]
+
+\starttexdefinition startexample
+ \par
+ \startnarrower
+\stoptexdefinition
+
+\starttexdefinition stopexample
+ \stopnarrower
+\stoptexdefinition
+
+%D Command references:
+
+\usemodule[int-load] \loadsetups
+
+\let\showsetup\setup
+
+\setupframedtexts
+ [setuptext]
+ [\c!background=\v!screen,
+ \c!frame=\v!off]
+
+% style (we use dejavu as it supports more characters)
+
+\switchtobodyfont
+ [dejavu-condensed,10pt] % preload
+
+\setupbodyfont
+ [dejavu,10pt] % main font
\mainlanguage
[en]
+\setuptyping
+ [\v!typing]
+ [\c!bodyfont=dejavu-condensed]
+
\setupwhitespace
[\v!big]
@@ -54,49 +288,30 @@
\c!height=middle,
\c!style=\ss]
-\setupsetup
- [\c!reference=1] % mkiv?
-
-\startnotmode[single]
-
- \setuppagenumbering
- [\c!alternative={\v!doublesided,\v!singlesided}]
-
-\stopnotmode
-
\setuppagenumbering
[\c!location=]
+\setuppagenumbering
+ [\c!alternative={\v!doublesided,\v!singlesided}]
+
\setupfootertexts
[\v!edge]
- [][\v!pagenumber]
+ [][\pagenumber]
-\startmode[single]
-
- \setupfootertexts
- [\v!margin]
- [\filename{\Modulefile}][]
-
-\stopmode
-
-\startnotmode[single]
-
- \setupfootertexts
- [\v!margin]
- [\filename{\Modulefile}][]
- [\filename{\Modulefile}][]
-
-\stopnotmode
+\setupfootertexts
+ [\v!margin]
+ [\filename{\documentvariable{file}}][]
+ [\filename{\documentvariable{file}}][]
\setupfootertexts
[\v!text]
[\CONTEXT]
- [\Moduletitle]
+ [\documentvariable{title}]
\setupheadertexts
[\v!text]
[]
- [\Modulesubtitle]
+ [\documentvariable{subtitle}]
\setupinmargin
[\c!location=\v!left]
@@ -106,15 +321,19 @@
\setuphead
[\v!chapter]
- [\c!style=\ssc,
+ [\c!style=\bfc,
\c!page=\v!right,
\c!header=\v!empty]
\setuphead
[\v!section]
- [\c!style=\ssb,
+ [\c!style=\bfb,
\c!page=\v!right]
+\setuphead
+ [\v!subsection]
+ [\c!style=\bfa]
+
\setuplist
[\v!chapter]
[\c!style=\v!bold,
@@ -130,17 +349,39 @@
[\c!balance=\v!yes,
\c!indicator=\v!no]
-\startmode[nocolor]
-
- \setupcolors
- [\c!conversion=\v!always]
-
-\stopmode
-
\setupinteraction
[\c!state=\v!start,
\c!color=,
\c!contrastcolor=,
\c!style=]
+% modes
+
+\doifmode {nocolor} {
+
+ \setupcolors
+ [\c!conversion=\v!always]
+
+}
+
+\doifmode {singlesided} {
+
+ \setuppagenumbering
+ [\c!alternative=\v!singlesided]
+
+ \setupfootertexts
+ [\v!margin]
+ [\filename{\documentvariable{file}}][]
+
+}
+
+% bonus
+
+\usemodule
+ [abr-02]
+
+% another one
+
+\dontcomplain
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/s-mod-02.mkii b/Master/texmf-dist/tex/context/base/s-mod-02.mkii
index bc53f689008..2d095ff9ab6 100644
--- a/Master/texmf-dist/tex/context/base/s-mod-02.mkii
+++ b/Master/texmf-dist/tex/context/base/s-mod-02.mkii
@@ -5,7 +5,7 @@
%D subtitle=Documentation Screen Environment,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-mod-02.mkiv b/Master/texmf-dist/tex/context/base/s-mod-02.mkiv
index 1ca88b796d9..032ace8a645 100644
--- a/Master/texmf-dist/tex/context/base/s-mod-02.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-mod-02.mkiv
@@ -5,419 +5,14 @@
%D subtitle=Documentation Screen Environment,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 looks like crap, is not documented, will
-%D change, and used to be called modu-*.tex.
-
-% now split in mkii/mkiv so we will cleanup
-
-% Macro's
-
-\usemodule[mod-00]
-
\unprotect
-% todo: internationalize + setups
-
-\setuphead[paragraaf][expansion=command]
-\setuphead[section][expansion=command]
-
-\def\complexmodule[#1]% redefined
- {\startglobal % i.v.m. \bgroup in \startdocumentation
- \getparameters[Module][#1]
- \stopglobal % i.v.m. \bgroup in \startdocumentation
- %%\section{\Modulesubtitle}
- \xdef\Temp{\Modulesubtitle}%%Modulesubtitle:\framed{BEGIN \Modulesubtitle END} :#1 !}
- \@EA\section\@EA{\Temp}
- \WriteLists}
-
-\def\stopmodule % redefined
- {\page
- \determineregistercharacteristics
- [index]
- [criterium=section]
- \doifmode{*register}
- {\pagereference
- [index]
- \placeregister
- [index]
- [balance=yes,
- indicator=no,
- criterium=section]}}
-
-\let\ComposeLists=\relax
-
-\newcounter\ModuleNumber
-
-\newwrite\BatchFile \openout\BatchFile=\jobname.bat
-
-\def\WriteBatchFile
- {\doglobal\increment\ModuleNumber
-% \immediate\write\BatchFile{call modu-run \FileName\space \ModuleNumber}}
-% \immediate\write\BatchFile{texmfstart texutil --modu \FileName}}
- \immediate\write\BatchFile{texmfstart texexec --pdf --modu --batch \FileName }}
-
-\newif\ifProcessingPublic
-
-\def\WriteLists
- {\writetolist[FileNames] {}{\FileName}
- \writetolist[GroupItems]{}{\GroupItem}}
-
-\def\moduletitle{}
-
-\def\TypeZeroModule#1%
- {\section{[to be extracted: #1]}
- {\em This module is not yet split off.}
- \WriteLists}
-
-\def\TypeOneModule#1%
- {\section{[to be documented: #1]}
- {\em This module is not yet fully documented.}
- \WriteLists}
-
-\def\TypeTwoModule#1%
- {\ifProcessingPublic
- \readfile{#1.ted}{}{}%
- \WriteBatchFile
- \else
- \section{[not yet public: #1]}
- {\em This module is documented but not yet public.}
- \WriteLists
- \fi}
-
-\def\TypeThreeModule#1%
- {\readfile{#1.ted}{}{}%
- \WriteBatchFile}
-
-\def\processmodule#1#2%
- {\page
- \bgroup
- \def\FileName{#1}
- \setupreferencing[prefix=#1]
- \useexternaldocument[PaperVersion][#1][]
- \aftersplitstring#1\at-\to\GroupItem
- \ComposeLists
- \ifcase#2
- \TypeZeroModule{#1}
- \or
- \TypeOneModule{#1}
- \or
- \TypeTwoModule{#1}
- \or
- \TypeThreeModule{#1}
- \fi
- \page
- \setupreferencing[prefix=]
- \egroup}
-
-\def\ModuleGroup#1#2%
- {\page
- \let\Modulefile=\empty
- \setupreferencing[prefix=#1]
- \def\FileGroup{#1}
- \writetolist[FileGroups]{}{\FileGroup}
- \chapter[content]{#2}
- \MakeListOfItems
- \MakeListOfNames
- \MakeListOfGroups
- \placecontent[criterium=chapter,level=section]}
-
-% Layout
-
-\setupbodyfont
- [9pt]
-
-\setuppapersize
- [S6][S6]
-
-\setuplayout
- [backspace=72.5pt,
- leftmargin=50pt,
- leftmargindistance=12.5pt,
- rightmargin=0pt,
- rightedge=80pt,
- rightedgedistance=10pt,
- leftedge=0pt,
- width=430pt,
- topspace=10pt,
- header=0pt,
- footer=30pt,
- bottomdistance=10pt,
- bottom=15pt,
- height=410pt,
- style=\ss]
-
-\setuptyping
- [palet=colorpretty]
-
-\setupsetup
- [reference=3]
-
-\definecolor [AchtergrondKleur] [s=.6]
-\definecolor [ButtonKleur] [r=.2,g=.2,b=.6]
-\definecolor [TekstKleur] [r=.6,g=.2,b=.2]
-
-\definecolor [colorprettyone] [r=.6,g=.0,b=.0] % red
-\definecolor [colorprettytwo] [r=.0,g=.6,b=.0] % green
-\definecolor [colorprettythree] [r=.0,g=.0,b=.6] % blue
-\definecolor [colorprettyfour] [r=.6,g=.6,b=.0] % yellow
-
-\setupinteraction
- [state=start,
- page=yes,
- contrastcolor=,
- menu=on,
- color=]
-
-\setupbackgrounds
- [page]
- [background=color,
- backgroundcolor=AchtergrondKleur,
- offset=2.5pt] % this offset influences the menus!
-
-\setupbackgrounds
- [text,footer]
- [text,leftmargin]
- [background=color,
- backgroundcolor=white]
-
-\setupsubpagenumber
- [way=bysection,
- state=start]
-
-\setupinteractionbar
- [frame=off,
- offset=0pt,
- height=fit]
-
-\setupwhitespace
- [big]
-
-\setuptyping
- [typing]
- [option=color]
-
-\setuptyping
- [definition]
- [option=color]
-
-\setuptyping
- [file]
- [option=color]
-
-\setuppagenumbering
- [alternative=singlesided,
- way=bysection,
- state=none]
-
-\setupinmargin
- [location=left]
-
-\setupheads
- [alternative=inmargin]
-
-\setuphead
- [chapter]
- [style=\ssc,
- page=right]
-
-\setuphead
- [section]
- [style=\ssb,
- page=right]
-
-\setuplist
- [chapter]
- [style=bold,
- after=\blank]
-
-\setupcontent
- [width=2em]
-
-\setupindex
- [balance=yes,
- indicator=no]
-
-\setupcolors
- [state=start]
-
-\def\TitelBlad#1%
- {\startstandardmakeup
- \definefont[GrootFont] [SansBold at 72pt]
- \definefont[MiddelFont][Sans at 32pt]
- \definefont[KleinFont] [Sans at 24pt]
- \startcolor[AchtergrondKleur]
- \vskip12pt
- \midaligned{\GrootFont\setstrut\strut Con\TeX t}
- \vskip24pt
- \midaligned{\MiddelFont\setstrut\strut #1}
- \vskip24pt
- \midaligned{\KleinFont\setstrut\strut Hans Hagen}
- \vfilll
- \midaligned{\KleinFont\setstrut\strut PRAGMA ADE}
- \vskip24pt
- \midaligned{\KleinFont\setstrut\strut www.pragma-ade.com --- \currentdate}
- \vskip12pt
- \stopcolor
- \stopstandardmakeup}
-
-\def\ColofonBlad
- {\startmode[atpragma]
- \page
- \bgroup
- \def\PragmaHoogte {\makeupheight}
- \def\PragmaBreedte{\textwidth}
- \def\PragmaKopwit {\topspace}
- \def\PragmaRugwit {\backspace}
- \def\PragmaMarge {0pt}
- \PragmaLijnentrue
- \PlaatsPragmaLogo[ADE]
- \vfill
- todo: colofon
- \startnarrower[3*middle]
- This is the official documentation of \CONTEXT\ version
- \referraldate, a \TEX\ macropackage developed by J.~Hagen
- \& A.F.~Otten, who both hold the copyrights.
- \stopnarrower
- \vfill
- \page
- \egroup
- \stopmode}
-
-\def\ColofonBlad
- {}
-
-\newbox\ListOfItems
-\newbox\ListOfGroups
-\newbox\ListOfNames
-
-\definelist[FileNames] \def\FileName {}
-\definelist[FileGroups] \def\FileGroup {}
-\definelist[GroupItems] \def\GroupItem {}
-
-\setuplist
- [FileNames,FileGroups,FileGroups]
- [expansion=yes,
- pagenumber=no,
- style=\ss\bf]
-
-\setuplist
- [FileNames]
- [command=\FileNameEntry,
- after=\endgraf,
- alternative=none] % horizontal
-
-\setuplist
- [FileGroups]
- [command=\FileGroupEntry,
- after=\hss,
- alternative=horizontal]
-
-\def\FileNameEntry#1#2#3%
- {\strut\hbox{#2}\endgraf}
-
-\def\FileGroupEntry#1#2#3%
- {\strut\hbox{#2}\endgraf}
-
-\def\MakeListOfItems
- {\setbox\ListOfItems=\vbox
- {\ss\bf
- \placelist[GroupItems][color=ButtonKleur,contrastcolor=white,criterium=chapter]}}
-
-\def\MakeListOfNames
- {\setbox\ListOfNames=\vbox
- {\hsize\rightedgewidth
- \ss\bf\setupinterlinespace
- \startsimplecolumns[distance=10pt]
- \placelist[FileNames][color=ButtonKleur,contrastcolor=white,criterium=chapter]
- \stopsimplecolumns}}
-
-\def\MakeListOfGroups
- {\setbox\ListOfGroups=\hbox to \textwidth
- {\ss\bf
- \setupinteraction[color=ButtonKleur]%
- \placelist[FileGroups][color=ButtonKleur,contrastcolor=white,criterium=all]\unskip\unskip}}
-
-\setbox\ListOfGroups=\hbox{}
-
-%\setupfootertexts
-% [rand]
-% []
-% [{\interactiebalk[variant=g]}]
-
-\setupinteractionmenu
- [right,bottom]
- [state=start,
- frame=off,
- color=AchtergrondKleur,
- contrastcolor=white,
- style=\ss\bf,
- height=15pt,
- offset=0pt,
- inbetween=\vskip5pt,
- background=color,
- backgroundcolor=ButtonKleur]
-
-\startinteractionmenu[right]
- \boxofsize \vbox \textheight \footerdistance \footerheight 5pt
- \bgroup
- \copy\ListOfNames
- \vfill
- \but [\FileGroup:content] local contents \\
- \but [\FileName:index] local register \\
- \but [PaperVersion::begin] paper version \\
- \but [content] main contents \\
- \but [index] main register \\
- \but [PreviousJump] previous jump \\
- \but [CloseDocument] close document \\
- \unskip
- \egroup
-\stopinteractionmenu
-
-\startinteractionmenu[bottom]
- \unhcopy\ListOfGroups
-\stopinteractionmenu
-
-\def\placemoduleregister
- {\startbackmatter
- \setupsubpagenumber[reset]
- \title[-:index]{Register}
- \placeregister[index]
- \stopbackmatter}
-
-\def\placemodulecontent
- {\startfrontmatter
- \title[-:content]{Contents}
- \setupinteractionbar[state=stop]
- \placecontent[criterium=text,level=chapter]
- \stopfrontmatter}
-
-\setupcontent
- [pagenumber=no,
- level=chapter,
- interaction=all,
- style=,
- before=,
- after=]
-
-\setupfootertexts
- [margin]
- [\tt\Modulefile]
- []
-
-\setupfootertexts
- [text]
- [chapter][chapter]
-
-\setupindex
- [symbol=1]
-
-\setuptolerance
- [verytolerant]
+% gone
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/s-mod.ctx b/Master/texmf-dist/tex/context/base/s-mod.ctx
index a85c991a57b..5059c77d442 100644
--- a/Master/texmf-dist/tex/context/base/s-mod.ctx
+++ b/Master/texmf-dist/tex/context/base/s-mod.ctx
@@ -14,6 +14,7 @@
<!-- ctx:flag>purge</ctx:flag -->
<ctx:flag>global</ctx:flag>
<ctx:flag>prep</ctx:flag>
+ <ctx:flag>purge</ctx:flag>
</ctx:flags>
<ctx:process>
<ctx:resources>
diff --git a/Master/texmf-dist/tex/context/base/s-phy-01.mkiv b/Master/texmf-dist/tex/context/base/s-phy-01.mkiv
new file mode 100644
index 00000000000..dde3f9bbb32
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/s-phy-01.mkiv
@@ -0,0 +1,111 @@
+%D \module
+%D [ file=s-phy-01,
+%D version=2011-11-24,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Units 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.
+
+\unprotect
+
+% todo: better breaks of head line
+
+\startluacode
+moduledata.units = moduledata.units or { }
+
+local tables = physics.units.tables
+local units = tables.units
+local shortcuts = tables.shortcuts
+
+local HL = context.HL
+local NC = context.NC
+local NR = context.NR
+
+local function typeset(list,followup,name,category)
+ if list then
+ if followup then
+ context.TB()
+ end
+ if category then
+ HL()
+ NC()
+ context.rlap(category .. ":" .. name)
+ NC()
+ NC()
+ NR()
+ HL()
+ end
+ for k, v in table.sortedhash(list) do
+ NC()
+ context(k)
+ NC()
+ if isunit then
+ context(v)
+ else
+ context.type(v)
+ end
+ NC()
+ if name == "units" or name == "symbols" or name == "packaged" then
+ context.unittext(v)
+ elseif name == "prefixes" then
+ context.prefixtext(v)
+ elseif name == "operators" then
+ context.operatortext(v)
+ elseif name == "suffixes" then
+ context.suffixtext(v)
+ end
+ NC()
+ NR()
+ end
+ if category and name then
+ HL()
+ end
+ end
+end
+
+function moduledata.units.show_table(name)
+ context.starttabulate { "|lT|l|c|" }
+ if name and name ~= "" then
+ local first, second = string.match(name,"(.-):(.-)") -- [units|shortcuts]:[units|...]
+ if first then
+ typeset(tables[first] and tables[first][second],false)
+ else
+ typeset(units[name],false)
+ typeset(shortcuts[name],true)
+ end
+ else
+ local done = false
+ for what, list in table.sortedhash(units) do
+ typeset(list,done,what,"units")
+ done = true
+ end
+ for what, list in table.sortedhash(shortcuts) do
+ typeset(list,done,what,"shortcuts")
+ done = true
+ end
+ end
+ context.stoptabulate()
+end
+
+\stopluacode
+
+\unexpanded\def\ShowUnitsTable
+ {\dosingleempty\Show_Units_Table}
+
+\def\Show_Units_Table[#1]%
+ {\ctxlua{moduledata.units.show_table("#1")}}
+
+\protect
+
+\continueifinputfile{s-phy-01.mkiv}
+
+\usemodule[art-01]
+
+\starttext
+ \ShowUnitsTable
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/s-pre-00.tex b/Master/texmf-dist/tex/context/base/s-pre-00.tex
index 7b22e2fd9a0..7f217d5bb89 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-00.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-00.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 0,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-01.tex b/Master/texmf-dist/tex/context/base/s-pre-01.tex
index b86133fa66b..89c5642f9f5 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-01.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-01.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 1,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-02.tex b/Master/texmf-dist/tex/context/base/s-pre-02.tex
index 9df1fe3833c..d7a6fe4589a 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-02.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-02.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 2,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-03.tex b/Master/texmf-dist/tex/context/base/s-pre-03.tex
index bdd7960c5a4..19a11d24e5d 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-03.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-03.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 3,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-04.tex b/Master/texmf-dist/tex/context/base/s-pre-04.tex
index 09cc79b72e8..088f4e510ed 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-04.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-04.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 4,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-05.tex b/Master/texmf-dist/tex/context/base/s-pre-05.tex
index 9b3ae89ff04..8081127879d 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-05.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-05.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 5,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-06.tex b/Master/texmf-dist/tex/context/base/s-pre-06.tex
index 7a84323e934..21e7236e7fd 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-06.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-06.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 6,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-07.tex b/Master/texmf-dist/tex/context/base/s-pre-07.tex
index bf84971bbd3..ba62b323694 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-07.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-07.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 7,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-08.tex b/Master/texmf-dist/tex/context/base/s-pre-08.tex
index 42531029908..b545bef2386 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-08.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-08.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 8,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-09.tex b/Master/texmf-dist/tex/context/base/s-pre-09.tex
index a829dd6e2d9..a20b9f31acd 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-09.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-09.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 9,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-10.tex b/Master/texmf-dist/tex/context/base/s-pre-10.tex
index 67a867ec74c..a92e5af01c5 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-10.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-10.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 10,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-11.tex b/Master/texmf-dist/tex/context/base/s-pre-11.tex
index 23bf9e22318..551c5ebbcce 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-11.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-11.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 11,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-12.tex b/Master/texmf-dist/tex/context/base/s-pre-12.tex
index 722d59ced39..23418fbba34 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-12.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-12.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 12,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-13.tex b/Master/texmf-dist/tex/context/base/s-pre-13.tex
index 6032f36d286..7b4daa4b31f 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-13.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-13.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 13,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-14.tex b/Master/texmf-dist/tex/context/base/s-pre-14.tex
index 93f8cdbc35e..4dae6c0097b 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-14.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-14.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 14,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-15.tex b/Master/texmf-dist/tex/context/base/s-pre-15.tex
index c9a157abb86..25fb357839a 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-15.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-15.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 15,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-16.tex b/Master/texmf-dist/tex/context/base/s-pre-16.tex
index 81f21ec609a..715936890bd 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-16.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-16.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 16,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-17.tex b/Master/texmf-dist/tex/context/base/s-pre-17.tex
index 798f30cf841..7e8310a537e 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-17.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-17.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 17,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-18.tex b/Master/texmf-dist/tex/context/base/s-pre-18.tex
index d92117aaf79..876eec5f1f8 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-18.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-18.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 18,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-19.tex b/Master/texmf-dist/tex/context/base/s-pre-19.tex
index 3715d6ac176..991d311ced0 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-19.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-19.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 19,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-22.tex b/Master/texmf-dist/tex/context/base/s-pre-22.tex
index 8930c34be02..be50ae195e4 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-22.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-22.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 22,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-23.tex b/Master/texmf-dist/tex/context/base/s-pre-23.tex
index 90ed183532f..f9983a89ed7 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-23.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-23.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 20,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-26.tex b/Master/texmf-dist/tex/context/base/s-pre-26.tex
index a995169607d..7c1dec5f8f1 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-26.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-26.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 26,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-27.tex b/Master/texmf-dist/tex/context/base/s-pre-27.tex
index eda75e8f468..2e201e8df93 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-27.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-27.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 27,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-30.mkii b/Master/texmf-dist/tex/context/base/s-pre-30.mkii
index 2a3899c9290..a7152deb60b 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-30.mkii
+++ b/Master/texmf-dist/tex/context/base/s-pre-30.mkii
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 30,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-30.mkiv b/Master/texmf-dist/tex/context/base/s-pre-30.mkiv
index c3b524047d6..1be85d02b1c 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-30.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-pre-30.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 30,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -242,13 +242,13 @@
\StartSample{Basics}
\startbuffer
-\lua{a = 1.5 ; b = 1.8 ; c = a*b ; tex.print(c) ;}
+\lua{a = 1.5 ; b = 1.8 ; c = a*b ; context(c) ;}
\startlua
a = 1
b = 2
c = a*b
- tex.print(c)
+ context(c)
\stoplua
\stopbuffer
diff --git a/Master/texmf-dist/tex/context/base/s-pre-50.tex b/Master/texmf-dist/tex/context/base/s-pre-50.tex
index 41ae048215d..ff3e48631ea 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-50.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-50.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 50,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -76,7 +76,7 @@
%D Trick. Nowadays we can use streams.
-\installoutput\FlushStep
+\installoutputroutine\FlushStep
{\StartStep\unvbox\normalpagebox\StopStep}
%D Demo.
diff --git a/Master/texmf-dist/tex/context/base/s-pre-60.mkii b/Master/texmf-dist/tex/context/base/s-pre-60.mkii
index 4df3e8a617b..8823c66ce1e 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-60.mkii
+++ b/Master/texmf-dist/tex/context/base/s-pre-60.mkii
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 60,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-60.mkiv b/Master/texmf-dist/tex/context/base/s-pre-60.mkiv
index aa5ec36d085..b39a0631169 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-60.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-pre-60.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 60,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-61.tex b/Master/texmf-dist/tex/context/base/s-pre-61.tex
index 216bb9a003c..21e461320a4 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-61.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-61.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 61,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -221,7 +221,7 @@
[bottom] [text]
[background=topics]
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-pre-61.tex}
\starttext
@@ -234,6 +234,7 @@
\StartSteps
\startitemize
+\item Fiona Apple \FlushStep
\item Tori Amos \FlushStep
\item Kate Bush \FlushStep
\item Heather Nova \FlushStep
diff --git a/Master/texmf-dist/tex/context/base/s-pre-62.tex b/Master/texmf-dist/tex/context/base/s-pre-62.tex
index 8e50af5292e..cc9762e12c8 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-62.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-62.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 62,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -54,14 +54,13 @@
backspace=5\measure{layoutwd},
topspace=5\measure{layoutht}]
-\setuplayout
+\definelayout
[step]
[ backspace=\numexpr2+ \getvariable{layout}{dx}\relax\measure{layoutwd},
cutspace=\numexpr3+\getvariable{layout}{nx}-\getvariable{layout}{dx}\relax\measure{layoutwd},
topspace=\numexpr2+ \getvariable{layout}{dy}\relax\measure{layoutht},
bottomspace=\numexpr3+\getvariable{layout}{ny}-\getvariable{layout}{dy}\relax\measure{layoutht}]
-
\definecolor[layout:left] [t=.5,a=1,b=1]
\definecolor[layout:right] [t=.5,a=1,r=1]
\definecolor[layout:top] [t=.5,a=1,g=1]
diff --git a/Master/texmf-dist/tex/context/base/s-pre-63.tex b/Master/texmf-dist/tex/context/base/s-pre-63.tex
index 1a0fdf607c1..0535fc1d06c 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-63.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-63.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 63,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-64.tex b/Master/texmf-dist/tex/context/base/s-pre-64.tex
index 9e82b255c55..ef4889bbb66 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-64.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-64.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 64,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-66.tex b/Master/texmf-dist/tex/context/base/s-pre-66.tex
index e085caedafd..3e89e4a7e11 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-66.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-66.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 66,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=Hans Hagen]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-68.tex b/Master/texmf-dist/tex/context/base/s-pre-68.tex
index 616d410eb9c..3c04a87e15a 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-68.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-68.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 68,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-69.mkiv b/Master/texmf-dist/tex/context/base/s-pre-69.mkiv
index 9cf6fdfd55a..c87bcd53745 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-69.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-pre-69.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 69,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
@@ -231,7 +231,8 @@
shape[#shape+1] = string.format("%sbp %sbp",left,hsize)
end
-- print(table.serialize(shape))
- tex.sprint(tex.ctxcatcodes,string.format("\\parshape %s %s",#shape,table.concat(shape," ")))
+ -- context.parshape(string.format("%s %s ",#shape,table.concat(shape," ")))
+ context("\\parshape %s %s ",#shape,table.concat(shape," "))
end
\stopluacode
diff --git a/Master/texmf-dist/tex/context/base/s-pre-70.mkiv b/Master/texmf-dist/tex/context/base/s-pre-70.mkiv
index 60462cf7a9b..2c8bb2d2648 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-70.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-pre-70.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 70,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA / Hans Hagen]
+%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
@@ -119,16 +119,16 @@
[state=start]
\startinteractionmenu[bottom]
- \txt
+ \starttxt
\interactionbar
[alternative=d,
symbol=yes,
color=white,
contrastcolor=textcolor]
- \\
+ \stoptxt
\hfilll
- \but [previouspage] < < < \\
- \but [nextpage] > > > \\
+ \startbut [previouspage] < < < \stopbut
+ \startbut [nextpage] > > > \stopbut
\stopinteractionmenu
%D Instead of the normal symbols we use more punky ones.
@@ -150,7 +150,7 @@
%D Run this file with the command: \type {context --mode=demo s-pre-70}
%D in order to get an example.
-\doifnotmode{demo} {\endinput}
+\continueifinputfile{s-pre-70.mkiv}
\usemodule[pre-60] % use the stepper
@@ -159,14 +159,18 @@
\title {Punk for dummies}
\dorecurse{10} {
+
\title{Just a few dummy pages}
- \StartSteps \startitemize[packed]
- \startitemize
- \startitem bla \FlushStep \stopitem
- \startitem bla bla \FlushStep \stopitem
- \startitem bla bla bla \FlushStep \stopitem
- \startitem bla bla bla bla \FlushStep \stopitem
- \stopitemize \StopSteps
+
+ \StartSteps
+ \startitemize[packed]
+ \startitem bla \FlushStep \stopitem
+ \startitem bla bla \FlushStep \stopitem
+ \startitem bla bla bla \FlushStep \stopitem
+ \startitem bla bla bla bla \FlushStep \stopitem
+ \stopitemize
+ \StopSteps
+
}
\stoptext
diff --git a/Master/texmf-dist/tex/context/base/s-pre-71.mkii b/Master/texmf-dist/tex/context/base/s-pre-71.mkii
index db65c8e2819..3431367685e 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-71.mkii
+++ b/Master/texmf-dist/tex/context/base/s-pre-71.mkii
@@ -7,7 +7,7 @@
%D subtitle=Presentation Environment 71,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-71.mkiv b/Master/texmf-dist/tex/context/base/s-pre-71.mkiv
index 69280243b55..38dae61dfa5 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-71.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-pre-71.mkiv
@@ -7,7 +7,7 @@
%D subtitle=Presentation Environment 71,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -145,7 +145,7 @@
\let\StartText\starttext
\let\StopText \stoptext
-\doifnotmode{demo}{\endinput}
+\continueifinputfile{s-pre-71.mkiv}
\starttext
diff --git a/Master/texmf-dist/tex/context/base/s-pre-93.tex b/Master/texmf-dist/tex/context/base/s-pre-93.tex
index 7eabd5ed133..c36762f3861 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-93.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-93.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 20,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-pre-96.tex b/Master/texmf-dist/tex/context/base/s-pre-96.tex
index 705e74eecd4..2ad752007c3 100644
--- a/Master/texmf-dist/tex/context/base/s-pre-96.tex
+++ b/Master/texmf-dist/tex/context/base/s-pre-96.tex
@@ -5,7 +5,7 @@
%D subtitle=Presentation Environment 26,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-ptj-01.tex b/Master/texmf-dist/tex/context/base/s-ptj-01.tex
index 9990bf00615..a14a03ef145 100644
--- a/Master/texmf-dist/tex/context/base/s-ptj-01.tex
+++ b/Master/texmf-dist/tex/context/base/s-ptj-01.tex
@@ -6,7 +6,7 @@
%D author=Aditya Mahajan,
%D email=adityam at umich dot edu,
%D date=\currentdate,
-%D copyright=2009 Aditya Mahajan]
+%D copyright={Aditya Mahajan}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
@@ -72,7 +72,7 @@
%D uses latin modern for sans serif and monotype. For the main face, 12pt is
%D used with a 15.5pt baseline skip. Font protrusion is enabled, but font
%D expansion is not. We follow these conventions. \CONTEXT\ uses Pagella fonts
-%D from \TEX{gyre} project, so we use them instead.
+%D from \TEX{gyre} project, so we use them instead.
\usetypescript [serif,sans,mono] [hanging] [pure]
\setupalign [hanging]
@@ -148,7 +148,7 @@
after={\blank[big]}]
%D Next we define internal frames to take care of the layout of the extra
-%D material in the title.
+%D material in the title.
\defineframed
[pracjourninfotitle]
@@ -223,7 +223,7 @@
author={\getvariable{pracjourn}{author}},
subtitle={The PracTeX Journal Article}]
\stopsetups
-
+
% If revision number is present, write it to \filename{_rev.tex}
% FIXME: Do we need to ensure that the dates and month are two digits?
\startrawsetups [pracjourndate]
@@ -266,8 +266,8 @@
\definetext [pracjourntitleheader] [header] [\setups{pracjourntitleheader}][]
\definetext [pracjourntitlefooter] [footer] [\setups{pracjourntitlefooter}]
-\setuphead
- [title]
+\setuphead
+ [title]
[header=pracjourntitleheader,
footer=pracjourntitlefooter]
diff --git a/Master/texmf-dist/tex/context/base/s-reg-01.mkiv b/Master/texmf-dist/tex/context/base/s-reg-01.mkiv
index d3e456881c8..36434c30c19 100644
--- a/Master/texmf-dist/tex/context/base/s-reg-01.mkiv
+++ b/Master/texmf-dist/tex/context/base/s-reg-01.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Extra Regime Support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/s-syn-01.tex b/Master/texmf-dist/tex/context/base/s-syn-01.tex
index d797be61e8f..01c8f6653dd 100644
--- a/Master/texmf-dist/tex/context/base/s-syn-01.tex
+++ b/Master/texmf-dist/tex/context/base/s-syn-01.tex
@@ -5,7 +5,7 @@
%D subtitle=Preliminary Syntax Stuff,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/scrn-bar.mkvi b/Master/texmf-dist/tex/context/base/scrn-bar.mkvi
index 4605f1d2e16..dabc8f77dc6 100644
--- a/Master/texmf-dist/tex/context/base/scrn-bar.mkvi
+++ b/Master/texmf-dist/tex/context/base/scrn-bar.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Progress Bars,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -57,9 +57,9 @@
%D \stoptext
%D \stoptyping
-\installcommandhandler \??ib {interactionbar} \??ib
+\installcorenamespace{interactionbar}
-\presetlocalframed[\??ib]
+\installframedcommandhandler \??interactionbar {interactionbar} \??interactionbar
\unexpanded\def\interactionbar
{\dodoubleempty\scrn_bar_direct}
@@ -68,19 +68,20 @@
{\iflocation
\begingroup
\doifassignmentelse{#tag}
- {\getparameters[\??ib][#tag]%
+ {\let\currentinteractionbar\empty
+ \setupcurrentinteractionbar[#tag]%
\edef\currentinteractionbar{\interactionbarparameter\c!alternative}}%
{\edef\currentinteractionbar{#tag}%
- \ifsecondargument\getparameters[\??ib#tag][#settings]\fi}%
+ \ifsecondargument\setupcurrentinteractionbar[#settings]\fi}%
\doif{\interactionbarparameter\c!state}\v!start
{\interactionbarparameter\c!command}%
\endgroup
\fi}
-\newdimen\scrn_bar_width
-\newdimen\scrn_bar_height
-\newdimen\scrn_bar_depth
-\newdimen\scrn_bar_distance
+\newdimen\d_scrn_bar_width
+\newdimen\d_scrn_bar_height
+\newdimen\d_scrn_bar_depth
+\newdimen\d_scrn_bar_distance
%D Interaction buttons, in fact a row of tiny buttons, are
%D typically only used for navigational purposed. The next
@@ -125,32 +126,33 @@
\def\scrn_bar_buttons_indeed[#settings][#list]%
{\begingroup
%\let\menuparameter\interactionbarparameter
- \setupinteractionbar[#settings]%
- \scrn_bar_width\interactionbarparameter\c!width
- \ifdim\scrn_bar_width=\zeropoint
- \scrn_bar_width1.5\emwidth
+ \setupcurrentinteractionbar[#settings]%
+ \d_scrn_bar_width\interactionbarparameter\c!width
+ \ifdim\d_scrn_bar_width=\zeropoint
+ \d_scrn_bar_width1.5\emwidth
\fi
\doifnothing{\interactionbarparameter\c!height}{\letinteractionbarparameter\c!height\v!broad}%
\doifnothing{\interactionbarparameter\c!depth }{\letinteractionbarparameter\c!depth\!!zeropoint}%%%
- \setbox2\hbox{\localframed[\??ib\currentinteractionbar][\c!background=]{\symbol[\interactionparameter\c!symbolset][\v!previouspage]}}%
+ \letinteractionbarparameter\c!background\empty
+ \setbox2\hbox{\inheritedinteractionbarframed{\symbol[\interactionparameter\c!symbolset][\v!previouspage]}}%
\!!heighta\ht2 % needed because we default to nothing
- \setupinteractionbar[\c!strut=\v!no]%
+ \letinteractionbarparameter\c!strut\v!no
\letinteractionparameter\c!width\zeropoint
\!!counta\zerocount % new, was 1
\processallactionsinset
[#list]
- [ \v!page=>\advance\!!counta 4,
- \v!subpage=>\advance\!!counta 4,
- \s!unknown=>\advance\!!counta 1]%
- \ifdim\scrn_bar_width=\zeropoint
- \!!widtha\dimexpr2\emwidth+\scrn_bar_distance\relax
- \!!widthb\dimexpr\!!counta\!!widtha-\scrn_bar_distance\relax
+ [ \v!page=>\advance\!!counta\plusfour,
+ \v!subpage=>\advance\!!counta\plusfour,
+ \s!unknown=>\advance\!!counta\plusone]%
+ \ifdim\d_scrn_bar_width=\zeropoint
+ \!!widtha\dimexpr2\emwidth+\d_scrn_bar_distance\relax
+ \!!widthb\dimexpr\!!counta\!!widtha-\d_scrn_bar_distance\relax
\else
- \!!widtha\scrn_bar_width
- \!!widthb\dimexpr\!!counta\scrn_bar_distance-\scrn_bar_distance\relax
+ \!!widtha\d_scrn_bar_width
+ \!!widthb\dimexpr\!!counta\d_scrn_bar_distance-\d_scrn_bar_distance\relax
\advance\!!widtha -\!!widthb
\divide\!!widtha \!!counta
- \!!widthb\scrn_bar_width
+ \!!widthb\d_scrn_bar_width
\fi
\hbox to \!!widthb
{\setnostrut
@@ -177,15 +179,17 @@
[#action]%
\hss}
+% todo: this will be \letblackruleparameter\c!width\!!widtha (faster)
+
\def\scrn_bar_alternative_a
- {\scrn_bar_width \interactionbarparameter\c!width
- \scrn_bar_distance\interactionbarparameter\c!distance
- \scrn_bar_height \interactionbarparameter\c!height
- \scrn_bar_depth \interactionbarparameter\c!depth
- \noindent\hbox to \scrn_bar_width \bgroup
+ {\d_scrn_bar_width \interactionbarparameter\c!width
+ \d_scrn_bar_distance\interactionbarparameter\c!distance
+ \d_scrn_bar_height \interactionbarparameter\c!height
+ \d_scrn_bar_depth \interactionbarparameter\c!depth
+ \noindent\hbox to \d_scrn_bar_width \bgroup
\dontcomplain
\setupblackrules[\c!height=\v!max,\c!depth=\v!max]%
- \!!widthb\dimexpr\scrn_bar_width-4\emwidth\relax
+ \!!widthb\dimexpr\d_scrn_bar_width-4\emwidth\relax
\processaction
[\interactionbarparameter\c!step]
[ \v!small=>\scratchcounter 20,
@@ -194,7 +198,7 @@
\s!unknown=>\scratchcounter 10]%
\!!widtha\dimexpr\!!widthb/\scratchcounter\relax
\setupblackrules[\c!width=\!!widtha]%
- \setbox\scratchbox\hbox to \scrn_bar_width
+ \setbox\scratchbox\hbox to \d_scrn_bar_width
{\hskip2\emwidth
\setbox\scratchbox\hbox{\blackrule[\c!color=\interactionbarparameter\c!backgroundcolor]}%
\dorecurse\scratchcounter
@@ -226,10 +230,10 @@
\def\scrn_bar_alternative_c
{\ifnum\lastpage>\plusone
- \scrn_bar_width\interactionbarparameter\c!width
- \hbox to \scrn_bar_width
+ \d_scrn_bar_width\interactionbarparameter\c!width
+ \hbox to \d_scrn_bar_width
{\setupblackrules[\c!height=\interactionbarparameter\c!height,\c!depth=\interactionbarparameter\c!depth,\c!width=\emwidth]%
- \scratchdimen\dimexpr(\scrn_bar_width-4\emwidth)/\numexpr\lastpage+\minusone\relax\relax
+ \scratchdimen\dimexpr(\d_scrn_bar_width-4\emwidth)/\numexpr\lastpage+\minusone\relax\relax
\!!widtha\numexpr\realpageno+\minusone\relax\scratchdimen
\!!widthb\numexpr\lastpage-\realpageno\relax\scratchdimen
\directgotospecbox\interactionbarparameter{\blackrule}[\v!firstpage]%
@@ -245,20 +249,20 @@
{\symbol[\ifcase#whereto\v!previous\or\v!somewhere\or\v!next\fi]}
\unexpanded\def\scrn_bar_goto_b#whereto%
- {\vrule\!!height\scrn_bar_height\!!depth\scrn_bar_depth\!!width\!!widtha\relax}
+ {\vrule\!!height\d_scrn_bar_height\!!depth\d_scrn_bar_depth\!!width\!!widtha\relax}
\unexpanded\def\scrn_bar_goto_c#whereto%
{\symbol[\ifcase#whereto\v!previous\or\v!somewhere\or\v!somewhere\or\v!somewhere\or\v!next\fi}
\unexpanded\def\scrn_bar_goto_d#whereto%
{\vrule \!!width\!!widtha \ifcase#whereto%
- \!!height \scrn_bar_height \!!depth \scrn_bar_depth \or
- \!!height.5\scrn_bar_height \!!depth.5\scrn_bar_depth \or
- \!!height \scrn_bar_height \!!depth \scrn_bar_depth \or
- \!!height.5\scrn_bar_height \!!depth.5\scrn_bar_depth \else
- \!!height \scrn_bar_height \!!depth \scrn_bar_depth \fi}
+ \!!height \d_scrn_bar_height \!!depth \d_scrn_bar_depth \or
+ \!!height.5\d_scrn_bar_height \!!depth.5\d_scrn_bar_depth \or
+ \!!height \d_scrn_bar_height \!!depth \d_scrn_bar_depth \or
+ \!!height.5\d_scrn_bar_height \!!depth.5\d_scrn_bar_depth \else
+ \!!height \d_scrn_bar_height \!!depth \d_scrn_bar_depth \fi}
-\newconstant\scrn_bar_mode
+\newconstant\c_scrn_bar_mode
\unexpanded\def\scrn_bar_goto_x#command%
{\doifelse{\interactionbarparameter\c!symbol}\v!yes
@@ -267,64 +271,64 @@
{\let\scrn_bar_goto_indeed\scrn_bar_goto_b}%
\dorecurse\nofsubpages
{\scratchcounter\numexpr\recurselevel+\firstsubpage+\minusone\relax
- \scrn_bar_mode
+ \c_scrn_bar_mode
\ifnum\scratchcounter<\realpageno \zerocount \else
\ifnum\scratchcounter=\realpageno \plusone \else
\plustwo \fi\fi
- \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\scrn_bar_goto_indeed\scrn_bar_mode}[page(\the\scratchcounter)]}%
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\scrn_bar_goto_indeed\c_scrn_bar_mode}[page(\the\scratchcounter)]}%
#command}%
\unskip}
\def\scrn_bar_alternative_d
- {\ifnum\nofsubpages>\plusone \doif{\structurecounterparameter\s!subpage\c!state}\v!start{%
- \scrn_bar_width \interactionbarparameter\c!width
- \scrn_bar_distance\interactionbarparameter\c!distance
- \scrn_bar_height \interactionbarparameter\c!height
- \scrn_bar_depth \interactionbarparameter\c!depth
- \!!widtha\scrn_bar_width
- \noindent\hbox{\scrn_bar_goto_x{\hskip\scrn_bar_distance}}%
+ {\ifnum\nofsubpages>\plusone \doif{\counterparameter\s!subpage\c!state}\v!start{%
+ \d_scrn_bar_width \interactionbarparameter\c!width
+ \d_scrn_bar_distance\interactionbarparameter\c!distance
+ \d_scrn_bar_height \interactionbarparameter\c!height
+ \d_scrn_bar_depth \interactionbarparameter\c!depth
+ \!!widtha\d_scrn_bar_width
+ \noindent\hbox{\scrn_bar_goto_x{\hskip\d_scrn_bar_distance}}%
}\fi}
\def\scrn_bar_alternative_e
- {\ifnum\nofsubpages>\plusone \doif{\structurecounterparameter\s!subpage\c!state}\v!start{%
- \scrn_bar_width \interactionbarparameter\c!width
- \scrn_bar_distance\interactionbarparameter\c!distance
- \scrn_bar_height \interactionbarparameter\c!height
- \scrn_bar_depth \interactionbarparameter\c!depth
- \!!widthb\dimexpr\nofsubpages\scrn_bar_distance-\scrn_bar_distance\relax % (n-1)
- \!!widtha\dimexpr(\scrn_bar_width-\!!widthb)/\nofsubpages\relax
- \ifdim\!!widtha<\scrn_bar_distance
+ {\ifnum\nofsubpages>\plusone \doif{\counterparameter\s!subpage\c!state}\v!start{%
+ \d_scrn_bar_width \interactionbarparameter\c!width
+ \d_scrn_bar_distance\interactionbarparameter\c!distance
+ \d_scrn_bar_height \interactionbarparameter\c!height
+ \d_scrn_bar_depth \interactionbarparameter\c!depth
+ \!!widthb\dimexpr\nofsubpages\d_scrn_bar_distance-\d_scrn_bar_distance\relax % (n-1)
+ \!!widtha\dimexpr(\d_scrn_bar_width-\!!widthb)/\nofsubpages\relax
+ \ifdim\!!widtha<\d_scrn_bar_distance
\scrn_bar_alternative_f
\else
- \noindent\hbox to \scrn_bar_width{\scrn_bar_goto_x{\hss}\unskip}%
+ \noindent\hbox to \d_scrn_bar_width{\scrn_bar_goto_x{\hss}\unskip}%
\fi
}\fi}
\def\scrn_bar_alternative_f
- {\ifnum\nofsubpages>\plusone \doif{\structurecounterparameter\s!subpage\c!state}\v!start{%
- \scrn_bar_width \interactionbarparameter\c!width
- \scrn_bar_distance\interactionbarparameter\c!distance
- \scrn_bar_height \interactionbarparameter\c!height
- \scrn_bar_depth \interactionbarparameter\c!depth
- \noindent \hbox to \scrn_bar_width \bgroup
+ {\ifnum\nofsubpages>\plusone \doif{\counterparameter\s!subpage\c!state}\v!start{%
+ \d_scrn_bar_width \interactionbarparameter\c!width
+ \d_scrn_bar_distance\interactionbarparameter\c!distance
+ \d_scrn_bar_height \interactionbarparameter\c!height
+ \d_scrn_bar_depth \interactionbarparameter\c!depth
+ \noindent \hbox to \d_scrn_bar_width \bgroup
\doloop
{\!!countc\numexpr(\nofsubpages/\recurselevel)+\plusone\relax % rounding
- \!!widthb\scrn_bar_distance
+ \!!widthb\d_scrn_bar_distance
\multiply\!!widthb \!!countc
- \advance\!!widthb -\scrn_bar_distance
- \!!widtha\scrn_bar_width
+ \advance\!!widthb -\d_scrn_bar_distance
+ \!!widtha\d_scrn_bar_width
\advance\!!widtha -\!!widthb
\divide\!!widtha \!!countc
- \ifdim\!!widtha<\scrn_bar_distance\else
+ \ifdim\!!widtha<\d_scrn_bar_distance\else
\!!countb\recurselevel
\exitloop
\fi}%
\ifnum\!!countc>\plusone
% this is not that well tested
\advance\!!countc \minustwo
- \!!widtha-\scrn_bar_distance
+ \!!widtha-\d_scrn_bar_distance
\!!widtha\!!countc\!!widtha
- \advance\!!widtha \scrn_bar_width
+ \advance\!!widtha \d_scrn_bar_width
\advance\!!countc \plusone
\divide\!!widtha \!!countc
\fi
@@ -341,7 +345,7 @@
\advance\!!countf \plusone
\ifnum\recurselevel=\firstsubpage\relax \!!doneatrue \fi
\ifnum\recurselevel=\lastsubpage \relax \!!doneatrue \fi
- \scrn_bar_mode
+ \c_scrn_bar_mode
\if!!donea
\ifnum\recurselevel<\realpageno
\zerocount
@@ -363,7 +367,7 @@
\plusthree
\fi
\fi
- \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\scrn_bar_goto_indeed\scrn_bar_mode}[page(\recurselevel)]}%
+ \normalexpanded{\directgotospecbox\noexpand\interactionbarparameter{\scrn_bar_goto_indeed\c_scrn_bar_mode}[page(\recurselevel)]}%
\hss
\!!countf\zerocount}%
\unskip
diff --git a/Master/texmf-dist/tex/context/base/scrn-but.mkvi b/Master/texmf-dist/tex/context/base/scrn-but.mkvi
index e1dedd6051b..b20d34c09ac 100644
--- a/Master/texmf-dist/tex/context/base/scrn-but.mkvi
+++ b/Master/texmf-dist/tex/context/base/scrn-but.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Interaction,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -44,15 +44,15 @@
%D
%D \showsetup{setupbuttons}
-\installcommandhandler \??bt {button} \??bt
+\installcorenamespace{button}
+\installcorenamespace{buttonlocation}
-\let\setupbuttons\setupbutton
+\installframedcommandhandler \??button {button} \??button
-\presetlocalframed[\??bt]
+\let\setupbuttons\setupbutton
\appendtoks
\setuevalue\currentbutton{\scrn_button_direct{\currentbutton}}%
- \setevalue{\??bt:\currentbutton\s!parent}{\??bt\currentbutton}% framed
\to \everydefinebutton
\unexpanded\def\scrn_button_direct#tag%
@@ -67,17 +67,21 @@
\scrn_button_direct_indeed
\scrn_button_direct_ignore}
-%\def\buttonframed{\dodoubleempty\localframed[\??bt]} % goodie
-
% empty=yes
%
% \button[settings]{}[action] % normally used at the tex end
\def\scrn_button_direct_indeed[#settings]#text[#action]%
{\iffirstargument
- \setupbuttons[\currentbutton][#settings]%
+ \setupcurrentbutton[#settings]%
\fi
- \scrn_button_make\??bt\currentbutton\buttonparameter{#text}{#action}%
+ \scrn_button_make
+ \buttonparameter
+ \inheritedbuttonframed
+ \letbuttonparameter
+ \setbuttonparameter
+ {#text}%
+ {#action}%
\endgroup}
\def\scrn_button_direct_ignore[#settings]#text[#destination]%
@@ -140,94 +144,98 @@
%D The renderers:
-\expandafter\let\csname\??bt:\c!location:\v!yes \endcsname\zerocount
-\expandafter\let\csname\??bt:\c!location:\v!empty \endcsname\plusone
-\expandafter\let\csname\??bt:\c!location:\v!no \endcsname\plustwo
-\expandafter\let\csname\??bt:\c!location:\v!none \endcsname\plusthree
-\expandafter\let\csname\??bt:\c!location:\v!normal \endcsname\plusone % default
-\expandafter\let\csname\??bt:\c!location:\s!default\endcsname\plusone % default
-\expandafter\let\csname\??bt:\c!location:\s!empty \endcsname\plusone % default
+\expandafter\let\csname\??buttonlocation\v!yes \endcsname\zerocount
+\expandafter\let\csname\??buttonlocation\v!empty \endcsname\plusone
+\expandafter\let\csname\??buttonlocation\v!no \endcsname\plustwo
+\expandafter\let\csname\??buttonlocation\v!none \endcsname\plusthree
+\expandafter\let\csname\??buttonlocation\v!normal \endcsname\plusone % default
+\expandafter\let\csname\??buttonlocation\s!default\endcsname\plusone % default
+\expandafter\let\csname\??buttonlocation\s!empty \endcsname\plusone % default
-\newconditional\scrn_button_skipped
+\newconditional\c_scrn_button_skipped
-\def\scrn_button_make#namespace#current#currentparameter#text#action%
+\def\scrn_button_make#currentparameter#inheritedframed#letparameter#setparameter#text#action%
{\begingroup
\attribute\referenceattribute\attributeunsetvalue
- \global\setfalse\scrn_button_skipped
- \chardef\locationboxpagestate\csname\??bt:\c!location:#currentparameter\c!samepage\endcsname
+ \global\setfalse\c_scrn_button_skipped
+ \chardef\locationboxpagestate\csname\??buttonlocation#currentparameter\c!samepage\endcsname % ?? bt: todo
\doifreferencefoundelse{#action}\scrn_button_make_yes\scrn_button_make_nop
- {#namespace}{#current}{#currentparameter}{#text}%
+ #currentparameter%
+ #inheritedframed%
+ #letparameter%
+ #setparameter
+ {#text}%
\endgroup}
\def\scrn_button_make_yes
- {\analyzecurrentreference % needed as we act on the state
- \ifcase\referencepagestate
- \expandafter\scrn_button_make_normal % no state : something else than a page reference
+ {\scratchcounter\referencerealpage\relax % called in otr
+ \ifcase\scratchcounter
+ \expandafter\scrn_button_make_normal % no state : something else than a page reference
+ \else\ifnum\scratchcounter=\realpageno
+ \expandafter\expandafter\expandafter\scrn_button_make_yes_same
+ \else
+ \expandafter\expandafter\expandafter\scrn_button_make_yes_other
+ \fi\fi}
+
+\def\scrn_button_make_yes_same
+ {\ifcase\locationboxpagestate\relax
+ \expandafter\scrn_button_make_contrast % same page: yes: same page or not ... todo
+ \or
+ \expandafter\scrn_button_make_empty % same page: empty but frame: no click
+ \or
+ \expandafter\scrn_button_make_nothing % same page: empty no frame: no
+ \else
+ \expandafter\scrn_button_make_skipped % same page: nothing at all
+ \fi}
+
+\def\scrn_button_make_yes_other
+ {\ifcase\locationboxpagestate\relax
+ \expandafter\scrn_button_make_normal % other page: yes: same page or not ... todo
+ \or
+ \expandafter\scrn_button_make_normal % other page: empty but frame: no click
\or
- \ifcase\locationboxpagestate\relax
- \expandafter\expandafter\expandafter\scrn_button_make_contrast % same page: yes: same page or not ... todo
- \or
- \expandafter\expandafter\expandafter\scrn_button_make_empty % same page: empty but frame: no click
- \or
- \expandafter\expandafter\expandafter\scrn_button_make_nothing % same page: empty no frame: no
- \else
- \expandafter\expandafter\expandafter\scrn_button_make_skipped % same page: nothing at all
- \fi
+ \expandafter\scrn_button_make_normal % other page: empty no frame: no
\else
- \ifcase\locationboxpagestate\relax
- \expandafter\expandafter\expandafter\scrn_button_make_normal % other page: yes: same page or not ... todo
- \or
- \expandafter\expandafter\expandafter\scrn_button_make_normal % other page: empty but frame: no click
- \or
- \expandafter\expandafter\expandafter\scrn_button_make_normal % other page: empty no frame: no
- \else
- \expandafter\expandafter\expandafter\scrn_button_make_skipped % other page: nothing at all
- \fi%
+ \expandafter\scrn_button_make_skipped % other page: nothing at all
\fi}
\def\scrn_button_make_nop
{\ifcase\locationboxpagestate\relax
- \expandafter\scrn_button_make_framed
+ \expandafter\scrn_button_make_framed
\or
- \expandafter\scrn_button_make_empty
+ \expandafter\scrn_button_make_empty
\or
- \expandafter\scrn_button_make_nothing
+ \expandafter\scrn_button_make_nothing
\or
- \expandafter\scrn_button_make_skipped
+ \expandafter\scrn_button_make_skipped
\fi}
-\def\scrn_button_make_framed#namespace#current#currentparameter#text%
- {\directlocalframed[#namespace:#current]{\ignorespaces#text\removeunwantedspaces}}
+\def\scrn_button_make_framed#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {#inheritedframed{\ignorespaces#text\removeunwantedspaces}}
-\def\scrn_button_make_skipped#namespace#current#currentparameter#text%
- {\global\settrue\scrn_button_skipped}
+\def\scrn_button_make_skipped#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {\global\settrue\c_scrn_button_skipped}
-\def\scrn_button_make_normal#namespace#current#currentparameter#text%
+\def\scrn_button_make_normal#currentparameter#inheritedframed#letparameter#setparameter#text%
{\ctxlua{structures.references.injectcurrentset(nil,nil)}%
\hbox attr \referenceattribute \lastreferenceattribute
- {\directlocalframed
- [#namespace:#current]%
- {\ignorespaces#text\removeunwantedspaces}}}
+ {#inheritedframed{\ignorespaces#text\removeunwantedspaces}}}
-\def\scrn_button_make_contrast#namespace#current#currentparameter#text%
+\def\scrn_button_make_contrast#currentparameter#inheritedframed#letparameter#setparameter#text%
{\ctxlua{structures.references.injectcurrentset(nil,nil)}%
\hbox attr \referenceattribute \lastreferenceattribute
- {\localframedwithsettings
- [#namespace:#current]%
- [\c!foregroundcolor=#currentparameter\c!contrastcolor]%
- {\ignorespaces#text\removeunwantedspaces}}}
-
-\def\scrn_button_make_empty#namespace#current#currentparameter#text%
- {\localframedwithsettings
- [#namespace:#current]%
- [\c!empty=\v!yes]%
- {\ignorespaces#text\removeunwantedspaces}}
-
-\def\scrn_button_make_nothing#namespace#current#currentparameter#text%
- {\localframedwithsettings
- [#namespace:#current]%
- [\c!empty=\v!yes,\c!frame=,\c!background=]%
- {\ignorespaces#text\removeunwantedspaces}}
+ {#setparameter\c!foregroundcolor{#currentparameter\c!contrastcolor}%
+ #inheritedframed{\ignorespaces#text\removeunwantedspaces}}}
+
+\def\scrn_button_make_empty#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {#letparameter\c!empty\v!yes
+ #inheritedframed{\ignorespaces#text\removeunwantedspaces}}
+
+\def\scrn_button_make_nothing#currentparameter#inheritedframed#letparameter#setparameter#text%
+ {#letparameter\c!empty\v!yes
+ #letparameter\c!frame\empty
+ #letparameter\c!background\empty
+ #inheritedframed{\ignorespaces#text\removeunwantedspaces}}
%D Menus:
%D
@@ -316,11 +324,15 @@
%D \setupinteractionmenu[right][samepage=none, unknownreference=none]
%D \stoptyping
-\installcommandhandler \??am {interactionmenu} \??am
+\installcorenamespace{menu}
+\installcorenamespace{menutoks}
+\installcorenamespace{menustate}
+\installcorenamespace{menupacker}
+\installcorenamespace{menualign}
-\let\setupinteractionmenus\setupinteractionmenu
+\installframedcommandhandler \??menu {interactionmenu} \??menu
-\presetlocalframed[\??am]
+\let\setupinteractionmenus\setupinteractionmenu
\let\scrn_menu_action\relax
@@ -335,34 +347,30 @@
{\scrn_menu_define_original[#tag][#category][\c!category=#category,#settings]}% child definition
{\scrn_menu_define_original[#tag][#settings][\c!category=#category]}% % child definition
\scrn_menu_register{#tag}{#category}%
- \setevalue{\??am:#tag\s!parent}{\??am#tag}% framed
\else\ifsecondargument
\doifassignmentelse{#category}%
- {\scrn_menu_define_original[#tag][#category]% % root definition
- \setevalue{\??am:#tag\s!parent}{\??am}}% framed
+ {\scrn_menu_define_original[#tag][#category]}% % root definition
{\scrn_menu_define_original[#tag][#category][\c!category=#category]% % child definition
- \scrn_menu_register{#tag}{#category}%
- \setevalue{\??am:#tag\s!parent}{\??am#tag}}% framed
- \else
+ \scrn_menu_register{#tag}{#category}}%
+ \else
\scrn_menu_define_original[#tag]% % root definition
- \setevalue{\??am:#tag\s!parent}{\??am}% framed
\fi\fi}
\def\scrn_menu_register#tag#category%
- {\ifcsname\??am:t:#category\endcsname \else
- \expandafter\newtoks \csname\??am:t:#category\endcsname
- \expandafter\setfalse\csname\??am:c:#category\endcsname
+ {\ifcsname\??menutoks#category\endcsname \else
+ \expandafter\newtoks \csname\??menutoks#category\endcsname
+ \expandafter\setfalse\csname\??menustate#category\endcsname
\fi
- \normalexpanded{\csname\??am:t:#category\endcsname{\the\csname\??am:t:#category\endcsname\scrn_menu_action{#tag}}}}
+ \normalexpanded{\csname\??menutoks#category\endcsname{\the\csname\??menutoks#category\endcsname\scrn_menu_action{#tag}}}}
\def\scrn_menu_actions#category%
- {\the\csname\??am:t:#category\endcsname}
+ {\the\csname\??menutoks#category\endcsname}
%D Fill menus:
\normalexpanded{\long\def\expandafter\noexpand\csname\e!start\v!interactionmenu\endcsname[#tag]#content\expandafter\noexpand\csname\e!stop\v!interactionmenu\endcsname}%
{\def\currentinteractionmenu{#tag}%
- \expandafter\settrue\csname\??am:c:\interactionmenuparameter\c!category\endcsname
+ \expandafter\settrue\csname\??menustate\interactionmenuparameter\c!category\endcsname
\setinteractionmenuparameter\c!menu{#content}}
\def\resetinteractionmenu[#tag]%
@@ -402,69 +410,69 @@
%D The no longer hard coded text areas offset compensation makes tuning
%D easier. After all, menus need some setup anyway.
-\newbox \scrn_menu_box
+\newbox \b_scrn_menu
-\newdimen\scrn_menu_next_distance
-\newdimen\scrn_menu_final_width
-\newdimen\scrn_menu_final_height
-\newdimen\scrn_menu_used_width
-\newdimen\scrn_menu_used_height
-\newdimen\scrn_menu_asked_width
-\newdimen\scrn_menu_asked_height
-\newdimen\scrn_menu_offset_top
-\newdimen\scrn_menu_offset_bottom
-\newdimen\scrn_menu_offset_left
-\newdimen\scrn_menu_offset_right
+\newdimen\d_scrn_menu_next_distance
+\newdimen\d_scrn_menu_final_width
+\newdimen\d_scrn_menu_final_height
+\newdimen\d_scrn_menu_used_width
+\newdimen\d_scrn_menu_used_height
+\newdimen\d_scrn_menu_asked_width
+\newdimen\d_scrn_menu_asked_height
+\newdimen\d_scrn_menu_offset_top
+\newdimen\d_scrn_menu_offset_bottom
+\newdimen\d_scrn_menu_offset_left
+\newdimen\d_scrn_menu_offset_right
-\newconditional\scrn_menu_zerodimensions
+\newconditional\c_scrn_menu_zerodimensions
\def\scrn_menu_set_used
- {\doassigncheckedframeoffset\scrn_menu_offset_left {\interactionmenuparameter\c!leftoffset }%
- \doassigncheckedframeoffset\scrn_menu_offset_right {\interactionmenuparameter\c!rightoffset }%
- \doassigncheckedframeoffset\scrn_menu_offset_top {\interactionmenuparameter\c!topoffset }%
- \doassigncheckedframeoffset\scrn_menu_offset_bottom{\interactionmenuparameter\c!bottomoffset}%
- \scrn_menu_asked_width \interactionmenuparameter\c!maxwidth
- \scrn_menu_asked_height \interactionmenuparameter\c!maxheight
- \scrn_menu_used_width\dimexpr
- \scrn_menu_asked_width + \scrn_menu_offset_left + \scrn_menu_offset_right
+ {\doassigncheckedframeoffset\d_scrn_menu_offset_left {\interactionmenuparameter\c!leftoffset }%
+ \doassigncheckedframeoffset\d_scrn_menu_offset_right {\interactionmenuparameter\c!rightoffset }%
+ \doassigncheckedframeoffset\d_scrn_menu_offset_top {\interactionmenuparameter\c!topoffset }%
+ \doassigncheckedframeoffset\d_scrn_menu_offset_bottom{\interactionmenuparameter\c!bottomoffset}%
+ \d_scrn_menu_asked_width \interactionmenuparameter\c!maxwidth
+ \d_scrn_menu_asked_height \interactionmenuparameter\c!maxheight
+ \d_scrn_menu_used_width\dimexpr
+ \d_scrn_menu_asked_width + \d_scrn_menu_offset_left + \d_scrn_menu_offset_right
\relax
- \scrn_menu_used_height\dimexpr
- \scrn_menu_asked_height + \scrn_menu_offset_top + \scrn_menu_offset_bottom
+ \d_scrn_menu_used_height\dimexpr
+ \d_scrn_menu_asked_height + \d_scrn_menu_offset_top + \d_scrn_menu_offset_bottom
\relax}
\def\scrn_menu_set_final
- {\scrn_menu_final_width \namedinteractionmenuparameter\askedinteractionmenulocation\c!maxwidth
- \scrn_menu_final_height\namedinteractionmenuparameter\askedinteractionmenulocation\c!maxheight}
+ {\d_scrn_menu_final_width \namedinteractionmenuparameter\askedinteractionmenulocation\c!maxwidth
+ \d_scrn_menu_final_height\namedinteractionmenuparameter\askedinteractionmenulocation\c!maxheight}
\def\scrn_menu_apply_final
- {\ifconditional\scrn_menu_zerodimensions
- \wd\scrn_menu_box\zeropoint
- \ht\scrn_menu_box\zeropoint
+ {\ifconditional\c_scrn_menu_zerodimensions
+ \wd\b_scrn_menu\zeropoint
+ \ht\b_scrn_menu\zeropoint
\else
- \wd\scrn_menu_box\scrn_menu_final_width
- \ht\scrn_menu_box\scrn_menu_final_height
+ \wd\b_scrn_menu\d_scrn_menu_final_width
+ \ht\b_scrn_menu\d_scrn_menu_final_height
\fi
- \dp\scrn_menu_box\zeropoint}
+ \dp\b_scrn_menu\zeropoint}
\def\scrn_menu_apply_used
- {\ifdim\scrn_menu_offset_left=\zeropoint \else
- \setbox\scrn_menu_box\hbox{\hskip-\scrn_menu_offset_left \box\scrn_menu_box}%
+ {\ifdim\d_scrn_menu_offset_left=\zeropoint \else
+ \setbox\b_scrn_menu\hbox{\hskip-\d_scrn_menu_offset_left \box\b_scrn_menu}%
\fi
- \ifdim\scrn_menu_offset_bottom=\zeropoint \else
- \setbox\scrn_menu_box\hbox{\lower \scrn_menu_offset_bottom \box\scrn_menu_box}%
+ \ifdim\d_scrn_menu_offset_bottom=\zeropoint \else
+ \setbox\b_scrn_menu\hbox{\lower \d_scrn_menu_offset_bottom \box\b_scrn_menu}%
\fi
- \wd\scrn_menu_box\scrn_menu_asked_width
- \ht\scrn_menu_box\scrn_menu_asked_height
- \dp\scrn_menu_box\zeropoint}
-
-\setvalue{scrn_menu_align_\v!right }{\let\scrn_menu_left_align\raggedright}
-\setvalue{scrn_menu_align_\v!left }{\let\scrn_menu_left_align\raggedleft}
-\setvalue{scrn_menu_align_\v!flushright}{\let\scrn_menu_left_align\raggedleft}
-\setvalue{scrn_menu_align_\v!flushleft }{\let\scrn_menu_left_align\raggedright}
-\setvalue{scrn_menu_align_\v!middle }{\let\scrn_menu_left_align\raggedcenter}
-\setvalue{scrn_menu_align_\v!low }{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\relax}
-\setvalue{scrn_menu_align_\v!high }{\let\scrn_menu_top_align\relax\let\scrn_menu_bottom_align\vss}
-\setvalue{scrn_menu_align_\v!lohi }{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\vss}
+ \wd\b_scrn_menu\d_scrn_menu_asked_width
+ \ht\b_scrn_menu\d_scrn_menu_asked_height
+ \dp\b_scrn_menu\zeropoint}
+
+\setvalue{\??menualign\v!right }{\let\scrn_menu_left_align\raggedright}
+\setvalue{\??menualign\v!left }{\let\scrn_menu_left_align\raggedleft}
+\setvalue{\??menualign\v!flushright}{\let\scrn_menu_left_align\raggedleft}
+\setvalue{\??menualign\v!flushleft }{\let\scrn_menu_left_align\raggedright}
+\setvalue{\??menualign\v!middle }{\let\scrn_menu_left_align\raggedcenter}
+\setvalue{\??menualign\v!low }{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\relax}
+\setvalue{\??menualign\v!high }{\let\scrn_menu_top_align\relax\let\scrn_menu_bottom_align\vss}
+\setvalue{\??menualign\v!lohi }{\let\scrn_menu_top_align\vss\let\scrn_menu_bottom_align\vss}
\let\scrn_menu_left_align \relax
\let\scrn_menu_right_align \relax
@@ -472,7 +480,7 @@
\let\scrn_menu_bottom_align\relax
\def\scrn_menu_set_align
- {\csname scrn_menu_align_\interactionmenuparameter\c!itemalign\endcsname}
+ {\csname\??menualign\interactionmenuparameter\c!itemalign\endcsname}
%D Hook into the pagebuilder (as less testing as possible):
@@ -484,7 +492,7 @@
\fi}
\def\scrn_menu_insert_checked#location%
- {\ifconditional\csname\??am:c:#location\endcsname
+ {\ifconditional\csname\??menustate#location\endcsname
\scrn_menu_insert_indeed{#location}%
\fi}
@@ -492,28 +500,28 @@
{\begingroup
\xdef\askedinteractionmenulocation{#location}%
\scrn_menu_set_final
- \ifcase\scrn_menu_final_width \else \ifcase\scrn_menu_final_height \else
+ \ifcase\d_scrn_menu_final_width \else \ifcase\d_scrn_menu_final_height \else
\forgetall
- \global\scrn_menu_next_distance\zeropoint
+ \global\d_scrn_menu_next_distance\zeropoint
\let\scrn_menu_action\scrn_menu_package_indeed
\the\everysetmenucommands
- \csname\??am:\c!menu:\namedinteractionmenuparameter\askedinteractionmenulocation\c!alternative\endcsname
+ \csname\??menupacker\namedinteractionmenuparameter\askedinteractionmenulocation\c!alternative\endcsname
\fi \fi
\endgroup}
%D This calls: % can be \c!command for vertical/horizontal
-\setvalue{\??am:\c!menu:\v!vertical}% all menus
+\setvalue{\??menupacker\v!vertical}% all menus
{\let\scrn_menu_packager\scrn_menu_packager_vertical
- \setbox\scrn_menu_box\hbox{\scrn_menu_actions\askedinteractionmenulocation}%
+ \setbox\b_scrn_menu\hbox{\scrn_menu_actions\askedinteractionmenulocation}%
\scrn_menu_apply_final
- \box\scrn_menu_box}
+ \box\b_scrn_menu}
-\setvalue{\??am:\c!menu:\v!horizontal}% all menus
+\setvalue{\??menupacker\v!horizontal}% all menus
{\let\scrn_menu_packager\scrn_menu_packager_horizontal
- \setbox\scrn_menu_box\vbox{\scrn_menu_actions\askedinteractionmenulocation}%
+ \setbox\b_scrn_menu\vbox{\scrn_menu_actions\askedinteractionmenulocation}%
\scrn_menu_apply_final
- \box\scrn_menu_box}
+ \box\b_scrn_menu}
% stop : skipped
% start: processed
@@ -533,48 +541,50 @@
%D With the packager being one of:
+\let\currentinteractionmenudistance\!!zeropoint
+
\def\scrn_menu_packager_vertical
{\scrn_menu_set_used
- \hskip\scrn_menu_next_distance
- \setbox\scrn_menu_box\hbox to \scrn_menu_used_width
+ \hskip\d_scrn_menu_next_distance
+ \setbox\b_scrn_menu\hbox to \d_scrn_menu_used_width
{\ifx\currentinteractionmenustate\v!empty \else
\interactionmenuparameter\c!left
- \scrn_menu_package_vertical{\interactionmenuparameter\c!menu}%
+ \scrn_menu_package_vertical{\strictinteractionmenuparameter\c!menu}%
\interactionmenuparameter\c!right
\fi}%
\edef\currentinteractionmenudistance{\interactionmenuparameter\c!distance}%
\ifx\currentinteractionmenudistance\v!overlay
- \global\scrn_menu_next_distance\zeropoint
- \wd\scrn_menu_box\zeropoint
+ \global\d_scrn_menu_next_distance\zeropoint
+ \wd\b_scrn_menu\zeropoint
\else
- \global\scrn_menu_next_distance\currentinteractionmenudistance
+ \global\d_scrn_menu_next_distance\currentinteractionmenudistance
\scrn_menu_apply_used
\fi
- \box\scrn_menu_box}
+ \box\b_scrn_menu}
\def\scrn_menu_packager_horizontal
{\scrn_menu_set_used
- \vskip\scrn_menu_next_distance
+ \vskip\d_scrn_menu_next_distance
\scrn_menu_set_align
- \setbox\scrn_menu_box\vbox to \scrn_menu_used_height
+ \setbox\b_scrn_menu\vbox to \d_scrn_menu_used_height
{\ifx\currentinteractionmenustate\v!none \else
\scrn_menu_top_align
\interactionmenuparameter\c!before
- \scrn_menu_package_horizontal{\interactionmenuparameter\c!menu}%
+ \scrn_menu_package_horizontal{\strictinteractionmenuparameter\c!menu}%
\interactionmenuparameter\c!after
\scrn_menu_bottom_align
\fi}%
\edef\currentinteractionmenudistance{\interactionmenuparameter\c!distance}%
\ifx\currentinteractionmenudistance\v!overlay
- \global\scrn_menu_next_distance\zeropoint
+ \global\d_scrn_menu_next_distance\zeropoint
\offinterlineskip
- \dp\scrn_menu_box\zeropoint
- \ht\scrn_menu_box\zeropoint
+ \dp\b_scrn_menu\zeropoint
+ \ht\b_scrn_menu\zeropoint
\else
- \global\scrn_menu_next_distance\currentinteractionmenudistance
+ \global\d_scrn_menu_next_distance\currentinteractionmenudistance
\scrn_menu_apply_used
\fi
- \box\scrn_menu_box}
+ \box\b_scrn_menu}
%D For a right menu, a sequence of calls to \type
%D {right_menu_button} is generated.
@@ -587,65 +597,65 @@
%D while the rest is positional info. The status variable is
%D 0, 1 or~2: not found, found and found but current page.
-\newcount \scrn_menu_position
-\newconstant \scrn_menu_page_mode % 0=notfound 1=found 2=currentpage
-\newconditional\scrn_menu_positioning
-\newtoks \scrn_menu_mp_data
+\newcount \c_scrn_menu_position
+\newconstant \c_scrn_menu_page_mode % 0=notfound 1=found 2=currentpage
+\newconditional\c_scrn_menu_positioning
+\newtoks \t_scrn_menu_meta_data
-\def\scrn_menu_button_mp_template
+\def\scrn_menu_button_meta_template
{\askedinteractionmenulocation _menu_button(%
- \number\scrn_menu_position,%
- \number\scrn_menu_page_mode,%
- \MPpos{\askedinteractionmenulocation:\number\scrn_menu_position}%
+ \number\c_scrn_menu_position,%
+ \number\c_scrn_menu_page_mode,%
+ \MPpos{\askedinteractionmenulocation:\number\c_scrn_menu_position}%
);}
-\def\MPmenubuttons#1{\the\scrn_menu_mp_data}
+\def\MPmenubuttons#1{\the\t_scrn_menu_meta_data}
\appendtoks
- \global\scrn_menu_mp_data\emptytoks
+ \global\t_scrn_menu_meta_data\emptytoks
\to \everyshipout
\def\scrn_menu_whole_position % cannot happen in previous due to align
- {\setbox\scrn_menu_box\hbox \bgroup
- \hpos{menu:\askedinteractionmenulocation:\the\realpageno}{\box\scrn_menu_box}%
+ {\setbox\b_scrn_menu\hbox \bgroup
+ \hpos{menu:\askedinteractionmenulocation:\the\realpageno}{\box\b_scrn_menu}%
\egroup}
% removed: \restorestandardblank (vspacing) ... should happen elsewhere
\def\scrn_menu_package_vertical#content%
{\begingroup
- \global\scrn_menu_position\zerocount
+ \global\c_scrn_menu_position\zerocount
\def\scrn_menu_between_action_indeed{\interactionmenuparameter\c!inbetween}%
- \doifelse{\interactionmenuparameter\c!position}\v!yes\settrue\setfalse\scrn_menu_positioning
+ \doifelse{\interactionmenuparameter\c!position}\v!yes\settrue\setfalse\c_scrn_menu_positioning
\scrn_menu_set_align
- \setbox\scrn_menu_box\vbox to \scrn_menu_used_height \bgroup
- \hsize\scrn_menu_used_width
+ \setbox\b_scrn_menu\vbox to \d_scrn_menu_used_height \bgroup
+ \hsize\d_scrn_menu_used_width
\scrn_menu_left_align
\interactionmenuparameter\c!before\relax
\ignorespaces#content\unskip
\interactionmenuparameter\c!after
\scrn_menu_right_align
\egroup
- \ifconditional\scrn_menu_positioning
+ \ifconditional\c_scrn_menu_positioning
\scrn_menu_whole_position
\fi
- \box\scrn_menu_box
+ \box\b_scrn_menu
\endgroup}
\def\scrn_menu_package_horizontal#content%
{\begingroup
- \global\scrn_menu_position\zerocount
+ \global\c_scrn_menu_position\zerocount
\def\scrn_menu_between_action_indeed{\interactionmenuparameter\c!middle}%
- \doifelse{\interactionmenuparameter\c!position}\v!yes\settrue\setfalse\scrn_menu_positioning
- \setbox\scrn_menu_box\hbox to \scrn_menu_used_width \bgroup
+ \doifelse{\interactionmenuparameter\c!position}\v!yes\settrue\setfalse\c_scrn_menu_positioning
+ \setbox\b_scrn_menu\hbox to \d_scrn_menu_used_width \bgroup
\interactionmenuparameter\c!left\relax
\ignorespaces#content\unskip
\interactionmenuparameter\c!right
\egroup
- \ifconditional\scrn_menu_positioning
+ \ifconditional\c_scrn_menu_positioning
\scrn_menu_whole_position
\fi
- \box\scrn_menu_box
+ \box\b_scrn_menu
\endgroup}
\def\scrn_menu_action_start
@@ -653,7 +663,7 @@
\begingroup}
\def\scrn_menu_action_stop
- {\ifconditional\scrn_button_skipped \else
+ {\ifconditional\c_scrn_button_skipped \else
\scrn_menu_between_action_indeed
\fi
\endgroup
@@ -666,52 +676,67 @@
\unexpanded\def\scrn_menu_but_start[#action]#text\stopbut
{\scrn_menu_action_start
- \ifconditional\scrn_menu_positioning
+ \ifconditional\c_scrn_menu_positioning
\expandafter\scrn_button_make_position
\else
\expandafter\scrn_button_make
- \fi\??am\currentinteractionmenu\interactionmenuparameter{#text}{#action}%
+ \fi
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \letinteractionmenuparameter
+ \setinteractionmenuparameter
+ {#text}%
+ {#action}%
\scrn_menu_action_stop}
-\def\scrn_button_make_position#namespace#current#currentparameter#text#action%
- {\global\advance\scrn_menu_position\plusone
+\def\scrn_button_make_position#currentparameter#inheritedframed#letparameter#setparameter#text#action%
+ {\global\advance\c_scrn_menu_position\plusone
\doifreferencefoundelse{#action}% 0=not found, 1=same page, >1=elsewhere
- {\scrn_menu_page_mode\ifnum\currentreferencerealpage=\realpageno\plusone\else\plustwo\fi}%
- {\scrn_menu_page_mode\plustwo}%
+ {\c_scrn_menu_page_mode\ifnum\currentreferencerealpage=\realpageno\plusone\else\plustwo\fi}%
+ {\c_scrn_menu_page_mode\plustwo}%
\doglobal\appendetoks
- \scrn_menu_button_mp_template
- \to \scrn_menu_mp_data
+ \scrn_menu_button_meta_template
+ \to \t_scrn_menu_meta_data
\hpos
- {\askedinteractionmenulocation:\number\scrn_menu_position}%
- {\scrn_button_make{#namespace}{#current}{#currentparameter}{#text}{#action}}}
+ {\askedinteractionmenulocation:\number\c_scrn_menu_position}%
+ {\scrn_button_make
+ #currentparameter%
+ #inheritedframed%
+ #letparameter%
+ #setparameter%
+ {#text}%
+ {#action}}}
\unexpanded\def\scrn_menu_got_start[#action]#text\stopgot
{\scrn_menu_action_start
- \setupbuttons[\currentinteractionmenu][\c!frame=\v!off,\c!background=]%
- \scrn_button_make\??am\currentinteractionmenu\interactionmenuparameter{#text}{#action}%
+ \setupcurrentinteractionmenu[\c!frame=\v!off,\c!background=]% needs checking, was buttons
+ \scrn_button_make
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \letinteractionmenuparameter
+ \setinteractionmenuparameter
+ {#text}%
+ {#action}%
\scrn_menu_action_stop}
\unexpanded\def\scrn_menu_nop_start#text\stopnop
{\scrn_menu_action_start
- \localframedwithsettings
- [\??am:\currentinteractionmenu]%
- [\c!frame=\v!off,\c!background=,\c!empty=\v!yes]%
- {\ignorespaces#text\removeunwantedspaces}%
+ \letinteractionmenuparameter\c!frame\v!off
+ \letinteractionmenuparameter\c!background\empty
+ \letinteractionmenuparameter\v!yes
+ \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
\scrn_menu_action_stop}
\unexpanded\def\scrn_menu_txt_start#text\stoptxt
{\scrn_menu_action_start
- \localframedwithsettings
- [\??am:\currentinteractionmenu]%
- [\c!frame=\v!off,\c!background=]%
- {\ignorespaces#text\removeunwantedspaces}%
+ \letinteractionmenuparameter\c!frame\v!off
+ \letinteractionmenuparameter\c!background\empty
+ \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
\scrn_menu_action_stop}
\unexpanded\def\scrn_menu_rul_start#text\stoprul
{\scrn_menu_action_start
- \directlocalframed
- [\??am:\currentinteractionmenu]%
- {\ignorespaces#text\removeunwantedspaces}%
+ \inheritedinteractionmenuframed{\ignorespaces#text\removeunwantedspaces}%
\scrn_menu_action_stop}
\unexpanded\def\scrn_menu_com_start#text\stopcom
@@ -722,20 +747,20 @@
\unexpanded\def\scrn_menu_but#content\\{\scrn_menu_but_start#content\stopbut} \let\stopbut\relax
\unexpanded\def\scrn_menu_got#content\\{\scrn_menu_got_start#content\stopgot} \let\stopgot\relax
\unexpanded\def\scrn_menu_nop#content\\{\scrn_menu_nop_start#content\stopnop} \let\stopnop\relax
-\unexpanded\def\scrn_menu_txt#content\\{\scrn_menu_nop_start#content\stoptxt} \let\stoptxt\relax
+\unexpanded\def\scrn_menu_txt#content\\{\scrn_menu_txt_start#content\stoptxt} \let\stoptxt\relax
\unexpanded\def\scrn_menu_rul#content\\{\scrn_menu_rul_start#content\stoprul} \let\stoprul\relax
\unexpanded\def\scrn_menu_com#content\\{\scrn_menu_com_start#content\stopcom} \let\stopcom\relax
\newtoks\everysetmenucommands % public
\appendtoks
- \let\raw\scrn_menu_raw \let\startraw\scrn_menu_raw_start
- \let\but\scrn_menu_but \let\startbut\scrn_menu_but_start
- \let\got\scrn_menu_got \let\startgot\scrn_menu_got_start
- \let\nop\scrn_menu_nop \let\startnop\scrn_menu_nop_start
- \let\txt\scrn_menu_txt \let\starttxt\scrn_menu_txt_start
- \let\rul\scrn_menu_rul \let\startrul\scrn_menu_rul_start
- \let\com\scrn_menu_com \let\startcom\scrn_menu_com_start
+ \let\raw\scrn_menu_raw \let\startraw\scrn_menu_raw_start \let\stopraw\relax
+ \let\but\scrn_menu_but \let\startbut\scrn_menu_but_start \let\stopbut\relax
+ \let\got\scrn_menu_got \let\startgot\scrn_menu_got_start \let\stopgot\relax
+ \let\nop\scrn_menu_nop \let\startnop\scrn_menu_nop_start \let\stopnop\relax
+ \let\txt\scrn_menu_txt \let\starttxt\scrn_menu_txt_start \let\stoptxt\relax
+ \let\rul\scrn_menu_rul \let\startrul\scrn_menu_rul_start \let\stoprul\relax
+ \let\com\scrn_menu_com \let\startcom\scrn_menu_com_start \let\stopcom\relax
\to \everysetmenucommands
%D Sometimes handy:
@@ -757,8 +782,7 @@
\edef\currentinteractionmenu{#tag}%
\doif{\interactionmenuparameter\c!state}\v!local
{\letinteractionmenuparameter\c!state\v!start
- \setinteractionmenuparameter\s!parent{\??am\askedinteractionmenulocation}% nice hack
- \interactionmenuparameter\c!menu}%
+ \strictinteractionmenuparameter\c!menu}%
\endgroup}
%D Direct call (todo):
@@ -768,13 +792,9 @@
\def\scrn_menu_interaction_menu[#tag][#settings]%
{\begingroup
- \setupinteractionmenu[#tag][#settings]%
-% \edef\currentinteractionmenu {#tag}%
-% \edef\askedinteractionmenulocation {\interactionmenuparameter\c!category}%
-% \edef\askedinteractionmenualternative{\interactionmenuparameter\c!alternative}%
-% \def\scrn_menu_actions#dummy{\scrn_menu_package_indeed\currentinteractionmenu}%
-% \csname\??am:\c!menu:\askedinteractionmenualternative\endcsname
- \scrn_menu_insert{#tag}%
+ \edef\currentinteractionmenu{#tag}%
+ \setupcurrentinteractionmenu[#settings]%
+ \scrn_menu_insert{#tag}%
\endgroup}
%D Plugin handler:
@@ -799,41 +819,33 @@
\unexpanded\def\scrn_menu_leftedge
{\hbox to \leftedgewidth \bgroup
\hsize\leftedgewidth
- %\csname\??tk\v!leftedge\c!left\endcsname
- \settrue\scrn_menu_zerodimensions
+ \settrue\c_scrn_menu_zerodimensions
\scrn_menu_insert\v!left
- %\csname\??tk\v!leftedge\c!right\endcsname
\egroup
\hskip-\leftedgewidth}
\unexpanded\def\scrn_menu_rightedge
{\hbox to \rightedgewidth \bgroup
\hsize\rightedgewidth
- %\csname\??tk\v!rightedge\c!left\endcsname
- \settrue\scrn_menu_zerodimensions
+ \settrue\c_scrn_menu_zerodimensions
\scrn_menu_insert\v!right
- %\csname\??tk\v!rightedge\c!right\endcsname
\egroup
\hskip-\rightedgewidth}
-\unexpanded\def\scrn_menu_top % uses \??tk
+\unexpanded\def\scrn_menu_top
{\vbox to \topheight \bgroup
\vsize\topheight
- %\csname\??tk\v!top\c!before\endcsname
- \settrue\scrn_menu_zerodimensions
+ \settrue\c_scrn_menu_zerodimensions
\scrn_menu_insert\v!top
- %\csname\??tk\v!top\c!after\endcsname
\kern\zeropoint
\egroup
\vskip-\topheight}
-\unexpanded\def\scrn_menu_bottom % uses \??tk
+\unexpanded\def\scrn_menu_bottom
{\vbox to \bottomheight \bgroup
\vsize\bottomheight
- %\csname\??tk\v!bottom\c!before\endcsname
- \settrue\scrn_menu_zerodimensions
+ \settrue\c_scrn_menu_zerodimensions
\scrn_menu_insert\v!bottom
- %\csname\??tk\v!bottom\c!after\endcsname
\kern\zeropoint
\egroup
\vskip-\bottomheight}
@@ -922,15 +934,32 @@
%D Lists:
-\setvalue{\@@dodolistelement\v!left }{\def\dosomelistelement{\scrn_menu_list_element\v!left }}
-\setvalue{\@@dodolistelement\v!right }{\def\dosomelistelement{\scrn_menu_list_element\v!right }}
-\setvalue{\@@dodolistelement\v!top }{\def\dosomelistelement{\scrn_menu_list_element\v!top }}
-\setvalue{\@@dodolistelement\v!bottom}{\def\dosomelistelement{\scrn_menu_list_element\v!bottom}}
+\ifdefined\definelistalternative
+
+ \definelistalternative [\v!left ] [\c!renderingsetup=strc:lists:rendering:menu]
+ \definelistalternative [\v!right ] [\c!renderingsetup=strc:lists:rendering:menu]
+ \definelistalternative [\v!top ] [\c!renderingsetup=strc:lists:rendering:menu]
+ \definelistalternative [\v!bottom] [\c!renderingsetup=strc:lists:rendering:menu]
+
+ \startsetups[strc:lists:rendering:menu]
+ \startbut[internal(\currentlistentryinternal)]
+ \limitatetext\currentlistentrytext{\currentlistparameter\c!maxwidth}\unknown
+ \stopbut
+ \stopsetups
+
+\else % will go
+
+ \setvalue{\??listelement\v!left }{\def\dosomelistelement{\scrn_menu_list_element\v!left }}
+ \setvalue{\??listelement\v!right }{\def\dosomelistelement{\scrn_menu_list_element\v!right }}
+ \setvalue{\??listelement\v!top }{\def\dosomelistelement{\scrn_menu_list_element\v!top }}
+ \setvalue{\??listelement\v!bottom}{\def\dosomelistelement{\scrn_menu_list_element\v!bottom}}
+
+ \def\scrn_menu_list_element#1#2#3#4#5#6#7%
+ {\startbut[internal(#3)]
+ \limitatetext{#5}{\namedlistparameter{#2}\c!maxwidth}\unknown%
+ \stopbut}
-\def\scrn_menu_list_element#1#2#3#4#5#6#7%
- {\startbut[internal(#3)]
- \limitatetext{#5}{\namedlistparameter{#2}\c!maxwidth}\unknown%
- \stopbut}
+\fi
%D Sometimes handy:
@@ -954,7 +983,8 @@
\scrn_menu_menu_button_a
{#menutag}{#settings}{#text}{#action}%
\else
- \doifassignmentelse{#menutag}\scrn_menu_menu_button_b\scrn_menu_menu_button_c{#menutag}{#text}{#action}%
+ \doifassignmentelse{#menutag}\scrn_menu_menu_button_b\scrn_menu_menu_button_c
+ {#menutag}{#text}{#action}%
\fi}
\def\scrn_menu_menu_button_ignore[#menutag][#settings]#text[#action]%
@@ -963,21 +993,42 @@
\def\scrn_menu_menu_button_a#tag#settings#text#action%
{\doif{\interactionmenuparameter\c!state}\v!start
{\dontleavehmode \begingroup
- \setupinteractionmenu[#tag][#settings]%
- \scrn_button_make\??am{#tag}\menuparameter{#text}{#action}%
+ \edef\currentinteractionmenu{#tag}%
+ \setupcurrentinteractionmenu[#settings]%
+ \scrn_button_make
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \letinteractionmenuparameter
+ \setinteractionmenuparameter
+ {#text}%
+ {#action}%
\endgroup}}
\def\scrn_menu_menu_button_b#settings#text#action%
{\doif{\buttonparameter\c!state}\v!start
{\dontleavehmode \begingroup
- \setupbuttons[#settings]%
- \scrn_button_make\??bt\empty\buttonparameter{#text}{#action}%
+ \let\currentbutton\empty
+ \setupcurrentbutton[#settings]%
+ \scrn_button_make
+ \buttonparameter
+ \inheritedbuttonframed
+ \letbuttonparameter
+ \setbuttonparameter
+ {#text}%
+ {#action}%
\endgroup}}
\def\scrn_menu_menu_button_c#tag#text#action%
{\doif{\interactionmenuparameter\c!state}\v!start
{\dontleavehmode \begingroup
- \scrn_button_make\??am{#tag}\menuparameter{#text}{#action}%
+ \edef\currentinteractionmenu{#tag}%
+ \scrn_button_make
+ \interactionmenuparameter
+ \inheritedinteractionmenuframed
+ \letinteractionmenuparameter
+ \setinteractionmenuparameter
+ {#text}%
+ {#action}%
\endgroup}}
%D Untested:
diff --git a/Master/texmf-dist/tex/context/base/scrn-fld.lua b/Master/texmf-dist/tex/context/base/scrn-fld.lua
index 439de13b3f5..275fb4a9b39 100644
--- a/Master/texmf-dist/tex/context/base/scrn-fld.lua
+++ b/Master/texmf-dist/tex/context/base/scrn-fld.lua
@@ -8,6 +8,9 @@ if not modules then modules = { } end modules ['scrn-fld'] = {
-- we should move some code from lpdf-fld to here
+local variables = interfaces.variables
+local v_yes = variables.yes
+
local fields = { }
interactions.fields = fields
@@ -40,7 +43,7 @@ commands.definefieldset = defineset
commands.clonefield = clone
function commands.insertfield(name,specification)
- tex.box["scrn_field_box_body"] = insert(name,specification)
+ tex.box["b_scrn_field_body"] = insert(name,specification)
end
-- (for the monent) only tex interface
@@ -59,6 +62,12 @@ function commands.getdefaultfieldvalue(name)
end
end
+function commands.exportformdata(export)
+ if export == v_yes then
+ codeinjections.exportformdata()
+ end
+end
+
function commands.setformsmethod(method)
codeinjections.setformsmethod(method)
end
diff --git a/Master/texmf-dist/tex/context/base/scrn-fld.mkii b/Master/texmf-dist/tex/context/base/scrn-fld.mkii
index 4e1b34fa974..993b510ea4b 100644
--- a/Master/texmf-dist/tex/context/base/scrn-fld.mkii
+++ b/Master/texmf-dist/tex/context/base/scrn-fld.mkii
@@ -5,7 +5,7 @@
%D subtitle=Fields,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/scrn-fld.mkvi b/Master/texmf-dist/tex/context/base/scrn-fld.mkvi
index bf84f15b79f..87209909961 100644
--- a/Master/texmf-dist/tex/context/base/scrn-fld.mkvi
+++ b/Master/texmf-dist/tex/context/base/scrn-fld.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Fields,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -100,22 +100,23 @@
%D When submitting a form, we need to tell the driver module
%D that we want \FDF\ or \HTML.
-\newtoks\everysetupforms
+\installcorenamespace {forms}
-\unexpanded\def\setupforms
- {\dosingleempty\scrn_forms_setup}
-
-\def\scrn_forms_setup[#settings]
- {\getparameters[\??fr][#settings]%
- \the\everysetupforms}
+\installdirectcommandhandler \??forms {forms}
\appendtoks
- \ctxcommand{setformsmethod("@@frmethod")}%
+ \ctxcommand{setformsmethod("\formsparameter\c!method")}%
\to \everysetupforms
\setupforms
[\c!method=XML] % no need for everyjob initialization as this is the default
+\appendtoks
+ \iflocation
+ \ctxcommand{exportformdata("\formsparameter\c!export")}%
+ \fi
+\to \everystoptext
+
%D We need to initialize symbols in a special way so that they
%D can be used as rendering for a widget.
@@ -128,10 +129,8 @@
\def\scrn_symbols_preset_indeed#tag%
{\doifobjectfoundelse{SYM}{#tag}
{}
- {\settightobject{SYM}{#tag}\hbox{\symbol[#tag]}%
- \flushatshipout
- {\setbox0\hbox{\hskip-\maxdimen\getobject{SYM}{#tag}}%
- \smashbox0\box0}}}
+ {\settightobject{SYM}{#tag}\hbox{\symbol[#tag]}% % todo: set this as immediate xform
+ \page_otr_add_special_content{\hskip-\maxdimen\getobject{SYM}{#tag}}}} % and then force it into the file
\let\dosetfieldsymbol\scrn_symbols_preset_indeed
@@ -140,17 +139,20 @@
\unexpanded\def\definedefaultsymbols % used ?
{\definesymbol[defaultyes][\mathematics{\times}]%
- \definesymbol[defaultno ][\mathematics{\cdot }]}
+ \definesymbol[defaultno] [\mathematics{\cdot }]}
% \def\resetfieldsymbol[#tag]% for experimental usage only
% {\resetobject{SYM}{#tag}}
%D Now comes the real code:
-\installcommandhandler \??fd {fieldcategory} \??fd
-\installcommandhandler \??fb {fieldbody} \??fb
+\installcorenamespace{fieldcategory}
+\installcorenamespace{fieldbody}
+
+\installcommandhandler \??fieldcategory {fieldcategory} \??fieldcategory
+\installcommandhandler \??fieldbody {fieldbody} \??fieldbody
-\newbox\scrn_field_box_body
+\newbox\b_scrn_field_body
\setupfieldcategory
[\c!alternative=\v!normal, % normal clone copy
@@ -165,9 +167,11 @@
\def\scrn_field_check_category
{\edef\currentfieldbodycategory{\fieldbodyparameter\c!category}%
\ifx\currentfieldbodycategory\empty
- \setevalue{\??fb\currentfieldbody\s!parent}{\??fd}%
+ \letfieldbodyparameter\s!parent\??fieldcategory
+ %\setevalue{\currentfieldbodyhash\s!parent}{\namedfieldcategoryhash\empty}% to WS: not hash !
\else
- \setevalue{\??fb\currentfieldbody\s!parent}{\??fd\currentfieldbodycategory}%
+ \normalexpanded{\setfieldbodyparameter{\s!parent}{\??fieldcategory\currentfieldbodycategory}}%
+ %\setevalue{\currentfieldbodyhash\s!parent}{\namedfieldcategoryhash\currentfieldbodycategory}% to WS: not hash !
\fi}
\appendtoks % we cannot use parent .. maybe s!parent has to change
@@ -201,10 +205,10 @@
\hbox\bgroup
\edef\currentfieldbody{#tag}%
\ifsecondargument
- \setupfieldbody[#tag][#settings]%
+ \setupcurrentfieldbody[#settings]%
\fi
\scrn_field_body_typeset
- \box\scrn_field_box_body
+ \box\b_scrn_field_body
\egroup
\fi}
@@ -212,12 +216,14 @@
{\edef\currentfieldframecolor{\fieldbodyparameter\c!fieldframecolor}%
\ifx\currentfieldframecolor\empty\else
\getcolorattributevalue\currentfieldframecolor\currentfieldframecolorvalue
+ % == \edef\currentfieldframecolorvalue{\thecolorattribute\currentfieldframecolor}%
\fi
\edef\currentfieldbackgroundcolor{\fieldbodyparameter\c!fieldbackgroundcolor}%
\ifx\currentfieldbackgroundcolor\empty\else
\getcolorattributevalue\currentfieldbackgroundcolor\currentfieldbackgroundcolorvalue
+ % == \edef\currentfieldbackgroundcolorvalue{\thecolorattribute\currentfieldbackgroundcolor}%
\fi
- \dosetfieldbodyattributes\c!style\c!color
+ \usefieldbodystyleandcolor\c!style\c!color
\ctxcommand{insertfield("\currentfieldbody", {
title = "\currentfieldbody",
width = \number\dimexpr\fieldbodyparameter\c!width \relax,
@@ -235,6 +241,7 @@
\ifx\currentfieldbackgroundcolor\empty \else
backgroundcolor = "\currentfieldbackgroundcolor",
backgroundcolorvalue = "\currentfieldbackgroundcolorvalue",
+
\fi
\ifx\currentfieldframecolor\empty \else
framecolor = "\currentfieldframecolor",
@@ -326,9 +333,10 @@
%D (implemented as properties).
\appendtoks
+ \let\currentfieldcategory\empty
\doifelse{\interactionparameter\c!fieldlayer}\v!auto
- {\setupfieldcategory[\c!fieldlayer=\currentviewerlayer]}%
- {\setupfieldcategory[\c!fieldlayer=]}%
+ {\setupcurrentfieldcategory[\c!fieldlayer=\currentviewerlayer]}%
+ {\setupcurrentfieldcategory[\c!fieldlayer=]}%
\to \everysetupinteraction
\setupinteraction
@@ -344,7 +352,7 @@
%D \ruledhbox{\fitfield[buttona]}
%D \stoptyping
-\newbox\scrn_field_box_fit_symbol
+\newbox\b_scrn_field_fit_symbol
\defineframed
[fitfieldframed]
@@ -360,12 +368,12 @@
{\iflocation
\begingroup
\edef\currentdefaultfieldvalue{\ctxcommand{getdefaultfieldvalue("#tag")}}%
- \setbox\scrn_field_box_fit_symbol\hbox{\symbol[\currentdefaultfieldvalue]}%
+ \setbox\b_scrn_field_fit_symbol\hbox{\symbol[\currentdefaultfieldvalue]}%
\fitfieldframed[#tag]
{\fieldbody[#tag]
- [\c!width=\wd\scrn_field_box_fit_symbol,
- \c!height=\ht\scrn_field_box_fit_symbol,
- \c!depth=\dp\scrn_field_box_fit_symbol,
+ [\c!width=\wd\b_scrn_field_fit_symbol,
+ \c!height=\ht\b_scrn_field_fit_symbol,
+ \c!depth=\dp\b_scrn_field_fit_symbol,
#settings]}%
\endgroup
\fi}
@@ -373,31 +381,35 @@
%D The traditional field command does some labeling and
%D boxing:
-\installparameterhandler \??wl {fieldlabelframed}
-\installparameterhandler \??wc {fieldcontentframed}
-\installparameterhandler \??wt {fieldtotalframed}
+\installcorenamespace{fieldlabel}
+\installcorenamespace{fieldcontent}
+\installcorenamespace{fieldtotal}
+
+\installparameterhandler \??fieldlabel {fieldlabelframed}
+\installparameterhandler \??fieldcontent {fieldcontentframed}
+\installparameterhandler \??fieldtotal {fieldtotalframed}
+
+\installsetuphandler \??fieldlabel {fieldlabelframed}
+\installsetuphandler \??fieldcontent {fieldcontentframed}
+\installsetuphandler \??fieldtotal {fieldtotalframed}
-\installsetuphandler \??wl {fieldlabelframed}
-\installsetuphandler \??wc {fieldcontentframed}
-\installsetuphandler \??wt {fieldtotalframed}
+\installinheritedframed {fieldlabelframed}
+\installinheritedframed {fieldcontentframed}
+\installinheritedframed {fieldtotalframed}
\unexpanded\def\setupfield {\doquintupleempty\scrn_field_setup_field}
\unexpanded\def\setupfields{\doquadrupleempty\scrn_field_setup_fields}
-% \presetlocalframed[\??wl]
-% \presetlocalframed[\??wc]
-% \presetlocalframed[\??wt]
-
\setupfieldcontentframed
[\c!align=\v!flushleft,
\c!strut=\v!no,
- \s!parent=\??ol]
+ \s!parent=\??ol] % needs checking
\setupfieldcontentframed % independent
[\c!alternative=\v!normal,
\c!type=\v!line,
\c!width=5em,
- \c!height=1em,
+ \c!height=\lineheight,
\c!depth=\zeropoint,
\c!align=\v!flushleft,
\c!option=\v!printable,
@@ -407,38 +419,40 @@
[\c!style=,
\c!color=,
\c!align=\v!flushleft,
- \s!parent=\??ol]
+ \s!parent=\??ol] % needs checking
\setupfieldtotalframed
[%\c!alternative={\v!label,\v!frame,\v!horizontal},
\c!strut=\v!no,
\c!align=,
- \s!parent=\??ol]
+ \s!parent=\??ol] % needs checking
+
+% \setupcurrent
\def\scrn_field_setup_field[#tag][#variant][#totalsettings][#labelsettings][#fieldsettings]%
{\iffifthargument
- \definefieldcategory[#tag][\s!parent=\??wc#tag,#fieldsettings]
- \setupfieldtotalframed [#tag][\s!parent=\??wt,\c!alternative={#variant},#totalsettings]%
- \setupfieldlabelframed [#tag][\s!parent=\??wl,#labelsettings]%
- \setupfieldcontentframed[#tag][\s!parent=\??wc,#fieldsettings]%
+ \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#fieldsettings]%
+ \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant},#totalsettings]%
+ \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel,#labelsettings]%
+ \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#fieldsettings]%
\else\iffourthargument
- \definefieldcategory[#tag][\s!parent=\??wc#tag,#labelsettings]
- \setupfieldtotalframed [#tag][\s!parent=\??wt,\c!alternative={#variant},#totalsettings]%
- \setupfieldlabelframed [#tag][\s!parent=\??wl]%
- \setupfieldcontentframed[#tag][\s!parent=\??wc,#labelsettings]%
+ \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#labelsettings]%
+ \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant},#totalsettings]%
+ \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel]%
+ \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#labelsettings]%
\else\ifthirdargument
- \definefieldcategory[#tag][\s!parent=\??wc#tag,#totalsettings]
- \setupfieldtotalframed [#tag][\s!parent=\??wt,\c!alternative={#variant}]%
- \setupfieldlabelframed [#tag][\s!parent=\??wl]%
- \setupfieldcontentframed[#tag][\s!parent=\??wc,#totalsettings]%
+ \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#totalsettings]%
+ \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal,\c!alternative={#variant}]%
+ \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel]%
+ \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#totalsettings]%
\else\ifsecondargument
- \definefieldcategory[#tag][\s!parent=\??wc#tag,#variant]
- \setupfieldtotalframed [#tag][\s!parent=\??wt]%
- \setupfieldlabelframed [#tag][\s!parent=\??wl]%
- \setupfieldcontentframed[#tag][\s!parent=\??wc,#variant]%
+ \definefieldcategory[#tag][\s!parent=\??fieldcontent#tag,#variant]%
+ \setupfieldtotalframed [#tag][\s!parent=\??fieldtotal]%
+ \setupfieldlabelframed [#tag][\s!parent=\??fieldlabel]%
+ \setupfieldcontentframed[#tag][\s!parent=\??fieldcontent,#variant]%
\fi\fi\fi\fi}
-\def\scrn_field_setup_fields[#variant][#totalsettings][#labelsettings][#fieldsettings]
+\def\scrn_field_setup_fields[#variant][#totalsettings][#labelsettings][#fieldsettings]%
{\iffourthargument
\setupfieldtotalframed [\c!alternative={#variant},#totalsettings]%
\setupfieldlabelframed [#labelsettings]%
@@ -456,10 +470,10 @@
% just to get the chain right for no category:
-\definefieldcategory [][\s!parent=\??wc]
-\setupfieldtotalframed [][\s!parent=\??wt]
-\setupfieldlabelframed [][\s!parent=\??wl]
-\setupfieldcontentframed[][\s!parent=\??wc]
+\definefieldcategory [][\s!parent=\??fieldcontent]
+%setupfieldtotalframed [][\s!parent=\??fieldtotal]
+%setupfieldlabelframed [][\s!parent=\??fieldlabel]
+%setupfieldcontentframed[][\s!parent=\??fieldcontent]
% no longer supported:
@@ -475,7 +489,7 @@
\unexpanded\def\field
{\dodoubleempty\scrn_field_direct}
-\def\scrn_field_direct[#tag][#label]%
+\def\scrn_field_direct[#tag][#label]% can be sped up with \setupcurrentfieldtotalframed etc
{\iflocation
\dontleavehmode
\begingroup
@@ -487,9 +501,9 @@
\let\currentfieldlabel\currentfieldbody
\fi
\ifx\currentfieldcategory\empty
- \setupfieldtotalframed [\currentfieldbody][\s!parent=\??wt]%
- \setupfieldlabelframed [\currentfieldbody][\s!parent=\??wl]%
- \setupfieldcontentframed[\currentfieldbody][\s!parent=\??wc]%
+ \setupfieldtotalframed [\currentfieldbody][\s!parent=\??fieldtotal]%
+ \setupfieldlabelframed [\currentfieldbody][\s!parent=\??fieldlabel]%
+ \setupfieldcontentframed[\currentfieldbody][\s!parent=\??fieldcontent]%
\definefieldcategory [\currentfieldbody]%
\setupfieldbody [\currentfieldbody][\c!category=\currentfieldbody]%
\let\currentfieldcategory\currentfieldbody
@@ -499,9 +513,11 @@
\let\currentfieldcontentframed\currentfieldcategory
\scrn_field_analyze_setups
\ifconditional\fieldframeshown
- \localframed[\??wt\currentfieldcategory]\bgroup
+ \inheritedfieldtotalframedframed % lower framedoffset
+ \bgroup
\else
- \vbox\bgroup
+ \vbox
+ \bgroup
\fi
\dontcomplain
\ifconditional\fieldlabelshown
@@ -523,57 +539,67 @@
% opties: veld, label, kader, vertikaal/horizontaal
-\newbox\scrn_field_box_label
-\newbox\scrn_field_box_content
+\newbox\b_scrn_field_label
+\newbox\b_scrn_field_content
% lower framedoffset
\def\scrn_field_set_label_box
- {\setbox\scrn_field_box_label\hbox
+ {\setbox\b_scrn_field_label\hbox
{\reshapeframeboxtrue % else wrong dimensions % still needed?
- \localframed
- [\??wl\currentfieldcategory]
+ \inheritedfieldlabelframedframed
{\currentfieldlabel}}}
% \c!fieldoffset=-\framedoffset,\c!fieldbackgroundcolor=,
% \hbox{\lower\@@fdfieldoffset\hbox{\typesetfield}}
\def\scrn_field_set_content_box
- {\setbox\scrn_field_box_content\hbox
+ {\setbox\b_scrn_field_content\hbox
{\reshapeframeboxtrue % else wrong dimensions (to be checked)
- \ifconditional\fieldisvertical
- \setupfieldcontentframed[\c!height=6ex,\c!width=\hsize]%
- \else\ifconditional\fieldishorizontal
- \setupfieldcontentframed[\c!height=\vsize,\c!width=20em]%
- \else
- \setupfieldcontentframed[\c!height=2cm,\c!width=2cm]%
- \fi\fi
- \localframed % lower framedoffset
- [\??wc\currentfieldcategory]
+ \doifnothing{\fieldcontentframedparameter\c!height}
+ {\ifconditional\fieldisvertical
+ \setfieldcontentframedparameter\c!height{6ex}%
+ \else\ifconditional\fieldishorizontal
+ \setfieldcontentframedparameter\c!height{\vsize}%
+ \else
+ \setfieldcontentframedparameter\c!height{2cm}%
+ \fi\fi}%
+ \doifnothing{\fieldcontentframedparameter\c!width}
+ {\ifconditional\fieldisvertical
+ \setfieldcontentframedparameter\c!width{\hsize}%
+ \else\ifconditional\fieldishorizontal
+ \setfieldcontentframedparameter\c!width{20em}%
+ \else
+ \setfieldcontentframedparameter\c!width{2cm}%
+ \fi\fi}%
+ \inheritedfieldcontentframedframed % lower framedoffset
{\fieldbody
[\currentfieldbody]
[\c!width=\framedwidth,\c!height=\framedheight]}}}
+
\def\scrn_field_flush_vertical
{\vbox
- {\copy\scrn_field_box_label
+ {\copy\b_scrn_field_label
\fieldtotalframedparameter\c!inbetween
- \copy\scrn_field_box_content}}
+ \copy\b_scrn_field_content}}
\def\scrn_field_flush_horizontal
{\hbox
- {\vbox \ifdim\ht\scrn_field_box_content>\ht\scrn_field_box_label to \ht\scrn_field_box_content \fi
+ {\vbox \ifdim\ht\b_scrn_field_content>\ht\b_scrn_field_label to \ht\b_scrn_field_content \fi
{\fieldtotalframedparameter\c!before
- \copy\scrn_field_box_label
+ \copy\b_scrn_field_label
\fieldtotalframedparameter\c!after}%
\hskip\fieldtotalframedparameter\c!distance
- \vbox \ifdim\ht\scrn_field_box_label>\ht\scrn_field_box_content to \ht\scrn_field_box_label \fi
+ \vbox \ifdim\ht\b_scrn_field_label>\ht\b_scrn_field_content to \ht\b_scrn_field_label \fi
{\fieldtotalframedparameter\c!before
- \box\scrn_field_box_content
+ \box\b_scrn_field_content
\fieldtotalframedparameter\c!after}}}
\def\scrn_field_flush_content
- {\box\scrn_field_box_content}
+ {\box\b_scrn_field_content}
+
+%D todo: replace \processallactionsinset
\def\scrn_field_analyze_setups
{\setfalse\fieldlabelshown
@@ -600,11 +626,11 @@
%D Common stuff (obsolete)
-\newcount\scrn_field_system_n
+\newcount\c_scrn_field_system_n
\def\nextsystemfield
- {\global\advance\scrn_field_system_n\plusone
- \def\currentsystemfield{sys::\number\scrn_field_system_n}}
+ {\global\advance\c_scrn_field_system_n\plusone
+ \def\currentsystemfield{sys::\number\c_scrn_field_system_n}}
%D \CONTEXT\ had tooltips right from the moment that it
%D supported fields. Due to the at that moment somewhat
@@ -620,11 +646,13 @@
%D before \tooltip[left]{inbetween}{a very nice tip} after\par
%D \stoptyping
-\newbox \scrn_tooltip_box_anchor
-\newbox \scrn_tooltip_box_text
-\newcount\scrn_tooltip_n
+\newbox \b_scrn_tooltip_anchor
+\newbox \b_scrn_tooltip_text
+\newcount\c_scrn_tooltip_n
-\installcommandhandler \??wh {tooltip} \??wh
+\installcorenamespace{tooltip}
+
+\installframedcommandhandler \??tooltip {tooltip} \??tooltip
\setuptooltip
[\c!location=\v!right,
@@ -633,8 +661,6 @@
\c!background=\v!color,
\c!backgroundcolor=gray]
-\presetlocalframed[\??wh]
-
\appendtoks
\setuevalue\currenttooltip{\scrn_tooltip_direct{\currenttooltip}}%
\to \everydefinetooltip
@@ -651,49 +677,50 @@
\def\scrn_tooltip_indeed[#settings]#anchortext#tiptext% a more modern aproach (push buttons)
{\dontleavehmode \hbox \bgroup
\dontcomplain
- \global\advance\scrn_tooltip_n\plusone
- \edef\currenttooltipname{tooltip:\number\scrn_tooltip_n}%
- \setbox\scrn_tooltip_box_anchor\hbox
+ \global\advance\c_scrn_tooltip_n\plusone
+ \edef\currenttooltipname{tooltip:\number\c_scrn_tooltip_n}%
+ \setbox\b_scrn_tooltip_anchor\hbox
{\strut#anchortext}%
\doifassignmentelse{#settings}
- {\setuptooltip[\currenttooltip][#settings]}%
- {\setuptooltip[\currenttooltip][\c!location=#settings]}%
- \setbox\scrn_tooltip_box_text\hbox
- {\localframed[\??wh\currenttooltip][\c!location=]{#tiptext}}%
+ {\setupcurrenttooltip[#settings]}%
+ {\setupcurrenttooltip[\c!location=#settings]}%
+ \setbox\b_scrn_tooltip_text\hbox
+ {\lettooltipparameter\c!location\empty
+ \inheritedtooltipframed{#tiptext}}%
\definesymbol
[\currenttooltipname:txt]
- [\copy\scrn_tooltip_box_text]%
+ [\copy\b_scrn_tooltip_text]%
\definefieldbody
[\currenttooltipname:txt]
[\c!type=push,
- \c!width=\wd\scrn_tooltip_box_text,
- \c!height=\ht\scrn_tooltip_box_text,
- \c!depth=\dp\scrn_tooltip_box_text,
+ \c!width=\wd\b_scrn_tooltip_text,
+ \c!height=\ht\b_scrn_tooltip_text,
+ \c!depth=\dp\b_scrn_tooltip_text,
\c!option=\v!hidden,
\c!values=\currenttooltipname:txt]%
- \setbox\scrn_tooltip_box_text\hbox
+ \setbox\b_scrn_tooltip_text\hbox
{\fieldbody[\currenttooltipname:txt]}%
- \setbox\scrn_tooltip_box_text\hbox
- {\strut\lower\dimexpr.25ex+\ht\scrn_tooltip_box_text\relax\box\scrn_tooltip_box_text}%
+ \setbox\b_scrn_tooltip_text\hbox
+ {\strut\lower\dimexpr.25ex+\ht\b_scrn_tooltip_text\relax\box\b_scrn_tooltip_text}%
\edef\currenttooltiplocation{\tooltipparameter\c!location}%
\ifx\currenttooltiplocation\v!left
- \hsmashed{\hskip\wd\scrn_tooltip_box_anchor\llap{\box\scrn_tooltip_box_text}}%
+ \hsmashed{\hskip\wd\b_scrn_tooltip_anchor\llap{\box\b_scrn_tooltip_text}}%
\else\ifx\currenttooltiplocation\v!middle
- \hsmashed to \wd\scrn_tooltip_box_anchor{\hss\box\scrn_tooltip_box_text\hss}%
+ \hsmashed to \wd\b_scrn_tooltip_anchor{\hss\box\b_scrn_tooltip_text\hss}%
\else
- \hsmashed{\box\scrn_tooltip_box_text}%
+ \hsmashed{\box\b_scrn_tooltip_text}%
\fi\fi
\definesymbol
[\currenttooltipname:but]
- [\hphantom{\copy\scrn_tooltip_box_anchor}]%
+ [\hphantom{\copy\b_scrn_tooltip_anchor}]%
\definefieldbody
[\currenttooltipname:but]
[\c!type=push,
\c!regionin=action(show{\currenttooltipname:txt}),
\c!regionout=action(hide{\currenttooltipname:txt}),
- \c!width=\wd\scrn_tooltip_box_anchor,
- \c!height=\ht\scrn_tooltip_box_anchor,
- \c!depth=\dp\scrn_tooltip_box_anchor]%
+ \c!width=\wd\b_scrn_tooltip_anchor,
+ \c!height=\ht\b_scrn_tooltip_anchor,
+ \c!depth=\dp\b_scrn_tooltip_anchor]%
\hsmashed{\fieldbody[\currenttooltipname:but]}%
\egroup
#anchortext}% when hyphenated the text wil stick out ... such are fields and we cannot use a link here
@@ -732,32 +759,32 @@
\fi
\getvalue{scrn_fieldstack:#tag}}
-\newbox\scrn_fieldstack_box
+\newbox\b_scrn_fieldstack_box
\def\scrn_fieldstack_add#tag#settings#symbol%
{\advance\scratchcounter\plusone
\edef\currentfieldstackname{#tag:\number\scratchcounter}%
- \ifnum\scratchcounter=\@@fdstart\relax
+ \ifnum\scratchcounter=\fieldcategoryparameter\c!start\relax
\definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\empty},\c!default={#symbol}]%
\else
\definefieldbody[\currentfieldstackname][\c!type=check,\c!values={#symbol,\empty},\c!default=]%
\fi
- \setbox\scrn_fieldstack_box\hbox{\symbol[#symbol]}%
+ \setbox\b_scrn_fieldstack_box\hbox{\symbol[#symbol]}%
\setcollector
[fieldstack]
{\fieldbody
[\currentfieldstackname]
[\c!option=\v!readonly,
- \c!width=\wd\scrn_fieldstack_box,
- \c!height=\ht\scrn_fieldstack_box,
- \c!depth=\dp\scrn_fieldstack_box,
+ \c!width=\wd\b_scrn_fieldstack_box,
+ \c!height=\ht\b_scrn_fieldstack_box,
+ \c!depth=\dp\b_scrn_fieldstack_box,
#settings]}}
\def\scrn_fieldstack_construct[#tag][#symbols][#settings]% start=n, 0 == leeg
{\iflocation
\dontleavehmode
\begingroup
- \getparameters[\??fd][\c!start=1,#settings]%
+ \setupfieldcategory[\c!start=1,#settings]% was just \??fieldcategory
\scrn_field_load_scripts
\definecollector
[fieldstack]%
@@ -783,7 +810,7 @@
%D \framed[background=WithTest]{toggle}
%D \stoptyping
-\newcount\scrn_rollbutton_n
+\newcount\c_scrn_rollbutton_n
\unexpanded\def\overlayrollbutton
{\dodoubleargument\scrn_rollbutton_overlay}
@@ -791,12 +818,12 @@
\def\scrn_rollbutton_overlay[#regionin][#regionout]%
{\iflocation
\bgroup
- \global\advance\scrn_rollbutton_n\plusone
+ \global\advance\c_scrn_rollbutton_n\plusone
\definesymbol
- [rollbutton:\number\scrn_rollbutton_n]
+ [rollbutton:\number\c_scrn_rollbutton_n]
[{\framed[\c!frame=\v!off,\c!width=\overlaywidth,\c!height=\overlayheight]{}}]%
\definefieldbody
- [rollbutton:\number\scrn_rollbutton_n]
+ [rollbutton:\number\c_scrn_rollbutton_n]
[\c!type=push,
\c!regionin={#regionin},
\c!regionout={#regionout},
@@ -806,20 +833,32 @@
\egroup
\fi}
-\protect \endinput
+% \protect \endinput % THE FOLLOWING CODE IS NOT CHECKED
%D I will redo these when I need them.
+% \setupinteraction[state=start]
+%
% \definepushbutton [reset]
%
-% \definepushsymbol [reset] [n] [\uniqueMPgraphic{whatever}{color=green}]
-% \definepushsymbol [reset] [r] [\uniqueMPgraphic{whatever}{color=white}]
+% \startuniqueMPgraphic{whatever}{color}
+% fill fullcircle xysized (OverlayWidth,OverlayHeight) withcolor \MPvar{color} ;
+% \stopuniqueMPgraphic
+%
+% \definepushsymbol [reset] [n] [\uniqueMPgraphic{whatever}{color=red}]
+% \definepushsymbol [reset] [r] [\uniqueMPgraphic{whatever}{color=green}]
+% \definepushsymbol [reset] [d] [\uniqueMPgraphic{whatever}{color=blue}]
%
-% \startinteractionmenu[bottom]
-% \psh [reset] [JS(reset_something)] \\
-% \stopinteractionmenu
+% \starttext
+% \startTEXpage
+% \pushbutton [reset] [page(2)]
+% \stopTEXpage
+% \startTEXpage
+% \pushbutton [reset] [page(1)]
+% \stopTEXpage
+% \stoptext
-\newcount\scrn_pushbutton_n
+\newcount\c_scrn_pushbutton_n
\unexpanded\def\definepushbutton % name optional setup
{\dodoubleempty\scrn_pushbutton_define}
@@ -837,7 +876,7 @@
\def\scrn_pushbutton_handle#tag#settings#reference%
{\bgroup
- \global\advance\scrn_pushbutton_n\plusone
+ \global\advance\c_scrn_pushbutton_n\plusone
\setupfield
[pushbutton]
[\c!frame=\v!overlay,
@@ -845,12 +884,12 @@
\c!clickout={#reference},
#settings]%
\definefield
- [pushbutton:\number\scrn_pushbutton_n]%
+ [pushbutton:\number\c_scrn_pushbutton_n]%
[push]
[pushbutton]
[pushsymbol:#tag:n,pushsymbol:#tag:r,pushsymbol:#tag:d]%
\fitfield
- [pushbutton:\number\scrn_pushbutton_n]%
+ [pushbutton:\number\c_scrn_pushbutton_n]%
\egroup}
\unexpanded\def\definepushsymbol
@@ -877,7 +916,7 @@
\let\startpsh\scrn_menu_psh_start
\let\stoppsh \relax
\let\psh \scrn_menu_psh_direct
-\everysetmenucommands
+\to \everysetmenucommands
%D Another goodie: (unchecked in \MKIV)
@@ -907,53 +946,72 @@
r=green,
d=blue]
-\newcount\scrn_rollbutton_n_button
-\newcount\scrn_rollbutton_n_symbol
+\newcount\c_scrn_rollbutton_n_button
+\newcount\c_scrn_rollbutton_n_symbol
\unexpanded\def\rollbutton
{\dodoubleempty\scrn_rollbutton}
+\def\scrn_rollbutton_symbol_m
+ {\scrn_rollbutton_symbol_indeed
+ \getinteractionmenuparameter
+ \inheritedinteractionmenuframed
+ \setinteractionmenuparameter
+ \useinteractionmenustyleandcolor}
+
+\def\scrn_rollbutton_symbol_b
+ {\scrn_rollbutton_symbol_indeed
+ \getbuttonparameter
+ \inheritedbuttonframed
+ \setbuttonparameter
+ \usebuttonstyleandcolor}
+
\def\scrn_rollbutton[#tag][#settings]#text[#reference]%
{\dontleavehmode
\bgroup
- \doglobal\advance\scrn_rollbutton_n_button
- \doglobal\advance\scrn_rollbutton_n_symbol
+ \doglobal\advance\c_scrn_rollbutton_n_button
+ \doglobal\advance\c_scrn_rollbutton_n_symbol
\iffirstargument
\ifsecondargument
- \getparameters[\??am#tag][#settings]%
- \def\scrn_rollbutton_symbol{\scrn_rollbutton_symbol_indeed{\??am#tag}{#text}}%
+ \edef\currentinteractionmenu{#tag}%
+ \setupcurrentinteractionmenu[#settings]%
+ \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_m
\else
\doifassignmentelse{#tag}
- {\getparameters[\??bt][#tag]%
- \def\scrn_rollbutton_symbol{\scrn_rollbutton_symbol_indeed{\??bt}{#text}}}
- {\def\scrn_rollbutton_symbol{\scrn_rollbutton_symbol_indeed{\??am#tag}{#text}}}%
+ {\let\currentbutton\empty
+ \setupcurrentbutton[#tag]%
+ \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b}%
+ {\edef\currentinteractionmenu{#tag}%
+ \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_m}%
\fi
\else
- \def\scrn_rollbutton_symbol{\set_location_box_indeed_indeed{\??bt}{#text}}%
+ \let\scrn_rollbutton_symbol\scrn_rollbutton_symbol_b
\fi
% todo: share symbols, tricky since different dimensions
- \definesymbol[rollsymbol:\number\scrn_rollbutton_n_symbol:n][\scrn_rollbutton_symbol{n}]%
- \definesymbol[rollsymbol:\number\scrn_rollbutton_n_symbol:r][\scrn_rollbutton_symbol{r}]%
- \definesymbol[rollsymbol:\number\scrn_rollbutton_n_symbol:d][\scrn_rollbutton_symbol{d}]%
+ \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:n][\scrn_rollbutton_symbol{n}{#text}]%
+ \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:r][\scrn_rollbutton_symbol{r}{#text}]%
+ \definesymbol[rollsymbol:\number\c_scrn_rollbutton_n_symbol:d][\scrn_rollbutton_symbol{d}{#text}]%
\setupfield
[rollbutton]
[\c!frame=\v!off,
\c!offset=\v!overlay,
\c!clickout={#reference}]%
\definefield
- [rollbutton:\number\scrn_rollbutton_n_button][push][rollbutton]
- [rollsymbol:\number\scrn_rollbutton_n_symbol:n,%
- rollsymbol:\number\scrn_rollbutton_n_symbol:r,%
- rollsymbol:\number\scrn_rollbutton_n_symbol:d]%
- \fitfield[rollbutton:\number\scrn_rollbutton_n_button]%
+ [rollbutton:\number\c_scrn_rollbutton_n_button][push][rollbutton]
+ [rollsymbol:\number\c_scrn_rollbutton_n_symbol:n,%
+ rollsymbol:\number\c_scrn_rollbutton_n_symbol:r,%
+ rollsymbol:\number\c_scrn_rollbutton_n_symbol:d]%
+ \fitfield[rollbutton:\number\c_scrn_rollbutton_n_button]%
\egroup}
-\unexpanded\def\scrn_rollbutton_symbol_indeed#namespace#text#what%
+\unexpanded\def\scrn_rollbutton_symbol_indeed#getparameter#inheritedframed#setparameter#usestyleandcolor#what#text%
{\definecolor[rollover][rollover:#what]%
- \doifelse{#what}{n}{\doifelsevalue{#namespace\c!alternative}\v!hidden\phantom\hbox}\hbox
- {\localframed[#namespace]
- [\c!framecolor=rollover,\c!backgroundcolor=rollover,\c!color=rollover]%
- {\dolocationattributes{#namespace}\c!style\c!color{#text}}}}%
+ \doifelse{#what}{n}% ?
+ {\doifelse{#getparameter\c!alternative}\v!hidden\phantom\hbox}\hbox
+ {#setparameter\c!framecolor {rollover}%
+ #setparameter\c!backgroundcolor{rollover}%
+ #setparameter\c!color {rollover}%
+ #inheritedframed{#usestyleandcolor\c!style\c!color{#text}}}}
%D We plug into the menu system
@@ -967,6 +1025,6 @@
\let\startrob\scrn_menu_rob_start
\let\stoprob \relax
\let\rob \scrn_menu_rob_direct
-\everysetmenucommands
+\to \everysetmenucommands
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/scrn-hlp.mkii b/Master/texmf-dist/tex/context/base/scrn-hlp.mkii
index c9fcbd29ac0..c526f51ebb4 100644
--- a/Master/texmf-dist/tex/context/base/scrn-hlp.mkii
+++ b/Master/texmf-dist/tex/context/base/scrn-hlp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Help (Experimental),
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/scrn-hlp.mkvi b/Master/texmf-dist/tex/context/base/scrn-hlp.mkvi
index d9782430056..f5a78fb0891 100644
--- a/Master/texmf-dist/tex/context/base/scrn-hlp.mkvi
+++ b/Master/texmf-dist/tex/context/base/scrn-hlp.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Help (Experimental),
%D author={Hans Hagen \& Ton Otten},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -55,12 +55,14 @@
% also status
-\newbox \scrn_help_box
-\newcount\scrn_help_n
+\newbox \b_scrn_help_box
+\newcount\c_scrn_help_n
\definesystemattribute[help][public]
-\installcommandhandler \??wp {help} \??wp
+\installcorenamespace{popuphelp}
+
+\installframedcommandhandler \??popuphelp {help} \??popuphelp
\setuphelp
[\c!frame=\v!off,
@@ -68,8 +70,6 @@
\c!background=\v!color,
\c!backgroundcolor=gray]
-\presetlocalframed[\??wp]
-
\appendtoks
\setuevalue \currenthelp {\scrn_help_argument{\currenthelp}}%
\setuevalue{\e!start\currenthelp}{\scrn_help_start {\currenthelp}}%
@@ -78,8 +78,8 @@
\unexpanded\def\scrn_help_argument#category%
{\def\currenthelp{#category}%
- \global\advance\scrn_help_n\plusone
- \edef\currenthelpname{help:\number\scrn_help_n}%
+ \global\advance\c_scrn_help_n\plusone
+ \edef\currenthelpname{help:\number\c_scrn_help_n}%
\doifelselocation
{\dosingleempty\scrn_help_argument_indeed}
{\dosingleempty\scrn_help_argument_ignore}}
@@ -88,25 +88,25 @@
{\edef\currenthelpreference{#reference}%
\dontleavehmode \hbox \bgroup
\dontcomplain
- \setbox\scrn_help_box\hbox{\strut#text}%
+ \setbox\b_scrn_help_box\hbox{\strut#text}%
\doregisterhelp{#target}%
\egroup % can be usernode instead
\goto
- {\helpsignal{\number\scrn_help_n}#target}%
- [\helpaction{\number\scrn_help_n}]}
+ {\helpsignal{\number\c_scrn_help_n}#target}%
+ [\helpaction{\number\c_scrn_help_n}]}
\def\scrn_help_argument_ignore[#reference]#text#target%
{#target}
\unexpanded\def\scrn_help_start#category%
{\def\currenthelp{#category}%
- \global\advance\scrn_help_n\plusone
- \edef\currenthelpname{help:\number\scrn_help_n}%
+ \global\advance\c_scrn_help_n\plusone
+ \edef\currenthelpname{help:\number\c_scrn_help_n}%
\dosingleempty\scrn_help_start_indeed}
\def\scrn_help_start_indeed[#reference]%
{\edef\currenthelpreference{#reference}%
- \dostartbuffer[\currenthelp][\e!start\currenthelp][\e!stop\currenthelp]}
+ \grabbufferdatadirect\currenthelp{\e!start\currenthelp}{\e!stop\currenthelp}}
\unexpanded\def\scrn_help_stop
{\iflocation
@@ -114,34 +114,33 @@
\fi}
\def\scrn_help_register#text%
- {\setbox\scrn_help_box\hbox
- {\localframed[\??wp\currenthelp]{#text}}%
+ {\setbox\b_scrn_help_box\hbox{\inheritedhelpframed{#text}}%
\definesymbol
[\currenthelpname]
- [\copy\scrn_help_box]%
+ [\copy\b_scrn_help_box]%
\definefieldbody
[\currenthelpname]
[\c!type=push,
- \c!width=\wd\scrn_help_box,
- \c!height=\ht\scrn_help_box,
- \c!depth=\dp\scrn_help_box,
+ \c!width=\wd\b_scrn_help_box,
+ \c!height=\ht\b_scrn_help_box,
+ \c!depth=\dp\b_scrn_help_box,
\c!option=\v!hidden,
\c!clickin=action(hide{\currenthelpname}),
\c!closepage=action(hide{\currenthelpname}),
\c!values=\currenthelpname]%
- \setbox\scrn_help_box\hbox
+ \setbox\b_scrn_help_box\hbox
{\fieldbody[\currenthelpname]}%
- \ctxcommand{registerhelp(\number\scrn_help_n,"\currenthelpreference",\number\scrn_help_box)}}
+ \ctxcommand{registerhelp(\number\c_scrn_help_n,"\currenthelpreference",\number\b_scrn_help_box)}}
\def\doifelsehelp
- {\ifcase\scrn_help_n
+ {\ifcase\c_scrn_help_n
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
\def\placehelp % was \helpdata
- {\ifinpagebody\ifcase\scrn_help_n\else
+ {\ifinpagebody\ifcase\c_scrn_help_n\else
\ctxcommand{collecthelp(255)}% rather hard coded ... bad
\fi\fi}
diff --git a/Master/texmf-dist/tex/context/base/scrn-ini.mkvi b/Master/texmf-dist/tex/context/base/scrn-ini.mkvi
index 860c696c0e8..daf0a1b911c 100644
--- a/Master/texmf-dist/tex/context/base/scrn-ini.mkvi
+++ b/Master/texmf-dist/tex/context/base/scrn-ini.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -27,14 +27,16 @@
%D
%D \showsetup{setupinteraction}
-\installcommandhandler\??ia{interaction}\??ia
+\installcorenamespace{interaction}
-\let\currentinteraction\empty
+\installswitchcommandhandler \??interaction {interaction} \??interaction
\appendtoks
- \doifelse{\interactionparameter\c!state}\v!start
- {\locationtrue \setsystemmode \v!interaction}%
- {\locationfalse \resetsystemmode\v!interaction}%
+ \ifx\currentinteraction\previousinteraction
+ \doifelse{\interactionparameter\c!state}\v!start
+ {\locationtrue \setsystemmode \v!interaction}%
+ {\locationfalse \resetsystemmode\v!interaction}%
+ \fi
\to \everysetupinteraction
\def\doifelselocation
@@ -85,6 +87,17 @@
\unexpanded\def\setinteraction[#1]%
{\def\currentinteraction{#1}}
+\defineinteraction % keep it simple
+ [\v!hidden]
+
+\setupinteraction
+ [\v!hidden]
+ [\c!state=\v!start,
+ \c!color=,
+ \c!contrastcolor=,
+ \c!style=,
+ \c!click=\v!off]
+
%D As long as there a natural feeling of what can be considered
%D hyper active or not, we have to tell users where they can
%D possibly click. We've already seen a few macros that deal
@@ -107,46 +120,49 @@
%D When we're dealing with pure page references, contrast
%D colors are used when we are already at the page mentioned.
-\def\setlocationcolor#1% not grouped !
- {\ifnum\referencepagestate=\plusone
- \edef\askedcontrastcolor{\csname#1\c!contrastcolor\endcsname}%
+\unexpanded\def\setlocationcolorspecified#1% not grouped !
+ {\ifnum#1=\plusone
+ \edef\askedcontrastcolor{\interactionparameter\c!contrastcolor}%
\ifx\askedcontrastcolor\empty
- \dosetcolorattribute{#1}\c!color
+ \useinteractioncolorparameter\c!color
\else
- \dosetcolorattribute{#1}\c!contrastcolor
+ \useinteractioncolorparameter\c!contrastcolor
\fi
\else % we could just set and if > 0 set again
- \dosetcolorattribute{#1}\c!color
+ \useinteractioncolorparameter\c!color
\fi}
-\def\setlocationfont#1%
- {\dosetfontattribute{#1}\c!style}
-
-\def\setlocationattributes#1%
- {\ifnum\referencepagestate=\plusone
- \edef\askedcontrastcolor{\csname#1\c!contrastcolor\endcsname}%
+\unexpanded\def\setlocationattributesspecified#1% not grouped !
+ {\ifnum#1=\plusone
+ \edef\askedcontrastcolor{\interactionparameter\c!contrastcolor}%
\ifx\askedcontrastcolor\empty
- \dosetcolorattribute{#1}\c!color
+ \useinteractionstyleandcolor\c!style\c!color
\else
- \dosetcolorattribute{#1}\c!contrastcolor
+ \useinteractionstyleandcolor\c!style\c!contrastcolor
\fi
\else % we could just set and if > 0 set again
- \dosetcolorattribute{#1}\c!color
- \fi
- \dosetfontattribute{#1}\c!style}
+ \useinteractionstyleandcolor\c!style\c!color
+ \fi}
-\def\setlocationcolorspec#1% \resolver
- {\ifnum\referencepagestate=\plusone
- \edef\askedcontrastcolor{#1\c!contrastcolor}%
+\unexpanded\def\setlocationcolorspec#1#2% \resolver
+ {\ifnum#1=\plusone
+ \edef\askedcontrastcolor{#2\c!contrastcolor}%
\ifx\askedcontrastcolor\empty
- \doactivatecolor{#1\c!color}%
+ \doactivatecolor{#2\c!color}%
\else
\doactivatecolor\askedcontrastcolor
\fi
\else
- \doactivatecolor{#1\c!color}%
+ \doactivatecolor{#2\c!color}%
\fi}
+\unexpanded\def\setlocationcolor {\setlocationcolorspecified \referencepagestate}
+\unexpanded\def\setlocationattributes{\setlocationattributesspecified\referencepagestate}
+\unexpanded\def\setlocationcolorspec {\setlocationcolorspecspecified \referencepagestate}
+
+\unexpanded\def\setlocationfont % not grouped !
+ {\useinteractionstyleparameter\c!style}
+
\setupinteraction
[\c!style=\v!bold,
\c!color=interactioncolor,
@@ -168,6 +184,12 @@
\scrn_identity_synchronize
\to \everysetupinteraction
+\appendtoks % not interfaced i.e. english
+ \doifvariable{document}{metadata:author}{\setupinteraction[author=\documentvariable{metadata:author}]}%
+ \doifvariable{document}{metadata:title}{\setupinteraction[title=\documentvariable{metadata:title}]}%
+ \doifvariable{document}{metadata:subject}{\setupinteraction[subject=\documentvariable{metadata:subject}]}%
+\to \everysetupdocument
+
\setupinteraction
[\c!title=,
\c!subtitle=,
diff --git a/Master/texmf-dist/tex/context/base/scrn-int.mkii b/Master/texmf-dist/tex/context/base/scrn-int.mkii
index cf55f864af6..01d8501e217 100644
--- a/Master/texmf-dist/tex/context/base/scrn-int.mkii
+++ b/Master/texmf-dist/tex/context/base/scrn-int.mkii
@@ -5,7 +5,7 @@
%D subtitle=Interaction,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -89,7 +89,8 @@
\advance\backspace -\!!widtha
\fi\fi
\advance\!!widtha\rightcombitotal
- \advance\!!widtha 2\dimexpr\@@scbackspace+\@@schoroffset\relax}
+ \advance\!!widtha 2\dimexpr\@@scbackspace+\@@schoroffset\relax
+ \advance\!!widtha \makeupwidth}
{\doifelse\@@scwidth\v!max
{\!!widtha\printpaperwidth}
{\!!widtha\@@scwidth}}%
@@ -1128,7 +1129,7 @@
\dostepwiserecurse\plusone\lastpage\!!counta
{\gotorealpage\empty\empty\recurselevel{\copy\scratchbox}}%
\hss}%
- \global\wd\interactionbarbox\zeropoint
+ \wd\interactionbarbox\zeropoint
\egroup
\fi
\egroup
diff --git a/Master/texmf-dist/tex/context/base/scrn-nav.mkii b/Master/texmf-dist/tex/context/base/scrn-nav.mkii
index 591d4134c36..3bb56bacee7 100644
--- a/Master/texmf-dist/tex/context/base/scrn-nav.mkii
+++ b/Master/texmf-dist/tex/context/base/scrn-nav.mkii
@@ -5,7 +5,7 @@
%D subtitle=Navigation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/scrn-pag.mkvi b/Master/texmf-dist/tex/context/base/scrn-pag.mkvi
index 8e1dbde8e9c..66f197ffdc2 100644
--- a/Master/texmf-dist/tex/context/base/scrn-pag.mkvi
+++ b/Master/texmf-dist/tex/context/base/scrn-pag.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Pages, % moved code
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,8 +19,10 @@
\unprotect
-\installparameterhandler \??sc {interactionscreen}
-\installsetuphandler \??sc {interactionscreen}
+\installcorenamespace{interactionscreen}
+
+\installparameterhandler \??interactionscreen {interactionscreen}
+\installsetuphandler \??interactionscreen {interactionscreen}
\newdimen\canvaswidth
\newdimen\canvasheight
@@ -29,68 +31,7 @@
\newdimen\canvasmaxwidth
\newdimen\canvasmaxheight
-\newconditional\scrn_canvas_tight_page
-
-% \def\scrn_canvas_calculate
-% {\begingroup
-% \edef\currentinteractionscreenwidth {\interactionscreenparameter\c!width }%
-% \edef\currentinteractionscreenheight{\interactionscreenparameter\c!height}%
-% \canvasbackoffset\backspace
-% \canvastopoffset\topspace
-% \ifx\currentinteractionscreenwidth\v!fit
-% \global\canvaswidth\leftcombitotal
-% \ifdim\backspace>\canvaswidth
-% \ifdim\backspace>\zeropoint\relax
-% \global\advance\canvasbackoffset -\canvaswidth
-% \fi
-% \fi
-% \global\advance\canvaswidth\dimexpr
-% \rightcombitotal
-% + 2\dimexpr
-% \interactionscreenparameter\c!backspace
-% + \interactionscreenparameter\c!horoffset
-% \relax
-% \relax
-% \donetrue
-% \else\ifx\currentinteractionscreenwidth\v!max
-% \global\canvaswidth\printpaperwidth
-% \donetrue
-% \else
-% \global\canvaswidth\currentinteractionscreenwidth
-% \donefalse
-% \fi\fi
-% \ifdone
-% \ifdim\canvaswidth>\paperwidth\ifdim\canvaswidth>\zeropoint
-% \global\paperwidth\canvaswidth % kills location=middle
-% \fi\fi
-% \fi
-% \ifx\currentinteractionscreenheight\v!fit
-% \global\canvasheight\dimexpr\topheight+\topdistance\relax
-% \ifdim\topspace>\canvasheight
-% \ifdim\topspace>\zeropoint\relax
-% \global\advance\canvastopoffset -\canvasheight
-% \fi
-% \fi
-% \global\advance\canvasheight\dimexpr
-% \makeupheight
-% + \bottomdistance
-% + \bottomheight
-% + 2\dimexpr
-% \interactionscreenparameter\c!topspace
-% + \interactionscreenparameter\c!veroffset
-% \relax
-% \relax
-% \else\ifx\currentinteractionscreenheight\v!max
-% \global\canvasheight\printpaperheight
-% \else
-% \global\canvasheight\currentinteractionscreenheight
-% \fi\fi
-% \ifdone
-% \ifdim\canvasheight>\paperheight\ifdim\canvasheight>\zeropoint
-% \global\paperheight\canvasheight % kills location=middle
-% \fi\fi
-% \fi
-% \endgroup}
+\newconditional\c_scrn_canvas_tight_page
\def\scrn_canvas_calculate
{\begingroup
@@ -98,26 +39,50 @@
\edef\currentinteractionscreenheight{\interactionscreenparameter\c!height}%
\canvasbackoffset\backspace
\canvastopoffset\topspace
- \ifx\currentinteractionscreenwidth\v!fit
- \global\canvaswidth\leftcombitotal
+ \ifx\currentinteractionscreenwidth\v!max
+ \global\canvaswidth\printpaperwidth
+ \else\ifx\currentinteractionscreenwidth\v!fit
+ \global\canvaswidth\dimexpr
+ \leftcombitotal
+ + \makeupwidth
+ + \rightcombitotal
+ + 2\dimexpr
+ \interactionscreenparameter\c!backspace
+ + \interactionscreenparameter\c!horoffset
+ \relax
+ \relax
+ \else\ifx\currentinteractionscreenwidth\v!tight
\ifdim\backspace>\canvaswidth
\ifdim\backspace>\zeropoint\relax
\global\advance\canvasbackoffset -\canvaswidth
\fi
\fi
\global\advance\canvaswidth\dimexpr
- \rightcombitotal
+ \makeupwidth
+ + \rightcombitotal
+ 2\dimexpr
\interactionscreenparameter\c!backspace
+ \interactionscreenparameter\c!horoffset
\relax
\relax
- \else\ifx\currentinteractionscreenwidth\v!max
- \global\canvaswidth\printpaperwidth
\else
\global\canvaswidth\currentinteractionscreenwidth
- \fi\fi
- \ifx\currentinteractionscreenheight\v!fit
+ \fi\fi\fi
+ \ifx\currentinteractionscreenheight\v!max
+ \global\canvasheight\printpaperheight
+ \else\ifx\currentinteractionscreenheight\v!fit
+ \global\canvasheight\dimexpr
+ \topheight
+ + \topdistance
+ + \makeupheight
+ + \bottomdistance
+ + \bottomheight
+ + 2\dimexpr
+ \interactionscreenparameter\c!topspace
+ + \interactionscreenparameter\c!veroffset
+ \relax
+ \relax
+ \else\ifx\currentinteractionscreenheight\v!tight
\global\canvasheight\dimexpr\topheight+\topdistance\relax
\ifdim\topspace>\canvasheight
\ifdim\topspace>\zeropoint\relax
@@ -133,15 +98,13 @@
+ \interactionscreenparameter\c!veroffset
\relax
\relax
- \else\ifx\currentinteractionscreenheight\v!max
- \global\canvasheight\printpaperheight
\else
\global\canvasheight\currentinteractionscreenheight
- \fi\fi
- \ifconditional\page_location_is_set
- \global\setfalse\scrn_canvas_tight_page
+ \fi\fi\fi
+ \ifconditional\c_page_layouts_location_is_set
+ \global\setfalse\c_scrn_canvas_tight_page
\fi
- \ifconditional\scrn_canvas_tight_page
+ \ifconditional\c_scrn_canvas_tight_page
\global\canvasmaxwidth \paperwidth
\global\canvasmaxheight\paperheight
\else
@@ -183,8 +146,8 @@
\appendtoks
\doifcommonelse{\interactionscreenparameter\c!option}{\v!max,\v!fit}%
- {\global\settrue \scrn_canvas_tight_page}%
- {\global\setfalse\scrn_canvas_tight_page}%
+ {\global\settrue \c_scrn_canvas_tight_page}%
+ {\global\setfalse\c_scrn_canvas_tight_page}%
\to \everysetupinteractionscreen
\appendtoks
diff --git a/Master/texmf-dist/tex/context/base/scrn-ref.mkvi b/Master/texmf-dist/tex/context/base/scrn-ref.mkvi
index 8c3f4fb4aba..a06ba1ad8fc 100644
--- a/Master/texmf-dist/tex/context/base/scrn-ref.mkvi
+++ b/Master/texmf-dist/tex/context/base/scrn-ref.mkvi
@@ -5,7 +5,7 @@
%D subtitle=References, % moved code
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/scrn-wid.lua b/Master/texmf-dist/tex/context/base/scrn-wid.lua
index 7b1dd940a2c..6fdc4fca0d6 100644
--- a/Master/texmf-dist/tex/context/base/scrn-wid.lua
+++ b/Master/texmf-dist/tex/context/base/scrn-wid.lua
@@ -28,6 +28,10 @@ local nodeinjections = backends.nodeinjections
local variables = interfaces.variables
local v_auto = variables.auto
+local trace_attachments = false trackers.register("widgets.attachments", function(v) trace_attachments = v end)
+
+local report_attachments = logs.reporter("widgets","attachments")
+
-- Symbols
function commands.presetsymbollist(list)
@@ -66,10 +70,13 @@ local function checkbuffer(specification)
end
end
-function attachments.register(specification)
- checkregistered(specification)
+function attachments.register(specification) -- beware of tag/registered mixup(tag is namespace)
+ local registered = checkregistered(specification)
checkbuffer(specification)
- attachments[lastregistered] = specification
+ attachments[registered] = specification
+ if trace_attachments then
+ report_attachments("registering '%s'",registered)
+ end
return specification
end
@@ -77,12 +84,17 @@ function attachments.insert(specification)
local registered = checkregistered(specification)
local r = attachments[registered]
if r then
+ if trace_attachments then
+ report_attachments("including registered '%s'",registered)
+ end
for k, v in next, r do
local s = specification[k]
if s == "" then
specification[k] = v
end
end
+ elseif trace_attachments then
+ report_attachments("including unregistered '%s'",registered)
end
checkbuffer(specification)
return nodeinjections.attachfile(specification)
@@ -91,7 +103,7 @@ end
commands.registerattachment = attachments.register
function commands.insertattachment(specification)
- tex.box["scrn_attachment_box_link"] = attachments.insert(specification)
+ tex.box["b_scrn_attachment_link"] = attachments.insert(specification)
end
-- Comment
@@ -105,7 +117,7 @@ function comments.insert(specification)
end
function commands.insertcomment(specification)
- tex.box["scrn_comment_box_link"] = comments.insert(specification)
+ tex.box["b_scrn_comment_link"] = comments.insert(specification)
end
-- Soundclips
diff --git a/Master/texmf-dist/tex/context/base/scrn-wid.mkvi b/Master/texmf-dist/tex/context/base/scrn-wid.mkvi
index 72f5255bbce..2b75f83cd75 100644
--- a/Master/texmf-dist/tex/context/base/scrn-wid.mkvi
+++ b/Master/texmf-dist/tex/context/base/scrn-wid.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Widgets,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -60,11 +60,14 @@
% startattachment -> temp file
-\newbox\scrn_attachment_box_collect
-\newbox\scrn_attachment_box_link
-\newbox\scrn_attachment_box_symbol
+\newbox\b_scrn_attachment_collect
+\newbox\b_scrn_attachment_link
+\newbox\b_scrn_attachment_symbol
-\installcommandhandler\??at{attachment}\??at
+\installcorenamespace{attachment}
+\installcorenamespace{attachmentlocation}
+
+\installcommandhandler \??attachment {attachment} \??attachment
\let\setupattachments\setupattachment % convenience and compatibility
@@ -94,17 +97,20 @@
{\ifsecondargument
\begingroup
\def\currentattachment{_}%
- \setupattachment[_][#settings,\s!parent=\??at]%
+ \setupcurrentattachment[#settings,\s!parent=\??attachment]%
\ctxcommand{registerattachment{
- tag = "#tag",
- title = "\attachmentparameter\c!title",
- subtitle = "\attachmentparameter\c!subtitle",
- author = "\attachmentparameter\c!author",
- file = "\attachmentparameter\c!file",
- name = "\attachmentparameter\c!name",
- buffer = "\attachmentparameter\c!buffer",
+ tag = "#tag",
+ registered = "#tag",
+ title = "\attachmentparameter\c!title",
+ subtitle = "\attachmentparameter\c!subtitle",
+ author = "\attachmentparameter\c!author",
+ file = "\attachmentparameter\c!file",
+ name = "\attachmentparameter\c!name",
+ buffer = "\attachmentparameter\c!buffer",
}}%
\endgroup
+ \else
+ % todo
\fi}
\appendtoks
@@ -157,7 +163,7 @@
{\doifassignmentelse{#registered}
{\def\scrn_attachment_stop{\scrn_attachment_inject[\v!auto][\c!buffer=\v!attachment,#registered]\egroup}}%
{\def\scrn_attachment_stop{\scrn_attachment_inject[#registered][\c!buffer=\v!attachment,#settings]\egroup}}}%
- \dostartbuffer[\v!attachment][\e!start\currentattachment][\e!stop\currentattachment]}
+ \grabbufferdatadirect\v!attachment{\e!start\currentattachment}{\e!stop\currentattachment}}
\def\scrn_attachment_start_ignore
{\expandafter\gobbleuntil\csname\e!stop\currentattachment\endcsname}
@@ -179,10 +185,10 @@
\else
\ctxcommand{presetsymbollist("\attachmentparameter\c!symbol")}%
% we cannot yet ask for the wd/ht/dp of an xform else we could use those
- \setbox\scrn_attachment_box_symbol\hbox{\symbol[\lastpredefinedsymbol]}%
- \ifx\currentattachmentwidth \v!fit\edef\currentattachmentwidth {\wd\scrn_attachment_box_symbol}\fi
- \ifx\currentattachmentheight\v!fit\edef\currentattachmentheight{\ht\scrn_attachment_box_symbol}\fi
- \ifx\currentattachmentdepth \v!fit\edef\currentattachmentdepth {\dp\scrn_attachment_box_symbol}\fi
+ \setbox\b_scrn_attachment_symbol\hbox{\symbol[\lastpredefinedsymbol]}%
+ \ifx\currentattachmentwidth \v!fit\edef\currentattachmentwidth {\wd\b_scrn_attachment_symbol}\fi
+ \ifx\currentattachmentheight\v!fit\edef\currentattachmentheight{\ht\b_scrn_attachment_symbol}\fi
+ \ifx\currentattachmentdepth \v!fit\edef\currentattachmentdepth {\dp\b_scrn_attachment_symbol}\fi
\fi
\ctxcommand{insertattachment{
tag = "\currentattachment",
@@ -191,7 +197,7 @@
height = \number\dimexpr\currentattachmentheight\relax,
depth = \number\dimexpr\currentattachmentdepth \relax,
color = "\attachmentparameter\c!color",
- colormodel = \number\currentcolormodel,
+ colormodel = \number\attribute\colormodelattribute,
colorvalue = \thecolorattribute{\attachmentparameter\c!color},
transparencyvalue = \thetransparencyattribute{\attachmentparameter\c!color},
symbol = "\currentattachmentsymbol",
@@ -204,11 +210,11 @@
name = "\attachmentparameter\c!name",
buffer = "\attachmentparameter\c!buffer",
}}%
- \setbox\scrn_attachment_box_link\hbox{\scrn_attachment_place}%
- \wd\scrn_attachment_box_link\currentattachmentwidth
- \ht\scrn_attachment_box_link\currentattachmentheight
- \dp\scrn_attachment_box_link\currentattachmentdepth
- \box\scrn_attachment_box_link}
+ \setbox\b_scrn_attachment_link\hbox{\scrn_attachment_place}%
+ \wd\b_scrn_attachment_link\currentattachmentwidth
+ \ht\b_scrn_attachment_link\currentattachmentheight
+ \dp\b_scrn_attachment_link\currentattachmentdepth
+ \box\b_scrn_attachment_link}
\setvalue{scrn_attachment_method_\v!hidden}%
{\ctxcommand{insertattachment{
@@ -219,29 +225,29 @@
\def\scrn_attachment_place
{\executeifdefined
- {\??at:\c!location:\attachmentparameter\c!location}\hbox
- {\box\scrn_attachment_box_link}}
+ {\??attachmentlocation\attachmentparameter\c!location}\hbox
+ {\box\b_scrn_attachment_link}}
-\setvalue{\??at:\c!location:\v!inmargin }{\inmargin }
-\setvalue{\??at:\c!location:\v!leftedge }{\inleftedge }
-\setvalue{\??at:\c!location:\v!rightedge }{\inrightedge }
-\setvalue{\??at:\c!location:\v!leftmargin }{\inleftmargin }
-\setvalue{\??at:\c!location:\v!rightmargin}{\inrightmargin}
-\setvalue{\??at:\c!location:\v!high }{\high}
-\setvalue{\??at:\c!location:\v!none }{\scrn_attachment_collect}
+\setvalue{\??attachmentlocation\v!inmargin }{\inmargin }
+\setvalue{\??attachmentlocation\v!leftedge }{\inleftedge }
+\setvalue{\??attachmentlocation\v!rightedge }{\inrightedge }
+\setvalue{\??attachmentlocation\v!leftmargin }{\inleftmargin }
+\setvalue{\??attachmentlocation\v!rightmargin}{\inrightmargin}
+\setvalue{\??attachmentlocation\v!high }{\high}
+\setvalue{\??attachmentlocation\v!none }{\scrn_attachment_collect}
\def\scrn_attachment_collect#content%
- {\global\setbox\scrn_attachment_box_collect\hbox\bgroup
- \ifvoid\scrn_attachment_box_collect\else
- \box\scrn_attachment_box_collect
+ {\global\setbox\b_scrn_attachment_collect\hbox\bgroup
+ \ifvoid\b_scrn_attachment_collect\else
+ \box\b_scrn_attachment_collect
\hskip\attachmentparameter\c!distance
\fi
#content%
\egroup}
\unexpanded\def\placeattachments
- {\ifvoid\scrn_attachment_box_collect\else
- \box\scrn_attachment_box_collect
+ {\ifvoid\b_scrn_attachment_collect\else
+ \box\b_scrn_attachment_collect
\fi}
\defineattachment[attachment]
@@ -345,12 +351,15 @@
%
% test
-\installcommandhandler\??cc{comment}\??cc
+\installcorenamespace{comment}
+\installcorenamespace{commentlocation}
+
+\installcommandhandler \??comment {comment} \??comment
-\newbox\scrn_comment_box_collect
-\newbox\scrn_comment_box_rendering
-\newbox\scrn_comment_box_link
-\newbox\scrn_comment_box_symbol
+\newbox\b_scrn_comment_collect
+\newbox\b_scrn_comment_rendering
+\newbox\b_scrn_comment_link
+\newbox\b_scrn_comment_symbol
\setupcomment
[\c!state=\v!start,
@@ -368,8 +377,6 @@
\c!ny=10,
\c!location=\v!high]
-\presetlocalframed[\??cc]
-
\appendtoks
\setuevalue \currentcomment {\scrn_comment_argument{\currentcomment}}%
\setuevalue{\e!start\currentcomment}{\scrn_comment_start {\currentcomment}}%
@@ -389,8 +396,8 @@
\def\scrn_comment_argument_indeed[#title][#settings]#text%
{\doifassignmentelse{#title}
- {\setupcomment[\currentcomment][#title]}
- {\setupcomment[\currentcomment][\c!title=#title,#settings]}%
+ {\setupcurrentcomment[#title]}
+ {\setupcurrentcomment[\c!title=#title,#settings]}%
\ctxlua{buffers.assign("\v!comment",\!!bs#text\!!es)}% todo: expansion control, but expanded by default (xml)
\scrn_comment_inject
\ignorespaces}
@@ -401,10 +408,10 @@
\unexpanded\def\scrn_comment_start#category%
{\def\currentcomment{#category}%
\doifelselocation
- {\dodoubleempty\scrn_comment_start_indeed}
+ {\dodoubleempty\scrn_comment_start_status}
{\dodoubleempty\scrn_comment_start_ignore}}
-\def\scrn_comment_start_indeed
+\def\scrn_comment_start_status
{\doifelse{\commentparameter\c!state}\v!start
{\scrn_comment_start_indeed}
{\scrn_comment_start_ignore}}
@@ -412,10 +419,10 @@
\def\scrn_comment_start_indeed[#title][#settings]%
{\bgroup
\doifassignmentelse{#title}
- {\setupcomment[\currentcomment][#title]}
- {\setupcomment[\currentcomment][\c!title=#title,#settings]}%
+ {\setupcurrentcomment[#title]}
+ {\setupcurrentcomment[\c!title=#title,#settings]}%
\def\scrn_comment_stop{\scrn_comment_inject\egroup}%
- \dostartbuffer[\v!comment][\e!start\currentcomment][\e!stop\currentcomment]}
+ \grabbufferdatadirect\v!comment{\e!start\currentcomment}{\e!stop\currentcomment}}
\def\scrn_comment_start_ignore
{\expandafter\gobbleuntil\csname\e!stop\currentcomment\endcsname}
@@ -423,13 +430,15 @@
\unexpanded\def\scrn_comment_stop
{}
+\installcorenamespace{commentmethods}
+
\def\scrn_comment_inject
- {\expandcheckedcsname{scrn_comment_method_}{\commentparameter\c!method}\v!normal}
+ {\expandcheckedcsname\??commentmethods{\commentparameter\c!method}\v!normal}
%D Beware: comments symbols don't scale in acrobat (cf. spec but somewhat
%D weird, esp because for instance attachment symbols do scale).
-\setvalue{scrn_comment_method_\v!normal}%
+\setvalue{\??commentmethods\v!normal}%
{\edef\currentcommentsymbol{\commentparameter\c!symbol}%
\edef\currentcommentwidth {\commentparameter\c!width }%
\edef\currentcommentheight{\commentparameter\c!height}%
@@ -441,10 +450,10 @@
\else
\ctxcommand{presetsymbollist("\commentparameter\c!symbol")}%
% we cannot yet ask for the wd/ht/dp of an xform else we could use those
- \setbox\scrn_comment_box_symbol\hbox{\symbol[\lastpredefinedsymbol]}%
- \ifx\currentcommentwidth \v!fit\edef\currentcommentwidth {\wd\scrn_comment_box_symbol}\fi
- \ifx\currentcommentheight\v!fit\edef\currentcommentheight{\ht\scrn_comment_box_symbol}\fi
- \ifx\currentcommentdepth \v!fit\edef\currentcommentdepth {\dp\scrn_comment_box_symbol}\fi
+ \setbox\b_scrn_comment_symbol\hbox{\symbol[\lastpredefinedsymbol]}%
+ \ifx\currentcommentwidth \v!fit\edef\currentcommentwidth {\wd\b_scrn_comment_symbol}\fi
+ \ifx\currentcommentheight\v!fit\edef\currentcommentheight{\ht\b_scrn_comment_symbol}\fi
+ \ifx\currentcommentdepth \v!fit\edef\currentcommentdepth {\dp\b_scrn_comment_symbol}\fi
\fi
\ctxcommand{insertcomment{
tag = "\currentcomment",
@@ -456,7 +465,7 @@
depth = \number\dimexpr\currentcommentdepth,
nx = \commentparameter\c!nx,
ny = \commentparameter\c!ny,
- colormodel = \number\currentcolormodel,
+ colormodel = \number\attribute\colormodelattribute,
colorvalue = \thecolorattribute{\commentparameter\c!color},
transparencyvalue = \thetransparencyattribute{\commentparameter\c!color},
option = "\commentparameter\c!option", % todo
@@ -464,41 +473,41 @@
buffer = "\v!comment",
layer = "\commentparameter\c!textlayer"
}}%
- \wd\scrn_comment_box_link\currentcommentwidth
- \ht\scrn_comment_box_link\currentcommentheight
- \dp\scrn_comment_box_link\currentcommentdepth
+ \wd\b_scrn_comment_link\currentcommentwidth
+ \ht\b_scrn_comment_link\currentcommentheight
+ \dp\b_scrn_comment_link\currentcommentdepth
\scrn_comment_place}
-\setvalue{scrn_comment_method_\v!hidden}%
+\setvalue{\??commentmethods\v!hidden}%
{}
% todo: dedicated margin classes
\def\scrn_comment_place
{\executeifdefined
- {\??cc:\c!location:\commentparameter\c!location}\hbox
- {\hbox{\box\scrn_comment_box_link}}}
+ {\??commentlocation\commentparameter\c!location}\hbox
+ {\hbox{\box\b_scrn_comment_link}}}
-\setvalue{\??cc:\c!location:\v!inmargin }{\inmargin }
-\setvalue{\??cc:\c!location:\v!leftedge }{\inleftedge }
-\setvalue{\??cc:\c!location:\v!rightedge }{\inrightedge }
-\setvalue{\??cc:\c!location:\v!leftmargin }{\inleftmargin }
-\setvalue{\??cc:\c!location:\v!rightmargin}{\inrightmargin}
-\setvalue{\??cc:\c!location:\v!high }{\high}
-\setvalue{\??cc:\c!location:\v!none }{\scrn_comment_collect}
+\setvalue{\??commentlocation\v!inmargin }{\inmargin }
+\setvalue{\??commentlocation\v!leftedge }{\inleftedge }
+\setvalue{\??commentlocation\v!rightedge }{\inrightedge }
+\setvalue{\??commentlocation\v!leftmargin }{\inleftmargin }
+\setvalue{\??commentlocation\v!rightmargin}{\inrightmargin}
+\setvalue{\??commentlocation\v!high }{\high}
+\setvalue{\??commentlocation\v!none }{\scrn_comment_collect}
\def\scrn_comment_collect#content%
- {\global\setbox\scrn_comment_box_collect\hbox\bgroup
- \ifvoid\scrn_comment_box_collect\else
- \box\scrn_comment_box_collect
+ {\global\setbox\b_scrn_comment_collect\hbox\bgroup
+ \ifvoid\b_scrn_comment_collect\else
+ \box\b_scrn_comment_collect
\hskip\commentparameter\c!distance
\fi
#content%
\egroup}
\unexpanded\def\placecomments
- {\ifvoid\scrn_comment_box_collect\else
- \box\scrn_comment_box_collect
+ {\ifvoid\b_scrn_comment_collect\else
+ \box\b_scrn_comment_collect
\fi}
\definecomment[comment]
@@ -585,8 +594,8 @@
\def\renderingtype #tag{\ctxlua{interactions.renderings.var("#tag","type")}}
\def\renderingoption#tag{\ctxlua{interactions.renderings.var("#tag","option")}}
-\def\renderingwidth {8cm} % will become private
-\def\renderingheight {6cm} % will become private
+\def\renderingwidth {8cm} % will become private
+\def\renderingheight{6cm} % will become private
\unexpanded\def\definerenderingwindow
{\dodoubleempty\scrn_rendering_define_window}
@@ -624,7 +633,7 @@
\def\currentrenderingwindow{#window}%
\else
\let\currentrenderingwindow\s!default
- \scrn_rendering_define_window[\currentrenderingwindow]%
+ \definerenderingwindow[\currentrenderingwindow]%
\fi
% todo
% \handlereferenceactions{\getvalue{\??rw\currentrenderingwindow\c!openpageaction }}\dosetuprenderingopenpageaction
diff --git a/Master/texmf-dist/tex/context/base/scrp-cjk.lua b/Master/texmf-dist/tex/context/base/scrp-cjk.lua
index d817c28cf86..3463a8eb51a 100644
--- a/Master/texmf-dist/tex/context/base/scrp-cjk.lua
+++ b/Master/texmf-dist/tex/context/base/scrp-cjk.lua
@@ -6,6 +6,8 @@ if not modules then modules = { } end modules ['scrp-cjk'] = {
license = "see context related readme files"
}
+local utfchar = utf.char
+
local has_attribute = node.has_attribute
local insert_node_after = node.insert_after
local insert_node_before = node.insert_before
@@ -13,6 +15,7 @@ local remove_node = nodes.remove
local nodepool = nodes.pool
local new_glue = nodepool.glue
+local new_kern = nodepool.kern
local new_penalty = nodepool.penalty
local nodecodes = nodes.nodecodes
@@ -30,59 +33,123 @@ local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
local quaddata = fonthashes.quads
+local trace_details = false trackers.register("scripts.details", function(v) trace_details = v end)
+
+local report_details = logs.reporter("scripts","detail")
+
-- raggedleft is controlled by leftskip and we might end up with a situation where
-- the intercharacter spacing interferes with this; the solution is to patch the
-- nodelist but better is to use veryraggedleft
-local inter_char_stretch = 0
-local inter_char_half_shrink = 0
-local inter_char_hangul_penalty = 0
+local inter_char_shrink = 0
+local inter_char_stretch = 0
+local inter_char_half_shrink = 0
+local inter_char_half_stretch = 0
+local inter_char_quarter_shrink = 0
+local inter_char_quarter_stretch = 0
+
+local full_char_width = 0
+local half_char_width = 0
+local quarter_char_width = 0
+
+local inter_char_hangul_penalty = 0
local function set_parameters(font,data)
-- beware: parameters can be nil in e.g. punk variants
local quad = quaddata[font]
- inter_char_half_shrink = data.inter_char_half_shrink_factor * quad
- inter_char_stretch = data.inter_char_stretch_factor * quad
- inter_char_hangul_penalty = data.inter_char_hangul_penalty
+ full_char_width = quad
+ half_char_width = quad/2
+ quarter_char_width = quad/4
+ inter_char_shrink = data.inter_char_shrink_factor * quad
+ inter_char_stretch = data.inter_char_stretch_factor * quad
+ inter_char_half_shrink = data.inter_char_half_shrink_factor * quad
+ inter_char_half_stretch = data.inter_char_half_stretch_factor * quad
+ inter_char_quarter_shrink = data.inter_char_quarter_shrink_factor * quad
+ inter_char_quarter_stretch = data.inter_char_quarter_stretch_factor * quad
+ inter_char_hangul_penalty = data.inter_char_hangul_penalty
end
-- a test version did compensate for crappy halfwidth but we can best do that
-- at font definition time and/or just assume a correct font
+local function trace_detail(current,what)
+ local prev = current.prev
+ local c_id = current.id
+ local p_id = prev and prev.id
+ if c_id == glyph_code then
+ local c_ch = current.char
+ if p_id == glyph_code then
+ local p_ch = p_id and prev.char
+ report_details("[U+%05X %s %s] [%s] [U+%05X %s %s]",p_ch,utfchar(p_ch),hash[p_ch] or "unknown",what,c_ch,utfchar(c_ch),hash[c_ch] or "unknown")
+ else
+ report_details("[%s] [U+%05X %s %s]",what,c_ch,utfchar(c_ch),hash[c_ch] or "unknown")
+ end
+ else
+ if p_id == glyph_code then
+ local p_ch = p_id and prev.char
+ report_details("[U+%05X %s %s] [%s]",p_ch,utfchar(p_ch),hash[p_ch] or "unknown",what)
+ else
+ report_details("[%s]",what)
+ end
+ end
+end
+
local function nobreak(head,current)
+ if trace_details then
+ trace_detail(current,"break")
+ end
insert_node_before(head,current,new_penalty(10000))
end
local function stretch_break(head,current)
+ if trace_details then
+ trace_detail(current,"stretch break")
+ end
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
end
local function shrink_break(head,current)
+ if trace_details then
+ trace_detail(current,"shrink break")
+ end
insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
end
local function nobreak_stretch(head,current)
+ if trace_details then
+ trace_detail(current,"no break stretch")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
end
local function korean_break(head,current)
+ if trace_details then
+ trace_detail(current,"korean break")
+ end
insert_node_before(head,current,new_penalty(inter_char_hangul_penalty))
end
local function nobreak_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
end
local function nobreak_autoshrink(head,current)
- if true then
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink")
end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
end
local function nobreak_stretch_nobreak_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak stretch nobreak shrink")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
insert_node_before(head,current,new_penalty(10000))
@@ -90,15 +157,19 @@ local function nobreak_stretch_nobreak_shrink(head,current)
end
local function nobreak_stretch_nobreak_autoshrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak stretch nobreak autoshrink")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
- if true then
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
- end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
end
local function nobreak_shrink_nobreak_stretch(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink nobreak stretch")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
insert_node_before(head,current,new_penalty(10000))
@@ -106,29 +177,37 @@ local function nobreak_shrink_nobreak_stretch(head,current)
end
local function nobreak_autoshrink_nobreak_stretch(head,current)
- if true then
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink nobreak stretch")
end
insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
end
local function nobreak_shrink_break_stretch(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink break stretch")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
end
local function nobreak_autoshrink_break_stretch(head,current)
- if true then
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink break stretch")
end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
end
local function nobreak_shrink_break_stretch_nobreak_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink break stretch nobreak shrink")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
@@ -136,187 +215,191 @@ local function nobreak_shrink_break_stretch_nobreak_shrink(head,current)
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
end
+local function japanese_between_full_close_open(head,current) -- todo: check width
+ if trace_details then
+ trace_detail(current,"japanese between full close open")
+ end
+ insert_node_before(head,current,new_kern(-half_char_width))
+ insert_node_before(head,current,new_glue(half_char_width,0,inter_char_half_shrink))
+ insert_node_before(head,current,new_kern(-half_char_width))
+end
+
+local function japanese_between_full_close_full_close(head,current) -- todo: check width
+ if trace_details then
+ trace_detail(current,"japanese between full close full close")
+ end
+ insert_node_before(head,current,new_kern(-half_char_width))
+ -- insert_node_before(head,current,new_glue(half_char_width,0,inter_char_half_shrink))
+end
+
+local function japanese_before_full_width_punct(head,current) -- todo: check width
+ if trace_details then
+ trace_detail(current,"japanese before full width punct")
+ end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(quarter_char_width,0,inter_char_quarter_shrink))
+ insert_node_before(head,current,new_kern(-quarter_char_width))
+end
+
+local function japanese_after_full_width_punct(head,current) -- todo: check width
+ if trace_details then
+ trace_detail(current,"japanese after full width punct")
+ end
+ insert_node_before(head,current,new_kern(-quarter_char_width))
+ insert_node_before(head,current,new_glue(quarter_char_width,0,inter_char_quarter_shrink))
+end
+
local function nobreak_autoshrink_break_stretch_nobreak_autoshrink(head,current)
- if true then
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink break stretch nobreak autoshrink")
end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
- if true then
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
- end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
end
local function nobreak_autoshrink_break_stretch_nobreak_shrink(head,current)
- if true then
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
+ if trace_details then
+ trace_detail(current,"nobreak autoshrink break stretch nobreak shrink")
end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
end
local function nobreak_shrink_break_stretch_nobreak_autoshrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak shrink break stretch nobreak autoshrink")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
- if true then
- insert_node_before(head,current,new_penalty(10000))
- insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
- end
+ insert_node_before(head,current,new_penalty(10000))
+ insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
end
local function nobreak_stretch_break_shrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak stretch break shrink")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
end
local function nobreak_stretch_break_autoshrink(head,current)
+ if trace_details then
+ trace_detail(current,"nobreak stretch break autoshrink")
+ end
insert_node_before(head,current,new_penalty(10000))
insert_node_before(head,current,new_glue(0,inter_char_stretch,0))
- if true then
- insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
- end
+ insert_node_before(head,current,new_glue(0,0,inter_char_half_shrink))
end
--- hangul (korean)
+-- Korean: hangul
+
+local korean_0 = {
+}
+
+local korean_1 = {
+ jamo_initial = korean_break,
+ korean = korean_break,
+ chinese = korean_break,
+ hiragana = korean_break,
+ katakana = korean_break,
+ half_width_open = stretch_break,
+ half_width_close = nobreak,
+ full_width_open = stretch_break,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = korean_break,
+ other = korean_break,
+}
+
+local korean_2 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = stretch_break,
+ half_width_close = nobreak,
+ full_width_open = stretch_break,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = stretch_break,
+ other = stretch_break,
+}
+
+local korean_3 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = stretch_break,
+ half_width_close = nobreak,
+ full_width_open = stretch_break,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = nobreak,
+ other = nobreak,
+}
+
+local korean_4 = {
+ jamo_initial = nobreak,
+ korean = nobreak,
+ chinese = nobreak,
+ hiragana = nobreak,
+ katakana = nobreak,
+ half_width_open = nobreak,
+ half_width_close = nobreak,
+ full_width_open = nobreak,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+ hyphen = nobreak,
+ non_starter = nobreak,
+ other = nobreak,
+}
+
+local korean_5 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = stretch_break,
+ half_width_close = nobreak_stretch,
+ full_width_open = stretch_break,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
local injectors = { -- [previous] [current]
- jamo_final = {
- jamo_initial = korean_break,
- korean = korean_break,
- chinese = korean_break,
- half_width_open = stretch_break,
- half_width_close = nobreak,
- full_width_open = stretch_break,
- full_width_close = nobreak,
- -- hyphen = nil,
- non_starter = korean_break,
- other = korean_break,
- },
- korean = {
- jamo_initial = korean_break,
- korean = korean_break,
- chinese = korean_break,
- half_width_open = stretch_break,
- half_width_close = nobreak,
- full_width_open = stretch_break,
- full_width_close = nobreak,
- -- hyphen = nil,
- non_starter = korean_break,
- other = korean_break,
- },
- chinese = {
- jamo_initial = korean_break,
- korean = korean_break,
- chinese = korean_break,
- half_width_open = stretch_break,
- half_width_close = nobreak,
- full_width_open = stretch_break,
- full_width_close = nobreak,
- -- hyphen = nil,
- non_starter = korean_break,
- other = korean_break,
- },
- hyphen = {
- jamo_initial = stretch_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = stretch_break,
- half_width_close = nobreak,
- full_width_open = stretch_break,
- full_width_close = nobreak,
- -- hyphen = nil,
- non_starter = stretch_break,
- other = stretch_break,
- },
- start = {
- -- jamo_initial = nil,
- -- korean = nil,
- -- chinese = nil,
- -- half_width_open = nil,
- -- half_width_close = nil,
- -- full_width_open = nil,
- -- full_width_close = nil,
- -- hyphen = nil,
- -- non_starter = nil,
- -- other = nil,
- },
- other = {
- jamo_initial = stretch_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = stretch_break,
- half_width_close = nobreak,
- full_width_open = stretch_break,
- full_width_close = nobreak,
- -- hyphen = nil,
- non_starter = stretch_break,
- other = stretch_break,
- },
- non_starter = {
- jamo_initial = stretch_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = stretch_break,
- half_width_close = nobreak,
- full_width_open = stretch_break,
- full_width_close = nobreak,
- -- hyphen = nil,
- non_starter = nobreak,
- other = nobreak,
- },
- full_width_open = {
- jamo_initial = nobreak,
- korean = nobreak,
- chinese = nobreak,
- half_width_open = nobreak,
- half_width_close = nobreak,
- full_width_open = nobreak,
- full_width_close = nobreak,
- hyphen = nobreak,
- non_starter = nobreak,
- other = nobreak,
- },
- half_width_open = {
- jamo_initial = nobreak,
- korean = nobreak,
- chinese = nobreak,
- half_width_open = nobreak,
- half_width_close = nobreak,
- full_width_open = nobreak,
- full_width_close = nobreak,
- hyphen = nobreak,
- non_starter = nobreak,
- other = nobreak,
- },
- full_width_close = {
- jamo_initial = stretch_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = stretch_break,
- half_width_close = nobreak_stretch,
- full_width_open = stretch_break,
- full_width_close = nobreak_stretch,
- hyphen = nobreak_stretch,
- non_starter = nobreak_stretch,
- other = stretch_break,
- },
- half_width_close = {
- jamo_initial = stretch_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = stretch_break,
- half_width_close = nobreak_stretch,
- full_width_open = stretch_break,
- full_width_close = nobreak_stretch,
- hyphen = nobreak_stretch,
- non_starter = nobreak_stretch,
- other = stretch_break,
- },
+ jamo_final = korean_1,
+ korean = korean_1,
+ chinese = korean_1,
+ hiragana = korean_1,
+ katakana = korean_1,
+ hyphen = korean_2,
+ start = korean_0,
+ other = korean_2,
+ non_starter = korean_3,
+ full_width_open = korean_4,
+ half_width_open = korean_4,
+ full_width_close = korean_5,
+ full_width_punct = korean_5,
+ half_width_close = korean_5,
}
local function process(head,first,last)
@@ -377,150 +460,167 @@ end
scripts.installmethod {
name = "hangul",
process = process,
- datasets = {
+ datasets = { -- todo: metatables
default = {
- inter_char_stretch_factor = 0.50, -- of quad
- inter_char_half_shrink_factor = 0.50, -- of quad
- inter_char_hangul_penalty = 50,
+ inter_char_shrink_factor = 0.50, -- of quad
+ inter_char_stretch_factor = 0.50, -- of quad
+ inter_char_half_shrink_factor = 0.50, -- of quad
+ inter_char_half_stretch_factor = 0.50, -- of quad
+ inter_char_quarter_shrink_factor = 0.50, -- of quad
+ inter_char_quarter_stretch_factor = 0.50, -- of quad
+ inter_char_hangul_penalty = 50,
},
},
}
--- hanzi (chinese)
+-- Chinese: hanzi
+
+local chinese_0 = {
+}
+
+local chinese_1 = {
+ jamo_initial = korean_break,
+ korean = korean_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local chinese_2 = {
+ jamo_initial = korean_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local chinese_3 = {
+ jamo_initial = korean_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local chinese_4 = {
+-- jamo_initial = nil,
+-- korean = nil,
+-- chinese = nil,
+-- hiragana = nil,
+-- katakana = nil,
+ half_width_open = nobreak_autoshrink,
+ half_width_close = nil,
+ full_width_open = nobreak_shrink,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = nobreak,
+-- other = nil,
+}
+
+local chinese_5 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local chinese_6 = {
+ jamo_initial = nobreak_stretch,
+ korean = nobreak_stretch,
+ chinese = nobreak_stretch,
+ hiragana = nobreak_stretch,
+ katakana = nobreak_stretch,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = nobreak_stretch,
+}
+
+local chinese_7 = {
+ jami_initial = nobreak_shrink_break_stretch,
+ korean = nobreak_shrink_break_stretch,
+ chinese = stretch_break, -- nobreak_shrink_break_stretch,
+ hiragana = stretch_break, -- nobreak_shrink_break_stretch,
+ katakana = stretch_break, -- nobreak_shrink_break_stretch,
+ half_width_open = nobreak_shrink_break_stretch_nobreak_autoshrink,
+ half_width_close = nobreak_shrink_nobreak_stretch,
+ full_width_open = nobreak_shrink_break_stretch_nobreak_shrink,
+ full_width_close = nobreak_shrink_nobreak_stretch,
+ full_width_punct = nobreak_shrink_nobreak_stretch,
+ hyphen = nobreak_shrink_break_stretch,
+ non_starter = nobreak_shrink_break_stretch,
+ other = nobreak_shrink_break_stretch,
+}
+
+local chinese_8 = {
+ jami_initial = nobreak_shrink_break_stretch,
+ korean = nobreak_autoshrink_break_stretch,
+ chinese = stretch_break, -- nobreak_autoshrink_break_stretch,
+ hiragana = stretch_break, -- nobreak_autoshrink_break_stretch,
+ katakana = stretch_break, -- nobreak_autoshrink_break_stretch,
+ half_width_open = nobreak_autoshrink_break_stretch_nobreak_autoshrink,
+ half_width_close = nobreak_autoshrink_nobreak_stretch,
+ full_width_open = nobreak_autoshrink_break_stretch_nobreak_shrink,
+ full_width_close = nobreak_autoshrink_nobreak_stretch,
+ full_width_punct = nobreak_autoshrink_nobreak_stretch,
+ hyphen = nobreak_autoshrink_break_stretch,
+ non_starter = nobreak_autoshrink_break_stretch,
+ other = nobreak_autoshrink_break_stretch,
+}
local injectors = { -- [previous] [current]
- jamo_final = {
- jamo_initial = korean_break,
- korean = korean_break,
- chinese = stretch_break,
- half_width_open = nobreak_stretch_break_autoshrink,
- half_width_close = nobreak_stretch,
- full_width_open = nobreak_stretch_break_shrink,
- full_width_close = nobreak_stretch,
- -- hyphen = nil,
- non_starter = nobreak_stretch,
- other = stretch_break,
- },
- korean = {
- jamo_initial = korean_break,
- korean = korean_break,
- chinese = stretch_break,
- half_width_open = nobreak_stretch_break_autoshrink,
- half_width_close = nobreak_stretch,
- full_width_open = nobreak_stretch_break_shrink,
- full_width_close = nobreak_stretch,
- -- hyphen = nil,
- non_starter = nobreak_stretch,
- other = stretch_break,
- },
- chinese = {
- jamo_initial = korean_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = nobreak_stretch_break_autoshrink,
- half_width_close = nobreak_stretch,
- full_width_open = nobreak_stretch_break_shrink,
- full_width_close = nobreak_stretch,
- hyphen = nobreak_stretch,
- non_starter = nobreak_stretch,
- other = stretch_break,
- },
- hyphen = {
- jamo_initial = korean_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = nobreak_stretch_break_autoshrink,
- half_width_close = nobreak_stretch,
- full_width_open = nobreak_stretch_break_shrink,
- full_width_close = nobreak_stretch,
- -- hyphen = nil,
- non_starter = nobreak_stretch,
- other = stretch_break,
- },
- start = {
- -- jamo_initial = nil,
- -- korean = nil,
- -- chinese = nil,
- half_width_open = nobreak_autoshrink,
- half_width_close = nil,
- full_width_open = nobreak_shrink,
- full_width_close = nobreak,
- -- hyphen = nil,
- non_starter = nobreak,
- -- other = nil,
- },
- other = {
- jamo_initial = stretch_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = nobreak_stretch_break_autoshrink,
- half_width_close = nobreak_stretch,
- full_width_open = nobreak_stretch_break_shrink,
- full_width_close = nobreak_stretch,
- -- hyphen = nil,
- non_starter = nobreak_stretch,
- other = stretch_break,
- },
- non_starter = {
- jamo_initial = stretch_break,
- korean = stretch_break,
- chinese = stretch_break,
- half_width_open = nobreak_stretch_break_autoshrink,
- half_width_close = nobreak_stretch,
- full_width_open = nobreak_stretch_break_shrink,
- full_width_close = nobreak_stretch,
- -- hyphen = nil,
- non_starter = nobreak_stretch,
- other = stretch_break,
- },
- full_width_open = {
- jamo_initial = nobreak_stretch,
- korean = nobreak_stretch,
- chinese = nobreak_stretch,
- half_width_open = nobreak_stretch_break_autoshrink,
- half_width_close = nobreak_stretch,
- full_width_open = nobreak_stretch_break_shrink,
- full_width_close = nobreak_stretch,
- hyphen = nobreak_stretch,
- non_starter = nobreak_stretch,
- other = nobreak_stretch,
- },
- half_width_open = {
- jamo_initial = nobreak_stretch,
- korean = nobreak_stretch,
- chinese = nobreak_stretch,
- half_width_open = nobreak_stretch_break_autoshrink,
- half_width_close = nobreak_stretch,
- full_width_open = nobreak_stretch_nobreak_shrink,
- full_width_close = nobreak_stretch,
- hyphen = nobreak_stretch,
- non_starter = nobreak_stretch,
- other = nobreak_stretch,
- },
- full_width_close = {
- jami_initial = nobreak_shrink_break_stretch,
- korean = nobreak_shrink_break_stretch,
- chinese = stretch_break, -- nobreak_shrink_break_stretch,
- half_width_open = nobreak_shrink_break_stretch_nobreak_autoshrink,
- half_width_close = nobreak_shrink_nobreak_stretch,
- full_width_open = nobreak_shrink_break_stretch_nobreak_shrink,
- full_width_close = nobreak_shrink_nobreak_stretch,
- hyphen = nobreak_shrink_break_stretch,
- non_starter = nobreak_shrink_break_stretch,
- other = nobreak_shrink_break_stretch,
- },
- half_width_close = {
- jami_initial = nobreak_shrink_break_stretch,
- korean = nobreak_autoshrink_break_stretch,
- chinese = stretch_break, -- nobreak_autoshrink_break_stretch,
- half_width_open = nobreak_autoshrink_break_stretch_nobreak_autoshrink,
- half_width_close = nobreak_autoshrink_nobreak_stretch,
- full_width_open = nobreak_autoshrink_break_stretch_nobreak_shrink,
- full_width_close = nobreak_autoshrink_nobreak_stretch,
- hyphen = nobreak_autoshrink_break_stretch,
- non_starter = nobreak_autoshrink_break_stretch,
- other = nobreak_autoshrink_break_stretch,
- },
+ jamo_final = chinese_1,
+ korean = chinese_1,
+ chinese = chinese_2,
+ hiragana = chinese_2,
+ katakana = chinese_2,
+ hyphen = chinese_3,
+ start = chinese_4,
+ other = chinese_5,
+ non_starter = chinese_5,
+ full_width_open = chinese_6,
+ half_width_open = chinese_6,
+ full_width_close = chinese_7,
+ full_width_punct = chinese_7,
+ half_width_close = chinese_8,
}
local function process(head,first,last)
@@ -551,11 +651,11 @@ local function process(head,first,last)
if pid == glyph_code and nid == glyph_code then
local pa, na = has_attribute(p,a_prestat), has_attribute(n,a_prestat)
local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na]
- if not pcjk or not ncjk
- or pcjk == "korean" or ncjk == "korean"
- or pcjk == "other" or ncjk == "other"
- -- or pcjk == "jamo_final" or ncjk == "jamo_initial" then
- or pcjk == "jamo_final" or ncjk == "jamo_initial" or pcjk == "half_width_close" or ncjk == "half_width_open" then
+ if not pcjk or not ncjk
+ or pcjk == "korean" or ncjk == "korean"
+ or pcjk == "other" or ncjk == "other"
+ or pcjk == "jamo_final" or ncjk == "jamo_initial"
+ or pcjk == "half_width_close" or ncjk == "half_width_open" then -- extra compared to korean
previous = "start"
else -- if head ~= first then
remove_node(head,first,true)
@@ -584,9 +684,236 @@ scripts.installmethod {
process = process,
datasets = {
default = {
- inter_char_stretch_factor = 0.50, -- of quad
- inter_char_half_shrink_factor = 0.50, -- of quad
- inter_char_hangul_penalty = 50,
+ inter_char_shrink_factor = 0.50, -- of quad
+ inter_char_stretch_factor = 0.50, -- of quad
+ inter_char_half_shrink_factor = 0.50, -- of quad
+ inter_char_half_stretch_factor = 0.50, -- of quad
+ inter_char_quarter_shrink_factor = 0.50, -- of quad
+ inter_char_quarter_stretch_factor = 0.50, -- of quad
+ inter_char_hangul_penalty = 50,
+ },
+ },
+}
+
+-- Japanese: idiographic, hiragana, katakana, romanji / jis
+
+local japanese_0 = {
+}
+
+local japanese_1 = {
+ jamo_initial = korean_break,
+ korean = korean_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local japanese_2 = {
+ jamo_initial = korean_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = japanese_before_full_width_punct, -- nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local japanese_3 = {
+ jamo_initial = korean_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local japanese_4 = {
+-- jamo_initial = nil,
+-- korean = nil,
+-- chinese = nil,
+-- hiragana = nil,
+-- katakana = nil,
+ half_width_open = nobreak_autoshrink,
+ half_width_close = nil,
+ full_width_open = nobreak_shrink,
+ full_width_close = nobreak,
+ full_width_punct = nobreak,
+-- hyphen = nil,
+ non_starter = nobreak,
+-- other = nil,
+}
+
+local japanese_5 = {
+ jamo_initial = stretch_break,
+ korean = stretch_break,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+-- hyphen = nil,
+ non_starter = nobreak_stretch,
+ other = stretch_break,
+}
+
+local japanese_6 = {
+ jamo_initial = nobreak_stretch,
+ korean = nobreak_stretch,
+ chinese = nobreak_stretch,
+ hiragana = nobreak_stretch,
+ katakana = nobreak_stretch,
+ half_width_open = nobreak_stretch_break_autoshrink,
+ half_width_close = nobreak_stretch,
+ full_width_open = nobreak_stretch_break_shrink,
+ full_width_close = nobreak_stretch,
+ full_width_punct = nobreak_stretch,
+ hyphen = nobreak_stretch,
+ non_starter = nobreak_stretch,
+ other = nobreak_stretch,
+}
+
+local japanese_7 = {
+ jami_initial = nobreak_shrink_break_stretch,
+ korean = nobreak_shrink_break_stretch,
+ chinese = japanese_after_full_width_punct, -- stretch_break
+ hiragana = japanese_after_full_width_punct, -- stretch_break
+ katakana = japanese_after_full_width_punct, -- stretch_break
+ half_width_open = nobreak_shrink_break_stretch_nobreak_autoshrink,
+ half_width_close = nobreak_shrink_nobreak_stretch,
+ full_width_open = japanese_between_full_close_open, -- !!
+ full_width_close = japanese_between_full_close_full_close, -- nobreak_shrink_nobreak_stretch,
+ full_width_punct = nobreak_shrink_nobreak_stretch,
+ hyphen = nobreak_shrink_break_stretch,
+ non_starter = nobreak_shrink_break_stretch,
+ other = nobreak_shrink_break_stretch,
+}
+
+local japanese_8 = {
+ jami_initial = nobreak_shrink_break_stretch,
+ korean = nobreak_autoshrink_break_stretch,
+ chinese = stretch_break,
+ hiragana = stretch_break,
+ katakana = stretch_break,
+ half_width_open = nobreak_autoshrink_break_stretch_nobreak_autoshrink,
+ half_width_close = nobreak_autoshrink_nobreak_stretch,
+ full_width_open = nobreak_autoshrink_break_stretch_nobreak_shrink,
+ full_width_close = nobreak_autoshrink_nobreak_stretch,
+ full_width_punct = nobreak_autoshrink_nobreak_stretch,
+ hyphen = nobreak_autoshrink_break_stretch,
+ non_starter = nobreak_autoshrink_break_stretch,
+ other = nobreak_autoshrink_break_stretch,
+}
+
+local injectors = { -- [previous] [current]
+ jamo_final = japanese_1,
+ korean = japanese_1,
+ chinese = japanese_2,
+ hiragana = japanese_2,
+ katakana = japanese_2,
+ hyphen = japanese_3,
+ start = japanese_4,
+ other = japanese_5,
+ non_starter = japanese_5,
+ full_width_open = japanese_6,
+ half_width_open = japanese_6,
+ full_width_close = japanese_7,
+ full_width_punct = japanese_7,
+ half_width_close = japanese_8,
+}
+
+local function process(head,first,last)
+ if first ~= last then
+ local lastfont, previous, last = nil, "start", nil
+ while true do
+ local upcoming, id = first.next, first.id
+ if id == glyph_code then
+ local a = has_attribute(first,a_prestat)
+ local current = numbertocategory[a]
+ local action = injectors[previous]
+ if action then
+ action = action[current]
+ if action then
+ local font = first.font
+ if font ~= lastfont then
+ lastfont = font
+ set_parameters(font,numbertodataset[has_attribute(first,a_preproc)])
+ end
+ action(head,first)
+ end
+ end
+ previous = current
+ else -- glue
+ local p, n = first.prev, upcoming
+ if p and n then
+ local pid, nid = p.id, n.id
+ if pid == glyph_code and nid == glyph_code then
+ local pa, na = has_attribute(p,a_prestat), has_attribute(n,a_prestat)
+ local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na]
+ if not pcjk or not ncjk
+ or pcjk == "korean" or ncjk == "korean"
+ or pcjk == "other" or ncjk == "other"
+ or pcjk == "jamo_final" or ncjk == "jamo_initial"
+ or pcjk == "half_width_close" or ncjk == "half_width_open" then -- extra compared to korean
+ previous = "start"
+ else -- if head ~= first then
+ remove_node(head,first,true)
+ previous = pcjk
+ -- else
+ -- previous = pcjk
+ end
+ else
+ previous = "start"
+ end
+ else
+ previous = "start"
+ end
+ end
+ if upcoming == last then -- was stop
+ break
+ else
+ first = upcoming
+ end
+ end
+ end
+end
+
+scripts.installmethod {
+ name = "nihongo", -- what name to use?
+ process = process,
+ datasets = {
+ default = {
+ inter_char_shrink_factor = 0.50, -- of quad
+ inter_char_stretch_factor = 0.50, -- of quad
+ inter_char_half_shrink_factor = 0.50, -- of quad
+ inter_char_half_stretch_factor = 0.50, -- of quad
+ inter_char_quarter_shrink_factor = 0.25, -- of quad
+ inter_char_quarter_stretch_factor = 0.25, -- of quad
+ inter_char_hangul_penalty = 50,
},
},
}
+
diff --git a/Master/texmf-dist/tex/context/base/scrp-ini.lua b/Master/texmf-dist/tex/context/base/scrp-ini.lua
index ef036cdf686..e55dc0780ea 100644
--- a/Master/texmf-dist/tex/context/base/scrp-ini.lua
+++ b/Master/texmf-dist/tex/context/base/scrp-ini.lua
@@ -6,12 +6,11 @@ if not modules then modules = { } end modules ['scrp-ini'] = {
license = "see context related readme files"
}
--- we need to rewrite this a bit ... rather old code
+-- We need to rewrite this a bit ... rather old code ... will be done when japanese
+-- is finished.
local attributes, nodes, node = attributes, nodes, node
-local texwrite = tex.write
-
local trace_analyzing = false trackers.register("scripts.analyzing", function(v) trace_analyzing = v end)
local trace_injections = false trackers.register("scripts.injections", function(v) trace_injections = v end)
@@ -50,7 +49,7 @@ scripts.handlers = handlers
storage.register("scripts/hash", hash, "scripts.hash")
-if not next(hash) then
+if not next(hash) then -- this might move to char-def
hash = { -- no local
--
@@ -76,7 +75,6 @@ if not next(hash) then
[0xFF08] = "full_width_open", -- ( left parenthesis
[0xFF3B] = "full_width_open", -- ï¼» left square brackets
[0xFF5B] = "full_width_open", -- ï½› left curve bracket
- [0xFF62] = "full_width_open", -- left corner bracket
--
-- half width closing parenthesis
[0x0029] = "half_width_close",
@@ -101,7 +99,9 @@ if not next(hash) then
[0xFF09] = "full_width_close", -- ) right parenthesis
[0xFF3D] = "full_width_close", -- ï¼½ right square brackets
[0xFF5D] = "full_width_close", -- ï½ right curve brackets
- [0xFF63] = "full_width_close", -- right corner bracket
+
+ [0xFF62] = "half_width_open", -- left corner bracket
+ [0xFF63] = "half_width_close", -- right corner bracket
--
-- vertical opening vertical
--
@@ -133,13 +133,14 @@ if not next(hash) then
-- full width closing punctuation
[0x3001] = "full_width_close", -- ã€
[0x3002] = "full_width_close", -- 。
- [0xFF01] = "full_width_close", -- ï¼
[0xFF0C] = "full_width_close", -- ,
[0xFF0E] = "full_width_close", -- .
- [0xFF1A] = "full_width_close", -- :
- [0xFF1B] = "full_width_close", -- ï¼›
+ -- depends on font
+ [0xFF01] = "full_width_close", -- ï¼
[0xFF1F] = "full_width_close", -- ?
--
+ [0xFF1A] = "full_width_punct", -- :
+ [0xFF1B] = "full_width_punct", -- ï¼›
-- non starter
--
[0x3005] = "non_starter", [0x3041] = "non_starter", [0x3043] = "non_starter", [0x3045] = "non_starter", [0x3047] = "non_starter",
@@ -159,13 +160,13 @@ if not next(hash) then
[0x2014] = "hyphen", -- — hyphen
}
- for i=0x03040,0x0309F do if not hash[i] then hash[i] = "chinese" end end
- for i=0x030A0,0x030FF do if not hash[i] then hash[i] = "chinese" end end
- for i=0x031F0,0x031FF do if not hash[i] then hash[i] = "chinese" end end
+ for i=0x03040,0x030FF do if not hash[i] then hash[i] = "katakana" end end -- had tag 'chinese'
+ for i=0x031F0,0x031FF do if not hash[i] then hash[i] = "katakana" end end -- had tag 'chinese'
+ for i=0x032D0,0x032FE do if not hash[i] then hash[i] = "katakana" end end -- had tag 'chinese'
for i=0x03400,0x04DFF do if not hash[i] then hash[i] = "chinese" end end
for i=0x04E00,0x09FFF do if not hash[i] then hash[i] = "chinese" end end
for i=0x0F900,0x0FAFF do if not hash[i] then hash[i] = "chinese" end end
- for i=0x0FF00,0x0FFEF do if not hash[i] then hash[i] = "chinese" end end
+ for i=0x0FF00,0x0FFEF do if not hash[i] then hash[i] = "katakana" end end -- had tag 'chinese'
for i=0x20000,0x2A6DF do if not hash[i] then hash[i] = "chinese" end end
for i=0x2F800,0x2FA1F do if not hash[i] then hash[i] = "chinese" end end
for i=0x0AC00,0x0D7A3 do if not hash[i] then hash[i] = "korean" end end
@@ -189,6 +190,18 @@ local numbertohandler = allocate()
scripts.numbertodataset = numbertodataset
+local defaults = {
+ inter_char_shrink_factor = 0,
+ inter_char_stretch_factor = 0,
+ inter_char_half_shrink_factor = 0,
+ inter_char_half_stretch_factor = 0,
+ inter_char_quarter_shrink_factor = 0,
+ inter_char_quarter_stretch_factor = 0,
+ inter_char_hangul_penalty = 0,
+}
+
+scripts.defaults = defaults -- so we can add more
+
function scripts.installmethod(handler)
local name = handler.name
handlers[name] = handler
@@ -196,6 +209,10 @@ function scripts.installmethod(handler)
local datasets = handler.datasets
if not datasets or not datasets.default then
report_preprocessing("missing (default) dataset in script '%s'",name)
+ datasets.default = { } -- slower but an error anyway
+ end
+ for k, v in next, datasets do
+ table.setmetatableindex(v,defaults)
end
setmetatable(attributes, {
__index = function(t,k)
@@ -267,14 +284,19 @@ function scripts.reset()
end
-- the following tables will become a proper installer (move to cjk/eth)
+--
+-- 0=gray 1=red 2=green 3=blue 4=yellow 5=magenta 6=cyan 7=x-yellow 8=x-magenta 9=x-cyan
local scriptcolors = allocate { -- todo: just named colors
korean = "trace:0",
chinese = "trace:0",
+ katakana = "trace:0",
+ hiragana = "trace:0",
full_width_open = "trace:1",
full_width_close = "trace:2",
half_width_open = "trace:3",
half_width_close = "trace:4",
+ full_width_punct = "trace:5",
hyphen = "trace:5",
non_starter = "trace:6",
jamo_initial = "trace:7",
@@ -290,10 +312,13 @@ scripts.colors = scriptcolors
local numbertocategory = allocate { -- rather bound to cjk ... will be generalized
"korean",
"chinese",
+ "katakana",
+ "hiragana",
"full_width_open",
"full_width_close",
"half_width_open",
"half_width_close",
+ "full_width_punct",
"hyphen",
"non_starter",
"jamo_initial",
@@ -338,7 +363,9 @@ end
-- eventually we might end up with more extensive parsing
-- todo: pass t[start..stop] == original
--
--- one of the time consuming functiions:
+-- one of the time consuming functions:
+
+-- we can have a fonts.hashes.originals
function scripts.preprocess(head)
local start = first_glyph(head)
@@ -374,11 +401,18 @@ function scripts.preprocess(head)
if normal_process then
local f = start.font
if f ~= lastfont then
- originals = fontdata[f].resources.originals
+ originals = fontdata[f].resources
+ if resources then
+ originals = resources.originals
+ else
+ -- can't happen
+ end
lastfont = f
end
local c = start.char
- if originals then c = originals[c] or c end
+ if originals then
+ c = originals[c] or c
+ end
local h = hash[c]
if h then
set_attribute(start,a_prestat,categorytonumber[h])
diff --git a/Master/texmf-dist/tex/context/base/scrp-ini.mkiv b/Master/texmf-dist/tex/context/base/scrp-ini.mkiv
index 0e50452ff3b..8182368d787 100644
--- a/Master/texmf-dist/tex/context/base/scrp-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/scrp-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA / Hans Hagen]
+%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
@@ -26,7 +26,9 @@
\unprotect
-\installcommandhandler\??ls{script}\??ls
+\installcorenamespace{script}
+
+\installcommandhandler \??script {script} \??script
% presets are global and are currently defined in lua
@@ -34,12 +36,12 @@
\setuevalue\currentscript{\setscript[\currentscript]}%
\to \everydefinescript
-\unexpanded\def\dosetscript
+\unexpanded\def\scripts_basics_set
{\ctxlua{scripts.set("\currentscript","\scriptparameter\c!method","\scriptparameter\c!preset")}}
\unexpanded\def\setscript[#1]%
{\edef\currentscript{#1}%
- \dosetscript}
+ \scripts_basics_set}
\unexpanded\def\resetscript
{\ctxlua{scripts.reset()}}
@@ -47,18 +49,19 @@
\unexpanded\def\startscript[#1]%
{\begingroup
\edef\currentscript{#1}%
- \dosetscript}
+ \scripts_basics_set}
\unexpanded\def\stopscript
{\endgroup}
% \setscript[hangul] \hangul \startscript[hangul]
-\definescript[hangul] [\c!method=hangul]
-\definescript[hanzi] [\c!method=hanzi]
+\definescript[hangul] [\c!method=hangul]
+\definescript[hanzi] [\c!method=hanzi]
+\definescript[nihongo] [\c!method=nihongo]
-\definescript[ethiopic] [\c!method=ethiopic]
+\definescript[ethiopic][\c!method=ethiopic]
-\definescript[latin] [\c!method=] % resets the attribute (also currentscript)
+\definescript[latin] [\c!method=] % resets the attribute (also currentscript)
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/sort-def.mkii b/Master/texmf-dist/tex/context/base/sort-def.mkii
index 10dc31b14e4..168f94e9e9a 100644
--- a/Master/texmf-dist/tex/context/base/sort-def.mkii
+++ b/Master/texmf-dist/tex/context/base/sort-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Defaults,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/sort-ini.lua b/Master/texmf-dist/tex/context/base/sort-ini.lua
index 7a91910ca7d..8640ba825d8 100644
--- a/Master/texmf-dist/tex/context/base/sort-ini.lua
+++ b/Master/texmf-dist/tex/context/base/sort-ini.lua
@@ -96,10 +96,11 @@ local validmethods = table.tohash {
}
local predefinedmethods = {
- [v_before] = "mm,mc,uc",
- [v_after] = "pm,mc,uc",
- [v_first] = "pc,mm,uc",
- [v_last] = "mc,mm,uc",
+ [v_default] = "zc,pc,zm,pm,uc",
+ [v_before] = "mm,mc,uc",
+ [v_after] = "pm,mc,uc",
+ [v_first] = "pc,mm,uc",
+ [v_last] = "mc,mm,uc",
}
sorters = {
@@ -113,7 +114,7 @@ sorters = {
digitsoffset = digitsoffset,
digitsmaximum = digitsmaximum,
defaultlanguage = v_default,
- defaultmethod = v_before,
+ defaultmethod = v_default,
defaultdigits = v_numbers,
}
}
@@ -317,7 +318,7 @@ local function setlanguage(l,m,d,u)
method = predefinedmethods[variables[method]] or method
data.method = method
--
- data.digits = digite
+ data.digits = digits
--
local seq = utilities.parsers.settings_to_array(method or "") -- check the list
sequence = { }
diff --git a/Master/texmf-dist/tex/context/base/sort-ini.mkii b/Master/texmf-dist/tex/context/base/sort-ini.mkii
index f1ed1c3162e..8114f82c8eb 100644
--- a/Master/texmf-dist/tex/context/base/sort-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/sort-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/sort-ini.mkiv b/Master/texmf-dist/tex/context/base/sort-ini.mkiv
index a4dc2f6badc..b7b49025561 100644
--- a/Master/texmf-dist/tex/context/base/sort-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/sort-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/sort-lan.lua b/Master/texmf-dist/tex/context/base/sort-lan.lua
index e7556c1de7b..6a0cb8eab07 100644
--- a/Master/texmf-dist/tex/context/base/sort-lan.lua
+++ b/Master/texmf-dist/tex/context/base/sort-lan.lua
@@ -8,7 +8,8 @@ if not modules then modules = { } end modules ['sort-lan'] = {
-- Many vectors were supplied by Wolfgang Schuster and Philipp
-- Gesang. However this is a quite adapted and reformatted variant
--- so it needs some checking.
+-- so it needs some checking. Other users provides tables and
+-- corrections as well.
local utfchar, utfbyte = utf.char, utf.byte
local sorters = sorters
@@ -863,8 +864,7 @@ definitions["et"] = {
local fschars = characters.fschars
local function firstofsplit(first)
- local fs = fschars[first] or first
- -- print(string.format("%04x %04x",utfbyte(first),utfbyte(fs)))
+ local fs = fschars[first] or first -- leadconsonant
return fs, fs -- entry, tag
end
@@ -876,3 +876,34 @@ definitions["kr"] = {
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
}
}
+
+-- Japanese
+
+definitions["jp"] = {
+ replacements = {
+ { "ã", "ã‚" }, { "ãƒ", "ã„" },
+ { "ã…", "ã†" }, { "ã‡", "ãˆ" },
+ { "ã‰", "ãŠ" }, { "ã£", "ã¤" },
+ { "ゃ", "や" }, { "ゅ", "ゆ" },
+ { "ょ", "よ" },
+ },
+ entries = {
+ ["ã‚"] = "ã‚", ["ã„"] = "ã„", ["ã†"] = "ã†", ["ãˆ"] = "ãˆ", ["ãŠ"] = "ãŠ",
+ ["ã‹"] = "ã‹", ["ã"] = "ã", ["ã"] = "ã", ["ã‘"] = "ã‘", ["ã“"] = "ã“",
+ ["ã•"] = "ã•", ["ã—"] = "ã—", ["ã™"] = "ã™", ["ã›"] = "ã›", ["ã"] = "ã",
+ ["ãŸ"] = "ãŸ", ["ã¡"] = "ã¡", ["ã¤"] = "ã¤", ["ã¦"] = "ã¦", ["ã¨"] = "ã¨",
+ ["ãª"] = "ãª", ["ã«"] = "ã«", ["ã¬"] = "ã¬", ["ã­"] = "ã­", ["ã®"] = "ã®",
+ ["ã¯"] = "ã¯", ["ã²"] = "ã²", ["ãµ"] = "ãµ", ["ã¸"] = "ã¸", ["ã»"] = "ã»",
+ ["ã¾"] = "ã¾", ["ã¿"] = "ã¿", ["ã‚€"] = "ã‚€", ["ã‚"] = "ã‚", ["ã‚‚"] = "ã‚‚",
+ ["や"] = "や", ["ゆ"] = "ゆ", ["よ"] = "よ",
+ ["ら"] = "ら", ["ã‚Š"] = "ã‚Š", ["ã‚‹"] = "ã‚‹", ["ã‚Œ"] = "ã‚Œ", ["ã‚"] = "ã‚",
+ ["ã‚"] = "ã‚", ["ã‚"] = "ã‚", ["ã‚‘"] = "ã‚‘", ["ã‚’"] = "ã‚’", ["ã‚“"] = "ã‚“",
+ },
+ orders = {
+ "ã‚", "ã„", "ã†", "ãˆ", "ãŠ", "ã‹", "ã", "ã", "ã‘", "ã“",
+ "ã•", "ã—", "ã™", "ã›", "ã", "ãŸ", "ã¡", "ã¤", "ã¦", "ã¨",
+ "ãª", "ã«", "ã¬", "ã­", "ã®", "ã¯", "ã²", "ãµ", "ã¸", "ã»",
+ "ã¾", "ã¿", "ã‚€", "ã‚", "ã‚‚", "ã‚„", "ゆ", "よ",
+ "ら", "ã‚Š", "ã‚‹", "ã‚Œ", "ã‚", "ã‚", "ã‚", "ã‚‘", "ã‚’", "ã‚“",
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/sort-lan.mkii b/Master/texmf-dist/tex/context/base/sort-lan.mkii
index db52c63fb66..c239623718f 100644
--- a/Master/texmf-dist/tex/context/base/sort-lan.mkii
+++ b/Master/texmf-dist/tex/context/base/sort-lan.mkii
@@ -5,7 +5,7 @@
%D subtitle=Language Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spac-par.lua b/Master/texmf-dist/tex/context/base/spac-adj.lua
index f695e11e92f..4cba2f91eb2 100644
--- a/Master/texmf-dist/tex/context/base/spac-par.lua
+++ b/Master/texmf-dist/tex/context/base/spac-adj.lua
@@ -1,6 +1,6 @@
-if not modules then modules = { } end modules ['spac-par'] = {
+if not modules then modules = { } end modules ['spac-adj'] = {
version = 1.001,
- comment = "companion to spac-par.mkiv",
+ comment = "companion to spac-adj.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
diff --git a/Master/texmf-dist/tex/context/base/spac-adj.mkiv b/Master/texmf-dist/tex/context/base/spac-adj.mkiv
new file mode 100644
index 00000000000..447dd722963
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/spac-adj.mkiv
@@ -0,0 +1,50 @@
+%D \module
+%D [ file=spac-adj, % moved from spac-par.mkiv
+%D version=2009.10.16, % 1997.03.31, was core-spa.tex
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Paragraphs,
+%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 Spacing Macros / Adjustments}
+
+\unprotect
+
+% Very nasty but needed for margin stuff inside colored
+% paragraphs. Obsolete anyway.
+
+\registerctxluafile{spac-adj}{1.001}
+
+\definesystemattribute [graphicvadjust] [public]
+
+\unexpanded\def\enablegraphicvadjust
+ {\ctxlua{nodes.tasks.enableaction("finalizers","nodes.handlers.graphicvadjust")}%
+ \glet\enablegraphicvadjust\relax}
+
+\unexpanded\def\graphicvadjust % currently not enabled ... nasty bidi handling
+ {\enablegraphicvadjust % and no longer needed anyway
+ \dowithnextboxcontentcs\forgetall\spac_vadjust_graphic_finish\vbox}
+
+\def\spac_vadjust_graphic_finish
+ {\vadjust
+ {\vbox attr \graphicvadjustattribute \plusone
+ {\unvbox\nextbox
+ % corrects for one line paragraphs
+ \nointerlineskip
+ \kern-\struttotal
+ \nointerlineskip
+ \verticalstrut}}}
+
+\unexpanded\def\fakedvadjust
+ {\dowithnextboxcs\spac_vadjust_faked_finish\vtop}
+
+\def\spac_vadjust_faked_finish
+ {\setbox\nextbox\hbox{\llap{\lower\strutdepth\box\nextbox}}%
+ \smashedbox\nextbox}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/spac-ali.lua b/Master/texmf-dist/tex/context/base/spac-ali.lua
index 37bff74d1e2..effd26fe482 100644
--- a/Master/texmf-dist/tex/context/base/spac-ali.lua
+++ b/Master/texmf-dist/tex/context/base/spac-ali.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['spac-ali'] = {
}
local div = math.div
+local format = string.format
local tasks = nodes.tasks
local appendaction = tasks.appendaction
@@ -39,6 +40,7 @@ local texcount = tex.count
local isleftpage = layouts.status.isleftpage
+typesetters = typesetters or { }
local alignments = { }
typesetters.alignments = alignments
@@ -125,7 +127,7 @@ commands.setrealign = alignments.set
statistics.register("realigning", function()
if nofrealigned > 0 then
- return string.format("%s processed",nofrealigned)
+ return format("%s processed",nofrealigned)
else
return nil
end
diff --git a/Master/texmf-dist/tex/context/base/spac-ali.mkiv b/Master/texmf-dist/tex/context/base/spac-ali.mkiv
index 0cf22f470cf..57806b6f240 100644
--- a/Master/texmf-dist/tex/context/base/spac-ali.mkiv
+++ b/Master/texmf-dist/tex/context/base/spac-ali.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Alignments,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,29 +15,56 @@
\unprotect
+%D The \type {new} and \type {old} methods are gone as we now have \type
+%D {flush*} variants. Starting at the last day of 2011 both methods are
+%D merged into one and caching has been added, which makes switching
+%D twice as fast.
+
\registerctxluafile{spac-ali}{1.001}
-\definesystemattribute[realign][public]
+\definesystemattribute[realign] [public] % might be combined with the next one
+\definesystemattribute[alignstate][public] % will make a single attributes for several states
+
+\appendtoks
+ \attribute\realignattribute \attributeunsetvalue
+ \attribute\alignstateattribute\attributeunsetvalue
+\to \everyforgetall
\unexpanded\def\resetrealignsignal{\attribute\realignattribute\attributeunsetvalue}
\unexpanded\def\signalinnerrealign{\ctxcommand{setrealign(2)}}
\unexpanded\def\signalouterrealign{\ctxcommand{setrealign(1)}}
-\appendtoks
- \resetrealignsignal
-\to \everyforgetall
+\installcorenamespace{aligncommand}
+\installcorenamespace{alignhorizontal}
+\installcorenamespace{alignvertical}
+
+\installcorenamespace{alignmentnormalcache}
+\installcorenamespace{alignmentraggedcache}
+
+% nasty hack:
+
+\installcorenamespace{alignmentnormalcacheodd}
+\installcorenamespace{alignmentnormalcacheeven}
+
+\installcorenamespace{alignmentraggedcacheodd}
+\installcorenamespace{alignmentraggedcacheeven}
+
+\def\??alignmentnormalcache{\ifodd\realpageno\??alignmentnormalcacheodd\else\??alignmentnormalcacheeven\fi}
+\def\??alignmentraggedcache{\ifodd\realpageno\??alignmentraggedcacheodd\else\??alignmentraggedcacheeven\fi}
+
+\newtoks\everyresetalign % todo
% We will not use bodydir and pagedir so we disable them. That way we get
% normal hyperlink support.
-\let\@@bodydir\normalbodydir
-\let\@@pagedir\normalpagedir
+\let\spac_directions_normal_body_dir\normalbodydir
+\let\spac_directions_normal_page_dir\normalpagedir
-\unexpanded\def\bodydir{\afterassignment\do@@bodydir\@@bodydir} \let\normalbodydir\bodydir
-\unexpanded\def\pagedir{\afterassignment\do@@pagedir\@@pagedir} \let\normalpagedir\pagedir
+\unexpanded\def\bodydir{\afterassignment\spac_directions_bodydir_indeed\spac_directions_normal_body_dir} \let\normalbodydir\bodydir
+\unexpanded\def\pagedir{\afterassignment\spac_directions_pagedir_indeed\spac_directions_normal_page_dir} \let\normalpagedir\pagedir
-\def\do@@bodydir{\@@bodydir TLT\relax}
-\def\do@@pagedir{\@@pagedir TLT\relax}
+\def\spac_directions_bodydir_indeed{\spac_directions_normal_body_dir TLT\relax}
+\def\spac_directions_pagedir_indeed{\spac_directions_normal_page_dir TLT\relax}
% This will become a more advanced layout controller soon:
@@ -47,26 +74,38 @@
\unexpanded\def\lefttoright
{\ifvmode
- \settrue\displaylefttoright
- \settrue\inlinelefttoright
- \textdir TLT\relax
- \pardir TLT\relax
+ \spac_directions_lefttoright_vmode
\else
- \settrue\inlinelefttoright
- \textdir TLT\relax
+ \spac_directions_lefttoright_hmode
\fi}
+\unexpanded\def\spac_directions_lefttoright_vmode
+ {\settrue\displaylefttoright
+ \settrue\inlinelefttoright
+ \textdir TLT\relax
+ \pardir TLT\relax}
+
+\unexpanded\def\spac_directions_lefttoright_hmode
+ {\settrue\inlinelefttoright
+ \textdir TLT\relax}
+
\unexpanded\def\righttoleft
{\ifvmode
- \setfalse\displaylefttoright
- \setfalse\inlinelefttoright
- \textdir TRT\relax
- \pardir TRT\relax
+ \spac_directions_righttoleft_vmode
\else
- \textdir TRT\relax
- \setfalse\inlinelefttoright
+ \spac_directions_righttoleft_hmode
\fi}
+\unexpanded\def\spac_directions_righttoleft_vmode
+ {\setfalse\displaylefttoright
+ \setfalse\inlinelefttoright
+ \textdir TRT\relax
+ \pardir TRT\relax}
+
+\unexpanded\def\spac_directions_righttoleft_hmode
+ {\textdir TRT\relax
+ \setfalse\inlinelefttoright}
+
\def\currentdirectionparameters
{\ifconditional\inlinelefttoright \else
idir="r2l",
@@ -74,268 +113,635 @@
\ifconditional\displaylefttoright \else
ddir="r2l",
\fi}
-
-\def\dodefinehbox[#1][#2]%
- {\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}}
-\unexpanded\def\definehbox
- {\dodoubleargument\dodefinehbox}
+\unexpanded\def\synchronizelayoutdirection
+ {\ifconditional\layoutlefttoright
+ \spac_directions_synchronize_lr
+ \else
+ \spac_directions_synchronize_rl
+ \fi}
-% To be redone:
+\unexpanded\def\synchronizedisplaydirection
+ {\ifconditional\displaylefttoright
+ \spac_directions_synchronize_lr
+ \else
+ \spac_directions_synchronize_rl
+ \fi}
-\def\ibox#1#2#3%
- {\vbox\bgroup
- \forgetall
- \let\\=\endgraf
- \ifdoublesided\signalinnerrealign\fi
- \doifrightpageelse\raggedright\raggedleft
- \let\next}
+\def\spac_directions_synchronize_lr
+ {\settrue\inlinelefttoright
+ \textdir TLT\relax
+ \pardir TLT\relax}
-\def\obox#1#2#3%
- {\vbox\bgroup
- \forgetall
- \let\\=\endgraf
- \ifdoublesided\signalouterrealign\fi
- \doifrightpageelse\raggedleft\raggedright
- \let\next}
+\def\spac_directions_synchronize_rl
+ {\setfalse\inlinelefttoright
+ \textdir TRT\relax
+ \pardir TRT\relax}
-\def\@@ragged@@command{@@ragged@@c}
-\def\@@ragged@@hbox {@@ragged@@h}
-\def\@@ragged@@vbox {@@ragged@@v}
+\unexpanded\def\synchronizeinlinedirection
+ {\textdir T\ifconditional\inlinelefttoright L\else R\fi T\relax}
-\def\dosetraggedvbox#1% can be more keys
- {\let\raggedbox\vbox
- \processcommacommand[#1]\dosetraggedvbox}
+\unexpanded\def\showdirections
+ {\dontleavehmode
+ \begingroup\infofont\textdir TLT[\space
+ layout:\ifconditional \layoutlefttoright l2r\else r2l\fi\space
+ display:\ifconditional\displaylefttoright l2r\else r2l\fi\space
+ inline:\ifconditional \inlinelefttoright l2r\else r2l\fi\space
+ ]\endgroup}
-\def\dosetraggedhbox#1% can be more keys
- {\let\raggedbox\hbox
- \processcommacommand[#1]\dosetraggedhbox}
+% Tolerance and hyphenation
-\def\dosetraggedvbox#1%
- {\ifcsname\@@ragged@@vbox#1\endcsname
- \csname\@@ragged@@vbox#1\endcsname
- \quitcommalist
- \fi}
+\newcount\hyphenminoffset
-\def\dosetraggedhbox#1%
- {\ifcsname\@@ragged@@hbox#1\endcsname
- \csname\@@ragged@@hbox#1\endcsname
- \quitcommalist
- \fi}
+\ifx\sethyphenationvariables\undefined \let\sethyphenationvariables\relax \fi
+
+\unexpanded\def\lesshyphens
+ {\advance\hyphenminoffset\plusone
+ \sethyphenationvariables}
+
+\unexpanded\def\morehyphens
+ {\ifcase\hyphenminoffset \else
+ \advance\hyphenminoffset\minusone
+ \fi
+ \sethyphenationvariables}
-\setvalue{\@@ragged@@vbox\v!left }{\let\raggedbox\lbox}
-\setvalue{\@@ragged@@vbox\v!right }{\let\raggedbox\rbox}
-\setvalue{\@@ragged@@vbox\v!middle }{\let\raggedbox\cbox}
-\setvalue{\@@ragged@@vbox\v!inner }{\let\raggedbox\ibox}
-\setvalue{\@@ragged@@vbox\v!outer }{\let\raggedbox\obox}
-\setvalue{\@@ragged@@vbox\v!flushleft }{\let\raggedbox\rbox}
-\setvalue{\@@ragged@@vbox\v!flushright}{\let\raggedbox\lbox}
-\setvalue{\@@ragged@@vbox\v!center }{\let\raggedbox\cbox}
-\setvalue{\@@ragged@@vbox\v!no }{\def\raggedbox{\vbox\bgroup\raggedright\let\next=}]}
-\setvalue{\@@ragged@@hbox\v!left }{\def\raggedbox{\doalignedline\v!left }}
-\setvalue{\@@ragged@@hbox\v!right }{\def\raggedbox{\doalignedline\v!right }}
-\setvalue{\@@ragged@@hbox\v!middle }{\def\raggedbox{\doalignedline\v!middle}}
-\setvalue{\@@ragged@@hbox\v!inner }{\def\raggedbox{\doalignedline\v!inner }}
-\setvalue{\@@ragged@@hbox\v!outer }{\def\raggedbox{\doalignedline\v!outer }}
-\setvalue{\@@ragged@@hbox\v!flushleft }{\def\raggedbox{\doalignedline\v!right }}
-\setvalue{\@@ragged@@hbox\v!flushright}{\def\raggedbox{\doalignedline\v!left }}
-\setvalue{\@@ragged@@hbox\v!center }{\def\raggedbox{\doalignedline\v!middle}}
+\unexpanded\def\nohyphens % % % % % not clever, we still hyphenate but supress application
+ {\ifx\dohyphens\relax
+ \edef\dohyphens
+ {\hyphenpenalty \the\hyphenpenalty
+ \exhyphenpenalty\the\exhyphenpenalty
+ \relax}%
+ \fi
+ \hyphenpenalty\plustenthousand
+ \exhyphenpenalty\plustenthousand}
-\def\dosetraggedcommand#1%
- {\normalexpanded{\noexpand\dodosetraggedcommand{#1}}}
+\let\dohyphens\relax
-\newtoks\everyraggedcommand
+\newconstant\c_spac_tolerance_default \c_spac_tolerance_default = 1500 % shouldn't that be 200
+\newconstant\c_spac_tolerance_minimum \c_spac_tolerance_minimum = 1500
+\newconstant\c_spac_tolerance_normal \c_spac_tolerance_normal = 3000
+\newconstant\c_spac_tolerance_extreme \c_spac_tolerance_extreme = 4500
-\def\raggedcommand{\the\everyraggedcommand}
+\def\spac_align_set_raggedness_left {\plustwo\bodyfontsize}
+\def\spac_align_set_raggedness_right {\plustwo\bodyfontsize}
+\def\spac_align_set_raggedness_middle{\plussix\bodyfontsize} % overloaded below
-% slow, we can do this in lua ... some day
+% oeps, hsize can be 0pt in which case we get a strange division
+% was: 6\bodyfontsize, fails on: \placefigure{x $x=x$ x}{}
-\let\raggedbox\relax
+\def\spac_align_set_raggedness_middle{\ifdim\hsize=\zeropoint\plussix\bodyfontsize\else.5\hsize\fi}
-\unexpanded\def\dodosetraggedcommand#1% beware: #1=empty is ignored, keep that!
- {\everyraggedcommand{\resetrealignsignal}% \emptytoks maybe only when #1 <> empty
- \let\raggedtopcommand\empty
- \let\raggedbottomcommand\empty
- \let\raggedbox\relax
- \setfalse\raggedonelinerstate
- \doifsomething{#1}%
- {\doifinsetelse\v!broad{#1}\!!doneatrue\!!doneafalse
- \doifinsetelse\v!wide {#1}\!!donebtrue\!!donebfalse
- \!!donectrue
- \rawprocesscommalist[#1]\dododosetraggedcommand}}
-
-\def\dododosetraggedcommand#1%
- {\executeifdefined{\@@ragged@@command\string#1}\relax}
-
-\setvalue{\@@ragged@@command\v!hanging }{\appendtoks\enableprotruding \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!nothanging }{\appendtoks\disableprotruding \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!hz }{\appendtoks\enableadjusting \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!nohz }{\appendtoks\disableadjusting \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!spacing }{\appendtoks\enablespacehandling
- \enablekernhandling \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!nospacing }{\appendtoks\disablespacehandling
- \disablekernhandling \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!hyphenated }{\appendtoks\dohyphens \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!nothyphenated}{\appendtoks\nohyphens \to\everyraggedcommand}
-
-\setvalue{\@@ragged@@command\v!tolerant }{\appendtoks\tolerance3000\relax \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!verytolerant}{\appendtoks\tolerance4500\relax \to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!stretch }{\appendtoks\emergencystretch\bodyfontsize\to\everyraggedcommand}
-
-\setvalue{\@@ragged@@command\v!left}%
- {\if!!donea \appendtoks\veryraggedleft\to\everyraggedcommand
- \else \appendtoks\raggedleft \to\everyraggedcommand
+\unexpanded\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
+ % todo: take set value or none .. better done elsewhere (200 is normal)
\fi
- \!!donecfalse}
+ \ifx\dohyphens\relax % was 2.5 in old implementation using scratch registers
+ \hyphenpenalty\dimexpr2.8\hsize/\dimexpr#1\relax\relax % 50 in raggedright/raggedleft
+ \fi}
-\setvalue{\@@ragged@@command\v!right}%
- {\if!!donea \appendtoks\veryraggedright\to\everyraggedcommand
- \else \appendtoks\raggedright \to\everyraggedcommand
- \fi
- \!!donecfalse}
-
-\setvalue{\@@ragged@@command\v!middle}%
- {\if!!donec
- \if!!doneb \appendtoks\raggedwidecenter\to\everyraggedcommand
- \else\if!!donea \appendtoks\veryraggedcenter\to\everyraggedcommand
- \else \appendtoks\raggedcenter \to\everyraggedcommand
- \fi\fi
- \!!donecfalse
- \else
- \let\raggedbottomcommand\vfilll % bonus, pretty strong
- \let\raggedtopcommand \vfilll % used with \framed for
- \fi} % instance in tables
+\unexpanded\def\spac_align_set_tolerant
+ {\tolerance\c_spac_tolerance_normal}
-\setvalue{\@@ragged@@command\v!flushleft }{\getvalue{\@@ragged@@command\v!right }}
-\setvalue{\@@ragged@@command\v!flushright}{\getvalue{\@@ragged@@command\v!left }}
-\setvalue{\@@ragged@@command\v!center }{\getvalue{\@@ragged@@command\v!middle}}
+\unexpanded\def\spac_align_set_very_tolerant
+ {\tolerance\c_spac_tolerance_extreme}
-\setvalue{\@@ragged@@command\v!high}%
- {\let\raggedbottomcommand\vfilll} % and since we lack a
+\unexpanded\def\spac_align_set_stretch
+ {\emergencystretch\bodyfontsize}
-\setvalue{\@@ragged@@command\v!low}%
- {\let\raggedtopcommand\vfilll} % proper keyword, but
+% Vertical
-\setvalue{\@@ragged@@command\v!lohi}%
- {\let\raggedbottomcommand\vfilll % we do support the
- \let\raggedtopcommand\vfilll} % ugly laho (lohi)
+\newconstant\c_spac_align_state_vertical
-\setvalue{\@@ragged@@command\v!no}%
- {\appendtoks\raggedright\to\everyraggedcommand}
+\unexpanded\def\spac_align_set_vertical_none
+ {\let\raggedtopcommand \relax
+ \let\raggedbottomcommand\relax}
-\setvalue{\@@ragged@@command\v!yes}%
- {\appendtoks\notragged\to\everyraggedcommand}
+\unexpanded\def\spac_align_set_vertical_lohi
+ {\let\raggedtopcommand \vfilll
+ \let\raggedbottomcommand\vfilll}
-\setvalue{\@@ragged@@command\v!normal}%
- {\appendtoks\notragged\to\everyraggedcommand}
+\unexpanded\def\spac_align_set_vertical_low
+ {\let\raggedtopcommand \vfilll
+ \let\raggedbottomcommand\relax}
-\setvalue{\@@ragged@@command\v!inner}%
- {\ifdoublesided
- \appendtoks\signalinnerrealign\to\everyraggedcommand
- \fi
- \rightorleftpageaction
- {\getvalue{\@@ragged@@command\v!right}}%
- {\getvalue{\@@ragged@@command\v!left }}}
+\unexpanded\def\spac_align_set_vertical_high
+ {\let\raggedtopcommand \relax
+ \let\raggedbottomcommand\vfilll}
-\setvalue{\@@ragged@@command\v!outer}%
- {\ifdoublesided
- \appendtoks\signalouterrealign\to\everyraggedcommand
- \fi
- \rightorleftpageaction
- {\getvalue{\@@ragged@@command\v!left }}%
- {\getvalue{\@@ragged@@command\v!right}}}
+\def\spac_align_flush_vertical
+ {\ifcase\c_spac_align_state_vertical
+ \spac_align_set_vertical_none
+ \or
+ \spac_align_set_vertical_lohi
+ \or
+ \spac_align_set_vertical_low
+ \or
+ \spac_align_set_vertical_high
+ \fi}
-\setvalue{\@@ragged@@command\v!lesshyphenation}%
- {\appendtoks\lesshyphens\to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!morehyphenation}%
- {\appendtoks\morehyphens\to\everyraggedcommand}
+% Horizontal
-\setvalue{\@@ragged@@command\v!lefttoright}{\appendtoks\lefttoright\to\everyraggedcommand}
-\setvalue{\@@ragged@@command\v!righttoleft}{\appendtoks\righttoleft\to\everyraggedcommand}
-\setvalue{\@@ragged@@command l2r}{\appendtoks\lefttoright\to\everyraggedcommand}
-\setvalue{\@@ragged@@command r2l}{\appendtoks\righttoleft\to\everyraggedcommand}
+\ifdefined\raggedonelinerstate \else
+ \newconditional\raggedonelinerstate % public
+\fi
-% compare:
-%
-% \framed[width=4cm,align=no] {\hfil xxx}
-% \framed[width=4cm,align=disable]{\hfil xxx}
+% \appendtoks
+% \setfalse\raggedonelinerstate
+% \to \everyforgetall
-\setvalue{\@@ragged@@command\v!disable}% for one liners
- {\appendtoks\raggedright\parfillskip\zeropoint\to\everyraggedcommand}
+\newconstant\raggedstatus % public
-\ifdefined\raggedonelinerstate \else \newconditional\raggedonelinerstate \fi
+\newconstant\c_spac_align_state_horizontal
+\newconstant\c_spac_align_state_broad
-\setvalue{\@@ragged@@command\v!line}%
- {\settrue\raggedonelinerstate}
+\def\v_spac_align_fill_amount {\plusone fil}
+\def\v_spac_align_fill_amount_negative {\minusone fil}
+\def\v_spac_align_fill_amount_double {\plustwo fil}
+\def\v_spac_align_fill_amount_space {\plustwo fil} % can be added to xspace if we have a key
+\def\v_spac_align_fill_amount_half {.5fil}
+\let\v_spac_align_space_amount \interwordspace
+\def\v_spac_align_space_amount_x {.5\emwidth}
-% More alignments:
+\newskip\s_zero_plus_one_fil \s_zero_plus_one_fil = 0pt plus 1fil
+\newskip\s_zero_plus_zero \s_zero_plus_zero = 0pt plus 0pt
-% \hyphenpenalty = ( 2.5 * \hsize ) / \raggedness
-% \tolerance >= 1500 % was 200
-% \raggedness = 2 .. 6\bodyfontsize
+% \!!plus ... slower than inline
-\newconstant\raggedstatus % normal left center right
+\unexpanded\def\spac_align_set_horizontal_none % should also relax \updateraggedskips
+ {\raggedstatus\zerocount
+ \attribute\alignstateattribute\attributeunsetvalue
+ \leftskip \plusone\leftskip
+ \rightskip \plusone\rightskip
+ \spaceskip \zeropoint
+ \xspaceskip \zeropoint
+ \parfillskip\s_zero_plus_one_fil % new
+ \setfalse\raggedonelinerstate % now here
+ \let\updateraggedskips\relax} % no need for adaption
+
+\unexpanded\def\spac_align_set_horizontal_left
+ {\setraggedness\spac_align_set_raggedness_left
+ \raggedstatus\plusone
+ \attribute\alignstateattribute\plusone
+ \leftskip \plusone\leftskip \!!plus\spac_align_set_raggedness_left
+ \rightskip \plusone\rightskip\!!plus\zeropoint
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_center
+ {\setraggedness\spac_align_set_raggedness_middle
+ \raggedstatus\plustwo
+ \attribute\alignstateattribute\plustwo
+ \leftskip \plusone\leftskip \!!plus\spac_align_set_raggedness_middle
+ \rightskip \plusone\rightskip\!!plus\spac_align_set_raggedness_middle
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_right
+ {\setraggedness\spac_align_set_raggedness_right
+ \raggedstatus\plusthree
+ \attribute\alignstateattribute\plusthree
+ \leftskip \plusone\leftskip \!!plus\zeropoint
+ \rightskip \plusone\rightskip\!!plus\spac_align_set_raggedness_right
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_one_fil
+ %\parindent \parindent
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_very_left
+ {\raggedstatus\plusone
+ \attribute\alignstateattribute\plusone
+ \leftskip \plusone\leftskip \!!plus\v_spac_align_fill_amount
+ \rightskip \plusone\rightskip\!!plus\zeropoint
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_very_center
+ {\raggedstatus\plustwo
+ \attribute\alignstateattribute\plustwo
+ \leftskip \plusone\leftskip \!!plus\v_spac_align_fill_amount
+ \rightskip \plusone\rightskip\!!plus\v_spac_align_fill_amount
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_very_right
+ {\raggedstatus\plusthree
+ \attribute\alignstateattribute\plusthree
+ \leftskip \plusone\leftskip \!!plus\zeropoint
+ \rightskip \plusone\rightskip\!!plus\v_spac_align_fill_amount
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ %\parindent \parindent
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_wide_center
+ {\setraggedness\spac_align_set_raggedness_middle
+ \raggedstatus\plustwo
+ \attribute\alignstateattribute\plustwo
+ \leftskip \plusone\leftskip \!!plus\v_spac_align_fill_amount_half
+ \rightskip \plusone\rightskip\!!plus\v_spac_align_fill_amount_half
+ \spaceskip \v_spac_align_space_amount
+ \xspaceskip \v_spac_align_space_amount_x
+ \parfillskip\s_zero_plus_zero
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_centered_last_line
+ {\raggedstatus\zerocount
+ \attribute\alignstateattribute\attributeunsetvalue
+ \leftskip \plusone\leftskip \!!plus\v_spac_align_fill_amount\relax
+ \rightskip \plusone\rightskip\!!plus\v_spac_align_fill_amount_negative\relax
+ \spaceskip \zeropoint\relax
+ \xspaceskip \zeropoint\relax
+ \parfillskip\zeropoint\!!plus\v_spac_align_fill_amount_double\relax
+ \parindent \zeropoint
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_right_tt % a plain command
+ {\tttf % brrr
+ \raggedstatus\plusthree
+ \attribute\alignstateattribute\plusthree
+ \leftskip \plusone\leftskip \!!plus\zeropoint\relax
+ \rightskip \plusone\rightskip\!!plus\spac_align_set_raggedness_right\relax
+ \spaceskip \zeropoint\relax
+ \xspaceskip \zeropoint\relax
+ \parfillskip\s_zero_plus_zero
+ %\parindent \parindent
+ \relax}
+
+\unexpanded\def\spac_align_set_horizontal_extra
+ {\xspaceskip\zeropoint\!!plus\v_spac_align_fill_amount_space\relax}
+
+\def\spac_align_flush_horizontal
+ {\ifcase\c_spac_align_state_horizontal
+ % 0
+ \spac_align_set_horizontal_none
+ \or
+ % 1 center
+ \ifcase\c_spac_align_state_broad
+ \spac_align_set_horizontal_center
+ \or
+ \spac_align_set_horizontal_very_center
+ \or
+ \spac_align_set_horizontal_wide_center
+ \fi
+ \or
+ % 2 flush left
+ \ifcase\c_spac_align_state_broad
+ \spac_align_set_horizontal_right
+ \else
+ \spac_align_set_horizontal_very_right
+ \fi
+ \or
+ % 3 flush right
+ \ifcase\c_spac_align_state_broad
+ \spac_align_set_horizontal_left
+ \else
+ \spac_align_set_horizontal_very_left
+ \fi
+ \or
+ % 4 inner
+ \ifdoublesided
+ \signalinnerrealign
+ \fi
+ \rightorleftpageaction\spac_align_set_horizontal_right\spac_align_set_horizontal_left
+ \or
+ % 5 outer
+ \ifdoublesided
+ \signalouterrealign
+ \fi
+ \rightorleftpageaction\spac_align_set_horizontal_left\spac_align_set_horizontal_right
+ \or
+ % 6 oneliner
+ \ifcase\c_spac_align_state_broad
+ \spac_align_set_horizontal_right
+ \else
+ \spac_align_set_horizontal_very_right
+ \fi
+ \parfillskip\zeropoint
+ \or
+ % 7 centered last line
+ \spac_align_set_horizontal_centered_last_line
+ \fi}
-\def\leftraggedness {2\bodyfontsize}
-\def\rightraggedness {2\bodyfontsize}
-\def\middleraggedness {6\bodyfontsize}
+% Page spacing:
-\def\middleraggedness {.5\hsize} % was: 6\bodyfontsize, fails on: \placefigure{x $x=x$ x}{}
+\newconstant\c_spac_align_state_page
-% oeps, hsize can be 0pt in which case we get a strange division
+\def\bottomalignlimit{\plusthree\lineheight}
-\def\middleraggedness {\ifdim\hsize=\zeropoint6\bodyfontsize\else.5\hsize\fi} % was: 6\bodyfontsize, fails on: \placefigure{x $x=x$ x}{}
+\newconstant\bottomraggednessmode % 0=ragged 1=normal/align 2=baseline
-%D More hyphenation control, will be combined with align
-%D setup.
+\unexpanded\def\raggedbottom
+ {\bottomraggednessmode\zerocount
+ \settopskip}
-\def\nohyphens % % % % % not clever, we still hyphenate but supress application
- {\ifx\dohyphens\relax
- \edef\dohyphens
- {\hyphenpenalty\the\hyphenpenalty
- \exhyphenpenalty\the\exhyphenpenalty\relax}%
+\unexpanded\def\alignbottom
+ {\bottomraggednessmode\plusone
+ \settopskip}
+
+\unexpanded\def\baselinebottom
+ {\bottomraggednessmode\plustwo
+ \settopskip}
+
+\let\normalbottom\alignbottom % downward compatible
+
+\unexpanded\def\setbottomalignmode#1%
+ {\bottomraggednessmode#1%
+ \settopskip}
+
+\def\spac_align_flush_page
+ {\ifcase\c_spac_align_state_page
+ % keep state
+ \or
+ \raggedbottom
+ \or
+ \alignbottom
+ \or
+ \baselinebottom
+ \fi}
+
+% Directions
+
+\newconstant\c_spac_align_state_direction
+
+\def\spac_align_flush_direction
+ {\ifcase\c_spac_align_state_direction
+ % keep state
+ \or
+ \lefttoright
+ \or
+ \righttoleft
+ \fi}
+
+% Interesting is that the non cached version is also pretty efficient
+% and as we cache we seldom call that one now so one can debate the
+% speedup.
+
+\newtoks\t_spac_align_collected
+
+\let\raggedcommand \relax
+\let\updateraggedskips\relax
+
+\def\spac_align_add_to_cache#1%
+ {\edef\askedraggedalign{#1}%
+ \let\raggedbox\relax % why
+ % we inherit hyphenation and tolerance
+ \t_spac_align_collected \emptytoks
+ \c_spac_align_state_broad \zerocount
+ \c_spac_align_state_horizontal\zerocount
+ \c_spac_align_state_vertical \zerocount
+ \c_spac_align_state_direction \zerocount % what is default ?
+ \c_spac_align_state_page \zerocount
+ \ifcsname\??aligncommand\askedraggedalign\endcsname
+ \csname\??aligncommand\askedraggedalign\endcsname % not much gain in new method
+ \else
+ \rawprocesscommacommand[\askedraggedalign]\spac_align_collect
\fi
- \hyphenpenalty\plustenthousand
- \exhyphenpenalty\plustenthousand}
+ \normalexpanded{\t_spac_align_collected
+ {% \resetrealignsignal % can go as it is always set
+ \setfalse\raggedonelinerstate % bad
+ \the\t_spac_align_collected
+ \spac_align_flush_horizontal
+ \spac_align_flush_vertical
+ \spac_align_flush_direction
+ \spac_align_flush_page
+ }}% kept, nice for tracing
+ \edef\raggedcommand {\the\t_spac_align_collected }%
+ \edef\updateraggedskips{\spac_align_flush_horizontal}%
+ \global\expandafter\let\csname\??alignmentnormalcache#1\endcsname\raggedcommand
+ \global\expandafter\let\csname\??alignmentraggedcache#1\endcsname\updateraggedskips}
+
+\def\spac_align_collect#1%
+ {\csname\??aligncommand#1\endcsname}
+
+% The local (key driven) setter:
+
+\unexpanded\def\spac_align_prepare#1% deferred
+ {\expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache#1\endcsname
+ \ifx\raggedcommand\relax
+ \spac_align_add_to_cache{#1}%
+ \else
+ \expandafter\let\expandafter\updateraggedskips\csname\??alignmentraggedcache#1\endcsname
+ \fi}
-\let\dohyphens\relax
+\let\dosetraggedcommand\spac_align_prepare % sort of public
-%D To prevent unwanted side effects, we also have to check
-%D for hyphens here:
+% The regular align setter:
-\newskip\@@raggedskipa
-\newskip\@@raggedskipb
+\unexpanded\def\setupalign
+ {\dosingleempty\spac_align_setup}
-\def\setraggedness#1%
- {\ifnum\tolerance<1500\relax % small values have
- \tolerance1500\relax % unwanted side effects
+\def\spac_align_setup[#1]% immediate
+ {\expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache#1\endcsname
+ \ifx\raggedcommand\relax
+ \spac_align_add_to_cache{#1}%
+ \else
+ \expandafter\let\expandafter\updateraggedskips\csname\??alignmentraggedcache#1\endcsname
\fi
- \ifx\dohyphens\relax
- % this code will be reconsidered / kind of fuzzy (and old)
- \@@raggedskipa 2.5\hsize
- \@@raggedskipb #1\relax
- \divide\@@raggedskipa \@@raggedskipb
- \hyphenpenalty\@@raggedskipa
+ \raggedcommand}
+
+\unexpanded\def\usealignparameter#1% faster local variant
+ {\edef\m_spac_align{#1\c!align}%
+ \ifx\m_spac_align\empty\else
+ \expandafter\let\expandafter\raggedcommand\csname\??alignmentnormalcache\m_spac_align\endcsname
+ \ifx\raggedcommand\relax
+ \spac_align_add_to_cache\m_spac_align
+ \else
+ \expandafter\let\expandafter\updateraggedskips\csname\??alignmentraggedcache\m_spac_align\endcsname
+ \fi
+ \raggedcommand
\fi}
-\let\updateraggedskips\relax
+% The keywords:
+
+\unexpanded\def\installalign#1#2% beware: commands must be unexpandable!
+ {\ifcsname\??aligncommand#1\endcsname \else
+ \setvalue{\??aligncommand#1}{\t_spac_align_collected\expandafter{\the\t_spac_align_collected#2}}%
+ \fi}
+
+\letvalue{\??aligncommand\empty }\empty
+\setvalue{\??aligncommand\v!broad }{\c_spac_align_state_broad \plusone }
+\setvalue{\??aligncommand\v!wide }{\c_spac_align_state_broad \plustwo }
+
+\setvalue{\??aligncommand\v!bottom }{\c_spac_align_state_page \plusone }
+\setvalue{\??aligncommand\v!height }{\c_spac_align_state_page \plustwo }
+\setvalue{\??aligncommand\v!line }{\c_spac_align_state_page \plusthree
+ % this will become another keyword (undocumented anyway)
+ \t_spac_align_collected\expandafter{\the\t_spac_align_collected\settrue\raggedonelinerstate}}
+
+\setvalue{\??aligncommand\v!high }{\c_spac_align_state_vertical \plusthree}
+\setvalue{\??aligncommand\v!low }{\c_spac_align_state_vertical \plustwo }
+\setvalue{\??aligncommand\v!lohi }{\c_spac_align_state_vertical \plusone }
+
+\setvalue{\??aligncommand\v!flushright }{\c_spac_align_state_horizontal\plusthree}
+\setvalue{\??aligncommand\v!flushleft }{\c_spac_align_state_horizontal\plustwo }
+\setvalue{\??aligncommand\v!middle }{\c_spac_align_state_horizontal\plusone }
+\setvalue{\??aligncommand\v!no }{\c_spac_align_state_horizontal\plustwo }
+\setvalue{\??aligncommand\v!yes }{\c_spac_align_state_horizontal\zerocount}
+\setvalue{\??aligncommand\v!width }{\c_spac_align_state_horizontal\zerocount}
+\setvalue{\??aligncommand\v!normal }{\c_spac_align_state_horizontal\zerocount}
+\setvalue{\??aligncommand\v!reset }{\c_spac_align_state_page \zerocount
+ \c_spac_align_state_horizontal\zerocount}
+\setvalue{\??aligncommand\v!inner }{\c_spac_align_state_horizontal\plusfour }
+\setvalue{\??aligncommand\v!outer }{\c_spac_align_state_horizontal\plusfive }
+\setvalue{\??aligncommand\v!flushinner }{\c_spac_align_state_horizontal\plusfive }
+\setvalue{\??aligncommand\v!flushouter }{\c_spac_align_state_horizontal\plusfour }
+\setvalue{\??aligncommand\v!right }{\c_spac_align_state_horizontal\plustwo }
+\setvalue{\??aligncommand\v!left }{\c_spac_align_state_horizontal\plusthree}
+\setvalue{\??aligncommand\v!center }{\c_spac_align_state_horizontal\plusone
+ \c_spac_align_state_broad \plustwo }
+\setvalue{\??aligncommand\v!disable }{\c_spac_align_state_horizontal\plussix }
+\setvalue{\??aligncommand\v!last }{\c_spac_align_state_horizontal\plusseven}
+
+
+\setvalue{\??aligncommand\v!lefttoright }{\c_spac_align_state_direction \plusone }
+\setvalue{\??aligncommand\v!righttoleft }{\c_spac_align_state_direction \plustwo }
+\setvalue{\??aligncommand l2r}{\c_spac_align_state_direction \plusone }
+\setvalue{\??aligncommand r2l}{\c_spac_align_state_direction \plustwo }
+
+\setvalue{\??aligncommand\v!table }{\c_spac_align_state_vertical \plusthree
+ \c_spac_align_state_broad \plusone
+ \c_spac_align_state_horizontal\plustwo }
+
+\setvalue{\??aligncommand\v!lesshyphenation}{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\lesshyphens}}
+\setvalue{\??aligncommand\v!morehyphenation}{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\morehyphens}}
+
+\setvalue{\??aligncommand\v!hanging }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\font_protruding_enable }}
+\setvalue{\??aligncommand\v!nothanging }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\font_protruding_disable}}
+\setvalue{\??aligncommand\v!hz }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\font_expansion_enable }}
+\setvalue{\??aligncommand\v!nohz }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\font_expansion_disable }}
+%setvalue{\??aligncommand\v!spacing }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\enablespacehandling \enablekernhandling }} % not in mkiv
+%setvalue{\??aligncommand\v!nospacing }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\disablespacehandling\disablekernhandling}} % not in mkiv
+\setvalue{\??aligncommand\v!hyphenated }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\dohyphens}}
+\setvalue{\??aligncommand\v!nothyphenated }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\nohyphens}}
+
+\setvalue{\??aligncommand\v!tolerant }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\spac_align_set_tolerant}}
+\setvalue{\??aligncommand\v!verytolerant }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\spac_align_set_very_tolerant}}
+\setvalue{\??aligncommand\v!stretch }{\t_spac_align_collected\expandafter{\the\t_spac_align_collected\spac_align_set_stretch}}
+
+% Visible commands:
+
+\let\notragged \spac_align_set_horizontal_none
+\let\raggedleft \spac_align_set_horizontal_left
+\let\raggedcenter \spac_align_set_horizontal_center
+\let\raggedright \spac_align_set_horizontal_right
+\let\veryraggedleft \spac_align_set_horizontal_very_left
+\let\veryraggedcenter\spac_align_set_horizontal_very_center
+\let\veryraggedright \spac_align_set_horizontal_very_right
+\let\raggedwidecenter\spac_align_set_horizontal_wide_center
+\let\centeredlastline\spac_align_set_horizontal_centered_last_line
+\let\ttraggedright \spac_align_set_horizontal_right_tt % a plain command
+
+\let\forgetragged \spac_align_set_horizontal_none
+
+% Box commands.
+
+\unexpanded\def\ibox#1#2#3%
+ {\vbox\bgroup
+ \forgetall
+ \let\\=\endgraf
+ \ifdoublesided\signalinnerrealign\fi
+ \doifrightpageelse\spac_align_set_horizontal_right\spac_align_set_horizontal_left
+ \let\next}
+
+\unexpanded\def\obox#1#2#3%
+ {\vbox\bgroup
+ \forgetall
+ \let\\=\endgraf
+ \ifdoublesided\signalouterrealign\fi
+ \doifrightpageelse\c_spac_align_state_horizontal_left\spac_align_set_horizontal_right
+ \let\next}
+
+\let\raggedbox\relax
+
+\def\dosetraggedvbox#1% can be more keys .. how about caching here (but seldom used)
+ {\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
+ \processcommacommand[#1]\spac_align_set_ragged_hbox}
+
+\def\spac_align_set_ragged_vbox#1%
+ {\ifcsname\??alignvertical#1\endcsname
+ \csname\??alignvertical#1\endcsname
+ \quitcommalist
+ \fi}
+
+\def\spac_align_set_ragged_hbox#1%
+ {\ifcsname\??alignhorizontal#1\endcsname
+ \csname\??alignhorizontal#1\endcsname
+ \quitcommalist
+ \fi}
-\def\setraggedskips#1#2#3#4#5#6#7% never change this name
- {\def\updateraggedskips{\dosetraggedskips{#1}{#2}{#3}{#4}{#5}{#6}{#7}}%
+% \def\usealignparametersethbox#1%
+% {\edef\p_spac_align{#1\c!align}%
+% \let\raggedbox\hbox
+% \ifx\p_spac_align\empty \else
+% \processcommacommand[\p_spac_align]\spac_align_set_ragged_hbox
+% \fi}
+%
+% \def\usealignparametersetvbox#1%
+% {\edef\p_spac_align{#1\c!align}%
+% \let\raggedbox\vbox
+% \ifx\p_spac_align\empty \else
+% \processcommacommand[\p_spac_align]\spac_align_set_ragged_vbox
+% \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}}
+
+% 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}}%
\updateraggedskips}
\def\dosetraggedskips#1#2#3#4#5#6#7%
- {\raggedstatus#1\relax
- \leftskip 1\leftskip \!!plus#2\relax % zie: Tex By Topic 8.1.3
- \rightskip 1\rightskip\!!plus#3\relax % zie: Tex By Topic 8.1.3
- \spaceskip #4\relax
- \xspaceskip #5\relax
- \parfillskip\zeropoint\!!plus#6\relax
- \parindent #7\relax}
-
-% \def\notragged%
-% {\setraggedskips{0}{0em}{0em}{0em}{0em}{1fil}{\parindent}}
+ {\raggedstatus #1\relax
+ \leftskip 1\leftskip \!!plus#2\relax
+ \rightskip 1\rightskip\!!plus#3\relax
+ \spaceskip #4\relax
+ \xspaceskip #5\relax
+ \parfillskip \zeropoint\!!plus#6\relax
+ \parindent #7\relax
+ \attribute\alignstateattribute\ifcase\raggedstatus\attributeunsetvalue\else\raggedstatus\fi}
% older (context) names:
@@ -344,16 +750,16 @@
% tracing:
-\def\doshowpardata#1%
+\def\spac_show_par_data#1%
{\ifx#1\relax\else
\hbox{\string#1: \the#1}\endgraf
- \expandafter\doshowpardata
+ \expandafter\spac_show_par_data
\fi}
-\def\showpardata
+\unexpanded\def\showpardata
{\edef\thepardata
{\hbox{font: \fontname\font}\endgraf
- \doshowpardata
+ \spac_show_par_data
\interwordspace \interwordstretch \interwordshrink \emwidth \exheight \extraspace
\hsize \vsize
\leftskip \rightskip
@@ -363,214 +769,30 @@
\displaywidowpenalty \widowpenalty \clubpenalty \brokenpenalty
\doublehyphendemerits \finalhyphendemerits \adjdemerits
\relax}%
+ \dontleavehmode
\begingroup
- \dontshowcomposition
- \inleftmargin{\vsmash
- {\infofont
- \framed[\c!align=\v!right]{\thepardata}}}%
+ \inleftmargin{\vsmash{\infofont\framed[\c!align=\v!right]{\thepardata}}}%
\endgroup}
\unexpanded\def\startshowpardata
{\begingroup
- \showcomposition
- \showstruts\tracepositionstrue \tracingparagraphs\maxdimen
+ \showstruts
+ \tracingparagraphs\maxdimen
\appendtoksonce\showpardata\let\showpardata\relax\to\everypar}
\unexpanded\def\stopshowpardata
{\endgraf
\endgroup}
-% defaults
-
-\def\raggedfillamount {1fil}
-\def\raggedhalffillamount{.5fil}
-\def\raggedspaceamount {\interwordspace} % {.3333em}
-\def\raggedxspaceamount {.5em}
-
-\unexpanded\def\notragged
- {\raggedstatus\zerocount
- \leftskip 1\leftskip
- \rightskip 1\rightskip
- \spaceskip \zeropoint
- \xspaceskip \zeropoint
- \parfillskip\zeropoint\!!plus\raggedfillamount\relax
- \let\updateraggedskips\relax} % new
-
-\let\forgetragged\notragged
-
-\unexpanded\def\raggedleft
- {\setraggedness\leftraggedness
- \setraggedskips1\leftraggedness\zeropoint\raggedspaceamount
- \raggedxspaceamount\zeropoint\zeropoint}
-
-\unexpanded\def\raggedcenter
- {\setraggedness\middleraggedness
- \setraggedskips2\middleraggedness\middleraggedness\raggedspaceamount
- \raggedxspaceamount\zeropoint\zeropoint}
-
-%D We used to have:
-%D
-%D \starttyping
-%D \def\raggedright
-%D {\setraggedness\rightraggedness
-%D \setraggedskips{3}{0em}{\rightraggedness}{.3333em}{.5em}{0em}{\parindent}}
-%D \stoptyping
-%D
-%D However, the next alternative, suggested by Taco, is better.
-
-\unexpanded\def\raggedright
- {\setraggedness\rightraggedness
- \setraggedskips3\zeropoint\rightraggedness\raggedspaceamount
- \raggedxspaceamount\raggedfillamount\parindent}
-
-\unexpanded\def\veryraggedleft
- {\setraggedskips1\raggedfillamount\zeropoint\raggedspaceamount
- \raggedxspaceamount\zeropoint\zeropoint}
-
-%D When we want the last line to have a natural width:
-%D
-%D \starttyping
-%D \def\veryraggedleft%
-%D {\setraggedskips{1}{1fil}{0em}{.3333em}{.5em}{0em}{-1fil}}
-%D \stoptyping
-%D
-%D but this one is not accepted by the macros.
-
-\unexpanded\def\veryraggedcenter
- {\setraggedskips2\raggedfillamount\raggedfillamount\raggedspaceamount
- \raggedxspaceamount\zeropoint\zeropoint}
-
-\unexpanded\def\veryraggedright
- {\setraggedskips3\zeropoint\raggedfillamount\raggedspaceamount
- \raggedxspaceamount\zeropoint\parindent}
-
-\unexpanded\def\ttraggedright
- {\tttf
- \setraggedskips3\zeropoint\rightraggedness
- \zeropoint\zeropoint\zeropoint\parindent} % \ctxparindent
-
-%D A bonus one:
-
-\unexpanded\def\raggedwidecenter
- {\setraggedness\middleraggedness
- \setraggedskips2\raggedhalffillamount\raggedhalffillamount
- \raggedspaceamount\raggedxspaceamount\zeropoint\zeropoint}
-
-\newif\if@@asragged \@@asraggedtrue % old method
-
-% todo
-%
-% \setuplayout[grid=yes,lines=44] \showgrid
-% \starttext
-% test \vfill test \endgraf \strut \endgraf \vskip-\lineheight \removedepth \pagina test
-% \stoptext
-
-% \setupalign[reset,new,right,old]
-
-\def\@@align@@rl{\if!!donea\veryraggedleft \else\raggedleft \fi}
-\def\@@align@@rr{\if!!donea\veryraggedright \else\raggedright \fi}
-\def\@@align@@rc{\if!!donea\veryraggedcenter\else\raggedcenter\fi}
-
-\setvalue{@@ngila@@\v!broad }{\!!doneatrue}
-\setvalue{@@ngila@@\v!wide }{\!!donebtrue}
-
-\def\setraggedparagraphmode
- {\doifrightpageelse
- {\ifdoublesided\signalinnerrealign\expandafter\firstoftwoarguments \fi}
- {\ifdoublesided\signalouterrealign\expandafter\secondoftwoarguments\fi}}
-
-\def\installalign#1#2{\setvalue{@@align@@#1}{#2}} % can be used for overloads
-
-\installalign \v!new {\@@asraggedfalse}
-\installalign \v!old {\@@asraggedtrue}
-\installalign \empty {}
-
-\installalign \v!line {\baselinebottom}
-\installalign \v!bottom {\raggedbottom}
-\installalign \v!height {\normalbottom}
-\installalign \v!width {\notragged}
-\installalign \v!normal {\notragged}
-\installalign \v!yes {\notragged}
-\installalign \v!no {\raggedright}
-\installalign \v!inner {\if@@asragged \setraggedparagraphmode\@@align@@rl\@@align@@rr \else
- \setraggedparagraphmode\@@align@@rr\@@align@@rl \fi}
-\installalign \v!outer {\if@@asragged \setraggedparagraphmode\@@align@@rr\@@align@@rl \else
- \setraggedparagraphmode\@@align@@rl\@@align@@rr \fi}
-\installalign \v!left {\if@@asragged\@@align@@rl\else\@@align@@rr\fi}
-\installalign \v!right {\if@@asragged\@@align@@rr\else\@@align@@rl\fi}
-\installalign \v!middle {\if!!doneb\raggedwidecenter\else\@@align@@rc\fi}
-\installalign \v!flushleft {\if!!donea\veryraggedright \else\raggedright\fi}
-\installalign \v!flushright {\if!!donea\veryraggedleft \else\raggedleft \fi}
-\installalign \v!flushouter {\setraggedparagraphmode\raggedleft\raggedright}
-\installalign \v!flushinner {\setraggedparagraphmode\raggedright\raggedleft}
-\installalign \v!center {\if!!doneb\raggedwidecenter\else\@@align@@rc\fi}
-\installalign \v!hanging {\enableprotruding}
-\installalign \v!nothanging {\disableprotruding}
-\installalign \v!hz {\enableadjusting}
-\installalign \v!nohz {\disableadjusting}
-\installalign \v!spacing {\enablespacehandling \enablekernhandling}
-\installalign \v!nospacing {\disablespacehandling\disablekernhandling}
-\installalign \v!hyphenated {\dohyphens}
-\installalign \v!nothyphenated {\nohyphens}
-\installalign \v!new {\@@asraggedfalse} % so new will give you consistency
-\installalign \v!reset {\notragged\normalbottom}
-
-\installalign \v!tolerant {\tolerance3000 \relax}
-\installalign \v!verytolerant {\tolerance4500 \relax}
-\installalign \v!stretch {\emergencystretch\bodyfontsize}
-
-\installalign \v!righttoleft {\lefttoright}
-\installalign \v!lefttoright {\righttoleft}
-\installalign {l2r} {\lefttoright}
-\installalign {r2l} {\righttoleft}
-
-\newcount\hyphenminoffset
-
-\ifx\sethyphenationvariables\undefined \let\sethyphenationvariables\relax \fi
-
-\unexpanded\def\lesshyphens
- {\advance\hyphenminoffset\plusone
- \sethyphenationvariables}
-
-\unexpanded\def\morehyphens
- {\ifcase\hyphenminoffset \else
- \advance\hyphenminoffset\minusone
- \fi
- \sethyphenationvariables}
-
-\installalign \v!lesshyphenation {\lesshyphens}
-\installalign \v!morehyphenation {\morehyphens}
-
-\def\dodosetupalign#1{\csname @@align@@#1\endcsname}
-\def\dodosetupngila#1{\csname @@ngila@@#1\endcsname}
-
-\unexpanded\def\setupalign
- {\dosingleargument\dosetupalign}
-
-\def\dosetupalign[#1]% can be made faster by checking for defined #1
- {\!!doneafalse
- \!!donebfalse
- \raggedstatus\zerocount
- \resetrealignsignal
- \processcommacommand[#1]\dodosetupngila
- \processcommacommand[#1]\dodosetupalign}
-
-% \setupalign[flushleft] \input ward \par % lijnlinks
-% \setupalign[right] \input ward \par
-
-% \setupalign[flushright] \input ward \par % lijnrechts
-% \setupalign[left] \input ward \par
-
-% \setupalign[middle] \input ward \par % centreer
-% \setupalign[center] \input ward \par
+% Structure:
\unexpanded\def\startalignment
- {\bgroup
+ {\begingroup
\setupalign}
\unexpanded\def\stopalignment
{\par
- \egroup}
+ \endgroup}
\setnewconstant\alignstrutmode\plusone
@@ -579,7 +801,7 @@
\newtoks \everyleftofalignedline
\newtoks \everyrightofalignedline
-\def\shiftalignedline#1#2#3#4% left, right, inner, outer
+\unexpanded\def\shiftalignedline#1#2#3#4% left, right, inner, outer
{\rightorleftpageaction
{\everyleftofalignedline {\hskip\dimexpr#1+#3\relax}%
\everyrightofalignedline{\hskip\dimexpr#2+#4\relax}}
@@ -591,7 +813,7 @@
\dontleavehmode % added in marrakesch at TUG 2006\begingroup
\begingroup
\setlocalhsize % new
- \def\\{\egroup\par\doalignline{#1}{#2}\bgroup}%
+ \def\\{\endgroup\par\doalignline{#1}{#2}\begingroup}%
\dowithnextbox
{\hbox to \localhsize
{\ifcase\alignstrutmode\or\strut\fi
@@ -608,39 +830,38 @@
\ifdefined\rightline \else \def\rightline #1{\line{\hss#1}} \fi
\ifdefined\centerline \else \def\centerline#1{\line{\hss#1\hss}} \fi
-% directe commando's
+% direct commands
-\def\leftaligned {\doalignline \relax \hss }
-\def\midaligned {\doalignline \hss \hss }
-\def\rightaligned{\doalignline \hss \relax}
+\unexpanded\def\leftaligned {\doalignline\relax \hss }
+\unexpanded\def\midaligned {\doalignline\hss \hss }
+\unexpanded\def\rightaligned{\doalignline\hss \relax}
+\unexpanded\def\maxaligned {\doalignline\relax \relax}
\let\centeraligned\midaligned
-% \def\regelbegrensd#1{\limitatetext{#1}{\hsize}{\unknown}} % to be translated
+\installcorenamespace{alignline}
-% indirecte commando's
+\letvalue{\??alignline\v!left }\leftaligned
+\letvalue{\??alignline\v!right }\rightaligned
+\letvalue{\??alignline\v!middle }\midaligned
+\letvalue{\??alignline\v!flushleft }\rightaligned % beware, makes no sense in locations / we will have a special locations handler
+\letvalue{\??alignline\v!flushright}\leftaligned % beware, makes no sense in locations / we will have a special locations handler
+\letvalue{\??alignline\v!center }\midaligned
+\letvalue{\??alignline\v!max }\maxaligned
-\letvalue{\s!do\v!line\v!left }\leftaligned
-\letvalue{\s!do\v!line\v!right }\rightaligned
-\letvalue{\s!do\v!line\v!middle }\midaligned
-\letvalue{\s!do\v!line\v!flushleft }\rightaligned
-\letvalue{\s!do\v!line\v!flushright}\leftaligned
-\letvalue{\s!do\v!line\v!center }\midaligned
-
-\def\doalignedline#1{\resetrealignsignal\csname\s!do\v!line#1\endcsname}
+\def\doalignedline#1{\resetrealignsignal\csname\??alignline#1\endcsname}
%D Experimental (will be redone when floats are redone as it's real messy
-%D now):
+%D now). It can also be made faster (if needed).
\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
+ \def\\{\endgroup\par\doxalignline#1#2#3#4#5#6\begingroup}% inefficient
\dowithnextbox
- {%\noindent moved up
- \hbox to \localhsize
+ {\hbox to \localhsize
{#1\hskip\ifdone#2\else#3\fi#4%
\hbox to \localhsize
{\the\everyleftofalignedline
@@ -654,35 +875,33 @@
\def\doxcheckline % used for floats so multipass anyway
{\signalrightpage\doifrightpageelse\donetrue\donefalse}
-\setvalue{\s!do\v!line\v!inner }{\doxalignline\doxcheckline++\zeropoint \relax\hss }
-\setvalue{\s!do\v!line\v!outer }{\doxalignline\doxcheckline++\zeropoint \hss \relax}
-\setvalue{\s!do\v!line\v!innermargin}{\doxalignline\doxcheckline-+\innermargintotal\relax\hss }
-\setvalue{\s!do\v!line\v!outermargin}{\doxalignline\doxcheckline+-\outermargintotal\hss \relax}
-\setvalue{\s!do\v!line\v!inneredge }{\doxalignline\doxcheckline-+\inneredgetotal \relax\hss }
-\setvalue{\s!do\v!line\v!outeredge }{\doxalignline\doxcheckline+-\outeredgetotal \hss \relax}
-\setvalue{\s!do\v!line\v!backspace }{\doxalignline\doxcheckline-+\backspace \relax\hss }
-\setvalue{\s!do\v!line\v!cutspace }{\doxalignline\doxcheckline+-\cutspace \hss \relax}
-
-\setvalue{\s!do\v!line\v!leftmargin }{\doxalignline\donefalse --\leftmargintotal \hss \relax}
-\setvalue{\s!do\v!line\v!rightmargin}{\doxalignline\donefalse ++\rightmargintotal\relax\hss }
-\setvalue{\s!do\v!line\v!leftedge }{\doxalignline\donefalse --\leftedgetotal \hss \relax}
-\setvalue{\s!do\v!line\v!rightedge }{\doxalignline\donefalse ++\rightedgetotal \relax\hss }
-
-% ! ! ! beware, redefining \doalignline gives the wrong results ! ! !
-%
-% \def\doalignline{\doxalignline\donefalse++\zeropoint}
+\setvalue{\??alignline\v!inner }{\doxalignline\doxcheckline++\zeropoint \relax\hss }
+\setvalue{\??alignline\v!outer }{\doxalignline\doxcheckline++\zeropoint \hss \relax}
+\setvalue{\??alignline\v!innermargin}{\doxalignline\doxcheckline-+\innermargintotal\relax\hss }
+\setvalue{\??alignline\v!outermargin}{\doxalignline\doxcheckline+-\outermargintotal\hss \relax}
+\setvalue{\??alignline\v!inneredge }{\doxalignline\doxcheckline-+\inneredgetotal \relax\hss }
+\setvalue{\??alignline\v!outeredge }{\doxalignline\doxcheckline+-\outeredgetotal \hss \relax}
+\setvalue{\??alignline\v!backspace }{\doxalignline\doxcheckline-+\backspace \relax\hss }
+\setvalue{\??alignline\v!cutspace }{\doxalignline\doxcheckline+-\cutspace \hss \relax}
-%D Better:
+\setvalue{\??alignline\v!leftmargin }{\doxalignline\donefalse --\leftmargintotal \hss \relax}
+\setvalue{\??alignline\v!rightmargin}{\doxalignline\donefalse ++\rightmargintotal\relax\hss }
+\setvalue{\??alignline\v!leftedge }{\doxalignline\donefalse --\leftedgetotal \hss \relax}
+\setvalue{\??alignline\v!rightedge }{\doxalignline\donefalse ++\rightedgetotal \relax\hss }
-\def\doalignedline#1{\csname\s!do\v!line#1\endcsname}
+\def\doalignedline#1% unchecked
+ {\csname\??alignline#1\endcsname} % no \resetrealignsignal here ?
\def\alignedline#1#2% setting default
- {\csname\s!do\v!line\ifcsname\s!do\v!line#1\endcsname#1\else#2\fi\endcsname}
+ {\csname\??alignline\ifcsname\??alignline#1\endcsname#1\else#2\fi\endcsname}
% beware: \wordright{whatever\kern-\rightskip} should work!
% so, no funny boxing here
-\def\dowordright[#1]%
+\unexpanded\def\wordright
+ {\dosingleempty\spac_word_right}
+
+\def\spac_word_right[#1]%
{% don't change
\groupedcommand
{\removeunwantedspaces
@@ -697,50 +916,50 @@
\finalhyphendemerits\zerocount % yes or no (see hyhenation/specialcases-001.tex)
\par}}
-\unexpanded\def\wordright
- {\dosingleempty\dowordright}
-
-% \dorecurse{5}{something } \wordright{--someone} \endgraf
-% \dorecurse{6}{something } \wordright{--someone} \endgraf
-% \dorecurse{7}{something } \wordright{--someone} \endgraf
+% \dorecurse{5}{something} \wordright{--someone} \endgraf
+% \dorecurse{6}{something} \wordright{--someone} \endgraf
+% \dorecurse{7}{something} \wordright{--someone} \endgraf
%
-% \dorecurse{5}{something } \wordright{--someone else entirely} \endgraf
-% \dorecurse{6}{something } \wordright{--someone else entirely} \endgraf
-% \dorecurse{7}{something } \wordright{--someone else entirely} \endgraf
+% \dorecurse{5}{something} \wordright{--someone else entirely} \endgraf
+% \dorecurse{6}{something} \wordright{--someone else entirely} \endgraf
+% \dorecurse{7}{something} \wordright{--someone else entirely} \endgraf
%
% \wordright[\rightskip]{whatever}
-
-% \simplealignedbox{2cm}{right}{x}
-% \setvalue{\s!simple\c!align\v!right }#1#2{\hbox to #1{#2\hss}}
-% \setvalue{\s!simple\c!align\v!left }#1#2{\hbox to #1{\hss#2}}
-% \setvalue{\s!simple\c!align\v!flushright }#1#2{\hbox to #1{\hss#2}}
-% \setvalue{\s!simple\c!align\v!flushleft }#1#2{\hbox to #1{#2\hss}}
-% \setvalue{\s!simple\c!align\v!middle }#1#2{\hbox to #1{\hss#2\hss}}
+% \simplealignedbox{2cm}{right}{x}
-% \unexpanded\def\simplealignedbox#1%
-% {\csname\s!simple\c!align\ifcsname\s!simple\c!align#1\endcsname#1\else\v!right\fi\endcsname}
+\installcorenamespace{alignsimple}
-\setvalue{\s!simple:\c!align:\v!right }#1{{#1\hss}}
-\setvalue{\s!simple:\c!align:\v!left }#1{{\hss#1}}
-\setvalue{\s!simple:\c!align:\v!flushright }#1{{\hss#1}}
-\setvalue{\s!simple:\c!align:\v!flushleft }#1{{#1\hss}}
-\setvalue{\s!simple:\c!align:\v!middle }#1{{\hss#1\hss}}
+\setvalue{\??alignsimple\v!right }#1{{#1\hss}}
+\setvalue{\??alignsimple\v!left }#1{{\hss#1}}
+\setvalue{\??alignsimple\v!flushright}#1{{\hss#1}}
+\setvalue{\??alignsimple\v!flushleft }#1{{#1\hss}}
+\setvalue{\??alignsimple\v!middle }#1{{\hss#1\hss}}
\unexpanded\def\simplealignedbox#1#2%
- {\hbox to #1\csname\s!simple:\c!align:\ifcsname\s!simple:\c!align:#2\endcsname#2\else\v!right\fi\endcsname}
-
-% \setvalue{spac_align_set_ss_\v!right }#1#2{\let#1\relax\let#2\hss }
-% \setvalue{spac_align_set_ss_\v!left }#1#2{\let#1\hss \let#2\relax}
-% \setvalue{spac_align_set_ss_\v!flushright}#1#2{\let#1\hss \let#2\relax}
-% \setvalue{spac_align_set_ss_\v!flushleft }#1#2{\let#1\relax\let#2\hss }
-% \setvalue{spac_align_set_ss_\v!middle }#1#2{\let#1\hss \let#2\hss }
-% \setvalue{spac_align_set_ss_\v!low }#1#2{\let#1\vss \let#2\relax}
-% \setvalue{spac_align_set_ss_\v!high }#1#2{\let#1\relax\let#2\vss }
-% \setvalue{spac_align_set_ss_\v!lohi }#1#2{\let#1\vss \let#2\vss }
-% \setvalue{spac_align_set_ss_\s!unknown }#1#2{\let#1\relax\let#2\relax}
+ {\hbox to #1\csname\??alignsimple\ifcsname\??alignsimple#2\endcsname#2\else\v!right\fi\endcsname}
+% \installnamespace{alignsets}
+%
+% \setvalue{\??alignsets\v!right }#1#2{\let#1\relax\let#2\hss }
+% \setvalue{\??alignsets\v!left }#1#2{\let#1\hss \let#2\relax}
+% \setvalue{\??alignsets\v!flushright}#1#2{\let#1\hss \let#2\relax}
+% \setvalue{\??alignsets\v!flushleft }#1#2{\let#1\relax\let#2\hss }
+% \setvalue{\??alignsets\v!middle }#1#2{\let#1\hss \let#2\hss }
+% \setvalue{\??alignsets\v!low }#1#2{\let#1\vss \let#2\relax}
+% \setvalue{\??alignsets\v!high }#1#2{\let#1\relax\let#2\vss }
+% \setvalue{\??alignsets\v!lohi }#1#2{\let#1\vss \let#2\vss }
+% \setvalue{\??alignsets\s!unknown }#1#2{\let#1\relax\let#2\relax}
+%
% \unexpanded\def\spac_align_set_ss#1%
-% {\csname spac_align_set_ss_\ifcsname spac_align_set_ss_#1\endcsname#1\else\s!unknown\fi\endcsname}
+% {\csname\??alignsetss\ifcsname\??alignsetss#1\endcsname#1\else\s!unknown\fi\endcsname}
+
+% Some obsolete (old) helpers:
+
+\def\dodefinehbox[#1][#2]%
+ {\setvalue{hbox#1}##1{\hbox to #2{\begstrut##1\endstrut\hss}}}
+
+\unexpanded\def\definehbox
+ {\dodoubleargument\dodefinehbox}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/spac-chr.lua b/Master/texmf-dist/tex/context/base/spac-chr.lua
new file mode 100644
index 00000000000..00c3d676603
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/spac-chr.lua
@@ -0,0 +1,200 @@
+if not modules then modules = { } end modules ['spac-chr'] = {
+ version = 1.001,
+ comment = "companion to spac-chr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local byte, lower = string.byte, string.lower
+
+-- beware: attribute copying is bugged ... there will be a proper luatex helper
+-- for this
+
+-- to be redone: characters will become tagged spaces instead as then we keep track of
+-- spaceskip etc
+
+trace_characters = false trackers.register("typesetters.characters", function(v) trace_characters = v end)
+
+report_characters = logs.reporter("typesetting","characters")
+
+local nodes, node = nodes, node
+
+local set_attribute = node.set_attribute
+local has_attribute = node.has_attribute
+local insert_node_after = node.insert_after
+local remove_node = nodes.remove -- ! nodes
+local copy_node_list = node.copy_list
+
+local nodepool = nodes.pool
+local tasks = nodes.tasks
+
+local new_penalty = nodepool.penalty
+local new_glue = nodepool.glue
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+
+local space_skip_code = skipcodes["spaceskip"]
+
+local chardata = characters.data
+
+local typesetters = typesetters
+
+local characters = { }
+typesetters.characters = characters
+
+local fonthashes = fonts.hashes
+local fontparameters = fonthashes.parameters
+local fontcharacters = fonthashes.characters
+local fontquads = fonthashes.quads
+
+local a_character = attributes.private("characters")
+local a_alignstate = attributes.private("alignstate")
+
+local c_zero = byte('0')
+local c_period = byte('.')
+
+local function inject_quad_space(unicode,head,current,fraction)
+ local attr = current.attr
+ if fraction ~= 0 then
+ fraction = fraction * fontquads[current.font]
+ end
+ local glue = new_glue(fraction)
+-- glue.attr = copy_node_list(attr)
+ glue.attr = attr
+current.attr = nil
+ set_attribute(glue,a_character,unicode)
+ head, current = insert_node_after(head,current,glue)
+ return head, current
+end
+
+local function inject_char_space(unicode,head,current,parent)
+ local attr = current.attr
+ local font = current.font
+ local char = fontcharacters[font][parent]
+ local glue = new_glue(char and char.width or fontparameters[font].space)
+-- glue.attr = copy_node_list(current.attr)
+ glue.attr = current.attr
+current.attr = nil
+ set_attribute(glue,a_character,unicode)
+ head, current = insert_node_after(head,current,glue)
+ return head, current
+end
+
+local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink)
+ local attr = current.attr
+ local glue = new_glue(space,spacestretch,spaceshrink)
+ local penalty = new_penalty(10000)
+-- glue.attr = copy_node_list(attr)
+ glue.attr = attr
+current.attr = nil
+-- penalty.attr = attr
+ set_attribute(glue,a_character,unicode)
+ head, current = insert_node_after(head,current,penalty)
+ head, current = insert_node_after(head,current,glue)
+ return head, current
+end
+
+local methods = {
+
+ -- The next one uses an attribute assigned to the character but still we
+ -- don't have the 'local' value.
+
+ [0x00A0] = function(head,current) -- nbsp
+ local para = fontparameters[current.font]
+ if has_attribute(current,a_alignstate) == 1 then -- flushright
+ head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0)
+ current.subtype = space_skip_code
+ else
+ head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink)
+ end
+ return head, current
+ end,
+
+ [0x2000] = function(head,current) -- enquad
+ return inject_quad_space(0x2000,head,current,1/2)
+ end,
+
+ [0x2001] = function(head,current) -- emquad
+ return inject_quad_space(0x2001,head,current,1)
+ end,
+
+ [0x2002] = function(head,current) -- enspace
+ return inject_quad_space(0x2002,head,current,1/2)
+ end,
+
+ [0x2003] = function(head,current) -- emspace
+ return inject_quad_space(0x2003,head,current,1)
+ end,
+
+ [0x2004] = function(head,current) -- threeperemspace
+ return inject_quad_space(0x2004,head,current,1/3)
+ end,
+
+ [0x2005] = function(head,current) -- fourperemspace
+ return inject_quad_space(0x2005,head,current,1/4)
+ end,
+
+ [0x2006] = function(head,current) -- sixperemspace
+ return inject_quad_space(0x2006,head,current,1/6)
+ end,
+
+ [0x2007] = function(head,current) -- figurespace
+ return inject_char_space(0x2007,head,current,c_zero)
+ end,
+
+ [0x2008] = function(head,current) -- punctuationspace
+ return inject_char_space(0x2008,head,current,c_period)
+ end,
+
+ [0x2009] = function(head,current) -- breakablethinspace
+ return inject_quad_space(0x2009,head,current,1/8) -- same as next
+ end,
+
+ [0x200A] = function(head,current) -- hairspace
+ return inject_quad_space(0x200A,head,current,1/8) -- same as previous (todo)
+ end,
+
+ [0x200B] = function(head,current) -- zerowidthspace
+ return inject_quad_space(0x200B,head,current,0)
+ end,
+
+ [0x202F] = function(head,current) -- narrownobreakspace
+ return inject_nobreak_space(0x202F,head,current,fontquads[current.font]/8)
+ end,
+
+ [0x205F] = function(head,current) -- math thinspace
+ return inject_nobreak_space(0x205F,head,current,fontparameters[current.font].space/8)
+ end,
+
+ -- [0xFEFF] = function(head,current) -- zerowidthnobreakspace
+ -- return head, current
+ -- end,
+
+}
+
+function characters.handler(head)
+ local current = head
+ local done = false
+ while current do
+ local next = current.next
+ local id = current.id
+ if id == glyph_code then
+ local char = current.char
+ local method = methods[char]
+ if method then
+ if trace_characters then
+ report_characters("replacing character U+%04X (%s)",char,lower(chardata[char].description))
+ end
+ head = method(head,current)
+ head = remove_node(head,current,true)
+ done = true
+ end
+ end
+ current = next
+ end
+ return head, done
+end
diff --git a/Master/texmf-dist/tex/context/base/spac-chr.mkiv b/Master/texmf-dist/tex/context/base/spac-chr.mkiv
new file mode 100644
index 00000000000..e2ed1252280
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/spac-chr.mkiv
@@ -0,0 +1,90 @@
+%D \module
+%D [ file=spac-chr,
+%D version=2011.05.24, % code moved from core-spa.mkiv
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Characters,
+%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 Spacing Macros / Characters}
+
+\unprotect
+
+\registerctxluafile{spac-chr}{1.001}
+
+\definesystemattribute[characters][public]
+
+%D The nobreakspace is special as it needs to keep track of the space being
+%D flexible. Another option is to use space (glue) nodes and tag them as characters
+%D instead. No big deal but takes a moment of coding. So, as a prelude we
+%D tag the nobreakspace only. Interesting is that it also fits better in the
+%D tagging mechanism.
+%D
+%D But we need to do some checking as from then on we no longer can compare
+%D them in a string. So this needs thinking. Not that we can compare the
+%D nobreakspace now anyway.
+
+% \unexpanded\def\specialspacecharacter#1{\begingroup\attribute\charactersattribute#1\ \endgroup}
+%
+% \unexpanded\edef\nobreakspace {\specialspacecharacter{"00A0}} % 1 = left
+% \unexpanded\edef\ideographicspace {\specialspacecharacter{"2000}}
+% \unexpanded\edef\ideographichalffillspace{\specialspacecharacter{"2001}}
+% \unexpanded\edef\twoperemspace {\specialspacecharacter{"2002}}
+% \unexpanded\edef\threeperemspace {\specialspacecharacter{"2004}}
+% \unexpanded\edef\fourperemspace {\specialspacecharacter{"2005}}
+% \unexpanded\edef\sixperemspace {\specialspacecharacter{"2006}}
+% \unexpanded\edef\figurespace {\specialspacecharacter{"2007}}
+% \unexpanded\edef\punctuationspace {\specialspacecharacter{"2008}}
+% \unexpanded\edef\breakablethinspace {\specialspacecharacter{"2009}}
+% \unexpanded\edef\hairspace {\specialspacecharacter{"200A}}
+% \unexpanded\edef\zerowidthspace {\specialspacecharacter{"200B}}
+% \unexpanded\edef\zwnj {\specialspacecharacter{"200C}}
+% \unexpanded\edef\zwj {\specialspacecharacter{"200D}}
+% \unexpanded\edef\narrownobreakspace {\specialspacecharacter{"202F}}
+
+% This does not work as spaceskip is only inserted in the case of raggedleft
+% and we need to be able to figure out all of them. Which makes me wonder ...
+% can't we just always set spaceskip to some value?
+
+% Making them active is also not an option unless we do that in every
+% catcode vector.
+
+% \nobreakspace {\begingroup\setalignstateattribute\utfchar{"00A0}\endgroup} % 1 = left
+
+\edef\nobreakspace {\utfchar{"00A0}}
+\edef\ideographicspace {\utfchar{"2000}}
+\edef\ideographichalffillspace{\utfchar{"2001}}
+\edef\twoperemspace {\utfchar{"2002}}
+\edef\threeperemspace {\utfchar{"2004}}
+\edef\fourperemspace {\utfchar{"2005}}
+\edef\sixperemspace {\utfchar{"2006}}
+\edef\figurespace {\utfchar{"2007}}
+\edef\punctuationspace {\utfchar{"2008}}
+\edef\breakablethinspace {\utfchar{"2009}}
+\edef\hairspace {\utfchar{"200A}}
+\edef\zerowidthspace {\utfchar{"200B}}
+\edef\zwnj {\utfchar{"200C}}
+\edef\zwj {\utfchar{"200D}}
+\edef\narrownobreakspace {\utfchar{"202F}}
+
+%edef\zerowidthnobreakspace {\utfchar{"FEFF}}
+
+\unexpanded\def\zerowidthnobreakspace{\penalty\plustenthousand\kern\zeropoint}
+
+% Shortcuts:
+
+% unexpanded as otherwise we need to intercept / cleanup a lot
+
+\unexpanded\def~{\nobreakspace}
+
+% Goodies:
+
+\unexpanded\def\fiveperemspace{\hskip\dimexpr\emwidth/5\relax}
+
+\protect \endinput
+
diff --git a/Master/texmf-dist/tex/context/base/spac-def.mkiv b/Master/texmf-dist/tex/context/base/spac-def.mkiv
index 3aa85dda515..4cd7b1d1c76 100644
--- a/Master/texmf-dist/tex/context/base/spac-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/spac-def.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,59 +13,64 @@
\writestatus{loading}{ConTeXt Spacing Macros / Definitions}
+% todo: move resetters to other modules
+
\unprotect
-\def\forgeteverypar
+\unexpanded\def\forgeteverypar
{\everypar{\the\neverypar}}
-\def\forgetparindent
- {\forgeteverypar
- \indentfirstparagraphtrue % recently added
- \let\currentindentation\v!none
- \ctxparindent\zeropoint
- \parindent\zeropoint\relax}
+% worth trying:
+%
+% \unexpanded\def\forgeteverypar
+% {\everypar\neverypar}
-\def\forgetparskip
- {\let\currentwhitespace\v!none
- \ctxparskip\zeropoint
- \parskip\zeropoint\relax}
+\unexpanded\def\forgetparskip
+ {\s_spac_whitespace_parskip\zeropoint
+ \parskip\zeropoint
+ \let\v_spac_whitespace_current\v!none}
-\def\forgetbothskips
- {\tolerance1500
- \leftskip\zeropoint
- \rightskip\zeropoint\relax}
+\unexpanded\def\forgetbothskips
+ {\leftskip\zeropoint
+ \rightskip\zeropoint
+ \relax}
-\def\forgetspacing
+\unexpanded\def\forgethorizontalstretch
{\emergencystretch\zeropoint}
+\unexpanded\def\forgetverticalstretch
+ {\spacing\plusone}
+
\newif\ifforgotten % rather good signal for inner
-\appendtoks \forgottentrue \to \everyforgetall
-\appendtoks \forgetragged \to \everyforgetall
-\appendtoks \forgetparskip \to \everyforgetall
-\appendtoks \forgetparindent \to \everyforgetall
-\appendtoks \forgetbothskips \to \everyforgetall
-\appendtoks \forgetspacing \to \everyforgetall % i.v.m. funny spacing in pagebody
-\appendtoks \spacing\plusone \to \everyforgetall % new per 10/08/2004, else problems in otr / !! needed
-\appendtoks \everypar\emptytoks \to \everyforgetall % indeed!
+% This will become better: several resetters that do all in once as currently there is
+% redundant code.
+\appendtoks \forgottentrue \to \everyforgetall
+\appendtoks \forgetragged \to \everyforgetall
+\appendtoks \forgetparskip \to \everyforgetall
+\appendtoks \forgetparindent \to \everyforgetall
+\appendtoks \forgetbothskips \to \everyforgetall
+\appendtoks \forgethorizontalstretch \to \everyforgetall % needed in pagebody
+\appendtoks \forgetverticalstretch \to \everyforgetall % needed in otr
+\appendtoks \everypar\emptytoks \to \everyforgetall % indeed!
-\appendtoks \spacing\plusone \to \everybodyfont
+\appendtoks \forgetverticalstretch \to \everybodyfont
\appendtoks \presetnormallineheight \to \everybodyfont
-\appendtoks \setnormalbaselines \to \everybodyfont % check if redundant
-\appendtoks \setstrut \to \everybodyfont % check if redundant
-\appendtoks \settopskip \to \everybodyfont
-\appendtoks \setmaxdepth \to \everybodyfont
-\appendtoks \simplesetupindenting \to \everybodyfont
-\appendtoks \simplesetupblank \to \everybodyfont
-\appendtoks \simplesetupwhitespace \to \everybodyfont
-\appendtoks \simplesetupspacing \to \everybodyfont % nieuw
+\appendtoks \setnormalbaselines \to \everybodyfont % check if redundant (\forgetverticalstretch does it too)
+\appendtoks \setstrut \to \everybodyfont % check if redundant (\forgetverticalstretch does it too)
+\appendtoks \settopskip \to \everybodyfont % factors set in \forgetverticalstretch
+\appendtoks \setmaxdepth \to \everybodyfont % factors set in \forgetverticalstretch
+\appendtoks \synchronizeindenting \to \everybodyfont
+\appendtoks \synchronizeblank \to \everybodyfont
+\appendtoks \synchronizewhitespace \to \everybodyfont
+\appendtoks \synchronizespacecodes \to \everybodyfont % not needed, frozen factors
\appendtoks \setrelativeinterlinespace \to \everybodyfont
-\appendtoks \updateraggedskips \to \everyfontswitch % under test
-\prependtoks \let\par\endgraf \to \everypagebody % see \fillinline
-\appendtoks \simplesetupspacing \to \everydefinedfont
-
+\appendtoks \updateraggedskips \to \everyfontswitch % under test
+\prependtoks \let\par\normalpar \to \everybeforepagebody % see \fillinline (was endgraf)
+\appendtoks \synchronizespacecodes \to \everydefinedfont % not needed, frozen factors
+
\setupwhitespace
[\v!none]
@@ -75,32 +80,31 @@
\setupindenting
[\v!none]
-\setupvspacing
- [\v!standard,
- \v!big]
+\setupblank
+ [\v!big] % alternatively [\v!standard]
-\definevspacing[\v!default] [\currentblank]
-\definevspacing[\v!before] [\v!default]
-\definevspacing[\v!inbetween][\v!default]
-\definevspacing[\v!after] [\v!before]
+\defineblank[\v!default] [\v!big] % todo: needs to adapt to \setupblank
+\defineblank[\v!before] [\v!default] % but we need to avoid circular references
+\defineblank[\v!inbetween][\v!default] % then
+\defineblank[\v!after] [\v!before]
\setupinterlinespace
- [\c!minheight=0pt, % only special purpose
- \c!mindepth=0pt, % only special purpose
+ [\c!minheight=\zeropoint, % only special purpose
+ \c!mindepth=\zeropoint, % only special purpose
\c!height=.72,
\c!depth=.28,
\c!top=1.0,
\c!bottom=0.4,
- \c!distance=1pt,
- \c!line=2.8ex,
- \c!stretch=0]
+ \c!distance=\onepoint,
+ \c!line=2.8\exheight,
+ \c!stretch=\zerocount]
\setupnarrower
[\c!before=\endgraf,
\c!after=\endgraf,
- \c!left=1.5em,
- \c!right=1.5em,
- \c!middle=1.5em]
+ \c!left=1.5\emwidth,
+ \c!right=1.5\emwidth,
+ \c!middle=1.5\emwidth]
\setuptolerance
[\v!horizontal,\v!verystrict]
diff --git a/Master/texmf-dist/tex/context/base/spac-fnt.mkiv b/Master/texmf-dist/tex/context/base/spac-fnt.mkiv
deleted file mode 100644
index c268d7893cf..00000000000
--- a/Master/texmf-dist/tex/context/base/spac-fnt.mkiv
+++ /dev/null
@@ -1,94 +0,0 @@
-%D \module
-%D [ file=spac-fnt,
-%D version=2009.10.16, % 1997.03.31, was core-spa.tex
-%D title=\CONTEXT\ Spacing Macros,
-%D subtitle=Fonts,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 Spacing Macros / Fonts}
-
-%D For historic reasons here, will move and/or disappear:
-
-\unprotect
-
-\let\dostopattributes\relax % in case these commands end up in an edef
-
-\unexpanded\def\@@dostopattributes
- {\stopcolor
- \finishparbasedattributes
- \endgroup}
-
-\unexpanded\def\@@nostopattributes
- {\finishparbasedattributes
- \endgroup}
-
-\unexpanded\def\doattributes#1#2#3#4%
- {\dostartattributes{#1}{#2}{#3}{#4}\dostopattributes}
-
-% An even faster \ETEX\ version:
-
-\unexpanded\def\dostartattributes#1#2#3%
- {\begingroup % geen \bgroup, anders in mathmode lege \hbox
- \ifincolor
- \ifcsname#1#3\endcsname
- \let\dostopattributes\@@dostopattributes
- \faststartcolor[\csname#1#3\endcsname]%
- \else
- \let\dostopattributes\@@nostopattributes
- \fi
- \else
- \let\dostopattributes\@@nostopattributes
- \fi
- \ifcsname#1#2\endcsname
- % \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname
- \@EA\doconvertfont\csname#1#2\@EA\endcsname
- \fi}
-
-\unexpanded\def\@@dostopattributes
- {\faststopcolor
- \finishparbasedattributes
- \endgroup}
-
-\unexpanded\def\@@nostopattributes
- {\finishparbasedattributes
- \endgroup}
-
-%D Bonus macro, see core-sec.tex
-
-\newconditional\fontattributeisset
-
-\unexpanded\def\dosetfontattribute#1#2%
- {\ifcsname#1#2\endcsname
- \settrue\fontattributeisset % reset is done elsewhere
- \@EA\doconvertfont\csname#1#2\@EA\endcsname
- \fi\empty}
-
-%D Since this happens a lot, and sometimes large arguments
-%D are passed in \type {#4}, we just copy some code:
-
-\unexpanded\def\doattributes#1#2#3#4%
- {\begingroup % geen \bgroup, anders in mathmode lege \hbox
- \ifincolor
- \ifcsname#1#3\endcsname
- \let\dostopattributes\@@dostopattributes
- \faststartcolor[\csname#1#3\endcsname]%
- \else
- \let\dostopattributes\endgroup
- \fi
- \else
- \let\dostopattributes\endgroup
- \fi
- \ifcsname#1#2\endcsname
- % \@EAEAEA\doconvertfont\@EA\@EA\csname#1#2\endcsname
- \@EA\doconvertfont\csname#1#2\@EA\endcsname
- \fi
- {#4}%
- \dostopattributes}
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/spac-gen.mkii b/Master/texmf-dist/tex/context/base/spac-gen.mkii
index 4e7b3810c5f..91e37925041 100644
--- a/Master/texmf-dist/tex/context/base/spac-gen.mkii
+++ b/Master/texmf-dist/tex/context/base/spac-gen.mkii
@@ -5,7 +5,7 @@
%D subtitle=Spacing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spac-grd.mkii b/Master/texmf-dist/tex/context/base/spac-grd.mkii
index 249e2e4308e..97699de51c4 100644
--- a/Master/texmf-dist/tex/context/base/spac-grd.mkii
+++ b/Master/texmf-dist/tex/context/base/spac-grd.mkii
@@ -5,7 +5,7 @@
%D subtitle=Grid Snapping (Experimental),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spac-grd.mkiv b/Master/texmf-dist/tex/context/base/spac-grd.mkiv
index 8701f4d7ee2..487521f6cc0 100644
--- a/Master/texmf-dist/tex/context/base/spac-grd.mkiv
+++ b/Master/texmf-dist/tex/context/base/spac-grd.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Grid Snapping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -100,27 +100,41 @@
% \definecolor[GridLineColor][red]
% \definecolor[GridTextColor][blue]
-\let\thetopbaselinecorrection \!!zeropoint
-\let\thebotbaselinecorrection \!!zeropoint
-\let\thenegtopbaselinecorrection\!!zeropoint
-\let\thenegbotbaselinecorrection\!!zeropoint
-
-\def\setbaselinecorrections
- {\setbox0\hbox{\setstrut\strut}%
- \setbox2\hbox{(}%
- \dimen0\ht0\advance\dimen0 -\ht2
- \ifdim\dimen0<\zeropoint\dimen0\zeropoint\fi
- \dimen2\dp0\advance\dimen2 -\dp2
- \ifdim\dimen2<\zeropoint\dimen2\zeropoint\fi
- \edef\thetopbaselinecorrection {\the\dimen0}\dimen0-\dimen0
- \edef\thebotbaselinecorrection {\the\dimen2}\dimen2-\dimen2
- \edef\thenegtopbaselinecorrection{\the\dimen0}%
- \edef\thenegbotbaselinecorrection{\the\dimen2}}
-
-\def\dotopbaselinecorrection {\kern\thetopbaselinecorrection}
-\def\dobotbaselinecorrection {\kern\thebotbaselinecorrection}
-\def\donegtopbaselinecorrection{\kern\thenegtopbaselinecorrection}
-\def\donegbotbaselinecorrection{\kern\thenegbotbaselinecorrection}
+\newdimen\d_spac_lines_correction_before
+\newdimen\d_spac_lines_correction_after
+
+\newbox \b_spac_lines_correction_before
+\newbox \b_spac_lines_correction_after
+
+\def\spac_lines_initialize_corrections
+ {\setbox\b_spac_lines_correction_before\hbox{\setstrut\strut}%
+ \setbox\b_spac_lines_correction_after \hbox{(}%
+ \d_spac_lines_correction_before\dimexpr\ht\b_spac_lines_correction_before-\ht\b_spac_lines_correction_after\relax
+ \d_spac_lines_correction_after \dimexpr\dp\b_spac_lines_correction_before-\dp\b_spac_lines_correction_after\relax
+ \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
+% \startframedtext test \stopframedtext
+% \input ward \par
+% \startlinecorrection \framed{xxx} \stoplinecorrection
+% \input ward \par
+%
+% \setupwhitespace[big]
+%
+% \input ward \par
+% \startframedtext test \stopframedtext
+% \input ward \par
+% \startlinecorrection \framed{xxx} \stoplinecorrection
+% \input ward \par
+
+\unexpanded\def\dotopbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_before]}
+\unexpanded\def\dobotbaselinecorrection{\expandafter\blank\expandafter[\the\d_spac_lines_correction_after ]}
\def\showbaselinecorrection
{\def\dobaselinecorrection % visualization is not watertight!
@@ -135,11 +149,11 @@
\egroup
\prevdepth\strutdp}%
\def\dotopbaselinecorrection
- {\hrule\!!height\thetopbaselinecorrection}%
+ {\hrule\!!height\d_spac_lines_correction_before}%
\def\dobotbaselinecorrection
- {\hrule\!!height\thebotbaselinecorrection}}
+ {\hrule\!!height\d_spac_lines_correction_after}}
-\def\dobaselinecorrection
+\def\dobaselinecorrection % beware, this one is redefined / used locally elsewhere
{\ifdim\prevdepth>\zeropoint\kern-\prevdepth\fi
\kern\strutdp
\prevdepth\strutdp}
@@ -227,7 +241,7 @@
\def\forcedtopbaselinecorrection
{\ifvmode
\bgroup
- \setbaselinecorrections
+ \spac_lines_initialize_corrections
\whitespace % no longer ok
\nointerlineskip
\dotopbaselinecorrection
@@ -237,7 +251,7 @@
\def\botbaselinecorrection
{\ifvmode
\bgroup
- \setbaselinecorrections
+ \spac_lines_initialize_corrections
\dobotbaselinecorrection
\allowbreak % new, otherwise problems when many in a row
\prevdepth\strutdp
@@ -245,27 +259,6 @@
\fi}
\let\forcedbotbaselinecorrection\botbaselinecorrection
-
-% experiment, todo: proper mkiv mechanism
-%
-% \input ward \par
-% \startframedtext test \stopframedtext
-% \input ward \par
-% \startlinecorrection \framed{xxx} \stoplinecorrection
-% \input ward \par
-%
-% \setupwhitespace[big]
-%
-% \input ward \par
-% \startframedtext test \stopframedtext
-% \input ward \par
-% \startlinecorrection \framed{xxx} \stoplinecorrection
-% \input ward \par
-
-\def\dotopbaselinecorrection {\blank[\thetopbaselinecorrection ]}
-\def\dobotbaselinecorrection {\blank[\thebotbaselinecorrection ]}
-\def\donegtopbaselinecorrection{\blank[\thenegtopbaselinecorrection]}
-\def\donegbotbaselinecorrection{\blank[\thenegbotbaselinecorrection]}
% nointerlineskip
%
@@ -277,8 +270,8 @@
\def\forcedtopbaselinecorrection
{\ifvmode
\bgroup
- \setbaselinecorrections
- \vspacing[white]
+ \spac_lines_initialize_corrections
+ \vspacing[\v!white]
% \nointerlineskip %
\dotopbaselinecorrection
\egroup
@@ -291,7 +284,7 @@
\vspacing[\the\dimexpr\strutdp\relax]%
\fi
\prevdepth\strutdp}
-
+
\let\normalstartbaselinecorrection\startbaselinecorrection
\unexpanded\def\startbaselinecorrection
diff --git a/Master/texmf-dist/tex/context/base/spac-hor.mkiv b/Master/texmf-dist/tex/context/base/spac-hor.mkiv
index 39edaa2ff00..eeb5cadfd5b 100644
--- a/Master/texmf-dist/tex/context/base/spac-hor.mkiv
+++ b/Master/texmf-dist/tex/context/base/spac-hor.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Horizontal,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,152 +17,176 @@
\registerctxluafile{spac-hor}{1.001}
-\let\currentindentation\empty % amount/keyword
-\let\currentindenting \empty % method
+\let\v_spac_indentation_current\empty % amount/keyword
-\newdimen \ctxparindent
-\parindent\ctxparindent % for the show
+\newdimen \d_spac_indentation_par
+\parindent\d_spac_indentation_par % for the show
-\newif\ifindentfirstparagraph \indentfirstparagraphtrue
-
-\newconstant\indentingtogglestate
+\newconditional\c_spac_indentation_indent_first \settrue\c_spac_indentation_indent_first
+\newconstant \c_spac_indentation_toggle_state
%D After a blank or comparable situation (left side floats) we
%D need to check if the next paragraph has to be indented.
-\def\presetindentation
- {\doifoutervmode{\ifindentfirstparagraph\else\noindentation\fi}}
+\unexpanded\def\presetindentation
+ {\doifoutervmode{\ifconditional\c_spac_indentation_indent_first\else\spac_indentation_variant_no\fi}}
-% we need a better everypar model: for each option a switch, which we
-% set to false with \forgetall and can enable when needed (context 4);
-% that way we can control the order of execution of options
+\unexpanded\def\setupindenting
+ {\doifnextoptionalelse\spac_indentation_setup_options\spac_indentation_setup_size}
-\def\checkeverypar % currently a hack
- {\ifzeropt\parindent\else
- \doifsometokselse\everypar\donothing\docheckupcomingindentation
- \fi}
+\def\spac_indentation_setup_size
+ {\assigndimension\v_spac_indentation_current\d_spac_indentation_par{1\emwidth}{1.5\emwidth}{2\emwidth}}
-\def\docheckupcomingindentation
- {\appendtoks\checkindentation\to\everypar}
+\let\synchronizeindenting\spac_indentation_setup_size
-\definecomplexorsimple\setupindenting
+\let\m_spac_indentation_options\empty
-\def\complexsetupindenting[#1]%
- {\edef\currentindenting{#1}%
- \ifx\currentindenting\empty \else
- \doapplycurrentindenting
+\def\spac_indentation_setup_options[#1]%
+ {\edef\m_spac_indentation_options{#1}% comma separated list
+ \ifx\m_spac_indentation_options\empty \else
+ \spac_indentation_setup_indeed
\fi}
-\def\doapplycurrentindenting
- {% not here: \indentfirstparagraphtrue
- % not here: \parindent\ctxparindent
- % not here: \indentingtogglestate\zerocount
- % we use commacommand in order to catch #1 being a command (expanded parameter)
- \processcommacommand[\currentindenting]\docomplexsetupindentingA % catch small, medium, etc
- \processcommacommand[\currentindenting]\docomplexsetupindentingB % catch rest
- \checkeverypar % only when non-empty #1
- \ifindentfirstparagraph\else\noindentation\fi % added
- \toggleindentation}
-
-\def\docomplexsetupindentingA#1%
- {\ifcsname\??in:#1\endcsname
- % case b
+\def\spac_indentation_setup_indeed
+ {% not here: \settrue\c_spac_indentation_indent_first
+ % not here: \parindent\d_spac_indentation_par
+ % not here: \c_spac_indentation_toggle_state\zerocount
+ \processcommacommand[\m_spac_indentation_options]\spac_indentation_apply_step_one % catch small, medium, etc
+ \processcommacommand[\m_spac_indentation_options]\spac_indentation_apply_step_two % catch rest
+ \ifzeropt\parindent\else
+ \doifemptytoks\everypar\spac_indentation_set_everypar
+ \fi
+ \ifconditional\c_spac_indentation_indent_first\else
+ \spac_indentation_variant_no
+ \fi
+ \spac_indentation_check_toggle}
+
+\def\spac_indentation_set_everypar
+ {\everypar{\checkindentation}}
+
+\def\spac_indentation_apply_step_one#1%
+ {\ifcsname\??indentingmethod#1\endcsname
+ % case two
\else
- \edef\currentindentation{#1}%
- \let\normalindentation\currentindentation
- \simplesetupindenting
+ \edef\v_spac_indentation_current{#1}% single entry in list
+ \let\normalindentation\v_spac_indentation_current
+ \spac_indentation_setup_size
\fi}
-\def\docomplexsetupindentingB#1%
- {\ifcsname\??in:#1\endcsname
- \csname\??in:#1\endcsname
+\def\spac_indentation_apply_step_two#1%
+ {\ifcsname\??indentingmethod#1\endcsname
+ \csname\??indentingmethod#1\endcsname
\else
- % case a
+ % case one
\fi}
-\def\simplesetupindenting % empty case, a it strange, needed this way?
- {\assigndimension\currentindentation\ctxparindent{1em}{1.5em}{2em}}
-
-\def\indenting % kind of obsolete
- {\dosingleargument\complexsetupindenting}
+\unexpanded\def\indenting % kind of obsolete
+ {\doifnextoptionalelse\spac_indentation_setup_options\relax}
% use \noindentation to suppress next indentation
-\unexpanded\def\defineindentingmethod[#1]#2%
- {\setvalue{\??in:#1}{#2}}
+\installcorenamespace{indentingmethod}
-\defineindentingmethod [\v!no] {\parindent\zeropoint}% was: \ctxparindent\noindent}
-\defineindentingmethod [\v!not] {\parindent\zeropoint}% was: \ctxparindent\noindent}
+\unexpanded\def\installindentingmethod#1#2%
+ {\setvalue{\??indentingmethod#1}{#2}}
-\defineindentingmethod [\v!first] {\indentfirstparagraphtrue}
-\defineindentingmethod [\v!next] {\indentfirstparagraphfalse}
+\installindentingmethod \v!no {\parindent\zeropoint}
+\installindentingmethod \v!not {\parindent\zeropoint}
-\defineindentingmethod [\v!yes] {\parindent\ctxparindent\relax} % no \indent !
-\defineindentingmethod [\v!always] {\parindent\ctxparindent\relax} % no \indent !
+\installindentingmethod \v!first {\settrue\c_spac_indentation_indent_first}
+\installindentingmethod \v!next {\setfalse\c_spac_indentation_indent_first}
-\defineindentingmethod [\v!never] {\parindent\zeropoint\relax % no \indent !
- \indentingtogglestate\zerocount}
+\installindentingmethod \v!yes {\parindent\d_spac_indentation_par\relax} % not \indent !
+\installindentingmethod \v!always{\parindent\d_spac_indentation_par\relax} % not \indent !
-\defineindentingmethod [\v!odd] {\indentingtogglestate\plusone}
-\defineindentingmethod [\v!even] {\indentingtogglestate\plustwo}
+\installindentingmethod \v!never {\parindent\zeropoint\relax % no \indent !
+ \c_spac_indentation_toggle_state\zerocount}
-\defineindentingmethod [\v!normal] {\ifx\normalindentation\empty\else
- \let\currentindentation\normalindentation
- \simplesetupindenting
- \fi}
+\installindentingmethod \v!odd {\c_spac_indentation_toggle_state\plusone}
+\installindentingmethod \v!even {\c_spac_indentation_toggle_state\plustwo}
-\defineindentingmethod [\v!reset] {\indentfirstparagraphtrue
- \parindent\zeropoint
- \indentingtogglestate\zerocount}
+\installindentingmethod \v!normal{\ifx\normalindentation\empty\else
+ \let\v_spac_indentation_current\normalindentation
+ \simplesetupindenting
+ \fi}
-\def\noindenting{\indenting[\v!no, \v!next ]}
-\def\doindenting{\indenting[\v!yes,\v!first]}
+\installindentingmethod \v!reset {\settrue\c_spac_indentation_indent_first
+ \parindent\zeropoint
+ \c_spac_indentation_toggle_state\zerocount}
-%D This one sets up the local indentation behaviour (i.e. either or not
-%D a next paragraph will be indented).
+\installindentingmethod \v!toggle{\parindent\ifdim\parindent=\zeropoint
+ \d_spac_indentation_par
+ \else
+ \zeropoint
+ \fi\relax}
-\def\dochecknextindentation#1% internal one
- {\checknextindentation[\csname#1\c!indentnext\endcsname]}
+\unexpanded\def\noindenting{\indenting[\v!no, \v!next ]}
+\unexpanded\def\doindenting{\indenting[\v!yes,\v!first]}
-\setvalue{\??in->\s!empty}{}
-\setvalue{\??in->\v!yes }{\doindentation}
-\setvalue{\??in->\v!no }{\noindentation}
-\setvalue{\??in->\v!auto }{\autoindentation}
+%D Here come the handlers (still rather messy ... we need states).
-\unexpanded\def\checknextindentation[#1]%
- {\csname\??in->\ifcsname\??in->#1\endcsname#1\else\s!empty\fi\endcsname}
+\newif\ifindentation \indentationtrue % will become a mode
+
+\let\checkindentation\relax
+
+\def\spac_indentation_remove
+ {\ifdim\parindent=\zeropoint \else
+ \begingroup
+ \setbox\scratchbox\lastbox
+ \endgroup
+ \fi}
-%D Here come the handlers.
+\def\spac_indentation_kill_indeed
+ {\global\indentationfalse
+ \spac_indentation_remove}
-\newif\ifindentation \indentationtrue % documenteren, naar buiten
+\def\spac_indentation_do_toggle_indeed
+ {\global\indentationfalse
+ \global\let\checkindentation\spac_indentation_no_toggle_indeed
+ \spac_indentation_remove}
-\let\checkindentation\relax
+\def\spac_indentation_no_toggle_indeed
+ {\global\indentationtrue
+ \global\let\checkindentation\spac_indentation_do_toggle_indeed}
+
+\def\spac_indentation_do_indeed
+ {\global\indentationtrue}
-\ifx\autoindentation\undefined \let\autoindentation\relax \fi % hook
+\def\spac_indentation_do_toggle
+ {\global\let\checkindentation\spac_indentation_do_toggle_indeed}
-\def\doindentation
- {\gdef\checkindentation{\global\indentationtrue}}
+\def\spac_indentation_no_toggle
+ {\global\let\checkindentation\spac_indentation_no_toggle_indeed}
-\def\noindentation % made global
+\def\spac_indentation_check_toggle
+ {\ifcase\c_spac_indentation_toggle_state
+ % nothing
+ \or
+ \spac_indentation_no_toggle
+ \or
+ \spac_indentation_do_toggle
+ \fi}
+
+\def\spac_indentation_variant_yes
+ {\global\let\checkindentation\spac_indentation_do_indeed}
+
+\def\spac_indentation_no_next_check
+ {\spac_indentation_remove
+ \global\let\checkindentation\spac_indentation_do_indeed}
+
+\def\spac_indentation_variant_no % made global
{\ifinpagebody \else
\global\indentationfalse
- \gdef\checkindentation
- {\donoindentation
- \gdef\checkindentation{\global\indentationtrue}}%
+ \global\let\checkindentation\spac_indentation_no_next_check
\fi}
\def\nonoindentation % bv bij floats
{\ifinpagebody \else
\global\indentationtrue
- \gdef\checkindentation{\global\indentationtrue}%
- \fi}
-
-\def\donoindentation
- {\ifdim\parindent=\zeropoint \else
- \bgroup \setbox\scratchbox\lastbox \egroup
+ \global\let\checkindentation\spac_indentation_do_indeed
\fi}
-\def\indentation
+\def\spac_indentation_variant_force
{\ifvmode \ifdim\parindent=\zeropoint \else
% was : \hskip\parindent
% can be: \indent
@@ -170,52 +194,52 @@
\noindent\hskip\parindent
\fi \fi}
-\def\toggleindentation % does not play well with noindentation
- {\ifcase\indentingtogglestate
- % nothing
- \or
- \notoggleindentation
- \or
- \dotoggleindentation
- \fi}
-
-\def\dokillindentation
- {\gdef\checkindentation{\global\indentationfalse\donoindentation}}
-
-\def\dotoggleindentation
- {\gdef\checkindentation{\global\indentationfalse\notoggleindentation\donoindentation}}
-
-\def\notoggleindentation
- {\gdef\checkindentation{\global\indentationtrue\dotoggleindentation}}
-
\appendtoks
- \pushmacro\checkindentation
- \pushmacro\ifindentation
+ \pushmacro\checkindentation
+ \pushmacro\ifindentation
\to \everypushsomestate
\appendtoks
- \popmacro\ifindentation
- \popmacro\checkindentation
+ \popmacro\ifindentation
+ \popmacro\checkindentation
\to \everypopsomestate
-
-% This is a user requested hack (using the auto-hook).
-\newconditional\recheckindentationmode
+% public:
-\def\dontrechecknextindentation
- {\global\setfalse\recheckindentationmode}
+\let\indentation \spac_indentation_variant_force
+\let\noindentation\spac_indentation_variant_no % public
+\let\doindentation\spac_indentation_variant_yes % public
-\def\dorechecknextindentation
- {\ifconditional\recheckindentationmode
- \dontrechecknextindentation
- \expandafter\doautoindentation
- \fi}
+\def\dontrechecknextindentation % public (in macros)
+ {\global\let\dorechecknextindentation\relax}
+
+\let\dorechecknextindentation\relax % public (in macros)
+
+\def\spac_indentation_check_next_indentation
+ {\global\let\dorechecknextindentation\relax
+ \doifnextcharelse\par\donothing\spac_indentation_variant_no} % messy check as next is seldom \par
+
+\def\spac_indentation_variant_auto
+ {\global\let\dorechecknextindentation\spac_indentation_check_next_indentation}
-\def\doautoindentation
- {\doifnextcharelse\par\donothing\noindentation}
+%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]%
+ {\csname\??indentnext\ifcsname\??indentnext#1\endcsname#1\fi\endcsname}
+
+\unexpanded\def\useindentnextparameter#1% new, the more efficient variant
+ {\edef\p_indentnext{#1\c!indentnext}%
+ \ifx\p_indentnext\empty\else
+ \csname\??indentnext\ifcsname\??indentnext\p_indentnext\endcsname\p_indentnext\fi\endcsname
+ \fi}
-\def\autoindentation
- {\global\settrue\recheckindentationmode}
+\letvalue{\??indentnext }\donothing
+\letvalue{\??indentnext\v!yes }\spac_indentation_variant_yes
+\letvalue{\??indentnext\v!no }\spac_indentation_variant_no
+\letvalue{\??indentnext\v!auto}\spac_indentation_variant_auto
%D An example of usage:
%D
@@ -254,7 +278,17 @@
%D \input tufte \startformula a = b \stopformula
%D \stoptyping
-\def\softbreak
+% maybe an everyforgetparindent
+
+\unexpanded\def\forgetparindent
+ {\settrue\c_spac_indentation_indent_first % recently added
+ \d_spac_indentation_par\zeropoint
+ \parindent\zeropoint
+ \let\v_spac_indentation_current\v!none}
+
+%D Helper:
+
+\unexpanded\def\softbreak
{\relax\ifhmode\hskip\parfillskip\break\fi}
%D \macros
@@ -266,40 +300,46 @@
%D Hm ... todo:
-\sfcode`\)=0
-\sfcode`\'=0
-\sfcode`\]=0
+\installcorenamespace{spacecodemethod}
-\def\setfrenchspacing#1%
- {\sfcode`\.#1 \sfcode`\,#1\relax
- \sfcode`\?#1 \sfcode`\!#1\relax
- \sfcode`\:#1 \sfcode`\;#1\relax}
+\sfcode`\)=\zerocount
+\sfcode`\'=\zerocount
+\sfcode`\]=\zerocount
-\def\frenchspacing
- {\setfrenchspacing{1000}}
+\def\spac_spacecodes_set_fixed#1%
+ {\sfcode`\.#1\relax \sfcode`\,#1\relax
+ \sfcode`\?#1\relax \sfcode`\!#1\relax
+ \sfcode`\:#1\relax \sfcode`\;#1\relax}
-\def\resetfrenchspacing
+\def\spac_spacecodes_set_stretch
{\sfcode`\.3000 \sfcode`\,1250
\sfcode`\?3000 \sfcode`\!3000
\sfcode`\:2000 \sfcode`\;1500 }
-\def\frenchspacing {\setfrenchspacing{1000}}
-\def\newfrenchspacing{\setfrenchspacing{1050}}
-\def\nonfrenchspacing{\resetfrenchspacing}
+\unexpanded\def\frenchspacing {\spac_spacecodes_set_fixed\plusthousand}
+\unexpanded\def\newfrenchspacing{\spac_spacecodes_set_fixed{1050}}
+\unexpanded\def\nonfrenchspacing{\spac_spacecodes_set_stretch}
-\unexpanded\def\definespacingmethod[#1]#2{\setvalue{\??sg\??sg#1}{#2}}
+\unexpanded\def\installspacingmethod#1#2{\setvalue{\??spacecodemethod#1}{#2}}
-\definespacingmethod[\v!packed]{\newfrenchspacing}
-\definespacingmethod[\v!broad ]{\nonfrenchspacing}
+\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
-\def\complexsetupspacing[#1]%
- {\executeifdefined{\??sg\??sg#1}\relax
- \updateraggedskips}
+\unexpanded\def\setupspacing
+ {\doifnextoptionalelse\spac_spacecodes_setup_yes\spac_spacecodes_setup_nop}
-\def\simplesetupspacing
- {\updateraggedskips}
+\def\spac_spacecodes_setup_yes[#1]%
+ {\csname\??spacecodemethod#1\endcsname
+ \updateraggedskips} % not needed, as sf codes are static
-\definecomplexorsimple\setupspacing
+\def\spac_spacecodes_setup_nop
+ {\updateraggedskips} % not needed, as sf codes are static
+
+% This is not needed, as \updateraggedskips is taking care of it:
+
+\let\synchronizespacecodes\spac_spacecodes_setup_nop % \relax
% \dorecurse{100}{\recurselevel\spacefactor 800 \space} \par
% \dorecurse{100}{\recurselevel\spacefactor1200 \space} \par
@@ -341,14 +381,14 @@
\letcatcodecommand \ctxcatcodes \tildeasciicode \nonbreakablespace % overloaded later
-\def\space { }
-\def\removelastspace{\ifhmode\unskip\fi}
-\def\nospace {\removelastspace\ignorespaces}
+ \def\space { }
+\unexpanded\def\removelastspace{\ifhmode\unskip\fi}
+\unexpanded\def\nospace {\removelastspace\ignorespaces}
\ifdefined\softhyphen \else \let\softhyphen\- \fi
-\ctxsprint{"\string\\unexpanded\string\\def\string\\\string\n{\string\\space}"}
-%ctxsprint{"\string\\let\string\\\string\n=\string\\space"}
+\cldcontext{"\string\\unexpanded\string\\def\string\\\string\n{\string\\space}"}
+%cldcontext{"\string\\let\string\\\string\n=\string\\space"}
% in tables we need:
%
@@ -357,27 +397,27 @@
% but, since not all fonts have .5em digits:
\unexpanded\def\fixedspace
- {\setbox\scratchbox\normalhbox{\mathortext{0}{0}}%
+ {\setbox\scratchbox\hbox{\mathortext{0}{0}}%
\hskip\wd\scratchbox\relax}
-\def\fixedspaces
+\unexpanded\def\fixedspaces
{\letcatcodecommand \ctxcatcodes \tildeasciicode \fixedspace}
\appendtoks
- \let~\space
- \let\ \space
-\to\simplifiedcommands
+ \let~\space
+ \let\ \space
+\to \simplifiedcommands
\unexpanded\def\removeunwantedspaces
{\ifhmode
- \expandafter \doremoveunwantedspace
+ \expandafter \spac_helpers_remove_unwantedspace
\fi}
-\def\doremoveunwantedspace
- {\ifnum\lastnodetype=\@@gluenode
- \unskip \expandafter\doremoveunwantedspace
+\def\spac_helpers_remove_unwantedspace
+ {\ifnum\lastnodetype=\gluenodecode
+ \unskip \expandafter\spac_helpers_remove_unwantedspace
\fi}
-
+
% \startbuffer
% \startlines \tt \fixedspaces
% 0~1~~2~~~3~~~~4~~~~~5
@@ -402,7 +442,7 @@
%D A couple of plain macros:
-\ifx\thinspace\undefined
+\ifdefined\thinspace \else
\def\thinspace {\kern .16667\emwidth}
\def\negthinspace{\kern-.16667\emwidth}
@@ -410,7 +450,7 @@
\fi
-\ifx\quad\undefined
+\ifdefined\quad \else
\def\enskip{\hskip.5\emwidth}
\def\quad {\hskip \emwidth}
@@ -426,242 +466,210 @@
% Bovendien definieren we enkele extra \fill's:
-\def\hfilll{\hskip\zeropoint\!!plus1filll\relax}
-\def\vfilll{\vskip\zeropoint\!!plus1filll\relax}
+\unexpanded\def\hfilll{\hskip\zeropoint\!!plus1filll\relax}
+\unexpanded\def\vfilll{\vskip\zeropoint\!!plus1filll\relax}
-% De onderstaande hulpmacro's moeten nog eens instelbaar worden
-% gemaakt.
+\unexpanded\def\tfskip {\begingroup\tf\hskip\emwidth\endgroup}
+\unexpanded\def\dotfskip#1{\begingroup\tf\hskip #1\endgroup} % used elsewhere
-\def\tfskipsize{1em\relax}
-\def\tfkernsize{1ex\relax}
-
-\def\tfskip{\dotfskip\tfskipsize}
-\def\tfkern{\dotfkern\tfkernsize}
-
-\def\dotfskip#1{{\tf\hskip#1}}
-\def\dotfkern#1{{\tf\kern #1}}
-
% needs a proper \definenarrower or installnarrower
-
-\newskip\ctxleftskip
-\newskip\ctxrightskip
-\newskip\ctxmidskip
-
-% \def\dosinglenarrower#1%
-% {\processaction
-% [#1]
-% [ \v!left=>\global\advance\ctxleftskip \@@slleft,
-% \v!middle=>\global\advance\ctxmidskip \@@slmiddle,
-% \v!right=>\global\advance\ctxrightskip \@@slright,
-% \v!reset=>\global\ctxleftskip \zeropoint
-% \global\ctxmidskip \zeropoint
-% \global\ctxrightskip\zeropoint,
-% \v!none=>,
-% \s!unknown=>\global\advance\ctxmidskip \commalistelement]}
-
-\def\donarrower[#1]% hm, can be dorepeat directly
- {\dorepeatwithcommand[#1]\donarrowermethod}
-
-\unexpanded\def\definenarrowermethod[#1]#2%
- {\setvalue{\??sl:#1}{#2}}
-
-\def\donarrowermethod#1%
- {\ifcsname\??sl:#1\endcsname\csname\??sl:#1\endcsname\else\global\advance\ctxmidskip#1\relax\fi}
-
-\definenarrowermethod[\v!left ]{\global\advance\ctxleftskip \@@slleft \relax}
-\definenarrowermethod[\v!middle ]{\global\advance\ctxmidskip \@@slmiddle\relax}
-\definenarrowermethod[\v!right ]{\global\advance\ctxrightskip \@@slright \relax}
-\definenarrowermethod[-\v!left ]{\global\advance\ctxleftskip -\@@slleft \relax}
-\definenarrowermethod[-\v!middle]{\global\advance\ctxmidskip -\@@slmiddle\relax}
-\definenarrowermethod[-\v!right ]{\global\advance\ctxrightskip-\@@slright \relax}
-\definenarrowermethod[\v!reset ]{\global\ctxleftskip \zeropoint
- \global\ctxmidskip \zeropoint
- \global\ctxrightskip\zeropoint\relax}
-\definenarrowermethod[\v!none ]{}
-
-% todo: definenarrower
-%
-% \definecomplexorsimple\startnarrower
-%
-% \def\simplestartnarrower
-% {\startnarrower[\v!middle]}
-%
-% \def\complexstartnarrower[#1]%
-% {\@@slbefore % was hard coded \par
-% \bgroup
-% \global\ctxleftskip \zeropoint
-% \global\ctxrightskip\zeropoint
-% \global\ctxmidskip \zeropoint
-% \processcommalistwithparameters[#1]\donarrower
-% \advance\leftskip \dimexpr\ctxleftskip +\ctxmidskip\relax
-% \advance\rightskip \dimexpr\ctxrightskip+\ctxmidskip\relax
-% \seteffectivehsize}
-%
-% \unexpanded\def\stopnarrower
-% {\@@slafter % was hard coded \par / needed, else skips forgotten
-% \egroup}
%
-% \unexpanded\def\setupnarrower
-% {\dodoubleargument\getparameters[\??sl]}
+% maybe we should hash the analysis
-%D Contrary to \MKII\ we can now define classes of narrower (generalized
-%D by Wolfgang). This environment will be enhanced for bidi.
+\installcorenamespace{narrower}
+\installcorenamespace{narrowermethod}
-\def\narrowerparameter #1{\csname\donarrowerparameter{\??sl\@@narrower}#1\endcsname}
-\def\donarrowerparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\donarrowerparentparameter\csname#1\s!parent\endcsname#2\fi}
-\def\donarrowerparentparameter#1#2{\ifx#1\relax\s!empty\else\donarrowerparameter#1#2\fi}
+\newskip\s_spac_narrower_left
+\newskip\s_spac_narrower_right
+\newskip\s_spac_narrower_mid
-\getparameters
- [\??sl]
+\installcommandhandler \??narrower {narrower} \??narrower
+
+\setupnarrower
[\c!before=\endgraf,
\c!after=\endgraf,
- \c!left=1.5em,
- \c!right=1.5em,
- \c!middle=1.5em]
-
-\unexpanded\def\definenarrower
- {\dodoubleempty\dodefinenarrower}
-
-\def\dodefinenarrower[#1][#2]%
- {\getparameters[\??sl#1][\s!parent=\??sl,#2]%
- \setvalue{\e!start#1}{\dodoubleempty\dostartnarrower[#1]}%
- \setvalue{\e!stop #1}{\dostopnarrower}}
-
-\unexpanded\def\setupnarrower
- {\dodoubleempty\dosetupnarrower}
-
-\def\dosetupnarrower[#1][#2]%
- {\doifelsenothing{#2}
- {\getparameters[\??sl][#1]}
- {\def\docommand##1{\getparameters[\??sl##1][#2]}%
- \processcommacommand[#1]\docommand}}
-
-\definenarrowermethod[\v!left ]{\global\advance\ctxleftskip \narrowerparameter\c!left \relax}
-\definenarrowermethod[\v!middle ]{\global\advance\ctxmidskip \narrowerparameter\c!middle\relax}
-\definenarrowermethod[\v!right ]{\global\advance\ctxrightskip \narrowerparameter\c!right \relax}
-\definenarrowermethod[-\v!left ]{\global\advance\ctxleftskip -\narrowerparameter\c!left \relax}
-\definenarrowermethod[-\v!middle]{\global\advance\ctxmidskip -\narrowerparameter\c!middle\relax}
-\definenarrowermethod[-\v!right ]{\global\advance\ctxrightskip-\narrowerparameter\c!right \relax}
-\definenarrowermethod[\v!reset ]{\global\ctxleftskip \zeropoint
- \global\ctxmidskip \zeropoint
- \global\ctxrightskip\zeropoint\relax}
-\definenarrowermethod[\v!none ]{}
-
-\def\dostartnarrower[#1][#2]%
- {\bgroup
- \ifsecondargument % \doifsomethingelse{#2}?
- \dodostartnarrower[#1][#2]%
+ \c!left=1.5\emwidth,
+ \c!right=1.5\emwidth,
+ \c!middle=1.5\emwidth,
+ \c!default=\v!middle]
+
+\appendtoks
+ \setuevalue{\e!start\currentnarrower}{\spac_narrower_start{\currentnarrower}}%
+ \setuevalue{\e!stop \currentnarrower}{\spac_narrower_stop}%
+\to \everydefinenarrower
+
+\unexpanded\def\installnarrowermethod#1#2%
+ {\setvalue{\??narrowermethod#1}{#2}}
+
+\unexpanded\def\spac_narrower_method_analyze#1%
+ {\ifcsname\??narrowermethod#1\endcsname
+ \csname\??narrowermethod#1\endcsname
+ \else
+ \global\advance\s_spac_narrower_mid#1\relax
+ \fi}
+
+\def\spac_narrower_initialize[#1]% hm, can be dorepeat directly
+ {\dorepeatwithcommand[#1]\spac_narrower_method_analyze}
+
+\installnarrowermethod \v!left {\global\advance\s_spac_narrower_left \narrowerparameter\c!left \relax}
+\installnarrowermethod \v!middle{\global\advance\s_spac_narrower_mid \narrowerparameter\c!middle\relax}
+\installnarrowermethod \v!right {\global\advance\s_spac_narrower_right \narrowerparameter\c!right \relax}
+\installnarrowermethod-\v!left {\global\advance\s_spac_narrower_left -\narrowerparameter\c!left \relax}
+\installnarrowermethod-\v!middle{\global\advance\s_spac_narrower_mid -\narrowerparameter\c!middle\relax}
+\installnarrowermethod-\v!right {\global\advance\s_spac_narrower_right-\narrowerparameter\c!right \relax}
+\installnarrowermethod \v!reset {\global \s_spac_narrower_left \zeropoint
+ \global \s_spac_narrower_mid \zeropoint
+ \global \s_spac_narrower_right \zeropoint\relax}
+\installnarrowermethod\v!none {}
+
+\unexpanded\def\spac_narrower_start#1%
+ {\begingroup
+ \edef\currentnarrower{#1}%
+ \dosingleempty\spac_narrower_start_indeed}
+
+\unexpanded\def\spac_narrower_start_indeed[#1]%
+ {\iffirstargument
+ \spac_narrower_start_apply{#1}%
\else
- \dodostartnarrower[#1][\v!middle]%
+ \spac_narrower_start_apply{\narrowerparameter\v!default}%
\fi}
-\def\dodostartnarrower[#1][#2]%
- {\edef\@@narrower{#1}%
- \narrowerparameter\c!before
- \global\ctxleftskip \zeropoint
- \global\ctxrightskip\zeropoint
- \global\ctxmidskip \zeropoint
- \processcommalistwithparameters[#2]\donarrower
- \advance\leftskip \dimexpr\ctxleftskip +\ctxmidskip\relax
- \advance\rightskip\dimexpr\ctxrightskip+\ctxmidskip\relax
+\def\spac_narrower_start_apply#1%
+ {\narrowerparameter\c!before
+ \global\s_spac_narrower_left \zeropoint
+ \global\s_spac_narrower_right\zeropoint
+ \global\s_spac_narrower_mid \zeropoint
+ \processcommalistwithparameters[#1]\spac_narrower_initialize
+ \advance\leftskip \dimexpr\s_spac_narrower_left +\s_spac_narrower_mid\relax
+ \advance\rightskip\dimexpr\s_spac_narrower_right+\s_spac_narrower_mid\relax
\seteffectivehsize}
-\def\dostopnarrower
+\unexpanded\def\spac_narrower_stop
{\narrowerparameter\c!after
- \egroup}
+ \endgroup}
-\def\v!narrower{narrower}
+\unexpanded\def\startnarrower
+ {\dosingleempty\spac_narrower_start_basic}
-\definenarrower[\v!narrower]
-
-\newdimen\@@effectivehsize \def\effectivehsize {\hsize}
-\newdimen\@@effectiveleftskip \def\effectiveleftskip {\leftskip}
-\newdimen\@@effectiverightskip \def\effectiverightskip{\rightskip}
+\unexpanded\def\spac_narrower_start_basic[#1]%
+ {\begingroup
+ \let\currentnarrower\empty
+ \iffirstargument
+ \spac_narrower_start_apply{#1}%
+ \else
+ \spac_narrower_start_apply{\narrowerparameter\v!default}%
+ \fi}
+
+\let\stopnarrower\spac_narrower_stop
+
+\unexpanded\def\startnarrow % current how
+ {\begingroup
+ \dodoubleempty\spac_narrower_start_named}
-\def\seteffectivehsize
+\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}
+
+\let\stopnarrow\spac_narrower_stop
+
+% \def\v!narrower{narrower}
+% \definenarrower[\v!narrower]
+
+\newdimen\d_spac_effective_hsize \def\effectivehsize {\hsize}
+\newdimen\d_spac_effective_leftskip \def\effectiveleftskip {\leftskip}
+\newdimen\d_spac_effective_rightskip \def\effectiverightskip{\rightskip}
+
+\unexpanded\def\seteffectivehsize
{\setlocalhsize
- \@@effectivehsize \localhsize
- \@@effectiveleftskip \leftskip
- \@@effectiverightskip \rightskip
- \let\effectivehsize \@@effectivehsize
- \let\effectiveleftskip \@@effectiveleftskip
- \let\effectiverightskip\@@effectiverightskip}
+ \d_spac_effective_hsize \localhsize
+ \d_spac_effective_leftskip \leftskip
+ \d_spac_effective_rightskip\rightskip
+ \let\effectivehsize \d_spac_effective_hsize
+ \let\effectiveleftskip \d_spac_effective_leftskip
+ \let\effectiverightskip\d_spac_effective_rightskip}
+
+\installcorenamespace{skipadaptionleft}
+\installcorenamespace{skipadaptionright}
\newskip\leftskipadaption
\newskip\rightskipadaption
-\setvalue{@lsa@\v!standard}{\ifdim\ctxparindent=\zeropoint\@@slleft\else\ctxparindent\fi}
-\setvalue{@lsa@\v!yes }{\ifdim\ctxparindent=\zeropoint\@@slleft\else\ctxparindent\fi}
-\letvalue{@lsa@\v!no }\zeropoint
-\letvalue{@lsa@\empty }\zeropoint
-\setvalue{@rsa@\v!standard}{\@@slright}
-\setvalue{@rsa@\v!yes }{\@@slright}
-\letvalue{@rsa@\v!no }\zeropoint
-\letvalue{@rsa@\empty }\zeropoint
-
-\def\dosetleftskipadaption #1{\leftskipadaption \ifcsname @lsa@#1\endcsname\csname @lsa@#1\endcsname\else#1\fi\relax}
-\def\dosetrightskipadaption#1{\rightskipadaption\ifcsname @rsa@#1\endcsname\csname @rsa@#1\endcsname\else#1\fi\relax}
+\setvalue{\??skipadaptionleft \v!standard}{\ifdim\d_spac_indentation_par=\zeropoint\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
+\setvalue{\??skipadaptionleft \v!yes }{\ifdim\d_spac_indentation_par=\zeropoint\narrowerparameter\c!left\else\d_spac_indentation_par\fi}
+\letvalue{\??skipadaptionleft \v!no }\zeropoint
+\letvalue{\??skipadaptionleft \empty }\zeropoint
+\setvalue{\??skipadaptionright\v!standard}{\narrowerparameter\c!right}
+\setvalue{\??skipadaptionright\v!yes }{\narrowerparameter\c!right}
+\letvalue{\??skipadaptionright\v!no }\zeropoint
+\letvalue{\??skipadaptionright\empty }\zeropoint
-\def\doadaptleftskip #1{\dosetleftskipadaption {#1}\advance\leftskip \leftskipadaption }
-\def\doadaptrightskip#1{\dosetrightskipadaption{#1}\advance\rightskip\rightskipadaption}
+\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}
-%D Tolerance:
+\unexpanded\def\doadaptleftskip #1{\dosetleftskipadaption {#1}\advance\leftskip \leftskipadaption }
+\unexpanded\def\doadaptrightskip#1{\dosetrightskipadaption{#1}\advance\rightskip\rightskipadaption}
-\unexpanded\def\definetolerancemethod
- {\dodoubleargument\dodefinetolerancemethod}
+%D Tolerance (can also be set with align):
-\def\dodefinetolerancemethod[#1][#2]#3%
- {\setvalue{\??to:#1:#2}{#3}}
+\installcorenamespace{tolerancemethods}
-\definetolerancemethod [\v!vertical] [\v!verystrict ] {\let\bottomtolerance\empty}
-\definetolerancemethod [\v!vertical] [\v!strict ] {\def\bottomtolerance{.050}}
-\definetolerancemethod [\v!vertical] [\v!tolerant ] {\def\bottomtolerance{.075}}
-\definetolerancemethod [\v!vertical] [\v!verytolerant] {\def\bottomtolerance{.100}}
+\unexpanded\def\installtolerancemethod#1#2#3%
+ {\setvalue{\??tolerancemethods#1:#2}{#3}}
-\definetolerancemethod [\v!horizontal] [\v!stretch ] {\emergencystretch\bodyfontsize}
-\definetolerancemethod [\v!horizontal] [\v!space ] {\spaceskip.5em\!!plus.25em\!!minus.25em\relax}
-\definetolerancemethod [\v!horizontal] [\v!verystrict ] {\tolerance 200 }
-\definetolerancemethod [\v!horizontal] [\v!strict ] {\tolerance1500 }
-\definetolerancemethod [\v!horizontal] [\v!tolerant ] {\tolerance3000 }
-\definetolerancemethod [\v!horizontal] [\v!verytolerant] {\tolerance4500 }
+\installtolerancemethod \v!vertical \v!verystrict {\let\bottomtolerance\empty}
+\installtolerancemethod \v!vertical \v!strict {\def\bottomtolerance{.050}}
+\installtolerancemethod \v!vertical \v!tolerant {\def\bottomtolerance{.075}}
+\installtolerancemethod \v!vertical \v!verytolerant {\def\bottomtolerance{.100}}
-\def\dotolerancencemethodvertical #1{\csname\??to:\v!vertical :#1\endcsname}
-\def\dotolerancencemethodhorizontal#1{\csname\??to:\v!horizontal:#1\endcsname}
+\installtolerancemethod \v!horizontal \v!stretch {\emergencystretch\bodyfontsize}
+\installtolerancemethod \v!horizontal \v!space {\spaceskip.5em\!!plus.25em\!!minus.25em\relax}
+\installtolerancemethod \v!horizontal \v!verystrict {\tolerance 200 }
+\installtolerancemethod \v!horizontal \v!strict {\tolerance1500 }
+\installtolerancemethod \v!horizontal \v!tolerant {\tolerance3000 }
+\installtolerancemethod \v!horizontal \v!verytolerant {\tolerance4500 }
-\def\dosetuptolerance[#1]%
- {\doifinsetelse\v!vertical{#1}%
- {\processcommacommand[#1]\dotolerancencemethodvertical}
- {\processcommacommand[#1]\dotolerancencemethodhorizontal}}
+\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\dosetuptolerance}
+ {\dosingleargument\spac_tolerances_setup}
+
+\def\spac_tolerances_setup[#1]%
+ {\doifinsetelse\v!vertical{#1}%
+ {\processcommacommand[#1]\spac_tolerances_step_vertical }
+ {\processcommacommand[#1]\spac_tolerances_step_horizontal}}
%D \macros
%D {pushindentation,popindentation}
%D
%D The pushing and popping is done by:
-\newbox\indentationboxA
-\newbox\indentationboxB
+\newbox\b_spac_indentations_a
+\newbox\b_spac_indentations_b
-\def\pushindentation
- {\bgroup
+\unexpanded\def\pushindentation
+ {\begingroup
\ifhmode
\unskip
- \setbox\indentationboxA\lastbox % get \strut if present
+ \setbox\b_spac_indentations_a\lastbox % get \strut if present
\unskip
- \setbox\indentationboxB\lastbox % get \indent generated box
+ \setbox\b_spac_indentations_b\lastbox % get \indent generated box
\unskip
\else
- \hskip\zeropoint % switch to horizontal mode
+ \dontleavehmode % was \hskip\zeropoint % switch to horizontal mode
\unskip
- \setbox\indentationboxA\lastbox % get \indent generated box
- \setbox\indentationboxB\emptybox
+ \setbox\b_spac_indentations_a\lastbox % get \indent generated box
+ \setbox\b_spac_indentations_b\emptybox
\fi}
-\def\popindentation
- {\box\indentationboxB\box\indentationboxA % put back the boxes
- \egroup}
+\unexpanded\def\popindentation
+ {\box\b_spac_indentations_b
+ \box\b_spac_indentations_a
+ \endgroup}
%D The only complication lays in \type{\strut}. In \PLAIN\
%D \TEX\ a \type{\strut} is defined as:
@@ -694,7 +702,7 @@
%D {\relax\ifmmode
%D \copy\strutbox
%D \else
-%D \bgroup\setbox\strutbox=\normalhbox{\box\strutbox}\unhcopy\strutbox\egroup
+%D \bgroup\setbox\strutbox=\hbox{\box\strutbox}\unhcopy\strutbox\egroup
%D \fi}
%D \stoptyping
%D
@@ -707,7 +715,7 @@
% \unexpanded \def\crlf
% {\ifhmode\unskip\else\strut\fi\ifcase\raggedstatus\hfil\fi\break}
-\unexpanded \def\crlf
+\unexpanded\def\crlf
{\ifhmode
\unskip
\prewordbreak\crlfplaceholder
@@ -718,11 +726,11 @@
\endgraf
\fi}
-\def\crlfplaceholder
+\unexpanded\def\crlfplaceholder
{\strut}
-\def\settestcrlf
- {\def\crlfplaceholder
+\unexpanded\def\settestcrlf
+ {\unexpanded\def\crlfplaceholder
{\hbox to \zeropoint
{\strut{\infofont\kern.25em}\lohi{\infofont CR}{\infofont LF}\hss}}}
@@ -756,46 +764,51 @@
%unexpanded\def\justaperiod {\removeunwantedspaces.}
%unexpanded\def\justacomma {\removeunwantedspaces,}
-\def\ignorecrlf
+\installcorenamespace{hspace}
+
+\unexpanded\def\ignorecrlf
{\let\crlf\justonespace\let\\\crlf}
\unexpanded\def\definehspace
- {\dotripleempty\dodefinehspace}
+ {\dotripleempty\spac_hspaces_define}
-\def\dodefinehspace[#1][#2][#3]% #1 = optional namespace
+\def\spac_hspaces_define[#1][#2][#3]% #1 = optional namespace
{\ifthirdargument
- \setvalue{\??hs#1:#2}{#3}%
+ \setvalue{\??hspace#1:#2}{#3}%
\else
- \setvalue{\??hs:#1}{#2}%
+ \setvalue{\??hspace:#1}{#2}%
\fi}
\unexpanded\def\hspace
- {\dodoubleempty\dohspace}
+ {\dodoubleempty\spac_hspaces_insert}
-\def\dohspace[#1][#2]%
- {\ifsecondargument
- \dodohspace[#1][#2]%
- \else\iffirstargument
- \hspace[][#1]%
- \else
- \hspace[][\s!default]%
- \fi\fi}
-
-\def\dodohspace[#1][#2]%
+\def\spac_hspaces_insert[#1][#2]%
{\ifhmode
\removeunwantedspaces
- \hskip\hspaceamount{#1}{#2}%
+ \hskip % always a skip even when 0pt
+ \ifsecondargument
+ \hspaceamount{#1}{#2}%
+ \else\iffirstargument
+ \hspaceamount\empty{#1}%
+ \else
+ \hspaceamount\empty\s!default
+ \fi\fi
\expandafter\ignorespaces
- \fi}
+ \fi}
\def\hspaceamount#1#2%
- {\executeifdefined{\??hs#1:#2}{\executeifdefined{\??hs:#2}\zeropoint}}
+ {\csname\??hspace
+ \ifcsname\??hspace#1:#2\endcsname#1:#2\else:\v!none\fi
+ \endcsname}
+
+% no installhspace here (this is already an old command)
\definehspace [\v!small] [.25\emspaceamount]
\definehspace [\v!medium] [.5\emspaceamount]
\definehspace [\v!big] [1\emspaceamount]
\definehspace [\v!normal] [1\spaceamount]
\definehspace [\v!default] [\spaceamount]
+\definehspace [\v!none] [\zeropoint]
%D Taken from Taco's math module (cq. \AMS\ macros), but
%D adapted to \type {\hspace}:
@@ -816,23 +829,20 @@
% needed for unicode:
-\unexpanded\def\breakablethinspace {\breakabletextormathspace+\thinmuskip 1}
-
-\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\space}
-\unexpanded\def\nobreakspace {\penalty\plustenthousand\kern\interwordspace}
-\unexpanded\def\narrownobreakspace {\penalty\plustenthousand\thinspace}
-%unexpanded\def\zerowidthnobreakspace {\penalty\plustenthousand\hskip\zeropoint}
-\unexpanded\def\zerowidthnobreakspace {\penalty\plustenthousand\kern\zeropoint}
-\unexpanded\def\zerowidthspace {\hskip\zeropoint}
+%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}
\definehspace[.5][.1250\emspaceamount] % could also be [.1250\spaceamount]
\definehspace[1] [.1667\emspaceamount]
@@ -844,6 +854,11 @@
\let \; \thickspace
\let \! \negthinspace
+% plain ...
+%
+% \ifdefined\> \else \unexpanded\def\>{\mskip \medmuskip } \fi
+% \ifdefined\* \else \unexpanded\def\*{\discretionary{\thinspace\the\textfont2\char2}{}{}} \fi
+
\def\flexiblespaceamount#1#2#3%
{#1\interwordspace
\!!plus#2\interwordstretch
@@ -858,32 +873,38 @@
%
% do we need \normalspaceprimitive here?
-\def\installspacehandler#1#2% needs to set \obeyedspace
- {\setvalue{\??sr#1}{#2}}
+\installcorenamespace{spacemethods}
+
+\unexpanded\def\installspacemethod#1#2% needs to set \obeyedspace
+ {\setvalue{\??spacemethods#1}{#2}}
-\installspacehandler \v!on
+\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}}%
+
+\installspacemethod \v!on
{\obeyspaces
- \unexpanded\def\obeyedspace{\mathortext\normalspace{\dontleavehmode{\tt\controlspace}}}%
+ \let\obeyedspace\spac_spaces_checked_control
\let\ =\obeyedspace}
-\installspacehandler \v!yes
+\installspacemethod \v!yes
{\obeyspaces
- \unexpanded\def\obeyedspace{\mathortext\normalspace{\dontleavehmode\normalspace}}%
+ \let\obeyedspace\spac_spaces_checked_normal
\let\ =\obeyedspace}
-\installspacehandler \v!off % == default
+\installspacemethod \v!off % == default
{\normalspaces
\let\obeyedspace\normalspace
\let\ =\normalspaceprimitive} % was \normalspace
-\installspacehandler \v!fixed
+\installspacemethod \v!fixed
{\obeyspaces
- \unexpanded\def\obeyedspace{\mathortext\normalspace{\dontleavehmode\fixedspace}}%
+ \let\obeyedspace\spac_spaces_checked_fixed
\let\ =\obeyedspace}
-\def\activatespacehandler#1%
- {\executeifdefined{\??sr#1}{\activatespacehandler\v!off}}
-
\appendtoks
\normalspaces % to be sure
\to \everybeforeoutput
@@ -899,18 +920,15 @@
%D
%D \typebuffer \getbuffer
-% unexpanded is important here as it prevents premature expansion in
-% e.g. \normalexpanded{\egroup\sortingparameter\c!next}
-
\unexpanded\def\autoinsertnextspace
- {\futurelet\nexttoken\doautoinsertnextspace}
+ {\futurelet\nexttoken\spac_spaces_auto_insert_next}
-\def\doautoinsertnextspace
+\def\spac_spaces_auto_insert_next
{\ctxcommand{autonextspace("\meaning\nexttoken")}} % todo, just consult nexttoken at the lua end
%D Moved from bib module:
-\def\outdented#1%
+\unexpanded\def\outdented#1%
{\hskip-\hangindent#1\relax}
%D Beware: due to char-def this becomes an active character but that
@@ -918,24 +936,24 @@
%D node insertions. We might even expand it to utf then as it then
%D can be used in string comparison (not that much needed anyway).
-\chardef\zwnj="200C
-\chardef\zwj ="200D
+% \chardef\zwnj="200C
+% \chardef\zwj ="200D
% TODO (but used in languages):
-\unexpanded\def\textormathglue#1#2#3% cleaned up one
+\unexpanded\def\spac_glues_text_or_math#1#2%
{\begingroup
\ifmmode
- \mskip#1#2%
+ \mskip#1%
\else
- \scratchdimen#1\hspaceamount\empty{#3}%
+ \scratchdimen#1\hspaceamount\empty{#2}%
\scratchskip\scratchdimen\!!plus.5\scratchdimen\!!minus.3\scratchdimen
\hskip\scratchskip
\fi
\endgroup}
-\def\thinglue {\textormathglue+\thinmuskip 1}
-\def\medglue {\textormathglue+\medmuskip 2}
-\def\thickglue{\textormathglue+\thickmuskip3}
+\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}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/spac-lin.mkiv b/Master/texmf-dist/tex/context/base/spac-lin.mkiv
new file mode 100644
index 00000000000..094e18e0bac
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/spac-lin.mkiv
@@ -0,0 +1,148 @@
+%D \module
+%D [ file=spac-lin,
+%D version=2012.01.08, % 2009.10.16 (core-ver) 1997.03.31 (core-spa)
+%D title=\CONTEXT\ Spacing Macros,
+%D subtitle=Vertical,
+%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 Spacing Macros / Lines}
+
+\unprotect
+
+%D When spacing is active we need to handle commands in
+%D a special way:
+%D
+%D \starttyping
+%D \setuplines[space=on]
+%D
+%D \startlines
+%D Let's talk about this{\ttsl\gobbleoneargument or}that.
+%D \stoplines
+%D
+%D \startlines
+%D Let's talk about this{\getvalue{ttsl}or}that.
+%D \stoplines
+%D \stoptyping
+%D
+%D One can indent in several ways:
+%D
+%D \starttyping
+%D \setupindenting[medium] \setuplines[indenting=odd] % no yes odd even
+%D
+%D \startlines
+%D first
+%D second
+%D third
+%D fourth
+%D \stoplines
+%D \stoptyping
+
+%D Contrary to \MKII\ we can now define classes of lines (generalized by
+%D Wolfgang). I will probably rewrite bits in \LUA.
+
+\installcorenamespace{lines}
+
+\installcommandhandler \??lines {lines} \??lines
+
+\setuplines
+ [\c!option=,
+ \c!command=,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!inbetween=\blank,
+ \c!indenting=\v!no,
+ \c!space=\v!default]
+
+\appendtoks
+ \setuevalue{\e!start\currentlines}{\spac_lines_start[\currentlines]}%
+ \setuevalue{\e!stop \currentlines}{\spac_lines_stop}%
+\to \everydefinelines
+
+\unexpanded\def\spac_lines_start[#1]%
+ {\bgroup
+ \edef\currentlines{#1}%
+ \obeylines
+ \dosingleempty\spac_lines_start_indeed}
+
+\let\p_lines_option\empty
+
+\let\spac_lines_break \relax
+\let\spac_after_first_obeyed_line\relax
+
+\def\spac_lines_start_indeed[#1]% new: optional second argument (WS)
+ {\iffirstargument
+ \setupcurrentlines[#1]%
+ \fi
+ \edef\p_lines_option{\linesparameter\c!option}%
+ \ifx\p_lines_option\v!packed
+ \let\spac_lines_break\nobreak
+ \else
+ \let\spac_lines_break\relax
+ \fi
+ \linesparameter\c!before
+ \pushmacro\checkindentation
+ \whitespace
+ \dostarttagged\t!lines\currentlines
+ \begingroup
+ \uselinesstyleandcolor\c!style\c!color
+ \setupindenting[\linesparameter\c!indenting]%
+ \setupalign[\linesparameter\c!align]%
+ \typesettinglinestrue
+ \setupwhitespace[\v!none]%
+ %\obeylines % move upwards to keep spaces in the first line due to optional argument
+ \ignorespaces
+ \glet\spac_after_first_obeyed_line\spac_lines_after_first_obeyed_line_a
+ \let\obeyedline\spac_lines_obeyed_line
+ \activatespacehandler{\linesparameter\c!space}%
+ \dostarttagged\t!line\empty
+ \GotoPar} % this will become a nice lowercased helper
+
+% we could have states instead and handle option in there
+
+\def\spac_lines_after_first_obeyed_line_a % tzt two pass, like itemize
+ {\linesparameter\c!command
+ \glet\spac_after_first_obeyed_line\spac_lines_after_first_obeyed_line_b}
+
+\def\spac_lines_after_first_obeyed_line_b
+ {\spac_lines_break
+ \linesparameter\c!command}
+
+\def\spac_lines_obeyed_line
+ {\dostoptagged
+ \par
+ \dostarttagged\t!line\empty
+ \futurelet\next\spac_lines_between}
+
+\unexpanded\def\spac_lines_stop
+ {\dostoptagged
+ \endgroup
+ \dostoptagged
+ \popmacro\checkindentation
+ \linesparameter\c!after
+ \egroup}
+
+\def\spac_lines_between
+ {\doifmeaningelse\next\obeyedline % brrr
+ {\linesparameter\c!inbetween}
+ {\spac_after_first_obeyed_line}}
+
+\definelines[\v!lines]
+
+\unexpanded\def\emptylines
+ {\dosingleempty\spac_lines_empty}
+
+\def\spac_lines_empty[#1]%
+ {\endgraf\dorecurse{\iffirstargument#1\else3\fi}\crlf}
+
+\ifdefined\startlines \else
+ \expandafter\let\expandafter\startlines\csname\e!start\v!lines\endcsname
+ \expandafter\let\expandafter\stoplines \csname\e!stop \v!lines\endcsname
+\fi
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/spac-pag.mkiv b/Master/texmf-dist/tex/context/base/spac-pag.mkiv
index 9babab29a27..da4c8e9703b 100644
--- a/Master/texmf-dist/tex/context/base/spac-pag.mkiv
+++ b/Master/texmf-dist/tex/context/base/spac-pag.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Pages,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,17 +15,18 @@
\unprotect
-%D A quick way to determine left|/|middle|/|right states
-%D (experimental).
+%D The code here has evolved over time and might not be the best
+%D around. Maybe much will be gone a some point.
-\setvalue{\??as\v!left }{0}
-\setvalue{\??as\v!middle}{1}
-\setvalue{\??as\v!right }{2}
+\installcorenamespace {alignswitch}
+
+\letvalue{\??alignswitch\v!left }\zerocount
+\letvalue{\??alignswitch\v!middle}\plusone
+\letvalue{\??alignswitch\v!right }\plustwo
\def\setalignmentswitch#1%
- {\chardef\alignmentswitch0\csname\??as#1\endcsname\relax}
+ {\chardef\alignmentswitch\csname\??alignswitch\ifcsname\??alignswitch#1\endcsname#1\else\v!left\fi\endcsname}
-\newcount \noftrackedpagestates
\newif \ifpagestatemismatch
\newcount \realpagestateno
\newconstant\frozenpagestate
@@ -37,163 +38,141 @@
\def\doforcedtrackpagestate#1#2%
{\ifcase\frozenpagestate
- \global\advance\noftrackedpagestates\plusone
\global\advance#2\plusone
- \lazysavetaggedtwopassdata{#1}{\number\noftrackedpagestates}{\number#2}{\noexpand\realfolio}%
- %\llap{\infofont\number\noftrackedpagestates/\number#2}% tracing
+ \setpagestate[#1][\number#2]%
\fi}
-\def\doifrightpagestateelse#1#2%
+\let\m_spac_pagestates_realpage\empty
+
+\newconditional\c_spac_pagestates_found
+
+\unexpanded\def\docheckpagestate#1#2%
+ {\ifcase\frozenpagestate
+ \setpagestaterealpageno{#1}{\number#2}%
+ \fi}
+
+\unexpanded\def\doifrightpagestateelse#1#2% not expandable !
{\ifcase\frozenpagestate
\pagestatemismatchfalse
\realpagestateno\realfolio
\ifinpagebody
\ifdoublesided
\ifodd\realpageno\relax
- \twopassdatafoundtrue \else \twopassdatafoundfalse
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
\fi
\else
- \twopassdatafoundtrue
+ \settrue\c_spac_pagestates_found
\fi
\else\ifdoublesided
- \findtwopassdata{#1}{\number#2}%
- \iftwopassdatafound
- \realpagestateno\twopassdata\relax
- \ifnum\twopassdata=\realpageno \else
- \pagestatemismatchtrue
- \fi
- \ifodd\twopassdata\relax
- \twopassdatafoundtrue \else \twopassdatafoundfalse
+ \edef\m_spac_pagestates_realpage{\pagestaterealpage{#1}{\number#2}}%
+ \ifx\m_spac_pagestates_realpage\empty
+ \ifodd\realpageno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
\fi
\else
- \ifodd\realpageno\relax
- \twopassdatafoundtrue \else \twopassdatafoundfalse
+ \realpagestateno\m_spac_pagestates_realpage\relax
+ \ifnum\realpagestateno=\realpageno \else
+ \pagestatemismatchtrue
+ \fi
+ \ifodd\realpagestateno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
\fi
\fi
\else
- \twopassdatafoundtrue
+ \settrue\c_spac_pagestates_found
\fi\fi
\else
\ifodd\realpagestateno\relax
- \twopassdatafoundtrue \else \twopassdatafoundfalse
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
\fi
\fi
- \iftwopassdatafound
- \@EA\firstoftwoarguments
+ \ifconditional\c_spac_pagestates_found
+ \expandafter\firstoftwoarguments
\else
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
-\def\doifforcedrightpagestateelse#1#2%
+\unexpanded\def\doifforcedrightpagestateelse#1#2%
{\ifcase\frozenpagestate
\pagestatemismatchfalse
\realpagestateno\realfolio
- \findtwopassdata{#1}{\number#2}%
- \iftwopassdatafound
- \realpagestateno\twopassdata\relax
- \ifnum\twopassdata=\realpageno \else
- \pagestatemismatchtrue
- \fi
- \ifodd\twopassdata\relax
- \twopassdatafoundtrue \else \twopassdatafoundfalse
+ \edef\m_spac_pagestates_realpage{\pagestaterealpage{#1}{\number#2}}%
+ \ifx\m_spac_pagestates_realpage\empty
+ \ifodd\realpageno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
\fi
\else
- \ifodd\realpageno\relax
- \twopassdatafoundtrue \else \twopassdatafoundfalse
+ \realpagestateno\m_spac_pagestates_realpage\relax
+ \ifnum\realpagestateno=\realpageno \else
+ \pagestatemismatchtrue
+ \fi
+ \ifodd\realpagestateno\relax
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
\fi
\fi
\else
\ifodd\realpagestateno\relax
- \twopassdatafoundtrue \else \twopassdatafoundfalse
+ \settrue\c_spac_pagestates_found
+ \else
+ \setfalse\c_spac_pagestates_found
\fi
\fi
- \iftwopassdatafound
- \@EA\firstoftwoarguments
+ \ifconditional\c_spac_pagestates_found
+ \expandafter\firstoftwoarguments
\else
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
-\def\freezepagestate {\frozenpagestate\plusone }
-\def\defrostpagestate{\frozenpagestate\zerocount}
+\unexpanded\def\freezepagestate {\frozenpagestate\plusone }
+\unexpanded\def\defrostpagestate{\frozenpagestate\zerocount}
% we can make more of these on top, but how to deal with mixed frozen states
-\definetwopasslist\s!paragraph \newcount \nofraggedparagraphs
-
-\def\signalrightpage {\dotrackpagestate \s!paragraph\nofraggedparagraphs}
-\def\doifrightpageelse{\doifrightpagestateelse\s!paragraph\nofraggedparagraphs}
-
-\newcount\pagesignallevel
-
-\unexpanded\def\startsignalrightpage % one may do a \postsignalrightplace
- {\advance\pagesignallevel\plusone
- \presignalrightpage
- \let\signalrightpage\relax
- \let\presignalrightpage\relax
- \let\startsignalrightpage\relax
- \doifrightpageelse\donothing\donothing
- \freezepagestate}
-
-\unexpanded\def\stopsignalrightpage
- {\ifcase\pagesignallevel\or\postsignalrightpage\fi
- \advance\pagesignallevel\minusone}
-
-% \def\setraggedparagraphmode
-% {\signalrightpage\doifrightpageelse} % move it there
-
-\ifx\swapmargins\undefined \let\swapmargins\undefined \fi % todo
-
-\def\doifswappedrightpageelse#1#2% alleen in box construction !
- {\doifrightpageelse
- {#1}
- {\scratchcounter\realpageno
- \realpageno\realpagestateno\relax
- \swapmargins
- \realpageno\scratchcounter
- #2}}
-
-\newbox\signaledrightpage % this way we can avoid interference, i.e. postpone placement
-
-\def\presignalrightpage {\global\setbox\signaledrightpage\hbox{\signalrightpage}}
-\def\postsignalrightpage{\ifvoid\signaledrightpage\else\box\signaledrightpage\fi}
-
-% The next feature is is used in:
-%
-% \definenumber[test][way=bypage]
-%
-% \def\Test
-% {\incrementnumber[test]\rawnumber[test]/%
-% \incrementnumber[test]\rawnumber[test]/%
-% \incrementnumber[test]\rawnumber[test]\space
-% \checkpagechange{oeps}\changedpage{oeps}\space
-% \ifpagechanged TRUE\else FALSE\fi}
-%
-% \Test\page \Test\par \Test\page \Test\par \Test\page \Test\page
-%
-% (adapted from cont-new.tex:)
+% \dorecurse{500}{\dontleavehmode\signalrightpage\doifrightpageelse{right}{left}\par} % given doublesided
+
+\newcount\nofraggedparagraphs
+
+\definepagestate[\s!paragraph]
+
+\unexpanded\def\signalrightpage {\dotrackpagestate \s!paragraph\nofraggedparagraphs} % use \dontleavehmode if needed
+\unexpanded\def\doifrightpageelse{\doifrightpagestateelse\s!paragraph\nofraggedparagraphs}
+
+\installcorenamespace{pagechanges}
\newif\ifpagechanged \let\lastchangedpage\empty
-\def\docheckpagestatechange#1#2#3%
+\def\spac_pagechanges_check#1#2#3%
{\pagechangedfalse
\doforcedtrackpagestate{#2}{#3}%
- \findtwopassdata{#2}{\number#3}%
- \iftwopassdatafound
- \ifnum\twopassdata>0\getvalue{#2:p:#1}\relax
+ \edef\m_spac_pagestates_realpage{\pagestaterealpage{#2}{\number#3}}%
+ \ifx\m_spac_pagestates_realpage\empty \else
+ \ifnum\m_spac_pagestates_realpage>0\getvalue{\??pagechanges#2:#1}\relax
\pagechangedtrue
\fi
\fi
\ifpagechanged
- \letgvalue{#2:p:#1}\twopassdata
- \globallet\lastchangedpage\twopassdata
+ \letgvalue{\??pagechanges#2:#1}\m_spac_pagestates_realpage
+ \globallet\lastchangedpage\m_spac_pagestates_realpage
\else
\globallet\lastchangedpage\realfolio
\fi}
\def\changedpagestate#1#2%
- {\executeifdefined{#2:p:#1}{0}}
+ {\executeifdefined{\??pagechanges#2:#1}0}
-\def\checkpagechange#1{\docheckpagestatechange{#1}\s!paragraph\nofraggedparagraphs}
+\def\checkpagechange#1{\spac_pagechanges_check{#1}\s!paragraph\nofraggedparagraphs}
\def\changedpage #1{\changedpagestate{#1}\s!paragraph}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/spac-par.mkiv b/Master/texmf-dist/tex/context/base/spac-par.mkiv
index 222f4fd2c20..af032a14535 100644
--- a/Master/texmf-dist/tex/context/base/spac-par.mkiv
+++ b/Master/texmf-dist/tex/context/base/spac-par.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Paragraphs,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -23,53 +23,74 @@
%D inside the group are forgotten afterwards. (I must
%D not forget its existence).
-\global\let\carriedoverpar\relax
-
-\def\carryoverpar#1%
- {\normalexpanded % \scratchtoks{#1}%
- {\noexpand#1% \the\scratchtoks
+\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}}
-\newconditional \parbasedattributes
+\unexpanded\def\pushparagraphproperties
+ {\edef\currentparagraphproperties{\carryoverpar\relax}%
+ \pushmacro\currentparagraphproperties}
+
+\unexpanded\def\popparagraphproperties
+ {\popmacro\currentparagraphproperties
+ \currentparagraphproperties}
+
+\unexpanded\def\flushparagraphproperties
+ {\popmacro\currentparagraphproperties}
-\def\finishparbasedattributes
- {\ifconditional\parbasedattributes
- \setfalse\parbasedattributes
- \par
- \fi}
+% Beware, changing this will break some code (like pos/backgrounds) but
+% it has been changed anyway so let's see where things go wrong.
-\def\dostopparbasedattributes
- {\settrue\parbasedattributes
- \dostopattributes}
+\installcorenamespace{paragraphintro}
-% beware, changing this will break some code (like pos/backgrounds)
+\let\insertparagraphintro\relax % hook into everypar
-\newtoks\everyfirstparagraphintro
-\newtoks\everynextparagraphintro
-\newtoks\@@everyparagraphtoks
+\newtoks\t_spac_paragraphs_intro_first
+\newtoks\t_spac_paragraphs_intro_next
+\newtoks\t_spac_paragraphs_intro_each
-\newconstant\everyparagraphintrostate
+\newconditional\c_spac_paragraphs_intro_first
+\newconditional\c_spac_paragraphs_intro_next
+\newconditional\c_spac_paragraphs_intro_each
\unexpanded\def\setupparagraphintro
- {\dodoubleempty\dosetupparagraphintro}
-
-\def\dosetupparagraphintro[#1][#2]%
- {\processallactionsinset
- [#1]
- [ \v!reset=>\global\everyparagraphintrostate\zerocount
- \global\everyfirstparagraphintro\emptytoks
- \global\everynextparagraphintro \emptytoks,
- \v!first=>\global\everyparagraphintrostate\plusone
- \doglobal\appendtoks#2\to\everyfirstparagraphintro,
- \v!next=>\ifcase\everyparagraphintrostate\global\everyparagraphintrostate\plusone\fi
- \doglobal\appendtoks#2\to\everynextparagraphintro,
- \v!each=>\ifcase\everyparagraphintrostate\global\everyparagraphintrostate\plustwo\fi
- \doglobal\appendtoks#2\to\everyfirstparagraphintro
- \doglobal\appendtoks#2\to\everynextparagraphintro]}
+ {\dodoubleempty\spac_paragraphs_intro}
+
+\unexpanded\def\spac_paragraphs_intro[#1][#2]%
+ {\def\spac_paragraphs_intro_step##1%
+ {\csname\??paragraphintro\ifcsname\??paragraphintro##1\endcsname##1\fi\endcsname{#2}}%
+ \processcommacommand[#1]\spac_paragraphs_intro_step}
+
+\letvalue{\??paragraphintro\empty}\gobbleoneargument
+
+\setvalue{\??paragraphintro\v!reset}#1%
+ {\global\setfalse\c_spac_paragraphs_intro_first
+ \global\setfalse\c_spac_paragraphs_intro_next
+ \global\setfalse\c_spac_paragraphs_intro_each
+ \global\t_spac_paragraphs_intro_first\emptytoks
+ \global\t_spac_paragraphs_intro_next \emptytoks
+ \global\t_spac_paragraphs_intro_each \emptytoks
+ \glet\insertparagraphintro\relax}
+
+\setvalue{\??paragraphintro\v!first}#1%
+ {\global\settrue\c_spac_paragraphs_intro_first
+ \global\t_spac_paragraphs_intro_first\expandafter{\the\t_spac_paragraphs_intro_first#1}%
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro}
+
+\setvalue{\??paragraphintro\v!next}#1%
+ {\global\settrue\c_spac_paragraphs_intro_next
+ \global\t_spac_paragraphs_intro_next\expandafter{\the\t_spac_paragraphs_intro_next#1}%
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro}
+
+\setvalue{\??paragraphintro\v!each}#1%
+ {\global\settrue\c_spac_paragraphs_intro_each
+ \global\t_spac_paragraphs_intro_each\expandafter{\the\t_spac_paragraphs_intro_each#1}%
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro}
%D We can say:
%D
@@ -82,36 +103,7 @@
%D \starttyping
%D \flushatparagraph{\index{Zapf}}
%D \stoptyping
-
-\def\flushatparagraph#1%
- {\global\everyparagraphintrostate\plusone
- \global\appendtoks{#1}\to\everyfirstparagraphintro
- \global\let\insertparagraphintro\doinsertparagraphintro}
-
-\def\doinsertparagraphintro % can be merged with the next
- {\ifcase\everyparagraphintrostate\else\@EA\dodoinsertparagraphintro\fi}
-
-\def\dodoinsertparagraphintro
- {\begingroup
- \everypar\emptytoks
- \ifcase\everyparagraphintrostate\relax
- % no data
- \@@everyparagraphtoks\emptytoks
- \or
- % first data
- \global\everyparagraphintrostate\plustwo
- \@@everyparagraphtoks\everyfirstparagraphintro
- \global\everyfirstparagraphintro\emptytoks
- \or
- % next data
- \@@everyparagraphtoks\everynextparagraphintro
- \fi
- \the\@@everyparagraphtoks
- \global\let\insertparagraphintro\relax
- \endgroup}
-
-\let\insertparagraphintro\relax
-
+%D
%D \starttyping
%D \setupparagraphintro[first][\hbox to 3.5em{\tt FIRST \hss}]
%D \setupparagraphintro[first][\hbox to 3.5em{\tt TSRIF \hss}]
@@ -123,79 +115,92 @@
%D some paragraph \par
%D some paragraph \par
%D some paragraph \par
+%D some paragraph \par
%D
-%D \definelabel[parnumber]
-%D
-%D \setupparagraphintro[reset,each][\inleft{\slxx\parnumber}]
+%D \setupparagraphintro[first][\hbox to 3.5em{\tt FIRST \hss}]
+%D \setupparagraphintro[first][\hbox to 3.5em{\tt TSRIF \hss}]
%D
%D some paragraph \par
%D some paragraph \par
+%D
+%D \setupparagraphintro[reset]
+%D
%D some paragraph \par
%D \stoptyping
-
+
+\unexpanded\def\flushatparagraph#1%
+ {\global\c_spac_paragraphs_intro_first\plusone
+ \global\t_spac_paragraphs_intro_first\expandafter{\the\t_spac_paragraphs_intro_first#1}%
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro}
+
+%D Here comes the flusher (we misuse the one level expansion of token
+%D registers to feed a nice stream into the paragraph.)
+
+\unexpanded\def\spac_paragraphs_flush_intro % we make sure that the token lists expand directly after another
+ {\normalexpanded{% % so the first code is there twice
+ \ifconditional\c_spac_paragraphs_intro_each
+ \ifconditional\c_spac_paragraphs_intro_next
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro_next
+ \else
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro_each
+ \fi
+ \ifconditional\c_spac_paragraphs_intro_first
+ \global\setfalse\c_spac_paragraphs_intro_first
+ \global\t_spac_paragraphs_intro_first\emptytoks
+ \the\t_spac_paragraphs_intro_first
+ \fi
+ \the\t_spac_paragraphs_intro_each
+ \else
+ \ifconditional\c_spac_paragraphs_intro_next
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro_next
+ \fi
+ \ifconditional\c_spac_paragraphs_intro_first
+ \global\setfalse\c_spac_paragraphs_intro_first
+ \global\t_spac_paragraphs_intro_first\emptytoks
+ \the\t_spac_paragraphs_intro_first
+ \fi
+ \fi}}
+
+\unexpanded\def\spac_paragraphs_flush_intro_next
+ {\normalexpanded{%
+ \global\setfalse\c_spac_paragraphs_intro_next
+ \global\t_spac_paragraphs_intro_next\emptytoks
+ \ifconditional\c_spac_paragraphs_intro_each
+ \glet\insertparagraphintro\spac_paragraphs_flush_intro_each
+ \the\t_spac_paragraphs_intro_next
+ \the\t_spac_paragraphs_intro_each
+ \else
+ \glet\insertparagraphintro\relax
+ \the\t_spac_paragraphs_intro_next
+ \fi}}
+
+\unexpanded\def\spac_paragraphs_flush_intro_each
+ {\the\t_spac_paragraphs_intro_each}
+
%D \macros
%D {flushatnextpar}
%D
%D This macro collects data that will be flushed at the next paragraph.
%D By using this macro you can avoid interfering nodes (writes, etc).
-\newbox\postponednodedata
-\let\flushpostponednodedata\relax
+\let\flushpostponednodedata\relax % hook into everypar
+
+\newbox\b_spac_postponed_data
-\def\flushatnextpar
- {\bgroup
- \global\let\flushpostponednodedata\doflushpostponednodedata
- \dowithnextbox{\global\setbox\postponednodedata\hbox{\box\postponednodedata\box\nextbox}\egroup}\hbox}
+\unexpanded\def\flushatnextpar
+ {\begingroup
+ \glet\flushpostponednodedata\spac_postponed_flush
+ \dowithnextboxcs\spac_postponed_finish\hbox}
+
+\def\spac_postponed_finish
+ {\global\setbox\b_spac_postponed_data\hbox
+ {\box\b_spac_postponed_data\box\nextbox}%
+ \endgroup}
-\def\doflushpostponednodedata
- {\ifvoid\postponednodedata\else
- \hbox{\smashedbox\postponednodedata}%
+\def\spac_postponed_flush
+ {\ifvoid\b_spac_postponed_data\else
+ \hbox{\smashedbox\b_spac_postponed_data}%
\fi
- \global\let\flushpostponednodedata\relax}
-
-% Very nasty but needed for margin stuff inside colored
-% paragraphs.
-
-\registerctxluafile{spac-par}{1.001}
-
-\definesystemattribute [graphicvadjust] [public]
-
-\let\normalvadjust\vadjust
-
-\def\enablegraphicvadjust
- {\ctxlua{nodes.tasks.enableaction("finalizers","nodes.handlers.graphicvadjust")}%
- \glet\enablegraphicvadjust\relax}
-
-\def\graphicvadjust % currently not enabled; nasty bidi handling
- {\enablegraphicvadjust
- \dowithnextboxcontent
- {\forgetall}
- {\vadjust{\vbox attr \graphicvadjustattribute \plusone
- {\unvbox\nextbox
- % corrects for one line paragraphs
- \nointerlineskip
- \kern-\struttotal
- \nointerlineskip
- \verticalstrut}}}%
- \vbox}
-
-%D This works only in a properly strutted line, and is meant
-%D for deeply burried operations, like in heads.
-
-\def\fakedvadjust
- {\dowithnextbox
- {\setbox\nextbox\hbox{\llap{\lower\strutdepth\box\nextbox}}%
- \smashedbox\nextbox}%
- \vtop}
-
-\def\localvbox#1#% used?
- {\vbox#1\bgroup
- \forgetparskip
- \setlocalhsize
- \hsize\localhsize
- \forgetparindent
- \forgetbothskips
- \forgeteverypar
- \let\next=}
+ \glet\flushpostponednodedata\relax}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/spac-ver.lua b/Master/texmf-dist/tex/context/base/spac-ver.lua
index 83ee6e49208..66698a49e91 100644
--- a/Master/texmf-dist/tex/context/base/spac-ver.lua
+++ b/Master/texmf-dist/tex/context/base/spac-ver.lua
@@ -8,6 +8,8 @@ if not modules then modules = { } end modules ['spac-ver'] = {
-- we also need to call the spacer for inserts!
+-- todo: directly set skips
+
-- this code dates from the beginning and is kind of experimental; it
-- will be optimized and improved soon
--
@@ -27,6 +29,7 @@ local lpegmatch = lpeg.match
local unpack = unpack or table.unpack
local points = number.points
local allocate = utilities.storage.allocate
+local todimen = string.todimen
local P, C, R, S, Cc = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc
@@ -141,7 +144,7 @@ local function listtohash(str)
else
k = values[key]
if k then
- detail = string.todimen(detail)
+ detail = todimen(detail)
if detail then
t[k] = detail
end
@@ -169,7 +172,7 @@ function vspacing.definesnapmethod(name,method)
local t = listtohash(method)
snapmethods[n] = t
t.name, t.specification = name, method
- tex.write(n)
+ context(n)
end
--~ local rule_id = nodecodes.rule
@@ -266,6 +269,8 @@ local function floored(n)
end
end
+-- check variables.none etc
+
local function snap_hlist(where,current,method,height,depth) -- method.strut is default
local list = current.list
--~ print(table.serialize(method))
@@ -487,7 +492,8 @@ h, d = ch, cd
local lines = (ch+cd)/snaphtdp
if t then
local original = (h+d)/snaphtdp
- t[#t+1] = format("final lines: %s -> %s",original,lines)
+ local whatever = (ch+cd)/(texdimen.globalbodyfontstrutheight + texdimen.globalbodyfontstrutdepth)
+ t[#t+1] = format("final lines: %s -> %s (%s)",original,lines,whatever)
t[#t+1] = format("final height: %s -> %s",points(h),points(ch))
t[#t+1] = format("final depth: %s -> %s",points(d),points(cd))
end
@@ -567,7 +573,7 @@ do -- todo: interface.variables
local function analyze(str,oldcategory) -- we could use shorter names
for s in gmatch(str,"([^ ,]+)") do
- local amount, keyword, detail = lpegmatch(splitter,s)
+ local amount, keyword, detail = lpegmatch(splitter,s) -- the comma splitter can be merged
if not keyword then
report_vspacing("unknown directive: %s",s)
else
@@ -674,7 +680,7 @@ local function nodes_to_string(head)
if id == penalty_code then
t[#t+1] = format("%s:%s",ty,current.penalty)
elseif id == glue_code then
- t[#t+1] = format("%s:%s",ty,stripzeros(topoints(current.spec.width)))
+ t[#t+1] = format("%s:%s",ty,glue_to_string(current)) -- stripzeros(topoints(current.spec.width)))
elseif id == kern_code then
t[#t+1] = format("%s:%s",ty,stripzeros(topoints(current.kern)))
else
@@ -1297,7 +1303,7 @@ local builders = nodes.builders
local actions = nodes.tasks.actions("vboxbuilders")
-function nodes.builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction)
+function builders.vpack_filter(head,groupcode,size,packtype,maxdepth,direction)
local done = false
if head then
starttiming(builders)
@@ -1325,7 +1331,7 @@ end
local actions = nodes.tasks.actions("mvlbuilders")
-function nodes.builders.buildpage_filter(groupcode)
+function builders.buildpage_filter(groupcode)
starttiming(builders)
local head = texlists.contrib_head
local head, done = actions(head,groupcode)
@@ -1334,9 +1340,17 @@ function nodes.builders.buildpage_filter(groupcode)
return (done and head) or true
end
-callbacks.register('vpack_filter', nodes.builders.vpack_filter, "vertical spacing etc")
-callbacks.register('buildpage_filter', nodes.builders.buildpage_filter, "vertical spacing etc (mvl)")
+callbacks.register('vpack_filter', builders.vpack_filter, "vertical spacing etc")
+callbacks.register('buildpage_filter', builders.buildpage_filter, "vertical spacing etc (mvl)")
statistics.register("v-node processing time", function()
return statistics.elapsedseconds(builders)
end)
+
+-- interface
+
+commands.vspacing = vspacing.analyze
+commands.vspacingsetamount = vspacing.setskip
+commands.vspacingdefine = vspacing.setmap
+commands.vspacingcollapse = vspacing.collapsevbox
+commands.vspacingsnap = vspacing.snapbox
diff --git a/Master/texmf-dist/tex/context/base/spac-ver.mkiv b/Master/texmf-dist/tex/context/base/spac-ver.mkiv
index 897e9c9d732..23229b65078 100644
--- a/Master/texmf-dist/tex/context/base/spac-ver.mkiv
+++ b/Master/texmf-dist/tex/context/base/spac-ver.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Vertical,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,26 +17,14 @@
\registerctxluafile{spac-ver}{1.001}
-\newskip\blankskip \blankskip=\bigskipamount
+% todo: itemize : intro ... only when there is one or two lines preceding and then
+% keep these together i.e. \blank[intro]
-\def\skipfactor {.75}
-\def\skipgluefactor{.25}
-
-\def\normalskipamount
- {\openlineheight
- \ifgridsnapping \else \ifblankflexible
- \!!plus \skipgluefactor\openlineheight
- \!!minus\skipgluefactor\openlineheight
- \fi \fi
- \relax}
-\def\linedistance {\normalskipamount}
-\def\appliedblankskip{\skipfactor\linedistance}
-\def\lastblankskip {\blankskip}
-\def\currentblank {\v!big}
-\def\oldprevdepth {\prevdepth}
-\def\newprevdepth {-1001pt}
-\def\mindimen {1sp} % was: 0.00002pt
+% Isn't it about time to get rid of topskip i.e. make it equivalent to
+% \openstrutheight so that we can remove delta code.
+%
+% There might be more namespace protection.
%D There are two ways to influence the interline spacing. The
%D most general and often most consistent way is using
@@ -67,40 +55,51 @@
%D arguments) to set the interline space according to the
%D current font, e.g. a \type{\bfa}.
+% will be cleaned up but it will stay messy because we accept so
+% many variants
+
\newif\iflocalinterlinespace
-% font-ini
+\newskip\s_spac_vspacing_temp \s_spac_vspacing_temp\bigskipamount
-\ifx\bodyfontinterlinespecs\undefined
+\def\skipfactor {.75}
+\def\skipgluefactor{.25}
- \let\bodyfontinterlinespecs\empty
- \let\bodyfontinterlinespace\empty
+\def\normalskipamount
+ {\openlineheight
+ \ifgridsnapping \else \ifblankflexible
+ \!!plus \skipgluefactor\openlineheight
+ \!!minus\skipgluefactor\openlineheight
+ \fi \fi
+ \relax}
+\ifdefined\bodyfontinterlinespace \else
+ \let\bodyfontinterlinespace\empty
\fi
-\def\presetnormallineheight
+\unexpanded\def\presetnormallineheight % each bodyfont
{\edef\normallineheight{\interlinespaceparameter\c!line}%
- %done elsewhere : \spacing\!!plusone % new per 10/08/2004, else problems in otr / !! needed
\iflocalinterlinespace \else
- \doifdefined\bodyfontinterlinespecs
- {\doifsomething\bodyfontinterlinespace
- {\edef\normallineheight{\bodyfontinterlinespace}}}%
+ \edef\m_spac_normallineheight{\bodyfontinterlinespace}%
+ \ifx\m_spac_normallineheight\empty \else
+ \let\normallineheight\m_spac_normallineheight
+ \fi
\fi}
\unexpanded\def\setupspecifiedinterlinespace[#1]%
- {\getparameters[\??it\currentinterlinespace][#1]%
- \dosetupspecifiedinterlinespaceindeed}
+ {\setupcurrentinterlinespace[#1]%
+ \spac_linespacing_setup_specified_interline_space}
-\def\dosetupspecifiedinterlinespaceindeed
- {\edef\strutheightfactor {\interlinespaceparameter\c!height}%
- \edef\strutdepthfactor {\interlinespaceparameter\c!depth}%
+\def\spac_linespacing_setup_specified_interline_space
+ {\edef\strutheightfactor {\interlinespaceparameter\c!height }%
+ \edef\strutdepthfactor {\interlinespaceparameter\c!depth }%
\edef\minimumstrutheight {\interlinespaceparameter\c!minheight}%
- \edef\minimumstrutdepth {\interlinespaceparameter\c!mindepth}%
- \edef\minimumlinedistance{\interlinespaceparameter\c!distance}%
- \edef\normallineheight {\interlinespaceparameter\c!line}%
- \edef\topskipfactor {\interlinespaceparameter\c!top}%
- \edef\maxdepthfactor {\interlinespaceparameter\c!bottom}%
- \edef\baselinegluefactor {\interlinespaceparameter\c!stretch}%
+ \edef\minimumstrutdepth {\interlinespaceparameter\c!mindepth }%
+ \edef\minimumlinedistance{\interlinespaceparameter\c!distance }%
+ \edef\normallineheight {\interlinespaceparameter\c!line }%
+ \edef\topskipfactor {\interlinespaceparameter\c!top }%
+ \edef\maxdepthfactor {\interlinespaceparameter\c!bottom }%
+ \edef\baselinegluefactor {\interlinespaceparameter\c!stretch }%
% often topskip does more bad than good, so:
\ifx\topskipfactor\v!height
\let\topskipfactor\strutheightfactor
@@ -108,93 +107,87 @@
\setfontparameters % redundant, can be \setstrut, test first
\updateraggedskips} % yes indeed
+\installcorenamespace{interlinespacerelative}
+
+\let\setrelativeinterlinespace \relax % used elsewhere
\let\currentrelativeinterlinespace\empty
-\setvalue{\??it::\v!on }{\oninterlineskip}
-\setvalue{\??it::\v!off }{\offinterlineskip}
-\setvalue{\??it::\v!reset}{\let\currentrelativeinterlinespace\empty
- \let\setrelativeinterlinespace\relax
- \setfontparameters}
-\setvalue{\??it::\v!auto }{\let\setrelativeinterlinespace\dosetrelativeinterlinespace}
+\setvalue{\??interlinespacerelative\v!on }{\oninterlineskip}
+\setvalue{\??interlinespacerelative\v!off }{\offinterlineskip}
+\setvalue{\??interlinespacerelative\v!reset}{\let\currentrelativeinterlinespace\empty
+ \let\setrelativeinterlinespace\relax
+ \setfontparameters}
+\setvalue{\??interlinespacerelative\v!auto }{\let\setrelativeinterlinespace\spac_linespacing_set_relative_interlinespace}
-\def\dosetspecifiedrelativeinterlinespace#1% fragile?
+\def\spac_linespacing_set_specified_relative_interlinespace#1% fragile?
{\doifdimenstringelse{#1}
{\setupspecifiedinterlinespace[\c!line=#1]}
{\assignvalue{#1}\currentrelativeinterlinespace{1.00}{1.25}{1.50}%
\spacing\currentrelativeinterlinespace}}
\unexpanded\def\setuprelativeinterlinespace[#1]%
- {\processcommalist[#1]\dosetuprelativeinterlinespace}
+ {\processcommalist[#1]\spac_linespacing_setup_relative_interlinespace}
-\def\dosetuprelativeinterlinespace#1%
- {\ifcsname\??it::#1\endcsname
- \csname\??it::#1\endcsname
+\def\spac_linespacing_setup_relative_interlinespace#1%
+ {\ifcsname\??interlinespacerelative#1\endcsname
+ \csname\??interlinespacerelative#1\endcsname
\else
- \dosetspecifiedrelativeinterlinespace{#1}%
+ \spac_linespacing_set_specified_relative_interlinespace{#1}%
\fi}
-\def\dosetrelativeinterlinespace
+\def\spac_linespacing_set_relative_interlinespace
{\ifx\currentrelativeinterlinespace\empty\else
\spacing\currentrelativeinterlinespace
\fi}
-\let\setrelativeinterlinespace\relax
-
-\newtoks \everysetupglobalinterlinespace
-\newtoks \everysetuplocalinterlinespace
-
-\def\interlinespaceparameter #1{\csname\dointerlinespaceparameter{\??it\currentinterlinespace}#1\endcsname}
-\def\dointerlinespaceparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dointerlinespaceparentparameter\csname#1\s!parent\endcsname#2\fi}
-\def\dointerlinespaceparentparameter#1#2{\ifx#1\relax\s!empty\else\dointerlinespaceparameter#1#2\fi}
+\newtoks\everysetupglobalinterlinespace
+\newtoks\everysetuplocalinterlinespace
\newconditional\interlinespaceisset
-\let\currentinterlinespace\empty
-
-\unexpanded\def\defineinterlinespace
- {\dodoubleempty\dodefineinterlinespace}
+\installcorenamespace{interlinespace}
-\def\dodefineinterlinespace[#1][#2]%
- {\getparameters[\??it#1][\s!parent=\??it,#2]}
+\installcommandhandler \??interlinespace {interlinespace} \??interlinespace
\unexpanded\def\setupinterlinespace
- {\dodoubleempty\dosetupinterlinespace}
+ {\dodoubleempty\spac_linespacing_setup}
-\def\dosetupinterlinespace[#1][#2]%
+\def\spac_linespacing_setup[#1][#2]%
{\settrue\interlinespaceisset % reset has to be done when needed
\ifsecondargument
- \getparameters[\??it#1][#2]%
+ \setup_interlinespace[#1][#2]%
\else\iffirstargument
- \edef\currentinterlinespace{\ifcsname\??it#1\s!parent\endcsname#1\fi}%
- \ifx\currentinterlinespace\empty
- \complexsetupinterlinespace[#1]%
+ \ifcsname\namedinterlinespacehash{#1}\s!parent\endcsname
+ \edef\currentinterlinespace{#1}%
+ \spac_linespacing_setup_specified_interline_space
+ %\dosetupspecifiedinterlinespaceindeed
\else
- \dosetupspecifiedinterlinespaceindeed
+ \spac_linespacing_setup_specified_or_relative[#1]%
\fi
\else
\let\currentinterlinespace\empty
- \simplesetupinterlinespace
+ \spac_linespacing_synchronize_local
\fi\fi}
-\def\complexsetupinterlinespace[#1]% \commalistelement ipv #1
+\def\spac_linespacing_setup_specified_or_relative[#1]%
{\doifassignmentelse{#1}\setupspecifiedinterlinespace\setuprelativeinterlinespace[#1]%
\the\iflocalinterlinespace\everysetuplocalinterlinespace\else\everysetupglobalinterlinespace\fi}
-\def\simplesetupinterlinespace % adapts to the font
+\def\spac_linespacing_synchronize_local % adapts to the font
{\localinterlinespacetrue
\setfontparameters
\updateraggedskips % funny one here
\the\everysetuplocalinterlinespace
\localinterlinespacefalse}
-\def\dosetupcheckedinterlinespace#1% often a chain
+\unexpanded\def\dosetupcheckedinterlinespace#1% often a chain
{\edef\askedinterlinespace{#1}%
\ifx\askedinterlinespace\empty
- \simplesetupinterlinespace
- \else\ifcsname\??it\askedinterlinespace\s!parent\endcsname
+ \spac_linespacing_synchronize_local
+ \else\ifcsname\namedinterlinespacehash\askedinterlinespace\s!parent\endcsname % we could have a \s!check
\pushmacro\currentinterlinespace
\let\currentinterlinespace\askedinterlinespace
- \dosetupspecifiedinterlinespaceindeed
+ \spac_linespacing_setup_specified_interline_space % \dosetupspecifiedinterlinespaceindeed
\iflocalinterlinespace
\the\everysetuplocalinterlinespace
\else
@@ -205,8 +198,7 @@
\popmacro\currentinterlinespace
\else
\normalexpanded{\noexpand\doifassignmentelse{\askedinterlinespace}%
- \noexpand\setupspecifiedinterlinespace
- \noexpand\setuprelativeinterlinespace[\askedinterlinespace]}%
+ \setupspecifiedinterlinespace\setuprelativeinterlinespace[\askedinterlinespace]}%
\iflocalinterlinespace
\the\everysetuplocalinterlinespace
\else
@@ -225,115 +217,52 @@
\let\switchtointerlinespace\setuplocalinterlinespace
-\definecomplexorsimple\setupinterlinespace
-
-\def\removelastskip % a redefinition of plain
+% \definecomplexorsimple\setupinterlinespace
+
+%D Helpers
+
+\newskip \s_spac_lastskip
+\newdimen\d_spac_prevdepth
+\newcount\c_spac_spacefactor
+
+\unexpanded\def\removelastskip
{\ifvmode\ifdim\lastskip=\zeropoint\else\vskip-\lastskip\fi\fi}
-\def\doifoutervmode#1%
- {\ifvmode\ifinner\else#1\fi\fi}
+\def\doifoutervmode
+ {\ifvmode
+ \ifinner
+ \doubleexpandafter\gobbleoneargument
+ \else
+ \doubleexpandafter\firstofoneargument
+ \fi
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
-\def\dosomebreak#1%
+\unexpanded\def\dosomebreak#1%
{\doifoutervmode
- {\scratchskip\lastskip
+ {\s_spac_lastskip\lastskip
\removelastskip
- %\leavevmode\type{#1}%
#1\relax
- \ifdim\scratchskip=\zeropoint % else interference with footnotes
+ \ifdim\s_spac_lastskip=\zeropoint
+ % avoid interference with footnotes
\else
- \vskip\scratchskip
+ \vskip\s_spac_lastskip
\fi}}
-
-\def\packed
+
+\unexpanded\def\packed
{\nointerlineskip}
-\def\godown[#1]%
+\unexpanded\def\godown[#1]%
{\relax
\ifhmode\endgraf\fi
\ifvmode\nointerlineskip\vskip#1\relax\fi}
-
-\ifx\smallskip\undefined
-
- \def\smallskip{\vskip\smallskipamount}
- \def\medskip {\vskip\medskipamount}
- \def\bigskip {\vskip\bigskipamount}
-
-\fi
-\ifx\allowbreak\undefined
+\unexpanded\def\smallskip{\vskip\smallskipamount}
+\unexpanded\def\medskip {\vskip\medskipamount}
+\unexpanded\def\bigskip {\vskip\bigskipamount}
- \def\break {\penalty\ifhmode-\plustenthousand\else\ejectpenalty\fi}
- \def\nobreak {\penalty \plustenthousand}
- \def\allowbreak{\penalty \zeropoint}
- \def\filbreak {\par\vfil\penalty-200\vfilneg}
- \def\goodbreak {\par\penalty-500 }
-
-\fi
-
-%D Made slightly more readable:
-
-\ifx\vglue\undefined
-
- \def\vglue {\afterassignment\dovglue\scratchskip=}
- \def\hglue {\afterassignment\dohglue\scratchskip=}
- \def\topglue{\nointerlineskip\vglue-\topskip\vglue}
-
- \def\dovglue
- {\par
- \scratchdimen\prevdepth
- \hrule\!!height\zeropoint
- \nobreak
- \vskip\scratchskip
- \prevdepth\scratchdimen}
-
- \def\dohglue
- {\dontleavehmode % \leavevmode
- \scratchcounter\spacefactor
- \vrule\!!width\zeropoint
- \nobreak
- \hskip\scratchskip
- \spacefactor\scratchcounter}
-
-\fi
-
-\ifx\eject\undefined
-
- \def\eject{\par\break}
-
-\fi
-
-\ifx\supereject\undefined
-
- \def\supereject{\par\penalty\superpenalty}
-
-\fi
-
-\ifx\dosupereject\undefined
-
- \def\dosupereject
- {\ifnum\insertpenalties>\zerocount % something is being held over
- \line{}
- \kern-\topskip
- \nobreak
- \vfill\supereject
- \fi}
-
-\fi
-
-%D We adapt plain's \type {\removelastskip} a bit:
-
-\ifx\removelastskip\undefined
-
- \def\removelastskip
- {\ifvmode \ifdim\lastskip=\zeropoint \else
- \vskip-\lastskip
- \fi \fi}
-
-\fi
-
-\ifx\smallbreak\undefined
-
-\def\smallbreak
+\unexpanded\def\smallbreak
{\par
\ifdim\lastskip<\smallskipamount
\removelastskip
@@ -341,7 +270,7 @@
\smallskip
\fi}
-\def\medbreak
+\unexpanded\def\medbreak
{\par
\ifdim\lastskip<\medskipamount
\removelastskip
@@ -349,7 +278,7 @@
\medskip
\fi}
-\def\bigbreak
+\unexpanded\def\bigbreak
{\par
\ifdim\lastskip<\bigskipamount
\removelastskip
@@ -357,178 +286,310 @@
\bigskip
\fi}
-\fi
-
-\newskip\ctxparskip \ctxparskip\zeropoint
+\unexpanded\def\break {\penalty-\plustenthousand} % can be hmode or vmode
+\unexpanded\def\nobreak {\penalty \plustenthousand} % can be hmode or vmode
+\unexpanded\def\allowbreak{\penalty \zeropoint} % can be hmode or vmode
+\unexpanded\def\goodbreak {\par\penalty-500\relax} % forces vmode
+\unexpanded\def\filbreak {\par\vfil\penalty-200\vfilneg} % forces vmode
-\newconditional \flexiblewhitespace \settrue\flexiblewhitespace
+%D Made slightly more readable:
-\def\currentwhitespace {\zeropoint}
+\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{\nointerlineskip\vglue-\topskip\vglue}
-\definecomplexorsimple\setupwhitespace
+\def\spac_helpers_vglue_indeed
+ {\par
+ \d_spac_prevdepth\prevdepth
+ \hrule\!!height\zeropoint
+ \nobreak
+ \vskip\s_spac_lastskip
+ \prevdepth\d_spac_prevdepth}
+
+\def\spac_helpers_hglue_indeed
+ {\dontleavehmode % \leavevmode
+ \c_spac_spacefactor\spacefactor
+ \vrule\!!width\zeropoint
+ \nobreak
+ \hskip\s_spac_lastskip
+ \spacefactor\c_spac_spacefactor}
-\def\simplesetupwhitespace
- {\doifnot\currentwhitespace\v!none\dosetupwhitespace}
+%D We adapt plain's \type {\removelastskip} a bit:
-\def\complexsetupwhitespace[#1]%
- {\edef\nextcurrentwhitespace{#1}%
- \ifx\nextcurrentwhitespace\empty
- \simplesetupwhitespace
- \else
- \let\currentwhitespace\nextcurrentwhitespace
- \dosetupwhitespace
+\unexpanded\def\removelastskip % also in supp-box
+ {\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
+
+% The whitespace handler. We could cache settings but normally there are not
+% that many in a set.
+
+\installcorenamespace{whitespacemethod}
+
+\newskip \s_spac_whitespace_parskip \s_spac_whitespace_parskip\zeropoint
+\newconditional\c_spac_whitespace_flexible \settrue\c_spac_whitespace_flexible
+\newconstant \c_spac_whitespace_grid_mode % option in layout / 1=permit_half_lines
+
+%def\v_spac_whitespace_current{\zeropoint}
+\let\v_spac_whitespace_current\v!none
+
+\unexpanded\def\setupwhitespace
+ {\doifnextoptionalelse\spac_whitespace_setup_yes\spac_whitespace_setup_nop}
+
+\def\spac_whitespace_setup_nop
+ {\ifx\v_spac_whitespace_current\v!none\else
+ \spac_whitespace_setup
\fi}
-\newconstant\baselinegridmode % option in layout / 1=permit_half_lines
+\let\synchronizewhitespace\spac_whitespace_setup_nop
+
+\def\spac_whitespace_setup_yes[#1]%
+ {\edef\m_spac_whitespace_asked{#1}%
+ \ifx\m_spac_whitespace_asked\empty
+ \spac_whitespace_setup_nop
+ \else
+ \let\v_spac_whitespace_current\m_spac_whitespace_asked
+ \spac_whitespace_setup
+ \fi}
-\def\dosetupwhitespace % quick test for no list
- {\ifcsname\??ws\??ws\currentwhitespace\endcsname
- \csname\??ws\??ws\currentwhitespace\endcsname
+\def\spac_whitespace_setup % quick test for no list
+ {\ifcsname\??whitespacemethod\v_spac_whitespace_current\endcsname
+ \csname\??whitespacemethod\v_spac_whitespace_current\endcsname
\else
- \expandafter\processcommalist\expandafter[\currentwhitespace]\dowhitespacemethod % can be raw
+ \expandafter\processcommalist\expandafter[\v_spac_whitespace_current]\spac_whitespace_setup_method % can be raw
\fi\relax
\ifgridsnapping
- \setfalse\flexiblewhitespace
- \ifdim\ctxparskip>\zeropoint
- \ctxparskip
- \ifcase\baselinegridmode
- \baselineskip % normal ! ! ! ! !!
- \or
- \ifdim\scratchdimen=\baselineskip % maybe range
- \baselineskip % normal ! ! ! ! !!
- \else
- \numexpr\ctxparskip/\dimexpr.5\lineheight\relax\relax\dimexpr.5\lineheight\relax
- \fi
- \else
- \baselineskip % normal ! ! ! ! !!
- \fi
- \fi
+ \spac_whitespace_setup_grid
\else
- \ifconditional\flexiblewhitespace \else \ctxparskip1\ctxparskip \fi
+ \spac_whitespace_setup_normal
\fi
- \parskip\ctxparskip}
+ \parskip\s_spac_whitespace_parskip}
-\def\dodosetupwhitespace
- {\ifgridsnapping
- \setfalse\flexiblewhitespace
- \ctxparskip1\ctxparskip
- \ifdim\ctxparskip>\zeropoint
- \ifcase\baselinegridmode
- \ctxparskip\baselineskip % normal ! ! ! ! !!
+\def\spac_whitespace_setup_normal
+ {\ifconditional\c_spac_whitespace_flexible \else
+ \s_spac_whitespace_parskip\plusone\s_spac_whitespace_parskip
+ \fi}
+
+\def\spac_whitespace_setup_grid
+ {\setfalse\c_spac_whitespace_flexible
+ \ifdim\s_spac_whitespace_parskip>\zeropoint
+ \s_spac_whitespace_parskip
+ \ifcase\c_spac_whitespace_grid_mode
+ \baselineskip
\or
\ifdim\scratchdimen=\baselineskip % maybe range
- \ctxparskip\baselineskip % normal ! ! ! ! !!
+ \baselineskip
\else
- \ctxparskip\numexpr\ctxparskip/\dimexpr.5\lineheight\relax\relax\dimexpr.5\lineheight\relax
+ \numexpr\s_spac_whitespace_parskip/\dimexpr.5\lineheight\relax\relax\dimexpr.5\lineheight\relax
\fi
\else
- \ctxparskip\baselineskip % normal ! ! ! ! !!
+ \baselineskip
\fi
- \fi
- \else
- \ifconditional\flexiblewhitespace \else \ctxparskip1\ctxparskip \fi
- \fi
- \parskip\ctxparskip}
-
-\definesystemvariable {ws} % whitespace
+ \fi}
-\unexpanded\def\definewhitespacemethod[#1]#2{\setvalue{\??ws\??ws#1}{#2}}
+\unexpanded\def\installwhitespacemethod#1#2%
+ {\setvalue{\??whitespacemethod#1}{#2}}
-\definewhitespacemethod [\v!fix] {}
-\definewhitespacemethod [\v!fixed] {\setfalse\flexiblewhitespace}
-\definewhitespacemethod [\v!flexible] {\settrue\flexiblewhitespace}
-\definewhitespacemethod [\v!line] {\ctxparskip \baselineskip}
-\definewhitespacemethod [\v!halfline] {\ctxparskip.5\baselineskip}
-\definewhitespacemethod [\v!none] {\ctxparskip \zeropoint}
-\definewhitespacemethod [\v!big] {\ctxparskip \bigskipamount}
-\definewhitespacemethod [\v!medium] {\ctxparskip \medskipamount}
-\definewhitespacemethod [\v!small] {\ctxparskip \smallskipamount}
+\installwhitespacemethod \v!fix {}
+\installwhitespacemethod \v!fixed {\setfalse\c_spac_whitespace_flexible}
+\installwhitespacemethod \v!flexible {\settrue \c_spac_whitespace_flexible}
-\definewhitespacemethod [\s!default] {\simplesetupwhitespace} % {\stelwitruimteopnieuwin}
+\installwhitespacemethod \v!line {\s_spac_whitespace_parskip \baselineskip}
+\installwhitespacemethod \v!halfline {\s_spac_whitespace_parskip .5\baselineskip}
+\installwhitespacemethod \v!quarterline {\s_spac_whitespace_parskip.25\baselineskip}
+\installwhitespacemethod \v!none {\s_spac_whitespace_parskip \zeropoint}
+\installwhitespacemethod \v!big {\s_spac_whitespace_parskip \bigskipamount}
+\installwhitespacemethod \v!medium {\s_spac_whitespace_parskip \medskipamount}
+\installwhitespacemethod \v!small {\s_spac_whitespace_parskip \smallskipamount}
-\def\dowhitespacemethod#1%
- {\ifcsname\??ws\??ws#1\endcsname\csname\??ws\??ws#1\endcsname\else\ctxparskip#1\fi\relax}
+\installwhitespacemethod \s!default {\spac_whitespace_setup_nop}
-\def\nowhitespace{\vspacing[\v!nowhite]}
-\def\whitespace {\vspacing[\v!white]}
+\def\spac_whitespace_setup_method#1%
+ {\ifcsname\??whitespacemethod#1\endcsname
+ \csname\??whitespacemethod#1\endcsname
+ \else
+ \s_spac_whitespace_parskip#1\fi
+ \relax}
+
+\unexpanded\def\forgetparskip
+ {\s_spac_whitespace_parskip\zeropoint
+ \parskip\zeropoint
+ \let\v_spac_whitespace_current\v!none}
+
+% \installwhitespacemethod \s!unknown {\s_spac_whitespace_parskip\commalistelement\relax}
+%
+% \def\spac_whitespace_setup_method#1%
+% {\csname\??whitespacemethod\ifcsname\??whitespacemethod#1\endcsname#1\else\s!unknown\endcsname\relax}
+
+\unexpanded\def\nowhitespace{\vspacing[\v!nowhite]}
+\unexpanded\def\whitespace {\vspacing[\v!white]}
-% De onderstaande macro handelt ook de situatie dat er geen
-% tekst tussen \start ... \stop is geplaatst. Daartoe wordt de
-% laatste skip over de lege tekst heen gehaald. Dit komt goed
-% van pas bij het plaatsen van (mogelijk lege) lijsten.
+% Packed:
-\newconditional\noblankinpacked
-\newcount\packeddepth
+% todo: when packed blocks blank, we need to enable forced
+
+\newconditional\c_spac_packed_blank \settrue\c_spac_packed_blank
+\newcount \c_spac_packed_level
\unexpanded\def\startpacked
- {\dosingleempty\dostartpacked}
+ {\dosingleempty\spac_packed_start}
-\def\dostartpacked[#1]% nesting afvangen
- {\global\advance\packeddepth\plusone
+\def\spac_packed_start[#1]% nesting afvangen
+ {\global\advance\c_spac_packed_level\plusone
\par
- \ifnum\packeddepth=\plusone \ifvmode
- \bgroup
+ \ifnum\c_spac_packed_level=\plusone \ifvmode
+ \begingroup
\whitespace % not combined
\blank[\v!disable]%
- \doifelse{#1}\v!blank\setfalse\settrue\noblankinpacked
+ \doifelse{#1}\v!blank\settrue\setfalse\c_spac_packed_blank
\setupwhitespace[\v!none]%
\fi \fi}
\unexpanded\def\stoppacked
{\par
- \ifnum\packeddepth=\plusone \ifvmode
- \egroup
+ \ifnum\c_spac_packed_level=\plusone \ifvmode
+ \endgroup
\fi \fi
- \global\advance\packeddepth\minusone}
+ \global\advance\c_spac_packed_level\minusone}
\unexpanded\def\startunpacked
{\blank
- \bgroup}
+ \begingroup}
\unexpanded\def\stopunpacked
- {\egroup
+ {\endgroup
\blank}
-
-% De onderstaande macro's moeten nog eens nader worden uitgewerkt.
-% Ze spelen een rol bij de spatiering rond omkaderde teksten
-% en/of boxen zonder diepte.
% \prevdepth crosses pageboundaries!
%
% todo: a version that works ok inside a box
-\let\doaroundlinecorrection\relax
+\installcorenamespace{linesaround}
+
+\let\v_spac_lines_around_action_set\relax
+\let\m_spac_lines_around \empty
+
+% \setvalue{\??linesaround\v!blank }{\blank}
+% \letvalue{\??linesaround\empty }\relax
+% \setvalue{\??linesaround\s!unknown}{\blank[\m_spac_lines_around]}
+%
+% \unexpanded\def\startlinecorrection
+% {\bgroup
+% \dodoubleempty\spac_lines_start_correction}
+%
+% \def\spac_lines_start_correction[#1][#2]% #2 gobbles spaces
+% {\edef\m_spac_lines_around{#1}%
+% \expandafter\let\expandafter\spac_lines_action_around\csname\??linesaround
+% \ifcsname\??linesaround\m_spac_lines_around\endcsname\m_spac_lines_around\else\s!unknown\fi
+% \endcsname
+% \spac_lines_action_around
+% \startbaselinecorrection
+% \offbaselinecorrection
+% \ignorespaces}
+%
+% \unexpanded\def\stoplinecorrection
+% {\stopbaselinecorrection
+% \spac_lines_action_around
+% \egroup}
+
+\setvalue{\??linesaround\v!blank }{\blank}
+\letvalue{\??linesaround\empty }\relax
+\setvalue{\??linesaround\s!unknown}{\blank[\m_spac_lines_around]}
+
+\def\spac_lines_action_around % we used to let this one but it's cleaner this way
+ {\csname\??linesaround % i.e. do it twice
+ \ifcsname\??linesaround\m_spac_lines_around\endcsname\m_spac_lines_around\else\s!unknown\fi
+ \endcsname}
\unexpanded\def\startlinecorrection
- {\dodoubleempty\dostartlinecorrection}
+ {\endgraf
+ \bgroup
+ \dosingleempty\spac_lines_start_correction}
+
+\unexpanded\def\startlocallinecorrection
+ {\endgraf
+ \bgroup
+ \setlocalhsize
+ \hsize\localhsize
+ \dosingleempty\spac_lines_start_correction}
+
+\def\spac_lines_start_correction
+ {\ifvmode
+ \expandafter\spac_lines_start_correction_yes
+ \else
+ \expandafter\spac_lines_start_correction_nop
+ \fi}
-\def\dostartlinecorrection[#1][#2]% #2 gobbles spaces
- {\bgroup
- \processaction
- [#1]
- [ \v!blank=>\let\doaroundlinecorrection\blank,
- \s!default=>\let\doaroundlinecorrection\relax,
- \s!unknown=>{\def\doaroundlinecorrection{\blank[#1]}}]%
- \doaroundlinecorrection
- \startbaselinecorrection
- \offbaselinecorrection
- \ignorespaces}
+\def\spac_lines_start_correction_nop[#1]%
+ {\vbox\bgroup
+ \ignorespaces
+ \let\spac_lines_stop_correction\spac_lines_stop_correction_nop}
+
+\def\spac_lines_stop_correction_nop
+ {\removeunwantedspaces
+ \egroup}
+
+\newdimen\d_spac_prevdepth
-\unexpanded\def\stoplinecorrection
- {\stopbaselinecorrection
- \doaroundlinecorrection
+\def\spac_lines_start_correction_yes[#1]%
+ {\edef\m_spac_lines_around{#1}%
+ \spac_lines_action_around
+ \d_spac_prevdepth\prevdepth
+ \spac_lines_initialize_corrections
+ \offbaselinecorrection % ???
+ \setbox\scratchbox\vbox\bgroup
+ \ignorespaces
+ \let\spac_lines_stop_correction\spac_lines_stop_correction_yes}
+
+\unexpanded\def\spac_lines_stop_correction_yes
+ {\removeunwantedspaces
+ \egroup
+ \ifgridsnapping
+ \blank[\v!white]%
+ \snaptogrid\hbox{\box\scratchbox}%
+ \else
+ \ifdim\d_spac_prevdepth<\maxdimen
+ \unless\ifdim\d_spac_prevdepth<\zeropoint
+ \ifdim\d_spac_prevdepth<\strutdp \relax
+ \pushlastnode
+ \ifdim\d_spac_prevdepth>\zeropoint
+ \kern-\d_spac_prevdepth
+ \fi
+ \kern\strutdp
+ \prevdepth\strutdp
+ \poplastnode
+ \fi
+ \fi
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ \blank[\v!white,\the\d_spac_lines_correction_before]% \blank[\v!white]\dotopbaselinecorrection
+ \fi
+ \nointerlineskip % new
+ \dontleavehmode
+ \box\scratchbox
+ \endgraf
+ \blank[\the\d_spac_lines_correction_after]% \dobotbaselinecorrection
+ % \allowbreak % new, otherwise problems when many in a row
+ \prevdepth\strutdp
+ \fi
+ \spac_lines_action_around
\egroup}
-\def\correctwhitespace
- {\dowithnextbox
- {\startbaselinecorrection
- \flushnextbox
- \stopbaselinecorrection}%
- \vbox}
-
-\def\verticalstrut {\normalvbox{\hsize\zeropoint\forgetall\strut}}
-\def\horizontalstrut{\normalhbox {\strut}}
-
+\unexpanded\def\stoplinecorrection{\spac_lines_stop_correction}
+
+\let\stoplocallinecorrection\stoplinecorrection
+
+% todo:
+
+\unexpanded\def\correctwhitespace
+ {\dowithnextboxcs\correctwhitespacefinish\vbox}
+
+\unexpanded\def\correctwhitespacefinish
+ {\startbaselinecorrection
+ \flushnextbox
+ \stopbaselinecorrection}
+
+\unexpanded\def\verticalstrut {\vbox{\hsize\zeropoint\forgetall\strut}}
+\unexpanded\def\horizontalstrut{\hbox {\strut}}
+
% Hieronder volgen enkele instellingen en macro's ten behoeve
% van de interlinie en \strut. De waarden 2.8, 0.07, 0.72 en
% 0.28 zijn ooit eens ontleend aan INRS-TEX en moeten wellicht
@@ -581,15 +642,15 @@
\def\baselinefactor {2.8}
\def\baselinegluefactor {0}
-\def\minimumstrutheight {0pt}
-\def\minimumstrutdepth {0pt}
+\def\minimumstrutheight {\zeropoint}
+\def\minimumstrutdepth {\zeropoint}
\def\normallineheight {\baselinefactor ex}
\def\minimumlinedistance {\lineskip}
-\def\strutheight {0pt}
-\def\strutdepth {0pt}
-\def\strutwidth {0pt}
+\def\strutheight {\zeropoint}
+\def\strutdepth {\zeropoint}
+\def\strutwidth {\zeropoint}
\let\spacingfactor \plusone
@@ -599,61 +660,59 @@
\def\systemtopskipfactor {\topskipfactor}
\def\systemmaxdepthfactor {\maxdepthfactor}
-\ifdefined\globalbodyfontsize\else
- \newdimen\globalbodyfontsize
- \globalbodyfontsize=12pt
+\ifdefined\globalbodyfontsize \else
+ \newdimen\globalbodyfontsize
+ \globalbodyfontsize=12pt
\fi
-\ifdefined\normalizedbodyfontsize\else
- \def\normalizedbodyfontsize{12pt}
+\ifdefined\normalizedbodyfontsize \else
+ \def\normalizedbodyfontsize{12pt}
\fi
-% door een \dimen. Dit is geen probleem omdat (1) de default
-% korpsgrootte 12pt is en (2) de fonts nog niet geladen zijn
-% en de instellingen bij het laden nogmaals plaatsvinden.
-
-\def\topskipcorrection
+\unexpanded\def\topskipcorrection
{\simpletopskipcorrection
\vskip-\struttotal
\verticalstrut}
-\def\simpletopskipcorrection
+\unexpanded\def\simpletopskipcorrection
{\ifdim\topskip>\openstrutheight
% == \vskip\topskipgap
\vskip\topskip
\vskip-\openstrutheight
\fi}
-\def\settopskip % the extra test is needed for the lbr family
- {\topskip\systemtopskipfactor\globalbodyfontsize
- \ifgridsnapping \else
- \ifr@ggedbottom\!!plus5\globalbodyfontsize\fi
+\unexpanded\def\settopskip % the extra test is needed for the lbr family
+ {\topskip
+ \ifgridsnapping
+ \zeropoint
+ \else
+ \systemtopskipfactor\globalbodyfontsize
+ \ifcase\bottomraggednessmode % ragged bottom
+ \!!plus5\globalbodyfontsize
+ \fi
\fi
-\ifgridsnapping
- \topskip\zeropoint
-\fi
- \relax % the skip
+ %\relax
\topskipgap\topskip
\advance\topskipgap -\openstrutheight\relax
\ifdim\minimumstrutheight>\zeropoint
\ifdim\topskip<\minimumstrutheight
\topskip\minimumstrutheight\relax
\fi
- \else
+ \else
\ifdim\topskip<\strutheightfactor\openlineheight
\topskip\strutheightfactor\openlineheight\relax
\fi
- \fi}
+ \fi}
-\def\setmaxdepth
+\unexpanded\def\setmaxdepth
{\maxdepth\systemmaxdepthfactor\globalbodyfontsize}
-\def\normalbaselines
+\unexpanded\def\normalbaselines
{\baselineskip \normalbaselineskip
\lineskip \normallineskip
\lineskiplimit\normallineskiplimit}
-\def\setnormalbaselines
+\unexpanded\def\setnormalbaselines
{\ifdim\normallineheight>\zeropoint
\lineheight\normallineheight
\fi
@@ -678,13 +737,10 @@
\fi
\normallineskip\minimumlinedistance\relax % \onepoint\relax
\normallineskiplimit\zeropoint\relax
- \normalbaselines
- %\dosetupgridsnapping
- }
+ \normalbaselines}
-\def\spacing#1%
+\unexpanded\def\spacing#1% vertical
{\ifgridsnapping
- %\ifdim#1\points=\onepoint\else\showmessage\m!layouts{11}{\withoutpt\the\dimexpr#1\points\relax}\fi
\let\spacingfactor\plusone
\else
\edef\spacingfactor{#1}%
@@ -702,8 +758,8 @@
\let\restoreinterlinespace\relax
-\def\saveinterlinespace
- {\edef\restoreinterlinespace
+\unexpanded\def\saveinterlinespace
+ {\unexpanded\edef\restoreinterlinespace
{\lineheight \the\lineheight
\openstrutheight \the\openstrutheight
\openstrutdepth \the\openstrutdepth
@@ -722,15 +778,11 @@
%
% \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
-\ifx\strutbox\undefined
+\newbox\strutbox
- \newbox\strutbox
+\setbox\strutbox\hbox{\vrule\!!height8.5pt\!!depth3.5pt\!!width\zeropoint} % just a start
- \setbox\strutbox\normalhbox{\vrule height8.5pt depth3.5pt width\zeropoint}
-
- \def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
-
-\fi
+\def\strut{\relax\ifmmode\copy\else\unhcopy\fi\strutbox}
\let\normalstrut\strut
@@ -778,7 +830,7 @@
\dosetstrut}
\unexpanded\def\setcharstrut#1%
- {\setbox\strutbox\normalhbox{#1}%
+ {\setbox\strutbox\hbox{#1}%
\strutht\ht\strutbox
\strutdp\dp\strutbox
\dosetstrut}
@@ -791,13 +843,13 @@
%D Handy for math (used in mathml):
-\def\charhtstrut
+\unexpanded\def\charhtstrut
{\begingroup
\setcharstrut{GJY}%
\vrule\!!width\zeropoint\!!depth\zeropoint\!!height\strutht
\endgroup}
-\def\chardpstrut
+\unexpanded\def\chardpstrut
{\begingroup
\setcharstrut{gjy}%
\vrule\!!width\zeropoint\!!depth\strutdp\!!height\zeropoint
@@ -808,35 +860,34 @@
% treatment; tests with using an attribute so far have shown that
% it's slower because testing the attribute takes time too
-\newdimen\tempstrutdimen
-
-\def\dosetstrut
+\unexpanded\def\dosetstrut
{\let\strut\normalstrut
- \tempstrutdimen\dimexpr\strutht+\strutdp-\lineheight\relax
- \ifabsnum\tempstrutdimen<\plustwo
- % compensate rounding error /- 1sp to avoid too many
- % 1sp baselineskips in for instance verbatim
- \strutht\dimexpr\strutht-\tempstrutdimen\relax
+ \ifabsnum\dimexpr\strutht+\strutdp-\lineheight\relax<\plustwo
+ % compensate rounding error /- 1sp to avoid too many
+ % 1sp baselineskips in for instance verbatim
+ \strutht\dimexpr\lineheight-\strutdp\relax
+ \struttotal\lineheight
+ \else
+ \struttotal\dimexpr\strutht+\strutdp\relax
\fi
- \edef\strutheight{\the\strutht}% maybe better \number\strutht sp
+ \edef\strutheight{\the\strutht}%
\edef\strutdepth {\the\strutdp}%
\ifdim\strutwidth=\zeropoint
- \dosetstruthide
+ \spac_struts_set_hide
\else
- \dosetstrutvide
- \fi
- \struttotal\dimexpr\strutht+\strutdp\relax}
+ \spac_struts_set_vide
+ \fi}
-\def\dosetstruthide
- {\setbox\strutbox\normalhbox
+\def\spac_struts_set_hide
+ {\setbox\strutbox\hbox
{\vrule
\!!width \zeropoint
\!!height\strutht
\!!depth \strutdp}}
-\def\dosetstrutvide
- {\setbox\strutbox\normalhbox
- {\normalhbox to \zeropoint
+\def\spac_struts_set_vide
+ {\setbox\strutbox\hbox
+ {\hbox to \zeropoint
{% \hss % new, will be option
\vrule
\!!width \strutwidth
@@ -848,16 +899,19 @@
%D strut; occasionally a one scaled point difference can show
%D up with the lineheight.
-% experiment
+% This is more efficient (less callbacks):
-\newbox\emptystrutbox \setbox\emptystrutbox\emptyhbox
+\newbox\b_spac_struts_empty \setbox\b_spac_struts_empty\emptyhbox
-\def\dosetstruthide
- {\setbox\strutbox\copy\emptystrutbox
+\def\spac_struts_set_hide
+ {\setbox\strutbox\copy\b_spac_struts_empty
\ht\strutbox\strutht
\dp\strutbox\strutdp}
-\def\strut{\relax\dontleavehmode\copy\strutbox} % still callbacks for \hbox{\strut}
+\unexpanded\def\strut % still callbacks for \hbox{\strut}
+ {\relax
+ \dontleavehmode
+ \copy\strutbox}
\let\normalstrut\strut
@@ -871,36 +925,38 @@
%D \NC \NC a normal strut \NC {\showstruts\setupstrut\strut} \NC \NR
%D \stoptabulate
-\setvalue{@strut@\v!yes }{\setstrut}
-\setvalue{@strut@\v!auto }{\setautostrut}
-\setvalue{@strut@\v!no }{\setnostrut}
-\setvalue{@strut@\v!cap }{\setcapstrut}
-\setvalue{@strut@\v!fit }{\setfontstrut}
-\setvalue{@strut@\v!line }{\setstrut}
-\setvalue{@strut@\s!default}{\setstrut}
-\setvalue{@strut@\s!empty }{\setstrut}
+%D Beware: using an unknown value results in char struts.
+
+\installcorenamespace{struts}
\unexpanded\def\setupstrut
- {\dosingleempty\dosetupstrut}
+ {\dosingleempty\spac_struts_setup}
-\def\dosetupstrut[#1]% yet undocumented, todo: fontstrut
- {\ifcsname @strut@#1\endcsname
- \csname @strut@#1\endcsname
+\def\spac_struts_setup[#1]%
+ {\ifcsname\??struts#1\endcsname
+ \csname\??struts#1\endcsname % these are defined later
\else
\setcharstrut{#1}%
\fi}
-\def\showstruts
+\def\synchronizestrut#1% no [] parsing, faster for internal
+ {\ifcsname\??struts#1\endcsname
+ \csname\??struts#1\endcsname
+ \else
+ \setcharstrut{#1}%
+ \fi}
+
+\unexpanded\def\showstruts
{\setteststrut
\settestcrlf}
-
-\def\setteststrut
+
+\unexpanded\def\setteststrut
{\def\strutwidth{.8pt}%
\setstrut}
\def\autostrutfactor{1.1}
-\def\setautostrut
+\unexpanded\def\setautostrut
{\begingroup
\setbox\scratchbox\copy\strutbox
\setstrut
@@ -912,52 +968,79 @@
\endgroup
\fi\fi}
+\newbox\nostrutbox \setbox\nostrutbox\emptyhbox
+
+\unexpanded\def\setnostrut
+ {\setbox\strutbox\copy\nostrutbox
+ \let\strut\empty
+ \let\endstrut\empty
+ \let\begstrut\empty
+ \let\crlfplaceholder\empty}
+
% when enabled, sigstruts will remove themselves if nothing
% goes inbetween
\newsignal\strutsignal \setfalse\sigstruts
-\def\begstrut
- {\relax\ifcase\strutht\else
- \ifconditional\sigstruts
- \noindent\horizontalstrut
- \normalpenalty\plustenthousand
- \normalhskip-\strutsignal
- \normalhskip\strutsignal
- \else
- \strut
- \normalpenalty\plustenthousand
- \normalhskip\zeropoint
- \fi
- \expandafter \ignorespaces
+\unexpanded\def\begstrut
+ {\relax\ifcase\strutht
+ % \ignorespaces % maybe
+ \else
+ \spac_struts_beg
\fi}
-\def\endstrut
- {\relax\ifhmode\ifcase\strutht\else
- \ifconditional\sigstruts
- \ifdim\lastskip=\strutsignal
- \unskip\unskip\unpenalty\setbox\scratchbox\lastbox
- \else
- \normalpenalty\plustenthousand
- \normalhskip\zeropoint
- \strut
- \fi
+\def\spac_struts_beg
+ {\ifconditional\sigstruts
+ \spac_struts_beg_signal
+ \else
+ \spac_struts_beg_normal
+ \fi
+ \ignorespaces}
+
+\def\spac_struts_beg_signal
+ {\noindent\horizontalstrut
+ \penalty\plustenthousand
+ \hskip-\strutsignal
+ \hskip\strutsignal}
+
+\def\spac_struts_beg_normal
+ {\strut
+ \penalty\plustenthousand
+ \hskip\zeropoint}
+
+\unexpanded\def\endstrut
+ {\relax\ifhmode
+ \ifcase\strutht
+ % \removeunwantedspaces % maybe
\else
- \removeunwantedspaces
- \normalpenalty\plustenthousand
- \normalhskip\zeropoint
- \strut
+ \spac_struts_end
\fi
- \fi\fi}
+ \fi}
-\newbox\nostrutbox \setbox\nostrutbox\emptyhbox
+\def\spac_struts_end
+ {\ifconditional\sigstruts
+ \spac_struts_end_signal
+ \else
+ \spac_struts_end_normal
+ \fi}
-\def\setnostrut
- {\setbox\strutbox\copy\nostrutbox
- \let\strut\empty
- \let\endstrut\empty
- \let\begstrut\empty
- \let\crlfplaceholder\empty}
+\def\spac_struts_end_signal
+ {\ifdim\lastskip=\strutsignal
+ \unskip
+ \unskip
+ \unpenalty
+ \setbox\scratchbox\lastbox
+ \else
+ \penalty\plustenthousand
+ \hskip\zeropoint
+ \strut
+ \fi}
+
+\def\spac_struts_end_normal
+ {\removeunwantedspaces
+ \penalty\plustenthousand
+ \hskip\zeropoint
+ \strut}
% unsave:
%
@@ -975,22 +1058,31 @@
%
% so:
-\def\pseudostrut
+\unexpanded\def\pseudostrut
{\noindent} % better: \dontleavehmode
\let\pseudobegstrut\pseudostrut
-
\let\pseudoendstrut\removeunwantedspaces
-\def\resetteststrut
+\unexpanded\def\resetteststrut
{\def\strutwidth{\zeropoint}% no let
\setstrut}
-\ifdefined\setfontparameters\else
- % problems ! ! ! !
- \def\setfontparameters{\the\everybodyfont}
+\ifdefined\setfontparameters \else
+ \def\setfontparameters{\the\everybodyfont}
\fi
+%D Keyword based strutting:
+
+\letvalue{\??struts\v!yes }\setstrut % \setvalue{\??struts\v!yes }{\setstrut}
+\letvalue{\??struts\v!auto }\setautostrut % \setvalue{\??struts\v!auto }{\setautostrut}
+\letvalue{\??struts\v!no }\setnostrut % \setvalue{\??struts\v!no }{\setnostrut}
+\letvalue{\??struts\v!cap }\setcapstrut % \setvalue{\??struts\v!cap }{\setcapstrut}
+\letvalue{\??struts\v!fit }\setfontstrut % \setvalue{\??struts\v!fit }{\setfontstrut}
+\letvalue{\??struts\v!line }\setstrut % \setvalue{\??struts\v!line }{\setstrut}
+\letvalue{\??struts\s!default}\setstrut % \setvalue{\??struts\s!default}{\setstrut}
+\letvalue{\??struts\empty }\setstrut % \setvalue{\??struts\empty }{\setstrut}
+
%D Handy:
\def\baselinedistance{\the\lineheight}
@@ -1000,64 +1092,56 @@
%D why|>| this assignment gives troubles in for instance the
%D visual debugger.
-\def\offinterlineskip
+\unexpanded\def\offinterlineskip
{\baselineskip-\thousandpoint
\lineskip\zeropoint
\lineskiplimit\maxdimen
% We also need this here now; thanks to taco for figuring that out!
\def\minimumlinedistance{\zeropoint}}
-\def\nointerlineskip
+\unexpanded\def\nointerlineskip
{\prevdepth-\thousandpoint}
-\let\normaloffinterlineskip=\offinterlineskip % knuth's original
+\let\normaloffinterlineskip\offinterlineskip % knuth's original
%D My own one:
-\def\dopushinterlineskip
+\unexpanded\def\spac_helpers_push_interlineskip_yes
{\edef\oninterlineskip
{\baselineskip\the\baselineskip
\lineskip\the\lineskip
\lineskiplimit\the\lineskiplimit
\noexpand\edef\noexpand\minimumlinedistance{\the\dimexpr\minimumlinedistance}%
- \let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}}
+ \let\noexpand\offinterlineskip\noexpand\normaloffinterlineskip}} % \noexpand not needed
-\def\nopushinterlineskip
+\unexpanded\def\spac_helpers_push_interlineskip_nop
{\let\oninterlineskip\setnormalbaselines}
-\def\offinterlineskip
+\unexpanded\def\offinterlineskip
{\ifdim\baselineskip>\zeropoint
- \dopushinterlineskip
+ \spac_helpers_push_interlineskip_yes
\else
- \nopushinterlineskip
+ \spac_helpers_push_interlineskip_nop
\fi
\normaloffinterlineskip}
-\let\oninterlineskip=\relax
-
-\def\leaveoutervmode
+\let\oninterlineskip\relax
+
+\unexpanded\def\leaveoutervmode
{\ifvmode\ifinner\else
\leavevmode
\fi\fi}
-% We stellen enkele penalties anders in dan Plain TEX:
-%
-% \widowpenalty=\defaultwidowpenalty\relax
-% \clubpenalty =\defaultclubpenalty \relax
-
-\def\resetpenalties#1%
+\unexpanded\def\resetpenalties#1%
{\ifdefined#1%
#1\minusone
\fi}
-\def\setpenalties#1#2#3%
+\unexpanded\def\setpenalties#1#2#3%
{\ifdefined#1% space before #3 prevents lookahead problems, needed when #3=text
#1\numexpr#2+\plusone\relax\space\doexpandedrecurse{\the\numexpr#2\relax}{ #3}\zerocount\relax
\fi}
-\def\doexpandedrecurse#1#2%
- {\ifnum#1>\zerocount#2\@EA\doexpandedrecurse\@EA{\the\numexpr#1-1\relax}{#2}\fi}
-
%D \macros
%D {keeplinestogether}
%D
@@ -1066,19 +1150,19 @@
% just before margintexts ... will eventually be done differently in mkiv using
% attributes
-\newcount\nofkeeplinestogether
+\newcount\c_spac_keep_lines_together
\let\restoreinterlinepenalty\relax
-\def\dorestoreinterlinepenalty
+\unexpanded\def\spac_penalties_restore
{\global\let\restoreinterlinepenalty\relax
\global\resetpenalties\interlinepenalties
- \global\nofkeeplinestogether\zerocount}
+ \global\c_spac_keep_lines_together\zerocount}
-\def\keeplinestogether#1%
- {\ifnum#1>\nofkeeplinestogether
- \global\nofkeeplinestogether#1%
- \global\setpenalties\interlinepenalties\nofkeeplinestogether\plustenthousand
- \global\let\restoreinterlinepenalty\dorestoreinterlinepenalty
+\unexpanded\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
+ \global\let\restoreinterlinepenalty\spac_penalties_restore
\fi}
\newif\ifgridsnapping % to be sure
@@ -1093,7 +1177,7 @@
\def\defaultgriddisplaywidowpenalty {0}
\def\defaultgridbrokenpenalty {0}
-\def\nopenalties
+\unexpanded\def\nopenalties
{\widowpenalty \zerocount
\clubpenalty \zerocount
\brokenpenalty \zerocount
@@ -1101,36 +1185,36 @@
\finalhyphendemerits \zerocount
\adjdemerits \zerocount}
-\def\setdefaultpenalties
+\unexpanded\def\setdefaultpenalties
{\directsetup{\systemsetupsprefix\s!default}}
\startsetups [\systemsetupsprefix\s!reset]
- \resetpenalties\widowpenalties
- \resetpenalties\clubpenalties
- \resetpenalties\interlinepenalties
+ \resetpenalties\widowpenalties
+ \resetpenalties\clubpenalties
+ \resetpenalties\interlinepenalties
\stopsetups
% we use \directsetup because it's faster and we know there is no csl
\startsetups [\systemsetupsprefix\s!default]
- \directsetup{\systemsetupsprefix\s!reset}
+ \directsetup{\systemsetupsprefix\s!reset}
- \widowpenalty \defaultwidowpenalty
- \clubpenalty \defaultclubpenalty
- \displaywidowpenalty\defaultdisplaywidowpenalty
- \brokenpenalty \defaultbrokenpenalty
+ \widowpenalty \defaultwidowpenalty
+ \clubpenalty \defaultclubpenalty
+ \displaywidowpenalty\defaultdisplaywidowpenalty
+ \brokenpenalty \defaultbrokenpenalty
\stopsetups
\startsetups [\v!grid] [\systemsetupsprefix\s!default]
- \directsetup{\systemsetupsprefix\s!reset}
+ \directsetup{\systemsetupsprefix\s!reset}
- \widowpenalty \defaultgridwidowpenalty
- \clubpenalty \defaultgridclubpenalty
- \displaywidowpenalty\defaultgriddisplaywidowpenalty
- \brokenpenalty \defaultgridbrokenpenalty
+ \widowpenalty \defaultgridwidowpenalty
+ \clubpenalty \defaultgridclubpenalty
+ \displaywidowpenalty\defaultgriddisplaywidowpenalty
+ \brokenpenalty \defaultgridbrokenpenalty
\stopsetups
@@ -1138,11 +1222,11 @@
\startsetups [\systemsetupsprefix\v!strict]
- \directsetup{\systemsetupsprefix\s!reset}
+ \directsetup{\systemsetupsprefix\s!reset}
- \setpenalties\widowpenalties2\maxdimen
- \setpenalties\clubpenalties 2\maxdimen
- \brokenpenalty \maxdimen
+ \setpenalties\widowpenalties\plustwo\maxdimen
+ \setpenalties\clubpenalties \plustwo\maxdimen
+ \brokenpenalty \maxdimen
\stopsetups
@@ -1150,59 +1234,10 @@
%D To be checked:
-\ifx\savedstrutbox\undefined \newbox\savedstrutbox \fi
-
-\def\savestrut {\setbox\savedstrutbox\copy\strutbox}
-\def\savedstrut{\copy \savedstrutbox}
-
-%D Page spacing
-
-\newconstant\bottomraggednessmode % 0=ragged 1=normal/align 2=baseline
-
-\def\bottomalignlimit{3\lineheight}
-
-\newif\ifn@rmalbottom
-\newif\ifr@ggedbottom
-\newif\ifb@selinebottom
-
-\def\normalbottom
- {% \topskip 10pt
- \r@ggedbottomfalse}
-
-\def\raggedbottom
- {\bottomraggednessmode\zerocount
- \n@rmalbottomfalse
- \r@ggedbottomtrue
- \b@selinebottomfalse
- \settopskip}
+\newbox\b_spac_struts_saved
-\def\alignbottom
- {\bottomraggednessmode\plusone
- \n@rmalbottomtrue
- \r@ggedbottomfalse
- \b@selinebottomfalse
- \settopskip}
-
-\def\baselinebottom
- {\bottomraggednessmode\plustwo
- \n@rmalbottomfalse
- \r@ggedbottomfalse
- \b@selinebottomtrue
- \settopskip}
-
-\let\normalbottom=\alignbottom % downward compatible
-
-% so, the new one will be
-%
-% \bottomraggednessmode=0 % 0=ragged 1=normal/align 2=baseline
-%
-% \def\bottomalignlimit{3\lineheight} % will be settable
-%
-% \def\raggedbottom {\bottomraggednessmode\zerocount\settopskip}
-% \def\alignbottom {\bottomraggednessmode\plusone \settopskip}
-% \def\baselinebottom{\bottomraggednessmode\plustwo \settopskip}
-%
-% \let\normalbottom =\alignbottom
+\unexpanded\def\savestrut {\setbox\b_spac_struts_saved\copy\strutbox}
+\unexpanded\def\savedstrut{\copy \b_spac_struts_saved}
%D Good old blank redone:
@@ -1217,6 +1252,9 @@
% TODO: NAMED SNAPPERS
+\installcorenamespace{gridsnappers}
+\installcorenamespace{gridsnapperattributes}
+
\newskip \bodyfontlineheight
\newdimen \bodyfontstrutheight
\newdimen \bodyfontstrutdepth
@@ -1228,40 +1266,40 @@
\def\snappedvboxattribute{\ifgridsnapping attr \snapvboxattribute \attribute\snapmethodattribute\fi}
\def\setlocalgridsnapping{\ifgridsnapping \attribute \snapvboxattribute \attribute\snapmethodattribute\fi}
-\def\dosetlocalgridsnapping#1%
+\def\spac_grids_set_local_snapping#1%
{\ifgridsnapping
\doifsomething{#1}%
- {\autosetsnapvalue{#1}%
+ {\spac_grids_snap_value_set{#1}%
\attribute \snapvboxattribute \attribute\snapmethodattribute}%
\fi}
-\def\installsnapvalues#1#2% todo: a proper define
+\unexpanded\def\installsnapvalues#1#2% todo: a proper define
{\edef\currentsnapper{#1:#2}%
- \ifcsname\currentsnapper\endcsname \else
- \setevalue\currentsnapper{\ctxlua{builders.vspacing.definesnapmethod("#1","#2")}}%
+ \ifcsname\??gridsnapperattributes\currentsnapper\endcsname \else
+ \setevalue{\??gridsnapperattributes\currentsnapper}{\ctxlua{builders.vspacing.definesnapmethod("#1","#2")}}%
\fi
- \setevalue{\??gr:#1}{\attribute\snapmethodattribute\csname\currentsnapper\endcsname\space}}
+ \setevalue{\??gridsnappers#1}{\attribute\snapmethodattribute\csname\??gridsnapperattributes\currentsnapper\endcsname\space}}
\unexpanded\def\definegridsnapping
- {\dodoubleargument\dodefinegridsnapping}
+ {\dodoubleargument\spac_grids_define}
-\def\dodefinegridsnapping[#1][#2]%
+\def\spac_grids_define[#1][#2]%
{\installsnapvalues{#1}{#2}}
-\edef\resetsnapvalue
+\edef\spac_grids_snap_value_reset
{%\gridsnappingfalse
\attribute\snapmethodattribute\attributeunsetvalue}
-\def\setsnapvalue#1%
+\def\spac_grids_snap_value_set#1%
{%\gridsnappingtrue
- \ifcsname\??gr:#1\endcsname\csname\??gr:#1\endcsname\fi}
+ \ifcsname\??gridsnappers#1\endcsname\csname\??gridsnappers#1\endcsname\fi}
-\def\autosetsnapvalue#1%
- {\ifcsname\??gr:#1\endcsname
- \csname\??gr:#1\endcsname
+\def\spac_grids_snap_value_auto#1%
+ {\ifcsname\??gridsnappers#1\endcsname
+ \csname\??gridsnappers#1\endcsname
\else
\installsnapvalues\s!dummy{#1}%
- \csname\??gr:\s!dummy\endcsname
+ \csname\??gridsnappers\s!dummy\endcsname
\fi}
% \installsnapvalues{loose} {\v!maxdepth:0.8,\v!maxheight:0.8,\v!strut}
@@ -1279,7 +1317,9 @@
% minheight round height down
% maxheight round height up
% local use local interline space
-% shift:-3tp vertical shift within box
+% offset:-3tp vertical shift within box
+% bottom:lines
+% top:lines
%D We're not downward compatible with \MKII !
@@ -1300,23 +1340,23 @@
\definegridsnapping[\v!first] [\v!first]
\definegridsnapping[\v!last] [\v!last]
\definegridsnapping[\v!high] [\v!minheight,\v!maxdepth,\v!none]
+\definegridsnapping[\v!one] [\v!minheight,\v!mindepth]
\definegridsnapping[\v!low] [\v!maxheight,\v!mindepth,\v!none]
+\definegridsnapping[\v!none] [\v!none]
\definegridsnapping[\v!line] [\v!line]
\definegridsnapping[\v!strut] [\v!strut]
\definegridsnapping[\v!max] [\v!maxdepth,\v!maxheight,\v!strut]
\definegridsnapping[\v!min] [\v!mindepth,\v!minheight,\v!strut]
-\newtoks\everysetupgridsnapping % this only happens at the setuplayout level
+\definegridsnapping[\v!middle] [\v!maxheight,\v!maxdepth] % used in placement
-\def\dosetupgridsnapping{\the\everysetupgridsnapping} % not used !
-
-\def\synchronizelocallinespecs
+\unexpanded\def\synchronizelocallinespecs
{\bodyfontlineheight \normallineheight
\bodyfontstrutheight\strutheight
\bodyfontstrutdepth \strutdepth}
-\def\synchronizegloballinespecs
+\unexpanded\def\synchronizegloballinespecs
{\global\globalbodyfontlineheight \normallineheight
\global\globalbodyfontstrutheight\strutheight
\global\globalbodyfontstrutdepth \strutdepth}
@@ -1330,65 +1370,84 @@
\synchronizelocallinespecs
\to \everysetuplocalinterlinespace
+%D We still have to synchronize these:
+
+\unexpanded\def\synchronizeskipamounts
+ {\bigskipamount
+ \skipfactor\baselineskip
+ plus\skipgluefactor\baselineskip
+ minus\skipgluefactor\baselineskip
+ \relax
+ \medskipamount \bigskipamount \divide\medskipamount \plustwo
+ \smallskipamount\bigskipamount \divide\smallskipamount\plusfour}
+
+\appendtoks
+ \synchronizeskipamounts
+\to \everysetupglobalinterlinespace
+
+\appendtoks
+ \synchronizeskipamounts
+\to \everysetuplocalinterlinespace
+
%D Snapping.
\newif\ifgridsnapping
\let\showgridsnapping\relax
-\def\snaptogrid {\dosingleempty\dosnaptogrid}
-\def\moveongrid {\dosingleempty\domoveongrid}
-\unexpanded\def\placeongrid{\dosingleempty\doplaceongrid}
+%unexpanded\def\moveongrid {\dosingleempty\spac_grids_move_on}
+\unexpanded\def\snaptogrid {\dosingleempty\spac_grids_snap_to}
+\unexpanded\def\placeongrid{\dosingleempty\spac_grids_place_on}
-\def\dodomoveongrid[#1]%
- {} % gone, unless we set an attribute
+% \def\spac_grids_move_on[#1]%
+% {[obsolete]} % gone, unless we set an attribute
-\def\doplaceongrid[#1]%
+\def\spac_grids_place_on[#1]%
{\snaptogrid[#1]\vbox} % mark as done
-\def\dosnaptogrid[#1]% list or predefined
+\def\spac_grids_snap_to[#1]% list or predefined
{\ifgridsnapping
- \expandafter\dodosnaptogrid
+ \expandafter\spac_grids_snap_to_indeed
\else
\expandafter\gobbleoneargument
\fi{#1}}
-\def\dodosnaptogrid#1%
+\def\spac_grids_snap_to_indeed#1%
{\bgroup
- \resetsnapvalue
- \dowithnextbox{\dododosnaptogrid{#1}}}
+ \spac_grids_snap_value_reset
+ \dowithnextbox{\spac_grids_snap_to_finish{#1}}}
% eventually there will always be a line snap
-\def\dododosnaptogrid#1%
+\def\spac_grids_snap_to_finish#1%
{\ifvbox\nextbox % this will go away
- \ctxlua{builders.vspacing.collapsevbox(\number\nextbox)}% isn't that already done?
+ \ctxcommand{vspacingcollapse(\number\nextbox)}% isn't that already done?
\fi
- \doifelsenothing{#1}{\setsnapvalue\v!normal}{\autosetsnapvalue{#1}}%
- \ctxlua{builders.vspacing.snapbox(\number\nextbox,\number\attribute\snapmethodattribute)}%
+ \doifelsenothing{#1}{\spac_grids_snap_value_set\v!normal}{\spac_grids_snap_value_set{#1}}%
+ \ctxcommand{vspacingsnap(\number\nextbox,\number\attribute\snapmethodattribute)}%
\ifvbox\nextbox\vbox\else\hbox\fi attr \snapmethodattribute \zerocount {\box\nextbox}%
\egroup}
-\def\docheckgridsnappingnop
+\def\spac_grids_check_nop
{\gridsnappingfalse
\resetsystemmode\v!grid
- \resetsnapvalue}
+ \spac_grids_snap_value_reset}
-\def\docheckgridsnappingyes
+\def\spac_grids_check_yes
{\gridsnappingtrue
\setsystemmode\v!grid
- \autosetsnapvalue\askedgridmode}
+ \spac_grids_snap_value_set\askedgridmode}
-\def\docheckgridsnapping
+\unexpanded\def\synchronizegridsnapping
{\edef\askedgridmode{\layoutparameter\c!grid}%
\ifx\askedgridmode\v!no % official
- \docheckgridsnappingnop
+ \spac_grids_check_nop
\else\ifx\askedgridmode\v!off % for taco and luigi
- \docheckgridsnappingnop
+ \spac_grids_check_nop
\else\ifx\askedgridmode\empty % to be sure
- \docheckgridsnappingnop
+ \spac_grids_check_nop
\else
- \docheckgridsnappingyes
+ \spac_grids_check_yes
\fi\fi\fi}
%D Visualization:
@@ -1400,11 +1459,11 @@
three=blue,
four=gray]
-\def\setgridtracebox#1[#2]% % maybe reverse the order
+\unexpanded\def\setgridtracebox#1[#2]% % maybe reverse the order
{\setbox\nextbox#1%
{\hbox
{\hbox to \zeropoint
- {\setlayoutcomponentattribute\v!grid\v!test
+ {\setlayoutcomponentattribute{\v!grid:\v!test}%
\color[grid:#2]{\ruledhbox \layoutcomponentboxattribute {\fakebox\nextbox}}%
\hss}%
\flushnextbox}}}
@@ -1412,10 +1471,22 @@
\setnewconstant\gridboxlinenomode\plusone % 0:nothing 1:all 2:lines 3:frame 4:l/r
\setnewconstant\gridboxlinemode \plusone
-\def\gridboxvbox {\ifcase\gridboxlinemode\vbox\or\ruledvbox\or\vbox\or\ruledvbox\else\ruledvbox\fi}
+\unexpanded\def\gridboxvbox
+ {\ifcase\gridboxlinemode
+ \vbox
+ \or
+ \ruledvbox
+ \or
+ \vbox
+ \or
+ \ruledvbox
+ \else
+ \ruledvbox
+ \fi}
+
\def\gridboxwidth{\ifcase\gridboxlinemode0\or.5\or.5\or0\else.5\fi\testrulewidth}
-\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
+\unexpanded\def\setgridbox#1#2#3% maybe ifgridsnapping at outer level
{\setbox#1\gridboxvbox to #3 % given size
{\forgetall
\resetteststrut
@@ -1427,10 +1498,10 @@
\fi
\gridboxvbox % calculated size
{\getrawnoflines{#3}% \getnoflines{#3}%
- \scratchdimen#2\advance\scratchdimen \lineheight
+ \scratchdimen\dimexpr#2+\lineheight\relax
\dorecurse\noflines
{\strut
- \hskip-.5\lineheight
+ \hskip-.5\lineheight\relax
\ifcase\gridboxlinenomode\or
\rlap
{\hskip.2\bodyfontsize\hskip\scratchdimen
@@ -1452,22 +1523,22 @@
\def\fuzzysnappedbox#1#2% \box<n> \unvbox<n>
{#1#2}
-\def\moveboxontogrid#1#2#3% will become obsolete
+\def\moveboxontogrid#1#2#3% will become obsolete, but it needs checking
{}
%D Helper:
-\def\doassignsomeskip#1\to#2% ook nog \v!halfline+fuzzysnap
- {\doifelse{#1}\v!line
- {#2\ifgridsnapping
+\unexpanded\def\spac_helpers_assign_skip#1#2% ook nog \v!halfline+fuzzysnap
+ {\doifelse{#2}\v!line
+ {#1\ifgridsnapping
\bodyfontlineheight
\else
\openlineheight
\fi}
{\ifgridsnapping
- \assigndimension{#1}{#2}{.25\bodyfontlineheight}{.5\bodyfontlineheight}\bodyfontlineheight
+ \assigndimension{#2}{#1}{.25\bodyfontlineheight}{.5\bodyfontlineheight}\bodyfontlineheight
\else
- \assigndimension{#1}{#2}\smallskipamount\medskipamount\bigskipamount
+ \assigndimension{#2}{#1}\smallskipamount\medskipamount\bigskipamount
\fi}%
\relax}
@@ -1493,9 +1564,25 @@
% \defineblankmethod [\v!joinedup] {\ifvmode\nointerlineskip\fi}
% todo, in grid mode: builders.vspacing.fixed = false
+%
+% \ifgridsnapping will go
+
+\installcorenamespace{vspacingamount}
+
+\unexpanded\def\definevspacingamount
+ {\dotripleempty\spac_vspacing_define_amount}
+
+\def\spac_vspacing_define_amount[#1][#2][#3]% can be combined
+ {\setvalue{\??vspacingamount#1}{\ifgridsnapping#3\else#2\fi}%
+ \ctxcommand{vspacingsetamount("#1")}}
+
+\unexpanded\def\definevspacing
+ {\dodoubleempty\spac_vspacing_define}
+
+\def\spac_vspacing_define[#1][#2]%
+ {\ctxcommand{vspacingdefine("#1","#2")}}
-\let\saveouterspacing \relax % for old times sake
-\let\restoreouterspacing\relax % for old times sake
+%D The injector code (generated at the \LUA\ end):
\newtoks\everybeforeblankhandling
\newtoks\everyafterblankhandling
@@ -1503,28 +1590,10 @@
\newconditional\someblankdone
\appendtoks
- \blankskip\zeropoint
+ \s_spac_vspacing_temp\zeropoint
\attribute\skipcategoryattribute\plusone
\attribute\skippenaltyattribute \attributeunsetvalue
\attribute\skiporderattribute \attributeunsetvalue
- \ifgridsnapping % \ifblankflexible
- \setfalse\blankisfixed
- \else
- \settrue\blankisfixed
- \fi
-\to \everybeforeblankhandling
-
-\appendtoks
- \ifconditional\blankisfixed
- \blankskip1\blankskip
- \else
- \blankskip1\blankskip\!!plus\skipgluefactor\blankskip\!!minus\skipgluefactor\blankskip
- \fi
-\to \everyafterblankhandling
-
-% \ifgridsnapping will go
-
-\appendtoks
\ifgridsnapping
\settrue\blankisfixed
\else
@@ -1532,6 +1601,14 @@
\fi
\to \everybeforeblankhandling
+\appendtoks
+ \s_spac_vspacing_temp\plusone\s_spac_vspacing_temp
+ \ifconditional\blankisfixed \else
+ \!!plus \skipgluefactor\s_spac_vspacing_temp
+ \!!minus\skipgluefactor\s_spac_vspacing_temp
+ \fi
+\to \everyafterblankhandling
+
\def\setblankcategory#1%
{\settrue\someblankdone
\attribute\skipcategoryattribute#1\relax}
@@ -1547,9 +1624,9 @@
\def\addblankskip#1#2#3%
{\settrue\someblankdone
- \advance\blankskip#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax}
+ \advance\s_spac_vspacing_temp#1\dimexpr\ifgridsnapping#3\else#2\fi\relax\relax}
-\def\setblankpenalty #1%
+\def\setblankpenalty#1%
{\flushblankhandling
\settrue\someblankdone
\attribute\skipcategoryattribute \plusthree
@@ -1575,101 +1652,116 @@
\unexpanded\def\stopblankhandling
{\the\everyafterblankhandling
\ifconditional\someblankdone
- \vskip\blankskip
+ \vskip\s_spac_vspacing_temp
\fi
\endgroup}
\def\flushblankhandling
{\the\everyafterblankhandling
\ifconditional\someblankdone
- \vskip\blankskip
+ \vskip\s_spac_vspacing_temp
\fi
\setfalse\someblankdone
\the\everybeforeblankhandling}
-% % % % we can move much to lua once we can expand there % % % %
-
-\unexpanded\def\definevspacingamount
- {\dotripleempty\dodefinevspacingamount}
-
-\def\dodefinevspacingamount[#1][#2][#3]% can be combined
- {\setvalue{\??vs:#1}{\ifgridsnapping#3\else#2\fi}%
- \ctxlua{builders.vspacing.setskip("#1")}}
-
\def\addpredefinedblankskip#1#2%
{\settrue\someblankdone
- \advance\blankskip#1\dimexpr\csname\??vs:#2\endcsname\relax}
+ \advance\s_spac_vspacing_temp#1\dimexpr\csname\??vspacingamount#2\endcsname\relax}
\def\addaskedblankskip#1#2%
{\settrue\someblankdone
- \advance\blankskip#1\dimexpr#2\relax}
+ \advance\s_spac_vspacing_temp#1\dimexpr#2\relax}
-\unexpanded\def\definevspacing
- {\dodoubleempty\dodefinevspacing}
-
-\def\dodefinevspacing[#1][#2]%
- {\ctxlua{builders.vspacing.setmap("#1","#2")}}
+% The main spacer:
\unexpanded\def\vspacing
- {\dosingleempty\dovspacing}
+ {\doifnextoptionalelse\spac_vspacing_yes\spac_vspacing_nop}
-% todo: when packed blocks blank, we need to enable forced
+\def\spac_vspacing_yes
+ {\ifinpagebody % somewhat weird
+ \singleexpandafter\spac_vspacing_yes_indeed
+ \else\ifconditional\c_spac_packed_blank
+ \doubleexpandafter\spac_vspacing_yes_indeed
+ \else
+ \doubleexpandafter\spac_vspacing_yes_ignore
+ \fi\fi}
-\def\dovspacing % blank also has a \flushnotes
- {\ifinpagebody
- \expandafter\dovspacingyes
- \else\ifconditional\noblankinpacked % todo: better reset this conditional in pagebody
- \expandafter\expandafter\expandafter\dovspacingnop
+\def\spac_vspacing_nop
+ {\ifinpagebody % somewhat weird
+ \singleexpandafter\spac_vspacing_nop_indeed
+ \else\ifconditional\c_spac_packed_blank
+ \doubleexpandafter\spac_vspacing_nop_indeed
\else
- \expandafter\expandafter\expandafter\dovspacingyes
+ \doubleexpandafter\spac_vspacing_nop_ignore
\fi\fi}
-\def\dovspacingyes[#1]%
- %{\ifmmode\else\ctxlua{builders.vspacing.analyze("\iffirstargument#1\else\s!default\fi")}\fi}
- {\ifmmode\else\ctxlua{builders.vspacing.analyze("\iffirstargument#1\else\currentvspacing\fi")}\fi}
+\def\spac_vspacing_yes_indeed[#1]%
+ {\ifmmode\else\ctxcommand{vspacing("#1")}\fi}
-\def\dovspacingnop[#1]%
+\def\spac_vspacing_yes_ignore[#1]%
{\ifmmode\else\par\fi}
-% todo: check them and make them faster:
+\def\spac_vspacing_nop_indeed
+ {\ifmmode\else\ctxcommand{vspacing("\currentvspacing")}\fi}
-\definecomplexorsimple\setupvspacing
+\def\spac_vspacing_nop_ignore
+ {\ifmmode\else\par\fi}
-\let\currentvspacing\s!default
+% these depend on bigskipamount cum suis so we'd better sync them
-\def\complexsetupvspacing[#1]%
- {\edef\currentvspacing{#1}}
+\unexpanded\def\setupvspacing
+ {\doifnextoptionalelse\setupvspacing_yes\setupvspacing_nop}
-\def\simplesetupvspacing
- {\ifx\empty\currentvspacing\else
+\let\currentvspacing\s!default % hm, default, standard ...
+
+\def\setupvspacing_yes[#1]%
+ {\edef\currentvspacing{#1}%
+ \spac_whitespace_setup_nop % yes or no, was forgotten
+ }
+
+\def\setupvspacing_nop
+ {\ifx\empty\currentvspacing % mistakenly had an \else
\let\currentvspacing\s!default
\fi
- \simplesetupwhitespace}
+ \spac_whitespace_setup_nop}
-\def\restorestandardblank
+\unexpanded\def\restorestandardblank % or default ?
{\let\currentvspacing\v!standard}
+\let\synchronizevspacing\setupvspacing_nop
+
% used both
-\def\doinhibitblank{\vspacing[\v!disable]} % can be made faster (keep this command, used in styles)
-\def\inhibitblank {\vspacing[\v!disable]} % can be made faster
+\unexpanded\def\inhibitblank
+ {\vspacing[\v!disable]} % can be made faster
+
+\let\doinhibitblank\inhibitblank % keep this command, used in styles
\let\setupblank \setupvspacing
-\let\simplesetupblank\simplesetupvspacing
\let\blank \vspacing
+\let\synchronizeblank\synchronizevspacing
% category:4 is default
-\definevspacingamount[\v!none] [\zeropoint] [\zeropoint]
-\definevspacingamount[\v!big] [\bigskipamount] [\bodyfontlineheight]
-\definevspacingamount[\v!medium] [\medskipamount] [0.50\bodyfontlineheight]
-\definevspacingamount[\v!small] [\smallskipamount] [0.25\bodyfontlineheight]
-\definevspacingamount[\v!line] [\openlineheight] [\bodyfontlineheight]
-\definevspacingamount[\v!halfline][0.50\openlineheight][0.50\bodyfontlineheight]
-\definevspacingamount[\v!formula] [\medskipamount] [0.50\bodyfontlineheight]
-\definevspacingamount[\v!white] [\parskip] [\bodyfontwhitespace]
-\definevspacingamount[\v!height] [\strutheight] [\bodyfontstrutheight]
-\definevspacingamount[\v!depth] [\strutdepth] [\bodyfontstrutdepth]
+% this interface might change (into an \install, buw we will then keep this one hidden)
+
+\definevspacingamount[\v!none] [\zeropoint] [\zeropoint]
+\definevspacingamount[\v!big] [\bigskipamount] [\bodyfontlineheight]
+\definevspacingamount[\v!medium] [\medskipamount] [.5\bodyfontlineheight]
+\definevspacingamount[\v!small] [\smallskipamount] [.25\bodyfontlineheight]
+\definevspacingamount[\v!line] [\openlineheight] [\bodyfontlineheight]
+\definevspacingamount[\v!halfline] [.5\openlineheight] [.5\bodyfontlineheight]
+\definevspacingamount[\v!quarterline] [.25\openlineheight] [.25\bodyfontlineheight]
+\definevspacingamount[\v!formula] [\medskipamount] [.5\bodyfontlineheight]
+\definevspacingamount[\v!white] [\parskip] [\bodyfontwhitespace]
+\definevspacingamount[\v!height] [\strutheight] [\bodyfontstrutheight]
+\definevspacingamount[\v!depth] [\strutdepth] [\bodyfontstrutdepth]
+
+\definevspacingamount[-\v!line] [-\openlineheight] [-\bodyfontlineheight]
+\definevspacingamount[-\v!halfline] [-.5\openlineheight] [-.5\bodyfontlineheight]
+\definevspacingamount[-\v!quarterline][-.25\openlineheight][-.25\bodyfontlineheight]
+
+\definevspacingamount[\v!standard] [.75\openlineheight] [.75\openlineheight] % mkii compatible
\def\bodyfontwhitespace
{\dimexpr
@@ -1696,7 +1788,11 @@
\definevspacing[\s!default] [\v!white] % was big for a while
\dorecurse{10} % todo: other values < 4000
- {\expanded{\definevspacing[\v!samepage-\recurselevel][penalty:\the\numexpr4000+250*\recurselevel\relax]}}
+ {\normalexpanded{\definevspacing[\v!samepage-\recurselevel][penalty:\the\numexpr4000+250*\recurselevel\relax]}}
+
+%D Maybe at some point we will differ between \type {\vspacing} and
+%D \type {\blank} (we needed the first one while playing with the
+%D new code).
\let\blank \vspacing
\let\defineblank \definevspacing
@@ -1706,163 +1802,52 @@
%D care as it does {\em not} work in tandem with the other spacing
%D commands.
+\installcorenamespace{vspace}
+
\unexpanded\def\definevspace
- {\dotripleempty\dodefinevspace}
+ {\dotripleempty\spac_vspace_define}
-\def\dodefinevspace[#1][#2][#3]%
+\def\spac_vspace_define[#1][#2][#3]%
{\ifthirdargument
- \setvalue{\??va#1:#2}{#3}%
+ \setvalue{\??vspace#1:#2}{#3}%
\else
- \setvalue{\??va:#1}{#2}%
+ \setvalue{\??vspace:#1}{#2}%
\fi}
-\unexpanded\def\vspace
- {\dodoubleempty\dovspace}
+\letvalue{\??vspace:\s!unknown}\zeropoint
-\def\dovspace[#1][#2]%
- {\ifsecondargument
- \dodovspace[#1][#2]%
- \else\iffirstargument
- \vspace[][#1]%
- \else
- \vspace[][\s!default]%
- \fi\fi}
+\unexpanded\def\vspace
+ {\dodoubleempty\spac_vspace_inject}
-\def\dodovspace[#1][#2]%
+\def\spac_vspace_inject[#1][#2]%
{\par
\ifvmode
\removelastskip
- \vskip\vspaceamount{#1}{#2}\relax
+ \vskip
+ \csname\??vspace
+ \ifsecondargument
+ \ifcsname\??vspace#1:#2\endcsname
+ #1:#2%
+ \else\ifcsname\??vspace:#2\endcsname
+ :#2%
+ \else
+ :\s!unknown
+ \fi\fi
+ \else\iffirstargument
+ \ifcsname\??vspace:#1\endcsname
+ :#1%
+ \else
+ :\s!unknown
+ \fi
+ \else
+ \ifcsname\??vspace:\s!default\endcsname
+ :\s!default
+ \else
+ :\s!unknown
+ \fi
+ \fi\fi
+ \endcsname
+ \relax
\fi}
-\def\vspaceamount#1#2%
- {\executeifdefined{\??va#1:#2}{\executeifdefined{\??va:#2}\zeropoint}}
-
-%D When spacing is active we need to handle commands in
-%D a special way:
-%D
-%D \starttyping
-%D \setuplines[space=on]
-%D
-%D \startlines
-%D Let's talk about this{\ttsl\gobbleoneargument or}that.
-%D \stoplines
-%D
-%D \startlines
-%D Let's talk about this{\getvalue{ttsl}or}that.
-%D \stoplines
-%D \stoptyping
-%D
-%D One can indent in several ways:
-%D
-%D \starttyping
-%D \setupindenting[medium] \setuplines[indenting=odd] % no yes odd even
-%D
-%D \startlines
-%D first
-%D second
-%D third
-%D fourth
-%D \stoplines
-%D \stoptyping
-
-%D Contrary to \MKII\ we can now define classes of lines (generalized by
-%D Wolfgang). I will probably rewrite bits in \LUA.
-
-\let\currentlines\empty
-
-\def\linesparameter #1{\csname\dolinesparameter{\??rg\currentlines}#1\endcsname}
-\def\linesparameterhash#1{\dolinesparameterhash {\??rg\currentlines}#1}
-
-\def\dolinesparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dolinesparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\dolinesparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\dolinesparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\dolinesparentparameter #1#2{\ifx#1\relax\s!empty\else\dolinesparameter #1#2\fi}
-\def\dolinesparentparameterhash#1#2{\ifx#1\relax \else\dolinesparameterhash#1#2\fi}
-
-\def\dosetlinesattributes#1#2% style color
- {\edef\fontattributehash {\linesparameterhash#1}%
- \edef\colorattributehash{\linesparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-\getparameters
- [\??rg]
- [\c!option=,
- \c!command=,
- \c!before=\blank,
- \c!after=\blank,
- \c!inbetween=\blank,
- \c!indenting=\v!no,
- \c!space=\v!default]
-
-\unexpanded\def\definelines
- {\dodoubleempty\dodefinelines}
-
-\def\dodefinelines[#1][#2]%
- {\getparameters[\??rg#1][\s!parent=\??rg,#2]%
- \setvalue{\e!start#1}{\dostartlines[#1]}%
- \setvalue{\e!stop #1}{\dostoplines}}
-
-\unexpanded\def\setuplines
- {\dodoubleempty\dosetuplines}
-
-\def\dosetuplines[#1][#2]%
- {\doifelsenothing{#2}
- {\getparameters[\??rg][#1]}
- {\def\docommand##1{\getparameters[\??rg##1][#2]}%
- \processcommacommand[#1]\docommand}}
-
-\def\dostartlines[#1]%
- {\bgroup
- \edef\currentlines{#1}%
- \obeylines
- \dosingleempty\dodostartlines}
-
-\def\dodostartlines[#1]% new: optional second argument (WS)
- {\iffirstargument
- \getparameters[\??rg\currentlines][#1]%
- \fi
- \edef\linesoption{\linesparameter\c!option}%
- \linesparameter\c!before
- \pushmacro\checkindentation
- \whitespace
- \begingroup
- \dosetlinesattributes\c!style\c!color
- \setupindenting[\linesparameter\c!indenting]%
- \setupalign[\linesparameter\c!align]%
- \typesettinglinestrue
- \setupwhitespace[\v!none]%
- %\obeylines % move upwards to keep spaces in the first line due to optional argument
- \ignorespaces
- \gdef\afterfirstobeyedline % tzt two pass, net als opsomming
- {\linesparameter\c!command
- \gdef\afterfirstobeyedline
- {\ifx\linesoption\v!packed\nobreak\fi
- \linesparameter\c!command}}%
- \def\obeyedline
- {\par
- \futurelet\next\dobetweenthelines}%
- \activatespacehandler{\linesparameter\c!space}%
- \GotoPar}
-
-\def\dostoplines
- {\endgroup
- \popmacro\checkindentation
- \linesparameter\c!after
- \egroup}
-
-\def\dobetweenthelines
- {\doifmeaningelse\next\obeyedline
- {\linesparameter\c!inbetween}
- {\afterfirstobeyedline}}
-
-\definelines[\v!lines]
-
-\def\emptylines
- {\dosingleempty\doemptylines}
-
-\def\doemptylines[#1]%
- {\endgraf\dorecurse{\iffirstargument#1\else3\fi}\crlf}
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/spec-def.mkii b/Master/texmf-dist/tex/context/base/spec-def.mkii
index ad1a9bb1d17..60051579d04 100644
--- a/Master/texmf-dist/tex/context/base/spec-def.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-dpm.mkii b/Master/texmf-dist/tex/context/base/spec-dpm.mkii
index ddbb6caf811..fe721405aee 100644
--- a/Master/texmf-dist/tex/context/base/spec-dpm.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-dpm.mkii
@@ -5,7 +5,7 @@
%D subtitle=DVIPDFM support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-dvi.mkii b/Master/texmf-dist/tex/context/base/spec-dvi.mkii
index 52289085191..89a1330a2e5 100644
--- a/Master/texmf-dist/tex/context/base/spec-dvi.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-dvi.mkii
@@ -5,7 +5,7 @@
%D subtitle=Generic \TEX\ Solutions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-fdf.mkii b/Master/texmf-dist/tex/context/base/spec-fdf.mkii
index 30e15ff34eb..0713fa80cd1 100644
--- a/Master/texmf-dist/tex/context/base/spec-fdf.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-fdf.mkii
@@ -5,7 +5,7 @@
%D subtitle=Support Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -3169,7 +3169,8 @@
/BM /\ifcase#1 Normal\or Normal\or Multiply\or Screen\or
Overlay\or SoftLight\or HardLight\or ColorDodge\or
ColorBurn\or Darken\or Lighten\or Difference\or
- Exclusion\else Compatible\fi
+ Exclusion\or Hue\or Saturation\or Color\or
+ Luminosity\else Compatible\fi
#3>>}
\def\dodoPDFstarttransparency#1#2%
diff --git a/Master/texmf-dist/tex/context/base/spec-ini.mkii b/Master/texmf-dist/tex/context/base/spec-ini.mkii
index 0229a0e3ddf..9361ed2225a 100644
--- a/Master/texmf-dist/tex/context/base/spec-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-mis.mkii b/Master/texmf-dist/tex/context/base/spec-mis.mkii
index d56eca27e4a..de0debd3cdf 100644
--- a/Master/texmf-dist/tex/context/base/spec-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Miscellaneous Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-pdf.mkii b/Master/texmf-dist/tex/context/base/spec-pdf.mkii
index 222c4e3a6c6..33722f60345 100644
--- a/Master/texmf-dist/tex/context/base/spec-pdf.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-pdf.mkii
@@ -5,7 +5,7 @@
%D subtitle=Adobe \ACROBAT\ version 2.1,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-ps.mkii b/Master/texmf-dist/tex/context/base/spec-ps.mkii
index 803defe02ba..02ec16453cb 100644
--- a/Master/texmf-dist/tex/context/base/spec-ps.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-ps.mkii
@@ -5,7 +5,7 @@
%D subtitle=Adobe PostScript,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-tpd.mkii b/Master/texmf-dist/tex/context/base/spec-tpd.mkii
index 6af3b1272df..042d5cdfe36 100644
--- a/Master/texmf-dist/tex/context/base/spec-tpd.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-tpd.mkii
@@ -5,7 +5,7 @@
%D subtitle=\PDFTEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-tr.mkii b/Master/texmf-dist/tex/context/base/spec-tr.mkii
index c1f997bca19..19ddb7495a3 100644
--- a/Master/texmf-dist/tex/context/base/spec-tr.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-tr.mkii
@@ -5,7 +5,7 @@
%D subtitle=Thomas Rokicki's \DVIPS,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-tst.mkii b/Master/texmf-dist/tex/context/base/spec-tst.mkii
index 628a0dbbf77..4f580e7b403 100644
--- a/Master/texmf-dist/tex/context/base/spec-tst.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-tst.mkii
@@ -5,7 +5,7 @@
%D subtitle=Special Test Macro,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-var.mkii b/Master/texmf-dist/tex/context/base/spec-var.mkii
index 8d561dc6f99..3641ba9599e 100644
--- a/Master/texmf-dist/tex/context/base/spec-var.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-var.mkii
@@ -5,7 +5,7 @@
%D subtitle=Variables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-win.mkii b/Master/texmf-dist/tex/context/base/spec-win.mkii
index 55ceec691df..e16984a56e6 100644
--- a/Master/texmf-dist/tex/context/base/spec-win.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-win.mkii
@@ -5,7 +5,7 @@
%D subtitle=\YandY's \DVIWINDO,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/spec-yy.mkii b/Master/texmf-dist/tex/context/base/spec-yy.mkii
index beec95493e2..b5a1d590b08 100644
--- a/Master/texmf-dist/tex/context/base/spec-yy.mkii
+++ b/Master/texmf-dist/tex/context/base/spec-yy.mkii
@@ -5,7 +5,7 @@
%D subtitle=\YandY's \DVIPSONE\ and \DVIWINDO,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/status-files.pdf b/Master/texmf-dist/tex/context/base/status-files.pdf
index fb377d90e58..071753577c6 100644
--- a/Master/texmf-dist/tex/context/base/status-files.pdf
+++ b/Master/texmf-dist/tex/context/base/status-files.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/context/base/status-lua.pdf b/Master/texmf-dist/tex/context/base/status-lua.pdf
index ac8fc6ac377..fd66c594f93 100644
--- a/Master/texmf-dist/tex/context/base/status-lua.pdf
+++ b/Master/texmf-dist/tex/context/base/status-lua.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/context/base/status-mkiv.lua b/Master/texmf-dist/tex/context/base/status-mkiv.lua
new file mode 100644
index 00000000000..5c54b079f19
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/status-mkiv.lua
@@ -0,0 +1,1513 @@
+-- colo-run.mkiv colo-imp-*.mkiv ...
+
+return {
+ core = {
+ {
+ filename = "syst-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "norm-ctx",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "syst-pln",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "syst-mes",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "luat-cod",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "luat-bas",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe combine (3)",
+ },
+ {
+ filename = "luat-lib",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe combine (3)",
+ },
+ {
+ filename = "catc-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "catc-act",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "forward dependency",
+ },
+ {
+ filename = "catc-def",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "catc-ctx",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "catc-sym",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "cldf-ini",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe combine (1)",
+ },
+ {
+ filename = "syst-aux",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "will be better protected"
+ },
+ {
+ filename = "syst-lua",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe combine (1)",
+ },
+ {
+ filename = "syst-con",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe combine (1)",
+ },
+ {
+ filename = "syst-fnt",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe combine (1)",
+ },
+ {
+ filename = "syst-rtp",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe combine (1)",
+ },
+ {
+ filename = "file-ini",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "maybe combine (2)",
+ },
+ {
+ filename = "file-res",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "maybe combine (2)",
+ },
+ {
+ filename = "file-lib",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "supp-dir",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "char-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "char-utf",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "char-act",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "forward dependency",
+ },
+ {
+ filename = "mult-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "mult-sys",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "mult-def",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "mult-chk",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "mult-aux",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "mult-dim",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "cldf-int",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "luat-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "toks-ini",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe this becomes a runtime module",
+ },
+ {
+ filename = "attr-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "core-var",
+ marktype = "mkiv",
+ status = "unknown",
+ comment = "code might move from here",
+ },
+ {
+ filename = "core-env",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "might need more redoing",
+ },
+ {
+ filename = "layo-ini",
+ marktype = "mkiv",
+ status = "todo",
+ comment = "more might move to here",
+ },
+ {
+ filename = "node-ini",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe this becomes a runtime module",
+ },
+ {
+ filename = "cldf-bas",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "node-fin",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "might need more redoing",
+ },
+ {
+ filename = "node-mig",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "needs integration and configuration",
+ },
+ {
+ filename = "node-par",
+ marktype = "mkiv",
+ status = "experimental",
+ },
+ {
+ filename = "back-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "attr-col",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "attr-lay",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "attr-neg",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "attr-eff",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "trac-tex",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "needs more usage",
+ },
+ {
+ filename = "trac-deb",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "supp-box",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "supp-vis",
+ marktype = "mkiv",
+ status = "unknown",
+ comment = "will become a module (and part will stay in the core)",
+ },
+ {
+ filename = "supp-fun",
+ marktype = "mkiv",
+ status = "unknown",
+ comment = "will be integrated elsewhere",
+ },
+ {
+ filename = "supp-ran",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "supp-mat",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "will be moved to the math-* modules",
+ },
+ {
+ filename = "supp-ali",
+ marktype = "mkiv",
+ status = "unknown",
+ comment = "will be reimplemented",
+ },
+ {
+ filename = "supp-num",
+ marktype = "mkiv",
+ status = "obsolete",
+ comment = "replaced by units",
+ },
+ {
+ filename = "typo-ini",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-ins",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "file-syn",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "file-mod",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "core-con",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "cont-fil",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "regi-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "enco-ini",
+ marktype = "mkiv",
+ status = "messy",
+ },
+ {
+ filename = "hand-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lang-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lang-lab",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "namespace should be languages",
+ },
+ {
+ filename = "unic-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "core-uti",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "core-two",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe rename to core-two",
+ },
+ {
+ filename = "core-dat",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "colo-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "colo-ext",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "colo-grp",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "node-bck",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "trac-vis",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "lang-mis",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lang-url",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lang-def",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lang-wrd",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "file-job",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "might need more redoing",
+ },
+ {
+ filename = "symb-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "sort-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "pack-mis",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "pack-rul",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "namespace to be done",
+ },
+ {
+ filename = "pack-mrl",
+ marktype = "mkiv",
+ status = "todo",
+ comment = "this is something to be done on a rainy day"
+ },
+ {
+ filename = "pack-bck",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "pack-fen",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lxml-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lxml-sor",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-prc",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "strc-ini",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "strc-tag",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "strc-doc",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-num",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-mar",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-sbe",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-lst",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "strc-sec",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-pag",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-ren",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-xml",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-def",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-ref",
+ marktype = "mkvi",
+ status = "unknown",
+ },
+ {
+ filename = "strc-reg",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-lev",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "spac-ali",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe some tuning is needed / will happen",
+ },
+ {
+ filename = "spac-hor",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "probably needs some more work",
+ },
+ {
+ filename = "spac-ver",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe some changes will happen"
+ },
+ {
+ filename = "spac-lin",
+ marktype = "mkiv",
+ status = "unknown",
+ comment = "could be improved if needed"
+ },
+ {
+ filename = "spac-pag",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "this needs to be checked occasionally",
+ },
+ {
+ filename = "spac-par",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "spac-def",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "spac-grd",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "anch-pos",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "in transition",
+ },
+ {
+ filename = "anch-pgr",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "in transition",
+ },
+ {
+ filename = "scrn-ini",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "maybe change locationattribute names"
+ },
+ {
+ filename = "scrn-ref",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "namespace needs checking"
+ },
+ {
+ filename = "pack-obj",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-itm",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "strc-des",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-des",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-enu",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-ind",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-lab",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "core-sys",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "a funny mix",
+ },
+ {
+ filename = "page-var",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-otr",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "page-ini",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "code might end up elsewhere",
+ },
+ {
+ filename = "page-fac",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-brk",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "otr commands will be redone",
+ },
+ {
+ filename = "page-col",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-inf",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-grd",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-flt",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-bck",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "page-not",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-one",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "can probably be improved",
+ },
+ {
+ filename = "page-lay",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "page-box",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "page-txt",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "page-sid",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "strc-flt",
+ marktype = "mkvi",
+ status = "unknown",
+ },
+ {
+ filename = "page-mis",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-mbk",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "might be extended",
+ },
+ {
+ filename = "page-mul",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-set",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "pack-lyr",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "pack-pos",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-mak",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "page-lin",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-par",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "typo-pag",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-mar",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "buff-ini",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "check other modules for buffer usage",
+ },
+ {
+ filename = "buff-ver",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "check obsolete processbuffer"
+ },
+ {
+ filename = "buff-par",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "buff-imp-tex",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "buff-imp-mp",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "buff-imp-lua",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "buff-imp-xml",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "buff-imp-parsed-xml",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-blk",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-imp",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-sel",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-com",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "scrn-pag",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "namespace needs checking"
+ },
+ {
+ filename = "scrn-wid",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "namespace needs checking"
+ },
+ {
+ filename = "scrn-but",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "namespace needs checking"
+ },
+ {
+ filename = "scrn-bar",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "namespace needs checking"
+ },
+ {
+ filename = "strc-bkm",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "tabl-com",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "somewhat weird",
+ },
+ {
+ filename = "tabl-pln",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "tabl-tab",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "tabl-tbl",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "can probably be improved (names and such)",
+ },
+ {
+ filename = "tabl-ntb",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "tabl-nte",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "tabl-ltb",
+ marktype = "mkiv",
+ status = "unknown",
+ comment = "will be redone when needed",
+ },
+ {
+ filename = "tabl-tsp",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "tabl-xtb",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "namespace needs checking"
+ },
+ {
+ filename = "java-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "scrn-fld",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "namespace needs checking"
+ },
+ {
+ filename = "scrn-hlp",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "namespace needs checking"
+ },
+ {
+ filename = "char-enc",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "font-lib",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-fil",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-fea",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-mat",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-ini",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "needs occasional checking and upgrading",
+ },
+ {
+ filename = "font-sym",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-sty",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-set",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-emp",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-col",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-pre",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "font-unk",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "font-tra",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "likely this will become a module",
+ },
+ {
+ filename = "font-uni",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "this one might be merged",
+ },
+ {
+ filename = "font-col",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "font-gds",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lxml-css",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "this is work in progress",
+ },
+ {
+ filename = "spac-chr",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "blob-ini",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "typo-cln",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-spa",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-krn",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "do we keep the style and color or not"
+ },
+ {
+ filename = "typo-itc",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "typo-dir",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "typo-brk",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-cap",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-dig",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-rep",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-txt",
+ marktype = "mkvi",
+ status = "okay",
+ comment = "maybe there will be a nicer interface",
+ },
+ {
+ filename = "typo-par",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "might get extended",
+ },
+ {
+ filename = "type-ini",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ {
+ filename = "type-set",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "scrp-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "prop-ini",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "this module is obsolete",
+ },
+ {
+ filename = "mlib-ctx",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "meta-ini",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "metapost code is always evolving",
+ },
+ {
+ filename = "meta-tex",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "meta-fun",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe this one will be merged"
+ },
+ {
+ filename = "meta-pag",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "might get updated when mp code gets cleaned up",
+ },
+ {
+ filename = "page-mrk",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-flw",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-spr",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-plg",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-str",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "anch-pgr",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "anch-bck",
+ marktype = "mkvi",
+ status = "unknown",
+ },
+ {
+ filename = "anch-tab",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "anch-bar",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "anch-snc",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "math-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "math-pln",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "this file might merge into others",
+ },
+ {
+ filename = "math-for",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "math-def",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "eventually this will be split and spread",
+ },
+ {
+ filename = "math-ali",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "math-arr",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "math-frc",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "at least for the moment",
+ },
+ {
+ filename = "math-scr",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "math-int",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "math-del",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "code get replaced (by autodelimiters)",
+ },
+ {
+ filename = "math-inl",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "code might move to here",
+ },
+ {
+ filename = "math-dis",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "code might move to here",
+ },
+ {
+ filename = "phys-dim",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "strc-mat",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "chem-ini",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "chem-str",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "typo-scr",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "core-fnt",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "node-rul",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "maybe some cleanup is needed",
+ },
+ {
+ filename = "node-spl",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-not",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "strc-lnt",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "core-mis",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "pack-com",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "typo-del",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "grph-trf",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "namespace has to be made consistent"
+ },
+ {
+ filename = "grph-inc",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "grph-fig",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "grph-raw",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "pack-box",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "pack-bar",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "page-app",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "meta-fig",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "lang-spa",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "more or less obsolete"
+ },
+ {
+ filename = "bibl-bib",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "bibl-tra",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "meta-xml",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "not needed"
+ },
+ {
+ filename = "cont-log",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "task-ini",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "cldf-ver",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "cldf-com",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "core-ctx",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "core-ini",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "core-def",
+ marktype = "mkiv",
+ status = "unknown",
+ },
+ {
+ filename = "back-pdf",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "object related code might move or change",
+ },
+ {
+ filename = "mlib-pdf",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "mlib-pps",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "meta-pdf",
+ marktype = "mkiv",
+ status = "okay",
+ },
+ {
+ filename = "grph-epd",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "might need more work",
+ },
+ {
+ filename = "back-exp",
+ marktype = "mkiv",
+ status = "okay",
+ comment = "some parameters might move from export to backend"
+ },
+ },
+ extra = {
+ {
+ filename = "tabl-xnt",
+ marktype = "mkvi",
+ status = "okay",
+ },
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/status-mkiv.tex b/Master/texmf-dist/tex/context/base/status-mkiv.tex
new file mode 100644
index 00000000000..0d22d51a15d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/status-mkiv.tex
@@ -0,0 +1,161 @@
+ \setupbodyfont[dejavu,10pt]
+
+\setuplayout
+ [width=middle,
+ height=middle,
+ backspace=1cm,
+ topspace=1cm,
+ footer=0pt,
+ header=1.25cm]
+
+\setuphead
+ [subject]
+ [style=\bfa,
+ page=yes]
+
+\setuppagenumbering
+ [location=]
+
+\setupheadertexts
+ [\currentdate][MkIV cleanup Status / Page \pagenumber]
+
+\starttext
+
+% anch attr back buff colo font grph java lang luat lxml math meta mlib mult node
+% pack page phys scrn spac strc supp symb syst tabl toks typo
+
+\startsubject[title=Todo]
+
+\startitemize[packed]
+ \startitem currently the new namespace prefixes are not consistent but this
+ will be done when we're satisfied with one scheme \stopitem
+ \startitem there will be additional columns in the table, like for namespace
+ so we need another round of checking then \stopitem
+ \startitem the imp modules are not in the list and need checking too \stopitem
+ \startitem the s, x, m modules will be checked, redone and reorganized \stopitem
+ \startitem the lua code will be cleaned up upgraded as some is quite old
+ and experimental \stopitem
+ \startitem we need a proper dependency tree and better defined loading order \stopitem
+ \startitem all dotag.. will be moved to the tags_.. namespace \stopitem
+ \startitem we need to check what messages are gone (i.e.\ clean up mult-mes) \stopitem
+ \startitem some commands can go from mult-def (and the xml file) \stopitem
+ \startitem check for setuphandler vs simplesetuphandler \stopitem
+ \startitem all showcomposition etc can go (we can redo that in lua if needed) \stopitem
+ \startitem for the moment we will go for \type {xxxx_} namespaces that (mostly) match
+ the filename but later we can replace these by longer names (via a script) so
+ module writers should {\bf not} use the core commands with \type{_} in the
+ name \stopitem
+ \startitem the message system will be unified \stopitem
+\stopitemize
+
+\stopsubject
+
+\startsubject[title=Status]
+
+\startluacode
+
+ local coremodules = dofile("status-mkiv.lua")
+
+ if coremodules then
+
+ local function tabelize(loaded,what)
+
+ if loaded then
+
+ local nofunknown = 0
+ local nofloaded = #loaded
+
+ for i=1,nofloaded do
+ loaded[i].order = i
+ end
+
+ table.sort(loaded,function(a,b) return a.filename < b.filename end)
+
+ context.starttabulate { "|Tr|Tl|Tl|l|p|" }
+ context.NC() -- context.bold("order")
+ context.NC() context.bold("file")
+ context.NC() context.bold("mark")
+ context.NC() context.bold("status")
+ context.NC() context.bold("comment")
+ context.NC() context.NR()
+ for i=1,nofloaded do
+ local module = loaded[i]
+ local status = module.status
+ context.NC() context(module.order)
+ context.NC() context(module.filename)
+ context.NC() context(module.marktype)
+ if status == "unknown" then
+ context.NC() context.bold(status)
+ nofunknown = nofunknown + 1
+ else
+ context.NC() context(status)
+ end
+ context.NC() context(module.comment)
+ context.NC() context.NR()
+ end
+ context.stoptabulate()
+
+ context.blank()
+
+ context("Of the %s %s modules (so far) in this list %s have the status unknown",nofloaded,what,nofunknown)
+
+ end
+
+ end
+
+ tabelize(coremodules.core, "core")
+ tabelize(coremodules.extra,"extra")
+
+ end
+
+ local namespaces = dofile("status-namespaces.lua")
+
+ local valid = table.tohash {
+ "toks", "attr", "page", "buff", "font", "colo", "phys", "supp", "typo", "strc",
+ "syst", "tabl", "spac", "scrn", "lang", "lxml", "mlib", "java", "pack", "math",
+ "symb", "grph", "anch", "luat", "mult", "back", "node", "meta",
+ "module",
+ }
+
+ context.startsubject { title = "Valid prefixes" }
+
+ for namespace, data in table.sortedhash(namespaces) do
+ if valid[namespace] then
+ context.type(namespace)
+ end
+ context.par()
+ end
+
+ context.stopsubject()
+
+ context.startsubject { title = "Messy namespaces" }
+
+ for namespace, data in table.sortedhash(namespaces) do
+ if valid[namespace] then
+ else
+ context(namespace)
+ end
+ context.par()
+ end
+
+ context.stopsubject()
+
+ local registers = dofile("status-registers.lua")
+
+ context.startsubject { title = "Messy registers" }
+ for register, data in table.sortedhash(registers) do
+ context(register)
+ context.par()
+ for name in table.sortedhash(data) do
+ context.quad()
+ context.type(name)
+ context.par()
+ end
+ context.par()
+ end
+
+\stopluacode
+
+\stopsubject
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/strc-bkm.lua b/Master/texmf-dist/tex/context/base/strc-bkm.lua
index 6a2cc382775..4eb9551a9f9 100644
--- a/Master/texmf-dist/tex/context/base/strc-bkm.lua
+++ b/Master/texmf-dist/tex/context/base/strc-bkm.lua
@@ -188,3 +188,9 @@ function bookmarks.finalize(levels)
-- that we will support when the main loop has become a coroutine.
codeinjections.addbookmarks(levels,bookmarks.method)
end
+
+-- interface
+
+commands.overloadbookmark = bookmarks.overload
+commands.registerbookmark = bookmarks.register
+commands.setupbookmarks = bookmarks.setup
diff --git a/Master/texmf-dist/tex/context/base/strc-bkm.mkiv b/Master/texmf-dist/tex/context/base/strc-bkm.mkiv
index b7a5bc805eb..8ddf0a6dff9 100644
--- a/Master/texmf-dist/tex/context/base/strc-bkm.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-bkm.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Bookmarks,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -50,7 +50,7 @@
\def\dobookmark[#1]#2%
{\begingroup
\simplifycommands
- \ctxlua{structures.bookmarks.overload("#1",\!!bs\detokenize\expandafter{\normalexpanded{#2}}\!!es)}%
+ \ctxcommand{overloadbookmark("#1",\!!bs\detokenize\expandafter{\normalexpanded{#2}}\!!es)}%
\endgroup}
%D Placement \unknown\ look how simple compared to \MKII:
@@ -86,7 +86,7 @@
\else\ifsecondargument
\doifassignmentelse{#2}{\let\askedopened\empty\getparameters[\??bm][#2]}\donothing
\fi\fi
- \ctxlua{structures.bookmarks.register {
+ \ctxcommand{registerbookmark {
names = "\askednames",
opened = "\askedopened",
force = "\bookmarkparameter\c!force",
@@ -100,7 +100,7 @@
\c!number=\v!yes] % might become v!no
\appendtoks
- \ctxlua{structures.bookmarks.setup {
+ \ctxcommand{setupbookmarks {
separatorset = "\bookmarkparameter\c!numberseparatorset",
conversionset = "\bookmarkparameter\c!numberconversionset",
starter = \!!bs\bookmarkparameter\c!numberstarter\!!es,
@@ -109,9 +109,6 @@
}}%
\to \everysetupbookmarks
-% \prependtoks\ctxlua{structures.bookmarks.place()}\to\everystoptext % too late
-% \prependtoks\ctxlua{structures.bookmarks.place()}\to\everylastbackendshipout % okay but not nice
-
\protect \endinput
% \starttext
diff --git a/Master/texmf-dist/tex/context/base/strc-blk.lua b/Master/texmf-dist/tex/context/base/strc-blk.lua
index cbdc8c6ea36..d2f25dfb34f 100644
--- a/Master/texmf-dist/tex/context/base/strc-blk.lua
+++ b/Master/texmf-dist/tex/context/base/strc-blk.lua
@@ -37,7 +37,6 @@ end
job.register('structures.blocks.collected', tobesaved, initializer)
-local printer = (lpeg.patterns.textline/tex.print)^0 -- can be shared
local listitem = utilities.parsers.listitem
function blocks.print(name,data,hide)
@@ -144,3 +143,11 @@ function blocks.save(name,tag,buffer) -- wrong, not yet adapted
end
buffers.erase(buffer)
end
+
+-- interface
+
+
+commands.definestructureblock = blocks.define
+commands.savestructureblock = blocks.save
+commands.selectstructureblock = blocks.select
+commands.setstructureblockstate = blocks.setstate
diff --git a/Master/texmf-dist/tex/context/base/strc-blk.mkii b/Master/texmf-dist/tex/context/base/strc-blk.mkii
index c4e38a607b5..b6056769c87 100644
--- a/Master/texmf-dist/tex/context/base/strc-blk.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-blk.mkii
@@ -5,7 +5,7 @@
%D subtitle=Blockmoves,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-blk.mkiv b/Master/texmf-dist/tex/context/base/strc-blk.mkiv
index f625fa44849..3bd5d04ed20 100644
--- a/Master/texmf-dist/tex/context/base/strc-blk.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-blk.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Blockmoves,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -41,14 +41,14 @@
\c!inner=,
\c!style=,
\c!file=]% todo
- \ctxlua{structures.blocks.define("#1")}%
+ \ctxcommand{definestructureblock("#1")}%
\setuvalue{\e!begin#1}{\dodoubleempty\dobeginofblock[#1]}%
\letvalue{\e!end#1}\relax}
-\long\def\dobeginofblock[#1][#2]%
- {\normalexpanded{\noexpand\dodowithbuffer{@block@}{\e!begin#1}{\e!end#1}}
+\def\dobeginofblock[#1][#2]%
+ {\normalexpanded{\buff_pickup{@block@}{\e!begin#1}{\e!end#1}}
{}% before
- {\ctxlua{structures.blocks.save("#1","#2","@block@")}}}% after
+ {\ctxcommand{savestructureblock("#1","#2","@block@")}}}% after
\def\dostarthiddenblock
{\startnointerference
@@ -71,8 +71,8 @@
\doblocksetups\currentblock
\let\doblocksetups\gobbleoneargument
\namedblockparameter\currentblock\c!before
- \dosetfontattribute{\??tb\currentblock}\c!style
- \dosetcolorattribute{\??tb\currentblock}\c!color
+ \dousestylehashparameter{\??tb\currentblock}\c!style
+ \dousecolorhashparameter{\??tb\currentblock}\c!color
\namedblockparameter\currentblock\c!inner
\ignorespaces}
@@ -83,17 +83,17 @@
\egroup}
\def\dosetblockstate[#1][#2][#3]% state name tag
- {\ctxlua{structures.blocks.setstate("#1","#2","#3")}}
+ {\ctxcommand{setstructureblockstate("#1","#2","#3")}}
\def\doselectblocks[#1][#2][#3][#4]% state name tag setups
{\bgroup
\doifassignmentelse{#3}
{\getparameters[\??tb\??tb][\c!criterium=\v!text,#3]%
\def\doblocksetups##1{\getparameters[\??tb##1][#3]}%
- \ctxlua{structures.blocks.select("#1","#2","","\@@tb@@tbcriterium")}}
+ \ctxcommand{selectstructureblock("#1","#2","","\@@tb@@tbcriterium")}}
{\getparameters[\??tb\??tb][\c!criterium=\v!text,#4]%
\def\doblocksetups##1{\getparameters[\??tb##1][#4]}%
- \ctxlua{structures.blocks.select("#1","#2","#3","\@@tb@@tbcriterium")}}%
+ \ctxcommand{selectstructureblock("#1","#2","#3","\@@tb@@tbcriterium")}}%
\egroup}
% hide: save, if [+] also hidden execute
diff --git a/Master/texmf-dist/tex/context/base/strc-des.lua b/Master/texmf-dist/tex/context/base/strc-con.lua
index ee5fe702b7f..29a1c0cb36d 100644
--- a/Master/texmf-dist/tex/context/base/strc-des.lua
+++ b/Master/texmf-dist/tex/context/base/strc-con.lua
@@ -1,6 +1,6 @@
-if not modules then modules = { } end modules ['strc-des'] = {
+if not modules then modules = { } end modules ['strc-con'] = {
version = 1.001,
- comment = "companion to strc-des.mkiv",
+ comment = "companion to strc-con.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
diff --git a/Master/texmf-dist/tex/context/base/strc-con.mkvi b/Master/texmf-dist/tex/context/base/strc-con.mkvi
new file mode 100644
index 00000000000..3068fda0ba7
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-con.mkvi
@@ -0,0 +1,892 @@
+%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}{1.001}
+
+% 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
+%D we can conveniently build upon them. They are not really meant for
+%D users but module writers might find them useful. We mention a
+%D couple of parameters but these are only mentioned because in the
+%D shared code we map all resolvers to constructions.
+
+\unprotect
+
+\ifdefined\v!construction \else \def\v!construction{construction} \fi
+
+%D Todo:
+
+\installcorenamespace{construction}
+
+\installcommandhandler \??construction {construction} \??construction
+
+\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=7em,
+ \c!distance=1em,
+ \c!titledistance=0.5em,
+ %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
+
+\appendtoks
+ \ifx\currentconstructionparent\empty
+ \letvalue{\??constructionmain\currentconstruction}\currentconstruction
+ \definelist[\currentconstruction]% goodie
+ \else
+ \letvalue{\??constructionmain\currentconstruction}\currentconstructionparent
+ \definelist[\currentconstruction][\currentconstructionparent]% goodie
+ \fi
+ \setevalue{\??constructionlevel\currentconstruction}{\number\constructionparameter\c!level}%
+ \setevalue{\??constructionclass\currentconstruction}{\constructionparameter\s!handler}%
+\to \everydefineconstruction
+
+\appendtoks
+ \setuevalue{\e!start\currentconstruction}{\strc_constructions_start{\currentconstruction}}%
+ \setuevalue{\e!stop \currentconstruction}{\strc_constructions_stop}%
+\to \everydefineconstruction
+
+%D Just a basic environment (mostly for testing). We will provide a 'setup' based
+%D plugin once the rest is sorted out.
+
+\unexpanded\def\strc_constructions_start#1%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \dodoubleempty\strc_constructions_start_regular}
+
+\unexpanded\def\strc_constructions_start_regular[#1][#2]%
+ {\strc_constructions_register[\c!label={\constructionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1][#2]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_constructions_stop
+ {\csname\??constructionstophandler\currentconstructionhandler\endcsname
+ \endgroup}
+
+%D As we will build on top of the generic construction mechanism we
+%D have handlers as a sort of plug in mechanism. In order to have
+%D some consistency we share some namespaces.
+
+\installcorenamespace{constructioninitializer}
+\installcorenamespace{constructionfinalizer}
+
+\installcorenamespace{constructionmainhandler}
+\installcorenamespace{constructioncommandhandler}
+\installcorenamespace{constructionstarthandler}
+\installcorenamespace{constructionstophandler}
+
+\installcorenamespace{constructiontexthandler}
+\installcorenamespace{constructionnotehandler}
+
+\unexpanded\def\strc_constructions_initialize#1% class instance
+ {\edef\currentconstruction{#1}%
+\let\currentconstructionlistentry\!!zerocount
+ \expandafter\let\expandafter\currentconstructionmain \csname\??constructionmain \currentconstruction\endcsname
+ \expandafter\let\expandafter\currentconstructionlevel \csname\??constructionlevel\currentconstruction\endcsname
+ \expandafter\let\expandafter\currentconstructionhandler\csname\??constructionclass\currentconstruction\endcsname
+ \csname\??constructioninitializer\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_constructions_finalize
+ {\csname\??constructionfinalizer\currentconstructionhandler\endcsname
+ \strc_constructions_discard}
+
+\newconditional\c_strc_constructions_number_state
+\newconditional\c_strc_constructions_title_state
+
+\setvalue{\??constructioninitializer\v!construction}%
+ {\setfalse\c_strc_constructions_number_state
+ \setfalse\c_strc_constructions_title_state}
+
+\setvalue{\??constructionfinalizer\v!construction}%
+ {}
+
+% 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.
+
+\ifdefined\dotagsetconstruction \else \let\dotagsetconstruction\relax \fi
+
+\newtoks\everyconstruction
+
+\unexpanded\def\currentconstructiontext
+ {\begstrut
+ \csname\??constructiontexthandler\currentconstructionhandler\endcsname
+ \endstrut}
+
+\unexpanded\def\currentconstructionsample
+ {\begstrut
+ \constructionparameter\c!text
+ \constructionparameter\c!sample
+ \endstrut}
+
+\setvalue{\??constructionmainhandler\v!construction}#1%
+ {\iftrialtypesetting \else
+ \begingroup
+ \currentconstructionsynchronize % reinstated
+ \attribute\destinationattribute\currentconstructionattribute\relax % todo, whole text
+ \signalcharacter
+ \endgroup
+ \fi#1}
+
+\setvalue{\??constructiontexthandler\v!construction}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext
+ \the\everyconstruction
+ \constructionparameter\c!headcommand
+ {\strut
+ \constructionparameter\c!text
+ \ctxcommand{savedlisttitle("\currentconstructionmain",\currentconstructionlistentry)}}%
+ \endgroup}
+
+\unexpanded\def\strc_constructions_stored_start
+ {\begingroup % brrr \endgroup elsewhere ... will be sorted out
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\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}
+
+\setvalue{\??constructioncommandhandler\v!construction}%
+ {\endgroup}
+
+\setvalue{\??constructionstarthandler\v!construction}% this will be redone (reorganized) .. too much boxing
+ {\dostarttagged\t!construction\currentconstruction
+ \dotagsetconstruction
+ \constructionparameter\c!before
+ \begingroup
+ \edef\currentconstructionalternative{\constructionparameter\c!alternative}%
+ \doadaptleftskip{\constructionparameter\c!margin}%
+ \setlocalhsize % so we can use \localhsize in width assignments
+ \constructionsheaddistance\constructionalternativeparameter\c!distance\relax
+ \ifdim\constructionsheaddistance=\zeropoint
+ \doif{\constructionalternativeparameter\c!width}\v!broad{\constructionsheaddistance\emwidth}%
+ \fi
+ % inefficient and not always needed, for instance not with margins so we will make checkers
+ % per alternative
+ \setbox\constructionheadbox\hbox
+ {\forgetall
+ \dontcomplain
+ \settrialtypesetting
+ \doifelsenothing{\constructionparameter\c!sample}
+ {\csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext}%
+ {\csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructionsample}}%
+ \assignwidth
+ {\constructionalternativeparameter\c!width}
+ \constructionsheadwidth
+ {\unhcopy\constructionheadbox}
+ \constructionsheaddistance
+ \dostarttagged\t!constructiontag\empty % todo
+ \setbox\constructionheadbox\hbox
+ {\forgetall
+ \dontcomplain
+ \doifelse{\constructionparameter\c!alternative}\v!serried % brrr, hack, will change
+ {\csname\??constructionmainhandler\currentconstructionhandler\endcsname\currentconstructiontext}
+ {\csname\??constructionmainhandler\currentconstructionhandler\endcsname{\boxedconstructionhead\currentconstructiontext}}}%
+ \doifelse{\constructionparameter\c!aligntitle}\v!no
+ {\leftconstructionskip \leftskip
+ \rightconstructionskip\rightskip}
+ {\ifcase\c_strc_constructions_nested_state
+ \leftconstructionskip \leftskip
+ \rightconstructionskip\rightskip
+ \fi}%
+ \doifsomething{\constructionparameter\c!align}{\setupalign[\constructionparameter\c!align]}% \use...
+ \indenting[\constructionparameter\c!indenting]% \use...
+ \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
+ %
+ \doifnotsetups {\constructionalternativeparameter\c!renderingsetup}
+ {\let\currentconstructionalternative\v!left}%
+ \directsetup{\constructionalternativeparameter\c!renderingsetup}\relax
+ %
+ \dostoptagged % tag
+ \dostarttagged\t!constructioncontent\empty
+ \ignorespaces} % args not needed
+
+\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}
+
+\def\boxedconstructionhead#1%
+ {\vtop
+ {\hsize\constructionsheadwidth
+ \doifsomething{\constructionparameter\c!headalign}{\setupalign[\constructionparameter\c!headalign]}%
+ #1}}
+
+\installcorenamespace{constructionalternative}
+\installcorenamespace{constructionrenderings}
+
+% see lists: alternativemethods ... todo
+
+\installcommandhandler \??constructionalternative {constructionalternative} \??constructionalternative
+
+\setupconstructionalternative
+ [\c!width=\constructionparameter\c!width,
+ \c!distance=\constructionparameter\c!distance]
+
+\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=\v!fit,
+ \c!renderingsetup=\??constructionrenderings:\v!hanging]
+
+\defineconstructionalternative
+ [\v!top]
+ [\c!renderingsetup=\??constructionrenderings:\v!top,
+ \c!width=\localhsize]
+
+\defineconstructionalternative
+ [\v!command]
+ [\c!renderingsetup=\??constructionrenderings:\v!command]
+
+\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
+ \edef\p_headalign{\constructionparameter\c!headalign}%
+ \ifx\p_headalign\empty
+ \setupalign[#1]% use fast one
+ \else
+ \setupalign[\p_headalign]% use fast one
+ \fi
+ \advance\ifx#1\v!flushleft\rightskip\else\leftskip\fi\constructionsheaddistance % only difference and wrong anyway
+ \ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}%
+ \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
+ \edef\p_headalign{\constructionparameter\c!headalign}%
+ \ifx\p_headalign\empty
+ \setupalign[#1]% use fast one
+ \else
+ \setupalign[\p_headalign]% use fast one
+ \fi
+ \ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}%
+ \ht\constructionheadbox\strutht
+ \dp\constructionheadbox\strutdp}
+
+\def\strc_constructions_set_hang#1%
+ {\edef\p_hang{\constructionparameter\c!hang}%
+ \ifx\p_hang\empty
+ \else\ifx\p_hang\v!fit
+ \scratchdimen\htdp\constructionheadbox
+ \getnoflines\scratchdimen
+ \hangafter-\noflines
+ \else\ifx\p_hang\v!broad
+ \scratchdimen\dimexpr\htdp\constructionheadbox+.5\strutht\relax
+ \getnoflines\scratchdimen
+ \hangafter-\noflines
+ \else
+ \hangafter-\p_hang
+ \fi\fi\fi
+ \relax
+ \hangindent\ifx#1\v!right-\fi\constructionsheadwidth}
+
+% The setups. These only deal with placement of the descriptor and initializing the
+% environment. The wrapping happens elsewhere.
+
+\startsetups[\??constructionrenderings:\v!left]
+ \edef\p_hang{\constructionparameter\c!hang}
+ \doifsetupselse{\??constructionrenderings:\v!left:\p_hang} {
+ \directsetup{\??constructionrenderings:\v!left:\p_hang}
+ } {
+ \directsetup{\??constructionrenderings:\v!left:\v!hanging}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right]
+ \edef\p_hang{\constructionparameter\c!hang}
+ \doifsetupselse{\??constructionrenderings:\v!right:\p_hang} {
+ \directsetup{\??constructionrenderings:\v!right:\p_hang}
+ } {
+ \directsetup{\??constructionrenderings:\v!right:\v!hanging}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:\v!none]
+ \let\\=\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushleft
+ \leftskip\dimexpr\leftconstructionskip+\constructionsheadwidth\relax
+ \rightskip\rightconstructionskip
+ \advance\leftskip\constructionsheaddistance
+ \llap {
+ \hbox to \leftskip {
+ \hskip\leftconstructionskip
+ \copy\constructionheadbox\hss
+ }
+ }
+ \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]
+ \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
+ }
+ \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]%
+ \let\\=\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushleft
+ \llap {
+ \hbox to \constructionsheadwidth {
+ \copy\constructionheadbox
+ \hss
+ }
+ \hskip\constructionsheaddistance
+ }
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:\v!margin]%
+ \let\\=\crlf
+ \noindent
+ \strc_constructions_set_pure_box\v!flushright
+ \rlap {
+ \hskip\constructionsheaddistance
+ \hbox to \constructionsheadwidth {
+ \copy\constructionheadbox\hss
+ }
+ }
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!left:\v!hanging]%
+ \let\\=\crlf
+ \dontcomplain
+ \advance\constructionsheadwidth \constructionsheaddistance
+ \strc_constructions_set_hang_box\v!flushleft
+ \strc_constructions_set_hang\v!left
+ \noindent
+ \llap {
+ \vtop to \zeropoint {
+ \box\constructionheadbox
+ }
+ }
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!right:\v!hanging]%
+ \let\\=\crlf
+ \dontcomplain
+ \advance\constructionsheadwidth \constructionsheaddistance
+ \strc_constructions_set_hang_box\v!flushright
+ \strc_constructions_set_hang\v!right
+ \noindent
+ \rlap {
+ \hbox to \dimexpr\hsize-\leftskip-\rightskip\relax {
+ \hss
+ \vtop to \zeropoint {
+ \box\constructionheadbox
+ }
+ }
+ }
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!top]
+ \dohandlepagebreakX\plusone
+ \let\\=\space
+ \noindent
+ \copy\constructionheadbox\par % copy ?
+ \nobreak
+ \doifelsenothing{\constructionparameter\c!inbetween}{\blank}{\constructionparameter\c!inbetween}%
+ \nobreak
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+% why copy? historic reason?
+
+\startsetups[\??constructionrenderings:\v!margin]
+ \let\\=\crlf
+ \noindent
+ \inmargin[\c!scope=\v!local]{\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!leftmargin]
+ \let\\=\crlf
+ \noindent
+ \inleft[\c!scope=\v!local]{\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!rightmargin]
+ \let\\=\crlf
+ \noindent
+ \inright[\c!scope=\v!local]{\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!innermargin]
+ \let\\=\crlf
+ \noindent
+ \ininner[\c!scope=\v!local]{\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}%
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!outermargin]
+ \let\\=\crlf
+ \noindent
+ \inouter[\c!scope=\v!local]{\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}%
+ \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]
+ \edef\p_width{\constructionparameter\c!width}% CHECK ! ! ! wrong parameter namespace
+ \doifsetupselse{\??constructionrenderings:\v!serried:\p_width} {
+ \directsetup{\??constructionrenderings:\v!serried:\p_width}
+ } {
+ \directsetup{\??constructionrenderings:\v!serried:\v!wide}
+ }
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!fit]
+ \let\\=\crlf
+ \noindent
+ \ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox
+ \hskip\constructionsheaddistance\relax
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!broad]
+ \let\\=\crlf
+ \noindent
+ \ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox
+ \hskip\constructionsheaddistance \!!plus .5\constructionsheaddistance \!!minus .25\constructionsheaddistance\relax
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:]
+ \directsetup{\??constructionrenderings:\v!serried:\v!broad}
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!serried:\v!wide]
+ \let\\=\crlf
+ \noindent
+ \hbox to \constructionsheadwidth {
+ \ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox
+ \hss
+ }
+ \hskip\constructionsheaddistance\relax
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+\startsetups[\??constructionrenderings:\v!hanging]
+ % tricky: leftskipadaption is somewhat unpredictable
+ \let\\=\crlf
+ \noindent
+ \advance\leftskip-\leftskipadaption\relax
+ \ifdim\leftskipadaption=\zeropoint
+ \leftskipadaption1.5em\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\unhcopy\else\copy\fi\constructionheadbox
+ \kern\ifdim\constructionsheaddistance=\zeropoint .75em\else\constructionsheaddistance\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{\ifhbox\constructionheadbox\unhcopy\else\copy\fi\constructionheadbox}
+ \useconstructionstyleandcolor\c!style\c!color
+ \ignorespaces
+\stopsetups
+
+% 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}
+
+\unexpanded\def\strc_constructions_close_symbol_place
+ {\ifconditional\csname\??constructionclosesymbol\currentconstruction\endcsname
+ \global\expandafter\setfalse\csname\??constructionclosesymbol\currentconstruction\endcsname
+ \edef\p_closesymbol{\constructionparameter\c!closesymbol}%
+ \ifx\p_closesymbol\empty \else
+ \constructionparameter\c!closecommand{\p_closesymbol}% hm why {} maybe because box expected
+ \fi
+ \fi}
+
+\newif\ifnoconstructioncaption
+
+%D The storage macros:
+
+\let\currentconstructionlistentry\!!zerocount
+
+\def\strc_constructions_register
+ {\ctxcommand{doiflisthasentry(\currentconstructionlistentry)}%
+ \strc_constructions_register_nop
+ \strc_constructions_register_yes}
+
+% \def\strc_constructions_register{\strc_constructions_register_yes}
+
+\def\strc_constructions_register_nop[#1][#2]% #1=interfaced-settings, #2=optional user data
+ %{\writestatus{constructions}{reusing \currentconstruction: \number\currentconstructionlistentry}}
+ {}
+
+\def\strc_constructions_discard
+ {\iftrialtypesetting
+ % \writestatus{constructions}{discarding \currentconstruction: \number\currentconstructionlistentry}%
+ \ctxcommand{discardfromlist(\currentconstructionlistentry)}%
+ \fi}
+
+\let\currentconstructionlistnumber \!!zerocount
+\let\currentconstructionsynchronize\relax
+\let\currentconstructionattribute \attributeunsetvalue
+
+\def\strc_constructions_register_yes[#1][#2]% #1=interfaced-settings, #2=optional user data
+ {\begingroup % similar to structure so we might generalize this
+ \setupcurrentconstruction[#1]% % 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
+ \global\let\currentconstructionexpansion\v!no
+ \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
+ \global\let\currentconstructionlist\currentconstructiontitle
+ \fi
+ \global\let\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
+ \globallet\currentconstructionlist\currentconstructiontitle
+ \fi
+ \globallet\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\ctxcommand{addtolist{ % we can set a counter at the lua end
+ metadata = {
+ kind = "construction",
+ name = "\currentconstructionmain",
+ level = structures.sections.currentlevel(),
+ catcodes = \the\catcodetable,
+ % \currentdirectionparameters
+ },
+ references = {
+ internal = \nextinternalreference,
+ order = \nextinternalorderreference,
+ reference = "\currentconstructionreference",
+ referenceprefix = "\referenceprefix",
+ block = "\currentsectionblock",
+ section = structures.sections.currentid(),
+ },
+ titledata = {
+ label = \!!bs\detokenize\expandafter{\currentconstructionlabel }\!!es,
+ title = \!!bs\detokenize\expandafter{\currentconstructiontitle }\!!es,
+ \ifx\currentconstructionbookmark\currentconstructiontitle \else
+ bookmark = \!!bs\detokenize\expandafter{\currentconstructionbookmark}\!!es,
+ \fi
+ \ifx\currentconstructionlist\currentconstructiontitle \else
+ list = \!!bs\detokenize\expandafter{\currentconstructionlist }\!!es,
+ \fi
+ },
+ \ifconditional\c_strc_constructions_number_state
+ prefixdata = {
+ prefix = "\constructionparameter\c!prefix",
+ separatorset = "\constructionparameter\c!prefixseparatorset",
+ conversion = \!!bs\constructionparameter\c!prefixconversion\!!es,
+ conversionset = "\constructionparameter\c!prefixconversionset",
+ set = "\constructionparameter\c!prefixset",
+ segments = "\constructionparameter\c!prefixsegments",
+ connector = \!!bs\constructionparameter\c!prefixconnector\!!es,
+ },
+ numberdata = {
+ numbers = structures.counters.compact("\currentconstructionnumber",nil,true), % ! number can be cloned
+ separatorset = "\constructionparameter\c!numberseparatorset",
+ conversion = "\constructionparameter\c!numberconversion",
+ conversionset = "\constructionparameter\c!numberconversionset",
+ starter = \!!bs\constructionparameter\c!numberstarter\!!es,
+ stopper = \!!bs\constructionparameter\c!numberstopper\!!es,
+ segments = "\constructionparameter\c!numbersegments",
+ },
+ \or
+ % symbol
+ \fi
+ userdata = \!!bs\detokenize{#2}\!!es % will be converted to table at the lua end
+ }
+ }\relax
+ % \writestatus{constructions}{registering \currentconstruction: \number\scratchcounter}%
+ \normalexpanded{%
+ \endgroup
+ \edef\noexpand\currentconstructionlistentry {\the\scratchcounter}%
+ \edef\noexpand\currentconstructionattribute {\ctxcommand {setinternalreference("\referenceprefix","\currentconstructionreference",\nextinternalreference,"\interactionparameter\c!focus")}}%
+ \edef\noexpand\currentconstructionsynchronize{\ctxlatecommand{enhancelist(\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.
+
+\def\reinstateconstructionnumberentry#1% was xdef
+ {\edef\currentconstructionattribute {\ctxcommand {getinternalreference(#1)}}%
+ \edef\currentconstructionsynchronize{\ctxlatecommand{enhancelist(#1)}}}
+
+\installstructurelistprocessor{construction}{\usestructurelistprocessor{number+title}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-def.mkiv b/Master/texmf-dist/tex/context/base/strc-def.mkiv
index e386902e02c..7917b7d83c0 100644
--- a/Master/texmf-dist/tex/context/base/strc-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-def.mkiv
@@ -4,7 +4,7 @@
%D subtitle=Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -16,39 +16,7 @@
\unprotect
-% \def\installparameterhandler#1#2#3#4#5#6#7#8#9{%
-% \def#3##1{\csname#5{#1#2}##1\endcsname}%
-% \def#4##1{#6{#1#2}##1}%
-% %
-% \def#5##1##2{\ifcsname##1##2\endcsname##1##2\else\expandafter#7\csname##1\s!parent\endcsname##2\fi}%
-% \def#6##1##2{\ifcsname##1##2\endcsname ##1\else\expandafter#8\csname##1\s!parent\endcsname##2\fi}%
-% %
-% \def#7##1##2{\ifx##1\relax\s!empty\else#5##1##2\fi}%
-% \def#8##1##2{\ifx##1\relax \else#6##1##2\fi}%
-% %
-% \def#9##1##2% style color
-% {\edef\fontattributehash {#4##1}%
-% \edef\colorattributehash{#4##2}%
-% \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash ##1\fi
-% \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash##2\fi}%
-% %
-% }
-
-% \installparameterhandler
-% \empty
-% \@@framed
-% \framedparameter
-% \framedparameterhash
-% \doframedparameter
-% \doframedparameterhash
-% \doframedparentparameter
-% \doframedparentparameterhash
-% \dosetframedattributes
-
-
-% \setupheads
-
-\setupstructureheads[%
+\setupheads[%
%\c!after=,
%\c!align=,
%\c!aligntitle=,
@@ -71,14 +39,14 @@
\c!incrementnumber=\v!yes,
\c!indentnext=\v!no,
%\c!label=,
- \c!limittext=\v!yes,
+ %\c!limittext=\languageparameter\c!limittext,
\c!margin=\zeropoint,
%\c!margintext=,
\c!number=\v!yes,
- \c!numbercolor=\structureheadparameter\c!color,
- \c!textcolor=\structureheadparameter\c!color,
- \c!numberstyle=\structureheadparameter\c!style,
- \c!textstyle=\structureheadparameter\c!style,
+ \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,
@@ -95,13 +63,16 @@
%\c!strut=,
%\c!style=,
%\c!text=,
- %\c!tolerance=
+ %\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
]
-% \setupstructureblock[appendix][sectionconversionset=appendix]
-% \setupstructurehead[chapter][sectionconversionset=\structureblockparameter\c!sectionconversionset] % \structureblockparameter]
+% \setupsectionblock[appendix][sectionconversionset=appendix]
+% \setuphead[chapter][sectionconversionset=\sectionblockparameter\c!sectionconversionset] % \sectionblockparameter]
-% \definestructureresetset[default][0,1,1,0][1] % this will not reset parts and subsections
+% \defineresetset[default][0,1,1,0][1] % this will not reset parts and subsections
% \setuphead[part][sectionresetset=default]
% \starttext
% \placelist[chapter,section,subsection][criterium=all,width=3cm]
@@ -109,150 +80,151 @@
% \part{second} \chapter{gamma} \section{a} \section{b} \subsection{x} \subsection{y} \chapter{delta}
% \stoptext
-\definestructureseparatorset [\s!default] [] [.]
-\definestructureconversionset [\s!default] [] [numbers]
-\definestructureresetset [\s!default] [] [1] % each level
-\definestructureprefixset [\s!default] [section-1,section-2,section-3] []
+\defineseparatorset [\s!default] [] [.]
+\defineconversionset [\s!default] [] [numbers]
+\defineresetset [\s!default] [] [1] % each level
+\defineprefixset [\s!default] [section-1,section-2,section-3] []
-\definestructureconversionset [\v!pagenumber] [] [numbers]
+\defineconversionset [\v!pagenumber] [] [numbers]
-\definestructureprefixset [\v!all] [section-1,section-2,section-3,section-4,section-5,section-6,section-7,section-8] []
-\definestructureprefixset [\v!none] [] []
+\defineprefixset [\v!all] [section-1,section-2,section-3,section-4,section-5,section-6,section-7,section-8] []
+\defineprefixset [\v!none] [] []
-\definestructureprefixset [\v!part] [section-1] []
-\definestructureprefixset [\v!chapter] [section-2] []
+\defineprefixset [\v!part] [section-1] []
+\defineprefixset [\v!chapter] [section-2] []
-\definestructureseparatorset [\v!appendix:\s!default] [] [.]
-\definestructureconversionset [\v!appendix:\s!default] [Romannumerals,Characters] [numbers]
-\definestructureresetset [\v!appendix:\s!default] [] [1] % why was this 0
+\defineseparatorset [\v!appendix:\s!default] [] [.]
+\defineconversionset [\v!appendix:\s!default] [Romannumerals,Characters] [numbers]
+\defineresetset [\v!appendix:\s!default] [] [1] % why was this 0
-\setupuserpagenumber [\c!numberconversionset=\v!pagenumber]
+\setupuserpagenumber
+ [\c!numberconversionset=\v!pagenumber]
% \startsetups defaults:frontpart:pagenumbers:roman
-% \definestructureconversionset[\c!frontpart:\c!pagenumber][][romannumerals]
+% \defineconversionset[\c!frontpart:\c!pagenumber][][romannumerals]
% \setupuserpagenumber[\c!way=\v!byblock]
% \stopsetups
% \definesectionblock
-\definestructureblock [\v!frontpart] [\v!frontmatter] [\c!number=\v!no]
-\definestructureblock [\v!bodypart] [\v!bodymatter] [\c!number=\v!yes]
-\definestructureblock [\v!appendix] [\v!appendices] [\c!number=\v!yes]
-\definestructureblock [\v!backpart] [\v!backmatter] [\c!number=\v!no]
+\definesectionblock [\v!frontpart] [\v!frontmatter] [\c!number=\v!no]
+\definesectionblock [\v!bodypart] [\v!bodymatter] [\c!number=\v!yes]
+\definesectionblock [\v!appendix] [\v!appendices] [\c!number=\v!yes]
+\definesectionblock [\v!backpart] [\v!backmatter] [\c!number=\v!no]
-\setstructureblock [\v!bodypart] % default
+\setsectionblock [\v!bodypart] % default
\appendtoks
- \setstructureblock [\v!bodypart]% default
+ \setsectionblock [\v!bodypart]% default
\to \everyjob
-% \definesection
+% \definesection (could become \definehead with one parameter)
-\definestructuresection[\s!section-1] % part
-\definestructuresection[\s!section-2] % chapter
-\definestructuresection[\s!section-3] % section
-\definestructuresection[\s!section-4] % subsection
-\definestructuresection[\s!section-5] % subsubsection
-\definestructuresection[\s!section-6] % subsubsubsection
-\definestructuresection[\s!section-7] % subsubsubsubsection
+\definesection[\s!section-1] % part
+\definesection[\s!section-2] % chapter
+\definesection[\s!section-3] % section
+\definesection[\s!section-4] % subsection
+\definesection[\s!section-5] % subsubsection
+\definesection[\s!section-6] % subsubsubsection
+\definesection[\s!section-7] % subsubsubsubsection
% \definehead
-\definestructurehead
+\definehead
[\v!part]
[\c!section=\s!section-1]
-\definestructurehead
+\definehead
[\v!chapter]
[\c!section=\s!section-2]
-\definestructurehead
+\definehead
[\v!section]
[\c!section=\s!section-3]
-\definestructurehead
+\definehead
[\v!subsection]
[\c!section=\s!section-4,
\c!default=\v!section]
-\definestructurehead
+\definehead
[\v!subsubsection]
[\c!section=\s!section-5,
\c!default=\v!subsection]
-\definestructurehead
+\definehead
[\v!subsubsubsection]
[\c!section=\s!section-6,
\c!default=\v!subsubsection]
-\definestructurehead
+\definehead
[\v!subsubsubsubsection]
[\c!section=\s!section-7,
\c!default=\v!subsubsubsection]
-\definestructurehead
+\definehead
[\v!title]
[\c!coupling=\v!chapter,
\c!default=\v!chapter,
\c!incrementnumber=\v!no]
-\definestructurehead
+\definehead
[\v!subject]
[\c!coupling=\v!section,
\c!default=\v!section,
\c!incrementnumber=\v!no]
-\definestructurehead
+\definehead
[\v!subsubject]
[\c!coupling=\v!subsection,
\c!default=\v!subsection,
\c!incrementnumber=\v!no]
-\definestructurehead
+\definehead
[\v!subsubsubject]
[\c!coupling=\v!subsubsection,
\c!default=\v!subsubsection,
\c!incrementnumber=\v!no]
-\definestructurehead
+\definehead
[\v!subsubsubsubject]
[\c!coupling=\v!subsubsubsection,
\c!default=\v!subsubsubsection,
\c!incrementnumber=\v!no]
-\definestructurehead
+\definehead
[\v!subsubsubsubsubject]
[\c!coupling=\v!subsubsubsubsection,
\c!default=\v!subsubsubsubsection,
\c!incrementnumber=\v!no]
-\setupstructurehead
+\setuphead
[\v!part]
[\c!placehead=\v!no]
-\setupstructurehead
+\setuphead
[\v!chapter]
[\v!appendix\c!label=\v!appendix,
\v!bodypart\c!label=\v!chapter] % bijlageconversie=\Character
-\setupstructurehead
+\setuphead
[\v!section]
[\v!appendix\c!label=\v!section,
\v!bodypart\c!label=\v!section] % bijlageconversie=\Character
-\setupstructurehead
+\setuphead
[\v!subsection]
[\v!appendix\c!label=\v!subsection,
\v!bodypart\c!label=\v!subsection] % bijlageconversie=\Character
-\setupstructurehead
+\setuphead
[\v!subsubsection]
[\v!appendix\c!label=\v!subsubsection,
\v!bodypart\c!label=\v!subsubsection] % bijlageconversie=\Character
% \setuphead
-\setupstructurehead
+\setuphead
[\v!part,\v!chapter]
[%\c!align=,
%\c!indentnext=\v!no,
@@ -265,7 +237,7 @@
\c!before={\blank[2*\v!big]},
\c!after={\blank[2*\v!big]}]
-\setupstructurehead
+\setuphead
[\v!section]
[%\c!align=,
%\c!indentnext=\v!no,
@@ -274,13 +246,13 @@
\c!before={\blank[2*\v!big]},
\c!after=\blank]
-\setupstructurehead % nieuw
+\setuphead % nieuw
[\v!subsection]
[\c!page=]
% brrr
-% \definestructurecounter[\v!page][\c!start=1] % todo: setup
+% \definecounter[\v!page][\c!start=1] % todo: setup
% lists
diff --git a/Master/texmf-dist/tex/context/base/strc-des.mkii b/Master/texmf-dist/tex/context/base/strc-des.mkii
index 0c34e9ef9e0..587ef13e73f 100644
--- a/Master/texmf-dist/tex/context/base/strc-des.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-des.mkii
@@ -5,7 +5,7 @@
%D subtitle=Descriptions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-des.mkiv b/Master/texmf-dist/tex/context/base/strc-des.mkiv
deleted file mode 100644
index 54eba1eaa65..00000000000
--- a/Master/texmf-dist/tex/context/base/strc-des.mkiv
+++ /dev/null
@@ -1,1130 +0,0 @@
-%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 / Hans Hagen]
-%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}
-
-\registerctxluafile{strc-des}{1.001}
-
-%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]
-
-\unprotect
-
-% description parameters
-
-\def\descriptionparameter #1{\csname\dodescriptionparameter{\??dd\currentdescription }#1\endcsname}
-\def\descriptionmainparameter #1{\csname\dodescriptionparameter{\??dd\currentdescriptionmain }#1\endcsname}
-\def\descriptionnumberparameter#1{\csname\dodescriptionparameter{\??dd\currentdescriptionnumber}#1\endcsname}
-
-\def\nameddescriptionparameter #1#2{\csname\dodescriptionparameter{\??dd#1}#2\endcsname}
-
-\def\detokenizeddescriptionparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??dd\currentdescription#1\endcsname}}
-
-\def\dodescriptionparameter#1#2%
- {\ifcsname#1#2\endcsname#1#2\else\expandafter\dodescriptionparentparameter\csname#1\s!parent\endcsname#2\fi}
-
-\def\dodescriptionparentparameter#1#2%
- {\ifx#1\relax\s!empty\else\dodescriptionparameter#1#2\fi}
-
-\def\descriptionlocationparameter#1{\csname\dodescriptionlocationparameter{\??dd\currentdescription}#1\endcsname}
-
-\def\dodescriptionlocationparameter#1#2%
- {\ifcsname#1#2:\descriptionparameter\c!location\endcsname
- #1#2:\descriptionparameter\c!location
- \else\ifcsname#1\s!parent\endcsname
- \expandafter\dodescriptionlocationparameter\csname#1\s!parent\endcsname#2%
- \else
- \dodescriptionparameter{\??dd\currentdescription}#2%
- \fi\fi}
-
-% description hashes (needed for style/color)
-
-\def\descriptionparameterhash #1{\dodescriptionparameterhash{\??dd\currentdescription }#1}
-\def\descriptionmainparameterhash#1{\dodescriptionparameterhash{\??dd\currentdescriptionmain}#1}
-
-\def\dodescriptionparameterhash#1#2%
- {\ifcsname#1#2\endcsname#1\else\expandafter\dodescriptionparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\dodescriptionparentparameterhash#1#2%
- {\ifx#1\relax\else\dodescriptionparameterhash#1#2\fi}
-
-\def\dosetdescriptionattributes#1#2% style color
- {\edef\fontattributehash {\descriptionparameterhash#1}%
- \edef\colorattributehash{\descriptionparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-% typesetting code
-
-\newbox \descriptionheadbox
-\newskip \leftdescriptionskip
-\newskip \rightdescriptionskip
-\newdimen \descriptionsheadwidth % replaces \!!widtha
-\newdimen \descriptionsheaddistance % replaces \!!widthb
-
-\setvalue{@@description\v!left }{\@@descriptionhang\@@descriptionleftpure \@@descriptionlefthang \@@descriptionleftmargin }
-\setvalue{@@description\v!right}{\@@descriptionhang\@@descriptionrightpure\@@descriptionrighthang\@@descriptionrightmargin}
-
-\def\@@descriptionhang#1#2#3% \next still needed?
- {\processaction
- [\descriptionparameter\c!hang]
- [ \v!none=>\let\next#1,%
- 0=>\let\next#1,%
- \v!margin=>\let\next#3,%
- \s!unknown=>\let\next#2,%
- \s!default=>\let\next#1]%
- \next}
-
-\def\@@descriptionleftpure
- {\def\\{\crlf}%
- \noindent
- \leftskip\dimexpr\leftdescriptionskip+\descriptionsheadwidth\relax
- \rightskip\rightdescriptionskip
- \@@makedescriptionpurebox\raggedright
- \advance\leftskip\descriptionsheaddistance
- \llap
- {\hbox to \leftskip
- {\hskip\leftdescriptionskip
- \copy\descriptionheadbox\hss}}%
- \@@dodescription}
-
-\def\@@descriptionrightpure
- {\def\\{\crlf}%
- \noindent
- \leftskip\leftdescriptionskip
- \rightskip\dimexpr\rightdescriptionskip+\descriptionsheadwidth\relax
- \@@makedescriptionpurebox\raggedleft
- \rlap
- {\hskip\dimexpr\hsize-\leftskip-\rightskip\relax
- \copy\descriptionheadbox
- \hskip\rightdescriptionskip}%
- \advance\rightskip \descriptionsheaddistance
- \@@dodescription}
-
-\def\@@descriptionleftmargin
- {\def\\{\crlf}%
- \noindent
- \llap
- {\@@makedescriptionpurebox\raggedright
- \hbox to \descriptionsheadwidth{\copy\descriptionheadbox\hss}%
- \hskip\descriptionsheaddistance}%
- \@@dodescription}
-
-\def\@@descriptionrightmargin % whatever this means
- {\def\\{\crlf}%
- \noindent
- \rlap
- {\hskip\descriptionsheaddistance
- \@@makedescriptionpurebox\raggedright
- \hbox to \descriptionsheadwidth{\copy\descriptionheadbox\hss}}%
- \@@dodescription}
-
-\def\@@makedescriptionpurebox#1%
- {\setbox\descriptionheadbox\vtop
- {\dontcomplain
- \hsize\descriptionsheadwidth
- \leftskip\zeropoint
- \rightskip\zeropoint
- #1\setupalign[\descriptionparameter\c!headalign]%
- \ifhbox\descriptionheadbox\unhcopy\else\copy\fi\descriptionheadbox}%
- \ht\descriptionheadbox\strutht
- \dp\descriptionheadbox\strutdp}
-
-\def\@@descriptionlefthang
- {\def\\{\crlf}%
- \dontcomplain
- \advance\descriptionsheadwidth \descriptionsheaddistance
- \hangindent\descriptionsheadwidth
- \@@makedescriptionhangbox\raggedright{\advance\rightskip \descriptionsheaddistance}%
- \noindent
- \llap
- {\dontshowcomposition
- \vtop to \zeropoint{\box\descriptionheadbox}}%
- \@@dodescription}
-
-\def\@@descriptionrighthang
- {\def\\{\crlf}%
- \dontcomplain
- \advance\descriptionsheadwidth \descriptionsheaddistance
- \hangindent-\descriptionsheadwidth
- \@@makedescriptionhangbox\raggedleft{\advance\leftskip \descriptionsheaddistance}%
- \noindent
- \rlap
- {\dontcomplain
- \dontshowcomposition
- \hbox to \dimexpr\hsize-\leftskip-\rightskip\relax % can be a macro
- {\hss\vtop to \zeropoint{\box\descriptionheadbox}}}%
- \@@dodescription}
-
-\def\@@makedescriptionhangbox#1#2%
- {\setbox\descriptionheadbox\vtop % \vbox gaat fout in hang
- {\forgetall
- \dontcomplain
- \hsize\descriptionsheadwidth
- #1\setupalign[\descriptionparameter\c!headalign]#2%
- \ifhbox\descriptionheadbox\unhcopy\else\copy\fi\descriptionheadbox}%
- \ht\descriptionheadbox\strutht
- \dp\descriptionheadbox\strutdp
- \doifsomething{\descriptionparameter\c!hang}
- {\doifinsetelse{\descriptionparameter\c!hang}{\v!fit,\v!broad}
- {\scratchdimen\htdp\descriptionheadbox
- \doif{\descriptionparameter\c!hang}\v!broad
- {\advance\scratchdimen .5\strutht}%
- \getnoflines\scratchdimen
- \hangafter-\noflines}
- {\hangafter-\descriptionparameter\c!hang}}}
-
-\setvalue{@@description\v!top}%
- {%\page[\v!preference]% % Weg ermee!
- %\dosomebreak{\goodbreak}% % Dit is beter en nodig!
- \dohandlepagebreakX\plusone % En dit moet het maar worden.
- \let\\=\space
- \noindent
- \copy\descriptionheadbox\par
- \nobreak
- %\descriptionparameter\c!inbetween % .. brrrr ... :
- \doifelsenothing{\descriptionparameter\c!inbetween}{\blank}{\descriptionparameter\c!inbetween}%
- \nobreak
- \@@dodescription}
-
-\def\do@@description#1% temp hack, the scope
- {\def\\{\crlf}%
- \noindent
- #1[\c!scope=\v!local]{\ifhbox\descriptionheadbox\unhcopy\else\copy\fi\descriptionheadbox}%
- \@@dodescription}
-
-\setvalue{@@description\v!inmargin }{\do@@description\inmargin}
-\setvalue{@@description\v!inleft }{\do@@description\inleft }
-\setvalue{@@description\v!inright }{\do@@description\inright }
-\setvalue{@@description\v!margin }{\do@@description\inmargin}
-\setvalue{@@description\v!leftmargin }{\do@@description\inleft }
-\setvalue{@@description\v!rightmargin }{\do@@description\inright }
-\setvalue{@@description\v!innermargin }{\do@@description\ininner }
-\setvalue{@@description\v!outermargin }{\do@@description\inouter }
-
-\setvalue{@@description\v!serried\v!fit}%
- {\def\\{\crlf}%
- \noindent
- \ifhbox\descriptionheadbox\unhcopy\else\copy\fi\descriptionheadbox
- \hskip\descriptionsheaddistance % toegevoegd
- \@@dodescription}
-
-\setvalue{@@description\v!serried\v!broad}%
- {\def\\{\crlf}%
- \noindent
- \ifhbox\descriptionheadbox\unhcopy\else\copy\fi\descriptionheadbox
- \hskip\descriptionsheaddistance \!!plus .5\descriptionsheaddistance \!!minus .25\descriptionsheaddistance
- \@@dodescription}
-
-\setvalue{@@description\v!serried\v!wide}%
- {\def\\{\crlf}%
- \noindent
- \hbox to \descriptionsheadwidth
- {\ifhbox\descriptionheadbox\unhcopy\else\copy\fi\descriptionheadbox\hss}%
- \hskip\descriptionsheaddistance
- \@@dodescription}
-
-\setvalue{@@description\v!serried}%
- {\processaction
- [\descriptionlocationparameter\c!width]
- [ \v!fit=>\let\next\v!fit,
- \v!broad=>\let\next\v!broad,
- \s!unknown=>\let\next\v!wide,
- \s!default=>\let\next\v!broad]%
- \getvalue{@@description\v!serried\next}}
-
-\setvalue{@@description\v!hanging}%
- {\def\\{\crlf}%
- \noindent
- \advance\leftskip -\leftskipadaption \relax
- \ifdim\leftskipadaption=\zeropoint
- \leftskipadaption1.5em\relax % just some default
- \ifnum\nesteddescriptionstate=\plusone
- \ifdim\leftskip>\zeropoint \relax
- \leftskipadaption\leftskip
- \fi
- \fi
- \fi
- \ifnum\nesteddescriptionstate>\zerocount % was \ifnum\nesteddescriptionstate=\plusone
- \advance\leftskip \leftskipadaption % but we're already further on
- \fi
- \hskip-\leftskipadaption
- \ifhbox\descriptionheadbox\unhcopy\else\copy\fi\descriptionheadbox
- \kern\ifdim\descriptionsheaddistance=\zeropoint .75em\else\descriptionsheaddistance\fi
- \@@dodescription}
-
-%D A bonus definition
-%D
-%D \starttyping
-%D \setupfootnotedefinition[location=command,headcommand=\llap]
-%D \stoptyping
-
-% \setvalue{@@description\v!command}%
-% {\do@@description{\executeifdefined{\descriptionparameterhash\c!headcommand}\framed}}
-
-\setvalue{@@description\v!command}%
- {\noindent
- \descriptionparameter\c!headcommand{\ifhbox\descriptionheadbox\unhcopy\else\copy\fi\descriptionheadbox}%
- \@@dodescription}
-
-%D A new key 'headalign' in definitions.
-
-\newconstant\nesteddescriptionstate
-
-\def\resetdescriptions % to be used in e.g. footnotes
- {\nesteddescriptionstate\zerocount}
-
-\resetdescriptions
-
-\def\@@dostartdescription
- {\descriptionparameter\c!before
- \begingroup
- \doadaptleftskip{\descriptionparameter\c!margin}%
- \showcomposition
- \setlocalhsize % so we can use \localhsize in width assignments
- \descriptionsheaddistance\descriptionlocationparameter\c!distance\relax
- \ifdim\descriptionsheaddistance=\zeropoint\relax
- \doif{\descriptionlocationparameter\c!width}\v!broad{\descriptionsheaddistance=1em}%
- \fi
- \setbox\descriptionheadbox\hbox
- {\forgetall\dontcomplain
- \settrialtypesetting
- \doifelsenothing{\descriptionparameter\c!sample}
- {\dodescriptionhandler\currentdescriptiontext}%
- {\dodescriptionhandler\currentdescriptionsample}}%
- \assignwidth
- \descriptionsheadwidth
- {\descriptionlocationparameter\c!width}
- {\unhcopy\descriptionheadbox}
- \descriptionsheaddistance
- \setbox\descriptionheadbox\hbox
- {\forgetall\dontcomplain
- \doifelse{\descriptionparameter\c!location}\v!serried % brrr, hack
- {\dodescriptionhandler\currentdescriptiontext}
- {\dodescriptionhandler{\boxeddescriptionhead\currentdescriptiontext}}}%
- \doifelse{\descriptionparameter\c!aligntitle}\v!no
- {\leftdescriptionskip\leftskip\rightdescriptionskip\rightskip}
- {\ifcase\nesteddescriptionstate\leftdescriptionskip\leftskip\rightdescriptionskip\rightskip\fi}%
- \doifsomething{\descriptionparameter\c!align}{\setupalign[\descriptionparameter\c!align]}%
- \normalexpanded{\noexpand\indenting[\descriptionparameter\c!indenting]}%
- % better a system mode
- \ifcase\nesteddescriptionstate
- \nesteddescriptionstate\plusone
- \or
- \nesteddescriptionstate\plustwo
- \fi % now happens elsewhere : \noindent\ignorespaces
- \@@resetdescriptionclosesymbol}
-
-\def\boxeddescriptionhead#1%
- {\vtop
- %{\hsize\dimexpr\descriptionsheadwidth-\descriptionsheaddistance\relax
- {\hsize\descriptionsheadwidth
- \doifsomething{\descriptionparameter\c!headalign}{\setupalign[\descriptionparameter\c!headalign]}%
- #1}}
-
-\def\@@stopdescription
- {\@@placedescriptionclosesymbol
- \doifnot{\descriptionparameter\c!display}\v!no\par
- \dostoptagged
- \dostoptagged
- \endgroup
- \descriptionparameter\c!after % which currentdescription is taken here?
- \normalexpanded
- {\egroup % temporary hack
- \noexpand\checknextindentation[\descriptionparameter\c!indentnext]}%
- \dorechecknextindentation}
-
-\def\@@dodescription
- {\dosetdescriptionattributes\c!style\c!color
- \ignorespaces}
-
-% starters:
-
-\def\@@startdescription[#1]%
- {\doifelse{\descriptionparameter\c!title}\v!yes
- {\permitspacesbetweengroups
- \dodoublegroupempty{\dohandledescriptionstart[#1]}}
- {\dohandledescriptionstart[#1]{}}}
-
-\def\@@description[#1]%
- {\doifelse{\descriptionparameter\c!title}\v!yes
- {\permitspacesbetweengroups
- \dodoublegroupempty{\dohandledescriptiondo[#1]}}
- {\dohandledescriptiondo[#1]{}}}
-
-% these call:
-
-\long\def\@@somedescription[#1]#2%
- {\dowithpar
- {\bgroup % temporary hack
- \@@makedescription[#1]{#2}}%
- {\@@stopdescription}}
-
-\long\def\@@startsomedescription[#1]#2%
- {\bgroup % temporary hack
- \BeforePar{\@@makedescription[#1]{#2}}%
- \GotoPar}
-
-\let\dotagsetdescriptiontag\relax
-
-\def\@@dostartdescriptionindeed
- {\edef\currentdescriptionlocation{\descriptionparameter\c!location}%
- \ifx\currentdescriptionlocation\empty
- \let\currentdescriptionlocation\v!left
- \fi
- \ifcsname @@description\currentdescriptionlocation\endcsname \else
- \let\currentdescriptionlocation\v!left
- \fi
- \dostarttagged\t!description\currentdescription
- \dostarttagged\t!descriptiontag\empty
- \dotagsetdescriptiontag
- \@@dostartdescription
- \csname @@description\currentdescriptionlocation\endcsname
- \dostoptagged
- \dostarttagged\t!descriptioncontent\empty} % args not needed
-
-\def\@@makedescription[#1]#2%
- {\postponenotes % new, assumes grouping
- \edef\currentdescriptionreference{#1}%
- \doenumerationcheckconditions
- \dodescriptioncomponent[\c!reference=#1,\c!label={\descriptionparameter\c!text},\c!title={#2},\c!bookmark=,\c!list=][]%
- \@@dostartdescriptionindeed}
-
-\def\dostartstoreddescription
- {\@@dostartdescriptionindeed}
-
-\def\dostopstoreddescription
- {\@@stopdescription}
-
-% % % % % % % % % % % %
-
-% helpers
-
-% todo: \dosetfontattributewithhash \descriptionparameterhash\c!headstyle
-
-% setup descriptions
-
-\unexpanded\def\setupdescriptions
- {\dodoubleempty\dosetupdescriptions}
-
-\def\dosetupdescriptions[#1][#2]% % beter: \iffirstargument
- {\ifsecondargument
- \dodoubleargumentwithset\dodosetupdescriptions[#1][#2]%
- \else
- \dodosetupdescriptions[][#1]%
- \fi}
-
-\def\dodosetupdescriptions[#1]% [#2]%
- {\getparameters[\??dd#1]} % [#2]}
-
-% define descriptions
-
-\unexpanded\def\definedescription
- {\dotripleemptywithset\dodefinedescription}
-
-\def\dodefinedescription[#1][#2][#3]% to be simplified cf enumeration
- {\dodescriptioninit{#1}%
- \getparameters[\??dd#1][\c!text=,\s!handler=\v!description,\c!title=\v!yes]%
- \ifsecondargument\doifassignmentelse{#2}\donetrue\donefalse\else\donetrue\fi
- \ifdone
- \getparameters[\??dd#1][\s!parent=\??dd,\c!text=,\s!handler=\v!description,#2]%
- \dodefinedescriptioncommands{#1}{\??dd}%
- \else % clone
- \getparameters[\??dd#1][\s!parent=\??dd#2,\c!text=,\s!handler=\v!description,#3]% clone
- \dodefinedescriptioncommands{#1}{\??dd#2}%
- \fi}
-
-\def\dodefinedescriptioncommands#1#2%
- {\setuevalue {#1}{\noexpand\dodescriptioncommand{#1}}%
- \setuevalue{\e!start#1}{\noexpand\dodescriptionstart {#1}}%
- \setuevalue{\e!stop #1}{\noexpand\dodescriptionstop {#1}}}
-
-% handle descriptions
-
-\def\dodescriptioninit#1%
- {\let\currentdescriptionmain \empty
- \let\currentdescriptionlevel \empty
- \edef\currentdescriptionname {#1}%
- \edef\currentdescription {#1}}
-
-\def\dodescriptioncommand#1{\dodescriptioninit{#1}\dosingleempty\@@description}
-\def\dodescriptionstart #1{\dodescriptioninit{#1}\dosingleempty\@@startdescription}
-\def\dodescriptionstop #1{\dodescriptioninit{#1}\@@stopdescription}
-
-\def\dodescriptiontext {\csname\??dd:\descriptionparameter\s!handler:\s!handler:\s!text \endcsname}
-\def\dodescriptionnumber {\csname\??dd:\descriptionparameter\s!handler:\s!handler:\s!number\endcsname}
-\def\dodescriptionhandler {\csname\??dd:\descriptionparameter\s!handler:\s!handler \endcsname}
-\def\dohandledescriptiondo {\csname\??dd:\descriptionparameter\s!handler:\s!handler:\s!do \endcsname}
-\def\dohandledescriptionstart{\csname\??dd:\descriptionparameter\s!handler:\s!handler:\s!start \endcsname}
-
-\def\currentdescriptiontext {\begstrut\dodescriptiontext\endstrut}
-\def\currentdescriptionsample{\begstrut\descriptionparameter\c!text\descriptionparameter\c!sample\endstrut}
-
-% implementation
-
-% beware: with footnotes #2 can be something messy but then #1 is
-% empty anyway, so we have an extra safeguard
-
-\newtoks \everydescription
-
-\setvalue{\??dd:\v!description:\s!handler:\s!text }{\@@dodescriptiontext}
-\setvalue{\??dd:\v!description:\s!handler }{\@@dodescriptionhandler}
-\setvalue{\??dd:\v!description:\s!handler:\s!do }{\@@somedescription}
-\setvalue{\??dd:\v!description:\s!handler:\s!start}{\@@startsomedescription}
-
-\def\@@dodescriptionhandler#1%
- {\iftrialtypesetting \else
- \begingroup
- \currentdescriptionsynchronize
- \attribute\destinationattribute\currentdescriptionattribute\relax % todo, whole text
- \forcecolorhack
- \endgroup
- \fi#1}
-
-\def\@@dododescriptiontext
- {\ctxlua{structures.lists.savedtitle("\currentdescriptionmain",\currentdescriptionnumberentry)}}
-
-\def\@@dodescriptiontext
- {\begingroup
- \dosetdescriptionattributes\c!headstyle\c!headcolor
- \the\everydescription
- \descriptionparameter\c!command{\strut\descriptionparameter\c!text\ignorespaces\@@dododescriptiontext}% probably incomplete
- \endgroup}
-
-% setup enumerations
-
-\unexpanded\def\setupenumerations
- {\dodoubleempty\dosetupenumerations}
-
-\def\dodosetupenumerations[#1][#2]%
- {\doenumerationinit{#1}{1}\empty
- \getparameters[\??dd#1][#2]%
- \dosetupenumerationcounter{#1}}
-
-\def\dosetupenumerations[#1][#2]%
- {\ifsecondargument
- \dodoubleargumentwithset\dodosetupenumerations[#1][#2]%
- \else
- \getparameters[\??dn][#1]%
- \fi}
-
-% define enumerations
-
-\unexpanded\def\defineenumeration
- {\dotripleemptywithset\dodefineenumeration}
-
-\def\dodefineenumeration[#1][#2][#3]% #2 or #3 assignment
- {\doenumerationinit{#1}{1}\empty
- \getparameters[\??dd#1][\c!text=#1,\c!state=\v!start,\s!handler=\v!enumeration,\c!levels=4]%
- \ifsecondargument\doifassignmentelse{#2}\donetrue\donefalse\else\donetrue\fi
- \ifdone % independent
- \getparameters[\??dd#1][\s!counter=#1,#2]%
- \dodefineenumerationcommands{#1}{1}{}{\??dn}%
- \let\@@subslevel\empty
- \dostepwiserecurse{2}{\descriptionparameter\c!levels}{1}
- {\normalexpanded{\noexpand\dodefineenumerationcommands{#1}{\recurselevel}{\@@subslevel\v!sub}{\??dd\@@subslevel#1}}%
- \edef\@@subslevel{\@@subslevel\v!sub}}%
- \else % clone
- \getparameters[\??dd#1][\s!parent=\??dd#2,#3]%
- \let\@@subslevel\empty
- \dorecurse{\descriptionparameter\c!levels}
- {\normalexpanded{\noexpand\dodefineenumerationcommands{#1}{\recurselevel}{\@@subslevel}{\??dd\@@subslevel#2}}%
- \edef\@@subslevel{\@@subslevel\v!sub}}%
- \fi
- \edef\currentdescriptioncounter{\descriptionparameter\s!counter}%
- \ifx\currentdescriptioncounter\empty
- \ifdone\dodefineenumerationcounter{#1}\fi
- \else\ifx\currentdescriptioncounter\v!yes
- \ifdone\dodefineenumerationcounter{#1}\fi
- \else\ifx\currentdescriptioncounter\v!no
- \ifdone\dodefineenumerationcounter{#1}\fi
- \else
- \letvalue{\??dd#1\s!counter}\currentdescriptioncounter % ?
- %[[#1:\currentdescriptioncounter]]
- \doifstructurecounterelse{\currentdescriptioncounter}{}{\dodefineenumerationcounter\currentdescriptioncounter}%
- \fi\fi\fi
- \dosetupenumerationcounter{#1}} % new
-
-\newtoks\everysetupenumerationcounter
-\let\currentenumerationcountername\empty
-
-\def\dosetupenumerationcounter#1%
- {\edef\currentenumerationcountername{#1}% only used in the token list
- \edef\currentdescription{#1}%
- \the\everysetupenumerationcounter}
-
-\appendtoks
- \dostructurecountersetup\currentenumerationcountername\descriptionparameter
-\to \everysetupenumerationcounter
-
-\def\dodefineenumerationcounter#1% todo: fast inheritance (was mainparameter
- {\definestructurecounter[#1]%
- \dosetupenumerationcounter{#1}}
-
-\def\dodefineenumerationcommands#1#2#3#4% since we use \currentdescription, we need an edef
- {\setevalue{\??dd#3#1\s!parent}{#4}%
- \setuevalue {#3#1}{\noexpand\doenumerationcommand {#1}{#2}{#3}}%
- \setuevalue{\c!reset#3#1}{\noexpand\doresetenumerationnumber{#1}{#2}{#3}}%
- %setuevalue{\c!set #3#1}{\noexpand\dosetenumerationnumber {#1}{#2}{#3}}%
- \setuevalue{\e!next #3#1}{\noexpand\donextenumerationnumber {#1}{#2}{#3}}%
- \setuevalue{\e!start#3#1}{\noexpand\doenumerationstart {#1}{#2}{#3}}%
- \setuevalue{\e!stop #3#1}{\noexpand\doenumerationstop {#1}{#2}{#3}}}
-
-% handle enumeration
-
-\def\currentdescriptionnumber {\csname\??dd\currentdescriptionmain\s!counter\endcsname}% no edef (yet)
-\def\specificdescriptionnumber#1{\csname\??dd#1\s!counter\endcsname}% no edef (yet)
-
-\def\doenumerationinit#1#2#3%
- {\edef\currentdescriptionmain {#1}%
- \edef\currentdescriptionlevel{#2}%
- \edef\currentdescriptionname {#1}%
- \edef\currentdescription {#3#1}}
-
-\def\doenumerationcommand#1#2#3{\doenumerationinit{#1}{#2}{#3}\dosingleempty\@@description}
-\def\doenumerationstart #1#2#3{\doenumerationinit{#1}{#2}{#3}\dosingleempty\@@startdescription}
-\def\doenumerationstop #1#2#3{\doenumerationinit{#1}{#2}{#3}\@@stopdescription}
-
-\def\doresetenumerationnumber#1#2#3{\doresetsubstructurecounter [\specificdescriptionnumber{#1}][#2]}
-\def\dosetenumerationnumber#1#2#3#4{\dosetsubstructurecounter [\specificdescriptionnumber{#1}][#2]{#4}}
-\def\donextenumerationnumber #1#2#3{\doincrementsubstructurecounter[\specificdescriptionnumber{#1}][#2]}
-
-% implementation
-
-\newtoks \everyenumeration
-\newconditional\enumerationnumberenabled
-\def \enumerationdisablenumbersignal {-}
-
-\appendtoks \disablepseudocaps \to \everyenumeration % sorry, uppercase causes troubles
-
-\setvalue{\??dd:\v!enumeration:\s!handler:\s!number}{\@@doenumerationnumber}
-\setvalue{\??dd:\v!enumeration:\s!handler:\s!text }{\@@doenumerationtext}
-\setvalue{\??dd:\v!enumeration:\s!handler }{\@@doenumerationhandler}
-\setvalue{\??dd:\v!enumeration:\s!handler:\s!do }{\@@somedescription}
-\setvalue{\??dd:\v!enumeration:\s!handler:\s!start }{\@@startsomedescription}
-
-\let\@@doenumerationhandler\@@dodescriptionhandler
-
-% \def\currentenumerationfullnumber
-% {\ctxlua{structures.lists.savedprefixednumber("\currentdescriptionmain",\currentdescriptionnumberentry)}}
-
-\def\@@doenumerationnumber
- {\ctxlua{structures.lists.savedprefixednumber("\currentdescriptionmain",\currentdescriptionnumberentry)}}
-
-\def\@@dodoenumerationtext
- {\ctxlua{structures.lists.savedtitle("\currentdescriptionmain",\currentdescriptionnumberentry)}}
-
-\def\doenumerationnumber
- {\descriptionparameter\c!left
- \descriptionparameter\c!starter
- \dodescriptionnumber
- \descriptionparameter\c!stopper
- \descriptionparameter\c!right}
-
-\def\@@doenumerationtext
- {\ifconditional\enumerationnumberenabled
- \iftrialtypesetting
- \doenumerationfullnumberyes
- \doenumerationcouplingsymbol
- \else
- \doenumerationregistercoupling
- \doenumerationfullnumberyes
- \doenumerationcouplingsymbol
- \fi
- \else
- \doenumerationfullnumbernop
- \fi}
-
-\def\doenumerationfullnumberyes % text, title
- {\begingroup
- \dosetdescriptionattributes\c!headstyle\c!headcolor
- \the\everyenumeration
- \descriptionparameter\c!command{\strut\showdntext\doenumerationnumber\doenumerationextratext}%
- \endgroup}
-
-\def\doenumerationfullnumbernop % text, title
- {\begingroup
- \dosetdescriptionattributes\c!headstyle\c!headcolor
- \the\everyenumeration
- \descriptionparameter\c!command{\strut\showdnpuretext\doenumerationextratext}%
- \endgroup}
-
-\def\doenumerationfullnumber#1% text, title (used in notes) .. todo
- {\begingroup
- \dosetdescriptionattributes\c!headstyle\c!headcolor
- \the\everyenumeration
- \descriptionparameter\c!command{\strut#1\doenumerationnumber\doenumerationextratext}%
- \endgroup}
-
-\def\doenumerationextratext
- {\doif{\descriptionparameter\c!title}\v!yes
- {\doifsomething\@@dodoenumerationtext
- {\begingroup
- \dosetdescriptionattributes\c!titlestyle\c!titlecolor
- \hskip\descriptionparameter\c!titledistance
- \descriptionparameter\c!titlecommand
- {\descriptionparameter\c!titleleft
- \begstrut\@@dodoenumerationtext\endstrut
- \descriptionparameter\c!titleright}%
- \endgroup}}}
-
-\def\doenumerationsavecounter {\savestructurecounter[\currentdescriptionnumber]}
-\def\doenumerationrestorecounter {\restorestructurecounter[\currentdescriptionnumber]}
-\def\doenumerationincrementcounter{\doincrementsubstructurecounter[\currentdescriptionnumber][\currentdescriptionlevel]}
-
-% to be used in for instance:
-%
-% coupling=questions .... coupling=answers
-%
-% we will provide some more control, like skipping etc or reference relates
-
-\def\doenumerationcheckconditions
- {\doifelse{\descriptionparameter\c!number}\v!yes
- {\ifx\currentdescriptionreference\enumerationdisablenumbersignal
- \setfalse\enumerationnumberenabled \else \settrue\enumerationnumberenabled
- \fi}%
- {\setfalse\enumerationnumberenabled}%
- \edef\currentenumerationcoupling{\descriptionparameter\c!coupling}}
-
-\def\doenumerationregistercoupling
- {\iflocation
- % no area yet, we will provide variants some day
- \fi}
-
-\def\doenumerationcouplingsymbol
- {\iflocation \ifx\currentenumerationcoupling\empty\else
- \symbolreference[order(description:\currentenumerationcoupling:\nextinternalorderreference)]%
- \fi \fi}
-
-\def\skipenumerationcoupling[#1]% e.g. for questions with no answer
- {\ctxlua{structures.references.setnextorder("description","#1")}}
-
-\def\showdnpuretext{\strut\descriptionparameter\c!text} % geen spatie
-\def\showdnlisttext{\descriptionparameter\c!listtext} % space in default
-\def\showdntext {\doifsomething{\descriptionparameter\c!text}{\descriptionparameter\c!text\removeunwantedspaces\fixedspace}}
-
-\unexpanded\def\structurecounterreference#1%
- {[enumref: #1]}
-
-% you can use \placeclosesymbol or \qed to place a symbol at the end of a
-% description
-
-\def\@@resetdescriptionclosesymbol
- {\global\@EA\settrue\csname\??dd\currentdescription:mrk\endcsname
- \let\placeclosesymbol\@@placedescriptionclosesymbol
- \let\qed \@@placedescriptionclosesymbol}
-
-\def\@@placedescriptionclosesymbol
- {\ifconditional\csname\??dd\currentdescription:mrk\endcsname
- \global\@EA\setfalse\csname\??dd\currentdescription:mrk\endcsname
- \doifsomething{\descriptionparameter\c!closesymbol}{\descriptionparameter\c!closecommand{\descriptionparameter\c!closesymbol}}%
- \fi}
-
-\newif\ifnodescriptioncaption
-
-\def\doifelsedescriptioncomponent
- {\ctxlua{structures.lists.doifstoredelse(currentdescriptionnumberentry)}}
-
-\def\dodescriptioncomponent
- {\doifelsedescriptioncomponent\nododescriptioncomponent\dododescriptioncomponent}
-
-\def\nododescriptioncomponent[#1][#2]% #1=interfaced-settings, #2=optional user data
- {}
-
-\def\dododescriptioncomponent[#1][#2]% #1=interfaced-settings, #2=optional user data
- {\begingroup % similar to structure so we might generalize this
- \getparameters[\??dd\currentdescription][#1]%
- %
- \xdef\currentdescriptionexpansion {\descriptionparameter\c!expansion}%
- \xdef\currentdescriptionxmlsetup {\descriptionparameter\c!xmlsetup}%
- \xdef\currentdescriptioncatcodes {\descriptionparameter\s!catcodes}%
- \xdef\currentdescriptionlabel {\descriptionparameter\c!label}%
- \xdef\currentdescriptionreference {\descriptionparameter\c!reference}%
- \xdef\currentdescriptionreferenceprefix{\descriptionparameter\c!referenceprefix}%
- %xdef\currentdescriptionshownumber {\descriptionparameter\c!number}%
- \xdef\currentdescriptionsaveinlist {\descriptionparameter\c!saveinlist}%
- \xdef\currentdescriptionincrementnumber{\descriptionparameter\c!incrementnumber}%
- %
- \ifx\currentdescriptionexpansion\empty
- \glet\currentdescriptionexpansion\v!no
- \fi
- %
- \ifx\currentdescriptionexpansion\s!xml
- \xmlstartraw
- \xdef\currentdescriptiontitle {\descriptionparameter\c!title}%
- \xdef\currentdescriptionbookmark{\descriptionparameter\c!bookmark}%
- \xdef\currentdescriptionmarking {\descriptionparameter\c!marking}%
- \xdef\currentdescriptionlist {\descriptionparameter\c!list}%
- \xmlstopraw
- \ifx\currentdescriptionlist\empty
- \globallet\currentdescriptionlist\currentdescriptiontitle
- \fi
- \globallet\currentdescriptioncoding\s!xml
- \else
- \ifx\currentdescriptionexpansion\v!yes
- \xdef\currentdescriptiontitle {\descriptionparameter\c!title}%
- \xdef\currentdescriptionbookmark{\descriptionparameter\c!bookmark}%
- \xdef\currentdescriptionmarking {\descriptionparameter\c!marking}%
- \xdef\currentdescriptionlist {\descriptionparameter\c!list}%
- \else
- \xdef\currentdescriptiontitle {\detokenizeddescriptionparameter\c!title}%
- \xdef\currentdescriptionbookmark{\detokenizeddescriptionparameter\c!bookmark}%
- \xdef\currentdescriptionmarking {\detokenizeddescriptionparameter\c!marking}%
- \xdef\currentdescriptionlist {\detokenizeddescriptionparameter\c!list}%
- \iflocation \ifx\currentdescriptionbookmark\empty
- \begingroup
- \simplifycommands
- \xdef\currentdescriptionbookmark{\detokenize\expandafter{\normalexpanded{\descriptionparameter\c!title}}}%
- \endgroup
- \fi \fi
- \fi
- \ifx\currentdescriptionlist\empty
- \globallet\currentdescriptionlist\currentdescriptiontitle
- \fi
- \globallet\currentdescriptioncoding\s!tex
- \fi
- %
- \ifx\currentdescriptiontitle\v!none % will become obsolete
- \global\nodescriptioncaptiontrue\global\nodescriptionnumbertrue
- \fi
- %
- \ifconditional\enumerationnumberenabled
- \doifelsedescriptioncomponent\donothing\doenumerationincrementcounter
- \fi
- %
- \ifnodescriptioncaption
- \glet\currentdescriptionlistnumber \relax
- \glet\currentdescriptionsynchronize\relax
- \glet\currentdescriptionattribute \relax
- \else
- %\setnextinternalreference
- \setnextinternalreferences{description}\currentdescriptionname % plural
- \xdef\currentdescriptionnumberentry{\ctxlua{structures.lists.push{
- metadata = {
- kind = "description",
- name = "\currentdescriptionname",
- level = structures.sections.currentlevel(),
- catcodes = \the\catcodetable,
- % \currentdirectionparameters
- },
- references = {
- internal = \nextinternalreference,
- order = \nextinternalorderreference,
- reference = "\currentdescriptionreference",
- referenceprefix = "\referenceprefix",
- block = "\currentstructureblock",
- section = structures.sections.currentid(),
- },
- titledata = {
- label = \!!bs\detokenize\expandafter{\currentdescriptionlabel }\!!es,
- title = \!!bs\detokenize\expandafter{\currentdescriptiontitle }\!!es,
- \ifx\currentdescriptionbookmark\currentdescriptiontitle \else
- bookmark = \!!bs\detokenize\expandafter{\currentdescriptionbookmark}\!!es,
- \fi
- \ifx\currentdescriptionlist\currentdescriptiontitle \else % \ifx\currentdescriptionsaveinlist\v!no
- list = \!!bs\detokenize\expandafter{\currentdescriptionlist }\!!es,
- \fi % \fi
- },
- \ifconditional\enumerationnumberenabled
- prefixdata = {
- prefix = "\descriptionparameter\c!prefix",
- separatorset = "\descriptionparameter\c!prefixseparatorset",
- conversion = \!!bs\descriptionparameter\c!prefixconversion\!!es,
- conversionset = "\descriptionparameter\c!prefixconversionset",
- set = "\descriptionparameter\c!prefixset",
- segments = "\descriptionparameter\c!prefixsegments",
- connector = \!!bs\descriptionparameter\c!prefixconnector\!!es,
- },
- numberdata = {
- numbers = structures.counters.compact("\currentdescriptionnumber",nil,true), % ! number can be cloned
- separatorset = "\descriptionparameter\c!numberseparatorset",
- conversion = "\descriptionparameter\c!numberconversion",
- conversionset = "\descriptionparameter\c!numberconversionset",
- starter = \!!bs\descriptionparameter\c!numberstarter\!!es,
- stopper = \!!bs\descriptionparameter\c!numberstopper\!!es,
- segments = "\descriptionparameter\c!numbersegments",
- },
- \fi
- userdata = structures.helpers.touserdata(\!!bs\detokenize{#2}\!!es)
- }
- }}%
- \xdef\currentdescriptionattribute {\ctxlua {tex.write(structures.references.setinternalreference("\referenceprefix","\currentdescriptionreference",\nextinternalreference,"\interactionparameter\c!focus"))}}%
- \xdef\currentdescriptionsynchronize{\ctxlatelua{structures.lists.enhance(\currentdescriptionnumberentry)}}%
- \fi
- \endgroup}
-
-% 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.
-
-\def\reinstatedescriptionnumberentry#1%
- {\xdef\currentdescriptionattribute {\ctxlua {tex.write(structures.references.getinternalreference(#1))}}%
- \xdef\currentdescriptionsynchronize{\ctxlatelua{structures.lists.enhance(#1)}}}
-
-\installstructurelistprocessor{description}{\usestructurelistprocessor{number+title}}
-
-% labels, we could share with enumerations and forget about the text; anyhow, figure
-% labels etc can use enumerations; we keep labels for compatibility reasons; we need
-% the slightly different namespace; we can still define structure counters directly
-% (multiple levels) and use an enumeration without following text
-
-% unfinished
-
-\unexpanded\def\setuplabels
- {\getparameters[\??db]}
-
-\unexpanded\def\definelabel
- {\dotripleargumentwithset\dodefinelabel}
-
-\def\dodefinelabel[#1][#2][#3]% #2 or #3 assignment
- {\doenumerationinit{#1}{1}\empty
- \getparameters[\??dd#1][\c!command=,\c!state=\v!start,\c!location=,\c!text=#1]%
- \ifsecondargument\doifassignmentelse{#2}\donetrue\donefalse\else\donetrue\fi
- \ifdone
- % an independent one
- \getparameters[\??dd#1][\s!counter=#1,\s!parent=\??db,#2]%
- \dodefinelabelcommands{#1}{\??db}%
- \dodefineenumerationcounter{#1}%
- \else
- \getparameters[\??dd#1][\s!counter=#1,\s!parent=\??dd#2,#3]%
- \dodefinelabelcommands{#1}{\??dd#2}%
- \fi}
-
-\def\dodefinelabelcommands#1#2%
- {\setuevalue {#1}{\noexpand\dolabelnumbercommand {#1}}%
- \setuevalue{\c!reset #1}{\noexpand\doresetlabelnumber {#1}}%
- %\setuevalue{\c!set #1}{\noexpand\dosetlabelnumber {#1}}% [#2] or {#2} ?
- \setuevalue{\e!next #1}{\noexpand\donextlabelnumber {#1}}%
- \setuevalue{\e!increment#1}{\noexpand\doincrementlabelnumber{#1}}%
- \setuevalue{\c!current #1}{\noexpand\docurrentlabelnumber {#1}}}
-
-% this is just for downward compatibility, we might drop it
-
-\setvalue{\??db:\c!location:\v!inmargin}{\inmargin}
-\setvalue{\??db:\c!location:\v!inleft }{\inleft}
-\setvalue{\??db:\c!location:\v!inright }{\inright}
-\setvalue{\??db:\c!location:\v!margin }{\inmargin}
-
-\def\dolabelinit#1%
- {\def\currentdescriptionmain{#1}%
- \def\currentdescription {#1}%
- \def\currentdescriptionlevel{1}}
-
-\def\docurrentlabelnumber #1{\dolabelinit{#1}\dosingleempty\dodocurrentlabelnumber}
-\def\donextlabelnumber #1{\dolabelinit{#1}\dosingleempty\dodonextlabelnumber}
-\def\dolabelnumbercommand #1{\dolabelinit{#1}\dosingleempty\dodolabelnumbercommand}
-
-\def\doresetlabelnumber #1{\dolabelinit{#1}\doresetsubstructurecounter [\currentdescriptionnumber][\currentdescriptionlevel]}
-\def\dosetlabelnumber #1#2{\dolabelinit{#1}\dosetsubstructurecounter [\currentdescriptionnumber][\currentdescriptionlevel]{#2}}
-\def\doincrementlabelnumber #1{\dolabelinit{#1}\doincrementsubstructurecounter[\currentdescriptionnumber][\currentdescriptionlevel]}
-
-\def\dodocurrentlabelnumber[#1]%
- {\dontleavehmode
- \writestatus{!!!}{todo: reference of label}%
- \dotextprefix{\descriptionparameter\c!text}%
- \convertedsubstructurecounter[\currentdescriptionnumber][\currentdescriptionlevel]}
-
-\def\dodonextlabelnumber[#1]% todo: ref
- {\doincrementsubstructurecounter[\currentdescriptionnumber][\currentdescriptionlevel]%
- \dodocurrentlabelnumber[\currentdescriptionnumber]}
-
-\def\dodolabelnumbercommand[#1]% todo: ref
- {\dontleavehmode
- \descriptionparameter\c!before
- \begingroup
- \doincrementsubstructurecounter[\currentdescriptionnumber][\currentdescriptionlevel]%
- \dosetdescriptionattributes\c!headstyle\c!headcolor
- \executeifdefined{\??db:\c!location:\descriptionparameter\c!location}{\descriptionparameter\c!command}{\dodocurrentlabelnumber[#1]}%
- \endgroup
- \descriptionparameter\c!after}
-
-% to be reimplmented
-
-\unexpanded\def\setupindentations
- {\dodoubleempty\dosetupindentations}
-
-\def\dosetupindentations[#1][#2]%
- {\ifsecondargument
- \dodoubleargumentwithset\dodosetupindentations[#1][#2]%
- \else
- \dodosetupindentations[][#1]%
- \fi}
-
-\def\dodosetupindentations[#1][#2]%
- {\getparameters[\??ds#1][#2]}
-
-\unexpanded\def\defineindenting
- {\dodoubleargumentwithset\dodefineindenting}
-
-\def\dodefineindenting[#1][#2]%
- {\copyparameters[\??ds#1][\??ds]
- [\c!text,\c!separator,\c!width,\c!style,\c!color,
- \c!headstyle,\c!sample,\c!before,\c!after,\c!distance]%
- \getparameters[\??ds#1][#2]%
- \setuvalue {#1}{\dododefineindenting{#1}{0}{1}}%
- \setuvalue {\v!sub#1}{\dododefineindenting{#1}{1}{2}}%
- \setuvalue{\v!sub\v!sub#1}{\dododefineindenting{#1}{2}{3}}}
-
-\def\dododefineindenting#1#2#3%
- {\par
- \getvalue{\??ds#1\c!before}%
- \begingroup
- \doifvaluenothing{\??ds#1\c!sample}
- {\setvalue{\??ds#1\c!sample}{\getvalue{\??ds#1\c!text}}}%
- \assignwidth
- {\descriptionsheadwidth}
- {\getvalue{\??ds#1\c!width}}
- {\doattributes
- {\??ds#1}\c!headstyle\c!headcolor
- {\getvalue{\??ds#1\c!sample}%
- \spr{\getvalue{\??ds#1\c!separator}}}}
- {\getvalue{\??ds#1\c!distance}}%
- \advance\descriptionsheadwidth \getvalue{\??ds#1\c!distance}%
- \setbox\scratchbox\hbox to \descriptionsheadwidth
- {\doattributes
- {\??ds#1}\c!headstyle\c!headcolor
- {\strut
- \getvalue{\??ds#1\c!text}%
- \hss
- \spr{\getvalue{\??ds#1\c!separator}}%
- \hskip\getvalue{\??ds#1\c!distance}}}%
- \parindent\zeropoint
- \hskip#2\descriptionsheadwidth\indent\box\scratchbox
- \hangindent#3\descriptionsheadwidth
- \doattributes{\??ds#1}\c!style\c!color\empty
- \AfterPar{\endgroup\getvalue{\??ds#1\c!after}}% must be redone
- \GetPar}
-
-\setupdescriptions
- [\c!location=\v!left,
- \c!headstyle=\v!bold,
- \c!titlestyle=\v!bold,
- \c!style=\v!normal,
- \c!color=,
- \c!headcolor=,
- \c!titlecolor=,
- \c!width=8em,
- \c!distance=0pt,
- \c!titledistance=0.5em,
- \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=]
-
-\setupenumerations
- [\c!location=\v!top,
- \c!text=,
- \c!way=\v!by\v!text,
- \c!prefix=\v!no,
- \c!prefixconnector=.,
- \c!starter=,
- \c!stopper=,
- \c!number=\v!yes, % else description
- \c!start=0,
- \s!parent=\??dd]
-
-\setupdescriptions
- [\c!expansion=\v!no,
- \c!xmlsetup=,
- \s!catcodes=,
- \c!saveinlist=\v!yes]
-
-\setupenumerations
- [\c!expansion=\v!no,
- \c!xmlsetup=,
- \s!catcodes=,
- \c!saveinlist=\v!yes]
-
-\setupdescriptions
- [\c!width=7em,
- \c!distance=1em]
-
-\setupdescriptions[\c!width:\c!top=\localhsize] % undocumented, only width and distance
-% \setupdescriptions[\c!width:\c!left=7em,\c!distance=1em]
-% \setupdescriptions[\c!width:\c!right=7em,\c!distance=1em]
-
-
-\setuplabels
- [\s!parent=\??dn]
-
-\setupindentations
- [\c!style=\v!normal,
- \c!headstyle=\v!normal,
- \c!color=,
- \c!headcolor=,
- \c!width=\v!fit,
- \c!text=\unknown,
- \c!sample=,
- \c!before=\blank,
- \c!after=\blank,
- \c!distance=1em,
- \c!separator={ :}]
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-des.mkvi b/Master/texmf-dist/tex/context/base/strc-des.mkvi
new file mode 100644
index 00000000000..1b29c864fbc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-des.mkvi
@@ -0,0 +1,200 @@
+%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
+
+\let\setupdescriptions\setupdescription
+
+% \setupdescriptions % check with old
+% [\c!alternative=\descriptionparameter\c!location,
+% \c!location=\v!left]
+
+\setupdescriptions % 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=7em,
+ \c!distance=1em,
+ \c!titledistance=0.5em,
+ %\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
+ \setuevalue {\currentdescription}{\strc_descriptions_command{\currentdescription}}%
+ \setuevalue{\e!start\currentdescription}{\strc_descriptions_start {\currentdescription}}%
+ \setuevalue{\e!stop \currentdescription}{\strc_descriptions_stop}%
+\to \everydefinedescription
+
+\setvalue{\??constructioninitializer\v!description}%
+ {\let\currentdescription \currentconstruction
+ \let\constructionparameter \descriptionparameter
+ \let\detokenizedconstructionparameter\detokenizeddescriptionparameter
+ \let\letconstructionparameter \letdescriptionparameter
+ \let\useconstructionstyleandcolor \usedescriptionstyleandcolor
+ \let\setupcurrentconstruction \setupcurrentdescription
+ \edef\p_title{\constructionparameter\c!title}%
+ \ifx\p_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.
+
+\ifdefined\dotagsetdescription \else \let\dotagsetdescription\relax \fi
+
+% \startdescription [reference] text \stopdescription
+% \startdescription [reference]{title} text \stopdescription
+% \startdescription [title=,title=,reference=] text \stopdescription
+
+\unexpanded\def\strc_descriptions_start#1%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \doifnextoptionalelse\strc_descriptions_start_yes\strc_descriptions_start_nop}
+
+\unexpanded\def\strc_descriptions_start_yes[#1]%
+ {\doifassignmentelse{#1}\strc_descriptions_start_yes_assignment\strc_descriptions_start_yes_reference[#1]}
+
+\unexpanded\def\strc_descriptions_start_yes_assignment[#1]% todo userdata
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1][]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_start_yes_reference
+ {\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_start_yes_titled
+ \else
+ \expandafter\strc_descriptions_start_yes_normal
+ \fi}
+
+\unexpanded\def\strc_descriptions_start_yes_titled[#1]#2% todo userdata
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=][]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_start_yes_normal[#1]% todo userdata
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=][]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_start_nop
+ {\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_start_nop_titled
+ \else
+ \expandafter\strc_descriptions_start_nop_normal
+ \fi}
+
+\unexpanded\def\strc_descriptions_start_nop_titled#1%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_start_nop_normal
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=][]%
+ \csname\??constructionstarthandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_stop
+ {\csname\??constructionstophandler\currentconstructionhandler\endcsname}
+
+% \description [reference] text \par
+% \description [reference] {title} text \par
+
+\unexpanded\def\strc_descriptions_command#1%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \doifnextoptionalelse\strc_descriptions_yes\strc_descriptions_nop}
+
+\unexpanded\def\strc_descriptions_yes
+ {\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_yes_titled
+ \else
+ \expandafter\strc_descriptions_yes_normal
+ \fi}
+
+\unexpanded\def\strc_descriptions_yes_titled[#1]#2%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=][]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_yes_normal[#1]%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title=,\c!bookmark=,\c!list=][]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_nop
+ {\ifconditional\c_strc_constructions_title_state
+ \expandafter\strc_descriptions_nop_titled
+ \else
+ \expandafter\strc_descriptions_nop_normal
+ \fi}
+
+\unexpanded\def\strc_descriptions_nop_titled#1%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]%
+ \csname\??constructioncommandhandler\currentconstructionhandler\endcsname}
+
+\unexpanded\def\strc_descriptions_nop_normal
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\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
+
+\setvalue{\??constructioncommandhandler\v!description}%
+ {\dowithpar
+ {\csname\??constructionstarthandler\v!construction\endcsname}%
+ {\csname\??constructionstophandler \v!construction\endcsname\endgroup}}
+
+\setvalue{\??constructionstarthandler\v!description}%
+ {\BeforePar{\csname\??constructionstarthandler\v!construction\endcsname}%
+ \GotoPar}
+
+\setvalue{\??constructionstophandler\v!description}%
+ {\csname\??constructionstophandler\v!construction\endcsname
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-doc.lua b/Master/texmf-dist/tex/context/base/strc-doc.lua
index d50d49b9236..f10b175a463 100644
--- a/Master/texmf-dist/tex/context/base/strc-doc.lua
+++ b/Master/texmf-dist/tex/context/base/strc-doc.lua
@@ -7,41 +7,57 @@ if not modules then modules = { } end modules ['strc-doc'] = {
}
-- todo: associate counter with head
-
+-- we need to better split the lua/tex end
-- we need to freeze and document this module
+-- keep this as is:
+--
+-- in section titles by default a zero aborts, so there we need: sectionset=bagger with \definestructureprefixset [bagger] [section-2,section-4] []
+-- in lists however zero's are ignored, so there numbersegments=2:4 gives result
+
local next, type = next, type
-local format, gsub, find, concat, gmatch, match = string.format, string.gsub, string.find, table.concat, string.gmatch, string.match
-local texsprint, texwrite = tex.sprint, tex.write
+local format, gsub, find, gmatch, match = string.format, string.gsub, string.find, string.gmatch, string.match
local concat = table.concat
local max, min = math.max, math.min
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
-
-local ctxcatcodes = tex.ctxcatcodes
-local variables = interfaces.variables
-
---~ if not trackers then trackers = { register = function() end } end
-
-local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end)
-local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end)
-
-local report_structure = logs.reporter("structure","sectioning")
-
-local structures, context = structures, context
-
-local helpers = structures.helpers
-local documents = structures.documents
-local sections = structures.sections
-local lists = structures.lists
-local counters = structures.counters
-local sets = structures.sets
-local tags = structures.tags
-local processors = structures.processors
-
-local sprintprocessor = processors.sprint
-local ignoreprocessor = processors.ignore
-
-local a_internal = attributes.private('internal')
+local allocate, mark, accesstable = utilities.storage.allocate, utilities.storage.mark, utilities.tables.accesstable
+
+local catcodenumbers = catcodes.numbers
+local ctxcatcodes = tex.ctxcatcodes
+local variables = interfaces.variables
+
+local v_last = variables.last
+local v_first = variables.first
+local v_previous = variables.previous
+local v_next = variables.next
+local v_auto = variables.auto
+local v_strict = variables.strict
+local v_all = variables.all
+local v_positive = variables.positive
+local v_by = variables.by
+
+local trace_sectioning = false trackers.register("structures.sectioning", function(v) trace_sectioning = v end)
+local trace_detail = false trackers.register("structures.detail", function(v) trace_detail = v end)
+
+local report_structure = logs.reporter("structure","sectioning")
+
+local structures = structures
+local context = context
+
+local helpers = structures.helpers
+local documents = structures.documents
+local sections = structures.sections
+local lists = structures.lists
+local counters = structures.counters
+local sets = structures.sets
+local tags = structures.tags
+
+local processors = typesetters.processors
+local applyprocessor = processors.apply
+local startapplyprocessor = processors.startapply
+local stopapplyprocessor = processors.stopapply
+local strippedprocessor = processors.stripped
+
+local a_internal = attributes.private('internal')
-- -- -- document -- -- --
@@ -49,37 +65,49 @@ local data
function documents.initialize()
data = {
- numbers = { },
- forced = { },
+ numbers = { },
+ forced = { },
ownnumbers = { },
- status = { },
- checkers = { },
- depth = 0,
- blocks = { },
- block = "",
+ status = { },
+ checkers = { },
+ depth = 0,
+ blocks = { },
+ block = "",
}
documents.data = data
end
function documents.reset()
- data.numbers = { }
- data.forced = { }
+ data.numbers = { }
+ data.forced = { }
data.ownnumbers = { }
- data.status = { }
---~ data.checkers = { }
- data.depth = 0
+ data.status = { }
+ -- data.checkers = { }
+ data.depth = 0
end
documents.initialize()
--- -- -- sections -- -- --
+-- -- -- components -- -- --
+function documents.preset(numbers)
+ local nofnumbers = #numbers
+ data.numbers = numbers
+ data.depth = nofnumbers
+ data.ownnumbers = { }
+ for i=1,nofnumbers do
+ data.ownnumbers[i] = ""
+ end
+ sections.setnumber(nofnumbers,"-1")
+end
-local collected = allocate()
-local tobesaved = allocate()
+-- -- -- sections -- -- --
+
+local collected = allocate()
+local tobesaved = allocate()
-sections.collected = collected
-sections.tobesaved = tobesaved
+sections.collected = collected
+sections.tobesaved = tobesaved
--~ local function initializer()
--~ collected = sections.collected
@@ -88,6 +116,15 @@ sections.tobesaved = tobesaved
--~ job.register('structures.sections.collected', tobesaved, initializer)
+sections.registered = sections.registered or allocate()
+local registered = sections.registered
+
+storage.register("structures/sections/registered", registered, "structures.sections.registered")
+
+function sections.register(name,specification)
+ registered[name] = specification
+end
+
function sections.currentid()
return #tobesaved
end
@@ -158,14 +195,16 @@ function sections.getlevel(name)
return levelmap[name] or 0
end
-function sections.way(way,by)
- context((gsub(way,"^"..by,"")))
+local byway = "^" .. v_by
+
+function sections.way(way)
+ context((gsub(way,byway,"")))
end
function sections.setblock(name)
local block = name or data.block or "unknown" -- can be used to set the default
data.block = block
- texwrite(block)
+ context(block)
end
function sections.pushblock(name)
@@ -174,7 +213,7 @@ function sections.pushblock(name)
data.blocks[#data.blocks+1] = block
data.block = block
documents.reset()
- texwrite(block)
+ context(block)
end
function sections.popblock()
@@ -182,7 +221,7 @@ function sections.popblock()
local block = data.blocks[#data.blocks] or data.block
data.block = block
documents.reset()
- texwrite(block)
+ context(block)
end
function sections.currentblock()
@@ -194,17 +233,21 @@ function sections.currentlevel()
end
function sections.getcurrentlevel()
- texwrite(data.depth)
+ context(data.depth)
end
function sections.somelevel(given)
-- old number
- local numbers, ownnumbers, forced, status, olddepth = data.numbers, data.ownnumbers, data.forced, data.status, data.depth
- local givenname = given.metadata.name
+ local numbers = data.numbers
+ local ownnumbers = data.ownnumbers
+ local forced = data.forced
+ local status = data.status
+ local olddepth = data.depth
+ local givenname = given.metadata.name
local mappedlevel = levelmap[givenname]
- local newdepth = tonumber(mappedlevel or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-*
- local directives = given.directives
- local resetset = (directives and directives.resetset) or ""
+ local newdepth = tonumber(mappedlevel or (olddepth > 0 and olddepth) or 1) -- hm, levelmap only works for section-*
+ local directives = given.directives
+ local resetset = (directives and directives.resetset) or ""
-- local resetter = sets.getall("structure:resets",data.block,resetset)
-- a trick to permits userdata to overload title, ownnumber and reference
-- normally these are passed as argument but nowadays we provide several
@@ -324,6 +367,11 @@ function sections.somelevel(given)
references.tag = references.tag or tags.getid(metadata.kind,metadata.name)
+ local setcomponent = structures.references.setcomponent
+ if setcomponent then
+ setcomponent(given) -- might move to the tex end
+ end
+
references.section = sections.save(given)
-- given.numberdata = nil
end
@@ -382,7 +430,7 @@ function sections.matchingtilldepth(depth,numbers,parentnumbers)
end
function sections.getnumber(depth) -- redefined later ...
- texwrite(data.numbers[depth] or 0)
+ context(data.numbers[depth] or 0)
end
function sections.set(key,value)
@@ -394,42 +442,56 @@ function sections.cct()
context(metadata and metadata.catcodes or ctxcatcodes)
end
+-- this one will become: return catcode, d (etc)
+
function sections.structuredata(depth,key,default,honorcatcodetable) -- todo: spec table and then also depth
- if not depth or depth == 0 then depth = data.depth end
+ if depth then
+ depth = levelmap[depth] or tonumber(depth)
+ end
+ if not depth or depth == 0 then
+ depth = data.depth
+ end
local data = data.status[depth]
- local d = data
- for k in gmatch(key,"([^.]+)") do
- if type(d) == "table" then
- d = d[k]
- if not d then
- -- unknown key
- break
- end
+ local d
+ if data then
+ if find(key,"%.") then
+ d = accesstable(key,data)
+ else
+ d = data.titledata
+ d = d and d[key]
end
- if type(d) == "string" then
- if honorcatcodetable == true or honorcatcodetable == variables.auto then
- local metadata = data.metadata
- texsprint((metadata and metadata.catcodes) or ctxcatcodes,d)
- elseif not honorcatcodetable then
+ end
+ if d and type(d) ~= "table" then
+ if honorcatcodetable == true or honorcatcodetable == v_auto then
+ local metadata = data.metadata
+ local catcodes = metadata and metadata.catcodes
+ if catcodes then
+ context.sprint(catcodes,d)
+ else
context(d)
- elseif type(honorcatcodetable) == "number" then
- texsprint(honorcatcodetable,d)
- elseif type(honorcatcodetable) == "string" and honorcatcodetable ~= "" then
- honorcatcodetable = tex[honorcatcodetable] or ctxcatcodes-- we should move ctxcatcodes to another table, ctx or so
- texsprint(honorcatcodetable,d)
+ end
+ elseif not honorcatcodetable or honorcatcodetable == "" then
+ context(d)
+ else
+ local catcodes = catcodenumbers[honorcatcodetable]
+ if catcodes then
+ context.sprint(catcodes,d)
else
context(d)
end
- return
end
- end
- if default then
+ elseif default then
context(default)
end
end
function sections.userdata(depth,key,default)
- if not depth or depth == 0 then depth = data.depth end
+ if depth then
+ depth = levelmap[depth] or tonumber(depth)
+ end
+ if not depth or depth == 0 then
+ depth = data.depth
+ end
if depth > 0 then
local userdata = data.status[depth]
userdata = userdata and userdata.userdata
@@ -455,7 +517,7 @@ function sections.depthnumber(n)
elseif n < 0 then
n = depth + n
end
- return texwrite(data.numbers[n] or 0)
+ return context(data.numbers[n] or 0)
end
function sections.autodepth(numbers)
@@ -496,9 +558,9 @@ local function process(index,numbers,ownnumbers,criterium,separatorset,conversio
local separator = sets.get("structure:separators",block,separatorset,preceding,".")
if separator then
if result then
- result[#result+1] = ignoreprocessor(separator)
+ result[#result+1] = strippedprocessor(separator)
else
- sprintprocessor(ctxcatcodes,separator)
+ applyprocessor(separator)
end
end
preceding = false
@@ -514,14 +576,14 @@ local function process(index,numbers,ownnumbers,criterium,separatorset,conversio
end
else
if ownnumber ~= "" then
- sprintprocessor(ctxcatcodes,ownnumber)
+ applyprocessor(ownnumber)
elseif conversion and conversion ~= "" then -- traditional (e.g. used in itemgroups)
context.convertnumber(conversion,number)
else
local theconversion = sets.get("structure:conversions",block,conversionset,index,"numbers")
- sprintprocessor(ctxcatcodes,theconversion,function(str)
- return format("\\convertnumber{%s}{%s}",str or "numbers",number)
- end)
+ local data = startapplyprocessor(theconversion)
+ context.convertnumber(data or "numbers",number)
+ stopapplyprocessor()
end
end
return index, true
@@ -565,11 +627,11 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
if set == "" then set = "default" end
if segments == "" then segments = nil end
--
- if criterium == variables.strict then
+ if criterium == v_strict then
criterium = 0
- elseif criterium == variables.positive then
+ elseif criterium == v_positive then
criterium = -1
- elseif criterium == variables.all then
+ elseif criterium == v_all then
criterium = -1000000
else
criterium = 0
@@ -578,6 +640,9 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
local firstprefix, lastprefix = 0, 16
if segments then
local f, l = match(tostring(segments),"^(.-):(.+)$")
+ if l == "*" then
+ l = 100 -- new
+ end
if f and l then
-- 0:100, chapter:subsubsection
firstprefix = tonumber(f) or sections.getlevel(f) or 0
@@ -603,9 +668,9 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
local prefixlist = set and sets.getall("structure:prefixes","",set) -- "" == block
if starter then
if result then
- result[#result+1] = ignoreprocessor(starter)
+ result[#result+1] = strippedprocessor(starter)
else
- sprintprocessor(ctxcatcodes,starter)
+ applyprocessor(starter)
end
end
if prefixlist and (kind == 'section' or kind == 'prefix' or kind == 'direct') then
@@ -668,13 +733,13 @@ function sections.typesetnumber(entry,kind,...) -- kind='section','number','pref
if result then
-- can't happen as we're in 'direct'
else
- sprintprocessor(ctxcatcodes,connector)
+ applyprocessor(connector)
end
elseif done and stopper then
if result then
- result[#result+1] = ignoreprocessor(stopper)
+ result[#result+1] = strippedprocessor(stopper)
else
- sprintprocessor(ctxcatcodes,stopper)
+ applyprocessor(stopper)
end
end
return result -- a table !
@@ -691,29 +756,36 @@ function sections.title()
end
end
-function sections.findnumber(depth,what)
+function sections.findnumber(depth,what) -- needs checking (looks wrong and slow too)
local data = data.status[depth or data.depth]
if data then
local index = data.references.section
local collected = sections.collected
local sectiondata = collected[index]
if sectiondata and sectiondata.hidenumber ~= true then -- can be nil
- if what == variables.first then
+ local quit = what == v_previous or what == v_next
+ if what == v_first or what == v_previous then
for i=index,1,-1 do
local s = collected[i]
local n = s.numbers
if #n == depth and n[depth] and n[depth] ~= 0 then
sectiondata = s
+ if quit then
+ break
+ end
elseif #n < depth then
break
end
end
- elseif what == variables.last then
+ elseif what == v_last or what == v_next then
for i=index,#collected do
local s = collected[i]
local n = s.numbers
if #n == depth and n[depth] and n[depth] ~= 0 then
sectiondata = s
+ if quit then
+ break
+ end
elseif #n < depth then
break
end
@@ -724,6 +796,62 @@ function sections.findnumber(depth,what)
end
end
+function sections.finddata(depth,what)
+ local data = data.status[depth or data.depth]
+ if data then
+ -- if sectiondata and sectiondata.hidenumber ~= true then -- can be nil
+ local index = data.references.listindex
+ if index then
+ local collected = structures.lists.collected
+ local quit = what == v_previous or what == v_next
+ if what == v_first or what == v_previous then
+ for i=index-1,1,-1 do
+ local s = collected[i]
+ if not s then
+ break
+ elseif s.metadata.kind == "section" then -- maybe check on name
+ local n = s.numberdata.numbers
+ if #n == depth and n[depth] and n[depth] ~= 0 then
+ data = s
+ if quit then
+ break
+ end
+ elseif #n < depth then
+ break
+ end
+ end
+ end
+ elseif what == v_last or what == v_next then
+ for i=index+1,#collected do
+ local s = collected[i]
+ if not s then
+ break
+ elseif s.metadata.kind == "section" then -- maybe check on name
+ local n = s.numberdata.numbers
+ if #n == depth and n[depth] and n[depth] ~= 0 then
+ data = s
+ if quit then
+ break
+ end
+ elseif #n < depth then
+ break
+ end
+ end
+ end
+ end
+ end
+ return data
+ end
+end
+
+function sections.internalreference(sectionname,what) -- to be used in pagebuilder (no marks used)
+ local r = type(sectionname) == "number" and sectionname or registered[sectionname]
+ if r then
+ local data = sections.finddata(r.level,what)
+ return data and data.references and data.references.internal
+ end
+end
+
function sections.fullnumber(depth,what)
local sectiondata = sections.findnumber(depth,what)
if sectiondata then
@@ -733,5 +861,68 @@ end
function sections.getnumber(depth,what) -- redefined here
local sectiondata = sections.findnumber(depth,what)
- texwrite((sectiondata and sectiondata.numbers[depth]) or 0)
+ context((sectiondata and sectiondata.numbers[depth]) or 0)
+end
+
+-- experimental
+
+local levels = { }
+
+--~ function commands.autonextstructurelevel(level)
+--~ if level > #levels then
+--~ for i=#levels+1,level do
+--~ levels[i] = ""
+--~ end
+--~ end
+--~ local finish = concat(levels,"\n",level) or ""
+--~ for i=level+1,#levels do
+--~ levels[i] = ""
+--~ end
+--~ levels[level] = [[\finalizeautostructurelevel]]
+--~ context(finish)
+--~ end
+
+--~ function commands.autofinishstructurelevels()
+--~ local finish = concat(levels,"\n") or ""
+--~ levels = { }
+--~ context(finish)
+--~ end
+
+function commands.autonextstructurelevel(level)
+ if level > #levels then
+ for i=#levels+1,level do
+ levels[i] = false
+ end
+ else
+ for i=level,#levels do
+ if levels[i] then
+ context.finalizeautostructurelevel()
+ levels[i] = false
+ end
+ end
+ end
+ levels[level] = true
end
+
+function commands.autofinishstructurelevels()
+ for i=1,#levels do
+ if levels[i] then
+ context.finalizeautostructurelevel()
+ end
+ end
+ levels = { }
+end
+
+-- interface (some are actually already commands, like sections.fullnumber)
+
+commands.structurenumber = function() sections.fullnumber() end
+commands.structuretitle = function() sections.title () end
+
+commands.structurevariable = function(name) sections.structuredata(nil,name) end
+commands.structureuservariable = function(name) sections.userdata (nil,name) end
+commands.structurecatcodedget = function(name) sections.structuredata(nil,name,nil,true) end
+commands.structuregivencatcodedget = function(name,catcode) sections.structuredata(nil,name,nil,catcode) end
+commands.structureautocatcodedget = function(name,catcode) sections.structuredata(nil,name,nil,catcode) end
+
+commands.namedstructurevariable = function(depth,name) sections.structuredata(depth,name) end
+commands.namedstructureuservariable = function(depth,name) sections.userdata (depth,name) end
diff --git a/Master/texmf-dist/tex/context/base/strc-doc.mkiv b/Master/texmf-dist/tex/context/base/strc-doc.mkiv
index 683d65d2f0f..4e9dec32e57 100644
--- a/Master/texmf-dist/tex/context/base/strc-doc.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-doc.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Document Structure,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -24,18 +24,15 @@
% that accepts multiple arguments. We might change this approach and
% remove this layer but it was needed for the transition.
-\def\currentstructurecounter{0}
+\installcorenamespace{structure}
-\definesystemvariable {ns}
+\installdirectcommandhandler \??structure {structure} % unchecked, so we need to initialize used parameters
-\def\structureparameter#1{\csname\??ns#1\endcsname}
+% \definesystemvariable{ns}
+% \def\structureparameter#1{\csname\??ns#1\endcsname}
+% \def\detokenizedstructureparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??ns#1\endcsname}}
-\def\detokenizedstructureparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??ns#1\endcsname}}
-
-\def\structurecomponent{\dodoubleempty\dostructurecomponent}
-
-\getparameters % initialization, used not grouped anyway
- [\??ns]
+\setupstructure % not a user command so we might need to change the name
[\c!number=,
\c!level=,
\c!name=,
@@ -53,6 +50,7 @@
\c!sectionsegments=,
\c!sectionresetset=,
\c!reference=,
+ \c!backreference=,
\c!expansion=\v!no,
\c!xmlsetup=,
\s!catcodes=,
@@ -60,12 +58,30 @@
\c!command=\showstructuredata]
% maybe flags for list, bm, mark
-%
-% hm messed up
+
+\def\structurereferenceprefixon {+}
+\def\structurereferenceprefixoff{-}
+
+\def\setstructurereferenceprefix
+ {\ifx\currentstructurereferenceprefix\empty
+ % nothing
+ \else\ifx\currentstructurereferenceprefix\structurereferenceprefixon
+ \setupglobalreferenceprefix[\currentstructurereference]%
+ \else\ifx\currentstructurereferenceprefix\structurereferenceprefixoff
+ \setupglobalreferenceprefix[]%
+ \else
+ \setupglobalreferenceprefix[\currentstructurereferenceprefix]%
+ \fi\fi\fi
+ \let\currentstructurereferenceprefix\referenceprefix}
+
+% why xdef ?
+
+\unexpanded\def\structurecomponent
+ {\dodoubleempty\dostructurecomponent}
\def\dostructurecomponent[#1][#2]% #1=interfaced-settings, #2=optional user data (not yet supported)
{\begingroup
- \getparameters[\??ns][#1]%
+ \setupstructure[#1]%
\xdef\currentstructurename {\structureparameter\c!name}%
\xdef\currentstructurecoupling {\structureparameter\c!coupling}%
\xdef\currentstructureownnumber {\structureparameter\c!ownnumber}% optional own number
@@ -115,11 +131,12 @@
\globallet\currentstructurecoding\s!tex
\fi
\setnextinternalreference
+ \setstructurereferenceprefix
\xdef\currentstructurenumber{\ctxlua{ % todo: combine with next call, adapt marks accordingly
structures.sections.somelevel {
references = {
internal = \nextinternalreference,
- block = "\currentstructureblock",
+ block = "\currentsectionblock",
reference = "\currentstructurereference",
referenceprefix = "\currentstructurereferenceprefix",
backreference = "\currentstructurebackreference",
@@ -162,7 +179,7 @@
},
numberdata = {
% needed ?
- block = "\currentstructureblock",
+ block = "\currentsectionblock",
hidenumber = \ifx\currentstructureshownumber\v!no true\else nil\fi, % titles
% so far
separatorset = "\structureparameter\c!sectionseparatorset",
@@ -174,22 +191,24 @@
segments = "\structureparameter\c!sectionsegments",
ownnumber = "\currentstructureownnumber",
},
- userdata = structures.helpers.touserdata(\!!bs\detokenize{#2}\!!es)
+ userdata = \!!bs\detokenize{#2}\!!es % will be converted to table at the lua end
}
}}%
- \xdef\currentstructurelistnumber{\ctxlua{structures.lists.push(structures.sections.current())}}%
+ \xdef\currentstructurelistnumber{\ctxcommand{addtolist(structures.sections.current())}}%
% \currentstructuresynchronize has to be called someplace, since it introduces a node
\setstructuresynchronization\currentstructurelistnumber
\structureparameter\c!command
\endgroup}
-\let\currentstructurenumber \!!zerocount
-\let\currentstructurecounter \!!zerocount
-\let\previousstructurecounter\!!zerocount
+\let\currentstructurenumber \!!zerocount
+\let\currentsectioncountervalue \!!zerocount % redefined later
+\let\previoussectioncountervalue\!!zerocount % redefined later
+
+% todo: a direct flusher (needed when hidden)
-\def\setstructuresynchronization#1%
- {\xdef\currentstructureattribute {\ctxlua {tex.write(structures.references.setinternalreference("\currentstructurereferenceprefix","\currentstructurereference",\nextinternalreference,"\interactionparameter\c!focus"))}}%
- \xdef\currentstructuresynchronize{\ctxlatelua{structures.lists.enhance(#1)}}}
+\def\setstructuresynchronization#1% todo: use ctxcontext
+ {\xdef\currentstructureattribute {\ctxlua {tex.write(structures.references.setinternalreference("\currentstructurereferenceprefix","\currentstructurereference",\nextinternalreference,"\interactionparameter\c!focus"))}}%
+ \xdef\currentstructuresynchronize{\ctxlatecommand{enhancelist(#1)}}}
\def\reportcurrentstructure{\ctxlua{structures.sections.reportstructure()}}
@@ -221,12 +240,17 @@
% \stopchapter
% \stoptext
-\def\structurevariable #1{\ctxlua{structures.sections.structuredata(nil,"#1")}}
-\def\structureuservariable #1{\ctxlua{structures.sections.userdata(nil,"#1")}}
-\def\structurenumber {\ctxlua{structures.sections.fullnumber()}}
-\def\structuretitle {\ctxlua{structures.sections.title()}}
-\def\structurecatcodedget #1{\ctxlua{structures.sections.structuredata(nil,"#1",nil,true)}} % bad name
-\def\structuregivencatcodedget#1#2{\ctxlua{structures.sections.structuredata(nil,"#1",nil,\number#2)}} % bad name
-\def\structureautocatcodedget #1#2{\ctxlua{structures.sections.structuredata(nil,"#1",nil,"#2")}}
+% todo: #1 => "#1" ... adapt lua code for name and number
+
+\def\structurenumber {\ctxcommand{structurenumber()}}
+\def\structuretitle {\ctxcommand{structuretitle()}}
+\def\structurevariable #1{\ctxcommand{structurevariable("#1")}}
+\def\structureuservariable #1{\ctxcommand{structureuservariable("#1")}}
+\def\structurecatcodedget #1{\ctxcommand{structurecatcodedget("#1")}} % bad name
+\def\structuregivencatcodedget #1#2{\ctxcommand{structuregivencatcodedget("#1",\number#2)}} % bad name
+\def\structureautocatcodedget #1#2{\ctxcommand{structureautocatcodedget ("#1","#2")}}
+
+\def\namedstructurevariable #1#2{\ctxcommand{namedstructurevariable ("#1","#2")}}
+\def\namedstructureuservariable#1#2{\ctxcommand{namedstructureuservariable("#1","#2")}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-enu.mkvi b/Master/texmf-dist/tex/context/base/strc-enu.mkvi
new file mode 100644
index 00000000000..e3261fa35cb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-enu.mkvi
@@ -0,0 +1,385 @@
+%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
+
+\let\setupenumerations\setupenumeration
+
+\setupenumerations % 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=8em,
+ \c!distance=0pt,
+\c!distance=1em,
+ \c!titledistance=0.5em,
+ %\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)
+
+\unexpanded\def\strc_define_commands_enumeration#1#2#3% current level parent
+ {\doifelsenothing{#3}
+ {\normalexpanded{\defineconstruction[#1][\s!handler=\v!enumeration,\c!level=#2]}%
+ \setevalue{\??enumeration#1:\s!parent}{\??enumeration}}%
+ {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!enumeration,\c!level=#2]}%
+ \setevalue{\??enumeration#1:\s!parent}{\??enumeration#3}}%
+ \setuevalue{\e!next #1}{\strc_enumerations_next }%
+ \setuevalue{\c!reset#1}{\strc_enumerations_reset }%
+ %setuevalue{\c!set #1}{\strc_enumerations_set }%
+ \setuevalue {#1}{\strc_enumerations_command{#1}}%
+ \setuevalue{\e!start#1}{\strc_enumerations_start {#1}}%
+ \setuevalue{\e!stop #1}{\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
+ \doifcounterelse\p_counter\donothing{\strc_enumerations_define_counter\p_counter}%
+ \letenumerationparameter\s!counter\p_counter
+ \strc_enumerations_setup_counter\currentenumeration
+\to \everydefineenumeration
+
+\setvalue{\??constructioninitializer\v!enumeration}%
+ {\let\currentenumeration \currentconstruction
+ \let\constructionparameter \enumerationparameter
+ \let\detokenizedconstructionparameter\detokenizedenumerationparameter
+ \let\letconstructionparameter \letenumerationparameter
+ \let\useconstructionstyleandcolor \useenumerationstyleandcolor
+ \let\setupcurrentconstruction \setupcurrentenumeration
+ \edef\p_number{\constructionparameter\c!number}%
+ \ifx\p_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_title{\constructionparameter\c!title}%
+ \ifx\p_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+\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
+
+\unexpanded\def\strc_enumerations_next {\strc_counters_increment_sub{\specificconstructionnumber\currentconstruction}{\currentconstructionlevel}}
+\unexpanded\def\strc_enumerations_reset {\strc_counters_reset_sub {\specificconstructionnumber\currentconstruction}{\currentconstructionlevel}}
+%unexpanded\def\strc_enumerations_set #3{\strc_counters_set_sub {\specificconstructionnumber\currentconstruction}{\currentconstructionlevel}{#2}}
+
+%D Counters (maybe we can share this code): (not ok yet, messy with notes)
+
+%%%%%%%%%%% BEGIN TODO (SEE NOTES) %%%%%%%%%%%%%%%
+
+\newtoks\everysetupenumerationcounter
+
+\let\v_strc_enumerations_counter_name\empty % or just p_counter
+
+\def\strc_enumerations_setup_counter#1%
+ {\edef\v_strc_enumerations_counter_name{#1}% only used in the token list
+ \the\everysetupenumerationcounter}
+
+\def\strc_enumerations_define_counter#1% todo: fast inheritance (was mainparameter)
+ {\definecounter[#1]%
+ \strc_enumerations_setup_counter{#1}}
+
+\appendtoks
+ \strc_counter_setup_using_parameter\v_strc_enumerations_counter_name\enumerationparameter
+\to \everysetupenumerationcounter
+
+% \def\currentconstructionnumber {\enumerationparameter\s!counter}
+% \def\specificconstructionnumber#1{\namedenumerationparameter{#1}\s!counter}
+
+\def\currentconstructionnumber {\constructionparameter\s!counter}
+\def\specificconstructionnumber#1{\namedconstructionparameter{#1}\s!counter}
+
+\appendtoks
+ \strc_enumerations_setup_counter\currentenumeration
+\to \everysetupenumeration
+
+%%%%%%%%%%% END TODO (SEE NOTES) %%%%%%%%%%%%%%%
+
+%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
+
+\setvalue{\??constructiontexthandler\v!enumeration}%
+ {\begingroup
+ \useconstructionstyleandcolor\c!headstyle\c!headcolor
+ \strc_enumerations_text
+ \endgroup}
+
+\unexpanded\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}
+
+\unexpanded\def\strc_enumerations_inject_text_with_space
+ {\edef\p_text{\constructionparameter\c!text}%
+ \ifx\p_text\empty \else
+ \p_text
+ \removeunwantedspaces
+ \nobreakspace
+ \fi}
+
+\unexpanded\def\strc_enumerations_inject_extra_text
+ {\ifconditional\c_strc_constructions_title_state
+ \ctxcommand{doiflisthastitleelse("\currentconstructionmain",\currentconstructionlistentry)}
+ \donothing
+ \strc_enumerations_inject_extra_text_indeed
+ \fi}
+
+\unexpanded\def\strc_enumerations_inject_text
+ {\constructionparameter\c!numbercommand
+ {\constructionparameter\c!text}}
+
+% head ( number title )
+
+\unexpanded\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
+ \ctxcommand{savedlisttitle("\currentconstructionmain",\currentconstructionlistentry)}%
+ \constructionparameter\c!titleright}%
+ \endgroup}
+
+\unexpanded\def\strc_enumerations_inject_symbol % todo check
+ {\constructionparameter\c!left
+ \constructionparameter\c!symbol
+ \constructionparameter\c!right}
+
+\unexpanded\def\strc_enumerations_inject_number
+ {\constructionparameter\c!left
+ \constructionparameter\c!starter
+ \ctxcommand{savedlistprefixednumber("\currentconstructionmain",\currentconstructionlistentry)}%
+ \constructionparameter\c!stopper
+ \constructionparameter\c!right}
+
+\unexpanded\def\strc_enumerations_inject_text_and_number
+ {\constructionparameter\c!numbercommand
+ {\strc_enumerations_inject_text_with_space
+ \strc_enumerations_inject_number}}
+
+\unexpanded\def\strc_enumerations_inject_text_and_symbol
+ {\constructionparameter\c!numbercommand
+ {\strc_enumerations_inject_text_with_space
+ \strc_enumerations_inject_symbol}}
+
+\unexpanded\def\strc_enumerations_full_number_yes
+ {\constructionparameter\c!headcommand
+ {\begstrut
+ \strc_enumerations_inject_text_and_number
+ \strc_enumerations_inject_extra_text
+ \endstrut}}
+
+\unexpanded\def\strc_enumerations_full_number_nop
+ {\constructionparameter\c!headcommand
+ {\begstrut
+ \strc_enumerations_inject_text
+ \strc_enumerations_inject_extra_text
+ \endstrut}}
+
+\unexpanded\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
+
+% todo
+
+ \unexpanded\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:\nextinternalorderreference)]%
+ \fi
+ \fi}
+
+ \def\skipenumerationcoupling[#1]% e.g. for questions with no answer
+ {\ctxlua{structures.references.setnextorder("construction","#1")}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-flt.mkii b/Master/texmf-dist/tex/context/base/strc-flt.mkii
index 3d07cdc2064..26125c65f96 100644
--- a/Master/texmf-dist/tex/context/base/strc-flt.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-flt.mkii
@@ -5,7 +5,7 @@
%D subtitle=Floating Bodies,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -519,9 +519,7 @@
\setvalue {\e!start#1\e!text}{\dotripleempty\docomplexstarttextblock[#1]}%
\setvalue {\e!stop#1\e!text}{\dostoptextfloat}%
\setvalue{\e!start\e!reserve#1\e!text}{\doquadrupleempty\docomplexstartreservetextblock[#1]}%
- \setvalue {\e!stop\e!reserve#1\e!text}{\dostoptextfloat}%
- \setvalue {\e!emptyone#1}{\doemptyblock{#1}}%
- \setvalue {\e!emptytwo#1}{\doemptyblock{#1}}}
+ \setvalue {\e!stop\e!reserve#1\e!text}{\dostoptextfloat}}
% \setupfloat[...][leftmargindistance=1cm,default={left,none}]
@@ -1436,18 +1434,6 @@
\fi
\fi}
-\def\dopreparesidecaption#1#2#3%
- {\scratchdimen\dimexpr\hsize-\wd\tempfloatbox-\@@bkmargin\relax % was \tfskipsize\relax
- \ifdim\wd\tempcaptionbox>\scratchdimen
- \ifdim\wd\tempcaptionbox<1.3\scratchdimen
- \scratchdimen0.8\scratchdimen
- \fi
- \fi
- \dosettempcaptionbox % \setbox\tempcaptionbox\vbox
- {\hsize\scratchdimen
- \doifnothing{\floatcaptionparameter\c!align}\raggedright % on purpose overloads align !
- \putcompletecaption{#2}{#3}}}
-
\newdimen\tempfloatheight
\newdimen\tempfloatwidth
diff --git a/Master/texmf-dist/tex/context/base/strc-flt.mkiv b/Master/texmf-dist/tex/context/base/strc-flt.mkiv
deleted file mode 100644
index 32024a27695..00000000000
--- a/Master/texmf-dist/tex/context/base/strc-flt.mkiv
+++ /dev/null
@@ -1,2054 +0,0 @@
-%D \module
-%D [ file=strc-flt,
-%D version=2008.10.20,
-%D title=\CONTEXT\ Structure Macros,
-%D subtitle=Float Numbering,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
-%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 / Float Numbering}
-
-\registerctxluafile{strc-flt}{1.001}
-
-\unprotect
-
-%D This module needs a cleanup and will be split in
-%D strc-flt.tex and page-flt.mkiv cq. page-flt.mkii.
-
-\ifdefined\addlocalbackgroundtobox\else \def\addlocalbackgroundtobox{\resetglobal\gobbleoneargument} \fi
-
-\unexpanded\def\placefloats{\doflushfloats} % keep this one
-
-\let\currentfloat\empty
-
-\def\letfloatparameter #1{\expandafter\let\csname\??fl\currentfloat#1\endcsname}
-
-\def\floatparameter #1{\csname\dofloatparameter{\??fl\currentfloat}#1\endcsname}
-\def\floatsharedparameter#1{\csname \??fl #1\endcsname}
-\def\floatparameterhash #1{\dofloatparameterhash {\??fl\currentfloat}#1}
-
-\def\dofloatparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dofloatparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\dofloatparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\dofloatparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\dofloatparentparameter #1#2{\ifx#1\relax\s!empty\else\dofloatparameter #1#2\fi}
-\def\dofloatparentparameterhash#1#2{\ifx#1\relax \else\dofloatparameterhash#1#2\fi}
-
-\def\detokenizedfloatparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??fl\currentfloat#1\endcsname}}
-
-\def\dosetfloatattributes#1#2% style color
- {\edef\fontattributehash {\floatparameterhash#1}%
- \edef\colorattributehash{\floatparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-\def\floatcaptionparameter #1{\csname\dofloatcaptionparameter{\??kj\currentfloat}#1\endcsname}
-\def\floatcaptionparameterhash#1{\dofloatcaptionparameterhash {\??kj\currentfloat}#1}
-
-\def\dofloatcaptionparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dofloatcaptionparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\dofloatcaptionparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\dofloatcaptionparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\dofloatcaptionparentparameter #1#2{\ifx#1\relax\s!empty\else\dofloatcaptionparameter #1#2\fi}
-\def\dofloatcaptionparentparameterhash#1#2{\ifx#1\relax \else\dofloatcaptionparameterhash#1#2\fi}
-
-\def\detokenizedcaptionparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??kj\currentfloat#1\endcsname}}
-
-\def\dosetfloatcaptionattributes#1#2% style color
- {\edef\fontattributehash {\floatcaptionparameterhash#1}%
- \edef\colorattributehash{\floatcaptionparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-\def\dohandlenextfloatindent
- {\checknextindentation[\floatparameter\c!indentnext]%
- \dorechecknextindentation}
-
-%D The two shared (parent) definitions:
-
-% todo: everysetupfloat everysetupcaption for all floats
-
-\unexpanded\def\setupfloats {\dosingleargument\dosetupfloats} % was \??bk
-\unexpanded\def\setupcaptions{\dosingleargument\dosetupcaptions}
-
-\let\alldefinedfloats\empty
-
-\def\doprocessallfloats#1%
- {\def\doprocesssomefloat##1{\def\currentfloat{##1}#1}%
- \processcommacommand[\alldefinedfloats]\doprocesssomefloat}
-
-\def\dosetupfloats [#1]{\getparameters[\??fl][#1]\doprocessallfloats{\the\everysetupfloat}}
-\def\dosetupcaptions[#1]{\getparameters[\??kj][#1]\doprocessallfloats{\the\everysetupcaption}}
-
-% \def\dosetupfloats [#1]{\getparameters[\??fl][#1]}
-% \def\dosetupcaptions[#1]{\getparameters[\??kj][#1]}
-
-\setupcaptions
- [\c!location=\v!bottom,
- \c!grid=,
- \c!before=, % not used (yet)
- \c!inbetween={\blank[\v!medium]},
- \c!after=, % not used (yet)
- \c!spacebefore=,
- \c!spaceinbetween=, % replaces fuzzy inbetween dual usage
- \c!spaceafter=,
- \c!width=\v!fit,
- \c!minwidth=\v!fit, % id est: the width of the floatbox in some cases
- \c!headstyle=\v!bold,
- \c!headcolor=,
- \c!leftmargin=\zeropoint,
- \c!rightmargin=\zeropoint,
- \c!outermargin=\zeropoint,
- \c!innermargin=\zeropoint,
- \c!setups=,
- \c!style=\v!normal,
- \c!color=,
- \c!textstyle=,
- \c!textcolor=,
- \c!align=,
- \c!number=\v!yes,
- % \c!prefix=\v!no,
- % \c!prefixconnector=.,
- % \c!way=\v!by\v!chapter,
- % \c!prefixsegments=2:2,
- % \c!way=\@@nrway,
- % \c!blockway=\@@nrblockway,
- % \c!sectionnumber=\@@nrsectionnumber,
- % \c!separator=\@@koseparator,
- % \c!starter=\@@kostarter,
- % \c!stopper=\@@kostopper,
- \c!suffixseparator=, % currently rather hard coded
- \c!suffix=\floatcaptionsuffix,
- \c!distance=1em,
- \c!conversion=\v!numbers,
- \c!command=]
-
-% we can comment some of these
-
-\setupfloats
- [\c!location=\v!middle,
- \c!width=8\lineheight,
- \c!height=6\lineheight,
- \c!offset=\v!overlay,
- \c!frame=\v!off,
- \c!strut=\v!no,
- \c!radius=.5\bodyfontsize,
- \c!corner=\v!rectangular,
- \c!background=,
- \c!backgroundcolor=,
- \c!backgroundoffset=\!!zeropoint,
- \c!topframe=,
- \c!bottomframe=,
- \c!leftframe=,
- \c!rightframe=,
- \c!frameoffset=\!!zeropoint,
- \c!before=,
- \c!after=,
- \c!spacebefore=\v!big,
- \c!spaceafter=\v!big,
- \c!sidespacebefore=\floatsharedparameter\c!spacebefore,
- \c!sidespaceafter=\floatsharedparameter\c!spaceafter,
- \c!sidealign=\v!normal,
- \c!textmethod=\ifgridsnapping2\else0\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt)
- \c!sidemethod=\ifgridsnapping2\else1\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt)
- \c!indentnext=\v!no,
- \c!margin=1em,
- \c!method=1,
- \c!cache=\v!yes, % when no, then intermediate flush
- \c!leftmargin=\zeropoint, % displacement in 'normal floats'
- \c!rightmargin=\zeropoint, % idem
- \c!innermargin=\zeropoint, % idem
- \c!outermargin=\zeropoint, % idem
- \c!leftmargindistance=\zeropoint,
- \c!rightmargindistance=\floatparameter\c!leftmargindistance,
- \c!ntop=2,
- \c!nbottom=0,
- \c!nlines=4,
- \c!local=,
- \c!bottombefore=, % e.g. \vfill
- \c!bottomafter=,
- \c!default=, % default location
- \c!numbering=\v!yes]
-
-\def\@@bknumbering {\floatsharedparameter\c!numbering } % global one
-\def\@@bkspaceafter {\floatsharedparameter\c!spaceafter } % global one
-\def\@@bkspacebefore{\floatsharedparameter\c!spacebefore} % global one
-\def\@@bknbottom {\floatsharedparameter\c!nbottom } % global one
-\def\@@bkntop {\floatsharedparameter\c!ntop } % global one
-\def\@@bknlines {\floatsharedparameter\c!nlines } % global one
-\def\@@bkmargin {\floatsharedparameter\c!margin } % global one
-\def\@@bkcache {\floatsharedparameter\c!cache } % global one
-\def\@@bklocation {\floatsharedparameter\c!location }
-
-% float
-%
-% [%\c!width=8\lineheight, % 15\bodyfontsize,
-% %\c!height=6\lineheight, % 10\bodyfontsize,
-% \c!offset=\v!overlay,
-% \c!width=\v!fit,
-% \c!height=\v!fit,
-% \c!minwidth=,
-% \c!maxwidth=,
-% \c!maxheight=,
-% \c!criterium=,
-% % inherited
-% \c!pageboundaries=,
-% \c!default=]%
-
-% number
-%
-% [\c!text=#1,
-% \c!location=\v!intext,
-% \c!way=\floatcaptionparameter\c!way,
-% \c!blockway=\floatcaptionparameter\c!blockway,
-% \c!sectionnumber=\floatcaptionparameter\c!sectionnumber,
-% \c!conversion=\floatcaptionparameter\c!conversion]%
-
-%D Individial settings:
-
-\unexpanded\def\setupfloat {\dodoubleargument\dosetupfloat}
-\unexpanded\def\setupcaption{\dodoubleargument\dosetupcaption}
-
-\newtoks\everysetupfloat
-\newtoks\everysetupcaption
-
-\def\dosetupfloat[#1][#2]%
- {\def\docommand##1{\getparameters[\??fl##1][#2]\def\currentfloat{##1}\the\everysetupfloat}%
- \processcommalist[#1]\docommand}
-
-\def\dosetupcaption[#1][#2]%
- {\def\docommand##1{\getparameters[\??kj##1][#2]\def\currentfloat{##1}\the\everysetupcaption}%
- \processcommalist[#1]\docommand}
-
-\presetstructurecountersetup\setupcaptions\sharedstructurecounterparameter
-
-\appendtoks
- \dostructurecountersetup\currentfloat\floatcaptionparameter
- \docheckstructurecountersetup\currentfloat
-\to \everysetupcaption
-
-%D Definitions:
-
-\unexpanded\def\definefloat
- {\dotripleempty\dodefinefloat}
-
-\def\dodefinefloat[#1][#2][#3]% #1=naam #2=meervoud #3=parent
- {\ifthirdargument
- \redodefinefloat[#1][#2][#3]%
- \else\ifsecondargument
- \dododefinefloat[#1][#2]%
- \else
- \dododefinefloat[#1][#1]%
- \fi\fi}
-
-\presetlocalframed[\??fl]
-
-\def\dododefinefloat[#1][#2]%
- {\copylocalframed[\??fl#1][\??fl]%
- \definestructurecounter[#1]%
- \addtocommalist{#1}\alldefinedfloats
- \setupfloat[#1][\s!parent=\??fl]%
- \setupcaption[#1][\s!parent=\??kj]%
- \definelist[#1]%
- \presetlabeltext[#1=\Word{#1}~]%
- \presetheadtext[#2=\Word{#2}]%
- \dodefinefloatcommands[#1][#2]%
- }% \newnodelocation{\v!float\@@thenumber{#1}}}
-
-\def\redodefinefloat[#1][#2][#3]%
- {\copylocalframed[\??fl#1][\??fl#3]%
- \setupfloat[#1][\s!parent=\??fl#3]%
- \setupcaption[#1][\s!parent=\??kj#3]%
- \definestructurecounter[#1][#3]%
- \definelist[#1][#3]%
- \presetlabeltext[#1=\Word{#3}~]%
- \presetheadtext[#2=\Word{#2}]%
- \dodefinefloatcommands[#1][#2]}
-
-\def\dodefinefloatcommands[#1][#2]%
- {\setuvalue {\e!place\e!listof#2}{\dodoubleempty\doplacelist[#1]}%
- \setuvalue {\e!complete\e!listof#2}{\dotripleempty\dodocompletelist[#1][#2]}%
- \setuvalue {\e!place#1}{\dotripleempty\docomplexplacefloat[#1]}%
- \setuvalue {\e!reserve#1}{\doquadrupleempty\docomplexreserveblock[#1]}%
- \setuvalue {\e!start#1\e!text}{\dotripleempty\docomplexstarttextblock[#1]}%
- \setuvalue {\e!stop#1\e!text}{\dostoptextfloat}%
- \setuvalue{\e!start\e!reserve#1\e!text}{\doquadrupleempty\docomplexstartreservetextblock[#1]}%
- \setuvalue {\e!stop\e!reserve#1\e!text}{\dostoptextfloat}%
- \setuvalue {\e!emptyone#1}{\doemptyfloatblock{#1}}%
- \setuvalue {\e!emptytwo#1}{\doemptyfloatblock{#1}}}
-
-%D Fallback float body:
-
-\def\doemptyfloatblock#1%
- {\framed
- [\c!frame=\v!on,
- \c!width=\floatsharedparameter\c!width,
- \c!height=\floatsharedparameter\c!height,
- \c!location=\v!normal,
- \c!offset=\floatsharedparameter\c!offset]%
- {\getmessage\m!floatblocks{12}\empty}}
-
-%D Data. We can generalize this to lists.
-
-\newif\ifnofloatcaption
-\newif\ifnofloatnumber
-\newif\ifemptyfloatcaption
-
-\def\getfloatparameters {\getparameters[\??fl\currentfloat]}
-\def\getcaptionparameters{\getparameters[\??kj\currentfloat]}
-
-\installstructurelistprocessor{float}{\usestructurelistprocessor{number+title}}
-
-% \def\thecurrentfloatnumber
-% {\ifnofloatcaption \else \ifnofloatnumber \else
-% \ifx\currentfloatnumber\relax\else
-% \dostarttagged\t!floattag\empty
-% \labeltexts\currentfloat{\ctxlua{structures.lists.savedprefixednumber("\currentfloat",\currentfloatnumber)}}%
-% \dostoptagged
-% \fi
-% \fi \fi}
-
-\unexpanded\def\thecurrentfloatnumbersuffix
- {\doifsomething{\floatcaptionparameter\c!suffix}
- {\floatcaptionparameter\c!suffixseparator
- \floatcaptionparameter\c!suffix}}
-
-\def\thecurrentfloatnumber
- {\ifnofloatcaption \else \ifnofloatnumber \else
- \ifx\currentfloatnumber\relax\else
- \dostarttagged\t!floattag\empty
- \labeltexts\currentfloat
- {\ctxlua{structures.lists.savedprefixednumber("\currentfloat",\currentfloatnumber)}%
- \thecurrentfloatnumbersuffix}%
- \dostoptagged
- \fi
- \fi \fi}
-
-\def\thecurrentfloatcaption
- {\ifnofloatcaption \else
- \ifx\currentfloatnumber\relax\else
- \dostarttagged\t!floattext\empty
- \ctxlua{structures.lists.savedtitle("\currentfloat",\currentfloatnumber)}%
- \dostoptagged
- \fi
- \fi}
-
-%D Captions.
-
-\let\floatcaptionsuffix\empty % an optional suffix
-\let\floatcaptionnumber\empty % a logical counter
-
-% the split is needed when for instance the float goes into
-% a multi page field and the list of figs becomes larger than
-% one page: cycle between 'only flush when object ref ok'
-% and 'one/many page fig list'; see "uguide finometer"
-%
-% potential sync bug with sectionblocks, see uguide.tex
-
-% NOT YET REDONE ! ! ! ! !
-
- \unexpanded\def\placefloatcaption
- {\dodoubleempty\doplacefloatcaption}
-
- \long\def\doplacefloatcaption[#1][#2]#3%
- {\setfloatcaption[#1][#2]{#3}%
- \placefloatcaptiontext[#1]%
- \placefloatcaptionreference[#1]}
-
- \unexpanded\def\setfloatcaption % \dosetfloatcaption already in use
- {\dodoubleempty\dodosetfloatcaption} % beware, name clash
-
- \long\def\dodosetfloatcaption[#1][#2]#3% to do namespace for number/ascii
- {\ifnofloatnumber % also handle trialtypesetting
- \letgvalue{@fl@r@#1}\relax
- \letgvalue{@fl@t@#1}\relax
- \else
- \preparefloatnumber{#1}%
- \letgvalue{@fl@n@#1}\composedsectionnumber
- % indirect macro can be more efficient
- \setgvalue{@fl@r@#1}%
- {\tracefloatnumber{#1}%
- \ifconditional\retainfloatnumber\else
- % todo
- \fi
- \letgvalue{@fl@r@#1}\relax}% nils
- \setgvalue{@fl@t@#1}%
- {\preparefullnumber{\??kj#1}{\getvalue{@fl@n@#1}}\preparednumber
- \begingroup
- \dosetfloatcaptionattributes\c!style\c!color
- \begingroup
- \dosetfloatcaptionattributes\c!headstyle\c!headcolor
- \labeltexts{#1}{\preparednumber}%
- \endgroup
- \begingroup
- \dosetfloatcaptionattributes\c!textstyle\c!textcolor
- \dotfskip{\floatcaptionparameter\c!distance}#3%
- \endgroup
- \endgroup}%
- \fi}
-
- \long\def\dodosetfloatcaption[#1][#2]#3% to do namespace for number/ascii
- {\letgvalue{@fl@r@#1}\relax
- \letgvalue{@fl@t@#1}\relax}
-
- \unexpanded\def\placefloatcaptiontext [#1]{\getvalue{@fl@t@#1}}
- \unexpanded\def\placefloatcaptionnumber [#1]{\getvalue{@fl@n@#1}}
- \unexpanded\def\placefloatcaptionreference[#1]{\getvalue{@fl@r@#1}}
-
- % still needed for uguide
-
- \let\placefloatlabel \placefloatcaption
- \let\placefloatlabeltext \placefloatcaptiontext
- \let\placefloatlabelreference \placefloatcaptionreference
-
-% TILL HERE
-
-\newbox\captionbox
-
-\long\def\putcompletecaption#1#2%
- {\doifsomething{\floatcaptionparameter\c!spacebefore}{\blank[\floatcaptionparameter\c!spacebefore]}%
- %\floatcaptionparameter\c!before % test for side effects first
- \noindent
- \gdef\lastcaptiontag{\strut#1}% was xdef
- \begingroup
- \dosetfloatcaptionattributes\c!style\c!color
- \ifnofloatnumber
- \else
- \hbox{\dosetfloatcaptionattributes\c!headstyle\c!headcolor\strut#1}%
- \ifnofloatcaption \else \ifemptyfloatcaption \else
- \doifelsenothing{\floatcaptionparameter\c!spaceinbetween}
- {\scratchskip\floatcaptionparameter\c!distance\relax
- \dotfskip\scratchskip\emergencystretch.5\scratchskip}
- {\blank[\floatcaptionparameter\c!spaceinbetween]}%
- \fi \fi
- \fi
- \ifnofloatcaption
- \globallet\lastcaptionht\!!zeropoint
- \globallet\lastcaptiondp\!!zeropoint
- \else
- \dosetfloatcaptionattributes\c!textstyle\c!textcolor
- \xdef\lastcaptionht{\strutheight}%
- \xdef\lastcaptiondp{\strutdepth}%
- \begstrut#2\endstrut\endgraf
- \fi
- \endgroup
- %\floatcaptionparameter\c!after % test for side effects first
- \doifsomething{\floatcaptionparameter\c!spaceafter}{\blank[\floatcaptionparameter\c!spaceafter]}}
-
-\let\lastcaptionht\!!zeropoint
-\let\lastcaptiondp\!!zeropoint
-
-\newbox\tempcaptionbox
-
-\newif\iftracecaptions
-
-\def\settracedcaptionbox
- {\iftracecaptions\setbox\tempcaptionbox\ruledhbox{\box\tempcaptionbox}\fi}
-
-% \definefloat [figure-1] [figure]
-% \definefloat [figure-2] [figure]
-% \setupfloat [figure-1] [location=left,leftmargin=10mm]
-% \setupfloat [figure-2] [location=left,leftmargin=-5mm]
-% \setupcaption [figure-1] [align=flushleft]
-% \setupcaption [figure-2] [align=flushleft,leftmargin=15mm]
-%
-% \startsetups somefigure
-% \ifdim\wd\nextbox>\textwidth
-% \placefloat[figure-2][][]{}{\box\nextbox}
-% \else
-% \placefloat[figure-1][][]{}{\box\nextbox}
-% \fi
-% \stopsetups
-%
-% \unexpanded\def\setupswithbox[#1]{\dowithnextbox{\setups[#1]}\vbox}
-%
-% test \setupswithbox[somefigure]{\framed[width=3cm] {}} test
-% test \setupswithbox[somefigure]{\framed[width=\dimexpr\textwidth+3cm\relax]{}} test
-
-\def\dosetcaptionthings
- {\doprocesslocalsetups{\floatcaptionparameter\c!setups}% expanded ?
- %\advance\leftskip \floatcaptionparameter\c!leftmargin
- %\advance\rightskip\floatcaptionparameter\c!rightmargin
- \relax}
-
-\def\dofakecaptionthings
- {\hbox{\dosetcaptionthings\hskip\leftskip\hskip\rightskip}}
-
-\long\def\docheckcaptioncontent#1#2%
- {\ifnofloatcaption \else
- \setbox\tempcaptionbox\hbox
- {\settrialtypesetting
- \notesenabledfalse
- \putcompletecaption{#1}{#2}}%
- % new, \placefigure{\xmlfirst{#1}{somecaption}}{} passes earlier empty check
- % so here we misuse the scratch box; actually this means that the previous
- % test can go away (some day, when i redo this module)
- \ifdim\wd\tempcaptionbox=\zeropoint
- \global\emptyfloatcaptiontrue
- \ifnofloatnumber
- \global\nofloatcaptiontrue
- \fi
- \else
- \setbox\tempcaptionbox\hbox{\dosetcaptionthings\hskip\leftskip\box\tempcaptionbox}% yet incomplete
- \fi
- \fi}
-
-% the tricky part of getting float related two pass data is
-% that we should fetch is early but can only save it with
-% the composed float box; this determines the order: get it
-% before saving it
-
-\definetwopasslist{\s!float\s!data} \newcounter\noffloatdata
-
-\let\twopassfloatdata\realpageno % used for odd/even determination, can be combined with nodelocation
-
-\def\dosavefloatdata % \expanded ... will change in mkiv
- {\doglobal\increment\noffloatdata
- \lazysavetaggedtwopassdata{\s!float\s!data}{\noffloatdata}{\noffloatpages}{\noexpand\realfolio}}% later {}{}{}{} and \getfirst...
-
-\def\dogetfloatdata % precedes save !
- {\doglobal\increment\noffloatpages
- \findtwopassdata{\s!float\s!data}{\noffloatpages}%
- \iftwopassdatafound
- \globallet\twopassfloatdata\twopassdata
- \else
- \globallet\twopassfloatdata\realpageno % \realfolio
- \fi}
-
-\def\tracefloatnumber#1%
- {\doifnot{\floatsharedparameter\c!numbering}\v!nocheck{\tagnodelocation{\v!float\@@thenumber{#1}}}}
-
-\newconditional\retainfloatnumber
-
-\def\preparefloatnumber#1% use in special case see below
- {\xdef\floatcaptionnumber{#1}%
- \doifelsenodelocation{\v!float\@@thenumber{#1}}
- \donothing {\nodelocationmode\zerocount}%
- \doifelse{\floatsharedparameter\c!numbering}\v!nocheck
- {\incrementnumber[#1]%
- \makesectionnumber[#1]%
- \ifconditional\retainfloatnumber\decrementnumber[#1]\fi}
- {\ifinsidecolumns
- \nodelocationmode\zerocount
- % to be perfected:
- % \nodelocationmode\plustwo
- \fi
-% FOR THE MOMENT NOT AVAILABLE
-\nodelocationmode\zerocount
-% BUT NOT THAT HARD TO DO
- \ifcase\nodelocationmode
- \incrementnumber[#1]%
- \makesectionnumber[#1]%
- \ifconditional\retainfloatnumber\decrementnumber[#1]\fi
- \else
- % force check, so that we get a proper way-sync and
- % can use the accumulated number
- % \checknumber[#1]% \incrementnumber does this
- \incrementnumber[#1]%
- \savenumber[#1]%
- % the real work is done here
- \nextnodelocation{\v!float\@@thenumber{#1}}% better \nextfloatnumber
- \analyzenodelocation{\v!float\@@thenumber{#1}}%
- \scratchcounter\getnodelocationo{\v!float\@@thenumber{#1}}%
- \advance\scratchcounter\minusone
- % here we correct for 'per whatever handling'
- \advance\scratchcounter-\accumulatednumber[#1]%
- \setnumber[#1]\scratchcounter
- \incrementnumber[#1]%
- \makesectionnumber[#1]%
- \restorenumber[#1]%
- % now we're back to normal numbering
- \fi}}
-
-%D test case:
-%D
-%D \starttyping
-%D \setupfloat[figure][criterium=\marginwidth,fallback=bottom]
-%D \dorecurse{3}{
-%D \chapter{test}
-%D \placefigure[bottom]{1}{\framed{bottom}}
-%D test
-%D \placetable[bottom]{1}{\framed{table}}
-%D test
-%D \placetable{2}{\framed{table}}
-%D test
-%D \placefigure[left]{2}{\framed{left but way too wide}}
-%D \input tufte
-%D \placefigure[left]{3}{\framed{left but ok}}
-%D \input tufte }
-%D \stoptyping
-
-% A complication is that we may have to handle a pagebreak
-% first, which in turn may issue a (postponed) float.
-% Therefore we may not trust on variable assignments before
-% we're realy dealing with the float. Some day I'll root out
-% the global settings.
-
-\def\docomplexplacefloat[#1][#2]% [#3]#4%
- {\edef\currentfloat{#1}%
- \doifnothing\currentfloat{\let\currentfloat\v!figure}%
- \doifelsenothing{#2}
- {\edef\floatlocation{\floatparameter\c!default}}
- {\edef\floatlocation{#2}}%
- \doifinsetelse\v!split{#2}
- {\normalexpanded{\noexpand\dodocomplexsplitfloat[\currentfloat][\floatlocation]}}
- {\normalexpanded{\noexpand\dodocomplexplacefloat[\currentfloat][\floatlocation]}}}
-
-\long\def\dodocomplexsplitfloat[#1][#2][#3]#4%
- {\splitfloat{\dodocomplexplacefloat[#1][#2][#3]{#4}}}
-
-\def\flushfloatslist
- {\v!left,\v!right,\v!inner,\v!outer,%
- \v!backspace,\v!cutspace,%
- \v!inleft,\v!inright,\v!inmargin,%
- \v!leftmargin,\v!rightmargin,\v!leftedge,\v!rightedge,%
- \v!innermargin,\v!outermargin,\v!inneredge,\v!outeredge,%
- \v!text,\v!opposite}% \v!page
-
-\long\def\dodocomplexplacefloat[#1][#2][#3]#4%
- {\flushnotes
- \flushsidefloats % here !
- \ifsomefloatwaiting
- % this was \checkwaitingfloats spread all over
- \doifinsetelse\v!always{#2}
- {\showmessage\m!floatblocks5\empty}
- {\normalexpanded{\noexpand\doifcommonelse{#2}{\flushfloatslist}}\doflushfloats\donothing}%
- % but which should be done before using box \floatbox
- \fi
- \ifmarginblocks
- \doifinset\v!margin{#2}\endgraf
- \fi
- \global\insidefloattrue
- \begingroup % **
- \dostarttagged\t!float\currentfloat
- \ifmarginblocks
- \doifinset\v!margin{#2}{\hsize\@@mbwidth}%
- \fi
- \the\everyinsidefloat
- \let\@@extrafloat\empty
- \presetmorefloatvariables{#2}%
- \dowithnextboxcontent % better a \the\everyfloattoks
- {\setlocalfloathsize
- \floatparameter\c!inner
- \dostarttagged\t!floatcontent\empty
- \aftergroup\dostoptagged % tricky, never change \dowithnextboxcontent
- \postponenotes} % new
- {\doifsomething{\floatparameter\c!criterium}
- {\ifdim\wd\nextbox>\floatparameter\c!criterium\relax
- \edef\forcedfloatmethod{\floatparameter\c!fallback}%
- \ifx\forcedfloatmethod\empty\let\forcedfloatmethod\v!here\fi
- \fi}%
- \xdocompletefloat{#1}{#3}{#2}{#4}% ** not yet done
- % we need to carry over the par because of side floats
- \doifnotinset\v!text{#2}{\dostoptagged\carryoverpar\endgroup}% **
- \global\sidefloatdownshift \zeropoint
- \global\sidefloatextrashift\zeropoint
- \ifparfloat
- \doifinset\v!reset{#2}\forgetsidefloats
- \doinhibitblank
- \fi}% better move this to side floats
- \vbox}
-
-\def\xxdocompletefloat#1#2%
- {\rightorleftpageaction{\let\@@extrafloat#1}{\let\@@extrafloat#2}}
-
-\setnewconstant\sidefloatalign \zerocount
-\setnewconstant\textfloatmethod\zerocount % 0=raw 1=safe (.99) 2=tight (-1pt)
-\setnewconstant\sidefloatmethod\plusone % 0=raw 1=safe (.99) 2=tight (-1pt)
-
-\let\floatrotation\!!zerocount
-
-\long\def\presetfloatvariables#1#2#3#4%
- {\doifcommonelse
- {#2}
- {\v!left,\v!right,\v!inner,\v!outer,%
- \v!inleft,\v!inright,\v!inmargin,%
- \v!backspace,\v!cutspace,%
- \v!innermargin,\v!outermargin,\v!inneredge,\v!outeredge,%
- \v!leftmargin,\v!leftedge,\v!rightmargin,\v!rightedge}
- {\global\parfloattrue}
- {\global\parfloatfalse}%
- \ifinsidecolumns
- \global\parfloatfalse
- \fi
- \global\sidefloatshift\zeropoint
- \global\sidefloatmaximum\zeropoint
- \global\sidefloatmethod\floatparameter\c!sidemethod
- \global\textfloatmethod\floatparameter\c!textmethod
- \global\sidefloatalign\zerocount
- \globallet\floatrotation\!!zerocount
- \calculatefloatskips
- \ifparfloat
- \processaction
- [\floatparameter\c!sidealign]
- [\v!height=>\global\sidefloatalign\plusone,%
- \v!line=>\global\sidefloatalign\plustwo,% (***)
- \v!depth=>\global\sidefloatalign\plusthree,%
- \v!grid=>\global\sidefloatalign\plusfour,%
- \v!halfline=>\global\sidefloatalign\plusfive]%
- % todo (test first): \doifinset\v!lokaal{#2}{\global\sidefloatalign\zerocount}%
- \ifcase\sidefloatalign\relax % todo: optie v!lokaal => \else
- \doifinset\v!height {#2}{\global\sidefloatalign\plusone}%
- \doifinset\v!line {#2}{\global\sidefloatalign\plustwo}%
- \doifinset\v!depth {#2}{\global\sidefloatalign\plusthree}%
- \doifinset\v!grid {#2}{\global\sidefloatalign\plusfour}%
- \doifinset\v!halfline{#2}{\global\sidefloatalign\plusfive}% meant for 'none'
- \fi
- \doifinset\v!high{#2}{\global\sidefloattopskip \zeropoint}%
- \doifinset\v!low {#2}{\global\sidefloatbottomskip\zeropoint}%
- \doifinset\v!fit {#2}
- {\global\sidefloattopskip \zeropoint
- \global\sidefloatbottomskip\zeropoint
- \global\floatsideskip \zeropoint}%
- \else
- \processallactionsinset
- [#2]
- [ 90=>\globallet\floatrotation\commalistelement,%
- 180=>\globallet\floatrotation\commalistelement,%
- 270=>\globallet\floatrotation\commalistelement]%
- \fi
- \doifinsetelse\v!nonumber{#2}
- {\global\nofloatnumbertrue}
- {\doifelse{\floatcaptionparameter\c!number}\v!yes
- {\global\nofloatnumberfalse}
- {\global\nofloatnumbertrue}}%
- % this has to change
- \ConvertToConstant\doifelse{#4}{}
-% \ConvertToConstant\doifelse{\detokenize{#4}}{}
- {\global\emptyfloatcaptiontrue}
- {\global\emptyfloatcaptionfalse}%
-% \doifinsetelse\v!none{#2}
-% {\global\nofloatcaptiontrue}
-% {\ConvertToConstant\doifelse{#4}\v!none
-% {\global\nofloatcaptiontrue}
-% {\global\nofloatcaptionfalse}}%
- \doifinsetelse\v!none{#2}
- {\global\nofloatcaptiontrue}
- {\global\nofloatcaptionfalse}%
- \doif{\floatcaptionparameter\c!number}\v!none % new
- {\global\nofloatcaptiontrue}%
- \ifemptyfloatcaption \ifnofloatnumber
- \global\nofloatcaptiontrue
- \fi \fi}
-
-% documenteren in details
-
-\def\presetmorefloatvariables#1%
- {\doifelse{\floatparameter\c!local}\v!yes % fout keyword
- \globalcenterfloatboxtrue
- \globalcenterfloatboxfalse
- \ifglobalcenterfloatbox
- \localcenterfloatboxtrue
- \else
- \doifinsetelse\v!local{#1}
- \localcenterfloatboxtrue
- \localcenterfloatboxfalse
- \fi
- \doifnotcommon{\v!always,\v!here,\v!force}{#1} % ! ! ! ! ! !
- {\globalcenterfloatboxfalse
- \localcenterfloatboxfalse}}
-
-\let\naturalfloatheight\!!zeropoint
-\let\naturalfloatwidth \!!zeropoint
-\let\naturalfloatdepth \!!zeropoint
-
-\def\setnaturalfloatdimensions#1%
- {\xdef\naturalfloatheight{\the\ht#1}%
- \xdef\naturalfloatwidth {\the\wd#1}%
- \xdef\naturalfloatdepth {\the\dp#1}}
-
-\long\def\doifelsemainfloatbody#1#2%
- {\ifinsidesplitfloat\ifconditional\splitfloatfirstdone#2\else#1\fi\else#1\fi}
-
-% todo: optional user pars
-
-\let\currentfloatattribute\empty % to be checked
-
-\def\floatcaptionattribute
- {\iflocation \ifnofloatnumber \else \ifnofloatcaption \else \ifinsidesplitfloat \else
- attr \destinationattribute \currentfloatattribute
- \fi \fi \fi \fi}
-
-\newconditional\usesamefloatnumber
-
-\long\def\docompletefloat#1#2#3#4#5% #1:floatclass #2:reference #3:optionlist #4:caption #5:box number
- {\presetfloatvariables{#1}{#3}{#2}{#5}% check this one
- \bgroup
- % prepare structure data
- %
- % \dofloatcomponent[\c!name=#1,\c!reference=#2,\c!bookmark=,\c!title={#4}][]% ifnofloatnumber ifnofloatcaption \tracefloatnumber{#1}%
- %
- \ifconditional\usesamefloatnumber
- \globallet\currentfloatnumber \previousfloatnumber
- \globallet\currentfloatattribute \empty
- \globallet\currentfloatsynchronize\relax
- \else
- \dostructurecountercomponent
- {float}%
- \getcaptionparameters
- \floatcaptionparameter
- \detokenizedcaptionparameter
- \relax
- \relax
- \relax
- [\c!name=\currentfloat,\s!counter=\@@thestructurecounter\currentfloat,%
- \s!hascaption=\ifnofloatcaption \v!no\else\v!yes\fi,%
- \s!hasnumber=\ifnofloatnumber \v!no\else\v!yes\fi,%
- \s!hastitle=\ifemptyfloatcaption\v!no\else\v!yes\fi,%
- \c!reference=#2,\c!title={#4},\c!bookmark=]%
- []%
- \globallet\previousfloatnumber \laststructurecounternumber
- \globallet\currentfloatnumber \laststructurecounternumber
- \globallet\currentfloatattribute \laststructurecounterattribute
- \globallet\currentfloatsynchronize\laststructurecountersynchronize
- \fi
- %
- \global\setfalse\usesamefloatnumber % one shot
- % check float box
- \setnaturalfloatdimensions#5%
- \global\setbox\floatbox\vbox{\floatparameter\c!command{\box#5}}%
- \setnaturalfloatdimensions\floatbox
- \ifdim\htdp\floatbox=\zeropoint
- \showmessage\m!floatblocks{11}\empty
- \global\setbox\floatbox\vbox{\doemptyfloatblock{#1}}%
- \fi
- % deal with lack of caption
- \global\setbox\floatbox\vbox \floatcaptionattribute
- {\doifelsemainfloatbody\currentfloatsynchronize\donothing
- \unvbox\floatbox
- \ifnofloatcaption
- \vss
- \fi}% gets rid of the depth (unless tabulate)
- \egroup
- % place the float
- \dofloat{#3}{\thecurrentfloatnumber}{\thecurrentfloatcaption}%
-% \dostoptagged % tricky here, we need an extra mechanism (add to previous or so)
- \global\insidefloatfalse}
-
-\def\setlocalfloathsize
- {\iflocalcenterfloatbox
- \seteffectivehsize
- \hsize\localhsize
- \fi}
-
-\newevery \everyinsidefloat \relax
-
-\appendtoks
- \everyinsidefloat\emptytoks % in case it's called earlier
- \dogetfloatdata
-\to \everyinsidefloat
-
-\def\doifrightpagefloatelse
- {\ifdoublesided
- \ifsinglesided
- \@EAEAEA\firstoftwoarguments
- \else
- \@EAEAEA\doifoddfloatpageelse
- \fi
- \else
- \@EA\firstoftwoarguments
- \fi}
-
-\def\doifoddfloatpageelse
- {\ifodd\purenumber\twopassfloatdata\space
- \@EA\firstoftwoarguments
- \else
- \@EA\secondoftwoarguments
- \fi}
-
-\appendtoks
- \let\rightorleftpageaction\doifrightpagefloatelse
-\to \everyinsidefloat
-
-\newif\ifextrafloatactions \extrafloatactionstrue
-
-% \let\movesidefloat\gobbleoneargument
-
-% new : \place...[leftmargin,-2*line]; we need to catch fxtb:2*3
-% watch out: line alone aligns on the line ! ! !
-
-\def\movesidefloat[#1]% (-)n*line|x=,y=
- {\global\sidefloatdownshift \zeropoint
- \global\sidefloatextrashift\zeropoint
- \doifassignmentelse{#1}%
- {\bgroup
- \getparameters[\??fl][\c!x=\zeropoint,\c!y=\zeropoint,#1]%
- \ifgridsnapping
- \getnoflines\@@fly
- \global\sidefloatdownshift\noflines\lineheight
- \else
- \global\sidefloatdownshift\@@fly
- \fi
- \global\sidefloatextrashift\@@flx
- \egroup}
- {\movedownsidefloat[#1]}}
-
-\def\movedownsidefloat[#1]% already in core
- {\bgroup
- \cleanupfeatures
- \doifinstringelse{:}{#1}
- \donothing
- {\def\docommand##1%
- {\processaction
- [##1]%
- [ \v!line=>\dodocommand+,%
- +\v!line=>\dodocommand+,%
- -\v!line=>\dodocommand-]}%
- \def\dodocommand##1%
- {\ifdone\else\global\sidefloatdownshift\zeropoint\donetrue\fi
- \global\advance\sidefloatdownshift##1\lineheight}%
- \donefalse\normalexpanded{\noexpand\dorepeatwithcommand[#1]}\docommand
- \def\docommand##1%
- {\processaction
- [##1]%
- [ \v!hang=>\dodocommand+,%
- +\v!hang=>\dodocommand+,%
- -\v!hang=>\dodocommand-]}%
- \def\dodocommand##1% inefficient but who cares
- {\ifdone\else\global\sidefloatsidelines\zeropoint\donetrue\fi
- \global\advance\sidefloatsidelines\plusone\relax}%
- \donefalse\normalexpanded{\noexpand\dorepeatwithcommand[#1]}\docommand}%
- \egroup}
-
-\def\hangsidefloat[#1]%
- {\global\sidefloatsidelines#1\relax}
-
-\long\def\xdocompletefloat#1#2#3#4%
- {\ifextrafloatactions
- \doifinsetelse\v!text{#3}
- {% fuzzy, text overloads left, since then it's a directive
- \docompletefloat{#1}{#2}{#3}{#4}\nextbox}
- {\let\@@extrafloat\empty
- % \sidefloatdownshift will be reset afterwards, and can
- % already be set at this point
- \processallactionsinset
- [#3] % ininner/inouter : for old times sake
- [ \v!inner=>\xxdocompletefloat\v!left \v!right,
- \v!outer=>\xxdocompletefloat\v!right \v!left,
- \v!innermargin=>\xxdocompletefloat\v!leftmargin \v!rightmargin,
- \v!outermargin=>\xxdocompletefloat\v!rightmargin\v!leftmargin,
- \v!inneredge=>\xxdocompletefloat\v!leftedge \v!rightedge,
- \v!outeredge=>\xxdocompletefloat\v!rightedge \v!leftedge,
- \v!backspace=>\xxdocompletefloat\v!backspace \v!cutspace,
- \v!cutspace=>\xxdocompletefloat\v!cutspace \v!backspace,
-% \v!margin=>\xxdocompletefloat\v!cutspace \v!backspace,
- \v!left=>\xxdocompletefloat\v!left \v!left,
- \v!right=>\xxdocompletefloat\v!right \v!right,
- \v!line=>, % only -n*line is handled (see ***)
- \s!unknown=>{\movedownsidefloat[\commalistelement]}]%
- \ifx\@@extrafloat\empty
- \docompletefloat{#1}{#2}{#3}{#4}\nextbox
- \else
- \docompletefloat{#1}{#2}{\@@extrafloat,#3}{#4}\nextbox
- \fi}%
- \else % downward compatible
- \docompletefloat{#1}{#2}{#3}{#4}\nextbox
- \fi}
-
-% pas op, maxbreedte niet instellen als plaats=links/rechts
-
-\def\setlocalfloatdimensions#1%
- {\global\sidefloatshift \zeropoint % duplicate
- \global\sidefloatmaximum\zeropoint\relax % duplicate
- \ifextrafloatactions
- \ifdim\sidefloatdownshift=\zeropoint\else
- \global\setbox\floatbox\vbox
- {\vskip\sidefloatdownshift\nointerlineskip\box\floatbox}%
- \fi
- \doifsomething{\floatparameter\c!minwidth}
- {\scratchdimen\floatparameter\c!minwidth\relax
- \ifdim\wd\floatbox<\scratchdimen
- \global\setbox\floatbox\hbox to \scratchdimen
- {\doifnot{\floatparameter\c!location}\v!left \hss
- \box\floatbox
- \doifnot{\floatparameter\c!location}\v!right\hss}%
- \fi}%
- % todo: rand / rug
- \doifinset\v!hanging{#1}
- {\doifcommonelse{\v!inleft,\v!leftmargin}{#1}
- {\letfloatparameter\c!maxwidth\leftmarginwidth}%
- {\doifcommon{\v!inright,\v!rightmargin}{#1}
- {\letfloatparameter\c!maxwidth\rightmarginwidth}}}%
- \doifsomething{\floatparameter\c!maxwidth}
- {\scratchdimen\floatparameter\c!maxwidth\relax
- \ifdim\wd\floatbox>\scratchdimen
- \doifcommonelse{\v!inright,\v!rightmargin,\v!rightedge,\v!inleft,\v!leftmargin,\v!leftedge}{#1}
- {\global\sidefloatmaximum\scratchdimen}
- {\global\setbox\floatbox\hbox to \scratchdimen
- {\doifcommonelse{\v!right,\v!left}{#1}
- {\doifnotinset\v!right{#1}\hss
- \box\floatbox
- \doifnotinset\v!left{#1}\hss}%
- {\doifnot{\floatparameter\c!location}\v!left\hss
- \box\floatbox
- \doifnot{\floatparameter\c!location}\v!right\hss}}}%
- \fi}%
- \fi}
-
-\def\docomplexstarttextblock[#1][#2][#3]%
- {\flushnotes
- \flushsidefloats % hoort eigenlijk niet hier
- \docomplexplacefloat[#1][\v!text,#2,\v!left][#3]}
-
-\long\def\docomplexreserveblock[#1][#2][#3][#4]#5%
- {\getvalue{\e!place#1}[#3][#4]{#5}{\localframed[\??fl#1][#2]{#1}}}
-
-\def\docomplexstartreservetextblock[#1][#2][#3][#4]%
- {\flushsidefloats % hoort eigenlijk niet hier
- \docomplexreserveblock[#1][#2][\v!text,#3,\v!left][#4]}
-
-\unexpanded\def\placefloat
- {\dotripleempty\docomplexplacefloat}
-
-\installinsertion\topins
-\installinsertion\botins
-
-\newdimen\botinserted
-\newdimen\topinserted
-
-\newif\iftopofinsert
-\newif\iftestfloatbox
-
-\newdimen\floatsideskip \floatsideskip =12pt
-\newdimen\floattopskip \floattopskip =\floattopskip
-\newdimen\floatbottomskip \floatbottomskip=\floattopskip
-
-\newdimen\sidefloattopskip \sidefloattopskip =\floattopskip
-\newdimen\sidefloatbottomskip \sidefloatbottomskip=\floatbottomskip
-
-\newskip\sidefloatdownshift
-\newskip\sidefloatleftshift
-\newskip\sidefloatrightshift
-
-\def\sidefloattopoffset {\openstrutdepth} % {\strutdp}
-
-\newcount\noftopfloats \noftopfloats=2
-\newcount\nofbotfloats \nofbotfloats=0
-
-\def\docalculatefloatskip#1#2%
- {\doifelsenothing{#2}
- {\global#1\zeropoint}
- {\doifelse{#2}\v!none
- {\global#1\zeropoint}
- {\setbox\scratchbox\vbox{\whitespace\normalexpanded{\noexpand\blank[#2]}}%
- \global#1\ht\scratchbox}}}
-
-\def\calculatefloatskips
- {{\docalculatefloatskip\floattopskip{\floatsharedparameter\c!spacebefore}%
- \docalculatefloatskip\floatbottomskip{\floatsharedparameter\c!spaceafter}%
- \docalculatefloatskip\sidefloattopskip{\floatsharedparameter\c!sidespacebefore}%
- \docalculatefloatskip\sidefloatbottomskip{\floatsharedparameter\c!sidespaceafter}%
- \gdef\sidefloattopoffset{\openstrutdepth}% was \def
- \global\floatsideskip\floatsharedparameter\c!margin
- \global\sidefloatleftshift\floatparameter\c!leftmargindistance
- \global\sidefloatrightshift\floatparameter\c!rightmargindistance
- \global\noftopfloats\floatsharedparameter\c!ntop\relax
- \global\nofbotfloats\floatsharedparameter\c!nbottom\relax}}
-
-% beter de laatste skip buiten de \insert uitvoeren,
-% bovendien bij volle flush onder baseline.
-
-% \def\betweenfloatblanko% assumes that spaceafter is present
-% {\bgroup
-% \setbox0\vbox{\strut\blank[\floatsharedparameter\c!spacebefore]\strut}%
-% \setbox2\vbox{\strut\blank[\floatsharedparameter\c!spaceafter]\strut}%
-% \ifdim\ht0>\ht2
-% \blank[-\floatsharedparameter\c!spaceafter,\floatsharedparameter\c!spacebefore]%
-% \fi
-% \egroup}
-
-\def\betweenfloatblanko% assumes that spaceafter is present
- {\blank[\floatsharedparameter\c!spacebefore]} % or v!back,....
-
-\def\doplacefloatbox
- {%\forgetall % NO
- \whitespace
- \blank[\floatsharedparameter\c!spacebefore]
- \flushfloatbox
- \blank[\floatsharedparameter\c!spaceafter]}
-
-\ifdefined\someherefloat\else \let\someherefloat\doplacefloatbox \fi
-\ifdefined\someslotfloat\else \let\someslotfloat\doplacefloatbox \fi
-\ifdefined\somefixdfloat\else \let\somefixdfloat\doplacefloatbox \fi
-\ifdefined\sometopsfloat\else \let\sometopsfloat\doplacefloatbox \fi
-\ifdefined\somebotsfloat\else \let\somebotsfloat\doplacefloatbox \fi
-\ifdefined\somesidefloat\else \let\somesidefloat\doplacefloatbox \fi
-
-% test case:
-%
-% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=0.9\textheight,color=green]}
-% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=1.0\textheight,color=green]}
-% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=1.1\textheight,color=green]}
-
-\def\sometextfloat[#1]% lang, links, rechts, hoog, midden, laag, offset
- {%\checkwaitingfloats{#1}%
- \gdef\dostoptextfloat{\dodostoptextfloat[#1]}% brr global
- \global\floattextwidth\hsize
- \global\floatwidth\wd\floatbox
- \global\floatheight\ht\floatbox % forget about the depth
- \global\advance\floattextwidth -\floatwidth
- \global\advance\floattextwidth -\floatsharedparameter\c!margin\relax % was \tfskipsize
- \doifinsetelse\v!tall{#1}
- {\floattextheight\pagegoal
- \advance\floattextheight -\pagetotal
- \advance\floattextheight -\bigskipamount % lelijk
- \ifdim\floattextheight>\textheight
- \floattextheight\textheight
- \fi
- \boxmaxdepth\zeropoint \relax % toegevoegd
- \ifdim\floattextheight<\floatheight
- \floattextheight\floatheight
- \fi
- \setbox\floattext\vbox to \floattextheight}
- {\setbox\floattext\vbox}%
- \bgroup
- \forgetall \setupblank \setupwhitespace % new, also needed for footnotes
- \blank[\v!disable]
- \hsize\floattextwidth
- \ignorespaces}
-
-\def\dodostoptextfloat[#1]% % de tekst kan beter in een soort
- {\egroup % kadertekst zonder kader, is flexibeler
- \doifnotinset\v!tall{#1}% en beter
- {\ifdim\ht\floattext<\floatheight
- \floattextheight\floatheight
- \else
- \floattextheight\ht\floattext
- \fi}%
- \setbox\floatbox\vbox to \floattextheight
- {\hsize\floatwidth
- \doifinsetelse\v!both{#1}%
- {\doifinsetelse\v!low{#1}
- {\vfill\box\floatbox}
- {\doifinsetelse\v!middle{#1}
- {\vfill\box\floatbox\vfill}
- {\box\floatbox\vfill}}}
- {\box\floatbox\vfill}}%
- \setbox\floattext\vbox to \floattextheight
- {\hsize\floattextwidth
- \doifinsetelse\v!low{#1}
- {\vfill
- \box\floattext
- \doifinset\c!offset{#1}{\whitespace\blank}}
- {\doifinsetelse\v!middle{#1}
- {\vfill
- \box\floattext
- \vfill}
- {\doifinset\v!offset{#1}{\whitespace\blank}%
- \box\floattext
- \vfill}}}%
- \doifinsetelse\v!right{#1}% \floatmethod
- {\setbox\floatbox\hbox to \hsize
- {\box\floattext
- \hfill
- \box\floatbox}}
- {\setbox\floatbox\hbox to \hsize
- {\box\floatbox
- \hfill
- \box\floattext}}%
- \baselinecorrection
- \whitespace
- \blank[\floatsharedparameter\c!spacebefore]%
- \doifnotinset\v!tall{#1}%
- {\dp\floatbox\openstrutdepth}% dp\strutbox}% % toegevoegd
- \box\floatbox
- \dostoptagged
- \blank[\floatsharedparameter\c!spaceafter]%
- \endgroup % **
-% \dostoptagged
- \doinsertfloatinfo}
-
-\def\somefacefloat[#1]% links, rechts, midden, hoog, midden, laag
- {%\checkwaitingfloats{#1}%
- \startopposite\box\floatbox\stopopposite
- \doinsertfloatinfo}
-
-\def\someelsefloat[#1]%
- {\doifinsetelse\v!here{#1}
- {\doifinsetelse\v!always{#1}
- {\page[\v!preference]%
- \docheckiffloatfits
- \ifroomforfloat
- \placesomeherefloat[#1]%
- \else
- \showmessage\m!floatblocks9\empty
- \doreversesavefloat
- \fi}
- {\ifsomefloatwaiting
- \dosavefloat
- \else
- \page[\v!preference]%
- \docheckiffloatfits
- \ifroomforfloat
- \placesomeherefloat[#1]%
- \else
- \dosavefloat
- \fi
- \fi}}
- {\doifinsetelse\v!always{#1}
- {\docheckiffloatfits
- \ifroomforfloat
- \sometopbottomfloat[#1]
- \else
- \showmessage\m!floatblocks9\empty
- \doreversesavefloat
- \fi}
- {\docheckiffloatfits
- \ifroomforfloat
- \sometopbottomfloat[#1]
- \else
- \dosavefloat
- \fi}}}
-
-\def\floatautofactor{.5}
-
-\def\sometopbottomfloat[#1]%
- {\doifelse\floatmethod\v!auto
- {\ifdim\pagetotal<\floatautofactor\pagegoal % when empty page, maxdimen
- \placesometopsfloat[#1]%
- \else
- \placesomebotsfloat[#1]%
- \fi}
- {\doifelse\floatmethod\v!top
- {\placesometopsfloat[#1]}
- {\doifelse\floatmethod\v!bottom
- {\placesomebotsfloat[#1]}
- {\placesomeherefloat[#1]}}}}
-
-\def\borderedfloatbox
- {\localframed
- [\??fl\currentfloat]
- [\c!location=\v!normal,\c!width=\wd\floatbox,\c!height=\htdp\floatbox]
- {\box\floatbox}}
-
-\newbox\tempfloatbox
-
-% minwidth=fit,width=max : no overshoot, as wide as graphic
-
-\ifdefined\moveboxontogrid\else \let\movecaptionontogrid\gobblethreearguments \fi
-
-\def\locatefloatbox
- {\alignstrutmode\zerocount
- \shiftalignedline
- {\floatparameter\c!leftmargin }{\floatparameter\c!rightmargin}%
- {\floatparameter\c!innermargin}{\floatparameter\c!outermargin}%
- \alignedline{\floatparameter\c!location}\v!middle}
-
-\def\locatecaptionbox
- {\alignstrutmode\zerocount
- \shiftalignedline
- {\floatcaptionparameter\c!leftmargin }{\floatcaptionparameter\c!rightmargin}%
- {\floatcaptionparameter\c!innermargin}{\floatcaptionparameter\c!outermargin}%
- \alignedline{\floatparameter\c!location}\v!middle}
-
-\long\def\dosetpagfloat#1#2#3% \copy wegwerken
- {\bgroup
- \setlocalfloathsize
- \ifnum\floatrotation>0
- \swapdimens\hsize\vsize
- \fi
- \forgetall
- \postponenotes
- \dontcomplain
- \setbox\tempfloatbox\vbox{\borderedfloatbox}%
- \let\locatefloat \locatefloatbox
- \let\locatecaption\locatecaptionbox
- \docheckcaptioncontent{#2}{#3}%
- \ifcase\floatparameter\c!method
- \or % automatic
- \ifnofloatcaption
- \dopreparenocaption{#1}{#2}{#3}%
- \edef\width{\the\wd\floatbox}%
- \doglobal\addlocalbackgroundtobox\floatbox
- \else
- % todo: installable maken, variant/method=auto vs macro
- \dopreparedocaption{#1}{#2}{#3}%
- \settracedcaptionbox
- \edef\width{\the\wd\tempfloatbox}%
- \addlocalbackgroundtobox\tempfloatbox
- \setbox\tempcaptionbox\hbox
- {\dosetcaptionthings
- \floatcaptionparameter\c!command{\box\tempcaptionbox}}%
- \moveboxontogrid\tempcaptionbox{\floatcaptionparameter\c!grid}\lastcaptionht
- \addlocalbackgroundtobox\tempcaptionbox
- \buildfloatbox
- \fi
- \or % semi automatic
- \or % manual
- \fi
- \ifnum\floatrotation>0
- \global\setbox\floatbox\vbox
- {\rotate[\c!rotation=\floatrotation]{\box\floatbox}}%
- \edef\width{\the\wd\tempfloatbox}%
- \else
- \postcenterfloatbox\width
- \fi
- \egroup}
-
-\def\captionminwidth {15\bodyfontsize}
-\def\captionovershoot {2em}
-
-\def\dopreparenocaption#1#2#3%
- {\global\setbox\floatbox\vbox % pas op als wd groter dan hsize
- {\ifinsidecolumns\ifdim\wd\tempfloatbox>\hsize
- \let\locatefloat\relax
- \fi\fi
- \locatefloat{\copy\tempfloatbox}}}
-
-\def\dopreparedocaption#1#2#3%
- {\dostarttagged\t!floatcaption\empty
- \doifinsetelse{\floatcaptionparameter\c!location}{\v!top,\v!bottom}
- {\doifinsetelse{\floatcaptionparameter\c!width}{\v!fit,\v!max}
- {\doifelse{\floatcaptionparameter\c!minwidth}\v!fit
- {\doifelse{\floatcaptionparameter\c!width}\v!max
- {\dopreparestackcaptionmax{#1}{#2}{#3}}
- {\ifdim\wd\tempcaptionbox>\wd\tempfloatbox % wider caption
- \doifelse{\floatcaptionparameter\c!width}\v!fit
- {\dopreparestackcaptionaut{#1}{#2}{#3}}
- {\dopreparestackcaptionwid{#1}{#2}{#3}}%
- \else
- \dopreparestackcaptionmin{#1}{#2}{#3}%
- \fi}}
- {\dopreparestackcaptionfix{#1}{#2}{#3}}}%
- {\dopreparesidewidthcaption{#1}{#2}{#3}}}% new, special effects (see icare)
- {\doifinsetelse{\floatcaptionparameter\c!width}{\v!fit,\v!max}
- {\dopreparesideautocaption{#1}{#2}{#3}}
- {\dopreparesidewidthcaption{#1}{#2}{#3}}}%
- \dostoptagged}
-
-% \def\dosettempcaptionbox
-% {\dosetraggedvbox{\floatcaptionparameter\c!align}%
-% \setbox\tempcaptionbox\raggedbox}
-
-\def\dosettempcaptionbox
- {\setbox\tempcaptionbox\vbox\bgroup
- %expanded{\setupalign[\v!new,\v!reset,\floatcaptionparameter\c!align,\v!old]}% wrong! see icare
- \normalexpanded{\noexpand\setupalign[\v!reset,\floatcaptionparameter\c!align]}% i need to check what reset does
- \dosetcaptionthings
- \let\next}
-
-\def\dopreparesideautocaption#1#2#3%
- {\scratchdimen\dimexpr\hsize-\wd\tempfloatbox-\floatparameter\c!margin\relax % was \tfskipsize\relax
- \ifdim\wd\tempcaptionbox>\scratchdimen
- \ifdim\wd\tempcaptionbox<1.3\scratchdimen
- \scratchdimen0.8\scratchdimen
- \fi
- \fi
- \dosettempcaptionbox
- {\hsize\scratchdimen
- \putcompletecaption{#2}{#3}}}
-
-\def\dopreparesidewidthcaption#1#2#3%
- {\dosettempcaptionbox
- {\hsize\floatcaptionparameter\c!width
- \putcompletecaption{#2}{#3}}}
-
-\def\dopreparestackcaptionfix#1#2#3%
- {\dosettempcaptionbox
- {\hsize\floatcaptionparameter\c!minwidth % special effects
- \putcompletecaption{#2}{#3}}}
-
-\def\dopreparestackcaptionmax#1#2#3%
- {\dosettempcaptionbox
- {\hsize\wd\tempfloatbox
- \putcompletecaption{#2}{#3}}}
-
-\def\dopreparestackcaptionwid#1#2#3%
- {\dosettempcaptionbox
- {\hsize\floatcaptionparameter\c!width
- \putcompletecaption{#2}{#3}}}
-
-\def\dopreparestackcaptionmin#1#2#3%
- {\dosettempcaptionbox
- {\hsize\wd\tempfloatbox
- \doifnothing{\floatcaptionparameter\c!align}\raggedcenter % on purpose overloads align !
- \putcompletecaption{#2}{#3}}}
-
-\def\dopreparestackcaptionaut#1#2#3%
- {\doifsomething{\floatcaptionparameter\c!align}
- {\doifnotinset{\v!middle}{\floatcaptionparameter\c!align}%
- {\let\captionovershoot\!!zeropoint}}%
- \edef\captionhsize{\the\wd\tempfloatbox}%
- \ifdim\captionhsize>\hsize
- % float is wider than \hsize
- \dosettempcaptionbox
- {\settrialtypesetting
- \hsize\captionhsize
- \notesenabledfalse
- \putcompletecaption{#2}{#3}}%
- \ifdim\ht\scratchbox>\lineheight % more lines
- \dosettempcaptionbox
- {\hsize\captionhsize
- \advance\hsize -\captionovershoot\relax
- \ifdim\hsize<\captionminwidth\relax
- \hsize\captionhsize
- \fi
- \putcompletecaption{#2}{#3}}%
- \else
- \dosettempcaptionbox
- {\hsize\captionhsize
- \putcompletecaption{#2}{#3}}%
- \fi
- \else
- % float is smaller of equal to \hsize
- \ifdim\captionhsize<\captionminwidth\relax
- \scratchdimen\captionminwidth % float smaller than min width
- \edef\captionhsize{\the\scratchdimen}%
- \fi
- \setbox\scratchbox\vbox % test with overshoot
- {\settrialtypesetting
- \scratchdimen\captionhsize
- \advance\scratchdimen \captionovershoot
- \advance\scratchdimen 3em % an average word length
- \ifdim\scratchdimen<\hsize \hsize\scratchdimen \fi
- \notesenabledfalse
- \putcompletecaption{#2}{#3}}%
- \ifdim\ht\scratchbox>\lineheight
- % at least an average word longer than a line
- \dosettempcaptionbox
- {\scratchdimen\captionhsize
- \advance\scratchdimen \captionovershoot
- \ifdim\scratchdimen<\hsize \hsize\scratchdimen \fi
- \putcompletecaption{#2}{#3}}%
- \else
- % just over a line, don't use an overshoot % % % todo: outer/inner and such
- \doifcommonelse{\floatcaptionparameter\c!align}{\v!left,\v!right,\v!flushleft,\v!flushright}
- {\dosettempcaptionbox
- {\hsize\captionhsize
- % strange : \raggedcenter
- \putcompletecaption{#2}{#3}}}
- {% nicer
- \dosettempcaptionbox
- {\hsize\captionhsize
- \doifnothing{\floatcaptionparameter\c!align}\raggedcenter% overloads
- \putcompletecaption{#2}{#3}}}%
- \fi
- \fi}
-
-\def\dopreparesidecaption#1#2#3%
- {\scratchdimen\dimexpr\hsize-\wd\tempfloatbox-\floatparameter\c!margin\relax % was \tfskipsize\relax
- \ifdim\wd\tempcaptionbox>\scratchdimen
- \ifdim\wd\tempcaptionbox<1.3\scratchdimen
- \scratchdimen0.8\scratchdimen
- \fi
- \fi
- \dosettempcaptionbox % \setbox\tempcaptionbox\vbox
- {\hsize\scratchdimen
- \doifnothing{\floatcaptionparameter\c!align}\raggedright % on purpose overloads align !
- \putcompletecaption{#2}{#3}}}
-
-\newdimen\tempfloatheight
-\newdimen\tempfloatwidth
-
-\def\dofloatboxbetweenstack
- {\endgraf\nointerlineskip\floatcaptionparameter\c!inbetween\endgraf}
-
-\def\dofloatboxdefaultbuilder % done
- {\locatefloat{\box\tempfloatbox}}
-
-\def\dofloatboxnextrightbuilder#1%
- {\ifparfloat \hbox \else \expandafter \locatefloat \fi
- {\tempfloatheight\ht\tempfloatbox
- \box\tempfloatbox
- \normalexpanded{\noexpand\doifnotinset{\v!hang}{\floatcaptionparameter\c!location}}{\dotfskip{\floatcaptionparameter\c!distance}}%
- \vbox to\tempfloatheight{#1}}}
-
-\def\dofloatboxnextleftbuilder#1%
- {\ifparfloat \hbox \else \expandafter \locatefloat \fi
- {\tempfloatheight\ht\tempfloatbox
- \vbox to\tempfloatheight{#1}%
- \normalexpanded{\noexpand\doifnotinset{\v!hang}{\floatcaptionparameter\c!location}}{\dotfskip{\floatcaptionparameter\c!distance}}%
- \box\tempfloatbox}}
-
-\def\dofloatboxnextouterbuilder
- {\doifrightpagefloatelse\dofloatboxnextrightbuilder\dofloatboxnextleftbuilder}
-\def\dofloatboxnextinnerbuilder
- {\doifrightpagefloatelse\dofloatboxnextleftbuilder\dofloatboxnextrightbuilder}
-
-\def\dofloatboxnextrighthangbuilder#1%
- {\ifparfloat \hbox \else \expandafter \locatefloat \fi
- {\tempfloatheight\ht\tempfloatbox
- \box\tempfloatbox
- \vbox to\tempfloatheight{#1}}}
-
-\def\dofloatboxnextlefthangbuilder#1%
- {\ifparfloat \hbox \else \expandafter \locatefloat \fi
- {\tempfloatheight\ht\tempfloatbox
- \vbox to\tempfloatheight{#1}%
- \box\tempfloatbox}}
-
-\def\dodofloatboxnextrightmarginbuilder#1#2%
- {\ifparfloat
- \hbox\bgroup
- \tempfloatheight\ht\tempfloatbox
- \box\tempfloatbox
- \hsmash{\hskip#1\vbox to\tempfloatheight{#2}}%
- \egroup
- \else
- \begingroup
- \tempfloatheight\ht\tempfloatbox
- \everyrightofalignedline{\hsmash{\hskip#1\vbox to\tempfloatheight{#2}}}%
- \locatefloat{\box\tempfloatbox}%
- \endgroup
- \fi}
-
-\def\dodofloatboxnextleftmarginbuilder#1#2%
- {\ifparfloat
- \hbox\bgroup
- \tempfloatheight\ht\tempfloatbox
- \hsmash{\hskip-\dimexpr#1+\wd\tempcaptionbox\relax\vbox to\tempfloatheight{#2}}%
- \box\tempfloatbox
- \egroup
- \else
- \begingroup
- \tempfloatheight\ht\tempfloatbox
- \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\tempcaptionbox\relax\vbox to\tempfloatheight{#2}}}%
- \locatefloat{\box\tempfloatbox}%
- \endgroup
- \fi}
-
-\def\dofloatboxnextrightmarginbuilder{\dodofloatboxnextrightmarginbuilder\rightmargindistance}
-\def\dofloatboxnextleftmarginbuilder {\dodofloatboxnextleftmarginbuilder \leftmargindistance }
-
-\def\dofloatboxnextoutermarginbuilder
- {\doifrightpagefloatelse
- {\dodofloatboxnextrightmarginbuilder\rightmargindistance}
- {\dodofloatboxnextleftmarginbuilder \rightmargindistance}}
-
-\def\dofloatboxnextinnermarginbuilder
- {\doifrightpagefloatelse
- {\dodofloatboxnextleftmarginbuilder \leftmargindistance}
- {\dodofloatboxnextrightmarginbuilder\leftmargindistance}}
-
-\def\dofloatboxnextbuilder % beware, we first check on left/rightmargin because there can be left/right also
- {\let\next\dofloatboxnextleftbuilder
- \normalexpanded{\noexpand\processallactionsinset[\floatcaptionparameter\c!location]}
- [ \v!outermargin=>\let\next\dofloatboxnextoutermarginbuilder,
- \v!innermargin=>\let\next\dofloatboxnextinnermarginbuilder,
- \v!leftmargin=>\let\next\dofloatboxnextleftmarginbuilder,
- \v!rightmargin=>\let\next\dofloatboxnextrightmarginbuilder,
- \v!lefthanging=>\let\next\dofloatboxnextlefthangbuilder,
- \v!righthanging=>\let\next\dofloatboxnextrighthangbuilder,
- \v!outer=>\let\next\dofloatboxnextouterbuilder,
- \v!inner=>\let\next\dofloatboxnextinnerbuilder,
- \v!left=>\let\next\dofloatboxnextleftbuilder,
- \v!right=>\let\next\dofloatboxnextrightbuilder]%
- \next}
-
-\def\dofloatboxsidebuilder
- {\ifparfloat
- \let\next\dofloatboxhighbuilder
- \else
- \let\next\dofloatboxmiddlebuilder
- \expanded{\processallactionsinset[\floatcaptionparameter\c!location]}
- [ \v!low=>\let\next\dofloatboxlowbuilder,
- \v!middle=>\let\next\dofloatboxmiddlebuilder,
- \v!high=>\let\next\dofloatboxhighbuilder]%
- \fi
- \next}
-
-\def\doflushfloatleftcaptionhang
- {\hsmash{\llap{\box\tempcaptionbox\dotfskip{\floatcaptionparameter\c!distance}}}}
-\def\doflushfloatrightcaptionhang
- {\hsmash{\rlap{\dotfskip{\floatcaptionparameter\c!distance}\box\tempcaptionbox}}}
-
-\def\doflushfloatcaptionhang
- {\expanded{\doifinsetelse{\v!righthanging}{\floatcaptionparameter\c!location}}
- {\doflushfloatrightcaptionhang}
- {\expanded{\doifinsetelse{\v!lefthanging}{\floatcaptionparameter\c!location}}
- {\doflushfloatleftcaptionhang}
- {\expanded{\doifinsetelse{\v!hang}{\floatcaptionparameter\c!location}}
- {\expanded{\doifinsetelse{\v!outer}{\floatcaptionparameter\c!location}}
- {\doifrightpagefloatelse{\doflushfloatrightcaptionhang}{\doflushfloatleftcaptionhang}}
- {\expanded{\doifinsetelse{\v!right}{\floatcaptiondirectives}}
- {\doflushfloatrightcaptionhang}
- {\doflushfloatleftcaptionhang}}}
- {\box\tempcaptionbox}}}}
-
-\def\dofloatboxhighbuilder
- {\dofloatboxnextbuilder{\dofloatboxbetweenstack\doflushfloatcaptionhang\vfill}}
-
-\def\dofloatboxlowbuilder
- {\dofloatboxnextbuilder{\vfill\doflushfloatcaptionhang\dofloatboxbetweenstack}}
-
-\def\dofloatboxmiddlebuilder
- {\dofloatboxnextbuilder{\vfill\box\tempcaptionbox\vfill}}
-
-% \definefloat
-% [lefty][lefties][figure]
-% \setupfloat
-% [lefty]
-% [default=left,
-% rightmargindistance=-2cm,
-% leftmargindistance=-2cm]
-% \setupcaption
-% [lefty]
-% [location={bottom,overlay}]
-%
-% \starttext
-% \placelefty{}{} \input tufte \input tufte
-% \placelefty{}{} \input tufte \input tufte
-% \stoptext
-
-\def\bothangfloat#1{\ruledvbox to \ht\tempfloatbox{#1\vss}}
-\def\tophangfloat#1{\ruledvbox to \ht\tempfloatbox{\vss#1}}
-
-\def\dofloatboxnormaltopstackbuilder
- {\expanded{\doifinset{\v!overlay}{\floatcaptionparameter\c!location}}\tophangfloat
- {\tempfloatwidth\wd\tempfloatbox
- \ifparfloat
- \hbox{\locatesidefloat{\box\tempcaptionbox}}%
- \dofloatboxbetweenstack
- \hbox{\hbox {\box\tempfloatbox }}%
- \else
- \hbox{\locatetextfloat{\box\tempcaptionbox}}
- \dofloatboxbetweenstack
- \hbox{\locatefloat {\box\tempfloatbox }}%
- \fi}}
-
-\def\dofloatboxnormalbotstackbuilder
- {\expanded{\doifinset{\v!overlay}{\floatcaptionparameter\c!location}}\bothangfloat
- {\tempfloatwidth\wd\tempfloatbox
- \ifparfloat
- \hbox{\hbox {\box\tempfloatbox }}%
- \dofloatboxbetweenstack
- \hbox{\locatesidefloat{\box\tempcaptionbox}}%
- \else
- \hbox{\locatefloat {\box\tempfloatbox }}%
- \dofloatboxbetweenstack
- \hbox{\locatetextfloat{\box\tempcaptionbox}}%
- \fi}}
-
-\def\dofloatboxgridtopstackbuilder
- {\dp\tempcaptionbox\strutdepth
- \setbox\scratchbox\vbox
- {\tempfloatwidth\wd\tempfloatbox
- \ifparfloat
- \locatesidefloat{\box\tempcaptionbox}%
- \vss\dofloatboxbetweenstack
- \hbox {\box\tempfloatbox }%
- \else
- \locatetextfloat{\box\tempcaptionbox}%
- \vss\dofloatboxbetweenstack
- \locatefloat {\box\tempfloatbox }%
- \fi}%
- \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
- \vbox to \noflines\lineheight{\unvbox\scratchbox}}
-
-\def\dofloatboxgridbotstackbuilder
- {\dp\tempcaptionbox\strutdepth
- \setbox\scratchbox\vbox
- {\tempfloatwidth\wd\tempfloatbox
- \ifparfloat
- \hbox {\box\tempfloatbox }%
- \vss\dofloatboxbetweenstack
- \locatesidefloat{\box\tempcaptionbox}%
- \else
- \locatefloat {\box\tempfloatbox }%
- \vss\dofloatboxbetweenstack
- \locatetextfloat{\box\tempcaptionbox}%
- \fi}%
- \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
- \vbox to \noflines\lineheight{\unvbox\scratchbox}}
-
-\def\dofloatboxstretchtopstackbuilder
- {\dp\tempcaptionbox\strutdepth
- \setbox\scratchbox\vbox
- {\locatecaption{\copy\tempcaptionbox}%
- \locatefloat {\copy\tempfloatbox }}%
- \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
- \vbox to \noflines\lineheight
- {\tempfloatwidth\wd\tempfloatbox
- \ifparfloat
- \locatesidefloat{\box\tempcaptionbox}%
- \vss\dofloatboxbetweenstack\vss
- \hbox {\box\tempfloatbox }%
- \else
- \locatetextfloat{\box\tempcaptionbox}%
- \vss\dofloatboxbetweenstack\vss
- \locatefloat {\box\tempfloatbox }%
- \fi}}
-
-\def\dofloatboxstretchbotstackbuilder
- {\dp\tempcaptionbox\strutdepth
- \setbox\scratchbox\vbox
- {\locatefloat {\copy\tempfloatbox }%
- \locatecaption{\copy\tempcaptionbox}}%
- \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
- \vbox to \noflines\lineheight
- {\tempfloatwidth\wd\tempfloatbox
- \ifparfloat
- \hbox {\box\tempfloatbox }%
- \vss\dofloatboxbetweenstack\vss
- \locatesidefloat{\box\tempcaptionbox}
- \else
- \locatefloat {\box\tempfloatbox }%
- \vss\dofloatboxbetweenstack\vss
- \locatetextfloat{\box\tempcaptionbox}%
- \fi}}
-
-\def\dofloatboxtopbuilder
- {\let\next\dofloatboxnormaltopstackbuilder
- \expanded{\processfirstactioninset[\floatcaptionparameter\c!location]}
- [ \v!grid=>\let\next\dofloatboxgridstackbuilder,
- \v!stretch=>\let\next\dofloatboxstretchstackbuilder]%
- \next}
-
-\def\dofloatboxbottombuilder
- {\let\next\dofloatboxnormalbotstackbuilder
- \expanded{\processfirstactioninset[\floatcaptionparameter\c!location]}
- [ \v!grid=>\let\next\dofloatboxgridstackbuilder,
- \v!stretch=>\let\next\dofloatboxstretchstackbuilder]%
- \next}
-
-\def\relocatecaptionright#1{\locatecaption{\hbox to \tempfloatwidth{\hss#1}}}
-\def\relocatecaptionleft #1{\locatecaption{\hbox to \tempfloatwidth{#1\hss}}}
-
-\long\def\installfloatboxbuilder#1#2{\setvalue{\??kj:#1}{#2}}
-
-\def\buildfloatbox
- {\global\setbox\floatbox\vbox
- {\setlocalfloathsize
- \forgetall
- \let\floatcaptionarrangement\s!default
- \def\docommand##1%
- {\doifdefined{\??kj:##1}{\def\floatcaptionarrangement{##1}\quitcommalist}}%
- \processcommacommand[\floatcaptionparameter\c!location]\docommand
- \executeifdefined{\??kj:\floatcaptionarrangement}{\getvalue{\??kj:\s!default}}}}
-
-\def\locatetextfloat
- {\let\next\locatecaption
- \expanded{\processallactionsinset[\floatcaptionparameter\c!location]}
- [ \v!left=>\let\next\relocatecaptionleft,
- \v!right=>\let\next\relocatecaptionright,
- \v!inner=>\doifrightpagefloatelse{\let\next\relocatecaptionleft }{\let\next\relocatecaptionright},
- \v!outer=>\doifrightpagefloatelse{\let\next\relocatecaptionright}{\let\next\relocatecaptionleft }]%
- \next}
-
-\installfloatboxbuilder \v!none \dofloatboxdefaultbuilder
-\installfloatboxbuilder \s!default \dofloatboxdefaultbuilder
-\installfloatboxbuilder \v!high \dofloatboxhighbuilder
-\installfloatboxbuilder \v!low \dofloatboxlowbuilder
-\installfloatboxbuilder \v!middle \dofloatboxmiddlebuilder
-
-\installfloatboxbuilder \v!left \dofloatboxsidebuilder
-\installfloatboxbuilder \v!right \dofloatboxsidebuilder
-
-\installfloatboxbuilder \v!top \dofloatboxtopbuilder
-\installfloatboxbuilder \v!bottom \dofloatboxbottombuilder
-
-% \setuplayout[grid=yes] \showgrid \setupcaptions[style=smallbodyfont,location=grid,inbetween=]
-%
-% \starttext
-% test \placefigure{} {\externalfigure[cow.pdf][frame=on,grid=yes]} test \page
-% test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=yes]} test \page
-% test \placefigure{} {\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
-% test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
-% \stoptext
-
-\newif\ifpostponecolumnfloats \postponecolumnfloatsfalse % don't change
-
-\setnewconstant\postcenterfloatmethod\plusone
-
-\def\postcenterfloatbox#1%
- {\scratchdimen
- \ifcase\postcenterfloatmethod
- #1% \wd\floatbox
- \or\ifinsidecolumns
- \ifpostponecolumnfloats\makeupwidth\else#1\fi
- \else\ifdim#1>\hsize
- \hsize
- \else
- \wd\floatbox
- \fi\fi\fi
- \global\setbox\floatbox\hbox to \scratchdimen
- % {\hfill\box\floatbox\hfill}} % geen \hss, gaat mis in kolommen !
- % {\hss \box\floatbox\hss }} % wel \hss, anders mis in colset
- {\ifglobalcenterfloatbox
- \donetrue
- \else\iflocalcenterfloatbox
- \donetrue
- \else
- \donefalse
- \fi\fi
- \ifdim\scratchdimen>\effectivehsize
- \donefalse
- \fi
- \hss\ifdone\hskip\effectiveleftskip\fi
- \box\floatbox
- \ifdone\hskip\effectiverightskip\fi\hss}}
-
-\long\def\dosetparfloat#1#2#3%
- {\bgroup
- \forgetall
- \postponenotes
- \dontcomplain
- %\showcomposition
- \setbox\tempfloatbox\vbox{\borderedfloatbox}%
- \addlocalbackgroundtobox\tempfloatbox % no \doglobal
- \docheckcaptioncontent{#2}{#3}%
- \ifnofloatcaption
- \global\setbox\floatbox\vbox{\box\tempfloatbox}%
- \else
- \dopreparedosidecaption{#1}{#2}{#3}%
- \settracedcaptionbox
- \setbox\tempcaptionbox\hbox{\floatcaptionparameter\c!command{\box\tempcaptionbox}}%
- \moveboxontogrid\tempcaptionbox{\floatcaptionparameter\c!grid}\lastcaptionht
- \addlocalbackgroundtobox\tempcaptionbox % no \doglobal
- \buildsidefloatbox
- \fi
- \egroup}
-
-\def\dopreparedosidecaption#1#2#3% will be enhanced
- {\doifelse{\floatcaptionparameter\c!width}\v!max
- {\dosettempcaptionbox
- {\hsize\wd\tempfloatbox
- \putcompletecaption{#2}{#3}}}%
- {\doifelse{\floatcaptionparameter\c!width}\v!fit
- {\ifdim\wd\tempcaptionbox>\wd\tempfloatbox\relax
- \setbox\tempcaptionbox\vbox
- {\forgetall % needed?
- \hsize\wd\tempfloatbox
- \dosetcaptionthings
- \putcompletecaption{#2}{#3}}%
- \else
- \setbox\tempcaptionbox\hbox to \wd\tempfloatbox
- {\hss\box\tempcaptionbox\hss}%
- \fi}
- {\dosettempcaptionbox
- {\hsize\floatcaptionparameter\c!width % \wd\tempfloatbox
- \putcompletecaption{#2}{#3}}}}}
-
-\def\buildsidefloatbox
- {\let\locatefloat \relax
- \let\locatecaption\relax
- \def\locatesidefloat##1%
- {\begingroup
- \alignstrutmode\zerocount
- \hsize\tempfloatwidth \forgetall
- \alignedline{\floatparameter\c!location}\v!middle{##1}%
- \endgroup}%
- \buildfloatbox}
-
-\newif\ifparfloat
-
-\long\def\dosetfloatbox#1#2#3% todo : \global\setbox, currently messy
- {\ifvisible
- \par
- \edef\floatcaptiondirectives{\floatparameter\c!location,\floatcaptionparameter\c!location}%
- \ifparfloat\@EA\dosetparfloat\else\@EA\dosetpagfloat\fi{#1}{#2}{#3}%
- \setlocalfloatdimensions{#1}%
- \global\advance\totalnoffloats\plusone
- \setbox\floatbox\hbox{\dosavefloatdata\box\floatbox}% still needed? we will do renumbering differently
- \global\floatheight\htdp\floatbox
- \global\floatwidth\wd\floatbox
- \doifnotinset\v!margin{#1} % gaat namelijk nog fout
- {\setbox\floatbox\vbox
- {\parindent\zeropoint
- \doifconcepttracing{\inleftmargin{\framed{\infofont\the\totalnoffloats}}}%
- \box\floatbox}}%
- \wd\floatbox\floatwidth
- \ifdim\dimexpr\floatheight+\lineheight\relax<\textheight \else
- \global\floatheight\dimexpr\textheight-\lineheight\relax
- \ht\floatbox\floatheight
- \dp\floatbox\zeropoint
- \showmessage\m!floatblocks{10}{\the\totalnoffloats}%
- \fi
- \fi}
-
-\newcounter\noxfloatlocations
-
-\long\def\dofloat#1#2#3% #1 is optionlist
- {\dosetfloatbox{#1}{#2}{#3}%
- \dogetfloatbox{#1}\empty}
-
-\def\dooutput{\sidefloatoutput} % redefinition of \dooutput
-
-\definefloat
- [\v!figure]
- [\v!figures]
-
-\definefloat
- [\v!table]
- [\v!tables]
-
-\setupfloat
- [\v!table]
- [\c!frame=\v!off]
-
-\definefloat
- [\v!intermezzo]
- [\v!intermezzi]
-
-\definefloat
- [\v!graphic]
- [\v!graphics]
-
-% float strategy, replaces some of the above macros
-
-\let\floatmethod \empty
-\let\floatlabel \empty
-\let\floatcolumn \empty
-\let\floatrow \empty
-\let\forcedfloatmethod\empty
-
-% \def\setfloatmethodvariables#1%
-% {\getfromcommalist[#1][1]%
-% \@EA\beforesplitstring\commalistelement\at:\to\floatmethod
-% \@EA\aftersplitstring \commalistelement\at:\to\floatcolumn
-% \@EA\aftersplitstring \floatcolumn\at*\to\floatrow
-% \@EA\beforesplitstring\floatcolumn\at*\to\floatcolumn}
-
-\def\setfloatmethodvariables#1% \floatmethod \floatlabel \floatrow \floatcolumn
- {\ctxlua{floats.analysemethod("#1")}}
-
-\def\dogetfloatbox#1#2%
- {\ifvisible
- \let \floatlabel \empty
- \let \floatcolumn\empty
- \let \floatrow \empty
- \edef\floatmethod{#2}%
- \ifx\floatmethod\empty
- \setfloatmethodvariables{#1}%
- % todo: nog algemeen otr
- \ifdefined\OTRSETsetpreferedcolumnslot
- \OTRSETsetpreferedcolumnslot\floatcolumn\floatrow
- \fi
- \fi
- \doifundefined{\string\floatmethod\floatmethod}
- {\let\floatmethod\v!here}%
- \doifsomething\forcedfloatmethod
- {\edef\floatmethod{\forcedfloatmethod}}%
- %\getvalue{\string\floatmethod\floatmethod}[#1]%
- \getvalue{\string\floatmethod\floatmethod}[\floatmethod,#1]%
- \fi}
-
-\def\installfloathandler#1#2% #1=keyword #2=handler
- {\setvalue{\string\floatmethod#1}{#2}}
-
-\def\somesomewherefloat[#1]%
- {\dofloatssavesomewherefloat\s!somewhere{#1}}
-
-\installfloathandler \v!here \someherefloat
-\installfloathandler \v!force \somefixdfloat
-\installfloathandler \v!left \someleftsidefloat
-\installfloathandler \v!right \somerightsidefloat
-\installfloathandler \v!text \sometextfloat
-\installfloathandler \v!top \sometopfloat
-\installfloathandler \v!bottom \somebottomfloat
-\installfloathandler \v!auto \someautofloat
-\installfloathandler \v!margin \somemarginfloat
-\installfloathandler \v!opposite \somefacefloat
-\installfloathandler \v!page \somepagefloat
-\installfloathandler \v!leftpage \someleftpagefloat
-\installfloathandler \v!rightpage \somerightpagefloat
-\installfloathandler \v!inmargin \someinmarginfloat
-\installfloathandler \v!inleft \someinleftmarginfloat
-\installfloathandler \v!inright \someinrightmarginfloat
-\installfloathandler \v!leftmargin \someinleftmarginfloat
-\installfloathandler \v!rightmargin \someinrightmarginfloat
-\installfloathandler \v!leftedge \someinleftedgefloat
-\installfloathandler \v!rightedge \someinrightedgefloat
-
-\installfloathandler \v!somewhere \somesomewherefloat
-
-\installfloathandler \v!backspace \somebackspacefloat
-\installfloathandler \v!cutspace \somecutspacefloat
-
-\installfloathandler {tblr} \someslotfloat
-\installfloathandler {lrtb} \someslotfloat
-\installfloathandler {tbrl} \someslotfloat
-\installfloathandler {rltb} \someslotfloat
-\installfloathandler {btlr} \someslotfloat
-\installfloathandler {lrbt} \someslotfloat
-\installfloathandler {btrl} \someslotfloat
-\installfloathandler {rlbt} \someslotfloat
-\installfloathandler {fxtb} \someslotfloat
-\installfloathandler {fxbt} \someslotfloat
-
-% no \registerotrcommand\placesome* here!, this has to be cleaned up:
-
-\def\somesidefloat{\OTRcommand\somesidefloat}
-
-\def\someleftsidefloat [#1]{\somesidefloat[#1]\presetindentation}
-\def\somerightsidefloat [#1]{\somesidefloat[#1]}
-\def\sometopfloat [#1]{\someelsefloat[#1]\nonoindentation}
-\def\somebottomfloat [#1]{\someelsefloat[#1]}
-\def\someautofloat [#1]{\someelsefloat[#1]}
-\def\somemarginfloat [#1]{\somenextfloat[#1]\nonoindentation}
-\def\someinleftmarginfloat [#1]{\somesidefloat[#1]}
-\def\someinrightmarginfloat[#1]{\somesidefloat[#1]}
-\def\someinleftedgefloat [#1]{\somesidefloat[#1]}
-\def\someinrightedgefloat [#1]{\somesidefloat[#1]}
-\def\someinmarginfloat [#1]{\somesidefloat[#1]}
-\def\someherefloat [#1]{\someelsefloat[\v!here,#1]}
-\def\somebackspacefloat [#1]{\somesidefloat[#1]}
-\def\somecutspacefloat [#1]{\somesidefloat[#1]}
-
-\unexpanded\def\placesomeslotfloat {\OTRcommand\someslotfloat}
-\unexpanded\def\placesomeherefloat {\OTRcommand\someherefloat}
-\unexpanded\def\placesomefixdfloat {\OTRcommand\somefixdfloat}
-\unexpanded\def\placesomepagefloat {\OTRcommand\somepagefloat}
-\unexpanded\def\placesomeleftpagefloat {\OTRcommand\someleftpagefloat}
-\unexpanded\def\placesomerightpagefloat{\OTRcommand\somerightpagefloat}
-\unexpanded\def\placesometopsfloat {\OTRcommand\sometopsfloat}
-\unexpanded\def\placesomebotsfloat {\OTRcommand\somebotsfloat}
-\unexpanded\def\placesomesidefloat {\OTRcommand\somesidefloat}
-\unexpanded\def\placesomefacefloat {\OTRcommand\somefacefloat}
-%unexpanded\def\placesomesomewherefloat{\OTRcommand\somesomewherefloat}
-
-\def\somefixdfloat {\placesomefixdfloat}
-\def\somepagefloat {\placesomepagefloat}
-\def\someleftpagefloat {\placesomeleftpagefloat}
-\def\somerightpagefloat{\placesomerightpagefloat}
-\def\somefacefloat {\placesomefacefloat}
-\def\someslotfloat {\placesomeslotfloat}
-
-%D Local floats:
-
-\def\setuplocalfloats
- {\getparameters[\??lf]}
-
-\setuplocalfloats
- [%\c!before=\blank,
- %\c!after=\blank,
- \c!inbetween=\blank]
-
-\installfloathandler \v!local \somelocalfloat
-
-\initializeboxstack{localfloats}
-
-\newcounter\noflocalfloats
-
-\def\resetlocalfloats
- {\doglobal\newcounter\noflocalfloats
- \initializeboxstack{localfloats}}
-
-\def\somelocalfloat[#1]%
- {\doglobal\increment\noflocalfloats
- \savebox{localfloats}{\noflocalfloats}{\box\floatbox}}
-
-\def\getlocalfloats
- {\dorecurse\noflocalfloats
- {\ifnum\recurselevel=\plusone % 1\relax
- \getvalue{\??lf\c!before}%
- \else
- \getvalue{\??lf\c!inbetween}%
- \fi
- \dontleavehmode\hbox{\foundbox{localfloats}\recurselevel}%
- \ifnum\recurselevel=\noflocalfloats\relax
- \getvalue{\??lf\c!after}%
- \fi}}
-
-\def\flushlocalfloats
- {\getlocalfloats
- \resetlocalfloats}
-
-\def\getlocalfloat#1{\expanded{\foundbox{localfloats}{\number#1}}}
-
-\def\forcelocalfloats{\let\forcedfloatmethod\v!local}
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-flt.mkvi b/Master/texmf-dist/tex/context/base/strc-flt.mkvi
new file mode 100644
index 00000000000..05cfa40e333
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-flt.mkvi
@@ -0,0 +1,2120 @@
+%D \module
+%D [ file=strc-flt,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Float Numbering,
+%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 / Float Numbering}
+
+\registerctxluafile{strc-flt}{1.001}
+
+\unprotect
+
+% todo: delay caption creation and make setups for each method instead
+% so that we can have a list of methods and redo them as we can
+% keep the list or even better: recreate it
+%
+% todo: strc_floats_analyze_variables_two could trigger a setup
+% and we could have nofmethods of them
+
+% Less globals!
+
+%D This module is being converted into a mkvi one.
+%D
+%D - rename macros
+%D - get rid of dead code
+%D - less gobal mess
+%D - more mkiv-ish
+
+\installcorenamespace{float}
+\installcorenamespace{floatbuilder}
+\installcorenamespace{floatcaption}
+
+\installframedcommandhandler \??float {float} \??float
+\installframedcommandhandler \??floatcaption {floatcaption} \??floatcaption
+
+\let\setupfloats \setupfloat
+\let\setupcaption \setupfloatcaption
+\let\setupcaptions\setupfloatcaption
+
+\def\dohandlenextfloatindent
+ {\useindentnextparameter\floatparameter
+ \dorechecknextindentation}
+
+\setupcaptions
+ [\c!location=\v!bottom,
+ \c!grid=,
+ \c!before=, % not used (yet)
+ \c!inbetween={\blank[\v!medium]},
+ \c!after=, % not used (yet)
+ \c!spacebefore=,
+ \c!spaceinbetween=, % replaces fuzzy inbetween dual usage
+ \c!spaceafter=,
+ \c!width=\v!fit,
+ \c!minwidth=\v!fit, % id est: the width of the floatbox in some cases
+ \c!headstyle=\v!bold,
+ \c!headcolor=,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!outermargin=\zeropoint,
+ \c!innermargin=\zeropoint,
+ \c!setups=,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!textstyle=,
+ \c!textcolor=,
+ \c!align=,
+ \c!number=\v!yes,
+ % \c!expansion=\v!no
+ % \c!prefix=\v!no,
+ % \c!prefixconnector=.,
+ % \c!way=\v!by\v!chapter,
+ % \c!prefixsegments=2:2,
+ % \c!way=\@@nrway,
+ % \c!blockway=\@@nrblockway,
+ % \c!sectionnumber=\@@nrsectionnumber,
+ % \c!separator=\@@koseparator,
+ % \c!starter=\@@kostarter,
+ % \c!stopper=\@@kostopper,
+ \c!suffixseparator=, % currently rather hard coded
+ \c!suffix=\floatcaptionsuffix,
+ \c!distance=1em,
+ \c!conversion=\v!numbers,
+ \c!command=]
+
+% we can comment some of these
+
+\setupfloats
+ [\c!location=\v!middle,
+ \c!width=8\lineheight,
+ \c!height=6\lineheight,
+ \c!offset=\v!overlay,
+ \c!frame=\v!off,
+ \c!strut=\v!no,
+ \c!radius=.5\bodyfontsize,
+ \c!corner=\v!rectangular,
+ %\c!background=,
+ %\c!backgroundcolor=,
+ \c!backgroundoffset=\!!zeropoint,
+ %\c!topframe=,
+ %\c!bottomframe=,
+ %\c!leftframe=,
+ %\c!rightframe=,
+ \c!frameoffset=\!!zeropoint,
+ %\c!before=,
+ %\c!after=,
+ \c!spacebefore=\v!big,
+ \c!spaceafter=\v!big,
+ \c!sidespacebefore=\rootfloatparameter\c!spacebefore,
+ \c!sidespaceafter=\rootfloatparameter\c!spaceafter,
+ \c!sidealign=\v!normal,
+ \c!textmethod=\ifgridsnapping2\else0\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) % THIS WILL CHANGE
+ \c!sidemethod=\ifgridsnapping2\else1\fi, % 0=raw 1=safe (.99pg) 2=tight (-1pt) % THIS WILL CHANGE
+ \c!indentnext=\v!no,
+ \c!margin=1em,
+ \c!method=1,
+ \c!cache=\v!yes, % when no, then intermediate flush
+ \c!leftmargin=\zeropoint, % displacement in 'normal floats'
+ \c!rightmargin=\zeropoint, % idem
+ \c!innermargin=\zeropoint, % idem
+ \c!outermargin=\zeropoint, % idem
+ \c!leftmargindistance=\zeropoint,
+ \c!rightmargindistance=\floatparameter\c!leftmargindistance,
+ \c!ntop=2,
+ \c!nbottom=0,
+ \c!nlines=4,
+ %\c!local=,
+ %\c!bottombefore=, % e.g. \vfill
+ %\c!bottomafter=,
+ %\c!default=, % default location
+ \c!numbering=\v!yes]
+
+%D Individial settings:
+
+\strc_counter_preset_using_parameter\setupcaption\sharedcounterparameter
+
+\appendtoks
+ \let\currentfloat\currentfloatcaption
+ \ifx\currentfloat\empty \else
+ \strc_counter_setup_using_parameter\currentfloatcaption\floatcaptionparameter
+ \strc_counters_check_setup\currentfloatcaption
+ \fi
+\to \everysetupfloatcaption
+
+%D Definitions:
+
+\let\saveddefinefloat\definefloat
+
+\unexpanded\def\definefloat
+ {\dotripleempty\dodefinefloat}
+
+\def\dodefinefloat[#1][#2][#3]% #1=naam #2=meervoud #3=parent
+ {\ifthirdargument
+ \redodefinefloat[#1][#2][#3]%
+ \else\ifsecondargument
+ \dododefinefloat[#1][#2]%
+ \else
+ \dododefinefloat[#1][#1]%
+ \fi\fi}
+
+\def\dododefinefloat[#1][#2]%
+ {\definefloatcaption[#1]%
+ \definecounter[#1]%
+ \definelist[#1]%
+ \presetlabeltext[#1=\Word{#1}~]%
+ \presetheadtext[#2=\Word{#2}]%
+ \saveddefinefloat[#1]%
+ \dodefinefloatcommands[#1][#2]}
+
+\def\redodefinefloat[#1][#2][#3]%
+ {\definefloatcaption[#1][#3]%
+ \definecounter[#1][#3]%
+ \definelist[#1][#3]%
+ \presetlabeltext[#1=\Word{#3}~]%
+ \presetheadtext[#2=\Word{#2}]%
+ \saveddefinefloat[#1][#3]%
+ \dodefinefloatcommands[#1][#2]}
+
+\def\dodefinefloatcommands[#1][#2]%
+ {\setuvalue {\e!place\e!listof#2}{\dodoubleempty\strc_lists_place[#1]}% call will change
+ \setuvalue {\e!complete\e!listof#2}{\dotripleempty\strc_lists_complete_indeed[#1][#2]}% call will change
+ \setuevalue {\e!place#1}{\strc_floats_place{#1}}%
+ \setuevalue {\e!start\e!place#1}{\strc_floats_start_place{#1}}%
+ \setuevalue {\e!stop\e!place#1}{\strc_floats_stop_place}%
+ \setuevalue {\e!start#1\e!text}{\strc_floats_start_text{#1}}%
+ \setuevalue {\e!stop#1\e!text}{\strc_floats_stop_text}%
+ % these will become obsolete:
+ \setuevalue {\e!reserve#1}{\strc_floats_reserve{#1}}%
+ \setuevalue{\e!start\e!reserve#1\e!text}{\strc_floats_start_reserve_text{#1}}%
+ \setuevalue {\e!stop\e!reserve#1\e!text}{\strc_floats_stop_reserve_text}}
+
+%D Fallback float body:
+
+\unexpanded\def\strc_floats_place_empty_box % \inheritedfloatframed
+ {\framed
+ [\c!frame=\v!on,
+ \c!width=\rootfloatparameter\c!width,
+ \c!height=\rootfloatparameter\c!height,
+ \c!location=\v!normal,
+ \c!offset=\rootfloatparameter\c!offset]%
+ {\getmessage\m!floatblocks{12}\empty}}
+
+%D Data. We can generalize this to lists.
+
+\newif\ifnofloatcaption
+\newif\ifnofloatnumber
+\newif\ifemptyfloatcaption
+
+\installstructurelistprocessor{float}{\usestructurelistprocessor{number+title}}
+
+\unexpanded\def\thecurrentfloatnumbersuffix
+ {\doifsomething{\floatcaptionparameter\c!suffix}
+ {\floatcaptionparameter\c!suffixseparator
+ \floatcaptionparameter\c!suffix
+ \floatcaptionparameter\c!suffixstopper}}
+
+\unexpanded\def\thecurrentfloatnumber
+ {\ifnofloatcaption \else \ifnofloatnumber \else
+ \ifx\currentfloatnumber\relax\else
+ \namedtaggedlabeltexts
+ \t!floatlabel \currentfloat
+ \t!floatnumber\currentfloat
+ {\ctxcommand{savedlistprefixednumber("\currentfloat",\currentfloatnumber)}%
+ \thecurrentfloatnumbersuffix}%
+ \fi
+ \fi \fi}
+
+\unexpanded\def\thecurrentfloatcaption
+ {\ifnofloatcaption \else
+ \ifx\currentfloatnumber\relax\else
+ \dostarttagged\t!floattext\empty
+ \ctxcommand{savedlisttitle("\currentfloat",\currentfloatnumber)}%
+ \dostoptagged
+ \fi
+ \fi}
+
+%D Captions.
+
+\let\floatcaptionsuffix\empty % an optional suffix
+\let\floatcaptionnumber\empty % a logical counter
+
+% the split is needed when for instance the float goes into
+% a multi page field and the list of figs becomes larger than
+% one page: cycle between 'only flush when object ref ok'
+% and 'one/many page fig list'; see "uguide finometer"
+%
+% potential sync bug with sectionblocks, see uguide.tex
+
+% begin of todo
+
+\unexpanded\def\placefloatcaption{\dodoubleempty\doplacefloatcaption}
+\unexpanded\def\setfloatcaption {\dodoubleempty\dodosetfloatcaption}
+
+\def\doplacefloatcaption[#tag][#reference]#caption{[not supported]}
+\def\dodosetfloatcaption[#tag][#reference]#caption{[not supported]} % \dosetfloatcaption already in use
+
+\unexpanded\def\placefloatcaptiontext [#tag]{[not suported yet]}
+\unexpanded\def\placefloatcaptionnumber [#tag]{[not suported yet]}
+\unexpanded\def\placefloatcaptionreference[#tag]{[not suported yet]}
+
+\let\placefloatlabel \placefloatcaption
+\let\placefloatlabeltext \placefloatcaptiontext
+\let\placefloatlabelreference\placefloatcaptionreference
+
+% end of todo
+
+\newbox \b_strc_floats_caption
+\newbox \b_strc_floats_content
+\newdimen\d_strc_floats_caption_height
+\newdimen\d_strc_floats_caption_depth
+
+\def\strc_floats_make_complete_caption
+ {\doifsomething{\floatcaptionparameter\c!spacebefore}{\blank[\floatcaptionparameter\c!spacebefore]}%
+ \synchronizedisplaydirection % temp hack, till we have a proper model
+ \noindent
+ \gdef\lastcaptiontag{\strut\thecurrentfloatnumber}% was xdef ... needs checking
+ \begingroup
+ \usefloatcaptionstyleandcolor\c!style\c!color
+ \ifnofloatnumber
+ \else
+ \hbox{\usefloatcaptionstyleandcolor\c!headstyle\c!headcolor\strut\thecurrentfloatnumber}%
+ \ifnofloatcaption \else \ifemptyfloatcaption \else
+ \doifelsenothing{\floatcaptionparameter\c!spaceinbetween}
+ {\scratchskip\floatcaptionparameter\c!distance\relax
+ \dotfskip\scratchskip\emergencystretch.5\scratchskip}
+ {\blank[\floatcaptionparameter\c!spaceinbetween]}%
+ \fi \fi
+ \fi
+ \ifnofloatcaption
+ \global\d_strc_floats_caption_height\zeropoint
+ \global\d_strc_floats_caption_depth \zeropoint
+ \else
+ \usefloatcaptionstyleandcolor\c!textstyle\c!textcolor
+ \global\d_strc_floats_caption_height\strutheight
+ \global\d_strc_floats_caption_depth \strutdepth
+ \begstrut\thecurrentfloatcaption\endstrut\endgraf
+ \fi
+ \endgroup
+ \doifsomething{\floatcaptionparameter\c!spaceafter}{\blank[\floatcaptionparameter\c!spaceafter]}}
+
+% \newif\iftracecaptions
+%
+% \def\settracedcaptionbox
+% {\iftracecaptions\setbox\b_strc_floats_caption\ruledhbox{\box\b_strc_floats_caption}\fi}
+
+% \definefloat [figure-1] [figure]
+% \definefloat [figure-2] [figure]
+% \setupfloat [figure-1] [location=left,leftmargin=10mm]
+% \setupfloat [figure-2] [location=left,leftmargin=-5mm]
+% \setupcaption [figure-1] [align=flushleft]
+% \setupcaption [figure-2] [align=flushleft,leftmargin=15mm]
+%
+% \startsetups somefigure
+% \ifdim\wd\nextbox>\textwidth
+% \placefloat[figure-2][][]{}{\box\nextbox}
+% \else
+% \placefloat[figure-1][][]{}{\box\nextbox}
+% \fi
+% \stopsetups
+%
+% \unexpanded\def\setupswithbox[#1]{\dowithnextbox{\setups[#1]}\vbox}
+%
+% test \setupswithbox[somefigure]{\framed[width=3cm] {}} test
+% test \setupswithbox[somefigure]{\framed[width=\dimexpr\textwidth+3cm\relax]{}} test
+
+% temporary removed ... was not applied systematically
+%
+% \def\dosetcaptionthings
+% {\doprocesslocalsetups{\floatcaptionparameter\c!setups}\relax}
+
+\def\strc_floats_check_caption_content
+ {\ifnofloatcaption
+ \else
+ \setbox\b_strc_floats_caption\hbox
+ {\settrialtypesetting
+ \notesenabledfalse
+ \strc_floats_make_complete_caption}%
+ % new, \placefigure{\xmlfirst{#1}{somecaption}}{} passes earlier empty check
+ % so here we misuse the scratch box; actually this means that the previous
+ % test can go away (some day, when i redo this module)
+ \ifdim\wd\b_strc_floats_caption=\zeropoint
+ \global\emptyfloatcaptiontrue
+ \ifnofloatnumber
+ \global\nofloatcaptiontrue
+ \fi
+ \else
+ \global\emptyfloatcaptionfalse
+ \setbox\b_strc_floats_caption\hbox{\hskip\leftskip\box\b_strc_floats_caption}%
+ \fi
+ \fi}
+
+% The tricky part of getting float related two pass data is
+% that we should fetch is early but can only save it with
+% the composed float box; this determines the order: get it
+% before saving it.
+
+% We had this:
+%
+% \definetwopasslist{\s!float\s!data} \newcounter\noffloatdata
+%
+% \let\strc_float_realpage\realpageno % used for odd/even determination, can be combined with nodelocation
+%
+% \def\strc_float_save_data % \expanded ... will change in mkiv
+% {\doglobal\increment\noffloatdata
+% \lazysavetaggedtwopassdata{\s!float\s!data}{\noffloatdata}{\noffloatpages}{\noexpand\realfolio}}% later {}{}{}{} and \getfirst...
+%
+% \def\strc_float_load_data % precedes save !
+% {\doglobal\increment\noffloatpages
+% \findtwopassdata{\s!float\s!data}{\noffloatpages}%
+% \ifconditional\twopassdatafound
+% \globallet\strc_float_realpage\twopassdata
+% \else
+% \globallet\strc_float_realpage\realpageno % \realfolio
+% \fi}
+
+%D We can do this ...
+%D
+%D \starttyping
+%D \newcount\c_strc_floats_n
+%D
+%D \definedataset[\s!float][\c!delay=\v!yes]
+%D
+%D \let\strc_float_realpage\realpageno
+%D
+%D \def\strc_float_save_data
+%D {\setdataset[\s!float][\number\c_strc_floats_n][]}
+%D
+%D \def\strc_float_load_data % precedes save !
+%D {\global\advance\c_strc_floats_n\plusone
+%D \xdef\strc_float_realpage{\datasetvariable\s!float{\number\c_strc_floats_n}\s!page}%
+%D \ifx\strc_float_realpage\empty
+%D \globallet\strc_float_realpage\realpageno % \realfolio
+%D \fi}
+%D \stoptyping
+%D
+%D ... but this is more efficient:
+
+\definepagestate[\s!float][\c!delay=\v!yes]
+
+\newcount\c_strc_floats_n
+
+\let\strc_float_realpage\realpageno
+
+\def\strc_float_save_data
+ {\setpagestate[\s!float][\number\c_strc_floats_n]}
+
+\def\strc_float_load_data % precedes save !
+ {\global\advance\c_strc_floats_n\plusone
+ \xdef\strc_float_realpage{\pagestaterealpage\s!float{\number\c_strc_floats_n}}%
+ \ifx\strc_float_realpage\empty
+ \globallet\strc_float_realpage\realpageno % \realfolio
+ \fi}
+
+%D test case:
+%D
+%D \starttyping
+%D \setupfloat[figure][criterium=\marginwidth,fallback=bottom]
+%D \dorecurse{3}{
+%D \chapter{test}
+%D \placefigure[bottom]{1}{\framed{bottom}}
+%D test
+%D \placetable[bottom]{1}{\framed{table}}
+%D test
+%D \placetable{2}{\framed{table}}
+%D test
+%D \placefigure[left]{2}{\framed{left but way too wide}}
+%D \input tufte
+%D \placefigure[left]{3}{\framed{left but ok}}
+%D \input tufte }
+%D \stoptyping
+
+% A complication is that we may have to handle a pagebreak
+% first, which in turn may issue a (postponed) float.
+% Therefore we may not trust on variable assignments before
+% we're really dealing with the float. Some day I'll root out
+% the global settings.
+
+\def\strc_floats_set_current_tag#tag%
+ {\edef\currentfloat{#tag}%
+ \ifx\currentfloat\empty
+ \let\currentfloat\v!figure % a bit of a hack
+ \fi
+ \let\currentfloatcaption\currentfloat}
+
+\def\strc_floats_reset_variables
+ {\global\emptyfloatcaptionfalse
+ \global\nofloatcaptionfalse
+ \global\nofloatnumberfalse}
+
+% place
+
+\unexpanded\def\strc_floats_place#tag%
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \strc_floats_set_current_tag{#tag}%
+ \dodoubleempty\strc_floats_place_indeed}
+
+\def\strc_floats_place_indeed[#location][#reference]#caption%
+ {\strc_floats_reset_variables
+ \edef\floatlocation{#location}%
+ \ifx\floatlocation\empty
+ \edef\floatlocation{\floatparameter\c!default}% beware of a clash between alignment locations
+ \fi
+ \setupcurrentfloatcaption[\c!reference={#reference},\c!title={#caption},\c!marking=,\c!list=,\c!bookmark=]%
+ \doifinsetelse\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal}
+
+\unexpanded\def\placefloat
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \dotripleempty\strc_floats_place_float}
+
+\def\strc_floats_place_float[#tag]%
+ {\strc_floats_set_current_tag{#tag}%
+ \strc_floats_place_indeed}
+
+% start-stop
+
+\unexpanded\def\strc_floats_start_place#tag%
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \strc_floats_set_current_tag{#tag}%
+ \dosingleempty\strc_floats_start_place_indeed}
+
+\def\strc_floats_start_place_indeed[#settings]% tricky ... saved not ok yet
+ {\strc_floats_reset_variables
+ \edef\savedfloatlocation{\floatcaptionparameter\c!location}%
+ \setupcurrentfloatcaption[\c!location=,\c!reference=,\c!title=,\c!marking=,\c!list=,\c!bookmark=,#settings]%
+ \edef\floatlocation{\floatcaptionparameter\c!location}%
+ \setupcurrentfloatcaption[\c!location=\savedfloatlocation]%
+ \ifx\floatlocation\empty
+ \edef\floatlocation{\floatparameter\c!default}%
+ \fi
+ \doifinsetelse\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal
+ \bgroup
+ \ignorespaces}
+
+\unexpanded\def\strc_floats_stop_place
+ {\removeunwantedspaces
+ \egroup}
+
+\unexpanded\def\startplacefloat
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \dodoubleempty\strc_floats_start_place_float}
+
+\def\strc_floats_start_place_float[#tag]%
+ {\strc_floats_set_current_tag{#tag}%
+ \strc_floats_start_place_indeed}
+
+\let\stopplacefloat\strc_floats_stop_place
+
+% reserve
+
+\unexpanded\def\strc_floats_reserve#tag%
+ {\flushnotes
+ \page_otr_command_flush_side_floats % here !
+ \strc_floats_begin_group
+ \strc_floats_set_current_tag{#tag}%
+ \dotripleempty\strc_floats_reserve_indeed}
+
+\def\strc_floats_reserve_indeed[#settings][#location][#reference]#caption% maybe check for #settings
+ {\strc_floats_place_indeed[#location][#reference]{#caption}{\strc_floats_reserve_box{#settings}}}
+
+\def\strc_floats_reserve_box#settings%
+ {\begingroup
+ \setupcurrentfloat[\c!frame=\v!on,#settings]%
+ \inheritedfloatframed{}%
+ \endgroup}
+
+% text
+
+\unexpanded\def\strc_floats_start_text#tag%
+ {\flushnotes % Here indeed?
+ \page_otr_command_flush_side_floats % Here indeed?
+ \strc_floats_begin_text_group
+ \strc_floats_set_current_tag{#tag}%
+ \dodoubleempty\strc_floats_start_text_indeed}
+
+\def\strc_floats_start_text_indeed[#location][#reference]%
+ {\strc_floats_place_indeed[\v!text,#location,\v!left][#reference]}
+
+\unexpanded\def\strc_floats_stop_text
+ {\strc_floats_stop_text_indeed}
+
+% reserved text
+
+\unexpanded\def\strc_floats_start_reserve_text#tag%
+ {\flushnotes
+ \page_otr_command_flush_side_floats
+ \strc_floats_begin_text_group
+ \strc_floats_set_current_tag{#tag}%
+ \dotripleempty\strc_floats_start_reserve_text_indeed}
+
+\def\strc_floats_start_reserve_text_indeed[#settings][#location][#reference]#caption%
+ {\strc_floats_place_indeed[\v!text,#location,\v!left][#reference]{#caption}{\strc_floats_reserve_box{#settings}}}
+
+\unexpanded\def\strc_floats_stop_reserve_text
+ {\strc_floats_stop_text_indeed}
+
+% special hack
+
+\def\strc_floats_begin_group {\begingroup}
+\def\strc_floats_end_group {\carryoverpar\endgroup}
+\def\strc_floats_end_split_group {\endgroup}
+
+\def\strc_floats_begin_text_group {\begingroup\let\strc_floats_end_group\relax}
+\def\strc_floats_end_text_group {\endgroup}
+
+% implementation
+
+\ifdefined\page_margin_strc_floats_before \else \let\page_margin_strc_floats_before \relax \fi
+\ifdefined\page_margin_strc_floats_set_hsize \else \let\page_margin_strc_floats_set_hsize\relax \fi
+
+\def\flushfloatslist
+ {\v!left,\v!right,\v!inner,\v!outer,%
+ \v!backspace,\v!cutspace,%
+ \v!inleft,\v!inright,\v!inmargin,%
+ \v!leftmargin,\v!rightmargin,\v!leftedge,\v!rightedge,%
+ \v!innermargin,\v!outermargin,\v!inneredge,\v!outeredge,%
+ \v!text,\v!opposite}% \v!page
+
+\unexpanded\def\strc_floats_place_next_box_split
+ {\let\splitfloatfinalizer\strc_floats_end_split_group
+ \let\strc_floats_end_group\relax
+ \splitfloat{\strc_floats_place_next_box_normal}}
+
+\unexpanded\def\strc_floats_place_next_box_normal
+ {\ifsomefloatwaiting
+ % this was \checkwaitingfloats spread all over
+ \doifinsetelse\v!always\floatlocation
+ {\showmessage\m!floatblocks5\empty}
+ {\doifcommonelse\floatlocation\flushfloatslist\page_otr_command_flush_floats\donothing}%
+ % but which should be done before using box \floatbox
+ \fi
+ \page_margin_strc_floats_before % todo: each float handler gets a before
+ \global\insidefloattrue
+ \dostarttagged\t!float\currentfloat
+ \page_margin_strc_floats_set_hsize % todo: each float handler gets a set_hsize
+ \the\everyinsidefloat
+ \strc_floats_analyze_variables_one
+ \dostarttagged\t!floatcontent\empty
+ \dowithnextboxcontent
+ {\strc_floats_set_local_hsize
+ \floatparameter\c!inner
+ \postponenotes} % new
+ {\dostoptagged
+ \strc_floats_finish_placement}
+ \vbox}
+
+\def\strc_floats_finish_placement
+ {\doifsomething{\floatparameter\c!criterium}
+ {\ifdim\wd\nextbox>\floatparameter\c!criterium\relax
+ \edef\forcedfloatmethod{\floatparameter\c!fallback}%
+ \ifx\forcedfloatmethod\empty\let\forcedfloatmethod\v!here\fi
+ \fi}%
+ \strc_floats_check_extra_actions
+ \strc_floats_analyze_variables_two
+ \strc_floats_place_packaged_boxes
+ \dostoptagged % tricky ... needs checking
+ % we need to carry over the par because of side floats
+ \global\sidefloatdownshift \zeropoint
+ \global\sidefloatextrashift\zeropoint
+ \ifparfloat
+ \doifinset\v!reset\floatlocation\page_sides_forget_floats
+ \doinhibitblank
+ \fi
+ \strc_floats_end_group}
+
+\setnewconstant\textfloatmethod\zerocount % 0=raw 1=safe (.99) 2=tight (-1pt)
+\setnewconstant\floatrotation \zerocount % 0 90 180 270
+
+% nicer is a bunch of states and one loop that sets those states
+
+\def\strc_floats_analyze_variables_two
+ {\ifinsidecolumns
+ \global\parfloatfalse
+ \else
+ \doifcommonelse
+ {\floatlocation}
+ {\flushfloatslist}
+ {\global\parfloattrue}
+ {\global\parfloatfalse}%
+ \fi
+ \global\sidefloatshift\zeropoint
+ \global\sidefloatmaximum\zeropoint
+ \global\sidefloatmethod\floatparameter\c!sidemethod
+ \global\textfloatmethod\floatparameter\c!textmethod
+ \global\sidefloatalign\zerocount
+ \global\floatrotation\zerocount
+ \strc_floats_calculate_skips
+ \ifparfloat
+ \processaction
+ [\floatparameter\c!sidealign]
+ [\v!height=>\global\sidefloatalign\plusone,%
+ \v!line=>\global\sidefloatalign\plustwo,% (***)
+ \v!depth=>\global\sidefloatalign\plusthree,%
+ \v!grid=>\global\sidefloatalign\plusfour,%
+ \v!halfline=>\global\sidefloatalign\plusfive]%
+ \ifcase\sidefloatalign\relax % todo: optie v!lokaal => \else
+ \doifinset\v!height \floatlocation{\global\sidefloatalign\plusone}%
+ \doifinset\v!line \floatlocation{\global\sidefloatalign\plustwo}%
+ \doifinset\v!depth \floatlocation{\global\sidefloatalign\plusthree}%
+ \doifinset\v!grid \floatlocation{\global\sidefloatalign\plusfour}%
+ \doifinset\v!halfline\floatlocation{\global\sidefloatalign\plusfive}% meant for 'none'
+ \fi
+ \doifinset\v!high\floatlocation{\global\sidefloattopskip \zeropoint}%
+ \doifinset\v!low \floatlocation{\global\sidefloatbottomskip\zeropoint}%
+ \doifinset\v!fit \floatlocation
+ {\global\sidefloattopskip \zeropoint
+ \global\sidefloatbottomskip\zeropoint
+ \global\floatsideskip \zeropoint}%
+ \else
+ \processallactionsinset
+ [\floatlocation]
+ [ 90=>\global\floatrotation\commalistelement\relax,%
+ 180=>\global\floatrotation\commalistelement\relax,%
+ 270=>\global\floatrotation\commalistelement\relax]%
+ \fi
+ \doifinsetelse\v!nonumber\floatlocation
+ {\global\nofloatnumbertrue}
+ {\doifelse{\floatcaptionparameter\c!number}\v!yes
+ {\global\nofloatnumberfalse}
+ {\global\nofloatnumbertrue}}%
+ \doifinsetelse\v!none\floatlocation
+ {\global\nofloatcaptiontrue}
+ {\global\nofloatcaptionfalse}%
+ \doif{\floatcaptionparameter\c!number}\v!none % new
+ {\global\nofloatcaptiontrue}%
+ \ifemptyfloatcaption \ifnofloatnumber
+ \global\nofloatcaptiontrue
+ \fi \fi}
+
+% documenteren in details
+
+\def\strc_floats_analyze_variables_one
+ {\doifelse{\floatparameter\c!local}\v!yes % fout keyword
+ \globalcenterfloatboxtrue
+ \globalcenterfloatboxfalse
+ \ifglobalcenterfloatbox
+ \localcenterfloatboxtrue
+ \else
+ \doifinsetelse\v!local\floatlocation
+ \localcenterfloatboxtrue
+ \localcenterfloatboxfalse
+ \fi
+ \doifnotcommon{\v!always,\v!here,\v!force}\floatlocation % ! ! ! ! ! !
+ {\globalcenterfloatboxfalse
+ \localcenterfloatboxfalse}}
+
+\let\naturalfloatheight\!!zeropoint
+\let\naturalfloatwidth \!!zeropoint
+\let\naturalfloatdepth \!!zeropoint
+
+\def\strc_floats_set_natural_dimensions#box%
+ {\xdef\naturalfloatheight{\the\ht#box}%
+ \xdef\naturalfloatwidth {\the\wd#box}%
+ \xdef\naturalfloatdepth {\the\dp#box}}
+
+\def\doifelsemainfloatbody
+ {\ifinsidesplitfloat
+ \ifconditional\splitfloatfirstdone
+ \doubleexpandafter\secondoftwoarguments
+ \else
+ \doubleexpandafter\firstoftwoarguments
+ \fi
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+% todo: optional user pars
+
+\let\currentfloatattribute\empty % to be checked
+
+\def\floatcaptionattribute
+ {\iflocation
+ \ifnofloatnumber
+ \else
+ \ifnofloatcaption
+ \else
+ \ifinsidesplitfloat
+ \ifconditional\splitfloatfirstdone
+ \else
+ attr \destinationattribute \currentfloatattribute
+ \fi
+ \else
+ attr \destinationattribute \currentfloatattribute
+ \fi
+ \fi
+ \fi
+ \fi}
+
+\newconditional\usesamefloatnumber
+
+\def\strc_floats_place_packaged_boxes
+ {\bgroup
+ \ifconditional\usesamefloatnumber
+ \globallet\currentfloatnumber \previousfloatnumber
+ \globallet\currentfloatattribute \empty
+ \globallet\currentfloatsynchronize\relax
+ \else
+ \ifnofloatnumber \else \ifnofloatcaption \else
+ \strc_counters_increment{\strc_counters_the\currentfloat}%
+ \fi \fi
+ \strc_counters_register_component
+ {float}%
+ \setupcurrentfloatcaption
+ \floatcaptionparameter
+ \detokenizedfloatcaptionparameter
+ \relax
+ \relax
+ \relax
+ [\c!name=\currentfloat,%
+ \s!counter=\strc_counters_the\currentfloat,%
+ \s!hascaption=\ifnofloatcaption \v!no\else\v!yes\fi,%
+ \s!hasnumber=\ifnofloatnumber \v!no\else\v!yes\fi,%
+ \s!hastitle=\ifemptyfloatcaption\v!no\else\v!yes\fi]%
+ []%
+ \globallet\previousfloatnumber \m_strc_counters_last_registered_index
+ \globallet\currentfloatnumber \m_strc_counters_last_registered_index
+ \globallet\currentfloatattribute \m_strc_counters_last_registered_attribute
+ \globallet\currentfloatsynchronize\m_strc_counters_last_registered_synchronize
+ \fi
+ %
+ \global\setfalse\usesamefloatnumber % one shot
+ % check float box
+ \strc_floats_set_natural_dimensions\nextbox
+ \global\setbox\floatbox\vbox{\floatparameter\c!command{\box\nextbox}}%
+ \strc_floats_set_natural_dimensions\floatbox
+ \ifdim\htdp\floatbox=\zeropoint
+ \showmessage\m!floatblocks{11}\empty
+ \global\setbox\floatbox\vbox
+ {\dostarttagged\t!floatcontent\empty
+ \strc_floats_place_empty_box
+ \dostoptagged}%
+ \fi
+ % deal with lack of caption
+ \global\setbox\floatbox\vbox \floatcaptionattribute
+ {\doifelsemainfloatbody\currentfloatsynchronize\donothing
+ \unvbox\floatbox
+ \ifnofloatcaption
+ \vss
+ \fi}% gets rid of the depth (unless tabulate)
+ \egroup
+ % place the float
+ \strc_floats_set_box
+ \strc_floats_get_box
+ \global\insidefloatfalse}
+
+% \def\strc_floats_set_local_hsize
+% {\iflocalcenterfloatbox
+% \seteffectivehsize
+% \hsize\localhsize
+% \else
+% \doifinset\v!margin\floatlocation % brr, really needed! see wm will be redone
+% {\let\currentmarginblock\empty
+% \hsize\marginblockparameter\c!width}%
+% \fi}
+
+\newdimen\availablefloatwidth
+\newdimen\availablefloatheight
+
+\def\strc_floats_set_local_hsize
+ {\iflocalcenterfloatbox
+ % also available check here?
+ \seteffectivehsize
+ \hsize\localhsize
+ \else
+ \doifinset\v!margin\floatlocation % brr, really needed! see wm will be redone
+ {\hsize\namedmarginblockparameter\empty\c!width}%
+ \fi
+ \edef\p_availablewidth {\floatparameter\c!availablewidth }%
+ \edef\p_availableheight{\floatparameter\c!availableheight}%
+ \availablefloatwidth \ifx\p_availablewidth \empty\hsize\else\p_availablewidth \relax\fi
+ \availablefloatheight\ifx\p_availableheight\empty\vsize\else\p_availableheight\relax\fi}
+
+\ifdefined\everyinsidefloat \else \newevery \everyinsidefloat \relax \fi
+
+\appendtoks
+ \everyinsidefloat\emptytoks % in case it's called earlier
+ \strc_float_load_data
+\to \everyinsidefloat
+
+\def\doifrightpagefloatelse
+ {\ifdoublesided
+ \ifsinglesided
+ \doubleexpandafter\firstoftwoarguments
+ \else
+ \doubleexpandafter\doifoddfloatpageelse
+ \fi
+ \else
+ \expandafter\firstoftwoarguments
+ \fi}
+
+\def\doifoddfloatpageelse
+ {\ifodd\purenumber\strc_float_realpage\space
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+\appendtoks
+ \let\rightorleftpageaction\doifrightpagefloatelse
+\to \everyinsidefloat
+
+% \let\movesidefloat\gobbleoneargument
+
+% new : \place...[leftmargin,-2*line]; we need to catch fxtb:2*3
+% watch out: line alone aligns on the line ! ! !
+
+\unexpanded\def\movesidefloat[#settings]% (-)n*line|x=,y=
+ {\global\sidefloatdownshift \zeropoint
+ \global\sidefloatextrashift\zeropoint
+ \doifassignmentelse{#settings}%
+ {\begingroup
+ \setupcurrentfloat[\c!x=\zeropoint,\c!y=\zeropoint,#settings]%
+ \ifgridsnapping
+ \getnoflines{\floatparameter\c!y}%
+ \global\sidefloatdownshift\noflines\lineheight
+ \else
+ \global\sidefloatdownshift\floatparameter\c!y
+ \fi
+ \global\sidefloatextrashift\floatparameter\c!x
+ \endgroup}
+ {\movedownsidefloat[#settings]}}
+
+\installcorenamespace{floatmovement}
+
+\setvalue{\??floatmovement \v!line}{\strc_floats_move_down_line+}
+\setvalue{\??floatmovement+\v!line}{\strc_floats_move_down_line+}
+\setvalue{\??floatmovement-\v!line}{\strc_floats_move_down_line-}
+\setvalue{\??floatmovement \v!hang}{\strc_floats_move_down_hang\plusone}
+\setvalue{\??floatmovement+\v!hang}{\strc_floats_move_down_hang\plusone}
+\setvalue{\??floatmovement-\v!hang}{\strc_floats_move_down_hang\minusone}
+
+\def\strc_floats_move_down#setting%
+ {\csname\??floatmovement
+ \ifcsname\??floatmovement#setting\endcsname#setting\fi
+ \endcsname}
+
+\def\strc_floats_move_down_line#sign%
+ {\if!!donea \else
+ \global\sidefloatdownshift\zeropoint
+ \!!doneatrue
+ \fi
+ \global\advance\sidefloatdownshift#sign\lineheight}
+
+\def\strc_floats_move_down_hang#lines%
+ {\if!!doneb \else
+ \global\sidefloatsidelines\zerocount
+ \!!donebtrue
+ \fi
+ \global\advance\sidefloatsidelines#lines\relax}
+
+\unexpanded\def\movedownsidefloat[#settings]% already in core
+ {\doifnotinstring{:}{#settings}
+ {\begingroup
+ \!!doneafalse
+ \!!donebfalse
+ \normalexpanded{\dorepeatwithcommand[#settings]}\strc_floats_move_down
+ \endgroup}}
+
+\unexpanded\def\hangsidefloat[#number]%
+ {\global\sidefloatsidelines#number\relax}
+
+\def\strc_floats_set_extra_action#rightpagelocation#leftpagelocation%
+ {\rightorleftpageaction
+ {\let\extrafloatlocation#rightpagelocation}%
+ {\let\extrafloatlocation#leftpagelocation}}
+
+\installcorenamespace{extrafloataction}
+
+\setvalue{\??extrafloataction \v!inner}#1{\strc_floats_set_extra_action\v!left \v!right}
+\setvalue{\??extrafloataction \v!outer}#1{\strc_floats_set_extra_action\v!right \v!left}
+\setvalue{\??extrafloataction\v!innermargin}#1{\strc_floats_set_extra_action\v!leftmargin \v!rightmargin}
+\setvalue{\??extrafloataction\v!outermargin}#1{\strc_floats_set_extra_action\v!rightmargin\v!leftmargin}
+\setvalue{\??extrafloataction \v!inneredge}#1{\strc_floats_set_extra_action\v!leftedge \v!rightedge}
+\setvalue{\??extrafloataction \v!outeredge}#1{\strc_floats_set_extra_action\v!rightedge \v!leftedge}
+\setvalue{\??extrafloataction \v!backspace}#1{\strc_floats_set_extra_action\v!backspace \v!cutspace}
+\setvalue{\??extrafloataction \v!cutspace}#1{\strc_floats_set_extra_action\v!cutspace \v!backspace}
+%setvalue{\??extrafloataction \v!margin}#1{\strc_floats_set_extra_action\v!cutspace \v!backspace}
+\setvalue{\??extrafloataction \v!left}#1{\strc_floats_set_extra_action\v!left \v!left}
+\setvalue{\??extrafloataction \v!right}#1{\strc_floats_set_extra_action\v!right \v!right}
+\setvalue{\??extrafloataction \v!line}#1{} % only -n*line is handled (see ***)
+\setvalue{\??extrafloataction \s!unknown}#1{\movedownsidefloat[#1]}
+
+\def\strc_floats_check_extra_actions % less tracingthis way ...
+ {\doifnotinset\v!text\floatlocation % fuzzy, text overloads left, since then it's a directive
+ {\let\extrafloatlocation\empty
+ % \sidefloatdownshift will be reset afterwards, and can
+ % already be set at this point
+ \processcommacommand[\floatlocation]\strc_floats_check_extra_actions_step
+ \ifx\extrafloatlocation\empty \else
+ \edef\floatlocation{\extrafloatlocation,\floatlocation}%
+ \fi}}
+
+\def\strc_floats_check_extra_actions_step#step%
+ {\csname\??extrafloataction
+ \ifcsname\??extrafloataction#step\endcsname#step\else\s!unknown\fi
+ \endcsname{#step}}
+
+% pas op, maxbreedte niet instellen als plaats=links/rechts
+
+\def\strc_floats_set_local_dimensions
+ {\global\sidefloatshift \zeropoint % duplicate
+ \global\sidefloatmaximum\zeropoint\relax % duplicate
+ \ifdim\sidefloatdownshift=\zeropoint\else
+ \global\setbox\floatbox\vbox
+ {\vskip\sidefloatdownshift
+ \nointerlineskip
+ \box\floatbox}%
+ \fi
+ \edef\p_minwidth{\floatparameter\c!minwidth}%
+ \ifx\p_minwidth\empty
+ % nothing
+ \else
+ \scratchwidth\p_minwidth\relax
+ \ifdim\wd\floatbox<\scratchwidth
+ \strc_floats_realign_floatbox_horizontal_two
+ \fi
+ \fi
+ % we can also support edges .. in that case no common but a fast loop
+ \doifinsetelse\v!hanging\floatlocation
+ {\doifcommonelse{\v!inleft,\v!leftmargin}\floatlocation
+ {\let\p_maxwidth\leftmarginwidth}%
+ {\doifcommonelse{\v!inright,\v!rightmargin}\floatlocation
+ {\let\p_maxwidth\rightmarginwidth}%
+ {\edef\p_maxwidth{\floatparameter\c!maxwidth}}}}%
+ {\edef\p_maxwidth{\floatparameter\c!maxwidth}}%
+ \ifx\p_maxwidth\empty
+ % nothing
+ \else
+ \scratchwidth\p_maxwidth\relax
+ \ifdim\wd\floatbox>\scratchwidth
+ \doifcommonelse{\v!inright,\v!rightmargin,\v!rightedge,\v!inleft,\v!leftmargin,\v!leftedge}\floatlocation
+ {\global\sidefloatmaximum\scratchwidth}
+ {\doifcommonelse{\v!right,\v!left}\floatlocation
+ \strc_floats_realign_floatbox_horizontal_one
+ \strc_floats_realign_floatbox_horizontal_two}%
+ \fi
+ \fi}
+
+\def\strc_floats_realign_floatbox_horizontal_one
+ {\global\setbox\floatbox\hbox to \scratchwidth
+ {\doifnotinset\v!right\floatlocation\hss
+ \box\floatbox
+ \doifnotinset\v!left \floatlocation\hss}}
+
+\def\strc_floats_realign_floatbox_horizontal_two
+ {\global\setbox\floatbox\hbox to \scratchwidth
+ {\doifnot{\floatparameter\c!location}\v!left \hss
+ \box\floatbox
+ \doifnot{\floatparameter\c!location}\v!right\hss}}
+
+\unexpanded\def\placefloats
+ {\page_otr_command_flush_floats}
+
+\installinsertion\topins
+\installinsertion\botins
+
+\newdimen\botinserted
+\newdimen\topinserted
+
+\newif\iftestfloatbox
+
+\newdimen\floatsideskip \floatsideskip 12pt
+\newdimen\floattopskip \floattopskip \floattopskip
+\newdimen\floatbottomskip \floatbottomskip \floattopskip
+
+\newcount\noftopfloats \noftopfloats=2
+\newcount\nofbotfloats \nofbotfloats=0
+
+\def\strc_floats_calculate_skip#target#skip%
+ {\edef\askedfloatskip{#skip}%
+ \ifx\askedfloatskip\empty
+ \global#target\zeropoint
+ \else\ifx\askedfloatskip\v!none
+ \global#target\zeropoint
+ \else
+ \setbox\scratchbox\vbox{\whitespace\blank[\askedfloatskip]}% todo: move whitespace inside blank
+ \global#target\ht\scratchbox
+ \fi\fi}
+
+\def\strc_floats_calculate_skips
+ {\begingroup
+ \strc_floats_calculate_skip\floattopskip {\rootfloatparameter\c!spacebefore}%
+ \strc_floats_calculate_skip\floatbottomskip {\rootfloatparameter\c!spaceafter}%
+ \strc_floats_calculate_skip\sidefloattopskip {\rootfloatparameter\c!sidespacebefore}%
+ \strc_floats_calculate_skip\sidefloatbottomskip{\rootfloatparameter\c!sidespaceafter}%
+ \global\floatsideskip \rootfloatparameter\c!margin
+ \global\sidefloatleftshift \floatparameter\c!leftmargindistance
+ \global\sidefloatrightshift\floatparameter\c!rightmargindistance
+ \global\noftopfloats \rootfloatparameter\c!ntop\relax
+ \global\nofbotfloats \rootfloatparameter\c!nbottom\relax
+ \endgroup}
+
+% beter de laatste skip buiten de \insert uitvoeren,
+% bovendien bij volle flush onder baseline.
+
+% \def\betweenfloatblanko% assumes that spaceafter is present
+% {\bgroup
+% \setbox0\vbox{\strut\blank[\rootfloatparameter\c!spacebefore]\strut}%
+% \setbox2\vbox{\strut\blank[\rootfloatparameter\c!spaceafter]\strut}%
+% \ifdim\ht0>\ht2
+% \blank[-\rootfloatparameter\c!spaceafter,\rootfloatparameter\c!spacebefore]%
+% \fi
+% \egroup}
+
+\unexpanded\def\betweenfloatblanko% assumes that spaceafter is present
+ {\blank[\rootfloatparameter\c!spacebefore]} % or v!back,....
+
+\def\doplacefloatbox % used elsewhere
+ {%\forgetall % NO
+ \whitespace
+ \blank[\rootfloatparameter\c!spacebefore]
+ \page_otr_command_flush_float_box
+ \blank[\rootfloatparameter\c!spaceafter]}
+
+% test case:
+%
+% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=0.9\textheight,color=green]}
+% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=1.0\textheight,color=green]}
+% \placefigure[page,none]{}{\blackrule[width=\textwidth,height=1.1\textheight,color=green]}
+
+% the [#1] will go away
+
+\def\page_one_place_float_text % this macro should be defined elsewhere
+ {%\checkwaitingfloats\floatlocationmethod
+ % todo: check if #1 is indeed \floatlocation or maybe more
+ \global\floattextwidth\hsize
+ \global\floatwidth\wd\floatbox
+ \global\floatheight\ht\floatbox % forget about the depth
+ \global\advance\floattextwidth -\floatwidth
+ \global\advance\floattextwidth -\rootfloatparameter\c!margin\relax
+ \edef\floatlocation{\floatlocationmethod}% to be sure .. why
+ \doifinsetelse\v!tall\floatlocationmethod
+ {\floattextheight\pagegoal
+ \advance\floattextheight -\pagetotal
+ \advance\floattextheight -\bigskipamount % lelijk
+ \ifdim\floattextheight>\textheight
+ \floattextheight\textheight
+ \fi
+ \boxmaxdepth\zeropoint \relax % toegevoegd
+ \ifdim\floattextheight<\floatheight
+ \floattextheight\floatheight
+ \fi
+ \setbox\floattext\vbox to \floattextheight}
+ {\setbox\floattext\vbox}%
+ \bgroup
+ \forgetall
+ \setupblank
+ \setupwhitespace % new, also needed for footnotes
+ \blank[\v!disable]
+ \hsize\floattextwidth
+ \ignorespaces}
+
+\def\strc_floats_stop_text_indeed
+ {\egroup
+ \doifnotinset\v!tall\floatlocation
+ {\ifdim\ht\floattext<\floatheight
+ \floattextheight\floatheight
+ \else
+ \floattextheight\ht\floattext
+ \fi}%
+ \setbox\floatbox\vbox to \floattextheight
+ {\hsize\floatwidth
+ \doifinsetelse\v!both\floatlocation
+ {\doifinsetelse\v!low\floatlocation
+ {\vfill\box\floatbox}
+ {\doifinsetelse\v!middle\floatlocation
+ {\vfill\box\floatbox\vfill}
+ {\box\floatbox\vfill}}}
+ {\box\floatbox\vfill}}%
+ \setbox\floattext\vbox to \floattextheight
+ {\hsize\floattextwidth
+ \doifinsetelse\v!low\floatlocation
+ {\vfill
+ \box\floattext
+ \doifinset\c!offset\floatlocation{\whitespace\blank}}
+ {\doifinsetelse\v!middle\floatlocation
+ {\vfill
+ \box\floattext
+ \vfill}
+ {\doifinset\v!offset\floatlocation{\whitespace\blank}%
+ \box\floattext
+ \vfill}}}%
+ \doifinsetelse\v!right\floatlocation
+ {\setbox\floatbox\hbox to \hsize
+ {\box\floattext
+ \hfill
+ \box\floatbox}}
+ {\setbox\floatbox\hbox to \hsize
+ {\box\floatbox
+ \hfill
+ \box\floattext}}%
+ \baselinecorrection
+ \whitespace
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \doifnotinset\v!tall\floatlocation
+ {\dp\floatbox\openstrutdepth}% dp\strutbox}% % toegevoegd
+ \box\floatbox
+ \dostoptagged
+ \blank[\rootfloatparameter\c!spaceafter]%
+ \strc_floats_end_text_group
+ \doinsertfloatinfo}
+
+\def\borderedfloatbox
+ {\begingroup
+ \setupcurrentfloat[\c!location=\v!normal,\c!width=\v!fit,\c!height=\v!fit]%
+ \inheritedfloatframed{\box\floatbox}%
+ \endgroup}
+
+% minwidth=fit,width=max : no overshoot, as wide as graphic
+
+\def\strc_floats_align_content_indeed
+ {\alignstrutmode\zerocount
+ \doifnotcommon{\floatcaptionparameter\c!location}{\v!outermargin,\v!innermargin,\v!leftmargin,\v!rightmargin}
+ {\shiftalignedline
+ {\floatparameter\c!leftmargin }{\floatparameter\c!rightmargin}%
+ {\floatparameter\c!innermargin}{\floatparameter\c!outermargin}}%
+ \alignedline{\floatparameter\c!location}\v!middle}
+
+\def\strc_floats_align_caption_indeed
+ {\alignstrutmode\zerocount
+ \shiftalignedline
+ {\floatcaptionparameter\c!leftmargin }{\floatcaptionparameter\c!rightmargin}%
+ {\floatcaptionparameter\c!innermargin}{\floatcaptionparameter\c!outermargin}%
+ \alignedline{\floatparameter\c!location}\v!middle}
+
+\newdimen\d_strc_floats_content
+
+\def\strc_floats_set_page_variant
+ {\bgroup
+ \strc_floats_set_local_hsize
+ \ifcase\floatrotation\else
+ \swapdimens\hsize\vsize
+ \fi
+ \forgetall
+ \postponenotes
+ \dontcomplain
+ \setbox\b_strc_floats_content\vbox{\borderedfloatbox}%
+ \let\strc_floats_align_content\strc_floats_align_content_indeed
+ \let\strc_floats_align_caption\strc_floats_align_caption_indeed
+ \strc_floats_check_caption_content
+\d_strc_floats_content\wd\b_strc_floats_content
+ \ifcase\floatparameter\c!method
+ \or % automatic
+ \ifnofloatcaption
+ \strc_floats_prepare_no_caption
+ %\page_backgrounds_add_local_to_box\floatbox % was \doglobal but not needed
+ \else
+ % todo: installable maken, variant/method=auto vs macro
+ \strc_floats_prepare_page_caption
+ %\page_backgrounds_add_local_to_box\b_strc_floats_content
+ \setbox\b_strc_floats_caption\hbox
+ {\floatcaptionparameter\c!command{\box\b_strc_floats_caption}}%
+ \moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height
+ %\page_backgrounds_add_local_to_box\b_strc_floats_caption
+ \strc_floats_build_box
+ \fi
+ \or % semi automatic
+ \or % manual
+ \fi
+ \ifcase\floatrotation
+ \doifnotinset\v!margin\floatlocation % brr, really needed! see wm
+ {\postcenterfloatbox\d_strc_floats_content}%
+ \else
+ \global\setbox\floatbox\vbox
+ {\rotate[\c!rotation=\number\floatrotation]{\box\floatbox}}%
+ \fi
+ \egroup}
+
+\def\captionminwidth {15\bodyfontsize}
+\def\captionovershoot {2em}
+
+\def\strc_floats_prepare_no_caption
+ {\global\setbox\floatbox\vbox % pas op als wd groter dan hsize
+ {\ifinsidecolumns\ifdim\wd\b_strc_floats_content>\hsize
+ \let\strc_floats_align_content\relax
+ \fi\fi
+ \strc_floats_align_content{\copy\b_strc_floats_content}}}
+
+\def\strc_floats_prepare_page_caption
+ {\dostarttagged\t!floatcaption\empty
+ \doifinsetelse{\floatcaptionparameter\c!location}{\v!top,\v!bottom}
+ {\doifinsetelse{\floatcaptionparameter\c!width}{\v!fit,\v!max}
+ {\doifelse{\floatcaptionparameter\c!minwidth}\v!fit
+ {\doifelse{\floatcaptionparameter\c!width}\v!max
+ {\dopreparestackcaptionmax}
+ {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content % wider caption
+ \doifelse{\floatcaptionparameter\c!width}\v!fit
+ {\dopreparestackcaptionaut}
+ {\dopreparestackcaptionwid}%
+ \else
+ \dopreparestackcaptionmin
+ \fi}}
+ {\dopreparestackcaptionfix}}%
+ {\dopreparesidewidthcaption}}% new, special effects (see icare)
+ {\doifinsetelse{\floatcaptionparameter\c!width}{\v!fit,\v!max}
+ {\dopreparesideautocaption}
+ {\dopreparesidewidthcaption}}%
+ \dostoptagged}
+
+% makes sense if we preexpand more variables
+
+% \def\strc_floats_prepare_page_caption
+% {\edef\p_caption_location{\floatcaptionparameter\c!location}%
+% \edef\p_caption_width {\floatcaptionparameter\c!width}%
+% \edef\p_caption_minwidth{\floatcaptionparameter\c!minwidth}%
+% \edef\p_caption_align {\floatcaptionparameter\c!align}%
+% \dostarttagged\t!floatcaption\empty
+% \ifx\p_caption_location\v!top
+% \strc_floats_prepare_page_caption_top_bottom
+% \else\ifx\p_caption_location\v!bottom
+% \strc_floats_prepare_page_caption_top_bottom
+% \else\ifx\p_caption_width\v!fit
+% \dopreparesideautocaption
+% \else\ifx\p_caption_width\v!max
+% \dopreparesideautocaption
+% \else
+% \dopreparesidewidthcaption
+% \fi\fi\fi\fi
+% \dostoptagged}
+
+% \def\strc_floats_prepare_page_caption_top_bottom
+% {\ifx\p_caption_width\v!fit
+% \strc_floats_prepare_page_caption_top_bottom_fit_max
+% \else\ifx\p_caption_width\v!max
+% \strc_floats_prepare_page_caption_top_bottom_fit_max
+% \else
+% \dopreparesidewidthcaption % new, special effects (see icare)
+% \fi\fi}
+
+% \def\strc_floats_prepare_page_caption_top_bottom_fit_max
+% {\ifx\p_caption_minwidth\v!fit
+% \ifx\p_caption_width\v!max
+% \dopreparestackcaptionmax
+% \else\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content % wider caption
+% \ifx\p_caption_width\v!fit
+% \dopreparestackcaptionaut
+% \else
+% \dopreparestackcaptionwid
+% \fi
+% \else
+% \dopreparestackcaptionmin
+% \fi\fi
+% \else
+% \dopreparestackcaptionfix
+% \fi}
+
+% \def\dopreparestackcaptionmin
+% {\setbox\b_strc_floats_caption\vbox
+% {\strc_floats_caption_set_align
+% \hsize\wd\b_strc_floats_content
+% \ifx\p_caption_align\empty
+% \raggedcenter % on purpose overloads align !
+% \fi
+% \strc_floats_make_complete_caption}}
+
+\def\strc_floats_caption_set_align
+ {\normalexpanded{\setupalign[\v!reset,\floatcaptionparameter\c!align]}}
+
+\def\dopreparesideautocaption
+ {\scratchdimen\dimexpr\hsize-\wd\b_strc_floats_content-\floatparameter\c!margin\relax
+ \ifdim\wd\b_strc_floats_caption>\scratchdimen
+ \ifdim\wd\b_strc_floats_caption<1.3\scratchdimen
+ \scratchdimen0.8\scratchdimen
+ \fi
+ \fi
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\scratchdimen
+ \strc_floats_make_complete_caption}}
+
+\def\dopreparesidewidthcaption
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\floatcaptionparameter\c!width
+ \strc_floats_make_complete_caption}}
+
+\def\dopreparestackcaptionfix
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\floatcaptionparameter\c!minwidth % special effects
+ \strc_floats_make_complete_caption}}
+
+\def\dopreparestackcaptionmax
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}}
+
+\def\dopreparestackcaptionwid
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\floatcaptionparameter\c!width
+ \strc_floats_make_complete_caption}}
+
+\def\dopreparestackcaptionmin
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\wd\b_strc_floats_content
+ \doifnothing{\floatcaptionparameter\c!align}\raggedcenter % on purpose overloads align !
+ \strc_floats_make_complete_caption}}
+
+\def\dopreparestackcaptionaut
+ {\doifsomething{\floatcaptionparameter\c!align}
+ {\doifnotinset\v!middle{\floatcaptionparameter\c!align}%
+ {\let\captionovershoot\!!zeropoint}}%
+ \edef\captionhsize{\the\wd\b_strc_floats_content}%
+ \ifdim\captionhsize>\hsize
+ % float is wider than \hsize
+ \setbox\b_strc_floats_caption\vbox
+ {\settrialtypesetting
+ \strc_floats_caption_set_align
+ \hsize\captionhsize
+ \notesenabledfalse
+ \strc_floats_make_complete_caption}%
+ \ifdim\ht\scratchbox>\lineheight % more lines
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\captionhsize
+ \advance\hsize -\captionovershoot\relax
+ \ifdim\hsize<\captionminwidth\relax
+ \hsize\captionhsize
+ \fi
+ \strc_floats_make_complete_caption}%
+ \else
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\captionhsize
+ \strc_floats_make_complete_caption}%
+ \fi
+ \else
+ % float is smaller of equal to \hsize
+ \ifdim\captionhsize<\captionminwidth\relax
+ \scratchdimen\captionminwidth % float smaller than min width
+ \edef\captionhsize{\the\scratchdimen}%
+ \fi
+ \setbox\scratchbox\vbox % test with overshoot
+ {\settrialtypesetting
+ \scratchdimen\captionhsize
+ \advance\scratchdimen \captionovershoot
+ \advance\scratchdimen 3em % an average word length
+ \ifdim\scratchdimen<\hsize \hsize\scratchdimen \fi
+ \notesenabledfalse
+ \strc_floats_make_complete_caption}%
+ \ifdim\ht\scratchbox>\lineheight
+ % at least an average word longer than a line
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \scratchdimen\captionhsize
+ \advance\scratchdimen \captionovershoot
+ \ifdim\scratchdimen<\hsize \hsize\scratchdimen \fi
+ \strc_floats_make_complete_caption}%
+ \else
+ % just over a line, don't use an overshoot % % % todo: outer/inner and such
+ \doifcommonelse{\floatcaptionparameter\c!align}{\v!left,\v!right,\v!flushleft,\v!flushright}
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\captionhsize
+ % strange : \raggedcenter
+ \strc_floats_make_complete_caption}}
+ {% nicer
+ \setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\captionhsize
+ \doifnothing{\floatcaptionparameter\c!align}\raggedcenter% overloads
+ \strc_floats_make_complete_caption}}%
+ \fi
+ \fi}
+
+\newdimen\tempfloatheight
+\newdimen\tempfloatwidth
+
+\def\dofloatboxbetweenstack
+ {\endgraf\nointerlineskip\floatcaptionparameter\c!inbetween\endgraf}
+
+\def\dofloatboxdefaultbuilder % done
+ {\strc_floats_align_content{\box\b_strc_floats_content}}
+
+\def\dofloatboxnextrightbuilder#1%
+ {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi
+ {\tempfloatheight\ht\b_strc_floats_content
+ \box\b_strc_floats_content
+ \normalexpanded{\noexpand\doifnotinset{\v!hang}{\floatcaptionparameter\c!location}}{\dotfskip{\floatcaptionparameter\c!distance}}%
+ \vbox to\tempfloatheight{#1}}}
+
+\def\dofloatboxnextleftbuilder#1%
+ {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi
+ {\tempfloatheight\ht\b_strc_floats_content
+ \vbox to\tempfloatheight{#1}%
+ \normalexpanded{\noexpand\doifnotinset{\v!hang}{\floatcaptionparameter\c!location}}{\dotfskip{\floatcaptionparameter\c!distance}}%
+ \box\b_strc_floats_content}}
+
+\def\dofloatboxnextouterbuilder
+ {\doifrightpagefloatelse\dofloatboxnextrightbuilder\dofloatboxnextleftbuilder}
+
+\def\dofloatboxnextinnerbuilder
+ {\doifrightpagefloatelse\dofloatboxnextleftbuilder\dofloatboxnextrightbuilder}
+
+\def\dofloatboxnextrighthangbuilder#1%
+ {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi
+ {\tempfloatheight\ht\b_strc_floats_content
+ \box\b_strc_floats_content
+ \vbox to\tempfloatheight{#1}}}
+
+\def\dofloatboxnextlefthangbuilder#1%
+ {\ifparfloat \hbox \else \expandafter \strc_floats_align_content \fi
+ {\tempfloatheight\ht\b_strc_floats_content
+ \vbox to\tempfloatheight{#1}%
+ \box\b_strc_floats_content}}
+
+\def\dodofloatboxnextrightmarginbuilder#1#2%
+ {\ifparfloat
+ \hbox\bgroup
+ \tempfloatheight\ht\b_strc_floats_content
+ \box\b_strc_floats_content
+ \hsmash{\hskip#1\vbox to\tempfloatheight{#2}}%
+ \egroup
+ \else
+ \begingroup
+ \tempfloatheight\ht\b_strc_floats_content
+ \everyrightofalignedline{\hsmash{\hskip#1\vbox to\tempfloatheight{#2}}}%
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \endgroup
+ \fi}
+
+\def\dodofloatboxnextleftmarginbuilder#1#2%
+ {\ifparfloat
+ \hbox\bgroup
+ \tempfloatheight\ht\b_strc_floats_content
+ \hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\tempfloatheight{#2}}%
+ \box\b_strc_floats_content
+ \egroup
+ \else
+ \begingroup
+ \tempfloatheight\ht\b_strc_floats_content
+ \everyleftofalignedline{\hsmash{\hskip-\dimexpr#1+\wd\b_strc_floats_caption\relax\vbox to\tempfloatheight{#2}}}%
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \endgroup
+ \fi}
+
+\def\dofloatboxnextrightmarginbuilder{\dodofloatboxnextrightmarginbuilder\rightmargindistance}
+\def\dofloatboxnextleftmarginbuilder {\dodofloatboxnextleftmarginbuilder \leftmargindistance }
+
+\def\dofloatboxnextoutermarginbuilder
+ {\doifrightpagefloatelse
+ {\dodofloatboxnextrightmarginbuilder\rightmargindistance}
+ {\dodofloatboxnextleftmarginbuilder \rightmargindistance}}
+
+\def\dofloatboxnextinnermarginbuilder
+ {\doifrightpagefloatelse
+ {\dodofloatboxnextleftmarginbuilder \leftmargindistance}
+ {\dodofloatboxnextrightmarginbuilder\leftmargindistance}}
+
+\def\dofloatboxnextbuilder % beware, we first check on left/rightmargin because there can be left/right also
+ {\let\next\dofloatboxnextleftbuilder
+ \normalexpanded{\noexpand\processallactionsinset[\floatcaptionparameter\c!location]}
+ [ \v!outermargin=>\let\next\dofloatboxnextoutermarginbuilder,
+ \v!innermargin=>\let\next\dofloatboxnextinnermarginbuilder,
+ \v!leftmargin=>\let\next\dofloatboxnextleftmarginbuilder,
+ \v!rightmargin=>\let\next\dofloatboxnextrightmarginbuilder,
+ \v!lefthanging=>\let\next\dofloatboxnextlefthangbuilder,
+ \v!righthanging=>\let\next\dofloatboxnextrighthangbuilder,
+ \v!outer=>\let\next\dofloatboxnextouterbuilder,
+ \v!inner=>\let\next\dofloatboxnextinnerbuilder,
+ \v!left=>\let\next\dofloatboxnextleftbuilder,
+ \v!right=>\let\next\dofloatboxnextrightbuilder]%
+ \next}
+
+\def\dofloatboxsidebuilder
+ {\ifparfloat
+ \let\next\dofloatboxhighbuilder
+ \else
+ \let\next\dofloatboxmiddlebuilder
+ \expanded{\processallactionsinset[\floatcaptionparameter\c!location]}
+ [ \v!low=>\let\next\dofloatboxlowbuilder,
+ \v!middle=>\let\next\dofloatboxmiddlebuilder,
+ \v!high=>\let\next\dofloatboxhighbuilder]%
+ \fi
+ \next}
+
+\def\doflushfloatleftcaptionhang
+ {\hsmash{\llap{\box\b_strc_floats_caption\dotfskip{\floatcaptionparameter\c!distance}}}}
+
+\def\doflushfloatrightcaptionhang
+ {\hsmash{\rlap{\dotfskip{\floatcaptionparameter\c!distance}\box\b_strc_floats_caption}}}
+
+\def\doflushfloatcaptionhang % expanded can go
+ {\expanded{\doifinsetelse{\v!righthanging}{\floatcaptionparameter\c!location}}
+ {\doflushfloatrightcaptionhang}
+ {\expanded{\doifinsetelse{\v!lefthanging}{\floatcaptionparameter\c!location}}
+ {\doflushfloatleftcaptionhang}
+ {\expanded{\doifinsetelse{\v!hang}{\floatcaptionparameter\c!location}}
+ {\expanded{\doifinsetelse{\v!outer}{\floatcaptionparameter\c!location}}
+ {\doifrightpagefloatelse{\doflushfloatrightcaptionhang}{\doflushfloatleftcaptionhang}}
+ {\expanded{\doifinsetelse{\v!right}{\floatcaptiondirectives}}
+ {\doflushfloatrightcaptionhang}
+ {\doflushfloatleftcaptionhang}}}
+ {\box\b_strc_floats_caption}}}}
+
+\def\dofloatboxhighbuilder
+ {\dofloatboxnextbuilder{\dofloatboxbetweenstack\doflushfloatcaptionhang\vfill}}
+
+\def\dofloatboxlowbuilder
+ {\dofloatboxnextbuilder{\vfill\doflushfloatcaptionhang\dofloatboxbetweenstack}}
+
+\def\dofloatboxmiddlebuilder
+ {\dofloatboxnextbuilder{\vfill\box\b_strc_floats_caption\vfill}}
+
+% \definefloat
+% [lefty][lefties][figure]
+% \setupfloat
+% [lefty]
+% [default=left,
+% rightmargindistance=-2cm,
+% leftmargindistance=-2cm]
+% \setupcaption
+% [lefty]
+% [location={bottom,overlay}]
+%
+% \starttext
+% \placelefty{}{} \input tufte \input tufte
+% \placelefty{}{} \input tufte \input tufte
+% \stoptext
+
+\def\bothangfloat#1{\ruledvbox to \ht\b_strc_floats_content{#1\vss}}
+\def\tophangfloat#1{\ruledvbox to \ht\b_strc_floats_content{\vss#1}}
+
+\def\dofloatboxnormaltopstackbuilder
+ {\expanded{\doifinset{\v!overlay}{\floatcaptionparameter\c!location}}\tophangfloat
+ {\tempfloatwidth\wd\b_strc_floats_content
+ \ifparfloat
+ \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
+ \dofloatboxbetweenstack
+ \hbox{\hbox{\box\b_strc_floats_content}}%
+ \else
+ \page_otr_command_set_float_hsize
+ \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}
+ \dofloatboxbetweenstack
+ \hbox{\strc_floats_align_content{\box\b_strc_floats_content}}%
+ \fi}}
+
+\def\dofloatboxnormalbotstackbuilder
+ {\expanded{\doifinset{\v!overlay}{\floatcaptionparameter\c!location}}\bothangfloat
+ {\tempfloatwidth\wd\b_strc_floats_content
+ \ifparfloat
+ \hbox{\hbox{\box\b_strc_floats_content}}%
+ \dofloatboxbetweenstack
+ \hbox{\strc_floats_locate_side_float{\box\b_strc_floats_caption}}%
+ \else
+ \page_otr_command_set_float_hsize
+ \hbox{\strc_floats_align_content{\box\b_strc_floats_content}}%
+ \dofloatboxbetweenstack
+ \hbox{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}%
+ \fi}}
+
+\def\dofloatboxgridtopstackbuilder
+ {\dp\b_strc_floats_caption\strutdepth
+ \setbox\scratchbox\vbox
+ {\tempfloatwidth\wd\b_strc_floats_content
+ \ifparfloat
+ \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
+ \vss\dofloatboxbetweenstack
+ \hbox{\box\b_strc_floats_content}%
+ \else
+ \page_otr_command_set_float_hsize
+ \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
+ \vss\dofloatboxbetweenstack
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \fi}%
+ \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
+ \vbox to \noflines\lineheight{\unvbox\scratchbox}}
+
+\def\dofloatboxgridbotstackbuilder
+ {\dp\b_strc_floats_caption\strutdepth
+ \setbox\scratchbox\vbox
+ {\tempfloatwidth\wd\b_strc_floats_content
+ \ifparfloat
+ \hbox{\box\b_strc_floats_content}%
+ \vss\dofloatboxbetweenstack
+ \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
+ \else
+ \page_otr_command_set_float_hsize
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \vss\dofloatboxbetweenstack
+ \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
+ \fi}%
+ \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
+ \vbox to \noflines\lineheight{\unvbox\scratchbox}}
+
+\def\dofloatboxstretchtopstackbuilder
+ {\dp\b_strc_floats_caption\strutdepth
+ \setbox\scratchbox\vbox
+ {\strc_floats_align_caption{\copy\b_strc_floats_caption}%
+ \strc_floats_align_content {\copy\b_strc_floats_content }}%
+ \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
+ \vbox to \noflines\lineheight
+ {\tempfloatwidth\wd\b_strc_floats_content
+ \ifparfloat
+ \strc_floats_locate_side_float{\box\b_strc_floats_caption}%
+ \vss\dofloatboxbetweenstack\vss
+ \hbox{\box\b_strc_floats_content}%
+ \else
+ \page_otr_command_set_float_hsize
+ \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
+ \vss\dofloatboxbetweenstack\vss
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \fi}}
+
+\def\dofloatboxstretchbotstackbuilder
+ {\dp\b_strc_floats_caption\strutdepth
+ \setbox\scratchbox\vbox
+ {\strc_floats_align_content{\copy\b_strc_floats_content }%
+ \strc_floats_align_caption{\copy\b_strc_floats_caption}}%
+ \getnoflines{\dimexpr\htdp\scratchbox-10\scaledpoint\relax}% get rid of inaccuracy
+ \vbox to \noflines\lineheight
+ {\tempfloatwidth\wd\b_strc_floats_content
+ \ifparfloat
+ \hbox{\box\b_strc_floats_content}%
+ \vss\dofloatboxbetweenstack\vss
+ \strc_floats_locate_side_float{\box\b_strc_floats_caption}
+ \else
+ \page_otr_command_set_float_hsize
+ \strc_floats_align_content{\box\b_strc_floats_content}%
+ \vss\dofloatboxbetweenstack\vss
+ \strc_floats_locate_text_float{\box\b_strc_floats_caption}%
+ \fi}}
+
+\def\dofloatboxtopbuilder
+ {\let\next\dofloatboxnormaltopstackbuilder
+ \expanded{\processfirstactioninset[\floatcaptionparameter\c!location]}
+ [ \v!grid=>\let\next\dofloatboxgridstackbuilder,
+ \v!stretch=>\let\next\dofloatboxstretchstackbuilder]%
+ \next}
+
+\def\dofloatboxbottombuilder
+ {\let\next\dofloatboxnormalbotstackbuilder
+ \expanded{\processfirstactioninset[\floatcaptionparameter\c!location]}
+ [ \v!grid=>\let\next\dofloatboxgridstackbuilder,
+ \v!stretch=>\let\next\dofloatboxstretchstackbuilder]%
+ \next}
+
+\def\relocatecaptionright#1{\strc_floats_align_caption{\hbox to \tempfloatwidth{\hss#1}}}
+\def\relocatecaptionleft #1{\strc_floats_align_caption{\hbox to \tempfloatwidth{#1\hss}}}
+
+\unexpanded\def\installfloatboxbuilder#1#2{\setvalue{\??floatbuilder#1}{#2}}
+
+\def\strc_floats_build_box
+ {\global\setbox\floatbox\vbox
+ {\strc_floats_set_local_hsize
+ \forgetall
+ \let\floatcaptionarrangement\s!default
+ \def\docommand##1%
+ {\doifdefined{\??floatbuilder##1}{\def\floatcaptionarrangement{##1}\quitcommalist}}%
+ \processcommacommand[\floatcaptionparameter\c!location]\docommand
+ \executeifdefined{\??floatbuilder\floatcaptionarrangement}{\getvalue{\??floatbuilder\s!default}}}}
+
+\def\strc_floats_locate_text_float
+ {\let\next\strc_floats_align_caption
+ \expanded{\processallactionsinset[\floatcaptionparameter\c!location]}
+ [ \v!left=>\let\next\relocatecaptionleft,
+ \v!right=>\let\next\relocatecaptionright,
+ \v!inner=>\doifrightpagefloatelse{\let\next\relocatecaptionleft }{\let\next\relocatecaptionright},
+ \v!outer=>\doifrightpagefloatelse{\let\next\relocatecaptionright}{\let\next\relocatecaptionleft }]%
+ \next}
+
+\installfloatboxbuilder \v!none \dofloatboxdefaultbuilder
+\installfloatboxbuilder \s!default \dofloatboxdefaultbuilder
+\installfloatboxbuilder \v!high \dofloatboxhighbuilder
+\installfloatboxbuilder \v!low \dofloatboxlowbuilder
+\installfloatboxbuilder \v!middle \dofloatboxmiddlebuilder
+
+\installfloatboxbuilder \v!left \dofloatboxsidebuilder
+\installfloatboxbuilder \v!right \dofloatboxsidebuilder
+
+\installfloatboxbuilder \v!top \dofloatboxtopbuilder
+\installfloatboxbuilder \v!bottom \dofloatboxbottombuilder
+
+% \setuplayout[grid=yes] \showgrid \setupcaptions[style=smallbodyfont,location=grid,inbetween=]
+%
+% \starttext
+% test \placefigure{} {\externalfigure[cow.pdf][frame=on,grid=yes]} test \page
+% test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=yes]} test \page
+% test \placefigure{} {\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
+% test \placefigure{\input zapf\relax}{\externalfigure[cow.pdf][frame=on,grid=depth]} test \page
+% \stoptext
+
+\newif\ifpostponecolumnfloats \postponecolumnfloatsfalse % don't change
+
+\setnewconstant\postcenterfloatmethod\plusone
+
+\def\postcenterfloatbox#1%
+ {\scratchdimen
+ \ifcase\postcenterfloatmethod
+ #1% \wd\floatbox
+ \or\ifinsidecolumns
+ \ifpostponecolumnfloats\makeupwidth\else#1\fi
+ \else\ifdim#1>\hsize
+ \hsize
+ \else
+ \wd\floatbox
+ \fi\fi\fi
+ \global\setbox\floatbox\hbox to \scratchdimen
+ % {\hfill\box\floatbox\hfill}} % geen \hss, gaat mis in kolommen !
+ % {\hss \box\floatbox\hss }} % wel \hss, anders mis in colset
+ {\ifglobalcenterfloatbox
+ \donetrue
+ \else\iflocalcenterfloatbox
+ \donetrue
+ \else
+ \donefalse
+ \fi\fi
+ \ifdim\scratchdimen>\effectivehsize
+ \donefalse
+ \fi
+ \hss\ifdone\hskip\effectiveleftskip\fi
+ \box\floatbox
+ \ifdone\hskip\effectiverightskip\fi\hss}}
+
+\def\strc_floats_set_paragraph_variant
+ {\bgroup
+ \forgetall
+ \postponenotes
+ \dontcomplain
+ %\showcomposition
+ \setbox\b_strc_floats_content\vbox{\borderedfloatbox}%
+ %\page_backgrounds_add_local_to_box\b_strc_floats_content
+ \ifnofloatcaption
+ \global\setbox\floatbox\vbox{\box\b_strc_floats_content}%
+ \else
+ \strc_floats_check_caption_content
+ \strc_floats_prepare_side_caption
+ \setbox\b_strc_floats_caption\hbox{\floatcaptionparameter\c!command{\box\b_strc_floats_caption}}%
+ \moveboxontogrid\b_strc_floats_caption{\floatcaptionparameter\c!grid}\d_strc_floats_caption_height
+ %\page_backgrounds_add_local_to_box\b_strc_floats_caption
+ \strc_floats_build_side_box
+ \fi
+ \egroup}
+
+\def\strc_floats_prepare_side_caption
+ {\dostarttagged\t!floatcaption\empty
+ \doifelse{\floatcaptionparameter\c!width}\v!max
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}}%
+ {\doifelse{\floatcaptionparameter\c!width}\v!fit
+ {\ifdim\wd\b_strc_floats_caption>\wd\b_strc_floats_content\relax
+ \setbox\b_strc_floats_caption\vbox
+ {\forgetall % needed?
+ \hsize\wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}%
+ \else
+ \setbox\b_strc_floats_caption\hbox to \wd\b_strc_floats_content
+ {\hss\hbox{\strc_floats_make_complete_caption}\hss}%
+ \fi}
+ {\setbox\b_strc_floats_caption\vbox
+ {\strc_floats_caption_set_align
+ \hsize\floatcaptionparameter\c!width % \wd\b_strc_floats_content
+ \strc_floats_make_complete_caption}}}%
+ \dostoptagged}
+
+\def\strc_floats_locate_side_float#1%
+ {\begingroup
+ \alignstrutmode\zerocount
+ \hsize\tempfloatwidth \forgetall
+ \alignedline{\floatparameter\c!location}\v!middle{#1}%
+ \endgroup}
+
+\def\strc_floats_build_side_box
+ {\let\strc_floats_align_content\relax
+ \let\strc_floats_align_caption\relax
+ \strc_floats_build_box}
+
+\newif\ifparfloat
+
+\def\strc_floats_set_box % todo : \global\setbox, currently messy
+ {\ifvisible
+ \par
+ \edef\floatcaptiondirectives{\floatparameter\c!location,\floatcaptionparameter\c!location}%
+ \ifparfloat
+ \strc_floats_set_paragraph_variant
+ \else
+ \strc_floats_set_page_variant
+ \fi
+ \strc_floats_set_local_dimensions
+ \global\advance\totalnoffloats\plusone
+ \setbox\floatbox\hbox{\strc_float_save_data\box\floatbox}% still needed? we will do renumbering differently
+ \global\floatheight\htdp\floatbox
+ \global\floatwidth\wd\floatbox
+ \doifnotinset\v!margin\floatlocation % gaat namelijk nog fout
+ {\setbox\floatbox\vbox
+ {\parindent\zeropoint
+ \box\floatbox}}%
+ \wd\floatbox\floatwidth
+ \ifdim\dimexpr\floatheight+\lineheight\relax<\textheight \else
+ \global\floatheight\dimexpr\textheight-\lineheight\relax
+ \ht\floatbox\floatheight
+ \dp\floatbox\zeropoint
+ \showmessage\m!floatblocks{10}{\the\totalnoffloats}%
+ \fi
+ \fi}
+
+\newcounter\noxfloatlocations
+
+% \def\dooutput{\sidefloatoutput} % redefinition of \dooutput
+
+\definefloat
+ [\v!figure]
+ [\v!figures]
+
+\definefloat
+ [\v!table]
+ [\v!tables]
+
+\setupfloat
+ [\v!table]
+ [\c!frame=\v!off]
+
+\definefloat
+ [\v!intermezzo]
+ [\v!intermezzi]
+
+\definefloat
+ [\v!graphic]
+ [\v!graphics]
+
+% float strategy, replaces some of the above macros
+
+\installcorenamespace{floatmethods}
+
+\let\floatmethod \empty
+\let\floatlabel \empty
+\let\floatcolumn \empty
+\let\floatrow \empty
+\let\forcedfloatmethod\empty
+
+\def\setfloatmethodvariables#1% \floatmethod \floatlabel \floatrow \floatcolumn
+ {\ctxcommand{analysefloatmethod("#1")}}
+
+\def\somesomewherefloat[#1]%
+ {\dofloatssavesomewherefloat\s!somewhere{#1}}
+
+\def\strc_floats_get_box
+ {\ifvisible
+ \let\floatlabel \empty
+ \let\floatcolumn\empty
+ \let\floatrow \empty
+ \setfloatmethodvariables\floatlocation
+ % todo: nog algemeen otr
+ \ifdefined\OTRSETsetpreferedcolumnslot
+ \OTRSETsetpreferedcolumnslot\floatcolumn\floatrow
+ \fi
+ \ifcsname\??floatmethods\currentoutputroutine:\floatmethod\endcsname \else
+ \let\floatmethod\v!here
+ \fi
+ \ifx\forcedfloatmethod\empty \else
+ \let\floatmethod\forcedfloatmethod
+ \fi
+ % [] will go
+ \edef\floatlocationmethod{\floatmethod,\floatlocation}%
+ \csname\??floatmethods\currentoutputroutine:\floatmethod\endcsname
+ \fi}
+
+\installcorenamespace{floatsettings}
+
+\unexpanded\def\installfloatmethod#1#2#3% routine keyword handler
+ {\setvalue{\??floatmethods#1:#2}{#3}}
+
+\unexpanded\def\handlefloatmethod#1%
+ {\csname\??floatmethods\currentoutputroutine:#1\endcsname}
+
+% \unexpanded\def\installfloatmethod#1#2#3% routine keyword handler
+% {\ifcsname\??floatsettings#1:#2\endcsname \else
+% \expandafter\newtoks\csname\??floatsettings#1:#2\endcsname
+% \fi
+% \setvalue{\??floatmethods#1:#2}{#3}}
+%
+% \unexpanded\def\startfloatmethodsettings#1#2 #3\stopfloatmethodsettings
+% {\csname\??floatsettings#1:#2\endcsname\expandafter{\the\csname\??floatsettings#1:#2\endcsname#3}}
+%
+% \let\stopfloatmethodsettings\relax
+%
+% \unexpanded\def\applyfloatmethodsettings#1#2{\the\??floatsettings#1:#2\endcsname}
+
+\definesystemconstant{tblr}
+\definesystemconstant{lrtb}
+\definesystemconstant{tbrl}
+\definesystemconstant{rltb}
+\definesystemconstant{btlr}
+\definesystemconstant{lrbt}
+\definesystemconstant{btrl}
+\definesystemconstant{rlbt}
+\definesystemconstant{fxtb}
+\definesystemconstant{fxbt}
+\definesystemconstant{fixd}
+
+\installfloatmethod \s!singlecolumn \v!here \page_one_place_float_here
+\installfloatmethod \s!singlecolumn \v!force \page_one_place_float_force
+\installfloatmethod \s!singlecolumn \v!left \page_one_place_float_left
+\installfloatmethod \s!singlecolumn \v!right \page_one_place_float_right
+\installfloatmethod \s!singlecolumn \v!text \page_one_place_float_text
+\installfloatmethod \s!singlecolumn \v!top \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \v!bottom \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \v!auto \page_one_place_float_auto
+\installfloatmethod \s!singlecolumn \v!margin \page_one_place_float_margin
+\installfloatmethod \s!singlecolumn \v!opposite \page_one_place_float_face
+\installfloatmethod \s!singlecolumn \v!page \page_one_place_float_page
+\installfloatmethod \s!singlecolumn \v!leftpage \page_one_place_float_leftpage
+\installfloatmethod \s!singlecolumn \v!rightpage \page_one_place_float_rightpage
+\installfloatmethod \s!singlecolumn \v!inmargin \page_one_place_float_inmargin
+\installfloatmethod \s!singlecolumn \v!inleft \page_one_place_float_leftmargin
+\installfloatmethod \s!singlecolumn \v!inright \page_one_place_float_rightmargin
+\installfloatmethod \s!singlecolumn \v!leftmargin \page_one_place_float_leftmargin
+\installfloatmethod \s!singlecolumn \v!rightmargin \page_one_place_float_rightmargin
+\installfloatmethod \s!singlecolumn \v!leftedge \page_one_place_float_leftedge
+\installfloatmethod \s!singlecolumn \v!rightedge \page_one_place_float_rightedge
+\installfloatmethod \s!singlecolumn \v!somewhere \page_one_place_float_somewhere
+\installfloatmethod \s!singlecolumn \v!backspace \page_one_place_float_backspace
+\installfloatmethod \s!singlecolumn \v!cutspace \page_one_place_float_cutspace
+\installfloatmethod \s!singlecolumn \s!tblr \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!lrtb \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!tbrl \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!fxtb \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!rltb \page_one_place_float_top
+\installfloatmethod \s!singlecolumn \s!btlr \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!lrbt \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!btrl \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!rlbt \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!fxbt \page_one_place_float_bottom
+\installfloatmethod \s!singlecolumn \s!fixd \page_one_place_float_force
+
+\installfloatmethod \s!multicolumn \v!here \page_mul_place_float_here
+\installfloatmethod \s!multicolumn \v!force \page_mul_place_float_force
+%installfloatmethod \s!multicolumn \v!left
+%installfloatmethod \s!multicolumn \v!right
+%installfloatmethod \s!multicolumn \v!text
+\installfloatmethod \s!multicolumn \v!top \page_mul_place_float_top
+\installfloatmethod \s!multicolumn \v!bottom \page_mul_place_float_bottom
+%installfloatmethod \s!multicolumn \v!auto
+%installfloatmethod \s!multicolumn \v!margin
+%installfloatmethod \s!multicolumn \v!opposite
+%installfloatmethod \s!multicolumn \v!page
+%installfloatmethod \s!multicolumn \v!leftpage
+%installfloatmethod \s!multicolumn \v!rightpage
+%installfloatmethod \s!multicolumn \v!inmargin
+%installfloatmethod \s!multicolumn \v!inleft
+%installfloatmethod \s!multicolumn \v!inright
+%installfloatmethod \s!multicolumn \v!leftmargin
+%installfloatmethod \s!multicolumn \v!rightmargin
+%installfloatmethod \s!multicolumn \v!leftedge
+%installfloatmethod \s!multicolumn \v!rightedge
+%installfloatmethod \s!multicolumn \v!somewhere
+%installfloatmethod \s!multicolumn \v!backspace
+%installfloatmethod \s!multicolumn \v!cutspace
+%installfloatmethod \s!multicolumn \s!tblr
+%installfloatmethod \s!multicolumn \s!lrtb
+%installfloatmethod \s!multicolumn \s!tbrl
+%installfloatmethod \s!multicolumn \s!rltb
+%installfloatmethod \s!multicolumn \s!fxtb
+%installfloatmethod \s!multicolumn \s!btlr
+%installfloatmethod \s!multicolumn \s!lrbt
+%installfloatmethod \s!multicolumn \s!btrl
+%installfloatmethod \s!multicolumn \s!rlbt
+%installfloatmethod \s!multicolumn \s!fxbt
+%installfloatmethod \s!multicolumn \s!fixd
+
+\installfloatmethod \s!columnset \v!here \page_set_place_float_here
+\installfloatmethod \s!columnset \v!force \page_set_place_float_force
+%installfloatmethod \s!columnset \v!left
+%installfloatmethod \s!columnset \v!right
+%installfloatmethod \s!columnset \v!text
+\installfloatmethod \s!columnset \v!top \page_set_place_float_top
+\installfloatmethod \s!columnset \v!bottom \page_set_place_float_bottom
+%installfloatmethod \s!columnset \v!auto
+%installfloatmethod \s!columnset \v!margin
+%installfloatmethod \s!columnset \v!opposite
+\installfloatmethod \s!columnset \v!page \page_set_place_float_page
+%installfloatmethod \s!columnset \v!leftpage
+%installfloatmethod \s!columnset \v!rightpage
+%installfloatmethod \s!columnset \v!inmargin
+%installfloatmethod \s!columnset \v!inleft
+%installfloatmethod \s!columnset \v!inright
+%installfloatmethod \s!columnset \v!leftmargin
+%installfloatmethod \s!columnset \v!rightmargin
+%installfloatmethod \s!columnset \v!leftedge
+%installfloatmethod \s!columnset \v!rightedge
+%installfloatmethod \s!columnset \v!somewhere
+%installfloatmethod \s!columnset \v!backspace
+%installfloatmethod \s!columnset \v!cutspace
+\installfloatmethod \s!columnset \s!tblr \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!lrtb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!tbrl \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!rltb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fxtb \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!btlr \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!lrbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!btrl \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!rlbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fxbt \page_set_place_float_slot
+\installfloatmethod \s!columnset \s!fixd \page_set_place_float_force
+
+%D Local floats:
+
+\def\setuplocalfloats
+ {\getparameters[\??lf]}
+
+\setuplocalfloats
+ [%\c!before=\blank,
+ %\c!after=\blank,
+ \c!inbetween=\blank]
+
+\initializeboxstack{localfloats}
+
+\newcounter\noflocalfloats
+
+\def\resetlocalfloats
+ {\doglobal\newcounter\noflocalfloats
+ \initializeboxstack{localfloats}}
+
+\def\somelocalfloat
+ {\doglobal\increment\noflocalfloats
+ \savebox{localfloats}{\noflocalfloats}{\box\floatbox}}
+
+\def\getlocalfloats
+ {\dorecurse\noflocalfloats
+ {\ifnum\recurselevel=\plusone % 1\relax
+ \getvalue{\??lf\c!before}%
+ \else
+ \getvalue{\??lf\c!inbetween}%
+ \fi
+ \dontleavehmode\hbox{\foundbox{localfloats}\recurselevel}%
+ \ifnum\recurselevel=\noflocalfloats\relax
+ \getvalue{\??lf\c!after}%
+ \fi}}
+
+\def\flushlocalfloats
+ {\getlocalfloats
+ \resetlocalfloats}
+
+\unexpanded\def\getlocalfloat#1{\expanded{\foundbox{localfloats}{\number#1}}}
+
+\def\forcelocalfloats{\let\forcedfloatmethod\v!local}
+
+\installfloatmethod \s!singlecolumn \v!local \somelocalfloat
+\installfloatmethod \s!multicolumn \v!local \somelocalfloat
+\installfloatmethod \s!columnset \v!local \somelocalfloat
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-ind.mkiv b/Master/texmf-dist/tex/context/base/strc-ind.mkiv
new file mode 100644
index 00000000000..4b65c740798
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-ind.mkiv
@@ -0,0 +1,123 @@
+%D \module
+%D [ file=strc-ind, % was part of strc-des,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Indented Text,
+%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 / Indented Text}
+
+\unprotect
+
+%D \macros
+%D {defineindentedtext,
+%D setupindentedtext}
+%D
+%D Ok, we keep it but with a different command as it all looks too
+%D much like indentation and indenting. We also assume start/stop
+%D usage or some explicit par.
+
+\installcorenamespace{indentedtext}
+
+\installcommandhandler \??indentedtext {indentedtext} \??indentedtext
+
+%D \startbuffer
+%D \defineindentedtext[one][text=one]
+%D \defineindentedtext[two][text=two]
+%D
+%D \one test test \par
+%D \subone test test \par
+%D \subtwo test test \par
+%D \subsubone test test \par
+%D
+%D \startone
+%D test test
+%D \startone
+%D test test
+%D \startone
+%D test test
+%D \stopone
+%D \starttwo
+%D test test
+%D \startone
+%D test test
+%D \stopone
+%D \stoptwo
+%D \stopone
+%D \stopone
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\newcount\c_strc_indentedtexts_nesting
+\newdimen\d_strc_indentedtexts_width
+
+\appendtoks
+ \setuevalue {\e!start\currentindentedtext}{\strc_indentedtexts_start{\currentindentedtext}\c_strc_indentedtexts_nesting}%
+ \setuevalue {\e!stop \currentindentedtext}{\strc_indentedtexts_stop}%
+ % to be avoided ... might go away
+ \setuevalue {\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{0}}%
+ \setuevalue {\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{1}}%
+ \setuevalue{\v!sub\v!sub\currentindentedtext}{\strc_indentedtexts_direct{\currentindentedtext}{2}}%
+\to \everydefineindentedtext
+
+\unexpanded\def\strc_indentedtexts_start#1#2%
+ {\par
+ \begingroup
+ \c_strc_indentedtexts_nesting#2\relax
+ \edef\currentindentedtext{#1}%
+ \indentedtextparameter\c!before
+ \doifnothing{\indentedtextparameter\c!sample}
+ {\setindentedtextparameter\c!sample{\indentedtextparameter\c!text}}%
+ \assignwidth
+ {\indentedtextparameter\c!width}
+ {\d_strc_indentedtexts_width}
+ {\useindentedtextstyleandcolor\c!headstyle\c!headcolor
+ \indentedtextparameter\c!sample
+ \spr{\indentedtextparameter\c!separator}}
+ {\indentedtextparameter\c!distance}%
+ \advance\d_strc_indentedtexts_width \indentedtextparameter\c!distance
+ \setbox\scratchbox\hbox to \d_strc_indentedtexts_width
+ {\useindentedtextstyleandcolor\c!headstyle\c!headcolor
+ \strut
+ \indentedtextparameter\c!text
+ \hss
+ \spr{\indentedtextparameter\c!separator}%
+ \hskip\indentedtextparameter\c!distance}%
+ \parindent\zeropoint
+ \hskip\c_strc_indentedtexts_nesting\d_strc_indentedtexts_width
+ \advance\c_strc_indentedtexts_nesting\plusone
+ \dontleavehmode\box\scratchbox
+ \hangindent\c_strc_indentedtexts_nesting\d_strc_indentedtexts_width
+ \useindentedtextstyleandcolor\c!style\c!color}
+
+\unexpanded\def\strc_indentedtexts_stop
+ {\indentedtextparameter\c!after
+ \par
+ \endgroup}
+
+\let\stopindentedtext\strc_indentedtexts_stop
+
+\unexpanded\def\strc_indentedtexts_direct#1#2#3\par % no longer clever grabpar trickery
+ {\strc_indentedtexts_start{#1}{#2}#3\strc_indentedtexts_stop}
+
+\setupindentedtext
+ [\c!style=\v!normal,
+ \c!headstyle=\v!normal,
+ %\c!color=,
+ %\c!headcolor=,
+ \c!width=\v!fit,
+ \c!text=\unknown,
+ %\c!sample=,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance=1em,
+ \c!separator={ :}]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-ini.lua b/Master/texmf-dist/tex/context/base/strc-ini.lua
index a9013c641a3..c246ccd2762 100644
--- a/Master/texmf-dist/tex/context/base/strc-ini.lua
+++ b/Master/texmf-dist/tex/context/base/strc-ini.lua
@@ -20,28 +20,22 @@ but it does not make sense to store all processdata.
]]--
-local format, concat, match = string.format, table.concat, string.match
-local count, texwrite, texprint, texsprint = tex.count, tex.write, tex.print, tex.sprint
-local type, next, tonumber, tostring = type, next, tonumber, tostring
+local format, concat = string.format, table.concat
local lpegmatch = lpeg.match
+local count = tex.count
+local type, next, tonumber = type, next, tonumber
local settings_to_array, settings_to_hash = utilities.parsers.settings_to_array, utilities.parsers.settings_to_hash
local allocate = utilities.storage.allocate
-local ctxcatcodes, xmlcatcodes, notcatcodes = tex.ctxcatcodes, tex.xmlcatcodes, tex.notcatcodes -- tricky as we're in notcatcodes
+local ctxcatcodes = tex.ctxcatcodes
+local xmlcatcodes = tex.xmlcatcodes
+local notcatcodes = tex.notcatcodes
+local txtcatcodes = tex.txtcatcodes
-local trace_processors = false trackers.register("structures.processors", function(v) trace_processors = v end)
+local trace_processors = false
+local report_processors = logs.reporter("processors","structure")
-local report_processors = logs.reporter("structure","processors")
-
--- move this
-
-commands = commands or { }
-local commands = commands
-
-function commands.firstinlist(str)
- local first = match(str,"^([^,]+),")
- texsprint(ctxcatcodes,first or str)
-end
+trackers.register("typesetters.processors", function(v) trace_processors = v end)
-- -- -- namespace -- -- --
@@ -58,7 +52,6 @@ structures.registers = structures.registers or { }
structures.references = structures.references or { }
structures.lists = structures.lists or { }
structures.helpers = structures.helpers or { }
-structures.processors = structures.processors or { }
structures.documents = structures.documents or { }
structures.notes = structures.notes or { }
structures.descriptions = structures.descriptions or { }
@@ -74,6 +67,8 @@ structures.synonyms = structures.synonyms or { }
--~ table.print(structures)
+local processors = typesetters.processors
+
-- -- -- specials -- -- --
-- we can store information and get back a reference; this permits
@@ -104,9 +99,9 @@ function specials.store(class,data)
tobesaved[class] = s
end
s[#s+1] = data
- texwrite(#s)
+ context(#s)
else
- texwrite(0)
+ context(0)
end
end
@@ -121,10 +116,23 @@ end
local helpers = structures.helpers
-function helpers.touserdata(str)
- local hash = str and str ~= "" and settings_to_hash(str)
- if hash and next(hash) then
- return hash
+-- function helpers.touserdata(str)
+-- local hash = str and str ~= "" and settings_to_hash(str)
+-- if hash and next(hash) then
+-- return hash
+-- end
+-- end
+
+function helpers.touserdata(data)
+ if type(data) == "string" then
+ if data == "" then
+ return nil
+ else
+ data = settings_to_hash(data)
+ end
+ end
+ if data and next(data) then
+ return data
end
end
@@ -177,6 +185,8 @@ local tags = {
--
-- local command = format("\\xmlprocessbuffer{%s}{%s}{}",metadata.xmlroot or "main",tag)
+local experiment = true
+
function helpers.title(title,metadata) -- coding is xml is rather old and not that much needed now
if title and title ~= "" then -- so it might disappear
if metadata then
@@ -185,12 +195,21 @@ function helpers.title(title,metadata) -- coding is xml is rather old and not th
-- title can contain raw xml
local tag = tags[metadata.kind] or tags.generic
local xmldata = format("<?xml version='1.0'?><%s>%s</%s>",tag,title,tag)
+if not experiment then
buffers.assign(tag,xmldata)
+end
if trace_processors then
report_processors("putting xml data in buffer: %s",xmldata)
report_processors("processing buffer with setup '%s' and tag '%s'",xmlsetup or "",tag)
end
+if experiment then
+ -- the question is: will this be forgotten ... better store in a via file
+ local xmltable = lxml.convert("temp",xmldata or "")
+ lxml.store("temp",xmltable)
+ context.xmlsetup("temp",xmlsetup or "")
+else
context.xmlprocessbuffer("dummy",tag,xmlsetup or "")
+end
elseif xmlsetup then -- title is reference to node (so \xmlraw should have been used)
if trace_processors then
report_processors("feeding xmlsetup '%s' using node '%s'",xmlsetup,title)
@@ -207,68 +226,15 @@ function helpers.title(title,metadata) -- coding is xml is rather old and not th
if trace_processors then
report_processors("cct: %s, txt: %s",catcodes,title)
end
- texsprint(catcodes,title)
+ context.sprint(catcodes,title) -- was: texsprint(catcodes,title)
end
end
else
- texsprint(title) -- no catcode switch
+ context(title) -- no catcode switch, was: texsprint(title)
end
end
end
--- -- -- processors -- -- -- syntax: processor->data ... not ok yet
-
-local processors = structures.processors
-
-local registered = { }
-
-function processors.register(p)
- registered[p] = true
-end
-
-function processors.reset(p)
- registered[p] = nil
-end
-
-local splitter = lpeg.splitat("->",true)
-
-function processors.split(str)
- local p, s = lpegmatch(splitter,str)
- if registered[p] then
- return p, s
- else
- return false, str
- end
-end
-
-function processors.sprint(catcodes,str,fnc,...) -- not ok: mixed
- local p, s = lpegmatch(splitter,str)
- local code
- if registered[p] then
- code = format("\\applyprocessor{%s}{%s}",p,(fnc and fnc(s,...)) or s)
- else
- code = (fnc and fnc(str,...)) or str
- end
- if trace_processors then
- report_processors("cct: %s, seq: %s",catcodes,code)
- end
- texsprint(catcodes,code)
-end
-
-function processors.apply(str)
- local p, s = lpegmatch(splitter,str)
- if registered[p] then
- return format("\\applyprocessor{%s}{%s}",p,s)
- else
- return str
- end
-end
-
-function processors.ignore(str)
- local p, s = lpegmatch(splitter,str)
- return s or str
-end
-
-- -- -- sets -- -- --
local sets = structures.sets
@@ -314,7 +280,20 @@ function sets.getall(namespace,block,name)
end
end
+-- messy (will be another keyword, fixedconversion)
+
+local splitter = lpeg.splitat("::")
+
function sets.get(namespace,block,name,level,default) -- check if name is passed
+ --fixed::R:a: ...
+ local kind, rest = lpegmatch(splitter,name)
+ if kind and rest then
+ if kind == "fixed" then
+ local s = settings_to_array(rest)
+ return s[level] or default
+ end
+ end
+ --
local ds = setlist[namespace]
if not ds then
return default
@@ -336,6 +315,11 @@ function sets.get(namespace,block,name,level,default) -- check if name is passed
if not dn then
return default
end
+-- inspect(dn)
local dl = dn[1][level]
return dl or dn[2] or default
end
+
+-- interface
+
+commands.definestructureset = sets.define
diff --git a/Master/texmf-dist/tex/context/base/strc-ini.mkiv b/Master/texmf-dist/tex/context/base/strc-ini.mkvi
index b1b11d8718a..8488d1dab86 100644
--- a/Master/texmf-dist/tex/context/base/strc-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-ini.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Initialization \& Helpers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -22,7 +22,7 @@
% section : [sectionnumber(s)]
% sectionseparatorset (default) sectionconversionset (default) sectionstopper () sectionset sectionsegments
-% lists : [sectionnumber(s)] [text] [prefix(es)[separator]][pagenumber(s)]
+% lists : [sectionnumber(s)] [text] [prefix(es)[separator][pagenumber(s)]
% sectionseparatorset (default) sectionconversionset (default) sectionstopper sectionset sectionsegments
% prefixseparatorset (default) prefixconversionset (default) prefixstopper (.) prefixset prefixsegments
% pageseparatorset (default) pageconversionset (default) pagestopper () pagesegments
@@ -65,18 +65,25 @@
% level of a number in sets. This is all handles at the \LUA\ end.
% References to such sets travel with the multipass information.
-\unexpanded\def\definestructureresetset {\dotripleempty\dodefinestructureresetset}
-\unexpanded\def\definestructureseparatorset {\dotripleempty\dodefinestructureseparatorset}
-\unexpanded\def\definestructureconversionset{\dotripleempty\dodefinestructureconversionset}
-\unexpanded\def\definestructureprefixset {\dotripleempty\dodefinestructureprefixset}
+\unexpanded\def\defineresetset {\dotripleempty\strc_sets_define_reset_set}
+\unexpanded\def\defineseparatorset {\dotripleempty\strc_sets_define_separator_set}
+\unexpanded\def\defineconversionset{\dotripleempty\strc_sets_define_conversion_set}
+\unexpanded\def\defineprefixset {\dotripleempty\strc_sets_define_prefix_set}
-\def\dodefinestructureresetset [#1][#2][#3]{\ctxlua{structures.sets.define("structure:resets", "#1","\luaescapestring{\detokenize{#2}}","\luaescapestring{\detokenize{#3}}",true)}}
-\def\dodefinestructureseparatorset [#1][#2][#3]{\ctxlua{structures.sets.define("structure:separators", "#1","\luaescapestring{\detokenize{#2}}","\luaescapestring{\detokenize{#3}}")}}
-\def\dodefinestructureconversionset[#1][#2][#3]{\ctxlua{structures.sets.define("structure:conversions","#1","\luaescapestring{\detokenize{#2}}","\luaescapestring{\detokenize{#3}}")}}
-\def\dodefinestructureprefixset [#1][#2][#3]{\ctxlua{structures.sets.define("structure:prefixes", "#1","\luaescapestring{\detokenize{#2}}","\luaescapestring{\detokenize{#3}}")}}
+% Low level versions (no optional checking). The detokenize and escaping might go away.
-% \definestructureseparatorset [weird][!,?,*][:] % tex content
-% \definestructureconversionset[weird][numbers,characters,romannumerals][numbers] % symbolic names
-% \definestructureresetset [weird][0,0,1][0] % numbers
+\unexpanded\def\strc_sets_define_reset_set [#name][#set][#default]{\ctxcommand{definestructureset("structure:resets", "#name","\luaescapestring{\detokenize{#set}}","\luaescapestring{\detokenize{#default}}",true)}}
+\unexpanded\def\strc_sets_define_separator_set [#name][#set][#default]{\ctxcommand{definestructureset("structure:separators", "#name","\luaescapestring{\detokenize{#set}}","\luaescapestring{\detokenize{#default}}")}}
+\unexpanded\def\strc_sets_define_conversion_set[#name][#set][#default]{\ctxcommand{definestructureset("structure:conversions","#name","\luaescapestring{\detokenize{#set}}","\luaescapestring{\detokenize{#default}}")}}
+\unexpanded\def\strc_sets_define_prefix_set [#name][#set][#default]{\ctxcommand{definestructureset("structure:prefixes", "#name","\luaescapestring{\detokenize{#set}}","\luaescapestring{\detokenize{#default}}")}}
+
+\let\definestructureresetset \defineresetset
+\let\definestructureseparatorset \defineseparatorset
+\let\definestructureconversionset\defineconversionset
+\let\definestructureprefixset \defineprefixset
+
+% \defineseparatorset [weird][!,?,*][:] % tex content
+% \defineconversionset[weird][numbers,characters,romannumerals][numbers] % symbolic names
+% \defineresetset [weird][0,0,1][0] % numbers
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-itm.lua b/Master/texmf-dist/tex/context/base/strc-itm.lua
index 1c7c2adb59e..8a745f356fb 100644
--- a/Master/texmf-dist/tex/context/base/strc-itm.lua
+++ b/Master/texmf-dist/tex/context/base/strc-itm.lua
@@ -10,14 +10,29 @@ local structures = structures
local itemgroups = structures.itemgroups
local jobpasses = job.passes
+local setfield = jobpasses.save
+local getfield = jobpasses.getfield
+
function itemgroups.register(name,nofitems,maxwidth)
- jobpasses.savedata("itemgroup", { nofitems, maxwidth })
+ setfield("itemgroup", { nofitems, maxwidth })
end
function itemgroups.nofitems(name,index)
- jobpasses.getfield("itemgroup", index, 1, 0)
+ return getfield("itemgroup", index, 1, 0)
end
function itemgroups.maxwidth(name,index)
- jobpasses.getfield("itemgroup", index, 2, 0)
+ return getfield("itemgroup", index, 2, 0)
+end
+
+-- interface (might become counter/dimension)
+
+commands.registeritemgroup = itemgroups.register
+
+function commands.nofitems(name,index)
+ context(getfield("itemgroup", index, 1, 0))
+end
+
+function commands.maxitemwidth(name,index)
+ context(getfield("itemgroup", index, 2, 0))
end
diff --git a/Master/texmf-dist/tex/context/base/strc-itm.mkii b/Master/texmf-dist/tex/context/base/strc-itm.mkii
index 1de63c7c32b..697618323bb 100644
--- a/Master/texmf-dist/tex/context/base/strc-itm.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-itm.mkii
@@ -5,7 +5,7 @@
%D subtitle=itemgroups,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-itm.mkiv b/Master/texmf-dist/tex/context/base/strc-itm.mkiv
deleted file mode 100644
index 67f42f86672..00000000000
--- a/Master/texmf-dist/tex/context/base/strc-itm.mkiv
+++ /dev/null
@@ -1,1408 +0,0 @@
-%D \module
-%D [ file=strc-itm,
-%D version=2008.10.20,
-%D title=\CONTEXT\ Structure Macros,
-%D subtitle=Itemgroups,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
-%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 / Itemgroups}
-
-\registerctxluafile{strc-itm}{1.001}
-
-% this will be reimplemented: \startitem ... \stopitem will be the main macros and
-% \item will then call them
-
-\unprotect
-
-\newconditional\sublistitem \setfalse\sublistitem
-\newconditional\symbollistitem \setfalse\symbollistitem
-\newconditional\headlistitem \setfalse\headlistitem
-\newconditional\introlistitem \setfalse\introlistitem
-\newconditional\randomizeitems \setfalse\randomizeitems
-\newconditional\autointrolistitem \setfalse\autointrolistitem
-\newconditional\optimizelistitem \settrue \optimizelistitem
-\newconditional\packlistitem \setfalse\packlistitem
-\newconditional\paragraphlistitem \setfalse\paragraphlistitem
-\newconditional\textlistitem \setfalse\textlistitem
-\newconditional\firstlistitem \setfalse\firstlistitem
-\newconditional\beforelistitem \setfalse\beforelistitem
-\newconditional\afterlistitem \setfalse\afterlistitem
-\newconditional\nowhitelistitem \setfalse\nowhitelistitem
-\newconditional\joinedlistitem \setfalse\joinedwhitelistitem
-\newconditional\reverselistitem \setfalse\reverselistitem
-\newconditional\continuelistitems \setfalse\continuelistitems
-\newconditional\fittinglistitems \setfalse\fittinglistitems
-\newconditional\indentedfirstlistitem \setfalse\indentedfirstlistitem
-\newconditional\inlinelistitem \setfalse\inlinelistitem
-
-\newcount\noflists
-\newcount\currentnoflists
-\newcount\noflistelements
-\newcount\itemcolumndepth
-\newcount\itemdepth
-% \newcount\maxitemdepth \maxitemdepth=6
-
-\newdimen\itemgrouplistwidth
-\newdimen\itemgroupaskedwidth
-\newbox \itemgroupitembox
-
-\def\currentitemgroupcounter{itemgroup:\currentitemgroup}
-
-\let\currentitemlevel \!!zerocount
-\let\currentitemgroup \empty
-\let\currentnofitems \!!zerocount
-\def\currentitemnumber {\dorawsubstructurecounter[\currentitemgroupcounter][\currentitemlevel]}
-\let\currentrepeatstart \empty
-
-\def\dolistreference
- {\iftrialtypesetting \else % no need for different treatment of \continuelistitems
- \ctxlua{structures.itemgroups.register("\currentitemgroup",\number\noflistelements,"\getitemparameter\currentitemlevel\c!maxwidth")}%
- \fi}
-
-\def\checkcurrentnofitems % we could do this at the lua end and save a call
- {\edef\currentnofitems {\ctxlua{structures.itemgroups.nofitems("\currentitemgroup",\number\currentnoflists)}}%
- \edef\currentitemmaxwidth{\ctxlua{structures.itemgroups.maxwidth("\currentitemgroup",\number\currentnoflists)}\scaledpoint}}
-
-% todo: \dodosetreference -> \dostructurecountercomponent (to be checked)
-
-\def\dohandleitemreference % we will make a decent number helper
- {\ifx\currentitemreference \empty \else
-\iftrialtypesetting \else
- \setnextinternalreference
- \ctxlua {structures.references.setandgetattribute("\s!full", "\referenceprefix","\currentitemreference",
- {
- metadata = {
- kind = "item",% ?
- catcodes = \the\catcodetable,
- xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text
- },
- references = {
- internal = \nextinternalreference,
- section = structures.sections.currentid(),
- },
- prefixdata = structures.helpers.simplify {
- prefix = "\structurecounterparameter\currentitemgroupcounter\c!prefix",
- separatorset = "\structurecounterparameter\currentitemgroupcounter\c!prefixseparatorset",
- conversion = \!!bs\structurecounterparameter\currentitemgroupcounter\c!prefixconversion\!!es,
- conversionset = "\structurecounterparameter\currentitemgroupcounter\c!prefixconversionset",
- set = "\structurecounterparameter\currentitemgroupcounter\c!prefixset",
- segments = "\structurecounterparameter\currentitemgroupcounter\c!prefixsegments",
- % segments = "\askedprefixsegments",
- connector = \!!bs\structurecounterparameter\currentitemgroupcounter\c!prefixconnector\!!es,
- },
- numberdata = structures.helpers.simplify {
- numbers = structures.counters.compact("\currentitemgroupcounter",nil,true),
- separatorset = "\structurecounterparameter\currentitemgroupcounter\c!numberseparatorset",
- conversion = "\structurecounterparameter\currentitemgroupcounter\c!numberconversion",
- conversionset = "\structurecounterparameter\currentitemgroupcounter\c!numberconversionset",
- % for the moment no stopper, we need to make references configurable first
- % stopper = \!!bs\structurecounterparameter\currentitemgroupcounter\c!numberstopper\!!es,
- segments = "\structurecounterparameter\currentitemgroupcounter\c!numbersegments",
- },
- })
- }%
- \xdef\currentitemattribute{\number\lastdestinationattribute}%
- \begingroup\attribute\destinationattribute\currentitemattribute\kern\zeropoint\endgroup % todo, apply attribute to symbol
-\fi
- \fi}
-
-% \startitemize[n,packed]
-% \item test \item test \item test
-% \stopitemize
-%
-% \startitemize[n,packed,reverse]
-% \item test \item test \item test
-% \stopitemize
-%
-% \startitemize[n,packed,reverse] \item test \item test \stopitemize
-% \startitemize[continue]
-% \item test \startitemize[n,packed] \item test \item test \stopitemize
-% \item test
-% \item test
-% \stopitemize
-% \startitemize[continue] \item test \stopitemize
-%
-% \startitemize[n,packed] \item test \item test \stopitemize
-% \startitemize[continue] \item test \stopitemize
-% \startitemize[continue] \item test \stopitemize
-
-\def\itemparameter #1#2{\csname\doitemparameter{\??op\currentitemgroup#1}#2\endcsname}
-\def\itemparameterhash#1#2{\doitemparameterhash {\??op\currentitemgroup#1}#2}
-
-
-\def\doitemparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\doitemparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\doitemparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\doitemparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\doitemparentparameter #1#2{\ifx#1\relax\s!empty\else\doitemparameter #1#2\fi}
-\def\doitemparentparameterhash#1#2{\ifx#1\relax \else\doitemparameterhash#1#2\fi}
-
-\def\dosetitemattributes#1#2#3% style color
- {\edef\fontattributehash {\itemparameterhash#1#2}%
- \edef\colorattributehash{\itemparameterhash#1#3}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #2\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#3\fi}
-
-\def\setitemparameter #1#2{\@EA \def\csname\??op\currentitemgroup#1#2\endcsname} % #3 -> {#3}
-\def\esetitemparameter#1#2{\@EA\edef\csname\??op\currentitemgroup#1#2\endcsname} % #3 -> {#3}
-\def\xsetitemparameter#1#2{\@EA\xdef\csname\??op\currentitemgroup#1#2\endcsname} % #3 -> {#3}
-\def\letitemparameter #1#2{\@EA \let\csname\??op\currentitemgroup#1#2\endcsname}
-\let\getitemparameter \itemparameter
-
-\def\@@globalitemsymbol #1{\??op\currentitemgroup\c!symbol\s!global#1}
-\def\@@localitemsymbol #1{\??op\currentitemgroup\c!symbol\s!local #1}
-\def\@@currentitemsymbol#1{\??op\currentitemgroup\c!symbol #1}
-
-\def\@@itemcounter{\s!itemcount\currentitemgroup}
-
-% \def\doitembreak#1{\ifconditional\optimizelistitem\ifconditional\textlistitem\else\dosomebreak#1\fi\fi}
-%
-% \def\allowitembreak {\doitembreak\allowbreak}
-% \def\noitembreak {\doitembreak\nobreak}
-% \def\itembreakspecial {\doitembreak\itembreak}
-% \def\noitembreakspecial{\doitembreak\itemnobreak}
-%
-% \def\itembreak {\flushnotes\penalty-5\relax} % -10
-% \def\itemnobreak{\flushnotes\penalty+5\ifinsidecolumns\else00\fi\relax} % +5
-
-\definevspacing[\v!item @0] [penalty:0] % allow
-\definevspacing[\v!item @10000] [penalty:10000] % no
-\definevspacing[\v!item @-5] [penalty:-5]
-\definevspacing[\v!item @5] [penalty:5]
-\definevspacing[\v!item @500] [penalty:500]
-
-\def\doitembreak#1{\ifconditional\optimizelistitem\ifconditional\textlistitem\else#1\fi\fi}
-
-\def\allowitembreak {\doitembreak\itembreakallow}
-\def\noitembreak {\doitembreak\itembreakno}
-\def\itembreakspecial {\doitembreak\itembreak}
-\def\noitembreakspecial{\doitembreak\itemnobreak}
-
-\def\itembreakallow{\vspacing[\v!item @0]}
-\def\itembreakno {\vspacing[\v!item @10000]}
-\def\itembreak {\flushnotes\vspacing[\v!item @-5]}
-\def\itemnobreak {\flushnotes\ifinsidecolumns\vspacing[\v!item @5]\else\vspacing[\v!item @500]\fi}
-
-% cool but wrong:
-%
-% \def\initializeitemgrouplevel#1%
-% {\ifcsname\??op\currentitemgroup#1\s!parent\endcsname
-% % ok
-% \else\ifnum#1>\plusone
-% \setevalue{\??op\currentitemgroup#1\s!parent}{\??op\currentitemgroup\the\numexpr#1-1\relax}%
-% \else
-% \setevalue{\??op\currentitemgroup#1\s!parent}{\??op\currentitemgroup}%
-% \fi\fi}
-%
-% so we have:
-
-\def\initializeitemgrouplevel#1%
- {\ifcsname\??op\currentitemgroup\number#1\s!parent\endcsname
- % ok
- \else
- \setxvalue{\??op\currentitemgroup \c!levels}{\number#1}%
- \setxvalue{\??op\currentitemgroup\number#1\s!parent}{\??op\currentitemgroup}%
- \fi}
-
-\unexpanded\def\defineitemgroup
- {\dotripleempty\dodefineitemgroup}
-
-\def\dodefineitemgroup[#1][#2][#3]% todo: clone
- {\doifsomething{#1}
- {\pushmacro\currentitemgroup
- \def\currentitemgroup{#1}%
- \setuvalue{\e!start#1}{\startitemgroup[#1]}%
- \setuvalue{\e!stop#1}{\stopitemgroup}%
- \setuvalue{\e!setup#1\e!endsetup}{\setupitemgroup[#1]}% for old times sake
- \doifelsenothing{#2}
- {\getparameters[\??op#1][\s!parent=\??oo,#3]}%
- {\doifassignmentelse{#2}
- {\getparameters[\??op#1][\s!parent=\??oo,#2]}%
- {\getparameters[\??op#1][\s!parent=\??op#2,#3]}}%
- \dorecurse{\itemparameter\empty\c!levels}{\initializeitemgrouplevel\recurselevel}%
- \definestructurecounter[itemgroup:#1]%
- \popmacro\currentitemgroup}}
-
-\newtoks\everysetupitemgroup
-
-\unexpanded\def\setupitemgroups % [#1]
- {\dodoubleargument\getparameters[\??oo]} % [#1]
-
-\def\packitems
- {\ifcase\currentitemlevel \else \settrue\packlistitem \fi}
-
-\def\dosetupitemgroupvariable[#1]% [#2]% niveau instellingen
- {\doifelsenothing{#1}
- {\getparameters[\??op\currentitemgroup\currentitemlevel]}%
- {\getparameters[\??op\currentitemgroup#1]}}
-
-\def\dosetupitemgroupconstant#1%
- {\global\setitemparameter\currentitemlevel\c!maxwidth{0}%
- \processcommacommand[#1]\dodosetupitemgroupconstant} % expansion of #2 is handy for xml
-
-\def\dodosetupitemgroupconstant#1%
- {\edef\itemgroupconstantvalue{#1}%
- \ifx\itemgroupconstantvalue\empty\else
- \splitstring\itemgroupconstantvalue\at*\to\itemgroupfirst\and\itemgroupsecond
- \ifx\itemgroupsecond\empty
- \let\itemgroupsecond\itemgroupfirst
- \let\itemgroupfirst\!!plusone
- \fi
- \ifcsname\??op:::\itemgroupsecond\endcsname\csname\??op:::\itemgroupsecond\endcsname\fi
- \fi}
-
-\setvalue{\??op:::\v!packed }{\packitems}
-\setvalue{\??op:::\v!intro }{\settrue\introlistitem} % here? not set to false
-\setvalue{\??op:::\v!autointro}{\settrue\autointrolistitem}
-\setvalue{\??op:::\v!broad }{\ifx\itemgroupfirst\empty\def\itemgroupfirst{1}\fi
- \letitemparameter\currentitemlevel\c!factor\itemgroupfirst}
-\setvalue{\??op:::\v!text }{\settrue\textlistitem
- \settrue\inlinelistitem
- \settrue\joinedlistitem
- \packitems}
-\setvalue{\??op:::\v!columns }{\packitems}
-\setvalue{\??op:::\v!before }{\settrue\beforelistitem}
-\setvalue{\??op:::\v!after }{\settrue\afterlistitem}
-\setvalue{\??op:::\v!nowhite }{\settrue\nowhitelistitem}
-\setvalue{\??op:::\v!margin }{\setitemparameter\currentitemlevel\c!width{-2em}} % signal
-\setvalue{\??op:::\v!inmargin }{\setitemparameter\currentitemlevel\c!width{-2em}} % signal
-\setvalue{\??op:::\v!atmargin }{\doifnot\currentitemlevel{1}{\setitemparameter\currentitemlevel\c!width{0em}}} % signal
-\setvalue{\??op:::\v!intext }{\settrue\inlinelistitem}
-\setvalue{\??op:::\v!loose }{\setfalse\optimizelistitem}
-\setvalue{\??op:::\v!fit }{\settrue\fittinglistitems}
-\setvalue{\??op:::\v!nofit }{\setfalse\fittinglistitems}
-\setvalue{\??op:::\v!paragraph}{\settrue\paragraphlistitem
- \packitems}
-\setvalue{\??op:::\v!joinedup }{\settrue\joinedlistitem
- \packitems}
-\setvalue{\??op:::\v!serried }{\edef\itemgroupfirst{-\ifx\itemgroupfirst\empty1\else\itemgroupfirst\fi}%
- \letitemparameter\currentitemlevel\c!factor\itemgroupfirst}
-\setvalue{\??op:::\v!stopper }{\letitemparameter\currentitemlevel\c!placestopper\v!yes} % keep {}
-\setvalue{\??op:::\v!unpacked }{\setfalse\packlistitem}
-\setvalue{\??op:::\v!repeat }{\settrue\repeatlistitem}
-\setvalue{\??op:::\v!reverse }{\settrue\reverselistitem}
-\setvalue{\??op:::\v!standard }{\dosetupstandarditemgroup\currentitemlevel}
-
-\def\dosetupstandarditemgroup#1%
- {\getparameters
- [\??op\currentitemgroup#1]
- [\c!width=1.5em,\c!factor=0,\c!distance=.5em,\c!inner=,\c!factor=0,
- \c!beforehead=,\c!afterhead=\blank,\c!before=\blank,\c!inbetween=\blank,\c!after=\blank]}
-
-% \def\packeditemspacing{\empty}
-
-% \setupwhitespace[big]
-% \starttext
-% test \startitemize[joinedup] \item test \item test \stopitemize test \par
-% test \startitemize[joinedup,nowhite] \item test \item test \stopitemize test \par
-% test \startitemize[joinedup,nowhite,before] \item test \item test \stopitemize test \par
-% test \startitemize[joinedup,nowhite,after] \item test \item test \stopitemize test \par
-% \stoptext
-
-\def\itembeforecommand
- {\ifconditional\nowhitelistitem
- \ifconditional\beforelistitem
- \ifcase\currentitemlevel\or\getitemparameter\currentitemlevel\c!before\fi
- \else
- \nowhitespace
- \fi
- \else\ifconditional\joinedlistitem
- % \empty
- \else
- \getitemparameter\currentitemlevel\c!before
- \fi\fi
- \dostarttagged\t!itemgroup\currentitemgroup
- \dotagsetitemize}
-
-\def\itemaftercommand
- {\dostoptagged
- \ifconditional\nowhitelistitem
- \ifconditional\afterlistitem
- \ifcase\currentitemlevel\or\getitemparameter\currentitemlevel\c!after\fi
- \else
- \nowhitespace
- \fi
- \else\ifconditional\joinedlistitem
- % \empty
- \else
- \getitemparameter\currentitemlevel\c!after
- \fi\fi}
-
-\def\iteminbetweencommand
- {\ifconditional\nowhitelistitem
- \nowhitespace
- \else\ifconditional\joinedlistitem
- % \empty
- \else
- \getitemparameter\currentitemlevel\c!inbetween
- \fi\fi}
-
-\def\itembeforeheadcommand
- {\ifconditional\nowhitelistitem
- \nowhitespace
- \else\ifconditional\joinedlistitem
- % \empty
- \else
- \getitemparameter\currentitemlevel\c!beforehead
- \fi\fi}
-
-\def\itemafterheadcommand
- {\ifconditional\nowhitelistitem
- \nowhitespace
- \else\ifconditional\joinedlistitem
- % \empty
- \else
- \getitemparameter\currentitemlevel\c!afterhead
- \fi\fi}
-
-\unexpanded\def\dododododosetupitemgroup[#1][#2]% prevent expansion below
- {\doifassignmentelse{#2}%
- {\dosetupitemgroupvariable[#1][#2]}%
- {\setitemparameter{#1}\c!option{#2}}}%
-
-\def\dodododosetupitemgroup[#1][#2]%
- {\doifsomething{#2}
- {\doifelse{#1}\v!each
- {\dorecurse{\itemparameter\empty\c!levels}{\normalexpanded{\dododododosetupitemgroup[\recurselevel]}[#2]}}
- {\normalexpanded{\dododododosetupitemgroup[#1]}[#2]}}}
-
-\def\dododosetupitemgroup[#1][#2]%
- {\doifelsenothing{#2}
- {\doifsomething{#1}
- {\ifcase\currentitemlevel\relax
- \dodododosetupitemgroup[\v!each][#1]%
- \else
- \dodododosetupitemgroup[\currentitemlevel][#1]%
- \fi}}%
- {\doifelsenothing{#1}
- {\ifcase\currentitemlevel\relax
- \dodododosetupitemgroup[\v!each][#2]%
- \else
- \dodododosetupitemgroup[\currentitemlevel][#2]%
- \fi}
- {\dodododosetupitemgroup[#1][#2]}}}
-
-\def\dodosetupitemgroup[#1][#2][#3][#4]%
- {\pushmacro\currentitemgroup
- \def\currentitemgroup{#1}%
- \dododosetupitemgroup[#2][#3]%
- \doifsomething{#4}{\dododosetupitemgroup[#2][#4]}%
- \the\everysetupitemgroup
- \popmacro\currentitemgroup}
-
-\def\dosetupitemgroup[#1][#2][#3][#4]%
- {\def\docommand##1{\dodosetupitemgroup[##1][#2][#3][#4]}%
- \processcommalist[#1]\docommand}
-
-\unexpanded\def\setupitemgroup
- {\doquadrupleempty\dosetupitemgroup}
-
-\def\doadvanceitem
- {\ifconditional\sublistitem\else\ifconditional\symbollistitem\else
- \doincrementsubstructurecounter[\currentitemgroupcounter][\currentitemlevel]%
- \fi\fi}
-
-\def\setitemlevel#1%
- {\ifnum\currentitemlevel>\zerocount
- \settrue\firstlistitem
- \ifconditional\continuelistitems\else
- \dorestartsubstructurecounter[\currentitemgroupcounter][\currentitemlevel]{\the\numexpr\getitemparameter\currentitemlevel\c!start-1\relax}%
- \fi
- \fi}
-
-\unexpanded\def\actualitemnumber
- {\ifconditional\repeatlistitem
- \ifcase\currentitemlevel\or\else
- \doactualitemnumber
- \fi
- \else
- \doactualitemnumber
- \fi}
-
-\def\doactualitemnumber
- {\begingroup
- \setupstructurecounter
- [\currentitemgroupcounter]
- [%\c!prefix=\v!no,
- \c!prefix=\getitemparameter\currentitemlevel\c!prefix,
- \c!prefixstopper=\getitemparameter\currentitemlevel\c!prefixstopper,
- \c!prefixseparatorset=\getitemparameter\currentitemlevel\c!prefixseparatorset,
- \c!prefixconversion=\getitemparameter\currentitemlevel\c!prefixconversion,
- \c!prefixconversionset=\getitemparameter\currentitemlevel\c!prefixseparatorset,
- \c!prefixset=\getitemparameter\currentitemlevel\c!prefixset,
- \c!prefixsegments=\getitemparameter\currentitemlevel\c!prefixsegments,
- \c!prefixconnector=\getitemparameter\currentitemlevel\c!prefixconnector,
- \c!criterium=\getitemparameter\currentitemlevel\c!criterium,
- \c!numberorder=\ifconditional\reverselistitem\v!reverse\else\v!normal\fi,
- \c!numberstopper=\expdoif{\getitemparameter\currentitemlevel\c!placestopper}\v!yes{\getitemparameter\currentitemlevel\c!stopper},
- %\c!numberseparatorset=,
- %\c!numberconversionset=,
- \c!numberconversion=\currentitemsymbol,
- \c!numbersegments=\ifx\currentrepeatstart\empty\else\currentrepeatstart:\fi\number\currentitemlevel]%
- \ifconditional\reverselistitem
- \convertedstructurecounter[\currentitemgroupcounter]% [\number\currentitemlevel]%
- \else
- \convertedstructurecounter[\currentitemgroupcounter]% [\number\currentitemlevel]%
- \fi
- \dohandleitemreference
- \endgroup}
-
-\def\unknownitemsymbol{?}
-
-\def\setitemmark#1% % en pas op: resets \docommand ; todo: conversionset
- {\doifsymboldefinedelse{#1}
- {\edef\currentitemsymbol{#1}%
- \setxvalue{\@@globalitemsymbol\currentitemlevel}{\currentitemsymbol}%
- \setgvalue{\@@localitemsymbol \currentitemlevel}{\unknownitemsymbol}%
- \def\listitem{\symbol[\currentitemsymbol]}%
- \let\@@opsymbol\empty}%
- {\doifconversiondefinedelse{#1}
- {\edef\currentitemsymbol{#1}%
- \setxvalue{\@@globalitemsymbol\currentitemlevel}{\currentitemsymbol}%
- \setgvalue{\@@localitemsymbol\currentitemlevel }{\actualitemnumber }%
- \def\listitem
- {\ifconditional\textlistitem
- % maybe block stopper here, but one can as well clone an
- % itemgroup then
- \getitemparameter\currentitemlevel\c!lefttext
- \getvalue{\@@localitemsymbol\currentitemlevel}%
- \getitemparameter\currentitemlevel\c!righttext
- \else
- \getitemparameter\currentitemlevel\c!left
- \getvalue{\@@localitemsymbol\currentitemlevel}%
- \getitemparameter\currentitemlevel\c!right
- \fi}%
- \let\@@opsymbol\empty}%
- {}}}
-
-% \def\calculatelistwidth#1% distance deals with 'broad'
-% {\itemgrouplistwidth\getitemparameter#1\c!distance\relax
-% \ifnum\getitemparameter#1\c!factor>\zerocount
-% \ifdim\itemgrouplistwidth=\zeropoint \itemgrouplistwidth=.5em\fi
-% \fi
-% \multiply\itemgrouplistwidth \getitemparameter#1\c!factor
-% \advance \itemgrouplistwidth \getitemparameter#1\c!width\relax}
-
-\def\calculatelistwidth#1%
- {\ifdim\currentitemmaxwidth>\zeropoint
- \itemgrouplistwidth\currentitemmaxwidth
- \else\ifnum\getitemparameter#1\c!factor>\zerocount
- \itemgrouplistwidth\getitemparameter#1\c!step\relax
- \ifdim\itemgrouplistwidth=\zeropoint \itemgrouplistwidth=.5em\fi
- \multiply\itemgrouplistwidth \getitemparameter#1\c!factor
- \advance\itemgrouplistwidth\getitemparameter#1\c!width\relax
- \else
- \itemgrouplistwidth\getitemparameter#1\c!width\relax
- \fi\fi
- \advance\itemgrouplistwidth\getitemparameter#1\c!distance\relax}
-
-% The next conditionals deal with \item \startitemgroup. It
-% looks like a hack to skip back, but that way we preserve
-% the indentation and bullet placement. It's a rather
-% untested feature.
-
-\newconditional\concatnextitem \setfalse\concatnextitem
-\newconditional\autoconcatnextitem \settrue \autoconcatnextitem
-\newsignal \itemsignal
-
-\unexpanded\def\startitemgroup
- {\dotripleempty\dostartitemgroup}
-
-\def\dostartitemgroup[#1][#2][#3]%
- {\bgroup
- \ifnum\currentitemlevel=\zerocount
- \def\currentitemgroup{#1}% no nested mixing of itemgroups
- \fi
- \ifthirdargument
- \dodostartitemgroup[#2][#3]%
- \else
- \doifassignmentelse{#2}
- {\dodostartitemgroup[][#2]}
- {\dodostartitemgroup[#2][]}%
- \fi}
-
-\def\dodostartitemgroup[#1]% [#2]%
- {\relax % prevents lookahead
- \global\advance\itemdepth\plusone
- \initializeitemgrouplevel\itemdepth
- \xdef\currentitemlevel{\number\itemdepth}%
- \edef\itemgroupoptions{\getitemparameter\currentitemlevel\c!option}%
- \ifx\itemgroupoptions\empty
- \edef\itemgroupoptions{#1}%
- \else
- \doifsomething{#1}{\edef\itemgroupoptions{\itemgroupoptions,#1}}%
- \fi
- \normalexpanded{\noexpand\redostartitemgroup[\itemgroupoptions]}}% [#2]
-
-\let\startcollectitems\relax
-\let\stopcollectitems \relax
-
-%D A nice example of a plugin:
-%D
-%D \startbuffer
-%D \startitemize[a,random,packed]
-%D \startitem first \stopitem \startitem second \stopitem
-%D \startitem third \stopitem \startitem fourth \stopitem
-%D \stopitemize
-%D
-%D \startitemize[a,random,packed]
-%D \startitem first \stopitem \startitem second \stopitem
-%D \startitem third \stopitem \startitem fourth \stopitem
-%D \stopitemize
-%D
-%D \startitemize[a,packed]
-%D \startitem first \stopitem \startitem second \stopitem
-%D \startitem third \stopitem \startitem fourth \stopitem
-%D \stopitemize
-%D \stopbuffer
-%D
-%D \typebuffer \getbuffer
-
-% better collectitems als conditional and a real plugin mechanism (some day)
-
-\@EA\long\@EA\def\@EA\collectitemgroupitem\@EA#\@EA1\csname\e!stop\v!item\endcsname
- {\increment\itemcollectcounter
- \long\setvalue{\v!item*\itemcollectcounter}{\startitemgroupitem#1\stopitemgroupitem}}
-
-\def\flushcollecteditems
- {\ifconditional\randomizeitems
- \getrandomnumber\itemcollectcounternow\plusone\itemcollectcounter
- \else
- \increment\itemcollectcounternow
- \fi
- \doifdefined{\v!item*\itemcollectcounternow}
- {\getvalue{\v!item*\itemcollectcounternow}%
- \letbeundefined{\v!item*\itemcollectcounternow}%
- \increment\itemcollectcounterdone}%
- \ifnum\itemcollectcounterdone<\itemcollectcounter\relax
- \expandafter\flushcollecteditems
- \fi}
-
-\unexpanded\def\stopcollectitems
- {\ifconditional\randomizeitems
- \newcounter\itemcollectcounterdone
- \ifnum\itemcollectcounter>\zerocount
- \@EAEAEA\flushcollecteditems
- \fi
- \fi}
-
-\unexpanded\def\startcollectitems
- {\ifconditional\randomizeitems
- \newcounter\itemcollectcounter
- \letvalue{\e!start\v!item}\collectitemgroupitem
- \fi}
-
-%D End of plugin.
-
-\ifx\startcolumns\undefined \unexpanded\def\startcolumns[#1]{} \fi
-\ifx\stopcolumns \undefined \let\stopcolumns\relax \fi
-
-\def\dosetsymalign#1% hm, we should use one of the core-spa macros or make a helper
- {\processaction
- [#1]
- [ \v!flushleft=>\let\symalignleft\relax,
- \v!right=>\let\symalignleft\relax,
- \v!flushright=>\let\symalignleft\hfill,
- \v!left=>\let\symalignleft\hfill,
- \v!middle=>\let\symalignleft\hfil,
- \v!center=>\let\symalignleft\hfil]}
-
-\let\currentitemindenting\empty
-
-\let\dotagsetitemize\relax
-
-\def\redostartitemgroup[#1][#2]%
- {\setfalse\inlinelistitem % new, no indent (leftskip)
- \setfalse\concatnextitem % new, concat
- \setfalse\txtlistitem
- \ifhmode
- \ifconditional\autoconcatnextitem % new, concat
- \ifdim\lastskip=\itemsignal % new, concat
- \settrue\concatnextitem % new, concat
- \fi % new, concat
- \fi % new, concat
- \ifconditional\textlistitem\else\doifnotinset\v!text{#1}\par\fi % suboptimal
- \fi
- \begingroup
- % new where, ok or not / we should integrate random, intro, continue here
- % beware, the following no longer inherit from the previous level, is this ok?
- \setfalse\reverselistitem
- \setfalse\introlistitem
- \setfalse\autointrolistitem
- \setfalse\beforelistitem
- \setfalse\afterlistitem
- \setfalse\nowhitelistitem
- \setfalse\randomizeitems
- %
- \doifinsetelse\v!intro {#1}{\settrue\introlistitem }{\setfalse\introlistitem }%
- \doifinsetelse\v!random {#1}{\settrue\randomizeitems }{\setfalse\randomizeitems }%
- \doifinsetelse\v!continue{#1}{\settrue\continuelistitems}{\setfalse\continuelistitems}%
- % == \doifinsetelse\v!intro{#1}\settrue\setfalse\introlistitem
-\iftrialtypesetting
- \savestructurecounter[\currentitemgroupcounter]%[\currentitemlevel]% todo: per level
-\fi
- \global\advance\noflists\plusone
- \currentnoflists\noflists
- \noflistelements\zerocount
- \setfalse\headlistitem
- \setfalse\sublistitem
- \setfalse\symbollistitem
- \let\marsymbol\relax
- \globallet\doitemdestination\empty
- \let\symsymbol\empty
- \let\symalignleft\relax
- \the\itemgroupcommands
- \checkcurrentnofitems
- % \getitemparameter\currentitemlevel\empty
- \let\listitem\empty % ** start value
- \doifelsenothing{#1} % iffirstargument
- {\edef\@@opsymbol{\noexpand\getitemparameter\currentitemlevel\noexpand\c!symbol}%
- \letgvalueempty{\@@globalitemsymbol\currentitemlevel}%
- \global\letitemparameter\currentitemlevel\v!continue\empty
- \dosetupitemgroupvariable[\currentitemlevel][#2]}
- {\dosetupitemgroupconstant{#1}%
- \dosetupitemgroupvariable[\currentitemlevel][#2]%
- \ifconditional\continuelistitems
- \edef\@@opsymbol{\executeifdefined{\@@globalitemsymbol\currentitemlevel}{\currentitemlevel}}%
- \getitemparameter\currentitemlevel\v!continue
- \else
- \edef\@@opsymbol{\noexpand\getitemparameter\currentitemlevel\noexpand\c!symbol}%
- \global\setitemparameter\currentitemlevel\v!continue
- {\dosetupitemgroupconstant{#1}%
- \dosetupitemgroupvariable[\currentitemlevel][#2]}%
- \fi
- \def\docommand##1% \setitemmark resets \docommand
- {\doifnot{##1}{0}{\setitemmark{##1}}}%
- % \processcommalist[#1,\@@opsymbol]\docommand
- \processcommalist[#1]\docommand}% ** preset sequence or provided sequence
- % moved to here, after settings
- \ifnum\currentitemlevel=\plusone % NIEUW
- \doadaptleftskip {\getitemparameter\currentitemlevel\c!margin}%
- \doadaptleftskip {\getitemparameter\currentitemlevel\c!leftmargin}%
- \doadaptrightskip{\getitemparameter\currentitemlevel\c!rightmargin}%
- \fi
- \dosetraggedcommand{\getitemparameter\currentitemlevel\c!align}\raggedcommand
- \dosetsymalign{\getitemparameter\currentitemlevel\c!symalign}%
- %\doifsomething{\getitemparameter\currentitemlevel\c!indenting}
- % {\normalexpanded{\noexpand\setupindenting[\v!reset,\v!yes,\getitemparameter\currentitemlevel\c!indenting]}}%
- % {\normalexpanded{\noexpand\setupindenting[\getitemparameter\currentitemlevel\c!indenting]}}%
- %
- \edef\currentitemindenting{\getitemparameter\currentitemlevel\c!indenting}%
- %
- \setitemlevel{#1}% moved to here
- \ifx\listitem\empty
- \setitemmark\@@opsymbol % ** default value
- \ifx\listitem\empty
- \edef\currentitemsymbol{\currentitemlevel}% ** fall back
- \fi
- \fi
- \ifconditional\autointrolistitem\ifnum\prevgraf<3
- \settrue\introlistitem
- \fi\fi
- \ifconditional\paragraphlistitem
- \ifnum\currentitemlevel>\plusone
- \letitemparameter\currentitemlevel\c!inbetween\empty
- \fi
- \fi
- \ifconditional\packlistitem
- \letitemparameter\currentitemlevel\c!inbetween\empty
- \fi
- \doifinset\v!columns{#1}%
- {\ifinsidecolumns\else\ifcase\itemcolumndepth
- \global\itemcolumndepth\currentitemlevel\relax
- \itembeforecommand
- \processfirstactioninset
- [#1]
- [ \v!one=>\setitemparameter\currentitemlevel\c!n{1},
- \v!two=>\setitemparameter\currentitemlevel\c!n{2},
- \v!three=>\setitemparameter\currentitemlevel\c!n{3},
- \v!four=>\setitemparameter\currentitemlevel\c!n{4},
- \v!five=>\setitemparameter\currentitemlevel\c!n{5},
- \s!unknown=>\@EA\!!counta\getitemparameter\currentitemlevel\c!n]%
- \startcolumns
- [\c!n=\getitemparameter\currentitemlevel\c!n,
- \c!height=,
- \c!rule=\v!off,
- \c!balance=\v!yes,
- \c!align=\v!no]%
- \fi\fi}%
- \ifconditional\fittinglistitems
- \ifdim\currentitemmaxwidth>\zeropoint
- \esetitemparameter\currentitemlevel\c!width{\currentitemmaxwidth}%
- \fi
- \fi
- \calculatelistwidth\currentitemlevel
- \ifdim\itemgrouplistwidth>\zeropoint\relax
- \ifconditional\inlinelistitem\else
- \advance\leftskip\itemgrouplistwidth\relax
- \fi
- \fi
- \startcollectitems}
-
-% test / example
-%
-% \startnarrower[left] \startcolumns[n=3] \startitemize
-% \item \input ward \item \input ward \item \input ward
-% \stopitemize \stopcolumns\stopnarrower \blank
-%
-% \startnarrower[left] \startitemize[columns,three]
-% \item \input ward \item \input ward \item \input ward
-% \stopitemize \stopnarrower \blank
-%
-% \setupitemize[leftmargin=1.5em] \startitemize[columns,three]
-% \item \input ward \item \input ward \item \input ward
-% \stopitemize \blank
-
-\def\dorestoreitemgroup
- {\restorestructurecounter[\currentitemgroupcounter]% [\currentitemlevel]% todo: per level
- \global\advance\noflists\minusone
- \currentnoflists\noflists}
-
-\unexpanded\def\stopitemgroup
- {\stopcollectitems
- \ifconditional\textlistitem
- \removeunwantedspaces\space\ignorespaces
- \else
- \par
- \fi
- \dolistreference
- \ifconditional\firstlistitem
- \else
- \dostoptagged
- \dostoptagged
- \endgroup
- \fi % toegevoegd, eerste \som opent groep
- \ifnum\itemcolumndepth=\currentitemlevel\relax
- \stopcolumns
- \global\itemcolumndepth\zerocount
- \itemaftercommand
- \dontrechecknextindentation
- \else
- \ifnum\currentitemlevel=\plusone
- \allowitembreak
- \itemaftercommand
- \checknextindentation[\getitemparameter\currentitemlevel\c!indentnext]%
- \else
- % nieuw, not yet nobreak handling
- \ifcase\autoitemgroupspacing
- \itemaftercommand
- \or
- \itemaftercommand
- \fi
- \dontrechecknextindentation
- \fi
- \fi
- % new test, needed in sidefloats (surfaced in volker's proceedings)
-\iftrialtypesetting
- \dorestoreitemgroup
-\fi
- \ifconditional\textlistitem % else forgotten
- \endgroup
- \global\advance\itemdepth-\plusone
- \xdef\currentitemlevel{\number\itemdepth}%
- \egroup
- \else
- \endgroup
- \global\advance\itemdepth-\plusone
- \xdef\currentitemlevel{\number\itemdepth}%
- \egroup
- \par
- \fi
- \dorechecknextindentation}
-
-\newtoks\itemgroupcommands
-\newtoks\itemgroupfinalizer
-
-\def\itemgroupitem
- {\the\itemgroupfinalizer
- \doitemgroupitem}
-
-\def\itemgroupnoitem
- {\the\itemgroupfinalizer
- \doitemgroupnoitem}
-
-\def\itemgroupbutton[#1]%
- {\the\itemgroupfinalizer
- \gdef\doitemdestination{#1}%
- \itemgroupitem}
-
-\def\itemgroupdummy
- {\the\itemgroupfinalizer
- \itemgroupsymbol{\strut}\strut}
-
-\def\itemgroupsubitem
- {\the\itemgroupfinalizer
- \settrue\sublistitem
- \itemgroupitem}
-
-\def\itemgroupsymbol#1%
- {\the\itemgroupfinalizer
- \def\symsymbol{#1}%
- \settrue\symbollistitem
- \itemgroupitem}
-
-\def\itemgroupedge#1%
- {\the\itemgroupfinalizer
- \itemgroupsymbol
- {\calculatelistwidth\currentitemlevel
- \hbox to \itemgrouplistwidth
- {#1\hskip\getitemparameter\currentitemlevel\c!distance}}}
-
-\def\itemgrouphead
- {\the\itemgroupfinalizer
- \settrue\headlistitem\doitemgrouphead}
-
-\def\itemgroupitems
- {\the\itemgroupfinalizer
- \dosingleempty\doitemgroupitems}
-
-\def\doitemgroupitems[#1]%
- {\itemgroupedge
- {\dorecurse{0\getitemparameter\currentitemlevel\c!items}{\listitem\hss}%
- \unskip}}
-
-\def\itemgroupmargin#1%
- {\the\itemgroupfinalizer
- \def\marsymbol
- {\llap
- {\dosetitemattributes\currentitemlevel\c!marstyle\c!marcolor{#1}%
- \hskip\leftskip\hskip\leftmargindistance}}%
- \itemgroupitem}
-
-\appendtoks \let\item \itemgroupitem \to \itemgroupcommands
-\appendtoks \let\noitem \itemgroupnoitem \to \itemgroupcommands
-\appendtoks \letvalue\v!item \itemgroupitem \to \itemgroupcommands
-\appendtoks \let\itm \itemgroupitem \to \itemgroupcommands
-\appendtoks \let\but \itemgroupbutton \to \itemgroupcommands
-\appendtoks \let\nop \itemgroupdummy \to \itemgroupcommands
-\appendtoks \letvalue\v!sub \itemgroupsubitem \to \itemgroupcommands
-\appendtoks \letvalue\v!sym \itemgroupsymbol \to \itemgroupcommands
-\appendtoks \letvalue\v!ran \itemgroupedge \to \itemgroupcommands
-\appendtoks \letvalue\v!head \itemgrouphead \to \itemgroupcommands
-\appendtoks \letvalue\v!its \itemgroupitems \to \itemgroupcommands
-\appendtoks \letvalue\v!mar \itemgroupmargin \to \itemgroupcommands
-
-% todo : \startitem .. \stopitem
-%
-% beware, we don't group (yet) as we want to keep the left/right skip
-%
-% \startitemize
-% \startitem \stopitem
-% some intermediate text that will properly indent
-% \startitem \stopitem
-% \stopitem
-%
-% so we need to keep that property
-
-\let\startitemgroupitem\itemgroupitem
-
-\def\stopitemgroupitem
- {\ifconditional\textlistitem
- % nothing
- \else
- \endgraf
- \fi}
-
-\def\startitemgroupitemhead#1%
- {\itemgrouphead#1\par}
-
-\def\stopitemgroupitemhead
- {\ifconditional\textlistitem
- % to be tested
- \else
- \endgraf
- \fi}
-
-\appendtoks
- \letvalue{\e!start\v!item}\startitemgroupitem
- \letvalue{\e!stop \v!item}\stopitemgroupitem
-\to \itemgroupcommands
-
-\appendtoks
- \letvalue{\e!start\v!head}\startitemgroupitemhead
- \letvalue{\e!stop \v!head}\stopitemgroupitemhead
-\to \itemgroupcommands
-
-% \startitemize
-% \starthead {xx} test \stophead
-% \startitem test \stopitem
-% \startitem test \stopitem
-% \stopitemize
-
-% Sometimes the user demands get pretty weird:
-%
-% \startitemize
-% \item test
-% \item test
-% \headsym{xx} test \par test
-% \stopitemize
-
-% aligned items
-%
-% \startitemize[n,fit,broad][itemalign=flushright]
-% \dorecurse{100}{\item The first item.}
-% \stopitemize
-%
-% \setupitemgroup[itemize][each][fit]
-% \setupitemgroup[itemize][each][distance=.5em,factor=1,itemalign=flushright]
-%
-% \startitemize[n]
-% \dorecurse{100}{\item The first item.}
-% \stopitemize
-
-\appendtoks \let\headsym \itemgroupheadsym \to \itemgroupcommands
-
-\def\itemgroupheadsym#1%
- {\def\symsymbol{#1}%
- \settrue\symbollistitem
- \settrue\headlistitem
- \doitemgrouphead}
-
-% \defineitemgroup[gbitemize]
-% \setupitemgroup[gbitemize][each][headstyle=bold]
-
-% \startgbitemize
-% \txt{italian} some italians like this kind of cross||breed between
-% an itemize and a description
-% \txt{sicilians} i wonder how many sicilian mathematicians do a thesis
-% on the math involved in predicting the next big bang of the vulcano
-% \stopgbitemize
-
-\appendtoks \letvalue\v!txt\itemgrouptext \to \itemgroupcommands
-
-\newconditional\txtlistitem \setfalse\txtlistitem
-
-\def\itemgrouptext#1%
- {\def\symsymbol{#1}%
- \settrue\symbollistitem
- \settrue\txtlistitem
- \itemgroupitem}
-
-\def\dodotxtitem
- {\scratchdimen\wd\itemgroupitembox
- \advance \scratchdimen \getitemparameter\currentitemlevel\c!distance\relax
- \ifdim\scratchdimen>\itemgrouplistwidth
- \advance\scratchdimen -\itemgrouplistwidth
- \else
- \scratchdimen\zeropoint
- \fi
- \llap{\hbox to \itemgrouplistwidth{\ifconditional\sublistitem\llap{+\enspace}\fi\box\itemgroupitembox\hss}}% was: \hfill
- \hskip\scratchdimen}
-
-\def\optimizelistitemsbreak
- {\ifcase\itemcolumndepth \ifconditional\optimizelistitem
- \ifcase \currentnofitems \else
- \ifnum\currentnofitems=\plusthree
- \ifnum\noflistelements>\plusone
- \noitembreakspecial
- \fi
- \else\ifnum\currentnofitems>\plusthree
- \ifnum\noflistelements=\plustwo
- \ifconditional\introlistitem
- \noitembreak
- \else
- \noitembreakspecial
- \fi
- \else\ifnum\currentnofitems=\noflistelements\relax
- \noitembreakspecial
- \else\ifnum\noflistelements>\plustwo
- \itembreakspecial
- \else
- \ifconditional\introlistitem\else\itembreakspecial\fi
- \fi\fi\fi
- \fi\fi
- \fi
- \fi\fi}
-
-\def\dodosubitem
- {\ifconditional\sublistitem\llap{+\enspace}\fi}
-
-\def\dodolapitem
- {\llap
- {\hbox to \itemgrouplistwidth
- {\dodosubitem
- \symalignleft
- \box\itemgroupitembox % can already have a forced widt, only factor handled here
- \hfil
- \hskip\getitemparameter\currentitemlevel\c!distance}}}
-
-\def\dolistitem % evt aantal items opslaan per niveau, scheelt zoeken
- {\ifconditional\textlistitem
- % begin of item
- \else
- \par
- \fi
- \advance\noflistelements\plusone
- \optimizelistitemsbreak
- \setfalse\indentedfirstlistitem
- \ifx\currentitemindenting\empty \else
- \normalexpanded{\noexpand\setupindenting[\v!reset,\v!yes,\currentitemindenting]}%
- \doifnot{\getitemparameter\currentitemlevel\c!alignsymbol}\v!yes
- {\ifindentfirstparagraph\settrue\indentedfirstlistitem\fi}%
- \fi
- \dontleavehmode
- \ifconditional\indentedfirstlistitem
- \hskip-\parindent
- \fi
- \setbox\itemgroupitembox\hbox
- {\ifconditional\headlistitem
- \ifconditional\symbollistitem
- \dosetitemattributes\currentitemlevel\c!symstyle\c!symcolor{\symsymbol}%
- \else
- \dosetitemattributes\currentitemlevel\c!headstyle\c!headcolor{\listitem}%
- \fi
- \else
- \ifconditional\symbollistitem
- \dosetitemattributes\currentitemlevel\c!symstyle\c!symcolor{\symsymbol}%
- \else
- \dosetitemattributes\currentitemlevel\c!style\c!color{\listitem}%
- \fi
- \fi}%
- \doifsomething\doitemdestination
- {\setbox\itemgroupitembox\hbox{\directgotobox{\box\itemgroupitembox}[\doitemdestination]}}%
- \itemgroupaskedwidth\getitemparameter\currentitemlevel\c!width\relax
- \ifconditional\fittinglistitems
- \ifdim\wd\itemgroupitembox>\getitemparameter\currentitemlevel\c!maxwidth sp\relax
- \xsetitemparameter\currentitemlevel\c!maxwidth{\number\wd\itemgroupitembox}%
- \fi
- \ifdim\currentitemmaxwidth>\zeropoint
- \setbox\itemgroupitembox\simplealignedbox
- {\dimexpr\currentitemmaxwidth+\getitemparameter\currentitemlevel\c!distance\relax}
- {\getitemparameter\currentitemlevel\c!itemalign}
- {\box\itemgroupitembox\hskip\getitemparameter\currentitemlevel\c!distance}%
- \fi
- \else\ifdim\itemgroupaskedwidth>\zeropoint
- \doifsomething{\getitemparameter\currentitemlevel\c!itemalign}
- {\setbox\itemgroupitembox\simplealignedbox
- {\dimexpr\itemgroupaskedwidth+\getitemparameter\currentitemlevel\c!distance\relax}
- {\getitemparameter\currentitemlevel\c!itemalign}
- {\box\itemgroupitembox\hskip\getitemparameter\currentitemlevel\c!distance}}%
- \fi\fi
- \globallet\doitemdestination\empty
- % new, prevents loops when symbol is (not yet found) graphic
- \ht\itemgroupitembox\strutheight
- \dp\itemgroupitembox\strutdepth
- % so that content differs per run (esp mp graphics afterwards)
- \checkforrepeatedlistitem
- \ifdim\itemgroupaskedwidth<\zeropoint\relax
- \llap{\ifconditional\sublistitem\llap{+\enspace}\fi\box\itemgroupitembox\hskip\leftmargindistance}%
- \else
- \ifdim\itemgroupaskedwidth=\zeropoint\relax
- \calculatelistwidth1%
- \else
- \calculatelistwidth\currentitemlevel
- \fi
- \ifconditional\textlistitem
- \hbox{\ifconditional\sublistitem+\enspace\fi\box\itemgroupitembox\hskip\interwordspace}\nobreak
- \else\ifconditional\inlinelistitem
- \hbox to \itemgrouplistwidth{\ifconditional\sublistitem\llap{+\enspace}\fi\box\itemgroupitembox\hss}% was: \hfill
- \else\ifconditional\txtlistitem
- \dodotxtitem
- \else
- \dodolapitem
- \fi\fi\fi
- \fi
- \setevalue{\@@currentitemsymbol\currentitemlevel}%
- {\getvalue{\@@localitemsymbol\currentitemlevel}}% still problems with \uchar ?
- %{\noexpand\getvalue{\@@localitemsymbol\currentitemlevel}}% no, spoils subrefs
- \setfalse\headlistitem
- \setfalse\sublistitem
- \setfalse\symbollistitem
- \EveryPar{\ignorespaces}% needed ?
- \ifconditional\indentedfirstlistitem
- \hskip\parindent
- \fi
- \ignorespaces}
-
-% For Wolfgang Schuster
-
-% \startitemize[n,repeat]
-% \noitem \startitemize[a] \item Item 1.a. \item Item 1.b. \stopitemize
-% \noitem \startitemize[a] \item Item 2.a. \item Item 2.b. \stopitemize
-% \stopitemize
-
-\def\donolistitem % reduced \dolistitem
- {\advance\noflistelements\plusone
- \setbox\itemgroupitembox\hbox
- {\dosetitemattributes\currentitemlevel\c!style\c!color{\listitem}}%
- \checkforrepeatedlistitem
- \ignorespaces}
-
-\def\doitemgroupnoitem
- {\doadvanceitem\donolistitem}
-
-% For Frank Grieshaber and Mojca Miklavec:
-
-\newconditional\repeatlistitem
-
-\def\checkforrepeatedlistitem
- {\ifconditional\repeatlistitem
- \ifx\currentrepeatstart\empty
- \let\currentrepeatstart\currentitemlevel
- \fi
- \setbox\itemgroupitembox\hbox to \wd\itemgroupitembox{\hskip-\itemgroupaskedwidth\box\itemgroupitembox}% what a hack !
- \fi}
-
-% \startbuffer
-% \item
-% \startitemize[n]
-% \item item 1.1
-% \item item 1.2
-% \startitemize[n] \item item 1.2.1 \item item 1.2.2 \stopitemize
-% \item item 1.3
-% \stopitemize
-% \item
-% \startitemize[n] \item item 2.1 \item item 2.2 \stopitemize
-% \item item 3
-% \startitemize[n] \item item 3.1 \item item 3.2 \stopitemize
-% \item
-% \startitemize[n] \item item 4.1 \item item 4.2 \stopitemize
-% \stopbuffer
-%
-% \startitemize[n,repeat,6*broad,packed] \getbuffer \stopitemize \blank[3*big]
-% \startitemize[n,repeat,packed] \getbuffer \stopitemize \blank[3*big]
-% \setupitemize[each][atmargin][width=3em]
-% \startitemize[n,repeat,packed] \getbuffer \stopitemize
-
-\setnewconstant\autoitemgroupspacing\plustwo % 0 = voor/na, 1=tussen als geen voor 2=(prev)tussen=old/normal
-
-% todo: assume startitem ... stopitem and do an autostopitem .. cleaner for
-% elements
-
-\def\complexdoitemgroupitem[#1]%
- {\def\currentitemreference{#1}%
- \ifconditional\textlistitem
- % begin of item
- \else
- \par
- \fi
- \ifconditional\concatnextitem % new, concat
- \noitembreak % new, concat
- \fi % new, concat
- \doadvanceitem
- \ifconditional\firstlistitem
- \setfalse\firstlistitem
- \begingroup
- \ifcase\currentitemlevel
- \or % 1
- \ifcase\itemcolumndepth
- \ifconditional\introlistitem\noitembreak\fi
- \itembeforecommand
- \ifconditional\introlistitem\noitembreak\fi
- \fi
- \else % 2 en hoger
- \ifconditional\paragraphlistitem \else
- \edef\previtemlevel{\the\numexpr\currentitemlevel-1}%
- \ifcase\autoitemgroupspacing\relax % nieuw
- \itembeforecommand
- \or
- \doifelsenothing\itembeforecommand\itembeforecommand{\getitemparameter\previtemlevel\c!inbetween}%
- \else
- \getitemparameter\previtemlevel\c!inbetween
- \fi
- \fi
- \fi
- \else
-\dostoptagged
-\dostoptagged
- \ifconditional\textlistitem % was bugged: \inlinelistitem
- \ifhmode
- % WS: make the distance between items customizable, think about better default values -> see itemize-1.tex
- \normalexpanded{\doassigntextitemdistance{\getitemparameter\currentitemlevel\c!textdistance}}% HH: moved out and made configurable (sort of)
- \removeunwantedspaces\hskip\textitemdistance\relax
- \fi
- \else
- \iteminbetweencommand
- \fi
- \fi
- \ifconditional\concatnextitem
- \vskip-\dimexpr\lastskip+\lineheight\relax
- \nobreak
- \fi
-\dostarttagged\t!item\empty
-\dostarttagged\t!itemtag\empty
- \dolistitem
-\dostoptagged
- \relax
- \ifconditional\packlistitem
- \setupwhitespace[\v!none]%
- \fi
- \getitemparameter\currentitemlevel\c!inner
- \marsymbol
- \let\marsymbol\relax
-\dostarttagged\t!itemcontent\empty
- \strut % added 11-08-99
- \setfalse\concatnextitem % new, concat
- \nobreak % else problems with intext items
- \hskip\itemsignal % new, concat
- \getitemparameter\currentitemlevel\c!command} % \defaultitemcommand
-
-% \startitemize[text][space=medium]
-% \item one \item two \item three
-% \stopitemize
-
-\setvalue{\??op:\??op:\c!textdistance:\v!none}%
- {\def\textitemdistance{\zeropoint}}
-
-\def\doassigngiventextitemdistance#1%
- {\assignvalue
- {#1}%
- \textitemdistance
- {.5\interwordspace\!!plus.5\emwidth}%
- {\interwordspace \!!plus \emwidth}%
- {\emwidth \!!plus \interwordstretch\!!minus\interwordshrink}}
-
-\unexpanded\def\doassigntextitemdistance#1%
- {\ifcsname\??op:\??op:\c!textdistance:#1\endcsname
- \csname\??op:\??op:\c!textdistance:#1\endcsname
- \else
- \doassigngiventextitemdistance{#1}%
- \fi}
-
-\def\defaultitemcommand
- {\EveryPar{\ignorespaces}% needed ?
- \ignorespaces}
-
-% For Giuseppe "Oblomov" Bilotta, inspired on a suggestion by Taco
-% Hoekwater.
-%
-% \def\MyItemCommand#1{{\bf#1}\quad}
-% \setupitemgroup[itemize][command=\MyItemCommand]
-%
-% \startitemize
-% \item {test} is this okay?
-% \item {test} is this okay?
-% \item {test} is this okay?
-% \stopitemize
-
-% \def\complexitem[#1]#2\par % todo: no two pass data
-% {\startitemgroup[#1]%
-% \complexdoitemgroupitem[]\begstrut#2\endstrut\par
-% \stopitemgroup}
-
-\def\complexitem[#1]#2\par
- {\doifsomethingelse{#1}{\startitemgroup[#1]}{\startitemgroup[\v!itemize]}%
- \startitem#2\stopitem
- \stopitemgroup}
-
-\setvalue{\e!start\v!item}%
- {\startitemgroup[\v!itemize]\startitem
- \setvalue{\e!stop \v!item}{\endgraf\stopitemgroup}} % inside, else overloaded
-
-\definecomplexorsimpleempty\item
-\definecomplexorsimpleempty\doitemgroupitem
-
-% the next solution accepts \head test \type{x{x}x} test ...
-
-\let\doenditemhead\relax
-
-\def\complexdoitemgrouphead[#1]% beter in \complexdosom hangen met een if
- {\ifconditional\firstlistitem\else\allowitembreak\fi
- \ifconditional\packlistitem\else\itembeforeheadcommand\fi
- \ifconditional\firstlistitem\ifconditional\introlistitem\else\ifcase\currentitemlevel % incr in \complexdosom
- \allowitembreak
- \fi\fi\fi
- \complexdoitemgroupitem[#1]%
- \bgroup
- \dosetitemattributes\currentitemlevel\c!headstyle\c!headcolor\empty
- \ignorespaces
- \itemgroupfinalizer{\enditemhead}%
- \let\par\enditemhead} % brrrr but simple anyway
-
-\def\enditemhead
- {\removeunwantedspaces
- \egroup
- \ifconditional\textlistitem
- \space\ignorespaces
- \else
- \par
- \fi
- \noitembreak
- \ifconditional\packlistitem\else\itemafterheadcommand\fi
- \noitembreak
- \noindentation}
-
-\definecomplexorsimpleempty\head
-\definecomplexorsimpleempty\doitemgrouphead
-
-\def\sym#1%
- {\noindent
- \begingroup
- \setbox\scratchbox\hbox{\settrialtypesetting#1}%
- \setbox\scratchbox\hbox
- \ifdim\wd\scratchbox<1em to 1.5\else spread 1\fi em{#1\hfil}%
- \normalexpanded{\box\scratchbox\endgroup\hangindent\the\wd\scratchbox}%
- \ignorespaces}
-
-\setupitemgroups
- [\c!margin=\zeropoint,
- \c!leftmargin=\zeropoint,
- \c!rightmargin=\zeropoint,
- \c!indentnext=\v!yes,
- \c!width=1.5em,
- \c!factor=0,
- \c!distance=.5em,
- %\c!align=\v!normal, % definitely not \v!normal, see mails and
- %\c!align=, % debug reports of David A & Patrick G on context list
- %\c!symalign=,
- %\c!color=,
- %\c!indenting=, % untouched if empty
- %\c!style=,
- \c!marstyle=\c!type, % \c! ???
- %\c!symstyle=,
- %\c!headstyle=,
- %\c!marcolor=,
- %\c!symcolor=,
- %\c!headcolor=,
- %\c!beforehead=,
- \c!afterhead=\blank,
- \c!before=\blank,
- \c!inbetween=\blank,
- \c!after=\blank,
- %\c!stopper=.,
- \c!placestopper=\v!yes,
- \c!stopper=.,
- %\c!inner=,
- \c!n=2,
- \c!items=4,
- \c!levels=10,
- \c!lefttext=(,
- \c!righttext=),
- \c!start=1,
- \c!criterium=\v!all, % permits 0 and negative numbers
- %\c!option=,
- \c!textdistance=\v!big,
- \c!command=\defaultitemcommand,
- \c!indenting=\v!next,
- %\c!alignsymbol=v!no,
- \c!symbol=\currentitemlevel]
-
-% new:
-
-\setupitemgroups
- [\c!step=.5em, % deals with broad
- \c!distance=\zeropoint]
-
-\setupitemgroups
- [\c!prefix=\v!no,
-% \c!prefixstopper=.,
-% \c!prefixseparatorset=,
-% \c!prefixconversion=,
-% \c!prefixconversionset=,
-% \c!prefixset=,
-% \c!prefixsegments=1:100,
- \c!prefixconnector=.,
- %
- \c!numberseparatorset=,
- \c!numberconversionset=,
- \c!numberstopper=.,
- \c!numbersegments=1]
-
-\defineitemgroup [\v!itemize]
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-itm.mkvi b/Master/texmf-dist/tex/context/base/strc-itm.mkvi
new file mode 100644
index 00000000000..86acba33c09
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-itm.mkvi
@@ -0,0 +1,1573 @@
+%D \module
+%D [ file=strc-itm,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Itemgroups,
+%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 / Itemgroups}
+
+\registerctxluafile{strc-itm}{1.001}
+
+%D Cleaning up this module happened around the time when Kate Bush came up
+%D with the nicest numbered list of words: 50 Words For Snow. It's therefore
+%D no surprise that I had that cd running several times when updating this
+%D code. One of the highlights of 2011.
+
+% todo: check breaks
+% todo: check grouping
+% todo: fixedconversion
+
+% \startitemize[n,packed]
+% \item test \item test \item test
+% \stopitemize
+%
+% \startitemize[n,packed,reverse]
+% \item test \item test \item test
+% \stopitemize
+%
+% \startitemize[n,packed,reverse] \item test \item test \stopitemize
+% \startitemize[continue]
+% \item test \startitemize[n,packed] \item test \item test \stopitemize
+% \item test
+% \item test
+% \stopitemize
+% \startitemize[continue] \item test \stopitemize
+%
+% \startitemize[n,packed] \item test \item test \stopitemize
+% \startitemize[continue] \item test \stopitemize
+% \startitemize[continue] \item test \stopitemize
+%
+% \setupwhitespace[big]
+% \starttext
+% test \startitemize[joinedup] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite,before] \item test \item test \stopitemize test \par
+% test \startitemize[joinedup,nowhite,after] \item test \item test \stopitemize test \par
+% \stoptext
+%
+% test / example
+%
+% \startnarrower[left] \startcolumns[n=3] \startitemize
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \stopcolumns\stopnarrower \blank
+%
+% \startnarrower[left] \startitemize[columns,three]
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \stopnarrower \blank
+%
+% \setupitemize[leftmargin=1.5em] \startitemize[columns,three]
+% \item \input ward \item \input ward \item \input ward
+% \stopitemize \blank
+%
+% beware, we don't group (yet) as we want to keep the left/right skip
+%
+% \startitemize
+% \startitem \stopitem
+% some intermediate text that will properly indent
+% \startitem \stopitem
+% \stopitem
+%
+% so we need to keep that property
+%
+% \startitemize
+% \starthead {xx} test \stophead
+% \startitem test \stopitem
+% \startitem test \stopitem
+% \stopitemize
+%
+% Sometimes the user demands get pretty weird:
+%
+% \startitemize
+% \item test
+% \item test
+% \headsym{xx} test \par test
+% \stopitemize
+%
+% aligned items
+%
+% \startitemize[n,fit,broad][itemalign=flushright]
+% \dorecurse{100}{\item The first item.}
+% \stopitemize
+%
+% \setupitemgroup[itemize][each][fit]
+% \setupitemgroup[itemize][each][distance=.5em,factor=1,itemalign=flushright]
+%
+% \startitemize[n]
+% \dorecurse{100}{\item The first item.}
+% \stopitemize
+%
+% \defineitemgroup[gbitemize]
+% \setupitemgroup[gbitemize][each][headstyle=bold]
+%
+% \startgbitemize
+% \txt{italian} some italians like this kind of cross||breed between
+% an itemize and a description
+% \txt{sicilians} i wonder how many sicilian mathematicians do a thesis
+% on the math involved in predicting the next big bang of the vulcano
+% \stopgbitemize
+%
+% \startitemize[n,repeat]
+% \noitem \startitemize[a] \item Item 1.a. \item Item 1.b. \stopitemize
+% \noitem \startitemize[a] \item Item 2.a. \item Item 2.b. \stopitemize
+% \stopitemize
+%
+% \startbuffer
+% \item
+% \startitemize[n]
+% \item item 1.1
+% \item item 1.2
+% \startitemize[n] \item item 1.2.1 \item item 1.2.2 \stopitemize
+% \item item 1.3
+% \stopitemize
+% \item
+% \startitemize[n] \item item 2.1 \item item 2.2 \stopitemize
+% \item item 3
+% \startitemize[n] \item item 3.1 \item item 3.2 \stopitemize
+% \item
+% \startitemize[n] \item item 4.1 \item item 4.2 \stopitemize
+% \stopbuffer
+%
+% \startitemize[n,repeat,6*broad,packed] \getbuffer \stopitemize \blank[3*big]
+% \startitemize[n,repeat,packed] \getbuffer \stopitemize \blank[3*big]
+% \setupitemize[each][atmargin][width=3em]
+% \startitemize[n,repeat,packed] \getbuffer \stopitemize
+%
+% todo: assume startitem ... stopitem and do an autostopitem .. cleaner for
+% elements
+%
+% \startitemize[text][space=medium]
+% \item one \item two \item three
+% \stopitemize
+%
+% For Giuseppe "Oblomov" Bilotta, inspired on a suggestion by Taco
+% Hoekwater.
+%
+% \def\MyItemCommand#1{{\bf#1}\quad}
+% \setupitemgroup[itemize][command=\MyItemCommand]
+%
+% \startitemize
+% \item {test} is this okay?
+% \item {test} is this okay?
+% \item {test} is this okay?
+% \stopitemize
+
+\unprotect
+
+\newconditional\c_strc_itemgroups_sub
+\newconditional\c_strc_itemgroups_head
+\newconditional\c_strc_itemgroups_intro
+\newconditional\c_strc_itemgroups_randomize
+\newconditional\c_strc_itemgroups_auto_intro
+\newconditional\c_strc_itemgroups_pack
+\newconditional\c_strc_itemgroups_paragraph
+\newconditional\c_strc_itemgroups_text
+\newconditional\c_strc_itemgroups_text_saved
+\newconditional\c_strc_itemgroups_first
+\newconditional\c_strc_itemgroups_before
+\newconditional\c_strc_itemgroups_after
+\newconditional\c_strc_itemgroups_nowhite
+\newconditional\c_strc_itemgroups_joined
+\newconditional\c_strc_itemgroups_reverse
+\newconditional\c_strc_itemgroups_continue
+\newconditional\c_strc_itemgroups_fitting
+\newconditional\c_strc_itemgroups_indented_first
+\newconditional\c_strc_itemgroups_inline
+\newconditional\c_strc_itemgroups_columns
+\newconditional\c_strc_itemgroups_concat
+\newconditional\c_strc_itemgroups_txt
+\newconditional\c_strc_itemgroups_repeat
+
+% 0 = before/after
+% 1 = between unless before
+% 2 = between
+
+\newconstant \c_strc_itemgroups_spacing_mode \c_strc_itemgroups_spacing_mode\plustwo
+\newconditional\c_strc_itemgroups_optimize \settrue\c_strc_itemgroups_optimize
+\newconditional\c_strc_itemgroups_auto_concat \settrue\c_strc_itemgroups_auto_concat
+
+\newsignal \d_strc_itemgroups_signal
+
+\newbox \b_strc_itemgroups
+
+\newdimen \d_strc_itemgroups_list_width
+\newdimen \d_strc_itemgroups_asked_width
+
+\newdimen \d_strc_itemgroups_max_width % multipass
+\newcount \c_strc_itemgroups_max_items % multipass
+
+\newcount \c_strc_itemgroups_n_of_lists
+\newcount \c_strc_itemgroups_n_of_items
+\newcount \c_strc_itemgroups_nesting
+\newcount \c_strc_itemgroups_column_depth
+
+\def \v_strc_itemgroups_counter {itemgroup:\currentparentitemgroup}
+
+\let \m_strc_itemgroups_repeat_start \empty
+\def \v_strc_itemgroups_unknown_symbol {?}
+
+\let \m_strc_itemgroups_indenting \empty
+\let \m_strc_itemgroups_destination \empty
+
+\let \currentitemlevel \!!zerocount % public
+\def \currentnofitems {\the\c_strc_itemgroups_max_items}
+\def \currentitemnumber {\strc_counters_raw_sub\v_strc_itemgroups_counter\currentitemlevel} % public
+
+\newtoks \itemgroupcommands % maybe public
+
+\def \currentitemgroupsymbol {n} % here we cannot use a _ in the name
+\let \currentitemgroupconversionset \empty % here we cannot use a _ in the name
+\let \currentitemgroupsegments \empty
+
+\def\strc_itemgroups_register_status
+ {\iftrialtypesetting \else
+ \ctxcommand{registeritemgroup("\currentitemgroup",\number\c_strc_itemgroups_n_of_items,"\itemgroupparameter\c!maxwidth")}%
+ \fi}
+
+\def\strc_itemgroups_check_n_of_items % we could do this at the lua end and save a call (i.e. will be dimen and counter)
+ {\c_strc_itemgroups_max_items\ctxcommand{nofitems("\currentitemgroup",\number\c_strc_itemgroups_n_of_lists)}\relax
+ \d_strc_itemgroups_max_width\ctxcommand{maxitemwidth("\currentitemgroup",\number\c_strc_itemgroups_n_of_lists)}\scaledpoint
+ \edef\currentnofitems{\the\c_strc_itemgroups_max_items}}
+
+% todo: \dodosetreference -> \strc_counters_register_component (to be checked)
+
+\def\strc_itemgroups_insert_reference % we will make a decent number helper
+ {\iftrialtypesetting \else \ifx\currentitemreference \empty \else
+ \strc_itemgroups_insert_reference_indeed
+ \fi \fi}
+
+\def\strc_itemgroups_insert_reference_indeed % maybe we need a 'frozen counter' numberdata blob / quick hack .. .mive this to strc-ref
+ {%\setnextinternalreference
+ % no need to collect nodes in \b_strc_destination_nodes here ... maybe at some point
+ \strc_references_start_destination_nodes
+ \ctxlua {structures.references.setandgetattribute("\s!full", "\referenceprefix","\currentitemreference",
+ {
+ metadata = {
+ kind = "item",% ?
+ catcodes = \the\catcodetable,
+ xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text
+ },
+ references = {
+ % internal = \nextinternalreference, % no: this spoils references
+ block = "\currentsectionblock",
+ section = structures.sections.currentid(),
+ },
+ prefixdata = structures.helpers.simplify {
+ prefix = "\counterparameter\v_strc_itemgroups_counter\c!prefix",
+ separatorset = "\counterparameter\v_strc_itemgroups_counter\c!prefixseparatorset",
+ conversion = \!!bs\counterparameter\v_strc_itemgroups_counter\c!prefixconversion\!!es,
+ conversionset = "\counterparameter\v_strc_itemgroups_counter\c!prefixconversionset",
+ set = "\counterparameter\v_strc_itemgroups_counter\c!prefixset",
+ segments = "\counterparameter\v_strc_itemgroups_counter\c!prefixsegments",
+ % segments = "\askedprefixsegments",
+ connector = \!!bs\counterparameter\v_strc_itemgroups_counter\c!prefixconnector\!!es,
+ },
+ numberdata = structures.helpers.simplify {
+ numbers = structures.counters.compact("\v_strc_itemgroups_counter",nil,true),
+ separatorset = "\counterparameter\v_strc_itemgroups_counter\c!numberseparatorset",
+ % conversion = "\counterparameter\v_strc_itemgroups_counter\c!numberconversion",
+ % conversion = "\currentitemgroupconversionset",
+ % conversionset = "\counterparameter\v_strc_itemgroups_counter\c!numberconversionset",
+ % todo: fixedconversion = "\currentitemgroupconversionset", % temp hack:
+ conversionset = "fixed::\currentitemgroupconversionset",
+ %
+ % for the moment no stopper, we need to make references configurable first
+ % stopper = \!!bs\counterparameter\v_strc_itemgroups_counter\c!numberstopper\!!es,
+ segments = "\counterparameter\v_strc_itemgroups_counter\c!numbersegments",
+ },
+ })
+ }%
+ \strc_references_stop_destination_nodes
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ % will become an option:
+ \ifnum\lastdestinationattribute>\zerocount
+ \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
+ \strc_references_flush_destination_nodes
+ \egroup
+ \fi}
+
+%D Defining and setup:
+
+\installcorenamespace{itemgroup}
+\installcorenamespace{itemgroupoption}
+\installcorenamespace{itemgroupsetting}
+\installcorenamespace{itemgroupkeyword}
+\installcorenamespace{itemgroupalign}
+\installcorenamespace{itemgrouplocal}
+\installcorenamespace{itemgroupglobal}
+\installcorenamespace{itemgroupdistance}
+\installcorenamespace{itemgroupstack}
+\installcorenamespace{itemgroupfirst}
+\installcorenamespace{itemgroupstart}
+
+\installcommandhandler \??itemgroup {itemgroup} \??itemgroup
+
+\let\setupitemgroups\setupitemgroup
+
+\appendtoks
+ \setuevalue{\e!start\currentitemgroup}{\startitemgroup[\currentitemgroup]}%
+ \setuevalue{\e!stop \currentitemgroup}{\stopitemgroup}%
+ \setuevalue{\e!setup\currentitemgroup\e!endsetup}{\setupitemgroup[\currentitemgroup]}% obsolete
+ \let\currentparentitemgroup\currentitemgroup
+ \definecounter[\v_strc_itemgroups_counter]%
+ % beware ... we cannot use _ as the conversion set is not expanded
+ % \defineconversionset[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]%
+\to \everydefineitemgroup
+
+%D Global states
+
+\def\strc_itemgroups_store_continue_state#options#settings%
+ {\setxvalue{\??itemgroupoption \currentitemgroup}{\strc_itemgroups_process_options{#options}}%
+ \setgvalue{\??itemgroupsetting\currentitemgroup}{\setupcurrentitemgroup [#settings]}}
+
+\def\strc_itemgroups_fetch_continue_state
+ {\getvalue{\??itemgroupoption \currentitemgroup}%
+ \getvalue{\??itemgroupsetting\currentitemgroup}}
+
+\def\strc_itemgroups_reset_continue_state
+ {\letgvalue{\??itemgroupoption \currentitemgroup}\relax
+ \letgvalue{\??itemgroupsetting\currentitemgroup}\relax}
+
+% These will become keywords. We will also add a feature to keep the while set
+% together.
+
+\definevspacing[\v!item @0] [penalty:0] % allow
+\definevspacing[\v!item @10000] [penalty:10000] % no
+\definevspacing[\v!item @-5] [penalty:-5]
+\definevspacing[\v!item @5] [penalty:5]
+\definevspacing[\v!item @500] [penalty:500] % discourage .. too low, 5000 is better
+
+\def\strc_itemgroups_insert_break_when_needed#break%
+ {\ifconditional\c_strc_itemgroups_optimize
+ \ifconditional\c_strc_itemgroups_text \else
+ #break\relax
+ \fi
+ \fi}
+
+\def\strc_itemgroups_insert_breakallow {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_breakallow_indeed}
+\def\strc_itemgroups_insert_breakno {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_breakno_indeed }
+\def\strc_itemgroups_insert_break {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_break_indeed }
+\def\strc_itemgroups_insert_nobreak {\strc_itemgroups_insert_break_when_needed\strc_itemgroups_insert_nobreak_indeed }
+
+\def\strc_itemgroups_insert_breakallow_indeed{\vspacing[\v!item @0]}
+\def\strc_itemgroups_insert_breakno_indeed {\vspacing[\v!item @10000]}
+\def\strc_itemgroups_insert_break_indeed {\flushnotes
+ \vspacing[\v!item @-5]}
+\def\strc_itemgroups_insert_nobreak_indeed {\flushnotes
+ \ifinsidecolumns
+ \vspacing[\v!item @5]%
+ \else
+ \vspacing[\v!item @500]%
+ \fi}
+
+\unexpanded\def\strc_itemgroups_process_options#options%
+ {\processcommacommand[#options]\strc_itemgroups_process_option} % expansion of options is handy for xml
+
+\def\strc_itemgroups_process_option#option%
+ {\edef\itemgroupconstantvalue{#option}%
+ \ifx\itemgroupconstantvalue\empty\else
+ \splitstring\itemgroupconstantvalue\at*\to\itemgroupfirst\and\itemgroupsecond
+ \ifx\itemgroupsecond\empty
+ \let\itemgroupsecond\itemgroupfirst
+ \let\itemgroupfirst\!!plusone
+ \fi
+ \ifcsname\??itemgroupkeyword\itemgroupsecond\endcsname
+ \csname\??itemgroupkeyword\itemgroupsecond\endcsname
+ \else
+ \strc_itemgroups_set_symbol\itemgroupconstantvalue
+ \fi
+ \fi}
+
+\def\strc_itemgroups_process_set_option_pack
+ {\ifcase\c_strc_itemgroups_nesting \else
+ \settrue\c_strc_itemgroups_pack
+ \fi}
+
+\setvalue{\??itemgroupkeyword\!!zerocount}{} % ignore 0
+\setvalue{\??itemgroupkeyword\v!packed }{\strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!intro }{\settrue\c_strc_itemgroups_intro} % here? not set to false
+\setvalue{\??itemgroupkeyword\v!autointro}{\settrue\c_strc_itemgroups_auto_intro}
+\setvalue{\??itemgroupkeyword\v!broad }{\ifx\itemgroupfirst\empty
+ \let\itemgroupfirst\!!plusone
+ \fi
+ \letitemgroupparameter\c!factor\itemgroupfirst}
+\setvalue{\??itemgroupkeyword\v!text }{\settrue\c_strc_itemgroups_text
+ \settrue\c_strc_itemgroups_inline
+ \settrue\c_strc_itemgroups_joined
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!columns }{\strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!before }{\settrue\c_strc_itemgroups_before}
+\setvalue{\??itemgroupkeyword\v!after }{\settrue\c_strc_itemgroups_after}
+\setvalue{\??itemgroupkeyword\v!nowhite }{\settrue\c_strc_itemgroups_nowhite}
+\setvalue{\??itemgroupkeyword\v!margin }{\setitemgroupparameter\c!width{-2em}} % signal
+\setvalue{\??itemgroupkeyword\v!inmargin }{\setitemgroupparameter\c!width{-2em}} % signal
+\setvalue{\??itemgroupkeyword\v!atmargin }{\ifnum\c_strc_itemgroups_nesting>\plusone
+ \setitemgroupparameter\c!width{0em}%
+ \fi} % signal
+\setvalue{\??itemgroupkeyword\v!intext }{\settrue\c_strc_itemgroups_inline}
+\setvalue{\??itemgroupkeyword\v!loose }{\setfalse\c_strc_itemgroups_optimize}
+\setvalue{\??itemgroupkeyword\v!fit }{\settrue\c_strc_itemgroups_fitting}
+\setvalue{\??itemgroupkeyword\v!nofit }{\setfalse\c_strc_itemgroups_fitting}
+\setvalue{\??itemgroupkeyword\v!paragraph}{\settrue\c_strc_itemgroups_paragraph
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!joinedup }{\settrue\c_strc_itemgroups_joined
+ \strc_itemgroups_process_set_option_pack}
+\setvalue{\??itemgroupkeyword\v!serried }{\edef\itemgroupfirst{-\ifx\itemgroupfirst\empty1\else\itemgroupfirst\fi}%
+ \letitemgroupparameter\c!factor\itemgroupfirst}
+\setvalue{\??itemgroupkeyword\v!stopper }{\letitemgroupparameter\c!placestopper\v!yes} % keep {}
+\setvalue{\??itemgroupkeyword\v!unpacked }{\setfalse\c_strc_itemgroups_pack}
+\setvalue{\??itemgroupkeyword\v!repeat }{\settrue\c_strc_itemgroups_repeat}
+\setvalue{\??itemgroupkeyword\v!reverse }{\settrue\c_strc_itemgroups_reverse}
+\setvalue{\??itemgroupkeyword\v!columns }{\settrue\c_strc_itemgroups_columns}
+\setvalue{\??itemgroupkeyword\v!one }{\letitemgroupparameter\c!n\plusone}
+\setvalue{\??itemgroupkeyword\v!two }{\letitemgroupparameter\c!n\plustwo}
+\setvalue{\??itemgroupkeyword\v!three }{\letitemgroupparameter\c!n\plusthree}
+\setvalue{\??itemgroupkeyword\v!four }{\letitemgroupparameter\c!n\plusfour}
+\setvalue{\??itemgroupkeyword\v!five }{\letitemgroupparameter\c!n\plusfive}
+\setvalue{\??itemgroupkeyword\v!standard }{\setupcurrentitemgroup
+ [\c!width=1.5em,\c!factor=0,\c!distance=.5em,\c!inner=,\c!factor=0,%
+ \c!beforehead=,\c!afterhead=\blank,%
+ \c!before=\blank,\c!inbetween=\blank,\c!after=\blank]}
+
+\def\strc_itemgroups_initialize_local
+ {\setfalse\c_strc_itemgroups_inline
+ \setfalse\c_strc_itemgroups_concat
+ \setfalse\c_strc_itemgroups_txt
+ %
+ \setfalse\c_strc_itemgroups_reverse
+ \setfalse\c_strc_itemgroups_intro
+ \setfalse\c_strc_itemgroups_auto_intro
+ \setfalse\c_strc_itemgroups_before
+ \setfalse\c_strc_itemgroups_after
+ \setfalse\c_strc_itemgroups_nowhite
+ \setfalse\c_strc_itemgroups_randomize
+ \setfalse\c_strc_itemgroups_intro
+ \setfalse\c_strc_itemgroups_continue
+ % this will be a constant
+ \setfalse\c_strc_itemgroups_head
+ \setfalse\c_strc_itemgroups_sub
+ \setfalse\c_strc_itemgroups_columns
+ % to be checked
+ \let\m_strc_itemgroups_destination\empty
+ \let\strc_itemgroups_used_symbol\empty % ** start value
+ \let\strc_itemgroups_margin_symbol\empty
+ \let\strc_itemgroups_extra_symbol\empty
+ %
+ \global\letitemgroupparameter\c!maxwidth\!!zerocount
+ }
+
+\setvalue{\??itemgroupfirst\v!intro }{\settrue\c_strc_itemgroups_intro }
+\setvalue{\??itemgroupfirst\v!random }{\settrue\c_strc_itemgroups_randomize}
+\setvalue{\??itemgroupfirst\v!continue}{\settrue\c_strc_itemgroups_continue }
+
+\def\strc_itemgroups_preset_stage_one#options%
+ {\processcommacommand[#options]\strc_itemgroups_preset_stage_one_indeed}
+
+\def\strc_itemgroups_preset_stage_one_indeed#option%
+ {\ifcsname\??itemgroupfirst#option\endcsname
+ \csname\??itemgroupfirst#option\endcsname
+ \fi}
+
+\ifdefined\dotagsetitemgroup \else \let\dotagsetitemgroup\relax \fi
+
+\def\strc_itemgroups_tag_start_group
+ {\dostarttagged\t!itemgroup\currentitemgroup
+ \dotagsetitemgroup}
+
+\def\strc_itemgroups_tag_stop_group
+ {\dostoptagged}
+
+\def\strc_itemgroups_before_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \ifconditional\c_strc_itemgroups_before
+ \ifcase\c_strc_itemgroups_nesting\or\itemgroupparameter\c!before\fi
+ \else
+ \nowhitespace
+ \fi
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!before
+ \fi\fi}
+
+\def\strc_itemgroups_after_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \ifconditional\c_strc_itemgroups_after
+ \ifcase\c_strc_itemgroups_nesting\or\itemgroupparameter\c!after\fi
+ \else
+ \nowhitespace
+ \fi
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!after
+ \fi\fi}
+
+\def\strc_itemgroups_between_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!inbetween
+ \fi\fi}
+
+\def\strc_itemgroups_before_head_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!beforehead
+ \fi\fi}
+
+\def\strc_itemgroups_after_head_command
+ {\ifconditional\c_strc_itemgroups_nowhite
+ \nowhitespace
+ \else\ifconditional\c_strc_itemgroups_joined
+ % \empty
+ \else
+ \itemgroupparameter\c!afterhead
+ \fi\fi}
+
+% compatible setup command:
+
+\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
+ \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
+ \else\ifthirdargument
+ \ifx\strc_itemgroups_setup_what\v!each
+ \strc_itemgroups_setup_each{#category}{#options}%
+ \else
+ \strc_itemgroups_setup_list{#levels}{#category}{#options}%
+ \fi
+ \else\ifsecondargument
+ \strc_itemgroups_setup_each{#category}{#levels}%
+ \else
+ \strc_itemgroups_normal_setup[#category]% == settings
+ \fi\fi\fi}
+
+% can be made a bit faster
+
+\def\strc_itemgroups_setup_each#category#whatever%
+ {\doifassignmentelse{#whatever}
+ {\strc_itemgroups_normal_setup[#category][#whatever]}
+ {\strc_itemgroups_normal_setup[#category][\c!option={#whatever}]}}
+
+\def\strc_itemgroups_setup_list_level_a#category#whatever#level%
+ {\strc_itemgroups_normal_setup[#category:#level][#whatever]}
+
+\def\strc_itemgroups_setup_list_level_b#category#whatever#level%
+ {\strc_itemgroups_normal_setup[#category:#level][\c!option={#whatever}]}
+
+\def\strc_itemgroups_setup_list#subcategories#category#whatever%
+ {\doifassignmentelse{#whatever}
+ {\processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_a{#category}{#whatever}}}
+ {\processcommalist[#subcategories]{\strc_itemgroups_setup_list_level_b{#category}{#whatever}}}}
+
+\def\strc_itemgroups_increment_item_counter
+ {\ifconditional\c_strc_itemgroups_sub \else \ifx\strc_itemgroups_extra_symbol\empty
+ \strc_counters_increment_sub\v_strc_itemgroups_counter\currentitemlevel
+ \fi\fi}
+
+\unexpanded\def\strc_itemgroups_insert_item_counter
+ {\ifconditional\c_strc_itemgroups_repeat
+ \ifcase\c_strc_itemgroups_nesting
+ % skip
+ \or
+ \strc_itemgroups_insert_item_counter_indeed % this could become an option
+ \else
+ \strc_itemgroups_insert_item_counter_indeed
+ \fi
+ \else
+ \strc_itemgroups_insert_item_counter_indeed
+ \fi}
+
+\def\strc_itemgroups_insert_item_counter_indeed
+ {\begingroup
+ \strc_counters_setup
+ [\v_strc_itemgroups_counter]%
+ [%\c!prefix=\v!no,
+ \c!prefix=\itemgroupparameter\c!prefix,
+ \c!prefixstopper=\itemgroupparameter\c!prefixstopper,
+ \c!prefixseparatorset=\itemgroupparameter\c!prefixseparatorset,
+ \c!prefixconversion=\itemgroupparameter\c!prefixconversion,
+ \c!prefixconversionset=\itemgroupparameter\c!prefixseparatorset,
+ \c!prefixset=\itemgroupparameter\c!prefixset,
+ \c!prefixsegments=\itemgroupparameter\c!prefixsegments,
+ \c!prefixconnector=\itemgroupparameter\c!prefixconnector,
+ \c!criterium=\itemgroupparameter\c!criterium,
+ \c!numberorder=\ifconditional\c_strc_itemgroups_reverse\v!reverse\else\v!normal\fi,
+ \c!numberstopper=\expdoif{\itemgroupparameter\c!placestopper}\v!yes{\itemgroupparameter\c!stopper},
+ %\c!numberseparatorset=,
+ \c!numberconversionset=\v_strc_itemgroups_counter, % itemgroup:\currentparentitemgroup,
+ %\c!numberconversion=\currentitemgroupsymbol,
+ \c!numbersegments=\currentitemgroupsegments]%
+ % there will be a fixedconversion key
+ %\normalexpanded{\defineconversionset[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+ \normalexpanded{\strc_sets_define_conversion_set[\v_strc_itemgroups_counter][\currentitemgroupconversionset][\currentitemgroupsymbol]}%
+ %
+ \convertedcounter[\v_strc_itemgroups_counter]% [\number\currentitemlevel]%
+ \strc_itemgroups_insert_reference
+ \endgroup}
+
+\def\strc_itemgroups_set_symbol#symbol%
+ {\edef\strc_itemgroups_tmp_symbol{#symbol}%
+ \ifx\strc_itemgroups_tmp_symbol\empty \else
+ \doifsymboldefinedelse\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_set_symbol_symbol
+ {\doifconversiondefinedelse\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_set_symbol_conversion
+ \donothing}%
+ \fi}
+
+\def\strc_itemgroups_set_symbol_symbol
+ {\let\currentitemgroupsymbol\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_store_global_symbol\currentitemgroupsymbol
+ \strc_itemgroups_store_local_symbol\v_strc_itemgroups_unknown_symbol
+ \let\strc_itemgroups_used_symbol\strc_itemgroups_set_symbol_symbol_item
+ \let\strc_itemgroups_asked_symbol\empty}
+
+\def\strc_itemgroups_set_symbol_conversion
+ {\let\currentitemgroupsymbol\strc_itemgroups_tmp_symbol
+ \strc_itemgroups_store_global_symbol\currentitemgroupsymbol
+ \strc_itemgroups_store_local_symbol\strc_itemgroups_insert_item_counter
+ \let\strc_itemgroups_used_symbol\strc_itemgroups_set_symbol_conversion_item
+ \let\strc_itemgroups_asked_symbol\empty}
+
+\def\strc_itemgroups_set_symbol_symbol_item
+ {\symbol[\currentitemgroupsymbol]}
+
+\def\strc_itemgroups_set_symbol_conversion_item
+ {\ifconditional\c_strc_itemgroups_text
+ % maybe block stopper here, but one can as well clone an itemgroup then
+ \itemgroupparameter\c!lefttext
+ \strc_itemgroups_fetch_local_symbol
+ \itemgroupparameter\c!righttext
+ \else
+ \itemgroupparameter\c!left
+ \strc_itemgroups_fetch_local_symbol
+ \itemgroupparameter\c!right
+ \fi}
+
+\def\strc_itemgroups_calculate_list_width#level%
+ {\let\savedcurrentitemgroup\currentitemgroup
+ \edef\currentitemgroup{\currentparentitemgroup:\number#level}%
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \d_strc_itemgroups_list_width\d_strc_itemgroups_max_width
+ \else\ifnum\itemgroupparameter\c!factor>\zerocount
+ \d_strc_itemgroups_list_width\itemgroupparameter\c!step\relax
+ \ifdim\d_strc_itemgroups_list_width=\zeropoint \d_strc_itemgroups_list_width=.5em\fi
+ \multiply\d_strc_itemgroups_list_width \itemgroupparameter\c!factor
+ \advance\d_strc_itemgroups_list_width\itemgroupparameter\c!width\relax
+ \else
+ \d_strc_itemgroups_list_width\itemgroupparameter\c!width\relax
+ \fi\fi
+ \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]%
+ {\begingroup % (1)
+ \def\currentitemgroup{#category}% no nested mixing of itemgroups
+ \let\currentparentitemgroup\currentitemgroup
+ \global\advance\c_strc_itemgroups_nesting\plusone
+ \def\currentitemlevel{\number\c_strc_itemgroups_nesting}%
+ \normalexpanded{\chaintocurrentitemgroup{\currentparentitemgroup:\currentitemlevel}}%
+ \edef\currentitemgroup{\currentparentitemgroup:\currentitemlevel}%
+ %
+ \ifthirdargument
+ \strc_itemgroups_start_indeed[#options][#settings]%
+ \else\ifsecondargument
+ \doifassignmentelse{#options}
+ {\strc_itemgroups_start_indeed[][#options]}
+ {\strc_itemgroups_start_indeed[#options][]}%
+ \else
+ \strc_itemgroups_start_indeed[][]%
+ \fi\fi}
+
+\def\strc_itemgroups_start_indeed[#options][#settings]%
+ {\edef\itemgroupoptions{\itemgroupparameter\c!option}%
+ \edef\itemgroupextraoptions{#options}%
+ \ifx\itemgroupoptions\empty
+ \let\itemgroupoptions\itemgroupextraoptions
+ \else\ifx\itemgroupextraoptions\empty
+ % ok
+ \else
+ \edef\itemgroupoptions{\itemgroupoptions,\itemgroupextraoptions}%
+ \fi\fi
+ \begingroup % (2)
+ \the\itemgroupcommands
+ \let\c_strc_itemgroups_text_saved\c_strc_itemgroups_text
+ \strc_itemgroups_initialize_local
+ \strc_itemgroups_preset_stage_one\itemgroupoptions
+%
+% \ifhmode
+% \ifconditional\c_strc_itemgroups_auto_concat
+% \ifdim\lastskip=\d_strc_itemgroups_signal
+% \settrue\c_strc_itemgroups_concat
+% \fi
+% \fi
+% \ifconditional\c_strc_itemgroups_text_saved \else
+% \ifconditional\c_strc_itemgroups_text \else
+% \par
+% \fi
+% \fi
+% \fi
+%
+ \iftrialtypesetting
+ \strc_counters_save\v_strc_itemgroups_counter
+ \fi
+ \global\advance\c_strc_itemgroups_n_of_lists\plusone
+ \c_strc_itemgroups_n_of_items\zerocount
+ \strc_itemgroups_check_n_of_items
+ \ifx\itemgroupoptions\empty
+ \strc_itemgroups_setup_symbol_default
+ \strc_itemgroups_reset_continue_state
+ \setupcurrentitemgroup[#settings]%
+ \else
+ \strc_itemgroups_process_options\itemgroupoptions
+ \setupcurrentitemgroup[#settings]%
+ \ifconditional\c_strc_itemgroups_continue
+ \strc_itemgroups_setup_symbol_continue
+ \strc_itemgroups_fetch_continue_state
+ \else
+ \strc_itemgroups_setup_symbol_asked
+ \strc_itemgroups_store_continue_state\itemgroupoptions{#settings}%
+ \fi
+ \fi
+ %
+ \ifhmode
+ \ifconditional\c_strc_itemgroups_auto_concat
+ \ifdim\lastskip=\d_strc_itemgroups_signal
+ \settrue\c_strc_itemgroups_concat
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_text_saved \else
+ \ifconditional\c_strc_itemgroups_text \else
+ \par
+ \fi
+ \fi
+ \fi
+ %
+ \ifnum\c_strc_itemgroups_nesting=\plusone % NIEUW
+ \doadaptleftskip {\itemgroupparameter\c!margin}%
+ \doadaptleftskip {\itemgroupparameter\c!leftmargin}%
+ \doadaptrightskip{\itemgroupparameter\c!rightmargin}%
+ \fi
+ \dosetraggedcommand{\itemgroupparameter\c!align}\raggedcommand
+ \edef\m_strc_itemgroups_indenting{\itemgroupparameter\c!indenting}%
+ \ifnum\c_strc_itemgroups_nesting>\zerocount
+ \settrue\c_strc_itemgroups_first
+ \ifconditional\c_strc_itemgroups_continue \else
+ \strc_counters_restart_sub\v_strc_itemgroups_counter\currentitemlevel{\numexpr\itemgroupparameter\c!start-\plusone\relax}%
+ \fi
+ \fi
+ \ifx\strc_itemgroups_used_symbol\empty
+ \strc_itemgroups_set_symbol\strc_itemgroups_asked_symbol % ** default value
+ \ifx\strc_itemgroups_used_symbol\empty
+ \let\currentitemgroupsymbol\currentitemlevel % ** fall back
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_auto_intro\ifnum\prevgraf<\plusthree
+ \settrue\c_strc_itemgroups_intro
+ \fi\fi
+ \ifconditional\c_strc_itemgroups_paragraph
+ \ifnum\c_strc_itemgroups_nesting>\plusone
+ \letitemgroupparameter\c!inbetween\empty
+ \fi
+ \fi
+ \ifconditional\c_strc_itemgroups_pack
+ \letitemgroupparameter\c!inbetween\empty
+ \fi
+ \ifconditional\c_strc_itemgroups_columns
+ \ifinsidecolumns\else\ifcase\c_strc_itemgroups_column_depth
+ \global\c_strc_itemgroups_column_depth\c_strc_itemgroups_nesting % global ?
+ \strc_itemgroups_before_command
+ \strc_itemgroups_tag_start_group
+ \strc_itemgroups_start_columns
+ \fi\fi
+ \fi
+ \ifconditional\c_strc_itemgroups_fitting
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \letitemgroupparameter\c!width\d_strc_itemgroups_max_width
+ \fi
+ \fi
+ \strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \ifdim\d_strc_itemgroups_list_width>\zeropoint\relax
+ \ifconditional\c_strc_itemgroups_inline\else
+ \advance\leftskip\d_strc_itemgroups_list_width\relax
+ \fi
+ \fi
+ \ifx\m_strc_itemgroups_repeat_start\empty
+ \let\currentitemgroupconversionset \currentitemgroupsymbol
+ \edef\currentitemgroupsegments {\currentitemlevel}%
+ \else
+ \edef\currentitemgroupconversionset{\currentitemgroupconversionset,\currentitemgroupsymbol}%
+ \edef\currentitemgroupsegments {\m_strc_itemgroups_repeat_start:\currentitemlevel}%
+ \fi
+ \d_strc_itemgroups_asked_width\itemgroupparameter\c!width\relax
+ \startcollectitems}
+
+\let\startcollectitems\relax
+\let\stopcollectitems \relax
+
+\ifdefined\startcolumns \else \unexpanded\def\startcolumns[#settings]{} \fi
+\ifdefined\stopcolumns \else \unexpanded\def\stopcolumns {} \fi
+
+\letvalue{\??itemgroupalign\v!flushleft }\relax
+\letvalue{\??itemgroupalign\v!right }\relax
+\letvalue{\??itemgroupalign\v!flushright}\hfill
+\letvalue{\??itemgroupalign\v!left }\hfill
+\letvalue{\??itemgroupalign\v!middle }\hfil
+\letvalue{\??itemgroupalign\v!center }\hfil
+
+\def\strc_itemgroups_left_sym_filler
+ {\csname\??itemgroupalign\itemgroupparameter\c!symalign\endcsname}
+
+% symbols + states
+
+\def\strc_itemgroups_store_global_symbol#symbol%
+ {\letgvalue{\??itemgroupglobal\currentitemlevel}#symbol}
+
+\def\strc_itemgroups_store_local_symbol#symbol%
+ {\letgvalue{\??itemgrouplocal\currentitemlevel}#symbol}
+
+\def\strc_itemgroups_fetch_global_symbol
+ {\getvalue{\??itemgroupglobal\currentitemlevel}}
+
+\def\strc_itemgroups_fetch_local_symbol
+ {\getvalue{\??itemgrouplocal\currentitemlevel}}
+
+\def\strc_itemgroups_setup_symbol_default
+ {\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}%
+ \strc_itemgroups_store_global_symbol\empty}
+
+\def\strc_itemgroups_setup_symbol_continue
+ {\ifcsname\??itemgroupglobal\currentitemlevel\endcsname
+ \let\strc_itemgroups_asked_symbol\strc_itemgroups_fetch_global_symbol
+ \else
+ \let\strc_itemgroups_asked_symbol\currentitemlevel
+ \fi}
+
+\def\strc_itemgroups_setup_symbol_asked
+ {\edef\strc_itemgroups_asked_symbol{\itemgroupparameter\c!symbol}}
+
+\def\strc_itemgroups_start_columns
+ {\startcolumns
+ [\c!n=\itemgroupparameter\c!n,
+ \c!height=,
+ \c!rule=\v!off,
+ \c!balance=\v!yes,
+ \c!align=\v!no]}
+
+\def\strc_itemgroups_stop_columns
+ {\stopcolumns}
+
+\unexpanded\def\stopitemgroup
+ {\stopcollectitems
+ \ifconditional\c_strc_itemgroups_text
+ \removeunwantedspaces
+ \space
+ \ignorespaces
+ \else
+ \par
+ \fi
+ \strc_itemgroups_register_status
+ \ifconditional\c_strc_itemgroups_first \else
+ \dostoptagged
+ \dostoptagged
+ % \endgroup % (3)
+ \fi
+ \ifnum\c_strc_itemgroups_column_depth=\c_strc_itemgroups_nesting\relax
+ \strc_itemgroups_stop_columns
+ \global\c_strc_itemgroups_column_depth\zerocount % global ?
+ \strc_itemgroups_tag_stop_group
+ \strc_itemgroups_after_command
+ \dontrechecknextindentation
+ \else\ifnum\c_strc_itemgroups_nesting=\plusone
+ \strc_itemgroups_insert_breakallow
+ \strc_itemgroups_tag_stop_group
+ \strc_itemgroups_after_command
+ \useindentnextparameter\itemgroupparameter
+ \else
+ % nieuw, not yet nobreak handling
+ \strc_itemgroups_tag_stop_group
+ \ifcase\c_strc_itemgroups_spacing_mode
+ \strc_itemgroups_after_command
+ \or
+ \strc_itemgroups_after_command
+ \fi
+ \dontrechecknextindentation
+ \fi\fi
+ % new test, needed in sidefloats (surfaced in volker's proceedings)
+ \iftrialtypesetting
+ \strc_counters_restore\v_strc_itemgroups_counter
+ \global\advance\c_strc_itemgroups_n_of_lists\minusone
+ \fi
+ \global\advance\c_strc_itemgroups_nesting\minusone
+ \xdef\currentitemlevel{\number\c_strc_itemgroups_nesting}%
+ %\ifconditional\c_strc_itemgroups_text
+ \endgroup % (2)
+ \endgroup % (1)
+ %\else
+ % \endgroup % (2)
+ % \endgroup % (1)
+ % \par % hm, already done, and dangerous as \c_strc_itemgroups_text is already forgotten
+ %\fi
+ \dorechecknextindentation}
+
+% The items.
+
+\unexpanded\def\startitemgroupitem
+ {\dosingleempty\strc_itemgroups_start_item}
+
+\def\strc_itemgroups_start_item_first
+ {\setfalse\c_strc_itemgroups_first
+ % \begingroup % (3)
+ \ifcase\c_strc_itemgroups_nesting
+ % 0
+ \or
+ \strc_itemgroups_start_item_first_one % 1
+ \else
+ \strc_itemgroups_start_item_first_two % 2+
+ \fi}
+
+\def\strc_itemgroups_start_item_first_one
+ {\ifcase\c_strc_itemgroups_column_depth
+ \ifconditional\c_strc_itemgroups_intro\strc_itemgroups_insert_breakno\fi
+ \strc_itemgroups_before_command
+ \strc_itemgroups_tag_start_group
+ \ifconditional\c_strc_itemgroups_intro\strc_itemgroups_insert_breakno\fi
+ \fi}
+
+\def\strc_itemgroups_start_item_first_two
+ {\ifconditional\c_strc_itemgroups_paragraph\else
+ \edef\previtemlevel{\the\numexpr\c_strc_itemgroups_nesting-\plusone}%
+ \ifcase\c_strc_itemgroups_spacing_mode
+ \strc_itemgroups_before_command
+ \or
+ \doifelsenothing\strc_itemgroups_before_command % should possibly expand to empty
+ {\nameditemgroupparameter{\currentparentitemgroup:\previtemlevel}\c!inbetween}%
+ \strc_itemgroups_before_command
+ \else
+ \nameditemgroupparameter{\currentparentitemgroup:\previtemlevel}\c!inbetween
+ \fi
+ \strc_itemgroups_tag_start_group
+ \fi}
+
+\def\strc_itemgroups_start_item_next
+ {\dostoptagged % ok? what do we stop here?
+ \dostoptagged % ok? what do we stop here?
+ \ifconditional\c_strc_itemgroups_text
+ \ifhmode
+ % WS: make the distance between items customizable, think about better default values -> see itemize-1.tex
+ \strc_itemgroups_set_text_item_distance% HH: moved out and made configurable (sort of)
+ \removeunwantedspaces
+ \hskip\m_strc_itemgroups_text_distance\relax
+ \fi
+ \else
+ \strc_itemgroups_between_command
+ \fi}
+
+\unexpanded\def\strc_itemgroups_start_item[#1]% we can reuse more
+ {\def\currentitemreference{#1}%
+ \ifconditional\c_strc_itemgroups_text
+ % begin of item
+ \else
+ \par
+ \fi
+ \ifconditional\c_strc_itemgroups_concat
+ \strc_itemgroups_insert_breakno
+ \fi
+ \strc_itemgroups_increment_item_counter
+ \ifconditional\c_strc_itemgroups_first
+ \strc_itemgroups_start_item_first
+ \else
+ \strc_itemgroups_start_item_next
+ \fi
+ \ifconditional\c_strc_itemgroups_concat
+ % \vskip-\dimexpr\lastskip+\lineheight\relax
+ \vskip-\lastskip % we cannot use a \dimexpr here because
+ \vskip-\lineheight % then we loose the stretch and shrink
+ \nobreak
+ \setfalse\c_strc_itemgroups_concat
+ \fi
+ \dostarttagged\t!item\empty
+ \dostarttagged\t!itemtag\empty
+ \strc_itemgroups_insert_item
+ \dostoptagged
+ \ifconditional\c_strc_itemgroups_pack
+ \setupwhitespace[\v!none]%
+ \fi
+ \itemgroupparameter\c!inner % will become obsolete (better use setups)
+ \strc_itemgroups_margin_symbol
+ \let\strc_itemgroups_margin_symbol\relax
+ \dostarttagged\t!itemcontent\empty
+ \strut
+ \nobreak % else problems with intext items
+ \hskip\d_strc_itemgroups_signal % concat
+ \itemgroupparameter\c!command}
+
+\unexpanded\def\stopitemgroupitem
+ {\ifconditional\c_strc_itemgroups_text
+ % nothing
+ \else
+ \endgraf
+ \fi}
+
+\unexpanded\def\startitemgrouphead
+ {\dosingleempty\strc_itemgroups_start_head}
+
+\unexpanded\def\strc_itemgroups_start_head[#reference]%
+ {\ifconditional\c_strc_itemgroups_first \else
+ \strc_itemgroups_insert_breakallow
+ \fi
+ \ifconditional\c_strc_itemgroups_pack \else
+ \strc_itemgroups_before_head_command
+ \fi
+ \ifconditional\c_strc_itemgroups_first
+ \ifconditional\c_strc_itemgroups_intro \else
+ \ifcase\c_strc_itemgroups_nesting
+ \strc_itemgroups_insert_breakallow
+ \fi
+ \fi
+ \fi
+ \strc_itemgroups_start_item[#reference]%
+ \groupedcommand\strc_itemgroups_start_head_indeed\strc_itemgroups_stop_head_indeed}
+
+\unexpanded\def\stopitemgrouphead
+ {\stopitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_head_indeed
+ {\settrue\c_strc_itemgroups_head
+ \useitemgroupstyleandcolor\c!headstyle\c!headcolor\ignorespaces}
+
+\unexpanded\def\strc_itemgroups_stop_head_indeed
+ {\removeunwantedspaces
+ \ifconditional\c_strc_itemgroups_text
+ \space
+ \ignorespaces
+ \else
+ \par
+ \fi
+ \strc_itemgroups_insert_breakno
+ \ifconditional\c_strc_itemgroups_pack\else\strc_itemgroups_after_head_command\fi
+ \strc_itemgroups_insert_breakno
+ \noindentation}
+
+% Simple commands.
+
+\unexpanded\def\strc_itemgroups_start_do_item
+ {\startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_no_item % ?
+ {\startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_button[#destination]%
+ {\edef\m_strc_itemgroups_destination{#destination}%
+ \startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_symbol#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_dummy
+ {\strc_itemgroups_start_symbol\strut\strut} % two ?
+
+\unexpanded\def\strc_itemgroups_start_subitem
+ {\settrue\c_strc_itemgroups_sub
+ \startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_edge#text%
+ {\strc_itemgroups_start_symbol
+ {\strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \hbox to \d_strc_itemgroups_list_width
+ {#text\hskip\itemgroupparameter\c!distance}}}
+
+\unexpanded\def\strc_itemgroups_start_margin#text%
+ {\def\strc_itemgroups_margin_symbol % brrr
+ {\llap
+ {\begingroup
+ \useitemgroupstyleandcolor\c!marstyle\c!marcolor
+ #text% keep em/ex local
+ \endgroup
+ \hskip\dimexpr\leftskip+\leftmargindistance\relax}}%
+ \startitemgroupitem}
+
+\unexpanded\def\strc_itemgroups_start_text#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_txt
+ \startitemgroupitem}
+
+% \unexpanded\def\strc_itemgroups_start_head
+% {\settrue\c_strc_itemgroups_head
+% \startitemgrouphead}
+
+\unexpanded\def\strc_itemgroups_start_items
+ {\dosingleempty\strc_itemgroups_start_items_indeed}
+
+\unexpanded\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\stopspecialitemgroupitem
+ {\stopitemgroupitem}
+
+\letvalue{\??itemgroupstart\v!item}\strc_itemgroups_start_do_item
+\letvalue{\??itemgroupstart\v!sub }\strc_itemgroups_start_subitem
+\letvalue{\??itemgroupstart\v!sym }\strc_itemgroups_start_symbol
+\letvalue{\??itemgroupstart\v!ran }\strc_itemgroups_start_edge
+\letvalue{\??itemgroupstart\v!its }\strc_itemgroups_start_items
+\letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin
+
+\def\optimizelistitemsbreak
+ {\ifcase\c_strc_itemgroups_column_depth \ifconditional\c_strc_itemgroups_optimize
+ \ifcase \c_strc_itemgroups_max_items \else
+ \ifnum\c_strc_itemgroups_max_items=\plusthree
+ \ifnum\c_strc_itemgroups_n_of_items>\plusone
+ \strc_itemgroups_insert_nobreak
+ \fi
+ \else\ifnum\c_strc_itemgroups_max_items>\plusthree
+ \ifnum\c_strc_itemgroups_n_of_items=\plustwo
+ \ifconditional\c_strc_itemgroups_intro
+ \strc_itemgroups_insert_breakno
+ \else
+ \strc_itemgroups_insert_nobreak
+ \fi
+ \else\ifnum\c_strc_itemgroups_max_items=\c_strc_itemgroups_n_of_items\relax
+ \strc_itemgroups_insert_nobreak
+ \else\ifnum\c_strc_itemgroups_n_of_items>\plustwo
+ \strc_itemgroups_insert_break
+ \else
+ \ifconditional\c_strc_itemgroups_intro\else\strc_itemgroups_insert_break\fi
+ \fi\fi\fi
+ \fi\fi
+ \fi
+ \fi\fi}
+
+\def\strc_itemgroups_handle_text_item
+ {\scratchdimen\wd\b_strc_itemgroups
+ \advance \scratchdimen \itemgroupparameter\c!distance\relax
+ \ifdim\scratchdimen>\d_strc_itemgroups_list_width
+ \advance\scratchdimen -\d_strc_itemgroups_list_width
+ \else
+ \scratchdimen\zeropoint
+ \fi
+ \llap{\hbox to \d_strc_itemgroups_list_width{\ifconditional\c_strc_itemgroups_sub\llap{+\enspace}\fi\box\b_strc_itemgroups\hss}}% was: \hfill
+ \hskip\scratchdimen}
+
+\def\strc_itemgroups_handle_lapped_item_positive
+ {\llap
+ {\hbox to \d_strc_itemgroups_list_width
+ {\ifconditional\c_strc_itemgroups_sub
+ \llap{+\enspace}%
+ \fi
+ \strc_itemgroups_left_sym_filler
+ \box\b_strc_itemgroups % can already have a forced widt, only factor handled here
+ \hfil
+ \hskip\itemgroupparameter\c!distance}}}
+
+\def\strc_itemgroups_handle_lapped_item_negative
+ {\llap
+ {\ifconditional\c_strc_itemgroups_sub
+ \llap{+\enspace}%
+ \fi
+ \box\b_strc_itemgroups
+ \hskip\leftmargindistance}}
+
+\def\strc_itemgroups_handle_groups_text_item
+ {\hbox
+ {\ifconditional\c_strc_itemgroups_sub
+ +\enspace
+ \fi
+ \box\b_strc_itemgroups
+ \hskip\interwordspace}%
+ \nobreak}
+
+\def\strc_itemgroups_handle_groups_inline_item
+ {\hbox to \d_strc_itemgroups_list_width
+ {\ifconditional\c_strc_itemgroups_sub
+ \llap{+\enspace}%
+ \fi
+ \box\b_strc_itemgroups
+ \hss}} % was: \hfill
+
+\unexpanded\def\strc_itemgroups_start_head_sym#text%
+ {\def\strc_itemgroups_extra_symbol{#text}%
+ \settrue\c_strc_itemgroups_head
+ \strc_itemgroups_start_head}
+
+\def\strc_itemgroups_make_symbol_box
+ {\setbox\b_strc_itemgroups\hbox
+ {\ifconditional\c_strc_itemgroups_head
+ \ifx\strc_itemgroups_extra_symbol\empty
+ \useitemgroupstyleandcolor\c!headstyle\c!headcolor
+ \strc_itemgroups_used_symbol
+ \else
+ \useitemgroupstyleandcolor\c!symstyle\c!symcolor
+ \strc_itemgroups_extra_symbol
+ \fi
+ \else
+ \ifx\strc_itemgroups_extra_symbol\empty
+ \useitemgroupstyleandcolor\c!style\c!color
+ \strc_itemgroups_used_symbol
+ \else
+ \useitemgroupstyleandcolor\c!symstyle\c!symcolor
+ \strc_itemgroups_extra_symbol
+ \fi
+ \fi}%
+ \let\strc_itemgroups_extra_symbol\empty}
+
+\def\strc_itemgroups_make_fitting_box
+ {\ifdim\wd\b_strc_itemgroups>\itemgroupparameter\c!maxwidth\scaledpoint\relax % brr, sp
+ \normalexpanded{\global\setitemgroupparameter{\c!maxwidth}{\number\wd\b_strc_itemgroups}}%
+ \fi
+ \ifdim\d_strc_itemgroups_max_width>\zeropoint
+ \setbox\b_strc_itemgroups\simplealignedbox
+ {\dimexpr\d_strc_itemgroups_max_width+\itemgroupparameter\c!distance\relax}
+ {\itemgroupparameter\c!itemalign}
+ {\box\b_strc_itemgroups\hskip\itemgroupparameter\c!distance}%
+ \fi}
+
+\def\strc_itemgroups_make_aligned_box
+ {\doifsomething{\itemgroupparameter\c!itemalign}
+ {\setbox\b_strc_itemgroups\simplealignedbox
+ {\dimexpr\d_strc_itemgroups_asked_width+\itemgroupparameter\c!distance\relax}
+ {\itemgroupparameter\c!itemalign}
+ {\box\b_strc_itemgroups\hskip\itemgroupparameter\c!distance}}}
+
+\def\strc_itemgroups_make_destination_box
+ {\iftrialtypesetting \else \ifx\m_strc_itemgroups_destination\empty \else
+ \setbox\b_strc_itemgroups\hbox{\directgotobox{\box\b_strc_itemgroups}[\m_strc_itemgroups_destination]}%
+ \fi\fi}
+
+\def\strc_itemgroups_check_indenting
+ {\setfalse\c_strc_itemgroups_indented_first
+ \ifx\m_strc_itemgroups_indenting\empty \else
+ \normalexpanded{\setupindenting[\v!reset,\v!yes,\m_strc_itemgroups_indenting]}%
+ \ifconditional\c_spac_indentation_indent_first % better is to have a mode
+ \doifnot{\itemgroupparameter\c!alignsymbol}\v!yes
+ {\settrue\c_strc_itemgroups_indented_first}%
+ \fi
+ \fi}
+
+\def\strc_itemgroups_check_for_repeated
+ {\ifconditional\c_strc_itemgroups_repeat
+ \ifx\m_strc_itemgroups_repeat_start\empty
+ \edef\m_strc_itemgroups_repeat_start{\currentitemlevel}%
+ \fi
+ \fi}
+
+\def\strc_itemgroups_insert_item
+ {\ifconditional\c_strc_itemgroups_text % again?
+ % begin of item
+ \else
+ \par % done twice?
+ \fi
+ \advance\c_strc_itemgroups_n_of_items\plusone
+ \optimizelistitemsbreak
+ \strc_itemgroups_check_indenting
+ \dontleavehmode
+ \ifconditional\c_strc_itemgroups_indented_first
+ \hskip-\parindent
+ \fi
+ \strc_itemgroups_make_symbol_box
+ \strc_itemgroups_make_destination_box
+ \ifconditional\c_strc_itemgroups_fitting
+ \strc_itemgroups_make_fitting_box
+ \else\ifdim\d_strc_itemgroups_asked_width>\zeropoint
+ \strc_itemgroups_make_aligned_box
+ \fi\fi
+ \let\m_strc_itemgroups_destination\empty
+ \ht\b_strc_itemgroups\strutheight % just in case a symbols is not yet available in
+ \dp\b_strc_itemgroups\strutdepth % the current run (more a mkii mp side artifact)
+ \strc_itemgroups_check_for_repeated
+ \ifdim\d_strc_itemgroups_asked_width<\zeropoint\relax
+ \strc_itemgroups_handle_lapped_item_negative
+ \else
+ \ifdim\d_strc_itemgroups_asked_width=\zeropoint\relax
+ \strc_itemgroups_calculate_list_width\plusone
+ \else
+ \strc_itemgroups_calculate_list_width\c_strc_itemgroups_nesting
+ \fi
+ \ifconditional\c_strc_itemgroups_text
+ \strc_itemgroups_handle_groups_text_item
+ \else\ifconditional\c_strc_itemgroups_inline
+ \strc_itemgroups_handle_groups_inline_item
+ \else\ifconditional\c_strc_itemgroups_txt
+ \strc_itemgroups_handle_text_item
+ \else
+ \strc_itemgroups_handle_lapped_item_positive
+ \fi\fi\fi
+ \fi
+ \setfalse\c_strc_itemgroups_head
+ \setfalse\c_strc_itemgroups_sub
+ \ifconditional\c_strc_itemgroups_indented_first
+ \hskip\parindent
+ \fi
+ \ignorespaces}
+
+\def\strc_itemgroups_start_item_nop
+ {\let\currentitemreference\empty
+ \strc_itemgroups_increment_item_counter
+ \advance\c_strc_itemgroups_n_of_items\plusone
+ \setbox\b_strc_itemgroups\hbox
+ {\useitemgroupstyleandcolor\c!style\c!color
+ \strc_itemgroups_used_symbol}%
+ \strc_itemgroups_check_for_repeated
+ \ignorespaces}
+
+\setvalue{\??itemgroupdistance\v!none}%
+ {\let\m_strc_itemgroups_text_distance\zeropoint}
+
+\setvalue{\??itemgroupdistance\v!space}%
+ {\def\m_strc_itemgroups_text_distance{\interwordspace\!!plus\interwordstretch\!!minus\interwordshrink}}
+
+\setvalue\??itemgroupdistance % catches empty value
+ {\let\m_strc_itemgroups_text_distance\zeropoint}
+
+\unexpanded\def\strc_itemgroups_set_text_item_distance
+ {\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}%
+ \ifx\m_strc_itemgroups_text_distance\empty
+ %
+ \else\ifcsname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname
+ \csname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname
+ \else
+ \strc_itemgroups_set_text_item_distance_indeed
+ \fi\fi}
+
+\def\strc_itemgroups_set_text_item_distance_indeed
+ {\assignvalue
+ \m_strc_itemgroups_text_distance
+ \m_strc_itemgroups_text_distance
+ {.5\interwordspace\!!plus.5\emwidth}%
+ {\interwordspace \!!plus \emwidth}%
+ {\emwidth \!!plus \interwordstretch\!!minus\interwordshrink}}
+
+\unexpanded\def\strc_itemgroups_default_command
+ {\EveryPar{\ignorespaces}% needed ?
+ \ignorespaces}
+
+%D Special case:
+
+\unexpanded\def\strc_itemgroups_head#text\par
+ {\startitemgrouphead{#text}}
+
+%D The local commands:
+
+\appendtoks
+ \let\item \strc_itemgroups_start_do_item
+ \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 \stopitemgroupitemhead
+ \let\startspecialitem\startspecialitemgroupitem
+ \let\stopspecialitem \stopspecialitemgroupitem
+\to \itemgroupcommands
+
+\ifx\currentinterface \v!english \else
+
+ \appendtoks
+ \expandafter\let\csname\v!item \endcsname\strc_itemgroups_start_do_item
+ \expandafter\let\csname\v!sub \endcsname\strc_itemgroups_start_subitem
+ \expandafter\let\csname\v!sym \endcsname\strc_itemgroups_start_symbol
+ \expandafter\let\csname\v!ran \endcsname\strc_itemgroups_start_edge
+ \expandafter\let\csname\v!head \endcsname\strc_itemgroups_head
+ \expandafter\let\csname\v!its \endcsname\strc_itemgroups_start_items
+ \expandafter\let\csname\v!mar \endcsname\strc_itemgroups_start_margin
+ \expandafter\let\csname\v!txt \endcsname\strc_itemgroups_start_text
+ \expandafter\let\csname\e!start\v!item\endcsname\startitemgroupitem
+ \expandafter\let\csname\e!stop \v!item\endcsname\stopitemgroupitem
+ \expandafter\let\csname\e!start\v!head\endcsname\startitemgrouphead
+ \expandafter\let\csname\e!stop \v!head\endcsname\stopitemgrouphead
+ \to \itemgroupcommands
+
+\fi
+
+%D A nice example of a plugin:
+%D
+%D \startbuffer
+%D \startitemize[a,random,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D
+%D \startitemize[a,random,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D
+%D \startitemize[a,packed]
+%D \startitem first \stopitem \startitem second \stopitem
+%D \startitem third \stopitem \startitem fourth \stopitem
+%D \stopitemize
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+% better collectitems als conditional and a real plugin mechanism (some day)
+
+\newcount\c_strc_itemgroups_collected_stored
+\newcount\c_strc_itemgroups_collected_done
+\newcount\c_strc_itemgroups_collected_current
+
+\@EA\def\@EA\strc_itemgroups_collected_store\@EA#\@EA1\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}}
+
+\def\strc_itemgroups_collected_flush
+ {\ifconditional\c_strc_itemgroups_randomize
+ \getrandomcount\c_strc_itemgroups_collected_current\plusone\c_strc_itemgroups_collected_stored
+ \else
+ \advance\c_strc_itemgroups_collected_current\plusone
+ \fi
+ \doifdefined{\??itemgroupstack\number\c_strc_itemgroups_collected_current}
+ {\getvalue{\??itemgroupstack\number\c_strc_itemgroups_collected_current}%
+ \letbeundefined{\??itemgroupstack\number\c_strc_itemgroups_collected_current}%
+ \advance\c_strc_itemgroups_collected_done\plusone}%
+ \ifnum\c_strc_itemgroups_collected_done<\c_strc_itemgroups_collected_stored
+ \expandafter\strc_itemgroups_collected_flush
+ \fi}
+
+\unexpanded\def\stopcollectitems
+ {\ifconditional\c_strc_itemgroups_randomize
+ \c_strc_itemgroups_collected_done \zerocount
+ \c_strc_itemgroups_collected_current\zerocount
+ \ifnum\c_strc_itemgroups_collected_stored>\zerocount
+ \doubleexpandafter\strc_itemgroups_collected_flush
+ \fi
+ \fi}
+
+\unexpanded\def\startcollectitems
+ {\ifconditional\c_strc_itemgroups_randomize
+ \c_strc_itemgroups_collected_stored\zerocount
+ \letvalue{\e!start\v!item}\strc_itemgroups_collected_store
+ \fi}
+
+%D Left-overs:
+
+\unexpanded\def\item
+ {\strc_itemgroups_item_alone}
+
+\def\strc_itemgroups_item_alone[#category]#text\par
+ {\doifsomethingelse{#category}{\startitemgroup[#category]}{\startitemgroup[\v!itemize]}%
+ \startitem#text\stopitem
+ \stopitemgroup}
+
+\unexpanded\def\head
+ {\strc_itemgroups_head_alone}
+
+\def\strc_itemgroups_head_alone[#category]#head\par#body\par
+ {\doifsomethingelse{#category}{\startitemgroup[#category]}{\startitemgroup[\v!itemize]}%
+ \starthead{#head}#body\stophead
+ \stopitemgroup}
+
+\setuvalue{\e!start\v!item}%
+ {\startitemgroup[\v!itemize]%
+ \startitemgroupitem
+ \setuvalue{\e!stop\v!item}{\stopitemgroupitem\stopitemgroup}}
+
+% \def\sym#text%
+% {\noindent
+% \begingroup
+% \setbox\scratchbox\hbox{\settrialtypesetting#text}%
+% \setbox\scratchbox\hbox\ifdim\wd\scratchbox<1em to 1.5\else spread 1\fi em{#text\hfil}%
+% \normalexpanded{\box\scratchbox\endgroup\hangindent\the\wd\scratchbox}%
+% \ignorespaces}
+
+%D End of plugin.
+
+\setupitemgroup
+ [\c!margin=\zeropoint,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\zeropoint,
+ \c!indentnext=\v!yes,
+ \c!width=1.5em,
+ \c!factor=0,
+ %\c!distance=.5em, % is now:
+ \c!step=.5em, % deals with broad
+ \c!distance=\zeropoint,
+ %\c!align=\v!normal, % definitely not \v!normal !
+ %\c!symalign=,
+ %\c!color=,
+ %\c!indenting=, % untouched if empty
+ %\c!style=,
+ \c!marstyle=\v!type,
+ %\c!symstyle=,
+ %\c!headstyle=,
+ %\c!marcolor=,
+ %\c!symcolor=,
+ %\c!headcolor=,
+ %\c!beforehead=,
+ \c!symcolor=\itemgroupparameter\c!color, % new per 2012.01.17
+ \c!symstyle=\itemgroupparameter\c!style, % new per 2012.01.17
+ \c!afterhead=\blank,
+ \c!before=\blank,
+ \c!inbetween=\blank,
+ \c!after=\blank,
+ %\c!stopper=.,
+ \c!placestopper=\v!yes,
+ \c!stopper=.,
+ %\c!inner=,
+ \c!n=2,
+ \c!items=4,
+ \c!levels=10,
+ \c!lefttext=(,
+ \c!righttext=),
+ \c!start=1,
+ \c!criterium=\v!all, % permits 0 and negative numbers
+ %\c!option=,
+ \c!textdistance=\v!space, % none big medium small <dimension>
+ \c!command=\strc_itemgroups_default_command,
+ \c!indenting=\v!next,
+ %\c!alignsymbol=v!no,
+ \c!symbol=\currentitemlevel,
+ \c!prefix=\v!no,
+ %\c!prefixstopper=.,
+ %\c!prefixseparatorset=,
+ %\c!prefixconversion=,
+ %\c!prefixconversionset=,
+ %\c!prefixset=,
+ %\c!prefixsegments=1:100,
+ \c!prefixconnector=.,
+ \c!numberseparatorset=,
+ \c!numberconversionset=,
+ \c!numberstopper=.,
+ \c!numbersegments=1]
+
+\defineitemgroup
+ [\v!itemize]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-lab.mkiv b/Master/texmf-dist/tex/context/base/strc-lab.mkiv
new file mode 100644
index 00000000000..483791462c4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-lab.mkiv
@@ -0,0 +1,96 @@
+%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
+
+% labels, we could share with enumerations and forget about the text; anyhow, figure
+% labels etc can use enumerations; we keep labels for compatibility reasons; we need
+% the slightly different namespace; we can still define structure counters directly
+% (multiple levels) and use an enumeration without following text
+
+% unfinished ... no longer okay
+
+\unexpanded\def\setuplabels
+ {\getparameters[\??db]}
+
+\unexpanded\def\definelabel
+ {\dotripleargumentwithset\dodefinelabel}
+
+\def\dodefinelabel[#1][#2][#3]% #2 or #3 assignment
+ {\doenumerationinit{#1}{1}\empty
+ \getparameters[\??dd#1][\c!command=,\c!state=\v!start,\c!location=,\c!text=#1]%
+ \ifsecondargument\doifassignmentelse{#2}\donetrue\donefalse\else\donetrue\fi
+ \ifdone
+ % an independent one
+ \getparameters[\??dd#1][\s!counter=#1,\s!parent=\??db,#2]%
+ \dodefinelabelcommands{#1}{\??db}%
+ \dodefineenumerationcounter{#1}%
+ \else
+ \getparameters[\??dd#1][\s!counter=#1,\s!parent=\??dd#2,#3]%
+ \dodefinelabelcommands{#1}{\??dd#2}%
+ \fi}
+
+\def\dodefinelabelcommands#1#2%
+ {\setuevalue {#1}{\noexpand\dolabelnumbercommand {#1}}%
+ \setuevalue{\c!reset #1}{\noexpand\doresetlabelnumber {#1}}%
+ %\setuevalue{\c!set #1}{\noexpand\dosetlabelnumber {#1}}% [#2] or {#2} ?
+ \setuevalue{\e!next #1}{\noexpand\donextlabelnumber {#1}}%
+ \setuevalue{\e!increment#1}{\noexpand\doincrementlabelnumber{#1}}%
+ \setuevalue{\c!current #1}{\noexpand\docurrentlabelnumber {#1}}}
+
+% this is just for downward compatibility, we might drop it
+
+\setvalue{\??db:\c!location:\v!inmargin}{\inmargin}
+\setvalue{\??db:\c!location:\v!inleft }{\inleft}
+\setvalue{\??db:\c!location:\v!inright }{\inright}
+\setvalue{\??db:\c!location:\v!margin }{\inmargin}
+
+\def\dolabelinit#1%
+ {\def\currentdescriptionmain{#1}%
+ \def\currentdescription {#1}%
+ \def\currentdescriptionlevel{1}}
+
+\def\docurrentlabelnumber #1{\dolabelinit{#1}\dosingleempty\dodocurrentlabelnumber}
+\def\donextlabelnumber #1{\dolabelinit{#1}\dosingleempty\dodonextlabelnumber}
+\def\dolabelnumbercommand #1{\dolabelinit{#1}\dosingleempty\dodolabelnumbercommand}
+
+\def\doresetlabelnumber #1{\dolabelinit{#1}\strc_counters_reset_sub \currentdescriptionnumber\currentdescriptionlevel}
+\def\dosetlabelnumber #1#2{\dolabelinit{#1}\strc_counters_set_sub \currentdescriptionnumber\currentdescriptionlevel{#2}}
+\def\doincrementlabelnumber #1{\dolabelinit{#1}\strc_counters_increment_sub\currentdescriptionnumber\currentdescriptionlevel}
+
+\def\dodocurrentlabelnumber[#1]%
+ {\dontleavehmode
+ \writestatus{!!!}{todo: reference of label}%
+ \dotextprefix{\descriptionparameter\c!text}%
+ \convertedsubcounter[\currentdescriptionnumber][\currentdescriptionlevel]}
+
+\def\dodonextlabelnumber[#1]% todo: ref
+ {\strc_counters_increment_sub\currentdescriptionnumber\currentdescriptionlevel
+ \dodocurrentlabelnumber[\currentdescriptionnumber]}
+
+\def\dodolabelnumbercommand[#1]% todo: ref
+ {\dontleavehmode
+ \descriptionparameter\c!before
+ \begingroup
+ \strc_counters_increment_sub\currentdescriptionnumber\currentdescriptionlevel
+ \usedescriptionstyleandcolor\c!headstyle\c!headcolor
+ \executeifdefined{\??db:\c!location:\descriptionparameter\c!location}{\descriptionparameter\c!command}{\dodocurrentlabelnumber[#1]}%
+ \endgroup
+ \descriptionparameter\c!after}
+
+\setuplabels
+ [\s!parent=\??dn]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-lev.lua b/Master/texmf-dist/tex/context/base/strc-lev.lua
index ff30c3f91ad..4ca049d7a20 100644
--- a/Master/texmf-dist/tex/context/base/strc-lev.lua
+++ b/Master/texmf-dist/tex/context/base/strc-lev.lua
@@ -18,29 +18,33 @@ local level, levels, categories = 0, sections.levels, { }
storage.register("structures/sections/levels", levels, "structures.sections.levels")
-function sections.defineautolevels(category,list)
+function commands.definesectionlevels(category,list)
levels[category] = utilities.parsers.settings_to_array(list)
end
-function sections.startautolevel(category)
+function commands.startsectionlevel(category)
category = category ~= "" and category or default
level = level + 1
local lc = levels[category]
if not lc or level > #lc then
- context.nostartstructurehead { format("%s:%s",category,level) }
+ context.nostarthead { format("%s:%s",category,level) }
else
- context.dostartstructurehead { lc[level] }
+ context.dostarthead { lc[level] }
end
insert(categories,category)
end
-function sections.stopautolevel()
+function commands.stopsectionlevel()
local category = remove(categories)
- local lc = levels[category]
- if not lc or level > #lc then
- context.nostopstructurehead { format("%s:%s",category,level) }
+ if category then
+ local lc = levels[category]
+ if not lc or level > #lc then
+ context.nostophead { format("%s:%s",category,level) }
+ else
+ context.dostophead { lc[level] }
+ end
+ level = level - 1
else
- context.dostopstructurehead { lc[level] }
+ -- error
end
- level = level - 1
end
diff --git a/Master/texmf-dist/tex/context/base/strc-lev.mkiv b/Master/texmf-dist/tex/context/base/strc-lev.mkiv
deleted file mode 100644
index 4c4605bcd14..00000000000
--- a/Master/texmf-dist/tex/context/base/strc-lev.mkiv
+++ /dev/null
@@ -1,92 +0,0 @@
-%D \module
-%D [ file=strc-lev,
-%D version=2010.09.23,
-%D title=\CONTEXT\ Structure Macros,
-%D subtitle=Automatic Levels,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
-%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 / Automatic Levels}
-
-%D This module is the result of a discussion between Alan Braslau and
-%D me. I used to have a private (\MKII) module for this but the new
-%D structure code in \MKIV\ is more suitable for this so now we have
-%D it as core functionality. For the moment this an experiment that
-%D Alan and I conduct so it might evolve.
-
-\registerctxluafile{strc-lev}{1.001}
-
-\unprotect
-
-\unexpanded\def\definestructurelevels{\dodoubleargument\dodefinestructurelevels}
-\unexpanded\def\startstructurelevel {\dosingleempty\dostartstructurelevel}
-
-\unexpanded\def\dodefinestructurelevels[#1][#2]{\ctxlua{structures.sections.defineautolevels("#1","#2")}}
-\unexpanded\def\dostartstructurelevel [#1]{\ctxlua{structures.sections.startautolevel("#1")}}
-\unexpanded\def\stopstructurelevel {\ctxlua{structures.sections.stopautolevel()}}
-
-\unexpanded\def\nostartstructurehead{\dotripleargument\nonostartstructurehead}
-\unexpanded\def\nostopstructurehead {\dosingleargument\nonostopstructurehead }
-
-\unexpanded\def\dostartstructurelevel[#1]%
- {\doifassignmentelse{#1}
- {\ctxlua{structures.sections.startautolevel("\v!default")}[#1]}
- {\ctxlua{structures.sections.startautolevel("#1")}}}
-
-\unexpanded\def\nonostartstructurehead[#1][#2][#3]%
- {\blank
- \noindentation{\tttf[start missing structure level #1]}
- \blank}
-
-\unexpanded\def\nonostopstructurehead[#1]%
- {\blank
- \noindentation{\tttf[stop missing structure level #1]}
- \blank}
-
-\definestructurelevels
- [\v!default]
- [\v!chapter,
- \v!section,
- \v!subsection,
- \v!subsubsection,
- \v!subsubsubsection,
- \v!subsubsubsubsection]
-
-\protect \endinput
-
-% \starttext
-
-% \definehead[xxxxxxsection][subsubsection]
-% \setuphead [xxxxxxsection][color=red]
-
-% \definestructurelevels[main][chapter,section,subsection,subsubsection]
-% \definestructurelevels[next][chapter,section,subsection,xxxxxxsection]
-
-% \startstructurelevel [main] [title=first top level]
-
-% \startstructurelevel [main] [title=first lower level]
-% \startstructurelevel [main] [title=second lower level]
-% \startstructurelevel [main] [title=third lower level]
-% test
-% \stopstructurelevel
-% \stopstructurelevel
-% \stopstructurelevel
-
-% \startstructurelevel [main] [title=first lower level]
-% \startstructurelevel [main] [title=second lower level]
-% \startstructurelevel [next] [title=third lower level]
-% test
-% \stopstructurelevel
-% \stopstructurelevel
-% \stopstructurelevel
-
-% \stopstructurelevel
-
-
-% \stoptext
-
diff --git a/Master/texmf-dist/tex/context/base/strc-lev.mkvi b/Master/texmf-dist/tex/context/base/strc-lev.mkvi
new file mode 100644
index 00000000000..b3ec2a2d5a4
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-lev.mkvi
@@ -0,0 +1,96 @@
+%D \module
+%D [ file=strc-lev,
+%D version=2010.09.23,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Automatic Levels,
+%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 / Automatic Levels}
+
+%D This module is the result of a discussion between Alan Braslau and
+%D me. I used to have a private (\MKII) module for this but the new
+%D structure code in \MKIV\ is more suitable for this so now we have
+%D it as core functionality. For the moment this an experiment that
+%D Alan and I conduct so it might evolve.
+
+\registerctxluafile{strc-lev}{1.001}
+
+\unprotect
+
+\unexpanded\def\definesectionlevels{\dodoubleargument\strc_levels_define}
+\unexpanded\def\startsectionlevel {\dosingleempty \strc_levels_start }
+
+\unexpanded\def\strc_levels_define[#category][#list]{\ctxcommand{definesectionlevels("#category","#list")}}
+\unexpanded\def\strc_levels_start [#category]{\ctxcommand{startsectionlevel("#category")}}
+\unexpanded\def\stopsectionlevel {\ctxcommand{stopsectionlevel()}}
+
+\unexpanded\def\nostarthead{\dotripleargument\strc_levels_start_nop} % used at the lua end
+\unexpanded\def\nostophead {\dosingleargument\strc_levels_stop_nop } % used at the lua end
+
+\unexpanded\def\strc_levels_start[#category]%
+ {\doifassignmentelse{#category}
+ {\ctxcommand{startsectionlevel("\v!default")}[#category]}
+ {\ctxcommand{startsectionlevel("#category")}}}
+
+\unexpanded\def\strc_levels_start_nop[#category][#settings][#userdata]%
+ {\blank
+ \noindentation{\tttf[start missing section level #category]}
+ \blank}
+
+\unexpanded\def\strc_levels_stop_nop[#category]%
+ {\blank
+ \noindentation{\tttf[stop missing section level #category]}
+ \blank}
+
+\definesectionlevels
+ [\v!default]
+ [\v!chapter,
+ \v!section,
+ \v!subsection,
+ \v!subsubsection,
+ \v!subsubsubsection,
+ \v!subsubsubsubsection]
+
+
+\let\definestructurelevels\definesectionlevels
+\let\startstructurelevel \startsectionlevel
+\let\stopstructurelevel \stopsectionlevel
+
+\protect \endinput
+
+% \starttext
+%
+% \definehead[xxxxxxsection][subsubsection]
+% \setuphead [xxxxxxsection][color=red]
+%
+% \definesectionlevels[main][chapter,section,subsection,subsubsection]
+% \definesectionlevels[next][chapter,section,subsection,xxxxxxsection]
+%
+% \startsectionlevel [main] [title=first top level]
+%
+% \startsectionlevel [main] [title=first lower level]
+% \startsectionlevel [main] [title=second lower level]
+% \startsectionlevel [main] [title=third lower level]
+% test
+% \stopsectionlevel
+% \stopsectionlevel
+% \stopsectionlevel
+%
+% \startsectionlevel [main] [title=first lower level]
+% \startsectionlevel [main] [title=second lower level]
+% \startsectionlevel [next] [title=third lower level]
+% test
+% \stopsectionlevel
+% \stopsectionlevel
+% \stopsectionlevel
+%
+% \stopsectionlevel
+%
+% \stoptext
+
diff --git a/Master/texmf-dist/tex/context/base/strc-lnt.mkii b/Master/texmf-dist/tex/context/base/strc-lnt.mkii
index ef09842cd7a..3c878a8d232 100644
--- a/Master/texmf-dist/tex/context/base/strc-lnt.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-lnt.mkii
@@ -5,7 +5,7 @@
%D subtitle=Line Notes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-lnt.mkiv b/Master/texmf-dist/tex/context/base/strc-lnt.mkvi
index 442a9378fb6..f07ce783983 100644
--- a/Master/texmf-dist/tex/context/base/strc-lnt.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-lnt.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Line Notes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,58 +17,71 @@
\unprotect
-\newcount\noflinenotes \newif\iftracelinenotes % will be tracker
+\installcorenamespace{linenote}
-\def\dohandlelinenote#1#2#3%
- {\bgroup
- \def\linenotelinenumber##1{\inlinerange[#2]}% ##1 == order
- \setupnote[#1][\c!numbercommand=\linenotelinenumber,\c!textcommand=\gobbleoneargument]% todo: deep hook
- \getvalue{\??vn:ln:#1}{#3}%
- \egroup}
+\let\setuplinenote\setupnote
+
+\newcount\c_strc_linenotes
-\def\dotracedlinenote#1%
+\unexpanded\def\definelinenote
+ {\dotripleempty\strc_linenotes_define}
+
+\def\strc_linenotes_define[#1][#2][#3]%
+ {\definenote[#1][#2][#3]%
+ \expandafter\let\csname\??linenote#1\expandafter\endcsname\csname#1\endcsname % use copy command
+ \setuevalue {#1}{\strc_linenotes_direct{#1}}%
+ \setuevalue{\e!start#1}{\strc_linenotes_start {#1}}%
+ \setuevalue{\e!stop #1}{\strc_linenotes_stop }}
+
+\unexpanded\def\strc_linenotes_direct#1#2%
+ {\global\advance\c_strc_linenotes\plusone
+ \strc_linenotes_indeed{#1}{\the\c_strc_linenotes}{#2}%
+ \strc_linenotes_traced\empty
+ \normalexpanded{\someline[\the\c_strc_linenotes]}}
+
+\unexpanded\def\strc_linenotes_start#1[#2]#3%
+ {\global\advance\c_strc_linenotes\plusone
+ \strc_linenotes_indeed{#1}{#2}{#3}%
+ \strc_linenotes_traced{#2}%
+ \startline[#2]}
+
+\unexpanded\def\strc_linenotes_stop[#1]%
+ {\stopline[#1]}
+
+\unexpanded\def\strc_linenotes_indeed#1#2#3% will be redone
+ {\begingroup
+ % we keep things local so we can use it as regular note too
+ \unexpanded\def\linenotelinenumber##1{\inlinerange[#2]}% ##1 == order
+% \setupnotation[#1][\c!numbercommand=\linenotelinenumber]% todo: deep hook
+% \setupnote[#1][\c!textcommand=\gobbleoneargument]% todo: deep hook
+ \edef\currentnotation{#1}%
+ \let\currentnote\currentnotation
+ \letnotationparameter\c!numbercommand\linenotelinenumber% todo: deep hook
+ \letnoteparameter \c!textcommand \gobbleoneargument % todo: deep hook
+ \relax\getvalue{\??linenote#1}{#3}%
+ \endgroup}
+
+\let\strc_linenotes_traced\gobbleoneargument
+
+\def\strc_linenotes_traced_indeed#1%
{\iftracelinenotes
\hbox to \zeropoint
{\forgetall
\hsize\zeropoint
\hss
- \vbox to \strutheight{\llap{\red\infofont\setstrut\the\noflinenotes}\vss}%
+ \vbox to \strutheight{\llap{\red\infofont\setstrut\the\c_strc_linenotes}\vss}%
{\color[blue]{\vl}}%
\vbox to \strutheight{\rlap{\red\infofont\setstrut#1}\vss}%
\hss}%
\prewordbreak
\fi}
-\def\dolinenote#1#2%
- {\global\advance\noflinenotes\plusone
- \dohandlelinenote{#1}{\the\noflinenotes}{#2}%
- \dotracedlinenote\empty
- \normalexpanded{\someline[\the\noflinenotes]}}
-
-\def\dostartlinenote#1[#2]#3%
- {\global\advance\noflinenotes\plusone
- \dohandlelinenote{#1}{#2}{#3}%
- \dotracedlinenote{#2}%
- \startline[#2]}
-
-\def\dostoplinenote#1[#2]%
- {\stopline[#2]}
-
-\unexpanded\def\definelinenote
- {\dotripleempty\dodefinelinenote}
-
-\def\dodefinelinenote[#1][#2][#3]%
- {\dodefinenote[#1][#2][#3]% do as we need to test for arguments
- \expandafter\let\csname\??vn:ln:#1\expandafter\endcsname\csname#1\endcsname % use copy command
- \setuvalue {#1}{\dolinenote {#1}}%
- \setuvalue{\e!start#1}{\dostartlinenote{#1}}%
- \setuvalue{\e!stop #1}{\dostoplinenote {#1}}}
-
-\let\setuplinenote\setupnote
+\unexpanded\def\tracelinenotes
+ {\let\strc_linenotes_traced\strc_linenotes_traced_indeed}
% We predefine one, namely \type {\linenote} cum suis.
-\definelinenote[\v!linenote]
+% \definelinenote[\v!linenote]
% beware: line numbers are added later on so grouping setups is a bad idea
%
diff --git a/Master/texmf-dist/tex/context/base/strc-lst.lua b/Master/texmf-dist/tex/context/base/strc-lst.lua
index 21015e43a21..48aab78dbfe 100644
--- a/Master/texmf-dist/tex/context/base/strc-lst.lua
+++ b/Master/texmf-dist/tex/context/base/strc-lst.lua
@@ -11,47 +11,50 @@ if not modules then modules = { } end modules ['strc-lst'] = {
-- section, metadata cache (internal then has to move up one level) or a
-- shared cache [we can use a fast and stupid serializer]
+-- todo: tag entry in list is crap
+--
+-- move more to commands
+
local format, gmatch, gsub = string.format, string.gmatch, string.gsub
local tonumber = tonumber
-local texsprint, texprint, texwrite, texcount = tex.sprint, tex.print, tex.write, tex.count
+local texcount = tex.count
local concat, insert, remove = table.concat, table.insert, table.remove
local lpegmatch = lpeg.match
local simple_hash_to_string, settings_to_hash = utilities.parsers.simple_hash_to_string, utilities.parsers.settings_to_hash
local allocate, checked = utilities.storage.allocate, utilities.storage.checked
-local trace_lists = false trackers.register("structures.lists", function(v) trace_lists = v end)
-
-local report_lists = logs.reporter("structure","lists")
+local trace_lists = false trackers.register("structures.lists", function(v) trace_lists = v end)
-local ctxcatcodes = tex.ctxcatcodes
+local report_lists = logs.reporter("structure","lists")
-local structures = structures
-local lists = structures.lists
-local sections = structures.sections
-local helpers = structures.helpers
-local documents = structures.documents
-local pages = structures.pages
-local tags = structures.tags
-local references = structures.references
+local structures = structures
+local lists = structures.lists
+local sections = structures.sections
+local helpers = structures.helpers
+local documents = structures.documents
+local pages = structures.pages
+local tags = structures.tags
+local references = structures.references
-local collected = allocate()
-local tobesaved = allocate()
-local cached = allocate()
-local pushed = allocate()
+local collected = allocate()
+local tobesaved = allocate()
+local cached = allocate()
+local pushed = allocate()
-lists.collected = collected
-lists.tobesaved = tobesaved
+lists.collected = collected
+lists.tobesaved = tobesaved
-lists.enhancers = lists.enhancers or { }
-lists.internals = allocate(lists.internals or { }) -- to be checked
-lists.ordered = allocate(lists.ordered or { }) -- to be checked
-lists.cached = cached
-lists.pushed = pushed
+lists.enhancers = lists.enhancers or { }
+lists.internals = allocate(lists.internals or { }) -- to be checked
+lists.ordered = allocate(lists.ordered or { }) -- to be checked
+lists.cached = cached
+lists.pushed = pushed
-references.specials = references.specials or { }
+references.specials = references.specials or { }
-local variables = interfaces.variables
-local matchingtilldepth, numberatdepth = sections.matchingtilldepth, sections.numberatdepth
+local variables = interfaces.variables
+local matchingtilldepth = sections.matchingtilldepth
+local numberatdepth = sections.numberatdepth
-- -- -- -- -- --
@@ -104,12 +107,19 @@ local function initializer()
end
end
end
+ if r then
+ r.listindex = i -- handy to have
+ end
end
end
job.register('structures.lists.collected', tobesaved, initializer)
-function lists.push(t)
+function lists.addto(t)
+ local u = t.userdata
+ if u and type(u) == "string" then
+ t.userdata = helpers.touserdata(u) -- nicer at the tex end
+ end
local m = t.metadata
local r = t.references
local i = (r and r.internal) or 0 -- brrr
@@ -118,12 +128,34 @@ function lists.push(t)
p = #cached + 1
cached[p] = helpers.simplify(t)
pushed[i] = p
+ r.listindex = p
+ end
+ --
+ local setcomponent = references.setcomponent
+ if setcomponent then
+ setcomponent(t) -- might move to the tex end
end
- texwrite(p)
+ return p
end
-function lists.doifstoredelse(n)
- commands.doifelse(cached[tonumber(n)])
+function lists.discard(n)
+ n = tonumber(n)
+ if not n then
+ -- maybe an error message
+ elseif n == #cached then
+ cached[n] = nil
+ n = n -1
+ while n > 0 and cached[n] == false do
+ cached[n] = nil -- collect garbage
+ n = n - 1
+ end
+ else
+ cached[n] = false
+ end
+end
+
+function lists.iscached(n)
+ return cached[tonumber(n)]
end
-- this is the main pagenumber enhancer
@@ -144,7 +176,12 @@ function lists.enhance(n)
local kind = metadata.kind
local name = metadata.name
if references then
- references.tag = tags.getid(kind,name)
+ -- is this used ?
+ local tag = tags.getid(kind,name)
+ if tag and tag ~= "?" then
+ references.tag = tag
+ end
+ --~ references.listindex = n
end
-- specific enhancer (kind of obsolete)
local enhancer = kind and lists.enhancers[kind]
@@ -214,7 +251,7 @@ local sorters = {
end,
}
--- some day soon we will pass a table
+-- some day soon we will pass a table .. also split the function
local function filtercollected(names, criterium, number, collected, forced, nested, sortorder) -- names is hash or string
local numbers, depth = documents.data.numbers, documents.data.depth
@@ -377,6 +414,20 @@ local function filtercollected(names, criterium, number, collected, forced, nest
else
return filtercollected(names,variables.current,number,collected,forced,false,sortorder)
end
+ elseif criterium == variables.component then
+ -- special case, no structure yet
+ local component = resolvers.jobs.currentcomponent() or ""
+ if component ~= "" then
+ for i=1,#collected do
+ local v = collected[i]
+ local r = v.references
+ local m = v.metadata
+ if r and r.component == component and (m and names[m.name] or all) then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ end
else -- sectionname, number
-- not the same as register
local depth = sections.getlevel(criterium)
@@ -386,17 +437,23 @@ local function filtercollected(names, criterium, number, collected, forced, nest
detail = format("depth: %s, number: %s, numbers: %s, startset: %s",depth,number,(#t>0 and concat(t,".",1,depth)) or "?",#collected)
end
if number > 0 then
- local parent = nested and nested.parent and nested.parent.numberdata.numbers -- so local as well as nested
+ local pnumbers = nil
+ local pblock = block
+ local parent = nested and nested.parent
+ if parent then
+ pnumbers = parent.numberdata.numbers or pnumbers -- so local as well as nested
+ pblock = parent.references.block or pblock
+ end
for i=1,#collected do
local v = collected[i]
local r = v.references
- if r then -- block ?
+ if r and (not block or not r.block or pblock == r.block) then
local sectionnumber = sections.collected[r.section]
if sectionnumber then
local metadata = v.metadata
local cnumbers = sectionnumber.numbers
if cnumbers then
- if (all or names[metadata.name or false]) and #cnumbers >= depth and matchingtilldepth(depth,cnumbers,parent) then
+ if (all or names[metadata.name or false]) and #cnumbers >= depth and matchingtilldepth(depth,cnumbers,pnumbers) then
nofresult = nofresult + 1
result[nofresult] = v
end
@@ -454,7 +511,7 @@ function lists.process(specification)
local r = lists.result[i]
local m = r.metadata
local s = specials and r.numberdata and specials[zerostrippedconcat(r.numberdata.numbers,".")] or ""
- context.processlistofstructure(m.name,m.kind,i,s)
+ context.strclistsentryprocess(m.name,m.kind,i,s)
end
end
@@ -468,7 +525,7 @@ function lists.userdata(name,r,tag) -- to tex (todo: xml)
local userdata, metadata = result.userdata, result.metadata
local str = userdata and userdata[tag]
if str then
- texsprint(metadata and metadata.catcodes or ctxcatcodes,str)
+ return str, metadata
end
end
end
@@ -481,20 +538,18 @@ function lists.uservalue(name,r,tag,default) -- to lua
end
function lists.size()
- texprint(#lists.result)
+ return #lists.result
end
function lists.location(n)
local l = lists.result[n]
- texsprint(l.references.internal or n)
+ return l and l.references.internal or n
end
function lists.label(n,default)
local l = lists.result[n]
local t = l.titledata
- if t then
- texsprint(t.label or default or "")
- end
+ return t and t.label or default or ""
end
function lists.sectionnumber(name,n,spec)
@@ -516,35 +571,37 @@ function lists.title(name,n,tag) -- tag becomes obsolete
end
end
-function lists.savedtitle(name,n,tag)
+function lists.hastitledata(name,n,tag)
local data = cached[tonumber(n)]
if data then
local titledata = data.titledata
if titledata then
- helpers.title(titledata[tag] or titledata.title or "",data.metadata)
+ return (titledata[tag] or titledata.title or "") == ""
end
end
+ return false
end
-function lists.savednumber(name,n)
- local data = cached[tonumber(n)]
+function lists.haspagedata(name,n)
+ local data = lists.result[n]
if data then
- local numberdata = data.numberdata
- if numberdata then
- sections.typesetnumber(numberdata,"number",numberdata or false)
+ local references = data.references
+ if references and references.realpage then -- or references.pagedata
+ return true
end
end
+ return false
end
-function lists.savedprefixednumber(name,n)
- local data = cached[tonumber(n)]
+function lists.hasnumberdata(name,n)
+ local data = lists.result[n]
if data then
- helpers.prefix(data,data.prefixdata)
local numberdata = data.numberdata
if numberdata then
- sections.typesetnumber(numberdata,"number",numberdata or false)
+ return true
end
end
+ return false
end
function lists.prefix(name,n,spec)
@@ -563,9 +620,9 @@ function lists.realpage(name,n)
local data = lists.result[n]
if data then
local references = data.references
- texsprint(references and references.realpage or 0)
+ return references and references.realpage or 0
else
- texsprint(0)
+ return 0
end
end
@@ -614,3 +671,75 @@ function references.specials.order(var,actions) -- references.specials !
end
end
end
+
+-- interface (maybe strclistpush etc)
+
+commands.pushlist = lists.pushnesting
+commands.poplist = lists.popnesting
+commands.enhancelist = lists.enhance
+commands.processlist = lists.process
+commands.analyzelist = lists.analyze
+commands.listtitle = lists.title
+commands.listprefixednumber = lists.prefixednumber
+commands.listprefixedpage = lists.prefixedpage
+
+
+function commands.addtolist (...) context(lists.addto (...)) end -- we could use variables instead of print
+function commands.listsize (...) context(lists.size (...)) end
+function commands.listlocation(...) context(lists.location(...)) end
+function commands.listlabel (...) context(lists.label (...)) end
+function commands.listrealpage(...) context(lists.realpage(...)) end
+
+function commands.listuserdata(...)
+ local str, metadata = lists.userdata(...)
+ if str then
+ -- local catcodes = metadata and metadata.catcodes
+ -- if catcodes then
+ -- context.sprint(catcodes,str)
+ -- else
+ -- context(str)
+ -- end
+ helpers.title(str,metadata)
+ end
+end
+
+-- we could also set variables .. names will change (when this module is done)
+-- maybe strc_lists_savedtitle etc
+
+function commands.doiflisthastitleelse (...) commands.doifelse(lists.hastitledata (...)) end
+function commands.doiflisthaspageelse (...) commands.doifelse(lists.haspagedata (...)) end
+function commands.doiflisthasnumberelse(...) commands.doifelse(lists.hasnumberdata(...)) end
+function commands.doiflisthasentry (n) commands.doifelse(lists.iscached (n )) end
+
+function commands.savedlistnumber(name,n)
+ local data = cached[tonumber(n)]
+ if data then
+ local numberdata = data.numberdata
+ if numberdata then
+ sections.typesetnumber(numberdata,"number",numberdata or false)
+ end
+ end
+end
+
+function commands.savedlisttitle(name,n,tag)
+ local data = cached[tonumber(n)]
+ if data then
+ local titledata = data.titledata
+ if titledata then
+ helpers.title(titledata[tag] or titledata.title or "",data.metadata)
+ end
+ end
+end
+
+function commands.savedlistprefixednumber(name,n)
+ local data = cached[tonumber(n)]
+ if data then
+ local numberdata = data.numberdata
+ if numberdata then
+ helpers.prefix(data,data.prefixdata)
+ sections.typesetnumber(numberdata,"number",numberdata or false)
+ end
+ end
+end
+
+commands.discardfromlist = lists.discard
diff --git a/Master/texmf-dist/tex/context/base/strc-lst.mkii b/Master/texmf-dist/tex/context/base/strc-lst.mkii
index 527966354ba..ffb1a4dbde4 100644
--- a/Master/texmf-dist/tex/context/base/strc-lst.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-lst.mkii
@@ -5,7 +5,7 @@
%D subtitle=Lists,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-lst.mkiv b/Master/texmf-dist/tex/context/base/strc-lst.mkiv
deleted file mode 100644
index c2be8338a45..00000000000
--- a/Master/texmf-dist/tex/context/base/strc-lst.mkiv
+++ /dev/null
@@ -1,1080 +0,0 @@
-%D \module
-%D [ file=strc-lst,
-%D version=2008.10.20,
-%D title=\CONTEXT\ Structure Macros,
-%D subtitle=Lists,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
-%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 / Lists}
-
-\registerctxluafile{strc-lst}{1.001}
-
-\unprotect
-
-\def\currentstructurelistnumber{0}
-
-% nmstate -> no pagenumber if not start
-% autocrossdocument -> todo
-% expansion -> todo
-% auto refs to lists (chain) -> todo (\dododowritetolist)
-% todo: \normalexpanded{\noexpand\everylistentry\emptytoks\the\everylistentry}% \emptytoks, else loop
-
-% interface to lua
-
-% we have to deal with compatible processing, i.e. list elements that have two
-% elements plus a pagenumber
-
-\let\listentry\gobblesixarguments
-
-\def\currentlist {\s!unknown}
-\def\currentlistmethod{entry}
-\def\currentlistindex {0}
-
-\def\setlistparameter#1#2#3{\@EA\def\csname\??li#1#2\endcsname{#3}} % often
-%def\listparameter #1{\ifcsname\??li\currentlist#1\endcsname\csname\??li\currentlist#1\endcsname\fi}
-
-% interface
-
-\def\listparameter #1{\csname\dolistparameter{\??li\currentlist}#1\endcsname}
-\def\namedlistparameter#1#2{\csname\dolistparameter{\??li #1}#2\endcsname}
-\def\listparameterhash #1{\dolistparameterhash {\??li\currentlist}#1}
-
-\def\dolistparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dolistparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\dolistparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\dolistparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\dolistparentparameter #1#2{\ifx#1\relax\s!empty\else\dolistparameter #1#2\fi}
-\def\dolistparentparameterhash#1#2{\ifx#1\relax \else\dolistparameterhash#1#2\fi}
-
-\def\dosetlistattributes#1#2% style color
- {\edef\fontattributehash {\listparameterhash#1}%
- \edef\colorattributehash{\listparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-\def\donestedlistattributes#1#2%
- {\dosetlistattributes#1#2%
- \ifx\colorattributehash\empty \else
- \resetinteractionparameter\c!color
- \resetinteractionparameter\c!contrastcolor
- \fi}
-
-% handling
-
-% The next code injects data into the list at the current level.
-
-\def\structurelistinject{\dotripleempty\dostructurelistinject}
-
-\def\dostructurelistinject[#1]% [#2][#3]% no check on nofarguments here
- {\begingroup
- \edef\currentlist{#1}%
- \doifelse{\listparameter\c!state}\v!start\dodostructurelistinject\nonostructurelistinject}
-
-\def\dodostructurelistinject[#1][#2]%
- {\endgroup}
-
-\def\dodostructurelistinject[#1][#2]%
- {\getparameters[\??li\??li][\c!type=userdata,\c!location=\v!none,#1]%
- \edef\currentlisttype {\@@li@@litype}%
- \edef\currentlistlocation{\@@li@@lilocation}%
- \setnextinternalreference
- \edef\currentlistnumber{\ctxlua{structures.lists.push{
- references = {
- internal = \nextinternalreference,
- block = "\currentstructureblock", % handy for lists, like bibl
- section = structures.sections.currentid(),
- % location = "\currentlistlocation",
- },
- metadata = {
- kind = "\currentlisttype",
- name = "\currentlist",
- level = structures.sections.currentlevel(),
- catcodes = \the\catcodetable,
- },
- userdata = structures.helpers.touserdata(\!!bs\detokenize{#2}\!!es)
- }}}%
- % we can do the enhance injection at the lua end which saves tokenization and a call
- \ifx\currentlistlocation\v!here
- % this injects nodes !
- \expanded{\ctxlatelua{structures.lists.enhance(\currentlistnumber)}}%
- % new from here
- \xdef\currentstructurelistattribute{\ctxlua{tex.write(structures.references.setinternalreference(nil,nil,\nextinternalreference))}}%
- \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
- %begingroup\attribute\destinationattribute\currentdestinationattribute\dontleavehmode\emptyhbox\endgroup % todo
- \dontleavehmode\hbox attr \destinationattribute \currentdestinationattribute{}% todo
- % end of new
- \else
- \ctxlua{structures.lists.enhance(\currentlistnumber)}% direct injection
- \fi
- \endgroup}
-
-\def\structurelistlocation
- {\ctxlua{structures.lists.location(\currentlistindex)}}
-
-\def\structurelistpagenumber
- {\dostarttagged\t!listpage\empty
- \ctxlua{structures.lists.prefixedpage(
- "\currentlist",
- \currentlistindex,
- {
- separatorset = "\listparameter\c!pageprefixseparatorset",
- conversionset = "\listparameter\c!pageprefixconversionset",
- set = "\listparameter\c!pageprefixset",
- segments = "\listparameter\c!pageprefixsegments",
- connector = \!!bs\listparameter\c!pageprefixconnector\!!es,
- },
- {
- prefix = "\listparameter\c!pageprefix",
- conversionset = "\listparameter\c!pageconversionset",
- starter = \!!bs\listparameter\c!pagestarter\!!es,
- stopper = \!!bs\listparameter\c!pagestopper\!!es,
- }
- )}%
- \dostoptagged}
-
-\def\structurelistrealpagenumber
- {\ctxlua{structures.lists.realpage("\currentlist",\currentlistindex)}}
-
-\def\structurelistfirst
- {\dostarttagged\t!listdata{first}% not always ok
- \ctxlua{structures.lists.userdata("\currentlist",\currentlistindex,"first")}%
- \dostoptagged}
-
-\def\structurelistsecond
- {\dostarttagged\t!listdata{second}%
- \ctxlua{structures.lists.userdata("\currentlist",\currentlistindex,"second")}%
- \dostoptagged}
-
-\def\structurelistuservariable#1%
- {\dostarttagged\t!listdata{#1}%
- \ctxlua{structures.lists.userdata("\currentlist",\currentlistindex,"#1")}%
- \dostoptagged}
-
-% \appendtoks
-% \to \everystructurelist
-
-\unexpanded\def\doplacestructurelist#1#2#3#4#5% beware, not a user command
- {\dostarttagged\t!list\empty
- \ctxlua{structures.lists.process {
- names = "#1",
- criterium = "#2",
- number = "#3",
- extras = "#4",
- order = "#5"
- }}%
- \dostoptagged}
-
-\unexpanded\def\doanalyzestructurelist#1#2#3%
- {\ctxlua{structures.lists.analyze {
- names = "#1",
- criterium = "#2",
- number = "#3"
- }}}
-
-\def\firststructureelementinlist#1%
- {\ctxcommand{firstinlist("#1")}}
-
-\def\structurelistsize
- {\ctxlua{structures.lists.size()}}
-
-\def\@@structurelistprocess{structurelist:process:}
-
-\unexpanded\def\installstructurelistprocessor#1#2%
- {\expandafter\def\csname\@@structurelistprocess#1\endcsname{#2}}
-
-\def\usestructurelistprocessor#1%
- {\csname\@@structurelistprocess#1\endcsname}
-
-\installstructurelistprocessor\s!default
- {no list method}
-
-% push pop test:
-%
-% \starttext
-% \placelist[chapter] [after={\placelist[section][criterium=local]}]
-% \chapter{One} \section{Alpha} \section{Beta}
-% \chapter{Two} \section{First} \section{Second}
-% \stoptext
-
-\def\definelistextra
- {\dodoubleargument\dodefinelistextra}
-
-\def\dodefinelistextra[#1][#2]%
- {\getparameters[\??li:\c!extras:#1:][#2]}
-
-% todo: more generic tracing
-
-\definelistextra
- [\v!page]
- [\c!before={\showmessage\m!system{14}{\currentlist/\currentlistindex}\page}]
-
-\def\processlistextrabefore{\executeifdefined{\??li:\c!extras:\currentlistextra:\c!before}\relax}
-\def\processlistextraafter {\executeifdefined{\??li:\c!extras:\currentlistextra:\c!after }\relax}
-
-\unexpanded\def\processlistofstructure#1#2#3#4% name, method, n, extra
- {\ctxlua{structures.lists.pushnesting(#3)}%
- \edef\currentlist {#1}%
- \edef\currentlistmethod {#2}%
- \edef\currentlistindex {#3}%
- \edef\currentlistextra {#4}%
- \processlistextrabefore
- \dostarttagged\t!listitem\currentlist
- \csname\@@structurelistprocess
- \ifcsname\@@structurelistprocess\currentlist:\currentlistmethod\endcsname\currentlist:\currentlistmethod\else
- \ifcsname\@@structurelistprocess\currentlistmethod \endcsname\currentlistmethod \else
- \ifcsname\@@structurelistprocess\currentlist \endcsname\currentlist \else
- \s!default \fi\fi\fi
- \endcsname
- \dostoptagged
- \processlistextraafter
- \ctxlua{structures.lists.popnesting()}}
-
-% \installstructcurelistprocessor{pubs:userdata}
-% {\ctxlua{structures.lists.userdata("\currentlist",\currentlistindex,"bibref")}}
-
-\installstructurelistprocessor{command}
- {\ctxlua{structures.lists.userdata("\currentlist",\currentlistindex,"command")}}
-
-\installstructurelistprocessor{section}
- {\dodolistelement
- \currentlist
- \structurelistlocation
- \structurelistgenericnumber
- \structurelistgenerictitle % hm, can end up in message (volkers test)
- \structurelistpagenumber
- \structurelistrealpagenumber}
-
-% so far (todo: also recursive)
-
-\def\listalternativeparameter#1%
- {\ifcsname\??li\??li\listparameter\c!alternative#1\endcsname
- \csname\??li\??li\listparameter\c!alternative#1\endcsname
- \else
- \listparameter{#1}%
- \fi}
-
-\unexpanded\def\setuplistalternative[#1]%
- {\dodoubleargument\getparameters[\??li\??li#1]}
-
-\def\listfill {\listalternativeparameter\c!command }
-\def\listskip {\listalternativeparameter\c!distance}
-\def\listwidth {\listalternativeparameter\c!width }
-\def\liststretch{\listalternativeparameter\c!stretch }
-
-% a : nr - tit - pag
-% b : nr - tit - fill - pag
-% c : nr - tit - dots - pag
-
-\setuplistalternative[a][\c!distance=0pt,\c!width=2em,\c!stretch=10em,\c!command=\hskip.25em\relax]
-\setuplistalternative[b][\c!distance=5em,\c!width=2em,\c!stretch=10em,\c!command=\hfill]
-\setuplistalternative[c][\c!distance=5em,\c!width=0pt,\c!stretch=10em,\c!command=\hskip.5em\listdots\hskip.5em\relax]
-
-%def\listdots{\leaders \hbox to .5em{\hss.\hss}\hfill}
-\def\listdots{\gleaders\hbox to .5em{\hss.\hss}\hfill}
-
-% \setvalue{\??li\c!alternative}{\getvalue{\??li\c!alternative b}} % ?
-% \getvalue{\??li\c!alternative} % ?
-
-\def\checklistexistence#1%
- {\ifcsname\??li#1\s!parent\endcsname \else
- \letvalue{\??li#1\s!parent}\??li
- \fi}
-
-\def\dosetuplist[#1][#2]% slow -)
- {\checklistexistence{#1}%
- \def\docommand##1{\getparameters[\??li##1][#2]}%
- \processcommalist[#1]\docommand}
-
-\unexpanded\def\setuplist
- {\dodoubleargument\dosetuplist}
-
-\def\dodefinelist[#1][#2][#3]%
- {\presetlocalframed[\??li#1]% still inefficient (will change when we redu core-rul)
- \doifassignmentelse{#2}
- {\getparameters[\??li#1][\s!parent=\??li,#2]}
- {\doifelsenothing{#2}
- {\getparameters[\??li#1][\s!parent=\??li]}
- {\getparameters[\??li#1][\s!parent=\??li#2,#3]}}}
-
-\unexpanded\def\setuplists % new, but not for users (hardly handy)
- {\dodoubleargument\getparameters[\??li]}
-
-\setuplists
- [\c!height=\v!broad,
- \c!depth=\v!broad,
- \c!offset=0.25em,
- \c!maxwidth=,
- \c!state=\v!start,
- \c!coupling=\v!off,
- \c!criterium=\v!local,
- \c!number=0,
- \c!width=3em,
- \c!alternative=\c!b,
- \c!style=\v!normal,
- \c!textstyle=\listparameter\c!style,
- \c!numberstyle=\listparameter\c!style,
- \c!pagestyle=\listparameter\c!style,
- %\c!color=,
- \c!textcolor=\listparameter\c!color,
- \c!numbercolor=\listparameter\c!color,
- \c!pagecolor=\listparameter\c!color,
- \c!numbercommand=\listnumbercommand,
- \c!textcommand=\listtextcommand,
- \c!pagecommand=\listpagecommand,
- \c!pagenumber=\v!yes,
- \c!headnumber=\v!yes,
- \c!extras=,
- \c!margin=\!!zeropoint,
- \c!aligntitle=,
- \c!before=,
- \c!after=,
- \c!inbetween=,
- \c!symbol=,
- \c!interaction=\v!sectionnumber,
- \c!label=\v!no,
- \c!distance=\!!zeropoint,
- \c!limittext=\@@kolimittext,
- %\c!sectionseparatorset=,
- %\c!sectionconversionset=,
- %\c!sectionstarter=,
- %\c!sectionstopper=,
- %\c!sectionset=,
- %\c!sectionsegments=,
- %\c!prefix=\v!no,
- %\c!prefixseparatorset=,
- %\c!prefixconversionset=,
- %\c!prefixstarter=.,
- %\c!prefixstopper=.,
- %\c!prefixset=,
- %\c!prefixsegments=,
- %\c!pageseparatorset=,
- %\c!pageconversionset=,
- %\c!pagestarter=,
- %\c!pagestopper=,
- %\c!expansion=,
- % \c!prefixconnector=., % maybe inherit from setupheads
- % \c!pageprefix=\v!no, % is unset, inherits
- % \c!pageprefixconnector=\listparameter\c!prefixconnector,
- ]%\c!pagesegments=2:2]
-
-\unexpanded\def\definelist
- {\dotripleempty\dodefinelist}
-
-\unexpanded\def\placelist
- {\dodoubleempty\doplacelist}
-
-\unexpanded\def\placerawlist
- {\dodoubleempty\doplacerawlist}
-
-\def\dobeginoflist
- {\begingroup
- \startpacked[\v!blank]}
-
-\def\doendoflist
- {\stoppacked
- \endgroup}
-
-\def\doplacelist[#1][#2]%
- {\dobeginoflist
- \doplacerawlist[#1][#2]%
- \doendoflist}
-
-\newtoks\everystructurelist
-
-% writing to lists
-
-\let\dowritetolist \gobblefourarguments
-\let\dodowritetolist\gobblefourarguments
-
-
-%D Regular list entries are bound to a specific location in order to
-%D get the right pagenumber etc.\ associated. When pushing something
-%D inbetween (in mkiv) it ends up directtly in the list. This is the
-%D default because otherwise users will wonder why spacing might get
-%D messed up (due to an unseen but present node). It is possible to
-%D force a location by explicitly setting \type {location} to \type
-%D {here}.
-%D
-%D Another way to force a certain order is to set the \type {order}
-%D variable when placing a list. The \type {command} option only
-%D pushes commands into the right order, and \type {all} orders all
-%D entries (which might be too much). In this case no specific
-%D location is needed with the inbetween method. Maybe additional
-%D mechanisms show up some day. See \type {inbetween-001.tex} for an
-%D example.
-
-% command : location=none
-% userdata : location=none
-% simple : location=here
-
-\unexpanded\def\writebetweenlist{\dodoubleempty \dowritebetweenlist}
-\unexpanded\def\writedatatolist {\dotripleargument\dowritedatatolist}
-\unexpanded\def\writetolist {\dodoubleempty \dowritetolist}
-
-\def\dowritebetweenlist[#1][#2]#3% we can overload location
- {\doif{\namedlistparameter{#1}\c!state}\v!start
- {\ifsecondargument
- \dostructurelistinject[#1][#2,\c!type=command][command={#3}]%
- \else
- \dostructurelistinject[#1][\c!type=command][command={#3}]%
- \fi}}
-
-\def\dowritedatatolist[#1][#2][#3]% we can overload location
- {\doif{\namedlistparameter{#1}\c!state}\v!start
- {\ifthirdargument
- \dostructurelistinject[#1][#2,\c!type=userdata][#3]%
- \else
- \dostructurelistinject[#1][\c!type=userdata][#2]%
- \fi}}
-
-
-\def\dowritetolist[#1][#2]#3#4% we can overload location
- {\doif{\namedlistparameter{#1}\c!state}\v!start
- {\ifsecondargument
- \dostructurelistinject[#1][\c!location=\v!here,#2,\c!type=simple][first={#3},second={#4}]%
- \else
- \dostructurelistinject[#1][\c!location=\v!here,\c!type=simple][first={#3},second={#4}]%
- \fi}}
-
-\installstructurelistprocessor{simple}
- {\dodolistelement
- \currentlist
- \structurelistlocation
- \structurelistfirst
- \structurelistsecond
- \structurelistpagenumber
- \structurelistrealpagenumber}
-
-% % %
-
-\def\doplacerawlist[#1][#2]% listreferences will be redone
- {\begingroup
- \dosetuplist[#1][#2]%
- \edef\currentlist{\firststructureelementinlist{#1}}%
- \the\everystructurelist
- \doif{\listparameter\c!coupling}\v!on{\startlistreferences{#1}}%
- \doplacestructurelist
- {#1}%
- {\listparameter\c!criterium}%
- {\number\listparameter\c!number}%
- {\listparameter\c!extras}%
- {\listparameter\c!order}%
- \stoplistreferences
- \endgroup
- \dosetlistmode}
-
-\def\dosetlistmode
- {\ifcase\structurelistsize\relax
- \resetsystemmode\v!list
- \else
- \setsystemmode \v!list
- \fi}
-
-\unexpanded\def\systemsuppliedchapter {\getvalue{\v!chapter}} % brrr
-\unexpanded\def\systemsuppliedtitle {\getvalue{\v!title}} % brrr
-
-\def\dodocompletelist[#1][#2][#3]% enkelvoud, meervoud, instellingen
- {\normalexpanded{\systemsuppliedtitle[#2]{\noexpand\headtext{#2}}}% expansion needed for v! vs french !
- \doplacelist[#1][#3]}
-
-\def\docompletelist[#1][#2]%
- {\dodocompletelist[#1][#1][#2]}
-
-\unexpanded\def\completelist
- {\dodoubleempty\docompletelist}
-
-\def\listelements {} % list of page breaks
-\def\listnumbercommand #1{#1} % no strut due to interactive version
-\def\listtextcommand #1{\begstrut#1\endstrut}
-\def\listpagecommand #1{\strut#1}
-
-\def\doassigndimen#1#2#3%
- {\doifinsetelse{#2}{\v!fit,\v!broad}{#1=#3}{#1=#2}\relax}
-
-\unexpanded\def\listsymbol[#1]#2%
- {\begingroup
- \edef\currentlist{#1}%
- \def\currentlistnumber{#2}% no edef else tag problems
- \currentlistsymbol
- \endgroup}
-
-% Beware, the list symbol macro gets an argument passed, i.e. when this
-% argument is not picked up, the symbol becomes a kind of prefix.
-
-% for historical reasons we're stuck to symbols, so in order to generalize,
-% we have to hook it into the symbol handler; we need a beter clean up later
-%
-% < 2005
-%
-% \def\dosetlistsymbol % #1
-% {\executeifdefined{listsymbol@\listparameter\c!symbol}\listsymbol@default} % {#1}
-%
-% >= 2005
-%
-% at this symbol level, we have access to the raw 'number' in
-% \currentlistnumber
-
-\definesymbol[\v!list][\v!none ][\listsymbol@none ]
-\definesymbol[\v!list][\v!one ][\listsymbol@one ]
-\definesymbol[\v!list][\v!two ][\listsymbol@two ]
-\definesymbol[\v!list][\v!three ][\listsymbol@three ]
-\definesymbol[\v!list][\s!default][\listsymbol@default]
-\definesymbol[\v!list][\s!unknown][\listsymbol@unknown]
-
-\def\currentlistsymbol
- {\doifinsymbolsetelse\v!list{\listparameter\c!symbol}
- {\directsymbol\v!list{\listparameter\c!symbol}}
- {\directsymbol\v!list\s!default}}
-
-\def\listsymbol@none
- {\doassigndimen\scratchdimen{\listparameter\c!width}{1.5em}%
- \hbox to \scratchdimen{}}
-
-\def\listsymbol@one
- {\strut$\bullet$}
-
-\def\listsymbol@two
- {\vrule\!!width1em\!!height1ex\!!depth\zeropoint}
-
-\def\listsymbol@three
- {\begingroup
- \doassigndimen{\dimen0}{\listparameter\c!width }{1.5em}%
- \doassigndimen{\dimen2}{\listparameter\c!height}{1ex}%
- \doassigndimen{\dimen4}{\listparameter\c!depth }\zeropoint
- \vrule\!!width\dimen0\!!height\dimen2\!!depth\dimen4%
- \endgroup}
-
-\def\listsymbol@default
- {\strut
- \begingroup
- \edef\currentlistlabel{\listparameter\c!label}%
- \ifx\currentlistlabel\empty % default
- \listparameter\c!starter
- \currentlistnumber
- \listparameter\c!stopper
- \else\ifx\currentlistlabel\v!no % also default
- \listparameter\c!starter
- \currentlistnumber
- \listparameter\c!stopper
- \else\ifx\currentlistlabel\v!none % real minimal (as suggested by WS)
- \currentlistnumber
- \else\ifx\currentlistlabel\v!yes % auto (use value stored in tuc file)
- \edef\currentlistlabel{\ctxlua{structures.lists.label(\currentlistindex,"\currentlistlabel")}}%
- \leftlabeltext\currentlistlabel
- \listparameter\c!starter
- \currentlistnumber
- \listparameter\c!stopper
- \rightlabeltext\currentlistlabel
- \else % use whatever is set
- \leftlabeltext\currentlistlabel
- \listparameter\c!starter
- \currentlistnumber
- \listparameter\c!stopper
- \rightlabeltext\currentlistlabel
- \fi\fi\fi\fi
- \endgroup}
-
-\def\listsymbol@unknown
- {\listparameter\c!symbol}
-
-% so far for list symbols
-
-\def\@@dodolistelement{dodolistelement}
-
-\def\dosomelistelement#1#2#3{#1 #2 #3}
-
-\setvalue{\@@dodolistelement a}{\let\dosomelistelement\dodofixdlistelementABC}
-\setvalue{\@@dodolistelement b}{\let\dosomelistelement\dodofixdlistelementABC}
-\setvalue{\@@dodolistelement c}{\let\dosomelistelement\dodofixdlistelementABC}
-\setvalue{\@@dodolistelement d}{\let\dosomelistelement\dodofixdlistelementD}
-\setvalue{\@@dodolistelement e}{\let\dosomelistelement\dodofixdlistelementE}
-\setvalue{\@@dodolistelement f}{\let\dosomelistelement\dodofixdlistelementF}
-\setvalue{\@@dodolistelement g}{\let\dosomelistelement\dodofixdlistelementG}
-
-\setvalue{\@@dodolistelement\v!none }{\def\dosomelistelement{\dodofreevlistelement}}
-\setvalue{\@@dodolistelement\v!vertical }{\def\dosomelistelement{\dodofreevlistelement}}
-\setvalue{\@@dodolistelement\v!horizontal}{\def\dosomelistelement{\dodofreehlistelement}}
-\setvalue{\@@dodolistelement\v!command }{\let\dosomelistelement\dodocommandlistelement}
-
-% \setuplist
-% [section]
-% [alternative=MyListItem,
-% after=\blank,
-% before=\blank]
-%
-% \definelistplacement[MyListItem][none]#1#2#3%
-% {(#1) (#2) (#3)}
-
-\unexpanded\def\definelistplacement
- {\dodoubleempty\dodefinelistplacement}
-
-\def\dodefinelistplacement[#1][#2]%
- {\setvalue{\@@dodolistelement#1}%
- {\doifelsenothing{#2}
- {\getvalue{\@@dodolistelement\v!command}}%
- {\executeifdefined{\@@dodolistelement#2}{\getvalue{\@@dodolistelement\v!command}}}%
- \setvalue{\??li\currentlist\c!command}{\getvalue{\@@dodolistelement::#1}}}%
- \setvalue{\@@dodolistelement::#1}}
-
-% don't mess arround with endgraf/grouping else we loose leftskip
-
-% \strippedcsname\dodolistelement
-
-\def\newlineinlist{\space}
-
-\let\currentlist\s!unknown
-
-\def\docurrentlistalternative
- {\edef\currentlistalternative{\listparameter\c!alternative}%
- \ifx\currentlistalternative\empty
- [unknown list alternative]%
- \else
- \executeifdefined{\@@dodolistelement\currentlistalternative}{[unknown list alternative: \currentlistalternative]}%
- \fi}
-
-\def\dodolistelement#1#2#3#4#5#6%
- {\edef\currentlist{#1}%
- \def\currentlistnumber{#3}% no edef else tag problem
- \docurrentlistalternative
- \letinteractionparameter\c!width\zeropoint
- \dontcomplain
- \dosomelistelement{#1}{#2}{#3}{#4}{#5}{#6}}
-
-\def\dodocommandlistelement#1#2#3#4#5#6%
- {\doifdefinedelse{\??li#1\c!command}
- {\listparameter\c!command{#3}{#4}{#5}}
- {[\currentlist: #3 -- #4 -- #5]}}
-
-\def\domakelistelement#1#2#3#4% ref internal command data
- {\dontleavehmode
- \iflocation % we cannot tweak \iflocation as we nest
- \doifelse{\listparameter\c!interaction}{#1}
- {\begingroup
- \doif{\namedstructureheadparameter\currentlist\c!interaction}\v!list
- {\dosetsimplepagereference{bck:#2}%
- \attribute\destinationattribute\currentdestinationattribute}%
- \directgoto{\setlocationcolor\??ia#4}[internal(#2)]% we can get the attribute instead so then we don't need a goto
- \endgroup}% was \directgotobox
- {#3{#4}}%
- \else
- #3{#4}%
- \fi}
-
-\def\dodofreelistelement#1#2#3#4#5#6#7#8%
- {\listparameter\c!before% can be \hskip
- \doifdefinedelse{\??li#1\c!command}
- {\domakelistelement{\listparameter\c!interaction}{#2}\hbox
- {\listparameter\c!command
- {#3}% geen conversies etc
- {#4}% geen conversies etc
- {#5}}}% geen command
- {#7%
- \vbox
- {\forgetall
- \domakelistelement\v!all{#2}\hbox
- {\doif{\listparameter\c!headnumber}\v!yes
- {\domakelistelement\v!sectionnumber{#2}\hbox
- {\donestedlistattributes\c!numberstyle\c!numbercolor
- {\listparameter\c!numbercommand{\currentlistsymbol}}}}%
- \domakelistelement\v!text{#2}\hbox
- {\donestedlistattributes\c!textstyle\c!textcolor
- {\let\\=\newlineinlist
- \dontconvertfont
- \listparameter\c!textcommand{#4}}}%
- \doif{\listparameter\c!pagenumber}\v!yes
- {\doifsomething{#5}
- {\domakelistelement\v!pagenumber{#2}\hbox
- {\donestedlistattributes\c!pagestyle\c!pagecolor
- {\listparameter\c!pagecommand{#5}}}}}}}%
- #8}%
- \listparameter\c!after}
-
-\def\dodofreehlistelement#1#2#3#4#5#6%
- {\dodofreelistelement{#1}{#2}{#3}{#4}{#5}{#6}
- {\noindent}{}}
-
-\def\dodofreevlistelement#1#2#3#4#5#6% % \nointerlineskip needed,
- {\dodofreelistelement{#1}{#2}{#3}{#4}{#5}{#6} % otherwise wrong spacing
- {\ifvmode\nointerlineskip\fi} % at multi-line lists
- {\ifvmode\nointerlineskip\fi\endgraf\allowbreak}} % test is saveguard
-
-% to be documented: align, hang
-
-\def\limitatedlistentry#1%
- {\doifelsenothing{\listparameter\c!maxwidth}
- {\listparameter\c!textcommand{#1}}
- {\listparameter\c!textcommand
- {\limitatetext
- {#1}%
- {\listparameter\c!maxwidth}%
- {\splitsymbol{\listparameter\c!limittext}}}}}
-
-\def\dodofixdlistelementABC#1#2#3#4#5#6% weeden
- {\endgraf
- \leftskip\listparameter\c!margin% na de \endgraf !
- \listparameter\c!before
- \!!widthc\listparameter\c!distance
- \doifelse{\listparameter\c!width}\v!fit
- {\!!widtha\zeropoint}
- {\doifelsenothing{#3}
- {\doifelse{\listparameter\c!aligntitle}\v!yes
- {\!!widtha\zeropoint
- \!!widthc\zeropoint}
- {\!!widtha\listparameter\c!width}}
- {\!!widtha\listparameter\c!width}}%
-% \getvalue{\??li\c!alternative\listparameter\c!alternative}% ?
- \endgraf
- \noindent
- \domakelistelement\v!all{#2}\hbox
- {\setlocalhsize
- \hsize\localhsize
- \hbox to \hsize
- {\forgetall
- \dosetlistattributes\c!style\c!color
- \!!widthb\hsize
- \doifelse{\listparameter\c!headnumber}\v!yes
- {\setbox2\hbox \ifdim\!!widtha>\zeropoint to \!!widtha \fi
- {\domakelistelement\v!sectionnumber{#2}\hbox
- {\donestedlistattributes\c!numberstyle\c!numbercolor
- {\listparameter\c!numbercommand{\currentlistsymbol}}%
- \hfill}}}
- {\!!widtha\zeropoint
- \!!widthc\zeropoint
- \setbox2\emptyhbox}%
- \setbox4\hbox
- {\doif{\listparameter\c!pagenumber}\v!yes
- {\doifsomething{#5} % \listwidth is new ; temp hack
- {\hbox \ifdim\listwidth>\zeropoint to \listwidth\fi
- {\hfill
- \domakelistelement\v!pagenumber{#2}\hbox
- {\donestedlistattributes\c!pagestyle\c!pagecolor
- {\listparameter\c!pagecommand{#5}}}}}}}%
- \vbox
- {\hsize\!!widthb
- \setupalign[\listparameter\c!align]%
- \ifdim\!!widtha<\hsize
- \hangindent\wd2
- \dimen2=\!!widthc % \listparameter\c!distance
- \advance\hangindent \dimen2
- \hangafter\plusone
- \doif{\listparameter\c!hang}\v!no{\hangafter\zerocount}%
- \ifdim\wd4=\zeropoint % \ifvoid4
- % we kunnen gewoon afbreken aan het eind
- \else
- \ifdim\listskip>\zeropoint\relax
- \rightskip\listskip\!!plus\liststretch\relax
- \parfillskip-\rightskip
- \fi
- \fi
- \else
- \dimen2\zeropoint
- \fi
- \parindent\zeropoint\relax
- \leavevmode
- \box2\relax
- \hskip\dimen2
-\domakelistelement\v!text{#2}\firstofoneargument{%
- \bgroup
- \donestedlistattributes\c!textstyle\c!textcolor
- {\let\\=\newlineinlist
- \dontconvertfont
- %\listparameter\c!textcommand{#4}}%
- \limitatedlistentry{#4}}%
- %\carryoverpar % new otherwise wrong linespacing
- \egroup
-}%
- \ifdim\wd4=\zeropoint\relax % \ifvoid4
- % \ifdim\!!widtha<\hsize \hfill\strut \fi % spoils align
- \else
- \nobreak\listfill
- \box4\relax
- \relax
- \fi}%
- \hss}}% new
- \endgraf % new, else problems with nointerlinespace and prevdepth
- \nointerlineskip % anders verkeerde spatiering bij multi-line
- \endgraf
- \allowbreak
- \listparameter\c!after}
-
-% % example from the context list
-%
-% \setuphead [part] [page=right,placehead=yes]
-% \setuplist [chapter] [alternative=d,before=\blank,after=\blank]
-% \setuplist [part] [before=\blank,after=\blank]
-%
-% \starttext
-% \startnarrower[2*right] \placecontent \stopnarrower
-% \blank[4*big]
-% \startsetups chapter
-% \blank \startnarrower[3*middle] \placecontent[criterium=local] \stopnarrower
-% \stopsetups
-% \placelist[part][criterium=text,after=\setups{chapter}]
-%
-% \part{First part} \chapter{Chapter one} \chapter{Chapter two}
-% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
-% \part{Second part} \chapter{Chapter one} \chapter{Chapter two}
-% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
-% \part{Third part} \chapter{Chapter one} \chapter{Chapter two}
-% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
-% \stoptext
-
-% overrulen interactie kan sneller, bv door hulpconstanten
-% te gebruiken en die te letten
-
-\def\dodofixdlistelementD#1#2#3#4#5#6%
- {%\leftskip=\listparameter\c!margin
- \ifvmode
- \advance\leftskip\listparameter\c!margin% AANGEPAST
- \fi
- \bgroup
- \ifvmode
- \noindent\leavevmode % leavevmode ? ? ?
- \fi
-%% actually, the next can be supported now (will be enabled when I have time to test it)
- \doif{\listparameter\c!interaction}\v!text % not supported
- {\setlistparameter\currentlist\c!interaction\v!sectionnumber}%
- \doif{\listparameter\c!interaction}\v!all % not supported
- {\setlistparameter\currentlist\c!interaction\v!sectionnumber}%
-%%
- \setbox4\hbox
- {\doif{\listparameter\c!pagenumber}\v!yes
- {\doifsomething{#5}
- {\domakelistelement\v!pagenumber{#2}\hbox
- {\donestedlistattributes\c!pagestyle\c!pagecolor
- {\listparameter\c!pagecommand{#5}}}}}}%
-%% \domakelistelement\v!all{#2}\firstofoneargument{%
- \doif{\listparameter\c!headnumber}\v!yes
- {\donetrue
- \doifnothing{#3}{\doifnothing{\listparameter\c!symbol}\donefalse}%
- % == \doifnothing{#3\listparameter\c!symbol}\donefalse
- \ifdone
- \hbox
- {\listparameter\c!left
- \domakelistelement\v!sectionnumber{#2}\hbox
- {\donestedlistattributes\c!numberstyle\c!numbercolor
- {\listparameter\c!numbercommand{\currentlistsymbol}}}%
- \listparameter\c!right
- \hskip.5em}%
- \nobreak
- \fi}%
- \tolerance3500 % niet zomaar veranderen
-%% \domakelistelement\v!text{#2}\firstofoneargument{%
- \donestedlistattributes\c!textstyle\c!textcolor
- {\let\\=\newlineinlist
- \dontconvertfont
- %\listparameter\c!textcommand{#4}}%
- \limitatedlistentry{#4}}%
-%% }%
- \ifvoid4\else
- \nobreak
- \hskip.75em\relax
- \nobreak
- \box4
- \fi
-%% }%
- \dimen0=\listparameter\c!distance\relax
- \ifdim\dimen0<1em\relax
- \hskip1em\!!plus1em\!!minus.25em\relax
- \else
- \hskip\dimen0\!!plus.5\dimen0\!!minus.25\dimen0\relax
- \fi
- \egroup}
-
-\def\dodofixdlistelementE#1%
- {\dodofixdlistelementEFG
- {\setupinteraction[\c!strut=\v!no]}
- {\localframed[\??li\currentlist][\c!depth=\!!zeropoint,\c!color=]}
- {}}
-
-\def\dodofixdlistelementF#1%
- {\dodofixdlistelementEFG
- {}
- {\dosetraggedhbox{\listparameter\c!align}\raggedbox}
- {}}
-
-\def\dodofixdlistelementG#1%
- {\dodofixdlistelementEFG
- {}
- \midaligned
- {}}
-
-\def\dodofixdlistelementEFG#1#2#3#4#5#6#7#8%
- {\noindent
- \bgroup
- \domakelistelement\v!no{#4}{#2}%
- {\let\\=\newlineinlist
- #1% in case E nils the strut (still needed?)
- \dosetlistattributes\c!style\c!color
- \ignorespaces\dontconvertfont\setstrut
- \begstrut
- \limitatedlistentry{#6}%
- \endstrut}%
- \egroup
- \par
- \listparameter\c!inbetween}
-
-\def\listlength{\utilitylistlength}
-\def\listwidth {\utilitylistwidth}
-\def\listheight{\utilitylistheight}
-
-\def\utilitylistlength {0}
-\def\utilitylistwidth {0pt} % no longer supported
-\def\utilitylistheight {0pt} % no longer supported
-
-\def\dodeterminelistcharacteristics[#1][#2]%
- {\begingroup
- \dosetuplist[#1][#2]%
- \edef\currentlist{\firststructureelementinlist{#1}}%
- \the\everystructurelist
- \doanalyzestructurelist{#1}{\listparameter\c!criterium}{\number\listparameter\c!number}%
- \xdef\utilitylistlength{\structurelistsize}%
- \endgroup
- \dosetlistmode}
-
-\unexpanded\def\determinelistcharacteristics
- {\dodoubleempty\dodeterminelistcharacteristics}
-
-\def\combinedlistparameter#1{\csname\??ih\currentcombinedlist#1\endcsname}
-
-\unexpanded\def\setupcombinedlist
- {\dodoubleargument\dosetupcombinedlist}
-
-\def\dosetupcombinedlist[#1][#2]%
- {\getparameters[\??ih#1][#2]%
- \edef\currentcombinedlist{#1}%
- \normalexpanded{\noexpand\setuplist[\combinedlistparameter\c!list]}[#2]}
-
-\unexpanded\def\definecombinedlist
- {\dotripleempty\dodefinecombinedlist}
-
-\def\dodefinecombinedlist[#1][#2][#3]%
- {\getparameters
- [\??ih#1]
- [\c!criterium=\v!local,\c!number=0,\c!list={#2},#3]%
- \setvalue{\e!setup#1\e!endsetup}{\dodoubleempty\dosetupcombinedlist[#1]}%
- \setvalue{\e!place#1}{\dodoubleempty\doplacecombinedlist[#1]}%
- \setvalue{\e!complete#1}{\dodoubleempty\docompletecombinedlist[#1]}}
-
-\unexpanded\def\placecombinedlist
- {\dodoubleempty\doplacecombinedlist}
-
-\def\doplacecombinedlist[#1][#2]% we can move much of the analysis to lua
- {\begingroup
- % level is no longer supported
- \def\currentcombinedlist{#1}%
- \getparameters[\??ih#1][#2]%
- \edef\combinedlist{\combinedlistparameter\c!list}%
- \the\everystructurelist
- \doif{\combinedlistparameter\c!coupling}\v!on{\startlistreferences{#1}}%
- \dobeginoflist
- \normalexpanded{\noexpand\dosetuplist[\combinedlist][#2]}%
- \doplacestructurelist
- {\combinedlist}%
- {\combinedlistparameter\c!criterium}%
- {\combinedlistparameter\c!number}%
- {\combinedlistparameter\c!extras}%
- {\combinedlistparameter\c!order}%
- \doendoflist
- \stoplistreferences
- \endgroup
- \dosetlistmode}
-
-\def\docompletecombinedlist[#1][#2]%
- {\normalexpanded{\systemsuppliedtitle[#1]{\noexpand\headtext{#1}}}% expansion due to v! vs french !
- \doplacecombinedlist[#1][#2]}
-
-% lists that have a number/title are kind of generic and can share code
-
-\installstructurelistprocessor{number+title}
- {\dodolistelement
- \currentlist
- \structurelistlocation
- \structurelistgenericnumber
- \structurelistgenerictitle
- \structurelistpagenumber
- \structurelistrealpagenumber}
-
-\def\structurelistgenerictitle
- {\dostarttagged\t!listcontent\empty
- \ctxlua{structures.lists.title("\currentlist",\currentlistindex)}%
- \dostoptagged}
-
-\def\structurelistgenericnumber % tricky, we need to delay tagging as we have nested lua calls
- {\dostarttagged\t!listtag\empty
- \ctxlua{structures.lists.prefixednumber("\currentlist",\currentlistindex, {
- prefix = "\listparameter\c!prefix",
- separatorset = "\listparameter\c!prefixseparatorset",
- conversionset = "\listparameter\c!prefixconversionset",
- starter = \!!bs\listparameter\c!prefixstarter\!!es,
- stopper = \!!bs\listparameter\c!prefixstopper\!!es,
- set = "\listparameter\c!prefixset",
- segments = "\listparameter\c!prefixsegments",
- connector = \!!bs\listparameter\c!prefixconnector\!!es,
- },
- {
- separatorset = "\listparameter\c!numberseparatorset",
- conversionset = "\listparameter\c!numberconversionset",
- starter = \!!bs\listparameter\c!numberstarter\!!es,
- stopper = \!!bs\listparameter\c!numberstopper\!!es,
- segments = "\listparameter\c!numbersegments",
- } )}%
- \dostoptagged}
-
-% new and yet undocumented (used in cocoa qa), temporarily disabled in mkiv
-%
-% \setupremaininglistlength
-% [left=\hss nog~,right=~ingangen]
-%
-% \resetremaininglistlength
-% [section][settings]
-%
-% \placelist
-% [section]
-% [before=\showremaininglistlength]
-%
-% \dorecurse{100}{\section{hans}}
-%
-% \definesystemvariable {ll} % ListLength
-%
-% \unexpanded\def\setupremaininglistlength[#1]%
-% {\getparameters[\??ll][#1]%
-% \globallet\listlengthcounter\!!zerocount}
-%
-% \setupremaininglistlength
-% [\c!left=\hss,\c!right=,\c!number=\v!yes,
-% \c!before=\blank,\c!after=\page,
-% \c!style=\v!smallnormal,\c!color=]
-%
-% \def\resetremaininglistlength
-% {\dodoubleempty\doresetremaininglistlength}
-%
-% \def\doresetremaininglistlength[#1][#2]%
-% {\determinelistcharacteristics[#1][#2]%
-% \xdef\listlengthcounter{\number\utilitylistlength}}
-%
-% \def\showremaininglistlength
-% {\bgroup
-% \ifnum\listlengthcounter>\plusone
-% \setbox\scratchbox\vbox
-% {\@@llbefore\par\horizontalstrut\par\horizontalstrut\par\@@llafter}%
-% \scratchdimen\pagetotal
-% \advance\scratchdimen \ht\scratchbox
-% \advance\scratchdimen \dp\scratchbox
-% \ifdim\scratchdimen>\pagegoal
-% \@@llbefore
-% \nobreak\hbox to \hsize
-% {\doifnot\@@llnumber\v!yes{\let\listlengthcounter\empty}%
-% \doattributes\??ll\c!style\c!color{\@@llleft\listlengthcounter\@@llright}}
-% \@@llafter
-% \fi
-% \fi
-% \doglobal\decrement\listlengthcounter\relax
-% \egroup}
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-lst.mkvi b/Master/texmf-dist/tex/context/base/strc-lst.mkvi
new file mode 100644
index 00000000000..16544f8662b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-lst.mkvi
@@ -0,0 +1,1296 @@
+%D \module
+%D [ file=strc-lst,
+%D version=2008.10.20,
+%D title=\CONTEXT\ Structure Macros,
+%D subtitle=Lists,
+%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 / Lists}
+
+\registerctxluafile{strc-lst}{1.001}
+
+% clean up in progress ...
+%
+% also (long term) todo:
+%
+% autocrossdocument
+% auto refs to lists (chain)
+%
+% TODO: strut=yes|no
+%
+% \lists -> strc_lists
+
+\unprotect
+
+% To be added to mult-def.lua:
+
+\ifdefined\c!renderingsetup \else \def\c!renderingsetup{renderingsetup} \fi % maybe not interfaced
+\ifdefined\c!filler \else \def\c!filler {filler} \fi
+\ifdefined\v!interactive \else \def\v!interactive {interactive} \fi
+
+%D Lists are mostly used for tables of contents but are in fact a rather generic
+%D feature of \CONTEXT. We seperate between storage and rendering and the current
+%D implementation is a reworked version of all that was added in steps. As lists
+%D are used frequently compatibility is an important aspect. A couple of rendering
+%D alternatives are provided here but more are possible.
+
+\installcorenamespace{list}
+
+\installframedcommandhandler \??list {list} \??list
+
+\let\setuplists\setuplist % yes or no
+
+\setuplist
+ [\c!height=\v!broad,
+ \c!depth=\v!broad,
+ \c!offset=.25\emwidth,
+ \c!state=\v!start,
+ \c!coupling=\v!off,
+ \c!criterium=\v!local,
+ \c!number=\zerocount,
+ \c!width=3\emwidth,
+ %\c!maxwidth=,
+ \c!distance=\zeropoint,
+ \c!margin=\zeropoint,
+ \c!alternative=\c!b,
+ \c!style=\v!normal,
+ %\c!color=,
+ \c!textstyle=\listparameter\c!style, % \currentliststyleparameter (but then we need to set it in every ...)
+ \c!numberstyle=\listparameter\c!style, % \currentliststyleparameter
+ \c!pagestyle=\listparameter\c!style, % \currentliststyleparameter
+ \c!textcolor=\listparameter\c!color, % \currentlistcolorparameter (but then we need to set it in every ...)
+ \c!numbercolor=\listparameter\c!color, % \currentlistcolorparameter
+ \c!pagecolor=\listparameter\c!color, % \currentlistcolorparameter
+ \c!numbercommand=\firstofoneargument,
+ \c!textcommand=\firstofoneargument,
+ \c!pagecommand=\firstofoneargument,
+ \c!pagenumber=\v!yes, % better: 'first'
+ \c!headnumber=\v!yes, % better: 'second'
+% \c!sectionnumber=\listparameter\c!headnumber, % use this instead
+ \c!interaction=\v!all, % was \v!sectionnumber, % or make this headnumber (or accept both)
+ \c!label=\v!no,
+ %\c!extras=,
+ %\c!aligntitle=,
+ %\c!before=,
+ %\c!after=,
+ %\c!inbetween=,
+ %\c!symbol=,
+ %\c!expansion=,
+ \c!limittext=\languageparameter\c!limittext] % not used currently
+
+%D Helpers:
+
+\unexpanded\def\usenestedliststyleandcolor#style#color% will change
+ {\useliststyleandcolor#style#color%
+ \ifx\currentcolorparameter\empty \else
+ \resetinteractionparameter\c!color
+ \resetinteractionparameter\c!contrastcolor
+ \fi}
+
+\unexpanded\def\doifelselist#tag% can also move to \installcommandhandler
+ {\ifcsname\namedlisthash{#tag}\s!parent\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
+
+%D Regular list entries are bound to a specific location in order to
+%D get the right pagenumber etc.\ associated. When pushing something
+%D inbetween (in mkiv) it ends up directtly in the list. This is the
+%D default because otherwise users will wonder why spacing might get
+%D messed up (due to an unseen but present node). It is possible to
+%D force a location by explicitly setting \type {location} to \type
+%D {here}.
+%D
+%D Another way to force a certain order is to set the \type {order}
+%D variable when placing a list. The \type {command} option only
+%D pushes commands into the right order, and \type {all} orders all
+%D entries (which might be too much). In this case no specific
+%D location is needed with the inbetween method. Maybe additional
+%D mechanisms show up some day. See \type {inbetween-001.tex} for an
+%D example.
+
+% command : location=none
+% userdata : location=none
+% simple : location=here
+
+\unexpanded\def\structurelistinject
+ {\dotripleempty\strc_lists_inject}
+
+\def\strc_lists_inject[#tag]%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \doifelse{\listparameter\c!state}\v!start\strc_lists_inject_yes\strc_lists_inject_nop}
+
+\def\strc_lists_inject_nop[#dummya][#dummyb]%
+ {\endgroup}
+
+\def\strc_lists_inject_yes[#settings][#userdata]%
+ {\setupcurrentlist[\c!type=userdata,\c!location=\v!none,#settings]% grouped
+ \edef\p_location{\listparameter\c!location}%
+ \setnextinternalreference
+ \edef\currentlistnumber{\ctxcommand{addtolist{
+ references = {
+ internal = \nextinternalreference,
+ block = "\currentsectionblock", % handy for lists, like bibl
+ section = structures.sections.currentid(),
+ % location = "\p_location",
+ },
+ metadata = {
+ kind = "\listparameter\c!type",
+ name = "\currentlist",
+ level = structures.sections.currentlevel(),
+ catcodes = \the\catcodetable,
+ },
+ userdata = \!!bs\detokenize{#userdata}\!!es % will be converted to table at the lua end
+ }}}%
+ \ifx\p_location\v!here
+ % this branch injects nodes !
+ \expanded{\ctxlatecommand{enhancelist(\currentlistnumber)}}%
+ \ctxlua{structures.references.setinternalreference(nil,nil,\nextinternalreference)}% will change
+ \xdef\currentstructurelistattribute{\number\lastdestinationattribute}%
+ \dontleavehmode\hbox attr \destinationattribute \lastdestinationattribute{}% todo
+ \else
+ % and this one doesn't
+ \ctxcommand{enhancelist(\currentlistnumber)}%
+ \fi
+ \endgroup}
+
+\unexpanded\def\writebetweenlist{\dodoubleempty \strc_lists_write_between}
+\unexpanded\def\writedatatolist {\dotripleargument\strc_lists_write_data_to}
+\unexpanded\def\writetolist {\dodoubleempty \strc_lists_write_to}
+
+\def\strc_lists_write_between[#tag]%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \doifelse{\namedlistparameter{#tag}\c!state}\v!start
+ \strc_lists_write_between_yes
+ \strc_lists_write_between_nop}
+
+\def\strc_lists_write_between_yes[#settings]#command%
+ {\strc_lists_inject_yes[#settings,\c!type=\s!command][command={#command}]}
+
+\def\strc_lists_write_between_nop[#settings]#command%
+ {\endgroup}
+
+\def\strc_lists_write_data_to[#tag]%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \doifelse{\namedlistparameter{#tag}\c!state}\v!start
+ \strc_lists_write_data_to_yes
+ \strc_lists_write_data_to_nop}
+
+\def\strc_lists_write_data_to_yes[#settings][#userdata]%
+ {\ifthirdargument % no need to have an extra step ... used seldom
+ \strc_lists_inject_yes[#settings,\c!type=\s!userdata][#userdata]%
+ \else
+ \strc_lists_inject_yes[\c!type=\s!userdata][#settings]%
+ \fi}
+
+\def\strc_lists_write_data_to_nop[#settings][#userdata]%
+ {\endgroup}
+
+\def\strc_lists_write_to[#tag]%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \doifelse{\namedlistparameter{#tag}\c!state}\v!start
+ \strc_lists_write_to_yes
+ \strc_lists_write_to_nop}
+
+\def\strc_lists_write_to_yes[#settings]#first#second% no \s!first because we don't expand user settings
+ {\strc_lists_inject_yes[\c!location=\v!here,#settings,\c!type=\s!simple][first={#first},second={#second}]}
+
+\def\strc_lists_write_to_nop[#settings]#first#second%
+ {\endgroup} % \strc_lists_inject_nop[][]
+
+%D When placing a list either one or a set can be giving. This makes
+%D it possible to flush for instance an nested (or merged) table of
+%D contents. Keep in mind that placing a list is what we do most (think
+%D of tables of contents, figures, etc.\ but other usag eis also possible
+%D in which case low level commands have to be used.
+
+\newtoks\everystructurelist
+
+\unexpanded\def\placelist
+ {\dodoubleempty\strc_lists_place}
+
+\unexpanded\def\placerawlist
+ {\dodoubleempty\strc_lists_place_raw}
+
+\def\strc_lists_place[#taglist][#settings]%
+ {\begingroup
+ \startpacked[\v!blank]%
+ \edef\m_list {#taglist}%
+ \edef\m_first{\firststructureelementinlist{#taglist}}%
+ \ifx\m_list\m_first
+ % use settings of first
+ \else
+ % use settings of root
+ \let\m_first\empty
+ \fi
+ \strc_lists_place_indeed\m_first\m_list{#settings}%
+ \stoppacked
+ \endgroup}
+
+\def\strc_lists_place_raw[#tag][#settings]% just one list
+ {\strc_lists_place_indeed\empty{#tag}{#settings}}
+
+\def\strc_lists_place_indeed#tag#list#settings%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \setupcurrentlist[#settings]%
+ \the\everystructurelist
+ % \doif{\listparameter\c!coupling}\v!on{\startlistreferences{#tag}}%
+ \doplacestructurelist % maybe inline
+ {#list}%
+ {\listparameter\c!criterium}%
+ {\listparameter\c!number}%
+ {\listparameter\c!extras}%
+ {\listparameter\c!order}%
+ % \stoplistreferences
+ \par % todo: only when vertical list mode
+ \endgroup
+ \strc_lists_set_mode}
+
+\def\strc_lists_set_mode
+ {\ifcase\structurelistsize\relax
+ \resetsystemmode\v!list
+ \else
+ \setsystemmode \v!list
+ \fi}
+
+%D Complete lists are just lists but with a title. They were
+%D originally introduced to minimize the number for commands in
+%D a document source but nowadays that is less an issue in the
+%D sense that the extra few lines are neglectable to the rest.
+
+\unexpanded\def\systemsuppliedchapter {\getvalue{\v!chapter}} % obsolete
+\unexpanded\def\systemsuppliedtitle {\getvalue{\v!title}} % obsolete
+
+\unexpanded\def\completelist
+ {\dodoubleempty\strc_lists_complete}
+
+\def\strc_lists_complete[#tag][#settings]%
+ {\strc_lists_complete_indeed[#tag][#tag][#settings]}
+
+\def\strc_lists_complete_indeed[#singular][#plural][#settings]%
+ {\normalexpanded{\startnamedsection[\v!title][\c!title=\headtext{#plural},\c!reference=#singular]}%
+ \strc_lists_place[#singular][#settings]%
+ \stopnamedsection}
+
+%D Combined list provide a nice level of abstraction.
+%D
+%D \starttyping
+%D \definecombinedlist[whatever][a,b,c][settings]
+%D \stoptyping
+
+\unexpanded\def\definecombinedlist
+ {\dotripleempty\strc_lists_combined_define}
+
+\def\strc_lists_combined_define[#tag][#list][#settings]%
+ {\definelist[#tag][\c!criterium=\v!local,\c!number=0,\c!alternative=,\c!list={#list},#settings]% inherits from root
+ \setvalue{\e!setup #tag\e!endsetup}{\dodoubleempty\strc_lists_combined_setup [#tag]}%
+ \setvalue{\e!place #tag}{\dodoubleempty\strc_lists_combined_place [#tag]}%
+ \setvalue{\e!complete #tag}{\dodoubleempty\strc_lists_combined_complete[#tag]}}
+
+\unexpanded\def\setupcombinedlist
+ {\dodoubleargument\strc_lists_combined_setup}
+
+\def\strc_lists_combined_setup[#tag][#settings]%
+ {\ifsecondargument
+ \setuplist[#tag][#settings]% we don't want to mess up the parent
+ \fi}
+
+\unexpanded\def\placecombinedlist
+ {\dodoubleempty\strc_lists_combined_place}
+
+\def\strc_lists_combined_place[#tag][#settings]% i.e. no list set in settings
+ {\begingroup
+ %
+ \edef\currentlist{#tag}%
+ \setupcurrentlist[#settings]%
+ \edef\m_strc_list_alternative{\listparameter\c!alternative}% we only inherit alternative
+ %
+ \strc_lists_place_indeed{#tag}{\listparameter\c!list}{#settings}%
+ \endgroup}
+
+\def\strc_lists_combined_complete[#tag][#settings]%
+ {\normalexpanded{\startnamedsection[\v!title][\c!title={\headtext{#tag}},\c!reference=#tag]}%
+ \strc_lists_combined_place[#tag][#settings]%
+ \stopnamedsection}
+
+%D Given that some variables are set, we can ask for some properties of
+%D an entry.
+
+\def\currentstructurelistnumber{0} % injection
+\def\currentlistmethod {entry} % typesetting
+\def\currentlistindex {0} % typesetting
+
+\def\structurelistlocation
+ {\ctxcommand{listlocation(\currentlistindex)}}
+
+\def\structurelistrealpagenumber
+ {\ctxcommand{listrealpage("\currentlist",\currentlistindex)}}
+
+\unexpanded\def\structurelistpagenumber
+ {\dostarttagged\t!listpage\empty
+ \ctxcommand{listprefixedpage(
+ "\currentlist",
+ \currentlistindex,
+ {
+ separatorset = "\listparameter\c!pageprefixseparatorset",
+ conversionset = "\listparameter\c!pageprefixconversionset",
+ set = "\listparameter\c!pageprefixset",
+ segments = "\listparameter\c!pageprefixsegments",
+ connector = \!!bs\listparameter\c!pageprefixconnector\!!es,
+ },
+ {
+ prefix = "\listparameter\c!pageprefix",
+ conversionset = "\listparameter\c!pageconversionset",
+ starter = \!!bs\listparameter\c!pagestarter\!!es,
+ stopper = \!!bs\listparameter\c!pagestopper\!!es,
+ }
+ )}%
+ \dostoptagged}
+
+\unexpanded\def\structurelistuservariable#name%
+ {\dostarttagged\t!listdata{#name}%
+ \ctxcommand{listuserdata("\currentlist",\currentlistindex,"#name")}%
+ \dostoptagged}
+
+\unexpanded\def\structurelistfirst {\structurelistuservariable\s!first } % s!
+\unexpanded\def\structurelistsecond{\structurelistuservariable\s!second} % s!
+
+\unexpanded\def\doifstructurelisthaspageelse
+ {\ctxcommand{doiflisthaspageelse("\currentlist",\currentlistindex)}}
+
+\unexpanded\def\doifstructurelisthasnumberelse
+ {\ctxcommand{doiflisthasnumberelse("\currentlist",\currentlistindex)}}
+
+\unexpanded\def\structurelistgenerictitle
+ {\dostarttagged\t!listcontent\empty
+ \ctxcommand{listtitle("\currentlist",\currentlistindex)}%
+ \dostoptagged}
+
+\unexpanded\def\structurelistgenericnumber % tricky, we need to delay tagging as we have nested lua calls
+ {\dostarttagged\t!listtag\empty
+ \ctxcommand{listprefixednumber("\currentlist",\currentlistindex, {
+ prefix = "\listparameter\c!prefix",
+ separatorset = "\listparameter\c!prefixseparatorset",
+ conversionset = "\listparameter\c!prefixconversionset",
+ starter = \!!bs\listparameter\c!prefixstarter\!!es,
+ stopper = \!!bs\listparameter\c!prefixstopper\!!es,
+ set = "\listparameter\c!prefixset",
+ segments = "\listparameter\c!prefixsegments",
+ connector = \!!bs\listparameter\c!prefixconnector\!!es,
+ },
+ {
+ separatorset = "\listparameter\c!numberseparatorset",
+ conversionset = "\listparameter\c!numberconversionset",
+ starter = \!!bs\listparameter\c!numberstarter\!!es,
+ stopper = \!!bs\listparameter\c!numberstopper\!!es,
+ segments = "\listparameter\c!numbersegments",
+ } )}%
+ \dostoptagged}
+
+% TODO: pass extra tag name (contents, figures, bibliography ...)
+
+\unexpanded\def\doplacestructurelist#list#criterium#number#extras#order% beware, not a user command
+ {\dostarttagged\t!list\empty
+ \ctxcommand{processlist{
+ names = "#list",
+ criterium = "#criterium",
+ number = "\number#number",
+ extras = "#extras",
+ order = "#order"
+ }}%
+ \dostoptagged}
+
+\unexpanded\def\doanalyzestructurelist#list#criterium#number%
+ {\ctxcommand{analyzelist{
+ names = "#list",
+ criterium = "#criterium",
+ number = "\number#number"
+ }}}
+
+\def\firststructureelementinlist#list%
+ {\ctxcommand{firstinset("#list")}}
+
+\def\structurelistsize
+ {\ctxcommand{listsize()}}
+
+%D Depending on what kind of list we have (e.g.\ a section related one)
+%D processors can be defined.
+
+% push pop test:
+%
+% \starttext
+% \placelist[chapter] [after={\placelist[section][criterium=local]}]
+% \chapter{One} \section{Alpha} \section{Beta}
+% \chapter{Two} \section{First} \section{Second}
+% \stoptext
+
+\installcorenamespace{structurelistprocessor} % the topmost list handler
+\installcorenamespace{listextra} % control of that handler
+
+\installcommandhandler \??listextra {listextra} \??listextra
+
+\definelistextra % example
+ [\v!page]
+ [\c!before={\showmessage\m!system{14}{\currentlist/\currentlistindex}\page}]
+
+\unexpanded\def\installstructurelistprocessor#tag#meaning%
+ {\expandafter\normaldef\csname\??structurelistprocessor#tag\endcsname{#meaning}}
+
+\def\usestructurelistprocessor#tag%
+ {\csname\??structurelistprocessor#tag\endcsname}
+
+\unexpanded\def\strclistsentryprocess#tag#method#index#extra% This one is called at the lua end!
+ {\ctxcommand{pushlist(#index)}%
+ \edef\currentlist {#tag}%
+ \edef\currentlistmethod{#method}%
+ \edef\currentlistindex {#index}%
+ \edef\currentlistextra {#extra}%
+ \listextraparameter\c!before
+ \dostarttagged\t!listitem\currentlist
+ \csname\??structurelistprocessor
+ \ifcsname\??structurelistprocessor\currentlist:\currentlistmethod\endcsname\currentlist:\currentlistmethod\else
+ \ifcsname\??structurelistprocessor\currentlistmethod \endcsname\currentlistmethod \else
+ \ifcsname\??structurelistprocessor\currentlist \endcsname\currentlist \else
+ \s!default \fi\fi\fi
+ \endcsname
+ \dostoptagged
+ \listextraparameter\c!after
+ \ctxcommand{poplist()}}
+
+% lists that have a number/title are kind of generic and can share code
+
+\installstructurelistprocessor\s!default
+ {no list method}
+
+\installstructurelistprocessor\s!simple
+ {\let\currentlistentrynumber \structurelistfirst
+ \let\currentlistentrytitle \structurelistsecond
+ \let\currentlistentrypagenumber\structurelistpagenumber
+ \strc_lists_apply_renderingsetup}
+
+\installstructurelistprocessor\s!command
+ {\ctxcommand{listuserdata("\currentlist",\currentlistindex,"\s!command")}}
+
+\installstructurelistprocessor{section}
+ {\let\currentlistentrynumber \structurelistgenericnumber
+ \let\currentlistentrytitle \structurelistgenerictitle
+ \let\currentlistentrypagenumber\structurelistpagenumber
+ \strc_lists_apply_renderingsetup}
+
+\installstructurelistprocessor{number+title}
+ {\let\currentlistentrynumber \structurelistgenericnumber
+ \let\currentlistentrytitle \structurelistgenerictitle
+ \let\currentlistentrypagenumber\structurelistpagenumber
+ \strc_lists_apply_renderingsetup}
+
+% example of usage elsewhere:
+%
+% \installstructcurelistprocessor{pubs:userdata}
+% {\ctxcommand{listuserdata("\currentlist",\currentlistindex,"bibref")}}
+
+%D List symbols are used in interactive documents where no numbers
+%D are used but nevertheless structure is present. Beware, the list
+%D symbol macro gets an argument passed, i.e. when this argument is
+%D not picked up, the symbol becomes a kind of prefix. It's not really
+%D a user command (and might even get protected).
+
+\unexpanded\def\listsymbol[#tag]#number%
+ {\begingroup
+ \edef\currentlist{#tag}%
+ \def\currentlistentrynumber{#number}% no edef else tag problems
+ \currentlistsymbol
+ \endgroup}
+
+% For historical reasons we're stuck to symbols, so in order to generalize,
+% we have to hook it into the symbol handle. One way to deal with this is
+% to use a different key and as it makes sense to use setups instead of
+% def's we use a new key 'renderingsetup' which is the name of a setup.
+
+\def\strc_lists_assign_dimen#dimension#key#default%
+ {\edef\m_strc_list_dimen{\listparameter#key}%
+ \doifinsetelse\m_strc_list_dimen{\v!fit,\v!broad}{#dimension#default}{#dimension\m_strc_list_dimen}\relax}
+
+\definesymbol[\v!list][\v!none ][\strc_lists_symbol_none]
+\definesymbol[\v!list][\v!one ][\strc_lists_symbol_one]
+\definesymbol[\v!list][\v!two ][\strc_lists_symbol_two]
+\definesymbol[\v!list][\v!three ][\strc_lists_symbol_three]
+\definesymbol[\v!list][\s!default][\strc_lists_symbol_default]
+\definesymbol[\v!list][\s!unknown][\strc_lists_symbol_unknown]
+
+\unexpanded\def\currentlistsymbol
+ {\edef\p_symbol{\listparameter\c!symbol}%
+ \doifinsymbolsetelse\v!list\p_symbol
+ {\directsymbol\v!list\p_symbol}
+ {\directsymbol\v!list\s!default}}
+
+\unexpanded\def\strc_lists_symbol_none
+ {\strc_lists_assign_dimen\scratchwidth\c!width{1.5\emwidth}%
+ \hbox to \scratchwidth{}}
+
+\unexpanded\def\strc_lists_symbol_one
+ {\strut\symbol[bullet]}
+
+\unexpanded\def\strc_lists_symbol_two
+ {\vrule\!!width\emwidth\!!height\exheight\!!depth\zeropoint}
+
+\unexpanded\def\strc_lists_symbol_three
+ {\begingroup
+ \strc_lists_assign_dimen\scratchwidth \c!width {1.5\emwidth}%
+ \strc_lists_assign_dimen\scratchheight\c!height\exheight
+ \strc_lists_assign_dimen\scratchdepth \c!depth \zeropoint
+ \vrule\!!width\scratchwidth\!!height\scratchheight\!!depth\scratchdepth
+ \endgroup}
+
+\unexpanded\def\strc_lists_symbol_unknown
+ {\listparameter\c!symbol}
+
+\installcorenamespace{listsymbollabels}
+
+\unexpanded\def\strc_lists_symbol_default
+ {\dontleavehmode
+ \strut
+ \begingroup
+ \edef\currentlistlabel{\listparameter\c!label}% can be used in label
+ \csname\??listsymbollabels
+ \ifcsname\??listsymbollabels\currentlistlabel\endcsname\currentlistlabel\else\s!unknown\fi
+ \endcsname
+ \endgroup}
+
+\setvalue{\??listsymbollabels\s!unknown}% use whatever is set
+ {\leftlabeltext\currentlistlabel
+ \listparameter\c!starter
+ \currentlistentrynumber
+ \listparameter\c!stopper
+ \rightlabeltext\currentlistlabel}
+
+\setvalue{\??listsymbollabels}% default (empty)
+ {\listparameter\c!starter
+ \currentlistentrynumber
+ \listparameter\c!stopper}
+
+\setvalue{\??listsymbollabels\v!no}% also default
+ {\listparameter\c!starter
+ \currentlistentrynumber
+ \listparameter\c!stopper}
+
+\setvalue{\??listsymbollabels\v!none}% real minimal (as suggested by WS)
+ {\currentlistentrynumber}
+
+\setvalue{\??listsymbollabels\v!yes}% auto (use value stored in tuc file)
+ {\edef\currentlistlabel{\ctxcommand{listlabel(\currentlistindex,"\currentlistlabel")}}%
+ \leftlabeltext\currentlistlabel
+ \listparameter\c!starter
+ \currentlistentrynumber
+ \listparameter\c!stopper
+ \rightlabeltext\currentlistlabel}
+
+% a : nr - tit - pag
+% b : nr - tit - fill - pag
+% c : nr - tit - dots - pag
+% d : inline
+% e : interaction
+% f : interaction
+% g : interaction
+
+\installcorenamespace{listalternative} % specific ways of rendering a list
+\installcorenamespace{listrenderings} % a namespace for setups (rather local)
+
+\installcommandhandler \??listalternative {listalternative} \??listalternative
+
+% Commands are bound to specific list instances as often these are
+% quite special and don't apply to multiple. So, being strict saves
+% us resets.
+
+\setuplistalternative
+ [\c!command=\strictlistparameter\c!command]
+
+\definelistalternative
+ [a]
+ [\c!distance=0pt,
+ \c!width=2em,
+ \c!stretch=10em,
+ \c!filler=\hskip.25em\relax,
+ \c!renderingsetup=\??listrenderings:abc]
+
+\definelistalternative
+ [b]
+ [\c!distance=5em,
+ \c!width=2em,
+ \c!stretch=10em,
+ \c!filler=\hfill,
+ \c!renderingsetup=\??listrenderings:abc]
+
+\definelistalternative
+ [c]
+ [\c!distance=5em,
+ \c!width=0pt,
+ \c!stretch=10em,
+ \c!filler=\hskip.5em\gleaders\hbox to .5em{\hss.\hss}\hfill\hskip.5em\relax,
+ \c!renderingsetup=\??listrenderings:abc]
+
+\definelistalternative
+ [d]
+ [\c!renderingsetup=\??listrenderings:d]
+
+\definelistalternative
+ [e]
+ [\c!renderingsetup=\??listrenderings:e]
+
+\definelistalternative
+ [f]
+ [\c!renderingsetup=\??listrenderings:f]
+
+\definelistalternative
+ [g]
+ [\c!renderingsetup=\??listrenderings:g]
+
+\definelistalternative
+ [\v!command]
+ [\c!renderingsetup=\??listrenderings:command]
+
+\definelistalternative
+ [\v!none]
+ [\c!renderingsetup=\??listrenderings:none]
+
+\definelistalternative
+ [\v!vertical]
+ [\c!before=\ifvmode\nointerlineskip\fi,
+ \c!after=\ifvmode\nointerlineskip\fi\endgraf\allowbreak,
+ \c!renderingsetup=\??listrenderings:generic]
+
+\definelistalternative
+ [\v!horizontal]
+ [\c!before=\noindent,
+ \c!after=,
+ \c!renderingsetup=\??listrenderings:generic]
+
+% \setuplist
+% [section]
+% [alternative=MyListItem,
+% after=\blank,
+% before=\blank]
+%
+% \definelistplacement[MyListItem][command]#1#2#3{(#1) (#2) (#3)}
+% \definelistplacement[MyListItem][command]{\whatever}
+%
+% this is a compatibility command, best use the regular
+% defined with command= either set in the alternative or
+% in the list
+
+\installcorenamespace{listelementcommand} % the old plugin model
+
+\unexpanded\def\definelistplacement
+ {\dodoubleempty\strc_lists_define_placement}
+
+\def\strc_lists_define_placement[#tag][#method]%
+ {\edef\p_method{#method}%
+ \ifx\p_method\empty
+ \let\p_method\v!command
+ \fi
+ \normalexpanded{\definelistalternative[#tag][\p_method]}[\c!command=\strc_lists_placement_command]%
+ \doifnextbgroupelse
+ {\strc_lists_define_placement_yes{#tag}}
+ {\strc_lists_define_placement_nop{#tag}}}
+
+% indirect definition: <three ignore arguments>: {\bla}
+
+\def\strc_lists_define_placement_yes#tag%
+ {\unexpanded\expandafter\normaldef\csname\??listelementcommand#tag\endcsname##1##2##3}
+
+% direct definition: <three arguments>{\bla}
+
+\def\strc_lists_define_placement_nop#tag%
+ {\unexpanded\expandafter\normaldef\csname\??listelementcommand#tag\endcsname}
+
+\def\strc_lists_placement_command
+ {\csname\??listelementcommand\currentlistalternative\endcsname}
+
+%D The rendering macros.
+
+\newbox \b_strc_lists_number
+\newbox \b_strc_lists_text
+\newbox \b_strc_lists_page
+
+\newtoks \t_lists_every_renderingsetup
+\newtoks \t_lists_every_renderingtext
+\newtoks \t_lists_every_renderingsynchronize
+\newtoks \t_lists_every_renderingcleanup
+
+\newconditional\c_lists_has_number
+\newconditional\c_lists_has_page
+\newconditional\c_lists_show_number
+\newconditional\c_lists_show_page
+
+\let\currentlistentrylocation \empty % watch the 'entry' in the name
+\let\currentlistentrynumber \empty % watch the 'entry' in the name
+\let\currentlistentrytitle \empty % watch the 'entry' in the name
+\let\currentlistentrypagenumber\empty % watch the 'entry' in the name
+
+\appendtoks
+ \dontcomplain
+ \letinteractionparameter\c!width\zeropoint % a weird one
+\to \t_lists_every_renderingsetup
+
+\appendtoks
+ % better is to use a special list entry but we keep this for compatibility
+ \let\\=\space
+ % so expanding this token register has to come *after* the font switch
+ \dontconvertfont
+\to \t_lists_every_renderingtext
+
+\appendtoks
+ % because we want to avoid redundant lua calls we expand the
+ % location beforehand
+ \ifx\currentlistentrylocation\empty
+ \edef\currentlistentrylocation{\structurelistlocation}% needs attention
+ \fi
+ % because these tests happen often and because we're dealing with
+ % rather complex composed data we have special conditionals; keep
+ % in mind that testing for empty fails do to tagging being applied
+ \edef\p_pagenumber{\listparameter\c!pagenumber}%
+ \ifx\p_pagenumber\v!always
+ \settrue\c_lists_has_page
+ \settrue\c_lists_show_page
+ \else
+ \doifstructurelisthaspageelse\settrue\setfalse\c_lists_has_page
+ \ifx\p_pagenumber\v!yes
+ \settrue\c_lists_show_page
+ \else
+ \setfalse\c_lists_show_page
+ \fi
+ \fi
+ % always forces number placement (in bib we use a forced number)
+ \edef\p_headnumber{\listparameter\c!headnumber}%
+ \ifx\p_headnumber\v!always
+ \settrue\c_lists_has_number
+ \settrue\c_lists_show_number
+ \else
+ \doifstructurelisthasnumberelse\settrue\setfalse\c_lists_has_number
+ \ifx\p_headnumber\v!yes
+ \settrue\c_lists_show_number
+ \else
+ \setfalse\c_lists_show_number
+ \fi
+ \fi
+ \strc_lists_interaction_check
+\to \t_lists_every_renderingsetup
+
+\appendtoks
+ \strc_references_flush_destination_nodes
+\to \t_lists_every_renderingsynchronize
+
+\appendtoks
+ % as we don't want any interference we clear some variables
+ % afterwards
+ \let\currentlistentrylocation \empty
+ \let\currentlistentrynumber \empty
+ \let\currentlistentrytitle \empty
+ \let\currentlistentrypagenumber\empty
+ \setfalse\c_lists_has_page
+ \setfalse\c_lists_has_number
+ \setfalse\c_lists_show_page
+ \setfalse\c_lists_show_number
+\to \t_lists_every_renderingcleanup
+
+\let\m_strc_list_alternative\empty % combined
+
+\unexpanded\def\strc_lists_apply_renderingsetup
+ {\the\t_lists_every_renderingsetup
+ \ifx\m_strc_list_alternative\empty
+ \edef\currentlistalternative{\listparameter\c!alternative}%
+ \else
+ \let\currentlistalternative\m_strc_list_alternative
+ \fi
+ \directsetup{\listalternativeparameter\c!renderingsetup}\relax
+ \the\t_lists_every_renderingcleanup}
+
+% todo: provide packager via attributes
+
+\installcorenamespace{listalternativemethods} % the general wrapper of a rendering
+
+\startsetups[\??listrenderings:none]
+ % nothing, nb we use the [] syntax here because we end with a \cs
+\stopsetups
+
+\startsetups[\??listrenderings:command]
+ \edef\p_command{\listalternativeparameter\c!command}%
+ \ifx\p_command\empty
+ [\currentlist: \currentlistentrynumber\space -- \currentlistentrytitle\space -- \currentlistentrypagenumber]%
+ \else
+ \p_command
+ \currentlistentrynumber
+ {\the\t_lists_every_renderingsynchronize\currentlistentrytitle}%
+ \currentlistentrypagenumber
+ \fi
+\stopsetups
+
+% \startsetups[\??listrenderings:\v!vertical]
+% \directsetup{\??listrenderings:generic}
+% \stopsetups
+
+% \startsetups[\??listrenderings:\v!horizontal]
+% \directsetup{\??listrenderings:generic}
+% \stopsetups
+
+\startsetups[\??listrenderings:generic]
+ \listparameter\c!before % can be \hskip
+ \edef\p_command{\listalternativeparameter\c!command}
+ \ifx\p_command\empty
+ \listalternativeparameter\c!before
+ \vbox {
+ \forgetall
+ \hbox \strc_lists_get_reference_attribute\v!all {
+ \ifconditional\c_lists_show_number
+ % \ifconditional\c_lists_has_page
+ \hbox \strc_lists_get_reference_attribute\v!number {
+ \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
+ \listparameter\c!numbercommand\currentlistsymbol
+ }
+ % \fi
+ \fi
+ \hbox \strc_lists_get_reference_attribute\v!text {
+ \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \listparameter\c!textcommand\currentlistentrytitle
+ }
+ \ifconditional\c_lists_show_page
+ \ifconditional\c_lists_has_page
+ \hbox \strc_lists_get_reference_attribute\v!pagenumber {
+ \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
+ \listparameter\c!pagecommand\currentlistentrypagenumber
+ }
+ \fi
+ \fi
+ }
+ }
+ \listalternativeparameter\c!after
+ \else
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber
+ }
+ \fi
+ \listparameter\c!after
+\stopsetups
+
+% to be documented: align, hang
+
+\startsetups[\??listrenderings:abc]
+ \endgraf % are we grouped?
+ \leftskip\listparameter\c!margin % after \endgraf !
+ \listparameter\c!before
+ \endgraf
+ \edef\p_width{\listparameter\c!width}
+ \scratchdistance\listparameter\c!distance\relax
+ \ifx\p_width\v!fit
+ \scratchwidth\zeropoint
+ \else\ifconditional\c_lists_has_number
+ \scratchwidth\p_width
+ \else
+ \edef\p_aligntitle{\listparameter\c!aligntitle}
+ \ifx\p_aligntitle\v!yes
+ \scratchwidth\zeropoint
+ \scratchdistance\zeropoint
+ \else
+ \scratchwidth\p_width
+ \fi
+ \fi\fi
+ \noindent
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \setlocalhsize
+ \hsize\localhsize
+ \hbox to \hsize {
+ \forgetall
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \scratchhsize\hsize
+ \ifconditional\c_lists_has_number
+ \ifconditional\c_lists_show_number
+ \setbox\b_strc_lists_number\hbox \strc_lists_get_reference_attribute\v!number \ifdim\scratchwidth>\zeropoint to \scratchwidth \fi {
+ \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
+ \listparameter\c!numbercommand\currentlistsymbol
+ \hfill
+ }
+ \else
+ \setbox\b_strc_lists_number\emptyhbox
+ \fi
+ \else
+ \scratchwidth\zeropoint
+ \scratchdistance\zeropoint
+ \setbox\b_strc_lists_number\emptyhbox
+ \fi
+ \ifconditional\c_lists_has_page
+ \ifconditional\c_lists_show_page
+ \setbox\b_strc_lists_page\hbox {
+ \scratchdimen\listalternativeparameter\c!width
+ \hbox \strc_lists_get_reference_attribute\v!pagenumber \ifdim\scratchdimen>\zeropoint to \scratchdimen\fi {
+ \hfill
+ \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
+ \strut
+ \listparameter\c!pagecommand\currentlistentrypagenumber
+ }
+ }
+ \else
+ \setbox\b_strc_lists_page\emptyhbox
+ \fi
+ \else
+ \setbox\b_strc_lists_page\emptyhbox
+ \fi
+ \vbox {
+ \hsize\scratchhsize
+ \usealignparameter\listparameter
+ \ifdim\scratchwidth<\hsize
+ \edef\p_hang{\listparameter\c!hang}
+ \hangindent\dimexpr\wd\b_strc_lists_number+\scratchdistance\relax
+ \hangafter\ifx\p_hang\v!no\zerocount\else\plusone\fi
+ \scratchdimen\listalternativeparameter\c!distance\relax
+ \ifdim\wd\b_strc_lists_page=\zeropoint \else\ifdim\scratchdimen>\zeropoint\relax
+ \rightskip\scratchdimen\!!plus\listalternativeparameter\c!stretch\relax
+ \parfillskip-\rightskip
+ \fi \fi
+ \else
+ \scratchdistance\zeropoint
+ \fi
+ \parindent\zeropoint
+ \dontleavehmode
+ % % topaligned
+ %
+ % \scratchdimen\wd\b_strc_lists_number
+ % \setbox\b_strc_lists_number\hbox to \hsize{\box\b_strc_lists_number\hss\box\b_strc_lists_page}%
+ % \wd\b_strc_lists_number\scratchdimen
+ %
+ \box\b_strc_lists_number
+ \hskip\scratchdistance\relax
+ \begingroup
+ \strc_lists_set_reference_attribute\v!text
+ \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut % needs checking, new here
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ \endgroup
+ \ifdim\wd\b_strc_lists_page=\zeropoint\else
+ \nobreak
+ \listalternativeparameter\c!filler
+ \box\b_strc_lists_page
+ \fi
+ }
+ \hss
+ }
+ }% new
+ \endgraf % new, else problems with nointerlinespace and prevdepth
+ \nointerlineskip % anders verkeerde spatiering bij multi-line
+ \endgraf
+ \allowbreak
+ \listparameter\c!after
+\stopsetups
+
+% % example from the context list
+%
+% \setuphead [part] [page=right,placehead=yes]
+% \setuplist [chapter] [alternative=d,before=\blank,after=\blank]
+% \setuplist [part] [before=\blank,after=\blank]
+%
+% \starttext
+% \startnarrower[2*right] \placecontent \stopnarrower
+% \blank[4*big]
+% \startsetups chapter
+% \blank \startnarrower[3*middle] \placecontent[criterium=local] \stopnarrower
+% \stopsetups
+% \placelist[part][criterium=text,after=\setups{chapter}]
+%
+% \part{First part} \chapter{Chapter one} \chapter{Chapter two}
+% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
+% \part{Second part} \chapter{Chapter one} \chapter{Chapter two}
+% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
+% \part{Third part} \chapter{Chapter one} \chapter{Chapter two}
+% \chapter{Chapter three} \chapter{Chapter four} \chapter{Chapter five}
+% \stoptext
+
+% overrulen interactie kan sneller, bv door hulpconstanten
+% te gebruiken en die te letten
+
+\startsetups[\??listrenderings:d]
+ \ifvmode
+ \advance\leftskip\listparameter\c!margin
+ \fi
+ \begingroup
+ \ifvmode
+ \noindent
+ \fi
+ \begingroup
+ \strc_lists_set_reference_attribute\v!all
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \strc_lists_get_destination_attribute
+ \begingroup
+ \ifconditional\c_lists_show_number
+ \donetrue
+ \ifconditional\c_lists_has_number \else
+ \edef\p_symbol{\listparameter\c!symbol}
+ \ifx\p_symbol\empty
+ \donefalse
+ \fi
+ \fi
+ \ifdone
+ \begingroup
+ \strc_lists_set_reference_attribute\v!number
+ \strc_lists_set_style_color\c!numberstyle\c!numbercolor\v!number
+ \listparameter\c!left
+ \listparameter\c!numbercommand\currentlistsymbol
+ \listparameter\c!right
+ \endgroup
+ \kern.5em
+ \nobreak
+ \fi
+ \fi
+ \endgroup
+ \begingroup
+ \strc_lists_set_reference_attribute\v!text
+ \strc_lists_set_style_color\c!textstyle\c!textcolor\v!text
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut % needs checking, new here
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ \endgroup
+ \begingroup
+ \ifconditional\c_lists_has_page
+ \ifconditional\c_lists_show_page
+ \nobreak
+ \hskip.75em\relax
+ \nobreak
+ \strc_lists_set_reference_attribute\v!pagenumber
+ \strc_lists_set_style_color\c!pagestyle\c!pagecolor\v!pagenumber
+ \strut
+ \listparameter\c!pagecommand\currentlistentrypagenumber
+ \fi
+ \fi
+ \endgroup
+ \scratchdistance\listparameter\c!distance\relax
+ \ifdim\scratchdistance<\emwidth
+ \hskip\emwidth\!!plus\emwidth\!!minus.25\emwidth\relax
+ \else
+ \hskip\scratchdistance\!!plus.5\scratchdistance\!!minus.25\scratchdistance\relax
+ \fi
+ \endgroup
+ \endgroup
+\stopsetups
+
+\startsetups[\??listrenderings:e]
+ \noindent
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \letlistparameter\c!depth\zeropoint
+ \letlistparameter\c!color\empty
+ \inheritedlistframed {
+ \letinteractionparameter\c!strut\v!no % still needed?
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ }
+ }
+ \par
+ \listparameter\c!inbetween
+\stopsetups
+
+\startsetups[\??listrenderings:f]
+ \noindent
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \dosetraggedhbox{\listparameter\c!align}%
+ \raggedbox {
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ }
+ }
+ \par
+ \listparameter\c!inbetween
+\stopsetups
+
+\startsetups[\??listrenderings:g]
+ \noindent
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \midaligned {
+ \strc_lists_set_style_color\c!style\c!color\v!all
+ \the\t_lists_every_renderingtext
+ \the\t_lists_every_renderingsynchronize
+ \setstrut
+ \begstrut
+ \strc_lists_limitated_text\currentlistentrytitle
+ \endstrut
+ }
+ }
+ \par
+ \listparameter\c!inbetween
+\stopsetups
+
+%D This is a new one, similar to vertical and horizontal but better suited when
+%D no command is set (WS):
+
+\definelistalternative
+ [\v!interactive]
+ [\c!renderingsetup=\??listrenderings:interactive]
+
+\startsetups[\??listrenderings:interactive]
+ \edef\p_command{\listalternativeparameter\c!command}%
+ \ifx\p_command\empty
+ [\currentlist: \currentlistentrynumber\space -- \currentlistentrytitle\space -- \currentlistentrypagenumber]%
+ \else
+ \listparameter\c!before
+ \hbox \strc_lists_get_reference_attribute\v!all \strc_lists_get_destination_attribute {
+ \p_command\currentlistentrynumber\currentlistentrytitle\currentlistentrypagenumber
+ }
+ \listparameter\c!after
+ \fi
+\stopsetups
+
+%D List elements are packaged in such a way that we can click on them
+%D in an interactive document. Here are a few helpers.
+
+\newconstant\a_strc_lists_reference
+\newconstant\a_strc_lists_destination
+
+\installcorenamespace{listinteractions}
+
+\letvalue{\??listinteractions\v!number }\v!number
+\letvalue{\??listinteractions\v!sectionnumber}\v!number
+\letvalue{\??listinteractions\v!text }\v!text
+\letvalue{\??listinteractions\v!title }\v!text
+\letvalue{\??listinteractions\v!page }\v!pagenumber
+\letvalue{\??listinteractions\v!pagenumber }\v!pagenumber
+\letvalue{\??listinteractions\v!all }\v!all
+\letvalue{\??listinteractions\v!yes }\v!all
+
+\unexpanded\def\strc_lists_interaction_check
+ {\iflocation
+ \strc_lists_interaction_check_yes
+ \else
+ \strc_lists_interaction_check_nop
+ \fi}
+
+\def\strc_lists_interaction_check_yes
+ {\edef\p_interaction_forward{\listparameter\c!interaction}%
+ \ifcsname\??listinteractions\p_interaction_forward\endcsname
+ \expandafter\let\expandafter\p_interaction_forward\csname\??listinteractions\p_interaction_forward\endcsname
+ \strc_references_get_simple_page_reference{internal(\currentlistentrylocation)}%
+ \a_strc_lists_reference\currentreferenceattribute
+ \else
+ \a_strc_lists_reference\attributeunsetvalue
+ \fi
+ \ifnum\a_strc_lists_reference=\attributeunsetvalue
+ \let\strc_lists_get_reference_attribute\gobbleoneargument
+ \let\strc_lists_set_reference_attribute\gobbleoneargument
+ \let\strc_lists_set_style_color \strc_lists_set_style_color_normal
+ \else
+ \let\strc_lists_get_reference_attribute\strc_lists_get_reference_attribute_indeed
+ \let\strc_lists_set_reference_attribute\strc_lists_set_reference_attribute_indeed
+ \let\strc_lists_set_style_color \strc_lists_set_style_color_special
+ \fi
+ \edef\p_interaction_backward{\namedheadparameter\currentlist\c!interaction}% \namedheadparameter !
+ \ifx\p_interaction_backward\v!list
+ \strc_references_set_simple_page_reference{bck:\currentlistentrylocation}%
+ \a_strc_lists_destination\currentdestinationattribute
+ \else
+ \a_strc_lists_destination\attributeunsetvalue
+ \fi
+ \ifnum\a_strc_lists_destination=\attributeunsetvalue
+ \let\strc_lists_get_destination_attribute\empty
+ \let\strc_lists_set_destination_attribute\empty
+ \else
+ \let\strc_lists_get_destination_attribute\strc_lists_get_destination_attribute_indeed
+ \let\strc_lists_set_destination_attribute\strc_lists_set_destination_attribute_indeed
+ \fi}
+
+\def\strc_lists_interaction_check_nop
+ {\let\strc_lists_get_reference_attribute \gobbleoneargument
+ \let\strc_lists_set_reference_attribute \gobbleoneargument
+ \let\strc_lists_get_destination_attribute\empty
+ \let\strc_lists_set_destination_attribute\empty
+ \let\strc_lists_set_style_color \strc_lists_set_style_color_normal}
+
+\strc_lists_interaction_check_nop
+
+\def\strc_lists_get_reference_attribute_indeed#element%
+ {\ifx#element\p_interaction_forward
+ attr \referenceattribute\a_strc_lists_reference
+ \fi}
+
+\def\strc_lists_set_reference_attribute_indeed#element%
+ {\ifx#element\p_interaction_forward
+ \attribute\referenceattribute\a_strc_lists_reference
+ \fi}
+
+\def\strc_lists_get_destination_attribute_indeed
+ {attr \destinationattribute\number\a_strc_lists_destination}
+
+\def\strc_lists_set_destination_attribute_indeed
+ {\attribute\destinationattribute\a_strc_lists_destination}
+
+\unexpanded\def\strc_lists_set_style_color_normal#style#color#element%
+ {\useliststyleandcolor#style#color}
+
+\unexpanded\def\strc_lists_set_style_color_special#style#color#element%
+ {\useliststyleandcolor#style#color%
+ \ifx\currentcolorparameter\empty
+ \ifx#element\p_interaction_forward
+ \setlocationcolor
+ \fi
+ % \else
+ % \resetinteractionparameter\c!color
+ % \resetinteractionparameter\c!contrastcolor
+ \fi}
+
+%D A helper:
+
+\def\strc_lists_limitated_text#text%
+ {\edef\p_maxwidth{\listparameter\c!maxwidth}%
+ \ifx\p_maxwidth\empty
+ \listparameter\c!textcommand{#text}%
+ \else
+ \listparameter\c!textcommand{\limitatetext{#text}\p_maxwidth{\splitsymbol{\listparameter\c!limittext}}}%
+ \fi}
+
+% todo:
+
+\def\utilitylistlength{\listlength} % old name ... uses in styles
+
+\let\listlength\!!zerocount % better use listmode
+
+\unexpanded\def\determinelistcharacteristics
+ {\dodoubleempty\strc_lists_determine_characteristics}
+
+\def\strc_lists_determine_characteristics[#list][#settings]%
+ {\begingroup
+ \edef\currentlist{\firststructureelementinlist{#list}}%
+ \ifx\currentlist\empty
+ \endgroup
+ \let\listlength\!!zerocount
+ \else
+ \setupcurrentlist[#settings]%
+ \doanalyzestructurelist{#list}{\listparameter\c!criterium}{\listparameter\c!number}%
+ \normalexpanded{\endgroup\noexpand\edef\noexpand\listlength{\structurelistsize}}%
+ \fi
+ \strc_lists_set_mode}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-mar.lua b/Master/texmf-dist/tex/context/base/strc-mar.lua
index 5bb40fa94e3..66ec047394d 100644
--- a/Master/texmf-dist/tex/context/base/strc-mar.lua
+++ b/Master/texmf-dist/tex/context/base/strc-mar.lua
@@ -7,10 +7,12 @@ if not modules then modules = { } end modules ['strc-mar'] = {
}
-- todo: cleanup stack (structures.marks.reset(v_all) also does the job)
+-- todo: only commands.* print to tex, native marks return values
local insert, concat = table.insert, table.concat
local tostring, next, rawget = tostring, next, rawget
local lpegmatch = lpeg.match
+local match = string.match
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -45,6 +47,7 @@ local v_current = variables.current
local v_default = variables.default
local v_page = variables.page
local v_all = variables.all
+local v_keep = variables.keep
local v_nocheck_suffix = ":" .. variables.nocheck
@@ -130,21 +133,33 @@ local classes = { }
setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s return s end)
-function marks.synchronize(class,n)
+local lasts = { }
+
+function marks.synchronize(class,n,option)
local box = texbox[n]
if box then
local first, last = sweep(box.list,0,0)
- local classlist = classes[class]
- for i=1,#classlist do
- local class = classlist[i]
- local range = ranges[class]
- if not range then
- range = { }
- ranges[class] = range
- end
- range.first, range.last = first, last
+ if option == v_keep and first == 0 and last == 0 then
if trace_marks_get or trace_marks_set then
- report_marks("synchronize: class=%s, first=%s, last=%s",class,range.first,range.last)
+ report_marks("synchronize: class=%s, box=%s, retaining",class,n)
+ end
+ -- todo: check if still valid firts/last in range
+ first = lasts[class] or 0
+ last = first
+ else
+ lasts[class] = last
+ local classlist = classes[class]
+ for i=1,#classlist do
+ local class = classlist[i]
+ local range = ranges[class]
+ if not range then
+ range = { }
+ ranges[class] = range
+ end
+ range.first, range.last = first, last
+ if trace_marks_get or trace_marks_set then
+ report_marks("synchronize: class=%s, first=%s, last=%s",class,range.first,range.last)
+ end
end
end
elseif trace_marks_get or trace_marks_set then
@@ -180,7 +195,7 @@ function marks.define(name,settings)
settings = settings or { }
data[name] = settings
local parent = settings.parent
- if parent == nil or parent == "" then
+ if parent == nil or parent == "" or parent == name then
settings.parent = false
else
local dp = data[parent]
@@ -274,7 +289,7 @@ function marks.set(name,value)
report_marks("set: parent=%s, child=%s, index=%s, value=%s",parent,child,topofstack,value)
end
end
- tex.setattribute("global",a_marks,topofstack)
+ texsetattribute("global",a_marks,topofstack)
end
end
@@ -479,6 +494,15 @@ local function doresolve(name,rangename,swap,df,dl,strict)
return value, index, found
end
+-- previous : last before sync
+-- next : first after sync
+
+-- top : first in sync
+-- bottom : last in sync
+
+-- first : first not top in sync
+-- last : last not bottom in sync
+
methods[v_previous] = function(name,range) return doresolve(name,range,false,-1,0,true ) end -- strict
methods[v_top] = function(name,range) return doresolve(name,range,false, 0,0,true ) end -- strict
methods[v_bottom] = function(name,range) return doresolve(name,range,true , 0,0,true ) end -- strict
@@ -489,27 +513,66 @@ methods[v_top_nocheck] = function(name,range) return doresolve(name,range,f
methods[v_bottom_nocheck] = function(name,range) return doresolve(name,range,true , 0,0,false) end
methods[v_next_nocheck] = function(name,range) return doresolve(name,range,true , 0,1,false) end
-local function resolve(name,range,f_swap,l_swap,step,strict) -- we can have an offset
- local f_value, f_index, f_found = doresolve(name,range,f_swap,0,0,strict)
- local l_value, l_index, l_found = doresolve(name,range,l_swap,0,0,strict)
+local function do_first(name,range,check)
+ if trace_marks_get then
+ report_marks("resolve: name=%s, range=%s, resolve first",name,range)
+ end
+ local f_value, f_index, f_found = doresolve(name,range,false,0,0,check)
+ if trace_marks_get then
+ report_marks("resolve: name=%s, range=%s, resolve last",name,range)
+ end
+ local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check)
if f_found and l_found and l_index > f_index then
local name = parentname(name)
- for i=f_index,l_index,step do
+ for i=f_index,l_index,1 do
local si = stack[i]
local sn = si[name]
if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= f_value then
+ if trace_marks_get then
+ report_marks("resolve: name=%s, range=%s, index=%s, value=%s",name,range,i,sn)
+ end
return sn, i, si
end
end
end
+ if trace_marks_get then
+ report_marks("resolve: name=%s, range=%s, using first",name,range)
+ end
return f_value, f_index, f_found
end
-methods[v_first ] = function(name,range) return resolve(name,range,false,true, 1,true ) end -- strict
-methods[v_last ] = function(name,range) return resolve(name,range,true,false,-1,true ) end -- strict
+local function do_last(name,range,check)
+ if trace_marks_get then
+ report_marks("resolve: name=%s, range=%s, resolve first",name,range)
+ end
+ local f_value, f_index, f_found = doresolve(name,range,false,0,0,check)
+ if trace_marks_get then
+ report_marks("resolve: name=%s, range=%s, resolve last",name,range)
+ end
+ local l_value, l_index, l_found = doresolve(name,range,true ,0,0,check)
+ if f_found and l_found and l_index > f_index then
+ local name = parentname(name)
+ for i=l_index,f_index,-1 do
+ local si = stack[i]
+ local sn = si[name]
+ if sn and sn ~= false and sn ~= true and sn ~= "" and sn ~= l_value then
+ if trace_marks_get then
+ report_marks("resolve: name=%s, range=%s, index=%s, value=%s",name,range,i,sn)
+ end
+ return sn, i, si
+ end
+ end
+ end
+ if trace_marks_get then
+ report_marks("resolve: name=%s, range=%s, using last",name,range)
+ end
+ return l_value, l_index, l_found
+end
-methods[v_first_nocheck] = function(name,range) return resolve(name,range,false,true, 1,false) end
-methods[v_last_nocheck ] = function(name,range) return resolve(name,range,true,false,-1,false) end
+methods[v_first ] = function(name,range) return do_first(name,range,true ) end
+methods[v_last ] = function(name,range) return do_last (name,range,true ) end
+methods[v_first_nocheck] = function(name,range) return do_first(name,range,false) end
+methods[v_last_nocheck ] = function(name,range) return do_last (name,range,false) end
methods[v_current] = function(name,range) -- range is ignored here
local top = stack[topofstack]
@@ -592,15 +655,25 @@ function marks.fetchonemark (name,range,method) fetchonemark (name,range,method)
function marks.fetchtwomarks(name,range) fetchtwomarks(name,range ) end
function marks.fetchallmarks(name,range) fetchallmarks(name,range ) end
--- here we have a few helpers
+-- here we have a few helpers .. will become commands.*
function marks.title(tag,n)
- lists.savedtitle(tag,n,"marking")
+ local listindex = match(n,"^li::(.-)$")
+ if listindex then
+ commands.savedlisttitle(tag,listindex,"marking")
+ else
+ context(n)
+ end
end
function marks.number(tag,n) -- no spec
- -- no prefix (as it is the prefix)
- lists.savednumber(tag,n)
+ local listindex = match(n,"^li::(.-)$")
+ if listindex then
+ commands.savedlistnumber(tag,listindex)
+ else
+ -- no prefix (as it is the prefix)
+ context(n)
+ end
end
-- interface
diff --git a/Master/texmf-dist/tex/context/base/strc-mar.mkii b/Master/texmf-dist/tex/context/base/strc-mar.mkii
index 62e6f4ded55..2ae81e47bb5 100644
--- a/Master/texmf-dist/tex/context/base/strc-mar.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-mar.mkii
@@ -5,7 +5,7 @@
%D subtitle=Markings,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-mar.mkiv b/Master/texmf-dist/tex/context/base/strc-mar.mkiv
index 2fe8631b27b..19fc30c3191 100644
--- a/Master/texmf-dist/tex/context/base/strc-mar.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-mar.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Markings,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -41,59 +41,28 @@
\definesystemattribute [marks] [global]
-\let\currentmarking\empty
-
-\def\markingparameter #1{\csname\domarkingparameter{\??mk\currentmarking}#1\endcsname}
-\def\namedmarkingparameter #1#2{\csname\domarkingparameter{\??mk#1}#2\endcsname}
-\def\domarkingparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\domarkingparentparameter\csname#1\s!parent\endcsname#2\fi}
-\def\domarkingparentparameter#1#2{\ifx#1\relax\s!empty\else\domarkingparameter#1#2\fi}
-
-% \def\markingparameterhash #1{\domarkingparameterhash{\??mk\currentmarking}#1}
-% \def\domarkingparameterhash #1#2{\ifcsname#1#2\endcsname#1\else\expandafter\domarkingparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-% \def\domarkingparentparameterhash#1#2{\ifx#1\relax\else\domarkingparameterhash#1#2\fi}
-%
-% \def\detokenizedmarkingparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??mk\currentmarking#1\endcsname}}
-%
-% \def\dosetmarkingattributes#1#2% style color
-% {\edef\fontattributehash {\markingparameterhash#1}%
-% \edef\colorattributehash{\markingparameterhash#2}%
-% \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
-% \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-\newconditional\inhibitgetmarking
-\newconditional\inhibitsetmarking
-\newtoks \everymarking
+\installcorenamespace{marking}
-\unexpanded\def\setupmarking
- {\dodoubleargument\dosetupmarking}
+\installcommandhandler \??marking {marking} \??marking
-\def\dosetupmarking[#1][#2]%
- {\ifsecondargument
- \def\docommand##1{\getparameters[\??mk##1][#2]}%
- \processcommalist[#1]\docommand
- \else
- \getparameters[\??mk][#1]%
- \fi}
+\newconditional\inhibitgetmarking % will become private
+\newconditional\inhibitsetmarking % will become private
-% management
+\newtoks \everymarking
-\unexpanded\def\definemarking {\dodoubleempty \dodefinemarking}
-\unexpanded\def\relatemarking {\dodoubleempty \dorelatemarking}
-\unexpanded\def\setmarking {\dosingleargument\dosetmarking } \let\marking\setmarking
-\unexpanded\def\resetmarking {\dosingleargument\doresetmarking }
-\unexpanded\def\synchronizemarking{\dodoubleargument\dosynchronizemarking }
+\unexpanded\def\relatemarking {\dodoubleempty \strc_markings_relate }
+\unexpanded\def\setmarking {\dosingleargument\strc_markings_set } \let\marking\setmarking
+\unexpanded\def\resetmarking {\dosingleargument\strc_markings_reset }
+\unexpanded\def\synchronizemarking{\dotripleargument\strc_markings_synchronize}
-\def\dodefinemarking[#1][#2]% marking parent
- {\doifelsenothing{#2}
- {\ctxcommand{definemarking("#1")}%
- \getparameters[\??mk#1][\s!parent=\??mk]}
- {\ctxcommand{definemarking("#1",{ parent = "#2" })}%
- \getparameters[\??mk#1][\s!parent=\??mk#2]}}
+\appendtoks
+ \ctxcommand{definemarking("\currentmarking",{ parent = "\currentmarkingparent" })}%
+\to \everydefinemarking
-\def\dorelatemarking[#1][#2]%
+\def\strc_markings_relate[#1][#2]%
{\ctxcommand{relatemarking("#1","#2")}}
-\def\dosetmarking[#1]#2%
+\def\strc_markings_set[#1]#2%
{\ifconditional\inhibitsetmarking
% nothing
\else
@@ -102,17 +71,17 @@
{\ctxcommand{setmarking("#1",\!!bs\detokenize{#2}\!!es)}}%
\fi}
-\def\doresetmarking[#1]%
+\def\strc_markings_reset[#1]%
{\ctxcommand{resetmarking("#1")}}
+\def\strc_markings_synchronize[#1][#2][#3]% #1=class #2=boxnumber (some day also name) #3=options, maybe second argument table
+ {\ifvoid#2\else\ctxcommand{synchronizemarking("#1",\number#2,"#3")}\fi}
+
\def\doifelsemarking#1%
{\ctxcommand{doifelsemarking("#1")}}
-\def\dosynchronizemarking[#1][#2]% class boxnumber (some day also name), maybe second argument table
- {\ifvoid#2\else\ctxcommand{synchronizemarking("#1",\number#2)}\fi}
-
% \appendtoks
-% \dosynchronizemarking[\v!page][\normalpagebox]%
+% \strc_markings_synchronize[\v!page][\normalpagebox][\v!keep]% keep if no marks
% \to \everybeforepagebody
% defaults
@@ -127,15 +96,15 @@
\unexpanded\def\getmarking
{\ifconditional\inhibitgetmarking
- \expandafter\dotripleargument\expandafter\nogetmarking
+ \expandafter\dotripleargument\expandafter\strc_markings_get_nop
\else
- \expandafter\dotripleargument\expandafter\dogetmarking
+ \expandafter\dotripleargument\expandafter\strc_markings_get_yes
\fi}
-\def\nogetmarking[#1][#2][#3]%
+\def\strc_markings_get_nop[#1][#2][#3]%
{}
-\def\dogetmarking[#1][#2][#3]%
+\def\strc_markings_get_yes[#1][#2][#3]%
{\doif{\namedmarkingparameter{#1}\c!state}\v!start
{\begingroup
\setsystemmode\v!marking
diff --git a/Master/texmf-dist/tex/context/base/strc-mat.lua b/Master/texmf-dist/tex/context/base/strc-mat.lua
index d9cca27176a..98b1e996c3c 100644
--- a/Master/texmf-dist/tex/context/base/strc-mat.lua
+++ b/Master/texmf-dist/tex/context/base/strc-mat.lua
@@ -22,7 +22,7 @@ local formuladata = { }
function formulas.store(data)
formuladata[#formuladata+1] = data
- tex.write(#formuladata)
+ context(#formuladata)
end
function formulas.current()
diff --git a/Master/texmf-dist/tex/context/base/strc-mat.mkii b/Master/texmf-dist/tex/context/base/strc-mat.mkii
index 0d32cb29864..d85df79e2f6 100644
--- a/Master/texmf-dist/tex/context/base/strc-mat.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-mat.mkii
@@ -5,7 +5,7 @@
%D subtitle=Math Fundamentals,
%D author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-mat.mkiv b/Master/texmf-dist/tex/context/base/strc-mat.mkiv
index 8d408936036..121808cd13a 100644
--- a/Master/texmf-dist/tex/context/base/strc-mat.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-mat.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Math Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -15,91 +15,158 @@
\registerctxluafile{strc-mat}{1.001}
-% we have potential for captions
+% -- we have potential for captions
+% -- this module will use the commandhandler
+% -- key/value pairs will be added (I have no time now)
\unprotect
-\definestructureconversionset[\v!formula][numbers,characters]
-
\setupformulas
- [%\c!way=\@@nrway,
+ [%\c!way=,
%\c!blockway=,
- %\c!sectionnumber=\@@nrsectionnumber,
+ %\c!sectionnumber=,
%\c!conversion=\v!numbers,
- \c!location=\v!right,
- \c!left=(,
- \c!right=),
%\c!numberstyle=,
%\c!numbercolor=,
%\c!numbercommand=,
+ %\c!margin=,
+ %\c!align=,
+ %\c!separator=,
+ %\c!grid=,
+ \c!location=\v!right,
+ \c!left=(,
+ \c!right=),
+ \c!expansion=\v!yes, % maybe automatically
\c!spacebefore=\v!big,
\c!spaceafter=\formulaparameter\c!spacebefore,
\c!leftmargin=\!!zeropoint,
\c!rightmargin=\!!zeropoint,
- %\c!margin=,
\c!indentnext=\v!no,
\c!alternative=\s!default,
- %\c!align=,
\c!strut=\v!no,
- %\c!separator=\@@koseparator,
- %\c!grid=,
\c!distance=1em]
-\definestructurecounter
+\setupsubformulas % subformulas could be last in chain
+ [\c!indentnext=\formulaparameter\c!indentnext]
+
+\definecounter
[\v!formula]
-% \setupstructurecounter
-% [\v!formula]
-% [\c!numberconversionset=\v!formula]
+\defineconversionset
+ [\v!formula]
+ [numbers,characters]
-\presetstructurecountersetup\setupformulas\sharedstructurecounterparameter
+\strc_counter_preset_using_parameter\setupformulas\sharedcounterparameter
\appendtoks
-% \dostructurecountersetup\currentformula\formulaparameter
-% \docheckstructurecountersetup\currentformula
- \dostructurecountersetup\v!formula\formulaparameter
-% \docheckstructurecountersetup\v!formula
-\to \everysetupformulas
+ \strc_counter_setup_using_parameter\v!formula\formulaparameter
+ \strc_counters_check_setup\v!formula % yes or no
+\to \everysetupformula
\setupformulas
[\c!numberconversionset=\v!formula] % why forgotten
+\appendtoks
+ \normalexpanded{\definelist[\currentformula]}% is expansion needed?
+ \setuevalue{\e!start\currentformula\v!formula}{\dostartformula{\currentformula}}%
+ \setuevalue{\e!stop \currentformula\v!formula}{\dostopformula}%
+\to \everydefineformula
+
+\definelist[\v!formula]
+
+\setuvalue{\e!start\v!formula}{\dostartformula{}}
+\setuvalue{\e!stop \v!formula}{\dostopformula}
+
+\let\dostartformula\relax % defined later
+\let\dostopformula \relax % defined later
+
+\unexpanded\def\defineformulaalternative % this might change ... start and stop can become keys
+ {\dotripleargument\dodefineformulaalternative} % to the general define .. s!startcommand
+
+\def\dodefineformulaalternative[#1][#2][#3]%
+ {\setvalue{\e!start#1\v!formula}{#2}%
+ \setvalue{\e!stop #1\v!formula}{#3}}
+
+% sp = single line paragraph sd = single line display
+% mp = multi line paragraph md = multy line display
+
+\defineformulaalternative[\s!default][\startdisplaymath][\stopdisplaymath]
+\defineformulaalternative[\s!single] [\startdisplaymath][\stopdisplaymath]
+\defineformulaalternative[\s!multi] [\startdisplaymath][\stopdisplaymath]
+
+\defineformula
+ [sp]
+ [\c!spacebefore=\v!none,
+ \c!spaceafter=\v!none,
+ \c!indentnext=\v!no,
+ \c!alternative=\s!single]
+
+\defineformula
+ [sd]
+ [\c!spacebefore=\v!none,
+ \c!spaceafter=\v!none,
+ \c!indentnext=\v!yes,
+ \c!alternative=\s!single]
+
+\defineformula
+ [mp]
+ [\c!indentnext=\v!no,
+ \c!alternative=\s!multi]
+
+\defineformula
+ [md]
+ [\c!indentnext=\v!yes,
+ \c!alternative=\s!multi]
+
+\newtoks\everyresetformulas
+
+\appendtoks
+ \let\currentformula\empty % to be checked:
+\to \everyresetformulas
+
+% implementation
+
\def\storecurrentformulanumber#1#2#3#4#5% ref, todo:str, \sync % todo: title etc (like float)
- {\dostructurecountercomponent
+ {\settrue\handleformulanumber
+ \strc_counters_register_component
{formula}%
- \getformulaparameters \formulaparameter \detokenizedformulaparameter
+ \setupcurrentformula \formulaparameter \detokenizedformulaparameter
\relax \relax \relax
-% [\c!name=\currentformula,\s!counter=\currentformula,%
[\c!name=\v!formula,\s!counter=\v!formula,%
\s!hascaption=\v!yes,\s!hastitle=\v!yes,\s!hasnumber=\v!yes,%\s!haslevel=#6,%
- \s!hasnumber=\v!no,%
\c!reference=#1,\c!title=\namedformulaentry,\c!bookmark=]%
[#2]%
- \glet\namedformulaentry\relax
- \globallet#3\laststructurecounternumber
- \globallet#4\laststructurecountersynchronize
- \globallet#5\laststructurecounterattribute}
-
-\newif\ifnoformulanumber
+ \glet\namedformulaentry\empty % \relax
+ \globallet#3\m_strc_counters_last_registered_index
+ \globallet#4\m_strc_counters_last_registered_synchronize
+ \globallet#5\m_strc_counters_last_registered_attribute}
-\newconditional\handleformulanumber
-\newconditional\incrementformulanumber
-
-\newtoks\everyresetformulas
-
-% 0=unset, 1=forced, 2=none, 3=reference
+% modes: 0=unset, 1=forced, 2=none, 3=reference
\newconstant\placeformulanumbermode
\newconstant\formulasnumbermode
\newconstant\subformulasnumbermode
\newconstant\nestedformulanumbermode
+\appendtoks
+ \placeformulanumbermode \zerocount
+ \formulasnumbermode \zerocount
+ \subformulasnumbermode \zerocount
+ \nestedformulanumbermode\zerocount
+\to \everyresetformulas
+
+\newconditional\handleformulanumber
+\newconditional\incrementformulanumber
+
\newconditional\insideplaceformula
\newconditional\insideplacesubformula
\newconditional\insideformulas
\newconditional\insidesubformulas
-% 0=unset, 1=forced, 2=none, 3=reference
+\appendtoks
+ \global\setfalse\insideplaceformula
+ \global\setfalse\insideplacesubformula
+\to \everyresetformulas
\def\handleplaceformulanumbering % place formula
{\settrue\handleformulanumber
@@ -108,11 +175,11 @@
\glet\donestedformulanumber\donestedformulanumberindeed}
\def\handleformulasnumbering % formulas
- {\docheckformulareference\formulasnumbermode\currentformularesference}
+ {\docheckformulareference\formulasnumbermode\currentformulareference}
\def\handlesubformulasnumbering % sub formulas
{\docheckformulareference\subformulasnumbermode\currentsubformulasreference
- \doincrementsubstructurecounter[\v!formula][1]% always
+ \strc_counters_increment\v!formula
\storecurrentformulanumber
\currentsubformulasreference
\empty
@@ -121,23 +188,41 @@
\currentsubformulasattribute
}
-\def\tracedformulamode
- {\hbox{\quad\tt\txx[\number\placeformulanumbermode,\number\formulasnumbermode,\number\subformulasnumbermode,\number\nestedformulanumbermode]}}
+\let\dotraceformulareferencestate\relax
+\let\doshowformulareferencestate \relax
+
+% \def\dotraceformulareferencestate
+% {\rlap{\hbox{\quad\tt\txx[%
+% \number\placeformulanumbermode,%
+% \number\formulasnumbermode,%
+% \number\subformulasnumbermode,%
+% \number\nestedformulanumbermode
+% ]}}}
+
+% \def\doshowformulareferencestate
+% {\writestatus{\v!formula}%
+% {place: \number\placeformulanumbermode,\space
+% formula: \number\formulasnumbermode,\space
+% subformula: \number\subformulasnumbermode,\space
+% nested: \number\nestedformulanumbermode]}}
\unexpanded\def\placecurrentformulanumber
{\rm % nodig ?
\doif{\formulaparameter\c!location}\v!right{\hskip\formulaparameter\c!distance}%
\formulaparameter\c!numbercommand
- {\dosetformulaattributes\c!numberstyle\c!numbercolor
+ {\useformulastyleandcolor\c!numberstyle\c!numbercolor
\strut
\formulaparameter\c!left
- \labeltexts\v!formula{\ignorespaces\doplacecurrentformulanumber\unskip}%
+ \namedtaggedlabeltexts
+ \t!formulalabel \v!formula
+ \t!formulanumber\v!formula
+ {\ignorespaces\doplacecurrentformulanumber\removeunwantedspaces}%
\formulaparameter\c!right}%
\doif{\formulaparameter\c!location}\v!left{\hskip\formulaparameter\c!distance}}
\def\doplacecurrentformulanumber
{\dohandlecurrentformulareferences
- \labeltexts\currentformula{\doconvertedstructurecounter[\v!formula][]}}
+ \labeltexts\currentformula{\convertedcounter[\v!formula][]}}
% \def\theboxdestinationattribute#1{\iflocation\ifx#1\relax\else\ifx#1\empty\else attr \destinationattribute#1\fi\fi\fi}
% \def\thedestinationattribute #1{\iflocation\ifx#1\relax\else\ifx#1\empty\else \attribute\destinationattribute#1\fi\fi\fi}
@@ -148,18 +233,57 @@
\glet#1\relax
\fi\fi\fi}
+\let\currentplaceformulaattribute\relax
+\let\currentformulaattribute \relax
+\let\currentsubformulaattribute \relax
+\let\currentformulasattribute \relax
+
+\let\currentplaceformulanumber\relax
+\let\currentformulanumber \relax
+\let\currentsubformulanumber \relax
+\let\currentformulasnumber \relax
+
+\let\currentformulasreference \empty
+\let\currentformulareference \empty
+\let\currentsubformulareference \empty
+\let\currentnestedformulareference\empty
+
+\appendtoks
+ \glet\currentformulasreference \empty
+ \glet\currentformulareference \empty
+ \glet\currentsubformulareference \empty
+ \glet\currentnestedformulareference\empty
+\to \everyresetformulas
+
+\let\currentformulassuffix \empty
+\let\currentformulasuffix \empty
+\let\currentsubformulasuffix \empty
+\let\currentnestedformulasuffix\empty
+
+\appendtoks
+ \glet\currentformulassuffix \empty
+ \glet\currentformulasuffix \empty
+ \glet\currentsubformulasuffix \empty
+ \glet\currentnestedformulasuffix\empty
+\to \everyresetformulas
+
+\let\currentplaceformulasynchronize\relax
+\let\currentformulasynchronize \relax
+\let\currentsubformulasynchronize \relax
+\let\currentformulassynchronize \relax
+
\appendtoks
\glet\currentplaceformulasynchronize \relax
\glet\currentformulassynchronize \relax
\glet\currentsubformulassynchronize \relax
\glet\currentnestedformulasynchronize\relax
- \let\currentformula\empty
\to \everyresetformulas
% currently we do the number, some day we will do the (sub) formula
\def\dohandlecurrentformulareferences
- {\ifnum\placeformulanumbermode=\plusthree
+ {\doshowformulareferencestate
+ \ifnum\placeformulanumbermode=\plusthree
\storecurrentformulanumber
\currentplaceformulareference
\empty
@@ -199,25 +323,15 @@
% needs checking ... too many:
-\let\currentplaceformulaattribute\relax \let\currentplaceformulasynchronize\relax \let\currentplaceformulanumber\relax
-\let\currentformulaattribute \relax \let\currentformulasynchronize \relax \let\currentformulanumber \relax
-\let\currentsubformulaattribute \relax \let\currentsubformulasynchronize \relax \let\currentsubformulanumber \relax
-\let\currentformulasattribute \relax \let\currentformulassynchronize \relax \let\currentformulasnumber \relax
-
-\let\currentformulasreference \empty \let\currentformulassuffix \empty
-\let\currentformulareference \empty \let\currentformulasuffix \empty
-\let\currentsubformulareference \empty \let\currentsubformulasuffix \empty
-\let\currentnestedformulareference\empty \let\currentnestedformulasuffix\empty
-
\def\dohandleformulanumbering
- {\doincrementsubstructurecounter[\v!formula][1]%
- \doiftext\currentplaceformulasuffix{\setsubstructurecounterown[\v!formula][2]{\currentplaceformulasuffix}}%
+ {\strc_counters_increment\v!formula
+ \doiftext\currentplaceformulasuffix{\strc_counters_setown_sub\v!formula\plustwo\currentplaceformulasuffix}%
\placecurrentformulanumber}
\def\dohandlesubformulanumbering
{\doiftextelse\currentsubformulasuffix
- {\setsubstructurecounterown[\v!formula][2]{\currentsubformulasuffix}}
- {\doincrementsubstructurecounter[\v!formula][2]}%
+ {\strc_counters_setown_sub\v!formula\plustwo\currentsubformulasuffix}
+ {\strc_counters_increment_sub\v!formula\plustwo}%
\placecurrentformulanumber}
\def\dododoformulanumber
@@ -257,27 +371,15 @@
\dohandlesubformulanumbering
\fi
\fi
- %\rlap{\tracedformulamode}%
+ \dotraceformulareferencestate
\egroup
\fi}
-\definelist[\v!formula]
-
\installstructurelistprocessor\v!formula % to be checked ...
- {\dodolistelement
- \currentlist
- \structurelistlocation
- \structurelistgenericnumber
- \structurelistgenerictitle % hm, can end up in message (volkers test)
- \structurelistpagenumber
- \structurelistrealpagenumber}
-
-\appendtoks
- \global\setfalse\insideplaceformula
- \global\setfalse\insideplacesubformula
-% \global\setfalse\insideformulas
-% \global\setfalse\insidesubformulas
-\to \everyresetformulas
+ {\let\currentlistentrynumber \structurelistgenericnumber
+ \let\currentlistentrytitle \structurelistgenerictitle
+ \let\currentlistentrypagenumber\structurelistpagenumber
+ \strc_lists_apply_renderingsetup}
\newif\ifinformula
@@ -296,69 +398,9 @@
\let\normalreqno\gobbleoneargument \let\eqno \gobbleoneargument
\let\doplaceformulanumber\empty}
-%D
-
-\unexpanded\def\defineformula
- {\dodoubleempty\dodefineformula}
-
-\def\dodefineformula[#1][#2]%
- {\doifsomething{#1}
- {\getparameters[\??fm#1][\s!parent=\??fm,#2]%
- \definelist[#1]%
- \setvalue{\e!start#1\v!formula}{\dostartformula{#1}}%
- \setvalue{\e!stop #1\v!formula}{\dostopformula}}}
-
-\unexpanded\def\defineformulaalternative
- {\dotripleargument\dodefineformulaalternative}
-
-\def\dodefineformulaalternative[#1][#2][#3]%
- {\setvalue{\e!start#1\v!formula}{#2}%
- \setvalue{\e!stop #1\v!formula}{#3}}
-
-% sp = single line paragraph sd = single line display
-% mp = multi line paragraph md = multy line display
-
-\defineformulaalternative[\s!default][\startdisplaymath][\stopdisplaymath]
-\defineformulaalternative[\s!single] [\startdisplaymath][\stopdisplaymath]
-\defineformulaalternative[\s!multi] [\startdisplaymath][\stopdisplaymath]
-
-\defineformula
- [sp]
- [\c!spacebefore=\v!none,
- \c!spaceafter=\v!none,
- \c!indentnext=\v!no,
- \c!alternative=\s!single]
-
-\defineformula
- [sd]
- [\c!spacebefore=\v!none,
- \c!spaceafter=\v!none,
- \c!indentnext=\v!yes,
- \c!alternative=\s!single]
-
-\defineformula
- [mp]
- [\c!indentnext=\v!no,
- \c!alternative=\s!multi]
-
-\defineformula
- [md]
- [\c!indentnext=\v!yes,
- \c!alternative=\s!multi]
-
%D \macros
-%D {setupsubformulas, startsubformulas}
-
-\def\subformulaparameter#1{\ifcname\??fn#1\endcsname\cname\??fn#1\endcsname\fi}
+%D {startsubformulas}
-\unexpanded\def\setupsubformulas
- {\dodoubleargument\getparameters[\??fn]}
-
-\setupsubformulas
- [\c!indentnext=\formulaparameter\c!indentnext]
-
-% \setupsubformulas[conversion=romannumerals]
-%
% \placeformula
% \startsubformulas[Maxwell]
% \startformulas
@@ -395,9 +437,6 @@
\abovedisplayshortskip\zeropoint
\belowdisplayshortskip\zeropoint}
-\setvalue{\e!start\v!formula}{\dostartformula{}}
-\setvalue{\e!stop \v!formula}{\dostopformula}
-
\def\predisplaysizethreshhold{2em} % was 3em
\def\leftdisplayskip {\leftskip}
@@ -411,20 +450,6 @@
\def\afterdisplayspace
{\doifnot{\formulaparameter\c!spaceafter }\v!none{\blank[\formulaparameter\c!spaceafter ]}}
-% \def\setpredisplaysize
-% {\predisplaysize\lastlinewidth\relax
-% \ifdim\predisplaysize<\maxdimen
-% \ifdim\predisplaysize>\zeropoint
-% \advance\predisplaysize \predisplaysizethreshhold
-% \fi
-% \advance\predisplaysize \displayindent % needed ?
-% \ifdim\predisplaysize>\hsize
-% \predisplaysize\hsize
-% \fi
-% \else
-% \predisplaysize\zeropoint
-% \fi}
-
\def\setdisplaydimensions
{\displayindent\leftdisplayskip
\advance\displayindent\leftdisplaymargin
@@ -439,7 +464,7 @@
\advance\displaywidth\dimexpr-\displayindent-\rightdisplayskip-\rightdisplaymargin\relax
\hsize\displaywidth} % new, else overfull in itemize
-\def\dostartformula#1%
+\unexpanded\def\dostartformula#1%
{\dodoubleempty\dodostartformula[#1]}
\newskip\formulaparskip
@@ -480,43 +505,45 @@
\forgetdisplayskips
\getvalue{\e!start\formulaparameter\c!alternative\v!formula}}
+% tagging of formulanumbers is not ok (we get two display maths blobs)
+
+\unexpanded\def\dostopformula
+ {\dostarttagged\t!formulacaption\empty
+ \doplaceformulanumber
+ \dostoptagged
+ \dostarttagged\t!formulacontent\empty
+ \getvalue{\e!stop\formulaparameter\c!alternative\v!formula}%
+ \dostoptagged
+ \dostoptagged
+ \nonoindentation
+ \useindentnextparameter\formulaparameter
+ \egroup
+ \hangafter\minusone % added for side floats
+ \hangindent\zeropoint % added for side floats
+ \setfalse\handleformulanumber
+ \the\everyresetformulas
+ \dorechecknextindentation} % here ?
+
% experiment:
\appendtoks
\edef\currentformulagrid{\formulaparameter\c!grid}%
\ifx\currentformulagrid\empty \else
- \autosetsnapvalue\currentformulagrid
+ \spac_grids_snap_value_auto\currentformulagrid
\fi
\to \everybeforedisplayformula
\def\switchtoformulabodyfont{\switchtobodyfont}
-\setvalue{\v!formula}{\dosingleempty\doformula}
+\setuvalue{\v!formula}{\dosingleempty\doformula}
-\def\doformula[#1]#2%
+\def\doformula[#1]#2% todo: tagged
{\begingroup
\doifsomething{#1}{\switchtoformulabodyfont[#1]}%
% not : \def\doformula[##1]##2{\mathematics{##2}}%
\mathematics{#2}%
\endgroup}
-\def\dostopformula
- {\dostarttagged\t!formulatag\empty
- \doplaceformulanumber
- \dostoptagged
- \dostarttagged\t!formulacontent\empty
- \getvalue{\e!stop\formulaparameter\c!alternative\v!formula}%
- \dostoptagged
- \dostoptagged
- \nonoindentation
- \checknextindentation[\formulaparameter\c!indentnext]%
- \egroup
- \hangafter\minusone % added for side floats
- \hangindent\zeropoint % added for side floats
- \setfalse\handleformulanumber
- \the\everyresetformulas
- \dorechecknextindentation} % here ?
-
%D \starttyping
%D % test \par % no preceding hlist
%D % $$x$$ % preceding hlist
@@ -547,9 +574,6 @@
\par
\egroup}
-\newif\ifclipdisplaymath \clipdisplaymathtrue
-\def\displaymathclipfactor{1.1}
-
% already defined
%
% \let\startinnermath\empty
@@ -586,7 +610,7 @@
\unexpanded\def\stopsubformulas
{\nonoindentation
- \checknextindentation[\formulaparameter\c!indentnext]%
+ \useindentnextparameter\subformulaparameter
\the\everyresetformulas % to be checked
\global\setfalse\insidesubformulas
\dorechecknextindentation} % here ?
@@ -656,7 +680,7 @@
\def\forceformulanumberflag {+}
\def\docheckformulareference#1#2%
- {#1\unless\ifx\namedformulaentry\relax % new 29/8/2010
+ {#1\unless\ifx\namedformulaentry\empty % \relax % new 29/8/2010
\plusthree
\else\ifx#2\empty
\zerocount
@@ -668,7 +692,7 @@
\plusthree
\fi\fi\fi\fi}
-\def\formulanumber{\doformulanumber} % for the moment
+\unexpanded\def\formulanumber{\doformulanumber} % for the moment
\def\doformulanumber
{\dosingleempty\dodoformulanumber}
@@ -696,11 +720,11 @@
\let\currentplaceformulasuffix\empty
\doifnextbgroupelse\moreplaceformula\redoplaceformula} % [ref]{}
-\long\def\moreplaceformula#1%
+\def\moreplaceformula#1%
{\def\currentplaceformulasuffix{#1}%
\redoplaceformula}
-\long\def\redoplaceformula
+\def\redoplaceformula
{\doifnextcharelse$\dispplaceformula\dodoplaceformula} % [ref]$$ [ref]\start
\def\dodoplaceformula
@@ -715,19 +739,8 @@
% to be checked
-\def\doformulanumber
- {\dosingleempty\dodoformulanumber}
-
-\def\dodoformulanumber[#1]%
- {\def\currentformulareference{#1}%
- \dosinglegroupempty\dododoformulanumber}
-
-\def\redoformulanumber#1%
- {\def\currentformulasuffix{#1}%
- \dododoformulanumber}
-
-\glet\doplaceformulanumber \relax
-\glet\donestedformulanumber\gobbletwoarguments
+\let\doplaceformulanumber \relax
+\let\donestedformulanumber\gobbletwoarguments
\def\donestedformulanumberindeed#1#2%
{\def\currentnestedformulareference{#1}%
@@ -764,9 +777,9 @@
\setformulalistentry{#2}%
\next}
-\glet\namedformulaentry\relax % this will become a key/value so that we can do bookmarks
+\let\namedformulaentry\empty % \relax % this will become a key/value so that we can do bookmarks
-\def\setformulalistentry#1%
+\unexpanded\def\setformulalistentry#1%
{\gdef\namedformulaentry{#1}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-not.lua b/Master/texmf-dist/tex/context/base/strc-not.lua
index 07cd3249646..6a3f3bfad3d 100644
--- a/Master/texmf-dist/tex/context/base/strc-not.lua
+++ b/Master/texmf-dist/tex/context/base/strc-not.lua
@@ -10,7 +10,8 @@ local format = string.format
local next = next
local texcount = tex.count
-local trace_notes = false trackers.register("structures.notes", function(v) trace_notes = v end)
+local trace_notes = false trackers.register("structures.notes", function(v) trace_notes = v end)
+local trace_references = false trackers.register("structures.notes.references", function(v) trace_references = v end)
local report_notes = logs.reporter("structure","notes")
@@ -44,7 +45,9 @@ function notes.store(tag,n)
local nnd = #nd + 1
nd[nnd] = n
local state = notestates[tag]
- if state.kind ~= "insert" then
+ if not state then
+ report_notes("unknown state for %s",tag)
+ elseif state.kind ~= "insert" then
if trace_notes then
report_notes("storing %s with state %s as %s",tag,state.kind,nnd)
end
@@ -53,17 +56,19 @@ function notes.store(tag,n)
context(#nd)
end
-local function get(tag,n)
+local function get(tag,n) -- tricky ... only works when defined
local nd = notedata[tag]
if nd then
n = n or #nd
nd = nd[n]
if nd then
if trace_notes then
- report_notes("getting note %s of '%s'",n,tag)
+ report_notes("getting note %s of '%s' with listindex '%s'",n,tag,nd)
end
-- is this right?
- local newdata = lists.collected[nd]
+-- local newdata = lists.collected[nd]
+ local newdata = lists.cached[nd]
+-- local newdata = lists.tobesaved[nd]
return newdata
end
end
@@ -161,10 +166,11 @@ end
local function internal(tag,n)
local nd = get(tag,n)
if nd then
+-- inspect(nd)
local r = nd.references
if r then
local i = r.internal
---~ return i and lists.internals[i]
+-- return i and lists.internals[i]
return i and references.internals[i] -- dependency on references
end
end
@@ -210,33 +216,6 @@ function notes.checkpagechange(tag) -- called before increment !
end
end
-function notes.deltapage(tag,n)
- -- 0:unknown 1:textbefore, 2:textafter, 3:samepage
- local what = 0
- local li = internal(tag,n)
- if li then
- local metadata, pagenumber = li.metadata, li.pagenumber
- if metadata and pagenumber then
- local symbolpage = references.symbolpage or 0
- local notepage = pagenumber.number or 0
- if notepage > 0 and symbolpage > 0 then
- if notepage < symbolpage then
- what = 1
- elseif notepage > symbolpage then
- what = 2
- else
- what = 3
- end
- end
- else
- -- might be a note that is not flushed due to to deep
- -- nesting in a vbox
- what = 3
- end
- end
- context(what)
-end
-
function notes.postpone()
if trace_notes then
report_notes("postponing all insert notes")
@@ -252,34 +231,79 @@ function notes.setsymbolpage(tag,n,l)
local l = l or notes.listindex(tag,n)
if l then
local p = texcount.realpageno
- if trace_notes then
- report_notes("note %s of '%s' with list index %s gets page %s",n,tag,l,p)
+ if trace_notes or trace_references then
+ report_notes("note %s of '%s' with list index %s gets symbol page %s",n,tag,l,p)
+ end
+ local entry = lists.cached[l]
+ if entry then
+ entry.references.symbolpage = p
+ else
+ report_notes("internal error: note %s of '%s' is not flushed",n,tag)
end
- lists.cached[l].references.symbolpage = p
else
report_notes("internal error: note %s of '%s' is not initialized",n,tag)
end
end
+-- function notes.getsymbolpage(tag,n)
+-- local nd = get(tag,n)
+-- local p = nd and nd.references.symbolpage or 0
+-- if trace_notes or trace_references then
+-- report_notes("page number of note symbol %s of '%s' is %s",n,tag,p)
+-- end
+-- context(p)
+-- end
+
function notes.getsymbolpage(tag,n)
- local nd = get(tag,n)
- local p = nd and nd.references.symbolpage or 0
- if trace_notes then
- report_notes("page number of note symbol %s of '%s' is %s",n,tag,p)
+ local li = internal(tag,n)
+ li = li and li.references
+ li = li and (li.symbolpage or li.realpage) or 0
+ if trace_notes or trace_references then
+ report_notes("page number of note symbol %s of '%s' is %s",n,tag,li)
end
- context(p)
+ context(li)
end
function notes.getnumberpage(tag,n)
local li = internal(tag,n)
li = li and li.references
li = li and li.realpage or 0
- if trace_notes then
+ if trace_notes or trace_references then
report_notes("page number of note number %s of '%s' is %s",n,tag,li)
end
context(li)
end
+function notes.deltapage(tag,n)
+ -- 0:unknown 1:textbefore, 2:textafter, 3:samepage
+ local what = 0
+
+-- references.internals[lists.tobesaved[nd].internal]
+
+ local li = internal(tag,n)
+ if li then
+ local references = li.references
+ if references then
+ local symbolpage = references.symbolpage or 0
+ local notepage = references.realpage or 0
+ if trace_references then
+ report_notes("note number %s of '%s' points from page %s to page %s ",n,tag,symbolpage,notepage)
+ end
+ if notepage < symbolpage then
+ what = 3 -- after
+ elseif notepage > symbolpage then
+ what = 2 -- before
+ elseif notepage > 0 then
+ what = 1 -- same
+ end
+ else
+ -- might be a note that is not flushed due to to deep
+ -- nesting in a vbox
+ end
+ end
+ context(what)
+end
+
function notes.flush(tag,whatkind,how) -- store and postpone
local state = notestates[tag]
local kind = state.kind
@@ -357,12 +381,12 @@ function notes.resetpostponed()
end
end
-function notes.title(tag,n)
- lists.savedtitle(tag,notedata[tag][n])
+function commands.notetitle(tag,n)
+ command.savedlisttitle(tag,notedata[tag][n])
end
-function notes.number(tag,n,spec)
- lists.savedprefixednumber(tag,notedata[tag][n])
+function commands.noteprefixednumber(tag,n,spec)
+ commands.savedlistprefixednumber(tag,notedata[tag][n])
end
function notes.internalid(tag,n)
diff --git a/Master/texmf-dist/tex/context/base/strc-not.mkii b/Master/texmf-dist/tex/context/base/strc-not.mkii
index ec38410d483..bee21342ea7 100644
--- a/Master/texmf-dist/tex/context/base/strc-not.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-not.mkii
@@ -5,7 +5,7 @@
%D subtitle=Note Handling, % Footnote Handling
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-not.mkiv b/Master/texmf-dist/tex/context/base/strc-not.mkiv
deleted file mode 100644
index bf815c7281f..00000000000
--- a/Master/texmf-dist/tex/context/base/strc-not.mkiv
+++ /dev/null
@@ -1,1378 +0,0 @@
-%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 / Hans Hagen]
-%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}{1.001}
-
-\unprotect
-
-% this needs a further cleanup ...
-%
-% -- 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
-%D symbol {\setupfootnotes [conversion=set 2]\footnote
-%D {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
-%D reference they can be seen as a special kind of
-%D floating bodies. Their placement is postponed but has to be
-%D taken into account in the pagebreak calculations. This kind
-%D of calculations are forced by using \type{\insert}s and dealing
-%D 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
-%D to mess around with inserts at all. Take for instance a table
-%D of contents. And so we can 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 \everypagebody
-\appendtoks \notesenabledfalse \to \everystructurelist % quick hack
-
-%D Often we need to process the whole set of notes and to make that
-%D fast, we use a token register:
-
-\newtoks\tobeprocessednotes
-
-\unexpanded\def\processnotes#1% #1: \macro that uses \currentnote
- {\def\doprocesssomenote##1{\edef\currentnote{##1}\let\currentdescription\currentnote#1}%
- \the\tobeprocessednotes}
-
-%D Notes have their own paremater handlers. The complication here
-%D is that we use descriptions to typeset the note, so we have several
-%D resolvers.
-
-\let\currentnote\v!footnote
-
-\def\noteparameter #1{\csname\donoteparameter{\??vn\currentnote}#1\endcsname}
-\def\noteparameterhash#1{\donoteparameterhash {\??vn\currentnote}#1}
-
-\def\namednoteparameter#1#2{\csname\donoteparameter{\??vn#1}#2\endcsname}
-
-\def\donoteparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\donoteparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\donoteparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\donoteparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\donoteparentparameter #1#2{\ifx#1\relax\s!empty\else\donoteparameter #1#2\fi}
-\def\donoteparentparameterhash#1#2{\ifx#1\relax \else\donoteparameterhash#1#2\fi}
-
-\def\detokenizednoteparameter#1{\detokenize\expandafter\expandafter\expandafter{\csname\??vn#1\endcsname}}
-
-\def\dosetnoteattributes#1#2% style color
- {\edef\fontattributehash {\noteparameterhash#1}%
- \edef\colorattributehash{\noteparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-%D \macros
-%D {setupnote,setupnotedefinition}
-%D
-%D We can influence footnote typesetting with the setup
-%D command:
-%D
-%D \showsetup{setupnotes}
-%D \showsetup{setupnote}
-%D
-%D The definition command indicate that we can frame the footnote
-%D area. The footnotes themselves are treated as descriptions.
-%D
-%D \showsetup{definenote}
-%D
-%D It's sort of a custom to precede footnotes by a horizontal
-%D rule and although 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
-%D text width.
-
-\unexpanded\def\setupnotes
- {\dodoubleargument\getparameters[\??vn]}
-
-\setupnotes
- [\c!location=\v!page,
- \c!way=\v!by\v!part,
- %\c!conversion=,
- \c!rule=\v!on,
- \c!before=\blank,
- \c!bodyfont=\v!small,
- %\c!style=,
- %\c!color=,
- %\c!after=,
- %\c!rulecolor=,
- \c!rulethickness=\linewidth,
- \c!frame=\v!off,
- \c!margindistance=.5em,
- \c!columndistance=1em,
- \c!distance=.125em,
- \c!align=\v!normal,
- \c!tolerance=\v!tolerant,
- \c!split=\v!tolerant,
- %\c!width=\makeupwidth,
- %\c!width=\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi,
- \c!width=\defaultnotewidth,
- \c!height=\textheight,
- \c!numbercommand=\high,
- \c!command=, % \noteparameter\c!numbercommand, % (command in enumeration) too messy, called twice
- \c!separator=,% \@@koseparator,
- \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=\hskip1em,
- \c!n=1]
-
-\setupnotes
- [\c!expansion=\v!no,
- \c!xmlsetup=,
- \s!catcodes=,
- \c!saveinlist=\v!yes]
-
-\def\@@defaultnotedefloc{\v!inleft}
-\def\@@defaultnotedefdis{\!!zeropoint}
-
-\unexpanded\def\startnotedef{\resetdescriptions\csname\e!start\??vn\??vn\currentnote\endcsname}
-\unexpanded\def\stopnotedef {\csname\e!stop \??vn\??vn\currentnote\endcsname}
-
-\def\currentnoteins{\csname\??vn:\currentnote\endcsname}
-
-\newtoks \everysetupnote
-
-\unexpanded\def\definenote
- {\dotripleempty\dodefinenote}
-
-\def\dodefinenote[#1][#2][#3]% note [parent] [settings]
- {\edef\currentnote{#1}%
- \ifcsname\??vn:\currentnote\endcsname\else
- \@EA\installinsertion\csname\??vn:\currentnote\endcsname\relax
- \appendtoks\doprocesssomenote{#1}\to\tobeprocessednotes
- \fi
- \ifsecondargument
- \doifassignmentelse{#2}{\dodefinenotewithsettings{#2}}{\dodefinenotewithparent{#2}{#3}}%
- \else
- \dodefinenotesimple
- \fi
- \ctxlua{structures.notes.define("\currentnote","insert",\number\csname\??vn:\currentnote\endcsname)}%
- \the\everysetupnote
- \dochecknote}
-
-\def\dodefinenotesimple
- {\defineenumeration
- [\currentnote]
- [\s!handler=\v!note,
- \c!text=,
- \c!location=\@@defaultnotedefloc,
- \c!distance=\@@defaultnotedefdis,
- \c!width=\v!fit,
- \c!headstyle=\noteparameter\c!style,
- \c!headcolor=\noteparameter\c!color,
- \c!before=,
- \c!after=]%
- \doredefinenotecommands
- \presetlocalframed
- [\??vn\currentnote]%
- \setupenumerations
- [\currentnote]
- [\s!parent=\??vn\currentnote,
- \c!number=\v!yes]% no inheritance from decriptions which is okay
- \getparameters
- [\??vn\currentnote]
- [\s!parent=\??vn]}
-
-\def\dodefinenotewithsettings#1%
- {\defineenumeration % description
- [\currentnote]
- [\s!handler=\v!note,
- \c!text=,
- \c!location=\@@defaultnotedefloc,
- \c!distance=\@@defaultnotedefdis,
- \c!width=\v!fit,
- \c!headstyle=\noteparameter\c!style,
- \c!headcolor=\noteparameter\c!color,
- \c!before=,
- \c!after=]%
- \doredefinenotecommands
- \presetlocalframed
- [\??vn\currentnote]%
- \setupenumerations
- [\currentnote]
- [\s!parent=\??vn\currentnote,
- \c!number=\v!yes]%
- \getparameters
- [\??vn\currentnote]
- [\s!parent=\??vn,#1]}
-
-\def\dodefinenotewithparent#1#2%
- {%setevalue{\??vn:#2:kids}{\ifcsname\??vn:#2:kids\endcsname\csname\??vn:#2:kids\endcsname,\fi#1}%
- \defineenumeration
- [\currentnote]
- [\s!handler=\v!note,
- \c!text=]%
- \doredefinenotecommands
- \presetlocalframed
- [\??vn\currentnote]%
- \setupenumerations
- [\currentnote]
- [\s!parent=\??dd#1,
- \c!number=\v!yes]%
- \getparameters
- [\??vn\currentnote]
- [\s!parent=\??vn#1,#2]}
-
-% \starttext
-% text \startfootnote Test.\stopfootnote
-% test \footnote{xxxx} \subfootnote{xxxx}
-% test \footnote{xxxx} \subfootnote{xxxx}
-% \stoptext
-
-\def\dodoredefinenotecommands#1#2#3%
- {\unexpanded\expandafter\def\csname\e!start#3#1\expandafter\endcsname\expandafter
- {\expandafter\dosingleempty\csname\s!do\e!start#3#1\endcsname}%
- \unexpanded\expandafter\def\csname\s!do\e!start#3#1\expandafter\endcsname
- \expandafter[\expandafter##\expandafter1\expandafter]\expandafter##\expandafter2\csname\e!stop#3#1\endcsname
- {\begingroup
- \doenumerationinit{#1}{#2}{#3}%
- \@@notemakedescription[##1]{}{##2}%
- \expandafter\endgroup\noteparameter\c!next}} % WS: added \noteparameter\c!next
-
-\def\doredefinenotecommands
- {\normalexpanded{\noexpand\dodoredefinenotecommands{\currentnote}{1}{}}%
- \let\@@subslevel\empty
- \dostepwiserecurse{2}{\descriptionparameter\c!levels}{1}
- {\normalexpanded{\noexpand\dodoredefinenotecommands{\currentnote}{\recurselevel}{\@@subslevel\v!sub}}%
- \edef\@@subslevel{\@@subslevel\v!sub}}}
-
-\let\setupnotedefinition\setupenumerations
-
-% \def\dodowithcurrentnoteandkids#1#2% action kid
-% {\pushmacro\currentnote
-% \def\currentnote{#2}%
-% \dowithcurrentnoteandkids{#1}% recursive
-% \popmacro\currentnote}%
-
-\appendtoks
- \setupenumerations[\currentnote][]%
-\to \everysetupnote
-
-\unexpanded\def\setupnote
- {\dodoubleempty\dosetupnote}
-
-\def\dosetupnote[#1][#2]%
- {\edef\currentnote{#1}%
- \ifsecondargument
- \getparameters[\??vn\currentnote][#2]%
- \the\everysetupnote
- \fi
- \dochecknote}
-
-\appendtoks
- \setvalue{\??vn\c!rule:c:\currentnote}{\normalnoterule}% hm
- \letvalue{\??vn\c!rule:a:\currentnote}\v!left
-\to \everysetupnote
-
-\appendtoks
- \expanded{\processallactionsinset
- [\noteparameter\c!rule]}
- [ \v!on=>\setvalue{\??vn\c!rule:c:\currentnote}{\normalnoterule}, % no let as it can be changed afterwards
- \v!normal=>\setvalue{\??vn\c!rule:c:\currentnote}{\normalnoterule},
- \v!left=>\setvalue{\??vn\c!rule:a:\currentnote}{l2r},
- \v!right=>\setvalue{\??vn\c!rule:a:\currentnote}{r2l},
- \v!off=>\letvalue{\??vn\c!rule:c:\currentnote}\relax,
- \s!default=>\letvalue{\??vn\c!rule:c:\currentnote}\relax,
- \s!unknown=>\setvalue{\??vn\c!rule:c:\currentnote}{\noteparameter\c!rule}]%
-\to \everysetupnote
-
-\appendtoks
- \processaction % todo
- [\noteparameter\c!split]
- [ \v!tolerant=>\notepenalty\zeropoint,
- \v!strict=>\notepenalty9999,
- \v!verystrict=>\notepenalty\maxdimen,
- \s!default=>\notepenalty\zeropoint,
- \s!unknown=>\notepenalty\commalistelement]%
-\to \everysetupnote
-
-%D The following switch can be used to disable limiting the
-%D height of the footnote area, something that is needed in
-%D multi column balancing. Use this switch with care.
-
-\newif\ifnotelimit \notelimittrue % shared
-
-% bottomnotes endnotes
-% clevernotes
-
-\appendtoks
- \doifsomething{\noteparameter\c!factor}
- {\ifnum\noteparameter\c!factor<\zerocount\else
- \count\currentnoteins\noteparameter\c!factor
- \fi}%
-\to \everysetupnote
-
-% compatibility (will go away)
-
-\newif\ifbottomnotes % still used in page-one.mkiv
-%newif\endnotes % no longer used
-
-% locations:
-
-\def\s!noteloc{nodeloc} % 1=page 2=columns 3=lastcolumn 4=firstcolumn 5=none
-\def\s!notepos{nodepos} % 0=nothing 1=high 2=bottom
-\def\s!notefmt{nodefmt} % 1 text
-\def\s!notecol{nodecol}
-
-\def\clevernotes % compatibility hack, will be redone
- {\numexpr\ifcase\namednoteparameter\v!footnote\s!noteloc\or0\or2\or2\or1\else0\fi\relax}
-
-\def\setnotelocation #1{\expandafter\let\csname\??vn\currentnote\s!noteloc\endcsname#1\relax}
-\def\setnoteposition #1{\expandafter\let\csname\??vn\currentnote\s!notepos\endcsname#1\relax}
-\def\setnoteformatting#1{\expandafter\let\csname\??vn\currentnote\s!notefmt\endcsname#1\relax}
-
-\def\currentnofcolumns{\@@kln}
-
-\setvalue{\??vn @\v!page }{\setnotelocation\plusone}
-\setvalue{\??vn @\v!columns }{\setnotelocation\plustwo}
-\setvalue{\??vn @\v!lastcolumn }{\setnotelocation\plusthree}
-\setvalue{\??vn @\v!firstcolumn}{\setnotelocation\plusfour}
-\setvalue{\??vn @\v!none }{\setnotelocation\plusfive}
-\setvalue{\??vn @\v!text }{\setnotelocation\plusfive \setnoteformatting\plusone} % test
-\setvalue{\??vn @\v!high }{\setnoteposition\plusone}
-\setvalue{\??vn @\v!bottom }{\setnoteposition\plustwo}
-
-\def\dosetcheckednote#1{\csname\??vn @#1\endcsname}
-
-\newtoks\everychecknote
-
-\def\dochecknote
- {% node states
- \setnotelocation\plusone % page
- \setnoteposition\plustwo % high
- \normalexpanded{\rawprocesscommalist[\noteparameter\c!location]}\dosetcheckednote
- % compatibility hack
- %ifnum\noteparameter\s!noteloc=\plusfive \endnotestrue \else \endnotesfalse \fi
- \ifnum\noteparameter\s!notepos=\plustwo \bottomnotestrue \else \bottomnotesfalse \fi
- % set column multiplier
- \edef\currentnotenofcolumns{\noteparameter\c!n}%
- \ifx\currentnotenofcolumns\empty
- \let\currentnotenofcolumns\!!plusone
- \fi
- \ifcase\noteparameter\s!noteloc
- % can't happen
- \scratchcounter\plusone
- \or
- % page
- \scratchcounter \currentnotenofcolumns
- \or
- % columns
- \scratchcounter\ifnum\currentnofcolumns=\zerocount \plusone \else \currentnotenofcolumns \fi \relax
- \or
- % firstcolumn
- \scratchcounter\plusone
- \or
- % lastcolumn
- \scratchcounter\plusone
- \or
- % text
- \scratchcounter\currentnotenofcolumns
- \fi
- % column factor
- \ifcase\scratchcounter
- \scratchcounter\plusone
- \fi
- \global\count\currentnoteins\plusthousand
- \global\count\currentnoteins\numexpr\plusthousand/\scratchcounter\relax
- % maximize height
- \ifnotelimit
- \global\dimen\currentnoteins\dimexpr\noteparameter\c!height*\scratchcounter\relax
- \fi
- % distance -> tricky as this might depend on a font switch so we need a fast checker
- \dosetnotedistance
- % play safe
- \ifnum\noteparameter\s!noteloc=\plusfive
- \ctxlua{structures.notes.setstate("\currentnote","store")}%
- % text notes (e.g. end notes) but we don't use inserts anyway
- \global\dimen\currentnoteins\maxdimen
- \global\count\currentnoteins\zerocount
- \global\skip \currentnoteins\zeropoint
- \fi
- \the\everychecknote}
-
-\def\dosetnotedistance
- {\begingroup
- \setbox\scratchbox\vbox
- {\forgetall
-% \setnotebodyfont
- \dontcomplain
- \noteparameter\c!before
- \placenoterule
- \noteparameter\c!after}%
- \global\skip\currentnoteins\ht\scratchbox
- \endgroup}
-
-% \def\checknotes % no longer needed
-% {\processnotes\dochecknote}
-%
-% \def\checknotedistances
-% {\processnotes\dosetnotedistance}
-%
-% fails but not that much needed anyway:
-%
-% \appendtoks
-% \checknotedistances
-% \to \everyglobalbodyfont
-
-% D When \type{n} exceeds~1, footnotes are typeset in
-% D multi||columns, using the algoritm presented on page~397
-% D of \TEX book. Footnotes can be places on a per page basis
-% D or whereever suitable. When we set~\type{n} to~0, we get a
-% D rearanged paragraph, typeset by the algoritms on pages 398
-% D and~389 (at least in \MKII). We definitely did not reinvent
-% D that wheel.
-
-% 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
-%D setup macro at every skipswitch is tricky (many many MP
-%D runs). Let's just reserve a few points, that probably match
-%D those of the stretch component.
-
-%D A bit messy:
-
-\unexpanded\def\placenoterule
- {\bgroup
- \setupalign[\getvalue{\??vn\c!rule:a:\currentnote}]%
- \righttoleft
- \getvalue{\??vn\c!rule:c:\currentnote}%
- \par
- \egroup}
-
-\unexpanded\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}
-
-\ifx\setnotehsize\undefined
-
- \unexpanded\def\setnotehsize{\hsize\noteparameter\c!width\relax} % can be overloaded
-
-\fi
-
-%D The formatting depends on the width of the table, so we
-%D have to set \type {n} to 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
-%D therefore its formal specification looks like:
-%D
-%D \showsetup{footnote}
-%D
-%D This command has one optional command: the reference. By
-%D saying \type{[-]} the number is omitted. The footnote
-%D command is not that sensitive to spacing, so it's quite
-%D legal to say:
-%D
-%D \startbuffer
-%D Users of \CONTEXT\ must keep both feet \footnote{Given they
-%D have two.} on the ground and not get confused \footnote{Or
-%D even crazy.} by all those obscure \footnote{But fortunately
-%D 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
-%D when reshaping boxes.
-%D
-%D The additional macro \type {\footnotetext} and the
-%D associated \type {\note} macro were implemented at
-%D request of users on the mailing list and a suggestion by
-%D taco to split of the symbol placement. I decided to
-%D merge this functionality with the existing \type {\note}
-%D functionality.
-
-%D The next implementation runs on top of enumerations (only in \MKIV).
-%D
-%D \starttyping
-%D \setupenumerations
-%D [footnote]
-%D [ style=\type{(es)},
-%D headstyle=\type{(hs)}]
-%D
-%D \setupnote
-%D [footnote]
-%D [ style=\type{(s)},
-%D command=\type{(c)},
-%D textcommand=\type{(tc)},
-%D textstyle=\type{(ts)},
-%D numberstyle=\type{(ns)},
-%D numbercommand=\type{(nc)}]
-%D
-%D \setuplayout[backspace=6cm,marginwidth=cm,width=middle]
-%D
-%D \starttext
-%D \dorecurse{9}{This\footnote{Hello World #1} is a test.\par }
-%D \stoptext
-%D \stoptyping
-
-% TODO: \ifnotesenabled
-
-\newif\ifnotesymbol \notesymboltrue
-
-\newconditional\skipnoteplacement
-
-\unexpanded\def\setnote [#1]{\getvalue{#1}}
-\unexpanded\def\setnotetext[#1]{\global\settrue\skipnoteplacement\getvalue{#1}}
-
-\def\domovednote#1#2#3#4%
- {\ifcase\ctxlua{structures.notes.deltapage("#1",#2)}\or\symbol[#3]\or\symbol[#4]\fi}
-
-\setvalue{\??dd:\v!note:\s!handler:\s!text }{\@@donotetext}
-\setvalue{\??dd:\v!note:\s!handler:\s!number}{\@@donotenumber}
-\setvalue{\??dd:\v!note:\s!handler }{\@@donotehandler}
-\setvalue{\??dd:\v!note:\s!handler:\s!do }{\@@somenotedescription}
-\setvalue{\??dd:\v!note:\s!handler:\s!start }{\@@startsomenotedescription}
-
-\let\@@donotehandler\@@dodescriptionhandler
-
-\def\@@somenotedescription {\@@notemakedescription}
-\def\@@startsomenotedescription{\@@notemakedescription}
-
-\def\@@notemakedescription[#1]#2#3%
- {\ifnotesenabled
- \edef\currentdescriptionreference{#1}%
- \iftrialtypesetting
- \doenumerationcheckconditions
- \let\currentnote\currentdescriptionmain
- \typesetdummynotesymbol
- \else
- \begingroup
- \doenumerationcheckconditions
- \let\currentnote\currentdescriptionmain
- \dodescriptioncomponent[\c!reference=#1,\c!label={\descriptionparameter\c!text},\c!title={#3},\c!list=,\c!bookmark=,][]%
- \xdef\currentnotenumber{\ctxlua{structures.notes.store("\currentnote",\currentdescriptionnumberentry)}}%
- \settrue\processingnote
- \ifconditional\skipnoteplacement
- \globallet\lastnotesymbol\dolastnotesymbol
- \else
- \iftypesettinglines % otherwise problems with \type <crlf> {xxx}
- \ignorelines % makes footnotes work in \startlines ... \stoplines
- \fi
- \ifnotesymbol
- \dolastnotesymbol
- \else
- \unskip\unskip
- \globallet\lastnotesymbol\dolastnotesymbol
- \fi
- \fi
- \ifconditional\postponingnotes % todo: per note class
- \global\settrue\postponednote
- \else\ifconditional\inlocalnotes % todo: per note class
- \global\settrue\postponednote
- \else
- \handlenoteinsert\currentnote\currentnotenumber
- \fi\fi
- \endgroup
- \fi
- \fi
- \ifconditional\skipnoteplacement
- \global\setfalse\skipnoteplacement
- \else
- \kern\notesignal\relax % \relax is needed to honor spaces
- \fi}
-
-\def\dolastnotesymbol
- {\typesetsomenotesymbol\currentnote\currentnotenumber\currentdescriptionnumberentry}
-
-\let\dotagsetnotesymbol\relax
-
-\def\dotypesetsomenotesymbol#1#2#3% running text (messy: #1 and current mixed)
- {\dodonotesymbol
- {\synchronizesomenotesymbol{#1}{#2}{#3}%
-% \ctxlua{structures.notes.number("\currentnote",\currentnotenumber)}% \currentdescriptionnumberentry
- \dostarttagged\t!descriptionsymbol\currentnote
- \dotagsetnotesymbol
- \ctxlua{structures.notes.number("#1",#2)}%
- \dostoptagged
- \domovednote{#1}{#2}\v!previouspage\v!nextpage}}
-
-\unexpanded\def\typesetsomenotesymbol#1#2#3% running text
- {\removeunwantedspaces
- \doifitalicelse\/\donothing % Charles IV \footnote{the fourth}
- \ifdim\lastkern=\notesignal
- \dodonotesymbol{\kern\noteparameter\c!distance}% gets the font right, hack !
- \fi
- \nobreak
- \doifelse{\noteparameter\c!interaction}\v!no
- {\dotypesetsomenotesymbol{#1}{#2}{#3}}
- {\directgotobox{\dotypesetsomenotesymbol{#1}{#2}{#3}}[page(\ctxlua{structures.notes.getnumberpage("#1",\number#2)})]}% f:
- \globallet\lastnotesymbol\relax}
-
-\unexpanded\def\typesetdummynotesymbol % temp hack
- {\removeunwantedspaces
- \doifitalicelse\/\donothing % Charles IV \footnote{the fourth}
- \ifdim\lastkern=\notesignal
- \dodonotesymbol{\kern\noteparameter\c!distance}% gets the font right, hack !
- \fi
- \nobreak
- \hbox to .5em{}%
- \globallet\lastnotesymbol\relax}
-
-\def\currentnotedescriptiontext % todo: can be other number
- {\ctxlua{structures.notes.title("\currentnote",\currentdescriptionnumberentry)}}
-
-\def\@@donotetext
- {\ifconditional\enumerationnumberenabled
- \iftrialtypesetting
- \doenumerationfullnumber\showdntext
- \doenumerationcouplingsymbol
- \else
- \doenumerationregistercoupling
- \doenumerationfullnumber\showdntext
- \doenumerationcouplingsymbol
- \fi
- \else
- \doenumerationfullnumber\showdnpuretext
- \fi}
-
-% \def\currentnoteenumerationfullnumber
-\def\@@donotenumber
- {\doifelse{\noteparameter\c!interaction}\v!no
- {\docurrentnoteenumerationfullnumber}%
- {\directgotobox
- {\docurrentnoteenumerationfullnumber}%
- [page(\ctxlua{structures.notes.getsymbolpage("\currentnote",\currentdescriptionnumberentry)})]}}
-
-\def\docurrentnoteenumerationfullnumber
- {\noteparameter\c!numbercommand
- {\dosetnoteattributes\c!numberstyle\c!numbercolor
- \ctxlua{structures.notes.number("\currentnote",\currentdescriptionnumberentry)}%
- \domovednote\currentdescription\currentdescriptionnumberentry\v!nextpage\v!previouspage}}
-
-\def\synchronizesomenotesymbol#1#2#3% called more often than needed
- {\iftrialtypesetting\else
- \normalexpanded{\noexpand\ctxlatelua{structures.notes.setsymbolpage("#1",#2,#3)}}%
- \fi}
-
-\def\handlenoteinsert#1#2% tg, id
- {\begingroup
- \edef\currentnote{#1}%
- \the\everybeforenoteinsert
- \insert\currentnoteins\bgroup
- \the\everyinsidenoteinsert
- \doprocesslocalsetups{\noteparameter\c!setups}% experimental
- \doifelse{\noteparameter\c!paragraph}\v!yes
- {\nointerlineskip
- \startvboxtohbox
- \handlenoteitself{#1}{#2}%
- % add some slack
- \stopvboxtohbox}
- {\handlenoteitself{#1}{#2}}%
- \egroup
- \the\everyafternoteinsert
- \endgroup}
-
-\def\betweennoteitself#1% tg
- {\edef\currentnote{#1}%
- \doif{\noteparameter\c!paragraph}\v!yes\dobetweenparagraphnotes}
-
-\def\handlenoteitself#1#2% tg, id
- {\edef\currentdescription{#1}%
- \edef\currentnote{#1}%
- \edef\currentdescriptionnumberentry{#2}%
- \edef\currentdescriptionlistentry{\ctxlua{tex.write(structures.notes.listindex("#1",#2))}}%
- % as we can have collected notes (e.g. in tables) we need to recover
- % \currentdescriptionattribute and \currentdescriptionsynchronize
- \reinstatedescriptionnumberentry\currentdescriptionlistentry % we could store the number in the entry
- %
- \dontcomplain % should be done in startstoreddescription instead
- \dostartstoreddescription\begstrut\currentnotedescriptiontext\endstrut\dostopstoreddescription}
-
-\def\dostartstoreddescription
- {\bgroup\@@dostartdescriptionindeed}
-
-\def\dostopstoreddescription
- {\@@stopdescription}
-
-%D The main typesetting routine is more or less the same as the
-%D \PLAIN\ \TEX\ one, except that we only handle one type while
-%D \PLAIN\ also has something \type{\v...}. In most cases
-%D footnotes can be handled by a straight insert, but we do so
-%D by using an indirect call to the \type{\insert} primitive.
-
-%D Making footnote numbers active is not always that logical,
-%D especially when we keep the reference and text at one page.
-%D On the other hand we need interactivity when we refer to
-%D previous notes or use end notes. Therefore we support
-%D interactive footnote numbers in two ways \footnote{This
-%D feature was implemented years after we were able to do so,
-%D mainly because endnotes had to be supported.} that is,
-%D automatically (vise versa) and by user supplied reference.
-
-\let\startpushnote\relax
-\let\stoppushnote \relax
-
-\newsignal\notesignal
-\newcount \notepenalty
-
-\notepenalty=0 % needed in order to split in otrset
-
-\newconditional\processingnote
-\newconditional\postponednote
-
-\newtoks\everybeforenoteinsert
-\newtoks\everyinsidenoteinsert
-\newtoks\everyafternoteinsert
-
-\appendtoks
- \let\flushnotes\relax
- \let\postponenotes\relax
- \forgetall
- \resetallattributes % new, we don't want color bleed into notes
-\to \everybeforenoteinsert
-
-\appendtoks
- \doif{\noteparameter\c!scope}\v!page{\floatingpenalty\maxdimen}% experiment
- \penalty\notepenalty
- \forgetall
- \setnotebodyfont
- \redoconvertfont % to undo \undo calls in in headings etc
- \splittopskip\strutht % not actually needed here
- \splitmaxdepth\strutdp % not actually needed here
- \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
-\to \everyinsidenoteinsert
-
-% not: \appendtoks \setnotehsize \to \everyinsidenoteinsert (spoils columns)
-
-\let\lastnotesymbol\relax
-
-%D \macros
-%D {note}
-%D
-%D Refering to a note is accomplished by the rather short
-%D command:
-%D
-%D \showsetup{note}
-%D
-%D This command is implemented rather straightforward as:
-
-\unexpanded\def\notesymbol
- {\dodoubleempty\donotesymbol}
-
-\def\donotesymbol[#1][#2]%
- {\bgroup
- \ifnotesenabled
- \edef\currentnote{#1}%
- \ifsecondargument
- \unskip
- \dodonotesymbol{\in[#2]}%
- \else
- \dodonotesymbol\lastnotesymbol
- \fi
- \fi
- \egroup}
-
-\def\dodonotesymbol#1%
- {\noteparameter\c!textcommand{\dosetnoteattributes\c!textstyle\c!textcolor#1}}
-
-%D Normally footnotes are saved as inserts that are called upon
-%D as soon as the pagebody is constructed. The footnote
-%D insertion routine looks just like the \PLAIN\ \TEX\ one,
-%D 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}}
-
-\unexpanded\def\placenoteinserts
- {\processnotes\doplacenoteinserts}
-
-\unexpanded\def\unvboxed {\ifvmode\unvbox \else\box \fi}
-\unexpanded\def\unvcopied{\ifvmode\unvcopy\else\copy\fi}
-
-% idea: tag with attr and then just flush them again
-
-\def\dobetweenparagraphnotes % should not be too much
- {\noteparameter\c!inbetween}
-
-\def\doflushgobalnotes
- {\doifelse{\noteparameter\c!paragraph}\v!yes
- {\vbox
- {\beginofshapebox
- \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins
- \endofshapebox
- %\doreshapebox{\box\shapebox}{}{}{}% get rid of penalties etc
- \gdef\dodobetweenparagraphnotes{\glet\dodobetweenparagraphnotes\dobetweenparagraphnotes}% shape works reverse
- \doreshapebox{\hbox{\unhbox\shapebox\dodobetweenparagraphnotes}}{}{}{}% get rid of penalties etc
- \innerflushshapebox
- \convertvboxtohbox}}
- {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins}}
-
-\def\dodoplacenoteinserts
- {\ifcase\noteparameter\c!n\relax
- % should not happen
- \or
- \doglobalflushnotesnormal
- \else
- \doglobalflushnotescolums
- \fi}
-
-\def\doglobalflushnotesnormal
- {%\iftrialtypesetting\copy\else\box\fi\currentnoteins
- \doflushgobalnotes
- \obeydepth} % (a) added , since split footnotes will not align properly
-
-\def\doglobalflushnotescolums
- {\edef\currentnotewidth{\noteparameter\c!width}%
- \doifdimensionelse\currentnotewidth\donothing
- {\edef\currentnotewidth{\the\hsize}}%
- \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]%
- %\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins % compare with local
- \doflushgobalnotes
- \stopsimplecolumns}
-
-\def\doplacenoteinserts
- {\relax\ifdim\ht\currentnoteins>\zeropoint\relax
- \ifnum\noteparameter\s!noteloc=\plusfive
- \else
- \endgraf
- \ifvmode
- \whitespace
- \noteparameter\c!before
- \fi
- % \bgroup
- % \setupalign[\noteparameter\c!align]%
- \placenoterule % alleen in ..mode
- % \par
- % \egroup
- \bgroup
- \setnotebodyfont
- \setbox\scratchbox\hbox
- {\dodoplacenoteinserts}%
- \setbox\scratchbox\hbox
- {\localframed
- [\??vn\currentnote]
- [\c!width=\v!fit,
- \c!height=\v!fit,
- \c!strut=\v!no,
- \c!offset=\v!overlay]
- {\ifdim\dp\scratchbox=\zeropoint % this hack is needed because \vadjust
- \hbox{\lower\strutdp\box\scratchbox}% % in margin number placement
- \else % hides the (always) present depth
- \box\scratchbox
- \fi}}%
- \setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}%
- \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth
- \box\scratchbox
- \egroup
- \endgraf
- \ifvmode
- \noteparameter\c!after
- \fi
- \fi
- \fi}
-
-%D Supporting end notes is surprisingly easy. Even better, we
-%D can combine this feature with solving the common \TEX\
-%D problem of disappearing inserts when they're called for in
-%D 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
-%D etc. The latter one sometimes calls for notes local to
-%D 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)
-%D insert operation. A not too robust method uses the
-%D \type{\insert} primitive when possible. This method fails in
-%D situations where it's not entirely clear in what mode \TEX\
-%D is. Therefore the auto method can is to be overruled when
-%D needed.
-
-\newconditional\postponingnotes
-
-% we need a proper state: normal, postponing, flushing
-
-\def\postponenotes
- {\ifconditional\postponingnotes\else
- \global\settrue\postponingnotes
- \global\let\flushnotes\doflushnotes
- \ctxlua{structures.notes.postpone()}%
- \fi}
-
-\let\flushnotes\relax
-
-\def\doflushnotes
- {\ifconditional\postponingnotes
- \begingroup
- \let\flushnotes \relax
- \let\postponenotes\relax
- \ctxlua{structures.notes.flushpostponed()}% this also resets the states !
- \global\setfalse\postponednote
- \global\setfalse\postponingnotes
- \global\let\flushnotes\relax
- \endgroup
- \fi}
-
-%D \macros
-%D {startlocalfootnotes,placelocalfootnotes}
-%D
-%D The next two macros can be used in for instance tables, as
-%D we'll demonstrate later on.
-%D
-%D \showsetup{startlocalfootnotes}
-%D \showsetup{placelocalfootnotes}
-
-% todo: compatibility mode: when first arg is assignment or missing, then all
-
-\newtoks\everyplacelocalnotes
-
-\appendtoks
- \let\flushnotes \relax
- \let\postponenotes\relax
-\to \everyplacelocalnotes
-
-\def\defaultnotewidth{\makeupwidth} % {\ifdim\hsize<\makeupwidth\hsize\else\makeupwidth\fi}
-
-\newconditional\inlocalnotes
-
-\unexpanded\def\startlocalnotes
- {\dosingleempty\dostartlocalnotes}
-
-\def\dostartlocalnotes[#1]%
- {\def\localnoteslist{#1}%
- \settrue\inlocalnotes
- \processcommacommand[\localnoteslist]\dodostartlocalnotes}
-
-\unexpanded\def\stoplocalnotes
- {\processcommacommand[\localnoteslist]\dodostoplocalnotes
- \setfalse\inlocalnotes}
-
-\def\dodostartlocalnotes#1%
- {\doifnot{\noteparameter\c!continue}\v!yes
- {\savestructurecounter[#1]%
- \resetstructurecounter[#1]}%
- \ctxlua{structures.notes.save("#1","store")}}
-
-\def\dodostoplocalnotes#1%
- {\doifnot{\noteparameter\c!continue}\v!yes
- {\restorestructurecounter[#1]}%
- \ctxlua{structures.notes.restore("#1")}}
-
-\unexpanded\def\placelocalnotes
- {\dodoubleempty\doplacelocalnotes}
-
-\def\doplacelocalnotes[#1][#2]%
- {\doif{\ctxlua{structures.notes.getstate("#1")}}{store}{\dodoplacelocalnotes{#2}{#1}}}
-
-\def\dodoplacelocalnotes#1#2% settings note
- {\begingroup
- \the\everyplacelocalnotes
- % beware, we cannot trust setting \currentnote here
- \getparameters[\??vn#2][\c!width=\v!fit,\c!height=\v!fit,\c!strut=\v!no,\c!offset=\v!overlay,#1]% we only need a selective one
- \dolocalnotealternative{#2}%
- \endgroup
- \dochecknote} % we need to restore the old state
-
-%D These commands can be used like:
-%D
-%D \startbuffer
-%D \startlocalnotes[width=.3\hsize,n=0]
-%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 {\placelocalnotes}
-%D \stoplocalnotes
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D Because this table placement macro expect box content, and
-%D thanks to the grouping of the local footnotes, we don't need
-%D additional braces.
-%D
-%D \getbuffer
-
-%D \macros
-%D {placefootnotes}
-%D
-%D We still have no decent command for placing footnotes
-%D somewhere else than at the bottom of the page (for which no
-%D user action is needed). Footnotes (endnotes) can be
-%D placed by using
-%D
-%D \showsetup{placefootnotes}
-
-\unexpanded\def\placebottomnotes
- {\processnotes\placenoteinserts}
-
-\unexpanded\def\placenotes
- {\dodoubleempty\doplacenotes}
-
-\def\doplacenotes[#1][#2]%
- {\processcommalist[#1]{\dodoplacenotes{#2}}}
-
-\def\dodoplacenotes#1#2% settings note
- {\edef\currentnote{#2}%
- \doifelse{\ctxlua{structures.notes.getstate("#2")}}{store}
- \dodoplacelocalnotes
- \dodoplaceglobalnotes
- {#1}{#2}}
-
-\def\dodoplaceglobalnotes#1#2%
- {\begingroup
- \setupnote[#2][#1]%
- \doplacenoteinserts
- \endgroup
- \the\everysetupnote} % to be checkes
-
-%D Placement
-
-\long\def\installnotealternative#1#2%
- {\setvalue{\??vn:\c!alternative:#1}{#2}}
-
-\def\doifnotescollected#1%
- {\ctxlua{structures.notes.doifcontent("#1")}}
-
-\def\dolocalnotealternative#1%
- {\edef\currentnote{#1}%
- \doifnotescollected\currentnote
- {\endgraf
- \ifvmode
- \whitespace
- \noteparameter\c!before
- \fi
- \begingroup
- \setnotebodyfont
- \getvalue{\??vn:\c!alternative:\noteparameter\c!alternative}%
- \endgroup
- \ifvmode
- \noteparameter\c!after
- \fi}}
-
-\setvalue{\??vn:\c!alternative:}{\getvalue{\??vn:\c!alternative:\v!none}}
-
-%D A stupid alternative is also provided:
-%D
-%D \starttyping
-%D \setupfootnotes[location=text,alternative=none]
-%D \stoptyping
-
-% \def\flushlocalnotes#1{\ctxlua{structures.notes.flush("#1","store")}}
-\def\flushlocalnotes#1{\ctxlua{structures.notes.flush("#1","store","\noteparameter\c!criterium")}}
-
-\installnotealternative \v!none
- {\flushlocalnotes\currentnote}
-
-\installnotealternative \v!grid % test if n > 0
- {\snaptogrid\hbox
- {\localframed
- [\??vn\currentnote]
- {\flushlocalnotes\currentnote}}}
-
-\installnotealternative \v!fixed % test if n > 0
- {\localframed
- [\??vn\currentnote]
- {\flushlocalnotes\currentnote}}
-
-\installnotealternative \v!columns % redundant
- {\localframed
- [\??vn\currentnote]
- {\edef\currentnotewidth{\noteparameter\c!width}%
- \doifdimensionelse\currentnotewidth\donothing
- {\edef\currentnotewidth{\the\hsize}}%
-% \setupinmargin[\c!align=\v!left]%
- \startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\currentnotewidth]%
- \flushlocalnotes\currentnote
- \stopsimplecolumns}}
-
-%D \macros
-%D {fakenotes}
-
- % is this ok? endnotes and such
-
- \unexpanded\def\fakenotes
- {\ifhmode\endgraf\fi\ifvmode
- \calculatetotalclevernoteheight
- \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
- \fi}
-
- \unexpanded\def\fakepagenotes
- {\ifhmode\endgraf\fi\ifvmode
- \calculatetotalpagenoteheight
- \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
- \fi}
-
- \newdimen\totalnoteheight
-
- \def\doaddtototalnoteheight#1%
- {\ifdim\ht#1>\zeropoint
- \ifcase\count#1\else
- % todo: divide by count
- \advance\totalnoteheight\ht #1%
- \advance\totalnoteheight\skip#1%
- \fi
- \fi}
-
- \def\docalculatetotalnoteheight
- {\ifcase\clevernotes % tricky here ! ! ! to be sorted out ! ! !
- \doaddtototalnoteheight\currentnoteins
- \else
-% \doaddtototalnoteheight\currentbackupnoteins
- \fi}
-
- \def\docalculatetotalclevernoteheight
- {\ifcase\clevernotes \else % tricky here ! ! ! to be sorted out ! ! !
- \doaddtototalnoteheight\currentnoteins
- \fi}
-
- \def\docalculatetotalpagenoteheight
- {\doaddtototalnoteheight\currentnoteins}
-
- \def\calculatetotalnoteheight {\totalnoteheight\zeropoint\processnotes\docalculatetotalnoteheight}
- \def\calculatetotalclevernoteheight{\totalnoteheight\zeropoint\processnotes\docalculatetotalclevernoteheight}
- \def\calculatetotalpagenoteheight {\totalnoteheight\zeropoint\processnotes\docalculatetotalpagenoteheight}
-
- \newif\ifnotespresent
-
- \def\dochecknotepresence
- {\ifdim\ht\currentnoteins>\zeropoint
- \notespresenttrue
- \fi}
-
- \def\checknotepresence
- {\notespresentfalse
- \processnotes\dochecknotepresence}
-
-%D Now how can this mechanism be hooked into \CONTEXT\ without
-%D explictly postponing footnotes? The solution turned out to
-%D be rather simple:
-%D
-%D \starttyping
-%D \everypar {...\flushnotes...}
-%D \neverypar {...\postponenotes}
-%D \stoptyping
-%D
-%D and
-%D
-%D \starttyping
-%D \def\ejectinsert%
-%D {...
-%D \flushnotes
-%D ...}
-%D \stoptyping
-%D
-%D We can use \type{\neverypar} because in most commands
-%D sensitive to footnote gobbling we disable \type{\everypar}
-%D in favor for \type{\neverypar}. In fact, this footnote
-%D implementation is the first to use this scheme.
-
-%D This is a nasty and new secondary footnote flusher. It
-%D can be hooked into \type {\everypar} like:
-%D
-%D \starttyping
-%D \appendtoks \synchronizenotes \to \everypar
-%D \stoptyping
-
- % \def\dosynchronizenotes
- % {\ifvoid\currentnoteins\else\insert\currentnoteins{\unvbox\currentnoteins}\fi}
- %
- % \def\synchronizenotes
- % {\processnotes\dosynchronizenotes}
-
-\let\synchronizenotes\relax
-
-%D When typesetting footnotes, we have to return to the
-%D footnote specific bodyfont size, which is in most cases derived
-%D from the global document bodyfont size. In the previous macros
-%D we already used a footnote specific font setting macro.
-
-\def\setnotebodyfont
- {\let\setnotebodyfont\relax
- \restoreglobalbodyfont
- \switchtobodyfont[\noteparameter\c!bodyfont]%
- \setuptolerance[\noteparameter\c!tolerance]%
- \setupalign[\noteparameter\c!align]}
-
-%D The footnote mechanism defaults to a traditional one
-%D column way of showing them. By default we precede them by
-%D a small line.
-
-\ifx\v!endnote\undefined \def\v!endnote{endnote} \fi
-
-\definenote [\v!footnote]
-\definenote [\v!endnote ] [\c!location=\v!none] % else no break
-
-%D Compatibility macros:
-
-\unexpanded\def\setupfootnotedefinition{\setupnotedefinition [\v!footnote]}
-\unexpanded\def\setupfootnotes {\setupnote [\v!footnote]}
-%unexpanded\def\footnote {\setnote [\v!footnote]}
-\def\footnotetext {\setnotetext [\v!footnote]}
-%unexpanded\def\note {\dodoubleempty\notesymbol [\v!footnote]} % alleen footnote
-\unexpanded\def\placefootnotes {\dodoubleempty\doplacefootnotes [\v!footnote]}
-\unexpanded\def\placelocalfootnotes {\dodoubleempty\doplacelocalfootnotes[\v!footnote]}
-\unexpanded\def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote
-\unexpanded\def\stoplocalfootnotes {\stoplocalnotes }
-
-\def\doplacefootnotes [#1][#2]{\ifsecondargument\placenotes [#1][#2,\c!height=\textheight]\else\placenotes [#1]\fi}
-\def\doplacelocalfootnotes[#1][#2]{\ifsecondargument\placelocalnotes[#1][#2,\c!height=\textheight]\else\placelocalnotes[#1]\fi}
-
-\unexpanded\def\note{\dodoubleempty\donote}
-
-\def\donote[#1][#2]{\ifsecondargument\donotesymbol[#1][#2]\else\secondargumenttrue\donotesymbol[\v!footnote][#1]\fi}
-
-%D Goodies:
-%D
-%D \starttyping
-%D \dorecurse {100} {
-%D test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}}
-%D }
-%D \stoptyping
-
-\def\doifnoteonsamepageelse[#1]{\ctxlua{structures.notes.doifonsamepageasprevious("#1")}}
-
-%D New trickery:
-
-\def\ownnotesymbol#1% #1 gets number passed
- {\executeifdefined{\??vn::\currentnote}\empty}
-
-\unexpanded\def\setnotesymbol[#1]#2#3%
- {\prewordbreak % prevent lookback
- \setgvalue{\??vn::#1}{#3}
- \dolastnotesymbol}
-
-\unexpanded\def\ownnote[#1]#2#3#4%
- {\setnotesymbol[#1]{#2}{#3}%
- \setnotetext [#1]{#4}}
-
-\defineconversion
- [ownnote]
- [\ownnotesymbol]
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-not.mkvi b/Master/texmf-dist/tex/context/base/strc-not.mkvi
new file mode 100644
index 00000000000..5f1f041e35e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-not.mkvi
@@ -0,0 +1,1727 @@
+%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}{1.001}
+
+\unprotect
+
+% todo: more p_strc_notations_* (outside trial loop)
+
+% todo: see if we can now use \insertpenalties (>0 == some left)
+
+\ifdefined\v!notation \else \def\v!notation {notation} \fi
+\ifdefined\v!endnote \else \def\v!endnote {endnote} \fi
+\ifdefined\c!symbolcommand \else \def\c!symbolcommand{symbolcommand} \fi
+
+\ifdefined\dotagsetnotesymbol \else \let\dotagsetnotesymbol\relax \fi
+
+\unexpanded\def\unvboxed {\ifvmode\unvbox \else\box \fi} % will change or used more often
+\unexpanded\def\unvcopied{\ifvmode\unvcopy\else\copy\fi} % will change or used more often
+
+%D Notes have two handlers: notations and notes. Although notations can
+%D be defined independently it makes not much sense. In principle we can
+%D treat notes as lists but they are currently done as a variant on
+%D enumerations. I will provide a list variant as well. One complication is
+%D that for page related notes inserts are used and therefore notes are
+%D typeset immediately and descriptions are better suited for that. For
+%D 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,setupnotedefinition}
+%D
+%D We can influence footnote typesetting with the setup
+%D command:
+%D
+%D \showsetup{setupnotes}
+%D \showsetup{setupnote}
+%D
+%D The definition command indicate that we can frame the footnote
+%D area. The footnotes themselves are treated as descriptions.
+%D
+%D \showsetup{definenote}
+%D
+%D It's sort of a custom to precede footnotes by a horizontal
+%D rule and although 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
+%D text width.
+
+% \c!headstyle=\noteparameter\c!style,
+% \c!headcolor=\noteparameter\c!color,
+
+\installcorenamespace{notation}
+
+\installcommandhandler \??notation {notation} \??notation
+
+\let\setupnotations\setupnotation
+
+% \unexpanded\def\lowllap#1{\low{\llap{#1}}}
+
+\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]
+
+% mostly the same as enumersations but we want to keep them
+% isolated and at some point we might differentiate
+
+% to be considered:
+%
+% \let\??construction\??notation
+%
+% with push/pop (also at definition time)
+
+\unexpanded\def\strc_define_commands_notation#1#2#3% current level parent
+ {\doifelsenothing{#3}
+ {\normalexpanded{\defineconstruction[#1][\s!handler=\v!notation,\c!level=#2]}%
+ \setevalue{\??notation#1:\s!parent}{\??notation}}%
+ {\normalexpanded{\defineconstruction[#1][#3][\s!handler=\v!notation,\c!level=#2]}%
+ \setevalue{\??notation#1:\s!parent}{\??notation#3}}%
+ \setuevalue{\e!next #1}{\strc_notations_next }%
+ \setuevalue{\c!reset#1}{\strc_notations_reset }%
+ %setuevalue{\c!set #1}{\strc_notations_set }%
+% \setuevalue {#1}{\strc_notations_command{\currentnotation}}%
+% \setuevalue{\e!start#1}{\strc_notations_start {\currentnotation}{#1}}%
+ \setuevalue {#1}{\strc_notations_command{#1}}%
+ \setuevalue{\e!start#1}{\strc_notations_start {#1}{#1}}% okay?
+ \setuevalue{\e!stop #1}{\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
+% \doifcounterelse\p_counter\donothing{\strc_enumerations_define_counter\p_counter}%
+% \letnotationparameter\s!counter\p_counter
+% \strc_enumerations_setup_counter\currentnotation
+ \doifcounterelse\p_counter\donothing{\strc_notes_define_counter\p_counter}%
+ \letnotationparameter\s!counter\p_counter
+ \strc_notes_setup_counter\currentnotation
+\to \everydefinenotation
+
+\setvalue{\??constructioninitializer\v!notation}%
+ {\let\currentnotation \currentconstruction
+ \let\constructionparameter \notationparameter
+ \let\detokenizedconstructionparameter\detokenizednotationparameter
+ \let\letconstructionparameter \letnotationparameter
+ \let\useconstructionstyleandcolor \usenotationstyleandcolor
+ \let\setupcurrentconstruction \setupcurrentnotation
+ \edef\p_number{\constructionparameter\c!number}%
+ \ifx\p_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_title{\constructionparameter\c!title}%
+ \ifx\p_title\v!yes
+ \settrue\c_strc_constructions_title_state
+ \else
+ \setfalse\c_strc_constructions_title_state
+ \fi}
+
+\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
+%D and sounds like description and enumeration) are a special case
+%D in the sense that they are stored, rendered elsewhere and referered
+%D to from where they are specified. For that reason they have a different
+%D set op main commands.
+
+% \notation[ref]{title}
+% \notation[reference=,title=]
+% \startnotation[ref] title \stopnotation
+
+\let\strc_notations_next \strc_enumerations_next
+\let\strc_notations_reset\strc_enumerations_reset
+%let\strc_notations_set \strc_enumerations_set
+
+\unexpanded\def\strc_notations_command#1%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \doifnextoptionalelse\strc_notations_command_yes\strc_notations_command_nop}
+
+\unexpanded\def\strc_notations_command_nop#1%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \endgroup}
+
+\unexpanded\def\strc_notations_command_yes[#1]%
+ {\doifassignmentelse{#1}\strc_notations_command_assignment\strc_notations_command_argument[#1]}
+
+\unexpanded\def\strc_notations_command_assignment[#1]%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title=,\c!bookmark=,\c!list=,#1][]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \endgroup}
+
+\unexpanded\def\strc_notations_command_argument[#1]#2%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=][]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \endgroup}
+
+\unexpanded\def\strc_notations_start#1#2%
+ {\begingroup
+ \strc_constructions_initialize{#1}%
+ \strc_counters_increment_sub\currentconstructionnumber\currentconstructionlevel
+ \normalexpanded % not that efficient but also not that frequently used
+ {\def\noexpand\strc_pickup_yes[##1]##2\csname\e!stop#2\endcsname{\strc_notations_command_yes[##1]{##2}}%
+ \def\noexpand\strc_pickup_nop ##1\csname\e!stop#2\endcsname{\strc_notations_command_nop {##1}}}%
+ \doifnextoptionalelse\strc_pickup_yes\strc_pickup_nop}
+
+\unexpanded\def\strc_notations_start_yes[#1]#2%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference={#1},\c!title={#2},\c!bookmark=,\c!list=][]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \endgroup}
+
+\unexpanded\def\strc_notations_start_nop#1%
+ {\strc_constructions_register[\c!label={\descriptionparameter\c!text},\c!reference=,\c!title={#1},\c!bookmark=,\c!list=][]%
+ \csname\??constructionnotehandler\currentconstructionhandler\endcsname
+ \strc_constructions_finalize
+ \endgroup}
+
+\unexpanded\def\strc_notations_stop
+ {}
+
+%D A complication is that we need to set up rather specific properties
+%D of e.g. footnotes. It is for this reason that we introduce an extra
+%D level of indirectness. This way notations don't bark on undefined
+%D macros when used in combination.
+
+\setvalue{\??constructionnotehandler\v!notation}%
+ {\csname\??constructionnotehandler\currentconstructionhandler:\constructionparameter\c!type\endcsname}
+
+\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
+ \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!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}
+
+\def\currentnoteins{\csname\??noteinsertion\currentnote\endcsname}
+
+\appendtoks
+ \ifcsname\??noteinsertion\currentnote\endcsname\else
+ \expandafter\installinsertion\csname\??noteinsertion\currentnote\endcsname\relax
+ \normalexpanded{\t_strc_notes{\the\t_strc_notes\noexpand\strc_notes_process_list{\currentnote}}}%
+ \fi
+ \ctxlua{structures.notes.define("\currentnote","insert",\number\currentnoteins)}%
+ \ifx\currentnoteparent\empty
+ \definenotation[\currentnote][\c!type=\v!note]%
+ \else
+ \definenotation[\currentnote][\currentnoteparent][\c!type=\v!note]%
+ \fi
+\to \everydefinenote
+
+% maybe we will share this at some point
+
+%%%%%%%%%%% BEGIN TODO (SEE ENUMERATIONS) %%%%%%%%%%%%%%%
+
+\newtoks\everysetupnotecounter
+
+\let\v_strc_note_counter_name\empty
+
+\def\strc_notes_setup_counter#1%
+ {\edef\v_strc_note_counter_name{#1}% only used in the token list
+ \the\everysetupnotecounter}
+
+\def\strc_notes_define_counter#1% todo: fast inheritance (was mainparameter
+ {\definecounter[#1]%
+ \strc_notes_setup_counter{#1}}
+
+\appendtoks
+ \strc_counter_setup_using_parameter\v_strc_note_counter_name\notationparameter
+\to \everysetupnotecounter
+
+\appendtoks
+ \strc_notes_setup_counter\currentnotation
+\to \everysetupnotation
+
+%%%%%%%%%%% END TODO (SEE ENUMERATIONS) %%%%%%%%%%%%%%%
+
+% \setvalue{\??constructionstarthandler\v!notation}%
+% {\csname\??constructionstarthandler\v!construction\endcsname}
+
+%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
+
+\setvalue{\??constructionmainhandler\v!notation}#1%
+ {\iftrialtypesetting \else
+ \begingroup
+ \currentconstructionsynchronize
+ \attribute\destinationattribute\currentconstructionattribute\relax % todo, whole text
+ \signalcharacter
+ \endgroup
+ \fi#1}
+
+\setvalue{\??constructionnotehandler\v!notation:\v!note}% in the running text
+ {\ifnotesenabled
+ \let\currentnote\currentconstructionmain % do be done elsewhere
+ \iftrialtypesetting
+ \strc_notes_inject_dummy
+ \else
+ \begingroup
+ \edef\currentnotenumber{\ctxlua{structures.notes.store("\currentnote",\currentconstructionlistentry)}}%
+ \settrue\processingnote
+ \ifconditional\c_strc_notes_skip
+ \globallet\lastnotesymbol\strc_notes_inject_symbol
+ \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
+ \else
+ \unskip\unskip
+ \globallet\lastnotesymbol\strc_notes_inject_symbol
+ \fi
+ \fi
+ \ifconditional\postponingnotes % todo: per note class
+ \global\settrue\postponednote
+ \else\ifconditional\inlocalnotes % todo: per note class
+ \global\settrue\postponednote
+ \else
+ \handlenoteinsert\currentnote\currentnotenumber % either an insert or just delayed
+ \fi\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
+%D flushed. In principle it is more or less the same as lists but where
+%D in lists we pack whole entries, in notes this doesn't happen. Okay,
+%D in retrospect we could have made descriptions lists but that will be
+%D a backward compatibility mess. At some point a completely new mechanism
+%D might show up, but not now. Also, as notes are inserts there is some
+%D extra mess to be kept in mind and it's easier to maintain two mechanisms
+%D than to combine too much.
+%D
+%D Interaction is also complicated because we want to provide several variants.
+%D For simple reference there is no need for anything special, as page references
+%D will 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
+%D one 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
+
+\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}
+
+\setvalue{\??noteinteractioninline\v!yes}%
+ {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getnumberpage("\currentnote",\currentnotenumber)})}%
+ \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}%
+ \let \strc_notes_set_style_color_inline \strc_notes_set_style_color_inline_yes}
+
+\setvalue{\??noteinteractioninline\v!all}%
+ {%\strc_references_get_simple_page_reference{note:\cldcontext{structures.notes.internalid("\currentnote",\currentnotenumber)}}%
+ \strc_references_get_simple_page_reference{note:\currentnote:\currentnotenumber}%
+ \edef\strc_notes_get_reference_attribute_symbol{attr\referenceattribute\currentreferenceattribute}%
+ \let \strc_notes_set_style_color_inline \strc_notes_set_style_color_inline_yes}
+
+\setvalue{\??noteinteractioninline\v!no}%
+ {\let\strc_notes_get_reference_attribute_symbol\empty
+ \let\strc_notes_set_style_color_inline \strc_notes_set_style_color_inline_nop}
+
+\expandafter\let\csname\??noteinteractioninline\v!number\expandafter\endcsname\csname\??noteinteractioninline\v!yes\endcsname
+\expandafter\let\csname\??noteinteractioninline\v!text \expandafter\endcsname\csname\??noteinteractioninline\v!yes\endcsname
+
+\setvalue{\??noteinteractiondisplay\v!yes}%
+ {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getsymbolpage("\currentnote",\currentnotenumber)})}%
+ \edef\strc_notes_set_reference_attribute_number{\attribute\referenceattribute\currentreferenceattribute}%
+ \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_yes}
+
+\setvalue{\??noteinteractiondisplay\v!no}%
+ {\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}
+
+\setvalue{\??noteinteractiondisplay\v!all}%
+ {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getsymbolpage("\currentnote",\currentnotenumber)})}%
+ \edef\strc_notes_set_reference_attribute_text {\attribute\referenceattribute\currentreferenceattribute}%
+ %\strc_references_set_simple_page_reference{note:\cldcontext{structures.notes.internalid("\currentnote",\currentnotenumber)}}%
+ \strc_references_set_simple_page_reference{note:\currentnote:\currentnotenumber}%
+ \edef\strc_notes_set_destination_attribute_text{\attribute\destinationattribute\currentdestinationattribute}%
+ \let \strc_notes_set_reference_attribute_number\strc_notes_set_reference_attribute_text
+ \let \strc_notes_set_style_color_display \strc_notes_set_style_color_display_yes}
+
+\setvalue{\??noteinteractiondisplay\v!text}%
+ {\strc_references_get_simple_page_reference{page(\ctxlua{structures.notes.getsymbolpage("\currentnote",\currentnotenumber)})}%
+ \edef\strc_notes_set_reference_attribute_text {\attribute\referenceattribute\currentreferenceattribute}%
+ %\strc_references_set_simple_page_reference{note:\cldcontext{structures.notes.internalid("\currentnote",\currentnotenumber)}}%
+ \strc_references_set_simple_page_reference{note:\currentnote:\currentnotenumber}%
+ \edef\strc_notes_set_destination_attribute_text{\attribute\destinationattribute\currentdestinationattribute}%
+ \let \strc_notes_set_reference_attribute_number\donothing
+ \let \strc_notes_set_style_color_display \strc_notes_set_style_color_display_yes}
+
+\expandafter\let\csname\??noteinteractiondisplay\v!number\expandafter\endcsname\csname\??noteinteractiondisplay\v!yes\endcsname
+
+\let\strc_notes_set_style_color_inline_nop \usenotestyleandcolor
+\let\strc_notes_set_style_color_display_nop\usenotationstyleandcolor
+
+\unexpanded\def\strc_notes_set_style_color_inline_yes#1#2%
+ {\usenotestyleandcolor#1#2%
+ \iflocation\strc_notes_set_style_color_special\fi}
+
+\unexpanded\def\strc_notes_set_style_color_display_yes#1#2%
+ {\usenotationstyleandcolor#1#2%
+ \iflocation\strc_notes_set_style_color_special\fi}
+
+\def\strc_notes_set_style_color_special
+ {\iftrialtypesetting
+ % keep
+ \else\ifx\currentcolorparameter\empty
+ \scratchcounter\ctxlua{structures.notes.deltapage("\currentnote",\currentnotenumber)}\relax % todo calculate once
+ \setlocationcolorspecified\scratchcounter
+ \fi\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
+ \strc_notes_set_style_color_display\c!headstyle\c!headcolor
+ \strc_enumerations_text
+ \endgroup}
+
+% in mkii the pointer only showed up in pagewise notes
+
+\unexpanded\def\strc_notes_inject_pointer % todo calculate once
+ {\ifcase\ctxlua{structures.notes.deltapage("\currentnote",\currentnotenumber)}\relax
+ % unknown
+ \or
+ % same page
+ \or
+ \noteparameter\c!symbolcommand{\symbol[\v!note:\v!nextpage]}%
+ \or
+ \noteparameter\c!symbolcommand{\symbol[\v!note:\v!previouspage]}%
+ \fi}
+
+\unexpanded\def\strc_notes_register_note_page % called more often than needed
+ {\iftrialtypesetting \else
+ \normalexpanded{\noexpand\ctxlatelua{structures.notes.setsymbolpage("\currentnote",\currentnotenumber)}}%
+ \fi}
+
+\unexpanded\def\strc_notes_inject_symbol
+ {\removeunwantedspaces
+ \doifitalicelse\/\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
+ \begingroup
+ \currentconstructionsynchronize % this flushes the data to the list
+ \strc_notes_register_note_page % this registers the symbol page number (late)
+ \strc_notes_interaction_check_inline
+ \strc_notes_set_style_color_inline\c!textstyle\c!textcolor
+ \hbox \strc_notes_get_reference_attribute_symbol \bgroup
+ \dostarttagged\t!descriptionsymbol\currentnote
+ \dotagsetnotesymbol
+ \noteparameter\c!textcommand{\ctxcommand{noteprefixednumber("\currentnote",\currentnotenumber)}}%
+ % 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
+ \dostoptagged % check
+ \globallet\lastnotesymbol\relax}
+
+\unexpanded\def\strc_notes_inject_dummy % temp hack
+ {\removeunwantedspaces
+ \doifitalicelse\/\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
+ \hbox to .5em{}%
+ \globallet\lastnotesymbol\relax}
+
+\unexpanded\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
+%D symbol {\setupfootnotes [conversion=set 2]\footnote
+%D {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
+%D reference they can be seen as a special kind of
+%D floating bodies. Their placement is postponed but has to be
+%D taken into account in the pagebreak calculations. This kind
+%D of calculations are forced by using \type{\insert}s and dealing
+%D 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
+%D to mess around with inserts at all. Take for instance a table
+%D of contents. And so we can 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
+
+%D Often we need to process the whole set of notes and to make that
+%D fast, we use a 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
+
+\unexpanded\def\strc_notes_process#1% argument is a \macro that uses \currentnote
+ {\def\strc_notes_process_list##1{\edef\currentnote{##1}\let\currentdescription\currentnote#1}%
+ \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}
+
+\def\currentnoterulecommand{\csname\??notecommand\currentnote\endcsname}
+\def\currentnoterulealign {\csname\??notealign \currentnote\endcsname}
+
+\def\currentnoterulecommandcommand{\noteparameter\c!rulecommand}
+\def\currentnoterulecommandnormal {\normalnoterule} % no let as it can be changed afterwards
+%def\currentnoterulecommandunknown{\noteparameter\c!rule}
+
+\def\letcurrentnoterulecommand{\expandafter\let\csname\??notecommand\currentnote\endcsname}
+\def\letcurrentnoterulealign {\expandafter\let\csname\??notealign \currentnote\endcsname}
+
+\appendtoks
+ \letvalue{\??notecommand\currentnote}\currentnoterulecommandnormal
+ \letvalue{\??notealign \currentnote}\lefttoright
+\to \everysynchronizenote
+
+\def\strc_notes_set_rule
+ {\letcurrentnoterulecommand\relax % so we default to nothing
+ \processcommacommand[\noteparameter\c!rule]\strc_notes_set_rule_step}
+
+\def\strc_notes_set_rule_step#1%
+ {\csname\??noterule\ifcsname\??noterule#1\endcsname#1\else\s!unknown\fi\endcsname}
+
+\setvalue{\??noterule\v!command}{\letcurrentnoterulecommand\currentnoterulecommandcommand}
+\setvalue{\??noterule \v!on}{\letcurrentnoterulecommand\currentnoterulecommandnormal}
+\setvalue{\??noterule \v!normal}{\letcurrentnoterulecommand\currentnoterulecommandnormal}
+\setvalue{\??noterule \v!left}{\letcurrentnoterulealign \lefttoright}
+\setvalue{\??noterule \v!right}{\letcurrentnoterulealign \righttoleft}
+\setvalue{\??noterule \v!off}{\letcurrentnoterulecommand\relax}
+%setvalue{\??noterule\s!unknown}{\letcurrentnoterulecommand\currentnoterulecommandunknown} % obsolete
+
+\appendtoks
+ \strc_notes_set_rule
+\to \everysynchronizenote
+
+\def\currentnotepenalty
+ {\ifcsname\??notepenalty\noteparameter\c!split\endcsname
+ \csname\??notepenalty\noteparameter\c!split\endcsname
+ \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
+
+\def\strc_notes_set_width
+ {\edef\p_width{\noteparameter\c!width}%
+ \ifx\p_width\empty
+ \setnoteparameter\c!width{\hsize}%
+ \fi}
+
+\appendtoks
+ \strc_notes_set_width
+\to \everysynchronizenote
+
+%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\currentnoteins\p_factor % new: global
+ \fi
+ \fi}
+
+\appendtoks
+ \strc_notes_set_factor
+\to \everysynchronizenote
+
+% locations:
+
+\installcorenamespace{notelocationvariant}
+\installcorenamespace{notepositionvariant}
+\installcorenamespace{notelocation}
+
+% \newconditional\c_strc_notes_delayed
+
+\setvalue{\??notelocation\v!page }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_page}
+\setvalue{\??notelocation\v!columns }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_columns}
+\setvalue{\??notelocation\v!lastcolumn }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_lastcolumn}
+\setvalue{\??notelocation\v!firstcolumn}{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_firstcolumn}
+\setvalue{\??notelocation\v!none }{\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_location_none}
+\setvalue{\??notelocation\v!text }{\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}
+
+\def\strc_notes_set_location
+ {\letvalue{\??notelocationvariant\currentnote}\strc_notes_set_position_page
+ \letvalue{\??notepositionvariant\currentnote}\strc_notes_set_position_bottom
+ \normalexpanded{\rawprocesscommalist[\noteparameter\c!location]\strc_notes_set_location_step}}
+
+\unexpanded\def\strc_notes_set_location_step#1%
+ {\ifcsname\??notelocation#1\endcsname
+ \csname\??notelocation#1\endcsname
+ \fi}
+
+\appendtoks
+ \strc_notes_set_location
+\to \everysynchronizenote
+
+\newskip \s_strc_notes_distance % we need to implement stretch
+\newcount\c_strc_notes_columns
+
+\def\strc_notes_set_distance
+ {\begingroup
+ \setbox\scratchbox\vbox % no reuse as it can mirror
+ {\forgetall
+ % \strc_notes_set_bodyfont
+ \dontcomplain
+ \noteparameter\c!before
+ \placenoterule
+ \noteparameter\c!after}%
+ \expandafter\endgroup\expandafter
+ \s_strc_notes_distance\the\ht\scratchbox\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
+ \global\count\currentnoteins\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\currentnoteins\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \currentnoteins\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
+ \global\count\currentnoteins\numexpr\plusthousand/\c_strc_notes_columns\relax
+ \global\dimen\currentnoteins\ifnotelimit\dimexpr\noteparameter\c!height*\c_strc_notes_columns\relax\else\maxdimen\fi
+ \global\skip \currentnoteins\s_strc_notes_distance}
+
+\def\strc_notes_set_location_firstcolumn
+ {%\setfalse\c_strc_notes_delayed
+ \strc_notes_set_distance
+ \strc_notes_set_columns
+ \global\count\currentnoteins\plusthousand
+ \global\dimen\currentnoteins\ifnotelimit\noteparameter\c!height\else\maxdimen\fi
+ \global\skip \currentnoteins\s_strc_notes_distance}
+
+\let\strc_notes_set_location_lastcolumn\strc_notes_set_location_firstcolumn
+
+\def\strc_notes_set_location_text % we don't use inserts anyway (e.g. endnotes)
+ {%\settrue\c_strc_notes_delayed
+ \ctxlua{structures.notes.setstate("\currentnote","store")}%
+ \global\dimen\currentnoteins\maxdimen
+ \global\count\currentnoteins\zerocount
+ \global\skip \currentnoteins\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
+ \csname\??notelocationvariant\currentnote\endcsname}
+
+\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\currentnoteins\else
+ \csname\??notepositionvariant\currentnote\endcsname
+ \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
+%D setup macro at every skipswitch is tricky (many many MP
+%D runs). Let's just reserve a few points, that probably match
+%D those of the stretch component.
+
+%D A bit messy:
+
+\unexpanded\def\placenoterule
+ {\begingroup
+ \currentnoterulealign
+ \currentnoterulecommand
+ \par
+ \endgroup}
+
+\unexpanded\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}
+
+\ifdefined\setnotehsize \else
+
+ \unexpanded\def\setnotehsize{\hsize\noteparameter\c!width\relax} % can be overloaded
+
+\fi
+
+%D The formatting depends on the width of the table, so we
+%D have to set \type {n} to 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
+%D therefore its formal specification looks like:
+%D
+%D \showsetup{footnote}
+%D
+%D This command has one optional command: the reference. By
+%D saying \type{[-]} the number is omitted. The footnote
+%D command is not that sensitive to spacing, so it's quite
+%D legal to say:
+%D
+%D \startbuffer
+%D Users of \CONTEXT\ must keep both feet \footnote{Given they
+%D have two.} on the ground and not get confused \footnote{Or
+%D even crazy.} by all those obscure \footnote{But fortunately
+%D 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
+%D when reshaping boxes.
+%D
+%D The additional macro \type {\footnotetext} and the
+%D associated \type {\note} macro were implemented at
+%D request of users on the mailing list and a suggestion by
+%D taco to split of the symbol placement. I decided to
+%D merge this functionality with the existing \type {\note}
+%D functionality.
+
+\newconditional\c_strc_notes_symbol \settrue\c_strc_notes_symbol % not used
+\newconditional\c_strc_notes_skip
+
+ \unexpanded\def\setnote [#1]{\getvalue{#1}}
+ \unexpanded\def\setnotetext[#1]{\global\settrue\c_strc_notes_skip\getvalue{#1}}
+
+\unexpanded\def\handlenoteinsert#1#2% tg, id
+ {\begingroup
+ \edef\currentnote{#1}%
+ \strc_constructions_initialize{#1}%
+ \the\everybeforenoteinsert
+ \insert\currentnoteins\bgroup
+ \the\everyinsidenoteinsert\relax
+ \doprocesslocalsetups{\noteparameter\c!setups}% experimental
+ \doifelse{\noteparameter\c!paragraph}\v!yes
+ {\nointerlineskip
+ \startvboxtohbox
+ \handlenoteitself{#1}{#2}%
+ % add some slack
+ \stopvboxtohbox}
+ {\handlenoteitself{#1}{#2}}%
+ \egroup
+ \the\everyafternoteinsert
+ \endgroup}
+
+\unexpanded\def\betweennoteitself#1% tg
+ {\edef\currentnote{#1}%
+ \doif{\noteparameter\c!paragraph}\v!yes\strc_notes_between_paragraphs}
+
+\unexpanded\def\handlenoteitself#1#2% tg, id
+ {\edef\currentnote{#1}%
+ \edef\currentnotenumber{#2}%
+ \strc_constructions_initialize{#1}% not needed when called in handlenoteinsert
+ \edef\currentconstructionlistentry{\ctxlua{tex.write(structures.notes.listindex("#1",#2))}}% index in list cache
+ % as we can have collected notes (e.g. in tables) we need to recover
+ % \currentdescriptionattribute and \currentdescriptionsynchronize
+ %
+ %\reinstateconstructionnumberentry\currentconstructionlistentry % we could store the number in the entry
+ %
+ \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
+ \endstrut
+ \strc_constructions_stored_stop
+% \endgroup
+ }
+
+\unexpanded\def\strc_notes_inject_text
+ {\ctxcommand{savedlisttitle("\currentconstructionmain",\currentconstructionlistentry)}}
+
+\let\startpushnote\relax
+\let\stoppushnote \relax
+
+\newsignal\notesignal
+
+\newconditional\processingnote
+\newconditional\postponednote
+
+\newtoks\everybeforenoteinsert
+\newtoks\everyinsidenoteinsert
+\newtoks\everyafternoteinsert
+
+\appendtoks
+ \let\flushnotes\relax
+ \let\postponenotes\relax
+ \forgetall
+ \resetallattributes % new, we don't want color bleed into notes
+\to \everybeforenoteinsert
+
+\appendtoks
+ \doif{\noteparameter\c!scope}\v!page{\floatingpenalty\maxdimen}% experiment
+ \penalty\currentnotepenalty
+ \forgetall
+ \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
+ % brrr
+% \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
+\to \everyinsidenoteinsert
+
+\appendtoks % only needed when columns
+ \setsimplecolumnshsize[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
+\to \everyinsidenoteinsert
+
+% not: \appendtoks \setnotehsize \to \everyinsidenoteinsert (spoils columns)
+
+%D Normally footnotes are saved as inserts that are called upon
+%D as soon as the pagebody is constructed. The footnote
+%D insertion routine looks just like the \PLAIN\ \TEX\ one,
+%D 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}}
+
+\unexpanded\def\placenoteinserts
+ {\strc_notes_process\strc_notes_place_inserts}
+
+\def\strc_notes_place_inserts
+ {%\ifconditional\c_strc_notes_delayed \else
+ \ifdim\ht\currentnoteins>\zeropoint % or a faster delayed test
+ \strc_notes_place_inserts_indeed
+ \fi}
+
+\def\strc_notes_place_inserts_indeed
+ {\relax
+ \ifdim\ht\currentnoteins>\zeropoint
+ \endgraf
+ \ifvmode
+ \whitespace
+ \noteparameter\c!before
+ \fi
+ % \bgroup
+ % \setupalign[\noteparameter\c!align]%
+ \placenoterule % alleen in ..mode
+ % \par
+ % \egroup
+ \bgroup
+ \strc_notes_set_bodyfont
+ \setbox\scratchbox\hbox
+ {\strc_notes_flush_inserts}%
+ \setbox\scratchbox\hbox
+ {\setupcurrentnote
+ [\c!location=,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!strut=\v!no,
+ \c!offset=\v!overlay]%
+ \inheritednoteframed
+ {\ifdim\dp\scratchbox=\zeropoint % this hack is needed because \vadjust
+ \hbox{\lower\strutdp\box\scratchbox}% % in margin number placement
+ \else % hides the (always) present depth
+ \box\scratchbox
+ \fi}}%
+ \setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}%
+ \dp\scratchbox\strutdepth % so we know that it has the note bodyfont depth
+ \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
+ {%\iftrialtypesetting\copy\else\box\fi\currentnoteins
+ \strc_notes_flush_global
+ \obeydepth} % (a) added , since split footnotes will not align properly
+
+\def\strc_notes_flush_inserts_columns
+ {\startsimplecolumns[\c!distance=\noteparameter\c!columndistance,\c!n=\noteparameter\c!n,\c!width=\noteparameter\c!width]%
+ %\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins % compare with local
+ \strc_notes_flush_global
+ \stopsimplecolumns}
+
+% idea: tag with attr and then just flush them again
+
+\def\strc_notes_between_paragraphs % should not be too much
+ {\noteparameter\c!inbetween}
+
+\def\strc_notes_between_paragraphs_first
+ {\glet\strc_notes_between_paragraphs_indeed\strc_notes_between_paragraphs}% shape works reverse
+
+\def\strc_notes_flush_global % will be done in lua instead
+ {\doifelse{\noteparameter\c!paragraph}\v!yes
+ {\vbox
+ {\beginofshapebox
+ \iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins
+ \endofshapebox
+ %\doreshapebox{\box\shapebox}{}{}{}% get rid of penalties etc
+ \let\strc_notes_between_paragraphs_indeed\strc_notes_between_paragraphs_first % shape works reverse
+ \doreshapebox
+ {\hbox{\unhbox\shapebox\strc_notes_between_paragraphs_indeed}}
+ {}%
+ {}%
+ {}% get rid of penalties etc
+ \innerflushshapebox
+ \convertvboxtohbox}}
+ {\iftrialtypesetting\unvcopied\else\unvboxed\fi\currentnoteins}}
+
+%D Supporting end notes is surprisingly easy. Even better, we
+%D can combine this feature with solving the common \TEX\
+%D problem of disappearing inserts when they're called for in
+%D 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
+%D etc. The latter one sometimes calls for notes local to
+%D 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)
+%D insert operation. A not too robust method uses the
+%D \type{\insert} primitive when possible. This method fails in
+%D situations where it's not entirely clear in what mode \TEX\
+%D is. Therefore the auto method can is to be overruled when
+%D needed.
+
+\newconditional\postponingnotes
+
+% we need a proper state: normal, postponing, flushing
+
+\def\postponenotes
+ {\ifconditional\postponingnotes\else
+ \global\settrue\postponingnotes
+ \global\let\flushnotes\doflushnotes
+ \ctxlua{structures.notes.postpone()}%
+ \fi}
+
+\let\flushnotes\relax
+
+\def\doflushnotes
+ {\ifconditional\postponingnotes
+ \begingroup
+ \let\flushnotes \relax
+ \let\postponenotes\relax
+ \ctxlua{structures.notes.flushpostponed()}% this also resets the states !
+ \global\setfalse\postponednote
+ \global\setfalse\postponingnotes
+ \global\let\flushnotes\relax
+ \endgroup
+ \fi}
+
+%D \macros
+%D {startlocalfootnotes,placelocalfootnotes}
+%D
+%D The next two macros can be used in for instance tables, as
+%D we'll demonstrate later on.
+%D
+%D \showsetup{startlocalfootnotes}
+%D \showsetup{placelocalfootnotes}
+
+% todo: compatibility mode: when first arg is assignment or missing, then all
+
+\newtoks\everyplacelocalnotes
+
+\appendtoks
+ \let\flushnotes \relax
+ \let\postponenotes\relax
+\to \everyplacelocalnotes
+
+\newconditional\inlocalnotes
+
+\unexpanded\def\startlocalnotes
+ {\dosingleempty\strc_notes_local_start}
+
+\def\strc_notes_local_start[#1]%
+ {\def\localnoteslist{#1}%
+ \settrue\inlocalnotes
+ \processcommacommand[\localnoteslist]\strc_notes_local_start_step}
+
+\unexpanded\def\stoplocalnotes
+ {\processcommacommand[\localnoteslist]\strc_notes_local_stop_step
+ \setfalse\inlocalnotes}
+
+\def\strc_notes_local_start_step#1%
+ {\doifnot{\noteparameter\c!continue}\v!yes
+ {\strc_counters_save{#1}%
+ \strc_counters_reset{#1}}%
+ \ctxlua{structures.notes.save("#1","store")}}
+
+\def\strc_notes_local_stop_step#1%
+ {\doifnot{\noteparameter\c!continue}\v!yes
+ {\strc_counters_restore{#1}}%
+ \ctxlua{structures.notes.restore("#1")}}
+
+\unexpanded\def\placelocalnotes
+ {\dodoubleempty\strc_notes_local_place}
+
+\def\strc_notes_local_place[#1][#2]%
+ {\doif{\ctxlua{structures.notes.getstate("#1")}}{store}{\strc_notes_local_place_indeed{#2}{#1}}}
+
+\def\strc_notes_local_place_indeed#1#2% settings note
+ {\begingroup
+ \edef\currentnote{#2}% is already set?
+ \the\everyplacelocalnotes
+ % beware, we cannot trust setting \currentnote here
+ \setupcurrentnote[\c!width=\v!fit,\c!height=\v!fit,\c!strut=\v!no,\c!offset=\v!overlay,#1]% we only need a selective one
+ \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[width=.3\hsize,n=0]
+%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 {\placelocalnotes}
+%D \stoplocalnotes
+%D \stopbuffer
+%D
+%D \typebuffer
+%D
+%D Because this table placement macro expect box content, and
+%D thanks to the grouping of the local footnotes, we don't need
+%D additional braces.
+%D
+%D \getbuffer
+
+%D \macros
+%D {placefootnotes}
+%D
+%D We still have no decent command for placing footnotes
+%D somewhere else than at the bottom of the page (for which no
+%D user action is needed). Footnotes (endnotes) can be
+%D placed by using
+%D
+%D \showsetup{placefootnotes}
+
+\unexpanded\def\placebottomnotes
+ {\strc_notes_process\strc_notes_place_inserts}
+
+\unexpanded\def\placenotes
+ {\dodoubleempty\strc_notes_place}
+
+\def\strc_notes_place[#1][#2]%
+ {\processcommalist[#1]{\strc_notes_place_indeed{#2}}}
+
+\def\strc_notes_place_indeed#1#2% settings note
+ {\edef\currentnote{#2}% grouping ?
+ \doifelse{\ctxlua{structures.notes.getstate("#2")}}{store}
+ \strc_notes_local_place_indeed
+ \strc_notes_global_place_indeed
+ {#1}{#2}}
+
+\def\strc_notes_global_place_indeed#1#2%
+ {\begingroup
+ \setupnote[#2][#1]%
+ \strc_notes_place_inserts
+ \endgroup
+ \the\everysetupnote} % to be checked .. synchronize
+
+%D Placement
+
+\installcorenamespace{notealternative}
+
+\unexpanded\def\installnotealternative#1#2%
+ {\setvalue{\??notealternative#1}{#2}}
+
+\unexpanded\def\doifnotescollected#1%
+ {\ctxlua{structures.notes.doifcontent("#1")}}
+
+\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
+ \getvalue{\??notealternative\noteparameter\c!alternative}%
+ \endgroup
+ \ifvmode
+ \noteparameter\c!after
+ \fi}}
+
+\setvalue{\??notealternative}{\getvalue{\??notealternative\v!none}}
+
+%D A stupid alternative is also provided:
+%D
+%D \starttyping
+%D \setupfootnotes[location=text,alternative=none]
+%D \stoptyping
+
+% setups ?
+
+% \def\flushlocalnotes#1{\ctxlua{structures.notes.flush("#1","store")}}
+\def\flushlocalnotes#1{\ctxlua{structures.notes.flush("#1","store","\noteparameter\c!criterium")}}
+
+\installnotealternative \v!none
+ {\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}%
+ \doifdimensionelse\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
+
+\unexpanded\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
+
+\unexpanded\def\checknotepresence
+ {\notespresentfalse
+ \strc_notes_process\strc_notes_check_presence}
+
+\def\strc_notes_check_presence
+ {\ifdim\ht\currentnoteins>\zeropoint
+ \notespresenttrue
+ \fi}
+
+%D \macros
+%D {fakenotes}
+
+ % used in page-mul
+
+ \ifdefined\currentnofcolumns\else \def\currentnofcolumns{\@@kln} \fi
+
+ \unexpanded\def\fakenotes
+ {\ifhmode\endgraf\fi\ifvmode
+ \calculatetotalclevernoteheight
+ \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
+ \fi}
+
+ \unexpanded\def\fakepagenotes
+ {\ifhmode\endgraf\fi\ifvmode
+ \calculatetotalpagenoteheight
+ \ifdim\totalnoteheight>\zeropoint \kern\totalnoteheight \fi
+ \fi}
+
+ \newdimen\totalnoteheight
+
+ \def\doaddtototalnoteheight#1%
+ {\ifdim\ht#1>\zeropoint
+ \ifcase\count#1\else
+ % todo: divide by count
+ \advance\totalnoteheight\ht #1%
+ \advance\totalnoteheight\skip#1%
+ \fi
+ \fi}
+
+ \def\docalculatetotalnoteheight
+ {\ifcase\c_strc_notes_page_location % tricky here ! ! ! to be sorted out ! ! !
+ \doaddtototalnoteheight\currentnoteins
+ \else
+ % \doaddtototalnoteheight\currentbackupnoteins
+ \fi}
+
+ \def\docalculatetotalclevernoteheight
+ {\ifcase\c_strc_notes_page_location \else % tricky here ! ! ! to be sorted out ! ! !
+ \doaddtototalnoteheight\currentnoteins
+ \fi}
+
+ \def\docalculatetotalpagenoteheight
+ {\doaddtototalnoteheight\currentnoteins}
+
+ \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
+%D explictly postponing footnotes? The solution turned out to
+%D 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
+%D sensitive to footnote gobbling we disable \type{\everypar}
+%D in favor for \type{\neverypar}. In fact, this footnote
+%D implementation is the first to use this scheme.
+
+%D This is a nasty and new secondary footnote flusher. It
+%D can be hooked into \type {\everypar} like:
+%D
+%D \starttyping
+%D \appendtoks \synchronizenotes \to \everypar
+%D \stoptyping
+
+% \def\dosynchronizenotes
+% {\ifvoid\currentnoteins\else\insert\currentnoteins{\unvbox\currentnoteins}\fi}
+%
+% \def\synchronizenotes
+% {\strc_notes_process\dosynchronizenotes}
+
+\let\synchronizenotes\relax
+
+%D When typesetting footnotes, we have to return to the
+%D footnote specific bodyfont size, which is in most cases derived
+%D from the global document bodyfont size. In the previous macros
+%D we already used a footnote specific font setting macro.
+
+\def\strc_notes_set_bodyfont
+ {\let\strc_notes_set_bodyfont\relax
+ \restoreglobalbodyfont
+ \switchtobodyfont[\noteparameter\c!bodyfont]%
+ \setupalign[\noteparameter\c!align]}
+
+%D The footnote mechanism defaults to a traditional one
+%D column way of showing them. By default we precede them by
+%D a small line.
+
+\definenote [\v!footnote]
+\definenote [\v!endnote ] [\c!location=\v!none] % else no break
+
+%D Compatibility macros:
+
+\unexpanded\def\setupfootnotedefinition{\setupnotedefinition [\v!footnote]}
+\unexpanded\def\setupfootnotes {\setupnote [\v!footnote]}
+ \def\footnotetext {\setnotetext [\v!footnote]}
+\unexpanded\def\placefootnotes {\dodoubleempty\strc_notes_place_footnotes [\v!footnote]}
+\unexpanded\def\placelocalfootnotes {\dodoubleempty\strc_notes_place_local_footnotes[\v!footnote]}
+\unexpanded\def\startlocalfootnotes {\startlocalnotes [\v!footnote]} % alleen footnote
+\unexpanded\def\stoplocalfootnotes {\stoplocalnotes }
+
+\def\strc_notes_place_footnotes [#1][#2]{\ifsecondargument\placenotes [#1][#2,\c!height=\textheight]\else\placenotes [#1]\fi}
+\def\strc_notes_place_local_footnotes[#1][#2]{\ifsecondargument\placelocalnotes[#1][#2,\c!height=\textheight]\else\placelocalnotes[#1]\fi}
+
+%D Goodies:
+%D
+%D \starttyping
+%D \dorecurse {100} {
+%D test \footnote{\doifnoteonsamepageelse[footnote]{ibidem}{aaa}}
+%D }
+%D \stoptyping
+
+\def\doifnoteonsamepageelse[#1]{\ctxlua{structures.notes.doifonsamepageasprevious("#1")}}
+
+%D New trickery:
+
+%D \macros
+%D {note}
+%D
+%D Refering to a note is accomplished by the rather short
+%D command:
+%D
+%D \showsetup{note}
+%D
+%D This command is implemented rather straightforward as:
+
+\installcorenamespace{notesymbol}
+
+\let\lastnotesymbol\relax % todo: per class
+
+\unexpanded\def\notesymbol
+ {\dodoubleempty\strc_notes_symbol}
+
+\def\strc_notes_symbol[#1][#2]%
+ {\dontleavehmode
+ \begingroup
+ \edef\currentnote{#1}%
+ \usenotestyleandcolor\c!textstyle\c!textcolor
+ \ifnotesenabled
+ \ifsecondargument
+ \unskip
+ \noteparameter\c!textcommand{\in[#2]}% command here?
+ \else
+ \noteparameter\c!textcommand\lastnotesymbol % check if command double
+ \fi
+ \fi
+ \endgroup}
+
+\unexpanded\def\note
+ {\dodoubleempty\strc_notes_note}
+
+\def\strc_notes_note[#1][#2]%
+ {\ifsecondargument
+ \strc_notes_symbol[#1][#2]%
+ \else
+ \secondargumenttrue
+ \strc_notes_symbol[\v!footnote][#1]%
+ \fi}
+
+% will be redone if needed
+%
+% \def\ownnotesymbol#1% #1 gets number passed
+% {\executeifdefined{\??notesymbol\currentnote}\empty}
+%
+% \unexpanded\def\setnotesymbol[#1]#2#3%
+% {\prewordbreak % prevent lookback
+% \setgvalue{\??notesymbol#1}{#3}
+% \strc_notes_inject_symbol}
+%
+% \unexpanded\def\ownnote[#1]#2#3#4%
+% {\setnotesymbol[#1]{#2}{#3}%
+% \setnotetext [#1]{#4}}
+%
+% \defineconversion
+% [ownnote]
+% [\ownnotesymbol]
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-num.lua b/Master/texmf-dist/tex/context/base/strc-num.lua
index 95cf6d94127..0715a9e4913 100644
--- a/Master/texmf-dist/tex/context/base/strc-num.lua
+++ b/Master/texmf-dist/tex/context/base/strc-num.lua
@@ -6,12 +6,12 @@ if not modules then modules = { } end modules ['strc-num'] = {
license = "see context related readme files"
}
--- this will be reimplemented
+-- this will be reimplemented and some more will move to the commands namespace
local format = string.format
local next, type = next, type
local min, max = math.min, math.max
-local texsprint, texcount = tex.sprint, tex.count
+local texcount = tex.count
local allocate = utilities.storage.allocate
local setmetatableindex = table.setmetatableindex
@@ -66,7 +66,7 @@ end
job.register('structures.counters.collected', tobesaved, initializer, finalizer)
-local function constructor(t,s,name,i)
+local function constructor(t,s,name,i) -- variables ?
if s == "last" then
local cc = collected[name]
t.stop = (cc and cc[i] and cc[i][t.range]) or 0 -- stop is available for diagnostics purposes only
@@ -181,26 +181,18 @@ local function savevalue(name,i)
end
end
-function counters.define(name, start, counter, method) -- todo: step
- local d = allocate(name,1)
- d.start = start
- d.state = variables.start or ""
- if counter ~= "" then
- d.counter = counter -- only for special purposes, cannot be false
- d.method = method -- frozen at define time
- end
-end
-
-function counters.trace(name)
- local cd = counterdata[name]
- if cd then
- texsprint(format("[%s:",name))
- local data = cd.data
- for i=1,#data do
- local d = data[i]
- texsprint(format(" (%s: %s,%s,%s s:%s r:%s)",i,(d.start or 0),d.number or 0,d.last,d.step or 0,d.range or 0))
+function counters.define(specification)
+ local name = specification.name
+ if name and name ~= "" then
+ -- todo: step
+ local d = allocate(name,1)
+ d.start = specification.start
+ d.state = variables.start or ""
+ local counter = specification.counter
+ if counter and counter ~= "" then
+ d.counter = counter -- only for special purposes, cannot be false
+ d.method = specification.method -- frozen at define time
end
- texsprint("]")
end
end
@@ -228,34 +220,30 @@ end
-- depends on when incremented, before or after (driven by d.offset)
-function counters.doifelse(name)
- commands.doifelse(counterdata[name])
-end
-
function counters.previous(name,n)
- texsprint(allocate(name,n).previous)
+ return allocate(name,n).previous
end
function counters.next(name,n)
- texsprint(allocate(name,n).next)
+ return allocate(name,n).next
end
counters.prev = counters.previous
-function counters.current(name,n)
- texsprint(allocate(name,n).number)
+function counters.currentvalue(name,n)
+ return allocate(name,n).number
end
function counters.first(name,n)
- texsprint(allocate(name,n).first)
+ return allocate(name,n).first
end
function counters.last(name,n)
- texsprint(allocate(name,n).last)
+ return allocate(name,n).last
end
function counters.subs(name,n)
- texsprint(counterdata[name].data[n].subs or 0)
+ return counterdata[name].data[n].subs or 0
end
function counters.setvalue(name,tag,value)
@@ -349,14 +337,16 @@ function counters.setown(name,n,value)
end
end
-function counters.restart(name,n,newstart)
+function counters.restart(name,n,newstart,noreset)
local cd = counterdata[name]
if cd then
newstart = tonumber(newstart)
if newstart then
local d = allocate(name,n)
d.start = newstart
- counters.reset(name,n)
+ if not noreset then
+ counters.reset(name,n) -- hm
+ end
end
end
end
@@ -377,13 +367,14 @@ end
function counters.add(name,n,delta)
local cd = counterdata[name]
---~ table.print(cd,name)
+-- inspect(cd)
if cd and (cd.state == variables.start or cd.state == "") then
local data = cd.data
local d = allocate(name,n)
d.number = (d.number or d.start or 0) + delta*(d.step or 0)
-- d.own = nil
local level = cd.level
+-- print(name,n,delta,level)
if not level or level == -1 then
-- -1 is signal that we reset manually
elseif level == -2 then
@@ -426,7 +417,7 @@ function counters.get(name,n,key)
end
function counters.value(name,n) -- what to do with own
- tex.write(counters.get(name,n or 1,'number') or 0)
+ return counters.get(name,n or 1,'number') or 0
end
function counters.converted(name,spec) -- name can be number and reference to storage
@@ -481,6 +472,51 @@ function counters.converted(name,spec) -- name can be number and reference to st
end
end
+-- interfacing
+
+commands.definecounter = counters.define
+commands.setcounter = counters.set
+commands.setowncounter = counters.setown
+commands.resetcounter = counters.reset
+commands.restartcounter = counters.restart
+commands.savecounter = counters.save
+commands.restorecounter = counters.restore
+commands.addcounter = counters.add
+
+commands.rawcountervalue = function(...) context(counters.raw (...)) end
+commands.countervalue = function(...) context(counters.value (...)) end
+commands.lastcountervalue = function(...) context(counters.last (...)) end
+commands.firstcountervalue = function(...) context(counters.first (...)) end
+commands.nextcountervalue = function(...) context(counters.next (...)) end
+commands.prevcountervalue = function(...) context(counters.previous(...)) end
+commands.subcountervalues = function(...) context(counters.subs (...)) end
+
+function commands.showcounter(name)
+ local cd = counterdata[name]
+ if cd then
+ context("[%s:",name)
+ local data = cd.data
+ for i=1,#data do
+ local d = data[i]
+ context(" (%s: %s,%s,%s s:%s r:%s)",i,(d.start or 0),d.number or 0,d.last,d.step or 0,d.range or 0)
+ end
+ context("]")
+ end
+end
+
+function commands.doifelsecounter(name) commands.doifelse(counterdata[name]) end
+function commands.doifcounter (name) commands.doif (counterdata[name]) end
+function commands.doifnotcounter (name) commands.doifnot (counterdata[name]) end
+
+function commands.incrementedcounter(...) context(counters.add(...)) end
+
+function commands.checkcountersetup(name,level,start,state)
+ counters.restart(name,1,start,true) -- no reset
+ counters.setstate(name,state)
+ counters.setlevel(name,level)
+ sections.setchecker(name,level,counters.reset)
+end
+
--~ -- move to strc-pag.lua
--~ function counters.analyze(name,counterspecification)
diff --git a/Master/texmf-dist/tex/context/base/strc-num.mkii b/Master/texmf-dist/tex/context/base/strc-num.mkii
index 28f69b441a1..99fb687c865 100644
--- a/Master/texmf-dist/tex/context/base/strc-num.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-num.mkii
@@ -5,7 +5,7 @@
%D subtitle=Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-num.mkiv b/Master/texmf-dist/tex/context/base/strc-num.mkiv
index b386b5d9518..9c08693be56 100644
--- a/Master/texmf-dist/tex/context/base/strc-num.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-num.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Basic Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -17,326 +17,485 @@
\unprotect
-% we need to rework this, i.e. clone like itm, des etc with \s!parent
+% work in progress
+% to be checked: can we use the command handler code here?
-% numbering
+\installcorenamespace{counter}
-% \definestructurecounter[name]
-% \setupstructurecounter[name][wijze=,blok=,tekst=,plaats=,conversie=,start=]
-% \setstructurecounter[name]{value}
-% \resetstructurecounter[name]
-% \incrementstructurecounter[name]
-% \decrementstructurecounter[name]
-% \savestructurecounter[name]
-% \restorestructurecounter[name]
-% \convertedstructurecounter[name] % depricated: \getstructurecounter[name]
-% \rawstructurecounter[name]
+\unexpanded\def\setupstructurecounting{\dodoubleempty\getparameters[\??counter]}
-% private (defined in core-sec.tex)
-%
-% \nextstructurecounter[name][tag][reference]
-% \currentstructurecounter[name]
-
-% todo: better inheritane system
-
-\unexpanded\def\setupstructurecountering{\dodoubleempty\getparameters[\??nn]}
-
-\setupstructurecountering
+\setupstructurecounting
[\c!way=\v!by\v!chapter,
% \c!blockway=,
% \c!prefixstarter=,
% \c!prefixstopper=,
\c!prefixconnector=.,
- \c!prefixsegments=\thenamedstructurecounterlevel\currentstructurecounter,
+ \c!prefixsegments=\autostructureprefixsegments\sharedcounterparameter,
\c!start=0,
\c!prefix=\v!yes,
\c!state=\v!start]
-\setupstructurecountering
- [\c!prefixsegments=\autostructureprefixsegments\sharedstructurecounterparameter]
+\def\strc_counters_the#1% we need a nicer name
+ {\ifcsname\??counter#1\c!number\endcsname
+ \expandafter\strc_counters_the\csname\??counter#1\c!number\endcsname
+ \else
+ #1%
+ \fi}
\def\autostructureprefixsegments#1% todo: \c!prefixsegments=\v!auto
- {2:\thenamedstructureheadlevel{\ctxlua{structures.sections.way("#1\c!way","\v!by")}}}
+ {2:\thenamedheadlevel{\ctxlua{structures.sections.way("#1\c!way")}}}
-\def\structurecounterparameter#1#2%
+\def\counterparameter#1#2% this will become \named....
{\csname
- \ifcsname\??nn#1#2\endcsname
- \??nn#1#2%
- \else\ifcsname\??nn\@@thestructurecounter{#1}#2\endcsname
- \??nn\@@thestructurecounter{#1}#2%
- \else\ifcsname\??nn#2\endcsname
- \??nn#2%
+ \ifcsname\??counter#1#2\endcsname
+ \??counter#1#2%
+ \else\ifcsname\??counter\strc_counters_the{#1}#2\endcsname
+ \??counter\strc_counters_the{#1}#2%
+ \else\ifcsname\??counter#2\endcsname
+ \??counter#2%
\else
\s!empty
\fi\fi\fi
\endcsname}
-\def\@@thestructurecounter#1%
- {\ifcsname\??nn#1\c!number\endcsname
- \expandafter\@@thestructurecounter\csname\??nn#1\c!number\endcsname
- \else
- #1%
- \fi}
-
-\def\sharedstructurecounterparameter#1%
+\def\sharedcounterparameter#1%
{\csname
- \ifcsname\??nn#1\endcsname
- \??nn#1%
+ \ifcsname\??counter#1\endcsname
+ \??counter#1%
\else
\s!empty
\fi
\endcsname}
-\let\numberingparameter\sharedstructurecounterparameter
+\unexpanded\def\definecounter
+ {\dodoubleempty\strc_counters_define}
-% \def\structurecounterparameter #1#2{\csname\dostructurecounterparameter{\??nn#1}#2\endcsname}
-% \def\dostructurecounterparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dostructurecounterparentparameter\csname#1\s!number\endcsname#2\fi}
-% \def\dostructurecounterparentparameter#1#2{\ifx#1\relax\s!empty\else\dostructurecounterparameter#1#2\fi}
-
-\unexpanded\def\definestructurecounter
- {\dodoubleempty\dodefinestructurecounter}
-
-\def\dodefinestructurecounter[#1][#2]%
+\def\strc_counters_define[#1][#2]%
{\doifassignmentelse{#2}
- {\dododefinestructurecounter[#1][#2]}
+ {\strc_counters_define_yes[#1][#2]}
{\doifelsenothing{#2}
- {\dododefinestructurecounter[#1][]}
- {\donodefinestructurecounter[#1][#2]}}}
+ {\strc_counters_define_yes[#1][]}
+ {\strc_counters_define_nop[#1][#2]}}}
+
+\def\strc_counters_define_yes[#1][#2]%
+ {\getparameters[\??counter#1][\s!counter=,#2]% counter is for internal purposes
+ \ctxcommand{definecounter {
+ name = "#1",
+ start = tonumber("\counterparameter{#1}\c!start") or 0,
+ counter = "\counterparameter{#1}\s!counter",
+ method = "\counterparameter{#1}\c!method",
+ }}%
+ \strc_counters_check_setup{#1}}
+
+\def\strc_counters_define_nop[#1][#2]% inherit
+ {\getparameters[\??counter#1][\c!number=#2]%
+ \strc_counters_check_setup{#1}}
+
+\unexpanded\def\setupcounter
+ {\dodoubleargument\strc_counters_setup}
+
+\def\strc_counters_setup[#1][#2]%
+ {\getparameters[\??counter#1][\c!start=,#2]%
+ \strc_counters_check_setup{#1}}
+
+% % % %
+
+\def\strc_counters_way#1% slow, we need to store it at the tex end
+ {\ctxlua{structures.sections.way("\counterparameter{#1}\c!way")}}
+
+% \def\thenamedcounterlevel#1%
+% {\thenamedheadlevel{\strc_counters_way{#1}}}
+
+\def\thenamedcounterlevel#1%
+ {\xthenamedheadlevel{\strc_counters_way{#1}}}
+
+\def\xthenamedheadlevel#1%
+ {\xsectionlevel{#1}{\sectionheadsection{\sectionheadcoupling{#1}}}}
+
+\def\xsectionlevel#1#2% direct indirect
+ {\csname\??headlevel
+ \ifcsname\??headlevel#1\endcsname
+ #1%
+ \else\ifcsname\??headlevel#2\endcsname
+ #2%
+ \else
+ \v!none
+ \fi\fi
+ \endcsname}
+
+\def\strc_counters_check_setup#1% does it have to happen here?
+ {% this can be done at the lua end / a bit messy here ... todo ...
+ \ifcsname\??counter#1\c!number\endcsname
+ \doifelsevalue {\??counter#1\c!number}{#1} {\letbeundefined{\??counter#1\c!number}}%
+ {\doifvaluenothing{\??counter#1\c!number} {\letbeundefined{\??counter#1\c!number}}}%
+ \fi
+ \ifcsname\??counter#1\c!number\endcsname
+ % it's a clone
+ \else
+ \edef\currentcounterlevel{\thenamedcounterlevel{#1}}%
+ \ctxcommand{checkcountersetup("#1",\currentcounterlevel,"\counterparameter{#1}\c!start","\counterparameter{#1}\c!state")}%
+ \fi}
-\def\dododefinestructurecounter[#1][#2]%
- {\getparameters[\??nn#1][\s!counter=,#2]% counter is for internal purposes
- \ctxlua{structures.counters.define("#1", % this will be a table
- tonumber("\structurecounterparameter{#1}\c!start") or 0,
- "\structurecounterparameter{#1}\s!counter",
- "\structurecounterparameter{#1}\c!method")}%
- \docheckstructurecountersetup{#1}}
+\unexpanded\def\doifcounterelse #1{\ctxcommand{doifelsecounter("\strc_counters_the{#1}")}}
+\unexpanded\def\doifcounter #1{\ctxcommand{doifcounter ("\strc_counters_the{#1}")}}
+\unexpanded\def\doifnotcounter #1{\ctxcommand{doifnotcounter ("\strc_counters_the{#1}")}}
+
+\unexpanded\def\setcounter {\dotripleempty \strc_counters_set_interfaced}
+\unexpanded\def\setcounterown {\dotripleempty \strc_counters_setown_interfaced}
+\unexpanded\def\restartcounter {\dotripleempty \strc_counters_restart_interfaced}
+\unexpanded\def\resetcounter {\dodoubleempty \strc_counters_reset_interfaced}
+\unexpanded\def\incrementcounter {\dodoubleempty \strc_counters_increment_interfaced}
+\unexpanded\def\decrementcounter {\dodoubleempty \strc_counters_decrement_interfaced}
+
+\unexpanded\def\rawcounter {\dodoubleargument\strc_counters_raw_interfaced}
+\unexpanded\def\lastcounter {\dodoubleargument\strc_counters_last_interfaced}
+\unexpanded\def\firstcounter {\dodoubleargument\strc_counters_first_interfaced}
+\unexpanded\def\nextcounter {\dodoubleargument\strc_counters_next_interfaced}
+\unexpanded\def\prevcounter {\dodoubleargument\strc_counters_prev_interfaced}
+\unexpanded\def\countersubs {\dodoubleargument\strc_counters_subs_interfaced}
+
+\unexpanded\def\savecounter {\dodoubleempty \strc_counters_save_interfaced}
+\unexpanded\def\restorecounter {\dodoubleempty \strc_counters_restore_interfaced}
+
+\def\strc_counters_set_interfaced
+ {\ifthirdargument
+ \singleexpandafter\strc_counters_set_two
+ \else\ifsecondargument
+ \doubleexpandafter\strc_counters_set_one
+ \else
+ \doubleexpandafter\gobblethreeoptionals
+ \fi\fi}
+
+\def\strc_counters_setown_interfaced
+ {\ifthirdargument
+ \singleexpandafter\strc_counters_setown_two
+ \else\ifsecondargument
+ \doubleexpandafter\strc_counters_setown_one
+ \else
+ \doubleexpandafter\gobblethreeoptionals
+ \fi\fi}
+
+\def\strc_counters_restart_interfaced
+ {\ifthirdargument
+ \singleexpandafter\strc_counters_restart_two
+ \else\ifsecondargument
+ \doubleexpandafter\strc_counters_restart_one
+ \else
+ \doubleexpandafter\gobblethreeoptionals
+ \fi\fi}
-\def\donodefinestructurecounter[#1][#2]% inherit
- {\getparameters[\??nn#1][\c!number=#2]%
- \docheckstructurecountersetup{#1}}
+\def\strc_counters_reset_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_reset_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_reset_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
-\unexpanded\def\setupstructurecounter
- {\dodoubleargument\dosetupstructurecounter}
+\def\strc_counters_increment_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_increment_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_increment_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
-\def\dosetupstructurecounter[#1][#2]%
- {\getparameters[\??nn#1][\c!start=,#2]%
- \docheckstructurecountersetup{#1}}
+\def\strc_counters_decrement_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_decrement_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_decrement_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
-\def\structurecounterway#1% slow, we need to store it at the tex end
- {\ctxlua{structures.sections.way("\structurecounterparameter{#1}\c!way","\v!by")}}
+\def\strc_counters_raw_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_raw_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_raw_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
-\def\thenamedstructurecounterlevel#1%
- {\thenamedstructureheadlevel{\structurecounterway{#1}}}
+\def\strc_counters_last_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_last_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_last_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
-\def\docheckstructurecountersetup#1%
- {% this can be done at the lua end / a bit messy here ... todo ...
- \ifcsname\??nn#1\c!number\endcsname
- \doifelsevalue {\??nn#1\c!number}{#1} {\letbeundefined{\??nn#1\c!number}}%
- {\doifvaluenothing{\??nn#1\c!number} {\letbeundefined{\??nn#1\c!number}}}%
- \fi
- \ifcsname\??nn#1\c!number\endcsname
- % it's a clone
+\def\strc_counters_first_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_first_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_first_one
\else
- \edef\currentstructurecounterlevel{\thenamedstructurecounterlevel{#1}}%
- \ctxlua{
- structures.counters.restart("#1",1,"\structurecounterparameter{#1}\c!start")
- structures.counters.setstate("#1","\structurecounterparameter{#1}\c!state")
- structures.counters.setlevel("#1",\currentstructurecounterlevel)
- structures.sections.setchecker("#1",\currentstructurecounterlevel,structures.counters.reset)
- }%
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_prev_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_prev_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_prev_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_next_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_next_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_next_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_subs_interfaced
+ {\ifsecondargument
+ \singleexpandafter\strc_counters_subs_two
+ \else\iffirstargument
+ \doubleexpandafter\strc_counters_subs_one
+ \else
+ \doubleexpandafter\gobbletwooptionals
+ \fi\fi}
+
+\def\strc_counters_save_interfaced
+ {\iffirstargument
+ \expandafter\strc_counters_save_one
+ \else
+ \expandafter\gobbleoneoptional
\fi}
-\def\doifstructurecounterelse#1{\ctxlua{structures.counters.doifelse("\@@thestructurecounter{#1}")}}
-\def\doifstructurecounter #1{\ctxlua{structures.counters.doif ("\@@thestructurecounter{#1}")}}
-\def\doifnotstructurecounter #1{\ctxlua{structures.counters.doifnot ("\@@thestructurecounter{#1}")}}
-
-\def\setstructurecounter [#1]#2{\ctxlua{structures.counters.set ("\@@thestructurecounter{#1}",1,\number#2)}}
-\def\setstructurecounterown [#1]#2{\ctxlua{structures.counters.setown ("\@@thestructurecounter{#1}",1,"#2")}}
-\def\resetstructurecounter [#1]{\ctxlua{structures.counters.reset ("\@@thestructurecounter{#1}",1)}}
-\def\restartstructurecounter [#1]#2{\ctxlua{structures.counters.restart("\@@thestructurecounter{#1}",1,#2)}}
-\def\savestructurecounter [#1]{\ctxlua{structures.counters.save ("\@@thestructurecounter{#1}")}}
-\def\restorestructurecounter [#1]{\ctxlua{structures.counters.restore("\@@thestructurecounter{#1}")}}
-\def\incrementstructurecounter [#1]{\ctxlua{structures.counters.add ("\@@thestructurecounter{#1}",1,1)}}
-\def\decrementstructurecounter [#1]{\ctxlua{structures.counters.add ("\@@thestructurecounter{#1}",1,-1)}}
-\def\rawstructurecounter [#1]{\ctxlua{structures.counters.value ("\@@thestructurecounter{#1}",1)}}
-\def\laststructurecounter [#1]{\ctxlua{structures.counters.last ("\@@thestructurecounter{#1}",1)}}
-\def\firststructurecounter [#1]{\ctxlua{structures.counters.first ("\@@thestructurecounter{#1}",1)}}
-\def\nextstructurecounter [#1]{\ctxlua{structures.counters.next ("\@@thestructurecounter{#1}",1)}}
-\def\prevstructurecounter [#1]{\ctxlua{structures.counters.prev ("\@@thestructurecounter{#1}",1)}}
-\def\structurecountersubs [#1]{\ctxlua{structures.counters.subs ("\@@thestructurecounter{#1}",1)}}
-
-\def\tracestructurecounter [#1]{\ctxlua{structures.counters.trace ("\@@thestructurecounter{#1}")}}
-
-\def\incrementedstructurecounter[#1]{\ctxlua{tex.write(structures.counters.add("\@@thestructurecounter{#1}",1,1))}}
-\def\decrementedstructurecounter[#1]{\ctxlua{tex.write(structures.counters.add("\@@thestructurecounter{#1}",1,-1))}}
-
-\def\setsubstructurecounter {\dodoubleargument\dosetsubstructurecounter}
-\def\setsubstructurecounterown {\dodoubleargument\dosetsubstructurecounterown}
-\def\resetsubstructurecounter {\dodoubleargument\doresetsubstructurecounter}
-\def\restartsubstructurecounter {\dodoubleargument\dorestartsubstructurecounter}
-\def\incrementsubstructurecounter {\dodoubleargument\doincrementsubstructurecounter}
-\def\decrementsubstructurecounter {\dodoubleargument\dodecrementsubstructurecounter}
-\def\rawsubstructurecounter {\dodoubleargument\dorawsubstructurecounter}
-
-\def\dosetsubstructurecounter [#1][#2]#3{\ctxlua{structures.counters.set ("\@@thestructurecounter{#1}",#2,\number#3)}}
-\def\dosetsubstructurecounterown [#1][#2]#3{\ctxlua{structures.counters.setown ("\@@thestructurecounter{#1}",#2,"#3")}}
-\def\doresetsubstructurecounter [#1][#2]{\ctxlua{structures.counters.reset ("\@@thestructurecounter{#1}",#2)}}
-\def\dorestartsubstructurecounter [#1][#2]#3{\ctxlua{structures.counters.restart("\@@thestructurecounter{#1}",#2,#3)}}
-\def\doincrementsubstructurecounter [#1][#2]{\ctxlua{structures.counters.add ("\@@thestructurecounter{#1}",#2,1)}}
-\def\dodecrementsubstructurecounter [#1][#2]{\ctxlua{structures.counters.add ("\@@thestructurecounter{#1}",#2,-1)}}
-\def\dorawsubstructurecounter [#1][#2]{\ctxlua{structures.counters.value ("\@@thestructurecounter{#1}",#2)}}
-\def\dolastsubstructurecounter [#1][#2]{\ctxlua{structures.counters.last ("\@@thestructurecounter{#1}",#2)}}
-\def\dofirstsubstructurecounter [#1][#2]{\ctxlua{structures.counters.first ("\@@thestructurecounter{#1}",#2)}}
-\def\dosubstructurecountersubs [#1][#2]{\ctxlua{structures.counters.subs ("\@@thestructurecounter{#1}",#2)}}
-
-% The bypage check needs a multipass reference and therefore
-% we only check for it when we increment and know that some
-% content will be placed. We could also check for spreads.
-
-% to be checked !
-
-\def\docheckstructurecounterbypage#1% since we call lua to get the way we can as well do all in lua
- {\doif{\structurecounterway{#1}}\v!page{\checkpagechange{#1}\ifpagechanged\resetstructurecounter[#1]\fi}}
-
-\def\incrementstructurecounter[#1]%
- {\docheckstructurecounterbypage{#1}%
- \ctxlua{structures.counters.add("\@@thestructurecounter{#1}",1,1)}}
-
-\def\doincrementsubstructurecounter[#1][#2]%
- {\docheckstructurecounterbypage{#1}%
- \ctxlua{structures.counters.add("\@@thestructurecounter{#1}",#2,1)}}
-
-\def\convertedstructurecounter
- {\dodoubleempty\doconvertedstructurecounter}
-
-\def\doconvertedstructurecounter[#1][#2]%
+\def\strc_counters_restore_interfaced
+ {\iffirstargument
+ \expandafter\strc_counters_restore_one
+ \else
+ \expandafter\gobbleoneoptional
+ \fi}
+
+\def\strc_counters_set_two [#1][#2][#3]{\strc_counters_set_sub {#1}{#2}{#3}}
+\def\strc_counters_setown_two [#1][#2][#3]{\strc_counters_setown_sub {#1}{#2}{#3}}
+\def\strc_counters_restart_two [#1][#2][#3]{\strc_counters_restart_sub {#1}{#2}{#3}}
+\def\strc_counters_reset_two [#1][#2]{\strc_counters_reset_sub {#1}{#2}}
+\def\strc_counters_increment_two [#1][#2]{\strc_counters_increment_sub{#1}{#2}}
+\def\strc_counters_decrement_two [#1][#2]{\strc_counters_decrement_sub{#1}{#2}}
+
+\def\strc_counters_raw_two [#1][#2]{\strc_counters_raw_sub {#1}{#2}}
+\def\strc_counters_last_two [#1][#2]{\strc_counters_last_sub {#1}{#2}}
+\def\strc_counters_first_two [#1][#2]{\strc_counters_first_sub {#1}{#2}}
+\def\strc_counters_next_two [#1][#2]{\strc_counters_next_sub {#1}{#2}}
+\def\strc_counters_prev_two [#1][#2]{\strc_counters_prev_sub {#1}{#2}}
+\def\strc_counters_subs_two [#1][#2]{\strc_counters_subs_sub {#1}{#2}}
+
+\def\strc_counters_set_one [#1][#2][#3]{\strc_counters_set_sub {#1}\plusone{#2}}
+\def\strc_counters_setown_one [#1][#2][#3]{\strc_counters_setown_sub {#1}\plusone{#2}}
+\def\strc_counters_restart_one [#1][#2][#3]{\strc_counters_restart_sub {#1}\plusone{#2}}
+\def\strc_counters_reset_one [#1][#2]{\strc_counters_reset_sub {#1}\plusone}
+\def\strc_counters_increment_one [#1][#2]{\strc_counters_increment_sub{#1}\plusone}
+\def\strc_counters_decrement_one [#1][#2]{\strc_counters_decrement_sub{#1}\plusone}
+
+\def\strc_counters_raw_one [#1][#2]{\strc_counters_raw_sub {#1}\plusone}
+\def\strc_counters_last_one [#1][#2]{\strc_counters_last_sub {#1}\plusone}
+\def\strc_counters_first_one [#1][#2]{\strc_counters_first_sub {#1}\plusone}
+\def\strc_counters_next_one [#1][#2]{\strc_counters_next_sub {#1}\plusone}
+\def\strc_counters_prev_one [#1][#2]{\strc_counters_prev_sub {#1}\plusone}
+\def\strc_counters_subs_one [#1][#2]{\strc_counters_subs_sub {#1}\plusone}
+
+\def\strc_counters_save_one [#1]{\strc_counters_save {#1}}
+\def\strc_counters_restore_one [#1]{\strc_counters_restore {#1}}
+
+\unexpanded\def\strc_counters_set #1#2{\strc_counters_set_sub {#1}\plusone{#2}}
+\unexpanded\def\strc_counters_setown #1#2{\strc_counters_setown_sub {#1}\plusone{#2}}
+\unexpanded\def\strc_counters_restart #1#2{\strc_counters_restart_sub {#1}\plusone{#2}}
+\unexpanded\def\strc_counters_reset #1{\strc_counters_reset_sub {#1}\plusone}
+\unexpanded\def\strc_counters_increment #1{\strc_counters_increment_sub{#1}\plusone}
+\unexpanded\def\strc_counters_decrement #1{\strc_counters_decrement_sub{#1}\plusone}
+
+ \def\strc_counters_raw #1{\strc_counters_raw_sub {#1}\plusone}
+ \def\strc_counters_last #1{\strc_counters_last_sub {#1}\plusone}
+ \def\strc_counters_first #1{\strc_counters_first_sub {#1}\plusone}
+ \def\strc_counters_next #1{\strc_counters_next_sub {#1}\plusone}
+ \def\strc_counters_prev #1{\strc_counters_prev_sub {#1}\plusone}
+ \def\strc_counters_subs #1{\strc_counters_subs_sub {#1}\plusone}
+
+\unexpanded\def\strc_counters_set_sub #1#2#3{\ctxcommand{setcounter ("\strc_counters_the{#1}",\number#2,\number#3)}}
+\unexpanded\def\strc_counters_setown_sub #1#2#3{\ctxcommand{setowncounter ("\strc_counters_the{#1}",\number#2,"#3")}}
+\unexpanded\def\strc_counters_restart_sub #1#2#3{\ctxcommand{restartcounter("\strc_counters_the{#1}",\number#2,\number#3)}}
+\unexpanded\def\strc_counters_reset_sub #1#2{\ctxcommand{resetcounter ("\strc_counters_the{#1}",\number#2)}}
+\unexpanded\def\strc_counters_increment_sub #1#2{\ctxcommand{addcounter ("\strc_counters_the{#1}",\number#2,1)}}
+\unexpanded\def\strc_counters_decrement_sub #1#2{\ctxcommand{addcounter ("\strc_counters_the{#1}",\number#2,-1)}}
+
+ \def\strc_counters_raw_sub #1#2{\ctxcommand{countervalue ("\strc_counters_the{#1}",\number#2)}} % maybe raw
+ \def\strc_counters_last_sub #1#2{\ctxcommand{lastcountervalue ("\strc_counters_the{#1}",\number#2)}}
+ \def\strc_counters_first_sub #1#2{\ctxcommand{firstcountervalue ("\strc_counters_the{#1}",\number#2)}}
+ \def\strc_counters_next_sub #1#2{\ctxcommand{nextcountervalue ("\strc_counters_the{#1}",\number#2)}}
+ \def\strc_counters_prev_sub #1#2{\ctxcommand{previouscountervalue("\strc_counters_the{#1}",\number#2)}}
+ \def\strc_counters_subs_sub #1#2{\ctxcommand{subcountervalues ("\strc_counters_the{#1}",\number#2)}}
+
+\unexpanded\def\strc_counters_save #1{\ctxcommand{savecounter ("\strc_counters_the{#1}")}}
+\unexpanded\def\strc_counters_restore #1{\ctxcommand{restorecounter("\strc_counters_the{#1}")}}
+
+\unexpanded\def\strc_counters_incremented #1{\ctxcommand{incrementedcounter("\strc_counters_the{#1}",1, 1)}}
+\unexpanded\def\strc_counters_decremented #1{\ctxcommand{incrementedcounter("\strc_counters_the{#1}",1,-1)}}
+
+\unexpanded\def\showcounter [#1]{\ctxcommand{tracecounter("\strc_counters_the{#1}")}}
+
+\unexpanded\def\incrementedcounter [#1]{\strc_counters_incremented{#1}} % expandable, no \dosingleargument
+\unexpanded\def\decrementedcounter [#1]{\strc_counters_decremented{#1}} % expandable, no \dosingleargument
+
+% public variants ... beware, for old cases, from now on the value variants are the
+% ones that are expandable
+
+\def\rawcountervalue [#1]{\strc_counters_raw_sub {#1}\plusone}
+\def\lastcountervalue [#1]{\strc_counters_last_sub {#1}\plusone}
+\def\firstcountervalue[#1]{\strc_counters_first_sub{#1}\plusone}
+\def\nextcountervalue [#1]{\strc_counters_next_sub {#1}\plusone}
+\def\prevcountervalue [#1]{\strc_counters_prev_sub {#1}\plusone}
+
+\let\rawsubcountervalue \strc_counters_raw_two
+\let\lastsubcountervalue \strc_counters_last_two
+\let\firstsubcountervalue\strc_counters_first_two
+\let\nextsubcountervalue \strc_counters_next_two
+\let\prevsubcountervalue \strc_counters_prev_two
+
+% The bypage check needs a multipass reference and therefore we only check for it when we increment
+% and know that some content will be placed. We could also check for spreads.
+
+\unexpanded\def\strc_counters_increment_sub#1#2%
+ {% this will be combined into one lua call
+ \edef\m_strc_counters_way{\strc_counters_way{#1}}%
+ \ifx\m_strc_counters_way\v!page
+ \checkpagechange{#1}%
+ \ifpagechanged
+ \strc_counters_reset{#1}%
+ \fi
+ \fi
+ \ctxcommand{addcounter("\strc_counters_the{#1}",\number#2,1)}}
+
+\unexpanded\def\convertedcounter
+ {\dodoubleempty\strc_counters_converted}
+
+\def\strc_counters_converted[#1][#2]%
{\begingroup
- \ifsecondargument\getparameters[\??nn#1][#2]\fi
- \ctxlua{structures.counters.prefixedconverted(
- "\@@thestructurecounter{#1}",
+ \ifsecondargument\getparameters[\??counter#1][#2]\fi
+ \ctxlua{structures.sections.prefixedconverted(
+ "\strc_counters_the{#1}",
{
- prefix = "\structurecounterparameter{#1}\c!prefix",
- separatorset = "\structurecounterparameter{#1}\c!prefixseparatorset",
- conversion = "\structurecounterparameter{#1}\c!prefixconversion",
- conversionset = "\structurecounterparameter{#1}\c!prefixconversionset",
- starter = \!!bs\structurecounterparameter{#1}\c!prefixstarter\!!es,
- stopper = \!!bs\structurecounterparameter{#1}\c!prefixstopper\!!es,
- set = "\structurecounterparameter{#1}\c!prefixset",
- segments = "\structurecounterparameter{#1}\c!prefixsegments",
- connector = \!!bs\structurecounterparameter{#1}\c!prefixconnector\!!es,
+ prefix = "\counterparameter{#1}\c!prefix",
+ separatorset = "\counterparameter{#1}\c!prefixseparatorset",
+ conversion = "\counterparameter{#1}\c!prefixconversion",
+ conversionset = "\counterparameter{#1}\c!prefixconversionset",
+ starter = \!!bs\counterparameter{#1}\c!prefixstarter\!!es,
+ stopper = \!!bs\counterparameter{#1}\c!prefixstopper\!!es,
+ set = "\counterparameter{#1}\c!prefixset",
+ segments = "\counterparameter{#1}\c!prefixsegments",
+ connector = \!!bs\counterparameter{#1}\c!prefixconnector\!!es,
},
{
- order = "\structurecounterparameter{#1}\c!numberorder",
- separatorset = "\structurecounterparameter{#1}\c!numberseparatorset",
- conversion = \!!bs\structurecounterparameter{#1}\c!numberconversion\!!es,
- conversionset = "\structurecounterparameter{#1}\c!numberconversionset",
- starter = \!!bs\structurecounterparameter{#1}\c!numberstarter\!!es,
- stopper = \!!bs\structurecounterparameter{#1}\c!numberstopper\!!es,
- segments = "\structurecounterparameter{#1}\c!numbersegments",
- type = "\structurecounterparameter{#1}\c!type",
- criterium = "\structurecounterparameter{#1}\c!criterium", % might change if we also want this with sectioning
+ order = "\counterparameter{#1}\c!numberorder",
+ separatorset = "\counterparameter{#1}\c!numberseparatorset",
+ conversion = \!!bs\counterparameter{#1}\c!numberconversion\!!es,
+ conversionset = "\counterparameter{#1}\c!numberconversionset",
+ starter = \!!bs\counterparameter{#1}\c!numberstarter\!!es,
+ stopper = \!!bs\counterparameter{#1}\c!numberstopper\!!es,
+ segments = "\counterparameter{#1}\c!numbersegments",
+ type = "\counterparameter{#1}\c!type",
+ criterium = "\counterparameter{#1}\c!criterium", % might change if we also want this with sectioning
}
)}%
\endgroup}
-\def\directconvertedstructurecounter#1#2% name, type
- {\begingroup
- \ctxlua{structures.counters.prefixedconverted(
- "\@@thestructurecounter{#1}",
+\def\directconvertedcounter#1#2% name, type
+ {\ctxlua{structures.sections.prefixedconverted(
+ "\strc_counters_the{#1}",
{
- prefix = "\structurecounterparameter{#1}\c!prefix",
- separatorset = "\structurecounterparameter{#1}\c!prefixseparatorset",
- conversion = "\structurecounterparameter{#1}\c!prefixconversion",
- conversionset = "\structurecounterparameter{#1}\c!prefixconversionset",
- % starter = \!!bs\structurecounterparameter{#1}\c!prefixstarter\!!es,
- % stopper = \!!bs\structurecounterparameter{#1}\c!prefixstopper\!!es,
- set = "\structurecounterparameter{#1}\c!prefixset",
- segments = "\structurecounterparameter{#1}\c!prefixsegments",
- connector = \!!bs\structurecounterparameter{#1}\c!prefixconnector\!!es,
+ prefix = "\counterparameter{#1}\c!prefix",
+ separatorset = "\counterparameter{#1}\c!prefixseparatorset",
+ conversion = "\counterparameter{#1}\c!prefixconversion",
+ conversionset = "\counterparameter{#1}\c!prefixconversionset",
+ % starter = \!!bs\counterparameter{#1}\c!prefixstarter\!!es,
+ % stopper = \!!bs\counterparameter{#1}\c!prefixstopper\!!es,
+ set = "\counterparameter{#1}\c!prefixset",
+ segments = "\counterparameter{#1}\c!prefixsegments",
+ connector = \!!bs\counterparameter{#1}\c!prefixconnector\!!es,
},
{
- order = "\structurecounterparameter{#1}\c!numberorder",
- separatorset = "\structurecounterparameter{#1}\c!numberseparatorset",
- conversion = \!!bs\structurecounterparameter{#1}\c!numberconversion\!!es,
- conversionset = "\structurecounterparameter{#1}\c!numberconversionset",
- starter = \!!bs\structurecounterparameter{#1}\c!numberstarter\!!es,
- stopper = \!!bs\structurecounterparameter{#1}\c!numberstopper\!!es,
- segments = "\structurecounterparameter{#1}\c!numbersegments",
+ order = "\counterparameter{#1}\c!numberorder",
+ separatorset = "\counterparameter{#1}\c!numberseparatorset",
+ conversion = \!!bs\counterparameter{#1}\c!numberconversion\!!es,
+ conversionset = "\counterparameter{#1}\c!numberconversionset",
+ starter = \!!bs\counterparameter{#1}\c!numberstarter\!!es,
+ stopper = \!!bs\counterparameter{#1}\c!numberstopper\!!es,
+ segments = "\counterparameter{#1}\c!numbersegments",
type = "#2",
}
- )}%
- \endgroup}
+ )}}
-\unexpanded\def\convertedsubstructurecounter
- {\dotripleempty\doconvertedsubstructurecounter}
+\unexpanded\def\convertedsubcounter
+ {\dotripleempty\strc_counters_converted_sub}
-\def\doconvertedsubstructurecounter[#1][#2][#3]% #2 can be n or n:m
+\def\strc_counters_converted_sub[#1][#2][#3]% #2 can be n or n:m
{\ifsecondargument
- \doconvertedstructurecounter[#1][\c!numbersegments=#2,#3]%
+ \strc_counters_converted[#1][\c!numbersegments=#2,#3]%
\else
- \secondargumentfalse\doconvertedstructurecounter[#1][]%
+ \secondargumentfalse\strc_counters_converted[#1][]%
\fi}
-\let\getstructurecounter\convertedstructurecounter
-
-\def\doifdefinedstructurecounter #1{\doifdefined {\csname\s!structurecounter#1\c!number\endcsname}}
-\def\doifundefinedstructurecounter #1{\doifundefined {\csname\s!number#1\c!number\endcsname}}
-\def\doifdefinedstructurecounterelse#1{\doifdefinedelse{\csname\s!number#1\c!number\endcsname}}
-
-\ifx\checkstructurecounter\undefined \def\checkstructurecounter[#1]{} \fi
-
-\def\checkstructurecounter[#1]{}
-
-%D What follows is a compatibility layer. This will be phased out (at
-%D least from core usage).
-
-\def\reset
- {\dosingleargument\doreset}
-
-\def\doreset[#1]%
- {\processcommalist[#1]\dodoreset}
-
-\def\dodoreset#1%
- {\csname\s!reset#1\endcsname}%
-
-\let \numberparameter \structurecounterparameter % {name}\c!key
+\unexpanded\def\doifdefinedcounter#1%
+ {\ifcsname\s!number#1\c!number\endcsname
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
-\let \definenumber \definestructurecounter % [name]
-\let \setupnumber \setupstructurecounter % [name][setups]
+\unexpanded\def\doifundefinedcounter#1%
+ {\ifcsname\s!number#1\c!number\endcsname
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
-\let \setnumber \setstructurecounter % [name]{value}
-\let \resetnumber \resetstructurecounter % [name]
-\let \savenumber \savestructurecounter % [name]
-\let \restorenumber \restorestructurecounter % [name]
-\let \incrementnumber \incrementstructurecounter % [name]
-\let \decrementnumber \decrementstructurecounter % [name]
-\let \rawnumber \rawstructurecounter % [name]
-\let \getnumber \getstructurecounter % [name]
-\let \convertednumber \getstructurecounter % [name]
+\unexpanded\def\doifdefinedcounterelse#1%
+ {\ifcsname\s!number#1\c!number\endcsname
+ \expandafter\firstoftwoarguments
+ \else
+ \expandafter\secondoftwoarguments
+ \fi}
-\let \doifdefinednumber \doifstructurecounter % {number}{true}
-\let \doifundefinednumber \doifnotstructurecounter % {number}{true}
-\let \doifdefinednumberelse \doifstructurecounterelse % {number}{true}{false}
+%D What follows is a compatibility layer.
-% weird one
+\let \numberparameter \counterparameter % {name}\c!key
-\def\accumulatednumber[#1]{}
+\let \definenumber \definecounter % [name]
+\let \setupnumber \setupcounter % [name][setups]
-% funny, here, todo: these are the defaults
+\let \setnumber \setcounter % [name]{value}
+\let \resetnumber \resetcounter % [name]
+\let \savenumber \savecounter % [name]
+\let \restorenumber \restorecounter % [name]
+\let \incrementnumber \incrementcounter % [name]
+\let \decrementnumber \decrementcounter % [name]
+\let \rawnumber \rawcounter % [name]
+\let \getnumber \convertedcounter % [name]
+\let \convertednumber \convertedcounter % [name]
-\unexpanded\def\setupnumbering
- {\dodoubleempty\getparameters[\??nr]}
+\let \doifdefinednumber \doifdefinedcounter % {number}{true}
+\let \doifundefinednumber \doifnotdefinedcounter % {number}{true}
+\let \doifdefinednumberelse \doifdefinedcounterelse % {number}{true}{false}
-\setupnumbering
- [\c!way=\v!by\v!chapter,
- \c!blockway=,
- \c!state=\v!start]
+\let \setupnumbering \setupstructurecounting
%D Helpers:
% call:
%
-% \dostructurecountercomponent
+% \strc_counters_register_component
% \currentfloat
% \getfloatparameters \floatparameter \detokenizedfloatparameter
% \hascaption \hastitle \hasnumber
@@ -344,21 +503,22 @@
%
% sets:
%
-% \laststructurecounternumber
-% \laststructurecountersynchronize
+% \m_strc_counters_last_registered_index
+% \m_strc_counters_last_registered_attribute
+% \m_strc_counters_last_registered_synchronize
-\newconditional\hasstructurecountercaption
-\newconditional\hasstructurecountertitle
-\newconditional\hasstructurecounternumber
+\newconditional\hascountercaption
+\newconditional\hascountertitle
+\newconditional\hascounternumber
-\def\dostructurecountercomponent#1#2#3#4#5#6#7[#8][#9]%
+\unexpanded\def\strc_counters_register_component#1#2#3#4#5#6#7[#8][#9]% maybe also nolist
{\begingroup
%
#2[\s!haslevel=1,#8]%
- \edef\hasstructurecountercaption{#3\s!hascaption}%
- \edef\hasstructurecountertitle {#3\s!hastitle}%
- \edef\hasstructurecounternumber {#3\s!hasnumber}%
- \edef\hasstructurecounterlevel {#3\s!haslevel}%
+ \edef\hascounterlevel {#3\s!haslevel}%
+ \edef\hascountercaption{#3\s!hascaption}%
+ \edef\hascountertitle {#3\s!hastitle}%
+ \edef\hascounternumber {#3\s!hasnumber}%
%
\edef\askedprefixsegments{#3\c!prefixsegments}%
\ifx\askedprefixsegments\v!auto
@@ -374,60 +534,86 @@
\let\currentcounter\currentname
\fi
%
- \doif{#3\c!title}\v!none{\setfalse\hasstructurecountercaption\setfalse\hasstructurecounternumber}% will become obsolete
- %
- \ifx\hasstructurecounternumber\v!yes % here due to previous test but best in callers
- \doincrementsubstructurecounter[\currentcounter][\hasstructurecounterlevel]%
- \fi
- %
- \ifx\hasstructurecountercaption\v!yes
- \edef\currentexpansion{#3\c!expansion}%
- \ifx\currentexpansion\s!xml
- \edef\currenttitle{#4\c!title}%
- \edef\currentbookmark{#4\c!bookmark}%
+ \ifx\hascountercaption\v!yes
+ \xdef\currentstructurecomponentname {#3\c!name}%
+ \xdef\currentstructurecomponentlevel {#3\c!level}%
+ \edef\currentstructurecomponentexpansion {#3\c!expansion}%
+ \xdef\currentstructurecomponentxmlsetup {#3\c!xmlsetup}%
+ \xdef\currentstructurecomponentcatcodes {#3\s!catcodes}%
+ \xdef\currentstructurecomponentlabel {#3\c!label}%
+ \xdef\currentstructurecomponentreference {#3\c!reference}%
+ \xdef\currentstructurecomponentreferenceprefix{#3\c!referenceprefix}%
+ \ifx\currentstructurecomponentexpansion\s!xml
\xmlstartraw
- \edef\currentlisttitle{#3\c!title}%
+ \xdef\currentstructurecomponenttitle {#3\c!title}%
+ \xdef\currentstructurecomponentbookmark{#3\c!bookmark}%
+ \xdef\currentstructurecomponentmarking {#3\c!marking}%
+ \xdef\currentstructurecomponentlist {#3\c!list}%
\xmlstopraw
- \let\currentcoding\s!xml
+ \ifx\currentstructurecomponentlist\empty
+ \globallet\currentstructurecomponentlist\currentstructurecomponenttitle
+ \fi
+ \globallet\currentstructurecomponentcoding\s!xml
\else
- \ifx\currentexpansion\v!yes
- \edef\currenttitle{#3\c!title}%
- \edef\currentbookmark{#3\c!bookmark}%
+ \ifx\currentstructurecomponentexpansion\v!yes
+ \xdef\currentstructurecomponenttitle {#3\c!title}%
+ \xdef\currentstructurecomponentbookmark{#3\c!bookmark}%
+ \xdef\currentstructurecomponentmarking {#3\c!marking}%
+ \xdef\currentstructurecomponentlist {#3\c!list}%
\else
- \edef\currenttitle{#4\c!title}%
- \edef\currentbookmark{#4\c!bookmark}%
+ \xdef\currentstructurecomponenttitle {#4\c!title}%
+ \xdef\currentstructurecomponentbookmark{#4\c!bookmark}%
+ \xdef\currentstructurecomponentmarking {#4\c!marking}%
+ \xdef\currentstructurecomponentlist {#4\c!list}%
+ \iflocation \ifx\currentstructurecomponentbookmark\empty
+ \begingroup
+ \simplifycommands
+ \xdef\currentstructurecomponentbookmark{\detokenize\expandafter{\normalexpanded{#3\c!title}}}%
+ \endgroup
+ \fi \fi
+ \fi
+ \ifx\currentstructurecomponentlist\empty
+ \globallet\currentstructurecomponentlist\currentstructurecomponenttitle
\fi
- \let\currentlisttitle\currenttitle
- \let\currentcoding\s!tex
+ \globallet\currentstructurecomponentcoding\s!tex
\fi
- \edef\currentlabel{#3\c!label}%
- \edef\currentreference{#3\c!reference}%
+ %
\setnextinternalreference
- \xdef\laststructurecounternumber{\ctxlua{structures.lists.push{
+ \xdef\m_strc_counters_last_registered_index{\ctxcommand{addtolist{
metadata = {
kind = "#1",
name = "\currentname",
level = structures.sections.currentlevel(),
- catcodes = \the\catcodetable,
+ catcodes = \the\ifx\currentstructurecomponentcatcodes\empty\catcodetable\else\csname\currentstructurecomponentcatcodes\endcsname\fi,
+ coding = "\currentstructurecomponentcoding",
+ \ifx\currentstructurecomponentcoding\s!xml
+ xmlroot = "\xmldocument",
+ \fi
+ \ifx\currentstructurecomponentxmlsetup\empty \else
+ xmlsetup = "\currentstructurexmlsetup",
+ \fi
},
references = {
internal = \nextinternalreference,
- reference = "\currentreference",
- referenceprefix = "\referenceprefix",
- block = "\currentstructureblock",
+ block = "\currentsectionblock",
+ reference = "\currentstructurecomponentreference",
+ referenceprefix = "\currentstructurecomponentreferenceprefix",
section = structures.sections.currentid(),
},
titledata = {
- label = \!!bs\detokenize\expandafter{\currentlabel }\!!es,
- title = \!!bs\detokenize\expandafter{\currenttitle }\!!es,
- \ifx\currentbookmark\currenttitle \else
- bookmark = \!!bs\detokenize\expandafter{\currentbookmark }\!!es,
+ label = \!!bs\detokenize\expandafter{\currentstructurecomponentlabel }\!!es,
+ title = \!!bs\detokenize\expandafter{\currentstructurecomponenttitle }\!!es,
+ \ifx\currentstructurecomponentbookmark\currentstructurecomponenttitle \else
+ bookmark = \!!bs\detokenize\expandafter{\currentstructurecomponentbookmark }\!!es,
+ \fi
+ \ifx\currentstructurecomponentmarking\currentstructurecomponenttitle \else
+ marking = \!!bs\detokenize\expandafter{\currentstructurecomponentmarking }\!!es,
\fi
- \ifx\currentlisttitle\currenttitle \else
- list = \!!bs\detokenize\expandafter{\currentlisttitle}\!!es,
+ \ifx\currentstructurecomponentlist\currentstructurecomponenttitle \else
+ list = \!!bs\detokenize\expandafter{\currentstructurecomponentlist}\!!es,
\fi
},
- \ifx\hasstructurecountercaption\v!yes
+ \ifx\hascounternumber\v!yes
prefixdata = {
prefix = "#3\c!prefix",
separatorset = "#3\c!prefixseparatorset",
@@ -448,24 +634,24 @@
segments = "#3\c!numbersegments",
},
\fi
- userdata = structures.helpers.touserdata(\!!bs\detokenize{#9}\!!es)
+ userdata = \!!bs\detokenize{#9}\!!es % will be converted to table at the lua end
}
}}%
- \xdef\laststructurecounterattribute {\ctxlua {tex.write(structures.references.setinternalreference(nil,nil,\nextinternalreference))}}%
- \xdef\laststructurecountersynchronize{\ctxlatelua{structures.lists.enhance(\laststructurecounternumber)}}%
+ \xdef\m_strc_counters_last_registered_attribute {\ctxlua {tex.write(structures.references.setinternalreference(nil,nil,\nextinternalreference))}}%
+ \xdef\m_strc_counters_last_registered_synchronize{\ctxlatecommand{enhancelist(\m_strc_counters_last_registered_index)}}%
\else
- \glet\laststructurecounternumber \relax
- \glet\laststructurecounterattribute \attributeunsetvalue
- \glet\laststructurecountersynchronize\relax
+ \glet\m_strc_counters_last_registered_index \relax
+ \glet\m_strc_counters_last_registered_attribute \attributeunsetvalue
+ \glet\m_strc_counters_last_registered_synchronize\relax
\fi
\endgroup}
-\let\laststructurecounternumber \relax
-\let\laststructurecounterattribute \relax
-\let\laststructurecountersynchronize\relax
+\let\m_strc_counters_last_registered_index \relax
+\let\m_strc_counters_last_registered_attribute \relax
+\let\m_strc_counters_last_registered_synchronize\relax
-\def\dostructurecountersetup#1#2% name \someparameter
- {\setupstructurecounter
+\def\strc_counter_setup_using_parameter#1#2% name \someparameter
+ {\setupcounter
[#1]
[ \c!start=#2\c!start,
\c!state=#2\c!state, % beware, "" == start
@@ -489,7 +675,7 @@
\c!numberstopper=#2\c!numberstopper,
\c!numbersegments=#2\c!numbersegments]}
-\def\presetstructurecountersetup#1#2% \setupcommand \someparameter
+\def\strc_counter_preset_using_parameter#1#2% \setupcommand \someparameter
{#1%
[\c!way =#2\c!way,
\c!prefix =#2\c!prefix,
diff --git a/Master/texmf-dist/tex/context/base/strc-pag.lua b/Master/texmf-dist/tex/context/base/strc-pag.lua
index bce8a2c3a4e..460d4ff008e 100644
--- a/Master/texmf-dist/tex/context/base/strc-pag.lua
+++ b/Master/texmf-dist/tex/context/base/strc-pag.lua
@@ -8,26 +8,29 @@ if not modules then modules = { } end modules ['strc-pag'] = {
local texcount, format = tex.count, string.format
-local ctxcatcodes = tex.ctxcatcodes
local allocate, mark = utilities.storage.allocate, utilities.storage.mark
-local trace_pages = false trackers.register("structures.pages", function(v) trace_pages = v end)
+local trace_pages = false trackers.register("structures.pages", function(v) trace_pages = v end)
-local report_pages = logs.reporter("structure","pages")
+local report_pages = logs.reporter("structure","pages")
-local structures = structures
+local structures = structures
-local helpers = structures.helpers
-local sections = structures.sections
-local pages = structures.pages
-local processors = structures.processors
-local sets = structures.sets
-local counters = structures.counters
+local helpers = structures.helpers
+local sections = structures.sections
+local pages = structures.pages
+local sets = structures.sets
+local counters = structures.counters
-local counterdata = counters.data
+local counterdata = counters.data
-local variables = interfaces.variables
-local context = context
+local variables = interfaces.variables
+local context = context
+
+local processors = typesetters.processors
+local applyprocessor = processors.apply
+local startapplyprocessor = processors.startapply
+local stopapplyprocessor = processors.stopapply
-- storage
@@ -52,8 +55,8 @@ function pages.save(prefixdata,numberdata)
report_pages("saving page %s.%s",realpage,userpage)
end
local data = {
- number = userpage,
- block = sections.currentblock(),
+ number = userpage,
+ block = sections.currentblock(),
prefixdata = prefixdata and helpers.simplify(prefixdata),
numberdata = numberdata and helpers.simplify(numberdata),
}
@@ -91,17 +94,19 @@ function pages.number(realdata,pagespec)
local starter = (pagespec and pagespec.starter ~= "" and pagespec.starter ) or (numberspec and numberspec.starter ~= "" and numberspec.starter ) or ""
local stopper = (pagespec and pagespec.stopper ~= "" and pagespec.stopper ) or (numberspec and numberspec.stopper ~= "" and numberspec.stopper ) or ""
if starter ~= "" then
- processors.sprint(ctxcatcodes,starter)
+ applyprocessor(starter)
end
if conversion ~= "" then
context.convertnumber(conversion,userpage)
else
if conversionset == "" then conversionset = "default" end
local theconversion = sets.get("structure:conversions",block,conversionset,1,"numbers") -- to be checked: 1
- processors.sprint(ctxcatcodes,theconversion,convertnumber,userpage)
+ local data = startapplyprocessor(theconversion)
+ context.convertnumber(data or "number",userpage)
+ stopapplyprocessor()
end
if stopper ~= "" then
- processors.sprint(ctxcatcodes,stopper)
+ applyprocessors(stopper)
end
end
@@ -116,17 +121,29 @@ function pages.analyze(entry,pagespecification)
if not references then
return false, false, "no references"
end
- local realpage = references.realpage
- if not realpage then
- return false, false, "no realpage"
+ local pagedata = references.pagedata -- sometimes resolved (external)
+ if not pagedata then
+ local realpage = references.realpage
+ if realpage then
+ pagedata = collected[realpage]
+ else
+ return false, false, "no realpage"
+ end
end
- local pagedata = collected[realpage]
if not pagedata then
return false, false, "no pagedata"
end
- local section = references.section
- if not section then
- return pagedata, false, "no section"
+ local sectiondata = references.sectiondata -- sometimes resolved (external)
+ if not sectiondata then
+ local section = references.section
+ if section then
+ sectiondata = sections.collected[section]
+ else
+ return pagedata, false, "no section"
+ end
+ end
+ if not sectiondata then
+ return pagedata, false, "no sectiondata"
end
local no = variables.no
-- local preferences
@@ -134,16 +151,16 @@ function pages.analyze(entry,pagespecification)
return pagedata, false, "current spec blocks prefix"
end
-- stored preferences
---~ if entry.prefix == no then
---~ return pagedata, false, "entry blocks prefix"
---~ end
+ -- if entry.prefix == no then
+ -- return pagedata, false, "entry blocks prefix"
+ -- end
-- stored page state
pagespecification = pagedata.prefixdata
if pagespecification and pagespecification.prefix == no then
return pagedata, false, "pagedata blocks prefix"
end
-- final verdict
- return pagedata, sections.collected[references.section], "okay"
+ return pagedata, sectiondata, "okay"
end
function helpers.page(data,pagespec)
@@ -271,7 +288,7 @@ function counters.analyze(name,counterspecification)
return cd, sectiondata, "okay"
end
-function counters.prefixedconverted(name,prefixspec,numberspec)
+function sections.prefixedconverted(name,prefixspec,numberspec)
local cd, prefixdata, result = counters.analyze(name,prefixspec)
if cd then
if prefixdata then
diff --git a/Master/texmf-dist/tex/context/base/strc-pag.mkii b/Master/texmf-dist/tex/context/base/strc-pag.mkii
index 5a86a99e87f..40e69b849b3 100644
--- a/Master/texmf-dist/tex/context/base/strc-pag.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-pag.mkii
@@ -5,7 +5,7 @@
%D subtitle=Numbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-pag.mkiv b/Master/texmf-dist/tex/context/base/strc-pag.mkiv
index f4b658365f9..e3828464cd8 100644
--- a/Master/texmf-dist/tex/context/base/strc-pag.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-pag.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Pagenumbering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -43,8 +43,8 @@
% all get their own counter. After all, it's easier to combine them in
% a pseudo counterset than to deal with a complex set itself.
-% \definestructureprefixset [mine][section-1,section-2]
-% \definestructureseparatorset[mine][:]
+% \defineprefixset [mine][section-1,section-2]
+% \defineseparatorset[mine][:]
%
% \setupuserpagenumber
% [way=bypart,
@@ -52,8 +52,8 @@
% prefixset=mine,
% prefixseparatorset=mine]
-% \definestructureconversionset[frontpart:pagenumber][][romannumerals]
-% \definestructureconversionset[bodypart:pagenumber] [][numbers]
+% \defineconversionset[frontpart:pagenumber][][romannumerals]
+% \defineconversionset[bodypart:pagenumber] [][numbers]
%
% \setupuserpagenumber[way=byblock]
% \setupuserpagenumber[way=bychapter]
@@ -71,9 +71,9 @@
% \stopbodymatter
% \stoptext
-\definestructurecounter[\s!realpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=realpageno,\c!method=\v!page]
-\definestructurecounter[\s!userpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=userpageno,\c!method=\v!page]
-\definestructurecounter[\s!subpage] [\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=subpageno, \c!method=\v!page]
+\definecounter[\s!realpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=realpageno,\c!method=\v!page]
+\definecounter[\s!userpage][\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=userpageno,\c!method=\v!page]
+\definecounter[\s!subpage] [\c!prefix=\v!no,\c!start=1,\c!prefixsegments=,\s!counter=subpageno, \c!method=\v!page]
\newtoks\everysetuprealpagenumber % todo: set state: none, start, stop, reset
\newtoks\everysetupuserpagenumber % todo: set state: none, start, stop, reset
@@ -83,20 +83,20 @@
\unexpanded\def\setupuserpagenumber{\dosingleargument\dosetupuserpagenumber}
\unexpanded\def\setupsubpagenumber {\dosingleargument\dosetupsubpagenumber}
-\def\dosavepagenumberstate#1{\edef\oldpagenumberstate{\structurecounterparameter#1\c!state}}
+\def\dosavepagenumberstate#1{\edef\oldpagenumberstate{\counterparameter#1\c!state}}
-\def\dosetuprealpagenumber[#1]{\dosavepagenumberstate\s!realpage\dosetupstructurecounter[\s!realpage][#1]\the\everysetuprealpagenumber}
-\def\dosetupuserpagenumber[#1]{\dosavepagenumberstate\s!userpage\dosetupstructurecounter[\s!userpage][#1]\the\everysetupuserpagenumber}
-\def\dosetupsubpagenumber [#1]{\dosavepagenumberstate\s!subpage \dosetupstructurecounter[\s!subpage ][#1]\the\everysetupsubpagenumber }
+\def\dosetuprealpagenumber[#1]{\dosavepagenumberstate\s!realpage\strc_counters_setup[\s!realpage][#1]\the\everysetuprealpagenumber}
+\def\dosetupuserpagenumber[#1]{\dosavepagenumberstate\s!userpage\strc_counters_setup[\s!userpage][#1]\the\everysetupuserpagenumber}
+\def\dosetupsubpagenumber [#1]{\dosavepagenumberstate\s!subpage \strc_counters_setup[\s!subpage ][#1]\the\everysetupsubpagenumber }
\def\resetrealpagenumber {} % not permitted
-\def\resetuserpagenumber {\resetstructurecounter[\s!userpage]}
-\def\resetsubpagenumber {\resetstructurecounter[\s!subpage]}
+\def\resetuserpagenumber {\strc_counters_reset\s!userpage}
+\def\resetsubpagenumber {\strc_counters_reset\s!subpage}
\appendtoks
- \setstructurecounter[\s!realpage]\realpageno
- \setstructurecounter[\s!userpage]\userpageno
- \setstructurecounter[\s!subpage] \subpageno
+ \strc_counters_set\s!realpage\realpageno
+ \strc_counters_set\s!userpage\userpageno
+ \strc_counters_set\s!subpage \subpageno
\to \everyinitializepagecounters
\let\setuppagenumber\setupuserpagenumber
@@ -104,18 +104,18 @@
\def\savecurrentpagestate % \normalexpanded?
{\ctxlua{structures.pages.save({
- prefix = "\structurecounterparameter\s!userpage\c!prefix",
- separatorset = "\structurecounterparameter\s!userpage\c!prefixseparatorset",
- conversion = "\structurecounterparameter\s!userpage\c!prefixconversion",
- conversionset = "\structurecounterparameter\s!userpage\c!prefixconversionset",
- set = "\structurecounterparameter\s!userpage\c!prefixset",
- segments = "\structurecounterparameter\s!userpage\c!prefixsegments",
- connector = \!!bs\structurecounterparameter\s!userpage\c!prefixconnector\!!es,
+ prefix = "\counterparameter\s!userpage\c!prefix",
+ separatorset = "\counterparameter\s!userpage\c!prefixseparatorset",
+ conversion = "\counterparameter\s!userpage\c!prefixconversion",
+ conversionset = "\counterparameter\s!userpage\c!prefixconversionset",
+ set = "\counterparameter\s!userpage\c!prefixset",
+ segments = "\counterparameter\s!userpage\c!prefixsegments",
+ connector = \!!bs\counterparameter\s!userpage\c!prefixconnector\!!es,
},{
- conversion = "\structurecounterparameter\s!userpage\c!numberconversion",
- conversionset = "\structurecounterparameter\s!userpage\c!numberconversionset",
- starter = \!!bs\structurecounterparameter\s!userpage\c!numberstarter\!!es,
- stopper = \!!bs\structurecounterparameter\s!userpage\c!numberstopper\!!es,
+ conversion = "\counterparameter\s!userpage\c!numberconversion",
+ conversionset = "\counterparameter\s!userpage\c!numberconversionset",
+ starter = \!!bs\counterparameter\s!userpage\c!numberstarter\!!es,
+ stopper = \!!bs\counterparameter\s!userpage\c!numberstopper\!!es,
}
)}}
@@ -123,8 +123,8 @@
\savecurrentpagestate
\to \everyshipout
-\def\pushpagestate{\setxvalue{\??nm:\s!userpage:\c!state}{\structurecounterparameter\s!userpage\c!state}}
-\def\poppagestate {\normalexpanded{\noexpand\setuppagenumber[\c!state=\getvalue{\??nm:\s!userpage:\c!state}]}}
+\def\pushpagestate{\setxvalue{\??nm:\s!userpage:\c!state}{\counterparameter\s!userpage\c!state}}
+\def\poppagestate {\normalexpanded{\setuppagenumber[\c!state=\getvalue{\??nm:\s!userpage:\c!state}]}}
\setuppagenumber
[\c!way=\v!by\v!text,
@@ -139,51 +139,37 @@
% Counters
-% \def\firstpage {1} \def\prevpage {1} \def\nextpage {1} \def\lastpage {1}
-% \def\firstuserpage{1} \def\prevuserpage{1} \def\nextuserpage{1} \def\lastuserpage{1}
-% \def\firstsubpage {1} \def\prevsubpage {1} \def\nextsubpage {1} \def\lastsubpage {1}
+\def\firstrealpagenumber{\convertedcounter[\s!realpage][\c!type=\v!first]}
+\def\firstuserpagenumber{\convertedcounter[\s!userpage][\c!type=\v!first]}
+\def\firstsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!first]}
-% \def\firstrealpage{\firststructurecounter[\s!realpage]}
-% \def\prevrealpage {\prevstructurecounter [\s!realpage]}
-% \def\nextrealpage {\nextstructurecounter [\s!realpage]}
-% \def\lastrealpage {\laststructurecounter [\s!realpage]}
+\def\lastrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!last]}
+\def\lastuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!last]}
+\def\lastsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!last]}
-% \let\firstpage\firstrealpage
-% \let\prevpage \prevrealpage
-% \let\nextpage \nextrealpage
-% \let\lastpage \lastrealpage
+\def\prevrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!previous]}
+\def\prevuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!previous]}
+\def\prevsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!previous]}
-\def\firstrealpagenumber{\convertedstructurecounter[\s!realpage][\c!type=\v!first]}
-\def\firstuserpagenumber{\convertedstructurecounter[\s!userpage][\c!type=\v!first]}
-\def\firstsubpagenumber {\convertedstructurecounter[\s!subpage ][\c!type=\v!first]}
+\def\nextrealpagenumber {\convertedcounter[\s!realpage][\c!type=\v!next]}
+\def\nextuserpagenumber {\convertedcounter[\s!userpage][\c!type=\v!next]}
+\def\nextsubpagenumber {\convertedcounter[\s!subpage ][\c!type=\v!next]}
-\def\lastrealpagenumber {\convertedstructurecounter[\s!realpage][\c!type=\v!last]}
-\def\lastuserpagenumber {\convertedstructurecounter[\s!userpage][\c!type=\v!last]}
-\def\lastsubpagenumber {\convertedstructurecounter[\s!subpage ][\c!type=\v!last]}
+\def\firstrealpage{\strc_counters_first\s!realpage}
+\def\firstuserpage{\strc_counters_first\s!userpage}
+\def\firstsubpage {\strc_counters_first\s!subpage }
-\def\prevrealpagenumber {\convertedstructurecounter[\s!realpage][\c!type=\v!previous]}
-\def\prevuserpagenumber {\convertedstructurecounter[\s!userpage][\c!type=\v!previous]}
-\def\prevsubpagenumber {\convertedstructurecounter[\s!subpage ][\c!type=\v!previous]}
+\def\prevrealpage {\strc_counters_prev \s!realpage}
+\def\prevuserpage {\strc_counters_prev \s!userpage}
+\def\prevsubpage {\strc_counters_prev \s!subpage }
-\def\nextrealpagenumber {\convertedstructurecounter[\s!realpage][\c!type=\v!next]}
-\def\nextuserpagenumber {\convertedstructurecounter[\s!userpage][\c!type=\v!next]}
-\def\nextsubpagenumber {\convertedstructurecounter[\s!subpage ][\c!type=\v!next]}
+\def\nextrealpage {\strc_counters_next \s!realpage}
+\def\nextuserpage {\strc_counters_next \s!userpage}
+\def\nextsubpage {\strc_counters_next \s!subpage }
-\def\firstrealpage{\firststructurecounter[\s!realpage]}
-\def\firstuserpage{\firststructurecounter[\s!userpage]}
-\def\firstsubpage {\firststructurecounter[\s!subpage ]}
-
-\def\prevrealpage {\prevstructurecounter [\s!realpage]}
-\def\prevuserpage {\prevstructurecounter [\s!userpage]}
-\def\prevsubpage {\prevstructurecounter [\s!subpage ]}
-
-\def\nextrealpage {\nextstructurecounter [\s!realpage]}
-\def\nextuserpage {\nextstructurecounter [\s!userpage]}
-\def\nextsubpage {\nextstructurecounter [\s!subpage ]}
-
-\def\lastrealpage {\laststructurecounter [\s!realpage]}
-\def\lastuserpage {\laststructurecounter [\s!userpage]}
-\def\lastsubpage {\laststructurecounter [\s!subpage ]}
+\def\lastrealpage {\strc_counters_last \s!realpage}
+\def\lastuserpage {\strc_counters_last \s!userpage}
+\def\lastsubpage {\strc_counters_last \s!subpage }
\let\firstpage\firstrealpage
\let\prevpage \prevrealpage
@@ -198,33 +184,33 @@
% Renderers:
-\def\pagenumber {\rawstructurecounter[\s!userpage]}
-\def\prefixedpagenumber {\directconvertedstructurecounter\s!userpage\empty} % \userpagenumber
+\def\pagenumber {\strc_counters_raw\s!userpage}
+\def\prefixedpagenumber {\directconvertedcounter\s!userpage\empty} % \userpagenumber
-\def\realpagenumber {\directconvertedstructurecounter\s!realpage\empty}
-\def\userpagenumber {\directconvertedstructurecounter\s!userpage\empty}
-\def\subpagenumber {\directconvertedstructurecounter\s!subpage \empty}
+\def\realpagenumber {\directconvertedcounter\s!realpage\empty}
+\def\userpagenumber {\directconvertedcounter\s!userpage\empty}
+\def\subpagenumber {\directconvertedcounter\s!subpage \empty}
-\def\firstrealpagenumber{\directconvertedstructurecounter\s!realpage\v!first}
-\def\firstuserpagenumber{\directconvertedstructurecounter\s!userpage\v!first}
-\def\firstsubpagenumber {\directconvertedstructurecounter\s!subpage \v!first}
+\def\firstrealpagenumber{\directconvertedcounter\s!realpage\v!first}
+\def\firstuserpagenumber{\directconvertedcounter\s!userpage\v!first}
+\def\firstsubpagenumber {\directconvertedcounter\s!subpage \v!first}
-\def\lastrealpagenumber {\directconvertedstructurecounter\s!realpage\v!last}
-\def\lastuserpagenumber {\directconvertedstructurecounter\s!userpage\v!last}
-\def\lastsubpagenumber {\directconvertedstructurecounter\s!subpage \v!last}
+\def\lastrealpagenumber {\directconvertedcounter\s!realpage\v!last}
+\def\lastuserpagenumber {\directconvertedcounter\s!userpage\v!last}
+\def\lastsubpagenumber {\directconvertedcounter\s!subpage \v!last}
-\def\prevrealpagenumber {\directconvertedstructurecounter\s!realpage\v!previous}
-\def\prevuserpagenumber {\directconvertedstructurecounter\s!userpage\v!previous}
-\def\prevsubpagenumber {\directconvertedstructurecounter\s!subpage \v!previous}
+\def\prevrealpagenumber {\directconvertedcounter\s!realpage\v!previous}
+\def\prevuserpagenumber {\directconvertedcounter\s!userpage\v!previous}
+\def\prevsubpagenumber {\directconvertedcounter\s!subpage \v!previous}
-\def\nextrealpagenumber {\directconvertedstructurecounter\s!realpage\v!next}
-\def\nextuserpagenumber {\directconvertedstructurecounter\s!userpage\v!next}
-\def\nextsubpagenumber {\directconvertedstructurecounter\s!subpage \v!next}
+\def\nextrealpagenumber {\directconvertedcounter\s!realpage\v!next}
+\def\nextuserpagenumber {\directconvertedcounter\s!userpage\v!next}
+\def\nextsubpagenumber {\directconvertedcounter\s!subpage \v!next}
\def\dodeincrementpageboundcounters % only at the end
- {\decrementstructurecounter[\s!realpage]%
- \decrementstructurecounter[\s!userpage]%
- \decrementstructurecounter[\s!subpage ]}
+ {\strc_counters_decrement\s!realpage
+ \strc_counters_decrement\s!userpage
+ \strc_counters_decrement\s!subpage}
\def\doincrementpageboundcounters
{\incrementpagenumber
@@ -258,21 +244,21 @@
% Realpage and subpage numbers:
-\def\setnextrealpageno{\global\realpageno\incrementedstructurecounter[\s!realpage]\relax}
-\def\setnextsubpageno {\global\subpageno \incrementedstructurecounter[\s!subpage ]\relax}
+\def\setnextrealpageno{\global\realpageno\strc_counters_incremented\s!realpage\relax}
+\def\setnextsubpageno {\global\subpageno \strc_counters_incremented\s!subpage \relax}
-% Page numbers: (can move to lua)
+% Page numbers: (can move to lua) ... inconsistent names
-\def\dodecrementpagenumber {\global\userpageno\decrementedstructurecounter[\s!userpage]\relax}
-\def\doincrementpagenumber {\global\userpageno\incrementedstructurecounter[\s!userpage]\relax}
+\def\dodecrementpagenumber {\global\userpageno\strc_counters_decremented\s!userpage\relax}
+\def\doincrementpagenumber {\global\userpageno\strc_counters_incremented\s!userpage\relax}
-\def\decrementsubpagenumber{\global\subpageno \decrementedstructurecounter[\s!subpage ]\relax}
-\def\incrementsubpagenumber{\global\subpageno \incrementedstructurecounter[\s!subpage ]\relax}
+\def\decrementsubpagenumber{\global\subpageno \strc_counters_decremented\s!subpage \relax}
+\def\incrementsubpagenumber{\global\subpageno \strc_counters_incremented\s!subpage \relax}
\def\dosynchronizepagenumber{\global\let\@@pnstate\v!start}
-\def\decrementpagenumber{\csname\??pn-\structurecounterparameter\s!userpage\c!state\endcsname}
-\def\incrementpagenumber{\csname\??pn+\structurecounterparameter\s!userpage\c!state\endcsname}
+\def\decrementpagenumber{\csname\??pn-\counterparameter\s!userpage\c!state\endcsname}
+\def\incrementpagenumber{\csname\??pn+\counterparameter\s!userpage\c!state\endcsname}
\letvalue{\??pn-\v!start}\dodecrementpagenumber
\letvalue{\??pn-\v!none }\dodecrementpagenumber
@@ -316,12 +302,17 @@
\trackingmarginnotesfalse
\fi
\fi
+ \page_backgrounds_recalculate
\dosetpagenumberlocation
\to \everysetuppagenumbering
-\appendtoks
- \ifdefined \recalculatebackgrounds \recalculatebackgrounds \fi
-\to \everysetuppagenumbering
+\ifdefined \page_backgrounds_recalculate \else
+ \let\page_backgrounds_recalculate\relax
+\fi
+
+\ifdefined \dosetpagenumberlocation \else
+ \let\dosetpagenumberlocation\relax
+\fi
\def\flushfinallayoutpage
{\doifsomething\@@nmpage{\doifnot\@@nmpage\v!no{\page[\@@nmpage]}}}
@@ -329,42 +320,6 @@
% The numbered location handler is there because we need to be downward
% compatible. So, in fact there can be multiple handlers active at the
% same time, but only the current one does something.
-%
-% thsi code might move to page-txt
-
-\newcount\currentpagenumberlocation
-
-\def\dosetpagenumberlocation
- {\advance\currentpagenumberlocation\plusone
- \ifx\@@nmlocation\empty \else
- \let\@@pagenumbervlocation\v!footer
- \let\@@pagenumberhlocation\v!text
- \let\@@pagenumberxlocation\c!middletext
- \normalexpanded{\noexpand\processallactionsinset[\@@nmlocation]}
- [ \v!header=>\let\@@pagenumbervlocation\v!header,
- \v!footer=>\let\@@pagenumbervlocation\v!footer,
- \v!middle=>\let\@@pagenumberhlocation\v!text \let\@@pagenumberxlocation\c!middletext,
- \v!left=>\let\@@pagenumberhlocation\v!text \let\@@pagenumberxlocation\c!lefttext,
- \v!right=>\let\@@pagenumberhlocation\v!text \let\@@pagenumberxlocation\c!righttext,
- \v!inleft=>\let\@@pagenumberhlocation\v!margin\let\@@pagenumberxlocation\c!lefttext,
- \v!inright=>\let\@@pagenumberhlocation\v!margin\let\@@pagenumberxlocation\c!righttext,
- \v!inmargin=>\let\@@pagenumberhlocation\v!margin\def\@@pagenumberxlocation{\ifdoublesided\c!margintext\else\c!righttext\fi},
- \v!margin=>\let\@@pagenumberhlocation\v!margin\def\@@pagenumberxlocation{\ifdoublesided\c!margintext\else\c!righttext\fi},
- \v!atmargin=>\let\@@pagenumberhlocation\v!text \let\@@pagenumberxlocation\c!marginedgetext,
- \v!marginedge=>\let\@@pagenumberhlocation\v!text \let\@@pagenumberxlocation\c!marginedgetext]%
- \normalexpanded{\noexpand\setspecificlayouttext
- {\@@pagenumbervlocation}{\@@pagenumberhlocation}{\@@pagenumberxlocation}%
- {\noexpand\doplacepagenumberatlocation{\number\currentpagenumberlocation}}}%
- \fi}
-
-\def\setspecificlayouttext#1#2#3#4{\setvalue{\??tk#1#2#3}{#4}} % weird place
-
-\appendtoks
- \dosetpagenumberlocation
-\to \everyinitializepagecounters
-
-\def\doplacepagenumberatlocation#1%
- {\ifnum#1=\currentpagenumberlocation\relax\expandafter\placelocationpagenumber\fi}
% Rendering:
@@ -372,7 +327,11 @@
{\ifnum\userpagenumberstate=\plustwo
\ifnum\overallpagenumberstate=\plusone
\doif\@@nmstrut\v!yes\strut
- \@@nmcommand{\doattributes\??nm\c!style\c!color{\@@nmleft\labeltexts\v!pagenumber{\prefixedpagenumber}\@@nmright}}%
+ \begingroup
+ \dousestyleparameter\@@nmstyle
+ \dousecolorparameter\@@nmcolor
+ \@@nmcommand{\@@nmleft\labeltexts\v!pagenumber{\prefixedpagenumber}\@@nmright}%
+ \endgroup
\fi
\fi}
@@ -403,7 +362,7 @@
\setnewconstant\overallpagenumberstate\plusone % general number: 0=invisible, 1=visible
\def\checkpagenumberstatechange#1#2%
- {\edef\newpagenumberstate{\structurecounterparameter#1\c!state}%
+ {\edef\newpagenumberstate{\counterparameter#1\c!state}%
\ifx\newpagenumberstate\oldpagenumberstate \else
\doifelse\newpagenumberstate\v!start
{#2\plustwo}%
@@ -454,18 +413,18 @@
% just for downward compatbility
\appendtoks
- \edef\askeduserpagenumber{\structurecounterparameter\s!userpage\c!number}%
+ \edef\askeduserpagenumber{\counterparameter\s!userpage\c!number}%
\ifx\askeduserpagenumber\empty \else
- \normalexpanded{\noexpand\setuppagenumber[\c!start=\structurecounterparameter\s!userpage\c!number,\c!number=]}%
- \userpageno\rawstructurecounter[\s!userpage]%
+ \normalexpanded{\setuppagenumber[\c!start=\counterparameter\s!userpage\c!number,\c!number=]}%
+ \userpageno\strc_counters_raw\s!userpage
\fi
\to \everysetupuserpagenumber % todo: set state: none, start, stop, reset
\appendtoks
- \edef\askedsubpagenumber{\structurecounterparameter\s!subpage\c!number}%
+ \edef\askedsubpagenumber{\counterparameter\s!subpage\c!number}%
\ifx\askedsubpagenumber\empty \else
- \normalexpanded{\noexpand\setupsubpagenumber[\c!start=\structurecounterparameter\s!subpage\c!number,\c!number=]}%
- \subpageno\rawstructurecounter[\s!subpage]%
+ \normalexpanded{\setupsubpagenumber[\c!start=\counterparameter\s!subpage\c!number,\c!number=]}%
+ \subpageno\strc_counters_raw\s!subpage\relax
\fi
\to \everysetupsubpagenumber % todo: set state: none, start, stop, reset
@@ -475,7 +434,7 @@
% \starttext \dorecurse{20}{\input knuth \par} \stoptext
\def\checkpagenumbershift
- {\userpageno\rawstructurecounter[\s!userpage]\relax
+ {\userpageno\strc_counters_raw\s!userpage\relax
\ifnum\realpageno=\plusone
\ifodd\userpageno
\else
diff --git a/Master/texmf-dist/tex/context/base/strc-prc.lua b/Master/texmf-dist/tex/context/base/strc-prc.lua
deleted file mode 100644
index b1a1fb0a966..00000000000
--- a/Master/texmf-dist/tex/context/base/strc-prc.lua
+++ /dev/null
@@ -1,9 +0,0 @@
-if not modules then modules = { } end modules ['strc-prc'] = {
- version = 1.001,
- comment = "companion to strc-prc.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- code will move from strc-ini to here
diff --git a/Master/texmf-dist/tex/context/base/strc-ref.lua b/Master/texmf-dist/tex/context/base/strc-ref.lua
index ee32353f0c4..8a478a4e6e7 100644
--- a/Master/texmf-dist/tex/context/base/strc-ref.lua
+++ b/Master/texmf-dist/tex/context/base/strc-ref.lua
@@ -6,76 +6,96 @@ if not modules then modules = { } end modules ['strc-ref'] = {
license = "see context related readme files"
}
+-- beware, this is a first step in the rewrite (just getting rid of
+-- the tuo file); later all access and parsing will also move to lua
+
+-- the useddata and pagedata names might change
+-- todo: pack exported data
+
+-- todo: autoload components when :::
+
local format, find, gmatch, match, concat = string.format, string.find, string.gmatch, string.match, table.concat
-local lpegmatch, lpegP, lpegCs = lpeg.match, lpeg.P, lpeg.Cs
local texcount, texsetcount = tex.count, tex.setcount
-local rawget = rawget
+local rawget, tonumber = rawget, tonumber
+local lpegmatch = lpeg.match
+local copytable = table.copy
-local allocate = utilities.storage.allocate
-local mark = utilities.storage.mark
-local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local mark = utilities.storage.mark
+local setmetatableindex = table.setmetatableindex
-local trace_referencing = false trackers.register("structures.referencing", function(v) trace_referencing = v end)
+local trace_referencing = false trackers.register("structures.referencing", function(v) trace_referencing = v end)
+local trace_analyzing = false trackers.register("structures.referencing.analyzing", function(v) trace_analyzing = v end)
+local trace_identifying = false trackers.register("structures.referencing.identifying", function(v) trace_identifying = v end)
+local trace_importing = false trackers.register("structures.referencing.importing", function(v) trace_importing = v end)
-local report_references = logs.reporter("structure","references")
+local report_references = logs.reporter("references")
+local report_unknown = logs.reporter("unknown")
+local report_identifying = logs.reporter("references","identifying")
+local report_importing = logs.reporter("references","importing")
-local variables = interfaces.variables
-local constants = interfaces.constants
-local context = context
+local variables = interfaces.variables
+local constants = interfaces.constants
+local context = context
-local settings_to_array = utilities.parsers.settings_to_array
-local unsetvalue = attributes.unsetvalue
+local texcount = tex.count
+local texconditionals = tex.conditionals
--- beware, this is a first step in the rewrite (just getting rid of
--- the tuo file); later all access and parsing will also move to lua
+local productcomponent = resolvers.jobs.productcomponent
+local justacomponent = resolvers.jobs.justacomponent
--- the useddata and pagedata names might change
--- todo: pack exported data
+local logsnewline = logs.newline
+local logspushtarget = logs.pushtarget
+local logspoptarget = logs.poptarget
-local structures = structures
-local helpers = structures.helpers
-local sections = structures.sections
-local references = structures.references
-local lists = structures.lists
-local counters = structures.counters
+local settings_to_array = utilities.parsers.settings_to_array
+local unsetvalue = attributes.unsetvalue
+
+local structures = structures
+local helpers = structures.helpers
+local sections = structures.sections
+local references = structures.references
+local lists = structures.lists
+local counters = structures.counters
-- some might become local
-references.defined = references.defined or allocate()
-
-local defined = references.defined
-local derived = allocate()
-local specials = allocate()
-local runners = allocate()
-local internals = allocate()
-local exporters = allocate()
-local imported = allocate()
-local filters = allocate()
-local executers = allocate()
-local handlers = allocate()
-local tobesaved = allocate()
-local collected = allocate()
-local tobereferred = allocate()
-local referred = allocate()
-
-references.derived = derived
-references.specials = specials
-references.runners = runners
-references.internals = internals
-references.exporters = exporters
-references.imported = imported
-references.filters = filters
-references.executers = executers
-references.handlers = handlers
-references.tobesaved = tobesaved
-references.collected = collected
-references.tobereferred = tobereferred
-references.referred = referred
+references.defined = references.defined or allocate()
+
+local defined = references.defined
+local derived = allocate()
+local specials = allocate()
+local runners = allocate()
+local internals = allocate()
+local filters = allocate()
+local executers = allocate()
+local handlers = allocate()
+local tobesaved = allocate()
+local collected = allocate()
+local tobereferred = allocate()
+local referred = allocate()
+
+references.derived = derived
+references.specials = specials
+references.runners = runners
+references.internals = internals
+references.filters = filters
+references.executers = executers
+references.handlers = handlers
+references.tobesaved = tobesaved
+references.collected = collected
+references.tobereferred = tobereferred
+references.referred = referred
+
+local splitreference = references.splitreference
+local splitprefix = references.splitcomponent -- replaces: references.splitprefix
+local prefixsplitter = references.prefixsplitter
+local componentsplitter = references.componentsplitter
+
+local currentreference = nil
storage.register("structures/references/defined", references.defined, "structures.references.defined")
-local currentreference = nil
-
local initializers = { }
local finalizers = { }
@@ -103,42 +123,90 @@ end
job.register('structures.references.collected', tobesaved, initializer, finalizer)
local maxreferred = 1
+local nofreferred = 0
+
+-- local function initializer() -- can we use a tobesaved as metatable for collected?
+-- tobereferred = references.tobereferred
+-- referred = references.referred
+-- nofreferred = #referred
+-- end
local function initializer() -- can we use a tobesaved as metatable for collected?
tobereferred = references.tobereferred
referred = references.referred
- local function get(t,n) -- catch sparse, a bit slow but who cares
- for i=n,1,-1 do -- we could make a tree ... too much work
- local p = rawget(t,i)
- if p then
- return p
- end
- end
- end
- setmetatableindex(referred, get)
+ setmetatableindex(referred,get) -- hm, what is get ?
end
-local function finalizer() -- make sparse
- local last
+-- We make the array sparse (maybe a finalizer should optionally return a table) because
+-- there can be quite some page links involved. We only store one action number per page
+-- which is normally good enough for what we want (e.g. see above/below) and we do
+-- a combination of a binary search and traverse backwards. A previous implementation
+-- always did a traverse and was pretty slow on a large number of links (given that this
+-- methods was used). It took me about a day to locate this as a bottleneck in processing
+-- a 2500 page interactive document with 60 links per page. In that case, traversing
+-- thousands of slots per link then brings processing to a grinding halt (especially when
+-- there are no slots at all, which is the case in a first run).
+
+local sparsetobereferred = { }
+
+local function finalizer()
+ local lastr, lasti
+ local n = 0
for i=1,maxreferred do
local r = tobereferred[i]
- if not last then
- last = r
- elseif r == last then
- tobereferred[i] = nil
- else
- last = r
+ if not lastr then
+ lastr = r
+ lasti = i
+ elseif r ~= lastr then
+ n = n + 1
+ sparsetobereferred[n] = { lastr, lasti }
+ lastr = r
+ lasti = i
end
end
+ if lastr then
+ n = n + 1
+ sparsetobereferred[n] = { lastr, lasti }
+ end
end
-job.register('structures.references.referred', tobereferred, initializer, finalizer)
-
-function references.referredpage(n)
- return referred[n] or referred[n] or texcount.realpageno
+job.register('structures.references.referred', sparsetobereferred, initializer, finalizer)
+
+local function referredpage(n)
+ local max = nofreferred
+ if max > 0 then
+ -- find match
+ local min = 1
+ while true do
+ local mid = floor((min+max)/2)
+ local r = referred[mid]
+ local m = r[2]
+ if n == m then
+ return r[1]
+ elseif n > m then
+ min = mid + 1
+ else
+ max = mid - 1
+ end
+ if min > max then
+ break
+ end
+ end
+ -- find first previous
+ for i=min,1,-1 do
+ local r = referred[i]
+ if r and r[2] < n then
+ return r[1]
+ end
+ end
+ end
+ -- fallback
+ return texcount.realpageno
end
-function references.registerpage(n)
+references.referredpage = referredpage
+
+function references.registerpage(n) -- called in the backend code
if not tobereferred[n] then
if n > maxreferred then
maxreferred = n
@@ -176,113 +244,89 @@ function references.currentorder(kind,name)
context(orders[kind] and orders[kind][name] or lastorder)
end
+local function setcomponent(data)
+ -- we might consider doing this at the tex end, just like prefix
+ local component = productcomponent()
+ if component then
+ local references = data and data.references
+ if references then
+ references.component = component
+ end
+ return component
+ end
+ -- but for the moment we do it here (experiment)
+end
+
+references.setcomponent = setcomponent
+
function references.set(kind,prefix,tag,data)
+-- setcomponent(data)
+ local pd = tobesaved[prefix]
+ if not pd then
+ pd = { }
+ tobesaved[prefix] = pd
+ end
for ref in gmatch(tag,"[^,]+") do
- local p, r = match(ref,"^(%-):(.-)$")
- if p and r then
- prefix, ref = p, r
- else
- prefix = ""
- end
if ref ~= "" then
- local pd = tobesaved[prefix]
- if not pd then
- pd = { }
- tobesaved[prefix] = pd
- end
pd[ref] = data
context.dofinishsomereference(kind,prefix,ref)
end
end
end
-function references.setandgetattribute(kind,prefix,tag,data,view) -- maybe do internal automatically here
- references.set(kind,prefix,tag,data)
- texcount.lastdestinationattribute = references.setinternalreference(prefix,tag,nil,view) or -0x7FFFFFFF
-end
-
-function references.enhance(prefix,tag,spec)
+function references.enhance(prefix,tag)
local l = tobesaved[prefix][tag]
if l then
l.references.realpage = texcount.realpageno
end
end
--- this reference parser is just an lpeg version of the tex based one
-
-local result = { }
-
-local lparent, rparent, lbrace, rbrace, dcolon, backslash = lpegP("("), lpegP(")"), lpegP("{"), lpegP("}"), lpegP("::"), lpegP("\\")
-
-local reset = lpegP("") / function() result = { } end
-local b_token = backslash / function(s) result.has_tex = true return s end
-
-local o_token = 1 - rparent - rbrace - lparent - lbrace
-local a_token = 1 - rbrace
-local s_token = 1 - lparent - lbrace - lparent - lbrace
-local i_token = 1 - lparent - lbrace
-local f_token = 1 - lparent - lbrace - dcolon
-
-local outer = (f_token )^1 / function (s) result.outer = s end
-local operation = lpegCs((b_token + o_token)^1) / function (s) result.operation = s end
-local arguments = lpegCs((b_token + a_token)^0) / function (s) result.arguments = s end
-local special = (s_token )^1 / function (s) result.special = s end
-local inner = (i_token )^1 / function (s) result.inner = s end
-
-local outer_reference = (outer * dcolon)^0
-
-operation = outer_reference * operation -- special case: page(file::1) and file::page(1)
-
-local optional_arguments = (lbrace * arguments * rbrace)^0
-local inner_reference = inner * optional_arguments
-local special_reference = special * lparent * (operation * optional_arguments + operation^0) * rparent
-
-local scanner = (reset * outer_reference * (special_reference + inner_reference)^-1 * -1) / function() return result end
-
---~ function references.analyze(str) -- overloaded
---~ return lpegmatch(scanner,str)
---~ end
-
-function references.split(str)
- return lpegmatch(scanner,str or "")
-end
-
---~ print(table.serialize(references.analyze("")))
---~ print(table.serialize(references.analyze("inner")))
---~ print(table.serialize(references.analyze("special(operation{argument,argument})")))
---~ print(table.serialize(references.analyze("special(operation)")))
---~ print(table.serialize(references.analyze("special()")))
---~ print(table.serialize(references.analyze("inner{argument}")))
---~ print(table.serialize(references.analyze("outer::")))
---~ print(table.serialize(references.analyze("outer::inner")))
---~ print(table.serialize(references.analyze("outer::special(operation{argument,argument})")))
---~ print(table.serialize(references.analyze("outer::special(operation)")))
---~ print(table.serialize(references.analyze("outer::special()")))
---~ print(table.serialize(references.analyze("outer::inner{argument}")))
---~ print(table.serialize(references.analyze("special(outer::operation)")))
-
-- -- -- related to strc-ini.lua -- -- --
references.resolvers = references.resolvers or { }
+local resolvers = references.resolvers
-function references.resolvers.section(var)
- local vi = lists.collected[var.i[2]]
+local function getfromlist(var)
+ local vi = var.i
if vi then
- var.i = vi
- var.r = (vi.references and vi.references.realpage) or (vi.pagedata and vi.pagedata.realpage) or 1
+ vi = vi[3] or lists.collected[vi[2]]
+ if vi then
+ local r = vi.references and vi.references
+ if r then
+ r = r.realpage
+ end
+ if not r then
+ r = vi.pagedata and vi.pagedata
+ if r then
+ r = r.realpage
+ end
+ end
+ var.i = vi
+ var.r = r or 1
+ else
+ var.i = nil
+ var.r = 1
+ end
else
var.i = nil
var.r = 1
end
end
-references.resolvers.float = references.resolvers.section
-references.resolvers.description = references.resolvers.section
-references.resolvers.formula = references.resolvers.section
-references.resolvers.note = references.resolvers.section
+-- resolvers.section = getfromlist
+-- resolvers.float = getfromlist
+-- resolvers.description = getfromlist
+-- resolvers.formula = getfromlist
+-- resolvers.note = getfromlist
+
+setmetatableindex(resolvers,function(t,k)
+ local v = getfromlist
+ resolvers[k] = v
+ return v
+end)
-function references.resolvers.reference(var)
- local vi = var.i[2]
+function resolvers.reference(var)
+ local vi = var.i[2] -- check
if vi then
var.i = vi
var.r = (vi.references and vi.references.realpage) or (vi.pagedata and vi.pagedata.realpage) or 1
@@ -292,22 +336,26 @@ function references.resolvers.reference(var)
end
end
-local function register_from_lists(collected,derived)
+local function register_from_lists(collected,derived,pages,sections)
local g = derived[""] if not g then g = { } derived[""] = g end -- global
for i=1,#collected do
local entry = collected[i]
local m, r = entry.metadata, entry.references
if m and r then
- local prefix, reference = r.referenceprefix or "", r.reference or ""
+ local reference = r.reference or ""
+ local prefix = r.referenceprefix or ""
+ local component = r.component and r.component or ""
if reference ~= "" then
local kind, realpage = m.kind, r.realpage
if kind and realpage then
local d = derived[prefix] if not d then d = { } derived[prefix] = d end
- local t = { kind, i }
+local c = derived[component] if not c then c = { } derived[component] = c end
+ local t = { kind, i, entry }
for s in gmatch(reference,"%s*([^,]+)") do
if trace_referencing then
report_references("list entry %s provides %s reference '%s' on realpage %s",i,kind,s,realpage)
end
+c[s] = c[s] or t -- share them
d[s] = d[s] or t -- share them
g[s] = g[s] or t -- first wins
end
@@ -315,6 +363,7 @@ local function register_from_lists(collected,derived)
end
end
end
+-- inspect(derived)
end
references.registerinitializer(function() register_from_lists(lists.collected,derived) end)
@@ -334,24 +383,40 @@ end
local pushcatcodes, popcatcodes, txtcatcodes = context.pushcatcodes, context.popcatcodes, tex.txtcatcodes
-function references.urls.get(name,method,space) -- method: none, before, after, both, space: yes/no
+function references.urls.get(name)
local u = urls[name]
if u then
local url, file = u[1], u[2]
- pushcatcodes(txtcatcodes)
if file and file ~= "" then
- context("%s/%s",url,file)
+ return format("%s/%s",url,file)
else
- context(url)
+ return url
end
+ end
+end
+
+function commands.geturl(name)
+ local url = references.urls.get(name)
+ if url and url ~= "" then
+ pushcatcodes(txtcatcodes)
+ context(url)
popcatcodes()
end
end
+-- function commands.gethyphenatedurl(name,...)
+-- local url = references.urls.get(name)
+-- if url and url ~= "" then
+-- hyphenatedurl(url,...)
+-- end
+-- end
+
function commands.doifurldefinedelse(name)
commands.doifelse(urls[name])
end
+commands.useurl= references.urls.define
+
-- files
references.files = references.files or { }
@@ -361,7 +426,7 @@ local files = references.files.data
function references.files.define(name,file,description)
if name and name ~= "" then
- files[name] = { file or "", description or file or ""}
+ files[name] = { file or "", description or file or "" }
end
end
@@ -376,6 +441,8 @@ function commands.doiffiledefinedelse(name)
commands.doifelse(files[name])
end
+commands.usefile= references.files.define
+
-- helpers
function references.checkedfile(whatever) -- return whatever if not resolved
@@ -462,31 +529,6 @@ function references.whatfrom(name)
context((urls[name] and variables.url) or (files[name] and variables.file) or variables.unknown)
end
---~ function references.from(name)
---~ local u = urls[name]
---~ if u then
---~ local url, file, description = u[1], u[2], u[3]
---~ if description ~= "" then
---~ context.dofromurldescription(description)
---~ -- ok
---~ elseif file and file ~= "" then
---~ context.dofromurlliteral(url .. "/" .. file)
---~ else
---~ context(dofromurlliteral,url)
---~ end
---~ else
---~ local f = files[name]
---~ if f then
---~ local description, file = f[1], f[2]
---~ if description ~= "" then
---~ context.dofromfiledescription(description)
---~ else
---~ context.dofromfileliteral(file)
---~ end
---~ end
---~ end
---~ end
-
function references.from(name)
local u = urls[name]
if u then
@@ -502,7 +544,7 @@ function references.from(name)
else
local f = files[name]
if f then
- local description, file = f[1], f[2]
+ local file, description = f[1], f[2]
if description ~= "" then
context.dofromfiledescription(description)
else
@@ -512,160 +554,6 @@ function references.from(name)
end
end
--- export
-
-exporters.references = exporters.references or { }
-exporters.lists = exporters.lists or { }
-
-function exporters.references.generic(data)
- local useddata = {}
- local entries, userdata = data.entries, data.userdata
- if entries then
- for k, v in next, entries do
- useddata[k] = v
- end
- end
- if userdata then
- for k, v in next, userdata do
- useddata[k] = v
- end
- end
- return useddata
-end
-
-function exporters.lists.generic(data)
- local useddata = { }
- local titledata, numberdata = data.titledata, data.numberdata
- if titledata then
- useddata.title = titledata.title
- end
- if numberdata then
- local numbers = numberdata.numbers
- local t, tn = { }, 0
- for i=1,#numbers do
- local n = numbers[i]
- if n ~= 0 then
- tn = tn + 1
- t[tn] = n
- end
- end
- useddata.number = concat(t,".")
- end
- return useddata
-end
-
-local function referencer(data)
- local references = data.references
- local realpage = references.realpage
- local numberdata = jobpages.tobesaved[realpage]
- local specification = numberdata.specification
- return {
- realpage = references.realpage,
- number = numberdata.number,
- conversion = specification.conversion,
- -- prefix = only makes sense when bywhatever
- }
-end
-
--- Exported and imported references ... not yet used but don't forget it
--- and redo it.
-
-function references.export(usedname)
- local exported = { }
- local e_references, e_lists = exporters.references, exporters.lists
- local g_references, g_lists = e_references.generic, e_lists.generic
- -- todo: pagenumbers
- -- todo: some packing
- for prefix, references in next, references.tobesaved do
- local pe = exported[prefix] if not pe then pe = { } exported[prefix] = pe end
- for key, data in next, references do
- local metadata = data.metadata
- local exporter = e_references[metadata.kind] or g_references
- if exporter then
- pe[key] = {
- metadata = {
- kind = metadata.kind,
- catcodes = metadata.catcodes,
- coding = metadata.coding, -- we can omit "tex"
- },
- useddata = exporter(data),
- pagedata = referencer(data),
- }
- end
- end
- end
- local pe = exported[""] if not pe then pe = { } exported[""] = pe end
- for n, data in next, lists.tobesaved do
- local metadata = data.metadata
- local exporter = e_lists[metadata.kind] or g_lists
- if exporter then
- local result = {
- metadata = {
- kind = metadata.kind,
- catcodes = metadata.catcodes,
- coding = metadata.coding, -- we can omit "tex"
- },
- useddata = exporter(data),
- pagedata = referencer(data),
- }
- for key in gmatch(data.references.reference,"[^,]+") do
- pe[key] = result
- end
- end
- end
- local e = {
- references = exported,
- version = 1.00,
- }
- io.savedata(file.replacesuffix(usedname or tex.jobname,"tue"),table.serialize(e,true))
-end
-
-function references.import(usedname)
- if usedname then
- local jdn = imported[usedname]
- if not jdn then
- local filename = files[usedname]
- if filename then -- only registered files
- filename = filename[1]
- else
- filename = usedname
- end
- local data = io.loaddata(file.replacesuffix(filename,"tue")) or ""
- if data == "" then
- interfaces.showmessage("references",24,filename)
- data = nil
- else
- data = loadstring(data)
- if data then
- data = data()
- end
- if data then
- -- version check
- end
- if not data then
- interfaces.showmessage("references",25,filename)
- end
- end
- if data then
- interfaces.showmessage("references",26,filename)
- jdn = data
- jdn.filename = filename
- else
- jdn = { filename = filename, references = { }, version = 1.00 }
- end
- imported[usedname] = jdn
- imported[filename] = jdn
- end
- return jdn
- else
- return nil
- end
-end
-
-function references.load(usedname)
- -- gone
-end
-
function references.define(prefix,reference,list)
local d = defined[prefix] if not d then d = { } defined[prefix] = d end
d[reference] = { "defined", list }
@@ -693,7 +581,6 @@ end
local strict = false
local function resolve(prefix,reference,args,set) -- we start with prefix,reference
- texcount.referencehastexstate = 0
if reference and reference ~= "" then
if not set then
set = { prefix = prefix, reference = reference }
@@ -719,7 +606,7 @@ local function resolve(prefix,reference,args,set) -- we start with prefix,refere
if d then
resolve(prefix,d[2],nil,set)
else
- local var = lpegmatch(scanner,ri)
+ local var = splitreference(ri)
if var then
var.reference = ri
local vo, vi = var.outer, var.inner
@@ -755,10 +642,6 @@ local function resolve(prefix,reference,args,set) -- we start with prefix,refere
end
end
end
- if set.has_tex then
- texcount.referencehastexstate = 1
- end
---~ table.print(set)
return set
else
return { }
@@ -769,42 +652,6 @@ end
references.currentset = nil
---~ local b, e = "\\ctxlua{local jc = structures.references.currentset;", "}"
---~ local o, a = 'jc[%s].operation=[[%s]];', 'jc[%s].arguments=[[%s]];'
---~
---~ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex
---~ local currentset = references.currentset
---~ if currentset and currentset.has_tex then
---~ local done = false
---~ for i=1,#currentset do
---~ local ci = currentset[i]
---~ local operation = ci.operation
---~ if operation then
---~ if find(operation,"\\") then -- if o_has_tex then
---~ if not done then
---~ context(b)
---~ done = true
---~ end
---~ context(o,i,operation)
---~ end
---~ end
---~ local arguments = ci.arguments
---~ if arguments then
---~ if find(arguments,"\\") then -- if a_has_tex then
---~ if not done then
---~ context(b)
---~ done = true
---~ end
---~ context(a,i,arguments)
---~ end
---~ end
---~ end
---~ if done then
---~ context(e)
---~ end
---~ end
---~ end
-
function commands.setreferenceoperation(k,v)
references.currentset[k].operation = v
end
@@ -833,283 +680,806 @@ function references.expandcurrent() -- todo: two booleans: o_has_tex& a_has_tex
end
end
---~ local uo = urls[outer]
---~ if uo then
---~ special, operation, argument = "url", uo[1], inner or uo[2] -- maybe more is needed
---~ else
---~ local fo = files[outer]
---~ if fo then
---~ special, operation, argument = "file", fo[1], inner -- maybe more is needed
---~ end
---~ end
+local externals = { }
+
+-- we have prefixes but also components:
+--
+-- : prefix
+-- :: always external
+-- ::: internal (for products) or external (for components)
+
+local function loadexternalreferences(name,utilitydata)
+ local struc = utilitydata.structures
+ if struc then
+ local external = struc.references.collected -- direct references
+ local lists = struc.lists.collected -- indirect references (derived)
+ local pages = struc.pages.collected -- pagenumber data
+ -- a bit weird one, as we don't have the externals in the collected
+ for prefix, set in next, external do
+ for reference, data in next, set do
+ if trace_importing then
+ report_importing("registering external reference: regular | %s | %s | %s",name,prefix,reference)
+ end
+ local section = reference.section
+ local realpage = reference.realpage
+ if section then
+ reference.sectiondata = lists[section]
+ end
+ if realpage then
+ reference.pagedata = pages[realpage]
+ end
+ end
+ end
+ for i=1,#lists do
+ local entry = lists[i]
+ local metadata = entry.metadata
+ local references = entry.references
+ if metadata and references then
+ local reference = references.reference
+ if reference and reference ~= "" then
+ local kind = metadata.kind
+ local realpage = references.realpage
+ if kind and realpage then
+ references.pagedata = pages[realpage]
+ local prefix = references.referenceprefix or ""
+ local target = external[prefix]
+ if not target then
+ target = { }
+ external[prefix] = target
+ end
+ for s in gmatch(reference,"%s*([^,]+)") do
+ if trace_importing then
+ report_importing("registering external reference: %s | %s | %s | %s",kind,name,prefix,s)
+ end
+ target[s] = target[s] or entry
+ end
+ end
+ end
+ end
+ end
+ externals[name] = external
+ return external
+ end
+end
-local prefixsplitter = lpegCs(lpegP((1-lpegP(":"))^1 * lpegP(":"))) * lpegCs(lpegP(1)^1)
+local externalfiles = { }
--- todo: add lots of tracing here
+table.setmetatableindex(externalfiles, function(t,k)
+ local v = files[k]
+ if not v then
+ v = { k, k }
+ end
+ externalfiles[k] = v
+ return v
+end)
-local n = 0
+table.setmetatableindex(externals,function(t,k) -- either or not automatically
+ local filename = externalfiles[k][1] -- filename
+ local fullname = file.replacesuffix(filename,"tuc")
+ if lfs.isfile(fullname) then -- todo: use other locator
+ local utilitydata = job.loadother(fullname)
+ if utilitydata then
+ local external = loadexternalreferences(k,utilitydata)
+ t[k] = external or false
+ return external
+ end
+ end
+ t[k] = false
+ return false
+end)
-local function identify(prefix,reference)
- local set = resolve(prefix,reference)
- local bug = false
-n = n + 1
-set.n = n
- for i=1,#set do
- local var = set[i]
- local special, inner, outer, arguments, operation = var.special, var.inner, var.outer, var.arguments, var.operation
- if special then
- local s = specials[special]
- if s then
- if outer then
- if operation then
- -- special(outer::operation)
- var.kind = "special outer with operation"
- else
- -- special()
- var.kind = "special outer"
- end
- var.f = outer
- elseif operation then
- if arguments then
- -- special(operation{argument,argument})
- var.kind = "special operation with arguments"
- else
- -- special(operation)
- var.kind = "special operation"
- end
- else
- -- special()
- var.kind = "special"
+local productdata = {
+ productreferences = { },
+ componentreferences = { },
+ components = { },
+}
+
+local function loadproductreferences(productname,componentname,utilitydata)
+ local struc = utilitydata.structures
+ if struc then
+ local productreferences = struc.references.collected -- direct references
+ local lists = struc.lists.collected -- indirect references (derived)
+ local pages = struc.pages.collected -- pagenumber data
+ -- we use indirect tables to save room but as they are eventually
+ -- just references we resolve them to data here (the mechanisms
+ -- that use this data check for indirectness)
+ for prefix, set in next, productreferences do
+ for reference, data in next, set do
+ if trace_importing then
+ report_importing("registering product reference: regular | %s | %s | %s",productname,prefix,reference)
+ end
+ local section = reference.section
+ local realpage = reference.realpage
+ if section then
+ reference.sectiondata = lists[section]
+ end
+ if realpage then
+ reference.pagedata = pages[realpage]
end
- else
- var.error = "unknown special"
end
- elseif outer then
- local e = references.import(outer)
- if e then
- if inner then
- local r = e.references
- if r then
- r = r[prefix]
- if r then
- r = r[inner]
- if r then
- if arguments then
- -- outer::inner{argument}
- var.kind = "outer with inner with arguments"
- else
- -- outer::inner
- var.kind = "outer with inner"
- end
- var.i = { "reference", r }
- references.resolvers.reference(var)
- var.f = outer
- var.e = true -- external
+ end
+ --
+ local componentreferences = { }
+ for i=1,#lists do
+ local entry = lists[i]
+ local metadata = entry.metadata
+ local references = entry.references
+ if metadata and references then
+ local reference = references.reference
+ if reference and reference ~= "" then
+ local kind = metadata.kind
+ local realpage = references.realpage
+ if kind and realpage then
+ references.pagedata = pages[realpage]
+ local prefix = references.referenceprefix or ""
+ local component = references.component
+ local ctarget, ptarget
+ if component and component == componentname then
+ -- skip
+ else
+ -- one level up
+ local external = componentreferences[component]
+ if not external then
+ external = { }
+ componentreferences[component] = external
+ end
+ if component == prefix then
+ prefix = ""
+ end
+ ctarget = external[prefix]
+ if not ctarget then
+ ctarget = { }
+ external[prefix] = ctarget
end
end
- end
- if not r then
- r = e.derived
- if r then
- r = r[prefix]
- if r then
- r = r[inner]
- if r then
- -- outer::inner
- if arguments then
- -- outer::inner{argument}
- var.kind = "outer with inner with arguments"
- else
- -- outer::inner
- var.kind = "outer with inner"
- end
- var.i = r
- references.resolvers[r[1]](var)
- var.f = outer
+ ptarget = productreferences[prefix]
+ if not ptarget then
+ ptarget = { }
+ productreferences[prefix] = ptarget
+ end
+ for s in gmatch(reference,"%s*([^,]+)") do
+ if ptarget then
+ if trace_importing then
+ report_importing("registering product reference: %s | %s | %s | %s",kind,productname,prefix,s)
end
+ ptarget[s] = ptarget[s] or entry
end
- end
- end
- if not r then
- var.error = "unknown outer"
- end
- elseif special then
- local s = specials[special]
- if s then
- if operation then
- if arguments then
- -- outer::special(operation{argument,argument})
- var.kind = "outer with special and operation and arguments"
- else
- -- outer::special(operation)
- var.kind = "outer with special and operation"
+ if ctarget then
+ if trace_importing then
+ report_importing("registering component reference: %s | %s | %s | %s",kind,productname,prefix,s)
+ end
+ ctarget[s] = ctarget[s] or entry
end
- else
- -- outer::special()
- var.kind = "outer with special"
end
- var.f = outer
- else
- var.error = "unknown outer with special"
end
- else
- -- outer::
- var.kind = "outer"
- var.f = outer
end
- else
- if inner then
- if arguments then
- -- outer::inner{argument}
- var.kind = "outer with inner with arguments"
- else
- -- outer::inner
- var.kind = "outer with inner"
+ end
+ end
+ productdata.productreferences = productreferences -- not yet used
+ productdata.componentreferences = componentreferences
+ end
+end
+
+local function loadproductvariables(product,component,utilitydata)
+ local struc = utilitydata.structures
+ if struc then
+ local lists = struc.lists and struc.lists.collected
+ if lists then
+ local pages = struc.pages and struc.pages.collected
+ for i=1,#lists do
+ local li = lists[i]
+ if li.metadata.kind == "section" and li.references.component == component then
+ local firstsection = li
+ if firstsection.numberdata then
+ local numbers = firstsection.numberdata.numbers
+ if numbers then
+ if trace_importing then
+ report_importing("initializing section number to %s",concat(numbers,":"))
+ end
+ productdata.firstsection = firstsection
+ structures.documents.preset(numbers)
+ end
end
- var.i = { "reference", inner }
- references.resolvers.reference(var)
- var.f = outer
- elseif special then
- local s = specials[special]
- if s then
- if operation then
- if arguments then
- -- outer::special(operation{argument,argument})
- var.kind = "outer with special and operation and arguments"
- else
- -- outer::special(operation)
- var.kind = "outer with special and operation"
+ if pages and firstsection.references then
+ local firstpage = pages[firstsection.references.realpage]
+ local number = firstpage and firstpage.number
+ if number then
+ if trace_importing then
+ report_importing("initializing page number to %s",number)
end
- else
- -- outer::special()
- var.kind = "outer with special"
+ productdata.firstpage = firstpage
+ counters.set("userpage",1,number)
end
- var.f = outer
- else
- var.error = "unknown outer with special"
end
+ break
+ end
+ end
+ end
+ end
+end
+
+local function componentlist(tree,target)
+ local branches = tree and tree.branches
+ if branches then
+ for i=1,#branches do
+ local branch = branches[i]
+ local type = branch.type
+ if type == "component" then
+ if target then
+ target[#target+1] = branch.name
else
- -- outer::
- var.kind = "outer"
- var.f = outer
+ target = { branch.name }
end
+ elseif type == "product" or type == "component" then
+ target = componentlist(branch,target)
end
+ end
+ end
+ return target
+end
+
+local function loadproductcomponents(product,component,utilitydata)
+ local job = utilitydata.job
+ productdata.components = componentlist(job and job.structure and job.structure.collected) or { }
+end
+
+function structures.references.loadpresets(product,component) -- we can consider a special components hash
+ if product and component and product~= "" and component ~= "" and not productdata.product then -- maybe: productdata.filename ~= filename
+ productdata.product = product
+ productdata.component = component
+ local fullname = file.replacesuffix(product,"tuc")
+ if lfs.isfile(fullname) then -- todo: use other locator
+ local utilitydata = job.loadother(fullname)
+ if utilitydata then
+ if trace_importing then
+ report_importing("loading references for component %s of product %s from %s",component,product,fullname)
+ end
+ loadproductvariables (product,component,utilitydata)
+ loadproductreferences(product,component,utilitydata)
+ loadproductcomponents(product,component,utilitydata)
+ -- inspect(productdata)
+ end
+ end
+ end
+end
+
+structures.references.productdata = productdata
+
+local useproduct = commands.useproduct
+
+if useproduct then
+
+ function commands.useproduct(product)
+ useproduct(product)
+ if texconditionals.autocrossfilereferences then
+ local component = justacomponent()
+ if component then
+ if trace_referencing or trace_importing then
+ report_references("loading presets for component '%s' of product '%s'",component,product)
+ end
+ structures.references.loadpresets(product,component)
+ end
+ end
+ end
+
+end
+
+-- productdata.firstsection.numberdata.numbers
+-- productdata.firstpage.number
+
+local function report_identify_special(set,var,i,type)
+ local reference = set.reference
+ local prefix = set.prefix or ""
+ local special = var.special
+ local error = var.error
+ local kind = var.kind
+ if error then
+ report_identifying("type %s: %s, n: %s, prefix: %s, special: %s, error: %s",type,reference,i,prefix,special,error)
+ else
+ report_identifying("type %s: %s, n: %s, prefix: %s, special: %s, kind: %s",type,reference,i,prefix,special,kind)
+ end
+end
+
+local function report_identify_arguments(set,var,i,type)
+ local reference = set.reference
+ local prefix = set.prefix or ""
+ local arguments = var.arguments
+ local error = var.error
+ local kind = var.kind
+ if error then
+ report_identifying("type %s: %s, n: %s, prefix: %s, arguments: %s, error: %s",type,reference,i,prefix,arguments,error)
+ else
+ report_identifying("type %s: %s, n: %s, prefix: %s, arguments: %s, kind: %s",type,reference,i,prefix,arguments,kind)
+ end
+end
+
+local function report_identify_outer(set,var,i,type)
+ local reference = set.reference
+ local prefix = set.prefix or ""
+ local outer = var.outer
+ local error = var.error
+ local kind = var.kind
+ if outer then
+ if error then
+ report_identifying("type %s: %s, n: %s, prefix: %s, outer: %s, error: %s",type,reference,i,prefix,outer,error)
+ else
+ report_identifying("type %s: %s, n: %s, prefix: %s, outer: %s, kind: %s",type,reference,i,prefix,outer,kind)
+ end
+ else
+ if error then
+ report_identifying("type %s: %s, n: %s, prefix: %s, error: %s",type,reference,i,prefix,error)
else
+ report_identifying("type %s: %s, n: %s, prefix: %s, kind: %s",type,reference,i,prefix,kind)
+ end
+ end
+end
+
+local function identify_special(set,var,i)
+ local special = var.special
+ local s = specials[special]
+ if s then
+ local outer = var.outer
+ local operation = var.operation
+ local arguments = var.arguments
+ if outer then
+ if operation then
+ -- special(outer::operation)
+ var.kind = "special outer with operation"
+ else
+ -- special()
+ var.kind = "special outer"
+ end
+ var.f = outer
+ elseif operation then
if arguments then
- local s = specials[inner]
- if s then
- -- inner{argument}
- var.kind = "special with arguments"
- else
- var.error = "unknown inner or special"
- end
+ -- special(operation{argument,argument})
+ var.kind = "special operation with arguments"
else
- -- inner ... we could move the prefix logic into the parser so that we have 'm for each entry
- -- foo:bar -> foo == prefix (first we try the global one)
- -- -:bar -> ignore prefix
- local p, i = prefix, nil
- local splitprefix, splitinner = lpegmatch(prefixsplitter,inner)
- -- these are taken from other anonymous references
- if splitprefix and splitinner then
- if splitprefix == "-" then
- i = collected[""]
- i = i and i[splitinner]
- if i then
- p = ""
- end
- else
- i = collected[splitprefix]
- i = i and i[splitinner]
- if i then
- p = splitprefix
- end
- end
- end
- -- todo: strict here
- if not i then
- i = collected[prefix]
- i = i and i[inner]
- if i then
- p = prefix
- end
+ -- special(operation)
+ var.kind = "special operation"
+ end
+ else
+ -- special()
+ var.kind = "special"
+ end
+ if trace_identifying then
+ report_identify_special(set,var,i,"1a")
+ end
+ else
+ var.error = "unknown special"
+ end
+ return var
+end
+
+local function identify_arguments(set,var,i)
+ local s = specials[var.inner]
+ if s then
+ -- inner{argument}
+ var.kind = "special with arguments"
+ else
+ var.error = "unknown inner or special"
+ end
+ if trace_identifying then
+ report_identify_arguments(set,var,i,"3a")
+ end
+ return var
+end
+
+local function identify_inner(set,var,prefix,collected,derived,tobesaved)
+ local inner = var.inner
+ local outer = var.outer
+ -- inner ... we could move the prefix logic into the parser so that we have 'm for each entry
+ -- foo:bar -> foo == prefix (first we try the global one)
+ -- -:bar -> ignore prefix
+ local p, i = prefix, nil
+ local splitprefix, splitinner
+ -- the next test is a safeguard when references are auto loaded from outer
+ if inner then
+ splitprefix, splitinner = lpegmatch(prefixsplitter,inner)
+ end
+ -- these are taken from other anonymous references
+ if splitprefix and splitinner then
+ if splitprefix == "-" then
+ i = collected[""]
+ i = i and i[splitinner]
+ if i then
+ p = ""
+ end
+ else
+ i = collected[splitprefix]
+ i = i and i[splitinner]
+ if i then
+ p = splitprefix
+ end
+ end
+ end
+ -- todo: strict here
+ if not i then
+ i = collected[prefix]
+ i = i and i[inner]
+ if i then
+ p = prefix
+ end
+ end
+ if not i and prefix ~= "" then
+ i = collected[""]
+ i = i and i[inner]
+ if i then
+ p = ""
+ end
+ end
+ if i then
+ var.i = { "reference", i }
+ resolvers.reference(var)
+ var.kind = "inner"
+ var.p = p
+ elseif derived then
+ -- these are taken from other data structures (like lists)
+ if splitprefix and splitinner then
+ if splitprefix == "-" then
+ i = derived[""]
+ i = i and i[splitinner]
+ if i then
+ p = ""
end
- if not i and prefix ~= "" then
- i = collected[""]
- i = i and i[inner]
- if i then
- p = ""
- end
+ else
+ i = derived[splitprefix]
+ i = i and i[splitinner]
+ if i then
+ p = splitprefix
end
+ end
+ end
+ if not i then
+ i = derived[prefix]
+ i = i and i[inner]
+ if i then
+ p = prefix
+ end
+ end
+ if not i and prefix ~= "" then
+ i = derived[""]
+ i = i and i[inner]
+ if i then
+ p = ""
+ end
+ end
+ if i then
+ var.kind = "inner"
+ var.i = i
+ var.p = p
+ local ri = resolvers[i[1]]
+ if ri then
+ ri(var)
+ else
+ -- can't happen as we catch it with a metatable now
+ report_references("unknown inner resolver for '%s'",i[1])
+ end
+ else
+ -- no prefixes here
+ local s = specials[inner]
+ if s then
+ var.kind = "special"
+ else
+ i = (collected and collected[""] and collected[""][inner]) or
+ (derived and derived [""] and derived [""][inner]) or
+ (tobesaved and tobesaved[""] and tobesaved[""][inner])
if i then
- var.i = { "reference", i }
- references.resolvers.reference(var)
var.kind = "inner"
- var.p = p
+ var.i = { "reference", i }
+ resolvers.reference(var)
+ var.p = ""
else
- -- these are taken from other data structures (like lists)
---~ print("!!!!!!!!!!!!!!",splitprefix,splitinner)
---~ table.print(derived)
- if splitprefix and splitinner then
- if splitprefix == "-" then
- i = derived[""]
- i = i and i[splitinner]
- if i then
- p = ""
- end
- else
- i = derived[splitprefix]
- i = i and i[splitinner]
- if i then
- p = splitprefix
- end
- end
- end
- if not i then
- i = derived[prefix]
- i = i and i[inner]
- if i then
- p = prefix
+ var.error = "unknown inner or special"
+ end
+ end
+ end
+ end
+ return var
+end
+
+local function identify_outer(set,var,i)
+ local outer = var.outer
+ local inner = var.inner
+ local external = externals[outer]
+ if external then
+ local v = copytable(var)
+ v = identify_inner(set,v,nil,external)
+ if v.i and not v.error then
+ v.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,v,i,"2a")
+ end
+ return v
+ end
+ v = copytable(var)
+ local v = identify_inner(set,v,v.outer,external)
+ if v.i and not v.error then
+ v.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,v,i,"2b")
+ end
+ return v
+ end
+ end
+ local external = productdata.componentreferences[outer]
+ if external then
+ local v = identify_inner(set,copytable(var),nil,external)
+ if v.i and not v.error then
+ v.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,v,i,"2c")
+ end
+ return v
+ end
+ end
+ local external = productdata.productreferences[outer]
+ if external then
+ local vi = external[inner]
+ if vi then
+ var.kind = "outer with inner"
+ var.i = vi
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"2d")
+ end
+ return var
+ end
+ end
+ -- the rest
+ local special = var.special
+ local arguments = var.arguments
+ local operation = var.operation
+ if inner then
+ if arguments then
+ -- outer::inner{argument}
+ var.kind = "outer with inner with arguments"
+ else
+ -- outer::inner
+ var.kind = "outer with inner"
+ end
+ var.i = { "reference", inner }
+ resolvers.reference(var)
+ var.f = outer
+ if trace_identifying then
+ report_identify_outer(set,var,i,"2e")
+ end
+ elseif special then
+ local s = specials[special]
+ if s then
+ if operation then
+ if arguments then
+ -- outer::special(operation{argument,argument})
+ var.kind = "outer with special and operation and arguments"
+ else
+ -- outer::special(operation)
+ var.kind = "outer with special and operation"
+ end
+ else
+ -- outer::special()
+ var.kind = "outer with special"
+ end
+ var.f = outer
+ else
+ var.error = "unknown outer with special"
+ end
+ if trace_identifying then
+ report_identify_outer(set,var,i,"2f")
+ end
+ else
+ -- outer::
+ var.kind = "outer"
+ var.f = outer
+ if trace_identifying then
+ report_identify_outer(set,var,i,"2g")
+ end
+ end
+ return var
+end
+
+local function identify_inner_or_outer(set,var,i)
+ -- here we fall back on product data
+ local inner = var.inner
+ if inner and inner ~= "" then
+ local v = identify_inner(set,copytable(var),set.prefix,collected,derived,tobesaved)
+ if v.i and not v.error then
+ v.kind = "inner" -- check this
+ if trace_identifying then
+ report_identify_outer(set,v,i,"4a")
+ end
+ return v
+ end
+
+local components = job.structure.components
+if components then
+ for i=1,#components do
+ local component = components[i]
+ local data = collected[component]
+ local vi = data and data[inner]
+ if vi then
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4x")
+ end
+ return var
+ end
+ end
+end
+
+ local componentreferences = productdata.componentreferences
+ local productreferences = productdata.productreferences
+ local components = productdata.components
+ if components and componentreferences then
+ -- for component, data in next, productdata.componentreferences do -- better do this in order of processing:
+ for i=1,#components do
+ local component = components[i]
+ local data = componentreferences[component]
+ if data then
+ local d = data[""]
+ local vi = d and d[inner]
+ if vi then
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4b")
end
+ return var
end
- if not i and prefix ~= "" then
- i = derived[""]
- i = i and i[inner]
- if i then
- p = ""
- end
+ end
+ end
+ end
+ local component, inner = lpegmatch(componentsplitter,inner)
+ if component then
+ local data = componentreferences and componentreferences[component]
+ if data then
+ local d = data[""]
+ local vi = d and d[inner]
+ if vi then
+ var.inner = inner
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4c")
end
- if i then
- var.kind = "inner"
- var.i = i
- references.resolvers[i[1]](var)
- var.p = p
- else
- -- no prefixes here
- local s = specials[inner]
- if s then
- var.kind = "special"
- else
- i = (collected[""] and collected[""][inner]) or
- (derived [""] and derived [""][inner]) or
- (tobesaved[""] and tobesaved[""][inner])
- if i then
- var.kind = "inner"
- var.i = { "reference", i }
- references.resolvers.reference(var)
- var.p = ""
- else
- var.error = "unknown inner or special"
- end
- end
+ return var
+ end
+ end
+ local data = productreferences and productreferences[component]
+ if data then
+ local vi = data[inner]
+ if vi then
+ var.inner = inner
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4d")
end
+ return var
end
end
end
- bug = bug or var.error
+ var.error = "unknown inner"
+ else
+ var.error = "no inner"
+ end
+ if trace_identifying then
+ report_identify_outer(set,var,i,"4e")
+ end
+ return var
+end
+
+-- local function identify_inner_or_outer(set,var,i)
+-- -- we might consider first checking with a prefix prepended and then without
+-- -- which is better for fig:oeps
+-- local var = do_identify_inner_or_outer(set,var,i)
+-- if var.error then
+-- local prefix = set.prefix
+-- if prefix and prefix ~= "" then
+-- var.inner = prefix .. ':' .. var.inner
+-- var.error = nil
+-- return do_identify_inner_or_outer(set,var,i)
+-- end
+-- end
+-- return var
+-- end
+
+local function identify_inner_component(set,var,i)
+ -- we're in a product (maybe ignore when same as component)
+ local component = var.component
+ identify_inner(set,var,component,collected,derived,tobesaved)
+ if trace_identifying then
+ report_identify_outer(set,var,i,"5a")
+ end
+ return var
+end
+
+local function identify_outer_component(set,var,i)
+ local component = var.component
+ local inner = var.inner
+ local data = productdata.componentreferences[component]
+ if data then
+ local d = data[""]
+ local vi = d and d[inner]
+ if vi then
+ var.inner = inner
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"6a")
+ end
+ return var
+ end
+ end
+ local data = productdata.productreferences[component]
+ if data then
+ local vi = data[inner]
+ if vi then
+ var.inner = inner
+ var.outer = component
+ var.i = vi
+ var.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,var,i,"6b")
+ end
+ return var
+ end
+ end
+ var.error = "unknown component"
+ if trace_identifying then
+ report_identify_outer(set,var,i,"6c")
+ end
+ return var
+end
+
+local nofidentified = 0
+
+local function identify(prefix,reference)
+ if not reference then
+ prefix = ""
+ reference = prefix
+ end
+ local set = resolve(prefix,reference)
+ local bug = false
+ texcount.referencehastexstate = set.has_tex and 1 or 0
+ nofidentified = nofidentified + 1
+ set.n = nofidentified
+ for i=1,#set do
+ local var = set[i]
+ if var.special then
+ var = identify_special(set,var,i)
+ elseif var.outer then
+ var = identify_outer(set,var,i)
+ elseif var.arguments then
+ var = identify_arguments(set,var,i)
+ elseif not var.component then
+ var = identify_inner_or_outer(set,var,i)
+ elseif productcomponent() then
+ var = identify_inner_component(set,var,i)
+ else
+ var = identify_outer_component(set,var,i)
+ end
set[i] = var
+ bug = bug or var.error
end
references.currentset = mark(set) -- mark, else in api doc
---~ table.print(set,tostring(bug))
+ if trace_analyzing then
+ report_references(table.serialize(set,reference))
+ end
return set, bug
end
@@ -1136,19 +1506,25 @@ function references.doifelse(prefix,reference,highlight,newwindow,layer)
currentreference = set[1]
end
-- we can do the expansion here which saves a call
---~ print("!!!!!!",not unknown)
commands.doifelse(not unknown)
end
function references.reportproblems() -- might become local
if nofunknowns > 0 then
- interfaces.showmessage("references",5,nofunknowns) -- 5 = unknown, 6 = illegal
- -- -- we need a proper logger specific for the log file
- -- texio.write_nl("log",format("%s unknown references",nofunknowns))
- -- for k, v in table.sortedpairs(unknowns) do
- -- texio.write_nl("log",format("%s (n=%s)",k,v))
- -- end
- -- texio.write_nl("log","")
+ statistics.register("cross referencing", function()
+ return format("%s identified, %s unknown",nofidentified,nofunknowns)
+ end)
+ logspushtarget("logfile")
+ logsnewline()
+ report_references("start problematic references")
+ logsnewline()
+ for k, v in table.sortedpairs(unknowns) do
+ report_unknown("%4i: %s",v,k)
+ end
+ logsnewline()
+ report_references("stop problematic references")
+ logsnewline()
+ logspoptarget()
end
end
@@ -1177,14 +1553,16 @@ directives.register("references.linkmethod", function(v) -- page mixed names
references.setinnermethod(v)
end)
-function references.setinternalreference(prefix,tag,internal,view)
+-- this is inconsistent
+
+function references.setinternalreference(prefix,tag,internal,view) -- needs checking
if innermethod == "page" then
return unsetvalue
else
local t, tn = { }, 0 -- maybe add to current
if tag then
if prefix and prefix ~= "" then
- prefix = prefix .. ":"
+ prefix = prefix .. ":" -- watch out, : here
for ref in gmatch(tag,"[^,]+") do
tn = tn + 1
t[tn] = prefix .. ref
@@ -1206,8 +1584,22 @@ function references.setinternalreference(prefix,tag,internal,view)
end
end
+function references.setandgetattribute(kind,prefix,tag,data,view) -- maybe do internal automatically here
+ references.set(kind,prefix,tag,data)
+ texcount.lastdestinationattribute = references.setinternalreference(prefix,tag,nil,view) or -0x7FFFFFFF
+end
+
function references.getinternalreference(n) -- n points into list (todo: registers)
local l = lists.collected[n]
+ return l and l.references.internal or n
+end
+
+function commands.setinternalreference(prefix,tag,internal,view) -- needs checking
+ context(references.setinternalreference(prefix,tag,internal,view))
+end
+
+function commands.getinternalreference(n) -- this will also be a texcount
+ local l = lists.collected[n]
context(l and l.references.internal or n)
end
@@ -1233,22 +1625,27 @@ function references.getcurrentprefixspec(default) -- todo: message
end
function references.filter(name,...) -- number page title ...
- local data = currentreference and currentreference.i
+ local data = currentreference and currentreference.i -- maybe we should take realpage from here
if data then
- local kind = data.metadata and data.metadata.kind
- if kind then
- local filter = filters[kind] or filters.generic
- filter = filter and (filter[name] or filter.unknown or filters.generic[name] or filters.generic.unknown)
- if filter then
- if trace_referencing then
- report_references("name '%s', kind '%s', using dedicated filter",name,kind)
+ if name == "realpage" then
+ local cs = references.analyze() -- normally already analyzed but also sets state
+ context(cs.realpage or 0) -- todo, return and in command namespace
+ else -- assumes data is table
+ local kind = type(data) == "table" and data.metadata and data.metadata.kind
+ if kind then
+ local filter = filters[kind] or filters.generic
+ filter = filter and (filter[name] or filter.unknown or filters.generic[name] or filters.generic.unknown)
+ if filter then
+ if trace_referencing then
+ report_references("name '%s', kind '%s', using dedicated filter",name,kind)
+ end
+ filter(data,name,...)
+ elseif trace_referencing then
+ report_references("name '%s', kind '%s', using generic filter",name,kind)
end
- filter(data,name,...)
elseif trace_referencing then
- report_references("name '%s', kind '%s', using generic filter",name,kind)
+ report_references("name '%s', unknown kind",name)
end
- elseif trace_referencing then
- report_references("name '%s', unknown kind",name)
end
elseif trace_referencing then
report_references("name '%s', no reference",name)
@@ -1279,7 +1676,6 @@ function filters.generic.number(data,what,prefixspec) -- todo: spec and then no
if data then
local numberdata = data.numberdata
if numberdata then
---~ print(table.serialize(prefixspec))
helpers.prefix(data,prefixspec)
sections.typesetnumber(numberdata,"number",numberdata)
else
@@ -1295,7 +1691,7 @@ filters.generic.default = filters.generic.text
function filters.generic.page(data,prefixspec,pagespec)
local pagedata = data.pagedata
- if pagedata then -- imported
+ if pagedata then
local number, conversion = pagedata.number, pagedata.conversion
if not number then
-- error
@@ -1336,14 +1732,21 @@ function filters.text.title(data)
helpers.title(data.entries.text or "?",data.metadata)
end
-function filters.text.number(data)
- helpers.title(data.entries.text or "?",data.metadata)
-end
+-- no longer considered useful:
+--
+-- function filters.text.number(data)
+-- helpers.title(data.entries.text or "?",data.metadata)
+-- end
function filters.text.page(data,prefixspec,pagespec)
helpers.prefixpage(data,prefixspec,pagespec)
end
+filters.full = { }
+
+filters.full.title = filters.text.title
+filters.full.page = filters.text.page
+
filters.section = { }
function filters.section.number(data,what,prefixspec)
@@ -1364,23 +1767,29 @@ filters.section.title = filters.generic.title
filters.section.page = filters.generic.page
filters.section.default = filters.section.number
-filters.note = { default = filters.generic.number }
-filters.formula = { default = filters.generic.number }
-filters.float = { default = filters.generic.number }
-filters.description = { default = filters.generic.number }
-filters.item = { default = filters.generic.number }
+-- filters.note = { default = filters.generic.number }
+-- filters.formula = { default = filters.generic.number }
+-- filters.float = { default = filters.generic.number }
+-- filters.description = { default = filters.generic.number }
+-- filters.item = { default = filters.generic.number }
-function references.sectiontitle(n)
- helpers.sectiontitle(lists.collected[tonumber(n) or 0])
-end
+setmetatableindex(filters, function(t,k) -- beware, test with rawget
+ local v = { default = filters.generic.number } -- not copy as it might be extended differently
+ t[k] = v
+ return v
+end)
-function references.sectionnumber(n)
- helpers.sectionnumber(lists.collected[tonumber(n) or 0])
-end
+-- function references.sectiontitle(n)
+-- helpers.sectiontitle(lists.collected[tonumber(n) or 0])
+-- end
-function references.sectionpage(n,prefixspec,pagespec)
- helpers.prefixedpage(lists.collected[tonumber(n) or 0],prefixspec,pagespec)
-end
+-- function references.sectionnumber(n)
+-- helpers.sectionnumber(lists.collected[tonumber(n) or 0])
+-- end
+
+-- function references.sectionpage(n,prefixspec,pagespec)
+-- helpers.prefixedpage(lists.collected[tonumber(n) or 0],prefixspec,pagespec)
+-- end
-- analyze
@@ -1390,69 +1799,124 @@ references.testspecials = references.testspecials or { }
local runners = references.testrunners
local specials = references.testspecials
+-- We need to prevent ending up in the 'relative location' analyzer as it is
+-- pretty slow (progressively). In the pagebody one can best check the reference
+-- real page to determine if we need contrastlocation as that is more lightweight.
+
local function checkedpagestate(n,page)
- local r, p = referred[n] or texcount.realpageno, tonumber(page)
+ local r, p = referredpage(n), tonumber(page)
if not p then
return 0
elseif p > r then
- return 3
+ return 3 -- after
elseif p < r then
- return 2
+ return 2 -- before
else
- return 1
+ return 1 -- same
end
end
-function references.analyze(actions)
+local function setreferencerealpage(actions)
actions = actions or references.currentset
if not actions then
- actions = { realpage = 0 }
- texcount.referencepagestate = 0
- elseif actions.realpage then
- -- already analyzed
- texcount.referencepagestate = checkedpagestate(actions.n,actions.realpage)
+ return 0
else
- -- we store some analysis data alongside the indexed array
- -- at this moment only the real reference page is analyzed
- -- normally such an analysis happens in the backend code
+ local realpage = actions.realpage
+ if realpage then
+ return realpage
+ end
local nofactions = #actions
if nofactions > 0 then
for i=1,nofactions do
local a = actions[i]
local what = runners[a.kind]
if what then
- what = what(a,actions)
+ what = what(a,actions) -- needs documentation
end
end
- texcount.referencepagestate = checkedpagestate(actions.n,actions.realpage)
+ realpage = actions.realpage
+ if realpage then
+ return realpage
+ end
+ end
+ actions.realpage = 0
+ return 0
+ end
+end
+
+-- we store some analysis data alongside the indexed array
+-- at this moment only the real reference page is analyzed
+-- normally such an analysis happens in the backend code
+
+function references.analyze(actions)
+ actions = actions or references.currentset
+ if not actions then
+ actions = { realpage = 0, pagestate = 0 }
+ elseif actions.pagestate then
+ -- already done
+ else
+ local realpage = actions.realpage or setreferencerealpage(actions)
+ if realpage == 0 then
+ actions.pagestate = 0
+ elseif actions.external then
+ actions.pagestate = 0
else
- texcount.referencepagestate = 0
+ actions.pagestate = checkedpagestate(actions.n,realpage)
end
end
return actions
end
-function references.realpage() -- special case, we always want result
- local cs = references.analyze()
- context(cs.realpage or 0)
+function commands.referencepagestate(actions)
+ actions = actions or references.currentset
+ if not actions then
+ context(0)
+ else
+ if not actions.pagestate then
+ references.analyze(actions) -- delayed unless explicitly asked for
+ end
+ context(actions.pagestate)
+ end
+end
+
+function commands.referencerealpage(actions)
+ actions = actions or references.currentset
+ context(not actions and 0 or actions.realpage or setreferencerealpage(actions))
end
-local plist
+local plist, nofrealpages
-local function realpageofpage(p)
+local function realpageofpage(p) -- the last one counts !
if not plist then
local pages = structures.pages.collected
+ nofrealpages = #pages
plist = { }
- for rp=1,#pages do
+ for rp=1,nofrealpages do
plist[pages[rp].number] = rp
end
+ references.nofrealpages = nofrealpages
end
return plist[p]
end
references.realpageofpage = realpageofpage
---
+function references.checkedrealpage(r)
+ if not plist then
+ realpageofpage(r) -- just initialize
+ end
+ if not r then
+ return texcount.realpageno
+ elseif r < 1 then
+ return 1
+ elseif r > nofrealpages then
+ return nofrealpages
+ else
+ return r
+ end
+end
+
+-- use local ?
local pages = allocate {
[variables.firstpage] = function() return counters.record("realpage")["first"] end,
@@ -1489,7 +1953,8 @@ end
runners["special operation"] = runners["special"]
runners["special operation with arguments"] = runners["special"]
--- weird, why is this code here and in lpdf-ano
+-- These are the testspecials not the real ones. They are used to
+-- check the validity.
function specials.internal(var,actions)
local v = references.internals[tonumber(var.operation)]
@@ -1530,3 +1995,34 @@ function specials.userpage(var,actions)
actions.realpage = actions.realpage or p -- first wins
end
end
+
+function specials.deltapage(var,actions)
+ local p = tonumber(var.operation)
+ if p then
+ p = references.checkedrealpage(p + texcount.realpageno)
+ var.r = p
+ actions.realpage = actions.realpage or p -- first wins
+ end
+end
+
+function specials.section(var,actions)
+ local sectionname = var.arguments
+ local destination = var.operation
+ local internal = structures.sections.internalreference(sectionname,destination)
+ if internal then
+ var.special = "internal"
+ var.operation = internal
+ var.arguments = nil
+ specials.internal(var,actions)
+ end
+end
+
+-- needs a better split ^^^
+
+commands.filterreference = references.filter
+
+-- done differently now:
+
+function references.export(usedname) end
+function references.import(usedname) end
+function references.load (usedname) end
diff --git a/Master/texmf-dist/tex/context/base/strc-ref.mkii b/Master/texmf-dist/tex/context/base/strc-ref.mkii
index 4550f714430..8a135eb043e 100644
--- a/Master/texmf-dist/tex/context/base/strc-ref.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-ref.mkii
@@ -5,7 +5,7 @@
%D subtitle=Cross Referencing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-ref.mkiv b/Master/texmf-dist/tex/context/base/strc-ref.mkvi
index bec96e05c23..d3c9325984a 100644
--- a/Master/texmf-dist/tex/context/base/strc-ref.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-ref.mkvi
@@ -5,7 +5,7 @@
%D subtitle=Cross Referencing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -13,9 +13,9 @@
% todo: (1) configure references, (2) rendering => with presets
%
-% \definestructureconversionset[default][Character,number,Romannumerals,Character][number]
-% \definestructureseparatorset [default][.,.,--][.]
-% \setupstructurehead[subsection][sectionstopper=),sectionsegments=4:4]
+% \defineconversionset[default][Character,number,Romannumerals,Character][number]
+% \defineseparatorset [default][.,.,--][.]
+% \setuphead[subsection][sectionstopper=),sectionsegments=4:4]
% \setupreferencestructureprefix[default][prefixsegments=2:4]
% \setupreferencestructureprefix[figure][default][prefixsegments=3:4]
% \chapter {One}
@@ -27,6 +27,7 @@
\writestatus{loading}{ConTeXt Structure Macros / Cross Referencing}
+\registerctxluafile{strc-rsc}{1.001}
\registerctxluafile{strc-ref}{1.001}
\registerctxluafile{node-ref}{1.001}
@@ -48,11 +49,6 @@
\let\showcurrentreference \relax
\let\setexecutecommandcheck\gobbletwoarguments
-\def\s!full{full}
-\def\s!user{user}
-\def\s!text{text}
-\def\s!page{page}
-
% todo : unknown/illegal reference no arg
% todo : +n pages check on 'samepage' (contrastcolor)
% todo : multiple text in reference
@@ -93,17 +89,17 @@
%D \reference[here]{some text}
%D \stoptyping
-\unexpanded\def\textreference {\dosingleargument\dotextreference}
-\unexpanded\def\pagereference {\dosingleargument\dopagereference}
-\unexpanded\def\reference {\dosingleargument\doreference }
-\unexpanded\def\setreference {\dodoubleargument\dosetreference }
+\unexpanded\def\textreference {\dosingleargument\strc_references_text_reference}
+\unexpanded\def\pagereference {\dosingleargument\strc_references_page_reference}
+\unexpanded\def\reference {\dosingleargument\strc_references_full_reference}
+\unexpanded\def\setreference {\dodoubleargument\strc_references_set_reference }
%D These are implemented in a low level form as:
-\def\dotextreference [#1]{\dodosetreference\s!text{#1}{}}
-\def\dopagereference [#1]{\dodosetreference\s!page{#1}{}{}}
-\def\doreference [#1]{\dodosetreference\s!full{#1}{}}
-\def\dosetreference[#1][#2]{\dodosetreference\s!user{#1}{#2}{}}
+\def\strc_references_text_reference [#labels]{\strc_references_set_named_reference\s!text{#labels}{}}
+\def\strc_references_page_reference [#labels]{\strc_references_set_named_reference\s!page{#labels}{}{}}
+\def\strc_references_full_reference [#labels]{\strc_references_set_named_reference\s!full{#labels}{}}
+\def\strc_references_set_reference[#labels][#settings]{\strc_references_set_named_reference\s!user{#labels}{#settings}{}}
%D Actually there is not much difference between a text and a
%D full reference, but it's the concept that counts. The low
@@ -112,57 +108,73 @@
\newcount\lastreferenceattribute
\newcount\lastdestinationattribute
-\def\dofinishfullreference#1#2{\normalexpanded{\ctxlatelua{structures.references.enhance("#1","#2")}}}
-\def\dofinishtextreference#1#2{\normalexpanded{\ctxlatelua{structures.references.enhance("#1","#2",{})}}}
+\def\dofinishfullreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label")}}}
+\def\dofinishtextreference#prefix#label{\normalexpanded{\ctxlatelua{structures.references.enhance("#prefix","#label",{})}}}
\let\dofinishpagereference\dofinishfullreference
\let\dofinishuserreference\dofinishfullreference
-\def\dofinishsomereference#1{\executeifdefined{dofinish#1reference}\gobbletwoarguments}
+\def\dofinishsomereference#kind{\executeifdefined{dofinish#{kind}reference}\gobbletwoarguments}
-\def\dodosetreference
+\def\strc_references_set_named_reference
{\ifreferencing
- \expandafter\dododosetreference
+ \expandafter\strc_references_set_named_reference_indeed
\else
\expandafter\gobblefourarguments
\fi}
-\def\dododosetreference#1#2#3#4% kind labels userdata text -> todo: userdata
+\newbox\b_strc_destination_nodes
+
+\unexpanded\def\strc_references_flush_destination_nodes
+ {\ifvoid\b_strc_destination_nodes \else
+ \unhbox\b_strc_destination_nodes
+ \fi}
+
+\unexpanded\def\strc_references_start_destination_nodes % messy but we need the delay
+ {\setbox\b_strc_destination_nodes\hbox\bgroup} % also sets lastdestinationattribute
+
+\unexpanded\def\strc_references_stop_destination_nodes
+ {\normalexpanded{\egroup\lastdestinationattribute\the\lastdestinationattribute\relax}}
+
+\unexpanded\def\strc_references_set_named_reference_indeed#kind#labels#userdata#text% labels userdata text -> todo: userdata
{\ifreferencing
% we could have a more efficient one for page references but for the moment
% we don't care too much
- \edef\currentreferencekind{#1}%
- \edef\currentreferencelabels{#2}%
- \edef\currentreferenceuserdata{#3}%
+ \edef\currentreferencekind {#kind}%
+ \edef\currentreferencelabels {#labels}%
+ \edef\currentreferenceuserdata {#userdata}%
\edef\currentreferenceexpansion{\@@rfexpansion}% {\referenceparameter\c!expansion}
- \ifx\currentreferencelabels\empty \else
+ \ifx\currentreferencelabels\empty
+ \lastdestinationattribute\attributeunsetvalue
+ \else
\ifx\currentreferenceexpansion\s!xml
\xmlstartraw
- \xdef\currentreferencedata{#4}% data, no text else conflict
+ \xdef\currentreferencedata{#text}% data, no text else conflict
\xmlstopraw
\globallet\currentreferencecoding\s!xml
\else
\ifx\currentreferenceexpansion\v!yes
- \xdef\currentreferencedata{#4}%
+ \xdef\currentreferencedata{#text}%
\else
- \xdef\currentreferencedata{\detokenize{#4}}%
+ \xdef\currentreferencedata{\detokenize{#text}}%
\fi
\globallet\currentreferencecoding\s!tex
\fi
% beware, the structures.references.set writes a
% \setnextinternalreference
- \ctxlua{structures.references.setandgetattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels",
- {
+ \strc_references_start_destination_nodes
+ \ctxlua{structures.references.setandgetattribute("\currentreferencekind", "\referenceprefix","\currentreferencelabels",
+ {
references = {
% internal = \nextinternalreference, % no need for an internal as we have an explicit
- block = "\currentstructureblock",
+ block = "\currentsectionblock",
section = structures.sections.currentid(),
},
metadata = { % we could assume page to have no metadata
- kind = "#1",
+ kind = "#kind", % \currentreferencekind
\ifx\currentreferencekind\s!page\else
catcodes = \the\catcodetable,
- xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument" \else nil \fi, % only useful when text
+ xmlroot = \ifx\currentreferencecoding\s!xml "\xmldocument"\else nil\fi, % only useful when text
\fi
},
\ifx\currentreferencedata\empty\else
@@ -171,53 +183,97 @@
},
\fi
\ifx\currentreferenceuserdata\empty\else
- userdata = structures.helpers.touserdata(\!!bs\detokenize{#3}\!!es)
+ userdata = structures.helpers.touserdata(\!!bs\detokenize{#userdata}\!!es)
\fi
},"\interactionparameter\c!focus")
- }%
- % todo: optional
- \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
- \begingroup\attribute\destinationattribute\currentdestinationattribute\emptyhbox\endgroup % todo
+ }%
+ \strc_references_stop_destination_nodes
\fi
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \fi
+ % will become obsolete:
+ \xdef\currentdestinationattribute{\number\lastdestinationattribute}%
+ % will become an option:
+ \ifnum\lastdestinationattribute>\zerocount
+ \dontleavehmode\hbox attr \destinationattribute\lastdestinationattribute\bgroup
+ \strc_references_flush_destination_nodes
+ \egroup
\fi}
-\def\defaultreferencepage#1{[[[#1]]]}
-\def\defaultreferencetext#1{[[[#1]]]}
+\def\strc_references_set_page_only_destination_attribute#labels% could in fact be fully expandable
+ {\ifreferencing
+ \edef\currentreferencelabels{#labels}%
+ \ifx\currentreferencelabels\empty
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \else
+ \strc_references_start_destination_nodes
+ \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","\currentreferencelabels",
+ {
+ references = {
+ block = "\currentsectionblock",
+ section = structures.sections.currentid(),
+ },
+ metadata = {
+ kind = "page",
+ },
+ },"\interactionparameter\c!focus")
+ }%
+ \strc_references_stop_destination_nodes
+ \fi
+ \else
+ \setbox\b_strc_destination_nodes\emptyhbox
+ \lastdestinationattribute\attributeunsetvalue
+ \fi}
+
+\def\strc_references_set_page_only_destination_box_attribute#cs#labels%
+ {\strc_references_set_page_only_destination_attribute{#labels}%
+ \ifnum\lastdestinationattribute>\zerocount
+ \edef#cs{attr \destinationattribute\number\lastdestinationattribute}%
+ \else
+ \let#cs\empty
+ \fi}
+
+% \ifx\currentdestinationattribute\empty
+% \begingroup\attribute\destinationattribute\currentdestinationattribute\emptyhbox\endgroup % todo
+% \fi
+
+\def\defaultreferencepage#text{[[[#text]]]}
+\def\defaultreferencetext#text{[[[#text]]]}
%D For internal usage:
-\def\dosetsimplepagereference#1% label
+\def\strc_references_set_simple_page_reference#label%
{\iflocation
- \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#1",
- {
+ \strc_references_start_destination_nodes
+ \ctxlua{structures.references.setandgetattribute("\s!page", "\referenceprefix","#label",
+ {
references = {
- % block = "\currentstructureblock",
+ % block = "\currentsectionblock",
% section = structures.sections.currentid(),
},
metadata = { % we could assume page to have no metadata
kind = "\s!page",
},
- },"\interactionparameter\c!focus")
- }%
+ },"\interactionparameter\c!focus")
+ }%
+ \strc_references_stop_destination_nodes
\xdef\currentdestinationattribute{\number\lastdestinationattribute}%
\else
+ \setbox\b_strc_destination_nodes\emptyhbox
\xdef\currentdestinationattribute{\number\attributeunsetvalue}%
\fi}
-\def\dogetsimplepagereference#1%
+\def\strc_references_get_simple_page_reference#label%
{\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#1",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
+ \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
\xdef\currentreferenceattribute{\number\lastreferenceattribute}%
\else
\xdef\currentreferenceattribute{\number\attributeunsetvalue}%
\fi}
-%D These macros depend on three other ones,
-%D \type {\makesectionformat}, that generated \type
-%D {\sectionformat}, \type {\pagenumber}. The not yet used
-%D argument \type{#1} is a tag that specifies the type of
-%D reference.
-
%D \macros
%D {everyreference}
%D
@@ -230,7 +286,7 @@
%D different alphabet and needs accented entries in registers.
\appendtoks
- \cleanupfeatures
+ \cleanupfeatures
\to \everyreference
%D We did not yet discuss prefixing. Especially in interactive
@@ -257,8 +313,7 @@
%D \NC \NC $\star$ \NC \NC\NR
%D \stoptabulate
-\def\usereferences[#1]% not yet
- {\writestatus\m!system{references from other files are handled automatically}}
+\unexpanded\def\usereferences[#filename]{} % obsolete
%D As mentioned we will also use the cross reference mechanism
%D for navigational purposes. The main reason for this is that
@@ -290,28 +345,15 @@
\let\currentsubtextreference \empty
\let\currentsubsubtextreference\empty
-\newcount\referencepagestate % set in backend
\newcount\referencehastexstate % set in backend
+\def\referencepagestate{\ctxcommand{referencepagestate()}}
+\def\referencerealpage {\ctxcommand{referencerealpage ()}}
+
% referencepagestate:
%
% 0 = no page ref, 1=same page, 2=before, 3=after
-%D Text references can contain more than one entry and
-%D therefore we check for
-%D
-%D \starttyping
-%D {entry}
-%D \stoptyping
-%D
-%D or
-%D
-%D \starttyping
-%D {{entry}{entry}{entry}}
-%D \stoptyping
-%D
-%D and split accordingly.
-
%D Cross references appear as numbers (figure~1.1, chapter~2)
%D or pagenumbers (page~2, page 3--2), and are called with
%D \type{\in} and \type{\at}. In interactive documents we also
@@ -333,27 +375,6 @@
%D references for instance refer to a \JAVASCRIPT. The last
%D example shows that we can pass arguments to the actions.
%D
-%D When we split off the components of such a reference, the
-%D results are available in:
-%D
-%D \starttyping
-%D \currentreferencespecial
-%D \currentreferenceoperation
-%D \currentreferencearguments
-%D \currentinnerreference
-%D \currentouterreference
-%D \currentfullreference
-%D \stoptyping
-
-\newif\ifreferencefound
-
-% \let\currentfullreference \empty
-% \let\currentreferencespecial \empty
-% \let\currentreferenceoperation\empty
-% \let\currentreferencearguments\empty
-% \let\currentouterreference \empty
-% \let\currentinnerreference \empty
-
%D Now we've come to the testing step. As we can see below,
%D this macro does bit more than testing: it also resolves
%D the reference. This means that whenever we test for the
@@ -413,16 +434,16 @@
%D true.
\unexpanded\def\definereference
- {\dodoubleempty\dodefinereference}
+ {\dodoubleempty\strc_references_define_reference}
-\def\dodefinereference[#1][#2]%
- {\ctxlua{structures.references.define("\referenceprefix","#1",\!!bs\detokenize{#2}\!!es)}}
+\def\strc_references_define_reference[#name][#specification]%
+ {\ctxlua{structures.references.define("\referenceprefix","#name",\!!bs\detokenize{#specification}\!!es)}}
-\def\resetreference[#1]%
- {\ctxlua{structures.references.reset("\referenceprefix","#1")}}
+\unexpanded\def\resetreference[#name]%
+ {\ctxlua{structures.references.reset("\referenceprefix","#name")}}
-\def\setpagereference#1#2% name, specification
- {\ctxlua{structures.references.define("","#1",\!!bs\v!page(\luaescapestring{#2})\!!es)}}
+\def\setpagereference#name#specification% hm,. low level ?
+ {\ctxlua{structures.references.define("","#name",\!!bs\v!page(\luaescapestring{#specification})\!!es)}}
%D Chained references are defined as:
%D
@@ -454,13 +475,14 @@
\def\expandtexincurrentreference % will happen in lua some time
{\ifcase\referencehastexstate\else\ctxlua{structures.references.expandcurrent()}\fi}
-\def\expandreferenceoperation#1#2{\ctxcommand{setreferenceoperation(#1,\!!bs#2\!!es)}}
-\def\expandreferencearguments#1#2{\ctxcommand{setreferencearguments(#1,\!!bs#2\!!es)}}
+\def\expandreferenceoperation#tag#content{\ctxcommand{setreferenceoperation(#tag,\!!bs#content\!!es)}}
+\def\expandreferencearguments#tag#content{\ctxcommand{setreferencearguments(#tag,\!!bs#content\!!es)}}
-\def\doifreferencefoundelse#1#2#3%
- {\ctxlua{structures.references.doifelse("\referenceprefix","#1",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}%
- {\expandtexincurrentreference#2}%
- {#3}}
+\def\doifreferencefoundelse#labels#yes#nop%
+ {\ctxlua{structures.references.doifelse("\referenceprefix","#labels",\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow)}%
+ {\expandtexincurrentreference
+ #yes}%
+ {#nop}}
%D The tester only splits the reference in components but does
%D not look into them. The following macro does a preroll and
@@ -469,9 +491,6 @@
%D one wants to use the pagestate the next macro seldom needs to
%D be called.
-\def\analyzecurrentreference
- {\ctxlua{structures.references.analyze()}}
-
%D The inner case is simple. Only two cases have to be taken
%D care of:
%D
@@ -494,13 +513,6 @@
%D An unknown reference is reported on the screen, in the log
%D file and, when enabled, in the left margin of the text.
-% \def\unknownreference#1%
-% {\iftrialtypesetting \else
-% \ifinpagebody \else
-% \doifconcepttracing{\doifsomething{#1}{\inleft{\infofont\doboundtext{#1}{\dimexpr\leftmarginwidth-2em\relax}{..}->}}}%
-% \fi
-% \fi}
-
\let\unknownreference\gobbleoneargument
%D When a reference is not found, we typeset a placeholder
@@ -575,29 +587,29 @@
\def\setnextinternalreference
{\global\advance\locationcount\plusone}
-\def\setnextinternalreferences#1#2% plural
- {\ctxlua{structures.references.setnextinternal("#1","#2")}}
+\def\setnextinternalreferences#kind#name% plural
+ {\ctxlua{structures.references.setnextinternal("#kind","#name")}}
-\def\getinternalorderreference#1#2%
- {\ctxlua{structures.references.currentorder("#1","#2")}}
+\def\getinternalorderreference#kind#name%
+ {\ctxlua{structures.references.currentorder("#kind","#name")}}
-\def\thisissomeinternal#1#2% tag reference (only for old time sake)
+\def\thisissomeinternal#kind#name% only for old time sake
{\begingroup
- \ctxlua{structures.references.setinternalreference("","#1:#2")}%
+ \ctxlua{structures.references.setinternalreference("","#kind:#name")}%
\hbox attr \destinationattribute\lastdestinationattribute{}%
\endgroup}
\newconditional\preferpagereferences
-\def\gotosomeinternal#1#2#3#4%
+\def\gotosomeinternal#kind#name#target#text%
{\ifconditional\preferpagereferences
- \directgoto{#4}[page(#3)]%
+ \directgoto{#text}[page(#target)]%
\else
- \directgoto{#4}[#1:#2]%
+ \directgoto{#text}[#kind:#name]%
\fi}
-\def\gotonextinternal#1#2%
- {\directgoto{#1}[internal(#2)]}
+\def\gotonextinternal#text#target%
+ {\directgoto{#text}[internal(#target)]}
%D In this module we define three system references: one for
%D handling navigational, viewer specific, commands, another
@@ -618,10 +630,6 @@
%D \goto{some text}[\v!action(PreviousJump]
%D \stoptyping
-% compatibility hack
-
-\def\setglobalsystemreference#1#2#3{\definereference[#2][\v!action(#3)]}
-
\newif\ifreferencing \referencingtrue
%D One can also activate an automatic prefix mechanism. By
@@ -640,16 +648,13 @@
%D document). By setting the \type{interaction} variable, one
%D can influences the way interactive references are set.
-\newconstant\autocrossfilereferences % not yet supported in mkiv
-\newconstant\referencefilecaseswap % not yet supported in mkiv
-
\newtoks \everysetupreferencing
\unexpanded\def\setupreferencing
- {\dosingleargument\dosetupreferencing}
+ {\dosingleargument\strc_references_setup_referencing}
-\def\dosetupreferencing[#1]%
- {\getparameters[\??rf][\c!prefix=\s!unknown,#1]%
+\def\strc_references_setup_referencing[#settings]%
+ {\getparameters[\??rf][\c!prefix=\s!unknown,#settings]%
\the\everysetupreferencing}
\appendtoks
@@ -659,65 +664,29 @@
\v!start=>\referencingtrue]%
\to \everysetupreferencing
-% \newconstant \referencecontentmode
-%
-% \appendtoks
-% \processaction
-% [\@@rfinteraction]
-% [ \v!all=>\referencecontentmode\zerocount,
-% \v!label=>\referencecontentmode\plusone,
-% \v!text=>\referencecontentmode\plustwo,
-% \v!symbol=>\referencecontentmode\plusthree]%
-% \to \everysetupreferencing
-
-\appendtoks
- \autocrossfilereferences\zerocount
- \processaction
- [\@@rfautofile] % not yet in mkiv
- [ \v!yes=>\autocrossfilereferences\plusone,
- \v!page=>\autocrossfilereferences\plustwo]%
-\to \everysetupreferencing
-
-\appendtoks
- \referencefilecaseswap\zerocount
- \processaction[\@@rfconvertfile] % not yet in mkiv
- [ \v!yes=>\referencefilecaseswap\plusone,
- \v!big=>\referencefilecaseswap\plusone,
- \v!small=>\referencefilecaseswap\plustwo]%
-\to \everysetupreferencing
+\newconditional\autocrossfilereferences
\appendtoks
- \setupreferenceprefix[\@@rfprefix]%
- \doifelse\@@rfglobal\v!yes
- {\settrue \autoglobalfilereferences}%
- {\setfalse\autoglobalfilereferences}%
+ \doifelse\@@rfautofile\v!yes\settrue\setfalse\autocrossfilereferences
\to \everysetupreferencing
-% \appendtoks\ctxlua{structures.references.export("whatever")}\to\everystoptext
-% \starttext
-% \chapter[test]{test}
-% test \in{IN}[more] and \in{IN}[test] or \at{AT}[more] and \at{AT}[test]\par
-% test \in{IN}[whatever::more] and \in{IN}[whatever::test] or \at{AT}[whatever::more] and \at{AT}[whatever::test] \page
-% reference\reference[more]{oeps}
-% \stoptext
-
\def\exportreferences
{\doif\@@rfexport\v!yes{\ctxlua{structures.references.export()}}}
\appendtoks
- \exportreferences
+ \exportreferences
\to \everygoodbye
\def\incrementreferenceprefix{+}
\def\decrementreferenceprefix{-}
-\unexpanded\def\setupreferenceprefix[#1]%
- {\edef\@@rfprefix{#1}%
+\unexpanded\def\setupreferenceprefix[#prefix]%
+ {\edef\@@rfprefix{#prefix}%
\ifx\@@rfprefix\empty
\let\referenceprefix\empty
\else\ifx\@@rfprefix\incrementreferenceprefix
\advance\prefixcounter \plusone % should be global
- \edef\referenceprefix{\the\prefixcounter:}%
+ \edef\referenceprefix{\the\prefixcounter}%
\let\@@rfprefix\s!unknown
\else\ifx\@@rfprefix\decrementreferenceprefix
\let\referenceprefix\empty
@@ -725,57 +694,22 @@
\else\ifx\@@rfprefix\s!unknown
% forget about it
\else
- \edef\referenceprefix{\@@rfprefix:}%
+ \edef\referenceprefix{\@@rfprefix}% expanded !
\fi\fi\fi\fi}
-%D The most straightforward way of retrieving references is
-%D using \type{\ref}. Consider the reference:
-%D
-%D \startbuffer
-%D \reference[my ref]{{Look}{Here}{I am}}
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D \getbuffer
-%D
-%D We can ask for upto five reference components:
-%D
-%D \startbuffer
-%D user page reference: \ref[p][my ref]
-%D text reference: \ref[t][my ref]
-%D real page reference: \ref[r][my ref]
-%D sub text reference: \ref[s][my ref]
-%D extra text reference: \ref[e][my ref]
-%D \stopbuffer
-%D
-%D \typebuffer
-%D
-%D And get back:
-%D
-%D \startlines
-%D \getbuffer
-%D \stoplines
-%D
-%D This is a cheap compatibility hack. Don't use this command
-%D as there will be more advanced access to user data.
+\unexpanded\def\setupglobalreferenceprefix[#prefix]%
+ {\xdef\referenceprefix{#prefix}}
-\def\ref{\dodoubleargument\doref}
+\unexpanded\def\pushreferenceprefix#prefix%
+ {\pushmacro\referenceprefix
+ \xdef\referenceprefix{#prefix}}
-\def\reftypep{\currentreferencepage}
-\def\reftypet{\currentreferencetext}
-\def\reftyper{\currentreferencepage}
-\def\reftypes{\currentreferencetext}
-\def\reftypee{\currentreferencetext}
+\unexpanded\def\popreferenceprefix
+ {\popmacro\referenceprefix}
-\def\doref[#1][#2]%
- {\ifsecondargument
- \doifreferencefoundelse{#2}
- {\executeifdefined{reftype#1}\reftypep}
- {\dummyreference}%
- \else
- \dummyreference
- \fi}
+\appendtoks
+ \setupreferenceprefix[\@@rfprefix]
+\to \everysetupreferencing
%D We can typeset a reference using \type{\in}, \type{\at} and
%D \type{\about} and goto specific locations using
@@ -821,36 +755,62 @@
%D and~\type{[} becomes active (and when asked for, typeset
%D in a different color and typeface).
-% \unexpanded\def\in {\mathortext\donormalmathin \dospecialin}
-% \unexpanded\def\at {\mathortext\donormalmathat \dospecialat}
-% \unexpanded\def\about{\mathortext\donormalmathabout\dospecialabout}
-% \unexpanded\def\from {\mathortext\donormalmathfrom \dospecialfrom}
-% \unexpanded\def\over {\mathortext\donormalmathover \dospecialabout}
+% \unexpanded\def\in {\mathortext\donormalmathin \strc_references_in}
+% \unexpanded\def\at {\mathortext\donormalmathat \strc_references_at}
+% \unexpanded\def\about{\mathortext\donormalmathabout\strc_references_about}
+% \unexpanded\def\from {\mathortext\donormalmathfrom \strc_references_from}
+% \unexpanded\def\over {\mathortext\donormalmathover \strc_references_about}
+
+% \definecommand in {\strc_references_in}
+% \definecommand at {\strc_references_at}
+% \definecommand about {\strc_references_about}
+% \definecommand from {\strc_references_from}
+% \definecommand over {\strc_references_about} % needed here, else math problems
-% \definecommand in {\dospecialin}
-% \definecommand at {\dospecialat}
-% \definecommand about {\dospecialabout}
-% \definecommand from {\dospecialfrom}
-% \definecommand over {\dospecialabout} % needed here, else math problems
+\appendtoks
+ \ifdefined\in \let\normalmathin \in \unexpanded\def\in {\mathortext\normalmathin \strc_references_in } \else \let\in \strc_references_in \fi
+ \ifdefined\at \let\normalmathat \at \unexpanded\def\at {\mathortext\normalmathat \strc_references_at } \else \let\at \strc_references_at \fi
+ \ifdefined\about \let\normalmathabout\about \unexpanded\def\about{\mathortext\normalmathabout\strc_references_about} \else \let\about\strc_references_about \fi
+ \ifdefined\from \let\normalmathfrom \from \unexpanded\def\from {\mathortext\normalmathfrom \strc_references_from } \else \let\from \strc_references_from \fi
+ \ifdefined\over \let\normalmathover \over \unexpanded\def\over {\mathortext\normalmathover \strc_references_about} \else \let\over \strc_references_about \fi
+\to \everydump
+
+ \def\filterreference #key{\ctxcommand{filterreference("#key")}} % no checking, expanded
+\unexpanded\def\getreferenceentry#key{\ctxcommand{filterreference("#key")}} % no checking, unexpanded
+
+\def\currentreferencenumber {\filterreference{number}}
+\def\currentreferencepage {\filterreference{page}}
+\def\currentreferencetitle {\filterreference{title}}
+\def\currentreferencetext {\filterreference{text}}
+\def\currentreferencedefault {\filterreference{default}}
+\def\currentreferencerealpage{\filterreference{realpage}}
+
+%D The most straightforward way of retrieving references is
+%D using \type{\ref}.
+
+\unexpanded\def\getreference % checking, unexpanded
+ {\dodoubleargument\strc_references_get_reference}
+
+\def\strc_references_get_reference[#key][#label]% #key = number page title text default realpage ...
+ {\ifsecondargument
+ \doifreferencefoundelse{#label}{\ctxcommand{filterreference("#key")}}\dummyreference
+ \else
+ \dummyreference
+ \fi}
-\def\currentreferencenumber {\ctxlua{structures.references.filter("number")}}
-\def\currentreferencepage {\ctxlua{structures.references.filter("page")}}
-\def\currentreferencetitle {\ctxlua{structures.references.filter("title")}}
-\def\currentreferencetext {\ctxlua{structures.references.filter("text")}}
-\def\currentreferencedefault {\ctxlua{structures.references.filter("default")}}
-\def\currentreferencerealpage{\ctxlua{structures.references.realpage()}}
+\let\ref\getreference
-\def\getreferenceentry#1{\ctxlua{structures.references.filter("#1")}} % user entry
+%D Special cases:
-\unexpanded\def\dospecialabout[#1]%
+\unexpanded\def\strc_references_about[#label]%
{\dontleavehmode
\begingroup
\let\crlf\space
\let\\\space
\postponenotes
\@@rfleft
- \doifreferencefoundelse{#1}
- {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#1]}% not so efficient (dup lookup)
+ \doifreferencefoundelse{#label}
+ {\goto{\limitatetext\currentreferencetitle\@@rfwidth\unknown}[#label]}% not so efficient (dup lookup)
{}% todo
\@@rfright
\endgroup}
@@ -862,57 +822,47 @@
%D $^\gobackwardcharacter$ $^\gonowherecharacter$}, depending
%D on the direction to go.
-% 1 = whatever
-% 2 = forward, following page
-% 3 = backward, preceding page
-% 4 = forward, same page
-% 5 = backward, same page
-
-% Yet untested:
-
-\unexpanded\def\somewhere#1#2#3[#4]% #3 gobbles space around #2 % todo
- {\doifreferencefoundelse{#4}% kind of inefficient as \goto also analyzes
- {\goto{\analyzecurrentreference\ifcase\referencepagestate\relax#1/#2\or#2\or#1\or#2\fi}[#4]}
- {[#1/#2]}}
-
-\unexpanded\def\atpage[#1]% todo
- {\doifreferencefoundelse{#1}% kind of inefficient as \goto also analyzes
- {\goto{\analyzecurrentreference\ifcase\referencepagestate
- \labeltexts\v!page\dummyreference
- \or
- \labeltexts\v!atpage\currentreferencepage
- \or
- \labeltexts\v!atpage\currentreferencepage
- \or
- \labeltexts\v!atpage\currentreferencepage
- \or
- \labeltext\v!hereafter
- \or
- \labeltext\v!hencefore
- \fi}[#1]}
- {[?]}}
+% 0 = unknown
+% 1 = same
+% 2 = before
+% 3 = after
+
+% \def\strc_references_by_reference_page_state#unknown#before#current#after%
+% {\ifcase\referencepagestate\relax#unknown\or#current\or#before\or#after\fi}
+%
+% this fails in an expansion as the \relax stays, so we need:
+
+\def\strc_references_by_reference_page_state#unknown#before#current#after%
+ {\ifcase\referencepagestate\space#unknown\or#current\or#before\or#after\fi}
+
+\unexpanded\def\somewhere#backward#foreward#dummy[#label]% #dummy gobbles space around #foreward
+ {\doifreferencefoundelse{#label}% usage needs checking (useless)
+ {\goto{\strc_references_by_reference_page_state{#label}{#backward}{}{#foreward}}[#label]}
+ {[#label]}}
+
+\unexpanded\def\atpage[#label]% todo
+ {\doifreferencefoundelse{#label}% kind of inefficient as \goto also analyzes
+ {\goto
+ {\strc_references_by_reference_page_state
+ {\labeltexts\v!page\dummyreference}%
+ {\labeltext\v!hencefore}%
+ {\labeltexts\v!atpage\currentreferencepage}%
+ {\labeltext\v!hereafter}}%
+ [#label]}
+ {[#label]}}
\unexpanded\def\referencesymbol
{\hbox{\strut\high
{\setupsymbolset[\interactionparameter\c!symbolset]%
- \symbol
- [\ifcase\referencepagestate
- \v!somewhere
- \or % same
- \v!nowhere
- \or % before
- \v!previous
- \or % after
- \v!next%
- \fi]}}}
+ \symbol[\strc_references_by_reference_page_state\v!somewhere\v!nowhere\v!previous\v!next]}}}
%D The other alternatives just conform their names: only the
%D label, only the text, or the label and the text.
% \dounknownreference -> \dummyreference
-\def\symbolreference[#1]% for old times sake
- {\goto{\referencesymbol}[#1]}
+\def\symbolreference[#label]% for old times sake
+ {\goto{\referencesymbol}[#label]}
% \referencecontentmode 0=all 1=label 2=text 3=symbol
@@ -927,13 +877,13 @@
\let\rightofreference \empty
\setvalue{\??rf\c!interaction\v!all}%
- {\leftofreference
- \the\leftreferencetoks
+ {\the\leftreferencetoks
\doifsometokselse\leftreferencetoks \leftofreferencecontent \donothing
+ \leftofreference
\currentreferencecontent
+ \rightofreference
\doifsometokselse\rightreferencetoks\rightofreferencecontent\donothing
- \the\rightreferencetoks
- \rightofreference}
+ \the\rightreferencetoks}
\setvalue{\??rf\c!interaction\v!label}%
{\leftofreference
@@ -965,40 +915,41 @@
\glet\rightofreference\relax
\to \everyresetinatreference
-\def\dostartgotoreference
+\def\strc_references_start_goto
{\dontleavehmode
\begingroup}
-\def\dostopgotoreference
+\def\strc_references_stop_goto
{\the\everyresetinatreference
\endgroup}
-\def\dopickupgotoreference
- {\dodoublegroupempty\dodopickupgotoreference}
+\def\strc_references_pickup_goto
+ {\dodoublegroupempty\strc_references_pickup_goto_indeed}
-\def\dodopickupgotoreference#1#2#3[#4]% #3 gobbles spaces (really needed)
+\def\strc_references_pickup_goto_indeed#left#right#dummy[#label]% #dummy gobbles spaces (really needed)
{\leftreferencetoks
\iffirstargument
- {#1}%
+ {#left}%
\else
\defaultleftreferencetoks
\let\leftofreferencecontent\empty
\fi
\rightreferencetoks
\ifsecondargument
- {#2}%
+ {#right}%
\else
\defaultrightreferencetoks
\let\rightofreferencecontent\empty
\fi
- \doifreferencefoundelse{#4} % we need to resolve the text
- {\goto{\referencesequence}[#4]}
+ % inefficient: double resolve
+ \doifreferencefoundelse{#label} % we need to resolve the text
+ {\goto{\referencesequence}[#label]}
{\let\currentreferencecontent\dummyreference
- \goto{\referencesequence}[#4]}%
- \dostopgotoreference}
+ \goto{\referencesequence}[#label]}%
+ \strc_references_stop_goto}
-\unexpanded\def\dospecialin{\dostartgotoreference\let\currentreferencecontent\currentreferencedefault\dopickupgotoreference}
-\unexpanded\def\dospecialat{\dostartgotoreference\let\currentreferencecontent\currentreferencepage \dopickupgotoreference}
+\unexpanded\def\strc_references_in{\strc_references_start_goto\let\currentreferencecontent\currentreferencedefault\strc_references_pickup_goto}
+\unexpanded\def\strc_references_at{\strc_references_start_goto\let\currentreferencecontent\currentreferencepage \strc_references_pickup_goto}
%D \macros
%D {definereferenceformat}
@@ -1023,7 +974,6 @@
%D Instead of a text, one can specify a label, which should
%D be defined with \type {\setuplabeltext}.
%D
-%D
%D Watch out: the second argument is somewhat special and mostly
%D meant for a suffix to a number:
%D
@@ -1042,45 +992,50 @@
%D
%D \typebuffer \getbuffer
-% todo: inherit
-
-\let\currentreferenceformat\empty
+% to be done: interfaced
-\def\referenceformatparameter#1% some day we will add inheritance
- {\ifcsname\??rf\currentreferenceformat#1\endcsname\csname\??rf\currentreferenceformat#1\expandafter\endcsname\fi}
+\installcorenamespace{referenceformat}
-\unexpanded\def\definereferenceformat
- {\dodoubleargument\dodefinereferenceformat}
+\installcommandhandler \??referenceformat {referenceformat} \??referenceformat
-% left right text label
-
-\def\dodefinereferenceformat[#1][#2]%
- {\iffirstargument
- \getparameters[\??rf#1][\c!left=,\c!right=,\c!text=,\c!label=,\c!autocase=v!no,#2]%
- \setuvalue{#1}{\doexecutereferenceformat{#1}}%
- \fi}
+\appendtoks
+ \setuevalue\currentreferenceformat{\strc_references_apply_format{\currentreferenceformat}}%
+\to \everydefinereferenceformat
+
+\setupreferenceformat
+ [\c!left=,
+ \c!right=,
+ \c!text=,
+ \c!label=,
+ \c!autocase=\v!no,
+ \c!style=,
+ \c!type=default, % to be done: interfaced
+ \c!setups=,
+ \c!color=]
-\def\doexecutereferenceformat#1% quite slow due to all assignments but we will speed it up
- {\dostartgotoreference % once it's stable
- \edef\currentreferenceformat{#1}%
- \gdef\leftofreference {\referenceformatparameter\c!left }%
- \gdef\rightofreference{\referenceformatparameter\c!right}%
- % we can make a helper for this .. we will use the new parameter handler anyway
- % but at least aditya can play with it now
- \doifsomething{\referenceformatparameter\c!style}
- {\dosetfontattribute{\??rf\currentreferenceformat}\c!style
- \resetinteractionparameter\c!style}%
- \doifsomething{\referenceformatparameter\c!color}
- {\dosetcolorattribute{\??rf\currentreferenceformat}\c!color
- \resetinteractionparameter\c!contrastcolor
- \resetinteractionparameter\c!color}%
- %
- \edef\currentreferenceformatlabel{\referenceformatparameter\c!label}%
+\unexpanded\def\strc_references_apply_format#name%
+ {\strc_references_start_goto
+ \edef\currentreferenceformat{#name}%
+ \gdef\leftofreference {\referenceformatparameter\c!left }%
+ \gdef\rightofreference {\referenceformatparameter\c!right }%
+ \edef\currentreferenceformatlabel {\referenceformatparameter\c!label }%
+ \edef\currentreferenceformattype {\referenceformatparameter\c!type }%
+ \edef\currentreferenceformatsetups {\referenceformatparameter\c!setups }%
+ \edef\currentreferenceformatautocase{\referenceformatparameter\c!autocase}%
+ \usereferenceformatstyleandcolor\c!style\c!color
+ \ifx\currentstyleparameter\empty \else
+ \resetinteractionparameter\c!style
+ \fi
+ \ifx\currentcolorparameter\empty \else
+ \resetinteractionparameter\c!contrastcolor
+ \resetinteractionparameter\c!color
+ \fi
\ifx\currentreferenceformatlabel\autoreferencelabeltextflag
\edef\currentreferenceformatlabel{\autoreferencelabeltext}%
\fi
- \doif{\referenceformatparameter\c!autocase}\v!yes
- {\setcharactercleaning[1]}%
+ \ifx\currentreferenceformatautocase\v!yes
+ \setcharactercleaning[1]%
+ \fi
\ifx\currentreferenceformatlabel\empty
\defaultleftreferencetoks {\referenceformatparameter\c!text}%
\defaultrightreferencetoks\emptytoks
@@ -1088,12 +1043,19 @@
\defaultleftreferencetoks {\leftlabeltext \currentreferenceformatlabel}%
\defaultrightreferencetoks{\rightlabeltext\currentreferenceformatlabel}%
\fi
- \doifelse{\referenceformatparameter\c!type}\v!page
- {\let\currentreferencecontent\currentreferencepage}
- {\let\currentreferencecontent\currentreferencedefault}%
+ \ifx\currentreferenceformattype\empty
+ \def\currentreferenceformattype{default}%
+ \fi
+ %
+ \ifx\currentreferenceformatsetups\empty
+ \def\currentreferencecontent{\filterreference\currentreferenceformattype}%
+ \else
+ \def\currentreferencecontent{\directsetup\currentreferenceformatsetups}%
+ \fi
+ %
\let\leftofreferencecontent \empty
\let\rightofreferencecontent\empty
- \dopickupgotoreference}
+ \strc_references_pickup_goto}
\def\autoreferencelabeltextflag{*} % a proper key like 'auto' or 'name' can clash with a label key
@@ -1112,6 +1074,12 @@
% [\inxx{a}{b}[one]]
% \stoptext
+% \startsetups referenceformat:numberplustext
+% \filterreference{number}, \filterreference{title}
+% \stopsetups
+%
+% \definereferenceformat[hellup][text=Hellup ,setups=referenceformat:numberplustext]
+
%D In interactive documents going to a specific location is not
%D bound to cross references. The \type{\goto} commands can be
%D used to let users access another part of the document. In
@@ -1136,10 +1104,22 @@
\newconditional\uselocationstrut \settrue\uselocationstrut
-\def\extrareferencearguments{\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow,"\currentviewerlayer"}
+\def\extrareferencearguments
+ {\luaconditional\highlighthyperlinks,\luaconditional\gotonewwindow,"\currentviewerlayer"}
+
+\unexpanded\def\directgoto
+ {\ifconditional\uselocationstrut
+ \expandafter\dodirectgoto
+ \else
+ \expandafter\dodirectgotohtdp
+ \fi}
-\unexpanded\def\directgoto{\ifconditional\uselocationstrut\expandafter\dodirectgoto\else\expandafter\directgotohtdp\fi}
-\unexpanded\def\goto {\ifconditional\uselocationstrut\expandafter\dogoto \else\expandafter\gotohtdp \fi}
+\unexpanded\def\goto
+ {\ifconditional\uselocationstrut
+ \expandafter\dogoto
+ \else
+ \expandafter\dogotohtdp
+ \fi}
% The unbox trick is needed in order to permit \par inside a reference. Otherwise
% the reference attribute migrates to the outer boxes.
@@ -1151,165 +1131,167 @@
\def\revivesavedreferenceattribute % sometimes handy as no test etc needed
{\attribute\referenceattribute\lastsavedreferenceattribute}
-\def\dodirectgoto#1[#2]% no test for valid references
+\def\dodirectgoto#content[#label]% no test for valid references
{\dontleavehmode
\begingroup
\attribute\referenceattribute\attributeunsetvalue
\global\lastsavedreferenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#2",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
- \setlocationattributes\??ia
+ \ctxlua{structures.references.inject("\referenceprefix","#label",\number\ht\strutbox,\number\dp\strutbox,\extrareferencearguments)}%
+ \setlocationattributes
\setstrut % can be option
\global\lastsavedreferenceattribute\lastreferenceattribute
\attribute\referenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty % not here
- #1%
+ #content%
\dostoptagged
\else
- #1%
+ #content%
\fi
\endgroup}
-\def\dodirectgotohtdp#1[#2]% no test for valid references
+\def\dodirectgotohtdp#content[#label]% no test for valid references
{\dontleavehmode
\begingroup
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#2",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}%
- \setlocationattributes\??ia
+ \ctxlua{structures.references.inject("\referenceprefix","#label",\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax,\extrareferencearguments)}%
+ \setlocationattributes
\attribute\referenceattribute\lastreferenceattribute
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
- #1%
+ #content%
\dostoptagged
\else
- #1%
+ #content%
\fi
\endgroup}
-\def\dogoto#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok
+\def\dogoto#content#dummy[#label]% #dummy gobbles spaces
{\dontleavehmode
\begingroup
%\setbox\referencebox\hbox\bgroup % experiment, might change again to non \par support
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}%
+ \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
{\expandtexincurrentreference
\ctxlua{structures.references.injectcurrentset(\number\ht\strutbox,\number\dp\strutbox)}%
- \setlocationattributes\??ia
+ \setlocationattributes
\setstrut % can be option
\global\lastsavedreferenceattribute\lastreferenceattribute
\attribute\referenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
- #1%
+ #content%
\dostoptagged}%
- {#1}%
+ {#content}%
\else
- #1%
+ #content%
\fi
%\egroup\unhbox\referencebox}
\endgroup}
-\def\dogotohtdp#1#2[#3]% #2 gobbles spaces after #1 so that \goto{xx} [yy] works ok
+\def\dogotohtdp#content#dummy[#label]% dummy gobbles spaces
{\dontleavehmode
\begingroup
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}%
+ \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
{\expandtexincurrentreference
\ctxlua{structures.references.injectcurrentset(\number\dimexpr\interactionparameter\c!height\relax,\number\dimexpr\interactionparameter\c!depth\relax)}%
- \setlocationattributes\??ia
+ \setlocationattributes
\global\lastsavedreferenceattribute\lastreferenceattribute
\attribute\referenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
- #1%
+ #content%
\dostoptagged}%
- {#1}%
+ {#content}%
\else
- #1%
+ #content%
\fi
\endgroup}
-\unexpanded\def\directgotobox#1[#2]% no test for valid references
+\unexpanded\def\directgotobox#content[#label]% no test for valid references
{\dontleavehmode
\begingroup
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}%
- \setlocationattributes\??ia
+ \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
+ \setlocationattributes
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
- \hbox attr \referenceattribute \lastreferenceattribute {#1}%
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
\dostoptagged
\else
- #1%
+ #content%
\fi
\endgroup}
-\unexpanded\def\directgotospecbox#1#2[#3]% no test for valid references
+\unexpanded\def\directgotospecbox#resolver#content[#label]% no test for valid references
{\dontleavehmode
\begingroup
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#3",nil,nil,\extrareferencearguments)}%
- \setlocationcolorspec{#1}% no consequence for strut
+ \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
+ \setlocationcolorspec{#resolver}% no consequence for strut
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
- \hbox attr \referenceattribute \lastreferenceattribute {#2}%
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
\dostoptagged
\else
- #2%
+ #content%
\fi
\endgroup}
-\unexpanded\def\directgotodumbbox#1[#2]% no test for valid references
+\unexpanded\def\directgotodumbbox#content[#label]% no test for valid references
{\dontleavehmode
\begingroup
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.inject("\referenceprefix","#2",nil,nil,\extrareferencearguments)}%
+ \ctxlua{structures.references.inject("\referenceprefix","#label",nil,nil,\extrareferencearguments)}%
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
- \hbox attr \referenceattribute \lastreferenceattribute {#1}%
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
\dostoptagged
\else
- #1%
+ #content%
\fi
\endgroup}
-\unexpanded\def\gotobox#1[#2]% no test for valid references
+\unexpanded\def\gotobox#content[#label]%
{\dontleavehmode
\begingroup
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
\iflocation
- \ctxlua{structures.references.doifelse("\referenceprefix","#2",\extrareferencearguments)}%
+ \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
{\expandtexincurrentreference
\ctxlua{structures.references.injectcurrentset(nil,nil)}%
- \setlocationattributes\??ia
+ \setlocationattributes
\global\lastsavedreferenceattribute\lastreferenceattribute
\dostarttagged\t!link\empty
- \hbox attr \referenceattribute \lastreferenceattribute {#1}%
+ \hbox attr \referenceattribute \lastreferenceattribute {#content}%
\dostoptagged}%
- {#1}%
+ {#content}%
\else
- #1%
+ #content%
\fi
\endgroup}
-\unexpanded\def\gotowdhtbox#1#2[#3]% fast variant for overlays
+\unexpanded\def\gotowdhtbox#width#height[#label]% fast variant for overlays
{\dontleavehmode
\begingroup
- \setbox\scratchbox\emptyhbox\wd\scratchbox#1\ht\scratchbox#2%
+ \setbox\scratchbox\emptyhbox
+ \wd\scratchbox#width%
+ \ht\scratchbox#height%
\global\lastsavedreferenceattribute\attributeunsetvalue
\attribute\referenceattribute\attributeunsetvalue
- \ctxlua{structures.references.doifelse("\referenceprefix","#3",\extrareferencearguments)}%
+ \ctxlua{structures.references.doifelse("\referenceprefix","#label",\extrareferencearguments)}%
{\ctxlua{structures.references.injectcurrentset(nil,nil)}%
\global\lastsavedreferenceattribute\lastreferenceattribute
\hbox attr \referenceattribute \lastreferenceattribute {\box\scratchbox}}
@@ -1365,20 +1347,20 @@
%D specified. This is logical when one keeps in mind that a
%D valid \URL\ can also be a mail address.
-\unexpanded\def\usefile{\dotripleargument\dousefile} % so that they can be used in expanded arguments
-\unexpanded\def\useurl {\doquadrupleempty\douseurl } % so that they can be used in expanded arguments
+\unexpanded\def\useurl {\doquadrupleempty\strc_references_use_url } % so that they can be used in expanded arguments
+\unexpanded\def\usefile{\dotripleargument\strc_references_use_file} % so that they can be used in expanded arguments
\let\useURL \useurl
\let\useexternaldocument\usefile
-\def\douseurl[#1][#2][#3][#4]%
- {\ctxlua{structures.references.urls.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es,\!!bs\detokenize{#4}\!!es)}}
+\def\strc_references_use_url[#label][#url][#file][#description]%
+ {\ctxcommand{useurl("#label",\!!bs\detokenize{#url}\!!es,\!!bs\detokenize{#file}\!!es,\!!bs\detokenize{#description}\!!es)}}
-\def\dousefile[#1][#2][#3]%
- {\ctxlua{structures.references.files.define("#1",\!!bs\detokenize{#2}\!!es,\!!bs\detokenize{#3}\!!es)}}
+\def\strc_references_use_file[#label][#file][#description]%
+ {\ctxcommand{usefile("#label",\!!bs\detokenize{#file}\!!es,\!!bs\detokenize{#description}\!!es)}}
-\def\doifurldefinedelse #1{\ctxcommand{doifurldefinedelse ("#1")}}
-\def\doiffiledefinedelse#1{\ctxcommand{doiffiledefinedelse("#1")}}
+\def\doifurldefinedelse #label{\ctxcommand{doifurldefinedelse ("#label")}}
+\def\doiffiledefinedelse#label{\ctxcommand{doiffiledefinedelse("#label")}}
%D \macros
%D {url,setupurl}
@@ -1400,16 +1382,14 @@
\unexpanded\def\setupurl
{\dodoubleargument\getparameters[\??ur]}
-\unexpanded\def\url[#1]%
+\unexpanded\def\url[#label]% move \hyphenatedurl to lua end (is already lua)
{\dontleavehmode
\begingroup
- \dosetfontattribute\??ur\c!style
- \dosetcolorattribute\??ur\c!color
- \hyphenatedurl{\ctxlua{structures.references.urls.get("#1","\@@uralternative","\@@urspace")}}%
+ \dousestyleparameter\@@urstyle
+ \dousecolorparameter\@@urcolor
+ \hyphenatedurl{\ctxcommand{geturl("#label")}}%
\endgroup}
-% # fails
-
%D This macro is hooked into a support macro, and thereby
%D \URL's break ok, according to the setting of a switch,
%D
@@ -1424,46 +1404,29 @@
%D Such an \URL\ is, depending on the settings, hyphenated as:
%D
%D \getbuffer
-%D
-%D \startlinecorrection
-%D \hbox to \hsize
-%D {\hss\en
-%D \setupreferencing[urlalternative=both]%
-%D \vbox{\hsize.25cm\hbox{\bf both}\prewordbreak\url[test]}%
-%D \hss
-%D \setupreferencing[urlalternative=before]%
-%D \vbox{\hsize.25cm\hbox{\bf before}\prewordbreak\url[test]}%
-%D \hss
-%D \setupreferencing[urlalternative=after]%
-%D \vbox{\hsize.25cm\hbox{\bf after}\prewordbreak\url[test]}%
-%D \hss}
-%D \stoplinecorrection
-%D
-%D By setting \type{urlspace=yes} one can get slightly better
-%D spacing when using very long \URL's.
-%D
+
%D When defining the external source of information, one can
%D also specify a suitable name (the last argument). This name
%D can be called upon with:
%D
%D \showsetup{from}
-
+%D
%D We keep this for compatibility reasons, hence the hackery.
-\unexpanded\def\dospecialfrom
- {\dosingleempty\dodospecialfrom}
+\unexpanded\def\strc_references_from
+ {\dosingleempty\strc_references_do_special_from}
-\def\dodospecialfrom[#1]%
+\def\strc_references_do_special_from[#label]%
{\dontleavehmode
- \goto{\ctxlua{structures.references.from("#1")}}[fileorurl(#1)]}
+ \goto{\ctxlua{structures.references.from("#label")}}[fileorurl(#label)]}
-\def\dofromurldescription#1%
- {#1}
+\def\dofromurldescription#content% called at the lua end
+ {#content}
-\def\dofromurlliteral#1%
- {\dosetfontattribute \??ur\c!style
- \dosetcolorattribute\??ur\c!color
- \hyphenatedurl{#1}}
+\def\dofromurlliteral#content% called at the lua end
+ {\dousestyleparameter\@@urstyle
+ \dousecolorparameter\@@urcolor
+ \hyphenatedurl{#content}}
\let\dofromfiledescription\dofromurldescription
\let\dofromfileliteral \dofromurlliteral % maybe some day setupfile that inherits from url
@@ -1497,17 +1460,17 @@
{\dodoubleargument\getparameters[\??pr]}
\unexpanded\def\defineprogram
- {\dotripleargument\dodefineprogram}
+ {\dotripleargument\strc_references_define_program}
-\def\dodefineprogram[#1][#2][#3]%
- {\ctxlua{structures.references.programs.define("#1","#2","#3")}}
+\def\strc_references_define_program[#name][#program][#description]%
+ {\ctxlua{structures.references.programs.define("#name","#program","#description")}}
-\def\program[#1]% incompatible, more consistent, hardy used anyway
+\def\program[#name]% incompatible, more consistent, hardy used anyway
{\dontleavehmode
\begingroup
- \dosetfontattribute\??pr\c!style
- \dosetcolorattribute\??pr\c!color
- \ctxlua{structures.references.programs.get("#1","\@@pralternative","\@@prspace")}%
+ \dousestyleparameter\@@prstyle
+ \dousecolorparameter\@@prcolor
+ \ctxlua{structures.references.programs.get("#name","\@@pralternative","\@@prspace")}%
\endgroup}
%D As we can see, we directly use the special reference
@@ -1544,13 +1507,13 @@
%D \showsetup{gotopage}
\unexpanded\def\definepage
- {\dodoubleargument\dodefinepage}
+ {\dodoubleargument\strc_references_define_page}
-\def\dodefinepage[#1][#2]%
- {\definereference[#1][page(#1)]}
+\def\strc_references_define_page[#name][#target]%
+ {\definereference[#name][page(#target)]}
-\def\gotopage#1[#2]%
- {\goto{#1}[\v!page(#2)]}
+\def\gotopage#text[#target]%
+ {\goto{#text}[\v!page(#target)]}
%D The previous definitions are somewhat obsolete so we don't
%D use it here.
@@ -1594,9 +1557,9 @@
%D to, that is, when one clicks on the title.
\def\coupledocument
- {\doquadrupleempty\docoupledocument}
+ {\doquadrupleempty\strc_references_couple_document}
-\def\docoupledocument[#1][#2][#3][#4]% [name] [file] [sections] [description]
+\def\strc_references_couple_document[#name][#file][#sections][#description]%
{\ifthirdargument
% this will be done differently (when it's needed)
\fi}
@@ -1613,9 +1576,9 @@
%D
%D Only when \type {text} is not empty, a space is inserted.
-\def\dotextprefix#1%
+\def\dotextprefix#text%
{\begingroup
- \setbox\scratchbox\hbox{#1}% to be solved some day
+ \setbox\scratchbox\hbox{#text}% to be solved some day
\ifdim\wd\scratchbox>\zeropoint
\unhbox\scratchbox
\doifsomething\@@rfseparator{\removeunwantedspaces\@@rfseparator}% remove is new
@@ -1646,15 +1609,11 @@
\c!export=\v!no]
\setupurl
- [\c!alternative=\v!both,
- \c!space=\v!no,
- \c!style=\v!type,
+ [\c!style=\v!type,
\c!color=]
\setupprograms
[\c!directory=,
- \c!alternative=\v!both,
- \c!space=\v!no,
\c!style=\v!type,
\c!color=]
@@ -1748,52 +1707,57 @@
% \stop \blank
% \stoptext
-\unexpanded\def\setupreferencestructureprefix
- {\dotripleargument\dosetupreferencestructureprefix}
+% todo: parameterhandler
-\def\getreferencestructureprefix#1#2#3%
+\def\getreferencestructureprefix#kind#name#category%
{{
- prefix = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefix",
- separatorset = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixseparatorset",
- conversion = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconversion",
- conversionset = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconversionset",
- set = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixset",
- segments = "\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixsegments",
- connector = \!!bs\referencestructureprefixparameter{#1}{#2}{#3}\c!prefixconnector\!!es,
+ prefix = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefix",
+ separatorset = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixseparatorset",
+ conversion = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversion",
+ conversionset = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconversionset",
+ set = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixset",
+ segments = "\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixsegments",
+ connector = \!!bs\referencestructureprefixparameter{#kind}{#name}{#category}\c!prefixconnector\!!es,
}}
\unexpanded\def\setupreferencestructureprefix
- {\dotripleempty\dosetupreferencestructureprefix}
+ {\dotripleempty\strc_references_setup_reference_structure_prefix}
-\def\dosetupreferencestructureprefix[#1][#2][#3]%
+\def\strc_references_setup_reference_structure_prefix[#kind][#category][#settings]%
{\ifthirdargument
- \getparameters[\??rf:\c!prefix:#1:#2][#3]%
+ \getparameters[\??rf:\c!prefix:#kind:#category][#settings]%
\else\ifsecondargument
- \getparameters[\??rf:\c!prefix::#1][#2]%
+ \getparameters[\??rf:\c!prefix::#kind][#category]%
\fi\fi}
-\def\referencestructureprefixparameter#1#2#3#4% kind name category parameter
- {\ifcsname\??rf:\c!prefix:#2:#3#4\endcsname
- \csname\??rf:\c!prefix:#2:#3#4\endcsname
- \else\ifcsname\??rf:\c!prefix:#1:#3#4\endcsname
- \csname\??rf:\c!prefix:#1:#3#4\endcsname
- \else\ifcsname\??rf:\c!prefix::#3#4\endcsname
- \csname\??rf:\c!prefix::#3#4\endcsname
+\def\referencestructureprefixparameter#kind#name#category#parameter%
+ {\ifcsname\??rf:\c!prefix:#name:#category#parameter\endcsname
+ \csname\??rf:\c!prefix:#name:#category#parameter\endcsname
+ \else\ifcsname\??rf:\c!prefix:#kind:#category#parameter\endcsname
+ \csname \??rf:\c!prefix:#kind:#category#parameter\endcsname
+ \else\ifcsname\??rf:\c!prefix::#category#parameter\endcsname
+ \csname \??rf:\c!prefix::#category#parameter\endcsname
\fi\fi\fi}
-% \def\getreferencestructureprefixspec#1% we can save one call by moving this to the lua end
-% {\getreferencestructureprefix
-% {\ctxlua{structures.references.getcurrentmetadata("kind")}}
-% {\ctxlua{structures.references.getcurrentmetadata("name")}}
-% {#1}}
-% \def\currentreferencedefault
-% {\ctxlua{structures.references.filter("default",\getreferencestructureprefixspec\v!default)}}
-%
-% this is shortcut for:
-
\def\currentreferencedefault
{\ctxlua{structures.references.filter("default",\ctxlua{structures.references.getcurrentprefixspec("\v!default")})}}
+%D Not all support is visible by looking at the \TEX\ code; here is one of those:^
+%D
+%D \starttyping
+%D \startinteractionmenu[right]
+%D \startbut [section(first {chapter})] first chapter \stopbut
+%D \startbut [section(previous{chapter})] previous chapter \stopbut
+%D \startbut [section(next {chapter})] next chapter \stopbut
+%D \startbut [section(last {chapter})] last chapter \stopbut
+%D \blank[2*big]
+%D \startbut [section(first {section})] first section \stopbut
+%D \startbut [section(previous{section})] previous section \stopbut
+%D \startbut [section(next {section})] next section \stopbut
+%D \startbut [section(last {section})] last section \stopbut
+%D \stopinteractionmenu
+%D \stoptyping
+
\protect \endinput
% tricky:
diff --git a/Master/texmf-dist/tex/context/base/strc-reg.lua b/Master/texmf-dist/tex/context/base/strc-reg.lua
index c19ae12d65c..6da58345bf5 100644
--- a/Master/texmf-dist/tex/context/base/strc-reg.lua
+++ b/Master/texmf-dist/tex/context/base/strc-reg.lua
@@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['strc-reg'] = {
}
local next, type = next, type
-local texwrite, texcount = tex.write, tex.count
+local texcount = tex.count
local format, gmatch = string.format, string.gmatch
local equal, concat, remove = table.are_equal, table.concat, table.remove
local utfchar = utf.char
@@ -24,14 +24,14 @@ local helpers = structures.helpers
local sections = structures.sections
local documents = structures.documents
local pages = structures.pages
-local processors = structures.processors
local references = structures.references
local mappings = sorters.mappings
local entries = sorters.entries
local replacements = sorters.replacements
-local processor_split = processors.split
+local processors = typesetters.processors
+local splitprocessor = processors.split
local variables = interfaces.variables
local context = context
@@ -227,7 +227,7 @@ end
registers.define = allocate
-local entrysplitter = lpeg.Ct(lpeg.splitat('+')) -- & obsolete in mkiv
+local entrysplitter = lpeg.tsplitat('+') -- & obsolete in mkiv
local tagged = { }
@@ -240,13 +240,13 @@ local function preprocessentries(rawdata)
if type(e) == "table" then
et = e
else
- entryproc, e = processor_split(e)
+ entryproc, e = splitprocessor(e)
et = lpegmatch(entrysplitter,e)
end
if type(k) == "table" then
kt = k
else
- pageproc, k = processor_split(k)
+ pageproc, k = splitprocessor(k)
kt = lpegmatch(entrysplitter,k)
end
entries = { }
@@ -276,7 +276,7 @@ function registers.store(rawdata) -- metadata, references, entries
data[#data+1] = rawdata
local label = references.label
if label and label ~= "" then tagged[label] = #data end
- texwrite(#data)
+ context(#data)
end
function registers.enhance(name,n)
@@ -847,7 +847,7 @@ function registers.flush(data,options,prefixspec,pagespec)
end
function registers.analyze(class,options)
- texwrite(registers.analyzed(class,options))
+ context(registers.analyzed(class,options))
end
function registers.process(class,...)
diff --git a/Master/texmf-dist/tex/context/base/strc-reg.mkii b/Master/texmf-dist/tex/context/base/strc-reg.mkii
index b088246d327..45be825258f 100644
--- a/Master/texmf-dist/tex/context/base/strc-reg.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-reg.mkii
@@ -5,7 +5,7 @@
%D subtitle=Register Management,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-reg.mkiv b/Master/texmf-dist/tex/context/base/strc-reg.mkiv
index 19634390dba..e36556949b2 100644
--- a/Master/texmf-dist/tex/context/base/strc-reg.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-reg.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Registers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -46,7 +46,9 @@
% \index[pageclass::] {textclass::entry}
% \index[pageclass::key]{textclass::entry}
-%D Parameters:
+%D Parameters ... we set up levels so we need a slightly different command handler here .. okay, we
+%D can use the childs for that ... but then we need to tweak the name in order to distinguis:
+%D register -> register:1 (i.e. prefix)
\let\currentregister\empty
@@ -63,11 +65,11 @@
\def\doregisterparentparameter #1#2{\ifx#1\relax\s!empty\else\doregisterparameter #1{#2}\fi}
\def\doregisterparentparameterhash#1#2{\ifx#1\relax \else\doregisterparameterhash#1{#2}\fi}
-\def\dosetregisterattributes#1#2% style color
- {\edef\fontattributehash {\registerparameterhash#1}%
- \edef\colorattributehash{\registerparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
+\def\useregisterstyleandcolor#1#2% style color
+ {\edef\currentstyleparameter{\registerparameter#1}%
+ \edef\currentcolorparameter{\registerparameter#2}%
+ \ifx\currentstyleparameter\empty\else\dousestyleparameter\currentstyleparameter\fi
+ \ifx\currentcolorparameter\empty\else\dousecolorparameter\currentcolorparameter\fi}
%D Setup:
@@ -270,7 +272,7 @@
\currentregistersynchronize % here?
% needs thinking ... bla\index{bla}. will break before the . but adding a
% penalty is also no solution
- \attribute\destinationattribute\lastdestinationattribute \forcecolorhack % no \strut as it will be removed during cleanup
+ \attribute\destinationattribute\lastdestinationattribute \signalcharacter % no \strut as it will be removed during cleanup
\endgroup}
\def\doregister[#1][#2]%
@@ -538,10 +540,10 @@
{\iffirstargument
\begingroup
\edef\currentregister{#1}%
- % the expansion is needed because we don't want \v!'s in the tuo file (french)
- \normalexpanded{\systemsuppliedchapter[\currentregister]{\noexpand\headtext{\currentregister}}}%
+ \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\currentregister}},reference=\currentregister]}%
\placeregister[\currentregister][#2]%
\page[\v!yes]%
+ \stopnamedsection
\endgroup
\fi}
@@ -597,7 +599,7 @@
{\registerparameter\c!before
% bugged, why does leftskip gets set: \vskip\lineheight\goodbreak\vskip-\lineheight
\begingroup
- \dosetregisterattributes\c!style\c!color
+ \useregisterstyleandcolor\c!style\c!color
\dontleavehmode
\strut
\iflocation
@@ -614,7 +616,7 @@
\setvalue{\??id:\c!indicator:b}#1% will be shared with a
{\registerparameter\c!before
\begingroup
- \dosetregisterattributes\c!style\c!color
+ \useregisterstyleandcolor\c!style\c!color
\dontleavehmode
\strut
\iflocation
@@ -639,6 +641,7 @@
{\endgraf
\begingroup
\dostarttagged\t!register\currentregister
+ \forgeteverypar
\forgetparindent
\forgetparskip}
@@ -651,7 +654,7 @@
{\endgraf
\begingroup
\dostarttagged\t!registerentries\empty
- \dosetregisterattributes\c!textstyle\c!textcolor
+ \useregisterstyleandcolor\c!textstyle\c!textcolor
\advance\leftskip\numexpr#1-1\relax\dimexpr\registerparameter\c!distance\relax
\hangindent\registerparameter\c!distance\hangafter\plusone}
@@ -676,7 +679,7 @@
{\begingroup
\dostarttagged\t!registerpages\empty
\setfalse\registerpagedone
- \dosetregisterattributes\c!pagestyle\c!pagecolor}
+ \useregisterstyleandcolor\c!pagestyle\c!pagecolor}
\unexpanded\def\stopregisterpages
{\dostoptagged
@@ -687,7 +690,7 @@
\begingroup
\setfalse\registerpagedone
\dostarttagged\t!registerpage\empty
- \dosetregisterattributes\c!pagestyle\c!pagecolor}
+ \useregisterstyleandcolor\c!pagestyle\c!pagecolor}
\unexpanded\def\stopregisterseewords
{\dostoptagged
@@ -706,9 +709,9 @@
\def\withregisterpagecommand#1#2#3#4%
{\def\currentregisterpageindex{#2}%
\iflocation
- \goto{\registerparameter\c!pagecommand{#4}}[internal(#2)]%
+ \goto{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
\else
- \registerparameter\c!pagecommand{#4}%
+ \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
\fi}
\def\registeronepage#1#2#3#4% #1:processor content
@@ -743,7 +746,7 @@
\iflocation
\def\currentregisterseeindex{#3}%
\doifelse{\registerparameter\c!interaction}\v!text
- {\directgoto{\setlocationcolor\??ia\doapplyregisterentrycommand{#1}{#4}}[internal(#2)]}
+ {\directgoto{\setlocationcolor\doapplyregisterentrycommand{#1}{#4}}[internal(#2)]}
{\doapplyregisterentrycommand{#1}{#4}}%
\else
\let\currentregisterseeindex\empty
diff --git a/Master/texmf-dist/tex/context/base/strc-ren.mkiv b/Master/texmf-dist/tex/context/base/strc-ren.mkiv
index 73eb0ccd206..543c55fff67 100644
--- a/Master/texmf-dist/tex/context/base/strc-ren.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-ren.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Section Rendering,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -25,47 +25,43 @@
\newevery \everyheadstart \relax
-\unexpanded\def\placeheadmargintexts
- {\the\everyheadstart
- \doif{\structureheadparameter\c!margintext}\v!yes\placemargincontent}
-
\unexpanded\def\setupheadcomponentfont#1#2%
{\dontconvertfont
- \ifconditional\structureheadisdisplay
- \edef\askedstructureheadinterlinespace{\structureheadparameter\c!interlinespace}%
- \ifx\askedstructureheadinterlinespace\empty
+ \ifconditional\headisdisplay
+ \edef\askedheadinterlinespace{\headparameter\c!interlinespace}%
+ \ifx\askedheadinterlinespace\empty
% here the interline space is only set when style sets no space
- \setfalse\fontattributeisset
+ \setfalse\fontattributeisset % use the currentfontparameter state instead
\setfalse\interlinespaceisset
- \dosetstructureheadattributes\c!style\c!color
+ \useheadstyleandcolor\c!style\c!color
\ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else
\setupinterlinespace
\fi \fi
- \setfalse\fontattributeisset \dosetstructureheadattributes#1#2%
+ \setfalse\fontattributeisset \useheadstyleandcolor#1#2%
\ifconditional\fontattributeisset \ifconditional\interlinespaceisset \else
\setupinterlinespace
\fi \fi
\else
% here the set interline space overloads any other set space in the style
\setfalse\fontattributeisset
- \dosetstructureheadattributes\c!style\c!color
+ \useheadstyleandcolor\c!style\c!color
\ifconditional\fontattributeisset
- \dosetupcheckedinterlinespace\askedstructureheadinterlinespace
+ \dosetupcheckedinterlinespace\askedheadinterlinespace
\fi
\setfalse\fontattributeisset
- \dosetstructureheadattributes#1#2%
+ \useheadstyleandcolor#1#2%
\ifconditional\fontattributeisset
- \dosetupcheckedinterlinespace\askedstructureheadinterlinespace
+ \dosetupcheckedinterlinespace\askedheadinterlinespace
\fi
\fi
\else
\setfalse\fontattributeisset
- \dosetstructureheadattributes\c!style\c!color
+ \useheadstyleandcolor\c!style\c!color
\ifconditional\fontattributeisset
\setupspacing
\fi
\setfalse\fontattributeisset
- \dosetstructureheadattributes#1#2%
+ \useheadstyleandcolor#1#2%
\ifconditional\fontattributeisset
\setupspacing
\fi
@@ -74,23 +70,22 @@
\def\doplaceheadtextcomponent#1%
{\begingroup
\setupheadcomponentfont\c!textstyle\c!textcolor
- \structureheadparameter\c!commandbefore
- \placeheadmargintexts
- \ifcsname\??nh\currentstructurehead\c!deeptextcommand\endcsname
- \expandafter\let\expandafter\deepstructuretitlecommand\csname\??nh\currentstructurehead\c!deeptextcommand\endcsname
+ \headparameter\c!commandbefore
+ \ifcsname\currentheadhash\c!deeptextcommand\endcsname
+ \expandafter\let\expandafter\deepstructuretitlecommand\csname\currentheadhash\c!deeptextcommand\endcsname
\fi
- \ifconditional\structureheadisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay % \ifdisplaysectionhead
% struts can be nilled with \setnostrut
- \structureheadparameter\c!textcommand{\setstrut\begstrut#1\endstrut}%
+ \headparameter\c!textcommand{\setstrut\begstrut#1\endstrut}%
\xdef\localheadheight {\the\strutht}%
\xdef\localheaddepth {\the\strutdp}%
\xdef\localheadlineheight{\the\lineheight}%
% == \globallet\localheaddepth\strutdepth
\else
- \structureheadparameter\c!textcommand{#1}%
+ \headparameter\c!textcommand{#1}%
\fi
- \structureheadparameter\c!commandafter
- \ifconditional\structureheadisdisplay % \ifdisplaysectionhead
+ \headparameter\c!commandafter
+ \ifconditional\headisdisplay % \ifdisplaysectionhead
\endgraf
\fi
\endgroup}
@@ -98,15 +93,14 @@
\def\doplaceheadnumbercomponent#1%
{\begingroup
\setupheadcomponentfont\c!numberstyle\c!numbercolor
- \placeheadmargintexts
- \ifcsname\??nh\currentstructurehead\c!deepnumbercommand\endcsname
- \expandafter\let\expandafter\deepstructurenumbercommand\csname\??nh\currentstructurehead\c!deeptextcommand\endcsname
+ \ifcsname\currentheadhash\c!deepnumbercommand\endcsname
+ \expandafter\let\expandafter\deepstructurenumbercommand\csname\currentheadhash\c!deepnumbercommand\endcsname
\fi
- \ifconditional\structureheadisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay % \ifdisplaysectionhead
% can be nilled with \setnostrut
- \structureheadparameter\c!numbercommand{\setstrut\begstrut#1\endstrut}%
+ \headparameter\c!numbercommand{\setstrut\begstrut#1\endstrut}%
\else
- \structureheadparameter\c!numbercommand{#1}%
+ \headparameter\c!numbercommand{#1}%
\fi
\endgroup}
@@ -116,74 +110,75 @@
\let\currentstructurereferenceattribute\attributeunsetvalue
-\def\structureheadreferenceattributes
+\def\headreferenceattributes
{\iflocation
+ % \ctxlua{structures.lists.taglocation(\nextinternalreference)}% maybe ... tags entry as used
attr \destinationattribute \currentstructureattribute
attr \referenceattribute \currentstructurereferenceattribute
% attr \internalattribute \nextinternalreference
\fi}
-\def\setinlinestructureheadreferenceattributes
- {\ifconditional\structureheadisdisplay \else \iflocation
+\def\setinlineheadreferenceattributes
+ {\ifconditional\headisdisplay \else \iflocation
\attribute\destinationattribute\currentstructureattribute
\attribute\referenceattribute \currentstructurereferenceattribute
% \attribute\internalattribute \nextinternalreference
\fi \fi}
-\def\docheckstructureheadreference
- {\edef\currentstructureheadinteraction{\structureheadparameter\c!interaction}%
- \ifx\currentstructureheadinteraction\v!list
+\def\docheckheadreference
+ {\edef\currentheadinteraction{\headparameter\c!interaction}%
+ \ifx\currentheadinteraction\v!list
% setuphead[<section>][interaction=list,...]
- \dogetsimplepagereference{bck:\nextinternalreference}%
+ \strc_references_get_simple_page_reference{bck:\nextinternalreference}%
\let\currentstructurereferenceattribute\currentreferenceattribute
- \else\ifx\currentstructureheadinteraction\v!reference
+ \else\ifx\currentheadinteraction\v!reference
% setuphead[<section>][interaction=reference,...] start<section>[backreference=abc,...]
- \edef\currentstructureheadbackreference{\structurevariable{references.backreference}}%
- \ifx\currentstructureheadbackreference\empty \else
- \dogetsimplepagereference\currentstructureheadbackreference
+ \edef\currentheadbackreference{\structurevariable\c!backreference}% weird, was references.backreference
+ \ifx\currentheadbackreference\empty \else
+ \strc_references_get_simple_page_reference\currentheadbackreference
\let\currentstructurereferenceattribute\currentreferenceattribute
\fi
\else
% maybe auto: backreference when given, else list
\fi\fi}
-\unexpanded\def\placestructureheadtext
+\unexpanded\def\placecurrentheadtext
{\beginheadplacement
- \setstructureheadmarking
+ \setheadmarking
\doresettructureheadnumbercontent
- \ifconditional\structureheadleaveempty
- \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \structureheadreferenceattributes to \zeropoint{}%
+ \ifconditional\headleaveempty
+ \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \headreferenceattributes to \zeropoint{}%
\makestrutofbox\sectionheadbox
\else
- \docheckstructureheadreference
- \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \structureheadreferenceattributes
- {\dosetlocalgridsnapping{\structureheadparameter\c!internalgrid}%
+ \docheckheadreference
+ \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \headreferenceattributes
+ {\spac_grids_set_local_snapping{\headparameter\c!internalgrid}%
\doresettructureheadnumbercontent
- \dosetfontattribute{\??nh\currentstructurehead}\c!style % but we don't want color to influence user command, todo: get the if-else out of it
- \setinlinestructureheadreferenceattributes
- \structureheadparameter\c!command{}{\doplaceheadtextcomponent\getstructureheadtitle}}%
+ \useheadstyleparameter\c!style
+ \setinlineheadreferenceattributes
+ \headparameter\c!command{}{\doplaceheadtextcomponent\getheadtitle}}%
\fi
- \endheadplacement{\getstructureheadsyncs}}
+ \endheadplacement{\getheadsyncs}}
-\unexpanded\def\placestructureheadnumbertext
+\unexpanded\def\placecurrentheadnumbertext
{\beginheadplacement
- \setstructureheadmarking
- \doiftextelse{\getstructureheadnumber}\dosettructureheadnumbercontent\doresettructureheadnumbercontent
- \ifconditional\structureheadleaveempty
- \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \structureheadreferenceattributes to \zeropoint{}%
+ \setheadmarking
+ \doiftextelse{\getheadnumber}\dosettructureheadnumbercontent\doresettructureheadnumbercontent
+ \ifconditional\headleaveempty
+ \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \headreferenceattributes to \zeropoint{}%
\makestrutofbox\sectionheadbox
\else % = needed
- \docheckstructureheadreference
- \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \structureheadreferenceattributes
- {\dosetlocalgridsnapping{\structureheadparameter\c!internalgrid}%
- \dosetfontattribute{\??nh\currentstructurehead}\c!style
- \setinlinestructureheadreferenceattributes
- \structureheadparameter\c!command{\doplaceheadnumbercomponent\getstructureheadnumber}{\doplaceheadtextcomponent\getstructureheadtitle}}%
+ \docheckheadreference
+ \setbox\sectionheadbox\ifvertical\vbox\else\hbox\fi \headreferenceattributes
+ {\spac_grids_set_local_snapping{\headparameter\c!internalgrid}%
+ \useheadstyleparameter\c!style
+ \setinlineheadreferenceattributes
+ \headparameter\c!command{\doplaceheadnumbercomponent\getheadnumber}{\doplaceheadtextcomponent\getheadtitle}}%
\fi
- \endheadplacement{\getstructureheadsyncs}}
+ \endheadplacement{\getheadsyncs}}
-\unexpanded\def\placestructureheadempty
- {\hbox \structureheadreferenceattributes {\getstructureheadsyncs}}
+\unexpanded\def\placecurrentheadempty
+ {\hbox \headreferenceattributes {\getheadsyncs}}
%D \starttyping
%D \def\StretchedBox#1%
@@ -205,14 +200,14 @@
\def\dolocalheadsetup % koppeling met standaard kopcommando / engels
{\forgetall % traag dus ...
- \doifsomething{\structureheadparameter\c!align } {\normalexpanded{\noexpand\setupalign [\structureheadparameter\c!align ]}}%
- \doifsomething{\structureheadparameter\c!tolerance} {\normalexpanded{\noexpand\setuptolerance[\structureheadparameter\c!tolerance]}}%
- \doif {\structureheadparameter\c!strut }\v!no{\setnostrut}% new
+ \doifsomething{\headparameter\c!align } {\normalexpanded{\noexpand\setupalign [\headparameter\c!align ]}}%
+ \doifsomething{\headparameter\c!tolerance} {\normalexpanded{\noexpand\setuptolerance[\headparameter\c!tolerance]}}%
+ \doif {\headparameter\c!strut }\v!no{\setnostrut}% new
\def\\{\crlf\strut\ignorespaces}}
\def\beginheadplacement
{\bgroup
- \setsystemmode\currentstructurehead
+ \setsystemmode\currenthead
\xdef\localheadheight {\the\strutht}%
\xdef\localheaddepth {\the\strutdp}%
\xdef\localheadlineheight{\the\lineheight}%
@@ -220,7 +215,7 @@
\everypar\emptytoks % needed indeed
\noindent % ipv \whitespace elders, na \forgetall !
\bgroup
- \doifinsetelse{\structureheadparameter\c!aligntitle}{\v!yes,\v!float}% new
+ \doifinsetelse{\headparameter\c!aligntitle}{\v!yes,\v!float}% new
{\skip0 1\leftskip
\skip2 1\rightskip
\xdef\localheadskip{\the\skip0}%
@@ -231,10 +226,11 @@
\forgetbothskips}
{\globallet\localheadskip\!!zeropoint
\forgetall}%
+ \setfalse\inhibitmargindata % brrrr is set in forgetall
\dontcomplain
\postponenotes
\iflocation
- \ifconditional\structureheadisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay % \ifdisplaysectionhead
\else
% obsolete: \noninterferingmarks
\fi
@@ -282,10 +278,10 @@
\def\endheadplacement#1%
{\noflines\zerocount
- \ifconditional\structureheadisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay % \ifdisplaysectionhead
% new (todo tight == one following line up)
\processaction
- [\structureheadparameter\c!hang]
+ [\headparameter\c!hang]
[ \v!line=>\hangheadplacement\noflines\zerocount,
\v!broad=>\hangheadplacement\getnoflines\scratchdimen,
\v!fit=>\hangheadplacement\getrawnoflines\scratchdimen,
@@ -296,22 +292,22 @@
\let\headlastlinewidth\!!zeropoint
% kind of special, we want to snap heads also according to local specs local
\ifgridsnapping
- \begingroup
- \edef\currentstructureheadgridsnapping{\structureheadparameter\c!grid}%
- \ifconditional\structureheadisdisplay
- \ifx\currentstructureheadgridsnapping\empty\else
- \dosetstructureheadattributes\c!style\c!color
- \setupinterlinespace
- \dosetstructureheadattributes\c!textstyle\c!textcolor
- \setupinterlinespace
+ \hbox\bgroup % extra hbox will trigger global snapper on top of local
+ \edef\currentheadgridsnapping{\headparameter\c!grid}%
+ \ifconditional\headisdisplay
+ \ifx\currentheadgridsnapping\empty\else
+ \useheadstyleandcolor\c!style\c!color
+ \setupinterlinespace
+ \useheadstyleandcolor\c!textstyle\c!textcolor
+ \setupinterlinespace
+ \fi
\fi
- \fi
- \snaptogrid[\currentstructureheadgridsnapping]\hbox
- {\hskip\localheadskip\hskip\structureheadparameter\c!margin\box\sectionheadbox}%
- \endgroup
+ \snaptogrid[\currentheadgridsnapping]\hbox
+ {\hskip\localheadskip\hskip\headparameter\c!margin\box\sectionheadbox}%
+ \egroup
\else
\hbox
- {\hskip\localheadskip\hskip\structureheadparameter\c!margin\box\sectionheadbox}%
+ {\hskip\localheadskip\hskip\headparameter\c!margin\box\sectionheadbox}%
\fi
\flushnotes % new, not really needed
\endgraf
@@ -330,9 +326,9 @@
\globallet\headlastlinewidth\!!zeropoint
#1%
\hskip\numberheaddistance\!!plus\numberheaddistance\!!minus.25\dimexpr\numberheaddistance\relax
- \hskip\continuousstructureheadsignal\ignorespaces
+ \hskip\continuousheadsignal\ignorespaces
\fi
- \ifconditional\structureheadisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay % \ifdisplaysectionhead
\ifvmode
\ifgridsnapping % important, font related depth, see comment
\prevdepth\strutdp
@@ -343,8 +339,8 @@
\fi
\egroup
\egroup
- \ifconditional\structureheadisdisplay % \ifdisplaysectionhead
- \checknextindentation[\structureheadparameter\c!indentnext]%
+ \ifconditional\headisdisplay % \ifdisplaysectionhead
+ \useindentnextparameter\headparameter
\else
\nonoindentation % recently added, was a bug
\fi}
@@ -363,26 +359,53 @@
% \input tufte \par
% \stopnarrower
+\installcorenamespace{headplacementalternative}
+\installcorenamespace{headplacementnature}
+
\let\numberheadalternative\v!normal
\unexpanded\def\defineheadplacement
{\dodoubleargument\dodefineheadplacement}
-\def\dodefineheadplacement[#1][#2]% #3#4
- {\setvalue{\??ns:#1}{#2}%
- \setvalue{\??ns::#1}}
+% \def\dodefineheadplacement[#1][#2]% #3#4
+% {\setvalue{\??headplacementnature#1}{#2}%
+% \setvalue{\??headplacementalternative#1}}
+
+% \dodefineheadplacement[sectiona][vertical]{#1->#2}
+% \dodefineheadplacement[sectionb][vertical]#1#2{#1->#2}
+%
+% \setuphead[section][alternative=sectiona]
+% \setuphead[subsection][alternative=sectionb]
+
+\def\dodefineheadplacementyes[#1][#2]%#3#4%
+ {\setvalue{\??headplacementnature#1}{#2}%
+ \setvalue{\??headplacementalternative#1}##1##2}
+
+\def\dodefineheadplacementnop[#1][#2]%
+ {\setvalue{\??headplacementnature#1}{#2}%
+ \setvalue{\??headplacementalternative#1}}
+
+\def\dodefineheadplacement[#1][#2]%
+ {\doifnextbgroupelse
+ {\dodefineheadplacementyes[#1][#2]}%
+ {\dodefineheadplacementnop[#1][#2]}}
\def\presetnumberheadalternative
- {\doifelsevalue{\??ns:\numberheadalternative}\v!horizontal\setfalse\settrue\structureheadisdisplay}
+ {\doifelsevalue{\??headplacementnature\numberheadalternative}\v!horizontal\setfalse\settrue\headisdisplay}
\def\normalplacehead
- {\csname\??ns::\ifcsname\??ns::\numberheadalternative\endcsname\numberheadalternative\else\v!normal\fi\endcsname}
+ {\csname\??headplacementalternative\ifcsname\??headplacementalternative\numberheadalternative\endcsname\numberheadalternative\else\v!normal\fi\endcsname}
+
+\def\setheaddisplay % used in strc-sec
+ {\doifelsevalue{\??headplacementnature\headparameter\c!alternative}\v!horizontal
+ {\setfalse\headisdisplay}
+ {\settrue \headisdisplay}}
\defineheadplacement[\v!paragraph][\v!vertical]#1#2%
{\vbox
{\localheadsetup
\begstrut
- \ifconditional\structureheadshownumber % \ifheadnumbercontent
+ \ifconditional\headshownumber % \ifheadnumbercontent
#1\hskip\numberheaddistance
\fi
#2}}
@@ -397,10 +420,10 @@
\defineheadplacement[\v!normal][\v!vertical]#1#2%
{\vbox
{\localheadsetup
- \edef\headwidth {\structureheadparameter\c!width }%
- \edef\headnumberwidth{\structureheadparameter\c!numberwidth}%
- \edef\headtextwidth {\structureheadparameter\c!textwidth }%
- \ifconditional\structureheadshownumber
+ \edef\headwidth {\headparameter\c!width }%
+ \edef\headnumberwidth{\headparameter\c!numberwidth}%
+ \edef\headtextwidth {\headparameter\c!textwidth }%
+ \ifconditional\headshownumber
\ifx\headwidth\empty
\else
\ifx\headnumberwidth\empty
@@ -439,20 +462,20 @@
\fi
#2}}
-\unexpanded\def\placeheadmargin#1#2%
+\unexpanded\def\placeheadmarginalternative#1#2%
{\vbox
{\localheadsetup
\begstrut % use one \strut here!
\dontleavehmode % in case there is no strut, else side effects with llap
- \ifconditional\structureheadshownumber
+ \ifconditional\headshownumber
\llap{\hbox{\hfill{#1}\hskip\localheadskip\hskip\leftmargindistance}}% introduces whitespace
% maybe better:
% \inleftmargin{\hbox{\hss{#1}\hskip\localheadskip}}%
\fi
{#2}}}
-\defineheadplacement[\v!inmargin][\v!vertical]#1#2{\placeheadmargin{#1}{#2}}
-\defineheadplacement[\v!margin] [\v!vertical]#1#2{\placeheadmargin{#1}{#2}}
+\defineheadplacement[\v!inmargin][\v!vertical]#1#2{\placeheadmarginalternative{#1}{#2}}
+\defineheadplacement[\v!margin] [\v!vertical]#1#2{\placeheadmarginalternative{#1}{#2}}
\defineheadplacement[\v!middle][\v!vertical]#1#2%
{\vbox
@@ -460,7 +483,7 @@
\veryraggedcenter
\let\\\endgraf
\let\crlf\endgraf
- \ifconditional\structureheadshownumber
+ \ifconditional\headshownumber
\strut#1\par
\fi
\begstrut#2}}
@@ -468,14 +491,14 @@
\defineheadplacement[\v!text][\v!horizontal]#1#2%
{\bgroup
\localheadsetup % no stretch in distance
- \ifconditional\structureheadshownumber
+ \ifconditional\headshownumber
{#1}\kern\numberheaddistance
\fi
{\begstrut#2}%
\egroup}
-\unexpanded\def\placeheadlohi#1#2#3%
- {\ifconditional\structureheadshownumber
+\unexpanded\def\placeheadlohialternative#1#2#3%
+ {\ifconditional\headshownumber
\setbox0\hbox{#2}
\setbox2=#1{\localheadsetup\advance\hsize-\wd0\relax#3}%
\hbox{\box0\hskip\numberheaddistance\box2}%
@@ -486,8 +509,8 @@
% onder/boven lijnt het nummer op de onderste/bovenste regel
% uit van een meerregelige kop
-\defineheadplacement[\v!bottom][\v!vertical]#1#2{\placeheadlohi\vbox{#1}{#2}}
-\defineheadplacement[\v!top] [\v!vertical]#1#2{\placeheadlohi\vtop{#1}{#2}}
+\defineheadplacement[\v!bottom][\v!vertical]#1#2{\placeheadlohialternative\vbox{#1}{#2}}
+\defineheadplacement[\v!top] [\v!vertical]#1#2{\placeheadlohialternative\vtop{#1}{#2}}
% helpers
@@ -495,7 +518,7 @@
%
% \defineheadplacement[MyTest][horizontal]#1#2%
% {\startlocalheadsetup
-% %\ChapterInMargin{\structureheadhbox{\strut#2}}% proper destination, ref okay
+% %\ChapterInMargin{\headhbox{\strut#2}}% proper destination, ref okay
% \ChapterInMargin{\strut#2}% zero destination, ref okay
% \stoplocalheadsetup}
%
@@ -503,8 +526,8 @@
% [chapter]
% [alternative=MyTest]
-\unexpanded\def\structureheadhbox{\hbox\structureheadreferenceattributes}
-\unexpanded\def\structureheadvbox{\vbox\structureheadreferenceattributes}
+\unexpanded\def\headhbox{\hbox\headreferenceattributes}
+\unexpanded\def\headvbox{\vbox\headreferenceattributes}
\unexpanded\def\startlocalheadsetup{\bgroup\localheadsetup}
\unexpanded\def\stoplocalheadsetup {\egroup}
diff --git a/Master/texmf-dist/tex/context/base/strc-rsc.lua b/Master/texmf-dist/tex/context/base/strc-rsc.lua
new file mode 100644
index 00000000000..a90f577e30c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/strc-rsc.lua
@@ -0,0 +1,154 @@
+if not modules then modules = { } end modules ['strc-rsc'] = {
+ version = 1.001,
+ comment = "companion to strc-ref.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- The scanner is in a separate module so that we can test without too
+-- many dependencies.
+
+-- The scanner accepts nested outer, but we don't care too much, maybe
+-- some day we will have both but currently the innermost wins.
+
+local lpegmatch, lpegP, lpegS, lpegCs, lpegCt, lpegCf, lpegCc, lpegC, lpegCg = lpeg.match, lpeg.P, lpeg.S, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.C, lpeg.Cg
+local find = string.find
+
+local spaces = lpegP(" ")^0
+local lparent = lpegP("(")
+local rparent = lpegP(")")
+local lbrace = lpegP("{")
+local rbrace = lpegP("}")
+local tcolon = lpegP(":::") -- component or outer
+local dcolon = lpegP("::") -- outer
+local scolon = lpegP(":") -- prefix
+local backslash = lpegP("\\")
+
+ lparent = spaces * lparent * spaces
+ rparent = spaces * rparent * spaces
+ lbrace = spaces * lbrace * spaces
+ rbrace = spaces * rbrace * spaces
+ tcolon = spaces * tcolon * spaces
+ dcolon = spaces * dcolon * spaces
+
+local endofall = spaces * lpegP(-1)
+
+local o_token = 1 - rparent - rbrace - lparent - lbrace -- can be made more efficient
+local a_token = 1 - rbrace
+local s_token = 1 - lparent - lbrace
+local i_token = 1 - lparent - lbrace - endofall
+local f_token = 1 - lparent - lbrace - dcolon
+local c_token = 1 - lparent - lbrace - tcolon
+
+local hastexcode = lpegCg(lpegCc("has_tex") * lpegCc(true)) -- cannot be made to work
+local component = lpegCg(lpegCc("component") * lpegCs(c_token^1))
+local outer = lpegCg(lpegCc("outer") * lpegCs(f_token^1))
+local operation = lpegCg(lpegCc("operation") * lpegCs(o_token^1))
+local arguments = lpegCg(lpegCc("arguments") * lpegCs(a_token^0))
+local special = lpegCg(lpegCc("special") * lpegCs(s_token^1))
+local inner = lpegCg(lpegCc("inner") * lpegCs(i_token^1))
+
+ arguments = (lbrace * arguments * rbrace)^-1
+ component = component * tcolon
+ outer = outer * dcolon
+ operation = outer^-1 * operation -- special case: page(file::1) and file::page(1)
+ inner = inner * arguments
+ special = special * lparent * (operation * arguments)^-1 * rparent
+
+local referencesplitter = spaces * lpegCf (lpegCt("") * (component + outer)^-1 * (special + inner)^-1 * endofall, rawset)
+local prefixsplitter = lpegCs(lpegP((1-scolon)^1 * scolon)) * #-scolon * lpegCs(lpegP(1)^1)
+local componentsplitter = lpegCs(lpegP((1-scolon)^1)) * scolon * #-scolon * lpegCs(lpegP(1)^1)
+
+prefixsplitter = componentsplitter
+
+local function splitreference(str)
+ if str and str ~= "" then
+ local t = lpegmatch(referencesplitter,str)
+ if t then
+ local a = t.arguments
+ if a and find(a,"\\") then
+ t.has_tex = true
+ else
+ local o = t.arguments
+ if o and find(o,"\\") then
+ t.has_tex = true
+ end
+ end
+ return t
+ end
+ end
+end
+
+local function splitprefix(str)
+ return lpegmatch(prefixsplitter,str)
+end
+
+local function splitcomponent(str)
+ return lpegmatch(componentsplitter,str)
+end
+
+-- register in the right namespace
+
+structures = structures or { }
+structures.references = structures.references or { }
+local references = structures.references
+
+references.referencesplitter = referencesplitter
+references.splitreference = splitreference
+references.prefixsplitter = prefixsplitter
+references.splitprefix = splitprefix
+references.componentsplitter = componentsplitter
+references.splitcomponent = splitcomponent
+
+-- test code:
+
+-- inspect(splitreference([[component:::inner]]))
+-- inspect(splitprefix([[component:::inner]]))
+-- inspect(splitprefix([[component:inner]]))
+
+-- inspect(splitreference([[ ]]))
+-- inspect(splitreference([[ inner ]]))
+-- inspect(splitreference([[ special ( operation { argument, argument } ) ]]))
+-- inspect(splitreference([[ special ( operation { argument } ) ]]))
+-- inspect(splitreference([[ special ( operation { argument, \argument } ) ]]))
+-- inspect(splitreference([[ special ( operation { \argument } ) ]]))
+-- inspect(splitreference([[ special ( operation ) ]]))
+-- inspect(splitreference([[ special ( \operation ) ]]))
+-- inspect(splitreference([[ special ( o\peration ) ]]))
+-- inspect(splitreference([[ special ( ) ]]))
+-- inspect(splitreference([[ inner { argument } ]]))
+-- inspect(splitreference([[ inner { \argument } ]]))
+-- inspect(splitreference([[ inner { ar\gument } ]]))
+-- inspect(splitreference([[inner{a\rgument}]]))
+-- inspect(splitreference([[ inner { argument, argument } ]]))
+-- inspect(splitreference([[ inner { argument, \argument } ]])) -- fails: bug in lpeg?
+-- inspect(splitreference([[ inner { \argument, \argument } ]]))
+-- inspect(splitreference([[ outer :: ]]))
+-- inspect(splitreference([[ outer :: inner]]))
+-- inspect(splitreference([[ outer :: special (operation { argument,argument } ) ]]))
+-- inspect(splitreference([[ outer :: special (operation { } )]]))
+-- inspect(splitreference([[ outer :: special ( operation { argument, \argument } ) ]]))
+-- inspect(splitreference([[ outer :: special ( operation ) ]]))
+-- inspect(splitreference([[ outer :: special ( \operation ) ]]))
+-- inspect(splitreference([[ outer :: special ( ) ]]))
+-- inspect(splitreference([[ outer :: inner { argument } ]]))
+-- inspect(splitreference([[ special ( outer :: operation ) ]]))
+
+-- inspect(splitreference([[]]))
+-- inspect(splitreference([[inner]]))
+-- inspect(splitreference([[special(operation{argument,argument})]]))
+-- inspect(splitreference([[special(operation)]]))
+-- inspect(splitreference([[special(\operation)]]))
+-- inspect(splitreference([[special()]]))
+-- inspect(splitreference([[inner{argument}]]))
+-- inspect(splitreference([[inner{\argument}]]))
+-- inspect(splitreference([[outer::]]))
+-- inspect(splitreference([[outer::inner]]))
+-- inspect(splitreference([[outer::special(operation{argument,argument})]]))
+-- inspect(splitreference([[outer::special(operation{argument,\argument})]]))
+-- inspect(splitreference([[outer::special(operation)]]))
+-- inspect(splitreference([[outer::special(\operation)]]))
+-- inspect(splitreference([[outer::special()]]))
+-- inspect(splitreference([[outer::inner{argument}]]))
+-- inspect(splitreference([[special(outer::operation)]]))
diff --git a/Master/texmf-dist/tex/context/base/strc-sbe.mkiv b/Master/texmf-dist/tex/context/base/strc-sbe.mkiv
index e9d8d9c1ae1..a98b6788523 100644
--- a/Master/texmf-dist/tex/context/base/strc-sbe.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-sbe.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Section Block Environments,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -27,96 +27,90 @@
% \chapter{second} \section{alpha} test \section{beta} test \page
% \stopbodymatter % optional
-\definesystemvariable {nb}
+\unexpanded\def\definesectionblock{\dotripleargument\dodefinesectionblock}
+\unexpanded\def\setupsectionblock {\dodoubleargument\dosetupsectionblock}
+\def\setsectionblock {\dosingleargument\dosetsectionblock}
-\def\v!structureblockenvironment{structureblockenvironment}
-
-\unexpanded\def\definestructureblock{\dotripleargument\dodefinestructureblock}
-\unexpanded\def\setupstructureblock {\dodoubleargument\dosetupstructureblock}
-\def\setstructureblock {\dosingleargument\dosetstructureblock}
-
-% \def\structureblockparameter#1{\executeifdefined{\??nb\currentstructureblock#1}\empty}
-
-\def\structureblockparameter#1%
+\def\sectionblockparameter#1%
{\csname
- \ifcsname\??nb\currentstructureblock#1\endcsname\??nb\currentstructureblock#1\else\s!empty\fi
+ \ifcsname\??sb\currentsectionblock#1\endcsname\??sb\currentsectionblock#1\else\s!empty\fi
\endcsname}
-\newtoks \everybeforestructureblock
-\newtoks \everyafterstructureblock
+\newtoks \everybeforesectionblock
+\newtoks \everyaftersectionblock
-\def\dodefinestructureblock[#1][#2][#3]% singular plural settings
+\def\dodefinesectionblock[#1][#2][#3]% singular plural settings
{\getparameters
- [\??nb#1]
+ [\??sb#1]
[\c!number=\v!yes,
\c!page=\v!right, % anders worden marks te vroeg gereset !
#3]%
\expandafter\newif\csname if#2\endcsname % better a mode
- \setstructureblockenvironment{#1}\empty
- \setvalue {\e!start#2}{\startstructureblock[#1]}%
- \setvalue {\e!stop #2}{\stopstructureblock}}
+ \setsectionblockenvironment{#1}\empty
+ \setvalue {\e!start#2}{\startsectionblock[#1]}%
+ \setvalue {\e!stop #2}{\stopsectionblock}}
\ifdefined \resetallstructuremarks \else
\let\resetallstructuremarks\relax
\fi
\appendtoks
- \doifsomething{\structureblockparameter\c!page}{\page[\structureblockparameter\c!page]}%
+ \doifsomething{\sectionblockparameter\c!page}{\page[\sectionblockparameter\c!page]}%
\resetallstructuremarks
- \getstructureblockenvironment\currentstructureblock
- \structureblockparameter\c!before % don't move
- \dostarttagged\t!division\currentstructureblock
-\to \everybeforestructureblock
+ \getsectionblockenvironment\currentsectionblock
+ \sectionblockparameter\c!before % don't move
+ \dostarttagged\t!division\currentsectionblock
+\to \everybeforesectionblock
\appendtoks
- \structureblockparameter\c!after % don't move
- \doifsomething{\structureblockparameter\c!page}{\page[\structureblockparameter\c!page]}%
+ \sectionblockparameter\c!after % don't move
+ \doifsomething{\sectionblockparameter\c!page}{\page[\sectionblockparameter\c!page]}%
\dostoptagged
\resetallstructuremarks
-\to \everyafterstructureblock
+\to \everyaftersectionblock
-\def\dosetupstructureblock[#1]%
- {\getparameters[\??nb#1]}% [#2]
+\def\dosetupsectionblock[#1]%
+ {\getparameters[\??sb#1]}% [#2]
-\def\dosetstructureblock[#1]% used to set the default
- {\edef\currentstructureblock{\ctxlua{structures.sections.setblock("#1")}}}
+\def\dosetsectionblock[#1]% used to set the default
+ {\edef\currentsectionblock{\ctxlua{structures.sections.setblock("#1")}}}
-\let\currentstructureblock\s!unknown
+\let\currentsectionblock\empty % was \s!unknown
-\unexpanded\def\startstructureblock[#1]%
+\unexpanded\def\startsectionblock[#1]%
{%\ctxlua{structures.counters.check(0)}% we assume sane usage of \page, as this is the only workable place (in push)
\begingroup
- \edef\currentstructureblock{\ctxlua{structures.sections.pushblock("#1")}}%
+ \edef\currentsectionblock{\ctxlua{structures.sections.pushblock("#1")}}%
\csname #1true\endcsname % for old times sake
- \setsystemmode\currentstructureblock
- \the\everybeforestructureblock\relax
- \showmessage\m!structures1\currentstructureblock}
-
-\unexpanded\def\stopstructureblock
- {\showmessage\m!structures2\currentstructureblock
- \the\everyafterstructureblock\relax
- \edef\currentstructureblock{\ctxlua{structures.sections.popblock()}}%
+ \setsystemmode\currentsectionblock
+ \the\everybeforesectionblock\relax
+ \showmessage\m!structures1\currentsectionblock}
+
+\unexpanded\def\stopsectionblock
+ {\showmessage\m!structures2\currentsectionblock
+ \the\everyaftersectionblock\relax
+ \edef\currentsectionblock{\ctxlua{structures.sections.popblock()}}%
\endgroup}
-\long\def\setstructureblockenvironment#1#2%
- {\long\setvalue{\??nb\s!do#1}{\do{#2}}}
+\long\def\setsectionblockenvironment#1#2%
+ {\long\setvalue{\??sb\s!do#1}{\do{#2}}}
-\def\getstructureblockenvironment#1%
+\def\getsectionblockenvironment#1%
{\let\do\firstofoneargument
- %\structureblockparameter{\s!do#1}}
- \csname\??nb\s!do#1\endcsname}
+ %\sectionblockparameter{\s!do#1}}
+ \csname\??sb\s!do#1\endcsname}
%D \starttyping
%D \startsectionblockenvironment[frontpart]
-%D \setuppagenumbering[conversion=romannumerals]
+%D \setupnumber[userpage][numberconversion=romannumerals,start=1]
%D \stopsectionblockenvironment
%D
%D \startsectionblockenvironment[bodypart]
-%D \setuppagenumber[number=1]
+%D \setupnumber[userpage][numberconversion=numbers,start=1]
%D \stopsectionblockenvironment
%D
-%D \startsectionblockenvironment[frontpart]
-%D \setuppagenumbering[conversion=character]
+%D \startsectionblockenvironment[backpart]
+%D \setupnumber[userpage][numberconversion=numbers,start=1]
%D \stopsectionblockenvironment
%D
%D \starttext
@@ -126,22 +120,10 @@
%D \stoptext
%D \stoptyping
-\setvalue{\e!start\v!structureblockenvironment}%
- {\dosingleargument\dostartstructureblockenvironment}
-
-\def\dostartstructureblockenvironment[#1]% evt \pushendofline \popendofline
- {\long\def\do##1##2{\setstructureblockenvironment{#1}{##1##2}}%
- %\grabuntil{\e!stop\v!structureblockenvironment}{\structureblockparameter{\s!do#1}}}
- \grabuntil{\e!stop\v!structureblockenvironment}{\csname\??nb\s!do#1\endcsname}}
-
-% this will become: (we ran in parallel for a while during transition)
-
\setvalue{\e!start\v!sectionblockenvironment}%
{\dosingleargument\dostartsectionblockenvironment}
\def\dostartsectionblockenvironment[#1]% evt \pushendofline \popendofline
- {\long\def\do##1##2{\setstructureblockenvironment{#1}{##1##2}}%
- %\grabuntil{\e!stop\v!sectionblockenvironment}{\structureblockparameter{\s!do#1}}}
- \grabuntil{\e!stop\v!sectionblockenvironment}{\csname\??nb\s!do#1\endcsname}}
+ {\grabuntil{\e!stop\v!sectionblockenvironment}{\setsectionblockenvironment{#1}}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-sec.mkii b/Master/texmf-dist/tex/context/base/strc-sec.mkii
index 0698ef93c06..01ca71eadbc 100644
--- a/Master/texmf-dist/tex/context/base/strc-sec.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-sec.mkii
@@ -5,7 +5,7 @@
%D subtitle=Sectioning,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-sec.mkiv b/Master/texmf-dist/tex/context/base/strc-sec.mkiv
index 6cb6f84c142..e9b613f219f 100644
--- a/Master/texmf-dist/tex/context/base/strc-sec.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-sec.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Sectioning,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -50,411 +50,350 @@
\def\getsomestructurenumber #1#2{\ctxlua{structures.sections.getnumber(#1,"#2")}} % level, what
\def\getfullstructurenumber #1{\ctxlua{structures.sections.fullnumber(#1)}} % level
\def\getsomefullstructurenumber#1#2{\ctxlua{structures.sections.fullnumber(#1,"#2")}}
-\def\getspecificstructuretitle #1{\ctxlua{structures.sections.structuredata(#1,"titledata.title",nil,"\structureheadparameter\s!catcodes")}}%
+\def\getspecificstructuretitle #1{\ctxlua{structures.sections.structuredata("#1","titledata.title",nil,"\headparameter\s!catcodes")}}%
-% interface
+% will be:
+%
+% \def\getfullstructurenumber #1{\ctxcommand{structurenumber(\thenamedheadlevel{#1})}}
-\def\structureheadparameter #1{\csname\dostructureheadparameter{\??nh\currentstructurehead}{#1}\endcsname}
-\def\structureheadparameterhash #1{\dostructureheadparameterhash {\??nh\currentstructurehead}{#1}}
-\def\namedstructureheadparameter#1#2{\csname\dostructureheadparameter{\??nh#1}{#2}\endcsname}
+% structure heads (like \startchapter)
-\def\dostructureheadparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dostructureheadparentparameter \csname#1\s!parent\endcsname{#2}\fi}
-\def\dostructureheadparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\dostructureheadparentparameterhash\csname#1\s!parent\endcsname{#2}\fi}
+% \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
-\def\dostructureheadparentparameter #1#2{\ifx#1\relax\s!empty\else\dostructureheadparameter #1{#2}\fi}
-\def\dostructureheadparentparameterhash#1#2{\ifx#1\relax \else\dostructureheadparameterhash#1{#2}\fi}
+\installcorenamespace{head}
+\installcorenamespace{headlevel}
+\installcorenamespace{headincrement}
+\installcorenamespace{headplace}
+\installcorenamespace{headmarkyes}
+\installcorenamespace{headmarknop}
-\def\structureheadparameterstrict#1{\csname\ifcsname\??nh\currentstructurehead#1\endcsname\??nh\currentstructurehead#1\else\s!empty\fi\endcsname}
+\installcommandhandler \??head {head} \??head
-\def\dosetstructureheadattributes#1#2% style color
- {\edef\fontattributehash {\structureheadparameterhash#1}%
- \edef\colorattributehash{\structureheadparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
+\let\setupheads\setuphead % will go
-% so far
+\appendtoks
+ \ifx\currentheadparent\empty
+ \edef\currentheaddefault{\headparameter\c!default}%
+ \edef\currentheadsection{\headparameter\c!section}%
+ \ifx\currenthead\currentheaddefault
+ \let\currentheadparent\currentheadsection
+ \else\ifx\currentheaddefault\empty
+ \let\currentheadparent\currentheadsection
+ \else
+ \let\currentheadparent\currentheaddefault
+ \fi\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\c!number][\c!filtercommand=\noexpand\sectionheadmarkingnumber{\currenthead}]%
+ }%
+ \doifelselist\currenthead\donothing
+ {\definelist[\currenthead][\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
-\newcount\maxstructuredepth
+\appendtoks
+ \setstructurelevel\currenthead{\thenamedheadlevel\currenthead}%
+\to \everydefinehead
+
+\appendtoks
+ % beware, this is a global register
+ \begingroup
+ \edef\currentsectionheadcoupling{\sectionheadcoupling\currenthead}%
+ \edef\currentsectionheadsection {\sectionheadsection \currentsectionheadcoupling}%
+ \edef\currentsectionlevel {\sectionlevel \currentsectionheadsection}%
+ \ctxlua{structures.sections.register("\currenthead",{
+ coupling = "\currentsectionheadcoupling",
+ section = "\currentsectionheadsection",
+ level = \currentsectionlevel,
+ })}%
+ \endgroup
+\to \everydefinehead
+
+\appendtoks
+ % \setevalue{\e!next \currenthead}{\donexthead [\currenthead]}%
+ \setevalue{\e!start\currenthead}{\dostarthead[\currenthead]}%
+ \setevalue{\e!stop \currenthead}{\dostophead [\currenthead]}%
+\to \everydefinehead
+
+\appendtoks
+ \doifelse{\headparameter\c!ownnumber}\v!yes
+ {\setevalue\currenthead{\dohandleheadown[\currenthead]}}
+ {\setevalue\currenthead{\dohandleheadnop[\currenthead]}}%
+\to \everysetuphead
+
+\let\currentnamedsection\empty
+
+\unexpanded\def\startnamedsection
+ {\dotripleempty\dostartnamedsection}
-\let\laststructuresectionname\empty
+\def\dostartnamedsection[#1]% [#2][#3]
+ {\pushmacro\currentnamedsection
+ \edef\currentnamedsection{#1}%
+ \normalexpanded{\dodostarthead[\currentnamedsection]}} % [#2][#3]
+
+\unexpanded\def\stopnamedsection
+ {\normalexpanded{\dostophead[\currentnamedsection]}%
+ \popmacro\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[\v!section-1]} % will become option
-\def\resetcurrentstructuremarks {\resetmarking[\laststructuresectionname]} % will become option
-%def\resetcurrentstructuremarkswithpage{\resetmarking[\laststructuresectionname]} % will become option
-
-% \c!before=,
-% \c!after=,
-% \c!distance=\zeropoint,
-% \c!page=,
-% \c!header=,
-% \c!text=,
-% \c!footer=,
-% \c!numbercommand=,
-% \c!textcommand=,
-% \c!ownnumber=\v!no,
-% \c!number=\v!yes,
-% \c!file=,
-% \c!expansion=,
-% \c!grid=,
-% \c!margintext=,
-%
-% \c!xmlsetup=,
-% \s!catcodes=,
+\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
-\newtoks\everydefinestructuresection
+% -2=text -1=manual 0=block 1+=structurelevel
-\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.
- \getparameters[\??nh\currentstructuresection]
- [ \c!textstyle=\structureheadparameterstrict\c!style,
- \c!textcolor=\structureheadparameterstrict\c!color,
- \c!numberstyle=\structureheadparameterstrict\c!style,
- \c!numbercolor=\structureheadparameterstrict\c!color]%
-\to \everydefinestructuresection
-
-\unexpanded\def\definestructuresection[#1]%
- {\ifcsname\??nh#1\endcsname
- % redefinition is a rather fatal error
- \else
- \edef\currentstructuresection{#1}%
- \global\advance\maxstructuredepth\plusone
- \setevalue{\??nh#1\c!level}{\the\maxstructuredepth}%
- \setstructurelevel{#1}{\the\maxstructuredepth}%
- \normalexpanded{\noexpand\getparameters[\??nh#1][\s!parent=\??nh\laststructuresectionname]}%
- \the\everydefinestructuresection
+\newcount\maxstructuredepth
+
+\def\setnextsectionlevel#1%
+ {\global\advance\maxstructuredepth\plusone
+ \setevalue{\??headlevel#1}{\the\maxstructuredepth}}
+
+\def\sectionlevel#1%
+ {\csname\??headlevel\ifcsname\??headlevel#1\endcsname#1\else\v!none\fi\endcsname}
+
+\setvalue{\??headlevel\v!block}{0}
+\setvalue{\??headlevel\v!none }{-1}
+\setvalue{\??headlevel\v!text }{-2}
+
+\newtoks\everydefinesection
+
+\unexpanded\def\definesection[#1]%
+ {\ifcsname\??headlevel#1\endcsname \else
+ \edef\currentsection{#1}% not used, will go
+ \edef\currenthead{#1}%
+ \setnextsectionlevel{#1}%
+ \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{\noexpand\relatemarking[#1][\laststructuresectionname]}% so, the parent will reset the child
+ \normalexpanded{\noexpand\relatemarking[#1][\lastsectionname]}% so, the parent will reset the child
\fi
- \xdef\laststructuresectionname{#1}%
- \fi}
-
-\unexpanded\def\setupstructuresection
- {\dotripleempty\dosetupstructuresection}
+ \xdef\lastsectionname{#1}%
+ \ifx\firstsectionname\empty
+ \glet\firstsectionname\lastsectionname
+ \fi
+ \fi}
-\def\dosetupstructuresection[#1]%
- {\doifdefinedelse{\??nh#1}
- {\dodosetupstructuresection[#1]}
- {\dodosetupstructuresection[\structuresectionheadsection{#1}]}}
+\unexpanded\def\setupsection
+ {\dotripleempty\dosetupsection}
-\def\dodosetupstructuresection[#1][#2][#3]%
- {\ifthirdargument
- \getparameters[\??nh#1#2][#3]% ? probably sectionblock
+\def\dosetupsection[#1][#2][#3]%
+ {\ifcsname\??headlevel#1\endcsname
+ \dodosetupsection[#1][#2][#3]%
\else
- \getparameters[\??nh#1][#2]%
+ \dodosetupsection[\sectionheadsection{#1}][#2][#3]%
\fi}
-% -2=text -1=manual 0=block 1+=structurelevel
+\def\dodosetupsection[#1][#2][#3]%
+ {\pushmacro\currenthead
+ \ifthirdargument
+ \edef\currenthead{#1#2}% % not used at any more in mkiv (sets now)
+ \setupcurrenthead[#3]%
+ \else
+ \edef\currenthead{#1}%
+ \setupcurrenthead[#2]%
+ \fi
+ \popmacro\currenthead}
-\def\structuresectionlevel#1%
- {\executeifdefined{\??nh#1\c!level}{-1}}
-
-\setvalue{\??nh\v!block\c!level}{0}
-\setvalue{\??nh\v!none \c!level}{-1}
-\setvalue{\??nh\v!text \c!level}{-2}
-
-% head -> structurehead
-
-\let\currentstructurehead\empty
-\newtoks\everystructureheadsetup
-
-\unexpanded\def\setupstructureheads{\dosingleargument\dosetupstructureheads}
-\unexpanded\def\setupstructurehead {\dodoubleempty\dosetupstructurehead}
-\unexpanded\def\definestructurehead{\dodoubleempty\dodefinestructurehead}
-
-\newif\ifsectionnumber % maybe conditional
-
-\def\dosetupstructureheads[#1]%
- {\getparameters[\??nh][#1]%
- \doifelse{\structureheadparameter\c!sectionnumber}\v!yes\sectionnumbertrue\sectionnumberfalse}
-
-\def\dosetupstructurehead[#1][#2]% we move the test for command being nothing elsewhere (needed, else hard to trace)
- {\processcommalist[#1]{\dodosetupstructurehead{#2}}}
-
-\def\dodosetupstructurehead#1#2%
- {\edef\currentstructurehead{#2}%
- \getparameters[\??nh#2][#1]%
- \the\everystructureheadsetup}
-
-\def\dodefinestructurehead[#1][#2]%
- {\processcommalist[#1]{\dododefinestructurehead{#2}}}
-
-\def\dododefinestructurehead#1#2% #1: parameters|parent, #2: self
- {\doifsomethingelse{#2}
- {\doifassignmentelse{#1}
- \dodefineuniquestructurehead
- {\doifdefinedelse{\??nh#1\s!parent} % just a check
- \dodefineclonedstructurehead
- \dodefineerrorstructurehead}}
- \dodefineerrorstructurehead
- {#2}{#1}}
-
-\def\dodefineerrorstructurehead#1#2%
- {\setvalue{#1}{\par error: #1 is undefined\par}}
-
-% deeptextcommand and deepnumbercommand are left undefined !
-
-\def\dodefineuniquestructurehead#1#2% class, parent
- {\def\currentstructurehead{#1}%
- \presetlabeltext[#1=]%
- \getparameters[\??nh#1][\c!label=#1,#2]%
- \edef\currentstructureheaddefault{\structureheadparameter\c!default}%
- \edef\currentstructureheadsection{\structureheadparameter\c!section}%
- \edef\currentstructureheadparent
- {\ifx\currentstructurehead\currentstructureheaddefault
- \currentstructureheadsection
- \else\ifx\currentstructureheaddefault\empty
- \currentstructureheadsection
- \else
- \currentstructureheaddefault
- \fi\fi}%
- \normalexpanded{\noexpand\getparameters[\??nh#1][\s!parent=\??nh\currentstructureheadparent]}%
- % or just \setevalue{\??nh#1\s!parent}{\??nh\currentstructureheadparent}%
- \definemarking[#1] [\currentstructureheadsection]%
- \definemarking[#1\v!number][\currentstructureheadsection]%
- \setupmarking [#1] [\c!filtercommand=\sectionheadmarkingtitle {#1}]%
- \setupmarking [#1\c!number][\c!filtercommand=\sectionheadmarkingnumber{#1}]%
- \doifundefined{\??li#1}{\definelist[#1][\c!prefix=\v!no]}% definestructurelist ?
- \the\everystructureheadsetup}
+% 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 {\strictheadparameter\c!style}%
+ \setheadparameter\c!textcolor {\strictheadparameter\c!color}%
+ \setheadparameter\c!numberstyle{\strictheadparameter\c!style}%
+ \setheadparameter\c!numbercolor{\strictheadparameter\c!color}%
+\to \everydefinesection
+
+% head -> head
\def\sectionheadmarkingtitle #1#2{\ctxlua{structures.marks.title("#1","#2")}}
\def\sectionheadmarkingnumber#1#2{\ctxlua{structures.marks.number("#1","#2")}}
-\def\dodefineclonedstructurehead#1#2% class parent
- {\def\currentstructurehead{#1}%
- \presetlabeltext[#1=]%
- \doifelse{#1}{#2}
- {\getparameters[\??nh#1][\c!label=#1]%
- \doifundefined{\??li#1}{\definelist[#1][\c!prefix=\v!no]}}% definestructurelist ?
- {\getparameters[\??nh#1][\s!parent=\??nh#2,\c!label=#1,\c!coupling=#2]%
- \definemarking[#1] [#2]%
- \definemarking[#1\v!number][#2\c!number]%
- \doifundefined{\??li#1}{\definelist[#1][#2][\c!prefix=\v!no]}}% definestructurelist ?
- \the\everystructureheadsetup}
-
-\appendtoks
- \setstructurelevel\currentstructurehead{\thenamedstructureheadlevel\currentstructurehead}%
- \doifelse{\structureheadparameter\c!ownnumber}\v!yes
- {\setevalue\currentstructurehead{\dohandlestructureheadown[\currentstructurehead]}}
- {\setevalue\currentstructurehead{\dohandlestructureheadnop[\currentstructurehead]}}%
- \setevalue{\e!next \currentstructurehead}{\donextstructurehead [\currentstructurehead]}%
- \setevalue{\e!start\currentstructurehead}{\dostartstructurehead[\currentstructurehead]}%
- \setevalue{\e!stop \currentstructurehead}{\dostopstructurehead [\currentstructurehead]}%
-\to \everystructureheadsetup
-
-% todo, check if section is defined
-
-\def\structuresectionheadcoupling#1%
- {\ifcsname\??nh#1\c!coupling\endcsname
- \expandafter\structuresectionheadcoupling\csname\??nh#1\c!coupling\endcsname\else#1%
- \fi}
-
-\def\structuresectionheadsection#1%
- {\ifcsname\??nh#1\c!section\endcsname
- \expandafter\structuresectionheadcoupling\csname\??nh#1\c!section\endcsname\else#1%
- \fi}
+\def\sectionheadcoupling#1{\namedheadparameter{#1}\c!coupling}
+\def\sectionheadsection #1{\namedheadparameter{#1}\c!section}
% head construction
-\unexpanded\def\dohandlestructureheadown{\dodoubleempty\dodohandlestructureheadown} % [ref] {nr} {title}
-\unexpanded\def\dohandlestructureheadnop{\dodoubleempty\dodohandlestructureheadnop} % [ref] {title}
-\unexpanded\def\dostartstructurehead {\dotripleempty\dodostartstructurehead} % [settings] [userdata]
+\unexpanded\def\dohandleheadown{\dodoubleempty\dodohandleheadown} % [ref] {nr} {title}
+\unexpanded\def\dohandleheadnop{\dodoubleempty\dodohandleheadnop} % [ref] {title}
+\unexpanded\def\dostarthead {\dotripleempty\dodostarthead} % [settings] [userdata] !!! also used at lua end
\newconditional\currentstructureown
-\newtoks\everybeforestructurehead % hook, todo: before/after keys
-\newtoks\everyafterstructurehead % hook, todo: before/after keys
+\newtoks\everybeforehead % hook, todo: before/after keys
+\newtoks\everyafterhead % hook, todo: before/after keys
-\unexpanded\def\dodohandlestructureheadown[#1][#2]#3#4%
+\unexpanded\def\dodohandleheadown[#1][#2]#3#4%
{\settrue\currentstructureown
- \dohandlestructurehead{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title --
-
-% \unexpanded\def\dodohandlestructureheadnop[#1][#2]#3%
-% {\setfalse\currentstructureown
-% \dohandlestructurehead{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --
+ \triggerautostructurelevel
+ \dohandlehead{#1}{\c!reference={#2},\c!ownnumber={#3},\c!title={#4}}{}} % name ref nr title --
-\unexpanded\def\dodohandlestructureheadnop[#1][#2]% for taco: [key=value] variant
+\unexpanded\def\dodohandleheadnop[#1][#2]% for taco: [key=value] variant
{\setfalse\currentstructureown
- \doifassignmentelse{#2}\dodohandlestructureheadnopA\dodohandlestructureheadnopB{#1}{#2}}
+ \triggerautostructurelevel
+ \doifassignmentelse{#2}\dodohandleheadnopA\dodohandleheadnopB{#1}{#2}}
-\unexpanded\def\dodohandlestructureheadnopA#1#2%
- {\dohandlestructurehead{#1}{#2}{}}
+\unexpanded\def\dodohandleheadnopA#1#2%
+ {\dohandlehead{#1}{#2}{}}
-\unexpanded\def\dodohandlestructureheadnopB#1#2#3%
- {\dohandlestructurehead{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --
+\unexpanded\def\dodohandleheadnopB#1#2#3%
+ {\dohandlehead{#1}{\c!reference={#2},\c!title={#3}}{}} % name ref nr title --
-\unexpanded\def\dodostartstructurehead[#1][#2][#3]% for the moment no grouping, too annoying with page breaks
+\unexpanded\def\dodostarthead[#1][#2][#3]% for the moment no grouping, too annoying with page breaks
{\setfalse\currentstructureown
- %\globalpushmacro\currentstructurehead
- \xdef\currentstructurehead{#1}%
- \structureheadparameter\c!beforesection
- \the\everybeforestructurehead
- \dohandlestructurehead{#1}{#2}{#3}} % name -- -- -- userdata (we might move the tagged to here)
-
-\unexpanded\def\dostopstructurehead[#1]%
- {\dostoptagged\dostoptagged
- %\globalpopmacro\currentstructurehead
- \xdef\currentstructurehead{#1}% recover
- \structureheadparameter\c!aftersection
- \the\everyafterstructurehead}
-
-\unexpanded\def\donextstructurehead[#1][#2][#3]%
- {\setfalse\currentstructureown
- \xdef\currentstructurehead{#1}%
- \dohandlestructurehead{#1}{#2}{#3}} % name -- -- -- userdata
+ %\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
+ \dohandlehead{#1}{#2}{#3}% name -- -- -- userdata (we might move the tagged to here)
+ \headparameter\c!insidesection}
+
+\unexpanded\def\dostophead[#1]% !!! also used at lua end
+ {\dostoptagged
+ \dostoptagged
+ %\globalpopmacro\currenthead % so we do a hard recover
+ \xdef\currenthead{#1}% recover
+ \headparameter\c!aftersection
+ \the\everyafterhead
+ \resetsystemmode\currenthead} % new, also here now
+
+% \unexpanded\def\donexthead[#1][#2][#3]% obsolete
+% {\setfalse\currentstructureown
+% \xdef\currenthead{#1}%
+% \dohandlehead{#1}{#2}{#3}} % name -- -- -- userdata
% \newconditional\structurereversesectionnumbers % todo: key/val
-\newconditional\structureheadtolist
-\newconditional\structureheaddoincrement
-\newconditional\structureheaddoplace
-\newconditional\structureheadleaveempty
-\newconditional\structureheadhidden
-\newconditional\structureheadshownumber
-\newconditional\structureheadisdisplay
-
-\let\structureheadprefix\empty \def\structureheadprefixplus{+}
-
-% When do we reset the referenceprefix? This needs to be checked. Does it work
-% at all? Todo: pushpop.
-
-% \def\setstructureheadreference
-% {\edef\structureheadreference {\structureheadparameter\c!reference}%
-% \edef\structureheadreferenceprefix{\structureheadparameter\c!prefix}%
-% \ifx\structureheadreferenceprefix\empty
-% \ifx\currentrefenceprefix\structureheadreferenceprefixplus
-% \setupreferenceprefix[]% yes or no? only when set by structure
-% \fi
-% \else\ifx\structureheadreferenceprefix\structureheadreferenceprefixplus
-% \ifx\structureheadreference\empty
-% \expanded{\setupreferenceprefix[\structureheadreferenceprefixplus]}%
-% \else
-% \expanded{\setupreferenceprefix[\structureheadreference]}% we assume just one reference
-% \fi
-% \else
-% \expanded{\setupreferenceprefix[\structureheadreferenceprefix]}%
-% \fi\fi}
-
-% pop in stopsection commands unless empty
-
-\def\setstructureheadreference
- {\edef\structureheadreference {\structureheadparameter\c!reference}%
- \edef\structureheadreferenceprefix{\structureheadparameter\c!prefix}%
- \ifx\structureheadreferenceprefix\empty
- \let\structureheadreferenceprefix\referenceprefix
- \else
- \setupreferenceprefix[\structureheadreferenceprefix]% currenty no pop
- \fi}
-
-\setvalue{\??nh:\c!incrementnumber:\v!yes }{\settrue \structureheaddoincrement\settrue \structureheadtolist}
-\setvalue{\??nh:\c!incrementnumber:\v!no }{\setfalse\structureheaddoincrement\setfalse\structureheadtolist}
-\setvalue{\??nh:\c!incrementnumber:\v!list }{\setfalse\structureheaddoincrement\settrue \structureheadtolist}
-\setvalue{\??nh:\c!incrementnumber:\s!empty}{\settrue \structureheaddoincrement\settrue \structureheadtolist}
-
-\def\setstructureheadincrement
- {\edef\currentstructureheadincrement{\structureheadparameter\c!incrementnumber}%
- \ifcsname\??nh:\c!incrementnumber:\currentstructureheadincrement\endcsname
- \csname\??nh:\c!incrementnumber:\currentstructureheadincrement\endcsname
+\newconditional\headtolist
+\newconditional\headdoincrement
+\newconditional\headdoplace
+\newconditional\headleaveempty
+\newconditional\headhidden
+\newconditional\headshownumber
+\newconditional\headisdisplay
+
+\setvalue{\??headincrement\v!yes }{\settrue \headdoincrement\settrue \headtolist}
+\setvalue{\??headincrement\v!no }{\setfalse\headdoincrement\setfalse\headtolist}
+\setvalue{\??headincrement\v!list }{\setfalse\headdoincrement\settrue \headtolist}
+\setvalue{\??headincrement\s!empty}{\settrue \headdoincrement\settrue \headtolist}
+
+\def\setheadincrement
+ {\edef\currentheadincrement{\headparameter\c!incrementnumber}%
+ \ifcsname\??headincrement\currentheadincrement\endcsname
+ \csname\??headincrement\currentheadincrement\endcsname
\else
- \settrue \structureheaddoincrement\settrue \structureheadtolist
- % \filterstructureheadnumber
+ \settrue \headdoincrement\settrue \headtolist
+ % \filterheadnumber
\fi}
-\def\filterstructureheadnumber
- {\settrue\structureheaddoincrement
- \settrue\structureheadtolist
+\def\filterheadnumber
+ {\settrue\headdoincrement
+ \settrue\headtolist
\ifx\currentproduct\empty
% todo : filter from other toc (number, file, title)
- % use : \currentstructureheadincrement as spec
+ % use : \currentheadincrement as spec
\fi}
-% \def\setstructureheadplacement
-% {\setfalse\structureheadleaveempty
-% \settrue \structureheaddoplace
-% \setfalse\structureheadhidden
-% \processaction
-% [\structureheadparameter\c!placehead]
-% [ \v!yes=>,
-% \v!empty=>\settrue\structureheadleaveempty,
-% \v!no=>\settrue\structureheadleaveempty\setfalse\structureheaddoplace,
-% \v!hidden=>\settrue\structureheadleaveempty\setfalse\structureheaddoplace\settrue\structureheadhidden]}
-
-\setvalue{\??nh:\c!placehead:\v!yes}%
- {\setfalse\structureheadleaveempty
- \settrue \structureheaddoplace
- \setfalse\structureheadhidden}
-
-\setvalue{\??nh:\c!placehead:\v!empty}%
- {\settrue \structureheadleaveempty
- \settrue \structureheaddoplace
- \setfalse\structureheadhidden}
-
-\setvalue{\??nh:\c!placehead:\v!no}%
- {\settrue \structureheadleaveempty
- \setfalse\structureheaddoplace
- \setfalse\structureheadhidden}
-
-\setvalue{\??nh:\c!placehead:\v!hidden}%
- {\settrue \structureheadleaveempty
- \setfalse\structureheaddoplace
- \settrue \structureheadhidden}
-
-\def\setstructureheadplacement
+\setvalue{\??headplace\v!yes}%
+ {\setfalse\headleaveempty
+ \settrue \headdoplace
+ \setfalse\headhidden}
+
+\setvalue{\??headplace\v!empty}%
+ {\settrue \headleaveempty
+ \settrue \headdoplace
+ \setfalse\headhidden}
+
+\setvalue{\??headplace\v!no}%
+ {\settrue \headleaveempty
+ \setfalse\headdoplace
+ \setfalse\headhidden}
+
+\setvalue{\??headplace\v!hidden}%
+ {\settrue \headleaveempty
+ \setfalse\headdoplace
+ \settrue \headhidden}
+
+\def\setheadplacement
{\executeifdefined
- {\??nh:\c!placehead:\structureheadparameter\c!placehead}
- {\getvalue{\??nh:\c!placehead:\v!yes}}}
+ {\??headplace\headparameter\c!placehead}
+ {\getvalue{\??headplace\v!yes}}}
+
+
+\ifdefined\setheaddisplay \else \let\setheaddisplay\relax \fi
-\def\setstructureheaddisplay
- {\doifelsevalue{\??nh:\structureheadparameter\c!alternative}\v!horizontal
- {\setfalse\structureheadisdisplay}
- {\settrue \structureheadisdisplay}}
+\newmode\v!sectionnumber
\def\dosettructureheadnumbercontent
- {\setsystemmode \v!sectionnumber
- \settrue\structureheadshownumber}
+ {\setsystemmode\v!sectionnumber
+ \settrue\headshownumber} % why ?
\def\doresettructureheadnumbercontent
{\resetsystemmode\v!sectionnumber
- \setfalse\structureheadshownumber}
-
-\def\setstructureheadnumber
- {\ifsectionnumber
- \doifelse{\structureblockparameter\c!number}\v!yes % todo
- {\doifelse{\structureheadparameter\c!number}\v!yes
- {\settrue\structureheadshownumber}
- {\setfalse\structureheadshownumber}}
- {\setfalse\structureheadshownumber}%
- \else
- \setfalse\structureheadshownumber
- \fi}
+ \setfalse\headshownumber} % why ?
+
+\def\setheadnumber
+ {\doifelse{\sectionblockparameter\c!number}\v!yes % todo
+ {\doifelse{\headparameter\c!number}\v!yes
+ {\settrue\headshownumber}
+ {\setfalse\headshownumber}}
+ {\setfalse\headshownumber}}
-\unexpanded\def\thestructureheadsynchonization
- {\pagetype[\currentstructureheadcoupling]% hm also number
- \currentstructuresynchronize}
+\unexpanded\def\theheadsynchonization
+ {\currentstructuresynchronize}
-\unexpanded\def\setstructureheadmarking
- {\normalexpanded{\noexpand\setmarking[\currentstructurehead]{\currentstructurelistnumber}}}
+% 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)
-% \unexpanded\def\fullstructureheadnumber{\labeltexts{\structureheadparameter\c!label}{\structurenumber}} % todo
-% \def\fullstructureheadtitle {\structurevariable{titledata.title}} % no catcode!
-% \unexpanded\def\fullstructureheadtitle{\structureautocatcodedget{titledata.title}{\structureheadparameter\s!catcodes}}
+\unexpanded\def\setheadmarking % li:: so that we can use \marking[section]{Taco needed this}
+ {\normalexpanded{\setmarking[\currenthead]{li::\currentstructurelistnumber}}}
\let\deepstructurenumbercommand\relax
\let\deepstructuretitlecommand \relax
-\unexpanded\def\fullstructureheadnumber
- {\edef\currentstructureheadlabeltag{\currentstructureblock\c!label}%
+\unexpanded\def\fullheadnumber
+ {\edef\currentheadlabeltag{\currentsectionblock\c!label}%
\dostarttagged\t!sectionnumber\empty
\labeltexts
- {\structureheadparameter\currentstructureheadlabeltag}
+ {\headparameter\currentheadlabeltag}
{\ifx\deepstructurenumbercommand\relax
\structurenumber
\else
@@ -462,7 +401,7 @@
\fi}%
\dostoptagged}
-\unexpanded\def\fullstructureheadtitle
+\unexpanded\def\fullheadtitle
{\dostarttagged\t!sectiontitle\empty
\ifx\deepstructuretitlecommand\relax
\structuretitle
@@ -471,92 +410,94 @@
\fi
\dostoptagged}
-\let\currentstructurehead \empty
-\let\currentstructureheadcoupling\empty
-\let\currentstructureheadsection \empty
-\let\currentstructureheadlevel \!!zerocount
-\let\currentstructureheadcounter \!!zerocount
+\let\currenthead \empty
+\let\currentheadcoupling\empty
+\let\currentheadsection \empty
+\let\currentheadlevel \!!zerocount
+\let\currentheadcounter \!!zerocount
% here we could inherit as well but it's a bit complex
-\def\doregisterstructurehead#1#2#3% name data userdata
+\def\doregisterhead#1#2#3% name data userdata
{\structurecomponent
- %[\c!label={\structureheadparameter\c!label}, % why { }
- [\c!label={\structureheadparameter{\currentstructureblock\c!label}},
- \c!incrementnumber=\ifconditional\structureheaddoincrement\v!yes\else\v!no\fi, % not that needed
- \c!saveinlist=\ifconditional\structureheadtolist\v!yes\else\v!no\fi,
- \c!level=\currentstructureheadlevel,
+ %[\c!label={\headparameter\c!label}, % why { }
+ [\c!label={\headparameter{\currentsectionblock\c!label}},
+ \c!incrementnumber=\ifconditional\headdoincrement\v!yes\else\v!no\fi, % not that needed
+ \c!saveinlist=\ifconditional\headtolist\v!yes\else\v!no\fi,
+ \c!level=\currentheadlevel,
\c!name=#1,
- \c!number=\ifconditional\structureheaddoincrement\ifconditional\structureheadshownumber\v!yes\else\v!no\fi\else\v!no\fi,
+ \c!number=\ifconditional\headdoincrement\ifconditional\headshownumber\v!yes\else\v!no\fi\else\v!no\fi,
\c!bookmark=,
\c!marking=,
\c!list=,
- \c!expansion=\structureheadparameter\c!expansion,
- \c!xmlsetup=\structureheadparameter\c!xmlsetup,
- \s!catcodes=\structureheadparameter\s!catcodes,
- \c!sectionresetset=\structureheadparameter\c!sectionresetset,
- \c!sectionseparatorset=\structureheadparameter\c!sectionseparatorset,
- \c!sectionconversionset=\structureheadparameter\c!sectionconversionset,
- \c!sectionconversion=\structureheadparameter\c!conversion, % just for compatibility
- \c!sectionstarter=\structureheadparameter\c!sectionstarter,
- \c!sectionstopper=\structureheadparameter\c!sectionstopper,
- \c!sectionset=\structureheadparameter\c!sectionset,
- \c!sectionsegments=\structureheadparameter\c!sectionsegments,
- \c!reference=\structureheadreference,
- \c!referenceprefix=\structureheadreferenceprefix,
+ \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!backreference=,
\c!command=,
#2]%
[#3]%
\reportcurrentstructure}
-\unexpanded\def\placeheadtext {\dosingleempty\doplaceheadtext } % use with care
-\unexpanded\def\placeheadnumber{\dosingleempty\doplaceheadnumber} % use with care
+\unexpanded\def\placeheadtext {\dosingleempty\strc_sections_place_head_text } % use with care
+\unexpanded\def\placeheadnumber{\dosingleempty\strc_sections_place_head_number} % use with care
\ifdefined\setupheadcomponentfont \else
\unexpanded\def\setupheadcomponentfont#1#2%
{\dontconvertfont
- \dosetstructureheadattributes\c!style\c!color
- \dosetstructureheadattributes#1#2%
+ \useheadstyleandcolor\c!style\c!color
+ \useheadstyleandcolor#1#2%
\setupinterlinespace}
\fi
-\def\doplaceheadtext[#1]%
+\def\strc_sections_place_head_text[#1]%
{\dontleavehmode
\begingroup
- \edef\currentstructurehead{#1}%
+ \edef\currenthead{#1}%
\setupheadcomponentfont\c!textstyle\c!textcolor
\relax
- \getspecificstructuretitle{\thenamedstructureheadlevel{#1}}%
+ \getspecificstructuretitle{\thenamedheadlevel{#1}}%
\endgraf
\endgroup}
-\def\doplaceheadnumber[#1]%
+\def\strc_sections_place_head_number[#1]%
{\dontleavehmode
\begingroup
- \edef\currentstructurehead{#1}%
+ \edef\currenthead{#1}%
\setupheadcomponentfont\c!numberstyle\c!numbercolor
\relax
- \getfullstructurenumber{\thenamedstructureheadlevel{#1}}%
+ \getfullstructurenumber{\thenamedheadlevel{#1}}%
\endgraf
\endgroup}
-\ifdefined \else \let\presetnumberheadalternative\relax \fi
+\ifdefined\presetnumberheadalternative \else \let\presetnumberheadalternative\relax \fi
+\ifdefined\setautostructurelevel \else \let\setautostructurelevel \relax \fi
+\ifdefined\triggerautostructurelevel \else \let\triggerautostructurelevel \relax \fi
-\def\dohandlestructurehead#1#2#3% name data userdata (we can move #1 to the caller)
- {\xdef\currentstructurehead {#1}%
- \xdef\currentstructureheadcoupling{\structuresectionheadcoupling\currentstructurehead}%
- \xdef\currentstructureheadsection {\structuresectionheadsection \currentstructureheadcoupling}%
- \xdef\currentstructureheadlevel {\structuresectionlevel \currentstructureheadsection}%
- %writestatus\m!system{setup: \currentstructurehead,\currentstructureheadcoupling,\currentstructureheadsection,\currentstructureheadlevel}%
+\def\dohandlehead#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}%
%
- \setstructureheadreference % does not do much currently
- \setstructureheadincrement
- \setstructureheadplacement
- \setstructureheaddisplay
- \setstructureheadnumber
+ \setautostructurelevel
+ \setheadincrement
+ \setheadplacement
+ \setheaddisplay
+ \setheadnumber
%
\unexpanded\def\\{\space}%
\flushingcolumnfloatsfalse
@@ -565,69 +506,69 @@
%
% we might remove the lower level
%
- % not here, after optional \page: \doregisterstructurehead\currentstructurehead{#2}{#3}%
+ % not here, after optional \page: \doregisterhead\currenthead{#2}{#3}%
%
-% \xdef\currentstructureheadcounter{\currentstructurecounter}% lua call
+% \xdef\currentheadcounter{\currentsectioncountervalue}% lua call
%
% \currentstructuresynchronize % will move
%
- \edef\numberheaddistance {\structureheadparameter\c!distance }% compatibility
- \edef\numberheadalternative{\structureheadparameter\c!alternative}% compatibility
+ \edef\numberheaddistance {\headparameter\c!distance }% compatibility
+ \edef\numberheadalternative{\headparameter\c!alternative}% compatibility
\presetnumberheadalternative
%
- \let\getstructureheadnumber\empty
- \let\getstructureheadtitle \empty
- \let\getstructureheadsyncs \empty
- \ifconditional\structureheaddoincrement
- \ifconditional\structureheaddoplace
- \dostructureheadspacingbeforeyes
- \doregisterstructurehead\currentstructurehead{#2}{#3}% after optional \page
- \let\getstructureheadsyncs\thestructureheadsynchonization
- \let\getstructureheadtitle\fullstructureheadtitle
- \ifconditional\structureheadshownumber
- \let\getstructureheadnumber\fullstructureheadnumber
- \placestructureheadnumbertext
+ \let\getheadnumber\empty
+ \let\getheadtitle \empty
+ \let\getheadsyncs \empty
+ \ifconditional\headdoincrement
+ \ifconditional\headdoplace
+ \doheadspacingbeforeyes
+ \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \let\getheadsyncs\theheadsynchonization
+ \let\getheadtitle\fullheadtitle
+ \ifconditional\headshownumber
+ \let\getheadnumber\fullheadnumber
+ \placecurrentheadnumbertext
\else
- \placestructureheadtext
+ \placecurrentheadtext
\fi
- \dostructureheadspacingafteryes
- \else\ifconditional\structureheadhidden
- \doregisterstructurehead\currentstructurehead{#2}{#3}% after optional \page
- \let\getstructureheadsyncs\thestructureheadsynchonization
- \placestructureheadhidden % only something when tracing
+ \doheadspacingafteryes
+ \else\ifconditional\headhidden
+ \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \let\getheadsyncs\theheadsynchonization
+ \placecurrentheadhidden % only something when tracing
\else
- \dostructureheadspacingbeforenop % toegevoegd ivm subpaginanr / tug sheets
- \doregisterstructurehead\currentstructurehead{#2}{#3}% after optional \page
- \let\getstructureheadsyncs\thestructureheadsynchonization
- \placestructureheadempty % just flush 'm
- \dostructureheadspacingafternop
+ \doheadspacingbeforenop % toegevoegd ivm subpaginanr / tug sheets
+ \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \let\getheadsyncs\theheadsynchonization
+ \placecurrentheadempty % just flush 'm
+ \doheadspacingafternop
\fi\fi
\else
- \ifconditional\structureheaddoplace
- \dostructureheadspacingbeforeyes
- \doregisterstructurehead\currentstructurehead{#2}{#3}% after optional \page
- \let\getstructureheadsyncs\thestructureheadsynchonization
- \let\getstructureheadtitle\fullstructureheadtitle
- \placestructureheadtext
- \dostructureheadspacingafteryes
- \else\ifconditional\structureheadhidden
- \doregisterstructurehead\currentstructurehead{#2}{#3}% after optional \page
- \let\getstructureheadsyncs\thestructureheadsynchonization
- \placestructureheadhidden % only something when tracing
+ \ifconditional\headdoplace
+ \doheadspacingbeforeyes
+ \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \let\getheadsyncs\theheadsynchonization
+ \let\getheadtitle\fullheadtitle
+ \placecurrentheadtext
+ \doheadspacingafteryes
+ \else\ifconditional\headhidden
+ \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \let\getheadsyncs\theheadsynchonization
+ \placecurrentheadhidden % only something when tracing
\else
% do nothing / should be vbox to 0pt
- \dostructureheadspacingbeforenop
- \doregisterstructurehead\currentstructurehead{#2}{#3}% after optional \page
- \let\getstructureheadsyncs\thestructureheadsynchonization
- \placestructureheadempty % just flush 'm
- \dostructureheadspacingafternop
+ \doheadspacingbeforenop
+ \doregisterhead\currenthead{#2}{#3}% after optional \page
+ \let\getheadsyncs\theheadsynchonization
+ \placecurrentheadempty % just flush 'm
+ \doheadspacingafternop
\fi\fi
\fi
\flushingcolumnfloatstrue
\setfalse\ignorehandlepagebreak
% ignorespaces prevents spaces creeping in when after=\dontleavehmode
\dostarttagged\t!sectioncontent\empty
- \ifconditional\structureheadisdisplay % \ifdisplaysectionhead
+ \ifconditional\headisdisplay % \ifdisplaysectionhead
\ignorespaces
\else
\expandafter\GotoPar
@@ -635,40 +576,48 @@
% typesetting
-\unexpanded\def\placestructureheadnumbertext % dummy, will be overloaded
- {\setstructureheadmarking
- \getstructureheadnumber/\getstructureheadtitle
- \getstructureheadsyncs}
+\unexpanded\def\placecurrentheadnumbertext
+ {\setheadmarking
+ \getheadnumber/\getheadtitle
+ \getheadsyncs}
-\unexpanded\def\placestructureheadtext % dummy, will be overloaded
- {\setstructureheadmarking
- \getstructureheadtitle
- \getstructureheadsyncs}
+\unexpanded\def\placecurrentheadtext
+ {\setheadmarking
+ \getheadtitle
+ \getheadsyncs}
-\unexpanded\def\placestructureheadempty % dummy, will be overloaded
- {\setstructureheadmarking
- \getstructureheadsyncs}
+\unexpanded\def\placecurrentheadempty
+ {\setheadmarking
+ \getheadsyncs}
-\unexpanded\def\placestructureheadhidden
- {\setxvalue{\currentstructurehead:sync}%
- {\noexpand\setgvalue{\currentstructurehead:sync}{}%
- \noexpand\pagetype[\currentstructureheadcoupling]% hm also number
- \noexpand\setmarking[\currentstructureheadcoupling]{\currentstructurelistnumber}%
- \currentstructuresynchronize}}
+\installcorenamespace{hiddenheadattr}
+\installcorenamespace{hiddenheadsync}
-\def\synchronizestructurehead#1%
- {\getvalue{#1:sync}}
+% todo: when in the page builder we need to resolve the marking immediately
+% because otherwise we have an async
-\unexpanded\def\placerawheaddata [#1]{\synchronizestructurehead {#1}}
-\unexpanded\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedstructureheadlevel{#1}}}
-\unexpanded\def\placerawheadnumber[#1]{\getfullstructurenumber {\thenamedstructureheadlevel{#1}}}
+\unexpanded\def\placecurrentheadhidden % 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}%
+ \hbox\headreferenceattributes{}% otherwise no destination ... maybe tag ref as hidden and fall back on page reference
+ \currentstructuresynchronize}} % and it's a node anyway
+
+\def\synchronizehead #1{\csname\??hiddenheadsync#1\endcsname}
+\def\theheadreferenceattributes#1{\csname\??hiddenheadattr#1\endcsname}
+
+\unexpanded\def\placerawheaddata [#1]{\synchronizehead{#1}}
+\unexpanded\def\placerawheadtext [#1]{\getspecificstructuretitle{\thenamedheadlevel{#1}}}
+\unexpanded\def\placerawheadnumber[#1]{\getfullstructurenumber{\thenamedheadlevel{#1}}}
% \setuphead[chapter][placehead=hidden]
% \chapter {test}
%
-% %(\synchronizestructurehead{chapter}) % \getstructureheadsyncs
-% %(\getfullstructurenumber{\thenamedstructureheadlevel{chapter}})
-% %(\getspecificstructuretitle{\thenamedstructureheadlevel{chapter}})
+% %(\synchronizehead{chapter}) % \getheadsyncs
+% %(\getfullstructurenumber{\thenamedheadlevel{chapter}})
+% %(\getspecificstructuretitle{\thenamedheadlevel{chapter}})
%
% (\placerawheaddata [chapter])
% (\placerawheadnumber[chapter])
@@ -679,55 +628,47 @@
\newcount\precedingstructurelevel \precedingstructurelevel\plusone
\newconditional\ignorehandlepagebreak
-\def\dostructureheadspacingbeforeyes
- {\docheckstructureheadbefore
- \dohandlestructureheadpagebreakyes
- \structureheadparameter\c!inbetween
- \dostarttagged\t!section\currentstructurehead}
-
-\def\dostructureheadspacingbeforenop
- {\docheckstructureheadbefore
- \dohandlestructureheadpagebreaknop
- \structureheadparameter\c!inbetween
- \dostarttagged\currentstructurehead\empty}
-
-% \def\emptystructureheadcorrection
-% {\ifconditional\structureheadleaveempty % inlined \emptyheadcorrection (with after=\blank)
-% \vskip-\lineheight
-% \dosomebreak\nobreak % \penalty10000 in vspacing
-% \kern\zeropoint
-% \prevdepth\strutdepth
-% \fi}
-
-\def\emptystructureheadcorrection
- {\ifconditional\structureheadleaveempty % inlined \emptyheadcorrection (with after=\blank)
+\def\doheadspacingbeforeyes
+ {\docheckheadbefore
+ \dohandleheadpagebreakyes
+ \headparameter\c!inbetween
+ \dostarttagged\t!section\currenthead}
+
+\def\doheadspacingbeforenop
+ {\docheckheadbefore
+ \dohandleheadpagebreaknop
+ \headparameter\c!inbetween
+ \dostarttagged\currenthead\empty}
+
+\def\emptyheadcorrection
+ {\ifconditional\headleaveempty % inlined \emptyheadcorrection (with after=\blank)
\penalty10000 % first ... we need to adapt this all to vspacing
\vskip-\lineheight
\kern\zeropoint
\prevdepth\strutdepth
\fi}
-\def\dostructureheadspacingafteryes
- {\ifconditional\structureheadisdisplay
+\def\doheadspacingafteryes
+ {\ifconditional\headisdisplay
\dosomebreak\nobreak % needs to be adapted to vspacing
- \emptystructureheadcorrection
- \structureheadparameter\c!after
+ \emptyheadcorrection
+ \headparameter\c!after
\fi}
-\def\dostructureheadspacingafternop
+\def\doheadspacingafternop
{}
-\newsignal\continuousstructureheadsignal
+\newsignal\continuousheadsignal
-\def\docheckstructureheadbefore#1%
+\def\docheckheadbefore#1%
{\ifhmode
\scratchcounter\lastpenalty\unpenalty % no beauty in this
- \ifdim\lastskip=\continuousstructureheadsignal
+ \ifdim\lastskip=\continuousheadsignal
% no page break
\ifconditional\ignorehandlepagebreak
\setfalse\ignorehandlepagebreak
\else
- \global\precedingstructurelevel\currentstructureheadlevel
+ \global\precedingstructurelevel\currentheadlevel
\nobreak
\fi
\global\settrue\continuoussectionhead
@@ -741,125 +682,78 @@
#1%
\fi}
-\def\dodocheckstructureheadlayout#1#2%
+\def\dodocheckheadlayout#1#2%
{\doifelselayouttextline{#1}
- {\doifsomething{\structureheadparameter#2}{\expanded{\setuplayouttext[#1][\c!state=\structureheadparameter#2]}}}
+ {\doifsomething{\headparameter#2}{\expanded{\setuplayouttext[#1][\c!state=\headparameter#2]}}}
\donothing}
-\setvalue{\??nh:\??mk:n:\v!page }{}
-\setvalue{\??nh:\??mk:n:\v!reset}{\resetcurrentstructuremarks}
-\setvalue{\??nh:\??mk:y:\v!page }{} % to be checked: {\resetcurrentstructuremarks}
-\setvalue{\??nh:\??mk:y:\v!reset}{\resetcurrentstructuremarks}
-
-\def\docheckstructureheadlayout
- {\doifelsenothing{\structureheadparameter\c!page}
- {\getvalue{\??nh:\??mk:n:\structureheadparameter\c!marking}}
- {\page[\structureheadparameter\c!page]%
- \getvalue{\??nh:\??mk:y:\structureheadparameter\c!marking}%
- \dodocheckstructureheadlayout\v!header\c!header
- \dodocheckstructureheadlayout\v!text \c!text
- \dodocheckstructureheadlayout\v!footer\c!footer}}
-
-\def\currentstructurecounter {\ctxlua{structures.sections.depthnumber(\thenamedstructureheadlevel\currentstructurehead)}}
-\def\previousstructurecounter{\ctxlua{structures.sections.depthnumber(\thenamedstructureheadlevel\currentstructurehead-1)}}
-
-\def\dohandlestructureheadpagebreaknop
- {\doifelse{\structureheadparameter\c!continue}\v!yes
- {\ifnum\previousstructurecounter=\zerocount
- \docheckstructureheadlayout
- \else\ifnum\currentstructurecounter>\zerocount
- \docheckstructureheadlayout
+\setvalue{\??headmarknop\v!page }{}
+\setvalue{\??headmarknop\v!reset}{\resetcurrentstructuremarks}
+\setvalue{\??headmarkyes\v!page }{} % to be checked: {\resetcurrentstructuremarks}
+\setvalue{\??headmarkyes\v!reset}{\resetcurrentstructuremarks}
+
+\def\docheckheadlayout
+ {\doifelsenothing{\headparameter\c!page}
+ {\getvalue{\??headmarknop\headparameter\c!marking}}
+ {\page[\headparameter\c!page]%
+ \getvalue{\??headmarkyes\headparameter\c!marking}%
+ \dodocheckheadlayout\v!header\c!header
+ \dodocheckheadlayout\v!text \c!text
+ \dodocheckheadlayout\v!footer\c!footer}}
+
+\def\currentsectioncountervalue {\ctxlua{structures.sections.depthnumber(\thenamedheadlevel\currenthead)}}
+\def\previoussectioncountervalue{\ctxlua{structures.sections.depthnumber(\thenamedheadlevel\currenthead-1)}}
+
+\def\dohandleheadpagebreaknop
+ {\doifelse{\headparameter\c!continue}\v!yes
+ {\ifnum\previoussectioncountervalue=\zerocount
+ \docheckheadlayout
+ \else\ifnum\currentsectioncountervalue>\zerocount
+ \docheckheadlayout
\fi\fi}%
- {\docheckstructureheadlayout}}
+ {\docheckheadlayout}}
-\def\dohandlestructureheadpagebreakyes
- {%[[\currentstructurehead @\thenamedstructureheadlevel\currentstructurehead/prev:\previousstructurecounter/curr:\currentstructurecounter]]
+\def\dohandleheadpagebreakyes
+ {%[[\currenthead @\thenamedheadlevel\currenthead/prev:\previoussectioncountervalue/curr:\currentsectioncountervalue]]
\ifconditional\ignorehandlepagebreak
\setfalse\ignorehandlepagebreak
\else
- \ifnum\lastpenalty>\zerocount
+% \ifnum\lastpenalty>\zerocount
% \global\pagebreakdisabledtrue
- \fi
+% \fi
% beware, these numbers are not yet know here
- \doifelse{\structureheadparameter\c!continue}\v!yes
- {\ifnum\previousstructurecounter=\zerocount
- \docheckstructureheadlayout
- \else\ifnum\currentstructurecounter>\zerocount
- \docheckstructureheadlayout
+ \doifelse{\headparameter\c!continue}\v!yes
+ {\ifnum\previoussectioncountervalue=\zerocount
+ \docheckheadlayout
+ \else\ifnum\currentsectioncountervalue>\zerocount
+ \docheckheadlayout
\fi\fi}%
- {\docheckstructureheadlayout}%
- \doifnot{\structureheadparameter\c!aligntitle}\v!float\flushsidefloats
- \structureheadparameter\c!before
+ {\docheckheadlayout}%
+ \doifnot{\headparameter\c!aligntitle}\v!float\page_otr_command_flush_side_floats
+ \headparameter\c!before
\relax
% \ifpagebreakdisabled
% \global\pagebreakdisabledfalse
% \else
-% \dopreventbreakafterstructureheadauto % not ok as it binds the prev par
+% \dopreventbreakafterheadauto % not ok as it binds the prev par
% \fi
- \doif{\structureheadparameter\c!aligntitle}\v!float\indent
- \global\precedingstructurelevel\currentstructureheadlevel
+ \doif{\headparameter\c!aligntitle}\v!float\indent
+ \global\precedingstructurelevel\currentheadlevel
\fi}
-% the next one was: \somebreakmethod
-
-
-% 0 = nothing, 1 = weighted, 2 = strict, 3 = vspacing
+\settrue\autoheadbreak % todo: \vspacing[category:8] == keep_together
-\setnewconstant\somestructureheadbreakmethod\plusthree
-
-% \def\dopreventbreakafterstructureheadauto % used after \c!before
-% {\ifcase\somestructureheadbreakmethod
-% % 0 = nothing
-% \or
-% % 1 = old weighted version
-% \ifnum\currentstructureheadlevel>\precedingstructurelevel
-% \dosomebreak{\penalty\numexpr20000+500*\currentstructureheadlevel\relax}%
-% \else
-% \dosomebreak\allowbreak % brr
-% \fi
-% \or
-% % 2 = strict version
-% \dosomebreak{\penalty\maxdimen}%
-% \or
-% % 3 = vspacing
-% \vspacing[\v!samepage]% if preceded by ! then a loop
-% \else
-% % nothing
-% \fi}
-%
-% \def\dopreventbreakafterstructureheadspec#1% see enumerations etc
-% {\ifcase\somestructureheadbreakmethod
-% % 0 = nothing
-% \or
-% % 1 = old weighted version
-% \dosomebreak{\penalty\numexpr20000+500*(\currentstructureheadlevel+#1)\relax}%
-% \or
-% % 2 = strict version
-% \dosomebreak{\penalty\maxdimen}%
-% \or
-% % 3 = vspacing
-% \vspacing[\v!samepage]%
-% \else
-% % nothing
-% \fi}
-%
-% todo: \vspacing[category:8] == keep_together
-
-\def\dopreventbreakafterstructureheadauto % used after \c!before
- {\ifcase\somestructureheadbreakmethod
- % 0 = nothing
- \else
- \vspacing[\v!samepage-\currentstructureheadlevel]%
+\def\dopreventbreakafterheadauto % used after \c!before
+ {\ifconditional\autoheadbreak
+ \vspacing[\v!samepage-\currentheadlevel]%
\fi}
-\def\dopreventbreakafterstructureheadspec#1% see enumerations etc
- {\ifcase\somestructureheadbreakmethod
- % 0 = nothing
- \else
- \vspacing[\v!samepage-\the\numexpr\currentstructureheadlevel+1\relax]% todo #1
+\def\dopreventbreakafterheadspec#1% see enumerations etc
+ {\ifconditional\autoheadbreak
+ \vspacing[\v!samepage-\the\numexpr\currentheadlevel+1\relax]% todo #1
\fi}
-\def\dohandlepagebreakX{\dopreventbreakafterstructureheadspec} % no \let so we can redefind
+\def\dohandlepagebreakX{\dopreventbreakafterheadspec} % no \let so we can redefine
% we do support negative numbers but it can have side effects that we won't
% catch
@@ -867,65 +761,76 @@
% \chapter{some} \setupheadnumber[chapter][3] \chapter{more}
% \setupheadnumber[section][8] \section{b} \section{c} \setupheadnumber[section][-1] \section{d}
-% \def\thecurrentstructureheadlevel#1%
-% {\getcurrentstructurelevel{#1}}
-
-\def\thenamedstructureheadlevel#1%
- {\structuresectionlevel{\structuresectionheadsection{\structuresectionheadcoupling{#1}}}}
+\def\thenamedheadlevel#1%
+ {\sectionlevel{\sectionheadsection{\sectionheadcoupling{#1}}}}
\unexpanded\def\setupheadnumber
{\dodoubleargument\dosetupheadnumber}
\def\dosetupheadnumber[#1][#2]% todo: reset if at other level
- {\setstructurenumber{\thenamedstructureheadlevel{#1}}{#2}}
+ {\setstructurenumber{\thenamedheadlevel{#1}}{#2}}
-\def\currentstructureheadnumber{0} % ==> \currentheadnumber
+\def\currentheadnumber{0} % ==> \currentheadnumber
\unexpanded\def\determineheadnumber[#1]%
- {\xdef\currentstructureheadnumber{\getstructurenumber{\thenamedstructureheadlevel{#1}}}}
+ {\xdef\currentheadnumber{\getstructurenumber{\thenamedheadlevel{#1}}}}
% The previous macro is been replaced by the expandable:
-\def\namedheadnumber #1{\getstructurenumber {\thenamedstructureheadlevel{#1}}}
-\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedstructureheadlevel{#1}}{#2}}
+\def\namedheadnumber #1{\getstructurenumber {\thenamedheadlevel{#1}}}
+\def\somenamedheadnumber#1#2{\getsomestructurenumber{\thenamedheadlevel{#1}}{#2}}
-\unexpanded\def\structureheadnumber
- {\dodoubleempty\dostructureheadnumber}
+\unexpanded\def\headnumber
+ {\dodoubleempty\doheadnumber}
-\def\dostructureheadnumber[#1][#2]% simple case is just a number
- {\getsomefullstructurenumber{\iffirstargument\thenamedstructureheadlevel{#1}\fi}{#2}}
+\def\doheadnumber[#1][#2]% simple case is just a number
+ {\getsomefullstructurenumber{\iffirstargument\thenamedheadlevel{#1}\fi}{#2}}
-\def\somestructureheadnumber
- {\dodoubleempty\dosomestructureheadnumber}
+\def\someheadnumber
+ {\dodoubleempty\dosomeheadnumber}
-\def\dosomestructureheadnumber[#1][#2]%
+\def\dosomeheadnumber[#1][#2]%
{\dontleavehmode
\begingroup
- \edef\currentstructurehead{#1}%
- \getsomefullstructurenumber{\thenamedstructureheadlevel{#1}}{#2}%
+ \edef\currenthead{#1}%
+ \getsomefullstructurenumber{\thenamedheadlevel{#1}}{#2}%
\endgroup}
-% compatibility code (after all, we might offer different structure handlers as well
-% but we might as well remove the 'structure' substring at some point (we needed it
-% in order to test the old and new methods alongside)
-
-\let\definesectionblock \definestructureblock
-\let\definesection \definestructuresection
-\let\setupsection \setupstructuresection
-\let\setupheads \setupstructureheads
-\let\definehead \definestructurehead
-\let\setuphead \setupstructurehead
-\let\headnumber \structureheadnumber
-\let\setupsectionblock \setupstructureblock
-
\let\sectioncountervalue\structurevalue
-\def\currentheadnumber {\currentstructureheadnumber}
-\def\currentheadtext {obsolete, use marks}
+\def\currentheadtext{obsolete, use marks}
% list references, will be redone in lua when we need it
\let\startlistreferences\relax
\let\stoplistreferences \relax
+% experimental
+
+\newconditional\c_strc_sections_auto_levels
+
+\appendtoks
+ \settrue\c_strc_sections_auto_levels
+\to \everyenableelements
+
+\def\setautostructurelevel
+ {\ifconditional\c_strc_sections_auto_levels
+ \ctxcommand{autonextstructurelevel(\number\currentheadlevel)}%
+ \global\setfalse\c_strc_sections_auto_levels
+ \fi}
+
+\def\triggerautostructurelevel
+ {\global\settrue\c_strc_sections_auto_levels}
+
+\def\finalizeautostructurelevels
+ {\ctxcommand{autofinishstructurelevels()}}
+
+\unexpanded\def\finalizeautostructurelevel
+ {\dostoptagged
+ \dostoptagged}
+
+\appendtoks
+ \finalizeautostructurelevels
+\to \everystoptext
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-swd.mkii b/Master/texmf-dist/tex/context/base/strc-swd.mkii
index 4a71b8781b8..1525ab597a1 100644
--- a/Master/texmf-dist/tex/context/base/strc-swd.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-swd.mkii
@@ -5,7 +5,7 @@
%D subtitle=Section Worlds,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-syn.lua b/Master/texmf-dist/tex/context/base/strc-syn.lua
index f3ba97ffca2..c2b5251d08e 100644
--- a/Master/texmf-dist/tex/context/base/strc-syn.lua
+++ b/Master/texmf-dist/tex/context/base/strc-syn.lua
@@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['str-syn'] = {
}
local next, type = next, type
-local texwrite, format = tex.write, string.format
+local format = string.format
local allocate = utilities.storage.allocate
-- interface to tex end
diff --git a/Master/texmf-dist/tex/context/base/strc-syn.mkii b/Master/texmf-dist/tex/context/base/strc-syn.mkii
index 39acb7d91d8..2ba5c94679e 100644
--- a/Master/texmf-dist/tex/context/base/strc-syn.mkii
+++ b/Master/texmf-dist/tex/context/base/strc-syn.mkii
@@ -5,7 +5,7 @@
%D subtitle=Synonyms and Sorts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/strc-syn.mkiv b/Master/texmf-dist/tex/context/base/strc-syn.mkiv
index f063ef087d6..535eab04ba3 100644
--- a/Master/texmf-dist/tex/context/base/strc-syn.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-syn.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Synonyms and Sorting,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -20,8 +20,8 @@
\unprotect
-\let\dotagsynonym\relax
-\let\dotagsorting\relax
+\ifdefined\dotagsynonym \else \let\dotagsynonym\relax \fi
+\ifdefined\dotagsorting \else \let\dotagsorting\relax \fi
% general help, can be shared
@@ -51,35 +51,11 @@
\globallet#3\s!tex
\fi}
-\let\currentsynonym\empty
+\installcorenamespace{synonym}
-\def\synonymparameter #1{\csname\dosynonymparameter{\??sm\currentsynonym}#1\endcsname}
-\def\synonymparameterhash#1{\dosynonymparameterhash {\??sm\currentsynonym}#1}
+\installsimplecommandhandler \??synonym {synonym} \??synonym
-\def\dosynonymparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dosynonymparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\dosynonymparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\dosynonymparentparameterhash\csname#1\s!parent\endcsname#2\fi}
-
-\def\dosynonymparentparameter #1#2{\ifx#1\relax\s!empty\else\dosynonymparameter #1#2\fi}
-\def\dosynonymparentparameterhash#1#2{\ifx#1\relax \else\dosynonymparameterhash#1#2\fi}
-
-\unexpanded\def\dosetsynonymattributes#1#2% style color
- {\edef\fontattributehash {\synonymparameterhash#1}%
- \edef\colorattributehash{\synonymparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-\newtoks\everysetupsynonyms
-
-\unexpanded\def\setupsynonyms
- {\dodoubleargument\dosetupsynonyms}
-
-\def\dosetupsynonyms[#1][#2]%
- {\ifsecondargument
- \getparameters[\??sm#1][#2]%
- \else
- \getparameters[\??sm][#1]%
- \fi
- \the\everysetupsynonyms}
+\let\setupsynonyms\setupsynonym
\setupsynonyms
[\c!state=\v!start,
@@ -106,7 +82,8 @@
{\doquadrupleempty\dodefinesynonyms}
\def\dodefinesynonyms[#1][#2][#3][#4]% name plural \meaning \use
- {\iffourthargument
+ {\edef\currentsynonym{#1}%
+ \iffourthargument
\unexpanded\def#4##1{\doinsertsynonym{#1}{##1}}% name tag
\ifthirdargument
\unexpanded\def#3##1{\doinsertsynonymmeaning{#1}{##1}}% \meaning
@@ -118,10 +95,10 @@
\fi
\setuvalue{#1}{\definesynonym[\v!yes][#1]}% \name
\fi
- \getparameters[\??sm#1][\s!parent=\??sm,\s!single={#1},\s!multi={#2}]%
+ \checksynonymparent
+ \setupcurrentsynonym[\s!single={#1},\s!multi={#2}]%
\presetheadtext[#2=\Word{#2}]% changes the \if...argument
- %\ctxlua{structures.synonyms.define('#1')}%
- \setvalue{\e!setup #2\e!endsetup}{\dodoubleargument\getparameters[\??sm#1]}% to be obsolete
+ \setvalue{\e!setup #2\e!endsetup}{\setupsynonym[#1]}% obsolete definition
\setvalue{\e!place \e!listof#2}{\placelistofsynonyms[#1]}% accepts extra argument
\setvalue{\e!complete\e!listof#2}{\completelistofsynonyms[#1]}}
@@ -158,16 +135,16 @@
\fi
\endgroup}
-\def\registersynonym
+\unexpanded\def\registersynonym
{\dodoubleargument\doregistersynonym}
-\def\registersynonym[#1][#2]%
+\def\doregistersynonym[#1][#2]%
{\ctxlua{structures.synonyms.registerused("#1","#2")}}
\unexpanded\def\doinsertsynonymmeaning#1#2% name tag
{\begingroup
\def\currentsynonym{#1}%
- \dosetsynonymattributes\c!textstyle\c!textcolor
+ \usesynonymstyleandcolor\c!textstyle\c!textcolor
\synonymparameter\c!textcommand{\ctxlua{structures.synonyms.meaning("#1","#2")}}%
\endgroup}
@@ -175,9 +152,9 @@
{\begingroup
\def\currentsynonym{#1}%
\def\currentsynonymtag{#2}%
- \dotagsynonym
\dostarttagged\t!synonym\currentsynonym
- \dosetsynonymattributes\c!synonymstyle\c!synonymcolor
+ \dotagsynonym
+ \usesynonymstyleandcolor\c!synonymstyle\c!synonymcolor
\synonymparameter\c!synonymcommand{\ctxlua{structures.synonyms.synonym("#1","#2")}}%
\dostoptagged
\normalexpanded{\endgroup\synonymparameter\c!next}}
@@ -200,8 +177,6 @@
\c!inbetween=\synonymparameter\c!inbetween,
\c!after=\synonymparameter\c!after,
\c!indentnext=\synonymparameter\c!indentnext,
-% \c!headstyle=\synonymparameter\c!headstyle,
-% \c!headcolor=\synonymparameter\c!headcolor,
\c!headstyle=\synonymparameter\c!textstyle,
\c!headcolor=\synonymparameter\c!textcolor,
\c!style=,
@@ -221,9 +196,10 @@
\def\docompletelistofsynonyms[#1][#2]%
{\edef\currentsynonym{#1}%
- \normalexpanded{\systemsuppliedchapter[#1]{\noexpand\headtext{\synonymparameter\s!multi}}}%
+ \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\synonymparameter\s!multi}},\c!reference=#1]}%
\doplacelistofsynonyms[#1][#2]%
- \page[\v!yes]}
+ \page
+ \stopnamedsection}
\let\startsynonymoutput \relax
\let\stopsynonymoutput \relax
@@ -231,41 +207,13 @@
\let\stopsynonymsection \relax
\unexpanded\def\synonymentry#1#2#3#4%
-% {\syndef{\dosetsynonymattributes\c!textstyle\c!textcolor#2}#3\par}
-% {\startsyndef{#2}#3\stopsyndef}
{\syndef{#3}#4\par}
-
-\let\currentsorting\empty
-
-% we can share if we also have synonymprefix = so
-
-\def\sortingparameter #1{\csname\dosortingparameter{\??so\currentsorting}#1\endcsname}
-\def\sortingparameterhash#1{\dosortingparameterhash {\??so\currentsorting}#1}
-\def\dosortingparameter #1#2{\ifcsname#1#2\endcsname#1#2\else\expandafter\dosortingparentparameter \csname#1\s!parent\endcsname#2\fi}
-\def\dosortingparameterhash#1#2{\ifcsname#1#2\endcsname #1\else\expandafter\dosortingparentparameterhash\csname#1\s!parent\endcsname#2\fi}
+%D Sorting (a simplified version of synonym).
-\def\dosortingparentparameter #1#2{\ifx#1\relax\s!empty\else\dosortingparameter #1#2\fi}
-\def\dosortingparentparameterhash#1#2{\ifx#1\relax \else\dosortingparameterhash#1#2\fi}
+\installcorenamespace{sorting}
-\def\dosetsortingattributes#1#2% style color
- {\edef\fontattributehash {\sortingparameterhash#1}%
- \edef\colorattributehash{\sortingparameterhash#2}%
- \ifx\fontattributehash \empty\else\dosetfontattribute \fontattributehash #1\fi
- \ifx\colorattributehash\empty\else\dosetcolorattribute\colorattributehash#2\fi}
-
-\newtoks\everysetupsorting
-
-\unexpanded\def\setupsorting
- {\dodoubleargument\dosetupsorting}
-
-\def\dosetupsorting[#1][#2]%
- {\ifsecondargument
- \getparameters[\??so#1][#2]%
- \else
- \getparameters[\??so][#1]%
- \fi
- \the\everysetupsorting}
+\installsimplecommandhandler \??sorting {sorting} \??sorting
\setupsorting
[\c!state=\v!start,
@@ -284,7 +232,8 @@
% if #3=\relax or \v!none, then no command but still protected
\def\dodefinesorting[#1][#2][#3]%
- {\ifthirdargument
+ {\edef\currentsorting{#1}%
+ \ifthirdargument
\doifnot{#3}\v!none
{\ifx#3\relax \else
\unexpanded\def#3##1{\doinsertsort{#1}{##1}}%
@@ -293,10 +242,10 @@
\else
\setuvalue{#1}{\definesort[\v!yes][#1]}%
\fi
- \getparameters[\??so#1][\s!parent=\??so,\s!multi={#2}]%
+ \checksortingparent
+ \setupcurrentsorting[\s!multi={#2}]%
\presetheadtext[#2=\Word{#2}]% after \ifthirdargument -)
- %\ctxlua{structures.synonyms.define('#1')}%
- \setvalue{\e!setup #2\e!endsetup}{\dodoubleargument\getparameters[\??so#1]}% to be obsolete
+ \setvalue{\e!setup #2\e!endsetup}{\setupsorting[#1]}% obsolete definition
\setvalue{\e!place \e!listof#2}{\placelistofsorts[#1]}%
\setvalue{\e!complete\e!listof#2}{\completelistofsorts[#1]}}
@@ -336,17 +285,17 @@
% no kap currently, of .. we need to map cap onto WORD
\edef\currentsorting{#1}%
\def\currentsortingtag{#2}%
- \dotagsorting
\dostarttagged\t!sorting\currentsorting
- \dosetsortingattributes\c!style\c!color
+ \dotagsorting
+ \usesortingstyleandcolor\c!style\c!color
\ctxlua{structures.synonyms.synonym("#1","#2")}%
\dostoptagged
\normalexpanded{\endgroup\sortingparameter\c!next}}
-\def\registersort
+\unexpanded\def\registersort
{\dodoubleargument\doregistersort}
-\def\registersort[#1][#2]%
+\def\doregistersort[#1][#2]%
{\ctxlua{structures.synonyms.registerused("#1","#2")}}
% before after
@@ -359,7 +308,7 @@
\def\doplacelistofsorts[#1][#2]% NOG EEN RUWE VERSIE MAKEN ZONDER WITRUIMTE ETC ETC
{\begingroup
\def\currentsorting{#1}%
- \getparameters[\??so#1][#2]%
+ \setupcurrentsorting[#2]%
\startpacked
\ctxlua{structures.synonyms.process('#1',{
criterium = "\sortingparameter\c!criterium",
@@ -373,9 +322,11 @@
{\dodoubleempty\docompletelistofsorts}
\def\docompletelistofsorts[#1][#2]%
- {\normalexpanded{\systemsuppliedchapter[#1]{\noexpand\headtext{#2}}}%
+ {\edef\currentsorting{#1}%
+ \normalexpanded{\startnamedsection[\v!chapter][\c!title={\headtext{\sortingparameter\s!multi}},\c!reference=#1]}%
\doplacelistofsorts[#1][#2]%
- \page[\v!yes]}
+ \page
+ \stopnamedsection}
\let\startsortingoutput \relax
\let\stopsortingoutput \relax
@@ -384,42 +335,8 @@
\def\sortingentry#1#2#3#4% #4 is meaning but empty here
{\doifelsenothing{\sortingparameter\c!command}
- {\begingroup\dosetsortingattributes\c!style\c!color#3\endgroup\par} % todo
+ {\begingroup\usesortingstyleandcolor\c!style\c!color#3\endgroup\par} % todo
{\sortingparameter\c!command{#1}{#2}{#3}}}
-
-%D Here we define a support macro that can sort simple comma
-%D separated lists. It's a multi-list variant of a prototype
-%D written by Taco.
-
-% \def\mkloadsortedlist#1% class
-% {\bgroup
-% \getvalue{\s!set#1}%
-% \ctxlua{structures.synonyms.process('#1')}%
-% \getvalue{\s!reset#1}%
-% \egroup}
-
-% \def\processlistofsorts[#1]%
-% {\mkloadsortedlist{#1}}
-
-% \newcounter\nofsortedalphalists
-
-% \def\sortalphacommacommand#1%
-% {\begingroup
-% \doglobal\increment\nofsortedalphalists
-% \edef\currentsortedalphalist{alpha:\nofsortedalphalists}%
-% \definesorting[\currentsortedalphalist][\currentsortedalphalist]%
-% \processcommacommand[#1]{\getvalue\currentsortedalphalist}%
-% \global\let\sortedcommalist\empty
-% \def\makesortedlist##1{\doglobal\appendtocommalist{##1}\sortedcommalist}%
-% \setupsorting[\currentsortedalphalist][\c!criterium=\v!all,\c!command=\makesortedlist]%
-% \processlistofsorts[\currentsortedalphalist]%
-% \endgroup
-% \dodoglobal\let#1\sortedcommalist}
-
-% \starttext
-% \def\whatever{a,b,q,d,r,f} \sortalphacommacommand\whatever \whatever \endgraf
-% \def\whatever{ax,bx,qx,dx,rx,fx} \sortalphacommacommand\whatever \whatever \endgraf
-% \stoptext
%D Presets.
@@ -435,19 +352,6 @@
\definesorting
[\v!logo]
[\v!logos]
- % no [\logogram]
-
-\definesynonyms
- [\v!unit]
- [\v!units]
- [\unitmeaning]
-
-% \setupsynonyms
-% [\v!unit]
-% [\c!textstyle=\dimension]
-
-\setupsynonyms
- [\v!unit]
- [\c!synonymcommand=\dimension]
+% [\logogram] % no
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/strc-tag.lua b/Master/texmf-dist/tex/context/base/strc-tag.lua
index f1381dad5f0..78b8074878f 100644
--- a/Master/texmf-dist/tex/context/base/strc-tag.lua
+++ b/Master/texmf-dist/tex/context/base/strc-tag.lua
@@ -26,27 +26,31 @@ local a_tagged = attributes.private('tagged')
local unsetvalue = attributes.unsetvalue
local codeinjections = backends.codeinjections
-local taglist = allocate()
-local properties = allocate()
-local labels = allocate()
-local stack = { }
-local chain = { }
-local ids = { }
-local enabled = false
-local tagdata = { } -- used in export
-
-local tags = structures.tags
-tags.taglist = taglist -- can best be hidden
-tags.labels = labels
-tags.data = tagdata
-
-local properties = allocate {
+local taglist = allocate()
+local properties = allocate()
+local labels = allocate()
+local stack = { }
+local chain = { }
+local ids = { }
+local enabled = false
+local tagdata = { } -- used in export
+local tagmetadata = { } -- used in export
+
+local tags = structures.tags
+tags.taglist = taglist -- can best be hidden
+tags.labels = labels
+tags.data = tagdata
+tags.metadata = tagmetadata
+
+local properties = allocate {
document = { pdf = "Div", nature = "display" },
division = { pdf = "Div", nature = "display" },
paragraph = { pdf = "P", nature = "mixed" },
+ p = { pdf = "P", nature = "mixed" },
construct = { pdf = "Span", nature = "inline" },
+ highlight = { pdf = "Span", nature = "inline" },
section = { pdf = "Sect", nature = "display" },
sectiontitle = { pdf = "H", nature = "mixed" },
@@ -64,12 +68,15 @@ local properties = allocate {
descriptionsymbol = { pdf = "Span", nature = "inline" }, -- note reference
verbatimblock = { pdf = "Code", nature = "display" },
- verbatimlines = { pdf = "Code", nature = "display" },
+ verbatimlines = { pdf = "Code", nature = "display" },
verbatimline = { pdf = "Code", nature = "mixed" },
verbatim = { pdf = "Code", nature = "inline" },
+ lines = { pdf = "Code", nature = "display" },
+ line = { pdf = "Code", nature = "mixed" },
+
synonym = { pdf = "Span", nature = "inline" },
- sort = { pdf = "Span", nature = "inline" },
+ sorting = { pdf = "Span", nature = "inline" },
register = { pdf = "Div", nature = "display" },
registersection = { pdf = "Div", nature = "display" },
@@ -84,6 +91,7 @@ local properties = allocate {
table = { pdf = "Table", nature = "display" },
tablerow = { pdf = "TR", nature = "display" },
tablecell = { pdf = "TD", nature = "mixed" },
+
tabulate = { pdf = "Table", nature = "display" },
tabulaterow = { pdf = "TR", nature = "display" },
tabulatecell = { pdf = "TD", nature = "mixed" },
@@ -99,9 +107,13 @@ local properties = allocate {
delimited = { pdf = "Quote", nature = "inline" },
subsentence = { pdf = "Span", nature = "inline" },
+ label = { pdf = "Span", nature = "mixed" },
+ number = { pdf = "Span", nature = "mixed" },
+
float = { pdf = "Div", nature = "display" }, -- Figure
- floatcaption = { pdf = "Caption", nature = "display" },
- floattag = { pdf = "Span", nature = "mixed" },
+ floatcaption = { pdf = "Caption", nature = "mixed" },
+ floatlabel = { pdf = "Span", nature = "inline" },
+ floatnumber = { pdf = "Span", nature = "inline" },
floattext = { pdf = "Span", nature = "mixed" },
floatcontent = { pdf = "P", nature = "mixed" },
@@ -110,7 +122,9 @@ local properties = allocate {
formulaset = { pdf = "Div", nature = "display" },
formula = { pdf = "Div", nature = "display" }, -- Formula
- formulatag = { pdf = "Span", nature = "mixed" },
+ formulacaption = { pdf = "Span", nature = "mixed" },
+ formulalabel = { pdf = "Span", nature = "mixed" },
+ formulanumber = { pdf = "Span", nature = "mixed" },
formulacontent = { pdf = "P", nature = "display" },
subformula = { pdf = "Div", nature = "display" },
@@ -119,7 +133,7 @@ local properties = allocate {
margintextblock = { pdf = "Span", nature = "inline" },
margintext = { pdf = "Span", nature = "inline" },
- math = { pdf = "Div", nature = "display" },
+ math = { pdf = "Div", nature = "inline" }, -- no display
mn = { pdf = "Span", nature = "mixed" },
mi = { pdf = "Span", nature = "mixed" },
mo = { pdf = "Span", nature = "mixed" },
@@ -136,12 +150,61 @@ local properties = allocate {
mfrac = { pdf = "Span", nature = "display" },
mroot = { pdf = "Span", nature = "display" },
msqrt = { pdf = "Span", nature = "display" },
+ mfenced = { pdf = "Span", nature = "display" },
+ maction = { pdf = "Span", nature = "display" },
+
+ mtable = { pdf = "Table", nature = "display" }, -- might change
+ mtr = { pdf = "TR", nature = "display" }, -- might change
+ mtd = { pdf = "TD", nature = "display" }, -- might change
+
+ ignore = { pdf = "Span", nature = "mixed" },
+ metadata = { pdf = "Div", nature = "display" },
+ metavariable = { pdf = "Span", nature = "mixed" },
+
+ sub = { pdf = "Span", nature = "inline" },
+ sup = { pdf = "Span", nature = "inline" },
+ subsup = { pdf = "Span", nature = "inline" },
+ combination = { pdf = "Span", nature = "display" },
+ combinationpair = { pdf = "Span", nature = "display" },
+ combinationcontent = { pdf = "Span", nature = "mixed" },
+ combinationcaption = { pdf = "Span", nature = "mixed" },
}
+function tags.detailedtag(tag,detail,attribute)
+ if not attribute then
+ attribute = texattribute[a_tagged]
+ end
+ if attribute >= 0 then
+ local tl = taglist[attribute]
+ if tl then
+ local pattern
+ if detail and detail ~= "" then
+ pattern = "^" .. tag .. ":".. detail .. "%-"
+ else
+ pattern = "^" .. tag .. "%-"
+ end
+ for i=#tl,1,-1 do
+ local tli = tl[i]
+ if find(tli,pattern) then
+ return tli
+ end
+ end
+ end
+ else
+ -- enabled but not auto
+ end
+ return false -- handy as bogus index
+end
+
tags.properties = properties
-function tags.settagproperty(tag,key,value)
+local lasttags = { }
+local userdata = { }
+
+tags.userdata = userdata
+
+function tags.setproperty(tag,key,value)
local p = properties[tag]
if p then
p[key] = value
@@ -150,10 +213,25 @@ function tags.settagproperty(tag,key,value)
end
end
-local lasttags = { }
-local userdata = { }
+function tags.registerdata(data)
+ local fulltag = chain[nstack]
+ if fulltag then
+ tagdata[fulltag] = data
+ end
+end
-tags.userdata = userdata
+local metadata
+
+function tags.registermetadata(data)
+ local d = settings_to_hash(data)
+ if metadata then
+ table.merge(metadata,d)
+ else
+ metadata = d
+ end
+end
+
+local nstack = 0
function tags.start(tag,specification)
local label, detail, user
@@ -164,40 +242,65 @@ function tags.start(tag,specification)
codeinjections.enabletags()
enabled = true
end
- labels[tag] = label ~= "" and label or tag
- local fulltag
+ --
+--~ labels[tag] = label ~= "" and label or tag
+--~ local fulltag
+--~ if detail and detail ~= "" then
+--~ fulltag = tag .. ":" .. detail
+--~ else
+--~ fulltag = tag
+--~ end
+ --
+ local fulltag = label ~= "" and label or tag
+ labels[tag] = fulltag
if detail and detail ~= "" then
- fulltag = tag .. ":" .. detail
- else
- fulltag = tag
+ fulltag = fulltag .. ":" .. detail
end
+ --
local t = #taglist + 1
local n = (ids[fulltag] or 0) + 1
ids[fulltag] = n
lasttags[tag] = n
---~ print("SETTING",tag,n)
local completetag = fulltag .. "-" .. n
- chain[#chain+1] = completetag -- insert(chain,tag .. ":" .. n)
- stack[#stack+1] = t -- insert(stack,t)
- taglist[t] = { unpack(chain) } -- we can add key values for alt and actualtext if needed
+ nstack = nstack + 1
+ chain[nstack] = completetag
+ stack[nstack] = t
+ -- a copy as we can add key values for alt and actualtext if needed:
+ taglist[t] = { unpack(chain,1,nstack) }
+ --
if user and user ~= "" then
-- maybe we should merge this into taglist or whatever ... anyway there is room to optimize
-- taglist.userdata = settings_to_hash(user)
userdata[completetag] = settings_to_hash(user)
end
+ if metadata then
+ tagmetadata[completetag] = metadata
+ metadata = nil
+ end
+ texattribute[a_tagged] = t
+ return t
+end
+
+function tags.restart(completetag)
+ local t = #taglist + 1
+ nstack = nstack + 1
+ chain[nstack] = completetag
+ stack[nstack] = t
+ taglist[t] = { unpack(chain,1,nstack) }
texattribute[a_tagged] = t
return t
end
function tags.stop()
- local t = stack[#stack] stack[#stack] = nil -- local t = remove(stack)
+ if nstack > 0 then
+ nstack = nstack -1
+ end
+ local t = stack[nstack]
if not t then
if trace_tags then
- report_tags("ignoring end tag, previous chain: %s",#chain > 0 and concat(chain[#chain]) or "none")
+ report_tags("ignoring end tag, previous chain: %s",nstack > 0 and concat(chain[nstack],"",1,nstack) or "none")
end
t = unsetvalue
- else
- chain[#chain] = nil -- remove(chain)
end
texattribute[a_tagged] = t
return t
@@ -216,14 +319,7 @@ function tags.last(tag)
end
function tags.lastinchain()
- return chain[#chain]
-end
-
-function tags.registerdata(data)
- local fulltag = chain[#chain]
- if fulltag then
- tagdata[fulltag] = data
- end
+ return chain[nstack]
end
function structures.atlocation(str)
@@ -237,9 +333,11 @@ end
statistics.register("structure elements", function()
if enabled then
- return format("%s element chains identified",#taglist)
- else
- return nil
+ if nstack > 0 then
+ return format("%s element chains identified, open chain: %s ",#taglist,concat(chain," => ",1,nstack))
+ else
+ return format("%s element chains identified",#taglist)
+ end
end
end)
@@ -249,3 +347,7 @@ directives.register("backend.addtags", function(v)
enabled = true
end
end)
+
+commands.starttag = tags.start
+commands.stoptag = tags.stop
+commands.settagproperty = tags.setproperty
diff --git a/Master/texmf-dist/tex/context/base/strc-tag.mkiv b/Master/texmf-dist/tex/context/base/strc-tag.mkiv
index 8bc8d9f6979..84d6fb2d377 100644
--- a/Master/texmf-dist/tex/context/base/strc-tag.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-tag.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Tags,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -19,85 +19,125 @@
\unprotect
-% labels: temporary here
-
-\def\t!document {document} % Div
-
-\def\t!division {division} % Div
-\def\t!paragraph {paragraph} % P
-\def\t!construct {construct} % Span
-
-\def\t!section {section} % Sect
-\def\t!sectiontitle {sectiontitle} % H
-\def\t!sectionnumber {sectionnumber} % H
-\def\t!sectioncontent {sectioncontent} % Div
-
-\def\t!itemgroup {itemgroup} % L
-\def\t!item {item} % Li
-\def\t!itemtag {itemtag} % Lbl
-\def\t!itemcontent {itemcontent} % LBody
-
-\def\t!description {description} % Li
-\def\t!descriptiontag {descriptiontag} % Lbl
-\def\t!descriptioncontent{descriptioncontent} % LBody
-\def\t!descriptionsymbol {descriptionsymbol} % Span
-
-\def\t!verbatimblock {verbatimblock} % Code
-\def\t!verbatimlines {verbatimlines} % Code
-\def\t!verbatimline {verbatimline} % Code
-\def\t!verbatim {verbatim} % Code
-
-\def\t!sorting {sorting} % Span
-\def\t!synonym {synonym} % Span
-
-\def\t!register {register} % Div
-\def\t!registersection {registersection} % Div
-\def\t!registertag {registertag} % Span
-\def\t!registerentries {registerentries} % Div
-\def\t!registerentry {registerentry} % Span
-\def\t!registersee {registersee} % Span
-\def\t!registerpages {registerpages} % Span
-\def\t!registerpage {registerpage} % Span
-\def\t!registerpagerange {registerpagerange} % Span
-
-\def\t!table {table} % Table
-\def\t!tablerow {tablerow} % TR
-\def\t!tablecell {tablecell} % TD
-\def\t!tabulate {tabulate} % Table
-\def\t!tabulaterow {tabulaterow} % TR
-\def\t!tabulatecell {tabulatecell} % TD
-
-\def\t!list {list} % TOC
-\def\t!listitem {listitem} % TOCI
-\def\t!listtag {listtag} % Lbl
-\def\t!listcontent {listcontent} % P
-\def\t!listdata {listdata} % P
-\def\t!listpage {listpage} % Reference
-
-\def\t!delimitedblock {delimited} % BlockQuote
-\def\t!delimited {delimited} % Quote
-\def\t!subsentence {subsentence} % Span
-
-\def\t!float {float} % Div
-\def\t!floatcaption {floatcaption} % Caption
-\def\t!floattag {floattag} % Span
-\def\t!floattext {floattext} % Span
-\def\t!floatcontent {floatcontent} % P
-
-\def\t!image {image} % P
-
-\def\t!mpgraphic {mpgraphic} % P
-
-\def\t!formulaset {formulaset} % Div
-\def\t!formula {formula} % Div
-\def\t!formulatag {formulatag} % Span
-\def\t!formulacontent {formulacontent} % P
-\def\t!subformula {subformula} % Div
-
-\def\t!link {link} % Link
-
-\def\t!margintext {margintext} % Span
-\def\t!margintextblock {margintextblock} % Div
+%D Eventually these labels will either move to the modules
+%D where they're used, or they will en dup in mult-tag.
+
+\def\t!document {document} % Div
+
+\def\t!division {division} % Div
+\def\t!paragraph {paragraph} % P
+\def\t!p {p} % P
+\def\t!construct {construct} % Span
+\def\t!highlight {highlight} % Span
+
+\def\t!section {section} % Sect
+\def\t!sectiontitle {sectiontitle} % H
+\def\t!sectionnumber {sectionnumber} % H
+\def\t!sectioncontent {sectioncontent} % Div
+
+\def\t!itemgroup {itemgroup} % L
+\def\t!item {item} % Li
+\def\t!itemtag {itemtag} % Lbl
+\def\t!itemcontent {itemcontent} % LBody
+
+\def\t!description {description} % Li
+\def\t!descriptiontag {descriptiontag} % Lbl
+\def\t!descriptioncontent {descriptioncontent} % LBody
+\def\t!descriptionsymbol {descriptionsymbol} % Span
+
+\let\t!construction \t!description
+\let\t!constructiontag \t!descriptiontag
+\let\t!constructioncontent\t!descriptioncontent
+\let\t!constructionsymbol \t!descriptionsymbol
+
+\def\t!verbatimblock {verbatimblock} % Code
+\def\t!verbatimlines {verbatimlines} % Code
+\def\t!verbatimline {verbatimline} % Code
+\def\t!verbatim {verbatim} % Code
+
+\def\t!lines {lines} % Code
+\def\t!line {line} % Code
+
+\def\t!sorting {sorting} % Span
+\def\t!synonym {synonym} % Span
+
+\def\t!register {register} % Div
+\def\t!registersection {registersection} % Div
+\def\t!registertag {registertag} % Span
+\def\t!registerentries {registerentries} % Div
+\def\t!registerentry {registerentry} % Span
+\def\t!registersee {registersee} % Span
+\def\t!registerpages {registerpages} % Span
+\def\t!registerpage {registerpage} % Span
+\def\t!registerpagerange {registerpagerange} % Span
+
+\def\t!table {table} % Table
+\def\t!tablerow {tablerow} % TR
+\def\t!tablecell {tablecell} % TD
+\def\t!tabulate {tabulate} % Table
+\def\t!tabulaterow {tabulaterow} % TR
+\def\t!tabulatecell {tabulatecell} % TD
+
+\def\t!math {math} % math
+\def\t!mathtable {mtable} % Table
+\def\t!mathtablerow {mtr} % TR
+\def\t!mathtablecell {mtd} % TD
+\def\t!mathaction {maction} %
+
+\def\t!list {list} % TOC
+\def\t!listitem {listitem} % TOCI
+\def\t!listtag {listtag} % Lbl
+\def\t!listcontent {listcontent} % P
+\def\t!listdata {listdata} % P
+\def\t!listpage {listpage} % Reference
+
+\def\t!delimitedblock {delimited} % BlockQuote
+\def\t!delimited {delimited} % Quote
+\def\t!subsentence {subsentence} % Span
+
+\def\t!float {float} % Div
+\def\t!floatcaption {floatcaption} % Caption
+\def\t!floatlabel {floatlabel} % Span
+\def\t!floattext {floattext} % Span
+\def\t!floatnumber {floatnumber} % Span
+\def\t!floatcontent {floatcontent} % P
+
+\def\t!image {image} % P
+
+\def\t!mpgraphic {mpgraphic} % P
+
+\def\t!formulaset {formulaset} % Div
+\def\t!formula {formula} % Div
+\def\t!formulacaption {formulacaption} % Span
+\def\t!formulalabel {formulalabel} % Span
+\def\t!formulanumber {formulanumber} % P
+\def\t!formulacontent {formulacontent} % P
+\def\t!subformula {subformula} % Div
+
+\def\t!link {link} % Link
+
+\def\t!margintext {margintext} % Span
+\def\t!margintextblock {margintextblock} % Div
+
+% we might opt for verbose variants so this is experimental:
+
+\def\t!label {label} % Span
+\def\t!number {number} % Span
+
+\def\t!ignore {ignore} % Span
+
+\def\t!sub {sub} % Span
+\def\t!sup {sup} % Span
+\def\t!subsup {subsup} % Span
+
+\def\t!unit {unit} % Span
+\def\t!quantity {quantity} % Span
+\def\t!number {number} % Span
+
+\def\t!combination {combination} % Span
+\def\t!combinationpair {combinationpair} % Span
+\def\t!combinationcontent {combinationcontent} % Span
+\def\t!combinationcaption {combinationcaption} % Span
% \setuptaglabeltext
% [en]
@@ -108,90 +148,110 @@
\definesystemattribute[tagged][public]
\definesystemattribute[image] [public]
-\def\setelementbackendtag{\dodoubleargument\dosetelementbackendtag}
-\def\setelementnature {\dodoubleargument\dosetelementnature}
+\unexpanded\def\setelementbackendtag{\dodoubleargument\strc_tags_set_backend}
+\unexpanded\def\setelementnature {\dodoubleargument\strc_tags_set_nature}
-\def\dosetelementbackendtag[#1][#2]{\ctxlua{structures.tags.settagproperty("#1","backend","#2")}}
-\def\dosetelementnature [#1][#2]{\ctxlua{structures.tags.settagproperty("#1","nature", "#2")}}
+\def\strc_tags_set_backend[#1][#2]{\ctxcommand{settagproperty("#1","backend","#2")}}
+\def\strc_tags_set_nature [#1][#2]{\ctxcommand{settagproperty("#1","nature", "#2")}}
-% todo: indirect macro for trialtypesetting
+\installcorenamespace{tagging}
-\unexpanded\def\dostartelement{\iftrialtypesetting\expandafter\renostartelement\else\expandafter\redostartelement\fi}
-\unexpanded\def\dostopelement {\iftrialtypesetting\expandafter\nonostopelement \else\expandafter\dodostopelement \fi}
+\installsetuponlycommandhandler \??tagging {tagging}
-\unexpanded\def\redostartelement{\dodoubleempty\dodostartelement}
-\unexpanded\def\renostartelement{\dodoubleempty\nonostartelement}
+\unexpanded\def\strc_tags_element_start_yes{\dodoubleempty\strc_tags_element_start_yes_indeed}
+\unexpanded\def\strc_tags_element_start_nop{\dodoubleempty\strc_tags_element_start_nop_indeed}
-\unexpanded\def\dodostartelement[#1][#2]%
- {\ctxlua{structures.tags.start("#1",{
- label = "\dogetupsometaglabeltext{#1}",
- userdata = \!!bs#2\!!es,
- })}}
+\unexpanded\def\strc_tags_element_start_yes_indeed
+ {\iftrialtypesetting
+ \expandafter\strc_tags_element_start_nop_indeed
+ \else
+ \expandafter\strc_tags_element_start_yes_indeed_yes
+ \fi}
-\unexpanded\def\dodostopelement
- {\ctxlua{structures.tags.stop()}}
+\unexpanded\def\strc_tags_element_stop
+ {\iftrialtypesetting
+ \expandafter\strc_tags_element_stop_nop
+ \else
+ \expandafter\strc_tags_element_stop_yes
+ \fi}
-\unexpanded\def\nonostartelement[#1][#2]{}
-\unexpanded\def\nonostopelement {}
+\unexpanded\def\strc_tags_element_start_yes_indeed_yes[#1][#2]%
+ {\ctxcommand{starttag("#1",{label="\dogetupsometaglabeltext{#1}",userdata=\!!bs#2\!!es})}}
-% beware: making this one unexpanded spoils tables (noalign problem)
+\unexpanded\def\strc_tags_element_stop_yes
+ {\ctxcommand{stoptag()}}
-\def\dodostarttagged{\iftrialtypesetting\expandafter\nododostarttagged\else\expandafter\dododostarttagged\fi}
-\def\dodostoptagged {\iftrialtypesetting\expandafter\nododostoptagged \else\expandafter\dododostoptagged \fi}
+\unexpanded\def\strc_tags_element_start_nop_indeed[#1][#2]%
+ {}
-\def\dododostarttagged#1#2%
- {\ctxlua{structures.tags.start("#1",{
- label = "\dogetupsometaglabeltext{#1}",
- detail = "#2",
- })}}
+\unexpanded\def\strc_tags_element_stop_nop
+ {}
-\def\dododostoptagged
- {\ctxlua{structures.tags.stop()}}
+\unexpanded\def\strc_tags_enable_elements
+ {\setuplanguage[\s!default][\s!righthyphenchar="AD]% for the moment here
+ \let\startelement\strc_tags_element_start_yes
+ \let\stopelement \strc_tags_element_stop_yes}
-\def\nododostarttagged#1#2{}
-\def\nododostoptagged {}
+\unexpanded\def\strc_tags_disable_elements
+ {\let\startelement\strc_tags_element_start_nop
+ \let\stopelement \strc_tags_element_stop_nop}
-\newtoks\everysetupstructure
+% beware: making these unexpanded spoils tables (noalign problem)
-\def\setupstructure[#1]%
- {\getparameters[\??el][#1]%
- \the\everysetupstructure}
+\def\strc_tags_enabled_start
+ {\iftrialtypesetting
+ \expandafter\strc_tags_start_nop
+ \else
+ \expandafter\strc_tags_start_yes
+ \fi}
-\def\doenableelements
- {\setuplanguage[\s!default][\s!righthyphenchar="AD]% for the moment here
- \let\startelement\dostartelement
- \let\stopelement \dostopelement}
+\def\strc_tags_enabled_stop
+ {\iftrialtypesetting
+ \expandafter\strc_tags_stop_nop
+ \else
+ \expandafter\strc_tags_stop_yes
+ \fi}
+
+\def\strc_tags_start_yes#1#2% we could have a fast labeltext resolver
+ {\ctxcommand{starttag("#1",{label="\dogetupsometaglabeltext{#1}",detail="#2"})}}
+
+\def\strc_tags_stop_yes
+ {\ctxcommand{stoptag()}}
+
+\def\strc_tags_start_nop#1#2%
+ {}
-\def\dodisableelements
- {\let\startelement\renostartelement
- \let\stopelement \nonostopelement}
+\def\strc_tags_stop_nop
+ {}
-\def\doenabletagged
- {\let\dostarttagged\dodostarttagged
- \let\dostoptagged \dodostoptagged }
+\unexpanded\def\strc_tags_enable
+ {\let\dostarttagged\strc_tags_start_yes
+ \let\dostoptagged \strc_tags_stop_yes}
-\def\dodisabletagged
- {\let\dostarttagged\nododostarttagged
- \let\dostoptagged \nododostoptagged }
+\unexpanded\def\strc_tags_disable
+ {\let\dostarttagged\strc_tags_start_nop
+ \let\dostoptagged \strc_tags_stop_nop}
+
+%D The triggers:
\newtoks\everyenableelements
\newtoks\everydisableelements
\appendtoks
- \doenableelements
- \doifelse\@@elmethod\v!auto\doenabletagged\dodisabletagged
+ \strc_tags_enable_elements
+ \doifelse{\taggingparameter\c!method}\v!auto\strc_tags_enable\strc_tags_disable
\to \everyenableelements
\appendtoks
- \dodisableelements
- \dodisabletagged
+ \strc_tags_disable_elements
+ \strc_tags_disable
\to \everydisableelements
\appendtoks
- \doifelse\@@elstate\v!start{\the\everyenableelements}{\the\everydisableelements}%
-\to \everysetupstructure
+ \doifelse{\taggingparameter\c!state}\v!start{\the\everyenableelements}{\the\everydisableelements}%
+\to \everysetuptagging
-\setupstructure
+\setuptagging
[\c!state=\v!stop,
\c!method=\v!auto]
@@ -199,9 +259,13 @@
{\dostarttagged\t!paragraph\empty}
\unexpanded\def\stopparagraph
- {\dostoptagged
+ {% \removeunwantedspaces % yes or no
+ \dostoptagged
\par}
+\let\startpar\startparagraph
+\let\stoppar \stopparagraph
+
\appendtoks
\dostarttagged\t!document\empty
\to \everystarttext
@@ -210,11 +274,62 @@
\dostoptagged
\to \everystoptext
+\appendtoks
+ \strc_tags_disable_elements
+ \strc_tags_disable
+\to \everybeforepagebody
+
% \doifinelementelse{structure:section} {yes} {no}
% \doifinelementelse{structure:chapter} {yes} {no}
% \doifinelementelse{division:*-structure:chapter} {yes} {no}
-\def\doifinelementelse#1%
+\unexpanded\def\doifinelementelse#1%
{\ctxcommand{testcase(structures.atlocation("#1"))}}
+\unexpanded\def\taggedlabeltexts#1#2#3% experimental: label, numberdetail, numbercontent
+ {\begingroup
+ \dostarttagged\t!label{#1}%
+ \labeltexts{#1}%
+ {\dostoptagged
+ \dostarttagged\t!number{#2}%
+ #3%
+ \dostoptagged
+ \dostarttagged\t!label{#1}}%
+ \dostoptagged
+ \endgroup}
+
+\unexpanded\def\namedtaggedlabeltexts#1#2#3#4#5% experimental: labeltag label numbertag numberdetail numbercontent
+ {\begingroup
+ \dostarttagged{#1}{#2}%
+ \labeltexts{#2}%
+ {\dostoptagged
+ \dostarttagged{#3}{#4}%
+ #5%
+ \dostoptagged
+ \dostarttagged{#1}{#2}}%
+ \dostoptagged
+ \endgroup}
+
+%D Metadata is added after the following structure element so
+%D here we get some as child of the document root and some as child
+%D of the chapter element.
+%D
+%D \settaggedmetadata[title=Hello World!,author=Hans Hagen]
+%D
+%D \starttyping
+%D \starttext
+%D \startelement[ignore]
+%D \input tufte
+%D \stopelement
+%D \par \input ward \par
+%D \settaggedmetadata[whatever=Again and Again]
+%D \startchapter[title=test]
+%D \input ward
+%D \stopchapter
+%D \stoptext
+%D \stoptyping
+
+\unexpanded\def\settaggedmetadata[#1]%
+ {\ctxlua{structures.tags.registermetadata(\!!bs#1\!!es)}}
+
\protect
diff --git a/Master/texmf-dist/tex/context/base/strc-xml.mkiv b/Master/texmf-dist/tex/context/base/strc-xml.mkiv
index 9696c2e06c2..3f9b4ef811d 100644
--- a/Master/texmf-dist/tex/context/base/strc-xml.mkiv
+++ b/Master/texmf-dist/tex/context/base/strc-xml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=XML Processing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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
@@ -62,7 +62,7 @@
% test.tex
-\setupstructurehead[chapter][expansion=xml]
+\setuphead[chapter][expansion=xml]
\startxmlsetups xml:demo:define:base
\xmlsetsetup{demo}{document|section|p|b|i}{xml:demo:*}
diff --git a/Master/texmf-dist/tex/context/base/supp-ali.mkii b/Master/texmf-dist/tex/context/base/supp-ali.mkii
index 8727efbb271..c4a1aadc526 100644
--- a/Master/texmf-dist/tex/context/base/supp-ali.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-ali.mkii
@@ -5,7 +5,7 @@
%D subtitle=Alignment,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-ali.mkiv b/Master/texmf-dist/tex/context/base/supp-ali.mkiv
index 1bd31eb78a2..54a7b77e4f2 100644
--- a/Master/texmf-dist/tex/context/base/supp-ali.mkiv
+++ b/Master/texmf-dist/tex/context/base/supp-ali.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Alignment,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-box.lua b/Master/texmf-dist/tex/context/base/supp-box.lua
index 48baecf6fc2..853de4cbefc 100644
--- a/Master/texmf-dist/tex/context/base/supp-box.lua
+++ b/Master/texmf-dist/tex/context/base/supp-box.lua
@@ -47,7 +47,7 @@ end
commands.hyphenatedlist = hyphenatedlist
function commands.showhyphenatedinlist(list)
- report_hyphenation("show: %s",nodes.listtoutf(list))
+ report_hyphenation("show: %s",nodes.listtoutf(list,false,true))
end
local function checkedlist(list)
diff --git a/Master/texmf-dist/tex/context/base/supp-box.mkii b/Master/texmf-dist/tex/context/base/supp-box.mkii
index 8cdea862090..55641fd6336 100644
--- a/Master/texmf-dist/tex/context/base/supp-box.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-box.mkii
@@ -5,7 +5,7 @@
%D subtitle=Boxes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-box.mkiv b/Master/texmf-dist/tex/context/base/supp-box.mkiv
index f449e1d76b4..de1da677a88 100644
--- a/Master/texmf-dist/tex/context/base/supp-box.mkiv
+++ b/Master/texmf-dist/tex/context/base/supp-box.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Boxes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,6 +17,51 @@
\registerctxluafile{supp-box}{1.001}
+% This file is partially cleaned up.
+
+% handy to have
+%
+% \hbox to \hsize
+% {\en
+% \switchnaarkorps[5pt]%
+% \emergencystretch2em
+% \dimen0=\baselineskip
+% \baselineskip=\dimen0 plus 1pt
+% \hsize=.2\hsize
+% \vsize=2\hsize
+% \ruledvbox to \vsize{\input tufte \par}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern-\prevdepth}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern0pt}\hss
+% \ruledvbox to \vsize{\input tufte \par\vfill}\hss
+% \ruledvbox to \vsize{\input tufte \par\kern-\prevdepth\vfill}}
+%
+% \hbox to \hsize
+% {\en
+% \switchnaarkorps[5pt]%
+% \emergencystretch2em
+% \dimen0=\baselineskip
+% \baselineskip=\dimen0 plus 1pt
+% \hsize=.18\hsize
+% \vsize=2.5\hsize
+% \setbox0=\vbox{\input tufte\relax}%
+% \ruledvbox to \vsize{\unvcopy0}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern-\dp0}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern0pt}\hss
+% \ruledvbox to \vsize{\unvcopy0\vfill}\hss
+% \ruledvbox to \vsize{\unvcopy0\kern-\dp0\vfill}}
+
+%D \macros
+%D {dontcomplain}
+%D
+%D The next macro suppresses over- and underfull messages which
+%D often makes sense when we deal with boxes.
+
+\unexpanded\def\dontcomplain
+ {\hbadness\plustenthousand
+ \vbadness\plustenthousand
+ \hfuzz \maxdimen
+ \vfuzz \maxdimen}
+
%D This module implements some box manipulation macros. Some
%D are quite simple, some are more advanced and when understood
%D well, all can be of use.
@@ -35,12 +80,13 @@
\def\strutwd{\wd\strutbox}
%D \macros
-%D {resetbox, emptybox}
+%D {voidbox,nextbox}
%D
%D Let's start with an easy one. The next macro hides the
%D ugly \type {@} in \type {\voidb@x}.
-\ifx\voidbox\undefined \newbox\voidbox \fi
+\ifdefined\voidbox \else \newbox\voidbox \fi
+\ifdefined\nextbox \else \newbox\nextbox \fi
%D \macros
%D {nextdepth}
@@ -59,13 +105,15 @@
%D reducing the dimensions of a box to zero. The most resolute
%D one is presented first.
-\def\smashbox#1%
+\unexpanded\def\smashbox#1%
{\wd#1\zeropoint
\ht#1\zeropoint
\dp#1\zeropoint}
-\def\smashboxed#1%
- {\smashbox{#1}%
+\unexpanded\def\smashboxed#1%
+ {\wd#1\zeropoint
+ \ht#1\zeropoint
+ \dp#1\zeropoint
\box#1\relax}
%D \macros
@@ -74,45 +122,47 @@
%D Smashing can be used for overlaying boxes. Depending on
%D the mode, horizontal or vertical, one can use:
-\def\hsmashbox#1%
+\unexpanded\def\hsmashbox#1%
{\wd#1\zeropoint}
-\def\vsmashbox#1%
+\unexpanded\def\vsmashbox#1%
{\ht#1\zeropoint
\dp#1\zeropoint}
%D The next implementation is less sensitive for spurious
%D spaces.
-\newcount\registercount
+\newcount\c_boxes_register
-\def\smashbox
- {\afterassignment\dosmashbox\registercount}
+\unexpanded\def\smashbox
+ {\afterassignment\syst_boxes_smash_boxes_register\c_boxes_register}
-\def\dosmashbox
- {\wd\registercount\zeropoint
- \ht\registercount\zeropoint
- \dp\registercount\zeropoint}
+\def\syst_boxes_smash_boxes_register
+ {\wd\c_boxes_register\zeropoint
+ \ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint}
-\def\smashedbox
- {\afterassignment\thesmashedbox\registercount}
+\unexpanded\def\hsmashbox
+ {\afterassignment\syst_boxes_hsmashed_boxes_register\c_boxes_register}
-\def\thesmashedbox
- {\dosmashbox
- \box\registercount}
+\def\syst_boxes_hsmashed_boxes_register
+ {\wd\c_boxes_register\zeropoint}
-\def\hsmashbox
- {\afterassignment\dohsmashbox\registercount}
+\unexpanded\def\vsmashbox
+ {\afterassignment\syst_boxes_vsmashed_boxes_register\c_boxes_register}
-\def\dohsmashbox
- {\wd\registercount\zeropoint}
+\def\syst_boxes_vsmashed_boxes_register
+ {\ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint}
-\def\vsmashbox
- {\afterassignment\dovsmashbox\registercount}
+\unexpanded\def\smashedbox
+ {\afterassignment\syst_boxes_smashed_boxes_register\c_boxes_register}
-\def\dovsmashbox
- {\ht\registercount\zeropoint
- \dp\registercount\zeropoint}
+\unexpanded\def\syst_boxes_smashed_boxes_register
+ {\wd\c_boxes_register\zeropoint
+ \ht\c_boxes_register\zeropoint
+ \dp\c_boxes_register\zeropoint
+ \box\c_boxes_register}
%D \macros
%D {hsmash,vsmash,
@@ -123,29 +173,28 @@
%D and smashed alternatives. The later ones reduce all
%D dimensions to zero.
-% Ok, but inefficient and/or catcode unsafe:
-%
-% \def\hsmash #1{\bgroup\setbox0=\normalhbox{#1}\hsmashbox0\box0\egroup}
-% \def\vsmash #1{\bgroup\setbox0=\normalvbox{#1}\vsmashbox0\box0\egroup}
-% \def\hsmashed#1{\bgroup\setbox0=\normalhbox{#1}\smashbox 0\box0\egroup}
-% \def\vsmashed#1{\bgroup\setbox0=\normalvbox{#1}\smashbox 0\box0\egroup}
-%
-% Better, but a waste of tokens:
-%
-% \def\hsmash {\bgroup\dowithnextbox{\hsmashbox\nextbox\flushnextbox\egroup}\normalhbox}
-% \def\vsmash {\bgroup\dowithnextbox{\vsmashbox\nextbox\flushnextbox\nextbox\egroup}\normalvbox}
-% \def\hsmashed{\bgroup\dowithnextbox{\smashbox \nextbox\flushnextbox\nextbox\egroup}\normalhbox}
-% \def\vsmashed{\bgroup\dowithnextbox{\smashbox \nextbox\flushnextbox\nextbox\egroup}\normalvbox}
-%
-% The best:
+\unexpanded\def\hsmash {\bgroup\dowithnextboxcs\syst_boxes_hsmashed_nextbox\hbox}
+\unexpanded\def\vsmash {\bgroup\dowithnextboxcs\syst_boxes_vsmashed_nextbox\vbox}
+\unexpanded\def\hsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \hbox}
+\unexpanded\def\vsmashed{\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox \vbox}
+
+\unexpanded\def\syst_boxes_hsmashed_nextbox
+ {\wd\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
-\def\dosomesmash#1% (begin|end)group ipv (b|e)group ?
- {\bgroup\dowithnextbox{#1\nextbox\flushnextbox\egroup}}
+\unexpanded\def\syst_boxes_vsmashed_nextbox
+ {\ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
-\def\hsmash {\dosomesmash\hsmashbox\normalhbox}
-\def\vsmash {\dosomesmash\vsmashbox\normalvbox}
-\def\hsmashed{\dosomesmash\smashbox \normalhbox}
-\def\vsmashed{\dosomesmash\smashbox \normalvbox}
+\unexpanded\def\syst_boxes_smashed_nextbox
+ {\ht\nextbox\zeropoint
+ \dp\nextbox\zeropoint
+ \wd\nextbox\zeropoint
+ \box\nextbox
+ \egroup}
%D \macros
%D {smashedhbox,smashedvbox}
@@ -157,12 +206,17 @@
%D \smashedvbox to ... {...}
%D \stoptyping
-\def\dosmashedbox#1%
- %{#1\bgroup\dowithnextbox{\smashbox\nextbox\flushnextbox\egroup}#1}
- {#1\bgroup\dowithnextbox{\smashedbox\nextbox\egroup}#1}
+\unexpanded\def\smashedhbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\hbox}
+\unexpanded\def\smashedvbox{\vbox\bgroup\dowithnextboxcs\syst_boxes_smashed_nextbox\vbox}
+
+%D First we define a helper. We use a \LUATEX\ feature in order to avoid
+%D mathpalettes.
-\def\smashedhbox{\dosmashedbox\hbox}
-\def\smashedvbox{\dosmashedbox\vbox}
+\newcount\c_boxes_math_style
+
+\unexpanded\def\syst_boxes_math_set_nextbox#1%
+ {\c_boxes_math_style\mathstyle
+ \setbox\nextbox\hbox{$\mathsurround\zeropoint\triggermathstyle\c_boxes_math_style{#1}$}}
%D \macros
%D {smash}
@@ -172,40 +226,61 @@
%D math module (although the \type {\leavevmode} is not added
%D here).
-\def\smash
- {\futurelet\nexttoken\dosmash}
+\unexpanded\def\smash
+ {\begingroup
+ \futurelet\nexttoken\syst_boxes_smash}
-\def\dosmash
- {\ifx\nexttoken[\@EA\dodosmash\else\@EA\donosmash\fi}
+\def\syst_boxes_smash
+ {\ifx\nexttoken[%
+ \expandafter\syst_boxes_smash_yes
+ \else
+ \expandafter\syst_boxes_smash_nop
+ \fi}
-\def\donosmash
- {\dodosmash[hd]}
+\def\syst_boxes_smash_nop
+ {\edef\m_boxes_smash_options{hd}%
+ \futurelet\nexttoken\syst_boxes_smash_indeed}
-\def\dodosmash[#1]%
- {\edef\@@smash{#1}\futurelet\nexttoken\dododosmash}
+\def\syst_boxes_smash_yes[#1]%
+ {\edef\m_boxes_smash_options{#1}%
+ \futurelet\nexttoken\syst_boxes_smash_indeed}
-\def\dododosmash % if needed we can avoid the \next
+\def\syst_boxes_smash_indeed
{\ifmmode
- \def\next##1{\mathpalette\mathsm@sh{##1}}%
+ \expandafter\syst_boxes_smash_math
\else\ifx\nexttoken\bgroup
- \let\next\finsm@sh
+ \doubleexpandafter\syst_boxes_smash_hbox
\else
- \def\next##1{\finsm@sh{##1}}%
- \fi\fi
- \next}
+ \doubleexpandafter\syst_boxes_smash_text
+ \fi\fi}
-\def\mathsm@sh#1#2% redefined plain macro
- {\finsm@sh{$\mathsurround\zeropoint#1{#2}$}}
+\def\syst_boxes_smash_math#1%
+ {\syst_boxes_math_set_nextbox{#1}%
+ \syst_boxes_smash_process}
-\def\makesm@sh#1% redefined plain macro (handles t b h d w)
- {\if#1w\nextboxwd\zeropoint\else
- \if#1h\nextboxht\zeropoint\else
- \if#1d\nextboxdp\zeropoint\else
- \if#1t\nextboxht\zeropoint\else
- \if#1b\nextboxdp\zeropoint\fi\fi\fi\fi\fi}
+\def\syst_boxes_smash_hbox
+ {\dowithnextboxcs\syst_boxes_smash_process\hbox}
-\def\finsm@sh % redefined plain macro
- {\dowithnextbox{\@EA\handletokens\@@smash\with\makesm@sh\flushnextbox}\normalhbox}
+\def\syst_boxes_smash_text#1%
+ {\setbox\nextbox\hbox{#1}%
+ \syst_boxes_smash_process}
+
+\def\syst_boxes_smash_process
+ {\expandafter\syst_boxes_smash_process_option\m_boxes_smash_options\relax
+ \box\nextbox
+ \endgroup}
+
+\def\syst_boxes_s_w{\wd\nextbox\zeropoint}
+\def\syst_boxes_s_h{\ht\nextbox\zeropoint}
+\def\syst_boxes_s_d{\dp\nextbox\zeropoint}
+\def\syst_boxes_s_t{\ht\nextbox\zeropoint}
+\def\syst_boxes_s_b{\dp\nextbox\zeropoint}
+
+\def\syst_boxes_smash_process_option#1%
+ {\ifx#1\relax\else
+ \csname boxes_s_#1\endcsname
+ \expandafter\syst_boxes_smash_process_option
+ \fi}
%D \starttabulate[|l|l|]
%D \NC w \NC \ruledhbox{\smash [w]{This is some great smashing, isn't it?}} \NC \NR
@@ -220,44 +295,78 @@
%D
%D The next implementation of \type {\phantom} cum suis does
%D not grab an argument in the non||math case, which is better.
-
-\unexpanded\def\phantom {\ph@nt\nextbox\nextbox\nextbox}
-\unexpanded\def\vphantom{\ph@nt\nextbox\nextbox\voidbox}
-\unexpanded\def\hphantom{\ph@nt\voidbox\voidbox\nextbox}
-
+%D
%D Due to a complicated call to \type {\mathpallete} and
%D thereby \type {\mathchoice}, the next macro looks ugly.
%D We also take care of non||braced arguments.
-\def\ph@nt#1#2#3%
- {\def\doph@nt
- {\ifmmode
- \def\mathph@nt####1####2{\makeph@nt#1#2#3{$\mathsurround\zeropoint####1{####2}$}}%
- \def\nextph@nt{\mathpalette\mathph@nt}%
- \else\ifx\nextph@nt\bgroup
- \def\nextph@nt{\makeph@nt#1#2#3}%
- \else
- \def\nextph@nt####1{\makeph@nt#1#2#3{####1}}%
- \fi\fi
- \nextph@nt}%
- \futurelet\nextph@nt\doph@nt}
+\unexpanded\def\phantom {\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed }
+\unexpanded\def\vphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_v}
+\unexpanded\def\hphantom{\begingroup\futurelet\nexttoken\syst_boxes_phantom_indeed_h}
-\def\makeph@nt#1#2#3%
- {\begingroup
- \dowithnextbox
- {\setbox\scratchbox\emptyhbox
- \ht\scratchbox\ht#1%
- \dp\scratchbox\dp#2%
- \wd\scratchbox\wd#3%
- \box\scratchbox
- \endgroup}
- \normalhbox}
+\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}
+\def\syst_boxes_phantom_math_h#1{\syst_boxes_math_set_nextbox{#1}\syst_boxes_phantom_make_h}
+
+\def\syst_boxes_phantom_hbox {\dowithnextboxcs\syst_boxes_phantom_make \hbox} % always hbox
+\def\syst_boxes_phantom_hbox_v{\dowithnextboxcs\syst_boxes_phantom_make_v\hbox} % always hbox
+\def\syst_boxes_phantom_hbox_h{\dowithnextboxcs\syst_boxes_phantom_make_h\hbox} % always hbox
+
+\def\syst_boxes_phantom_text #1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make } % always hbox
+\def\syst_boxes_phantom_text_v#1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make_v} % always hbox
+\def\syst_boxes_phantom_text_h#1{\setbox\nextbox\hbox{#1}\syst_boxes_phantom_make_h} % always hbox
+
+\def\syst_boxes_phantom_indeed
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math
+ \else\ifx\nexttoken\bgroup
+ \doubleexpandafter\syst_boxes_phantom_hbox
+ \else
+ \doubleexpandafter\syst_boxes_phantom_text
+ \fi\fi}
+
+\def\syst_boxes_phantom_indeed_v
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math_v
+ \else\ifx\nexttoken\bgroup
+ \doubleexpandafter\syst_boxes_phantom_hbox_v
+ \else
+ \doubleexpandafter\syst_boxes_phantom_text_v
+ \fi\fi}
+
+\def\syst_boxes_phantom_indeed_h
+ {\ifmmode
+ \expandafter\syst_boxes_phantom_math_h
+ \else\ifx\nexttoken\bgroup
+ \doubleexpandafter\syst_boxes_phantom_hbox_h
+ \else
+ \doubleexpandafter\syst_boxes_phantom_text_h
+ \fi\fi}
+
+\def\syst_boxes_phantom_make
+ {\setbox\scratchbox\emptyhbox
+ \ht\scratchbox\ht\nextbox
+ \dp\scratchbox\dp\nextbox
+ \wd\scratchbox\wd\nextbox
+ \box\scratchbox
+ \endgroup}
+
+\def\syst_boxes_phantom_make_v
+ {\setbox\scratchbox\emptyhbox
+ \ht\scratchbox\ht\nextbox
+ \dp\scratchbox\dp\nextbox
+ \box\scratchbox
+ \endgroup}
-\let\finph@nt\undefined
+\def\syst_boxes_phantom_make_h
+ {\setbox\scratchbox\emptyhbox
+ \wd\scratchbox\wd\nextbox
+ \box\scratchbox
+ \endgroup}
%D We also define plain's \type {\mathstrut}.
-\unexpanded\def\mathstrut{\vphantom{(}}
+\unexpanded\def\mathstrut{\vphantom(} % can be made faster by inlining
%D \macros
%D {getboxheight}
@@ -293,9 +402,9 @@
%D it accepts \type {{12}} as well as \type {12} as box
%D number.
-\def\getboxheight#1\of#2\box#3%
- {\def\next{#1\dimexpr\ht\registercount+\dp\registercount\relax}%
- \afterassignment\next\registercount=#3}
+\unexpanded\def\getboxheight#1\of#2\box#3%
+ {\def\next{#1\dimexpr\ht\c_boxes_register+\dp\c_boxes_register\relax}%
+ \afterassignment\next\c_boxes_register=#3}
%D For a long time the following three macros were part of
%D the grid snapping core module, but it makes more sense to
@@ -345,7 +454,7 @@
\newcount\noflines
\newdimen\noflinesheight
-\def\getnoflines#1%
+\unexpanded\def\getnoflines#1%
{\noflinesheight#1\relax
\ifzeropt\noflinesheight
\noflines\zerocount
@@ -361,7 +470,7 @@
\advance\noflines\minusone
\fi\fi}
-\def\getroundednoflines#1%
+\unexpanded\def\getroundednoflines#1%
{\noflinesheight#1\relax
\ifzeropt\noflinesheight
\noflines\zerocount
@@ -375,7 +484,7 @@
\noflines\noflinesheight
\fi\fi}
-\def\getrawnoflines#1%
+\unexpanded\def\getrawnoflines#1%
{\noflinesheight#1\relax
\ifzeropt\noflinesheight
\noflines\zerocount
@@ -439,12 +548,12 @@
\reshapebox{\global\advance\scratchcounter\plusone}%
\expandafter\egroup\expandafter\noflines\the\scratchcounter\relax}
-\def\determinenoflines
+\unexpanded\def\determinenoflines
{\bgroup
\forgetall
\let\crlf\endgraf
\let\\\endgraf
- \dowithnextbox{\dodeterminenoflines}\vbox}
+ \dowithnextboxcs\dodeterminenoflines\vbox}
%D \macros
%D {doiftextelse, doiftext}
@@ -458,19 +567,27 @@
%D \doiftext {data} {then branch}
%D \stoptyping
-\def\doiftextelse#1%
- {\bgroup
- \setbox\scratchbox\normalhbox
+\unexpanded\def\doiftextelse#1%
+ {\begingroup
+ \setbox\scratchbox\hbox
{\settrialtypesetting
\ignorespaces#1\removeunwantedspaces}%
\ifzeropt\wd\scratchbox
- \egroup\@EA\secondoftwoarguments
+ \endgroup\expandafter\secondoftwoarguments
\else
- \egroup\@EA\firstoftwoarguments
+ \endgroup\expandafter\firstoftwoarguments
\fi}
-\def\doiftext#1#2%
- {\doiftextelse{#1}{#2}\donothing}
+\unexpanded\def\doiftext#1%
+ {\begingroup
+ \setbox\scratchbox\hbox
+ {\settrialtypesetting
+ \ignorespaces#1\removeunwantedspaces}%
+ \ifzeropt\wd\scratchbox
+ \endgroup\expandafter\gobbleoneargument
+ \else
+ \endgroup\expandafter\firstofoneargument
+ \fi}
%D \macros
%D {dowithnextbox,nextbox}
@@ -495,8 +612,8 @@
%D
%D \starttyping
%D \def\getfloat%
-%D {\def\handlefloat{...\flushnextbox...}
-%D \dowithnextbox\handlefloat\normalvbox}
+%D {\def\handlefloat{...\box\nextbox...}
+%D \dowithnextboxcs\handlefloat\vbox}
%D \stoptyping
%D
%D instead of:
@@ -510,51 +627,46 @@
%D is needed because \type{\afterassignment} is executed inside
%D the box.
-\ifx\nextbox\undefined \newbox\nextbox \fi
-
-\long\def\dowithnextbox#1%
- {\long\def\dodowithnextbox{#1}%
- \afterassignment\dododowithnextbox
+\unexpanded\def\dowithnextbox#1%
+ {\def\syst_boxes_with_next_box{#1}%
+ \afterassignment\syst_boxes_with_next_box_indeed
\setbox\nextbox}
-\def\dododowithnextbox
- {\aftergroup\dodowithnextbox}
+\def\syst_boxes_with_next_box_indeed
+ {\aftergroup\syst_boxes_with_next_box}
-\long\def\dowithnextboxcs#1%
- {\let\dodowithnextbox#1%
- \afterassignment\dododowithnextbox
+\unexpanded\def\dowithnextboxcs#1%
+ {\let\syst_boxes_with_next_box#1%
+ \afterassignment\syst_boxes_with_next_box_indeed
\setbox\nextbox}
-\def\dododowithnextbox
- {\aftergroup\dodowithnextbox}
-
%D So in fact we get:
%D
%D \starttyping
-%D \setbox\nextbox { \aftergroup\dodowithnextbox ... }
+%D \setbox\nextbox { \aftergroup\syst_boxes_with_next_box ... }
%D \stoptyping
%D
%D or
%D
%D \starttyping
-%D \setbox\nextbox { ... } \dodowithnextbox
+%D \setbox\nextbox { ... } \syst_boxes_with_next_box
%D \stoptyping
%D
%D A slower but more versatile implementation is:
%D
%D \starttyping
%D \long\def\dowithnextbox#1#2%
-%D {\long\def\dodowithnextbox{#1}%
-%D \ifx#2\normalhbox
-%D \afterassignment\dododowithnextbox
-%D \else\ifx#2\normalvbox
-%D \afterassignment\dododowithnextbox
+%D {\long\def\syst_boxes_with_next_box{#1}%
+%D \ifx#2\hbox
+%D \afterassignment\syst_boxes_with_next_box_indeed
+%D \else\ifx#2\vbox
+%D \afterassignment\syst_boxes_with_next_box_indeed
%D \else\ifx#2\normalvtop
-%D \afterassignment\dododowithnextbox
+%D \afterassignment\syst_boxes_with_next_box_indeed
%D \else\ifx#2\normalvcenter
-%D \afterassignment\dododowithnextbox
+%D \afterassignment\syst_boxes_with_next_box_indeed
%D \else
-%D \afterassignment\dodowithnextbox
+%D \afterassignment\syst_boxes_with_next_box
%D \fi\fi\fi\fi
%D \setbox\nextbox#2}
%D \stoptyping
@@ -573,7 +685,7 @@
\def\nextboxdp {\dp\nextbox}
\def\nextboxhtdp {\dimexpr\ht\nextbox+\dp\nextbox\relax}
-\def\flushnextbox{\box\nextbox}
+\unexpanded\def\flushnextbox{\box\nextbox}
%D \macros
%D {dowithnextboxcontent}
@@ -588,38 +700,20 @@
%D
%D {\em todo: Search source for potential usage!}
-\long\def\dowithnextboxcontent#1#2% inside, after
- {\long\def\dodowithnextbox{#2}%
- \def\dododowithnextbox{#1\aftergroup\dodowithnextbox}%
- \afterassignment\dododowithnextbox
+\unexpanded\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}
-%D Now we can redefine \type {\dowithnextbox} as follows:
-%D
-%D \starttyping
-%D \def\dowithnextbox{\dowithnextboxcontent\empty}
-%D \stoptyping
-%D
-%D But since this macro is used often and since this implementation
-%D is slower, we will not use that definition.
+\unexpanded\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}
-% maybe:
-%
-% depending on the size of the action, about 10% faster
-%
-% \newtoks\nextboxtoks
-%
-% \def\dowithnextbox {\afterassignment\redowithnextbox\nextboxtoks}
-% \def\redowithnextbox {\afterassignment\dododowithnextbox\setbox\nextbox}
-% \def\dododowithnextbox{\aftergroup\dodowithnextbox}
-% \def\dodowithnextbox {\the\nextboxtoks}
-%
-% \long\def\dowithnextboxcontent#1% #2% inside, after
-% {\def\dododowithnextbox{#1\aftergroup\dodowithnextbox}%
-% \afterassignment\redowithnextboxcontent\nextboxtoks}
-%
-% \def\redowithnextboxcontent
-% {\afterassignment\dododowithnextbox\setbox\nextbox}
+\def\syst_boxes_with_next_box_content_indeed
+ {\syst_boxes_with_next_box_two\aftergroup\syst_boxes_with_next_box_one}
%D \macros
%D {llap, rlap, tlap, blap, clap}
@@ -627,13 +721,13 @@
%D Some well known friends, but we implement them our own
%D way. We want the macros to work in both math and text mode.
-\def\dodorlap{\normalhbox to \zeropoint{\flushnextbox\normalhss}\endgroup}
-\def\dodollap{\normalhbox to \zeropoint{\normalhss\flushnextbox}\endgroup}
-\def\dodoclap{\normalhbox to \zeropoint{\normalhss\flushnextbox\normalhss}\endgroup}
+\def\dodorlap{\hbox to \zeropoint{\box\nextbox\normalhss}\endgroup}
+\def\dodollap{\hbox to \zeropoint{\normalhss\box\nextbox}\endgroup}
+\def\dodoclap{\hbox to \zeropoint{\normalhss\box\nextbox\normalhss}\endgroup}
-\def\dorlap{\begingroup\dowithnextboxcs\dodorlap\normalhbox}
-\def\dollap{\begingroup\dowithnextboxcs\dodollap\normalhbox}
-\def\doclap{\begingroup\dowithnextboxcs\dodoclap\normalhbox}
+\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{$\mathsurround\zeropoint#1#2$}}
\def\domathllap{\mathpalette\dodomathllap} \def\dodomathllap#1#2{\dollap{$\mathsurround\zeropoint#1#2$}}
@@ -643,11 +737,11 @@
\unexpanded\def\llap{\mathortext\domathllap\dollap}
\unexpanded\def\clap{\mathortext\domathclap\doclap}
-\def\dodotlap{\normalvbox to \zeropoint{\normalvss\flushnextbox}\endgroup}
-\def\dodoblap{\normalvbox to \zeropoint{\flushnextbox\normalvss}\endgroup}
+\def\dodotlap{\vbox to \zeropoint{\normalvss\box\nextbox}\endgroup}
+\def\dodoblap{\vbox to \zeropoint{\box\nextbox\normalvss}\endgroup}
-\def\tlap{\begingroup\dowithnextboxcs\dodotlap\normalvbox}
-\def\blap{\begingroup\dowithnextboxcs\dodoblap\normalvbox}
+\unexpanded\def\tlap{\begingroup\dowithnextboxcs\dodotlap\vbox}
+\unexpanded\def\blap{\begingroup\dowithnextboxcs\dodoblap\vbox}
%D \macros
%D {beginofshapebox,
@@ -694,7 +788,7 @@
%D
%D \reshapebox
%D {\doglobal\increment\LineNumber
-%D \normalhbox{\llap{\LineNumber\hskip2em}\box\shapebox}}
+%D \hbox{\llap{\LineNumber\hskip2em}\box\shapebox}}
%D
%D \flushshapebox
%D \stopbuffer
@@ -716,7 +810,7 @@
%D
%D \reshapebox
%D {\doglobal\increment\LineNumber
-%D \normalhbox
+%D \hbox
%D {\llap{\LineNumber\ (\NumberOfLines)\hskip2em}%
%D \box\shapebox}%
%D \doglobal\decrement\NumberOfLines}
@@ -739,7 +833,7 @@
%D
%D \reshapebox
%D {\doglobal\increment\LineNumber
-%D \normalhbox{\llap{$\star$\hskip1em}\box\shapebox}%
+%D \hbox{\llap{$\star$\hskip1em}\box\shapebox}%
%D \doglobal\decrement\NumberOfLines}
%D
%D \flushshapebox
@@ -787,7 +881,7 @@
\def\shapesignal{.12345678pt} % or 12345sp
-\def\reshapebox#1%
+\unexpanded\def\reshapebox#1%
{\doreshapebox
{#1}%
{\penalty\shapepenalty}%
@@ -803,7 +897,7 @@
\ifzeropt\ht\oldshapebox % \ifdim\ht\oldshapebox=\zeropoint
\setbox\newshapebox\emptyvbox
\else
- \setbox\newshapebox\normalvbox
+ \setbox\newshapebox\vbox
{\unvcopy\oldshapebox
\setbox\newshapebox\emptybox
\shapecounter\zerocount
@@ -815,25 +909,25 @@
% We will turn this into a \MKIV\ variant.
-\def\insertshapesignal
- {\normalhbox to \shapesignal{\strut\hss}% plus \strut
+\unexpanded\def\insertshapesignal
+ {\hbox to \shapesignal{\strut\hss}% plus \strut
\prevdepth\strutdp} % never \nointerlineskip
-\def\restoreshapebox % compensates for the signal
+\unexpanded\def\restoreshapebox % compensates for the signal
{\global\setbox\tmpshapebox\vbox{\vskip-\lineheight\unvcopy\oldshapebox}}
\def\dodoreshapebox#1#2#3#4% \shapebox, \shapepenalty, \shapekern, \shapeskip
- {\ifnum\lastnodetype=\@@gluenode
+ {\ifnum\lastnodetype=\gluenodecode
\shapeskip\lastskip
- \global\setbox\tmpshapebox\normalvbox{#4\unvbox\tmpshapebox}%
+ \global\setbox\tmpshapebox\vbox{#4\unvbox\tmpshapebox}%
\unskip
- \else\ifnum\lastnodetype=\@@kernnode
+ \else\ifnum\lastnodetype=\kernnodecode
\shapekern\lastkern
- \global\setbox\tmpshapebox\normalvbox{#3\unvbox\tmpshapebox}%
+ \global\setbox\tmpshapebox\vbox{#3\unvbox\tmpshapebox}%
\unkern
- \else\ifnum\lastnodetype=\@@penaltynode
+ \else\ifnum\lastnodetype=\penaltynodecode
\shapepenalty\lastpenalty
- \global\setbox\tmpshapebox\normalvbox{#2\unvbox\tmpshapebox}%
+ \global\setbox\tmpshapebox\vbox{#2\unvbox\tmpshapebox}%
\unpenalty
\else\ifnum\lastnodetype<\zeropoint
\exitloop
@@ -844,7 +938,7 @@
\exitloop
\else
\shapecounter\zerocount
- \global\setbox\tmpshapebox\normalvbox{#1\unvbox\tmpshapebox}%
+ \global\setbox\tmpshapebox\vbox{#1\unvbox\tmpshapebox}%
\fi\fi
\fi\fi\fi\fi
\ifnum\shapecounter>100 % can be less
@@ -856,21 +950,21 @@
\advance\shapecounter \plusone
\fi}
-\def\beginofshapebox
- {\setbox\oldshapebox\normalvbox
+\unexpanded\def\beginofshapebox
+ {\setbox\oldshapebox\vbox
\bgroup
\reshapingboxtrue
\the\everyshapebox
\insertshapesignal}
-\def\endofshapebox
+\unexpanded\def\endofshapebox
{\endgraf
\egroup}
\let\beginshapebox\beginofshapebox
\let\endshapebox \endofshapebox
-\def\flushshapebox
+\unexpanded\def\flushshapebox
{\bgroup
\ifzeropt\ht\newshapebox % \ifdim\ht\newshapebox=\zeropoint
\else
@@ -921,7 +1015,7 @@
%
% \omlijnd[offset=0pt,hoogte=8mm,uitlijnen={rechts,laho}]{\bfa test}
-\def\innerflushshapebox
+\unexpanded\def\innerflushshapebox
{\ifzeropt\ht\newshapebox \else
\unvcopy\newshapebox\relax % unvcopy ! else spacing problem
% \kern-\dp\newshapebox\relax
@@ -943,15 +1037,15 @@
%D
%D When constructing a new box, using the content of \type
%D {\shapebox}, one can best use \type {\shapedhbox} instead
-%D of \type {\normalhbox}, since it manages the height and depth of
+%D of \type {\hbox}, since it manages the height and depth of
%D the line.
-\def\shapedhbox % lines with non strutted dimensions have
- {\expanded{\dowithnextbox % interlineskip so if we want the original
- {\nextboxht\the\ht\shapebox % spacing, we need to preserve the original
- \nextboxdp\the\dp\shapebox % height and depth which is definitely
- \noexpand\flushnextbox}} % needed if we apply struts to the 'new'
- \normalhbox} % box or do something that changed ist size
+\unexpanded\def\shapedhbox % lines with non strutted dimensions have
+ {\expanded{\dowithnextbox % interlineskip so if we want the original
+ {\dp\nextbox\the\ht\shapebox % spacing, we need to preserve the original
+ \dp\nextbox\the\dp\shapebox % height and depth which is definitely
+ \box\nextbox}} % needed if we apply struts to the 'new'
+ \hbox} % box or do something that changed ist size
%D \macros
%D {hyphenatedword,
@@ -969,7 +1063,7 @@
\def\doshowhyphenatednextbox
{\ctxcommand{showhyphenatedinlist(tex.box[\number\nextbox].list)}}
-\def\showhyphens{\dowithnextbox\doshowhyphenatednextbox\hbox}
+\unexpanded\def\showhyphens{\dowithnextboxcs\doshowhyphenatednextbox\hbox}
%D The following macros are seldom used but handy for tracing.
%D
@@ -983,9 +1077,9 @@
{\ctxcommand{hyphenatedlist(tex.box[\number\nextbox])}%
\unhbox\nextbox}
-\def\hyphenatedword {\dowithnextbox\dohyphenatednextbox \hbox}
-\def\hyphenatedpar {\dowithnextbox\dohyphenatednextbox \hbox}
-\def\hyphenatedfile#1{\dowithnextbox\dohyphenatednextbox \hbox{\readfile{#1}\donothing\donothing}}
+\unexpanded\def\hyphenatedword {\dowithnextboxcs\dohyphenatednextbox \hbox}
+\unexpanded\def\hyphenatedpar {\dowithnextboxcs\dohyphenatednextbox \hbox}
+\unexpanded\def\hyphenatedfile#1{\dowithnextboxcs\dohyphenatednextbox \hbox{\readfile{#1}\donothing\donothing}}
%D \macros
%D {processtokens}
@@ -1015,6 +1109,22 @@
%D The list of tokens may contain spaces, while \type{\\},
%D \type{{}} and \type{\ } are handled as space too.
+\unexpanded\def\processtokens#1#2#3#4#5%
+ {\begingroup
+ \def\lastcharacter{\lastcharacter}%
+ \def\space{ }%
+ \let\\=\space
+ \def\before {#1}%
+ \def\between{#2}%
+ \def\after {#3}%
+ \def\white {#4}%
+ \let\savedbefore\before
+ \doprocesstokens#5\lastcharacter
+ \endgroup}
+
+\def\doprocesstokens% the space after = is essential
+ {\afterassignment\dodoprocesstokens\let\nextprocessedtoken= }
+
\def\dodoprocesstokens
{\ifx\nextprocessedtoken\lastcharacter
\after
@@ -1038,22 +1148,6 @@
\fi\fi
\nextprocessedtoken}
-\def\doprocesstokens% the space after = is essential
- {\afterassignment\dodoprocesstokens\let\nextprocessedtoken= }
-
-\def\processtokens#1#2#3#4#5%
- {\begingroup
- \def\lastcharacter{\lastcharacter}%
- \def\space{ }%
- \let\\=\space
- \def\before {#1}%
- \def\between{#2}%
- \def\after {#3}%
- \def\white {#4}%
- \let\savedbefore\before
- \doprocesstokens#5\lastcharacter
- \endgroup}
-
%D \macros
%D {doboundtext}
%D
@@ -1073,16 +1167,16 @@
%D complex macro than needed at first sight.
\def\dodoboundtext#1%
- {\setbox0\normalhbox{#1}%
+ {\setbox0\hbox{#1}%
\advance\scratchdimen -\wd0
\ifdim\scratchdimen>\zeropoint\relax#1\fi}%
\def\doboundtext#1#2#3% still used?
- {\normalhbox
- {\setbox\scratchbox\normalhbox{#1}%
+ {\hbox
+ {\setbox\scratchbox\hbox{#1}%
\scratchdimen#2\relax
\ifdim\wd\scratchbox>\scratchdimen
- \setbox\scratchbox\normalhbox{#3}%
+ \setbox\scratchbox\hbox{#3}%
\advance\scratchdimen -\wd\scratchbox
\handletokens#1\with\dodoboundtext
\fi
@@ -1104,113 +1198,73 @@
%D When no width is given, the whole text comes available. The
%D sentinel is optional. This is about the third version.
-\ifx\fakecompoundhyphen\undefined \let\fakecompoundhyphen\relax \fi
-\ifx\veryraggedright \undefined \def\veryraggedright{\raggedright} \fi
-
-%D The simple alternative is as follows:
-%D
-%D \starttyping
-%D \unexpanded\def\limitatetext%
-%D {\bgroup % evt \setstrut
-%D \forgetall
-%D \fakecompoundhyphen % dangerous ! ! ! ! ! ! ! ! !
-%D \dowithnextbox\dolimitatetext\normalhbox}
-%D
-%D \def\dolimitatetext#1#2%
-%D {\doifelsenothing{#1}
-%D {\unhbox\nextbox}
-%D {\widowpenalty=0
-%D \clubpenalty=0
-%D \scratchdimen=#1\relax
-%D \ifdim\nextboxwd>\scratchdimen
-%D \setbox\scratchbox=\normalhbox{ #2}%
-%D \advance\scratchdimen by -\wd\scratchbox
-%D \setbox\nextbox=\normalvbox
-%D {\hsize=\scratchdimen
-%D \hfuzz\maxdimen
-%D \veryraggedright
-%D \strut\unhcopy\nextbox}%
-%D \ifdim\nextboxht>\strutht \else
-%D \setbox\scratchbox\emptyhbox % overfull and not split
-%D \fi
-%D \setbox\nextbox=\normalvbox % if omitted: missing brace reported
-%D {\splittopskip=\openstrutheight
-%D \setbox\nextbox=\vsplit\nextbox to \strutht
-%D \unvbox\nextbox
-%D \setbox\nextbox=\lastbox
-%D \global\setbox1=\normalhbox
-%D {\unhbox\nextbox\unskip\kern\zeropoint\box\scratchbox\unskip}}%
-%D \unhbox1
-%D \else
-%D \unhbox\nextbox
-%D \fi}%
-%D \egroup}
-%D \stoptyping
-%D
-%D The next alternative accepts a negative width. A negative
-%D value crops the beginning. The macro thereby becomes less
-%D readable, which is why we kept the original here too.
+\ifdefined\fakecompoundhyphen\else \let\fakecompoundhyphen\relax \fi
+\ifdefined\veryraggedright \else \def\veryraggedright{\raggedright} \fi
\unexpanded\def\limitatetext
{\bgroup % evt \setstrut
\forgetall % otherwise indentation and so
- %\def\limitatetext##1##2##3{##1}% \def !
\let\limitatetext\firstofthreearguments
\fakecompoundhyphen % dangerous ! ! ! ! ! ! ! ! !
- \dowithnextboxcs\dolimitatetext\normalhbox}
-
-\def\dolimitatetext#1#2%
- {\doifelsenothing{#1}
- {\unhbox\nextbox}
- {\nopenalties
- \scratchdimen#1\relax
- \ifdim\scratchdimen<\zeropoint\relax % we'll take the last line
- \donefalse
- \scratchdimen-\scratchdimen
- \else
- \donetrue
- \fi
- \ifdim\nextboxwd>\scratchdimen
- \setbox\scratchbox\normalhbox{\ifdone\space#2\else#2\space\fi}%
- \advance\scratchdimen -\wd\scratchbox
- \setbox0\flushnextbox
- \setbox\nextbox\normalvbox
- {\hsize\scratchdimen
- \hfuzz\maxdimen
- \veryraggedright
- \strut
- \ifdone \else
- \parfillskip\zeropoint
- \rightskip\zeropoint
- \hskip\zeropoint \!!plus 1\!!fill % \hsize
- \fi
- \unhcopy0}%
- \ifdim\nextboxht>\strutht
- \setbox\nextbox\normalvbox % if omitted: missing brace reported
- {\splittopskip\openstrutheight
- \ifdone
- \setbox\nextbox\vsplit\nextbox to \strutht
+ \dowithnextboxcs\syst_boxes_limitate_text\hbox}
+
+\def\syst_boxes_limitate_text#1% #2
+ {\doifelsenothing{#1}\syst_boxes_limitate_text_nop\syst_boxes_limitate_text_yes{#1}} % {#2}
+
+\def\syst_boxes_limitate_text_nop#1#2%
+ {\unhbox\nextbox
+ \egroup}
+
+\def\syst_boxes_limitate_text_yes#1#2%
+ {\nopenalties
+ \scratchdimen#1\relax
+ \ifdim\scratchdimen<\zeropoint\relax % we'll take the last line
+ \donefalse
+ \scratchdimen-\scratchdimen
+ \else
+ \donetrue
+ \fi
+ \ifdim\wd\nextbox>\scratchdimen
+ \setbox\scratchbox\hbox{\ifdone\space#2\else#2\space\fi}%
+ \advance\scratchdimen -\wd\scratchbox
+ \setbox0\box\nextbox
+ \setbox\nextbox\vbox
+ {\hsize\scratchdimen
+ \hfuzz\maxdimen
+ \veryraggedright
+ \strut
+ \ifdone \else
+ \parfillskip\zeropoint
+ \rightskip\zeropoint
+ \hskip\zeropoint \!!plus 1\!!fill % \hsize
+ \fi
+ \unhcopy0}%
+ \ifdim\ht\nextbox>\strutht
+ \setbox\nextbox\vbox % if omitted: missing brace reported
+ {\splittopskip\openstrutheight
+ \ifdone
+ \setbox\nextbox\vsplit\nextbox to \strutht
+ \else
+ \doloop
+ {\setbox0\vsplit\nextbox to \strutht
+ \ifdim\ht\nextbox>\strutht \else \exitloop \fi}%
+ \fi
+ \unvbox\nextbox
+ \setbox\nextbox\lastbox
+ \global\setbox1\hbox
+ {\ifdone
+ \unhbox\nextbox\unskip\kern\zeropoint\box\scratchbox
\else
- \doloop
- {\setbox0\vsplit\nextbox to \strutht
- \ifdim\nextboxht>\strutht \else \exitloop \fi}%
+ \box\scratchbox\unhbox\nextbox
\fi
- \unvbox\nextbox
- \setbox\nextbox\lastbox
- \global\setbox1\normalhbox
- {\ifdone
- \unhbox\nextbox\unskip\kern\zeropoint\box\scratchbox
- \else
- \box\scratchbox\unhbox\nextbox
- \fi
- \unskip}}%
- \unhbox1
- \else
- \unhbox0
- \fi
- \else
- \unhbox\nextbox
- \fi}%
+ \unskip}}%
+ \unhbox1
+ \else
+ \unhbox0
+ \fi
+ \else
+ \unhbox\nextbox
+ \fi
\egroup}
%D We can also limit a text with more control:
@@ -1226,23 +1280,24 @@
%D
%D We build this feature on top of the previous macro.
+% we could move the text argument to the end
+
\let\normallimitatetext\limitatetext
\def\speciallimitatetext#1#2#3#4% text left right placeholder
{%\dontleavehmode
\bgroup
- %\def\speciallimitatetext##1##2##3##4{##1}% \def !
\let\speciallimitatetext\firstoffourarguments
- \setbox0\normalhbox
+ \setbox0\hbox
{\nohyphens
\normallimitatetext{#1}{+#2}{}#4%
\normallimitatetext{#1}{-#3}{}}%
- \setbox2\normalhbox
+ \setbox2\hbox
{#1}%
- \ifdim\wd2<\wd0 #1\else\unhbox0\fi
- \egroup}
+ \ifdim\wd2<\wd0 #1\else\unhbox0\fi
+ \egroup}
-\def\limitatetext#1#2#3% \expanded added 2003/01/16
+\unexpanded\def\limitatetext#1#2#3% \expanded added 2003/01/16
{\expanded{\beforesplitstring#2}\at,\to\leftlimit
\expanded{\aftersplitstring #2}\at,\to\rightlimit
\ifx\rightlimit\empty
@@ -1257,7 +1312,7 @@
%D \limitatefirstline{\input tufte\relax}{10cm}{\unknown}
%D \stoptyping
-\def\limitatefirstline#1#2#3%
+\unexpanded\def\limitatefirstline#1#2#3%
{\hbox\bgroup\strut
\setbox\scratchbox\hbox{\begstrut#1\endstrut}%
\ifdim\wd\scratchbox>#2\relax
@@ -1290,27 +1345,29 @@
%D \startbuffer
%D \processisolatedchars{some more words} \ruledhbox \par
%D \processisolatedchars{and some $x + y = z$ math} \ruledhbox \par
-%D \processisolatedchars{and a \normalhbox{$x + y = z$}} \ruledhbox \par
+%D \processisolatedchars{and a \hbox{$x + y = z$}} \ruledhbox \par
%D \processisolatedwords{some more words} \ruledhbox \par
%D \processisolatedwords{and some $x + y = z$ math} \ruledhbox \par
-%D \processisolatedwords{and a \normalhbox{$x + y = z$}} \ruledhbox \par
+%D \processisolatedwords{and a \hbox{$x + y = z$}} \ruledhbox \par
%D \stopbuffer
%D
%D \typebuffer \blank \getbuffer \blank
% todo: provide variant with #1 picked up as box
-\def\processisolatedchars#1#2%
+\unexpanded\def\processisolatedchars#1#2%
{\dontleavehmode
\begingroup
- \setbox\scratchbox\normalhbox{#1}%
+ \setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}%
+ \setbox\scratchbox\hbox{\restorecurrentattributes{pic}#1}%
\ctxcommand{applytochars(\number\scratchbox,"\strippedcsname#2",true)}%
\endgroup}
-\def\processisolatedwords#1#2%
+\unexpanded\def\processisolatedwords#1#2%
{\dontleavehmode
\begingroup
- \setbox\scratchbox\normalhbox{#1}%
+ \setbox\scratchbox\hbox{\settrialtypesetting#2{\savecurrentattributes{pic}}}%
+ \setbox\scratchbox\hbox{\restorecurrentattributes{pic}#1}%
\ctxcommand{applytowords(\number\scratchbox,"\strippedcsname#2",true)}%
\endgroup}
@@ -1321,15 +1378,15 @@
%D The better variant:
-\def\applytocharacters#1%
+\unexpanded\def\applytocharacters#1%
{\dontleavehmode
\dowithnextbox{\ctxcommand{applytochars(\number\nextbox,"\strippedcsname#1",true)}}%
- \normalhbox}
+ \hbox}
-\def\applytowords#1%
+\unexpanded\def\applytowords#1%
{\dontleavehmode
\dowithnextbox{\ctxcommand{applytowords(\number\nextbox,"\strippedcsname#1",true)}}%
- \normalhbox}
+ \hbox}
%D \macros
%D {sbox}
@@ -1348,28 +1405,29 @@
%D
%D Shows up as:
%D
-%D \startvoorbeeld
+%D \startexample
%D \vskip3\baselineskip
%D \getbuffer
-%D \stopvoorbeeld
+%D \stopexample
%D
%D Before displaying the result we added some skip, otherwise
%D the first two lines would have ended up in the text. This
%D macro can be useful when building complicated menus, headers
%D and footers and|/|or margin material.
-\def\sbox% in handleiding, voorbeeld \inleft{xx} \extern..
- {\normalvbox\bgroup % new ! ! !
- \dowithnextbox
- {\setbox\scratchbox\normalhbox
- {\strut
- \nextboxdp\zeropoint
- \lower\strutdepth\flushnextbox}%
- \dp\scratchbox\strutdepth
- \ht\scratchbox\strutheight
- \box\scratchbox
- \egroup}%
- \normalvbox}
+\unexpanded\def\sbox
+ {\vbox\bgroup
+ \dowithnextboxcs\syst_boxes_sbox_finish\vbox}
+
+\unexpanded\def\syst_boxes_sbox_finish
+ {\setbox\nextbox\hbox
+ {\strut
+ \dp\nextbox\zeropoint
+ \lower\strutdepth\box\nextbox}%
+ \dp\nextbox\strutdepth
+ \ht\nextbox\strutheight
+ \box\nextbox
+ \egroup}
%D \macros
%D {struttedbox}
@@ -1377,14 +1435,15 @@
%D This boxing macro limits the height and depth to those of
%D a strut.
-\def\struttedbox
- {\normalhbox\bgroup % new ! ! !
- \dowithnextbox
- {\nextboxdp\strutdepth
- \nextboxht\strutheight
- \flushnextbox
- \egroup}%
- \normalhbox}
+\unexpanded\def\struttedbox
+ {\hbox\bgroup
+ \dowithnextboxcs\syst_boxes_struttedbox_finish\hbox}
+
+\def\syst_boxes_struttedbox_finish
+ {\ht\nextbox\strutdepth
+ \ht\nextbox\strutheight
+ \box\nextbox
+ \egroup}%
%D \macros
%D {topskippedbox}
@@ -1393,14 +1452,14 @@
%D and strutheight. Watch how we preserve the depth when it
%D equals strutdepth.
-\def\topskippedbox
- {\normalhbox\bgroup
- \dowithnextbox
- {\edef\next{\ifdim\strutdepth=\nextboxdp\nextboxdp\the\nextboxdp\fi}%
- \lower\topskip\normalhbox{\raise\strutheight\flushnextbox}%
- \next
- \egroup}%
- \normalhbox}
+\unexpanded\def\topskippedbox
+ {\hbox\bgroup\dowithnextboxcs\syst_boxes_topskippedbox_finish\hbox}
+
+\def\syst_boxes_topskippedbox_finish
+ {\edef\m_boxes_tmp{\ifdim\strutdepth=\dp\nextbox\dp\nextbox\the\dp\nextbox\fi}%
+ \lower\topskip\hbox{\raise\strutheight\box\nextbox}%
+ \m_boxes_tmp
+ \egroup}
%D \macros
%D {centeredbox, centerednextbox}
@@ -1448,26 +1507,26 @@
%D intact. This commands handles positive and negative
%D dimensions (which is why we need two boxes with rules).
-\def\centeredbox#1#% height +/-dimen width +/-dimen
+\unexpanded\def\centeredbox#1#% height +/-dimen width +/-dimen
{\bgroup
- \setbox0\normalvbox to \vsize
+ \setbox0\vbox to \vsize
\bgroup
\dontcomplain
\forgetall
- \setbox0\normalhbox{\vrule\!!width \zeropoint#1}%
- \setbox2\normalvbox{\hrule\!!height\zeropoint#1}%
+ \setbox0\hbox{\vrule\!!width \zeropoint#1}%
+ \setbox2\vbox{\hrule\!!height\zeropoint#1}%
\advance\vsize \ht2
\advance\hsize \wd0
- \normalvbox to \vsize
+ \vbox to \vsize
\bgroup
\vskip-\ht2
\vss
- \normalhbox to \hsize
+ \hbox to \hsize
\bgroup
\dowithnextbox
{\hskip-\wd0
\hss
- \flushnextbox
+ \box\nextbox
\hss
\egroup
\vss
@@ -1477,7 +1536,7 @@
\ht0\vsize
\box0
\egroup}
- \normalhbox}
+ \hbox}
%D For those who don't want to deal with \type {\hsize}
%D and \type {\vsize}, we have:
@@ -1489,14 +1548,14 @@
%D
%D Do you see what we call this one \type {next}?
-\def\centerednextbox#1#%
+\unexpanded\def\centerednextbox#1#%
{\bgroup
\dowithnextbox
- {\hsize\nextboxwd
- \vsize\nextboxht
- \centeredbox#1{\flushnextbox}%
+ {\hsize\wd\nextbox
+ \vsize\ht\nextbox
+ \centeredbox#1{\box\nextbox}%
\egroup}
- \normalhbox}
+ \hbox}
%D \macros
%D {centerbox}
@@ -1510,17 +1569,17 @@
%D When omitted, the current \type {\hsize} and \type
%D {\vsize} are used. Local dimensions are supported.
-\long\def\centerbox#1#% optional height +/-dimen width +/-dimen
+\unexpanded\def\centerbox#1#% optional height +/-dimen width +/-dimen
{\bgroup
\dowithnextbox
{\setlocalhsize
- \setbox\scratchbox\normalhbox{\vrule\!!width \zeropoint#1}%
+ \setbox\scratchbox\hbox{\vrule\!!width \zeropoint#1}%
\ifzeropt\wd\scratchbox\else\hsize\wd\scratchbox\fi
- \setbox\scratchbox\normalvbox{\hrule\!!height\zeropoint#1}%
+ \setbox\scratchbox\vbox{\hrule\!!height\zeropoint#1}%
\ifzeropt\ht\scratchbox\else\vsize\ht\scratchbox\fi
- \normalvbox to \vsize{\vss\normalhbox to \hsize{\hss\flushnextbox\hss}\vss}%
+ \vbox to \vsize{\vss\hbox to \hsize{\hss\box\nextbox\hss}\vss}%
\egroup}%
- \normalhbox}
+ \hbox}
%D \macros
%D {setrigidcolumnhsize,rigidcolumnbalance,rigidcolumnlines}
@@ -1546,7 +1605,7 @@
%D De eerste switch bepaald het uitlijnen, de tweede rekt de
%D individuele kolommen op naar \type{\vsize}.
-\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr
+\unexpanded\def\setrigidcolumnhsize#1#2#3% todo: \dimexpr
{\xdef\savedrigidhsize{\the\hsize}%
\hsize#1\relax
\global\chardef\rigidcolumns#3\relax
@@ -1567,15 +1626,15 @@
\let\rigidcolumnlines\!!zerocount
-\def\rigidcolumnbalance#1%
+\unexpanded\def\rigidcolumnbalance#1%
{\ifnum\rigidcolumns=1 % tzt ook h/d correctie
\ifinner\ifhmode\box\else\unvbox\fi\else\unvbox\fi#1\relax
\else
- \normalvbox
+ \vbox
{\forgetall
\nopenalties
\dontcomplain
- \setbox\rigidcolumnbox\normalvbox
+ \setbox\rigidcolumnbox\vbox
{\line{}\goodbreak\unvbox#1\removebottomthings}%
\splittopskip\openstrutheight
\setbox\scratchbox\vsplit\rigidcolumnbox to \zeropoint
@@ -1604,7 +1663,7 @@
\setbox0=\box\rigidcolumnbox
\doloop
{\setbox\rigidcolumnbox=\copy0
- \setbox\scratchbox\normalhbox to \savedrigidhsize
+ \setbox\scratchbox\hbox to \savedrigidhsize
{\dorecurse\rigidcolumns
{\setbox\scratchbox\vsplit\rigidcolumnbox to \scratchdimen
\dp\scratchbox\openstrutdepth
@@ -1619,10 +1678,10 @@
\hfillneg}%
\ifvoid\rigidcolumnbox\exitloop\else\advance\scratchdimen\lineheight\fi}%
\iftightrigidcolumns
- \setbox\scratchbox\normalhbox{\raise\dp\scratchbox\box\scratchbox}%
+ \setbox\scratchbox\hbox{\raise\dp\scratchbox\box\scratchbox}%
\else
\advance\scratchdimen -\openstrutdepth
- \setbox\scratchbox\normalhbox{\raise\scratchdimen\box\scratchbox}%
+ \setbox\scratchbox\hbox{\raise\scratchdimen\box\scratchbox}%
\dp\scratchbox\openstrutdepth
\ht\scratchbox\scratchdimen
\fi
@@ -1637,14 +1696,14 @@
%D like:
%D
%D \starttyping
-%D \normalvbox
+%D \vbox
%D \bgroup
%D \startvboxtohbox ... \stopvboxtohbox
%D \startvboxtohbox ... \stopvboxtohbox
%D \startvboxtohbox ... \stopvboxtohbox
%D \egroup
%D
-%D \normalvbox
+%D \vbox
%D \bgroup
%D \convertvboxtohbox
%D \egroup
@@ -1653,7 +1712,7 @@
%D These macros are used in reformatting footnotes, so they do
%D what they're meant for.
-\def\setvboxtohbox
+\unexpanded\def\setvboxtohbox
{\bgroup
\ifdim\baselineskip<16pt \relax
\scratchdimen\baselineskip
@@ -1664,36 +1723,36 @@
\fi
\divide\scratchdimen \hsize
\multiply\scratchdimen 64
- \xdef\normalvboxtohboxfactor{\withoutpt\the\scratchdimen}%
+ \xdef\vboxtohboxfactor{\withoutpt\the\scratchdimen}%
\egroup}
-\def\startvboxtohbox
+\unexpanded\def\startvboxtohbox
{\bgroup
\setvboxtohbox
- \setbox\scratchbox\normalhbox\bgroup}
+ \setbox\scratchbox\hbox\bgroup}
-\def\stopvboxtohbox
+\unexpanded\def\stopvboxtohbox
{\egroup
\dp\scratchbox\zeropoint
- \ht\scratchbox\normalvboxtohboxfactor\wd\scratchbox
+ \ht\scratchbox\vboxtohboxfactor\wd\scratchbox
\box\scratchbox
\egroup}
-\def\convertvboxtohbox
+\unexpanded\def\convertvboxtohbox
{\setvboxtohbox
\makehboxofhboxes
- \setbox0\normalhbox{\unhbox0 \removehboxes}%
+ \setbox0\hbox{\unhbox0 \removehboxes}%
\noindent\unhbox0\par}
-\def\makehboxofhboxes
+\unexpanded\def\makehboxofhboxes
{\setbox0\emptyhbox
\loop % \doloop { .. \exitloop .. }
\setbox2\lastbox
\ifhbox2
- \setbox0\normalhbox{\box2\unhbox0}%
+ \setbox0\hbox{\box2\unhbox0}%
\repeat}
-\def\removehboxes
+\unexpanded\def\removehboxes
{\setbox0\lastbox
\ifhbox0
{\removehboxes}\unhbox0
@@ -1710,21 +1769,21 @@
\newdimen \lasthhboxwidth
\newskip \hhboxindent
-\def\unhhbox#1\with#2%
+\unexpanded\def\unhhbox#1\with#2%
{\bgroup
\nopenalties
\dontcomplain
\forgetall
- \setbox\unhhedbox\normalvbox{\hskip\hhboxindent\strut\unhbox#1}% => \hsize
+ \setbox\unhhedbox\vbox{\hskip\hhboxindent\strut\unhbox#1}% => \hsize
\doloop
{\setbox\hhbox\vsplit\unhhedbox to \lineheight
\ifvoid\unhhedbox
- \setbox\hhbox\normalhbox{\strut\normalhboxofvbox\hhbox}%
+ \setbox\hhbox\hbox{\strut\hboxofvbox\hhbox}%
\fi
\ht\hhbox\strutht
\dp\hhbox\strutdp
\ifzeropt\hhboxindent\else % \ifdim\hhboxindent=\zeropoint\else
- \setbox\hhbox\normalhbox{\hskip-\hhboxindent\box\hhbox}%
+ \setbox\hhbox\hbox{\hskip-\hhboxindent\box\hhbox}%
\hhboxindent\zeropoint
\fi
\global\lasthhboxwidth\wd\hhbox
@@ -1737,11 +1796,11 @@
\egroup}
\def\dohboxofvbox
- {\setbox0\normalvbox{\unvbox\scratchcounter\global\setbox1\lastbox}%
+ {\setbox0\vbox{\unvbox\scratchcounter\global\setbox1\lastbox}%
\unhbox1
\egroup}
-\def\normalhboxofvbox
+\unexpanded\def\hboxofvbox
{\bgroup
\afterassignment\dohboxofvbox
\scratchcounter=}
@@ -1753,8 +1812,8 @@
%D headers.
%D
%D \startbuffer
-%D \setbox0=\normalhbox{\input tufte \relax}
-%D \setbox2=\normalhbox{\input knuth \relax}
+%D \setbox0=\hbox{\input tufte \relax}
+%D \setbox2=\hbox{\input knuth \relax}
%D \unhhbox0\with{\ruledhbox{\box\hhbox}}
%D \hskip1em plus 1em minus 1em
%D \hhboxindent=\lasthhboxwidth
@@ -1781,21 +1840,21 @@
%D \doifcontent{pre content}{post content}{no content}\somebox
%D \stoptyping
%D
-%D Where \type{\somebox} is either a \type{\normalhbox} or
-%D \type{\normalvbox}. If the dimension of this box suggest some
+%D Where \type{\somebox} is either a \type{\hbox} or
+%D \type{\vbox}. If the dimension of this box suggest some
%D content, the resulting box is unboxed and surrounded by the
%D first two arguments, else the third arguments is executed.
\unexpanded\def\doifcontent#1#2#3%
{\dowithnextbox
{\ifhbox\nextbox
- \ifdim\nextboxwd>\zeropoint
+ \ifdim\wd\nextbox>\zeropoint
#1\unhbox\nextbox#2\relax
\else
#3\relax
\fi
\else
- \ifdim\nextboxht>\zeropoint
+ \ifdim\ht\nextbox>\zeropoint
#1\unvbox\nextbox#2\relax
\else
#3\relax
@@ -1805,11 +1864,11 @@
%D So when we say:
%D
%D \startbuffer
-%D \doifcontent{[}{]}{}\normalhbox{content sensitive typesetting}
+%D \doifcontent{[}{]}{}\hbox{content sensitive typesetting}
%D
-%D \doifcontent{}{\page}{}\normalvbox{content sensitive typesetting}
+%D \doifcontent{}{\page}{}\vbox{content sensitive typesetting}
%D
-%D \doifcontent{}{}{\message{Didn't you forget something?}}\normalhbox{}
+%D \doifcontent{}{}{\message{Didn't you forget something?}}\hbox{}
%D \stopbuffer
%D
%D \typebuffer
@@ -1827,32 +1886,60 @@
%D The next macro gobble boxes and is for instance used for
%D overlays. First we show the general handler.
-\newbox\processbox
+% we cannot use \futurelet here as we want to skip spaces between
+% boxes (see startoverlay for an example usage)
+
+% \newbox\processbox % public : this is the one where \nextbox's end up in
+%
+% \unexpanded\def\processboxes#1%
+% {\bgroup
+% \def\syst_boxes_process_indeed{#1}% #1 can be redefined halfway
+% \setbox\processbox\emptybox
+% \afterassignment\syst_boxes_process
+% \let\nexttoken}
+%
+% \def\syst_boxes_process
+% {\ifx\nexttoken\bgroup
+% \expandafter\syst_boxes_process_yes
+% \else
+% \expandafter\syst_boxes_process_nop
+% \fi}
+%
+% \def\syst_boxes_process_yes
+% {\dowithnextboxcs\syst_boxes_process_content\hbox\bgroup}
+%
+% \def\syst_boxes_process_content
+% {\removeunwantedspaces
+% \syst_boxes_process_indeed % takes \nextbox makes \processbox
+% \afterassignment\syst_boxes_process
+% \let\nexttoken}
+%
+% \unexpanded\def\syst_boxes_process_nop
+% {\removeunwantedspaces
+% \box\processbox
+% \nexttoken % messy as we are still in the group
+% \egroup}
+
+\newbox\processbox % public : this is the one where \nextbox's end up in
-\def\processboxes#1%
+\unexpanded\def\processboxes#1%
{\bgroup
- \def\doprocessbox{#1}% #1 can be redefined halfway
+ \def\syst_boxes_process_indeed{#1}% #1 can be redefined halfway
\setbox\processbox\emptybox
- \afterassignment\dogetprocessbox\let\next=}
+ \doifnextbgroupelse\syst_boxes_process_yes\syst_boxes_process_nop}
-\def\endprocessboxes
- {\ifhmode\unskip\fi
- \box\processbox
- \next
- \egroup}
+\def\syst_boxes_process_yes
+ {\dowithnextboxcs\syst_boxes_process_content\hbox}
-\def\dogetprocessbox
- {\ifx\next\bgroup
- \expandafter\dodogetprocessbox
- \else
- \expandafter\endprocessboxes
- \fi}
+\def\syst_boxes_process_content
+ {\removeunwantedspaces
+ \syst_boxes_process_indeed % takes \nextbox makes \processbox
+ \doifnextbgroupelse\syst_boxes_process_yes\syst_boxes_process_nop}
-\def\dodogetprocessbox
- {\dowithnextbox
- {\ifhmode\unskip\fi\doprocessbox % takes \nextbox makes \processbox
- \afterassignment\dogetprocessbox\let\next=}
- \normalhbox\bgroup}
+\unexpanded\def\syst_boxes_process_nop
+ {\removeunwantedspaces
+ \box\processbox
+ \egroup}
%D \macros
%D {startoverlay}
@@ -1873,38 +1960,26 @@
%D
%D \leavevmode\getbuffer
-\def\dooverlaybox
- {\ifhmode\unskip\fi
- \scratchdimen\dp
- \ifdim\nextboxdp>\dp\processbox
- \nextbox
- \else
- \processbox
- \fi
- \ifdim\nextboxht>\ht\processbox
- \setbox\processbox\normalvbox to \nextboxht
- {\dp\processbox\zeropoint\vss\box\processbox\vss}%
+\def\syst_boxes_overlay_process
+ {%\removeunwantedspaces % already done
+ \scratchdepth\dp\ifdim\dp\nextbox>\dp\processbox\nextbox\else\processbox\fi
+ \ifdim\ht\nextbox>\ht\processbox
+ \setbox\processbox\vbox to \ht\nextbox {\dp\processbox\zeropoint\vss\box\processbox\vss}%
\else
- \setbox\nextbox\normalvbox to \ht\processbox
- {\nextboxdp\zeropoint\vss\flushnextbox\vss}%
+ \setbox\nextbox \vbox to \ht\processbox{\dp\nextbox \zeropoint\vss\box\nextbox \vss}%
\fi
- \nextboxdp\scratchdimen
- \dp\processbox\scratchdimen
- \scratchdimen\wd
- \ifdim\nextboxwd>\wd\processbox
- \nextbox
- \else
- \processbox
- \fi
- \setbox\processbox\normalhbox to \scratchdimen
- {\normalhbox to \scratchdimen{\hss\box\processbox\hss}%
- \hskip-\scratchdimen
- \normalhbox to \scratchdimen{\hss\flushnextbox\hss}}}
+ \dp\nextbox \scratchdepth
+ \dp\processbox\scratchdepth
+ \scratchwidth\wd\ifdim\wd\nextbox>\wd\processbox\nextbox\else\processbox\fi
+ \setbox\processbox\hbox to \scratchwidth
+ {\hbox to \scratchwidth{\hss\box\processbox\hss}%
+ \hskip-\scratchwidth
+ \hbox to \scratchwidth{\hss\box\nextbox \hss}}}
\unexpanded\def\startoverlay
{\bgroup
\let\stopoverlay\egroup
- \processboxes\dooverlaybox}
+ \processboxes\syst_boxes_overlay_process}
\let\stopoverlay\relax
@@ -1914,24 +1989,24 @@
%D The next macro is a rather silly one, but saves space.
%D
%D \starttyping
-%D \normalhbox{\fakebox0}
+%D \hbox{\fakebox0}
%D \stoptyping
%D
%D returns an empty box with the dimensions of the box
%D specified, here being zero.
-\def\dofakebox
- {\setbox\scratchbox\emptyhbox
+\unexpanded\def\fakebox
+ {\bgroup
+ \afterassignment\syst_boxes_fakebox_finish\scratchcounter}
+
+\def\syst_boxes_fakebox_finish
+ {\setbox\scratchbox\ifhbox\scratchcounter\emptyhbox\else\emptyvbox\fi
\wd\scratchbox\wd\scratchcounter
\ht\scratchbox\ht\scratchcounter
\dp\scratchbox\dp\scratchcounter
- \ifhbox\scratchcounter\normalhbox\else\normalvbox\fi{\box\scratchbox}%
+ \box\scratchbox
\egroup}
-\def\fakebox
- {\bgroup
- \afterassignment\dofakebox\scratchcounter}
-
%D \macros
%D {lbox,rbox,cbox,tbox,bbox}
%D
@@ -1943,21 +2018,20 @@
%D \rbox{text ...}
%D \stoptyping
%D
-%D Are similar to \type {\normalvbox}, which means that they also
+%D Are similar to \type {\vbox}, which means that they also
%D accept something like \type{to 3cm}, but align to the left,
%D middle and right. These box types can be used to typeset
%D paragraphs.
-\def\lbox{\makelrcbox\normalvbox\raggedleft}
-\def\cbox{\makelrcbox\normalvbox\raggedcenter}
-\def\rbox{\makelrcbox\normalvbox\raggedright}
+\def\syst_boxes_lrc_process#1{\bgroup\forgetall\let\\\endgraf#1\let\next}
-\def\ltop{\makelrcbox\normalvtop\raggedleft}
-\def\ctop{\makelrcbox\normalvtop\raggedcenter}
-\def\rtop{\makelrcbox\normalvtop\raggedright}
+\unexpanded\def\lbox#1#{\vbox#1\syst_boxes_lrc_process\raggedleft }
+\unexpanded\def\cbox#1#{\vbox#1\syst_boxes_lrc_process\raggedcenter}
+\unexpanded\def\rbox#1#{\vbox#1\syst_boxes_lrc_process\raggedright }
-\def\makelrcbox#1#2#3#%
- {#1#3\bgroup \forgetall \let\\=\endgraf #2\let\next=}
+\unexpanded\def\ltop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedleft }
+\unexpanded\def\ctop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedcenter}
+\unexpanded\def\rtop#1#{\normalvtop#1\syst_boxes_lrc_process\raggedright }
%D The alternatives \type {\tbox} and \type {\bbox} can be used
%D to properly align boxes, like in:
@@ -1979,34 +2053,41 @@
%D
%D \getbuffer
-\def\tbox{\tbbox\ht\dp}
-\def\bbox{\tbbox\dp\ht}
+\unexpanded\def\tbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_tbox_finish\hbox}
+\unexpanded\def\bbox{\hbox\bgroup\dowithnextboxcs\syst_boxes_bbox_finish\hbox}
+
+\def\syst_boxes_tbox_finish
+ {\scratchdepth\dimexpr\ht\nextbox+\dp\nextbox-\ht\strutbox\relax
+ \ht\nextbox\ht\strutbox
+ \dp\nextbox\scratchdepth
+ \setbox\nextbox\hbox{\lower\dp\nextbox\box\nextbox}%
+ \ht\nextbox\ht\strutbox
+ \dp\nextbox\scratchdepth
+ \box\nextbox
+ \egroup}
-\def\tbbox#1#2%
- {\normalhbox\bgroup
- \dowithnextbox
- {\scratchdimen\dimexpr\nextboxht+\nextboxdp-#1\strutbox\relax
- #1\nextbox#1\strutbox
- #2\nextbox\scratchdimen
- \setbox\nextbox\normalhbox{\lower\nextboxdp\flushnextbox}%
- #1\nextbox#1\strutbox
- #2\nextbox\scratchdimen
- \flushnextbox
- \egroup}
- \normalhbox}
+\def\syst_boxes_bbox_finish
+ {\scratchheight\dimexpr\ht\nextbox+\dp\nextbox-\dp\strutbox\relax
+ \dp\nextbox\dp\strutbox
+ \ht\nextbox\scratchheight
+ \setbox\nextbox\hbox{\lower\dp\nextbox\box\nextbox}%
+ \dp\nextbox\dp\strutbox
+ \ht\nextbox\scratchheight
+ \box\nextbox
+ \egroup}
%D \macros
%D {lhbox,mhbox,rhbox}
%D
%D A few more boxes.
-\def\dodolhbox{\normalhbox to \hsize{\flushnextbox\hss }}
-\def\dodomhbox{\normalhbox to \hsize{\hss\flushnextbox\hss}}
-\def\dodorhbox{\normalhbox to \hsize{\hss\flushnextbox }}
+\def\dodolhbox{\hbox to \hsize{\box\nextbox\hss }}
+\def\dodomhbox{\hbox to \hsize{\hss\box\nextbox\hss}}
+\def\dodorhbox{\hbox to \hsize{\hss\box\nextbox }}
-\def\lhbox{\dowithnextboxcs\dodolhbox\normalhbox}
-\def\mhbox{\dowithnextboxcs\dodomhbox\normalhbox}
-\def\rhbox{\dowithnextboxcs\dodorhbox\normalhbox}
+\unexpanded\def\lhbox{\dowithnextboxcs\dodolhbox\hbox}
+\unexpanded\def\mhbox{\dowithnextboxcs\dodomhbox\hbox}
+\unexpanded\def\rhbox{\dowithnextboxcs\dodorhbox\hbox}
\let\lefthbox \lhbox
\let\midhbox \mhbox
@@ -2020,7 +2101,7 @@
%D additions, we can use:
%D
%D \starttyping
-%D \boxofsize \normalvbox 10cm 3cm -5cm {the text to be typeset}
+%D \boxofsize \vbox 10cm 3cm -5cm {the text to be typeset}
%D \stoptyping
%D
%D This example demonstrates that one can use positive and
@@ -2028,7 +2109,7 @@
\newdimen\sizeofbox
-\def\boxofsize#1%
+\unexpanded\def\boxofsize#1%
{\bgroup
\sizeofbox\zeropoint
\scratchdimen\zeropoint
@@ -2050,25 +2131,25 @@
% \limitvbox
% \limithbox
-\def\limitatelines#1#2% size sentinel
+\unexpanded\def\limitatelines#1#2% size sentinel
{\dowithnextbox
{\dimen0=#1\hsize
- \ifdim\nextboxwd>\dimen0
- \setbox\nextbox\normalhbox
+ \ifdim\wd\nextbox>\dimen0
+ \setbox\nextbox\hbox
{\advance\dimen0 -.1\hsize
\limitatetext{\unhbox\nextbox}{\dimen0}{\nobreak#2}}%
\fi
\unhbox\nextbox}
- \normalhbox}
+ \hbox}
-\def\fittoptobaselinegrid % weg hier
+\unexpanded\def\fittoptobaselinegrid % weg hier
{\dowithnextbox
{\bgroup
\par
- \dimen0\nextboxht
- \nextboxht\strutht
- \nextboxdp\strutdp
- \normalhbox{\flushnextbox}
+ \dimen0\ht\nextbox
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \hbox{\box\nextbox}
\prevdepth\strutdp
\doloop
{\advance\dimen0 -\lineheight
@@ -2076,10 +2157,10 @@
\exitloop
\else
\nobreak
- \normalhbox{\strut}
+ \hbox{\strut}
\fi}
\egroup}
- \normalvbox}
+ \vbox}
%D Some more undocumented macros (used in m-chart).
@@ -2087,14 +2168,14 @@
\newbox\fakedboxcursor
-\setbox\fakedboxcursor\normalhbox
+\setbox\fakedboxcursor\hbox
{\vrule\!!width\zeropoint\!!height\zeropoint\!!depth\zeropoint}
-\def\boxcursor % overloaded in core-vis
+\unexpanded\def\boxcursor % overloaded in core-vis
{\iftraceboxplacement
\bgroup
- \scratchdimen2pt
- \setbox\scratchbox\normalhbox to \zeropoint
+ \scratchdimen2\onepoint
+ \setbox\scratchbox\hbox to \zeropoint
{\hss
\vrule
\!!width \scratchdimen
@@ -2107,120 +2188,128 @@
\copy\fakedboxcursor
\fi}
-\def\placedbox
- {\iftraceboxplacement\ruledhbox\else\normalhbox\fi}
+\unexpanded\def\placedbox
+ {\iftraceboxplacement\ruledhbox\else\hbox\fi}
\newdimen\boxoffset
\newdimen\boxhdisplacement
\newdimen\boxvdisplacement
-\def\rightbox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement\boxoffset
- \global\boxvdisplacement.5\ht\scratchbox
- \global\advance\boxvdisplacement-.5\dp\scratchbox
- \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\scratchbox}}
-
-\def\leftbox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement-\wd\scratchbox
- \global\advance\boxhdisplacement-\boxoffset
- \global\boxvdisplacement.5\ht\scratchbox
- \global\advance\boxvdisplacement-.5\dp\scratchbox
- \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\scratchbox}}
-
-\def\topbox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement-.5\wd\scratchbox
- \global\boxvdisplacement-\dp\scratchbox
- \global\advance\boxvdisplacement-\boxoffset
- \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\scratchbox}}
-
-\def\bottombox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement-.5\wd\scratchbox
- \global\boxvdisplacement\ht\scratchbox
- \global\advance\boxvdisplacement\boxoffset
- \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\scratchbox}}
-
-\def\lefttopbox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement-\wd\scratchbox
- \global\advance\boxhdisplacement-\boxoffset
- \global\boxvdisplacement-\dp\scratchbox
- \global\advance\boxvdisplacement-\boxoffset
- \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\scratchbox}}
-
-\def\righttopbox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement\boxoffset
- \global\boxvdisplacement-\dp\scratchbox
- \global\advance\boxvdisplacement-\boxoffset
- \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\scratchbox}}
-
-\def\leftbottombox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement-\wd\scratchbox
- \global\advance\boxhdisplacement-\boxoffset
- \global\boxvdisplacement\ht\scratchbox
- \global\advance\boxvdisplacement\boxoffset
- \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\scratchbox}}
-
-\def\rightbottombox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement\boxoffset
- \global\boxvdisplacement\ht\scratchbox
- \global\advance\boxvdisplacement\boxoffset
- \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\scratchbox}}
+\unexpanded\def\rightbox {\hbox\bgroup\dowithnextboxcs\syst_boxes_rightbox_finish \placedbox}
+\unexpanded\def\leftbox {\hbox\bgroup\dowithnextboxcs\syst_boxes_leftbox_finish \placedbox}
+\unexpanded\def\topbox {\hbox\bgroup\dowithnextboxcs\syst_boxes_topbox_finish \placedbox}
+\unexpanded\def\bottombox {\hbox\bgroup\dowithnextboxcs\syst_boxes_bottombox_finish \placedbox}
+\unexpanded\def\lefttopbox {\hbox\bgroup\dowithnextboxcs\syst_boxes_lefttopbox_finish \placedbox}
+\unexpanded\def\righttopbox {\hbox\bgroup\dowithnextboxcs\syst_boxes_righttopbox_finish \placedbox}
+\unexpanded\def\leftbottombox {\hbox\bgroup\dowithnextboxcs\syst_boxes_leftbottombox_finish \placedbox}
+\unexpanded\def\rightbottombox{\hbox\bgroup\dowithnextboxcs\syst_boxes_rightbottombox_finish\placedbox}
\let\topleftbox \lefttopbox
\let\toprightbox \righttopbox
\let\bottomleftbox \leftbottombox
\let\bottomrightbox\rightbottombox
-\def\middlebox#1%
- {\normalhbox{\setbox\scratchbox\placedbox{#1}\boxoffset=-.5\wd\scratchbox\rightbox{\box\scratchbox}}}
-
-\def\baselinemiddlebox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement-.5\wd\scratchbox
- \global\advance\boxhdisplacement-\boxoffset
- \global\boxvdisplacement-\boxoffset
- \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\scratchbox}}
-
-\def\baselineleftbox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement-\wd\scratchbox
- \global\advance\boxhdisplacement-\boxoffset
- \global\boxvdisplacement-\boxoffset
- \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\scratchbox}}
-
-\def\baselinerightbox#1%
- {\normalhbox
- {\setbox\scratchbox\placedbox{#1}%
- \global\boxhdisplacement\boxoffset
- \global\boxvdisplacement-\boxoffset
- \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\scratchbox}}
+\def\syst_boxes_rightbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_leftbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_topbox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_bottombox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_lefttopbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_righttopbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement-\dp\nextbox
+ \global\advance\boxvdisplacement-\boxoffset
+ \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_leftbottombox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_rightbottombox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement\ht\nextbox
+ \global\advance\boxvdisplacement\boxoffset
+ \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\unexpanded\def\middlebox {\hbox\bgroup\dowithnextboxcs\syst_boxes_middlebox_finish \placedbox}
+\unexpanded\def\baselinemiddlebox{\hbox\bgroup\dowithnextboxcs\syst_boxes_baselinemiddlebox_finish\placedbox}
+\unexpanded\def\baselineleftbox {\hbox\bgroup\dowithnextboxcs\syst_boxes_baselineleftbox_finish \placedbox}
+\unexpanded\def\baselinerightbox {\hbox\bgroup\dowithnextboxcs\syst_boxes_baselinerightbox_finish \placedbox}
+
+\def\syst_boxes_middlebox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\boxvdisplacement.5\ht\nextbox
+ \global\advance\boxvdisplacement-.5\dp\nextbox
+ \boxcursor\hskip\boxhdisplacement\lower\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselinemiddlebox_finish
+ {\global\boxhdisplacement-.5\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselineleftbox_finish
+ {\global\boxhdisplacement-\wd\nextbox
+ \global\advance\boxhdisplacement-\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
+
+\def\syst_boxes_baselinerightbox_finish
+ {\global\boxhdisplacement\boxoffset
+ \global\boxvdisplacement-\boxoffset
+ \boxcursor\hskip\boxhdisplacement\raise-\boxvdisplacement\box\nextbox
+ \egroup}
%D \macros
%D {obox}
%D
%D Experimental, not yet frozen:
-\def\lrtbbox#1#2#3#4% l r t b
+\unexpanded\def\lrtbbox#1#2#3#4% l r t b
{\bgroup
\dowithnextboxcontent
- {\advance\hsize-#1\advance\hsize-#2\advance\vsize-#3\advance\vsize-#4\relax}
+ {\advance\hsize-#1\advance\hsize-#2\relax
+ \advance\vsize-#3\advance\vsize-#4\relax}
{\forgetall\vbox to \vsize{\vskip#3\hbox to \hsize{\hskip#1\box\nextbox\hss}\vss}\egroup}
\vbox}
@@ -2229,18 +2318,19 @@
%D
%D See core-tbl.tex for an example of its usage:
-\def\toplinebox
- {\dowithnextbox
- {\ifdim\nextboxdp>\strutdepth
- \scratchdimen\nextboxdp
- \advance\scratchdimen-\strutdepth
- \getnoflines\scratchdimen
- \struttedbox{\flushnextbox}%
- \dorecurse\noflines\verticalstrut
- \else
- \flushnextbox
- \fi}%
- \tbox}
+\unexpanded\def\toplinebox
+ {\dowithnextboxcs\syst_boxes_toplinebox_finish\tbox}
+
+\def\syst_boxes_toplinebox_finish
+ {\ifdim\dp\nextbox>\strutdepth
+ \scratchdimen\dp\nextbox
+ \advance\scratchdimen-\strutdepth
+ \getnoflines\scratchdimen
+ \struttedbox{\box\nextbox}%
+ \dorecurse\noflines\verticalstrut
+ \else
+ \box\nextbox
+ \fi}
%D \macros
%D {initializeboxstack,savebox,foundbox}
@@ -2255,30 +2345,30 @@
%D \savebox{one}{p}{test p}
%D \savebox{one}{q}{test q}
%D
-%D \normalhbox{a:\foundbox{one}{a}} \par
-%D \normalhbox{q:\foundbox{one}{q}} \par
-%D \normalhbox{p:\foundbox{one}{p}} \par
-%D \normalhbox{x:\foundbox{one}{x}} \par
-%D \normalhbox{y:\foundbox{two}{a}} \par
+%D \hbox{a:\foundbox{one}{a}} \par
+%D \hbox{q:\foundbox{one}{q}} \par
+%D \hbox{p:\foundbox{one}{p}} \par
+%D \hbox{x:\foundbox{one}{x}} \par
+%D \hbox{y:\foundbox{two}{a}} \par
%D \stoptyping
\def\@@stackbox{@box@}
\def\@@stacklst{@xob@}
-\def\setstackbox#1#2%
+\unexpanded\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\normalvbox}
+ \global\setbox\csname\@@stackbox:#1:#2\endcsname\vbox}
-\def\initializeboxstack#1%
+\unexpanded\def\initializeboxstack#1%
{\def\docommand##1{\setstackbox{#1}{##1}{}}%
\ifcsname\@@stacklst#1\endcsname
\processcommacommand[\getvalue{\@@stacklst#1}]\docommand
\fi
\letgvalueempty{\@@stacklst#1}}
-\def\savebox#1#2% stack name
+\unexpanded\def\savebox#1#2% stack name
{% beware, \setxvalue defines the cs beforehand so we cannot use the
% test inside the { }
\ifcsname\@@stacklst#1\endcsname
@@ -2288,13 +2378,13 @@
\fi
\setstackbox{#1}{#2}}
-\def\foundbox#1#2%
- {\normalvbox
+\unexpanded\def\foundbox#1#2%
+ {\vbox
{\ifcsname\@@stackbox:#1:#2\endcsname
\copy\csname\@@stackbox:#1:#2\endcsname
\fi}}
-\long\def\doifboxelse#1#2#3#4%
+\unexpanded\def\doifboxelse#1#2#3#4%
{\ifcsname\@@stackbox:#1:#2\endcsname
\ifvoid\csname\@@stackbox:#1:#2\endcsname#4\else#3\fi
\else
@@ -2308,25 +2398,34 @@
%D \type {\obeydepth} makes sure we have depth. Both macros
%D leave the \type {\prevdepth} untouched.
-\def\removedepth
- {\ifvmode \ifdim\prevdepth>\zeropoint \kern-\prevdepth \fi \fi}
+\unexpanded\def\removedepth
+ {\ifvmode
+ \ifdim\prevdepth>\zeropoint
+ \kern-\prevdepth
+ \fi
+ \fi}
-\def\obeydepth
- {\par \removedepth \ifvmode \kern\strutdp \fi}
+\unexpanded\def\obeydepth
+ {\par
+ \ifvmode
+ \ifdim\prevdepth>\zeropoint
+ \kern-\prevdepth
+ \fi
+ \kern\strutdp
+ \fi}
-\def\undepthed
- {\dowithnextbox{\nextboxdp\zeropoint\flushnextbox}\hbox}
+\unexpanded\def\undepthed
+ {\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\hbox}
%D \macros
%D {removebottomthings, removelastskip}
%D
%D A funny (but rather stupid) one, plus a redefinition.
-\def\removebottomthings
+\unexpanded\def\removebottomthings
{\dorecurse5{\unskip\unkern\unpenalty}}
-\def\removelastskip % \ifvmode the plain tex one \fi
-% {\ifvmode\ifdim\lastskip=\zeropoint\else\vskip-\lastskip\fi\fi}
+\unexpanded\def\removelastskip % \ifvmode the plain tex one \fi
{\ifvmode\ifzeropt\lastskip\else\vskip-\lastskip\fi\fi}
%D \macros
@@ -2336,12 +2435,12 @@
%D strut.
\def\domakestrutofbox
- {\ht\registercount\strutht
- \dp\registercount\strutdp
- \wd\registercount\zeropoint}
+ {\ht\c_boxes_register\strutht
+ \dp\c_boxes_register\strutdp
+ \wd\c_boxes_register\zeropoint}
-\def\makestrutofbox
- {\afterassignment\domakestrutofbox\registercount}
+\unexpanded\def\makestrutofbox
+ {\afterassignment\domakestrutofbox\c_boxes_register}
%D \macros
%D {raisebox,lowerbox}
@@ -2351,49 +2450,67 @@
%D article.
%D
%D \starttyping
-%D \raisebox{100pt}\normalhbox{test}
-%D \raisebox50pt\normalhbox{test}
-%D \hsmash{\raisebox{100pt}\normalhbox{test}}
+%D \raisebox{100pt}\hbox{test}
+%D \hsmash{\raisebox{100pt}\hbox{test}}
%D \stoptyping
-\def\doraiselowerbox#1#2% a nice trick us used to accept
- {\def\next % both direct and {} dimensions
- {\dowithnextbox
- {\setbox\nextbox\normalhbox{#1\scratchdimen\flushnextbox}%
- \nextboxht\strutht
- \nextboxdp\strutdp
- \flushnextbox}}%
- \afterassignment\next\scratchdimen=#2}
+\unexpanded\def\raisebox#1{\bgroup\afterassignment\syst_boxes_raise_indeed\scratchdimen#1} % so both 10pt and {10pt} is accepted
+\unexpanded\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}
+
+\def\syst_boxes_raise_finish
+ {\setbox\nextbox\hbox{\raise\scratchdimen\box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}
-\def\raisebox{\doraiselowerbox\raise}
-\def\lowerbox{\doraiselowerbox\lower}
+\def\syst_boxes_lower_finish
+ {\setbox\nextbox\hbox{\lower\scratchdimen\box\nextbox}%
+ \ht\nextbox\strutht
+ \dp\nextbox\strutdp
+ \box\nextbox
+ \egroup}
% vcenter in text, we kunnen vcenter overloaden
-\def\halfwaybox
- {\dowithnextbox
- {\nextboxdp\zeropoint
- \setbox\nextbox\normalhbox{\lower.5\nextboxht\flushnextbox}%
- \flushnextbox}
- \normalhbox}
+\unexpanded\def\halfwaybox
+ {\hbox\bgroup
+ \dowithnextboxcs\syst_boxes_halfwaybox_finish\hbox}
+
+\def\syst_boxes_halfwaybox_finish
+ {\dp\nextbox\zeropoint
+ \lower.5\ht\nextbox\box\nextbox
+ \egroup}
+
+\unexpanded\def\depthonlybox
+ {\vtop\bgroup
+ \dowithnextboxcs\syst_boxes_depthonlybox_finish\vbox}
+
+\def\syst_boxes_depthonlybox_finish
+ {\hsize\wd\nextbox
+ \kern\zeropoint\box\nextbox
+ \egroup}
%D New:
-\def\setdimentoatleast#1#2%
- {\ifdim#1>\zeropoint\else#1=#2\fi}
+\def\setdimentoatleast#1#2{\ifdim#1>\zeropoint\else#1=#2\fi}
+\def\setdimentoatmost #1#2{\ifdim#1>#2\relax \else#1=#2\fi}
%D And even rawer:
-\let\naturalhbox \normalhbox
-\let\naturalvbox \normalvbox
-\let\naturalvtop \normalvtop
-\let\naturalvcenter \normalvtop
+\let\naturalhbox \hbox
+\let\naturalvbox \vbox
+\let\naturalvtop \normalvtop
+\let\naturalvcenter\normalvtop
\ifdefined\textdir
- \def\naturalhbox{\normalhbox dir TLT}
- \def\naturalvbox{\normalvbox dir TLT}
- %def\naturalvtop{\normalvtop dir TLT}
+ \unexpanded\def\naturalhbox{\hbox dir TLT}
+ \unexpanded\def\naturalvbox{\vbox dir TLT}
+ %\unexpanded\def\naturalvtop{\normalvtop dir TLT}
\fi
@@ -2402,39 +2519,50 @@
%D
%D Also new: tex mode \type {\vcenter}.
-\let\verynormalvcenter \vcenter % since \vcenter can be visualized
+\unexpanded\def\vcenter
+ {\vbox\bgroup
+ \dowithnextboxcs\syst_boxes_vcenter_finish\vbox}
-\def\vcenter
- {\normalvbox\bgroup
- \dowithnextbox{\normalhbox{$\verynormalvcenter{\flushnextbox}$}\egroup}
- \normalvbox}
+\def\syst_boxes_vcenter_finish
+ {\hbox{$\normalvcenter{\box\nextbox}$}%
+ \egroup}
% could be \everymathematics
\prependtoks \let\vcenter\normalvcenter \to \everymath
\prependtoks \let\vcenter\normalvcenter \to \everydisplay
+% \appendtoks \let\vcenter\normalvcenter \to \everymathematics
+
%D \macros
%D {frozenhbox}
%D
-%D A not so well unhboxable bxo can be made with:
+%D A not so well unhboxable box can be made with:
+
+\unexpanded\def\frozenhbox
+ {\hbox\bgroup
+ \dowithnextboxcs\syst_boxes_frozenhbox_finish\hbox}
-\def\frozenhbox
- {\hbox\bgroup\dowithnextbox{\hbox{\hbox{\flushnextbox}}\egroup}\hbox}
+\def\syst_boxes_frozenhbox_finish
+ {\hbox{\hbox{\box\nextbox}}%
+ \egroup}
%D \macros
%D {setboxllx,setboxlly,gsetboxllx,gsetboxlly,getboxllx,getboxlly}
%D
%D A prelude to an extended \TEX:
-\def\setboxllx#1#2{\setevalue{b@@x\number#1}{\the\dimexpr#2\relax}}
-\def\setboxlly#1#2{\setevalue{b@@y\number#1}{\the\dimexpr#2\relax}}
+\unexpanded\def\setboxllx #1#2{\expandafter\edef\csname boxes_x_\number#1\endcsname{\the\dimexpr#2\relax}}
+\unexpanded\def\setboxlly #1#2{\expandafter\edef\csname boxes_y_\number#1\endcsname{\the\dimexpr#2\relax}}
-\def\gsetboxllx{\global\setboxllx}
-\def\gsetboxlly{\global\setboxlly}
+\unexpanded\def\gsetboxllx#1#2{\expandafter\xdef\csname boxes_x_\number#1\endcsname{\the\dimexpr#2\relax}}
+\unexpanded\def\gsetboxlly#1#2{\expandafter\xdef\csname boxes_y_\number#1\endcsname{\the\dimexpr#2\relax}}
-\def\getboxllx#1{\executeifdefined{b@@x\number#1}\zeropoint}
-\def\getboxlly#1{\executeifdefined{b@@y\number#1}\zeropoint}
+\def\getboxllx#1{\ifcsname boxes_x_\number#1\endcsname\csname boxes_x_\number#1\endcsname\else\zeropoint\fi}
+\def\getboxlly#1{\ifcsname boxes_y_\number#1\endcsname\csname boxes_y_\number#1\endcsname\else\zeropoint\fi}
+
+\def\directgetboxllx#1{\csname boxes_x_\number#1\endcsname} % use when sure existence
+\def\directgetboxlly#1{\csname boxes_y_\number#1\endcsname} % use when sure existence
%D \macros
%D {shownextbox}
@@ -2449,7 +2577,7 @@
%D \shownextbox\vbox{\setupwhitespace[big]test\endgraf\thinrule}
%D \stoptyping
-\def\shownextbox
+\unexpanded\def\shownextbox % seldom used
{\dowithnextbox
{\bgroup
\showboxbreadth\maxdimen
@@ -2461,7 +2589,7 @@
\interactionmode\scratchcounter
\egroup}}
-\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>}
+\unexpanded\def\spreadhbox#1% rebuilds \hbox{<box><hss><box><hss><box>}
{\bgroup
\ifhbox#1\relax
\setbox2\emptybox
@@ -2499,3 +2627,48 @@
\ruledvbox to \strutheight{\hbox{\strut gans}}
\ruledvbox to \strutheight{\vss\hbox{gans}}
\egroup
+
+% to be considered
+
+% \startluacode
+%
+% local spacer = lpeg.patterns.spacer
+%
+% function commands.withwords(command,str)
+% if str then
+% command = command or "ruledhbox"
+% local done = false
+% local function apply(s)
+% if done then
+% context.space()
+% done = true
+% else
+% context.dontleavehmode()
+% end
+% context[command](s)
+% end
+% lpeg.match(lpeg.splitter(spacer,apply),str)
+% end
+%
+% end
+%
+% \stopluacode
+%
+% \unprotect
+%
+% \unexpanded\def\withwordsinstring#1#2% command str
+% {\ctxcommand{withwords(\!!bs#1\!!es,\!!bs#2\!!es)}}
+%
+% \unexpanded\def\withwordsinfile#1#2% command name
+% {\ctxcommand{withwords(\!!bs#1\!!es,io.loaddata(resolvers.findfile("#2")))}}
+%
+% \protect
+%
+% \starttext
+%
+% \defineframed[colored][foregroundcolor=red,foregroundstyle=\bfc\underbar,location=low]
+%
+% \withwordsinstring{colored}{bla bla}
+% \withwordsinfile{colored}{ward.tex}
+%
+% \stoptext
diff --git a/Master/texmf-dist/tex/context/base/supp-dir.mkii b/Master/texmf-dist/tex/context/base/supp-dir.mkii
index 41cd1b56fae..f4f2949035b 100644
--- a/Master/texmf-dist/tex/context/base/supp-dir.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-dir.mkii
@@ -5,7 +5,7 @@
%D subtitle=Directional Things,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-dir.mkiv b/Master/texmf-dist/tex/context/base/supp-dir.mkiv
index dce47a1784d..6251012b6a1 100644
--- a/Master/texmf-dist/tex/context/base/supp-dir.mkiv
+++ b/Master/texmf-dist/tex/context/base/supp-dir.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Directional Things,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-emp.mkii b/Master/texmf-dist/tex/context/base/supp-emp.mkii
index 15489bca783..ba9e09e3a4c 100644
--- a/Master/texmf-dist/tex/context/base/supp-emp.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-emp.mkii
@@ -5,7 +5,7 @@
%D subtitle=\EMTEX\ specials to \PDF\ conversion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-eps.mkii b/Master/texmf-dist/tex/context/base/supp-eps.mkii
index 5684b25dd5c..fb99469c5d6 100644
--- a/Master/texmf-dist/tex/context/base/supp-eps.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-eps.mkii
@@ -5,7 +5,7 @@
%D subtitle=\EPS\ tools,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-fil.lua b/Master/texmf-dist/tex/context/base/supp-fil.lua
deleted file mode 100644
index a2c0b5d7daa..00000000000
--- a/Master/texmf-dist/tex/context/base/supp-fil.lua
+++ /dev/null
@@ -1,334 +0,0 @@
-if not modules then modules = { } end modules ['supp-fil'] = {
- version = 1.001,
- comment = "companion to supp-fil.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
--- This module will be redone !
-
--- context is not defined yet! todo! (we need to load tupp-fil after cld)
--- todo: move startreadingfile to lua and push regime there
-
---[[ldx--
-<p>It's more convenient to manipulate filenames (paths) in
-<l n='lua'/> than in <l n='tex'/>. These methods have counterparts
-at the <l n='tex'/> side.</p>
---ldx]]--
-
-local find, gsub, match, format, concat = string.find, string.gsub, string.match, string.format, table.concat
-local texcount = tex.count
-local isfile = lfs.isfile
-
-local trace_modules = false trackers.register("modules.loading", function(v) trace_modules = v end)
-local trace_files = false trackers.register("resolvers.readfile", function(v) trace_files = v end)
-
-local report_modules = logs.reporter("resolvers","modules")
-local report_files = logs.reporter("files","readfile")
-
-commands = commands or { }
-local commands = commands
-environment = environment or { }
-local environment = environment
-
-local findbyscheme = resolvers.finders.byscheme
-
-function commands.checkfilename(str) -- "/whatever..." "c:..." "http://..."
- texcount.kindoffile = (find(str,"^/") or find(str,"[%a]:") and 1) or 0
-end
-
-function commands.thesanitizedfilename(str)
- context((gsub(str,"\\","/")))
-end
-
-local testcase = commands.testcase
-
-function commands.splitfilename(fullname)
- local path, name, base, suffix = '', fullname, fullname, ''
- local p, n = match(fullname,"^(.+)/(.-)$")
- if p and n then
- path, name, base = p, n, n
- end
- local b, s = match(base,"^(.+)%.(.-)$")
- if b and s then
- name, suffix = b, s
- end
- texcount.splitoffkind = (path == "" and 0) or (path == '.' and 1) or 2
- local setvalue = context.setvalue
- setvalue("splitofffull", fullname)
- setvalue("splitoffpath", path)
- setvalue("splitoffbase", base)
- setvalue("splitoffname", name)
- setvalue("splitofftype", suffix)
-end
-
-function commands.splitfiletype(fullname)
- local name, suffix = fullname, ''
- local n, s = match(fullname,"^(.+)%.(.-)$")
- if n and s then
- name, suffix = n, s
- end
- local setvalue = context.setvalue
- setvalue("splitofffull", fullname)
- setvalue("splitoffpath", "")
- setvalue("splitoffname", name)
- setvalue("splitofftype", suffix)
-end
-
-function commands.doifparentfileelse(n)
- testcase(n == environment.jobname or n == environment.jobname .. '.tex' or n == environment.outputfilename)
-end
-
--- saves some .15 sec on 12 sec format generation
-
-local lastexistingfile = ""
-
-function commands.doiffileexistelse(name)
- if not name or name == "" then
- lastexistingfile = ""
- else
- lastexistingfile = resolvers.findtexfile(name) or ""
- end
- return testcase(lastexistingfile ~= "")
-end
-
-function commands.lastexistingfile()
- context(lastexistingfile)
-end
-
--- more, we can cache matches
-
-local finders, loaders, openers = resolvers.finders, resolvers.loaders, resolvers.openers
-
-local found = { } -- can best be done in the resolver itself
-
--- todo: tracing
-
-local function readfilename(specification,backtrack,treetoo)
- local name = specification.filename
- local fnd = found[name]
- if not fnd then
- if isfile(name) then
- if trace_files then
- report_files("found local: %s",name)
- end
- fnd = name
- end
- if not fnd and backtrack then
- local fname = name
- for i=1,backtrack,1 do
- fname = "../" .. fname
- if isfile(fname) then
- if trace_files then
- report_files("found by backtracking: %s",fname)
- end
- fnd = fname
- break
- elseif trace_files then
- report_files("not found by backtracking: %s",fname)
- end
- end
- end
- if not fnd and treetoo then
- fnd = resolvers.findtexfile(name) or ""
- if trace_files then
- if fnd ~= "" then
- report_files("found by tree lookup: %s",fnd)
- else
- report_files("not found by tree lookup: %s",name)
- end
- end
- end
- found[name] = fnd
- elseif trace_files then
- if fnd ~= "" then
- report_files("already found: %s",fnd)
- else
- report_files("already not found: %s",name)
- end
- end
- return fnd or ""
-end
-
-function commands.readfilename(filename)
- return findbyscheme("any",filename)
-end
-
-function finders.job(specification) return readfilename(specification,false,false) end -- current path, no backtracking
-function finders.loc(specification) return readfilename(specification,2, false) end -- current path, backtracking
-function finders.sys(specification) return readfilename(specification,false,true ) end -- current path, obeys tex search
-function finders.fix(specification) return readfilename(specification,2, false) end -- specified path, backtracking
-function finders.set(specification) return readfilename(specification,false,false) end -- specified path, no backtracking
-function finders.any(specification) return readfilename(specification,2, true ) end -- loc job sys
-
-openers.job = openers.file loaders.job = loaders.file -- default anyway
-openers.loc = openers.file loaders.loc = loaders.file
-openers.sys = openers.file loaders.sys = loaders.file
-openers.fix = openers.file loaders.fix = loaders.file
-openers.set = openers.file loaders.set = loaders.file
-openers.any = openers.file loaders.any = loaders.file
-
-function finders.doreadfile(scheme,path,name) -- better do a split and then pass table
- local fullname
- if url.hasscheme(name) then
- fullname = name
- else
- fullname = ((path == "") and format("%s:///%s",scheme,name)) or format("%s:///%s/%s",scheme,path,name)
- end
- return resolvers.findtexfile(fullname) or "" -- can be more direct
-end
-
-function commands.doreadfile(scheme,path,name)
- context(finders.doreadfile(scheme,path,name))
-end
-
--- modules can have a specific suffix or can specify one
-
-local prefixes = { "m", "p", "s", "x", "v", "t" }
-local suffixes = { "mkiv", "tex", "mkvi" } -- order might change and how about cld
-local modstatus = { }
-
-local function usemodule(name,hasscheme)
- local foundname
- if hasscheme then
- -- no auto suffix as http will return a home page or error page
- -- so we only add one if missing
- local fullname = file.addsuffix(name,"tex")
- if trace_modules then
- report_modules("checking url: '%s'",fullname)
- end
- foundname = resolvers.findtexfile(fullname) or ""
- elseif file.extname(name) ~= "" then
- if trace_modules then
- report_modules("checking file: '%s'",name)
- end
- foundname = findbyscheme("any",name) or ""
- else
- for i=1,#suffixes do
- local fullname = file.addsuffix(name,suffixes[i])
- if trace_modules then
- report_modules("checking file: '%s'",fullname)
- end
- foundname = findbyscheme("any",fullname) or ""
- if foundname ~= "" then
- break
- end
- end
- end
- if foundname ~= "" then
- if trace_modules then
- report_modules("loading: '%s'",foundname)
- end
- context.startreadingfile()
- context.input(foundname)
- context.stopreadingfile()
- return true
- else
- return false
- end
-end
-
-function commands.usemodules(prefix,askedname,truename)
- local hasprefix = prefix and prefix ~= ""
- local hashname = ((hasprefix and prefix) or "*") .. "-" .. truename
- local status = modstatus[hashname]
- if status == 0 then
- -- not found
- elseif status == 1 then
- status = status + 1
- else
- if trace_modules then
- report_modules("locating: '%s'",truename)
- end
- local hasscheme = url.hasscheme(truename)
- if hasscheme then
- -- no prefix and suffix done
- if usemodule(truename,true) then
- status = 1
- else
- status = 0
- end
- elseif hasprefix then
- if usemodule(prefix .. "-" .. truename) then
- status = 1
- else
- status = 0
- end
- else
- for i=1,#prefixes do
- -- todo: reconstruct name i.e. basename
- local thename = prefixes[i] .. "-" .. truename
- if usemodule(thename) then
- status = 1
- break
- end
- end
- if status then
- -- ok, don't change
- elseif usemodule(truename) then
- status = 1
- else
- status = 0
- end
- end
- end
- if status == 0 then
- report_modules("not found: '%s'",askedname)
- elseif status == 1 then
- report_modules("loaded: '%s'",trace_modules and truename or askedname)
- else
- report_modules("already loaded: '%s'",trace_modules and truename or askedname)
- end
- modstatus[hashname] = status
-end
-
-local loaded = { }
-
-function commands.uselibrary(name,patterns,action,failure)
- local files = utilities.parsers.settings_to_array(name)
- local done = false
- for i=1,#files do
- local filename = files[i]
- if not loaded[filename] then
- loaded[filename] = true
- for i=1,#patterns do
- local filename = format(patterns[i],filename)
- -- local foundname = resolvers.findfile(filename) or ""
- local foundname = finders.doreadfile("any",".",filename)
- if foundname ~= "" then
- action(name,foundname)
- done = true
- break
- end
- end
- if done then
- break
- end
- end
- end
- if failure and not done then
- failure(name)
- end
-end
-
-statistics.register("loaded tex modules", function()
- if next(modstatus) then
- local t, f, nt, nf = { }, { }, 0, 0
- for k, v in table.sortedhash(modstatus) do
- k = file.basename(k)
- if v == 0 then
- nf = nf + 1
- f[nf] = k
- else
- nt = nt + 1
- t[nt] = k
- end
- end
- local ts = (nt>0 and format(" (%s)",concat(t," "))) or ""
- local fs = (nf>0 and format(" (%s)",concat(f," "))) or ""
- return format("%s requested, %s found%s, %s missing%s",nt+nf,nt,ts,nf,fs)
- else
- return nil
- end
-end)
diff --git a/Master/texmf-dist/tex/context/base/supp-fil.mkii b/Master/texmf-dist/tex/context/base/supp-fil.mkii
index fc0492442ce..b76dfb901a2 100644
--- a/Master/texmf-dist/tex/context/base/supp-fil.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-fil.mkii
@@ -5,7 +5,7 @@
%D subtitle=Files,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-fil.mkiv b/Master/texmf-dist/tex/context/base/supp-fil.mkiv
deleted file mode 100644
index 6b9af21cee2..00000000000
--- a/Master/texmf-dist/tex/context/base/supp-fil.mkiv
+++ /dev/null
@@ -1,462 +0,0 @@
-%D \module
-%D [ file=supp-fil,
-%D version=1995.10.10,
-%D title=\CONTEXT\ Support Macros,
-%D subtitle=Files,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 \TEX\ operates on files, so one wouldn't wonder that there
-%D is a separate module for file commands. In \CONTEXT\ files
-%D are used for several purposes:
-%D
-%D \startitemize[packed]
-%D \item general textual input
-%D \item logging status information
-%D \item saving registers, lists and references
-%D \item buffering defered textual input
-%D \stopitemize
-%D
-%D When dealing with files we can load them as a whole, using
-%D the \type{\input} primitive or load them on a line||by||line
-%D basis, using \type{\read}. Writing is always done line by
-%D line, using \type{\write}.
-
-\writestatus{loading}{ConTeXt Support Macros / Files}
-
-\registerctxluafile{supp-fil}{1.001}
-
-\unprotect
-
-\ifx\undefined\f!pathseparator
- \def\f!pathseparator{/}
- \def\f!currentpath {.}
- \def\f!parentpath {..}
-\fi
-
-\def\openinputfile #1#2{\immediate\openin #1={#2}} \def\closeinputfile #1{\immediate\closein #1}
-\def\openoutputfile#1#2{\immediate\openout#1={#2}} \def\closeoutputfile#1{\immediate\closeout#1}
-
-%D \macros
-%D {pushendofline,popendofline}
-%D
-%D When we are loading files in the middle of the typesetting
-%D process, for instance when we load references, we have to be
-%D sure that the reading process does not generate so called
-%D 'spurious spaces'. This can be prevented by assigning the
-%D line ending character the \CATCODE\ comment. This is
-%D accomplished by
-%D
-%D \starttyping
-%D \pushendofline
-%D ... reading ...
-%D \popendofline
-%D \stoptyping
-
-\newcount \endoflinelevel
-
-\def\pushendofline
- {\advance\endoflinelevel\plusone
- \expandafter\chardef\csname :eol:\number\endoflinelevel\endcsname\catcode\endoflineasciicode
- \catcode\endoflineasciicode\commentcatcode\relax}
-
-\def\popendofline
- {\catcode\endoflineasciicode\csname :eol:\number\endoflinelevel\endcsname
- \advance\endoflinelevel\minusone}
-
-\def\restoreendofline
- {\catcode\endoflineasciicode\endoflinecatcode}
-
-%D \macros
-%D {scratchread, scratchwrite}
-%D
-%D We define a scratch file for reading. Keep in mind that
-%D the number of files is limited to~16, so use this one when
-%D possible. We also define a scratch output file.
-
-\ifx\undefined\scratchread \newread \scratchread \fi
-\ifx\undefined\scratchwrite \newwrite\scratchwrite \fi
-
-%D \macros
-%D {unlinkfile}
-%D
-%D Sometimes we want to make sure a file is deleted, so here
-%D is a macro that does the job. It's named after the \PERL\
-%D one.
-
-\def\unlinkfile#1{\ctxlua{os.remove([[#1]])}}
-
-%D \macros
-%D {writeln}
-%D
-%D This saves a few tokens:
-
-\def\writeln#1{\write#1{}}
-
-\def\doiffileexistselse #1{\ctxcommand{doiffileexistelse([[#1]])}}
-\def\lastfoundexistingfile {\ctxcommand{lastexistingfile()}}
-
-%D \macros
-%D {doprocessfile,fileline,fileprocessedtrue,dofinishfile}
-%D
-%D The next macro offers a framework for processing files on a
-%D line by line basis.
-%D
-%D \starttyping
-%D \doprocessfile \identifier {name} \action
-%D \stoptyping
-%D
-%D The first argument can for instance be \type{\scratchread}.
-%D The action must do something with \type{\fileline}, which
-%D holds the current line. One can halfway step out using
-%D \type{\dofinishfile} and ise \type{\iffileprocessed} to
-%D see if indeed some content was found.
-
-\newif\iffileprocessed
-
-\let\fileline\empty
-
-\def\doprocessfile#1#2#3%
- {\openinputfile{#1}{#2}%
- \ifeof#1%
- \fileprocessedfalse
- \closeinputfile#1%
- \else
- \fileprocessedtrue
- \gdef\dofinishfile
- {\closeinputfile#1%
- \global\let\doprocessline\relax}%
- \gdef\doprocessline
- {\ifeof#1%
- \expandafter\dofinishfile
- \else
- \global\read#1 to \fileline
- #3\relax
- \expandafter\doprocessline
- \fi}%
- \expandafter\doprocessline
- \fi}
-
-%D \macros
-%D {pathplusfile,assignfullfilename,sanitizefilename}
-%D
-%D Use \type{\pathplusfile} to compose a full file name, like
-%D in:
-%D
-%D \starttyping
-%D \pathplusfile{path}{file}
-%D \stoptyping
-%D
-%D By default, this expands into {\tt \pathplusfile{path}{file}}.
-
-\def\pathplusfile#1#2{#1\f!pathseparator#2}
-
-%D This one constructs a filename from a (possible empty)
-%D path and filename.
-
-\def\assignfullfilename#1#2\to#3%
- {\doifelsenothing{#1}
- {\edef#3{#2}}
- {\edef#3{#1\f!pathseparator#2}}}
-
-\def\sanitizefilename#1\to#2{\edef#2{\ctxcommand{thesanitizedfilename([[#1]])}}}
-
-%D NEW:
-
-\newconstant\kindoffile % 0=normal 1=full path spec (or http) / set at the lua end
-
-\def\checkfilename#1{\ctxcommand{checkfilename([[#1]])}}
-
-%D \macros
-%D {input, normalinput}
-%D
-%D Sometimes we run into troubles when \type {\input} wants to get
-%D expanded, e.g. in a \type {\write} (which happens in the metafun
-%D manual when we permit long MP lines). So, instead of fixing that,
-%D we go for a redefinition of \type {\input}. Of course it's better
-%D to use \type {\readfile} or \type {\processfile}.
-
-\unexpanded\def\input{\normalinput}
-
-\def\inputgivenfile#1{\normalinput{#1}}
-
-%D \macros
-%D {readfile,ReadFile}
-%D
-%D One cannot be sure if a file exists. When no file can be
-%D found, the \type{\input} primitive gives an error message
-%D and switches to interactive mode. The macro \type{\readfile}
-%D takes care of non||existing files. This macro has two faces.
-%D
-%D \starttyping
-%D \ReadFile {filename}
-%D \readfile {filename} {before loading} {not found}
-%D \stoptyping
-%D
-%D Many \TEX\ implementations have laid out some strategy for
-%D locating files. This can lead to unexpected results,
-%D especially when one loads files that are not found in the
-%D current directory. Let's give an example of this. In
-%D \CONTEXT\ illustrations can be defined in an external file.
-%D The resizing macro first looks if an illustration is defined
-%D in the local definitions file. When no such file is found,
-%D it searches for a global file and when this file is not
-%D found either, the illustration itself is scanned for
-%D dimensions. One can imagine what happens if an adapted,
-%D localy stored illustration, is scaled according to
-%D dimensions stored somewhere else.
-%D
-%D When some \TEX\ implementation starts looking for a file, it
-%D normally first looks in the current directory. When no file
-%D is found, \TEX\ starts searching on the path where format
-%D and|/|or style files are stored. Depending on the implementation
-%D this can considerably slow down processing speed.
-%D
-%D In \CONTEXT, we support a project||wise ordening of files.
-%D In such an approach it seems feasible to store common files
-%D in a lower directory. When for instance searching for a
-%D general layout file, we therefore have to backtrack.
-%D
-%D These three considerations have lead to a more advanced
-%D approach for loading files.
-%D
-%D We first present an earlier implementation of
-%D \type{\readfile}. This command backtracks parent
-%D directories, upto a predefined level. Users can change this
-%D level (on the commandline using a directive); we default to~3.
-%D
-%D We use \type{\normalinput} instead of \type{\input}
-%D because we want to be able to redefine the original
-%D \type{\input} when needed, for instance when loading third
-%D party libraries.
-
-\newevery \everybeforereadfile \EveryBeforeReadFile
-\newevery \everyafterreadfile \EveryAfterReadFile
-
-\let \everyreadfile \everybeforereadfile
-
-\def\maxreadlevel{\ctxcommand{maxreadlevel()}}
-
-% We need to postpone loading, else we got frozen type-* files and so when
-% a format is generated on a source path.
-
-\def\doreadfile#1#2#3% protocol path filename true false
- {\edef\readfilename{\ctxcommand{doreadfile("#1","#2","#3")}}%
- \ifx\readfilename\empty
- \expandafter\doreadfilenop
- \else
- \expandafter\doreadfileyes
- \fi}
-
-\long\def\doreadfileyes#1#2%
- {#1\relax
- \the\everybeforereadfile
- \relax\inputgivenfile\readfilename\relax
- \the\everyafterreadfile}
-
-\long\def\doreadfilenop#1#2%
- {#2}
-
-%D \macros
-%D {readjobfile,readlocfile,readsysfile,
-%D readfixfile,readsetfile}
-%D
-%D This implementation honnors the third situation, but we
-%D still can get unwanted files loaded and/or can get involved
-%D in extensive searching.
-%D
-%D Due to different needs, we decided to offer four alternative
-%D loading commands. With \type{\readjobfile} we load a local
-%D file and do no backtracking, while \type{\readlocfile}
-%D backtracks~\number\maxreadlevel\ directories, including the current
-%D one.
-%D
-%D System files can be anywhere and therefore
-%D \type{\readsysfile} is not bound to the current directory
-%D and obeys the \TEX\ implementation.
-%D
-%D Of the last two, \type{\readfixfile} searches on the
-%D directory specified and backtracks too, while
-%D \type{\readsetfile} does only search on the specified path.
-%D
-%D The most liberal is \type {\readfile}.
-
-\unexpanded\def\readjobfile #1{\doreadfile{job} {.}{#1}} % current path, no backtracking
-\unexpanded\def\readlocfile #1{\doreadfile{loc} {.}{#1}} % current path, backtracking
-\unexpanded\def\readsysfile #1{\doreadfile{sys} {.}{#1}} % current path, obeys tex search
-\unexpanded\def\readfixfile#1#2{\doreadfile{fix}{#1}{#2}} % specified path, backtracking
-\unexpanded\def\readsetfile#1#2{\doreadfile{set}{#1}{#2}} % specified path, no backtracking
-\unexpanded\def\readfile #1{\doreadfile{any} {.}{#1}}
-\unexpanded\def\ReadFile #1{\doreadfile{any} {.}{#1}\donothing\donothing}
-
-%D So now we've got ourselves five file loading commands:
-%D
-%D \starttyping
-%D \readfile {filename} {before loading} {not found}
-%D
-%D \readjobfile {filename} {before loading} {not found}
-%D \readlocfile {filename} {before loading} {not found}
-%D \readfixfile {filename} {before loading} {not found}
-%D \readsysfile {directory} {filename} {before loading} {not found}
-%D \stoptyping
-
-\def\readtexfile#1#2#3%
- {\pushcatcodetable \catcodetable \ctxcatcodes
- \readfile{#1}{#2}{#3}%
- \popcatcodetable}
-
-\ifdefined \xmlcatcodes
-
- \def\readxmlfile#1#2#3%
- {\pushcatcodetable \catcodetable \xmlcatcodes
- \readfile{#1}{#2}{#3}%
- \popcatcodetable}
-
-\fi
-
-%D \macros
-%D {doiffileelse,doiflocfileelse}
-%D
-%D The next alternative only looks if a file is present. No
-%D loading is done. This one obeys the standard \TEX\
-%D implementation method.
-%D
-%D \starttyping
-%D \doiffileelse {filename} {found} {not found}
-%D \stoptyping
-%D
-%D \starttyping
-%D \doiflocfileelse {filename} {before loading} {not found}
-%D \stoptyping
-
-\def\doiffileelse {\doiffileexistselse}
-\def\doiffile #1{\doiffileexistselse{#1}\firstofoneargument\gobbleoneargument}
-\def\doifnotfile #1{\doiffileexistselse{#1}\gobbleoneargument\firstofoneargument}
-
-\def\doiflocfileelse#1%
- {\makelocreadfilename{#1}%
- \doiffileelse\readfilename}
-
-\def\makelocreadfilename#1%
- {\sanitizefilename#1\to\readfilename
- \checkfilename\readfilename
- \ifcase\kindoffile
- \edef\readfilename{\pathplusfile\f!currentpath{#1}}%
- \fi}
-
-%D \macros
-%D {doonlyonce, doinputonce, doendinputonce}
-%D
-%D Especially macropackages need only be loaded once.
-%D Repetitive loading not only costs time, relocating registers
-%D often leads to abortion of the processing because \TEX's
-%D capacity is limited. One can prevent multiple execution and
-%D loading by using one of both:
-%D
-%D \starttyping
-%D \doonlyonce{actions}
-%D \doinputonce{filename}
-%D \doendinputonce{filename}
-%D \stoptyping
-%D
-%D This command obeys the standard method for locating files.
-
-\long\def\doonlyonce#1%
- {\doifundefinedelse{@@@#1@@@}
- {\letgvalue{@@@#1@@@}\empty
- \firstofoneargument}
- {\gobbleoneargument}}
-
-\def\doinputonce#1%
- {\doonlyonce{#1}{\doiffileelse{#1}{\inputgivenfile{#1}}\donothing}}
-
-\def\doendinputonce#1%
- {\doifdefined{@@@#1@@@}\endinput}
-
-\def\forgetdoingonce#1%
- {\global\letbeundefined{@@@#1@@@}}
-
-%D \macros
-%D {doifparentfileelse}
-%D
-%D The test \type{\doifelse{\jobname}{filename}} does not give
-%D the desired result, simply because \type{\jobname} expands
-%D to characters with \CATCODE~12, while the characters in
-%D \type{filename} have \CATCODE~11. So we can better use:
-%D
-%D \starttyping
-%D \doifparentfileelse{filename}{yes}{no}
-%D \stoptyping
-%D
-%D Since \TEXEXEC\ (and thereby \CONTEXT) supports renaming of
-%D the outputfile, we also need to check on that alternative
-%D name.
-
-\ifx\outputfilename\undefined \def\outputfilename{\jobname} \fi
-
-\def\doifparentfileelse#1{\ctxcommand{doifparentfileelse([[#1]])}}
-
-\newcount\readingfilelevel
-
-%D We need to redo this: catcode sets and such
-
-\newtoks \everystartreadingfile
-\newtoks \everystopreadingfile
-
-\unexpanded\def\startreadingfile% beter een every en \setnormalcatcodes
- {\global\advance\readingfilelevel\plusone
- \the\everystartreadingfile
- \pushcatcodetable % saveguard
- \ctxlua{regimes.push()}% temporarily this way
- }% \setcatcodetable\prtcatcodes % no longer in mkiv, has to be done explictly
-
-\unexpanded\def\stopreadingfile
- {\popcatcodetable % saveguard
- \ctxlua{regimes.pop()}% temporarily this way
- \the\everystopreadingfile
- \global\advance\readingfilelevel\minusone}
-
-%D \macros
-%D {splitfilename}
-%D
-%D I should have made this one sooner. This macro was first needed when
-%D ran into graphic with a period in the pathpart.
-%D
-%D \startbuffer
-%D \def\showfilesplit
-%D {\bgroup \tttf
-%D \hbox{(full: \splitofffull)}\space
-%D \hbox{(path: \splitoffpath)}\space
-%D \hbox{(base: \splitoffbase)}\space
-%D \hbox{(name: \splitoffname)}\space
-%D \hbox{(type: \splitofftype)}\space
-%D \egroup}
-%D
-%D \splitfilename{c:/aa/bb/cc/dd.ee.ff} \showfilesplit \endgraf
-%D \splitfilename{c:/aa/bb/cc/dd.ee} \showfilesplit \endgraf
-%D \splitfilename{c:/aa/bb/cc/dd} \showfilesplit \endgraf
-%D
-%D \splitfilename{dd.ee.ff} \showfilesplit \endgraf
-%D \splitfilename{dd.ee} \showfilesplit \endgraf
-%D \splitfilename{dd} \showfilesplit \endgraf
-%D \stopbuffer
-%D
-%D \start \typebuffer \getbuffer \stop
-
-\def\splitoffroot{.} \newconstant\splitoffkind
-
-\let\splitofffull\empty
-\let\splitoffpath\empty
-\let\splitoffbase\empty
-\let\splitoffname\empty
-\let\splitofftype\empty
-
-\def\splitfilename#1{\ctxcommand{splitfilename([[#1]])}}
-\def\splitfiletype#1{\ctxcommand{splitfiletype([[#1]])}}
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/supp-fun.mkii b/Master/texmf-dist/tex/context/base/supp-fun.mkii
index 6b26437038e..9bba4f5a85f 100644
--- a/Master/texmf-dist/tex/context/base/supp-fun.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-fun.mkii
@@ -5,7 +5,7 @@
%D subtitle=Fun Stuff,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-fun.mkiv b/Master/texmf-dist/tex/context/base/supp-fun.mkiv
index a8db3b6343d..33bee0306d1 100644
--- a/Master/texmf-dist/tex/context/base/supp-fun.mkiv
+++ b/Master/texmf-dist/tex/context/base/supp-fun.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Fun Stuff,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,6 +13,9 @@
\unprotect
+%D Beware, these macros wil be replaced and at some point this
+%D module will not be preloaded any more.
+
%D This module implements some typographics tricks that can
%D be fun when designing document layouts. The examples use
%D macros that are typical to \CONTEXT, but non \CONTEXT\
@@ -20,21 +23,15 @@
%D macros without problems. This module will be extended
%D when the need for more of such tricks arises.
-\ifx \undefined \writestatus \input supp-mis.tex \relax \fi
-
\writestatus{loading}{ConTeXt Support Macros / Fun Stuff}
-\ifx\definefont\undefined
- \def\definedfont[#1]{\font\temp#1\relax\temp}
-\fi
-
%D \macros
%D {DroppedCaps, DroppedString, DroppedIndent, DroppedLines}
%D
%D \startbuffer
%D \DroppedCaps
-%D {\color[green]} {cmbx12}
-%D {2.2\baselineskip} {2pt} {\baselineskip} {2}
+%D {\color[green]} {SerifBold}
+%D {\the\dimexpr2.2\baselineskip} {2pt} {\the\baselineskip} {2}
%D Let's start
%D \stopbuffer
%D
@@ -58,8 +55,8 @@
%D
%D \startbuffer
%D \DroppedCaps
-%D {\color[red]} {cmbx12}
-%D {\baselineskip} {0pt} {0pt} {1}
+%D {\color[red]} {SerifBold}
+%D {\the\baselineskip} {0pt} {0pt} {1}
%D This simple
%D \stopbuffer
%D
@@ -70,8 +67,8 @@
%D
%D \startbuffer
%D \DroppedCaps
-%D {\color[red]} {cmbx12}
-%D {2\baselineskip} {0pt} {\baselineskip} {2}
+%D {\color[red]} {SerifBold}
+%D {\the\dimexpr2\baselineskip} {0pt} {\the\baselineskip} {2}
%D Is this ugly
%D \stopbuffer
%D
@@ -98,8 +95,8 @@
%D \startbuffer
%D \def\MyDroppedCaps%
%D {\DroppedCaps
-%D {\color[green]} {cmbx12}
-%D {5\baselineskip} {3pt} {3\baselineskip} {4}}
+%D {\color[green]} {SerifBold}
+%D {\the\dimexpr5\baselineskip} {3pt} {\the\dimexpr3\baselineskip} {4}}
%D
%D \MyDroppedCaps The implementation
%D \stopbuffer
@@ -537,30 +534,9 @@
\def\NormalizeFontHeight{\NormalizeFontSize\ht}
\def\NormalizeFontWidth {\NormalizeFontSize\wd}
-% \def\NormalizeFontSize#1#2#3#4#5%
-% {\bgroup
-% \dimen0=#4% #4 can be \ht0 or so
-% \setbox0\hbox{\definedfont[#5 at 10pt]#3}%
-% \ifdim\wd0>\zeropoint
-% \dimen2=#10 % #1 is \wd or \ht
-% \dimen4=10000pt
-% \divide\dimen4 \dimen2
-% \divide\dimen0 \plusthousand
-% \dimen0=\number\dimen4\dimen0
-% \xdef\TheNormalizedFontSize{\the\dimen0}%
-% \else
-% \dimen0\bodyfontsize
-% \fi
-% \definedfont[#5 at \the\dimen0]%
-% \expandafter
-% \egroup
-% \expandafter\font\expandafter#2\fontname\font\relax}
-%
-% the familiar struggle with accuracy forces us to use:
-
\def\NormalizeFontSize#1#2#3#4#5%
{\bgroup
- \dimen0=#4% #4 can be \ht0 or so
+ \dimen0=#4% #4 can be \ht0 or so
\setbox0\hbox{\definedfont[#5 at 5pt]#3}% 10pt
\ifdim\wd0>\zeropoint
\dimen2=#10 % #1 is \wd or \ht
@@ -573,13 +549,7 @@
\else
\dimen0\bodyfontsize
\fi
- % mkii
- % \definedfont[#5 at \the\dimen0]%
- % \expandafter
- % \egroup
- % \expandafter\font\expandafter#2\fontname\font\relax}
- % mkiv safe (file: prefix etc)
- \expanded{\egroup\def\noexpand#2{\definedfont[#5 at \the\dimen0]}}}
+ \normalexpanded{\egroup\def\noexpand#2{\definedfont[#5 at \the\dimen0]}}}
%D Afterwards, we have access to the calculated size by:
diff --git a/Master/texmf-dist/tex/context/base/supp-lat.mkii b/Master/texmf-dist/tex/context/base/supp-lat.mkii
index 576121327cb..343a7674c27 100644
--- a/Master/texmf-dist/tex/context/base/supp-lat.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-lat.mkii
@@ -5,7 +5,7 @@
%D subtitle=General,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-mat.mkii b/Master/texmf-dist/tex/context/base/supp-mat.mkii
index 1a51164e676..e8a34fc90ee 100644
--- a/Master/texmf-dist/tex/context/base/supp-mat.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-mat.mkii
@@ -5,7 +5,7 @@
%D subtitle=Math,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-mat.mkiv b/Master/texmf-dist/tex/context/base/supp-mat.mkiv
index e441cbc2824..bc26611ae05 100644
--- a/Master/texmf-dist/tex/context/base/supp-mat.mkiv
+++ b/Master/texmf-dist/tex/context/base/supp-mat.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Math,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -61,29 +61,32 @@
\let\startdmath \Ustartdisplaymath % obsolete, less safe
\let\stopdmath \Ustopmath % obsolete, less safe
-\long\def\mathematics#1{\relax \ifmmode#1\else\normalstartimath#1\normalstopimath\fi}
-\long\def\displaymath#1{\noindent \ifmmode#1\else\normalstartdmath#1\normalstopdmath\fi}
-\long\def\inlinemath #1{\dontleavehmode\ifmmode#1\else\normalstartimath#1\normalstopimath\fi}
+\unexpanded\def\mathematics#1{\relax \ifmmode#1\else\normalstartimath#1\normalstopimath\fi}
+\unexpanded\def\displaymath#1{\noindent \ifmmode#1\else\normalstartdmath#1\normalstopdmath\fi}
+\unexpanded\def\inlinemath #1{\dontleavehmode\ifmmode#1\else\normalstartimath#1\normalstopimath\fi}
+\unexpanded\def\textmath #1{\dontleavehmode\ifmmode#1\else\begingroup\everymath\emptytoks\normalstartimath#1\normalstopimath\endgroup\fi} % \mathsurround\zeropoint
\let\m\mathematics % unexpanded?
\let\stopmathmode\relax
-\unexpanded\def\startmathmode % cannot be used nested
- {\relax\ifmmode
- \let\stopmathmode\relax
- \else
- \normalstartimath\let\stopmathmode\normalstopimath
- \fi}
+% \unexpanded\def\startmathmode % cannot be used nested
+% {\relax\ifmmode
+% \let\stopmathmode\relax
+% \else
+% \normalstartimath\let\stopmathmode\normalstopimath
+% \fi}
\unexpanded\def\startmathmode % nested variant
{\relax\ifmmode
- \begingroup\let\stopmathmode\endgroup
+ \begingroup
+ \let\stopmathmode\endgroup
\else
- \normalstartimath\let\stopmathmode\normalstopimath
+ \normalstartimath
+ \let\stopmathmode\normalstopimath
\fi}
-\def\nomathematics#1%
+\unexpanded\def\nomathematics#1%
{\relax\ifmmode\hbox{#1}\else#1\fi}
\let\math\mathematics
@@ -93,20 +96,20 @@
%D
%D An example of usage of the following can be found in the MathML module:
-\long\def\displaymathematics#1{\relax\ifmmode#1\else\dostartformula{}#1\dostopformula\fi}
- \def\inlinemathematics {\dontleavehmode\mathematics}
- \def\automathematics {\relax\ifhmode\@EA\inlinemathematics\else\@EA\displaymathematics\fi}
+\unexpanded\def\displaymathematics#1{\relax\ifmmode#1\else\dostartformula{}#1\dostopformula\fi}
+\unexpanded\def\inlinemathematics {\dontleavehmode\mathematics}
+\unexpanded\def\automathematics {\relax\ifhmode\expandafter\inlinemathematics\else\expandafter\displaymathematics\fi}
% better, esp when used in bTABLE ... eTABLE
-\def\automathematics
+\unexpanded\def\automathematics
{\relax
\ifhmode
\expandafter\inlinemathematics
\else\ifintable
- \expandafter\expandafter\expandafter\inlinemathematics
+ \doubleexpandafter\inlinemathematics
\else
- \expandafter\expandafter\expandafter\displaymathematics
+ \doubleexpandafter\displaymathematics
\fi\fi}
%D \macros
@@ -116,6 +119,8 @@
%D such a way that spacing is acceptable. I won't spend much
%D words on these macros, because they will be overloaded in
%D the units module.
+%D
+%D REPLACED (keep commented):
\newsignal\dimensionsignal
@@ -211,8 +216,8 @@
%D
%D \typebuffer \getbuffer
-\def\cramped
- {\mathpalette\docramped}
+\unexpanded\def\cramped
+ {\mathpalette\math_cramped}
%D We force a cramped style by issuing a non||existing radical (box).
%D After that we make sure the height is correct. (Comment taken from
@@ -240,7 +245,7 @@
% \ht\scratchbox-\scratchdimen
% \box\scratchbox}
-\def\docramped#1#2%
+\def\math_cramped#1#2%
{\begingroup % added HH, made even more cramped
\setbox\scratchbox\hbox
{\nulldelimiterspace\zeropoint
@@ -290,13 +295,13 @@
%D Notice that \type {\clap{\cramped ... }} would also work,
%D but it requires \TEX\ to typeset it arguments 16 times.
-\def\docrampedllap#1#2{{}\dollap{\docramped #1{#2}}}
-\def\docrampedrlap#1#2{{}\dorlap{\docramped #1{#2}}}
-\def\docrampedclap#1#2{{}\doclap{\docramped #1{#2}}}
+\unexpanded\def\crampedllap{\mathpalette\math_cramped_llap}
+\unexpanded\def\crampedrlap{\mathpalette\math_cramped_rlap}
+\unexpanded\def\crampedclap{\mathpalette\math_cramped_clap}
-\def\crampedllap{\mathpalette\docrampedllap}
-\def\crampedrlap{\mathpalette\docrampedrlap}
-\def\crampedclap{\mathpalette\docrampedclap}
+\def\math_cramped_llap#1#2{{}\dollap{\math_cramped #1{#2}}}
+\def\math_cramped_rlap#1#2{{}\dorlap{\math_cramped #1{#2}}}
+\def\math_cramped_clap#1#2{{}\doclap{\math_cramped #1{#2}}}
% experiment, not yet to be used
diff --git a/Master/texmf-dist/tex/context/base/supp-mis.mkii b/Master/texmf-dist/tex/context/base/supp-mis.mkii
index f3bde453ba2..bc511e518b6 100644
--- a/Master/texmf-dist/tex/context/base/supp-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Missing (For Generic Use),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-mpe.mkii b/Master/texmf-dist/tex/context/base/supp-mpe.mkii
index f28176292d6..2e5e7e52820 100644
--- a/Master/texmf-dist/tex/context/base/supp-mpe.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-mpe.mkii
@@ -5,7 +5,7 @@
%D subtitle=METAPOST Special Extensions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -1268,7 +1268,8 @@
/BM /\ifcase#1 Normal\or Normal\or Multiply\or Screen\or
Overlay\or SoftLight\or HardLight\or ColorDodge\or
ColorBurn\or Darken\or Lighten\or Difference\or
- Exclusion\else Compatible\fi
+ Exclusion\or Hue\or Saturation\or Color\or
+ Luminosity\else Compatible\fi
#3>>}
\fi
diff --git a/Master/texmf-dist/tex/context/base/supp-mps.mkii b/Master/texmf-dist/tex/context/base/supp-mps.mkii
index b071ffe72de..3991280e6d4 100644
--- a/Master/texmf-dist/tex/context/base/supp-mps.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-mps.mkii
@@ -5,7 +5,7 @@
%D subtitle=\METAPOST\ Inclusion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-mrk.mkii b/Master/texmf-dist/tex/context/base/supp-mrk.mkii
index eb186547149..b9d476c2a7c 100644
--- a/Master/texmf-dist/tex/context/base/supp-mrk.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-mrk.mkii
@@ -5,7 +5,7 @@
%D subtitle=Marks,
%D author=Jim Fox / Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-num.mkii b/Master/texmf-dist/tex/context/base/supp-num.mkii
index 74234975374..5e35a20b07d 100644
--- a/Master/texmf-dist/tex/context/base/supp-num.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-num.mkii
@@ -5,7 +5,7 @@
%D subtitle=Numbers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-num.mkiv b/Master/texmf-dist/tex/context/base/supp-num.mkiv
index 68b775403e3..be0df026da4 100644
--- a/Master/texmf-dist/tex/context/base/supp-num.mkiv
+++ b/Master/texmf-dist/tex/context/base/supp-num.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Numbers,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -45,30 +45,30 @@
%D \stopbuffer
%D
%D \typebuffer
-%D
-%D This is typset as:
-%D
-%D \startlines
-%D \getbuffer
-%D \stoplines
+%
+% This is typset as:
+%
+% \startlines
+% \getbuffer
+% \stoplines
%D
%D The sign can be typeset as is or within the space of a
%D digit.
%D
%D \startbuffer
%D \setdigitsign 0 \digits +12.345,90
-%D \setdigitmode 1 \digits +12.345,90
-%D \setdigitmode 2 \digits +12.345,90
-%D \setdigitmode 3 \digits +12.345,90
+%D \setdigitsign 1 \digits +12.345,90
+%D \setdigitsign 2 \digits +12.345,90
+%D \setdigitsign 3 \digits +12.345,90
%D \stopbuffer
%D
%D \typebuffer
%D
-%D This is typset as:
-%D
-%D \startlines
-%D \getbuffer
-%D \stoplines
+% This is typset as:
+%
+% \startlines
+% \getbuffer
+% \stoplines
\chardef\digitoutputmode=1 % 0..6
\chardef\digitsignmode =0 % 0..3
@@ -95,10 +95,7 @@
%D the grouped call, the other branch handles the fuzzy
%D delimited calls.
-\ifx\mbox\undefined \let\mbox\normalhbox \fi
-
-% \unexpanded\def\digits
-% {\bgroup\let~@\doifnextbgroupelse\dodigits\grabdigit}
+\ifdefined\mbox \else \let\mbox\hbox \fi
\unexpanded\def\digits
{\bgroup
@@ -357,10 +354,10 @@
%D \stopbuffer
%D
%D \typebuffer
-%D
-%D \startlines
-%D \getbuffer
-%D \stoplines
+%
+% \startlines
+% \getbuffer
+% \stoplines
%D \macros
%D {Digits}
@@ -417,88 +414,3 @@
\fi\fi}
\protect \endinput
-
-
-\endinput
-
-\def\digitszeropadding {\zeroamount}
-\def\digitsnegative {\mathematics\negative}
-\def\digitspositive {\mathematics\positive}
-\def\digitsspace {\hphantom{0}}
-\def\digitsseparatorspace{\hphantom{.}}
-\def\digitssignspace {\hphantom{+}}
-\def\digitshighspace {\hphantom{\mathematics\positive}}
-\def\digitspower {\high}
-
-\starttext
-
-% print(table.serialize(table.keys(jobs)))
-
-local P, S, R, Cs = lpeg.P, lpeg.S, lpeg.R, lpeg.Cs
-
-local done = false
-local swap = false
-local digit = R("09")
-local sign = S("+-")
-local power = S("^e")
-local space = S(" ~@_")
-local comma = P(",")
-local period = P(".")
-local signspace = P("/")
-local positive = P("p")
-local negative = P("n")
-local highspace = P("s")
-local padding = P("=")
-
-local space = space / "\\digitsspace"
-local digit = digit / function(s) done = true return s end
-local separator = comma / function(s) if not done then return "\\digitsseparatorspace" elseif swap then return "." else return "," end end
- + period / function(s) if not done then return "\\digitsseparatorspace" elseif swap then return "," else return "." end end
-local signspace = signspace / "\\digitssignspace"
-local positive = positive / "\\digitspositive"
-local negative = negative / "\\digitsnegative"
-local highspace = highspace / "\\digitshighspace"
-local power = power/"" * (Cs((sign + signspace)^0 * digit^1) / function(s) return "\\digitspower{" .. s .. "}" end)
-local padding = padding / "\\digitszeropadding"
-
-local replace = lpeg.Cs (
- (sign + signspace + positive + negative + highspace)^0
- * (separator^0 * (space + digit)^1)^1
- * power^0
-)
-
-local function digits(str)
- done = false
---~ swap = true
- local str = lpeg.match(replace,str)
--- print(str)
- tex.sprint(tex.ctxcatcodes,"\\dontleavehmode",str,"\\par")
-end
--- namespaces.register("digits")
-
-digits("12")
-digits("~~~.~~~.~~~.68.712,34")
-digits("~~~.~~~.~~~.68.712,34")
-digits("___.___.111.68.712,34")
-digits("111.111.111.68.712,34")
-digits("12.345,90")
-digits("12.345.000")
-digits("12,34")
-digits("392.857.230.68.712,34")
-digits("1234")
-digits("123.222,00")
-digits("123.222,==")
-digits("123.222,00^10")
-digits("123.222,00e10")
-digits("/123.222,00e-12")
-digits("-123.222,00e-12")
--- digits("+123.222,00e-12")
-digits("n123.222,00e-12")
-digits("s123.222,00e-12")
-digits("p123.222,00e/12")
-
-\stopluacode
-[[\digitsseparatorspace]]
-\stoptext
-
-
diff --git a/Master/texmf-dist/tex/context/base/supp-pat.mkii b/Master/texmf-dist/tex/context/base/supp-pat.mkii
index 8cd4dd072d8..425eae215f6 100644
--- a/Master/texmf-dist/tex/context/base/supp-pat.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-pat.mkii
@@ -5,7 +5,7 @@
%D subtitle=Patterns,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-pdf.mkii b/Master/texmf-dist/tex/context/base/supp-pdf.mkii
index 4d3619d4b8b..4dd2db776b3 100644
--- a/Master/texmf-dist/tex/context/base/supp-pdf.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-pdf.mkii
@@ -5,7 +5,7 @@
%D subtitle=\METAPOST\ to \PDF\ conversion,
%D author=Hans Hagen \& others (see text),
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-ran.lua b/Master/texmf-dist/tex/context/base/supp-ran.lua
index accd5c94c15..75202f696f8 100644
--- a/Master/texmf-dist/tex/context/base/supp-ran.lua
+++ b/Master/texmf-dist/tex/context/base/supp-ran.lua
@@ -16,7 +16,6 @@ local commands = commands
local math = math
local random, randomseed, round, seed, last = math.random, math.randomseed, math.round, false, 1
-local texwrite = tex.write
function math.setrandomseedi(n,comment)
if not n then
@@ -35,12 +34,12 @@ end
function commands.getrandomcounta(min,max)
last = random(min,max)
- texwrite(last)
+ context(last)
end
function commands.getrandomcountb(min,max)
last = random(min,max)/65536
- texwrite(last)
+ context(last)
end
function commands.setrandomseed(n)
@@ -49,7 +48,7 @@ function commands.setrandomseed(n)
end
function commands.getrandomseed(n)
- texwrite(last)
+ context(last)
end
-- maybe stack
diff --git a/Master/texmf-dist/tex/context/base/supp-ran.mkii b/Master/texmf-dist/tex/context/base/supp-ran.mkii
index 0c07099ed1e..0a39026bfd3 100644
--- a/Master/texmf-dist/tex/context/base/supp-ran.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-ran.mkii
@@ -5,7 +5,7 @@
%D subtitle=Random Number Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-ran.mkiv b/Master/texmf-dist/tex/context/base/supp-ran.mkiv
index 500170ab0f9..356ed580fa8 100644
--- a/Master/texmf-dist/tex/context/base/supp-ran.mkiv
+++ b/Master/texmf-dist/tex/context/base/supp-ran.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Random Number Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -18,13 +18,13 @@
\registerctxluafile{supp-ran}{1.001}
-\def\getrandomcount #1#2#3{#1=\ctxcommand{getrandomcounta(\number#2,\number#3)}}
-\def\getrandomdimen #1#2#3{#1=\ctxcommand{getrandomcounta(\number\dimexpr#2,\number\dimexpr#3)}\scaledpoint}
-\def\getrandomnumber#1#2#3{\edef#1{\ctxcommand{getrandomcounta(\number#2,\number#3)}}}
-\def\getrandomfloat #1#2#3{\edef#1{\ctxcommand{getrandomcountb(\number\dimexpr#2\points,\number\dimexpr#3\points)}}}
-\def\setrandomseed #1{\ctxcommand{setrandomseed(\number#1)}}
-\def\getrandomseed #1{\edef#1{\ctxcommand{getrandomseed()}}}
-\def\freezerandomseed {\ctxcommand{freezerandomseed()}}
-\def\defrostrandomseed {\ctxcommand{defrostrandomseed()}}
+\unexpanded\def\getrandomcount #1#2#3{#1=\ctxcommand{getrandomcounta(\number#2,\number#3)}}
+\unexpanded\def\getrandomdimen #1#2#3{#1=\ctxcommand{getrandomcounta(\number\dimexpr#2,\number\dimexpr#3)}\scaledpoint}
+\unexpanded\def\getrandomnumber#1#2#3{\edef#1{\ctxcommand{getrandomcounta(\number#2,\number#3)}}}
+\unexpanded\def\getrandomfloat #1#2#3{\edef#1{\ctxcommand{getrandomcountb(\number\dimexpr#2\points,\number\dimexpr#3\points)}}}
+\unexpanded\def\setrandomseed #1{\ctxcommand{setrandomseed(\number#1)}}
+\unexpanded\def\getrandomseed #1{\edef#1{\ctxcommand{getrandomseed()}}}
+\unexpanded\def\freezerandomseed {\ctxcommand{freezerandomseed()}}
+\unexpanded\def\defrostrandomseed {\ctxcommand{defrostrandomseed()}}
\endinput
diff --git a/Master/texmf-dist/tex/context/base/supp-spe.mkii b/Master/texmf-dist/tex/context/base/supp-spe.mkii
index 8cb8e2ac177..4625695c7a2 100644
--- a/Master/texmf-dist/tex/context/base/supp-spe.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-spe.mkii
@@ -5,7 +5,7 @@
%D subtitle=Specials,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-tpi.mkii b/Master/texmf-dist/tex/context/base/supp-tpi.mkii
index 9b2ac93283b..16e42359689 100644
--- a/Master/texmf-dist/tex/context/base/supp-tpi.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-tpi.mkii
@@ -5,7 +5,7 @@
%D subtitle=\TPIC\ Conversion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-vis.mkii b/Master/texmf-dist/tex/context/base/supp-vis.mkii
index f38c8e1e353..22a745b1308 100644
--- a/Master/texmf-dist/tex/context/base/supp-vis.mkii
+++ b/Master/texmf-dist/tex/context/base/supp-vis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Visualization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/supp-vis.mkiv b/Master/texmf-dist/tex/context/base/supp-vis.mkiv
index f38c8e1e353..1b025316215 100644
--- a/Master/texmf-dist/tex/context/base/supp-vis.mkiv
+++ b/Master/texmf-dist/tex/context/base/supp-vis.mkiv
@@ -5,13 +5,14 @@
%D subtitle=Visualization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
-% no longer generic, who cares ...
+%D This module is no longer generic \unknown\ but who cares. Maybe
+%D the code will be moved out of the core (apart from ruled boxes).
%D \gdef\ShowBufferedExample% private typeseting macro
%D {\startlinecorrection
@@ -47,16 +48,6 @@
%D \egroup
%D \stoplinecorrection}
-%D Although an integral part of \CONTEXT, this module is one
-%D of the support modules. Its stand alone character permits
-%D use in \PLAIN\ \TEX\ or \TEX\ based macropackages.
-%D \ifCONTEXT \else If in some examples the verbatim listings
-%D don't show up nice, this is due to processing by a system
-%D that does not support buffering. In \CONTEXT\ we show the
-%D commands in the margin, use bit more advanced way of
-%D numbering, and typeset the source in \TEX nicolored
-%D verbatim. Sorry for this inconvenience.\fi
-%D
%D Depending on my personal needs and those of whoever uses it,
%D the macros will be improved in terms of visualization,
%D efficiency and compatibility. These rather low level
@@ -65,9 +56,10 @@
%D attention. Most of those macros can be found in \type
%D {core-vis} and other core modules. Their integration in
%D \CONTEXT\ prohibits generic applications.
-
-\ifx \undefined \writestatus \input supp-mis.tex \fi
-
+%D
+%D We no longer assume usage outside context so we no longer
+%D load support modules.
+%D
%D One of the strong points of \TEX\ is abstraction of textual
%D input. When macros are defined well and do what we
%D want them to do, we will seldom need the tools present in
@@ -103,7 +95,7 @@
%D unwanted results. We can therefore turn all those things
%D off with \type{\dontinterfere}.
-\def\dontinterfere
+\unexpanded\def\dontinterfere % or maybe just forgetall
{\everypar \emptytoks
\let\par \endgraf
\parindent\zeropoint
@@ -119,14 +111,15 @@
%D don't want to be confronted with to many over- and underfull
%D messages we introduce \type{\dontcomplain}.
-\def\dontcomplain
- {\hbadness\!!tenthousand \vbadness\hbadness
- \hfuzz \maxdimen \vfuzz \hfuzz}
+\ifdefined\dontcomplain \else
-% This obsolete dutch name is sometimes uses in manual styles; when
-% cleaning up the codebase I decided to move this definition here.
+ \unexpanded\def\dontcomplain
+ {\hbadness\plustenthousand
+ \vbadness\plustenthousand
+ \hfuzz \maxdimen
+ \vfuzz \maxdimen}
-\let\mindermeldingen\dontcomplain
+\fi
%D \macros
%D {normaloffinterlineskip}
@@ -134,8 +127,8 @@
%D The next hack is needed because in \CONTEXT\ we redefine
%D \type{\offinterlineskip}.
-\ifx\undefined\normaloffinterlineskip
- \let\normaloffinterlineskip\offinterlineskip
+\ifdefined\normaloffinterlineskip \else
+ \let\normaloffinterlineskip\offinterlineskip
\fi
%D \macros
@@ -148,8 +141,6 @@
%D baseline behavior. Especially \type{\vtop}'s need our
%D special attention.
-% already saved
-
%D \macros
%D {normalhskip,
%D normalvskip}
@@ -157,8 +148,6 @@
%D Next come the flexible skips, which come in two flavors
%D too. Like boxes these are handled with \TEX\ primitives.
-% already saved
-
%D \macros
%D {normalpenalty,
%D normalkern}
@@ -167,8 +156,6 @@
%D primitives. This means that when making them visible, we
%D have to take the current mode into account.
-% already saved
-
%D \macros
%D {normalhglue,
%D normalvglue}
@@ -177,8 +164,8 @@
%D As we will see, their definitions make the implementation of
%D their visible counterparts a bit more \TeX{}nical.
-\let\normalhglue = \hglue
-\let\normalvglue = \vglue
+\let\normalhglue\hglue
+\let\normalvglue\vglue
%D \macros
%D {normalmkern,
@@ -190,8 +177,6 @@
%D with other dimensions. As a result, the visual appearance
%D of these primitives is kept primitive too.
-% already saved
-
%D \macros
%D {hfilneg,
%D vfilneg}
@@ -201,12 +186,12 @@
%D offers \type{\hfilneg} and \type{\vfilneg}, we define our
%D own alternative double \type{ll}'ed ones.
-\def\hfilneg {\normalhskip\zeropoint \!!plus-1fil\relax}
-\def\vfilneg {\normalvskip\zeropoint \!!plus-1fil\relax}
-\def\hfillneg {\normalhskip\zeropoint \!!plus-1fill\relax}
-\def\vfillneg {\normalvskip\zeropoint \!!plus-1fill\relax}
-\def\hfilllneg{\normalhskip\zeropoint \!!plus-1filll\relax}
-\def\vfilllneg{\normalvskip\zeropoint \!!plus-1filll\relax}
+\def\hfilneg {\normalhskip\zeropoint\!!plus-1fil\relax}
+\def\vfilneg {\normalvskip\zeropoint\!!plus-1fil\relax}
+\def\hfillneg {\normalhskip\zeropoint\!!plus-1fill\relax}
+\def\vfillneg {\normalvskip\zeropoint\!!plus-1fill\relax}
+\def\hfilllneg{\normalhskip\zeropoint\!!plus-1filll\relax}
+\def\vfilllneg{\normalvskip\zeropoint\!!plus-1filll\relax}
%D \macros
%D {normalhss,normalhfil,normalhfill,
@@ -226,24 +211,22 @@
%D in standard \TEX\ documentation. They can nevertheless be
%D used at will.
-\let\normalhfillneg = \hfillneg
-\let\normalvfillneg = \vfillneg
+\let\normalhfillneg\hfillneg
+\let\normalvfillneg\vfillneg
%D Visualization is not always wanted. Instead of turning this
%D option off in those (unpredictable) situations, we just
%D redefine a few \PLAIN\ macros.
-\ifx\tlap\undefined
-
- \def\rlap#1{\normalhbox to \zeropoint{#1\normalhss}}
- \def\llap#1{\normalhbox to \zeropoint{\normalhss#1}}
- \def\blap#1{\normalvbox to \zeropoint{#1\normalvss}}
- \def\tlap#1{\normalvbox to \zeropoint{\normalvss#1}}
-
-\fi
+% \ifx\tlap\undefined
+%
+% \def\rlap#1{\normalhbox to \zeropoint{#1\normalhss}}
+% \def\llap#1{\normalhbox to \zeropoint{\normalhss#1}}
+% \def\blap#1{\normalvbox to \zeropoint{#1\normalvss}}
+% \def\tlap#1{\normalvbox to \zeropoint{\normalvss#1}}
+%
+% \fi
-\ifx\contextversion\undefined \def~{\normalpenalty\!!tenthousand\ } \fi
-
%D \macros
%D {makeruledbox}
%D
@@ -271,8 +254,8 @@
%D At the cost of some overhead these alternatives are
%D implemented using \type{\if}'s:
-\newif\ifbaselinerule \baselineruletrue
-\newif\ifbaselinefill \baselinefillfalse
+\newif\ifbaselinerule\baselineruletrue
+\newif\ifbaselinefill\baselinefillfalse
%D \macros
%D {iftoprule,ifbottomrule,ifleftrule,ifrightrule}
@@ -288,10 +271,10 @@
%D
%D As we see below:
-\newif\iftoprule \topruletrue
-\newif\ifbottomrule \bottomruletrue
-\newif\ifleftrule \leftruletrue
-\newif\ifrightrule \rightruletrue
+\newif\iftoprule \topruletrue
+\newif\ifbottomrule\bottomruletrue
+\newif\ifleftrule \leftruletrue
+\newif\ifrightrule \rightruletrue
%D \macros
%D {boxrulewidth}
@@ -303,12 +286,14 @@
%D \starttyping
%D \boxrulewidth=.2pt
%D \stoptyping
-%D
-%D Although we are already low on \DIMENSIONS\ it's best to
-%D spend one here, mainly because it enables easy manipulation,
-%D like multiplication by a given factor.
-\newdimen\boxrulewidth \boxrulewidth=.2pt
+\newdimen \boxrulewidth \boxrulewidth=.2pt
+
+\newdimen \boxruleht
+\newdimen \boxruledp
+\newdimen \boxrulewd
+
+\newbox \boxrulescratchbox
%D The core macro \type{\makeruledbox} looks a bit hefty. The
%D manipulation at the end is needed because we want to
@@ -328,32 +313,28 @@
%D primitive too. By storing and restoring the height and depth
%D of box \type{#1}, we preserve the mode.
-\let\dowithruledbox\relax
-
-\let\ruledheight\!!zeropoint
-\let\ruleddepth \!!zeropoint
-\let\ruledwidth \!!zeropoint
+\let\dowithruledbox\relax % hook
-\def\makeruledbox#1%
- {\edef\ruledheight{\the\ht#1}%
- \edef\ruleddepth {\the\dp#1}%
- \edef\ruledwidth {\the\wd#1}%
- \setbox\scratchbox\normalvbox
+\unexpanded\def\makeruledbox#1%
+ {\boxruleht\ht#1%
+ \boxruledp\dp#1%
+ \boxrulewd\wd#1%
+ \setbox\boxrulescratchbox\normalvbox
{\dontcomplain
\normaloffinterlineskip
\visualhrule
\!!height\boxrulewidth
\iftoprule\else\!!width\zeropoint\fi
\normalvskip-\boxrulewidth
- \normalhbox to \ruledwidth
+ \normalhbox to \boxrulewd
{\visualvrule
- \!!height\ruledheight
- \!!depth\ruleddepth
- \!!width\ifleftrule\else0\fi\boxrulewidth
- \ifdim\ruledheight>\zeropoint \else \baselinerulefalse \fi
- \ifdim\ruleddepth>\zeropoint \else \baselinerulefalse \fi
+ \!!height\boxruleht
+ \!!depth \boxruledp
+ \!!width \ifleftrule\boxrulewidth\else\zeropoint\fi
+ \ifdim\boxruleht>\zeropoint \else \baselinerulefalse \fi
+ \ifdim\boxruledp>\zeropoint \else \baselinerulefalse \fi
\ifbaselinerule
- \ifdim\ruledwidth<20\boxrulewidth
+ \ifdim\boxrulewd<20\boxrulewidth
\baselinefilltrue
\fi
\cleaders
@@ -371,7 +352,7 @@
\fi
\normalhfill
\visualvrule
- \!!width\ifrightrule\else0\fi\boxrulewidth}%
+ \!!width\ifrightrule\boxrulewidth\else\zeropoint\fi}%
\normalvskip-\boxrulewidth
\visualhrule
\!!height\boxrulewidth
@@ -380,10 +361,10 @@
\setbox#1=\ifhbox#1\normalhbox\else\normalvbox\fi
{\normalhbox
{\box#1%
- \lower\ruleddepth\normalhbox{\dowithruledbox{\box\scratchbox}}}}%
- \ht#1=\ruledheight
- \wd#1=\ruledwidth
- \dp#1=\ruleddepth}
+ \lower\boxruledp\normalhbox{\dowithruledbox{\box\boxrulescratchbox}}}}%
+ \ht#1\boxruleht
+ \wd#1\boxrulewd
+ \dp#1\boxruledp}
%D Just in case one didn't notice: the rules are in fact layed
%D over the box. This way the contents of a box cannot
@@ -417,8 +398,12 @@
\unexpanded\def\ruledhbox
{\normalhbox\bgroup
- \dowithnextbox{\makeruledbox\nextbox\box\nextbox\egroup}%
- \normalhbox}
+ \dowithnextboxcs\supp_visualizers_hbox_finish\normalhbox}
+
+\def\supp_visualizers_hbox_finish
+ {\makeruledbox\nextbox
+ \box\nextbox
+ \egroup}
%D \startbuffer
%D \vbox
@@ -435,8 +420,12 @@
\unexpanded\def\ruledvbox
{\normalvbox\bgroup
- \dowithnextbox{\makeruledbox\nextbox\box\nextbox\egroup}%
- \normalvbox}
+ \dowithnextboxcs\supp_visualizers_vbox_finish\normalvbox}
+
+\def\supp_visualizers_vbox_finish
+ {\makeruledbox\nextbox
+ \box\nextbox
+ \egroup}
%D \startbuffer
%D \vtop
@@ -453,8 +442,12 @@
\unexpanded\def\ruledvtop
{\normalvtop\bgroup
- \dowithnextbox{\makeruledbox\nextbox\box\nextbox\egroup}%
- \normalvtop}
+ \dowithnextboxcs\supp_visualizers_vtop_finish\normalvtop}
+
+\def\supp_visualizers_vtop_finish
+ {\makeruledbox\nextbox
+ \box\nextbox
+ \egroup}
%D \startbuffer
%D \hbox
@@ -471,14 +464,16 @@
\unexpanded\def\ruledvcenter
{\normalvbox\bgroup
\dontinterfere
- \dowithnextbox
- {\scratchdimen.5\ht\nextbox
- \advance\scratchdimen .5\dp\nextbox
- \ht\nextbox\scratchdimen
- \dp\nextbox\scratchdimen
- \ruledhbox{\box\nextbox}%
- \egroup}%
- \normalvbox}
+ \dowithnextboxcs\supp_visualizers_vcenter_finish\normalvbox}
+
+\def\supp_visualizers_vcenter_finish
+ {\scratchdimen.5\dimexpr\ht\nextbox+\dp\nextbox\relax
+ \ht\nextbox\scratchdimen
+ \dp\nextbox\scratchdimen
+ %\ruledhbox{\box\nextbox}%
+ \makeruledbox\nextbox
+ \box\nextbox
+ \egroup}
%D \macros
%D {ruledbox,
@@ -504,10 +499,23 @@
%D variant that does not need the~\type{=}, but we stick to:
\unexpanded\def\ruledbox
- {\dowithnextbox{\makeruledbox\nextbox\box\nextbox}}
+ {\dowithnextboxcs\supp_visualizers_box_finish}
+
+\def\supp_visualizers_box_finish
+ {\makeruledbox\nextbox\box\nextbox}
+
+% \def\setruledbox#1=%
+% {\dowithnextbox{\makeruledbox\nextbox\setbox#1\nextbox}}
-\def\setruledbox#1=%
- {\dowithnextbox{\makeruledbox\nextbox\setbox#1\nextbox}}
+\def\setruledbox#1=% not nice, better
+ {\afterassignment\supp_visualizers_setruledbox_indeed\scratchcounter}
+
+\def\supp_visualizers_setruledbox_indeed
+ {\dowithnextboxcs\supp_visualizers_setruledbox_finish}
+
+\def\supp_visualizers_setruledbox_finish
+ {\makeruledbox\nextbox
+ \setbox\scratchcounter\nextbox}
%D \macros
%D {investigateskip,
@@ -538,7 +546,8 @@
%D Users of these macros are invited to study their exact
%D behavior first. The positive and negative states both
%D include zero and are in fact non-negative ($\geq0$) and
-%D non-positive ($\leq0$) .
+%D non-positive ($\leq0$). Well, no dirty trick is needed
+%D any longer as we have \ETEX\ functionality.
\newif\ifflexible
\newif\ifzero
@@ -547,10 +556,19 @@
\def\investigateskip#1%
{\relax
- \scratchdimen#1\relax
- \edef\!!stringa{\the\scratchdimen}%
- \edef\!!stringb{\the#1}%
- \ifx\!!stringa\!!stringb \flexiblefalse \else \flexibletrue \fi
+ \ifdim#1=\zeropoint
+ \ifdim\gluestretch#1=\zeropoint
+ \ifdim\glueshrink#1=\zeropoint
+ \flexiblefalse
+ \else
+ \flexibletrue
+ \fi
+ \else
+ \flexibletrue
+ \fi
+ \else
+ \flexibletrue
+ \fi
\ifdim#1=\zeropoint\relax
\zerotrue \else
\zerofalse \fi
@@ -561,33 +579,6 @@
\negativefalse \else
\negativetrue \fi}
-% etex
-%
-% \def\investigateskip#1%
-% {\relax
-% \ifdim\scratchskip=\zeropoint
-% \ifdim\gluestretch\scratchskip=\zeropoint
-% \ifdim\glueshrink\scratchskip=\zeropoint
-% \flexiblefalse
-% \else
-% \flexibletrue
-% \fi
-% \else
-% \flexibletrue
-% \fi
-% \else
-% \flexibletrue
-% \fi
-% \ifdim#1=\zeropoint\relax
-% \zerotrue \else
-% \zerofalse \fi
-% \ifdim#1<\zeropoint\relax
-% \positivefalse \else
-% \positivetrue \fi
-% \ifdim#1>\zeropoint\relax
-% \negativefalse \else
-% \negativetrue \fi}
-
\def\investigatecount#1%
{\relax
\flexiblefalse
@@ -601,9 +592,9 @@
\negativefalse \else
\negativetrue \fi}
-\def\investigatemuskip#1%
+\def\investigatemuskip#1% etex ?
{\relax
- \edef\!!stringa{\the\scratchmuskip}%
+ \edef\!!stringa{\the#1}%
\edef\!!stringb{0mu}%
\def\!!stringc##1##2\\{##1}%
\expandafter\edef\expandafter\!!stringc\expandafter
@@ -624,7 +615,7 @@
\negativefalse
\fi
\fi}
-
+
%D Now the neccessary utility macros are defined, we can make a
%D start with the visualizing ones. The implementation of these
%D macros is a compromise between readability, efficiency of
@@ -819,20 +810,11 @@
%D All five substitutions use the same auxiliary macro. Watch
%D the positive first -- negative next approach.
-\unexpanded\def\ruledhss
- {\doruledhfiller\normalhss\normalhfilneg{0}{0}}
-
-\unexpanded\def\ruledhfil
- {\doruledhfiller\normalhfil\normalhfilneg{10}{-6}}
-
-\unexpanded\def\ruledhfill
- {\doruledhfiller\normalhfill\normalhfillneg{18}{-14}}
-
-\unexpanded\def\ruledhfilneg
- {\doruledhfiller\normalhfilneg\normalhfil{-6}{10}}
-
-\unexpanded\def\ruledhfillneg
- {\doruledhfiller\normalhfillneg\normalhfill{-14}{18}}
+\unexpanded\def\ruledhss {\doruledhfiller\normalhss \normalhfilneg {0}{0}}
+\unexpanded\def\ruledhfil {\doruledhfiller\normalhfil \normalhfilneg {10}{-6}}
+\unexpanded\def\ruledhfill {\doruledhfiller\normalhfill \normalhfillneg{18}{-14}}
+\unexpanded\def\ruledhfilneg {\doruledhfiller\normalhfilneg \normalhfil {-6}{10}}
+\unexpanded\def\ruledhfillneg{\doruledhfiller\normalhfillneg\normalhfill {-14}{18}}
%D \macros
%D {ruledvss,
@@ -949,7 +931,7 @@
%D stretch could be drawing the mid line over a length of the
%D stretch, in positive or negative direction.
-\def\doruledhskip
+\def\supp_visualizers_hskip_indeed
{\relax
\dontinterfere
\dontcomplain
@@ -1007,7 +989,7 @@
\divide\skip2 2
\advance\scratchskip -\skip2
\normalhskip\scratchskip
- \normalpenalty\!!tenthousand
+ \normalpenalty\plustenthousand
\box0
\normalhskip\skip2
\else
@@ -1018,7 +1000,7 @@
\unexpanded\def\ruledhskip
{\bgroup
- \afterassignment\doruledhskip
+ \afterassignment\supp_visualizers_hskip_indeed
\scratchskip=}
%D The visual skip is located at a feasible point. Normally
@@ -1147,7 +1129,7 @@
\normalvskip\skip2
\fi
\fi
- \normalpenalty\!!tenthousand
+ \normalpenalty\plustenthousand
\box0
\prevdepth\nextdepth % not \dp0=\nextdepth
\normalvskip\scratchskip}
@@ -1170,7 +1152,7 @@
{\bgroup
\afterassignment\doruledvskip
\scratchskip=}
-
+
%D \macros
%D {ruledkern}
%D
@@ -1201,7 +1183,7 @@
%D visualized a bit different, because we want to see them
%D anyhow.
-\def\doruledhkern
+\def\supp_visualizers_hkern_indeed
{\dontinterfere
\dontcomplain
\baselinerulefalse
@@ -1238,7 +1220,7 @@
\setbox0\ruledhbox{\box0}% \make...
\fi
\smashbox0%
- \normalpenalty\!!tenthousand
+ \normalpenalty\plustenthousand
\normalhbox to \zeropoint
{\ifnegative\normalhskip1\scratchskip\fi
\box0}%
@@ -1248,7 +1230,7 @@
\unexpanded\def\ruledhkern#1%
{\bgroup
\let\afterwards#1%
- \afterassignment\doruledhkern
+ \afterassignment\supp_visualizers_hkern_indeed
\scratchskip=}
%D After having seen the horizontal ones, the vertical kerns
@@ -1275,7 +1257,7 @@
%D Like before, we have to postpone \type{\prevdepth}. If we
%D leave out this trick, we got ourselves some wrong spacing.
-\def\dodoruledvkern
+\def\supp_visualizers_vkern_finish
{\nextdepth\prevdepth
\dontinterfere
\dontcomplain
@@ -1319,17 +1301,17 @@
\normalvcue
{\ifnegative\normalhskip-16\testrulewidth\fi\box0}}%
\smashbox0%
- \normalpenalty\!!tenthousand
+ \normalpenalty\plustenthousand
\box0
\prevdepth\nextdepth} % not \dp0=\nextdepth
-\def\doruledvkern
+\def\supp_visualizers_vkern_indeed
{\ifdim\pagegoal=\maxdimen
\ifinner
- \dodoruledvkern
+ \supp_visualizers_vkern_finish
\fi
\else
- \dodoruledvkern
+ \supp_visualizers_vkern_finish
\fi
\afterwards\scratchskip
\egroup}
@@ -1337,7 +1319,7 @@
\unexpanded\def\ruledvkern#1%
{\bgroup
\let\afterwards#1\relax
- \afterassignment\doruledvkern
+ \afterassignment\supp_visualizers_vkern_indeed
\scratchskip=}
\unexpanded\def\ruledkern
@@ -1354,7 +1336,7 @@
%D \unexpanded\def\ruledkern%
%D {\csname ruled\ifvmode v\else h\fi kern\endcsname\normalkern}
%D \stoptyping
-
+
%D \macros
%D {ruledhglue,ruledvglue}
%D
@@ -1378,18 +1360,18 @@
%D
%D \ShowBufferedExample
-\def\doruledhglue
+\def\supp_visualizers_hglue_indeed
{\leavevmode
\scratchcounter\spacefactor
\visualvrule\!!width\zeropoint
- \normalpenalty\!!tenthousand
+ \normalpenalty\plustenthousand
\ruledhkern\normalhskip\scratchskip
\spacefactor\scratchcounter
\egroup}
\unexpanded\def\ruledhglue
{\bgroup
- \afterassignment\doruledhglue\scratchskip=}
+ \afterassignment\supp_visualizers_hglue_indeed\scratchskip=}
%D \startbuffer
%D first line
@@ -1408,18 +1390,18 @@
%D
%D \ShowBufferedExample
-\def\doruledvglue
+\def\supp_visualizers_vglue_indeed
{\endgraf % \par
\nextdepth\prevdepth
\visualhrule\!!height\zeropoint
- \normalpenalty\!!tenthousand
+ \normalpenalty\plustenthousand
\ruledvkern\normalvskip\scratchskip
\prevdepth\nextdepth
\egroup}
\unexpanded\def\ruledvglue
{\bgroup
- \afterassignment\doruledvglue\scratchskip=}
+ \afterassignment\supp_visualizers_vglue_indeed\scratchskip=}
%D \macros
%D {ruledmkern,ruledmskip}
@@ -1430,40 +1412,40 @@
%D subtle matter, we've used a very simple, not overloaded way
%D to show them.
-\def\dodoruledmkern#1%
+\def\supp_visualizers_mkern_finish#1%
{\dontinterfere
\dontcomplain
- \setbox0\normalhbox
- {$\normalmkern\ifnegative-\fi\scratchmuskip$}%
- \setbox0\normalhbox to \wd0
+ \setbox\boxrulescratchbox\normalhbox
+ {$\normalmkern\ifnegative-\fi\scratchskip$}%
+ \setbox\boxrulescratchbox\normalhbox to \wd\boxrulescratchbox
{\visualvrule
\!!height16\testrulewidth
- \!!depth16\testrulewidth
- \!!width\testrulewidth
+ \!!depth 16\testrulewidth
+ \!!width \testrulewidth
\leaders
\visualhrule
- \!!height\ifpositive16\else-14\fi\testrulewidth
- \!!depth\ifpositive-14\else16\fi\testrulewidth
+ \!!height\ifpositive 16\else-14\fi\testrulewidth
+ \!!depth \ifpositive-14\else 16\fi\testrulewidth
\normalhfill
\ifflexible
- \normalhskip-\wd0
+ \normalhskip-\wd\boxrulescratchbox
\leaders
\visualhrule
\!!height\testrulewidth
- \!!depth\testrulewidth
+ \!!depth \testrulewidth
\normalhfill
\fi
\visualvrule
\!!height16\testrulewidth
- \!!depth16\testrulewidth
- \!!width\testrulewidth}%
+ \!!depth 16\testrulewidth
+ \!!width \testrulewidth}%
\smashbox0%
\ifnegative
- #1\scratchmuskip
- \box0
+ #1\scratchskip
+ \box\boxrulescratchbox
\else
- \box0
- #1\scratchmuskip
+ \box\boxrulescratchbox
+ #1\scratchskip
\fi
\egroup}
@@ -1476,14 +1458,15 @@
%D
%D \ShowBufferedExample
-\def\doruledmkern
- {\investigatemuskip\scratchmuskip
- \flexiblefalse
- \dodoruledmkern\normalmkern}
-
\unexpanded\def\ruledmkern
{\bgroup
- \afterassignment\doruledmkern\scratchmuskip=}
+ \afterassignment\supp_visualizers_mkern_indeed
+ \scratchmuskip=}
+
+\def\supp_visualizers_mkern_indeed
+ {\investigatemuskip\scratchmuskip
+ \flexiblefalse
+ \supp_visualizers_mkern_finish\normalmkern}
%D \startbuffer
%D $a \mskip3mu = \mskip3mu
@@ -1494,15 +1477,16 @@
%D
%D \ShowBufferedExample
-\def\doruledmskip
+\def\supp_visualizers_mskip_indeed
{\investigatemuskip\scratchmuskip
\flexibletrue
- \dodoruledmkern\normalmskip}
+ \supp_visualizers_mkern_finish\normalmskip}
\unexpanded\def\ruledmskip
{\bgroup
- \afterassignment\doruledmskip\scratchmuskip=}
-
+ \afterassignment\supp_visualizers_mskip_indeed
+ \scratchmuskip=}
+
%D \macros
%D {penalty}
%D
@@ -1571,43 +1555,43 @@
%D test \ruledhpenalty1000 \ruledhpenalty-1000
%D test
-\def\setruledpenaltybox#1#2#3#4#5#6%
+\def\supp_visualizers_penalty_box#1#2#3#4#5#6%
{\setbox#1\normalhbox
- {\ifnum#2=0 \else
- \edef\sign
- {\ifnum#2>0 +\else-\fi}%
- \dimen0=\ifnum\sign#2>9999
- 28\else
- \ifnum\sign#2>999
- 22\else
- \ifnum\sign#2>99
- 16\else
- \ifnum\sign#2>9
- 10\else
- 4
- \fi\fi\fi\fi \testrulewidth
- \ifnum#2<0
- \normalhskip-\dimen0
+ {\ifnum#2=\zerocount \else
+ \edef\sign{\ifnum#2>\zerocount +\else-\fi}%
+ \scratchdimen
+ \ifnum\sign#2>9999 28\else
+ \ifnum\sign#2>999 22\else
+ \ifnum\sign#2>99 16\else
+ \ifnum\sign#2>9 10\else
+ 4\fi\fi\fi\fi \testrulewidth
+ \ifnum#2<\zerocount
+ \normalhskip-\scratchdimen
\normalhskip-2\testrulewidth
\visualvrule
- \!!width2\testrulewidth
+ \!!width 2\testrulewidth
\!!height#3\testrulewidth
- \!!depth#4\testrulewidth
+ \!!depth #4\testrulewidth
\fi
\visualvrule
- \!!width\dimen0
+ \!!width \scratchdimen
\!!height#5\testrulewidth
- \!!depth#6\testrulewidth
- \ifnum#2>0
+ \!!depth #6\testrulewidth
+ \ifnum#2>\zerocount
\visualvrule
- \!!width2\testrulewidth
+ \!!width 2\testrulewidth
\!!height#3\testrulewidth
- \!!depth#4\testrulewidth
+ \!!depth #4\testrulewidth
\fi
\fi}%
\smashbox#1}
-\def\doruledhpenalty
+\unexpanded\def\ruledhpenalty
+ {\bgroup
+ \afterassignment\supp_visualizers_hpenalty_indeed
+ \scratchcounter=}
+
+\def\supp_visualizers_hpenalty_indeed
{\dontinterfere
\dontcomplain
\investigatecount\scratchcounter
@@ -1617,10 +1601,10 @@
{\ifnegative\else\normalhss\fi
\visualvrule
\!!depth8\testrulewidth
- \!!width\ifzero0\else4\fi\testrulewidth
+ \!!width\ifzero\zeropoint\else4\testrulewidth\fi
\ifpositive\else\normalhss\fi}%
- \setruledpenaltybox{2}{\scratchcounter}{0}{8}{-3.5}{4.5}%
- \normalpenalty\!!tenthousand
+ \supp_visualizers_penalty_box{2}{\scratchcounter}{0}{8}{-3.5}{4.5}%
+ \normalpenalty\plustenthousand
\setbox0\normalhbox
{\normalhskip-4\testrulewidth
\ifnegative
@@ -1633,11 +1617,6 @@
\normalpenalty\scratchcounter
\egroup}
-\unexpanded\def\ruledhpenalty
- {\bgroup
- \afterassignment\doruledhpenalty
- \scratchcounter=}
-
%D The size of a vertical penalty is also shown on the
%D horizontal axis. This way there is less interference with
%D the often preceding or following skips and kerns.
@@ -1657,9 +1636,13 @@
%D
%D \ShowBufferedExample
-\def\doruledvpenalty
- {\ifdim\pagegoal=\maxdimen
- \else
+\unexpanded\def\ruledvpenalty
+ {\bgroup
+ \afterassignment\supp_visualizers_vpenalty_indeed
+ \scratchcounter=}
+
+\def\supp_visualizers_vpenalty_indeed
+ {\ifdim\pagegoal=\maxdimen \else
\nextdepth\prevdepth
\dontinterfere
\dontcomplain
@@ -1669,13 +1652,13 @@
\setbox0\ruledhbox
{\visualvrule
\!!height4\testrulewidth
- \!!depth4\testrulewidth
- \!!width\zeropoint
+ \!!depth 4\testrulewidth
+ \!!width \zeropoint
\visualvrule
\!!height\ifnegative.5\else4\fi\testrulewidth
- \!!depth\ifpositive.5\else4\fi\testrulewidth
- \!!width8\testrulewidth}%
- \setruledpenaltybox{2}{\scratchcounter}{4}{4}{.5}{.5}%
+ \!!dept \ifpositive.5\else4\fi\testrulewidth
+ \!!width 8\testrulewidth}%
+ \supp_visualizers_penalty_box{2}{\scratchcounter}{4}{4}{.5}{.5}%
\setbox0\normalhbox
{\normalhskip-4\testrulewidth
\ifnegative
@@ -1685,7 +1668,7 @@
\fi
\normalhss}%
\smashbox0%
- \normalpenalty\!!tenthousand
+ \normalpenalty\plustenthousand
\nointerlineskip
\dp0\nextdepth % not \prevdepth=\nextdepth
\normalvbox
@@ -1694,10 +1677,7 @@
\normalpenalty\scratchcounter
\egroup}
-\unexpanded\def\ruledvpenalty
- {\bgroup
- \afterassignment\doruledvpenalty
- \scratchcounter=}
+%D This comes together in:
\unexpanded\def\ruledpenalty
{\ifvmode
@@ -1706,14 +1686,6 @@
\expandafter\ruledhpenalty
\fi}
-%D At the cost of some more tokens, a bit more clever
-%D implementation would be:
-%D
-%D \starttyping
-%D \unexpanded\def\ruledpenalty%
-%D {\csname ruled\ifvmode v\else h\fi penalty\endcsname}
-%D \stoptyping
-
%D \macros
%D {showfils,dontshowfils,
%D showboxes,dontshowboxes,
@@ -1725,7 +1697,7 @@
\newif\ifshowingcomposition % see later why we need this
-\def\showfils
+\unexpanded\def\showfils
{\showingcompositiontrue
\let\hss \ruledhss
\let\hfil \ruledhfil
@@ -1738,7 +1710,7 @@
\let\vfilneg \ruledvfilneg
\let\vfillneg \ruledvfillneg}
-\def\dontshowfils
+\unexpanded\def\dontshowfils
{\let\hss \normalhss
\let\hfil \normalhfil
\let\hfill \normalhfill
@@ -1750,7 +1722,7 @@
\let\vfilneg \normalvfilneg
\let\vfillneg \normalvfillneg}
-\def\showboxes
+\unexpanded\def\showboxes
{\showingcompositiontrue
\baselineruletrue
\let\hbox \ruledhbox
@@ -1758,13 +1730,13 @@
\let\vtop \ruledvtop
\let\vcenter \ruledvcenter}
-\def\dontshowboxes
+\unexpanded\def\dontshowboxes
{\let\hbox \normalhbox
\let\vbox \normalvbox
\let\vtop \normalvtop
\let\vcenter \normalvcenter}
-\def\showskips
+\unexpanded\def\showskips
{\showingcompositiontrue
\let\hskip \ruledhskip
\let\vskip \ruledvskip
@@ -1774,7 +1746,7 @@
\let\hglue \ruledhglue
\let\vglue \ruledvglue}
-\def\dontshowskips
+\unexpanded\def\dontshowskips
{\let\hskip \normalhskip
\let\vskip \normalvskip
\let\kern \normalkern
@@ -1783,11 +1755,11 @@
\let\hglue \normalhglue
\let\vglue \normalvglue}
-\def\showpenalties
+\unexpanded\def\showpenalties
{\showingcompositiontrue
\let\penalty \ruledpenalty}
-\def\dontshowpenalties
+\unexpanded\def\dontshowpenalties
{\let\penalty \normalpenalty}
%D \macros
@@ -1814,7 +1786,7 @@
\newif\ifshowingcomposition
-\def\showcomposition
+\unexpanded\def\showcomposition
{\ifshowingcomposition
\showfils
\showboxes
@@ -1822,7 +1794,7 @@
\showpenalties
\fi}
-\def\dontshowcomposition
+\unexpanded\def\dontshowcomposition
{\ifshowingcomposition
\dontshowfils
\dontshowboxes
@@ -1851,25 +1823,18 @@
%D Beware, it's a macro not a \DIMENSION.
\ifx\bodyfontsize\undefined
- \edef\defaulttestrulewidth{\the\testrulewidth}
+ \edef\defaulttestrulewidth{\the\testrulewidth}
\else
- \def\defaulttestrulewidth{.02\bodyfontsize}
+ \def\defaulttestrulewidth{.02\bodyfontsize}
\fi
-\def\showmakeup
+\unexpanded\def\showmakeup
{\testrulewidth\defaulttestrulewidth
\showingcompositiontrue
\showcomposition}
\protect
-%D \ifCONTEXT \let\next=\relax \else \let\next=\endinput
-%D The documented source you have been reading was processed
-%D using some surrogate makeup. When this file is processed
-%D in \CONTEXT, a few more examples show up here, like a local
-%D table of contents and a local register.
-%D \fi \next
-
%D Lets end with some more advanced examples.
%D Definitions and enumerations come in many flavors. The
%D next one for instance is defined as:
diff --git a/Master/texmf-dist/tex/context/base/symb-cow.mkii b/Master/texmf-dist/tex/context/base/symb-cow.mkii
index fac6ca485bd..933a00c45e7 100644
--- a/Master/texmf-dist/tex/context/base/symb-cow.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-cow.mkii
@@ -5,7 +5,7 @@
%D subtitle=Cow Symbols,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-eur.mkii b/Master/texmf-dist/tex/context/base/symb-eur.mkii
index 400e88ac5cd..67023ec91c0 100644
--- a/Master/texmf-dist/tex/context/base/symb-eur.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-eur.mkii
@@ -5,7 +5,7 @@
%D subtitle=Adobe Euro Symbols,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-glm.mkii b/Master/texmf-dist/tex/context/base/symb-glm.mkii
index 0b01ca7dfdb..ff94bfe7fc7 100644
--- a/Master/texmf-dist/tex/context/base/symb-glm.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-glm.mkii
@@ -5,7 +5,7 @@
%D subtitle=Guillemots,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-cow.mkiv b/Master/texmf-dist/tex/context/base/symb-imp-cow.mkiv
index adfd484d868..59eabae28ca 100644
--- a/Master/texmf-dist/tex/context/base/symb-cow.mkiv
+++ b/Master/texmf-dist/tex/context/base/symb-imp-cow.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Cow Symbols,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-eur.mkiv b/Master/texmf-dist/tex/context/base/symb-imp-eur.mkiv
index 4ec5a8931cc..19a88c8fa86 100644
--- a/Master/texmf-dist/tex/context/base/symb-eur.mkiv
+++ b/Master/texmf-dist/tex/context/base/symb-imp-eur.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Adobe Euro Symbols,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-jmn.mkiv b/Master/texmf-dist/tex/context/base/symb-imp-jmn.mkiv
index 593e3e375bf..d66e0a33257 100644
--- a/Master/texmf-dist/tex/context/base/symb-jmn.mkiv
+++ b/Master/texmf-dist/tex/context/base/symb-imp-jmn.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Special Navigational Symbols,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-mis.mkiv b/Master/texmf-dist/tex/context/base/symb-imp-mis.mkiv
index 612886daa37..d2657512f3f 100644
--- a/Master/texmf-dist/tex/context/base/symb-mis.mkiv
+++ b/Master/texmf-dist/tex/context/base/symb-imp-mis.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Miscelaneous,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
@@ -16,17 +16,18 @@
%D We predefine some common symbols and conversions that will
%D be understood by many commands. The \type {\mathematics}
%D is no longer needed, although only math fonts might have
-%D these symbols.
+%D these symbols. The \type {\textmath} macro is twice as
+%D efficient.
\definesymbol [\v!none] []
-\definesymbol [bullet] [\mathematics{\bullet}]
-\definesymbol [dash] [\mathematics{-}]
-\definesymbol [star] [\mathematics{\star}]
-\definesymbol [triangle] [\mathematics{\triangleright}]
-\definesymbol [circle] [\mathematics{\circ}]
-\definesymbol [square] [\mathematics{\square}]
-\definesymbol [diamond] [\mathematics{\diamond}]
+\definesymbol [bullet] [\textmath\bullet]
+\definesymbol [dash] [\textmath-]
+\definesymbol [star] [\textmath\star]
+\definesymbol [triangle] [\textmath\triangleright]
+\definesymbol [circle] [\textmath\circ]
+\definesymbol [square] [\textmath\square]
+\definesymbol [diamond] [\textmath\diamond]
% I'm not sure about this ... I dislike the small bullet. So we provide
% it as variant: \type {\setupsymbolset[text]}. Also, we want to be
@@ -49,9 +50,9 @@
\stopsymbolset
-\definesymbol [smallcircle] [\hbox{\raise.1ex\hbox{\mathematics{\scriptscriptstyle\bigcirc}}}]
-\definesymbol [medcircle] [\hbox{\raise.1ex\hbox{\mathematics{\scriptstyle \bigcirc}}}]
-\definesymbol [bigcircle] [\mathematics{\bigcirc}]
+\definesymbol [smallcircle] [\hbox{\raise.1ex\hbox{\textmath{\scriptscriptstyle\bigcirc}}}]
+\definesymbol [medcircle] [\hbox{\raise.1ex\hbox{\textmath{\scriptstyle \bigcirc}}}]
+\definesymbol [bigcircle] [\textmath{\bigcirc}]
\definesymbol [1] [\symbol{bullet}]
\definesymbol [2] [\symbol{dash}]
diff --git a/Master/texmf-dist/tex/context/base/symb-mvs.mkiv b/Master/texmf-dist/tex/context/base/symb-imp-mvs.mkiv
index 312a50a8898..9902fc9e8a3 100644
--- a/Master/texmf-dist/tex/context/base/symb-mvs.mkiv
+++ b/Master/texmf-dist/tex/context/base/symb-imp-mvs.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Martin Vogels Symbole,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-nav.mkiv b/Master/texmf-dist/tex/context/base/symb-imp-nav.mkiv
index 0f5fd289fea..6e2f2c1f034 100644
--- a/Master/texmf-dist/tex/context/base/symb-nav.mkiv
+++ b/Master/texmf-dist/tex/context/base/symb-imp-nav.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Navigational Symbols,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-ini.lua b/Master/texmf-dist/tex/context/base/symb-ini.lua
index 1bc8ee2aaaf..559b032e490 100644
--- a/Master/texmf-dist/tex/context/base/symb-ini.lua
+++ b/Master/texmf-dist/tex/context/base/symb-ini.lua
@@ -18,19 +18,29 @@ local status_symbols = logs.messenger("fonts","symbols")
local patterns = { "symb-imp-%s.mkiv", "symb-imp-%s.tex", "symb-%s.mkiv", "symb-%s.tex" }
local listitem = utilities.parsers.listitem
+local function action(name,foundname)
+ -- context.startnointerference()
+ context.startreadingfile()
+ context.input(foundname)
+ status_symbols("loaded: library '%s'",name)
+ context.stopreadingfile()
+ -- context.stopnointerference()
+end
+
+local function failure(name)
+ report_symbols("unknown: library '%s'",name)
+end
+
function symbols.uselibrary(name)
if name ~= variables.reset then
for name in listitem(name) do
- commands.uselibrary(name,patterns,function(name,foundname)
- -- context.startnointerference()
- context.startreadingfile()
- context.input(foundname)
- status_symbols("loaded: library '%s'",name)
- context.stopreadingfile()
- -- context.stopnointerference()
- end, function(name)
- report_symbols("unknown: library '%s'",name)
- end)
+ commands.uselibrary {
+ name = name,
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = true,
+ }
end
end
end
diff --git a/Master/texmf-dist/tex/context/base/symb-ini.mkii b/Master/texmf-dist/tex/context/base/symb-ini.mkii
index 1df1fe68822..3154c8a04c4 100644
--- a/Master/texmf-dist/tex/context/base/symb-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Basic Symbols Commands,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-ini.mkiv b/Master/texmf-dist/tex/context/base/symb-ini.mkiv
index 8282649b033..e957e68c1f5 100644
--- a/Master/texmf-dist/tex/context/base/symb-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/symb-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Basic Symbols Commands,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -43,94 +43,128 @@
%D \definesymbol [level 5] [$\star$]
%D \stoptyping
-% ss:tag -> symbol
-% ss:set:tag -> symbol out of set
-% sstag -> list of symbols in set
+\installcorenamespace{symbol}
+\installcorenamespace{symbolset}
+
+\let\currentsymbol \empty
+\let\currentsymbolset\empty
+
+\newtoks\t_symb_setups
+
+\let\m_symb_current_set\empty
+
+\newconditional\c_symb_found
+
+\newtoks\everysymbol
+
+%D We don't use the commandhandler as symbols have their own
+%D subsystem for resolving values.
\unexpanded\def\definesymbol
- {\dotripleempty\dodefinesymbol}
+ {\dotripleempty\symb_define}
-\def\dodefinesymbol[#1][#2][#3]% class name meaning
+\def\symb_define[#1][#2][#3]% class name meaning
{\ifthirdargument
- \setvalue{\??ss:#1:#2}{#3}%
- \doifsomething{#1}{\addvalue{\??ss*#1}{#2}}%
+ \setvalue{\??symbol#1:#2}{#3}%
+ \doifsomething{#1}{\addvalue{\??symbolset#1}{#2}}%
\else
- \setvalue{\??ss:\currentsymboldef:#1}{#2}%
- \addvalue{\??ss*\currentsymboldef}{#1}%
+ \setvalue{\??symbol\m_symb_current_set:#1}{#2}%
+ \addvalue{\??symbolset\m_symb_current_set}{#1}%
\fi}
-% \def\doifinsymbolsetelse#1#2{\doifdefinedelse{\??ss:#1:#2}}
-% \def\doifinsymbolset #1#2{\doifdefined {\??ss:#1:#2}}
-% \def\doifsymbolsetelse #1{\doifdefinedelse{\??ss*#1}}
-%
-% \def\symbolset#1{\executeifdefined{\??ss*#1}\empty} % no [#1], to be used in commalists etc
-
-\def\doifinsymbolsetelse#1#2{\ifcsname\??ss:#1:#2\endcsname\@EA\firstoftwoarguments\else\@EA\secondoftwoarguments\fi}
-\def\doifinsymbolset #1#2{\ifcsname\??ss:#1:#2\endcsname\@EA\firstofoneargument \else\@EA\gobbleoneargument \fi}
-\def\doifsymbolsetelse #1{\ifcsname\??ss*#1\endcsname \@EA\firstoftwoarguments\else\@EA\secondoftwoarguments\fi}
+\letvalue{\??symbolset}\empty
-\letvalue{\??ss*}\empty
+\unexpanded\def\doifinsymbolsetelse#1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
+\unexpanded\def\doifinsymbolset #1#2{\ifcsname\??symbol#1:#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi}
+\unexpanded\def\doifsymbolsetelse #1{\ifcsname\??symbolset#1\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
-\def\symbolset#1{\csname\??ss*\ifcsname\??ss*#1\endcsname#1\fi\endcsname} % no [#1], to be used in commalists etc
+\def\symbolset#1{\csname\??symbolset\ifcsname\??symbolset#1\endcsname#1\fi\endcsname} % no [#1], to be used in commalists etc
%D Since symbols are used frequently in interactive
%D documents, we speed up this one. Well, that was history,
%D since now we simplified things a bit, because the low
-%D level macros have been sped up now and then.
-
-\unexpanded\def\symbol % This one always gobbles spaces,
- {\dodoubleempty\dosymbol} % so never change it again!
-
-\newif\ifnosymbol \newtoks\everysymbol
-
-\def\dodosymbol#1#2% \relax's prevent lookahead problems
- {\nosymbolfalse{\the\everysymbol\csname\??ss:#1:#2\endcsname\relax}\relax}
-
-\letvalue{\??ss:}\firstofoneargument
-
-\def\directsymbol#1#2% no \relax, there can be an argument, see lists
- {%\executeifdefined{\??ss:#1:#2}\firstofoneargument}
- \csname\??ss:\ifcsname\??ss:#1:#2\endcsname#1:#2\fi\endcsname}
+%D level macros have been sped up every now and then.
% We support both:
%
% Test test \symbol[whatever]\ test \symbol[whatever].
% Test test \symbol{whatever} test \symbol{whatever}.
-\def\dosymbol % so we also handle \symbol{name}
+\unexpanded\def\symbol % This one always gobbles spaces,
+ {\dodoubleempty\symb_place} % so never change it again!
+
+\def\symb_place % so we also handle \symbol{name}
{\iffirstargument % which is nicer with following spaces
- \expandafter\donormalsymbol
+ \expandafter\symb_place_normal
+ \else
+ \expandafter\symb_place_special
+ \fi}
+
+\def\symb_place_normal
+ {\ifsecondargument
+ \expandafter\symb_place_normal_a
+ \else
+ \expandafter\symb_place_normal_b
+ \fi}
+
+\def\symb_place_normal_a[#1][#2]%
+ {\edef\currentsymbol{#2}%
+ \ifcsname\??symbol#1:#2\endcsname
+ \symb_place_indeed{#1:#2}%
+ \else
+ \symb_place_normal_c
+ \fi}
+
+\def\symb_place_normal_b[#1][#2]%
+ {\edef\currentsymbol{#1}%
+ \ifcsname\??symbol\currentsymbolset:#1\endcsname
+ \symb_place_indeed{\currentsymbolset:#1}%
\else
- \expandafter\dospecialsymbol
+ \symb_place_normal_c
+ \fi}
+
+\def\symb_place_normal_c
+ {\setfalse\c_symb_found
+ \the\t_symb_setups
+ \ifconditional\c_symb_found \else
+ \symb_place_retry\currentsymbol % hm, isn't this redundant?
\fi}
-\def\dospecialsymbol[#1][#2]#3%
+\def\symb_place_special[#1][#2]#3%
{\firstargumenttrue
\secondargumentfalse
- \donormalsymbol[#3][]}
+ \symb_place_normal[#3][]}
-\def\donormalsymbol[#1][#2]%
- {\nosymboltrue
- \ifsecondargument
- \edef\currentsymbol{#2}%
- \doifinsymbolset{#1}{#2}{\dodosymbol{#1}{#2}}%
+\def\symb_place_indeed#1% \relax's prevent lookahead problems
+ {\settrue\c_symb_found
+ \begingroup
+ \the\everysymbol
+ \csname\??symbol#1\endcsname\relax
+ \endgroup}
+
+\letvalue{\??symbol}\firstofoneargument
+
+\def\directsymbol#1#2% no \relax, there can be an argument, see lists
+ {\csname\??symbol\ifcsname\??symbol#1:#2\endcsname#1:#2\fi\endcsname}
+
+\unexpanded\def\symb_fetch
+ {\ifconditional\c_symb_found
+ \expandafter\gobbleoneargument
\else
- \edef\currentsymbol{#1}%
- \fi
- \ifnosymbol
- \the\symbolsetups
- \ifnosymbol
- \redosymbol\currentsymbol
- \fi
+ \expandafter\symb_fetch_indeed
\fi}
-\def\fetchsymbol#1%
- {\ifnosymbol
- \doifinsymbolset{#1}\currentsymbol{\dodosymbol{#1}\currentsymbol}%
+\def\symb_fetch_indeed#1%
+ {\ifcsname\??symbol#1:\currentsymbol\endcsname
+ \symb_place_indeed{#1:\currentsymbol}%
\fi}
-\def\redosymbol#1%
- {\doifinsymbolsetelse\empty{#1}{\dodosymbol\empty}\firstofoneargument{#1}}
+\def\symb_place_retry#1%
+ {\ifcsname\??symbol:#1\endcsname
+ \symb_place_indeed{:#1}%
+ \else
+ #1%
+ \fi}
%D \macros
%D {definefiguresymbol}
@@ -145,23 +179,23 @@
\def\defaultsymbolfactor{10}
\def\defaultsymbolheight{1.25ex}
-\def\figuresymbol
- {\dodoubleempty\dofiguresymbol}
+\unexpanded\def\figuresymbol
+ {\dodoubleempty\symb_figure}
-\ifx\externalfigure \undefined \def\externalfigure[#1][#2]{#1} \fi
-\ifx\resetexternalfigures\undefined \let\resetexternalfigures\relax \fi
+\ifdefined\externalfigure \else \def\externalfigure[#1][#2]{#1} \fi
+\ifdefined\resetexternalfigures \else \let\resetexternalfigures\relax \fi
-\def\dofiguresymbol[#1][% #2]%
+\def\symb_figure[#1][% #2]%
{\externalfigure[#1][\c!reset=\v!yes,\c!symbol=\v!yes,\c!height=\defaultsymbolheight,}% #2]}
\appendtoks \resetexternalfigures \to \everysymbol
\unexpanded\def\definefiguresymbol
- {\dotripleempty\dodefinefiguresymbol}
+ {\dotripleempty\symb_figure_define}
-\def\dodefinefiguresymbol[#1][#2][#3]%
+\def\symb_figure_define[#1][#2][#3]%
{\ifsecondargument
- \definesymbol[#1][{\dofiguresymbol[#2][#3]}]%
+ \definesymbol[#1][{\symb_figure[#2][#3]}]%
\fi}
%D \macros
@@ -169,31 +203,34 @@
%D
%D A handy private one:
-% a bit messy
-
-\def\xfetchsymbol#1%
- {\ifnosymbol
- \doifinsymbolset{#1}\currentsymbol\nosymbolfalse
+\def\symb_fetch_first
+ {\ifconditional\c_symb_found
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\symb_fetch_first_indeed
\fi}
-\def\xredosymbol#1%
- {\doifinsymbolset\empty\currentsymbol\nosymbolfalse}
+\def\symb_fetch_first_indeed#1%
+ {\doifinsymbolset{#1}\currentsymbol{\settrue\c_symb_found}}
+
+\def\symb_fetch_second#1%
+ {\doifinsymbolset\empty\currentsymbol{\settrue\c_symb_found}}
\def\doifsymboldefinedelse#1%
- {\bgroup
+ {\begingroup
\edef\currentsymbol{#1}%
- \let\fetchsymbol\xfetchsymbol
- \nosymboltrue
- \the\symbolsetups
- \ifnosymbol
- \xredosymbol\currentsymbol
- \ifnosymbol
- \egroup\@EAEAEA\secondoftwoarguments
+ \let\symb_fetch\symb_fetch_first
+ \setfalse\c_symb_found
+ \the\t_symb_setups
+ \ifconditional\c_symb_found
+ \endgroup\expandafter\firstoftwoarguments
+ \else
+ \symb_fetch_second\currentsymbol
+ \ifconditional\c_symb_found
+ \endgroup\doubleexpandafter\firstoftwoarguments
\else
- \egroup\@EAEAEA\firstoftwoarguments
+ \endgroup\doubleexpandafter\secondoftwoarguments
\fi
- \else
- \egroup\@EA\firstoftwoarguments
\fi}
%D \macros
@@ -226,24 +263,30 @@
%D \showsetup{setupsymbolset}
%D \showsetup{startsymbolset}
-\let\currentsymboldef\empty
+\installcorenamespace{symbolsets}
\unexpanded\def\startsymbolset[#1]%
- {\def\currentsymboldef{#1}}
+ {\pushmacro\m_symb_current_set
+ \def\m_symb_current_set{#1}}
\unexpanded\def\stopsymbolset
- {\let\currentsymboldef\empty}
-
-\newtoks\symbolsetups
+ {\popmacro\m_symb_current_set}
\unexpanded\def\setupsymbolset[#1]%
- {\prependtoksonce\fetchsymbol{#1}\to\symbolsetups}
+ {\edef\currentsymbolset{#1}%
+ \ifcsname\??symbolsets\currentsymbolset\endcsname \else
+ \symb_setup_symbol_set
+ \fi}
+
+\def\symb_setup_symbol_set
+ {\normalexpanded{\t_symb_setups{\symb_fetch{\currentsymbolset}\the\t_symb_setups}}%
+ \letvalue{\??symbolsets\currentsymbolset}\empty} % speedup
-\def\resetsymbolset
- {\symbolsetups\emptytoks}
+\unexpanded\def\resetsymbolset
+ {\t_symb_setups\emptytoks}
-\def\forcesymbolset[#1]%
- {\symbolsetups{\fetchsymbol{#1}}}
+\unexpanded\def\forcesymbolset[#1]%
+ {\t_symb_setups{\symb_fetch{#1}}}
%D \macros
%D {showsymbolset}
@@ -257,7 +300,7 @@
%D
%D \showsetup{usesymbols}
-\def\usesymbols[#1]{\ctxcommand{usesymbols("#1")}}
+\unexpanded\def\usesymbols[#1]{\ctxcommand{usesymbols("#1")}}
%D As longs as symbols are linked to levels or numbers, we can
%D also use the conversion mechanism, but in for instance the
diff --git a/Master/texmf-dist/tex/context/base/symb-jmn.mkii b/Master/texmf-dist/tex/context/base/symb-jmn.mkii
index 392cac55260..aea2dce7b0b 100644
--- a/Master/texmf-dist/tex/context/base/symb-jmn.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-jmn.mkii
@@ -5,7 +5,7 @@
%D subtitle=Special Navigational Symbols,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-mis.mkii b/Master/texmf-dist/tex/context/base/symb-mis.mkii
index 9921fa94fb1..dacb816b411 100644
--- a/Master/texmf-dist/tex/context/base/symb-mis.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-mis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Miscelaneous,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-mvs.mkii b/Master/texmf-dist/tex/context/base/symb-mvs.mkii
index 5f1d3962b36..aae4e92d66c 100644
--- a/Master/texmf-dist/tex/context/base/symb-mvs.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-mvs.mkii
@@ -5,7 +5,7 @@
%D subtitle=Martin Vogels Symbole,
%D author=Tobias Burnus \& Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-nav.mkii b/Master/texmf-dist/tex/context/base/symb-nav.mkii
index 93badbc4d12..c9d1aae1d73 100644
--- a/Master/texmf-dist/tex/context/base/symb-nav.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-nav.mkii
@@ -5,7 +5,7 @@
%D subtitle=Navigational Symbols,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-run.mkii b/Master/texmf-dist/tex/context/base/symb-run.mkii
index 4e714832c52..8b8c62d8b55 100644
--- a/Master/texmf-dist/tex/context/base/symb-run.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-run.mkiv b/Master/texmf-dist/tex/context/base/symb-run.mkiv
index 33bbb7927c5..4bd2ceccae4 100644
--- a/Master/texmf-dist/tex/context/base/symb-run.mkiv
+++ b/Master/texmf-dist/tex/context/base/symb-run.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/symb-uni.mkii b/Master/texmf-dist/tex/context/base/symb-uni.mkii
index fcd613e7f0a..f5435810f15 100644
--- a/Master/texmf-dist/tex/context/base/symb-uni.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-uni.mkii
@@ -5,7 +5,7 @@
%D subtitle=Unicode Symbols,
%D author=Adam T. Lindsay,
%D date=\currentdate,
-%D copyright={Adam T. Lindsay / PRAGMA}]
+%D copyright={Adam Lindsay \& Hans Hagen}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C prepared by Adam T. Lindsay.
diff --git a/Master/texmf-dist/tex/context/base/symb-was.mkii b/Master/texmf-dist/tex/context/base/symb-was.mkii
index 53132cd23ff..e131cf04dae 100644
--- a/Master/texmf-dist/tex/context/base/symb-was.mkii
+++ b/Master/texmf-dist/tex/context/base/symb-was.mkii
@@ -5,7 +5,7 @@
%D subtitle=Roland Waldi's Symbols (wasy-2),
%D author=Henning Hraban Ramm,
%D date=\currentdate,
-%D copyright={public domain}]
+%D copyright={Public Domain}]
%C
%C This module is in the public domain.
diff --git a/Master/texmf-dist/tex/context/base/syst-aux.lua b/Master/texmf-dist/tex/context/base/syst-aux.lua
new file mode 100644
index 00000000000..7fd25d6ab0a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/syst-aux.lua
@@ -0,0 +1,52 @@
+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"
+}
+
+local settings_to_array = utilities.parsers.settings_to_array
+local concat = table.concat
+
+local setvalue = context.setvalue
+
+function commands.getfirstcharacter(str)
+ local first, rest = utf.match(str,"(.?)(.*)$")
+ setvalue("firstcharacter",first)
+ setvalue("remainingcharacters",rest)
+end
+
+function commands.doiffirstcharelse(chr,str)
+ commands.doifelse(utf.sub(str,1,1) == chr)
+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
diff --git a/Master/texmf-dist/tex/context/base/syst-aux.mkiv b/Master/texmf-dist/tex/context/base/syst-aux.mkiv
index d2bc84ae8bc..0e43a6202bd 100644
--- a/Master/texmf-dist/tex/context/base/syst-aux.mkiv
+++ b/Master/texmf-dist/tex/context/base/syst-aux.mkiv
@@ -5,7 +5,7 @@
%D subtitle=General,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -14,6 +14,13 @@
%D Some of the macros will move to syst-obs as they might become
%D obsolete once we've redone the bibliography module. Of course
%D the handy helpers will stay.
+%D
+%D There are some references to \LUA\ variants here but these concern
+%D (often old) experiments, moved from local test modules to here,
+%D cleaned up, but not really used. After all it's not that urgent
+%D and replacing helpers is a delicate process. Don't depend on it.
+
+\registerctxluafile{syst-aux}{1.001}
%D This is a stripped down combination of:
%D
@@ -34,6 +41,9 @@
%D Some of the macros here are used in the bibliography module. They
%D will be moved to a separate syst module some once the bib module
%D is made \MKIV.
+%D
+%D The original files contain previous implementations and notes about
+%D performance. This file will be stripped down in due time.
\unprotect
@@ -53,23 +63,6 @@
\let\unexpanded\normalprotected
%D \macros
-%D {doifolderversionelse}
-%D
-%D We start with a macro specially for Aditya who wants to be able
-%D to use development versions of \MKIV\ for real documents.
-%D
-%D \starttyping
-%D \doifolderversionelse\contextversion{1010.10.10} {OLDER} {OKAY} => OLDER
-%D \doifolderversionelse\contextversion{2020.20.20} {OLDER} {OKAY} => OKAY
-%D \doifolderversionelse\contextversion{2020} {OLDER} {OKAY} => OKAY
-%D \stoptyping
-%D
-%D The version pattern is \type {yyyy.mm.dd} (with mm and dd being optional).
-
-\def\doifolderversionelse#1#2{\ctxcommand{doifolderversionelse("#1","#2")}}
-\def\doifoldercontextelse #1{\ctxcommand{doifolderversionelse("#1")}}
-
-%D \macros
%D {normalspace}
%D
%D There is already \type{\space} but just to be sure we also
@@ -114,10 +107,10 @@
\def\!!plustwo {2} % alongside \plustwo
\def\!!plusthree {3} % alongside \plusthree
-\setnewconstant\uprotationangle 0
-\setnewconstant\rightrotatioangle 90
-\setnewconstant\downrotatioangle 180
-\setnewconstant\leftrotatioangle 270
+\setnewconstant \uprotationangle 0
+\setnewconstant\rightrotationangle 90
+\setnewconstant \downrotationangle 180
+\setnewconstant \leftrotationangle 270
\ifdefined\data \else \let\data \relax \fi % dep checker
@@ -128,33 +121,34 @@
%D variables). Redefining these constants can have disastrous
%D results.
-\def\v!prefix! {v!} \def\c!prefix! {c!}
-\def\s!prefix! {s!} \def\p!prefix! {p!}
+\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!next {next}
+\def\s!default {default}
+\def\s!dummy {dummy}
+\def\s!unknown {unknown}
-\def\s!do {do} \def\s!dodo {dodo}
+\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!complex {complex}
+\def\s!start {start}
+\def\s!simple {simple}
+\def\s!stop {stop}
\def\s!empty {empty}
-%D \macros
-%D {@EA,@EAEA,@EAEAEA,@EAEAEAEAEAEA,expanded,startexpanded}
-%D
-%D When in unprotected mode, to be entered with
-%D \type{\unprotect}, one can use \type{\@EA} as equivalent
-%D of \type{\expandafter}.
-
-\let\@NX\noexpand
-\let\@EA\expandafter
+%D These are not needed any more now that we have wide screens (and
+%D bytes come cheap).
-\def\@EAEA {\expandafter\expandafter}
-\def\@EAEAEA{\expandafter\expandafter\expandafter}
+\let\@EA \singleexpandafter
+\let\@EAEAEA \doubleexpandafter
+\let\@EAEAEAEAEAEA\tripleexpandafter
-\def\@EAEAEAEAEAEA{\expandafter\@EAEAEA\expandafter}
+\let\@NX \noexpand
+\def\@EAEA {\expandafter\expandafter} % can often be avoided
%D Sometimes we pass macros as arguments to commands that
%D don't expand them before interpretation. Such commands can
@@ -171,22 +165,24 @@
%D alternatives to this command. Beware, only the simple one
%D has \type {\noexpand} before its argument.
- \long\def\@@expanded{} % always long; global (less restores)
+\let\@@expanded\empty % always long and global (less restores)
-\long\def\expanded#1%
- {\long\xdef\@@expanded{\noexpand#1}\@@expanded}
+\unexpanded\def\expanded#1%
+ {\xdef\@@expanded{\noexpand#1}\@@expanded}
-\long\def\startexpanded#1\stopexpanded % see x-fo for example
- {\long\xdef\@@expanded{#1}\@@expanded}
+\unexpanded\def\startexpanded#1\stopexpanded % see x-fo for example
+ {\xdef\@@expanded{#1}\@@expanded}
+
+\let\stopexpanded\relax
%D Recent \TEX's have a primitive \expanded
% not yet as we need to adapt ##'s in calls
%
-% \long\def\expanded#1%
+% \def\expanded#1%
% {\normalexpanded{\noexpand#1}}
%
-% \long\def\startexpanded#1\stopexpanded
+% \def\startexpanded#1\stopexpanded
% {\normalexpanded{#1}}
%D \macros
@@ -195,16 +191,16 @@
%D The next set of macros just do nothing, except that they
%D get rid of a number of arguments.
-\long\def\gobbleoneargument #1{}
-\long\def\gobbletwoarguments #1#2{}
-\long\def\gobblethreearguments#1#2#3{}
-\long\def\gobblefourarguments #1#2#3#4{}
-\long\def\gobblefivearguments #1#2#3#4#5{}
-\long\def\gobblesixarguments #1#2#3#4#5#6{}
-\long\def\gobblesevenarguments#1#2#3#4#5#6#7{}
-\long\def\gobbleeightarguments#1#2#3#4#5#6#7#8{}
-\long\def\gobbleninearguments #1#2#3#4#5#6#7#8#9{}
-\long\def\gobbletenarguments #1{\gobbleninearguments}
+\def\gobbleoneargument #1{}
+\def\gobbletwoarguments #1#2{}
+\def\gobblethreearguments#1#2#3{}
+\def\gobblefourarguments #1#2#3#4{}
+\def\gobblefivearguments #1#2#3#4#5{}
+\def\gobblesixarguments #1#2#3#4#5#6{}
+\def\gobblesevenarguments#1#2#3#4#5#6#7{}
+\def\gobbleeightarguments#1#2#3#4#5#6#7#8{}
+\def\gobbleninearguments #1#2#3#4#5#6#7#8#9{}
+\def\gobbletenarguments #1{\gobbleninearguments}
\def\gobbleoneoptional [#1]{}
\def\gobbletwooptionals [#1][#2]{}
@@ -237,24 +233,24 @@
%D {\localnext} because we don't want clashes with \type
%D {\next}.
-\long\def\doifnextcharelse#1#2#3% #1 should not be {} !
+\unexpanded\def\doifnextcharelse#1#2#3% #1 should not be {} !
{\let\charactertoken=#1% = needed here
\def\!!stringa{#2}%
\def\!!stringb{#3}%
- \futurelet\nexttoken\inspectnextcharacter}
+ \futurelet\nexttoken\syst_helpers_inspect_next_character}
-\def\inspectnextcharacter
+\def\syst_helpers_inspect_next_character
{\ifx\nexttoken\blankspace
- \@EA\reinspectnextcharacter
+ \expandafter\syst_helpers_reinspect_next_character
\else
- \@EA\inspectnextcharacterindeed
+ \expandafter\syst_helpers_inspect_next_character_indeed
\fi}
-\def\inspectnextcharacterindeed
+\def\syst_helpers_inspect_next_character_indeed
{\ifx\nexttoken\charactertoken
- \@EA\!!stringa
+ \expandafter\!!stringa
\else
- \@EA\!!stringb
+ \expandafter\!!stringb
\fi}
%D Because we will mostly use this macro for testing if the next
@@ -263,87 +259,107 @@
%D test in a run. Of course it also is more convenient to read a
%D trace then.
-\newif\ifnextblankspacetoken
+% We could make variants without the \if_next_blank_space_token but
+% the overhead is only .1 sec on 3.5 for 10^6 tests and often that
+% branch is not entered anyway. The fast variants with less checking
+% do make a difference however:
+
+% \testfeature{1000000}{\doifnextoptionalelse \gobbleoneargument\gobbleoneargument[} % 2.902s
+% \testfeature{1000000}{\doifnextoptionalcselse \gobbleoneargument\gobbleoneargument[} % 2.590s
+% \testfeature{1000000}{\doiffastoptionalcheckelse \gobbleoneargument\gobbleoneargument[} % 2.387s
+% \testfeature{1000000}{\doiffastoptionalcheckcselse\gobbleoneargument\gobbleoneargument[} % 2.168s
+
+\newif\if_next_blank_space_token
-\let\nextoptionalcharactertoken=[
+\let\syst_helpers_next_optional_character_token=[
-\long\def\doifnextoptionalelse#1#2%
- {\def\nextoptionalcommandyes{#1}%
- \def\nextoptionalcommandnop{#2}%
- \let\ifnextblankspacetoken\iffalse
- \futurelet\nexttoken\inspectnextoptionalcharacter}
+\unexpanded\def\doifnextoptionalelse#1#2%
+ {\def\syst_helpers_next_optional_command_yes{#1}%
+ \def\syst_helpers_next_optional_command_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\inspectnextoptionalcharacter
+\unexpanded\def\doifnextoptionalcselse#1#2% \cs \cs (upto 10% faster)
+ {\let\syst_helpers_next_optional_command_yes#1%
+ \let\syst_helpers_next_optional_command_nop#2%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
+
+\def\syst_helpers_inspect_next_optional_character
{\ifx\nexttoken\blankspace
- \@EA\reinspectnextoptionalcharacter
+ \expandafter\syst_helpers_reinspect_next_optional_character
\else
- \@EA\inspectnextoptionalcharacterindeed
+ \expandafter\syst_helpers_inspect_next_optional_character_indeed
\fi}
-\def\inspectnextoptionalcharacterindeed
- {\ifx\nexttoken\nextoptionalcharactertoken
- \@EA\nextoptionalcommandyes
+\def\syst_helpers_inspect_next_optional_character_indeed
+ {\ifx\nexttoken\syst_helpers_next_optional_character_token
+ \expandafter\syst_helpers_next_optional_command_yes
\else
- \@EA\nextoptionalcommandnop
+ \expandafter\syst_helpers_next_optional_command_nop
\fi}
-\let\nextbgroupcharactertoken\bgroup
+\let\syst_helpers_next_bgroup_character_token\bgroup
-\long\def\doifnextbgroupelse#1#2%
- {\def\nextbgroupcommandyes{#1}%
- \def\nextbgroupcommandnop{#2}%
- \let\ifnextblankspacetoken\iffalse
- \futurelet\nexttoken\inspectnextbgroupcharacter}
+\unexpanded\def\doifnextbgroupelse#1#2%
+ {\def\syst_helpers_next_bgroup_command_yes{#1}%
+ \def\syst_helpers_next_bgroup_command_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
-\def\inspectnextbgroupcharacter
+\def\syst_helpers_inspect_next_bgroup_character
{\ifx\nexttoken\blankspace
- \@EA\reinspectnextbgroupcharacter
+ \expandafter\syst_helpers_reinspect_next_bgroup_character
\else
- \@EA\inspectnextbgroupcharacterindeed
+ \expandafter\syst_helpers_inspect_next_bgroup_character_indeed
\fi}
-\def\inspectnextbgroupcharacterindeed
- {\ifx\nexttoken\nextbgroupcharactertoken
- \@EA\nextbgroupcommandyes
+\def\syst_helpers_inspect_next_bgroup_character_indeed
+ {\ifx\nexttoken\syst_helpers_next_bgroup_character_token
+ \expandafter\syst_helpers_next_bgroup_command_yes
\else
- \@EA\nextbgroupcommandnop
+ \expandafter\syst_helpers_next_bgroup_command_nop
\fi}
-\let\nextparenthesischaractertoken(
+\let\syst_helpers_next_parenthesis_character_token(
-\long\def\doifnextparenthesiselse#1#2%
- {\def\nextparenthesiscommandyes{#1}%
- \def\nextparenthesiscommandnop{#2}%
- \let\ifnextblankspacetoken\iffalse
- \futurelet\nexttoken\inspectnextparenthesischaracter}
+\unexpanded\def\doifnextparenthesiselse#1#2%
+ {\def\syst_helpers_next_parenthesis_command_yes{#1}%
+ \def\syst_helpers_next_parenthesis_command_nop{#2}%
+ \let\if_next_blank_space_token\iffalse
+ \futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
-\def\inspectnextparenthesischaracter
+\def\syst_helpers_inspect_next_parenthesis_character
{\ifx\nexttoken\blankspace
- \@EA\reinspectnextparenthesischaracter
+ \expandafter\syst_helpers_reinspect_next_parenthesis_character
\else
- \@EA\inspectnextparenthesischaracterindeed
+ \expandafter\syst_helpers_inspect_next_parenthesis_character_indeed
\fi}
-\def\inspectnextparenthesischaracterindeed
- {\ifx\nexttoken\nextparenthesischaractertoken
- \@EA\nextparenthesiscommandyes
+\def\syst_helpers_inspect_next_parenthesis_character_indeed
+ {\ifx\nexttoken\syst_helpers_next_parenthesis_character_token
+ \expandafter\syst_helpers_next_parenthesis_command_yes
\else
- \@EA\nextparenthesiscommandnop
+ \expandafter\syst_helpers_next_parenthesis_command_nop
\fi}
%D The next one is handy in predictable situations:
-\long\def\doiffastoptionalcheckelse#1#2%
- {\def\nextoptionalcommandyes{#1}%
- \def\nextoptionalcommandnop{#2}%
- \let\ifnextblankspacetoken\iffalse % not needed
- \futurelet\nexttoken\dodoiffastoptionalcheckelse}
+\unexpanded\def\doiffastoptionalcheckelse#1#2%
+ {\def\syst_helpers_next_optional_command_yes{#1}%
+ \def\syst_helpers_next_optional_command_nop{#2}%
+ \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
+
+\unexpanded\def\doiffastoptionalcheckcselse#1#2% \cs \cs
+ {\let\syst_helpers_next_optional_command_yes#1%
+ \let\syst_helpers_next_optional_command_nop#2%
+ \futurelet\nexttoken\syst_helpers_do_if_fast_optional_check_else}
-\def\dodoiffastoptionalcheckelse
- {\ifx\nexttoken\nextoptionalcharactertoken
- \expandafter\nextoptionalcommandyes
+\def\syst_helpers_do_if_fast_optional_check_else
+ {\ifx\nexttoken\syst_helpers_next_optional_character_token
+ \expandafter\syst_helpers_next_optional_command_yes
\else
- \expandafter\nextoptionalcommandnop
+ \expandafter\syst_helpers_next_optional_command_nop
\fi}
%D This macro uses some auxiliary macros. Although we were able
@@ -361,18 +377,23 @@
%D \type{\:} becomes a delimiter of the longer named
%D \type{\reinspectnextcharacter}.
+% try: \expandafter\def\firstofoneargument{\syst_helpers_reinspect_next_character} {...}
+
\let\next\:
\def\:{\let\blankspace= } \:
-\def\:{\reinspectnextcharacter}
-\expandafter\def\: {\let\ifnextblankspacetoken\iftrue\futurelet\nexttoken\inspectnextcharacter}
+\def\:{\syst_helpers_reinspect_next_character}
+\expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_character}
+
+\def\:{\syst_helpers_reinspect_next_optional_character}
+\expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_optional_character}
-\def\:{\reinspectnextoptionalcharacter}
-\expandafter\def\: {\let\ifnextblankspacetoken\iftrue\futurelet\nexttoken\inspectnextoptionalcharacter}
+\def\:{\syst_helpers_reinspect_next_bgroup_character}
+\expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_bgroup_character}
-\def\:{\reinspectnextbgroupcharacter}
-\expandafter\def\: {\let\ifnextblankspacetoken\iftrue\futurelet\nexttoken\inspectnextbgroupcharacter}
+\def\:{\syst_helpers_reinspect_next_parenthesis_character}
+\expandafter\def\: {\let\if_next_blank_space_token\iftrue\futurelet\nexttoken\syst_helpers_inspect_next_parenthesis_character}
\let\:\next
@@ -465,53 +486,27 @@
%
% use a real if like \ifcsname#1\endcsname\else instead
-\ifdefined\suppressifcsnameerror
-
- \suppressifcsnameerror\plusone
-
- \def\doifundefinedelse#1%
- {\ifcsname#1\endcsname
- \@EA\secondoftwoarguments\else\@EA\firstoftwoarguments
- \fi}
-
- \def\doifdefinedelse#1%
- {\ifcsname#1\endcsname
- \@EA\firstoftwoarguments\else\@EA\secondoftwoarguments
- \fi}
+\suppressifcsnameerror\plusone
- \def\doifundefined#1%
- {\ifcsname#1\endcsname
- \@EA\gobbleoneargument\else\@EA\firstofoneargument
- \fi}
-
- \def\doifdefined#1%
- {\ifcsname#1\endcsname
- \@EA\firstofoneargument\else\@EA\gobbleoneargument
- \fi}
-
-\else
-
- \def\doifundefinedelse#1%
- {\ifcsname\detokenize\@EA{\normalexpanded{#1}}\endcsname
- \@EA\secondoftwoarguments\else\@EA\firstoftwoarguments
- \fi}
-
- \def\doifdefinedelse#1%
- {\ifcsname\detokenize\@EA{\normalexpanded{#1}}\endcsname
- \@EA\firstoftwoarguments\else\@EA\secondoftwoarguments
- \fi}
+\def\doifundefinedelse#1%
+ {\ifcsname#1\endcsname
+ \expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments
+ \fi}
- \def\doifundefined#1%
- {\ifcsname\detokenize\@EA{\normalexpanded{#1}}\endcsname
- \@EA\gobbleoneargument\else\@EA\firstofoneargument
- \fi}
+\def\doifdefinedelse#1%
+ {\ifcsname#1\endcsname
+ \expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments
+ \fi}
- \def\doifdefined#1%
- {\ifcsname\detokenize\@EA{\normalexpanded{#1}}\endcsname
- \@EA\firstofoneargument\else\@EA\gobbleoneargument
- \fi}
+\def\doifundefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\gobbleoneargument\else\expandafter\firstofoneargument
+ \fi}
-\fi
+\def\doifdefined#1%
+ {\ifcsname#1\endcsname
+ \expandafter\firstofoneargument\else\expandafter\gobbleoneargument
+ \fi}
%D \macros
%D {letbeundefined}
@@ -540,21 +535,22 @@
%D was due to this grouping subtilities. We therefore decided
%D to use \type{\begingroup} instead of \type{\bgroup}.
-\def\docheckonedefined#1%
- {\ifcsname#1\endcsname\else
- \donefalse
- \expandafter\quitcommalist % added
- \fi}
-
-\def\doifalldefinedelse#1%
+\unexpanded\def\doifalldefinedelse#1%
{\begingroup
- \donetrue \processcommalist[#1]\docheckonedefined
+ \donetrue % we could use a reserved one and avoid the group
+ \processcommalist[#1]\syst_helpers_do_if_all_defined_else
\ifdone
\endgroup\expandafter\firstoftwoarguments
\else
\endgroup\expandafter\secondoftwoarguments
\fi}
+\def\syst_helpers_do_if_all_defined_else#1%
+ {\ifcsname#1\endcsname\else
+ \donefalse
+ \expandafter\quitcommalist % added
+ \fi}
+
%D \macros
%D {doif,doifelse,doifnot}
%D
@@ -574,24 +570,27 @@
%D \doifelse {string1} {string2} {then ...}{else ...}
%D \stoptyping
-\long\def\doif#1#2%
- {\edef\!!stringa{#1}\edef\!!stringb{#2}%
+\unexpanded\def\doif#1#2%
+ {\edef\!!stringa{#1}%
+ \edef\!!stringb{#2}%
\ifx\!!stringa\!!stringb
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-\long\def\doifnot#1#2%
- {\edef\!!stringa{#1}\edef\!!stringb{#2}%
+\unexpanded\def\doifnot#1#2%
+ {\edef\!!stringa{#1}%
+ \edef\!!stringb{#2}%
\ifx\!!stringa\!!stringb
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
-\long\def\doifelse#1#2%
- {\edef\!!stringa{#1}\edef\!!stringb{#2}%
+\unexpanded\def\doifelse#1#2%
+ {\edef\!!stringa{#1}%
+ \edef\!!stringb{#2}%
\ifx\!!stringa\!!stringb
\expandafter\firstoftwoarguments
\else
@@ -611,7 +610,7 @@
%D
%D This time, the string is not expanded.
-\long\def\doifemptyelse#1%
+\unexpanded\def\doifemptyelse#1%
{\def\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\firstoftwoarguments
@@ -619,7 +618,7 @@
\expandafter\secondoftwoarguments
\fi}
-\long\def\doifempty#1%
+\unexpanded\def\doifempty#1%
{\def\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\firstofoneargument
@@ -627,7 +626,7 @@
\expandafter\gobbleoneargument
\fi}
-\long\def\doifnotempty#1%
+\unexpanded\def\doifnotempty#1%
{\def\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\gobbleoneargument
@@ -675,128 +674,128 @@
% !5yes=\doifnotinset{}{}{yes}
% !6yes=\doifnotinset{aaa}{}{yes}
-\def\rightoptionalbracket{]}
+\def\v_syst_helpers_right_optional_bracket{]}
-\long\def\doquitifiteminsetelse#1],\relax{\firstoftwoarguments}
-\long\def\doquitifiteminset #1],\relax{\firstofoneargument}
-\long\def\doquitifitemnotinset #1],\relax{\gobbleoneargument}
+\def\syst_helpers_do_quit_if_item_in_set_else#1],\relax{\firstoftwoarguments}
+\def\syst_helpers_do_quit_if_item_in_set #1],\relax{\firstofoneargument}
+\def\syst_helpers_do_quit_if_item_not_in_set #1],\relax{\gobbleoneargument}
-\long\def\redoifinsetelse{\expandafter\docheckifiteminsetelse\!!stringb,],\relax}
-\long\def\redoifinset {\expandafter\docheckifiteminset \!!stringb,],\relax}
-\long\def\redoifnotinset {\expandafter\docheckifitemnotinset \!!stringb,],\relax}
+\def\syst_helpers_re_do_if_in_set_else{\expandafter\syst_helpers_do_check_if_item_in_set_else\!!stringb,],\relax}
+\def\syst_helpers_re_do_if_in_set {\expandafter\syst_helpers_do_check_if_item_in_set \!!stringb,],\relax}
+\def\syst_helpers_re_do_if_not_in_set {\expandafter\syst_helpers_do_check_if_item_not_in_set \!!stringb,],\relax}
-\long\def\doifinsetelse#1% make this two step too
+\unexpanded\def\doifinsetelse#1% make this two step too
{\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\thirdofthreearguments
\else
- \expandafter\dodoifinsetelse
+ \expandafter\syst_helpers_do_if_in_set_else
\fi}
-\long\def\dodoifinsetelse#1%
+\def\syst_helpers_do_if_in_set_else#1%
{\edef\!!stringb{#1}%
\ifx\!!stringb\empty
\expandafter\secondoftwoarguments
\else
- \expandafter\redoifinsetelse
+ \expandafter\syst_helpers_re_do_if_in_set_else
\fi}
-\long\def\doifinset#1%
+\unexpanded\def\doifinset#1%
{\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\gobbletwoarguments
\else
- \expandafter\dodoifinset
+ \expandafter\syst_helpers_do_if_in_set
\fi}
-\long\def\dodoifinset#1%
+\def\syst_helpers_do_if_in_set#1%
{\edef\!!stringb{#1}%
\ifx\!!stringb\empty
\expandafter\gobbleoneargument
\else
- \expandafter\redoifinset
+ \expandafter\syst_helpers_re_do_if_in_set
\fi}
-\long\def\doifnotinset#1%
+\unexpanded\def\doifnotinset#1%
{\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\secondoftwoarguments
\else
- \expandafter\dodoifnotinset
+ \expandafter\syst_helpers_do_if_not_in_set
\fi}
-\long\def\dodoifnotinset#1%
+\def\syst_helpers_do_if_not_in_set#1%
{\edef\!!stringb{#1}%
\ifx\!!stringb\empty
\expandafter\firstofoneargument
\else
- \expandafter\redoifnotinset % ...]{true}
+ \expandafter\syst_helpers_re_do_if_not_in_set % ...]{true}
\fi}
-\def\docheckifiteminsetelse#1,#2% #2 eats up preceding space
+\def\syst_helpers_do_check_if_item_in_set_else#1,#2% #2 eats up preceding space
{\edef\!!stringb{#1}%
\ifx\!!stringb\empty
- \expandafter\docheckifiteminsetelse
+ \expandafter\syst_helpers_do_check_if_item_in_set_else
\else
- \expandafter\dodocheckifiteminsetelse
+ \expandafter\syst_helpers_do_do_check_if_item_in_set_else
\fi#2}
-\def\dodocheckifiteminsetelse
- {\ifx\!!stringb\rightoptionalbracket
+\def\syst_helpers_do_do_check_if_item_in_set_else
+ {\ifx\!!stringb\v_syst_helpers_right_optional_bracket
\expandafter\thirdofthreearguments
\else
- \expandafter\dododocheckifiteminsetelse
+ \expandafter\syst_helpers_do_do_do_check_if_item_in_set_else
\fi}
-\def\dododocheckifiteminsetelse
+\def\syst_helpers_do_do_do_check_if_item_in_set_else
{\ifx\!!stringa\!!stringb
- \expandafter\doquitifiteminsetelse
+ \expandafter\syst_helpers_do_quit_if_item_in_set_else
\else
- \expandafter\docheckifiteminsetelse
+ \expandafter\syst_helpers_do_check_if_item_in_set_else
\fi}
-\def\docheckifiteminset#1,#2% #2 eats up preceding space
+\def\syst_helpers_do_check_if_item_in_set#1,#2% #2 eats up preceding space
{\edef\!!stringb{#1}%
\ifx\!!stringb\empty
- \expandafter\docheckifiteminset
+ \expandafter\syst_helpers_do_check_if_item_in_set
\else
- \expandafter\dodocheckifiteminset
+ \expandafter\syst_helpers_do_do_check_if_item_in_set
\fi#2}
-\def\dodocheckifiteminset
- {\ifx\!!stringb\rightoptionalbracket
+\def\syst_helpers_do_do_check_if_item_in_set
+ {\ifx\!!stringb\v_syst_helpers_right_optional_bracket
\expandafter\gobbletwoarguments
\else
- \expandafter\dododocheckifiteminset
+ \expandafter\syst_helpers_do_do_do_check_if_item_in_set
\fi}
-\def\dododocheckifiteminset
+\def\syst_helpers_do_do_do_check_if_item_in_set
{\ifx\!!stringa\!!stringb
- \expandafter\doquitifiteminset
+ \expandafter\syst_helpers_do_quit_if_item_in_set
\else
- \expandafter\docheckifiteminset
+ \expandafter\syst_helpers_do_check_if_item_in_set
\fi}
-\def\docheckifitemnotinset#1,#2% #2 eats up preceding space
+\def\syst_helpers_do_check_if_item_not_in_set#1,#2% #2 eats up preceding space
{\edef\!!stringb{#1}%
\ifx\!!stringb\empty
- \expandafter\docheckifitemnotinset
+ \expandafter\syst_helpers_do_check_if_item_not_in_set
\else
- \expandafter\dodocheckifitemnotinset
+ \expandafter\syst_helpers_do_do_check_if_item_not_in_set
\fi#2}
-\def\dodocheckifitemnotinset
- {\ifx\!!stringb\rightoptionalbracket
+\def\syst_helpers_do_do_check_if_item_not_in_set
+ {\ifx\!!stringb\v_syst_helpers_right_optional_bracket
\expandafter\secondoftwoarguments
\else
- \expandafter\dododocheckifitemnotinset
+ \expandafter\syst_helpers_do_do_do_check_if_item_not_in_set
\fi}
-\def\dododocheckifitemnotinset
+\def\syst_helpers_do_do_do_check_if_item_not_in_set
{\ifx\!!stringa\!!stringb
- \expandafter\doquitifitemnotinset
+ \expandafter\syst_helpers_do_quit_if_item_not_in_set
\else
- \expandafter\docheckifitemnotinset
+ \expandafter\syst_helpers_do_check_if_item_not_in_set
\fi}
%D \macros
@@ -827,61 +826,65 @@
% !9yes=\doifcommonelse{,a,}{,,,a,}{yes}{nop}
% !9yes=\doifcommonelse{,,a,}{,,,a,}{yes}{nop}
-\long\def\doquitifcommonelse#1],\relax#2],\relax{\firstoftwoarguments}
+\let\m_syst_common_a\empty
+\let\m_syst_common_b\empty
+\let\m_syst_common_c\empty
-\long\def\doquitifcommonelsenop{\secondoftwoarguments}
+\def\syst_helpers_do_quit_if_common_else#1],\relax#2],\relax{\firstoftwoarguments}
-\def\docheckifcommonelseone#1,#2%
- {\edef\!!stringc{#1}%
- \ifx\!!stringc\rightoptionalbracket
+\def\syst_helpers_do_check_if_common_else_one#1,#2%
+ {\edef\m_syst_common_c{#1}%
+ \ifx\m_syst_common_c\v_syst_helpers_right_optional_bracket
\expandafter\thirdofthreearguments
\else
- \expandafter\p!docommoncheck
+ \expandafter\syst_helpers_do_common_check
\fi#2}
-\def\docheckifcommonelsetwo#1,#2% we can do an empty #1 check too
+\def\syst_helpers_do_check_if_common_else_two#1,#2% we can do an empty #1 check too
{\edef\commalistelement{#1}%
- \ifx\commalistelement\rightoptionalbracket
- \expandafter\redocheckifcommonelseone
+ \ifx\commalistelement\v_syst_helpers_right_optional_bracket
+ \expandafter\syst_helpers_re_do_check_if_common_else_one
\else
- \expandafter\dodocheckifcommonelsetwo
+ \expandafter\syst_helpers_do_do_check_if_common_else_two
\fi#2}
-\def\dodocheckifcommonelsetwo
+\def\syst_helpers_do_do_check_if_common_else_two
{\ifx\commalistelement\empty
- \expandafter\docheckifcommonelsetwo
+ \expandafter\syst_helpers_do_check_if_common_else_two
\else
- \expandafter\dododocheckifcommonelsetwo
+ \expandafter\syst_helpers_do_do_do_check_if_common_else_two
\fi}
-\def\dododocheckifcommonelsetwo
- {\ifx\!!stringc\commalistelement
- \expandafter\doquitifcommonelse
+\def\syst_helpers_do_do_do_check_if_common_else_two
+ {\ifx\m_syst_common_c\commalistelement
+ \expandafter\syst_helpers_do_quit_if_common_else
\else
- \expandafter\docheckifcommonelsetwo
+ \expandafter\syst_helpers_do_check_if_common_else_two
\fi}
-\def\redocheckifcommonelseone#1{\docheckifcommonelseone}
+\def\syst_helpers_re_do_check_if_common_else_one#1{\syst_helpers_do_check_if_common_else_one}
-\def\p!doifcommonelse#1#2#3#4%
- {\edef\!!stringa{#3}%
- \edef\!!stringb{#4}%
- \ifx\!!stringa\empty
+\def\syst_helpers_do_common_check
+ {\expandafter\syst_helpers_do_check_if_common_else_two\m_syst_common_b,],\relax}%
+
+\def\syst_helpers_do_do_do_if_common_else
+ {\expandafter\syst_helpers_do_check_if_common_else_one\m_syst_common_a,],\relax}
+
+\def\syst_helpers_do_do_if_common_else#1#2#3#4%
+ {\edef\m_syst_common_a{#3}%
+ \edef\m_syst_common_b{#4}%
+ \ifx\m_syst_common_a\empty
\expandafter\secondoftwoarguments
- \else\ifx\!!stringb\empty
+ \else\ifx\m_syst_common_b\empty
\expandafter\expandafter\expandafter\secondoftwoarguments
\else
- \expandafter\expandafter\expandafter\pp!doifcommonelse
+ \expandafter\expandafter\expandafter\syst_helpers_do_do_do_if_common_else
\fi\fi
#1#2}
-\def\pp!doifcommonelse
- {\def\p!docommoncheck{\expandafter\docheckifcommonelsetwo\!!stringb,],\relax}%
- \expandafter\docheckifcommonelseone\!!stringa,],\relax}
-
-\def\doifcommonelse{\p!doifcommonelse\firstoftwoarguments\secondoftwoarguments}
-\def\doifcommon {\p!doifcommonelse\firstofoneargument \gobbleoneargument }
-\def\doifnotcommon {\p!doifcommonelse\gobbleoneargument \firstofoneargument }
+\unexpanded\def\doifcommonelse{\syst_helpers_do_do_if_common_else\firstoftwoarguments\secondoftwoarguments}
+\unexpanded\def\doifcommon {\syst_helpers_do_do_if_common_else\firstofoneargument \gobbleoneargument }
+\unexpanded\def\doifnotcommon {\syst_helpers_do_do_if_common_else\gobbleoneargument \firstofoneargument }
%D \macros
%D {processcommalist,processcommacommand,quitcommalist,
@@ -917,68 +920,72 @@
\newcount\commalevel
-\def\dododoprocesscommaitem
+\def\syst_helpers_do_do_do_process_comma_item
{\csname\s!next\the\commalevel\endcsname}
-\def\dodoprocesscommaitem
+\def\syst_helpers_do_do_process_comma_item
{\ifx\nexttoken\blankspace
- \@EA\redoprocesscommaitem
+ \expandafter\syst_helpers_re_do_process_comma_item
\else
- \@EA\dodoprocesscommaitemindeed
+ \expandafter\syst_helpers_do_do_process_comma_item_indeed
\fi}
-\def\dodoprocesscommaitemindeed
+\def\syst_helpers_do_do_process_comma_item_indeed
{\ifx\nexttoken]%
- \@EA\gobbleoneargument
+ \expandafter\gobbleoneargument
\else
- \@EA\dododoprocesscommaitem
+ \expandafter\syst_helpers_do_do_do_process_comma_item
\fi}
-\def\doprocesscommaitem
- {\futurelet\nexttoken\dodoprocesscommaitem}
+\def\syst_helpers_do_process_comma_item
+ {\futurelet\nexttoken\syst_helpers_do_do_process_comma_item}
%D Empty arguments are not processed. Empty items (\type{,,})
%D however are treated. We have to check for the special case
%D \type{[{a,b,c}]}.
\unexpanded\def\processcommalist[%
- {\futurelet\nexttoken\docheckcommaitem}
+ {\futurelet\nexttoken\syst_helpers_do_check_comma_item}
-\def\docheckcommaitem
+\def\syst_helpers_do_check_comma_item
{\ifx\nexttoken]%
\expandafter\gobblethreearguments
\else
- \expandafter\doprocesscommalist
+ \expandafter\syst_helpers_do_process_comma_list
\fi
\relax} % this one preserved the next {}
-\def\doprocesscommalist#1]#2%
+\def\syst_helpers_do_process_comma_list#1]#2%
{\global\advance\commalevel \plusone
- \long\expandafter\def\csname\s!next\the\commalevel\endcsname##1,%
- {#2{##1}\doprocesscommaitem}%
- \@EA\dodoprocesscommaitem\gobbleoneargument#1,]\relax
+ \expandafter\def\csname\s!next\the\commalevel\endcsname##1,%
+ {#2{##1}\syst_helpers_do_process_comma_item}%
+ \expandafter\syst_helpers_do_do_process_comma_item\gobbleoneargument#1,]\relax
\global\advance\commalevel \minusone }
%D One way of quitting a commalist halfway is:
\def\quitcommalist
- {\begingroup\let\doprocesscommaitem\doquitcommalist}
+ {\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list}
-\def\doquitcommalist#1]%
+\def\syst_helpers_do_quit_comma_list#1]%
{\endgroup}
\def\quitprevcommalist
- {\begingroup\let\doprocesscommaitem\doquitprevcommalist}
+ {\begingroup\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_prev_comma_list}
-\def\doquitprevcommalist#1]%
- {\let\doprocesscommaitem\doquitcommalist}
+\def\syst_helpers_do_quit_prev_comma_list#1]%
+ {\let\syst_helpers_do_process_comma_item\syst_helpers_do_quit_comma_list}
%D The hack we used for checking the next character
%D \type {\doifnextcharelse} is also used here.
-\def\:{\redoprocesscommaitem}
+\let\next\:
+
+\def\:{\syst_helpers_re_do_process_comma_item} % \:not saved ?
-\expandafter\def\: {\futurelet\nexttoken\dodoprocesscommaitem}
+\expandafter\def\: {\futurelet\nexttoken\syst_helpers_do_do_process_comma_item}
+
+\let\:\next
%D The previous examples lead to:
%D
@@ -1028,21 +1035,21 @@
%D \def\command[#1]{... #1 ...}
%D \stoptyping
-\def\processcommalistwithparameters[#1]#2%
- {\def\docommand##1{#2[##1]}%
- \processcommalist[#1]\docommand}
+\unexpanded\def\processcommalistwithparameters[#1]#2%
+ {\def\syst_helpers_do_process_comma_list_with_parameters##1{#2[##1]}%
+ \processcommalist[#1]\syst_helpers_do_process_comma_list_with_parameters}
%D \macros
%D {startprocesscommalist,startprocesscommacommand}
%D
%D Two more:
-\long\unexpanded\def\startprocesscommalist[#1]#2\stopprocesscommalist
- {\long\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}%
+\unexpanded\def\startprocesscommalist[#1]#2\stopprocesscommalist
+ {\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}%
\processcommalist[#1]\currentcommalistcommand}
-\long\unexpanded\def\startprocesscommacommand[#1]#2\stopprocesscommacommand
- {\long\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}%
+\unexpanded\def\startprocesscommacommand[#1]#2\stopprocesscommacommand
+ {\def\currentcommalistcommand##1{\def\currentcommalistitem{##1}#2}%
\normalexpanded{\processcommalist[#1]}\currentcommalistcommand}
%D \macros
@@ -1087,7 +1094,9 @@
\newcount\processlevel
-\def\p!compareprocessactionA[#1=>#2][#3]%
+% obsolete: \def\expandactions{\let\expandedaction\edef} \expandactions (see mkii)
+
+\unexpanded\def\syst_helpers_do_compare_process_action_a[#1=>#2][#3]%
{\edef\!!stringb{#1}%
\ifx\!!stringb\s!default
\let\commalistelement\empty
@@ -1096,34 +1105,30 @@
% met \quitcommalist tot meer dan 25\% sneller
-\def\p!compareprocessactionB[#1=>#2][#3]%
- {\expandedaction\!!stringb{#1}%
+\unexpanded\def\syst_helpers_do_compare_process_action_b[#1=>#2][#3]%
+ {\edef\!!stringb{#1}%
\ifx\!!stringa\!!stringb
\def\commalistelement{#3}%
#2%
\expandafter\quitcommalist
- \else
- \edef\!!stringb{#1}%
- \ifx\!!stringb\s!unknown
- \def\commalistelement{#3}% beware of loops
- #2%
- \fi
- \fi}
+ \else\ifx\!!stringb\s!unknown
+ \def\commalistelement{#3}% beware of loops
+ #2%
+ \fi\fi}
-\def\processaction[#1]#2[%
- {\expandedaction\!!stringa{#1}%
+\unexpanded\def\processaction[#1]#2[%
+ {\edef\!!stringa{#1}%
\ifx\!!stringa\empty
- \let\p!compareprocessaction\p!compareprocessactionA
+ \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_a
\else
- \let\p!compareprocessaction\p!compareprocessactionB
+ \let\syst_helpers_do_compare_process_action\syst_helpers_do_compare_process_action_b
\fi
- \def\p!doprocessaction##1%
- {\p!compareprocessaction[##1][#1]}%
- \processnextcommalist\relax\expandactions\p!doprocessaction[}
+ \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[}
-\def\p!compareprocessactionC[#1=>#2][#3]%
- {\expandedaction\!!stringa{#1}%
- \expandedaction\!!stringb{#3}%
+\unexpanded\def\syst_helpers_do_compare_process_action_c[#1=>#2][#3]%
+ {\edef\!!stringa{#1}%
+ \edef\!!stringb{#3}%
\ifx\!!stringa\!!stringb
\def\commalistelement{#3}%
#2%
@@ -1137,25 +1142,23 @@
\fi}
\unexpanded\def\processfirstactioninset[#1]%
- {\expandedaction\!!stringa{#1}%
+ {\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\processaction
\else
- \expandafter\processfirstactionsinsetindeed
+ \expandafter\syst_helpers_process_first_action_in_set_indeed
\fi
[#1]}
-\unexpanded\def\processfirstactionsinsetindeed[#1]#2[#3]%
- {\def\p!doprocessaction##1%
- {\def\p!dodoprocessaction####1%
- {\p!compareprocessactionC[####1][##1]}%
- \processcommalist[#3]\p!dodoprocessaction}%
- \processcommalist[#1]\p!doprocessaction
- \expandactions}
-
-\def\p!compareprocessactionD[#1=>#2][#3]%
- {\expandedaction\!!stringa{#1}%
- \expandedaction\!!stringb{#3}%
+\unexpanded\def\syst_helpers_process_first_action_in_set_indeed[#1]#2[#3]%
+ {\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}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_action}
+
+\unexpanded\def\syst_helpers_do_compare_process_action_d[#1=>#2][#3]%
+ {\edef\!!stringa{#1}%
+ \edef\!!stringb{#3}%
\ifx\!!stringa\!!stringb
\def\commalistelement{#3}%
#2%
@@ -1168,71 +1171,39 @@
\fi
\fi}
-\def\doprocessallactionsinset
+\unexpanded\def\syst_helpers_do_process_all_actions_in_set
{\csname\s!do\the\processlevel\endcsname}
\unexpanded\def\processallactionsinset[#1]%
- {\expandedaction\!!stringa{#1}%
+ {\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\processaction
\else
- \expandafter\processallactionsinsetindeed
+ \expandafter\syst_helpers_process_all_actions_in_set_indeed
\fi
[#1]}
-\unexpanded\def\processallactionsinsetindeed[#1]#2[#3]%
+\unexpanded\def\syst_helpers_process_all_actions_in_set_indeed[#1]#2[#3]%
{\advance\processlevel \plusone
\expandafter\def\csname\s!do\the\processlevel\endcsname##1%
- {\def\p!dodoprocessaction####1%
- {\p!compareprocessactionD[####1][##1]}%
- \processcommalist[#3]\p!dodoprocessaction}%
- \processcommalist[#1]\doprocessallactionsinset
- \advance\processlevel \minusone
- \expandactions}
+ {\def\syst_helpers_do_do_process_action####1{\syst_helpers_do_compare_process_action_d[####1][##1]}%
+ \processcommalist[#3]\syst_helpers_do_do_process_action}%
+ \normalexpanded{\processcommalist[#1]}\syst_helpers_do_process_all_actions_in_set
+ \advance\processlevel\minusone}
%D These macros use:
-\def\processnextcommalist#1#2#3[#4#5]%
+\unexpanded\def\processnextcommalist#1#2#3[#4#5]%
{#1%
\let\nexttoken#4%
\global\advance\commalevel \plusone
- \long\expandafter\def\csname\s!next\the\commalevel\endcsname##1,%
- {#3{##1}\doprocesscommaitem}%
- \dodoprocesscommaitem#4#5,]\relax
- \global\advance\commalevel \minusone
+ \expandafter\def\csname\s!next\the\commalevel\endcsname##1,%
+ {#3{##1}\syst_helpers_do_process_comma_item}%
+ \syst_helpers_do_do_process_comma_item#4#5,]\relax
+ \global\advance\commalevel\minusone
#2}
%D \macros
-%D {unexpandedprocessaction,
-%D unexpandedprocessfirstactioninset,
-%D unexpandedprocessallactionsinset}
-%D
-%D Now what are those expansion commands doing there. Well,
-%D sometimes we want to compare actions that may consist off
-%D commands (i.e. are no constants). In such occasions we can
-%D use the a bit slower alternatives:
-
-\def\unexpandedprocessfirstactioninset{\dontexpandactions\processfirstactioninset}
-\def\unexpandedprocessaction {\dontexpandactions\processaction}
-\def\unexpandedprocessallactionsinset {\dontexpandactions\processallactionsinset}
-
-%D By default we expand actions:
-
-\def\expandactions{\let\expandedaction\edef} \expandactions
-
-%D But when needed we convert the strings to meaningful
-%D sequences of characters.
-
-\def\unexpandedaction#1>{}
-
-\def\noexpandedaction#1#2%
- {\def\@@convertedargument{#2}%
- \@EA\edef\@EA#1\@EA{\@EA\unexpandedaction\meaning\@@convertedargument}}
-
-\def\dontexpandactions
- {\let\expandedaction\noexpandedaction}
-
-%D \macros
%D {getfirstcharacter, firstcharacter, remainingcharacters, doiffirstcharacter}
%D
%D Sometimes the action to be undertaken depends on the
@@ -1247,27 +1218,8 @@
%D complicated arguments, for instance arguments that
%D consist of two or more expandable tokens.
-\def\dogetfirstcharacter#1#2\relax
- {\def\firstcharacter{#1}%
- \def\remainingcharacters{#2}}
-
-\def\getfirstcharacter#1%
- {\edef\!!stringa{#1}%
- \expandafter\dogetfirstcharacter\!!stringa\relax}
-
-\def\doiffirstcharelse#1#2% char string
-% kort (maar onleesbaar)
-% {\expanded{\dogetfirstcharacter#2}\\\doifelse{#1}\firstcharacter}
-% korter (en begrijpelijk))
- {\getfirstcharacter{#2}\doifelse{#1}\firstcharacter}
-% snel (maar zelden gebruikt, dus niet zo belangrijk)
-% {\getfirstcharacter{#2}%
-% \edef\!!stringa{#1}%
-% \ifx\!!stringa\firstcharacter
-% \expandafter\firstoftwoarguments
-% \else
-% \expandafter\secondoftwoarguments
-% \fi}
+\def\getfirstcharacter #1{\ctxcommand{getfirstcharacter(\!!bs#1\!!es)}}
+\def\doiffirstcharelse#1#2{\ctxcommand{doiffirstcharelse(\!!bs#1\!!es,\!!bs#2\!!es)}} % chr str
%D \macros
%D {doifinstringelse, doifincsnameelse}
@@ -1279,56 +1231,57 @@
%D \doifinsetelse {substring} {string} {then ...} {else ...}
%D \stoptyping
-\long\def\doifinstringelse#1%
+\unexpanded\def\doifinstringelse#1%
{\edef\@@@instring{#1}% expand #1 here
\ifx\@@@instring\empty
- \@EA\thirdofthreearguments
+ \expandafter\thirdofthreearguments
\else
- \@EA\dodoifinstringelse
+ \expandafter\syst_helpers_do_if_in_string_else_indeed
\fi}
-\long\def\dodoifinstringelse#1%
- {\p!doifinstringelse\@@@instring{#1}%
- \@EA\firstoftwoarguments
+\unexpanded\def\syst_helpers_do_if_in_string_else_indeed#1%
+ {\syst_helpers_do_if_in_string_else\@@@instring{#1}%
+ \expandafter\firstoftwoarguments
\else
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
-\long\def\doifinstring#1%%
+\unexpanded\def\doifinstring#1%%
{\edef\@@@instring{#1}% expand #1 here
\ifx\@@@instring\empty
- \@EA\gobbletwoarguments
+ \expandafter\gobbletwoarguments
\else
- \@EA\dodoifinstring
+ \expandafter\syst_helpers_do_if_in_string_indeed
\fi}
-\long\def\dodoifinstring#1%
- {\p!doifinstringelse\@@@instring{#1}%
- \@EA\firstofoneargument
+\unexpanded\def\syst_helpers_do_if_in_string_indeed#1%
+ {\syst_helpers_do_if_in_string_else\@@@instring{#1}%
+ \expandafter\firstofoneargument
\else
- \@EA\gobbleoneargument
+ \expandafter\gobbleoneargument
\fi}
-\long\def\doifnotinstring#1%%
+\unexpanded\def\doifnotinstring#1%%
{\edef\@@@instring{#1}% expand #1 here
\ifx\@@@instring\empty
- \@EA\gobbletwoarguments
+ \expandafter\gobbletwoarguments
\else
- \@EA\dodoifnotinstring
+ \expandafter\syst_helpers_do_if_not_in_string_indeed
\fi}
-\long\def\dodoifnotinstring#1%
- {\p!doifinstringelse\@@@instring{#1}%
- \@EA\gobbleoneargument
+\unexpanded\def\syst_helpers_do_if_not_in_string_indeed#1%
+ {\syst_helpers_do_if_in_string_else\@@@instring{#1}%
+ \expandafter\gobbleoneargument
\else
- \@EA\firstofoneargument
+ \expandafter\firstofoneargument
\fi}
% replaces prev
-\long\def\p!doifinstringelse#1#2% ##2 can be {abc}
- {\long\@EA\def\@EA\pp!doifinstringelse\@EA##\@EA1#1##2##3\war{\unless\if##2@}% expand #1 here
- \expandafter\pp!doifinstringelse\normalexpanded{#2#1}@@\war} % expand #2 here
+\unexpanded\def\syst_helpers_do_if_in_string_else#1#2% ##2 can be {abc}
+ {\expandafter\def\expandafter\syst_helpers_do_do_if_in_string_else
+ \expandafter##\expandafter1#1##2##3\war{\unless\if##2@}% expand #1 here
+ \expandafter\syst_helpers_do_do_if_in_string_else\normalexpanded{#2#1}@@\war} % expand #2 here
%D The next alternative proved to be upto twice as fast on
%D tasks like checking reserved words in pretty verbatim
@@ -1343,14 +1296,14 @@
%D possible, the latter alternative does minimal (one level)
%D expansion.
-\long\def\p!doifincsnameelse#1#2%
- {\long\def\pp!doifincsnameelse##1#1##2##3\war
+\unexpanded\def\syst_helpers_do_if_in_csname_else#1#2%
+ {\def\syst_helpers_do_do_if_in_csname_else##1#1##2##3\war
{\unless\if##2@}%
- \@EA\pp!doifincsnameelse#2#1@@\war}
+ \expandafter\syst_helpers_do_do_if_in_csname_else#2#1@@\war}
-\long\def\doifincsnameelse#1#2% % #3#4%
+\unexpanded\def\doifincsnameelse#1#2%
{\edef\@@@instring{#1}%
- \@EA\p!doifincsnameelse\@EA{\@@@instring}{#2}% % #3\else#4\fi}
+ \expandafter\syst_helpers_do_if_in_csname_else\expandafter{\@@@instring}{#2}%
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
@@ -1372,7 +1325,7 @@
%D \type{\getal} and \type{\the\count...}. This macro is a
%D rather dirty one.
-\long\def\doifnumberelse#1% does not accept counters
+\def\doifnumberelse#1% does not accept counters (fully expandable)
{\ifcase0\ifcase1#1\or\or\or\or\or\or\or\or\or\else1\fi\space
\expandafter\secondoftwoarguments
\else
@@ -1407,26 +1360,26 @@
%D length of the argument (the longer the argument, the less
%D we gain).
-\def\makerawcommalist[#1]#2% use \processnext ... here
- {\def\domakerawcommalist##1% we don't expand ##1
+\unexpanded\def\makerawcommalist[#1]#2% use \processnext ... here
+ {\def\syst_helpers_do_make_raw_comma_list##1% we don't expand ##1
{\ifx#2\empty
\def#2{##1}%
\else
- \@EA\def\@EA#2\@EA{#2,##1}%
+ \expandafter\def\expandafter#2\expandafter{#2,##1}%
\fi}%
\let#2\empty
- \processcommalist[#1]\domakerawcommalist}
+ \processcommalist[#1]\syst_helpers_do_make_raw_comma_list}
-\def\rawprocesscommaitem#1,#2% #2 eats up preceding space
+\def\syst_helpers_raw_process_comma_item#1,#2% #2 eats up preceding space
{\if]#1\else
\csname\s!next\the\commalevel\endcsname{#1}%
- \expandafter\rawprocesscommaitem
+ \expandafter\syst_helpers_raw_process_comma_item
\fi#2}
\unexpanded\def\rawprocesscommalist[#1]#2% accepteert ook [\cs]
{\global\advance\commalevel \plusone
\expandafter\let\csname\s!next\the\commalevel\endcsname#2%
- \expandafter\rawprocesscommaitem#1,],% \relax
+ \expandafter\syst_helpers_raw_process_comma_item#1,],% \relax
\global\advance\commalevel \minusone }
\unexpanded\def\rawprocesscommacommand[#1]% not really needed
@@ -1437,55 +1390,55 @@
\def\@@rawempty{,,}
-\long\def\rawdoifinsetelse#1%
+\unexpanded\def\rawdoifinsetelse#1%
{\edef\@@@instring{,#1,}% expand #1 here
\ifx\@@@instring\@@rawempty
- \@EA\thirdofthreearguments
+ \expandafter\thirdofthreearguments
\else
- \@EA\rawdodoifinsetelse
+ \expandafter\syst_helpers_raw_do_if_in_set_else
\fi}
-\long\def\rawdodoifinsetelse#1%
- {\p!doifinstringelse\@@@instring{,#1,}%
- \@EA\firstoftwoarguments
+\unexpanded\def\syst_helpers_raw_do_if_in_set_else#1%
+ {\syst_helpers_do_if_in_string_else\@@@instring{,#1,}%
+ \expandafter\firstoftwoarguments
\else
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
-\long\def\rawdoifinset#1%
+\unexpanded\def\rawdoifinset#1%
{\edef\@@@instring{,#1,}% expand #1 here
\ifx\@@@instring\@@rawempty
- \@EA\gobbletwoarguments
+ \expandafter\gobbletwoarguments
\else
- \@EA\rawdodoifinset
+ \expandafter\syst_helpers_raw_do_if_in_set
\fi}
-\long\def\rawdodoifinset#1%%
- {\p!doifinstringelse\@@@instring{,#1,}%
- \@EA\firstofoneargument
+\unexpanded\def\syst_helpers_raw_do_if_in_set#1%%
+ {\syst_helpers_do_if_in_string_else\@@@instring{,#1,}%
+ \expandafter\firstofoneargument
\else
- \@EA\gobbleoneargument
+ \expandafter\gobbleoneargument
\fi}
%D Some more raw material:
-\def\p!rawprocessaction[#1][#2]%
- {\def\pp!rawprocessaction##1,#1=>##2,##3\war%
+\def\syst_helpers_do_raw_process_action[#1][#2]%
+ {\def\syst_helpers_do_do_raw_process_action##1,#1=>##2,##3\war
{\if##3@\else
\def\!!processaction{##2}%
\fi}%
- \pp!rawprocessaction,#2,#1=>,@\war}
+ \syst_helpers_do_do_raw_process_action,#2,#1=>,@\war}
-\def\rawprocessaction[#1]#2[#3]%
+\unexpanded\def\rawprocessaction[#1]#2[#3]%
{\edef\!!stringa{#1}%
\edef\!!stringb{undefined}% better \!!undefined
\let\!!processaction\!!stringb
\ifx\!!stringa\empty
- \@EA\p!rawprocessaction\@EA[\s!default][#3]%
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\s!default][#3]%
\else
- \expandafter\p!rawprocessaction\expandafter[\!!stringa][#3]%
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\!!stringa][#3]%
\ifx\!!processaction\!!stringb
- \@EA\p!rawprocessaction\@EA[\s!unknown][#3]%
+ \expandafter\syst_helpers_do_raw_process_action\expandafter[\s!unknown][#3]%
\fi
\fi
\ifx\!!processaction\!!stringb
@@ -1519,22 +1472,22 @@
%D for use outside the assignment macros.
\def\dosetvalue#1#2% #3
- {\@EA\def\csname#1#2\endcsname} % {#3}}
+ {\expandafter\def\csname#1#2\endcsname} % {#3}}
\def\dosetevalue#1#2% #3
- {\@EA\edef\csname#1#2\endcsname} % {#3}}
+ {\expandafter\edef\csname#1#2\endcsname} % {#3}}
\def\dosetgvalue#1#2% #3
- {\@EA\gdef\csname#1#2\endcsname} % {#3}}
+ {\expandafter\gdef\csname#1#2\endcsname} % {#3}}
\def\doresetvalue#1#2%
- {\@EA\let\csname#1#2\endcsname\empty}
+ {\expandafter\let\csname#1#2\endcsname\empty}
\def\doignorevalue#1#2#3%
- {\@EA\let\csname#1#2\endcsname\empty}
+ {\expandafter\let\csname#1#2\endcsname\empty}
\def\docopyvalue#1#2#3%
- {\@EA\def\csname#1#3\endcsname{\csname#2#3\endcsname}}
+ {\expandafter\def\csname#1#3\endcsname{\csname#2#3\endcsname}}
%D \macros
%D {doassign,undoassign,doassignempty}
@@ -1656,13 +1609,13 @@
\let\currentvalue\empty
-\def\getparameters {\dogetparameters\dosetvalue}
-\def\geteparameters {\dogetparameters\dosetevalue}
-\def\getgparameters {\dogetparameters\dosetgvalue}
-\def\getxparameters {\dogetparameters\dosetxvalue}
-\def\forgetparameters{\dogetparameters\doignorevalue}
+\unexpanded\def\getparameters {\dogetparameters\dosetvalue}
+\unexpanded\def\geteparameters {\dogetparameters\dosetevalue}
+\unexpanded\def\getgparameters {\dogetparameters\dosetgvalue}
+\unexpanded\def\getxparameters {\dogetparameters\dosetxvalue}
+\unexpanded\def\forgetparameters{\dogetparameters\doignorevalue}
-\let\getexpandedparameters=\geteparameters
+\let\getexpandedparameters\geteparameters
\def\dogetparameters#1[#2]#3[#4%
{\if\noexpand#4]%
@@ -1676,14 +1629,14 @@
\def\xdogetparameters#1]%
{\xprocesscommaitem#1,],\@relax@}
-\long\def\xprocesscommaitem#1,#2% #2 takes space before ,
+\def\xprocesscommaitem#1,#2% #2 takes space before ,
{\if,#1,% dirty trick for testing #1=empty
- \@EA\xprocesscommaitem
+ \expandafter\xprocesscommaitem
\else\if]#1%
- \@EAEAEA\gobbleoneargument
+ \doubleexpandafter\gobbleoneargument
\else
\p!dogetparameter\@relax@#1==\empty\@relax@
- \@EAEAEA\xprocesscommaitem
+ \doubleexpandafter\xprocesscommaitem
\fi\fi#2}
\def\xshowassignerror#1#2#3%
@@ -1691,26 +1644,26 @@
\def\p!n!doassign#1\@relax@#2=#3=#4#5\@relax@
{\ifx\empty#2\empty
- \@EA\xshowassignerror
+ \expandafter\xshowassignerror
\else\ifx#4\empty
- \@EAEAEA\xshowassignerror
+ \doubleexpandafter\xshowassignerror
\else
- \@EAEAEA\setsomevalue
+ \doubleexpandafter\setsomevalue
\fi\fi
{#1}{#2}{#3}}
\def\p!e!doassign#1\@relax@#2=#3=#4#5\@relax@
{\ifx\empty#2\empty
- \@EA\xshowassignerror
+ \expandafter\xshowassignerror
\else\ifx#4\empty
- \@EAEAEA\xshowassignerror
+ \doubleexpandafter\xshowassignerror
\else
\ifcsname#1#2\endcsname
- \@EA\let\@EA\currentvalue\csname#1#2\endcsname
+ \expandafter\let\expandafter\currentvalue\csname#1#2\endcsname
\else
\let\currentvalue\empty
\fi
- \@EAEAEA\setsomevalue
+ \doubleexpandafter\setsomevalue
\fi\fi
{#1}{#2}{#3}}
@@ -1741,12 +1694,12 @@
\unexpanded\def\processassignmentcommand[#1]%
{\normalexpanded{\processassignmentlist[#1]}}
-\long\unexpanded\def\startprocessassignmentlist[#1]#2\stopprocessassignmentlist
- {\long\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}%
+\unexpanded\def\startprocessassignmentlist[#1]#2\stopprocessassignmentlist
+ {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}%
\processassignmentlist[#1]\currentassignmentlistcommand}
-\long\unexpanded\def\startprocessassignmentcommand[#1]#2\stopprocessassignmentcommand
- {\long\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}%
+\unexpanded\def\startprocessassignmentcommand[#1]#2\stopprocessassignmentcommand
+ {\def\currentassignmentlistcommand##1##2{\def\currentassignmentlistkey{##1}\def\currentassignmentlistvalue{##2}#2}%
\normalexpanded{\processassignmentlist[#1]}\currentassignmentlistcommand}
%D \macros{currentvalue}
@@ -1846,7 +1799,7 @@
%D By using \type{\docopyvalue} we've prepared this command
%D for use in a multi||lingual environment.
-\def\copyparameters[#1]#2[#3]#4[#5]%
+\unexpanded\def\copyparameters[#1]#2[#3]#4[#5]%
{\doifnot{#1}{#3}
{\def\docopyparameter{\docopyvalue{#1}{#3}}% ##1
\processcommalist[#5]\docopyparameter}}
@@ -1975,7 +1928,7 @@
% check sources
\def\dogetcommacommandelement#1\from#2\to%
- {\@EA\dodogetcommalistelement\@EA#1\@EA\from#2,,,,,,\to}
+ {\expandafter\dodogetcommalistelement\expandafter#1\expandafter\from#2,,,,,,\to}
%D \macros
%D {dosingleargument,dodoubleargument,dotripleargument,
@@ -2031,13 +1984,13 @@
%D us to do some checking, we reimplemented the non||empty
%D ones.
-\def\dosingleargument {\let\expectedarguments\plusone \dosingleempty }
-\def\dodoubleargument {\let\expectedarguments\plustwo \dodoubleempty }
-\def\dotripleargument {\let\expectedarguments\plusthree \dotripleempty }
-\def\doquadrupleargument {\let\expectedarguments\plusfour \doquadrupleempty }
-\def\doquintupleargument {\let\expectedarguments\plusfive \doquintupleempty }
-\def\dosixtupleargument {\let\expectedarguments\plussix \dosixtupleempty }
-\def\doseventupleargument{\let\expectedarguments\plusseven \doseventupleempty}
+\unexpanded\def\dosingleargument {\let\expectedarguments\plusone \dosingleempty }
+\unexpanded\def\dodoubleargument {\let\expectedarguments\plustwo \dodoubleempty }
+\unexpanded\def\dotripleargument {\let\expectedarguments\plusthree \dotripleempty }
+\unexpanded\def\doquadrupleargument {\let\expectedarguments\plusfour \doquadrupleempty }
+\unexpanded\def\doquintupleargument {\let\expectedarguments\plusfive \doquintupleempty }
+\unexpanded\def\dosixtupleargument {\let\expectedarguments\plussix \dosixtupleempty }
+\unexpanded\def\doseventupleargument{\let\expectedarguments\plusseven \doseventupleempty}
%D \macros
%D {iffirstagument,ifsecondargument,ifthirdargument,
@@ -2100,169 +2053,6 @@
\def\noshowargumenterror
{\let\expectedarguments\noexpectedarguments}
-% \long\def\dogetargument#1#2#3#4%
-% {\let\charactertoken=#1%
-% \def\!!stringa{\noshowargumenterror#3\dodogetargument}%
-% \def\!!stringb{\doshowargumenterror#4\dodogetargument#1#2}%
-% \futurelet\nexttoken\inspectnextcharacter}
-
-% \def\getsingleempty#1#2#3%
-% {\def\dodogetargument%
-% {#3}%
-% \dogetargument#1#2\firstargumenttrue\firstargumentfalse}
-
-% \def\getdoubleempty#1#2#3%
-% {\def\dodogetargument#1##1#2%
-% {\def\dodogetargument%
-% {#3#1{##1}#2}%
-% \dogetargument#1#2\secondargumenttrue\secondargumentfalse}%
-% \dogetargument#1#2\firstargumenttrue\firstargumentfalse}
-
-% \def\gettripleempty#1#2#3%
-% {\def\dodogetargument#1##1#2%
-% {\def\dodogetargument#1####1#2%
-% {\def\dodogetargument%
-% {#3#1{##1}#2%
-% #1{####1}#2}%
-% \dogetargument#1#2\thirdargumenttrue\thirdargumentfalse}%
-% \dogetargument#1#2\secondargumenttrue\secondargumentfalse}%
-% \dogetargument#1#2\firstargumenttrue\firstargumentfalse}
-
-% \def\getquadrupleempty#1#2#3%
-% {\def\dodogetargument#1##1#2%
-% {\def\dodogetargument#1####1#2%
-% {\def\dodogetargument#1########1#2%
-% {\def\dodogetargument%
-% {#3#1{##1}#2%
-% #1{####1}#2%
-% #1{########1}#2}%
-% \dogetargument#1#2\fourthargumenttrue\fourthargumentfalse}%
-% \dogetargument#1#2\thirdargumenttrue\thirdargumentfalse}%
-% \dogetargument#1#2\secondargumenttrue\secondargumentfalse}%
-% \dogetargument#1#2\firstargumenttrue\firstargumentfalse}
-
-% \def\getquintupleempty#1#2#3%
-% {\def\dodogetargument#1##1#2%
-% {\def\dodogetargument#1####1#2%
-% {\def\dodogetargument#1########1#2%
-% {\def\dodogetargument#1################1#2%
-% {\def\dodogetargument%
-% {#3#1{##1}#2%
-% #1{####1}#2%
-% #1{########1}#2%
-% #1{################1}#2}%
-% \dogetargument#1#2\fifthargumenttrue\fifthargumentfalse}%
-% \dogetargument#1#2\fourthargumenttrue\fourthargumentfalse}%
-% \dogetargument#1#2\thirdargumenttrue\thirdargumentfalse}%
-% \dogetargument#1#2\secondargumenttrue\secondargumentfalse}%
-% \dogetargument#1#2\firstargumenttrue\firstargumentfalse}
-
-% \def\getsixtupleempty#1#2#3%
-% {\def\dodogetargument#1##1#2%
-% {\def\dodogetargument#1####1#2%
-% {\def\dodogetargument#1########1#2%
-% {\def\dodogetargument#1################1#2%
-% {\def\dodogetargument#1################################1#2%
-% {\def\dodogetargument%
-% {#3#1{##1}#2%
-% #1{####1}#2%
-% #1{########1}#2%
-% #1{################1}#2%
-% #1{################################1}#2}%
-% \dogetargument#1#2\sixthargumenttrue\sixthargumentfalse}%
-% \dogetargument#1#2\fifthargumenttrue\fifthargumentfalse}%
-% \dogetargument#1#2\fourthargumenttrue\fourthargumentfalse}%
-% \dogetargument#1#2\thirdargumenttrue\thirdargumentfalse}%
-% \dogetargument#1#2\secondargumenttrue\secondargumentfalse}%
-% \dogetargument#1#2\firstargumenttrue\firstargumentfalse}
-
-% \def\getseventupleempty#1#2#3%
-% {\def\dodogetargument#1##1#2%
-% {\def\dodogetargument#1####1#2%
-% {\def\dodogetargument#1########1#2%
-% {\def\dodogetargument#1################1#2%
-% {\def\dodogetargument#1################################1#2%
-% {\def\dodogetargument#1################################%
-% ################################1#2%
-% {\def\dodogetargument%
-% {#3#1{##1}#2%
-% #1{####1}#2%
-% #1{########1}#2%
-% #1{################1}#2%
-% #1{################################1}#2%
-% #1{################################%
-% ################################1}#2}%
-% \dogetargument#1#2\seventhargumenttrue\seventhargumentfalse}%
-% \dogetargument#1#2\sixthargumenttrue\sixthargumentfalse}%
-% \dogetargument#1#2\fifthargumenttrue\fifthargumentfalse}%
-% \dogetargument#1#2\fourthargumenttrue\fourthargumentfalse}%
-% \dogetargument#1#2\thirdargumenttrue\thirdargumentfalse}%
-% \dogetargument#1#2\secondargumenttrue\secondargumentfalse}%
-% \dogetargument#1#2\firstargumenttrue\firstargumentfalse}
-
-% \def\dosingleempty {\getsingleempty []}
-% \def\dodoubleempty {\getdoubleempty []}
-% \def\dotripleempty {\gettripleempty []}
-% \def\doquadrupleempty {\getquadrupleempty []}
-% \def\doquintupleempty {\getquintupleempty []}
-% \def\dosixtupleempty {\getsixtupleempty []}
-% \def\doseventupleempty{\getseventupleempty[]}
-
-%D Because some of these are called quite often, we will now
-%D replace the more general version by alternatives tuned for
-%D speed.
-
-% \def\dosingleempty#1% we can make dedicated doifnextoptional's
-% {\noshowargumenterror % \relax % prevents lookahead, brr
-% \doifnextoptionalelse
-% {\firstargumenttrue#1}%
-% {\dosinglefakeempty#1}}
-%
-% \def\dosinglefakeempty#1%
-% {\firstargumentfalse#1[]}
-%
-% \def\dodoubleempty#1%
-% {\noshowargumenterror % \relax % prevents lookahead, brr
-% \doifnextoptionalelse
-% {\dodoubletestempty#1}%
-% {\dodoublefakeempty#1}}
-%
-% \def\dodoublefakeempty#1%
-% {\firstargumentfalse\secondargumentfalse#1[][]}
-%
-% \long\def\dodoubletestempty#1[#2]%
-% {\firstargumenttrue
-% \doifnextoptionalelse
-% {\secondargumenttrue #1[{#2}]}%
-% {\secondargumentfalse#1[{#2}][]}}
-%
-% \def\dotripleempty#1%
-% {\noshowargumenterror % \relax % prevents lookahead, brr
-% \doifnextoptionalelse
-% {\dotripletestempty#1}%
-% {\dotriplefakeempty#1}}
-%
-% \def\dotriplefakeempty#1%
-% {\firstargumentfalse\secondargumentfalse\thirdargumentfalse#1[][][]}
-%
-% \long\def\dotripletestempty#1[#2]%
-% {\firstargumenttrue
-% \doifnextoptionalelse
-% {\dotripletestemptyx #1[{#2}]}%
-% {\secondargumentfalse
-% \thirdargumentfalse #1[{#2}][][]}}
-%
-% \long\def\dotripletestemptyx#1[#2][#3]%
-% {\secondargumenttrue
-% \doifnextoptionalelse
-% {\thirdargumenttrue #1[{#2}][{#3}]}%
-% {\thirdargumentfalse#1[{#2}][{#3}][]}}
-
-%D We can obey following spaces with a bit more code.
-
-% 0.172 0.187 new (per 10000)
-% 0.156 0.140 old (per 10000)
-%
% \def\test[#1]{(#1)}
%
% \dosingleempty\test[] xxx\par
@@ -2283,7 +2073,7 @@
%D Single:
-\def\dosingleempty#1%
+\unexpanded\def\dosingleempty#1%
{\noshowargumenterror
\doifnextoptionalelse
{\firstargumenttrue#1}%
@@ -2295,13 +2085,13 @@
%D Double
-\def\dodoubleempty#1%
+\unexpanded\def\dodoubleempty#1%
{\noshowargumenterror
\doifnextoptionalelse
{\dodoubleemptyYESone#1}%
{\dodoubleemptyNOPone#1}}
-\long\def\dodoubleemptyYESone#1[#2]%
+\def\dodoubleemptyYESone#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
{\secondargumenttrue#1[{#2}]}%
@@ -2314,7 +2104,7 @@
\def\dodoubleemptyNOPtwo
{\secondargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dodoubleemptyonespaced
\else
\expandafter\dodoubleemptyonenormal
@@ -2325,19 +2115,19 @@
% Three
-\def\dotripleempty#1%
+\unexpanded\def\dotripleempty#1%
{\noshowargumenterror
\doifnextoptionalelse
{\dotripleemptyYESone#1}%
{\dotripleemptyNOPone#1}}
-\long\def\dotripleemptyYESone#1[#2]%
+\def\dotripleemptyYESone#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
{\dotripleemptyYEStwo#1{#2}}%
{\dotripleemptyNOPtwo#1{#2}}}
-\long\def\dotripleemptyYEStwo#1#2[#3]%
+\def\dotripleemptyYEStwo#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
{\thirdargumenttrue#1[{#2}][{#3}]}%
@@ -2352,7 +2142,7 @@
\def\dotripleemptyNOPtwo
{\secondargumentfalse
\thirdargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dotripleemptytwospaced
\else
\expandafter\dotripleemptytwonormal
@@ -2360,7 +2150,7 @@
\def\dotripleemptyNOPthree
{\thirdargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dotripleemptythreespaced
\else
\expandafter\dotripleemptythreenormal
@@ -2373,25 +2163,25 @@
%D Four:
-\def\doquadrupleempty#1%
+\unexpanded\def\doquadrupleempty#1%
{\noshowargumenterror
\doifnextoptionalelse
{\doquadrupleemptyYESone#1}%
{\doquadrupleemptyNOPone#1}}
-\long\def\doquadrupleemptyYESone#1[#2]%
+\def\doquadrupleemptyYESone#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
{\doquadrupleemptyYEStwo#1{#2}}%
{\doquadrupleemptyNOPtwo#1{#2}}}
-\long\def\doquadrupleemptyYEStwo#1#2[#3]%
+\def\doquadrupleemptyYEStwo#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
{\doquadrupleemptyYESthree#1{#2}{#3}}%
{\doquadrupleemptyNOPthree#1{#2}{#3}}}
-\long\def\doquadrupleemptyYESthree#1#2#3[#4]%
+\def\doquadrupleemptyYESthree#1#2#3[#4]%
{\thirdargumenttrue
\doifnextoptionalelse
{\fourthargumenttrue#1[{#2}][{#3}][{#4}]}%
@@ -2408,7 +2198,7 @@
{\secondargumentfalse
\thirdargumentfalse
\fourthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\doquadrupleemptytwospaced
\else
\expandafter\doquadrupleemptytwonormal
@@ -2417,7 +2207,7 @@
\def\doquadrupleemptyNOPthree
{\thirdargumentfalse
\fourthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\doquadrupleemptythreespaced
\else
\expandafter\doquadrupleemptythreenormal
@@ -2425,7 +2215,7 @@
\def\doquadrupleemptyNOPfour
{\fourthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\doquadrupleemptyfourspaced
\else
\expandafter\doquadrupleemptyfournormal
@@ -2440,31 +2230,31 @@
%D Five:
-\def\doquintupleempty#1%
+\unexpanded\def\doquintupleempty#1%
{\noshowargumenterror
\doifnextoptionalelse
{\doquintupleemptyYESone#1}%
{\doquintupleemptyNOPone#1}}
-\long\def\doquintupleemptyYESone#1[#2]%
+\def\doquintupleemptyYESone#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
{\doquintupleemptyYEStwo#1{#2}}%
{\doquintupleemptyNOPtwo#1{#2}}}
-\long\def\doquintupleemptyYEStwo#1#2[#3]%
+\def\doquintupleemptyYEStwo#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
{\doquintupleemptyYESthree#1{#2}{#3}}%
{\doquintupleemptyNOPthree#1{#2}{#3}}}
-\long\def\doquintupleemptyYESthree#1#2#3[#4]%
+\def\doquintupleemptyYESthree#1#2#3[#4]%
{\thirdargumenttrue
\doifnextoptionalelse
{\doquintupleemptyYESfour#1{#2}{#3}{#4}}%
{\doquintupleemptyNOPfour#1{#2}{#3}{#4}}}
-\long\def\doquintupleemptyYESfour#1#2#3#4[#5]%
+\def\doquintupleemptyYESfour#1#2#3#4[#5]%
{\fourthargumenttrue
\doifnextoptionalelse
{\fifthargumenttrue#1[{#2}][{#3}][{#4}][{#5}]}%
@@ -2483,7 +2273,7 @@
\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\doquintupleemptytwospaced
\else
\expandafter\doquintupleemptytwonormal
@@ -2493,7 +2283,7 @@
{\thirdargumentfalse
\fourthargumentfalse
\fifthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\doquintupleemptythreespaced
\else
\expandafter\doquintupleemptythreenormal
@@ -2502,7 +2292,7 @@
\def\doquintupleemptyNOPfour
{\fourthargumentfalse
\fifthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\doquintupleemptyfourspaced
\else
\expandafter\doquintupleemptyfournormal
@@ -2510,7 +2300,7 @@
\def\doquintupleemptyNOPfive
{\fifthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\doquintupleemptyfivespaced
\else
\expandafter\doquintupleemptyfivenormal
@@ -2527,37 +2317,37 @@
%D Six
-\def\dosixtupleempty#1%
+\unexpanded\def\dosixtupleempty#1%
{\noshowargumenterror
\doifnextoptionalelse
{\dosixtupleemptyYESone#1}
{\dosixtupleemptyNOPone#1}}
-\long\def\dosixtupleemptyYESone#1[#2]%
+\def\dosixtupleemptyYESone#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
{\dosixtupleemptyYEStwo#1{#2}}%
{\dosixtupleemptyNOPtwo#1{#2}}}
-\long\def\dosixtupleemptyYEStwo#1#2[#3]%
+\def\dosixtupleemptyYEStwo#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
{\dosixtupleemptyYESthree#1{#2}{#3}}%
{\dosixtupleemptyNOPthree#1{#2}{#3}}}
-\long\def\dosixtupleemptyYESthree#1#2#3[#4]%
+\def\dosixtupleemptyYESthree#1#2#3[#4]%
{\thirdargumenttrue
\doifnextoptionalelse
{\dosixtupleemptyYESfour#1{#2}{#3}{#4}}%
{\dosixtupleemptyNOPfour#1{#2}{#3}{#4}}}
-\long\def\dosixtupleemptyYESfour#1#2#3#4[#5]%
+\def\dosixtupleemptyYESfour#1#2#3#4[#5]%
{\fourthargumenttrue
\doifnextoptionalelse
{\dosixtupleemptyYESfive#1{#2}{#3}{#4}{#5}}%
{\dosixtupleemptyNOPfive#1{#2}{#3}{#4}{#5}}}
-\long\def\dosixtupleemptyYESfive#1#2#3#4#5[#6]%
+\def\dosixtupleemptyYESfive#1#2#3#4#5[#6]%
{\fifthargumenttrue
\doifnextoptionalelse
{\sixthargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}]}%
@@ -2578,7 +2368,7 @@
\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosixemptytwospaced
\else
\expandafter\dosixemptytwonormal
@@ -2589,7 +2379,7 @@
\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosixemptythreespaced
\else
\expandafter\dosixemptythreenormal
@@ -2599,7 +2389,7 @@
{\fourthargumentfalse
\fifthargumentfalse
\sixthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosixemptyfourspaced
\else
\expandafter\dosixemptyfournormal
@@ -2608,7 +2398,7 @@
\def\dosixtupleemptyNOPfive
{\fifthargumentfalse
\sixthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosixemptyfivespaced
\else
\expandafter\dosixemptyfivenormal
@@ -2616,7 +2406,7 @@
\def\dosixtupleemptyNOPsix
{\sixthargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosixemptysixspaced
\else
\expandafter\dosixemptysixnormal
@@ -2635,43 +2425,43 @@
%D Seven:
-\def\doseventupleempty#1%
+\unexpanded\def\doseventupleempty#1%
{\noshowargumenterror
\doifnextoptionalelse
{\doseventupleemptyYESone#1}%
{\doseventupleemptyNOPone#1}}
-\long\def\doseventupleemptyYESone#1[#2]%
+\def\doseventupleemptyYESone#1[#2]%
{\firstargumenttrue
\doifnextoptionalelse
{\doseventupleemptyYEStwo#1{#2}}%
{\doseventupleemptyNOPtwo#1{#2}}}
-\long\def\doseventupleemptyYEStwo#1#2[#3]%
+\def\doseventupleemptyYEStwo#1#2[#3]%
{\secondargumenttrue
\doifnextoptionalelse
{\doseventupleemptyYESthree#1{#2}{#3}}%
{\doseventupleemptyNOPthree#1{#2}{#3}}}
-\long\def\doseventupleemptyYESthree#1#2#3[#4]%
+\def\doseventupleemptyYESthree#1#2#3[#4]%
{\thirdargumenttrue
\doifnextoptionalelse
{\doseventupleemptyYESfour#1{#2}{#3}{#4}}%
{\doseventupleemptyNOPfour#1{#2}{#3}{#4}}}
-\long\def\doseventupleemptyYESfour#1#2#3#4[#5]%
+\def\doseventupleemptyYESfour#1#2#3#4[#5]%
{\fourthargumenttrue
\doifnextoptionalelse
{\doseventupleemptyYESfive#1{#2}{#3}{#4}{#5}}%
{\doseventupleemptyNOPfive#1{#2}{#3}{#4}{#5}}}
-\long\def\doseventupleemptyYESfive#1#2#3#4#5[#6]%
+\def\doseventupleemptyYESfive#1#2#3#4#5[#6]%
{\fifthargumenttrue
\doifnextoptionalelse
{\doseventupleemptyYESsix#1{#2}{#3}{#4}{#5}{#6}}%
{\doseventupleemptyNOPsix#1{#2}{#3}{#4}{#5}{#6}}}
-\long\def\doseventupleemptyYESsix#1#2#3#4#5#6[#7]%
+\def\doseventupleemptyYESsix#1#2#3#4#5#6[#7]%
{\sixthargumenttrue
\doifnextoptionalelse
{\seventhargumenttrue#1[{#2}][{#3}][{#4}][{#5}][{#6}][{#7}]}%
@@ -2694,7 +2484,7 @@
\fifthargumentfalse
\sixthargumentfalse
\seventhargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosevenemptytwospaced
\else
\expandafter\dosevenemptytwonormal
@@ -2706,7 +2496,7 @@
\fifthargumentfalse
\sixthargumentfalse
\seventhargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosevenemptythreespaced
\else
\expandafter\dosevenemptythreenormal
@@ -2717,7 +2507,7 @@
\fifthargumentfalse
\sixthargumentfalse
\seventhargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosevenemptyfourspaced
\else
\expandafter\dosevenemptyfournormal
@@ -2727,7 +2517,7 @@
{\fifthargumentfalse
\sixthargumentfalse
\seventhargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosevenemptyfivespaced
\else
\expandafter\dosevenemptyfivenormal
@@ -2736,7 +2526,7 @@
\def\doseventupleemptyNOPsix
{\sixthargumentfalse
\seventhargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosevenemptysixspaced
\else
\expandafter\dosevenemptysixnormal
@@ -2744,7 +2534,7 @@
\def\doseventupleemptyNOPseven
{\seventhargumentfalse
- \ifnextblankspacetoken
+ \if_next_blank_space_token
\expandafter\dosevenemptysevenspaced
\else
\expandafter\dosevenemptysevennormal
@@ -2819,13 +2609,13 @@
%D but changed into more versatile (more object oriented) ones
%D using the \type{\get..argument} commands.
-\def\complexorsimple#1%
+\unexpanded\def\complexorsimple#1%
{% \relax % prevents lookahead, brrr
\doifnextoptionalelse
{\firstargumenttrue \csname\s!complex\strippedcsname#1\endcsname}
{\firstargumentfalse\csname\s!simple \strippedcsname#1\endcsname}}
-\def\complexorsimpleempty#1%
+\unexpanded\def\complexorsimpleempty#1%
{% \relax % prevents lookahead, brrr
\doifnextoptionalelse
{\firstargumenttrue \csname\s!complex\strippedcsname#1\endcsname}
@@ -2847,13 +2637,13 @@
\unexpanded\def\definecomplexorsimple#1%
{\unexpanded\edef#1%
{\noexpand\docomplexorsimple
- \@EA\noexpand\csname\s!complex\strippedcsname#1\endcsname
- \@EA\noexpand\csname\s!simple \strippedcsname#1\endcsname}}
+ \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname
+ \expandafter\noexpand\csname\s!simple \strippedcsname#1\endcsname}}
\unexpanded\def\definecomplexorsimpleempty#1%
{\unexpanded\edef#1%
{\noexpand\docomplexorsimpleempty
- \@EA\noexpand\csname\s!complex\strippedcsname#1\endcsname}}
+ \expandafter\noexpand\csname\s!complex\strippedcsname#1\endcsname}}
%D These commands are called as:
%D
@@ -3016,32 +2806,34 @@
%D used to select arguments. Their names explain their
%D functionality.
-\long\def\firstofoneargument #1{#1}
+\def\firstofoneargument #1{#1}
-\long\def\firstoftwoarguments #1#2{#1}
-\long\def\secondoftwoarguments #1#2{#2}
+\def\firstoftwoarguments #1#2{#1}
+\def\secondoftwoarguments #1#2{#2}
-\long\def\firstofthreearguments #1#2#3{#1}
-\long\def\secondofthreearguments #1#2#3{#2}
-\long\def\thirdofthreearguments #1#2#3{#3}
+\def\firstofthreearguments #1#2#3{#1}
+\def\secondofthreearguments #1#2#3{#2}
+\def\thirdofthreearguments #1#2#3{#3}
-\long\def\firstoffourarguments #1#2#3#4{#1}
-\long\def\secondoffourarguments #1#2#3#4{#2}
-\long\def\thirdoffourarguments #1#2#3#4{#3}
-\long\def\fourthoffourarguments #1#2#3#4{#4}
+\def\firstoffourarguments #1#2#3#4{#1}
+\def\secondoffourarguments #1#2#3#4{#2}
+\def\thirdoffourarguments #1#2#3#4{#3}
+\def\fourthoffourarguments #1#2#3#4{#4}
-\long\def\firstoffivearguments #1#2#3#4#5{#1}
-\long\def\secondoffivearguments #1#2#3#4#5{#2}
-\long\def\thirdoffivearguments #1#2#3#4#5{#3}
-\long\def\fourthoffivearguments #1#2#3#4#5{#4}
-\long\def\fifthoffivearguments #1#2#3#4#5{#5}
+\def\firstoffivearguments #1#2#3#4#5{#1}
+\def\secondoffivearguments #1#2#3#4#5{#2}
+\def\thirdoffivearguments #1#2#3#4#5{#3}
+\def\fourthoffivearguments #1#2#3#4#5{#4}
+\def\fifthoffivearguments #1#2#3#4#5{#5}
-\long\def\firstofsixarguments #1#2#3#4#5#6{#1}
-\long\def\secondofsixarguments#1#2#3#4#5#6{#2}
-\long\def\thirdofsixarguments #1#2#3#4#5#6{#3}
-\long\def\fourthofsixarguments#1#2#3#4#5#6{#4}
-\long\def\fifthofsixarguments #1#2#3#4#5#6{#5}
-\long\def\sixthofsixarguments #1#2#3#4#5#6{#6}
+\def\firstofsixarguments #1#2#3#4#5#6{#1}
+\def\secondofsixarguments#1#2#3#4#5#6{#2}
+\def\thirdofsixarguments #1#2#3#4#5#6{#3}
+\def\fourthofsixarguments#1#2#3#4#5#6{#4}
+\def\fifthofsixarguments #1#2#3#4#5#6{#5}
+\def\sixthofsixarguments #1#2#3#4#5#6{#6}
+
+\unexpanded\def\firstofoneunexpanded#1{#1}
%D \macros
%D {globalletempty,letempty,
@@ -3220,7 +3012,7 @@
%D Apart from the prefixes, a few more \type{\expandafters}
%D are needed:
-\def\newif#1%
+\unexpanded\def\newif#1%
{\scratchcounter\escapechar
\escapechar\minusone
\expandafter\expandafter\expandafter
@@ -3237,16 +3029,16 @@
\unexpanded\def\define#1%
{\ifdefined#1%
\message{[\noexpand#1is already defined]}%
- \expandafter\def\expandafter\gobbleddefinition
+ \unexpanded\expandafter\def\expandafter\gobbleddefinition
\else
- \expandafter\def
+ \unexpanded\expandafter\def
\fi#1}
\def\redefine#1%
{\ifdefined#1%
\message{[\noexpand#1is redefined]}%
\fi
- \def#1}
+ \unexpanded\def#1}
% \define\hans{hans}
% \redefine\hans{hans}
@@ -3270,6 +3062,40 @@
%
% [\test]
+% todo: pick up keywords:
+%
+% \starttexdefinition unexpanded bagger ....
+
+% \bgroup \obeylines
+%
+% \gdef\starttexdefinition%
+% {\bgroup%
+% \obeylines%
+% \dostarttexdefinition}
+%
+% \gdef\dostarttexdefinition #1
+% {\catcode\endoflineasciicode\ignorecatcode%
+% \doifinstringelse\letterhash{\detokenize{#1}}\dodostarttexdefinition\nonostarttexdefinition#1
+% }
+%
+% \gdef\dodostarttexdefinition#1 #2
+% {\dododostarttexdefinition{#1}{#2}}
+%
+% \gdef\dododostarttexdefinition#1#2#3\stoptexdefinition%
+% {\egroup%
+% \expandafter\def\csname#1\endcsname#2{#3}}
+%
+% \gdef\nonostarttexdefinition#1
+% {\nononostarttexdefinition{#1}{}}
+%
+% \gdef\nononostarttexdefinition#1#2#3\stoptexdefinition%
+% {\egroup%
+% \expandafter\def\csname#1\endcsname{#3}}
+%
+% \egroup
+
+\def\s!unexpanded{unexpanded}
+
\bgroup \obeylines
\gdef\starttexdefinition%
@@ -3282,22 +3108,37 @@
\doifinstringelse\letterhash{\detokenize{#1}}\dodostarttexdefinition\nonostarttexdefinition#1
}
-\long\gdef\dodostarttexdefinition#1 #2
- {\dododostarttexdefinition{#1}{#2}}
-
-\long\gdef\dododostarttexdefinition#1#2#3\stoptexdefinition%
+\gdef\dodostarttexdefinition#1 #2
+ {\edef\texdefinitionname{#1}%
+ \ifx\texdefinitionname\s!unexpanded%
+ \expandafter\dododostarttexdefinitionU%
+ \else%
+ \expandafter\dododostarttexdefinitionN%
+ \fi%
+ {#1}#2
+ }
+
+\gdef\dododostarttexdefinitionU#1#2 #3
+ #4\stoptexdefinition%
+ {\egroup% #1=unexpanded
+ \unexpanded\expandafter\def\csname#2\endcsname#3{#4}}
+
+\gdef\dododostarttexdefinitionN#1#2
+ #3\stoptexdefinition%
{\egroup%
\expandafter\def\csname#1\endcsname#2{#3}}
-\long\gdef\nonostarttexdefinition#1
+\gdef\nonostarttexdefinition#1
{\nononostarttexdefinition{#1}{}}
-\long\gdef\nononostarttexdefinition#1#2#3\stoptexdefinition%
+\gdef\nononostarttexdefinition#1#2#3\stoptexdefinition%
{\egroup%
\expandafter\def\csname#1\endcsname{#3}}
\egroup
+\unexpanded\def\texdefinition#1{\csname\ifcsname#1\endcsname#1\else donothing\fi\endcsname}
+
% This is a first variant, more might be added:
\def\starttexcode{\unprotect}
@@ -3367,26 +3208,20 @@
%D Nowadays we don't mind a few more tokens if we can gain a
%D bit of speed.
-\def\doincrement#1%
- {\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\plusone \relax}}
-\def\dodecrement#1%
- {\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\minusone\relax}}
+\def\syst_helpers_do_increment#1{\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\plusone \relax}}
+\def\syst_helpers_do_decrement#1{\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+\minusone\relax}}
-\def\dododoincrement#1,#2)%
- {\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+#2\relax}}
-\def\dodododecrement#1,#2)%
- {\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi-#2\relax}}
+\def\syst_helpers_do_do_do_increment#1,#2){\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi+#2\relax}}
+\def\syst_helpers_do_do_do_decrement#1,#2){\dodoglobal\edef#1{\the\numexpr\ifdefined#1\ifx#1\relax\else#1\fi\fi-#2\relax}}
-\def\dodoincrement(#1%
- {\doifnextcharelse,{\dododoincrement#1}{\dododoincrement#1,\plusone}}
-\def\dododecrement(#1%
- {\doifnextcharelse,{\dodododecrement#1}{\dodododecrement#1,\plusone}}
+\def\syst_helpers_do_do_increment(#1{\doifnextcharelse,{\syst_helpers_do_do_do_increment#1}{\syst_helpers_do_do_do_increment#1,\plusone}}
+\def\syst_helpers_do_do_decrement(#1{\doifnextcharelse,{\syst_helpers_do_do_do_decrement#1}{\syst_helpers_do_do_do_decrement#1,\plusone}}
\def\fastincrement#1{\dodoglobal\edef#1{\the\numexpr#1+\plusone \relax}}
\def\fastdecrement#1{\dodoglobal\edef#1{\the\numexpr#1+\minusone\relax}}
-\def\increment{\doifnextcharelse(\dodoincrement\doincrement}
-\def\decrement{\doifnextcharelse(\dododecrement\dodecrement}
+\def\increment{\doifnextcharelse(\syst_helpers_do_do_increment\syst_helpers_do_increment}
+\def\decrement{\doifnextcharelse(\syst_helpers_do_do_decrement\syst_helpers_do_decrement}
\def\incrementvalue#1{\expandafter\increment\csname#1\endcsname}
\def\decrementvalue#1{\expandafter\decrement\csname#1\endcsname}
@@ -3443,77 +3278,6 @@
\fi}
%D \macros
-%D {newconditional,
-%D settrue, setfalse,
-%D ifconditional,then}
-%D
-%D \TEX's lacks boolean variables, although the \PLAIN\ format
-%D implements \type{\newif}. The main disadvantage of this
-%D scheme is that it takes three hash table entries. A more
-%D memory saving alternative is presented here. A conditional
-%D is defined by:
-%D
-%D \starttyping
-%D \newconditional\doublesided
-%D \setfalse
-%D \stoptyping
-%D Setting a conditional is done by \type{\settrue} and
-%D \type{\setfalse}:
-%D
-%D \starttyping
-%D \settrue\doublesided
-%D \setfalse
-%D \stoptyping
-%D while testing is accomplished by:
-%D
-%D \starttyping
-%D \ifconditional\doublesided ... \else ... \fi
-%D \setfalse
-%D \stoptyping
-%D We cannot use the simple scheme:
-%D
-%D \starttyping
-%D \def\settrue #1{\let#1=\iftrue}
-%D \def\setfalse#1{\let#1=\iffalse}
-%D \stoptyping
-%D
-%D Such an implementation gives problems with nested
-%D conditionals. The next implementation is abaou as fast
-%D and just as straightforward:
-
-% maybe reserve special zero and plusone
-
-\def\settrue #1{\let#1\zerocount}
-\def\setfalse#1{\let#1\plusone}
-
-\let\newconditional\setfalse
-\let\ifconditional \ifcase
-
-\let\then\relax % so that we can say: \ifnum1>2\then -)
-
-% demands that each conditional is defined .. it would be handy to have
-% a primitive \unless\ifcase .. then we could use better values
-%
-% \def\settrue #1{#1\zerocount}
-% \def\setfalse#1{#1\plusone}
-%
-% \def\newconditional#1{\ifdefined#1\else\newcount#1\fi\setfalse#1}
-% \let\ifconditional \ifcase
-
-%D \macros
-%D {ifzeropt}
-%D
-%D The next macro is both cosmetic and byte saving. It is
-%D pretty \type{\if}||safe too. It can be used in cases
-%D like:
-%D
-%D \starttyping
-%D \ifzeropt \somedimen ... \else ... \fi
-%D \stoptyping
-
-\let\ifzeropt\ifcase
-
-%D \macros
%D {dorecurse,recurselevel,recursedepth,
%D dostepwiserecurse,
%D for}
@@ -3567,10 +3331,10 @@
\def\@@irecurse{@@ir@@} % ecurse} % stepper
\def\@@arecurse{@@ar@@} % ecurse} % action
-\long\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
{\global\advance\outerrecurse \plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname{#4}%
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname{#4}%
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
\ifnum#3>0\relax
\ifnum#2<#1\relax
\let\nextrecurse\exitstepwiserecurse
@@ -3589,13 +3353,13 @@
\fi
\fi\normalexpanded{\nextrecurse{\number#1}{\number#2}{\number#3}}}
-\long\def\dodostepwiserecurse#1#2#3% from to step
+\def\dodostepwiserecurse#1#2#3% from to step
{\ifnum#1>#2\relax
- \@EA\nodostepwiserecurse
+ \expandafter\nodostepwiserecurse
\else
\def\recurselevel{#1}%
- \@EAEAEA\redostepwiserecurse\@EA
- \fi\@EA{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
+ \doubleexpandafter\redostepwiserecurse\expandafter
+ \fi\expandafter{\the\numexpr\recurselevel+#3\relax}{#2}{#3}}
\unexpanded\def\expandrecursecontent
{\csname\@@arecurse\recursedepth\endcsname}
@@ -3603,15 +3367,15 @@
\unexpanded\def\redostepwiserecurse
{\expandrecursecontent\dodostepwiserecurse}
-\long\unexpanded\def\dodostepwisereverse#1#2#3% from to step
+\unexpanded\def\dodostepwisereverse#1#2#3% from to step
{\ifnum#1<#2\relax
- \@EA\nodostepwiserecurse
+ \expandafter\nodostepwiserecurse
\else
\def\recurselevel{#1}%
\innerrecurse#1\relax
\advance\innerrecurse#3\relax
- \@EAEAEA\redostepwisereverse\@EA
- \fi\@EA{\the\innerrecurse}{#2}{#3}}
+ \doubleexpandafter\redostepwisereverse\expandafter
+ \fi\expandafter{\the\innerrecurse}{#2}{#3}}
\unexpanded\def\redostepwisereverse
{\expandrecursecontent\dodostepwisereverse}
@@ -3620,16 +3384,21 @@
{\nodostepwiserecurse\relax}
\unexpanded\def\nodostepwiserecurse#1#2#3#4%
- {\@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
+ {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
\global\advance\outerrecurse \minusone}
\unexpanded\def\nonostepwiserecurse#1#2#3%
- {\@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
+ {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
\global\advance\outerrecurse \minusone}
\unexpanded\def\dorecurse#1%
{\dostepwiserecurse1{#1}1}
+\def\doexpandedrecurse#1#2%
+ {\ifnum#1>\zerocount
+ #2\expandafter\doexpandedrecurse\expandafter{\the\numexpr#1-1\relax}{#2}%
+ \fi}
+
%D As we can see here, the simple command \type{\dorecurse} is
%D a special case of the more general:
%D
@@ -3649,7 +3418,7 @@
%D Because the simple case is used often, we implement it
%D more efficiently:
-\long\unexpanded\def\dorecurse#1%
+\unexpanded\def\dorecurse#1%
{\ifcase#1\relax
\expandafter\gobbletwoarguments
\or
@@ -3658,42 +3427,42 @@
\expandafter\xdorecurse
\fi{#1}}
-\long\unexpanded\def\xdorecurse#1#2%
+\unexpanded\def\xdorecurse#1#2%
{\global\advance\outerrecurse \plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname{#2}%
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \@EA\dodorecurse\@EA1\@EA{\number#1}}
+ \expandafter\gdef\csname\@@arecurse\recursedepth\endcsname{#2}%
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \expandafter\dodorecurse\expandafter1\expandafter{\number#1}}
-\long\unexpanded\def\ydorecurse#1#2%
+\unexpanded\def\ydorecurse#1#2%
{\global\advance\outerrecurse \plusone
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
\let\recurselevel\!!plusone
#2%
- \@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
+ \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
\global\advance\outerrecurse \minusone}
-\long\unexpanded\def\dodorecurse#1#2% from to
+\unexpanded\def\dodorecurse#1#2% from to
{\ifnum#1>#2\relax
- \@EA\nodorecurse
+ \expandafter\nodorecurse
\else
\def\recurselevel{#1}%
- \@EAEAEA\redorecurse
- \fi\@EA{\the\numexpr\recurselevel+\plusone\relax}{#2}}
+ \doubleexpandafter\redorecurse
+ \fi\expandafter{\the\numexpr\recurselevel+\plusone\relax}{#2}}
-\long\unexpanded\def\dodorecurse#1#2% from to
+\unexpanded\def\dodorecurse#1#2% from to
{\ifnum#1>#2\relax
- \@EA\nodorecurse
+ \expandafter\nodorecurse
\else
\def\recurselevel{#1}%
\innerrecurse#1\advance\innerrecurse\plusone
- \@EAEAEA\redorecurse
- \fi\@EA{\the\innerrecurse}{#2}}
+ \doubleexpandafter\redorecurse
+ \fi\expandafter{\the\innerrecurse}{#2}}
\unexpanded\def\redorecurse
{\expandrecursecontent\dodorecurse}
\unexpanded\def\nodorecurse#1#2#3%
- {\@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
+ {\expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
\global\advance\outerrecurse \minusone }
%D \macros
@@ -3716,29 +3485,29 @@
\let\endofloop\donothing
-\unexpanded\long\def\doloop#1%
+\unexpanded\def\doloop#1%
{\global\advance\outerrecurse \plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname{#1}%
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \expandafter\gdef\csname\@@arecurse\recursedepth\endcsname{#1}%
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
\let\endofloop\dodoloop
\dodoloop1} % no \plusone else \recurselevel wrong
-\unexpanded\long\def\dodoloop#1%
+\unexpanded\def\dodoloop#1%
{\def\recurselevel{#1}%
- \@EA\redoloop\@EA{\the\numexpr\recurselevel+\plusone\relax}}
+ \expandafter\redoloop\expandafter{\the\numexpr\recurselevel+\plusone\relax}}
\unexpanded\def\redoloop
{\expandrecursecontent\endofloop}
\unexpanded\def\nodoloop#1%
{\let\endofloop\dodoloop % new, permits nested \doloop's
- \@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
+ \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
\global\advance\outerrecurse\minusone}
\unexpanded\def\exitloop % \exitloop quits at end
{\let\endofloop\nodoloop}
-\long\unexpanded\def\exitloopnow#1\endofloop % \exitloopnow quits directly
+\unexpanded\def\exitloopnow#1\endofloop % \exitloopnow quits directly
{\nodoloop}
%D The loop is executed at least once, so beware of situations
@@ -3780,27 +3549,28 @@
%D \stoptyping
\def\expandrecursecontent
- {\csname\@@arecurse\recursedepth\@EA\@EA\@EA\endcsname\@EA\@EA\@EA{\@EA\recurselevel\@EA}\@EA{\recursedepth}}
+ {\csname\@@arecurse\recursedepth\expandafter\expandafter\expandafter\endcsname
+ \expandafter\expandafter\expandafter{\expandafter\recurselevel\expandafter}\expandafter{\recursedepth}}
-\long\unexpanded\def\xdorecurse#1#2%
+\unexpanded\def\xdorecurse#1#2%
{\global\advance\outerrecurse \plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}%
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \@EA\dodorecurse\@EA1\@EA{\number#1}}
+ \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}%
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \expandafter\dodorecurse\expandafter1\expandafter{\number#1}}
-\long\unexpanded\def\ydorecurse#1#2%
+\unexpanded\def\ydorecurse#1#2%
{\global\advance\outerrecurse \plusone
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
\let\recurselevel\!!plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}%
+ \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#2}%
\expandrecursecontent
- \@EA\let\@EA\recurselevel\csname\@@irecurse\recursedepth\endcsname
+ \expandafter\let\expandafter\recurselevel\csname\@@irecurse\recursedepth\endcsname
\global\advance\outerrecurse \minusone}
-\long\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
{\global\advance\outerrecurse \plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
\ifnum#3>0\relax
\ifnum#2<#1\relax
\let\nextrecurse\exitstepwiserecurse
@@ -3819,46 +3589,19 @@
\fi
\fi\normalexpanded{\nextrecurse{\number#1}{\number#2}{\number#3}}}
-\long\unexpanded\def\doloop#1%
+\unexpanded\def\doloop#1%
{\global\advance\outerrecurse \plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#1}%
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#1}%
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
\let\endofloop\dodoloop
\dodoloop1} % no \plusone else \recurselevel wrong
-% EXPERIMENT
-
% faster
-\long\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
{\global\advance\outerrecurse \plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
- \ifnum#3>\zerocount
- \ifnum#2<#1\relax
- \let\nextrecurse\exitstepwiserecurse
- \else
- \let\nextrecurse\dodostepwiserecurse
- \fi
- \else
- \ifnum#3<\zerocount
- \ifnum#1<#2\relax
- \let\nextrecurse\exitstepwiserecurse
- \else
- \let\nextrecurse\dodostepwisereverse
- \fi
- \else
- \let\nextrecurse\exitstepwiserecurse
- \fi
- \fi
- \normalexpanded{\nextrecurse{\number#1}{\number#2}{\number#3}}}
-
-% slightly faster
-
-\long\unexpanded\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
- {\global\advance\outerrecurse \plusone
- \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
- \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+ \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
+ \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
\csname @swr%
\ifnum#3>\zerocount
\ifnum#2<#1\else d\fi
@@ -3873,10 +3616,10 @@
% quite okay too, but untested
%
-% \long\def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
+% \def\dostepwiserecurse#1#2#3#4% can be made faster by postponing #4
% {\global\advance\outerrecurse \plusone
-% \long\global\@EA\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
-% \global\@EA\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
+% \global\expandafter\def\csname\@@arecurse\recursedepth\endcsname##1##2{#4}%
+% \global\expandafter\let\csname\@@irecurse\recursedepth\endcsname\recurselevel
% \normalexpanded
% {\ifnum#3>\zerocount
% \ifnum#2<#1
@@ -3898,56 +3641,63 @@
%D For special purposes:
-\newcount\fastrecursecounter
-\newcount\lastrecursecounter
-\newcount\steprecursecounter
+\newcount\fastloopindex
+\newcount\fastloopfinal
+\let\fastloopcs\relax
-\unexpanded\def\dofastrecurse#1#2#3#4%
- {\def\fastrecursebody{#4}%
- \fastrecursecounter#1\relax
- \lastrecursecounter#2\relax
- \steprecursecounter#3\relax
- \def\recurselevel{\number\fastrecursecounter}%
- \dodofastrecurse}
+\unexpanded\def\dofastloopcs#1#2%
+ {\let\fastloopcs#2
+ \fastloopindex\plusone
+ \fastloopfinal#1\relax
+ \dodofastloopcs}
-\unexpanded\def\resetrecurselevel{\let\recurselevel\!!zerocount}
-
-\unexpanded\def\dodofastrecurse
- {\ifnum\fastrecursecounter>\lastrecursecounter
- % \resetrecurselevel % slows down
+\unexpanded\def\dodofastloopcs
+ {\ifnum\fastloopindex>\fastloopfinal
+ \let\fastloopcs\relax
\else
- \fastrecursebody
- \advance\fastrecursecounter\steprecursecounter
- \expandafter\dodofastrecurse
+ \fastloopcs
+ \advance\fastloopindex\plusone
+ \expandafter\dodofastloopcs
\fi}
-% \appendtoks \resetrecurselevel \to \everydump
+% Helper:
-\everydump\expandafter{\the\everydump\resetrecurselevel}
+\unexpanded\def\resetrecurselevel{\let\recurselevel\!!zerocount}
+
+\let\recurselevel\!!zerocount
-%D This alternative looks a bit different and uses a
-%D pseudo counter. When this macro is nested, we have to use
-%D different counters. This time we use keywords.
+% \appendtoks \resetrecurselevel \to \everydump
+
+%D \macros
+%D {doloopoverlist}
%D
%D \starttyping
-%D \def\alfa{2} \def\beta{100} \def\gamma{3}
-%D
-%D \for \n=55 \to 100 \step 1 \do {... \n ...}
-%D \for \n=\alfa \to \beta \step \gamma \do {... \n ...}
-%D \for \n=\n \to 120 \step 1 \do {... \n ...}
-%D \for \n=120 \to 100 \step -3 \do {... \n ...}
-%D \for \n=55 \to 100 \step 2 \do {... \n ...}
+%D \doloopoverlist {red,green,blue} {
+%D \setuppalet[\recursestring]
+%D \doloopoverlist {light,normal,dark} {
+%D \blackrule[color=\recursestring,width=20cm,height=2cm,depth=0cm]\par
+%D }
+%D }
%D \stoptyping
%D
-%D Only in the third example we need to predefine \type{\n}.
-%D The use of \type{\od} as a dilimiter would have made nested
-%D use more problematic.
+%D or:
+%D
+%D \starttyping
+%D \doloopoverlist {red,green,blue} {
+%D \setuppalet[#1]
+%D \doloopoverlist {light,normal,dark} {
+%D \blackrule[color=##1,width=20cm,height=2cm,depth=0cm]\par
+%D }
+%D }
+%D \stoptyping
-% obsolete:
-%
-% \def\for#1=#2\to#3\step#4\do#5%
-% {\dostepwiserecurse{#2}{#3}{#4}
-% {\let#1\recurselevel#5\let#1\recurselevel}}
+\unexpanded\def\doloopoverlist#1#2%
+ {\global\advance\outerrecurse\plusone
+ \expandafter\gdef\csname\@@arecurse\recursedepth\endcsname##1{\edef\recursestring{##1}#2}%
+ \expandafter\glet\csname\@@irecurse\recursedepth\endcsname\recursestring
+ \normalexpanded{\processcommalist[#1]{\expandafter\noexpand\csname\@@arecurse\recursedepth\endcsname}}%
+ \expandafter\let\expandafter\recursestring\csname\@@irecurse\recursedepth\endcsname
+ \global\advance\outerrecurse\minusone}
%D \macros
%D {newevery,everyline,EveryLine,EveryPar}
@@ -4071,7 +3821,7 @@
{\expandafter\convertcommand\csname#1\endcsname\to}
\def\defconvertedvalue#1#2% less sensitive for \to
- {\@EA\defconvertedcommand\@EA#1\csname#2\endcsname}
+ {\expandafter\defconvertedcommand\expandafter#1\csname#2\endcsname}
%D \macros
%D {doifassignmentelse}
@@ -4093,15 +3843,22 @@
%D \doifassignmentelse {...} {then ...} {else ...}
%D \stoptyping
-\long\def\docheckifassignmentelse#1=#2#3\@end@{\if#2@}%
+\def\docheckifassignmentelse#1=#2#3\@end@{\if#2@}%
-\long\def\doifassignmentelse#1%
+\def\doifassignmentelse#1% expandable
{\expandafter\docheckifassignmentelse\detokenize{#1}=@@\@end@
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
\fi}
+\newif\ifassignment
+
+% \def\docheckassignmentindeed#1=#2#3\@end@{\if#2@\assignmentfalse\else\assignmenttrue\fi}
+%
+% \def\docheckassignment#1%
+% {\expandafter\docheckassignmentindeed\detokenize{#1}=@@\@end@}
+
% D \macros
% D {convertasciiafter}
% D
@@ -4113,7 +3870,7 @@
% D \stoptyping
%
% \def\convertasciiafter#1#2%
-% {\@EA#1\@EA{\detokenize{#2}}}
+% {\expandafter#1\expandafter{\detokenize{#2}}}
%D In \ETEX\ we can use \type {\detokenize} and gain some
%D speed, but in general far less that 1\% for \type
@@ -4122,17 +3879,17 @@
%D something I found out when primitives like \type
%D {\jobname} were fed (or something undefined).
-\long\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}}
-\long\def\convertcommand #1\to#2{\dodoglobal\edef#2{\@EA\detokenize\@EA{#1}}} % hm, only second is also ok
+\def\convertargument#1\to#2{\dodoglobal\edef#2{\detokenize{#1}}}
+\def\convertcommand #1\to#2{\dodoglobal\edef#2{\expandafter\detokenize\expandafter{#1}}} % hm, only second is also ok
-\long\def\defconvertedargument #1#2{\edef#1{\detokenize {#2}}}
-\long\def\defconvertedcommand #1#2{\edef#1{\detokenize\@EA{#2}}}
-\long\def\edefconvertedargument#1#2{\edef#1{#2}%
- \edef#1{\detokenize\@EA{#1}}}
-\long\def\gdefconvertedargument#1#2{\xdef#1{\detokenize {#2}}}
-\long\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\@EA{#2}}}
-\long\def\xdefconvertedargument#1#2{\xdef#1{#2}%
- \xdef#1{\detokenize\@EA{#1}}}
+\def\defconvertedargument #1#2{\edef#1{\detokenize{#2}}}
+\def\defconvertedcommand #1#2{\edef#1{\detokenize\expandafter{#2}}}
+\def\edefconvertedargument#1#2{\edef#1{#2}%
+ \edef#1{\detokenize\expandafter{#1}}}
+\def\gdefconvertedargument#1#2{\xdef#1{\detokenize{#2}}}
+\def\gdefconvertedcommand #1#2{\xdef#1{\detokenize\expandafter{#2}}}
+\def\xdefconvertedargument#1#2{\xdef#1{#2}%
+ \xdef#1{\detokenize\expandafter{#1}}}
%D When you try to convert a primitive command, you'll find
%D out that the \ETEX\ method fails on for instance \type
@@ -4238,7 +3995,7 @@
%D In examples~2 and~3 both arguments equal, in~1 and~4
%D they differ.
-\long\def\ConvertToConstant#1#2#3%
+\def\ConvertToConstant#1#2#3%
{\edef\!!stringa{\expandafter\detokenize\expandafter{#2}}%
\edef\!!stringb{\expandafter\detokenize\expandafter{#3}}%
#1{\!!stringa}{\!!stringb}}
@@ -4271,7 +4028,7 @@
%D where \type{...} can be anything legally \TEX.
\def\CheckConstantAfter#1#2%
- {\@EA\convertargument\v!prefix!\to\ascii
+ {\expandafter\convertargument\v!prefix!\to\ascii
\convertargument#1\to#2\relax
\doifinstringelse\ascii{#2}
{\expandafter\convertargument#1\to#2}
@@ -4338,7 +4095,7 @@
%D results in: \type{\message{Hello world!}}.
\def\dograbuntil#1#2%
- {\long\def\next##1#1{#2{##1}}\next}
+ {\def\next##1#1{#2{##1}}\next}
\def\grabuntil#1%
{\expandafter\dograbuntil\expandafter{\csname#1\endcsname}}
@@ -4365,11 +4122,11 @@
%D is related to these commands. This one simply throws away
%D everything preceding \type{\command}.
-\long\def\processbetween#1#2%
+\def\processbetween#1#2%
{\setvalue{\s!start#1}{\grabuntil{\s!stop#1}{#2}}}
\def\gobbleuntil#1%
- {\long\def\next##1#1{}\next}
+ {\def\next##1#1{}\next}
\def\gobbleuntilrelax#1\relax
{}
@@ -4381,7 +4138,7 @@
%D \stoptyping
\def\processuntil#1%
- {\long\def\next##1#1{##1}\next}
+ {\def\next##1#1{##1}\next}
%D \macros
%D {groupedcommand}
@@ -4451,38 +4208,38 @@
%D extra \type{\bgroup}||\type{\egroup} is needed to keep
%D \type{\AfterGroup} both into sight and local.
-\long\def\HandleGroup#1#2%
+\def\HandleGroup#1#2%
{\bgroup
- \long\def\BeforeGroup{\bgroup#1\bgroup\aftergroup\AfterGroup}%
- \long\def\AfterGroup {#2\egroup\egroup}%
+ \def\BeforeGroup{\bgroup#1\bgroup\aftergroup\AfterGroup}% can't we remove the second \bgroup
+ \def\AfterGroup {#2\egroup\egroup}% % and one \egroup here?
\afterassignment\BeforeGroup
\let\next=}
-\long\def\HandleSimpleGroup#1#2% no inner group (so no kerning interference)
+\def\HandleSimpleGroup#1#2% no inner group (so no kerning interference)
{\bgroup
- %long\def\BeforeGroup{\bgroup#1\aftergroup\AfterGroup}% interferes
- \long\def\BeforeGroup{\bgroup\aftergroup\AfterGroup#1}%
- \long\def\AfterGroup {#2\egroup}%
+ %def\BeforeGroup{\bgroup#1\aftergroup\AfterGroup}% interferes
+ \def\BeforeGroup{\bgroup\aftergroup\AfterGroup#1}%
+ \def\AfterGroup {#2\egroup}%
\afterassignment\BeforeGroup
\let\next=}
-% \long\def\HandleNoGroup#1#2%
-% {\long\def\AfterGroup{#2\egroup}%
+% \def\HandleNoGroup#1#2%
+% {\def\AfterGroup{#2\egroup}%
% \bgroup\aftergroup\AfterGroup#1}
\def\HandleNoGroup % retrofit into mkii
- {\ifnum\currentgrouptype=\@@semisimplegroup
+ {\ifnum\currentgrouptype=\semisimplegroupcode
\expandafter\HandleNoGroupA
\else
\expandafter\HandleNoGroupB
\fi}
-\long\def\HandleNoGroupA#1#2%
- {\long\def\AfterGroup{#2\endgroup}%
+\def\HandleNoGroupA#1#2%
+ {\def\AfterGroup{#2\endgroup}%
\begingroup\aftergroup\AfterGroup#1}
-\long\def\HandleNoGroupB#1#2%
- {\long\def\AfterGroup{#2\egroup}%
+\def\HandleNoGroupB#1#2%
+ {\def\AfterGroup{#2\egroup}%
\bgroup\aftergroup\AfterGroup#1}
%D I considered it a nuisance that
@@ -4497,10 +4254,10 @@
%D line||ending token is treated as a blank space. So the final
%D implementation became:
-\long\unexpanded\def\groupedcommand#1#2%
+\unexpanded\def\groupedcommand#1#2%
{\doifnextbgroupelse{\HandleGroup{#1}{#2}}{\HandleNoGroup{#1}{#2}}}
-\long\unexpanded\def\simplegroupedcommand#1#2%
+\unexpanded\def\simplegroupedcommand#1#2%
{\doifnextbgroupelse{\HandleSimpleGroup{#1}{#2}}{\HandleNoGroup{#1}{#2}}}
%D Users should be aware of the fact that grouping can
@@ -4608,7 +4365,7 @@
{\def\dodogotopar{#1}%
\redogotopar\par}
-\def\GetPar
+\unexpanded\def\GetPar
{\expanded
{\dowithpar
{\the\BeforePar
@@ -4617,7 +4374,7 @@
\BeforePar\emptytoks
\AfterPar\emptytoks}}}
-\def\GotoPar
+\unexpanded\def\GotoPar
{\expanded
{\dogotopar
{\the\BeforePar
@@ -4656,7 +4413,7 @@
%D ... \par
%D \stoptyping
-\def\dowithpargument#1%
+\unexpanded\def\dowithpargument#1%
{\def\nextpar##1 \par{#1{##1}}%
\def\nextarg##1{#1{##1}}%
\doifnextbgroupelse\nextarg{\doifnextcharelse\par{#1{}}\nextpar}}
@@ -4683,7 +4440,7 @@
%D ...
%D \stoptyping
-\def\dowithwargument#1%
+\unexpanded\def\dowithwargument#1%
{\def\nextwar##1 {#1{##1}}%
\def\nextarg##1{#1{##1}}%
\doifnextbgroupelse\nextarg\nextwar}
@@ -4718,17 +4475,18 @@
%D a row. In both commands, the \type{n*} is optional. When this
%D specification is missing, the command executes once.
-\def\dorepeatwithcommand[#1]%
+\unexpanded\def\dorepeatwithcommand[#1]%
{\dodorepeatwithcommand#1*\empty*\relax}
-\long\def\dodorepeatwithcommand#1*#2#3*#4\relax#5%
+\def\dodorepeatwithcommand#1*#2#3*#4\relax#5%
{\ifx#2\empty\redorepeatwithcommand[#1]#5\else\dododorepeatwithcommand{#1}{#2}{#3}#5\fi}
-\long\def\dododorepeatwithcommand#1#2#3#4%
+\def\dododorepeatwithcommand#1#2#3#4%
{\ifx#2\empty % redundant but gives cleaner extensions
#4{#1}%
\else\ifnum#1<\zerocount
- \normalexpanded{\dorecurse{\number-\number#1}}{#4{-#2#3}}%
+ %\normalexpanded{\dorecurse{\number-\number#1}}{#4{-#2#3}}%
+ \dorecurse{-#1}{#4{-#2#3}}%
\else\ifx#2+%
\dorecurse{#1}{#4{#3}}%
\else
@@ -4748,7 +4506,7 @@
%D \gdef\redorepeatwithcommand[#1]%
%D {\redodorepeatwithcommand#1*\empty*\relax}
%D
-%D \long\gdef\redodorepeatwithcommand#1*#2#3*#4\relax#5%
+%D \gdef\redodorepeatwithcommand#1*#2#3*#4\relax#5%
%D {\dododorepeatwithcommand{#1}{#2}{#3}#5}
%D
%D \egroup
@@ -4771,11 +4529,11 @@
%D are macros. This save some unneeded expansion.
%D
%D \starttyping
-%D \long\def\doifstringinstringelse#1#2%
-%D {\p!doifinstringelse#1#2%
-%D \@EA\firstoftwoarguments
+%D \def\doifstringinstringelse#1#2%
+%D {\syst_helpers_do_if_in_string_else#1#2%
+%D \expandafter\firstoftwoarguments
%D \else
-%D \@EA\secondoftwoarguments
+%D \expandafter\secondoftwoarguments
%D \fi}
%D \stoptyping
%D
@@ -4783,15 +4541,15 @@
\def\pp!doifstringinstringelse#1%
{\if#1@%
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\else
- \@EA\firstoftwoarguments
+ \expandafter\firstoftwoarguments
\fi}
-\long\def\doifstringinstringelse#1#2%
- {\long\@EA\def\@EA\p!doifstringinstringelse\@EA##\@EA1#1##2##3\war
+\def\doifstringinstringelse#1#2%
+ {\expandafter\def\expandafter\p!doifstringinstringelse\expandafter##\expandafter1#1##2##3\war
{\pp!doifstringinstringelse##2}%
- \@EA\@EA\@EA\p!doifstringinstringelse\@EA#2#1@@\war}
+ \expandafter\expandafter\expandafter\p!doifstringinstringelse\expandafter#2#1@@\war}
%D \macros
%D {appendtoks,prependtoks,appendtoksonce,prependtoksonce,
@@ -4808,44 +4566,43 @@
%D \dotoks\tokenlist
%D \stoptyping
%D
-%D Er worden eerst enkele klad||registers gedefinieerd. These
-%D macros are clones of the ones implemented in page~378 of
+%D These macros are clones of the ones implemented in page~378 of
%D Knuth's \TeX book.
\newtoks\@@scratchtoks
-\def\appendtoks {\doappendtoks \relax}
-\def\prependtoks {\doprependtoks \relax}
-\def\appendtoksonce {\doappendtoksonce \relax}
-\def\prependtoksonce{\doprependtoksonce\relax}
+\unexpanded\def\appendtoks {\doappendtoks \relax}
+\unexpanded\def\prependtoks {\doprependtoks \relax}
+\unexpanded\def\appendtoksonce {\doappendtoksonce \relax}
+\unexpanded\def\prependtoksonce{\doprependtoksonce\relax}
\def\dodoappendtoks
- {\dodoglobal\@@toks\@EAEAEA{\@EA\the\@EA\@@toks\the\@@scratchtoks}}
+ {\dodoglobal\@@toks\doubleexpandafter{\expandafter\the\expandafter\@@toks\the\@@scratchtoks}}
\def\dodoprependtoks
- {\dodoglobal\@@toks\@EAEAEA{\@EA\the\@EA\@@scratchtoks\the\@@toks}}
+ {\dodoglobal\@@toks\doubleexpandafter{\expandafter\the\expandafter\@@scratchtoks\the\@@toks}}
-\long\def\doappendtoks#1\to#2%
+\def\doappendtoks#1\to#2%
{\def\@@toks{#2}%
- \@@scratchtoks\@EA{\gobbleoneargument#1}\dodoappendtoks}
+ \@@scratchtoks\expandafter{\gobbleoneargument#1}\dodoappendtoks}
-\long\def\doprependtoks#1\to#2%
+\def\doprependtoks#1\to#2%
{\def\@@toks{#2}%
- \@@scratchtoks\@EA{\gobbleoneargument#1}\dodoprependtoks}
+ \@@scratchtoks\expandafter{\gobbleoneargument#1}\dodoprependtoks}
-\long\def\doappendtoksonce#1\to#2%
+\def\doappendtoksonce#1\to#2%
{\def\@@toks{#2}%
- \@@scratchtoks\@EA{\gobbleoneargument#1}%
+ \@@scratchtoks\expandafter{\gobbleoneargument#1}%
\doifintokselse\@@scratchtoks\@@toks\donothing\dodoappendtoks}
-\long\def\doprependtoksonce#1\to#2%
+\def\doprependtoksonce#1\to#2%
{\def\@@toks{#2}%
- \@@scratchtoks\@EA{\gobbleoneargument#1}%
+ \@@scratchtoks\expandafter{\gobbleoneargument#1}%
\doifintokselse\@@scratchtoks\@@toks\donothing\dodoprependtoks}
%D The test macro:
-\def\doifintokselse#1#2% #1 en #2 zijn toks
+\unexpanded\def\doifintokselse#1#2% #1 en #2 zijn toks
{\edef\asciia{\detokenize\expandafter{\the#1}}%
\edef\asciib{\detokenize\expandafter{\the#2}}%
\doifstringinstringelse\asciia\asciib}
@@ -4858,7 +4615,7 @@
% {\scratchtoks{xaa} \removetoks x\from\scratchtoks [\the\scratchtoks]}
% {\scratchtoks{a\relax b} \removetoks \relax\from\scratchtoks [\showthe\scratchtoks]}
-\def\removetoks#1\from#2%
+\unexpanded\def\removetoks#1\from#2%
{\def\doremovetoks##1#1##2\empty\empty\empty##3\\%
{\def\!!stringa{##3}%
\ifx\!!stringa\empty#2{##1}\else#2{##1##2}\fi}%
@@ -4866,8 +4623,8 @@
%D Also:
-\def\appendetoks #1\to{\normalexpanded{\noexpand\appendtoks #1}\to}
-\def\prependetoks#1\to{\normalexpanded{\noexpand\prependtoks#1}\to}
+\unexpanded\def\appendetoks #1\to{\normalexpanded{\noexpand\appendtoks #1}\to}
+\unexpanded\def\prependetoks#1\to{\normalexpanded{\noexpand\prependtoks#1}\to}
%D Hm.
@@ -4880,45 +4637,48 @@
\let\dotoks\the
-%D \macros
-%D {makecounter,pluscounter,minuscounter,
-%D resetcounter,setcounter,countervalue}
-%D
-%D Declaring, setting and resetting \COUNTERS\ can be done
-%D with the next set of commands.
-%D
-%D \starttyping
-%D \makecounter {name}
-%D \pluscounter {name}
-%D \minuscounter {name}
-%D \resetcounter {name}
-%D \setcounter {name} {value}
-%D \countervalue {name}
-%D \stoptyping
-
-\def\makecounter#1%
- {\global\@EA\let\csname#1\endcsname\zerocountervalue} % see earlier
-
-\def\countervalue#1%
- {\ifcsname#1\endcsname\csname#1\endcsname\fi}
-
-\def\pluscounter#1%
- {\@EA\xdef\csname#1\endcsname{\the\numexpr\csname#1\endcsname+\plusone\relax}}
-
-\def\minuscounter#1%
- {\@EA\xdef\csname#1\endcsname{\the\numexpr\csname#1\endcsname-\plusone\relax}}
-
-\def\resetcounter#1%
- {\global\@EA\let\csname#1\endcsname\zerocountervalue}
-
-\def\setcounter#1#2%
- {\@EA\xdef\csname#1\endcsname{\the\numexpr#2\relax}}
-
-\def\savecounter#1%
- {\@EA\xdef\csname ! #1 !\endcsname{\the\numexpr\csname#1\endcsname\relax}}
-
-\def\restorecounter#1%
- {\@EA\xdef\csname#1\endcsname{\the\numexpr\csname ! #1 !\endcsname\relax}}
+% The following code is obsolete (and names are reused for the more
+% advanced counter mechanism and those macros are not compatible!
+%
+% %D \macros
+% %D {makecounter,pluscounter,minuscounter,
+% %D resetcounter,setcounter,countervalue}
+% %D
+% %D Declaring, setting and resetting \COUNTERS\ can be done
+% %D with the next set of commands.
+% %D
+% %D \starttyping
+% %D \makecounter {name}
+% %D \pluscounter {name}
+% %D \minuscounter {name}
+% %D \resetcounter {name}
+% %D \setcounter {name} {value}
+% %D \countervalue {name}
+% %D \stoptyping
+%
+% \def\makecounter#1%
+% {\global\expandafter\let\csname#1\endcsname\zerocountervalue} % see earlier
+%
+% \def\countervalue#1%
+% {\ifcsname#1\endcsname\csname#1\endcsname\fi}
+%
+% \def\pluscounter#1%
+% {\expandafter\xdef\csname#1\endcsname{\the\numexpr\csname#1\endcsname+\plusone\relax}}
+%
+% \def\minuscounter#1%
+% {\expandafter\xdef\csname#1\endcsname{\the\numexpr\csname#1\endcsname-\plusone\relax}}
+%
+% \def\resetcounter#1%
+% {\global\expandafter\let\csname#1\endcsname\zerocountervalue}
+%
+% \def\setcounter#1#2%
+% {\expandafter\xdef\csname#1\endcsname{\the\numexpr#2\relax}}
+%
+% \def\savecounter#1%
+% {\expandafter\xdef\csname ! #1 !\endcsname{\the\numexpr\csname#1\endcsname\relax}}
+%
+% \def\restorecounter#1%
+% {\expandafter\xdef\csname#1\endcsname{\the\numexpr\csname ! #1 !\endcsname\relax}}
%D \macros
%D {beforesplitstring,aftersplitstring}
@@ -4940,12 +4700,12 @@
\def\beforesplitstring#1\at#2\to#3%
{\def\dosplitstring##1#2##2#2##3\\%
{\def#3{##1}}%
- \@EA\dosplitstring#1#2#2\\}
+ \expandafter\dosplitstring#1#2#2\\}
\def\aftersplitstring#1\at#2\to#3%
{\def\dosplitstring##1#2##2@@@##3\\%
{\def#3{##2}}%
- \@EA\dosplitstring#1@@@#2@@@\\}
+ \expandafter\dosplitstring#1@@@#2@@@\\}
%D \macros
%D {splitstring,greedysplitstring}
@@ -4961,7 +4721,7 @@
\else
\def#4{##2}%
\fi}%
- \@EA\dosplitstring#1\empty\empty\empty#2\empty\empty\empty\\}
+ \expandafter\dosplitstring#1\empty\empty\empty#2\empty\empty\empty\\}
\def\greedysplitstring#1\at#2\to#3\and#4%
{\edef\asciib{#1}%
@@ -4988,17 +4748,17 @@
\def\beforetestandsplitstring#1\at#2\to#3%
{\def\dosplitstring##1#2##2#2##3##4\\%
{\ifx##3\empty\let#3\empty\else\def#3{##1}\fi}%
- \@EA\dosplitstring#1#2#2\empty\\}
+ \expandafter\dosplitstring#1#2#2\empty\\}
\def\aftertestandsplitstring#1\at#2\to#3%
{\def\dosplitstring ##1#2##2@@@##3##4\\%
{\ifx##3\empty\let#3\empty\else\def#3{##2}\fi}%
- \@EA\dosplitstring #1@@@#2@@@\empty\\}
+ \expandafter\dosplitstring #1@@@#2@@@\empty\\}
\def\testandsplitstring#1\at#2\to#3\and#4%
{\def\dosplitstring##1#2##2#2##3##4\\%
{\ifx##3\empty\let#3\empty\let#4\empty\else\def#3{##1}\def#4{##2}\fi}%
- \@EA\dosplitstring#1#2#2\empty\\}
+ \expandafter\dosplitstring#1#2#2\empty\\}
%D \macros
%D {removesubstring}
@@ -5073,30 +4833,30 @@
%D
%D The faster alternatives are:
-\def\appendtocommalist#1#2%
+\unexpanded\def\appendtocommalist#1#2%
{\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}
-\def\prependtocommalist#1#2%
+\unexpanded\def\prependtocommalist#1#2%
{\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}
-\def\addtocommalist#1#2% {item} \cs
+\unexpanded\def\addtocommalist#1#2% {item} \cs
{\rawdoifinsetelse{#1}#2\resetglobal
{\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}}
-\def\pretocommalist#1#2% {item} \cs
+\unexpanded\def\pretocommalist#1#2% {item} \cs
{\rawdoifinsetelse{#1}#2\resetglobal
{\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}
-\def\robustdoifinsetelse#1#2%
+\unexpanded\def\robustdoifinsetelse#1#2%
{\edef\!!stringa{\detokenize\expandafter{\normalexpanded{#1}}}%
\edef\!!stringb{\detokenize\expandafter{\normalexpanded{#2}}}%
\rawdoifinsetelse\!!stringa\!!stringb}
-\def\robustaddtocommalist#1#2% {item} \cs
+\unexpanded\def\robustaddtocommalist#1#2% {item} \cs
{\robustdoifinsetelse{#1}#2\resetglobal
{\dodoglobal\edef#2{\ifx#2\empty\else#2,\fi#1}}}
-\def\robustpretocommalist#1#2% {item} \cs
+\unexpanded\def\robustpretocommalist#1#2% {item} \cs
{\robustdoifinsetelse{#1}#2\resetglobal
{\dodoglobal\edef#2{#1\ifx#2\empty\else,#2\fi}}}
@@ -5104,13 +4864,13 @@
{\def\dosplitstring##1,#2,##2,#2,##3\\%
{\edef\!!stringa{\bcleanedupcommalist##1\empty\empty\relax}%
\edef\!!stringb{\acleanedupcommalist##2,,\relax}}%
- \@EA\dosplitstring\@EA,#1,,#2,,#2,\\}
+ \expandafter\dosplitstring\expandafter,#1,,#2,,#2,\\}
\def\bcleanedupcommalist#1#2#3\relax{\if#1,\else#1\fi\if#2,\else#2\fi#3}
\def\bcleanedupcommalist#1#2\relax{\if#1,\else#1\fi#2}
\def\acleanedupcommalist#1,,#2\relax{#1}
-\def\removefromcommalist#1#2% to be sped up
+\unexpanded\def\removefromcommalist#1#2% to be sped up
{\rawdoifinsetelse{#1}#2%
{\normalexpanded{\noexpand\xsplitstring\noexpand#2{#1}}%
\dodoglobal\edef#2%
@@ -5121,6 +4881,12 @@
\fi}}
\resetglobal}
+% \unexpanded\def\addtocommalist#1#2% upto 3 times slower
+% {\dodoglobal\edef#2{\ctxcommand{addtocommalist(\!!bs#1\!!es,\!!bs#2\!!es)}}}
+%
+% \unexpanded\def\removefromcommalist#1#2% faster and more robust
+% {\dodoglobal\edef#2{\ctxcommand{addtocommalist(\!!bs#1\!!es,\!!bs#2\!!es)}}}
+
%D \macros
%D {substituteincommalist}
%D
@@ -5146,7 +4912,7 @@
\else
\edef#3{#3\ifx#3\empty\else,\fi##1}%
\fi}%
- \@EA\rawprocesscommacommand\@EA[\!!stringa]\dosubstituteincommalist}
+ \expandafter\rawprocesscommacommand\expandafter[\!!stringa]\dosubstituteincommalist}
%D A not so useful macro:
@@ -5160,7 +4926,7 @@
\def\dofrontstrip#1%
{\edef\!!stringa{#1}%
\ifx\!!stringa\empty \else
- \@EA\dodofrontstrip\@EA[#1]#1%
+ \expandafter\dodofrontstrip\expandafter[#1]#1%
\fi}
%D \macros
@@ -5194,8 +4960,9 @@
\ifx\newcommalist\empty
\let\newcommalist\newcommalistelement
\else
- \@EA\@EA\@EA\def\@EA\@EA\@EA\newcommalist\@EA\@EA\@EA
- {\@EA\newcommalist\@EA,\newcommalistelement}%
+ \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter
+ \newcommalist\expandafter\expandafter\expandafter
+ {\expandafter\newcommalist\expandafter,\newcommalistelement}%
\fi
\fi
\def\commalistelement{##1}%
@@ -5208,9 +4975,9 @@
\fi
\else
\ifx\nexttoken\bgroup % is known -)
- \@EA\def\@EA\newcommalist\@EA{\newcommalist,{##1}}%
+ \expandafter\def\expandafter\newcommalist\expandafter{\newcommalist,{##1}}%
\else
- \@EA\def\@EA\newcommalist\@EA{\newcommalist,##1}%
+ \expandafter\def\expandafter\newcommalist\expandafter{\newcommalist,##1}%
\fi
\fi
\fi
@@ -5218,7 +4985,7 @@
\let\commalistelement\empty
\let\newcommalist\empty
\commalistcounter\plusone
- \@EA\processcommalist\@EA[#1]\doreplaceincommalist
+ \expandafter\processcommalist\expandafter[#1]\doreplaceincommalist
\dodoglobal\let#1\newcommalist}
%D \macros
@@ -5285,16 +5052,23 @@
\def\numberofpoints #1{\the\numexpr\dimexpr#1\relax/\maxcard\relax}
%D \macros
-%D {swapdimens,swapcounts,swapmacros}
+%D {swapdimens,swapcounts,swapmacros,
+%D globalswapdimens,globalswapcounts,globalswapmacros}
%D
%D Simple but effective are the next two macros. There name
-%D exactly states their purpose. The \type{\scratchdimen} and
-%D \type{\!!stringa} can only be swapped when being the first
-%D argument.
+%D exactly states their purpose.
+
+\newdimen\d_syst_helpers_swapped
+\newcount\c_syst_helpers_swapped
+\let \m_syst_helpers_swapped\relax
-\def\swapdimens#1#2{\scratchdimen #1\redoglobal #1#2\dodoglobal #2\scratchdimen}
-\def\swapcounts#1#2{\scratchcounter#1\redoglobal #1#2\dodoglobal #2\scratchcounter}
-\def\swapmacros#1#2{\let\!!stringa #1\redoglobal\let#1#2\dodoglobal\let#2\!!stringa}
+\unexpanded\def\swapdimens#1#2{\d_syst_helpers_swapped #1\relax#1#2\relax#2\d_syst_helpers_swapped}
+\unexpanded\def\swapcounts#1#2{\c_syst_helpers_swapped #1\relax#1#2\relax#2\c_syst_helpers_swapped}
+\unexpanded\def\swapmacros#1#2{\let\m_syst_helpers_swapped#1\let #1#2\let #2\m_syst_helpers_swapped}
+
+\unexpanded\def\globalswapdimens#1#2{\d_syst_helpers_swapped #1\global #1#2\global #2\d_syst_helpers_swapped}
+\unexpanded\def\globalswapcounts#1#2{\c_syst_helpers_swapped #1\global #1#2\global #2\c_syst_helpers_swapped}
+\unexpanded\def\globalswapmacros#1#2{\let\m_syst_helpers_swapped#1\global\let#1#2\global\let#2\m_syst_helpers_swapped}
%D \macros
%D {pushmacro,popmacro}
@@ -5316,27 +5090,27 @@
\def\globalpushmacro#1%
{\xdef\@@pushedmacro{\string#1}%
\ifcsname\@sg@\@@pushedmacro\endcsname \else
- \@EA\newcount\csname\@sg@\@@pushedmacro\endcsname
+ \expandafter\newcount\csname\@sg@\@@pushedmacro\endcsname
\fi
\global\advance\csname\@sg@\@@pushedmacro\endcsname \plusone
- \global\@EA\let\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}
+ \global\expandafter\let\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}
\def\globalpopmacro#1%
{\xdef\@@pushedmacro{\string#1}%
- \global\@EA\let\@EA#1\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
+ \global\expandafter\let\expandafter#1\csname\the\csname\@sg@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
\global\advance\csname\@sg@\@@pushedmacro\endcsname \minusone}
\def\localpushmacro#1% this one can be used to push a value over an \egroup
{\xdef\@@pushedmacro{\string#1}%
\ifcsname\@sl@\@@pushedmacro\endcsname \else
- \@EA\newcount\csname\@sl@\@@pushedmacro\endcsname
+ \expandafter\newcount\csname\@sl@\@@pushedmacro\endcsname
\fi
\global\advance\csname\@sl@\@@pushedmacro\endcsname \plusone
- \global\@EA\let\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}
+ \global\expandafter\let\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname#1}
\def\localpopmacro#1%
{\xdef\@@pushedmacro{\string#1}%
- \@EA\let\@EA#1\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
+ \expandafter\let\expandafter#1\csname\the\csname\@sl@\@@pushedmacro\endcsname\@@pushedmacro\endcsname
\global\advance\csname\@sl@\@@pushedmacro\endcsname \minusone }
\let\pushmacro\localpushmacro
@@ -5359,21 +5133,48 @@
%D These examples show us that an optional can be used. The
%D value provided is added to \type{\localhsize}.
-\newdimen\localhsize
+% todo: a fast non argument variant
-\def\complexsetlocalhsize[#1]% don't change !
- {\localhsize\hsize
- \ifnum\hangafter<\zerocount
- \advance\localhsize\ifdim\hangindent>\zeropoint-\fi\hangindent
- \fi
- \advance\localhsize -\leftskip
- \advance\localhsize -\rightskip
- \advance\localhsize #1\relax}
+\newdimen\localhsize
-\def\simplesetlocalhsize
- {\complexsetlocalhsize[\zeropoint]}
+% \def\complexsetlocalhsize[#1]% don't change !
+% {\localhsize\hsize
+% \ifnum\hangafter<\zerocount
+% \advance\localhsize\ifdim\hangindent>\zeropoint-\fi\hangindent
+% \fi
+% \advance\localhsize -\leftskip
+% \advance\localhsize -\rightskip
+% \advance\localhsize #1\relax}
+%
+% \def\simplesetlocalhsize
+% {\complexsetlocalhsize[\zeropoint]}
+%
+% \definecomplexorsimple\setlocalhsize
+
+\unexpanded\def\setlocalhsize % don't change !
+ {\doifnextoptionalelse
+ \syst_helpers_set_local_hsize_yes
+ \syst_helpers_set_local_hsize_nop}
+
+% \def\syst_helpers_set_local_hsize_nop
+% {\localhsize\hsize
+% \ifnum\hangafter<\zerocount
+% \advance\localhsize\ifdim\hangindent>\zeropoint-\fi\hangindent
+% \fi
+% \advance\localhsize -\leftskip
+% \advance\localhsize -\rightskip}
+
+\def\syst_helpers_set_local_hsize_nop
+ {\localhsize\dimexpr
+ \hsize -\leftskip -\rightskip
+ \ifnum\hangafter<\zerocount
+ \ifdim\hangindent>\zeropoint-\else+\fi\hangindent
+ \fi
+ \relax}
-\definecomplexorsimple\setlocalhsize
+\def\syst_helpers_set_local_hsize_yes[#1]%
+ {\syst_helpers_set_local_hsize_nop
+ \advance\localhsize#1\relax}
%D \macros
%D {doifvalue,doifnotvalue,doifelsevalue,
@@ -5386,40 +5187,7 @@
%D tokens per call. Anyone familiar with the not||values
%D ones, can derive their meaning from the definitions.
- \def\doifvalue#1{\doif {\csname#1\endcsname}}
- \def\doifnotvalue#1{\doifnot {\csname#1\endcsname}}
- \def\doifelsevalue#1{\doifelse{\csname#1\endcsname}}
-
- \def\doifnothing#1{\doif {#1}{}}
- \def\doifsomething#1{\doifnot {#1}{}}
- \def\doifelsenothing#1{\doifelse{#1}{}}
-
- \def\doifvaluenothing#1{\doif {\csname#1\endcsname}{}}
- \def\doifvaluesomething#1{\doifnot {\csname#1\endcsname}{}}
-\def\doifelsevaluenothing#1{\doifelse{\csname#1\endcsname}{}}
-
-%D Faster but spoiling inheritance (copying parameters):
-%D
-%D \starttyping
-%D \def\doifelsevaluesomething#1#2#3%
-%D {\expandafter\ifx\csname#1\endcsname\empty#3\else#2\fi}
-%D
-%D \def\doifvaluesomething#1#2%
-%D {\expandafter\ifx\csname#1\endcsname\empty\else#2\fi}
-%D
-%D \def\doifvaluenothing#1#2%
-%D {\expandafter\ifx\csname#1\endcsname\empty#2\fi}
-%D \stoptyping
-%D
-%D Slightly more efficient:
-
- \def\doifnothing{\doif \empty}
- \def\doifsomething{\doifnot \empty}
-\def\doifelsenothing{\doifelse\empty}
-
-%D The somewhat faster alternatives are:
-
-\long\def\doifvalue#1#2%
+\def\doifvalue#1#2%
{\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
\ifx\!!stringa\!!stringb
\expandafter\firstofoneargument
@@ -5427,7 +5195,7 @@
\expandafter\gobbleoneargument
\fi}
-\long\def\doifnotvalue#1#2%
+\def\doifnotvalue#1#2%
{\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
\ifx\!!stringa\!!stringb
\expandafter\gobbleoneargument
@@ -5435,7 +5203,7 @@
\expandafter\firstofoneargument
\fi}
-\long\def\doifelsevalue#1#2%
+\def\doifelsevalue#1#2%
{\edef\!!stringa{\csname#1\endcsname}\edef\!!stringb{#2}%
\ifx\!!stringa\!!stringb
\expandafter\firstoftwoarguments
@@ -5443,7 +5211,7 @@
\expandafter\secondoftwoarguments
\fi}
-\long\def\doifnothing#1%
+\def\doifnothing#1%
{\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\firstofoneargument
@@ -5451,7 +5219,7 @@
\expandafter\gobbleoneargument
\fi}
-\long\def\doifsomething#1%
+\def\doifsomething#1%
{\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\gobbleoneargument
@@ -5459,7 +5227,7 @@
\expandafter\firstofoneargument
\fi}
-\long\def\doifelsenothing#1%
+\def\doifelsenothing#1%
{\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\firstoftwoarguments
@@ -5467,7 +5235,7 @@
\expandafter\secondoftwoarguments
\fi}
-\long\def\doifsomethingelse#1%
+\def\doifsomethingelse#1%
{\edef\!!stringa{#1}%
\ifx\!!stringa\empty
\expandafter\secondoftwoarguments
@@ -5475,7 +5243,7 @@
\expandafter\firstoftwoarguments
\fi}
-\long\def\doifvaluenothing#1%
+\def\doifvaluenothing#1%
{\edef\!!stringa{\csname#1\endcsname}%
\ifx\!!stringa\empty
\expandafter\firstofoneargument
@@ -5483,7 +5251,7 @@
\expandafter\gobbleoneargument
\fi}
-\long\def\doifvaluesomething#1%
+\def\doifvaluesomething#1%
{\edef\!!stringa{\csname#1\endcsname}%
\ifx\!!stringa\empty
\expandafter\gobbleoneargument
@@ -5491,7 +5259,7 @@
\expandafter\firstofoneargument
\fi}
-\long\def\doifelsevaluenothing#1%
+\def\doifelsevaluenothing#1%
{\edef\!!stringa{\csname#1\endcsname}%
\ifx\!!stringa\empty
\expandafter\firstoftwoarguments
@@ -5505,21 +5273,21 @@
%D Also handy:
\def\doifemptyelsevalue#1%
- {\@EA\ifx\csname#1\endcsname\empty
+ {\expandafter\ifx\csname#1\endcsname\empty
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
\def\doifemptyvalue#1%
- {\@EA\ifx\csname#1\endcsname\empty
+ {\expandafter\ifx\csname#1\endcsname\empty
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
\def\doifnotemptyvalue#1%
- {\@EA\ifx\csname#1\endcsname\empty
+ {\expandafter\ifx\csname#1\endcsname\empty
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
@@ -5532,22 +5300,17 @@
%D \type {\doifallcommonelse}, where the first two
%D arguments are sets.
-\def\@@doifallcommonelse#1#2#3#4% slow
- {\def\p!docommoncheck##1%
+\def\syst_helpers_do_if_all_common_else#1#2#3#4% slow
+ {\def\syst_helpers_do_common_check_all##1%
{\doifnotinset{##1}{#4}\donefalse
\ifdone\else\expandafter\quitcommalist\fi}%
\donetrue
- \processcommalist[#3]\p!docommoncheck
+ \processcommalist[#3]\syst_helpers_do_common_check_all
\ifdone\expandafter#1\else\expandafter#2\fi}
-\def\doifallcommonelse
- {\@@doifallcommonelse\firstoftwoarguments\secondoftwoarguments}
-
-\def\doifallcommon
- {\@@doifallcommonelse\firstofonearguments\gobbleoneargument}
-
-\def\doifnotallcommon
- {\@@doifallcommonelse\gobbleoneargument\firstofonearguments}
+\def\doifallcommonelse{\syst_helpers_do_if_all_common_else\firstoftwoarguments\secondoftwoarguments}
+\def\doifallcommon {\syst_helpers_do_if_all_common_else\firstofonearguments\gobbleoneargument }
+\def\doifnotallcommon {\syst_helpers_do_if_all_common_else\gobbleoneargument \firstofonearguments }
%D \macros
%D {DOIF,DOIFELSE,DOIFNOT}
@@ -5566,38 +5329,38 @@
%D We have to use a two||step implementation, because the
%D expansion has to take place outside \type{\uppercase}.
-\unexpanded\def\DOIF#1#2%
+\unexpanded\def\syst_helpers_do_IF#1#2%
{\uppercase{{$#1$}{$#2$}}%
\expandafter\firstofoneargument
\else
\expandafter\gobbleoneargument
\fi}
-\unexpanded\def\DOIFNOT#1#2%
+\unexpanded\def\syst_helpers_do_IF_NOT#1#2%
{\uppercase{{$#1$}{$#2$}}%
\expandafter\gobbleoneargument
\else
\expandafter\firstofoneargument
\fi}
-\unexpanded\def\DOIFELSE#1#2%
+\unexpanded\def\syst_helpers_do_IF_ELSE#1#2%
{\uppercase{{$#1$}{$#2$}}%
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\unexpanded\def\DOIFINSTRINGELSE#1#2%
+\unexpanded\def\syst_helpers_do_IF_INSTRING_ELSE#1#2%
{\uppercase{{$#1$}{$#2$}}%
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\def\DOIF #1#2{\normalexpanded{\p!DOIF {#1}{#2}}}
-\def\DOIFNOT #1#2{\normalexpanded{\p!DOIFNOT {#1}{#2}}}
-\def\DOIFELSE #1#2{\normalexpanded{\p!DOIFELSE {#1}{#2}}}
-\def\DOIFINSTRINGELSE #1#2{\normalexpanded{\p!DOIFINSTRINGELSE{#1}{#2}}}
+\unexpanded\def\DOIF #1#2{\normalexpanded{\syst_helpers_do_IF {#1}{#2}}}
+\unexpanded\def\DOIFNOT #1#2{\normalexpanded{\syst_helpers_do_IF_NOT {#1}{#2}}}
+\unexpanded\def\DOIFELSE #1#2{\normalexpanded{\syst_helpers_do_IF_ELSE {#1}{#2}}}
+\unexpanded\def\DOIFINSTRINGELSE #1#2{\normalexpanded{\syst_helpers_do_IF_INSTRING_ELSE{#1}{#2}}}
%D \macros
%D {dosingleargumentwithset,
@@ -5684,7 +5447,7 @@
\doifnotempty{##2}{\dostripcharacter##2\end}}%
\let\!!strippedstring\empty
\edef\!!stringa{#2}%
- \@EA\dostripcharacter\!!stringa#1\end
+ \expandafter\dostripcharacter\!!stringa#1\end
\dodoglobal\let#3\!!strippedstring}
\def\stripspaces\from#1\to#2% will become \unspacestring#1\from#2
@@ -5749,62 +5512,62 @@
\def\p!doifsomespaceelse#1 #2#3\war{\if\noexpand#2@}
-\long\def\doifsomespaceelse#1% % #2#3%
+\def\doifsomespaceelse#1% % #2#3%
{\p!doifsomespaceelse#1 @ @\war % #3\else#2\fi}
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
\fi}
-%D \macros
-%D {adaptdimension,balancedimensions}
-%D
-%D Again we introduce some macros that are closely related to
-%D an interface aspect of \CONTEXT. The first command can be
-%D used to adapt a \DIMENSION.
-%D
-%D \starttyping
-%D \adaptdimension {dimension} {value}
-%D \stoptyping
-%D
-%D When the value is preceed by a \type{+} or minus, the
-%D dimension is advanced accordingly, otherwise it gets the
-%D value.
-
-\def\doadaptdimension#1#2\\#3\\%
- {\if#1+%
- \dodoglobal\advance
- \else\if#1-%
- \dodoglobal\advance
- \else
- \dodoglobal
- \fi\fi
- #3 #1#2\relax}
-
-\def\adaptdimension#1#2%
- {\expandafter\doadaptdimension#2\\#1\\}
-
-%D A second command takes two \DIMENSIONS. Both are adapted,
-%D depending on the sign of the given value.
-%D maat. This time we take the value as it is, and don't look
-%D explicitly at the preceding sign.
-%D
-%D \starttyping
-%D \balancedimensions {dimension 1} {dimension 2} {value}
-%D \stoptyping
-%D
-%D When a positive value is given, the first dimension is
-%D incremented, the second ond is decremented. A negative value
-%D has the opposite result.
-
-\def\balancedimensions#1#2#3%
- {\scratchdimen#3\relax
- \redoglobal\advance#1 \scratchdimen
- \dodoglobal\advance#2 -\scratchdimen}
-
-%D Both commands can be preceded by \type{\doglobal}. Here we
-%D use \type{\redo} first, because \type{\dodo} resets the
-%D global character.
+% %D \macros
+% %D {adaptdimension,balancedimensions}
+% %D
+% %D Again we introduce some macros that are closely related to
+% %D an interface aspect of \CONTEXT. The first command can be
+% %D used to adapt a \DIMENSION.
+% %D
+% %D \starttyping
+% %D \adaptdimension {dimension} {value}
+% %D \stoptyping
+% %D
+% %D When the value is preceed by a \type{+} or minus, the
+% %D dimension is advanced accordingly, otherwise it gets the
+% %D value.
+%
+% \def\doadaptdimension#1#2\\#3\\%
+% {\if#1+%
+% \dodoglobal\advance
+% \else\if#1-%
+% \dodoglobal\advance
+% \else
+% \dodoglobal
+% \fi\fi
+% #3 #1#2\relax}
+%
+% \def\adaptdimension#1#2%
+% {\expandafter\doadaptdimension#2\\#1\\}
+%
+% %D A second command takes two \DIMENSIONS. Both are adapted,
+% %D depending on the sign of the given value.
+% %D maat. This time we take the value as it is, and don't look
+% %D explicitly at the preceding sign.
+% %D
+% %D \starttyping
+% %D \balancedimensions {dimension 1} {dimension 2} {value}
+% %D \stoptyping
+% %D
+% %D When a positive value is given, the first dimension is
+% %D incremented, the second ond is decremented. A negative value
+% %D has the opposite result.
+%
+% \def\balancedimensions#1#2#3%
+% {\scratchdimen#3\relax
+% \redoglobal\advance#1 \scratchdimen
+% \dodoglobal\advance#2 -\scratchdimen}
+%
+% %D Both commands can be preceded by \type{\doglobal}. Here we
+% %D use \type{\redo} first, because \type{\dodo} resets the
+% %D global character.
%D \macros
%D {processseparatedlist}
@@ -5850,7 +5613,7 @@
#4{##1##2}%
\fi\fi\fi
\dodoprocessseparatedlist}%
- \@EA\dodoprocessseparatedlist\gobbleoneargument#1#3]#3}
+ \expandafter\dodoprocessseparatedlist\gobbleoneargument#1#3]#3}
\def\processseparatedlist[%
{\doprocessseparatedlist\relax}
@@ -5872,7 +5635,7 @@
%D \processlist(){=>}\docommand(a=>b=>c=>d)
%D \stoptyping
-\long\def\processlist#1#2#3#4% no blank skipping !
+\def\processlist#1#2#3#4% no blank skipping !
{\def\doprocesslist##1#2%
{\def\dodoprocesslist####1####2#3%
{\ifx#2####1%
@@ -5931,7 +5694,7 @@
\escapechar\minusone
\dountexsomething}
-\long\def\dountexsomething#1#2\to#3%
+\def\dountexsomething#1#2\to#3%
{\doglobal#1#2\to\untexedargument
\endgroup
\let#3\untexedargument}
@@ -6017,7 +5780,7 @@
\newbox\@@dlhbox
-\unexpanded \def\dontleavehmode
+\unexpanded\def\dontleavehmode
{\ifhmode\else \ifmmode\else
\setbox\@@dlhbox\hbox{\mathsurround\zeropoint\everymath\emptytoks$ $}\unhbox\@@dlhbox
\fi \fi}
@@ -6039,11 +5802,11 @@
%D
%D the first argument may be a \type{\macro}.
-\def\uppercasestring#1\to#2% first @EA redundant
- {\uppercase\@EA{\@EA\dodoglobal\@EA\edef\@EA#2\@EA{\normalexpanded{#1}}}}
+\def\uppercasestring#1\to#2%
+ {\uppercase\expandafter{\expandafter\dodoglobal\expandafter\edef\expandafter#2\expandafter{\normalexpanded{#1}}}}
-\def\lowercasestring#1\to#2% first @EA redundant
- {\lowercase\@EA{\@EA\dodoglobal\@EA\edef\@EA#2\@EA{\normalexpanded{#1}}}}
+\def\lowercasestring#1\to#2%
+ {\lowercase\expandafter{\expandafter\dodoglobal\expandafter\edef\expandafter#2\expandafter{\normalexpanded{#1}}}}
%D \macros
%D {handletokens}
@@ -6108,7 +5871,7 @@
%D Consider for instance the macro for which I originally
%D wrote this token handler.
-\long\def\splitofftokens#1\from#2\to#3% slow but hardly used
+\def\splitofftokens#1\from#2\to#3% slow but hardly used
{\ifnum#1>\zerocount
\scratchcounter#1\relax
\def\dosplitofftokens##1%
@@ -6117,8 +5880,8 @@
\edef#3{#3##1}%
\fi}%
% \let#3\empty % #3 can be #2, so:
- \@EA\let\@EA#3\@EA\empty
- \@EA\handletokens#2\with\dosplitofftokens
+ \expandafter\let\expandafter#3\expandafter\empty
+ \expandafter\handletokens#2\with\dosplitofftokens
\else
\edef#3{#2}%
\fi}
@@ -6135,11 +5898,11 @@
%D mysterious way of expanding. Look at this:
%D
%D \startbuffer[next]
-%D \def\next{a} \edef\test{\next} [\test]
-%D \let\next=b \edef\test{\test\next} [\test]
-%D \let\next=c \edef\test{\next} [\test]
-%D \let\next=d \edef\test{\test\next} [\test]
-%D \let\next=e \@EA\edef\@EA\test\@EA{\test\next} [\test]
+%D \def\next{a} \edef\test{\next} [\test]
+%D \let\next=b \edef\test{\test\next} [\test]
+%D \let\next=c \edef\test{\next} [\test]
+%D \let\next=d \edef\test{\test\next} [\test]
+%D \let\next=e \expandafter\edef\expandafter\test\expandafter{\test\next} [\test]
%D \stopbuffer
%D
%D \typebuffer[next]
@@ -6158,7 +5921,7 @@
\def\dohandletokens % \nexthandledtoken is part of interface
{\futurelet\nexthandledtoken\dodohandletokens}
-\long\def\handletokens#1\with#2%
+\def\handletokens#1\with#2%
{\gdef\dododohandletokens{#2}% permits more complex #2's
\dohandletokens#1\end}
@@ -6174,7 +5937,7 @@
\def\dodohandletokensone * %
{\dododohandletokens{ }\dohandletokens}
-\long\def\dodohandletokenstwo *#1%
+\def\dodohandletokenstwo *#1%
{\dododohandletokens{#1}\dohandletokens}
%D This macro is tested on:
@@ -6217,41 +5980,6 @@
\appendtoks \let\iftrialtypesetting\iffalse \to \everyresettrialtypesetting
%D \macros
-%D {startlocal, startglobal}
-%D
-%D The next four macros are rather self explaining:
-%D
-%D \starttyping
-%D \startlocal
-%D whatever assignments
-%D \stoplocal
-%D
-%D \startglobal
-%D whatever assignments
-%D \stopglobal
-%D \stoptyping
-%D
-%D These macros are meant for those who know the difference
-%D between local and global assignments and are aware of the
-%D possible unwanted side effect
-
-\def\dostartglobaldefs#1#2%
- {\scratchcounter\globaldefs
- \ifnum\globaldefs#1\zerocount
- \globaldefs-\globaldefs
- \fi
- \advance\globaldefs#2\plusone
- \expandafter\chardef\csname@gd@\the\globaldefs\endcsname\scratchcounter}
-
-\def\dostopglobaldefs
- {\globaldefs\ifcsname @gd@\the\globaldefs\endcsname\zerocount}
-
-\unexpanded\def\startlocal {\dostartglobaldefs>-}
-\unexpanded\def\stoplocal {\dostopglobaldefs}
-\unexpanded\def\startglobal {\dostartglobaldefs<+}
-\unexpanded\def\stopglobal {\dostopglobaldefs}
-
-%D \macros
%D {twodigitrounding}
%D
%D When using \type {\special}s or \type {\pdfliteral}s, it
@@ -6259,19 +5987,24 @@
%D macro rounds a real number to two digits. It takes one
%D argument and only works in \ETEX.
-\def\dointegerrounding #1.#2\relax {#1}
-\def\doonedigitrounding #1.#2#3\relax {\ifx#2*#1\else#1.#2\fi}
-\def\dotwodigitrounding #1.#2#3#4\relax {\ifx#2*#1\else#1.#2#3\fi}
-\def\dothreedigitrounding#1.#2#3#4#5\relax{\ifx#2*#1\else#1.#2#3#4\fi}
+% \def\dointegerrounding #1.#2\relax {#1}
+% \def\doonedigitrounding #1.#2#3\relax {\ifx#2*#1\else#1.#2\fi}
+% \def\dotwodigitrounding #1.#2#3#4\relax {\ifx#2*#1\else#1.#2#3\fi}
+% \def\dothreedigitrounding#1.#2#3#4#5\relax{\ifx#2*#1\else#1.#2#3#4\fi}
+%
+% \def\integerrounding#1%
+% {\expandafter\expandafter\expandafter\dointegerrounding \expandafter\WITHOUTPT\the\dimexpr#1\points+.5\points \relax .\relax}
+% \def\onedigitrounding#1%
+% {\expandafter\expandafter\expandafter\doonedigitrounding \expandafter\WITHOUTPT\the\dimexpr#1\points+.05\points \relax 00.*0\relax}
+% \def\twodigitrounding#1%
+% {\expandafter\expandafter\expandafter\dotwodigitrounding \expandafter\WITHOUTPT\the\dimexpr#1\points+.005\points \relax 000.*00\relax}
+% \def\threedigitrounding#1%
+% {\expandafter\expandafter\expandafter\dothreedigitrounding\expandafter\WITHOUTPT\the\dimexpr#1\points+.0005\points\relax0000.*00\relax}
-\def\integerrounding#1%
- {\@EA\@EA\@EA\dointegerrounding \@EA\WITHOUTPT\the\dimexpr#1\points+.5\points \relax .\relax}
-\def\onedigitrounding#1%
- {\@EA\@EA\@EA\doonedigitrounding \@EA\WITHOUTPT\the\dimexpr#1\points+.05\points \relax 00.*0\relax}
-\def\twodigitrounding#1%
- {\@EA\@EA\@EA\dotwodigitrounding \@EA\WITHOUTPT\the\dimexpr#1\points+.005\points \relax 000.*00\relax}
-\def\threedigitrounding#1%
- {\@EA\@EA\@EA\dothreedigitrounding\@EA\WITHOUTPT\the\dimexpr#1\points+.0005\points\relax0000.*00\relax}
+\def\integerrounding #1{\cldcontext{"\letterpercent 0.0f",#1}}
+\def\onedigitrounding #1{\cldcontext{"\letterpercent 0.1f",#1}}
+\def\twodigitrounding #1{\cldcontext{"\letterpercent 0.2f",#1}}
+\def\threedigitrounding#1{\cldcontext{"\letterpercent 0.3f",#1}}
%D \macros
%D {processcontent}
@@ -6287,12 +6020,12 @@
%D
%D This macro is first used in the tabulation macros.
-\def\processcontent#1%
- {\begingroup\@EA\doprocesscontent\csname#1\endcsname}
+\unexpanded\def\processcontent#1%
+ {\begingroup\expandafter\doprocesscontent\csname#1\endcsname}
-\def\doprocesscontent#1#2#3%
- {\long\def\doprocesscontent##1#1%
- {\endgroup\long\def#2{##1}#3}%
+\unexpanded\def\doprocesscontent#1#2#3%
+ {\unexpanded\def\doprocesscontent##1#1%
+ {\endgroup\def#2{##1}#3}%
\doprocesscontent}
%D \macros
@@ -6343,7 +6076,7 @@
\newcount\comparedresult
\def\sortcommacommand[#1]%
- {\@EA\sortcommalist\@EA[#1]}
+ {\expandafter\sortcommalist\expandafter[#1]}
\def\sortcommalist[#1]#2%
{\getcommalistsize[#1]%
@@ -6362,8 +6095,8 @@
\def\!!tempa{#1}%
\ifx\!!tempa\empty\else
\scratchcounter\plusone
- \@EA\getcommalistsize\@EA[\sortedcommalist]%
- \@EA\processcommalist\@EA[\sortedcommalist]\docompareitems
+ \expandafter\getcommalistsize\expandafter[\sortedcommalist]%
+ \expandafter\processcommalist\expandafter[\sortedcommalist]\docompareitems
\fi
\fi}
@@ -6372,20 +6105,22 @@
\def\docompareitems#1%
{\doifnotempty{#1}
- {\@EA\comparecommand\@EA{\!!tempa}{#1}\relax
+ {\expandafter\comparecommand\expandafter{\!!tempa}{#1}\relax
%\ifcase\compareresult % equal
\ifnum\comparedresult<2
\ifnum\scratchcounter=\commalistsize
- \@EA\@EA\@EA\def\@EA\@EA\@EA\sortedcommalist
- \@EA\@EA\@EA{\@EA\sortedcommalist\@EA,\!!tempa}%
+ \expandafter\expandafter\expandafter\def
+ \expandafter\expandafter\expandafter\sortedcommalist
+ \expandafter\expandafter\expandafter{\expandafter\sortedcommalist\expandafter,\!!tempa}%
\fi
%\or % new element larger
% \ifnum\scratchcounter=\commalistsize
- % \@EA\@EA\@EA\def\@EA\@EA\@EA\sortedcommalist
- % \@EA\@EA\@EA{\@EA\sortedcommalist\@EA,\!!tempa}%
+ % \expandafter\expandafter\expandafter\def
+ % \expandafter\expandafter\expandafter\sortedcommalist
+ % \expandafter\expandafter\expandafter{\expandafter\sortedcommalist\expandafter,\!!tempa}%
% \fi
\else % old element larger
- \@EA\def\@EA\newcommalistelement\@EA{\!!tempa,#1}%
+ \expandafter\def\expandafter\newcommalistelement\expandafter{\!!tempa,#1}%
\replaceincommalist\sortedcommalist\scratchcounter
\expandafter\quitcommalist
\fi}%
@@ -6412,8 +6147,8 @@
\def\@True {00}
\def\@False {01}
-\def\@Not #1{0\ifcase#11 \or\@EA 1\else \@EA 0\fi}
-\def\@And #1#2{0\ifcase#1#2 \@EA 0\else \@EA 1\fi}
+\def\@Not #1{0\ifcase#11 \or\expandafter 1\else \expandafter 0\fi}
+\def\@And #1#2{0\ifcase#1#2 \expandafter 0\else \expandafter 1\fi}
%D \macros
%D {setdimensionwithunit, freezedimensionwithunit}
@@ -6439,27 +6174,43 @@
{\setdimensionwithunit\scratchdimen#1{#2}\edef#1{\the\scratchdimen}}
%D \macros
-%D {doifsometokselse}
+%D {doifsometokselse, doifsometoks}
%D
%D Not that fast I guess, but here's a way to test for token
%D registers being empty.
-\def\doifsometokselse#1% % #2#3%
- {\edef\!!stringa{\the#1}%
- \ifx\!!stringa\empty % #3\else#2\fi}
+\def\doifsometokselse#1%
+ {\edef\!!stringa{\the#1}% one level expansion so quite ok
+ \ifx\!!stringa\empty
\expandafter\secondoftwoarguments
\else
\expandafter\firstoftwoarguments
\fi}
+\def\doifsometoks#1%
+ {\edef\!!stringa{\the#1}% one level expansion so quite ok
+ \ifx\!!stringa\empty
+ \expandafter\gobbleoneargument
+ \else
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\doifemptytoks#1%
+ {\edef\!!stringa{\the#1}% one level expansion so quite ok
+ \ifx\!!stringa\empty
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\gobbleoneargument
+ \fi}
+
%D \macros
%D {startstrictinspectnextcharacter}
%D
%D This one if for Taco's bibliography module:
-\let\normalinspectnextcharacter\inspectnextcharacter
+\let\syst_helpers_normal_inspect_next_character\syst_helpers_inspect_next_character
-\def\strictinspectnextcharacter% no user macro !
+\def\syst_helpers_strict_inspect_next_character% no user macro !
{\ifx\nexttoken\charactertoken
\expandafter\!!stringa
\else
@@ -6469,10 +6220,10 @@
% better: push/pop
\unexpanded\def\startstrictinspectnextcharacter
- {\let\inspectnextcharacter\strictinspectnextcharacter}
+ {\let\syst_helpers_inspect_next_character\syst_helpers_strict_inspect_next_character}
\unexpanded\def\stopstrictinspectnextcharacter
- {\let\inspectnextcharacter\normalinspectnextcharacter}
+ {\let\syst_helpers_inspect_next_character\syst_helpers_normal_inspect_next_character}
\def\strictdoifnextoptionalelse#1#2%
{\startstrictinspectnextcharacter
@@ -6500,16 +6251,16 @@
%D These are needed in ordinal number conversions:
\def\lastdigit#1%
- {\@EA\thelastdigit\number#1\relax}
+ {\expandafter\thelastdigit\number#1\relax}
\def\thelastdigit#1#2%
- {\ifx#2\relax#1\else\@EA\thelastdigit\@EA#2\fi}
+ {\ifx#2\relax#1\else\expandafter\thelastdigit\expandafter#2\fi}
\def\lasttwodigits#1%
- {\@EA\thelasttwodigits\@EA0\number#1\relax}
+ {\expandafter\thelasttwodigits\expandafter0\number#1\relax}
\def\thelasttwodigits#1#2#3% 0 dig ... \relax
- {\ifx#3\relax#1#2\else\@EA\thelasttwodigits\@EA#2\@EA#3\fi}
+ {\ifx#3\relax#1#2\else\expandafter\thelasttwodigits\expandafter#2\expandafter#3\fi}
%D \macros
%D {serializecommalist}
@@ -6537,7 +6288,7 @@
%D macro works ok with \type {\the}, \type {\number} as well
%D as \ETEX's \type {\numexpr}.
-\def\purenumber#1{\@EA\firstofoneargument\@EA{\number#1}}
+\def\purenumber#1{\expandafter\firstofoneargument\expandafter{\number#1}}
%D \macros
%D {filterfromvalue}
@@ -6593,8 +6344,8 @@
\fi}
\def\filterfromvalue#1#2#3% value max n
- {\@EA\@EAEAEA\csname % we use the fact that an
- \@EA\ifx\csname#1\endcsname\relax % undefined cs has become \relax
+ {\expandafter\doubleexpandafter\csname % we use the fact that an
+ \expandafter\ifx\csname#1\endcsname\relax % undefined cs has become \relax
\strippedcsname\gobbleoneargument % which we then gobble here
\else
\dofilterfromstr{#2}{#3}%
@@ -6627,12 +6378,12 @@
% \setmeasure {xx} {1cm}
% \setmeasure {xxx}{1cm}
-\def\setmeasure #1#2{\expandafter\def \csname\??dm#1\endcsname{#2}} % quick way
-\def\setemeasure#1#2{\expandafter\edef\csname\??dm#1\endcsname{#2}} % quick way
-\def\setgmeasure#1#2{\expandafter\gdef\csname\??dm#1\endcsname{#2}} % quick way
-\def\setxmeasure#1#2{\expandafter\xdef\csname\??dm#1\endcsname{#2}} % quick way
+\unexpanded\def\setmeasure #1#2{\expandafter\def \csname\??dm#1\endcsname{#2}} % quick way
+\unexpanded\def\setemeasure#1#2{\expandafter\edef\csname\??dm#1\endcsname{#2}} % quick way
+\unexpanded\def\setgmeasure#1#2{\expandafter\gdef\csname\??dm#1\endcsname{#2}} % quick way
+\unexpanded\def\setxmeasure#1#2{\expandafter\xdef\csname\??dm#1\endcsname{#2}} % quick way
-\def\measure#1%
+\def\measure#1% maybe \dimexpr ... \relax
{\ifcsname\??dm#1\endcsname\csname\??dm#1\endcsname\else\zeropoint\fi}
%D \macros
@@ -6751,28 +6502,28 @@
% \copycsname xxx\endcsname\csname ..\endcsname
-\def\copycsname{\@EA\@EA\@EA\let\@EA\@EA\csname}
+\def\copycsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter\csname}
% \letcscsname \crap \csname ..\endcsname
% \letcsnamecs \csname ..\endcsname\crap
% \letcsnamecsname\csname ..\endcsname\csname ..\endcsname
-\def\letcscsname {\@EA\let\@EA}
-\def\letcsnamecs {\@EA\let}
-\def\letcsnamecsname{\@EA\@EA\@EA\let\@EA\@EA}
+\def\letcscsname {\expandafter\let\expandafter}
+\def\letcsnamecs {\expandafter\let}
+\def\letcsnamecsname{\expandafter\expandafter\expandafter\let\expandafter\expandafter}
% another one, add an item to a commalist
\def\addvalue#1#2% cs item
{\ifcsname#1\endcsname\else\expandafter\let\csname#1\endcsname\empty\fi
- \normalexpanded{\noexpand\addtocommalist{#2}\@EA\noexpand\csname#1\endcsname}}
+ \normalexpanded{\noexpand\addtocommalist{#2}\expandafter\noexpand\csname#1\endcsname}}
\def\unspaced#1%
{\dounspaced#1\end}
\def\dounspaced#1%
{\ifx#1\end
- \@EA\gobbleoneargument
+ \expandafter\gobbleoneargument
\else
\ifx#1\blankspace\else#1\fi
\fi
@@ -6796,44 +6547,44 @@
\def\dodoifhasspaceelse#1 #2#3\relax % \space\empty\relax
{\ifx\!!stringa\space
- \@EA\firstoftwoarguments
+ \expandafter\firstoftwoarguments
\else\ifx#2\empty
- \@EAEAEA\secondoftwoarguments
+ \doubleexpandafter\secondoftwoarguments
\else
- \@EAEAEA\firstoftwoarguments
+ \doubleexpandafter\firstoftwoarguments
\fi\fi}
% this will replace loadfile once and alike !!! todo
\def\@flg@{@flg@}
-\def\setflag #1{\@EA\dodoglobal\@EA\let\csname\@flg@#1\endcsname\zerocount}
-\def\resetflag#1{\@EA\dodoglobal\@EA\let\csname\@flg@#1\endcsname\plusone}
+\def\setflag #1{\expandafter\dodoglobal\expandafter\let\csname\@flg@#1\endcsname\zerocount}
+\def\resetflag#1{\expandafter\dodoglobal\expandafter\let\csname\@flg@#1\endcsname\plusone}
\let\ifflagged\ifcase
\def\flag#1{\csname\@flg@#1\endcsname}
\def\doifelseflagged#1%
- {\@EA\ifx\csname\@flg@#1\endcsname\relax
- \@EA\secondoftwoarguments
+ {\expandafter\ifx\csname\@flg@#1\endcsname\relax
+ \expandafter\secondoftwoarguments
\else\ifcase\csname\@flg@#1\endcsname
- \@EAEAEA\firstoftwoarguments
+ \doubleexpandafter\firstoftwoarguments
\else
- \@EAEAEA\secondoftwoarguments
+ \doubleexpandafter\secondoftwoarguments
\fi\fi}
\def\doifnotflagged#1%
- {\@EA\ifx\csname\@flg@#1\endcsname\relax
- \@EA\firstofoneargument
+ {\expandafter\ifx\csname\@flg@#1\endcsname\relax
+ \expandafter\firstofoneargument
\else\ifcase\csname\@flg@#1\endcsname
- \@EAEAEA\gobbleoneargument
+ \doubleexpandafter\gobbleoneargument
\else
- \@EAEAEA\firstofoneargument
+ \doubleexpandafter\firstofoneargument
\fi\fi}
-\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey % [bypasses k!prefix]
- {\@EA\def\csname#1#3\@EA\endcsname\@EA{\csname#1#5\endcsname}}
+\def\inheritparameter[#1]#2[#3]#4[#5]% tag tokey fromkey
+ {\expandafter\def\csname#1#3\expandafter\endcsname\expandafter{\csname#1#5\endcsname}}
% \buildarray[test][aa,bb,cc,dd,ee,ff]
% \setarrayelement{test}{1}{qq}
@@ -6869,14 +6620,14 @@
{\ifx#1\relax
\ifcase\scratchcounter
\endgroup
- \@EAEAEA\secondoftwoarguments
+ \doubleexpandafter\secondoftwoarguments
\else
\endgroup
- \@EAEAEA\firstoftwoarguments
+ \doubleexpandafter\firstoftwoarguments
\fi
\else
\endgroup
- \@EA\secondoftwoarguments
+ \expandafter\secondoftwoarguments
\fi}
\def\doifnonzeropositiveelse#1%
@@ -6884,10 +6635,10 @@
% here ?
-\def\dosetrawvalue #1#2#3{\@EA \def\csname#1#2\endcsname{#3}}
-\def\dosetrawevalue#1#2#3{\@EA\edef\csname#1#2\endcsname{#3}}
-\def\dosetrawgvalue#1#2#3{\@EA\gdef\csname#1#2\endcsname{#3}}
-\def\dosetrawxvalue#1#2#3{\@EA\xdef\csname#1#2\endcsname{#3}}
+\def\dosetrawvalue #1#2#3{\expandafter \def\csname#1#2\endcsname{#3}}
+\def\dosetrawevalue#1#2#3{\expandafter\edef\csname#1#2\endcsname{#3}}
+\def\dosetrawgvalue#1#2#3{\expandafter\gdef\csname#1#2\endcsname{#3}}
+\def\dosetrawxvalue#1#2#3{\expandafter\xdef\csname#1#2\endcsname{#3}}
\def\getrawparameters {\dogetparameters\dosetrawvalue }
\def\getraweparameters {\dogetparameters\dosetrawevalue}
@@ -6934,7 +6685,7 @@
\newcount\featuretest
-\def\testfeature#1#2%
+\unexpanded\def\testfeature#1#2%
{\def\dotestfeature
{\advance\featuretest \plusone
\ifnum\featuretest>#1\else#2\expandafter\dotestfeature\fi}%
@@ -6950,11 +6701,14 @@
\wait
\egroup}
-\def\showtimer#1%
+\unexpanded\def\showtimer#1%
{\writestatus{runtime}{\elapsedseconds\space s / #1}}
-\def\testfeatureonce#1#2%
- {\let\wait\relax\testfeature{#1}{#2}\end}
+\unexpanded\def\testfeatureonce#1#2%
+ {\begingroup
+ \let\wait\relax
+ \testfeature{#1}{#2}%
+ \endgroup}
%D \macros
%D {freezedimenmacro}
@@ -6984,10 +6738,10 @@
{\afterassignment\gobbleassigndimen#1=#2\!!zeropoint\\}
\def\setusage#1%
- {\@EA\let\csname#1\endcsname\iftrue}
+ {\expandafter\let\csname#1\endcsname\iftrue}
\def\resetusage#1%
- {\@EA\let\csname#1\endcsname\iffalse}
+ {\expandafter\let\csname#1\endcsname\iffalse}
\def\ifusage#1%
{\ifcsname#1\endcsname\else
@@ -7002,12 +6756,12 @@
% The following macros are used in XML handling.
-\long\setvalue{@u@s@"}#1#2"{#2} \long\setvalue{@g@s@"}#1#2"{\scratchtoks{#2}}
-\long\setvalue{@u@s@'}#1#2'{#2} \long\setvalue{@g@s@'}#1#2'{\scratchtoks{#2}}
-\long\setvalue{@u@s@ }#1#2 {#2} \long\setvalue{@g@s@ }#1#2 {\scratchtoks{#2}}
+\setvalue{@u@s@"}#1#2"{#2} \setvalue{@g@s@"}#1#2"{\scratchtoks{#2}}
+\setvalue{@u@s@'}#1#2'{#2} \setvalue{@g@s@'}#1#2'{\scratchtoks{#2}}
+\setvalue{@u@s@ }#1#2 {#2} \setvalue{@g@s@ }#1#2 {\scratchtoks{#2}}
-\long\def\unstringed#1{\csname\ifcsname @u@s@#1\endcsname @u@s@#1\else\s!empty\fi\endcsname#1}
-\long\def\grabstring#1{\csname\ifcsname @g@s@#1\endcsname @g@s@#1\else\s!empty\fi\endcsname#1}
+\def\unstringed#1{\csname\ifcsname @u@s@#1\endcsname @u@s@#1\else\s!empty\fi\endcsname#1}
+\def\grabstring#1{\csname\ifcsname @g@s@#1\endcsname @g@s@#1\else\s!empty\fi\endcsname#1}
\def\dowithgrabbedstring#1%
{\def\@@dowithgrabbedstring{#1}%
@@ -7019,31 +6773,35 @@
\def\@@ifequal#1#2\@@and#3%
{\ifx#1\relax
\ifx#3\relax
- \@EAEAEA\@@if@@equal@@true
+ \doubleexpandafter\@@if@@equal@@true
\else
- \@EAEAEA\@@if@@equal@@false
+ \doubleexpandafter\@@if@@equal@@false
\fi
\else
\ifx#3\relax
- \@EAEAEAEAEAEA\@@if@@equal@@false
+ \tripleexpandafter\@@if@@equal@@false
\else\ifx#1#3%
% go on
\else
- \@EAEAEAEAEAEA\@@if@@equal@@false
+ \tripleexpandafter\@@if@@equal@@false
\fi\fi
\fi
\@@ifequal#2\@@and}
-\long\def\@@if@@equal@@true #1\@@then#2#3{#2}
-\long\def\@@if@@equal@@false#1\@@then#2#3{#3}
+\def\@@if@@equal@@true #1\@@then#2#3{#2}
+\def\@@if@@equal@@false#1\@@then#2#3{#3}
-\def\appended#1#2#3{\@EA#1\@EA#2\@EA{#2#3}}
-\def\appendvalue #1{\@EA\appended\@EA \def\csname#1\endcsname}
-\def\appendgvalue#1{\@EA\appended\@EA\gdef\csname#1\endcsname}
+\def\appended#1#2#3{\expandafter#1\expandafter#2\expandafter{#2#3}}
+\def\appendvalue #1{\expandafter\appended\expandafter \def\csname#1\endcsname}
+\def\appendgvalue#1{\expandafter\appended\expandafter\gdef\csname#1\endcsname}
-\def\prepended#1#2#3{\scratchtoks{#3}\@EA\@EA\@EA#1\@EA\@EA\@EA#2\@EA\@EA\@EA{\@EA\the\@EA\scratchtoks#2}}
-\def\prependvalue #1{\@EA\prepended\@EA \def\csname#1\endcsname}
-\def\prependgvalue#1{\@EA\prepended\@EA\gdef\csname#1\endcsname}
+\def\prepended#1#2#3%
+ {\scratchtoks{#3}%
+ \expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter#2\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\scratchtoks#2}}
+
+\def\prependvalue #1{\expandafter\prepended\expandafter \def\csname#1\endcsname}
+\def\prependgvalue#1{\expandafter\prepended\expandafter\gdef\csname#1\endcsname}
%D \macros
%D {compresscommacommandnrs,compresscommalistnrs,compressedcommalistnrs,
@@ -7087,7 +6845,7 @@
\def\dodocompresslistnrs
{\edef\compressedlist
{\ifx\compressedlist\empty\else\compressedlist,\fi
- {\the\!!counta}{\ifnum\!!countb>\!!counta\the\!!countb\fi}}}
+ {\the\!!counta}{\ifnum\!!countb>\!!counta\the\!!countb\fi}}}
%D \def\test#1{{\tttf#1->\compresscommalistnrs[#1]\defconvertedcommand\ascii\compressedlist\ascii}}
%D \startlines
@@ -7198,9 +6956,9 @@
\def\uncompresslist[#1]% by TH
{\let\uncompressedlist\empty
\def\docompressedlistitem##1-##2-%
- {\@EA\dorecurse\@EA
+ {\expandafter\dorecurse\expandafter
{\the\numexpr1+##2-##1\relax}%
- {\@EA\appendtocommalist\@EA{\the\numexpr##1-1+####1\relax}\uncompressedlist}}%
+ {\expandafter\appendtocommalist\expandafter{\the\numexpr##1-1+####1\relax}\uncompressedlist}}%
\def\douncompresslist##1%
{\doifinstringelse{-}{##1}
{\docompressedlistitem##1-}
@@ -7302,4 +7060,117 @@
\unexpanded\def\signalcharacter{\char\zerocount} % \zwj
+%D Here are some nasty helpers:
+
+\def\constantnumber#1%
+ {\ifcase#1\zerocount
+ \or \plusone
+ \or \plustwo
+ \or \plusthree
+ \or \plusfour
+ \or \plusfive
+ \or \plussix
+ \or \plusseven
+ \or \pluseight
+ \or \plusnine
+ \or \plusten
+ \else \number#1\relax\fi}
+
+\def\constantnumberargument#1%
+ {\ifcase#1\zerocount
+ \or \plusone
+ \or \plustwo
+ \or \plusthree
+ \or \plusfour
+ \or \plusfive
+ \or \plussix
+ \or \plusseven
+ \or \pluseight
+ \or \plusnine
+ \or \plusten
+ \else {\number#1}\fi}
+
+\def\constantdimen#1%
+ {\ifdim#1=\zeropoint
+ \zeropoint
+ \else
+ \the#1\relax
+ \fi}
+
+\def\constantdimenargument#1%
+ {\ifdim#1=\zeropoint
+ \zeropoint
+ \else
+ {\the#1}%
+ \fi}
+
+\def\constantemptyargument#1%
+ {\ifx#1\empty
+ \noexpand\empty
+ \else
+ {#1}%
+ \fi}
+
+%D These can be used when constructing often reused token lists,
+%D as we do with tabulates.
+
\protect \endinput
+
+% \edef\choicetokenyes{+}
+% \edef\choicetokennop{-}
+%
+% \unexpanded\def\startchoice#1%
+% {\pushmacro\currentchoicevalue
+% \edef\currentchoicevalue{#1}%
+% \checkchoicetoken}
+%
+% \unexpanded\def\checkchoicetoken#1%
+% {\edef\choicetoken{#1}%
+% \ifx\choicetoken\choicetokenyes
+% \singleexpandafter\checkchoiceyes
+% \else\ifx\choicetoken\choicetokennop
+% \doubleexpandafter\checkchoicenop
+% \else
+% \doubleexpandafter\choicequit
+% \fi\fi}
+%
+% \def\checkchoiceyes#1%
+% {\edef\choicevalue{#1}%
+% \ifx\currentchoicevalue\choicevalue
+% \expandafter\choiceindeed
+% \else
+% \expandafter\choiceignore
+% \fi}
+%
+% \def\checkchoicenop
+% {\choiceindeed}
+%
+% \def\choiceabort#1\stopchoice
+% {\popmacro\currentchoicevalue}
+%
+% \def\choicequit
+% {\popmacro\currentchoicevalue}
+%
+% \def\choiceindeed#1#2\stopchoice
+% {\popmacro\currentchoicevalue
+% #1}
+%
+% \def\choiceignore#1%
+% {\checkchoicetoken}
+%
+% \let\stopchoice\relax
+%
+% \def\xxx{3}
+% \def\xxx{x}
+%
+% \startchoice {\xxx}
+% + {1} {
+% first
+% } + {2} {
+% second
+% } + {3} {
+% third
+% } - {
+% nothing
+% }
+% \stopchoice
diff --git a/Master/texmf-dist/tex/context/base/syst-con.lua b/Master/texmf-dist/tex/context/base/syst-con.lua
index bcc0205286e..2eaf98fd730 100644
--- a/Master/texmf-dist/tex/context/base/syst-con.lua
+++ b/Master/texmf-dist/tex/context/base/syst-con.lua
@@ -14,22 +14,28 @@ the top of <l n='luatex'/>'s char range but outside the unicode range.</p>
--ldx]]--
local tonumber = tonumber
-local char, texsprint, format = unicode.utf8.char, tex.sprint, string.format
+local utfchar = unicode.utf8.char
+local gsub, format = string.gsub, string.format
function converters.hexstringtonumber(n) tonumber(n,16) end
function converters.octstringtonumber(n) tonumber(n, 8) end
-function converters.rawcharacter (n) char(0x110000+n) end
+function converters.rawcharacter (n) utfchar(0x110000+n) end
function converters.lchexnumber (n) format("%x" ,n) end
function converters.uchexnumber (n) format("%X" ,n) end
function converters.lchexnumbers (n) format("%02x",n) end
function converters.uchexnumbers (n) format("%02X",n) end
function converters.octnumber (n) format("%03o",n) end
-function commands.hexstringtonumber(n) context(tonumber(n,16)) end
-function commands.octstringtonumber(n) context(tonumber(n, 8)) end
-function commands.rawcharacter (n) context(char(0x110000+n)) end
-function commands.lchexnumber (n) context(format("%x" ,n)) end
-function commands.uchexnumber (n) context(format("%X" ,n)) end
-function commands.lchexnumbers (n) context(format("%02x",n)) end
-function commands.uchexnumbers (n) context(format("%02X",n)) end
-function commands.octnumber (n) context(format("%03o",n)) end
+function commands.hexstringtonumber(n) context(tonumber(n,16)) end
+function commands.octstringtonumber(n) context(tonumber(n, 8)) end
+function commands.rawcharacter (n) context(utfchar(0x110000+n)) end
+function commands.lchexnumber (n) context("%x" ,n) end
+function commands.uchexnumber (n) context("%X" ,n) end
+function commands.lchexnumbers (n) context("%02x",n) end
+function commands.uchexnumbers (n) context("%02X",n) end
+function commands.octnumber (n) context("%03o",n) end
+
+function commands.format(fmt,...) -- used ?
+ fmt = gsub(fmt,"@","%%")
+ context(fmt,...)
+end
diff --git a/Master/texmf-dist/tex/context/base/syst-con.mkii b/Master/texmf-dist/tex/context/base/syst-con.mkii
index 877aad32a77..c1ad788cfe5 100644
--- a/Master/texmf-dist/tex/context/base/syst-con.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-con.mkii
@@ -5,7 +5,7 @@
%D subtitle=Conversions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-con.mkiv b/Master/texmf-dist/tex/context/base/syst-con.mkiv
index 1091be85970..6ef734c8fcf 100644
--- a/Master/texmf-dist/tex/context/base/syst-con.mkiv
+++ b/Master/texmf-dist/tex/context/base/syst-con.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Conversions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -134,18 +134,11 @@
% \let\calculatecos\gobbleoneargument
% \let\calculatetan\gobbleoneargument
-% \def\calculatedsin#1{\ctxsprint{math.sin(#1)}}
-% \def\calculatedcos#1{\ctxsprint{math.cos(#1)}}
-% \def\calculatedtan#1{\ctxsprint{math.tan(#1)}}
-
-% \def\setcalculatedsin#1#2{\edef#1{\ctxsprint{math.sind(#2)}}}
-% \def\setcalculatedcos#1#2{\edef#1{\ctxsprint{math.cosd(#2)}}}
-% \def\setcalculatedtan#1#2{\edef#1{\ctxsprint{math.tand(#2)}}}
-
-% this is actually 20% faster: some overhead in functions but less tokenization
-
\def\setcalculatedsin#1#2{\edef#1{\cldcontext{math.sind(#2)}}}
\def\setcalculatedcos#1#2{\edef#1{\cldcontext{math.cosd(#2)}}}
\def\setcalculatedtan#1#2{\edef#1{\cldcontext{math.tand(#2)}}}
+ \def\formatted#1{\ctxcommand{format(#1)}}
+\unexpanded\def\format #1{\ctxcommand{format(#1)}}
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/syst-ext.mkii b/Master/texmf-dist/tex/context/base/syst-ext.mkii
index 2357e81f1b1..39f4145f278 100644
--- a/Master/texmf-dist/tex/context/base/syst-ext.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-ext.mkii
@@ -5,7 +5,7 @@
%D subtitle=Extras,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-fnt.mkii b/Master/texmf-dist/tex/context/base/syst-fnt.mkii
index 66439c19454..5669475a634 100644
--- a/Master/texmf-dist/tex/context/base/syst-fnt.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-fnt.mkii
@@ -5,7 +5,7 @@
%D subtitle=Font Things,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-fnt.mkiv b/Master/texmf-dist/tex/context/base/syst-fnt.mkiv
index 8ba0dd2a3b5..f5c9ea34979 100644
--- a/Master/texmf-dist/tex/context/base/syst-fnt.mkiv
+++ b/Master/texmf-dist/tex/context/base/syst-fnt.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Font Things,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-gen.mkii b/Master/texmf-dist/tex/context/base/syst-gen.mkii
index 0367ba4fd76..bb0f54d11fa 100644
--- a/Master/texmf-dist/tex/context/base/syst-gen.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-gen.mkii
@@ -5,7 +5,7 @@
%D subtitle=General,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-ini.mkii b/Master/texmf-dist/tex/context/base/syst-ini.mkii
index c2c3e1947d2..9988efc10ca 100644
--- a/Master/texmf-dist/tex/context/base/syst-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Bootstrapping \TEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-ini.mkiv b/Master/texmf-dist/tex/context/base/syst-ini.mkiv
index 18388fa2100..983bedc52a7 100644
--- a/Master/texmf-dist/tex/context/base/syst-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/syst-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Bootstrapping \TEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -50,8 +50,6 @@
%.......
%catcode`\z = 11
-\chardef\activecatcode = 13 % later this will become a counter
-
\def ^^L{\par}
\def\^^M{\ } % control <return> = control <space>
\def\^^I{\ } % same for <tab>
@@ -92,8 +90,6 @@
\expandafter\end
\fi
-% todo: pdfsave pdfrestore pdfcolor... don't initialize them
-
\ifnum\texengine=\luatexengine
\directlua 0 { % this info is stored in the format
lua.name[0] = "main ctx instance"
@@ -126,14 +122,25 @@
\long\def\gobbleoneargument#1{} % will be defined later on anyway
-\mathchardef\etexversion =
- \numexpr\eTeXversion*100+\expandafter\gobbleoneargument\eTeXrevision\relax
+\mathchardef\etexversion = \numexpr\eTeXversion*100+\expandafter\gobbleoneargument\eTeXrevision\relax
%D First we define a simplified version of the \CONTEXT\
-%D protection mechanism.
-
-\def\unprotect{\catcode`@=11 }
-\def\protect {\catcode`@=12 }
+%D protection mechanism. Later we will implement a better
+%D variant.
+
+\def\unprotect
+ {\edef\protect
+ {\catcode`@=\the\catcode`@\relax
+ \catcode`?=\the\catcode`?\relax
+ \catcode`!=\the\catcode`!\relax
+ \catcode`_=\the\catcode`_\relax
+ \let\protect\relax}%
+ \catcode`@=11
+ \catcode`?=11
+ \catcode`!=11
+ \catcode`_=11 }
+
+\let\protect\relax
\unprotect
@@ -163,52 +170,47 @@
% 255 : page
% 256 - : user
-\countdef \minallocatedregister = 52 \minallocatedregister = 256 % can change
-\countdef \maxallocatedregister = 53 \maxallocatedregister = 32767
-\countdef \minallocatediochannel = 54 \minallocatediochannel = -1
-\countdef \maxallocatediochannel = 55 \maxallocatediochannel = 16
-\countdef \minallocatedlanguage = 56 \minallocatedlanguage = 0
-\countdef \maxallocatedlanguage = 57 \maxallocatedlanguage = 255
-\countdef \maxallocatedinsert = 58 \maxallocatedinsert = 254
-\countdef \minallocatedinsert = 59 \minallocatedinsert = 128
-\countdef \minallocatedfamily = 60 \minallocatedfamily = 128
-\countdef \maxallocatedfamily = 61 \maxallocatedfamily = 255
-\countdef \minallocatedattribute = 62 \minallocatedattribute = 1024 % 127-1023 : private
-
-\countdef \lastallocatedcount = 32 \lastallocatedcount = \minallocatedregister
-\countdef \lastallocateddimen = 33 \lastallocateddimen = \minallocatedregister
-\countdef \lastallocatedskip = 34 \lastallocatedskip = \minallocatedregister
-\countdef \lastallocatedmuskip = 35 \lastallocatedmuskip = \minallocatedregister
-\countdef \lastallocatedbox = 36 \lastallocatedbox = \minallocatedregister
-\countdef \lastallocatedtoks = 37 \lastallocatedtoks = \minallocatedregister
-\countdef \lastallocatedread = 38 \lastallocatedread = \minallocatediochannel
-\countdef \lastallocatedwrite = 39 \lastallocatedwrite = \minallocatediochannel
-\countdef \lastallocatedmarks = 40 \lastallocatedmarks = \minallocatedregister
-\countdef \lastallocatedlanguage = 41 \lastallocatedlanguage = \minallocatedlanguage % not used in context
-\countdef \lastallocatedinsertion = 42 \lastallocatedinsertion = \minallocatedinsert
-\countdef \lastallocatedfamily = 43 \lastallocatedfamily = \minallocatedfamily % not used in context
-\countdef \lastallocatedattribute = 44 \lastallocatedattribute = \minallocatedattribute
-
-\countdef \mincountervalue = 125 \mincountervalue = -"7FFFFFFF % beware, we use index 125 at the lua end
-\countdef \maxcountervalue = 126 \maxcountervalue = "7FFFFFFF % beware, we use index 126 at the lua end
-
-%countdef \minusone = 127 \minusone = -1
-%chardef \zerocount = 0
-%chardef \plusone = 1
-
-\countdef \zerocount = 120 \zerocount = 0
-\countdef \plusone = 121 \plusone = 1
-\countdef \minusone = 122 \minusone = -1
-
-%chardef \normalpagebox = 255
-\countdef \normalpagebox = 127 \normalpagebox = 255 % hardcoded in pdftex/xetex
-
-% A few traditional allocations:
-
-\countdef \count@ = 255 % hm, used in \newif .. todo: replace it there
-\dimendef \dimen@ = 0
-\dimendef \dimen@i = 1 % global only
-\dimendef \dimen@ii = 2
+\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 = 32767
+\countdef \c_syst_min_allocated_iochannel = 54 \c_syst_min_allocated_iochannel = -1
+\countdef \c_syst_max_allocated_iochannel = 55 \c_syst_max_allocated_iochannel = 16
+\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 = 255
+\countdef \c_syst_max_allocated_insert = 58 \c_syst_max_allocated_insert = 254
+\countdef \c_syst_min_allocated_insert = 59 \c_syst_min_allocated_insert = 128
+\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 % 127-1023 : private
+
+\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_iochannel
+\countdef \c_syst_last_allocated_write = 39 \c_syst_last_allocated_write = \c_syst_min_allocated_iochannel
+\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
+
+\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
+
+% A few traditional allocations (these might go):
+
+\countdef \count@ = 255 % hm, used in \newif .. todo: replace it there
+\dimendef \dimen@ = 0
+\dimendef \dimen@i = 1 % global only
+\dimendef \dimen@ii = 2
%D So, effectively we start allocating from 256 and upwards. The
%D inserts sit in the range 128 upto 254. Page numbers use the
@@ -216,33 +218,34 @@
%D scratch registers upto 31 without problem but all others are
%D reserved.
-\def\wlog#1{} % \def\wlog{\immediate\write\minusone} % write on log file (only)
+\let\wlog\gobbleoneargument % Let's get rid of this one.
%D The allocators share a common helper macro.
-\def\newcount {\allocateregister\lastallocatedcount \count \countdef \maxallocatedregister}
-\def\newdimen {\allocateregister\lastallocateddimen \dimen \dimendef \maxallocatedregister}
-\def\newskip {\allocateregister\lastallocatedskip \skip \skipdef \maxallocatedregister}
-\def\newmuskip {\allocateregister\lastallocatedmuskip \muskip \muskipdef \maxallocatedregister}
-\def\newbox {\allocateregister\lastallocatedbox \box \mathchardef\maxallocatedregister}
-\def\newtoks {\allocateregister\lastallocatedtoks \toks \toksdef \maxallocatedregister}
-\def\newread {\allocateregister\lastallocatedread \read \chardef \maxallocatediochannel}
-\def\newwrite {\allocateregister\lastallocatedwrite \write \chardef \maxallocatediochannel}
-\def\newmarks {\allocateregister\lastallocatedmarks \marks \mathchardef\maxallocatedregister}
-\def\newinsert {\allocateregister\lastallocatedinsertion\insert \chardef \maxallocatedinsert}
+\normalprotected\def\newcount {\syst_basics_allocate\c_syst_last_allocated_count \count \countdef \c_syst_max_allocated_register}
+\normalprotected\def\newdimen {\syst_basics_allocate\c_syst_last_allocated_dimen \dimen \dimendef \c_syst_max_allocated_register}
+\normalprotected\def\newskip {\syst_basics_allocate\c_syst_last_allocated_skip \skip \skipdef \c_syst_max_allocated_register}
+\normalprotected\def\newmuskip {\syst_basics_allocate\c_syst_last_allocated_muskip \muskip \muskipdef \c_syst_max_allocated_register}
+\normalprotected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \mathchardef\c_syst_max_allocated_register}
+\normalprotected\def\newtoks {\syst_basics_allocate\c_syst_last_allocated_toks \toks \toksdef \c_syst_max_allocated_register}
+\normalprotected\def\newread {\syst_basics_allocate\c_syst_last_allocated_read \read \chardef \c_syst_max_allocated_iochannel}
+\normalprotected\def\newwrite {\syst_basics_allocate\c_syst_last_allocated_write \write \chardef \c_syst_max_allocated_iochannel}
+\normalprotected\def\newmarks {\syst_basics_allocate\c_syst_last_allocated_marks \marks \mathchardef\c_syst_max_allocated_register}
+\normalprotected\def\newinsert {\syst_basics_allocate\c_syst_last_allocated_insertion\insert \chardef \c_syst_max_allocated_insert}
%D We don't need these in \CONTEXT:
-\def\newlanguage{\allocateregister\lastallocatedlanguage \language\chardef \maxallocatedlanguage}
-\def\newfamily {\allocateregister\lastallocatedfamily \fam \chardef \maxallocatedfamily}
+\normalprotected\def\newlanguage{\syst_basics_allocate\c_syst_last_allocated_language \language\chardef \c_syst_max_allocated_language}
+\normalprotected\def\newfamily {\syst_basics_allocate\c_syst_last_allocated_family \fam \chardef \c_syst_max_allocated_family}
\let\newfam\newfamily
% 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.
-\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1}
-\def\setnewconstant#1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number
+\normalprotected\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1}
+\normalprotected\def\setnewconstant#1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number
+\normalprotected\def\setconstant {} % dummy, no checking, so it warns
% maybe setconstant with check
@@ -259,10 +262,10 @@
%D now provide many registers we removed all traces.
\ifdefined\writestatus \else
- \def\writestatus#1#2{\immediate\write16{#1: #2}}
+ \normalprotected\def\writestatus#1#2{\immediate\write16{#1: #2}}
\fi
-\def\allocateregisteryes#1#2#3#4#5% last class method max name
+\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
@@ -270,16 +273,16 @@
\writestatus{warning}{no room for \string#2\space \string#5\space (max: \number#4)}%
\fi}
-\def\allocateregisternop#1#2#3#4#5% last class method max name
+\def\syst_basics_allocate_nop#1#2#3#4#5% last class method max name
{\writestatus{warning}{\string#2 \string#5 is already defined (\string\relax\space it first)}}
-\def\allocateregister#1#2#3#4#5% last class method max name
+\def\syst_basics_allocate#1#2#3#4#5% last class method max name
{\ifx#5\undefined
- \expandafter\allocateregisteryes
+ \expandafter\syst_basics_allocate_yes
\else\ifx#5\relax
- \expandafter\expandafter\expandafter\allocateregisteryes
+ \expandafter\expandafter\expandafter\syst_basics_allocate_yes
\else
- \expandafter\expandafter\expandafter\allocateregisternop
+ \expandafter\expandafter\expandafter\syst_basics_allocate_nop
\fi\fi
#1#2#3#4#5}
@@ -287,8 +290,8 @@
%D {\chardef} instead of the more limited \type {\mathchardef}.
\ifnum\texengine>\pdftexengine
- \def\newbox {\allocateregister\lastallocatedbox \box \chardef\maxallocatedregister}
- \def\newmarks{\allocateregister\lastallocatedmarks\marks\chardef\maxallocatedregister}
+ \normalprotected\def\newbox {\syst_basics_allocate\c_syst_last_allocated_box \box \chardef\c_syst_max_allocated_register}
+ \normalprotected\def\newmarks{\syst_basics_allocate\c_syst_last_allocated_marks\marks\chardef\c_syst_max_allocated_register}
\fi
%D Attributes are something very \LUATEX. In \CONTEXT\ you are not
@@ -298,15 +301,16 @@
%D and should not be touched.
\ifnum\texengine=\luatexengine
- \let\attributeunsetvalue\mincountervalue % used to be \minusone
- \def\newattribute{\allocateregister\minallocatedattribute\attribute\attributedef\maxallocatedregister}
+ \let\attributeunsetvalue\c_syst_min_counter_value % used to be \minusone
+ \normalprotected\def\newattribute{\syst_basics_allocate\c_syst_min_allocated_attribute\attribute\attributedef\c_syst_max_allocated_register}
\fi
%D Not used by \CONTEXT\ but for instance \PICTEX\ needs it. It's a
%D trick to force strings instead of tokens that take more memory.
-%D It's a trick to trick to force strings.
+%D It's a trick to trick to force strings. This macro is never used
+%D in \CONTEXT.
-\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
+\normalprotected\def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
%D \macros
%D {scratchcounter,
@@ -317,12 +321,12 @@
%D We now define a few scratch registers, so that successive
%D loads at least have some available.
-\newcount \scratchcounter \newcount \globalscratchcounter
-\newdimen \scratchdimen \newdimen \globalscratchdimen
-\newskip \scratchskip \newskip \globalscratchskip
-\newmuskip \scratchmuskip \newmuskip \globalscratchmuskip
-\newtoks \scratchtoks \newtoks \globalscratchtoks
-\newbox \scratchbox \newbox \globalscratchbox
+\newcount \scratchcounter \newcount \globalscratchcounter
+\newdimen \scratchdimen \newdimen \globalscratchdimen
+\newskip \scratchskip \newskip \globalscratchskip
+\newmuskip\scratchmuskip \newmuskip\globalscratchmuskip
+\newtoks \scratchtoks \newtoks \globalscratchtoks
+\newbox \scratchbox \newbox \globalscratchbox
\newcount\scratchcounterone \newcount\scratchcountertwo \newcount\scratchcounterthree
\newdimen \scratchdimenone \newdimen \scratchdimentwo \newdimen \scratchdimenthree
@@ -331,17 +335,32 @@
\newtoks \scratchtoksone \newtoks \scratchtokstwo \newtoks \scratchtoksthree
\newbox \scratchboxone \newbox \scratchboxtwo \newbox \scratchboxthree
+%D \macros
+%D {scratchwidth, scratchheight, scratchdepth, scratchoffset, scratchdistance}
+%D
+%D A few more scratch dimensions:
+
+\newdimen\scratchwidth
+\newdimen\scratchheight
+\newdimen\scratchdepth
+\newdimen\scratchoffset
+\newdimen\scratchdistance
+\newdimen\scratchhsize
+\newdimen\scratchvsize
+
%D More allocations:
-\newskip \zeroskip \zeroskip = 0pt plus 0pt minus 0pt
-\newdimen\zeropoint \zeropoint = 0pt
-\newdimen\onepoint \onepoint = 1pt
-\newdimen\maxdimen \maxdimen = 16383.99999pt
-\newdimen\onebasepoint \onebasepoint = 1bp
-\newdimen\scaledpoint \scaledpoint = 1sp
-\newdimen\thousandpoint\thousandpoint= 1000pt
+\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
+\newdimen\onebasepoint \onebasepoint = 1bp
+\newdimen\scaledpoint \scaledpoint = 1sp
+\newdimen\thousandpoint \thousandpoint = 1000pt
-\let\points\onepoint
+\let\points \onepoint
+\let\halfpoint\halfapoint
\newtoks \emptytoks
@@ -382,6 +401,15 @@
\newcount \maxcard \maxcard = 65536 % pdftex has less mathchars
\fi
+%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}
+
%D We prefer the more readable variant than in plain
%D \TEX. User should only use \type {\emptybox}:
@@ -406,7 +434,7 @@
\let \@ne \plusone
\let \tw@ \plustwo
\let \thr@@ \plusthree
-\let \sixt@@n \sixteen
+\let \sixt@@n \plussixteen
\let \@cclv \pluscclv
\let \@cclvi \pluscclvi
\newbox \voidb@x
@@ -426,7 +454,7 @@
%D with \type {\iffoo}.
%D \stopnarrower
-\def\newif#1%
+\normalprotected\def\newif#1%
{\count@\escapechar
\escapechar\minusone
\expandafter\expandafter\expandafter\def\@if #1{true}{\let#1\iftrue }%
@@ -451,62 +479,53 @@
\ifdefined\htdp \else \def\htdp#1{\dimexpr\ht#1+\dp#1\relax} \fi
-%D \macros
-%D {@@escape,@@begingroup,@@endgroup,@@mathshift,@@alignment,
-%D @@endofline,@@parameter,@@superscript,@@subscript,
-%D @@ignore,@@space,@@letter,@@other,@@active,@@comment}
-%D
-%D In \CONTEXT\ we sometimes manipulate the \CATCODES\ of certain
-%D characters. Because we are not that good at remembering numbers,
-%D we introduce some symbolic names.
-
-%D As we now have catc-* files, we also have more readable names but
-%D We will keep the following around for a while.
-
-\chardef\@@escape = 0
-\chardef\@@begingroup = 1
-\chardef\@@endgroup = 2
-\chardef\@@mathshift = 3
-\chardef\@@alignment = 4
-\chardef\@@endofline = 5
-\chardef\@@parameter = 6
-\chardef\@@superscript = 7
-\chardef\@@subscript = 8
-\chardef\@@ignore = 9
-\chardef\@@space = 10
-\chardef\@@letter = 11
-\chardef\@@other = 12
-\chardef\@@active = 13
-\chardef\@@comment = 14
+%D The catcode constants will be redefined in later catcode
+%D related modules but they can be used in the same way.
+
+\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
+\chardef\activecatcode = 13
+\chardef\commentcatcode = 14
+\chardef\invalidcatcode = 15
%D Constants to be used with \type {\currentgrouptype}.
-\chardef\@@bottomlevelgroup = 0
-\chardef\@@simplegroup = 1
-\chardef\@@hboxgroup = 2
-\chardef\@@adjustedhboxgroup = 3
-\chardef\@@vboxgroup = 4
-\chardef\@@vtopgroup = 5
-\chardef\@@aligngroup = 6
-\chardef\@@noaligngroup = 7
-\chardef\@@outputgroup = 8
-\chardef\@@mathgroup = 9
-\chardef\@@discretionarygroup = 10
-\chardef\@@insertgroup = 11
-\chardef\@@vcentergroup = 12
-\chardef\@@mathchoicegroup = 13
-\chardef\@@semisimplegroup = 14
-\chardef\@@mathshiftgroup = 15
-\chardef\@@mathleftgroup = 16
-
-\chardef\@@vadjustgroup = \@@insertgroup
+\chardef\bottomlevelgroupcode = 0
+\chardef\simplegroupcode = 1
+\chardef\hboxgroupcode = 2
+\chardef\adjustedhboxgroupcode = 3
+\chardef\vboxgroupcode = 4
+\chardef\vtopgroupcode = 5
+\chardef\aligngroupcode = 6
+\chardef\noaligngroupcode = 7
+\chardef\outputgroupcode = 8
+\chardef\mathgroupcode = 9
+\chardef\discretionarygroupcode = 10
+\chardef\insertgroupcode = 11
+\chardef\vcentergroupcode = 12
+\chardef\mathchoicegroupcode = 13
+\chardef\semisimplegroupcode = 14
+\chardef\mathshiftgroupcode = 15
+\chardef\mathleftgroupcode = 16
+\chardef\vadjustgroupcode = \insertgroupcode
%D Constants to be used with \type {\interactionmode}.
-\chardef\@@batchmode = 0
-\chardef\@@nonstopmode = 1
-\chardef\@@scrollmode = 2
-\chardef\@@errorstopmode = 3
+\chardef\batchmodecode = 0
+\chardef\nonstopmodecode = 1
+\chardef\scrollmodecode = 2
+\chardef\errorstopmodecode = 3
%D Constants to be used with \type {\lastnodetype}. The \type
%D {\lastnodetype} primitive is \ETEX\ compliant. The valid range is
@@ -516,45 +535,46 @@
%D mind that the internal node numbers are different and that there
%D are more node types that 15.
-\chardef\@@charnode = 0
-\chardef\@@hlistnode = 1
-\chardef\@@vlistnode = 2
-\chardef\@@rulenode = 3
-\chardef\@@insertnode = 4
-\chardef\@@marknode = 5
-\chardef\@@adjustnode = 6
-\chardef\@@ligaturenode = 7
-\chardef\@@discretionarynode = 8
-\chardef\@@whatsitnode = 9
-\chardef\@@mathnode = 10
-\chardef\@@gluenode = 11
-\chardef\@@kernnode = 12
-\chardef\@@penaltynode = 13
-\chardef\@@unsetnode = 14
-\chardef\@@mathsnode = 15
-
-%D Constants to be used with \type {\currentiftype}.
-
-\chardef\@@charif = 1
-\chardef\@@catif = 2
-\chardef\@@numif = 3
-\chardef\@@dimif = 4
-\chardef\@@oddif = 5
-\chardef\@@vmodeif = 6
-\chardef\@@hmodeif = 7
-\chardef\@@mmodeif = 8
-\chardef\@@innerif = 9
-\chardef\@@voidif = 10
-\chardef\@@hboxif = 11
-\chardef\@@vboxif = 12
-\chardef\@@xif = 13
-\chardef\@@eofif = 14
-\chardef\@@trueif = 15
-\chardef\@@falseif = 16
-\chardef\@@caseif = 17
-\chardef\@@definedif = 18
-\chardef\@@csnameif = 19
-\chardef\@@fontcharif = 20
+\chardef\charnodecode = 0
+\chardef\hlistnodecode = 1
+\chardef\vlistnodecode = 2
+\chardef\rulenodecode = 3
+\chardef\insertnodecode = 4
+\chardef\marknodecode = 5
+\chardef\adjustnodecode = 6
+\chardef\ligaturenodecode = 7
+\chardef\discretionarynodecode = 8
+\chardef\whatsitnodecode = 9
+\chardef\mathnodecode = 10
+\chardef\gluenodecode = 11
+\chardef\kernnodecode = 12
+\chardef\penaltynodecode = 13
+\chardef\unsetnodecode = 14
+\chardef\mathsnodecode = 15
+
+%D Constants to be used with \type {\currentiftype}. I wonder if
+%D we will ever use these in \CONTEXT.
+
+\chardef\charifcode = 1
+\chardef\catifcode = 2
+\chardef\numifcode = 3
+\chardef\dimifcode = 4
+\chardef\oddifcode = 5
+\chardef\vmodeifcode = 6
+\chardef\hmodeifcode = 7
+\chardef\mmodeifcode = 8
+\chardef\innerifcode = 9
+\chardef\voidifcode = 10
+\chardef\hboxifcode = 11
+\chardef\vboxifcode = 12
+\chardef\xifcode = 13
+\chardef\eofifcode = 14
+\chardef\trueifcode = 15
+\chardef\falseifcode = 16
+\chardef\caseifcode = 17
+\chardef\definedifcode = 18
+\chardef\csnameifcode = 19
+\chardef\fontcharifcode = 20
%D Of course we want even bigger log files, so we copied this
%D from the \ETEX\ source files.
@@ -572,7 +592,7 @@
%D
%D In \LUATEX\ we have ways around this.
-\def\tracingall
+\normalprotected\def\tracingall
{\tracingonline \plusone
\tracingcommands \plusthree
\tracingstats \plustwo
@@ -591,11 +611,11 @@
\tracingassigns \plustwo
\errorstopmode}
-\def\loggingall
+\normalprotected\def\loggingall
{\tracingall
\tracingonline \zerocount}
-\def\tracingnone
+\normalprotected\def\tracingnone
{\tracingassigns \zerocount
\tracingnesting \zerocount
\tracingscantokens\zerocount
@@ -644,11 +664,119 @@
\normaleveryjob{\the\everyjob}
-\def\appendtotoks #1{\def\temp{#1}\afterassignment\doappendtotoks \scratchtoks=}
-\def\prependtotoks#1{\def\temp{#1}\afterassignment\doprependtotoks\scratchtoks=}
+%D \macros
+%D {newconditional,
+%D settrue, setfalse,
+%D ifconditional,then}
+%D
+%D \TEX's lacks boolean variables, although the \PLAIN\ format
+%D implements \type{\newif}. The main disadvantage of this
+%D scheme is that it takes three hash table entries. A more
+%D memory saving alternative is presented here. A conditional
+%D is defined by:
+%D
+%D \starttyping
+%D \newconditional\doublesided
+%D \setfalse
+%D \stoptyping
+%D Setting a conditional is done by \type{\settrue} and
+%D \type{\setfalse}:
+%D
+%D \starttyping
+%D \settrue\doublesided
+%D \setfalse
+%D \stoptyping
+%D while testing is accomplished by:
+%D
+%D \starttyping
+%D \ifconditional\doublesided ... \else ... \fi
+%D \setfalse
+%D \stoptyping
+%D We cannot use the simple scheme:
+%D
+%D \starttyping
+%D \def\settrue #1{\let#1=\iftrue}
+%D \def\setfalse#1{\let#1=\iffalse}
+%D \stoptyping
+%D
+%D Such an implementation gives problems with nested
+%D conditionals. The next implementation is about as fast
+%D 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
+
+\normalprotected\def\settrue #1{\let#1\conditionaltrue }
+\normalprotected\def\setfalse#1{\let#1\conditionalfalse}
-\def\doappendtotoks {\expandafter\expandafter\expandafter{\expandafter\the\expandafter\temp\the\scratchtoks}}
-\def\doprependtotoks{\expandafter\expandafter\expandafter{\expandafter\the\expandafter\scratchtoks\the\temp}}
+\let\newconditional\setfalse
+\let\ifconditional \ifcase
+
+\let\then\relax % so that we can say: \ifnum1>2\then -)
+
+%D \macros
+%D {newmacro,setnewmacro,newfraction}
+%D
+%D Let's be complete and also introduce some definers. These are
+%D not mandate but handy for grepping.
+
+\normalprotected\def\newmacro #1{\let#1\empty}
+\normalprotected\def\setnewmacro#1{\let#1}
+
+\def\!!plusone{1}
+
+\normalprotected\def\newfraction#1{\let#1\!!plusone}
+
+%D It would be handy to have a primitive \unless\ifcase because
+%D then we could use nicer values. Anyhow, this conditional code
+%D used to be in the \type {syst-aux} module but is now promoted
+%D to here.
+
+%D \macros
+%D {ifzeropt}
+%D
+%D The next macro is both cosmetic and byte saving. It is
+%D pretty \type{\if}||safe too. It can be used in cases
+%D like:
+%D
+%D \starttyping
+%D \ifzeropt \somedimen ... \else ... \fi
+%D \stoptyping
+
+\let\ifzeropt\ifcase
+
+% these token list helpers might move to syst-aux.mkiv
+%
+% we assume a \cs. not toks0 or so
+%
+% \normalprotected\def\appendtotoks #1#{\def\temp{#1}\afterassignment\doappendtotoks \scratchtoks=}
+% \normalprotected\def\prependtotoks#1#{\def\temp{#1}\afterassignment\doprependtotoks\scratchtoks=}
+
+\newtoks\t_syst_toks_temp \let\m_syst_toks_temp\t_syst_toks_temp
+
+\normalprotected\def\appendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_l \t_syst_toks_temp=}
+\normalprotected\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}}}
+
+\normalprotected\def\globalappendtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_append_g \t_syst_toks_temp=}
+\normalprotected\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}}}
+
+\def\syst_toks_append_g {\global\syst_toks_append_l }
+\def\syst_toks_prepend_g{\global\syst_toks_prepend_l}
+
+\normalprotected\def\addtotoks #1{\let\m_syst_toks_temp#1\afterassignment\syst_toks_add_l\let\next}
+\normalprotected\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}
+
+\normalprotected\def\addtotokscs #1#2{#1{\the#1#2}} % saves a few bytes
+\normalprotected\def\globaladdtotokscs#1#2{\global#1{\the#1#2}} % saves a few bytes
%D \macros
%D {begcsname}
@@ -691,7 +819,7 @@
%D does not support nested loops. We use a namespace prefix
%D \type {@@pln}.
-\long\def\loop#1\repeat{\long\def\@@plnbody{#1}\@@plniterate}
+\long\def\loop#1\repeat{\long\def\@@plnbody{#1}\@@plniterate} % might go
%D The following makes \type {\loop} \unknown\ \type {\if}
%D \unknown\ \type {\repeat} skippable (clever trick):
@@ -732,15 +860,15 @@
%D The following registers are kind of standard and (for the moment)
%D we define them here. This might change.
-\newskip \bigskipamount \bigskipamount = 12pt plus 4pt minus 4pt
-\newskip \medskipamount \medskipamount = 6pt plus 2pt minus 2pt
-\newskip \smallskipamount \smallskipamount = 3pt plus 1pt minus 1pt
+\newskip \bigskipamount \bigskipamount = 12pt plus 4pt minus 4pt
+\newskip \medskipamount \medskipamount = 6pt plus 2pt minus 2pt
+\newskip \smallskipamount \smallskipamount = 3pt plus 1pt minus 1pt
\baselineskip = 12pt
\lineskip = 1pt
\lineskiplimit = 0pt
-%D Again a few kind-of-extensions the core:
+%D Again a few kind-of-extensions the core: (might go away)
\newskip \hideskip \hideskip = -1000pt plus 1fill
\newskip \centering \centering = 0pt plus 1000pt minus 1000pt
@@ -749,7 +877,7 @@
{\hskip\hideskip}
\def\ialign % initialized \halign
- {\everycr{}%
+ {\everycr\emptytoks
\tabskip\zeroskip
\halign}
@@ -817,25 +945,25 @@
% new after 1.10, watch the change in prefix
-\bindprimitive quitvmode ptexquitvmode
-\bindprimitive noligatures ptexnoligatures
-\bindprimitive setrandomseed ptexsetrandomseed
-\bindprimitive uniformdeviate ptexuniformdeviate
+% \bindprimitive quitvmode ptexquitvmode
+% \bindprimitive noligatures ptexnoligatures
+% \bindprimitive setrandomseed ptexsetrandomseed
+% \bindprimitive uniformdeviate ptexuniformdeviate
-\bindprimitive quitvmode pdfquitvmode
-\bindprimitive noligatures pdfnoligatures
-\bindprimitive setrandomseed pdfsetrandomseed
-\bindprimitive uniformdeviate pdfuniformdeviate
+% \bindprimitive quitvmode pdfquitvmode
+% \bindprimitive noligatures pdfnoligatures
+% \bindprimitive setrandomseed pdfsetrandomseed
+% \bindprimitive uniformdeviate pdfuniformdeviate
-\bindprimitive resettimer pdfresettimer
-\bindprimitive elapsedtime pdfelapsedtime
+% \bindprimitive resettimer pdfresettimer
+% \bindprimitive elapsedtime pdfelapsedtime
% new per 1.40
-\bindprimitive ifprimitive ifpdfprimitive
-\bindprimitive primitive pdfprimitive
-\bindprimitive ifabsdim ifpdfabsdim
-\bindprimitive ifabsnum ifpdfabsnum
+% \bindprimitive ifprimitive ifpdfprimitive
+% \bindprimitive primitive pdfprimitive
+% \bindprimitive ifabsdim ifpdfabsdim
+% \bindprimitive ifabsnum ifpdfabsnum
\ifnum\texengine=\xetexengine \else % this test might disappear some day
@@ -846,9 +974,9 @@
\ifdefined\pdfgentounicode \else \newcount\pdfgentounicode \fi \pdfgentounicode \plusone
\ifdefined\pdfinclusioncopyfonts\else \newcount\pdfinclusioncopyfonts \fi \pdfinclusioncopyfonts\plusone
- \def\nopdfcompression {\pdfobjcompresslevel\zerocount \pdfcompresslevel\zerocount}
- \def\maximumpdfcompression{\pdfobjcompresslevel\plusnine \pdfcompresslevel\plusnine }
- \def\normalpdfcompression {\pdfobjcompresslevel\plusthree \pdfcompresslevel\plusthree}
+ \normalprotected\def\nopdfcompression {\pdfobjcompresslevel\zerocount \pdfcompresslevel\zerocount}
+ \normalprotected\def\maximumpdfcompression{\pdfobjcompresslevel\plusnine \pdfcompresslevel\plusnine }
+ \normalprotected\def\normalpdfcompression {\pdfobjcompresslevel\plusthree \pdfcompresslevel\plusthree}
\normalpdfcompression
@@ -879,12 +1007,12 @@
\ifx\fmtname \undefined \def\fmtname {ConTeXt Minimized Plain TeX} \fi
\ifx\fmtversion\undefined \def\fmtversion{3.1415926} \fi
-\let\normalfmtversion\fmtversion
+\let\normalfmtversion\fmtversion % still needed ?
%D A few bonus macros:
\def\modulonumber#1#2{\the\numexpr#2-((((#2+(#1/2))/#1)-1)*#1)\relax}
-\def\dividonumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax}
+\def\dividenumber#1#2{\the\numexpr(#2-(#1/2))/#1\relax}
\ifnum\texengine=\xetexengine
\edef\xetexversion {\numexpr\XeTeXversion*100+(\expandafter\gobbleoneargument\XeTeXrevision-5)/10\relax}
@@ -892,26 +1020,36 @@
\fi
\ifcase\texengine
- \def\texenginename {impossible}
+ \def \texenginename {impossible}
\edef\texengineversion{0}
\or
- \def\texenginename {pdfTeX}
- \edef\texengineversion{\dividonumber{100}\pdftexversion.\modulonumber{100}\pdftexversion.\pdftexrevision}
+ \def \texenginename {pdfTeX}
+ \edef\texengineversion{\dividenumber{100}\pdftexversion.\modulonumber{100}\pdftexversion.\pdftexrevision}
\or
- \def\texenginename {XeTeX}
- \edef\texengineversion{\dividonumber{100}\xetexversion .\modulonumber{100}\xetexversion .\xetexrevision}
+ \def \texenginename {XeTeX}
+ \edef\texengineversion{\dividenumber{100}\xetexversion .\modulonumber{100}\xetexversion .\xetexrevision}
\or
- \def\texenginename {LuaTeX}
- \edef\texengineversion{\dividonumber{100}\luatexversion.\modulonumber{100}\luatexversion.\luatexrevision}
+ \def \texenginename {LuaTeX}
+ \edef\texengineversion{\dividenumber{100}\luatexversion.\modulonumber{100}\luatexversion.\luatexrevision}
\else
- \def\texenginename {impossible}
+ \def \texenginename {impossible}
\edef\texengineversion{0}
\fi
+%D We have no reason not to enable this:
+
+\savingvdiscards\plusone
+
%D We only can set this one via directives (system.synctex).
\let\synctex\undefined \newcount\synctex
+%D We get rid of the funny \TEX\ offset defaults of one
+%D inch by setting them to zero.
+
+\voffset \zeropoint \newdimen\voffset % prevent messing up
+\hoffset \zeropoint \newdimen\hoffset % prevent messing up
+
%D While cleaning this code up a bit I was listening to Heather
%D Nova's \CD\ Redbird. The first song on that \CD\ ends with
%D a few lines suitable for ending this initialization module:
diff --git a/Master/texmf-dist/tex/context/base/syst-lua.lua b/Master/texmf-dist/tex/context/base/syst-lua.lua
index 8a5a9531c1b..f735b1962e6 100644
--- a/Master/texmf-dist/tex/context/base/syst-lua.lua
+++ b/Master/texmf-dist/tex/context/base/syst-lua.lua
@@ -6,55 +6,59 @@ if not modules then modules = { } end modules ['syst-lua'] = {
license = "see context related readme files"
}
-local texsprint, texprint, texwrite, texiowrite_nl = tex.sprint, tex.print, tex.write, texio.write_nl
-local format, find = string.format, string.find
+local format, find, match, rep = string.format, string.find, string.match, string.rep
local tonumber = tonumber
-local S, Ct, lpegmatch, lpegsplitat = lpeg.S, lpeg.Ct, lpeg.match, lpeg.splitat
+local S, lpegmatch, lpegtsplitat = lpeg.S, lpeg.match, lpeg.tsplitat
-local ctxcatcodes = tex.ctxcatcodes
+local context = context
-commands = commands or { } -- cs = commands -- shorter, maybe some day, not used now
+commands = commands or { }
function commands.writestatus(...) logs.status(...) end -- overloaded later
--- todo: use shorter names i.e. less tokenization
+-- todo: use shorter names i.e. less tokenization, like prtcatcodes + f_o_t_a
+
+local firstoftwoarguments = context.firstoftwoarguments -- context.constructcsonly("firstoftwoarguments" )
+local secondoftwoarguments = context.secondoftwoarguments -- context.constructcsonly("secondoftwoarguments")
+local firstofoneargument = context.firstofoneargument -- context.constructcsonly("firstofoneargument" )
+local gobbleoneargument = context.gobbleoneargument -- context.constructcsonly("gobbleoneargument" )
local function testcase(b)
- if b then -- looks faster with if than with expression
- texsprint(ctxcatcodes,"\\firstoftwoarguments")
+ if b then
+ firstoftwoarguments()
else
- texsprint(ctxcatcodes,"\\secondoftwoarguments")
+ secondoftwoarguments()
end
end
-commands.testcase = testcase
-commands.doifelse = testcase
-
function commands.doif(b)
if b then
- texsprint(ctxcatcodes,"\\firstofoneargument")
+ firstofoneargument()
else
- texsprint(ctxcatcodes,"\\gobbleoneargument")
+ gobbleoneargument()
end
end
function commands.doifnot(b)
if b then
- texsprint(ctxcatcodes,"\\gobbleoneargument")
+ gobbleoneargument()
else
- texsprint(ctxcatcodes,"\\firstofoneargument")
+ firstofoneargument()
end
end
+commands.testcase = testcase
+commands.doifelse = testcase
+
function commands.boolcase(b)
- if b then texwrite(1) else texwrite(0) end
+ context(b and 1 or 0)
end
function commands.doifelsespaces(str)
- return commands.doifelse(find(str,"^ +$"))
+ return testcase(find(str,"^ +$"))
end
-local s = Ct(lpegsplitat(","))
+local s = lpegtsplitat(",")
local h = { }
function commands.doifcommonelse(a,b)
@@ -89,19 +93,11 @@ function commands.doifdimenstringelse(str)
testcase(lpegmatch(pattern,str))
end
-local splitter = lpegsplitat(S(". "))
+function commands.firstinset(str)
+ local first = match(str,"^([^,]+),")
+ context(first or str)
+end
-function commands.doifolderversionelse(one,two) -- one >= two
- if not two then
- one, two = environment.version, one
- elseif one == "" then
- one = environment.version
- end
- local y_1, m_1, d_1 = lpegmatch(splitter,one)
- local y_2, m_2, d_2 = lpegmatch(splitter,two)
- commands.testcase (
- (tonumber(y_1) or 0) >= (tonumber(y_2) or 0) and
- (tonumber(m_1) or 0) >= (tonumber(m_2) or 0) and
- (tonumber(d_1) or 0) >= (tonumber(d_1) or 0)
- )
+function commands.ntimes(str,n)
+ context(rep(str,n or 1))
end
diff --git a/Master/texmf-dist/tex/context/base/syst-lua.mkiv b/Master/texmf-dist/tex/context/base/syst-lua.mkiv
index 3ed70cc0b77..0d72e4a019b 100644
--- a/Master/texmf-dist/tex/context/base/syst-lua.mkiv
+++ b/Master/texmf-dist/tex/context/base/syst-lua.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Helper macros based on \LUA,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -32,12 +32,12 @@
\edef\!!bs{[\luastringsep[}
\edef\!!es{]\luastringsep]}
-\def\writestatus#1#2{\ctxcommand{writestatus(\!!bs#1\!!es,\!!bs#2\!!es)}}
+\unexpanded\def\writestatus#1#2{\ctxcommand{writestatus(\!!bs#1\!!es,\!!bs#2\!!es)}}
% a handy helper (we can probably omit the tex.ctxcatcodes here as nowadays we seldom
% change the regime at the tex end
-%def\luaexpr#1{\ctxlua {tex.sprint(tex.ctxcatcodes,tostring(#1))}}
-\def\luaexpr#1{\directlua\zerocount{tex.sprint(tex.ctxcatcodes,tostring(#1))}} % wrap in global function ?
+%def\luaexpr#1{\ctxlua {context(tostring(#1))}}
+\def\luaexpr#1{\directlua\zerocount{context(tostring(#1))}} % wrap in global function ?
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/syst-mes.mkiv b/Master/texmf-dist/tex/context/base/syst-mes.mkiv
index 070c7af72f9..4cd36e24bdf 100644
--- a/Master/texmf-dist/tex/context/base/syst-mes.mkiv
+++ b/Master/texmf-dist/tex/context/base/syst-mes.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Messages,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-new.mkii b/Master/texmf-dist/tex/context/base/syst-new.mkii
index 53ba18ffdf9..34b535b901e 100644
--- a/Master/texmf-dist/tex/context/base/syst-new.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-new.mkii
@@ -5,7 +5,7 @@
%D subtitle=New Ones,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-pln.mkii b/Master/texmf-dist/tex/context/base/syst-pln.mkii
index f2b6129ff99..1032b40b595 100644
--- a/Master/texmf-dist/tex/context/base/syst-pln.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-pln.mkii
@@ -5,7 +5,7 @@
%D subtitle=Efficient \PLAIN\ \TEX\ loading,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-pln.mkiv b/Master/texmf-dist/tex/context/base/syst-pln.mkiv
index 7fa91b73d40..2481131209f 100644
--- a/Master/texmf-dist/tex/context/base/syst-pln.mkiv
+++ b/Master/texmf-dist/tex/context/base/syst-pln.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Efficient \PLAIN\ \TEX\ loading,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -38,7 +38,7 @@
\finalhyphendemerits = 5000
%floatingpenalty = 0
%globaldefs = 0
-%hangafter = 1
+\hangafter = 1 % automatically set to 1 (no zero assignment)
\hbadness = 1000
%holdinginserts = 0
\hyphenpenalty = 50
diff --git a/Master/texmf-dist/tex/context/base/syst-rtp.mkii b/Master/texmf-dist/tex/context/base/syst-rtp.mkii
index a1c6abe2eed..fc0f503b062 100644
--- a/Master/texmf-dist/tex/context/base/syst-rtp.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-rtp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Run Time Processes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-rtp.mkiv b/Master/texmf-dist/tex/context/base/syst-rtp.mkiv
index 36ce8edb18a..f65e599eca5 100644
--- a/Master/texmf-dist/tex/context/base/syst-rtp.mkiv
+++ b/Master/texmf-dist/tex/context/base/syst-rtp.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Run Time Processes,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-str.mkii b/Master/texmf-dist/tex/context/base/syst-str.mkii
index 3e6d043e393..aacb70ec742 100644
--- a/Master/texmf-dist/tex/context/base/syst-str.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-str.mkii
@@ -5,7 +5,7 @@
%D subtitle=String Processing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/syst-tex.mkii b/Master/texmf-dist/tex/context/base/syst-tex.mkii
index a8aea268383..fee2b51b228 100644
--- a/Master/texmf-dist/tex/context/base/syst-tex.mkii
+++ b/Master/texmf-dist/tex/context/base/syst-tex.mkii
@@ -5,7 +5,7 @@
%D subtitle=Efficient \PLAIN\ \TEX\ loading,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-com.mkii b/Master/texmf-dist/tex/context/base/tabl-com.mkii
index 892905f6c12..8a0bb9e0c48 100644
--- a/Master/texmf-dist/tex/context/base/tabl-com.mkii
+++ b/Master/texmf-dist/tex/context/base/tabl-com.mkii
@@ -5,7 +5,7 @@
%D subtitle=Common Code,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-com.mkiv b/Master/texmf-dist/tex/context/base/tabl-com.mkiv
index 892905f6c12..e9008636886 100644
--- a/Master/texmf-dist/tex/context/base/tabl-com.mkiv
+++ b/Master/texmf-dist/tex/context/base/tabl-com.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Common Code,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,7 +15,39 @@
\unprotect
+\let\VL\relax
+
\let\NC\relax
+\let\RC\relax
+\let\HC\relax
+\let\EQ\relax
+
+\let\RQ\relax
+\let\HQ\relax
+
+\let\NG\relax
+\let\NN\relax
+\let\ND\relax
\let\NR\relax
+\let\NB\relax
+
+\let\CC\relax
+\let\CL\relax
+\let\CM\relax
+\let\CR\relax
+
+\let\SR\relax
+\let\FR\relax
+\let\MR\relax
+\let\LR\relax
+\let\AR\relax
+
+\let\FL\relax
+\let\ML\relax
+\let\LL\relax
+\let\TL\relax
+\let\BL\relax
+\let\HL\relax
+\let\HR\relax
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/tabl-ltb.mkii b/Master/texmf-dist/tex/context/base/tabl-ltb.mkii
index 095e30e2b76..bac2b589376 100644
--- a/Master/texmf-dist/tex/context/base/tabl-ltb.mkii
+++ b/Master/texmf-dist/tex/context/base/tabl-ltb.mkii
@@ -5,7 +5,7 @@
%D subtitle=Line Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-ltb.mkiv b/Master/texmf-dist/tex/context/base/tabl-ltb.mkiv
index 06e3eca2943..542d256f2fc 100644
--- a/Master/texmf-dist/tex/context/base/tabl-ltb.mkiv
+++ b/Master/texmf-dist/tex/context/base/tabl-ltb.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Line Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -245,34 +245,14 @@
\hbox \ifcase\linetablemode \or to\scratchdimen \fi \bgroup
\ifcase\alignmentswitch\hss\or\hss\fi
\fi
- \dostartattributes{\??lec\number\linetablecolumn}\c!style\c!color\empty
+ \dousestylehashparameter{\??lec\number\linetablecolumn}\c!style
+ \dousecolorhashparameter{\??lec\number\linetablecolumn}\c!color
\begstrut \ignorespaces}
-% \unexpanded\def\stoplinetablecell
-% {\unskip \endstrut
-% \dostopattributes
-% \ifcase\linetablemode
-% \endgraf
-% \else
-% \ifcase\alignmentswitch\else\hss\fi
-% \fi
-% \egroup
-% \hskip\linetablecparameter\c!rightoffset
-% \egroup
-% \iflinetablepreroll
-% \box\scratchbox
-% \else
-% \doif{\linetablecparameter\c!background}\v!color
-% {\backgroundline[\linetablecparameter\c!backgroundcolor]}%
-% {\box\scratchbox}%
-% \fi
-% \egroup}
-
\newconditional\linetableautoheight \settrue\linetableautoheight
\unexpanded\def\stoplinetablecell
{\unskip \endstrut
- \dostopattributes
\ifcase\linetablemode
\endgraf
\else
@@ -299,44 +279,6 @@
\fi
\egroup}
-% \unexpanded\def\stoplinetablecell
-% {\unskip \endstrut
-% \dostopattributes
-% \ifcase\linetablemode
-% \endgraf
-% \else
-% \ifcase\alignmentswitch\else\hss\fi
-% \fi
-% \egroup
-% \hskip\linetablecparameter\c!rightoffset
-% \egroup
-% \iflinetablepreroll
-% \box\scratchbox
-% \else
-% \doifelse{\linetablecparameter\c!background}\v!color
-% {\ifconditional\linetableautoheight
-% % \hbox{\blackrule
-% % [ \c!color=\linetablecparameter\c!backgroundcolor,
-% % \c!height=\linetablerparameter{x\c!height},
-% % \c!depth=\linetablerparameter{x\c!depth},
-% % \c!width=\wd\scratchbox]%
-% % \hskip-\wd\scratchbox\box\scratchbox}%
-% \dp\scratchbox\linetablerparameter{x\c!depth}%
-% \ht\scratchbox\linetablerparameter{x\c!height}%
-% \framed
-% [\c!offset=\v!overlay,
-% \c!frameoffset=.5\linewidth,
-% \c!leftframe=\v!off,\c!rightframe=\v!off,
-% \c!background=\v!color,
-% \c!backgroundcolor=\linetablecparameter\c!backgroundcolor%
-% ]{\box\scratchbox}%
-% \else
-% \backgroundline[\linetablecparameter\c!backgroundcolor]{\box\scratchbox}%
-% \fi}%
-% {\box\scratchbox}%
-% \fi
-% \egroup}
-
\def\savelinetablepart
{\global\setbox\tablebox\linetablepart
\ifnum\linetablepart=\zerocount
@@ -391,15 +333,14 @@
\unexpanded\def\startlinetablepart
{\global\linetablesubcol\zerocount
\setbox\scratchbox\hbox\bgroup
- \doconvertfont{\linetablerparameter\c!style}%
- \startcolor[\linetablerparameter\c!color]%
+ \dousestyleparameter{\linetablerparameter\c!style}%
+ \dousecolorparameter{\linetablerparameter\c!color}%
\ignorespaces}
\unexpanded\def\stoplinetablepart
{\ifnum\linetablepart>\zerocount
\unskip \unskip % remove last intercolumn skip (distance+fill)
\fi
- \stopcolor
\egroup
\iflinetablepreroll \else
\ifcase\linetablepart
@@ -732,7 +673,7 @@
\newtoks \@@linetablehead
-\long\unexpanded\def\startlinetablehead#1\stoplinetablehead
+\unexpanded\def\startlinetablehead#1\stoplinetablehead
{\ifinlinetable
\@@linetablehead\emptytoks
\fi
@@ -779,6 +720,7 @@
\startlinetableanalysis\readfile{#1}\donothing\donothing\stoplinetableanalysis
\startlinetablerun \readfile{#1}\donothing\donothing\stoplinetablerun
\egroup}
+
\protect \endinput
\doifnotmode{demo}{\endinput}
diff --git a/Master/texmf-dist/tex/context/base/tabl-ntb.mkii b/Master/texmf-dist/tex/context/base/tabl-ntb.mkii
index e243a55c21e..465ed44b21f 100644
--- a/Master/texmf-dist/tex/context/base/tabl-ntb.mkii
+++ b/Master/texmf-dist/tex/context/base/tabl-ntb.mkii
@@ -5,7 +5,7 @@
%D subtitle=Natural Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-ntb.mkiv b/Master/texmf-dist/tex/context/base/tabl-ntb.mkiv
index 96b1aabed82..99da4b5e8a3 100644
--- a/Master/texmf-dist/tex/context/base/tabl-ntb.mkiv
+++ b/Master/texmf-dist/tex/context/base/tabl-ntb.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Natural Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -22,6 +22,24 @@
% todo: fast if
% todo: avoid halign (just do it manual) and thereby globals
+% bug: width 3cm is not honored and column becomes too wide
+% as given width is added to distributed width
+%
+% \bTABLE
+% \bTR
+% \bTD test \eTD
+% \bTD \framed[height=3cm]{test} \eTD
+% \bTD[width=3cm] \dorecurse{30}{a } \eTD
+% \bTD \input ward \eTD
+% \eTR
+% \bTR
+% \bTD test \eTD
+% \bTD \framed[height=3cm]{test} \eTD
+% \bTD \dorecurse{30}{a } \eTD
+% \bTD \input ward \eTD
+% \eTR
+% \eTABLE
+
% \unexpanded\def\startrow {\bTR}
% \unexpanded\def\stoprow {\eTR}
% \unexpanded\def\startcell#1\stopcell{\bTD#1\eTD}
@@ -61,24 +79,16 @@
% \placefigure[left]{}{}
% \startlinecorrection \dontleavehmode \bTABLE
% \bTR \bTD oeps \eTD \eTR
-% \eTABLE
-% \stoplinecorrection
+% \eTABLE \stoplinecorrection
% \placefigure[right]{}{}
% \startlinecorrection \dontleavehmode \bTABLE
% \bTR \bTD oeps \eTD \eTR
-% \eTABLE
-% \stoplinecorrection
+% \eTABLE \stoplinecorrection
% \stoptext
%D To Do:
%D
%D \starttyping
-%D splitsen = ja | herhaal => als nofTH>1 then ja als herhaal
-%D \stoptyping
-
-%D To Do:
-%D
-%D \starttyping
%D break over pagina
%D kop herhalen
%D reset settings
@@ -116,12 +126,13 @@
%D
%D \typebuffer \getbuffer
-\let\dotagTABLEalign\relax
+\ifdefined\dotagTABLEcell \else \let\dotagTABLEcell \relax \fi
+\ifdefined\dotagTABLEsignal \else \let\dotagTABLEsignal\relax \fi
\def\bTBLCELL % why not \doinhibitblank
{\inhibitblank
- \dotagTABLEalign
- \doconvertfont\tbltblstyle\empty
+ \dotagTABLEcell
+ \dousestyleparameter\tbltblstyle
\everypar{\tbltblleft\delayedbegstrut}}
\def\eTBLCELL
@@ -923,21 +934,6 @@
\fi
\egroup}}
-% \def\begintbl
-% {\global\tblspn\zerocount
-% \global\tblcol\zerocount
-% \global\tblrow\zerocount
-% \global\advance\tblrow\minusone
-% \tabskip\zeropoint
-% \halign\bgroup
-% \registerparoptions % new
-% \ignorespaces##\unskip&&\ignorespaces##\unskip\cr}
-
-% \def\endtbl
-% {\egroup}
-
-\let\dotagTABLEcell\relax
-
\def\begintbl
{\global\tblspn\zerocount
\global\tblcol\zerocount
@@ -950,10 +946,12 @@
\halign\bgroup
\registerparoptions
% watch out: tagging the cell happens at the outer level (faster)
- \ignorespaces##\unskip&&\dostarttagged\t!tablecell\empty\ignorespaces##\unskip\dostoptagged\cr} % one too many
+% \ignorespaces##\unskip&&\dostarttagged\t!tablecell\empty\ignorespaces##\unskip\dostoptagged\cr} % one too many
+ \ignorespaces##\unskip&&\ignorespaces##\unskip\cr} % one too many
\def\endtbl
- {\dostoptagged\egroup
+ {\dostoptagged
+ \egroup
\dostoptagged}
\setvalue{\tblnone TBL}#1#2%
@@ -1009,16 +1007,17 @@
\settblhei{#1}{\the\ht\scratchbox}%
\fi}%
-\let\dotagnoftablecolumns\relax
-\let\dotagnoftablerows \relax
+\newcount\tablecellrows
+\newcount\tablecellcolumns
\def\domakeTBLthree#1 #2 %
{% height
+ \dostarttagged\t!tablecell\empty
\!!counta \gettblcol{#1}{#2}\relax
\!!countb \gettblrow{#1}{#2}\relax
\!!heighta\gettblht {#1}{#2}\relax
-\dotagnoftablecolumns
-\dotagnoftablerows
+ \tablecellcolumns\!!counta % used later so don't adapt these
+ \tablecellrows \!!countb % used later so don't adapt these
\scratchdimen\zeropoint
\ifnum\!!counta=\maximumcol\relax
% case: nc=maxcolumns
@@ -1041,7 +1040,10 @@
\advance\scratchcounter\plusone}%
\edef\widthTBL{\the\dimexpr\scratchdimen-\tbltblcolumndistance\relax}%
% cell
- \setbox\scratchbox\hbox{\gettbltxt{#1}{#2}}%
+ \setbox\scratchbox\hbox attr \taggedattribute \attribute\taggedattribute \bgroup
+ \dotagTABLEsignal % maybe we need to add some packaging in this case
+ \gettbltxt{#1}{#2}%
+ \egroup
\ifnum\!!counta=\maximumcol\relax
% case: nc=maxcolumns
\else
@@ -1057,7 +1059,7 @@
\else
\normalexpanded{\noexpand\directgotobox{\box\scratchbox}[\!!stringa]}% to be checked
\fi
- \dotagTABLEcell} % right spot
+ \dostoptagged} % right spot
\def\inTBLcell#1#2% hm, do we need #1 #2 ? we use tblcol anyway
{\doifnotinset\localwidth{\v!fit,\v!broad}% user set
@@ -1384,7 +1386,7 @@
\settblht{#1}{#2}{\the\ht\scratchbox}%
\settblwd{#1}{#2}{\the\wd\scratchbox}%
\ifautoTBLcheckwidth
- \ifdim\wd\scratchbox<.75\hsize
+ \ifdim\wd\scratchbox<.75\hsize % fuzzy guess
\ifdim\ht\scratchbox>2\openlineheight % honor width since this
\scratchdimen\gettblaut\tblcol\relax % can be a figure or so
\ifdim\scratchdimen=\zeropoint
diff --git a/Master/texmf-dist/tex/context/base/tabl-nte.mkii b/Master/texmf-dist/tex/context/base/tabl-nte.mkii
index cde64a033d5..6a5391f243b 100644
--- a/Master/texmf-dist/tex/context/base/tabl-nte.mkii
+++ b/Master/texmf-dist/tex/context/base/tabl-nte.mkii
@@ -5,7 +5,7 @@
%D subtitle=Natural Tables Extensions,
%D author=Hans Hagen \& Wolfgang Schuster,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-nte.mkiv b/Master/texmf-dist/tex/context/base/tabl-nte.mkiv
index 2a9e147038c..08ab34f0fa0 100644
--- a/Master/texmf-dist/tex/context/base/tabl-nte.mkiv
+++ b/Master/texmf-dist/tex/context/base/tabl-nte.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Natural Tables Extensions,
%D author=Hans Hagen \& Wolfgang Schuster,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-tab.mkii b/Master/texmf-dist/tex/context/base/tabl-tab.mkii
index e3bfca9c3ad..7909e509284 100644
--- a/Master/texmf-dist/tex/context/base/tabl-tab.mkii
+++ b/Master/texmf-dist/tex/context/base/tabl-tab.mkii
@@ -5,7 +5,7 @@
%D subtitle=\TABLE\ Embedding,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-tab.mkiv b/Master/texmf-dist/tex/context/base/tabl-tab.mkiv
index 24bbb4dd607..b50be8531ef 100644
--- a/Master/texmf-dist/tex/context/base/tabl-tab.mkiv
+++ b/Master/texmf-dist/tex/context/base/tabl-tab.mkiv
@@ -4,8 +4,7 @@
%D title=\CONTEXT\ Table Macros,
%D subtitle=\TABLE\ Embedding,
%D author=Hans Hagen with copied and patched code from MJ Wichura,
-%D date=\currentdate,
-%D copyright=PRAGMA-ADE (patched and extensions)]
+%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
@@ -894,7 +893,7 @@
\def\@VLd{.125em}
-\def\do!ttInsertVrule % will be merged in 2005
+\def\do!ttInsertVrule
{\vrule\!!width
\ifnum\!tgCode=\plusone
\ifx\!tgValue\empty
@@ -984,6 +983,9 @@
\def\donormaltableshortrule % was: \!ttShortHrule
{\omit
\!ttGetHalfRuleThickness
+ \ifx\tablecurrenthrulecolor\empty\else
+ \switchtocolor[\tablecurrenthrulecolor]% see *DL*
+ \fi
\leaders\hrule\!!height\scratchdimen\!!depth\scratchdimen\hfill
\emptyhbox
\ignorespaces}
@@ -1166,10 +1168,9 @@
%D \stoptable
%D \stopbuffer
%D
-%D \startcombination
-%D {\tracetablesfalse\getbuffer} {\type{\tracetablesfalse}}
-%D {\tracetablestrue\getbuffer} {\type{\tracetablestrue}}
-%D \stopcombination
+%D \startlinecorrection
+%D \getbuffer
+%D \stoplinecorrection
%D
%D This table is specified as:
%D
@@ -1190,37 +1191,9 @@
%D \VL beta \VL 2 \VL\AR
%D \VL gamma \VL 3 \VL\AR
%D \HL
-%D \stoptable
-%D \stopbuffer
-%D
-%D When we use the split table feature, we get a bit more
-%D information.
-%D
-%D {\tracetablesfalse\getbuffer}
-%D
-%D Sometimes in tables information shows up that is not typed
-%D in by the user. These messages give a cue in what aspect a
-%D table definition is wrong.
-%D
-%D \startbuffer
-%D \starttable[||||]
-%D \HL
-%D \VL first second \VL third \VL\AR
-%D \HL
-%D \VL alfa \VL 1 \VL a \VL\AR
-%D \VL beta \VL 2 \VL b \VL
-%D \VL gamma \VL \THREE{3} c \VL\AR
-%D \HL
-%D \stoptable
+%D \stoptables
%D \stopbuffer
%D
-%D \typebuffer
-%D
-%D Those terrible table has three errors, which all show up in
-%D typeset messages. Errors cannot always recovered 100\% and
-%D therefore can result in two or more succesive messages, like
-%D in the last row.
-%D
%D \getbuffer
%D
%D Some simple color support is provided:
@@ -1239,7 +1212,8 @@
%D
%D \typebuffer \getbuffer
-\def\s!TaBlE{TaBlE}
+\installcorenamespace{tabletemplate}
+
\def\m!TABLE{TABLE}
%D We already saw that the table macros report errors and
@@ -1293,16 +1267,14 @@
%D instead of brackets because we need brackets to specify the
%D format.
%D
-%D \startbuffer
+%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 \stopbuffer
-%D
-%D \ShowExample
+%D \stoptyping
%D
%D Although a more efficient implementation is possible |<|we
%D can for instance share common macros|>| we just adapt a copy
@@ -1383,7 +1355,7 @@
% We cannot define \unexpanded\def\dostoptable a ssomehow lookahead
% in alignments fail then, so we relax it and define it locally.
-\let\stoptabel\relax
+\let\stoptable\relax
\def\dostoptable
{\dochucktableautorow % before the tail, else noalign problem
@@ -1404,7 +1376,7 @@
%D Before we can grab the argument, we have to make sure that
%D the \CATCODES\ are set. The first stage takes care of that.
-\def\firststagestarttable%
+\def\firststagestarttable
{\bgroup
\global\intabletrue
\secondstagestarttable}
@@ -1428,6 +1400,9 @@
%D The implementation of the definition macro is not that
%D complicated:
+\installcorenamespace{tablehead}
+\installcorenamespace{tabletail}
+
\unexpanded\def\definetabletemplate % to be redone
{\bgroup
\catcode\barasciicode\othercatcode
@@ -1435,13 +1410,13 @@
\def\dodefinetabletemplate[#1][#2][#3][#4]%
{\ifsecondargument
- \setgvalue{\s!TaBlE#1}{\dousetabletemplate{#2}{#3}{#4}}%
+ \setgvalue{\??tabletemplate#1}{\dousetabletemplate{#2}{#3}{#4}}%
\fi
\egroup}
\def\dousetabletemplate#1#2#3%
- {\gdef\dotablehead{\getvalue{@@tablehead#2}}%
- \gdef\dotabletail{\getvalue{@@tabletail#3}}%
+ {\gdef\dotablehead{\executeifdefined{\??tablehead#2}\empty}%
+ \gdef\dotabletail{\executeifdefined{\??tabletail#3}\empty}%
\secondstagestarttable[#1]}
%D The optional third and fourth arguments define which table
@@ -1521,9 +1496,9 @@
\global\setfalse\hassometabletail
\expanded{\doifinstringelse{|}{#1}}
{\xdef\restarttable{\noexpand\dorestarttable{\noexpand\thirdstagestarttable{#1}}}}
- {\doifdefinedelse{\s!TaBlE#1}
- {\gdef\restarttable{\getvalue{\s!TaBlE#1}}}
- {\gdef\restarttable{\dorestartable{\getvalue{#1}}}}}%
+ {\doifdefinedelse{\??tabletemplate#1}
+ {\gdef\restarttable{\getvalue{\??tabletemplate#1}}}
+ {\gdef\restarttable{\dorestarttable{\getvalue{#1}}}}}%
\egroup
\restarttable}
@@ -1683,10 +1658,10 @@
\def\settablehead{\dodoubleempty\dosettablehead}
\def\settabletail{\dodoubleempty\dosettabletail}
-\long\def\dosettablehead[#1][#2]#3\end{\setvalue{@@tablehead#1}{\tablenoalign{\global\settrue\hassometablehead}#3}}
-\long\def\dosettabletail[#1][#2]#3\end{\setvalue{@@tabletail#1}{\tablenoalign{\global\settrue\hassometabletail}#3}}
+\long\def\dosettablehead[#1][#2]#3\end{\setvalue{\??tablehead#1}{\tablenoalign{\global\settrue\hassometablehead}#3}}
+\long\def\dosettabletail[#1][#2]#3\end{\setvalue{\??tabletail#1}{\tablenoalign{\global\settrue\hassometabletail}#3}}
-%D Redudant \type{\HL}'s are removed automatically, so
+%D Redundant \type{\HL}'s are removed automatically, so
%D mid||lines can be used without problems.
%D The order of the next macros is more or less random. First
@@ -2087,9 +2062,9 @@
\unexpanded\def\dotableDL
{\dochecktabledivision
- \dosingleempty\dotableDL}
+ \dosingleempty\dodotableDL}
-\def\dotableDL[#1]%
+\def\dodotableDL[#1]%
{\ifnum\tableactionstate=\tablerulestate
\writestatus\m!TABLE{skipping \string\DL}%
\else
@@ -2104,9 +2079,9 @@
\iffirstargument
\global\let\tablecurrenthrulecolor\empty
\rawprocesscommalist[#1]\dotabledrulecommand
- \ifx\tablecurrenthrulecolor\empty\else
- \switchtocolor[\tablecurrenthrulecolor]%
- \fi
+ % \ifx\tablecurrenthrulecolor\empty\else
+ % \switchtocolor[\tablecurrenthrulecolor]% see *DL*
+ % \fi
\fi
\ifcase\tabledrulespan
\global\advance\currenttablecolumn \plusone
@@ -2202,7 +2177,7 @@
\def\dolocaltablesetup
{\@@ticommands\relax
- \expanded{\switchtobodyfont[\@@tibodyfont]}% expanded ?
+ \doifsomething\@@tibodyfont{\switchtobodyfont[\@@tibodyfont]}%
\tablelinethicknessunit\dimexpr\@@tirulethickness/\tablelinethicknessfactor\relax
\doifelse\@@tiheight\v!strut
{\let\tablestrutheightfactor\tablestrutheightfactor}
@@ -2279,7 +2254,7 @@
\c!rulethickness=\linewidth,
\c!rulecolor=,
\c!distance=\v!medium,
- \c!bodyfont=\the\bodyfontsize,
+ \c!bodyfont=,
\c!commands=,
\c!background=\v!screen,
\c!backgroundscreen=\@@rsscreen,
diff --git a/Master/texmf-dist/tex/context/base/tabl-tbl.lua b/Master/texmf-dist/tex/context/base/tabl-tbl.lua
index 86968721b86..c48c5100d14 100644
--- a/Master/texmf-dist/tex/context/base/tabl-tbl.lua
+++ b/Master/texmf-dist/tex/context/base/tabl-tbl.lua
@@ -10,7 +10,7 @@ if not modules then modules = { } end modules ['tabl-tbl'] = {
-- TeX. More will follow.
local tonumber = tonumber
-local gsub, rep, sub = string.gsub, string.rep, string.sub
+local gsub, rep, sub, find = string.gsub, string.rep, string.sub, string.find
local P, C, Cc, Ct, lpegmatch = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.match
@@ -21,17 +21,20 @@ local nested = lpeg.patterns.nested
local pattern = Ct((separator * (C(nested) + Cc("")) * C((1-separator)^0))^0)
function commands.presettabulate(preamble)
- -- todo: lpeg but not now
- preamble = gsub(preamble, "%*(%b{})(%b{})", function(n,p)
- return rep(sub(p,2,-2),tonumber(sub(n,2,-2)) or 1)
- end)
+ preamble = gsub(preamble,"~","d") -- let's get rid of ~ mess here
+ if find(preamble,"%*") then
+ -- todo: lpeg but not now
+ preamble = gsub(preamble, "%*(%b{})(%b{})", function(n,p)
+ return rep(sub(p,2,-2),tonumber(sub(n,2,-2)) or 1)
+ end)
+ end
local t = lpegmatch(pattern,preamble)
local m = #t - 2
- settexcount("global","noftabulatecolumns", m/2)
- settexcount("global","tabulatehasfirstrulespec", t[1] == "" and 0 or 1)
- settexcount("global","tabulatehaslastrulespec", t[m+1] == "" and 0 or 1)
+ settexcount("global","c_tabl_tabulate_nofcolumns", m/2)
+ settexcount("global","c_tabl_tabulate_has_rule_spec_first", t[1] == "" and 0 or 1)
+ settexcount("global","c_tabl_tabulate_has_rule_spec_last", t[m+1] == "" and 0 or 1)
for i=1,m,2 do
context.settabulateentry(t[i],t[i+1])
end
- context.setlasttabulateentry(t[m+1])
+ context.settabulatelastentry(t[m+1])
end
diff --git a/Master/texmf-dist/tex/context/base/tabl-tbl.mkii b/Master/texmf-dist/tex/context/base/tabl-tbl.mkii
index 09fa4105c53..9f2d7df475c 100644
--- a/Master/texmf-dist/tex/context/base/tabl-tbl.mkii
+++ b/Master/texmf-dist/tex/context/base/tabl-tbl.mkii
@@ -5,7 +5,7 @@
%D subtitle=Text Flow Tabulation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-tbl.mkiv b/Master/texmf-dist/tex/context/base/tabl-tbl.mkiv
index b8ebb5ee7c9..ab4005fb7ee 100644
--- a/Master/texmf-dist/tex/context/base/tabl-tbl.mkiv
+++ b/Master/texmf-dist/tex/context/base/tabl-tbl.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Text Flow Tabulation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,28 +19,17 @@
%D I can probably reimplement this using a \LUATEX\ combination
%D but it does not pay of in development time. If I need something
-%D else I will write it from scratch anyway.
+%D else I will write it from scratch anyway. This module looks
+%D a bit complex which is a consequence of it dealing with paragraphs
+%D being split over pages and that there are several passes over the
+%D data set. We can probably do some cleanup (combine/split).
%D
-%D I never really looked at the preamble code of TaBlE (at that time
-%D I simply didn't look into alignments too much) but there seem to
-%D be some similarities with the following code. So, maybe it's not
-%D too much work to rewrite that package in a more contexty style. If
-%D it makes sense to do that remains to be seen. We might as well
-%D drop it.
-%D
-%D Be careful with changing the hsize calculation in p mode;
-%D the following code works quite well:
-%D
-%D \starttyping
-%D \setupfield [line][location=low,height=1.2\lineheight,width=\hsize]
-%D \definefield [test] [line] [line] []
-%D
-%D \starttabulate[|l|p|]
-%D \NC test \NC \field [test] \NC \NR
-%D \stoptabulate
-%D \stoptyping
+%D Caching the preamble does not save much (compared to other
+%D bits and pieces of \CONTEXT). There are not that many ways to
+%D deal with preambles and this is just one of them. The keys are
+%D somewhat similar to those of the \TABLE\ package.
-% |p2|p3| 2:3 -> spanning
+% |p2|p3| 2:3 -> spanning (maybe)
%
% In-text tabbing environment
%
@@ -72,6 +61,7 @@
% i i<n> skip left of column
% j i<n> skip right of column
% k i<n> skip around column
+% d digits (~)
%
% C [C\L\M\R] {color}
%
@@ -112,7 +102,8 @@
% \EQ \RQ \HQ equal (raw, hook)
% \NC \RC \HC normal (raw, hook)
%
-% \NR
+% \NR checked break
+% \NB no break
%
% \HR : rule with lineheight
%
@@ -156,392 +147,503 @@
% \NC 500 \NC \NC 20 \NC \NC 100 \NC \NR
% \stoptabulate
-\newtoks \tabulatepreamble
-\newtoks \tabulatebefore
-\newtoks \tabulateafter
-\newtoks \tabulatebmath
-\newtoks \tabulateemath
-\newtoks \tabulatefont
-\newtoks \tabulatesettings
-\newtoks \tabulatedummy
-
-\newcount \nofautotabulate
-\newcount \tabulatecolumns
-\newcount \tabulatecolumn
-
-\newcount \noftabulatecolumns % set by parser
-
-\newcount \tabulateminplines
-\newcount \tabulatemaxplines
-
-\newif \iftracetabulate
-
-\newconditional \tabulatenopbreak
-\newconditional \tabulatefirstflushed
-\newconditional \tabulateequal
-\newconditional \tabulatesplit \settrue\tabulatesplit
-\newconditional \tabulateautomode
-\newconditional \tabulatehandlepbreak \settrue\tabulatehandlepbreak
-
-\newdimen \tabulatepwidth
-\newdimen \tabulatexwidth
-\newdimen \tabulatewidth
-\newdimen \tabulateunit
-\newdimen \tabulatemaxpheight
-
-\newskip \tabulatepreskip
-\newskip \tabulateposskip
-\newskip \firstpretabskip
-\newskip \lastposttabskip
-
-\newbox \tabulatebox
-
-\newtoks \everytabulaterow
-\newtoks \everytabulatepar
-\newtoks \everyaftertabulaterow
-\newtoks \everytabulate
-
-\newconditional \tabulateautorulespacing \settrue\tabulateautorulespacing
-\newcount \tabulatehasfirstrulespec % for the moment a count
-\newcount \tabulatehaslastrulespec % for the moment a count
-\newconditional \tabulatesomeamble
-\newconstant \tabulatepass
-
-\setnewconstant \tabulatesplitlinemode \plusone
-
-\newconstant \tabulatecolorspan
-\newconstant \tabulatelocalcolorspan
-
-\newdimen \defaulttabulatevrulethickness
-\newdimen \defaulttabulatehrulethickness
-\newdimen \tabulatevrulethickness
-\newdimen \tabulatehrulethickness
-\newdimen \tabulatelocalvrulethickness
-\newdimen \tabulatelocalhrulethickness
+\newtoks \t_tabl_tabulate_preamble
+\newtoks \t_tabl_tabulate_before
+\newtoks \t_tabl_tabulate_after
+\newtoks \t_tabl_tabulate_bmath
+\newtoks \t_tabl_tabulate_emath
+\newtoks \t_tabl_tabulate_font
+\newtoks \t_tabl_tabulate_settings
+\newtoks \t_tabl_tabulate_dummy
+\newtoks \t_tabl_tabulate_every_row
+\newtoks \t_tabl_tabulate_every_after_row
+
+\newtoks \t_tabl_tabulate_initializers_first
+\newtoks \t_tabl_tabulate_initializers_second
+
+\newcount \c_tabl_tabulate_nofauto
+\newcount \c_tabl_tabulate_columns
+\newcount \c_tabl_tabulate_column
+\newcount \c_tabl_tabulate_plines_min
+\newcount \c_tabl_tabulate_plines_max
+\newcount \c_tabl_tabulate_max_colorcolumn
+\newcount \c_tabl_tabulate_repeathead
+\newcount \c_tabl_tabulate_noflines
+\newcount \c_tabl_tabulate_totalnoflines
+\newcount \c_tabl_tabulate_minusnoflines
+\newcount \c_tabl_tabulate_align
+
+\newcount \c_tabl_tabulate_nofcolumns % set at the lua end by parser
+\newcount \c_tabl_tabulate_has_rule_spec_first % set at the lua end by parser (for the moment a count)
+\newcount \c_tabl_tabulate_has_rule_spec_last % set at the lua end by parser (for the moment a count)
+
+\newconditional \c_tabl_tabulate_nopbreak
+\newconditional \c_tabl_tabulate_firstflushed
+\newconditional \c_tabl_tabulate_equal
+\newconditional \c_tabl_tabulate_split \settrue\c_tabl_tabulate_split
+\newconditional \c_tabl_tabulate_automode
+\newconditional \c_tabl_tabulate_handlepbreak \settrue\c_tabl_tabulate_handlepbreak
+\newconditional \c_tabl_tabulate_autorulespacing \settrue\c_tabl_tabulate_autorulespacing
+\newconditional \c_tabl_tabulate_someamble
+\newconditional \c_tabl_tabulate_has_colors
+\newconditional \c_tabl_tabulate_tolerant_break
+\newconditional \c_tabl_tabulate_splitoff_whitespace
+\newconditional \c_tabl_tabulate_pwidth_set
+\newconditional \c_tabl_tabulate_reshape
+
+\newdimen \d_tabl_tabulate_width_p
+\newdimen \d_tabl_tabulate_width_w
+\newdimen \d_tabl_tabulate_width
+\newdimen \d_tabl_tabulate_unit
+\newdimen \d_tabl_tabulate_height_p_max
+\newdimen \d_tabl_tabulate_vrulethickness_default
+\newdimen \d_tabl_tabulate_hrulethickness_default
+\newdimen \d_tabl_tabulate_vrulethickness
+\newdimen \d_tabl_tabulate_hrulethickness % not used
+\newdimen \d_tabl_tabulate_vrulethickness_local
+\newdimen \d_tabl_tabulate_hrulethickness_local
+\newdimen \d_tabl_tabulate_indent
+\newdimen \d_tabl_tabulate_splitoff_betweenskip
+\newdimen \d_tabl_tabulate_margin
+
+\newskip \s_tabl_tabulate_pre
+\newskip \s_tabl_tabulate_post
+\newskip \s_tabl_tabulate_first
+\newskip \s_tabl_tabulate_last
+\newskip \s_tabl_tabulate_separator
+
+\newbox \b_tabl_tabulate
+
+\newconstant \c_tabl_tabulate_pass
+\newconstant \c_tabl_tabulate_type
+\newconstant \c_tabl_tabulate_splitlinemode \c_tabl_tabulate_splitlinemode\plusone
+\newconstant \c_tabl_tabulate_colorspan
+\newconstant \c_tabl_tabulate_localcolorspan
+\newconstant \c_tabl_tabulate_modus
+
+\let \m_tabl_tabulate_separator_factor \empty % fraction
+
+\newif \iftracetabulate % will become a tracker
+\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
+
+\installcorenamespace{tabulatealign}
+\installcorenamespace{tabulatebox}
+\installcorenamespace{tabulatesetup}
+\installcorenamespace{tabulatehook}
+\installcorenamespace{tabulatesplit}
+\installcorenamespace{tabulateseparator}
+\installcorenamespace{tabulatecolor}
+\installcorenamespace{tabulateheader}
+\installcorenamespace{tabulatealigning}
+\installcorenamespace{tabulatepreamble}
+
+\installcorenamespace{tabulatehead}
+\installcorenamespace{tabulatefoot}
+\installcorenamespace{tabulatenext}
+
+\def\b_tabl_tabulate_current#1%
+ {\csname\??tabulatebox\number#1\endcsname} % beware, a synonym
+
+\def\tabl_tabulate_initialize_boxes#1%
+ {\scratchcounter#1\relax
+ \tabl_tabulate_initialize_boxes_step}
-\newskip \tabulateseparatorskip
+\def\tabl_tabulate_initialize_boxes_step
+ {\ifnum\scratchcounter>\zerocount
+ \tabl_tabulate_initialize_box\scratchcounter
+ \advance\scratchcounter\minusone
+ \expandafter\tabl_tabulate_initialize_boxes_step
+ \fi}
-\newcount \maxtabularcolorcolumn
+\def\tabl_tabulate_initialize_box#1% also used elsewhere
+ {\ifcsname\??tabulatebox\number#1\endcsname
+ \tabl_tabulate_initialize_box_yes#1%
+ \else
+ \tabl_tabulate_initialize_box_nop#1%
+ \fi}
-\newif \iftolerantTABLEbreak % used in styles !
+\def\tabl_tabulate_initialize_box_yes#1{\global \setbox\csname\??tabulatebox\number#1\endcsname\emptybox}
+\def\tabl_tabulate_initialize_box_nop#1{\expandafter\newbox\csname\??tabulatebox\number#1\endcsname}
-\newcount \tabulaterepeathead
-\newcount \noftabulatelines
-\newcount \totalnoftabulatelines
-\newcount \minusnoftabulatelines
+\tabl_tabulate_initialize_boxes{16} % not really needed
-\newconstant \tabulatetype
+\let\initializetablebox \tabl_tabulate_initialize_box % used elsewhere, will change
+\let\initializetableboxes\tabl_tabulate_initialize_boxes % used elsewhere, will change
+\let\tablebox \b_tabl_tabulate_current
% 0 = NC column next EQ equal column
% 1 = RC column raw RQ equal column raw
% 2 = HC column hook HQ equal column hook
-% for old times sake:
-
-\def\handletabulatepbreakfalse{\setfalse\tabulatehandlepbreak} % depricated
-
% handy helper
-\def\tabulatenoalign
+\def\tabulatenoalign % public ?
{\noalign
\bgroup
\let\noalign\relax
\let\tabulatenoalign\relax
\let\next=}
-\def\starttabulatenoalign
+\def\starttabulatenoalign % public ?
{\tabulatenoalign\bgroup}
\let\stoptabulatenoalign\egroup
% [|lg{.}|] => \NG 12.34 \NC
-\gdef\handletabulatecharalign#1 % space delimited ! (will be redone in lua)
- {\edef\alignmentclass{\the\tabulatecolumn}%
- \edef\alignmentcharacter{\csname\??tt:a:\the\tabulatecolumn\endcsname}%
- \ifcase\tabulatepass\or
+\def\tabl_tabulate_charalign#1 % space delimited ! (will be redone in lua)
+ {\edef\alignmentclass{\the\c_tabl_tabulate_column}%
+ \edef\alignmentcharacter{\csname\??tabulatealign\the\c_tabl_tabulate_column\endcsname}%
+ \ifcase\c_tabl_tabulate_pass\or
\setfirstpasscharacteralign\checkalignment{#1}%
\fi % force hsize
\setsecondpasscharacteralign\checkalignment{#1}}
-\def\noftabcolumns{16}
-
-\def\tablebox#1%
- {\csname\??tt:b:\number#1\endcsname}
-
-\def\initializetablebox#1% also used elsewhere
- {\ifcsname\??tt:b:\number#1\endcsname
- \global\setbox\csname\??tt:b:\number#1\endcsname\emptybox
- \else
- \expandafter\newbox\csname\??tt:b:\number#1\endcsname
- \fi}
-
-\def\initializetableboxes#1%
- {\scratchcounter#1\relax
- \doinitializetableboxes}
+\def\tabl_tabulate_nobreak_inject_tracer
+ {\red % maybe use the fast color switcher here
+ \hrule\!!height.5\linewidth\!!depth.5\linewidth
+ \par
+ \kern-\linewidth
+ \nobreak}
-\def\doinitializetableboxes
- {\ifnum\scratchcounter>\zerocount
- \initializetablebox\scratchcounter
- \advance\scratchcounter\minusone
- \expandafter\doinitializetableboxes
- \fi}
-
-\initializetableboxes\noftabcolumns
-
-\def\dodotabulatenobreak
+\def\tabl_tabulate_nobreak_inject_indeed
{\nobreak
\iftracetabulate
- \red\hrule\!!height.5\linewidth\!!depth.5\linewidth
- \par
- \kern-\linewidth
- \nobreak
+ \tabl_tabulate_nobreak_inject_tracer
\fi}
-\def\dotabulatenobreak
- {\tabulatenoalign{\dodotabulatenobreak}}
+\def\tabl_tabulate_nobreak_inject
+ {\tabulatenoalign{\tabl_tabulate_nobreak_inject_indeed}}
-\unexpanded\def\notabulatehook
- {}
-
-\unexpanded\def\checktabulatehook
- {\ifnum\tabulatetype<\plustwo
- \glet\tabulatehook\notabulatehook
+\unexpanded\def\tabl_tabulate_hook_check
+ {\ifnum\c_tabl_tabulate_type<\plustwo
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
\else
- \glet\tabulatehook\dotabulatehook
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
\fi}
-\unexpanded\def\checktabulatesetups
- {\csname\??tt:s:\the\tabulatecolumn\endcsname}
+\unexpanded\def\tabl_tabulate_setups_check
+ {\csname\??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}
-\unexpanded\def\beforetabulateentry{\ignorespaces\tabulatehook}
-\unexpanded\def\aftertabulateentry {\unskip\unskip\ifmmode\else\endgraf\fi}
+\unexpanded\def\tabl_tabulate_shaped_par_begin
+ {\dowithnextboxcs\tabl_tabulate_shaped_par_finish\vbox\bgroup}
-\unexpanded\def\beginreshapedtabulatepar
- {\dowithnextbox
- {\ctxcommand{doreshapeframedbox(\number\nextbox)}\ifvmode\unvbox\else\box\fi\nextbox}
- \vbox\bgroup}
+\def\tabl_tabulate_shaped_par_finish
+ {\ctxcommand{doreshapeframedbox(\number\nextbox)}%
+ \ifvmode\unvbox\else\box\fi\nextbox}
-\let\endreshapedtabulatepar\egroup
+\let\tabl_tabulate_shaped_par_end\egroup
-\let\dotagtabulatealign\relax
+\ifdefined\dotagtabulatecell \else \let\dotagtabulatecell \relax \fi
+\ifdefined\dotagtabulatesignal \else \let\dotagtabulatesignal\relax \fi
-\unexpanded\def\dochecklocaltabulatecolor#1#2%
+\unexpanded\def\tabl_tabulate_check_local_color_first#1#2%
+ {\relax}
+
+\unexpanded\def\tabl_tabulate_check_local_color_second#1#2%
{\relax
- \ifx\currenttabulatelocalcolor\empty
- \gdef\currenttabulatecolor{#1}%
+ \ifx\m_tabl_tabulate_color_local\empty
+ \xdef\m_tabl_tabulate_color{#1}%
\else
- \global\let\currenttabulatecolor\currenttabulatelocalcolor
- \global\let\currenttabulatelocalcolor\empty
+ \global\let\m_tabl_tabulate_color\m_tabl_tabulate_color_local
+ \global\let\m_tabl_tabulate_color_local\empty
\fi
- \ifcase\tabulatelocalcolorspan
- \global\tabulatecolorspan#2\relax
+ \ifcase\c_tabl_tabulate_localcolorspan
+ \global\c_tabl_tabulate_colorspan#2\relax
\else
- \global\tabulatecolorspan\tabulatelocalcolorspan
- \global\tabulatelocalcolorspan\zerocount
+ \global\c_tabl_tabulate_colorspan\c_tabl_tabulate_localcolorspan
+ \global\c_tabl_tabulate_localcolorspan\zerocount
\fi}
-\unexpanded\def\dochecklocaltabulatevrulecolor#1#2%
+\unexpanded\def\tabl_tabulate_check_local_vrule_thickness#1%
{\relax
- \ifx\currenttabulatelocalvrulecolor\empty
- \gdef\currenttabulatevrulecolor{#1}%
+ \ifcase\d_tabl_tabulate_vrulethickness_local
+ \global\d_tabl_tabulate_vrulethickness#1\relax
\else
- \global\let\currenttabulatevrulecolor\currenttabulatelocalvrulecolor
- \global\let\currenttabulatelocalvrulecolor\empty
- \fi
- \ifcase\tabulatelocalvrulethickness
- \global\tabulatevrulethickness#2\relax
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_local
+ \global\d_tabl_tabulate_vrulethickness_local\zeropoint
+ \fi}
+
+\unexpanded\def\tabl_tabulate_check_local_vrule_color_first#1%
+ {\relax}
+
+\unexpanded\def\tabl_tabulate_check_local_vrule_color_second#1%
+ {\relax
+ \ifx\m_tabl_tabulate_vrule_color_local\empty
+ \gdef\m_tabl_tabulate_vrule_color{#1}%
\else
- \global\tabulatevrulethickness\tabulatelocalvrulethickness
- \global\tabulatelocalvrulethickness\zeropoint
+ \global\let\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local
+ \global\let\m_tabl_tabulate_vrule_color_local\empty
\fi}
-\unexpanded\def\dotabulatepreskip#1%
+\let\tabl_tabulate_check_local_color \gobbletwoarguments
+\let\tabl_tabulate_check_local_vrule_color\gobbleoneargument
+
+\appendtoks
+ \let\tabl_tabulate_check_local_color \tabl_tabulate_check_local_color_first
+ \let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_check_local_color \tabl_tabulate_check_local_color_second
+ \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
+\def\tabl_tabulate_inject_pre_skip#1%
{\ifdim#1>\zeropoint
\hskip#1\relax
- \else\ifnum\tabulatecolumn=\zerocount
- \ifconditional\tabulateautorulespacing
- \ifcase\tabulatehasfirstrulespec\else
- \hskip\firstpretabskip\relax
+ \else\ifnum\c_tabl_tabulate_column=\zerocount
+ \ifconditional\c_tabl_tabulate_autorulespacing
+ \ifcase\c_tabl_tabulate_has_rule_spec_first\else
+ \hskip\s_tabl_tabulate_first\relax
\fi
\fi
\fi\fi}
-\unexpanded\def\dotabulatepostskip#1%
+% \unexpanded % we can expand this one
+\def\tabl_tabulate_inject_post_skip#1%
{\ifdim#1>\zeropoint
\hskip#1\relax
- \else\ifnum\tabulatecolumns=\noftabulatecolumns
- \ifconditional\tabulateautorulespacing
- \ifcase\tabulatehaslastrulespec\else
- \hskip\lastposttabskip\relax
+ \else\ifnum\c_tabl_tabulate_columns=\c_tabl_tabulate_nofcolumns
+ \ifconditional\c_tabl_tabulate_autorulespacing
+ \ifcase\c_tabl_tabulate_has_rule_spec_last\else
+ \hskip\s_tabl_tabulate_last\relax
\fi
\fi
\fi\fi}
-\def\dodosettabulatepreamble#1#2% only makes sense for many tabulates
- {\normalexpanded{\tabulatepreamble{\the\tabulatepreamble
- \dochecklocaltabulatevrulecolor{\currenttabulatevrulecolor}{\the\tabulatevrulethickness}%
- \dochecklocaltabulatecolor{\currenttabulatecolor}{\number\tabulatecolorspan}%
- \dorightsidetabulatecolor
+\let\tabl_tabulate_hook_b\donothing
+\let\tabl_tabulate_hook_e\donothing
+
+\def\tabl_tabulate_set_preamble_step#1#2% only makes sense for many tabulates
+ {\normalexpanded{\t_tabl_tabulate_preamble{\the\t_tabl_tabulate_preamble
+ \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
+ \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
+ \tabl_tabulate_check_local_color\constantemptyargument\m_tabl_tabulate_color\constantnumberargument\c_tabl_tabulate_colorspan
+ \tabl_tabulate_color_side_right
\aligntab
- \dotabulatevrule
- \doleftsidetabulatecolor
- \dotabulatepreskip{\the\tabulatepreskip}%
+ \tabl_tabulate_column_vrule_inject
+ \tabl_tabulate_color_side_left
+ \tabl_tabulate_inject_pre_skip{\the\s_tabl_tabulate_pre}%
\alignmark\alignmark
\aligntab
- \dobothsidetabulatecolor
- \global\tabulatecolorspan\zerocount
- \global\tabulatecolumn\the\tabulatecolumns\relax
- \checktabulatesetups % unexpandable
- \checktabulatehook % unexpandable
- \ifzeropt\tabulatewidth
- \ifcase\tabulatemodus\else
- \noexpand\settrue\noexpand\tabulateautomode
+ \tabl_tabulate_color_side_both
+ \global\c_tabl_tabulate_colorspan\zerocount
+ \global\c_tabl_tabulate_column\constantnumber\c_tabl_tabulate_columns
+ \tabl_tabulate_setups_check % unexpandable
+ \tabl_tabulate_hook_check % unexpandable
+ \ifzeropt\d_tabl_tabulate_width
+ \ifcase\c_tabl_tabulate_modus\else
+ \settrue\c_tabl_tabulate_automode
\fi
\else
- \ifnum\tabulatemodus=\zerocount
+ \ifcase\c_tabl_tabulate_modus
\hbox to
\else
\hsize
\fi
- \the\tabulatewidth
+ \the\d_tabl_tabulate_width
\fi
\bgroup
- \noexpand\bbskip
+ \tabl_tabulate_bbskip
\bgroup % we cannot combine the if because a cell may have only one ##
+\tabl_tabulate_hook_b
+ \c_tabl_tabulate_align\constantnumber\c_tabl_tabulate_align % needed in tag passing
\noexpand\dostarttagged\noexpand\t!tabulatecell\noexpand\empty
- \dotagtabulatealign
+ \noexpand\dotagtabulatecell
\noexpand#1%
- \ifcase\tabulatereshape\else
- \beginreshapedtabulatepar
+ \ifconditional\c_tabl_tabulate_reshape
+ \tabl_tabulate_shaped_par_begin
\fi
- \noexpand\ifnum\noexpand\tabulatetype=\plusone\noexpand\else
- \the\tabulatebmath % maybe later?
- \the\tabulatefont
- \the\tabulatesettings
- \the\tabulatebefore
+ \dotagtabulatesignal % empty cells .. todo (can be removed as soon as build)
+ \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
+ \the\t_tabl_tabulate_bmath % maybe later? can interfere with char 0
+ \the\t_tabl_tabulate_font
+ \the\t_tabl_tabulate_settings
+ \the\t_tabl_tabulate_before
\noexpand\fi
% grouping needs to be outside macros (or expandable), nice test
% example \NC \string \aligntab \NC which will fail otherwise (mk)
\bgroup
- \beforetabulateentry
+ \tabl_tabulate_entry_before
\alignmark\alignmark
- \aftertabulateentry
+ \tabl_tabulate_entry_after
\egroup
- \noexpand\ifnum\noexpand\tabulatetype=\plusone\noexpand\else
- \the\tabulateafter
- \the\tabulateemath
+ \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
+ \the\t_tabl_tabulate_after
+ \the\t_tabl_tabulate_emath
\noexpand\fi
- \ifcase\tabulatereshape\else
- \endreshapedtabulatepar
+ \ifconditional\c_tabl_tabulate_reshape
+ \tabl_tabulate_shaped_par_end
\fi
\noexpand#2%
- \noexpand\dostoptagged
+\tabl_tabulate_hook_e
\egroup
\egroup
\aligntab
- \dotabulatepostskip{\the\tabulateposskip}%
+ \noexpand\dostoptagged
+ \tabl_tabulate_inject_post_skip{\the\s_tabl_tabulate_post}%
\alignmark\alignmark
}}%
- \appendtoks\NC\to\tabulatedummy
- \tabulatepreskip.5\tabulateunit\relax
- \ifnum\tabulatecolumns<\numexpr\noftabulatecolumns-\plusone\relax
- \tabulateposskip\tabulatepreskip
+ \t_tabl_tabulate_dummy\expandafter{\the\t_tabl_tabulate_dummy\NC}%
+ \s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\relax
+ \ifnum\c_tabl_tabulate_columns<\numexpr\c_tabl_tabulate_nofcolumns-\plusone\relax
+ \s_tabl_tabulate_post\s_tabl_tabulate_pre
\else
- \tabulateposskip\zeropoint
+ \s_tabl_tabulate_post\zeropoint
\fi
%\let\gettabulateexit\dogettabulateexit % still needed ?
- \tabulatewidth\zeropoint}
-
-\setvalue{\??tt>\meaning x}{\let\tabulatealign\zerocount\settabulatepreamble} % internal
-\setvalue{\??tt>\meaning l}{\let\tabulatealign\plusone\settabulatepreamble}
-\setvalue{\??tt>\meaning r}{\let\tabulatealign\plustwo\settabulatepreamble}
-\setvalue{\??tt>\meaning c}{\let\tabulatealign\plusthree\settabulatepreamble}
-\setvalue{\??tt>\meaning p}{\gettabulateparagraph}
-\setvalue{\??tt>\meaning s}{\gettabulatesetups}
-\setvalue{\??tt>\meaning w}{\gettabulatewidth}
-\setvalue{\??tt>\meaning f}{\gettabulatefont}
-\setvalue{\??tt>\meaning B}{\tabulatefont{\bf}\settabulatepreamble}
-\setvalue{\??tt>\meaning I}{\tabulatefont{\it}\settabulatepreamble}
-\setvalue{\??tt>\meaning S}{\tabulatefont{\sl}\settabulatepreamble}
-\setvalue{\??tt>\meaning T}{\tabulatefont{\tt}\settabulatepreamble}
-\setvalue{\??tt>\meaning R}{\tabulatefont{\rm}\settabulatepreamble}
-\setvalue{\??tt>\meaning m}{\tabulatebmath{$}\tabulateemath{$}\settabulatepreamble}
-\setvalue{\??tt>\meaning M}{\tabulatebmath{$\displaystyle}\tabulateemath{$}\settabulatepreamble}
-\setvalue{\??tt>\meaning h}{\gettabulatehook}
-\setvalue{\??tt>\meaning b}{\gettabulatebefore}
-\setvalue{\??tt>\meaning a}{\gettabulateafter}
-\setvalue{\??tt>\meaning i}{\gettabulatepreskip}
-\setvalue{\??tt>\meaning j}{\gettabulateposskip}
-\setvalue{\??tt>\meaning k}{\gettabulatepreposskip}
-\setvalue{\??tt>\meaning e}{\appendtoks\global\settrue\tabulateequal\to\tabulatesettings\settabulatepreamble}
-\setvalue{\??tt>\meaning ~}{\appendtoks\fixedspaces\to\tabulatesettings\settabulatepreamble}
-\setvalue{\??tt>\meaning g}{\gettabulatealign}
-\setvalue{\??tt>\meaning .}{\gettabulatealign.}
-\setvalue{\??tt>\meaning ,}{\gettabulatealign,}
-\setvalue{\??tt>\meaning C}{\doparsecolortabulate}
-\setvalue{\??tt>\s!unknown }{\message{unknown preamble key [\meaning\next]}\settabulatepreamble}
-\setvalue{\??tt>\meaning\relax}{}
-
-\def\dosettabulatepreamble
- {\csname\??tt>\ifcsname\??tt>\meaning\next\endcsname\meaning\next\else\s!unknown\fi\endcsname}
-
-\def\gettabulatepreskip#1%
+ \d_tabl_tabulate_width\zeropoint}
+
+\unexpanded\def\installtabulatepreambleoption#1#2%
+ {\setvalue{\??tabulatepreamble\string#1}{#2}}%
+
+\installtabulatepreambleoption{x}{\c_tabl_tabulate_align\zerocount
+ \tabl_tabulate_set_preamble} % internal
+\installtabulatepreambleoption{l}{\c_tabl_tabulate_align\plusone
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{r}{\c_tabl_tabulate_align\plustwo
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{c}{\c_tabl_tabulate_align\plusthree
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{p}{\tabl_tabulate_set_paragraph}
+\installtabulatepreambleoption{s}{\tabl_tabulate_set_setups}
+\installtabulatepreambleoption{w}{\tabl_tabulate_set_width}
+\installtabulatepreambleoption{f}{\tabl_tabulate_set_font}
+\installtabulatepreambleoption{B}{\t_tabl_tabulate_font{\bf}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{I}{\t_tabl_tabulate_font{\it}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{S}{\t_tabl_tabulate_font{\sl}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{T}{\t_tabl_tabulate_font{\tt}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{R}{\t_tabl_tabulate_font{\rm}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{m}{\t_tabl_tabulate_bmath{$}\t_tabl_tabulate_emath{$}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{M}{\t_tabl_tabulate_bmath{$\displaystyle}\t_tabl_tabulate_emath{$}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{h}{\tabl_tabulate_set_hook}
+\installtabulatepreambleoption{b}{\tabl_tabulate_set_before}
+\installtabulatepreambleoption{a}{\tabl_tabulate_set_after}
+\installtabulatepreambleoption{i}{\tabl_tabulate_set_preskip}
+\installtabulatepreambleoption{j}{\tabl_tabulate_set_posskip}
+\installtabulatepreambleoption{k}{\tabl_tabulate_set_preposskip}
+\installtabulatepreambleoption{e}{\t_tabl_tabulate_settings\expandafter{\the\t_tabl_tabulate_settings\global\settrue\c_tabl_tabulate_equal}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{g}{\tabl_tabulate_set_align}
+\installtabulatepreambleoption{.}{\tabl_tabulate_set_align.}
+\installtabulatepreambleoption{,}{\tabl_tabulate_set_align,}
+\installtabulatepreambleoption{C}{\tabl_tabulate_set_color_span}
+\installtabulatepreambleoption{d}{\t_tabl_tabulate_settings\expandafter{\the\t_tabl_tabulate_settings\fixedspaces}%
+ \tabl_tabulate_set_preamble}
+\installtabulatepreambleoption{ }{\tabl_tabulate_set_preamble}
+
+% We no longer deal with '~' here but map it onto 'd' instead. Of course
+% we could prefix a key with \type {\meaning} instead, which works ok (and
+% is needed in order to pseudo expand \type {\next}, but is ugly at the
+% same time. The 'd' stands for digitspace.
+%
+% \installtabulatepreambleoption{~}{...} % see 'd'
+%
+% Also, as there is always a key, we no longer do some after assigment or
+% future let but just pick up the key.
+
+% \installtabulatepreambleoption \s!unknown %
+% {\writestatus{tabulate}{unknown preamble key [\meaning\next]}%
+% \tabl_tabulate_set_preamble}
+%
+% \def\tabl_tabulate_set_preamble
+% {\afterassignment\dosettabulatepreamble\let\next=}
+%
+% \def\dosettabulatepreamble
+% {\ifx\next\relax \else
+% \csname\??tabulatepreamble
+% \ifcsname\??tabulatepreamble\next\endcsname\next\else\s!unknown\fi
+% \expandafter\endcsname
+% \fi}
+
+\installtabulatepreambleoption\relax
+ {} % finished
+
+\def\tabl_tabulate_set_preamble#1%
+ {\ifcsname\??tabulatepreamble\string#1\endcsname
+ \expandafter\tabl_tabulate_set_preamble_yes
+ \else
+ \expandafter\tabl_tabulate_set_preamble_nop
+ \fi{#1}}
+
+\def\tabl_tabulate_set_preamble_yes#1%
+ {\csname\??tabulatepreamble\string#1\expandafter\endcsname}
+
+\def\tabl_tabulate_set_preamble_nop#1%
+ {\writestatus{tabulate}{unknown preamble key: #1}%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_preskip#1%
{\doifnumberelse{#1}
- {\tabulatepreskip#1\tabulateunit\let\next\empty}
- {\tabulatepreskip.5\tabulateunit\def\next{#1}}%
- \@EA\settabulatepreamble\next}
+ {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }
+ {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}}
-\def\gettabulateposskip#1%
+\def\tabl_tabulate_set_posskip#1%
{\doifnumberelse{#1}
- {\tabulateposskip#1\tabulateunit\let\next\empty}
- {\tabulateposskip.5\tabulateunit\def\next{#1}}%
- \@EA\settabulatepreamble\next}
+ {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble }
+ {\s_tabl_tabulate_post.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}}
-\def\gettabulatepreposskip#1%
+\def\tabl_tabulate_set_preposskip#1%
{\doifnumberelse{#1}
- {\tabulatepreskip#1\tabulateunit\let\next\empty}
- {\tabulatepreskip.5\tabulateunit\def\next{#1}}%
- \tabulateposskip\tabulatepreskip
- \@EA\settabulatepreamble\next}
+ {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble }
+ {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble#1}}
-\def\gettabulatesetups#1%
- {\setvalue{\??tt:s:\the\tabulatecolumns}{\setups[#1]}%
- \settabulatepreamble}
+\def\tabl_tabulate_set_setups#1%
+ {\setvalue{\??tabulatesetup\the\c_tabl_tabulate_columns}{\setups[#1]}%
+ \tabl_tabulate_set_preamble}
-\def\gettabulatehook#1%
- {\setvalue{\??tt:h:\the\tabulatecolumns}{#1}%
- \settabulatepreamble}
+\def\tabl_tabulate_set_hook#1%
+ {\setvalue{\??tabulatehook\the\c_tabl_tabulate_columns}{#1}%
+ \tabl_tabulate_set_preamble}
-\def\gettabulatealign#1%
- {\setvalue{\??tt:a:\the\tabulatecolumns}{#1}%
- \settabulatepreamble}
+\def\tabl_tabulate_set_align#1%
+ {\setvalue{\??tabulatealign\the\c_tabl_tabulate_columns}{#1}%
+ \tabl_tabulate_set_preamble}
-\def\gettabulatebefore#1%
- {\tabulatebefore{#1}%
- \settabulatepreamble}
+\def\tabl_tabulate_set_before#1%
+ {\t_tabl_tabulate_before{#1}%
+ \tabl_tabulate_set_preamble}
-\def\gettabulateafter#1%
- {\tabulateafter{#1}%
- \settabulatepreamble}
+\def\tabl_tabulate_set_after#1%
+ {\t_tabl_tabulate_after{#1}%
+ \tabl_tabulate_set_preamble}
-\def\gettabulatefont#1%
- {\tabulatefont{#1}%
- \settabulatepreamble}
+\def\tabl_tabulate_set_font#1%
+ {\t_tabl_tabulate_font{#1}%
+ \tabl_tabulate_set_preamble}
-\def\gettabulatewidth
- {\let\tabulatemodus\zerocount
- \let\tabulatedimen\zerocount
- \doifnextparenthesiselse\dogettabulatewidth\settabulatepreamble}
+\def\tabl_tabulate_pickup_width
+ {\doifnextparenthesiselse\tabl_tabulate_set_width_indeed\tabl_tabulate_set_preamble}
-\def\gettabulateparagraph
+\def\tabl_tabulate_set_width
+ {\setfalse\c_tabl_tabulate_pwidth_set
+ \c_tabl_tabulate_modus\zerocount
+ \tabl_tabulate_pickup_width}
+
+\def\tabl_tabulate_set_paragraph
{\doifnextparenthesiselse
- {\let\tabulatemodus\plusone
- \let\tabulatedimen\plusone
- \dogettabulatewidth}
- {\let\tabulatemodus\plustwo
- \let\tabulatedimen\zerocount
- \settabulatepreamble}}
+ {\c_tabl_tabulate_modus\plusone
+ \settrue\c_tabl_tabulate_pwidth_set
+ \tabl_tabulate_pickup_width}
+ {\c_tabl_tabulate_modus\plustwo
+ \setfalse\c_tabl_tabulate_pwidth_set
+ \tabl_tabulate_set_preamble}}
% \startbuffer
% \toplinebox{\framed[width=3cm,height=2cm]{tufte}}
@@ -553,181 +655,206 @@
% \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
% \stoptabulate
-\def\dogettabulatewidth(#1)%
+\def\tabl_tabulate_set_width_indeed(#1)%
{\processallactionsinset % can be made faster
[#1]%
- [ \v!fit=>\let\tabulatemodus\plusthree,
- \v!fixed=>\let\tabulatemodus\plusthree
- \settrue\tabulatenopbreak,
- \v!auto=>\let\tabulatemodus\plusthree
- \let\tabulatereshape\plusone,
- \s!unknown=>\tabulatewidth#1\relax]%
- \ifnum\tabulatedimen=\plusone
- \global\advance\tabulatepwidth\tabulatewidth % accumulated parwidth
+ [ \v!fit=>\c_tabl_tabulate_modus\plusthree,
+ \v!fixed=>\c_tabl_tabulate_modus\plusthree
+ \settrue\c_tabl_tabulate_nopbreak,
+ \v!auto=>\c_tabl_tabulate_modus\plusthree
+ \settrue\c_tabl_tabulate_reshape,
+ \s!unknown=>\d_tabl_tabulate_width#1\relax]%
+ \ifconditional\c_tabl_tabulate_pwidth_set
+ \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth
\fi
- \settabulatepreamble}
-
-\def\settabulatepreamble
- {\afterassignment\dosettabulatepreamble\let\next=}
-
-\def\tabulateraggedright {\ifnum\tabulatetype=\plusone \else\raggedright \fi}
-\def\tabulateraggedcenter{\ifnum\tabulatetype=\plusone \else\raggedcenter\fi}
-\def\tabulateraggedleft {\ifnum\tabulatetype=\plusone \else\raggedleft \fi}
-\def\tabulatenotragged {\ifnum\tabulatetype=\plusone \else\notragged \fi}
-\def\tabulatehss {\ifnum\tabulatetype=\plusone \else\hss \fi} % never change this to a fill
-
-\def\tabulatebskipraggedright {\bskip\tabulateraggedright }
-\def\tabulatebskipraggedleft {\bskip\tabulateraggedleft }
-\def\tabulatebskipraggedcenter{\bskip\tabulateraggedcenter}
-
-\def\tabulatesetpreamblewidthnormal
- {\ifcase\tabulatealign\relax
- \dodosettabulatepreamble\empty \tabulatehss \or
- \dodosettabulatepreamble\empty \tabulatehss \or
- \dodosettabulatepreamble\tabulatehss\empty \or
- \dodosettabulatepreamble\tabulatehss\tabulatehss \fi}
-
-\def\tabulatesetpreamblewidthfixed
- {\ifcase\tabulatealign\relax
- \dodosettabulatepreamble\bskip \eskip \or
- \dodosettabulatepreamble\tabulatebskipraggedright \eskip \or
- \dodosettabulatepreamble\tabulatebskipraggedleft \eskip \or
- \dodosettabulatepreamble\tabulatebskipraggedcenter\eskip \fi}
-
-\def\tabulatesetpreamblewidthauto
- {\global\advance\nofautotabulate\plusone
- \ifcase\tabulatealign\relax
- \dodosettabulatepreamble\bskip \eskip \or
- \dodosettabulatepreamble\tabulatebskipraggedright \eskip \or
- \dodosettabulatepreamble\tabulatebskipraggedleft \eskip \or
- \dodosettabulatepreamble\tabulatebskipraggedcenter\eskip \fi}
-
-\def\tabulatesetpreamblewidthsimple
- {\dodosettabulatepreamble\xbskip\xeskip}
-
-\def\doparsecolortabulate#1#2%
- {\gdef\currenttabulatecolor{#2}%
- \global\tabulatecolorspan\if#1L\plusone\else\if#1M\plustwo\else\if#1R\plusthree\else\zerocount\fi\fi\fi\relax
- \settabulatepreamble}
-
-\def\dotabulatevrulecommand#1%
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_raggedright {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedright \fi}
+\def\tabl_tabulate_set_raggedcenter{\ifnum\c_tabl_tabulate_type=\plusone \else\raggedcenter\fi}
+\def\tabl_tabulate_set_raggedleft {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedleft \fi}
+\def\tabl_tabulate_set_notragged {\ifnum\c_tabl_tabulate_type=\plusone \else\notragged \fi}
+\def\tabl_tabulate_set_hss {\ifnum\c_tabl_tabulate_type=\plusone \else\hss \fi} % never change this to a fill
+
+\def\tabl_tabulate_bskip_raggedright {\tabl_tabulate_bskip\tabl_tabulate_set_raggedright }
+\def\tabl_tabulate_bskip_raggedleft {\tabl_tabulate_bskip\tabl_tabulate_set_raggedleft }
+\def\tabl_tabulate_bskip_raggedcenter{\tabl_tabulate_bskip\tabl_tabulate_set_raggedcenter}
+
+\def\tabl_tabulate_set_width_normal
+ {\ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\empty \tabl_tabulate_set_hss \or
+ \tabl_tabulate_set_preamble_step\empty \tabl_tabulate_set_hss \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_set_hss\empty \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_set_hss\tabl_tabulate_set_hss \fi}
+
+\def\tabl_tabulate_set_width_fixed
+ {\ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedright \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedleft \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedcenter\tabl_tabulate_eskip \fi}
+
+\def\tabl_tabulate_set_width_auto
+ {\global\advance\c_tabl_tabulate_nofauto\plusone
+ \ifcase\c_tabl_tabulate_align\relax
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedright \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedleft \tabl_tabulate_eskip \or
+ \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedcenter\tabl_tabulate_eskip \fi}
+
+\def\tabl_tabulate_set_width_simple
+ {\tabl_tabulate_set_preamble_step\tabl_tabulate_xbskip\tabl_tabulate_xeskip}
+
+\def\tabl_tabulate_set_color_span#1#2%
+ {\xdef\m_tabl_tabulate_color{#2}%
+ \global\c_tabl_tabulate_colorspan\if#1L\plusone\else\if#1M\plustwo\else\if#1R\plusthree\else\zerocount\fi\fi\fi\relax
+ \tabl_tabulate_set_preamble}
+
+\def\tabl_tabulate_set_vrule_command#1%
{\doifnumberelse{#1}
- {\global\tabulatevrulethickness#1\defaulttabulatevrulethickness}
- {\xdef\currenttabulatevrulecolor{#1}}}
-
-\def\settabulateentry#1#2% rulespec template
- {\let\tabulatealign\@@tabulatealign
- \let\tabulatemodus\zerocount
- \let\tabulatedimen\zerocount
- \let\tabulatereshape\zerocount
- \tabulatebefore\emptytoks
- \tabulateafter\emptytoks
- \tabulatebmath\emptytoks
- \tabulateemath\emptytoks
- \tabulatefont\emptytoks
- \tabulatesettings\emptytoks
- \global\let\currenttabulatecolor\empty
- \global\let\currenttabulatevrulecolor\empty
- \global\tabulatecolorspan\zerocount
- \global\advance\tabulatecolumns\plusone % == #1
- \expandafter\let\csname\??tt:s:\the\tabulatecolumns\endcsname\donothing
- \edef\currenttabulatetrulespec{#1}%
- \ifx\currenttabulatetrulespec\empty
- \global\tabulatevrulethickness\zeropoint
+ {\global\d_tabl_tabulate_vrulethickness#1\d_tabl_tabulate_vrulethickness_default}
+ {\xdef\m_tabl_tabulate_vrule_color{#1}}}
+
+\def\tabl_tabulate_set_entry#1#2% rulespec template
+ {\c_tabl_tabulate_align\v_tabl_tabulate_align
+ \c_tabl_tabulate_modus\zerocount
+ \setfalse\c_tabl_tabulate_pwidth_set
+ \setfalse\c_tabl_tabulate_reshape
+ \t_tabl_tabulate_before\emptytoks
+ \t_tabl_tabulate_after\emptytoks
+ \t_tabl_tabulate_bmath\emptytoks
+ \t_tabl_tabulate_emath\emptytoks
+ \t_tabl_tabulate_font\emptytoks
+ \t_tabl_tabulate_settings\emptytoks
+ \global\let\m_tabl_tabulate_color\empty
+ \global\let\m_tabl_tabulate_vrule_color\empty
+ \global\c_tabl_tabulate_colorspan\zerocount
+ \global\advance\c_tabl_tabulate_columns\plusone
+ \expandafter\let\csname\??tabulatesetup\the\c_tabl_tabulate_columns\endcsname\donothing % here ?
+ \edef\currenttabulationtrulespec{#1}%
+ \ifx\currenttabulationtrulespec\empty
+ \global\d_tabl_tabulate_vrulethickness\zeropoint
\else
- \global\tabulatevrulethickness\defaulttabulatevrulethickness
- \rawprocesscommalist[#1]\dotabulatevrulecommand
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
+ \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
\fi
- \settabulatepreamble#2\relax\relax % permits i without n
- \ifcase\tabulatemodus\relax
- \tabulatesetpreamblewidthnormal
+ \tabl_tabulate_set_preamble#2\relax\relax % permits i without n
+ \ifcase\c_tabl_tabulate_modus\relax
+ \tabl_tabulate_set_width_normal
\or % fixed width
- \tabulatesetpreamblewidthfixed
+ \tabl_tabulate_set_width_fixed
\or % auto width
- \tabulatesetpreamblewidthauto
+ \tabl_tabulate_set_width_auto
\or % simple
- \tabulatesetpreamblewidthsimple
+ \tabl_tabulate_set_width_simple
\fi}
-\def\setlasttabulateentry#1% rulespec
- {\global\let\currenttabulatevrulecolor\empty
- \rawprocesscommalist[#1]\dotabulatevrulecommand
- \ifx\currenttabulatetrulespec\empty
- \global\tabulatevrulethickness\zeropoint
+\def\tabl_tabulate_set_last_entry#1% rulespec
+ {\global\let\m_tabl_tabulate_vrule_color\empty
+ \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
+ \ifx\currenttabulationtrulespec\empty
+ \global\d_tabl_tabulate_vrulethickness\zeropoint
\else
- \global\tabulatevrulethickness\defaulttabulatevrulethickness
- \rawprocesscommalist[#1]\dotabulatevrulecommand
+ \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
+ \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
\fi
- \normalexpanded{\tabulatepreamble{\the\tabulatepreamble
- \dochecklocaltabulatevrulecolor{\currenttabulatevrulecolor}{\the\tabulatevrulethickness}%
- \dotabulatevrule}}}
+ \normalexpanded{\t_tabl_tabulate_preamble{\the\t_tabl_tabulate_preamble
+ \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
+ \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
+ \tabl_tabulate_column_vrule_inject}}%
+ }
+
+\let\settabulateentry \tabl_tabulate_set_entry % used at the lua end
+\let\settabulatelastentry\tabl_tabulate_set_last_entry % used at the lua end
-\def\donormalizetabulatesplitline
- {\ifcase\tabulatesplitlinemode
+\def\tabl_tabulate_normalize_splitline
+ {\ifcase\c_tabl_tabulate_splitlinemode
% nothing
\or
- \ht\tabulatebox\strutht
- \dp\tabulatebox\strutdp
+ \ht\b_tabl_tabulate\strutht
+ \dp\b_tabl_tabulate\strutdp
\or
- \ifdim\ht\tabulatebox<\strutht
- \ht\tabulatebox\strutht
+ \ifdim\ht\b_tabl_tabulate<\strutht
+ \ht\b_tabl_tabulate\strutht
\fi
- \ifdim\dp\tabulatebox<\strutdp
- \dp\tabulatebox\strutdp
+ \ifdim\dp\b_tabl_tabulate<\strutdp
+ \dp\b_tabl_tabulate\strutdp
\fi
\fi}
-\def\flushtabulatesplitbox
- {\box\tabulatebox}
+\def\tabl_tabulate_whitespace
+ {\ifdim\d_tabl_tabulate_splitoff_betweenskip>\zeropoint
+ \vskip\d_tabl_tabulate_splitoff_betweenskip
+ \global\d_tabl_tabulate_splitoff_betweenskip\zeropoint
+ \fi}
+
+\def\tabl_tabulate_check_whitespace
+ {\setbox\scratchbox\vbox
+ {\splitdiscards
+ \unskip
+ \ifdim\lastskip>\d_tabl_tabulate_splitoff_betweenskip
+ \global\d_tabl_tabulate_splitoff_betweenskip\lastskip
+ \fi}}
-\def\splitofftabulatebox % overloads in anch-pgr
+\def\tabl_tabulate_splitoff_box
{\dontcomplain
- \global\setbox\tabulatebox % % % global ? % % %
- \vsplit\tablebox\tabulatecolumn to \lineheight
- \setbox\tabulatebox\normalvbox
- {\unvbox\tabulatebox}%
- \setbox\tabulatebox\hbox to \wd\tabulatebox
- {\iftrialtypesetting\else\ifconditional\tabulatehascolors\repeatsettabulatecolor\fi\fi
- \hss\dotabulatehook{\box\tabulatebox}\hss}%
- \donormalizetabulatesplitline
- \flushtabulatesplitbox}
-
-\def\dotabulatehook {\csname\??tt:h:\the\tabulatecolumn\endcsname}
-\def\dotabulatealign{\csname\??tt:a:\the\tabulatecolumn\endcsname}
-
-\def\resettabulatepheight
- {\global\tabulateminplines\plusone
- \ifdim\tabulatemaxpheight>\zeropoint
- \getnoflines\tabulatemaxpheight
- \global\tabulatemaxplines\noflines
+ \global\setbox\b_tabl_tabulate\vsplit\b_tabl_tabulate_current\c_tabl_tabulate_column to \lineheight % % % global ? % % %
+ \setbox\b_tabl_tabulate\vbox
+ {\unvbox\b_tabl_tabulate}%
+ \ifconditional\c_tabl_tabulate_splitoff_whitespace
+ \tabl_tabulate_check_whitespace
+ \fi
+ \setbox\b_tabl_tabulate\hbox to \wd\b_tabl_tabulate
+ {\tabl_tabulate_color_repeat
+ \hss\tabl_tabulate_hook_yes{\box\b_tabl_tabulate}\hss}%
+ \tabl_tabulate_normalize_splitline
+ \box\b_tabl_tabulate}
+
+\unexpanded\def\tabl_tabulate_hook_nop
+ {}
+
+\let\tabl_tabulate_hook\tabl_tabulate_hook_nop
+
+\def\tabl_tabulate_hook_yes {\csname\??tabulatehook \the\c_tabl_tabulate_column\endcsname}
+\def\tabl_tabulate_align_yes{\csname\??tabulatealign\the\c_tabl_tabulate_column\endcsname} % to be used
+
+\def\tabl_tabulate_pheight_reset
+ {\global\c_tabl_tabulate_plines_min\plusone
+ \ifdim\d_tabl_tabulate_height_p_max>\zeropoint
+ \getnoflines\d_tabl_tabulate_height_p_max
+ \global\c_tabl_tabulate_plines_max\noflines
\else
- \global\tabulatemaxplines\zerocount
+ \global\c_tabl_tabulate_plines_max\zerocount
\fi
- \global\tabulatemaxpheight\zeropoint}
+ \global\d_tabl_tabulate_height_p_max\zeropoint}
-\def\settabulatepheight
- {\scratchdimen\ht\tablebox\tabulatecolumn\relax
- \ifdim\scratchdimen>\tabulatemaxpheight
- \global\tabulatemaxpheight\scratchdimen
+\def\tabl_tabulate_pheight_set
+ {\scratchdimen\ht\b_tabl_tabulate_current\c_tabl_tabulate_column\relax
+ \ifdim\scratchdimen>\d_tabl_tabulate_height_p_max
+ \global\d_tabl_tabulate_height_p_max\scratchdimen
\fi}
-\def\dohandletabulatepbreak
- {\ifconditional\tabulatehandlepbreak
- \ifconditional\tabulatenopbreak
- \dotabulatenobreak
- \else\ifnum\tabulatemaxplines>\plusone
- \ifnum\tabulateminplines=\plusone
- \dotabulatenobreak
+\def\tabl_tabulate_pbreak_inject
+ {\ifconditional\c_tabl_tabulate_handlepbreak
+ \ifconditional\c_tabl_tabulate_nopbreak
+ \tabl_tabulate_nobreak_inject
+ \else\ifnum\c_tabl_tabulate_plines_max>\plusone
+ \ifnum\c_tabl_tabulate_plines_min=\plusone
+ \tabl_tabulate_nobreak_inject
\fi
- \global\advance\tabulateminplines\plusone
- \ifnum\tabulateminplines=\tabulatemaxplines\relax
- \dotabulatenobreak
+ \global\advance\c_tabl_tabulate_plines_min\plusone
+ \ifnum\c_tabl_tabulate_plines_min=\c_tabl_tabulate_plines_max\relax
+ \tabl_tabulate_nobreak_inject
\fi
\fi \fi
\fi}
-\def\handletabulatepbreak
- {\tabulatenoalign{\dohandletabulatepbreak}}
+\def\tabl_tabulate_pbreak_check
+ {\starttabulatenoalign
+ \tabl_tabulate_pbreak_inject
+ \ifconditional\c_tabl_tabulate_splitoff_whitespace
+ \tabl_tabulate_whitespace
+ \fi
+ \stoptabulatenoalign}
%D \startbuffer
%D \starttabulate[|c|p|p|]
@@ -755,407 +882,538 @@
%D
%D \typebuffer {\tracetabulatetrue\getbuffer}
-% \definetabulate
-% \redefinetabulate
-% \starttabulate[preamble]
-% \starttabulate -> \starttabulate[|l|p|]
+%D As we want to be compatible we use an indirect way to
+%D implement the definers. The next examples demonstrate
+%D the difference:
+%D
+%D \starttyping
+%D \definetabulate[test][|l|c|r|]
+%D \definetabulate[test][two][|r|c|l|]
+%D
+%D \definetabulation[more][format={|l|c|r|}]
+%D \definetabulation[more:two][format={|r|c|l|}]
+%D
+%D \starttest
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stoptest
+%D
+%D \starttest[two]
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stoptest
+%D \startmore
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stopmore
+%D
+%D \startmore[two]
+%D \NC t \NC t \NC t \NC \NR
+%D \NC te \NC te \NC te \NC \NR
+%D \NC tes \NC tes \NC tes \NC \NR
+%D \NC test \NC test \NC test \NC \NR
+%D \stopmore
+%D \stoptyping
+
+\installcorenamespace {tabulation}
+
+\installcommandhandler \??tabulation {tabulation} \??tabulation
+
+\setuptabulation
+ [\c!unit=1em,
+ EQ={:},
+ \c!format={|l|p|},
+ \c!frame=\v!off,
+ %\c!bodyfont=,
+ \c!rule=\v!normal,
+ %\c!rulecolor=,
+ \c!rulethickness=\linewidth,
+ %\c!inner=,
+ \c!before=\blank,
+ \c!after=\blank,
+ \c!distance={\v!depth,\v!medium},
+ \c!align=\v!normal,
+ \c!margin=\!!zeropoint,
+ \c!split=\v!auto,
+ \c!header=\v!yes,
+ %\c!title=,
+ \c!indenting=\v!no]
-\def\definetabulate
- {\dotripleempty\dodefinetabulate}
+\unexpanded\def\definetabulate
+ {\dotripleempty\tabl_tabulate_define}
-\def\dodefinetabulate[#1][#2][#3]%
+\def\tabl_tabulate_define[#1][#2][#3]%
{\ifthirdargument
- \ifcsname\??tt#1::\c!unit\endcsname \else
- \copyparameters
- [\??tt#1::][\??tt\v!tabulate::]%
- [\c!frame,\c!distance,\c!unit,\c!before,\c!bodyfont,\c!after,
- \c!inner,\c!indenting,\c!margin,\c!align,\c!header,\c!title,
- \c!rulecolor,\c!rulethickness,\c!split,EQ]%
+ % [tag] [sub] [template]
+ \ifcsname\namedtabulationhash{#1}\s!check\endcsname \else
+ \definetabulation[#1][\c!format={#3},\s!check=]%
\fi
- \copyparameters
- [\??tt#1::#2][\??tt#1::]%
- [\c!frame,\c!distance,\c!unit,\c!before,\c!bodyfont,\c!after,
- \c!inner,\c!indenting,\c!margin,\c!align,\c!header,\c!title,
- \c!rulecolor,\c!rulethickness,\c!split,EQ]%
- \setuvalue{\e!start#1::#2}{\dofinalstarttabulate[#1][#2][#3]}%
- \setuvalue{\e!start#1}{\bgroup\dosubstarttabulate[#1]}%
- \letvalueempty{\??tt#1-\v!header}%
- \letvalueempty{\??tt#1-\v!footer}%
+ \definetabulation[#1:#2][#1][\c!format={#3},\s!check=]%
\else\ifsecondargument
- \definetabulate[#1][][#2]%
+ % [tag] [template]
+ \definetabulation[#1][\c!format={#2},\s!check=]%
\else
- \definetabulate[#1][][|l|p|]%
+ % [tag]
+ \definetabulation[#1][\c!format={|l|p|},\s!check=]%
\fi\fi}
-\let\tabulateheadcontent\empty
-\let\tabulatetailcontent\empty
+\unexpanded\def\setuptabulate
+ {\dotripleempty\tabl_tabulate_setup}
+
+\def\tabl_tabulate_setup[#1][#2][#3]%
+ {\ifthirdargument
+ % [tag] [sub] [settings]
+ \setuptabulation[#1:#2][#3]%
+ \else\ifsecondargument
+ % [tag] [settings]
+ \setuptabulation[#1][#2]%
+ \else
+ % [tag]
+ \setuptabulation[#1]%
+ \fi\fi}
+
+\appendtoks
+ \setuevalue{\e!start\currenttabulation}{\tabl_start_defined[\currenttabulation]}%
+ \letvalue{\??tabulatehead\currenttabulation}\empty
+ \letvalue{\??tabulatefoot\currenttabulation}\empty
+\to \everydefinetabulation
+
+\let\tabulateparameter\tabulationparameter % will stay for a while
+\def\currenttabulate {\currenttabulation} % will stay for a while
-\def\processtabulateheadcontent
- {\tabulatenoalign{\global\settrue\tabulatesomeamble}%
- \csname\??tt\currenttabulate-\v!header\endcsname
- \tabulatenoalign{\global\setfalse\tabulatesomeamble}}%
+% Here begins the implementation.
-\def\processtabulatetailcontent
- {\tabulatenoalign{\global\settrue\tabulatesomeamble}%
- \csname\??tt\currenttabulate-\v!footer\endcsname
- \tabulatenoalign{\global\setfalse\tabulatesomeamble}}%
+\let\tabl_tabulate_insert_head\empty
+\let\tabl_tabulate_insert_body\empty
+\let\tabl_tabulate_insert_foot\empty
-\def\checkfulltabulatecontent % - needed, else confusion with \c!header
- {\ifcsname\??tt\currenttabulate-\v!header\endcsname
- \let\tabulateheadcontent\processtabulateheadcontent
+\def\tabl_tabulate_insert_head_content
+ {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
+ \csname\??tabulatehead\currenttabulation\endcsname
+ \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
+
+\def\tabl_tabulate_insert_foot_content
+ {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
+ \csname\??tabulatehead\currenttabulation\endcsname
+ \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
+
+\def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header
+ {\ifcsname\??tabulatehead\currenttabulation\endcsname
+ \let\tabl_tabulate_insert_head\tabl_tabulate_insert_head_content
\else
- \let\tabulateheadcontent\empty
+ \let\tabl_tabulate_insert_head\empty
\fi
- \ifcsname\??tt\currenttabulate-\v!footer\endcsname
- \let\tabulatetailcontent\processtabulatetailcontent
+ \ifcsname\??tabulatefoot\currenttabulation\endcsname
+ \let\tabl_tabulate_insert_foot\tabl_tabulate_insert_foot_content
\else
- \let\tabulatetailcontent\empty
+ \let\tabl_tabulate_insert_foot\empty
\fi}
-\def\fulltabulatecontent
- {\tabulateheadcontent
- \tabulatecontent
- \tabulatetailcontent
- \removefunnytabulateline}
+\def\tabl_tabulate_insert_content
+ {\tabl_tabulate_insert_head
+ \tabl_tabulate_insert_body
+ \tabl_tabulate_insert_foot
+ \tabl_tabulate_remove_funny_line}
-\def\removefunnytabulateline
+\def\tabl_tabulate_remove_funny_line
{\ifhmode
\strut\crcr
\tabulatenoalign{\kern-\lineheight}%
\fi}
-\setuvalue{\e!start\v!tabulatehead}%
- {\dosingleempty\dostartstarttabulatehead}
-
-\def\dostartstarttabulatehead[#1]%
- {\processcontent{\e!stop\v!tabulatehead}\next
- {\letvalue{\??tt\iffirstargument#1\else\v!tabulate\fi::-\v!header}\next}}
-
-\setuvalue{\e!start\v!tabulatetail}%
- {\dosingleempty\dostartstarttabulatetail}
+\setuvalue{\e!start\v!tabulatehead}{\doifnextoptionalelse\tabl_tabulate_start_head_yes\tabl_tabulate_start_head_nop}
+\setuvalue{\e!start\v!tabulatetail}{\doifnextoptionalelse\tabl_tabulate_start_foot_yes\tabl_tabulate_start_foot_nop}
-\def\dostartstarttabulatetail[#1]%
- {\processcontent{\e!stop\v!tabulatetail}\next
- {\letvalue{\??tt\iffirstargument#1\else\v!tabulate\fi::-\v!footer}\next}}
+\let\m_tabl_tabulate_data\empty
-\def\dosubstarttabulate
- {\dodoubleempty\dodosubstarttabulate}
+\def\tabl_tabulate_start_head_yes[#1]%
+ {\processcontent{\e!stop\v!tabulatehead}\m_tabl_tabulate_data{\letvalue{\??tabulatehead#1}\m_tabl_tabulate_data}}
-\def\dodosubstarttabulate[#1][#2]%
- {\csname\e!start#1::\ifcsname\e!start#1::#2\endcsname#2\fi\endcsname}
+\def\tabl_tabulate_start_foot_yes[#1]%
+ {\processcontent{\e!stop\v!tabulatetail}\m_tabl_tabulate_data{\letvalue{\??tabulatefoot#1}\m_tabl_tabulate_data}}
-\setuvalue{\e!start\v!tabulate}%
- {\bgroup\dodoubleempty\donormalstarttabulate}
-
-\def\doinhibitnestedtabulate
- {\setuvalue{\e!start\v!tabulate}%
- {\em Nested tabulate is not (yet) supported.\relax
- \expandafter\gobbleuntil\csname\e!stop\v!tabulate\endcsname}}
-
-\appendtoks
- \doinhibitnestedtabulate
-\to \everytabulate
+% \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]}
-\setuvalue{\e!stop\v!tabulate }{}
-\setuvalue{\e!stop\v!tabulatehead}{}
-\setuvalue{\e!stop\v!tabulatetail}{}
+\def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[]}
+\def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[]}
-\gdef\donormalstarttabulate[#1][#2]%
- {\ifsecondargument
- \getparameters[\??tt\v!tabulate::][#2]%
+\unexpanded\def\tabl_start_defined[#1]%
+ {\bgroup
+ \edef\currenttabulationparent{#1}%
+ \let\currenttabulation\currenttabulationparent
+ \doifnextoptionalelse\tabl_start_defined_yes\tabl_start_defined_nop}
+
+\def\tabl_start_defined_yes[#1]%
+ {\edef\currenttabulation{\currenttabulation:#1}%
+ \tabl_tabulate_start_building}
+
+\def\tabl_start_defined_nop
+ {\tabl_tabulate_start_building}
+
+% \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one
+
+\unexpanded\setuvalue{\e!start\v!tabulate}%
+ {\bgroup % whole thing
+ \dodoubleempty\tabl_start_regular}
+
+\def\tabl_start_regular[#1][#2]%
+ {%\let\currenttabulationparent\v!tabulate
+ \let\currenttabulationparent\empty
+ \let\currenttabulation\currenttabulationparent
+ \def\p_format{#1}%
+ \ifx\p_format\empty
+ \def\p_format{|l|p|}%
\fi
- \iffirstargument
- \def\next{\dofinalstarttabulate[\v!tabulate][][#1]}%
- \else
- \def\next{\dofinalstarttabulate[\v!tabulate][][|l|p|]}%
+ \lettabulationparameter\c!format\p_format
+ \ifsecondargument
+ \setupcurrenttabulation[#2]%
\fi
- \next}
+ \tabl_tabulate_start_building}
-% The much needed hook:
+\letvalue{\e!stop\v!tabulate }\relax
+\letvalue{\e!stop\v!tabulatehead}\relax
+\letvalue{\e!stop\v!tabulatetail}\relax
-% \appendtoks \optimizeverbatimfalse \to \everytabulate
+\unexpanded\def\tabl_tabulate_start_ignore
+ {\em Nested tabulate is not (yet) supported.\relax
+ \expandafter\gobbleuntil\csname\e!stop\v!tabulate\endcsname}
-% Todo: proper inheritance
+\appendtoks
+ \letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one
+\to \everytabulate
-\def\tabulateparameter#1{\csname\??tt\currenttabulate#1\endcsname}
+\setvalue{\??tabulatesplit\v!yes }{\settrue\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!repeat}{\settrue\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!no }{\setfalse\c_tabl_tabulate_split}
+\setvalue{\??tabulatesplit\v!auto }{\ifinsidefloat\ifinsidesplitfloat\else\setfalse\c_tabl_tabulate_split\fi\fi}
-\setvalue{\??tt:\c!split:\v!yes }{\settrue\tabulatesplit}
-\setvalue{\??tt:\c!split:\v!repeat}{\settrue\tabulatesplit}
-\setvalue{\??tt:\c!split:\v!no }{\setfalse\tabulatesplit}
-\setvalue{\??tt:\c!split:\v!auto }{\ifinsidefloat\ifinsidesplitfloat\else\setfalse\tabulatesplit\fi\fi}
+% todo: spacing around tabulate when bodyfont is set
-\def\dofinalstarttabulate[#1][#2][#3]% identifier sub preamble
- {\edef\currenttabulate{#1::#2}%
- \ifinsidefloat \else
+\unexpanded\def\tabl_tabulate_start_building
+ {\ifinsidefloat \else
\whitespace
- \tabulateparameter\c!before
+ \tabulationparameter\c!before
\fi
- \bgroup
+ \bgroup % settings
+ %
\resetcharacteralign
- % todo: spacing around tabulate when bodyfont is set
- % expansion en test needed ?
- \settrue\tabulatesplit
- \csname\??tt:\c!split:\tabulateparameter\c!split\endcsname
- \doifvaluesomething{\??tt\currenttabulate\c!bodyfont}
- {\expanded{\switchtobodyfont[\tabulateparameter\c!bodyfont]}}%
+ %
+ \edef\p_distance {\tabulationparameter\c!distance}%
+ \edef\p_align {\tabulationparameter\c!align}%
+ \edef\p_line {\tabulationparameter\c!rule}%
+ \edef\p_rulecolor {\tabulationparameter\c!rulecolor}%
+ \edef\p_rulethickness{\tabulationparameter\c!rulethickness}%
+ \edef\p_bodyfont {\tabulationparameter\c!bodyfont}
+ \edef\p_indenting {\tabulationparameter\c!indenting}%
+ %
+ \settrue\c_tabl_tabulate_split
+ \csname\??tabulatesplit\tabulationparameter\c!split\endcsname
+ %
+ \d_tabl_tabulate_unit\tabulationparameter\c!unit
+ \d_tabl_tabulate_margin\tabulationparameter\c!margin
+ \let\m_tabl_tabulate_vrule_color_default\p_rulecolor
+ \let\m_tabl_tabulate_hrule_color_default\p_rulecolor
+ \d_tabl_tabulate_vrulethickness_default\p_rulethickness
+ \d_tabl_tabulate_hrulethickness_default\p_rulethickness
+ \ifx\p_bodyfont\empty\else
+ \switchtobodyfont[\p_bodyfont]%
+ \fi
\postponenotes % new, to be tested / will be configurable
- \tabulatepass\plusone
\widowpenalty\zerocount % otherwise lines are not broken
\clubpenalty \zerocount % but overlap in funny ways
\the\everytabulate
- \tabulateparameter\c!inner
- \doifelsevalue{\??tt\currenttabulate\c!indenting}\v!yes
- {\edef\tabulateindent{\the\dimexpr\leftskip+\hangindent+\parindent}}% \ctxparindent
- {\edef\tabulateindent{\the\dimexpr\leftskip+\hangindent }}%
- \global\tabulatecolumn\zerocount
- \processcontent{\e!stop#1}\tabulatecontent{\processtabulate[#3]}} % \currenttabulate
+ \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
+ {\e!stop\ifx\currenttabulationparent\empty\v!tabulate\else\currenttabulationparent\fi}
+ \tabl_tabulate_insert_body
+ \tabl_tabulate_process}
\def\tabulateEQ
- {\ifconditional\tabulatefirstflushed\else\tabulateparameter{EQ}\fi
- \global\setfalse\tabulateequal}
+ {\ifconditional\c_tabl_tabulate_firstflushed\else\tabulationparameter{EQ}\fi
+ \global\setfalse\c_tabl_tabulate_equal}
% The next ones will be token registers
-\let\tabulatenormalpos\relax
-\let\tabulateequalpos \relax
+\let\tabulatenormalpos\relax % hooks, todo
+\let\tabulateequalpos \relax % hooks, todo
% color columns
-\glet\previoustabulatecolor \empty
-\glet\currenttabulatecolor \empty
-\glet\currenttabulatelocalcolor \empty
-\glet\currenttabulatevrulecolor \empty
-\glet\currenttabulatelocalvrulecolor\empty
+\let\m_tabl_tabulate_color_previous \empty
+\let\m_tabl_tabulate_color \empty
+\let\m_tabl_tabulate_color_local \empty
+\let\m_tabl_tabulate_vrule_color \empty
+\let\m_tabl_tabulate_vrule_color_local \empty
+\let\m_tabl_tabulate_vrule_color_default\empty % used local
+\let\m_tabl_tabulate_hrule_color_default\empty % used local
\appendtoks
- \glet\previoustabulatecolor \empty
- \glet\currenttabulatecolor \empty
- \glet\currenttabulatelocalcolor \empty
- \glet\currenttabulatevrulecolor \empty
- \glet\currenttabulatelocalvrulecolor\empty
- \global\tabulatelocalvrulethickness \zeropoint
-\to \everytabulaterow
-
-\unexpanded\def\dorightsidetabulatecolor
- {\iftrialtypesetting\else
- \ifx\previoustabulatecolor\empty \else
- \settabulatecolor\previoustabulatecolor
- \glet\previoustabulatecolor\empty
- \fi
+ \glet\m_tabl_tabulate_color_previous \empty
+ \glet\m_tabl_tabulate_color \empty
+ \glet\m_tabl_tabulate_color_local \empty
+ \glet\m_tabl_tabulate_vrule_color \empty
+ \glet\m_tabl_tabulate_vrule_color_local\empty
+ \global\d_tabl_tabulate_vrulethickness_local\zeropoint
+\to \t_tabl_tabulate_every_row
+
+\unexpanded\def\tabl_tabulate_color_side_right_second
+ {\ifx\m_tabl_tabulate_color_previous\empty \else
+ \tabl_tabulate_color_set\m_tabl_tabulate_color_previous
+ \glet\m_tabl_tabulate_color_previous\empty
\fi}
-\unexpanded\def\doleftsidetabulatecolor
- {\iftrialtypesetting\else
- \ifx\currenttabulatecolor\empty \else
- \ifcase\tabulatecolorspan
- \or
- \settabulatecolor\currenttabulatecolor
- \or
- \settabulatecolor\currenttabulatecolor
- \fi
+\unexpanded\def\tabl_tabulate_color_side_left_second
+ {\ifx\m_tabl_tabulate_color\empty \else
+ \ifcase\c_tabl_tabulate_colorspan
+ \or
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
+ \or
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
\fi
\fi}
-\unexpanded\def\dobothsidetabulatecolor
- {\iftrialtypesetting\else
- \ifx\currenttabulatecolor\empty \else
- \settabulatecolor\currenttabulatecolor
- \ifcase\tabulatecolorspan
- %\glet\previoustabulatecolor\empty
- \or
- \glet\previoustabulatecolor\empty
- \or
- \glet\previoustabulatecolor\currenttabulatecolor
- \or
- \glet\previoustabulatecolor\currenttabulatecolor
- \fi
+\unexpanded\def\tabl_tabulate_color_side_both_second
+ {\ifx\m_tabl_tabulate_color\empty \else
+ \tabl_tabulate_color_set\m_tabl_tabulate_color
+ \ifcase\c_tabl_tabulate_colorspan
+ %\glet\m_tabl_tabulate_color_previous\empty
+ \or
+ \glet\m_tabl_tabulate_color_previous\empty
+ \or
+ \glet\m_tabl_tabulate_color_previous\m_tabl_tabulate_color
+ \or
+ \glet\m_tabl_tabulate_color_previous\m_tabl_tabulate_color
\fi
\fi}
-\def\tabulatecolorcolumn#1% overloaded
+\let\tabl_tabulate_color_side_right \relax
+\let\tabl_tabulate_color_side_left \relax
+\let\tabl_tabulate_color_side_both \relax
+
+\appendtoks
+ \let\tabl_tabulate_color_side_right\tabl_tabulate_color_side_right_second
+ \let\tabl_tabulate_color_side_left \tabl_tabulate_color_side_left_second
+ \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
{\unskip
- \doiffastoptionalcheckelse{\tabulatecolorcolumnyes#1}{\tabulatecolorcolumnnop#1}}
+ \doiffastoptionalcheckelse{\tabl_tabulate_set_color_column_yes#1}{\tabl_tabulate_set_color_column_nop#1}}
-\def\tabulatecolorcolumnnop
- {\tabulatenormalcolumn}
+\def\tabl_tabulate_set_color_column_nop
+ {\tabl_tabulate_column_normal}
-\def\tabulatecolorcolumnyes#1[#2]%
- {\xdef\currenttabulatelocalcolor{#2}%
- \tabulatenormalcolumn#1}
+\def\tabl_tabulate_set_color_column_yes#1[#2]%
+ {\xdef\m_tabl_tabulate_color_local{#2}%
+ \tabl_tabulate_column_normal#1}
% normal columns:
-\def\tabulatenormalcolumn#1%
+\def\tabl_tabulate_column_normal#1%
{\unskip
\aligntab
- \ifconditional\tabulateequal\tabulateequalpos\else\tabulatenormalpos\fi
+ \ifconditional\c_tabl_tabulate_equal\tabulateequalpos\else\tabulatenormalpos\fi
\aligntab
- \global\tabulatetype#1%
+ \global\c_tabl_tabulate_type#1%
\aligntab}
% equal columns
-\def\tabulateequalcolumn#1% overloaded
+\def\tabl_tabulate_column_equal#1%
{\unskip
\aligntab
\tabulateequalpos
- \aligntab\global\tabulatetype#1%
+ \aligntab\global\c_tabl_tabulate_type#1%
\aligntab}
% ruled columns
-\def\tabulatevruledcolumn#1%
+\def\tabl_tabulate_column_vruled#1%
{\unskip % 0-n
- \ifnum\tabulatecolumn=\plusone
- \global\tabulatehasfirstrulespec\plusone
- \else\ifnum\tabulatecolumn=\noftabulatecolumns
- \global\tabulatehaslastrulespec\plusone
- \fi\fi
- \global\let\currenttabulatelocalvrulecolor\defaulttabulatevrulecolor
- \global\tabulatelocalvrulethickness\defaulttabulatevrulethickness
- \doiffastoptionalcheckelse{\tabulatevruledcolumnyes#1}{\tabulatevruledcolumnnop#1}}
+% \ifnum\c_tabl_tabulate_column=\plusone
+% \global\c_tabl_tabulate_has_rule_spec_first\plusone
+% \else\ifnum\c_tabl_tabulate_column=\c_tabl_tabulate_nofcolumns
+% \global\c_tabl_tabulate_has_rule_spec_last\plusone
+% \fi\fi
+ \global\let\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default
+ \global\d_tabl_tabulate_vrulethickness_local\d_tabl_tabulate_vrulethickness_default
+ \doiffastoptionalcheckelse{\tabl_tabulate_column_vruled_yes#1}{\tabl_tabulate_column_vruled_nop#1}}
+
+\def\tabl_tabulate_column_vruled_nop
+ {\tabl_tabulate_column_normal}
+
+\def\tabl_tabulate_column_vruled_step#1%
+ {\doifnumberelse{#1}
+ {\global\d_tabl_tabulate_vrulethickness_local#1\d_tabl_tabulate_vrulethickness_default}
+ {\xdef\m_tabl_tabulate_vrule_color_local{#1}}}
-\def\tabulatevruledcolumnnop
- {\tabulatenormalcolumn}
+\def\tabl_tabulate_column_vruled_yes#1[#2]%
+ {\rawprocesscommalist[#2]\tabl_tabulate_column_vruled_step
+ \tabl_tabulate_column_normal#1}
-\def\dotabulatevrulelocalcommand#1%
- {\doifnumberelse{#1}
- {\global\tabulatelocalvrulethickness#1\defaulttabulatevrulethickness}
- {\xdef\currenttabulatelocalvrulecolor{#1}}}
-
-\def\tabulatevruledcolumnyes#1[#2]%
- {\rawprocesscommalist[#2]\dotabulatevrulelocalcommand
- \tabulatenormalcolumn#1}
-
-\def\donormaltabulatevrule
- {\vrule\!!width\tabulatevrulethickness\relax}
-
-\def\docoloredtabulatevrule
- {\faststartcolor[\currenttabulatevrulecolor]%
- \vrule\!!width\tabulatevrulethickness\relax
- \faststopcolor}
-
-\unexpanded\def\dotabulatevrule
- {\ifcase\tabulatevrulethickness\else
- \iftrialtypesetting
- \donormaltabulatevrule
- \else\ifx\currenttabulatevrulecolor\empty
- \donormaltabulatevrule
+\def\tabl_tabulate_column_vruled_normal
+ {\vrule\!!width\d_tabl_tabulate_vrulethickness\relax}
+
+\def\tabl_tabulate_column_vruled_colored
+ {\dousecolorparameter\m_tabl_tabulate_vrule_color
+ \vrule\!!width\d_tabl_tabulate_vrulethickness\relax}
+
+\unexpanded\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
+ {\ifcase\d_tabl_tabulate_vrulethickness\else
+ \ifx\m_tabl_tabulate_vrule_color\empty
+ \tabl_tabulate_column_vruled_normal
\else
- \docoloredtabulatevrule
- \fi\fi
+ \tabl_tabulate_column_vruled_colored
+ \fi
\fi
- \global\tabulatevrulethickness\zeropoint} % nils second one
+ \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
+
+\let\tabl_tabulate_column_vrule_inject\relax
+
+\appendtoks
+ \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_second
+\to \t_tabl_tabulate_initializers_second
% auto columns
-\def\tabulateautocolumn
- {\tabulatenormalcolumn\zerocount
- \ifnum\tabulatecolumn>\tabulatecolumns\relax
+\def\tabl_tabulate_column_inject_auto
+ {\tabl_tabulate_column_normal\zerocount
+ \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_columns\relax
\expandafter\NR
\else
\expandafter\ignorespaces % interferes with the more tricky hooks
\fi}
-\def\setquicktabulate#1% see \startlegend \startgiven
- {\let#1\tabulateautocolumn
- \let\\\tabulateautocolumn}
-
-\setvalue{\??tt:rs:\v!blank }{\tabulateseparatorskip\bigskipamount}
-\setvalue{\??tt:rs:\v!depth }{\tabulateseparatorskip\strutdp}
-\setvalue{\??tt:rs:\v!small }{\def\factor{.25}}
-\setvalue{\??tt:rs:\v!medium}{\def\factor{.5}}
-\setvalue{\??tt:rs:\v!big }{}
-\setvalue{\??tt:rs:\v!none }{\tabulateseparatorskip\zeropoint\def\factor{0}}
-\setvalue{\??tt:rs:\v!grid }{\tabulateseparatorskip\zeropoint\def\factor{0}}
-
-\def\dodotabulateruleseparator#1%
- {\ifcsname\??tt:rs:#1\endcsname
- \csname\??tt:rs:#1\endcsname
+\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
+
+\setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount}
+\setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp}
+\setvalue{\??tabulateseparator\v!small }{\def\m_tabl_tabulate_separator_factor{.25}}
+\setvalue{\??tabulateseparator\v!medium}{\def\m_tabl_tabulate_separator_factor{.5}}
+\setvalue{\??tabulateseparator\v!big }{}
+\setvalue{\??tabulateseparator\v!none }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
+\setvalue{\??tabulateseparator\v!grid }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
+
+\def\tabl_tabulate_column_rule_separator_step#1%
+ {\ifcsname\??tabulateseparator#1\endcsname
+ \csname\??tabulateseparator#1\endcsname
\else
- \tabulateseparatorskip#1\relax
+ \s_tabl_tabulate_separator#1\relax
\fi}
-\def\dotabulateruleseparator % can be sped up (will do when used frequently)
+\def\tabl_tabulate_column_rule_separator_inject % can be sped up (will do when used frequently)
{\bgroup
- \edef\tabulateseparatordistance{\tabulateparameter\c!distance}%
- \tabulateseparatorskip\strutdp
- \ifx\tabulateseparatordistance\empty\else
- \let\factor\!!plusone
- \normalexpanded{\processcommalist[\tabulateparameter\c!distance]}\dodotabulateruleseparator
- \tabulateseparatorskip\factor\tabulateseparatorskip
+ \s_tabl_tabulate_separator\strutdp
+ \ifx\p_distance\empty\else
+ \let\m_tabl_tabulate_separator_factor\plusone
+ \processcommacommand[\p_distance]\tabl_tabulate_column_rule_separator_step
+ \s_tabl_tabulate_separator\m_tabl_tabulate_separator_factor\s_tabl_tabulate_separator
\fi
- \ifconditional\tabulatesomeamble\kern\else\vskip\fi\tabulateseparatorskip % new
+ \ifconditional\c_tabl_tabulate_someamble\kern\else\vskip\fi\s_tabl_tabulate_separator % new
\egroup}
-\def\tabulateignorehrulespec#1%
- {%\global\let\currenttabulatelocalhrulecolor\empty
- %\global\tabulatelocalhrulethickness\defaulttabulatehrulethickness
+\def\tabl_tabulate_hrule_spec_ignore#1%
+ {%\global\let\currenttabulationlocalhrulecolor\empty
+ %\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
\doiffastoptionalcheckelse#1#1}
-\def\tabulatepickuphrulespec#1%
- {\global\let\currenttabulatelocalhrulecolor\defaulttabulatehrulecolor
- \global\tabulatelocalhrulethickness\defaulttabulatehrulethickness
- \doiffastoptionalcheckelse{\tabulatepresethrule#1}#1}
+\def\tabl_tabulate_hrule_spec_pickup#1%
+ {\global\let\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default
+ \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
+ \doiffastoptionalcheckelse{\tabl_tabulate_hrule_preset#1}#1}
-\def\dotabulatehrulelocalcommand#1%
+\def\tabl_tabulate_hrule_preset_step#1%
{\doifnumberelse{#1}
- {\global\tabulatelocalhrulethickness#1\defaulttabulatehrulethickness}
- {\xdef\currenttabulatelocalhrulecolor{#1}}}
+ {\global\d_tabl_tabulate_hrulethickness_local#1\d_tabl_tabulate_hrulethickness_default}
+ {\xdef\currenttabulationlocalhrulecolor{#1}}}
-\def\tabulatepresethrule#1[#2]%
- {\rawprocesscommalist[#2]\dotabulatehrulelocalcommand
+\def\tabl_tabulate_hrule_preset#1[#2]%
+ {\rawprocesscommalist[#2]\tabl_tabulate_hrule_preset_step
#1}
-\def\donormaltabulatehrule
+\def\tabl_tabulate_hrule_inject_normal
{\hrule
- \!!height.5\tabulatelocalhrulethickness
- \!!depth .5\tabulatelocalhrulethickness
+ \!!height.5\d_tabl_tabulate_hrulethickness_local
+ \!!depth .5\d_tabl_tabulate_hrulethickness_local
\relax}
-\def\docoloredtabulatehrule
- {\faststartcolor[\currenttabulatelocalhrulecolor]%
- \donormaltabulatehrule
- \faststopcolor}
-
-\unexpanded\def\dotabulatehrule
- {\ifcase\tabulatelocalhrulethickness\else
- \iftrialtypesetting % does not happen as we nil the caller
- \donormaltabulatehrule
- \else\ifx\currenttabulatelocalhrulecolor\empty
- \donormaltabulatehrule
- \else
- \docoloredtabulatehrule
- \fi\fi
+\def\tabl_tabulate_hrule_inject_colored
+ {\dousecolorparameter\currenttabulationlocalhrulecolor
+ \tabl_tabulate_hrule_inject_normal}
+
+\unexpanded\def\tabl_tabulate_hrule_inject_first
+ {\ifcase\d_tabl_tabulate_hrulethickness_local\else
+ \tabl_tabulate_hrule_inject_normal
\fi}
-\def\donormaltabulatehlinerule
- {\leaders \hrule
- \!!height\dimexpr.5\lineheight-\strutdepth
- \!!depth-\dimexpr.5\lineheight-\strutdepth+\tabulatelocalhrulethickness
- \hfill}
-
-\def\docoloredtabulatehlinerule
- {\faststartcolor[\currenttabulatelocalhrulecolor]%
- \donormaltabulatehlinerule
- \faststopcolor}
-
-\def\dotabulatelinerule
- {\multispan\totaltabulatecolumns % \multispan is a plain macro
- % for the moment this one
- \strut\hskip\tabulateparameter\c!margin
- % neg values are ok !
- \hskip\tabulateindent\relax % new august 2003
- \ifcase\tabulatelocalhrulethickness\else
- \iftrialtypesetting % does not happen as we nil the caller
- \donormaltabulatehlinerule
- \else\ifx\currenttabulatelocalhrulecolor\empty
- \donormaltabulatehlinerule
+\unexpanded\def\tabl_tabulate_hrule_inject_second
+ {\ifcase\d_tabl_tabulate_hrulethickness_local\else
+ \ifx\currenttabulationlocalhrulecolor\empty
+ \tabl_tabulate_hrule_inject_normal
\else
- \docoloredtabulatehlinerule
- \fi\fi
- \fi
- \cr}
+ \tabl_tabulate_hrule_inject_colored
+ \fi
+ \fi}
+
+\let\tabl_tabulate_hrule_inject\relax
+
+\appendtoks
+ \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_second
+\to \t_tabl_tabulate_initializers_second
+
+% \def\totaltabulatecolumns{0}
+%
+% \def\donormaltabulatehlinerule
+% {\leaders \hrule
+% \!!height\dimexpr.5\lineheight-\strutdepth
+% \!!depth-\dimexpr.5\lineheight-\strutdepth+\d_tabl_tabulate_hrulethickness_local
+% \hfill}
+%
+% \def\docoloredtabulatehlinerule
+% {\dousecolorparameter\currenttabulationlocalhrulecolor
+% \donormaltabulatehlinerule}
+%
+% \def\dotabulatelinerule
+% {\multispan\totaltabulatecolumns % \multispan is a plain macro
+% % for the moment this one
+% \strut\hskip\d_tabl_tabulate_margin
+% % neg values are ok !
+% \hskip\d_tabl_tabulate_indent\relax % new august 2003
+% \ifcase\d_tabl_tabulate_hrulethickness_local\else
+% \iftrialtypesetting % does not happen as we nil the caller
+% \donormaltabulatehlinerule
+% \else\ifx\currenttabulationlocalhrulecolor\empty
+% \donormaltabulatehlinerule
+% \else
+% \docoloredtabulatehlinerule
+% \fi\fi
+% \fi
+% \cr}
%D Color:
@@ -1182,149 +1440,222 @@
% \NC test \NC[yellow] test \NC test \NC \NR
% \stoptabulate
-\unexpanded\def\settabulatecolor#1% we could store the attributes at the cost of a lua call
+\unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call
{\begingroup
- \doinitializeboxbackgrounds
- \global\settrue\tabulatehascolors
- \ifnum\tabulatecolumn>\maxtabularcolorcolumn
- \global\maxtabularcolorcolumn\tabulatecolumn
+ \node_backgrounds_boxes_initialize % name might change
+ \global\settrue\c_tabl_tabulate_has_colors
+ \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_colorcolumn
+ \global\c_tabl_tabulate_max_colorcolumn\c_tabl_tabulate_column
\fi
- \setxvalue{\??tt:c:\the\tabulatecolumn}{#1}%
+ \setxvalue{\??tabulatecolor\the\c_tabl_tabulate_column}{#1}%
\attribute\backgroundattribute\plusone
- \faststartcolor[#1]\strut\char0\faststopcolor
+ \dousecolorparameter{#1}\strut\char\zerocount % hack
\endgroup}
-\def\repeatsettabulatecolor
+\def\tabl_tabulate_color_repeat_second % for split off lines
{\begingroup
- \ifcsname\??tt:c:\the\tabulatecolumn\endcsname
+ \ifcsname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname
\attribute\backgroundattribute\plusone
- \faststartcolor[\csname\??tt:c:\the\tabulatecolumn\endcsname]\strut\char0\faststopcolor
+ \expandafter\dousecolorparameter\csname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname\strut\char\zerocount % hack
\fi
\endgroup}
-\def\resettabulatecolors
- {\ifcase\maxtabularcolorcolumn\else
- \doresettabulatecolors
+\let\tabl_tabulate_color_repeat\relax
+
+\appendtoks
+ \ifconditional\c_tabl_tabulate_has_colors
+ \let\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second
+ \fi
+\to \t_tabl_tabulate_initializers_second
+
+\def\tabl_tabulate_color_reset
+ {\ifcase\c_tabl_tabulate_max_colorcolumn\else
+ \tabl_tabulate_color_reset_indeed
\fi}
-\def\doresettabulatecolors
- {\dorecurse\maxtabularcolorcolumn{\letgvalue{\??tt:c:\recurselevel}\undefined}} % slow
+% \def\tabl_tabulate_color_reset_indeed
+% {\dorecurse\c_tabl_tabulate_max_colorcolumn{\letgvalue{\??tabulatecolor\recurselevel}\undefined}} % slow
+
+\def\tabl_tabulate_color_reset_indeed
+ {\dofastloopcs\c_tabl_tabulate_max_colorcolumn\tabl_tabulate_color_reset_step}
+
+\def\tabl_tabulate_color_reset_step % undefined or empty?
+ {\global\expandafter\let\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined}
\appendtoks
- \resettabulatecolors
-\to \everyaftertabulaterow
+ \tabl_tabulate_color_reset
+\to \t_tabl_tabulate_every_after_row
\appendtoks
- \global\setfalse\tabulatehascolors
+ \global\setfalse\c_tabl_tabulate_has_colors
\to \everytabulate
-%D When set to true, no (less) break optimization is done.
+% \def\tabl_tabulate_register_par_options_indeed
+% {\iftrialtypesetting \else
+% \registerparoptions
+% \ifinsidefloat
+% % that is, an unbreakable one
+% \glet\tabl_tabulate_register_par_options\empty
+% \else
+% % unsafe in crossing pages, at each b...
+% % \glet\tabl_tabulate_register_par_options\empty
+% \fi
+% \fi}
+%
+% \appendtoks
+% \glet\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_indeed
+% \to \everytabulate
-%D The main processing macro is large but splitting it up
-%D would make things less clear.
+\def\tabl_tabulate_register_par_options_first % maybe track here if needed
+ {}
-\def\doregistertabulateparoptions
- {\iftrialtypesetting \else
- \registerparoptions
- \ifinsidefloat
- % that is, an unbreakable one
- \glet\registertabulateparoptions\empty
- \else
- % unsafe in crossing pages, at each b...
- % \glet\registertabulateparoptions\empty
- \fi
+\def\tabl_tabulate_register_par_options_second
+ {\registerparoptions
+ \ifinsidefloat
+ % that is, an unbreakable one
+ \glet\tabl_tabulate_register_par_options\empty
+ \else
+ % unsafe in crossing pages, at each b...
+ % \glet\tabl_tabulate_register_par_options\empty
\fi}
+\let\tabl_tabulate_register_par_options\relax
+
\appendtoks
- \glet\registertabulateparoptions\doregistertabulateparoptions
-\to \everytabulate
+ \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_first
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_second
+\to \t_tabl_tabulate_initializers_second
\appendtoks
- \registertabulateparoptions
-\to \everytabulaterow
+ \tabl_tabulate_register_par_options
+\to \t_tabl_tabulate_every_row
-\def\flushtabulateindent
- {\ifnum\tabulatecolumn=\zerocount
- \hbox to \tabulateindent
+\def\tabl_tabulate_flush_indent
+ {\ifnum\c_tabl_tabulate_column=\zerocount
+ \hbox to \d_tabl_tabulate_indent
{% we now have a local hsize, and since we want to
% register positional info (i.e. real hsizes) we
% need to reconstitute the original hsize
- \advance\hsize\tabulateindent
+ \advance\hsize\d_tabl_tabulate_indent
% this is indeed rather messy and took a few hours
% to dis/uncover
- \the\everytabulaterow
+ \the\t_tabl_tabulate_every_row
\hss}%
\fi}
-\def\totaltabulatecolumns{0}
-
-\def\handletabulatedigits{\digits}
+\def\tabl_tabulate_digits{\digits}
%D Beware, we cannot use \type {\unexpanded} on \type {\HL}
%D cum suis, since \TEX's hard coded noalign lookahead fails
%D on it! I mistakenly added this for a while.
-\setvalue{\??tt:\c!align:\v!normal}{0}
-\setvalue{\??tt:\c!align:\v!right }{1}
-\setvalue{\??tt:\c!align:\v!left }{2}
-\setvalue{\??tt:\c!align:\v!middle}{3}
+\setvalue{\??tabulatealigning\v!normal}{0}
+\setvalue{\??tabulatealigning\v!right }{1}
+\setvalue{\??tabulatealigning\v!left }{2}
+\setvalue{\??tabulatealigning\v!middle}{3}
+
+\setvalue{\??tabulateheader\v!repeat}{\plusone}
+\setvalue{\??tabulateheader\v!text }{\plustwo}
-\setvalue{\??tt:\c!header:\v!repeat}{\plusone}
-\setvalue{\??tt:\c!header:\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{\hbox\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}
-\def\tabulatebskipone {\setbox\tabulatebox\vbox\bgroup\glet\tabulatehook\notabulatehook}
-\def\tabulateeskipone {\par\egroup\glet\tabulatehook\dotabulatehook}
-\def\tabulatexbskipone{\hbox\bgroup\vbox\bgroup\glet\tabulatehook\notabulatehook}
-\def\tabulatexeskipone{\par\egroup\egroup\glet\tabulatehook\dotabulatehook}
+\let\tabl_tabulate_bbskip\relax
+\let\tabl_tabulate_eeskip\relax
+\let\tabl_tabulate_bskip \relax
+\let\tabl_tabulate_eskip \relax
+\let\tabl_tabulate_xbskip\relax
+\let\tabl_tabulate_xeskip\relax
-\def\tabulatebaselinecorrection
- {\def\dobaselinecorrection % todo: mkiv
- {\vskip-\prevdepth+\strutdp+\strutdp\relax}%
+\appendtoks
+ \let\tabl_tabulate_bbskip\relax
+ %\let\tabl_tabulate_eeskip\relax % adapted by bskip
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_first
+ \let\tabl_tabulate_eskip \tabl_tabulate_eskip_first
+ \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_first
+ \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_first
+\to \t_tabl_tabulate_initializers_first
+
+\def\tabl_tabulate_baselinecorrection % keep an eye on this one
+ {\def\dobaselinecorrection{\vskip\dimexpr-\prevdepth+\strutdp+\strutdp\relax}% todo: mkiv
\baselinecorrection}
-\unexpanded\def\tabulateVLone{\tabulatevruledcolumn\zerocount}
-\unexpanded\def\tabulateNCone{\tabulatenormalcolumn\zerocount}
-\unexpanded\def\tabulateRCone{\tabulatenormalcolumn\plusone}
-\unexpanded\def\tabulateHCone{\tabulatenormalcolumn\plustwo}
-\unexpanded\def\tabulateEQone{\tabulateequalcolumn \zerocount}
-\unexpanded\def\tabulateRQone{\tabulateequalcolumn \plusone}
-\unexpanded\def\tabulateHQone{\tabulateequalcolumn \plustwo}
-\unexpanded\def\tabulateNGone{\NC\handletabulatecharalign}
-\unexpanded\def\tabulateNNone{\NC\handletabulatedigits} % new, undocumented, test first
-\unexpanded\def\tabulateNDone{\NC\handletabulatedigits} % same, for old times sake
-
-\unexpanded\def\tabulateHRone{\doHR\zerocount}
-
-\unexpanded\def\tabulateCCone{\global\tabulatelocalcolorspan\zerocount\tabulatecolorcolumn\zerocount}
-\unexpanded\def\tabulateCLone{\global\tabulatelocalcolorspan\plusone \tabulatecolorcolumn\zerocount}
-\unexpanded\def\tabulateCMone{\global\tabulatelocalcolorspan\plustwo \tabulatecolorcolumn\zerocount}
-\unexpanded\def\tabulateCRone{\global\tabulatelocalcolorspan\plusthree\tabulatecolorcolumn\zerocount}
-
-\unexpanded\def\tabulateNRone % next row
- {\global\advance\noftabulatelines\plusone
- \global\setfalse\tabulatefirstflushed
- \global\setfalse\tabulateequal
- \global\tabulatecolumn\zerocount
- \resettabulatepheight
- \unskip\unskip\crcr\flushtabulated
+\unexpanded\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount}
+\unexpanded\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount}
+\unexpanded\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\plusone}
+\unexpanded\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\plustwo}
+\unexpanded\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \zerocount}
+\unexpanded\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \plusone}
+\unexpanded\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \plustwo}
+
+\unexpanded\def\tabl_tabulate_NG_first{\NC\tabl_tabulate_charalign}
+\unexpanded\def\tabl_tabulate_NN_first{\NC\tabl_tabulate_digits} % new, undocumented, test first
+\unexpanded\def\tabl_tabulate_ND_first{\NC\tabl_tabulate_digits} % same, for old times sake
+\unexpanded\def\tabl_tabulate_NR_first{\tabl_tabulate_NR_common\tabl_tabulate_check_penalties} % next row
+\unexpanded\def\tabl_tabulate_NB_first{\tabl_tabulate_NR_common\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}
+
+\appendtoks
+ \let\VL\tabl_tabulate_VL_first
+ \let\NC\tabl_tabulate_NC_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
+\to \t_tabl_tabulate_initializers_first
+
+\appendtoks
+ \let\SR\NR
+ \let\FR\NR
+ \let\MR\NR
+ \let\LR\NR
+ \let\AR\NR
+\to \t_tabl_tabulate_initializers_first
+
+\unexpanded\def\tabl_tabulate_NR_common#1%
+ {\global\advance\c_tabl_tabulate_noflines\plusone
+ \global\setfalse\c_tabl_tabulate_firstflushed
+ \global\setfalse\c_tabl_tabulate_equal
+ \global\c_tabl_tabulate_column\zerocount
+ \tabl_tabulate_pheight_reset
+ \unskip\unskip\crcr\tabl_tabulate_flush_collected
\starttabulatenoalign
- \the\everyaftertabulaterow
- \checktabulatepenaltiesa
+ \the\t_tabl_tabulate_every_after_row
+ #1%
\stoptabulatenoalign}
-\def\checktabulatepenaltiesa
- {\iftolerantTABLEbreak\else
- \ifnum\totalnoftabulatelines=\plusone
+\def\tabl_tabulate_check_penalties
+ {\ifconditional\c_tabl_tabulate_tolerant_break\else
+ \ifnum\c_tabl_tabulate_totalnoflines=\plusone
% \allowbreak
\else
- \ifconditional\tabulatesomeamble \ifcase\tabulaterepeathead \else
+ \ifconditional\c_tabl_tabulate_someamble \ifcase\c_tabl_tabulate_repeathead \else
\allowbreak
\fi \fi
- \ifnum\noftabulatelines=\plusone
- \dotabulatenobreak
- \else\ifnum\noftabulatelines=\minusnoftabulatelines
- \ifnum\tabulatemaxplines<\plustwo
- \dotabulatenobreak
+ \ifnum\c_tabl_tabulate_noflines=\plusone
+ \tabl_tabulate_nobreak_inject
+ \else\ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_minusnoflines
+ \ifnum\c_tabl_tabulate_plines_max<\plustwo
+ \tabl_tabulate_nobreak_inject
\else
\allowbreak % needed with pbreak prevention
\fi
@@ -1333,66 +1664,85 @@
\fi\fi
\fi
\fi
- \global\setfalse\tabulatefirstflushed}
+ \global\setfalse\c_tabl_tabulate_firstflushed}
-\def\tabulatebbskiptwo
- {\ifvoid\tablebox\tabulatecolumn
- \ifx\flushtabulatedindeed\empty\else
+\unexpanded\def\tabl_tabulate_bbskip_second_split_yes
+ {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
+ \ifx\tabl_tabulate_flush_collected_indeed\empty\else
\setbox0\hbox
\fi
\fi}
-\def\tabulatebskiptwoeskip
+\unexpanded\def\tabl_tabulate_eskip_second
{\par\egroup
- \settabulatepheight
- \glet\tabulatehook\dotabulatehook
- \splitofftabulatebox}
+ \tabl_tabulate_pheight_set
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \tabl_tabulate_splitoff_box}
-\def\tabulatebskiptwo
- {\ifvoid\tablebox\tabulatecolumn
+\unexpanded\def\tabl_tabulate_bskip_second_split_yes
+ {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
% first line
- \global\setbox\tablebox\tabulatecolumn\vbox
+ \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox
\bgroup
- \glet\tabulatehook\notabulatehook
- \ifconditional\tabulateautomode\hsize\tabulatewidth\fi
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
+ \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
% \begstrut % interferes with pre-\pars
% evt: \appendtoks\begstrut\to\everypar
\ignorespaces
- \let\eskip\tabulatebskiptwoeskip
+ \let\tabl_tabulate_eskip\tabl_tabulate_eskip_second
\else
% successive lines
- \let\eskip\empty
+ \let\tabl_tabulate_eskip\empty
\dontcomplain
- \glet\tabulatehook\dotabulatehook
- \expandafter\splitofftabulatebox
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \expandafter\tabl_tabulate_splitoff_box
\fi}
-\def\tabulatexbskiptwo{\bskip}
-\def\tabulatexeskiptwo{\eskip}
+\unexpanded\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip}
+\unexpanded\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip}
-\def\dotabulateflushtabulatedtwo
- {\glet\flushtabulatedindeed\empty
- \global\tabulatecolumn\zerocount
- \handletabulatepbreak
- \dorecurse\tabulatecolumns % was: \noftabcolumns
- {\ifvoid\tablebox\recurselevel\else
- \gdef\flushtabulatedindeed{\the\tabulatedummy}%
- \fi}%
- \global\settrue\tabulatefirstflushed}
+\unexpanded\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}
-\def\tabulateflushtabulatedtwo
- {\tabulatenoalign{\dotabulateflushtabulatedtwo}%
- \flushtabulatedindeed}
+\unexpanded\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}%
+ \tabl_tabulate_flush_collected_indeed}
-\def\tabulatebskipthree
+\unexpanded\def\tabl_tabulate_bskip_second_split_nop
{\vtop\bgroup
- \ifconditional\tabulateautomode\hsize\tabulatewidth\fi
+ \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
% \begstrut % interferes with pre-\pars
% evt: \appendtoks\begstrut\to\everypar
\ignorespaces}
-\def\tabulateeskipthree % vertical strut added august 2003
- {\par\verticalstrut\vskip-\struttotal\egroup}
+\unexpanded\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003
+ {\par\verticalstrut
+ \vskip-\struttotal
+ \egroup}
+
+% \let\tabl_tabulate_eskip \relax % adapted by bskip
+% \let\tabl_tabulate_eeskip\relax % adapted by bskip
+
+\appendtoks
+ \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_second
+ \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_second
+ \ifconditional\c_tabl_tabulate_split
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_yes
+ \let\tabl_tabulate_bbskip\tabl_tabulate_bbskip_second_split_yes
+ \else
+ \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_nop
+ \let\tabl_tabulate_eskip \tabl_tabulate_eskip_second_split_nop
+ \fi
+\to \t_tabl_tabulate_initializers_second
% see ***
%
@@ -1401,116 +1751,113 @@
% \starttabulate[||] \dorecurse{100}{\NC Eins \NC \NR \HL} \stoptabulate
% \stoptext
-% old crap:
-%
-% \ifnum\noftabulatelines>\plusone
-% \ifnum\noftabulatelines<\minusnoftabulatelines
-% % *** somehow topskip messes up as it's intercepted
-% % \vskip \topskip\allowbreak\vskip- \topskip
-% % messy anyhow so this needs to be improved, so for
-% % the moment we keep this bugged variant
-% \vskip1\topskip
-% \allowbreak
-% \vskip-1\topskip
-
-\def\tabulateXXnone{\starttabulatenoalign\tabulateignorehrulespec\stoptabulatenoalign}
-
-\def\tabulateFLfive{\starttabulatenoalign\tabulatepickuphrulespec\dotabulateFLfive}
-\def\tabulateMLfive{\starttabulatenoalign\tabulatepickuphrulespec\dotabulateMLfive}
-\def\tabulateLLfive{\starttabulatenoalign\tabulatepickuphrulespec\dotabulateLLfive}
-\def\tabulateTLfive{\starttabulatenoalign\tabulatepickuphrulespec\dotabulateTLfive}
-\def\tabulateBLfive{\starttabulatenoalign\tabulatepickuphrulespec\dotabulateBLfive}
-%def\tabulateHLfive{\starttabulatenoalign\tabulatepickuphrulespec\dotabulateHLfive}
-
-% we can use one common spec: (saves 4 macros)
-%
-% \def\dotabulatecheckhrulespec#1%
-% {\iftrialtypesetting
-% \expandafter\tabulateignorehrulespec\expandafter\stoptabulatenoalign
-% \else
-% \expandafter\tabulatepickuphrulespec\expandafter\dotabulateFLfive
-% \fi}
+\def\tabl_tabulate_XX_none{\starttabulatenoalign\tabl_tabulate_hrule_spec_ignore\stoptabulatenoalign}
+
+\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}
-\unexpanded\def\dotabulateFLfive
+\unexpanded\def\tabl_tabulate_FL_second_indeed
{\ifinsidefloat\else
- \doifemptyvalue{\??tt\currenttabulate\c!before} % no expansion
- {\tabulatebaselinecorrection}%
+ \doifempty{\tabulationparameter\c!before}\tabl_tabulate_baselinecorrection % no expansion
\fi
- \dotabulatehrule
- \dotabulatenobreak
- \dotabulateruleseparator
+ \tabl_tabulate_hrule_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
\prevdepth\strutdp
- \dotabulatenobreak
+ \tabl_tabulate_nobreak_inject
\stoptabulatenoalign}
-\unexpanded\def\dotabulateMLfive
- {\dotabulateruleseparator
- \dotabulatehrule
- \vskip-\tabulateparameter\c!rulethickness
- \dotabulatehrule
+\unexpanded\def\tabl_tabulate_ML_second_indeed
+ {\tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_hrule_inject
+ \vskip-\p_rulethickness\relax
+ \tabl_tabulate_hrule_inject
\nobreak
- \dotabulateruleseparator
+ \tabl_tabulate_column_rule_separator_inject
\stoptabulatenoalign}
-\unexpanded\def\dotabulateLLfive
- {\dotabulatenobreak
- \dotabulateruleseparator
- \dotabulatenobreak
- \dotabulatehrule
+\unexpanded\def\tabl_tabulate_LL_second_indeed
+ {\tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_hrule_inject
\ifinsidefloat\else
- \doifemptyvalue{\??tt\currenttabulate\c!after} % no expansion
+ \doifempty{\tabulationparameter\c!after}
{\vskip\strutdp
\verticalstrut
\vskip-\struttotal}%
\fi
\stoptabulatenoalign}
-\unexpanded\def\dotabulateTLfive
- {\dotabulatenobreak
- \dotabulateruleseparator
- \dotabulatenobreak
- \dotabulatehrule
- \dotabulatenobreak
- \dotabulateruleseparator
+\unexpanded\def\tabl_tabulate_TL_second_indeed
+ {\tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_hrule_inject
+ \tabl_tabulate_nobreak_inject
+ \tabl_tabulate_column_rule_separator_inject
%\prevdepth\strutdp % todo, might differ between TL and BL
- \dotabulatenobreak
+ \tabl_tabulate_nobreak_inject
\stoptabulatenoalign}
-\let\dotabulateBLfive\dotabulateTLfive
+\let\tabl_tabulate_BL_second\tabl_tabulate_TL_second
-\def\tabulateHLfive
+\def\tabl_tabulate_HL_second
{\csname
- \ifnum\noftabulatelines=\zerocount F\else
- \ifnum\noftabulatelines=\totalnoftabulatelines L\else
- M\fi\fi
+ \ifnum\c_tabl_tabulate_noflines=\zerocount F\else
+ \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else
+ M\fi\fi
L\endcsname}
-\def\tabulatedoHRfive % horizontal rule line (break untested)
- {\starttabulatenoalign
- \globallet\dotabulateautoline\dotabulatelinerule
- %\ifcase#1\or % todo: check what this does
- \ifnum\noftabulatelines=\zerocount
- \glet\dotabulateautoline\donothing
- \else\ifnum\noftabulatelines=\totalnoftabulatelines
- \glet\dotabulateautoline\donothing
- \fi\fi
- %\fi
- \dotabulatenobreak
- \stoptabulatenoalign
- \dotabulateautoline
- \starttabulatenoalign
- \nobreak
- \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
- \ifnum\noftabulatelines=\totalnoftabulatelines
- \@EA\dotabulatenobreak
- \else
- \@EA\allowbreak
- \fi
- \stoptabulatenoalign
- \dotabulateautoline
- \starttabulatenoalign
- \dotabulatenobreak
- \stoptabulatenoalign}
+\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
+\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
+\to \t_tabl_tabulate_initializers_second
+
+% \def\tabulatedoHRfive % horizontal rule line (break untested)
+% {\starttabulatenoalign
+% \globallet\dotabulateautoline\dotabulatelinerule
+% %\ifcase#1\or % todo: check what this does
+% \ifnum\noftabulatelines=\zerocount
+% \glet\dotabulateautoline\donothing
+% \else\ifnum\noftabulatelines=\totalnoftabulatelines
+% \glet\dotabulateautoline\donothing
+% \fi\fi
+% %\fi
+% \dotabulatenobreak
+% \stoptabulatenoalign
+% \dotabulateautoline
+% \starttabulatenoalign
+% \nobreak
+% \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
+% \ifnum\noftabulatelines=\totalnoftabulatelines
+% \@EA\dotabulatenobreak
+% \else
+% \@EA\allowbreak
+% \fi
+% \stoptabulatenoalign
+% \dotabulateautoline
+% \starttabulatenoalign
+% \dotabulatenobreak
+% \stoptabulatenoalign}
% \dorecurse{10}{
% \starttabulate[|l|]
@@ -1531,7 +1878,7 @@
% \stoptabulate
% }
-% to be redone
+% This needs checking:
\def\tabulaterule {\HR} % a rule with lineheight
\def\tabulateline {\HL} % just a spaced rule
@@ -1546,27 +1893,27 @@
% places where we can use \LUA\ code (for instance in alignment of
% numbers. The repeat parser is replace at the \LUA\ end as well.
-\gdef\processtabulate[#1]% in the process of optimizing
- {\tabulateunit\tabulateparameter\c!unit
- \checkfulltabulatecontent
- \defaulttabulatevrulethickness\tabulateparameter\c!rulethickness
- \defaulttabulatehrulethickness\tabulateparameter\c!rulethickness
- \edef\defaulttabulatevrulecolor{\tabulateparameter\c!rulecolor}%
- \edef\defaulttabulatehrulecolor{\tabulateparameter\c!rulecolor}%
- \edef\@@tabulatealign{\executeifdefined{\??tt:\c!align:\tabulateparameter\c!align}0}%
- \tabulateposskip.5\tabulateunit
- \tabulatepreskip\zeropoint
- \firstpretabskip\tabulateposskip
- \lastposttabskip\tabulateposskip
- \global\tabulatecolumns\zerocount
- \global\nofautotabulate\zerocount
- \global\noftabulatelines\zerocount
- \totalnoftabulatelines\noftabulatelines
- \minusnoftabulatelines\noftabulatelines
- \global\tabulatepwidth\zeropoint
- \global\tabulatexwidth\zeropoint
- \global\setfalse\tabulateequal
- \resettabulatepheight
+\let\tabl_tabulate_flush_collected \empty
+\let\tabl_tabulate_flush_collected_indeed\empty
+
+\def\tabl_tabulate_process
+ {\c_tabl_tabulate_pass\plusone
+ \tabl_tabulate_check_full_content
+ \edef\v_tabl_tabulate_align{\executeifdefined{\??tabulatealigning\p_align}0}%
+ \s_tabl_tabulate_post\zeropoint
+ \s_tabl_tabulate_pre\zeropoint
+ \s_tabl_tabulate_first.5\d_tabl_tabulate_unit
+ \s_tabl_tabulate_last\s_tabl_tabulate_first
+ \global\c_tabl_tabulate_columns\zerocount
+ \global\c_tabl_tabulate_nofauto\zerocount
+ \global\c_tabl_tabulate_noflines\zerocount
+ \c_tabl_tabulate_totalnoflines\zerocount
+ \c_tabl_tabulate_minusnoflines\zerocount
+ \global\d_tabl_tabulate_width_p\zeropoint
+ \global\d_tabl_tabulate_width_w\zeropoint
+ \global\setfalse\c_tabl_tabulate_equal
+ \tabl_tabulate_pheight_reset
+ \tabskip\zeropoint
\ifinsidesplitfloat
\donetrue
\else\ifinsidefloat
@@ -1575,143 +1922,138 @@
\donetrue
\fi\fi
\ifdone
- \tabulaterepeathead\executeifdefined{\??tt:\c!header:\tabulateparameter\c!header}\zerocount
+ \c_tabl_tabulate_repeathead\executeifdefined{\??tabulateheader\tabulationparameter\c!header}\zerocount
+ \else
+ \c_tabl_tabulate_repeathead\zerocount
\fi
- \let\VL\tabulateVLone
- \let\NC\tabulateNCone
- \let\RC\tabulateRCone
- \let\HC\tabulateHCone
- \let\EQ\tabulateEQone
- \let\RQ\tabulateRQone
- \let\HQ\tabulateHQone
- \let\NG\tabulateNGone
- \let\NN\tabulateNNone
- \let\ND\tabulateNDone
- \let\NR\tabulateNRone
- \let\CC\tabulateCCone
- \let\CL\tabulateCLone
- \let\CM\tabulateCMone
- \let\CR\tabulateCRone
- \let\SR\NR
- \let\FR\NR
- \let\MR\NR
- \let\LR\NR
- \let\AR\NR
- \let\FL\tabulateXXnone
- \let\ML\tabulateXXnone
- \let\LL\tabulateXXnone
- \let\TL\tabulateXXnone
- \let\BL\tabulateXXnone
- \let\HL\tabulateXXnone
- \let\HR\tabulateXXnone
- \glet\flushtabulated\empty
- \tabskip\zeropoint
- \ifdim\tabulateparameter\c!margin>\zeropoint
- \tabulatepreamble{\aligntab\flushtabulateindent\strut\alignmark\alignmark\tabskip\tabulateparameter\c!margin\strut\aligntab\alignmark\alignmark\tabskip\zeropoint}%
+ %
+ \the\t_tabl_tabulate_initializers_first % collect more here
+ %
+ \glet\tabl_tabulate_flush_collected\empty
+ \ifdim\d_tabl_tabulate_margin>\zeropoint
+ \t_tabl_tabulate_preamble
+ {\aligntab
+ \tabl_tabulate_flush_indent
+% \global\advance\c_tabl_tabulate_noflines\plusone
+ \strut
+ \alignmark\alignmark
+ \tabskip\d_tabl_tabulate_margin
+ \strut
+ \aligntab
+ \alignmark\alignmark
+ \tabskip\zeropoint}%
\else
- \tabulatepreamble{\aligntab\flushtabulateindent\strut\alignmark\alignmark\aligntab\alignmark\alignmark\tabskip\zeropoint}%
+ \t_tabl_tabulate_preamble
+ {\aligntab
+ \tabl_tabulate_flush_indent
+% \global\advance\c_tabl_tabulate_noflines\plusone
+ \strut
+ \alignmark\alignmark
+ \aligntab
+ \alignmark\alignmark
+ \tabskip\zeropoint}%
+ \fi
+ \d_tabl_tabulate_width\zeropoint
+ % these counters are set at the lua end
+ \c_tabl_tabulate_nofcolumns \zerocount
+ \c_tabl_tabulate_has_rule_spec_first\zerocount
+ \c_tabl_tabulate_has_rule_spec_last \zerocount
+ \ctxcommand{presettabulate(\!!bs\detokenizedtabulationparameter\c!format\!!es)}%
+ %
+ % \edef\totaltabulatecolumns{\the\numexpr3*\c_tabl_tabulate_columns+\plusfour}%
+ \d_tabl_tabulate_width\zeropoint
+ \tabl_tabulate_initialize_boxes\c_tabl_tabulate_columns
+ \t_tabl_tabulate_preamble\expandafter{\the\t_tabl_tabulate_preamble
+ \aligntab\alignmark\alignmark\global\advance\c_tabl_tabulate_column\plusone
+ }%
+ \t_tabl_tabulate_dummy\expandafter{\the\t_tabl_tabulate_dummy
+ \NC\unskip\unskip\crcr\tabl_tabulate_flush_collected % no count
+ }%
+ \global\c_tabl_tabulate_column\zerocount
+ \tabl_tabulate_pheight_reset
+ \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
+ \ifx\p_indenting\v!no
+ \forgetparindent
\fi
- \tabulatewidth\zeropoint
- \ctxcommand{presettabulate(\!!bs\detokenize{#1}\!!es)}%
- \edef\totaltabulatecolumns{\the\numexpr3*\tabulatecolumns+4}%
- \tabulatewidth\zeropoint
- \initializetableboxes\tabulatecolumns
- \appendtoks\aligntab\alignmark\alignmark\global\advance\tabulatecolumn\plusone\to\tabulatepreamble
- \appendtoks\NC\unskip\unskip\crcr\flushtabulated\to\tabulatedummy % no count
- \global\tabulatecolumn\zerocount
- \resettabulatepheight
- \let\bbskip\empty
- %\let\eeskip\empty
- \let\bskip \tabulatebskipone
- \let\eskip \tabulateeskipone
- \let\xbskip\tabulatexbskipone
- \let\xeskip\tabulatexeskipone
- \glet\tabulatehook\dotabulatehook
- \doifvalue{\??tt\currenttabulate\c!indenting}\v!no\forgetparindent
\ifinsidefloat
- \let\tabulateindent\!!zeropoint
+ \d_tabl_tabulate_indent\zeropoint
\else
- \setlocalhsize \hsize\localhsize
+ \setlocalhsize
+ \hsize\localhsize
\fi
\dontcomplain
\forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved
\everypar\everytabulatepar
\setbox0\vbox % outside \if because of line counting
{\notesenabledfalse
- \let\tabulateindent\!!zeropoint
+ \d_tabl_tabulate_indent\zeropoint
\settrialtypesetting % very important
- \@EA\halign\@EA{\the\tabulatepreamble\crcr\fulltabulatecontent\crcr}}%
- \ifnum\nofautotabulate>\zerocount
- % so, even if the natural size is larger, in the final
- % run, we force the calculated width
- \tabulatewidth\dimexpr\hsize-\wd0-\tabulatepwidth-\tabulatexwidth\relax
- \ifnum\nofautotabulate>\zerocount
- \divide\tabulatewidth \nofautotabulate\relax
+ \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}%
+ \ifnum\c_tabl_tabulate_nofauto>\zerocount
+ % so, even if the natural size is larger, in the final run, we force the calculated width
+ \d_tabl_tabulate_width\dimexpr\hsize-\wd0-\d_tabl_tabulate_width_p-\d_tabl_tabulate_width_w\relax
+ \ifnum\c_tabl_tabulate_nofauto>\zerocount
+ \divide\d_tabl_tabulate_width \c_tabl_tabulate_nofauto\relax
\fi
\fi
- \let\xbskip\tabulatexbskiptwo
- \let\xeskip\tabulatexeskiptwo
- \ifconditional\tabulatesplit
+ \ifconditional\c_tabl_tabulate_split
\splittopskip\strutht
- \glet\flushtabulatedindeed\empty
- \let\bbskip\tabulatebbskiptwo
- \let\bskip\tabulatebskiptwo
- \glet\flushtabulated\tabulateflushtabulatedtwo
- \else
- % tabhook op alles ?
- \let\bskip\tabulatebskipthree
- \let\eskip\tabulateeskipthree
+ \glet\tabl_tabulate_flush_collected_indeed\empty
+ \glet\tabl_tabulate_flush_collected\tabl_tabulate_flush_second
+ \fi
+ \c_tabl_tabulate_totalnoflines\c_tabl_tabulate_noflines
+ \c_tabl_tabulate_minusnoflines\numexpr\c_tabl_tabulate_noflines+\minusone\relax
+ \global\c_tabl_tabulate_noflines\zerocount
+ %
+ \c_tabl_tabulate_pass\plustwo % final pass
+ \the\t_tabl_tabulate_initializers_second % collect more here
+ %
+ \ifx\p_line\v!line
+ \let\HL\HR
+ \let\tabulateautoline\tabulateautorule
+ \let\tabulateline\tabulaterule
\fi
- \totalnoftabulatelines\noftabulatelines
- \minusnoftabulatelines\numexpr\noftabulatelines+\minusone\relax
- \global\noftabulatelines\zerocount
- \let\FL\tabulateFLfive
- \let\ML\tabulateMLfive
- \let\LL\tabulateLLfive
- \let\TL\tabulateTLfive
- \let\BL\tabulateBLfive
- \let\HL\tabulateHLfive
- \let\HR\tabulateHRfive
- \doifvalue{\??tt\currenttabulate\c!rule}\v!line
- {\let\HL\HR
- \let\tabulateautoline\tabulateautorule
- \let\tabulateline\tabulaterule}%
- \tabulatepass\plustwo
%
- \ifcase\tabulaterepeathead
+ \ifcase\c_tabl_tabulate_repeathead
\ifinsidesplitfloat
- \setbox\tabulatebox\vbox \bgroup
+ \global\setbox\b_tabl_tabulate\vbox \bgroup
\else
- \startframedcontent[\tabulateparameter\c!frame]%
+ \startframedcontent[\tabulationparameter\c!frame]%
\fi
\else
- \setbox\tabulatebox\vbox \bgroup
+ \global\setbox\b_tabl_tabulate\vbox \bgroup
\fi
%
\dostarttagged\t!tabulate\empty
\dostarttagged\t!tabulaterow\empty
- \appendtoks\dostoptagged\dostarttagged\t!tabulaterow\empty\to\everycr
- \@EA\halign\@EA{\the\tabulatepreamble\crcr\fulltabulatecontent\crcr}%
+ \everycr\expandafter{\the\everycr\dostoptagged\dostarttagged\t!tabulaterow\empty}%
+ \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
\dostoptagged
\dostoptagged
\ifhmode\par\prevdepth\strutdp\fi % nog eens beter, temporary hack
- \doifvalue{\??tt\currenttabulate\c!distance}\v!grid{\vskip-\strutdp}% experimental tm-prikkels
+ \ifx\p_distance\v!grid
+ \vskip-\strutdp % experimental tm-prikkels
+ \fi
%
- \ifcase\tabulaterepeathead
+ \ifcase\c_tabl_tabulate_repeathead
\ifinsidesplitfloat
- \egroup \splittabulatebox\tabulatebox
+ \egroup % box
+ \egroup % settings
+ \tabl_split_box\b_tabl_tabulate
\else
\stopframedcontent
+ \egroup
\fi
\else
- \egroup \splittabulatebox\tabulatebox
+ \egroup % box
+ \egroup % settings
+ \tabl_split_box\b_tabl_tabulate
\fi
%
- \egroup
\ifinsidefloat \else
- \tabulateparameter\c!after
+ \tabulationparameter\c!after
\fi
- \egroup}
+ \egroup} % whole thing
% \egroup
@@ -1730,25 +2072,25 @@
% \NC test \NC \input tufte \relax \NC \NR
% \stoptabulate
-\def\splittabulatebox#1% #1 <> 0/2 / derived from the one in core-ntb.tex
+\def\tabl_split_box#1% #1 <> 0/2 / derived from the one in core-ntb.tex
{\ifinsidesplitfloat
- \dosplittabulatebox#1%
+ \tabl_split_box_indeed#1%
\else\ifinsidefloat
\unvbox#1%
\else
- \dosplittabulatebox#1%
+ \tabl_split_box_indeed#1%
\fi\fi}
-\def\dosplittabulatebox#1%
+\def\tabl_split_box_indeed#1%
{\resettsplit
\def\tsplitminimumfreelines{2}%
\def\tsplitminimumfreespace{0pt}%
\setbox\tsplitcontent\box#1%
- \ifcase\tabulaterepeathead\or
+ \ifcase\c_tabl_tabulate_repeathead\or
\setbox\tsplithead\vsplit\tsplitcontent to \lineheight
\setbox\tsplithead\vbox{\unvbox\tsplithead}%
\or
- \setbox\tsplithead\vbox{\hbox{\strut\tabulateparameter\c!title}}%
+ \setbox\tsplithead\vbox{\hbox{\strut\tabulationparameter\c!title}}%
\fi
\handletsplit}
@@ -1775,11 +2117,11 @@
% \NC text \NC text \NC \NR
% \stoptabulate
-\def\TabulateTB
+\def\tabl_tabulate_TB
{\starttabulatenoalign
- \dosingleempty\doTabulateTB}
+ \dosingleempty\tabl_tabulate_TB_indeed}
-\def\doTabulateTB[#1]%
+\def\tabl_tabulate_TB_indeed[#1]%
{\iffirstargument
\blank[#1]
\else
@@ -1789,19 +2131,68 @@
% to be tested:
%
-% \def\TabulateTB
+% \def\tabl_tabulate_TB
% {\starttabulatenoalign
-% \doiffastoptionalcheckelse\doTabulateTByes\doTabulateTBnop}
+% \doiffastoptionalcheckelse\tabl_tabulate_TB_yes\tabl_tabulate_TB_nop}
%
-% \def\doTabulateTByes[#1]%
+% \def\tabl_tabulate_TB_yes[#1]%
% {\blank[#1]
% \stoptabulatenoalign}
%
-% \def\doTabulateTBnop[#1]%
+% \def\tabl_tabulate_TB_nop[#1]%
% {\blank
% \stoptabulatenoalign}
-\appendtoks\let\TB\TabulateTB\to\everytabulate
+\appendtoks
+ \let\TB\tabl_tabulate_TB
+\to \everytabulate
+
+%D Some new trickery:
+%D
+%D \startbuffer
+%D \settrue\c_tabl_tabulate_splitoff_whitespace
+%D
+%D \starttabulate[|p(2cm)|p(2cm)|p(2cm)|]
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \par
+%D test 3b \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[line]
+%D test 3b \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[halfline]
+%D test 3b
+%D \blank[halfline]
+%D test 3c \NC \NR
+%D \NC \blank \NC \blank \NC \blank \NC \NR
+%D \NC test 1a \NC test 2a \NC test 3a
+%D \blank[halfline]
+%D test 3b
+%D \blank[halfline]
+%D test 3c \NC \NR
+%D \NC \blank \NC \blank \NC \NC \NR
+%D \NC test 1a
+%D \par
+%D test 1b
+%D \par
+%D test 1b \NC test 2a
+%D \par
+%D test 2b
+%D \par
+%D test 2b \NC test 3a \NC \NR
+%D \NC test 1a
+%D \blank
+%D test 1b
+%D \par
+%D test 1b \NC test 2a
+%D \par
+%D test 2b
+%D \blank
+%D test 2b \NC test 3a \NC \NR
+%D \stoptabulate
+%D \stopbuffer
+%D
+%D \typebuffer \start \getbuffer \stop
% \starttabulatie[|mc|]
% \NC \digits{100.000,00} \NC\NR
@@ -1843,35 +2234,4 @@
% \NC \digits $@@@.@@1,@@$ \NC\NR
% \stoptabulatie
-\unexpanded\def\setuptabulate
- {\dotripleempty\dosetuptabulate}
-
-\def\dosetuptabulate[#1][#2][#3]%
- {\ifthirdargument
- \getparameters[\??tt#1::#2][#3]%
- \else\ifsecondargument
- \getparameters[\??tt#1::][#2]%
- \else
- \getparameters[\??tt\v!tabulate::][#1]%
- \fi\fi}
-
-\setuptabulate
- [\c!unit=1em,
- EQ={:},
- \c!frame=\v!off,
- \c!bodyfont=,
- \c!rule=\v!normal,
- \c!rulecolor=,
- \c!rulethickness=\linewidth,
- \c!inner=,
- \c!before=\blank,
- \c!after=\blank,
- \c!distance={\v!depth,\v!medium},
- \c!align=\v!normal,
- \c!margin=\!!zeropoint,
- \c!split=\v!auto,
- \c!header=\v!yes,
- \c!title=,
- \c!indenting=\v!no]
-
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/tabl-tsp.mkii b/Master/texmf-dist/tex/context/base/tabl-tsp.mkii
index 49bb7ad90ed..59e9185e81d 100644
--- a/Master/texmf-dist/tex/context/base/tabl-tsp.mkii
+++ b/Master/texmf-dist/tex/context/base/tabl-tsp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Splitting,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/tabl-tsp.mkiv b/Master/texmf-dist/tex/context/base/tabl-tsp.mkiv
index d274df6cb4a..21182a98872 100644
--- a/Master/texmf-dist/tex/context/base/tabl-tsp.mkiv
+++ b/Master/texmf-dist/tex/context/base/tabl-tsp.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Splitting,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -28,23 +28,57 @@
% there is no need for a tracked structure number here
+%D When \type {inbetween} is made empty instead of the
+%D default \type {\page}, we will get delayed flushing
+%D and text may continue below the graphic.
+%D
+%D \starttyping
+%D \dorecurse{2}{\input tufte }
+%D
+%D \splitfloat[lines=auto,inbetween=]
+%D {\placetable{\dorecurse{5}{test\recurselevel\endgraf}}}
+%D {\bTABLE[split=yes]
+%D \bTR \bTD 11 \eTD \bTD \input tufte \eTD \eTR
+%D \bTR \bTD 12 \eTD \bTD \input zapf \eTD \eTR
+%D \bTR \bTD 13 \eTD \bTD \input bryson \eTD \eTR
+%D \bTR \bTD 14 \eTD \bTD test \eTD \eTR
+%D \bTR \bTD 21 \eTD \bTD \input tufte \eTD \eTR
+%D \bTR \bTD 22 \eTD \bTD \input zapf \eTD \eTR
+%D \bTR \bTD 23 \eTD \bTD \input bryson \eTD \eTR
+%D \bTR \bTD 24 \eTD \bTD test \eTD \eTR
+%D \bTR \bTD 31 \eTD \bTD \input tufte \eTD \eTR
+%D \bTR \bTD 32 \eTD \bTD \input zapf \eTD \eTR
+%D \bTR \bTD 33 \eTD \bTD \input bryson \eTD \eTR
+%D \bTR \bTD 34 \eTD \bTD test \eTD \eTR
+%D \eTABLE}
+%D
+%D \dorecurse{10}{\input tufte }
+%D \stoptyping
+
\newcount\noffloatssplits
-\unexpanded\def\setupfloatsplitting
- {\dodoubleargument\getparameters[\??si]}
+\settrue \onlyonesplitofffloat
+\setfalse\somenextsplitofffloat
+
+\newconditional\splitfloatdone
\newif\ifinsidesplitfloat % will become chardef
-\newtoks \everysplitfloatsetup
+\newtoks\everysplitfloatsetup
-\def\splitfloat
- {\dosingleempty\dosplitfloat}
+\def\extrasplitfloatlines{0}
+
+\let\splitfloatfinalizer\relax
\ifx\floatcaptionsuffix\undefined \else
\let\floatcaptionsuffix\empty % will become \splitfloatcaptionsuffix
\fi
-\def\extrasplitfloatlines{0}
+\unexpanded\def\setupfloatsplitting
+ {\dodoubleargument\getparameters[\??si]}
+
+\unexpanded\def\splitfloat
+ {\dosingleempty\dosplitfloat}
\def\dosplitfloat[#1]#2% nog dubbele refs
{\bgroup
@@ -59,119 +93,86 @@
\the\everysplitfloatsetup
\def\splitfloatcommand{#2}%
\global\settrue \onlyonesplitofffloat
- \global\setfalse\somenextplitofffloat
+ \global\setfalse\somenextsplitofffloat
\dopushsavedfloats
\@@sibefore
\let\next} % \bgroup
-\def\checksplitfloat
- {\ifconditional\splitfloatdone\else
- \blank{\tttf \getmessage\m!floatblocks{13}\empty}\blank
- \showmessage\m!floatblocks{13}\empty
+\unexpanded\def\checksplitfloat
+ {\ifconditional\splitfloatdone
+ \splitfloatfinalizer % a weird place (could interfere with flushing)
+ \else
+ \blank{\tttf \getmessage\m!floatblocks{13}\empty}\blank
+ \showmessage\m!floatblocks{13}\empty
\fi}
-\settrue \onlyonesplitofffloat
-\setfalse\somenextplitofffloat
-
-%D When \type {inbetween} is made empty instead of the
-%D default \type {\page}, we will get delayed flushing
-%D and text may continue below the graphic.
-%D
-%D \starttyping
-%D \dorecurse{2}{\input tufte }
-%D
-%D \splitfloat[lines=auto,inbetween=]
-%D {\placetable{\dorecurse{5}{test\recurselevel\endgraf}}}
-%D {\bTABLE[split=yes]
-%D \bTR \bTD 11 \eTD \bTD \input tufte \eTD \eTR
-%D \bTR \bTD 12 \eTD \bTD \input zapf \eTD \eTR
-%D \bTR \bTD 13 \eTD \bTD \input bryson \eTD \eTR
-%D \bTR \bTD 14 \eTD \bTD test \eTD \eTR
-%D \bTR \bTD 21 \eTD \bTD \input tufte \eTD \eTR
-%D \bTR \bTD 22 \eTD \bTD \input zapf \eTD \eTR
-%D \bTR \bTD 23 \eTD \bTD \input bryson \eTD \eTR
-%D \bTR \bTD 24 \eTD \bTD test \eTD \eTR
-%D \bTR \bTD 31 \eTD \bTD \input tufte \eTD \eTR
-%D \bTR \bTD 32 \eTD \bTD \input zapf \eTD \eTR
-%D \bTR \bTD 33 \eTD \bTD \input bryson \eTD \eTR
-%D \bTR \bTD 34 \eTD \bTD test \eTD \eTR
-%D \eTABLE}
-%D
-%D \dorecurse{10}{\input tufte }
-%D \stoptyping
-
-\newconditional\splitfloatdone
-
\def\dodowithsplitofffloat
- {\dowithnextbox
- {\forgetall
- \dontcomplain
- \global\settrue\splitfloatdone
- \nodelocationmode\zerocount % bypass auto-renumbering
- \global\advance\noffloatssplits\plusone
- \ifcase\noffloatssplits\relax
- \or
- \ifconditional\onlyonesplitofffloat
- \let\floatcaptionsuffix\empty
- \fi
- \else
- \global\settrue\usesamefloatnumber % one shot
- \fi
- \bgroup
- \ifconditional\somenextplitofffloat
- \settrue\retainfloatnumber
- \notesenabledfalse % best here, experimental, brrr; test with note in caption
- \else
- \setfalse\retainfloatnumber
- \fi
- \splitfloatcommand{\box\nextbox}%
- \egroup
- \ifconditional\somenextplitofffloat
- \doifelsenothing\@@siinbetween
- {\ifconditional\splitfloatfirstdone\else\page\fi}
- \@@siinbetween
- \else
- \@@siafter
- \dopopsavedfloats
- \doflushsavedfloats
- \fi
- \global\settrue\splitfloatfirstdone}%
- \vbox}
+ {\dowithnextboxcs\dodowithsplitofffloatfinish\vbox}
+
+\def\dodowithsplitofffloatfinish
+ {\forgetall
+ \dontcomplain
+ \global\settrue\splitfloatdone
+ % \nodelocationmode\zerocount % bypass auto-renumbering
+ \global\advance\noffloatssplits\plusone
+ \ifcase\noffloatssplits\relax \or
+ \ifconditional\onlyonesplitofffloat
+ \let\floatcaptionsuffix\empty
+ \fi
+ \fi
+ \bgroup
+ \ifconditional\somenextsplitofffloat
+ \notesenabledfalse % best here, experimental, brrr; test with note in caption
+ \fi
+ \splitfloatcommand{\box\nextbox}%
+ \egroup
+ \ifconditional\somenextsplitofffloat
+ \doifelsenothing\@@siinbetween
+ {\ifconditional\splitfloatfirstdone\else\page\fi}
+ \@@siinbetween
+ \else
+ \@@siafter
+ \dopopsavedfloats
+ \doflushsavedfloats
+ \fi
+ \global\settrue\splitfloatfirstdone}
\def\nodowithsplitofffloat
- {\dowithnextbox
- {\forgetall
- \dontcomplain
- \box\nextbox % maybe an option to unvbox
- \global\settrue\splitfloatfirstdone}%
- \vbox}
+ {\dowithnextboxcs\nodowithsplitofffloatfinish\vbox}
+
+\def\nodowithsplitofffloatfinish
+ {\forgetall
+ \dontcomplain
+ \box\nextbox % maybe an option to unvbox
+ \global\settrue\splitfloatfirstdone}
\def\dochecksplitofffloat#1% box
{\ifinsidesplitfloat
- \ifdim\ht#1=\zeropoint
- \global\setfalse\somenextplitofffloat
+ % \ifdim\ht#1=\zeropoint % funny: \ifcase does not check for overflow
+ \ifcase\ht#1\relax
+ \global\setfalse\somenextsplitofffloat
\else
- \global\settrue \somenextplitofffloat
+ \global\settrue \somenextsplitofffloat
\global\setfalse\onlyonesplitofffloat
\fi
\fi}
-\def\analyzesplitfloatcaption#1% depends on page-flt
- {\doif\extrasplitfloatlines\v!auto
- {\bgroup
- \settrue\retainfloatnumber
- \nodelocationmode\zerocount
+\def\analyzesplitfloatcaption#1% depends on page-flt .. pretty messy
+ {\edef\extrasplitfloatlines{\extrasplitfloatlines}%
+ \ifx\extrasplitfloatlines\v!auto
+ \bgroup
\forcelocalfloats
\setuplocalfloats[\c!before=,\c!after=,\c!inbetween=]%
- \splitfloatcommand{\hbox to \wd#1{\strut}}% dummy line
+ \splitfloatcommand{\hbox to #1{\strut}}% dummy line
\setbox\scratchbox\vbox{\flushlocalfloats}%
\getnoflines{\ht\scratchbox}%
\resetlocalfloats
\advance\noflines\minusone % compensate dummy line
- \expanded{\egroup\noexpand\edef\noexpand\extrasplitfloatlines{\the\noflines}}}}
-
-% \def\analyzesplitfloatcaption#1%
-% {\edef\extrasplitfloatlines{11}}
+ \normalexpanded{\egroup\noexpand\edef\noexpand\extrasplitfloatlines{\the\noflines}}%
+ \global\settrue\usesamefloatnumber
+ \else
+ \doifnumberelse\extrasplitfloatlines\donothing{\def\extrasplitfloatlines{1}}%
+ \fi}
\def\dowithsplitofffloat % nextbox
{\ifinsidesplitfloat
@@ -227,7 +228,7 @@
\newconditional\splitfloatfirstdone
\def\handletsplit
- {\analyzesplitfloatcaption\tsplitcontent
+ {\analyzesplitfloatcaption{\wd\tsplitcontent}%
\global\setfalse\splitfloatfirstdone
\testpagesync % new, sync, but still tricky
[\tsplitminimumfreelines]
@@ -329,11 +330,69 @@
\endgraf
\fi
\ifinsidecolumns
- \doifnotinsidesplitfloat\goodbreak
+ \goodbreak % was \doifnotinsidesplitfloat\goodbreak
\else
- \doifnotinsidesplitfloat\page
+ \page % was \doifnotinsidesplitfloat\page
\fi
+ \global\settrue\usesamefloatnumber % new, prevent next increment
\fi}%
+ \global\setfalse\usesamefloatnumber % new, prevent next increment
+ \global\setfalse\splitfloatfirstdone} % we can use this one for tests
+
+%D The next one assumes that the split takes place elsewhere. This is
+%D used in xtables.
+
+\let\resetdirecttsplit\resettsplit
+
+\def\tsplitdirectwidth{\hsize}
+
+\def\handledirecttsplit
+ {\analyzesplitfloatcaption{\tsplitdirectwidth}%
+ \global\setfalse\splitfloatfirstdone
+ \testpagesync % new, sync, but still tricky
+ [\tsplitminimumfreelines]
+ [\dimexpr\tsplitminimumfreespace+\extrasplitfloatlines\lineheight\relax]%
+ \doloop
+ {\ifinsidecolumns
+ \global\setfalse\splitfloatfirstdone
+ \scratchdimen\textheight
+ \else\ifconditional\splitfloatfirstdone
+ \scratchdimen\textheight
+ \else\ifdim\pagegoal<\maxdimen
+ \scratchdimen\dimexpr\pagegoal-\pagetotal\relax
+ \else
+ \scratchdimen\textheight
+ \fi\fi\fi
+ \scratchdimen\dimexpr\scratchdimen-\tsplitminimumfreespace-\extrasplitfloatlines\lineheight\relax
+ \tsplitdirectsplitter\scratchdimen % also sets state
+ \ifdim\ht\tsplitresult>\zeropoint
+ \ifconditional\somenextsplitofffloat
+ \global\setfalse\onlyonesplitofffloat
+ \fi
+ \ifdim\pagegoal<\maxdimen
+ \global\pagegoal\dimexpr\pagegoal+\lineheight\relax % etex
+ \fi
+ \dowithsplitofffloat{\tsplitbeforeresult\box\tsplitresult\tsplitafterresult}%
+ \global\settrue\usesamefloatnumber % new, prevent next increment
+ \endgraf
+ \ifconditional\somenextsplitofffloat
+ \ifinsidecolumns
+ \goodbreak
+ \else
+ \page
+ \fi
+ \fi
+ \global\settrue\splitfloatfirstdone
+ \else\ifconditional\somenextsplitofffloat
+ \ifinsidecolumns
+ \goodbreak
+ \else
+ \page % no room
+ \fi
+ \else
+ \exitloop
+ \fi\fi}%
+ \global\setfalse\usesamefloatnumber % new, prevent next increment
\global\setfalse\splitfloatfirstdone} % we can use this one for tests
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/tabl-xnt.mkvi b/Master/texmf-dist/tex/context/base/tabl-xnt.mkvi
new file mode 100644
index 00000000000..35451abe0d5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/tabl-xnt.mkvi
@@ -0,0 +1,135 @@
+% 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
+
+\let\tabl_x_normal_bTABLEhead\bTABLEhead
+\let\tabl_x_normal_eTABLEhead\eTABLEhead
+\let\tabl_x_normal_bTABLEnext\bTABLEnext
+\let\tabl_x_normal_eTABLEnext\eTABLEnext
+\let\tabl_x_normal_bTABLEfoot\bTABLEfoot
+\let\tabl_x_normal_eTABLEfoot\eTABLEfoot
+\let\tabl_x_normal_bTABLEbody\bTABLEbody
+\let\tabl_x_normal_eTABLEbody\eTABLEbody
+\let\tabl_x_normal_bTR \bTR
+\let\tabl_x_normal_eTR \eTR
+\let\tabl_x_normal_bTD \bTD
+\let\tabl_x_normal_eTD \eTD
+\let\tabl_x_normal_bTH \bTH
+\let\tabl_x_normal_eTH \eTH
+\let\tabl_x_normal_setupTABLE\setupTABLE
+\let\tabl_x_normal_bTABLE \bTABLE
+\let\tabl_x_normal_eTABLE \eTABLE
+
+\unexpanded\def\restoreTABLEfromxtable
+ {\let\bTABLEhead\tabl_x_normal_bTABLEhead
+ \let\eTABLEhead\tabl_x_normal_eTABLEhead
+ \let\bTABLEnext\tabl_x_normal_bTABLEnext
+ \let\eTABLEnext\tabl_x_normal_eTABLEnext
+ \let\bTABLEfoot\tabl_x_normal_bTABLEfoot
+ \let\eTABLEfoot\tabl_x_normal_eTABLEfoot
+ \let\bTABLEbody\tabl_x_normal_bTABLEbody
+ \let\eTABLEbody\tabl_x_normal_eTABLEbody
+ \let\bTR \tabl_x_normal_bTR
+ \let\eTR \tabl_x_normal_eTR
+ \let\bTD \tabl_x_normal_bTD
+ \let\eTD \tabl_x_normal_eTD
+ \let\bTH \tabl_x_normal_bTH
+ \let\eTH \tabl_x_normal_eTH
+ \let\setupTABLE\tabl_x_normal_setupTABLE
+ \let\bTABLE \tabl_x_normal_bTABLE
+ \let\eTABLE \tabl_x_normal_eTABLE}
+
+\unexpanded\def\mapTABLEtoxtable
+ {\let\bTABLEhead\startxtablehead
+ \let\eTABLEhead\stopxtablehead
+ \let\bTABLEnext\startxtablefoot
+ \let\eTABLEnext\stopxtablefoot
+ \let\bTABLEfoot\startxtablefoot
+ \let\eTABLEfoot\stopxtablefoot
+ \let\bTABLEbody\startxtablebody
+ \let\eTABLEbody\stopxtablebody
+ \let\bTR \startxrow
+ \let\eTR \stopxrow
+ \let\bTD \startxcell
+ \let\eTD \stopxcell
+ \let\bTH \tabl_x_TABLE_TH_start_cell
+ \let\eTH \tabl_x_TABLE_TH_stop_cell
+ \let\setupTABLE\tabl_x_TABLE_setup
+ \let\bTABLE \tabl_x_TABLE_start
+ \let\eTABLE \tabl_x_TABLE_stop}
+
+\unexpanded\def\tabl_x_TABLE_setup{\dosingleempty\tabl_x_TABLE_setup_indeed}
+\unexpanded\def\tabl_x_TABLE_start{\dosingleempty\tabl_x_TABLE_start_indeed}
+\unexpanded\def\tabl_x_TABLE_stop {\stopxtable}
+
+\unexpanded\def\tabl_x_TABLE_TH_start_cell
+ {\startxcellgroup[\c!foregroundstyle=\v!bold]%
+ \startxcell}
+
+\unexpanded\def\tabl_x_TABLE_TH_stop_cell
+ {\stopxcell
+ \stopxcellgroup}
+
+\unexpanded\def\tabl_x_TABLE_setup_indeed[#settings]%
+ {\iffirstargument
+ \setupxtable[#settings]%
+ \fi}
+
+\unexpanded\def\tabl_x_TABLE_start_indeed[#settings]%
+ {\bgroup
+ \tabl_x_prepare{#settings}%
+ \edef\tabl_x_current_buffer{\x_table_default_buffer}%
+ \buff_pickup\tabl_x_current_buffer{bTABLE}{eTABLE}\relax\tabl_x_process}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/tabl-xtb.lua b/Master/texmf-dist/tex/context/base/tabl-xtb.lua
new file mode 100644
index 00000000000..395d65a032c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/tabl-xtb.lua
@@ -0,0 +1,986 @@
+if not modules then modules = { } end modules ['tabl-xtb'] = {
+ version = 1.001,
+ comment = "companion to tabl-xtb.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[
+
+This table mechanism is a combination between TeX and Lua. We do process
+cells at the TeX end and inspect them at the Lua end. After some analysis
+we have a second pass using the calculated widths, and if needed cells
+will go through a third pass to get the heights right. This last pass is
+avoided when possible which is why some code below looks a bit more
+complex than needed. The reason for such optimizations is that each cells
+is actually a framed instance and because tables like this can be hundreds
+of pages we want to keep processing time reasonable.
+
+To a large extend the behaviour is comparable with the way bTABLE/eTABLE
+works and there is a module that maps that one onto this one. Eventually
+this mechamism will be improved so that it can replace its older cousin.
+
+]]--
+
+-- todo: use linked list instead of r/c array
+
+local texdimen = tex.dimen
+local texcount = tex.count
+local texbox = tex.box
+local texsetcount = tex.setcount
+local texsetdimen = tex.setdimen
+
+local format = string.format
+local concat = table.concat
+local points = number.points
+
+local context = context
+local context_beginvbox = context.beginvbox
+local context_endvbox = context.endvbox
+local context_blank = context.blank
+local context_nointerlineskip = context.nointerlineskip
+
+local variables = interfaces.variables
+
+local setmetatableindex = table.setmetatableindex
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local copy_node_list = node.copy_list
+local hpack_node_list = node.hpack
+local vpack_node_list = node.vpack
+local slide_node_list = node.slide
+local flush_node_list = node.flush_list
+
+local nodepool = nodes.pool
+
+local new_glue = nodepool.glue
+local new_kern = nodepool.kern
+local new_penalty = nodepool.penalty
+
+local v_stretch = variables.stretch
+local v_normal = variables.normal
+local v_width = variables.width
+local v_height = variables.height
+local v_repeat = variables["repeat"]
+local v_max = variables.max
+local v_fixed = variables.fixed
+
+local xtables = { }
+typesetters.xtables = xtables
+
+local trace_xtable = false
+local report_xtable = logs.reporter("xtable")
+
+trackers.register("xtable.construct", function(v) trace_xtable = v end)
+
+local null_mode = 0
+local head_mode = 1
+local foot_mode = 2
+local more_mode = 3
+local body_mode = 4
+
+local namedmodes = { [0] =
+ "null",
+ "head",
+ "foot",
+ "next",
+ "body",
+}
+
+local stack, data = { }, nil
+
+function xtables.create(settings)
+ table.insert(stack,data)
+ local rows = { }
+ local widths = { }
+ local heights = { }
+ local depths = { }
+ local spans = { }
+ local distances = { }
+ local autowidths = { }
+ local modes = { }
+ local fixedrows = { }
+ local fixedcolumns = { }
+ local frozencolumns = { }
+ local options = { }
+ data = {
+ rows = rows,
+ widths = widths,
+ heights = heights,
+ depths = depths,
+ spans = spans,
+ distances = distances,
+ modes = modes,
+ autowidths = autowidths,
+ fixedrows = fixedrows,
+ fixedcolumns = fixedcolumns,
+ frozencolumns = frozencolumns,
+ options = options,
+ nofrows = 0,
+ nofcolumns = 0,
+ currentrow = 0,
+ currentcolumn = 0,
+ settings = settings or { },
+ }
+ local function add_zero(t,k)
+ t[k] = 0
+ return 0
+ end
+ local function add_table(t,k)
+ local v = { }
+ t[k] = v
+ return v
+ end
+ local function add_cell(row,c)
+ local cell = {
+ nx = 0,
+ ny = 0,
+ list = false,
+ }
+ row[c] = cell
+ if c > data.nofcolumns then
+ data.nofcolumns = c
+ end
+ return cell
+ end
+ local function add_row(rows,r)
+ local row = { }
+ setmetatableindex(row,add_cell)
+ rows[r] = row
+ if r > data.nofrows then
+ data.nofrows = r
+ end
+ return row
+ end
+ setmetatableindex(rows,add_row)
+ setmetatableindex(widths,add_zero)
+ setmetatableindex(heights,add_zero)
+ setmetatableindex(depths,add_zero)
+ setmetatableindex(distances,add_zero)
+ setmetatableindex(modes,add_zero)
+ setmetatableindex(fixedrows,add_zero)
+ setmetatableindex(fixedcolumns,add_zero)
+ setmetatableindex(options,add_table)
+ --
+ settings.columndistance = tonumber(settings.columndistance) or 0
+ settings.rowdistance = tonumber(settings.rowdistance) or 0
+ settings.leftmargindistance = tonumber(settings.leftmargindistance) or 0
+ settings.rightmargindistance = tonumber(settings.rightmargindistance) or 0
+ settings.options = settings_to_hash(settings.option)
+ settings.textwidth = tonumber(settings.textwidth) or tex.hsize
+ settings.lineheight = tonumber(settings.lineheight) or texdimen.lineheight
+ settings.maxwidth = tonumber(settings.maxwidth) or settings.textwidth/8
+ -- if #stack > 0 then
+ -- settings.textwidth = tex.hsize
+ -- end
+ data.criterium_v = 2 * data.settings.lineheight
+ data.criterium_h = .75 * data.settings.textwidth
+
+end
+
+function xtables.initialize_reflow_width(option)
+ local r = data.currentrow
+ local c = data.currentcolumn + 1
+ local drc = data.rows[r][c]
+ drc.nx = texcount.c_tabl_x_nx
+ drc.ny = texcount.c_tabl_x_ny
+ local distances = data.distances
+ local distance = texdimen.d_tabl_x_distance
+ if distance > distances[c] then
+ distances[c] = distance
+ end
+ if option and option ~= "" then
+ local options = settings_to_hash(option)
+ data.options[r][c] = options
+ if options[v_fixed] then
+ data.frozencolumns[c] = true
+ end
+ end
+ data.currentcolumn = c
+end
+
+-- local function rather_fixed(n)
+-- for n in node.
+
+function xtables.set_reflow_width()
+ local r = data.currentrow
+ local c = data.currentcolumn
+ local rows = data.rows
+ local row = rows[r]
+ while row[c].span do -- can also be previous row ones
+ c = c + 1
+ end
+ local tb = texbox.b_tabl_x
+ local drc = row[c]
+ --
+ drc.list = true -- we don't need to keep the content around as we're in trial mode (no: copy_node_list(tb))
+ --
+ local widths, width = data.widths, tb.width
+ if width > widths[c] then
+ widths[c] = width
+ end
+ local heights, height = data.heights, tb.height
+ if height > heights[r] then
+ heights[r] = height
+ end
+ local depths, depth = data.depths, tb.depth
+ if depth > depths[r] then
+ depths[r] = depth
+ end
+ --
+ local dimensionstate = texcount.frameddimensionstate
+ local fixedcolumns = data.fixedcolumns
+ local fixedrows = data.fixedrows
+ if dimensionstate == 1 then
+ if width > fixedcolumns[c] then -- how about a span here?
+ fixedcolumns[c] = width
+ end
+ elseif dimensionstate == 2 then
+ fixedrows[r] = height
+ elseif dimensionstate == 3 then
+ fixedrows[r] = height -- width
+ fixedcolumns[c] = width -- height
+ else -- probably something frozen, like an image -- we could parse the list
+ if width <= data.criterium_h and height >= data.criterium_v then
+ if width > fixedcolumns[c] then -- how about a span here?
+ fixedcolumns[c] = width
+ end
+ end
+ end
+ drc.dimensionstate = dimensionstate
+ --
+ local nx, ny = drc.nx, drc.ny
+ if nx > 1 or ny > 1 then
+ local spans = data.spans
+ local self = true
+ for y=1,ny do
+ for x=1,nx do
+ if self then
+ self = false
+ else
+ local ry = r + y - 1
+ local cx = c + x - 1
+ if y > 1 then
+ spans[ry] = true
+ end
+ rows[ry][cx].span = true
+ end
+ end
+ end
+ c = c + nx - 1
+ end
+ if c > data.nofcolumns then
+ data.nofcolumns = c
+ end
+ data.currentcolumn = c
+end
+
+function xtables.initialize_reflow_height()
+ local r = data.currentrow
+ local c = data.currentcolumn + 1
+ local rows = data.rows
+ local row = rows[r]
+ while row[c].span do -- can also be previous row ones
+ c = c + 1
+ end
+ data.currentcolumn = c
+ local widths = data.widths
+ local w = widths[c]
+ local drc = row[c]
+ for x=1,drc.nx-1 do
+ w = w + widths[c+x]
+ end
+ texdimen.d_tabl_x_width = w
+ local dimensionstate = drc.dimensionstate or 0
+ if dimensionstate == 1 or dimensionstate == 3 then
+ -- width was fixed so height is known
+ texcount.c_tabl_x_skip_mode = 1
+ elseif dimensionstate == 2 then
+ -- height is enforced
+ texcount.c_tabl_x_skip_mode = 1
+ elseif data.autowidths[c] then
+ -- width has changed so we need to recalculate the height
+ texcount.c_tabl_x_skip_mode = 0
+ else
+ texcount.c_tabl_x_skip_mode = 1
+ end
+end
+
+function xtables.set_reflow_height()
+ local r = data.currentrow
+ local c = data.currentcolumn
+ local rows = data.rows
+ local row = rows[r]
+-- while row[c].span do -- we could adapt drc.nx instead
+-- c = c + 1
+-- end
+ local tb = texbox.b_tabl_x
+ local drc = row[c]
+ if data.fixedrows[r] == 0 then -- and drc.dimensionstate < 2
+ local heights, height = data.heights, tb.height
+ if height > heights[r] then
+ heights[r] = height
+ end
+ local depths, depth = data.depths, tb.depth
+ if depth > depths[r] then
+ depths[r] = depth
+ end
+ end
+-- c = c + drc.nx - 1
+-- data.currentcolumn = c
+end
+
+function xtables.initialize_construct()
+ local r = data.currentrow
+ local c = data.currentcolumn + 1
+ local rows = data.rows
+ local row = rows[r]
+ while row[c].span do -- can also be previous row ones
+ c = c + 1
+ end
+ data.currentcolumn = c
+ local widths = data.widths
+ local heights = data.heights
+ local depths = data.depths
+ local w = widths[c]
+ local h = heights[r]
+ local d = depths[r]
+ local drc = row[c]
+ for x=1,drc.nx-1 do
+ w = w + widths[c+x]
+ end
+ for y=1,drc.ny-1 do
+ h = h + heights[r+y]
+ d = d + depths[r+y]
+ end
+ texdimen.d_tabl_x_width = w
+ texdimen.d_tabl_x_height = h + d
+ texdimen.d_tabl_x_depth = 0
+end
+
+function xtables.set_construct()
+ local r = data.currentrow
+ local c = data.currentcolumn
+ local rows = data.rows
+ local row = rows[r]
+-- while row[c].span do -- can also be previous row ones
+-- c = c + 1
+-- end
+ local drc = row[c]
+ -- this will change as soon as in luatex we can reset a box list without freeing
+ drc.list = copy_node_list(texbox.b_tabl_x)
+-- c = c + drc.nx - 1
+-- data.currentcolumn = c
+end
+
+local function showwidths(where,widths,autowidths)
+ local result = { }
+ for i=1,#widths do
+ result[#result+1] = format("%12s%s",points(widths[i]),autowidths[i] and "*" or " ")
+ end
+ return report_xtable("%s : %s",where,concat(result," "))
+end
+
+function xtables.reflow_width()
+ local nofrows = data.nofrows
+ local nofcolumns = data.nofcolumns
+ local rows = data.rows
+ for r=1,nofrows do
+ local row = rows[r]
+ for c=1,nofcolumns do
+ local drc = row[c]
+ if drc.list then
+ --- flush_node_list(drc.list)
+ drc.list = false
+ end
+ end
+ end
+ -- spread
+ local settings = data.settings
+ local options = settings.options
+ local maxwidth = settings.maxwidth
+ -- calculate width
+ local widths = data.widths
+ local distances = data.distances
+ local autowidths = data.autowidths
+ local fixedcolumns = data.fixedcolumns
+ local frozencolumns = data.frozencolumns
+ local width = 0
+ local distance = 0
+ local nofwide = 0
+ local widetotal = 0
+ local available = settings.textwidth - settings.leftmargindistance - settings.rightmargindistance
+ if trace_xtable then
+ showwidths("stage 1",widths,autowidths)
+ end
+ local noffrozen = 0
+ if options[v_max] then
+ for c=1,nofcolumns do
+ width = width + widths[c]
+ if width > maxwidth then
+ autowidths[c] = true
+ nofwide = nofwide + 1
+ widetotal = widetotal + widths[c]
+ end
+ if c < nofcolumns then
+ distance = distance + distances[c]
+ end
+ if frozencolumns[c] then
+ noffrozen = noffrozen + 1 -- brr, should be nx or so
+ end
+ end
+ else
+ for c=1,nofcolumns do -- also keep track of forced
+ local fixedwidth = fixedcolumns[c]
+ if fixedwidth > 0 then
+ widths[c] = fixedwidth
+ width = width + fixedwidth
+ else
+ width = width + widths[c]
+ if width > maxwidth then
+ autowidths[c] = true
+ nofwide = nofwide + 1
+ widetotal = widetotal + widths[c]
+ end
+ end
+ if c < nofcolumns then
+ distance = distance + distances[c]
+ end
+ if frozencolumns[c] then
+ noffrozen = noffrozen + 1 -- brr, should be nx or so
+ end
+ end
+ end
+ if trace_xtable then
+ showwidths("stage 2",widths,autowidths)
+ end
+ local delta = available - width - distance - (nofcolumns-1) * settings.columndistance
+ if delta == 0 then
+ -- nothing to be done
+ if trace_xtable then
+ report_xtable("perfect fit")
+ end
+ elseif delta > 0 then
+ -- we can distribute some
+ if not options[v_stretch] then
+ -- not needed
+ if trace_xtable then
+ report_xtable("too wide but no stretch, delta: %s",points(delta))
+ end
+ elseif options[v_width] then
+ local factor = delta / width
+ if trace_xtable then
+ report_xtable("proportional stretch, delta: %s, width: %s, factor: %s",
+ points(delta),points(width),factor)
+ end
+ for c=1,nofcolumns do
+ widths[c] = widths[c] + factor * widths[c]
+ end
+ else
+ -- frozen -> a column with option=fixed will not stretch
+ local extra = delta / (nofcolumns - noffrozen)
+ if trace_xtable then
+ report_xtable("normal stretch, delta: %s, extra: %s",
+ points(delta),points(extra))
+ end
+ for c=1,nofcolumns do
+ if not frozencolumns[c] then
+ widths[c] = widths[c] + extra
+ end
+ end
+ end
+ elseif nofwide > 0 then
+ while true do
+ done = false
+ local available = (widetotal + delta) / nofwide
+ if trace_xtable then
+ report_xtable("shrink check, total: %s, delta: %s, columns: %s, fixed: %s",
+ points(widetotal),points(delta),nofwide,points(available))
+ end
+ for c=1,nofcolumns do
+ if autowidths[c] and available >= widths[c] then
+ autowidths[c] = nil
+ nofwide = nofwide - 1
+ widetotal = widetotal - widths[c]
+ done = true
+ end
+ end
+ if not done then
+ break
+ end
+ end
+ -- maybe also options[v_width] here but tricky as width does not say
+ -- much about amount
+
+ if options[v_width] then -- not that much (we could have a clever vpack loop balancing .. no fun)
+ local factor = (widetotal + delta) / width
+ if trace_xtable then
+ report_xtable("proportional shrink used, total: %s, delta: %s, columns: %s, factor: %s",
+ points(widetotal),points(delta),nofwide,factor)
+ end
+ for c=1,nofcolumns do
+ if autowidths[c] then
+ widths[c] = factor * widths[c]
+ end
+ end
+ else
+ local available = (widetotal + delta) / nofwide
+ if trace_xtable then
+ report_xtable("normal shrink used, total: %s, delta: %s, columns: %s, fixed: %s",
+ points(widetotal),points(delta),nofwide,points(available))
+ end
+ for c=1,nofcolumns do
+ if autowidths[c] then
+ widths[c] = available
+ end
+ end
+ end
+ end
+ if trace_xtable then
+ showwidths("stage 3",widths,autowidths)
+ end
+ --
+ data.currentrow = 0
+ data.currentcolumn = 0
+end
+
+function xtables.reflow_height()
+ data.currentrow = 0
+ data.currentcolumn = 0
+ local settings = data.settings
+ if settings.options[v_height] then
+ local heights = data.heights
+ local depths = data.depths
+ local nofrows = data.nofrows
+ local totalheight = 0
+ local totaldepth = 0
+ for i=1,nofrows do
+ totalheight = totalheight + heights[i]
+ totalheight = totalheight + depths [i]
+ end
+ local total = totalheight + totaldepth
+ local leftover = settings.textheight - total
+ if leftover > 0 then
+ local leftheight = (totalheight / total ) * leftover / #heights
+ local leftdepth = (totaldepth / total ) * leftover / #depths
+ for i=1,nofrows do
+ heights[i] = heights[i] + leftheight
+ depths [i] = depths [i] + leftdepth
+ end
+ end
+ end
+end
+
+local function showspans(data)
+ local rows = data.rows
+ local modes = data.modes
+ local nofcolumns = data.nofcolumns
+ local nofrows = data.nofrows
+ for r=1,nofrows do
+ local line = { }
+ local row = rows[r]
+ for c=1,nofcolumns do
+ local cell =row[c]
+ if cell.list then
+ line[#line+1] = "list"
+ elseif cell.span then
+ line[#line+1] = "span"
+ else
+ line[#line+1] = "none"
+ end
+ end
+ report_xtable("%3d : %s : %s",r,namedmodes[modes[r]] or "----",concat(line," "))
+ end
+end
+
+function xtables.construct()
+ local rows = data.rows
+ local heights = data.heights
+ local depths = data.depths
+ local widths = data.widths
+ local spans = data.spans
+ local distances = data.distances
+ local modes = data.modes
+ local settings = data.settings
+ local nofcolumns = data.nofcolumns
+ local nofrows = data.nofrows
+ local columndistance = settings.columndistance
+ local rowdistance = settings.rowdistance
+ local leftmargindistance = settings.leftmargindistance
+ local rightmargindistance = settings.rightmargindistance
+ -- ranges can be mixes so we collect
+
+ if trace_xtable then
+ showspans(data)
+ end
+
+ local ranges = {
+ [head_mode] = { },
+ [foot_mode] = { },
+ [more_mode] = { },
+ [body_mode] = { },
+ }
+ for r=1,nofrows do
+ local m = modes[r]
+ if m == 0 then
+ m = body_mode
+ end
+ local range = ranges[m]
+ range[#range+1] = r
+ end
+ -- todo: hook in the splitter ... the splitter can ask for a chunk of
+ -- a certain size ... no longer a split memory issue then and header
+ -- footer then has to happen here too .. target height
+ local function packaged_column(r)
+ local row = rows[r]
+ local start = nil
+ local stop = nil
+ if leftmargindistance > 0 then
+ start = new_kern(leftmargindistance)
+ stop = start
+ end
+ local hasspan = false
+ for c=1,nofcolumns do
+ local drc = row[c]
+ if not hasspan then
+ hasspan = drc.span
+ end
+ local list = drc.list
+ if list then
+ list.shift = list.height + list.depth
+ list = hpack_node_list(list) -- is somehow needed
+ list.width = 0
+ list.height = 0
+ list.depth = 0
+ if start then
+ stop.next = list
+ list.prev = stop
+ else
+ start = list
+ end
+ stop = list -- one node anyway, so not needed: slide_node_list(list)
+ end
+ local step = widths[c]
+ if c < nofcolumns then
+ step = step + columndistance + distances[c]
+ end
+ local kern = new_kern(step)
+ if stop then
+ stop.prev = kern
+ stop.next = kern
+ else -- can be first spanning next row (ny=...)
+ start = kern
+ end
+ stop = kern
+ end
+ if start then
+ if rightmargindistance > 0 then
+ local kern = new_kern(rightmargindistance)
+ stop.next = kern
+ kern.prev = stop
+ -- stop = kern
+ end
+ return start, heights[r] + depths[r], hasspan
+ end
+ end
+ local function collect_range(range)
+ local result, nofr = { }, 0
+ local nofrange = #range
+ for i=1,#range do
+ local r = range[i]
+ -- local row = rows[r]
+ local list, size, hasspan = packaged_column(r)
+ if list then
+ if hasspan and nofr > 0 then
+ result[nofr][4] = true
+ end
+ nofr = nofr + 1
+ result[nofr] = {
+ hpack_node_list(list),
+ size,
+ i < nofrange and rowdistance > 0 and rowdistance or false, -- might move
+ false
+ }
+ end
+ end
+ return result
+ end
+ local body = collect_range(ranges[body_mode])
+ data.results = {
+ [head_mode] = collect_range(ranges[head_mode]),
+ [foot_mode] = collect_range(ranges[foot_mode]),
+ [more_mode] = collect_range(ranges[more_mode]),
+ [body_mode] = body,
+ }
+ if #body == 0 then
+ texsetcount("global","c_tabl_x_state",0)
+ texsetdimen("global","d_tabl_x_final_width",0)
+ else
+ texsetcount("global","c_tabl_x_state",1)
+ texsetdimen("global","d_tabl_x_final_width",body[1][1].width)
+ end
+end
+
+local function inject(row,copy,package)
+ local list = row[1]
+ if copy then
+ row[1] = copy_node_list(list)
+ end
+ if package then
+ context_beginvbox()
+ context(list)
+ context(new_kern(row[2]))
+ context_endvbox()
+ context_nointerlineskip() -- figure out a better way
+ if row[4] then
+ -- nothing as we have a span
+ elseif row[3] then
+ context_blank(row[3] .. "sp") -- why blank ?
+ else
+ context(new_glue(0))
+ end
+ else
+ context(list)
+ context(new_kern(row[2]))
+ if row[3] then
+ context(new_glue(row[3]))
+ end
+ end
+end
+
+local function total(row,distance)
+ local n = #row > 0 and rowdistance or 0
+ for i=1,#row do
+ local ri = row[i]
+ n = n + ri[2] + (ri[3] or 0)
+ end
+ return n
+end
+
+-- local function append(list,what)
+-- for i=1,#what do
+-- local l = what[i]
+-- list[#list+1] = l[1]
+-- local k = l[2] + (l[3] or 0)
+-- if k ~= 0 then
+-- list[#list+1] = new_kern(k)
+-- end
+-- end
+-- end
+
+local function spanheight(body,i)
+ local height, n = 0, 1
+ while true do
+ local bi = body[i]
+ if bi then
+ height = height + bi[2] + (bi[3] or 0)
+ if bi[4] then
+ n = n + 1
+ i = i + 1
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+ return height, n
+end
+
+function xtables.flush(directives) -- todo split by size / no inbetween then .. glue list kern blank
+ local vsize = directives.vsize
+ local method = directives.method or v_normal
+ local settings = data.settings
+ local results = data.results
+ local rowdistance = settings.rowdistance
+ local head = results[head_mode]
+ local foot = results[foot_mode]
+ local more = results[more_mode]
+ local body = results[body_mode]
+ local repeatheader = settings.header == v_repeat
+ local repeatfooter = settings.footer == v_repeat
+ if vsize and vsize > 0 then
+ context_beginvbox()
+ local bodystart = data.bodystart or 1
+ local bodystop = data.bodystop or #body
+ if bodystart > 0 and bodystart <= bodystop then
+ local bodysize = vsize
+ local footsize = total(foot,rowdistance)
+ local headsize = total(head,rowdistance)
+ local moresize = total(more,rowdistance)
+ local firstsize, firstspans = spanheight(body,bodystart)
+ if bodystart == 1 then -- first chunk gets head
+ bodysize = bodysize - headsize - footsize
+ if headsize > 0 and bodysize >= firstsize then
+ for i=1,#head do
+ inject(head[i],repeatheader)
+ end
+ if rowdistance > 0 then
+ context(new_glue(rowdistance))
+ end
+ if not repeatheader then
+ results[head_mode] = { }
+ end
+ end
+ elseif moresize > 0 then -- following chunk gets next
+ bodysize = bodysize - footsize - moresize
+ if bodysize >= firstsize then
+ for i=1,#more do
+ inject(more[i],true)
+ end
+ if rowdistance > 0 then
+ context(new_glue(rowdistance))
+ end
+ end
+ elseif headsize > 0 and repeatheader then -- following chunk gets head
+ bodysize = bodysize - footsize - headsize
+ if bodysize >= firstsize then
+ for i=1,#head do
+ inject(head[i],true)
+ end
+ if rowdistance > 0 then
+ context(new_glue(rowdistance))
+ end
+ end
+ else -- following chunk gets nothing
+ bodysize = bodysize - footsize
+ end
+ if bodysize >= firstsize then
+ local i = bodystart
+ while i <= bodystop do -- room for improvement
+ local total, spans = spanheight(body,i)
+ local bs = bodysize - total
+ if bs > 0 then
+ bodysize = bs
+ for s=1,spans do
+ inject(body[i])
+ body[i] = nil
+ i = i + 1
+ end
+ bodystart = i
+ else
+ break
+ end
+ end
+ if bodystart > bodystop then
+ -- all is flushed and footer fits
+ if footsize > 0 then
+ if rowdistance > 0 then
+ context(new_glue(rowdistance))
+ end
+ for i=1,#foot do
+ inject(foot[i])
+ end
+ results[foot_mode] = { }
+ end
+ results[body_mode] = { }
+ texsetcount("global","c_tabl_x_state",0)
+ else
+ -- some is left so footer is delayed
+ -- todo: try to flush a few more lines
+ if repeatfooter and footsize > 0 then
+ if rowdistance > 0 then
+ context(new_glue(rowdistance))
+ end
+ for i=1,#foot do
+ inject(foot[i],true)
+ end
+ else
+ -- todo: try to fit more of body
+ end
+ texsetcount("global","c_tabl_x_state",2)
+ end
+ else
+ if firstsize > vsize then
+ -- get rid of the too large cell
+ for s=1,firstspans do
+ inject(body[bodystart])
+ body[bodystart] = nil
+ bodystart = bodystart + 1
+ end
+ end
+ texsetcount("global","c_tabl_x_state",2) -- 1
+ end
+ else
+ texsetcount("global","c_tabl_x_state",0)
+ end
+ data.bodystart = bodystart
+ data.bodystop = bodystop
+ context_endvbox()
+ else
+ if method == variables.split then
+ -- maybe also a non float mode with header/footer repeat although
+ -- we can also use a float without caption
+ for i=1,#head do
+ inject(head[i],false,true)
+ end
+ if #head > 0 and rowdistance > 0 then
+ context_blank(rowdistance .. "sp")
+ end
+ for i=1,#body do
+ inject(body[i],false,true)
+ end
+ if #foot > 0 and rowdistance > 0 then
+ context_blank(rowdistance .. "sp")
+ end
+ for i=1,#foot do
+ inject(foot[i],false,true)
+ end
+ else -- normal
+ context_beginvbox()
+ for i=1,#head do
+ inject(head[i])
+ end
+ if #head > 0 and rowdistance > 0 then
+ context(new_glue(rowdistance))
+ end
+ for i=1,#body do
+ inject(body[i])
+ end
+ if #foot > 0 and rowdistance > 0 then
+ context(new_glue(rowdistance))
+ end
+ for i=1,#foot do
+ inject(foot[i])
+ end
+ context_endvbox()
+ end
+ results[head_mode] = { }
+ results[body_mode] = { }
+ results[foot_mode] = { }
+ texsetcount("global","c_tabl_x_state",0)
+ end
+end
+
+function xtables.cleanup()
+ for mode, result in next, data.results do
+ for _, r in next, result do
+ flush_node_list(r[1])
+ end
+ end
+ data = table.remove(stack)
+end
+
+function xtables.next_row()
+ local r = data.currentrow + 1
+ data.modes[r] = texcount.c_tabl_x_mode
+ data.currentrow = r
+ data.currentcolumn = 0
+end
+
+-- eventually we might only have commands
+
+commands.x_table_create = xtables.create
+commands.x_table_reflow_width = xtables.reflow_width
+commands.x_table_reflow_height = xtables.reflow_height
+commands.x_table_construct = xtables.construct
+commands.x_table_flush = xtables.flush
+commands.x_table_cleanup = xtables.cleanup
+commands.x_table_next_row = xtables.next_row
+commands.x_table_init_reflow_width = xtables.initialize_reflow_width
+commands.x_table_init_reflow_height = xtables.initialize_reflow_height
+commands.x_table_init_construct = xtables.initialize_construct
+commands.x_table_set_reflow_width = xtables.set_reflow_width
+commands.x_table_set_reflow_height = xtables.set_reflow_height
+commands.x_table_set_construct = xtables.set_construct
diff --git a/Master/texmf-dist/tex/context/base/tabl-xtb.mkvi b/Master/texmf-dist/tex/context/base/tabl-xtb.mkvi
new file mode 100644
index 00000000000..2382cae2190
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/tabl-xtb.mkvi
@@ -0,0 +1,689 @@
+% 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}{1.001}
+
+% 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
+%
+%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
+
+% \def\v!xtable{xtable}
+
+% 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 \attribute\taggedattribute {...}
+%
+% \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 {\taggedctxcommand{settagtablecell(\number\tablecellrows,\number\tablecellcolumns,\number\raggedstatus)}}%
+ \def\dotagxtablesignal{\char\zerocount}% 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
+
+% \setupxtable[one][parent][a=b,c=d]
+% \setupxtable[one] [a=b,c=d]
+% \setupxtable [a=b,c=d]
+
+\installcorenamespace{xtable}
+\installcorenamespace{xtablecheck}
+
+\installframedautocommandhandler \??xtable {xtable} \??xtable
+
+\appendtoks
+ \checkxtableparent % so we can deal with undefined settings, not that it's efficient
+\to \everysetupxtable
+
+\setupxtable[%
+ \c!nr=1,
+ \c!nc=1,
+ \c!nx=1, % slow
+ \c!ny=1, % 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=8em,
+ \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!option=, % \v!stretch {\v!stretch,\v!width}
+ % \c!footer=,
+ % \c!header=,
+ \c!spaceinbetween=,
+ \c!textwidth=\hsize,
+ \c!textheight=\vsize,
+ \c!distance=\zeropoint, % individual column
+ \c!columndistance=\zeropoint, % each column (whole table)
+ \c!leftmargindistance=\zeropoint, % whole table
+ \c!rightmargindistance=\zeropoint,% whole table
+]
+
+\unexpanded\def\startxtable
+ {\dosingleempty\tabl_x_start_table}
+
+\let\stopxtable\relax
+
+\def\tabl_x_default_buffer{x_table_\number\c_tabl_x_nesting}
+
+\unexpanded\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}
+
+\unexpanded\def\processxtablebuffer
+ {\dosingleempty\tabl_x_process_buffer_directly}
+
+% 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.
+
+\def\tabl_x_process_buffer_directly[#name]%
+ {\bgroup
+ \let\tabl_x_start_table\tabl_x_process_buffer
+ \edef\tabl_x_current_buffer{#name}%
+ \tabl_x_get_buffer % pickup settings
+ \tabl_x_process}
+
+\def\tabl_x_start_ignore[#settings]%
+ {}
+
+\def\tabl_x_process_buffer[#settings]%
+ {\tabl_x_prepare{#settings}%
+ \let\tabl_x_start_table\tabl_x_start_ignore
+ \gobbleuntil\stopxtable}
+
+%D A bonus: you can use the following construct inside a macro.
+
+\unexpanded\def\startembeddedxtable
+ {\dosingleempty\tabl_x_embedded_start}
+
+\def\tabl_x_embedded_start[#settings]#content\stopembeddedxtable
+ {\tabl_x_prepare{#settings}%
+ \ctxcommand{assignbuffer("embedded_x_table",\!!bs\detokenize{#content}\!!es)}%
+ \bgroup
+ \let\tabl_x_start_table\tabl_x_process_buffer
+ \edef\tabl_x_current_buffer{embedded_x_table}%
+ \tabl_x_process}
+
+\let\stopembeddedxtable\relax
+
+%D We can also define xtables.
+
+\appendtoks
+ \setuevalue{\e!start\currentxtable}{\tabl_x_start_named{\currentxtable}}%
+ \setuevalue{\e!stop \currentxtable}{\tabl_x_stop_named}%
+\to \everydefinextable
+
+\unexpanded\def\tabl_x_start_named#tag%
+ {\bgroup
+ \edef\currentxtable{#tag}%
+ \dosingleempty\tabl_x_start_named_indeed}
+
+\unexpanded\def\tabl_x_start_named_indeed[#settings]%
+ {\advance\c_tabl_x_nesting\plusone
+ \dostarttagged\t!table\empty
+ \forgetall
+ \iffirstargument
+ \setupcurrentxtable[#settings]%
+ \fi
+ \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}}
+
+\unexpanded\def\tabl_x_stop_named
+ {}
+
+%D Now we come to processing:
+
+\def\tabl_x_prepare#settings% assumes \iffirstargument to be set
+ {\advance\c_tabl_x_nesting\plusone
+ \dostarttagged\t!table\empty
+ \forgetall
+ \iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\def\tabl_x_get_buffer
+ {\ctxcommand{gettexbuffer("\tabl_x_current_buffer")}}
+
+\unexpanded\def\tabl_x_process
+ {\begingroup % *
+ \doifsomething{\xtableparameter\c!bodyfont}
+ {\setupbodyfont[\xtableparameter\c!bodyfont]}%
+ \setbox\scratchbox\vbox
+ {\xtableparameter\c!spaceinbetween}%
+ \ctxcommand{x_table_create {
+ option = "\xtableparameter\c!option",
+ textwidth = \number\dimexpr\xtableparameter\c!textwidth,
+ textheight = \number\dimexpr\xtableparameter\c!textheight,
+ maxwidth = \number\dimexpr\xtableparameter\c!maxwidth,
+ lineheight = \number\openlineheight,
+ columndistance = \number\dimexpr\xtableparameter\c!columndistance,
+ leftmargindistance = \number\dimexpr\xtableparameter\c!leftmargindistance,
+ rightmargindistance = \number\dimexpr\xtableparameter\c!rightmargindistance,
+ rowdistance = \number\ht\scratchbox,
+ header = "\xtableparameter\c!header",
+ footer = "\xtableparameter\c!footer",
+ } }%
+ %
+ \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
+ \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
+ \ctxcommand{x_table_reflow_width()}\relax
+ \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
+ \tabl_x_get_buffer
+ \ctxcommand{x_table_reflow_height()}\relax
+ \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
+ \tabl_x_get_buffer
+ \ctxcommand{x_table_construct()}\relax
+ \endgroup
+ \endgroup % *
+ \ifinsidesplitfloat
+ \tabl_x_flush_float_split
+ \else\ifinsidefloat
+ \tabl_x_flush_float_normal
+ \else
+ \doifelse{\xtableparameter\c!split}\v!yes
+ \tabl_x_flush_flow_split
+ \tabl_x_flush_flow_normal
+ \fi\fi
+ \ctxcommand{x_table_cleanup()}%
+ \dostoptagged
+ \resetbuffer[\tabl_x_current_buffer]%
+ \egroup}
+
+\let\extratxtablesplitheight\zeropoint % might disappear so don't depend on it
+
+\def\tabl_x_flush_float_normal
+ {\ctxcommand{x_table_flush{ method = "\v!normal" }}}
+
+\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}
+
+\def\tabl_x_flush_flow_normal
+ {\ctxcommand{x_table_flush{ method = "\v!normal" }}}
+
+\def\tabl_x_flush_flow_split
+ {\ctxcommand{x_table_flush{ method = "\v!split" }}}
+
+\def\tabl_x_split_splitter#vsize%
+ {\setbox\tsplitresult\vbox
+ {\ctxcommand{x_table_flush{ method = "\v!split", vsize = \number\dimexpr#vsize }}}%
+ \ifcase\c_tabl_x_state
+ \global\setfalse\somenextsplitofffloat
+ \else
+ \global\settrue \somenextsplitofffloat
+ \fi}
+
+\unexpanded\def\startxrow
+ {\begingroup
+ \doifnextoptionalelse\tabl_x_start_row_yes\tabl_x_start_row_nop}
+
+\def\tabl_x_start_row_reflow_width_yes[#settings]%
+ {\setupcurrentxtable[#settings]%
+ \ctxcommand{x_table_next_row()}}
+
+\def\tabl_x_start_row_reflow_width_nop
+ {\ctxcommand{x_table_next_row()}}
+
+\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
+
+\def\tabl_x_start_row_construct_yes[#settings]%
+ {\setupcurrentxtable[#settings]%
+ \dostarttagged\t!tablerow\empty
+ \ctxcommand{x_table_next_row()}}
+
+\def\tabl_x_start_row_construct_nop
+ {\dostarttagged\t!tablerow\empty
+ \ctxcommand{x_table_next_row()}}
+
+\def\tabl_x_stop_row_construct
+ {\dostoptagged}
+
+\unexpanded\def\stopxrow
+ {\tabl_x_stop_row
+ \endgroup}
+
+\unexpanded\def\startxcell
+ {\doifnextoptionalelse\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\unexpanded\def\stopxcell
+ {\tabl_x_stop_cell}
+
+\def\tabl_x_begin_of_cell
+ {\inhibitblank
+ \everypar{\delayedbegstrut}}
+
+\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
+
+\unexpanded\def\tabl_x_start_cell_reflow_width_yes[#settings]%
+ {\setbox\b_tabl_x\hbox\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
+ \ctxcommand{x_table_init_reflow_width("\xtableparameter\c!option")}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \tabl_x_set_hsize}
+
+\unexpanded\def\tabl_x_start_cell_reflow_width_nop
+ {\setbox\b_tabl_x\hbox\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
+ \ctxcommand{x_table_init_reflow_width()}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \tabl_x_set_hsize}
+
+\unexpanded\def\tabl_x_stop_cell_reflow_width
+ {\tabl_x_end_of_cell
+ \egroup
+ \egroup
+ \ctxcommand{x_table_set_reflow_width()}}
+
+\unexpanded\def\tabl_x_start_cell_reflow_height_yes[#settings]%
+ {\setbox\b_tabl_x\hbox\bgroup
+ \ctxcommand{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}
+
+\unexpanded\def\tabl_x_start_cell_reflow_height_nop
+ {\setbox\b_tabl_x\hbox\bgroup
+ \ctxcommand{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}
+
+\unexpanded\def\tabl_x_stop_cell_reflow_height
+ {\ifcase\c_tabl_x_skip_mode
+ \tabl_x_end_of_cell
+ \egroup
+ \fi
+ \egroup
+ \ctxcommand{x_table_set_reflow_height()}}
+
+\unexpanded\def\tabl_x_start_cell_construct_yes[#settings]%
+ {\dostarttagged\t!tablecell\empty % can't we just tag the box
+ \setbox\b_tabl_x\hbox\bgroup
+ \setupcurrentxtable[#settings]%
+ \letxtableparameter\c!width \d_tabl_x_width % overloads given width
+ \letxtableparameter\c!height\d_tabl_x_height % overloads given height
+ \ctxcommand{x_table_init_construct()}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \dotagxtablecell}
+
+\unexpanded\def\tabl_x_start_cell_construct_nop
+ {\dostarttagged\t!tablecell\empty % can't we just tag the box
+ \setbox\b_tabl_x\hbox\bgroup
+ \letxtableparameter\c!width \d_tabl_x_width % overloads given width
+ \letxtableparameter\c!height\d_tabl_x_height % overloads given height
+ \ctxcommand{x_table_init_construct()}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \dotagxtablecell}
+
+\unexpanded\def\tabl_x_stop_cell_construct
+ {\tabl_x_end_of_cell
+ \egroup
+ \dotagxtablesignal % harmless spot
+ \egroup
+ \ctxcommand{x_table_set_construct()}%
+ \dostoptagged}
+
+\unexpanded\def\startxcellgroup
+ {\begingroup
+ \dosingleempty\tabl_x_start_cell_group}
+
+\unexpanded\def\stopxcellgroup
+ {\endgroup}
+
+\unexpanded\def\tabl_x_start_cell_group[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\unexpanded\def\startxrowgroup
+ {\begingroup
+ \dosingleempty\tabl_x_start_row_group}
+
+\unexpanded\def\stopxrowgroup
+ {\dostoptagged
+ \endgroup}
+
+\unexpanded\def\tabl_x_start_row_group[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+% \def\tabl_x_set_checked#settings
+% {\doifassignmentelse{#settings}
+% {\setupcurrentxtable[#settings]}
+% {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname
+% \edef\currentxtable{#settings}%
+% \fi}}
+
+\unexpanded\def\tabl_x_set_checked#settings%
+ {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname
+ \edef\currentxtable{#settings}%
+ \else
+ \setupcurrentxtable[#settings]%
+ \fi}
+
+\unexpanded\def\startxtablehead{\begingroup\c_tabl_x_mode\plusone \dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablefoot{\begingroup\c_tabl_x_mode\plustwo \dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablenext{\begingroup\c_tabl_x_mode\plusthree\dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablebody{\begingroup\c_tabl_x_mode\plusfour \dosingleempty\tabl_x_start_partition}
+
+\unexpanded\def\tabl_x_start_partition[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\unexpanded\def\tabl_x_stop_partition
+ {\endgroup}
+
+\let\stopxtablehead\tabl_x_stop_partition
+\let\stopxtablefoot\tabl_x_stop_partition
+\let\stopxtablenext\tabl_x_stop_partition
+\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
+
+% groups
+
+\unexpanded\def\startxgroup
+ {\begingroup
+ \doifnextoptionalelse\tabl_x_start_group_delayed_one\relax}
+
+\unexpanded\def\stopxgroup
+ {\endgroup}
+
+\def\tabl_x_start_group_delayed_one[#tag]%
+% {\ifcsname\namedxtablehash{#tag}\s!parent\endcsname
+ {\ifcsname\??xtablecheck#tag\endcsname
+ \expandafter\tabl_x_start_group_delayed_two
+ \else
+ \expandafter\setupcurrentxtable
+ \fi[#tag]}
+
+\def\tabl_x_start_group_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifnextoptionalelse\setupcurrentxtable\relax}
+
+\let\startxrowgroup \startxgroup
+\let\stopxrowgroup \stopxgroup
+\let\startxcellgroup\startxgroup
+\let\stopxcellgroup \stopxgroup
+
+% cells (maybe also check for 1 etc but it becomes messy)
+
+\unexpanded\def\startxcell
+ {\begingroup
+ \doifnextoptionalelse\tabl_x_start_cell_delayed_one\tabl_x_start_cell_nop}
+
+\def\tabl_x_start_cell_delayed_one[#tag]%
+% {\ifcsname\namedxtablehash{#tag}\s!parent\endcsname
+ {\ifcsname\??xtablecheck#tag\endcsname
+ \expandafter\tabl_x_start_cell_delayed_two
+ \else
+ \expandafter\tabl_x_start_cell_yes
+ \fi[#tag]}
+
+\def\tabl_x_start_cell_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifnextoptionalelse\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\unexpanded\def\stopxcell
+ {\tabl_x_stop_cell
+ \endgroup}
+
+% rows
+
+\unexpanded\def\startxrow
+ {\begingroup
+ \doifnextoptionalelse\tabl_x_start_row_delayed_one\tabl_x_start_row_nop}
+
+\def\tabl_x_start_row_delayed_one[#tag]%
+% {\ifcsname\namedxtablehash{#tag}\s!parent\endcsname
+ {\ifcsname\??xtablecheck#tag\endcsname
+ \expandafter\tabl_x_start_row_delayed_two
+ \else
+ \expandafter\tabl_x_start_row_yes
+ \fi[#tag]}
+
+\def\tabl_x_start_row_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifnextoptionalelse\tabl_x_start_row_yes\tabl_x_start_row_nop}
+
+\unexpanded\def\stopxrow
+ {\tabl_x_stop_row
+ \endgroup}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/task-ini.lua b/Master/texmf-dist/tex/context/base/task-ini.lua
index c1c22e8ccd9..1ec38e181e6 100644
--- a/Master/texmf-dist/tex/context/base/task-ini.lua
+++ b/Master/texmf-dist/tex/context/base/task-ini.lua
@@ -10,6 +10,8 @@ if not modules then modules = { } end modules ['task-ini'] = {
-- the load order can determine the trickery to be applied to node lists
--
-- we can disable more handlers and enable then when really used (*)
+--
+-- todo: two finalizers: real shipout (can be imposed page) and page shipout (individual page)
local tasks = nodes.tasks
local appendaction = tasks.appendaction
@@ -17,6 +19,7 @@ local disableaction = tasks.disableaction
local freezegroup = tasks.freezegroup
local freezecallbacks = callbacks.freeze
+appendaction("processors", "normalizers", "typesetters.characters.handler") -- always on
appendaction("processors", "normalizers", "fonts.collections.process") -- todo
appendaction("processors", "normalizers", "fonts.checkers.missing") -- disabled
@@ -40,6 +43,11 @@ appendaction("processors", "fonts", "nodes.handlers.stripping")
appendaction("processors", "lists", "typesetters.spacings.handler") -- disabled
appendaction("processors", "lists", "typesetters.kerns.handler") -- disabled
appendaction("processors", "lists", "typesetters.digits.handler") -- disabled (after otf handling)
+appendaction("processors", "lists", "typesetters.italics.handler") -- disabled (after otf/kern handling)
+
+-- appendaction("processors", "fonts", "typesetters.italics.handler") -- disabled (after otf/kern handling)
+
+appendaction("processors", "lists", "typesetters.paragraphs.handler") -- disabled
appendaction("shipouts", "normalizers", "nodes.handlers.cleanuppage") -- disabled
appendaction("shipouts", "normalizers", "typesetters.alignments.handler")
@@ -51,6 +59,8 @@ appendaction("shipouts", "normalizers", "structures.tags.handler")
appendaction("shipouts", "normalizers", "nodes.handlers.accessibility") -- disabled
appendaction("shipouts", "normalizers", "nodes.handlers.backgrounds") -- disabled
+--~ appendaction("shipouts", "normalizers", "nodes.handlers.export") -- disabled
+
appendaction("shipouts", "finishers", "attributes.colors.handler") -- disabled
appendaction("shipouts", "finishers", "attributes.transparencies.handler") -- disabled
appendaction("shipouts", "finishers", "attributes.colorintents.handler") -- disabled
@@ -59,19 +69,25 @@ appendaction("shipouts", "finishers", "attributes.effects.handler")
appendaction("shipouts", "finishers", "attributes.viewerlayers.handler") -- disabled
appendaction("math", "normalizers", "noads.handlers.unscript", nil, "nohead") -- always on (maybe disabled)
+appendaction("math", "normalizers", "noads.handlers.variants", nil, "nohead") -- always on
+appendaction("math", "normalizers", "noads.handlers.families", nil, "nohead") -- always on
appendaction("math", "normalizers", "noads.handlers.relocate", nil, "nohead") -- always on
+appendaction("math", "normalizers", "noads.handlers.render", nil, "nohead") -- always on
appendaction("math", "normalizers", "noads.handlers.collapse", nil, "nohead") -- always on
appendaction("math", "normalizers", "noads.handlers.resize", nil, "nohead") -- always on
appendaction("math", "normalizers", "noads.handlers.respace", nil, "nohead") -- always on
appendaction("math", "normalizers", "noads.handlers.check", nil, "nohead") -- always on
appendaction("math", "normalizers", "noads.handlers.tags", nil, "nohead") -- disabled
+appendaction("math", "normalizers", "noads.handlers.italics", nil, "nohead") -- disabled
appendaction("math", "builders", "builders.kernel.mlist_to_hlist") -- always on
-- quite experimental (nodes.handlers.graphicvadjust might go away)
+appendaction("finalizers", "lists", "builders.paragraphs.keeptogether")
appendaction("finalizers", "lists", "nodes.handlers.graphicvadjust") -- todo
appendaction("finalizers", "fonts", "builders.paragraphs.solutions.splitters.optimize") -- experimental
+appendaction("finalizers", "lists", "builders.paragraphs.tag")
-- still experimental
@@ -92,7 +108,9 @@ disableaction("processors", "typesetters.directions.handler")
disableaction("processors", "languages.words.check")
disableaction("processors", "typesetters.spacings.handler")
disableaction("processors", "typesetters.kerns.handler")
+disableaction("processors", "typesetters.italics.handler")
disableaction("processors", "nodes.handlers.stripping")
+disableaction("processors", "typesetters.paragraphs.handler")
disableaction("shipouts", "typesetters.alignments.handler")
disableaction("shipouts", "nodes.rules.handler")
@@ -111,14 +129,19 @@ disableaction("shipouts", "nodes.handlers.cleanuppage")
disableaction("shipouts", "nodes.references.handler")
disableaction("shipouts", "nodes.destinations.handler")
+--~ disableaction("shipouts", "nodes.handlers.export")
+
disableaction("mvlbuilders", "nodes.handlers.migrate")
disableaction("processors", "builders.paragraphs.solutions.splitters.split")
+disableaction("finalizers", "builders.paragraphs.keeptogether")
disableaction("finalizers", "builders.paragraphs.solutions.splitters.optimize")
disableaction("finalizers", "nodes.handlers.graphicvadjust") -- sort of obsolete
+disableaction("finalizers", "builders.paragraphs.tag")
disableaction("math", "noads.handlers.tags")
+disableaction("math", "noads.handlers.italics")
freezecallbacks("find_.*_file", "find file using resolver")
freezecallbacks("read_.*_file", "read file at once")
diff --git a/Master/texmf-dist/tex/context/base/task-ini.mkiv b/Master/texmf-dist/tex/context/base/task-ini.mkiv
index ef32ee87dca..6cdbe739f15 100644
--- a/Master/texmf-dist/tex/context/base/task-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/task-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/toks-ini.lua b/Master/texmf-dist/tex/context/base/toks-ini.lua
index f8b5b94396d..1f4d48466b2 100644
--- a/Master/texmf-dist/tex/context/base/toks-ini.lua
+++ b/Master/texmf-dist/tex/context/base/toks-ini.lua
@@ -33,8 +33,6 @@ a module.</p>
local token, tex = token, tex
-local texsprint = tex.sprint
-
local createtoken = token.create
local csname_id = token.csname_id
local command_id = token.command_id
@@ -81,7 +79,7 @@ local function printlist(data)
end)
end
-tex.printlist = printlist
+tex.printlist = printlist -- will change to another namespace
function collectors.flush(tag)
printlist(collectordata[tag])
@@ -107,7 +105,7 @@ function collectors.install(tag,end_cs)
local t = get_next()
local a, b = t[1], t[3]
if b == endcs then
- texsprint('\\' ..end_cs) -- to be checked, can be context[end_cs]()
+ context["end_cs"]()
return
elseif a == call and registered[b] then
expand()
diff --git a/Master/texmf-dist/tex/context/base/toks-ini.mkiv b/Master/texmf-dist/tex/context/base/toks-ini.mkiv
index 2aa2ed4a6ac..4eb756b7537 100644
--- a/Master/texmf-dist/tex/context/base/toks-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/toks-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -20,11 +20,11 @@
%D Handy for manuals \unknown
\unexpanded\def\starttokens [#1]{\ctxlua{tokens.collectors.install("#1","stoptokens")}}
-\let\stoptokens \relax
-\def\flushtokens [#1]{\ctxlua{tokens.collectors.flush("#1")}}
-\def\showtokens [#1]{\ctxlua{tokens.collectors.show("#1")}}
-\def\testtokens [#1]{\ctxlua{tokens.collectors.with_words("#1")}}
-\def\registertoken #1{\ctxlua{tokens.collectors.register("#1")}}
+ \let\stoptokens \relax
+ \def\flushtokens [#1]{\ctxlua{tokens.collectors.flush("#1")}}
+ \def\showtokens [#1]{\ctxlua{tokens.collectors.show("#1")}}
+ \def\testtokens [#1]{\ctxlua{tokens.collectors.with_words("#1")}}
+ \def\registertoken #1{\ctxlua{tokens.collectors.register("#1")}}
%D Inspired by a prototype by Taco for Thomas cum suis.
@@ -45,33 +45,25 @@
%
% \stoptext
-% incompatible with mkii ! ! ! ! so we need other names here
-%
-% \def\dograbuntil#1#2%
-% {\long\def\next##1#1{#2##1}\next}
-%
-% \def\grabuntil#1%
-% {\expandafter\dograbuntil\expandafter{\csname#1\endcsname}}
+\unexpanded\def\defineremapper[#1]%
+ {\setuevalue{\e!start#1}{\toks_start_remapper{#1}}%
+ \setuevalue{\e!stop #1}{\toks_stop_remapper {#1}}%
+ \letvalue{#1}\relax
+ \normalexpanded{\expandafter\def\csname#1\endcsname##1{\csname\e!start#1\endcsname##1\csname\e!stop#1\endcsname}}}
-\def\dostartremapper#1%
+\unexpanded\def\toks_start_remapper#1%
{\ctxlua{tokens.collectors.install("#1", "\e!stop#1")}}
-\def\dostopremapper#1%
+\unexpanded\def\toks_stop_remapper#1%
{\ctxlua{tokens.collectors.handle("#1",function(str) return tokens.collectors.remapper.convert("#1",str) end, true)}}
-\def\remaptokens#1%
+\unexpanded\def\remaptokens#1%
{\ctxlua{tokens.collectors.handle("#1",function(str) return tokens.collectors.remapper.convert("#1",str) end)}}
-\unexpanded\def\defineremapper[#1]%
- {\setvalue{\e!start#1}{\dostartremapper{#1}}%
- \setvalue{\e!stop #1}{\dostopremapper {#1}}%
- \def\next##1{\setvalue{#1}####1{\getvalue{\e!start#1}####1##1}}%
- \expandafter\next\csname\e!stop#1\endcsname}
-
-\def\remapcharacter
- {\dodoubleempty\doremapcharacter}
+\unexpanded\def\remapcharacter
+ {\dodoubleempty\toks_remap_character}
-\def\doremapcharacter[#1][#2]#3%
+\def\toks_remap_character[#1][#2]#3%
{\ctxlua{tokens.collectors.install("store", "ctxlua")}#3%
\ctxlua{tokens.collectors.remapper.store("store","#1",\number#2)}}
diff --git a/Master/texmf-dist/tex/context/base/trac-deb.mkiv b/Master/texmf-dist/tex/context/base/trac-deb.mkiv
index 2eb44247a33..4f5f0e931db 100644
--- a/Master/texmf-dist/tex/context/base/trac-deb.mkiv
+++ b/Master/texmf-dist/tex/context/base/trac-deb.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Debugger,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -16,22 +16,22 @@
\registerctxluafile{trac-lmx}{1.001}
\registerctxluafile{trac-deb}{1.001}
-\def\breakpoint{\showdebuginfo\wait}
+\unexpanded\def\breakpoint{\showdebuginfo\wait}
-\def\showtrackers {\ctxlua{trackers.show()}}
-\def\enabletrackers [#1]{\ctxlua{trackers.enable("#1")}}
-\def\disabletrackers [#1]{\ctxlua{trackers.disable("#1")}}
-\def\resettrackers {\ctxlua{trackers.reset()}}
+\unexpanded\def\showtrackers {\ctxlua{trackers.show()}}
+\unexpanded\def\enabletrackers [#1]{\ctxlua{trackers.enable("#1")}}
+\unexpanded\def\disabletrackers [#1]{\ctxlua{trackers.disable("#1")}}
+\unexpanded\def\resettrackers {\ctxlua{trackers.reset()}}
-\def\showdirectives {\ctxlua{directives.show()}}
-\def\enabledirectives [#1]{\ctxlua{directives.enable("#1")}}
-\def\disabledirectives [#1]{\ctxlua{directives.disable("#1")}}
+\unexpanded\def\showdirectives {\ctxlua{directives.show()}}
+\unexpanded\def\enabledirectives [#1]{\ctxlua{directives.enable("#1")}}
+\unexpanded\def\disabledirectives [#1]{\ctxlua{directives.disable("#1")}}
-\def\showexperiments {\ctxlua{experiments.show()}}
-\def\enableexperiments [#1]{\ctxlua{experiments.enable("#1")}}
-\def\disableexperiments[#1]{\ctxlua{experiments.disable("#1")}}
+\unexpanded\def\showexperiments {\ctxlua{experiments.show()}}
+\unexpanded\def\enableexperiments [#1]{\ctxlua{experiments.enable("#1")}}
+\unexpanded\def\disableexperiments[#1]{\ctxlua{experiments.disable("#1")}}
-\def\showdebuginfo{\ctxlua{lmx.showdebuginfo()}}
-\def\overloaderror{\ctxlua{lmx.overloaderror()}} % \enabledirectives[system.showerror]
+\unexpanded\def\showdebuginfo{\ctxlua{lmx.showdebuginfo()}}
+\unexpanded\def\overloaderror{\ctxlua{lmx.overloaderror()}} % \enabledirectives[system.showerror]
-\def\showlogcategories {\ctxlua{logs.show()}}
+\unexpanded\def\showlogcategories {\ctxlua{logs.show()}}
diff --git a/Master/texmf-dist/tex/context/base/trac-fil.lua b/Master/texmf-dist/tex/context/base/trac-fil.lua
new file mode 100644
index 00000000000..bf291ff6b88
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/trac-fil.lua
@@ -0,0 +1,149 @@
+if not modules then modules = { } end modules ['trac-fil'] = {
+ version = 1.001,
+ comment = "for the moment for myself",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, concat = string.format, table.concat
+local openfile = io.open
+local date = os.date
+local rawset, tonumber = rawset, tonumber
+
+local P, C, Cc, Cg, Cf, Ct, Cs = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cg, lpeg.Cf, lpeg.Ct, lpeg.Cs
+
+local patterns = lpeg.patterns
+local cardinal = patterns.cardinal
+local whitespace = patterns.whitespace^0
+
+patterns.timestamp = Cf(Ct("") * (
+ Cg (Cc("year") * (cardinal/tonumber)) * P("-")
+ * Cg (Cc("month") * (cardinal/tonumber)) * P("-")
+ * Cg (Cc("day") * (cardinal/tonumber)) * P(" ")
+ * Cg (Cc("hour") * (cardinal/tonumber)) * P(":")
+ * Cg (Cc("minute") * (cardinal/tonumber)) * P(":")
+ * Cg (Cc("second") * (cardinal/tonumber)) * P("+")
+ * Cg (Cc("thour") * (cardinal/tonumber)) * P(":")
+ * Cg (Cc("tminute") * (cardinal/tonumber))
+)^0, rawset)
+
+patterns.keysvalues = Cf(Ct("") * (
+ Cg(C(patterns.letter^0) * whitespace * "=" * whitespace * Cs(patterns.unquoted) * whitespace)
+)^0, rawset)
+
+patterns.statusline = Cf(Ct("") * (
+ whitespace * P("[") * Cg(Cc("timestamp") * patterns.timestamp ) * P("]")
+ * whitespace * Cg(Cc("status" ) * patterns.keysvalues)
+),rawset)
+
+
+loggers = loggers or { }
+
+local tz = os.timezone(true)
+
+local bugged = { }
+
+function loggers.message(filename,t)
+ if not bugged[filename] then
+ local f = openfile(filename,"a+")
+ if not f then
+ dir.mkdirs(file.dirname(filename))
+ f = openfile(filename,"a+")
+ end
+ if f then
+ f:write("[",date("!%Y-%m-%d %H:%M:%S"),tz,"]")
+ for k, v in table.sortedpairs(t) do
+ f:write(" ",k,'="',v,'"')
+ end
+ f:write("\n")
+ f:close()
+ else
+ bugged[filename] = true
+ end
+ end
+end
+
+--~ function loggers.collect(filename)
+--~ if lfs.isfile(filename) then
+--~ return lpeg.match(Ct(patterns.statusline^0),io.loaddata(filename))
+--~ else
+--~ return { }
+--~ end
+--~ end
+
+function loggers.collect(filename,result)
+ if lfs.isfile(filename) then
+ local r = lpeg.match(Ct(patterns.statusline^0),io.loaddata(filename))
+ if result then -- append
+ local nofresult = #result
+ for i=1,#r do
+ nofresult = nofresult + 1
+ result[nofresult] = r[i]
+ end
+ return result
+ else
+ return r
+ end
+ else
+ return result or { }
+ end
+end
+
+--~ local template = [[
+--~ <table>
+--~ <tr>%s</tr>
+--~ %s
+--~ </table>
+--~ ]]
+
+--~ function loggers.tohtml(entries,fields)
+--~ if not fields or #fields == 0 then
+--~ return ""
+--~ end
+--~ if type(entries) == "string" then
+--~ entries = loggers.collect(entries)
+--~ end
+--~ local scratch, lines = { }, { }
+--~ for i=1,#entries do
+--~ local entry = entries[i]
+--~ local status = entry.status
+--~ for i=1,#fields do
+--~ local field = fields[i]
+--~ local v = status[field.name]
+--~ if v ~= nil then
+--~ v = tostring(v)
+--~ local f = field.format
+--~ if f then v = format(f,v) end
+--~ scratch[i] = format("<td nowrap='nowrap' align='%s'>%s</td>",field.align or "left",v)
+--~ else
+--~ scratch[i] = "<td/>"
+--~ end
+--~ end
+--~ lines[i] = "<tr>" .. concat(scratch) .. "</tr>"
+--~ end
+--~ for i=1,#fields do
+--~ local field = fields[i]
+--~ scratch[i] = format("<th nowrap='nowrap' align='left'>%s</th>", field.label or field.name)
+--~ end
+--~ local result = format(template,concat(scratch),concat(lines,"\n"))
+--~ return result, entries
+--~ end
+
+--~ -- loggers.message("test.log","name","whatever","more",123)
+
+--~ local fields = {
+--~ -- { name = "id", align = "left" },
+--~ -- { name = "timestamp", align = "left" },
+--~ { name = "assessment", align = "left" },
+--~ { name = "assessmentname", align = "left" },
+--~ -- { name = "category", align = "left" },
+--~ { name = "filesize", align = "right" },
+--~ { name = "nofimages", align = "center" },
+--~ -- { name = "product", align = "left" },
+--~ { name = "resultsize", align = "right" },
+--~ { name = "fetchtime", align = "right", format = "%2.3f" },
+--~ { name = "runtime", align = "right", format = "%2.3f" },
+--~ { name = "organization", align = "left" },
+--~ -- { name = "username", align = "left" },
+--~ }
diff --git a/Master/texmf-dist/tex/context/base/trac-inf.lua b/Master/texmf-dist/tex/context/base/trac-inf.lua
index 5719b953f38..cbc9d13f880 100644
--- a/Master/texmf-dist/tex/context/base/trac-inf.lua
+++ b/Master/texmf-dist/tex/context/base/trac-inf.lua
@@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['trac-inf'] = {
-- get warnings about assignments. This is more efficient than using rawset
-- and rawget.
-local format = string.format
+local format, lower = string.format, string.lower
local clock = os.gettimeofday or os.clock -- should go in environment
local write_nl = texio.write_nl
@@ -113,10 +113,10 @@ function statistics.show(reporter)
-- this code will move
local register = statistics.register
register("luatex banner", function()
- return string.lower(status.banner)
+ return lower(status.banner)
end)
register("control sequences", function()
- return format("%s of %s", status.cs_count, status.hash_size+status.hash_extra)
+ return format("%s of %s + %s", status.cs_count, status.hash_size,status.hash_extra)
end)
register("callbacks", function()
local total, indirect = status.callbacks or 0, status.indirect_callbacks or 0
@@ -190,5 +190,5 @@ end
function commands.elapsedtime(name)
stoptiming(name or "whatever")
- tex.sprint(elapsedtime(name or "whatever"))
+ context(elapsedtime(name or "whatever"))
end
diff --git a/Master/texmf-dist/tex/context/base/trac-lmx.lua b/Master/texmf-dist/tex/context/base/trac-lmx.lua
index b4bfc36d6e9..452d03002f9 100644
--- a/Master/texmf-dist/tex/context/base/trac-lmx.lua
+++ b/Master/texmf-dist/tex/context/base/trac-lmx.lua
@@ -38,6 +38,9 @@ lmxvariables['color-background-main'] = '#3F3F3F'
lmxvariables['color-background-one'] = lmxvariables['color-background-green']
lmxvariables['color-background-two'] = lmxvariables['color-background-blue']
+lmxvariables['color-background-three'] = function() return lmxvariables['color-background-one'] end
+lmxvariables['color-background-four'] = function() return lmxvariables['color-background-two'] end
+
function lmx.set(key, value)
lmxvariables[key] = value
end
@@ -74,7 +77,12 @@ local function do_type(str)
end
local function do_variable(str)
- return variables[str] or lmxvariables[str] -- or format("<!-- unset lmx instance variable: %s -->",str or "?")
+ local value = variables[str] or lmxvariables[str] -- or format("<!-- unset lmx instance variable: %s -->",str or "?")
+ if type(value) == "function" then
+ return value(str)
+ else
+ return value
+ end
end
function lmx.loadedfile(name)
@@ -83,9 +91,9 @@ function lmx.loadedfile(name)
end
local function do_include(filename)
- local stylepath = do_variable('includepath')
+ local stylepath = do_variable('includepath') -- todo: store paths of loaded files
local data = lmx.loadedfile(filename)
- if (not data or data == "") and stylepath ~= "" then
+ if (not data or data == "") and stylepath and stylepath ~= "" then
data = lmx.loadedfile(file.join(stylepath,filename))
end
if not data or data == "" then
diff --git a/Master/texmf-dist/tex/context/base/trac-log.lua b/Master/texmf-dist/tex/context/base/trac-log.lua
index 13bb18b0682..44de8ebe6d0 100644
--- a/Master/texmf-dist/tex/context/base/trac-log.lua
+++ b/Master/texmf-dist/tex/context/base/trac-log.lua
@@ -46,7 +46,7 @@ local report, subreport, status, settarget, setformats, settranslations
local direct, subdirect, writer, pushtarget, poptarget
-if tex and tex.jobname or tex.formatname then
+if tex and (tex.jobname or tex.formatname) then
local valueiskey = { __index = function(t,k) t[k] = k return k end } -- will be helper
@@ -61,6 +61,10 @@ if tex and tex.jobname or tex.formatname then
write_nl(target,...)
end
+ newline = function()
+ write_nl(target,"\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(target,format("%-15s > %s\n",translations[a],format(formats[b],c,...)))
@@ -166,6 +170,10 @@ else
writer = write_nl
+ newline = function()
+ write_nl("\n")
+ end
+
report = function(a,b,c,...)
if c then
write_nl(format("%-15s | %s",a,format(b,c,...)))
@@ -225,6 +233,7 @@ logs.settranslations = settranslations
logs.direct = direct
logs.subdirect = subdirect
logs.writer = writer
+logs.newline = newline
-- installer
@@ -394,21 +403,58 @@ local real, user, sub
function logs.start_page_number()
real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
+-- real, user, sub = 0, 0, 0
end
-function logs.stop_page_number()
- if real > 0 then
- if user > 0 then
- if sub > 0 then
- report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+local timing = false
+local starttime = nil
+local lasttime = nil
+
+trackers.register("pages.timing", function(v) -- only for myself (diagnostics)
+ starttime = os.clock()
+ timing = true
+end)
+
+function logs.stop_page_number() -- the first page can includes the initialization so we omit this in average
+ if timing then
+ local elapsed, average
+ local stoptime = os.clock()
+ if not lasttime or real < 2 then
+ elapsed = stoptime
+ average = stoptime
+ starttime = stoptime
+ else
+ elapsed = stoptime - lasttime
+ average = (stoptime - starttime) / (real - 1)
+ end
+ lasttime = stoptime
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average)
+ else
+ report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average)
+ end
else
- report_pages("flushing realpage %s, userpage %s",real,user)
+ report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average)
end
else
- report_pages("flushing realpage %s",real)
+ report_pages("flushing page, time %0.04f / %0.04f",elapsed,average)
end
else
- report_pages("flushing page")
+ if real > 0 then
+ if user > 0 then
+ if sub > 0 then
+ report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub)
+ else
+ report_pages("flushing realpage %s, userpage %s",real,user)
+ end
+ else
+ report_pages("flushing realpage %s",real)
+ end
+ else
+ report_pages("flushing page")
+ end
end
logs.flush()
end
@@ -490,6 +536,13 @@ local function reportbanner(t)
end
end
+local function reportversion(t)
+ local banner = t.banner
+ if banner then
+ t.report(banner)
+ end
+end
+
local function reporthelp(t,...)
local helpinfo = t.helpinfo
if type(helpinfo) == "string" then
@@ -516,6 +569,7 @@ function logs.application(t)
t.report = logs.reporter(t.name)
t.help = function(...) reportbanner(t) ; reporthelp(t,...) ; reportinfo(t) end
t.identify = function() reportbanner(t) end
+ t.version = function() reportversion(t) end
return t
end
@@ -585,3 +639,8 @@ else
print(format(...))
end
end
+
+-- do we still need io.flush then?
+
+io.stdout:setvbuf('no')
+io.stderr:setvbuf('no')
diff --git a/Master/texmf-dist/tex/context/base/trac-set.lua b/Master/texmf-dist/tex/context/base/trac-set.lua
index 27b5f17f2ad..bc0070eb42b 100644
--- a/Master/texmf-dist/tex/context/base/trac-set.lua
+++ b/Master/texmf-dist/tex/context/base/trac-set.lua
@@ -74,6 +74,10 @@ local function set(t,what,newvalue)
if type(what) ~= "table" then
return
end
+ if not done then -- catch ... why not set?
+ done = { }
+ t.done = done
+ end
for w, value in next, what do
if value == "" then
value = newvalue
@@ -310,6 +314,8 @@ end
if texconfig then
+ -- this happens too late in ini mode but that is no problem
+
local function set(k,v)
v = tonumber(v)
if v then
diff --git a/Master/texmf-dist/tex/context/base/trac-tex.lua b/Master/texmf-dist/tex/context/base/trac-tex.lua
index dcfbf965d23..7920bd1cb72 100644
--- a/Master/texmf-dist/tex/context/base/trac-tex.lua
+++ b/Master/texmf-dist/tex/context/base/trac-tex.lua
@@ -58,7 +58,7 @@ local function saveusedfilesintrees(format)
local data = {
jobname = environment.jobname or "?",
version = environment.version or "?",
- files = table.sortedkeys(resolvers.instance.foundintrees)
+ files = resolvers.instance.foundintrees
}
local filename = file.replacesuffix(environment.jobname or "context-job",'jlg')
if format == "lua" then
diff --git a/Master/texmf-dist/tex/context/base/trac-tex.mkiv b/Master/texmf-dist/tex/context/base/trac-tex.mkiv
index 37eca912342..53c95ab01d7 100644
--- a/Master/texmf-dist/tex/context/base/trac-tex.mkiv
+++ b/Master/texmf-dist/tex/context/base/trac-tex.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\TEX,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -26,17 +26,17 @@
\let\alltextracers\empty % so that we can report available tracers
-\def\installtextracer#1%
+\unexpanded\def\installtextracer#1%
{\addtocommalist{#1}\alltextracers}
-\def\enabletextracers [#1]{\processcommalist[#1]\doenabletextracer}
-\def\disabletextracers[#1]{\processcommalist[#1]\dodisabletextracer}
+\unexpanded\def\enabletextracers [#1]{\processcommalist[#1]\syst_textracers_enable }
+\unexpanded\def\disabletextracers[#1]{\processcommalist[#1]\syst_textracers_disable}
-\def\doenabletextracer #1{\csname enabletracer#1\endcsname}
-\def\dodisabletextracer#1{\csname disabletracer#1\endcsname}
+\def\syst_textracers_enable #1{\csname enabletracer#1\endcsname}
+\def\syst_textracers_disable#1{\csname disabletracer#1\endcsname}
% The next one is for Taco, although we can use directives as well:
-\def\nomkivstatistics{\enabledirectives[system.nostatistics]}
+\unexpanded\def\nomkivstatistics{\enabledirectives[system.nostatistics]}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/trac-vis.mkii b/Master/texmf-dist/tex/context/base/trac-vis.mkii
index 23ded2af9ef..be7a204ec1d 100644
--- a/Master/texmf-dist/tex/context/base/trac-vis.mkii
+++ b/Master/texmf-dist/tex/context/base/trac-vis.mkii
@@ -5,7 +5,7 @@
%D subtitle=Visualization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/trac-vis.mkiv b/Master/texmf-dist/tex/context/base/trac-vis.mkiv
index 2056dc6355a..e906bb50dbb 100644
--- a/Master/texmf-dist/tex/context/base/trac-vis.mkiv
+++ b/Master/texmf-dist/tex/context/base/trac-vis.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Visualization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -58,7 +58,7 @@
{\vrule #5 20\testrulewidth \!!width \zeropoint
\normalhss}}}%
\smashbox\scratchbox
- \normalpenalty\!!tenthousand
+ \normalpenalty\plustenthousand
\box\scratchbox
\egroup}
@@ -261,15 +261,17 @@
\newdimen\tractempheight
\newdimen\tractempdepth
-\def \cutmarklength {2\bodyfontsize}
+\def \cutmarklength {2\bodyfontsize}
\newcount\horizontalcutmarks \horizontalcutmarks = 2
\newcount\verticalcutmarks \verticalcutmarks = 2
\newcount\cutmarkoffset \cutmarkoffset = 1
-\let\cutmarksymbol = \relax
-\let\cutmarktoptext = \empty
-\let\cutmarkbottomtext = \empty
+\let \cutmarksymbol \relax
+\let \cutmarktoptext \empty
+\let \cutmarkbottomtext \empty
+\let \cutmarkhoffset \empty
+\let \cutmarkvoffset \empty
\def\horizontalcuts
{\normalhbox to \tractempwidth
@@ -298,11 +300,12 @@
\normalhss
\normalvbox to \cutmarklength
{\scratchdimen\dimexpr\cutmarklength/2\relax
+ \scratchskip \ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
\normalvss
\hbox to \tractempwidth
- {\llap{\copy\scratchbox\normalhskip\cutmarkoffset\scratchdimen}%
+ {\llap{\copy\scratchbox\normalhskip\scratchskip}%
\normalhskip\scratchdimen\hss\infofont#1\hss\normalhskip\scratchdimen
- \rlap{\normalhskip\cutmarkoffset\scratchdimen\copy\scratchbox}}%
+ \rlap{\normalhskip\scratchskip\copy\scratchbox}}%
\normalvss}%
\normalhss}}
@@ -319,21 +322,29 @@
\hsize\tractempwidth
\setbox\scratchbox\normalvbox
{\setbox\scratchbox\normalhbox{\horizontalcuts}%
- \normalvskip\dimexpr-\cutmarkoffset\scratchdimen-2\scratchdimen\relax
- \copy\scratchbox
- \normalvskip\cutmarkoffset\scratchdimen
+ \scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
+% \normalvskip\dimexpr-\scratchskip-2\scratchdimen\relax
+% \copy\scratchbox
+% \normalvskip\scratchskip
+ \tlap{\copy\scratchbox\normalvskip\scratchskip}%
\hbox to \tractempwidth
- {\setbox\scratchbox\normalhbox{\verticalcuts}%
- \llap{\copy\scratchbox\normalhskip\cutmarkoffset\scratchdimen}%
- \bgroup
- \setbox\scratchbox\normalhbox{\baselinecuts}%
- \llap{\copy\scratchbox\normalhskip\cutmarkoffset\scratchdimen}%
- \normalhfill
- \rlap{\normalhskip\cutmarkoffset\scratchdimen\copy\scratchbox}%
- \egroup
- \rlap{\normalhskip\cutmarkoffset\scratchdimen\copy\scratchbox}}%
- \normalvskip\cutmarkoffset\scratchdimen
- \copy\scratchbox}%
+ {\scratchskip\ifx\cutmarkhoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkhoffset\fi
+ \setbox\scratchbox\normalhbox{\verticalcuts}%
+ \llap{\copy\scratchbox\normalhskip\scratchskip}%
+ \ifdim\tractempdepth=\zeropoint
+ \normalhfill
+ \else
+ \bgroup
+ \setbox\scratchbox\normalhbox{\baselinecuts}%
+ \llap{\copy\scratchbox\normalhskip\scratchskip}%
+ \normalhfill
+ \rlap{\normalhskip\scratchskip\copy\scratchbox}%
+ \egroup
+ \fi
+ \rlap{\normalhskip\scratchskip\copy\scratchbox}}%
+% \normalvskip\scratchskip
+% \copy\scratchbox}%
+ \blap{\normalvskip\scratchskip\copy\scratchbox}}%
\ht\scratchbox\tractempheight
\dp\scratchbox\tractempdepth
\wd\scratchbox\zeropoint
@@ -341,13 +352,14 @@
\box\scratchbox
\ifx\cutmarksymbol\relax \else
\setbox\scratchbox\normalvbox
- {\vskip-\cutmarkoffset\scratchdimen
+ {\scratchskip\ifx\cutmarkvoffset\empty\cutmarkoffset\scratchdimen\else\cutmarkvoffset\fi
+ \vskip-\scratchskip
\vskip-\cutmarklength
\normalhbox{\cutmarksymbols\cutmarktoptext}%
- \vskip\cutmarkoffset\scratchdimen
+ \vskip\scratchskip
\vskip\tractempheight
\vskip\tractempdepth
- \vskip\cutmarkoffset\scratchdimen
+ \vskip\scratchskip
\normalhbox{\cutmarksymbols\cutmarkbottomtext}}%
\ht\scratchbox\tractempheight
\dp\scratchbox\tractempdepth
@@ -505,8 +517,8 @@
\ht#2\tractempheight
\dp#2\tractempdepth}
-\def\colormarkbox {\ifincolor\@EA\docolormarkbox\else\@EA\gobbletwoarguments\fi\plusone } % #1
-\def\rastermarkbox{\ifincolor\@EA\docolormarkbox\else\@EA\gobbletwoarguments\fi\zerocount} % #1
+\def\colormarkbox {\docolormarkbox\plusone } % #1
+\def\rastermarkbox{\docolormarkbox\zerocount} % #1
%D \macros
%D {showwhatsits, dontshowwhatsits}
diff --git a/Master/texmf-dist/tex/context/base/type-buy.mkii b/Master/texmf-dist/tex/context/base/type-buy.mkii
index 56fc92e62d6..b8518acb0ea 100644
--- a/Master/texmf-dist/tex/context/base/type-buy.mkii
+++ b/Master/texmf-dist/tex/context/base/type-buy.mkii
@@ -5,7 +5,7 @@
%D subtitle=A Few Commercial Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-cbg.mkii b/Master/texmf-dist/tex/context/base/type-cbg.mkii
index 93cfa077ece..a45a71d4ed4 100644
--- a/Master/texmf-dist/tex/context/base/type-cbg.mkii
+++ b/Master/texmf-dist/tex/context/base/type-cbg.mkii
@@ -5,7 +5,7 @@
%D subtitle=CB Greek,
%D author={Giuseppe Bilotta, Hans Hagen},
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-cow.mkii b/Master/texmf-dist/tex/context/base/type-cow.mkii
index 507386443d7..f46ac968bb6 100644
--- a/Master/texmf-dist/tex/context/base/type-cow.mkii
+++ b/Master/texmf-dist/tex/context/base/type-cow.mkii
@@ -5,7 +5,7 @@
%D subtitle=Cow Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-def.mkii b/Master/texmf-dist/tex/context/base/type-def.mkii
index f31c93e504e..0ff1e0b7d8f 100644
--- a/Master/texmf-dist/tex/context/base/type-def.mkii
+++ b/Master/texmf-dist/tex/context/base/type-def.mkii
@@ -5,7 +5,7 @@
%D subtitle=Default Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-def.mkiv b/Master/texmf-dist/tex/context/base/type-def.mkiv
index c980a4ee528..a80b4f7bdf3 100644
--- a/Master/texmf-dist/tex/context/base/type-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-def.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Default Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,34 +13,34 @@
\starttypescriptcollection[simplification]
-\starttypescript [serif] [simple] [name]
- \definefontsynonym [Serif] [Simple]
- \definefontsynonym [SerifBold] [Serif]
- \definefontsynonym [SerifItalic] [Serif]
- \definefontsynonym [SerifSlanted] [Serif]
- \definefontsynonym [SerifBoldItalic] [Serif]
- \definefontsynonym [SerifBoldSlanted] [Serif]
- \definefontsynonym [SerifCaps] [Serif]
+\starttypescript [\s!serif] [\s!simple] [\s!name]
+ \definefontsynonym [\s!Serif] [\s!Simple]
+ \definefontsynonym [\s!SerifBold] [\s!Serif]
+ \definefontsynonym [\s!SerifItalic] [\s!Serif]
+ \definefontsynonym [\s!SerifSlanted] [\s!Serif]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!Serif]
+ \definefontsynonym [\s!SerifBoldSlanted] [\s!Serif]
+ \definefontsynonym [\s!SerifCaps] [\s!Serif]
\stoptypescript
-\starttypescript [sans] [simple] [name]
- \definefontsynonym [Sans] [Simple]
- \definefontsynonym [SansBold] [Sans]
- \definefontsynonym [SansItalic] [Sans]
- \definefontsynonym [SansSlanted] [Sans]
- \definefontsynonym [SansBoldItalic] [Sans]
- \definefontsynonym [SansBoldSlanted] [Sans]
- \definefontsynonym [SansCaps] [Sans]
+\starttypescript [\s!sans] [\s!simple] [\s!name]
+ \definefontsynonym [\s!Sans] [\s!Simple]
+ \definefontsynonym [\s!SansBold] [\s!Sans]
+ \definefontsynonym [\s!SansItalic] [\s!Sans]
+ \definefontsynonym [\s!SansSlanted] [\s!Sans]
+ \definefontsynonym [\s!SansBoldItalic] [\s!Sans]
+ \definefontsynonym [\s!SansBoldSlanted] [\s!Sans]
+ \definefontsynonym [\s!SansCaps] [\s!Sans]
\stoptypescript
-\starttypescript [mono] [simple] [name]
- \definefontsynonym [Mono] [Simple]
- \definefontsynonym [MonoBold] [Mono]
- \definefontsynonym [MonoItalic] [Mono]
- \definefontsynonym [MonoSlanted] [Mono]
- \definefontsynonym [MonoBoldItalic] [Mono]
- \definefontsynonym [MonoBoldSlanted] [Mono]
- \definefontsynonym [MonoCaps] [Mono]
+\starttypescript [\s!mono] [\s!simple] [\s!name]
+ \definefontsynonym [\s!Mono] [\s!Simple]
+ \definefontsynonym [\s!MonoBold] [\s!Mono]
+ \definefontsynonym [\s!MonoItalic] [\s!Mono]
+ \definefontsynonym [\s!MonoSlanted] [\s!Mono]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!Mono]
+ \definefontsynonym [\s!MonoBoldSlanted] [\s!Mono]
+ \definefontsynonym [\s!MonoCaps] [\s!Mono]
\stoptypescript
\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-exp.mkii b/Master/texmf-dist/tex/context/base/type-exp.mkii
index dae770e98c0..c7c6e4b45d3 100644
--- a/Master/texmf-dist/tex/context/base/type-exp.mkii
+++ b/Master/texmf-dist/tex/context/base/type-exp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Experimental Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-fbk.mkiv b/Master/texmf-dist/tex/context/base/type-fbk.mkiv
new file mode 100644
index 00000000000..4ac38178754
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-fbk.mkiv
@@ -0,0 +1,70 @@
+%D \module
+%D [ file=type-sfbk,
+%D version=2005.02.04, % moved from ini/def/set
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Fallbacks,
+%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.
+
+\unprotect
+
+\definetypescriptprefix [\s!serif] [\s!Serif]
+\definetypescriptprefix [\s!sans] [\s!Sans]
+\definetypescriptprefix [\s!mono] [\s!Mono]
+
+\definefontsynonym [\s!DefaultFont] [\s!file:lmmonoproplt10-regular]
+
+\startsetups [\s!font:\s!fallback:\s!serif]
+ \definefontsynonym[\s!Serif] [\s!DefaultFont]
+ \definefontsynonym[\s!SerifBold] [\s!Serif]
+ \definefontsynonym[\s!SerifItalic] [\s!Serif]
+ \definefontsynonym[\s!SerifSlanted] [\s!SerifItalic]
+ \definefontsynonym[\s!SerifBoldItalic] [\s!Serif]
+ \definefontsynonym[\s!SerifBoldSlanted][\s!SerifBoldItalic]
+ \definefontsynonym[\s!SerifCaps] [\s!Serif] [\s!features=\s!smallcaps]
+\stopsetups
+
+\startsetups [\s!font:\s!fallback:\s!sans]
+ \definefontsynonym[\s!Sans] [\s!DefaultFont]
+ \definefontsynonym[\s!SansBold] [\s!Sans]
+ \definefontsynonym[\s!SansItalic] [\s!Sans]
+ \definefontsynonym[\s!SansSlanted] [\s!SansItalic]
+ \definefontsynonym[\s!SansBoldItalic] [\s!Sans]
+ \definefontsynonym[\s!SansBoldSlanted][\s!SansBoldItalic]
+ \definefontsynonym[\s!SansCaps] [\s!Sans] [\s!features=\s!smallcaps]
+\stopsetups
+
+\startsetups [\s!font:\s!fallback:\s!mono]
+ \definefontsynonym[\s!Mono] [\s!DefaultFont]
+ \definefontsynonym[\s!MonoBold] [\s!Mono]
+ \definefontsynonym[\s!MonoItalic] [\s!Mono]
+ \definefontsynonym[\s!MonoSlanted] [\s!MonoItalic]
+ \definefontsynonym[\s!MonoBoldItalic] [\s!Mono]
+ \definefontsynonym[\s!MonoBoldSlanted][\s!MonoBoldItalic]
+ \definefontsynonym[\s!MonoCaps] [\s!Mono] [\s!features=\s!smallcaps]
+\stopsetups
+
+\starttypescript [\s!serif,\s!sans,\s!mono] [\s!fallback]
+ \setups[\s!font:\s!fallback:\typescriptone]
+\stoptypescript
+
+\startsetups [\s!font:allbold:\s!serif]
+ \definefontsynonym[\s!Serif] [\s!SerifBold]
+ \definefontsynonym[\s!SerifItalic] [\s!SerifBoldItalic]
+ \definefontsynonym[\s!SerifSlanted][\s!SerifBoldSlanted]
+ %definefontsynonym[\s!SerifCaps] [\s!SerifBold]
+\stopsetups
+
+\startsetups [\s!font:allbold:\s!sans]
+ \definefontsynonym[\s!Sans] [\s!SansBold]
+ \definefontsynonym[\s!SansItalic] [\s!SansBoldItalic]
+ \definefontsynonym[\s!SansSlanted][\s!SansBoldSlanted]
+ %definefontsynonym[\s!SansCaps] [\s!SansBold]
+\stopsetups
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/type-fsf.mkii b/Master/texmf-dist/tex/context/base/type-fsf.mkii
index 7813b7b5dbd..6782d3dcf76 100644
--- a/Master/texmf-dist/tex/context/base/type-fsf.mkii
+++ b/Master/texmf-dist/tex/context/base/type-fsf.mkii
@@ -5,7 +5,7 @@
%D subtitle=Fontsite 500,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-ghz.mkii b/Master/texmf-dist/tex/context/base/type-ghz.mkii
index 7e31096ee4a..3778cd96485 100644
--- a/Master/texmf-dist/tex/context/base/type-ghz.mkii
+++ b/Master/texmf-dist/tex/context/base/type-ghz.mkii
@@ -5,7 +5,7 @@
%D subtitle=Hermann Zapf's Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-imp-antykwa.mkiv b/Master/texmf-dist/tex/context/base/type-imp-antykwa.mkiv
new file mode 100644
index 00000000000..ba5895c8e4b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-antykwa.mkiv
@@ -0,0 +1,228 @@
+%D \module
+%D [ file=type-imp-antykwa,
+%D version=2010.06.21,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Antykwa Torunska,
+%D author=Mojca Miklavec \& 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.
+
+\starttypescriptcollection[antykwa-torunska]
+
+ \starttypescript [antykwa,antykwa-torunska,antykwa-torunska-light,antykwa-torunska-cond,antykwa-torunska-lightcond]
+ \definetypeface[\typescriptone][\s!rm][\s!serif][\typescriptone] [\s!default]
+ \definetypeface[\typescriptone][\s!ss][\s!sans] [modern] [\s!default] [\s!rscale=1.05]
+ \definetypeface[\typescriptone][\s!tt][\s!mono] [modern] [\s!default] [\s!rscale=1.05]
+ \definetypeface[\typescriptone][\s!mm][\s!math] [\typescriptone] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa,antykwa-torunska,antykwa-torunska-light,antykwa-torunska-cond,antykwa-torunska-lightcond]
+ \definefontsynonym [AntykwaTorunska-Regular] [\s!file:AntykwaTorunska-Regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-Italic] [\s!file:AntykwaTorunska-Italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-Bold] [\s!file:AntykwaTorunska-Bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-BoldItalic] [\s!file:AntykwaTorunska-BoldItalic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-Light] [\s!file:AntykwaTorunskaLight-Regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-LightItalic] [\s!file:AntykwaTorunskaLight-Italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-Medium] [\s!file:AntykwaTorunskaMed-Regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-MedItalic] [\s!file:AntykwaTorunskaMed-Italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-CondRegular] [\s!file:AntykwaTorunskaCond-Regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-CondItalic] [\s!file:AntykwaTorunskaCond-Italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-CondBold] [\s!file:AntykwaTorunskaCond-Bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-CondBoldItalic] [\s!file:AntykwaTorunskaCond-BoldItalic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-CondLight] [\s!file:AntykwaTorunskaCondLight-Regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-CondLightItalic] [\s!file:AntykwaTorunskaCondLight-Italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-CondMedium] [\s!file:AntykwaTorunskaCondMed-Regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaTorunska-CondMedItalic] [\s!file:AntykwaTorunskaCondMed-Italic] [\s!features=\s!default]
+
+ \definefontsynonym [AntykwaTorunska-Cap] [\s!file:AntykwaTorunska-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-ItalicCap] [\s!file:AntykwaTorunska-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-BoldCap] [\s!file:AntykwaTorunska-Bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-BoldItalicCap] [\s!file:AntykwaTorunska-BoldItalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-LightCap] [\s!file:AntykwaTorunskaLight-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-LightItalicCap] [\s!file:AntykwaTorunskaLight-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-MediumCap] [\s!file:AntykwaTorunskaMed-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-MedItalicCap] [\s!file:AntykwaTorunskaMed-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondCap] [\s!file:AntykwaTorunskaCond-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondItalicCap] [\s!file:AntykwaTorunskaCond-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondBoldCap] [\s!file:AntykwaTorunskaCond-Bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondBoldItalicCap] [\s!file:AntykwaTorunskaCond-BoldItalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondLightCap] [\s!file:AntykwaTorunskaCondLight-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondLightItalicCap][\s!file:AntykwaTorunskaCondLight-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondMediumCap] [\s!file:AntykwaTorunskaCondMed-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaTorunska-CondMedItalicCap] [\s!file:AntykwaTorunskaCondMed-Italic] [\s!features=\s!smallcaps]
+ \stoptypescript
+
+ \starttypescript [\s!math][antykwa,antykwa-torunska][\s!all]
+ \loadfontgoodies[antykwa-math]
+ \definefontsynonym[\s!MathRoman][antykwamath@antykwa-math]
+ \stoptypescript
+
+ \starttypescript [\s!math][antykwa-torunska-light][\s!all]
+ \loadfontgoodies[antykwa-math]
+ \definefontsynonym[\s!MathRoman][antykwalightmath@antykwa-light-math]
+ \stoptypescript
+
+ \starttypescript [\s!math][antykwa-torunska-cond][\s!all]
+ \loadfontgoodies[antykwa-math]
+ \definefontsynonym[\s!MathRoman][antykwacondmath@antykwa-cond-math]
+ \stoptypescript
+
+ \starttypescript [\s!math][antykwa-torunska-lightcond][\s!all]
+ \loadfontgoodies[antykwa-math]
+ \definefontsynonym[\s!MathRoman][antykwalightcondmath@antykwa-lightcond-math]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa,antykwa-torunska] [\s!name]
+ \definefontsynonym [\s!Serif] [AntykwaTorunska-Regular]
+ \definefontsynonym [\s!SerifBold] [AntykwaTorunska-Bold]
+ \definefontsynonym [\s!SerifItalic] [AntykwaTorunska-Italic]
+ \definefontsynonym [\s!SerifSlanted] [AntykwaTorunska-Italic]
+ \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-BoldItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-BoldItalic]
+ \definefontsynonym [\s!SerifCaps] [AntykwaTorunska-Cap]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa-torunska-light] [\s!name]
+ \definefontsynonym [\s!Serif] [AntykwaTorunska-Light]
+ \definefontsynonym [\s!SerifBold] [AntykwaTorunska-Medium]
+ \definefontsynonym [\s!SerifItalic] [AntykwaTorunska-LightItalic]
+ \definefontsynonym [\s!SerifSlanted] [AntykwaTorunska-LightItalic]
+ \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-MedItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-MedItalic]
+ \definefontsynonym [\s!SerifCaps] [AntykwaTorunska-LightCap]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa-torunska-cond] [\s!name]
+ \definefontsynonym [\s!Serif] [AntykwaTorunska-CondRegular]
+ \definefontsynonym [\s!SerifBold] [AntykwaTorunska-CondBold]
+ \definefontsynonym [\s!SerifItalic] [AntykwaTorunska-CondItalic]
+ \definefontsynonym [\s!SerifSlanted] [AntykwaTorunska-CondItalic]
+ \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-CondBoldItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-CondBoldItalic]
+ \definefontsynonym [\s!SerifCaps] [AntykwaTorunska-CondCap]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa-torunska-lightcond] [\s!name]
+ \definefontsynonym [\s!Serif] [AntykwaTorunska-CondLight]
+ \definefontsynonym [\s!SerifBold] [AntykwaTorunska-CondMedium]
+ \definefontsynonym [\s!SerifItalic] [AntykwaTorunska-CondLightItalic]
+ \definefontsynonym [\s!SerifSlanted] [AntykwaTorunska-CondLightItalic]
+ \definefontsynonym [\s!SerifBoldItalic] [AntykwaTorunska-CondMedItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [AntykwaTorunska-CondMedItalic]
+ \definefontsynonym [\s!SerifCaps] [AntykwaTorunska-CondLightCap]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa,antykwa-torunska] [\s!name]
+ \definefontsynonym [SerifRegular] [Serif]
+ \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-Cap]
+ \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-BoldCap]
+ \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-ItalicCap]
+ \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-ItalicCap]
+ \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-BoldItalicCap]
+ \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-BoldItalicCap]
+ \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-Cap]
+
+ \definefontsynonym [SerifRegularLight] [AntykwaTorunska-Light]
+ \definefontsynonym [SerifBoldLight] [AntykwaTorunska-Medium]
+ \definefontsynonym [SerifItalicLight] [AntykwaTorunska-LightItalic]
+ \definefontsynonym [SerifSlantedLight] [AntykwaTorunska-LightItalic]
+ \definefontsynonym [SerifBoldItalicLight] [AntykwaTorunska-MedItalic]
+ \definefontsynonym [SerifBoldSlantedLight] [AntykwaTorunska-MedItalic]
+ \definefontsynonym [SerifCapsLight] [AntykwaTorunska-LightCap]
+
+ \definefontsynonym [SerifRegularCond] [AntykwaTorunska-CondRegular]
+ \definefontsynonym [SerifBoldCond] [AntykwaTorunska-CondBold]
+ \definefontsynonym [SerifItalicCond] [AntykwaTorunska-CondItalic]
+ \definefontsynonym [SerifSlantedCond] [AntykwaTorunska-CondItalic]
+ \definefontsynonym [SerifBoldItalicCond] [AntykwaTorunska-CondBoldItalic]
+ \definefontsynonym [SerifBoldSlantedCond] [AntykwaTorunska-CondBoldItalic]
+ \definefontsynonym [SerifCapsCond] [AntykwaTorunska-CondCap]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa-torunska-light] [\s!name]
+ \definefontsynonym [SerifRegular] [Serif]
+ \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-LightCap]
+ \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-MediumCap]
+ \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-LightItalicCap]
+ \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-LightItalicCap]
+ \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-MedItalicCap]
+ \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-MedItalicCap]
+ \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-LightCap]
+
+ \definefontsynonym [SerifRegularDark] [AntykwaTorunska-Regular]
+ \definefontsynonym [SerifBoldDark] [AntykwaTorunska-Bold]
+ \definefontsynonym [SerifItalicDark] [AntykwaTorunska-Italic]
+ \definefontsynonym [SerifSlantedDark] [AntykwaTorunska-Italic]
+ \definefontsynonym [SerifBoldItalicDark] [AntykwaTorunska-BoldItalic]
+ \definefontsynonym [SerifBoldSlantedDark] [AntykwaTorunska-BoldItalic]
+ \definefontsynonym [SerifCapsDark] [AntykwaTorunska-Cap]
+
+ \definefontsynonym [SerifRegularCond] [AntykwaTorunska-CondLight]
+ \definefontsynonym [SerifBoldCond] [AntykwaTorunska-CondMedium]
+ \definefontsynonym [SerifItalicCond] [AntykwaTorunska-CondLightItalic]
+ \definefontsynonym [SerifSlantedCond] [AntykwaTorunska-CondLightItalic]
+ \definefontsynonym [SerifBoldItalicCond] [AntykwaTorunska-CondMedItalic]
+ \definefontsynonym [SerifBoldSlantedCond] [AntykwaTorunska-CondMedItalic]
+ \definefontsynonym [SerifCapsCond] [AntykwaTorunska-CondLightCap]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa-torunska-cond] [\s!name]
+ \definefontsynonym [SerifRegular] [Serif]
+ \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-CondCap]
+ \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-CondBoldCap]
+ \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-CondItalicCap]
+ \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-CondItalicCap]
+ \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-CondBoldItalicCap]
+ \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-CondBoldItalicCap]
+ \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-CondCap]
+
+ \definefontsynonym [SerifRegularLight] [AntykwaTorunska-CondLight]
+ \definefontsynonym [SerifBoldLight] [AntykwaTorunska-CondMedium]
+ \definefontsynonym [SerifItalicLight] [AntykwaTorunska-CondLightItalic]
+ \definefontsynonym [SerifSlantedLight] [AntykwaTorunska-CondLightItalic]
+ \definefontsynonym [SerifBoldItalicLight] [AntykwaTorunska-CondMedItalic]
+ \definefontsynonym [SerifBoldSlantedLight] [AntykwaTorunska-CondMedItalic]
+ \definefontsynonym [SerifCapsLight] [AntykwaTorunska-CondLightCap]
+
+ \definefontsynonym [SerifRegularExp] [AntykwaTorunska-Regular]
+ \definefontsynonym [SerifBoldExp] [AntykwaTorunska-Bold]
+ \definefontsynonym [SerifItalicExp] [AntykwaTorunska-Italic]
+ \definefontsynonym [SerifSlantedExp] [AntykwaTorunska-Italic]
+ \definefontsynonym [SerifBoldItalicExp] [AntykwaTorunska-BoldItalic]
+ \definefontsynonym [SerifBoldSlantedExp] [AntykwaTorunska-BoldItalic]
+ \definefontsynonym [SerifCapsExp] [AntykwaTorunska-Cap]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa-torunska-lightcond] [\s!name]
+ \definefontsynonym [SerifRegular] [Serif]
+ \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-CondLightCap]
+ \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-CondMediumCap]
+ \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-CondLightItalicCap]
+ \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-CondLightItalicCap]
+ \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-CondMedItalicCap]
+ \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-CondMedItalicCap]
+ \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-CondLightCap]
+
+ \definefontsynonym [SerifRegularDark] [AntykwaTorunska-CondRegular]
+ \definefontsynonym [SerifBoldDark] [AntykwaTorunska-CondBold]
+ \definefontsynonym [SerifItalicDark] [AntykwaTorunska-CondItalic]
+ \definefontsynonym [SerifSlantedDark] [AntykwaTorunska-CondItalic]
+ \definefontsynonym [SerifBoldItalicDark] [AntykwaTorunska-CondBoldItalic]
+ \definefontsynonym [SerifBoldSlantedDark] [AntykwaTorunska-CondBoldItalic]
+ \definefontsynonym [SerifCapsDark] [AntykwaTorunska-CondCap]
+
+ \definefontsynonym [SerifRegularExp] [AntykwaTorunska-Light]
+ \definefontsynonym [SerifBoldExp] [AntykwaTorunska-Medium]
+ \definefontsynonym [SerifItalicExp] [AntykwaTorunska-LightItalic]
+ \definefontsynonym [SerifSlantedExp] [AntykwaTorunska-LightItalic]
+ \definefontsynonym [SerifBoldItalicExp] [AntykwaTorunska-MedItalic]
+ \definefontsynonym [SerifBoldSlantedExp] [AntykwaTorunska-MedItalic]
+ \definefontsynonym [SerifCapsExp] [AntykwaTorunska-LightCap]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-antykwapoltawskiego.mkiv b/Master/texmf-dist/tex/context/base/type-imp-antykwapoltawskiego.mkiv
new file mode 100644
index 00000000000..5a4c1c4621c
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-antykwapoltawskiego.mkiv
@@ -0,0 +1,140 @@
+%D \module
+%D [ file=type-imp-antykwa-poltawskiego,
+%D version=2010.06.21,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Antykwa Poltawskiego,
+%D author=Mojca Miklavec \& 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.
+
+\starttypescriptcollection[antykwa-poltawskiego]
+
+ % condensed and extended variants are still missing
+
+ \starttypescript [antykwa-poltawskiego,antykwa-poltawskiego-light,antykwapoltawskiego,antykwapoltawskiego-light]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [\typescriptone] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default] [\s!rscale=1.05]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.05]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default] [\s!rscale=1.05]
+ \quittypescriptscanning
+ \stoptypescript
+
+ % names of "Caps" may still change
+
+ \starttypescript [\s!serif] [antykwa-poltawskiego,antykwa-poltawskiego-light,antykwapoltawskiego,antykwapoltawskiego-light]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-Light] [\s!file:antpoltltcond-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-LightItalic] [\s!file:antpoltltcond-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-Regular] [\s!file:antpoltcond-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-Italic] [\s!file:antpoltcond-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-Medium] [\s!file:antpoltltcond-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-MediumItalic] [\s!file:antpoltltcond-bolditalic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-Bold] [\s!file:antpoltcond-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-BoldItalic] [\s!file:antpoltcond-bolditalic] [\s!features=\s!default]
+
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsLight] [\s!file:antpoltltcond-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsLightItalic] [\s!file:antpoltltcond-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsRegular] [\s!file:antpoltcond-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsItalic] [\s!file:antpoltcond-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsMedium] [\s!file:antpoltltcond-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsMediumItalic] [\s!file:antpoltltcond-bolditalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsBold] [\s!file:antpoltcond-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsBoldItalic] [\s!file:antpoltcond-bolditalic] [\s!features=\s!smallcaps]
+
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Light] [\s!file:antpoltltsemicond-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-LightItalic] [\s!file:antpoltltsemicond-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Regular] [\s!file:antpoltsemicond-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Italic] [\s!file:antpoltsemicond-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Medium] [\s!file:antpoltltsemicond-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-MediumItalic] [\s!file:antpoltltsemicond-bolditalic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Bold] [\s!file:antpoltsemicond-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-BoldItalic] [\s!file:antpoltsemicond-bolditalic] [\s!features=\s!default]
+
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsLight] [\s!file:antpoltltsemicond-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsLightItalic] [\s!file:antpoltltsemicond-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsRegular] [\s!file:antpoltsemicond-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsItalic] [\s!file:antpoltsemicond-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsMedium] [\s!file:antpoltltsemicond-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsMediumItalic] [\s!file:antpoltltsemicond-bolditalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsBold] [\s!file:antpoltsemicond-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsBoldItalic] [\s!file:antpoltsemicond-bolditalic] [\s!features=\s!smallcaps]
+
+ \definefontsynonym [AntykwaPoltawskiego-Light] [\s!file:antpoltlt-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-LightItalic] [\s!file:antpoltlt-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Regular] [\s!file:antpolt-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Italic] [\s!file:antpolt-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Medium] [\s!file:antpoltlt-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-MediumItalic] [\s!file:antpoltlt-bolditalic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Bold] [\s!file:antpolt-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-BoldItalic] [\s!file:antpolt-bolditalic] [\s!features=\s!default]
+
+ \definefontsynonym [AntykwaPoltawskiego-CapsLight] [\s!file:antpoltcond-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-CapsLightItalic] [\s!file:antpoltcond-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-CapsRegular] [\s!file:antpolt-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-CapsItalic] [\s!file:antpolt-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-CapsMedium] [\s!file:antpoltcond-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-CapsMediumItalic] [\s!file:antpoltcond-bolditalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-CapsBold] [\s!file:antpolt-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-CapsBoldItalic] [\s!file:antpolt-bolditalic] [\s!features=\s!smallcaps]
+
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Light] [\s!file:antpoltltsemiexpd-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-LightItalic] [\s!file:antpoltltsemiexpd-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Regular] [\s!file:antpoltsemiexpd-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Italic] [\s!file:antpoltsemiexpd-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Medium] [\s!file:antpoltltsemiexpd-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-MediumItalic] [\s!file:antpoltltsemiexpd-bolditalic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Bold] [\s!file:antpoltsemiexpd-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-BoldItalic] [\s!file:antpoltsemiexpd-bolditalic] [\s!features=\s!default]
+
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsLight] [\s!file:antpoltltsemiexpd-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsLightItalic] [\s!file:antpoltltsemiexpd-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsRegular] [\s!file:antpoltsemiexpd-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsItalic] [\s!file:antpoltsemiexpd-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsMedium] [\s!file:antpoltltsemiexpd-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsMediumItalic] [\s!file:antpoltltsemiexpd-bolditalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsBold] [\s!file:antpoltsemiexpd-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsBoldItalic] [\s!file:antpoltsemiexpd-bolditalic] [\s!features=\s!smallcaps]
+
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-Light] [\s!file:antpoltltexpd-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-LightItalic] [\s!file:antpoltltexpd-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-Regular] [\s!file:antpoltexpd-regular] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-Italic] [\s!file:antpoltexpd-italic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-Medium] [\s!file:antpoltltexpd-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-MediumItalic] [\s!file:antpoltltexpd-bolditalic] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-Bold] [\s!file:antpoltexpd-bold] [\s!features=\s!default]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-BoldItalic] [\s!file:antpoltexpd-bolditalic] [\s!features=\s!default]
+
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsLight] [\s!file:antpoltltexpd-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsLightItalic] [\s!file:antpoltltexpd-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsRegular] [\s!file:antpoltexpd-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsItalic] [\s!file:antpoltexpd-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsMedium] [\s!file:antpoltltexpd-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsMediumItalic] [\s!file:antpoltltexpd-bolditalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsBold] [\s!file:antpoltexpd-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsBoldItalic] [\s!file:antpoltexpd-bolditalic] [\s!features=\s!smallcaps]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa-poltawskiego,antykwapoltawskiego] [\s!name]
+ \definefontsynonym [\s!Serif] [AntykwaPoltawskiego-Regular]
+ \definefontsynonym [\s!SerifBold] [AntykwaPoltawskiego-Bold]
+ \definefontsynonym [\s!SerifItalic] [AntykwaPoltawskiego-Italic]
+ \definefontsynonym [\s!SerifSlanted] [AntykwaPoltawskiego-Italic]
+ \definefontsynonym [\s!SerifBoldItalic] [AntykwaPoltawskiego-BoldItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [AntykwaPoltawskiego-BoldItalic]
+ \definefontsynonym [\s!SerifCaps] [AntykwaPoltawskiego-CapsRegular]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [antykwa-poltawskiego-light,antykwapoltawskiego-light] [\s!name]
+ \definefontsynonym [\s!Serif] [AntykwaPoltawskiego-Light]
+ \definefontsynonym [\s!SerifBold] [AntykwaPoltawskiego-Medium]
+ \definefontsynonym [\s!SerifItalic] [AntykwaPoltawskiego-LightItalic]
+ \definefontsynonym [\s!SerifSlanted] [AntykwaPoltawskiego-LightItalic]
+ \definefontsynonym [\s!SerifBoldItalic] [AntykwaPoltawskiego-MediumItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [AntykwaPoltawskiego-MediumItalic]
+ \definefontsynonym [\s!SerifCaps] [AntykwaPoltawskiego-CapsLight]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-asana.mkiv b/Master/texmf-dist/tex/context/base/type-imp-asana.mkiv
new file mode 100644
index 00000000000..b87c969e2cf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-asana.mkiv
@@ -0,0 +1,35 @@
+%D \module
+%D [ file=type-imp-asana,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Asana,
+%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.
+
+\loadtypescriptfile[texgyre]
+
+\starttypescriptcollection [asanamath]
+
+ \starttypescript [\s!math] [asana]
+ \definefontsynonym [AsanaMath] [\s!name:asanamath]
+ \stoptypescript
+
+ \starttypescript [\s!math] [asana] [\s!name]
+ \loadfontgoodies[asana-math]
+ \definefontsynonym [MathRoman] [AsanaMath] [\s!features=\s!math\mathsizesuffix,\s!goodies=asana-math]
+ \stoptypescript
+
+ \starttypescript[asana]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [palatino] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default] [\s!rscale=1.075]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.075]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [\typescriptone] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-averia.mkiv b/Master/texmf-dist/tex/context/base/type-imp-averia.mkiv
new file mode 100644
index 00000000000..fd0ee7100ad
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-averia.mkiv
@@ -0,0 +1,90 @@
+%D \module
+%D [ file=type-imp-averia,
+%D version=2012.04.24,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Averia fonts (iotic.com),
+%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 fonts can be downloaded from the (nice looking) page:
+%D
+%D \starttyping
+%D http://iotic.com/averia
+%D \stoptyping
+%D
+%D This link was posted by Aditya on the ConTeXt mailing list.
+%D
+%D There is no monospace font yet.
+
+\starttypescriptcollection[averia]
+
+ \starttypescript [\s!serif] [averia] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!file:averia-regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!file:averia-bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:averia-italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:averia-bolditalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [averiaserif] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!file:averiaserif-regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!file:averiaserif-bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:averiaserif-italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:averiaserif-bolditalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [averialight] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!file:averia-light] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!file:averia-regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:averia-lightitalic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:averia-italic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [averiaseriflight] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!file:averiaserif-light] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!file:averiaserif-regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:averiaserif-lightitalic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:averiaserif-italic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [averiasans] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!file:averiasans-regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!file:averiasans-bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:averiasans-italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:averiasans-bolditalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [averiasanslight] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!file:averiasans-light] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!file:averiasans-regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:averiasans-lightitalic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:averiasans-italic] [\s!features=\s!default]
+ \stoptypescript
+
+ % todo: rscale
+
+ \starttypescript[averia]
+ \definetypeface [averia] [\s!rm] [\s!serif] [averiaserif] [\s!default]
+ \definetypeface [averia] [\s!ss] [\s!sans] [averiasans] [\s!default]
+ \definetypeface [averia] [\s!tt] [\s!mono] [dejavu] [\s!default] [\s!rscale=0.850]
+ \definetypeface [averia] [\s!mm] [\s!math] [times] [\s!default] [\s!rscale=1.025]
+ \stoptypescript
+
+ \starttypescript[averialight]
+ \definetypeface [averialight] [\s!rm] [\s!serif] [averiaseriflight] [\s!default]
+ \definetypeface [averialight] [\s!ss] [\s!sans] [averiasanslight] [\s!default]
+ \definetypeface [averialight] [\s!tt] [\s!mono] [dejavu] [\s!default] [\s!rscale=0.850]
+ \definetypeface [averialight] [\s!mm] [\s!math] [times] [\s!default] [\s!rscale=1.025]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-buy.mkiv b/Master/texmf-dist/tex/context/base/type-imp-buy.mkiv
new file mode 100644
index 00000000000..9815cc44b9d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-buy.mkiv
@@ -0,0 +1,37 @@
+%D \module
+%D [ file=type-buy,
+%D version=2003.07.08, % 2001.04.12,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=A Few Commercial Fonts,
+%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.
+
+\starttypescriptcollection[sabon]
+
+\starttypescript [serif] [sabon] [name]
+
+ \definefontsynonym [Serif] [SabonMT]
+ \definefontsynonym [SerifItalic] [SabonMT-Italic]
+ \definefontsynonym [SerifSlanted] [SabonMT-Italic]
+ \definefontsynonym [SerifBold] [SabonMT-SemiBold]
+ \definefontsynonym [SerifBoldItalic] [SabonMT-SemiBoldItalic]
+ \definefontsynonym [SerifBoldSlanted] [SabonMT-SemiBoldItalic]
+ \definefontsynonym [SerifCaps] [SabonMT-RegularSC]
+
+ \definefontsynonym[SabonMT] [sab_____]
+ \definefontsynonym[SabonMT-Italic] [sabi____]
+ \definefontsynonym[SabonMT-ItalicOsF] [saboi___]
+ \definefontsynonym[SabonMT-SemiBoldOsF] [sabos___]
+ \definefontsynonym[SabonMT-SemiBold] [sabs____]
+ \definefontsynonym[SabonMT-RegularSC] [sabsc___]
+ \definefontsynonym[SabonMT-SemiBoldItalic] [sabsi___]
+ \definefontsynonym[SabonMT-SemiBoldItalicOsF][sasio___]
+\stoptypescript
+
+\stoptypescriptcollection
+
diff --git a/Master/texmf-dist/tex/context/base/type-imp-cambria.mkiv b/Master/texmf-dist/tex/context/base/type-imp-cambria.mkiv
new file mode 100644
index 00000000000..91288b6d0ac
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-cambria.mkiv
@@ -0,0 +1,73 @@
+%D \module
+%D [ file=type-imp-cambria,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Microsoft Cambria,
+%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.
+
+\starttypescriptcollection[cambria]
+
+ % microsoft: cambria.ttc cambriab.ttf cambriai.ttf cambriaz.ttf
+ % ascender : cambmath.ttf cambria.ttf cambriab.ttf cambriai.ttf cambriaz.ttf
+
+ \starttypescript [\s!math,\s!serif] [cambria,cambria-x,cambria-y]
+ % whatever matches
+ \definefontsynonym [CambriaMath] [\s!name:cambriamath]
+ \definefontsynonym [CambriaSerif] [\s!name:cambria]
+ \stoptypescript
+ \starttypescript [\s!math,\s!serif] [cambria-m]
+ % microsoft cabria
+ \definefontsynonym [CambriaMath] [\s!file:cambria.ttc(Cambria Math)]
+ \definefontsynonym [CambriaSerif] [\s!file:cambria.ttc(Cambria)]
+ \stoptypescript
+ \starttypescript [\s!math,\s!serif] [cambria-a]
+ % ascender cambria
+ \definefontsynonym [CambriaMath] [\s!file:cambmath.ttf]
+ \definefontsynonym [CambriaSerif] [\s!file:cambria.ttf]
+ \stoptypescript
+
+ % We load a goodies file that will apply a patch to the font. As a demonstration
+ % we apply the patch when caching as as when scaling which is why we also specify
+ % the goodies file with the name.
+
+ \starttypescript [\s!math] [cambria,cambria-m,cambria-a] [\s!name]
+ \loadfontgoodies[cambria-math]
+ \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features=\s!math\mathsizesuffix,\s!goodies=cambria-math]
+ \stoptypescript
+ \starttypescript [\s!math] [cambria-x] [\s!name]
+ \loadfontgoodies[cambria-math]
+ \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features=\s!math,\s!goodies=cambria-math]
+ \stoptypescript
+ \starttypescript [\s!math] [cambria-y] [\s!name]
+ \loadfontgoodies[cambria-math]
+ \definefontsynonym [\s!MathRoman] [CambriaMath] [\s!features=\s!math-nostack\mathsizesuffix,\s!goodies=cambria-math]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [cambria,cambria-m,cambria-a] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [CambriaSerif] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!name:cambriabold] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!name:cambriaitalic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!name:cambriabolditalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [cambria,cambria-m,cambria-a]
+ % any
+ \definetypeface [cambria] [\s!rm] [\s!serif] [\typescriptone] [\s!default]
+ \definetypeface [cambria] [\s!tt] [\s!mono] [modern] [\s!default]
+ \definetypeface [cambria] [\s!mm] [\s!math] [\typescriptone] [\s!default]
+ \stoptypescript
+ \starttypescript [cambria-x,cambria-y]
+ % test x
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [cambria] [\s!default]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [\typescriptone] [\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-charter.mkiv b/Master/texmf-dist/tex/context/base/type-imp-charter.mkiv
new file mode 100644
index 00000000000..b788a974e56
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-charter.mkiv
@@ -0,0 +1,36 @@
+%D \module
+%D [ file=type-imp-charter,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Charter,
+%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.
+
+\starttypescriptcollection[charter]
+
+ \starttypescript [\s!serif] [charter]
+ \definefontsynonym [Charter-Roman] [\s!name:CharterBT-Roman]
+ \definefontsynonym [Charter-Italic] [\s!name:CharterBT-Italic]
+ \definefontsynonym [Charter-Bold] [\s!name:CharterBT-Bold]
+ \definefontsynonym [Charter-BoldItalic] [\s!name:CharterBT-BoldItalic]
+ \definefontsynonym [Charter-Slanted] [\s!name:CharterBT-Italic]
+ \definefontsynonym [Charter-BoldSlanted] [\s!name:CharterBT-BoldItalic]
+ \definefontsynonym [Charter-Roman-Caps] [Charter-Roman]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [charter] [\s!name]
+ \definefontsynonym [Serif] [Charter-Roman]
+ \definefontsynonym [SerifItalic] [Charter-Italic]
+ \definefontsynonym [SerifBold] [Charter-Bold]
+ \definefontsynonym [SerifBoldItalic] [Charter-BoldItalic]
+ \definefontsynonym [SerifSlanted] [Charter-Slanted]
+ \definefontsynonym [SerifBoldSlanted] [Charter-BoldSlanted]
+ \definefontsynonym [SerifCaps] [Charter-Roman-Caps]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-cleartype.mkiv b/Master/texmf-dist/tex/context/base/type-imp-cleartype.mkiv
new file mode 100644
index 00000000000..b2f1b21a5b6
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-cleartype.mkiv
@@ -0,0 +1,56 @@
+%D \module
+%D [ file=type-imp-cleartype,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Microsoft Cleartype,
+%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.
+
+\starttypescriptcollection[cleartype]
+
+ \starttypescript [\s!sans] [candara] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!file:candara] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!file:candarab] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:candarai] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:candaraz] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [consolas] [\s!name]
+ \setups[\s!font:\s!fallback:\s!mono]
+ \definefontsynonym [\s!Mono] [\s!file:consola] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBold] [\s!file:consolab] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoItalic] [\s!file:consolai] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!file:consolaz] [\s!features=\s!none]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [constantia] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!file:constan] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!file:constanb] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:constani] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:constanz] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [corbel] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!file:corbel] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!file:corbelb] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:corbeli] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:corbelz] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [calibri] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!file:calibri] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!file:calibrib] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:calibrii] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:calibriz] [\s!features=\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-computer-modern-unicode.mkiv b/Master/texmf-dist/tex/context/base/type-imp-computer-modern-unicode.mkiv
new file mode 100644
index 00000000000..0789b922e63
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-computer-modern-unicode.mkiv
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=type-computer-modern-unicode,
+%D version=2007.07.30, % moved from type-otf
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Computer Modern Unicode,
+%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.
+
+\starttypescriptcollection[computer-modern-unicode]
+
+ \definefontfeature[default-slanted-concrete][default][slant=.2]
+ \definefontfeature[none-slanted-concrete] [none] [slant=.2]
+
+ \starttypescript [\s!serif] [computer-modern-unicode]
+ \definefontsynonym [\s!Serif] [\s!file:cmunrm] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:cmunti] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifSlanted] [\s!file:cmunsl] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!file:cmunbx] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:cmunbi] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldSlanted][\s!SerifBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [computer-modern-unicode-concrete]
+ \definefontsynonym [\s!Serif] [\s!file:cmunorm] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:cmunoti] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifSlanted] [\s!file:cmunorm] [\s!features=default-slanted-concrete]
+ \definefontsynonym [\s!SerifBold] [\s!file:cmunobx] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:cmunobi] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldSlanted][\s!file:cmunobx] [\s!features=default-slanted-concrete]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [computer-modern-unicode,computer-modern-unicode-concrete]
+ \definefontsynonym [\s!Sans] [\s!file:cmunss] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:cmunsi] [\s!features=\s!default]
+ \definefontsynonym [\s!SansSlanted] [\s!file:cmunss] [\s!features=default-slanted-concrete]
+ \definefontsynonym [\s!SansBold] [\s!file:cmunsx] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:cmunso] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldSlanted] [\s!file:cmunsx] [\s!features=default-slanted-concrete]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [computer-modern-unicode,computer-modern-unicode-concrete]
+ \definefontsynonym [\s!Mono] [\s!file:cmuntt] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoItalic] [\s!file:cmunit] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoSlanted] [\s!file:cmunst] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBold] [\s!file:cmuntb] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!file:cmuntx] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldSlanted] [\s!file:cmuntb] [\s!features=none-slanted-concrete]
+ \stoptypescript
+
+ \starttypescript[computer-modern-unicode,computer-modern-unicode-concrete]
+ \definetypeface[\typescriptone][\s!rm][\s!serif][\typescriptone] [\s!default]
+ \definetypeface[\typescriptone][\s!ss][\s!sans] [computer-modern-unicode][\s!default]
+ \definetypeface[\typescriptone][\s!tt][\s!mono] [computer-modern-unicode][\s!default]
+ \definetypeface[\typescriptone][\s!mm][\s!math] [modern] [\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/type-cow.mkiv b/Master/texmf-dist/tex/context/base/type-imp-cow.mkiv
index 5215e7122f5..1cb825a1192 100644
--- a/Master/texmf-dist/tex/context/base/type-cow.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-imp-cow.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Cow Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-imp-dejavu.mkiv b/Master/texmf-dist/tex/context/base/type-imp-dejavu.mkiv
new file mode 100644
index 00000000000..0e628c4ba8d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-dejavu.mkiv
@@ -0,0 +1,92 @@
+%D \module
+%D [ file=type-imp-dejavu,
+%D version=2010.06.21,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Dejavu fonts (dejavu-fonts.org),
+%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.
+
+\definefontfeature[dejavu-condensed-mono][extend=.8]
+
+\starttypescriptcollection[dejavu]
+
+ \starttypescript [\s!mono] [dejavu-condensed] [\s!name]
+ \setups[\s!font:\s!fallback:\s!mono]
+ % \definefontsynonym [\s!Mono] [\s!name:dejavusansmonocondensed] [\s!features=\s!none]
+ % \definefontsynonym [\s!MonoBold] [\s!name:dejavusansmonoboldcondensed] [\s!features=\s!none]
+ % \definefontsynonym [\s!MonoItalic] [\s!name:dejavusansmonoobliquecondensed] [\s!features=\s!none]
+ % \definefontsynonym [\s!MonoBoldItalic] [\s!name:dejavusansmonoboldobliquecondensed] [\s!features=\s!none]
+ \definefontsynonym [\s!Mono] [\s!name:dejavusansmono] [\s!features=dejavu-condensed-mono]
+ \definefontsynonym [\s!MonoBold] [\s!name:dejavusansmonobold] [\s!features=dejavu-condensed-mono]
+ \definefontsynonym [\s!MonoItalic] [\s!name:dejavusansmonooblique] [\s!features=dejavu-condensed-mono]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!name:dejavusansmonoboldoblique] [\s!features=dejavu-condensed-mono]
+ \stoptypescript
+
+ % \starttypescript [\s!mono] [dejavu-condensed] [\s!name]
+ % \setups[\s!font:\s!fallback:\s!mono]
+ % \definefontsynonym [\s!Mono] [\s!name:dejavusansmono] [\s!features=\s!none]
+ % \definefontsynonym [\s!MonoBold] [\s!name:dejavusansmonobold] [\s!features=\s!none]
+ % \definefontsynonym [\s!MonoItalic] [\s!name:dejavusansmonooblique] [\s!features=\s!none]
+ % \definefontsynonym [\s!MonoBoldItalic] [\s!name:dejavusansmonoboldoblique] [\s!features=\s!none]
+ % \stoptypescript
+
+ \starttypescript[dejavu-condensed]
+ \definetypeface [dejavu-condensed] [\s!rm] [\s!serif] [dejavu-condensed] [\s!default]
+ \definetypeface [dejavu-condensed] [\s!ss] [\s!sans] [dejavu-condensed] [\s!default]
+ \definetypeface [dejavu-condensed] [\s!tt] [\s!mono] [dejavu-condensed] [\s!default]
+ \definetypeface [dejavu-condensed] [\s!mm] [\s!math] [xits] [\s!default] [\s!rscale=1.2]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [dejavu] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!name:dejavuserif] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!name:dejavuserifbold] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!name:dejavuserifitalic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!name:dejavuserifbolditalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [dejavu] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!name:dejavusans] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!name:dejavusansbold] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!name:dejavusansoblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!name:dejavusansboldoblique] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [dejavu] [\s!name]
+ \setups[\s!font:\s!fallback:\s!mono]
+ \definefontsynonym [\s!Mono] [\s!name:dejavusansmono] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBold] [\s!name:dejavusansmonobold] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoItalic] [\s!name:dejavusansmonooblique] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!name:dejavusansmonoboldoblique] [\s!features=\s!none]
+ \stoptypescript
+
+ \starttypescript[dejavu]
+ \definetypeface [dejavu] [\s!rm] [\s!serif] [dejavu] [\s!default]
+ \definetypeface [dejavu] [\s!ss] [\s!sans] [dejavu] [\s!default]
+ \definetypeface [dejavu] [\s!tt] [\s!mono] [dejavu] [\s!default]
+ \definetypeface [dejavu] [\s!mm] [\s!math] [xits] [\s!default] [\s!rscale=1.2]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [dejavu-condensed] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!name:dejavuserifcondensed] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!name:dejavuserifcondensedbold] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!name:dejavuserifcondenseditalic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!name:dejavuserifcondensedbolditalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [dejavu-condensed] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!name:dejavusanscondensed] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!name:dejavusanscondensedbold] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!name:dejavusanscondensedoblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!name:dejavusanscondensedboldoblique] [\s!features=\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-euler.mkiv b/Master/texmf-dist/tex/context/base/type-imp-euler.mkiv
new file mode 100644
index 00000000000..60b9760f55d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-euler.mkiv
@@ -0,0 +1,47 @@
+%D \module
+%D [ file=type-otf,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Euler,
+%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.
+
+\loadtypescriptfile[texgyre]
+
+\starttypescriptcollection[pagella-euler]
+
+ \starttypescript [\s!math] [euler]
+ \definefontsynonym [EulerMath] [\s!file:euler.otf]
+ \stoptypescript
+
+ \starttypescript [\s!math] [euler] [\s!name]
+ % \definefontsynonym [MathRoman] [EulerMath] [\s!features=\s!math]
+ \definefontsynonym [MathRoman] [EulerMath] [\s!features=\s!math\mathsizesuffix]
+ \stoptypescript
+
+ \starttypescript [pagella-euler]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [pagella] [\s!default]
+ % \definetypeface [\typescriptone] [\s!ss] [\s!sans] [pagella] [\s!default]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [euler] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [\s!serif] [euler] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!file:euler.otf] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [euler]
+ \definetypeface [euler] [\s!rm] [\s!serif] [euler] [\s!default]
+ \definetypeface [euler] [\s!tt] [\s!mono] [modern] [\s!default]
+ \definetypeface [euler] [\s!mm] [\s!math] [euler] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-ghz.mkiv b/Master/texmf-dist/tex/context/base/type-imp-ghz.mkiv
index 34a3aa53c9c..868d7302115 100644
--- a/Master/texmf-dist/tex/context/base/type-ghz.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-imp-ghz.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Hermann Zapf's Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -148,11 +148,11 @@
\stoptypescript
-\starttypescript[optima-nova]
- \definetypeface[optima][ss][sans][optima-nova] [default][features=default]
- \definetypeface[optima][rm][sans][optima-nova] [default][features=default]
- \definetypeface[optima][tt][mono][modern] [default][rscale=1.1]
- \definetypeface[optima][mm][math][modern] [default][rscale=1.1]
+\starttypescript[optima-nova,optima]
+ \definetypeface[\typescriptone][ss][sans][optima-nova] [default][features=default]
+ \definetypeface[\typescriptone][rm][sans][optima-nova] [default][features=default]
+ \definetypeface[\typescriptone][tt][mono][modern] [default][rscale=1.1]
+ \definetypeface[\typescriptone][mm][math][modern] [default][rscale=1.1]
\quittypescriptscanning
\stoptypescript
diff --git a/Master/texmf-dist/tex/context/base/type-hgz.mkiv b/Master/texmf-dist/tex/context/base/type-imp-hgz.mkiv
index a3c2a78418c..a3c2a78418c 100644
--- a/Master/texmf-dist/tex/context/base/type-hgz.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-imp-hgz.mkiv
diff --git a/Master/texmf-dist/tex/context/base/type-husayni-default.mkiv b/Master/texmf-dist/tex/context/base/type-imp-husayni.mkiv
index b3c1af5b708..b3c1af5b708 100644
--- a/Master/texmf-dist/tex/context/base/type-husayni-default.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-imp-husayni.mkiv
diff --git a/Master/texmf-dist/tex/context/base/type-imp-hvmath.mkiv b/Master/texmf-dist/tex/context/base/type-imp-hvmath.mkiv
new file mode 100644
index 00000000000..01595710e54
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-hvmath.mkiv
@@ -0,0 +1,30 @@
+%D \module
+%D [ file=type-imp-hvmath,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=HV Math Fonts,
+%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.
+
+\loadtypescriptfile[texgyre]
+
+\starttypescriptcollection[hvmath]
+
+ \starttypescript [\s!math] [hvmath]
+ \definefontsynonym[\s!MathRoman][hvmath@hvmath-math]
+ \loadfontgoodies[hvmath-math]
+ \stoptypescript
+
+ \starttypescript [hvmath]
+ \definetypeface [hvmath] [\s!ss] [\s!sans] [heros] [\s!default] [\s!rscale=0.9]
+ \definetypeface [hvmath] [\s!rm] [\s!serif] [termes] [\s!default]
+ \definetypeface [hvmath] [\s!tt] [\s!mono] [cursor] [\s!default] [\s!rscale=1.05]
+ \definetypeface [hvmath] [\s!mm] [\s!math] [hvmath] [\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-inconsolata.mkiv b/Master/texmf-dist/tex/context/base/type-imp-inconsolata.mkiv
new file mode 100644
index 00000000000..159759e9b5d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-inconsolata.mkiv
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=type-imp-incolsolata,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Inconsolata,
+%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.
+
+\starttypescriptcollection[inconsolata]
+
+ \starttypescript [\s!mono] [inconsolata]
+ \definefontsynonym [Inconsolata] [\s!file:inconsolata.otf]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [inconsolata] [\s!name]
+ \setups[\s!font:\s!fallback:\s!mono]
+ \definefontsynonym [\s!Mono] [Inconsolata]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-buy.mkiv b/Master/texmf-dist/tex/context/base/type-imp-informal.mkiv
index becc4361c4a..575a836e58a 100644
--- a/Master/texmf-dist/tex/context/base/type-buy.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-imp-informal.mkiv
@@ -2,18 +2,16 @@
%D [ file=type-buy,
%D version=2003.07.08, % 2001.04.12,
%D title=\CONTEXT\ Typescript Macros,
-%D subtitle=A Few Commercial Fonts,
+%D subtitle=Informal by M. Vulis,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
-\starttypescriptcollection[commercial fonts]
-
-% Informal : Vulis
+\starttypescriptcollection[informal]
\starttypescript [casual] [informal]
\definefontsynonym [Serif] [Informal-Regular]
@@ -39,7 +37,7 @@
\definefontsynonym [Informal-BoldOblique] [file:ifbo]
\stoptypescript
-\starttypescript [math] [informal] [default]
+\starttypescript [math] [informal] [name]
\loadfontgoodies[informal-math]
\definefontsynonym[MathRoman][informalmath@informal-math]
\stoptypescript
@@ -50,33 +48,5 @@
\definetypeface[informal][mm][math] [informal][default]
\stoptypescript
-% Sabon
-
-\starttypescript [serif] [sabon] [name]
-
- \definefontsynonym [Serif] [SabonMT]
- \definefontsynonym [SerifItalic] [SabonMT-Italic]
- \definefontsynonym [SerifSlanted] [SabonMT-Italic]
- \definefontsynonym [SerifBold] [SabonMT-SemiBold]
- \definefontsynonym [SerifBoldItalic] [SabonMT-SemiBoldItalic]
- \definefontsynonym [SerifBoldSlanted] [SabonMT-SemiBoldItalic]
- \definefontsynonym [SerifCaps] [SabonMT-RegularSC]
-
- \definefontsynonym[SabonMT] [sab_____]
- \definefontsynonym[SabonMT-Italic] [sabi____]
- \definefontsynonym[SabonMT-ItalicOsF] [saboi___]
- \definefontsynonym[SabonMT-SemiBoldOsF] [sabos___]
- \definefontsynonym[SabonMT-SemiBold] [sabs____]
- \definefontsynonym[SabonMT-RegularSC] [sabsc___]
- \definefontsynonym[SabonMT-SemiBoldItalic] [sabsi___]
- \definefontsynonym[SabonMT-SemiBoldItalicOsF][sasio___]
-\stoptypescript
-
-% \definetypeface[sabon][rm][serif][sabon][default]
-% \setupbodyfont[sabon]
-% \starttext
-% \input tufte
-% \stoptext
-
\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-iwona.mkiv b/Master/texmf-dist/tex/context/base/type-imp-iwona.mkiv
new file mode 100644
index 00000000000..88cb7e719c3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-iwona.mkiv
@@ -0,0 +1,236 @@
+%D \module
+%D [ file=type-imp-iwona,
+%D version=2010.06.21,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Iwona,
+%D author=Mojca Miklavec \& 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.
+
+\starttypescriptcollection[iwona]
+
+ % maybe this will change in Iwona-Math-Letters and Iwona-Math-Letters-Italic
+
+ % These names are a depressing mess. They have changed over time and are
+ % still not consistent. I'd expect Bold-Regular and Bold-Italic.
+
+ \starttypescript [\s!sans] [iwona-light,iwona,iwona-medium,iwona-heavy,iwona-light-cond,iwona-cond,iwona-medium-cond,iwona-heavy-cond]
+
+ \definefontsynonym [Iwona-Regular] [\s!file:Iwona-Regular] [\s!features=\s!default]
+ \definefontsynonym [Iwona-Italic] [\s!file:Iwona-Italic] [\s!features=\s!default]
+ \definefontsynonym [Iwona-Bold] [\s!file:Iwona-Bold] [\s!features=\s!default]
+ \definefontsynonym [Iwona-BoldItalic] [\s!file:Iwona-BoldItalic] [\s!features=\s!default]
+ \definefontsynonym [Iwona-Light-Regular] [\s!file:IwonaLight-Regular] [\s!features=\s!default]
+ \definefontsynonym [Iwona-Light-Italic] [\s!file:IwonaLight-Italic] [\s!features=\s!default]
+ \definefontsynonym [Iwona-Medium-Regular] [\s!file:IwonaMedium-Regular] [\s!features=\s!default]
+ \definefontsynonym [Iwona-Medium-Italic] [\s!file:IwonaMedium-Italic] [\s!features=\s!default]
+ \definefontsynonym [Iwona-Heavy-Regular] [\s!file:IwonaHeavy-Regular] [\s!features=\s!default]
+ \definefontsynonym [Iwona-Heavy-Italic] [\s!file:IwonaHeavy-Italic] [\s!features=\s!default]
+
+ \definefontsynonym [Iwona-CapsRegular] [\s!file:Iwona-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsItalic] [\s!file:Iwona-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsBold] [\s!file:Iwona-Bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsBoldItalic] [\s!file:Iwona-BoldItalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsLight] [\s!file:IwonaLight-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsLight-Italic] [\s!file:IwonaLight-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsMedium] [\s!file:IwonaMedium-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsMedium-Italic] [\s!file:IwonaMedium-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsHeavy] [\s!file:IwonaHeavy-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsHeavy-Italic] [\s!file:IwonaHeavy-Italic] [\s!features=\s!smallcaps]
+
+ \definefontsynonym [Iwona-CondRegular] [\s!file:IwonaCond-Regular] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondItalic] [\s!file:IwonaCond-Italic] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondBold] [\s!file:IwonaCond-Bold] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondBoldItalic] [\s!file:IwonaCond-BoldItalic] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondLight-Regular] [\s!file:IwonaCondLight-Regular] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondLight-Italic] [\s!file:IwonaCondLight-Italic] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondMedium-Regular] [\s!file:IwonaCondMedium-Regular] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondMedium-Italic] [\s!file:IwonaCondMedium-Italic] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondHeavy-Regular] [\s!file:IwonaCondHeavy-Regular] [\s!features=\s!default]
+ \definefontsynonym [Iwona-CondHeavy-Italic] [\s!file:IwonaCondHeavy-Italic] [\s!features=\s!default]
+
+ \definefontsynonym [Iwona-CapsCondRegular] [\s!file:IwonaCond-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondItalic] [\s!file:IwonaCond-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondBold] [\s!file:IwonaCond-Bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondBoldItalic] [\s!file:IwonaCond-BoldItalic] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondLight-Regular] [\s!file:IwonaCondLight-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondLight-Italic] [\s!file:IwonaCondLight-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondMedium-Regular][\s!file:IwonaCondMedium-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondMedium-Italic] [\s!file:IwonaCondMedium-Italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondHeavy-Regular] [\s!file:IwonaCondHeavy-Regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [Iwona-CapsCondHeavy-Italic] [\s!file:IwonaCondHeavy-Italic] [\s!features=\s!smallcaps]
+
+ \stoptypescript
+
+ % [all] is redundant
+
+ \starttypescript [\s!math][iwona][\s!all]
+ \definefontsynonym[\s!MathRoman][iwonamath@iwona-math]
+ \stoptypescript
+ \starttypescript [\s!math][iwona-light][\s!all]
+ \definefontsynonym[\s!MathRoman][iwonalightmath@iwona-light-math]
+ \stoptypescript
+ \starttypescript [\s!math][iwona-medium][\s!all]
+ \definefontsynonym[\s!MathRoman][iwonamediummath@iwona-medium-math]
+ \stoptypescript
+ \starttypescript [\s!math][iwona-heavy][\s!all]
+ \definefontsynonym[\s!MathRoman][iwonaheavymath@iwona-heavy-math]
+ \stoptypescript
+
+ \starttypescript [\s!math] [iwona,iwona-light,iwona-medium,iwona-heavy] [\s!all]
+ \loadfontgoodies[iwona-math]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-light] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-Light-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-Light-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-Medium-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-Medium-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsLight]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsLightItalic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsMedium]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsMediumItalic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-light-caps] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CapsLight-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CapsLight-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-CapsMedium-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CapsMedium-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-Bold]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-BoldItalic]
+ \definefontsynonym [SansCaps] [Iwona-CapsRegular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsItalic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsBold]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-caps] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CapsRegular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CapsItalic]
+ \definefontsynonym [\s!SansBold] [Iwona-CapsBold]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CapsBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-medium] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-Medium-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-Medium-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-Heavy-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-Heavy-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsMedium-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-medium-caps] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CapsMedium-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CapsHeavy-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-heavy] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-Heavy-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-Heavy-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-Heavy-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-Heavy-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsHeavy-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-heavy-caps] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsHeavy-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-light-cond] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CondLight-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CondLight-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-CondMedium-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CondMedium-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsCondLight-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsCondLight-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsCondMedium-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondMedium-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-light-cond-caps,iwona-light-caps-cond] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CapsCondLight-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CapsCondLight-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-CapsCondMedium-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CapsCondMedium-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-cond] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CondRegular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CondItalic]
+ \definefontsynonym [\s!SansBold] [Iwona-CondBold]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CondBoldItalic]
+ \definefontsynonym [SansCaps] [Iwona-CapsCondRegular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsCondItalic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsCondBold]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-cond-caps,iwona-caps-cond] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CapsCondRegular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CapsCondItalic]
+ \definefontsynonym [\s!SansBold] [Iwona-CapsCondBold]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CapsCondBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-medium-cond] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CondMedium-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CondMedium-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-CondHeavy-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CondHeavy-Italic]
+ \definefontsynonym [SansCaps] [Iwona-CapsCondHeavy-Regular]
+ \definefontsynonym [SansItalicCaps] [Iwona-CapsCondMedium-Italic]
+ \definefontsynonym [SansBoldCaps] [Iwona-CapsCondHeavy-Regular]
+ \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondHeavy-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [iwona-medium-cond-caps,iwona-medium-caps-cond] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Iwona-CapsCondHeavy-Regular]
+ \definefontsynonym [\s!SansItalic] [Iwona-CapsCondMedium-Italic]
+ \definefontsynonym [\s!SansBold] [Iwona-CapsCondHeavy-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Iwona-CapsCondHeavy-Italic]
+ \stoptypescript
+
+ \starttypescript [iwona,iwona-light,iwona-heavy,iwona-medium]
+ \definetypeface[\typescriptone][\s!ss][\s!sans] [\typescriptone] [\s!default]
+ \definetypeface[\typescriptone][\s!rm][\s!serif][modern] [\s!default]
+ \definetypeface[\typescriptone][\s!tt][\s!mono] [modern] [\s!default]
+ \definetypeface[\typescriptone][\s!mm][\s!math] [\typescriptone] [\s!default][text=ss]
+ \quittypescriptscanning
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-kurier.mkiv b/Master/texmf-dist/tex/context/base/type-imp-kurier.mkiv
new file mode 100644
index 00000000000..d83510b95b5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-kurier.mkiv
@@ -0,0 +1,56 @@
+%D \module
+%D [ file=type-imp-kurier,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Kurier by JMN,
+%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.
+
+% There are no open type fonts yet so this should be in type-one.mkiv
+% instead but we keep it here till ready.
+
+\starttypescriptcollection[kurier]
+
+ \starttypescript [\s!sans] [kurier-light,kurier,kurier-medium]
+ \definefontsynonym[Kurier-Light] [kurierl]
+ \definefontsynonym[Kurier-Regular] [kurierr]
+ \definefontsynonym[Kurier-Medium] [kurierm]
+ \definefontsynonym[Kurier-Bold] [kurierb]
+ \definefontsynonym[Kurier-Heavy] [kurierh]
+ \definefontsynonym[Kurier-LightItalic] [kurierli]
+ \definefontsynonym[Kurier-Italic] [kurierri]
+ \definefontsynonym[Kurier-MediumItalic] [kuriermi]
+ \definefontsynonym[Kurier-BoldItalic] [kurierbi]
+ \definefontsynonym[Kurier-HeavyItalic] [kurierhi]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [kurier-light] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Kurier-Light-Regular]
+ \definefontsynonym [\s!SansItalic] [Kurier-Light-Italic]
+ \definefontsynonym [\s!SansBold] [Kurier-Medium-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Kurier-Medium-Italic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [kurier] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Kurier-Regular]
+ \definefontsynonym [\s!SansItalic] [Kurier-Italic]
+ \definefontsynonym [\s!SansBold] [Kurier-Bold]
+ \definefontsynonym [\s!SansBoldItalic] [Kurier-BoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [kurier-medium] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Kurier-Medium-Regular]
+ \definefontsynonym [\s!SansItalic] [Kurier-Medium-Italic]
+ \definefontsynonym [\s!SansBold] [Kurier-Heavy-Regular]
+ \definefontsynonym [\s!SansBoldItalic] [Kurier-Heavy-Italic]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-latinmodern.mkiv b/Master/texmf-dist/tex/context/base/type-imp-latinmodern.mkiv
new file mode 100644
index 00000000000..a9fddad7dfa
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-latinmodern.mkiv
@@ -0,0 +1,224 @@
+%D \module
+%D [ file=type-imp-modern,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Latin Modern,
+%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.
+
+% \starttypescriptcollection[\s!fallback]
+% \starttypescript [\s!fallback]
+% \definetypeface [\s!fallback] [\s!rm] [\s!serif] [modern] [\s!default]
+% \definetypeface [\s!fallback] [\s!ss] [\s!sans] [modern] [\s!default]
+% \definetypeface [\s!fallback] [\s!tt] [\s!mono] [modern] [\s!default]
+% \definetypeface [\s!fallback] [\s!mm] [\s!math] [modern] [\s!default]
+% \quittypescriptscanning
+% \stoptypescript
+% \stoptypescriptcollection
+
+%D Here comes good old Latin Modern, the default font, based on Knuths Computer
+%D Modern. The design size variants is:
+%D
+%D modern-designsize
+
+\starttypescriptcollection[latinmodern]
+
+ \starttypescript [modern-designsize]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [latin-modern-designsize] [\s!default] [\s!designsize=\s!auto]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [latin-modern-designsize] [\s!default] [\s!designsize=\s!auto]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [latin-modern-designsize] [\s!default] [\s!designsize=\s!auto]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [latin-modern-designsize] [\s!default] [\s!designsize=\s!auto]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [modern,modern-base]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [modernvariable,modern-variable]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern-variable] [\s!default]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern-variable] [\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [modernvariablelight,modern-variable-light]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern-variable-light] [\s!default]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern-variable-light] [\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [modern-mono,modern-base-mono]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern-light] [\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [\s!serif] [simple] [\s!name]% for old times sake (manuals)
+ \definefontsynonym [\s!Simple] [\s!file:lmmonoproplt10-regular] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [modern,latin-modern-designsize,latin-modern] [\s!name]
+ \loadfontgoodies[lm]
+ \definefontsynonym [\s!Serif] [LMRoman-Regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [LMRoman-Bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [LMRoman-Italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifSlanted] [LMRoman-Oblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [LMRoman-BoldItalic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldSlanted] [LMRoman-BoldOblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifCaps] [LMRoman-CapsRegular] [\s!features=\s!default]
+ \definefontsynonym [SerifCapsSlanted] [LMRoman-CapsOblique] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [modern,latin-modern-designsize,latin-modern] [\s!name]
+ \loadfontgoodies[lm]
+ \definefontsynonym [\s!Sans] [LMSans-Regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [LMSans-Bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [LMSans-Oblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SansSlanted] [LMSans-Oblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [LMSans-BoldOblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldSlanted] [LMSans-BoldOblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SansCaps] [LMSans-Regular] [\s!features=\s!default]
+ \definefontsynonym [SansCapsSlanted] [LMSans-Oblique] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [modern,latin-modern-designsize,latin-modern] [\s!name]
+ \loadfontgoodies[lm]
+ \definefontsynonym [\s!Mono] [LMTypewriter-Regular] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBold] [LMTypewriter-Dark] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoItalic] [LMTypewriter-Italic] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoSlanted] [LMTypewriter-Oblique] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldItalic] [LMTypewriter-DarkOblique] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldSlanted] [LMTypewriter-DarkOblique] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoCaps] [LMTypewriter-CapsRegular] [\s!features=\s!none]
+ \definefontsynonym [MonoCapsSlanted] [LMTypewriter-CapsOblique] [\s!features=\s!none]
+ \definefontsynonym [MonoVariable] [LMTypewriterVarWd-Regular] [\s!features=\s!none]
+ \stoptypescript
+
+ \starttypescript [\s!math] [modern,latin-modern-designsize,latin-modern] [\s!name]
+ \loadfontgoodies[lm]
+ \loadfontgoodies[lm-math]
+ \definefontsynonym [\s!MathRoman] [LMMathRoman-Regular]
+ \definefontsynonym [\s!MathRomanBold] [LMMathRoman-Bold]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [modern-variable,latin-modern-variable-designsize,latin-modern-variable] [\s!name]
+ \loadfontgoodies[lm]
+ \definefontsynonym [\s!Serif] [LMTypewriterVarWd-Regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [LMTypewriterVarWd-Oblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [LMTypewriterVarWd-Oblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifSlanted] [LMTypewriterVarWd-Dark] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [LMTypewriterVarWd-DarkOblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldSlanted] [LMTypewriterVarWd-DarkOblique] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifCaps] [LMTypewriterVarWd-Regular] [\s!features=\s!default]
+ \definefontsynonym [SerifCapsSlanted] [LMTypewriterVarWd-Oblique] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [modern-condensed,latin-modern-condensed-designsize,latin-modern-condensed,modern-light-condensed,latin-modern-light-condensed] [\s!name]
+ \loadfontgoodies[lm]
+ \definefontsynonym [\s!Mono] [LMTypewriter-LightCondensed] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBold] [LMTypewriter-LightCondensed] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoItalic] [LMTypewriter-LightCondensedOblique] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoSlanted] [LMTypewriter-LightCondensedOblique] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldItalic] [LMTypewriter-LightCondensed] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldSlanted] [LMTypewriter-LightCondensed] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoCaps] [LMTypewriter-LightCondensed] [\s!features=\s!none]
+ \definefontsynonym [MonoCapsSlanted] [LMTypewriter-LightCondensed] [\s!features=\s!none]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [modern-light,latin-modern-light-designsize,latin-modern-light] [\s!name]
+ \loadfontgoodies[lm]
+ \definefontsynonym [\s!Mono] [LMTypewriter-Light] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBold] [LMTypewriter-Light] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoItalic] [LMTypewriter-LightOblique] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoSlanted] [LMTypewriter-LightOblique] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldItalic] [LMTypewriter-Light] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldSlanted] [LMTypewriter-Light] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoCaps] [LMTypewriter-Light] [\s!features=\s!none]
+ \definefontsynonym [MonoCapsSlanted] [LMTypewriter-Light] [\s!features=\s!none]
+ \stoptypescript
+
+ % why not also [name]
+
+ \starttypescript [\s!serif] [modern,latin-modern]
+ \loadfontgoodies[lm]
+ \definefontsynonym [LMRoman-Regular] [\s!file:lmroman10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-Bold] [\s!file:lmroman10-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-Demi] [\s!file:lmromandemi10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-Italic] [\s!file:lmroman10-italic] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-Oblique] [\s!file:lmromanslant10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-BoldItalic] [\s!file:lmroman10-bolditalic] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-BoldOblique] [\s!file:lmromanslant10-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-DemiOblique] [\s!file:lmromandemi10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-CapsRegular] [\s!file:lmroman10-CapsRegular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-CapsOblique] [\s!file:lmroman10-CapsOblique] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-CapsRegular] [\s!file:lmromancaps10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-CapsOblique] [\s!file:lmromancaps10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-Dunhill] [\s!file:lmromandunh10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-DunhillOblique] [\s!file:lmromandunh10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMRoman-Unslanted] [\s!file:lmromanunsl10-regular] [\s!features=\s!default]
+
+ \stoptypescript
+
+ \starttypescript [\s!sans] [modern,latin-modern]
+ \loadfontgoodies[lm]
+ \definefontsynonym [LMSans-Regular] [\s!file:lmsans10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSans-Bold] [\s!file:lmsans10-bold] [\s!features=\s!default]
+ \definefontsynonym [LMSans-Oblique] [\s!file:lmsans10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSans-BoldOblique] [\s!file:lmsans10-boldoblique] [\s!features=\s!default]
+ \definefontsynonym [LMSans-DemiCondensed] [\s!file:lmsansdemicond10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSans-DemiCondensedOblique] [\s!file:lmsansdemicond10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSansQuotation-Regular] [\s!file:lmsansquot8-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSansQuotation-Bold] [\s!file:lmsansquot8-bold] [\s!features=\s!default]
+ \definefontsynonym [LMSansQuotation-Oblique] [\s!file:lmsansquot8-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSansQuotation-BoldOblique] [\s!file:lmsansquot8-boldoblique] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [modern,latin-modern,modern-variable,latin-modern-variable,modern-condensed,latin-modern-condensed]
+ \loadfontgoodies[lm]
+ \definefontsynonym [LMTypewriter-Regular] [\s!file:lmmono10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-Italic] [\s!file:lmmono10-italic] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-Oblique] [\s!file:lmmonoslant10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-CapsRegular] [\s!file:lmmonocaps10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-CapsOblique] [\s!file:lmmonocaps10-oblique] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-Light] [\s!file:lmmonolt10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-LightOblique] [\s!file:lmmonolt10-oblique] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-LightCondensed] [\s!file:lmmonoltcond10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-LightCondensedOblique] [\s!file:lmmonoltcond10-oblique] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-Dark] [\s!file:lmmonolt10-bold] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter-DarkOblique] [\s!file:lmmonolt10-boldoblique] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriterVarWd-Regular] [\s!file:lmmonoproplt10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd-Oblique] [\s!file:lmmonoproplt10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd-Light] [\s!file:lmmonoprop10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd-LightOblique] [\s!file:lmmonoprop10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd-Dark] [\s!file:lmmonoproplt10-bold] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd-DarkOblique] [\s!file:lmmonoproplt10-boldoblique] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!math] [modern,latin-modern]
+ \loadfontgoodies[lm]
+ \definefontsynonym [LMMathRoman-Regular] [\v!file:lmmath-regular.otf] [\s!features=\s!math\mathsizesuffix,\s!goodies=lm]
+ \definefontsynonym [LMMathRoman-Bold] [\v!file:lmmath-regular.otf] [\s!features=\s!math\mathsizesuffix,\s!goodies=lm]
+ \stoptypescript
+
+\stoptypescriptcollection
+
+%D It doesn't hurt to have these, at least for the moment (can go to type-imp-symbol)
+
+\definefontsynonym [ZapfDingbats] [\s!file:uzdr] [\s!goodies=dingbats]
+%definefontsynonym [MartinVogel] [\s!file:marvosym.ttf]
+%definefontsynonym [RalfSmithFormalScript] [\s!file:rsfs10]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/type-imp-liberation.mkiv b/Master/texmf-dist/tex/context/base/type-imp-liberation.mkiv
new file mode 100644
index 00000000000..cc2c01b7bd3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-liberation.mkiv
@@ -0,0 +1,47 @@
+%D \module
+%D [ file=type-imp-liberation,
+%D version=2010.06.21,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Liberation fonts,
+%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.
+
+\starttypescriptcollection[liberation]
+
+ \starttypescript [\s!serif] [liberation] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!file:liberationserif-regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!file:liberationserif-bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:liberationserif-italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:liberationserif-bolditalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [liberation] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!file:liberationsans-regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!file:liberationsans-bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:liberationsans-italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:liberationsans-bolditalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [liberation] [\s!name]
+ \setups[\s!font:\s!fallback:\s!mono]
+ \definefontsynonym [\s!Mono] [\s!file:liberationmono-regular] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBold] [\s!file:liberationmono-bold] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoItalic] [\s!file:liberationmono-italic] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!file:liberationmono-bolditalic] [\s!features=\s!none]
+ \stoptypescript
+
+ \starttypescript[liberation]
+ \definetypeface [liberation] [\s!rm] [\s!serif] [liberation] [\s!default]
+ \definetypeface [liberation] [\s!ss] [\s!sans] [liberation] [\s!default] [\s!rscale=0.870]
+ \definetypeface [liberation] [\s!tt] [\s!mono] [liberation] [\s!default] [\s!rscale=0.870]
+ \definetypeface [liberation] [\s!mm] [\s!math] [times] [\s!default] [\s!rscale=1.040]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-libertine.mkiv b/Master/texmf-dist/tex/context/base/type-imp-libertine.mkiv
new file mode 100644
index 00000000000..be92c27c730
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-libertine.mkiv
@@ -0,0 +1,63 @@
+%D \module
+%D [ file=type-imp-libertine,
+%D version=2010.06.21,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Libertine fonts,
+%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.
+
+\starttypescriptcollection[libertine]
+
+ \starttypescript [\s!serif] [libertine]
+ \definefontsynonym [Libertine-Regular] [\s!file:linlibertiner]
+ \definefontsynonym [Libertine-Italic] [\s!file:linlibertineri]
+ \definefontsynonym [Libertine-Slanted] [\s!file:linlibertinearl]
+ \definefontsynonym [Libertine-Bold] [\s!file:linlibertinerb]
+ \definefontsynonym [Libertine-BoldItalic] [\s!file:linlibertinerbi]
+ \definefontsynonym [Libertine-BoldSlanted] [\s!file:linlibertineabl]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [libertine] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [Libertine-Regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [Libertine-Italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifSlanted] [Libertine-Slanted] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [Libertine-Bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [Libertine-BoldItalic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldSlanted] [Libertine-BoldSlanted] [\s!features=\s!default]
+ \definefontsynonym [SerifCaps] [Libertine-Regular] [\s!features=\s!smallcaps]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [biolinum]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [Biolinum-Regular] [\s!file:linbiolinumr]
+ \definefontsynonym [Biolinum-Bold] [\s!file:linbiolinumrb]
+ \definefontsynonym [Biolinum-Italic] [\s!file:linbiolinumri]
+ \definefontsynonym [Biolinum-Slanted] [\s!file:linbiolinumarl]
+ \definefontsynonym [Biolinum-BoldSlanted] [\s!file:linbiolinumabl]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [biolinum] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [Biolinum-Regular] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [Biolinum-Bold] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [Biolinum-Italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansSlanted] [Biolinum-Slanted] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [Biolinum-BoldSlanted] [\s!features=\s!default]
+ \definefontsynonym [SansCaps] [Biolinum-Regular] [\s!features=\s!smallcaps]
+ \stoptypescript
+
+ \starttypescript [libertine]
+ \definetypeface [libertine] [\s!rm] [\s!serif] [libertine] [\s!default]
+ \definetypeface [libertine] [\s!ss] [\s!sans] [biolinum] [\s!default]
+ \definetypeface [libertine] [\s!tt] [\s!mono] [default] [\s!default]
+ %definetypeface [libertine] [\s!mm] [\s!math] [times] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-lmnames.mkiv b/Master/texmf-dist/tex/context/base/type-imp-lmnames.mkiv
new file mode 100644
index 00000000000..620c5d03b3e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-lmnames.mkiv
@@ -0,0 +1,129 @@
+%D \module
+%D [ file=type-otf,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Opentype Definitions,
+%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.
+
+\starttypescriptcollection[latinmodern-names]
+
+ \starttypescript [\s!serif] [modern,latin-modern-designsize,latin-modern]
+
+ \definefontsynonym [LMRoman5-Regular] [\s!file:lmroman5-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman6-Regular] [\s!file:lmroman6-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman7-Regular] [\s!file:lmroman7-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman8-Regular] [\s!file:lmroman8-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman9-Regular] [\s!file:lmroman9-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-Regular] [\s!file:lmroman10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman12-Regular] [\s!file:lmroman12-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman17-Regular] [\s!file:lmroman17-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman5-Bold] [\s!file:lmroman5-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman6-Bold] [\s!file:lmroman6-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman7-Bold] [\s!file:lmroman7-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman8-Bold] [\s!file:lmroman8-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman9-Bold] [\s!file:lmroman9-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-Bold] [\s!file:lmroman10-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman12-Bold] [\s!file:lmroman12-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman7-Italic] [\s!file:lmroman7-italic] [\s!features=\s!default]
+ \definefontsynonym [LMRoman8-Italic] [\s!file:lmroman8-italic] [\s!features=\s!default]
+ \definefontsynonym [LMRoman9-Italic] [\s!file:lmroman9-italic] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-Italic] [\s!file:lmroman10-italic] [\s!features=\s!default]
+ \definefontsynonym [LMRoman12-Italic] [\s!file:lmroman12-italic] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-BoldItalic] [\s!file:lmroman10-bolditalic] [\s!features=\s!default]
+ \definefontsynonym [LMRoman8-Oblique] [\s!file:lmromanslant8-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman9-Oblique] [\s!file:lmromanslant9-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-Oblique] [\s!file:lmromanslant10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman12-Oblique] [\s!file:lmromanslant12-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman17-Oblique] [\s!file:lmromanslant17-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-BoldOblique] [\s!file:lmromanslant10-bold] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-Demi] [\s!file:lmromandemi10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-DemiOblique] [\s!file:lmromandemi10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-CapsRegular] [\s!file:lmromancaps10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-CapsOblique] [\s!file:lmromancaps10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-Dunhill] [\s!file:lmromandunh10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-DunhillOblique] [\s!file:lmromandunh10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMRoman10-Unslanted] [\s!file:lmromanunsl10-regular] [\s!features=\s!default]
+
+ \stoptypescript
+
+ \starttypescript [\s!sans] [modern,latin-modern-designsize,latin-modern]
+
+ \definefontsynonym [LMSans8-Regular] [\s!file:lmsans8-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSans9-Regular] [\s!file:lmsans9-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSans10-Regular] [\s!file:lmsans10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSans12-Regular] [\s!file:lmsans12-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSans17-Regular] [\s!file:lmsans17-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSans10-Bold] [\s!file:lmsans10-bold] [\s!features=\s!default]
+ \definefontsynonym [LMSans8-Oblique] [\s!file:lmsans8-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSans9-Oblique] [\s!file:lmsans9-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSans10-Oblique] [\s!file:lmsans10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSans12-Oblique] [\s!file:lmsans12-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSans17-Oblique] [\s!file:lmsans17-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSans10-BoldOblique] [\s!file:lmsans10-boldoblique] [\s!features=\s!default]
+ \definefontsynonym [LMSans10-DemiCondensed] [\s!file:lmsansdemicond10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSans10-DemiCondensedOblique] [\s!file:lmsansdemicond10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSansQuotation8-Regular] [\s!file:lmsansquot8-regular] [\s!features=\s!default]
+ \definefontsynonym [LMSansQuotation8-Bold] [\s!file:lmsansquot8-bold] [\s!features=\s!default]
+ \definefontsynonym [LMSansQuotation8-Oblique] [\s!file:lmsansquot8-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMSansQuotation8-BoldOblique] [\s!file:lmsansquot8-boldoblique] [\s!features=\s!default]
+
+ \stoptypescript
+
+ \starttypescript [\s!mono] [modern,latin-modern-designsize,latin-modern,modern-variable,modern-condensed,latin-modern-variable,latin-modern-condensed]
+
+ \definefontsynonym [LMTypewriter8-Regular] [\s!file:lmmono8-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter9-Regular] [\s!file:lmmono9-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-Regular] [\s!file:lmmono10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter12-Regular] [\s!file:lmmono12-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-Italic] [\s!file:lmmono10-italic] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-Oblique] [\s!file:lmmonoslant10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-CapsRegular] [\s!file:lmmonocaps10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-CapsOblique] [\s!file:lmmonocaps10-oblique] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-Light] [\s!file:lmmonolt10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-LightOblique] [\s!file:lmmonolt10-oblique] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-LightCondensed] [\s!file:lmmonoltcond10-regular] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-LightCondensedOblique] [\s!file:lmmonoltcond10-oblique] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-Dark] [\s!file:lmmonolt10-bold] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriter10-DarkOblique] [\s!file:lmmonolt10-boldoblique] [\s!features=\s!none]
+ \definefontsynonym [LMTypewriterVarWd10-Regular] [\s!file:lmmonoproplt10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd10-Oblique] [\s!file:lmmonoproplt10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd10-Light] [\s!file:lmmonoprop10-regular] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd10-LightOblique] [\s!file:lmmonoprop10-oblique] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd10-Dark] [\s!file:lmmonoproplt10-bold] [\s!features=\s!default]
+ \definefontsynonym [LMTypewriterVarWd10-DarkOblique] [\s!file:lmmonoproplt10-boldoblique] [\s!features=\s!default]
+
+ \stoptypescript
+
+ \starttypescript [\s!math] [modern,latin-modern]
+
+ \definefontsynonym [LMMathRoman5-Regular] [LMMath5-Regular@lmroman5-math]
+ \definefontsynonym [LMMathRoman6-Regular] [LMMath6-Regular@lmroman6-math]
+ \definefontsynonym [LMMathRoman7-Regular] [LMMath7-Regular@lmroman7-math]
+ \definefontsynonym [LMMathRoman8-Regular] [LMMath8-Regular@lmroman8-math]
+ \definefontsynonym [LMMathRoman9-Regular] [LMMath9-Regular@lmroman9-math]
+ \definefontsynonym [LMMathRoman10-Regular] [LMMath10-Regular@lmroman10-math]
+ \definefontsynonym [LMMathRoman12-Regular] [LMMath12-Regular@lmroman12-math]
+ \definefontsynonym [LMMathRoman17-Regular] [LMMath17-Regular@lmroman17-math]
+
+ % we no longer care to provide pseudo full bold
+
+ \definefontsynonym [LMMathRoman5-Bold] [LMMathRoman5-Regular]
+ \definefontsynonym [LMMathRoman6-Bold] [LMMathRoman6-Regular]
+ \definefontsynonym [LMMathRoman7-Bold] [LMMathRoman7-Regular]
+ \definefontsynonym [LMMathRoman8-Bold] [LMMathRoman8-Regular]
+ \definefontsynonym [LMMathRoman9-Bold] [LMMathRoman9-Regular]
+ \definefontsynonym [LMMathRoman10-Bold] [LMMathRoman10-Regular]
+ \definefontsynonym [LMMathRoman12-Bold] [LMMathRoman12-Regular]
+ \definefontsynonym [LMMathRoman17-Bold] [LMMathRoman17-Regular]
+
+ \loadfontgoodies[lm-math]
+
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-lucida-opentype.mkiv b/Master/texmf-dist/tex/context/base/type-imp-lucida-opentype.mkiv
new file mode 100644
index 00000000000..8c4ff3bbae5
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-lucida-opentype.mkiv
@@ -0,0 +1,92 @@
+%D \module
+%D [ file=type-lucida-opentype,
+%D version=2011.05.18,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Lucida Nova Opentype,
+%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.
+
+% NOTA BENE: class feattures and goodies get expanded!
+
+\starttypescriptcollection[lucida-opentype]
+
+ \starttypescript [lucidanova,lucidaot,otlucida]
+ \loadfontgoodies[lucida-opentype-math]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [\typescriptone] [\s!default] [\s!features=\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [\typescriptone] [\s!default] [\s!features=\s!default]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [\typescriptone] [\s!default] [\s!features=\s!none]
+ \definetypeface [\typescriptone] [\s!hw] [\s!handwriting] [\typescriptone] [\s!default] [\s!features=\s!default]
+ \definetypeface [\typescriptone] [\s!cg] [\s!calligraphy] [\typescriptone] [\s!default] [\s!features=\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [\typescriptone] [\s!default]
+ % for the moment here:
+ \setupmathrendering[\typescriptone][\s!it=\s!italic]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [\s!serif] [lucidanova,lucidaot,otlucida]
+ \definefontsynonym [\s!Serif] [\s!file:LucidaBrightOT.otf]
+ \definefontsynonym [\s!SerifBold] [\s!file:LucidaBrightOT-Demi.otf]
+ \definefontsynonym [\s!SerifItalic] [\s!file:LucidaBrightOT-Italic.otf]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:LucidaBrightOT-DemiItalic.otf]
+ \definefontsynonym [\s!SerifSlanted] [\s!SerifItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [\s!SerifBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [lucidanova,lucidaot,otlucida]
+ \definefontsynonym [\s!Sans] [\s!file:LucidaSansOT.otf]
+ \definefontsynonym [\s!SansBold] [\s!file:LucidaSansOT-Demi.otf]
+ \definefontsynonym [\s!SansItalic] [\s!file:LucidaSansOT-Italic.otf]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:LucidaSansOT-DemiItalic.otf]
+ \definefontsynonym [\s!SansSlanted] [\s!SansItalic]
+ \definefontsynonym [\s!SansBoldSlanted] [\s!SansBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [lucidanova,lucidaot,otlucida]
+ \definefontsynonym [\s!Mono] [\s!file:LucidaSansTypewriterOT.otf]
+ \definefontsynonym [\s!MonoBold] [\s!file:LucidaSansTypewriterOT-Bold.otf]
+ \definefontsynonym [\s!MonoItalic] [\s!file:LucidaSansTypewriterOT-Oblique.otf]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!file:LucidaSansTypewriterOT-BoldOblique.otf]
+ \definefontsynonym [\s!MonoSlanted] [\s!MonoItalic]
+ \definefontsynonym [\s!MonoBoldSlanted] [\s!MonoBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!math] [lucidanova,lucidaot,otlucida]
+ \definefontsynonym [\s!MathRoman] [\s!file:LucidaBrightMathOT.otf] [\s!features=\s!math\mathsizesuffix,\s!goodies=lucidanova-math]
+ \definefontsynonym [\s!MathRomanBold] [\s!file:LucidaBrightMathOT-Demi.otf] [\s!features=\s!math\mathsizesuffix,\s!goodies=lucidanova-math]
+ \stoptypescript
+
+ \starttypescript [\s!handwriting] [lucidanova,lucidaot,otlucida]
+ \definefontsynonym [\s!Handwriting] [\s!file:LucidaHandwritingOT.otf]
+ \stoptypescript
+
+ \starttypescript [\s!calligraphy] [lucidanova,lucidaot,otlucida]
+ \definefontsynonym [\s!Calligraphy] [\s!file:LucidaCalligraphyOT.otf]
+ \stoptypescript
+
+\stoptypescriptcollection
+
+\endinput
+
+\starttext
+
+ \setupbodyfont[lucidanova]
+
+% \showfont[Serif][all]
+% \showfont[MathRoman][all]
+
+ \usemodule[fnt-31]
+
+ \startluacode
+ fonts.tracers.coverage {
+ "LucidaMathOT.otf",
+ "LucidaBrightOT.otf",
+ "LucidaSansOT-Typewriter.otf",
+ }
+ \stopluacode
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/type-imp-lucida-typeone.mkiv b/Master/texmf-dist/tex/context/base/type-imp-lucida-typeone.mkiv
new file mode 100644
index 00000000000..5f28b9eedcb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-lucida-typeone.mkiv
@@ -0,0 +1,134 @@
+%D \module
+%D [ file=type-imp-lucida-typeone,
+%D version=2010.06.21,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Lucida,
+%D author=Mojca Miklavec \& 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.
+
+\starttypescriptcollection[lucida-typeone]
+
+ \starttypescript [\s!serif] [lucida]
+ \definefontsynonym [LucidaBright] [\s!name:LucidaBright]
+ \definefontsynonym [LucidaBright-Demi] [\s!name:LucidaBright-Demi]
+ \definefontsynonym [LucidaBright-Italic] [\s!name:LucidaBright-Italic]
+ \definefontsynonym [LucidaBright-DemiItalic] [\s!name:LucidaBright-DemiItalic]
+ \definefontsynonym [LucidaBright-Oblique] [\s!name:LucidaBright-Oblique]
+ \definefontsynonym [LucidaBrightSmallcaps] [\s!name:LucidaBrightSmallcaps]
+ \definefontsynonym [LucidaBrightSmallcaps-Demi] [\s!name:LucidaBrightSmallcaps-Demi]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [lucida]
+ \definefontsynonym [LucidaSans] [\s!name:LucidaSans]
+ \definefontsynonym [LucidaSans-Demi] [\s!name:LucidaSans-Demi]
+ \definefontsynonym [LucidaSans-Bold] [\s!name:LucidaSans-Bold]
+ \definefontsynonym [LucidaSans-Italic] [\s!name:LucidaSans-Italic]
+ \definefontsynonym [LucidaSans-DemiItalic] [\s!name:LucidaSans-DemiItalic]
+ \definefontsynonym [LucidaSans-BoldItalic] [\s!name:LucidaSans-BoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [lucida]
+ \definefontsynonym [LucidaTypewriter] [\s!name:LucidaTypewriter]
+ \definefontsynonym [LucidaTypewriterBold] [\s!name:LucidaTypewriterBold]
+ \definefontsynonym [LucidaTypewriterOblique] [\s!name:LucidaTypewriterOblique]
+ \definefontsynonym [LucidaTypewriterBoldOblique] [\s!name:LucidaTypewriterBoldOblique]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [lucida]
+ \definefontsynonym [LucidaSans-Typewriter] [\s!name:LucidaSans-Typewriter]
+ \definefontsynonym [LucidaSans-TypewriterBold] [\s!name:LucidaSans-TypewriterBold]
+ \definefontsynonym [LucidaSans-TypewriterOblique] [\s!name:LucidaSans-TypewriterOblique]
+ \definefontsynonym [LucidaSans-TypewriterBoldOblique] [\s!name:LucidaSans-TypewriterBoldOblique]
+ \stoptypescript
+
+ \starttypescript [calligraphy] [lucida]
+ \definefontsynonym [LucidaCalligraphy-Italic] [\s!name:LucidaCalligraphy-Italic]
+ \stoptypescript
+
+ \starttypescript [casual] [lucida]
+ \definefontsynonym [LucidaCasual] [\s!name:LucidaCasual]
+ \definefontsynonym [LucidaCasual-Italic] [\s!name:LucidaCasual-Italic]
+ \stoptypescript
+
+ \starttypescript [handwriting] [lucida]
+ \definefontsynonym [LucidaHandwriting-Italic] [\s!name:LucidaHandwriting-Italic]
+ \stoptypescript
+
+ \starttypescript [fax] [lucida]
+ \definefontsynonym [LucidaFax] [\s!name:LucidaFax]
+ \definefontsynonym [LucidaFax-Demi] [\s!name:LucidaFax-Demi]
+ \definefontsynonym [LucidaFax-Italic] [\s!name:LucidaFax-Italic]
+ \definefontsynonym [LucidaFax-DemiItalic] [\s!name:LucidaFax-DemiItalic]
+ \stoptypescript
+
+ \starttypescript [blackletter] [lucida]
+ \definefontsynonym [LucidaBlackletter] [\s!name:LucidaBlackletter]
+ \stoptypescript
+
+ \starttypescript [\s!math] [lucida]
+ \loadfontgoodies[lucida-typeone-math]
+ \definefontsynonym[\s!MathRoman][lucidamath@lucida-math]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [lucida] [\s!name]
+ \definefontsynonym [\s!Serif] [LucidaBright]
+ \definefontsynonym [\s!SerifBold] [LucidaBright-Demi]
+ \definefontsynonym [\s!SerifItalic] [LucidaBright-Italic]
+ \definefontsynonym [\s!SerifBoldItalic] [LucidaBright-DemiItalic]
+ \definefontsynonym [\s!SerifSlanted] [LucidaBright-Oblique]
+ \definefontsynonym [\s!SerifBoldSlanted] [LucidaBright-DemiItalic]
+ \definefontsynonym [SerifCaps] [LucidaBrightSmallcaps]
+ \definefontsynonym [SerifBoldCaps] [LucidaBrightSmallcaps-Demi]
+ \stoptypescript
+
+ % Lucida Bright Sans
+
+ \starttypescript [\s!sans] [lucida] [\s!name]
+ \definefontsynonym [\s!Sans] [LucidaSans]
+ \definefontsynonym [\s!SansBold] [LucidaSans-Demi]
+ \definefontsynonym [\s!SansItalic] [LucidaSans-Italic]
+ \definefontsynonym [\s!SansBoldItalic] [LucidaSans-DemiItalic]
+ \definefontsynonym [\s!SansSlanted] [LucidaSans-Italic]
+ \definefontsynonym [\s!SansBoldSlanted] [LucidaSans-DemiItalic]
+ \definefontsynonym [SansCaps] [LucidaSans]
+ \stoptypescript
+
+ % Lucida Bright Sans Typewriter
+
+ \starttypescript [\s!mono] [lucida] [\s!name]
+ \definefontsynonym [\s!Mono] [LucidaSans-Typewriter]
+ \definefontsynonym [\s!MonoBold] [LucidaSans-TypewriterBold]
+ \definefontsynonym [\s!MonoItalic] [LucidaSans-TypewriterOblique]
+ \definefontsynonym [\s!MonoBoldItalic] [LucidaSans-TypewriterBoldOblique]
+ \definefontsynonym [\s!MonoSlanted] [LucidaSans-TypewriterOblique]
+ \definefontsynonym [\s!MonoBoldSlanted] [LucidaSans-TypewriterBoldOblique]
+ \definefontsynonym [MonoCaps] [LucidaSans-Typewriter]
+ \stoptypescript
+
+ % Lucida Calligraphy
+
+ \starttypescript [calligraphy] [lucida] [\s!name]
+ \definefontsynonym [Calligraphy] [LucidaCalligraphy-Italic]
+ \stoptypescript
+
+ % Lucida Handwriting
+
+ \starttypescript [handwriting] [lucida] [\s!name]
+ \definefontsynonym [Handwriting] [LucidaHandwriting-Italic]
+ \stoptypescript
+
+ \starttypescript [lucida]
+ \definetypeface [lucida] [\s!rm] [\s!serif] [lucida] [\s!default] [\s!features=\s!default]
+ \definetypeface [lucida] [\s!ss] [\s!sans] [lucida] [\s!default] [\s!features=\s!default]
+ \definetypeface [lucida] [\s!tt] [\s!mono] [lucida] [\s!default] [\s!features=\s!none]
+ \definetypeface [lucida] [\s!hw] [\s!handwriting] [lucida] [\s!default] [\s!features=\s!default]
+ \definetypeface [lucida] [\s!cg] [\s!calligraphy] [lucida] [\s!default] [\s!features=\s!default]
+ \definetypeface [lucida] [\s!mm] [\s!math] [lucida] [\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-mathdesign.mkiv b/Master/texmf-dist/tex/context/base/type-imp-mathdesign.mkiv
new file mode 100644
index 00000000000..39ec3843f97
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-mathdesign.mkiv
@@ -0,0 +1,32 @@
+%D \module
+%D [ file=type-imp-mathdesign,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Mathdesign,
+%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.
+
+\starttypescriptcollection [mathdesign]
+
+ \starttypescript [\s!math] [charter,mathdesignch] [\s!all]
+ \loadfontgoodies[charter-math]
+ \definefontsynonym[\s!MathRoman][chartermath@charter-math]
+ \stoptypescript
+
+ \starttypescript [\s!math] [garamond,mathdesigngm] [\s!all]
+ \loadfontgoodies[garamond-math]
+ \definefontsynonym[\s!MathRoman][garamondmath@garamond-math]
+ \stoptypescript
+
+ \starttypescript [\s!math] [utopia,mathdesignut] [\s!all]
+ \loadfontgoodies[utopia-math]
+ \definefontsynonym[\s!MathRoman][utopiamath@utopia-math]
+ \stoptypescript
+
+\stoptypescriptcollection
+
diff --git a/Master/texmf-dist/tex/context/base/type-imp-mathtimes.mkiv b/Master/texmf-dist/tex/context/base/type-imp-mathtimes.mkiv
new file mode 100644
index 00000000000..21288277289
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-mathtimes.mkiv
@@ -0,0 +1,31 @@
+%D \module
+%D [ file=type-imp-mathtimes,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Math Times,
+%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.
+
+\loadtypescriptfile[texgyre]
+
+\starttypescriptcollection[mathtimes]
+
+ \starttypescript [\s!math] [mathtimes] [\s!all]
+ \loadfontgoodies[mathtimes-math]
+ \definefontsynonym[\s!MathRoman][mathtimes@mathtimes-math]
+ \stoptypescript
+
+ \starttypescript [mathtimes]
+ \definetypeface [mathtimes] [\s!rm] [\s!serif] [times] [\s!default]
+ \definetypeface [mathtimes] [\s!ss] [\s!sans] [helvetica] [\s!default] [\s!rscale=0.9]
+ \definetypeface [mathtimes] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.05]
+ \definetypeface [mathtimes] [\s!mm] [\s!math] [mathtimes] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-mscore.mkiv b/Master/texmf-dist/tex/context/base/type-imp-mscore.mkiv
new file mode 100644
index 00000000000..19276c01722
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-mscore.mkiv
@@ -0,0 +1,64 @@
+%D \module
+%D [ file=type-imp-mscore,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Microsoft Core Fonts,
+%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.
+
+\starttypescriptcollection[mscore]
+
+ % .ttf not really needed but we want to force the originals
+
+ \starttypescript [\s!serif] [mscoretimes] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym [\s!Serif] [\s!file:times.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [\s!file:timesbd.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [\s!file:timesi.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!file:timesbi.ttf] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [mscorearial] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!file:arial.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!file:arialbd.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:ariali.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:arialbi.ttf] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [mscorecourier] [\s!name]
+ \setups[\s!font:\s!fallback:\s!mono]
+ \definefontsynonym [\s!Mono] [\s!file:cour.ttf] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBold] [\s!file:courbd.ttf] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoItalic] [\s!file:couri.ttf] [\s!features=\s!none]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!file:courbi.ttf] [\s!features=\s!none]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [mscoreverdana] [\s!name]
+ \setups[\s!font:\s!fallback:\s!sans]
+ \definefontsynonym [\s!Sans] [\s!file:verdana.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!file:verdanab.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!file:verdanai.ttf] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!file:verdanaz.ttf] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript[mscore]
+ \definetypeface [mscore] [\s!rm] [\s!serif] [mscoretimes] [\s!default]
+ \definetypeface [mscore] [\s!ss] [\s!sans] [mscorearial] [\s!default] [\s!rscale=0.860]
+ \definetypeface [mscore] [\s!tt] [\s!mono] [mscorecourier] [\s!default] [\s!rscale=1.065]
+ \definetypeface [mscore] [\s!mm] [\s!math] [times] [\s!default] [\s!rscale=1.020]
+ \stoptypescript
+
+ % \starttypescript[mscoress]
+ % \definetypeface [mscoress] [\s!ss] [\s!sans] [mscorearial] [\s!default]
+ % \definetypeface [mscoress] [\s!rm] [\s!serif] [mscoretimes] [\s!default] [rscale=1.160]
+ % \definetypeface [mscoress] [\s!tt] [\s!mono] [mscorecourier] [\s!default] [rscale=1.240]
+ % \definetypeface [mscoress] [\s!mm] [\s!math] [times] [\s!default] [rscale=1.185]
+ % \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-mac.mkiv b/Master/texmf-dist/tex/context/base/type-imp-osx.mkiv
index 9856439da44..16b8e054582 100644
--- a/Master/texmf-dist/tex/context/base/type-mac.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-imp-osx.mkiv
@@ -5,37 +5,11 @@
%D subtitle=Mac OS X Definitions,
%D author=Wolfgang Schuster,
%D date=\currentdate,
-%D copyright=Wolfgang Schuster]
+%D copyright={Wolfgang Schuster}]
%C
%C This module is part of the \CONTEXT\ macro||package. See
%C mreadme.pdf for details.
-\definetypescriptprefix [f:andalemono] [andalemono]
-\definetypescriptprefix [f:chalkboard] [chalkboard]
-\definetypescriptprefix [f:cochin] [cochin]
-\definetypescriptprefix [f:comicsans] [comicsansms]
-\definetypescriptprefix [f:couriernew] [couriernew]
-\definetypescriptprefix [f:georgia] [georgia]
-\definetypescriptprefix [f:lucidagrande] [lucidagrande]
-\definetypescriptprefix [f:monaco] [monaco]
-\definetypescriptprefix [f:tahoma] [tahoma]
-\definetypescriptprefix [f:timesnewroman] [timesnewroman]
-\definetypescriptprefix [f:trebuchet] [trebuchetms]
-\definetypescriptprefix [f:verdana] [verdana]
-
-\definetypescriptprefix [n:andalemono] [AndaleMono]
-\definetypescriptprefix [n:chalkboard] [Chalkboard]
-\definetypescriptprefix [n:cochin] [Cochin]
-\definetypescriptprefix [n:comicsans] [ComicSans]
-\definetypescriptprefix [n:couriernew] [CourierNew]
-\definetypescriptprefix [n:georgia] [Georgia]
-\definetypescriptprefix [n:lucidagrande] [LucidaGrande]
-\definetypescriptprefix [n:monaco] [Monaco]
-\definetypescriptprefix [n:tahoma] [Tahoma]
-\definetypescriptprefix [n:timesnewroman] [TimesNewRoman]
-\definetypescriptprefix [n:trebuchet] [Trebuchet]
-\definetypescriptprefix [n:verdana] [Verdana]
-
\starttypescriptcollection [macosx]
% American Typewriter
diff --git a/Master/texmf-dist/tex/context/base/type-imp-postscript.mkiv b/Master/texmf-dist/tex/context/base/type-imp-postscript.mkiv
new file mode 100644
index 00000000000..c53b8951996
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-postscript.mkiv
@@ -0,0 +1,26 @@
+%D \module
+%D [ file=type-imp-postscript,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Basic Font Set,
+%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.
+
+\loadtypescriptfile[texgyre]
+
+\starttypescriptcollection[postscript]
+
+ \starttypescript [postscript]
+ \definetypeface [postscript] [\s!rm] [\s!serif] [times] [\s!default]
+ \definetypeface [postscript] [\s!ss] [\s!sans] [helvetica] [\s!default] [\s!rscale=0.9]
+ \definetypeface [postscript] [\s!tt] [\s!mono] [courier] [\s!default] [\s!rscale=1.1]
+ \definetypeface [postscript] [\s!mm] [\s!math] [times] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-punknova.mkiv b/Master/texmf-dist/tex/context/base/type-imp-punknova.mkiv
new file mode 100644
index 00000000000..8d95bf88568
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-punknova.mkiv
@@ -0,0 +1,34 @@
+%D \module
+%D [ file=type-imp-punknova,
+%D version=2010.06.21,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Punk Nova,
+%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 file defined the Punk made by Khaled Hosny based on the
+%D \METAPOST\ output from a (slightly) adapted punk font.
+
+\starttypescriptcollection[punknova]
+
+ \definefontfeature [punknova] [mode=node,script=latn,rand=yes,kern=yes,liga=yes,tlig=yes]
+
+ \starttypescript [\s!serif] [punknova]
+ \definefontsynonym [\s!Serif] [\s!file:punknova-regular] [\s!features=punknova]
+ \definefontsynonym [\s!SerifSlanted] [\s!file:punknova-slanted] [\s!features=punknova]
+ \definefontsynonym [\s!SerifBold] [\s!file:punknova-bold] [\s!features=punknova]
+ \definefontsynonym [\s!SerifBoldSlanted][\s!file:punknova-boldslanted] [\s!features=punknova]
+ \definefontsynonym [\s!SerifItalic] [\s!SerifSlanted]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!SerifBoldSlanted]
+ \stoptypescript
+
+ \starttypescript [punknova]
+ \definetypeface [punknova] [\s!rm] [\s!serif] [punknova] [\s!default]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-texgyre.mkiv b/Master/texmf-dist/tex/context/base/type-imp-texgyre.mkiv
new file mode 100644
index 00000000000..823f6b4a9dc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-texgyre.mkiv
@@ -0,0 +1,222 @@
+%D \module
+%D [ file=type-imp-texgyre,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=\TEX Gyre Fonts,
+%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 There are some weird ones that are never used .. all these Caps ... we can better
+%D split them into pagella-caps etc.
+
+\starttypescriptcollection[texgyre]
+
+ \definetypescriptprefix [f:pagella] [pagella] \definetypescriptprefix [f:palatino] [pagella]
+ \definetypescriptprefix [f:termes] [termes] \definetypescriptprefix [f:times] [termes]
+ \definetypescriptprefix [f:heros] [heros] \definetypescriptprefix [f:helvetica] [heros]
+ \definetypescriptprefix [f:bonum] [bonum] \definetypescriptprefix [f:bookman] [bonum]
+ \definetypescriptprefix [f:schola] [schola] \definetypescriptprefix [f:schoolbook] [schola]
+ \definetypescriptprefix [f:adventor][adventor] \definetypescriptprefix [f:avantgarde] [adventor]
+ \definetypescriptprefix [f:cursor] [cursor] \definetypescriptprefix [f:courier] [cursor]
+ \definetypescriptprefix [f:chorus] [chorus] \definetypescriptprefix [f:chancery] [chorus]
+
+ \definetypescriptprefix [n:pagella] [TeXGyrePagella] \definetypescriptprefix [n:palatino] [TeXGyrePagella]
+ \definetypescriptprefix [n:termes] [TeXGyreTermes] \definetypescriptprefix [n:times] [TeXGyreTermes]
+ \definetypescriptprefix [n:heros] [TeXGyreHeros] \definetypescriptprefix [n:helvetica] [TeXGyreHeros]
+ \definetypescriptprefix [n:bonum] [TeXGyreBonum] \definetypescriptprefix [n:bookman] [TeXGyreBonum]
+ \definetypescriptprefix [n:schola] [TeXGyreSchola] \definetypescriptprefix [n:schoolbook] [TeXGyreSchola]
+ \definetypescriptprefix [n:adventor] [TeXGyreAdventor]% \definetypescriptprefix [n:adventor] [TeXGyreAdventor]
+ \definetypescriptprefix [n:cursor] [TeXGyreCursor] \definetypescriptprefix [n:courier] [TeXGyreCursor]
+ \definetypescriptprefix [n:chorus] [TeXGyreChorus] \definetypescriptprefix [n:chancery] [TeXGyreChorus] % not the full set
+
+ \starttypescript [\s!serif,\s!sans] [adventor,bonum,bookman,heros,helvetica,pagella,palatino,bonum,bookman,schola,schoolbook,termes,times]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [\s!features=\s!default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [\s!features=\s!default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [\s!features=\s!default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [\s!features=\s!default]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Caps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [\s!features=\s!smallcaps]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-ItalicCaps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [\s!features=\s!smallcaps]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldCaps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [\s!features=\s!smallcaps]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [\s!features=\s!smallcaps]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [cursor,courier]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [\s!features=\s!none]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [\s!features=\s!none]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [\s!features=\s!none]
+ \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [\s!features=\s!none]
+ \stoptypescript
+
+ \starttypescript [\s!serif,\s!calligraphy] [chorus,chancery]
+ \definefontsynonym [TeXGyreChorus-MediumItalic] [\s!file:texgyrechorus-mediumitalic] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [pagella,palatino,termes,times,bonum,bookman,schola,schoolbook] [\s!name]
+ \definefontsynonym [\s!Serif] [\typescriptprefix{n:\typescripttwo}-Regular]
+ \definefontsynonym [\s!SerifItalic] [\typescriptprefix{n:\typescripttwo}-Italic]
+ \definefontsynonym [\s!SerifBold] [\typescriptprefix{n:\typescripttwo}-Bold]
+ \definefontsynonym [\s!SerifBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalic]
+ \definefontsynonym [\s!SerifSlanted] [\s!SerifItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [\s!SerifBoldItalic]
+ \definefontsynonym [\s!SerifCaps] [\typescriptprefix{n:\typescripttwo}-Caps]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [pagella-caps,palatino-caps,termes-caps,times-caps,bonum-caps,bookman-caps,schola-caps,schoolbook-caps] [\s!name]
+ \definefontsynonym [\s!Serif] [\typescriptprefix{n:\typescripttwo}-Caps]
+ \definefontsynonym [\s!SerifItalic] [\typescriptprefix{n:\typescripttwo}-ItalicCaps]
+ \definefontsynonym [\s!SerifBold] [\typescriptprefix{n:\typescripttwo}-BoldCaps]
+ \definefontsynonym [\s!SerifBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps]
+ \definefontsynonym [\s!SerifSlanted] [\s!SerifItalic]
+ \definefontsynonym [\s!SerifBoldSlanted] [\s!SerifBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [chorus,chancery] [\s!name]
+ \definefontsynonym [\s!Serif] [TeXGyreChorus-MediumItalic]
+ \definefontsynonym [\s!SerifItalic] [\s!Serif]
+ \definefontsynonym [\s!SerifBold] [\s!Serif]
+ \definefontsynonym [\s!SerifBoldItalic] [\s!Serif]
+ \definefontsynonym [\s!SerifSlanted] [\s!Serif]
+ \definefontsynonym [\s!SerifBoldSlanted] [\s!Serif]
+ \definefontsynonym [\s!SerifCaps] [\s!Serif]
+ \stoptypescript
+
+ \starttypescript [\s!calligraphy] [chorus,chancery] [\s!name]
+ \definefontsynonym [Calligraphy] [TeXGyreChorus-MediumItalic]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [heros,helvetica,adventor] [\s!name]
+ \definefontsynonym [\s!Sans] [\typescriptprefix{n:\typescripttwo}-Regular]
+ \definefontsynonym [\s!SansItalic] [\typescriptprefix{n:\typescripttwo}-Italic]
+ \definefontsynonym [\s!SansBold] [\typescriptprefix{n:\typescripttwo}-Bold]
+ \definefontsynonym [\s!SansBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalic]
+ \definefontsynonym [\s!SansSlanted] [\s!SansItalic]
+ \definefontsynonym [\s!SansBoldSlanted] [\s!SansBoldItalic]
+ \definefontsynonym [\s!SansCaps] [\typescriptprefix{n:\typescripttwo}-Caps]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [heros-caps,helvetica-caps,adventor-caps] [\s!name]
+ \definefontsynonym [\s!Sans] [\typescriptprefix{n:\typescripttwo}-Caps]
+ \definefontsynonym [\s!SansItalic] [\typescriptprefix{n:\typescripttwo}-ItalicCaps]
+ \definefontsynonym [\s!SansBold] [\typescriptprefix{n:\typescripttwo}-BoldCaps]
+ \definefontsynonym [\s!SansBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps]
+ \definefontsynonym [\s!SansSlanted] [\s!SansItalic]
+ \definefontsynonym [\s!SansBoldSlanted] [\s!SansBoldItalic]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [cursor,courier] [\s!name]
+ \definefontsynonym [\s!Mono] [\typescriptprefix{n:\typescripttwo}-Regular]
+ \definefontsynonym [\s!MonoItalic] [\typescriptprefix{n:\typescripttwo}-Italic]
+ \definefontsynonym [\s!MonoBold] [\typescriptprefix{n:\typescripttwo}-Bold]
+ \definefontsynonym [\s!MonoBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalic]
+ \definefontsynonym [\s!MonoSlanted] [\s!MonoItalic]
+ \definefontsynonym [\s!MonoBoldSlanted] [\s!MonoBoldItalic]
+ \definefontsynonym [\s!MonoCaps] [\typescriptprefix{n:\typescripttwo}-Caps]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [cursor-caps,courier-caps] [\s!name]
+ \definefontsynonym [\s!Mono] [\typescriptprefix{n:\typescripttwo}-Caps]
+ \definefontsynonym [\s!MonoItalic] [\typescriptprefix{n:\typescripttwo}-ItalicCaps]
+ \definefontsynonym [\s!MonoBold] [\typescriptprefix{n:\typescripttwo}-BoldCaps]
+ \definefontsynonym [\s!MonoBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps]
+ \definefontsynonym [\s!MonoSlanted] [\s!MonoItalic]
+ \definefontsynonym [\s!MonoBoldSlanted] [\s!MonoBoldItalic]
+ \stoptypescript
+
+ % interesting is that we cannot move these definitions up (without loosing features)
+
+ % caps: \definetypeface [pagella] [rm] [serif] [pagella-caps] [default]
+
+ \starttypescript [times,termes]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [\typescriptone] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [helvetica] [\s!default] [\s!rscale=0.9]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.05]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [times] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [palatino,pagella]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [\typescriptone] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default] [\s!rscale=1.075]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.075]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [palatino] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [schoolbook,schola]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [\typescriptone] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default] [\s!rscale=1.1]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.1]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default] [\s!rscale=1.1]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [bookman,bonum]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [\typescriptone] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default] [\s!rscale=1.1]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.1]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default] [\s!rscale=1.1]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [chancery,chorus]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [\typescriptone] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [helvetica,heros]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [\typescriptone] [\s!default]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern] [\s!default] [\s!rscale=1.15]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.15]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default] [\s!rscale=1.15]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [avantgarde,adventor]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [adventor] [\s!default]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern] [\s!default] [\s!rscale=1.15]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.15]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+ \starttypescript [courier,cursor]
+ \definetypeface [\typescriptone] [\s!tt] [\s!mono] [\typescriptone] [\s!default]
+ \definetypeface [\typescriptone] [\s!rm] [\s!serif] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!ss] [\s!sans] [modern] [\s!default]
+ \definetypeface [\typescriptone] [\s!mm] [\s!math] [modern] [\s!default]
+ \quittypescriptscanning
+ \stoptypescript
+
+\stoptypescriptcollection
+
+\starttypescriptcollection[xmath]
+
+ % Times Math (tx)
+
+ \starttypescript [\s!math][times,termes][\s!all]
+ \loadfontgoodies[tx-math]
+ \definefontsynonym[\s!MathRoman][txmath@tx-math]
+ % \definefontsynonym[\s!MathRomanBold][MathRoman]
+ \stoptypescript
+
+ % Palatino Math (px)
+
+ \starttypescript [\s!math][palatino,pagella][\s!all]
+ \loadfontgoodies[px-math]
+ \definefontsynonym[\s!MathRoman][pxmath@px-math]
+ % \definefontsynonym[\s!MathRomanBold][MathRoman]
+ \stoptypescript
+
+% \starttypescript [\s!math][palatino,pagella][\s!all]
+% \definefontsynonym[\s!MathRoman][file:texgyrepagella-math.otf][\s!features=\s!math\mathsizesuffix]
+% \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-unfonts.mkiv b/Master/texmf-dist/tex/context/base/type-imp-unfonts.mkiv
new file mode 100644
index 00000000000..91ae3b2300f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-unfonts.mkiv
@@ -0,0 +1,142 @@
+%D \module
+%D [ file=type-imp-unfonts,
+%D version=2012.03.11,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=UnFonts,
+%D author=Dalyoung \& Hans,
+%D date=\currentdate,
+%D copyright=Dalyoung \& Hans]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+% usage: \setupbodyfont[unfonts]
+
+\loadtypescriptfile[texgyre]
+\loadtypescriptfile[xits]
+
+\definefontfeature
+ [kr-default]
+ [mode=node,script=hang,lang=kor]
+
+\definefontfeature
+ [kr-slanted]
+ [mode=node,script=hang,lang=kor,slant=.2]
+
+\definefontfeature
+ [kr-latin-default]
+ [default]
+
+\definefontfeature
+ [kr-latin-slanted]
+ [krlatindefault]
+ [slant=.2]
+
+\definefontfeature
+ [kr-latin-slanted-mono]
+ [slant=.2]
+
+\definefontfeature
+ [kr-latin-smallcaps]
+ [krlatindefault]
+ [smcp=yes]
+
+\definefontfeature
+ [kr-latin-smallcaps-mono]
+ [cmcp=yes]
+
+\definefontfallback[kr-serif] [texgyrepagella-regular*kr-latin-default] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-serifbold] [texgyrepagella-bold*kr-latin-default] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-serifitalic] [texgyrepagella-italic*kr-latin-default] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-serifbolditalic] [texgyrepagella-bolditalic*kr-latin-default] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-serifslanted] [texgyrepagella-regular*kr-latin-slanted] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-serifboldslanted][texgyrepagella-bold*kr-latin-slanted] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-serifcaps] [texgyrepagella-regular*kr-latin-smallcaps] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-sans] [texgyreheros-regular*kr-latin-default] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-sansbold] [texgyreheros-bold*kr-latin-default] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-sansitalic] [texgyreheros-italic*kr-latin-default] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-sansbolditalic] [texgyreheros-bolditalic*kr-latin-default] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-sansslanted] [texgyreheros-regular*kr-latin-slanted] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-sansboldslanted] [texgyreheros-bold*kr-latin-slanted] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-sanscaps] [texgyreheros-regular*kr-latin-smallcaps] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-mono] [texgyrecursor-regular] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-monobold] [texgyrecursor-bold] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-monoitalic] [texgyrecursor-italic] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-monobolditalic] [texgyrecursor-bolditalic] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-monoslanted] [texgyrecursor-regular*kr-latin-slanted-mono] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-monoboldslanted] [texgyrecursor-bold*kr-latin-slanted-mono] [0x0000-0x0400][force=yes]
+\definefontfallback[kr-monocaps] [texgyrecursor-regular*kr-latin-smallcaps-mono][0x0000-0x0400][force=yes]
+
+\starttypescriptcollection[unfonts]
+
+ \starttypescript [\s!serif] [unbatang]
+ \definefontsynonym [unbatang] [\s!file:unbatang] [\s!features=kr-default,\s!fallbacks=kr-serif]
+ \definefontsynonym [unbatangbold] [\s!file:unbatangbold][\s!features=kr-default,\s!fallbacks=kr-serifbold]
+ \definefontsynonym [unbatangitalic] [\s!file:unbatang] [\s!features=kr-slanted,\s!fallbacks=kr-serifitalic]
+ \definefontsynonym [unbatangbolditalic] [\s!file:unbatangbold][\s!features=kr-slanted,\s!fallbacks=kr-serifbolditalic]
+ \definefontsynonym [unbatangslanted] [\s!file:unbatang] [\s!features=kr-slanted,\s!fallbacks=kr-serifslanted]
+ \definefontsynonym [unbatangboldslanted][\s!file:unbatangbold][\s!features=kr-slanted,\s!fallbacks=kr-serifboldslanted]
+ \definefontsynonym [unbatangcaps] [\s!file:unbatang] [\s!features=kr-default,\s!fallbacks=kr-serifcaps]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [undotum]
+ \definefontsynonym[undotum] [\s!file:undotum] [\s!features=kr-default,\s!fallbacks=kr-sans]
+ \definefontsynonym[undotumbold] [\s!file:undotumbold] [\s!features=kr-default,\s!fallbacks=kr-sansbold]
+ \definefontsynonym[undotumitalic] [\s!file:undotum] [\s!features=kr-slanted,\s!fallbacks=kr-sansitalic]
+ \definefontsynonym[undotumbolditalic] [\s!file:undotumbold] [\s!features=kr-slanted,\s!fallbacks=kr-sansbolditalic]
+ \definefontsynonym[undotumslanted] [\s!file:undotum] [\s!features=kr-slanted,\s!fallbacks=kr-sansslanted]
+ \definefontsynonym[undotumboldslanted] [\s!file:undotumbold] [\s!features=kr-slanted,\s!fallbacks=kr-sansboldslanted]
+ \definefontsynonym[undotumcaps] [\s!file:undotum] [\s!features=kr-default,\s!fallbacks=kr-sanscaps]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [untype]
+ \definefontsynonym[untype] [\s!file:untaza] [\s!features=kr-default,\s!fallbacks=kr-mono]
+ \definefontsynonym[untypebold] [\s!file:untaza] [\s!features=kr-default,\s!fallbacks=kr-monobold]
+ \definefontsynonym[untypeitalic] [\s!file:untaza] [\s!features=kr-slanted,\s!fallbacks=kr-monoitalic]
+ \definefontsynonym[untypebolditalic] [\s!file:untaza] [\s!features=kr-slanted,\s!fallbacks=kr-monobolditalic]
+ \definefontsynonym[untypeslanted] [\s!file:untaza] [\s!features=kr-slanted,\s!fallbacks=kr-monoslanted]
+ \definefontsynonym[untypeboldslanted] [\s!file:untaza] [\s!features=kr-slanted,\s!fallbacks=kr-monoboldslanted]
+ \definefontsynonym[untypecaps] [\s!file:untaza] [\s!features=kr-default,\s!fallbacks=kr-monocaps]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [unbatang] [\s!name]
+ \definefontsynonym[\s!Serif] [unbatang]
+ \definefontsynonym[\s!SerifBold] [unbatangbold]
+ \definefontsynonym[\s!SerifItalic] [unbatangitalic]
+ \definefontsynonym[\s!SerifBoldItalic] [unbatangbolditalic]
+ \definefontsynonym[\s!SerifSlanted] [unbatangslanted]
+ \definefontsynonym[\s!SerifBoldSlanted][unbatangboldslanted]
+ \definefontsynonym[\s!SerifCaps] [unbatangcaps]
+ \stoptypescript
+
+ \starttypescript [\s!sans] [undotum] [\s!name]
+ \definefontsynonym[\s!Sans] [undotum]
+ \definefontsynonym[\s!SansBold] [undotumbold]
+ \definefontsynonym[\s!SansItalic] [undotumitalic]
+ \definefontsynonym[\s!SansBoldItalic] [undotumbolditalic]
+ \definefontsynonym[\s!SansSlanted] [undotumslanted]
+ \definefontsynonym[\s!SansBoldSlanted] [undotumboldslanted]
+ \definefontsynonym[\s!SansCaps] [undotumcaps]
+ \stoptypescript
+
+ \starttypescript [\s!mono] [untype] [\s!name]
+ \definefontsynonym[\s!Mono] [untype]
+ \definefontsynonym[\s!MonoBold] [untypebold]
+ \definefontsynonym[\s!MonoItalic] [untypeitalic]
+ \definefontsynonym[\s!MonoBoldItalic] [untypebolditalic]
+ \definefontsynonym[\s!MonoSlanted] [untypeslanted]
+ \definefontsynonym[\s!MonoBoldSlanted] [untypeboldslanted]
+ \definefontsynonym[\s!MonoCaps] [untypecaps]
+ \stoptypescript
+
+ % xits might get replaced with a pagella once we have it
+
+ \starttypescript[unfonts]
+ \definetypeface [unfonts] [\s!rm] [\s!serif] [unbatang]
+ \definetypeface [unfonts] [\s!ss] [\s!sans] [undotum]
+ \definetypeface [unfonts] [\s!tt] [\s!mono] [untype]
+ \definetypeface [unfonts] [\s!mm] [\s!math] [xits]
+ \stoptypescript
+
+\stoptypescriptcollection
diff --git a/Master/texmf-dist/tex/context/base/type-imp-xits.mkiv b/Master/texmf-dist/tex/context/base/type-imp-xits.mkiv
new file mode 100644
index 00000000000..5a0c4d15316
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-xits.mkiv
@@ -0,0 +1,57 @@
+%D \module
+%D [ file=type-imp-hvmath,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Xits,
+%D author=Khaled Hosny \& 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.
+
+% This one makes more sense than Stix. Xits uses the glyph collection from stix
+% but packages it in a proper OpenType Math font. From the Stix site: Version 1.1,
+% which will include fonts packaged for use with Microsoft Office applications, is
+% scheduled for release by the end of 2010. Version 1.2, which will include Type 1
+% fonts for use with LaTeX, will follow in 2011. So, we are on our own anyway.
+
+\loadtypescriptfile[texgyre]
+
+\starttypescriptcollection[xits]
+
+ \starttypescript [\s!math] [xits,xitsbidi] [\s!name]
+ \loadfontgoodies[xits-math]
+ \definefontsynonym[\s!MathRoman ][\s!file:xits-math.otf][\s!features=\s!math\mathsizesuffix,\s!goodies=xits-math]
+ \definefontsynonym[\s!MathRoman L2R][\s!file:xits-math.otf][\s!features=\s!math\mathsizesuffix-l2r,\s!goodies=xits-math]
+ \definefontsynonym[\s!MathRoman R2L][\s!file:xits-math.otf][\s!features=\s!math\mathsizesuffix-r2l,\s!goodies=xits-math]
+ \stoptypescript
+
+ \starttypescript [\s!serif] [xits] [\s!name]
+ \setups[\s!font:\s!fallback:\s!serif]
+ \definefontsynonym[\s!Serif] [\s!file:xits-regular.otf] [\s!features=\s!default]
+ \definefontsynonym[\s!SerifBold] [\s!file:xits-bold.otf] [\s!features=\s!default]
+ \definefontsynonym[\s!SerifItalic] [\s!file:xits-italic.otf] [\s!features=\s!default]
+ \definefontsynonym[\s!SerifBoldItalic][\s!file:xits-bolditalic.otf] [\s!features=\s!default]
+ \stoptypescript
+
+ \starttypescript[xits]
+ \definetypeface [xits] [\s!rm] [\s!serif] [xits] [\s!default]
+ \definetypeface [xits] [\s!ss] [\s!sans] [heros] [\s!default] [\s!rscale=0.9]
+ \definetypeface [xits] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.05]
+ \definetypeface [xits] [\s!mm] [\s!math] [xits] [\s!default]
+ \stoptypescript
+
+ % for the moment
+
+ \starttypescript[xitsbidi]
+ \definetypeface [xitsbidi] [\s!rm] [\s!serif] [xits] [\s!default]
+ \definetypeface [xitsbidi] [\s!ss] [\s!sans] [heros] [\s!default] [\s!rscale=0.9]
+ \definetypeface [xitsbidi] [\s!tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.05]
+ %definetypeface [xitsbidi] [\s!mm] [\s!math] [xitsbidi] [bidi] [\s!direction=\s!both]
+ \definetypeface [xitsbidi] [\s!mm] [\s!math] [xitsbidi] [\s!default] [\s!direction=\s!both]
+ \stoptypescript
+
+\stoptypescriptcollection
+
diff --git a/Master/texmf-dist/tex/context/base/type-imp-xitsbidi.mkiv b/Master/texmf-dist/tex/context/base/type-imp-xitsbidi.mkiv
new file mode 100644
index 00000000000..33c4340ed0e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-imp-xitsbidi.mkiv
@@ -0,0 +1,16 @@
+%D \module
+%D [ file=type-imp-hvmath,
+%D version=2007.07.30,
+%D title=\CONTEXT\ Typescript Macros,
+%D subtitle=Xits,
+%D author=Khaled Hosny \& 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.
+
+\loadtypescriptfile[xits]
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/type-ini.lua b/Master/texmf-dist/tex/context/base/type-ini.lua
index fd1282474bc..4ce953168f5 100644
--- a/Master/texmf-dist/tex/context/base/type-ini.lua
+++ b/Master/texmf-dist/tex/context/base/type-ini.lua
@@ -8,24 +8,66 @@ if not modules then modules = { } end modules ['type-ini'] = {
-- more code will move here
-local format, gsub = string.format, string.gsub
+local gsub = string.gsub
-local patterns = { "type-imp-%s.mkiv", "type-imp-%s.tex", "type-%s.mkiv", "type-%s.tex" }
+local report_typescripts = logs.reporter("fonts","typescripts")
-function commands.doprocesstypescriptfile(name)
- name = gsub(name,"^type%-","")
- for i=1,#patterns do
- local filename = format(patterns[i],name)
- local foundname = resolvers.finders.doreadfile("any",".",filename)
- if foundname ~= "" then
- context.startreadingfile()
- context.pushendofline()
- context.unprotect()
- context.input(foundname)
- context.protect()
- context.popendofline()
- context.stopreadingfile()
- return
- end
+local patterns = { "type-imp-%s.mkiv", "type-imp-%s.tex", "type-%s.mkiv", "type-%s.tex" } -- this will be imp only
+
+local function action(name,foundname)
+ context.startreadingfile()
+ context.pushendofline()
+ context.unprotect()
+ context.input(foundname)
+ context.protect()
+ context.popendofline()
+ context.stopreadingfile()
+end
+
+local name_one, name_two
+
+local function failure_two(name)
+ report_typescripts("unknown: library '%s' or '%s'",name_one,name_two)
+end
+
+local function failure_one(name)
+ name_two = gsub(name,"%-.*$","")
+ if name_two == name then
+ report_typescripts("unknown: library '%s'",name_one)
+ else
+ commands.uselibrary {
+ name = name_two,
+ patterns = patterns,
+ action = action,
+ failure = failure_two,
+ onlyonce = false, -- will become true
+ }
end
end
+
+function commands.doprocesstypescriptfile(name)
+ name_one = gsub(name,"^type%-","")
+ commands.uselibrary {
+ name = name_one,
+ patterns = patterns,
+ action = action,
+ failure = failure_one,
+ onlyonce = false, -- will become true
+ }
+end
+
+local patterns = { "type-imp-%s.mkiv", "type-imp-%s.tex" }
+
+local function failure(name)
+ report_typescripts("unknown: library '%s'",name)
+end
+
+function commands.loadtypescriptfile(name) -- a more specific name
+ commands.uselibrary {
+ name = gsub(name,"^type%-",""),
+ patterns = patterns,
+ action = action,
+ failure = failure,
+ onlyonce = false, -- will become true
+ }
+end
diff --git a/Master/texmf-dist/tex/context/base/type-ini.mkii b/Master/texmf-dist/tex/context/base/type-ini.mkii
index d15bb565b57..c6b0a8931d9 100644
--- a/Master/texmf-dist/tex/context/base/type-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/type-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-ini.mkiv b/Master/texmf-dist/tex/context/base/type-ini.mkiv
deleted file mode 100644
index 46b46976dc0..00000000000
--- a/Master/texmf-dist/tex/context/base/type-ini.mkiv
+++ /dev/null
@@ -1,525 +0,0 @@
-%D \module
-%D [ file=type-ini,
-%D version=2001.03.05,
-%D title=\CONTEXT\ Typescript Macros,
-%D subtitle=Initialization,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%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 Typescript Macros / Initialization}
-
-\registerctxluafile{type-ini}{1.001}
-
-%D The default fontclass is empty. We could demand always using fontclasses,
-%D and then make the calling macros simplier (always assume fontclass) but
-%D apart from downward compatibility issues, it would make global, class
-%D spanning definitions a pain. Some day we will introduce a default class.
-
-\unprotect
-
-\unexpanded\def\starttypescriptcollection
- {\dosingleempty\dostarttypescriptcollection}
-
-\def\dostarttypescriptcollection[#1]%
- {}
-
-\unexpanded\def\stoptypescriptcollection
- {}
-
-\let\typescriptfiles\empty
-
-\unexpanded\def\usetypescriptfile[#1]%
- {\doifelse{#1}\v!reset
- {\let\typescriptfiles\empty}
- {\splitfiletype{#1}%
- \addtocommalist\splitoffname\typescriptfiles}}
-
-% SO FAR
-
-\let\currenttypescripts\empty
-
-\newif\iftypescriptfound
-
-\let\@@typescriptone \empty \let\typescriptone \empty
-\let\@@typescripttwo \empty \let\typescripttwo \empty
-\let\@@typescriptthree\empty \let\typescriptthree\empty
-
-% method 2 is for Hans van der Meer
-
-\newtoks\documenttypescripts
-
-% tricky ... here we push/pop
-
-\chardef\typescriptmethod\plusone % 1: empty==all==true 2: empty==false
-\chardef\typescriptstate \plustwo % 1: process 2: store
-
-\unexpanded\def\usetypescript {\let\typescriptmethod\plusone\dotripleempty\dousetypescript}
-\unexpanded\def\usetypescriptexact{\let\typescriptmethod\plustwo\dotripleempty\dousetypescript}
-
-\def\dousetypescript[#1][#2][#3]%
- {\normalexpanded{\noexpand\dodousetypescript[#1][#2][#3]}}
-
-\def\dodousetypescript[#1][#2][#3]% also loads type-loc, a user file
- {\pushmacro\@@typescriptone \edef\@@typescriptone {\truetypescript{#1}}%
- \pushmacro\@@typescripttwo \edef\@@typescripttwo {\truetypescript{#2}}%
- \pushmacro\@@typescriptthree\edef\@@typescriptthree{\truetypescript{#3}}%
- \pushmacro\typescriptone
- \pushmacro\typescripttwo
- \pushmacro\typescriptthree
- \pushmacro\typescriptmethod
- \pushmacro\typescriptstate \let\typescriptstate\plusone % process
- \pushmacro\stoptypescript
- \typescriptfoundfalse
- \iftracetypescripts\writestatus\m!fonts{request: [\@@typescriptone] [\@@typescripttwo] [\@@typescriptthree]}\fi
- \processcommacommand[\typescriptfiles]\dododousetypescriptfile
- \the\documenttypescripts
- \firsttypescriptpassfalse % testen
- \popmacro\stoptypescript
- \popmacro\typescriptstate
- \popmacro\typescriptmethod
- \popmacro\typescriptthree
- \popmacro\typescripttwo
- \popmacro\typescriptone
- \popmacro\@@typescriptthree
- \popmacro\@@typescripttwo
- \popmacro\@@typescriptone}
-
-\newconditional\preloadingtypescripts
-
-\def\preloadtypescripts{\ifproductionrun\settrue\preloadingtypescripts\fi}
-
-\prependtoks
- \preloadtypescripts
-\to \everyjob
-
-% \long\def\xxstarttypescript#1\stoptypescript
-% {\global\loadedtypescripts\@EA{\the\loadedtypescripts\starttypescript#1\stoptypescript}}
-%
-% \long\def\xxstarttypescriptcollection#1\stoptypescriptcollection
-% {\global\loadedtypescripts\@EA{\the\loadedtypescripts\starttypescriptcollection#1\stoptypescriptcollection}}
-
-\newcount\nofpreloadedtypescripts % it's faster to append references than blobs
-
-\long\def\xxstarttypescript#1\stoptypescript
- {\global\advance\nofpreloadedtypescripts\plusone
- \edef\currentpreloadedtypescript{\??ts:\the\nofpreloadedtypescripts}%
- \setgvalue\currentpreloadedtypescript{\starttypescript#1\stoptypescript}%
- %\global\loadedtypescripts\@EAEAEA{\@EA\the\@EA\loadedtypescripts\@EA\getvalue\@EA{\currentpreloadedtypescript}}}
- \normalexpanded{\global\loadedtypescripts{\the\@EA\loadedtypescripts\noexpand\csname\currentpreloadedtypescript\endcsname}}}
-
-\long\def\xxstarttypescriptcollection#1\stoptypescriptcollection
- {\global\advance\nofpreloadedtypescripts\plusone
- \edef\currentpreloadedtypescript{\??ts:\the\nofpreloadedtypescripts}%
- \setgvalue\currentpreloadedtypescript{\starttypescriptcollection#1\stoptypescriptcollection}%
- %\global\loadedtypescripts\@EAEAEA{\@EA\the\@EA\loadedtypescripts\@EA\getvalue\@EA{\currentpreloadedtypescript}}}
- \normalexpanded{\global\loadedtypescripts{\the\@EA\loadedtypescripts\noexpand\csname\currentpreloadedtypescript\endcsname}}}
-
-\def\dododousetypescriptfile#1%
- {\setfalse\quittingtypescript
- \pushmacro\currenttypefile
- \def\currenttypefile{#1}%
- \ifconditional\preloadingtypescripts
- \doprocessandbuffertypescriptfile
- \else
- \doprocesstypescriptfile
- \fi
- \popmacro\currenttypefile
- \ifconditional\quittingtypescript
- \quitcommalist
- \setfalse\quittingtypescript
- \fi}
-
-\def\doprocessandbuffertypescriptfile
- {\expandafter\let\expandafter\loadedtypescripts\csname\??ts:\c!file:\currenttypefile\endcsname
- \ifx\loadedtypescripts\relax
- \dobuffertypescriptfile
- \fi
- \the\loadedtypescripts}
-
-\def\dobuffertypescriptfile
- {\newtoks\loadedtypescripts
- \bgroup
- \let\starttypescript\xxstarttypescript
- \let\starttypescriptcollection\xxstarttypescriptcollection
- \doprocesstypescriptfile
- \egroup
- \expandafter\let\csname\??ts:\c!file:\currenttypefile\endcsname\loadedtypescripts}
-
-\def\doprocesstypescriptfile
- {\ctxcommand{doprocesstypescriptfile("\currenttypefile")}}
-
-\def\usetypescriptonce
- {\dotripleempty\dousetypescriptonce}
-
-\def\dousetypescriptonce[#1][#2][#3]%
- {\doifelseflagged{ts:#1:#2:#3}%
- {\writestatus\m!fonts{once (#1) (#2) (#3)}}
- {\setflag{ts:#1:#2:#3}%
- \normalexpanded{\noexpand\dodousetypescript[#1][#2][#3]}}}
-
-% \definetypescriptsynonym[lbr][cmr]
-
-\unexpanded\def\definetypescriptsynonym
- {\dodoubleempty\dodefinetypescriptsynonym}
-
-\def\dodefinetypescriptsynonym[#1][#2]%
- {\ifsecondargument\setevalue{\??tm#1}{#2}\fi}
-
-\def\truetypescript#1%
- {\ifcsname\??tm#1\endcsname
- \@EA\truetypescript\csname\??tm#1\endcsname\else#1%
- \fi}
-
-% script [serif] [default] [size]
-% script [serif] [computer-modern] [size]
-% script [serif] [computer-modern] [ec]
-% script [serif] [computer-modern] [name]
-% script [serif] [computer-modern] [special]
-
-% todo, make firsttypescriptpass conditional
-
-\newif\iffirsttypescriptpass \firsttypescriptpasstrue
-
-\prependtoks\firsttypescriptpasstrue\to\everyjob
-
-\def\typescript@@all{all}
-
-\newif\iftracetypescripts
-
-\let\stoptypescript\relax
-
-\unexpanded\def\starttypescript
- {\ifcase\typescriptstate
- % 0 = skip
- \@EA\gobbleuntil\@EA\stoptypescript
- \or
- % 1 = process
- \expandafter\dostarttypescript
- \or
- % 2 = store
- \expandafter\nostarttypescript
- \else
- % ? = skip
- \@EA\gobbleuntil\@EA\stoptypescript
- \fi}
-
-\long\def\nostarttypescript#1\stoptypescript
- {\appendtoks\starttypescript#1\stoptypescript\to\documenttypescripts}
-
-\def\dostarttypescript
- {\let\typescriptone \@@typescriptone
- \let\typescripttwo \@@typescripttwo
- \let\typescriptthree\@@typescriptthree
- \let\typescriptmatch\empty
- \doifnextoptionalelse\dostarttypescriptone\dostarttypescriptall}
-
-\long\def\dostarttypescriptall
- {\iffirsttypescriptpass
- \expandafter\doprocesstypescript
- \else
- % skip this since it may do unwanted resets, like
- % setting symbolic font names to unknown, especially
- % in run time user type scripts
- \expandafter\noprocesstypescript
- \fi}
-
-\def\typescriptwritestatus
- {\writestatus\m!fonts{match:\ifx\currenttypefile\relax\space *\fi \typescriptmatch}}
-
-\long\def\dostarttypescriptyes
- {\ifdone
- \typescriptfoundtrue
- \iftracetypescripts\typescriptwritestatus\fi
- \expandafter\doprocesstypescript
- \else
- \expandafter\noprocesstypescript
- \fi}
-
-\long\def\dostarttypescriptone
- {\dochecktypescript\@@typescriptone\typescriptone\redostarttypescriptone}
-
-\long\def\dostarttypescripttwo
- {\dochecktypescript\@@typescripttwo\typescripttwo\redostarttypescripttwo}
-
-\long\def\dostarttypescriptthree
- {\dochecktypescript\@@typescriptthree\typescriptthree\redostarttypescriptthree}
-
-\long\def\redostarttypescriptone
- {\doifnextoptionalelse\dostarttypescripttwo\dostarttypescriptyes}
-
-\long\def\redostarttypescripttwo
- {\doifnextoptionalelse\dostarttypescriptthree\dostarttypescriptyes}
-
-\long\def\redostarttypescriptthree
- {\dostarttypescriptyes}
-
-\def\doprocesstypescript
- {\pushmacro\fontclass}
-
-\unexpanded\def\stoptypescript
- {\popmacro\fontclass}
-
-\long\def\noprocesstypescript#1\stoptypescript
- {}
-
-\let\typescriptmatch\empty
-
-\def\dochecktypescript#1#2#3[#4]% script use value next
- {\donefalse
- \def\@@typescriptcheck{#4}%
- \ifx\@@typescriptcheck\empty % no longer needed / met
- \ifcase\typescriptmethod\or\donetrue\fi
- \else\ifx#1\typescript@@all
- \donetrue
- \else\ifx\@@typescriptcheck\typescript@@all
- \donetrue
- \else\ifx#1\@@typescriptcheck % saves 10% trace so probably faster too
- \donetrue
- \let#2\@@typescriptcheck
- \else
- \normalexpanded{\noexpand\doifcommonelse{\@@typescriptcheck}{#1}}\donetrue\donefalse
- \ifdone
- \let#2\commalistelement
- \fi
- \fi\fi\fi\fi
- \ifdone
- \edef\typescriptmatch{\typescriptmatch\space[#4]}%
- \expandafter#3%
- \else
- \expandafter\noprocesstypescript
- \fi}
-
-%D Yet another speed up: when issued inside typescript, the call
-%D
-%D \starttyping
-%D \quittypescriptscanning
-%D \stoptyping
-%D
-%D quits further loading. For an example, see type-exa:
-
-\newconditional\quittingtypescript \setfalse\quittingtypescript
-
-\def\quittypescriptscanning{\settrue\quittingtypescript}
-
-%D Map files will go away in \LUATEX, but till that happens we
-%D use stripped down support for loading them.
-
-\def\loadmapfile{\dosingleempty\doloadmapfile}
-\def\loadmapline{\dodoubleempty\doloadmapline}
-
-\def\doloadmapfile [#1]{\ctxlua{fonts.mappings.loadfile("#1")}}
-\def\doloadmapline [#1][#2]{\ctxlua{fonts.mappings.loadline("#1","#2")}}
-\def\forgetmapfiles {\ctxlua{fonts.mappings.reset()}}
-
-% \appendtoks
-% \pdfmapfile{}% somehow does not work at the lua end
-% \to \everyjob
-
-\prependtoks
- \loadmapfile[mkiv-base.map]%
-\to \everystarttext
-
-%D A handy shortcut:
-
-% \definetypescriptprefix[serif][Serif]
-% \definetypescriptprefix[sans] [Sans]
-% \definetypescriptprefix[mono] [Mono]
-%
-%\starttypescript [serif,sans,mono] [handling,hanging,hz] [pure,normal,hz,quality]
-% \setupfontsynonym [\typescriptprefix\typescriptone] [handling=\typescriptthree]
-% \stoptypescript
-
-\unexpanded\def\definetypescriptprefix
- {\dodoubleargument\dodefinetypescriptprefix}
-
-\def\dodefinetypescriptprefix[#1][#2]%
- {\setgvalue{\??ts::#1}{#2}} % made global
-
-% without testing:
-%
-% \def\typescriptprefix#1%
-% {\csname\??ts::#1\endcsname}
-%
-% with testing:
-
-\def\typescriptprefix#1%
- {\executeifdefined{\??ts::#1}{#1}}
-
-% defining typefaces:
-%
-% \definetypeface [#1:joke] [#2:rm]
-% \definetypeface [#1:joke] [#2:rm] [#3:...]
-% \definetypeface [#1:joke] [#2:rm] [#3:serif] [#4:lucida] [#5:size] [#6:...]
-
-\unexpanded\def\definetypeface
- {\dosixtupleargument\dodefinetypeface}
-
-\def\tsvar#1#2% \executeifdefined{\??ts#1}{#2}
- {\@EA\ifx\csname\??ts#1\endcsname\empty
- #2%
- \else
- \csname\??ts#1\endcsname
- \fi}
-
-% #1=main #2=rm #3=serif #4=fontname #5=size #6=settings
-
-\let\typefaceencoding\s!default % obsolete
-
-\def\dostarttypefacedefining#1#2#3%
- {\geteparameters[\??ts][\s!rscale=\plusone,\s!features=,\s!fallbacks=,\s!goodies=,#3]%
- \pushmacro\fontclass
- \setcurrentfontclass{#1}%
- \pushmacro\relativefontsize
- \let\relativefontsize\@@tsrscale % still needed ?
- \savefontclassparameters{#2}\@@tsrscale\@@tsfeatures\@@tsfallbacks\@@tsgoodies}
-
-\def\dostoptypefacedefining
- {\popmacro\relativefontsize
- \popmacro\fontclass}
-
-\def\dofastdefinetypeface#1#2#3#4#5%
- {\dododefinetypeface[#1][#2]%
- \dostarttypefacedefining{#1}{#2}{#5}%
- \usetypescript[#3][#4][\t!size]%
- \dostoptypefacedefining}
-
-\def\dodefinetypeface[#1][#2][#3][#4][#5][#6]%
- {\iffifthargument % sixth is optional, we need to expand since in #6 there can be a \typescripttwo
- \iftracetypescripts\writestatus\m!fonts{define: [#1] [#2] [#3] [#4]}\fi
- \dododefinetypeface[#1][#2]%
- \dostarttypefacedefining{#1}{#2}{#6}%
- \usetypescript[#3][#4][\t!name,\t!default]%
- \usetypescript[#3][#5][\t!size]%
- \dostoptypefacedefining
- \else\iffourthargument
- \iftracetypescripts\writestatus\m!fonts{define: [#1] [#2] [#3] [#4]}\fi
- \dododefinetypeface[#1][#2]%
- \dostarttypefacedefining{#1}{#2}{}%
- \usetypescript[#3][#4][\t!name,\t!default]%
- \usetypescript[#3][\s!default][\t!size]%
- \dostoptypefacedefining
- \else\ifthirdargument
- \dododefinetypeface[#1][#2]%
- \getparameters[\??tf#1#2][#3]%
- \else % use definitions in lfg file
- \ctxlua{fonts.definetypeface(\!!bs#1\!!es,\!!bs#2\!!es)}%
- \fi\fi\fi}
-
-\def\dododefinetypeface[#1][#2]% saveguard against redefinition
- {\doifsomething{#1}
- {\ifcsname\??tf#1\s!default\endcsname \else
- \registerfontclass{#1}%
- \setgvalue{\??tf#1\s!default}{#2}%
- \fi
- \ifcsname#1\endcsname \else
- \setugvalue{#1}{\switchtotypeface[#1][#2]}%
- \fi}}
-
-\unexpanded\def\setuptypeface% [class] [settings]
- {\doquadrupleempty\doswitchtotypeface[\setupbodyfont][\fontclass]}
-
-\unexpanded\def\switchtotypeface% [class] [settings]
- {\doquadrupleempty\doswitchtotypeface[\switchtobodyfont][\globalfontclass]}
-
-\def\doswitchtotypeface[#1][#2][#3][#4]%
- {%\doifinsetelse{\s!default,\v!reset}{#3}
- % {\setcurrentfontclass\empty}
- % {\setcurrentfontclass{#3}}%
- \setcurrentfontclass{#3}%
- \let\globalfontclass#2%
- \iffourthargument
- #1[#4]%
- \else\ifx\fontclass\empty
- #1[\c!rm]%
- \else\ifcsname\??tf\fontclass\s!default\endcsname
- #1[\csname\??tf\fontclass\s!default\endcsname]%
- \else
- #1[\c!rm]%
- \fi \fi \fi
- \ifmmode\mr\else\tf\fi} % needed ?
-
-% \def\usetypefile[#1]% recurses on path !
-% {\edef\currenttypefile{\f!typeprefix#1}%
-% \readfile{\currenttypefile.\mksuffix}\donothing{\readfile\currenttypefile\donothing\donothing}}
-
-\def\usetypefile[#1]% recurses on path ! % no storage? obsolete?
- {\edef\currenttypefile{#1}%
- \ctxcommand{doprocesstypescriptfile("\currenttypefile")}}
-
-%D For Taco:
-%D
-%D \starttyping
-%D \inherittypeface[palatino][rm][postscript]
-%D \inherittypeface[palatino][rm][\fontclass]
-%D \inherittypeface[palatino][rm] % == \fontclass
-%D \inherittypeface[palatino] % == [rm,ss,tt,mm]
-%D \stoptyping
-
-\def\inherittypeface
- {\dotripleempty\doinherittypeface}
-
-\def\doinherittypeface[#1][#2][#3]%
- {\doifelsenothing{#2}
- {\doinherittypeface[#1][\c!rm,\c!ss,\c!tt,\c!mm][\fontclass]}
- {\doifnot{#1}{#3}
- {\global\let\checkfontclass\docheckfontclass
- \def\docommand##1{\setevalue{#1-##1}{#3}}%
- \processcommalist[#2]\docommand}}}
-
-%D This hooks into the font mechanism with:
-
-% \def\checkfontclass#1% called often
-% {\edef\fontclass{\executeifdefined{\fontclass-#1}{\fontclass}}}
-
-% \def\checkfontclass#1% called often
-% {\edef\fontclass{\ifcsname\fontclass-#1\endcsname\csname\fontclass-#1\endcsname\else\fontclass\fi}}
-
-\def\docheckfontclass#1% called often
- {\ifcsname\fontclass-#1\endcsname
- \expandafter\let\expandafter\fontclass\csname\fontclass-#1\endcsname
- \fi}
-
-\let\checkfontclass\gobbleoneargument
-
-\fetchruntimecommand \typetypescript {\f!typeprefix\s!run} % will become module
-
-\protect \endinput
-
-% Computer Modern Roman : Donald Knuth
-% Latin Modern: LM Font Revision Team
-
-% LM math vs CM math (analysis by Taco):
-%
-% lmex10.tfm % identical
-% lmmi5.tfm % identical
-% lmmi6.tfm % identical
-% lmmi7.tfm % identical
-% lmmi8.tfm % identical
-% lmmi9.tfm % identical
-% lmmi10.tfm % identical
-% lmmi12.tfm % identical
-% lmmib10.tfm % identical
-% lmsy5.tfm % extra chars: 254,255 (octal)
-% lmsy6.tfm % extra chars: 254,255 (octal)
-% lmsy7.tfm % extra chars: 254,255 (octal)
-% lmsy8.tfm % extra chars: 254,255 (octal)
-% lmsy9.tfm % extra chars: 254,255 (octal)
-% lmsy10.tfm % extra chars: 254,255 (octal)
-% lmbsy10.tfm % extra chars: 254,255 (octal)
-%
-% From the 'AMS' set:
-%
-% lmmib5.tfm % identical
-% lmmib7.tfm % identical
-% lmbsy5.tfm % extra chars: 254,255 (octal)
-% lmbsy7.tfm % extra chars: 254,255 (octal)
-%
-% The two extra characters are:
-%
-% /lessorequalslant
-% /greaterorequalslant
diff --git a/Master/texmf-dist/tex/context/base/type-ini.mkvi b/Master/texmf-dist/tex/context/base/type-ini.mkvi
new file mode 100644
index 00000000000..8ca42854f39
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/type-ini.mkvi
@@ -0,0 +1,605 @@
+%D \module
+%D [ file=type-ini,
+%D version=2001.03.05,
+%D title=\CONTEXT\ Typescript 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 Typescript Macros / Initialization}
+
+\registerctxluafile{type-ini}{1.001}
+
+%D The default fontclass is empty. We could demand always using fontclasses,
+%D and then make the calling macros simplier (always assume fontclass) but
+%D apart from downward compatibility issues, it would make global, class
+%D spanning definitions a pain. Some day we will introduce a default class.
+%D
+%D The \type {type-ini} and \type {font-ini} modules come as a pair and have
+%D mutual dependencies.
+%D
+%D At some point we will only store in memory so some code can go away.
+
+\unprotect
+
+\newcount \c_font_typescripts_n_of_preloaded
+\newconditional\c_font_typescripts_quit
+\newtoks \c_font_typescripts_document
+\newconditional\c_font_typescripts_preload
+\newconditional\c_font_typescripts_first_pass \settrue\c_font_typescripts_first_pass
+
+\newif \iftypescriptfound % will become a mode
+\newif \iftracetypescripts
+
+\newtoks \everybeforedefinetypeface
+\newtoks \everyafterdefinetypeface
+
+\let\typescriptfiles \empty
+\let\currenttypescripts\empty
+\let\currenttypefile \empty
+
+\let\typescriptone \empty % public, used in typescripts
+\let\typescripttwo \empty % public, used in typescripts
+\let\typescriptthree\empty % public, used in typescripts
+
+\let\fontclassstyle \empty
+
+\let\m_font_typescripts_one \empty
+\let\m_font_typescripts_two \empty
+\let\m_font_typescripts_three\empty
+\let\m_font_typescripts_check\empty
+\let\m_font_typescripts_match\empty
+
+\let\t_font_typescripts\relax % uses as synonym
+
+\installcorenamespace{typescriptcache}
+\installcorenamespace{typescriptfiles}
+\installcorenamespace{typescriptonce}
+\installcorenamespace{typescriptsynonyms}
+\installcorenamespace{typescriptprefix}
+\installcorenamespace{typescriptinheritances}
+\installcorenamespace{typescriptdefaultstyles}
+\installcorenamespace{typescriptrelatives}
+
+\definesystemvariable{ts} % TypeScript
+
+% tricky ... here we push/pop ... so \let
+
+\let\typescriptmethod\plusone % 1: empty==all==true 2: empty==false
+\let\typescriptstate \plustwo % 1: process 2: store
+
+\unexpanded\def\starttypescriptcollection
+ {\dosingleempty\font_typescripts_collection_start}
+
+\def\font_typescripts_collection_start[#tag]%
+ {}
+
+\let\stoptypescriptcollection\relax
+
+\unexpanded\def\usetypescriptfile[#filename]%
+ {\doifelse{#filename}\v!reset
+ {\let\typescriptfiles\empty}
+ {\splitfilename{#filename}%
+ \addtocommalist\splitoffbase\typescriptfiles}}
+
+\unexpanded\def\usetypescript {\dotripleempty\font_typescripts_use_one}
+\unexpanded\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}
+
+\unexpanded\def\font_typescripts_use[#one][#two][#three]%
+ {\pushmacro\m_font_typescripts_one
+ \pushmacro\m_font_typescripts_two
+ \pushmacro\m_font_typescripts_three
+ \edef\m_font_typescripts_one {\truetypescript{#one}}%
+ \edef\m_font_typescripts_two {\truetypescript{#two}}%
+ \edef\m_font_typescripts_three{\truetypescript{#three}}%
+ \pushmacro\typescriptone
+ \pushmacro\typescripttwo
+ \pushmacro\typescriptthree
+ \pushmacro\typescriptmethod
+ \pushmacro\typescriptstate
+ \pushmacro\stoptypescript
+ \typescriptfoundfalse
+ \let\typescriptstate\plusone % why
+ \iftracetypescripts
+ \writestatus\m!fonts{request: [\m_font_typescripts_one] [\m_font_typescripts_two] [\m_font_typescripts_three]}%
+ \fi
+ \processcommacommand[\typescriptfiles]\font_typescripts_load_file
+ \the\c_font_typescripts_document
+ \setfalse\c_font_typescripts_first_pass
+ \popmacro\stoptypescript
+ \popmacro\typescriptstate
+ \popmacro\typescriptmethod
+ \popmacro\typescriptthree
+ \popmacro\typescripttwo
+ \popmacro\typescriptone
+ \popmacro\m_font_typescripts_three
+ \popmacro\m_font_typescripts_two
+ \popmacro\m_font_typescripts_one}
+
+\unexpanded\def\preloadtypescripts
+ {\ifproductionrun\settrue\c_font_typescripts_preload\fi}
+
+\prependtoks
+ \preloadtypescripts
+\to \everyjob
+
+% The next will change .. we can load a file inside a typescript but as the state is
+% 1 then, it doesn't get stored without doing that explicitly
+
+% \unexpanded\def\loadtypescriptfile[#1]%
+% {\ctxcommand{loadtypescriptfile("#1")}}
+
+\unexpanded\def\loadtypescriptfile[#1]%
+ {\pushmacro\typescriptstate
+ \let\typescriptstate\plustwo % assumes 2 at the outer level
+ \ctxcommand{loadtypescriptfile("#1")}%
+ \popmacro\typescriptstate}
+
+\unexpanded\def\quittypescriptscanning
+ {\settrue\c_font_typescripts_quit} % public
+
+\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}%
+ %\normalexpanded{\global\t_font_typescripts{\the\expandafter\t_font_typescripts\noexpand\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}}
+ \global\t_font_typescripts\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_font_typescripts
+ \csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
+
+\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}%
+ %\normalexpanded{\global\t_font_typescripts{\the\expandafter\t_font_typescripts\noexpand\csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}}
+ \global\t_font_typescripts\expandafter\expandafter\expandafter
+ {\expandafter\the\expandafter\t_font_typescripts
+ \csname\??typescriptcache\the\c_font_typescripts_n_of_preloaded\endcsname}}
+
+\def\font_typescripts_load_file#filename%
+ {\setfalse\c_font_typescripts_quit
+ \pushmacro\currenttypefile
+ \def\currenttypefile{#filename}%
+ \ifconditional\c_font_typescripts_preload
+ \font_typescript_process_typescript_file_and_store
+ \else
+ \font_typescript_process_typescript_file
+ \fi
+ \popmacro\currenttypefile
+ \ifconditional\c_font_typescripts_quit
+ \quitcommalist
+ \setfalse\c_font_typescripts_quit
+ \fi}
+
+\def\font_typescript_process_typescript_file_and_store
+ {\expandafter\let\expandafter\t_font_typescripts\csname\??typescriptfiles\currenttypefile\endcsname
+ \ifx\t_font_typescripts\relax
+ \font_typescript_process_typescript_store_indeed
+ \fi
+ \the\t_font_typescripts}
+
+\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
+ \font_typescript_process_typescript_file
+ \endgroup
+ \expandafter\let\csname\??typescriptfiles\currenttypefile\endcsname\t_font_typescripts}
+
+\def\font_typescript_process_typescript_file
+ {\ctxcommand{doprocesstypescriptfile("\currenttypefile")}}
+
+\unexpanded\def\usetypescriptonce
+ {\dotripleempty\font_typescripts_use_once}
+
+\def\font_typescripts_use_once[#one][#two][#three]%
+ {\ifcsname\??typescriptonce#one:#two:#three\endcsname
+ \writestatus\m!fonts{once (#one) (#two) (#three)}%
+ \else
+ \expandafter\let\csname\??typescriptonce#one:#two:#three\endcsname\relax
+ \font_typescripts_use[#one][#two][#three]%
+ \fi}
+
+% \definetypescriptsynonym[lbr][cmr]
+
+\unexpanded\def\definetypescriptsynonym
+ {\dodoubleempty\font_typescripts_synonym_define}
+
+\def\font_typescripts_synonym_define[#name][#synonym]%
+ {\ifsecondargument\setevalue{\??typescriptsynonyms#name}{#synonym}\fi}
+
+\def\truetypescript#name%
+ {\ifcsname\??typescriptsynonyms#name\endcsname
+ \expandafter\truetypescript\csname\??typescriptsynonyms#name\endcsname\else#name%
+ \fi}
+
+% script [serif] [default] [size]
+% script [serif] [computer-modern] [size]
+% script [serif] [computer-modern] [ec]
+% script [serif] [computer-modern] [name]
+% script [serif] [computer-modern] [special]
+
+\prependtoks
+ \settrue\c_font_typescripts_first_pass
+\to \everyjob
+
+\unexpanded\def\starttypescript
+ {\ifcase\typescriptstate
+ % 0 = skip
+ \expandafter\font_typescripts_start_gobble
+ \or
+ % 1 = process
+ \expandafter\font_typescripts_start_process
+ \or
+ % 2 = store
+ \expandafter\font_typescripts_start_document
+ \else
+ % ? = skip
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_start_gobble#definitions\stoptypescript{}
+
+\def\font_typescripts_start_document#definitions\stoptypescript
+ %{\appendtoks\starttypescript#definitions\stoptypescript\to\c_font_typescripts_document}
+ {\c_font_typescripts_document\expandafter{\the\c_font_typescripts_document\starttypescript#definitions\stoptypescript}}
+
+\def\font_typescripts_start_process % could be a faster \doifnextoptionalelse if needed
+ {\let\typescriptone \m_font_typescripts_one
+ \let\typescripttwo \m_font_typescripts_two
+ \let\typescriptthree\m_font_typescripts_three
+ \let\m_font_typescripts_match\empty
+ \doifnextoptionalelse\font_typescripts_start_process_one\font_typescripts_start_process_all}
+
+\def\font_typescripts_start_process_all % could be a \let
+ {\ifconditional\c_font_typescripts_first_pass
+ \expandafter\font_typescripts_start_process_indeed
+ \else
+ % skip this since it may do unwanted resets, like
+ % setting symbolic font names to unknown, especially
+ % in run time user type scripts
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_show_match
+ {\writestatus\m!fonts{match:\ifx\currenttypefile\relax\space *\fi \m_font_typescripts_match}}
+
+\def\font_typescripts_start_process_yes
+ {\ifdone
+ \typescriptfoundtrue
+ \iftracetypescripts\font_typescripts_show_match\fi
+ \expandafter\font_typescripts_start_process_indeed
+ \else
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\def\font_typescripts_start_process_one
+ {\font_typescripts_check\m_font_typescripts_one\typescriptone\font_typescripts_start_process_again_one}
+
+\def\font_typescripts_start_process_two
+ {\font_typescripts_check\m_font_typescripts_two\typescripttwo\font_typescripts_start_process_again_two}
+
+\def\font_typescripts_start_process_three
+ {\font_typescripts_check\m_font_typescripts_three\typescriptthree\font_typescripts_start_process_again_three}
+
+\def\font_typescripts_start_process_again_one
+ {\doifnextoptionalelse\font_typescripts_start_process_two\font_typescripts_start_process_yes}
+
+\def\font_typescripts_start_process_again_two
+ {\doifnextoptionalelse\font_typescripts_start_process_three\font_typescripts_start_process_yes}
+
+\let\font_typescripts_start_process_again_three\font_typescripts_start_process_yes
+
+\def\font_typescripts_start_process_indeed
+ {\pushmacro\fontclass}
+
+\unexpanded\def\stoptypescript
+ {\popmacro\fontclass}
+
+\def\font_typescripts_check#asked#target#followup[#value]% script use value next
+ {\donefalse
+ \edef\m_font_typescripts_check{#value}%
+ \ifx\m_font_typescripts_check\empty % no longer needed / met
+ \ifcase\typescriptmethod\or\donetrue\fi
+ \else\ifx#asked\s!all
+ \donetrue
+ \else\ifx\m_font_typescripts_check\s!all
+ \donetrue
+ \else\ifx#asked\m_font_typescripts_check % saves 10% trace so probably faster too
+ \donetrue
+ \let#target\m_font_typescripts_check
+ \else
+ \doifcommonelse\m_font_typescripts_check#asked\donetrue\donefalse
+ \ifdone
+ \let#target\commalistelement
+ \fi
+ \fi\fi\fi\fi
+ \ifdone
+ \iftracetypescripts\extendtypescriptmatch\fi
+ \expandafter#followup%
+ \else
+ \expandafter\font_typescripts_start_gobble
+ \fi}
+
+\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
+%D use stripped down 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]%
+ {\ctxlua{fonts.mappings.loadfile("#filename")}}
+
+\def\font_map_load_line[#kind][#data]%
+ {\ctxlua{fonts.mappings.loadline("#kind","#data")}}
+
+\unexpanded\def\forgetmapfiles
+ {\ctxlua{fonts.mappings.reset()}}
+
+\prependtoks
+ \loadmapfile[mkiv-base.map]% can't we preload this one?
+\to \everystarttext
+
+%D A handy shortcut:
+
+% \definetypescriptprefix[serif][Serif]
+% \definetypescriptprefix[sans] [Sans]
+% \definetypescriptprefix[mono] [Mono]
+%
+%\starttypescript [serif,sans,mono] [handling,hanging,hz] [pure,normal,hz,quality]
+% \setupfontsynonym [\typescriptprefix\typescriptone] [handling=\typescriptthree]
+% \stoptypescript
+
+\unexpanded\def\definetypescriptprefix
+ {\dodoubleargument\font_typescripts_define_prefix}
+
+\def\font_typescripts_define_prefix[#name][#prefix]%
+ {\setgvalue{\??typescriptprefix#name}{#prefix}} % made global
+
+% without testing:
+%
+% \def\typescriptprefix#name%
+% {\csname\??typescriptprefix#name\endcsname}
+%
+% with testing:
+
+\def\typescriptprefix#name%
+ {\ifcsname\??typescriptprefix#name\endcsname\csname\??typescriptprefix#name\endcsname\else#name\fi}
+
+% defining typefaces:
+%
+% \definetypeface [joke] [rm]
+% \definetypeface [joke] [rm] [settings]
+% \definetypeface [joke] [rm] [serif] [lucida]
+% \definetypeface [joke] [rm] [serif] [lucida] [size]
+% \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
+
+%D This hooks into the font switcher:
+
+\settrue\autotypescripts
+
+\unexpanded\def\trycurrentfontclass#typeface%
+ {\ifconditional\autotypescripts
+ \usetypescript[#typeface]%
+ \ifcsname\??fontclassyes#typeface\endcsname
+ \edef\fontclass{#typeface}%
+ \else
+ \iftracetypescripts\writestatus\m!fonts{auto load typescript file 1: [#typeface]}\fi
+ \usetypescriptfile[#typeface]%
+ \usetypescript[#typeface]%
+ \ifcsname\??fontclassyes#typeface\endcsname
+ \edef\fontclass{#typeface}%
+ \else
+ % todo: message
+ \letvalueempty{\??fontclassnop#typeface}%
+ \fi
+ \fi
+ \else
+ % todo: message
+ \letvalueempty{\??fontclassnop#typeface}%
+ \fi}
+
+%D Now we define:
+
+\def\font_typefaces_define
+ {\iffifthargument
+ \singleexpandafter\font_typefaces_define_a
+ \else\iffourthargument
+ \doubleexpandafter\font_typefaces_define_b
+ \else\ifthirdargument
+ \tripleexpandafter\font_typefaces_define_c
+ \else
+ \tripleexpandafter\font_typefaces_define_d
+ \fi\fi\fi}
+
+\def\font_typefaces_define_a[#name][#style][#fontshape][#fontname][#fontsize][#settings]%
+ {\iftracetypescripts\writestatus\m!fonts{define: [#name] [#style] [#fontshape] [#fontname]}\fi
+ \font_typefaces_define_indeed[#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
+ \else
+ \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
+ \fi
+ \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_c[#name][#style][#settings][#dummya][#dummyb][#dummyc]% misuse for settings
+% {\font_typefaces_define_indeed[#name][#style]%
+% \getparameters[\??tf#name#style][#settings]} % not used
+
+\def\font_typefaces_define_c[#name][#style][#dummya][#dummyb][#dummyc][#dummyd]%
+ {\font_typefaces_define_indeed[#name][#style]}
+
+\def\font_typefaces_define_d[#name][#specification][#dummya][#dummyb][#dummyc][#dummyd]% use definitions in lfg file
+ {\ctxlua{fonts.definetypeface("#name",\!!bs#specification\!!es)}}
+
+\def\font_typefaces_define_indeed[#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
+ \pushmacro\fontclass
+ \pushmacro\fontclassstyle
+ \setcurrentfontclass{#name}%
+ \savefontclassparameters{#style}\@@tsrscale\@@tsfeatures\@@tsfallbacks\@@tsgoodies\@@tsdesignsize\@@tsdirection
+ \the\everybeforedefinetypeface}
+
+\def\tsvar#key#default% undocumented and unofficial
+ {\expandafter\ifx\csname\??ts#key\endcsname\empty
+ #default%
+ \else
+ \csname\??ts#key\endcsname
+ \fi}
+
+\def\font_typefaces_defining_stop
+ {\the\everyafterdefinetypeface
+ \popmacro\fontclassstyle
+ \popmacro\fontclass}
+
+\def\dofastdefinetypeface#name#style#fontshape#fontsize#settings% called from the lua end (via case d)
+ {\font_typefaces_define_indeed[#name][#style]%
+ \font_typefaces_defining_start{#name}{#style}{#settings}%
+ \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}
+
+\def\font_typefaces_setup[#class][#settings]%
+ {\setcurrentfontclass{#class}%
+ \let\globalfontclass\fontclass
+ \iffourthargument
+ \setupbodyfont[#settings]%
+ \else\ifx\fontclass\empty
+ \setupbodyfont[\s!rm]%
+ \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ \setupbodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+ \else
+ \setupbodyfont[\s!rm]%
+ \fi \fi \fi
+ \ifmmode\mr\else\tf\fi} % needed ?
+
+\def\font_typefaces_switch[#class][#settings]%
+ {\setcurrentfontclass{#class}%
+ \let\globalfontclass\globalfontclass
+ \iffourthargument
+ \switchtobodyfont[#settings]%
+ \else\ifx\fontclass\empty
+ \switchtobodyfont[\s!rm]%
+ \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ \switchtobodyfont[\csname\??typescriptdefaultstyles\fontclass\endcsname]%
+ \else
+ \switchtobodyfont[\s!rm]%
+ \fi \fi \fi
+ \ifmmode\mr\else\tf\fi} % needed ?
+
+% obsolete
+%
+% \unexpanded\def\usetypefile[#type]% recurses on path ! % no storage
+% {\edef\currenttypefile{#type}%
+% \ctxcommand{doprocesstypescriptfile("\currenttypefile")}}
+
+%D For Taco:
+%D
+%D \starttyping
+%D \inherittypeface[palatino][rm][postscript]
+%D \inherittypeface[palatino][rm][\fontclass]
+%D \inherittypeface[palatino][rm] % == \fontclass
+%D \inherittypeface[palatino] % == [rm,ss,tt,mm]
+%D \stoptyping
+
+\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}
+ {\global\let\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}}}
+
+%D This hooks into the font mechanism with:
+
+\def\font_typescripts_inherit_check_indeed#name% called often
+ {\ifcsname\??typescriptinheritances\fontclass:#name\endcsname
+ \expandafter\let\expandafter\fontclass\csname\??typescriptinheritances\fontclass:#name\endcsname
+ \fi}
+
+\let\font_typescripts_inherit_check\gobbleoneargument
+
+% not yet:
+%
+% \def\font_helpers_check_relative_font_id
+% {\ifcsname\??typescriptrelatives\fontclass\endcsname
+% \expandafter\let\expandafter\relativefontid\csname\??typescriptrelatives\fontclass\endcsname
+% \else
+% \expandafter\normalxdef\csname\??typescriptrelatives\fontclass\endcsname{\the\lastfontid}%
+% \let\relativefontid\minusone
+% \fi}
+
+\def\v_font_string_d % default fontstyle (expands to \s!Serif in font-ini)
+ {\expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!rm \s!Serif \else
+ \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!ss \s!Sans \else
+ \expandafter\ifx\csname\??typescriptdefaultstyles\fontclass\endcsname\s!tt \s!Mono \else
+ \s!Serif \fi\fi\fi}
+
+\unexpanded\def\font_helpers_set_fontstyle_of_fontclass
+ {\ifx\fontclass\empty
+ \let\fontstyle\s!rm
+ \else\ifcsname\??typescriptdefaultstyles\fontclass\endcsname
+ \edef\fontstyle{\csname\??typescriptdefaultstyles\fontclass\endcsname}%
+ \else
+ \let\fontstyle\s!rm
+ \fi\fi}
+
+%D This might become a module:
+
+\fetchruntimecommand \typetypescript {\f!typeprefix\s!run}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/type-lua.mkiv b/Master/texmf-dist/tex/context/base/type-lua.mkiv
index a6799671edc..fac6c3867a8 100644
--- a/Master/texmf-dist/tex/context/base/type-lua.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-lua.mkiv
@@ -5,84 +5,82 @@
%D subtitle=\MKIV\ goodies,
%D author=Hans Hagen \& Wolfgang Schuster,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
-\unprotect
-
\starttypescriptcollection [luatex]
-\starttypescript [specserif] [all] [name]
- \definefontsynonym [Serif] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
- \definefontsynonym [SerifItalic] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
- \definefontsynonym [SerifSlanted] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
- \definefontsynonym [SerifBold] [spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
- \definefontsynonym [SerifBoldItalic] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
- \definefontsynonym [SerifBoldSlanted] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
- \definefontsynonym [SerifCaps] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
+\starttypescript [specserif] [\s!all] [\s!name]
+ \definefontsynonym [\s!Serif] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifItalic] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifSlanted] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBold] [spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldItalic] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifBoldSlanted] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SerifCaps] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
\stoptypescript
-\starttypescript [specsans] [all] [name]
- \definefontsynonym [Sans] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
- \definefontsynonym [SansItalic] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
- \definefontsynonym [SansSlanted] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
- \definefontsynonym [SansBold] [spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
- \definefontsynonym [SansBoldItalic] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
- \definefontsynonym [SansBoldSlanted] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
- \definefontsynonym [SansCaps] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
+\starttypescript [specsans] [\s!all] [\s!name]
+ \definefontsynonym [\s!Sans] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!SansItalic] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansSlanted] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBold] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldItalic] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansBoldSlanted] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!SansCaps] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
\stoptypescript
-\starttypescript [specmono] [all] [name]
- \definefontsynonym [Mono] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
- \definefontsynonym [MonoItalic] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
- \definefontsynonym [MonoSlanted] [spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
- \definefontsynonym [MonoBold] [spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
- \definefontsynonym [MonoBoldItalic] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
- \definefontsynonym [MonoBoldSlanted] [spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
- \definefontsynonym [MonoCaps] [spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
+\starttypescript [specmono] [\s!all] [\s!name]
+ \definefontsynonym [\s!Mono] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoItalic] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoSlanted] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoBold] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!normal] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoBoldItalic] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoBoldSlanted] [\s!spec:\cleanfontname\typescripttwo-\s!bold -\s!italic] [\s!features=\s!default]
+ \definefontsynonym [\s!MonoCaps] [\s!spec:\cleanfontname\typescripttwo-\s!normal-\s!normal] [\s!features=\s!smallcaps]
\stoptypescript
% we could combine these in the normal serif settings
-\starttypescript [specserif] [default] [size]
+\starttypescript [specserif] [\s!default] [\s!size]
\definebodyfont
- [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt] [rm]
- [\s!default]
+ [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
+ [\s!rm] [\s!default]
\stoptypescript
-\starttypescript [specsans] [default] [size]
+\starttypescript [specsans] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [ss] [\s!default]
+ [\s!ss] [\s!default]
\stoptypescript
-\starttypescript [specmono] [default] [size]
+\starttypescript [specmono] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [tt] [\s!default]
+ [\s!tt] [\s!default]
\stoptypescript
-\starttypescript [specserif] [dtp] [size]
+\starttypescript [specserif] [\s!dtp] [\s!size]
\definebodyfont
[5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
- [rm] [\s!default]
+ [\s!rm] [\s!default]
\stoptypescript
-\starttypescript [specsans] [dtp] [size]
+\starttypescript [specsans] [\s!dtp] [\s!size]
\definebodyfont
[5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
- [ss] [\s!default]
+ [\s!ss] [\s!default]
\stoptypescript
-\starttypescript [specmono] [dtp] [size]
+\starttypescript [specmono] [\s!dtp] [\s!size]
\definebodyfont
[5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
- [tt] [\s!default]
+ [\s!tt] [\s!default]
\stoptypescript
\stoptypescriptcollection
-\protect \endinput
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/type-mac.mkii b/Master/texmf-dist/tex/context/base/type-mac.mkii
index ac57726cb9c..e8abf09b99e 100644
--- a/Master/texmf-dist/tex/context/base/type-mac.mkii
+++ b/Master/texmf-dist/tex/context/base/type-mac.mkii
@@ -5,7 +5,7 @@
%D subtitle=Mac OS X Definitions,
%D author=Wolfgang Schuster,
%D date=\currentdate,
-%D copyright=Wolfgang Schuster]
+%D copyright={Wolfgang Schuster}]
%C
%C This module is part of the \CONTEXT\ macro||package. See
%C mreadme.pdf for details.
diff --git a/Master/texmf-dist/tex/context/base/type-msw.mkiv b/Master/texmf-dist/tex/context/base/type-msw.mkiv
deleted file mode 100644
index 2e741f7a04b..00000000000
--- a/Master/texmf-dist/tex/context/base/type-msw.mkiv
+++ /dev/null
@@ -1 +0,0 @@
-\input type-win.mkiv \endinput % could be a file synonym
diff --git a/Master/texmf-dist/tex/context/base/type-one.mkii b/Master/texmf-dist/tex/context/base/type-one.mkii
index 55c108c69c3..e98f6864a64 100644
--- a/Master/texmf-dist/tex/context/base/type-one.mkii
+++ b/Master/texmf-dist/tex/context/base/type-one.mkii
@@ -5,7 +5,7 @@
%D subtitle=Type One Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -1483,6 +1483,7 @@
\definefontsynonym [AntykwaPoltawskiego-Expanded-CapsBold] [\typescriptthree-antpb6-sc] [encoding=\typescriptthree]
\definefontsynonym [AntykwaPoltawskiego-Expanded-CapsBoldItalic] [\typescriptthree-antpbi6-sc] [encoding=\typescriptthree]
+ % \loadmapfile[poltawski-\typescriptthree.map]
\loadmapfile[ap-\typescriptthree.map]
\stoptypescript
@@ -2747,4 +2748,128 @@
\stoptypescriptcollection
+\starttypescriptcollection[dejavu]
+
+ \definetypescriptprefix [e:ec] [t1]
+ \definetypescriptprefix [e:qx] [qx]
+ \definetypescriptprefix [e:t2a] [t2a]
+
+ \starttypescript [serif] [dejavu] [ec,qx,t2a]
+ \definefontsynonym [DejaVuSerif] [DejaVuSerif-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSerif-Italic] [DejaVuSerif-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSerif-Bold] [DejaVuSerif-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSerif-BoldItalic] [DejaVuSerif-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+
+ \loadmapfile[dejavu-truetype.map]
+ \stoptypescript
+
+ \starttypescript [serif] [dejavu-condensed] [ec,qx,t2a]
+ \definefontsynonym [DejaVuSerifCondensed] [DejaVuSerifCondensed-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSerifCondensed-Italic] [DejaVuSerifCondensed-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSerifCondensed-Bold] [DejaVuSerifCondensed-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSerifCondensed-BoldItalic] [DejaVuSerifCondensed-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+
+ \loadmapfile[dejavu-truetype.map]
+ \stoptypescript
+
+ \starttypescript [sans] [dejavu] [ec,qx,t2a]
+ \definefontsynonym [DejaVuSans] [DejaVuSans-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSans-Italic] [DejaVuSans-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSans-Bold] [DejaVuSans-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSans-BoldItalic] [DejaVuSans-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+
+ \loadmapfile[dejavu-truetype.map]
+ \stoptypescript
+
+ \starttypescript [sans] [dejavu-condensed] [ec,qx,t2a]
+ \definefontsynonym [DejaVuSansCondensed] [DejaVuSansCondensed-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSansCondensed-Italic] [DejaVuSansCondensed-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSansCondensed-Bold] [DejaVuSansCondensed-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSansCondensed-BoldItalic] [DejaVuSansCondensed-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+
+ \loadmapfile[dejavu-truetype.map]
+ \stoptypescript
+
+ \starttypescript [mono] [dejavu,dejavu-condensed] [ec,qx,t2a]
+ \definefontsynonym [DejaVuSansMono] [DejaVuSansMono-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSansMono-Italic] [DejaVuSansMono-Italic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSansMono-Bold] [DejaVuSansMono-Bold-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+ \definefontsynonym [DejaVuSansMono-BoldItalic] [DejaVuSansMono-BoldItalic-tlf-\typescriptprefix{e:\typescriptthree}] [encoding=\typescriptthree]
+
+ \loadmapfile[dejavu-truetype.map]
+ \stoptypescript
+
+ \starttypescript [serif] [dejavu] [name]
+ \definefontsynonym [Serif] [DejaVuSerif]
+ \definefontsynonym [SerifItalic] [DejaVuSerif-Italic]
+ \definefontsynonym [SerifBold] [DejaVuSerif-Bold]
+ \definefontsynonym [SerifBoldItalic] [DejaVuSerif-BoldItalic]
+
+ \definefontsynonym [SerifSlanted] [SerifItalic]
+ \definefontsynonym [SerifBoldSlanted] [SerifBoldItalic]
+ \definefontsynonym [SerifCaps] [Serif]
+ \stoptypescript
+
+ \starttypescript [serif] [dejavu-condensed] [name]
+ \definefontsynonym [Serif] [DejaVuSerifCondensed]
+ \definefontsynonym [SerifItalic] [DejaVuSerifCondensed-Italic]
+ \definefontsynonym [SerifBold] [DejaVuSerifCondensed-Bold]
+ \definefontsynonym [SerifBoldItalic] [DejaVuSerifCondensed-BoldItalic]
+
+ \definefontsynonym [SerifSlanted] [SerifItalic]
+ \definefontsynonym [SerifBoldSlanted] [SerifBoldItalic]
+ \definefontsynonym [SerifCaps] [Serif]
+ \stoptypescript
+
+ \starttypescript [sans] [dejavu] [name]
+ \definefontsynonym [Sans] [DejaVuSans]
+ \definefontsynonym [SansItalic] [DejaVuSans-Italic]
+ \definefontsynonym [SansBold] [DejaVuSans-Bold]
+ \definefontsynonym [SansBoldItalic] [DejaVuSans-BoldItalic]
+
+ \definefontsynonym [SansSlanted] [SansItalic]
+ \definefontsynonym [SansBoldSlanted] [SansBoldItalic]
+ \definefontsynonym [SansCaps] [Sans]
+ \stoptypescript
+
+ \starttypescript [sans] [dejavu-condensed] [name]
+ \definefontsynonym [Sans] [DejaVuSansCondensed]
+ \definefontsynonym [SansItalic] [DejaVuSansCondensed-Italic]
+ \definefontsynonym [SansBold] [DejaVuSansCondensed-Bold]
+ \definefontsynonym [SansBoldItalic] [DejaVuSansCondensed-BoldItalic]
+
+ \definefontsynonym [SansSlanted] [SansItalic]
+ \definefontsynonym [SansBoldSlanted] [SansBoldItalic]
+ \definefontsynonym [SansCaps] [Sans]
+ \stoptypescript
+
+ \starttypescript [mono] [dejavu,dejavu-condensed] [name]
+ \definefontsynonym [Mono] [DejaVuSansMono]
+ \definefontsynonym [MonoItalic] [DejaVuSansMono-Italic]
+ \definefontsynonym [MonoBold] [DejaVuSansMono-Bold]
+ \definefontsynonym [MonoBoldItalic] [DejaVuSansMono-BoldItalic]
+
+ \definefontsynonym [MonoSlanted] [MonoItalic]
+ \definefontsynonym [MonoBoldSlanted] [MonoBoldItalic]
+ \definefontsynonym [MonoCaps] [Mono]
+ \stoptypescript
+
+ \starttypescript [dejavu] [ec,qx,t2a]
+ \definetypeface [dejavu] [rm] [serif] [dejavu] [default] [encoding=\typescripttwo]
+ \definetypeface [dejavu] [ss] [sans] [dejavu] [default] [encoding=\typescripttwo]
+ \definetypeface [dejavu] [tt] [mono] [dejavu] [default] [encoding=\typescripttwo]
+ \definetypeface [dejavu] [mm] [math] [xits] [default] [rscale=auto]
+ \loadmapfile [dejavu-truetype.map]
+ \stoptypescript
+
+ \starttypescript [dejavu-condensed] [ec,qx,t2a]
+ \definetypeface [dejavu-condensed] [rm] [serif] [dejavu-condensed] [default] [encoding=\typescripttwo]
+ \definetypeface [dejavu-condensed] [ss] [sans] [dejavu-condensed] [default] [encoding=\typescripttwo]
+ \definetypeface [dejavu-condensed] [tt] [mono] [dejavu-condensed] [default] [encoding=\typescripttwo]
+ \definetypeface [dejavu-condensed] [mm] [math] [xits] [default] [rscale=auto]
+ \loadmapfile [dejavu-truetype.map]
+ \stoptypescript
+
+\stoptypescriptcollection
+
\endinput
diff --git a/Master/texmf-dist/tex/context/base/type-one.mkiv b/Master/texmf-dist/tex/context/base/type-one.mkiv
index fa5d9b08a70..12b9e14add2 100644
--- a/Master/texmf-dist/tex/context/base/type-one.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-one.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Type One Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -15,99 +15,4 @@
% one fonts but there are not that many useful left that only
% come in type one.
-\starttypescriptcollection[allkindofafm]
-
- % \starttypescript [serif] [bookman] [name]
- % \definefontsynonym [Serif] [Bookman-Light]
- % \definefontsynonym [SerifItalic] [Bookman-LightItalic]
- % \definefontsynonym [SerifBold] [Bookman-DemiBold]
- % \definefontsynonym [SerifBoldItalic] [Bookman-DemiBoldItalic]
- % \definefontsynonym [SerifSlanted] [Bookman-LightSlanted]
- % \definefontsynonym [SerifBoldSlanted] [Bookman-DemiBoldSlanted]
- % \definefontsynonym [SerifCaps] [Bookman-Light-Caps]
- % \stoptypescript
-
- % \starttypescript [calligraphy] [chancery] [name]
- % \definefontsynonym [Calligraphy] [Chancery]
- % \stoptypescript
-
- % \starttypescript [serif] [schoolbook] [name]
- % \definefontsynonym [Serif] [Schoolbook-Roman]
- % \definefontsynonym [SerifItalic] [Schoolbook-Italic]
- % \definefontsynonym [SerifBold] [Schoolbook-Bold]
- % \definefontsynonym [SerifBoldItalic] [Schoolbook-BoldItalic]
- % \definefontsynonym [SerifSlanted] [Schoolbook-RomanSlanted]
- % \definefontsynonym [SerifBoldSlanted] [Schoolbook-BoldSlanted]
- % \definefontsynonym [SerifCaps] [Schoolbook-Roman-Caps]
- % \stoptypescript
-
- % \starttypescript [serif] [utopia] [name]
- % \definefontsynonym [Serif] [Utopia-Regular]
- % \definefontsynonym [SerifItalic] [Utopia-Italic]
- % \definefontsynonym [SerifBold] [Utopia-Bold]
- % \definefontsynonym [SerifBoldItalic] [Utopia-BoldItalic]
- % \definefontsynonym [SerifSlanted] [Utopia-Slanted]
- % \definefontsynonym [SerifBoldSlanted] [Utopia-BoldSlanted]
- % \definefontsynonym [SerifCaps] [Utopia-Regular-Caps]
- % \stoptypescript
-
- % \starttypescript [serif] [charter] [name]
- % \definefontsynonym [Serif] [Charter-Roman]
- % \definefontsynonym [SerifItalic] [Charter-Italic]
- % \definefontsynonym [SerifBold] [Charter-Bold]
- % \definefontsynonym [SerifBoldItalic] [Charter-BoldItalic]
- % \definefontsynonym [SerifSlanted] [Charter-Slanted]
- % \definefontsynonym [SerifBoldSlanted] [Charter-BoldSlanted]
- % \definefontsynonym [SerifCaps] [Charter-Roman-Caps]
- % \stoptypescript
-
- % \starttypescript [serif] [times] [name]
- % \definefontsynonym [Serif] [Times-Roman]
- % \definefontsynonym [SerifBold] [Times-Bold]
- % \definefontsynonym [SerifItalic] [Times-Italic]
- % \definefontsynonym [SerifSlanted] [Times-Italic]
- % \definefontsynonym [SerifBoldItalic] [Times-BoldItalic]
- % \definefontsynonym [SerifBoldSlanted] [Times-BoldItalic]
- % \definefontsynonym [SerifCaps] [Times-Caps]
- % \stoptypescript
-
- % \starttypescript [sans] [helvetica] [name]
- % \definefontsynonym [Sans] [Helvetica]
- % \definefontsynonym [SansBold] [Helvetica-Bold]
- % \definefontsynonym [SansItalic] [Helvetica-Oblique]
- % \definefontsynonym [SansSlanted] [Helvetica-Oblique]
- % \definefontsynonym [SansBoldItalic] [Helvetica-BoldOblique]
- % \definefontsynonym [SansBoldSlanted] [Helvetica-BoldOblique]
- % \definefontsynonym [SansCaps] [Helvetica-Caps]
- % \stoptypescript
-
- % \starttypescript [math] [helvetica] [name]
- % \definefontsynonym [MathRoman] [Helvetica-MathRoman]
- % \definefontsynonym [MathExtension] [Helvetica-MathExtendedSymbols]
- % \definefontsynonym [MathItalic] [Helvetica-MathItalics]
- % \definefontsynonym [MathSymbol] [Helvetica-MathSymbols]
- % \stoptypescript
-
- % \starttypescript [mono] [courier] [name]
- % \definefontsynonym [Mono] [Courier]
- % \definefontsynonym [MonoBold] [Courier-Bold]
- % \definefontsynonym [MonoItalic] [Courier-Oblique]
- % \definefontsynonym [MonoSlanted] [Courier-Oblique]
- % \definefontsynonym [MonoBoldItalic] [Courier-BoldOblique]
- % \definefontsynonym [MonoBoldSlanted] [Courier-BoldOblique]
- % \definefontsynonym [MonoCaps] [Courier]
- % \stoptypescript
-
- % \starttypescript [serif] [palatino] [name]
- % \definefontsynonym [Serif] [Palatino]
- % \definefontsynonym [SerifBold] [Palatino-Bold]
- % \definefontsynonym [SerifItalic] [Palatino-Italic]
- % \definefontsynonym [SerifSlanted] [Palatino-Slanted]
- % \definefontsynonym [SerifBoldItalic] [Palatino-BoldItalic]
- % \definefontsynonym [SerifBoldSlanted] [Palatino-BoldSlanted]
- % \definefontsynonym [SerifCaps] [Palatino-Caps]
- % \stoptypescript
-
-\stoptypescriptcollection
-
\endinput
diff --git a/Master/texmf-dist/tex/context/base/type-otf.mkii b/Master/texmf-dist/tex/context/base/type-otf.mkii
index 9c49853efa8..d15994f6aed 100644
--- a/Master/texmf-dist/tex/context/base/type-otf.mkii
+++ b/Master/texmf-dist/tex/context/base/type-otf.mkii
@@ -5,7 +5,7 @@
%D subtitle=Opentype Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-otf.mkiv b/Master/texmf-dist/tex/context/base/type-otf.mkiv
index 95075367621..1f1564ef571 100644
--- a/Master/texmf-dist/tex/context/base/type-otf.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-otf.mkiv
@@ -5,1945 +5,23 @@
%D subtitle=Opentype Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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 Actually, \LUATEX\ does not need all these definitions since it can
-%D consult its database. However, here we use the names that we used
-%D in good old \TEX, and these may differ a bit. Here we also see
-%D some oldstyle definitions which normally are done with features.
+%D When a fontname equals the filename, then use
%D
-%D The ComputerModern* names will become obsolete (all LM now).
-
-% \starttypescriptcollection[myfonts]
-%
-% \starttypescript [serif] [myserif] [name]
-% \setups[font:fallback:serif]
-% \definefontsynonym [Serif] [\s!file:myserif.ttf] [features=default]
-% \definefontsynonym [SerifBold] [\s!file:myserifbold.ttf] [features=default]
-% \definefontsynonym [SerifItalic] [\s!file:myserifitalic.ttf] [features=default]
-% \definefontsynonym [SerifBoldItalic] [\s!file:myserifbolditalic.ttf] [features=default]
-% \stoptypescript
-%
-% \starttypescript[myfont]
-% \definetypeface [myfont] [rm] [serif] [myserif] [default]
-% \stoptypescript
-%
-% \stoptypescriptcollection
-%
-% \setupbodyfont[myfont]
-
-\starttypescriptcollection[fallback]
-
-\starttypescript [fallback]
- \definetypeface [] [rm] [serif] [modern] [computer-modern]
- \definetypeface [] [ss] [sans] [modern] [computer-modern]
- \definetypeface [] [tt] [mono] [modern] [computer-modern]
- \definetypeface [] [mm] [math] [modern] [computer-modern]
- \quittypescriptscanning
-\stoptypescript
-
-% faster
-%
-% \starttypescript [fallback]
-% \definetypeface [] [rm] [serif] [modern] [default]
-% \definetypeface [] [ss] [sans] [modern] [default]
-% \definetypeface [] [tt] [mono] [modern] [default]
-% \definetypeface [] [mm] [math] [modern] [default]
-% \quittypescriptscanning
-% \stoptypescript
-
-\stoptypescriptcollection
-
-% if a fontname equals the filename, then use
-%
-% \setupfontsynonym [LMRoman10-DemiOblique] [\s!features=\s!default] % file is lowercase, so fails
-% \definefontsynonym [LMRoman10-DemiOblique] [\s!name:LMRoman10-DemiOblique] [\s!features=\s!default]
-% \definefontsynonym [LMRoman10-DemiOblique] [lmroman10-demioblique] [\s!features=\s!default]
-
-% \starttypescript [math] [modern,computer-modern,latin-modern]
-% \definefontsynonym[MathSymbol][MathSymbol-Regular@symbol-math]
-% \loadfontgoodies[symbol-math]
-% \stoptypescript
-
-\starttypescriptcollection[latinmodern]
-
- %D The names have changed (again) ... but I will not change the symbolic names
- %D any more. Filename changes will be catched in luatex (fallbacks) but not in
- %D other tex's.
-
- \starttypescript [serif] [modern,latin-modern,computer-modern,default]
- \definefontsynonym [LMRoman5-Regular] [\s!file:lmroman5-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman6-Regular] [\s!file:lmroman6-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman7-Regular] [\s!file:lmroman7-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman8-Regular] [\s!file:lmroman8-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman9-Regular] [\s!file:lmroman9-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-Regular] [\s!file:lmroman10-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman12-Regular] [\s!file:lmroman12-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman17-Regular] [\s!file:lmroman17-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman5-Bold] [\s!file:lmroman5-bold] [\s!features=\s!default]
- \definefontsynonym [LMRoman6-Bold] [\s!file:lmroman6-bold] [\s!features=\s!default]
- \definefontsynonym [LMRoman7-Bold] [\s!file:lmroman7-bold] [\s!features=\s!default]
- \definefontsynonym [LMRoman8-Bold] [\s!file:lmroman8-bold] [\s!features=\s!default]
- \definefontsynonym [LMRoman9-Bold] [\s!file:lmroman9-bold] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-Bold] [\s!file:lmroman10-bold] [\s!features=\s!default]
- \definefontsynonym [LMRoman12-Bold] [\s!file:lmroman12-bold] [\s!features=\s!default]
- \definefontsynonym [LMRoman7-Italic] [\s!file:lmroman7-italic] [\s!features=\s!default]
- \definefontsynonym [LMRoman8-Italic] [\s!file:lmroman8-italic] [\s!features=\s!default]
- \definefontsynonym [LMRoman9-Italic] [\s!file:lmroman9-italic] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-Italic] [\s!file:lmroman10-italic] [\s!features=\s!default]
- \definefontsynonym [LMRoman12-Italic] [\s!file:lmroman12-italic] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-BoldItalic] [\s!file:lmroman10-bolditalic] [\s!features=\s!default]
- \definefontsynonym [LMRoman8-Oblique] [\s!file:lmromanslant8-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman9-Oblique] [\s!file:lmromanslant9-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-Oblique] [\s!file:lmromanslant10-regular][\s!features=\s!default]
- \definefontsynonym [LMRoman12-Oblique] [\s!file:lmromanslant12-regular][\s!features=\s!default]
- \definefontsynonym [LMRoman17-Oblique] [\s!file:lmromanslant17-regular][\s!features=\s!default]
- \definefontsynonym [LMRoman10-BoldOblique] [\s!file:lmromanslant10-bold] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-Demi] [\s!file:lmromandemi10-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-DemiOblique] [\s!file:lmromandemi10-oblique] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-CapsRegular] [\s!file:lmromancaps10-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-CapsOblique] [\s!file:lmromancaps10-oblique] [\s!features=\s!default]
-
- \definefontsynonym [LMRoman10-Dunhill] [\s!file:lmromandunh10-regular] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-DunhillOblique] [\s!file:lmromandunh10-oblique] [\s!features=\s!default]
- \definefontsynonym [LMRoman10-Unslanted] [\s!file:lmromanunsl10-regular] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [sans] [modern,latin-modern,computer-modern,default]
- \definefontsynonym [LMSans8-Regular] [\s!file:lmsans8-regular] [\s!features=\s!default]
- \definefontsynonym [LMSans9-Regular] [\s!file:lmsans9-regular] [\s!features=\s!default]
- \definefontsynonym [LMSans10-Regular] [\s!file:lmsans10-regular] [\s!features=\s!default]
- \definefontsynonym [LMSans12-Regular] [\s!file:lmsans12-regular] [\s!features=\s!default]
- \definefontsynonym [LMSans17-Regular] [\s!file:lmsans17-regular] [\s!features=\s!default]
- \definefontsynonym [LMSans10-Bold] [\s!file:lmsans10-bold] [\s!features=\s!default]
- \definefontsynonym [LMSans8-Oblique] [\s!file:lmsans8-oblique] [\s!features=\s!default]
- \definefontsynonym [LMSans9-Oblique] [\s!file:lmsans9-oblique] [\s!features=\s!default]
- \definefontsynonym [LMSans10-Oblique] [\s!file:lmsans10-oblique] [\s!features=\s!default]
- \definefontsynonym [LMSans12-Oblique] [\s!file:lmsans12-oblique] [\s!features=\s!default]
- \definefontsynonym [LMSans17-Oblique] [\s!file:lmsans17-oblique] [\s!features=\s!default]
- \definefontsynonym [LMSans10-BoldOblique] [\s!file:lmsans10-boldoblique] [\s!features=\s!default]
-
- \definefontsynonym [LMSans10-DemiCondensed] [\s!file:lmsansdemicond10-regular] [\s!features=\s!default]
- \definefontsynonym [LMSans10-DemiCondensedOblique] [\s!file:lmsansdemicond10-oblique] [\s!features=\s!default]
-
- \definefontsynonym [LMSansQuotation8-Regular] [\s!file:lmsansquot8-regular] [\s!features=\s!default]
- \definefontsynonym [LMSansQuotation8-Bold] [\s!file:lmsansquot8-bold] [\s!features=\s!default]
- \definefontsynonym [LMSansQuotation8-Oblique] [\s!file:lmsansquot8-oblique] [\s!features=\s!default]
- \definefontsynonym [LMSansQuotation8-BoldOblique] [\s!file:lmsansquot8-boldoblique] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [mono] [modern,modern-variable,modern-condensed,latin-modern,latin-modern-variable,latin-modern-condensed,computer-modern,default]
- \definefontsynonym [LMTypewriter8-Regular] [\s!file:lmmono8-regular] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter9-Regular] [\s!file:lmmono9-regular] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-Regular] [\s!file:lmmono10-regular] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter12-Regular] [\s!file:lmmono12-regular] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-Italic] [\s!file:lmmono10-italic] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-Oblique] [\s!file:lmmonoslant10-regular] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-CapsRegular] [\s!file:lmmonocaps10-regular] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-CapsOblique] [\s!file:lmmonocaps10-oblique] [\s!features=\s!none]
-
- \definefontsynonym [LMTypewriter10-Light] [\s!file:lmmonolt10-regular] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-LightOblique] [\s!file:lmmonolt10-oblique] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-LightCondensed] [\s!file:lmmonoltcond10-regular] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-LightCondensedOblique] [\s!file:lmmonoltcond10-oblique] [\s!features=\s!none]
-
- \definefontsynonym [LMTypewriter10-Dark] [\s!file:lmmonolt10-bold] [\s!features=\s!none]
- \definefontsynonym [LMTypewriter10-DarkOblique] [\s!file:lmmonolt10-boldoblique] [\s!features=\s!none]
-
- \definefontsynonym [LMTypewriterVarWd10-Regular] [\s!file:lmmonoproplt10-regular] [\s!features=\s!default]
- \definefontsynonym [LMTypewriterVarWd10-Oblique] [\s!file:lmmonoproplt10-oblique] [\s!features=\s!default]
- \definefontsynonym [LMTypewriterVarWd10-Light] [\s!file:lmmonoprop10-regular] [\s!features=\s!default]
- \definefontsynonym [LMTypewriterVarWd10-LightOblique] [\s!file:lmmonoprop10-oblique] [\s!features=\s!default]
- \definefontsynonym [LMTypewriterVarWd10-Dark] [\s!file:lmmonoproplt10-bold] [\s!features=\s!default]
- \definefontsynonym [LMTypewriterVarWd10-DarkOblique] [\s!file:lmmonoproplt10-boldoblique] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [math] [modern,latin-modern,computer-modern,default]
- \definefontsynonym[LMMathRoman5-Regular] [LMMath5-Regular@lmroman5-math]
- \definefontsynonym[LMMathRoman6-Regular] [LMMath6-Regular@lmroman6-math]
- \definefontsynonym[LMMathRoman7-Regular] [LMMath7-Regular@lmroman7-math]
- \definefontsynonym[LMMathRoman8-Regular] [LMMath8-Regular@lmroman8-math]
- \definefontsynonym[LMMathRoman9-Regular] [LMMath9-Regular@lmroman9-math]
- \definefontsynonym[LMMathRoman10-Regular][LMMath10-Regular@lmroman10-math]
- \definefontsynonym[LMMathRoman12-Regular][LMMath12-Regular@lmroman12-math]
- \definefontsynonym[LMMathRoman17-Regular][LMMath17-Regular@lmroman17-math]
-
- \definefontsynonym[LMMathRoman5-Bold] [LMMath10-Bold@lmroman10-boldmath]
- \definefontsynonym[LMMathRoman6-Bold] [LMMath10-Bold@lmroman10-boldmath]
- \definefontsynonym[LMMathRoman7-Bold] [LMMath10-Bold@lmroman10-boldmath]
- \definefontsynonym[LMMathRoman8-Bold] [LMMath10-Bold@lmroman10-boldmath]
- \definefontsynonym[LMMathRoman9-Bold] [LMMath10-Bold@lmroman10-boldmath]
- \definefontsynonym[LMMathRoman10-Bold] [LMMath10-Bold@lmroman10-boldmath]
- \definefontsynonym[LMMathRoman12-Bold] [LMMath10-Bold@lmroman10-boldmath]
- \definefontsynonym[LMMathRoman17-Bold] [LMMath10-Bold@lmroman10-boldmath]
-
- % are these needed?
- %
- % \definefontsynonym[MathRoman][LMMath10-Regular@lmroman10-math]
- % \definefontsynonym[MathBold] [LMMath10-Bold@lmroman10-boldmath]
-
- \loadfontgoodies[lm-math]
- \stoptypescript
-
- \starttypescript [serif] [modern,latin-modern,computer-modern,default] [name]
- \definefontsynonym [Serif] [LMRoman-Regular]
- \definefontsynonym [SerifBold] [LMRoman-Bold]
- \definefontsynonym [SerifItalic] [LMRoman-Italic]
- \definefontsynonym [SerifSlanted] [LMRoman-Oblique]
- \definefontsynonym [SerifBoldItalic] [LMRoman-BoldItalic]
- \definefontsynonym [SerifBoldSlanted] [LMRoman-BoldOblique]
- \definefontsynonym [SerifCaps] [LMRoman-CapsRegular]
- \definefontsynonym [SerifCapsSlanted] [LMRoman-CapsOblique]
- \stoptypescript
-
- \starttypescript [sans] [modern,latin-modern,computer-modern,default] [name]
- \definefontsynonym [Sans] [LMSans-Regular]
- \definefontsynonym [SansBold] [LMSans-Bold]
- \definefontsynonym [SansItalic] [LMSans-Oblique]
- \definefontsynonym [SansSlanted] [LMSans-Oblique]
- \definefontsynonym [SansBoldItalic] [LMSans-BoldOblique]
- \definefontsynonym [SansBoldSlanted] [LMSans-BoldOblique]
- \definefontsynonym [SansCaps] [LMSans-Regular]
- \definefontsynonym [SansCapsSlanted] [LMSans-Oblique]
- \stoptypescript
-
- \starttypescript [mono] [modern,latin-modern,computer-modern,default] [name]
- \definefontsynonym [Mono] [LMTypewriter-Regular]
- \definefontsynonym [MonoBold] [LMTypewriter-Dark]
- \definefontsynonym [MonoItalic] [LMTypewriter-Italic]
- \definefontsynonym [MonoSlanted] [LMTypewriter-Oblique]
- \definefontsynonym [MonoBoldItalic] [LMTypewriter-DarkOblique]
- \definefontsynonym [MonoBoldSlanted] [LMTypewriter-DarkOblique]
- \definefontsynonym [MonoCaps] [LMTypewriter-CapsRegular]
- \definefontsynonym [MonoCapsSlanted] [LMTypewriter-CapsOblique]
- \definefontsynonym [MonoVariable] [LMTypewriterVarWd-Regular]
- \stoptypescript
-
- \starttypescript [math] [modern,latin-modern,computer-modern,default] [name]
- \definefontsynonym [MathRoman] [LMMathRoman-Regular]
- \definefontsynonym [MathRomanBold] [LMMathRoman-Bold]
- %definefontsynonym [MathExtension] [LMMathExtension-Regular]
- %definefontsynonym [MathItalic] [LMMathItalic-Italic]
- %definefontsynonym [MathSymbol] [LMMathSymbols-Italic]
- \stoptypescript
-
- \starttypescript [serif] [modern-variable,latin-modern-variable,default] [name]
- \definefontsynonym [Serif] [LMTypewriterVarWd-Regular]
- \definefontsynonym [SerifBold] [LMTypewriterVarWd-Oblique]
- \definefontsynonym [SerifItalic] [LMTypewriterVarWd-Oblique]
- \definefontsynonym [SerifSlanted] [LMTypewriterVarWd-Dark]
- \definefontsynonym [SerifBoldItalic] [LMTypewriterVarWd-DarkOblique]
- \definefontsynonym [SerifBoldSlanted] [LMTypewriterVarWd-DarkOblique]
- \definefontsynonym [SerifCaps] [LMTypewriterVarWd-Regular]
- \definefontsynonym [SerifCapsSlanted] [LMTypewriterVarWd-Oblique]
- \stoptypescript
-
- \starttypescript [mono] [modern-condensed,latin-modern-condensed,modern-light-condensed,latin-modern-light-condensed,default] [name]
- \definefontsynonym [Mono] [LMTypewriter-LightCondensed]
- \definefontsynonym [MonoBold] [LMTypewriter-LightCondensed]
- \definefontsynonym [MonoItalic] [LMTypewriter-LightCondensedOblique]
- \definefontsynonym [MonoSlanted] [LMTypewriter-LightCondensedOblique]
- \definefontsynonym [MonoBoldItalic] [LMTypewriter-LightCondensed]
- \definefontsynonym [MonoBoldSlanted] [LMTypewriter-LightCondensed]
- \definefontsynonym [MonoCaps] [LMTypewriter-LightCondensed]
- \definefontsynonym [MonoCapsSlanted] [LMTypewriter-LightCondensed]
- \stoptypescript
-
- \starttypescript [mono] [modern-light,latin-modern-light,default] [name]
- \definefontsynonym [Mono] [LMTypewriter-Light]
- \definefontsynonym [MonoBold] [LMTypewriter-Light]
- \definefontsynonym [MonoItalic] [LMTypewriter-LightOblique]
- \definefontsynonym [MonoSlanted] [LMTypewriter-LightOblique]
- \definefontsynonym [MonoBoldItalic] [LMTypewriter-Light]
- \definefontsynonym [MonoBoldSlanted] [LMTypewriter-Light]
- \definefontsynonym [MonoCaps] [LMTypewriter-Light]
- \definefontsynonym [MonoCapsSlanted] [LMTypewriter-Light]
- \stoptypescript
-
- % Later we will map the real fonts, here we just map synonyms.
-
- \starttypescript [serif] [modern,latin-modern,computer-modern,default]
- \definefontsynonym [LMRoman-DemiOblique] [LMRoman10-DemiOblique]
- \definefontsynonym [LMRoman-Bold] [LMRoman10-Bold]
- \definefontsynonym [LMRoman-BoldItalic] [LMRoman10-BoldItalic]
- \definefontsynonym [LMRoman-BoldOblique] [LMRoman10-BoldOblique]
- \definefontsynonym [LMRoman-CapsRegular] [LMRoman10-CapsRegular]
- \definefontsynonym [LMRoman-CapsOblique] [LMRoman10-CapsOblique]
- \definefontsynonym [LMRoman-Regular] [LMRoman10-Regular]
- \definefontsynonym [LMRoman-Italic] [LMRoman10-Italic]
- \definefontsynonym [LMRoman-Oblique] [LMRoman10-Oblique]
- \stoptypescript
-
- \starttypescript [sans] [modern,latin-modern,computer-modern,default]
- \definefontsynonym [LMSans-Regular] [LMSans10-Regular]
- \definefontsynonym [LMSans-BoldOblique] [LMSans10-BoldOblique]
- \definefontsynonym [LMSans-Bold] [LMSans10-Bold]
- \definefontsynonym [LMSans-DemiCondensed] [LMSans10-DemiCondensed]
- \definefontsynonym [LMSans-DemiCondensedOblique] [LMSans10-DemiCondensedOblique]
- \definefontsynonym [LMSans-Oblique] [LMSans10-Oblique]
- \stoptypescript
-
- \starttypescript [mono] [modern,latin-modern,modern-variable,latin-modern-variable,modern-condensed,latin-modern-condensed,default]
- \definefontsynonym [LMTypewriter-CapsRegular] [LMTypewriter10-CapsRegular]
- \definefontsynonym [LMTypewriter-CapsOblique] [LMTypewriter10-CapsOblique]
- \definefontsynonym [LMTypewriter-Light] [LMTypewriter10-Light]
- \definefontsynonym [LMTypewriter-LightOblique] [LMTypewriter10-LightOblique]
- \definefontsynonym [LMTypewriter-LightCondensed] [LMTypewriter10-LightCondensed]
- \definefontsynonym [LMTypewriter-LightCondensedOblique] [LMTypewriter10-LightCondensedOblique]
- \definefontsynonym [LMTypewriter-Dark] [LMTypewriter10-Dark]
- \definefontsynonym [LMTypewriter-DarkOblique] [LMTypewriter10-DarkOblique]
- \definefontsynonym [LMTypewriter-Regular] [LMTypewriter10-Regular]
- \definefontsynonym [LMTypewriter-Italic] [LMTypewriter10-Italic]
- \definefontsynonym [LMTypewriter-Oblique] [LMTypewriter10-Oblique]
- \definefontsynonym [LMTypewriterVarWd-Regular] [LMTypewriterVarWd10-Regular]
- \definefontsynonym [LMTypewriterVarWd-Oblique] [LMTypewriterVarWd10-Oblique]
- \definefontsynonym [LMTypewriterVarWd-Light] [LMTypewriterVarWd10-Light]
- \definefontsynonym [LMTypewriterVarWd-LightOblique] [LMTypewriterVarWd10-LightOblique]
- \definefontsynonym [LMTypewriterVarWd-Dark] [LMTypewriterVarWd10-Dark]
- \definefontsynonym [LMTypewriterVarWd-DarkOblique] [LMTypewriterVarWd10-DarkOblique]
- \stoptypescript
-
- \starttypescript [serif] [modern,latin-modern,computer-modern,default]
- \definefontsynonym [ComputerModern] [LMRoman-Regular]
- \definefontsynonym [ComputerModern-Italic] [LMRoman-Italic]
- \definefontsynonym [ComputerModern-Slanted] [LMRoman-Oblique]
- \definefontsynonym [ComputerModern-Bold] [LMRoman-Bold]
- \definefontsynonym [ComputerModern-BoldItalic] [LMRoman-BoldItalic]
- \definefontsynonym [ComputerModern-BoldSlanted] [LMRoman-BoldOblique]
- \definefontsynonym [ComputerModern-Caps] [LMRoman-CapsRegular]
- \definefontsynonym [ComputerModern-CapsSlanted] [LMRoman-CapsOblique]
- \stoptypescript
-
- \starttypescript [sans] [modern,latin-modern,computer-modern,default]
- \definefontsynonym [ComputerModernSans] [LMSans-Regular]
- \definefontsynonym [ComputerModernSans-Italic] [LMSans-Oblique]
- \definefontsynonym [ComputerModernSans-Slanted] [LMSans-Oblique]
- \definefontsynonym [ComputerModernSans-Bold] [LMSans-Bold]
- \definefontsynonym [ComputerModernSans-BoldItalic] [LMSans-BoldOblique]
- \definefontsynonym [ComputerModernSans-BoldSlanted] [LMSans-BoldOblique]
- \definefontsynonym [ComputerModernSans-Caps] [LMSans-Regular]% [LMSans-CapsRegular]
- \definefontsynonym [ComputerModernSans-CapsSlanted] [LMSans-Oblique]% [LMSans-CapsOblique]
- \stoptypescript
-
- \starttypescript [mono] [modern,latin-modern,computer-modern,default]
- \definefontsynonym [ComputerModernMono] [LMTypewriter-Regular]
- \definefontsynonym [ComputerModernMono-Italic] [LMTypewriter-Italic]
- \definefontsynonym [ComputerModernMono-Slanted] [LMTypewriter-Oblique]
- \definefontsynonym [ComputerModernMono-Bold] [LMTypewriter-Dark]
- \definefontsynonym [ComputerModernMono-BoldItalic] [LMTypewriter-DarkOblique]
- \definefontsynonym [ComputerModernMono-BoldSlanted] [LMTypewriter-DarkOblique]
- \definefontsynonym [ComputerModernMono-Caps] [LMTypewriter-CapsRegular]
- \definefontsynonym [ComputerModernMono-CapsSlanted] [LMTypewriter-CapsOblique]
- \definefontsynonym [ComputerModernMono-Variable] [LMTypewriterVarWd-Regular]
- \stoptypescript
-
- \starttypescript [mono] [modern-light,latin-modern-light,default]
- \definefontsynonym [ComputerModernMono] [LMTypewriter-Light]
- \definefontsynonym [ComputerModernMono-Italic] [LMTypewriter-LightOblique]
- \definefontsynonym [ComputerModernMono-Slanted] [LMTypewriter-LightOblique]
- \definefontsynonym [ComputerModernMono-Bold] [LMTypewriter-Dark]
- \definefontsynonym [ComputerModernMono-BoldItalic] [LMTypewriter-DarkOblique]
- \definefontsynonym [ComputerModernMono-BoldSlanted] [LMTypewriter-DarkOblique]
- \definefontsynonym [ComputerModernMono-Caps] [LMTypewriter-Light]
- \definefontsynonym [ComputerModernMono-CapsSlanted] [LMTypewriter-LightOblique]
- \definefontsynonym [ComputerModernMono-Variable] [LMTypewriterVarWd-Light]
- \stoptypescript
-
- \starttypescript [serif] [modern-variable,latin-modern-variable,default]
- \definefontsynonym [ComputerModernVariable] [LMTypewriterVarWd-Regular]
- \definefontsynonym [ComputerModernVariable-Italic] [LMTypewriterVarWd-Oblique]
- \definefontsynonym [ComputerModernVariable-Slanted] [LMTypewriterVarWd-Oblique]
- \definefontsynonym [ComputerModernVariable-Bold] [LMTypewriterVarWd-Dark]
- \definefontsynonym [ComputerModernVariable-BoldItalic] [LMTypewriterVarWd-DarkOblique]
- \definefontsynonym [ComputerModernVariable-BoldSlanted] [LMTypewriterVarWd-DarkOblique]
- \definefontsynonym [ComputerModernVariable-Caps] [LMTypewriterVarWd-Regular]
- \definefontsynonym [ComputerModernVariable-CapsSlanted] [LMTypewriterVarWd-Oblique]
- \stoptypescript
-
- \starttypescript [serif] [modern-variable-light,latin-modern-variable-light,default]
- \definefontsynonym [ComputerModernVariable] [LMTypewriterVarWd-Light]
- \definefontsynonym [ComputerModernVariable-Italic] [LMTypewriterVarWd-LightOblique]
- \definefontsynonym [ComputerModernVariable-Slanted] [LMTypewriterVarWd-LightOblique]
- \definefontsynonym [ComputerModernVariable-Bold] [LMTypewriterVarWd-Dark]
- \definefontsynonym [ComputerModernVariable-BoldItalic] [LMTypewriterVarWd-DarkOblique]
- \definefontsynonym [ComputerModernVariable-BoldSlanted] [LMTypewriterVarWd-DarkOblique]
- \definefontsynonym [ComputerModernVariable-Caps] [LMTypewriterVarWd-Light]
- \definefontsynonym [ComputerModernVariable-CapsSlanted] [LMTypewriterVarWd-LightOblique]
- \stoptypescript
-
- \starttypescript [math] [modern,latin-modern,default]
- \definefontsynonym [LMMathRoman-Regular] [LMMathRoman10-Regular]
- \definefontsynonym [LMMathRoman-Bold] [LMMathRoman10-Bold]
- \stoptypescript
-
- \starttypescript [math] [modern,latin-modern,default]
- % \loadfontgoodies[lm-math]
- \definefontsynonym [LMMathRoman-Regular] [\v!file:lmmath-regular.otf] [\s!features=\s!math]
- % \definefontsynonym [LMMathRoman-Bold] [\v!file:lmmath-bold.otf] [\s!features=\s!math]
- \stoptypescript
-
- \starttypescript [modern,default]
- \definetypeface [modern] [rm] [serif] [modern] [computer-modern]
- \definetypeface [modern] [ss] [sans] [modern] [computer-modern]
- \definetypeface [modern] [tt] [mono] [modern] [computer-modern]
- \definetypeface [modern] [mm] [math] [modern] [computer-modern]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [modern-base]
- \definetypeface [modern] [rm] [serif] [modern] [default]
- \definetypeface [modern] [ss] [sans] [modern] [default]
- \definetypeface [modern] [tt] [mono] [modern] [default]
- \definetypeface [modern] [mm] [math] [modern] [default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [modernvariable,modern-variable]
- \definetypeface [modernvariable] [rm] [serif] [modern-variable] [default]
- \definetypeface [modernvariable] [tt] [mono] [modern-variable] [default]
- \definetypeface [modernvariable] [mm] [math] [modern] [default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [modernvariablelight,modern-variable-light]
- \definetypeface [modernvariable] [rm] [serif] [modern-variable-light] [default]
- \definetypeface [modernvariable] [tt] [mono] [modern-variable-light] [default]
- \definetypeface [modernvariable] [mm] [math] [modern] [default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [modern-mono]
- \definetypeface [modern] [rm] [serif] [modern] [computer-modern]
- \definetypeface [modern] [ss] [sans] [modern] [computer-modern]
- \definetypeface [modern] [tt] [mono] [modern-light] [computer-modern]
- \definetypeface [modern] [mm] [math] [modern] [computer-modern]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [modern-base-mono]
- \definetypeface [modern] [rm] [serif] [modern] [computer-modern] [default]
- \definetypeface [modern] [ss] [sans] [modern] [computer-modern] [default]
- \definetypeface [modern] [tt] [mono] [modern-light] [computer-modern] [default]
- \definetypeface [modern] [mm] [math] [modern] [computer-modern] [default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [serif] [simple] [name]% bad, will be changed but in sycn with manuals that use it
- \definefontsynonym [Simple] [cmvtt10]
- %setupfontsynonym [Simple] [handling=pure]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[texgyre]
-
- \definetypescriptprefix [f:pagella] [pagella] \definetypescriptprefix [f:palatino] [pagella]
- \definetypescriptprefix [f:termes] [termes] \definetypescriptprefix [f:times] [termes]
- \definetypescriptprefix [f:heros] [heros] \definetypescriptprefix [f:helvetica] [heros]
- \definetypescriptprefix [f:bonum] [bonum] \definetypescriptprefix [f:bookman] [bonum]
- \definetypescriptprefix [f:schola] [schola] \definetypescriptprefix [f:schoolbook] [schola]
- \definetypescriptprefix [f:adventor][adventor]% \definetypescriptprefix [f:adventor] [adventor]
- \definetypescriptprefix [f:cursor] [cursor] \definetypescriptprefix [f:courier] [cursor]
- \definetypescriptprefix [f:chorus] [chorus] \definetypescriptprefix [f:chancery] [chorus]
-
- \starttypescript [serif,sans] [adventor,bonum,bookman,heros,helvetica,pagella,palatino,schola,schoolbook,termes,times]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [\s!features=\s!default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [\s!features=\s!default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [\s!features=\s!default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [\s!features=\s!default]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Caps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-ItalicCaps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldCaps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [\s!features=\s!smallcaps]
- \stoptypescript
-
- \starttypescript [mono] [cursor,courier]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Regular] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-regular] [\s!features=\s!none]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Italic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-italic] [\s!features=\s!none]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-Bold] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bold] [\s!features=\s!none]
- \definefontsynonym [\typescriptprefix{n:\typescripttwo}-BoldItalic] [\s!file:texgyre\typescriptprefix{f:\typescripttwo}-bolditalic] [\s!features=\s!none]
- \stoptypescript
-
- \starttypescript [serif,calligraphy] [chorus,chancery]
- \definefontsynonym [TeXGyreChorus-MediumItalic] [\s!file:texgyrechorus-mediumitalic] [\s!features=\s!default]
- \stoptypescript
-
- \definetypescriptprefix [n:pagella] [TeXGyrePagella] \definetypescriptprefix [n:palatino] [TeXGyrePagella]
- \definetypescriptprefix [n:termes] [TeXGyreTermes] \definetypescriptprefix [n:times] [TeXGyreTermes]
- \definetypescriptprefix [n:heros] [TeXGyreHeros] \definetypescriptprefix [n:helvetica] [TeXGyreHeros]
- \definetypescriptprefix [n:bonum] [TeXGyreBonum] \definetypescriptprefix [n:bookman] [TeXGyreBonum]
- \definetypescriptprefix [n:schola] [TeXGyreSchola] \definetypescriptprefix [n:schoolbook] [TeXGyreSchola]
- \definetypescriptprefix [n:adventor] [TeXGyreAdventor]% \definetypescriptprefix [n:adventor] [TeXGyreAdventor]
- \definetypescriptprefix [n:cursor] [TeXGyreCursor] \definetypescriptprefix [n:courier] [TeXGyreCursor]
- \definetypescriptprefix [n:chorus] [TeXGyreChorus] \definetypescriptprefix [n:chancery] [TeXGyreChorus] % not the full set
-
- \starttypescript [serif] [pagella,palatino,termes,times,bonum,bookman,schola,schoolbook] [name]
- \definefontsynonym [Serif] [\typescriptprefix{n:\typescripttwo}-Regular]
- \definefontsynonym [SerifItalic] [\typescriptprefix{n:\typescripttwo}-Italic]
- \definefontsynonym [SerifBold] [\typescriptprefix{n:\typescripttwo}-Bold]
- \definefontsynonym [SerifBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalic]
- \definefontsynonym [SerifSlanted] [SerifItalic]
- \definefontsynonym [SerifBoldSlanted] [SerifBoldItalic]
- \definefontsynonym [SerifCaps] [\typescriptprefix{n:\typescripttwo}-Caps]
-
- \definefontsynonym [SerifRegular] [Serif]
- \definefontsynonym [SerifRegularCaps] [SerifCaps]
- \definefontsynonym [SerifItalicCaps] [\typescriptprefix{n:\typescripttwo}-ItalicCaps]
- \definefontsynonym [SerifBoldCaps] [\typescriptprefix{n:\typescripttwo}-BoldCaps]
- \definefontsynonym [SerifBoldItalicCaps] [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps]
- \definefontsynonym [SerifSlantedCaps] [SerifItalicCaps]
- \definefontsynonym [SerifBoldSlantedCaps] [SerifBoldItalicCaps]
- \definefontsynonym [SerifCapsCaps] [SerifCaps]
- \stoptypescript
-
- \starttypescript [serif] [chorus,chancery] [name]
- \definefontsynonym [SerifMediumItalic] [TeXGyreChorus-MediumItalic]
- \definefontsynonym [Serif] [SerifMediumItalic]
- \definefontsynonym [SerifItalic] [SerifMediumItalic]
- \definefontsynonym [SerifBold] [SerifMediumItalic]
- \definefontsynonym [SerifBoldItalic] [SerifMediumItalic]
- \definefontsynonym [SerifSlanted] [SerifMediumItalic]
- \definefontsynonym [SerifBoldSlanted] [SerifMediumItalic]
- \definefontsynonym [SerifCaps] [SerifMediumItalic]
- \stoptypescript
-
- \starttypescript [calligraphy] [chorus,chancery] [name]
- \definefontsynonym [Calligraphy] [TeXGyreChorus-MediumItalic]
- \stoptypescript
-
- \starttypescript [sans] [heros,helvetica,adventor] [name]
- \definefontsynonym [Sans] [\typescriptprefix{n:\typescripttwo}-Regular]
- \definefontsynonym [SansItalic] [\typescriptprefix{n:\typescripttwo}-Italic]
- \definefontsynonym [SansBold] [\typescriptprefix{n:\typescripttwo}-Bold]
- \definefontsynonym [SansBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalic]
- \definefontsynonym [SansSlanted] [SansItalic]
- \definefontsynonym [SansBoldSlanted] [SansBoldItalic]
- \definefontsynonym [SansCaps] [\typescriptprefix{n:\typescripttwo}-Caps]
-
- \definefontsynonym [SansRegular] [Sans]
- \definefontsynonym [SansRegularCaps] [SansCaps]
- \definefontsynonym [SansItalicCaps] [\typescriptprefix{n:\typescripttwo}-ItalicCaps]
- \definefontsynonym [SansBoldCaps] [\typescriptprefix{n:\typescripttwo}-BoldCaps]
- \definefontsynonym [SansBoldItalicCaps] [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps]
- \definefontsynonym [SansSlantedCaps] [SansItalicCaps]
- \definefontsynonym [SansBoldSlantedCaps] [SansBoldItalicCaps]
- \definefontsynonym [SansCapsCaps] [SansCaps]
- \stoptypescript
-
- \starttypescript [mono] [cursor,courier] [name]
- \definefontsynonym [Mono] [\typescriptprefix{n:\typescripttwo}-Regular]
- \definefontsynonym [MonoItalic] [\typescriptprefix{n:\typescripttwo}-Italic]
- \definefontsynonym [MonoBold] [\typescriptprefix{n:\typescripttwo}-Bold]
- \definefontsynonym [MonoBoldItalic] [\typescriptprefix{n:\typescripttwo}-BoldItalic]
- \definefontsynonym [MonoSlanted] [MonoItalic]
- \definefontsynonym [MonoBoldSlanted] [MonoBoldItalic]
-
- \definefontsynonym [MonoRegular] [Mono]
- \definefontsynonym [MonoRegularCaps] [MonoCaps]
- \definefontsynonym [MonoItalicCaps] [\typescriptprefix{n:\typescripttwo}-ItalicCaps]
- \definefontsynonym [MonoBoldCaps] [\typescriptprefix{n:\typescripttwo}-BoldCaps]
- \definefontsynonym [MonoBoldItalicCaps] [\typescriptprefix{n:\typescripttwo}-BoldItalicCaps]
- \definefontsynonym [MonoSlantedCaps] [MonoItalicCaps]
- \definefontsynonym [MonoBoldSlantedCaps] [MonoBoldItalicCaps]
- \definefontsynonym [MonoCapsCaps] [MonoCaps]
- \stoptypescript
-
- \starttypescript [times,termes]
- \definetypeface [\typescriptone] [rm] [serif] [\typescriptone] [default]
- \definetypeface [\typescriptone] [ss] [sans] [helvetica] [default] [rscale=0.9]
- \definetypeface [\typescriptone] [tt] [mono] [modern] [default] [rscale=1.05]
- \definetypeface [\typescriptone] [mm] [math] [times] [default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [palatino,pagella]
- \definetypeface [\typescriptone] [rm] [serif] [\typescriptone] [default]
- \definetypeface [\typescriptone] [ss] [sans] [modern] [default] [rscale=1.075]
- \definetypeface [\typescriptone] [tt] [mono] [modern] [default] [rscale=1.075]
- \definetypeface [\typescriptone] [mm] [math] [palatino] [default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [schoolbook,schola]
- \definetypeface [\typescriptone] [rm] [serif] [\typescriptone] [default]
- \definetypeface [\typescriptone] [ss] [sans] [modern] [default] [rscale=1.1]
- \definetypeface [\typescriptone] [tt] [mono] [modern] [default] [rscale=1.1]
- \definetypeface [\typescriptone] [mm] [math] [modern] [default] [rscale=1.1]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [bookman,bonum]
- \definetypeface [\typescriptone] [rm] [serif] [\typescriptone] [default]
- \definetypeface [\typescriptone] [ss] [sans] [modern] [default] [rscale=1.1]
- \definetypeface [\typescriptone] [tt] [mono] [modern] [default] [rscale=1.1]
- \definetypeface [\typescriptone] [mm] [math] [modern] [default] [rscale=1.1]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [chancery,chorus]
- \definetypeface [\typescriptone] [rm] [serif] [\typescriptone] [default]
- \definetypeface [\typescriptone] [ss] [sans] [modern] [default]
- \definetypeface [\typescriptone] [tt] [mono] [modern] [default]
- \definetypeface [\typescriptone] [mm] [math] [modern] [default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [helvetica,heros]
- \definetypeface [\typescriptone] [ss] [sans] [\typescriptone] [default]
- \definetypeface [\typescriptone] [rm] [serif] [modern] [default] [rscale=1.15]
- \definetypeface [\typescriptone] [tt] [mono] [modern] [default] [rscale=1.15]
- \definetypeface [\typescriptone] [mm] [math] [modern] [default] [rscale=1.15]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [avantgarde,adventor]
- \definetypeface [\typescriptone] [ss] [sans] [adventor] [default]
- \definetypeface [\typescriptone] [rm] [serif] [modern] [default] [rscale=1.15]
- \definetypeface [\typescriptone] [tt] [mono] [modern] [default] [rscale=1.15]
- \definetypeface [\typescriptone] [mm] [math] [modern] [default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [courier,cursor]
- \definetypeface [\typescriptone] [tt] [mono] [\typescriptone] [default]
- \definetypeface [\typescriptone] [rm] [serif] [modern] [default]
- \definetypeface [\typescriptone] [ss] [sans] [modern] [default]
- \definetypeface [\typescriptone] [mm] [math] [modern] [default]
- \quittypescriptscanning
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[xmath]
-
- % Times Math (tx)
-
- \starttypescript [math][times][all]
- \loadfontgoodies[tx-math]
- \definefontsynonym[MathRoman][txmath@tx-math]
- \stoptypescript
-
- % Palatino Math (px)
-
- \starttypescript [math][palatino][all]
- \loadfontgoodies[px-math]
- \definefontsynonym[MathRoman][pxmath@px-math]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[dejavu]
-
- \starttypescript [serif] [dejavu] [name]
- \setups[font:fallback:serif]
- \definefontsynonym [Serif] [name:dejavuserif] [features=default]
- \definefontsynonym [SerifBold] [name:dejavuserifbold] [features=default]
- \definefontsynonym [SerifItalic] [name:dejavuserifitalic] [features=default]
- \definefontsynonym [SerifBoldItalic] [name:dejavuserifbolditalic] [features=default]
- \stoptypescript
-
- \starttypescript [sans] [dejavu] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [name:dejavusans] [features=default]
- \definefontsynonym [SansBold] [name:dejavusansbold] [features=default]
- \definefontsynonym [SansItalic] [name:dejavusansoblique] [features=default]
- \definefontsynonym [SansBoldItalic] [name:dejavusansboldoblique] [features=default]
- \stoptypescript
-
- \starttypescript [mono] [dejavu] [name]
- \setups[font:fallback:mono]
- \definefontsynonym [Mono] [name:dejavusansmono] [features=none]
- \definefontsynonym [MonoBold] [name:dejavusansmonobold] [features=none]
- \definefontsynonym [MonoItalic] [name:dejavusansmonooblique] [features=none]
- \definefontsynonym [MonoBoldItalic] [name:dejavusansmonoboldoblique] [features=none]
- \stoptypescript
-
- \starttypescript[dejavu]
- \definetypeface [dejavu] [rm] [serif] [dejavu] [default]
- \definetypeface [dejavu] [ss] [sans] [dejavu] [default]
- \definetypeface [dejavu] [tt] [mono] [dejavu] [default]
- \definetypeface [dejavu] [mm] [math] [xits] [default] [rscale=auto]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[antykwa]
-
- % Antykwa Torunska (GUST)
-
- \starttypescript [serif] [antykwa-torunska,antykwa-torunska-light,antykwa-torunska-cond,antykwa-torunska-lightcond]
- \definefontsynonym [AntykwaTorunska-Regular] [\s!file:AntykwaTorunska-Regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-Italic] [\s!file:AntykwaTorunska-Italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-Bold] [\s!file:AntykwaTorunska-Bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-BoldItalic] [\s!file:AntykwaTorunska-BoldItalic] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-Light] [\s!file:AntykwaTorunskaLight-Regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-LightItalic] [\s!file:AntykwaTorunskaLight-Italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-Medium] [\s!file:AntykwaTorunskaMed-Regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-MedItalic] [\s!file:AntykwaTorunskaMed-Italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-CondRegular] [\s!file:AntykwaTorunskaCond-Regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-CondItalic] [\s!file:AntykwaTorunskaCond-Italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-CondBold] [\s!file:AntykwaTorunskaCond-Bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-CondBoldItalic] [\s!file:AntykwaTorunskaCond-BoldItalic] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-CondLight] [\s!file:AntykwaTorunskaCondLight-Regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-CondLightItalic] [\s!file:AntykwaTorunskaCondLight-Italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-CondMedium] [\s!file:AntykwaTorunskaCondMed-Regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaTorunska-CondMedItalic] [\s!file:AntykwaTorunskaCondMed-Italic] [\s!features=\s!default]
-
- \definefontsynonym [AntykwaTorunska-Cap] [\s!file:AntykwaTorunska-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-ItalicCap] [\s!file:AntykwaTorunska-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-BoldCap] [\s!file:AntykwaTorunska-Bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-BoldItalicCap] [\s!file:AntykwaTorunska-BoldItalic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-LightCap] [\s!file:AntykwaTorunskaLight-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-LightItalicCap] [\s!file:AntykwaTorunskaLight-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-MediumCap] [\s!file:AntykwaTorunskaMed-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-MedItalicCap] [\s!file:AntykwaTorunskaMed-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-CondCap] [\s!file:AntykwaTorunskaCond-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-CondItalicCap] [\s!file:AntykwaTorunskaCond-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-CondBoldCap] [\s!file:AntykwaTorunskaCond-Bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-CondBoldItalicCap] [\s!file:AntykwaTorunskaCond-BoldItalic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-CondLightCap] [\s!file:AntykwaTorunskaCondLight-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-CondLightItalicCap][\s!file:AntykwaTorunskaCondLight-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-CondMediumCap] [\s!file:AntykwaTorunskaCondMed-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaTorunska-CondMedItalicCap] [\s!file:AntykwaTorunskaCondMed-Italic] [\s!features=\s!smallcaps]
- \stoptypescript
-
- \starttypescript [math][antykwa-torunska][all]
- \loadfontgoodies[antykwa-math]
- \definefontsynonym[MathRoman][antykwamath@antykwa-math]
- \stoptypescript
-
- \starttypescript [math][antykwa-torunska-light][all]
- \loadfontgoodies[antykwa-math]
- \definefontsynonym[MathRoman][antykwalightmath@antykwa-light-math]
- \stoptypescript
-
- \starttypescript [math][antykwa-torunska-cond][all]
- \loadfontgoodies[antykwa-math]
- \definefontsynonym[MathRoman][antykwacondmath@antykwa-cond-math]
- \stoptypescript
-
- \starttypescript [math][antykwa-torunska-lightcond][all]
- \loadfontgoodies[antykwa-math]
- \definefontsynonym[MathRoman][antykwalightcondmath@antykwa-lightcond-math]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-torunska] [name]
- \definefontsynonym [Serif] [AntykwaTorunska-Regular]
- \definefontsynonym [SerifBold] [AntykwaTorunska-Bold]
- \definefontsynonym [SerifItalic] [AntykwaTorunska-Italic]
- \definefontsynonym [SerifSlanted] [AntykwaTorunska-Italic]
- \definefontsynonym [SerifBoldItalic] [AntykwaTorunska-BoldItalic]
- \definefontsynonym [SerifBoldSlanted] [AntykwaTorunska-BoldItalic]
- \definefontsynonym [SerifCaps] [AntykwaTorunska-Cap]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-torunska-light] [name]
- \definefontsynonym [Serif] [AntykwaTorunska-Light]
- \definefontsynonym [SerifBold] [AntykwaTorunska-Medium]
- \definefontsynonym [SerifItalic] [AntykwaTorunska-LightItalic]
- \definefontsynonym [SerifSlanted] [AntykwaTorunska-LightItalic]
- \definefontsynonym [SerifBoldItalic] [AntykwaTorunska-MedItalic]
- \definefontsynonym [SerifBoldSlanted] [AntykwaTorunska-MedItalic]
- \definefontsynonym [SerifCaps] [AntykwaTorunska-LightCap]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-torunska-cond] [name]
- \definefontsynonym [Serif] [AntykwaTorunska-CondRegular]
- \definefontsynonym [SerifBold] [AntykwaTorunska-CondBold]
- \definefontsynonym [SerifItalic] [AntykwaTorunska-CondItalic]
- \definefontsynonym [SerifSlanted] [AntykwaTorunska-CondItalic]
- \definefontsynonym [SerifBoldItalic] [AntykwaTorunska-CondBoldItalic]
- \definefontsynonym [SerifBoldSlanted] [AntykwaTorunska-CondBoldItalic]
- \definefontsynonym [SerifCaps] [AntykwaTorunska-CondCap]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-torunska-lightcond] [name]
- \definefontsynonym [Serif] [AntykwaTorunska-CondLight]
- \definefontsynonym [SerifBold] [AntykwaTorunska-CondMedium]
- \definefontsynonym [SerifItalic] [AntykwaTorunska-CondLightItalic]
- \definefontsynonym [SerifSlanted] [AntykwaTorunska-CondLightItalic]
- \definefontsynonym [SerifBoldItalic] [AntykwaTorunska-CondMedItalic]
- \definefontsynonym [SerifBoldSlanted] [AntykwaTorunska-CondMedItalic]
- \definefontsynonym [SerifCaps] [AntykwaTorunska-CondLightCap]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-torunska] [name]
- \definefontsynonym [SerifRegular] [Serif]
- \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-Cap]
- \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-BoldCap]
- \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-ItalicCap]
- \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-ItalicCap]
- \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-BoldItalicCap]
- \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-BoldItalicCap]
- \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-Cap]
-
- \definefontsynonym [SerifRegularLight] [AntykwaTorunska-Light]
- \definefontsynonym [SerifBoldLight] [AntykwaTorunska-Medium]
- \definefontsynonym [SerifItalicLight] [AntykwaTorunska-LightItalic]
- \definefontsynonym [SerifSlantedLight] [AntykwaTorunska-LightItalic]
- \definefontsynonym [SerifBoldItalicLight] [AntykwaTorunska-MedItalic]
- \definefontsynonym [SerifBoldSlantedLight] [AntykwaTorunska-MedItalic]
- \definefontsynonym [SerifCapsLight] [AntykwaTorunska-LightCap]
-
- \definefontsynonym [SerifRegularCond] [AntykwaTorunska-CondRegular]
- \definefontsynonym [SerifBoldCond] [AntykwaTorunska-CondBold]
- \definefontsynonym [SerifItalicCond] [AntykwaTorunska-CondItalic]
- \definefontsynonym [SerifSlantedCond] [AntykwaTorunska-CondItalic]
- \definefontsynonym [SerifBoldItalicCond] [AntykwaTorunska-CondBoldItalic]
- \definefontsynonym [SerifBoldSlantedCond] [AntykwaTorunska-CondBoldItalic]
- \definefontsynonym [SerifCapsCond] [AntykwaTorunska-CondCap]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-torunska-light] [name]
- \definefontsynonym [SerifRegular] [Serif]
- \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-LightCap]
- \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-MediumCap]
- \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-LightItalicCap]
- \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-LightItalicCap]
- \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-MedItalicCap]
- \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-MedItalicCap]
- \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-LightCap]
-
- \definefontsynonym [SerifRegularDark] [AntykwaTorunska-Regular]
- \definefontsynonym [SerifBoldDark] [AntykwaTorunska-Bold]
- \definefontsynonym [SerifItalicDark] [AntykwaTorunska-Italic]
- \definefontsynonym [SerifSlantedDark] [AntykwaTorunska-Italic]
- \definefontsynonym [SerifBoldItalicDark] [AntykwaTorunska-BoldItalic]
- \definefontsynonym [SerifBoldSlantedDark] [AntykwaTorunska-BoldItalic]
- \definefontsynonym [SerifCapsDark] [AntykwaTorunska-Cap]
-
- \definefontsynonym [SerifRegularCond] [AntykwaTorunska-CondLight]
- \definefontsynonym [SerifBoldCond] [AntykwaTorunska-CondMedium]
- \definefontsynonym [SerifItalicCond] [AntykwaTorunska-CondLightItalic]
- \definefontsynonym [SerifSlantedCond] [AntykwaTorunska-CondLightItalic]
- \definefontsynonym [SerifBoldItalicCond] [AntykwaTorunska-CondMedItalic]
- \definefontsynonym [SerifBoldSlantedCond] [AntykwaTorunska-CondMedItalic]
- \definefontsynonym [SerifCapsCond] [AntykwaTorunska-CondLightCap]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-torunska-cond] [name]
- \definefontsynonym [SerifRegular] [Serif]
- \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-CondCap]
- \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-CondBoldCap]
- \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-CondItalicCap]
- \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-CondItalicCap]
- \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-CondBoldItalicCap]
- \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-CondBoldItalicCap]
- \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-CondCap]
-
- \definefontsynonym [SerifRegularLight] [AntykwaTorunska-CondLight]
- \definefontsynonym [SerifBoldLight] [AntykwaTorunska-CondMedium]
- \definefontsynonym [SerifItalicLight] [AntykwaTorunska-CondLightItalic]
- \definefontsynonym [SerifSlantedLight] [AntykwaTorunska-CondLightItalic]
- \definefontsynonym [SerifBoldItalicLight] [AntykwaTorunska-CondMedItalic]
- \definefontsynonym [SerifBoldSlantedLight] [AntykwaTorunska-CondMedItalic]
- \definefontsynonym [SerifCapsLight] [AntykwaTorunska-CondLightCap]
-
- \definefontsynonym [SerifRegularExp] [AntykwaTorunska-Regular]
- \definefontsynonym [SerifBoldExp] [AntykwaTorunska-Bold]
- \definefontsynonym [SerifItalicExp] [AntykwaTorunska-Italic]
- \definefontsynonym [SerifSlantedExp] [AntykwaTorunska-Italic]
- \definefontsynonym [SerifBoldItalicExp] [AntykwaTorunska-BoldItalic]
- \definefontsynonym [SerifBoldSlantedExp] [AntykwaTorunska-BoldItalic]
- \definefontsynonym [SerifCapsExp] [AntykwaTorunska-Cap]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-torunska-lightcond] [name]
- \definefontsynonym [SerifRegular] [Serif]
- \definefontsynonym [SerifRegularCaps] [AntykwaTorunska-CondLightCap]
- \definefontsynonym [SerifBoldCaps] [AntykwaTorunska-CondMediumCap]
- \definefontsynonym [SerifItalicCaps] [AntykwaTorunska-CondLightItalicCap]
- \definefontsynonym [SerifSlantedCaps] [AntykwaTorunska-CondLightItalicCap]
- \definefontsynonym [SerifBoldItalicCaps] [AntykwaTorunska-CondMedItalicCap]
- \definefontsynonym [SerifBoldSlantedCaps] [AntykwaTorunska-CondMedItalicCap]
- \definefontsynonym [SerifCapsCaps] [AntykwaTorunska-CondLightCap]
-
- \definefontsynonym [SerifRegularDark] [AntykwaTorunska-CondRegular]
- \definefontsynonym [SerifBoldDark] [AntykwaTorunska-CondBold]
- \definefontsynonym [SerifItalicDark] [AntykwaTorunska-CondItalic]
- \definefontsynonym [SerifSlantedDark] [AntykwaTorunska-CondItalic]
- \definefontsynonym [SerifBoldItalicDark] [AntykwaTorunska-CondBoldItalic]
- \definefontsynonym [SerifBoldSlantedDark] [AntykwaTorunska-CondBoldItalic]
- \definefontsynonym [SerifCapsDark] [AntykwaTorunska-CondCap]
-
- \definefontsynonym [SerifRegularExp] [AntykwaTorunska-Light]
- \definefontsynonym [SerifBoldExp] [AntykwaTorunska-Medium]
- \definefontsynonym [SerifItalicExp] [AntykwaTorunska-LightItalic]
- \definefontsynonym [SerifSlantedExp] [AntykwaTorunska-LightItalic]
- \definefontsynonym [SerifBoldItalicExp] [AntykwaTorunska-MedItalic]
- \definefontsynonym [SerifBoldSlantedExp] [AntykwaTorunska-MedItalic]
- \definefontsynonym [SerifCapsExp] [AntykwaTorunska-LightCap]
- \stoptypescript
-
- \starttypescript [antykwa-torunska,antykwa-torunska-light,antykwa-torunska-cond,antykwa-torunska-lightcond]
- \definetypeface[antykwa][rm][serif][\typescriptone] [default]
- \definetypeface[antykwa][ss][sans] [modern] [default] [rscale=1.05]
- \definetypeface[antykwa][tt][mono] [modern] [default] [rscale=1.05]
- \definetypeface[antykwa][mm][math] [\typescriptone] [default]
- \quittypescriptscanning
- \stoptypescript
-
- % Antykwa Poltawskiego (GUST)
-
-% \starttypescript [serif] [antykwa-poltawskiego]
-% \definefontsynonym [AntykwaPoltawskiego-Regular] [antpr]
-% \definefontsynonym [AntykwaPoltawskiego-Bold] [antpb]
-% \definefontsynonym [AntykwaPoltawskiego-Italic] [antpri]
-% \definefontsynonym [AntykwaPoltawskiego-BoldItalic] [antpbi]
-% \stoptypescript
-
-% \starttypescript [serif] [antykwa-poltawskiego] [name]
-% \definefontsynonym [Serif] [AntykwaPoltawskiego-Regular]
-% \definefontsynonym [SerifBold] [AntykwaPoltawskiego-Bold]
-% \definefontsynonym [SerifItalic] [AntykwaPoltawskiego-Italic]
-% \definefontsynonym [SerifSlanted] [AntykwaPoltawskiego-Italic]
-% \definefontsynonym [SerifBoldItalic] [AntykwaPoltawskiego-Bold]
-% \definefontsynonym [SerifBoldSlanted] [AntykwaPoltawskiego-Bold]
-% \definefontsynonym [SerifCaps] [AntykwaPoltawskiego-Regular]
-% \stoptypescript
-
- % names of "Caps" may still change
- \starttypescript [serif] [antykwa-poltawskiego,antykwa-poltawskiego-light]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-Light] [\s!file:antpoltltcond-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-LightItalic] [\s!file:antpoltltcond-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-Regular] [\s!file:antpoltcond-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-Italic] [\s!file:antpoltcond-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-Medium] [\s!file:antpoltltcond-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-MediumItalic] [\s!file:antpoltltcond-bolditalic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-Bold] [\s!file:antpoltcond-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-BoldItalic] [\s!file:antpoltcond-bolditalic] [\s!features=\s!default]
-
- \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsLight] [\s!file:antpoltltcond-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsLightItalic] [\s!file:antpoltltcond-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsRegular] [\s!file:antpoltcond-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsItalic] [\s!file:antpoltcond-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsMedium] [\s!file:antpoltltcond-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsMediumItalic] [\s!file:antpoltltcond-bolditalic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsBold] [\s!file:antpoltcond-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Condensed-CapsBoldItalic] [\s!file:antpoltcond-bolditalic] [\s!features=\s!smallcaps]
-
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Light] [\s!file:antpoltltsemicond-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-LightItalic] [\s!file:antpoltltsemicond-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Regular] [\s!file:antpoltsemicond-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Italic] [\s!file:antpoltsemicond-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Medium] [\s!file:antpoltltsemicond-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-MediumItalic] [\s!file:antpoltltsemicond-bolditalic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-Bold] [\s!file:antpoltsemicond-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-BoldItalic] [\s!file:antpoltsemicond-bolditalic] [\s!features=\s!default]
-
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsLight] [\s!file:antpoltltsemicond-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsLightItalic] [\s!file:antpoltltsemicond-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsRegular] [\s!file:antpoltsemicond-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsItalic] [\s!file:antpoltsemicond-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsMedium] [\s!file:antpoltltsemicond-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsMediumItalic] [\s!file:antpoltltsemicond-bolditalic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsBold] [\s!file:antpoltsemicond-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiCondensed-CapsBoldItalic] [\s!file:antpoltsemicond-bolditalic] [\s!features=\s!smallcaps]
-
- \definefontsynonym [AntykwaPoltawskiego-Light] [\s!file:antpoltlt-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-LightItalic] [\s!file:antpoltlt-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Regular] [\s!file:antpolt-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Italic] [\s!file:antpolt-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Medium] [\s!file:antpoltlt-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-MediumItalic] [\s!file:antpoltlt-bolditalic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Bold] [\s!file:antpolt-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-BoldItalic] [\s!file:antpolt-bolditalic] [\s!features=\s!default]
-
- \definefontsynonym [AntykwaPoltawskiego-CapsLight] [\s!file:antpoltcond-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-CapsLightItalic] [\s!file:antpoltcond-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-CapsRegular] [\s!file:antpolt-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-CapsItalic] [\s!file:antpolt-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-CapsMedium] [\s!file:antpoltcond-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-CapsMediumItalic] [\s!file:antpoltcond-bolditalic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-CapsBold] [\s!file:antpolt-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-CapsBoldItalic] [\s!file:antpolt-bolditalic] [\s!features=\s!smallcaps]
-
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Light] [\s!file:antpoltltsemiexpd-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-LightItalic] [\s!file:antpoltltsemiexpd-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Regular] [\s!file:antpoltsemiexpd-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Italic] [\s!file:antpoltsemiexpd-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Medium] [\s!file:antpoltltsemiexpd-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-MediumItalic] [\s!file:antpoltltsemiexpd-bolditalic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-Bold] [\s!file:antpoltsemiexpd-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-BoldItalic] [\s!file:antpoltsemiexpd-bolditalic] [\s!features=\s!default]
-
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsLight] [\s!file:antpoltltsemiexpd-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsLightItalic] [\s!file:antpoltltsemiexpd-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsRegular] [\s!file:antpoltsemiexpd-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsItalic] [\s!file:antpoltsemiexpd-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsMedium] [\s!file:antpoltltsemiexpd-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsMediumItalic] [\s!file:antpoltltsemiexpd-bolditalic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsBold] [\s!file:antpoltsemiexpd-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-SemiExpanded-CapsBoldItalic] [\s!file:antpoltsemiexpd-bolditalic] [\s!features=\s!smallcaps]
-
- \definefontsynonym [AntykwaPoltawskiego-Expanded-Light] [\s!file:antpoltltexpd-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-LightItalic] [\s!file:antpoltltexpd-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-Regular] [\s!file:antpoltexpd-regular] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-Italic] [\s!file:antpoltexpd-italic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-Medium] [\s!file:antpoltltexpd-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-MediumItalic] [\s!file:antpoltltexpd-bolditalic] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-Bold] [\s!file:antpoltexpd-bold] [\s!features=\s!default]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-BoldItalic] [\s!file:antpoltexpd-bolditalic] [\s!features=\s!default]
-
- \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsLight] [\s!file:antpoltltexpd-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsLightItalic] [\s!file:antpoltltexpd-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsRegular] [\s!file:antpoltexpd-regular] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsItalic] [\s!file:antpoltexpd-italic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsMedium] [\s!file:antpoltltexpd-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsMediumItalic] [\s!file:antpoltltexpd-bolditalic] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsBold] [\s!file:antpoltexpd-bold] [\s!features=\s!smallcaps]
- \definefontsynonym [AntykwaPoltawskiego-Expanded-CapsBoldItalic] [\s!file:antpoltexpd-bolditalic] [\s!features=\s!smallcaps]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-poltawskiego] [name]
- \definefontsynonym [Serif] [AntykwaPoltawskiego-Regular]
- \definefontsynonym [SerifBold] [AntykwaPoltawskiego-Bold]
- \definefontsynonym [SerifItalic] [AntykwaPoltawskiego-Italic]
- \definefontsynonym [SerifSlanted] [AntykwaPoltawskiego-Italic]
- \definefontsynonym [SerifBoldItalic] [AntykwaPoltawskiego-BoldItalic]
- \definefontsynonym [SerifBoldSlanted] [AntykwaPoltawskiego-BoldItalic]
- \definefontsynonym [SerifCaps] [AntykwaPoltawskiego-CapsRegular]
- \stoptypescript
-
- \starttypescript [serif] [antykwa-poltawskiego-light] [name]
- \definefontsynonym [Serif] [AntykwaPoltawskiego-Light]
- \definefontsynonym [SerifBold] [AntykwaPoltawskiego-Medium]
- \definefontsynonym [SerifItalic] [AntykwaPoltawskiego-LightItalic]
- \definefontsynonym [SerifSlanted] [AntykwaPoltawskiego-LightItalic]
- \definefontsynonym [SerifBoldItalic] [AntykwaPoltawskiego-MediumItalic]
- \definefontsynonym [SerifBoldSlanted] [AntykwaPoltawskiego-MediumItalic]
- \definefontsynonym [SerifCaps] [AntykwaPoltawskiego-CapsLight]
- \stoptypescript
-
- % condensed and extended variants are still missing
-
- \starttypescript [antykwa-poltawskiego,antykwa-poltawskiego-light]
- \definetypeface [\typescriptone] [rm] [serif] [\typescriptone] [default]
- \definetypeface [\typescriptone] [ss] [sans] [modern] [default] [rscale=1.05]
- \definetypeface [\typescriptone] [tt] [mono] [modern] [default] [rscale=1.05]
- \definetypeface [\typescriptone] [mm] [math] [modern] [default] [rscale=1.05]
- \quittypescriptscanning
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[iwona]
-
- % maybe this will change in Iwona-Math-Letters and Iwona-Math-Letters-Italic
-
- % These names are a depressing mess. They have changed over time and are
- % still not consistent. I'd expect Bold-Regular and Bold-Italic.
-
- \starttypescript [sans] [iwona-light,iwona,iwona-medium,iwona-heavy,iwona-light-cond,iwona-cond,iwona-medium-cond,iwona-heavy-cond]
-
- \definefontsynonym [Iwona-Regular] [\s!file:Iwona-Regular] [\s!features=\s!default]
- \definefontsynonym [Iwona-Italic] [\s!file:Iwona-Italic] [\s!features=\s!default]
- \definefontsynonym [Iwona-Bold] [\s!file:Iwona-Bold] [\s!features=\s!default]
- \definefontsynonym [Iwona-BoldItalic] [\s!file:Iwona-BoldItalic] [\s!features=\s!default]
- \definefontsynonym [Iwona-Light-Regular] [\s!file:IwonaLight-Regular] [\s!features=\s!default]
- \definefontsynonym [Iwona-Light-Italic] [\s!file:IwonaLight-Italic] [\s!features=\s!default]
- \definefontsynonym [Iwona-Medium-Regular] [\s!file:IwonaMedium-Regular] [\s!features=\s!default]
- \definefontsynonym [Iwona-Medium-Italic] [\s!file:IwonaMedium-Italic] [\s!features=\s!default]
- \definefontsynonym [Iwona-Heavy-Regular] [\s!file:IwonaHeavy-Regular] [\s!features=\s!default]
- \definefontsynonym [Iwona-Heavy-Italic] [\s!file:IwonaHeavy-Italic] [\s!features=\s!default]
-
- \definefontsynonym [Iwona-CapsRegular] [\s!file:Iwona-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsItalic] [\s!file:Iwona-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsBold] [\s!file:Iwona-Bold] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsBoldItalic] [\s!file:Iwona-BoldItalic] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsLight] [\s!file:IwonaLight-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsLight-Italic] [\s!file:IwonaLight-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsMedium] [\s!file:IwonaMedium-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsMedium-Italic] [\s!file:IwonaMedium-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsHeavy] [\s!file:IwonaHeavy-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsHeavy-Italic] [\s!file:IwonaHeavy-Italic] [\s!features=\s!smallcaps]
-
- \definefontsynonym [Iwona-CondRegular] [\s!file:IwonaCond-Regular] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondItalic] [\s!file:IwonaCond-Italic] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondBold] [\s!file:IwonaCond-Bold] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondBoldItalic] [\s!file:IwonaCond-BoldItalic] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondLight-Regular] [\s!file:IwonaCondLight-Regular] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondLight-Italic] [\s!file:IwonaCondLight-Italic] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondMedium-Regular] [\s!file:IwonaCondMedium-Regular] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondMedium-Italic] [\s!file:IwonaCondMedium-Italic] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondHeavy-Regular] [\s!file:IwonaCondHeavy-Regular] [\s!features=\s!default]
- \definefontsynonym [Iwona-CondHeavy-Italic] [\s!file:IwonaCondHeavy-Italic] [\s!features=\s!default]
-
- \definefontsynonym [Iwona-CapsCondRegular] [\s!file:IwonaCond-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondItalic] [\s!file:IwonaCond-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondBold] [\s!file:IwonaCond-Bold] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondBoldItalic] [\s!file:IwonaCond-BoldItalic] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondLight-Regular] [\s!file:IwonaCondLight-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondLight-Italic] [\s!file:IwonaCondLight-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondMedium-Regular][\s!file:IwonaCondMedium-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondMedium-Italic] [\s!file:IwonaCondMedium-Italic] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondHeavy-Regular] [\s!file:IwonaCondHeavy-Regular] [\s!features=\s!smallcaps]
- \definefontsynonym [Iwona-CapsCondHeavy-Italic] [\s!file:IwonaCondHeavy-Italic] [\s!features=\s!smallcaps]
-
- \stoptypescript
-
- % [all] is redundant
-
- \starttypescript [math][iwona][all]
- \definefontsynonym[MathRoman][iwonamath@iwona-math]
- \stoptypescript
- \starttypescript [math][iwona-light][all]
- \definefontsynonym[MathRoman][iwonalightmath@iwona-light-math]
- \stoptypescript
- \starttypescript [math][iwona-medium][all]
- \definefontsynonym[MathRoman][iwonamediummath@iwona-medium-math]
- \stoptypescript
- \starttypescript [math][iwona-heavy][all]
- \definefontsynonym[MathRoman][iwonaheavymath@iwona-heavy-math]
- \stoptypescript
-
- \starttypescript [math] [iwona,iwona-light,iwona-medium,iwona-heavy] [all]
- \loadfontgoodies[iwona-math]
- \stoptypescript
-
- \starttypescript [sans] [iwona-light] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-Light-Regular]
- \definefontsynonym [SansItalic] [Iwona-Light-Italic]
- \definefontsynonym [SansBold] [Iwona-Medium-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-Medium-Italic]
- \definefontsynonym [SansCaps] [Iwona-CapsLight]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsLightItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsMedium]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsMediumItalic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-light-caps] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CapsLight-Regular]
- \definefontsynonym [SansItalic] [Iwona-CapsLight-Italic]
- \definefontsynonym [SansBold] [Iwona-CapsMedium-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-CapsMedium-Italic]
- \stoptypescript
-
- \starttypescript [sans] [iwona] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-Regular]
- \definefontsynonym [SansItalic] [Iwona-Italic]
- \definefontsynonym [SansBold] [Iwona-Bold]
- \definefontsynonym [SansBoldItalic] [Iwona-BoldItalic]
- \definefontsynonym [SansCaps] [Iwona-CapsRegular]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsBold]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsBoldItalic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-caps] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CapsRegular]
- \definefontsynonym [SansItalic] [Iwona-CapsItalic]
- \definefontsynonym [SansBold] [Iwona-CapsBold]
- \definefontsynonym [SansBoldItalic] [Iwona-CapsBoldItalic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-medium] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-Medium-Regular]
- \definefontsynonym [SansItalic] [Iwona-Medium-Italic]
- \definefontsynonym [SansBold] [Iwona-Heavy-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-Heavy-Italic]
- \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsMedium-Italic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-medium-caps] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CapsHeavy-Regular]
- \definefontsynonym [SansItalic] [Iwona-CapsMedium-Italic]
- \definefontsynonym [SansBold] [Iwona-CapsHeavy-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-CapsHeavy-Italic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-heavy] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-Heavy-Regular]
- \definefontsynonym [SansItalic] [Iwona-Heavy-Italic]
- \definefontsynonym [SansBold] [Iwona-Heavy-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-Heavy-Italic]
- \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsHeavy-Italic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-heavy-caps] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [SansCaps] [Iwona-CapsHeavy-Regular]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsHeavy-Italic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsHeavy-Regular]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsHeavy-Italic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-light-cond] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CondLight-Regular]
- \definefontsynonym [SansItalic] [Iwona-CondLight-Italic]
- \definefontsynonym [SansBold] [Iwona-CondMedium-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-CondMedium-Italic]
- \definefontsynonym [SansCaps] [Iwona-CapsCondLight-Regular]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsCondLight-Italic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsCondMedium-Regular]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondMedium-Italic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-light-cond-caps,iwona-light-caps-cond] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CapsCondLight-Regular]
- \definefontsynonym [SansItalic] [Iwona-CapsCondLight-Italic]
- \definefontsynonym [SansBold] [Iwona-CapsCondMedium-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-CapsCondMedium-Italic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-cond] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CondRegular]
- \definefontsynonym [SansItalic] [Iwona-CondItalic]
- \definefontsynonym [SansBold] [Iwona-CondBold]
- \definefontsynonym [SansBoldItalic] [Iwona-CondBoldItalic]
- \definefontsynonym [SansCaps] [Iwona-CapsCondRegular]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsCondItalic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsCondBold]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondBoldItalic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-cond-caps,iwona-caps-cond] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CapsCondRegular]
- \definefontsynonym [SansItalic] [Iwona-CapsCondItalic]
- \definefontsynonym [SansBold] [Iwona-CapsCondBold]
- \definefontsynonym [SansBoldItalic] [Iwona-CapsCondBoldItalic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-medium-cond] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CondMedium-Regular]
- \definefontsynonym [SansItalic] [Iwona-CondMedium-Italic]
- \definefontsynonym [SansBold] [Iwona-CondHeavy-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-CondHeavy-Italic]
- \definefontsynonym [SansCaps] [Iwona-CapsCondHeavy-Regular]
- \definefontsynonym [SansItalicCaps] [Iwona-CapsCondMedium-Italic]
- \definefontsynonym [SansBoldCaps] [Iwona-CapsCondHeavy-Regular]
- \definefontsynonym [SansBoldItalicCaps] [Iwona-CapsCondHeavy-Italic]
- \stoptypescript
-
- \starttypescript [sans] [iwona-medium-cond-caps,iwona-medium-caps-cond] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Iwona-CapsCondHeavy-Regular]
- \definefontsynonym [SansItalic] [Iwona-CapsCondMedium-Italic]
- \definefontsynonym [SansBold] [Iwona-CapsCondHeavy-Regular]
- \definefontsynonym [SansBoldItalic] [Iwona-CapsCondHeavy-Italic]
- \stoptypescript
-
- \starttypescript [iwona,iwona-light,iwona-heavy,iwona-medium]
- \definetypeface[\typescriptone][ss][sans] [\typescriptone] [default]
- \definetypeface[\typescriptone][rm][serif][modern] [default]
- \definetypeface[\typescriptone][tt][mono] [modern] [default]
- \definetypeface[\typescriptone][mm][math] [\typescriptone] [default][text=ss]
- \quittypescriptscanning
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[kurier]
-
- % Kurier (JMN) / no open type fonts yet so this should be in type-one.mkiv
-
- \starttypescript [sans] [kurier-light,kurier,kurier-medium]
- \definefontsynonym[Kurier-Light] [kurierl]
- \definefontsynonym[Kurier-Regular] [kurierr]
- \definefontsynonym[Kurier-Medium] [kurierm]
- \definefontsynonym[Kurier-Bold] [kurierb]
- \definefontsynonym[Kurier-Heavy] [kurierh]
- \definefontsynonym[Kurier-LightItalic] [kurierli]
- \definefontsynonym[Kurier-Italic] [kurierri]
- \definefontsynonym[Kurier-MediumItalic] [kuriermi]
- \definefontsynonym[Kurier-BoldItalic] [kurierbi]
- \definefontsynonym[Kurier-HeavyItalic] [kurierhi]
- \stoptypescript
-
- \starttypescript [sans] [kurier-light] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Kurier-Light-Regular]
- \definefontsynonym [SansItalic] [Kurier-Light-Italic]
- \definefontsynonym [SansBold] [Kurier-Medium-Regular]
- \definefontsynonym [SansBoldItalic] [Kurier-Medium-Italic]
- \stoptypescript
-
- \starttypescript [sans] [kurier] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Kurier-Regular]
- \definefontsynonym [SansItalic] [Kurier-Italic]
- \definefontsynonym [SansBold] [Kurier-Bold]
- \definefontsynonym [SansBoldItalic] [Kurier-BoldItalic]
- \stoptypescript
-
- \starttypescript [sans] [kurier-medium] [name]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [Kurier-Medium-Regular]
- \definefontsynonym [SansItalic] [Kurier-Medium-Italic]
- \definefontsynonym [SansBold] [Kurier-Heavy-Regular]
- \definefontsynonym [SansBoldItalic] [Kurier-Heavy-Italic]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[symbols]
-
- \starttypescript
- \definefontsynonym [ZapfDingbats] [\s!file:uzdr][goodies=dingbats]
- \definefontsynonym [RalfSmithFormalScript] [rsfs10]
- \definefontsynonym [MartinVogel] [\s!file:marvosym.ttf]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[charter]
-
- \starttypescript [serif] [charter]
- \definefontsynonym [Charter-Roman] [\s!name:CharterBT-Roman]
- \definefontsynonym [Charter-Italic] [\s!name:CharterBT-Italic]
- \definefontsynonym [Charter-Bold] [\s!name:CharterBT-Bold]
- \definefontsynonym [Charter-BoldItalic] [\s!name:CharterBT-BoldItalic]
- \definefontsynonym [Charter-Slanted] [\s!name:CharterBT-Italic]
- \definefontsynonym [Charter-BoldSlanted] [\s!name:CharterBT-BoldItalic]
- \definefontsynonym [Charter-Roman-Caps] [Charter-Roman]
- \stoptypescript
-
- \starttypescript [serif] [charter] [name]
- \definefontsynonym [Serif] [Charter-Roman]
- \definefontsynonym [SerifItalic] [Charter-Italic]
- \definefontsynonym [SerifBold] [Charter-Bold]
- \definefontsynonym [SerifBoldItalic] [Charter-BoldItalic]
- \definefontsynonym [SerifSlanted] [Charter-Slanted]
- \definefontsynonym [SerifBoldSlanted] [Charter-BoldSlanted]
- \definefontsynonym [SerifCaps] [Charter-Roman-Caps]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[mathtimes]
-
- \starttypescript [math] [mathtimes] [all]
- \loadfontgoodies[mathtimes-math]
- \definefontsynonym[MathRoman][mathtimes@mathtimes-math]
- \stoptypescript
-
- \starttypescript [mathtimes]
- \definetypeface [mathtimes] [rm] [serif] [times] [default]
- \definetypeface [mathtimes] [ss] [sans] [helvetica] [default] [rscale=0.9]
- \definetypeface [mathtimes] [tt] [mono] [modern] [default] [rscale=1.05]
- \definetypeface [mathtimes] [mm] [math] [mathtimes] [default]
- \quittypescriptscanning
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[lucida]
-
- \starttypescript [serif] [lucida]
- \definefontsynonym [LucidaBright] [\s!name:LucidaBright]
- \definefontsynonym [LucidaBright-Demi] [\s!name:LucidaBright-Demi]
- \definefontsynonym [LucidaBright-Italic] [\s!name:LucidaBright-Italic]
- \definefontsynonym [LucidaBright-DemiItalic] [\s!name:LucidaBright-DemiItalic]
- \definefontsynonym [LucidaBright-Oblique] [\s!name:LucidaBright-Oblique]
- \definefontsynonym [LucidaBrightSmallcaps] [\s!name:LucidaBrightSmallcaps]
- \definefontsynonym [LucidaBrightSmallcaps-Demi] [\s!name:LucidaBrightSmallcaps-Demi]
- \stoptypescript
-
- \starttypescript [sans] [lucida]
- \definefontsynonym [LucidaSans] [\s!name:LucidaSans]
- \definefontsynonym [LucidaSans-Demi] [\s!name:LucidaSans-Demi]
- \definefontsynonym [LucidaSans-Bold] [\s!name:LucidaSans-Bold]
- \definefontsynonym [LucidaSans-Italic] [\s!name:LucidaSans-Italic]
- \definefontsynonym [LucidaSans-DemiItalic] [\s!name:LucidaSans-DemiItalic]
- \definefontsynonym [LucidaSans-BoldItalic] [\s!name:LucidaSans-BoldItalic]
- \stoptypescript
-
- \starttypescript [mono] [lucida]
- \definefontsynonym [LucidaTypewriter] [\s!name:LucidaTypewriter]
- \definefontsynonym [LucidaTypewriterBold] [\s!name:LucidaTypewriterBold]
- \definefontsynonym [LucidaTypewriterOblique] [\s!name:LucidaTypewriterOblique]
- \definefontsynonym [LucidaTypewriterBoldOblique] [\s!name:LucidaTypewriterBoldOblique]
- \stoptypescript
-
- \starttypescript [mono] [lucida]
- \definefontsynonym [LucidaSans-Typewriter] [\s!name:LucidaSans-Typewriter]
- \definefontsynonym [LucidaSans-TypewriterBold] [\s!name:LucidaSans-TypewriterBold]
- \definefontsynonym [LucidaSans-TypewriterOblique] [\s!name:LucidaSans-TypewriterOblique]
- \definefontsynonym [LucidaSans-TypewriterBoldOblique] [\s!name:LucidaSans-TypewriterBoldOblique]
- \stoptypescript
-
- \starttypescript [calligraphy] [lucida]
- \definefontsynonym [LucidaCalligraphy-Italic] [\s!name:LucidaCalligraphy-Italic]
- \stoptypescript
-
- \starttypescript [casual] [lucida]
- \definefontsynonym [LucidaCasual] [\s!name:LucidaCasual]
- \definefontsynonym [LucidaCasual-Italic] [\s!name:LucidaCasual-Italic]
- \stoptypescript
-
- \starttypescript [handwriting] [lucida]
- \definefontsynonym [LucidaHandwriting-Italic] [\s!name:LucidaHandwriting-Italic]
- \stoptypescript
-
- \starttypescript [fax] [lucida]
- \definefontsynonym [LucidaFax] [\s!name:LucidaFax]
- \definefontsynonym [LucidaFax-Demi] [\s!name:LucidaFax-Demi]
- \definefontsynonym [LucidaFax-Italic] [\s!name:LucidaFax-Italic]
- \definefontsynonym [LucidaFax-DemiItalic] [\s!name:LucidaFax-DemiItalic]
- \stoptypescript
-
- \starttypescript [blackletter] [lucida]
- \definefontsynonym [LucidaBlackletter] [\s!name:LucidaBlackletter]
- \stoptypescript
-
- \starttypescript [math] [lucida]
- \loadfontgoodies[lucida-math]
- \definefontsynonym[MathRoman][lucidamath@lucida-math]
- \stoptypescript
-
- \starttypescript [serif] [lucida] [name]
- \definefontsynonym [Serif] [LucidaBright]
- \definefontsynonym [SerifBold] [LucidaBright-Demi]
- \definefontsynonym [SerifItalic] [LucidaBright-Italic]
- \definefontsynonym [SerifBoldItalic] [LucidaBright-DemiItalic]
- \definefontsynonym [SerifSlanted] [LucidaBright-Oblique]
- \definefontsynonym [SerifBoldSlanted] [LucidaBright-DemiItalic]
- \definefontsynonym [SerifCaps] [LucidaBrightSmallcaps]
- \definefontsynonym [SerifBoldCaps] [LucidaBrightSmallcaps-Demi]
- \stoptypescript
-
- % Lucida Bright Sans
-
- \starttypescript [sans] [lucida] [name]
- \definefontsynonym [Sans] [LucidaSans]
- \definefontsynonym [SansBold] [LucidaSans-Demi]
- \definefontsynonym [SansItalic] [LucidaSans-Italic]
- \definefontsynonym [SansBoldItalic] [LucidaSans-DemiItalic]
- \definefontsynonym [SansSlanted] [LucidaSans-Italic]
- \definefontsynonym [SansBoldSlanted] [LucidaSans-DemiItalic]
- \definefontsynonym [SansCaps] [LucidaSans]
- \stoptypescript
-
- % Lucida Bright Sans Typewriter
-
- \starttypescript [mono] [lucida] [name]
- \definefontsynonym [Mono] [LucidaSans-Typewriter]
- \definefontsynonym [MonoBold] [LucidaSans-TypewriterBold]
- \definefontsynonym [MonoItalic] [LucidaSans-TypewriterOblique]
- \definefontsynonym [MonoBoldItalic] [LucidaSans-TypewriterBoldOblique]
- \definefontsynonym [MonoSlanted] [LucidaSans-TypewriterOblique]
- \definefontsynonym [MonoBoldSlanted] [LucidaSans-TypewriterBoldOblique]
- \definefontsynonym [MonoCaps] [LucidaSans-Typewriter]
- \stoptypescript
-
- % Lucida Calligraphy
-
- \starttypescript [calligraphy] [lucida] [name]
- \definefontsynonym [Calligraphy] [LucidaCalligraphy-Italic]
- \stoptypescript
-
- % Lucida Handwriting
-
- \starttypescript [handwriting] [lucida] [name]
- \definefontsynonym [Handwriting] [LucidaHandwriting-Italic]
- \stoptypescript
-
- \starttypescript [lucida]
- \definetypeface [lucida] [rm] [\s!serif] [lucida] [\s!default] [\s!features=\s!default]
- \definetypeface [lucida] [ss] [\s!sans] [lucida] [\s!default] [\s!features=\s!default]
- \definetypeface [lucida] [tt] [\s!mono] [lucida] [\s!default] [\s!features=\s!none]
- \definetypeface [lucida] [hw] [\s!handwriting] [lucida] [\s!default] [\s!features=\s!default]
- \definetypeface [lucida] [cg] [\s!calligraphy] [lucida] [\s!default] [\s!features=\s!default]
- \definetypeface [lucida] [mm] [\s!math] [lucida] [\s!default]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection [mathdesign]
-
- \starttypescript [math] [charter,mathdesignch] [all]
- \loadfontgoodies[charter-math]
- \definefontsynonym[MathRoman][chartermath@charter-math]
- \stoptypescript
-
- \starttypescript [math] [garamond,mathdesigngm] [all]
- \loadfontgoodies[garamond-math]
- \definefontsynonym[MathRoman][garamondmath@garamond-math]
- \stoptypescript
-
- \starttypescript [math] [utopia,mathdesignut] [all]
- \loadfontgoodies[utopia-math]
- \definefontsynonym[MathRoman][utopiamath@utopia-math]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection [asanamath]
-
- \starttypescript [math] [asana]
- \definefontsynonym [AsanaMath] [\s!name:asanamath]
- \stoptypescript
-
- \starttypescript [math] [asana] [name]
- \loadfontgoodies[asana-math]
- \definefontsynonym [MathRoman] [AsanaMath] [\s!features=\s!math\mathsizesuffix,\s!goodies=asana-math]
- \stoptypescript
-
- \starttypescript[asana]
- \definetypeface [\typescriptone] [rm] [\s!serif] [palatino] [\s!default]
- \definetypeface [\typescriptone] [ss] [\s!sans] [modern] [\s!default] [\s!rscale=1.075]
- \definetypeface [\typescriptone] [tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.075]
- \definetypeface [\typescriptone] [mm] [\s!math] [\typescriptone] [\s!default]
- \quittypescriptscanning
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[cleartype]
-
- % microsoft: cambria.ttc cambriab.ttf cambriai.ttf cambriaz.ttf
- % ascender : cambmath.ttf cambria.ttf cambriab.ttf cambriai.ttf cambriaz.ttf
-
- \starttypescript [math,serif] [cambria,cambria-x,cambria-y]
- % whatever matches
- \definefontsynonym [CambriaMath] [\s!name:cambriamath]
- \definefontsynonym [CambriaSerif] [\s!name:cambria]
- \stoptypescript
- \starttypescript [math,serif] [cambria-m]
- % microsoft cabria
- \definefontsynonym [CambriaMath] [\s!file:cambria.ttc(Cambria Math)]
- \definefontsynonym [CambriaSerif] [\s!file:cambria.ttc(Cambria)]
- \stoptypescript
- \starttypescript [math,serif] [cambria-a]
- % ascender cambria
- \definefontsynonym [CambriaMath] [\s!file:cambmath.ttf]
- \definefontsynonym [CambriaSerif] [\s!file:cambria.ttf]
- \stoptypescript
-
- \starttypescript [math] [cambria,cambria-m,cambria-a] [name]
- \loadfontgoodies[cambria-math]
- \definefontsynonym [MathRoman] [CambriaMath] [\s!features=\s!math\mathsizesuffix]
- \stoptypescript
- \starttypescript [math] [cambria-x] [name]
- \loadfontgoodies[cambria-math]
- \definefontsynonym [MathRoman] [CambriaMath] [\s!features=\s!math]
- \stoptypescript
- \starttypescript [math] [cambria-y] [name]
- \loadfontgoodies[cambria-math]
- \definefontsynonym [MathRoman] [CambriaMath] [\s!features=\s!math-nostack\mathsizesuffix]
- \stoptypescript
-
- \starttypescript [serif] [cambria,cambria-m,cambria-a] [name]
- \setups[\s!font:\s!fallback:\s!serif]
- \definefontsynonym [\s!Serif] [CambriaSerif] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBold] [\s!name:cambriabold] [\s!features=\s!default]
- \definefontsynonym [\s!SerifItalic] [\s!name:cambriaitalic] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBoldItalic] [\s!name:cambriabolditalic] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [cambria,cambria-m,cambria-a]
- % any
- \definetypeface [cambria] [rm] [\s!serif] [\typescriptone] [\s!default]
- \definetypeface [cambria] [tt] [\s!mono] [modern] [\s!default]
- \definetypeface [cambria] [mm] [\s!math] [\typescriptone] [\s!default]
- \stoptypescript
- \starttypescript [cambria-x,cambria-y]
- % test x
- \definetypeface [\typescriptone] [rm] [\s!serif] [cambria] [\s!default]
- \definetypeface [\typescriptone] [tt] [\s!mono] [modern] [\s!default]
- \definetypeface [\typescriptone] [mm] [\s!math] [\typescriptone] [\s!default]
- \stoptypescript
-
- \starttypescript [sans] [candara] [name]
- \setups[\s!font:\s!fallback:\s!sans]
- \definefontsynonym [\s!Sans] [\s!file:candara] [\s!features=\s!default]
- \definefontsynonym [\s!SansBold] [\s!file:candarab] [\s!features=\s!default]
- \definefontsynonym [\s!SansItalic] [\s!file:candarai] [\s!features=\s!default]
- \definefontsynonym [\s!SansBoldItalic] [\s!file:candaraz] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [mono] [consolas] [name]
- \setups[\s!font:\s!fallback:\s!mono]
- \definefontsynonym [\s!Mono] [\s!file:consola] [\s!features=\s!none]
- \definefontsynonym [\s!MonoBold] [\s!file:consolab] [\s!features=\s!none]
- \definefontsynonym [\s!MonoItalic] [\s!file:consolai] [\s!features=\s!none]
- \definefontsynonym [\s!MonoBoldItalic] [\s!file:consolaz] [\s!features=\s!none]
- \stoptypescript
-
- \starttypescript [serif] [constantia] [name]
- \setups[\s!font:\s!font:\s!fallback:\s!serif]
- \definefontsynonym [\s!Serif] [\s!file:constan] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBold] [\s!file:constanb] [\s!features=\s!default]
- \definefontsynonym [\s!SerifItalic] [\s!file:constani] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBoldItalic] [\s!file:constanz] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [sans] [corbel] [name]
- \setups[\s!font:\s!fallback:\s!sans]
- \definefontsynonym [\s!Sans] [\s!file:corbel] [\s!features=\s!default]
- \definefontsynonym [\s!SansBold] [\s!file:corbelb] [\s!features=\s!default]
- \definefontsynonym [\s!SansItalic] [\s!file:corbeli] [\s!features=\s!default]
- \definefontsynonym [\s!SansBoldItalic] [\s!file:corbelz] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [sans] [calibri] [name]
- \setups[\s!font:\s!fallback:\s!sans]
- \definefontsynonym [\s!Sans] [\s!file:calibri] [\s!features=\s!default]
- \definefontsynonym [\s!SansBold] [\s!file:calibrib] [\s!features=\s!default]
- \definefontsynonym [\s!SansItalic] [\s!file:calibrii] [\s!features=\s!default]
- \definefontsynonym [\s!SansBoldItalic] [\s!file:calibriz] [\s!features=\s!default]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[mscore]
-
- % .ttf not really needed but we want to force the originals
-
- \starttypescript [serif] [mscoretimes] [name]
- \setups[\s!font:\s!fallback:\s!serif]
- \definefontsynonym [\s!Serif] [\s!file:times.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBold] [\s!file:timesbd.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SerifItalic] [\s!file:timesi.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBoldItalic] [\s!file:timesbi.ttf] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [sans] [mscorearial] [name]
- \setups[\s!font:\s!fallback:\s!sans]
- \definefontsynonym [\s!Sans] [\s!file:arial.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SansBold] [\s!file:arialbd.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SansItalic] [\s!file:ariali.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SansBoldItalic] [\s!file:arialbi.ttf] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [mono] [mscorecourier] [name]
- \setups[\s!font:\s!fallback:\s!mono]
- \definefontsynonym [\s!Mono] [\s!file:cour.ttf] [\s!features=\s!none]
- \definefontsynonym [\s!MonoBold] [\s!file:courbd.ttf] [\s!features=\s!none]
- \definefontsynonym [\s!MonoItalic] [\s!file:couri.ttf] [\s!features=\s!none]
- \definefontsynonym [\s!MonoBoldItalic] [\s!file:courbi.ttf] [\s!features=\s!none]
- \stoptypescript
-
- \starttypescript [sans] [mscoreverdana] [name]
- \setups[\s!font:\s!fallback:\s!sans]
- \definefontsynonym [\s!Sans] [\s!file:verdana.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SansBold] [\s!file:verdanab.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SansItalic] [\s!file:verdanai.ttf] [\s!features=\s!default]
- \definefontsynonym [\s!SansBoldItalic] [\s!file:verdanaz.ttf] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript[mscore]
- \definetypeface [mscore] [rm] [serif] [mscoretimes] [default]
- \definetypeface [mscore] [ss] [sans] [mscorearial] [default] [\s!rscale=0.860]
- \definetypeface [mscore] [tt] [mono] [mscorecourier] [default] [\s!rscale=1.065]
- \definetypeface [mscore] [mm] [math] [times] [default] [\s!rscale=1.020]
- \stoptypescript
-
- % \starttypescript[mscoress]
- % \definetypeface [mscoress] [ss] [sans] [mscorearial] [default]
- % \definetypeface [mscoress] [rm] [serif] [mscoretimes] [default] [rscale=1.160]
- % \definetypeface [mscoress] [tt] [mono] [mscorecourier] [default] [rscale=1.240]
- % \definetypeface [mscoress] [mm] [math] [times] [default] [rscale=1.185]
- % \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[liberation]
-
- \starttypescript [serif] [liberation] [name]
- \setups[\s!font:\s!fallback:\s!serif]
- \definefontsynonym [\s!Serif] [\s!file:liberationserif-regular] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBold] [\s!file:liberationserif-bold] [\s!features=\s!default]
- \definefontsynonym [\s!SerifItalic] [\s!file:liberationserif-italic] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBoldItalic] [\s!file:liberationserif-bolditalic] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [sans] [liberation] [name]
- \setups[\s!font:\s!fallback:\s!sans]
- \definefontsynonym [\s!Sans] [\s!file:liberationsans-regular] [\s!features=\s!default]
- \definefontsynonym [\s!SansBold] [\s!file:liberationsans-bold] [\s!features=\s!default]
- \definefontsynonym [\s!SansItalic] [\s!file:liberationsans-italic] [\s!features=\s!default]
- \definefontsynonym [\s!SansBoldItalic] [\s!file:liberationsans-bolditalic] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [mono] [liberation] [name]
- \setups[\s!font:\s!fallback:\s!mono]
- \definefontsynonym [\s!Mono] [\s!file:liberationmono-regular] [\s!features=\s!none]
- \definefontsynonym [\s!MonoBold] [\s!file:liberationmono-bold] [\s!features=\s!none]
- \definefontsynonym [\s!MonoItalic] [\s!file:liberationmono-italic] [\s!features=\s!none]
- \definefontsynonym [\s!MonoBoldItalic] [\s!file:liberationmono-bolditalic] [\s!features=\s!none]
- \stoptypescript
-
- \starttypescript[liberation]
- \definetypeface [liberation] [rm] [serif] [liberation] [default]
- \definetypeface [liberation] [ss] [sans] [liberation] [default] [\s!rscale=0.870]
- \definetypeface [liberation] [tt] [mono] [liberation] [default] [\s!rscale=0.870]
- \definetypeface [liberation] [mm] [math] [times] [default] [\s!rscale=1.040]
- \stoptypescript
-
-\stoptypescriptcollection
-
-%D For some reason the libertine collection has not retained its
-%D original names. We force the \OPENTYPE\ variant. Once these fonts
-%D are stable we might switch to the by then hopefully cleaner internal
-%D names.
-
-\starttypescriptcollection[libertine]
-
-% \starttypescript [serif] [libertine] [name]
-% \setups[\s!font:\s!fallback:\s!serif]
-% \definefontsynonym [\s!Serif] [\s!file:fxlr.otf] [\s!features=\s!default]
-% \definefontsynonym [\s!SerifBold] [\s!file:fxlb.otf] [\s!features=\s!default]
-% \definefontsynonym [\s!SerifItalic] [\s!file:fxlri.otf] [\s!features=\s!default]
-% \definefontsynonym [\s!SerifBoldItalic] [\s!file:fxlbi.otf] [\s!features=\s!default]
-% \stoptypescript
-
- \starttypescript [serif] [libertine]
- \definefontsynonym [Libertine-Regular] [\s!file:fxlr]
- \definefontsynonym [Libertine-Italic] [\s!file:fxlri]
- \definefontsynonym [Libertine-Bold] [\s!file:fxlb]
- \definefontsynonym [Libertine-BoldItalic] [\s!file:fxlbi]
- \definefontsynonym [Libertine-SmallCaps] [\s!file:fxlr] [\s!features=\s!smallcaps]
- \stoptypescript
-
- \starttypescript [serif] [libertine] [name]
- \setups[\s!font:\s!fallback:\s!serif]
- \definefontsynonym [\s!Serif] [Libertine-Regular] [\s!features=\s!default]
- \definefontsynonym [\s!SerifItalic] [Libertine-Italic] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBold] [Libertine-Bold] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBoldItalic] [Libertine-BoldItalic] [\s!features=\s!default]
- \definefontsynonym [\s!SerifCaps] [Libertine-Regular] [\s!features=\s!smallcaps]
- \stoptypescript
-
- \starttypescript [sans] [biolinum]
- \setups[\s!font:\s!fallback:\s!sans]
- \definefontsynonym [Biolinum-Regular] [\s!file:fxbr.otf]
- \definefontsynonym [Biolinum-Bold] [\s!file:fxbb.otf]
- \definefontsynonym [Biolinum-Italic] [\s!file:fxbri.otf]
- \definefontsynonym [Biolinum-Slanted] [\s!file:fxbro.otf]
- \definefontsynonym [Biolinum-BoldItalic] [\s!file:fxbbo.otf]
- \stoptypescript
-
- \starttypescript [sans] [biolinum] [name]
- \setups[\s!font:\s!fallback:\s!sans]
- \definefontsynonym [\s!Sans] [Biolinum-Regular] [\s!features=\s!default]
- \definefontsynonym [\s!SansBold] [Biolinum-Bold] [\s!features=\s!default]
- \definefontsynonym [\s!SansItalic] [Biolinum-Italic] [\s!features=\s!default]
- \definefontsynonym [\s!SansSlanted] [Biolinum-Slanted] [\s!features=\s!default]
- \definefontsynonym [\s!SansBoldItalic] [Biolinum-BoldItalic] [\s!features=\s!default]
- \definefontsynonym [\s!SansCaps] [Biolinum-Regular] [\s!features=\s!smallcaps]
- \stoptypescript
-
- \starttypescript [libertine]
- \definetypeface [libertine] [rm] [serif] [libertine] [default]
- \definetypeface [libertine] [ss] [sans] [biolinum] [default]
- \definetypeface [libertine] [tt] [mono] [default] [default]
- %definetypeface [libertine] [mm] [math] [times] [default]
- \quittypescriptscanning
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[inconsolata]
-
- \starttypescript [mono] [inconsolata]
- \definefontsynonym [Inconsolata] [\s!file:inconsolata.otf]
- \stoptypescript
-
- \starttypescript [mono] [inconsolata] [name]
- \setups[\s!font:\s!fallback:\s!mono]
- \definefontsynonym [\s!Mono] [Inconsolata]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[postscript]
-
- \starttypescript [postscript]
- \definetypeface [postscript] [rm] [\s!serif] [times] [\s!default]
- \definetypeface [postscript] [ss] [\s!sans] [helvetica] [\s!default] [\s!rscale=0.9]
- \definetypeface [postscript] [tt] [\s!mono] [courier] [\s!default] [\s!rscale=1.1]
- \definetypeface [postscript] [mm] [\s!math] [times] [\s!default]
- \quittypescriptscanning
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[pagella-euler]
-
- \starttypescript [math] [euler]
- \definefontsynonym [EulerMath] [\s!file:euler.otf]
- \stoptypescript
-
- \starttypescript [math] [euler] [name]
- % \definefontsynonym [MathRoman] [EulerMath] [\s!features=\s!math]
- \definefontsynonym [MathRoman] [EulerMath] [\s!features=\s!math\mathsizesuffix]
- \stoptypescript
-
- \starttypescript [pagella-euler]
- \definetypeface [\typescriptone] [rm] [\s!serif] [pagella] [\s!default]
- % \definetypeface [\typescriptone] [ss] [\s!sans] [pagella] [\s!default]
- \definetypeface [\typescriptone] [tt] [\s!mono] [modern] [\s!default]
- \definetypeface [\typescriptone] [mm] [\s!math] [euler] [\s!default]
- \quittypescriptscanning
- \stoptypescript
-
- \starttypescript [serif] [euler] [name]
- \setups[\s!font:\s!fallback:\s!serif]
- \definefontsynonym [Serif] [\s!file:euler.otf] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript [euler]
- \definetypeface [euler] [rm] [\s!serif] [euler] [\s!default]
- \definetypeface [euler] [tt] [\s!mono] [modern] [\s!default]
- \definetypeface [euler] [mm] [\s!math] [euler] [\s!default]
- \quittypescriptscanning
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[stix]
-
- % This typescript is only provided to keep an eye on developments of this font
- % but currenty these are not proper opentype math fonts (for instance they have
- % no math table yet). We will not make a virtual font for this as eventually
- % there will be a decent version. Beware, we force an otf suffix as there happen
- % to be ttf files as well. BTW, why 'italic' infull and 'bol' without 'd'?
-
- \starttypescript [math] [stix] [name]
- \definefontsynonym[MathRoman][\s!file:stixgeneral.otf] [\s!features=\s!math]
- \stoptypescript
-
- \starttypescript [serif] [stix] [name]
- \setups[\s!font:\s!fallback:\s!serif]
- \definefontsynonym[\s!Serif] [\s!file:stixgeneral.otf] [\s!features=\s!default]
- \definefontsynonym[\s!SerifBold] [\s!file:stixgeneralbol.otf] [\s!features=\s!default]
- \definefontsynonym[\s!SerifItalic] [\s!file:stixgeneralitalic.otf] [\s!features=\s!default]
- \definefontsynonym[\s!SerifBoldItalic][\s!file:stixgeneralbolita.otf] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript[stix]
- \definetypeface [stix] [rm] [\s!serif] [stix] [\s!default]
- \definetypeface [stix] [mm] [\s!math] [stix] [\s!default]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[xits]
-
- % This one makes more sense. Xits uses the glyph collection from stix but packages
- % it in a proper OpenType Math font. From the Stix site: Version 1.1, which will
- % include fonts packaged for use with Microsoft Office applications, is scheduled
- % for release by the end of 2010. Version 1.2, which will include Type 1 fonts for
- % use with LaTeX, will follow in 2011. So, we are on our own anyway.
-
- \starttypescript [math] [xits] [name]
- \definefontsynonym[MathRoman][\s!file:xits-math.otf][\s!features=\s!math\mathsizesuffix,\s!goodies=xits-math]
- \stoptypescript
-
- \starttypescript [serif] [xits] [name]
- \setups[\s!font:\s!fallback:\s!serif]
- \definefontsynonym[\s!Serif] [\s!file:xits-regular.otf] [\s!features=\s!default]
- \definefontsynonym[\s!SerifBold] [\s!file:xits-bold.otf] [\s!features=\s!default]
- \definefontsynonym[\s!SerifItalic] [\s!file:xits-italic.otf] [\s!features=\s!default]
- \definefontsynonym[\s!SerifBoldItalic][\s!file:xits-bolditalic.otf] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript[xits]
- \definetypeface [xits] [rm] [\s!serif] [xits] [\s!default]
- \definetypeface [xits] [ss] [\s!sans] [heros] [\s!default] [\s!rscale=0.9]
- \definetypeface [xits] [tt] [\s!mono] [modern] [\s!default] [\s!rscale=1.05]
- \definetypeface [xits] [mm] [\s!math] [xits] [\s!default]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[punk]
-
- \definefontfeature [punknova] [mode=node,script=latn,rand=yes,kern=yes,liga=yes,tlig=yes]
- \definefontfeature [punknova-slanted] [punknova] [slant=.25]
-
- \starttypescript [serif] [punknova]
- \definefontsynonym [Serif] [\s!file:punknova-regular] [\s!features=punknova]
- \definefontsynonym [SerifSlanted] [\s!file:punknova-regular] [\s!features=punknova-slanted]
- \definefontsynonym [SerifBold] [\s!file:punknova-bold] [\s!features=punknova]
- \definefontsynonym [SerifBoldSlanted][\s!file:punknova-bold] [\s!features=punknova-slanted]
- \definefontsynonym [SerifItalic] [SerifSlanted]
- \definefontsynonym [SerifBoldItalic] [SerifBoldSlanted]
- \stoptypescript
-
- % \definefontfeature [slanted-25] [slant=.25]
- % \starttypescript [serif] [punknova]
- % \definefontsynonym [SerifSlanted] [\s!file:punknova-regular] [\s!features={punknova,slanted-25}]
- % \stoptypescript
-
- \starttypescript [punknova]
- \definetypeface [punknova] [rm] [serif] [punknova] [default]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[hvmath]
-
- \starttypescript [math] [hvmath]
- \definefontsynonym[MathRoman][hvmath@hvmath-math]
- \loadfontgoodies[hvmath-math]
- \stoptypescript
-
- \starttypescript [hvmath]
- \definetypeface [hvmath] [ss] [sans] [heros] [default] [rscale=0.9]
- \definetypeface [hvmath] [rm] [serif] [termes] [default]
- \definetypeface [hvmath] [tt] [mono] [cursor] [default] [rscale=1.05]
- \definetypeface [hvmath] [mm] [math] [hvmath] [default]
- \stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[computer-modern-unicode]
-
- \starttypescript [serif,sans,mono] [computer-modern-unicode]
- \definefontsynonym [\s!Serif] [\s!file:cmunrm] [\s!features=\s!default]
- \definefontsynonym [\s!SerifItalic] [\s!file:cmunti] [\s!features=\s!default]
- \definefontsynonym [\s!SerifSlanted] [\s!file:cmunsl] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBold] [\s!file:cmunbx] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBoldItalic] [\s!file:cmunbi] [\s!features=\s!default]
- \definefontsynonym [\s!Sans] [\s!file:cmunss] [\s!features=\s!default]
- \definefontsynonym [\s!SansItalic] [\s!file:cmunsi] [\s!features=\s!default]
- \definefontsynonym [\s!SansBold] [\s!file:cmunsx] [\s!features=\s!default]
- \definefontsynonym [\s!SansBoldItalic] [\s!file:cmunso] [\s!features=\s!default]
- \definefontsynonym [\s!Mono] [\s!file:cmuntt] [\s!features=\s!none]
- \definefontsynonym [\s!MonoItalic] [\s!file:cmunit] [\s!features=\s!none]
- \definefontsynonym [\s!MonoSlanted] [\s!file:cmunst] [\s!features=\s!none]
- \definefontsynonym [\s!MonoBold] [\s!file:cmuntb] [\s!features=\s!none]
- \definefontsynonym [\s!MonoBoldItalic] [\s!file:cmuntx] [\s!features=\s!none]
- \stoptypescript
-
- \starttypescript [serif] [computer-modern-unicode-concrete]
- \definefontsynonym [\s!Serif] [\s!file:cmunorm] [\s!features=\s!default]
- \definefontsynonym [\s!SerifItalic] [\s!file:cmunoti] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBold] [\s!file:cmunobx] [\s!features=\s!default]
- \definefontsynonym [\s!SerifBoldItalic] [\s!file:cmunobi] [\s!features=\s!default]
- \stoptypescript
-
- \starttypescript[computer-modern-unicode]
- \definetypeface[computer-modern-unicode][rm][\s!serif][computer-modern-unicode][\s!default]
- \definetypeface[computer-modern-unicode][ss][\s!sans] [computer-modern-unicode][\s!default]
- \definetypeface[computer-modern-unicode][tt][\s!mono] [computer-modern-unicode][\s!default]
- \definetypeface[computer-modern-unicode][mm][\s!math] [modern] [\s!default]
- \stoptypescript
-
-\stoptypescriptcollection
+%D \starttyping
+%D \setupfontsynonym [LMRoman10-DemiOblique] [features=default]
+%D \definefontsynonym [LMRoman10-DemiOblique] [\s!name:LMRoman10-DemiOblique] [features=default]
+%D \definefontsynonym [LMRoman10-DemiOblique] [lmroman10-demioblique] [features=default]
+%D \stoptyping
+%D
+%D This file is no longer used. When going from \MKII\ to \MKIV\ quite some typescripts
+%D were collected here but now they are nicely distributed over files and a semi-automatic
+%D loaded takes care of finding the right ones. This also benefits for instance alternative
+%D loaders (like simplefonts).
\endinput
diff --git a/Master/texmf-dist/tex/context/base/type-pre.mkii b/Master/texmf-dist/tex/context/base/type-pre.mkii
index ad2109a65ca..99db52c2fad 100644
--- a/Master/texmf-dist/tex/context/base/type-pre.mkii
+++ b/Master/texmf-dist/tex/context/base/type-pre.mkii
@@ -5,7 +5,7 @@
%D subtitle=Compatibility scripts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-run.mkii b/Master/texmf-dist/tex/context/base/type-run.mkii
index 1b64c102ec6..51a9f2a885d 100644
--- a/Master/texmf-dist/tex/context/base/type-run.mkii
+++ b/Master/texmf-dist/tex/context/base/type-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-run.mkiv b/Master/texmf-dist/tex/context/base/type-run.mkiv
index 60061bcbe9e..4da633371d9 100644
--- a/Master/texmf-dist/tex/context/base/type-run.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-run.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Runtime Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-set.mkii b/Master/texmf-dist/tex/context/base/type-set.mkii
index 2845b1dbbee..7f34deadaad 100644
--- a/Master/texmf-dist/tex/context/base/type-set.mkii
+++ b/Master/texmf-dist/tex/context/base/type-set.mkii
@@ -5,7 +5,7 @@
%D subtitle=Default Settings,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-set.mkiv b/Master/texmf-dist/tex/context/base/type-set.mkiv
index a67be14af41..99c38bc5d0f 100644
--- a/Master/texmf-dist/tex/context/base/type-set.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-set.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Default Settings,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,65 +13,74 @@
\unprotect
-\definetypescriptprefix [serif] [Serif]
-\definetypescriptprefix [sans] [Sans]
-\definetypescriptprefix [mono] [Mono]
-
-\definefontsynonym [DefaultFont] [\s!file:lmmonoprop10-regular] % was cmvtt10
-
-\startsetups [font:fallback:serif]
- \definefontsynonym [Serif] [DefaultFont]
- \definefontsynonym [SerifBold] [Serif]
- \definefontsynonym [SerifItalic] [Serif]
- \definefontsynonym [SerifSlanted] [SerifItalic]
- \definefontsynonym [SerifBoldItalic] [Serif]
- \definefontsynonym [SerifBoldSlanted] [SerifBoldItalic]
- \definefontsynonym [SerifCaps] [Serif]
-\stopsetups
-
-\startsetups [font:fallback:sans]
- \definefontsynonym [Sans] [DefaultFont]
- \definefontsynonym [SansBold] [Sans]
- \definefontsynonym [SansItalic] [Sans]
- \definefontsynonym [SansSlanted] [SansItalic]
- \definefontsynonym [SansBoldItalic] [Sans]
- \definefontsynonym [SansBoldSlanted] [SansBoldItalic]
- \definefontsynonym [SansCaps] [Sans]
-\stopsetups
-
-\startsetups [font:fallback:mono]
- \definefontsynonym [Mono] [DefaultFont]
- \definefontsynonym [MonoBold] [Mono]
- \definefontsynonym [MonoItalic] [Mono]
- \definefontsynonym [MonoSlanted] [MonoItalic]
- \definefontsynonym [MonoBoldItalic] [Mono]
- \definefontsynonym [MonoBoldSlanted] [MonoBoldItalic]
- \definefontsynonym [MonoCaps] [Mono]
-\stopsetups
-
-\starttypescript [serif,sans,mono] [fallback]
- \setups[\s!font:\s!fallback:\typescriptone]
-\stoptypescript
-
-\startsetups [font:allbold:serif]
- \definefontsynonym [Serif] [SerifBold]
- \definefontsynonym [SerifItalic] [SerifBoldItalic]
- \definefontsynonym [SerifSlanted] [SerifBoldSlanted]
- %definefontsynonym [SerifCaps] [SerifBold]
-\stopsetups
-
-\startsetups [font:allbold:sans]
- \definefontsynonym [Sans] [SansBold]
- \definefontsynonym [SansItalic] [SansBoldItalic]
- \definefontsynonym [SansSlanted] [SansBoldSlanted]
- %definefontsynonym [SansCaps] [SansBold]
-\stopsetups
-
-%usetypescriptfile[def] % preloaded in main context.mkiv file
-%usetypescriptfile[lua] % preloaded in main context.mkiv file
-%usetypescriptfile[tmf] % replaced by otf (mkiv) en one (mkii)
-\usetypescriptfile[siz]
-\usetypescriptfile[otf]
-\usetypescriptfile[loc]
+\ifnum\typescriptstate=\plustwo
+
+ % store
+
+ \loadmarkfile{type-def}
+ \loadmarkfile{type-lua}
+ \loadmarkfile{type-siz}
+ \loadmarkfile{type-fbk}
+
+ % \loadtypescriptfile[def] % meant for local usage only
+ % \loadtypescriptfile[lua] % meant for local usage only
+ % \loadtypescriptfile[siz] % meant for local usage only
+ \loadmarkfile{type-imp-latinmodern}
+ % \usetypescriptfile[latinmodern]
+ \usetypescriptfile[loc]
+
+ % We want these names preset but they conflict with later loads so from now on
+ % one has to define a proper typeface if they are needed.
+ %
+ % \usetypescript[serif,sans,mono,math] [latin-modern]
+
+\else
+
+ \usetypescriptfile[def]
+ \usetypescriptfile[fbk]
+ \usetypescriptfile[lua]
+ \usetypescriptfile[siz]
+ \usetypescriptfile[otf]
+ \usetypescriptfile[loc]
+
+\fi
+
+\definefilesynonym [type-imp-lucida.mkiv] [type-imp-lucida-typeone.mkiv]
+\definefilesynonym [type-imp-lucidanova.mkiv] [type-imp-lucida-opentype.mkiv]
+\definefilesynonym [type-imp-lucidaot.mkiv] [type-imp-lucida-opentype.mkiv]
+
+\definefilesynonym [type-imp-palatino.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-courier.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-avantgarde.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-helvetica.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-chancery.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-bookman.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-schoolbook.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-times.mkiv] [type-imp-texgyre.mkiv]
+
+\definefilesynonym [type-imp-cursor.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-adventor.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-heros.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-chorus.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-bonum.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-schola.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-pagella.mkiv] [type-imp-texgyre.mkiv]
+\definefilesynonym [type-imp-termes.mkiv] [type-imp-texgyre.mkiv]
+
+\definefilesynonym [type-imp-mscoretimes.mkiv] [type-imp-mscore.mkiv]
+\definefilesynonym [type-imp-mscorearial.mkiv] [type-imp-mscore.mkiv]
+\definefilesynonym [type-imp-mscorecourier.mkiv] [type-imp-mscore.mkiv]
+\definefilesynonym [type-imp-mscoreverdana.mkiv] [type-imp-mscore.mkiv]
+
+\definefilesynonym [type-imp-candara.mkiv] [type-imp-cleartype.mkiv]
+\definefilesynonym [type-imp-consolas.mkiv] [type-imp-cleartype.mkiv]
+\definefilesynonym [type-imp-constantia.mkiv] [type-imp-cleartype.mkiv]
+\definefilesynonym [type-imp-corbel.mkiv] [type-imp-cleartype.mkiv]
+\definefilesynonym [type-imp-calibri.mkiv] [type-imp-cleartype.mkiv]
+
+\definefilesynonym [type-imp-antykwa-poltawskiego.mkiv] [type-imp-antykwapoltawskiego.mkiv]
+
+%definefilesynonym [type-imp-mac.mkiv] [type-imp-osx.mkiv]
+%definefilesynonym [type-imp-win.mkiv] [type-imp-mscore.mkiv]
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/type-siz.mkii b/Master/texmf-dist/tex/context/base/type-siz.mkii
index 831019e9598..4c3cfb28b0e 100644
--- a/Master/texmf-dist/tex/context/base/type-siz.mkii
+++ b/Master/texmf-dist/tex/context/base/type-siz.mkii
@@ -5,7 +5,7 @@
%D subtitle=Sizing scripts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-siz.mkiv b/Master/texmf-dist/tex/context/base/type-siz.mkiv
index 35bc8fb4446..d4c90b18229 100644
--- a/Master/texmf-dist/tex/context/base/type-siz.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-siz.mkiv
@@ -5,394 +5,165 @@
%D subtitle=Sizing scripts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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.
-\starttypescriptcollection[size]
+\unprotect
-\starttypescript [serif] [default] [size]
- \definebodyfont
- [4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [rm] [default]
-\stoptypescript
+% beware: no \s! before keys as these are interpreted
-\starttypescript [sans] [default] [size]
+\starttypescriptcollection[\s!size]
+
+\starttypescript [\s!serif] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [ss] [default]
+ [\s!rm] [\s!default]
\stoptypescript
-\starttypescript [mono] [default] [size]
+\starttypescript [\s!sans] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [tt] [default]
+ [\s!ss] [\s!default]
\stoptypescript
-\starttypescript [math,boldmath] [default] [size]
+\starttypescript [\s!mono] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [mm] [default]
+ [\s!tt] [\s!default]
\stoptypescript
-\starttypescript [bfmath] [default] [size]
+\starttypescript [\s!math] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [mm] [bfmath]
+ [\s!mm] [\s!default]
\stoptypescript
-\starttypescript [handwriting] [default] [size]
+\starttypescript [\s!handwriting] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [hw] [default]
+ [\s!hw] [\s!default]
\stoptypescript
-\starttypescript [calligraphy] [default] [size]
+\starttypescript [\s!calligraphy] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [cg] [default]
+ [\s!cg] [\s!default]
\stoptypescript
-\starttypescript [casual] [default] [size]
+\starttypescript [\s!casual] [\s!default] [\s!size]
\definebodyfont
[4pt,5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,14.4pt,17.3pt]
- [rm] [default]
+ [\s!rm] [\s!default]
\stoptypescript
-\starttypescript [all] [dtp] [size]
+\starttypescript [\s!all] [\s!dtp] [\s!size]
\definebodyfontenvironment
[4pt]
[\s!text=4pt,\s!script=4pt,\s!scriptscript=4pt,
- \c!x=4pt,\c!xx=4pt,\c!big=6pt,\c!small=4pt]
+ \s!x=4pt,\s!xx=4pt,\v!big=6pt,\v!small=4pt]
\definebodyfontenvironment
[5pt]
[\s!text=5pt,\s!script=5pt,\s!scriptscript=5pt,
- \c!x=5pt,\c!xx=5pt,\c!big=7pt,\c!small=5pt]
+ \s!x=5pt,\s!xx=5pt,\v!big=7pt,\v!small=5pt]
\definebodyfontenvironment
[6pt]
[\s!text=6pt,\s!script=5pt,\s!scriptscript=5pt,
- \c!x=5pt,\c!xx=5pt,\c!big=8pt,\c!small=5pt]
+ \s!x=5pt,\s!xx=5pt,\v!big=8pt,\v!small=5pt]
\definebodyfontenvironment
[7pt]
[\s!text=7pt,\s!script=6pt,\s!scriptscript=5pt,
- \c!x=6pt,\c!xx=5pt,\c!big=9pt,\c!small=5pt]
+ \s!x=6pt,\s!xx=5pt,\v!big=9pt,\v!small=5pt]
\definebodyfontenvironment
[8pt]
[\s!text=8pt,\s!script=6pt,\s!scriptscript=5pt,
- \c!x=6pt,\c!xx=5pt,\c!big=10pt,\c!small=6pt]
+ \s!x=6pt,\s!xx=5pt,\v!big=10pt,\v!small=6pt]
\definebodyfontenvironment
[9pt]
[\s!text=9pt,\s!script=7pt,\s!scriptscript=5pt,
- \c!x=7pt,\c!xx=5pt,\c!big=11pt,\c!small=7pt]
+ \s!x=7pt,\s!xx=5pt,\v!big=11pt,\v!small=7pt]
\definebodyfontenvironment
[10pt]
[\s!text=10pt,\s!script=7pt,\s!scriptscript=5pt,
- \c!x=8pt,\c!xx=6pt,\c!big=12pt,\c!small=8pt]
+ \s!x=8pt,\s!xx=6pt,\v!big=12pt,\v!small=8pt]
\definebodyfontenvironment
[11pt]
[\s!text=11pt,\s!script=8pt,\s!scriptscript=6pt,
- \c!x=9pt,\c!xx=7pt,\c!big=13pt,\c!small=9pt]
+ \s!x=9pt,\s!xx=7pt,\v!big=13pt,\v!small=9pt]
\definebodyfontenvironment
[12pt]
[\s!text=12pt,\s!script=9pt,\s!scriptscript=7pt,
- \c!x=10pt,\c!xx=8pt,\c!big=14pt,\c!small=10pt]
+ \s!x=10pt,\s!xx=8pt,\v!big=14pt,\v!small=10pt]
\definebodyfontenvironment
[13pt]
[\s!text=13pt,\s!script=10pt,\s!scriptscript=8pt,
- \c!x=11pt,\c!xx=9pt,\c!big=16pt,\c!small=11pt]
+ \s!x=11pt,\s!xx=9pt,\v!big=16pt,\v!small=11pt]
\definebodyfontenvironment
[14pt]
[\s!text=14pt,\s!script=10pt,\s!scriptscript=7pt,
- \c!x=12pt,\c!xx=10pt,\c!big=16pt,\c!small=12pt]
+ \s!x=12pt,\s!xx=10pt,\v!big=16pt,\v!small=12pt]
\definebodyfontenvironment
[16pt]
[\s!text=16pt,\s!script=12pt,\s!scriptscript=9pt,
- \c!x=13pt,\c!xx=11pt,\c!big=18pt,\c!small=14pt]
+ \s!x=13pt,\s!xx=11pt,\v!big=18pt,\v!small=14pt]
% suboptimal math sizes
\definebodyfontenvironment
[18pt]
[\s!text=18pt,\s!script=16pt,\s!scriptscript=14pt,
- \c!x=16pt,\c!xx=14pt,\c!big=22pt,\c!small=16pt]
+ \s!x=16pt,\s!xx=14pt,\v!big=22pt,\v!small=16pt]
\definebodyfontenvironment
[22pt]
[\s!text=22pt,\s!script=22pt,\s!scriptscript=18pt,
- \c!x=18pt,\c!xx=16pt,\c!big=28pt,\c!small=18pt]
+ \s!x=18pt,\s!xx=16pt,\v!big=28pt,\v!small=18pt]
\definebodyfontenvironment
[28pt]
[\s!text=28pt,\s!script=22pt,\s!scriptscript=18pt,
- \c!x=22pt,\c!xx=18pt,\c!big=28pt,\c!small=22pt]
+ \s!x=22pt,\s!xx=18pt,\v!big=28pt,\v!small=22pt]
\stoptypescript
-\starttypescript [serif] [dtp] [size]
+\starttypescript [\s!serif] [\s!dtp] [\s!size]
\definebodyfont
[5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
- [rm] [default]
+ [\s!rm] [\s!default]
\stoptypescript
-\starttypescript [sans] [dtp] [size]
+\starttypescript [\s!sans] [\s!dtp] [\s!size]
\definebodyfont
[5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
- [ss] [default]
+ [\s!ss] [\s!default]
\stoptypescript
-\starttypescript [mono] [dtp] [size]
+\starttypescript [\s!mono] [\s!dtp] [\s!size]
\definebodyfont
[5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
- [tt] [default]
+ [\s!tt] [\s!default]
\stoptypescript
-\starttypescript [math,boldmath] [dtp] [size]
+\starttypescript [\s!math] [\s!dtp] [\s!size]
\definebodyfont
[5pt,6pt,7pt,8pt,9pt,10pt,11pt,12pt,13pt,14pt,16pt,18pt,22pt,28pt]
- [mm] [default]
-\stoptypescript
-
-\stoptypescriptcollection
-
-\starttypescriptcollection[size-mkiv]
-
-\starttypescript [serif] [computer-modern] [size]
-
- \definebodyfont [12pt] [rm]
- [tf=LMRoman12-Regular,
- bf=LMRoman12-Bold,
- it=LMRoman12-Italic,
- sl=LMRoman12-Oblique,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [11pt] [rm]
- [tf=LMRoman10-Regular sa 1,
- bf=LMRoman10-Bold sa 1,
- it=LMRoman10-Italic sa 1,
- sl=LMRoman10-Oblique sa 1,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [10pt] [rm]
- [tf=LMRoman10-Regular,
- bf=LMRoman10-Bold,
- it=LMRoman10-Italic,
- sl=LMRoman10-Oblique,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [9pt] [rm]
- [tf=LMRoman9-Regular,
- bf=LMRoman9-Bold,
- it=LMRoman9-Italic,
- sl=LMRoman9-Oblique,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [8pt] [rm]
- [tf=LMRoman8-Regular,
- bf=LMRoman8-Bold,
- it=LMRoman8-Italic,
- sl=LMRoman8-Oblique,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [7pt] [rm]
- [tf=LMRoman7-Regular,
- bf=LMRoman7-Bold,
- it=LMRoman7-Italic sa 1,
- sl=LMRoman8-Oblique sa 1,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [6pt] [rm]
- [tf=LMRoman6-Regular,
- bf=LMRoman6-Bold,
- it=LMRoman7-Italic sa 1,
- sl=LMRoman8-Oblique sa 1,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [5pt] [rm]
- [tf=LMRoman5-Regular,
- bf=LMRoman5-Bold,
- it=LMRoman7-Italic sa 1,
- sl=LMRoman8-Oblique sa 1,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [4pt] [rm]
- [tf=LMRoman5-Regular sa 1,
- bf=LMRoman5-Bold sa 1,
- it=LMRoman7-Italic sa 1,
- sl=LMRoman8-Oblique sa 1,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
- \definebodyfont [14.4pt,17.3pt,20.7pt] [rm]
- [tf=LMRoman12-Regular sa 1,
- bf=LMRoman12-Bold sa 1,
- it=LMRoman12-Italic sa 1,
- sl=LMRoman12-Oblique sa 1,
- bi=LMRoman10-BoldItalic sa 1,
- bs=LMRoman10-BoldOblique sa 1,
- sc=LMRoman10-CapsRegular sa 1]
-
-\stoptypescript
-
-\starttypescript [sans] [computer-modern] [size]
-
- \definebodyfont [12pt] [ss]
- [tf=LMSans12-Regular,
- bf=LMSans10-Bold sa 1,
- it=LMSans12-Oblique,
- sl=LMSans12-Oblique,
- bi=LMSans10-BoldOblique sa 1,
- bs=LMSans10-BoldOblique sa 1,
- sc=LMSans12-Regular]
-
- \definebodyfont [11pt] [ss]
- [tf=LMSans10-Regular sa 1,
- bf=LMSans10-Bold sa 1,
- it=LMSans10-Oblique sa 1,
- sl=LMSans10-Oblique sa 1,
- bi=LMSans10-BoldOblique sa 1,
- bs=LMSans10-BoldOblique sa 1,
- sc=LMSans10-Regular sa 1]
-
- \definebodyfont [10pt] [ss]
- [tf=LMSans10-Regular,
- bf=LMSans10-Bold,
- it=LMSans10-Oblique,
- sl=LMSans10-Oblique,
- bi=LMSans10-BoldOblique,
- bs=LMSans10-BoldOblique,
- sc=LMSans10-Regular]
-
- \definebodyfont [9pt] [ss]
- [tf=LMSans9-Regular,
- bf=LMSans10-Bold sa 1,
- it=LMSans9-Oblique sa 1,
- sl=LMSans9-Oblique sa 1,
- bi=LMSans10-BoldOblique sa 1,
- bs=LMSans10-BoldOblique sa 1,
- sc=LMSans9-Regular]
-
- \definebodyfont [8pt] [ss]
- [tf=LMSans8-Regular,
- bf=LMSans10-Bold sa 1,
- it=LMSans8-Oblique,
- sl=LMSans8-Oblique,
- bi=LMSans10-BoldOblique sa 1,
- bs=LMSans10-BoldOblique sa 1,
- sc=LMSans8-Regular]
-
- \definebodyfont [7pt,6pt,5pt,4pt] [ss]
- [tf=LMSans8-Regular sa 1,
- bf=LMSans10-Bold sa 1,
- it=LMSans8-Oblique sa 1,
- sl=LMSans8-Oblique sa 1,
- bi=LMSans10-BoldOblique sa 1,
- bs=LMSans10-BoldOblique sa 1,
- sc=LMSans8-Regular sa 1]
-
- \definebodyfont [14.4pt,17.3pt,20.7pt] [ss]
- [tf=LMSans12-Regular sa 1,
- bf=LMSans10-Bold sa 1,
- it=LMSans12-Oblique sa 1,
- sl=LMSans12-Oblique sa 1,
- bi=LMSans10-BoldOblique sa 1,
- bs=LMSans10-BoldOblique sa 1,
- sc=LMSans12-Regular sa 1]
-
-\stoptypescript
-
-\starttypescript [mono] [computer-modern] [size]
-
- \definebodyfont [12pt] [tt]
- [tf=LMTypewriter12-Regular,
- it=LMTypewriter10-Italic sa 1,
- sl=LMTypewriter10-Oblique sa 1,
- bf=LMTypewriter10-Dark sa 1,
- bs=LMTypewriter10-DarkOblique sa 1,
- sc=LMTypewriter10-CapsRegular sa 1]
-
- \definebodyfont [9pt] [tt]
- [tf=LMTypewriter9-Regular,
- it=LMTypewriter10-Italic sa 1,
- sl=LMTypewriter10-Oblique sa 1,
- bf=LMTypewriter10-Dark sa 1,
- bs=LMTypewriter10-DarkOblique sa 1,
- sc=LMTypewriter10-CapsRegular sa 1]
-
- \definebodyfont [8pt] [tt]
- [tf=LMTypewriter8-Regular,
- it=LMTypewriter10-Italic sa 1,
- sl=LMTypewriter10-Oblique sa 1,
- bf=LMTypewriter10-Dark sa 1,
- bs=LMTypewriter10-DarkOblique sa 1,
- sc=LMTypewriter10-CapsRegular sa 1]
-
- \definebodyfont [11pt,10pt,7pt,6pt,5pt,4pt] [tt]
- [tf=LMTypewriter10-Regular sa 1,
- it=LMTypewriter10-Italic sa 1,
- sl=LMTypewriter10-Oblique sa 1,
- bf=LMTypewriter10-Dark sa 1,
- bs=LMTypewriter10-DarkOblique sa 1,
- sc=LMTypewriter10-CapsRegular sa 1]
-
- \definebodyfont [14.4pt,17.3pt,20.7pt] [tt]
- [tf=LMTypewriter12-Regular sa 1,
- it=LMTypewriter10-Italic sa 1,
- sl=LMTypewriter10-Oblique sa 1,
- bf=LMTypewriter10-Dark sa 1,
- bs=LMTypewriter10-DarkOblique sa 1,
- sc=LMTypewriter10-CapsRegular sa 1]
-
-\stoptypescript
-
-% ms=MathSymbol sa 1
-
-\starttypescript [math] [modern,computer-modern,latin-modern] [size]
-
- \definebodyfont [12pt] [mm] [mr=LMMathRoman12-Regular sa 1, mb=LMMathRoman12-Bold sa 1]
- \definebodyfont [11pt] [mm] [mr=LMMathRoman10-Regular sa 1, mb=LMMathRoman10-Bold sa 1]
- \definebodyfont [10pt] [mm] [mr=LMMathRoman10-Regular sa 1, mb=LMMathRoman10-Bold sa 1]
- \definebodyfont [9pt] [mm] [mr=LMMathRoman9-Regular sa 1, mb=LMMathRoman9-Bold sa 1]
- \definebodyfont [8pt] [mm] [mr=LMMathRoman8-Regular sa 1, mb=LMMathRoman8-Bold sa 1]
- \definebodyfont [7pt] [mm] [mr=LMMathRoman7-Regular sa 1, mb=LMMathRoman7-Bold sa 1]
- \definebodyfont [6pt] [mm] [mr=LMMathRoman6-Regular sa 1, mb=LMMathRoman6-Bold sa 1]
- \definebodyfont [5pt] [mm] [mr=LMMathRoman5-Regular sa 1, mb=LMMathRoman5-Bold sa 1]
- \definebodyfont [4pt] [mm] [mr=LMMathRoman5-Regular sa 1, mb=LMMathRoman5-Bold sa 1]
-
- \definebodyfont [14.4pt,17.3pt,20.7pt] [mm] [mr=LMMathRoman12-Regular sa 1, mb=LMMathRoman12-Bold sa 1]
-
+ [\s!mm] [\s!default]
\stoptypescript
\stoptypescriptcollection
-\endinput
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/type-tmf.mkii b/Master/texmf-dist/tex/context/base/type-tmf.mkii
index af9280c73c8..829b6baec99 100644
--- a/Master/texmf-dist/tex/context/base/type-tmf.mkii
+++ b/Master/texmf-dist/tex/context/base/type-tmf.mkii
@@ -5,7 +5,7 @@
%D subtitle=Core \TEX\ Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-tmf.mkiv b/Master/texmf-dist/tex/context/base/type-tmf.mkiv
index af9280c73c8..829b6baec99 100644
--- a/Master/texmf-dist/tex/context/base/type-tmf.mkiv
+++ b/Master/texmf-dist/tex/context/base/type-tmf.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Core \TEX\ Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-win.mkii b/Master/texmf-dist/tex/context/base/type-win.mkii
index cb0ad19f5dc..ae690982093 100644
--- a/Master/texmf-dist/tex/context/base/type-win.mkii
+++ b/Master/texmf-dist/tex/context/base/type-win.mkii
@@ -5,7 +5,7 @@
%D subtitle=Microsoft Windows Fonts,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/type-win.mkiv b/Master/texmf-dist/tex/context/base/type-win.mkiv
deleted file mode 100644
index 3f06fa4db1d..00000000000
--- a/Master/texmf-dist/tex/context/base/type-win.mkiv
+++ /dev/null
@@ -1,118 +0,0 @@
-%D \module
-%D [ file=type-win,
-%D version=2009.03.10,
-%D title=\CONTEXT\ Typescript Macros,
-%D subtitle=MS Windows Definitions,
-%D author=Vyatcheslav Yatskovsky,
-%D date=\currentdate,
-%D copyright=Vyatcheslav Yatskovsky]
-%C
-%C This module is part of the \CONTEXT\ macro||package. See
-%C mreadme.pdf for details.
-
-\starttypescriptcollection[windows]
-
-\starttypescript [serif] [georgia,palatino,times]
- \setups[font:fallback:serif]
- \definefontsynonym [Serif] [\typescripttwo-Regular] [features=default]
- \definefontsynonym [SerifBold] [\typescripttwo-Bold] [features=default]
- \definefontsynonym [SerifItalic] [\typescripttwo-Italic] [features=default]
- \definefontsynonym [SerifBoldItalic] [\typescripttwo-BoldItalic] [features=default]
-\stoptypescript
-
-\starttypescript [serif] [sylfaen]
- \setups[font:fallback:serif]
- \definefontsynonym [Serif] [\typescripttwo-Regular] [features=default]
-\stoptypescript
-
-\starttypescript [sans] [arial,trebuchet,verdana]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [\typescripttwo-Regular] [features=default]
- \definefontsynonym [SansBold] [\typescripttwo-Bold] [features=default]
- \definefontsynonym [SansItalic] [\typescripttwo-Italic] [features=default]
- \definefontsynonym [SansBoldItalic] [\typescripttwo-BoldItalic] [features=default]
-\stoptypescript
-
-\starttypescript [sans] [arialblack,impact,lucidasans,microsans]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [\typescripttwo-Regular] [features=default]
-\stoptypescript
-
-\starttypescript [sans] [comic,tahoma]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [\typescripttwo-Regular] [features=default]
- \definefontsynonym [SansBold] [\typescripttwo-Bold] [features=default]
-\stoptypescript
-
-\starttypescript [sans] [franklin]
- \setups[font:fallback:sans]
- \definefontsynonym [Sans] [\typescripttwo-Regular] [features=default]
- \definefontsynonym [SansItalic] [\typescripttwo-Italic] [features=default]
-\stoptypescript
-
-\starttypescript [mono] [courier]
- \setups[font:fallback:mono]
- \definefontsynonym [Mono] [\typescripttwo-Regular] [features=default]
- \definefontsynonym [MonoBold] [\typescripttwo-Bold] [features=default]
- \definefontsynonym [MonoItalic] [\typescripttwo-Italic] [features=default]
- \definefontsynonym [MonoBoldItalic] [\typescripttwo-BoldItalic] [features=default]
-\stoptypescript
-
-\starttypescript [mono] [lucidaconsole]
- \setups[font:fallback:mono]
- \definefontsynonym [Mono] [\typescripttwo-Regular] [features=default]
-\stoptypescript
-
-\definetypescriptprefix [f:arial] [Arial]
-\definetypescriptprefix [f:arialblack] [Arial Black]
-\definetypescriptprefix [f:comic] [Comic Sans MS]
-\definetypescriptprefix [f:courier] [Courier New]
-\definetypescriptprefix [f:franklin] [Franklin Gothic Medium]
-\definetypescriptprefix [f:georgia] [Georgia]
-\definetypescriptprefix [f:impact] [Impact]
-\definetypescriptprefix [f:lucidaconsole] [Lucida Console]
-\definetypescriptprefix [f:lucidasans] [Lucida Sans Unicode]
-\definetypescriptprefix [f:microsans] [Microsoft Sans Serif]
-\definetypescriptprefix [f:palatino] [Palatino Linotype]
-\definetypescriptprefix [f:sylfaen] [Sylfaen]
-\definetypescriptprefix [f:tahoma] [Tahoma]
-\definetypescriptprefix [f:times] [Times New Roman]
-\definetypescriptprefix [f:trebuchet] [Trebuchet MS]
-\definetypescriptprefix [f:verdana] [Verdana]
-
-\starttypescript [serif] [georgia,palatino,sylfaen,times]
- \definefontsynonym [\typescripttwo-Regular] [name:\typescriptprefix{f:\typescripttwo}] [features=default]
- \definefontsynonym [\typescripttwo-Bold] [name:\typescriptprefix{f:\typescripttwo} Bold] [features=default]
- \definefontsynonym [\typescripttwo-Italic] [name:\typescriptprefix{f:\typescripttwo} Italic] [features=default]
- \definefontsynonym [\typescripttwo-BoldItalic] [name:\typescriptprefix{f:\typescripttwo} Bold Italic] [features=default]
-\stoptypescript
-
-\starttypescript [sans] [arial,arialblack,comic,franklin,impact,lucidasans,microsans,tahoma,trebuchet,verdana]
- \definefontsynonym [\typescripttwo-Regular] [name:\typescriptprefix{f:\typescripttwo}] [features=default]
- \definefontsynonym [\typescripttwo-Bold] [name:\typescriptprefix{f:\typescripttwo} Bold] [features=default]
- \definefontsynonym [\typescripttwo-Italic] [name:\typescriptprefix{f:\typescripttwo} Italic] [features=default]
- \definefontsynonym [\typescripttwo-BoldItalic] [name:\typescriptprefix{f:\typescripttwo} Bold Italic] [features=default]
-\stoptypescript
-
-\starttypescript [mono] [courier,lucidaconsole]
- \definefontsynonym [\typescripttwo-Regular] [name:\typescriptprefix{f:\typescripttwo}] [features=default]
- \definefontsynonym [\typescripttwo-Bold] [name:\typescriptprefix{f:\typescripttwo} Bold] [features=default]
- \definefontsynonym [\typescripttwo-Italic] [name:\typescriptprefix{f:\typescripttwo} Italic] [features=default]
- \definefontsynonym [\typescripttwo-BoldItalic] [name:\typescriptprefix{f:\typescripttwo} Bold Italic] [features=default]
-\stoptypescript
-
-\starttypescript [georgia,palatino,sylfaen,times]
- \definetypeface [\typescriptone] [rm] [serif] [\typescriptone] [default]
-\stoptypescript
-
-\starttypescript [arial,arialblack,comic,franklin,impact,lucidasans,microsans,tahoma,trebuchet,verdana]
- \definetypeface [\typescriptone] [ss] [sans] [\typescriptone] [default]
-\stoptypescript
-
-\starttypescript [courier,lucidaconsole]
- \definetypeface [\typescriptone] [tt] [mono] [\typescriptone] [default]
-\stoptypescript
-
-\stoptypescriptcollection
-
-\endinput
diff --git a/Master/texmf-dist/tex/context/base/type-xtx.mkii b/Master/texmf-dist/tex/context/base/type-xtx.mkii
index 0ee0130f776..d8b5f9c2a85 100644
--- a/Master/texmf-dist/tex/context/base/type-xtx.mkii
+++ b/Master/texmf-dist/tex/context/base/type-xtx.mkii
@@ -5,7 +5,7 @@
%D subtitle=\XETEX's font treasures,
%D author=Adam T. Lindsay,
%D date=\currentdate,
-%D copyright={Adam T. Lindsay / PRAGMA}]
+%D copyright={Adam Lindsay \& Hans Hagen}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
diff --git a/Master/texmf-dist/tex/context/base/typo-brk.lua b/Master/texmf-dist/tex/context/base/typo-brk.lua
index fe0258bccd6..14f0b8b4744 100644
--- a/Master/texmf-dist/tex/context/base/typo-brk.lua
+++ b/Master/texmf-dist/tex/context/base/typo-brk.lua
@@ -32,10 +32,13 @@ local remove_node = nodes.remove -- ! nodes
local link_nodes = nodes.link
local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
local nodepool = nodes.pool
local tasks = nodes.tasks
+local v_reset = interfaces.variables.reset
+
local new_penalty = nodepool.penalty
local new_glue = nodepool.glue
local new_disc = nodepool.disc
@@ -54,7 +57,7 @@ typesetters.breakpoints = typesetters.breakpoints or {}
local breakpoints = typesetters.breakpoints
breakpoints.mapping = breakpoints.mapping or { }
-local mapping = breakpoints.mapping
+breakpoints.numbers = breakpoints.numbers or { }
breakpoints.methods = breakpoints.methods or { }
local methods = breakpoints.methods
@@ -64,27 +67,12 @@ breakpoints.attribute = a_breakpoints
storage.register("typesetters/breakpoints/mapping", breakpoints.mapping, "typesetters.breakpoints.mapping")
-function breakpoints.setreplacement(id,char,language,settings)
- char = utfbyte(char)
- local map = mapping[id]
- if not map then
- map = { }
- mapping[id] = map
- end
- local cmap = map[char]
- if not cmap then
- cmap = { }
- map[char] = cmap
- end
- local left, right, middle = settings.left, settings.right, settings.middle
- cmap[language or ""] = {
- type = tonumber(settings.type) or 1,
- nleft = tonumber(settings.nleft) or 1,
- nright = tonumber(settings.nright) or 1,
- left = left ~= "" and left or nil,
- right = right ~= "" and right or nil,
- middle = middle ~= "" and middle or nil,
- } -- was { type or 1, before or 1, after or 1 }
+local mapping = breakpoints.mapping
+local numbers = breakpoints.mapping
+
+for i=1,#mapping do
+ local m = mapping[i]
+ numbers[m.name] = m
end
local function insert_break(head,start,before,after)
@@ -167,12 +155,13 @@ local function process(namespace,attribute,head)
while start do
local id = start.id
if id == glyph_code then
- local attr = has_attribute(start,attribute)
+ local attr = has_attribute(start,a_breakpoints)
if attr and attr > 0 then
- unset_attribute(start,attribute) -- maybe test for subtype > 256 (faster)
+ unset_attribute(start,a_breakpoints) -- maybe test for subtype > 256 (faster)
-- look ahead and back n chars
- local map = mapping[attr]
- if map then
+ local data = mapping[attr]
+ if data then
+ local map = data.characters
local cmap = map[start.char]
if cmap then
local lang = start.lang
@@ -230,15 +219,64 @@ local function process(namespace,attribute,head)
return head, done
end
-function breakpoints.set(n)
- if trace_breakpoints then
- report_breakpoints("enabling breakpoints handler")
+local enabled = false
+
+function breakpoints.define(name)
+ local data = numbers[name]
+ if data then
+ -- error
+ else
+ local number = #mapping + 1
+ local data = {
+ name = name,
+ number = number,
+ characters = { },
+ }
+ mapping[number] = data
+ numbers[name] = data
+ end
+end
+
+function breakpoints.setreplacement(name,char,language,settings)
+ char = utfbyte(char)
+ local data = numbers[name]
+ if data then
+ local characters = data.characters
+ local cmap = characters[char]
+ if not cmap then
+ cmap = { }
+ characters[char] = cmap
+ end
+ local left, right, middle = settings.left, settings.right, settings.middle
+ cmap[language or ""] = {
+ type = tonumber(settings.type) or 1,
+ nleft = tonumber(settings.nleft) or 1,
+ nright = tonumber(settings.nright) or 1,
+ left = left ~= "" and left or nil,
+ right = right ~= "" and right or nil,
+ middle = middle ~= "" and middle or nil,
+ } -- was { type or 1, before or 1, after or 1 }
end
- tasks.enableaction("processors","typesetters.breakpoints.handler")
- function breakpoints.set(n)
- texattribute[a_breakpoints] = n
+end
+
+function breakpoints.set(n)
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = mapping[n]
+ if not n then
+ n = unsetvalue
+ else
+ if not enabled then
+ if trace_breakpoints then
+ report_breakpoints("enabling breakpoints handler")
+ end
+ tasks.enableaction("processors","typesetters.breakpoints.handler")
+ end
+ n = n.number
+ end
end
- breakpoints.set(n)
+ texattribute[a_breakpoints] = n
end
breakpoints.handler = nodes.installattributehandler {
@@ -247,6 +285,12 @@ breakpoints.handler = nodes.installattributehandler {
processor = process,
}
-function breakpoints.enable()
- tasks.enableaction("processors","typesetters.breakpoints.handler")
-end
+-- function breakpoints.enable()
+-- tasks.enableaction("processors","typesetters.breakpoints.handler")
+-- end
+
+-- interface
+
+commands.definebreakpoints = breakpoints.define
+commands.definebreakpoint = breakpoints.setreplacement
+commands.setbreakpoints = breakpoints.set
diff --git a/Master/texmf-dist/tex/context/base/typo-brk.mkiv b/Master/texmf-dist/tex/context/base/typo-brk.mkiv
index 4c21093ec4f..029f4402f00 100644
--- a/Master/texmf-dist/tex/context/base/typo-brk.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-brk.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Breakpoints,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -15,73 +15,65 @@
\unprotect
-\registerctxluafile{typo-brk}{1.001}
-
-\definesystemattribute[breakpoint][public]
-
-% compound stuff (under construction)
-
-\newbox\breakpointbox
-
-\exhyphenchar\minusone % we use a different order then base tex, so we really need this
-
-\newcount \maxbreakpointsid
-
-\unexpanded\def\definebreakpoints
- {\dosingleargument\dodefinebreakpoints}
-
-\def\dodefinebreakpoints[#1]%
- {\ifcsname\??bp:#1\endcsname \else
- \global\advance\maxbreakpointsid\plusone
- \setxvalue{\??bp:#1}{\number\maxbreakpointsid}%
- \fi}
-
-\def\installbreakpoint
- {\dotripleempty\doinstallbreakpoint}
-
% hm, we cannot prebuild lists, font dependent
%
% -- type nleft nright language left right middle
%
% -- we might eventually stick to only method 5
-\def\doinstallbreakpoint[#1][#2][#3]%
- {\ifcsname\??bp:#1\endcsname
- \begingroup
- \getparameters[\??bp][\c!type=1,\c!nleft=3,\c!nright=3,\s!language=,\c!left=,\c!right=,\c!middle=,#3]%
- \ctxlua{typesetters.breakpoints.setreplacement(\csname\??bp:#1\endcsname, "#2", "\reallanguagetag\@@bplanguage", {
- type = \@@bptype,
- nleft = "\@@bpnleft",
- nright = "\@@bpnright",
- right = "\@@bpright",
- left = "\@@bpleft",
- middle = "\@@bpmiddle"
- } )}% todo: table
- \endgroup
- \fi}
+\registerctxluafile{typo-brk}{1.001}
+
+\definesystemattribute[breakpoint][public,global]
+
+\exhyphenchar\minusone % we use a different order then base tex, so we really need this
+
+\unexpanded\def\definebreakpoints
+ {\dosingleargument\typo_breakpoints_define}
+
+\def\typo_breakpoints_define[#1]%
+ {\ctxcommand{definebreakpoints("#1")}}
+
+\def\definebreakpoint
+ {\dotripleempty\typo_breakpoints_define_character}
+
+\def\typo_breakpoints_define_character[#1][#2][#3]% name char settings
+ {\begingroup
+ \getparameters[\??bp][\c!type=1,\c!nleft=3,\c!nright=3,\s!language=,\c!left=,\c!right=,\c!middle=,#3]%
+ \ctxcommand{definebreakpoint("#1", "#2", "\reallanguagetag\@@bplanguage", {
+ type = \@@bptype,
+ nleft = "\@@bpnleft",
+ nright = "\@@bpnright",
+ right = "\@@bpright",
+ left = "\@@bpleft",
+ middle = "\@@bpmiddle"
+ } )}%
+ \endgroup}
\unexpanded\def\setbreakpoints[#1]%
- {\ctxlua{typesetters.breakpoints.set(\number\csname\??bp:#1\endcsname)}}
+ {\ctxcommand{setbreakpoints("#1")}}
-\letvalue{\??bp:\s!reset}\attributeunsetvalue
+\unexpanded\def\resetbreakpoints
+ {\attribute\breakpointattribute\attributeunsetvalue}
\definebreakpoints[compound]
-\installbreakpoint [compound] [+] [\c!nleft=3,\c!nright=3,\c!type=1] % middle=+,left=,right=
-\installbreakpoint [compound] [-] [\c!nleft=3,\c!nright=3,\c!type=1] % middle=+,left=,right=
-\installbreakpoint [compound] [/] [\c!nleft=3,\c!nright=3,\c!type=1] % middle=+,left=,right=
-\installbreakpoint [compound] [(] [\c!nleft=3,\c!nright=3,\c!type=2] % type=5,middle=(,left=(-,right=
-\installbreakpoint [compound] [)] [\c!nleft=3,\c!nright=3,\c!type=3] % type=5,middle=),left=,right=-)
+\definebreakpoint [compound] [+] [\c!nleft=3,\c!nright=3,\c!type=1] % middle=+,left=,right=
+\definebreakpoint [compound] [-] [\c!nleft=3,\c!nright=3,\c!type=1] % middle=+,left=,right=
+\definebreakpoint [compound] [/] [\c!nleft=3,\c!nright=3,\c!type=1] % middle=+,left=,right=
+\definebreakpoint [compound] [(] [\c!nleft=3,\c!nright=3,\c!type=2] % type=5,middle=(,left=(-,right=
+\definebreakpoint [compound] [)] [\c!nleft=3,\c!nright=3,\c!type=3] % type=5,middle=),left=,right=-)
+
+\let\installbreakpoint\definebreakpoint % for a while
% \start \hsize 1.5cm \setbreakpoints[compound]
-% \installbreakpoint [compound] [-] [nleft=3,nright=3,type=5,left=,right={-},middle={-}]
-% \installbreakpoint [compound] [(] [nleft=3,nright=3,type=5,left=,right={(-},middle={(}]
-% \installbreakpoint [compound] [)] [nleft=3,nright=3,type=5,left={-)},right=,middle={)}]
+% \definebreakpoint [compound] [-] [nleft=3,nright=3,type=5,left=,right={-},middle={-}]
+% \definebreakpoint [compound] [(] [nleft=3,nright=3,type=5,left=,right={(-},middle={(}]
+% \definebreakpoint [compound] [)] [nleft=3,nright=3,type=5,left={-)},right=,middle={)}]
% composed-word\par composed(word)\par
% \stop
% \mainlanguage[czech]
-% \installbreakpoint [compound] [\number`-] [language=cs,nleft=3,nright=3,type=4]
+% \definebreakpoint [compound] [\number`-] [language=cs,nleft=3,nright=3,type=4]
% \setbreakpoints[compound]
% \start \hsize 1mm test-test \par \stop
diff --git a/Master/texmf-dist/tex/context/base/typo-cap.lua b/Master/texmf-dist/tex/context/base/typo-cap.lua
index 2e20a95e7e4..3233a6ba222 100644
--- a/Master/texmf-dist/tex/context/base/typo-cap.lua
+++ b/Master/texmf-dist/tex/context/base/typo-cap.lua
@@ -4,7 +4,7 @@ if not modules then modules = { } end modules ['typo-cap'] = {
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
-}
+ }
local next, type = next, type
local format, insert = string.format, table.insert
@@ -23,6 +23,7 @@ local traverse_id = node.traverse_id
local copy_node = node.copy
local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
local nodecodes = nodes.nodecodes
local skipcodes = nodes.skipcodes
@@ -40,6 +41,9 @@ local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
local fontchar = fonthashes.characters
+local variables = interfaces.variables
+local v_reset = variables.reset
+
local chardata = characters.data
typesetters = typesetters or { }
@@ -131,17 +135,34 @@ local function helper(start, codes, special, attribute, once)
return start, false
end
-actions[1] = function(start,attribute)
+local registered, n = { }, 0
+
+local function register(name,f)
+ if type(f) == "function" then
+ n = n + 1
+ actions[n] = f
+ registered[name] = n
+ return n
+ else
+ local n = registered[f]
+ registered[name] = n
+ return n
+ end
+end
+
+cases.register = register
+
+local function WORD(start,attribute)
lastfont = nil
return helper(start,uccodes)
end
-actions[2] = function(start,attribute)
+local function word(start,attribute)
lastfont = nil
return helper(start,lccodes)
end
-actions[3] = function(start,attribute,attr)
+local function Word(start,attribute,attr)
lastfont = nil
local prev = start.prev
if prev and prev.id == kern_code and prev.subtype == kerning_code then
@@ -164,7 +185,7 @@ actions[3] = function(start,attribute,attr)
end
end
-actions[4] = function(start,attribute)
+local function Words(start,attribute)
lastfont = nil
local prev = start.prev
if prev and prev.id == kern_code and prev.subtype == kerning_code then
@@ -177,15 +198,19 @@ actions[4] = function(start,attribute)
end
end
-actions[5] = function(start,attribute) -- 3
+local function capital(start,attribute) -- 3
return helper(start,uccodes,true,attribute,true)
end
-actions[6] = function(start,attribute) -- 4
+local function Capital(start,attribute) -- 4
return helper(start,uccodes,true,attribute,false)
end
-actions[8] = function(start)
+local function none(start)
+ return start, false
+end
+
+local function random(start)
lastfont = nil
local ch = start.char
local mr = math.random
@@ -217,6 +242,18 @@ actions[8] = function(start)
return start, false
end
+register(variables.WORD, WORD) -- 1
+register(variables.word, word) -- 2
+register(variables.Word, Word) -- 3
+register(variables.Words, Words) -- 4
+register(variables.capital, capital) -- 5
+register(variables.Capital, Capital) -- 6
+register(variables.none, none) -- 7 (dummy)
+register(variables.random, random) -- 8
+
+register(variables.cap, variables.capital) -- clone
+register(variables.Cap, variables.Capital) -- clone
+
-- node.traverse_id_attr
local function process(namespace,attribute,head) -- not real fast but also not used on much data
@@ -257,19 +294,30 @@ end
local m, enabled = 0, false -- a trick to make neighbouring ranges work
function cases.set(n)
- if not enabled then
- tasks.enableaction("processors","typesetters.cases.handler")
- if trace_casing then
- report_casing("enabling case handler")
- end
- enabled = true
- end
- if m == 100 then
- m = 1
+ if n == v_reset then
+ n = unsetvalue
else
- m = m + 1
+ n = registered[n] or tonumber(n)
+ if n then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.cases.handler")
+ if trace_casing then
+ report_casing("enabling case handler")
+ end
+ enabled = true
+ end
+ if m == 100 then
+ m = 1
+ else
+ m = m + 1
+ end
+ n = m * 100 + n
+ else
+ n = unsetvalue
+ end
end
- texattribute[a_cases] = m * 100 + n
+ texattribute[a_cases] = n
+ -- return n -- bonus
end
cases.handler = nodes.installattributehandler {
@@ -277,3 +325,7 @@ cases.handler = nodes.installattributehandler {
namespace = cases,
processor = process,
}
+
+-- interface
+
+commands.setcharactercasing = cases.set
diff --git a/Master/texmf-dist/tex/context/base/typo-cap.mkiv b/Master/texmf-dist/tex/context/base/typo-cap.mkiv
index 1b3e0df26e9..28ced7c42cf 100644
--- a/Master/texmf-dist/tex/context/base/typo-cap.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-cap.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Capping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -36,11 +36,9 @@
%D
%D This calls result in:
%D
-%D \startvoorbeeld
%D \startlines
%D \getbuffer
%D \stoplines
-%D \stopvoorbeeld
%D
%D \showsetup{Word}
%D \showsetup{Words}
@@ -52,14 +50,23 @@
% test \Word{test TEST \TeX} test
\unexpanded\def\setcharactercasing[#1]%
- {\ctxlua{typesetters.cases.set(\number#1)}}
+ {\ctxcommand{setcharactercasing("#1")}}
% todo: names casings
-\unexpanded\def\WORD {\groupedcommand{\setcharactercasing[\plusone ]}{}}
-\unexpanded\def\word {\groupedcommand{\setcharactercasing[\plustwo ]}{}}
-\unexpanded\def\Word {\groupedcommand{\setcharactercasing[\plusthree]}{}}
-\unexpanded\def\Words{\groupedcommand{\setcharactercasing[\plusfour ]}{}}
+\unexpanded\def\WORD {\groupedcommand{\setcharactercasing[\v!WORD ]}{}}
+\unexpanded\def\word {\groupedcommand{\setcharactercasing[\v!word ]}{}}
+\unexpanded\def\Word {\groupedcommand{\setcharactercasing[\v!Word ]}{}}
+\unexpanded\def\Words{\groupedcommand{\setcharactercasing[\v!Words]}{}}
+
+% This might become:
+%
+% \unexpanded\def\WORD {\bgroup\def\g_word{\setcharactercasing[\v!WORD ]}\afterassignment\g_word\let\nexttoken}
+% \unexpanded\def\word {\bgroup\def\g_word{\setcharactercasing[\v!word ]}\afterassignment\g_word\let\nexttoken}
+% \unexpanded\def\Word {\bgroup\def\g_word{\setcharactercasing[\v!Word ]}\afterassignment\g_word\let\nexttoken}
+% \unexpanded\def\Words{\bgroup\def\g_word{\setcharactercasing[\v!Words]}\afterassignment\g_word\let\nexttoken}
+%
+% so no longer {\Word test} and { } mandate (also later \groupedcommands will go)
\let\WORDS\WORD
\let\words\word
@@ -83,11 +90,9 @@
%D Note the use of \type{\nocap}, \type{\\} and the nested
%D \type{\cap}.
%D
-%D \startvoorbeeld
%D \startlines
%D \getbuffer
%D \stoplines
-%D \stopvoorbeeld
%D
%D These macros show te main reason why we introduced the
%D smaller \type{\tx} and \type{\txx}.
@@ -122,33 +127,35 @@
\let\disablepseudocaps\relax % maybe used elsewhere
-\newconditional\pseudocapsenabled
+\newconditional\c_typo_capitals_pseudo
-\def\usepseudocaps{\settrue \pseudocapsenabled}
-\def\userealcaps {\setfalse\pseudocapsenabled}
+\unexpanded\def\usepseudocaps{\settrue \c_typo_capitals_pseudo}
+\unexpanded\def\userealcaps {\setfalse\c_typo_capitals_pseudo}
\usepseudocaps
% we use char0 as placeholder for the larger font
+%
+% here we keep the \groupedcommand
-\unexpanded\def\pseudosmallcapped{\groupedcommand{\setcharactercasing[\plusone ]\signalcharacter\tx}{}} % all upper
-\unexpanded\def\pseudoSmallcapped{\groupedcommand{\setcharactercasing[\plusfive]\signalcharacter\tx}{}} % one upper + font
-\unexpanded\def\pseudoSmallCapped{\groupedcommand{\setcharactercasing[\plussix ]\signalcharacter\tx}{}} % some upper + font
+\unexpanded\def\pseudosmallcapped{\groupedcommand{\setcharactercasing [\v!WORD ]\signalcharacter\tx}{}} % all upper
+\unexpanded\def\pseudoSmallcapped{\groupedcommand{\setcharactercasing [\v!capital]\signalcharacter\tx}{}} % one upper + font
+\unexpanded\def\pseudoSmallCapped{\groupedcommand{\setcharactercasing [\v!Capital]\signalcharacter\tx}{}} % some upper + font
-\unexpanded\def\realsmallcapped {\groupedcommand{\sc\setcharactercasing[\plusone ]}{}} % all lower
-\unexpanded\def\realSmallcapped {\groupedcommand{\sc\setcharactercasing[\plusthree]}{}} % one upper + font
-\unexpanded\def\realSmallCapped {\groupedcommand{\sc\setcharactercasing[\plusfour ]}{}} % some upper
+\unexpanded\def\realsmallcapped {\groupedcommand{\sc\setcharactercasing[\v!WORD ]}{}} % all lower
+\unexpanded\def\realSmallcapped {\groupedcommand{\sc\setcharactercasing[\v!Word ]}{}} % one upper + font
+\unexpanded\def\realSmallCapped {\groupedcommand{\sc\setcharactercasing[\v!Words ]}{}} % some upper
-\unexpanded\def\dohandlesmallcaps
- {\ifconditional\pseudocapsenabled
+\unexpanded\def\typo_capitals_smallcaps
+ {\ifconditional\c_typo_capitals_pseudo
\expandafter\firstoftwoarguments
\else
\expandafter\secondoftwoarguments
\fi}
-\unexpanded\def\smallcapped{\dohandlesmallcaps\pseudosmallcapped\realsmallcapped}
-\unexpanded\def\Smallcapped{\dohandlesmallcaps\pseudoSmallcapped\realSmallcapped}
-\unexpanded\def\SmallCapped{\dohandlesmallcaps\pseudoSmallCapped\realSmallCapped}
+\unexpanded\def\smallcapped{\typo_capitals_smallcaps\pseudosmallcapped\realsmallcapped}
+\unexpanded\def\Smallcapped{\typo_capitals_smallcaps\pseudoSmallcapped\realSmallcapped}
+\unexpanded\def\SmallCapped{\typo_capitals_smallcaps\pseudoSmallCapped\realSmallCapped}
\unexpanded\def\autocap{\ifmmode\expandafter\normalcap\else\expandafter\smallcapped\fi}
@@ -166,7 +173,7 @@
%D As suggested by WS:
-\unexpanded\def\notsmallcapped{\groupedcommand{\setcharactercasing[\plustwo]\signalcharacter}{}}
+\unexpanded\def\notsmallcapped{\groupedcommand{\setcharactercasing[\v!word]\signalcharacter}{}}
%D \macros
%D {setupcapitals}
@@ -178,16 +185,18 @@
\let\normalsmallcapped\smallcapped
+\definesystemvariable{kk}
+
\unexpanded\def\setupcapitals
- {\dosingleempty\dosetupcapitals}
+ {\dosingleempty\typo_capitals_setup}
-\def\dosetupcapitals[#1]% todo: don't use grouping just a switch
+\def\typo_capitals_setup[#1]% todo: don't use grouping just a switch
{\getparameters[\??kk][#1]%
\doifelse\@@kktitle\v!yes
- {\definealternativestyle[\v!capital][\normalsmallcapped][\normalsmallcapped]%
- \definealternativestyle[\v!smallcaps][\sc][\sc]}
- {\definealternativestyle[\v!capital][\normalsmallcapped][\normalWORD]%
- \definealternativestyle[\v!smallcaps][\sc][\normalWORD]}%
+ {\definealternativestyle[\v!capital ][\normalsmallcapped][\normalsmallcapped]%
+ \definealternativestyle[\v!smallcaps][\sc ][\sc ]}
+ {\definealternativestyle[\v!capital ][\normalsmallcapped][\normalWORD ]%
+ \definealternativestyle[\v!smallcaps][\sc ][\normalWORD ]}%
\doifelse\@@kksc\v!yes\userealcaps\usepseudocaps}
\let\uppercased\normalWORD
@@ -195,7 +204,7 @@
\setupcapitals
[\c!title=\v!yes,
- \c!sc=\v!no]
+ \s!sc=\v!no] % no \c!sc any longer
% \definestartstop is not yet in available at core-spa time
%
@@ -203,7 +212,7 @@
%
% \definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=]
-\def\randomizetext{\groupedcommand{\attribute\caseattribute\pluseight}{}}
+\unexpanded\def\randomizetext{\groupedcommand{\attribute\caseattribute\pluseight}{}}
\definestartstop[randomized][\c!before=\dosetattribute{case}{8},\c!after=]
diff --git a/Master/texmf-dist/tex/context/base/typo-cln.lua b/Master/texmf-dist/tex/context/base/typo-cln.lua
index a8542c1a130..c6a2707910d 100644
--- a/Master/texmf-dist/tex/context/base/typo-cln.lua
+++ b/Master/texmf-dist/tex/context/base/typo-cln.lua
@@ -1,6 +1,6 @@
-if not modules then modules = { } end modules ['typo-cap'] = {
+if not modules then modules = { } end modules ['typo-cln'] = {
version = 1.001,
- comment = "companion to typo-cap.mkiv",
+ comment = "companion to typo-cln.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
@@ -15,12 +15,14 @@ local utfbyte = utf.byte
local trace_cleaners = false trackers.register("typesetters.cleaners", function(v) trace_cleaners = v end)
local trace_autocase = false trackers.register("typesetters.cleaners.autocase",function(v) trace_autocase = v end)
-local report_cleaners = logs.reporters("nodes","cleaners")
-local report_autocase = logs.reporters("nodes","autocase")
+local report_cleaners = logs.reporter("nodes","cleaners")
+local report_autocase = logs.reporter("nodes","autocase")
typesetters.cleaners = typesetters.cleaners or { }
local cleaners = typesetters.cleaners
+local variables = interfaces.variables
+
local nodecodes = nodes.nodecodes
local tasks = nodes.tasks
@@ -69,19 +71,23 @@ local function process(namespace,attribute,head)
return head, done
end
--- see typo-cap for a more advanced settings handler .. now needed now
+-- see typo-cap for a more advanced settings handler .. not needed now
local enabled = false
function cleaners.set(n)
- if not enabled then
- tasks.enableaction("processors","typesetters.cleaners.handler")
- if trace_cleaners then
- report_cleaners("enabling cleaners")
+ if n == variables.reset or not tonumber(n) or n == 0 then
+ texattribute[a_cleaner] = unsetvalue
+ else
+ if not enabled then
+ tasks.enableaction("processors","typesetters.cleaners.handler")
+ if trace_cleaners then
+ report_cleaners("enabling cleaners")
+ end
+ enabled = true
end
- enabled = true
+ texattribute[a_cleaner] = n
end
- texattribute[a_cleaner] = n
end
cleaners.handler = nodes.installattributehandler {
@@ -89,3 +95,7 @@ cleaners.handler = nodes.installattributehandler {
namespace = cleaners,
processor = process,
}
+
+-- interface
+
+commands.setcharactercleaning = cleaners.set
diff --git a/Master/texmf-dist/tex/context/base/typo-cln.mkiv b/Master/texmf-dist/tex/context/base/typo-cln.mkiv
index d247b20d2b6..5306f614f27 100644
--- a/Master/texmf-dist/tex/context/base/typo-cln.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-cln.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Cleaning,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -22,9 +22,12 @@
%D Currently there is no interface.
%D
%D 1: Autocap first character of a line
-%D 2: Maybe dropped caps.
\unexpanded\def\setcharactercleaning[#1]% This name might change!
- {\ctxlua{typesetters.cleaners.set(\number#1)}}
+ {\ctxcommand{setcharactercleaning("#1")}} % also accepts "reset"
+
+% \appendtoks
+% \attribute\cleanerattribute\attributeunsetvalue
+% \to \everyforgetall
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-del.mkiv b/Master/texmf-dist/tex/context/base/typo-del.mkiv
new file mode 100644
index 00000000000..b2213db65bb
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-del.mkiv
@@ -0,0 +1,607 @@
+%D \module
+%D [ file=typo-del, % moved from core-mis,
+%D version=20110112,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Delimited Content,
+%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 / Delimited Content}
+
+\unprotect
+
+% THIS IS OBSOLETE:
+
+\unexpanded\def\setuphyphenmark
+ {\dodoubleargument\getparameters[\??kp]}
+
+\unexpanded\def\setuphyphenmark[#1]% sign=normal|wide
+ {\dodoubleargument\getparameters[\??kp][#1]%
+ \doifelse\@@kpsign {\v!normal}% was inset?
+ {\let\textmodehyphen\normalhyphen \let\textmodehyphendiscretionary\normalhyphendiscretionary}
+ {\let\textmodehyphen\composedhyphen\let\textmodehyphendiscretionary\composedhyphendiscretionary}}
+
+\setuphyphenmark[\c!sign=\v!wide]
+
+\definesymbol[\c!lefthyphen] [\languageparameter\c!lefthyphen]
+\definesymbol[\c!righthyphen] [\languageparameter\c!righthyphen]
+\definesymbol[\c!hyphen] [\languageparameter\c!hyphen]
+
+\def\normalhyphen
+ {\hbox{\directsymbol\empty\c!hyphen}}
+
+\def\composedhyphen
+ {\hbox{\directsymbol\empty\c!compoundhyphen}}
+
+\def\normalhyphendiscretionary
+ {\discretionary
+ {\hbox{\directsymbol\empty\c!righthyphen}}
+ {\hbox{\directsymbol\empty\c!lefthyphen}}
+ {\hbox{\directsymbol\empty\c!hyphen}}}
+
+\def\composedhyphendiscretionary
+ {\discretionary
+ {\hbox{\directsymbol\empty\c!rightcompoundhyphen}}
+ {\hbox{\directsymbol\empty\c!leftcompoundhyphen}}
+ {\hbox{\directsymbol\empty\c!compoundhyphen}}}
+
+\let\textmodehyphen \composedhyphen
+\let\textmodehyphendiscretionary\composedhyphendiscretionary
+
+\definesymbol[\c!leftcompoundhyphen] [\languageparameter\c!leftcompoundhyphen]
+\definesymbol[\c!rightcompoundhyphen] [\languageparameter\c!rightcompoundhyphen]
+\definesymbol[\c!compoundhyphen] [\languageparameter\c!compoundhyphen]
+
+% TILL HERE
+
+\setnewconstant\boundarycharactermode\plusone
+
+\unexpanded\def\midboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \languageparameter#1%
+ %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \or
+ \languageparameter#1%
+ \fi
+ \boundarycharactermode\plusone}
+
+\unexpanded\def\leftboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ \languageparameter#1%
+ \nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \or
+ \languageparameter#1%
+ \fi
+ \boundarycharactermode\plusone}
+
+\unexpanded\def\rightboundarycharacter#1#2%
+ {\ifcase\boundarycharactermode
+ \or
+ \prewordbreak %\nobreak
+ \hskip\hspaceamount\currentlanguage{#2}%
+ \languageparameter#1%
+ \or
+ \languageparameter#1%
+ \fi
+ \boundarycharactermode\plusone}
+
+\definehspace [sentence] [\zeropoint]
+\definehspace [intersentence] [.250\emwidth]
+
+\definesymbol
+ [\c!midsentence]
+ [\midboundarycharacter\c!midsentence{sentence}]
+
+\definesymbol
+ [\c!leftsentence]
+ [\leftboundarycharacter\c!leftsentence{sentence}]
+
+\definesymbol
+ [\c!rightsentence]
+ [\rightboundarycharacter\c!rightsentence{sentence}]
+
+\definesymbol
+ [\c!leftsubsentence]
+ [\leftboundarycharacter\c!leftsubsentence{sentence}]
+
+\definesymbol
+ [\c!rightsubsentence]
+ [\rightboundarycharacter\c!rightsubsentence{sentence}]
+
+\newsignal \d_typo_subsentence_signal
+\newcount \c_typo_subsentence_nesting
+
+\let\beforesubsentence\donothing
+\let\aftersubsentence \donothing
+
+% todo: make this language option
+%
+% \def\beforesubsentence{\removeunwantedspaces}
+% \def\aftersubsentence {\ignorespaces}
+
+\unexpanded\def\midsentence
+ {\symbol[\c!midsentence]}
+
+\unexpanded\def\beginofsubsentence
+ {\beforesubsentence
+ \ifdim\lastkern=\d_typo_subsentence_signal
+ \unskip
+ \kern\hspaceamount\currentlanguage{intersentence}%
+ \fi
+ \global\advance\c_typo_subsentence_nesting\plusone
+ \ifnum\c_typo_subsentence_nesting=\plusone
+ \dontleavehmode % was \leaveoutervmode
+ \fi
+ \dostarttagged\t!subsentence\empty
+ \symbol[\ifodd\c_typo_subsentence_nesting\c!leftsentence\else\c!leftsubsentence\fi]%
+ }% \ignorespaces}
+
+\unexpanded\def\endofsubsentence % relax prevents space gobbling
+ {\symbol[\ifodd\c_typo_subsentence_nesting\c!rightsentence\else\c!rightsubsentence\fi]%
+ \dostoptagged
+ \global\advance\c_typo_subsentence_nesting\minusone
+ \unskip
+ \kern\d_typo_subsentence_signal\relax
+ \aftersubsentence}
+
+\unexpanded\def\beginofsubsentencespacing % relax prevents space gobbling
+ {\kern\d_typo_subsentence_signal\relax}% \ignorespaces}
+
+\unexpanded\def\endofsubsentencespacing
+ {\ifdim\lastkern=\d_typo_subsentence_signal
+ \unskip
+ \hskip\hspaceamount\currentlanguage{intersentence}%
+ % no good, actually language dependent:
+% \ignorespaces
+ \else
+ \unskip
+ \fi}
+
+%D \startbuffer
+%D test |<|test |<|test|>| test|>| test \par
+%D test|<|test|<|test|>|test|>|test \par
+%D test |<||<|test|>||>| test \par
+%D test \directdiscretionary{<}test\directdiscretionary{>} test \par
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+\unexpanded\def\startsubsentence{\beginofsubsentence \prewordbreak\beginofsubsentencespacing}
+\unexpanded\def\stopsubsentence {\endofsubsentencespacing\prewordbreak\endofsubsentence}
+\unexpanded\def\subsentence {\groupedcommand\startsubsentence\stopsubsentence}
+
+\definehspace [quotation] [\zeropoint]
+\definehspace [interquotation] [.125em]
+
+%definehspace [quote] [\zeropoint]
+%definehspace [speech] [\zeropoint]
+
+\definehspace [quote] [\hspaceamount\currentlanguage{quotation}]
+\definehspace [speech] [\hspaceamount\currentlanguage{quotation}]
+
+\definesymbol
+ [\c!leftquotation]
+ [\leftboundarycharacter\c!leftquotation{quotation}]
+
+\definesymbol
+ [\c!rightquotation]
+ [\rightboundarycharacter\c!rightquotation{quotation}]
+
+\definesymbol
+ [\c!leftquote]
+ [\leftboundarycharacter\c!leftquote{quote}]
+
+\definesymbol
+ [\c!rightquote]
+ [\rightboundarycharacter\c!rightquote{quote}]
+
+\definesymbol
+ [\c!leftspeech]
+ [\leftboundarycharacter\c!leftspeech{speech}]
+
+\definesymbol
+ [\c!rightspeech]
+ [\rightboundarycharacter\c!rightspeech{speech}]
+
+\definesymbol
+ [\c!middlespeech]
+ [\leftboundarycharacter\c!middlespeech{speech}]
+
+\appendtoks\def\quotation#1{"#1"}\to\simplifiedcommands
+\appendtoks\def\quote #1{'#1'}\to\simplifiedcommands
+
+%D The next features was so desperately needed by Giuseppe
+%D Bilotta that he made a module for it. Since this is a
+%D typical example of core functionality, I decided to extend
+%D the low level quotation macros in such a way that a speech
+%D feature could be build on top of it. The speech opening and
+%D closing symbols are defined per language. Italian is an
+%D example of a language that has them set.
+
+\newsignal\d_typo_delimited_signal
+
+\let\currentdelimitedtext\s!unknown
+
+\let\delimitedtextlevel\!!zerocount
+
+\def\c_typo_delimited_nesting{\csname\??delimitedtextlevel\currentparentdelimitedtext\endcsname}
+
+\def\typo_delimited_push#1%
+ {\globalpushmacro\currentdelimitedtext
+ \def\currentdelimitedtext{#1}%
+ \let\currentparentdelimitedtext\currentdelimitedtext
+ \global\advance\c_typo_delimited_nesting\plusone
+ \edef\delimitedtextlevel{\number\c_typo_delimited_nesting}%
+ \normalexpanded{\chaintocurrentdelimitedtext{\currentparentdelimitedtext:\delimitedtextlevel}}%
+ \edef\currentdelimitedtext{\currentparentdelimitedtext:\delimitedtextlevel}}
+
+\def\typo_delimited_pop
+ {\global\advance\c_typo_delimited_nesting\minusone
+ \globalpopmacro\currentdelimitedtext}
+
+\installcorenamespace{delimitedtext}
+\installcorenamespace{delimitedtextlevel}
+
+\installcommandhandler \??delimitedtext {delimitedtext} \??delimitedtext
+
+\appendtoks
+ \expandafter\newcount\csname\??delimitedtextlevel\currentdelimitedtext\endcsname
+ \setuevalue{\currentdelimitedtext }{\delimitedtext[\currentdelimitedtext]}%
+ \setuevalue{\e!start\currentdelimitedtext}{\startdelimitedtext[\currentdelimitedtext]}%
+ \setuevalue{\e!stop \currentdelimitedtext}{\stopdelimitedtext}%
+\to \everydefinedelimitedtext
+
+\setupdelimitedtext
+ [\c!location=\v!margin, % \v!text \v!paragraph
+ \c!spacebefore=,
+ \c!spaceafter=\delimitedtextparameter\c!spacebefore,
+ \c!style=\v!normal,
+ \c!color=,
+ \c!leftmargin=\zeropoint,
+ \c!rightmargin=\delimitedtextparameter\c!leftmargin,
+ \c!indentnext=\v!yes,
+ \c!before=,
+ \c!after=,
+ \c!left=,
+ \c!right=,
+ %\c!level=0,
+ \c!method=,
+ \c!repeat=\v!no]
+
+\def\typo_delimited_repeat_ideed
+ {\relax\ifcase\delimitedtextlevel\else
+ \typo_delimited_handle_middle\c!middle
+ \fi}
+
+\let\typo_delimited_repeat\relax
+
+\unexpanded\def\startdelimitedtext[#1]%
+ {\begingroup
+ \typo_delimited_push{#1}%
+ \dostarttagged\t!delimitedblock\currentdelimitedtext
+ \edef\p_method{\delimitedtextparameter\c!method}%
+ \ifx\p_method\s!font
+ \expandafter\typo_delimited_start_font
+ \else
+ \expandafter\typo_delimited_start_other
+ \fi}
+
+\let\typo_delimited_stop\relax % hooks into \everypar
+
+\def\typo_delimited_start_font
+ {\let\typo_delimited_stop\typo_delimitedtexts_finish_font
+ \delimitedtextparameter\c!left
+ \ignorespaces}
+
+\def\typo_delimited_start_other
+ {\edef\p_repeat{\delimitedtextparameter\c!repeat}%
+ \ifx\p_repeat\v!yes
+ \let\typo_delimited_repeat\typo_delimited_repeat_ideed
+ \else
+ \let\typo_delimited_repeat\relax
+ \fi
+ \edef\p_location{\delimitedtextparameter\c!location}%
+ \ifx\p_location\v!paragraph
+ \singleexpandafter\typo_delimited_start_par
+ \else\ifx\p_location\v!margin
+ \doubleexpandafter\typo_delimited_start_par
+ \else
+ \doubleexpandafter\typo_delimited_start_txt
+ \fi\fi}
+
+\def\typo_delimitedtexts_finish_font
+ {\removeunwantedspaces\delimitedtextparameter\c!right}
+
+\def\typo_delimited_start_par
+ {\dosingleempty\typo_delimited_start_par_indeed}
+
+\def\typo_delimited_start_par_indeed[#1]%
+ {\let\typo_delimited_stop\typo_delimited_stop_par
+ \doifsomething{\delimitedtextparameter\c!spacebefore}
+ {\blank[\delimitedtextparameter\c!spacebefore]}%
+ \delimitedtextparameter\c!before
+ \edef\m_typo_delimited_narrower{#1}%
+ \ifx\m_typo_delimited_narrower\empty
+ \endgraf
+ \doadaptleftskip {\delimitedtextparameter\c!leftmargin}%
+ \doadaptrightskip{\delimitedtextparameter\c!rightmargin}%
+ \let\typo_delimited_stop_par_indeed\endgraf
+ \else % backward compatible direct directive
+ \startnarrower[#1]%
+ \let\typo_delimited_stop_par_indeed\stopnarrower
+ \fi
+ % so far
+ \pushmacro\checkindentation
+ \doifsomething{\delimitedtextparameter\c!indenting} % WS
+ {\setupindenting[\delimitedtextparameter\c!indenting]}%
+ \begingroup
+ \usedelimitedtextstyleandcolor\c!style\c!color
+ \leftdelimitedtextmark
+ \ignorespaces}
+
+\def\typo_delimited_stop_par
+ {\removeunwantedspaces
+ \removelastskip
+ \rightdelimitedtextmark
+ \endgroup
+ \popmacro\checkindentation
+ \typo_delimited_stop_par_indeed
+ \delimitedtextparameter\c!after
+ \doifsomething{\delimitedtextparameter\c!spaceafter}
+ {\blank[\delimitedtextparameter\c!spaceafter]}%
+ \useindentnextparameter\delimitedtextparameter
+ \dorechecknextindentation}% AM: This was missing!
+
+\def\typo_delimited_start_txt
+ {\let\typo_delimited_stop\typo_delimited_stop_txt
+ \begingroup
+ \usedelimitedtextstyleandcolor\c!style\c!color
+ \typo_delimited_handle_left\c!left
+ \ignorespaces}
+
+\def\typo_delimited_stop_txt
+ {\removeunwantedspaces
+ \typo_delimited_handle_right\c!right
+ \endgroup}
+
+\unexpanded\def\stopdelimitedtext
+ {\typo_delimited_stop
+ \dostoptagged
+ \typo_delimited_pop
+ \endgroup}
+
+\unexpanded\def\delimitedtext[#1]%
+ {\dontleavehmode % following ones can be omited
+ \typo_delimited_push{#1}%
+ \edef\p_method{\delimitedtextparameter\c!method}%
+ \ifx\p_method\s!font
+ \expandafter\typo_delimited_fontdriven
+ \else
+ \expandafter\typo_delimited_other
+ \fi}
+
+\def\typo_delimited_other
+ {\edef\p_location{\delimitedtextparameter\c!location}%
+ \ifx\p_location\v!paragraph
+ \singleexpandafter\typo_delimited_par
+ \else\ifx\p_location\v!margin
+ \doubleexpandafter\typo_delimited_par
+ \else
+ \doubleexpandafter\typo_delimited_txt
+ \fi\fi}
+
+% shortcuts
+
+\unexpanded\def\startdelimited{\startdelimitedtext}
+\unexpanded\def\stopdelimited {\stopdelimitedtext} % no let, dynamically assigned
+ \def\delimited {\delimitedtext}
+
+\unexpanded\def\leftdelimitedtextmark
+ {\doifsomething{\delimitedtextparameter\c!left}
+ {\setbox\scratchbox\hbox{\delimitedtextparameter\c!left}%
+ \dontleavehmode
+ \doif{\delimitedtextparameter\c!location}\v!margin{\hskip-\wd\scratchbox}%
+ \box\scratchbox}}
+
+\unexpanded\def\rightdelimitedtextmark
+ {\doifsomething{\delimitedtextparameter\c!right}
+ {\hsmash{\delimitedtextparameter\c!right}}}
+
+% \starttext
+% \hyphenatedword{groepsvrijstellingsverordeningen}\par
+% \hyphenatedword{\quote{groepsvrijstellingsverordeningen}}\par
+% \dorecurse{100}{\hskip300pt\hskip\recurselevel pt test \quote{xxx xxxx}.\par}
+% \page \setuppapersize[A5][A4]
+% \quotation {overly beautiful pusillanimous sesquipedalian
+% longwinded} test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test test test test test test test test test test test
+% test test test
+% \stoptext
+
+\def\typo_delimited_handle_middle#1%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\d_typo_delimited_signal
+ \unkern
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \fi
+ \ifhmode % else funny pagebeaks
+ \penalty\plustenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+ % \penalty\plustenthousand % else overfull boxes, but that's better than dangling periods
+ \kern\d_typo_delimited_signal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\def\typo_delimited_handle_left#1%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\d_typo_delimited_signal
+ \unkern
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else\ifdim\lastskip=\d_typo_delimited_signal
+ \unskip
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \fi\fi
+ \strut % new, needed below
+ \ifhmode % else funny pagebeaks
+ \penalty\plustenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \hskip\d_typo_delimited_signal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\def\typo_delimited_handle_right#1%
+ {\begingroup
+ \setbox\scratchbox\hbox{\delimitedtextparameter#1}%
+ \ifdim\wd\scratchbox>\zeropoint
+ \ifdim\lastkern=\d_typo_delimited_signal
+ \unkern
+ \penalty\plustenthousand
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \else\ifdim\lastskip=\d_typo_delimited_signal
+ \unskip
+ \penalty\plustenthousand
+ \hskip\hspaceamount\currentlanguage{interquotation}%
+ \fi\fi
+ \ifhmode % else funny pagebeaks
+ \penalty\plustenthousand
+ \hskip\zeropoint % == \prewordbreak
+ \fi
+ \strut % new, needed below
+ \delimitedtextparameter#1% unhbox\scratchbox
+ \kern\d_typo_delimited_signal % +- \prewordbreak
+ \fi
+ \endgroup}
+
+\unexpanded\def\typo_delimited_par
+ {\groupedcommand
+ {\dostarttagged\t!delimited\currentdelimitedtext % block?
+ \typo_delimited_handle_left\c!left}
+ {\typo_delimited_handle_right\c!right
+ \removelastskip
+ \dostoptagged
+ \typo_delimited_pop}}
+
+\unexpanded\def\typo_delimited_txt
+ {\doifelse{\delimitedtextparameter\c!style}\v!normal
+ \typo_delimited_quoted
+ \typo_delimited_attributed}
+
+\def\typo_delimited_quoted_b
+ {\dostarttagged\t!delimited\currentdelimitedtext
+ \typo_delimited_handle_left\c!left}
+
+\def\typo_delimited_quoted_e
+ {\typo_delimited_handle_right\c!right
+ \removelastskip
+ \dostoptagged
+ \typo_delimited_pop}
+
+\def\typo_delimited_attributed_b
+ {\dostarttagged\t!delimited\currentdelimitedtext
+ \usedelimitedtextstyleandcolor\c!style\c!color}
+
+\def\typo_delimited_attributed_e
+ {\dostoptagged
+ \typo_delimited_pop}
+
+\def\typo_delimited_fontdriven_b
+ {\dostarttagged\t!delimited\currentdelimitedtext
+ \languageparameter{\c!left\currentdelimitedtext}}
+
+\def\typo_delimited_fontdriven_e
+ {\languageparameter{\c!right\currentdelimitedtext}%
+ \dostoptagged
+ \typo_delimited_pop}
+
+% We now assume proper argument usage (so no longer grouped
+% command).
+
+% \def\typo_delimited_quoted {\groupedcommand \typo_delimited_quoted_b \typo_delimited_quoted_e }
+% \def\typo_delimited_attributed{\groupedcommand \typo_delimited_attributed_b\typo_delimited_attributed_e}
+% \def\typo_delimited_fontdriven{\simplegroupedcommand\typo_delimited_fontdriven_b\typo_delimited_fontdriven_e}
+
+\def\typo_delimited_quoted {\bgroup\typo_delimited_quoted_b \aftergroup\typo_delimited_quoted_e \let\next=}
+\def\typo_delimited_attributed{\bgroup\typo_delimited_attributed_b\aftergroup\typo_delimited_attributed_e\let\next=}
+\def\typo_delimited_fontdriven{\bgroup\typo_delimited_fontdriven_b\aftergroup\typo_delimited_fontdriven_e\let\next=}
+
+% testcase for nesting:
+%
+% \quotation{... \quotation{...} ...}
+% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
+% \setupdelimitedtext[quotation][1][left=(,right=)]
+% \setupdelimitedtext[quotation][2][left={[},right={]}]
+% \setupdelimitedtext[quotation][3][left=\{,right=\}]
+% \quotation{... \quotation{...} ...}
+% \startquotation ... \startquotation... \quotation{...} \stopquotation\space ...\stopquotation
+
+\definedelimitedtext
+ [\v!quotation]
+ [\c!left={\symbol[\c!leftquotation]},
+ \c!right={\symbol[\c!rightquotation]},
+ \c!leftmargin=\v!standard]
+
+\definedelimitedtext
+ [\v!quote][\v!quotation]
+
+\setupdelimitedtext
+ [\v!quote]
+ [\c!location=\v!text,
+ \c!left={\symbol[\c!leftquote]},
+ \c!right={\symbol[\c!rightquote]}]
+
+\definedelimitedtext
+ [\v!blockquote][\v!quotation]
+
+\setupdelimitedtext
+ [\v!blockquote]
+ [\c!left=,
+ \c!right=]
+
+\definedelimitedtext
+ [\v!speech][\v!quotation]
+
+\setupdelimitedtext
+ [\v!speech]
+ [\c!repeat=\v!yes,
+ \c!left={\symbol[\c!leftspeech]},
+ \c!middle={\symbol[\c!middlespeech]},
+ \c!right={\symbol[\c!rightspeech]}]
+
+% how do we call an tight quote
+%
+% \definedelimitedtext
+% [\v!quotation][\v!quotation]
+%
+% \setupdelimitedtext
+% [\v!quotation]
+% [\c!indentnext=\v!no,
+% \c!spacebefore=\v!nowhite]
+
+\unexpanded\def\setupquotation{\setupdelimitedtext[\v!quotation]}
+\unexpanded\def\setupquote {\setupdelimitedtext[\v!quote]}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-dig.lua b/Master/texmf-dist/tex/context/base/typo-dig.lua
index 1e4a02fc6b9..f11b3b0e378 100644
--- a/Master/texmf-dist/tex/context/base/typo-dig.lua
+++ b/Master/texmf-dist/tex/context/base/typo-dig.lua
@@ -28,6 +28,7 @@ local insert_before = node.insert_before
local insert_after = node.insert_after
local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
@@ -42,6 +43,8 @@ local fontdata = fonthashes.identifiers
local chardata = fonthashes.characters
local quaddata = fonthashes.quads
+local v_reset = interfaces.variables.reset
+
local charbase = characters.data
local getdigitwidth = fonts.helpers.getdigitwidth
@@ -125,20 +128,30 @@ end
local m, enabled = 0, false -- a trick to make neighbouring ranges work
-function digits.set(n)
- if not enabled then
- tasks.enableaction("processors","typesetters.digits.handler")
- if trace_digits then
- report_digits("enabling digit handler")
- end
- enabled = true
- end
- if m == 100 then
- m = 1
+function digits.set(n) -- number or 'reset'
+ if n == v_reset then
+ n = unsetvalue
else
- m = m + 1
+ n = tonumber(n)
+ if n then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.digits.handler")
+ if trace_digits then
+ report_digits("enabling digit handler")
+ end
+ enabled = true
+ end
+ if m == 100 then
+ m = 1
+ else
+ m = m + 1
+ end
+ n = m * 100 + n
+ else
+ n = unsetvalue
+ end
end
- texattribute[a_digits] = m * 100 + n
+ texattribute[a_digits] = n
end
digits.handler = nodes.installattributehandler {
@@ -146,3 +159,7 @@ digits.handler = nodes.installattributehandler {
namespace = digits,
processor = process,
}
+
+-- interface
+
+commands.setdigitsmanipulation = digits.set
diff --git a/Master/texmf-dist/tex/context/base/typo-dig.mkiv b/Master/texmf-dist/tex/context/base/typo-dig.mkiv
index 6e0299291aa..832ebbec4e1 100644
--- a/Master/texmf-dist/tex/context/base/typo-dig.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-dig.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Digits,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -39,7 +39,7 @@
%D \stoplines
\unexpanded\def\setdigitsmanipulation[#1]%
- {\ctxlua{typesetters.digits.set(\number#1)}}
+ {\ctxcommand{setdigitsmanipulation("#1")}}
\unexpanded\def\resetdigitsmanipulation
{\attribute\digitsattribute\attributeunsetvalue}
@@ -48,8 +48,8 @@
\resetdigitsmanipulation
\to \everyresettypesetting
-\unexpanded\def\equaldigits{\groupedcommand{\setdigitsmanipulation[\plusone]}{}}
-\unexpanded\def\dummydigit {\hphantom{\setdigitsmanipulation[\plusone]0}}
+\unexpanded\def\equaldigits{\groupedcommand{\setdigitsmanipulation[\number\plusone]}{}}
+\unexpanded\def\dummydigit {\hphantom {\setdigitsmanipulation[\number\plusone]0}}
\appendtoks
\resetcharacterspacing
diff --git a/Master/texmf-dist/tex/context/base/typo-dir.lua b/Master/texmf-dist/tex/context/base/typo-dir.lua
index 54c2e6e9882..cdc1427a19e 100644
--- a/Master/texmf-dist/tex/context/base/typo-dir.lua
+++ b/Master/texmf-dist/tex/context/base/typo-dir.lua
@@ -53,7 +53,7 @@ local endmath_code = mathcodes.endmath
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
-local chardata = fonthashes.characters
+local fontchar = fonthashes.characters
local chardata = characters.data
local chardirs = characters.directions -- maybe make a special mirror table
diff --git a/Master/texmf-dist/tex/context/base/typo-dir.mkiv b/Master/texmf-dist/tex/context/base/typo-dir.mkiv
index b4e7cb67fb0..33f11d9c8be 100644
--- a/Master/texmf-dist/tex/context/base/typo-dir.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-dir.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Directions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -91,7 +91,7 @@
\startluacode
function documentdata.split_tokens(str)
for s in str:bytes() do
- tex.sprint(tex.ctxcatcodes,string.format("\\hbox{\\char %s}",s))
+ context.sprint(tex.ctxcatcodes,string.format("\\hbox{\\char %s}",s))
end
end
\stopluacode
diff --git a/Master/texmf-dist/tex/context/base/typo-ini.lua b/Master/texmf-dist/tex/context/base/typo-ini.lua
index 40fe7dfaaee..c45d2966436 100644
--- a/Master/texmf-dist/tex/context/base/typo-ini.lua
+++ b/Master/texmf-dist/tex/context/base/typo-ini.lua
@@ -7,3 +7,5 @@ if not modules then modules = { } end modules ['typo-ini'] = {
}
-- nothing yet
+
+typesetters = typesetters or { }
diff --git a/Master/texmf-dist/tex/context/base/typo-ini.mkii b/Master/texmf-dist/tex/context/base/typo-ini.mkii
index 1317021ef29..6e19fb9b670 100644
--- a/Master/texmf-dist/tex/context/base/typo-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/typo-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/typo-ini.mkiv b/Master/texmf-dist/tex/context/base/typo-ini.mkiv
index 10be160539b..d05fcecb09c 100644
--- a/Master/texmf-dist/tex/context/base/typo-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -39,7 +39,7 @@
\def\vhbox{\ifvertical\vbox\else\hbox\fi}
-%D \marcros
+%D \macros
%D {everyresettypesetting}
\newtoks\everyresettypesetting
diff --git a/Master/texmf-dist/tex/context/base/typo-itc.lua b/Master/texmf-dist/tex/context/base/typo-itc.lua
new file mode 100644
index 00000000000..d294dd60a2e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-itc.lua
@@ -0,0 +1,255 @@
+if not modules then modules = { } end modules ['typo-itc'] = {
+ version = 1.001,
+ comment = "companion to typo-itc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local utfchar = utf.char
+
+local trace_italics = false trackers.register("typesetters.italics", function(v) trace_italics = v end)
+
+local report_italics = logs.reporter("nodes","italics")
+
+typesetters.italics = typesetters.italics or { }
+local italics = typesetters.italics
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local disc_code = nodecodes.disc
+
+local tasks = nodes.tasks
+
+local insert_node_after = node.insert_after
+local delete_node = nodes.delete
+local has_attribute = node.has_attribute
+
+local texattribute = tex.attribute
+local a_italics = attributes.private("italics")
+local unsetvalue = attributes.unsetvalue
+
+local new_correction_kern = nodes.pool.fontkern
+local new_correction_glue = nodes.pool.glue
+
+local points = number.points
+
+local fonthashes = fonts.hashes
+local fontdata = fonthashes.identifiers
+local italicsdata = fonthashes.italics
+
+local forcedvariant = false
+
+function typesetters.italics.forcevariant(variant)
+ forcedvariant = variant
+end
+
+local function setitalicinfont(font,char)
+ local tfmdata = fontdata[font]
+ local character = tfmdata.characters[char]
+ if character then
+ local italic = character.italic_correction
+ if not italic then
+ local autoitalicamount = tfmdata.properties.autoitalicamount or 0
+ if autoitalicamount ~= 0 then
+ local description = tfmdata.descriptions[char]
+ if description then
+ italic = description.italic
+ if not italic then
+ local boundingbox = description.boundingbox
+ italic = boundingbox[3] - description.width + autoitalicamount
+ if italic < 0 then -- < 0 indicates no overshoot or a very small auto italic
+ italic = 0
+ end
+ end
+ if italic ~= 0 then
+ italic = italic * tfmdata.parameters.hfactor
+ end
+ end
+ end
+ if trace_italics then
+ report_italics("setting italic correction of %s (U+%05X) of font %s to %s",utfchar(char),char,font,points(italic))
+ end
+ character.italic_correction = italic or 0
+ end
+ return italic
+ else
+ return 0
+ end
+end
+
+-- todo: clear attribute
+
+local function process(namespace,attribute,head)
+ local done = false
+ local italic = 0
+ local lastfont = nil
+ local lastattr = nil
+ local previous = nil
+ local prevchar = nil
+ local current = head
+ local inserted = nil
+ while current do
+ local id = current.id
+ if id == glyph_code then
+ local font = current.font
+ local char = current.char
+ local data = italicsdata[font]
+ if font ~= lastfont then
+ if italic ~= 0 then
+ if data then
+ if trace_italics then
+ report_italics("ignoring %s between italic %s and italic %s",points(italic),utfchar(prevchar),utfchar(char))
+ end
+ else
+ if trace_italics then
+ report_italics("inserting %s between italic %s and regular %s",points(italic),utfchar(prevchar),utfchar(char))
+ end
+ insert_node_after(head,previous,new_correction_kern(italic))
+ done = true
+ end
+ elseif inserted and data then
+ if trace_italics then
+ report_italics("deleting last correction before %s",utfchar(char))
+ end
+ delete_node(head,inserted)
+ else
+ -- nothing
+ end
+ lastfont = font
+ end
+ if data then
+ local attr = forcedvariant or has_attribute(current,attribute)
+ if attr and attr > 0 then
+ local cd = data[char]
+ if not cd then
+ -- this really can happen
+ italic = 0
+ else
+ italic = cd.italic or cd.italic_correction
+ if not italic then
+ italic = setitalicinfont(font,char) -- calculated once
+ -- italic = 0
+ end
+ if italic ~= 0 then
+ lastfont = font
+ lastattr = attr
+ previous = current
+ prevchar = char
+ end
+ end
+ else
+ italic = 0
+ end
+ else
+ italic = 0
+ end
+ inserted = nil
+ elseif id == disc_code then
+ -- skip
+ elseif id == kern_code then
+ inserted = nil
+ italic = 0
+ elseif id == glue_code then
+ if italic ~= 0 then
+ if trace_italics then
+ report_italics("inserting %s between italic %s and glue",points(italic),utfchar(prevchar))
+ end
+ inserted = new_correction_glue(italic) -- maybe just add ? else problem with penalties
+ insert_node_after(head,previous,inserted)
+ italic = 0
+ done = true
+ end
+ elseif italic ~= 0 then
+ if trace_italics then
+ report_italics("inserting %s between italic %s and whatever",points(italic),utfchar(prevchar))
+ end
+ inserted = nil
+ insert_node_after(head,previous,new_correction_kern(italic))
+ italic = 0
+ done = true
+ end
+ current = current.next
+ end
+ if italic ~= 0 and lastattr > 1 then -- more control is needed here
+ if trace_italics then
+ report_italics("inserting %s between italic %s and end of list",points(italic),utfchar(prevchar))
+ end
+ insert_node_after(head,previous,new_correction_kern(italic))
+ done = true
+ end
+ return head, done
+end
+
+local enable
+
+enable = function()
+ tasks.enableaction("processors","typesetters.italics.handler")
+ if trace_italics then
+ report_italics("enabling text italics")
+ end
+ enable = false
+end
+
+function italics.set(n)
+ if enable then
+ enable()
+ end
+ if n == variables.reset then
+ texattribute[a_italics] = unsetvalue
+ else
+ texattribute[a_italics] = tonumber(n) or unsetvalue
+ end
+end
+
+function italics.reset()
+ texattribute[a_italics] = unsetvalue
+end
+
+italics.handler = nodes.installattributehandler {
+ name = "italics",
+ namespace = italics,
+ processor = process,
+}
+
+local variables = interfaces.variables
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+function commands.setupitaliccorrection(option) -- no grouping !
+ if enable then
+ enable()
+ end
+ local options = settings_to_hash(option)
+ local variant = unsetvalue
+ if options[variables.text] then
+ variant = 1
+ elseif options[variables.always] then
+ variant = 2
+ end
+ if options[variables.global] then
+ forcedvariant = variant
+ texattribute[a_italics] = unsetvalue
+ else
+ forcedvariant = false
+ texattribute[a_italics] = variant
+ end
+ if trace_italics then
+ report_italics("force: %s, variant: %s",tostring(forcedvariant),tostring(variant ~= unsetvalue and variant))
+ end
+end
+
+-- for manuals:
+
+local stack = { }
+
+function commands.pushitaliccorrection()
+ table.insert(stack,{forcedvariant, texattribute[a_italics] })
+end
+
+function commands.popitaliccorrection()
+ local top = table.remove(stack)
+ forcedvariant = top[1]
+ texattribute[a_italics] = top[2]
+end
diff --git a/Master/texmf-dist/tex/context/base/typo-itc.mkvi b/Master/texmf-dist/tex/context/base/typo-itc.mkvi
new file mode 100644
index 00000000000..809c7a25245
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-itc.mkvi
@@ -0,0 +1,62 @@
+%D \module
+%D [ file=typo-itc,
+%D version=2011.10.08,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Italic Correction,
+%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 / Italics Corrections}
+
+\unprotect
+
+%D The brave might try:
+%D
+%D \starttyping
+%D \definefontfeature[default][default][itlc=yes,notextitalics=yes]
+%D \setupitaliccorrection[global,always]
+%D \stoptyping
+
+\registerctxluafile{typo-itc}{1.001}
+
+\definesystemattribute[italics][public]
+
+% \let\/=/
+% \let\emphasiscorrection\donothing
+
+\ifdefined \normalitaliccorrection \else
+ \let\normalitaliccorrection\italiccorrection
+\fi
+
+\unexpanded\def\italiccorrection
+ {\ifnum\attribute\italicsattribute<\plusone\normalitaliccorrection\fi}
+
+\let\/\italiccorrection
+
+% 1 = end of word
+% 2 = end of word and end of a list
+
+\unexpanded\def\setitaliccorrection[#code]% rather low level (might go away)
+ {\ctxlua{typesetters.italics.set(\number#code)}}
+
+\unexpanded\def\resetitaliccorrection% rather low level (might go away)
+ {\ctxlua{typesetters.italics.reset()}}
+
+% global : no attributes, just always (faster and less memory)
+% text : only text
+% always : text and boxes
+% none : -
+
+\unexpanded\def\setupitaliccorrection[#settings]%
+ {\ctxcommand{setupitaliccorrection("#settings")}}
+
+\appendtoks
+ \attribute\italicsattribute\attributeunsetvalue
+\to \everymathematics
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-krn.lua b/Master/texmf-dist/tex/context/base/typo-krn.lua
index a9428439cd8..54b1fd2d3cf 100644
--- a/Master/texmf-dist/tex/context/base/typo-krn.lua
+++ b/Master/texmf-dist/tex/context/base/typo-krn.lua
@@ -24,6 +24,7 @@ local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
local nodepool = nodes.pool
local tasks = nodes.tasks
@@ -45,11 +46,14 @@ local vlist_code = nodecodes.vlist
local kerning_code = kerncodes.kerning
local userkern_code = kerncodes.userkern
local userskip_code = skipcodes.userskip
+local spaceskip_code = skipcodes.spaceskip
+local xspaceskip_code = skipcodes.xspaceskip
local fonthashes = fonts.hashes
local fontdata = fonthashes.identifiers
local chardata = fonthashes.characters
local quaddata = fonthashes.quads
+local markdata = fonthashes.marks
typesetters = typesetters or { }
local typesetters = typesetters
@@ -60,6 +64,7 @@ local kerns = typesetters.kerns
kerns.mapping = kerns.mapping or { }
kerns.factors = kerns.factors or { }
local a_kerns = attributes.private("kern")
+local a_fontkern = attributes.private('fontkern')
kerns.attribute = kerns.attribute
storage.register("typesetters/kerns/mapping", kerns.mapping, "typesetters.kerns.mapping")
@@ -83,8 +88,8 @@ kerns.keeptogether = false -- just for fun (todo: control setting with key/value
local function do_process(namespace,attribute,head,force) -- todo: glue so that we can fully stretch
local start, done, lastfont = head, false, nil
-local keepligature = kerns.keepligature
-local keeptogether = kerns.keeptogether
+ local keepligature = kerns.keepligature
+ local keeptogether = kerns.keeptogether
while start do
-- faster to test for attr first
local attr = force or has_attribute(start,attribute)
@@ -97,55 +102,62 @@ local keeptogether = kerns.keeptogether
lastfont = start.font
local c = start.components
if c then
-if keepligature and keepligature(start) then
- -- keep 'm
-else
- c = do_process(namespace,attribute,c,attr)
- local s = start
- local p, n = s.prev, s.next
- local tail = find_node_tail(c)
- if p then
- p.next = c
- c.prev = p
+ if keepligature and keepligature(start) then
+ -- keep 'm
else
- head = c
- end
- if n then
- n.prev = tail
+ c = do_process(namespace,attribute,c,attr)
+ local s = start
+ local p, n = s.prev, s.next
+ local tail = find_node_tail(c)
+ if p then
+ p.next = c
+ c.prev = p
+ else
+ head = c
+ end
+ if n then
+ n.prev = tail
+ end
+ tail.next = n
+ start = c
+ s.components = nil
+ -- we now leak nodes !
+ -- free_node(s)
+ done = true
end
- tail.next = n
- start = c
- s.components = nil
- -- we now leak nodes !
- -- free_node(s)
- done = true
-end
end
local prev = start.prev
- if prev then
+ if not prev then
+ -- skip
+ elseif markdata[lastfont][start.char] then
+ -- skip
+ else
local pid = prev.id
if not pid then
-- nothing
- elseif pid == kern_code and prev.subtype == kerning_code then
-if keeptogether and prev.prev.id == glyph_code and keeptogether(prev.prev,start) then -- we could also pass start
- -- keep 'm
-else
- prev.subtype = userkern_code
- prev.kern = prev.kern + quaddata[lastfont]*krn -- here
- done = true
-end
+ elseif pid == kern_code then
+ if prev.subtype == kerning_code or has_attribute(prev,a_fontkern) then
+ if keeptogether and prev.prev.id == glyph_code and keeptogether(prev.prev,start) then -- we could also pass start
+ -- keep 'm
+ else
+ -- not yet ok, as injected kerns can be overlays (from node-inj.lua)
+ prev.subtype = userkern_code
+ prev.kern = prev.kern + quaddata[lastfont]*krn -- here
+ done = true
+ end
+ end
elseif pid == glyph_code then
if prev.font == lastfont then
local prevchar, lastchar = prev.char, start.char
-if keeptogether and keeptogether(prev,start) then
- -- keep 'm
-else
- local kerns = chardata[lastfont][prevchar].kerns
- local kern = kerns and kerns[lastchar] or 0
- krn = kern + quaddata[lastfont]*krn -- here
- insert_node_before(head,start,new_kern(krn))
- done = true
-end
+ if keeptogether and keeptogether(prev,start) then
+ -- keep 'm
+ else
+ local kerns = chardata[lastfont][prevchar].kerns
+ local kern = kerns and kerns[lastchar] or 0
+ krn = kern + quaddata[lastfont]*krn -- here
+ insert_node_before(head,start,new_kern(krn))
+ done = true
+ end
else
krn = quaddata[lastfont]*krn -- here
insert_node_before(head,start,new_kern(krn))
@@ -210,20 +222,25 @@ end
end
end
end
- elseif id == glue_code and start.subtype == userskip_code then
- local s = start.spec
- local w = s.width
- if w > 0 then
- local width, stretch, shrink = w+gluefactor*w*krn, s.stretch, s.shrink
- start.spec = new_gluespec(width,stretch*width/w,shrink*width/w)
- done = true
- end
- elseif false and id == kern_code and start.subtype == kerning_code then -- handle with glyphs
- local sk = start.kern
- if sk > 0 then
- start.kern = sk*krn
- done = true
+ elseif id == glue_code then
+ local subtype = start.subtype
+ if subtype == userskip_code or subtype == xspaceskip_code or subtype == spaceskip_code then
+ local s = start.spec
+ local w = s.width
+ if w > 0 then
+ local width, stretch, shrink = w+gluefactor*w*krn, s.stretch, s.shrink
+ start.spec = new_gluespec(width,stretch*width/w,shrink*width/w)
+ done = true
+ end
end
+ elseif id == kern_code then
+ -- if start.subtype == kerning_code then -- handle with glyphs
+ -- local sk = start.kern
+ -- if sk > 0 then
+ -- start.kern = sk*krn
+ -- done = true
+ -- end
+ -- end
elseif lastfont and (id == hlist_code or id == vlist_code) then -- todo: lookahead
local p = start.prev
if p and p.id ~= glue_code then
@@ -248,17 +265,19 @@ end
local enabled = false
function kerns.set(factor)
- if not enabled then
- tasks.enableaction("processors","typesetters.kerns.handler")
- enabled = true
- end
if factor ~= 0 then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.kerns.handler")
+ enabled = true
+ end
local a = factors[factor]
if not a then
a = #mapping + 1
factors[factors], mapping[a] = a, factor
end
factor = a
+ else
+ factor = unsetvalue
end
texattribute[a_kerns] = factor
return factor
@@ -273,3 +292,7 @@ kerns.handler = nodes.installattributehandler {
namespace = kerns,
processor = process,
}
+
+-- interface
+
+commands.setcharacterkerning = kerns.set
diff --git a/Master/texmf-dist/tex/context/base/typo-krn.mkiv b/Master/texmf-dist/tex/context/base/typo-krn.mkiv
index bb4a48a5d71..e1e404a7bef 100644
--- a/Master/texmf-dist/tex/context/base/typo-krn.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-krn.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Spacing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -23,34 +23,28 @@
%
% {\setcharacterkerning[extrakerning]\input davis\relax}
-\unexpanded\def\definecharacterkerning
- {\dodoubleargument\dodefinecharacterkerning}
+\installcorenamespace{characterkerning}
-\def\dodefinecharacterkerning[#1][#2]%
- {\getparameters[\??ck#1][\c!factor=0.125,#2]%
- \setuvalue{\??ck:#1}{\dosetcharacterkerning{#1}}}
+\installcommandhandler \??characterkerning {characterkerning} \??characterkerning
-\unexpanded\def\setupcharacterkerning
- {\dodoubleargument\dosetupcharacterkerning}
-
-\def\dosetupcharacterkerning[#1][#2]%
- {\ifcsname\??ck:#1\endcsname
- \getparameters[\??ck#1][#2]%
+\unexpanded\def\setcharacterkerning[#1]%
+ {\edef\currentcharacterkerning{#1}%
+ \ifx\currentcharacterkerning\s!reset
+ \resetcharacterkerning
\else
- \dodefinecharacterkerning[#1][#2]% bonus
+ \typo_kerning_set
\fi}
-\unexpanded\def\dosetcharacterkerning#1%
- {\ctxlua{typesetters.kerns.set(\csname\??ck#1\c!factor\endcsname)}}
+% \def\typo_kerning_set
+% {\ctxcommand{setcharacterkerning(\characterkerningparameter\c!factor)}}
-\unexpanded\def\setcharacterkerning[#1]%
- {\csname\??ck:#1\endcsname}
+\def\typo_kerning_set
+ {\usecharacterkerningstyleandcolor\c!style\c!color % goodie, maybe also strut
+ \ctxcommand{setcharacterkerning(\characterkerningparameter\c!factor)}}
\unexpanded\def\resetcharacterkerning % fast one
{\attribute\kernattribute\attributeunsetvalue}
-\letvalue{\??ck\s!reset\c!factor}\attributeunsetvalue % trick
-
\appendtoks
\resetcharacterkerning
\to \everyresettypesetting
@@ -65,23 +59,32 @@
%D \stoptyping
%D
%D We could combine this with the previous definition command but
-%D then we alwasy would get a command defined which is not beforehand
+%D then we always would get a command defined which is not beforehand
%D a good idea.
\def\v!kerncharacters{kerncharacters} % no time now for translations
\definecharacterkerning [\v!kerncharacters] [\c!factor=.125]
+% Here we need to keep the groupedcommand solution as it is
+% used as modifier.
+
\unexpanded\def\kerncharacters
- {\dosingleempty\dokerncharacters}
+ {\doifnextoptionalelse\typo_kerning_apply_yes\typo_kerning_apply_nop}
+
+\def\typo_kerning_apply_yes[#1]%
+ {\groupedcommand{\typo_kerning_apply_yes_indeed{#1}}\donothing}
+
+\def\typo_kerning_apply_nop
+ {\groupedcommand\typo_kerning_apply_nop_indeed\donothing}
-\def\dokerncharacters[#1]%
- {\groupedcommand{\dodokerncharacters{#1}}\donothing}
+\def\typo_kerning_apply_yes_indeed#1%
+ {\let\currentcharacterkerning\v!kerncharacters
+ \setupcurrentcharacterkerning[\c!factor=#1]%
+ \typo_kerning_set}
-\def\dodokerncharacters#1%
- {\iffirstargument
- \setupcharacterkerning[\v!kerncharacters][\c!factor=#1]%
- \fi
- \setcharacterkerning[\v!kerncharacters]}
+\def\typo_kerning_apply_nop_indeed
+ {\let\currentcharacterkerning\v!kerncharacters
+ \typo_kerning_set}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-mar.lua b/Master/texmf-dist/tex/context/base/typo-mar.lua
index 6bc98586888..a21d9b70a1b 100644
--- a/Master/texmf-dist/tex/context/base/typo-mar.lua
+++ b/Master/texmf-dist/tex/context/base/typo-mar.lua
@@ -13,94 +13,176 @@ if not modules then modules = { } end modules ['typo-mar'] = {
-- using margin data then as also vertical spacing kicks in
-- * floating margin data, with close-to-call anchoring
+-- -- experiment (does not work, too much interference)
+--
+-- local pdfprint = pdf.print
+-- local format = string.format
+--
+-- anchors = anchors or { }
+--
+-- local whatever = { }
+-- local factor = (7200/7227)/65536
+--
+-- function anchors.set(tag)
+-- whatever[tag] = { pdf.h, pdf.v }
+-- end
+--
+-- function anchors.reset(tag)
+-- whatever[tag] = nil
+-- end
+--
+-- function anchors.startmove(tag,how) -- save/restore nodes but they don't support moves
+-- local w = whatever[tag]
+-- if not w then
+-- -- error
+-- elseif how == "horizontal" or how == "h" then
+-- pdfprint("page",format(" q 1 0 0 1 %s 0 cm ", (w[1] - pdf.h) * factor))
+-- elseif how == "vertical" or how == "v" then
+-- pdfprint("page",format(" q 1 0 0 1 0 %s cm ", (w[2] - pdf.v) * factor))
+-- else
+-- pdfprint("page",format(" q 1 0 0 1 %s %s cm ", (w[1] - pdf.h) * factor, (w[2] - pdf.v) * factor))
+-- end
+-- end
+--
+-- function anchors.stopmove(tag)
+-- local w = whatever[tag]
+-- if not w then
+-- -- error
+-- else
+-- pdfprint("page"," Q ")
+-- end
+-- end
+--
+-- local latelua = nodes.pool.latelua
+--
+-- function anchors.node_set(tag)
+-- return latelua(format("anchors.set(%q)",tag))
+-- end
+--
+-- function anchors.node_reset(tag)
+-- return latelua(format("anchors.reset(%q)",tag))
+-- end
+--
+-- function anchors.node_start_move(tag,how)
+-- return latelua(format("anchors.startmove(%q,%q)",tag,how))
+-- end
+--
+-- function anchors.node_stop_move(tag)
+-- return latelua(format("anchors.stopmove(%q)",tag))
+-- end
+
+-- so far
+
local format = string.format
local insert, remove = table.insert, table.remove
local setmetatable, next = setmetatable, next
local attributes, nodes, node, variables = attributes, nodes, node, variables
-local trace_margindata = false trackers.register("typesetters.margindata", function(v) trace_margindata = v end)
+local trace_margindata = false trackers.register("typesetters.margindata", function(v) trace_margindata = v end)
+local trace_marginstack = false trackers.register("typesetters.margindata.stack", function(v) trace_marginstack = v end)
local report_margindata = logs.reporter("typesetters","margindata")
-local tasks = nodes.tasks
-local prependaction = tasks.prependaction
-local disableaction = tasks.disableaction
-local enableaction = tasks.enableaction
-
-local variables = interfaces.variables
-
-local conditionals = tex.conditionals
-
-local v_top = variables.top
-local v_depth = variables.depth
-local v_local = variables["local"]
-local v_global = variables["global"]
-local v_left = variables.left
-local v_right = variables.right
-local v_flushleft = variables.flushleft
-local v_flushright = variables.flushright
-local v_inner = variables.inner
-local v_outer = variables.outer
-local v_margin = variables.margin
-local v_edge = variables.edge
-local v_default = variables.default
-local v_normal = variables.normal
-local v_yes = variables.yes
-local v_first = variables.first
-
-local has_attribute = node.has_attribute
-local set_attribute = node.set_attribute
-local unset_attribute = node.unset_attribute
-local copy_node_list = node.copy_list
-local slide_nodes = node.slide
-local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here
-local traverse_id = node.traverse_id
-local free_node_list = node.free_list
-
-local link_nodes = nodes.link
-
-local nodecodes = nodes.nodecodes
-local listcodes = nodes.listcodes
-local gluecodes = nodes.gluecodes
-local whatsitcodes = nodes.whatsitcodes
-
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glue_code = nodecodes.glue
-local whatsit_code = nodecodes.whatsit
-local line_code = listcodes.line
-local leftskip_code = gluecodes.leftskip
-local rightskip_code = gluecodes.rightskip
-local userdefined_code = whatsitcodes.userdefined
-
-local nodepool = nodes.pool
-
-local new_kern = nodepool.kern
-local new_stretch = nodepool.stretch
-local new_usernumber = nodepool.usernumber
-
-local texcount = tex.count
-local texdimen = tex.dimen
-local texbox = tex.box
-
-local isleftpage = layouts.status.isleftpage
-
-local a_margindata = attributes.private("margindata")
-
-local inline_mark = nodepool.userids["margins.inline"]
-
-local margins = { }
-typesetters.margins = margins
-
-local locations = { v_left, v_right, v_inner, v_outer } -- order might change
-local categories = { }
-local displaystore = { } -- [category][location][scope]
-local inlinestore = { } -- [number]
-local nofsaved = 0
-local nofstored = 0
-local nofinlined = 0
-local nofdelayed = 0
+local tasks = nodes.tasks
+local prependaction = tasks.prependaction
+local disableaction = tasks.disableaction
+local enableaction = tasks.enableaction
+
+local variables = interfaces.variables
+
+local conditionals = tex.conditionals
+
+local v_top = variables.top
+local v_depth = variables.depth
+local v_local = variables["local"]
+local v_global = variables["global"]
+local v_left = variables.left
+local v_right = variables.right
+local v_flushleft = variables.flushleft
+local v_flushright = variables.flushright
+local v_inner = variables.inner
+local v_outer = variables.outer
+local v_margin = variables.margin
+local v_edge = variables.edge
+local v_default = variables.default
+local v_normal = variables.normal
+local v_yes = variables.yes
+local v_continue = variables.continue
+local v_first = variables.first
+local v_text = variables.text
+local v_column = variables.column
+
+local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+local unset_attribute = node.unset_attribute
+local copy_node_list = node.copy_list
+local slide_nodes = node.slide
+local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here
+local traverse_id = node.traverse_id
+local free_node_list = node.flush_list
+local insert_node_after = node.insert_after
+local insert_node_before = node.insert_before
+
+local link_nodes = nodes.link
+
+local nodecodes = nodes.nodecodes
+local listcodes = nodes.listcodes
+local gluecodes = nodes.gluecodes
+local whatsitcodes = nodes.whatsitcodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local penalty_code = nodecodes.penalty
+local whatsit_code = nodecodes.whatsit
+local line_code = listcodes.line
+local leftskip_code = gluecodes.leftskip
+local rightskip_code = gluecodes.rightskip
+local userdefined_code = whatsitcodes.userdefined
+
+local dir_code = whatsitcodes.dir
+local localpar_code = whatsitcodes.localpar
+
+local nodepool = nodes.pool
+
+local new_kern = nodepool.kern
+local new_glue = nodepool.glue
+local new_penalty = nodepool.penalty
+local new_stretch = nodepool.stretch
+local new_usernumber = nodepool.usernumber
+local new_latelua = nodepool.latelua
+
+local texcount = tex.count
+local texdimen = tex.dimen
+local texbox = tex.box
+
+local points = number.points
+
+local isleftpage = layouts.status.isleftpage
+local registertogether = builders.paragraphs.registertogether
+
+local jobpositions = job.positions
+local getposition = jobpositions.position
+
+local a_margindata = attributes.private("margindata")
+
+local inline_mark = nodepool.userids["margins.inline"]
+
+local margins = { }
+typesetters.margins = margins
+
+local locations = { v_left, v_right, v_inner, v_outer } -- order might change
+local categories = { }
+local displaystore = { } -- [category][location][scope]
+local inlinestore = { } -- [number]
+local nofsaved = 0
+local nofstored = 0
+local nofinlined = 0
+local nofdelayed = 0
+local h_anchors = 0
+local v_anchors = 0
local mt1 = {
__index = function(t,location)
@@ -140,11 +222,24 @@ local defaults = {
dy = 0,
baseline = false,
inline = false,
+ leftskip = 0,
+ rightskip = 0,
}
}
local enablelocal, enableglobal -- forward reference (delayed initialization)
+local function showstore(store,banner)
+ if next(store) then
+ for i, si in table.sortedpairs(store) do
+ local si =store[i]
+ report_margindata("%s: stored at %s: %s => %s",banner,i,si.name or "no name",nodes.toutf(si.box.list))
+ end
+ else
+ report_margindata("%s: nothing stored",banner)
+ end
+end
+
function margins.save(t)
setmetatable(t,defaults)
local inline = t.inline
@@ -166,52 +261,73 @@ function margins.save(t)
report_margindata("invalid scope: %s",scope)
return
end
- if enablelocal and scope == "local" then
+ if enablelocal and scope == v_local then
enablelocal()
end
- if enableglobal and scope == "global" then
+ if enableglobal and scope == v_global then
enableglobal()
end
nofsaved = nofsaved + 1
nofstored = nofstored + 1
local name = t.name
+ if trace_marginstack then
+ showstore(store,"before ")
+ end
if name and name ~= "" then
- for i=#store,1,-1 do
- local si = store[i]
- if si.name == name then
- local s = remove(store,i)
- free_node_list(s.box)
+ if inlinestore then -- todo: inline store has to be done differently (not sparse)
+ local t = table.sortedkeys(store) for j=#t,1,-1 do local i = t[j]
+ local si = store[i]
+ if si.name == name then
+ local s = remove(store,i)
+ free_node_list(s.box)
+ end
+ end
+ else
+ for i=#store,1,-1 do
+ local si = store[i]
+ if si.name == name then
+ local s = remove(store,i)
+ free_node_list(s.box)
+ end
end
end
+ if trace_marginstack then
+ showstore(store,"between")
+ end
end
- -- better make a new table and make t entry in t
- t.box = copy_node_list(texbox[t.number])
- t.n = nofsaved
- -- used later (we will clean up this natural mess later)
- -- nice is to make a special status table mechanism
- local leftmargindistance = texdimen.naturalleftmargindistance
- local rightmargindistance = texdimen.naturalrightmargindistance
- t.strutdepth = texbox.strutbox.depth
- t.strutheight = texbox.strutbox.height
- t.leftskip = tex.leftskip.width
- t.rightskip = tex.rightskip.width
- t.leftmargindistance = leftmargindistance
- t.rightmargindistance = rightmargindistance
- t.leftedgedistance = texdimen.naturalleftedgedistance
- + texdimen.leftmarginwidth
- + leftmargindistance
- t.rightedgedistance = texdimen.naturalrightedgedistance
- + texdimen.rightmarginwidth
- + rightmargindistance
- t.lineheight = texdimen.lineheight
- --
- -- t.realpageno = texcount.realpageno
- if inline then
- context(new_usernumber(inline_mark,nofsaved))
- store[nofsaved] = t -- no insert
- nofinlined = nofinlined + 1
- else
- insert(store,t)
+ if t.number then
+ -- better make a new table and make t entry in t
+ t.box = copy_node_list(texbox[t.number])
+ t.n = nofsaved
+ -- used later (we will clean up this natural mess later)
+ -- nice is to make a special status table mechanism
+ local leftmargindistance = texdimen.naturalleftmargindistance
+ local rightmargindistance = texdimen.naturalrightmargindistance
+ t.strutdepth = texbox.strutbox.depth
+ t.strutheight = texbox.strutbox.height
+ t.leftskip = tex.leftskip.width -- we're not in forgetall
+ t.rightskip = tex.rightskip.width -- we're not in forgetall
+ t.leftmargindistance = leftmargindistance -- todo:layoutstatus table
+ t.rightmargindistance = rightmargindistance
+ t.leftedgedistance = texdimen.naturalleftedgedistance
+ + texdimen.leftmarginwidth
+ + leftmargindistance
+ t.rightedgedistance = texdimen.naturalrightedgedistance
+ + texdimen.rightmarginwidth
+ + rightmargindistance
+ t.lineheight = texdimen.lineheight
+ --
+ -- t.realpageno = texcount.realpageno
+ if inline then
+ context(new_usernumber(inline_mark,nofsaved))
+ store[nofsaved] = t -- no insert
+ nofinlined = nofinlined + 1
+ else
+ insert(store,t)
+ end
+ end
+ if trace_marginstack then
+ showstore(store,"after ")
end
if trace_margindata then
report_margindata("saved: %s, location: %s, scope: %s, inline: %s",nofsaved,location,scope,tostring(inline))
@@ -258,6 +374,7 @@ local function realign(current,candidate)
if leftpage then
leftdistance, rightdistance = rightdistance, leftdistance
end
+
if location == v_left then
delta = hoffset + width + leftdistance + leftdelta
elseif location == v_right then
@@ -275,14 +392,54 @@ local function realign(current,candidate)
delta = -hoffset - hsize - rightdistance + rightdelta
end
end
+
-- we assume that list is a hbox, otherwise we had to take the whole current
-- in order to get it right
+
current.width = 0
- current.list = hpack_nodes(link_nodes(new_kern(-delta),current.list,new_kern(delta)))
- current.width = 0
- if trace_margindata then
- report_margindata("realigned: %s, location: %s, margin: %s",candidate.n,location,margin)
+ local anchornode, move_x
+
+ -- this mess is needed for alignments (combinations) so we use that
+ -- oportunity to add arbitrary anchoring
+
+ -- always increment anchor is nicer for multipass when we add new ..
+
+ local inline = candidate.inline
+ local anchor = candidate.anchor
+ if not anchor or anchor == "" then
+ anchor = v_text
+ end
+ if inline or anchor ~= v_text then
+ h_anchors = h_anchors + 1
+ anchornode = new_latelua(format("_plib_.set('md:h',%i,{x=true,c=true})",h_anchors))
+ local blob = jobpositions.get('md:h', h_anchors)
+ if blob then
+ local reference = jobpositions.getreserved(anchor,blob.c)
+ if reference then
+ if location == v_left then
+ move_x = (reference.x or 0) - (blob.x or 0)
+ elseif location == v_right then
+ move_x = (reference.x or 0) - (blob.x or 0) + (reference.w or 0) - hsize
+ else
+ -- not yet done
+ end
+ end
+ end
end
+
+ if move_x then
+ delta = delta - move_x
+ if trace_margindata then
+ report_margindata("realigned: %s, location: %s, margin: %s, move: %s",candidate.n,location,margin,points(move_x))
+ end
+ else
+ if trace_margindata then
+ report_margindata("realigned: %s, location: %s, margin: %s",candidate.n,location,margin)
+ end
+ end
+
+ current.list = hpack_nodes(link_nodes(anchornode,new_kern(-delta),current.list,new_kern(delta))) -- anchor == nil is ok in link_nodes
+ current.width = 0
end
local function realigned(current,a)
@@ -293,15 +450,57 @@ local function realigned(current,a)
return true
end
-local stacked = { }
+-- Stacking is done in two ways: the v_yes option stacks per paragraph (or line,
+-- depending on what gets by) and mostly concerns margin data dat got set at more or
+-- less the same time. The v_continue option uses position tracking and works on
+-- larger range. However, crossing pages is not part of it. Anyway, when you have
+-- such messed up margin data you'd better think twice.
+--
+-- The stacked table keeps track (per location) of the offsets (the v_yes case). This
+-- table gets saved when the v_continue case is active. We use a special variant
+-- of position tracking, after all we only need the page number and vertical position.
+
+local stacked = { } -- left/right keys depending on location
+local cache = { }
local function resetstacked()
- for i=1,#locations do
- stacked[locations[i]] = false
- end
+ stacked = { }
+end
+
+-- resetstacked()
+
+function margins.ha(tag) -- maybe l/r keys ipv left/right keys
+ local p = cache[tag]
+ p.p = true
+ p.y = true
+ jobpositions.set('md:v',tag,p)
+ cache[tag] = nil
+end
+
+local function markovershoot(current)
+ v_anchors = v_anchors + 1
+ cache[v_anchors] = stacked
+ local anchor = new_latelua(format("typesetters.margins.ha(%s)",v_anchors)) -- todo: alleen als offset > line
+ current.list = hpack_nodes(link_nodes(anchor,current.list))
end
-resetstacked()
+local function getovershoot(location)
+ local p = jobpositions.get("md:v",v_anchors)
+ local c = jobpositions.get("md:v",v_anchors+1)
+ if p and c and p.p and p.p == c.p then
+ local distance = p.y - c.y
+ local offset = p[location] or 0
+ local overshoot = offset - distance
+ if trace_marginstack then
+ report_margindata("location: %s, distance: %s, offset: %s, overshoot: %s",
+ location,points(distance),points(offset),points(overshoot))
+ end
+ if overshoot > 0 then
+ return overshoot
+ end
+ end
+ return 0
+end
local function inject(parent,head,candidate)
local box = candidate.box
@@ -315,8 +514,10 @@ local function inject(parent,head,candidate)
local voffset = candidate.voffset
local line = candidate.line
local baseline = candidate.baseline
+ local strutheight = candidate.strutheight
+ local strutdepth = candidate.strutdepth
local offset = stacked[location]
- local firstonstack = offset == false
+ local firstonstack = offset == false or offset == nil
nofstatus = nofstatus + 1
nofdelayed = nofdelayed + 1
status[nofstatus] = candidate
@@ -328,17 +529,32 @@ local function inject(parent,head,candidate)
--~ baseline = h.height
--~ break
--~ end
+ else
+ baseline = tonumber(baseline)
+ if not baseline or baseline <= 0 then
+ -- in case we have a box of width 0 that is not analyzed
+ baseline = false -- strutheight -- actually a hack
+ end
end
candidate.width = width
candidate.hsize = parent.width -- we can also pass textwidth
+ if trace_margindata then
+ report_margindata("processing, index %s, height: %s, depth: %s",candidate.n,height,depth)
+ end
if firstonstack then
offset = 0
else
- offset = offset + height
+-- offset = offset + height
end
if stack == v_yes then
offset = offset + candidate.dy
shift = shift + offset
+ elseif stack == v_continue then
+ offset = offset + candidate.dy
+ if firstonstack then
+ offset = offset + getovershoot(location)
+ end
+ shift = shift + offset
end
-- -- --
-- Maybe we also need to patch offset when we apply methods, but how ...
@@ -349,7 +565,7 @@ local function inject(parent,head,candidate)
if method == v_top then
local delta = height - parent.height
if trace_margindata then
- report_margindata("top aligned: %s, amount: %s",candidate.n,delta)
+ report_margindata("top aligned, amount: %s",delta)
end
if delta < candidate.threshold then
shift = shift + voffset + delta
@@ -360,46 +576,77 @@ local function inject(parent,head,candidate)
else
shift = shift + voffset -- normal
end
+ if trace_margindata then
+ report_margindata("first aligned")
+ end
elseif method == v_depth then
- local delta = candidate.strutdepth
+ local delta = strutdepth
if trace_margindata then
- report_margindata("depth aligned, amount: %s",candidate.n,delta)
+ report_margindata("depth aligned, amount: %s",delta)
end
shift = shift + voffset + delta
elseif method == v_height then
- local delta = - candidate.strutheight
+ local delta = - strutheight
if trace_margindata then
- report_margindata("height aligned, amount: %s",candidate.n,delta)
+ report_margindata("height aligned, amount: %s",delta)
end
shift = shift + voffset + delta
elseif voffset ~= 0 then
+ if trace_margindata then
+ report_margindata("voffset applied: %s",voffset)
+ end
shift = shift + voffset
end
-- -- --
if line ~= 0 then
local delta = line * candidate.lineheight
+ if trace_margindata then
+ report_margindata("line offset applied: %s (%s)",line,delta)
+ end
shift = shift + delta
offset = offset + delta
end
box.shift = shift
box.width = 0
- if head then
+ if not head then
+ head = box
+ elseif head.id == whatsit_code and head.subtype == localpar_code then
+ -- experimental
+ if head.dir == "TRT" then
+ box.list = hpack_nodes(link_nodes(new_kern(candidate.hsize),box.list,new_kern(-candidate.hsize)))
+ end
+ insert_node_after(head,head,box)
+ else
head.prev = box
box.next = head
+ head = box
end
- head = box
set_attribute(box,a_margindata,nofstatus)
if trace_margindata then
- report_margindata("injected: %s, location: %s",candidate.n,location)
+ report_margindata("injected, location: %s, shift: %s",location,shift)
end
-- we need to add line etc to offset as well
offset = offset + depth
- stacked[location] = offset
- return head
+ local room = {
+ height = height,
+ depth = offset,
+ slack = candidate.bottomspace, -- todo: 'depth' => strutdepth
+ lineheight = candidate.lineheight, -- only for tracing
+ }
+ offset = offset + height
+ stacked[location] = offset -- weird, no table ?
+ -- todo: if no real depth then zero
+ if trace_margindata then
+ report_margindata("status, offset: %s",offset)
+ end
+ return head, room, stack == v_continue
end
-local function flushinline(parent,head,done)
+local function flushinline(parent,head)
local current = head
+ local done = false
+ local continue = false
+ local room, don, con
while current and nofinlined > 0 do
local id = current.id
if id == whatsit_code then
@@ -409,34 +656,43 @@ local function flushinline(parent,head,done)
if candidate then -- no vpack, as we want to realign
inlinestore[n] = nil
nofinlined = nofinlined - 1
- head = inject(parent,head,candidate) -- maybe return applied offset
+ head, room, con = inject(parent,head,candidate) -- maybe return applied offset
+ continue = continue or con
done = true
nofstored = nofstored - 1
end
end
elseif id == hlist_code or id == vlist_code then
-- optional (but sometimes needed)
- current.list, done = flushinline(current,current.list,done)
+ current.list, don, con = flushinline(current,current.list)
+ continue = continue or con
+ done = done or don
end
current = current.next
end
- return head, done
+ return head, done, continue
end
+local a_linenumber = attributes.private('linenumber')
+
local function flushed(scope,parent) -- current is hlist
- local done = false
local head = parent.list
+ local done = false
+ local continue = false
+ local room, con, don
for c=1,#categories do
local category = categories[c]
for l=1,#locations do
local location = locations[l]
local store = displaystore[category][location][scope]
while true do
- local candidate = remove(store,1)
+ local candidate = remove(store,1) -- brr, local stores are sparse
if candidate then -- no vpack, as we want to realign
- head = inject(parent,head,candidate) -- maybe return applied offset
+ head, room, con = inject(parent,head,candidate)
done = true
+ continue = continue or con
nofstored = nofstored - 1
+ registertogether(parent,room)
else
break
end
@@ -447,13 +703,19 @@ local function flushed(scope,parent) -- current is hlist
if done then
parent.list = head
end
- head, done = flushinline(parent,head,false)
+ head, don, con = flushinline(parent,head)
+ continue = continue or con
+ done = done or don
end
if done then
+local a = has_attribute(head,a_linenumber) -- hack .. we need a more decent critical attribute inheritance mechanism
parent.list = hpack_nodes(head,parent.width,"exactly")
- resetstacked()
+if a then
+ set_attribute(parent.list,a_linenumber,a)
+end
+ -- resetstacked()
end
- return done
+ return done, continue
end
-- only when group : vbox|vmode_par
@@ -461,16 +723,20 @@ end
local function handler(scope,head,group)
if nofstored > 0 then
- -- if trace_margindata then
- -- report_margindata("flushing stage one, stored: %s, scope: %s, delayed: %s, group: %s",nofstored,scope,nofdelayed,group)
- -- end
+ if trace_margindata then
+ report_margindata("flushing stage one, stored: %s, scope: %s, delayed: %s, group: %s",nofstored,scope,nofdelayed,group)
+ end
local current = head
local done = false
while current do
local id = current.id
if (id == vlist_code or id == hlist_code) and not has_attribute(current,a_margindata) then
- if flushed(scope,current) then
+ local don, continue = flushed(scope,current)
+ if don then
set_attribute(current,a_margindata,0) -- signal to prevent duplicate processing
+ if continue then
+ markovershoot(current)
+ end
if nofstored <= 0 then
break
end
@@ -480,7 +746,7 @@ local function handler(scope,head,group)
current = current.next
end
-- if done then
- -- resetstacked()
+ resetstacked() -- why doesn't done work ok here?
-- end
return head, done
else
@@ -492,17 +758,23 @@ function margins.localhandler(head,group)
if conditionals.inhibitmargindata then
return head, false
elseif nofstored > 0 then
- return handler("local",head,group)
+ return handler(v_local,head,group)
else
return head, false
end
end
-function margins.globalhandler(head,group)
---~ print(group)
- if conditionals.inhibitmargindata then
+function margins.globalhandler(head,group) -- check group
+-- print(group)
+ if conditionals.inhibitmargindata or nofstored == 0 then
return head, false
- elseif nofstored > 0 and group == "hmode_par" then
+ elseif group == "hmode_par" then
+ return handler("global",head,group)
+ elseif group == "vmode_par" then -- experiment (for alignments)
+ return handler("global",head,group)
+ -- this needs checking as we then get quite some one liners to process and
+ -- we cannot look ahead then:
+ elseif group == "box" then -- experiment (for alignments)
return handler("global",head,group)
else
return head, false
@@ -547,19 +819,22 @@ function margins.finalhandler(head)
end
end
+-- Somehow the vbox builder (in combinations) gets pretty confused and decides to
+-- go horizontal. So this needs more testing.
+
prependaction("finalizers", "lists", "typesetters.margins.localhandler")
-prependaction("vboxbuilders", "normalizers", "typesetters.margins.localhandler")
+-- prependaction("vboxbuilders", "normalizers", "typesetters.margins.localhandler")
prependaction("mvlbuilders", "normalizers", "typesetters.margins.globalhandler")
prependaction("shipouts", "normalizers", "typesetters.margins.finalhandler")
disableaction("finalizers", "typesetters.margins.localhandler")
-disableaction("vboxbuilders", "typesetters.margins.localhandler")
+-- disableaction("vboxbuilders", "typesetters.margins.localhandler")
disableaction("mvlbuilders", "typesetters.margins.globalhandler")
disableaction("shipouts", "typesetters.margins.finalhandler")
enablelocal = function()
enableaction("finalizers", "typesetters.margins.localhandler")
- enableaction("vboxbuilders", "typesetters.margins.localhandler")
+ -- enableaction("vboxbuilders", "typesetters.margins.localhandler")
enableaction("shipouts", "typesetters.margins.finalhandler")
enablelocal = nil
end
@@ -572,7 +847,7 @@ end
statistics.register("margin data", function()
if nofsaved > 0 then
- return string.format("%s entries, %s pending",nofsaved,nofdelayed)
+ return format("%s entries, %s pending",nofsaved,nofdelayed)
else
return nil
end
diff --git a/Master/texmf-dist/tex/context/base/typo-mar.mkiv b/Master/texmf-dist/tex/context/base/typo-mar.mkiv
index aba3ef95a74..a393fc25098 100644
--- a/Master/texmf-dist/tex/context/base/typo-mar.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-mar.mkiv
@@ -7,7 +7,7 @@
%D subtitle=Margindata,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -99,11 +99,11 @@
%D argument concerns the data, the second the framed. Not sharing the setup is
%D on purpose: location, offset, alignment and other parameters might clash.
-\def\??mc{@@mc} % margincategory
-\def\??mf{@@mf} % marginframed
+\installcorenamespace{margindata}
+\installcorenamespace{marginframed}
-\installcommandhandler\??mc{margindata}\??mc
-\installcommandhandler\??mf{marginframed}\??mf
+\installcommandhandler \??margindata {margindata} \??margindata
+\installframedcommandhandler \??marginframed {marginframed} \??marginframed
\setupmargindata
[\c!location=\v!left,
@@ -119,6 +119,8 @@
\c!width=,
% \c!stack=,
\c!line=0,
+ \c!anchor=\v!text,
+ \c!bottomspace=\strutdepth, % slack used for keeptogether
\c!dy=\zeropoint,
\c!distance=\zeropoint,
\c!hoffset=\zeropoint,
@@ -139,95 +141,166 @@
\newconditional\inhibitmargindata % This one is used at the Lua end!
\newtoks \everymargindatacontent % Later on we will set this one.
-\unexpanded\def\margindata[#name]%
- {\setfalse\inhibitmargindata % flushing afterwards
- \begingroup
- %\settrue\inhibitmargindata % no flushing in here
- \def\currentmargindata{#name}%
- \dodoubleempty\domargindata}
-
\appendtoks
\settrue\inhibitmargindata
\to \everyforgetall
-% option test -> ruled
-
\appendtoks
\forgetall
\tf
\deactivatecolor
\to \everymargindatacontent
-\unexpanded\def\domargindata[#dataparameters][#textparameters]#content%
+% trialtypesetting: no need for margin stuff while trialing as
+% is has no dimensions
+
+\definesystemconstant{margintext}
+
+\newcount\nofmargintexts
+
+\definepagestate[\s!margintext]
+
+\unexpanded\def\typo_margins_data_synchronize
+ {\doforcedtrackpagestate\s!margintext\nofmargintexts % includes increment
+ \docheckpagestate\s!margintext\nofmargintexts
+ %\doifrightpagestateelse\s!margintext\nofmargintexts\relax\relax
+ \realpageno\realpagestateno
+ \swapmargins}
+
+\unexpanded\def\margindata
+ {\iftrialtypesetting
+ \expandafter\typo_margins_data_nop
+ \else
+ \expandafter\typo_margins_data_yes
+ \fi}
+
+\def\typo_margins_data_nop[#name]%
+ {\dodoubleempty\typo_margins_data_nop_indeed}
+
+\def\typo_margins_data_yes[#name]%
+ {\setfalse\inhibitmargindata % flushing afterwards
+ \begingroup
+ %\settrue\inhibitmargindata % no flushing in here
+ \def\currentmargindata{#name}%
+ \let\currentmarginframed\currentmargindata
+ \dodoubleempty\typo_margins_data_yes_indeed}
+
+\unexpanded\def\typo_margins_data_nop_indeed[#dataparameters][#textparameters]#content%
+ {}
+
+\unexpanded\def\typo_margins_data_yes_indeed[#dataparameters][#textparameters]#content%
{\iffirstargument
- \setupmargindata[\currentmargindata][#dataparameters]%
+ \setupcurrentmargindata[#dataparameters]%
\fi
- \edef\currentmargindatastrut{\margindataparameter\c!strut}%
- \the\everymargindatacontent
- \dostarttagged\t!margintext\currentmargindata
- \ifcsname\??mf\currentmargindata\s!parent\endcsname
- \setbox\nextbox\hbox\bgroup
- \the\everymargindatacontent
- \dosetmargindataattributes\c!style\c!color
- \localframedwithsettings[\??mf\currentmargindata][\c!location=\v!normal,#textparameters]\bgroup
- \ifx\currentmargindatastrut\empty \else
- \dosetupstrut[\currentmargindatastrut]%
- \fi
- \begstrut\margindataparameter\c!command{#content}\endstrut
- \egroup
- \egroup
- \edef\currentmarginfirstheight{\number\dimexpr\framedfirstheight}%
- \else
- \edef\currentmargindatawidth{\margindataparameter\c!width}%
- \ifx\currentmargindatawidth\empty
- \setbox\nextbox\hbox\bgroup
+ \doifelsenothing{#content}\donefalse\donetrue
+ \ifdone
+ \edef\currentmarginreference{\margindataparameter\c!reference}%
+ \ifx\currentmarginreference\empty \else
+ \strc_references_set_page_only_destination_box_attribute\currentmarginreference\currentmarginreference
+ \fi
+ \edef\currentmargindatastrut{\margindataparameter\c!strut}%
+ \dostarttagged\t!margintext\currentmargindata
+ \ifcsname\currentmarginframedhash\s!parent\endcsname
+ \setbox\nextbox\hbox \currentmarginreference \bgroup
\the\everymargindatacontent
- \dosetmargindataattributes\c!style\c!color
- \ifx\currentmargindatastrut\empty \else
- \dosetupstrut[\currentmargindatastrut]%
- \fi
- \begstrut\margindataparameter\c!command{#content}\endstrut
+ \usemargindatastyleandcolor\c!style\c!color
+ \setupcurrentmarginframed[\c!location=\v!normal,#textparameters]%
+\typo_margins_data_synchronize
+ \inheritedmarginframedframed\bgroup
+ \ifx\currentmargindatastrut\empty \else
+ \synchronizestrut\currentmargindatastrut
+ \fi
+ \begstrut
+ \strc_references_flush_destination_nodes
+ \margindataparameter\c!command{#content}%
+ \endstrut
+ \egroup
\egroup
- \let\currentmarginfirstheight\empty
+ \edef\currentmarginfirstheight{\number\dimexpr\framedfirstheight}%
\else
- \dosetraggedcommand{\margindataparameter\c!align}%
- \setbox\nextbox\hbox \bgroup\vtop \bgroup % hbox is needed
- \the\everymargindatacontent
- \dosetmargindataattributes\c!style\c!color
- \hsize\currentmargindatawidth
- \raggedcommand
- \ifx\currentmargindatastrut\empty \else
- \dosetupstrut[\currentmargindatastrut]%
- \fi
- \begstrut\margindataparameter\c!command{#content}\endstrut
- \egroup \egroup
- \edef\currentmarginfirstheight{true}%
+ \edef\currentmargindatawidth{\margindataparameter\c!width}%
+ \ifx\currentmargindatawidth\empty
+ \setbox\nextbox\hbox \currentmarginreference \bgroup
+\typo_margins_data_synchronize
+ \the\everymargindatacontent
+ \usemargindatastyleandcolor\c!style\c!color
+ \ifx\currentmargindatastrut\empty \else
+ \synchronizestrut\currentmargindatastrut
+ \fi
+ \begstrut
+ \strc_references_flush_destination_nodes
+ \margindataparameter\c!command{#content}%
+ \endstrut
+ \egroup
+ \let\currentmarginfirstheight\empty
+ \else
+ \setbox\nextbox\hbox \currentmarginreference \bgroup
+\typo_margins_data_synchronize
+ \dosetraggedcommand{\margindataparameter\c!align}%
+ \vtop \bgroup
+ \the\everymargindatacontent
+ \usemargindatastyleandcolor\c!style\c!color
+ \hsize\currentmargindatawidth
+ \raggedcommand
+ \ifx\currentmargindatastrut\empty \else
+ \dosetupstrut[\currentmargindatastrut]%
+ \fi
+ \begstrut
+ \strc_references_flush_destination_nodes
+ \margindataparameter\c!command{#content}%
+ \endstrut
+ \egroup
+ \egroup
+ \edef\currentmarginfirstheight{true}%
+ \fi
\fi
+ \dostoptagged
\fi
- \dostoptagged
- \ctxlua{typesetters.margins.save{
- \c!location = "\margindataparameter\c!location",
- \c!method = "\margindataparameter\c!method",
- \c!category = "\margindataparameter\c!category",
- \c!name = "\margindataparameter\c!name",
- \c!margin = "\margindataparameter\c!margin", % local normal margin edge
- \c!distance = \number\dimexpr\margindataparameter\c!distance,
- \c!hoffset = \number\dimexpr\margindataparameter\c!hoffset,
- \c!voffset = \number\dimexpr\margindataparameter\c!voffset,
- \c!dy = \number\dimexpr\margindataparameter\c!dy,
- \ifx\currentmarginfirstheight\empty \else
- baseline = \currentmarginfirstheight,
- \fi
- threshold = \number\dimexpr\margindataparameter\c!threshold, % will change
- \ifhmode
- inline = true,
+ \ifdone
+ \anch_positions_initialize % we use positions at the lua end
+ \ctxlua{typesetters.margins.save{
+ location = "\margindataparameter\c!location",
+ method = "\margindataparameter\c!method",
+ category = "\margindataparameter\c!category",
+ name = "\margindataparameter\c!name",
+ margin = "\margindataparameter\c!margin", % local normal margin edge
+ distance = \number\dimexpr\margindataparameter\c!distance,
+ hoffset = \number\dimexpr\margindataparameter\c!hoffset,
+ voffset = \number\dimexpr\margindataparameter\c!voffset,
+ dy = \number\dimexpr\margindataparameter\c!dy,
+ bottomspace = \number\dimexpr\margindataparameter\c!bottomspace,
+ \ifx\currentmarginfirstheight\empty \else
+ baseline = \currentmarginfirstheight,
+ \fi
+ threshold = \number\dimexpr\margindataparameter\c!threshold, % overlap related, will change
+ \ifhmode
+ inline = true,
+ \fi
+ anchor = "\margindataparameter\c!anchor",
+ %
+ % we're not in forgetall
+ %
+ % \ifzeropt\leftskip \else
+ % leftskip = \number\leftskip,
+ % \fi
+ % \ifzeropt\leftskip \else
+ % rightskip = \number\rightskip,
+ % \fi
+ scope = "\margindataparameter\c!scope",
+ align = "\margindataparameter\c!align",
+ line = \number\margindataparameter\c!line,
+ stack = "\margindataparameter\c!stack",
+ number = \number\nextbox,
+ }}%
+ \else
+ \ctxlua{typesetters.margins.save{
+ location = "\margindataparameter\c!location",
+ method = "\margindataparameter\c!method",
+ category = "\margindataparameter\c!category",
+ name = "\margindataparameter\c!name",
+ scope = "\margindataparameter\c!scope",
+ }}%
\fi
- \c!scope = "\margindataparameter\c!scope",
- \c!align = "\margindataparameter\c!align",
- \c!line = "\margindataparameter\c!line",
- \c!stack = "\margindataparameter\c!stack",
- \c!number = \number\nextbox
- }}%
\endgroup}
%D Downward compatible hack:
@@ -241,23 +314,25 @@
%D Another one:
-% \letvalue{\??mc->\v!left }\v!right
-% \letvalue{\??mc->\v!right }\v!left
-% \letvalue{\??mc->\v!inner }\v!outer
-% \letvalue{\??mc->\v!outer }\v!inner
-% \letvalue{\??mc->\v!normal}\v!normal
+% \installcorenamespace{oppositemargin}
+%
+% \letvalue{\??oppositemargin\v!left }\v!right
+% \letvalue{\??oppositemargin\v!right }\v!left
+% \letvalue{\??oppositemargin\v!inner }\v!outer
+% \letvalue{\??oppositemargin\v!outer }\v!inner
+% \letvalue{\??oppositemargin\v!normal}\v!normal
%
% \def\oppositemargin#1%
-% {\csname\??mc->\ifcsname\??mc->#1\endcsname#1\else\v!normal\fi\endcsname}
+% {\csname\??oppositemargin\ifcsname\??oppositemargin#1\endcsname#1\else\v!normal\fi\endcsname}
%D Definitions:
% common to lines and text
-\setupmargindata [\v!left ] [\c!method=\v!first,\c!location=\v!left ,\c!margin=\v!margin,\c!align=\v!flushright,\s!parent=\??mc] % we could autoparent when no define yet
-\setupmargindata [\v!right] [\c!method=\v!first,\c!location=\v!right,\c!margin=\v!margin,\c!align=\v!flushleft, \s!parent=\??mc]
-\setupmargindata [\v!outer] [\c!method=\v!first,\c!location=\v!outer,\c!margin=\v!margin,\c!align=\v!inner, \s!parent=\??mc]
-\setupmargindata [\v!inner] [\c!method=\v!first,\c!location=\v!inner,\c!margin=\v!margin,\c!align=\v!outer, \s!parent=\??mc]
+\setupmargindata [\v!left ] [\c!method=\v!first,\c!location=\v!left ,\c!margin=\v!margin,\c!align=\v!flushright,\s!parent=\??margindata] % we could autoparent when no define yet
+\setupmargindata [\v!right] [\c!method=\v!first,\c!location=\v!right,\c!margin=\v!margin,\c!align=\v!flushleft, \s!parent=\??margindata]
+\setupmargindata [\v!outer] [\c!method=\v!first,\c!location=\v!outer,\c!margin=\v!margin,\c!align=\v!inner, \s!parent=\??margindata]
+\setupmargindata [\v!inner] [\c!method=\v!first,\c!location=\v!inner,\c!margin=\v!margin,\c!align=\v!outer, \s!parent=\??margindata]
% lines
@@ -276,22 +351,22 @@
% text
-\definemargindata [inleft] [\v!left ] [\c!margin=\c!margin,\c!width=\leftmarginwidth ,\c!align=\v!flushright]
-\definemargindata [inright] [\v!right] [\c!margin=\c!margin,\c!width=\rightmarginwidth,\c!align=\v!flushleft]
-\definemargindata [inouter] [\v!outer] [\c!margin=\c!margin,\c!width=\outermarginwidth,\c!align=\v!inner]
-\definemargindata [ininner] [\v!inner] [\c!margin=\c!margin,\c!width=\innermarginwidth,\c!align=\v!outer]
+\definemargindata [inleft] [\v!left ] [\c!margin=\v!margin,\c!width=\leftmarginwidth ,\c!align=\v!flushright]
+\definemargindata [inright] [\v!right] [\c!margin=\v!margin,\c!width=\rightmarginwidth,\c!align=\v!flushleft]
+\definemargindata [inouter] [\v!outer] [\c!margin=\v!margin,\c!width=\outermarginwidth,\c!align=\v!inner]
+\definemargindata [ininner] [\v!inner] [\c!margin=\v!margin,\c!width=\innermarginwidth,\c!align=\v!outer]
% no longer auto auto-other
-\definemargindata [inmargin] [\v!left] [\c!margin=\c!margin,\c!width=\leftmarginwidth, \c!align=\v!flushright]
-\definemargindata [inother] [\v!right] [\c!margin=\c!margin,\c!width=\rightmarginwidth,\c!align=\v!flushleft]
+\definemargindata [inmargin] [\v!left] [\c!margin=\v!margin,\c!width=\leftmarginwidth, \c!align=\v!flushright]
+\definemargindata [inother] [\v!right] [\c!margin=\v!margin,\c!width=\rightmarginwidth,\c!align=\v!flushleft]
-\definemargindata [margintext] [\v!left] [\c!margin=\c!margin,\c!width=\leftmarginwidth, \c!align=\v!flushright]
+\definemargindata [margintext] [\v!left] [\c!margin=\v!margin,\c!width=\leftmarginwidth, \c!align=\v!flushright,\c!stack=\v!yes]
-\setupmarginframed [\v!left ] [\c!method=\v!first,\c!align=\v!flushright,\s!parent=\??mf] % we could autoparent when no define yet
-\setupmarginframed [\v!right] [\c!method=\v!first,\c!align=\v!flushleft, \s!parent=\??mf]
-\setupmarginframed [\v!outer] [\c!method=\v!first,\c!align=\v!inner, \s!parent=\??mf]
-\setupmarginframed [\v!inner] [\c!method=\v!first,\c!align=\v!outer, \s!parent=\??mf]
+\setupmarginframed [\v!left ] [\c!method=\v!first,\c!align=\v!flushright,\s!parent=\??marginframed] % we could autoparent when no define yet
+\setupmarginframed [\v!right] [\c!method=\v!first,\c!align=\v!flushleft, \s!parent=\??marginframed]
+\setupmarginframed [\v!outer] [\c!method=\v!first,\c!align=\v!inner, \s!parent=\??marginframed]
+\setupmarginframed [\v!inner] [\c!method=\v!first,\c!align=\v!outer, \s!parent=\??marginframed]
\definemarginframed [inleft] [\v!left ]
\definemarginframed [inright] [\v!right]
@@ -300,52 +375,52 @@
\definemarginframed [inmargin] [\v!inleft]
\definemarginframed [inother] [\v!inright]
-\let\marginword \margintext
-\let\margintitle\margintext
+\let\marginword \margintext
+\let\margintitle \margintext
+\let\inothermargin\inother % for old times sake
-%definemargindata [inouterextra] [\v!outer] [\c!margin=\c!edge,\c!location=\v!outer,\c!width=\outeredgewidth,\c!align=\v!outer,\c!category=\v!edge]
-%definemargindata [ininnerextra] [\v!inner] [\c!margin=\c!edge,\c!location=\v!inner,\c!width=\inneredgewidth,\c!align=\v!inner,\c!category=\v!edge]
+%definemargindata [inouterextra] [\v!outer] [\c!margin=\v!edge,\c!location=\v!outer,\c!width=\outeredgewidth,\c!align=\v!outer,\c!category=\v!edge]
+%definemargindata [ininnerextra] [\v!inner] [\c!margin=\v!edge,\c!location=\v!inner,\c!width=\inneredgewidth,\c!align=\v!inner,\c!category=\v!edge]
%
%definemarginframed [inouterextra] [\v!outer]
%definemarginframed [ininnerextra] [\v!inner]
%D As we have more control we are not backward compatible although in
-%D practice it won't hurt that much.
-%D So, from now on use:
+%D practice it won't hurt that much. So, from now on use:
%D
%D \starttyping
+%D \definemargindata
%D \setupmargindata
-%D \setupmargintext
+%D \definemarginframed
+%D \setupmarginframed
%D \stoptyping
-% The following sort of works okay:
-%
-% \let\definemarginline\definemargindata
-%
-% \unexpanded\def\defineinmargin
-% {\doquadrupleempty\dodefineinmargin}
-%
-% \def\dodefineinmargin[#name][#location][#align][#settings]% not completely compatible
-% {\definemargindata[#name][\c!location=#location,\c!align=#align,#settings]%
-% \definemarginframed[#name][#location][\c!align=#align,#settings]}
+% The following sort of works okay but is to be avoided:
-\let\setupinmargin\setupmargindata
+\let\definemarginline\definemargindata
-% The following is too dangerous:
-%
-% \unexpanded\def\setupinmargin
-% {\dodoubleempty\dosetupinmargin}
-%
-% \def\dosetupinmargin[#1][#2]%
-% {\ifsecondargument
-% \processcommalist[#1]{\dodosetupinmargin[#2]}%
-% \else
-% \setupmargindata [#1]% beware, here we can have clashes, so
-% \setupmarginframed[#1]% don't use setupinmargin any more
-% \fi}
+\unexpanded\def\defineinmargin
+ {\doquadrupleempty\typo_inmargin_define}
+
+\def\typo_inmargin_define[#name][#location][#align][#settings]% not completely compatible
+ {\definemargindata[#name][\c!location=#location,\c!align=#align,#settings]%
+ \definemarginframed[#name][#location][\c!align=#align,#settings]}
+
+\let\setupinmargin\setupmargindata % only partial (no framed)
+
+% begin of experimental code (will move)
%
-% \def\dodosetupinmargin[#1]#2% [settings]{class}
-% {\setupmargindata[#2][#1]%
-% \setupmargintext[#2][#1]}
+% \dosetanchor{x}test \dostarthanchoring{x}\llap{crap}\dostophanchoring{x}test test test
+% test \dostarthanchoring{text}\llap{crap}\dostophanchoring{text}test test test
+
+% \def\dosetanchor #1{\dontleavehmode\latelua{anchors.set("#1")}}
+% \def\doresetanchor #1{\dontleavehmode\latelua{anchors.reset("#1")}}
+% \def\doresetanchornow #1{\directlua{anchors.reset("#1")}}
+% \def\dostartanchoring #1{\dontleavehmode\latelua{anchors.startmove("#1")}}
+% \def\dostopanchoring #1{\dontleavehmode\latelua{anchors.stopmove("#1")}}
+% \def\dostarthanchoring#1{\dontleavehmode\latelua{anchors.startmove("#1","h")}}
+% \def\dostartvanchoring#1{\dontleavehmode\latelua{anchors.startmove("#1","v")}}
+% \let\dostophanchoring \dostopanchoring
+% \let\dostopvanchoring \dostopanchoring
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-pag.lua b/Master/texmf-dist/tex/context/base/typo-pag.lua
new file mode 100644
index 00000000000..482a3a9f866
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-pag.lua
@@ -0,0 +1,183 @@
+if not modules then modules = { } end modules ['typo-pag'] = {
+ version = 1.001,
+ comment = "companion to typo-pag.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local nodecodes = nodes.nodecodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local penalty_code = nodecodes.penalty
+
+local insert_node_after = node.insert_after
+local new_penalty = nodes.pool.penalty
+local has_attribute = node.has_attribute
+local unset_attribute = node.unset_attribute
+local set_attribute = node.set_attribute
+
+local points = number.points
+
+local a_keeptogether = attributes.private("keeptogether")
+
+local trace_keeptogether = false
+local report_keeptogether = logs.reporter("parbuilders","keeptogether")
+
+local cache = { }
+local last = 0
+local enabled = false
+
+trackers.register("parbuilders.keeptogether", function(v) trace_keeptogether = v end)
+
+-- todo: also support lines = 3 etc (e.g. dropped caps) but how to set that
+-- when no hlists are there ? ... maybe the local_par
+
+function builders.paragraphs.registertogether(line,specification) -- might change
+ if not enabled then
+ nodes.tasks.enableaction("finalizers","builders.paragraphs.keeptogether")
+ end
+ local a = has_attribute(line,a_keeptogether)
+ local c = a and cache[a]
+ if c then
+ local height = specification.height
+ local depth = specification.depth
+ local slack = specification.slack
+ if height and height > c.height then
+ c.height = height
+ end
+ if depth and depth > c.depth then
+ c.depth = depth
+ end
+ if slack and slack > c.slack then
+ c.slack = slack
+ end
+ else
+ last = last + 1
+ cache[last] = specification
+ if not specification.height then
+ specification.height = 0
+ end
+ if not specification.depth then
+ specification.depth = 0
+ end
+ if not specification.slack then
+ specification.slack = 0
+ end
+ set_attribute(line,a_keeptogether,last)
+ end
+ if trace_keeptogether then
+ local a = a or last
+ local c = cache[a]
+ if trace_keeptogether then
+ local noflines = specification.lineheight
+ local height = c.height
+ local depth = c.depth
+ local slack = c.slack
+ if not noflines or noflines == 0 then
+ noflines = "unknown"
+ else
+ noflines = math.round((height + depth - slack) / noflines)
+ end
+ report_keeptogether("registered, index: %s, height: %s, depth: %s, slack: %s, noflines: %s",
+ a,points(height),points(depth),points(slack),noflines)
+ end
+ end
+end
+
+local function keeptogether(start,a)
+ if start then
+ local specification = cache[a]
+ if a then
+ local current = start.next
+ local previous = start
+ local total = previous.depth
+ local slack = specification.slack
+ local threshold = specification.depth - slack
+ if trace_keeptogether then
+ report_keeptogether("list, index: %s, total: %s, threshold: %s, slack: %s",a,points(total),points(threshold),points(slack))
+ end
+ while current do
+ local id = current.id
+ if id == vlist_code or id == hlist_code then
+ total = total + current.height + current.depth
+ if trace_keeptogether then
+ report_keeptogether("list, index: %s, total: %s, threshold: %s",a,points(total),points(threshold))
+ end
+ if total <= threshold then
+ if previous.id == penalty_code then
+ previous.penalty = 10000
+ else
+ insert_node_after(head,previous,new_penalty(10000))
+ end
+ else
+ break
+ end
+ elseif id == glue_code then
+ -- hm, breakpoint, maybe turn this into kern
+ total = total + current.spec.width
+ if trace_keeptogether then
+ report_keeptogether("glue, index: %s, total: %s, threshold: %s",a,points(total),points(threshold))
+ end
+ if total <= threshold then
+ if previous.id == penalty_code then
+ previous.penalty = 10000
+ else
+ insert_node_after(head,previous,new_penalty(10000))
+ end
+ else
+ break
+ end
+ elseif id == kern_code then
+ total = total + current.kern
+ if trace_keeptogether then
+ report_keeptogether("kern, index: %s, total: %s, threshold: %s",a,points(total),points(threshold))
+ end
+ if total <= threshold then
+ if previous.id == penalty_code then
+ previous.penalty = 10000
+ else
+ insert_node_after(head,previous,new_penalty(10000))
+ end
+ else
+ break
+ end
+ elseif id == penalty_code then
+ if total <= threshold then
+ if previous.id == penalty_code then
+ previous.penalty = 10000
+ end
+ current.penalty = 10000
+ else
+ break
+ end
+ end
+ previous = current
+ current = current.next
+ end
+ end
+ end
+end
+
+-- also look at first non glue/kern node e.g for a dropped caps
+
+function builders.paragraphs.keeptogether(head)
+ local done = false
+ local current = head
+ while current do
+ if current.id == hlist_code then
+ local a = has_attribute(current,a_keeptogether)
+ if a and a > 0 then
+ keeptogether(current,a)
+ unset_attribute(current,a_keeptogether)
+ cache[a] = nil
+ done = true
+ end
+ end
+ current = current.next
+ end
+ return head, done
+end
diff --git a/Master/texmf-dist/tex/context/base/typo-pag.mkiv b/Master/texmf-dist/tex/context/base/typo-pag.mkiv
new file mode 100644
index 00000000000..30d2b51b73d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-pag.mkiv
@@ -0,0 +1,20 @@
+%D \module
+%D [ file=typo-pag,
+%D version=2011.11.02,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Pages,
+%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 / Pages}
+
+\unprotect
+
+\registerctxluafile{typo-pag}{1.001}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-par.lua b/Master/texmf-dist/tex/context/base/typo-par.lua
new file mode 100644
index 00000000000..0261d2e4e3f
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-par.lua
@@ -0,0 +1,184 @@
+if not modules then modules = { } end modules ['typo-par'] = {
+ version = 1.001,
+ comment = "companion to typo-par.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- A playground for experiments.
+
+local utfbyte = utf.byte
+local utfchar = utf.char
+
+local trace_paragraphs = false trackers.register("typesetters.paragraphs", function(v) trace_paragraphs = v end)
+local trace_dropper = false trackers.register("typesetters.paragraphs.dropper",function(v) trace_dropper = v end)
+
+local report_paragraphs = logs.reporter("nodes","paragraphs")
+local report_dropper = logs.reporter("nodes","dropped")
+
+typesetters.paragraphs = typesetters.paragraphs or { }
+local paragraphs = typesetters.paragraphs
+
+local nodecodes = nodes.nodecodes
+local whatsitcodes = nodes.whatsitcodes
+local tasks = nodes.tasks
+
+local variables = interfaces.variables
+
+local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
+
+local has_attribute = node.has_attribute
+local set_attribute = node.set_attribute
+
+local glyph_code = nodecodes.glyph
+local hlist_code = nodecodes.hlist
+local kern_node = nodecodes.kern
+local whatsit_code = nodecodes.whatsit
+local localpar_code = whatsitcodes.localpar
+
+local a_paragraph = attributes.private("paragraphspecial")
+local a_color = attributes.private('color')
+local a_transparency = attributes.private('transparency')
+local a_colorspace = attributes.private('colormodel')
+
+local dropper = {
+ enabled = false,
+ -- font = 0,
+ -- n = 0,
+ -- distance = 0,
+ -- hoffset = 0,
+ -- voffset = 0,
+}
+
+local droppers = { }
+
+typesetters.paragraphs.droppers = droppers
+
+function droppers.set(specification)
+ dropper = specification or { }
+end
+
+function droppers.freeze()
+ if dropper.enabled then
+ dropper.font = font.current()
+ end
+end
+
+-- dropped caps experiment (will be done properly when luatex
+-- stores the state in the local par node) .. btw, search still
+-- works with dropped caps, as does an export
+
+-- we need a 'par' attribute and in fact for dropped caps we don't need
+-- need an attribute ... dropit will become s state counter (or end up
+-- in the localpar user data
+
+-- for the moment, each paragraph gets a number as id (attribute) ..problem
+-- with nesting .. or anyhow, needed for tagging anyway
+
+-- todo: prevent linebreak .. but normally a dropper ends up atthe top of
+-- a page so this has a low priority
+
+local function process(namespace,attribute,head)
+ local done = false
+ if head.id == whatsit_code and head.subtype == localpar_code then
+ -- begin of par
+ local a = has_attribute(head,attribute)
+ if a and a > 0 then
+ if dropper.enabled then
+ dropper.enabled = false -- dangerous for e.g. nested || in tufte
+ local first = head.next
+ if first and first.id == hlist_code then
+ -- parbox .. needs to be set at 0
+ first = first.next
+ end
+ if first and first.id == glyph_code then
+-- if texattribute[a_paragraph] >= 0 then
+-- texattribute[a_paragraph] = unsetvalue
+-- end
+ local char = first.char
+ local prev = first.prev
+ local next = first.next
+ -- if prev.id == hlist_code then
+ -- -- set the width to 0
+ -- end
+ if next and next.id == kern_node then
+ next.kern = 0
+ end
+ first.font = dropper.font or first.font
+ -- can be a helper
+ local ma = dropper.ma or 0
+ local ca = dropper.ca
+ local ta = dropper.ta
+ if ca and ca > 0 then
+ set_attribute(first,a_colorspace,ma == 0 and 1 or ma)
+ set_attribute(first,a_color,ca)
+ end
+ if ta and ta > 0 then
+ set_attribute(first,a_transparency,ta)
+ end
+ --
+ local width = first.width
+ local height = first.height
+ local depth = first.depth
+ local distance = dropper.distance or 0
+ local voffset = dropper.voffset or 0
+ local hoffset = dropper.hoffset or 0
+ first.xoffset = - width - hoffset - distance
+ first.yoffset = - height - voffset
+ if true then
+ -- needed till we can store parindent with localpar
+ first.prev = nil
+ first.next = nil
+ local h = node.hpack(first)
+ h.width = 0
+ h.height = 0
+ h.depth = 0
+ prev.next = h
+ next.prev = h
+ h.next = next
+ h.prev = prev
+ end
+ if dropper.location == variables.margin then
+ -- okay
+ else
+ local lines = tonumber(dropper.n) or 0
+ if lines == 0 then -- safeguard, not too precise
+ lines = math.ceil((height+voffset) / tex.baselineskip.width)
+ end
+ tex.hangafter = - lines
+ tex.hangindent = width + distance
+ end
+ done = true
+ end
+ end
+ end
+ end
+ return head, done
+end
+
+local enabled = false
+
+function paragraphs.set(n)
+ if n == variables.reset or not tonumber(n) or n == 0 then
+ texattribute[a_paragraph] = unsetvalue
+ else
+ if not enabled then
+ tasks.enableaction("processors","typesetters.paragraphs.handler")
+ if trace_paragraphs then
+ report_paragraphs("enabling paragraphs")
+ end
+ enabled = true
+ end
+ texattribute[a_paragraph] = n
+ end
+end
+
+paragraphs.attribute = a_paragraph
+
+paragraphs.handler = nodes.installattributehandler {
+ name = "paragraphs",
+ namespace = paragraphs,
+ processor = process,
+}
diff --git a/Master/texmf-dist/tex/context/base/typo-par.mkiv b/Master/texmf-dist/tex/context/base/typo-par.mkiv
new file mode 100644
index 00000000000..7153d1f8adc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-par.mkiv
@@ -0,0 +1,107 @@
+%D \module
+%D [ file=typo-par,
+%D version=2011.10.27,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Paragraphs,
+%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 / Paragraphs}
+
+%D This will change ... par specific attribute set and such.
+
+\unprotect
+
+\registerctxluafile{typo-par}{1.001}
+
+\definesystemattribute[paragraphspecial][public]
+
+\unexpanded\def\setparagraphspecial[#1]%
+ {\ctxlua{typesetters.paragraphs.set("#1")}}
+
+\appendtoks
+ \attribute\paragraphspecialattribute\attributeunsetvalue
+\to \everyforgetall
+
+%D For the moment here: dropped caps redone. In addition to the
+%D parameters shown in the example you can use the \type {style} and
+%D more low level \type {font} keys to set up the font where
+%D the first one wins. If you don't like the behaviour you can always
+%D roll out your own command.
+%D
+%D \starttyping
+%D \placeinitial \input ward \par \input ward \par \placeinitial \input tufte
+%D
+%D \setupinitial
+%D [location=text,
+%D n=2,
+%D color=darkred,
+%D distance=-1em,
+%D hoffset=1em,
+%D voffset=-3ex,
+%D before=\blank]
+%D
+%D \placeinitial \input ward \par \input ward \placeinitial \input tufte
+%D \stoptyping
+
+\installcorenamespace{initial}
+
+\installsimplecommandhandler \??initial {initial} \??initial
+
+\appendtoks
+ \checkinitialparent % this might become automatic
+\to \everysetupinitial
+
+\def\v_typo_initials_auto_scale % magic
+ {\the\dimexpr\lineheight*\initialparameter\c!n-\initialparameter\c!voffset\relax}
+
+\setupinitial
+ [\c!location=\v!text,
+ \c!n=3,
+ % \s!font=Bold sa 4,
+ \s!font=Bold at \v_typo_initials_auto_scale,
+ \c!distance=.125em,
+ \c!hoffset=\zeropoint,
+ \c!voffset=-1ex,
+ \c!style=,
+ \c!color=,
+ \c!before=\blank]
+
+\unexpanded\def\placeinitial
+ {\dosingleempty\typo_initials_place}
+
+\def\typo_initials_place[#1]% todo: optional text
+ {\par
+ \begingroup
+ \edef\currentinitial{#1}%
+ \begingroup
+ \useinitialcolorparameter\c!color
+ \ctxlua{typesetters.paragraphs.droppers.set {
+ location = "\initialparameter\c!location",
+ enabled = true,
+ n = \number\initialparameter\c!n,
+ distance = \number\dimexpr\initialparameter\c!distance,
+ hoffset = \number\dimexpr\initialparameter\c!hoffset,
+ voffset = \number\dimexpr\initialparameter\c!voffset,
+ ma = \the\attribute\colormodelattribute ,
+ ca = \the\attribute\colorattribute ,
+ ta = \the\attribute\transparencyattribute
+ }}%
+ \stopluacode
+ \endgroup
+ \begingroup
+ \doifelsenothing{\initialparameter\c!style}
+ {\definedfont[\initialparameter\s!font]}
+ {\useinitialstyleparameter\c!style}%
+ \ctxlua{typesetters.paragraphs.droppers.freeze()}%
+ \endgroup
+ \endgroup
+ \setparagraphspecial[1]%
+ \namedinitialparameter{#1}\c!before}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-prc.lua b/Master/texmf-dist/tex/context/base/typo-prc.lua
new file mode 100644
index 00000000000..bb965ff66dd
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-prc.lua
@@ -0,0 +1,126 @@
+if not modules then modules = { } end modules ['typo-prc'] = {
+ version = 1.001,
+ comment = "companion to typo-prc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- moved from strc-ini.lua
+
+
+local format = string.format
+local lpegmatch, patterns, P, C, Cs = lpeg.match, lpeg.patterns, lpeg.P, lpeg.C, lpeg.Cs
+
+-- processors: syntax: processor->data ... not ok yet
+
+typesetters.processors = typesetters.processors or { }
+local processors = typesetters.processors
+
+local trace_processors = false
+local report_processors = logs.reporter("processors")
+local registered = { }
+
+trackers.register("typesetters.processors", function(v) trace_processors = v end)
+
+function processors.register(p)
+ registered[p] = true
+end
+
+function processors.reset(p)
+ registered[p] = nil
+end
+
+--~ local splitter = lpeg.splitat("->",true) -- also support =>
+
+local becomes = P('->')
+local processor = (1-becomes)^1
+local splitter = C(processor) * becomes * Cs(patterns.argument + patterns.content)
+
+function processors.split(str)
+ local p, s = lpegmatch(splitter,str)
+ if registered[p] then
+ return p, s
+ else
+ return false, str
+ end
+end
+
+function processors.apply(p,s)
+ local str = p
+ if s == nil then
+ p, s = lpegmatch(splitter,p)
+ end
+ if p and registered[p] then
+ if trace_processors then
+ report_processors("known: %s, argument: %s",p,s or "")
+ end
+ context.applyprocessor(p,s)
+ elseif s then
+ if trace_processors then
+ report_processors("unknown: %s, argument: %s",p or "?",s)
+ end
+ context(s)
+ elseif str then
+ if trace_processors then
+ report_processors("direct: %s",str)
+ end
+ context(str)
+ end
+end
+
+function processors.startapply(p,s)
+ local str = p
+ if s == nil then
+ p, s = lpegmatch(splitter,p)
+ end
+ if p and registered[p] then
+ if trace_processors then
+ report_processors("start: %s",p or "?")
+ end
+ context.applyprocessor(p)
+ context("{")
+ return s
+ elseif p then
+ if trace_processors then
+ report_processors("start: %s (unknown)",p)
+ end
+ context.firstofoneargument()
+ context("{")
+ return s
+ else
+ if trace_processors then
+ report_processors("start: ? (unset)")
+ end
+ context.firstofoneargument()
+ context("{")
+ return str
+ end
+end
+
+function processors.stopapply()
+ context("}")
+ if trace_processors then
+ report_processors("stop")
+ end
+end
+
+function processors.tostring(str)
+ local p, s = lpegmatch(splitter,str)
+ if registered[p] then
+ return format("\\applyprocessor{%s}{%s}",p,s)
+ else
+ return str
+ end
+end
+
+function processors.stripped(str)
+ local p, s = lpegmatch(splitter,str)
+ return s or str
+end
+
+-- interface
+
+commands.registerstructureprocessor = processors.register
+commands.resetstructureprocessor = processors.reset
+
diff --git a/Master/texmf-dist/tex/context/base/strc-prc.mkiv b/Master/texmf-dist/tex/context/base/typo-prc.mkvi
index 68339ed9274..de221f2419b 100644
--- a/Master/texmf-dist/tex/context/base/strc-prc.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-prc.mkvi
@@ -1,19 +1,19 @@
%D \module
-%D [ file=strc-prc,
+%D [ file=typo-prc,
%D version=2008.10.20,
%D title=\CONTEXT\ Structure Macros,
%D subtitle=Processors,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE / Hans Hagen]
+%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 / Processors}
+\writestatus{loading}{ConTeXt Typesetting Macros / Processors}
-\registerctxluafile{strc-prc}{1.001}
+\registerctxluafile{typo-prc}{1.001}
\unprotect
@@ -32,7 +32,7 @@
%D for instance:
%D
%D \starttyping
-%D \definestructureseparatorset [demosep] [demo->!,demo->?,demo->!,demo->?] [demo->@]
+%D \defineseparatorset [demosep] [demo->!,demo->?,demo->!,demo->?] [demo->@]
%D \stoptyping
%D
%D Here the \type {!} and \type {?} are just the seperator characters that end
@@ -44,41 +44,49 @@
%D Valid keys for defining a processor are \type {style}, \type {color}, \type {left},
%D \type {right}, and \type {command} (the given command takes one argument).
-\unexpanded\def\defineprocessor
- {\dodoubleargument\dodefineprocessor}
+\installcorenamespace{processor}
+\installcorenamespace{processorcheck}
-\def\dodefineprocessor[#1][#2]%
- {\ifsecondargument
- \letbeundefined{\??po#1\c!command}%
- \ctxlua{structures.processors.register("#1")}%
- \getparameters[\??po#1][\c!style=,\c!color=,\c!left=,\c!right=,#2]%
- \else
- \letbeundefined{\??po#1\c!style}%
- \ctxlua{structures.processors.reset("#1")}%
- \fi}
+\installcommandhandler \??processor {processor} \??processor
+
+\appendtoks
+ \letvalue{\??processorcheck\currentprocessor}\relax
+ \ctxcommand{registerstructureprocessor("\currentprocessor")}% global, but it permits using processor that are yet undefined
+\to \everydefineprocessor
%D The following command can be used by users but normally it will be
%D invoked behind the screens. After all, processor prefixes need to
-%D be split off first.
+%D be split off first. At the \LUA\ end we do check for a processor
+%D being registered anyway.
-\unexpanded\def\applyprocessor#1%
- {\ifcsname\??po#1\c!style\endcsname
- \expandafter\dodoapplyprocessor
+\unexpanded\def\applyprocessor#tag%
+ {\def\currentprocessor{#tag}%
+ \ifcsname\??processorcheck\currentprocessor\endcsname
+ \expandafter\typo_processor_apply
\else
- \expandafter\secondoftwoarguments
- \fi{#1}}
+ \expandafter\firstofoneargument
+ \fi}
+
+\def\typo_processor_apply
+ {\doifelse{\processorparameter\c!state}\v!stop
+ \firstofoneargument
+ \typo_processor_apply_indeed}
-\def\dodoapplyprocessor#1#2%
+\def\typo_processor_apply_indeed#content%
{\begingroup
- \dostartattributes{\??po#1}\c!style\c!color
- \csname\??po#1\c!left\endcsname
- \ifcsname\??po#1\c!command\endcsname
- \csname\??po#1\c!command\endcsname{#2}%
- \else
- #2%
- \fi
- \csname\??po#1\c!right\endcsname
- \dostopattributes
+ \useprocessorstyleandcolor\c!style\c!color
+ \processorparameter\c!left
+ \processorparameter\c!command{#content}%
+ \processorparameter\c!right
\endgroup}
+%D \startbuffer
+%D \defineprocessor[first] [style=bold]
+%D \defineprocessor[last] [first] [color=red]
+%D
+%D \applyprocessor{first}{hans} \applyprocessor{last}{hagen}
+%D \stopbuffer
+%D
+%D \typebuffer \start \blank \getbuffer \blank \stop
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-rep.lua b/Master/texmf-dist/tex/context/base/typo-rep.lua
index 5ecff558623..0d9bf8cc1b7 100644
--- a/Master/texmf-dist/tex/context/base/typo-rep.lua
+++ b/Master/texmf-dist/tex/context/base/typo-rep.lua
@@ -24,12 +24,17 @@ local has_attribute = node.has_attribute
local chardata = characters.data
local collected = false
-local attribute = attributes.private("stripping")
+local a_stripping = attributes.private("stripping")
local fontdata = fonts.hashes.identifiers
local tasks = nodes.tasks
-local nodecodes = nodes.nodecodes
-local glyph_code = nodecodes.glyph
+local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
+
+local v_reset = interfaces.variables.reset
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
-- todo: other namespace -> typesetters
@@ -74,7 +79,7 @@ function nodes.handlers.stripping(head)
while current do
if current.id == glyph_code then
-- it's more efficient to keep track of what needs to be kept
- local todo = has_attribute(current,attribute)
+ local todo = has_attribute(current,a_stripping)
if todo == 1 then
local char = current.char
local what = glyphs[char]
@@ -94,11 +99,31 @@ function nodes.handlers.stripping(head)
return head, done
end
+local enabled = false
+
+function stripping.set(n) -- number or 'reset'
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = tonumber(n)
+ if n then
+ if not enabled then
+ if initialize then initialize() end
+ tasks.enableaction("processors","nodes.handlers.stripping")
+ enabled = true
+ end
+ else
+ n = unsetvalue
+ end
+ end
+ texattribute[a_stripping] = n
+end
+
+-- why not in task-ini?
+
tasks.appendaction("processors","fonts","nodes.handlers.stripping",nil,"nodes.handlers.characters")
tasks.disableaction("processors","nodes.handlers.stripping")
-function nodes.stripping.enable()
- if initialize then initialize() end
- tasks.enableaction("processors","nodes.handlers.stripping")
- function nodes.stripping.enable() end
-end
+-- interface
+
+commands.setcharacterstripping = stripping.set
diff --git a/Master/texmf-dist/tex/context/base/typo-rep.mkiv b/Master/texmf-dist/tex/context/base/typo-rep.mkiv
index 75902d7be37..46b43949151 100644
--- a/Master/texmf-dist/tex/context/base/typo-rep.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-rep.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Stripping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -37,17 +37,15 @@
\definesystemattribute[stripping][public]
-\def\setcharacterstripping
- {\ctxlua{nodes.stripping.enable()}%
- \gdef\setcharacterstripping[##1]{\attribute\strippingattribute##1\relax}%
- \setcharacterstripping}
+\unexpanded\def\setcharacterstripping[#1]%
+ {\ctxcommand{setcharacterstripping("#1")}}
-\def\resetcharacterstripping
+\unexpanded\def\resetcharacterstripping
{\attribute\strippingattribute\attributeunsetvalue}
% maybe .. this might disappear, but is handy for testing
-\def\forcecharacterstripping % secret command
+\unexpanded\def\forcecharacterstripping % secret command
{\ctxlua{fonts.handlers.otf.features.register("formatters",true)}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-scr.mkiv b/Master/texmf-dist/tex/context/base/typo-scr.mkiv
new file mode 100644
index 00000000000..4b448752227
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-scr.mkiv
@@ -0,0 +1,104 @@
+%D \module
+%D [ file=typo-scr,
+%D version=2012.01.23, % very old ... 1995.10.10 .. moved from core-mis
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Scripts,
+%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 / Scripts}
+
+\unprotect
+
+%D I addition to the commands implemented here, we have alternative commands
+%D \type {shiftup} and \type {shiftdown} that can work across paragraphs.
+
+%D \macros
+%D {low, high, lohi, hilo}
+%D
+%D Although \TEX\ is pretty well aware of super- and subscripts, its mechanism
+%D is mainly tuned for math mode. The next few commands take care of script
+%D texts both modes.
+%D
+%D \startbuffer
+%D The higher\high{one goes} the lower\low{one drops}, or\lohi{yes}{no}?
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+%D
+%D Note the different placement of \type {\lohi}, where we need a bit more
+%D space. The implementation looks a bit fuzzy, since some \type {\fontdimen}'s
+%D are involved to determine the optimal placement.
+
+% These might become parameters: \setupscripts but we need fo come up with
+% nice keys.
+
+\def\highvfraction {0}
+\def\lowvfraction {0}
+\def\highlowvfraction{.1}
+\def\highlowhfraction{.1}
+
+\unexpanded\def\low {\typo_scripts_high_low\lower\mathsubnormal{.48}\lowvfraction \t!sub}
+\unexpanded\def\high{\typo_scripts_high_low\raise\mathsupnormal{.86}\highvfraction\t!sup}
+
+\def\typo_scripts_high_low#1#2#3#4#5#6% textscript mathscript fraction extra tag
+ {\dontleavehmode
+ \begingroup
+ \scratchdimen\dimexpr#3\exheight+#4\exheight\relax
+ \kern\highlowhfraction\exheight
+ \setbox\scratchbox\hbox{#1\scratchdimen\hbox
+ {\ifx\fontsize\empty\ifmmode\mr\else\tx\fi\else\tx\fi
+ \dostarttagged
+ #5\empty#6%
+ \dostoptagged}}%
+ \ht\scratchbox\strutheight
+ \dp\scratchbox\strutdepth
+ \box\scratchbox
+ \endgroup}
+
+%D You can provide an optional keyword \type {left}, in which case the super and
+%D subscripts will be aligned in a way that permits placement at the left of a word
+%D (which means that it will be right aligned).
+%D
+%D \startbuffer
+%D \lohi{aha}{ah} test \lohi{aha}{ah} test
+%D \lohi[left]{aha}{ah} test \lohi[left]{aha}{ah} test
+%D \lohi{aha}{ah} test\lohi{aha}{ah} test
+%D \lohi[left]{aha}{ah}test \lohi[left]{aha}{ah}test
+%D \stopbuffer
+%D
+%D \typebuffer
+%D \getbuffer
+
+\unexpanded\def\lohi{\dosingleempty\typo_scripts_lohi}
+\unexpanded\def\hilo{\dosingleempty\typo_scripts_hilo}
+
+\def\typo_scripts_lohi[#1]#2#3%
+ {\dontleavehmode
+ \hbox
+ {\dostarttagged\t!subsup\empty
+ \setbox4\hbox{\typo_scripts_high_low\lower\mathsubnormal{.48}\highlowvfraction\t!sub{#2}}%
+ \setbox6\hbox{\typo_scripts_high_low\raise\mathsupnormal{.86}\highlowvfraction\t!sup{#3}}%
+ \doif{#1}{\v!left}
+ {\ifdim\wd4<\wd6
+ \setbox4\hbox to \wd6{\hss\box4}%
+ \else
+ \setbox6\hbox to \wd4{\hss\box6}%
+ \fi}%
+ \ifdim\wd4<\wd6
+ \wd4=\zeropoint\box4\box6
+ \else
+ \wd6=\zeropoint\box6\box4
+ \fi
+ \dostoptagged}}
+
+\def\typo_scripts_hilo[#1]#2#3%
+ {\typo_scripts_lohi[#1]{#3}{#2}}
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/typo-spa.lua b/Master/texmf-dist/tex/context/base/typo-spa.lua
index e81a59bda95..9e653ad5563 100644
--- a/Master/texmf-dist/tex/context/base/typo-spa.lua
+++ b/Master/texmf-dist/tex/context/base/typo-spa.lua
@@ -6,8 +6,6 @@ if not modules then modules = { } end modules ['typo-spa'] = {
license = "see context related readme files"
}
--- get rid of tex.scale here
-
local utf = unicode.utf8
local next, type = next, type
@@ -30,10 +28,16 @@ local fontdata = fonthashes.identifiers
local quaddata = fonthashes.quads
local texattribute = tex.attribute
+local unsetvalue = attributes.unsetvalue
+
+local v_reset = interfaces.variables.reset
local nodecodes = nodes.nodecodes
local glyph_code = nodecodes.glyph
+local somespace = nodes.somespace
+local somepenalty = nodes.somepenalty
+
local nodepool = nodes.pool
local tasks = nodes.tasks
@@ -47,13 +51,25 @@ typesetters.spacings = typesetters.spacings or { }
local spacings = typesetters.spacings
spacings.mapping = spacings.mapping or { }
+spacings.numbers = spacings.numbers or { }
+
local a_spacings = attributes.private("spacing")
spacings.attribute = a_spacings
storage.register("typesetters/spacings/mapping", spacings.mapping, "typesetters.spacings.mapping")
+local mapping = spacings.mapping
+local numbers = spacings.numbers
+
+for i=1,#mapping do
+ local m = mapping[i]
+ numbers[m.name] = m
+end
+
+-- todo cache lastattr
+
local function process(namespace,attribute,head)
- local done, mapping = false, spacings.mapping
+ local done = false
local start = head
-- head is always begin of par (whatsit), so we have at least two prev nodes
-- penalty followed by glue
@@ -61,9 +77,9 @@ local function process(namespace,attribute,head)
if start.id == glyph_code then
local attr = has_attribute(start,attribute)
if attr and attr > 0 then
- local map = mapping[attr]
- if map then
- map = map[start.char]
+ local data = mapping[attr]
+ if data then
+ local map = data.characters[start.char]
unset_attribute(start,attribute) -- needed?
if map then
local left = map.left
@@ -74,33 +90,33 @@ local function process(namespace,attribute,head)
if left and left ~= 0 and prev then
local ok = false
if alternative == 1 then
- local somespace = nodes.somespace(prev,true)
+ local somespace = somespace(prev,true)
if somespace then
local prevprev = prev.prev
- local somepenalty = nodes.somepenalty(prevprev,10000)
+ local somepenalty = somepenalty(prevprev,10000)
if somepenalty then
if trace_spacing then
report_spacing("removing penalty and space before %s (left)", utfchar(start.char))
end
- head, _ = remove_node(head,prev,true)
- head, _ = remove_node(head,prevprev,true)
+ head = remove_node(head,prev,true)
+ head = remove_node(head,prevprev,true)
else
if trace_spacing then
report_spacing("removing space before %s (left)", utfchar(start.char))
end
- head, _ = remove_node(head,prev,true)
+ head = remove_node(head,prev,true)
end
end
ok = true
else
- ok = not (nodes.somespace(prev,true) and nodes.somepenalty(prev.prev,true)) or nodes.somespace(prev,true)
+ ok = not (somespace(prev,true) and somepenalty(prev.prev,true)) or somespace(prev,true)
end
if ok then
if trace_spacing then
report_spacing("inserting penalty and space before %s (left)", utfchar(start.char))
end
insert_node_before(head,start,new_penalty(10000))
- insert_node_before(head,start,new_glue(tex.scale(quad,left)))
+ insert_node_before(head,start,new_glue(left*quad))
done = true
end
end
@@ -108,35 +124,35 @@ local function process(namespace,attribute,head)
if right and right ~= 0 and next then
local ok = false
if alternative == 1 then
- local somepenalty = nodes.somepenalty(next,10000)
+ local somepenalty = somepenalty(next,10000)
if somepenalty then
local nextnext = next.next
- local somespace = nodes.somespace(nextnext,true)
+ local somespace = somespace(nextnext,true)
if somespace then
if trace_spacing then
report_spacing("removing penalty and space after %s (right)", utfchar(start.char))
end
- head, _ = remove_node(head,next,true)
- head, _ = remove_node(head,nextnext,true)
+ head = remove_node(head,next,true)
+ head = remove_node(head,nextnext,true)
end
else
- local somespace = nodes.somespace(next,true)
+ local somespace = somespace(next,true)
if somespace then
if trace_spacing then
report_spacing("removing space after %s (right)", utfchar(start.char))
end
- head, _ = remove_node(head,next,true)
+ head = remove_node(head,next,true)
end
end
ok = true
else
- ok = not (nodes.somepenalty(next,10000) and nodes.somespace(next.next,true)) or nodes.somespace(next,true)
+ ok = not (somepenalty(next,10000) and somespace(next.next,true)) or somespace(next,true)
end
if ok then
if trace_spacing then
report_spacing("inserting penalty and space after %s (right)", utfchar(start.char))
end
- insert_node_after(head,start,new_glue(tex.scale(quad,right)))
+ insert_node_after(head,start,new_glue(right*quad))
insert_node_after(head,start,new_penalty(10000))
done = true
end
@@ -152,26 +168,48 @@ end
local enabled = false
-function spacings.setup(id,char,left,right,alternative)
- local mapping = spacings.mapping[id]
- if not mapping then
- mapping = { }
- spacings.mapping[id] = mapping
+function spacings.define(name)
+ local data = numbers[name]
+ if data then
+ -- error
+ else
+ local number = #mapping + 1
+ local data = {
+ name = name,
+ number = number,
+ characters = { },
+ }
+ mapping[number] = data
+ numbers[name] = data
end
- local map = mapping[char]
- if not map then
- map = { }
- mapping[char] = map
+end
+
+function spacings.setup(name,char,settings)
+ local data = numbers[name]
+ if not data then
+ -- error
+ else
+ data.characters[char] = settings
end
- map.left, map.right, map.alternative = left, right, alternative
end
-function spacings.set(id)
- if not enabled then
- tasks.enableaction("processors","typesetters.spacings.handler")
- enabled = true
+function spacings.set(name)
+ local n = unsetvalue
+ if name ~= v_reset then
+ local data = numbers[name]
+ if data then
+ if not enabled then
+ tasks.enableaction("processors","typesetters.spacings.handler")
+ enabled = true
+ end
+ n = data.number or unsetvalue
+ end
end
- texattribute[a_spacings] = id
+ texattribute[a_spacings] = n
+end
+
+function spacings.reset()
+ texattribute[a_spacings] = unsetvalue
end
spacings.handler = nodes.installattributehandler {
@@ -179,3 +217,9 @@ spacings.handler = nodes.installattributehandler {
namespace = spacings,
processor = process,
}
+
+-- interface
+
+commands.definecharacterspacing = spacings.define
+commands.setupcharacterspacing = spacings.setup
+commands.setcharacterspacing = spacings.set
diff --git a/Master/texmf-dist/tex/context/base/typo-spa.mkiv b/Master/texmf-dist/tex/context/base/typo-spa.mkiv
index 7a72e95adae..0cfe446102b 100644
--- a/Master/texmf-dist/tex/context/base/typo-spa.mkiv
+++ b/Master/texmf-dist/tex/context/base/typo-spa.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Spacing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
@@ -23,33 +23,32 @@
%
% test: oeps {\setcharacterspacing[frenchpunctuation]x: xx \bfd x: xx} oeps: test
-\newcount \maxcharacterspacingid
+\installcorenamespace{characterspacing}
+
+\definesystemvariable{cs} % maybe a dummy namespace
\unexpanded\def\definecharacterspacing[#1]%
- {\ifcsname\??ch#1\endcsname \else
- \global\advance\maxcharacterspacingid\plusone
- \setxvalue{\??ch:#1}{\the\maxcharacterspacingid}%
- \fi}
+ {\ctxcommand{definecharacterspacing("#1")}}
\unexpanded\def\setupcharacterspacing
- {\dotripleargument\dosetupcharacterspacing}
+ {\dotripleargument\typo_characterspacing_setup}
-\def\dosetupcharacterspacing[#1][#2][#3]%
- {\ifcsname\??ch:#1\endcsname
- \begingroup % for the moment we use modes, in ordere to avoid interface translation
- \getparameters[\??ch][\c!left=0,\c!right=0,\c!alternative=0,#3]%
- \ctxlua{typesetters.spacings.setup(\getvalue{\??ch:#1},\number#2,\@@chleft,\@@chright,\@@chalternative)}%
- \endgroup
- \fi}
+\def\typo_characterspacing_setup[#1][#2][#3]% todo: #2 list
+ {\begingroup
+ \getparameters[\??cs][\c!left=0,\c!right=0,\c!alternative=0,#3]%
+ \ctxcommand{setupcharacterspacing("#1",\number#2, {
+ left = \@@csleft,
+ right = \@@csright,
+ alternative = \@@csalternative
+ })}%
+ \endgroup}
-\unexpanded\def\setcharacterspacing[#1]%
- {\ctxlua{typesetters.spacings.set(\number\csname\??ch:#1\endcsname)}}
+\unexpanded\def\setcharacterspacing[#1]% we can store the attribute if we want speed
+ {\ctxcommand{setcharacterspacing("#1")}}
\unexpanded\def\resetcharacterspacing % fast one
{\attribute\spacingattribute\attributeunsetvalue}
-\letvalue{\??ch:\s!reset}\attributeunsetvalue
-
\appendtoks
\resetcharacterspacing
\to \everyresettypesetting
diff --git a/Master/texmf-dist/tex/context/base/typo-txt.mkvi b/Master/texmf-dist/tex/context/base/typo-txt.mkvi
new file mode 100644
index 00000000000..f2859b58fe9
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/typo-txt.mkvi
@@ -0,0 +1,71 @@
+%D \module
+%D [ file=typo-txt,
+%D version=2011.10.27,
+%D title=\CONTEXT\ Typesetting Macros,
+%D subtitle=Texts,
+%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 replaces the by now rather old supp-fun module.
+
+\unprotect
+
+%D \NormalizeFontHeight \name {sample text} {height} {font}
+%D \NormalizeFontWidth \name {sample text} {width} {font}
+%D \NormalizeTextHeight {font} {height} {text}
+%D \NormalizeTextWidth {font} {width} {text}
+
+\newbox\b_typo_normalizers
+
+\def\typo_normalizers_size#axis#size%
+ {\dimexpr\ifdim#1\b_typo_normalizers=\zeropoint
+ \bodyfontsize
+ \else
+ \cldcontext{\number\dimexpr10pt\relax*\number\dimexpr#size\relax/\number#axis\b_typo_normalizers}\scaledpoint
+ \fi\relax}
+
+\def\typo_normalizers_font_at_size#axis#cs#text#size#font% avoid overflow by using lua
+ {\begingroup
+ \setbox\b_typo_normalizers\hbox{\definedfont[#font at 10pt]\settrialtypesetting#text}%
+ \normalexpanded{\endgroup\edef\noexpand\TheNormalizedFontSize{\the\typo_normalizers_size{#axis}{#size}}}%
+ \edef#cs{\noexpand\definedfont[#font at \TheNormalizedFontSize]}}
+
+\unexpanded\def\typo_normalizers_text_at_size#axis#font#size#text%
+ {\dontleavehmode
+ \begingroup
+ \setbox\b_typo_normalizers\hbox{\definedfont[#font at 10pt]\settrialtypesetting#text}%
+ \definedfont[#font at \the\typo_normalizers_size{#axis}{#size}]#text%
+ \endgroup}
+
+\let\TheNormalizedFontSize\!!zeropoint
+
+%D Traditionally we use UpperCasedNames for this kind of
+%D functionality.
+
+\unexpanded\def\NormalizeFontHeight{\typo_normalizers_font_at_size\ht}
+\unexpanded\def\NormalizeFontWidth {\typo_normalizers_font_at_size\wd}
+
+\unexpanded\def\NormalizeTextHeight{\typo_normalizers_text_at_size\ht}
+\unexpanded\def\NormalizeTextWidth {\typo_normalizers_text_at_size\wd}
+
+\unexpanded\def\WidthSpanningText#text#width#font% compatibility macro
+ {\hbox{\NormalizeFontWidth\temp{#text}{#width}{#font}\temp\the\everydefinedfont#1}}
+
+%D \startbuffer
+%D \NormalizeFontWidth \MyFontName {sample text} {10cm} {Serif*default}
+%D
+%D \ruledhbox{\MyFontName sample text}
+%D \blank
+%D \blackrule[width=10cm]
+%D \blank
+%D \ruledhbox{\NormalizeTextWidth {Serif*default} {10cm} {sample text}}
+%D \stopbuffer
+%D
+%D \typebuffer \getbuffer
+
+\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/unic-000.mkii b/Master/texmf-dist/tex/context/base/unic-000.mkii
index cb4c1fe8abd..4ef57044520 100644
--- a/Master/texmf-dist/tex/context/base/unic-000.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-000.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 0,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-001.mkii b/Master/texmf-dist/tex/context/base/unic-001.mkii
index e37de91367c..198a8d98d1b 100644
--- a/Master/texmf-dist/tex/context/base/unic-001.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-001.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 1,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-002.mkii b/Master/texmf-dist/tex/context/base/unic-002.mkii
index ae7deb12a92..906975f8691 100644
--- a/Master/texmf-dist/tex/context/base/unic-002.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-002.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 2,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-003.mkii b/Master/texmf-dist/tex/context/base/unic-003.mkii
index 3f994a662e4..ad7d6df6a8f 100644
--- a/Master/texmf-dist/tex/context/base/unic-003.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-003.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 3,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-004.mkii b/Master/texmf-dist/tex/context/base/unic-004.mkii
index 67ce877288a..7b413cdb91f 100644
--- a/Master/texmf-dist/tex/context/base/unic-004.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-004.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 4,
%D author=Mikael Persson \& Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-005.mkii b/Master/texmf-dist/tex/context/base/unic-005.mkii
index d15b74dbe44..e21edb20584 100644
--- a/Master/texmf-dist/tex/context/base/unic-005.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-005.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 5,
%D author=Adam Lindsay,
%D date=\currentdate,
-%D copyright=\PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-030.mkii b/Master/texmf-dist/tex/context/base/unic-030.mkii
index ef42c807a80..0065a738a3b 100644
--- a/Master/texmf-dist/tex/context/base/unic-030.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-030.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 30,
%D author=Adam Lindsay,
%D date=\currentdate,
-%D copyright={PRAGMA / Adam Lindsay}]
+%D copyright={Adam Lindsay \& Hans Hagen}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
diff --git a/Master/texmf-dist/tex/context/base/unic-031.mkii b/Master/texmf-dist/tex/context/base/unic-031.mkii
index 13fd47a5484..68d1633249b 100644
--- a/Master/texmf-dist/tex/context/base/unic-031.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-031.mkii
@@ -4,7 +4,8 @@
%D title=\CONTEXT\ \UNICODE\ Macros,
%D subtitle=Vector 31,
%D author=Thomas A. Schmitz,
-%D date=\currentdate]
+%D date=\currentdate,
+%D copyright={Thomas A. Schmitz}]
\unprotect
diff --git a/Master/texmf-dist/tex/context/base/unic-032.mkii b/Master/texmf-dist/tex/context/base/unic-032.mkii
index 32c25e4e26e..6bd176c8071 100644
--- a/Master/texmf-dist/tex/context/base/unic-032.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-032.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 32,
%D author={Hans Hagen \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-033.mkii b/Master/texmf-dist/tex/context/base/unic-033.mkii
index 91311a029d1..ad7a3b11ff0 100644
--- a/Master/texmf-dist/tex/context/base/unic-033.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-033.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 33,
%D author={Nikolai Weibull \& Hans Hagen \& Taco Hoekwater},
%D date=\currentdate,
-%D copyright={PRAGMA / Nikolai Weibull}]
+%D copyright={Nikolai Weibull \& Hans Hagen}]
\unprotect
@@ -92,7 +92,7 @@
\unknownchar \or % 214D
\unknownchar \or % 214E
\unknownchar \or % 214F
- \unknownchar \or % 2150
+ \unknownchar \or % 2150
\unknownchar \or % 2151
\unknownchar \or % 2152
\unic@fractiononethird \or % 2153 VULGAR FRACTION ONE THIRD
@@ -143,7 +143,7 @@
\unic@romannumeralonethousandCD \or % 2180 ROMAN NUMERAL ONE THOUSAND C D
\unic@romannumeralfivethousand \or % 2181 ROMAN NUMERAL FIVE THOUSAND
\unic@romannumeraltenthousand \or % 2182 ROMAN NUMERAL TEN THOUSAND
- \unic@romannumeralreversedonehundred\or % 2183 ROMAN NUMERAL REVERSED ONE HUNDRED
+ \unic@romannumeralreversedonehundred\or % 2183 ROMAN NUMERAL REVERSED ONE HUNDRED
\unknownchar \or % 2184
\unknownchar \or % 2185
\unknownchar \or % 2186
diff --git a/Master/texmf-dist/tex/context/base/unic-034.mkii b/Master/texmf-dist/tex/context/base/unic-034.mkii
index fece26bff16..f998c517070 100644
--- a/Master/texmf-dist/tex/context/base/unic-034.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-034.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 34,
%D author=Nikolai Weibull,
%D date=\currentdate,
-%D copyright={PRAGMA / Nikolai Weibull}]
+%D copyright={Nikolai Weibull \& Hans Hagen}]
\unprotect
diff --git a/Master/texmf-dist/tex/context/base/unic-035.mkii b/Master/texmf-dist/tex/context/base/unic-035.mkii
index 272799512ad..0c949017468 100644
--- a/Master/texmf-dist/tex/context/base/unic-035.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-035.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 35,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
\unprotect
diff --git a/Master/texmf-dist/tex/context/base/unic-037.mkii b/Master/texmf-dist/tex/context/base/unic-037.mkii
index 87f655a6810..646a4afb299 100644
--- a/Master/texmf-dist/tex/context/base/unic-037.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-037.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 37,
%D author=Luigi Scarso,
%D date=\currentdate,
-%D copyright={PRAGMA}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-039.mkii b/Master/texmf-dist/tex/context/base/unic-039.mkii
index bcf6490901f..02d5d3af24f 100644
--- a/Master/texmf-dist/tex/context/base/unic-039.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-039.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 39,
%D author=Nikolai Weibull,
%D date=\currentdate,
-%D copyright={PRAGMA / Nikolai Weibull}]
+%D copyright={Nikolai Weibull \& Hans Hagen}]
\unprotect
diff --git a/Master/texmf-dist/tex/context/base/unic-251.mkii b/Master/texmf-dist/tex/context/base/unic-251.mkii
index 150ade4561f..909cf5e9473 100644
--- a/Master/texmf-dist/tex/context/base/unic-251.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-251.mkii
@@ -5,7 +5,7 @@
%D subtitle=Vector 251,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA-ADE]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
\unprotect
diff --git a/Master/texmf-dist/tex/context/base/unic-cjk.mkii b/Master/texmf-dist/tex/context/base/unic-cjk.mkii
index 786546318c0..dc06e912ceb 100644
--- a/Master/texmf-dist/tex/context/base/unic-cjk.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-cjk.mkii
@@ -5,7 +5,7 @@
%D subtitle=CJK Vectors,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-exp.mkii b/Master/texmf-dist/tex/context/base/unic-exp.mkii
index 027aedab857..4bdda3f6fe8 100644
--- a/Master/texmf-dist/tex/context/base/unic-exp.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-exp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Expansion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-ini.mkii b/Master/texmf-dist/tex/context/base/unic-ini.mkii
index 7e358341ddd..96aed77bcd8 100644
--- a/Master/texmf-dist/tex/context/base/unic-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/unic-ini.mkiv b/Master/texmf-dist/tex/context/base/unic-ini.mkiv
index 62fd822429e..55764dbdc88 100644
--- a/Master/texmf-dist/tex/context/base/unic-ini.mkiv
+++ b/Master/texmf-dist/tex/context/base/unic-ini.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\UNICODE\ \& UTF-8 support,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -17,25 +17,21 @@
\unprotect
-\let\keeputfcharacters\relax % used in xtag
-\newconstant\utfunicodetracer % used in xtag
-
-%def\unicodechar #1{\char\numexpr#1\relax} % no lookahead
\def\unicodenumber #1{\the \numexpr#1\relax} % no lookahead
\def\unicodehexnumber#1{\cldcontext{number.toevenhex(\number#1))}}
-%D Better is:
-%D
%D \startbuffer
%D \unicodechar{left square bracket}okay\unicodechar{right square bracket}
%D \stopbuffer
%D
%D \typebuffer \getbuffer
-\def\unicodechar #1{\ctxcommand{unicodechar("#1")}}
+%def\unicodechar#1{\char\numexpr#1\relax} % no lookahead
+\def\unicodechar#1{\ctxcommand{unicodechar("#1")}}
-\unexpanded\def\unknownchar{{\hbox{\vrule\!!width.5em\!!height1ex\!!depth\zeropoint}}}
+\unexpanded\def\unknownchar
+ {\dontleavehmode\hbox{\vrule\!!width.5em\!!height1ex\!!depth\zeropoint}}
-\ifx\zwnbsp\undefined \let\zwnbsp\relax \fi % zerowidthnonbreakablespace
+\ifdefined\zwnbsp\else \let\zwnbsp\relax \fi % zerowidthnonbreakablespace
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/unic-run.mkii b/Master/texmf-dist/tex/context/base/unic-run.mkii
index 09c70151189..96348d8a792 100644
--- a/Master/texmf-dist/tex/context/base/unic-run.mkii
+++ b/Master/texmf-dist/tex/context/base/unic-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Goodies,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/util-deb.lua b/Master/texmf-dist/tex/context/base/util-deb.lua
index ce55de5c7cb..d82c1a114f5 100644
--- a/Master/texmf-dist/tex/context/base/util-deb.lua
+++ b/Master/texmf-dist/tex/context/base/util-deb.lua
@@ -27,90 +27,55 @@ local names = { }
-- one
local function hook()
- local f = getinfo(2,"f").func
- local n = getinfo(2,"Sn")
--- if n.what == "C" and n.name then print (n.namewhat .. ': ' .. n.name) end
+ local f = getinfo(2) -- "nS"
if f then
- local cf = counters[f]
- if cf == nil then
- counters[f] = 1
- names[f] = n
- else
- counters[f] = cf + 1
- end
- end
-end
-
-local function getname(func)
- local n = names[func]
- if n then
- if n.what == "C" then
- return n.name or '<anonymous>'
+ local n = "unknown"
+ if f.what == "C" then
+ n = f.name or '<anonymous>'
+ if not names[n] then
+ names[n] = format("%42s",n)
+ end
else
-- source short_src linedefined what name namewhat nups func
- local name = n.name or n.namewhat or n.what
- if not name or name == "" then name = "?" end
- return format("%s : %s : %s", n.short_src or "unknown source", n.linedefined or "--", name)
+ n = f.name or f.namewhat or f.what
+ if not n or n == "" then
+ n = "?"
+ end
+ if not names[n] then
+ names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ end
end
- else
- return "unknown"
+ counters[n] = (counters[n] or 0) + 1
end
end
-function debugger.showstats(printer,threshold)
+function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
printer = printer or texio.write or print
threshold = threshold or 0
local total, grandtotal, functions = 0, 0, 0
- printer("\n") -- ugly but ok
- -- table.sort(counters)
- for func, count in next, counters do
- if count > threshold then
- local name = getname(func)
- if not find(name,"for generator") then
- printer(format("%8i %s", count, name))
- total = total + count
- end
+ local dataset = { }
+ for name, count in next, counters do
+ dataset[#dataset+1] = { name, count }
+ end
+ table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
+ for i=1,#dataset do
+ local d = dataset[i]
+ local name = d[1]
+ local count = d[2]
+ if count > threshold and not find(name,"for generator") then -- move up
+ printer(format("%8i %s\n", count, names[name]))
+ total = total + count
end
grandtotal = grandtotal + count
functions = functions + 1
end
- printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
+ printer("\n")
+ printer(format("functions : % 10i\n", functions))
+ printer(format("total : % 10i\n", total))
+ printer(format("grand total: % 10i\n", grandtotal))
+ printer(format("threshold : % 10i\n", threshold))
end
--- two
-
---~ local function hook()
---~ local n = getinfo(2)
---~ if n.what=="C" and not n.name then
---~ local f = tostring(debug.traceback())
---~ local cf = counters[f]
---~ if cf == nil then
---~ counters[f] = 1
---~ names[f] = n
---~ else
---~ counters[f] = cf + 1
---~ end
---~ end
---~ end
---~ function debugger.showstats(printer,threshold)
---~ printer = printer or texio.write or print
---~ threshold = threshold or 0
---~ local total, grandtotal, functions = 0, 0, 0
---~ printer("\n") -- ugly but ok
---~ -- table.sort(counters)
---~ for func, count in next, counters do
---~ if count > threshold then
---~ printer(format("%8i %s", count, func))
---~ total = total + count
---~ end
---~ grandtotal = grandtotal + count
---~ functions = functions + 1
---~ end
---~ printer(format("functions: %s, total: %s, grand total: %s, threshold: %s\n", functions, total, grandtotal, threshold))
---~ end
-
--- rest
-
function debugger.savestats(filename,threshold)
local f = io.open(filename,'w')
if f then
@@ -144,6 +109,7 @@ end
--~ debugger.showstats(print,3)
local is_node = node and node.is_node
+local is_lpeg = lpeg and lpeg.type
function inspect(i) -- global function
local ti = type(i)
@@ -151,7 +117,26 @@ function inspect(i) -- global function
table.print(i,"table")
elseif is_node and is_node(i) then
table.print(nodes.astable(i),tostring(i))
+ elseif is_lpeg and is_lpeg(i) then
+ lpeg.print(i)
else
print(tostring(i))
end
end
+
+-- from the lua book:
+
+function traceback()
+ local level = 1
+ while true do
+ local info = debug.getinfo(level, "Sl")
+ if not info then
+ break
+ elseif info.what == "C" then
+ print(format("%3i : C function",level))
+ else
+ print(format("%3i : [%s]:%d",level,info.short_src,info.currentline))
+ end
+ level = level + 1
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/util-dim.lua b/Master/texmf-dist/tex/context/base/util-dim.lua
index 4e2cc166265..47e43c386e4 100644
--- a/Master/texmf-dist/tex/context/base/util-dim.lua
+++ b/Master/texmf-dist/tex/context/base/util-dim.lua
@@ -91,7 +91,12 @@ local function numbertodimen(n,unit,fmt)
return n
else
unit = unit or 'pt'
- return format(fmt or "%s%s",n*dimenfactors[unit],unit)
+ if not fmt then
+ fmt = "%s%s"
+ elseif fmt == true then
+ fmt = "%0.5f%s"
+ end
+ return format(fmt,n*dimenfactors[unit],unit)
-- if fmt then
-- return format(fmt,n*dimenfactors[unit],unit)
-- else
@@ -108,18 +113,18 @@ number.maxdimen = 1073741823
number.todimen = numbertodimen
number.dimenfactors = dimenfactors
-function number.topoints (n) return numbertodimen(n,"pt") end
-function number.toinches (n) return numbertodimen(n,"in") end
-function number.tocentimeters (n) return numbertodimen(n,"cm") end
-function number.tomillimeters (n) return numbertodimen(n,"mm") end
-function number.toscaledpoints(n) return numbertodimen(n,"sp") end
-function number.toscaledpoints(n) return n .. "sp" end
-function number.tobasepoints (n) return numbertodimen(n,"bp") end
-function number.topicas (n) return numbertodimen(n "pc") end
-function number.todidots (n) return numbertodimen(n,"dd") end
-function number.tociceros (n) return numbertodimen(n,"cc") end
-function number.tonewdidots (n) return numbertodimen(n,"nd") end
-function number.tonewciceros (n) return numbertodimen(n,"nc") end
+function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end
+function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end
+function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end
+function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end
+function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end
+function number.toscaledpoints(n) return n .. "sp" end
+function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end
+function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end
+function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end
+function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end
+function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end
+function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end
--[[ldx--
<p>More interesting it to implement a (sort of) dimen datatype, one
diff --git a/Master/texmf-dist/tex/context/base/util-lua.lua b/Master/texmf-dist/tex/context/base/util-lua.lua
index 54c2468baf6..b49e93beb38 100644
--- a/Master/texmf-dist/tex/context/base/util-lua.lua
+++ b/Master/texmf-dist/tex/context/base/util-lua.lua
@@ -10,14 +10,29 @@ utilities = utilities or {}
utilities.lua = utilities.lua or { }
utilities.report = logs and logs.reporter("system") or print
-function utilities.lua.compile(luafile,lucfile,cleanup,strip) -- defaults: cleanup=false strip=true
+local function stupidcompile(luafile,lucfile)
+ local data = io.loaddata(luafile)
+ if data and data ~= "" then
+ data = string.dump(data)
+ if data and data ~= "" then
+ io.savedata(lucfile,data)
+ end
+ end
+end
+
+function utilities.lua.compile(luafile,lucfile,cleanup,strip,fallback) -- defaults: cleanup=false strip=true
utilities.report("lua: compiling %s into %s",luafile,lucfile)
os.remove(lucfile)
local command = "-o " .. string.quoted(lucfile) .. " " .. string.quoted(luafile)
if strip ~= false then
command = "-s " .. command
end
- local done = os.spawn("texluac " .. command) == 0 or os.spawn("luac " .. command) == 0
+ local done = os.spawn("texluac " .. command) == 0 -- or os.spawn("luac " .. command) == 0
+ if not done and fallback then
+ utilities.report("lua: dumping %s into %s (unstripped)",luafile,lucfile)
+ stupidcompile(luafile,lucfile) -- maybe use the stripper we have elsewhere
+ cleanup = false -- better see how worse it is
+ end
if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
utilities.report("lua: removing %s",luafile)
os.remove(luafile)
diff --git a/Master/texmf-dist/tex/context/base/util-pck.lua b/Master/texmf-dist/tex/context/base/util-pck.lua
index c802a09ed81..d964c7a23a2 100644
--- a/Master/texmf-dist/tex/context/base/util-pck.lua
+++ b/Master/texmf-dist/tex/context/base/util-pck.lua
@@ -62,34 +62,38 @@ packers.simplehashed = simplehashed
--~ end
local function pack(t,keys,hash,index)
- for k,v in next, t do
- if type(v) == "table" then
- pack(v,keys,hash,index)
- if keys[k] then
- local h = hashed(v)
- local i = hash[h]
- if not i then
- i = #index + 1
- index[i] = v
- hash[h] = i
+ if t then
+ for k,v in next, t do
+ if type(v) == "table" then
+ pack(v,keys,hash,index)
+ if keys[k] then
+ local h = hashed(v)
+ local i = hash[h]
+ if not i then
+ i = #index + 1
+ index[i] = v
+ hash[h] = i
+ end
+ t[k] = i
end
- t[k] = i
end
end
end
end
local function unpack(t,keys,index)
- for k,v in next, t do
- if keys[k] and type(v) == "number" then
- local iv = index[v]
- if iv then
- v = iv
- t[k] = v
+ if t then
+ for k, v in next, t do
+ if keys[k] and type(v) == "number" then
+ local iv = index[v]
+ if iv then
+ v = iv
+ t[k] = v
+ end
+ end
+ if type(v) == "table" then
+ unpack(v,keys,index)
end
- end
- if type(v) == "table" then
- unpack(v,keys,index)
end
end
end
diff --git a/Master/texmf-dist/tex/context/base/util-prs.lua b/Master/texmf-dist/tex/context/base/util-prs.lua
index 59145376031..ab1bfb8eb26 100644
--- a/Master/texmf-dist/tex/context/base/util-prs.lua
+++ b/Master/texmf-dist/tex/context/base/util-prs.lua
@@ -6,9 +6,9 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local P, R, V, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
+local concat, format, gmatch, find = table.concat, string.format, string.gmatch, string.find
local tostring, type, next = tostring, type, next
utilities = utilities or {}
@@ -36,8 +36,12 @@ local rbrace = P("}")
local nobrace = 1 - (lbrace+rbrace)
local nested = P { lbrace * (nobrace + V(1))^0 * rbrace }
local spaces = space^0
+local argument = Cs((lbrace/"") * ((nobrace + nested)^0) * (rbrace/""))
+local content = (1-P(-1))^0
-lpeg.patterns.nested = nested
+lpeg.patterns.nested = nested -- no capture
+lpeg.patterns.argument = argument -- argument after e.g. =
+lpeg.patterns.content = content -- rest after e.g =
local value = P(lbrace * C((nobrace + nested)^0) * rbrace) + C((nested + (1-comma))^0)
@@ -118,9 +122,15 @@ parsers.patterns.settings_to_array = pattern
-- we could use a weak table as cache
-function parsers.settings_to_array(str)
+function parsers.settings_to_array(str,strict)
if not str or str == "" then
return { }
+ elseif strict then
+ if find(str,"{") then
+ return lpegmatch(pattern,str)
+ else
+ return { str }
+ end
else
return lpegmatch(pattern,str)
end
diff --git a/Master/texmf-dist/tex/context/base/util-seq.lua b/Master/texmf-dist/tex/context/base/util-seq.lua
index 22733b022db..c3361b7be9e 100644
--- a/Master/texmf-dist/tex/context/base/util-seq.lua
+++ b/Master/texmf-dist/tex/context/base/util-seq.lua
@@ -30,7 +30,9 @@ utilities.sequencers = sequencers
local functions = allocate()
sequencers.functions = functions
-local removevalue, insertaftervalue, insertbeforevalue = tables.removevalue, tables.insertaftervalue, tables.insertbeforevalue
+local removevalue = tables.removevalue
+local insertaftervalue = tables.insertaftervalue
+local insertbeforevalue = tables.insertbeforevalue
local function validaction(action)
if type(action) == "string" then
@@ -45,7 +47,11 @@ local function validaction(action)
return true
end
-function sequencers.reset(t)
+local compile
+
+local known = { } -- just a convenience, in case we want public access (only to a few methods)
+
+function sequencers.new(t) -- was reset
local s = {
list = { },
order = { },
@@ -59,85 +65,127 @@ function sequencers.reset(t)
s.arguments = t.arguments
s.returnvalues = t.returnvalues
s.results = t.results
+ local name = t.name
+ if name and name ~= "" then
+ s.name = name
+ known[name] = s
+ end
end
+ table.setmetatableindex(s,function(t,k)
+ -- this will automake a dirty runner
+ if k == "runner" then
+ local v = compile(t,t.compiler)
+ return v
+ end
+ end)
+ known[s] = s -- saves test for string later on
return s
end
function sequencers.prependgroup(t,group,where)
+ t = known[t]
if t then
local order = t.order
removevalue(order,group)
insertbeforevalue(order,where,group)
- t.list[group], t.dirty, t.runner = { }, true, nil
+ t.list[group] = { }
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.appendgroup(t,group,where)
+ t = known[t]
if t then
local order = t.order
removevalue(order,group)
insertaftervalue(order,where,group)
- t.list[group], t.dirty, t.runner = { }, true, nil
+ t.list[group] = { }
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.prependaction(t,group,action,where,kind,force)
+ t = known[t]
if t then
local g = t.list[group]
if g and (force or validaction(action)) then
removevalue(g,action)
insertbeforevalue(g,where,action)
- t.kind[action], t.dirty, t.runner = kind, true, nil
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
end
end
end
function sequencers.appendaction(t,group,action,where,kind,force)
+ t = known[t]
if t then
local g = t.list[group]
if g and (force or validaction(action)) then
removevalue(g,action)
insertaftervalue(g,where,action)
- t.kind[action], t.dirty, t.runner = kind, true, nil
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
end
end
end
-function sequencers.enableaction (t,action)
+function sequencers.enableaction(t,action)
+ t = known[t]
if t then
- t.askip[action], t.dirty, t.runner = false, true, nil
+ t.askip[action] = false
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.disableaction(t,action)
+ t = known[t]
if t then
- t.askip[action], t.dirty, t.runner = true, true, nil
+ t.askip[action] = true
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.enablegroup(t,group)
+ t = known[t]
if t then
- t.gskip[group], t.dirty, t.runner = false, true, nil
+ t.gskip[action] = false
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.disablegroup(t,group)
+ t = known[t]
if t then
- t.gskip[group], t.dirty, t.runner = true, true, nil
+ t.gskip[action] = true
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.setkind(t,action,kind)
+ t = known[t]
if t then
- t.kind[action], t.dirty, t.runner = kind, true, nil
+ t.kind[action] = kind
+ t.dirty = true
+ t.runner = nil
end
end
function sequencers.removeaction(t,group,action,force)
+ t = known[t]
local g = t and t.list[group]
if g and (force or validaction(action)) then
removevalue(g,action)
- t.dirty, t.runner = true, nil
+ t.dirty = true
+ t.runner = nil
end
end
@@ -145,7 +193,7 @@ local function localize(str)
return (gsub(str,"[%.: ]+","_"))
end
-local function construct(t,nodummy)
+local function construct(t)
local list, order, kind, gskip, askip = t.list, t.order, t.kind, t.gskip, t.askip
local arguments, returnvalues, results = t.arguments or "...", t.returnvalues, t.results
local variables, calls, n = { }, { }, 0
@@ -176,8 +224,8 @@ local function construct(t,nodummy)
end
end
t.dirty = false
- if nodummy and #calls == 0 then
- return nil
+ if n == 0 then
+ t.compiled = ""
else
variables = concat(variables,"\n")
calls = concat(calls,"\n")
@@ -186,44 +234,45 @@ local function construct(t,nodummy)
else
t.compiled = format("%s\nreturn function(%s)\n%s\nend",variables,arguments,calls)
end
- return t.compiled -- also stored so that we can trace
end
+ return t.compiled -- also stored so that we can trace
end
sequencers.tostring = construct
sequencers.localize = localize
-local function compile(t,compiler,n)
+compile = function(t,compiler,n) -- already referred to in sequencers.new
+ local compiled
if not t or type(t) == "string" then
-- weird ... t.compiled = t .. so
return false
- elseif compiler then
- t.compiled = compiler(t,n)
+ end
+ if compiler then
+ compiled = compiler(t,n)
+ t.compiled = compiled
else
- t.compiled = construct(t)
+ compiled = construct(t,n)
+ end
+ local runner
+ if compiled == "" then
+ runner = false
+ else
+ runner = compiled and loadstring(compiled)()
end
- local runner = loadstring(t.compiled)()
t.runner = runner
- return runner -- faster
+ return runner
end
sequencers.compile = compile
-function sequencers.autocompile(t,compiler,n) -- to be used in tasks
- t.runner = compile(t,compiler,n)
- local autorunner = function(...)
- return (t.runner or compile(t,compiler,n))(...) -- ugly but less bytecode
- end
- t.autorunner = autorunner
- return autorunner -- one more encapsulation
-end
-
-- we used to deal with tail as well but now that the lists are always
-- double linked and the kernel function no longer expect tail as
-- argument we stick to head and done (done can probably also go
-- as luatex deals with return values efficiently now .. in the
-- past there was some copying involved, but no longer)
+-- todo: use sequencer (can have arguments and returnvalues etc now)
+
local template = [[
%s
return function(head%s)
diff --git a/Master/texmf-dist/tex/context/base/util-sto.lua b/Master/texmf-dist/tex/context/base/util-sto.lua
index f4521c91fce..42ee6cf003b 100644
--- a/Master/texmf-dist/tex/context/base/util-sto.lua
+++ b/Master/texmf-dist/tex/context/base/util-sto.lua
@@ -14,8 +14,8 @@ local storage = utilities.storage
function storage.mark(t)
if not t then
- texio.write_nl("fatal error: storage '%s' cannot be marked",t)
- os.exit()
+ texio.write_nl("fatal error: storage cannot be marked")
+ return -- os.exit()
end
local m = getmetatable(t)
if not m then
@@ -44,8 +44,8 @@ end
function storage.checked(t)
if not t then
- texio.write_nl("fatal error: storage '%s' has not been allocated",t)
- os.exit()
+ texio.write_nl("fatal error: storage has not been allocated")
+ return -- os.exit()
end
return t
end
@@ -98,13 +98,13 @@ end
-- table namespace ?
-local function f_empty () return "" end -- t,k
-local function f_self (t,k) t[k] = k return k end
-local function f_ignore() end -- t,k,v
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
-local t_empty = { __index = empty }
-local t_self = { __index = self }
-local t_ignore = { __newindex = ignore }
+local t_empty = { __index = f_empty }
+local t_self = { __index = f_self }
+local t_ignore = { __newindex = f_ignore }
function table.setmetatableindex(t,f)
local m = getmetatable(t)
@@ -125,6 +125,7 @@ function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
end
+ return t
end
function table.setmetatablenewindex(t,f)
@@ -142,6 +143,7 @@ function table.setmetatablenewindex(t,f)
setmetatable(t,{ __newindex = f })
end
end
+ return t
end
function table.setmetatablecall(t,f)
@@ -151,6 +153,7 @@ function table.setmetatablecall(t,f)
else
setmetatable(t,{ __call = f })
end
+ return t
end
function table.setmetatablekey(t,key,value)
@@ -160,6 +163,7 @@ function table.setmetatablekey(t,key,value)
setmetatable(t,m)
end
m[key] = value
+ return t
end
function table.getmetatablekey(t,key,value)
diff --git a/Master/texmf-dist/tex/context/base/util-str.lua b/Master/texmf-dist/tex/context/base/util-str.lua
index adcbf1654d2..75cf443fbde 100644
--- a/Master/texmf-dist/tex/context/base/util-str.lua
+++ b/Master/texmf-dist/tex/context/base/util-str.lua
@@ -10,7 +10,7 @@ utilities = utilities or {}
utilities.strings = utilities.strings or { }
local strings = utilities.strings
-local find, gsub, rep = string.find, string.gsub, string.rep
+local gsub, rep = string.gsub, string.rep
local Cs, C, Cp, P, Carg = lpeg.Cs, lpeg.C, lpeg.Cp, lpeg.P, lpeg.Carg
local patterns, lpegmatch = lpeg.patterns, lpeg.match
@@ -33,27 +33,45 @@ end
-- The following functions might end up in another namespace.
---~ function strings.tabtospace(str,tab)
---~ -- we don't handle embedded newlines
---~ while true do
---~ local s = find(str,"\t")
---~ if s then
---~ if not tab then tab = 7 end -- only when found
---~ local d = tab-(s-1) % tab
---~ if d > 0 then
---~ str = gsub(str,"\t",rep(" ",d),1)
---~ else
---~ str = gsub(str,"\t","",1)
---~ end
---~ else
---~ break
---~ end
---~ end
---~ return str
---~ end
+local repeaters = { } -- watch how we also moved the -1 in depth-1 to the creator
+
+function strings.newrepeater(str,offset)
+ offset = offset or 0
+ local s = repeaters[str]
+ if not s then
+ s = { }
+ repeaters[str] = s
+ end
+ local t = s[offset]
+ if t then
+ return t
+ end
+ t = { }
+ setmetatable(t, {
+ __index = function(t,k)
+ if not k then
+ return ""
+ end
+ local n = k + offset
+ local s = n > 0 and rep(str,n) or ""
+ t[k] = s
+ return s
+ end
+ } )
+ s[offset] = t
+ return t
+end
+
+--~ local dashes = strings.newrepeater("--",-1)
+
+--~ print(dashes[2])
+--~ print(dashes[3])
+--~ print(dashes[1])
local extra, tab, start = 0, 0, 4, 0
+local nspaces = strings.newrepeater(" ")
+
local pattern =
Carg(1) / function(t)
extra, tab, start = 0, t or 7, 1
@@ -64,7 +82,7 @@ local pattern =
local spaces = tab-(current-1) % tab
if spaces > 0 then
extra = extra + spaces - 1
- return rep(" ",spaces)
+ return nspaces[spaces] -- rep(" ",spaces)
else
return ""
end
@@ -105,3 +123,8 @@ end
--~ bb
--~ cccccc
--~ ]])
+
+function strings.nice(str)
+ str = gsub(str,"[:%-+_]+"," ") -- maybe more
+ return str
+end
diff --git a/Master/texmf-dist/tex/context/base/util-tab.lua b/Master/texmf-dist/tex/context/base/util-tab.lua
index 818266d3c62..28a6b8cc531 100644
--- a/Master/texmf-dist/tex/context/base/util-tab.lua
+++ b/Master/texmf-dist/tex/context/base/util-tab.lua
@@ -10,9 +10,10 @@ utilities = utilities or {}
utilities.tables = utilities.tables or { }
local tables = utilities.tables
-local format, gmatch = string.format, string.gmatch
+local format, gmatch, rep = string.format, string.gmatch, string.rep
local concat, insert, remove = table.concat, table.insert, table.remove
local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
+local type, next, rawset, tonumber = type, next, rawset, tonumber
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -28,14 +29,31 @@ function tables.definetable(target) -- defines undefined tables
return concat(t,"\n")
end
-function tables.accesstable(target)
- local t = _G
+function tables.accesstable(target,root)
+ local t = root or _G
for name in gmatch(target,"([^%.]+)") do
t = t[name]
+ if not t then
+ return
+ end
end
return t
end
+function tables.migratetable(target,v,root)
+ local t = root or _G
+ local names = string.split(target,".")
+ for i=1,#names-1 do
+ local name = names[i]
+ t[name] = t[name] or { }
+ t = t[name]
+ if not t then
+ return
+ end
+ end
+ t[names[#names]] = v
+end
+
function tables.removevalue(t,value) -- todo: n
if value then
for i=1,#t do
@@ -79,13 +97,19 @@ end
-- experimental
-local function toxml(t,d,result)
+local function toxml(t,d,result,step)
for k, v in table.sortedpairs(t) do
if type(v) == "table" then
- result[#result+1] = format("%s<%s>",d,k)
- toxml(v,d.." ",result)
- result[#result+1] = format("%s</%s>",d,k)
- elseif tonumber(k) then
+ if type(k) == "number" then
+ result[#result+1] = format("%s<entry n='%s'>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</entry>",d,k)
+ else
+ result[#result+1] = format("%s<%s>",d,k)
+ toxml(v,d..step,result,step)
+ result[#result+1] = format("%s</%s>",d,k)
+ end
+ elseif type(k) == "number" then
result[#result+1] = format("%s<entry n='%s'>%s</entry>",d,k,v,k)
else
result[#result+1] = format("%s<%s>%s</%s>",d,k,tostring(v),k)
@@ -93,13 +117,52 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name,nobanner)
+function table.toxml(t,name,nobanner,indent,spaces)
local noroot = name == false
local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ local indent = rep(" ",indent or 0)
+ local spaces = rep(" ",spaces or 1)
if noroot then
- toxml( t, "", result)
+ toxml( t, inndent, result, spaces)
else
- toxml( { [name or "root"] = t }, "", result)
+ toxml( { [name or "root"] = t }, indent, result, spaces)
end
return concat(result,"\n")
end
+
+-- also experimental
+
+-- encapsulate(table,utilities.tables)
+-- encapsulate(table,utilities.tables,true)
+-- encapsulate(table,true)
+
+function tables.encapsulate(core,capsule,protect)
+ if type(capsule) ~= "table" then
+ protect = true
+ capsule = { }
+ end
+ for key, value in next, core do
+ if capsule[key] then
+ print(format("\ninvalid inheritance '%s' in '%s': %s",key,tostring(core)))
+ os.exit()
+ else
+ capsule[key] = value
+ end
+ end
+ if protect then
+ for key, value in next, core do
+ core[key] = nil
+ end
+ setmetatable(core, {
+ __index = capsule,
+ __newindex = function(t,key,value)
+ if capsule[key] then
+ print(format("\ninvalid overload '%s' in '%s'",key,tostring(core)))
+ os.exit()
+ else
+ rawset(t,key,value)
+ end
+ end
+ } )
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/verb-c.mkii b/Master/texmf-dist/tex/context/base/verb-c.mkii
index 1ecb0afc2b5..930977ca4f6 100644
--- a/Master/texmf-dist/tex/context/base/verb-c.mkii
+++ b/Master/texmf-dist/tex/context/base/verb-c.mkii
@@ -5,7 +5,7 @@
%D subtitle=Pretty C Verbatim,
%D author=Nikolai Weibull,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/verb-ini.mkii b/Master/texmf-dist/tex/context/base/verb-ini.mkii
index 829e10fd82e..5a817b4bb91 100644
--- a/Master/texmf-dist/tex/context/base/verb-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/verb-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/verb-js.mkii b/Master/texmf-dist/tex/context/base/verb-js.mkii
index e497e475b05..c249bd9bb2c 100644
--- a/Master/texmf-dist/tex/context/base/verb-js.mkii
+++ b/Master/texmf-dist/tex/context/base/verb-js.mkii
@@ -5,7 +5,7 @@
%D subtitle=Pretty \JAVASCRIPT\ Verbatim,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/verb-jv.mkii b/Master/texmf-dist/tex/context/base/verb-jv.mkii
index ee79e5c03d7..2149c3a4abc 100644
--- a/Master/texmf-dist/tex/context/base/verb-jv.mkii
+++ b/Master/texmf-dist/tex/context/base/verb-jv.mkii
@@ -5,7 +5,7 @@
%D subtitle=Pretty \JAVA\ Verbatim,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/verb-mp.mkii b/Master/texmf-dist/tex/context/base/verb-mp.mkii
index 7affaf0c4c4..aef52217d8c 100644
--- a/Master/texmf-dist/tex/context/base/verb-mp.mkii
+++ b/Master/texmf-dist/tex/context/base/verb-mp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Pretty \METAPOST\ Verbatim,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/verb-pl.mkii b/Master/texmf-dist/tex/context/base/verb-pl.mkii
index 47ce9a54f5a..634a0a3142a 100644
--- a/Master/texmf-dist/tex/context/base/verb-pl.mkii
+++ b/Master/texmf-dist/tex/context/base/verb-pl.mkii
@@ -5,7 +5,7 @@
%D subtitle=Pretty \PERL\ Verbatim,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/verb-tex.mkii b/Master/texmf-dist/tex/context/base/verb-tex.mkii
index 75e99fcefde..98655cc2d8a 100644
--- a/Master/texmf-dist/tex/context/base/verb-tex.mkii
+++ b/Master/texmf-dist/tex/context/base/verb-tex.mkii
@@ -5,7 +5,7 @@
%D subtitle=Pretty \TEX\ verbatim,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-asciimath.lua b/Master/texmf-dist/tex/context/base/x-asciimath.lua
index 50f4b0391a8..5ef741ce383 100644
--- a/Master/texmf-dist/tex/context/base/x-asciimath.lua
+++ b/Master/texmf-dist/tex/context/base/x-asciimath.lua
@@ -19,9 +19,7 @@ moduledata.asciimath = asciimath
local report_asciimath = logs.reporter("mathematics","asciimath")
local format = string.format
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
local lpegmatch = lpeg.match
-
local S, P, R, C, V, Cc, Ct, Cs = lpeg.S, lpeg.P, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc, lpeg.Ct, lpeg.Cs
local letter = lpeg.patterns.utf8
@@ -199,9 +197,9 @@ local function converted(original,totex)
end
if totex then
if ok then
- texsprint(ctxcatcodes,"\\mathematics{",result,"}")
+ context.mathematics(result)
else
- texsprint(ctxcatcodes,"{\\tt",result,"}")
+ context.type(result) -- some day monospaced
end
else
return result
diff --git a/Master/texmf-dist/tex/context/base/x-asciimath.mkiv b/Master/texmf-dist/tex/context/base/x-asciimath.mkiv
index fac3980a089..23caf13aa3c 100644
--- a/Master/texmf-dist/tex/context/base/x-asciimath.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-asciimath.mkiv
@@ -5,7 +5,7 @@
%D subtitle=AsciiMath,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-calcmath.lua b/Master/texmf-dist/tex/context/base/x-calcmath.lua
index bcf72f26f6e..707abe82a22 100644
--- a/Master/texmf-dist/tex/context/base/x-calcmath.lua
+++ b/Master/texmf-dist/tex/context/base/x-calcmath.lua
@@ -7,6 +7,7 @@ if not modules then modules = { } end modules ['x-calcmath'] = {
}
local format, lower, upper, gsub, sub = string.format, string.lower, string.upper, string.gsub, string.sub
+local concat = table.concat
local lpegmatch = lpeg.match
local calcmath = { }
@@ -225,7 +226,7 @@ if false then
local parser = space * grammar * -1
- local texprint = function(...) texio.write(table.concat{ ... }) end
+ local texprint = function(...) texio.write(concat{ ... }) end
local function has_factor(t)
for i=1,#t do
diff --git a/Master/texmf-dist/tex/context/base/x-calcmath.mkii b/Master/texmf-dist/tex/context/base/x-calcmath.mkii
index 68119b2fd04..a649aa64878 100644
--- a/Master/texmf-dist/tex/context/base/x-calcmath.mkii
+++ b/Master/texmf-dist/tex/context/base/x-calcmath.mkii
@@ -5,7 +5,7 @@
%D subtitle=Calculator Math,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-calcmath.mkiv b/Master/texmf-dist/tex/context/base/x-calcmath.mkiv
index 7dfa60e0e92..ce4f95ad233 100644
--- a/Master/texmf-dist/tex/context/base/x-calcmath.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-calcmath.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Calculator Math,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-cals.lua b/Master/texmf-dist/tex/context/base/x-cals.lua
index 904dc39c95b..4051dd157e1 100644
--- a/Master/texmf-dist/tex/context/base/x-cals.lua
+++ b/Master/texmf-dist/tex/context/base/x-cals.lua
@@ -7,8 +7,7 @@ if not modules then modules = { } end modules ['x-cals'] = {
}
local format, lower = string.format, string.lower
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
-local xmlsprint, xmlcprint, xmlcollected = xml.sprint, xml.cprint, xml.collected
+local xmlsprint, xmlcprint, xmlcollected, xmlelements = xml.sprint, xml.cprint, xml.collected, xml.elements
local n_todimen, s_todimen = number.todimen, string.todimen
-- there is room for speedups as well as cleanup (using context functions)
@@ -120,12 +119,13 @@ local function getspans(root, pattern, names, spans)
end
end
---local function texsprint(a,b) print(b) end
---local function xmlsprint(a) print(a) end
+local bTR, eTR, bTD, eTD = context.bTR, context.eTR, context.bTD, context.eTD
function cals.table(root,namespace)
local prefix = (namespace or "cals") .. ":"
+
+ local prefix = namespace and namespace ~= "" and (namespace .. ":") or ""
local p = "/" .. prefix
local tgroupspec = p .. "tgroup"
@@ -134,31 +134,34 @@ function cals.table(root,namespace)
local hcolspec = p .. "thead" .. p .. "colspec"
local bcolspec = p .. "tbody" .. p .. "colspec"
local fcolspec = p .. "tfoot" .. p .. "colspec"
- local entryspec = p .. "entry" .. "|" ..prefix .. "entrytbl"
+ local entryspec = p .. "entry" .. "|" .. prefix .. "entrytbl" -- shouldn't that be p ?
local hrowspec = p .. "thead" .. p .. "row"
local browspec = p .. "tbody" .. p .. "row"
local frowspec = p .. "tfoot" .. p .. "row"
local function tablepart(root, xcolspec, xrowspec, before, after) -- move this one outside
- texsprint(ctxcatcodes,before)
+ before()
local at = root.at
local pphalign, ppvalign = at.align, at.valign
local names, widths, spans = { }, { }, { }
getspecs(root, colspec , names, widths)
getspecs(root, xcolspec, names, widths)
getspans(root, spanspec, names, spans)
- for r, d, k in xml.elements(root,xrowspec) do
- texsprint(ctxcatcodes,"\\bTR")
+ for r, d, k in xmlelements(root,xrowspec) do
+ bTR()
local dk = d[k]
local at = dk.at
local phalign, pvalign = at.align or pphalign, at.valign or ppvalign -- todo: __p__ test
local col = 1
- for rr, dd, kk in xml.elements(dk,entryspec) do
+ for rr, dd, kk in xmlelements(dk,entryspec) do
local dk = dd[kk]
if dk.tg == "entrytbl" then
- texsprint(ctxcatcodes,"\\bTD{")
+ -- bTD(function() cals.table(dk) end)
+ bTD()
+ context("{")
cals.table(dk)
- texsprint(ctxcatcodes,"}\\eTD")
+ context("}")
+ eTD()
col = col + 1
else
local at = dk.at
@@ -174,36 +177,42 @@ function cals.table(root,namespace)
valign = valignments[valign]
end
local width = widths[col]
- if s or m or halign or valign or width then -- only english interface !
- texsprint(ctxcatcodes,format("\\bTD[nx=%s,ny=%s,align={%s,%s},width=%s]",
- s or 1, (m or 0)+1, halign or "flushleft", valign or "high", width or "fit"))
- -- texsprint(ctxcatcodes,"\\bTD[nx=",s or 1,"ny=",(m or 0)+1,"align={",halign or "flushleft",",",valign or "high","},width=",width or "fit","]")
+ if s or m or halign or valign or width then -- currently only english interface !
+ bTD {
+ nx = s or 1,
+ ny = (m or 0) + 1,
+ align = format("{%s,%s}",halign or "flushleft",valign or "high"),
+ width = width or "fit",
+ }
else
- texsprint(ctxcatcodes,"\\bTD[align={flushleft,high},width=fit]") -- else problems with vertical material
+ bTD {
+ align = "{flushleft,high}",
+ width = "fit", -- else problems with vertical material
+ }
end
xmlcprint(dk)
- texsprint(ctxcatcodes,"\\eTD")
+ eTD()
col = col + (s or 1)
end
end
- texsprint(ctxcatcodes,"\\eTR")
+ eTR()
end
- texsprint(ctxcatcodes,after)
+ after()
end
for tgroup in lxml.collected(root,tgroupspec) do
- texsprint(ctxcatcodes, "\\directsetup{cals:table:before}")
+ context.directsetup("cals:table:before")
lxml.directives.before(root,"cdx") -- "cals:table"
- texsprint(ctxcatcodes, "\\bgroup")
+ context.bgroup()
lxml.directives.setup(root,"cdx") -- "cals:table"
- texsprint(ctxcatcodes, "\\bTABLE")
- tablepart(tgroup, hcolspec, hrowspec, "\\bTABLEhead", "\\eTABLEhead")
- tablepart(tgroup, bcolspec, browspec, "\\bTABLEbody", "\\eTABLEbody")
- tablepart(tgroup, fcolspec, frowspec, "\\bTABLEfoot", "\\eTABLEfoot")
- texsprint(ctxcatcodes, "\\eTABLE")
- texsprint(ctxcatcodes, "\\egroup")
+ context.bTABLE()
+ tablepart(tgroup, hcolspec, hrowspec, context.bTABLEhead, context.eTABLEhead)
+ tablepart(tgroup, bcolspec, browspec, context.bTABLEbody, context.eTABLEbody)
+ tablepart(tgroup, fcolspec, frowspec, context.bTABLEfoot, context.eTABLEfoot)
+ context.eTABLE()
+ context.egroup()
lxml.directives.after(root,"cdx") -- "cals:table"
- texsprint(ctxcatcodes, "\\directsetup{cals:table:after}")
+ context.directsetup("cals:table:after")
end
end
diff --git a/Master/texmf-dist/tex/context/base/x-cals.mkiv b/Master/texmf-dist/tex/context/base/x-cals.mkiv
index e0d2ac11f8b..4e68c34003d 100644
--- a/Master/texmf-dist/tex/context/base/x-cals.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-cals.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Cals table renderer,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
@@ -26,11 +26,20 @@
% \xmlregistersetup{xml:cals:process}
\startxmlsetups xml:cals:process
- \xmlsetfunction {\xmldocument} {cals:table} {moduledata.cals.table}
+% \xmlsetfunction {\xmldocument} {cals:table} {moduledata.cals.table}
+ \xmlsetfunction {#1} {cals:table} {moduledata.cals.table}
+\stopxmlsetups
+
+\startxmlsetups xml:cals:nonamespace
+% \xmlsetfunction {\xmldocument} {table} {moduledata.cals.table}
+ \xmlsetfunction {#1} {table} {moduledata.cals.table}
\stopxmlsetups
\xmlregistersetup{xml:cals:process}
\xmlregisterns{cals}{cals}
+%D One can register the nonamespace variant for cases where the cals
+%D model is embedded in the parent DTD.
+
\stopmodule
diff --git a/Master/texmf-dist/tex/context/base/x-chemml.mkii b/Master/texmf-dist/tex/context/base/x-chemml.mkii
index 68b52cdd144..08d64e54b80 100644
--- a/Master/texmf-dist/tex/context/base/x-chemml.mkii
+++ b/Master/texmf-dist/tex/context/base/x-chemml.mkii
@@ -5,7 +5,7 @@
%D subtitle=Loading CHEMML Filters,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-chemml.mkiv b/Master/texmf-dist/tex/context/base/x-chemml.mkiv
index 9ad8ed6c12b..34aba3011eb 100644
--- a/Master/texmf-dist/tex/context/base/x-chemml.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-chemml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=MkIV ChemML renderer,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-contml.mkii b/Master/texmf-dist/tex/context/base/x-contml.mkii
index a582d8eb90f..22fffa50a37 100644
--- a/Master/texmf-dist/tex/context/base/x-contml.mkii
+++ b/Master/texmf-dist/tex/context/base/x-contml.mkii
@@ -8,7 +8,7 @@
%D subtitle=Basic \CONTEXT\ commands,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-corres.mkii b/Master/texmf-dist/tex/context/base/x-corres.mkii
index 09c7263dc17..effd79a5b31 100644
--- a/Master/texmf-dist/tex/context/base/x-corres.mkii
+++ b/Master/texmf-dist/tex/context/base/x-corres.mkii
@@ -5,7 +5,7 @@
%D subtitle=Handling Correspondence Base,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-ct.lua b/Master/texmf-dist/tex/context/base/x-ct.lua
index 222a127cec6..2dee985c329 100644
--- a/Master/texmf-dist/tex/context/base/x-ct.lua
+++ b/Master/texmf-dist/tex/context/base/x-ct.lua
@@ -6,11 +6,12 @@ if not modules then modules = { } end modules ['x-ct'] = {
license = "see context related readme files"
}
-local xmlsprint, xmlfilter, xmlcollected = xml.sprint, xml.filter, xml.collected
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+-- needs testing
+
+local xmlsprint, xmlcprint, xmlfilter, xmlcollected = xml.sprint, xml.cprint, xml.filter, xml.collected
local format, concat, rep, find = string.format, table.concat, string.rep, string.find
-lxml.context = { }
+moduledata.ct = moduledata.ct or { }
local halignments = {
left = 'l',
@@ -23,16 +24,27 @@ local halignments = {
justify = '',
}
+local templates = { }
+
+function moduledata.ct.registertabulatetemplate(name,str)
+ templates[name] = str
+end
+
local function roottemplate(root)
local rt = root.at.template
if rt then
- if not find(rt,"|") then
- rt = gsub(rt,",","|")
+ local template = templates[rt]
+ if template then
+ return template
+ else
+ if not find(rt,"|") then
+ rt = gsub(rt,",","|")
+ end
+ if not find(rt,"^|") then rt = "|" .. rt end
+ if not find(rt,"|$") then rt = rt .. "|" end
+ return rt
end
- if not find(rt,"^|") then rt = "|" .. rt end
- if not find(rt,"|$") then rt = rt .. "|" end
end
- return rt
end
local function specifiedtemplate(root,templatespec)
@@ -69,7 +81,7 @@ end
local defaulttemplate = "|l|p|"
-function lxml.context.tabulate(root,namespace)
+function moduledata.ct.tabulate(root,namespace)
if not root then
return
else
@@ -79,7 +91,7 @@ function lxml.context.tabulate(root,namespace)
local prefix = (namespace or "context") .. ":"
local templatespec = "/" .. prefix .. "template" .. "/" .. prefix .. "column"
- local bodyrowspec = "/" .. prefix .. "body" .. "/" .. prefix .. "row"
+ local bodyrowspec = "/" .. prefix .. "body" .. "/" .. prefix .. "row"
local cellspec = "/" .. prefix .. "cell"
local template =
@@ -90,22 +102,6 @@ function lxml.context.tabulate(root,namespace)
-- todo: head and foot
---~ lxml.directives.before(root,'cdx')
---~ texsprint(ctxcatcodes, "\\bgroup")
---~ lxml.directives.setup(root,'cdx')
---~ texsprint(ctxcatcodes, format("\\starttabulate[%s]",template))
---~ for e in xmlcollected(root,bodyrowspec) do
---~ texsprint(ctxcatcodes, "\\NC ")
---~ for e in xmlcollected(e,cellspec) do
---~ texsprint(xml.text(e)) -- use some xmlprint
---~ texsprint(ctxcatcodes, "\\NC")
---~ end
---~ texsprint(ctxcatcodes, "\\NR")
---~ end
---~ texsprint(ctxcatcodes, "\\stoptabulate")
---~ texsprint(ctxcatcodes, "\\egroup")
---~ lxml.directives.after(root,'cdx')
-
local NC, NR = context.NC, context.NR
lxml.directives.before(root,'cdx')
@@ -115,7 +111,7 @@ function lxml.context.tabulate(root,namespace)
for e in xmlcollected(root,bodyrowspec) do
NC()
for e in xmlcollected(e,cellspec) do
- texsprint(xml.text(e)) -- test: xmlcprint(e)
+ xmlcprint(e)
NC()
end
NR()
@@ -126,7 +122,7 @@ function lxml.context.tabulate(root,namespace)
end
-function lxml.context.combination(root,namespace)
+function moduledata.ct.combination(root,namespace)
if not root then
return
@@ -147,33 +143,20 @@ function lxml.context.combination(root,namespace)
end
local template = format("%s*%s", nx or 1, ny or 1)
- -- todo: alignments
-
---~ lxml.directives.before(root,'cdx')
---~ texsprint(ctxcatcodes, "\\bgroup")
---~ lxml.directives.setup(root,'cdx')
---~ texsprint(ctxcatcodes, "\\startcombination[",template,"]")
---~ for e in xmlcollected(root,pairspec) do
---~ texsprint(ctxcatcodes,"{")
---~ xmlfilter(e,contentspec)
---~ texsprint(ctxcatcodes,"}{")
---~ xmlfilter(e,captionspec)
---~ texsprint(ctxcatcodes,"}")
---~ end
---~ texsprint(ctxcatcodes, "\\stopcombination")
---~ texsprint(ctxcatcodes, "\\egroup")
---~ lxml.directives.after(root,'cdx')
-
lxml.directives.before(root,'cdx')
context.bgroup()
lxml.directives.setup(root,'cdx')
context.startcombination { template }
for e in xmlcollected(root,pairspec) do
- texsprint(ctxcatcodes,"{")
+ -- context.combination(
+ -- function() xmlfilter(e,contentspec) end,
+ -- function() xmlfilter(e,captionspec) end
+ -- )
+ context("{")
xmlfilter(e,contentspec)
- texsprint(ctxcatcodes,"}{")
+ context("}{")
xmlfilter(e,captionspec)
- texsprint(ctxcatcodes,"}")
+ context("}")
end
context.stopcombination()
context.egroup()
diff --git a/Master/texmf-dist/tex/context/base/x-ct.mkiv b/Master/texmf-dist/tex/context/base/x-ct.mkiv
index ad20eea05c9..6a6352f0359 100644
--- a/Master/texmf-dist/tex/context/base/x-ct.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-ct.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\CONTEXT\ Structures,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
@@ -18,8 +18,8 @@
\registerctxluafile{x-ct}{}
\startxmlsetups xml:context:process
- \xmlsetfunction {\xmldocument} {context:tabulate} {lxml.context.tabulate}
- \xmlsetfunction {\xmldocument} {context:combination} {lxml.context.combination}
+ \xmlsetfunction {\xmldocument} {context:tabulate} {moduledata.ct.tabulate}
+ \xmlsetfunction {\xmldocument} {context:combination} {moduledata.ct.combination}
\stopxmlsetups
\xmlregistersetup{xml:context:process}
diff --git a/Master/texmf-dist/tex/context/base/x-dir-01.tex b/Master/texmf-dist/tex/context/base/x-dir-01.tex
index b1056fdd527..6e4192a1326 100644
--- a/Master/texmf-dist/tex/context/base/x-dir-01.tex
+++ b/Master/texmf-dist/tex/context/base/x-dir-01.tex
@@ -5,7 +5,7 @@
%D subtitle=Overview (1),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-dir-05.mkii b/Master/texmf-dist/tex/context/base/x-dir-05.mkii
index 0d0edd832e8..53e73c5eb86 100644
--- a/Master/texmf-dist/tex/context/base/x-dir-05.mkii
+++ b/Master/texmf-dist/tex/context/base/x-dir-05.mkii
@@ -5,7 +5,7 @@
%D subtitle=Access,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-dir-05.mkiv b/Master/texmf-dist/tex/context/base/x-dir-05.mkiv
index 120f725caaf..de1d3fa5f26 100644
--- a/Master/texmf-dist/tex/context/base/x-dir-05.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-dir-05.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Access,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -46,7 +46,7 @@
else
value = fs[name] or ""
end
- tex.sprint(tex.vrbcatcodes,value)
+ context.sprint(tex.vrbcatcodes,value)
end
end
\stopluacode
diff --git a/Master/texmf-dist/tex/context/base/x-entities.mkiv b/Master/texmf-dist/tex/context/base/x-entities.mkiv
new file mode 100644
index 00000000000..3dd02118adf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/x-entities.mkiv
@@ -0,0 +1,18 @@
+%D \module
+%D [ file=x-entities,
+%D version=2008.05.29,
+%D title=\CONTEXT\ XML Modules,
+%D subtitle=\HTML\ entities,
+%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 XML Macros / HTML entities}
+
+\ctxlua{characters.registerentities()}
+
+\endinput
diff --git a/Master/texmf-dist/tex/context/base/x-fe.mkii b/Master/texmf-dist/tex/context/base/x-fe.mkii
index 8562b1d5296..dcf415850a3 100644
--- a/Master/texmf-dist/tex/context/base/x-fe.mkii
+++ b/Master/texmf-dist/tex/context/base/x-fe.mkii
@@ -5,7 +5,7 @@
%D subtitle=Simple Extensions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-fig-00.mkii b/Master/texmf-dist/tex/context/base/x-fig-00.mkii
index d293dc39f96..2e000c64ca7 100644
--- a/Master/texmf-dist/tex/context/base/x-fig-00.mkii
+++ b/Master/texmf-dist/tex/context/base/x-fig-00.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Loading,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-fig-01.mkii b/Master/texmf-dist/tex/context/base/x-fig-01.mkii
index c2f97fea901..5a2ea20c83e 100644
--- a/Master/texmf-dist/tex/context/base/x-fig-01.mkii
+++ b/Master/texmf-dist/tex/context/base/x-fig-01.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-fig-02.mkii b/Master/texmf-dist/tex/context/base/x-fig-02.mkii
index 22d49d27adf..a8232fba9e1 100644
--- a/Master/texmf-dist/tex/context/base/x-fig-02.mkii
+++ b/Master/texmf-dist/tex/context/base/x-fig-02.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Inclusion (I),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-fig-03.mkii b/Master/texmf-dist/tex/context/base/x-fig-03.mkii
index 1317528235e..c7f03453e09 100644
--- a/Master/texmf-dist/tex/context/base/x-fig-03.mkii
+++ b/Master/texmf-dist/tex/context/base/x-fig-03.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Inclusion (II),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-fo.mkii b/Master/texmf-dist/tex/context/base/x-fo.mkii
index 83cfe2433ee..3631f6d7e14 100644
--- a/Master/texmf-dist/tex/context/base/x-fo.mkii
+++ b/Master/texmf-dist/tex/context/base/x-fo.mkii
@@ -5,7 +5,7 @@
%D subtitle=Formatting Objects,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-foxet.mkii b/Master/texmf-dist/tex/context/base/x-foxet.mkii
index 0f8e43af9af..d44cf2b7ec7 100644
--- a/Master/texmf-dist/tex/context/base/x-foxet.mkii
+++ b/Master/texmf-dist/tex/context/base/x-foxet.mkii
@@ -5,7 +5,7 @@
%D subtitle=Formatting Objects,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-foxet.mkiv b/Master/texmf-dist/tex/context/base/x-foxet.mkiv
index b27969721b8..80fe7e500ca 100644
--- a/Master/texmf-dist/tex/context/base/x-foxet.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-foxet.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Formatting Objects,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-ldx.lua b/Master/texmf-dist/tex/context/base/x-ldx.lua
index 18e7b9b38df..2a04d6126a9 100644
--- a/Master/texmf-dist/tex/context/base/x-ldx.lua
+++ b/Master/texmf-dist/tex/context/base/x-ldx.lua
@@ -1,3 +1,15 @@
+if not modules then modules = { } end modules ['x-ldx'] = {
+ version = 1.001,
+ comment = "companion to x-ldx.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- --[[ldx--
+-- <topic>Introduction</topic>
+-- --ldx]]--
+
--[[ldx--
<source>Lua Documentation Module</source>
@@ -5,12 +17,11 @@ This file is part of the <logo label='context'/> documentation suite and
itself serves as an example of using <logo label='lua'/> in combination
with <logo label='tex'/>.
-I will rewrite this using lpeg once I have the time to study that nice new
-subsystem. On the other hand, we cannot expect proper <logo label='tex'/>
-ad for educational purposed the syntax migh be wrong.
+I will rewrite this using lpeg. On the other hand, we cannot expect proper
+<logo label='tex'/> and for educational purposed the syntax might be wrong.
--ldx]]--
--- there is anice parser on from http://lua-users.org/wiki/LpegRecipes (by
+-- there is a nice parser on from http://lua-users.org/wiki/LpegRecipes (by
-- Patrick Donnelly) but lua crashes when I apply functions to some of the
-- matches
@@ -32,6 +43,10 @@ That way, the libraries included in the runner will be used.
-- begin library merge
-- end library merge
+local gsub, find, sub = string.gsub, string.find, string.sub
+local splitstring, emptystring = string.split, string.is_empty
+local concat = table.concat
+
--[[
Just a demo comment line. We will handle such multiline comments but
only when they start and end at the beginning of a line. More rich
@@ -57,14 +72,14 @@ function ldx.load(filename)
local i, j, t = 0, 0, { }
while true do
local comment, ni
- ni, j, comment = data:find(expr, j)
+ ni, j, comment = find(data, expr, j)
if not ni then break end
- t[#t+1] = { code = data:sub(i, ni-1) }
+ t[#t+1] = { code = sub(data, i, ni-1) }
t[#t+1] = { comment = comment }
i = j + 1
end
- local str = data:sub(i, #data)
- str = str:gsub("^%s*(.-)%s*$", "%1")
+ local str = sub(data, i, #data)
+ str = gsub(str, "^%s*(.-)%s*$", "%1")
if #str > 0 then
t[#t+1] = { code = str }
end
@@ -115,7 +130,7 @@ construction.
do
local e = { [">"] = "&gt;", ["<"] = "&lt;", ["&"] = "&amp;" }
function ldx.escape(str)
- return (str:gsub("([><&])",e))
+ return (gsub(str, "([><&])",e))
end
end
@@ -135,25 +150,25 @@ function ldx.enhance(data) -- i need to use lpeg and then we can properly autoin
local v = data[k]
if v.code then
local dqs, sqs, com, cmt, cod = { }, { }, { }, { }, e(v.code)
- cod = cod:gsub('\\"', "##d##")
- cod = cod:gsub("\\'", "##s##")
- cod = cod:gsub("%-%-%[%[.-%]%]%-%-", function(s)
+ cod = gsub(cod, '\\"', "##d##")
+ cod = gsub(cod, "\\'", "##s##")
+ cod = gsub(cod, "%-%-%[%[.-%]%]%-%-", function(s)
cmt[#cmt+1] = s
return "<l<<<".. #cmt ..">>>l>"
end)
- cod = cod:gsub("%-%-([^\n]*)", function(s)
+ cod = gsub(cod, "%-%-([^\n]*)", function(s)
com[#com+1] = s
return "<c<<<".. #com ..">>>c>"
end)
- cod = cod:gsub("(%b\"\")", function(s)
- dqs[#dqs+1] = s:sub(2,-2) or ""
+ cod = gsub(cod, "(%b\"\")", function(s)
+ dqs[#dqs+1] = sub(s,2,-2) or ""
return "<d<<<".. #dqs ..">>>d>"
end)
- cod = cod:gsub("(%b\'\')", function(s)
- sqs[#sqs+1] = s:sub(2,-2) or ""
+ cod = gsub(cod, "(%b\'\')", function(s)
+ sqs[#sqs+1] = sub(s,2,-2) or ""
return "<s<<<".. #sqs ..">>>s>"
end)
- cod = cod:gsub("(%a+)",function(key)
+ cod = gsub(cod, "(%a+)",function(key)
local class = ldx.keywords.reserved[key]
if class then
return "<key class='" .. class .. "'>" .. key .. "</key>"
@@ -161,41 +176,41 @@ function ldx.enhance(data) -- i need to use lpeg and then we can properly autoin
return key
end
end)
- cod = cod:gsub("<s<<<(%d+)>>>s>", function(s)
+ cod = gsub(cod, "<s<<<(%d+)>>>s>", function(s)
return "<sqs>" .. sqs[tonumber(s)] .. "</sqs>"
end)
- cod = cod:gsub("<d<<<(%d+)>>>d>", function(s)
+ cod = gsub(cod, "<d<<<(%d+)>>>d>", function(s)
return "<dqs>" .. dqs[tonumber(s)] .. "</dqs>"
end)
- cod = cod:gsub("<c<<<(%d+)>>>c>", function(s)
+ cod = gsub(cod, "<c<<<(%d+)>>>c>", function(s)
return "<com>" .. com[tonumber(s)] .. "</com>"
end)
- cod = cod:gsub("<l<<<(%d+)>>>l>", function(s)
+ cod = gsub(cod, "<l<<<(%d+)>>>l>", function(s)
return cmt[tonumber(s)]
end)
- cod = cod:gsub("##d##", "\\\"")
- cod = cod:gsub("##s##", "\\\'")
+ cod = gsub(cod, "##d##", "\\\"")
+ cod = gsub(cod, "##s##", "\\\'")
if ldx.make_index then
- local lines = cod:split("\n")
+ local lines = splitstring(cod,"\n")
local f = "(<key class='1'>function</key>)%s+([%w%.]+)%s*%("
for k=1,#lines do
local v = lines[k]
-- functies
- v = v:gsub(f,function(key, str)
+ v = gsub(v,f,function(key, str)
return "<function>" .. str .. "</function>("
end)
-- variables
- v = v:gsub("^([%w][%w%,%s]-)(=[^=])",function(str, rest)
- local t = string.split(str, ",%s*")
+ v = gsub(v,"^([%w][%w%,%s]-)(=[^=])",function(str, rest)
+ local t = splitstring(str,",%s*")
for k=1,#t do
t[k] = "<variable>" .. t[k] .. "</variable>"
end
- return table.concat(t,", ") .. rest
+ return concat(t,", ") .. rest
end)
-- so far
lines[k] = v
end
- v.code = table.concat(lines,"\n")
+ v.code = concat(lines,"\n")
else
v.code = cod
end
@@ -217,30 +232,30 @@ function ldx.as_xml(data) -- ldx: not needed
t[#t+1] = "\n<document xmlns:ldx='http://www.pragma-ade.com/schemas/ldx.rng' xmlns='http://www.pragma-ade.com/schemas/ldx.rng'>\n"
for k=1,#data do
local v = data[k]
- if v.code and not v.code:is_empty() then
+ if v.code and not emptystring(v.code) then
t[#t+1] = "\n<code>\n"
- local split = v.code:split("\n")
+ local split = splitstring(v.code,"\n")
for k=1,#split do -- make this faster
local v = split[k]
- local a, b = v:find("^(%s+)")
- if v then v = v:gsub("[\n\r ]+$","") end
+ local a, b = find(v,"^(%s+)")
+ if v then v = gsub(v,"[\n\r ]+$","") end
if a and b then
- v = v:sub(b+1,#v)
+ v = sub(v,b+1,#v)
if cmode then
t[#t+1] = "<line comment='yes' n='" .. b .. "'>" .. v .. "</line>\n"
else
t[#t+1] = "<line n='" .. b .. "'>" .. v .. "</line>\n"
end
- elseif v:is_empty() then
+ elseif emptystring(v) then
if cmode then
t[#t+1] = "<line comment='yes'/>\n"
else
t[#t+1] = "<line/>\n"
end
- elseif v:find("^%-%-%[%[") then
+ elseif find(v,"^%-%-%[%[") then
t[#t+1] = "<line comment='yes'>" .. v .. "</line>\n"
cmode= true
- elseif v:find("^%]%]%-%-") then
+ elseif find(v,"^%]%]%-%-") then
t[#t+1] = "<line comment='yes'>" .. v .. "</line>\n"
cmode= false
elseif cmode then
@@ -257,7 +272,7 @@ function ldx.as_xml(data) -- ldx: not needed
end
end
t[#t+1] = "\n</document>\n"
- return table.concat(t,"")
+ return concat(t,"")
end
--[[ldx--
diff --git a/Master/texmf-dist/tex/context/base/x-ldx.mkiv b/Master/texmf-dist/tex/context/base/x-ldx.mkiv
index bf9bdf71a74..4f4da5acb77 100644
--- a/Master/texmf-dist/tex/context/base/x-ldx.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-ldx.mkiv
@@ -1,3 +1,16 @@
+%D \module
+%D [ file=x-ldx,
+%D version=2008.06.03,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Lua Source Pretty Printing,
+%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.
+
\setupxml[default=hidden]
\usemodule[x][mathml]
diff --git a/Master/texmf-dist/tex/context/base/x-mathml.lua b/Master/texmf-dist/tex/context/base/x-mathml.lua
index 434aefc553a..30e77019028 100644
--- a/Master/texmf-dist/tex/context/base/x-mathml.lua
+++ b/Master/texmf-dist/tex/context/base/x-mathml.lua
@@ -6,13 +6,15 @@ if not modules then modules = { } end modules ['x-mathml'] = {
license = "see context related readme files"
}
+-- This needs an upgrade to the latest greatest mechanisms.
+
local type, next = type, next
local utf = unicode.utf8
-local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
local format, lower, find, gsub = string.format, string.lower, string.find, string.gsub
+local strip = string.strip
local utfchar, utffind, utfgmatch, utfgsub = utf.char, utf.find, utf.gmatch, utf.gsub
local xmlsprint, xmlcprint, xmltext, xmlcontent = xml.sprint, xml.cprint, xml.text, xml.content
-local lxmltext, getid = lxml.text, lxml.getid
+local getid = lxml.getid
local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
local lpegmatch = lpeg.match
@@ -22,10 +24,12 @@ lxml.mathml = mathml -- for the moment
-- an alternative is to remap to private codes, where we can have
-- different properties .. to be done; this will move and become
--- generic
+-- generic; we can then make the private ones active in math mode
-- todo: handle opening/closing mo's here ... presentation mml is such a mess ...
+characters.registerentities()
+
local doublebar = utfchar(0x2016)
local n_replacements = {
@@ -52,6 +56,8 @@ local r_replacements = { -- in main table
[doublebar] = "\\mmlrightdelimiter\\Vert",
}
+-- todo: play with asciimode and avoid mmlchar
+
local o_replacements = { -- in main table
["@l"] = "\\mmlleftdelimiter.",
["@r"] = "\\mmlrightdelimiter.",
@@ -81,6 +87,8 @@ local o_replacements = { -- in main table
}
+--~ languages.data.labels.functions
+
local i_replacements = {
["sin"] = "\\mathopnolimits{sin}",
["cos"] = "\\mathopnolimits{cos}",
@@ -234,6 +242,7 @@ local csymbols = {
divergence = "divergence",
grad = "grad",
curl = "curl",
+ laplacian = "laplacian",
Laplacian = "laplacian",
},
calculus1 = {
@@ -448,38 +457,50 @@ function xml.functions.remapopenmath(e)
end
function mathml.checked_operator(str)
- texsprint(ctxcatcodes,(utfgsub(str,".",o_replacements)))
+ str = utfgsub(str,".",o_replacements)
+ context(str)
end
function mathml.stripped(str)
- tex.sprint(ctxcatcodes,str:strip())
+ context(strip(str))
end
-function characters.remapentity(chr,slot) -- brrrrrr
- texsprint(format("{\\catcode%s=13\\xdef%s{\\string%s}}",slot,utfchar(slot),chr))
+function characters.remapentity(chr,slot) -- Brrrrrr, this will be replaced!
+ context("{\\catcode%s=13\\xdef%s{\\string%s}}",slot,utfchar(slot),chr)
end
function mathml.mn(id,pattern)
-- maybe at some point we need to interpret the number, but
-- currently we assume an upright font
local str = xmlcontent(getid(id)) or ""
- str = gsub(str,"(%s+)",utfchar(0x205F)) -- medspace e.g.: twenty one (nbsp is not seen)
- texsprint(ctxcatcodes,(gsub(str,".",n_replacements)))
+ local rep = gsub(str,"&.-;","")
+ local rep = gsub(rep,"(%s+)",utfchar(0x205F)) -- medspace e.g.: twenty one (nbsp is not seen)
+ local rep = gsub(rep,".",n_replacements)
+ context.mn(rep)
end
function mathml.mo(id)
local str = xmlcontent(getid(id)) or ""
- texsprint(ctxcatcodes,(utfgsub(str,".",o_replacements)))
+ local rep = gsub(str,"&.-;","")
+ local rep = utfgsub(rep,".",o_replacements)
+ context(rep)
+ -- context.mo(rep) -- fails with \left etc
end
function mathml.mi(id)
- local str = xmlcontent(getid(id)) or ""
- -- str = gsub(str,"^%s*(.-)%s*$","%1")
- local rep = i_replacements[str]
- if rep then
- texsprint(ctxcatcodes,rep)
+ local e = getid(id)
+ local str = e.dt
+ if type(str) == "string" then -- we need a helper for this in the xml namespace ... xml.type(e)
+ -- local str = xmlcontent(e) or ""
+ local str = gsub(str,"&.-;","") -- needed?
+ local rep = i_replacements[str]
+ if not rep then
+ rep = gsub(str,".",i_replacements)
+ end
+ context(rep)
+ -- context.mi(rep)
else
- texsprint(ctxcatcodes,(gsub(str,".",i_replacements)))
+ context.xmlflush(id) -- xmlsprint or so
end
end
@@ -487,14 +508,14 @@ function mathml.mfenced(id) -- multiple separators
id = getid(id)
local left, right, separators = id.at.open or "(", id.at.close or ")", id.at.separators or ","
local l, r = l_replacements[left], r_replacements[right]
- texsprint(ctxcatcodes,"\\enabledelimiter")
+ context.enabledelimiter()
if l then
- texsprint(ctxcatcodes,l_replacements[left] or o_replacements[left] or "")
+ context(l_replacements[left] or o_replacements[left] or "")
else
- texsprint(ctxcatcodes,o_replacements["@l"])
- texsprint(ctxcatcodes,left)
+ context(o_replacements["@l"])
+ context(left)
end
- texsprint(ctxcatcodes,"\\disabledelimiter")
+ context.disabledelimiter()
local collected = lxml.filter(id,"/*") -- check the *
if collected then
local n = #collected
@@ -502,7 +523,6 @@ function mathml.mfenced(id) -- multiple separators
-- skip
elseif n == 1 then
xmlsprint(collected[1]) -- to be checked
---~ lxml.all(id,"/*")
else
local t = { }
for s in utfgmatch(separators,"[^%s]") do
@@ -521,37 +541,53 @@ function mathml.mfenced(id) -- multiple separators
elseif m == "}" then
m = "\\}"
end
- texsprint(ctxcatcodes,m)
+ context(m)
end
end
end
end
- texsprint(ctxcatcodes,"\\enabledelimiter")
+ context.enabledelimiter()
if r then
- texsprint(ctxcatcodes,r_replacements[right] or o_replacements[right] or "")
+ context(r_replacements[right] or o_replacements[right] or "")
else
- texsprint(ctxcatcodes,right)
- texsprint(ctxcatcodes,o_replacements["@r"])
+ context(right)
+ context(o_replacements["@r"])
end
- texsprint(ctxcatcodes,"\\disabledelimiter")
+ context.disabledelimiter()
end
+--~ local function flush(e,tag,toggle)
+--~ if toggle then
+--~ context("^{")
+--~ else
+--~ context("_{")
+--~ end
+--~ if tag == "none" then
+--~ context("{}")
+--~ else
+--~ xmlsprint(e.dt)
+--~ end
+--~ if not toggle then
+--~ context("}")
+--~ else
+--~ context("}{}")
+--~ end
+--~ return not toggle
+--~ end
+
local function flush(e,tag,toggle)
- -- texsprint(ctxcatcodes,(toggle and "^{") or "_{")
- if toggle then
- texsprint(ctxcatcodes,"^{")
- else
- texsprint(ctxcatcodes,"_{")
- end
if tag == "none" then
- texsprint(ctxcatcodes,"{}")
- else
+ -- if not toggle then
+ context("{}") -- {} starts a new ^_ set
+ -- end
+ elseif toggle then
+ context("^{")
xmlsprint(e.dt)
- end
- if not toggle then
- texsprint(ctxcatcodes,"}")
+ context("}{}") -- {} starts a new ^_ set
else
- texsprint(ctxcatcodes,"}{}")
+ context("_{")
+ xmlsprint(e.dt)
+ context("}")
end
return not toggle
end
@@ -561,7 +597,7 @@ function mathml.mmultiscripts(id)
for e in lxml.collected(id,"/*") do
local tag = e.tg
if tag == "mprescripts" then
- texsprint(ctxcatcodes,"{}")
+ context("{}")
done = true
elseif done then
toggle = flush(e,tag,toggle)
@@ -610,6 +646,7 @@ function mathml.mcolumn(root)
local tag = e.tg
if tag == "mi" or tag == "mn" or tag == "mo" or tag == "mtext" then
local str = xmltext(e)
+str = gsub(str,"&.-;","")
for s in utfcharacters(str) do -- utf.gmatch(str,".") btw, the gmatch was bugged
m[#m+1] = { tag, s }
end
@@ -624,8 +661,8 @@ function mathml.mcolumn(root)
for s in utfcharacters(str) do -- utf.gmatch(str,".") btw, the gmatch was bugged
m[#m+1] = { tag, s }
end
- elseif tag == "mline" then
- m[#m+1] = { tag, e }
+ -- elseif tag == "mline" then
+ -- m[#m+1] = { tag, e }
end
end
for e in lxml.collected(root,"/*") do
@@ -640,7 +677,9 @@ function mathml.mcolumn(root)
collect(m,e)
end
end
- tex.sprint(ctxcatcodes,"\\halign\\bgroup\\hss$#$&$#$\\cr")
+ context.halign()
+ context.bgroup()
+ context([[\hss\startimath\alignmark\stopimath\aligntab\startimath\alignmark\stopimath\cr]])
for i=1,#matrix do
local m = matrix[i]
local mline = true
@@ -651,12 +690,14 @@ function mathml.mcolumn(root)
end
end
if mline then
- tex.sprint(ctxcatcodes,"\\noalign{\\obeydepth\\nointerlineskip}")
+ context.noalign([[\obeydepth\nointerlineskip]])
end
for j=1,#m do
local mm = m[j]
local tag, chr = mm[1], mm[2]
if tag == "mline" then
+ -- This code is under construction ... I need some real motivation
+ -- to deal with this kind of crap.
--~ local n, p = true, true
--~ for c=1,#matrix do
--~ local mc = matrix[c][j]
@@ -687,17 +728,17 @@ function mathml.mcolumn(root)
chr = "\\mmlmcolumndigitspace" -- utfchar(0x2007)
end
if j == numbers + 1 then
- tex.sprint(ctxcatcodes,"&")
+ context("\\aligntab")
end
local nchr = n_replacements[chr]
- tex.sprint(ctxcatcodes,nchr or chr)
+ context(nchr or chr)
end
- tex.sprint(ctxcatcodes,"\\crcr")
+ context.crcr()
end
- tex.sprint(ctxcatcodes,"\\egroup")
+ context.egroup()
end
-local spacesplitter = lpeg.Ct(lpeg.splitat(" "))
+local spacesplitter = lpeg.tsplitat(" ")
function mathml.mtable(root)
-- todo: align, rowspacing, columnspacing, rowlines, columnlines
@@ -712,11 +753,9 @@ function mathml.mtable(root)
local framespacing = at.framespacing or "0pt"
local framespacing = at.framespacing or "-\\ruledlinewidth" -- make this an option
- texsprint(ctxcatcodes, format("\\bTABLE[frame=%s,offset=%s]",frametypes[frame or "none"] or "off",framespacing))
---~ context.bTABLE { frame = frametypes[frame or "none"] or "off", offset = framespacing }
+ context.bTABLE { frame = frametypes[frame or "none"] or "off", offset = framespacing }
for e in lxml.collected(root,"/(mml:mtr|mml:mlabeledtr)") do
- texsprint(ctxcatcodes,"\\bTR")
---~ context.bTR()
+ context.bTR()
local at = e.at
local col = 0
local rfr = at.frame or (frames and frames [#frames])
@@ -733,28 +772,23 @@ function mathml.mtable(root)
local cra = rowalignments [at.rowalign or (rowaligns and rowaligns [col]) or rra or "center"] or "lohi"
local cca = columnalignments[at.columnalign or (columnaligns and columnaligns[col]) or rca or "center"] or "middle"
local cfr = frametypes [at.frame or (frames and frames [col]) or rfr or "none" ] or "off"
- texsprint(ctxcatcodes,format("\\bTD[align={%s,%s},frame=%s,nx=%s,ny=%s]$\\ignorespaces",cra,cca,cfr,columnspan,rowspan))
---~ texfprint("\\bTD[align={%s,%s},frame=%s,nx=%s,ny=%s]$\\ignorespaces",cra,cca,cfr,columnspan,rowspan)
---~ context.bTD { align = format("{%s,%s}",cra,cca), frame = cfr, nx = columnspan, ny = rowspan }
---~ context.bmath()
---~ context.ignorespaces()
+ context.bTD { align = format("{%s,%s}",cra,cca), frame = cfr, nx = columnspan, ny = rowspan }
+ context.startimath()
+ context.ignorespaces()
xmlcprint(e)
- texsprint(ctxcatcodes,"\\removeunwantedspaces$\\eTD") -- $
---~ context.emath()
---~ context.removeunwantedspaces()
---~ context.eTD()
+ context.stopimath()
+ context.removeunwantedspaces()
+ context.eTD()
end
end
---~ if e.tg == "mlabeledtr" then
---~ texsprint(ctxcatcodes,"\\bTD")
---~ xmlcprint(xml.first(e,"/!mml:mtd"))
---~ texsprint(ctxcatcodes,"\\eTD")
---~ end
- texsprint(ctxcatcodes,"\\eTR")
---~ context.eTR()
+ -- if e.tg == "mlabeledtr" then
+ -- context.bTD()
+ -- xmlcprint(xml.first(e,"/!mml:mtd"))
+ -- context.eTD()
+ -- end
+ context.eTR()
end
- texsprint(ctxcatcodes, "\\eTABLE")
---~ context.eTABLE()
+ context.eTABLE()
end
function mathml.csymbol(root)
@@ -764,15 +798,34 @@ function mathml.csymbol(root)
local hash = url.hashed(lower(at.definitionUrl or ""))
local full = hash.original or ""
local base = hash.path or ""
- local text = string.strip(lxmltext(root))
---~ texsprint(ctxcatcodes,format("\\mmlapplycsymbol{%s}{%s}{%s}{%s}",full,base,encoding,text))
- texsprint(ctxcatcodes,"\\mmlapplycsymbol{",full,"}{",base,"}{",encoding,"}{",text,"}")
+ local text = strip(xmltext(root) or "")
+ context.mmlapplycsymbol(full,base,encoding,text)
end
function mathml.menclosepattern(root)
root = getid(root)
local a = root.at.notation
if a and a ~= "" then
- texsprint("mml:enclose:",gsub(a," +",",mml:enclose:"))
+ context("mml:enclose:",(gsub(a," +",",mml:enclose:")))
+ end
+end
+
+function xml.is_element(e,name)
+ return type(e) == "table" and (not name or e.tg == name)
+end
+
+function mathml.cpolar_a(root)
+ root = getid(root)
+ local dt = root.dt
+ context.mathopnolimits("Polar")
+ context.left(false,"(")
+ for k=1,#dt do
+ local dk = dt[k]
+ if xml.is_element(dk,"sep") then
+ context(",")
+ else
+ xmlsprint(dk)
+ end
end
+ context.right(false,")")
end
diff --git a/Master/texmf-dist/tex/context/base/x-mathml.mkii b/Master/texmf-dist/tex/context/base/x-mathml.mkii
index 101f65c5b6f..ccb9fa05463 100644
--- a/Master/texmf-dist/tex/context/base/x-mathml.mkii
+++ b/Master/texmf-dist/tex/context/base/x-mathml.mkii
@@ -5,7 +5,7 @@
%D subtitle=Loading \MATHML\ Filters,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-mathml.mkiv b/Master/texmf-dist/tex/context/base/x-mathml.mkiv
index 44e2b7432f5..f64fdbc74bc 100644
--- a/Master/texmf-dist/tex/context/base/x-mathml.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-mathml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Loading \MATHML\ Filters,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
@@ -13,12 +13,18 @@
% \xmlfilter{#1}{/*/name()} -> \xmltag
-% This module is under construction and will be cleaned up.
+% This module is under construction and will be cleaned up. We use a funny mix of
+% xml, tex and lua. I could rewrite the lot but it also shows how context evolves.
+%
+% no m:text strip (needs checking, maybe nbsp is mandate
\writestatus{loading}{ConTeXt XML Macros / MathML Renderer}
\unprotect
+\usemodule[x][calcmath]
+%usemodule[x][asciimath]
+
\startmodule [mathml]
\registerctxluafile{x-mathml}{}
@@ -31,8 +37,8 @@
\xmlfilter {\xmldocument} {mml:bind/function(remapmmlbind)}
\xmlfilter {\xmldocument} {mml:csymbol/function(remapmmlcsymbol)}
\xmlsetsetup{\xmldocument} {mml:*} {mml:*}
- \xmlsetsetup{\xmldocument} {mml:apply/mml:apply/mml:inverse/../../..} {mml:apply:inverse}
- \xmlstrip {\xmldocument} {(mml:mi|mml:mo|mml:mn|mml:mtext|mml:csymbol)}
+ \xmlsetsetup{\xmldocument} {mml:apply/mml:apply/mml:inverse/../..} {mml:apply:inverse}
+ \xmlstrip {\xmldocument} {(mml:mi|mml:mo|mml:mn|mml:csymbol)}
\stopxmlsetups
\xmlregisterns{omt}{openmath}
@@ -40,15 +46,29 @@
\xmlregistersetup{xml:mml:define}
-\unexpanded\def\setupMMLappearance[#1]{\dodoubleargument\getparameters[@@MML#1]}
-
\def\MMLhack{\let\MMLpar\par \let\par\relax \everyvbox{\let\par\MMLpar}}
-\xmlmapvalue {mml:math:mode} {display} {\displaymathematics}
-\xmlmapvalue {mml:math:mode} {inline} {\inlinemathematics}
+\xmlmapvalue {mml:math:mode} {display} {\displaymathematics} % we had this already
+\xmlmapvalue {mml:math:mode} {inline} {\inlinemathematics }
+
+\xmlmapvalue {mml:math:display} {block} {\displaymathematics} % before this showed up
+\xmlmapvalue {mml:math:display} {inline} {\inlinemathematics }
+
+\xmlmapvalue {mml:math:dir} {ltr} {\setfalse\c_math_right_to_left\math_basics_synchronize_direction}
+\xmlmapvalue {mml:math:dir} {rtl} {\settrue \c_math_right_to_left\math_basics_synchronize_direction}
\startxmlsetups mml:math
- \xmlval{mml:math:mode}{\xmlatt{#1}{mode}}{\automathematics}{\MMLhack\xmlflush{#1}}
+ \begingroup
+ \xmlval {mml:math:dir} {\xmlatt{#1}{dir}} {}
+ \xmlval {mml:math:display} {\xmlatt{#1}{display}} {
+ \xmlval {mml:math:mode} {\xmlatt{#1}{mode}} {
+ \automathematics
+ }
+ }
+ {
+ \MMLhack\xmlflush{#1}
+ }
+ \endgroup
\stopxmlsetups
\startxmlsetups mml:imath
@@ -106,7 +126,7 @@
\def\widevec#1%
{\vbox{\mathsurround\zeropoint\ialign{##\crcr
\rightarrowfill\crcr\noalign{\nointerlineskip}%
- $\hfil\displaystyle{#1}\hfil$\crcr}}}
+ \startimath\hfil\displaystyle{#1}\hfil\stopimath\crcr}}}
%D The rendering macros:
@@ -160,7 +180,11 @@
%D \type {apply}.
\def\MMLmathinner
- {\ifinner \expandafter \firstofoneargument \else \expandafter \mathinner \fi}
+ {\ifinner
+ \expandafter\firstofoneargument
+ \else
+ \expandafter\mathinner
+ \fi}
%D Auxiliary MathML macros: (to be generalized)
@@ -257,6 +281,8 @@
%D version 3 the following definitions may be sub optimal or
%D more complex than actually needed.
+%D We will more more to lua ...
+
% simple version
\newcount\@MMLlevel \def\MMLcreset{\@MMLlevel\zerocount}
@@ -309,11 +335,11 @@
% \MMLdoR
% } {
\edef\mmlapplyaction{\xmlfilter{#1}{/*/name()}}
- \doifsetupselse {mml:apply:\mmlapplyaction} {
- \xmlsetup{#1}{mml:apply:\mmlapplyaction}
+ \doifsetupselse {mml:apply:mml:\mmlapplyaction} {
+ \xmlsetup{#1}{mml:apply:mml:\mmlapplyaction}
} {
% \MMLdoL
- \xmlsetup{#1}{\xmlfilter{#1}{/*/name()}}
+ \xmlsetup{#1}{mml:\xmlfilter{#1}{/*/name()}}
% \MMLdoR
}
% }
@@ -328,15 +354,15 @@
\stopxmlsetups
\startxmlsetups mml:apply:mml:fn
- \xmldoifelse {#1} {/mml:ci} {
- \edef\mmlfnci{\xmlcontent{#1}{/mml:ci}}%
- \doifsetupselse{mml:fn:\mmlfnci} { % was mmc:fn:...
- \xmlsetup{#1}{mml:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
+ \xmldoifelse {#1} {/mml:fn/mml:ci} {
+ \edef\mmlfnci{\xmlstripped{#1}{/mml:fn/mml:ci}}% was xmlcontent
+ \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:...
+ \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
} {
\MMLcreset
\MMLdoL
\mmlfirst{#1}
- \ifnum\xmlcount{#1}>\plusone
+ \ifnum\xmlcount{#1}{/*}>\plusone
\negthinspace % not enough
\left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right)
\fi
@@ -351,12 +377,12 @@
\stopxmlsetups
\startxmlsetups mml:apply:mml:csymbol
- \xmlsetup{#1}{mml:csymbol} % \MMLdoL/MMLdoR to be handled in plugin
+ \xmlsetup{#1}{mml:csymbol}% \MMLdoL/MMLdoR to be handled in plugin
\stopxmlsetups
\startxmlsetups mml:apply:mml:ci
\xmlfirst{#1}{/mml:ci}
- \ifnum\xmlcount{#1}>\plusone
+ \ifnum\xmlcount{#1}{/*}>\plusone
\left(\MMLcreset\xmlconcatrange{#1}{/*}{2}{}{\MMLseparator,}\right)
\fi
\stopxmlsetups
@@ -369,22 +395,25 @@
% fn
-\startxmlsetups mmc:fn:\utfchar{"00B1} % plusminus ±
- \ifnum\xmlcount{#1}>\plustwo
- \MMLcreset
- \left(\xmlconcat{#1}{/*}{2}{}{\mmlfirst{#1}}\right)
- \else
- \mmlfirst{#1}
- \fi
+% plusminus ±
+
+\startxmlsetups mmc:fn:\utfchar{"00B1}
+ \MMLdoL
+ \xmlconcat{#1}{/[position()>1]}{\utfchar{"00B1}}
+ \MMLdoR
\stopxmlsetups
-\startxmlsetups mmc:fn:\utfchar{"2213} % minusplus
- \xmlsetup{#1}{mmc:fn:plusminus}
+% minusplus
+
+\startxmlsetups mmc:fn:\utfchar{"2213}
+ \MMLdoL
+ \xmlconcat{#1}{/[position()>1]}{\utfchar{"2213}}
+ \MMLdoR
\stopxmlsetups
\startxmlsetups mmc:fn
\begingroup
- \edef\mmlnoffn{\xmlcount{#1}}
+ \edef\mmlnoffn{\xmlcount{#1}{/*}}
\ifnum\mmlnoffn>\plustwo
\def\MMCfnleft {\left(}
\def\MMCfnright{\right)}
@@ -393,9 +422,9 @@
\let\MMCfnright\relax
\fi
\xmldoifelse {#1} {/mml:ci} { % first
- \edef\mmlfnci{\xmlcontent{#1}{/mml:ci}}%
- \doifsetupselse{mml:fn:\mmlfnci} { % was mmc:fn:...
- \xmlsetup{#1}{mml:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
+ \edef\mmlfnci{\xmltext{#1}{/mml:ci}}% was xmlcontent
+ \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:...
+ \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
} {
\MMLcreset
\mmlfirst{#1}
@@ -424,13 +453,13 @@
\startxmlsetups mmc:fn:apply % where used?
\xmldoifelse {#1} {/mml:ci} { % first
- \edef\mmlfnci{\xmlcontent{#1}{/mml:ci}}%
- \doifsetupselse{mml:fn:\mmlfnci} { % was mmc:fn:...
- \xmlsetup{#1}{mml:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
+ \edef\mmlfnci{\xmltext{#1}{/mml:ci}}% was xmlcontent
+ \doifsetupselse{mmc:fn:\mmlfnci} { % was mmc:fn:...
+ \xmlsetup{#1}{mmc:fn:\mmlfnci} % \MMLdoL/MMLdoR to be handled in plugin
} {
\MMLcreset
\mmlfirst{#1}
- \ifnum\xmlcount{#1}>\plusone
+ \ifnum\xmlcount{#1}{/*}>\plusone
\negthinspace
\left(\MMLcreset\xmlconcat{#1}{2}{}{\MMLseparator,}\right)
\fi
@@ -446,11 +475,14 @@
%D the open math extension module).
% http://www.publishers.com/somename
+%
+% called at the lua end
\starttexdefinition mmlapplycsymbol #1#2#3#4
% #1=full url, #2=name, #3=encoding, #4=text
\doifelse {#3} {text} {
- {\mr #4}
+% {\mr #4}
+ \text{#4}
} {
\doifsetupselse {mml:csymbol:#1} {
% full url
@@ -488,7 +520,7 @@
\startxmlsetups mml:ci \xmlcommand{#1}{/}{mml:ci:\xmlattdef{#1}{type}{default}} \stopxmlsetups
\startxmlsetups mml:cn \xmlcommand{#1}{/}{mml:cn:\xmlattdef{#1}{type}{default}} \stopxmlsetups
-% helpers cn
+% helpers cn / todo: \mn{...}
\startxmlsetups mml:cn:default
\mathopnolimits{\xmlflush{#1}}
@@ -551,7 +583,7 @@
\MMLcCNbasedata{\xmlflush{#1}}
} {
\MMLcCNbasedata{\xmlflush{#1}}\normalsubscript{
- \hbox {$
+ \hbox {\startimath
\mr
\scriptscriptstyle
\processaction
@@ -559,7 +591,7 @@
[\v!characters=>\MMLcCNbasestring BODH,
\v!text=>\MMLcCNbasestring{BIN}{OCT}{DEC}{HEX},
\s!unknown=>\mmlintegerbase]
- $}
+ \stopimath}
}
}
\fi
@@ -580,8 +612,7 @@
\stopxmlsetups
\startxmlsetups mml:cn:polar:a
- \mathopnolimits{Polar}% ? ? ?
- \left(\xmlsnippet{#1}{1},\xmlsnippet{#1}{3}\right)
+ \ctxmodulemathml{cpolar_a("#1")}
\stopxmlsetups
\startxmlsetups mml:cn:polar:b
@@ -661,16 +692,16 @@
% when empty element, then it's an apply
\startxmlsetups mml:interval
- \xmldoifelseempty {#1} {} {
- % #1 == interval
- \let\mmlintervalfirst \mmlfirst
- \let\mmlintervalsecond\mmlsecond
- \xmlsetup{#1}{mml:interval:\xmlattdef{#1}{closure}{closed}}
- } {
+ \doifelse {\xmltag{#1}} {apply} {
% #1 == apply
\let\mmlintervalfirst \mmlsecond
\let\mmlintervalsecond\mmlthird
\xmlsetup{#1}{mml:interval:\xmlattributedef{#1}{/mml:interval}{closure}{closed}}
+ } {
+ % #1 == interval
+ \let\mmlintervalfirst \mmlfirst
+ \let\mmlintervalsecond\mmlsecond
+ \xmlsetup{#1}{mml:interval:\xmlattdef{#1}{closure}{closed}}
}
\stopxmlsetups
@@ -708,7 +739,7 @@
\startxmlsetups mml:apply:inverse
\settrue\xmlinversefunction
- \xmlsetup{#1}{\xmlfilter{#1}{/mml:apply/*/name(1)}}
+ \xmlsetup{#1}{mml:\xmlfilter{#1}{/mml:apply/*[2]/name()}}
\stopxmlsetups
% condition
@@ -739,7 +770,7 @@
\doif \MMLdeclarestate \v!start {
\mathopnolimits{declare}
\mmlfirst{#1}
- \ifnum\xmlcount{#1}>\plusone
+ \ifnum\xmlcount{#1}{/*}>\plusone
\thickspace
\mathopnolimits{as}
\thickspace
@@ -1109,15 +1140,15 @@
\setupMMLappearance[relation][\c!align=\v!no]
-\xmlmapvalue {mml:relation} {mml:eq} {=}
-\xmlmapvalue {mml:relation} {mml:neq} {\neq}
-\xmlmapvalue {mml:relation} {mml:gt} {>}
-\xmlmapvalue {mml:relation} {mml:lt} {<}
-\xmlmapvalue {mml:relation} {mml:geq} {\geq}
-\xmlmapvalue {mml:relation} {mml:leq} {\leq}
-\xmlmapvalue {mml:relation} {mml:equivalent} {\equiv}
-\xmlmapvalue {mml:relation} {mml:approx} {\approx}
-\xmlmapvalue {mml:relation} {mml:factorof} {\mid}
+\xmlmapvalue {mml:relation} {eq} {=}
+\xmlmapvalue {mml:relation} {neq} {\neq}
+\xmlmapvalue {mml:relation} {gt} {>}
+\xmlmapvalue {mml:relation} {lt} {<}
+\xmlmapvalue {mml:relation} {geq} {\geq}
+\xmlmapvalue {mml:relation} {leq} {\leq}
+\xmlmapvalue {mml:relation} {equivalent} {\equiv}
+\xmlmapvalue {mml:relation} {approx} {\approx}
+\xmlmapvalue {mml:relation} {factorof} {\mid}
\startxmlsetups mml:eq \xmlsetup{#1}{mml:relation} \stopxmlsetups
\startxmlsetups mml:neq \xmlsetup{#1}{mml:relation} \stopxmlsetups
@@ -1135,28 +1166,28 @@
\stopxmlsetups
\startxmlsetups mml:relation:default
- \xmlconcatrange{#1}{/*}{2}{}{\xmlval{mml:relation}{\mmlapplyaction}{?}}
+ \xmlconcatrange{#1}{/*}{2}{}{\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}}
\stopxmlsetups
\startxmlsetups mml:relation:last
\eqalign {
- \xmlconcatrange{#1}{/*}{2}{-2}{&\xmlval{mml:relation}{\mmlapplyaction}{?}\crcr}
- \mmlprelast{#1}&\xmlval{mml:relation}{\mmlapplyaction}{?}{}\mmllast{#1}
+ \xmlconcatrange{#1}{/*}{2}{-2}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr}
+ \mmlprelast{#1}&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}\mmllast{#1}
}
\stopxmlsetups
\startxmlsetups mml:relation:first
\eqalign {
- \mmlsecond{#1}\xmlval{mml:relation}{\mmlapplyaction}{?}{}
- &\xmlconcatrange{#1}{/*}{3}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{?}{}&}
+ \mmlsecond{#1}\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}
+ &\xmlconcatrange{#1}{/*}{3}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&}
}
\stopxmlsetups
\startxmlsetups mml:relation:left
\eqalign {
- \xmlconcatrange{#1}{/*}{2}{}{&\xmlval{mml:relation}{\mmlapplyaction}{?}\crcr}
+ \xmlconcatrange{#1}{/*}{2}{}{&\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}\crcr}
}
\stopxmlsetups
\startxmlsetups mml:relation:right
\eqalign {
- &\xmlconcatrange{#1}{/*}{2}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{?}{}&}
+ &\xmlconcatrange{#1}{/*}{2}{}{\crcr\xmlval{mml:relation}{\mmlapplyaction}{[\mmlapplyaction]}{}&}
}
\stopxmlsetups
\startxmlsetups mml:relation:no
@@ -1230,9 +1261,15 @@
\xmldoifelse {#1} {/mml:lambda} {
% a special case (mathadore/openmath)
\frac {
- d\normalsuperscript{\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}{\xmlfirst{#1}{/mml:lambda}\xmlfirst{#1}{/mml:ci}}
+ d
+ \normalsuperscript
+ {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}
+ {\xmlfirst{#1}{/mml:lambda}\xmlfirst{#1}{/mml:ci}}
} {
- d{\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:ci}}\normalsuperscript{\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}
+ d
+ {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:ci}}
+ \normalsuperscript
+ {\xmlfirst{#1}{/mml:bvar}\xmlfirst{#1}{/mml:cn}}
}
} {
\xmldoifelse {#1} {/mml:bvar} {
@@ -1251,7 +1288,13 @@
\xmlfirst{#1}{/mml:ci}
} {
\MMLcreset
+\ifnum\xmlcount{#1}{/mml:apply/*}>\plustwo % hack
+ \left(
\xmlfirst{#1}{/mml:apply}
+ \right)
+\else
+ \xmlfirst{#1}{/mml:apply}
+\fi
}
}
} {
@@ -1265,7 +1308,8 @@
\left(\MMLcreset\xmlfirst{#1}{/(mml:apply\string|mml:ci)}\right)
}
} {
- \xmlconcatrange{#1}{/*}{2}{}\normalsuperscript\prime
+ % beware, the second {} is needed for the superscript
+ \xmlconcatrange{#1}{/*}{2}{}{}\normalsuperscript\prime
}
}
} {
@@ -1408,7 +1452,7 @@
\def\mmlstackedsubscripts#1%
{\vbox
{\baselineskip\zeropoint % hack, taco vragen
- \halign{$\scriptstyle\hss##\hss$\cr#1\crcr}}}
+ \halign{\startimath\scriptstyle\hss\alignmark\alignmark\hss\stopimath\cr#1\crcr}}}
% unfinished
@@ -1553,7 +1597,7 @@
\startxmlsetups mml:vector
\begingroup
- \ifnum\xmlcount{#1}>\plusone
+ \ifnum\xmlcount{#1}{/*}>\plusone
\doifelse\MMLvectordirection\v!horizontal {
\left(\xmlconcat{#1}{/*}{\MMLseparator\MMLvectorseparator}\right)
} {
@@ -1621,9 +1665,6 @@
}
\stopxmlsetups
-\usemodule[x][calcmath]
-%usemodule[x][asciimath]
-
\startxmlsetups mml:annotation
\xmldoifelse {#1} {.[oneof(@encoding,'TeX','tex','TEX','ConTeXt','context','CONTEXT','ctx')]} {
\xmlflushcontext{#1}
@@ -1674,31 +1715,31 @@
% todo: \def\mmlcfunction#1#2{\mathopnolimits{#2}\xmlsetup{#1}{mml:function}}
-\startxmlsetups mml:sin \mathopnolimits {sin}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:sinh \mathopnolimits {sinh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:cos \mathopnolimits {cos}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:cosh \mathopnolimits {cosh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:tan \mathopnolimits {tan}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:tanh \mathopnolimits {tanh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:cot \mathopnolimits {cot}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:coth \mathopnolimits {coth}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:csc \mathopnolimits {csc}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:csch \mathopnolimits {csch}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:sec \mathopnolimits {sec}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:sech \mathopnolimits {sech}\xmlsetup{#1}{mml:function} \stopxmlsetups
-
-\startxmlsetups mml:arcsin \mathopnolimits {arcsin}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arcsinh \mathopnolimits{arcsinh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccos \mathopnolimits {arccos}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccosh \mathopnolimits{arccosh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arctan \mathopnolimits {arctan}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arctanh \mathopnolimits{arctanh}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccot \mathopnolimits {arccot}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccoth \mathopnolimits{arccoth}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccsc \mathopnolimits {arccsc}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arccsch \mathopnolimits{arccsch}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arcsec \mathopnolimits {arcsec}\xmlsetup{#1}{mml:function} \stopxmlsetups
-\startxmlsetups mml:arcsech \mathopnolimits{arcsech}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:sin \mathcommand {sin}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:sinh \mathcommand {sinh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:cos \mathcommand {cos}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:cosh \mathcommand {cosh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:tan \mathcommand {tan}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:tanh \mathcommand {tanh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:cot \mathcommand {cot}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:coth \mathcommand {coth}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:csc \mathcommand {csc}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:csch \mathcommand {csch}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:sec \mathcommand {sec}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:sech \mathcommand {sech}\xmlsetup{#1}{mml:function} \stopxmlsetups
+
+\startxmlsetups mml:arcsin \mathcommand {arcsin}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arcsinh \mathcommand{arcsinh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccos \mathcommand {arccos}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccosh \mathcommand{arccosh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arctan \mathcommand {arctan}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arctanh \mathcommand{arctanh}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccot \mathcommand {arccot}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccoth \mathcommand{arccoth}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccsc \mathcommand {arccsc}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arccsch \mathcommand{arccsch}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arcsec \mathcommand {arcsec}\xmlsetup{#1}{mml:function} \stopxmlsetups
+\startxmlsetups mml:arcsech \mathcommand{arcsech}\xmlsetup{#1}{mml:function} \stopxmlsetups
\startxmlsetups mml:function
\ifx\MMLpowerelement\empty
@@ -1820,9 +1861,10 @@
\stopxmlsetups
\startxmlsetups mml:mn % todo: mathvariant mathsize mathcolor mathbackground
- \begingroup
- \mr \ctxmodulemathml{mn("#1")}% no \hbox, would be ok for . , but spoils rest
- \endgroup
+% \begingroup
+% \mr
+ \ctxmodulemathml{mn("#1")}% no \hbox, would be ok for . , but spoils rest
+% \endgroup
\stopxmlsetups
% <m:mo>-</m:mo><m:mn>2</m:mn> and <m:mn>1</m:mn><m:mo>-</m:mo><m:mn>2</m:mn>
@@ -1919,7 +1961,7 @@
\vcenter {
\framed
[frame=off,strut=no,background={\mmlmenclosenotation}] % offset is kind of undefined
- {$
+ {\startimath
\expanded{\doifinsetelse {mml:enclose:longdiv} {\mmlmenclosenotation}} {
\overline{\left)\strut\xmlflush{#1}\right.}
} {
@@ -1933,7 +1975,7 @@
}
}
}
- $}
+ \stopimath}
}
}
}
@@ -1944,6 +1986,7 @@
\xmlmapvalue {mml:mfrac:linethickness} {thin} {.2pt}
\xmlmapvalue {mml:mfrac:linethickness} {medium} {.4pt}
\xmlmapvalue {mml:mfrac:linethickness} {thick} {.8pt}
+\xmlmapvalue {mml:mfrac:linethickness} {0} {0pt}
\startxmlsetups mml:mfrac % dodo: handle linethickness in lua + unit
\begingroup
@@ -1958,6 +2001,7 @@
\doifelse {\xmlval{mml:mfrac:linethickness}{\mmlfraclinethickness}{}} {} {
\scratchdimen\xmlval{mml:mfrac:linethickness}\mmlfraclinethickness{.4pt}
} {
+ % probably not yet ok
\setdimensionwithunit\scratchdimen\mmlfraclinethickness{pt}
}
{
@@ -1987,16 +2031,16 @@
\endgroup
\stopxmlsetups
-\setupMMLappearance[text][\c!alternative=\v!a] % a=normal, b=keep spaces
+\setupMMLappearance[text][\c!alternative=\v!b] % a=normal, b=keep spaces
\startxmlsetups mml:mtext
- \domathtext {
+ \text {
\applymmlsometext{#1}{
- \doifelse\MMLscriptsalternative\v!a {
+ \doifelse \MMLtextalternative \v!a {
%\ctxmodulemathml{stripped(\!!bs\xmlflush{#1}\!!es)}
\ignorespaces
\xmlflush{#1}
- \unskip
+ \removeunwantedspaces
} {
\xmlflush{#1}
}
@@ -2005,12 +2049,13 @@
\stopxmlsetups
\startxmlsetups mml:merror
- \hbox{$\displaystyle\xmlflush{#1}$}
+ \hbox{\startimath\displaystyle\xmlflush{#1}\stopimath}
\stopxmlsetups
\startxmlsetups mml:mphantom
% \phantom{\ignorespaces{}\xmlflush{#1}\unskip} % watch spacing {} hack
- \phantom{\mathstyle{\ignorespaces{}\xmlflush{#1}\unskip}}%
+% \phantom{\mathstyle{\ignorespaces{}\xmlflush{#1}\unskip}}%
+ \phantom{\triggermathstyle\normalmathstyle\ignorespaces\xmlflush{#1}\removeunwantedspaces}
% \mktriggereffect\v!hidden
% \ignorespaces{}\xmlflush{#1}\unskip % no attributes in math yet
% \mktriggereffect\v!normal
@@ -2020,27 +2065,11 @@
\xmlflush{#1}
\stopxmlsetups
-% mrow
-
-% \startxmlsetups mml:mrow
-% \begingroup
-% \ifcase\xmlcount{#1}{/mml:mo}\relax
-% \xmlflush{#1}
-% \else % no \let
-% \def\MMLleft {\left }
-% \def\MMLright {\right}
-% \def\MMLmiddle{\middle}
-% \enabledelimiter
-% \checkdelimiters{\xmlall{#1}{/mml:mo}}
-% \fakeleftdelimiter
-% \xmlflush{#1}
-% \fakerightdelimiter
-% \disabledelimiter
-% \fi
-% \endgroup
-% \stopxmlsetups
+% mrow / option: no fenced
-% option: no fenced
+\startxmlsetups mml:maction
+ \xmlflush{#1}
+\stopxmlsetups
\startxmlsetups mml:mrow
\begingroup
@@ -2198,38 +2227,38 @@
\hskip\!!widtha
\fi
\else
- \phantom{\mathstyle{\mmlspacetext}}%
+ \phantom{\triggermathstyle\normalmathstyle\mmlspacetext}
\fi
\endgroup
\stopxmlsetups
% later we can do a better job by manipulating node lists
-\startxmlsetups mml:mline
- % new, rather undefined, we need to capture a few keywords
- \edef\mmllinewidth {\xmlatt{#1}{linethickness}}
- \edef\mmllinetext {\xmlatt{#1}{spacing}}
- \edef\mmllinelength{\xmlattdef{#1}{length}\!!zeropoint}
- \ifx\mmllinewidth\empty
- \!!deptha.5\linewidth
- \else
- \!!deptha.5\dimexpr\mmllinewidth\relax
- \fi
- \!!heighta\!!deptha
- \ifx\mmllinetext\empty
- \ifx\mmllinelength\empty
- \!!widtha\zeropoint
- \else
- \!!widtha\mmllinelength
- \fi
- \else
- \setbox\scratchbox\hbox{\mathematics{\mathstyle{\mmllinetext}}}% not ok
- \!!widtha\wd\scratchbox
- \fi
- \hbox{\vrule\!!width\!!widtha\!!depth\!!deptha\!!height\!!heighta}
-\stopxmlsetups
+% \startxmlsetups mml:mline
+% % new, rather undefined, we need to capture a few keywords
+% \edef\mmllinewidth {\xmlatt{#1}{linethickness}}
+% \edef\mmllinetext {\xmlatt{#1}{spacing}}
+% \edef\mmllinelength{\xmlattdef{#1}{length}\!!zeropoint}
+% \ifx\mmllinewidth\empty
+% \!!deptha.5\linewidth
+% \else
+% \!!deptha.5\dimexpr\mmllinewidth\relax
+% \fi
+% \!!heighta\!!deptha
+% \ifx\mmllinetext\empty
+% \ifx\mmllinelength\empty
+% \!!widtha\zeropoint
+% \else
+% \!!widtha\mmllinelength
+% \fi
+% \else
+% \setbox\scratchbox\hbox{\mathematics{\mathstyle{\mmllinetext}}}% not ok
+% \!!widtha\wd\scratchbox
+% \fi
+% \hbox{\vrule\!!width\!!widtha\!!depth\!!deptha\!!height\!!heighta}
+% \stopxmlsetups
-\startxmlsetups mml:mglyph % probably never ok
+\startxmlsetups mml:mglyph % probably never ok (hbox is needed in order to switch to normal font)
\begingroup
\edef\mmlglyphfontfamily{\xmlatt {#1}{fontfamily}}
\edef\mmlglyphalt {\xmlattdef{#1}{alt}{unknown}}
@@ -2239,7 +2268,7 @@
\else\ifx\mmlglyphindex\empty
\hbox{\tttf[no index specified for \mmlglyphalt]}
\else
- \getglyph\mmlglyphfontfamily\mmlglyphindex
+ \hbox{\getglyph\mmlglyphfontfamily\mmlglyphindex}
\fi\fi
\endgroup
\stopxmlsetups
diff --git a/Master/texmf-dist/tex/context/base/x-newcml.mkii b/Master/texmf-dist/tex/context/base/x-newcml.mkii
index 76d69ed516b..23c2bf1e2c0 100644
--- a/Master/texmf-dist/tex/context/base/x-newcml.mkii
+++ b/Master/texmf-dist/tex/context/base/x-newcml.mkii
@@ -5,7 +5,7 @@
%D subtitle=ChemML,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-newmme.mkii b/Master/texmf-dist/tex/context/base/x-newmme.mkii
index 5e17ea7a469..2e0d4c18969 100644
--- a/Master/texmf-dist/tex/context/base/x-newmme.mkii
+++ b/Master/texmf-dist/tex/context/base/x-newmme.mkii
@@ -5,7 +5,7 @@
%D subtitle=MathML Entities,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-newmml.mkii b/Master/texmf-dist/tex/context/base/x-newmml.mkii
index 17eda527664..e777edca11c 100644
--- a/Master/texmf-dist/tex/context/base/x-newmml.mkii
+++ b/Master/texmf-dist/tex/context/base/x-newmml.mkii
@@ -5,7 +5,7 @@
%D subtitle=MathML,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-newmml.mkiv b/Master/texmf-dist/tex/context/base/x-newmml.mkiv
index 757dcf38926..4c12daeeeb3 100644
--- a/Master/texmf-dist/tex/context/base/x-newmml.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-newmml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=MathML Renderer,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-newmmo.mkii b/Master/texmf-dist/tex/context/base/x-newmmo.mkii
index c3b56cc16b3..97fdeb06c0b 100644
--- a/Master/texmf-dist/tex/context/base/x-newmmo.mkii
+++ b/Master/texmf-dist/tex/context/base/x-newmmo.mkii
@@ -5,7 +5,7 @@
%D subtitle=MathML Renderer/Open Math Extensions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-newpml.mkii b/Master/texmf-dist/tex/context/base/x-newpml.mkii
index d69231e3fdd..ea3bae18262 100644
--- a/Master/texmf-dist/tex/context/base/x-newpml.mkii
+++ b/Master/texmf-dist/tex/context/base/x-newpml.mkii
@@ -5,7 +5,7 @@
%D subtitle=Units,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-pfs-01.mkiv b/Master/texmf-dist/tex/context/base/x-pfs-01.mkiv
new file mode 100644
index 00000000000..8b06bd873ff
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/x-pfs-01.mkiv
@@ -0,0 +1,399 @@
+% pfsense status info, work in progress
+%
+% usage:
+%
+% context --environment=x-pfs-01 filename.xml
+%
+% or
+%
+% <?context-directive job ctxfile x-pfsense.ctx ?>
+
+\setupbodyfont
+ [dejavu,10pt]
+
+\setuplayout
+ [topspace=1cm,
+ backspace=1cm,
+ footer=0pt,
+ header=1cm,
+ width=middle,
+ height=middle]
+
+\setupheader
+ [style=bold]
+
+\setuphead
+ [section]
+ [style=\bfb]
+
+\setuphead
+ [subsection]
+ [style=\bfa]
+
+\setuppagenumbering
+ [location=]
+
+\dontcomplain
+
+% todo: show all values and map keys onto longer names via labels
+
+\startxmlsetups xml:system
+
+ \startsection[title={System}]
+
+ \startsubsection[title={Properties}]
+
+ \starttabulate[|B|T|]
+ \NC hostname \NC \xmlfirst{#1}{hostname} \NC \NR
+ \NC domain \NC \xmlfirst{#1}{domain} \NC \NR
+ \NC timezone \NC \xmlfirst{#1}{timezone} \NC \NR
+ \NC timeservers \NC \xmlfirst{#1}{timeservers} \NC \NR
+ \NC dnsserver \NC \xmlfirst{#1}{dnsserver} \NC \NR
+ \stoptabulate
+
+ \stopsubsection
+
+ \startsubsection[title={Groups}]
+ \xmlfilter{#1}{group/command(xml:system:group)}
+ \stopsubsection
+
+ \startsubsection[title={Users}]
+ \xmlfilter{#1}{user/command(xml:system:user)}
+ \stopsubsection
+
+ \stopsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:system:group
+
+ \starttabulate[|B|T|]
+ \NC name \NC \xmlfirst{#1}{/name} \NC \NR
+ \NC description \NC \xmlfirst{#1}{/descr} \NC \NR
+ \NC scope \NC \xmlfirst{#1}{/scope} \NC \NR
+ \NC gid \NC \xmlfirst{#1}{/gid} \NC \NR
+ \NC privilege \NC \xmlfirst{#1}{/priv} \NC \NR
+ \NC members \NC \xmlconcat{#1}{/member}{ } \NC \NR
+ \stoptabulate
+
+\stopxmlsetups
+
+\startxmlsetups xml:system:user
+
+ \starttabulate[|B|T|]
+ \NC name \NC \xmlfirst{#1}{/name} \NC \NR
+ \NC description \NC \xmlfirst{#1}{/descr} \NC \NR
+ \NC scope \NC \xmlfirst{#1}{/scope} \NC \NR
+ \NC uid \NC \xmlfirst{#1}{/uid} \NC \NR
+ \NC group \NC \xmlfirst{#1}{/groupname} \NC \NR
+ \NC privilege \NC \xmlfirst{#1}{/priv} \NC \NR
+ \NC password \NC \xmldoifelsetext{#1}{/password}{set}{unset} \NC \NR
+ \NC ipsec psk \NC \xmldoifelsetext{#1}{/ipsecpsk}{set}{unset} \NC \NR
+ \NC certificate \NC \xmldoifelsetext{#1}{/cert} {set}{unset} \NC \NR
+ \stoptabulate
+
+\stopxmlsetups
+
+\startxmlsetups xml:interfaces
+
+ \startsection[title={Interfaces}]
+
+ \xmlfilter{#1}{*/command(xml:interfaces:network)}
+
+ \stopsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:interfaces:network
+
+ \startsubsection[title={\xmltag{#1}}]
+
+ % <blockpriv/> <blockbogons/> <spoofmac/> <enable/>
+
+ \starttabulate[|B|T|]
+ \NC interface \NC \xmlfirst{#1}{/if} \NC \NR
+ \NC block private \NC \xmldoifelse{#1}{/blockpriv} {yes}{no} \NC \NR
+ \NC block bogons \NC \xmldoifelse{#1}{/blockbogons}{yes}{no} \NC \NR
+ \NC spoof mac address \NC \xmldoifelse{#1}{/spoofmac} {yes}{no} \NC \NR
+ \NC enable interface \NC \xmldoifelse{#1}{/enable} {yes}{no} \NC \NR
+ \NC ipaddress \NC \xmlfirst{#1}{/ipaddr} \NC \NR
+ \NC subnet \NC \xmlfirst{#1}{/subnet} \NC \NR
+ \NC gateway \NC \xmlfirst{#1}{/gateway} \NC \NR
+ \NC description \NC \xmlfirst{#1}{/descr} \NC \NR
+ \stoptabulate
+
+ \stopsubsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:gateways
+
+ \startsection[title={Gateways}]
+
+ \xmlfilter{#1}{*/command(xml:gateways:entry)}
+
+ \stopsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:gateways:entry
+
+ \starttabulate[|B|T|]
+ \NC interface \NC \xmlfirst{#1}{/interface} \NC \NR
+ \NC gateway \NC \xmlfirst{#1}{/gateway} \NC \NR
+ \NC name \NC \xmlfirst{#1}{/name} \NC \NR
+ \NC weight \NC \xmlfirst{#1}{/weight} \NC \NR
+ \NC interval \NC \xmlfirst{#1}{/interval} \NC \NR
+ \NC description \NC \xmlfirst{#1}{/descr} \NC \NR
+ \NC disable monitor \NC \xmlfirst{#1}{/monitor_disable} \NC \NR
+ \NC default gateway \NC \xmlfirst{#1}{/defaultgw} \NC \NR
+ \stoptabulate
+
+\stopxmlsetups
+
+\startxmlsetups xml:virtualips
+
+ \startsection[title={Virtual ipadresses}]
+
+ \xmlfilter{#1}{*/command(xml:virtualips:entry)}
+
+ \stopsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:virtualips:entry
+
+ \starttabulate[|B|T|]
+ \NC interface \NC \xmlfirst{#1}{/interface} \NC \NR
+ \NC type \NC \xmlfirst{#1}{/type} \NC \NR
+ \NC mode \NC \xmlfirst{#1}{/mode} \NC \NR
+ \NC subnet \NC \xmlfirst{#1}{/subnet}
+ /\xmlfirst{#1}{/subnet_bits} \NC \NR
+ \NC description \NC \xmlfirst{#1}{/descr} \NC \NR
+ \stoptabulate
+
+\stopxmlsetups
+
+\startxmlsetups xml:dhcp
+
+ \startsection[title={DHCP}]
+
+ \xmlfilter{#1}{*/command(xml:dhcp:network)}
+
+ \stopsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:dhcp:network
+
+ \startsubsection[title={\xmltag{#1}}]
+
+ \starttabulate[|B|T|]
+ \NC range \NC \xmlfirst{#1}{/range/from} \endash\ \xmlfirst{#1}{/range/to} \NC \NR
+ \NC domain \NC \xmlfirst{#1}{/domain} \NC \NR
+ \NC dnsserver \NC \xmlfirst{#1}{/dnsserver} \NC \NR
+ \NC gateway \NC \xmlfirst{#1}{/gateway} \NC \NR
+ \NC ddnsdomain \NC \xmlfirst{#1}{/ddnsdomain} \NC \NR
+ \stoptabulate
+
+ \xmldoif {#1} {/staticmap} {
+
+ \starttabulate[|T|T|T|p|]
+ \NC \rm\bf macaddress
+ \NC \rm\bf ipaddress
+ \NC \rm\bf hostname
+ \NC \rm\bf description
+ \NC \NR
+ \HL
+ \xmlfilter{#1}{/staticmap/command(xml:dhcp:network:entry)}
+ \stoptabulate
+
+ }
+
+ \stopsubsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:dhcp:network:entry
+
+ \NC \xmlfirst{#1}{/mac}
+ \NC \xmlfirst{#1}{/ipaddr}
+ \NC \xmlfirst{#1}{/hostname}
+ \NC \xmlfirst{#1}{/descr}
+ \NC \NR
+
+\stopxmlsetups
+
+\startxmlsetups xml:dnsmasq
+
+ \startsection[title={DNS MASQ}]
+
+ \starttabulate[|T|T|T|p|]
+ \NC \rm\bf host
+ \NC \rm\bf domain
+ \NC \rm\bf ipaddress
+ \NC \rm\bf description
+ \NC \NR
+ \HL
+ \xmlfilter{#1}{/hosts/command(xml:dnsmasq:hosts)}
+ \stoptabulate
+
+ \stopsection
+
+\stopxmlsetups
+
+
+\startxmlsetups xml:dnsmasq:hosts
+
+ \NC \xmlfirst{#1}{/host}
+ \NC \xmlfirst{#1}{/domain}
+ \NC \xmlfirst{#1}{/ip}
+ \NC \xmlfirst{#1}{/descr}
+ \NC \NR
+
+\stopxmlsetups
+
+\startxmlsetups xml:nat
+
+ \startsection[title={NAT}]
+
+ \startsubsection[title={Rules}]
+
+ \starttabulate[|T|T|T|T|T|p|]
+ \NC \rm\bf interface
+ \NC \rm\bf protocol
+ \NC \rm\bf source
+ \NC \rm\bf destination
+ \NC \rm\bf target
+ \NC \rm\bf description
+ \NC \NR
+ \HL
+ \xmlfilter{#1}{/rule/command(xml:nat:rule)}
+ \stoptabulate
+
+ \stopsubsection
+
+ \startsubsection[title={One to one}]
+
+ \starttabulate[|T|T|T|T|T|p|]
+ \NC \rm\bf interface
+ \NC \rm\bf protocol
+ \NC \rm\bf source
+ \NC \rm\bf destination
+ \NC \rm\bf external
+ \NC \rm\bf description
+ \NC \NR
+ \HL
+ \xmlfilter{#1}{/onetoone/command(xml:nat:onetoone)}
+ \stoptabulate
+
+ \stopsubsection
+
+\stopsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:nat:rule
+
+ \NC \xmlfilter{#1}{/interface/command(xml:checked)}
+ \NC \xmlfilter{#1}{/protocol/command(xml:checked)}
+ \NC \xmlfilter{#1}{/source/command(xml:checked)}
+ \NC \xmlfilter{#1}{/destination/(address|any)/command(xml:checked)}
+ :\xmlfilter{#1}{/destination/port/command(xml:checked)}
+ \NC \xmlfilter{#1}{/target/command(xml:checked)}
+ :\xmlfilter{#1}{/local-port/command(xml:checked)}
+ \NC \xmlfirst {#1}{/descr}
+ \NC \NR
+
+\stopxmlsetups
+
+\startxmlsetups xml:nat:onetoone
+
+ \NC \xmlfilter{#1}{/interface/command(xml:checked)}
+ \NC \xmlfilter{#1}{/protocol/command(xml:checked)}
+ \NC \xmlfilter{#1}{/source/command(xml:checked)}
+ \NC \xmlfilter{#1}{/destination/(address|any)/command(xml:checked)}
+ :\xmlfilter{#1}{/destination/port/command(xml:checked)}
+ \NC \xmlfilter{#1}{/external/command(xml:checked)}
+ :\xmlfilter{#1}{/local-port/command(xml:checked)}
+ \NC \xmlfirst {#1}{/descr}
+ \NC \NR
+
+\stopxmlsetups
+
+\startxmlsetups xml:checked
+ \xmldoifelse {#1} {/any} {
+ *
+ } {
+ \xmldoifelsetext {#1} {.} {
+ \xmlflush{#1}
+ } {
+ *
+ }
+ }
+\stopxmlsetups
+
+\startxmlsetups xml:filter
+
+ \startsection[title={Filter}]
+
+ \startsubsection[title={Rules}]
+
+ \starttabulate[|T|T|T|T|T|p|]
+ \NC \rm\bf type
+ \NC \rm\bf interface
+ \NC \rm\bf protocol
+ \NC \rm\bf source
+ \NC \rm\bf destination
+ \NC \rm\bf description
+ \NC \NR
+ \HL
+ \xmlfilter{#1}{/rule/command(xml:filter:rule)}
+ \stoptabulate
+
+ \stopsubsection
+
+ \stopsubsection
+
+\stopxmlsetups
+
+\startxmlsetups xml:filter:rule
+
+ \NC \xmlfilter{#1}{/type/command(xml:checked)}
+ \NC \xmlfilter{#1}{/interface/command(xml:checked)}
+ \NC \xmlfilter{#1}{/protocol/command(xml:checked)}
+ \NC \xmlfilter{#1}{/source/(address|any)/command(xml:checked)}:
+ :\xmlfilter{#1}{/source/port/command(xml:checked)}
+ \NC \xmlfilter{#1}{/destination/(address|any)/command(xml:checked)}
+ :\xmlfilter{#1}{/destination/port/command(xml:checked)}
+ \NC \xmlfirst {#1}{/descr}
+ \NC \NR
+
+\stopxmlsetups
+
+\starttext
+
+ \doifelse {\inputfilename} {x-pfs-01.mkiv} {
+
+ \xmlloadonly{main}{router.xml}{}
+
+ \setupheadertexts[router.xml][\pagenumber]
+
+ } {
+
+ \xmlloadonly{main}{\inputfilename}{}
+
+ \setupheadertexts[\inputfilename][\pagenumber]
+
+ }
+
+ \xmlfilter{main}{/pfsense/system/command(xml:system)}
+ \xmlfilter{main}{/pfsense/interfaces/command(xml:interfaces)}
+ \xmlfilter{main}{/pfsense/gateways/command(xml:gateways)}
+ \xmlfilter{main}{/pfsense/virtualip/command(xml:virtualips)}
+ \xmlfilter{main}{/pfsense/dhcpd/command(xml:dhcp)}
+ \xmlfilter{main}{/pfsense/dnsmasq/command(xml:dnsmasq)}
+ \xmlfilter{main}{/pfsense/nat/command(xml:nat)}
+ \xmlfilter{main}{/pfsense/filter/command(xml:filter)}
+
+\stoptext
diff --git a/Master/texmf-dist/tex/context/base/x-pfsense.ctx b/Master/texmf-dist/tex/context/base/x-pfsense.ctx
new file mode 100644
index 00000000000..8d7087cf222
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/x-pfsense.ctx
@@ -0,0 +1,15 @@
+<?xml version='1.0' standalone='yes'?>
+
+<!-- this is also a demo of using the xml interface -->
+
+<ctx:job>
+ <ctx:message>pfsense configuration listing</ctx:message>
+ <ctx:process>
+ <ctx:flags>
+ <ctx:flag>purge</ctx:flag>
+ </ctx:flags>
+ <ctx:resources>
+ <ctx:environment>x-pfs-01.mkiv</ctx:environment>
+ </ctx:resources>
+ </ctx:process>
+</ctx:job>
diff --git a/Master/texmf-dist/tex/context/base/x-physml.mkii b/Master/texmf-dist/tex/context/base/x-physml.mkii
index 7f6a94642dd..4d9cffe3325 100644
--- a/Master/texmf-dist/tex/context/base/x-physml.mkii
+++ b/Master/texmf-dist/tex/context/base/x-physml.mkii
@@ -5,7 +5,7 @@
%D subtitle=Loading PHYSML Filters,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-physml.mkiv b/Master/texmf-dist/tex/context/base/x-physml.mkiv
index 508c70c52a5..dd9a164dd19 100644
--- a/Master/texmf-dist/tex/context/base/x-physml.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-physml.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Loading PHYSML Filters,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-00.mkii b/Master/texmf-dist/tex/context/base/x-res-00.mkii
index 9878d0a5834..d031e1453ed 100644
--- a/Master/texmf-dist/tex/context/base/x-res-00.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-00.mkii
@@ -5,7 +5,7 @@
%D subtitle=Resource Libraries,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-01.mkii b/Master/texmf-dist/tex/context/base/x-res-01.mkii
index dc14e70548b..41580a0b8ef 100644
--- a/Master/texmf-dist/tex/context/base/x-res-01.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-01.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-01.mkiv b/Master/texmf-dist/tex/context/base/x-res-01.mkiv
index b82d604848b..0ebb8933d11 100644
--- a/Master/texmf-dist/tex/context/base/x-res-01.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-res-01.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-02.mkii b/Master/texmf-dist/tex/context/base/x-res-02.mkii
index a29f446f345..f8502dbac1c 100644
--- a/Master/texmf-dist/tex/context/base/x-res-02.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-02.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Inclusion (I),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-03.mkii b/Master/texmf-dist/tex/context/base/x-res-03.mkii
index bf5ea226cff..15f2620c1be 100644
--- a/Master/texmf-dist/tex/context/base/x-res-03.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-03.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Inclusion (II),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-04.mkii b/Master/texmf-dist/tex/context/base/x-res-04.mkii
index b5032f5503f..b22e9ffa439 100644
--- a/Master/texmf-dist/tex/context/base/x-res-04.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-04.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Base Loading,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-08.mkii b/Master/texmf-dist/tex/context/base/x-res-08.mkii
index 3d79b00e47a..0805f071fdb 100644
--- a/Master/texmf-dist/tex/context/base/x-res-08.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-08.mkii
@@ -5,7 +5,7 @@
%D subtitle=Resource Reporting,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-09.mkii b/Master/texmf-dist/tex/context/base/x-res-09.mkii
index 60823615623..e3354e9a422 100644
--- a/Master/texmf-dist/tex/context/base/x-res-09.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-09.mkii
@@ -5,7 +5,7 @@
%D subtitle=Resource Reporting (2),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-10.mkii b/Master/texmf-dist/tex/context/base/x-res-10.mkii
index f23c503586e..833bce776e1 100644
--- a/Master/texmf-dist/tex/context/base/x-res-10.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-10.mkii
@@ -5,7 +5,7 @@
%D subtitle=Resource Dummy Generation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-11.mkii b/Master/texmf-dist/tex/context/base/x-res-11.mkii
index b8569d22e6f..84157be883a 100644
--- a/Master/texmf-dist/tex/context/base/x-res-11.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-11.mkii
@@ -5,7 +5,7 @@
%D subtitle=Resource Reporting (3),
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-12.mkii b/Master/texmf-dist/tex/context/base/x-res-12.mkii
index 1cff4871715..81761ae9ad1 100644
--- a/Master/texmf-dist/tex/context/base/x-res-12.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-12.mkii
@@ -5,7 +5,7 @@
%D subtitle=Resource Checking,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-20.mkii b/Master/texmf-dist/tex/context/base/x-res-20.mkii
index 3ff069ffd2f..0bc1358ec41 100644
--- a/Master/texmf-dist/tex/context/base/x-res-20.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-20.mkii
@@ -5,7 +5,7 @@
%D subtitle=Figure Lists,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-50.mkii b/Master/texmf-dist/tex/context/base/x-res-50.mkii
index 6fa1a3e4fd2..3c3e758a7d2 100644
--- a/Master/texmf-dist/tex/context/base/x-res-50.mkii
+++ b/Master/texmf-dist/tex/context/base/x-res-50.mkii
@@ -5,7 +5,7 @@
%D subtitle=Multimedia Presentation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={\PRAGMA\ / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-res-50.mkiv b/Master/texmf-dist/tex/context/base/x-res-50.mkiv
index 87b63dd97ec..62a86b7a744 100644
--- a/Master/texmf-dist/tex/context/base/x-res-50.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-res-50.mkiv
@@ -5,7 +5,7 @@
%D subtitle=Multimedia Presentation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={\PRAGMA\ / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-sch-00.mkii b/Master/texmf-dist/tex/context/base/x-sch-00.mkii
index 379d19cf2f8..5b4da0825b3 100644
--- a/Master/texmf-dist/tex/context/base/x-sch-00.mkii
+++ b/Master/texmf-dist/tex/context/base/x-sch-00.mkii
@@ -5,7 +5,7 @@
%D subtitle=XML Schema Basics,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-sch-01.mkii b/Master/texmf-dist/tex/context/base/x-sch-01.mkii
index d72cbf89c84..5bdf088fe71 100644
--- a/Master/texmf-dist/tex/context/base/x-sch-01.mkii
+++ b/Master/texmf-dist/tex/context/base/x-sch-01.mkii
@@ -5,7 +5,7 @@
%D subtitle=XML Schema Presentation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-set-01.mkii b/Master/texmf-dist/tex/context/base/x-set-01.mkii
index 75e1d43e24b..814ea5fc6c5 100644
--- a/Master/texmf-dist/tex/context/base/x-set-01.mkii
+++ b/Master/texmf-dist/tex/context/base/x-set-01.mkii
@@ -6,7 +6,7 @@
%D subtitle=Macro Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-set-02.mkii b/Master/texmf-dist/tex/context/base/x-set-02.mkii
index bb0b7583c33..8af98c41263 100644
--- a/Master/texmf-dist/tex/context/base/x-set-02.mkii
+++ b/Master/texmf-dist/tex/context/base/x-set-02.mkii
@@ -6,7 +6,7 @@
%D subtitle=Macro Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-set-11.mkii b/Master/texmf-dist/tex/context/base/x-set-11.mkii
index 3207ef5f9df..8c8f614a5b4 100644
--- a/Master/texmf-dist/tex/context/base/x-set-11.mkii
+++ b/Master/texmf-dist/tex/context/base/x-set-11.mkii
@@ -6,7 +6,7 @@
%D subtitle=Macro Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-set-11.mkiv b/Master/texmf-dist/tex/context/base/x-set-11.mkiv
index ceba34f3d54..a8e62542b54 100644
--- a/Master/texmf-dist/tex/context/base/x-set-11.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-set-11.mkiv
@@ -6,7 +6,7 @@
%D subtitle=Macro Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -513,8 +513,9 @@
\bgroup
\enablemode[setups-pass-two]
\doglobal\newcounter\currentSETUPargument
- \blank[\v!line]
- \switchtobodyfont[small]
+ %\blank[\v!line] % packed mode (we could do \startunpacked ...)
+ \godown[.75\lineheight]
+ \switchtobodyfont[\v!small]
\ignorespaces\xmlfilter{#1}{/arguments/text()}\endgraf
\egroup
}
diff --git a/Master/texmf-dist/tex/context/base/x-set-12.mkii b/Master/texmf-dist/tex/context/base/x-set-12.mkii
index d7990143365..c2aa265c3f2 100644
--- a/Master/texmf-dist/tex/context/base/x-set-12.mkii
+++ b/Master/texmf-dist/tex/context/base/x-set-12.mkii
@@ -6,7 +6,7 @@
%D subtitle=Macro Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-set-12.mkiv b/Master/texmf-dist/tex/context/base/x-set-12.mkiv
index d95aff4a3f4..bfeb0ab54aa 100644
--- a/Master/texmf-dist/tex/context/base/x-set-12.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-set-12.mkiv
@@ -6,7 +6,7 @@
%D subtitle=Macro Definitions,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -75,9 +75,6 @@
\usetypescript[palatino]
\setupbodyfont[palatino,9pt]
-\setupcolors
- [\c!state=\v!start]
-
\defineoverlay
[cover]
[\hbox to \paperwidth{\hss\reuseMPgraphic{cover+back}}]
diff --git a/Master/texmf-dist/tex/context/base/x-steps.mkii b/Master/texmf-dist/tex/context/base/x-steps.mkii
index 408a7e191ce..47141699a93 100644
--- a/Master/texmf-dist/tex/context/base/x-steps.mkii
+++ b/Master/texmf-dist/tex/context/base/x-steps.mkii
@@ -5,7 +5,7 @@
%D subtitle=Step Charts \& Tables,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-steps.mkiv b/Master/texmf-dist/tex/context/base/x-steps.mkiv
deleted file mode 100644
index 61681880920..00000000000
--- a/Master/texmf-dist/tex/context/base/x-steps.mkiv
+++ /dev/null
@@ -1,99 +0,0 @@
-%D \module
-%D [ file=m-steps,
-%D version=2001.05.28,
-%D title=\CONTEXT\ Modules,
-%D subtitle=Step Charts \& Tables,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA ADE / Hans Hagen \& Ton Otten}]
-%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 \XML\ interface. This module can be made way more efficient
-%D in \MKIV\ using textext but it makes only sense to do this when
-%D I really need it in a demanding application. Probably half of the
-%D code in m-steps.tex can go.
-
-\usemodule[m][steps]
-
-\unprotect
-
-\def\xmlstepchartdirective#1{\executeifdefined{@@stepchart@@#1}\gobbletwoarguments} % {#2}{#3}
-\def\xmlsteptabledirective#1{\executeifdefined{@@steptable@@#1}\gobbletwoarguments} % {#2}{#3}
-
-\setvalue{@@stepchart@@charts}{\setsomevalue\@@STPC}
-\setvalue{@@stepchart@@cells}{\setsomevalue\@@STEC}
-\setvalue{@@stepchart@@texts}{\setsomevalue\@@STET}
-\setvalue{@@stepchart@@lines}{\setsomevalue\@@STEL}
-
-\setvalue{@@steptable@@tables}{\setsomevalue\@@STPT}
-\setvalue{@@steptable@@cells}{\setsomevalue\@@STEC}
-\setvalue{@@steptable@@texts}{\setsomevalue\@@STET}
-\setvalue{@@steptable@@lines}{\setsomevalue\@@STEL}
-
-\startxmlsetups xml:ct:define
- \xmlsetsetup {#1} {ct:*} {xml:ct:*}
- \xmlsetsetup {#1} {ct:stepaligntable/cells} {xml:ct:stepaligntable:cells}
- \xmlsetsetup {#1} {ct:stepaligntable/lines} {xml:ct:stepaligntable:lines}
-\stopxmlsetups
-
-\xmlregisterns{ct}{stepcharts}
-
-\xmlregistersetup{xml:ct:define}
-
-\startxmlsetups xml:ct:prep
- \expanded{\prep[\xmltoparameters{#1}]}{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups xml:ct:text
- \expanded{\text[\xmltoparameters{#1}]}{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups xml:ct:texts
- \expanded{\texts[\xmltoparameters{#1}]}{\xmltext{#1}{/top}} {\xmltext{#1}{/bot}}
-\stopxmlsetups
-
-\startxmlsetups xml:ct:cell
- \expanded{\cell[\xmltoparameters{#1}]}{\xmlflush{#1}}
-\stopxmlsetups
-
-\startxmlsetups xml:ct:cells
- \expanded{\cells[\xmltoparameters{#1}]}{\xmltext{#1}{/top}} {\xmltext{#1}{/bot}}
-\stopxmlsetups
-
-\startxmlsetups xml:ct:lines
- \expanded{\startlines[\xmltoparameters{#1}]}
- \xmlflush{#1}
- \stoplines
-\stopxmlsetups
-
-\startxmlsetups xml:ct:steptable
- \expanded{\startSTEPtable[\xmltoparameters{#1}]}
- \xmlflush{#1}
- \stopSTEPtable
-\stopxmlsetups
-
-\startxmlsetups xml:ct:stepchart
- \expanded{\startSTEPchart[\xmltoparameters{#1}]}
- \xmlflush{#1}
- \stopSTEPchart
-\stopxmlsetups
-
-\startxmlsetups xml:ct:stepaligntable
- \expanded{\startSTEPaligntable[\xmltoparameters{#1}]}
- \xmlflush{#1}
- \stopSTEPaligntable
-\stopxmlsetups
-
-\startxmlsetups xml:ct:stepaligntable:cells
- \expanded{\cells[\xmltoparameters{#1}]} {\xmltext{#1}{/ct:c1}} {\xmltext{#1}{/ct:c2}} {\xmltext{#1}{/ct:c3}}
-\stopxmlsetups
-
-\startxmlsetups xml:ct:stepaligntable:lines
- \expanded{\setupSTEPlines[\xmltoparameters{#1}]}
- \xmlflush{#1}
-\stopxmlsetups
-
-\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/x-udhr.mkiv b/Master/texmf-dist/tex/context/base/x-udhr.mkiv
new file mode 100644
index 00000000000..81075ac702b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/x-udhr.mkiv
@@ -0,0 +1,98 @@
+%D \module
+%D [ file=x-udhr,
+%D version=2011.06.11,
+%D title=\CONTEXT\ Modules,
+%D subtitle=Unicode Language Test Files,
+%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 XML files can be fetched from: \from[http://unicode.org/udhr/].
+
+\startmodule[udhr]
+
+\startxmlsetups udhr:basics
+ \xmlsetsetup {#1} {*} {udhr:*}
+\stopxmlsetups
+
+\xmlregistersetup{udhr:basics}
+
+\startxmlsetups udhr:udhr
+
+ \mainlanguage[\xmlatt{#1}{language}]
+
+ \starttitle[title=\xmltext{#1}{/title}]
+ \xmlfirst{#1}{/preamble}
+ \xmlall{#1}{/article}
+ \stoptitle
+
+\stopxmlsetups
+
+\startxmlsetups udhr:preamble
+ \startsubject[title=\xmltext{#1}{/title}]
+ \xmlall{#1}{/*)}
+ \stopsubject
+\stopxmlsetups
+
+\startxmlsetups udhr:article
+ \startsubject[title=\xmltext{#1}{/title}]
+ \xmlall{#1}{/*)}
+ \stopsubject
+\stopxmlsetups
+
+\startxmlsetups udhr:orderedlist
+ \startitemize[n]
+ \xmlflush{#1}
+ \stopitemize
+\stopxmlsetups
+
+\startxmlsetups udhr:listitem
+ \startitem
+ \xmlflush{#1}
+ \stopitem
+\stopxmlsetups
+
+\startxmlsetups udhr:para
+ \xmlflush{#1}
+ \par
+\stopxmlsetups
+
+\setupbodyfont
+ [dejavu,10pt]
+
+\setuplayout
+ [width-=middle,
+ height=middle,
+ footer=0cm,
+ header=1.5cm]
+
+\setupwhitespace
+ [big]
+
+\setuphead
+ [chapter]
+ [header=high,
+ style=\bfb,
+ align=middle]
+
+\setuphead
+ [section]
+ [style=\bfa,
+ align=middle]
+
+\setuptolerance
+ [verytolerant]
+
+\doifnotmode{demo}{\endinput}
+
+% todo: when argument given then process it
+
+\starttext
+ \xmlprocessfile{main}{udhr_nld.xml}{}
+\stoptext
+
+\stopmodule
diff --git a/Master/texmf-dist/tex/context/base/x-xml-01.mkii b/Master/texmf-dist/tex/context/base/x-xml-01.mkii
index 9502ab71a3e..95ce51fc888 100644
--- a/Master/texmf-dist/tex/context/base/x-xml-01.mkii
+++ b/Master/texmf-dist/tex/context/base/x-xml-01.mkii
@@ -5,7 +5,7 @@
%D subtitle=Formatting X?? files,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-xml-02.mkii b/Master/texmf-dist/tex/context/base/x-xml-02.mkii
index 24f811c4dad..e33ab9ee4ce 100644
--- a/Master/texmf-dist/tex/context/base/x-xml-02.mkii
+++ b/Master/texmf-dist/tex/context/base/x-xml-02.mkii
@@ -5,7 +5,7 @@
%D subtitle=Pretty Printing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-xml-11.mkii b/Master/texmf-dist/tex/context/base/x-xml-11.mkii
index c1b185b559f..047561370e9 100644
--- a/Master/texmf-dist/tex/context/base/x-xml-11.mkii
+++ b/Master/texmf-dist/tex/context/base/x-xml-11.mkii
@@ -5,7 +5,7 @@
%D subtitle=Formatting X?? files,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/x-xtag.mkiv b/Master/texmf-dist/tex/context/base/x-xtag.mkiv
index be593300c83..09490cc8ff4 100644
--- a/Master/texmf-dist/tex/context/base/x-xtag.mkiv
+++ b/Master/texmf-dist/tex/context/base/x-xtag.mkiv
@@ -5,7 +5,7 @@
%D subtitle=\XML\ stream handler,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=PRAGMA]
+%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
@@ -18,6 +18,66 @@
\writestatus{xtag}{this module is obsolete, use the mkiv-xml features or use mkii instead}
+%D Well, at this time (2011.12.28) I'm not sure if this code still works in
+%D \MKIV. But in any case we move snippets here that are only needed for old
+%D \MKII\ code.
+
+\unprotect
+
+\newif\ifforcefileexpansion % handy for document level overload
+
+\def\installexpander#1#2#3% changed, no longer \convert..\to...
+ {\setvalue{\s!do\c!expansion#1l}{#2}%
+ \setvalue{\s!do\c!expansion#1g}{#3}}%
+
+\def\doconvertexpanded#1#2#3% #4 % [l|g] \cs {kind} {data}
+ {\csname % that we assign all exp a value
+ \s!do\c!expansion
+ \ifforcefileexpansion
+ \v!yes
+ \else\ifcsname\s!do\c!expansion#3#1\endcsname
+ #3%
+ \else
+ \s!default
+ \fi\fi
+ #1%
+ \endcsname#2}% #3
+
+\def\defconvertexpanded {\doconvertexpanded l}
+\def\gdefconvertexpanded{\doconvertexpanded g}
+
+\installexpander\v!command \defconvertedcommand \gdefconvertedcommand
+\installexpander\s!default \defconvertedargument \gdefconvertedargument
+\installexpander\empty \defconvertedargument \gdefconvertedargument
+\installexpander\v!no \defconvertedargument \gdefconvertedargument
+\installexpander\v!yes \defconvertedmeaning \gdefconvertedmeaning
+\installexpander\v!yes \defconvertedmeaning \gdefconvertedmeaning
+\installexpander\v!strict \defreducedargument \gdefreducedargument
+\installexpander {utf} \defreducedtoutf \gdefreducedtoutf
+
+\def\dodefconvertedmeaning#1#2#3% watch the double expansion !
+ {\bgroup
+ \xdef\@@globalexpanded{#3}%
+ \xdef\@@globalexpanded{\@@globalexpanded}%
+ \egroup
+ #1#2\@@globalexpanded}
+
+\def\defconvertedmeaning {\dodefconvertedmeaning\defconvertedcommand}
+\def\gdefconvertedmeaning{\dodefconvertedmeaning\gdefconvertedcommand}
+
+\def\dodefreducedargument#1#2#3%
+ {\begingroup
+ \reducetocoding[raw]%
+ \edef\ascii{#3}%
+ \expandafter\endgroup\expandafter#1\expandafter#2\expandafter{\ascii}}
+
+\def\defreducedargument {\dodefreducedargument\edef}
+\def\gdefreducedargument{\dodefreducedargument\xdef}
+
+\protect
+
+%D The \XML\ modules.
+
\loadmarkfile{catc-xml}
\loadcorefile{xtag-ini.mkii}
diff --git a/Master/texmf-dist/tex/context/base/xetx-ini.mkii b/Master/texmf-dist/tex/context/base/xetx-ini.mkii
index db3cccabdbf..55155fa1af2 100644
--- a/Master/texmf-dist/tex/context/base/xetx-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/xetx-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=\XETEX\ Initializations,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-ent.mkii b/Master/texmf-dist/tex/context/base/xtag-ent.mkii
index f4c3e4b0648..09051d0b435 100644
--- a/Master/texmf-dist/tex/context/base/xtag-ent.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-ent.mkii
@@ -5,7 +5,7 @@
%D subtitle=A bunch of Entities,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-exp.mkii b/Master/texmf-dist/tex/context/base/xtag-exp.mkii
index 337b4934879..9ecfcc5b124 100644
--- a/Master/texmf-dist/tex/context/base/xtag-exp.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-exp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Expansion,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -13,6 +13,8 @@
\writestatus{loading}{ConTeXt XML Macros / Expansion}
+\ifnum\texengine=\luatexengine \endinput \fi
+
\unprotect
%D Files
diff --git a/Master/texmf-dist/tex/context/base/xtag-ext.mkii b/Master/texmf-dist/tex/context/base/xtag-ext.mkii
index 9a132c677b7..60615b1c241 100644
--- a/Master/texmf-dist/tex/context/base/xtag-ext.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-ext.mkii
@@ -5,7 +5,7 @@
%D subtitle=Extra Macros,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -148,7 +148,7 @@
% trial macros (used in setupx), to be sped up !
-\bgroup \catcode`\<=\active
+\bgroup \catcode`\<=\activecatcode
\gdef\saveXMLasdata#1#2% name raw data
{\dodoglobal\setevalue{\@@XMLsave:#1}{#2}} % \edef!
@@ -348,7 +348,7 @@
\setupXMLprocessing
[\c!escape=e]
-\bgroup \catcode`\<=\active
+\bgroup \catcode`\<=\activecatcode
\long\gdef\defexpandedxmlargument#1#2#3%
{\begingroup
diff --git a/Master/texmf-dist/tex/context/base/xtag-hyp.mkii b/Master/texmf-dist/tex/context/base/xtag-hyp.mkii
index e4e048e2bf0..105f1a1e373 100644
--- a/Master/texmf-dist/tex/context/base/xtag-hyp.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-hyp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Hyphenation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-ini.mkii b/Master/texmf-dist/tex/context/base/xtag-ini.mkii
index 85b48141991..8f10c4f55cd 100644
--- a/Master/texmf-dist/tex/context/base/xtag-ini.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-ini.mkii
@@ -5,7 +5,7 @@
%D subtitle=Initialization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -16,6 +16,9 @@
%D Beware: don't rely on \longempty things, since this may
%D change!
+\ifdefined\keeputfcharacters \else \let\keeputfcharacters\relax \fi % for mkiv
+\ifdefined\utfunicodetracer \else \newconstant\utfunicodetracer \fi % for mkiv
+
%D \macros
%D {defineinputmode,setinputmode}
%D
@@ -258,25 +261,25 @@
\let\disableXMLelements \relax
% \bgroup
-% \catcode`\*=\@@comment
-% \catcode`\.=\@@escape
-% .catcode`.B=.@@begingroup
-% .catcode`.E=.@@endgroup
-% .catcode`.P=.@@parameter
-%
-% .catcode`.&=.@@active
-% .catcode`.<=.@@active
-%
-% .catcode`.#=.@@active
-% .catcode`.$=.@@active
-% .catcode`.%=.@@active
-% .catcode`.\=.@@active
-% .catcode`.^=.@@active
-% .catcode`._=.@@active
-% .catcode`.{=.@@active
-% .catcode`.}=.@@active
-% .catcode`.|=.@@active
-% .catcode`.~=.@@active
+% \catcode`\*=\commentcatcode
+% \catcode`\.=\escapecatcode
+% .catcode`.B=.begingroupcatcode
+% .catcode`.E=.endgroupcatcode
+% .catcode`.P=.parametercatcode
+%
+% .catcode`.&=.activecatcode
+% .catcode`.<=.activecatcode
+%
+% .catcode`.#=.activecatcode
+% .catcode`.$=.activecatcode
+% .catcode`.%=.activecatcode
+% .catcode`.\=.activecatcode
+% .catcode`.^=.activecatcode
+% .catcode`._=.activecatcode
+% .catcode`.{=.activecatcode
+% .catcode`.}=.activecatcode
+% .catcode`.|=.activecatcode
+% .catcode`.~=.activecatcode
%
% .gdef.enableXMLexpansion
% B.def<B.doXMLelementE.let&=.doXMLentityE
@@ -294,18 +297,18 @@
% * (eating up argument)
%
% .unexpanded.gdef.enableXML
-% B.catcode`.!=.@@other
-% .catcode`.?=.@@other
-% .catcode`.:=.@@other * active in french
-% .catcode`.;=.@@other * active in french
-% .catcode`.&=.@@active
-% .catcode`.<=.@@active
-% .catcode`.>=.@@other
-% .catcode`."=.@@other
-% .catcode`./=.@@other
-% .catcode`.'=.@@other
-% .catcode`.~=.@@other
-% .catcode`.#=.@@other
+% B.catcode`.!=.othercatcode
+% .catcode`.?=.othercatcode
+% .catcode`.:=.othercatcode * active in french
+% .catcode`.;=.othercatcode * active in french
+% .catcode`.&=.activecatcode
+% .catcode`.<=.activecatcode
+% .catcode`.>=.othercatcode
+% .catcode`."=.othercatcode
+% .catcode`./=.othercatcode
+% .catcode`.'=.othercatcode
+% .catcode`.~=.othercatcode
+% .catcode`.#=.othercatcode
% .let &=.doXMLentity
% .unexpanded.def<B.doXMLelementE*
% .ifcase.XMLtokensreduction
@@ -320,14 +323,14 @@
% E
%
% .gdef.activateXMLescapetokens
-% B.catcode`.$=.@@active
-% .catcode`.%=.@@active
-% .catcode`.\=.@@active
-% .catcode`.^=.@@active
-% .catcode`._=.@@active
-% .catcode`.{=.@@active
-% .catcode`.}=.@@active
-% .catcode`.|=.@@active
+% B.catcode`.$=.activecatcode
+% .catcode`.%=.activecatcode
+% .catcode`.\=.activecatcode
+% .catcode`.^=.activecatcode
+% .catcode`._=.activecatcode
+% .catcode`.{=.activecatcode
+% .catcode`.}=.activecatcode
+% .catcode`.|=.activecatcode
% E
%
% .xdef.entitleXMLescapetokens
@@ -357,29 +360,29 @@
% E
%
% .gdef.ignoreXMLescapetokens
-% B.catcode`.$=.@@other
-% .catcode`.%=.@@other
-% .catcode`.\=.@@other
-% .catcode`.^=.@@other
-% .catcode`._=.@@other
-% .catcode`.{=.@@other
-% .catcode`.}=.@@other
-% .catcode`.|=.@@other
+% B.catcode`.$=.othercatcode
+% .catcode`.%=.othercatcode
+% .catcode`.\=.othercatcode
+% .catcode`.^=.othercatcode
+% .catcode`._=.othercatcode
+% .catcode`.{=.othercatcode
+% .catcode`.}=.othercatcode
+% .catcode`.|=.othercatcode
% E
%
% * The following macro can be invokes when reading from
% * an auxiliary file.
%
% .unexpanded.gdef.enableXMLelements
-% B.catcode60=.@@active * .catcode`.<=.@@active
-% .catcode62=.@@other * .catcode`.>=.@@other
+% B.catcode60=.activecatcode * .catcode`.<=.activecatcode
+% .catcode62=.othercatcode * .catcode`.>=.other
% .unexpanded.def<B.doXMLelementE*
% .processingXMLtrue
% E
%
% .unexpanded.gdef.disableXMLelements
-% B.catcode60=.@@active * .catcode`.<=.@@active
-% .catcode62=.@@other * .catcode`.>=.@@other
+% B.catcode60=.activecatcode * .catcode`.<=.activecatcode
+% .catcode62=.othercatcode * .catcode`.>=.othercatcode
% .let<.relax * new
% .processingXMLfalse
% E
@@ -473,14 +476,14 @@
\let&\doXMLentity}
\unexpanded\gdef\enableXMLelements
- {\catcode60=\@@active
- \catcode62=\@@other
+ {\catcode60=\activecatcode
+ \catcode62=\othercatcode
\unexpanded\def<{\doXMLelement}%
\processingXMLtrue}
\unexpanded\gdef\disableXMLelements
- {\catcode60=\@@active
- \catcode62=\@@other
+ {\catcode60=\activecatcode
+ \catcode62=\othercatcode
\let<\relax
\processingXMLfalse}
@@ -1835,7 +1838,7 @@
%D definitions so that the mappings will run as fast as
%D possible.
-\bgroup \catcode`<=\@@active
+\bgroup \catcode`<=\activecatcode
\long\gdef\dododefineXMLsingular#1#2%
{\long\@EA\def\csname\@@XMLelement:#1/\endcsname{#2}}
@@ -2672,7 +2675,7 @@
%D Used in x-fo: I really need to document this!
-\bgroup \catcode`\<=\active
+\bgroup \catcode`\<=\activecatcode
% usage: \expanded{\rescanXMLatttributes{fo:table-cell}}
@@ -2691,7 +2694,7 @@
\def\XMLprocess#1%
{\begingroup\enableXML\XMLflush{#1}\endgroup}
-\bgroup \catcode`<=\@@active
+\bgroup \catcode`<=\activecatcode
\long\gdef\ignoreuntilXMLelement#1<{<}
\long\gdef\grabuntilXMLelement #1<\to#2{\def#2{#1}<}
@@ -2764,7 +2767,7 @@
\catcode\endoflineasciicode\spacecatcode
\catcode\formfeedasciicode \spacecatcode
\catcode\endoffileasciicode\spacecatcode
- \catcode`\#\@@other}
+ \catcode`\#\othercatcode}
\long\def\startXMLcode
{\begingroup
@@ -2904,7 +2907,7 @@
\newtoks\groupedtoks
\newif\ifcollectXMLgrouped
-\bgroup \catcode`\<=\@@active
+\bgroup \catcode`\<=\activecatcode
\newtoks\XMLgtoks
@@ -2995,8 +2998,8 @@
\bgroup
-\catcode`\<\active
-\catcode`\&\active
+\catcode`\<\activecatcode
+\catcode`\&\activecatcode
\gdef\flattenXMLcontent#1% we need taco's 'over one group'
{\begingroup
diff --git a/Master/texmf-dist/tex/context/base/xtag-map.mkii b/Master/texmf-dist/tex/context/base/xtag-map.mkii
index cbde4f1b175..4f639bf0183 100644
--- a/Master/texmf-dist/tex/context/base/xtag-map.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-map.mkii
@@ -5,7 +5,7 @@
%D subtitle=Remapping,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -459,9 +459,9 @@
\let\par\endgraf
\popmacro\doXMLentity % needed ?
\disableXMLexpansion
- \catcode`\{=\@@begingroup
- \catcode`\}=\@@endgroup
- \catcode`\\=\@@escape
+ \catcode`\{=\begingroupcatcode
+ \catcode`\}=\endgroupcatcode
+ \catcode`\\=\escapecatcode
\iftraceXMLremapping
\ifmmode\vbox\fi\bgroup
\defconvertedcommand\ascii\remappedXMLdata
@@ -724,7 +724,7 @@
{\remapXMLsingular[\s!unknown][CPA]\doXMLunknownSI
\remapXMLsequence[\s!unknown][CPA]\doXMLunknownSE}
-\bgroup \catcode`<=\active
+\bgroup \catcode`<=\activecatcode
\gdef\revertXMLremapping
{\gdef\doXMLunknownSE##1##2{<##1>##2</##1>}%
diff --git a/Master/texmf-dist/tex/context/base/xtag-mmc.mkii b/Master/texmf-dist/tex/context/base/xtag-mmc.mkii
index 27e2c42ea4b..9da7fef8411 100644
--- a/Master/texmf-dist/tex/context/base/xtag-mmc.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-mmc.mkii
@@ -5,7 +5,7 @@
%D subtitle=Content MathML,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-mml.mkii b/Master/texmf-dist/tex/context/base/xtag-mml.mkii
index 051d15b0078..f948128fa5e 100644
--- a/Master/texmf-dist/tex/context/base/xtag-mml.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-mml.mkii
@@ -5,7 +5,7 @@
%D subtitle=MathML,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-mmp.mkii b/Master/texmf-dist/tex/context/base/xtag-mmp.mkii
index 75167c9e90c..93f0a1504db 100644
--- a/Master/texmf-dist/tex/context/base/xtag-mmp.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-mmp.mkii
@@ -5,7 +5,7 @@
%D subtitle=Presentation MathML,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-pml.mkii b/Master/texmf-dist/tex/context/base/xtag-pml.mkii
index 53d22c52af0..a0930b63428 100644
--- a/Master/texmf-dist/tex/context/base/xtag-pml.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-pml.mkii
@@ -5,7 +5,7 @@
%D subtitle=Physics ML,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-pmu.mkii b/Master/texmf-dist/tex/context/base/xtag-pmu.mkii
index b913475f5e8..5c7c9a8f61a 100644
--- a/Master/texmf-dist/tex/context/base/xtag-pmu.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-pmu.mkii
@@ -5,7 +5,7 @@
%D subtitle=Units,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-pre.mkii b/Master/texmf-dist/tex/context/base/xtag-pre.mkii
index 94a213d941b..63706d64c3a 100644
--- a/Master/texmf-dist/tex/context/base/xtag-pre.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-pre.mkii
@@ -5,7 +5,7 @@
%D subtitle=Predefined Things,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-prs.mkii b/Master/texmf-dist/tex/context/base/xtag-prs.mkii
index 02bdcf21c1c..8728d992a47 100644
--- a/Master/texmf-dist/tex/context/base/xtag-prs.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-prs.mkii
@@ -5,7 +5,7 @@
%D subtitle=Parsing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-raw.mkii b/Master/texmf-dist/tex/context/base/xtag-raw.mkii
index e6dfdea4174..aab294c5adb 100644
--- a/Master/texmf-dist/tex/context/base/xtag-raw.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-raw.mkii
@@ -5,7 +5,7 @@
%D subtitle=Raw Specials,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-rng.mkii b/Master/texmf-dist/tex/context/base/xtag-rng.mkii
index 254282424b5..4b9dcfaf156 100644
--- a/Master/texmf-dist/tex/context/base/xtag-rng.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-rng.mkii
@@ -5,7 +5,7 @@
%D subtitle=Relax NG,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-run.mkii b/Master/texmf-dist/tex/context/base/xtag-run.mkii
index 03526810455..65424650c0f 100644
--- a/Master/texmf-dist/tex/context/base/xtag-run.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-run.mkii
@@ -5,7 +5,7 @@
%D subtitle=Visualization,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -19,31 +19,31 @@
\bgroup
-\catcode`\.=\@@escape
-.catcode`.B=.@@begingroup
-.catcode`.E=.@@endgroup
-.catcode`.#=.@@active
-.catcode`.$=.@@active
-.catcode`.%=.@@active
-.catcode`.\=.@@active
-.catcode`.^=.@@active
-.catcode`._=.@@active
-.catcode`.{=.@@active
-.catcode`.}=.@@active
-.catcode`.|=.@@active
-.catcode`.~=.@@active
+\catcode`\.=\escapecatcode
+.catcode`.B=.begingroupcatcode
+.catcode`.E=.endgroupcatcode
+.catcode`.#=.activecatcode
+.catcode`.$=.activecatcode
+.catcode`.%=.activecatcode
+.catcode`.\=.activecatcode
+.catcode`.^=.activecatcode
+.catcode`._=.activecatcode
+.catcode`.{=.activecatcode
+.catcode`.}=.activecatcode
+.catcode`.|=.activecatcode
+.catcode`.~=.activecatcode
.gdef.verbatimXML
- B.catcode`.#=.@@active .let#.letterhash
- .catcode`.$=.@@active .let$.dollar
- .catcode`.%=.@@active .let%.percent
- .catcode`.\=.@@active .let\.letterbackslash
- .catcode`.^=.@@active .let^.letterhat
- .catcode`._=.@@active .let_.letterunderscore
- .catcode`.{=.@@active .let{.leftargument
- .catcode`.}=.@@active .let}.rightargument
- .catcode`.|=.@@active .let|.letterbar
- .catcode`.~=.@@active .let~.lettertilde
+ B.catcode`.#=.activecatcode .let#.letterhash
+ .catcode`.$=.activecatcode .let$.dollar
+ .catcode`.%=.activecatcode .let%.percent
+ .catcode`.\=.activecatcode .let\.letterbackslash
+ .catcode`.^=.activecatcode .let^.letterhat
+ .catcode`._=.activecatcode .let_.letterunderscore
+ .catcode`.{=.activecatcode .let{.leftargument
+ .catcode`.}=.activecatcode .let}.rightargument
+ .catcode`.|=.activecatcode .let|.letterbar
+ .catcode`.~=.activecatcode .let~.lettertilde
E
.egroup
@@ -61,10 +61,10 @@
\bgroup
-\@EA\catcode\string`=\@@active
-\@EA\catcode\string`"\@@active
-\@EA\catcode\string``\@@active
-\@EA\catcode\string`&\@@active
+\@EA\catcode\string`=\activecatcode
+\@EA\catcode\string`"\activecatcode
+\@EA\catcode\string``\activecatcode
+\@EA\catcode\string`&\activecatcode
\gdef\doshowXMLargument#1#2#3#4%
{\hskip\zeropoint % or maybe \allowbreak
@@ -74,10 +74,10 @@
{\hskip\zeropoint % or maybe \allowbreak
\ifshowXMLarguments
\bgroup
- \@EA\catcode\string`=\@@active
- \@EA\catcode\string`"\@@active
- \@EA\catcode\string``\@@active
- \@EA\catcode\string`&\@@active
+ \@EA\catcode\string`=\activecatcode
+ \@EA\catcode\string`"\activecatcode
+ \@EA\catcode\string``\activecatcode
+ \@EA\catcode\string`&\activecatcode
\def={\color[xtag:7]{\string=}}%
\def"##1"{\doshowXMLargument""8{##1}}%
\def`##1`{\doshowXMLargument``8{##1}}%
diff --git a/Master/texmf-dist/tex/context/base/xtag-stk.mkii b/Master/texmf-dist/tex/context/base/xtag-stk.mkii
index e126ae5c74a..d454a63ca8d 100644
--- a/Master/texmf-dist/tex/context/base/xtag-stk.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-stk.mkii
@@ -5,7 +5,7 @@
%D subtitle=Stacking Data,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-utf.mkii b/Master/texmf-dist/tex/context/base/xtag-utf.mkii
index fec84d27984..b58fbbe88b6 100644
--- a/Master/texmf-dist/tex/context/base/xtag-utf.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-utf.mkii
@@ -5,7 +5,7 @@
%D subtitle=UTF,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-xsd.mkii b/Master/texmf-dist/tex/context/base/xtag-xsd.mkii
index 96169afa2ee..c1f4b91b649 100644
--- a/Master/texmf-dist/tex/context/base/xtag-xsd.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-xsd.mkii
@@ -5,7 +5,7 @@
%D subtitle=Schemas,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/context/base/xtag-xsl.mkii b/Master/texmf-dist/tex/context/base/xtag-xsl.mkii
index 3ad096c280a..49767e30c79 100644
--- a/Master/texmf-dist/tex/context/base/xtag-xsl.mkii
+++ b/Master/texmf-dist/tex/context/base/xtag-xsl.mkii
@@ -5,7 +5,7 @@
%D subtitle=XSLT processing,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
@@ -41,7 +41,7 @@
\def\obeyXSLTcharacters
{\setnaturalcatcodes
- \catcode`\\=\@@escape}
+ \catcode`\\=\escapecatcode}
\long\def\startXSLTscript #1 #2 %
{\bgroup
diff --git a/Master/texmf-dist/tex/context/fonts/antykwapoltawskiego.lfg b/Master/texmf-dist/tex/context/fonts/antykwapoltawskiego.lfg
index d5c902c6bf0..794b9f4079c 100644
--- a/Master/texmf-dist/tex/context/fonts/antykwapoltawskiego.lfg
+++ b/Master/texmf-dist/tex/context/fonts/antykwapoltawskiego.lfg
@@ -1,5 +1,5 @@
return {
- name = "antykwapoltawskiego",
+ name = "antykwa-poltawskiego",
version = "1.00",
comment = "Goodies that complement Antykwa Poltawskiego, one of Mojca's favourites",
author = "Hans & Mojca",
diff --git a/Master/texmf-dist/tex/context/fonts/asana-math.lfg b/Master/texmf-dist/tex/context/fonts/asana-math.lfg
index f845ca4dee1..2c13600c198 100644
--- a/Master/texmf-dist/tex/context/fonts/asana-math.lfg
+++ b/Master/texmf-dist/tex/context/fonts/asana-math.lfg
@@ -14,9 +14,22 @@ local function patch(data,filename,threshold)
end
end
-patches.register("after","check math parameters","asana",function(data,filename) patch(data,filename,1350) end)
+patches.register("after","analyze math","asana",function(data,filename) patch(data,filename,1350) end)
+
+local function less(value,target,original)
+ -- officially we should check the original
+ return 0.25 * value
+end
+
+local function more(value,target,original)
+ local o = original.mathparameters.DisplayOperatorMinHeight
+ if o < 2800 then
+ return 2800 * target.parameters.factor
+ else
+ return value -- already scaled
+ end
+end
-local function less(value,target,original) return 0.25 * value end
return {
name = "asana-math",
@@ -26,6 +39,7 @@ return {
copyright = "ConTeXt development team",
mathematics = {
parameters = {
+ DisplayOperatorMinHeight = more,
-- StackBottomDisplayStyleShiftDown = 0,
-- StackBottomShiftDown = 0,
-- StackDisplayStyleGapMin = 0,
diff --git a/Master/texmf-dist/tex/context/fonts/cambria-math.lfg b/Master/texmf-dist/tex/context/fonts/cambria-math.lfg
index 3fd15d8a03d..6415069e66e 100644
--- a/Master/texmf-dist/tex/context/fonts/cambria-math.lfg
+++ b/Master/texmf-dist/tex/context/fonts/cambria-math.lfg
@@ -1,6 +1,11 @@
-- This patch code is moved from font-pat.lua to this goodies
-- files as it does not belong in the core code.
+-- This is a fix to the font itself i.e. the cached instance will
+-- be patched. When the goodie file is loaded the patch will be
+-- added to the patch list. No goodies setting is needed with
+-- the filename.
+
local patches = fonts.handlers.otf.enhancers.patches
local function patch(data,filename,threshold)
@@ -14,8 +19,21 @@ local function patch(data,filename,threshold)
end
end
-patches.register("after","check math parameters","cambria", function(data,filename) patch(data,filename,2800) end)
-patches.register("after","check math parameters","cambmath",function(data,filename) patch(data,filename,2800) end)
+patches.register("after","analyze math","cambria", function(data,filename) patch(data,filename,2800) end)
+patches.register("after","analyze math","cambmath",function(data,filename) patch(data,filename,2800) end)
+
+-- This is a runtime fix, but then we need to explicitly set
+-- the goodies parameter for the font. As a demonstration we
+-- we do both.
+
+local function FixDisplayOperatorMinHeight(value,target,original)
+ local o = original.mathparameters.DisplayOperatorMinHeight
+ if o < 2800 then
+ return 2800 * target.parameters.factor
+ else
+ return value -- already scaled
+ end
+end
return {
name = "cambria-math",
@@ -23,4 +41,9 @@ return {
comment = "Goodies that complement cambria.",
author = "Hans Hagen",
copyright = "ConTeXt development team",
+ mathematics = {
+ parameters = {
+ DisplayOperatorMinHeight = FixDisplayOperatorMinHeight,
+ }
+ }
}
diff --git a/Master/texmf-dist/tex/context/fonts/demo.lfg b/Master/texmf-dist/tex/context/fonts/demo.lfg
index 6c7f6b62d39..00ca3ee6e73 100644
--- a/Master/texmf-dist/tex/context/fonts/demo.lfg
+++ b/Master/texmf-dist/tex/context/fonts/demo.lfg
@@ -1,3 +1,5 @@
+-- see test suite: goodies-002.tex
+
local yes = "yes"
local default = {
@@ -12,7 +14,7 @@ local smallcaps = {
}
local function statistics(tfmdata)
- commands.showfontparameters
+ commands.showfontparameters(tfmdata)
end
local function squeeze(tfmdata)
@@ -24,7 +26,7 @@ end
return {
name = "demo",
- version = "1.00",
+ version = "1.01",
comment = "An example of goodies.",
author = "Hans Hagen",
featuresets = {
@@ -43,7 +45,17 @@ return {
[2] = {
"two", "four", "six", "eight", "ten",
},
- }
+ },
+ all = {
+ [1] = {
+ "*",
+ },
+ },
+ some = {
+ [1] = {
+ "0x0030:0x0035",
+ },
+ },
},
postprocessors = {
statistics = statistics,
diff --git a/Master/texmf-dist/tex/context/fonts/lm-math.lfg b/Master/texmf-dist/tex/context/fonts/lm-math.lfg
index 43de0c51ef1..a2c095bc2b5 100644
--- a/Master/texmf-dist/tex/context/fonts/lm-math.lfg
+++ b/Master/texmf-dist/tex/context/fonts/lm-math.lfg
@@ -1,33 +1,38 @@
--- This patch code is moved from font-pat.lua to this goodies
--- files as it does not belomg in the core code.
-
-local patches = fonts.handlers.otf.enhancers.patches
+-- we could consider taking more from 'tex-mr-missing'
-local function patch(data,filename)
- local uni_to_ind = data.map.map
- if not uni_to_ind[0x391] then
- -- beware, this is a hack, features for latin often don't apply to greek
- -- but lm has not much features anyway (and only greek for math)
- patches.report("adding 13 greek capitals")
- uni_to_ind[0x391] = uni_to_ind[0x41]
- uni_to_ind[0x392] = uni_to_ind[0x42]
- uni_to_ind[0x395] = uni_to_ind[0x45]
- uni_to_ind[0x397] = uni_to_ind[0x48]
- uni_to_ind[0x399] = uni_to_ind[0x49]
- uni_to_ind[0x39A] = uni_to_ind[0x4B]
- uni_to_ind[0x39C] = uni_to_ind[0x4D]
- uni_to_ind[0x39D] = uni_to_ind[0x4E]
- uni_to_ind[0x39F] = uni_to_ind[0x4F]
- uni_to_ind[0x3A1] = uni_to_ind[0x52]
- uni_to_ind[0x3A4] = uni_to_ind[0x54]
- uni_to_ind[0x3A7] = uni_to_ind[0x58]
- uni_to_ind[0x396] = uni_to_ind[0x5A]
- end
-end
+-- This patch code is moved from font-pat.lua to this goodies
+-- files as it does not belong in the core code.
-patches.register("after","prepare glyphs","^lmroman", patch)
-patches.register("after","prepare glyphs","^lmsans", patch)
-patches.register("after","prepare glyphs","^lmtypewriter",patch)
+-- This patch is no longer needed but we keep it commented as
+-- it is an example.
+--
+-- local patches = fonts.handlers.otf.enhancers.patches
+--
+-- local function patch(data,filename)
+-- local uni_to_ind = data.map.map
+-- if not uni_to_ind[0x391] then
+-- -- beware, this is a hack, features for latin often don't apply to greek
+-- -- but lm has not much features anyway (and only greek for math)
+-- patches.report("adding 13 greek capitals")
+-- uni_to_ind[0x391] = uni_to_ind[0x41]
+-- uni_to_ind[0x392] = uni_to_ind[0x42]
+-- uni_to_ind[0x395] = uni_to_ind[0x45]
+-- uni_to_ind[0x397] = uni_to_ind[0x48]
+-- uni_to_ind[0x399] = uni_to_ind[0x49]
+-- uni_to_ind[0x39A] = uni_to_ind[0x4B]
+-- uni_to_ind[0x39C] = uni_to_ind[0x4D]
+-- uni_to_ind[0x39D] = uni_to_ind[0x4E]
+-- uni_to_ind[0x39F] = uni_to_ind[0x4F]
+-- uni_to_ind[0x3A1] = uni_to_ind[0x52]
+-- uni_to_ind[0x3A4] = uni_to_ind[0x54]
+-- uni_to_ind[0x3A7] = uni_to_ind[0x58]
+-- uni_to_ind[0x396] = uni_to_ind[0x5A]
+-- end
+-- end
+--
+-- patches.register("after","prepare glyphs","^lmroman", patch)
+-- patches.register("after","prepare glyphs","^lmsans", patch)
+-- patches.register("after","prepare glyphs","^lmtypewriter",patch)
-- rm-lmr5 : LMMathRoman5-Regular
-- rm-lmbx5 : LMMathRoman5-Bold ]
@@ -179,33 +184,13 @@ local ten = {
{ name = "eufb10.tfm", vector = "tex-fraktur-bold", optional=true },
}
-local ten_bold = {
- { name = "lmroman10-bold.otf", features = "virtualmath", main = true },
- { name = "rm-lmr10.tfm", vector = "tex-mr-missing" } ,
- { name = "lmmib10.tfm", vector = "tex-mi", skewchar=0x7F },
- { name = "lmmib10.tfm", vector = "tex-it", skewchar=0x7F },
- { name = "lmbsy10.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } ,
- { name = "lmex10.tfm", vector = "tex-ex", extension = true } ,
--- copied from roman:
- { name = "msam10.tfm", vector = "tex-ma" },
- { name = "msbm10.tfm", vector = "tex-mb" },
- { name = "stmary10.afm", vector = "tex-mc" },
- -- { name = "rm-lmbx10.tfm", vector = "tex-bf" } ,
- { name = "lmroman10-bold.otf", vector = "tex-bf" } ,
- { name = "lmmib10.tfm", vector = "tex-bi", skewchar=0x7F } ,
- { name = "lmsans10-regular.otf", vector = "tex-ss", optional=true },
- { name = "lmmono10-regular.otf", vector = "tex-tt", optional=true },
- { name = "eufm10.tfm", vector = "tex-fraktur", optional=true },
- { name = "eufb10.tfm", vector = "tex-fraktur-bold", optional=true },
-}
-
-- rm-lmr12 : LMMathRoman12-Regular
-- rm-lmbx12 : LMMathRoman12-Bold
-- lmmi12 : LMMathItalic12-Italic
local twelve = {
{ name = "lmroman12-regular.otf", features = "virtualmath", main = true },
- { name = "rm-lmr12.tfm", vector = "tex-mr-missing" } ,
+ { name = "rm-lmr12.tfm", vector = "tex-mr-missing" },
{ name = "lmmi12.tfm", vector = "tex-mi", skewchar=0x7F },
{ name = "lmmi12.tfm", vector = "tex-it", skewchar=0x7F },
{ name = "lmsy10.tfm", vector = "tex-sy", skewchar=0x30, parameters = true } ,
@@ -256,15 +241,14 @@ return {
"mkiv-base.map",
},
virtuals = {
- ["lmroman5-math"] = five,
- ["lmroman6-math"] = six,
- ["lmroman7-math"] = seven,
- ["lmroman8-math"] = eight,
- ["lmroman9-math"] = nine,
- ["lmroman10-math"] = ten,
- ["lmroman10-boldmath"] = ten_bold,
- ["lmroman12-math"] = twelve,
- ["lmroman17-math"] = seventeen,
+ ["lmroman5-math"] = five,
+ ["lmroman6-math"] = six,
+ ["lmroman7-math"] = seven,
+ ["lmroman8-math"] = eight,
+ ["lmroman9-math"] = nine,
+ ["lmroman10-math"] = ten,
+ ["lmroman12-math"] = twelve,
+ ["lmroman17-math"] = seventeen,
},
variables = {
joinrelfactor = 3, -- default anyway
diff --git a/Master/texmf-dist/tex/context/fonts/lm.lfg b/Master/texmf-dist/tex/context/fonts/lm.lfg
new file mode 100644
index 00000000000..406902ef2bc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/fonts/lm.lfg
@@ -0,0 +1,199 @@
+return {
+ name = "latin modern",
+ version = "1.00",
+ comment = "Goodies that complement latin modern.",
+ author = "Hans Hagen",
+ copyright = "ConTeXt development team",
+ mathematics = {
+ tweaks = {
+ aftercopying = {
+ mathematics.tweaks.fixbadprime, -- prime is too low
+ },
+ },
+ },
+ designsizes = {
+ ["LMMathRoman-Regular"] = {
+ ["4pt"] = "LMMath5-Regular@lmroman5-math",
+ ["5pt"] = "LMMath5-Regular@lmroman5-math",
+ ["6pt"] = "LMMath6-Regular@lmroman6-math",
+ ["7pt"] = "LMMath7-Regular@lmroman7-math",
+ ["8pt"] = "LMMath8-Regular@lmroman8-math",
+ ["9pt"] = "LMMath9-Regular@lmroman9-math",
+ ["10pt"] = "LMMath10-Regular@lmroman10-math",
+ ["11pt"] = "LMMath10-Regular@lmroman10-math",
+ ["12pt"] = "LMMath12-Regular@lmroman12-math",
+ default = "LMMath10-Regular@lmroman10-math"
+ },
+ ["LMMathRoman-Bold"] = { -- not yet ready
+ ["4pt"] = "LMMath5-Regular@lmroman5-math",
+ ["5pt"] = "LMMath5-Regular@lmroman5-math",
+ ["6pt"] = "LMMath6-Regular@lmroman6-math",
+ ["7pt"] = "LMMath7-Regular@lmroman7-math",
+ ["8pt"] = "LMMath8-Regular@lmroman8-math",
+ ["9pt"] = "LMMath9-Regular@lmroman9-math",
+ ["10pt"] = "LMMath10-Regular@lmroman10-math",
+ ["11pt"] = "LMMath10-Regular@lmroman10-math",
+ ["12pt"] = "LMMath12-Regular@lmroman12-math",
+ default = "LMMath10-Regular@lmroman10-math"
+ },
+ ["LMRoman-Regular"] = {
+ ["4pt"] = "file:lmroman5-regular",
+ ["5pt"] = "file:lmroman5-regular",
+ ["6pt"] = "file:lmroman6-regular",
+ ["7pt"] = "file:lmroman7-regular",
+ ["8pt"] = "file:lmroman8-regular",
+ ["9pt"] = "file:lmroman9-regular",
+ ["10pt"] = "file:lmroman10-regular",
+ ["11pt"] = "file:lmroman10-regular",
+ ["12pt"] = "file:lmroman12-regular",
+ default = "file:lmroman10-regular",
+ },
+ ["LMRoman-Bold"] = {
+ ["4pt"] = "file:lmroman5-bold",
+ ["5pt"] = "file:lmroman5-bold",
+ ["6pt"] = "file:lmroman6-bold",
+ ["7pt"] = "file:lmroman7-bold",
+ ["8pt"] = "file:lmroman8-bold",
+ ["9pt"] = "file:lmroman9-bold",
+ ["10pt"] = "file:lmroman10-bold",
+ ["11pt"] = "file:lmroman10-bold",
+ ["12pt"] = "file:lmroman12-bold",
+ default = "file:lmroman10-bold",
+ },
+ ["LMRoman-Demi"] = {
+ default = "file:lmromandemi10-regular",
+ },
+ ["LMRoman-Italic"] = {
+ ["4pt"] = "file:lmroman7-italic",
+ ["5pt"] = "file:lmroman7-italic",
+ ["6pt"] = "file:lmroman7-italic",
+ ["7pt"] = "file:lmroman7-italic",
+ ["8pt"] = "file:lmroman8-italic",
+ ["9pt"] = "file:lmroman9-italic",
+ ["10pt"] = "file:lmroman10-italic",
+ ["11pt"] = "file:lmroman10-italic",
+ ["12pt"] = "file:lmroman12-italic",
+ default = "file:lmroman10-italic",
+ },
+ ["LMRoman-Oblique"] = {
+ ["4pt"] = "file:lmromanslant8-regular",
+ ["5pt"] = "file:lmromanslant8-regular",
+ ["6pt"] = "file:lmromanslant8-regular",
+ ["7pt"] = "file:lmromanslant8-regular",
+ ["8pt"] = "file:lmromanslant8-regular",
+ ["9pt"] = "file:lmromanslant9-regular",
+ ["10pt"] = "file:lmromanslant10-regular",
+ ["11pt"] = "file:lmromanslant10-regular",
+ ["12pt"] = "file:lmromanslant12-regular",
+ default = "file:lmromanslant10-regular",
+ },
+ ["LMRoman-BoldItalic"] = {
+ default = "file:lmroman10-bolditalic",
+ },
+ ["LMRoman-BoldOblique"] = {
+ default = "file:lmromanslant10-bold",
+ },
+ ["LMRoman-DemiOblique"] = {
+ default = "file:lmromandemi10-oblique",
+ },
+ ["LMRoman-CapsRegular"] = {
+ default = "file:lmromancaps10-regular",
+ },
+ ["LMRoman-CapsOblique"] = {
+ default = "file:lmromancaps10-oblique",
+ },
+ ["LMRoman-Dunhill"] = {
+ default = "file:lmromandunh10-regular",
+ },
+ ["LMRoman-DunhillOblique"] = {
+ default = "file:lmromandunh10-oblique",
+ },
+ ["LMRoman-Unslanted"] = {
+ default = "file:lmromanunsl10-regular",
+ },
+ ["LMSans-Regular"] = {
+ ["8pt"] = "file:lmsans8-regular",
+ ["9pt"] = "file:lmsans9-regular",
+ ["10pt"] = "file:lmsans10-regular",
+ ["11pt"] = "file:lmsans10-regular",
+ ["12pt"] = "file:lmsans12-regular",
+ default = "file:lmsans10-regular",
+ },
+ ["LMSans-Oblique"] = {
+ ["8pt"] = "file:lmsans8-oblique",
+ ["9pt"] = "file:lmsans9-oblique",
+ ["10pt"] = "file:lmsans10-oblique",
+ ["11pt"] = "file:lmsans10-oblique",
+ ["12pt"] = "file:lmsans12-oblique",
+ default = "file:lmsans10-oblique",
+ },
+ ["LMSans-Bold"] = {
+ default = "file:lmsans10-bold",
+ },
+ ["LMSans-BoldOblique"] = {
+ default = "file:lmsans10-boldoblique",
+ },
+ ["LMSans-DemiCondensed"] = {
+ default = "file:lmsansdemicond10-regular",
+ },
+ ["LMSans-DemiCondensedOblique"] = {
+ default = "file:lmsansdemicond10-oblique",
+ },
+ ["LMTypewriter-Regular"] = {
+ ["8pt"] = "file:lmmono8-regular",
+ ["9pt"] = "file:lmmono9-regular",
+ ["10pt"] = "file:lmmono10-regular",
+ ["11pt"] = "file:lmmono10-regular",
+ ["12pt"] = "file:lmmono12-regular",
+ default = "file:lmmono10-regular",
+ },
+ ["LMTypewriter-Light"] = {
+ default = "file:lmmonolt10-regular",
+ },
+ ["LMTypewriter-Dark"] = {
+ default = "file:lmmonolt10-bold",
+ },
+ ["LMTypewriter-Italic"] = {
+ default = "file:lmmono10-italic",
+ },
+ ["LMTypewriter-LightOblique"] = {
+ default = "file:lmmonolt10-oblique",
+ },
+ ["LMTypewriter-Oblique"] = {
+ default = "file:lmmonoslant10-regular",
+ },
+ ["LMTypewriter-DarkOblique"] = {
+ default = "file:lmmonolt10-boldoblique",
+ },
+ ["LMTypewriter-LightCondensed"] = {
+ default = "file:lmmonoltcond10-regular",
+ },
+ ["LMTypewriter-LightCondensedOblique"] = {
+ default = "file:lmmonoltcond10-oblique",
+ },
+ ["LMTypewriterVarWd-Regular"] = {
+ default = "file:lmmonoproplt10-regular",
+ },
+ ["LMTypewriterVarWd-Oblique"] = {
+ default = "file:lmmonoproplt10-oblique",
+ },
+ ["LMTypewriterVarWd-Light"] = {
+ default = "file:lmmonoprop10-regular",
+ },
+ ["LMTypewriterVarWd-LightOblique"] = {
+ default = "file:lmmonoprop10-oblique",
+ },
+ ["LMTypewriterVarWd-Dark"] = {
+ default = "file:lmmonoproplt10-bold",
+ },
+ ["LMTypewriterVarWd-DarkOblique"] = {
+ default = "file:lmmonoproplt10-boldoblique",
+ },
+ ["LMTypewriter-CapsRegular"] = {
+ default = "file:lmmonocaps10-regular",
+ },
+ ["LMTypewriter-CapsOblique"] = {
+ default = "file:lmmonocaps10-oblique",
+ },
+ }
+}
diff --git a/Master/texmf-dist/tex/context/fonts/lucida-opentype-math.lfg b/Master/texmf-dist/tex/context/fonts/lucida-opentype-math.lfg
new file mode 100644
index 00000000000..38d54eee325
--- /dev/null
+++ b/Master/texmf-dist/tex/context/fonts/lucida-opentype-math.lfg
@@ -0,0 +1,12 @@
+return {
+ name = "lucida-opentype-math",
+ version = "1.00",
+ comment = "Goodies that complement lucida opentype.",
+ author = "Hans Hagen",
+ copyright = "ConTeXt development team",
+ mathematics = {
+ alternates = {
+ italic = { feature = 'ss01', value = 1, comment = "Mathematical Alternative Italic" },
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/fonts/lucida-math.lfg b/Master/texmf-dist/tex/context/fonts/lucida-typeone-math.lfg
index 443f52acea2..82ba589cd48 100644
--- a/Master/texmf-dist/tex/context/fonts/lucida-math.lfg
+++ b/Master/texmf-dist/tex/context/fonts/lucida-typeone-math.lfg
@@ -225,6 +225,8 @@ mathencodings["lbr-mb"] = {
[0x022CC] = 0xD1, -- rightthreetimes
[0x022D6] = 0xDC, -- lessdot
[0x022D7] = 0xDD, -- gtrdot
+ [0x022D8] = 0xDE, -- lll
+ [0x022D9] = 0xDF, -- ggg
[0x022DA] = 0xE8, -- lesseqgtr
[0x022DB] = 0xE9, -- gtreqless
[0x022DE] = 0xE6, -- curlyeqprec
@@ -268,6 +270,7 @@ mathencodings["lbr-sy"] = {
[0x02235] = 0x91, -- because
[0x0223D] = 0x24, -- backsim
[0x02242] = 0x99, -- eqsim
+ [0x02245] = 0x9B, -- cong
[0x0224A] = 0x9D, -- approxeq
[0x0224E] = 0xC7, -- Bumpeq
[0x02252] = 0xCB, -- fallingdotseq
@@ -328,6 +331,9 @@ return {
{ name = "hlcrv.tfm", vector = "tex-ex", extension = true },
{ name = "hlcra.tfm", vector = "lbr-ma" },
{ name = "hlcrm.tfm", vector = "lbr-mb" },
+ -- { name = "hlcrim.tfm", vector = "lbr-mb" }, -- LucidaNewMath-Italic <-> AltItalic
+ -- { name = "hlcdim.tfm", vector = "lbr-mb" }, -- LucidaNewMath-DemiItalic <-> AltDemiItalic
+ -- { name = "hlcrima.tfm", vector = "lbr-mb" }, -- LucidaNewMath-AltItalic <-> Italic
{ name = "file:lbd.afm", vector = "tex-bf" },
{ name = "file:lbdi.afm", vector = "tex-bi" } ,
{ name = "file:lsr.afm", vector = "tex-ss" },
diff --git a/Master/texmf-dist/tex/context/fonts/px-math.lfg b/Master/texmf-dist/tex/context/fonts/px-math.lfg
index 1d18bad361a..afb0270a202 100644
--- a/Master/texmf-dist/tex/context/fonts/px-math.lfg
+++ b/Master/texmf-dist/tex/context/fonts/px-math.lfg
@@ -11,6 +11,7 @@ return {
virtuals = {
["px-math"] = {
{ name = "texgyrepagella-regular.otf", features = "virtualmath", main = true },
+ { name = "texgyrepagella-regular.otf", features = "virtualmath", vector = "tex-mr-missing" } ,
{ name = "rpxr.tfm", vector = "tex-mr" } ,
{ name = "rpxmi.tfm", vector = "tex-mi", skewchar=0x7F },
{ name = "rpxpplri.tfm", vector = "tex-it", skewchar=0x7F },
diff --git a/Master/texmf-dist/tex/context/fonts/tx-math.lfg b/Master/texmf-dist/tex/context/fonts/tx-math.lfg
index 8423aaaf4ab..2ad17348659 100644
--- a/Master/texmf-dist/tex/context/fonts/tx-math.lfg
+++ b/Master/texmf-dist/tex/context/fonts/tx-math.lfg
@@ -11,6 +11,7 @@ return {
virtuals = {
["tx-math"] = {
{ name = "texgyretermes-regular.otf", features = "virtualmath", main = true },
+ { name = "texgyretermes-regular.otf", features = "virtualmath", vector = "tex-mr-missing" },
{ name = "rtxr.tfm", vector = "tex-mr" } ,
{ name = "rtxptmri.tfm", vector = "tex-it", skewchar=0x7F },
{ name = "rtxmi.tfm", vector = "tex-mi", skewchar=0x7F },
diff --git a/Master/texmf-dist/tex/context/fonts/xits-math.lfg b/Master/texmf-dist/tex/context/fonts/xits-math.lfg
index a97a7599d9b..24ed2b0aaff 100644
--- a/Master/texmf-dist/tex/context/fonts/xits-math.lfg
+++ b/Master/texmf-dist/tex/context/fonts/xits-math.lfg
@@ -1,8 +1,21 @@
-- \setupbodyfont[xits]
--
--- \starttext
--- $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$
--- \stoptext
+-- $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$
+--
+-- \setupmathematics[italics=1] test $a;b;a; b; f;$ test\par % fontitalics
+-- \setupmathematics[italics=2] test $a;b;a; b; f;$ test\par % fontdata
+-- \setupmathematics[italics=3] test $a;b;a; b; f;$ test\par % quad based
+-- \setupmathematics[italics=4] test $a;b;a; b; f;$ test\par % combination of 1 and 3
+
+local italics = {
+ defaultfactor = 0.025,
+ disableengine = true,
+ corrections = {
+ -- [0x1D44E] = 0.99, -- a (fraction of quad)
+ -- [0x1D44F] = 100, -- b (font points)
+ [0x1D453] = -0.0375, -- f
+ }
+}
return {
name = "xits-math",
@@ -11,6 +24,9 @@ return {
author = "Hans Hagen",
copyright = "ConTeXt development team",
mathematics = {
+ italics = {
+ ["xits-math"] = italics,
+ },
alternates = {
cal = { feature = 'ss01', value = 1, comment = "Mathematical Calligraphic Alphabet" },
greekssup = { feature = 'ss02', value = 1, comment = "Mathematical Greek Sans Serif Alphabet" },
@@ -20,6 +36,7 @@ return {
mathbbit = { feature = 'ss06', value = 1, comment = "Mathematical Italic Double-Struck Alphabet" },
mathbbbi = { feature = 'ss07', value = 1, comment = "Mathematical Bold Italic Double-Struck Alphabet" },
upint = { feature = 'ss08', value = 1, comment = "Upright Integrals" },
- }
+ vertnot = { feature = 'ss09', value = 1, comment = "Negated Symbols With Vertical Stroke" },
+ },
}
}
diff --git a/Master/texmf-dist/tex/context/interface/cont-cs.xml b/Master/texmf-dist/tex/context/interface/cont-cs.xml
index a7b2466553d..bd7dadddf08 100644
--- a/Master/texmf-dist/tex/context/interface/cont-cs.xml
+++ b/Master/texmf-dist/tex/context/interface/cont-cs.xml
@@ -2,16 +2,18 @@
<!-- versions:
- comment : user interface definitions of ConTeXt
+ comment : user interface definitions of ConTeXt
- authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
+ authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
- versions : 2004.11.17 : initial version
- 2006.08.02 : define + resolve
+ versions : 2004.11.17 : initial version
+ 2006.08.02 : define + resolve
-->
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="cs" version="2006.08.02">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context test" language="cs" version="2006.08.02">
+
+ <!-- there are some more -->
<cd:define name="align">
<cd:constant type="uvnitr"/>
@@ -25,6 +27,10 @@
<cd:constant type="normalni"/>
<cd:constant type="ne"/>
<cd:constant type="ano"/>
+ <cd:constant type="siroky"/>
+ <cd:constant type="posledni"/>
+ <cd:constant type="r2l"/>
+ <cd:constant type="l2r"/>
</cd:define>
<cd:define name="symalign">
@@ -3269,9 +3275,9 @@
</cd:arguments>
</cd:command>
- <cd:command name="setupindentations" file="core-des.tex">
+ <cd:command name="setupindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="nastavodsazeni"/>
+ <cd:string value="setupindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1" optional="yes" list="yes">
@@ -3310,16 +3316,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="defineindenting" file="core-des.tex">
+ <cd:command name="defineindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="definujodsazovani"/>
+ <cd:string value="defineindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments n="2" list="yes">
- <cd:inherit name="nastavodsazeni" n="2"/>
+ <cd:inherit name="setupindentedtext" n="2"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -7230,16 +7236,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="pagetype" file="page-ini.tex">
+ <!-- cd:command name="pagetype" file="page-ini.tex">
<cd:sequence>
- <cd:string value="typstrany"/>
+ <cd:string value="pagetype"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
</cd:arguments>
- </cd:command>
+ </cd:command -->
<cd:command name="processpage" file="page-ini.tex">
<cd:sequence>
diff --git a/Master/texmf-dist/tex/context/interface/cont-de.xml b/Master/texmf-dist/tex/context/interface/cont-de.xml
index 61441dd9ca0..7b120082ef1 100644
--- a/Master/texmf-dist/tex/context/interface/cont-de.xml
+++ b/Master/texmf-dist/tex/context/interface/cont-de.xml
@@ -2,16 +2,18 @@
<!-- versions:
- comment : user interface definitions of ConTeXt
+ comment : user interface definitions of ConTeXt
- authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
+ authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
- versions : 2004.11.17 : initial version
- 2006.08.02 : define + resolve
+ versions : 2004.11.17 : initial version
+ 2006.08.02 : define + resolve
-->
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="de" version="2006.08.02">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context test" language="de" version="2006.08.02">
+
+ <!-- there are some more -->
<cd:define name="align">
<cd:constant type="innen"/>
@@ -25,6 +27,10 @@
<cd:constant type="normal"/>
<cd:constant type="nein"/>
<cd:constant type="ja"/>
+ <cd:constant type="breit"/>
+ <cd:constant type="letzte"/>
+ <cd:constant type="r2l"/>
+ <cd:constant type="l2r"/>
</cd:define>
<cd:define name="symalign">
@@ -3269,9 +3275,9 @@
</cd:arguments>
</cd:command>
- <cd:command name="setupindentations" file="core-des.tex">
+ <cd:command name="setupindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="stelleeinzuegein"/>
+ <cd:string value="setupindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1" optional="yes" list="yes">
@@ -3310,16 +3316,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="defineindenting" file="core-des.tex">
+ <cd:command name="defineindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="definiereeinzug"/>
+ <cd:string value="defineindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments n="2" list="yes">
- <cd:inherit name="stelleeinzuegein" n="2"/>
+ <cd:inherit name="setupindentedtext" n="2"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -7230,16 +7236,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="pagetype" file="page-ini.tex">
+ <!-- cd:command name="pagetype" file="page-ini.tex">
<cd:sequence>
- <cd:string value="seitentyp"/>
+ <cd:string value="pagetype"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
</cd:arguments>
- </cd:command>
+ </cd:command -->
<cd:command name="processpage" file="page-ini.tex">
<cd:sequence>
diff --git a/Master/texmf-dist/tex/context/interface/cont-en.xml b/Master/texmf-dist/tex/context/interface/cont-en.xml
index b532f2b219f..a20ac37da81 100644
--- a/Master/texmf-dist/tex/context/interface/cont-en.xml
+++ b/Master/texmf-dist/tex/context/interface/cont-en.xml
@@ -2,16 +2,18 @@
<!-- versions:
- comment : user interface definitions of ConTeXt
+ comment : user interface definitions of ConTeXt
- authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
+ authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
- versions : 2004.11.17 : initial version
- 2006.08.02 : define + resolve
+ versions : 2004.11.17 : initial version
+ 2006.08.02 : define + resolve
-->
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="en" version="2006.08.02">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context test" language="en" version="2006.08.02">
+
+ <!-- there are some more -->
<cd:define name="align">
<cd:constant type="inner"/>
@@ -25,6 +27,10 @@
<cd:constant type="normal"/>
<cd:constant type="no"/>
<cd:constant type="yes"/>
+ <cd:constant type="broad"/>
+ <cd:constant type="last"/>
+ <cd:constant type="r2l"/>
+ <cd:constant type="l2r"/>
</cd:define>
<cd:define name="symalign">
@@ -3269,9 +3275,9 @@
</cd:arguments>
</cd:command>
- <cd:command name="setupindentations" file="core-des.tex">
+ <cd:command name="setupindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="setupindentations"/>
+ <cd:string value="setupindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1" optional="yes" list="yes">
@@ -3310,16 +3316,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="defineindenting" file="core-des.tex">
+ <cd:command name="defineindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="defineindenting"/>
+ <cd:string value="defineindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments n="2" list="yes">
- <cd:inherit name="setupindentations" n="2"/>
+ <cd:inherit name="setupindentedtext" n="2"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -7230,7 +7236,7 @@
</cd:arguments>
</cd:command>
- <cd:command name="pagetype" file="page-ini.tex">
+ <!-- cd:command name="pagetype" file="page-ini.tex">
<cd:sequence>
<cd:string value="pagetype"/>
</cd:sequence>
@@ -7239,7 +7245,7 @@
<cd:constant type="cd:name"/>
</cd:keywords>
</cd:arguments>
- </cd:command>
+ </cd:command -->
<cd:command name="processpage" file="page-ini.tex">
<cd:sequence>
diff --git a/Master/texmf-dist/tex/context/interface/cont-fr.xml b/Master/texmf-dist/tex/context/interface/cont-fr.xml
index 615eda784ba..bfb5c82f475 100644
--- a/Master/texmf-dist/tex/context/interface/cont-fr.xml
+++ b/Master/texmf-dist/tex/context/interface/cont-fr.xml
@@ -2,16 +2,18 @@
<!-- versions:
- comment : user interface definitions of ConTeXt
+ comment : user interface definitions of ConTeXt
- authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
+ authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
- versions : 2004.11.17 : initial version
- 2006.08.02 : define + resolve
+ versions : 2004.11.17 : initial version
+ 2006.08.02 : define + resolve
-->
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="fr" version="2006.08.02">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context test" language="fr" version="2006.08.02">
+
+ <!-- there are some more -->
<cd:define name="align">
<cd:constant type="interieur"/>
@@ -25,6 +27,10 @@
<cd:constant type="normal"/>
<cd:constant type="non"/>
<cd:constant type="oui"/>
+ <cd:constant type="large"/>
+ <cd:constant type="dernier"/>
+ <cd:constant type="r2l"/>
+ <cd:constant type="l2r"/>
</cd:define>
<cd:define name="symalign">
@@ -3269,9 +3275,9 @@
</cd:arguments>
</cd:command>
- <cd:command name="setupindentations" file="core-des.tex">
+ <cd:command name="setupindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="reglealineas"/>
+ <cd:string value="setupindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1" optional="yes" list="yes">
@@ -3310,16 +3316,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="defineindenting" file="core-des.tex">
+ <cd:command name="defineindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="definitcompoalinea"/>
+ <cd:string value="defineindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments n="2" list="yes">
- <cd:inherit name="reglealineas" n="2"/>
+ <cd:inherit name="setupindentedtext" n="2"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -7230,16 +7236,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="pagetype" file="page-ini.tex">
+ <!-- cd:command name="pagetype" file="page-ini.tex">
<cd:sequence>
- <cd:string value="tapepage"/>
+ <cd:string value="pagetype"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
</cd:arguments>
- </cd:command>
+ </cd:command -->
<cd:command name="processpage" file="page-ini.tex">
<cd:sequence>
diff --git a/Master/texmf-dist/tex/context/interface/cont-it.xml b/Master/texmf-dist/tex/context/interface/cont-it.xml
index 5038f13ac83..2ede93e6917 100644
--- a/Master/texmf-dist/tex/context/interface/cont-it.xml
+++ b/Master/texmf-dist/tex/context/interface/cont-it.xml
@@ -2,16 +2,18 @@
<!-- versions:
- comment : user interface definitions of ConTeXt
+ comment : user interface definitions of ConTeXt
- authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
+ authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
- versions : 2004.11.17 : initial version
- 2006.08.02 : define + resolve
+ versions : 2004.11.17 : initial version
+ 2006.08.02 : define + resolve
-->
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="it" version="2006.08.02">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context test" language="it" version="2006.08.02">
+
+ <!-- there are some more -->
<cd:define name="align">
<cd:constant type="interno"/>
@@ -25,6 +27,10 @@
<cd:constant type="normale"/>
<cd:constant type="no"/>
<cd:constant type="si"/>
+ <cd:constant type="ampio"/>
+ <cd:constant type="ultimo"/>
+ <cd:constant type="r2l"/>
+ <cd:constant type="l2r"/>
</cd:define>
<cd:define name="symalign">
@@ -3269,9 +3275,9 @@
</cd:arguments>
</cd:command>
- <cd:command name="setupindentations" file="core-des.tex">
+ <cd:command name="setupindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="impostarientri"/>
+ <cd:string value="setupindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1" optional="yes" list="yes">
@@ -3310,16 +3316,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="defineindenting" file="core-des.tex">
+ <cd:command name="defineindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="definiscirientro"/>
+ <cd:string value="defineindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments n="2" list="yes">
- <cd:inherit name="impostarientri" n="2"/>
+ <cd:inherit name="setupindentedtext" n="2"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -7230,16 +7236,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="pagetype" file="page-ini.tex">
+ <!-- cd:command name="pagetype" file="page-ini.tex">
<cd:sequence>
- <cd:string value="tipopagina"/>
+ <cd:string value="pagetype"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
</cd:arguments>
- </cd:command>
+ </cd:command -->
<cd:command name="processpage" file="page-ini.tex">
<cd:sequence>
diff --git a/Master/texmf-dist/tex/context/interface/cont-nl.xml b/Master/texmf-dist/tex/context/interface/cont-nl.xml
index 2d53444fb99..c4ad23ba961 100644
--- a/Master/texmf-dist/tex/context/interface/cont-nl.xml
+++ b/Master/texmf-dist/tex/context/interface/cont-nl.xml
@@ -2,16 +2,18 @@
<!-- versions:
- comment : user interface definitions of ConTeXt
+ comment : user interface definitions of ConTeXt
- authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
+ authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
- versions : 2004.11.17 : initial version
- 2006.08.02 : define + resolve
+ versions : 2004.11.17 : initial version
+ 2006.08.02 : define + resolve
-->
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="nl" version="2006.08.02">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context test" language="nl" version="2006.08.02">
+
+ <!-- there are some more -->
<cd:define name="align">
<cd:constant type="binnen"/>
@@ -25,6 +27,10 @@
<cd:constant type="normaal"/>
<cd:constant type="nee"/>
<cd:constant type="ja"/>
+ <cd:constant type="ruim"/>
+ <cd:constant type="laatste"/>
+ <cd:constant type="r2l"/>
+ <cd:constant type="l2r"/>
</cd:define>
<cd:define name="symalign">
@@ -2460,7 +2466,7 @@
<cd:parameter name="file">
<cd:constant type="cd:text"/>
</cd:parameter>
- <cd:parameter name="gebied">
+ <cd:parameter name="directory">
<cd:constant type="cd:text"/>
</cd:parameter>
<cd:parameter name="willekeur">
@@ -3269,9 +3275,9 @@
</cd:arguments>
</cd:command>
- <cd:command name="setupindentations" file="core-des.tex">
+ <cd:command name="setupindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="steldoorspringenin"/>
+ <cd:string value="stelingesprongentextin"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1" optional="yes" list="yes">
@@ -3310,16 +3316,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="defineindenting" file="core-des.tex">
+ <cd:command name="defineindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="doorspringen"/>
+ <cd:string value="definieeringesprongentext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments n="2" list="yes">
- <cd:inherit name="steldoorspringenin" n="2"/>
+ <cd:inherit name="stelingesprongentextin" n="2"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -5175,7 +5181,7 @@
<cd:parameter name="maxbreedte">
<cd:constant type="cd:dimension"/>
</cd:parameter>
- <cd:parameter name="order">
+ <cd:parameter name="volgorde">
<cd:constant type="commando"/>
<cd:constant type="alles"/>
<cd:constant type="normaal"/>
@@ -7230,16 +7236,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="pagetype" file="page-ini.tex">
+ <!-- cd:command name="pagetype" file="page-ini.tex">
<cd:sequence>
- <cd:string value="soortpagina"/>
+ <cd:string value="pagetype"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
</cd:arguments>
- </cd:command>
+ </cd:command -->
<cd:command name="processpage" file="page-ini.tex">
<cd:sequence>
@@ -8528,7 +8534,7 @@
<cd:parameter name="xmax">
<cd:constant type="cd:number"/>
</cd:parameter>
- <cd:parameter name="gebied">
+ <cd:parameter name="directory">
<cd:constant type="cd:text"/>
</cd:parameter>
<cd:parameter name="plaats">
@@ -9484,7 +9490,7 @@
</cd:sequence>
<cd:arguments>
<cd:assignments n="1" interactive="exclusive" list="yes">
- <cd:parameter name="gebied">
+ <cd:parameter name="directory">
<cd:constant type="cd:text"/>
</cd:parameter>
</cd:assignments>
diff --git a/Master/texmf-dist/tex/context/interface/cont-pe.xml b/Master/texmf-dist/tex/context/interface/cont-pe.xml
index 12a54339dad..b4e221171bf 100644
--- a/Master/texmf-dist/tex/context/interface/cont-pe.xml
+++ b/Master/texmf-dist/tex/context/interface/cont-pe.xml
@@ -2,16 +2,18 @@
<!-- versions:
- comment : user interface definitions of ConTeXt
+ comment : user interface definitions of ConTeXt
- authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
+ authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
- versions : 2004.11.17 : initial version
- 2006.08.02 : define + resolve
+ versions : 2004.11.17 : initial version
+ 2006.08.02 : define + resolve
-->
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="pe" version="2006.08.02">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context test" language="pe" version="2006.08.02">
+
+ <!-- there are some more -->
<cd:define name="align">
<cd:constant type="داخلی"/>
@@ -25,6 +27,10 @@
<cd:constant type="نرمال"/>
<cd:constant type="نه"/>
<cd:constant type="بله"/>
+ <cd:constant type="گسترده"/>
+ <cd:constant type="آخرین"/>
+ <cd:constant type="r2l"/>
+ <cd:constant type="l2r"/>
</cd:define>
<cd:define name="symalign">
@@ -3269,9 +3275,9 @@
</cd:arguments>
</cd:command>
- <cd:command name="setupindentations" file="core-des.tex">
+ <cd:command name="setupindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="بارگذاری‌تورÙتگیها"/>
+ <cd:string value="setupindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1" optional="yes" list="yes">
@@ -3310,16 +3316,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="defineindenting" file="core-des.tex">
+ <cd:command name="defineindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="تعریÙ‌تورÙتگی"/>
+ <cd:string value="defineindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments n="2" list="yes">
- <cd:inherit name="بارگذاری‌تورÙتگیها" n="2"/>
+ <cd:inherit name="setupindentedtext" n="2"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -7230,16 +7236,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="pagetype" file="page-ini.tex">
+ <!-- cd:command name="pagetype" file="page-ini.tex">
<cd:sequence>
- <cd:string value="نوع‌صÙحه"/>
+ <cd:string value="pagetype"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
</cd:arguments>
- </cd:command>
+ </cd:command -->
<cd:command name="processpage" file="page-ini.tex">
<cd:sequence>
diff --git a/Master/texmf-dist/tex/context/interface/cont-ro.xml b/Master/texmf-dist/tex/context/interface/cont-ro.xml
index b7fa62d59d4..1dbc8fb8566 100644
--- a/Master/texmf-dist/tex/context/interface/cont-ro.xml
+++ b/Master/texmf-dist/tex/context/interface/cont-ro.xml
@@ -2,16 +2,18 @@
<!-- versions:
- comment : user interface definitions of ConTeXt
+ comment : user interface definitions of ConTeXt
- authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
+ authors : Hans Hagen, Taco Hoekwater, Patrick Gundlach, Wolfgang Schuster, and others
- versions : 2004.11.17 : initial version
- 2006.08.02 : define + resolve
+ versions : 2004.11.17 : initial version
+ 2006.08.02 : define + resolve
-->
-<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context" language="ro" version="2006.08.02">
+<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="context test" language="ro" version="2006.08.02">
+
+ <!-- there are some more -->
<cd:define name="align">
<cd:constant type="intern"/>
@@ -25,6 +27,10 @@
<cd:constant type="normal"/>
<cd:constant type="nu"/>
<cd:constant type="da"/>
+ <cd:constant type="broad"/>
+ <cd:constant type="ultim"/>
+ <cd:constant type="r2l"/>
+ <cd:constant type="l2r"/>
</cd:define>
<cd:define name="symalign">
@@ -3269,9 +3275,9 @@
</cd:arguments>
</cd:command>
- <cd:command name="setupindentations" file="core-des.tex">
+ <cd:command name="setupindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="seteazaaliniate"/>
+ <cd:string value="setupindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1" optional="yes" list="yes">
@@ -3310,16 +3316,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="defineindenting" file="core-des.tex">
+ <cd:command name="defineindentedtext" file="strc-des.tex">
<cd:sequence>
- <cd:string value="definestealiat"/>
+ <cd:string value="defineindentedtext"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
<cd:assignments n="2" list="yes">
- <cd:inherit name="seteazaaliniate" n="2"/>
+ <cd:inherit name="setupindentedtext" n="2"/>
</cd:assignments>
</cd:arguments>
</cd:command>
@@ -7230,16 +7236,16 @@
</cd:arguments>
</cd:command>
- <cd:command name="pagetype" file="page-ini.tex">
+ <!-- cd:command name="pagetype" file="page-ini.tex">
<cd:sequence>
- <cd:string value="tippagina"/>
+ <cd:string value="pagetype"/>
</cd:sequence>
<cd:arguments>
<cd:keywords n="1">
<cd:constant type="cd:name"/>
</cd:keywords>
</cd:arguments>
- </cd:command>
+ </cd:command -->
<cd:command name="processpage" file="page-ini.tex">
<cd:sequence>
diff --git a/Master/texmf-dist/tex/context/interface/keys-cs.xml b/Master/texmf-dist/tex/context/interface/keys-cs.xml
index f91cc06f58d..a4206e2f247 100644
--- a/Master/texmf-dist/tex/context/interface/keys-cs.xml
+++ b/Master/texmf-dist/tex/context/interface/keys-cs.xml
@@ -7,6 +7,8 @@
<cd:variables>
<cd:variable name='Addition' value='Pridavek'/>
<cd:variable name='Balloon' value='Bublinka'/>
+ <cd:variable name='Cap' value='Kap'/>
+ <cd:variable name='Capital' value='Kapitalky'/>
<cd:variable name='Character' value='Pismeno'/>
<cd:variable name='Characters' value='Pismena'/>
<cd:variable name='CloseDocument' value='ZavritDokument'/>
@@ -64,6 +66,9 @@
<cd:variable name='ViewerHelp' value='NapovedaProhlizece'/>
<cd:variable name='WEEKDAY' value='VSEDNIDEN'/>
<cd:variable name='WORD' value='SLOVO'/>
+ <cd:variable name='WORDS' value='SLOVA'/>
+ <cd:variable name='Word' value='Slovo'/>
+ <cd:variable name='Words' value='Slova'/>
<cd:variable name='abbreviation' value='zkratka'/>
<cd:variable name='abbreviations' value='zkratky'/>
<cd:variable name='absolute' value='absolutni'/>
@@ -278,6 +283,7 @@
<cd:variable name='marking' value='znaceni'/>
<cd:variable name='mathalignment' value='mathalignment'/>
<cd:variable name='mathcases' value='mathcases'/>
+ <cd:variable name='mathematics' value='mathematika'/>
<cd:variable name='mathmatrix' value='mathmatrix'/>
<cd:variable name='max' value='max'/>
<cd:variable name='maxdepth' value='maxdepth'/>
@@ -359,6 +365,7 @@
<cd:variable name='previousoddpage' value='predchozilichastranka'/>
<cd:variable name='previouspage' value='predchozistranka'/>
<cd:variable name='previoussubpage' value='predchozipodstranka'/>
+ <cd:variable name='print' value='print'/>
<cd:variable name='printable' value='tisknutelne'/>
<cd:variable name='process' value='process'/>
<cd:variable name='product' value='produkt'/>
@@ -366,6 +373,7 @@
<cd:variable name='project' value='projekt'/>
<cd:variable name='protected' value='chranene'/>
<cd:variable name='quadruple' value='ctyrnasobny'/>
+ <cd:variable name='quarterline' value='quarterline'/>
<cd:variable name='quotation' value='citace'/>
<cd:variable name='quote' value='citovat'/>
<cd:variable name='ran' value='rozsah'/>
@@ -500,6 +508,8 @@
<cd:variable name='unavailable' value='nedostupne'/>
<cd:variable name='underbar' value='podtrzeno'/>
<cd:variable name='underbars' value='podtrzeni'/>
+ <cd:variable name='understrike' value='understrike'/>
+ <cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unit' value='jednotka'/>
<cd:variable name='units' value='jednotky'/>
<cd:variable name='unknown' value='neznamy'/>
@@ -519,6 +529,7 @@
<cd:variable name='white' value='bily'/>
<cd:variable name='wide' value='siroce'/>
<cd:variable name='width' value='sirka'/>
+ <cd:variable name='word' value='slovo'/>
<cd:variable name='xml' value='xml'/>
<cd:variable name='year' value='rok'/>
<cd:variable name='yes' value='ano'/>
@@ -539,6 +550,7 @@
<cd:constant name='alignsymbol' value='alignsymbol'/>
<cd:constant name='aligntitle' value='zarovnejtitul'/>
<cd:constant name='alternative' value='alternativa'/>
+ <cd:constant name='anchor' value='anchor'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arrow' value='sipka'/>
@@ -558,6 +570,8 @@
<cd:constant name='autohang' value='autohang'/>
<cd:constant name='autostrut' value='autostrut'/>
<cd:constant name='autowidth' value='autosirka'/>
+ <cd:constant name='availableheight' value='availableheight'/>
+ <cd:constant name='availablewidth' value='availablewidth'/>
<cd:constant name='axis' value='osa'/>
<cd:constant name='background' value='pozadi'/>
<cd:constant name='backgroundcolor' value='barvapozadi'/>
@@ -577,6 +591,7 @@
<cd:constant name='blank' value='prazdny'/>
<cd:constant name='blockway' value='dobloku'/>
<cd:constant name='bodyfont' value='zakladnifont'/>
+ <cd:constant name='boffset' value='boffset'/>
<cd:constant name='bookmark' value='zalozka'/>
<cd:constant name='bottom' value='spodek'/>
<cd:constant name='bottomafter' value='bottomafter'/>
@@ -608,6 +623,8 @@
<cd:constant name='commandafter' value='prikazpo'/>
<cd:constant name='commandbefore' value='predchoziprikaz'/>
<cd:constant name='commands' value='prikazy'/>
+ <cd:constant name='commentoffset' value='commentoffset'/>
+ <cd:constant name='compact' value='compact'/>
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
@@ -621,6 +638,7 @@
<cd:constant name='coupling' value='propojeni'/>
<cd:constant name='couplingway' value='zpusobpropojeni'/>
<cd:constant name='criterium' value='kriterium'/>
+ <cd:constant name='css' value='css'/>
<cd:constant name='current' value='aktualni'/>
<cd:constant name='cutspace' value='cutspace'/>
<cd:constant name='dash' value='pomlcka'/>
@@ -649,11 +667,13 @@
<cd:constant name='editoretallimit' value='editoretallimit'/>
<cd:constant name='editoretaltext' value='editoretaltext'/>
<cd:constant name='empty' value='prazdne'/>
+ <cd:constant name='entities' value='entities'/>
<cd:constant name='entries' value='entries'/>
<cd:constant name='equalheight' value='equalheight'/>
<cd:constant name='equalwidth' value='equalwidth'/>
<cd:constant name='escape' value='escape'/>
<cd:constant name='evenmargin' value='sudamarginalie'/>
+ <cd:constant name='exitoffset' value='labeloffset'/>
<cd:constant name='expansion' value='expanzen'/>
<cd:constant name='export' value='export'/>
<cd:constant name='extras' value='extras'/>
@@ -690,6 +710,7 @@
<cd:constant name='global' value='globalne'/>
<cd:constant name='grid' value='mrizka'/>
<cd:constant name='hang' value='zaveseni'/>
+ <cd:constant name='hcompact' value='hcompact'/>
<cd:constant name='headalign' value='headalign'/>
<cd:constant name='headcolor' value='barvahlavicky'/>
<cd:constant name='headcommand' value='headcommand'/>
@@ -718,6 +739,7 @@
<cd:constant name='inner' value='vnitrni'/>
<cd:constant name='innermargin' value='innermargin'/>
<cd:constant name='inputfile' value='inputfile'/>
+ <cd:constant name='insidesection' value='insidesection'/>
<cd:constant name='intent' value='intent'/>
<cd:constant name='interaction' value='interakce'/>
<cd:constant name='interlinespace' value='meziradkovamezera'/>
@@ -730,8 +752,10 @@
<cd:constant name='keys' value='keys'/>
<cd:constant name='keyword' value='keyword'/>
<cd:constant name='label' value='popisek'/>
+ <cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
+ <cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='vlevo'/>
<cd:constant name='leftcolor' value='barvavlevo'/>
<cd:constant name='leftcompoundhyphen' value='leftcompoundhyphen'/>
@@ -760,6 +784,7 @@
<cd:constant name='listtext' value='listtext'/>
<cd:constant name='local' value='lokalne'/>
<cd:constant name='location' value='misto'/>
+ <cd:constant name='loffset' value='loffset'/>
<cd:constant name='logo' value='logo'/>
<cd:constant name='logos' value='loga'/>
<cd:constant name='marcolor' value='barvaznacky'/>
@@ -836,6 +861,7 @@
<cd:constant name='page' value='stranka'/>
<cd:constant name='pageboundaries' value='hranicestranky'/>
<cd:constant name='pagecolor' value='barvastranky'/>
+ <cd:constant name='pagecolormodel' value='pagecolormodel'/>
<cd:constant name='pagecommand' value='strankovyprikaz'/>
<cd:constant name='pageconversion' value='pageconversion'/>
<cd:constant name='pageconversionset' value='pageconversionset'/>
@@ -876,6 +902,7 @@
<cd:constant name='preview' value='nahled'/>
<cd:constant name='previous' value='predchozi'/>
<cd:constant name='previousnumber' value='predchozicislo'/>
+ <cd:constant name='printable' value='tisknutelne'/>
<cd:constant name='process' value='process'/>
<cd:constant name='profile' value='profile'/>
<cd:constant name='pubsep' value='pubsep'/>
@@ -888,6 +915,7 @@
<cd:constant name='reference' value='odkaz'/>
<cd:constant name='referenceprefix' value='referenceprefix'/>
<cd:constant name='referencing' value='odkazujici'/>
+ <cd:constant name='region' value='region'/>
<cd:constant name='regionin' value='oblastuvnitr'/>
<cd:constant name='regionout' value='oblastvne'/>
<cd:constant name='repeat' value='opakovat'/>
@@ -912,9 +940,11 @@
<cd:constant name='rightsubsentence' value='podvetavpravo'/>
<cd:constant name='righttext' value='textvpravo'/>
<cd:constant name='rightwidth' value='sirkavpravo'/>
+ <cd:constant name='roffset' value='roffset'/>
<cd:constant name='rotation' value='rotace'/>
<cd:constant name='rule' value='linka'/>
<cd:constant name='rulecolor' value='barvalinky'/>
+ <cd:constant name='rulecommand' value='rulecommand'/>
<cd:constant name='rulethickness' value='tloustkalinky'/>
<cd:constant name='samepage' value='stejnastranka'/>
<cd:constant name='sample' value='vzor'/>
@@ -972,6 +1002,7 @@
<cd:constant name='subtitle' value='podtitulek'/>
<cd:constant name='suffix' value='suffix'/>
<cd:constant name='suffixseparator' value='suffixseparator'/>
+ <cd:constant name='suffixstopper' value='suffixstopper'/>
<cd:constant name='surnamesep' value='surnamesep'/>
<cd:constant name='sx' value='sx'/>
<cd:constant name='sy' value='sy'/>
@@ -989,6 +1020,7 @@
<cd:constant name='textcolor' value='barvatextu'/>
<cd:constant name='textcommand' value='textovyprikaz'/>
<cd:constant name='textdistance' value='textdistance'/>
+ <cd:constant name='textheight' value='vyskatextu'/>
<cd:constant name='textlayer' value='textlayer'/>
<cd:constant name='textmargin' value='textmargin'/>
<cd:constant name='textmethod' value='textmethod'/>
@@ -1006,6 +1038,7 @@
<cd:constant name='titleright' value='titleright'/>
<cd:constant name='titlestyle' value='styltitulek'/>
<cd:constant name='to' value='na'/>
+ <cd:constant name='toffset' value='toffset'/>
<cd:constant name='tolerance' value='tolerance'/>
<cd:constant name='top' value='vrsek'/>
<cd:constant name='topdistance' value='vzdalenostvrsku'/>
@@ -1022,6 +1055,8 @@
<cd:constant name='validate' value='validovat'/>
<cd:constant name='values' value='values'/>
<cd:constant name='vcommand' value='vprikaz'/>
+ <cd:constant name='vcompact' value='vcompact'/>
+ <cd:constant name='vector' value='vector'/>
<cd:constant name='veroffset' value='offsethlavicky'/>
<cd:constant name='vfil' value='vfil'/>
<cd:constant name='voffset' value='voffset'/>
@@ -1031,6 +1066,7 @@
<cd:constant name='white' value='bily'/>
<cd:constant name='width' value='sirka'/>
<cd:constant name='xfactor' value='xfaktor'/>
+ <cd:constant name='xhtml' value='xhtml'/>
<cd:constant name='xmax' value='xmax'/>
<cd:constant name='xoffset' value='xoffset'/>
<cd:constant name='xscale' value='xmeritko'/>
@@ -1051,8 +1087,6 @@
<cd:element name='complete' value='uplny'/>
<cd:element name='coupled' value='propojene'/>
<cd:element name='currentlocal' value='aktualnelokalni'/>
- <cd:element name='emptyone' value='leer'/>
- <cd:element name='emptytwo' value='prazdne'/>
<cd:element name='end' value='konec'/>
<cd:element name='endsetup' value=''/>
<cd:element name='get' value='ziskat'/>
@@ -1168,7 +1202,7 @@
<cd:command name='defineframedtext' value='definujoramovanytext'/>
<cd:command name='definehbox' value='definujhbox'/>
<cd:command name='definehead' value='definujnadpis'/>
- <cd:command name='defineindenting' value='definujodsazovani'/>
+ <cd:command name='defineindentedtext' value='defineindentedtext'/>
<cd:command name='defineinmargin' value='defineinmargin'/>
<cd:command name='defineinteractionmenu' value='definujinterakcnimenu'/>
<cd:command name='defineitemgroup' value='defineitemgroup'/>
@@ -1364,7 +1398,6 @@
<cd:command name='pagenumber' value='cislostrany'/>
<cd:command name='pageoffset' value='pageoffset'/>
<cd:command name='pagereference' value='odkaznastranu'/>
- <cd:command name='pagetype' value='typstrany'/>
<cd:command name='paperheight' value='vyskapapiru'/>
<cd:command name='paperwidth' value='sirkapapiru'/>
<cd:command name='periods' value='tecky'/>
@@ -1480,7 +1513,7 @@
<cd:command name='setupheads' value='nastavnadpisy'/>
<cd:command name='setupheadtext' value='nastavtexthlavicky'/>
<cd:command name='setuphyphenmark' value='nastavdelitko'/>
- <cd:command name='setupindentations' value='nastavodsazeni'/>
+ <cd:command name='setupindentedtext' value='setupindentedtext'/>
<cd:command name='setupindenting' value='nastavodsazovani'/>
<cd:command name='setupinmargin' value='nastavmarginalie'/>
<cd:command name='setupinteraction' value='nastavinterakci'/>
diff --git a/Master/texmf-dist/tex/context/interface/keys-de.xml b/Master/texmf-dist/tex/context/interface/keys-de.xml
index 9f01c61b43f..d0dbf545c39 100644
--- a/Master/texmf-dist/tex/context/interface/keys-de.xml
+++ b/Master/texmf-dist/tex/context/interface/keys-de.xml
@@ -7,6 +7,8 @@
<cd:variables>
<cd:variable name='Addition' value='Zusatz'/>
<cd:variable name='Balloon' value='Ballon'/>
+ <cd:variable name='Cap' value='Kap'/>
+ <cd:variable name='Capital' value='Versalien'/>
<cd:variable name='Character' value='Buchstabe'/>
<cd:variable name='Characters' value='Buchstaben'/>
<cd:variable name='CloseDocument' value='SchliesseDokument'/>
@@ -64,6 +66,9 @@
<cd:variable name='ViewerHelp' value='ViewerHilfe'/>
<cd:variable name='WEEKDAY' value='WOCHENTAG'/>
<cd:variable name='WORD' value='WORT'/>
+ <cd:variable name='WORDS' value='WOERTER'/>
+ <cd:variable name='Word' value='Wort'/>
+ <cd:variable name='Words' value='Woerter'/>
<cd:variable name='abbreviation' value='abkuerzung'/>
<cd:variable name='abbreviations' value='abkuerzungen'/>
<cd:variable name='absolute' value='absolut'/>
@@ -75,11 +80,11 @@
<cd:variable name='answerarea' value='answerarea'/>
<cd:variable name='appendices' value='anhaenge'/>
<cd:variable name='appendix' value='anhang'/>
- <cd:variable name='april' value='April'/>
+ <cd:variable name='april' value='april'/>
<cd:variable name='atmargin' value='amrand'/>
<cd:variable name='atpage' value='aufseite'/>
<cd:variable name='attachment' value='attachment'/>
- <cd:variable name='august' value='August'/>
+ <cd:variable name='august' value='august'/>
<cd:variable name='author' value='autor'/>
<cd:variable name='auto' value='auto'/>
<cd:variable name='autointro' value='autointro'/>
@@ -137,7 +142,7 @@
<cd:variable name='cutspace' value='cutspace'/>
<cd:variable name='date' value='datum'/>
<cd:variable name='day' value='tag'/>
- <cd:variable name='december' value='Dezember'/>
+ <cd:variable name='december' value='dezember'/>
<cd:variable name='default' value='default'/>
<cd:variable name='depth' value='tiefe'/>
<cd:variable name='description' value='beschreibung'/>
@@ -157,7 +162,7 @@
<cd:variable name='even' value='gerade'/>
<cd:variable name='external' value='extern'/>
<cd:variable name='fact' value='gegeben'/>
- <cd:variable name='february' value='Februar'/>
+ <cd:variable name='february' value='februar'/>
<cd:variable name='figure' value='abbildung'/>
<cd:variable name='figures' value='abbildungen'/>
<cd:variable name='file' value='datei'/>
@@ -235,10 +240,10 @@
<cd:variable name='item' value='pos'/>
<cd:variable name='itemize' value='aufzaehlung'/>
<cd:variable name='its' value='its'/>
- <cd:variable name='january' value='Januar'/>
+ <cd:variable name='january' value='januar'/>
<cd:variable name='joinedup' value='keinabstand'/>
- <cd:variable name='july' value='Juli'/>
- <cd:variable name='june' value='Juni'/>
+ <cd:variable name='july' value='juli'/>
+ <cd:variable name='june' value='juni'/>
<cd:variable name='keep' value='behalte'/>
<cd:variable name='knockout' value='knockout'/>
<cd:variable name='label' value='label'/>
@@ -271,19 +276,20 @@
<cd:variable name='ls' value='ls'/>
<cd:variable name='makeup' value='umbruch'/>
<cd:variable name='mar' value='mar'/>
- <cd:variable name='march' value='Maerz'/>
+ <cd:variable name='march' value='maerz'/>
<cd:variable name='margin' value='marginalie'/>
<cd:variable name='marginedge' value='marginalkante'/>
<cd:variable name='margintitle' value='marginaltitel'/>
<cd:variable name='marking' value='beschriftung'/>
<cd:variable name='mathalignment' value='mathalignment'/>
<cd:variable name='mathcases' value='mathcases'/>
+ <cd:variable name='mathematics' value='mathematik'/>
<cd:variable name='mathmatrix' value='mathmatrix'/>
<cd:variable name='max' value='max'/>
<cd:variable name='maxdepth' value='maxdepth'/>
<cd:variable name='maxheight' value='maxheight'/>
<cd:variable name='maxwidth' value='maxwidth'/>
- <cd:variable name='may' value='Mai'/>
+ <cd:variable name='may' value='mai'/>
<cd:variable name='mediaeval' value='mittelalterlich'/>
<cd:variable name='medium' value='mittel'/>
<cd:variable name='middle' value='mittig'/>
@@ -320,12 +326,12 @@
<cd:variable name='note' value='note'/>
<cd:variable name='nothanging' value='nothanging'/>
<cd:variable name='nothyphenated' value='nothyphenated'/>
- <cd:variable name='november' value='November'/>
+ <cd:variable name='november' value='november'/>
<cd:variable name='nowhere' value='nirgens'/>
<cd:variable name='nowhite' value='keinweiss'/>
<cd:variable name='number' value='nummer'/>
<cd:variable name='numbers' value='ziffern'/>
- <cd:variable name='october' value='Oktober'/>
+ <cd:variable name='october' value='oktober'/>
<cd:variable name='odd' value='ungerade'/>
<cd:variable name='off' value='aus'/>
<cd:variable name='offset' value='offset'/>
@@ -359,6 +365,7 @@
<cd:variable name='previousoddpage' value='vorigeungeradeseite'/>
<cd:variable name='previouspage' value='vorigeseite'/>
<cd:variable name='previoussubpage' value='vorigeunterseite'/>
+ <cd:variable name='print' value='print'/>
<cd:variable name='printable' value='druckbar'/>
<cd:variable name='process' value='process'/>
<cd:variable name='product' value='produkt'/>
@@ -366,6 +373,7 @@
<cd:variable name='project' value='projekt'/>
<cd:variable name='protected' value='geschuetzt'/>
<cd:variable name='quadruple' value='viertel'/>
+ <cd:variable name='quarterline' value='quarterline'/>
<cd:variable name='quotation' value='zitat'/>
<cd:variable name='quote' value='zitieren'/>
<cd:variable name='ran' value='ran'/>
@@ -405,7 +413,7 @@
<cd:variable name='sectionblockenvironment' value='sectionblockenvironment'/>
<cd:variable name='sectionnumber' value='abschnittsnummer'/>
<cd:variable name='see' value='sieh'/>
- <cd:variable name='september' value='September'/>
+ <cd:variable name='september' value='september'/>
<cd:variable name='serif' value='serif'/>
<cd:variable name='serried' value='kleinerabstand'/>
<cd:variable name='setups' value='impostazioni'/>
@@ -500,6 +508,8 @@
<cd:variable name='unavailable' value='nichtverfuegbar'/>
<cd:variable name='underbar' value='unterstrichen'/>
<cd:variable name='underbars' value='unterstreichen'/>
+ <cd:variable name='understrike' value='understrike'/>
+ <cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unit' value='einheit'/>
<cd:variable name='units' value='einheiten'/>
<cd:variable name='unknown' value='unbekannt'/>
@@ -519,6 +529,7 @@
<cd:variable name='white' value='weiss'/>
<cd:variable name='wide' value='breit'/>
<cd:variable name='width' value='breite'/>
+ <cd:variable name='word' value='wort'/>
<cd:variable name='xml' value='xml'/>
<cd:variable name='year' value='jahr'/>
<cd:variable name='yes' value='ja'/>
@@ -539,6 +550,7 @@
<cd:constant name='alignsymbol' value='alignsymbol'/>
<cd:constant name='aligntitle' value='titelausrichten'/>
<cd:constant name='alternative' value='alternative'/>
+ <cd:constant name='anchor' value='anchor'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arrow' value='pfeil'/>
@@ -558,6 +570,8 @@
<cd:constant name='autohang' value='autohang'/>
<cd:constant name='autostrut' value='autostrut'/>
<cd:constant name='autowidth' value='autobreite'/>
+ <cd:constant name='availableheight' value='availableheight'/>
+ <cd:constant name='availablewidth' value='availablewidth'/>
<cd:constant name='axis' value='achsen'/>
<cd:constant name='background' value='hintergrund'/>
<cd:constant name='backgroundcolor' value='hintergrundfarbe'/>
@@ -577,6 +591,7 @@
<cd:constant name='blank' value='blanko'/>
<cd:constant name='blockway' value='blockauf'/>
<cd:constant name='bodyfont' value='fliesstext'/>
+ <cd:constant name='boffset' value='boffset'/>
<cd:constant name='bookmark' value='bookmark'/>
<cd:constant name='bottom' value='unten'/>
<cd:constant name='bottomafter' value='bottomafter'/>
@@ -608,6 +623,8 @@
<cd:constant name='commandafter' value='zumbefehl'/>
<cd:constant name='commandbefore' value='vorbefehl'/>
<cd:constant name='commands' value='befehle'/>
+ <cd:constant name='commentoffset' value='commentoffset'/>
+ <cd:constant name='compact' value='compact'/>
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
@@ -621,6 +638,7 @@
<cd:constant name='coupling' value='verknuepfung'/>
<cd:constant name='couplingway' value='verkopplungsart'/>
<cd:constant name='criterium' value='kriterium'/>
+ <cd:constant name='css' value='css'/>
<cd:constant name='current' value='aktuell'/>
<cd:constant name='cutspace' value='cutspace'/>
<cd:constant name='dash' value='strich'/>
@@ -649,11 +667,13 @@
<cd:constant name='editoretallimit' value='editoretallimit'/>
<cd:constant name='editoretaltext' value='editoretaltext'/>
<cd:constant name='empty' value='leer'/>
+ <cd:constant name='entities' value='entities'/>
<cd:constant name='entries' value='entries'/>
<cd:constant name='equalheight' value='equalheight'/>
<cd:constant name='equalwidth' value='equalwidth'/>
<cd:constant name='escape' value='escape'/>
<cd:constant name='evenmargin' value='geraderand'/>
+ <cd:constant name='exitoffset' value='labeloffset'/>
<cd:constant name='expansion' value='expansion'/>
<cd:constant name='export' value='export'/>
<cd:constant name='extras' value='extras'/>
@@ -690,6 +710,7 @@
<cd:constant name='global' value='global'/>
<cd:constant name='grid' value='gritter'/>
<cd:constant name='hang' value='haengend'/>
+ <cd:constant name='hcompact' value='hcompact'/>
<cd:constant name='headalign' value='headalign'/>
<cd:constant name='headcolor' value='kopffarbe'/>
<cd:constant name='headcommand' value='headcommand'/>
@@ -718,6 +739,7 @@
<cd:constant name='inner' value='innen'/>
<cd:constant name='innermargin' value='innermargin'/>
<cd:constant name='inputfile' value='inputfile'/>
+ <cd:constant name='insidesection' value='insidesection'/>
<cd:constant name='intent' value='intent'/>
<cd:constant name='interaction' value='interaktion'/>
<cd:constant name='interlinespace' value='zeilenabstande'/>
@@ -730,8 +752,10 @@
<cd:constant name='keys' value='keys'/>
<cd:constant name='keyword' value='keyword'/>
<cd:constant name='label' value='label'/>
+ <cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
+ <cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='links'/>
<cd:constant name='leftcolor' value='linkerfarbe'/>
<cd:constant name='leftcompoundhyphen' value='leftcompoundhyphen'/>
@@ -760,6 +784,7 @@
<cd:constant name='listtext' value='listtext'/>
<cd:constant name='local' value='lokal'/>
<cd:constant name='location' value='platz'/>
+ <cd:constant name='loffset' value='loffset'/>
<cd:constant name='logo' value='logo'/>
<cd:constant name='logos' value='logos'/>
<cd:constant name='marcolor' value='beschrfarbe'/>
@@ -836,6 +861,7 @@
<cd:constant name='page' value='seite'/>
<cd:constant name='pageboundaries' value='seitenbegrenzung'/>
<cd:constant name='pagecolor' value='seitenfarbe'/>
+ <cd:constant name='pagecolormodel' value='pagecolormodel'/>
<cd:constant name='pagecommand' value='seitenbefehl'/>
<cd:constant name='pageconversion' value='pageconversion'/>
<cd:constant name='pageconversionset' value='pageconversionset'/>
@@ -876,6 +902,7 @@
<cd:constant name='preview' value='vorschau'/>
<cd:constant name='previous' value='vorige'/>
<cd:constant name='previousnumber' value='vorigenummer'/>
+ <cd:constant name='printable' value='druckbar'/>
<cd:constant name='process' value='process'/>
<cd:constant name='profile' value='profile'/>
<cd:constant name='pubsep' value='pubsep'/>
@@ -888,6 +915,7 @@
<cd:constant name='reference' value='referenz'/>
<cd:constant name='referenceprefix' value='referenceprefix'/>
<cd:constant name='referencing' value='referieren'/>
+ <cd:constant name='region' value='region'/>
<cd:constant name='regionin' value='regionin'/>
<cd:constant name='regionout' value='regionaus'/>
<cd:constant name='repeat' value='wiederholen'/>
@@ -912,9 +940,11 @@
<cd:constant name='rightsubsentence' value='rechtersubsatz'/>
<cd:constant name='righttext' value='rechtertext'/>
<cd:constant name='rightwidth' value='rechterbreite'/>
+ <cd:constant name='roffset' value='roffset'/>
<cd:constant name='rotation' value='rotation'/>
<cd:constant name='rule' value='linie'/>
<cd:constant name='rulecolor' value='linienfarbe'/>
+ <cd:constant name='rulecommand' value='rulecommand'/>
<cd:constant name='rulethickness' value='liniendicke'/>
<cd:constant name='samepage' value='selbeseite'/>
<cd:constant name='sample' value='muster'/>
@@ -972,6 +1002,7 @@
<cd:constant name='subtitle' value='untertitel'/>
<cd:constant name='suffix' value='suffix'/>
<cd:constant name='suffixseparator' value='suffixseparator'/>
+ <cd:constant name='suffixstopper' value='suffixstopper'/>
<cd:constant name='surnamesep' value='surnamesep'/>
<cd:constant name='sx' value='sx'/>
<cd:constant name='sy' value='sy'/>
@@ -989,6 +1020,7 @@
<cd:constant name='textcolor' value='textfarbe'/>
<cd:constant name='textcommand' value='textbefehl'/>
<cd:constant name='textdistance' value='textdistance'/>
+ <cd:constant name='textheight' value='texthoehe'/>
<cd:constant name='textlayer' value='textlayer'/>
<cd:constant name='textmargin' value='textmargin'/>
<cd:constant name='textmethod' value='textmethod'/>
@@ -1006,6 +1038,7 @@
<cd:constant name='titleright' value='titleright'/>
<cd:constant name='titlestyle' value='titelstil'/>
<cd:constant name='to' value='zu'/>
+ <cd:constant name='toffset' value='toffset'/>
<cd:constant name='tolerance' value='toleranz'/>
<cd:constant name='top' value='oben'/>
<cd:constant name='topdistance' value='obenabstand'/>
@@ -1022,6 +1055,8 @@
<cd:constant name='validate' value='validieren'/>
<cd:constant name='values' value='values'/>
<cd:constant name='vcommand' value='vbefehl'/>
+ <cd:constant name='vcompact' value='vcompact'/>
+ <cd:constant name='vector' value='vector'/>
<cd:constant name='veroffset' value='kopfoffset'/>
<cd:constant name='vfil' value='vfil'/>
<cd:constant name='voffset' value='voffset'/>
@@ -1031,6 +1066,7 @@
<cd:constant name='white' value='weiss'/>
<cd:constant name='width' value='breite'/>
<cd:constant name='xfactor' value='xfaktor'/>
+ <cd:constant name='xhtml' value='xhtml'/>
<cd:constant name='xmax' value='xmax'/>
<cd:constant name='xoffset' value='xoffset'/>
<cd:constant name='xscale' value='xformat'/>
@@ -1051,8 +1087,6 @@
<cd:element name='complete' value='vollende'/>
<cd:element name='coupled' value='verknuepft'/>
<cd:element name='currentlocal' value='aktuelllokal'/>
- <cd:element name='emptyone' value='vuoto'/>
- <cd:element name='emptytwo' value='leer'/>
<cd:element name='end' value='ende'/>
<cd:element name='endsetup' value='ein'/>
<cd:element name='get' value='get'/>
@@ -1168,7 +1202,7 @@
<cd:command name='defineframedtext' value='definiereumrahmtertext'/>
<cd:command name='definehbox' value='definierehbox'/>
<cd:command name='definehead' value='definiereueberschrift'/>
- <cd:command name='defineindenting' value='definiereeinzug'/>
+ <cd:command name='defineindentedtext' value='defineindentedtext'/>
<cd:command name='defineinmargin' value='defineinmargin'/>
<cd:command name='defineinteractionmenu' value='definiereinteraktionsmenue'/>
<cd:command name='defineitemgroup' value='defineitemgroup'/>
@@ -1364,7 +1398,6 @@
<cd:command name='pagenumber' value='seitenummer'/>
<cd:command name='pageoffset' value='pageoffset'/>
<cd:command name='pagereference' value='seitenreferenz'/>
- <cd:command name='pagetype' value='seitentyp'/>
<cd:command name='paperheight' value='papierhoehe'/>
<cd:command name='paperwidth' value='papierbreite'/>
<cd:command name='periods' value='punkt'/>
@@ -1480,7 +1513,7 @@
<cd:command name='setupheads' value='stelleueberschriftenein'/>
<cd:command name='setupheadtext' value='stelleueberschrifttextein'/>
<cd:command name='setuphyphenmark' value='stellebindestrichein'/>
- <cd:command name='setupindentations' value='stelleeinzuegein'/>
+ <cd:command name='setupindentedtext' value='setupindentedtext'/>
<cd:command name='setupindenting' value='stelleeinziehenein'/>
<cd:command name='setupinmargin' value='stelleinmarginalieein'/>
<cd:command name='setupinteraction' value='stelleinteraktionein'/>
diff --git a/Master/texmf-dist/tex/context/interface/keys-en.xml b/Master/texmf-dist/tex/context/interface/keys-en.xml
index b2954aa3a41..e26ee8becf4 100644
--- a/Master/texmf-dist/tex/context/interface/keys-en.xml
+++ b/Master/texmf-dist/tex/context/interface/keys-en.xml
@@ -7,6 +7,8 @@
<cd:variables>
<cd:variable name='Addition' value='Addition'/>
<cd:variable name='Balloon' value='Balloon'/>
+ <cd:variable name='Cap' value='Cap'/>
+ <cd:variable name='Capital' value='Capital'/>
<cd:variable name='Character' value='Character'/>
<cd:variable name='Characters' value='Characters'/>
<cd:variable name='CloseDocument' value='CloseDocument'/>
@@ -64,6 +66,9 @@
<cd:variable name='ViewerHelp' value='ViewerHelp'/>
<cd:variable name='WEEKDAY' value='WEEKDAY'/>
<cd:variable name='WORD' value='WORD'/>
+ <cd:variable name='WORDS' value='WORDS'/>
+ <cd:variable name='Word' value='Word'/>
+ <cd:variable name='Words' value='Words'/>
<cd:variable name='abbreviation' value='abbreviation'/>
<cd:variable name='abbreviations' value='abbreviations'/>
<cd:variable name='absolute' value='absolute'/>
@@ -75,11 +80,11 @@
<cd:variable name='answerarea' value='answerarea'/>
<cd:variable name='appendices' value='appendices'/>
<cd:variable name='appendix' value='appendix'/>
- <cd:variable name='april' value='April'/>
+ <cd:variable name='april' value='april'/>
<cd:variable name='atmargin' value='atmargin'/>
<cd:variable name='atpage' value='atpage'/>
<cd:variable name='attachment' value='attachment'/>
- <cd:variable name='august' value='August'/>
+ <cd:variable name='august' value='august'/>
<cd:variable name='author' value='author'/>
<cd:variable name='auto' value='auto'/>
<cd:variable name='autointro' value='autointro'/>
@@ -137,7 +142,7 @@
<cd:variable name='cutspace' value='cutspace'/>
<cd:variable name='date' value='date'/>
<cd:variable name='day' value='day'/>
- <cd:variable name='december' value='December'/>
+ <cd:variable name='december' value='december'/>
<cd:variable name='default' value='default'/>
<cd:variable name='depth' value='depth'/>
<cd:variable name='description' value='description'/>
@@ -157,7 +162,7 @@
<cd:variable name='even' value='even'/>
<cd:variable name='external' value='external'/>
<cd:variable name='fact' value='fact'/>
- <cd:variable name='february' value='February'/>
+ <cd:variable name='february' value='february'/>
<cd:variable name='figure' value='figure'/>
<cd:variable name='figures' value='figures'/>
<cd:variable name='file' value='file'/>
@@ -235,10 +240,10 @@
<cd:variable name='item' value='item'/>
<cd:variable name='itemize' value='itemize'/>
<cd:variable name='its' value='its'/>
- <cd:variable name='january' value='January'/>
+ <cd:variable name='january' value='january'/>
<cd:variable name='joinedup' value='joinedup'/>
- <cd:variable name='july' value='July'/>
- <cd:variable name='june' value='June'/>
+ <cd:variable name='july' value='july'/>
+ <cd:variable name='june' value='june'/>
<cd:variable name='keep' value='keep'/>
<cd:variable name='knockout' value='knockout'/>
<cd:variable name='label' value='label'/>
@@ -271,19 +276,20 @@
<cd:variable name='ls' value='ls'/>
<cd:variable name='makeup' value='makeup'/>
<cd:variable name='mar' value='mar'/>
- <cd:variable name='march' value='March'/>
+ <cd:variable name='march' value='march'/>
<cd:variable name='margin' value='margin'/>
<cd:variable name='marginedge' value='marginedge'/>
<cd:variable name='margintitle' value='margintitle'/>
<cd:variable name='marking' value='marking'/>
<cd:variable name='mathalignment' value='mathalignment'/>
<cd:variable name='mathcases' value='mathcases'/>
+ <cd:variable name='mathematics' value='mathematics'/>
<cd:variable name='mathmatrix' value='mathmatrix'/>
<cd:variable name='max' value='max'/>
<cd:variable name='maxdepth' value='maxdepth'/>
<cd:variable name='maxheight' value='maxheight'/>
<cd:variable name='maxwidth' value='maxwidth'/>
- <cd:variable name='may' value='May'/>
+ <cd:variable name='may' value='may'/>
<cd:variable name='mediaeval' value='mediaeval'/>
<cd:variable name='medium' value='medium'/>
<cd:variable name='middle' value='middle'/>
@@ -320,12 +326,12 @@
<cd:variable name='note' value='note'/>
<cd:variable name='nothanging' value='nothanging'/>
<cd:variable name='nothyphenated' value='nothyphenated'/>
- <cd:variable name='november' value='November'/>
+ <cd:variable name='november' value='november'/>
<cd:variable name='nowhere' value='nowhere'/>
<cd:variable name='nowhite' value='nowhite'/>
<cd:variable name='number' value='number'/>
<cd:variable name='numbers' value='numbers'/>
- <cd:variable name='october' value='October'/>
+ <cd:variable name='october' value='october'/>
<cd:variable name='odd' value='odd'/>
<cd:variable name='off' value='off'/>
<cd:variable name='offset' value='offset'/>
@@ -359,6 +365,7 @@
<cd:variable name='previousoddpage' value='previousoddpage'/>
<cd:variable name='previouspage' value='previouspage'/>
<cd:variable name='previoussubpage' value='previoussubpage'/>
+ <cd:variable name='print' value='print'/>
<cd:variable name='printable' value='printable'/>
<cd:variable name='process' value='process'/>
<cd:variable name='product' value='product'/>
@@ -366,6 +373,7 @@
<cd:variable name='project' value='project'/>
<cd:variable name='protected' value='protected'/>
<cd:variable name='quadruple' value='quadruple'/>
+ <cd:variable name='quarterline' value='quarterline'/>
<cd:variable name='quotation' value='quotation'/>
<cd:variable name='quote' value='quote'/>
<cd:variable name='ran' value='ran'/>
@@ -405,7 +413,7 @@
<cd:variable name='sectionblockenvironment' value='sectionblockenvironment'/>
<cd:variable name='sectionnumber' value='sectionnumber'/>
<cd:variable name='see' value='see'/>
- <cd:variable name='september' value='September'/>
+ <cd:variable name='september' value='september'/>
<cd:variable name='serif' value='serif'/>
<cd:variable name='serried' value='serried'/>
<cd:variable name='setups' value='setups'/>
@@ -500,6 +508,8 @@
<cd:variable name='unavailable' value='unavailable'/>
<cd:variable name='underbar' value='underbar'/>
<cd:variable name='underbars' value='underbars'/>
+ <cd:variable name='understrike' value='understrike'/>
+ <cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unit' value='unit'/>
<cd:variable name='units' value='units'/>
<cd:variable name='unknown' value='unknown'/>
@@ -519,6 +529,7 @@
<cd:variable name='white' value='white'/>
<cd:variable name='wide' value='wide'/>
<cd:variable name='width' value='width'/>
+ <cd:variable name='word' value='word'/>
<cd:variable name='xml' value='xml'/>
<cd:variable name='year' value='year'/>
<cd:variable name='yes' value='yes'/>
@@ -539,6 +550,7 @@
<cd:constant name='alignsymbol' value='alignsymbol'/>
<cd:constant name='aligntitle' value='aligntitle'/>
<cd:constant name='alternative' value='alternative'/>
+ <cd:constant name='anchor' value='anchor'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arrow' value='arrow'/>
@@ -558,6 +570,8 @@
<cd:constant name='autohang' value='autohang'/>
<cd:constant name='autostrut' value='autostrut'/>
<cd:constant name='autowidth' value='autowidth'/>
+ <cd:constant name='availableheight' value='availableheight'/>
+ <cd:constant name='availablewidth' value='availablewidth'/>
<cd:constant name='axis' value='axis'/>
<cd:constant name='background' value='background'/>
<cd:constant name='backgroundcolor' value='backgroundcolor'/>
@@ -577,6 +591,7 @@
<cd:constant name='blank' value='blank'/>
<cd:constant name='blockway' value='blockway'/>
<cd:constant name='bodyfont' value='bodyfont'/>
+ <cd:constant name='boffset' value='boffset'/>
<cd:constant name='bookmark' value='bookmark'/>
<cd:constant name='bottom' value='bottom'/>
<cd:constant name='bottomafter' value='bottomafter'/>
@@ -608,6 +623,8 @@
<cd:constant name='commandafter' value='commandafter'/>
<cd:constant name='commandbefore' value='commandbefore'/>
<cd:constant name='commands' value='commands'/>
+ <cd:constant name='commentoffset' value='commentoffset'/>
+ <cd:constant name='compact' value='compact'/>
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
@@ -621,6 +638,7 @@
<cd:constant name='coupling' value='coupling'/>
<cd:constant name='couplingway' value='couplingway'/>
<cd:constant name='criterium' value='criterium'/>
+ <cd:constant name='css' value='css'/>
<cd:constant name='current' value='current'/>
<cd:constant name='cutspace' value='cutspace'/>
<cd:constant name='dash' value='dash'/>
@@ -649,11 +667,13 @@
<cd:constant name='editoretallimit' value='editoretallimit'/>
<cd:constant name='editoretaltext' value='editoretaltext'/>
<cd:constant name='empty' value='empty'/>
+ <cd:constant name='entities' value='entities'/>
<cd:constant name='entries' value='entries'/>
<cd:constant name='equalheight' value='equalheight'/>
<cd:constant name='equalwidth' value='equalwidth'/>
<cd:constant name='escape' value='escape'/>
<cd:constant name='evenmargin' value='evenmargin'/>
+ <cd:constant name='exitoffset' value='labeloffset'/>
<cd:constant name='expansion' value='expansion'/>
<cd:constant name='export' value='export'/>
<cd:constant name='extras' value='extras'/>
@@ -690,6 +710,7 @@
<cd:constant name='global' value='global'/>
<cd:constant name='grid' value='grid'/>
<cd:constant name='hang' value='hang'/>
+ <cd:constant name='hcompact' value='hcompact'/>
<cd:constant name='headalign' value='headalign'/>
<cd:constant name='headcolor' value='headcolor'/>
<cd:constant name='headcommand' value='headcommand'/>
@@ -718,6 +739,7 @@
<cd:constant name='inner' value='inner'/>
<cd:constant name='innermargin' value='innermargin'/>
<cd:constant name='inputfile' value='inputfile'/>
+ <cd:constant name='insidesection' value='insidesection'/>
<cd:constant name='intent' value='intent'/>
<cd:constant name='interaction' value='interaction'/>
<cd:constant name='interlinespace' value='interlinespace'/>
@@ -730,8 +752,10 @@
<cd:constant name='keys' value='keys'/>
<cd:constant name='keyword' value='keyword'/>
<cd:constant name='label' value='label'/>
+ <cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
+ <cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='left'/>
<cd:constant name='leftcolor' value='leftcolor'/>
<cd:constant name='leftcompoundhyphen' value='leftcompoundhyphen'/>
@@ -760,6 +784,7 @@
<cd:constant name='listtext' value='listtext'/>
<cd:constant name='local' value='local'/>
<cd:constant name='location' value='location'/>
+ <cd:constant name='loffset' value='loffset'/>
<cd:constant name='logo' value='logo'/>
<cd:constant name='logos' value='logos'/>
<cd:constant name='marcolor' value='marcolor'/>
@@ -836,6 +861,7 @@
<cd:constant name='page' value='page'/>
<cd:constant name='pageboundaries' value='pageboundaries'/>
<cd:constant name='pagecolor' value='pagecolor'/>
+ <cd:constant name='pagecolormodel' value='pagecolormodel'/>
<cd:constant name='pagecommand' value='pagecommand'/>
<cd:constant name='pageconversion' value='pageconversion'/>
<cd:constant name='pageconversionset' value='pageconversionset'/>
@@ -876,6 +902,7 @@
<cd:constant name='preview' value='preview'/>
<cd:constant name='previous' value='previous'/>
<cd:constant name='previousnumber' value='previousnumber'/>
+ <cd:constant name='printable' value='printable'/>
<cd:constant name='process' value='process'/>
<cd:constant name='profile' value='profile'/>
<cd:constant name='pubsep' value='pubsep'/>
@@ -888,6 +915,7 @@
<cd:constant name='reference' value='reference'/>
<cd:constant name='referenceprefix' value='referenceprefix'/>
<cd:constant name='referencing' value='referencing'/>
+ <cd:constant name='region' value='region'/>
<cd:constant name='regionin' value='regionin'/>
<cd:constant name='regionout' value='regionout'/>
<cd:constant name='repeat' value='repeat'/>
@@ -912,9 +940,11 @@
<cd:constant name='rightsubsentence' value='rightsubsentence'/>
<cd:constant name='righttext' value='righttext'/>
<cd:constant name='rightwidth' value='rightwidth'/>
+ <cd:constant name='roffset' value='roffset'/>
<cd:constant name='rotation' value='rotation'/>
<cd:constant name='rule' value='rule'/>
<cd:constant name='rulecolor' value='rulecolor'/>
+ <cd:constant name='rulecommand' value='rulecommand'/>
<cd:constant name='rulethickness' value='rulethickness'/>
<cd:constant name='samepage' value='samepage'/>
<cd:constant name='sample' value='sample'/>
@@ -972,6 +1002,7 @@
<cd:constant name='subtitle' value='subtitle'/>
<cd:constant name='suffix' value='suffix'/>
<cd:constant name='suffixseparator' value='suffixseparator'/>
+ <cd:constant name='suffixstopper' value='suffixstopper'/>
<cd:constant name='surnamesep' value='surnamesep'/>
<cd:constant name='sx' value='sx'/>
<cd:constant name='sy' value='sy'/>
@@ -989,6 +1020,7 @@
<cd:constant name='textcolor' value='textcolor'/>
<cd:constant name='textcommand' value='textcommand'/>
<cd:constant name='textdistance' value='textdistance'/>
+ <cd:constant name='textheight' value='textheight'/>
<cd:constant name='textlayer' value='textlayer'/>
<cd:constant name='textmargin' value='textmargin'/>
<cd:constant name='textmethod' value='textmethod'/>
@@ -1006,6 +1038,7 @@
<cd:constant name='titleright' value='titleright'/>
<cd:constant name='titlestyle' value='titlestyle'/>
<cd:constant name='to' value='to'/>
+ <cd:constant name='toffset' value='toffset'/>
<cd:constant name='tolerance' value='tolerance'/>
<cd:constant name='top' value='top'/>
<cd:constant name='topdistance' value='topdistance'/>
@@ -1022,6 +1055,8 @@
<cd:constant name='validate' value='validate'/>
<cd:constant name='values' value='values'/>
<cd:constant name='vcommand' value='vcommand'/>
+ <cd:constant name='vcompact' value='vcompact'/>
+ <cd:constant name='vector' value='vector'/>
<cd:constant name='veroffset' value='veroffset'/>
<cd:constant name='vfil' value='vfil'/>
<cd:constant name='voffset' value='voffset'/>
@@ -1031,6 +1066,7 @@
<cd:constant name='white' value='white'/>
<cd:constant name='width' value='width'/>
<cd:constant name='xfactor' value='xfactor'/>
+ <cd:constant name='xhtml' value='xhtml'/>
<cd:constant name='xmax' value='xmax'/>
<cd:constant name='xoffset' value='xoffset'/>
<cd:constant name='xscale' value='xscale'/>
@@ -1051,8 +1087,6 @@
<cd:element name='complete' value='complete'/>
<cd:element name='coupled' value='coupled'/>
<cd:element name='currentlocal' value='currentlocal'/>
- <cd:element name='emptyone' value='empty'/>
- <cd:element name='emptytwo' value='empty'/>
<cd:element name='end' value='end'/>
<cd:element name='endsetup' value=''/>
<cd:element name='get' value='get'/>
@@ -1168,7 +1202,7 @@
<cd:command name='defineframedtext' value='defineframedtext'/>
<cd:command name='definehbox' value='definehbox'/>
<cd:command name='definehead' value='definehead'/>
- <cd:command name='defineindenting' value='defineindenting'/>
+ <cd:command name='defineindentedtext' value='defineindentedtext'/>
<cd:command name='defineinmargin' value='defineinmargin'/>
<cd:command name='defineinteractionmenu' value='defineinteractionmenu'/>
<cd:command name='defineitemgroup' value='defineitemgroup'/>
@@ -1364,7 +1398,6 @@
<cd:command name='pagenumber' value='pagenumber'/>
<cd:command name='pageoffset' value='pageoffset'/>
<cd:command name='pagereference' value='pagereference'/>
- <cd:command name='pagetype' value='pagetype'/>
<cd:command name='paperheight' value='paperheight'/>
<cd:command name='paperwidth' value='paperwidth'/>
<cd:command name='periods' value='periods'/>
@@ -1480,7 +1513,7 @@
<cd:command name='setupheads' value='setupheads'/>
<cd:command name='setupheadtext' value='setupheadtext'/>
<cd:command name='setuphyphenmark' value='setuphyphenmark'/>
- <cd:command name='setupindentations' value='setupindentations'/>
+ <cd:command name='setupindentedtext' value='setupindentedtext'/>
<cd:command name='setupindenting' value='setupindenting'/>
<cd:command name='setupinmargin' value='setupinmargin'/>
<cd:command name='setupinteraction' value='setupinteraction'/>
diff --git a/Master/texmf-dist/tex/context/interface/keys-fr.xml b/Master/texmf-dist/tex/context/interface/keys-fr.xml
index bcb18fca16a..bd0276ca34a 100644
--- a/Master/texmf-dist/tex/context/interface/keys-fr.xml
+++ b/Master/texmf-dist/tex/context/interface/keys-fr.xml
@@ -7,6 +7,8 @@
<cd:variables>
<cd:variable name='Addition' value='Ajout'/>
<cd:variable name='Balloon' value='Ballon'/>
+ <cd:variable name='Cap' value='Cap'/>
+ <cd:variable name='Capital' value='Capitale'/>
<cd:variable name='Character' value='Caratere'/>
<cd:variable name='Characters' value='Caracteres'/>
<cd:variable name='CloseDocument' value='FermeDocument'/>
@@ -64,6 +66,9 @@
<cd:variable name='ViewerHelp' value='AideVisualisateur'/>
<cd:variable name='WEEKDAY' value='JOURSEMAINE'/>
<cd:variable name='WORD' value='MOT'/>
+ <cd:variable name='WORDS' value='MOTS'/>
+ <cd:variable name='Word' value='Mot'/>
+ <cd:variable name='Words' value='Mots'/>
<cd:variable name='abbreviation' value='abreviation'/>
<cd:variable name='abbreviations' value='abreviations'/>
<cd:variable name='absolute' value='absolute'/>
@@ -278,6 +283,7 @@
<cd:variable name='marking' value='marquage'/>
<cd:variable name='mathalignment' value='mathalignment'/>
<cd:variable name='mathcases' value='mathcases'/>
+ <cd:variable name='mathematics' value='mathematique'/>
<cd:variable name='mathmatrix' value='mathmatrix'/>
<cd:variable name='max' value='max'/>
<cd:variable name='maxdepth' value='maxdepth'/>
@@ -359,6 +365,7 @@
<cd:variable name='previousoddpage' value='pageimpaireprecedente'/>
<cd:variable name='previouspage' value='pageprecedente'/>
<cd:variable name='previoussubpage' value='souspageprecedente'/>
+ <cd:variable name='print' value='print'/>
<cd:variable name='printable' value='editable'/>
<cd:variable name='process' value='process'/>
<cd:variable name='product' value='produit'/>
@@ -366,6 +373,7 @@
<cd:variable name='project' value='projet'/>
<cd:variable name='protected' value='protege'/>
<cd:variable name='quadruple' value='quadruple'/>
+ <cd:variable name='quarterline' value='quarterline'/>
<cd:variable name='quotation' value='citation'/>
<cd:variable name='quote' value='citer'/>
<cd:variable name='ran' value='cours'/>
@@ -500,6 +508,8 @@
<cd:variable name='unavailable' value='indisponible'/>
<cd:variable name='underbar' value='souslignetout'/>
<cd:variable name='underbars' value='sousligne'/>
+ <cd:variable name='understrike' value='understrike'/>
+ <cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unit' value='unite'/>
<cd:variable name='units' value='unites'/>
<cd:variable name='unknown' value='inconnu'/>
@@ -519,6 +529,7 @@
<cd:variable name='white' value='blanc'/>
<cd:variable name='wide' value='ample'/>
<cd:variable name='width' value='largeur'/>
+ <cd:variable name='word' value='mot'/>
<cd:variable name='xml' value='xml'/>
<cd:variable name='year' value='annee'/>
<cd:variable name='yes' value='oui'/>
@@ -539,6 +550,7 @@
<cd:constant name='alignsymbol' value='alignsymbol'/>
<cd:constant name='aligntitle' value='alignementtitre'/>
<cd:constant name='alternative' value='alternative'/>
+ <cd:constant name='anchor' value='anchor'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arrow' value='fleche'/>
@@ -558,6 +570,8 @@
<cd:constant name='autohang' value='autohang'/>
<cd:constant name='autostrut' value='autostrut'/>
<cd:constant name='autowidth' value='autolargeur'/>
+ <cd:constant name='availableheight' value='availableheight'/>
+ <cd:constant name='availablewidth' value='availablewidth'/>
<cd:constant name='axis' value='axe'/>
<cd:constant name='background' value='arriereplan'/>
<cd:constant name='backgroundcolor' value='couleurarriereplan'/>
@@ -577,6 +591,7 @@
<cd:constant name='blank' value='vide'/>
<cd:constant name='blockway' value='blockway'/>
<cd:constant name='bodyfont' value='policecorps'/>
+ <cd:constant name='boffset' value='boffset'/>
<cd:constant name='bookmark' value='marquepage'/>
<cd:constant name='bottom' value='inf'/>
<cd:constant name='bottomafter' value='bottomafter'/>
@@ -608,6 +623,8 @@
<cd:constant name='commandafter' value='commandeapres'/>
<cd:constant name='commandbefore' value='commandeavant'/>
<cd:constant name='commands' value='commandes'/>
+ <cd:constant name='commentoffset' value='commentoffset'/>
+ <cd:constant name='compact' value='compact'/>
<cd:constant name='component' value='composant'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
@@ -621,6 +638,7 @@
<cd:constant name='coupling' value='couplage'/>
<cd:constant name='couplingway' value='modecouplage'/>
<cd:constant name='criterium' value='critere'/>
+ <cd:constant name='css' value='css'/>
<cd:constant name='current' value='courant'/>
<cd:constant name='cutspace' value='cutspace'/>
<cd:constant name='dash' value='pointille'/>
@@ -649,11 +667,13 @@
<cd:constant name='editoretallimit' value='editoretallimit'/>
<cd:constant name='editoretaltext' value='editoretaltext'/>
<cd:constant name='empty' value='vide'/>
+ <cd:constant name='entities' value='entities'/>
<cd:constant name='entries' value='entries'/>
<cd:constant name='equalheight' value='equalheight'/>
<cd:constant name='equalwidth' value='equalwidth'/>
<cd:constant name='escape' value='escape'/>
<cd:constant name='evenmargin' value='margepaire'/>
+ <cd:constant name='exitoffset' value='labeloffset'/>
<cd:constant name='expansion' value='expansion'/>
<cd:constant name='export' value='export'/>
<cd:constant name='extras' value='extras'/>
@@ -690,6 +710,7 @@
<cd:constant name='global' value='global'/>
<cd:constant name='grid' value='grille'/>
<cd:constant name='hang' value='suspend'/>
+ <cd:constant name='hcompact' value='hcompact'/>
<cd:constant name='headalign' value='headalign'/>
<cd:constant name='headcolor' value='couleurtete'/>
<cd:constant name='headcommand' value='commandetete'/>
@@ -718,6 +739,7 @@
<cd:constant name='inner' value='interieur'/>
<cd:constant name='innermargin' value='margeinterieure'/>
<cd:constant name='inputfile' value='fichierentree'/>
+ <cd:constant name='insidesection' value='insidesection'/>
<cd:constant name='intent' value='intent'/>
<cd:constant name='interaction' value='interaction'/>
<cd:constant name='interlinespace' value='espaceinterligne'/>
@@ -730,8 +752,10 @@
<cd:constant name='keys' value='keys'/>
<cd:constant name='keyword' value='motcle'/>
<cd:constant name='label' value='etiquette'/>
+ <cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
+ <cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='gauche'/>
<cd:constant name='leftcolor' value='couleurgauche'/>
<cd:constant name='leftcompoundhyphen' value='leftcompoundhyphen'/>
@@ -760,6 +784,7 @@
<cd:constant name='listtext' value='texteliste'/>
<cd:constant name='local' value='local'/>
<cd:constant name='location' value='emplacement'/>
+ <cd:constant name='loffset' value='loffset'/>
<cd:constant name='logo' value='logo'/>
<cd:constant name='logos' value='logos'/>
<cd:constant name='marcolor' value='couleurmarquage'/>
@@ -836,6 +861,7 @@
<cd:constant name='page' value='page'/>
<cd:constant name='pageboundaries' value='limitespage'/>
<cd:constant name='pagecolor' value='couleurpage'/>
+ <cd:constant name='pagecolormodel' value='pagecolormodel'/>
<cd:constant name='pagecommand' value='commandepage'/>
<cd:constant name='pageconversion' value='pageconversion'/>
<cd:constant name='pageconversionset' value='pageconversionset'/>
@@ -876,6 +902,7 @@
<cd:constant name='preview' value='previsualisation'/>
<cd:constant name='previous' value='precedent'/>
<cd:constant name='previousnumber' value='numeroprecedent'/>
+ <cd:constant name='printable' value='editable'/>
<cd:constant name='process' value='process'/>
<cd:constant name='profile' value='profile'/>
<cd:constant name='pubsep' value='pubsep'/>
@@ -888,6 +915,7 @@
<cd:constant name='reference' value='reference'/>
<cd:constant name='referenceprefix' value='referenceprefix'/>
<cd:constant name='referencing' value='referencing'/>
+ <cd:constant name='region' value='region'/>
<cd:constant name='regionin' value='entreregion'/>
<cd:constant name='regionout' value='regionexterieure'/>
<cd:constant name='repeat' value='repete'/>
@@ -912,9 +940,11 @@
<cd:constant name='rightsubsentence' value='sousphrasedroite'/>
<cd:constant name='righttext' value='textedroit'/>
<cd:constant name='rightwidth' value='largeurdroite'/>
+ <cd:constant name='roffset' value='roffset'/>
<cd:constant name='rotation' value='rotation'/>
<cd:constant name='rule' value='ligne'/>
<cd:constant name='rulecolor' value='couleurligne'/>
+ <cd:constant name='rulecommand' value='rulecommand'/>
<cd:constant name='rulethickness' value='epaisseurligne'/>
<cd:constant name='samepage' value='memepage'/>
<cd:constant name='sample' value='echantillon'/>
@@ -972,6 +1002,7 @@
<cd:constant name='subtitle' value='soustitre'/>
<cd:constant name='suffix' value='suffix'/>
<cd:constant name='suffixseparator' value='suffixseparator'/>
+ <cd:constant name='suffixstopper' value='suffixstopper'/>
<cd:constant name='surnamesep' value='surnamesep'/>
<cd:constant name='sx' value='sx'/>
<cd:constant name='sy' value='sy'/>
@@ -989,6 +1020,7 @@
<cd:constant name='textcolor' value='couleurtexte'/>
<cd:constant name='textcommand' value='commandetexte'/>
<cd:constant name='textdistance' value='distancetexte'/>
+ <cd:constant name='textheight' value='hauteurtexte'/>
<cd:constant name='textlayer' value='calquetexte'/>
<cd:constant name='textmargin' value='margetexte'/>
<cd:constant name='textmethod' value='textmethod'/>
@@ -1006,6 +1038,7 @@
<cd:constant name='titleright' value='titleright'/>
<cd:constant name='titlestyle' value='styletitre'/>
<cd:constant name='to' value='vers'/>
+ <cd:constant name='toffset' value='toffset'/>
<cd:constant name='tolerance' value='tolerance'/>
<cd:constant name='top' value='sup'/>
<cd:constant name='topdistance' value='distancesup'/>
@@ -1022,6 +1055,8 @@
<cd:constant name='validate' value='valider'/>
<cd:constant name='values' value='values'/>
<cd:constant name='vcommand' value='vcommande'/>
+ <cd:constant name='vcompact' value='vcompact'/>
+ <cd:constant name='vector' value='vector'/>
<cd:constant name='veroffset' value='veroffset'/>
<cd:constant name='vfil' value='vfil'/>
<cd:constant name='voffset' value='voffset'/>
@@ -1031,6 +1066,7 @@
<cd:constant name='white' value='blanc'/>
<cd:constant name='width' value='largeur'/>
<cd:constant name='xfactor' value='xfactor'/>
+ <cd:constant name='xhtml' value='xhtml'/>
<cd:constant name='xmax' value='xmax'/>
<cd:constant name='xoffset' value='xoffset'/>
<cd:constant name='xscale' value='xscale'/>
@@ -1051,8 +1087,6 @@
<cd:element name='complete' value='complete'/>
<cd:element name='coupled' value='couple'/>
<cd:element name='currentlocal' value='localcourant'/>
- <cd:element name='emptyone' value='vide'/>
- <cd:element name='emptytwo' value='vide'/>
<cd:element name='end' value='fin'/>
<cd:element name='endsetup' value=''/>
<cd:element name='get' value='obtient'/>
@@ -1168,7 +1202,7 @@
<cd:command name='defineframedtext' value='defineframedtext'/>
<cd:command name='definehbox' value='definithbox'/>
<cd:command name='definehead' value='definittete'/>
- <cd:command name='defineindenting' value='definitcompoalinea'/>
+ <cd:command name='defineindentedtext' value='defineindentedtext'/>
<cd:command name='defineinmargin' value='definitdansmarge'/>
<cd:command name='defineinteractionmenu' value='definitmenuinteraction'/>
<cd:command name='defineitemgroup' value='defineitemgroup'/>
@@ -1364,7 +1398,6 @@
<cd:command name='pagenumber' value='numeropage'/>
<cd:command name='pageoffset' value='pageoffset'/>
<cd:command name='pagereference' value='referencepage'/>
- <cd:command name='pagetype' value='tapepage'/>
<cd:command name='paperheight' value='hauteurpapier'/>
<cd:command name='paperwidth' value='largeurpapier'/>
<cd:command name='periods' value='periodes'/>
@@ -1480,7 +1513,7 @@
<cd:command name='setupheads' value='regletetes'/>
<cd:command name='setupheadtext' value='regletextetete'/>
<cd:command name='setuphyphenmark' value='reglemarquagehyphenation'/>
- <cd:command name='setupindentations' value='reglealineas'/>
+ <cd:command name='setupindentedtext' value='setupindentedtext'/>
<cd:command name='setupindenting' value='reglecomposeenalinea'/>
<cd:command name='setupinmargin' value='regledansmarge'/>
<cd:command name='setupinteraction' value='regleinteraction'/>
diff --git a/Master/texmf-dist/tex/context/interface/keys-it.xml b/Master/texmf-dist/tex/context/interface/keys-it.xml
index 0a156e8425e..aa846599fa8 100644
--- a/Master/texmf-dist/tex/context/interface/keys-it.xml
+++ b/Master/texmf-dist/tex/context/interface/keys-it.xml
@@ -7,6 +7,8 @@
<cd:variables>
<cd:variable name='Addition' value='Aggiunta'/>
<cd:variable name='Balloon' value='Pallone'/>
+ <cd:variable name='Cap' value='Cap'/>
+ <cd:variable name='Capital' value='Maiuscolo'/>
<cd:variable name='Character' value='Lettera'/>
<cd:variable name='Characters' value='Lettere'/>
<cd:variable name='CloseDocument' value='ChiudiDocumento'/>
@@ -64,6 +66,9 @@
<cd:variable name='ViewerHelp' value='AiutoVisualizzatore'/>
<cd:variable name='WEEKDAY' value='GIORNOSETTIMANA'/>
<cd:variable name='WORD' value='PAROLA'/>
+ <cd:variable name='WORDS' value='PAROLE'/>
+ <cd:variable name='Word' value='Parola'/>
+ <cd:variable name='Words' value='Parole'/>
<cd:variable name='abbreviation' value='abbreviazione'/>
<cd:variable name='abbreviations' value='abbreviazioni'/>
<cd:variable name='absolute' value='assoluto'/>
@@ -278,6 +283,7 @@
<cd:variable name='marking' value='marcatura'/>
<cd:variable name='mathalignment' value='mathalignment'/>
<cd:variable name='mathcases' value='mathcases'/>
+ <cd:variable name='mathematics' value='matematica'/>
<cd:variable name='mathmatrix' value='mathmatrix'/>
<cd:variable name='max' value='max'/>
<cd:variable name='maxdepth' value='maxdepth'/>
@@ -359,6 +365,7 @@
<cd:variable name='previousoddpage' value='paginadispariprecedente'/>
<cd:variable name='previouspage' value='paginaprecedente'/>
<cd:variable name='previoussubpage' value='sottopaginaprecedente'/>
+ <cd:variable name='print' value='print'/>
<cd:variable name='printable' value='stampabile'/>
<cd:variable name='process' value='process'/>
<cd:variable name='product' value='prodotto'/>
@@ -366,6 +373,7 @@
<cd:variable name='project' value='progetto'/>
<cd:variable name='protected' value='protetto'/>
<cd:variable name='quadruple' value='quadruplo'/>
+ <cd:variable name='quarterline' value='quarterline'/>
<cd:variable name='quotation' value='citazione'/>
<cd:variable name='quote' value='menzione'/>
<cd:variable name='ran' value='corse'/>
@@ -500,6 +508,8 @@
<cd:variable name='unavailable' value='nondisponibile'/>
<cd:variable name='underbar' value='sottolinea'/>
<cd:variable name='underbars' value='sottolinee'/>
+ <cd:variable name='understrike' value='understrike'/>
+ <cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unit' value='unita'/>
<cd:variable name='units' value='unita'/>
<cd:variable name='unknown' value='ignoto'/>
@@ -519,6 +529,7 @@
<cd:variable name='white' value='bianco'/>
<cd:variable name='wide' value='ampio'/>
<cd:variable name='width' value='ampiezza'/>
+ <cd:variable name='word' value='parola'/>
<cd:variable name='xml' value='xml'/>
<cd:variable name='year' value='anno'/>
<cd:variable name='yes' value='si'/>
@@ -539,6 +550,7 @@
<cd:constant name='alignsymbol' value='alignsymbol'/>
<cd:constant name='aligntitle' value='allineatitolo'/>
<cd:constant name='alternative' value='alternativa'/>
+ <cd:constant name='anchor' value='anchor'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arrow' value='freccia'/>
@@ -558,6 +570,8 @@
<cd:constant name='autohang' value='autohang'/>
<cd:constant name='autostrut' value='autostrut'/>
<cd:constant name='autowidth' value='autoampiezza'/>
+ <cd:constant name='availableheight' value='availableheight'/>
+ <cd:constant name='availablewidth' value='availablewidth'/>
<cd:constant name='axis' value='asse'/>
<cd:constant name='background' value='sfondo'/>
<cd:constant name='backgroundcolor' value='coloresfondo'/>
@@ -577,6 +591,7 @@
<cd:constant name='blank' value='rigovuoto'/>
<cd:constant name='blockway' value='blockway'/>
<cd:constant name='bodyfont' value='fonttesto'/>
+ <cd:constant name='boffset' value='boffset'/>
<cd:constant name='bookmark' value='segnalibro'/>
<cd:constant name='bottom' value='fondo'/>
<cd:constant name='bottomafter' value='bottomafter'/>
@@ -608,6 +623,8 @@
<cd:constant name='commandafter' value='comdandodopo'/>
<cd:constant name='commandbefore' value='comandoprima'/>
<cd:constant name='commands' value='comandi'/>
+ <cd:constant name='commentoffset' value='commentoffset'/>
+ <cd:constant name='compact' value='compact'/>
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
@@ -621,6 +638,7 @@
<cd:constant name='coupling' value='accoppiamento'/>
<cd:constant name='couplingway' value='modoaccoppiamento'/>
<cd:constant name='criterium' value='criterio'/>
+ <cd:constant name='css' value='css'/>
<cd:constant name='current' value='corrente'/>
<cd:constant name='cutspace' value='cutspace'/>
<cd:constant name='dash' value='dash'/>
@@ -649,11 +667,13 @@
<cd:constant name='editoretallimit' value='editoretallimit'/>
<cd:constant name='editoretaltext' value='editoretaltext'/>
<cd:constant name='empty' value='vuoto'/>
+ <cd:constant name='entities' value='entities'/>
<cd:constant name='entries' value='entries'/>
<cd:constant name='equalheight' value='equalheight'/>
<cd:constant name='equalwidth' value='equalwidth'/>
<cd:constant name='escape' value='escape'/>
<cd:constant name='evenmargin' value='marginepari'/>
+ <cd:constant name='exitoffset' value='labeloffset'/>
<cd:constant name='expansion' value='espansione'/>
<cd:constant name='export' value='export'/>
<cd:constant name='extras' value='extras'/>
@@ -690,6 +710,7 @@
<cd:constant name='global' value='globale'/>
<cd:constant name='grid' value='griglia'/>
<cd:constant name='hang' value='sospendi'/>
+ <cd:constant name='hcompact' value='hcompact'/>
<cd:constant name='headalign' value='headalign'/>
<cd:constant name='headcolor' value='coloretesta'/>
<cd:constant name='headcommand' value='headcommand'/>
@@ -718,6 +739,7 @@
<cd:constant name='inner' value='interno'/>
<cd:constant name='innermargin' value='margineinterno'/>
<cd:constant name='inputfile' value='inputfile'/>
+ <cd:constant name='insidesection' value='insidesection'/>
<cd:constant name='intent' value='intent'/>
<cd:constant name='interaction' value='interazione'/>
<cd:constant name='interlinespace' value='interlinea'/>
@@ -730,8 +752,10 @@
<cd:constant name='keys' value='keys'/>
<cd:constant name='keyword' value='parolachiave'/>
<cd:constant name='label' value='etichetta'/>
+ <cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
+ <cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='sinistra'/>
<cd:constant name='leftcolor' value='coloresinistra'/>
<cd:constant name='leftcompoundhyphen' value='leftcompoundhyphen'/>
@@ -760,6 +784,7 @@
<cd:constant name='listtext' value='listtext'/>
<cd:constant name='local' value='locale'/>
<cd:constant name='location' value='luogo'/>
+ <cd:constant name='loffset' value='loffset'/>
<cd:constant name='logo' value='logo'/>
<cd:constant name='logos' value='loghi'/>
<cd:constant name='marcolor' value='coloremarcatura'/>
@@ -836,6 +861,7 @@
<cd:constant name='page' value='pagina'/>
<cd:constant name='pageboundaries' value='limitipagina'/>
<cd:constant name='pagecolor' value='colorepagina'/>
+ <cd:constant name='pagecolormodel' value='pagecolormodel'/>
<cd:constant name='pagecommand' value='comandopagina'/>
<cd:constant name='pageconversion' value='pageconversion'/>
<cd:constant name='pageconversionset' value='pageconversionset'/>
@@ -876,6 +902,7 @@
<cd:constant name='preview' value='anteprima'/>
<cd:constant name='previous' value='precedente'/>
<cd:constant name='previousnumber' value='numeroprecedente'/>
+ <cd:constant name='printable' value='stampabile'/>
<cd:constant name='process' value='process'/>
<cd:constant name='profile' value='profile'/>
<cd:constant name='pubsep' value='pubsep'/>
@@ -888,6 +915,7 @@
<cd:constant name='reference' value='riferimento'/>
<cd:constant name='referenceprefix' value='referenceprefix'/>
<cd:constant name='referencing' value='referencing'/>
+ <cd:constant name='region' value='region'/>
<cd:constant name='regionin' value='entraregione'/>
<cd:constant name='regionout' value='esciregione'/>
<cd:constant name='repeat' value='ripeti'/>
@@ -912,9 +940,11 @@
<cd:constant name='rightsubsentence' value='sottofrasedestra'/>
<cd:constant name='righttext' value='testodestro'/>
<cd:constant name='rightwidth' value='ampiezzadestra'/>
+ <cd:constant name='roffset' value='roffset'/>
<cd:constant name='rotation' value='rotazione'/>
<cd:constant name='rule' value='linea'/>
<cd:constant name='rulecolor' value='colorelinea'/>
+ <cd:constant name='rulecommand' value='rulecommand'/>
<cd:constant name='rulethickness' value='spessorelinea'/>
<cd:constant name='samepage' value='stessapagina'/>
<cd:constant name='sample' value='campione'/>
@@ -972,6 +1002,7 @@
<cd:constant name='subtitle' value='sottotitolo'/>
<cd:constant name='suffix' value='suffix'/>
<cd:constant name='suffixseparator' value='suffixseparator'/>
+ <cd:constant name='suffixstopper' value='suffixstopper'/>
<cd:constant name='surnamesep' value='surnamesep'/>
<cd:constant name='sx' value='sx'/>
<cd:constant name='sy' value='sy'/>
@@ -989,6 +1020,7 @@
<cd:constant name='textcolor' value='coloretesto'/>
<cd:constant name='textcommand' value='comandotesto'/>
<cd:constant name='textdistance' value='distanzatesto'/>
+ <cd:constant name='textheight' value='altezzatesto'/>
<cd:constant name='textlayer' value='textlayer'/>
<cd:constant name='textmargin' value='textmargin'/>
<cd:constant name='textmethod' value='textmethod'/>
@@ -1006,6 +1038,7 @@
<cd:constant name='titleright' value='titleright'/>
<cd:constant name='titlestyle' value='stiletitolo'/>
<cd:constant name='to' value='verso'/>
+ <cd:constant name='toffset' value='toffset'/>
<cd:constant name='tolerance' value='tolleranza'/>
<cd:constant name='top' value='cima'/>
<cd:constant name='topdistance' value='distanzacima'/>
@@ -1022,6 +1055,8 @@
<cd:constant name='validate' value='verifica'/>
<cd:constant name='values' value='values'/>
<cd:constant name='vcommand' value='vcomando'/>
+ <cd:constant name='vcompact' value='vcompact'/>
+ <cd:constant name='vector' value='vector'/>
<cd:constant name='veroffset' value='veroffset'/>
<cd:constant name='vfil' value='vfil'/>
<cd:constant name='voffset' value='voffset'/>
@@ -1031,6 +1066,7 @@
<cd:constant name='white' value='bianco'/>
<cd:constant name='width' value='ampiezza'/>
<cd:constant name='xfactor' value='xfactor'/>
+ <cd:constant name='xhtml' value='xhtml'/>
<cd:constant name='xmax' value='xmax'/>
<cd:constant name='xoffset' value='xoffset'/>
<cd:constant name='xscale' value='xscale'/>
@@ -1051,8 +1087,6 @@
<cd:element name='complete' value='completo'/>
<cd:element name='coupled' value='accoppiato'/>
<cd:element name='currentlocal' value='correntelocale'/>
- <cd:element name='emptyone' value='prazdne'/>
- <cd:element name='emptytwo' value='vuoti'/>
<cd:element name='end' value='fine'/>
<cd:element name='endsetup' value=''/>
<cd:element name='get' value='prendi'/>
@@ -1168,7 +1202,7 @@
<cd:command name='defineframedtext' value='definiscitestoincorniciato'/>
<cd:command name='definehbox' value='definiscihbox'/>
<cd:command name='definehead' value='definiscitesta'/>
- <cd:command name='defineindenting' value='definiscirientro'/>
+ <cd:command name='defineindentedtext' value='defineindentedtext'/>
<cd:command name='defineinmargin' value='defineinmargin'/>
<cd:command name='defineinteractionmenu' value='definiscimenuinterazione'/>
<cd:command name='defineitemgroup' value='defineitemgroup'/>
@@ -1364,7 +1398,6 @@
<cd:command name='pagenumber' value='numeropagina'/>
<cd:command name='pageoffset' value='pageoffset'/>
<cd:command name='pagereference' value='riferimentopagina'/>
- <cd:command name='pagetype' value='tipopagina'/>
<cd:command name='paperheight' value='altezzacarta'/>
<cd:command name='paperwidth' value='ampiezzacarta'/>
<cd:command name='periods' value='punti'/>
@@ -1480,7 +1513,7 @@
<cd:command name='setupheads' value='impostateste'/>
<cd:command name='setupheadtext' value='impostatestointestazioni'/>
<cd:command name='setuphyphenmark' value='impostasegnosillabazione'/>
- <cd:command name='setupindentations' value='impostarientri'/>
+ <cd:command name='setupindentedtext' value='setupindentedtext'/>
<cd:command name='setupindenting' value='impostarientro'/>
<cd:command name='setupinmargin' value='impostainmargine'/>
<cd:command name='setupinteraction' value='impostainterazione'/>
diff --git a/Master/texmf-dist/tex/context/interface/keys-nl.xml b/Master/texmf-dist/tex/context/interface/keys-nl.xml
index eb156cf5a50..a3110642cde 100644
--- a/Master/texmf-dist/tex/context/interface/keys-nl.xml
+++ b/Master/texmf-dist/tex/context/interface/keys-nl.xml
@@ -7,6 +7,8 @@
<cd:variables>
<cd:variable name='Addition' value='Toevoeging'/>
<cd:variable name='Balloon' value='Ballon'/>
+ <cd:variable name='Cap' value='Kap'/>
+ <cd:variable name='Capital' value='Kapitaal'/>
<cd:variable name='Character' value='Letter'/>
<cd:variable name='Characters' value='Letters'/>
<cd:variable name='CloseDocument' value='SluitDocument'/>
@@ -64,6 +66,9 @@
<cd:variable name='ViewerHelp' value='ViewerHelp'/>
<cd:variable name='WEEKDAY' value='WEEKDAG'/>
<cd:variable name='WORD' value='WOORD'/>
+ <cd:variable name='WORDS' value='WOORDEN'/>
+ <cd:variable name='Word' value='Woord'/>
+ <cd:variable name='Words' value='Woorden'/>
<cd:variable name='abbreviation' value='afkorting'/>
<cd:variable name='abbreviations' value='afkortingen'/>
<cd:variable name='absolute' value='absoluut'/>
@@ -278,6 +283,7 @@
<cd:variable name='marking' value='markering'/>
<cd:variable name='mathalignment' value='wiskundeuitlijnen'/>
<cd:variable name='mathcases' value='mathcases'/>
+ <cd:variable name='mathematics' value='wiskunde'/>
<cd:variable name='mathmatrix' value='wiskundematrix'/>
<cd:variable name='max' value='max'/>
<cd:variable name='maxdepth' value='maxdepth'/>
@@ -359,6 +365,7 @@
<cd:variable name='previousoddpage' value='vorigeonevenpagina'/>
<cd:variable name='previouspage' value='vorigepagina'/>
<cd:variable name='previoussubpage' value='vorigesubpagina'/>
+ <cd:variable name='print' value='print'/>
<cd:variable name='printable' value='printbaar'/>
<cd:variable name='process' value='proces'/>
<cd:variable name='product' value='produkt'/>
@@ -366,6 +373,7 @@
<cd:variable name='project' value='project'/>
<cd:variable name='protected' value='beschermd'/>
<cd:variable name='quadruple' value='viertal'/>
+ <cd:variable name='quarterline' value='kwartregel'/>
<cd:variable name='quotation' value='citaat'/>
<cd:variable name='quote' value='citeer'/>
<cd:variable name='ran' value='ran'/>
@@ -500,6 +508,8 @@
<cd:variable name='unavailable' value='nietbeschikbaar'/>
<cd:variable name='underbar' value='onderstreep'/>
<cd:variable name='underbars' value='onderstrepen'/>
+ <cd:variable name='understrike' value='understrike'/>
+ <cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unit' value='eenheid'/>
<cd:variable name='units' value='eenheden'/>
<cd:variable name='unknown' value='onbekend'/>
@@ -519,6 +529,7 @@
<cd:variable name='white' value='wit'/>
<cd:variable name='wide' value='breed'/>
<cd:variable name='width' value='breedte'/>
+ <cd:variable name='word' value='woord'/>
<cd:variable name='xml' value='xml'/>
<cd:variable name='year' value='jaar'/>
<cd:variable name='yes' value='ja'/>
@@ -539,6 +550,7 @@
<cd:constant name='alignsymbol' value='alignsymbol'/>
<cd:constant name='aligntitle' value='titeluitlijnen'/>
<cd:constant name='alternative' value='variant'/>
+ <cd:constant name='anchor' value='anker'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arrow' value='pijl'/>
@@ -558,6 +570,8 @@
<cd:constant name='autohang' value='autohang'/>
<cd:constant name='autostrut' value='autostrut'/>
<cd:constant name='autowidth' value='autobreedte'/>
+ <cd:constant name='availableheight' value='beschikbarehoogte'/>
+ <cd:constant name='availablewidth' value='beschikbarebreedte'/>
<cd:constant name='axis' value='assenstelsel'/>
<cd:constant name='background' value='achtergrond'/>
<cd:constant name='backgroundcolor' value='achtergrondkleur'/>
@@ -577,6 +591,7 @@
<cd:constant name='blank' value='blanko'/>
<cd:constant name='blockway' value='blokwijze'/>
<cd:constant name='bodyfont' value='korps'/>
+ <cd:constant name='boffset' value='boffset'/>
<cd:constant name='bookmark' value='bookmark'/>
<cd:constant name='bottom' value='onder'/>
<cd:constant name='bottomafter' value='bottomafter'/>
@@ -608,6 +623,8 @@
<cd:constant name='commandafter' value='nacommando'/>
<cd:constant name='commandbefore' value='voorcommando'/>
<cd:constant name='commands' value='commandos'/>
+ <cd:constant name='commentoffset' value='commentoffset'/>
+ <cd:constant name='compact' value='compact'/>
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='koppelteken'/>
<cd:constant name='compress' value='comprimeren'/>
@@ -621,6 +638,7 @@
<cd:constant name='coupling' value='koppeling'/>
<cd:constant name='couplingway' value='koppelwijze'/>
<cd:constant name='criterium' value='criterium'/>
+ <cd:constant name='css' value='css'/>
<cd:constant name='current' value='huidige'/>
<cd:constant name='cutspace' value='snijwit'/>
<cd:constant name='dash' value='streep'/>
@@ -634,7 +652,7 @@
<cd:constant name='depth' value='diepte'/>
<cd:constant name='depthcorrection' value='dieptecorrectie'/>
<cd:constant name='direction' value='richting'/>
- <cd:constant name='directory' value='gebied'/>
+ <cd:constant name='directory' value='directory'/>
<cd:constant name='display' value='scherm'/>
<cd:constant name='distance' value='afstand'/>
<cd:constant name='dot' value='punt'/>
@@ -649,11 +667,13 @@
<cd:constant name='editoretallimit' value='editoretallimit'/>
<cd:constant name='editoretaltext' value='editoretaltext'/>
<cd:constant name='empty' value='leeg'/>
+ <cd:constant name='entities' value='entities'/>
<cd:constant name='entries' value='ingangen'/>
<cd:constant name='equalheight' value='equalheight'/>
<cd:constant name='equalwidth' value='equalwidth'/>
<cd:constant name='escape' value='escape'/>
<cd:constant name='evenmargin' value='evenmarge'/>
+ <cd:constant name='exitoffset' value='labeloffset'/>
<cd:constant name='expansion' value='expansie'/>
<cd:constant name='export' value='exporteer'/>
<cd:constant name='extras' value='extras'/>
@@ -690,6 +710,7 @@
<cd:constant name='global' value='globaal'/>
<cd:constant name='grid' value='grid'/>
<cd:constant name='hang' value='hang'/>
+ <cd:constant name='hcompact' value='hcomprimeer'/>
<cd:constant name='headalign' value='kopuitlijnen'/>
<cd:constant name='headcolor' value='kopkleur'/>
<cd:constant name='headcommand' value='kopcommando'/>
@@ -718,6 +739,7 @@
<cd:constant name='inner' value='binnen'/>
<cd:constant name='innermargin' value='binnenmarge'/>
<cd:constant name='inputfile' value='inputfile'/>
+ <cd:constant name='insidesection' value='binnensectie'/>
<cd:constant name='intent' value='intent'/>
<cd:constant name='interaction' value='interactie'/>
<cd:constant name='interlinespace' value='interlinie'/>
@@ -730,8 +752,10 @@
<cd:constant name='keys' value='sleutels'/>
<cd:constant name='keyword' value='trefwoord'/>
<cd:constant name='label' value='label'/>
+ <cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
+ <cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='links'/>
<cd:constant name='leftcolor' value='linkerkleur'/>
<cd:constant name='leftcompoundhyphen' value='linkerkoppelteken'/>
@@ -760,6 +784,7 @@
<cd:constant name='listtext' value='lijsttekst'/>
<cd:constant name='local' value='lokaal'/>
<cd:constant name='location' value='plaats'/>
+ <cd:constant name='loffset' value='loffset'/>
<cd:constant name='logo' value='logo'/>
<cd:constant name='logos' value='logos'/>
<cd:constant name='marcolor' value='markleur'/>
@@ -827,7 +852,7 @@
<cd:constant name='openpage' value='openpagina'/>
<cd:constant name='openpageaction' value='openpaginaactie'/>
<cd:constant name='option' value='optie'/>
- <cd:constant name='order' value='order'/>
+ <cd:constant name='order' value='volgorde'/>
<cd:constant name='orientation' value='orientatie'/>
<cd:constant name='otherstext' value='otherstext'/>
<cd:constant name='outermargin' value='buitenmarge'/>
@@ -836,6 +861,7 @@
<cd:constant name='page' value='pagina'/>
<cd:constant name='pageboundaries' value='paginaovergangen'/>
<cd:constant name='pagecolor' value='paginakleur'/>
+ <cd:constant name='pagecolormodel' value='paginakleurmodel'/>
<cd:constant name='pagecommand' value='paginacommando'/>
<cd:constant name='pageconversion' value='pageconversion'/>
<cd:constant name='pageconversionset' value='pageconversionset'/>
@@ -876,6 +902,7 @@
<cd:constant name='preview' value='preview'/>
<cd:constant name='previous' value='vorige'/>
<cd:constant name='previousnumber' value='vorigenummer'/>
+ <cd:constant name='printable' value='printbaar'/>
<cd:constant name='process' value='proces'/>
<cd:constant name='profile' value='profile'/>
<cd:constant name='pubsep' value='pubsep'/>
@@ -888,6 +915,7 @@
<cd:constant name='reference' value='verwijzing'/>
<cd:constant name='referenceprefix' value='referenceprefix'/>
<cd:constant name='referencing' value='refereren'/>
+ <cd:constant name='region' value='gebied'/>
<cd:constant name='regionin' value='gebiedin'/>
<cd:constant name='regionout' value='gebieduit'/>
<cd:constant name='repeat' value='herhaal'/>
@@ -912,9 +940,11 @@
<cd:constant name='rightsubsentence' value='rechtersubzin'/>
<cd:constant name='righttext' value='rechtertekst'/>
<cd:constant name='rightwidth' value='rechterbreedte'/>
+ <cd:constant name='roffset' value='roffset'/>
<cd:constant name='rotation' value='rotatie'/>
<cd:constant name='rule' value='lijn'/>
<cd:constant name='rulecolor' value='lijnkleur'/>
+ <cd:constant name='rulecommand' value='lijncommando'/>
<cd:constant name='rulethickness' value='lijndikte'/>
<cd:constant name='samepage' value='zelfdepagina'/>
<cd:constant name='sample' value='monster'/>
@@ -972,6 +1002,7 @@
<cd:constant name='subtitle' value='subtitel'/>
<cd:constant name='suffix' value='suffix'/>
<cd:constant name='suffixseparator' value='suffixscheider'/>
+ <cd:constant name='suffixstopper' value='suffixafsluiter'/>
<cd:constant name='surnamesep' value='surnamesep'/>
<cd:constant name='sx' value='sx'/>
<cd:constant name='sy' value='sy'/>
@@ -989,6 +1020,7 @@
<cd:constant name='textcolor' value='tekstkleur'/>
<cd:constant name='textcommand' value='tekstcommando'/>
<cd:constant name='textdistance' value='tekstafstand'/>
+ <cd:constant name='textheight' value='teksthoogte'/>
<cd:constant name='textlayer' value='tekstlaag'/>
<cd:constant name='textmargin' value='tekstmarge'/>
<cd:constant name='textmethod' value='tekstmethode'/>
@@ -1006,6 +1038,7 @@
<cd:constant name='titleright' value='titelrechts'/>
<cd:constant name='titlestyle' value='titelletter'/>
<cd:constant name='to' value='aan'/>
+ <cd:constant name='toffset' value='toffset'/>
<cd:constant name='tolerance' value='tolerantie'/>
<cd:constant name='top' value='boven'/>
<cd:constant name='topdistance' value='bovenafstand'/>
@@ -1022,6 +1055,8 @@
<cd:constant name='validate' value='valideer'/>
<cd:constant name='values' value='waarden'/>
<cd:constant name='vcommand' value='vcommando'/>
+ <cd:constant name='vcompact' value='vcomprimeer'/>
+ <cd:constant name='vector' value='vector'/>
<cd:constant name='veroffset' value='kopoffset'/>
<cd:constant name='vfil' value='vfil'/>
<cd:constant name='voffset' value='voffset'/>
@@ -1031,6 +1066,7 @@
<cd:constant name='white' value='wit'/>
<cd:constant name='width' value='breedte'/>
<cd:constant name='xfactor' value='xfactor'/>
+ <cd:constant name='xhtml' value='xhtml'/>
<cd:constant name='xmax' value='xmax'/>
<cd:constant name='xoffset' value='xoffset'/>
<cd:constant name='xscale' value='xschaal'/>
@@ -1051,8 +1087,6 @@
<cd:element name='complete' value='volledige'/>
<cd:element name='coupled' value='gekoppelde'/>
<cd:element name='currentlocal' value='huidigelokale'/>
- <cd:element name='emptyone' value='leeg'/>
- <cd:element name='emptytwo' value='lege'/>
<cd:element name='end' value='eindvan'/>
<cd:element name='endsetup' value='in'/>
<cd:element name='get' value='haal'/>
@@ -1168,7 +1202,7 @@
<cd:command name='defineframedtext' value='definieerkadertekst'/>
<cd:command name='definehbox' value='definieerhbox'/>
<cd:command name='definehead' value='definieerkop'/>
- <cd:command name='defineindenting' value='doorspringen'/>
+ <cd:command name='defineindentedtext' value='definieeringesprongentext'/>
<cd:command name='defineinmargin' value='definieerinmarge'/>
<cd:command name='defineinteractionmenu' value='definieerinteractiemenu'/>
<cd:command name='defineitemgroup' value='definieeritemgroep'/>
@@ -1364,7 +1398,6 @@
<cd:command name='pagenumber' value='paginanummer'/>
<cd:command name='pageoffset' value='paginaoffset'/>
<cd:command name='pagereference' value='paginareferentie'/>
- <cd:command name='pagetype' value='soortpagina'/>
<cd:command name='paperheight' value='papierhoogte'/>
<cd:command name='paperwidth' value='papierbreedte'/>
<cd:command name='periods' value='punten'/>
@@ -1480,7 +1513,7 @@
<cd:command name='setupheads' value='stelkoppenin'/>
<cd:command name='setupheadtext' value='stelkoptekstin'/>
<cd:command name='setuphyphenmark' value='stelkoppeltekenin'/>
- <cd:command name='setupindentations' value='steldoorspringenin'/>
+ <cd:command name='setupindentedtext' value='stelingesprongentextin'/>
<cd:command name='setupindenting' value='stelinspringenin'/>
<cd:command name='setupinmargin' value='stelinmargein'/>
<cd:command name='setupinteraction' value='stelinteractiein'/>
diff --git a/Master/texmf-dist/tex/context/interface/keys-pe.xml b/Master/texmf-dist/tex/context/interface/keys-pe.xml
index 2dd57b3d127..74afbdba574 100644
--- a/Master/texmf-dist/tex/context/interface/keys-pe.xml
+++ b/Master/texmf-dist/tex/context/interface/keys-pe.xml
@@ -7,6 +7,8 @@
<cd:variables>
<cd:variable name='Addition' value='جمع'/>
<cd:variable name='Balloon' value='بادکنک'/>
+ <cd:variable name='Cap' value='Cap'/>
+ <cd:variable name='Capital' value='Capital'/>
<cd:variable name='Character' value='Character'/>
<cd:variable name='Characters' value='Characters'/>
<cd:variable name='CloseDocument' value='بستن‌نوشتار'/>
@@ -64,6 +66,9 @@
<cd:variable name='ViewerHelp' value='کمک‌نمایشگر'/>
<cd:variable name='WEEKDAY' value='روزهÙته'/>
<cd:variable name='WORD' value='کلمه'/>
+ <cd:variable name='WORDS' value='WORDS'/>
+ <cd:variable name='Word' value='Word'/>
+ <cd:variable name='Words' value='Words'/>
<cd:variable name='abbreviation' value='اختصار'/>
<cd:variable name='abbreviations' value='اختصارات'/>
<cd:variable name='absolute' value='قطعی'/>
@@ -278,6 +283,7 @@
<cd:variable name='marking' value='نشانه‌گذاری'/>
<cd:variable name='mathalignment' value='تنظیم‌ریاضی'/>
<cd:variable name='mathcases' value='حالتهای‌ریاضی'/>
+ <cd:variable name='mathematics' value='ریاضی'/>
<cd:variable name='mathmatrix' value='ماتریش‌ریاضی'/>
<cd:variable name='max' value='بیشترین'/>
<cd:variable name='maxdepth' value='maxdepth'/>
@@ -359,6 +365,7 @@
<cd:variable name='previousoddpage' value='صÙحه‌Ùردقبلی'/>
<cd:variable name='previouspage' value='صÙحه‌قبلی'/>
<cd:variable name='previoussubpage' value='زیرصÙحه‌قبلی'/>
+ <cd:variable name='print' value='print'/>
<cd:variable name='printable' value='قابل‌چاپ'/>
<cd:variable name='process' value='پردازش'/>
<cd:variable name='product' value='محصول'/>
@@ -366,6 +373,7 @@
<cd:variable name='project' value='پروژه'/>
<cd:variable name='protected' value='Ø­Ùاظت‌شده'/>
<cd:variable name='quadruple' value='quadruple'/>
+ <cd:variable name='quarterline' value='quarterline'/>
<cd:variable name='quotation' value='نقل‌قول'/>
<cd:variable name='quote' value='نقل'/>
<cd:variable name='ran' value='برد'/>
@@ -500,6 +508,8 @@
<cd:variable name='unavailable' value='غیرموجود'/>
<cd:variable name='underbar' value='میله‌زیر'/>
<cd:variable name='underbars' value='میله‌‌های‌زیر'/>
+ <cd:variable name='understrike' value='understrike'/>
+ <cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unit' value='واحد'/>
<cd:variable name='units' value='واحدها'/>
<cd:variable name='unknown' value='ناشناس'/>
@@ -519,6 +529,7 @@
<cd:variable name='white' value='سÙید'/>
<cd:variable name='wide' value='گسترده'/>
<cd:variable name='width' value='عرض'/>
+ <cd:variable name='word' value='word'/>
<cd:variable name='xml' value='xml'/>
<cd:variable name='year' value='سال'/>
<cd:variable name='yes' value='بله'/>
@@ -539,6 +550,7 @@
<cd:constant name='alignsymbol' value='alignsymbol'/>
<cd:constant name='aligntitle' value='عنوان‌تنظیم'/>
<cd:constant name='alternative' value='جایگزین'/>
+ <cd:constant name='anchor' value='anchor'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arrow' value='پیکان'/>
@@ -558,6 +570,8 @@
<cd:constant name='autohang' value='آویزان‌خودکار'/>
<cd:constant name='autostrut' value='بست‌خودکار'/>
<cd:constant name='autowidth' value='عرض‌خودکار'/>
+ <cd:constant name='availableheight' value='availableheight'/>
+ <cd:constant name='availablewidth' value='availablewidth'/>
<cd:constant name='axis' value='محورها'/>
<cd:constant name='background' value='پس‌زمینه'/>
<cd:constant name='backgroundcolor' value='رنگ‌پس‌زمینه'/>
@@ -577,6 +591,7 @@
<cd:constant name='blank' value='خالی'/>
<cd:constant name='blockway' value='راه‌بلوک'/>
<cd:constant name='bodyfont' value='قلم‌بدنه'/>
+ <cd:constant name='boffset' value='boffset'/>
<cd:constant name='bookmark' value='چوبخط'/>
<cd:constant name='bottom' value='پایین'/>
<cd:constant name='bottomafter' value='bottomafter'/>
@@ -608,6 +623,8 @@
<cd:constant name='commandafter' value='Ùرمان‌بعداز'/>
<cd:constant name='commandbefore' value='Ùرمان‌قبل‌از'/>
<cd:constant name='commands' value='Ùرمانها'/>
+ <cd:constant name='commentoffset' value='commentoffset'/>
+ <cd:constant name='compact' value='compact'/>
<cd:constant name='component' value='مولÙÙ‡'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='Ùشردن'/>
@@ -621,6 +638,7 @@
<cd:constant name='coupling' value='تزویج'/>
<cd:constant name='couplingway' value='روش‌تزویج'/>
<cd:constant name='criterium' value='criterium'/>
+ <cd:constant name='css' value='css'/>
<cd:constant name='current' value='جاری'/>
<cd:constant name='cutspace' value='Ùضای‌برش'/>
<cd:constant name='dash' value='دش'/>
@@ -649,11 +667,13 @@
<cd:constant name='editoretallimit' value='editoretallimit'/>
<cd:constant name='editoretaltext' value='editoretaltext'/>
<cd:constant name='empty' value='تهی'/>
+ <cd:constant name='entities' value='entities'/>
<cd:constant name='entries' value='entries'/>
<cd:constant name='equalheight' value='ارتÙاع‌یکسان'/>
<cd:constant name='equalwidth' value='عرض‌یکسان'/>
<cd:constant name='escape' value='Ùرار'/>
<cd:constant name='evenmargin' value='حاشیه‌زوج'/>
+ <cd:constant name='exitoffset' value='labeloffset'/>
<cd:constant name='expansion' value='گسترش'/>
<cd:constant name='export' value='export'/>
<cd:constant name='extras' value='extras'/>
@@ -690,6 +710,7 @@
<cd:constant name='global' value='سراسری'/>
<cd:constant name='grid' value='توری'/>
<cd:constant name='hang' value='بیاویز'/>
+ <cd:constant name='hcompact' value='hcompact'/>
<cd:constant name='headalign' value='headalign'/>
<cd:constant name='headcolor' value='رنگ‌سر'/>
<cd:constant name='headcommand' value='Ùرمان‌سر'/>
@@ -718,6 +739,7 @@
<cd:constant name='inner' value='داخلی'/>
<cd:constant name='innermargin' value='حاشیه‌داخلی'/>
<cd:constant name='inputfile' value='پرونده‌ورودی'/>
+ <cd:constant name='insidesection' value='insidesection'/>
<cd:constant name='intent' value='intent'/>
<cd:constant name='interaction' value='پانل'/>
<cd:constant name='interlinespace' value='Ùضای‌بین‌خط'/>
@@ -730,8 +752,10 @@
<cd:constant name='keys' value='keys'/>
<cd:constant name='keyword' value='کلید‌واژه'/>
<cd:constant name='label' value='برچسب'/>
+ <cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
+ <cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='Ú†Ù¾'/>
<cd:constant name='leftcolor' value='رنگ‌چپ'/>
<cd:constant name='leftcompoundhyphen' value='leftcompoundhyphen'/>
@@ -760,6 +784,7 @@
<cd:constant name='listtext' value='متن‌لیست'/>
<cd:constant name='local' value='موضعی'/>
<cd:constant name='location' value='مکان'/>
+ <cd:constant name='loffset' value='loffset'/>
<cd:constant name='logo' value='آرم'/>
<cd:constant name='logos' value='آرمها'/>
<cd:constant name='marcolor' value='رنگ‌حاش'/>
@@ -836,6 +861,7 @@
<cd:constant name='page' value='صÙحه'/>
<cd:constant name='pageboundaries' value='مرزهای‌صÙحه'/>
<cd:constant name='pagecolor' value='رنگ‌صÙحه'/>
+ <cd:constant name='pagecolormodel' value='pagecolormodel'/>
<cd:constant name='pagecommand' value='Ùرمان‌صÙحه'/>
<cd:constant name='pageconversion' value='pageconversion'/>
<cd:constant name='pageconversionset' value='pageconversionset'/>
@@ -876,6 +902,7 @@
<cd:constant name='preview' value='پیش‌دید'/>
<cd:constant name='previous' value='قبلی'/>
<cd:constant name='previousnumber' value='شماره‌قبلی'/>
+ <cd:constant name='printable' value='قابل‌چاپ'/>
<cd:constant name='process' value='پردازش'/>
<cd:constant name='profile' value='profile'/>
<cd:constant name='pubsep' value='pubsep'/>
@@ -888,6 +915,7 @@
<cd:constant name='reference' value='مرجع'/>
<cd:constant name='referenceprefix' value='referenceprefix'/>
<cd:constant name='referencing' value='مراجعه'/>
+ <cd:constant name='region' value='region'/>
<cd:constant name='regionin' value='ناحیه‌درون'/>
<cd:constant name='regionout' value='ناحیه‌بیرون'/>
<cd:constant name='repeat' value='تکرار'/>
@@ -912,9 +940,11 @@
<cd:constant name='rightsubsentence' value='زیرجمله‌راست'/>
<cd:constant name='righttext' value='متن‌راست'/>
<cd:constant name='rightwidth' value='عرض‌راست'/>
+ <cd:constant name='roffset' value='roffset'/>
<cd:constant name='rotation' value='دوران'/>
<cd:constant name='rule' value='خط'/>
<cd:constant name='rulecolor' value='رنگ‌خط'/>
+ <cd:constant name='rulecommand' value='rulecommand'/>
<cd:constant name='rulethickness' value='ضخامت‌خط'/>
<cd:constant name='samepage' value='همان‌صÙحه'/>
<cd:constant name='sample' value='نمونه'/>
@@ -972,6 +1002,7 @@
<cd:constant name='subtitle' value='زیرعنوان'/>
<cd:constant name='suffix' value='پسوند'/>
<cd:constant name='suffixseparator' value='suffixseparator'/>
+ <cd:constant name='suffixstopper' value='suffixstopper'/>
<cd:constant name='surnamesep' value='surnamesep'/>
<cd:constant name='sx' value='sx'/>
<cd:constant name='sy' value='sy'/>
@@ -989,6 +1020,7 @@
<cd:constant name='textcolor' value='رنگ‌متن'/>
<cd:constant name='textcommand' value='Ùرمان‌متن'/>
<cd:constant name='textdistance' value='Ùاصله‌متن'/>
+ <cd:constant name='textheight' value='ارتÙاع‌متن'/>
<cd:constant name='textlayer' value='لایه‌متن'/>
<cd:constant name='textmargin' value='حاشیه‌متن'/>
<cd:constant name='textmethod' value='روش‌متن'/>
@@ -1006,6 +1038,7 @@
<cd:constant name='titleright' value='عنوان‌راست'/>
<cd:constant name='titlestyle' value='سبک‌عنوان'/>
<cd:constant name='to' value='به'/>
+ <cd:constant name='toffset' value='toffset'/>
<cd:constant name='tolerance' value='بردباری'/>
<cd:constant name='top' value='بالا'/>
<cd:constant name='topdistance' value='Ùاصله‌بالا'/>
@@ -1022,6 +1055,8 @@
<cd:constant name='validate' value='تاییداعتبار'/>
<cd:constant name='values' value='values'/>
<cd:constant name='vcommand' value='vcommand'/>
+ <cd:constant name='vcompact' value='vcompact'/>
+ <cd:constant name='vector' value='vector'/>
<cd:constant name='veroffset' value='Ø¢Ùست‌عم'/>
<cd:constant name='vfil' value='vfil'/>
<cd:constant name='voffset' value='Ø¢Ùست‌ع'/>
@@ -1031,6 +1066,7 @@
<cd:constant name='white' value='سÙید'/>
<cd:constant name='width' value='عرض'/>
<cd:constant name='xfactor' value='Ùاکتورایکس'/>
+ <cd:constant name='xhtml' value='xhtml'/>
<cd:constant name='xmax' value='xmax'/>
<cd:constant name='xoffset' value='Ø¢Ùست‌ایکس'/>
<cd:constant name='xscale' value='مقیاس‌ایکس'/>
@@ -1051,8 +1087,6 @@
<cd:element name='complete' value='کامل'/>
<cd:element name='coupled' value='مزدوج'/>
<cd:element name='currentlocal' value='موضعی‌جاری'/>
- <cd:element name='emptyone' value='یک‌خالی'/>
- <cd:element name='emptytwo' value='دوخالی'/>
<cd:element name='end' value='انتها'/>
<cd:element name='endsetup' value='انتهای‌بارگذاری'/>
<cd:element name='get' value='بگیر'/>
@@ -1168,7 +1202,7 @@
<cd:command name='defineframedtext' value='تعریÙ‌متن‌قالبی'/>
<cd:command name='definehbox' value='تعریÙ‌جعبه‌‌اÙÙ‚ÛŒ'/>
<cd:command name='definehead' value='تعریÙ‌سر'/>
- <cd:command name='defineindenting' value='تعریÙ‌تورÙتگی'/>
+ <cd:command name='defineindentedtext' value='defineindentedtext'/>
<cd:command name='defineinmargin' value='تعریÙ‌درون‌حاشیه'/>
<cd:command name='defineinteractionmenu' value='تعریÙ‌منوی‌پانل'/>
<cd:command name='defineitemgroup' value='تعریÙ‌گروه‌آیتم'/>
@@ -1364,7 +1398,6 @@
<cd:command name='pagenumber' value='شماره‌صÙحه'/>
<cd:command name='pageoffset' value='Ø¢Ùست‌صÙحه'/>
<cd:command name='pagereference' value='مرجع‌صÙحه'/>
- <cd:command name='pagetype' value='نوع‌صÙحه'/>
<cd:command name='paperheight' value='ارتÙاع‌برگ'/>
<cd:command name='paperwidth' value='عرض‌برگ'/>
<cd:command name='periods' value='نقطه‌ها'/>
@@ -1480,7 +1513,7 @@
<cd:command name='setupheads' value='بارگذاری‌سرها'/>
<cd:command name='setupheadtext' value='بارگذاری‌متن‌سر'/>
<cd:command name='setuphyphenmark' value='بارگذاری‌نشانه‌شکستن'/>
- <cd:command name='setupindentations' value='بارگذاری‌تورÙتگیها'/>
+ <cd:command name='setupindentedtext' value='setupindentedtext'/>
<cd:command name='setupindenting' value='بارگذاری‌تورÙتگی'/>
<cd:command name='setupinmargin' value='بارگذاری‌درون‌حاشیه'/>
<cd:command name='setupinteraction' value='بارگذاری‌پانل'/>
diff --git a/Master/texmf-dist/tex/context/interface/keys-ro.xml b/Master/texmf-dist/tex/context/interface/keys-ro.xml
index c0ebc9c96d0..4d159ac0ab1 100644
--- a/Master/texmf-dist/tex/context/interface/keys-ro.xml
+++ b/Master/texmf-dist/tex/context/interface/keys-ro.xml
@@ -7,6 +7,8 @@
<cd:variables>
<cd:variable name='Addition' value='Adaugare'/>
<cd:variable name='Balloon' value='Balon'/>
+ <cd:variable name='Cap' value='Cap'/>
+ <cd:variable name='Capital' value='Majuscula'/>
<cd:variable name='Character' value='Caracter'/>
<cd:variable name='Characters' value='Caractere'/>
<cd:variable name='CloseDocument' value='InchideDocument'/>
@@ -64,6 +66,9 @@
<cd:variable name='ViewerHelp' value='AjutorVizualizator'/>
<cd:variable name='WEEKDAY' value='ZISAPTAMANA'/>
<cd:variable name='WORD' value='CUVANT'/>
+ <cd:variable name='WORDS' value='CUVINTE'/>
+ <cd:variable name='Word' value='Cuvant'/>
+ <cd:variable name='Words' value='Cuvinte'/>
<cd:variable name='abbreviation' value='abreviere'/>
<cd:variable name='abbreviations' value='abrevieri'/>
<cd:variable name='absolute' value='absolut'/>
@@ -278,6 +283,7 @@
<cd:variable name='marking' value='marcaje'/>
<cd:variable name='mathalignment' value='mathalignment'/>
<cd:variable name='mathcases' value='mathcases'/>
+ <cd:variable name='mathematics' value='matematica'/>
<cd:variable name='mathmatrix' value='mathmatrix'/>
<cd:variable name='max' value='max'/>
<cd:variable name='maxdepth' value='maxdepth'/>
@@ -359,6 +365,7 @@
<cd:variable name='previousoddpage' value='paginaimparaprecedenta'/>
<cd:variable name='previouspage' value='paginaanterioara'/>
<cd:variable name='previoussubpage' value='subpaginaanterioara'/>
+ <cd:variable name='print' value='print'/>
<cd:variable name='printable' value='tiparibil'/>
<cd:variable name='process' value='process'/>
<cd:variable name='product' value='produs'/>
@@ -366,6 +373,7 @@
<cd:variable name='project' value='proiect'/>
<cd:variable name='protected' value='protejat'/>
<cd:variable name='quadruple' value='cvadrupul'/>
+ <cd:variable name='quarterline' value='quarterline'/>
<cd:variable name='quotation' value='citat'/>
<cd:variable name='quote' value='minicitat'/>
<cd:variable name='ran' value='rulat'/>
@@ -500,6 +508,8 @@
<cd:variable name='unavailable' value='nedisponibil'/>
<cd:variable name='underbar' value='sublinie'/>
<cd:variable name='underbars' value='sublinii'/>
+ <cd:variable name='understrike' value='understrike'/>
+ <cd:variable name='understrikes' value='understrikes'/>
<cd:variable name='unit' value='unitate'/>
<cd:variable name='units' value='unitati'/>
<cd:variable name='unknown' value='necunoscut'/>
@@ -519,6 +529,7 @@
<cd:variable name='white' value='alb'/>
<cd:variable name='wide' value='larg'/>
<cd:variable name='width' value='latime'/>
+ <cd:variable name='word' value='cuvant'/>
<cd:variable name='xml' value='xml'/>
<cd:variable name='year' value='an'/>
<cd:variable name='yes' value='da'/>
@@ -539,6 +550,7 @@
<cd:constant name='alignsymbol' value='alignsymbol'/>
<cd:constant name='aligntitle' value='alinieretitlu'/>
<cd:constant name='alternative' value='alternativ'/>
+ <cd:constant name='anchor' value='anchor'/>
<cd:constant name='andtext' value='andtext'/>
<cd:constant name='apa' value='apa'/>
<cd:constant name='arrow' value='sageata'/>
@@ -558,6 +570,8 @@
<cd:constant name='autohang' value='autohang'/>
<cd:constant name='autostrut' value='autostrut'/>
<cd:constant name='autowidth' value='autolatime'/>
+ <cd:constant name='availableheight' value='availableheight'/>
+ <cd:constant name='availablewidth' value='availablewidth'/>
<cd:constant name='axis' value='axa'/>
<cd:constant name='background' value='fundal'/>
<cd:constant name='backgroundcolor' value='culoarefundal'/>
@@ -577,6 +591,7 @@
<cd:constant name='blank' value='blanc'/>
<cd:constant name='blockway' value='blockway'/>
<cd:constant name='bodyfont' value='fonttext'/>
+ <cd:constant name='boffset' value='boffset'/>
<cd:constant name='bookmark' value='semncarte'/>
<cd:constant name='bottom' value='jos'/>
<cd:constant name='bottomafter' value='bottomafter'/>
@@ -608,6 +623,8 @@
<cd:constant name='commandafter' value='comandadupa'/>
<cd:constant name='commandbefore' value='comandainainte'/>
<cd:constant name='commands' value='comenzi'/>
+ <cd:constant name='commentoffset' value='commentoffset'/>
+ <cd:constant name='compact' value='compact'/>
<cd:constant name='component' value='component'/>
<cd:constant name='compoundhyphen' value='compoundhyphen'/>
<cd:constant name='compress' value='compress'/>
@@ -621,6 +638,7 @@
<cd:constant name='coupling' value='cuplare'/>
<cd:constant name='couplingway' value='modcuplare'/>
<cd:constant name='criterium' value='criteriu'/>
+ <cd:constant name='css' value='css'/>
<cd:constant name='current' value='curent'/>
<cd:constant name='cutspace' value='cutspace'/>
<cd:constant name='dash' value='dash'/>
@@ -649,11 +667,13 @@
<cd:constant name='editoretallimit' value='editoretallimit'/>
<cd:constant name='editoretaltext' value='editoretaltext'/>
<cd:constant name='empty' value='gol'/>
+ <cd:constant name='entities' value='entities'/>
<cd:constant name='entries' value='entries'/>
<cd:constant name='equalheight' value='equalheight'/>
<cd:constant name='equalwidth' value='equalwidth'/>
<cd:constant name='escape' value='escape'/>
<cd:constant name='evenmargin' value='marginepara'/>
+ <cd:constant name='exitoffset' value='labeloffset'/>
<cd:constant name='expansion' value='expansiune'/>
<cd:constant name='export' value='export'/>
<cd:constant name='extras' value='extras'/>
@@ -690,6 +710,7 @@
<cd:constant name='global' value='global'/>
<cd:constant name='grid' value='grid'/>
<cd:constant name='hang' value='suspenda'/>
+ <cd:constant name='hcompact' value='hcompact'/>
<cd:constant name='headalign' value='headalign'/>
<cd:constant name='headcolor' value='culoaretitlu'/>
<cd:constant name='headcommand' value='headcommand'/>
@@ -718,6 +739,7 @@
<cd:constant name='inner' value='intern'/>
<cd:constant name='innermargin' value='innermargin'/>
<cd:constant name='inputfile' value='inputfile'/>
+ <cd:constant name='insidesection' value='insidesection'/>
<cd:constant name='intent' value='intent'/>
<cd:constant name='interaction' value='interactiune'/>
<cd:constant name='interlinespace' value='spatiereinterliniara'/>
@@ -730,8 +752,10 @@
<cd:constant name='keys' value='keys'/>
<cd:constant name='keyword' value='keyword'/>
<cd:constant name='label' value='eticheta'/>
+ <cd:constant name='labeloffset' value='labeloffset'/>
<cd:constant name='lastnamesep' value='lastnamesep'/>
<cd:constant name='lastpubsep' value='lastpubsep'/>
+ <cd:constant name='layout' value='layout'/>
<cd:constant name='left' value='stanga'/>
<cd:constant name='leftcolor' value='culoarestanga'/>
<cd:constant name='leftcompoundhyphen' value='leftcompoundhyphen'/>
@@ -760,6 +784,7 @@
<cd:constant name='listtext' value='listtext'/>
<cd:constant name='local' value='local'/>
<cd:constant name='location' value='locatie'/>
+ <cd:constant name='loffset' value='loffset'/>
<cd:constant name='logo' value='logo'/>
<cd:constant name='logos' value='logos'/>
<cd:constant name='marcolor' value='culoaremarcaj'/>
@@ -836,6 +861,7 @@
<cd:constant name='page' value='pagina'/>
<cd:constant name='pageboundaries' value='marginipagina'/>
<cd:constant name='pagecolor' value='culoarepagina'/>
+ <cd:constant name='pagecolormodel' value='pagecolormodel'/>
<cd:constant name='pagecommand' value='comandapagina'/>
<cd:constant name='pageconversion' value='pageconversion'/>
<cd:constant name='pageconversionset' value='pageconversionset'/>
@@ -876,6 +902,7 @@
<cd:constant name='preview' value='previzualizare'/>
<cd:constant name='previous' value='precendent'/>
<cd:constant name='previousnumber' value='numarprecedent'/>
+ <cd:constant name='printable' value='tiparibil'/>
<cd:constant name='process' value='process'/>
<cd:constant name='profile' value='profile'/>
<cd:constant name='pubsep' value='pubsep'/>
@@ -888,6 +915,7 @@
<cd:constant name='reference' value='referinta'/>
<cd:constant name='referenceprefix' value='referenceprefix'/>
<cd:constant name='referencing' value='referinta'/>
+ <cd:constant name='region' value='region'/>
<cd:constant name='regionin' value='regiuneintrare'/>
<cd:constant name='regionout' value='regiuneiesire'/>
<cd:constant name='repeat' value='repeta'/>
@@ -912,9 +940,11 @@
<cd:constant name='rightsubsentence' value='subpropozitiedreapta'/>
<cd:constant name='righttext' value='textdreapta'/>
<cd:constant name='rightwidth' value='marginedreapta'/>
+ <cd:constant name='roffset' value='roffset'/>
<cd:constant name='rotation' value='rotatie'/>
<cd:constant name='rule' value='rigla'/>
<cd:constant name='rulecolor' value='culoarerigla'/>
+ <cd:constant name='rulecommand' value='rulecommand'/>
<cd:constant name='rulethickness' value='grosimerigla'/>
<cd:constant name='samepage' value='aceeasipagina'/>
<cd:constant name='sample' value='exemplu'/>
@@ -972,6 +1002,7 @@
<cd:constant name='subtitle' value='subtitlu'/>
<cd:constant name='suffix' value='suffix'/>
<cd:constant name='suffixseparator' value='suffixseparator'/>
+ <cd:constant name='suffixstopper' value='suffixstopper'/>
<cd:constant name='surnamesep' value='surnamesep'/>
<cd:constant name='sx' value='sx'/>
<cd:constant name='sy' value='sy'/>
@@ -989,6 +1020,7 @@
<cd:constant name='textcolor' value='culoaretext'/>
<cd:constant name='textcommand' value='comandatext'/>
<cd:constant name='textdistance' value='textdistance'/>
+ <cd:constant name='textheight' value='inaltimetext'/>
<cd:constant name='textlayer' value='textlayer'/>
<cd:constant name='textmargin' value='textmargin'/>
<cd:constant name='textmethod' value='textmethod'/>
@@ -1006,6 +1038,7 @@
<cd:constant name='titleright' value='titleright'/>
<cd:constant name='titlestyle' value='stiltitlu'/>
<cd:constant name='to' value='catre'/>
+ <cd:constant name='toffset' value='toffset'/>
<cd:constant name='tolerance' value='toleranta'/>
<cd:constant name='top' value='sus'/>
<cd:constant name='topdistance' value='distantasus'/>
@@ -1022,6 +1055,8 @@
<cd:constant name='validate' value='verifica'/>
<cd:constant name='values' value='values'/>
<cd:constant name='vcommand' value='comandav'/>
+ <cd:constant name='vcompact' value='vcompact'/>
+ <cd:constant name='vector' value='vector'/>
<cd:constant name='veroffset' value='veroffset'/>
<cd:constant name='vfil' value='vfil'/>
<cd:constant name='voffset' value='voffset'/>
@@ -1031,6 +1066,7 @@
<cd:constant name='white' value='alb'/>
<cd:constant name='width' value='latime'/>
<cd:constant name='xfactor' value='xfactor'/>
+ <cd:constant name='xhtml' value='xhtml'/>
<cd:constant name='xmax' value='xmax'/>
<cd:constant name='xoffset' value='xoffset'/>
<cd:constant name='xscale' value='xscala'/>
@@ -1051,8 +1087,6 @@
<cd:element name='complete' value='complet'/>
<cd:element name='coupled' value='cuplat'/>
<cd:element name='currentlocal' value='localcurent'/>
- <cd:element name='emptyone' value='gol'/>
- <cd:element name='emptytwo' value='gol'/>
<cd:element name='end' value='sfarsit'/>
<cd:element name='endsetup' value=''/>
<cd:element name='get' value='get'/>
@@ -1168,7 +1202,7 @@
<cd:command name='defineframedtext' value='definestetextinconjurat'/>
<cd:command name='definehbox' value='definestehbox'/>
<cd:command name='definehead' value='definesteantet'/>
- <cd:command name='defineindenting' value='definestealiat'/>
+ <cd:command name='defineindentedtext' value='defineindentedtext'/>
<cd:command name='defineinmargin' value='defineinmargin'/>
<cd:command name='defineinteractionmenu' value='definestemeniuinteractiune'/>
<cd:command name='defineitemgroup' value='defineitemgroup'/>
@@ -1364,7 +1398,6 @@
<cd:command name='pagenumber' value='numarpagina'/>
<cd:command name='pageoffset' value='pageoffset'/>
<cd:command name='pagereference' value='referintapagina'/>
- <cd:command name='pagetype' value='tippagina'/>
<cd:command name='paperheight' value='inaltimehartie'/>
<cd:command name='paperwidth' value='latimehartie'/>
<cd:command name='periods' value='puncte'/>
@@ -1480,7 +1513,7 @@
<cd:command name='setupheads' value='seteazatitluri'/>
<cd:command name='setupheadtext' value='seteazatexttitlu'/>
<cd:command name='setuphyphenmark' value='seteazaliniesilabe'/>
- <cd:command name='setupindentations' value='seteazaaliniate'/>
+ <cd:command name='setupindentedtext' value='setupindentedtext'/>
<cd:command name='setupindenting' value='seteazaaliniat'/>
<cd:command name='setupinmargin' value='seteazamarginal'/>
<cd:command name='setupinteraction' value='seteazainteractiunea'/>
diff --git a/Master/texmf-dist/tex/context/sample/mill.png b/Master/texmf-dist/tex/context/sample/mill.png
index faff477dec9..9a1bf14e817 100644
--- a/Master/texmf-dist/tex/context/sample/mill.png
+++ b/Master/texmf-dist/tex/context/sample/mill.png
Binary files differ
diff --git a/Master/texmf-dist/tex/context/test/pdf-a1a-2005.mkiv b/Master/texmf-dist/tex/context/test/pdf-a1a-2005.mkiv
index 4600e7a096b..8f79d3f337a 100644
--- a/Master/texmf-dist/tex/context/test/pdf-a1a-2005.mkiv
+++ b/Master/texmf-dist/tex/context/test/pdf-a1a-2005.mkiv
@@ -6,19 +6,16 @@
[format=PDF/A-1a:2005,
intent=sRGB IEC61966-2.1, % use <info> entry here; otherwise problems with predefined default profile
profile=sRGB.icc, % use <filename> here
- level=0,
- ]
+ level=0]
-\setupstructure[state=start]
+\setuptagging[state=start]
\setupcolors[cmyk=no]
\definecolor[rgbblack][b=0.01]
\definecolor[transtest][r=1,g=1,t=.5]
-
\placebookmarks[chapter][all][force=yes]
-
\starttext
\starttextcolor[rgbblack]
diff --git a/Master/texmf-dist/tex/context/test/pdf-a1b-2005.mkiv b/Master/texmf-dist/tex/context/test/pdf-a1b-2005.mkiv
index 8a032395cae..f980e314849 100644
--- a/Master/texmf-dist/tex/context/test/pdf-a1b-2005.mkiv
+++ b/Master/texmf-dist/tex/context/test/pdf-a1b-2005.mkiv
@@ -6,17 +6,14 @@
[format=PDF/A-1a:2005,
intent=sRGB IEC61966-2.1, % use <info> entry here; otherwise problems with predefined default profile
profile=sRGB.icc, % use <filename> here
- level=0,
- ]
+ level=0]
-\setupstructure[state=start] % needed even for 'b'-version
+\setuptagging[state=start] % needed even for 'b'-version
\setupcolors[cmyk=no]
\definecolor[rgbblack][b=0.01]
\definecolor[transtest][r=1,g=1,t=.5]
-
-
\starttext
\starttextcolor[rgbblack] % forced /DeviceGray causes problems; we need a trigger
@@ -38,5 +35,4 @@ Text is needed, otherwise tagging base entries are not applied.
\egroup
%\stopTEXpage
-
\stoptext
diff --git a/Master/texmf-dist/tex/generic/context/luatex-basics-gen.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-basics-gen.lua
index 602601d5cc7..bdbc3cf5188 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-basics-gen.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-basics-gen.lua
@@ -80,6 +80,8 @@ local remapper = {
dfont = "truetype fonts", -- "truetype dictionary",
cid = "cid maps",
fea = "font feature files",
+ pfa = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
+ pfb = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
}
function resolvers.findfile(name,fileformat)
@@ -191,7 +193,7 @@ end
local function makefullname(path,name)
if path and path ~= "" then
name = "temp-" .. name -- clash prevention
- return file.addsuffix(file.join(path,name),"lua")
+ return file.addsuffix(file.join(path,name),"lua"), file.addsuffix(file.join(path,name),"luc")
end
end
@@ -202,25 +204,66 @@ end
function caches.loaddata(paths,name)
for i=1,#paths do
- local fullname = makefullname(paths[i],name)
- if fullname then
- texio.write(string.format("(load: %s)",fullname))
- local data = loadfile(fullname)
- return data and data()
+ local data = false
+ local luaname, lucname = makefullname(paths[i],name)
+ if lucname and lfs.isfile(lucname) then
+ texio.write(string.format("(load: %s)",lucname))
+ data = loadfile(lucname)
end
+ if not data and luaname and lfs.isfile(luaname) then
+ texio.write(string.format("(load: %s)",luaname))
+ data = loadfile(luaname)
+ end
+ return data and data()
end
end
function caches.savedata(path,name,data)
- local fullname = makefullname(path,name)
- if fullname then
- texio.write(string.format("(save: %s)",fullname))
- table.tofile(fullname,data,true,{ reduce = true })
+ local luaname, lucname = makefullname(path,name)
+ if luaname then
+ texio.write(string.format("(save: %s)",luaname))
+ table.tofile(luaname,data,true,{ reduce = true })
+ if lucname and type(caches.compile) == "function" then
+ os.remove(lucname) -- better be safe
+ texio.write(string.format("(save: %s)",lucname))
+ caches.compile(data,luaname,lucname)
+ end
+ end
+end
+
+-- According to KH os.execute is not permitted in plain/latex so there is
+-- no reason to use the normal context way. So the method here is slightly
+-- different from the one we have in context. We also use different suffixes
+-- as we don't want any clashes (sharing cache files is not that handy as
+-- context moves on faster.)
+--
+-- Beware: serialization might fail on large files (so maybe we should pcall
+-- this) in which case one should limit the method to luac and enable support
+-- for execution.
+
+caches.compilemethod = "luac" -- luac dump both
+
+function caches.compile(data,luaname,lucname)
+ local done = false
+ if caches.compilemethod == "luac" or caches.compilemethod == "both" then
+ local command = "-o " .. string.quoted(lucname) .. " -s " .. string.quoted(luaname)
+ done = os.spawn("texluac " .. command) == 0
+ end
+ if not done and (caches.compilemethod == "dump" or caches.compilemethod == "both") then
+ local d = table.serialize(data,true)
+ if d and d ~= "" then
+ local f = io.open(lucname,'w')
+ if f then
+ local s = loadstring(d)
+ f:write(string.dump(s))
+ f:close()
+ end
+ end
end
end
--
-local table.setmetatableindex(t,f)
+function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
diff --git a/Master/texmf-dist/tex/generic/context/luatex-basics-nod.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-basics-nod.lua
index 151d98a8f31..151d98a8f31 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-basics-nod.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-basics-nod.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-basics.tex b/Master/texmf-dist/tex/generic/context/luatex/luatex-basics.tex
index 8308204d572..bb34587ff6c 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-basics.tex
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-basics.tex
@@ -5,7 +5,7 @@
%D subtitle=Attribute Allocation,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=public domain]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%D As soon as we feel the need this file will file will contain an extension
%D to the standard plain register allocation. For the moment we stick to a
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-cbk.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-cbk.lua
index 9db94f65e48..9db94f65e48 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-cbk.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-cbk.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-def.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-def.lua
index 0c2f0dbd583..0c2f0dbd583 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-def.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-def.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-demo-vf-1.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua
index 3878ae64805..3878ae64805 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-demo-vf-1.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-demo-vf-1.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-enc.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-enc.lua
index ac736f2a6e8..e20c3a03b54 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-enc.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-enc.lua
@@ -18,7 +18,7 @@ fonts.encodings.agl = { }
setmetatable(fonts.encodings.agl, { __index = function(t,k)
if k == "unicodes" then
texio.write(" <loading (extended) adobe glyph list>")
- local unicodes = dofile(resolvers.findfile("font-agl.lua"))
+ local unicodes = dofile(resolvers.findfile("font-age.lua"))
fonts.encodings.agl = { unicodes = unicodes }
return unicodes
else
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-ext.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-ext.lua
index 951afcc7e0b..d8884ccc74c 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-ext.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-ext.lua
@@ -29,7 +29,7 @@ local function initializeitlc(tfmdata,value)
d.italic = it
end
end
- tfmdata.properties.italic_correction = true
+ tfmdata.properties.hasitalics = true
end
end
end
@@ -54,7 +54,7 @@ local function initializeslant(tfmdata,value)
elseif value < -1 then
value = -1
end
- tfmdata.parameters.slant_factor = value
+ tfmdata.parameters.slantfactor = value
end
otffeatures.register {
@@ -75,7 +75,7 @@ local function initializeextend(tfmdata,value)
elseif value < -10 then
value = -10
end
- tfmdata.parameters.extend_factor = value
+ tfmdata.parameters.extendfactor = value
end
otffeatures.register {
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-lua.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-lua.lua
index ec3fe38be3e..ec3fe38be3e 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-lua.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-lua.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-merged.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua
index 7e954182ad7..cdef91b38fd 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-merged.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 05/18/11 18:04:18
+-- merge date : 05/14/12 16:00:55
do -- begin closure to overcome local limits and interference
@@ -127,650 +127,6 @@ end -- closure
do -- begin closure to overcome local limits and interference
-if not modules then modules = { } end modules ['l-lpeg'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local lpeg = require("lpeg")
-
-local type = type
-
--- Beware, we predefine a bunch of patterns here and one reason for doing so
--- is that we get consistent behaviour in some of the visualizers.
-
-lpeg.patterns = lpeg.patterns or { } -- so that we can share
-local patterns = lpeg.patterns
-
-local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
-local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
-local lpegtype = lpeg.type
-
-local utfcharacters = string.utfcharacters
-local utfgmatch = unicode and unicode.utf8.gmatch
-
-local anything = P(1)
-local endofstring = P(-1)
-local alwaysmatched = P(true)
-
-patterns.anything = anything
-patterns.endofstring = endofstring
-patterns.beginofstring = alwaysmatched
-patterns.alwaysmatched = alwaysmatched
-
-local digit, sign = R('09'), S('+-')
-local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
-local newline = crlf + cr + lf
-local escaped = P("\\") * anything
-local squote = P("'")
-local dquote = P('"')
-local space = P(" ")
-
-local utfbom_32_be = P('\000\000\254\255')
-local utfbom_32_le = P('\255\254\000\000')
-local utfbom_16_be = P('\255\254')
-local utfbom_16_le = P('\254\255')
-local utfbom_8 = P('\239\187\191')
-local utfbom = utfbom_32_be + utfbom_32_le
- + utfbom_16_be + utfbom_16_le
- + utfbom_8
-local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
- + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
- + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
-
-local utf8next = R("\128\191")
-
-patterns.utf8one = R("\000\127")
-patterns.utf8two = R("\194\223") * utf8next
-patterns.utf8three = R("\224\239") * utf8next * utf8next
-patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
-patterns.utfbom = utfbom
-patterns.utftype = utftype
-
-local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
-local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
-
-patterns.utf8 = utf8char
-patterns.utf8char = utf8char
-patterns.validutf8 = validutf8char
-patterns.validutf8char = validutf8char
-
-patterns.digit = digit
-patterns.sign = sign
-patterns.cardinal = sign^0 * digit^1
-patterns.integer = sign^0 * digit^1
-patterns.float = sign^0 * digit^0 * P('.') * digit^1
-patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
-patterns.number = patterns.float + patterns.integer
-patterns.cnumber = patterns.cfloat + patterns.integer
-patterns.oct = P("0") * R("07")^1
-patterns.octal = patterns.oct
-patterns.HEX = P("0x") * R("09","AF")^1
-patterns.hex = P("0x") * R("09","af")^1
-patterns.hexadecimal = P("0x") * R("09","AF","af")^1
-patterns.lowercase = R("az")
-patterns.uppercase = R("AZ")
-patterns.letter = patterns.lowercase + patterns.uppercase
-patterns.space = space
-patterns.tab = P("\t")
-patterns.spaceortab = patterns.space + patterns.tab
-patterns.eol = S("\n\r")
-patterns.spacer = S(" \t\f\v") -- + string.char(0xc2, 0xa0) if we want utf (cf mail roberto)
-patterns.newline = newline
-patterns.emptyline = newline^1
-patterns.nonspacer = 1 - patterns.spacer
-patterns.whitespace = patterns.eol + patterns.spacer
-patterns.nonwhitespace = 1 - patterns.whitespace
-patterns.equal = P("=")
-patterns.comma = P(",")
-patterns.commaspacer = P(",") * patterns.spacer^0
-patterns.period = P(".")
-patterns.colon = P(":")
-patterns.semicolon = P(";")
-patterns.underscore = P("_")
-patterns.escaped = escaped
-patterns.squote = squote
-patterns.dquote = dquote
-patterns.nosquote = (escaped + (1-squote))^0
-patterns.nodquote = (escaped + (1-dquote))^0
-patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
-patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
-patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
-patterns.unspacer = ((patterns.spacer^1)/"")^0
-
-patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
-patterns.beginline = #(1-newline)
-
-local unquoted = Cs(patterns.unquoted * endofstring) -- not C
-
-function string.unquoted(str)
- return match(unquoted,str) or str
-end
-
---~ print(string.unquoted("test"))
---~ print(string.unquoted([["t\"est"]]))
---~ print(string.unquoted([["t\"est"x]]))
---~ print(string.unquoted("\'test\'"))
-
-function lpeg.anywhere(pattern) --slightly adapted from website
- return P { P(pattern) + 1 * V(1) } -- why so complex?
-end
-
-function lpeg.splitter(pattern, action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-
-local splitters_s, splitters_m = { }, { }
-
-local function splitat(separator,single)
- local splitter = (single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator = P(separator)
- local other = C((1 - separator)^0)
- if single then
- local any = anything
- splitter = other * (separator * C(any^0) + "") -- ?
- splitters_s[separator] = splitter
- else
- splitter = other * (separator * other)^0
- splitters_m[separator] = splitter
- end
- end
- return splitter
-end
-
-lpeg.splitat = splitat
-
---~ local p = splitat("->",false) print(match(p,"oeps->what->more")) -- oeps what more
---~ local p = splitat("->",true) print(match(p,"oeps->what->more")) -- oeps what->more
---~ local p = splitat("->",false) print(match(p,"oeps")) -- oeps
---~ local p = splitat("->",true) print(match(p,"oeps")) -- oeps
-
-local cache = { }
-
-function lpeg.split(separator,str)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.split(str,separator)
- local c = cache[separator]
- if not c then
- c = Ct(splitat(separator))
- cache[separator] = c
- end
- return match(c,str)
-end
-
-local spacing = patterns.spacer^0 * newline -- sort of strip
-local empty = spacing * Cc("")
-local nonempty = Cs((1-spacing)^1) * spacing^-1
-local content = (empty + nonempty)^1
-
-patterns.textline = content
-
---~ local linesplitter = Ct(content^0)
---~
---~ function string.splitlines(str)
---~ return match(linesplitter,str)
---~ end
-
-local linesplitter = Ct(splitat(newline))
-
-patterns.linesplitter = linesplitter
-
-function string.splitlines(str)
- return match(linesplitter,str)
-end
-
-local utflinesplitter = utfbom^-1 * Ct(splitat(newline))
-
-patterns.utflinesplitter = utflinesplitter
-
-function string.utfsplitlines(str)
- return match(utflinesplitter,str)
-end
-
---~ lpeg.splitters = cache -- no longer public
-
-local cache = { }
-
-function lpeg.checkedsplit(separator,str)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
-function string.checkedsplit(str,separator)
- local c = cache[separator]
- if not c then
- separator = P(separator)
- local other = C((1 - separator)^1)
- c = Ct(separator^0 * other * (separator^1 * other)^0)
- cache[separator] = c
- end
- return match(c,str)
-end
-
---~ from roberto's site:
-
-local f1 = string.byte
-
-local function f2(s) local c1, c2 = f1(s,1,2) return c1 * 64 + c2 - 12416 end
-local function f3(s) local c1, c2, c3 = f1(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
-local function f4(s) local c1, c2, c3, c4 = f1(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
-
-local utf8byte = patterns.utf8one/f1 + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
-
-patterns.utf8byte = utf8byte
-
---~ local str = " a b c d "
-
---~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpeg.match(s,str).."]")
---~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpeg.match(s,str).."]")
---~ local s = lpeg.stripper("ab") print("["..lpeg.match(s,str).."]")
---~ local s = lpeg.keeper("ab") print("["..lpeg.match(s,str).."]")
-
-local cache = { }
-
-function lpeg.stripper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs(((S(str)^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs(((str^1)/"" + 1)^0)
- end
-end
-
-local cache = { }
-
-function lpeg.keeper(str)
- if type(str) == "string" then
- local s = cache[str]
- if not s then
- s = Cs((((1-S(str))^1)/"" + 1)^0)
- cache[str] = s
- end
- return s
- else
- return Cs((((1-str)^1)/"" + 1)^0)
- end
-end
-
-function lpeg.frontstripper(str) -- or pattern (yet undocumented)
- return (P(str) + P(true)) * Cs(P(1)^0)
-end
-
-function lpeg.endstripper(str) -- or pattern (yet undocumented)
- return Cs((1 - P(str) * P(-1))^0)
-end
-
--- Just for fun I looked at the used bytecode and
--- p = (p and p + pp) or pp gets one more (testset).
-
-function lpeg.replacer(one,two)
- if type(one) == "table" then
- local no = #one
- if no > 0 then
- local p
- for i=1,no do
- local o = one[i]
- local pp = P(o[1]) / o[2]
- if p then
- p = p + pp
- else
- p = pp
- end
- end
- return Cs((p + 1)^0)
- end
- else
- two = two or ""
- return Cs((P(one)/two + 1)^0)
- end
-end
-
-local splitters_f, splitters_s = { }, { }
-
-function lpeg.firstofsplit(separator) -- always return value
- local splitter = splitters_f[separator]
- if not splitter then
- separator = P(separator)
- splitter = C((1 - separator)^0)
- splitters_f[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.secondofsplit(separator) -- nil if not split
- local splitter = splitters_s[separator]
- if not splitter then
- separator = P(separator)
- splitter = (1 - separator)^0 * separator * C(anything^0)
- splitters_s[separator] = splitter
- end
- return splitter
-end
-
-function lpeg.balancer(left,right)
- left, right = P(left), P(right)
- return P { left * ((1 - left - right) + V(1))^0 * right }
-end
-
---~ print(1,match(lpeg.firstofsplit(":"),"bc:de"))
---~ print(2,match(lpeg.firstofsplit(":"),":de")) -- empty
---~ print(3,match(lpeg.firstofsplit(":"),"bc"))
---~ print(4,match(lpeg.secondofsplit(":"),"bc:de"))
---~ print(5,match(lpeg.secondofsplit(":"),"bc:")) -- empty
---~ print(6,match(lpeg.secondofsplit(":",""),"bc"))
---~ print(7,match(lpeg.secondofsplit(":"),"bc"))
---~ print(9,match(lpeg.secondofsplit(":","123"),"bc"))
-
---~ -- slower:
---~
---~ function lpeg.counter(pattern)
---~ local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
---~ return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
---~ end
-
-local nany = utf8char/""
-
-function lpeg.counter(pattern)
- pattern = Cs((P(pattern)/" " + nany)^0)
- return function(str)
- return #match(pattern,str)
- end
-end
-
-if utfgmatch then
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local n = 0
- for _ in utfgmatch(str,what) do
- n = n + 1
- end
- return n
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-else
-
- local cache = { }
-
- function lpeg.count(str,what) -- replaces string.count
- if type(what) == "string" then
- local p = cache[what]
- if not p then
- p = Cs((P(what)/" " + nany)^0)
- cache[p] = p
- end
- return #match(p,str)
- else -- 4 times slower but still faster than / function
- return #match(Cs((P(what)/" " + nany)^0),str)
- end
- end
-
-end
-
-local patterns_escapes = { -- also defines in l-string
- ["%"] = "%%",
- ["."] = "%.",
- ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
- ["["] = "%[", ["]"] = "%]",
- ["("] = "%)", [")"] = "%)",
- -- ["{"] = "%{", ["}"] = "%}"
- -- ["^"] = "%^", ["$"] = "%$",
-}
-
-local simple_escapes = { -- also defines in l-string
- ["-"] = "%-",
- ["."] = "%.",
- ["?"] = ".",
- ["*"] = ".*",
-}
-
-local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
-local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
-
-function string.escapedpattern(str,simple)
- return match(simple and s or p,str)
-end
-
--- utf extensies
-
-lpeg.UP = lpeg.P
-
-if utfcharacters then
-
- function lpeg.US(str)
- local p
- for uc in utfcharacters(str) do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-
-elseif utfgmatch then
-
- function lpeg.US(str)
- local p
- for uc in utfgmatch(str,".") do
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- return p
- end
-
-else
-
- function lpeg.US(str)
- local p
- local f = function(uc)
- if p then
- p = p + P(uc)
- else
- p = P(uc)
- end
- end
- match((utf8char/f)^0,str)
- return p
- end
-
-end
-
-local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
-
-local utfchar = unicode and unicode.utf8 and unicode.utf8.char
-
-function lpeg.UR(str,more)
- local first, last
- if type(str) == "number" then
- first = str
- last = more or first
- else
- first, last = match(range,str)
- if not last then
- return P(str)
- end
- end
- if first == last then
- return P(str)
- elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
- local p
- for i=first,last do
- if p then
- p = p + P(utfchar(i))
- else
- p = P(utfchar(i))
- end
- end
- return p -- nil when invalid range
- else
- local f = function(b)
- return b >= first and b <= last
- end
- return utf8byte / f -- nil when invalid range
- end
-end
-
---~ lpeg.print(lpeg.R("ab","cd","gh"))
---~ lpeg.print(lpeg.P("a","b","c"))
---~ lpeg.print(lpeg.S("a","b","c"))
-
---~ print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
---~ print(lpeg.count("äáàa",lpeg.UP("áà")))
---~ print(lpeg.count("äáàa",lpeg.US("àá")))
---~ print(lpeg.count("äáàa",lpeg.UR("aá")))
---~ print(lpeg.count("äáàa",lpeg.UR("àá")))
---~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
-
-function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
- if type(list) ~= "table" then
- list = { list, ... }
- end
- -- sort(list) -- longest match first
- local p = P(list[1])
- for l=2,#list do
- p = p + P(list[l])
- end
- return p
-end
-
-function lpeg.is_lpeg(p)
- return p and lpegtype(p) == "pattern"
-end
-
---~ Cf(Ct("") * (Cg(C(...) * "=" * Cs(...)))^0, rawset)
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules = { } end modules ['l-boolean'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local type, tonumber = type, tonumber
-
-boolean = boolean or { }
-local boolean = boolean
-
--- function boolean.tonumber(b)
--- return b and 1 or 0 -- test and test and return or return
--- end
-
-function boolean.tonumber(b)
- if b then return 1 else return 0 end -- test and return or return
-end
-
-function toboolean(str,tolerant)
- if tolerant then
- local tstr = type(str)
- if tstr == "string" then
- return str == "true" or str == "yes" or str == "on" or str == "1" or str == "t"
- elseif tstr == "number" then
- return tonumber(str) ~= 0
- elseif tstr == "nil" then
- return false
- else
- return str
- end
- elseif str == "true" then
- return true
- elseif str == "false" then
- return false
- else
- return str
- end
-end
-
-string.toboolean = toboolean
-
-function string.is_boolean(str,default)
- if type(str) == "string" then
- if str == "true" or str == "yes" or str == "on" or str == "t" then
- return true
- elseif str == "false" or str == "no" or str == "off" or str == "f" then
- return false
- end
- end
- return default
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules = { } end modules ['l-math'] = {
- version = 1.001,
- comment = "companion to luat-lib.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
-local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan
-
-if not math.round then
- function math.round(x) return floor(x + 0.5) end
-end
-
-if not math.div then
- function math.div(n,m) return floor(n/m) end
-end
-
-if not math.mod then
- function math.mod(n,m) return n % m end
-end
-
-local pipi = 2*math.pi/360
-
-if not math.sind then
- function math.sind(d) return sin(d*pipi) end
- function math.cosd(d) return cos(d*pipi) end
- function math.tand(d) return tan(d*pipi) end
-end
-
-if not math.odd then
- function math.odd (n) return n % 2 == 0 end
- function math.even(n) return n % 2 ~= 0 end
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
if not modules then modules = { } end modules ['l-table'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
@@ -783,11 +139,12 @@ local type, next, tostring, tonumber, ipairs, table, string = type, next, tostri
local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
local format, find, gsub, lower, dump, match = string.format, string.find, string.gsub, string.lower, string.dump, string.match
local getmetatable, setmetatable = getmetatable, setmetatable
+local getinfo = debug.getinfo
-- Starting with version 5.2 Lua no longer provide ipairs, which makes
-- sense. As we already used the for loop and # in most places the
-- impact on ConTeXt was not that large; the remaining ipairs already
--- have been replaced. In a similar fashio we also hardly used pairs.
+-- have been replaced. In a similar fashion we also hardly used pairs.
--
-- Just in case, we provide the fallbacks as discussed in Programming
-- in Lua (http://www.lua.org/pil/7.3.html):
@@ -1130,6 +487,8 @@ end
-- problem: there no good number_to_string converter with the best resolution
+local function dummy() end
+
local function do_serialize(root,name,depth,level,indexed)
if level > 0 then
depth = depth .. " "
@@ -1324,18 +683,20 @@ local function do_serialize(root,name,depth,level,indexed)
end
elseif t == "function" then
if functions then
+ local f = getinfo(v).what == "C" and dump(dummy) or dump(v)
+ -- local f = getinfo(v).what == "C" and dump(function(...) return v(...) end) or dump(v)
if tk == "number" then -- or find(k,"^%d+$") then
if hexify then
- handle(format("%s [0x%04X]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [0x%04X]=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%s]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,k,f))
end
elseif tk == "boolean" then
- handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),dump(v)))
+ handle(format("%s [%s]=loadstring(%q),",depth,tostring(k),f))
elseif noquotes and not reserved[k] and find(k,"^%a[%w%_]*$") then
- handle(format("%s %s=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s %s=loadstring(%q),",depth,k,f))
else
- handle(format("%s [%q]=loadstring(%q),",depth,k,dump(v)))
+ handle(format("%s [%q]=loadstring(%q),",depth,k,f))
end
end
else
@@ -1698,6 +1059,893 @@ function table.has_one_entry(t)
return t and not next(t,next(t))
end
+-- new
+
+function table.loweredkeys(t) -- maybe utf
+ local l = { }
+ for k, v in next, t do
+ l[lower(k)] = v
+ end
+ return l
+end
+
+-- new, might move (maybe duplicate)
+
+function table.unique(old)
+ local hash = { }
+ local new = { }
+ local n = 0
+ for i=1,#old do
+ local oi = old[i]
+ if not hash[oi] then
+ n = n + 1
+ new[n] = oi
+ hash[oi] = true
+ end
+ end
+ return new
+end
+
+-- function table.sorted(t,...)
+-- table.sort(t,...)
+-- return t -- still sorts in-place
+-- end
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules = { } end modules ['l-lpeg'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+-- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1)
+
+local lpeg = require("lpeg")
+
+-- tracing (only used when we encounter a problem in integration of lpeg in luatex)
+
+local report = texio and texio.write_nl or print
+
+--~ local lpmatch = lpeg.match
+--~ local lpprint = lpeg.print
+--~ local lpp = lpeg.P
+--~ local lpr = lpeg.R
+--~ local lps = lpeg.S
+--~ local lpc = lpeg.C
+--~ local lpb = lpeg.B
+--~ local lpv = lpeg.V
+--~ local lpcf = lpeg.Cf
+--~ local lpcb = lpeg.Cb
+--~ local lpcg = lpeg.Cg
+--~ local lpct = lpeg.Ct
+--~ local lpcs = lpeg.Cs
+--~ local lpcc = lpeg.Cc
+--~ local lpcmt = lpeg.Cmt
+--~ local lpcarg = lpeg.Carg
+
+--~ function lpeg.match(l,...) report("LPEG MATCH") lpprint(l) return lpmatch(l,...) end
+
+--~ function lpeg.P (l) local p = lpp (l) report("LPEG P =") lpprint(l) return p end
+--~ function lpeg.R (l) local p = lpr (l) report("LPEG R =") lpprint(l) return p end
+--~ function lpeg.S (l) local p = lps (l) report("LPEG S =") lpprint(l) return p end
+--~ function lpeg.C (l) local p = lpc (l) report("LPEG C =") lpprint(l) return p end
+--~ function lpeg.B (l) local p = lpb (l) report("LPEG B =") lpprint(l) return p end
+--~ function lpeg.V (l) local p = lpv (l) report("LPEG V =") lpprint(l) return p end
+--~ function lpeg.Cf (l) local p = lpcf (l) report("LPEG Cf =") lpprint(l) return p end
+--~ function lpeg.Cb (l) local p = lpcb (l) report("LPEG Cb =") lpprint(l) return p end
+--~ function lpeg.Cg (l) local p = lpcg (l) report("LPEG Cg =") lpprint(l) return p end
+--~ function lpeg.Ct (l) local p = lpct (l) report("LPEG Ct =") lpprint(l) return p end
+--~ function lpeg.Cs (l) local p = lpcs (l) report("LPEG Cs =") lpprint(l) return p end
+--~ function lpeg.Cc (l) local p = lpcc (l) report("LPEG Cc =") lpprint(l) return p end
+--~ function lpeg.Cmt (l) local p = lpcmt (l) report("LPEG Cmt =") lpprint(l) return p end
+--~ function lpeg.Carg (l) local p = lpcarg(l) report("LPEG Carg =") lpprint(l) return p end
+
+local type = type
+local byte, char, gmatch = string.byte, string.char, string.gmatch
+
+-- Beware, we predefine a bunch of patterns here and one reason for doing so
+-- is that we get consistent behaviour in some of the visualizers.
+
+lpeg.patterns = lpeg.patterns or { } -- so that we can share
+local patterns = lpeg.patterns
+
+local P, R, S, V, match = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.match
+local Ct, C, Cs, Cc = lpeg.Ct, lpeg.C, lpeg.Cs, lpeg.Cc
+local lpegtype = lpeg.type
+
+local utfcharacters = string.utfcharacters
+local utfgmatch = unicode and unicode.utf8.gmatch
+
+local anything = P(1)
+local endofstring = P(-1)
+local alwaysmatched = P(true)
+
+patterns.anything = anything
+patterns.endofstring = endofstring
+patterns.beginofstring = alwaysmatched
+patterns.alwaysmatched = alwaysmatched
+
+local digit, sign = R('09'), S('+-')
+local cr, lf, crlf = P("\r"), P("\n"), P("\r\n")
+local newline = crlf + S("\r\n") -- cr + lf
+local escaped = P("\\") * anything
+local squote = P("'")
+local dquote = P('"')
+local space = P(" ")
+
+local utfbom_32_be = P('\000\000\254\255')
+local utfbom_32_le = P('\255\254\000\000')
+local utfbom_16_be = P('\255\254')
+local utfbom_16_le = P('\254\255')
+local utfbom_8 = P('\239\187\191')
+local utfbom = utfbom_32_be + utfbom_32_le
+ + utfbom_16_be + utfbom_16_le
+ + utfbom_8
+local utftype = utfbom_32_be / "utf-32-be" + utfbom_32_le / "utf-32-le"
+ + utfbom_16_be / "utf-16-be" + utfbom_16_le / "utf-16-le"
+ + utfbom_8 / "utf-8" + alwaysmatched / "unknown"
+
+local utf8next = R("\128\191")
+
+patterns.utf8one = R("\000\127")
+patterns.utf8two = R("\194\223") * utf8next
+patterns.utf8three = R("\224\239") * utf8next * utf8next
+patterns.utf8four = R("\240\244") * utf8next * utf8next * utf8next
+patterns.utfbom = utfbom
+patterns.utftype = utftype
+
+local utf8char = patterns.utf8one + patterns.utf8two + patterns.utf8three + patterns.utf8four
+local validutf8char = utf8char^0 * endofstring * Cc(true) + Cc(false)
+
+patterns.utf8 = utf8char
+patterns.utf8char = utf8char
+patterns.validutf8 = validutf8char
+patterns.validutf8char = validutf8char
+
+patterns.digit = digit
+patterns.sign = sign
+patterns.cardinal = sign^0 * digit^1
+patterns.integer = sign^0 * digit^1
+patterns.float = sign^0 * digit^0 * P('.') * digit^1
+patterns.cfloat = sign^0 * digit^0 * P(',') * digit^1
+patterns.number = patterns.float + patterns.integer
+patterns.cnumber = patterns.cfloat + patterns.integer
+patterns.oct = P("0") * R("07")^1
+patterns.octal = patterns.oct
+patterns.HEX = P("0x") * R("09","AF")^1
+patterns.hex = P("0x") * R("09","af")^1
+patterns.hexadecimal = P("0x") * R("09","AF","af")^1
+patterns.lowercase = R("az")
+patterns.uppercase = R("AZ")
+patterns.letter = patterns.lowercase + patterns.uppercase
+patterns.space = space
+patterns.tab = P("\t")
+patterns.spaceortab = patterns.space + patterns.tab
+patterns.eol = S("\n\r")
+patterns.spacer = S(" \t\f\v") -- + char(0xc2, 0xa0) if we want utf (cf mail roberto)
+patterns.newline = newline
+patterns.emptyline = newline^1
+patterns.nonspacer = 1 - patterns.spacer
+patterns.whitespace = patterns.eol + patterns.spacer
+patterns.nonwhitespace = 1 - patterns.whitespace
+patterns.equal = P("=")
+patterns.comma = P(",")
+patterns.commaspacer = P(",") * patterns.spacer^0
+patterns.period = P(".")
+patterns.colon = P(":")
+patterns.semicolon = P(";")
+patterns.underscore = P("_")
+patterns.escaped = escaped
+patterns.squote = squote
+patterns.dquote = dquote
+patterns.nosquote = (escaped + (1-squote))^0
+patterns.nodquote = (escaped + (1-dquote))^0
+patterns.unsingle = (squote/"") * patterns.nosquote * (squote/"")
+patterns.undouble = (dquote/"") * patterns.nodquote * (dquote/"")
+patterns.unquoted = patterns.undouble + patterns.unsingle -- more often undouble
+patterns.unspacer = ((patterns.spacer^1)/"")^0
+
+patterns.somecontent = (anything - newline - space)^1 -- (utf8char - newline - space)^1
+patterns.beginline = #(1-newline)
+
+-- print(string.unquoted("test"))
+-- print(string.unquoted([["t\"est"]]))
+-- print(string.unquoted([["t\"est"x]]))
+-- print(string.unquoted("\'test\'"))
+-- print(string.unquoted('"test"'))
+-- print(string.unquoted('"test"'))
+
+function lpeg.anywhere(pattern) --slightly adapted from website
+ return P { P(pattern) + 1 * V(1) } -- why so complex?
+end
+
+function lpeg.splitter(pattern, action)
+ return (((1-P(pattern))^1)/action+1)^0
+end
+
+function lpeg.tsplitter(pattern, action)
+ return Ct((((1-P(pattern))^1)/action+1)^0)
+end
+
+-- probleem: separator can be lpeg and that does not hash too well, but
+-- it's quite okay as the key is then not garbage collected
+
+local splitters_s, splitters_m, splitters_t = { }, { }, { }
+
+local function splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = P(separator)
+ local other = C((1 - separator)^0)
+ if single then
+ local any = anything
+ splitter = other * (separator * C(any^0) + "") -- ?
+ splitters_s[separator] = splitter
+ else
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
+local function tsplitat(separator)
+ local splitter = splitters_t[separator]
+ if not splitter then
+ splitter = Ct(splitat(separator))
+ splitters_t[separator] = splitter
+ end
+ return splitter
+end
+
+lpeg.splitat = splitat
+lpeg.tsplitat = tsplitat
+
+function string.splitup(str,separator)
+ if not separator then
+ separator = ","
+ end
+ return match(splitters_m[separator] or splitat(separator),str)
+end
+
+--~ local p = splitat("->",false) print(match(p,"oeps->what->more")) -- oeps what more
+--~ local p = splitat("->",true) print(match(p,"oeps->what->more")) -- oeps what->more
+--~ local p = splitat("->",false) print(match(p,"oeps")) -- oeps
+--~ local p = splitat("->",true) print(match(p,"oeps")) -- oeps
+
+local cache = { }
+
+function lpeg.split(separator,str)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.split(str,separator)
+ local c = cache[separator]
+ if not c then
+ c = tsplitat(separator)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+local spacing = patterns.spacer^0 * newline -- sort of strip
+local empty = spacing * Cc("")
+local nonempty = Cs((1-spacing)^1) * spacing^-1
+local content = (empty + nonempty)^1
+
+patterns.textline = content
+
+--~ local linesplitter = Ct(content^0)
+--~
+--~ function string.splitlines(str)
+--~ return match(linesplitter,str)
+--~ end
+
+local linesplitter = tsplitat(newline)
+
+patterns.linesplitter = linesplitter
+
+function string.splitlines(str)
+ return match(linesplitter,str)
+end
+
+local utflinesplitter = utfbom^-1 * tsplitat(newline)
+
+patterns.utflinesplitter = utflinesplitter
+
+function string.utfsplitlines(str)
+ return match(utflinesplitter,str or "")
+end
+
+--~ lpeg.splitters = cache -- no longer public
+
+local cache = { }
+
+function lpeg.checkedsplit(separator,str)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+function string.checkedsplit(str,separator)
+ local c = cache[separator]
+ if not c then
+ separator = P(separator)
+ local other = C((1 - separator)^1)
+ c = Ct(separator^0 * other * (separator^1 * other)^0)
+ cache[separator] = c
+ end
+ return match(c,str)
+end
+
+--~ from roberto's site:
+
+local function f2(s) local c1, c2 = byte(s,1,2) return c1 * 64 + c2 - 12416 end
+local function f3(s) local c1, c2, c3 = byte(s,1,3) return (c1 * 64 + c2) * 64 + c3 - 925824 end
+local function f4(s) local c1, c2, c3, c4 = byte(s,1,4) return ((c1 * 64 + c2) * 64 + c3) * 64 + c4 - 63447168 end
+
+local utf8byte = patterns.utf8one/byte + patterns.utf8two/f2 + patterns.utf8three/f3 + patterns.utf8four/f4
+
+patterns.utf8byte = utf8byte
+
+--~ local str = " a b c d "
+
+--~ local s = lpeg.stripper(lpeg.R("az")) print("["..lpeg.match(s,str).."]")
+--~ local s = lpeg.keeper(lpeg.R("az")) print("["..lpeg.match(s,str).."]")
+--~ local s = lpeg.stripper("ab") print("["..lpeg.match(s,str).."]")
+--~ local s = lpeg.keeper("ab") print("["..lpeg.match(s,str).."]")
+
+local cache = { }
+
+function lpeg.stripper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs(((S(str)^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs(((str^1)/"" + 1)^0)
+ end
+end
+
+local cache = { }
+
+function lpeg.keeper(str)
+ if type(str) == "string" then
+ local s = cache[str]
+ if not s then
+ s = Cs((((1-S(str))^1)/"" + 1)^0)
+ cache[str] = s
+ end
+ return s
+ else
+ return Cs((((1-str)^1)/"" + 1)^0)
+ end
+end
+
+function lpeg.frontstripper(str) -- or pattern (yet undocumented)
+ return (P(str) + P(true)) * Cs(P(1)^0)
+end
+
+function lpeg.endstripper(str) -- or pattern (yet undocumented)
+ return Cs((1 - P(str) * P(-1))^0)
+end
+
+-- Just for fun I looked at the used bytecode and
+-- p = (p and p + pp) or pp gets one more (testset).
+
+function lpeg.replacer(one,two)
+ if type(one) == "table" then
+ local no = #one
+ if no > 0 then
+ local p
+ for i=1,no do
+ local o = one[i]
+ local pp = P(o[1]) / o[2]
+ if p then
+ p = p + pp
+ else
+ p = pp
+ end
+ end
+ return Cs((p + 1)^0)
+ end
+ else
+ two = two or ""
+ return Cs((P(one)/two + 1)^0)
+ end
+end
+
+local splitters_f, splitters_s = { }, { }
+
+function lpeg.firstofsplit(separator) -- always return value
+ local splitter = splitters_f[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = C((1 - separator)^0)
+ splitters_f[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.secondofsplit(separator) -- nil if not split
+ local splitter = splitters_s[separator]
+ if not splitter then
+ separator = P(separator)
+ splitter = (1 - separator)^0 * separator * C(anything^0)
+ splitters_s[separator] = splitter
+ end
+ return splitter
+end
+
+function lpeg.balancer(left,right)
+ left, right = P(left), P(right)
+ return P { left * ((1 - left - right) + V(1))^0 * right }
+end
+
+--~ print(1,match(lpeg.firstofsplit(":"),"bc:de"))
+--~ print(2,match(lpeg.firstofsplit(":"),":de")) -- empty
+--~ print(3,match(lpeg.firstofsplit(":"),"bc"))
+--~ print(4,match(lpeg.secondofsplit(":"),"bc:de"))
+--~ print(5,match(lpeg.secondofsplit(":"),"bc:")) -- empty
+--~ print(6,match(lpeg.secondofsplit(":",""),"bc"))
+--~ print(7,match(lpeg.secondofsplit(":"),"bc"))
+--~ print(9,match(lpeg.secondofsplit(":","123"),"bc"))
+
+--~ -- slower:
+--~
+--~ function lpeg.counter(pattern)
+--~ local n, pattern = 0, (lpeg.P(pattern)/function() n = n + 1 end + lpeg.anything)^0
+--~ return function(str) n = 0 ; lpegmatch(pattern,str) ; return n end
+--~ end
+
+local nany = utf8char/""
+
+function lpeg.counter(pattern)
+ pattern = Cs((P(pattern)/" " + nany)^0)
+ return function(str)
+ return #match(pattern,str)
+ end
+end
+
+if utfgmatch then
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local n = 0
+ for _ in utfgmatch(str,what) do
+ n = n + 1
+ end
+ return n
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+else
+
+ local cache = { }
+
+ function lpeg.count(str,what) -- replaces string.count
+ if type(what) == "string" then
+ local p = cache[what]
+ if not p then
+ p = Cs((P(what)/" " + nany)^0)
+ cache[p] = p
+ end
+ return #match(p,str)
+ else -- 4 times slower but still faster than / function
+ return #match(Cs((P(what)/" " + nany)^0),str)
+ end
+ end
+
+end
+
+local patterns_escapes = { -- also defines in l-string
+ ["%"] = "%%",
+ ["."] = "%.",
+ ["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
+ ["["] = "%[", ["]"] = "%]",
+ ["("] = "%)", [")"] = "%)",
+ -- ["{"] = "%{", ["}"] = "%}"
+ -- ["^"] = "%^", ["$"] = "%$",
+}
+
+local simple_escapes = { -- also defines in l-string
+ ["-"] = "%-",
+ ["."] = "%.",
+ ["?"] = ".",
+ ["*"] = ".*",
+}
+
+local p = Cs((S("-.+*%()[]") / patterns_escapes + anything)^0)
+local s = Cs((S("-.+*%()[]") / simple_escapes + anything)^0)
+
+function string.escapedpattern(str,simple)
+ return match(simple and s or p,str)
+end
+
+-- utf extensies
+
+lpeg.UP = lpeg.P
+
+if utfcharacters then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfcharacters(str) do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+
+elseif utfgmatch then
+
+ function lpeg.US(str)
+ local p
+ for uc in utfgmatch(str,".") do
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ return p
+ end
+
+else
+
+ function lpeg.US(str)
+ local p
+ local f = function(uc)
+ if p then
+ p = p + P(uc)
+ else
+ p = P(uc)
+ end
+ end
+ match((utf8char/f)^0,str)
+ return p
+ end
+
+end
+
+local range = Cs(utf8byte) * (Cs(utf8byte) + Cc(false))
+
+local utfchar = unicode and unicode.utf8 and unicode.utf8.char
+
+function lpeg.UR(str,more)
+ local first, last
+ if type(str) == "number" then
+ first = str
+ last = more or first
+ else
+ first, last = match(range,str)
+ if not last then
+ return P(str)
+ end
+ end
+ if first == last then
+ return P(str)
+ elseif utfchar and last - first < 8 then -- a somewhat arbitrary criterium
+ local p
+ for i=first,last do
+ if p then
+ p = p + P(utfchar(i))
+ else
+ p = P(utfchar(i))
+ end
+ end
+ return p -- nil when invalid range
+ else
+ local f = function(b)
+ return b >= first and b <= last
+ end
+ return utf8byte / f -- nil when invalid range
+ end
+end
+
+--~ lpeg.print(lpeg.R("ab","cd","gh"))
+--~ lpeg.print(lpeg.P("a","b","c"))
+--~ lpeg.print(lpeg.S("a","b","c"))
+
+--~ print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
+--~ print(lpeg.count("äáàa",lpeg.UP("áà")))
+--~ print(lpeg.count("äáàa",lpeg.US("àá")))
+--~ print(lpeg.count("äáàa",lpeg.UR("aá")))
+--~ print(lpeg.count("äáàa",lpeg.UR("àá")))
+--~ print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+
+function lpeg.oneof(list,...) -- lpeg.oneof("elseif","else","if","then")
+ if type(list) ~= "table" then
+ list = { list, ... }
+ end
+ -- sort(list) -- longest match first
+ local p = P(list[1])
+ for l=2,#list do
+ p = p + P(list[l])
+ end
+ return p
+end
+
+function lpeg.is_lpeg(p)
+ return p and lpegtype(p) == "pattern"
+end
+
+-- For the moment here, but it might move to utilities. Beware, we need to
+-- have the longest keyword first, so 'aaa' comes beforte 'aa' which is why we
+-- loop back from the end cq. prepend.
+
+local sort, fastcopy, sortedkeys = table.sort, table.fastcopy, table.sortedkeys -- dependency!
+
+function lpeg.append(list,pp,delayed,checked)
+ local p = pp
+ if #list > 0 then
+ local keys = fastcopy(list)
+ sort(keys)
+ for i=#keys,1,-1 do
+ local k = keys[i]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ elseif delayed then -- hm, it looks like the lpeg parser resolves anyway
+ local keys = sortedkeys(list)
+ if p then
+ for i=1,#keys,1 do
+ local k = keys[i]
+ local v = list[k]
+ p = P(k)/list + p
+ end
+ else
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k) + p
+ else
+ p = P(k)
+ end
+ end
+ if p then
+ p = p / list
+ end
+ end
+ elseif checked then
+ -- problem: substitution gives a capture
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ if k == v then
+ p = P(k) + p
+ else
+ p = P(k)/v + p
+ end
+ else
+ if k == v then
+ p = P(k)
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ else
+ local keys = sortedkeys(list)
+ for i=1,#keys do
+ local k = keys[i]
+ local v = list[k]
+ if p then
+ p = P(k)/v + p
+ else
+ p = P(k)/v
+ end
+ end
+ end
+ return p
+end
+
+-- inspect(lpeg.append({ a = "1", aa = "1", aaa = "1" } ,nil,true))
+-- inspect(lpeg.append({ ["degree celsius"] = "1", celsius = "1", degree = "1" } ,nil,true))
+
+-- function lpeg.exact_match(words,case_insensitive)
+-- local pattern = concat(words)
+-- if case_insensitive then
+-- local pattern = S(upper(characters)) + S(lower(characters))
+-- local list = { }
+-- for i=1,#words do
+-- list[lower(words[i])] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[lower(s)] and i
+-- end)
+-- else
+-- local pattern = S(concat(words))
+-- local list = { }
+-- for i=1,#words do
+-- list[words[i]] = true
+-- end
+-- return Cmt(pattern^1, function(_,i,s)
+-- return list[s] and i
+-- end)
+-- end
+-- end
+
+-- experiment:
+
+local function make(t)
+ local p
+-- for k, v in next, t do
+ for k, v in table.sortedhash(t) do
+ if not p then
+ if next(v) then
+ p = P(k) * make(v)
+ else
+ p = P(k)
+ end
+ else
+ if next(v) then
+ p = p + P(k) * make(v)
+ else
+ p = p + P(k)
+ end
+ end
+ end
+ return p
+end
+
+function lpeg.utfchartabletopattern(list)
+ local tree = { }
+ for i=1,#list do
+ local t = tree
+ for c in gmatch(list[i],".") do
+ if not t[c] then
+ t[c] = { }
+ end
+ t = t[c]
+ end
+ end
+ return make(tree)
+end
+
+-- inspect ( lpeg.utfchartabletopattern {
+-- utfchar(0x00A0), -- nbsp
+-- utfchar(0x2000), -- enquad
+-- utfchar(0x2001), -- emquad
+-- utfchar(0x2002), -- enspace
+-- utfchar(0x2003), -- emspace
+-- utfchar(0x2004), -- threeperemspace
+-- utfchar(0x2005), -- fourperemspace
+-- utfchar(0x2006), -- sixperemspace
+-- utfchar(0x2007), -- figurespace
+-- utfchar(0x2008), -- punctuationspace
+-- utfchar(0x2009), -- breakablethinspace
+-- utfchar(0x200A), -- hairspace
+-- utfchar(0x200B), -- zerowidthspace
+-- utfchar(0x202F), -- narrownobreakspace
+-- utfchar(0x205F), -- math thinspace
+-- } )
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules = { } end modules ['l-boolean'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, tonumber = type, tonumber
+
+boolean = boolean or { }
+local boolean = boolean
+
+function boolean.tonumber(b)
+ if b then return 1 else return 0 end -- test and return or return
+end
+
+function toboolean(str,tolerant)
+ if tolerant then
+ local tstr = type(str)
+ if tstr == "string" then
+ return str == "true" or str == "yes" or str == "on" or str == "1" or str == "t"
+ elseif tstr == "number" then
+ return tonumber(str) ~= 0
+ elseif tstr == "nil" then
+ return false
+ else
+ return str
+ end
+ elseif str == "true" then
+ return true
+ elseif str == "false" then
+ return false
+ else
+ return str
+ end
+end
+
+string.toboolean = toboolean
+
+function string.is_boolean(str,default)
+ if type(str) == "string" then
+ if str == "true" or str == "yes" or str == "on" or str == "t" then
+ return true
+ elseif str == "false" or str == "no" or str == "off" or str == "f" then
+ return false
+ end
+ end
+ return default
+end
+
+end -- closure
+
+do -- begin closure to overcome local limits and interference
+
+if not modules then modules = { } end modules ['l-math'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local floor, sin, cos, tan = math.floor, math.sin, math.cos, math.tan
+
+if not math.round then
+ function math.round(x) return floor(x + 0.5) end
+end
+
+if not math.div then
+ function math.div(n,m) return floor(n/m) end
+end
+
+if not math.mod then
+ function math.mod(n,m) return n % m end
+end
+
+local pipi = 2*math.pi/360
+
+if not math.sind then
+ function math.sind(d) return sin(d*pipi) end
+ function math.cosd(d) return cos(d*pipi) end
+ function math.tand(d) return tan(d*pipi) end
+end
+
+if not math.odd then
+ function math.odd (n) return n % 2 ~= 0 end
+ function math.even(n) return n % 2 == 0 end
+end
+
end -- closure
do -- begin closure to overcome local limits and interference
@@ -1817,10 +2065,10 @@ end
local trick_1 = char(1)
local trick_2 = "^" .. trick_1 .. "/+"
-function file.join(...)
+function file.join(...) -- rather dirty
local lst = { ... }
local a, b = lst[1], lst[2]
- if a == "" then
+ if not a or a == "" then -- not a added
lst[1] = trick_1
elseif b and find(a,"^/+$") and find(b,"^/") then
lst[1] = ""
@@ -1850,9 +2098,39 @@ end
--~ print(file.join("http:///a","/y"))
--~ print(file.join("//nas-1","/y"))
+-- We should be able to use:
+--
+-- function file.is_writable(name)
+-- local a = attributes(name) or attributes(dirname(name,"."))
+-- return a and sub(a.permissions,2,2) == "w"
+-- end
+--
+-- But after some testing Taco and I came up with:
+
function file.is_writable(name)
- local a = attributes(name) or attributes(dirname(name,"."))
- return a and sub(a.permissions,2,2) == "w"
+ if lfs.isdir(name) then
+ name = name .. "/m_t_x_t_e_s_t.tmp"
+ local f = io.open(name,"wb")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
+ end
+ elseif lfs.isfile(name) then
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ return true
+ end
+ else
+ local f = io.open(name,"ab")
+ if f then
+ f:close()
+ os.remove(name)
+ return true
+ end
+ end
+ return false
end
function file.is_readable(name)
@@ -1900,7 +2178,7 @@ end
--~ variant. After some skyping we got it sort of compatible with the old
--~ one. After that the anchoring to currentdir was added in a better way.
--~ Of course there are some optimizations too. Finally we had to deal with
---~ windows drive prefixes and thinsg like sys://.
+--~ windows drive prefixes and things like sys://.
function file.collapsepath(str,anchor)
if anchor and not find(str,"^/") and not find(str,"^%a:") then
@@ -1928,7 +2206,7 @@ function file.collapsepath(str,anchor)
if element == '.' then
-- do nothing
elseif element == '..' then
- local n = i -1
+ local n = i - 1
while n > 0 do
local element = oldelements[n]
if element ~= '..' and element ~= '.' then
@@ -2102,10 +2380,42 @@ local path = C(((1-slash)^0 * slash)^0)
local suffix = period * C(P(1-period)^0 * P(-1))
local base = C((1-suffix)^0)
-local pattern = (drive + Cc("")) * (path + Cc("")) * (base + Cc("")) * (suffix + Cc(""))
+drive = drive + Cc("")
+path = path + Cc("")
+base = base + Cc("")
+suffix = suffix + Cc("")
+
+local pattern_a = drive * path * base * suffix
+local pattern_b = path * base * suffix
+local pattern_c = C(drive * path) * C(base * suffix)
+
+function file.splitname(str,splitdrive)
+ if splitdrive then
+ return lpegmatch(pattern_a,str) -- returns drive, path, base, suffix
+ else
+ return lpegmatch(pattern_b,str) -- returns path, base, suffix
+ end
+end
-function file.splitname(str) -- returns drive, path, base, suffix
- return lpegmatch(pattern,str)
+function file.nametotable(str,splitdrive) -- returns table
+ local path, drive, subpath, name, base, suffix = lpegmatch(pattern_c,str)
+ if splitdrive then
+ return {
+ path = path,
+ drive = drive,
+ subpath = subpath,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ else
+ return {
+ path = path,
+ name = name,
+ base = base,
+ suffix = suffix,
+ }
+ end
end
-- function test(t) for k, v in next, t do print(v, "=>", file.splitname(v)) end end
@@ -2390,6 +2700,11 @@ function io.readstring(f,n,m)
return str
end
+--
+
+if not io.i_limiter then function io.i_limiter() end end -- dummy so we can test safely
+if not io.o_limiter then function io.o_limiter() end end -- dummy so we can test safely
+
end -- closure
do -- begin closure to overcome local limits and interference
@@ -2476,6 +2791,8 @@ local remapper = {
dfont = "truetype fonts", -- "truetype dictionary",
cid = "cid maps",
fea = "font feature files",
+ pfa = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
+ pfb = "type1 fonts", -- this is for Khaled, in ConTeXt we don't use this!
}
function resolvers.findfile(name,fileformat)
@@ -2587,7 +2904,7 @@ end
local function makefullname(path,name)
if path and path ~= "" then
name = "temp-" .. name -- clash prevention
- return file.addsuffix(file.join(path,name),"lua")
+ return file.addsuffix(file.join(path,name),"lua"), file.addsuffix(file.join(path,name),"luc")
end
end
@@ -2598,26 +2915,67 @@ end
function caches.loaddata(paths,name)
for i=1,#paths do
- local fullname = makefullname(paths[i],name)
- if fullname then
- texio.write(string.format("(load: %s)",fullname))
- local data = loadfile(fullname)
- return data and data()
+ local data = false
+ local luaname, lucname = makefullname(paths[i],name)
+ if lucname and lfs.isfile(lucname) then
+ texio.write(string.format("(load: %s)",lucname))
+ data = loadfile(lucname)
end
+ if not data and luaname and lfs.isfile(luaname) then
+ texio.write(string.format("(load: %s)",luaname))
+ data = loadfile(luaname)
+ end
+ return data and data()
end
end
function caches.savedata(path,name,data)
- local fullname = makefullname(path,name)
- if fullname then
- texio.write(string.format("(save: %s)",fullname))
- table.tofile(fullname,data,true,{ reduce = true })
+ local luaname, lucname = makefullname(path,name)
+ if luaname then
+ texio.write(string.format("(save: %s)",luaname))
+ table.tofile(luaname,data,true,{ reduce = true })
+ if lucname and type(caches.compile) == "function" then
+ os.remove(lucname) -- better be safe
+ texio.write(string.format("(save: %s)",lucname))
+ caches.compile(data,luaname,lucname)
+ end
end
end
+-- According to KH os.execute is not permitted in plain/latex so there is
+-- no reason to use the normal context way. So the method here is slightly
+-- different from the one we have in context. We also use different suffixes
+-- as we don't want any clashes (sharing cache files is not that handy as
+-- context moves on faster.)
--
+-- Beware: serialization might fail on large files (so maybe we should pcall
+-- this) in which case one should limit the method to luac and enable support
+-- for execution.
+
+caches.compilemethod = "luac" -- luac dump both
-local table.setmetatableindex(t,f)
+function caches.compile(data,luaname,lucname)
+ local done = false
+ if caches.compilemethod == "luac" or caches.compilemethod == "both" then
+ local command = "-o " .. string.quoted(lucname) .. " -s " .. string.quoted(luaname)
+ done = os.spawn("texluac " .. command) == 0
+ end
+ if not done and (caches.compilemethod == "dump" or caches.compilemethod == "both") then
+ local d = table.serialize(data,true)
+ if d and d ~= "" then
+ local f = io.open(lucname,'w')
+ if f then
+ local s = loadstring(d)
+ f:write(string.dump(s))
+ f:close()
+ end
+ end
+ end
+end
+
+--
+
+function table.setmetatableindex(t,f)
setmetatable(t,{ __index = f })
end
@@ -2917,12 +3275,15 @@ if not modules then modules = { } end modules ['font-con'] = {
}
+-- some names of table entries will be changed (no _)
+
local utf = unicode.utf8
local next, tostring, rawget = next, tostring, rawget
local format, match, lower, gsub = string.format, string.match, string.lower, string.gsub
local utfbyte = utf.byte
local sort, insert, concat, sortedkeys, serialize, fastcopy = table.sort, table.insert, table.concat, table.sortedkeys, table.serialize, table.fastcopy
+local derivetable = table.derive
local trace_defining = false trackers.register("fonts.defining", function(v) trace_defining = v end)
local trace_scaling = false trackers.register("fonts.scaling" , function(v) trace_scaling = v end)
@@ -2935,32 +3296,128 @@ local report_defining = logs.reporter("fonts","defining")
<p>Here we only implement a few helper functions.</p>
--ldx]]--
-local fonts = fonts
-local constructors = { }
-fonts.constructors = constructors
-local handlers = { }
-fonts.handlers = handlers
+local fonts = fonts
+local constructors = { }
+fonts.constructors = constructors
+local handlers = { }
+fonts.handlers = handlers
-local specifiers = fonts.specifiers
-local contextsetups = specifiers.contextsetups
-local contextnumbers = specifiers.contextnumbers
+local specifiers = fonts.specifiers
+local contextsetups = specifiers.contextsetups
+local contextnumbers = specifiers.contextnumbers
-local allocate = utilities.storage.allocate
-local setmetatableindex = table.setmetatableindex
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
-- will be directives
-constructors.dontembed = allocate()
-constructors.mathactions = { }
-constructors.autocleanup = true
-constructors.namemode = "fullpath" -- will be a function
+constructors.dontembed = allocate()
+constructors.autocleanup = true
+constructors.namemode = "fullpath" -- will be a function
-constructors.version = 1.01
-constructors.cache = containers.define("fonts", "constructors", constructors.version, false)
+constructors.version = 1.01
+constructors.cache = containers.define("fonts", "constructors", constructors.version, false)
-constructors.privateoffset = 0xF0000 -- 0x10FFFF
+constructors.privateoffset = 0xF0000 -- 0x10FFFF
+
+-- Some experimental helpers (handy for tracing):
+--
+-- todo: extra:
+--
+-- extra_space => space.extra
+-- space => space.width
+-- space_stretch => space.stretch
+-- space_shrink => space.shrink
+
+-- We do keep the x-height, extra_space, space_shrink and space_stretch
+-- around as these are low level official names.
+
+constructors.keys = {
+ properties = {
+ encodingbytes = "number",
+ embedding = "number",
+ cidinfo = {
+ },
+ format = "string",
+ fontname = "string",
+ fullname = "string",
+ filename = "filename",
+ psname = "string",
+ name = "string",
+ virtualized = "boolean",
+ hasitalics = "boolean",
+ autoitalicamount = "basepoints",
+ nostackmath = "boolean",
+ noglyphnames = "boolean",
+ mode = "string",
+ hasmath = "boolean",
+ mathitalics = "boolean",
+ textitalics = "boolean",
+ finalized = "boolean",
+ },
+ parameters = {
+ mathsize = "number",
+ scriptpercentage = "float",
+ scriptscriptpercentage = "float",
+ units = "cardinal",
+ designsize = "scaledpoints",
+ expansion = {
+ stretch = "integerscale", -- might become float
+ shrink = "integerscale", -- might become float
+ step = "integerscale", -- might become float
+ auto = "boolean",
+ },
+ protrusion = {
+ auto = "boolean",
+ },
+ slantfactor = "float",
+ extendfactor = "float",
+ factor = "float",
+ hfactor = "float",
+ vfactor = "float",
+ size = "scaledpoints",
+ units = "scaledpoints",
+ scaledpoints = "scaledpoints",
+ slantperpoint = "scaledpoints",
+ spacing = {
+ width = "scaledpoints",
+ stretch = "scaledpoints",
+ shrink = "scaledpoints",
+ extra = "scaledpoints",
+ },
+ xheight = "scaledpoints",
+ quad = "scaledpoints",
+ ascender = "scaledpoints",
+ descender = "scaledpoints",
+ synonyms = {
+ space = "spacing.width",
+ spacestretch = "spacing.stretch",
+ spaceshrink = "spacing.shrink",
+ extraspace = "spacing.extra",
+ x_height = "xheight",
+ space_stretch = "spacing.stretch",
+ space_shrink = "spacing.shrink",
+ extra_space = "spacing.extra",
+ em = "quad",
+ ex = "xheight",
+ slant = "slantperpoint",
+ },
+ },
+ description = {
+ width = "basepoints",
+ height = "basepoints",
+ depth = "basepoints",
+ boundingbox = { },
+ },
+ character = {
+ width = "scaledpoints",
+ height = "scaledpoints",
+ depth = "scaledpoints",
+ italic = "scaledpoints",
+ },
+}
--- This might become an interface;
+-- This might become an interface:
local designsizes = allocate()
constructors.designsizes = designsizes
@@ -3009,7 +3466,7 @@ excessive memory usage in CJK fonts, we no longer pass the boundingbox.)</p>
-- The scaler is only used for otf and afm and virtual fonts. If
-- a virtual font has italic correction make sure to set the
--- italic_correction flag. Some more flags will be added in
+-- hasitalics flag. Some more flags will be added in
-- the future.
--[[ldx--
@@ -3055,39 +3512,75 @@ function constructors.calculatescale(tfmdata,scaledpoints)
return scaledpoints, scaledpoints / (parameters.units or 1000) -- delta
end
-function constructors.assignmathparameters(target,tfmdata)
+local unscaled = {
+ ScriptPercentScaleDown = true,
+ ScriptScriptPercentScaleDown = true,
+ RadicalDegreeBottomRaisePercent = true
+}
+
+function constructors.assignmathparameters(target,original) -- simple variant, not used in context
-- when a tfm file is loaded, it has already been scaled
- -- and it never enters the scaled so this is otf only
+ -- and it never enters the scaled so this is otf only and
+ -- even then we do some extra in the context math plugins
local mathparameters = original.mathparameters
if mathparameters and next(mathparameters) then
local targetparameters = target.parameters
+ local targetproperties = target.properties
local targetmathparameters = { }
- local factor = targetparameters.factor
+ local factor = targetproperties.math_is_scaled and 1 or targetparameters.factor
for name, value in next, mathparameters do
- if name == "RadicalDegreeBottomRaisePercent" then
+ if unscaled[name] then
targetmathparameters[name] = value
else
targetmathparameters[name] = value * factor
end
end
- if not targetmathparameters.AccentBaseHeight then
- targetmathparameters.AccentBaseHeight = nil -- safeguard, still needed?
- end
if not targetmathparameters.FractionDelimiterSize then
- targetmathparameters.FractionDelimiterSize = 0
+ targetmathparameters.FractionDelimiterSize = 1.01 * targetparameters.size
end
if not mathparameters.FractionDelimiterDisplayStyleSize then
- targetmathparameters.FractionDelimiterDisplayStyleSize = 0
+ targetmathparameters.FractionDelimiterDisplayStyleSize = 2.40 * targetparameters.size
end
target.mathparameters = targetmathparameters
end
end
+function constructors.beforecopyingcharacters(target,original)
+ -- can be used for additional tweaking
+end
+
+function constructors.aftercopyingcharacters(target,original)
+ -- can be used for additional tweaking
+end
+
+function constructors.enhanceparameters(parameters)
+ local xheight = parameters.x_height
+ local quad = parameters.quad
+ local space = parameters.space
+ local stretch = parameters.space_stretch
+ local shrink = parameters.space_shrink
+ local extra = parameters.extra_space
+ local slant = parameters.slant
+ parameters.xheight = xheight
+ parameters.spacestretch = stretch
+ parameters.spaceshrink = shrink
+ parameters.extraspace = extra
+ parameters.em = quad
+ parameters.ex = xheight
+ parameters.slantperpoint = slant
+ parameters.spacing = {
+ width = space,
+ stretch = stretch,
+ shrink = shrink,
+ extra = extra,
+ }
+end
+
function constructors.scale(tfmdata,specification)
local target = { } -- the new table
--
if tonumber(specification) then
- specification = { size = specification }
+ specification = { size = specification }
end
--
local scaledpoints = specification.size
@@ -3104,10 +3597,9 @@ function constructors.scale(tfmdata,specification)
local mathparameters = tfmdata.mathparameters or { }
--
local targetcharacters = { }
- local targetdescriptions = table.derive(descriptions)
- local targetparameters = table.derive(parameters)
- -- local targetmathparameters = table.fastcopy(mathparameters) -- happens elsewhere
- local targetproperties = table.derive(properties)
+ local targetdescriptions = derivetable(descriptions)
+ local targetparameters = derivetable(parameters)
+ local targetproperties = derivetable(properties)
local targetgoodies = goodies -- we need to loop so no metatable
target.characters = targetcharacters
target.descriptions = targetdescriptions
@@ -3123,9 +3615,10 @@ function constructors.scale(tfmdata,specification)
-- specification.textsize : natural (text)size
-- parameters.mathsize : 1=text 2=script 3=scriptscript >1000 enforced size (feature value other than yes)
--
- local mathsize = tonumber(specification.mathsize) or 0
- local textsize = tonumber(specification.textsize) or scaledpoints
- local forcedsize = tonumber(parameters.mathsize ) or 0
+ local mathsize = tonumber(specification.mathsize) or 0
+ local textsize = tonumber(specification.textsize) or scaledpoints
+ local forcedsize = tonumber(parameters.mathsize ) or 0
+ local extrafactor = tonumber(specification.factor ) or 1
if (mathsize == 2 or forcedsize == 2) and parameters.scriptpercentage then
scaledpoints = parameters.scriptpercentage * textsize / 100
elseif (mathsize == 3 or forcedsize == 3) and parameters.scriptscriptpercentage then
@@ -3212,17 +3705,17 @@ function constructors.scale(tfmdata,specification)
target.auto_protrude = protrusion.auto
end
-- widening
- local extend_factor = parameters.extend_factor or 0
- if extend_factor ~= 0 and extend_factor ~= 1 then
- hdelta = hdelta * extend_factor
- target.extend = extend_factor * 1000 -- extent ?
+ local extendfactor = parameters.extendfactor or 0
+ if extendfactor ~= 0 and extendfactor ~= 1 then
+ hdelta = hdelta * extendfactor
+ target.extend = extendfactor * 1000 -- extent ?
else
target.extend = 1000 -- extent ?
end
-- slanting
- local slant_factor = parameters.slant_factor or 0
- if slant_factor ~= 0 then
- target.slant = slant_factor * 1000
+ local slantfactor = parameters.slantfactor or 0
+ if slantfactor ~= 0 then
+ target.slant = slantfactor * 1000
else
target.slant = 0
end
@@ -3234,19 +3727,20 @@ function constructors.scale(tfmdata,specification)
targetparameters.units = units
targetparameters.scaledpoints = askedscaledpoints
--
- local isvirtual = properties.virtualized or tfmdata.type == "virtual"
- local hasquality = target.auto_expand or target.auto_protrude
- local hasitalic = properties.italic_correction
- local stackmath = not properties.no_stackmath
- local nonames = properties.noglyphnames
- local nodemode = properties.mode == "node"
+ local isvirtual = properties.virtualized or tfmdata.type == "virtual"
+ local hasquality = target.auto_expand or target.auto_protrude
+ local hasitalics = properties.hasitalics
+ local autoitalicamount = properties.autoitalicamount
+ local stackmath = not properties.nostackmath
+ local nonames = properties.noglyphnames
+ local nodemode = properties.mode == "node"
--
if changed and not next(changed) then
changed = false
end
--
target.type = isvirtual and "virtual" or "real"
- -- this will move to some subtable so that it is copied at once
+ --
target.postprocessors = tfmdata.postprocessors
--
local targetslant = (parameters.slant or parameters[1] or 0)
@@ -3257,7 +3751,7 @@ function constructors.scale(tfmdata,specification)
local targetquad = (parameters.quad or parameters[6] or 0)*hdelta
local targetextra_space = (parameters.extra_space or parameters[7] or 0)*hdelta
--
- targetparameters.slant = targetslant
+ targetparameters.slant = targetslant -- slantperpoint
targetparameters.space = targetspace
targetparameters.space_stretch = targetspace_stretch
targetparameters.space_shrink = targetspace_shrink
@@ -3273,25 +3767,27 @@ function constructors.scale(tfmdata,specification)
if descender then
targetparameters.descender = delta * descender
end
- -- copies, might disappear
- targetparameters.xheight = targetparameters.xheight or parameters.x_height
- targetparameters.extraspace = targetparameters.extraspace or parameters.extra_space
- targetparameters.spacestretch = targetparameters.spacestretch or parameters.space_stretch
- targetparameters.spaceshrink = targetparameters.spaceshrink or parameters.space_shrink
+ --
+ constructors.enhanceparameters(targetparameters) -- official copies for us
--
local protrusionfactor = (targetquad ~= 0 and 1000/targetquad) or 0
local scaledwidth = defaultwidth * hdelta
local scaledheight = defaultheight * vdelta
local scaleddepth = defaultdepth * vdelta
--
- local hasmath = (properties.has_math or next(mathparameters)) and true
+ if trace_defining then
+ report_defining("scaling by (%s,%s): name '%s', fullname: '%s', filename: '%s'",
+ hdelta,vdelta,name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ --
+ local hasmath = (properties.hasmath or next(mathparameters)) and true
if hasmath then
if trace_defining then
report_defining("math enabled for: name '%s', fullname: '%s', filename: '%s'",
name or "noname",fullname or "nofullname",filename or "nofilename")
end
constructors.assignmathparameters(target,tfmdata) -- does scaling and whatever is needed
- properties.has_math = true
+ properties.hasmath = true
target.nomath = false
target.MathConstants = target.mathparameters
else
@@ -3299,29 +3795,75 @@ function constructors.scale(tfmdata,specification)
report_defining("math disabled for: name '%s', fullname: '%s', filename: '%s'",
name or "noname",fullname or "nofullname",filename or "nofilename")
end
- properties.has_math = false
+ properties.hasmath = false
target.nomath = true
target.mathparameters = nil -- nop
end
--
- local sharedkerns = { }
+ local italickey = "italic"
+ --
+ -- some context specific trickery (this will move to a plugin)
+ --
+ if hasmath then
+ if properties.mathitalics then
+ italickey = "italic_correction"
+ if trace_defining then
+ report_defining("math italics disabled for: name '%s', fullname: '%s', filename: '%s'",
+ name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ end
+ autoitalicamount = false -- new
+ else
+ if properties.textitalics then
+ italickey = "italic_correction"
+ if trace_defining then
+ report_defining("text italics disabled for: name '%s', fullname: '%s', filename: '%s'",
+ name or "noname",fullname or "nofullname",filename or "nofilename")
+ end
+ if properties.delaytextitalics then
+ autoitalicamount = false
+ end
+ end
+ end
+ --
+ -- end of context specific trickery
+ --
+ constructors.beforecopyingcharacters(target,tfmdata)
+ --
+ local sharedkerns = { }
+ --
+ -- we can have a dumb mode (basemode without math etc) that skips most
--
for unicode, character in next, characters do
- local chr, description, index
+ local chr, description, index, touni
if changed then
- -- basemode hack
+ -- basemode hack (we try to catch missing tounicodes, e.g. needed for ssty in math cambria)
local c = changed[unicode]
if c then
- description = descriptions[c] or character
+ description = descriptions[c] or descriptions[unicode] or character
character = characters[c] or character
index = description.index or c
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ if not touni then -- goodie
+ local d = descriptions[unicode] or characters[unicode]
+ local i = d.index or unicode
+ touni = tounicode[i] -- nb: index!
+ end
+ end
else
description = descriptions[unicode] or character
index = description.index or unicode
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ end
end
else
description = descriptions[unicode] or character
index = description.index or unicode
+ if tounicode then
+ touni = tounicode[index] -- nb: index!
+ end
end
local width = description.width
local height = description.height
@@ -3364,15 +3906,12 @@ function constructors.scale(tfmdata,specification)
}
end
end
+ if touni then
+ chr.tounicode = touni
+ end
-- if trace_scaling then
-- report_defining("t=%s, u=%s, i=%s, n=%s c=%s",k,chr.tounicode or "",index or 0,description.name or '-',description.class or '-')
-- end
- if tounicode then
- local tu = tounicode[index] -- nb: index!
- if tu then
- chr.tounicode = tu
- end
- end
if hasquality then
-- we could move these calculations elsewhere (saves calculations)
local ve = character.expansion_factor
@@ -3388,11 +3927,21 @@ function constructors.scale(tfmdata,specification)
chr.right_protruding = protrusionfactor*width*vr
end
end
- -- todo: hasitalic
- if hasitalic then
- local vi = description.italic or character.italic
+ --
+ if autoitalicamount then
+ local vi = description.italic
+ if not vi then
+ local vi = description.boundingbox[3] - description.width + autoitalicamount
+ if vi > 0 then -- < 0 indicates no overshoot or a very small auto italic
+ chr[italickey] = vi*hdelta
+ end
+ elseif vi ~= 0 then
+ chr[italickey] = vi*hdelta
+ end
+ elseif hasitalics then
+ local vi = description.italic
if vi and vi ~= 0 then
- chr.italic = vi*hdelta
+ chr[italickey] = vi*hdelta
end
end
-- to be tested
@@ -3523,6 +4072,9 @@ function constructors.scale(tfmdata,specification)
end
targetcharacters[unicode] = chr
end
+ --
+ constructors.aftercopyingcharacters(target,tfmdata)
+ --
return target
end
@@ -3563,12 +4115,12 @@ function constructors.finalize(tfmdata)
parameters.size = tfmdata.size
end
--
- if not parameters.extend_factor then
- parameters.extend_factor = tfmdata.extend or 0
+ if not parameters.extendfactor then
+ parameters.extendfactor = tfmdata.extend or 0
end
--
- if not parameters.slant_factor then
- parameters.slant_factor = tfmdata.slant or 0
+ if not parameters.slantfactor then
+ parameters.slantfactor = tfmdata.slant or 0
end
--
if not parameters.designsize then
@@ -3621,8 +4173,8 @@ function constructors.finalize(tfmdata)
-- tfmdata.fonts
-- tfmdata.unscaled
--
- if not properties.has_math then
- properties.has_math = not tfmdata.nomath
+ if not properties.hasmath then
+ properties.hasmath = not tfmdata.nomath
end
--
tfmdata.MathConstants = nil
@@ -3907,7 +4459,7 @@ a helper function.</p>
function constructors.checkedfeatures(what,features)
local defaults = handlers[what].features.defaults
if features and next(features) then
- features = fastcopy(features) -- can be inherited
+ features = fastcopy(features) -- can be inherited (mt) but then no loops possible
for key, value in next, defaults do
if features[key] == nil then
features[key] = value
@@ -3941,7 +4493,7 @@ function constructors.initializefeatures(what,tfmdata,features,trace,report)
for i=1,#initializers do
local step = initializers[i]
local feature = step.name
--- we could intercept mode here .. needs a rewrite of this whole loop then btu it's cleaner that way
+-- we could intercept mode here .. needs a rewrite of this whole loop then but it's cleaner that way
local value = features[feature]
if not value then
-- disabled
@@ -4010,6 +4562,9 @@ function constructors.collectprocessors(what,tfmdata,features,trace,report)
end
end
end
+ elseif trace then
+ report("no feature processors for mode %s for font %s",
+ mode or 'unknown', tfmdata.properties.fullname or 'unknown')
end
end
return processes
@@ -4068,7 +4623,7 @@ fonts.encodings.agl = { }
setmetatable(fonts.encodings.agl, { __index = function(t,k)
if k == "unicodes" then
texio.write(" <loading (extended) adobe glyph list>")
- local unicodes = dofile(resolvers.findfile("font-agl.lua"))
+ local unicodes = dofile(resolvers.findfile("font-age.lua"))
fonts.encodings.agl = { unicodes = unicodes }
return unicodes
else
@@ -4351,6 +4906,15 @@ local function tounicode16sequence(unicodes)
return concat(t)
end
+local function fromunicode16(str)
+ if #str == 4 then
+ return tonumber(str,16)
+ else
+ local l, r = match(str,"(....)(....)")
+ return (tonumber(l,16)- 0xD800)*0x400 + tonumber(r,16) - 0xDC00
+ end
+end
+
--~ This is quite a bit faster but at the cost of some memory but if we
--~ do this we will also use it elsewhere so let's not follow this route
--~ now. I might use this method in the plain variant (no caching there)
@@ -4375,6 +4939,7 @@ mappings.loadlumtable = loadlumtable
mappings.makenameparser = makenameparser
mappings.tounicode16 = tounicode16
mappings.tounicode16sequence = tounicode16sequence
+mappings.fromunicode16 = fromunicode16
local separator = S("_.")
local other = C((1 - separator)^1)
@@ -4430,7 +4995,9 @@ function mappings.addtounicode(data,filename)
if unic == -1 or unic >= private or (unic >= 0xE000 and unic <= 0xF8FF) or unic == 0xFFFE or unic == 0xFFFF then
local unicode = lumunic and lumunic[name] or unicodevector[name]
if unicode then
- originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ originals[index] = unicode
+ tounicode[index] = tounicode16(unicode)
+ ns = ns + 1
end
-- cidmap heuristics, beware, there is no guarantee for a match unless
-- the chain resolves
@@ -4439,7 +5006,9 @@ function mappings.addtounicode(data,filename)
if foundindex then
unicode = cidcodes[foundindex] -- name to number
if unicode then
- originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ originals[index] = unicode
+ tounicode[index] = tounicode16(unicode)
+ ns = ns + 1
else
local reference = cidnames[foundindex] -- number to name
if reference then
@@ -4447,16 +5016,23 @@ function mappings.addtounicode(data,filename)
if foundindex then
unicode = cidcodes[foundindex]
if unicode then
- originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
+ originals[index] = unicode
+ tounicode[index] = tounicode16(unicode)
+ ns = ns + 1
end
end
if not unicode then
local foundcodes, multiple = lpegmatch(uparser,reference)
if foundcodes then
+ originals[index] = foundcodes
if multiple then
- originals[index], tounicode[index], nl, unicode = foundcodes, tounicode16sequence(foundcodes), nl + 1, true
+ tounicode[index] = tounicode16sequence(foundcodes)
+ nl = nl + 1
+ unicode = true
else
- originals[index], tounicode[index], ns, unicode = foundcodes, tounicode16(foundcodes), ns + 1, foundcodes
+ tounicode[index] = tounicode16(foundcodes)
+ ns = ns + 1
+ unicode = foundcodes
end
end
end
@@ -4467,19 +5043,8 @@ function mappings.addtounicode(data,filename)
-- a.whatever or a_b_c.whatever or a_b_c (no numbers)
if not unicode then
local split = lpegmatch(ligsplitter,name)
- local nplit = (split and #split) or 0
- if nplit == 0 then
- -- skip
- elseif nplit == 1 then
- local base = split[1]
- unicode = unicodes[base] or unicodevector[base]
- if unicode then
- if type(unicode) == "table" then
- unicode = unicode[1]
- end
- originals[index], tounicode[index], ns = unicode, tounicode16(unicode), ns + 1
- end
- else
+ local nplit = split and #split or 0
+ if nplit >= 2 then
local t, n = { }, 0
for l=1,nplit do
local base = split[l]
@@ -4497,26 +5062,39 @@ function mappings.addtounicode(data,filename)
if n == 0 then -- done then
-- nothing
elseif n == 1 then
- originals[index], tounicode[index], nl, unicode = t[1], tounicode16(t[1]), nl + 1, true
+ originals[index] = t[1]
+ tounicode[index] = tounicode16(t[1])
else
- originals[index], tounicode[index], nl, unicode = t, tounicode16sequence(t), nl + 1, true
+ originals[index] = t
+ tounicode[index] = tounicode16sequence(t)
end
+ nl = nl + 1
+ unicode = true
+ else
+ -- skip: already checked and we don't want privates here
end
end
- -- last resort
+ -- last resort (we might need to catch private here as well)
if not unicode then
local foundcodes, multiple = lpegmatch(uparser,name)
if foundcodes then
if multiple then
- originals[index], tounicode[index], nl, unicode = foundcodes, tounicode16sequence(foundcodes), nl + 1, true
+ originals[index] = foundcodes
+ tounicode[index] = tounicode16sequence(foundcodes)
+ nl = nl + 1
+ unicode = true
else
- originals[index], tounicode[index], ns, unicode = foundcodes, tounicode16(foundcodes), ns + 1, foundcodes
+ originals[index] = foundcodes
+ tounicode[index] = tounicode16(foundcodes)
+ ns = ns + 1
+ unicode = foundcodes
end
end
end
- if not unicode then
- originals[index], tounicode[index] = 0xFFFD, "FFFD"
- end
+ -- if not unicode then
+ -- originals[index] = 0xFFFD
+ -- tounicode[index] = "FFFD"
+ -- end
end
end
if trace_mapping then
@@ -4782,6 +5360,8 @@ if not modules then modules = { } end modules ['font-otf'] = {
-- to_table -> totable
-- ascent descent
+-- more checking against low level calls of functions
+
local utf = unicode.utf8
local utfbyte = utf.byte
@@ -4792,7 +5372,7 @@ local getn = table.getn
local lpegmatch = lpeg.match
local reversed, concat, remove = table.reversed, table.concat, table.remove
local ioflush = io.flush
-local fastcopy, tohash = table.fastcopy, table.tohash
+local fastcopy, tohash, derivetable = table.fastcopy, table.tohash, table.derive
local allocate = utilities.storage.allocate
local registertracker = trackers.register
@@ -4817,7 +5397,7 @@ local otf = fonts.handlers.otf
otf.glists = { "gsub", "gpos" }
-otf.version = 2.730 -- beware: also sync font-mis.lua
+otf.version = 2.736 -- beware: also sync font-mis.lua
otf.cache = containers.define("fonts", "otf", otf.version, true)
local fontdata = fonts.hashes.identifiers
@@ -4884,15 +5464,21 @@ local function showfeatureorder(rawdata,filename)
if features then
for feature, scripts in next, features do
local tt = { }
- for script, languages in next, scripts do
- local ttt = { }
- for language, _ in next, languages do
- ttt[#ttt+1] = language
+ if type(scripts) == "table" then
+ for script, languages in next, scripts do
+ local ttt = { }
+ for language, _ in next, languages do
+ ttt[#ttt+1] = language
+ end
+ tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
+ end
+ if trace_loading then
+ report_otf(" %s: %s",feature,concat(tt," "))
+ end
+ else
+ if trace_loading then
+ report_otf(" %s: %s",feature,tostring(scripts))
end
- tt[#tt+1] = format("[%s: %s]",script,concat(ttt," "))
- end
- if trace_loading then
- report_otf(" %s: %s",feature,concat(tt," "))
end
end
end
@@ -5061,11 +5647,14 @@ end
-- patches.register("before","migrate metadata","cambria",function() end)
function patches.register(what,where,pattern,action)
- local ww = what[where]
- if ww then
- ww[pattern] = action
- else
- ww = { [pattern] = action}
+ local pw = patches[what]
+ if pw then
+ local ww = pw[where]
+ if ww then
+ ww[pattern] = action
+ else
+ pw[where] = { [pattern] = action}
+ end
end
end
@@ -5106,8 +5695,8 @@ function otf.load(filename,format,sub,featurefile)
local attr = lfs.attributes(name)
featurefiles[#featurefiles+1] = {
name = name,
- size = size,
- time = time,
+ size = attr and attr.size or 0,
+ time = attr and attr.modification or 0,
}
end
end
@@ -5190,6 +5779,9 @@ function otf.load(filename,format,sub,featurefile)
duplicates = {
-- alternative unicodes
},
+ variants = {
+ -- alternative unicodes (variants)
+ },
lookuptypes = {
},
},
@@ -5214,6 +5806,7 @@ function otf.load(filename,format,sub,featurefile)
if packdata then
if cleanup > 0 then
collectgarbage("collect")
+--~ lua.collectgarbage()
end
enhance("pack",data,filename,nil)
end
@@ -5221,6 +5814,7 @@ function otf.load(filename,format,sub,featurefile)
data = containers.write(otf.cache, hash, data)
if cleanup > 1 then
collectgarbage("collect")
+--~ lua.collectgarbage()
end
stoptiming(data)
if elapsedtime then -- not in generic
@@ -5229,10 +5823,12 @@ function otf.load(filename,format,sub,featurefile)
fontloader.close(fontdata) -- free memory
if cleanup > 3 then
collectgarbage("collect")
+--~ lua.collectgarbage()
end
data = containers.read(otf.cache, hash) -- this frees the old table and load the sparse one
if cleanup > 2 then
collectgarbage("collect")
+--~ lua.collectgarbage()
end
else
data = nil
@@ -5269,7 +5865,7 @@ local mt = {
}
actions["prepare tables"] = function(data,filename,raw)
- data.properties.italic_correction = false
+ data.properties.hasitalics = false
end
actions["add dimensions"] = function(data,filename)
@@ -5354,7 +5950,7 @@ local function somecopy(old) -- fast one
end
end
--- not setting italic_correction and class (when nil) during
+-- not setting hasitalics and class (when nil) during
-- table cronstruction can save some mem
actions["prepare glyphs"] = function(data,filename,raw)
@@ -5370,6 +5966,7 @@ actions["prepare glyphs"] = function(data,filename,raw)
local unicodes = resources.unicodes -- name to unicode
local indices = resources.indices -- index to unicode
local duplicates = resources.duplicates
+ local variants = resources.variants
if rawsubfonts then
@@ -5469,11 +6066,28 @@ actions["prepare glyphs"] = function(data,filename,raw)
}
local altuni = glyph.altuni
if altuni then
- local d = { }
+ local d
for i=1,#altuni do
- d[#d+1] = altuni[i].unicode
+ local a = altuni[i]
+ local u = a.unicode
+ local v = a.variant
+ if v then
+ local vv = variants[v]
+ if vv then
+ vv[u] = unicode
+ else -- xits-math has some:
+ vv = { [u] = unicode }
+ variants[v] = vv
+ end
+ elseif d then
+ d[#d+1] = u
+ else
+ d = { u }
+ end
+ end
+ if d then
+ duplicates[unicode] = d
end
- duplicates[unicode] = d
end
else
report_otf("potential problem: glyph 0x%04X is used but empty",index)
@@ -5495,9 +6109,8 @@ actions["check encoding"] = function(data,filename,raw)
local properties = data.properties
local unicodes = resources.unicodes -- name to unicode
local indices = resources.indices -- index to unicodes
- local duplicates = resources.duplicates
- -- begin of messy (not needed whwn cidmap)
+ -- begin of messy (not needed when cidmap)
local mapdata = raw.map or { }
local unicodetoindex = mapdata and mapdata.map or { }
@@ -5571,7 +6184,6 @@ actions["add duplicates"] = function(data,filename,raw)
end
end
end
-
end
-- class : nil base mark ligature component (maybe we don't need it in description)
@@ -5582,9 +6194,9 @@ actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this
local resources = data.resources
local metadata = data.metadata
local properties = data.properties
- local italic_correction = false
+ local hasitalics = false
local widths = { }
- local marks = { }
+ local marks = { } -- always present (saves checking)
for unicode, description in next, descriptions do
local glyph = description.glyph
local italic = glyph.italic_correction
@@ -5594,7 +6206,7 @@ actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this
-- skip
else
description.italic = italic
- italic_correction = true
+ hasitalics = true
end
local width = glyph.width
widths[width] = (widths[width] or 0) + 1
@@ -5607,7 +6219,7 @@ actions["analyze glyphs"] = function(data,filename,raw) -- maybe integrate this
end
end
-- flag italic
- properties.italic_correction = italic_correction
+ properties.hasitalics = hasitalics
-- flag marks
resources.marks = marks
-- share most common width for cjk fonts
@@ -5729,6 +6341,29 @@ actions["prepare tounicode"] = function(data,filename,raw)
fonts.mappings.addtounicode(data,filename)
end
+local g_directions = {
+ gsub_contextchain = 1,
+ gpos_contextchain = 1,
+ -- gsub_context = 1,
+ -- gpos_context = 1,
+ gsub_reversecontextchain = -1,
+ gpos_reversecontextchain = -1,
+}
+
+-- Research by Khaled Hosny has demonstrated that the font loader merges
+-- regular and AAT features and that these can interfere (especially because
+-- we dropped checking for valid features elsewhere. So, we just check for
+-- the special flag and drop the feature if such a tag is found.
+
+local function supported(features)
+ for i=1,#features do
+ if features[i].ismac then
+ return false
+ end
+ end
+ return true
+end
+
actions["reorganize subtables"] = function(data,filename,raw)
local resources = data.resources
local sequences = { }
@@ -5741,72 +6376,72 @@ actions["reorganize subtables"] = function(data,filename,raw)
if dw then
for k=1,#dw do
local gk = dw[k]
- local typ = gk.type
- local chain =
- (typ == "gsub_contextchain" or typ == "gpos_contextchain") and 1 or
- (typ == "gsub_reversecontextchain" or typ == "gpos_reversecontextchain") and -1 or 0
- --
- local subtables = gk.subtables
- if subtables then
- local t = { }
- for s=1,#subtables do
- t[s] = subtables[s].name
- end
- subtables = t
- end
- local flags, markclass = gk.flags, nil
- if flags then
- local t = { -- forcing false packs nicer
- (flags.ignorecombiningmarks and "mark") or false,
- (flags.ignoreligatures and "ligature") or false,
- (flags.ignorebaseglyphs and "base") or false,
- flags.r2l or false,
- }
- markclass = flags.mark_class
- if markclass then
- markclass = resources.markclasses[markclass]
- end
- flags = t
- end
- --
- local name = gk.name
- --
local features = gk.features
- if features then
- -- scripts, tag, ismac
- local f = { }
- for i=1,#features do
- local df = features[i]
- local tag = strip(lower(df.tag))
- local ft = f[tag] if not ft then ft = {} f[tag] = ft end
- local dscripts = df.scripts
- for i=1,#dscripts do
- local d = dscripts[i]
- local languages = d.langs
- local script = strip(lower(d.script))
- local fts = ft[script] if not fts then fts = {} ft[script] = fts end
- for i=1,#languages do
- fts[strip(lower(languages[i]))] = true
+-- if features and supported(features) then
+ if not features or supported(features) then -- not always features !
+ local typ = gk.type
+ local chain = g_directions[typ] or 0
+ local subtables = gk.subtables
+ if subtables then
+ local t = { }
+ for s=1,#subtables do
+ t[s] = subtables[s].name
+ end
+ subtables = t
+ end
+ local flags, markclass = gk.flags, nil
+ if flags then
+ local t = { -- forcing false packs nicer
+ (flags.ignorecombiningmarks and "mark") or false,
+ (flags.ignoreligatures and "ligature") or false,
+ (flags.ignorebaseglyphs and "base") or false,
+ flags.r2l or false,
+ }
+ markclass = flags.mark_class
+ if markclass then
+ markclass = resources.markclasses[markclass]
+ end
+ flags = t
+ end
+ --
+ local name = gk.name
+ --
+ if features then
+ -- scripts, tag, ismac
+ local f = { }
+ for i=1,#features do
+ local df = features[i]
+ local tag = strip(lower(df.tag))
+ local ft = f[tag] if not ft then ft = {} f[tag] = ft end
+ local dscripts = df.scripts
+ for i=1,#dscripts do
+ local d = dscripts[i]
+ local languages = d.langs
+ local script = strip(lower(d.script))
+ local fts = ft[script] if not fts then fts = {} ft[script] = fts end
+ for i=1,#languages do
+ fts[strip(lower(languages[i]))] = true
+ end
end
end
+ sequences[#sequences+1] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ name = name,
+ subtables = subtables,
+ markclass = markclass,
+ features = f,
+ }
+ else
+ lookups[name] = {
+ type = typ,
+ chain = chain,
+ flags = flags,
+ subtables = subtables,
+ markclass = markclass,
+ }
end
- sequences[#sequences+1] = {
- type = typ,
- chain = chain,
- flags = flags,
- name = name,
- subtables = subtables,
- markclass = markclass,
- features = f,
- }
- else
- lookups[name] = {
- type = typ,
- chain = chain,
- flags = flags,
- subtables = subtables,
- markclass = markclass,
- }
end
end
end
@@ -5847,19 +6482,20 @@ end
local function t_hashed(t,cache)
if t then
- local h = { }
+ local ht = { }
for i=1,#t do
local ti = t[i]
- local h = cache[ti]
- if not h then
- h = { }
+ local tih = cache[ti]
+ if not tih then
+ tih = { }
for i=1,#ti do
- h[ti] = true
+ tih[ti[i]] = true
end
+ cache[ti] = tih
end
- cache[ti] = h
+ ht[i] = tih
end
- return h
+ return ht
else
return nil
end
@@ -5943,7 +6579,7 @@ actions["reorganize lookups"] = function(data,filename,raw)
for i=1,#current do
current[i] = current_class[current[i]] or { }
if lookups and not lookups[i] then
- lookups[i] = false
+ lookups[i] = false -- e.g. we can have two lookups and one replacement
end
end
rule.current = t_hashed(current,h_cache)
@@ -6040,8 +6676,6 @@ actions["reorganize lookups"] = function(data,filename,raw)
end
end
--- to be checked italic_correction
-
local function check_variants(unicode,the_variants,splitter,unicodes)
local variants = the_variants.variants
if variants then -- use splitter
@@ -6441,9 +7075,9 @@ local function copytotfm(data,cache_id)
if data then
local metadata = data.metadata
local resources = data.resources
- local properties = table.derive(data.properties)
- local descriptions = table.derive(data.descriptions)
- local goodies = table.derive(data.goodies)
+ local properties = derivetable(data.properties)
+ local descriptions = derivetable(data.descriptions)
+ local goodies = derivetable(data.goodies)
local characters = { }
local parameters = { }
local mathparameters = { }
@@ -6569,6 +7203,11 @@ local function copytotfm(data,cache_id)
local fullname = metadata.fullname or fontname
local units = metadata.units_per_em or 1000
--
+ if units == 0 then -- catch bugs in fonts
+ units = 1000
+ metadata.units_per_em = 1000
+ end
+ --
parameters.slant = 0
parameters.space = spaceunits -- 3.333 (cmr10)
parameters.space_stretch = units/2 -- 500 -- 1.666 (cmr10)
@@ -6654,9 +7293,9 @@ local function otftotfm(specification)
tfmdata.shared = shared
end
shared.rawdata = rawdata
- shared.features = features -- default
+ -- shared.features = features -- default
shared.dynamics = { }
- shared.processes = { }
+ -- shared.processes = { }
tfmdata.changed = { }
shared.features = features
shared.processes = otf.setfeatures(tfmdata,features)
@@ -6675,7 +7314,8 @@ local function read_from_otf(specification)
tfmdata.properties.sub = specification.sub
--
tfmdata = constructors.scale(tfmdata,specification)
- constructors.applymanipulators("otf",tfmdata,specification.features.normal,trace_features,report_otf)
+ local allfeatures = tfmdata.shared.features or specification.features.normal
+ constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
constructors.setname(tfmdata,specification) -- only otf?
fonts.loggers.register(tfmdata,file.extname(specification.filename),specification)
end
@@ -6741,15 +7381,15 @@ local function check_otf(forced,specification,suffix,what)
if forced then
name = file.addsuffix(name,suffix,true)
end
- local fullname, tfmdata = findbinfile(name,suffix) or "", nil -- one shot
+ local fullname = findbinfile(name,suffix) or ""
if fullname == "" then
- fullname = fonts.names.getfilename(name,suffix)
+ fullname = fonts.names.getfilename(name,suffix) or ""
end
if fullname ~= "" then
- specification.filename, specification.format = fullname, what -- hm, so we do set the filename, then
- tfmdata = read_from_otf(specification) -- we need to do it for all matches / todo
+ specification.filename = fullname
+ specification.format = what
+ return read_from_otf(specification)
end
- return tfmdata
end
local function opentypereader(specification,suffix,what)
@@ -6817,6 +7457,8 @@ local otf = fonts.handlers.otf
local otffeatures = fonts.constructors.newfeatures("otf")
local registerotffeature = otffeatures.register
+otf.defaultbasealternate = "none" -- first last
+
local wildcard = "*"
local default = "dflt"
@@ -6849,6 +7491,22 @@ local function cref(feature,lookupname)
end
end
+local function report_alternate(feature,lookupname,descriptions,unicode,replacement,value,comment)
+ report_prepare("%s: base alternate %s => %s (%s => %s)",cref(feature,lookupname),
+ gref(descriptions,unicode),replacement and gref(descriptions,replacement) or "-",
+ tostring(value),comment)
+end
+
+local function report_substitution(feature,lookupname,descriptions,unicode,substitution)
+ report_prepare("%s: base substitution %s => %s",cref(feature,lookupname),
+ gref(descriptions,unicode),gref(descriptions,substitution))
+end
+
+local function report_ligature(feature,lookupname,descriptions,unicode,ligature)
+ report_prepare("%s: base ligature %s => %s",cref(feature,lookupname),
+ gref(descriptions,ligature),gref(descriptions,unicode))
+end
+
local basemethods = { }
local basemethod = "<unset>"
@@ -7013,27 +7671,47 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local lookuptypes = resources.lookuptypes
local ligatures = { }
+ local alternate = tonumber(value)
+ local defaultalt = otf.defaultbasealternate
+
+ local trace_singles = trace_baseinit and trace_singles
+ local trace_alternatives = trace_baseinit and trace_alternatives
+ local trace_ligatures = trace_baseinit and trace_ligatures
local actions = {
substitution = function(lookupdata,lookupname,description,unicode)
- if trace_baseinit and trace_singles then
- report_prepare("%s: base substitution %s => %s",cref(feature,lookupname),
- gref(descriptions,unicode),gref(descriptions,replacement))
+ if trace_singles then
+ report_substitution(feature,lookupname,descriptions,unicode,lookupdata)
end
changed[unicode] = lookupdata
end,
alternate = function(lookupdata,lookupname,description,unicode)
- local replacement = lookupdata[value] or lookupdata[#lookupdata]
- if trace_baseinit and trace_alternatives then
- report_prepare("%s: base alternate %s %s => %s",cref(feature,lookupname),
- tostring(value),gref(descriptions,unicode),gref(descriptions,replacement))
+ local replacement = lookupdata[alternate]
+ if replacement then
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
+ end
+ elseif defaultalt == "first" then
+ replacement = lookupdata[1]
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ elseif defaultalt == "last" then
+ replacement = lookupdata[#data]
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ else
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
+ end
end
- changed[unicode] = replacement
end,
ligature = function(lookupdata,lookupname,description,unicode)
- if trace_baseinit and trace_alternatives then
- report_prepare("%s: base ligature %s %s => %s",cref(feature,lookupname),
- tostring(value),gref(descriptions,lookupdata),gref(descriptions,unicode))
+ if trace_ligatures then
+ report_ligature(feature,lookupname,descriptions,unicode,lookupdata)
end
ligatures[#ligatures+1] = { unicode, lookupdata }
end,
@@ -7199,6 +7877,12 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local lookuptypes = resources.lookuptypes
local ligatures = { }
+ local alternate = tonumber(value)
+ local defaultalt = otf.defaultbasealternate
+
+ local trace_singles = trace_baseinit and trace_singles
+ local trace_alternatives = trace_baseinit and trace_alternatives
+ local trace_ligatures = trace_baseinit and trace_ligatures
for l=1,#lookuplist do
local lookupname = lookuplist[l]
@@ -7206,20 +7890,38 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
local lookuptype = lookuptypes[lookupname]
for unicode, data in next, lookupdata do
if lookuptype == "substitution" then
- if trace_baseinit and trace_singles then
- report_prepare("%s: base substitution %s => %s",cref(feature,lookupname),
- gref(descriptions,unicode),gref(descriptions,data))
+ if trace_singles then
+ report_substitution(feature,lookupname,descriptions,unicode,data)
end
changed[unicode] = data
elseif lookuptype == "alternate" then
- local replacement = data[value] or data[#data]
- if trace_baseinit and trace_alternatives then
- report_prepare("%s: base alternate %s %s => %s",cref(feature,lookupname),
- tostring(value),gref(descriptions,unicode),gref(descriptions,replacement))
+ local replacement = data[alternate]
+ if replacement then
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"normal")
+ end
+ elseif defaultalt == "first" then
+ replacement = data[1]
+ changed[unicode] = replacement
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ elseif defaultalt == "last" then
+ replacement = data[#data]
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,defaultalt)
+ end
+ else
+ if trace_alternatives then
+ report_alternate(feature,lookupname,descriptions,unicode,replacement,value,"unknown")
+ end
end
- changed[unicode] = replacement
elseif lookuptype == "ligature" then
ligatures[#ligatures+1] = { unicode, data, lookupname }
+ if trace_ligatures then
+ report_ligature(feature,lookupname,descriptions,unicode,data)
+ end
end
end
end
@@ -7244,13 +7946,6 @@ local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplis
make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,lookupname)
end
- if done then
- for lookupname, list in next, done do
- report_prepare("%s: base ligatures %s => %s",cref(feature,lookupname),
- tostring(value),gref(descriptions,done))
- end
- end
-
end
end
@@ -7356,13 +8051,13 @@ registerotffeature {
description = "features",
default = true,
initializers = {
---~ position = 1, -- after setscript (temp hack ... we need to force script / language to 1
+ -- position = 1, -- after setscript (temp hack ... we need to force script / language to 1
base = featuresinitializer,
}
}
-- independent : collect lookups independently (takes more runtime ... neglectable)
--- shared : shares lookups with node mode (takes more memory ... noticeable)
+-- shared : shares lookups with node mode (takes more memory unless also a node mode variant is used ... noticeable)
directives.register("fonts.otf.loader.basemethod", function(v)
if basemethods[v] then
@@ -7410,6 +8105,7 @@ local traverse_id = node.traverse_id
local unset_attribute = node.unset_attribute
local has_attribute = node.has_attribute
local set_attribute = node.set_attribute
+local copy_node = node.copy
local insert_node_before = node.insert_before
local insert_node_after = node.insert_after
@@ -7420,17 +8116,38 @@ local cursbase = attributes.private('cursbase')
local curscurs = attributes.private('curscurs')
local cursdone = attributes.private('cursdone')
local kernpair = attributes.private('kernpair')
+local ligacomp = attributes.private('ligacomp')
+local fontkern = attributes.private('fontkern')
+
+if context then
+
+ local kern = nodes.pool.register(newkern())
+
+ set_attribute(kern,fontkern,1) -- we can have several, attributes are shared
+
+ newkern = function(k)
+ local c = copy_node(kern)
+ c.kern = k
+ return c
+ end
+
+end
+
+-- This injector has been tested by Idris Samawi Hamid (several arabic fonts as well as
+-- the rather demanding Husayni font), Khaled Hosny (latin and arabic) and Kaj Eigner
+-- (arabic, hebrew and thai) and myself (whatever font I come across). I'm pretty sure
+-- that this code is not 100% okay but examples are needed to figure things out.
local cursives = { }
local marks = { }
local kerns = { }
--- currently we do gpos/kern in a bit inofficial way but when we
--- have the extra fields in glyphnodes to manipulate ht/dp/wd
--- explicitly i will provide an alternative; also, we can share
--- tables
+-- Currently we do gpos/kern in a bit inofficial way but when we have the extra fields in
+-- glyphnodes to manipulate ht/dp/wd explicitly I will provide an alternative; also, we
+-- can share tables.
--- for the moment we pass the r2l key ... volt/arabtype tests
+-- For the moment we pass the r2l key ... volt/arabtype tests .. idris: this needs
+-- checking with husayni (volt and fontforge).
function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
local dx, dy = factor*(exit[1]-entry[1]), factor*(exit[2]-entry[2])
@@ -7473,14 +8190,16 @@ function injections.setkern(current,factor,rlmode,x,tfmchr)
end
end
-function injections.setmark(start,base,factor,rlmode,ba,ma,index) --ba=baseanchor, ma=markanchor
- local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2])
- local bound = has_attribute(base,markbase)
+function injections.setmark(start,base,factor,rlmode,ba,ma,index) -- ba=baseanchor, ma=markanchor
+ local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2]) -- the index argument is no longer used but when this
+ local bound = has_attribute(base,markbase) -- fails again we should pass it
+local index = 1
if bound then
local mb = marks[bound]
if mb then
- if not index then index = #mb + 1 end
- mb[index] = { dx, dy }
+ -- if not index then index = #mb + 1 end
+index = #mb + 1
+ mb[index] = { dx, dy, rlmode }
set_attribute(start,markmark,bound)
set_attribute(start,markdone,index)
return dx, dy, bound
@@ -7488,6 +8207,7 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,index) --ba=baseancho
report_injections("possible problem, U+%05X is base mark without data (id: %s)",base.char,bound)
end
end
+-- index = index or 1
index = index or 1
bound = #marks + 1
set_attribute(base,markbase,bound)
@@ -7534,7 +8254,7 @@ local function trace(head)
end
else
m = m[1]
- report_injections(" markmark: bound=%s, dx=%s, dy=%s",mm,m[1] or "?",m[2] or "?")
+ report_injections(" markmark: bound=%s, dx=%s, dy=%s",mm,m and m[1] or "?",m and m[2] or "?")
end
end
if cb then
@@ -7552,7 +8272,8 @@ end
-- todo: reuse tables (i.e. no collection), but will be extra fields anyway
-- todo: check for attribute
--- we can have a fast test on a font being processed, so we can check faster for marks etc
+-- We can have a fast test on a font being processed, so we can check faster for marks etc
+-- but I'll make a context variant anyway.
function injections.handler(head,where,keep)
local has_marks, has_cursives, has_kerns = next(marks), next(cursives), next(kerns)
@@ -7690,6 +8411,7 @@ function injections.handler(head,where,keep)
local p_markbase = has_attribute(p,markbase)
if p_markbase then
local mrks = marks[p_markbase]
+ local nofmarks = #mrks
for n in traverse_id(glyph_code,p.next) do
local n_markmark = has_attribute(n,markmark)
if p_markbase == n_markmark then
@@ -7703,7 +8425,7 @@ function injections.handler(head,where,keep)
-- that makes sense but we no longer do that so as a
-- consequence the sign of p.width was changed (we need
-- to keep an eye on it as we don't have that many fonts
- -- that enter this branch .. i'm still not sure if this
+ -- that enter this branch .. I'm still not sure if this
-- one is right
local k = wx[p]
if k then
@@ -7726,9 +8448,14 @@ function injections.handler(head,where,keep)
else
n.yoffset = n.yoffset + p.yoffset + d[2]
end
+ if nofmarks == 1 then
+ break
+ else
+ nofmarks = nofmarks - 1
+ end
end
else
- break
+ -- KE: there can be <mark> <mkmk> <mark> sequences in ligatures
end
end
end
@@ -7740,23 +8467,32 @@ function injections.handler(head,where,keep)
-- todo : combine
if next(wx) then
for n, k in next, wx do
- -- only w can be nil, can be sped up when w == nil
- local rl, x, w, r2l = k[1], k[2] or 0, k[4] or 0, k[6]
- local wx = w - x
- if r2l then
- if wx ~= 0 then
- insert_node_before(head,n,newkern(wx))
- end
- if x ~= 0 then
- insert_node_after (head,n,newkern(x))
- end
- else
- if x ~= 0 then
- insert_node_before(head,n,newkern(x))
- end
- if wx ~= 0 then
- insert_node_after(head,n,newkern(wx))
+ -- only w can be nil (kernclasses), can be sped up when w == nil
+ local x, w = k[2] or 0, k[4]
+ if w then
+ local rl = k[1] -- r2l = k[6]
+ local wx = w - x
+ if rl < 0 then -- KE: don't use r2l here
+ if wx ~= 0 then
+ insert_node_before(head,n,newkern(wx))
+ end
+ if x ~= 0 then
+ insert_node_after (head,n,newkern(x))
+ end
+ else
+ if x ~= 0 then
+ insert_node_before(head,n,newkern(x))
+ end
+ if wx ~= 0 then
+ insert_node_after(head,n,newkern(wx))
+ end
end
+ elseif x ~= 0 then
+ -- this needs checking for rl < 0 but it is unlikely that a r2l script
+ -- uses kernclasses between glyphs so we're probably safe (KE has a
+ -- problematic font where marks interfere with rl < 0 in the previous
+ -- case)
+ insert_node_before(head,n,newkern(x))
end
end
end
@@ -7795,9 +8531,9 @@ function injections.handler(head,where,keep)
end
if w then
-- copied from above
- local r2l = kk[6]
+ -- local r2l = kk[6]
local wx = w - x
- if r2l then
+ if rl < 0 then -- KE: don't use r2l here
if wx ~= 0 then
insert_node_before(head,n,newkern(wx))
end
@@ -7865,6 +8601,7 @@ if not modules then modules = { } end modules ['font-otn'] = {
-- default features (per language, script)
-- handle positions (we need example fonts)
-- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere)
+-- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests)
--[[ldx--
<p>This module is a bit more split up that I'd like but since we also want to test
@@ -7961,25 +8698,27 @@ local random = math.random
local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes
+local registertracker = trackers.register
+
local fonts = fonts
local otf = fonts.handlers.otf
-local trace_lookups = false trackers.register("otf.lookups", function(v) trace_lookups = v end)
-local trace_singles = false trackers.register("otf.singles", function(v) trace_singles = v end)
-local trace_multiples = false trackers.register("otf.multiples", function(v) trace_multiples = v end)
-local trace_alternatives = false trackers.register("otf.alternatives", function(v) trace_alternatives = v end)
-local trace_ligatures = false trackers.register("otf.ligatures", function(v) trace_ligatures = v end)
-local trace_contexts = false trackers.register("otf.contexts", function(v) trace_contexts = v end)
-local trace_marks = false trackers.register("otf.marks", function(v) trace_marks = v end)
-local trace_kerns = false trackers.register("otf.kerns", function(v) trace_kerns = v end)
-local trace_cursive = false trackers.register("otf.cursive", function(v) trace_cursive = v end)
-local trace_preparing = false trackers.register("otf.preparing", function(v) trace_preparing = v end)
-local trace_bugs = false trackers.register("otf.bugs", function(v) trace_bugs = v end)
-local trace_details = false trackers.register("otf.details", function(v) trace_details = v end)
-local trace_applied = false trackers.register("otf.applied", function(v) trace_applied = v end)
-local trace_steps = false trackers.register("otf.steps", function(v) trace_steps = v end)
-local trace_skips = false trackers.register("otf.skips", function(v) trace_skips = v end)
-local trace_directions = false trackers.register("otf.directions", function(v) trace_directions = v end)
+local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end)
+local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end)
+local trace_multiples = false registertracker("otf.multiples", function(v) trace_multiples = v end)
+local trace_alternatives = false registertracker("otf.alternatives", function(v) trace_alternatives = v end)
+local trace_ligatures = false registertracker("otf.ligatures", function(v) trace_ligatures = v end)
+local trace_contexts = false registertracker("otf.contexts", function(v) trace_contexts = v end)
+local trace_marks = false registertracker("otf.marks", function(v) trace_marks = v end)
+local trace_kerns = false registertracker("otf.kerns", function(v) trace_kerns = v end)
+local trace_cursive = false registertracker("otf.cursive", function(v) trace_cursive = v end)
+local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end)
+local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end)
+local trace_details = false registertracker("otf.details", function(v) trace_details = v end)
+local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end)
+local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end)
+local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end)
+local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end)
local report_direct = logs.reporter("fonts","otf direct")
local report_subchain = logs.reporter("fonts","otf subchain")
@@ -7987,15 +8726,15 @@ local report_chain = logs.reporter("fonts","otf chain")
local report_process = logs.reporter("fonts","otf process")
local report_prepare = logs.reporter("fonts","otf prepare")
-trackers.register("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
-trackers.register("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
+registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end)
+registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end)
-trackers.register("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
-trackers.register("otf.positions","otf.marks,otf.kerns,otf.cursive")
-trackers.register("otf.actions","otf.replacements,otf.positions")
-trackers.register("otf.injections","nodes.injections")
+registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
+registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
+registertracker("otf.actions","otf.replacements,otf.positions")
+registertracker("otf.injections","nodes.injections")
-trackers.register("*otf.sample","otf.steps,otf.actions,otf.analyzing")
+registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
local insert_node_after = node.insert_after
local delete_node = nodes.delete
@@ -8003,6 +8742,7 @@ local copy_node = node.copy
local find_node_tail = node.tail or node.slide
local set_attribute = node.set_attribute
local has_attribute = node.has_attribute
+local flush_node_list = node.flush_list
local setmetatableindex = table.setmetatableindex
@@ -8027,14 +8767,21 @@ local ligature_code = glyphcodes.ligature
local privateattribute = attributes.private
+-- Something is messed up: we have two mark / ligature indices, one at the injection
+-- end and one here ... this is bases in KE's patches but there is something fishy
+-- there as I'm pretty sure that for husayni we need some connection (as it's much
+-- more complex than an average font) but I need proper examples of all cases, not
+-- of only some.
+
local state = privateattribute('state')
local markbase = privateattribute('markbase')
local markmark = privateattribute('markmark')
-local markdone = privateattribute('markdone')
+local markdone = privateattribute('markdone') -- assigned at the injection end
local cursbase = privateattribute('cursbase')
local curscurs = privateattribute('curscurs')
local cursdone = privateattribute('cursdone')
local kernpair = privateattribute('kernpair')
+local ligacomp = privateattribute('ligacomp') -- assigned here (ideally it should be combined)
local injections = nodes.injections
local setmark = injections.setmark
@@ -8054,6 +8801,8 @@ local registerotffeature = otffeatures.register
local onetimemessage = fonts.loggers.onetimemessage
+otf.defaultnodealternate = "none" -- first last
+
-- we share some vars here, after all, we have no nested lookups and
-- less code
@@ -8156,21 +8905,35 @@ end
local function toligature(kind,lookupname,start,stop,char,markflag,discfound) -- brr head
if start == stop then
start.char = char
+ return start
elseif discfound then
-- print("start->stop",nodes.tosequence(start,stop))
+ local components = start.components
+ if components then
+ flush_node_list(components)
+ start.components = nil
+ end
local lignode = copy_node(start)
- lignode.font, lignode.char, lignode.subtype = start.font, char, ligature_code
- local next, prev = stop.next, start.prev
+ lignode.font = start.font
+ lignode.char = char
+ lignode.subtype = ligature_code
+ local next = stop.next
+ local prev = start.prev
stop.next = nil
- lignode = node.do_ligature_n(start, stop, lignode)
+ start.prev = nil
+ lignode.components = start
+ -- print("lignode",nodes.tosequence(lignode))
+ -- print("components",nodes.tosequence(lignode.components))
prev.next = lignode
if next then
next.prev = lignode
end
- lignode.next, lignode.prev = next, prev
- start = lignode
+ lignode.next = next
+ lignode.prev = prev
-- print("start->end",nodes.tosequence(start))
- else -- start is the ligature
+ return lignode
+ else
+ -- start is the ligature
local deletemarks = markflag ~= "mark"
local n = copy_node(start)
local current
@@ -8180,48 +8943,46 @@ local function toligature(kind,lookupname,start,stop,char,markflag,discfound) --
if snext then
snext.prev = current
end
- start.prev, stop.next = nil, nil
- current.char, current.subtype, current.components = char, ligature_code, start
+ start.prev = nil
+ stop.next = nil
+ current.char = char
+ current.subtype = ligature_code
+ current.components = start
local head = current
- if deletemarks then
- if trace_marks then
- while start do
- if marks[start.char] then
- logwarning("%s: remove mark %s",pref(kind,lookupname),gref(start.char))
- end
- start = start.next
- end
- end
- else
- local i = 0
- while start do
- if marks[start.char] then
- set_attribute(start,markdone,i)
- if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
- end
- head, current = insert_node_after(head,current,copy_node(start))
- else
- i = i + 1
+ -- this is messy ... we should get rid of the components eventually
+ local i = 0 -- is index of base
+ while start do
+ if not marks[start.char] then
+ i = i + 1
+ elseif not deletemarks then -- quite fishy
+ set_attribute(start,ligacomp,i)
+ if trace_marks then
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
+ end
+ head, current = insert_node_after(head,current,copy_node(start))
+ end
+ start = start.next
+ end
+ start = current.next
+ while start and start.id == glyph_code do
+ if marks[start.char] then
+ set_attribute(start,ligacomp,i)
+ if trace_marks then
+ logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
end
- start = start.next
- end
- start = current.next
- while start and start.id == glyph_code do
- if marks[start.char] then
- set_attribute(start,markdone,i)
- if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(start.char),i)
- end
- else
- break
- end
- start = start.next
+ else
+ break
end
+ start = start.next
end
+ --
+ -- we do need components in funny kerning mode but maybe I can better reconstruct then
+ -- as we do have the font components info available; removing components makes the
+ -- previous code much simpler
+ --
+ -- flush_node_list(head.components)
return head
end
- return start
end
function handlers.gsub_single(start,kind,lookupname,replacement)
@@ -8232,8 +8993,12 @@ function handlers.gsub_single(start,kind,lookupname,replacement)
return start, true
end
-local function alternative_glyph(start,alternatives,kind,chainname,chainlookupname,lookupname) -- chainname and chainlookupname optional
- local value, choice, n = featurevalue or tfmdata.shared.features[kind], nil, #alternatives -- global value, brrr
+local function get_alternative_glyph(start,alternatives,value)
+ -- needs checking: (global value, brrr)
+ local choice = nil
+ local n = #alternatives
+ local char = start.char
+ --
if value == "random" then
local r = random(1,n)
value, choice = format("random, choice %s",r), alternatives[r]
@@ -8246,23 +9011,26 @@ local function alternative_glyph(start,alternatives,kind,chainname,chainlookupna
if type(value) ~= "number" then
value, choice = "default, choice 1", alternatives[1]
elseif value > n then
- value, choice = format("no %s variants, taking %s",value,n), alternatives[n]
+ local defaultalt = otf.defaultnodealternate
+ if defaultalt == "first" then
+ value, choice = format("no %s variants, taking %s",value,n), alternatives[n]
+ elseif defaultalt == "last" then
+ value, choice = format("no %s variants, taking %s",value,1), alternatives[1]
+ else
+ value, choice = format("no %s variants, ignoring",value), false
+ end
elseif value == 0 then
- value, choice = format("choice %s (no change)",value), start.char
+ value, choice = format("choice %s (no change)",value), char
elseif value < 1 then
value, choice = format("no %s variants, taking %s",value,1), alternatives[1]
else
value, choice = format("choice %s",value), alternatives[value]
end
end
- if not choice then
- logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(start.char))
- choice, value = start.char, format("no replacement instead of %s",value)
- end
- return choice, value
+ return choice
end
-local function multiple_glyphs(start,multiple)
+local function multiple_glyphs(start,multiple) -- marks ?
local nofmultiples = #multiple
if nofmultiples > 0 then
start.char = multiple[1]
@@ -8290,11 +9058,18 @@ local function multiple_glyphs(start,multiple)
end
function handlers.gsub_alternate(start,kind,lookupname,alternative,sequence)
- local choice, index = alternative_glyph(start,alternative,kind,lookupname)
- if trace_alternatives then
- logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(start.char),gref(choice),index)
+ local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
+ local choice = get_alternative_glyph(start,alternative,value)
+ if choice then
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %s (%s)",pref(kind,lookupname),gref(char),gref(choice),choice)
+ end
+ start.char = choice
+ else
+ if trace_alternatives then
+ logwarning("%s: no variant %s for %s",pref(kind,lookupname),tostring(value),gref(char))
+ end
end
- start.char = choice
return start, true
end
@@ -8457,18 +9232,14 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
local markchar = start.char
if marks[markchar] then
local base = start.prev -- [glyph] [optional marks] [start=mark]
- local index = 1
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
local basechar = base.char
if marks[basechar] then
- index = index + 1
while true do
base = base.prev
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
basechar = base.char
- if marks[basechar] then
- index = index + 1
- else
+ if not marks[basechar] then
break
end
else
@@ -8479,8 +9250,7 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
end
end
end
- local i = has_attribute(start,markdone)
- if i then index = i end
+ local index = has_attribute(start,ligacomp)
local baseanchors = descriptions[basechar]
if baseanchors then
baseanchors = baseanchors.anchors
@@ -8494,7 +9264,7 @@ function handlers.gpos_mark2ligature(start,kind,lookupname,markanchors,sequence)
if ma then
ba = ba[index]
if ba then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,index)
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma) -- index
if trace_marks then
logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)",
pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -8525,46 +9295,55 @@ end
function handlers.gpos_mark2mark(start,kind,lookupname,markanchors,sequence)
local markchar = start.char
if marks[markchar] then
---~ local alreadydone = markonce and has_attribute(start,markmark)
---~ if not alreadydone then
- local base = start.prev -- [glyph] [basemark] [start=mark]
- if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then -- subtype test can go
- local basechar = base.char
- local baseanchors = descriptions[basechar]
+ local base = start.prev -- [glyph] [basemark] [start=mark]
+ -- while base and has_attribute(base,ligacomp) and has_attribute(base,ligacomp) ~= has_attribute(start,ligacomp) do
+ -- base = base.prev -- KE: prevents mkmk for marks on different components of a ligature
+ -- end
+ local slc = has_attribute(start,ligacomp)
+ if slc then -- a rather messy loop ... needs checking with husayni
+ while base do
+ local blc = has_attribute(base,ligacomp)
+ if blc and blc ~= slc then
+ base = base.prev
+ else
+ break
+ end
+ end
+ end
+ if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then -- subtype test can go
+ local basechar = base.char
+ local baseanchors = descriptions[basechar]
+ if baseanchors then
+ baseanchors = baseanchors.anchors
if baseanchors then
- baseanchors = baseanchors.anchors
+ baseanchors = baseanchors['basemark']
if baseanchors then
- baseanchors = baseanchors['basemark']
- if baseanchors then
- local al = anchorlookups[lookupname]
- for anchor,ba in next, baseanchors do
- if al[anchor] then
- local ma = markanchors[anchor]
- if ma then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)",
- pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return start,true
+ local al = anchorlookups[lookupname]
+ for anchor,ba in next, baseanchors do
+ if al[anchor] then
+ local ma = markanchors[anchor]
+ if ma then
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma)
+ if trace_marks then
+ logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%s,%s)",
+ pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy)
end
+ return start,true
end
end
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar))
- end
+ end
+ if trace_bugs then
+ logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar))
end
end
- else -- if trace_bugs then
- -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
- onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
end
- elseif trace_bugs then
- logwarning("%s: prev node is no mark",pref(kind,lookupname))
+ else -- if trace_bugs then
+ -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar))
+ onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
end
---~ elseif trace_marks and trace_details then
---~ logprocess("%s, mark %s is already bound (n=%s), ignoring mark2mark",pref(kind,lookupname),gref(markchar),alreadydone)
---~ end
+ elseif trace_bugs then
+ logwarning("%s: prev node is no mark",pref(kind,lookupname))
+ end
elseif trace_bugs then
logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar))
end
@@ -8718,33 +9497,6 @@ end
local logwarning = report_subchain
-function chainmores.chainsub(start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
- logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
- return start, false
-end
-
--- handled later:
---
--- function chainmores.gsub_single(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
--- return chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
--- end
-
-function chainmores.gsub_multiple(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
- logprocess("%s: gsub_multiple not yet supported",cref(kind,chainname,chainlookupname))
- return start, false
-end
-
-function chainmores.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
- logprocess("%s: gsub_alternate not yet supported",cref(kind,chainname,chainlookupname))
- return start, false
-end
-
--- handled later:
---
--- function chainmores.gsub_ligature(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
--- return chainprocs.gsub_ligature(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
--- end
-
local function logprocess(...)
if trace_steps then
registermessage(...)
@@ -8762,6 +9514,11 @@ function chainprocs.chainsub(start,stop,kind,chainname,currentcontext,lookuphash
return start, false
end
+function chainmores.chainsub(start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n)
+ logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname))
+ return start, false
+end
+
-- The reversesub is a special case, which is why we need to store the replacements
-- in a bit weird way. There is no lookup and the replacement comes from the lookup
-- itself. It is meant mostly for dealing with Urdu.
@@ -8793,17 +9550,29 @@ example, the following is valid:</p>
<p>Therefore we we don't really do the replacement here already unless we have the
single lookup case. The efficiency of the replacements can be improved by deleting
-as less as needed but that would also mke the code even more messy.</p>
+as less as needed but that would also make the code even more messy.</p>
--ldx]]--
-local function delete_till_stop(start,stop,ignoremarks)
- if start ~= stop then
- -- todo keep marks
+local function delete_till_stop(start,stop,ignoremarks) -- keeps start
+ local n = 1
+ if start == stop then
+ -- done
+ elseif ignoremarks then
+ repeat -- start x x m x x stop => start m
+ local next = start.next
+ if not marks[next.char] then
+ delete_node(start,next)
+ end
+ n = n + 1
+ until next == stop
+ else -- start x x x stop => start
repeat
local next = start.next
delete_node(start,next)
+ n = n + 1
until next == stop
end
+ return n
end
--[[ldx--
@@ -8813,10 +9582,6 @@ match.</p>
function chainprocs.gsub_single(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
-- todo: marks ?
---~ if not chainindex then
---~ delete_till_stop(start,stop) -- ,currentlookup.flags[1]
---~ stop = start
---~ end
local current = start
local subtables = currentlookup.subtables
if #subtables > 1 then
@@ -8862,7 +9627,7 @@ the match.</p>
--ldx]]--
function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- delete_till_stop(start,stop)
+ delete_till_stop(start,stop) -- we could pass ignoremarks as #3 ..
local startchar = start.char
local subtables = currentlookup.subtables
local lookupname = subtables[1]
@@ -8887,36 +9652,54 @@ function chainprocs.gsub_multiple(start,stop,kind,chainname,currentcontext,looku
return start, false
end
+-- function chainmores.gsub_multiple(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
+-- logprocess("%s: gsub_multiple not yet supported",cref(kind,chainname,chainlookupname))
+-- return start, false
+-- end
+
+chainmores.gsub_multiple = chainprocs.gsub_multiple
+
--[[ldx--
<p>Here we replace start by new glyph. First we delete the rest of the match.</p>
--ldx]]--
+-- char_1 mark_1 -> char_x mark_1 (ignore marks)
+-- char_1 mark_1 -> char_x
+
+-- to be checked: do we always have just one glyph?
+-- we can also have alternates for marks
+-- marks come last anyway
+-- are there cases where we need to delete the mark
+
function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
- -- todo: marks ?
- delete_till_stop(start,stop)
local current = start
local subtables = currentlookup.subtables
+ local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue
while current do
- if current.id == glyph_code then
+ if current.id == glyph_code then -- is this check needed?
local currentchar = current.char
local lookupname = subtables[1]
local alternatives = lookuphash[lookupname]
if not alternatives then
if trace_bugs then
- logwarning("%s: no alternative hits",cref(kind,chainname,chainlookupname,lookupname))
+ logwarning("%s: no alternative hit",cref(kind,chainname,chainlookupname,lookupname))
end
else
alternatives = alternatives[currentchar]
- if not alternatives then
- if trace_bugs then
- logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar))
- end
- else
- local choice, index = alternative_glyph(current,alternatives,kind,chainname,chainlookupname,lookupname)
- current.char = choice
- if trace_alternatives then
- logprocess("%s: replacing single %s by alternative %s (%s)",cref(kind,chainname,chainlookupname,lookupname),index,gref(currentchar),gref(choice),index)
+ if alternatives then
+ local choice = get_alternative_glyph(current,alternatives,value)
+ if choice then
+ if trace_alternatives then
+ logprocess("%s: replacing %s by alternative %s (%s)",cref(kind,chainname,chainlookupname,lookupname),gref(char),gref(choice),choice)
+ end
+ start.char = choice
+ else
+ if trace_alternatives then
+ logwarning("%s: no variant %s for %s",cref(kind,chainname,chainlookupname,lookupname),tostring(value),gref(char))
+ end
end
+ elseif trace_bugs then
+ logwarning("%s: no alternative for %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar))
end
end
return start, true
@@ -8929,6 +9712,13 @@ function chainprocs.gsub_alternate(start,stop,kind,chainname,currentcontext,look
return start, false
end
+-- function chainmores.gsub_alternate(start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,n)
+-- logprocess("%s: gsub_alternate not yet supported",cref(kind,chainname,chainlookupname))
+-- return start, false
+-- end
+
+chainmores.gsub_alternate = chainprocs.gsub_alternate
+
--[[ldx--
<p>When we replace ligatures we use a helper that handles the marks. I might change
this function (move code inline and handle the marks by a separate function). We
@@ -9079,18 +9869,14 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,
end
if markanchors then
local base = start.prev -- [glyph] [optional marks] [start=mark]
- local index = 1
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
local basechar = base.char
if marks[basechar] then
- index = index + 1
while true do
base = base.prev
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then
basechar = base.char
- if marks[basechar] then
- index = index + 1
- else
+ if not marks[basechar] then
break
end
else
@@ -9102,8 +9888,7 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,
end
end
-- todo: like marks a ligatures hash
- local i = has_attribute(start,markdone)
- if i then index = i end
+ local index = has_attribute(start,ligacomp)
local baseanchors = descriptions[basechar].anchors
if baseanchors then
local baseanchors = baseanchors['baselig']
@@ -9115,7 +9900,7 @@ function chainprocs.gpos_mark2ligature(start,stop,kind,chainname,currentcontext,
if ma then
ba = ba[index]
if ba then
- local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,index)
+ local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma) -- index
if trace_marks then
logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%s,%s)",
cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
@@ -9156,6 +9941,20 @@ function chainprocs.gpos_mark2mark(start,stop,kind,chainname,currentcontext,look
end
if markanchors then
local base = start.prev -- [glyph] [basemark] [start=mark]
+ -- while (base and has_attribute(base,ligacomp) and has_attribute(base,ligacomp) ~= has_attribute(start,ligacomp)) do
+ -- base = base.prev -- KE: prevents mkmk for marks on different components of a ligature
+ -- end
+ local slc = has_attribute(start,ligacomp)
+ if slc then -- a rather messy loop ... needs checking with husayni
+ while base do
+ local blc = has_attribute(base,ligacomp)
+ if blc and blc ~= slc then
+ base = base.prev
+ else
+ break
+ end
+ end
+ end
if base and base.id == glyph_code and base.subtype<256 and base.font == currentfont then -- subtype test can go
local basechar = base.char
local baseanchors = descriptions[basechar].anchors
@@ -9372,36 +10171,40 @@ end
local function normal_handle_contextchain(start,kind,chainname,contexts,sequence,lookuphash)
-- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6]
- local flags, done = sequence.flags, false
- local skipmark, skipligature, skipbase = flags[1], flags[2], flags[3]
- local someskip = skipmark or skipligature or skipbase -- could be stored in flags for a fast test (hm, flags could be false !)
- local markclass = sequence.markclass -- todo, first we need a proper test
- local skipped = false
+ local flags = sequence.flags
+ local done = false
+ local skipmark = flags[1]
+ local skipligature = flags[2]
+ local skipbase = flags[3]
+ local someskip = skipmark or skipligature or skipbase -- could be stored in flags for a fast test (hm, flags could be false !)
+ local markclass = sequence.markclass -- todo, first we need a proper test
+ local skipped = false
for k=1,#contexts do
- local match, current, last = true, start, start
- local ck = contexts[k]
- local seq = ck[3]
- local s = #seq
+ local match = true
+ local current = start
+ local last = start
+ local ck = contexts[k]
+ local seq = ck[3]
+ local s = #seq
-- f..l = mid string
if s == 1 then
-- never happens
match = current.id == glyph_code and current.subtype<256 and current.font == currentfont and seq[1][current.char]
else
- -- todo: better space check (maybe check for glue)
+ -- maybe we need a better space check (maybe check for glue or category or combination)
+ -- we cannot optimize for n=2 because there can be disc nodes
local f, l = ck[4], ck[5]
-- current match
- if f == 1 and f == l then
+ if f == 1 and f == l then -- current only
-- already a hit
- match = true
- else
+ -- match = true
+ else -- before/current/after | before/current | current/after
-- no need to test first hit (to be optimized)
- local n = f + 1
- last = last.next
- -- we cannot optimize for n=2 because there can be disc nodes
- -- if not someskip and n == l then
- -- -- n=2 and no skips then faster loop
- -- match = last and last.id == glyph_code and last.subtype<256 and last.font == currentfont and seq[n][last.char]
- -- else
+ if f == l then -- new, else last out of sync (f is > 1)
+ -- match = true
+ else
+ local n = f + 1
+ last = last.next
while n <= l do
if last then
local id = last.id
@@ -9423,24 +10226,29 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
end
n = n + 1
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
- elseif id == disc_code then -- what to do with kerns?
+ elseif id == disc_code then
last = last.next
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
end
- -- end
+ end
end
-- before
if match and f > 1 then
@@ -9464,26 +10272,31 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
elseif seq[n][char] then
n = n -1
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
elseif id == disc_code then
-- skip 'm
elseif seq[n][32] then
n = n -1
else
- match = false break
+ match = false
+ break
end
prev = prev.prev
elseif seq[n][32] then -- somehat special, as zapfino can have many preceding spaces
n = n -1
else
- match = false break
+ match = false
+ break
end
end
elseif f == 2 then
@@ -9491,7 +10304,8 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
else
for n=f-1,1 do
if not seq[n][32] then
- match = false break
+ match = false
+ break
end
end
end
@@ -9519,26 +10333,31 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
elseif seq[n][char] then
n = n + 1
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
else
- match = false break
+ match = false
+ break
end
elseif id == disc_code then
-- skip 'm
elseif seq[n][32] then -- brrr
n = n + 1
else
- match = false break
+ match = false
+ break
end
current = current.next
elseif seq[n][32] then
n = n + 1
else
- match = false break
+ match = false
+ break
end
end
elseif s-l == 1 then
@@ -9546,7 +10365,8 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
else
for n=l+1,s do
if not seq[n][32] then
- match = false break
+ match = false
+ break
end
end
end
@@ -9572,11 +10392,15 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
if nofchainlookups == 1 then
local chainlookupname = chainlookups[1]
local chainlookup = lookuptable[chainlookupname]
- local cp = chainprocs[chainlookup.type]
- if cp then
- start, done = cp(start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
- else
- logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ if chainlookup then
+ local cp = chainprocs[chainlookup.type]
+ if cp then
+ start, done = cp(start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence)
+ else
+ logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ end
+ else -- shouldn't happen
+ logprocess("%s is not yet supported",cref(kind,chainname,chainlookupname))
end
else
local i = 1
@@ -9598,8 +10422,8 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
end
end
local chainlookupname = chainlookups[i]
- local chainlookup = lookuptable[chainlookupname]
- local cp = chainmores[chainlookup.type]
+ local chainlookup = lookuptable[chainlookupname] -- can be false (n matches, <n replacement)
+ local cp = chainlookup and chainmores[chainlookup.type]
if cp then
local ok, n
start, ok, n = cp(start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence)
@@ -9612,7 +10436,8 @@ local function normal_handle_contextchain(start,kind,chainname,contexts,sequence
i = i + 1
end
else
- logprocess("%s: multiple subchains for %s are not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type)
+ -- is valid
+ -- logprocess("%s: multiple subchains for %s are not yet supported",cref(kind,chainname,chainlookupname),chainlookup and chainlookup.type or "?")
i = i + 1
end
start = start.next
@@ -9722,7 +10547,7 @@ local function initialize(sequence,script,language,enabled)
if valid then
local languages = scripts[script] or scripts[wildcard]
if languages and (languages[language] or languages[wildcard]) then
- return { valid, special_attributes[kind] or false, sequence.chain or 0, kind }
+ return { valid, special_attributes[kind] or false, sequence.chain or 0, kind, sequence }
end
end
end
@@ -9730,7 +10555,7 @@ local function initialize(sequence,script,language,enabled)
return false
end
-function otf.dataset(ftfmdata,sequences,font) -- generic variant, overloaded in context
+function otf.dataset(tfmdata,sequences,font) -- generic variant, overloaded in context
local shared = tfmdata.shared
local properties = tfmdata.properties
local language = properties.language or "dflt"
@@ -9759,6 +10584,22 @@ function otf.dataset(ftfmdata,sequences,font) -- generic variant, overloaded in
return rl
end
+-- elseif id == glue_code then
+-- if p[5] then -- chain
+-- local pc = pp[32]
+-- if pc then
+-- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
+-- if ok then
+-- done = true
+-- end
+-- if start then start = start.next end
+-- else
+-- start = start.next
+-- end
+-- else
+-- start = start.next
+-- end
+
local function featuresprocessor(head,font,attr)
local lookuphash = lookuphashes[font] -- we can also check sequences here
@@ -9788,67 +10629,147 @@ local function featuresprocessor(head,font,attr)
local done = false
local datasets = otf.dataset(tfmdata,sequences,font,attr)
+ local dirstack = { } -- could move outside function
+
+ -- We could work on sub start-stop ranges instead but I wonder if there is that
+ -- much speed gain (experiments showed that it made not much sense) and we need
+ -- to keep track of directions anyway. Also at some point I want to play with
+ -- font interactions and then we do need the full sweeps.
+
for s=1,#sequences do
- local pardir, txtdir, success = 0, { }, false -- we could reuse txtdir and use a top pointer
- local sequence = sequences[s]
- local dataset = datasets[s] -- cache
- featurevalue = dataset and dataset[1] -- todo: pass to function instead of using a global
- if featurevalue then
- local attribute, chain, typ, subtables = dataset[2], dataset[3], sequence.type, sequence.subtables
---~ print(typ)
---~ table.print(table.keys(sequence))
- if chain < 0 then
- -- this is a limited case, no special treatments like 'init' etc
- local handler = handlers[typ]
- -- we need to get rid of this slide !
- local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
- while start do
- local id = start.id
- if id == glyph_code then
- if start.subtype<256 and start.font == font then
- local a = has_attribute(start,0)
- if a then
- a = a == attr
- else
- a = true
- end
- if a then
- for i=1,#subtables do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[start.char]
- if lookupmatch then
- start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
- if success then
- break
+ local dataset = datasets[s]
+ if dataset then
+ featurevalue = dataset[1] -- todo: pass to function instead of using a global
+ if featurevalue then
+ local sequence = sequences[s] -- also dataset[5]
+ local rlparmode = 0
+ local topstack = 0
+ local success = false
+ local attribute = dataset[2]
+ local chain = dataset[3] -- sequence.chain or 0
+ local typ = sequence.type
+ local subtables = sequence.subtables
+ if chain < 0 then
+ -- this is a limited case, no special treatments like 'init' etc
+ local handler = handlers[typ]
+ -- we need to get rid of this slide! probably no longer needed in latest luatex
+ local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo
+ while start do
+ local id = start.id
+ if id == glyph_code then
+ if start.subtype<256 and start.font == font then
+ local a = has_attribute(start,0)
+ if a then
+ a = a == attr
+ else
+ a = true
+ end
+ if a then
+ for i=1,#subtables do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ start, success = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ if success then
+ break
+ end
end
+ else
+ report_missing_cache(typ,lookupname)
end
- else
- report_missing_cache(typ,lookupname)
end
+ if start then start = start.prev end
+ else
+ start = start.prev
end
- if start then start = start.prev end
else
start = start.prev
end
else
start = start.prev
end
- else
- start = start.prev
end
- end
- else
- local handler = handlers[typ]
- local ns = #subtables
- local start = head -- local ?
- rlmode = 0 -- to be checked ?
- if ns == 1 then
- local lookupname = subtables[1]
- local lookupcache = lookuphash[lookupname]
- if not lookupcache then
- report_missing_cache(typ,lookupname)
+ else
+ local handler = handlers[typ]
+ local ns = #subtables
+ local start = head -- local ?
+ rlmode = 0 -- to be checked ?
+ if ns == 1 then -- happens often
+ local lookupname = subtables[1]
+ local lookupcache = lookuphash[lookupname]
+ if not lookupcache then -- also check for empty cache
+ report_missing_cache(typ,lookupname)
+ else
+ while start do
+ local id = start.id
+ if id == glyph_code then
+ if start.subtype<256 and start.font == font then
+ local a = has_attribute(start,0)
+ if a then
+ a = (a == attr) and (not attribute or has_attribute(start,state,attribute))
+ else
+ a = not attribute or has_attribute(start,state,attribute)
+ end
+ if a then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ -- sequence kan weg
+ local ok
+ start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
+ if ok then
+ success = true
+ end
+ end
+ if start then start = start.next end
+ else
+ start = start.next
+ end
+ else
+ start = start.next
+ end
+ elseif id == whatsit_code then -- will be function
+ local subtype = start.subtype
+ if subtype == dir_code then
+ local dir = start.dir
+ if dir == "+TRT" or dir == "+TLT" then
+ topstack = topstack + 1
+ dirstack[topstack] = dir
+ elseif dir == "-TRT" or dir == "-TLT" then
+ topstack = topstack - 1
+ end
+ local newdir = dirstack[topstack]
+ if newdir == "+TRT" then
+ rlmode = -1
+ elseif newdir == "+TLT" then
+ rlmode = 1
+ else
+ rlmode = rlparmode
+ end
+ if trace_directions then
+ report_process("directions after txtdir %s: txtdir=%s:%s, parmode=%s, txtmode=%s",dir,topstack,newdir or "unset",rlparmode,rlmode)
+ end
+ elseif subtype == localpar_code then
+ local dir = start.dir
+ if dir == "TRT" then
+ rlparmode = -1
+ elseif dir == "TLT" then
+ rlparmode = 1
+ else
+ rlparmode = 0
+ end
+ rlmode = rlparmode
+ if trace_directions then
+ report_process("directions after pardir %s: parmode=%s, txtmode=%s",dir,rlparmode,rlmode)
+ end
+ end
+ start = start.next
+ else
+ start = start.next
+ end
+ end
+ end
else
while start do
local id = start.id
@@ -9861,13 +10782,22 @@ local function featuresprocessor(head,font,attr)
a = not attribute or has_attribute(start,state,attribute)
end
if a then
- local lookupmatch = lookupcache[start.char]
- if lookupmatch then
- -- sequence kan weg
- local ok
- start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
- if ok then
- success = true
+ for i=1,ns do
+ local lookupname = subtables[i]
+ local lookupcache = lookuphash[lookupname]
+ if lookupcache then
+ local lookupmatch = lookupcache[start.char]
+ if lookupmatch then
+ -- we could move all code inline but that makes things even more unreadable
+ local ok
+ start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
+ if ok then
+ success = true
+ break
+ end
+ end
+ else
+ report_missing_cache(typ,lookupname)
end
end
if start then start = start.next end
@@ -9877,54 +10807,39 @@ local function featuresprocessor(head,font,attr)
else
start = start.next
end
- -- elseif id == glue_code then
- -- if p[5] then -- chain
- -- local pc = pp[32]
- -- if pc then
- -- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
- -- if ok then
- -- done = true
- -- end
- -- if start then start = start.next end
- -- else
- -- start = start.next
- -- end
- -- else
- -- start = start.next
- -- end
elseif id == whatsit_code then
local subtype = start.subtype
if subtype == dir_code then
local dir = start.dir
if dir == "+TRT" or dir == "+TLT" then
- insert(txtdir,dir)
+ topstack = topstack + 1
+ dirstack[topstack] = dir
elseif dir == "-TRT" or dir == "-TLT" then
- remove(txtdir)
+ topstack = topstack - 1
end
- local d = txtdir[#txtdir]
- if d == "+TRT" then
+ local newdir = dirstack[topstack]
+ if newdir == "+TRT" then
rlmode = -1
- elseif d == "+TLT" then
+ elseif newdir == "+TLT" then
rlmode = 1
else
- rlmode = pardir
+ rlmode = rlparmode
end
if trace_directions then
- report_process("directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ report_process("directions after txtdir %s: txtdir=%s:%s, parmode=%s, txtmode=%s",dir,topstack,newdir or "unset",rlparmode,rlmode)
end
elseif subtype == localpar_code then
local dir = start.dir
if dir == "TRT" then
- pardir = -1
+ rlparmode = -1
elseif dir == "TLT" then
- pardir = 1
+ rlparmode = 1
else
- pardir = 0
+ rlparmode = 0
end
- rlmode = pardir
- --~ txtdir = { }
+ rlmode = rlparmode
if trace_directions then
- report_process("directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
+ report_process("directions after pardir %s: parmode=%s, txtmode=%s",dir,rlparmode,rlmode)
end
end
start = start.next
@@ -9933,105 +10848,13 @@ local function featuresprocessor(head,font,attr)
end
end
end
- else
- while start do
- local id = start.id
- if id == glyph_code then
- if start.subtype<256 and start.font == font then
- local a = has_attribute(start,0)
- if a then
- a = (a == attr) and (not attribute or has_attribute(start,state,attribute))
- else
- a = not attribute or has_attribute(start,state,attribute)
- end
- if a then
- for i=1,ns do
- local lookupname = subtables[i]
- local lookupcache = lookuphash[lookupname]
- if lookupcache then
- local lookupmatch = lookupcache[start.char]
- if lookupmatch then
- -- we could move all code inline but that makes things even more unreadable
- local ok
- start, ok = handler(start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
- if ok then
- success = true
- break
- end
- end
- else
- report_missing_cache(typ,lookupname)
- end
- end
- if start then start = start.next end
- else
- start = start.next
- end
- else
- start = start.next
- end
- -- elseif id == glue_code then
- -- if p[5] then -- chain
- -- local pc = pp[32]
- -- if pc then
- -- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4])
- -- if ok then
- -- done = true
- -- end
- -- if start then start = start.next end
- -- else
- -- start = start.next
- -- end
- -- else
- -- start = start.next
- -- end
- elseif id == whatsit_code then
- local subtype = start.subtype
- if subtype == dir_code then
- local dir = start.dir
- if dir == "+TRT" or dir == "+TLT" then
- insert(txtdir,dir)
- elseif dir == "-TRT" or dir == "-TLT" then
- remove(txtdir)
- end
- local d = txtdir[#txtdir]
- if d == "+TRT" then
- rlmode = -1
- elseif d == "+TLT" then
- rlmode = 1
- else
- rlmode = pardir
- end
- if trace_directions then
- report_process("directions after textdir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
- end
- elseif subtype == localpar_code then
- local dir = start.dir
- if dir == "TRT" then
- pardir = -1
- elseif dir == "TLT" then
- pardir = 1
- else
- pardir = 0
- end
- rlmode = pardir
- --~ txtdir = { }
- if trace_directions then
- report_process("directions after pardir %s: pardir=%s, txtdir=%s:%s, rlmode=%s",dir,pardir,#txtdir,txtdir[#txtdir] or "unset",rlmode)
- end
- end
- start = start.next
- else
- start = start.next
- end
- end
end
- end
- if success then
- done = true
- end
- if trace_steps then -- ?
- registerstep(head)
+ if success then
+ done = true
+ end
+ if trace_steps then -- ?
+ registerstep(head)
+ end
end
end
end
@@ -10110,55 +10933,59 @@ local function prepare_lookups(tfmdata)
local description = descriptions[unicode]
- local lookups = description.slookups
- if lookups then
- for lookupname, lookupdata in next, lookups do
- action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash)
+ if description then
+
+ local lookups = description.slookups
+ if lookups then
+ for lookupname, lookupdata in next, lookups do
+ action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash)
+ end
end
- end
- local lookups = description.mlookups
- if lookups then
- for lookupname, lookuplist in next, lookups do
- local lookuptype = lookuptypes[lookupname]
- for l=1,#lookuplist do
- local lookupdata = lookuplist[l]
- action[lookuptype](lookupdata,lookupname,unicode,lookuphash)
+ local lookups = description.mlookups
+ if lookups then
+ for lookupname, lookuplist in next, lookups do
+ local lookuptype = lookuptypes[lookupname]
+ for l=1,#lookuplist do
+ local lookupdata = lookuplist[l]
+ action[lookuptype](lookupdata,lookupname,unicode,lookuphash)
+ end
end
end
- end
- local list = description.kerns
- if list then
- for lookup, krn in next, list do -- ref to glyph, saves lookup
- local target = lookuphash[lookup]
- if target then
- target[unicode] = krn
- else
- lookuphash[lookup] = { [unicode] = krn }
+ local list = description.kerns
+ if list then
+ for lookup, krn in next, list do -- ref to glyph, saves lookup
+ local target = lookuphash[lookup]
+ if target then
+ target[unicode] = krn
+ else
+ lookuphash[lookup] = { [unicode] = krn }
+ end
end
end
- end
- local list = description.anchors
- if list then
- for typ, anchors in next, list do -- types
- if typ == "mark" or typ == "cexit" then -- or entry?
- for name, anchor in next, anchors do
- local lookups = anchor_to_lookup[name]
- if lookups then
- for lookup, _ in next, lookups do
- local target = lookuphash[lookup]
- if target then
- target[unicode] = anchors
- else
- lookuphash[lookup] = { [unicode] = anchors }
+ local list = description.anchors
+ if list then
+ for typ, anchors in next, list do -- types
+ if typ == "mark" or typ == "cexit" then -- or entry?
+ for name, anchor in next, anchors do
+ local lookups = anchor_to_lookup[name]
+ if lookups then
+ for lookup, _ in next, lookups do
+ local target = lookuphash[lookup]
+ if target then
+ target[unicode] = anchors
+ else
+ lookuphash[lookup] = { [unicode] = anchors }
+ end
end
end
end
end
end
end
+
end
end
@@ -10340,7 +11167,7 @@ end
--~ end
local valid = {
- coverage = { chainsub = true, chainpos = true },
+ coverage = { chainsub = true, chainpos = true, contextsub = true },
reversecoverage = { reversesub = true },
glyphs = { chainsub = true, chainpos = true },
}
@@ -11250,7 +12077,7 @@ registerotffeature {
methods.latn = analyzers.setstate
--- this info eventually will go into char-def adn we will have a state
+-- this info eventually will go into char-def and we will have a state
-- table for generic then
local zwnj = 0x200C
@@ -11280,6 +12107,12 @@ local isol_fina = {
[0x076C] = true, [0x0771] = true, [0x0773] = true, [0x0774] = true,
[0x0778] = true, [0x0779] = true, [0xFEF5] = true, [0xFEF7] = true,
[0xFEF9] = true, [0xFEFB] = true,
+
+ -- syriac
+
+ [0x0710] = true, [0x0715] = true, [0x0716] = true, [0x0717] = true,
+ [0x0718] = true, [0x0719] = true, [0x0728] = true, [0x072A] = true,
+ [0x072C] = true, [0x071E] = true,
}
local isol_fina_medi_init = {
@@ -11317,10 +12150,19 @@ local isol_fina_medi_init = {
[0x0772] = true, [0x0775] = true, [0x0776] = true, [0x0777] = true,
[0x077A] = true, [0x077B] = true, [0x077C] = true, [0x077D] = true,
[0x077E] = true, [0x077F] = true, [zwj] = true,
+
+ -- syriac
+
+ [0x0712] = true, [0x0713] = true, [0x0714] = true, [0x071A] = true,
+ [0x071B] = true, [0x071C] = true, [0x071D] = true, [0x071F] = true,
+ [0x0720] = true, [0x0721] = true, [0x0722] = true, [0x0723] = true,
+ [0x0725] = true, [0x0726] = true, [0x0727] = true, [0x0729] = true,
+ [0x072B] = true, [0x0724] = true, [0x0706] = true, [0x0707] = true,
}
local arab_warned = { }
+
-- todo: gref
local function warning(current,what)
@@ -11438,6 +12280,8 @@ function methods.arab(head,font,attr) -- maybe make a special version with no tr
return head, done
end
+methods.syrc = methods.arab
+
directives.register("otf.analyze.useunicodemarks",function(v)
analyzers.useunicodemarks = v
end)
@@ -11605,7 +12449,7 @@ function definers.registersplit(symbol,action,verbosename)
end
end
-function definers.makespecification(specification, lookup, name, sub, method, detail, size)
+function definers.makespecification(specification,lookup,name,sub,method,detail,size)
size = size or 655360
if trace_defining then
report_defining("%s -> lookup: %s, name: %s, sub: %s, method: %s, detail: %s",
@@ -11656,13 +12500,14 @@ end
function resolvers.name(specification)
local resolve = fonts.names.resolve
if resolve then
- local resolved, sub = fonts.names.resolve(specification.name,specification.sub)
- specification.resolved, specification.sub = resolved, sub
+ local resolved, sub = resolve(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
if resolved then
+ specification.resolved = resolved
+ specification.sub = sub
local suffix = file.suffix(resolved)
if fonts.formats[suffix] then
specification.forced = suffix
- specification.name = file.removesuffix(resolved)
+ specification.name = file.removesuffix(resolved)
else
specification.name = resolved
end
@@ -11675,10 +12520,12 @@ end
function resolvers.spec(specification)
local resolvespec = fonts.names.resolvespec
if resolvespec then
- specification.resolved, specification.sub = fonts.names.resolvespec(specification.name,specification.sub)
- if specification.resolved then
- specification.forced = file.extname(specification.resolved)
- specification.name = file.removesuffix(specification.resolved)
+ local resolved, sub = resolvespec(specification.name,specification.sub,specification) -- we pass specification for overloaded versions
+ if resolved then
+ specification.resolved = resolved
+ specification.sub = sub
+ specification.forced = file.extname(resolved)
+ specification.name = file.removesuffix(resolved)
end
else
resolvers.name(specification)
@@ -11697,17 +12544,6 @@ function definers.resolve(specification)
else
specification.forced = specification.forced
end
- -- for the moment here (goodies set outside features)
- local goodies = specification.goodies
- if goodies and goodies ~= "" then
- local normal = specification.features.normal
- if not normal then
- specification.features.normal = { goodies = goodies }
- elseif not normal.goodies then
- normal.goodies = goodies
- end
- end
- --
specification.hash = lower(specification.name .. ' @ ' .. constructors.hashfeatures(specification))
if specification.sub and specification.sub ~= "" then
specification.hash = specification.sub .. ' @ ' .. specification.hash
@@ -11731,25 +12567,43 @@ features (esp in virtual fonts) so let's not do that now.</p>
specification yet.</p>
--ldx]]--
--- not in context, at least not now:
---
+-- very experimental:
+
+function definers.applypostprocessors(tfmdata)
+ local postprocessors = tfmdata.postprocessors
+ if postprocessors then
+ for i=1,#postprocessors do
+ local extrahash = postprocessors[i](tfmdata) -- after scaling etc
+ if type(extrahash) == "string" and extrahash ~= "" then
+ -- e.g. a reencoding needs this
+ extrahash = gsub(lower(extrahash),"[^a-z]","-")
+ tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash)
+ end
+ end
+ end
+ return tfmdata
+end
+
-- function definers.applypostprocessors(tfmdata)
--- local postprocessors = tfmdata.postprocessors
--- if postprocessors then
--- for i=1,#postprocessors do
--- local extrahash = postprocessors[i](tfmdata) -- after scaling etc
--- if type(extrahash) == "string" and extrahash ~= "" then
--- -- e.g. a reencoding needs this
--- extrahash = gsub(lower(extrahash),"[^a-z]","-")
--- tfmdata.properties.fullname = format("%s-%s",tfmdata.properties.fullname,extrahash)
--- end
--- end
--- end
-- return tfmdata
-- end
-function definers.applypostprocessors(tfmdata)
- return tfmdata
+local function checkembedding(tfmdata)
+ local properties = tfmdata.properties
+ local embedding
+ if directive_embedall then
+ embedding = "full"
+ elseif properties and properties.filename and constructors.dontembed[properties.filename] then
+ embedding = "no"
+ else
+ embedding = "subset"
+ end
+ if properties then
+ properties.embedding = embedding
+ else
+ tfmdata.properties = { embedding = embedding }
+ end
+ tfmdata.embedding = embedding
end
function definers.loadfont(specification)
@@ -11781,21 +12635,8 @@ function definers.loadfont(specification)
end
end
if tfmdata then
- local properties = tfmdata.properties
- local embedding
- if directive_embedall then
- embedding = "full"
- elseif properties.filename and constructors.dontembed[properties.filename] then
- embedding = "no"
- else
- embedding = "subset"
- end
- if properties then
- properties.embedding = embedding
- else
- tfmdata.properties = { embedding = embedding }
- end
tfmdata = definers.applypostprocessors(tfmdata)
+ checkembedding(tfmdata) -- todo: general postprocessor
loadedfonts[hash] = tfmdata
designsizes[specification.hash] = tfmdata.parameters.designsize
end
@@ -11881,14 +12722,25 @@ function definers.read(specification,size,id) -- id can be optional, name can al
specification = definers.resolve(specification)
local hash = constructors.hashinstance(specification)
local tfmdata = definers.registered(hash) -- id
- if not tfmdata then
+ if tfmdata then
+ if trace_defining then
+ report_defining("already hashed: %s",hash)
+ end
+ else
tfmdata = definers.loadfont(specification) -- can be overloaded
if tfmdata then
---~ constructors.checkvirtualid(tfmdata) -- interferes
+ if trace_defining then
+ report_defining("loaded and hashed: %s",hash)
+ end
+ --~ constructors.checkvirtualid(tfmdata) -- interferes
tfmdata.properties.hash = hash
if id then
definers.register(tfmdata,id)
end
+ else
+ if trace_defining then
+ report_defining("not loaded and hashed: %s",hash)
+ end
end
end
lastdefined = tfmdata or id -- todo ! ! ! ! !
@@ -11898,7 +12750,7 @@ function definers.read(specification,size,id) -- id can be optional, name can al
local properties = tfmdata.properties or { }
local parameters = tfmdata.parameters or { }
report_defining("using %s font with id %s, name:%s size:%s bytes:%s encoding:%s fullname:%s filename:%s",
- properties.type or "unknown",
+ properties.format or "unknown",
id or "?",
properties.name or "?",
parameters.size or "default",
@@ -12054,7 +12906,7 @@ local function initializeitlc(tfmdata,value)
d.italic = it
end
end
- tfmdata.properties.italic_correction = true
+ tfmdata.properties.hasitalics = true
end
end
end
@@ -12079,7 +12931,7 @@ local function initializeslant(tfmdata,value)
elseif value < -1 then
value = -1
end
- tfmdata.parameters.slant_factor = value
+ tfmdata.parameters.slantfactor = value
end
otffeatures.register {
@@ -12100,7 +12952,7 @@ local function initializeextend(tfmdata,value)
elseif value < -10 then
value = -10
end
- tfmdata.parameters.extend_factor = value
+ tfmdata.parameters.extendfactor = value
end
otffeatures.register {
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-syn.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-syn.lua
index 36a74d0f497..36a74d0f497 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-syn.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-syn.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts-tfm.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-tfm.lua
index b9bb1bd0f28..b9bb1bd0f28 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts-tfm.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-tfm.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.lua
index 23d33f26b8f..f5045a4e32a 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.lua
@@ -7,9 +7,20 @@ if not modules then modules = { } end modules ['luatex-fonts'] = {
}
-- The following code isolates the generic ConTeXt code from already
--- defined or to be defined namespaces.
-
--- todo: all global namespaces in called modules will get local shortcuts
+-- defined or to be defined namespaces. This is the reference loader
+-- for plain, but the generic code is also used in luaotfload (which
+-- is is a file meant for latex) and that is maintained by Khaled
+-- Hosny. We do our best to keep the interface as clean as possible.
+--
+-- The code base is rather stable now, especially if you stay away from
+-- the non generic code. All relevant data is organized in tables within
+-- the main table of a font instance. There are a few places where in
+-- context other code is plugged in, but this does not affect the core
+-- code. Users can (given that their macro package provides this option)
+-- access the font data (characters, descriptions, properties, parameters,
+-- etc) of this main table.
+--
+-- Todo: all global namespaces in called modules will get local shortcuts.
utf = unicode.utf8
@@ -122,10 +133,10 @@ else
-- version 1.0 there will be an official api defined.
loadmodule('l-string.lua')
+ loadmodule('l-table.lua')
loadmodule('l-lpeg.lua')
loadmodule('l-boolean.lua')
loadmodule('l-math.lua')
- loadmodule('l-table.lua')
loadmodule('l-file.lua')
loadmodule('l-io.lua')
diff --git a/Master/texmf-dist/tex/generic/context/luatex-fonts.tex b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.tex
index 8ccc9f3d566..a7c8bc2b8fd 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-fonts.tex
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts.tex
@@ -4,7 +4,7 @@
%D title=\LUATEX\ Support Macros,
%D subtitle=Generic \OPENTYPE\ Font Handler,
%D author=Hans Hagen,
-%D copyright=see context related readme files]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%D \subject{Welcome}
%D
diff --git a/Master/texmf-dist/tex/generic/context/luatex-mplib.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-mplib.lua
index c6628acb3b8..c6628acb3b8 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-mplib.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-mplib.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-mplib.tex b/Master/texmf-dist/tex/generic/context/luatex/luatex-mplib.tex
index 69195864670..ef6dfff958b 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-mplib.tex
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-mplib.tex
@@ -4,7 +4,7 @@
%D title=\LUATEX\ Support Macros,
%D subtitle=\METAPOST\ to \PDF\ conversion,
%D author=Taco Hoekwater \& Hans Hagen,
-%D copyright=see context related readme files]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%D This is the companion to the \LUA\ module \type {supp-mpl.lua}. Further
%D embedding is up to others. A simple example of usage in plain \TEX\ is:
diff --git a/Master/texmf-dist/tex/generic/context/luatex/luatex-plain.tex b/Master/texmf-dist/tex/generic/context/luatex/luatex-plain.tex
new file mode 100644
index 00000000000..e47ad58ad9a
--- /dev/null
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-plain.tex
@@ -0,0 +1,25 @@
+%D \module
+%D [ file=luatex-plain,
+%D version=2009.12.01,
+%D title=\LUATEX\ Macros,
+%D subtitle=Plain Format,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+
+\input plain
+
+\directlua {tex.enableprimitives('', tex.extraprimitives())}
+
+\pdfoutput=1
+
+\everyjob \expandafter {%
+ \the\everyjob
+ \input luatex-basics\relax
+ \input luatex-fonts\relax
+ \input luatex-mplib\relax
+}
+
+\edef\fmtversion{\fmtversion+luatex}
+
+\dump
diff --git a/Master/texmf-dist/tex/generic/context/luatex-preprocessor-test.tex b/Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor-test.tex
index 857b28f831b..857b28f831b 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-preprocessor-test.tex
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor-test.tex
diff --git a/Master/texmf-dist/tex/generic/context/luatex-preprocessor.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor.lua
index 8faa0b47e69..8faa0b47e69 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-preprocessor.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor.lua
diff --git a/Master/texmf-dist/tex/generic/context/luatex-preprocessor.tex b/Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor.tex
index fe4872d6101..03b483f4185 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-preprocessor.tex
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-preprocessor.tex
@@ -4,7 +4,7 @@
%D title=\LUATEX\ Support Macros,
%D subtitle=Generic Preprocessor,
%D author=Hans Hagen,
-%D copyright=public domain]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
\directlua{dofile(kpse.find_file('luatex-preprocessor.lua'))}
diff --git a/Master/texmf-dist/tex/generic/context/luatex-test.tex b/Master/texmf-dist/tex/generic/context/luatex/luatex-test.tex
index 1c3aeb1b689..3020b5594cc 100644
--- a/Master/texmf-dist/tex/generic/context/luatex-test.tex
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-test.tex
@@ -5,13 +5,15 @@
%D subtitle=Simple Test File,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright=public domain]
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%D See \type {luatex-plain.tex} (or on my machine \type {luatex.tex}
%D for how to make a format.
\pdfoutput=1
+% \directlua{generic_context.caches.compilemethod = "both" } % none luac dump both
+
\font\testa=file:lmroman10-regular at 12pt \testa \input tufte \par
\font\testb=file:lmroman12-regular:+liga; at 24pt \testb effe flink fietsen \par
\font\testc=file:lmroman12-regular:mode=node;+liga; at 24pt \testc effe flink fietsen \par
diff --git a/Master/texmf-dist/tex/generic/context/m-metapo.tex b/Master/texmf-dist/tex/generic/context/m-metapo.tex
deleted file mode 100644
index 8680f69c6b2..00000000000
--- a/Master/texmf-dist/tex/generic/context/m-metapo.tex
+++ /dev/null
@@ -1,89 +0,0 @@
-%D \module
-%D [ file=m-metapo,
-%D version=1999.03.26,
-%D title=\LATEX\ Modules,
-%D subtitle=\METAPOST\ Inclusion,
-%D author=Hans Hagen,
-%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
-%C
-%C This module is part of the \CONTEXT\ distribution and is
-%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
-%C details.
-
-%D We quit when \CONTEXT\ is found and use some deep down
-%D macro to trigger this:
-
-\ifx\undefined\dodoplaceexternalfigure \else \expandafter \endinput \fi
-
-%D \macros
-%D {includeMPgraphics}
-%D
-%D This rather small \LATEX\ module is dedicated to David
-%D Arnold. It takes care of including the fonts used in
-%D \METAPOST\ graphics in the file. This hack is needed when
-%D one uses another \DVI\ driver than \DVIPS. This module
-%D falls back on the generic \CONTEXT\ support module:
-
-\ifx\undefined\includeMPfonts \input supp-mps.tex \relax \fi
-
-%D Instead of using \type {\includegraphics}, one should use its
-%D little brother \type {\includeMPgraphics}. This macro takes
-%D the same arguments.
-
-\def\includeMPgraphics#1#%
- {\leavevmode\vbox\bgroup\hbox\bgroup
- \def\includeMPgraphics##1%
- {\includeMPfonts{##1}%
- \includegraphics#1{##1}%
- \egroup\egroup}%
- \includeMPgraphics}
-
-%D An example of using this module is given below:
-%D
-%D \starttyping
-%D \documentclass[10pt]{article}
-%D
-%D \usepackage{graphicx}
-%D \usepackage{m-metapo}
-%D
-%D \begin{document}
-%D \includeMPgraphics{somefile.1}
-%D \includeMPgraphics[angle=90]{somefile.2}
-%D \end{document}
-%D \stoptyping
-%D
-%D This module needs \type {supp-mps} and \type {supp-mis},
-%D that both are present in the \CONTEXT\ path.
-%D
-%D Please do not forget to say \type {prologues:=1} at the
-%D top of the metapost file!
-%D
-%D For non \LATEX\ (and \CONTEXT) users we provide an
-%D alternative inclusion macro. This one has no optional
-%D arguments.
-
-\ifx\includegraphics\undefined
-
- \ifx\undefined\dogetEPSboundingbox \input supp-eps.tex \relax \fi
-
- \def\includeMPgraphics#1%
- {\hbox\bgroup
- \includeMPfonts{#1}%
- \dogetEPSboundingbox{#1}{\dimen2}{\dimen4}{\dimen6}{\dimen8}%
- \vbox to \dimen8
- {\forgetall
- \hsize\dimen6
- \vfill
- \hbox to \hsize
- {\special
- {PSfile="#1"\space
- llx=\EPSllx\space
- lly=\EPSlly\space
- urx=\EPSurx\space
- ury=\EPSury\space}}}%
- \egroup}
-
-\fi
-
-\endinput
diff --git a/Master/texmf-dist/tex/generic/context/mptopdf.tex b/Master/texmf-dist/tex/generic/context/mptopdf/mptopdf.tex
index a0ac34a42b3..3efe573924a 100644
--- a/Master/texmf-dist/tex/generic/context/mptopdf.tex
+++ b/Master/texmf-dist/tex/generic/context/mptopdf/mptopdf.tex
@@ -5,7 +5,7 @@
%D subtitle=conversion to \PDF,
%D author=Hans Hagen,
%D date=\currentdate,
-%D copyright={PRAGMA / Hans Hagen \& Ton Otten}]
+%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
diff --git a/Master/texmf-dist/tex/generic/context/m-ch-de.tex b/Master/texmf-dist/tex/generic/context/ppchtex/m-ch-de.tex
index 467cdc67044..467cdc67044 100644
--- a/Master/texmf-dist/tex/generic/context/m-ch-de.tex
+++ b/Master/texmf-dist/tex/generic/context/ppchtex/m-ch-de.tex
diff --git a/Master/texmf-dist/tex/generic/context/m-ch-en.tex b/Master/texmf-dist/tex/generic/context/ppchtex/m-ch-en.tex
index 6bd4353199b..6bd4353199b 100644
--- a/Master/texmf-dist/tex/generic/context/m-ch-en.tex
+++ b/Master/texmf-dist/tex/generic/context/ppchtex/m-ch-en.tex
diff --git a/Master/texmf-dist/tex/generic/context/m-ch-nl.tex b/Master/texmf-dist/tex/generic/context/ppchtex/m-ch-nl.tex
index c9d77733ac5..c9d77733ac5 100644
--- a/Master/texmf-dist/tex/generic/context/m-ch-nl.tex
+++ b/Master/texmf-dist/tex/generic/context/ppchtex/m-ch-nl.tex
diff --git a/Master/texmf-dist/tex/generic/context/ppchtex.noc b/Master/texmf-dist/tex/generic/context/ppchtex/ppchtex.noc
index 99d073255cb..99d073255cb 100644
--- a/Master/texmf-dist/tex/generic/context/ppchtex.noc
+++ b/Master/texmf-dist/tex/generic/context/ppchtex/ppchtex.noc
diff --git a/Master/texmf-dist/tex/latex/context/m-metapo.sty b/Master/texmf-dist/tex/latex/context/m-metapo.sty
deleted file mode 100644
index 2d568df9660..00000000000
--- a/Master/texmf-dist/tex/latex/context/m-metapo.sty
+++ /dev/null
@@ -1,5 +0,0 @@
-\ProvidesPackage{m-metapo}[2004/07/30 package wrapper for m-metapo.tex]
-
-\input{m-metapo.tex}
-
-\endinput \ No newline at end of file
diff --git a/Master/texmf-dist/tex/latex/context/m-ch-de.sty b/Master/texmf-dist/tex/latex/context/ppchtex/m-ch-de.sty
index d35f8cf2d25..d35f8cf2d25 100644
--- a/Master/texmf-dist/tex/latex/context/m-ch-de.sty
+++ b/Master/texmf-dist/tex/latex/context/ppchtex/m-ch-de.sty
diff --git a/Master/texmf-dist/tex/latex/context/m-ch-en.sty b/Master/texmf-dist/tex/latex/context/ppchtex/m-ch-en.sty
index e93a49867e2..e93a49867e2 100644
--- a/Master/texmf-dist/tex/latex/context/m-ch-en.sty
+++ b/Master/texmf-dist/tex/latex/context/ppchtex/m-ch-en.sty
diff --git a/Master/texmf-dist/tex/latex/context/m-ch-nl.sty b/Master/texmf-dist/tex/latex/context/ppchtex/m-ch-nl.sty
index 6e2b8d43d9f..6e2b8d43d9f 100644
--- a/Master/texmf-dist/tex/latex/context/m-ch-nl.sty
+++ b/Master/texmf-dist/tex/latex/context/ppchtex/m-ch-nl.sty
diff --git a/Master/texmf-dist/tex/latex/context/m-pictex.sty b/Master/texmf-dist/tex/latex/context/ppchtex/m-pictex.sty
index 18630f2ccbb..18630f2ccbb 100644
--- a/Master/texmf-dist/tex/latex/context/m-pictex.sty
+++ b/Master/texmf-dist/tex/latex/context/ppchtex/m-pictex.sty
diff --git a/Master/texmf/web2c/texmfcnf.lua b/Master/texmf/web2c/texmfcnf.lua
index 2b11b4e4ede..82db966b0a4 100644
--- a/Master/texmf/web2c/texmfcnf.lua
+++ b/Master/texmf/web2c/texmfcnf.lua
@@ -45,13 +45,13 @@ return {
-- only used for FONTCONFIG_PATH & TEXMFCACHE in TeX Live
TEXMFSYSVAR = "selfautoparent:texmf-var",
- TEXMFVAR = "home:.texlive2011/texmf-var",
+ TEXMFVAR = "home:.texlive2012/texmf-var",
-- We have only one cache path but there can be more. The first writable one
-- will be chosen but there can be more readable paths.
TEXMFCACHE = "$TEXMFSYSVAR;$TEXMFVAR",
- TEXMFCONFIG = "home:.texlive2011/texmf-config",
+ TEXMFCONFIG = "home:.texlive2012/texmf-config",
-- I don't like this texmf under home and texmf-home would make more
-- sense. One never knows what installers put under texmf anywhere and